Skip to contentSkip to conversation

radeon drm-next patches

PATCH In review [email protected] 10 participants 142 messages Jun 26, 2013 – Jun 29, 2013 Page 3 of 3

Subsystems (3)
lore
Share & tools
lore
Reviewed-by on v1 80/165
#94 lore raw

Re: [PATCH 080/165] drm/radeon/kms: add dpm support for sumo asics

In reply to [email protected]
Quoted 11 lines · On Wed, Jun 26, 2013 at 09:22:40AM -0400, [email protected] wrote:

From: Alex Deucher <[email protected]>

This adds dpm support for sumo asics. This includes:
- clockgating
- powergating
- dynamic engine clock scaling
- dynamic voltage scaling

set radeon.dpm=1 to enable it.

Quoted 641 lines
---
 drivers/gpu/drm/radeon/Makefile      |    2 +-
 drivers/gpu/drm/radeon/radeon_asic.c |   12 +
 drivers/gpu/drm/radeon/radeon_asic.h |   11 +
 drivers/gpu/drm/radeon/radeon_pm.c   |    3 +
 drivers/gpu/drm/radeon/sumo_dpm.c    | 1677 ++++++++++++++++++++++++++++++++++
 drivers/gpu/drm/radeon/sumo_dpm.h    |  199 ++++
 drivers/gpu/drm/radeon/sumo_smc.c    |  224 +++++
 drivers/gpu/drm/radeon/sumod.h       |  362 ++++++++
 8 files changed, 2489 insertions(+), 1 deletions(-)
 create mode 100644 drivers/gpu/drm/radeon/sumo_dpm.c
 create mode 100644 drivers/gpu/drm/radeon/sumo_dpm.h
 create mode 100644 drivers/gpu/drm/radeon/sumo_smc.c
 create mode 100644 drivers/gpu/drm/radeon/sumod.h
drivers/gpu/drm/radeon/Makefile +1 -1
index af3dd8f..7c77e1d 100644
@@ -78,7 +78,7 @@ radeon-y += radeon_device.o radeon_asic.o radeon_kms.o \
 	atombios_encoders.o radeon_semaphore.o radeon_sa.o atombios_i2c.o si.o \
 	si_blit_shaders.o radeon_prime.o radeon_uvd.o cik.o cik_blit_shaders.o \
 	r600_dpm.o rs780_dpm.o rv6xx_dpm.o rv770_dpm.o rv730_dpm.o rv740_dpm.o \
-	rv770_smc.o cypress_dpm.o btc_dpm.o
+	rv770_smc.o cypress_dpm.o btc_dpm.o sumo_dpm.o sumo_smc.o
 
 radeon-$(CONFIG_COMPAT) += radeon_ioc32.o
 radeon-$(CONFIG_VGA_SWITCHEROO) += radeon_atpx_handler.o
drivers/gpu/drm/radeon/radeon_asic.c +12 -0
index 20f65ad..8b541b4 100644
@@ -1539,6 +1539,18 @@ static struct radeon_asic sumo_asic = {
 		.set_uvd_clocks = &sumo_set_uvd_clocks,
 		.get_temperature = &sumo_get_temp,
 	},
+	.dpm = {
+		.init = &sumo_dpm_init,
+		.setup_asic = &sumo_dpm_setup_asic,
+		.enable = &sumo_dpm_enable,
+		.disable = &sumo_dpm_disable,
+		.set_power_state = &sumo_dpm_set_power_state,
+		.display_configuration_changed = &sumo_dpm_display_configuration_changed,
+		.fini = &sumo_dpm_fini,
+		.get_sclk = &sumo_dpm_get_sclk,
+		.get_mclk = &sumo_dpm_get_mclk,
+		.print_power_state = &sumo_dpm_print_power_state,
+	},
 	.pflip = {
 		.pre_page_flip = &evergreen_pre_page_flip,
 		.page_flip = &evergreen_page_flip,
drivers/gpu/drm/radeon/radeon_asic.h +11 -0
index 214429b..f6c0984 100644
@@ -536,6 +536,17 @@ int btc_dpm_enable(struct radeon_device *rdev);
 void btc_dpm_disable(struct radeon_device *rdev);
 int btc_dpm_set_power_state(struct radeon_device *rdev);
 void btc_dpm_fini(struct radeon_device *rdev);
+int sumo_dpm_init(struct radeon_device *rdev);
+int sumo_dpm_enable(struct radeon_device *rdev);
+void sumo_dpm_disable(struct radeon_device *rdev);
+int sumo_dpm_set_power_state(struct radeon_device *rdev);
+void sumo_dpm_setup_asic(struct radeon_device *rdev);
+void sumo_dpm_display_configuration_changed(struct radeon_device *rdev);
+void sumo_dpm_fini(struct radeon_device *rdev);
+u32 sumo_dpm_get_sclk(struct radeon_device *rdev, bool low);
+u32 sumo_dpm_get_mclk(struct radeon_device *rdev, bool low);
+void sumo_dpm_print_power_state(struct radeon_device *rdev,
+				struct radeon_ps *ps);
 
 /*
  * cayman
drivers/gpu/drm/radeon/radeon_pm.c +3 -0
index 0a770b5..b924bcc1 100644
@@ -1049,6 +1049,9 @@ int radeon_pm_init(struct radeon_device *rdev)
 	case CHIP_JUNIPER:
 	case CHIP_CYPRESS:
 	case CHIP_HEMLOCK:
+	case CHIP_PALM:
+	case CHIP_SUMO:
+	case CHIP_SUMO2:
 	case CHIP_BARTS:
 	case CHIP_TURKS:
 	case CHIP_CAICOS:
drivers/gpu/drm/radeon/sumo_dpm.c new file +548 -0
new file mode 100644
index 0000000..4f49450
@@ -0,0 +1,1677 @@
+/*
+ * Copyright 2012 Advanced Micro Devices, Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ */
+
+#include "drmP.h"
+#include "radeon.h"
+#include "sumod.h"
+#include "r600_dpm.h"
+#include "cypress_dpm.h"
+#include "sumo_dpm.h"
+#include "atom.h"
+
+#define SUMO_MAX_DEEPSLEEP_DIVIDER_ID 5
+#define SUMO_MINIMUM_ENGINE_CLOCK 800
+#define BOOST_DPM_LEVEL 7
+
+static const u32 sumo_utc[SUMO_PM_NUMBER_OF_TC] =
+{
+	SUMO_UTC_DFLT_00,
+	SUMO_UTC_DFLT_01,
+	SUMO_UTC_DFLT_02,
+	SUMO_UTC_DFLT_03,
+	SUMO_UTC_DFLT_04,
+	SUMO_UTC_DFLT_05,
+	SUMO_UTC_DFLT_06,
+	SUMO_UTC_DFLT_07,
+	SUMO_UTC_DFLT_08,
+	SUMO_UTC_DFLT_09,
+	SUMO_UTC_DFLT_10,
+	SUMO_UTC_DFLT_11,
+	SUMO_UTC_DFLT_12,
+	SUMO_UTC_DFLT_13,
+	SUMO_UTC_DFLT_14,
+};
+
+static const u32 sumo_dtc[SUMO_PM_NUMBER_OF_TC] =
+{
+	SUMO_DTC_DFLT_00,
+	SUMO_DTC_DFLT_01,
+	SUMO_DTC_DFLT_02,
+	SUMO_DTC_DFLT_03,
+	SUMO_DTC_DFLT_04,
+	SUMO_DTC_DFLT_05,
+	SUMO_DTC_DFLT_06,
+	SUMO_DTC_DFLT_07,
+	SUMO_DTC_DFLT_08,
+	SUMO_DTC_DFLT_09,
+	SUMO_DTC_DFLT_10,
+	SUMO_DTC_DFLT_11,
+	SUMO_DTC_DFLT_12,
+	SUMO_DTC_DFLT_13,
+	SUMO_DTC_DFLT_14,
+};
+
+struct sumo_ps *sumo_get_ps(struct radeon_ps *rps)
+{
+	struct sumo_ps *ps = rps->ps_priv;
+
+	return ps;
+}
+
+struct sumo_power_info *sumo_get_pi(struct radeon_device *rdev)
+{
+	struct sumo_power_info *pi = rdev->pm.dpm.priv;
+
+	return pi;
+}
+
+u32 sumo_get_xclk(struct radeon_device *rdev)
+{
+	return rdev->clock.spll.reference_freq;
+}
+
+static void sumo_gfx_clockgating_enable(struct radeon_device *rdev, bool enable)
+{
+	if (enable)
+		WREG32_P(SCLK_PWRMGT_CNTL, DYN_GFX_CLK_OFF_EN, ~DYN_GFX_CLK_OFF_EN);
+	else {
+		WREG32_P(SCLK_PWRMGT_CNTL, 0, ~DYN_GFX_CLK_OFF_EN);
+		WREG32_P(SCLK_PWRMGT_CNTL, GFX_CLK_FORCE_ON, ~GFX_CLK_FORCE_ON);
+		WREG32_P(SCLK_PWRMGT_CNTL, 0, ~GFX_CLK_FORCE_ON);
+		RREG32(GB_ADDR_CONFIG);
+	}
+}
+
+#define CGCG_CGTT_LOCAL0_MASK 0xE5BFFFFF
+#define CGCG_CGTT_LOCAL1_MASK 0xEFFF07FF
+
+static void sumo_mg_clockgating_enable(struct radeon_device *rdev, bool enable)
+{
+	u32 local0;
+	u32 local1;
+
+	local0 = RREG32(CG_CGTT_LOCAL_0);
+	local1 = RREG32(CG_CGTT_LOCAL_1);
+
+	if (enable) {
+		WREG32(CG_CGTT_LOCAL_0, (0 & CGCG_CGTT_LOCAL0_MASK) | (local0 & ~CGCG_CGTT_LOCAL0_MASK) );
+		WREG32(CG_CGTT_LOCAL_1, (0 & CGCG_CGTT_LOCAL1_MASK) | (local1 & ~CGCG_CGTT_LOCAL1_MASK) );
+	} else {
+		WREG32(CG_CGTT_LOCAL_0, (0xFFFFFFFF & CGCG_CGTT_LOCAL0_MASK) | (local0 & ~CGCG_CGTT_LOCAL0_MASK) );
+		WREG32(CG_CGTT_LOCAL_1, (0xFFFFCFFF & CGCG_CGTT_LOCAL1_MASK) | (local1 & ~CGCG_CGTT_LOCAL1_MASK) );
+	}
+}
+
+static void sumo_program_git(struct radeon_device *rdev)
+{
+	u32 p, u;
+	u32 xclk = sumo_get_xclk(rdev);
+
+	r600_calculate_u_and_p(SUMO_GICST_DFLT,
+			       xclk, 16, &p, &u);
+
+	WREG32_P(CG_GIT, CG_GICST(p), ~CG_GICST_MASK);
+}
+
+static void sumo_program_grsd(struct radeon_device *rdev)
+{
+	u32 p, u;
+	u32 xclk = sumo_get_xclk(rdev);
+	u32 grs = 256 * 25 / 100;
+
+	r600_calculate_u_and_p(1, xclk, 14, &p, &u);
+
+	WREG32(CG_GCOOR, PHC(grs) | SDC(p) | SU(u));
+}
+
+static void sumo_gfx_clockgating_initialize(struct radeon_device *rdev)
+{
+	sumo_program_git(rdev);
+	sumo_program_grsd(rdev);
+}
+
+static void sumo_gfx_powergating_initialize(struct radeon_device *rdev)
+{
+	u32 rcu_pwr_gating_cntl;
+	u32 p, u;
+	u32 p_c, p_p, d_p;
+	u32 r_t, i_t;
+	u32 xclk = sumo_get_xclk(rdev);
+
+	if (rdev->family == CHIP_PALM) {
+		p_c = 4;
+		d_p = 10;
+		r_t = 10;
+		i_t = 4;
+		p_p = 50 + 1000/200 + 6 * 32;
+	} else {
+		p_c = 16;
+		d_p = 50;
+		r_t = 50;
+		i_t  = 50;
+		p_p = 113;
+	}
+
+	WREG32(CG_SCRATCH2, 0x01B60A17);
+
+	r600_calculate_u_and_p(SUMO_GFXPOWERGATINGT_DFLT,
+			       xclk, 16, &p, &u);
+
+	WREG32_P(CG_PWR_GATING_CNTL, PGP(p) | PGU(u),
+		 ~(PGP_MASK | PGU_MASK));
+
+	r600_calculate_u_and_p(SUMO_VOLTAGEDROPT_DFLT,
+			       xclk, 16, &p, &u);
+
+	WREG32_P(CG_CG_VOLTAGE_CNTL, PGP(p) | PGU(u),
+		 ~(PGP_MASK | PGU_MASK));
+
+	if (rdev->family == CHIP_PALM) {
+		WREG32_RCU(RCU_PWR_GATING_SEQ0, 0x10103210);
+		WREG32_RCU(RCU_PWR_GATING_SEQ1, 0x10101010);
+	} else {
+		WREG32_RCU(RCU_PWR_GATING_SEQ0, 0x76543210);
+		WREG32_RCU(RCU_PWR_GATING_SEQ1, 0xFEDCBA98);
+	}
+
+	rcu_pwr_gating_cntl = RREG32_RCU(RCU_PWR_GATING_CNTL);
+	rcu_pwr_gating_cntl &=
+		~(RSVD_MASK | PCV_MASK | PGS_MASK);
+	rcu_pwr_gating_cntl |= PCV(p_c) | PGS(1) | PWR_GATING_EN;
+	if (rdev->family == CHIP_PALM) {
+		rcu_pwr_gating_cntl &= ~PCP_MASK;
+		rcu_pwr_gating_cntl |= PCP(0x77);
+	}
+	WREG32_RCU(RCU_PWR_GATING_CNTL, rcu_pwr_gating_cntl);
+
+	rcu_pwr_gating_cntl = RREG32_RCU(RCU_PWR_GATING_CNTL_2);
+	rcu_pwr_gating_cntl &= ~(MPPU_MASK | MPPD_MASK);
+	rcu_pwr_gating_cntl |= MPPU(p_p) | MPPD(50);
+	WREG32_RCU(RCU_PWR_GATING_CNTL_2, rcu_pwr_gating_cntl);
+
+	rcu_pwr_gating_cntl = RREG32_RCU(RCU_PWR_GATING_CNTL_3);
+	rcu_pwr_gating_cntl &= ~(DPPU_MASK | DPPD_MASK);
+	rcu_pwr_gating_cntl |= DPPU(d_p) | DPPD(50);
+	WREG32_RCU(RCU_PWR_GATING_CNTL_3, rcu_pwr_gating_cntl);
+
+	rcu_pwr_gating_cntl = RREG32_RCU(RCU_PWR_GATING_CNTL_4);
+	rcu_pwr_gating_cntl &= ~(RT_MASK | IT_MASK);
+	rcu_pwr_gating_cntl |= RT(r_t) | IT(i_t);
+	WREG32_RCU(RCU_PWR_GATING_CNTL_4, rcu_pwr_gating_cntl);
+
+	if (rdev->family == CHIP_PALM)
+		WREG32_RCU(RCU_PWR_GATING_CNTL_5, 0xA02);
+
+	sumo_smu_pg_init(rdev);
+
+	rcu_pwr_gating_cntl = RREG32_RCU(RCU_PWR_GATING_CNTL);
+	rcu_pwr_gating_cntl &=
+		~(RSVD_MASK | PCV_MASK | PGS_MASK);
+	rcu_pwr_gating_cntl |= PCV(p_c) | PGS(4) | PWR_GATING_EN;
+	if (rdev->family == CHIP_PALM) {
+		rcu_pwr_gating_cntl &= ~PCP_MASK;
+		rcu_pwr_gating_cntl |= PCP(0x77);
+	}
+	WREG32_RCU(RCU_PWR_GATING_CNTL, rcu_pwr_gating_cntl);
+
+	if (rdev->family == CHIP_PALM) {
+		rcu_pwr_gating_cntl = RREG32_RCU(RCU_PWR_GATING_CNTL_2);
+		rcu_pwr_gating_cntl &= ~(MPPU_MASK | MPPD_MASK);
+		rcu_pwr_gating_cntl |= MPPU(113) | MPPD(50);
+		WREG32_RCU(RCU_PWR_GATING_CNTL_2, rcu_pwr_gating_cntl);
+
+		rcu_pwr_gating_cntl = RREG32_RCU(RCU_PWR_GATING_CNTL_3);
+		rcu_pwr_gating_cntl &= ~(DPPU_MASK | DPPD_MASK);
+		rcu_pwr_gating_cntl |= DPPU(16) | DPPD(50);
+		WREG32_RCU(RCU_PWR_GATING_CNTL_3, rcu_pwr_gating_cntl);
+	}
+
+	sumo_smu_pg_init(rdev);
+
+	rcu_pwr_gating_cntl = RREG32_RCU(RCU_PWR_GATING_CNTL);
+	rcu_pwr_gating_cntl &=
+		~(RSVD_MASK | PCV_MASK | PGS_MASK);
+	rcu_pwr_gating_cntl |= PGS(5) | PWR_GATING_EN;
+
+	if (rdev->family == CHIP_PALM) {
+		rcu_pwr_gating_cntl |= PCV(4);
+		rcu_pwr_gating_cntl &= ~PCP_MASK;
+		rcu_pwr_gating_cntl |= PCP(0x77);
+	} else
+		rcu_pwr_gating_cntl |= PCV(11);
+	WREG32_RCU(RCU_PWR_GATING_CNTL, rcu_pwr_gating_cntl);
+
+	if (rdev->family == CHIP_PALM) {
+		rcu_pwr_gating_cntl = RREG32_RCU(RCU_PWR_GATING_CNTL_2);
+		rcu_pwr_gating_cntl &= ~(MPPU_MASK | MPPD_MASK);
+		rcu_pwr_gating_cntl |= MPPU(113) | MPPD(50);
+		WREG32_RCU(RCU_PWR_GATING_CNTL_2, rcu_pwr_gating_cntl);
+
+		rcu_pwr_gating_cntl = RREG32_RCU(RCU_PWR_GATING_CNTL_3);
+		rcu_pwr_gating_cntl &= ~(DPPU_MASK | DPPD_MASK);
+		rcu_pwr_gating_cntl |= DPPU(22) | DPPD(50);
+		WREG32_RCU(RCU_PWR_GATING_CNTL_3, rcu_pwr_gating_cntl);
+	}
+
+	sumo_smu_pg_init(rdev);
+}
+
+static void sumo_gfx_powergating_enable(struct radeon_device *rdev, bool enable)
+{
+	if (enable)
+		WREG32_P(CG_PWR_GATING_CNTL, DYN_PWR_DOWN_EN, ~DYN_PWR_DOWN_EN);
+	else {
+		WREG32_P(CG_PWR_GATING_CNTL, 0, ~DYN_PWR_DOWN_EN);
+		RREG32(GB_ADDR_CONFIG);
+	}
+}
+
+static int sumo_enable_clock_power_gating(struct radeon_device *rdev)
+{
+	struct sumo_power_info *pi = sumo_get_pi(rdev);
+
+	if (pi->enable_gfx_clock_gating)
+		sumo_gfx_clockgating_initialize(rdev);
+	if (pi->enable_gfx_power_gating)
+		sumo_gfx_powergating_initialize(rdev);
+	if (pi->enable_mg_clock_gating)
+		sumo_mg_clockgating_enable(rdev, true);
+	if (pi->enable_gfx_clock_gating)
+		sumo_gfx_clockgating_enable(rdev, true);
+	if (pi->enable_gfx_power_gating)
+		sumo_gfx_powergating_enable(rdev, true);
+
+	return 0;
+}
+
+static void sumo_disable_clock_power_gating(struct radeon_device *rdev)
+{
+	struct sumo_power_info *pi = sumo_get_pi(rdev);
+
+	if (pi->enable_gfx_clock_gating)
+		sumo_gfx_clockgating_enable(rdev, false);
+	if (pi->enable_gfx_power_gating)
+		sumo_gfx_powergating_enable(rdev, false);
+	if (pi->enable_mg_clock_gating)
+		sumo_mg_clockgating_enable(rdev, false);
+}
+
+static void sumo_calculate_bsp(struct radeon_device *rdev,
+			       u32 high_clk)
+{
+	struct sumo_power_info *pi = sumo_get_pi(rdev);
+	u32 xclk = sumo_get_xclk(rdev);
+
+	pi->pasi = 65535 * 100 / high_clk;
+	pi->asi = 65535 * 100 / high_clk;
+
+	r600_calculate_u_and_p(pi->asi,
+			       xclk, 16, &pi->bsp, &pi->bsu);
+
+	r600_calculate_u_and_p(pi->pasi,
+			       xclk, 16, &pi->pbsp, &pi->pbsu);
+
+	pi->dsp = BSP(pi->bsp) | BSU(pi->bsu);
+	pi->psp = BSP(pi->pbsp) | BSU(pi->pbsu);
+}
+
+static void sumo_init_bsp(struct radeon_device *rdev)
+{
+	struct sumo_power_info *pi = sumo_get_pi(rdev);
+
+	WREG32(CG_BSP_0, pi->psp);
+}
+
+
+static void sumo_program_bsp(struct radeon_device *rdev)
+{
+	struct sumo_power_info *pi = sumo_get_pi(rdev);
+	struct sumo_ps *ps = sumo_get_ps(rdev->pm.dpm.requested_ps);
+	u32 i;
+	u32 highest_engine_clock = ps->levels[ps->num_levels - 1].sclk;
+
+	if (ps->flags & SUMO_POWERSTATE_FLAGS_BOOST_STATE)
+		highest_engine_clock = pi->boost_pl.sclk;
+
+	sumo_calculate_bsp(rdev, highest_engine_clock);
+
+	for (i = 0; i < ps->num_levels - 1; i++)
+		WREG32(CG_BSP_0 + (i * 4), pi->dsp);
+
+	WREG32(CG_BSP_0 + (i * 4), pi->psp);
+
+	if (ps->flags & SUMO_POWERSTATE_FLAGS_BOOST_STATE)
+		WREG32(CG_BSP_0 + (BOOST_DPM_LEVEL * 4), pi->psp);
+}
+
+static void sumo_write_at(struct radeon_device *rdev,
+			  u32 index, u32 value)
+{
+	if (index == 0)
+		WREG32(CG_AT_0, value);
+	else if (index == 1)
+		WREG32(CG_AT_1, value);
+	else if (index == 2)
+		WREG32(CG_AT_2, value);
+	else if (index == 3)
+		WREG32(CG_AT_3, value);
+	else if (index == 4)
+		WREG32(CG_AT_4, value);
+	else if (index == 5)
+		WREG32(CG_AT_5, value);
+	else if (index == 6)
+		WREG32(CG_AT_6, value);
+	else if (index == 7)
+		WREG32(CG_AT_7, value);
+}
+
+static void sumo_program_at(struct radeon_device *rdev)
+{
+	struct sumo_power_info *pi = sumo_get_pi(rdev);
+	struct sumo_ps *ps = sumo_get_ps(rdev->pm.dpm.requested_ps);
+	u32 asi;
+	u32 i;
+	u32 m_a;
+	u32 a_t;
+	u32 r[SUMO_MAX_HARDWARE_POWERLEVELS];
+	u32 l[SUMO_MAX_HARDWARE_POWERLEVELS];
+
+	r[0] = SUMO_R_DFLT0;
+	r[1] = SUMO_R_DFLT1;
+	r[2] = SUMO_R_DFLT2;
+	r[3] = SUMO_R_DFLT3;
+	r[4] = SUMO_R_DFLT4;
+
+	l[0] = SUMO_L_DFLT0;
+	l[1] = SUMO_L_DFLT1;
+	l[2] = SUMO_L_DFLT2;
+	l[3] = SUMO_L_DFLT3;
+	l[4] = SUMO_L_DFLT4;
+
+	for (i = 0; i < ps->num_levels; i++) {
+		asi = (i == ps->num_levels - 1) ? pi->pasi : pi->asi;
+
+		m_a = asi * ps->levels[i].sclk / 100;
+
+		a_t = CG_R(m_a * r[i] / 100) | CG_L(m_a * l[i] / 100);
+
+		sumo_write_at(rdev, i, a_t);
+	}
+
+	if (ps->flags & SUMO_POWERSTATE_FLAGS_BOOST_STATE) {
+		asi = pi->pasi;
+
+		m_a = asi * pi->boost_pl.sclk / 100;
+
+		a_t = CG_R(m_a * r[ps->num_levels - 1] / 100) |
+			CG_L(m_a * l[ps->num_levels - 1] / 100);
+
+		sumo_write_at(rdev, BOOST_DPM_LEVEL, a_t);
+	}
+}
+
+static void sumo_program_tp(struct radeon_device *rdev)
+{
+	int i;
+	enum r600_td td = R600_TD_DFLT;
+
+	for (i = 0; i < SUMO_PM_NUMBER_OF_TC; i++) {
+		WREG32_P(CG_FFCT_0 + (i * 4), UTC_0(sumo_utc[i]), ~UTC_0_MASK);
+		WREG32_P(CG_FFCT_0 + (i * 4), DTC_0(sumo_dtc[i]), ~DTC_0_MASK);
+	}
+
+	if (td == R600_TD_AUTO)
+		WREG32_P(SCLK_PWRMGT_CNTL, 0, ~FIR_FORCE_TREND_SEL);
+	else
+		WREG32_P(SCLK_PWRMGT_CNTL, FIR_FORCE_TREND_SEL, ~FIR_FORCE_TREND_SEL);
+
+	if (td == R600_TD_UP)
+		WREG32_P(SCLK_PWRMGT_CNTL, 0, ~FIR_TREND_MODE);
+
+	if (td == R600_TD_DOWN)
+		WREG32_P(SCLK_PWRMGT_CNTL, FIR_TREND_MODE, ~FIR_TREND_MODE);
+}
+
+static void sumo_program_vc(struct radeon_device *rdev)
+{
+	WREG32(CG_FTV, SUMO_VRC_DFLT);
+}
+
+static void sumo_clear_vc(struct radeon_device *rdev)
+{
+	WREG32(CG_FTV, 0);
+}
+
+static void sumo_program_sstp(struct radeon_device *rdev)
+{
+	u32 p, u;
+	u32 xclk = sumo_get_xclk(rdev);
+
+	r600_calculate_u_and_p(SUMO_SST_DFLT,
+			       xclk, 16, &p, &u);
+
+	WREG32(CG_SSP, SSTU(u) | SST(p));
+}
+
+static void sumo_set_divider_value(struct radeon_device *rdev,
+				   u32 index, u32 divider)
+{
+	u32 reg_index = index / 4;
+	u32 field_index = index % 4;
+
+	if (field_index == 0)
+		WREG32_P(CG_SCLK_DPM_CTRL + (reg_index * 4),
+			 SCLK_FSTATE_0_DIV(divider), ~SCLK_FSTATE_0_DIV_MASK);
+	else if (field_index == 1)
+		WREG32_P(CG_SCLK_DPM_CTRL + (reg_index * 4),
+			 SCLK_FSTATE_1_DIV(divider), ~SCLK_FSTATE_1_DIV_MASK);
+	else if (field_index == 2)
+		WREG32_P(CG_SCLK_DPM_CTRL + (reg_index * 4),
+			 SCLK_FSTATE_2_DIV(divider), ~SCLK_FSTATE_2_DIV_MASK);
+	else if (field_index == 3)
+		WREG32_P(CG_SCLK_DPM_CTRL + (reg_index * 4),
+			 SCLK_FSTATE_3_DIV(divider), ~SCLK_FSTATE_3_DIV_MASK);
+}
+
+static void sumo_set_ds_dividers(struct radeon_device *rdev,
+				 u32 index, u32 divider)
+{
+	struct sumo_power_info *pi = sumo_get_pi(rdev);
+
+	if (pi->enable_sclk_ds) {
+		u32 dpm_ctrl = RREG32(CG_SCLK_DPM_CTRL_6);
+
+		dpm_ctrl &= ~(0x7 << (index * 3));
+		dpm_ctrl |= (divider << (index * 3));
+		WREG32(CG_SCLK_DPM_CTRL_6, dpm_ctrl);
+	}
+}
+
+static void sumo_set_ss_dividers(struct radeon_device *rdev,
+				 u32 index, u32 divider)
+{
+	struct sumo_power_info *pi = sumo_get_pi(rdev);
+
+	if (pi->enable_sclk_ds) {
+		u32 dpm_ctrl = RREG32(CG_SCLK_DPM_CTRL_11);
+
+		dpm_ctrl &= ~(0x7 << (index * 3));
+		dpm_ctrl |= (divider << (index * 3));
+		WREG32(CG_SCLK_DPM_CTRL_11, dpm_ctrl);
+	}
+}
+
+static void sumo_set_vid(struct radeon_device *rdev, u32 index, u32 vid)
+{
+	u32 voltage_cntl = RREG32(CG_DPM_VOLTAGE_CNTL);
+
+	voltage_cntl &= ~(DPM_STATE0_LEVEL_MASK << (index * 2));
+	voltage_cntl |= (vid << (DPM_STATE0_LEVEL_SHIFT + index * 2));
+	WREG32(CG_DPM_VOLTAGE_CNTL, voltage_cntl);
+}
+
+static void sumo_set_allos_gnb_slow(struct radeon_device *rdev, u32 index, u32 gnb_slow)
+{
+	struct sumo_power_info *pi = sumo_get_pi(rdev);
+	u32 temp = gnb_slow;
+	u32 cg_sclk_dpm_ctrl_3;
+
+	if (pi->driver_nbps_policy_disable)
+		temp = 1;
+
+	cg_sclk_dpm_ctrl_3 = RREG32(CG_SCLK_DPM_CTRL_3);
+	cg_sclk_dpm_ctrl_3 &= ~(GNB_SLOW_FSTATE_0_MASK << index);
+	cg_sclk_dpm_ctrl_3 |= (temp << (GNB_SLOW_FSTATE_0_SHIFT + index));
+
+	WREG32(CG_SCLK_DPM_CTRL_3, cg_sclk_dpm_ctrl_3);
+}
+

drivers/gpu/drm/radeon/sumo_dpm.c line 558

Quoted 10 lines
drivers/gpu/drm/radeon/sumo_dpm.c new file +10 -0
+static void sumo_program_power_level(struct radeon_device *rdev,
+				     struct sumo_pl *pl, u32 index)
+{
+	struct sumo_power_info *pi = sumo_get_pi(rdev);
+	int ret;
+	struct atom_clock_dividers dividers;
+	u32 ds_en = RREG32(DEEP_SLEEP_CNTL) & ENABLE_DS;
+
+        ret = radeon_atom_get_clock_dividers(rdev, COMPUTE_ENGINE_PLL_PARAM,
+                                             pl->sclk, false, &dividers);

Indentation issue (space instead of tab).

Quoted 1,497 lines
drivers/gpu/drm/radeon/sumo_dpm.c new file +1119 -0
+	if (ret)
+		return;
+
+	sumo_set_divider_value(rdev, index, dividers.post_div);
+
+	sumo_set_vid(rdev, index, pl->vddc_index);
+
+	if (pl->ss_divider_index == 0 || pl->ds_divider_index == 0) {
+		if (ds_en)
+			WREG32_P(DEEP_SLEEP_CNTL, 0, ~ENABLE_DS);
+	} else {
+		sumo_set_ss_dividers(rdev, index, pl->ss_divider_index);
+		sumo_set_ds_dividers(rdev, index, pl->ds_divider_index);
+
+		if (!ds_en)
+			WREG32_P(DEEP_SLEEP_CNTL, ENABLE_DS, ~ENABLE_DS);
+	}
+
+	sumo_set_allos_gnb_slow(rdev, index, pl->allow_gnb_slow);
+
+	if (pi->enable_boost)
+		sumo_set_tdp_limit(rdev, index, pl->sclk_dpm_tdp_limit);
+}
+
+static void sumo_power_level_enable(struct radeon_device *rdev, u32 index, bool enable)
+{
+	u32 reg_index = index / 4;
+	u32 field_index = index % 4;
+
+	if (field_index == 0)
+		WREG32_P(CG_SCLK_DPM_CTRL + (reg_index * 4),
+			 enable ? SCLK_FSTATE_0_VLD : 0, ~SCLK_FSTATE_0_VLD);
+	else if (field_index == 1)
+		WREG32_P(CG_SCLK_DPM_CTRL + (reg_index * 4),
+			 enable ? SCLK_FSTATE_1_VLD : 0, ~SCLK_FSTATE_1_VLD);
+	else if (field_index == 2)
+		WREG32_P(CG_SCLK_DPM_CTRL + (reg_index * 4),
+			 enable ? SCLK_FSTATE_2_VLD : 0, ~SCLK_FSTATE_2_VLD);
+	else if (field_index == 3)
+		WREG32_P(CG_SCLK_DPM_CTRL + (reg_index * 4),
+			 enable ? SCLK_FSTATE_3_VLD : 0, ~SCLK_FSTATE_3_VLD);
+}
+
+static bool sumo_dpm_enabled(struct radeon_device *rdev)
+{
+	if (RREG32(CG_SCLK_DPM_CTRL_3) & DPM_SCLK_ENABLE)
+		return true;
+	else
+		return false;
+}
+
+static void sumo_start_dpm(struct radeon_device *rdev)
+{
+	WREG32_P(CG_SCLK_DPM_CTRL_3, DPM_SCLK_ENABLE, ~DPM_SCLK_ENABLE);
+}
+
+static void sumo_stop_dpm(struct radeon_device *rdev)
+{
+	WREG32_P(CG_SCLK_DPM_CTRL_3, 0, ~DPM_SCLK_ENABLE);
+}
+
+static void sumo_set_forced_mode(struct radeon_device *rdev, bool enable)
+{
+	if (enable)
+		WREG32_P(CG_SCLK_DPM_CTRL_3, FORCE_SCLK_STATE_EN, ~FORCE_SCLK_STATE_EN);
+	else
+		WREG32_P(CG_SCLK_DPM_CTRL_3, 0, ~FORCE_SCLK_STATE_EN);
+}
+
+static void sumo_set_forced_mode_enabled(struct radeon_device *rdev)
+{
+	int i;
+
+	sumo_set_forced_mode(rdev, true);
+	for (i = 0; i < rdev->usec_timeout; i++) {
+		if (RREG32(CG_SCLK_STATUS) & SCLK_OVERCLK_DETECT)
+			break;
+		udelay(1);
+	}
+}
+
+static void sumo_wait_for_level_0(struct radeon_device *rdev)
+{
+	int i;
+
+	for (i = 0; i < rdev->usec_timeout; i++) {
+		if ((RREG32(TARGET_AND_CURRENT_PROFILE_INDEX) & CURR_SCLK_INDEX_MASK) == 0)
+			break;
+		udelay(1);
+	}
+	for (i = 0; i < rdev->usec_timeout; i++) {
+		if ((RREG32(TARGET_AND_CURRENT_PROFILE_INDEX) & CURR_INDEX_MASK) == 0)
+			break;
+		udelay(1);
+	}
+}
+
+static void sumo_set_forced_mode_disabled(struct radeon_device *rdev)
+{
+	sumo_set_forced_mode(rdev, false);
+}
+
+static void sumo_enable_power_level_0(struct radeon_device *rdev)
+{
+	sumo_power_level_enable(rdev, 0, true);
+}
+
+static void sumo_patch_boost_state(struct radeon_device *rdev)
+{
+	struct sumo_power_info *pi = sumo_get_pi(rdev);
+	struct sumo_ps *new_ps = sumo_get_ps(rdev->pm.dpm.requested_ps);
+
+	if (new_ps->flags & SUMO_POWERSTATE_FLAGS_BOOST_STATE) {
+		pi->boost_pl = new_ps->levels[new_ps->num_levels - 1];
+		pi->boost_pl.sclk = pi->sys_info.boost_sclk;
+		pi->boost_pl.vddc_index = pi->sys_info.boost_vid_2bit;
+		pi->boost_pl.sclk_dpm_tdp_limit = pi->sys_info.sclk_dpm_tdp_limit_boost;
+	}
+}
+
+static void sumo_pre_notify_alt_vddnb_change(struct radeon_device *rdev)
+{
+	struct sumo_ps *new_ps = sumo_get_ps(rdev->pm.dpm.requested_ps);
+	struct sumo_ps *old_ps = sumo_get_ps(rdev->pm.dpm.current_ps);
+	u32 nbps1_old = 0;
+	u32 nbps1_new = 0;
+
+	if (old_ps != NULL)
+		nbps1_old = (old_ps->flags & SUMO_POWERSTATE_FLAGS_FORCE_NBPS1_STATE) ? 1 : 0;
+
+	nbps1_new = (new_ps->flags & SUMO_POWERSTATE_FLAGS_FORCE_NBPS1_STATE) ? 1 : 0;
+
+	if (nbps1_old == 1 && nbps1_new == 0)
+		sumo_smu_notify_alt_vddnb_change(rdev, 0, 0);
+}
+
+static void sumo_post_notify_alt_vddnb_change(struct radeon_device *rdev)
+{
+	struct sumo_ps *new_ps = sumo_get_ps(rdev->pm.dpm.requested_ps);
+	struct sumo_ps *old_ps = sumo_get_ps(rdev->pm.dpm.current_ps);
+	u32 nbps1_old = 0;
+	u32 nbps1_new = 0;
+
+	if (old_ps != NULL)
+		nbps1_old = (old_ps->flags & SUMO_POWERSTATE_FLAGS_FORCE_NBPS1_STATE)? 1 : 0;
+
+	nbps1_new = (new_ps->flags & SUMO_POWERSTATE_FLAGS_FORCE_NBPS1_STATE)? 1 : 0;
+
+	if (nbps1_old == 0 && nbps1_new == 1)
+		sumo_smu_notify_alt_vddnb_change(rdev, 1, 1);
+}
+
+static void sumo_enable_boost(struct radeon_device *rdev, bool enable)
+{
+	struct sumo_ps *new_ps = sumo_get_ps(rdev->pm.dpm.requested_ps);
+
+	if (enable) {
+		if (new_ps->flags & SUMO_POWERSTATE_FLAGS_BOOST_STATE)
+			sumo_boost_state_enable(rdev, true);
+	} else
+		sumo_boost_state_enable(rdev, false);
+}
+
+static void sumo_update_current_power_levels(struct radeon_device *rdev)
+{
+	struct sumo_ps *new_ps = sumo_get_ps(rdev->pm.dpm.requested_ps);
+	struct sumo_power_info *pi = sumo_get_pi(rdev);
+
+	pi->current_ps = *new_ps;
+}
+
+static void sumo_set_forced_level(struct radeon_device *rdev, u32 index)
+{
+	WREG32_P(CG_SCLK_DPM_CTRL_3, FORCE_SCLK_STATE(index), ~FORCE_SCLK_STATE_MASK);
+}
+
+static void sumo_set_forced_level_0(struct radeon_device *rdev)
+{
+	sumo_set_forced_level(rdev, 0);
+}
+
+static void sumo_program_wl(struct radeon_device *rdev)
+{
+	struct sumo_ps *new_ps = sumo_get_ps(rdev->pm.dpm.requested_ps);
+	u32 dpm_ctrl4 = RREG32(CG_SCLK_DPM_CTRL_4);
+
+	dpm_ctrl4 &= 0xFFFFFF00;
+	dpm_ctrl4 |= (1 << (new_ps->num_levels - 1));
+
+	if (new_ps->flags & SUMO_POWERSTATE_FLAGS_BOOST_STATE)
+		dpm_ctrl4 |= (1 << BOOST_DPM_LEVEL);
+
+	WREG32(CG_SCLK_DPM_CTRL_4, dpm_ctrl4);
+}
+
+static void sumo_program_power_levels_0_to_n(struct radeon_device *rdev)
+{
+	struct sumo_power_info *pi = sumo_get_pi(rdev);
+	struct sumo_ps *new_ps = sumo_get_ps(rdev->pm.dpm.requested_ps);
+	struct sumo_ps *old_ps = sumo_get_ps(rdev->pm.dpm.current_ps);
+	u32 i;
+	u32 n_current_state_levels = (old_ps == NULL) ? 1 : old_ps->num_levels;
+
+	for (i = 0; i < new_ps->num_levels; i++) {
+		sumo_program_power_level(rdev, &new_ps->levels[i], i);
+		sumo_power_level_enable(rdev, i, true);
+	}
+
+	for (i = new_ps->num_levels; i < n_current_state_levels; i++)
+		sumo_power_level_enable(rdev, i, false);
+
+	if (new_ps->flags & SUMO_POWERSTATE_FLAGS_BOOST_STATE)
+		sumo_program_power_level(rdev, &pi->boost_pl, BOOST_DPM_LEVEL);
+}
+
+static void sumo_enable_acpi_pm(struct radeon_device *rdev)
+{
+	WREG32_P(GENERAL_PWRMGT, STATIC_PM_EN, ~STATIC_PM_EN);
+}
+
+static void sumo_program_power_level_enter_state(struct radeon_device *rdev)
+{
+	WREG32_P(CG_SCLK_DPM_CTRL_5, SCLK_FSTATE_BOOTUP(0), ~SCLK_FSTATE_BOOTUP_MASK);
+}
+
+static void sumo_program_acpi_power_level(struct radeon_device *rdev)
+{
+	struct sumo_power_info *pi = sumo_get_pi(rdev);
+	struct atom_clock_dividers dividers;
+	int ret;
+
+        ret = radeon_atom_get_clock_dividers(rdev, COMPUTE_ENGINE_PLL_PARAM,
+                                             pi->acpi_pl.sclk,
+					     false, &dividers);
+	if (ret)
+		return;
+
+	WREG32_P(CG_ACPI_CNTL, SCLK_ACPI_DIV(dividers.post_div), ~SCLK_ACPI_DIV_MASK);
+	WREG32_P(CG_ACPI_VOLTAGE_CNTL, 0, ~ACPI_VOLTAGE_EN);
+}
+
+static void sumo_program_bootup_state(struct radeon_device *rdev)
+{
+	struct sumo_power_info *pi = sumo_get_pi(rdev);
+	u32 dpm_ctrl4 = RREG32(CG_SCLK_DPM_CTRL_4);
+	u32 i;
+
+	sumo_program_power_level(rdev, &pi->boot_pl, 0);
+
+	dpm_ctrl4 &= 0xFFFFFF00;
+	WREG32(CG_SCLK_DPM_CTRL_4, dpm_ctrl4);
+
+	for (i = 1; i < 8; i++)
+		sumo_power_level_enable(rdev, i, false);
+}
+
+static void sumo_take_smu_control(struct radeon_device *rdev, bool enable)
+{
+	u32 v = RREG32(DOUT_SCRATCH3);
+
+	if (enable)
+		v |= 0x4;
+	else
+		v &= 0xFFFFFFFB;
+
+	WREG32(DOUT_SCRATCH3, v);
+}
+
+static void sumo_enable_sclk_ds(struct radeon_device *rdev, bool enable)
+{
+	if (enable) {
+		u32 deep_sleep_cntl = RREG32(DEEP_SLEEP_CNTL);
+		u32 deep_sleep_cntl2 = RREG32(DEEP_SLEEP_CNTL2);
+		u32 t = 1;
+
+		deep_sleep_cntl &= ~R_DIS;
+		deep_sleep_cntl &= ~HS_MASK;
+		deep_sleep_cntl |= HS(t > 4095 ? 4095 : t);
+
+		deep_sleep_cntl2 |= LB_UFP_EN;
+		deep_sleep_cntl2 &= INOUT_C_MASK;
+		deep_sleep_cntl2 |= INOUT_C(0xf);
+
+		WREG32(DEEP_SLEEP_CNTL2, deep_sleep_cntl2);
+		WREG32(DEEP_SLEEP_CNTL, deep_sleep_cntl);
+	} else
+		WREG32_P(DEEP_SLEEP_CNTL, 0, ~ENABLE_DS);
+}
+
+static void sumo_program_bootup_at(struct radeon_device *rdev)
+{
+	WREG32_P(CG_AT_0, CG_R(0xffff), ~CG_R_MASK);
+	WREG32_P(CG_AT_0, CG_L(0), ~CG_L_MASK);
+}
+
+static void sumo_reset_am(struct radeon_device *rdev)
+{
+	WREG32_P(SCLK_PWRMGT_CNTL, FIR_RESET, ~FIR_RESET);
+}
+
+static void sumo_start_am(struct radeon_device *rdev)
+{
+	WREG32_P(SCLK_PWRMGT_CNTL, 0, ~FIR_RESET);
+}
+
+static void sumo_program_ttp(struct radeon_device *rdev)
+{
+	u32 xclk = sumo_get_xclk(rdev);
+	u32 p, u;
+	u32 cg_sclk_dpm_ctrl_5 = RREG32(CG_SCLK_DPM_CTRL_5);
+
+	r600_calculate_u_and_p(1000,
+			       xclk, 16, &p, &u);
+
+	cg_sclk_dpm_ctrl_5 &= ~(TT_TP_MASK | TT_TU_MASK);
+	cg_sclk_dpm_ctrl_5 |= TT_TP(p) | TT_TU(u);
+
+	WREG32(CG_SCLK_DPM_CTRL_5, cg_sclk_dpm_ctrl_5);
+}
+
+static void sumo_program_ttt(struct radeon_device *rdev)
+{
+	u32 cg_sclk_dpm_ctrl_3 = RREG32(CG_SCLK_DPM_CTRL_3);
+	struct sumo_power_info *pi = sumo_get_pi(rdev);
+
+	cg_sclk_dpm_ctrl_3 &= ~(GNB_TT_MASK | GNB_THERMTHRO_MASK);
+	cg_sclk_dpm_ctrl_3 |= GNB_TT(pi->thermal_auto_throttling + 49);
+
+	WREG32(CG_SCLK_DPM_CTRL_3, cg_sclk_dpm_ctrl_3);
+}
+
+
+static void sumo_enable_voltage_scaling(struct radeon_device *rdev, bool enable)
+{
+	if (enable) {
+		WREG32_P(CG_DPM_VOLTAGE_CNTL, DPM_VOLTAGE_EN, ~DPM_VOLTAGE_EN);
+		WREG32_P(CG_CG_VOLTAGE_CNTL, 0, ~CG_VOLTAGE_EN);
+	} else {
+		WREG32_P(CG_CG_VOLTAGE_CNTL, CG_VOLTAGE_EN, ~CG_VOLTAGE_EN);
+		WREG32_P(CG_DPM_VOLTAGE_CNTL, 0, ~DPM_VOLTAGE_EN);
+	}
+}
+
+static void sumo_override_cnb_thermal_events(struct radeon_device *rdev)
+{
+	WREG32_P(CG_SCLK_DPM_CTRL_3, CNB_THERMTHRO_MASK_SCLK,
+		 ~CNB_THERMTHRO_MASK_SCLK);
+}
+
+static void sumo_program_dc_hto(struct radeon_device *rdev)
+{
+	u32 cg_sclk_dpm_ctrl_4 = RREG32(CG_SCLK_DPM_CTRL_4);
+	u32 p, u;
+	u32 xclk = sumo_get_xclk(rdev);
+
+	r600_calculate_u_and_p(100000,
+			       xclk, 14, &p, &u);
+
+	cg_sclk_dpm_ctrl_4 &= ~(DC_HDC_MASK | DC_HU_MASK);
+	cg_sclk_dpm_ctrl_4 |= DC_HDC(p) | DC_HU(u);
+
+	WREG32(CG_SCLK_DPM_CTRL_4, cg_sclk_dpm_ctrl_4);
+}
+
+static void sumo_force_nbp_state(struct radeon_device *rdev)
+{
+	struct sumo_power_info *pi = sumo_get_pi(rdev);
+	struct sumo_ps *new_ps = sumo_get_ps(rdev->pm.dpm.requested_ps);
+
+	if (!pi->driver_nbps_policy_disable) {
+		if (new_ps->flags & SUMO_POWERSTATE_FLAGS_FORCE_NBPS1_STATE)
+			WREG32_P(CG_SCLK_DPM_CTRL_3, FORCE_NB_PSTATE_1, ~FORCE_NB_PSTATE_1);
+		else
+			WREG32_P(CG_SCLK_DPM_CTRL_3, 0, ~FORCE_NB_PSTATE_1);
+	}
+}
+
+static u32 sumo_get_sleep_divider_from_id(u32 id)
+{
+	return 1 << id;
+}
+
+static u32 sumo_get_sleep_divider_id_from_clock(struct radeon_device *rdev,
+						u32 sclk,
+						u32 min_sclk_in_sr)
+{
+	struct sumo_power_info *pi = sumo_get_pi(rdev);
+	u32 i;
+	u32 temp;
+	u32 min = (min_sclk_in_sr > SUMO_MINIMUM_ENGINE_CLOCK) ?
+		min_sclk_in_sr : SUMO_MINIMUM_ENGINE_CLOCK;
+
+	if (sclk < min)
+		return 0;
+
+	if (!pi->enable_sclk_ds)
+		return 0;
+
+	for (i = SUMO_MAX_DEEPSLEEP_DIVIDER_ID;  ; i--) {
+		temp = sclk / sumo_get_sleep_divider_from_id(i);
+
+		if (temp >= min || i == 0)
+			break;
+	}
+	return i;
+}
+
+static u32 sumo_get_valid_engine_clock(struct radeon_device *rdev,
+				       u32 lower_limit)
+{
+	struct sumo_power_info *pi = sumo_get_pi(rdev);
+	u32 i;
+
+	for (i = 0; i < pi->sys_info.sclk_voltage_mapping_table.num_max_dpm_entries; i++) {
+		if (pi->sys_info.sclk_voltage_mapping_table.entries[i].sclk_frequency >= lower_limit)
+			return pi->sys_info.sclk_voltage_mapping_table.entries[i].sclk_frequency;
+	}
+
+	return pi->sys_info.sclk_voltage_mapping_table.entries[pi->sys_info.sclk_voltage_mapping_table.num_max_dpm_entries - 1].sclk_frequency;
+}
+
+static void sumo_patch_thermal_state(struct radeon_device *rdev,
+				     struct sumo_ps *ps,
+				     struct sumo_ps *current_ps)
+{
+	struct sumo_power_info *pi = sumo_get_pi(rdev);
+	u32 sclk_in_sr = pi->sys_info.min_sclk; /* ??? */
+	u32 current_vddc;
+	u32 current_sclk;
+	u32 current_index = 0;
+
+	if (current_ps) {
+		current_vddc = current_ps->levels[current_index].vddc_index;
+		current_sclk = current_ps->levels[current_index].sclk;
+	} else {
+		current_vddc = pi->boot_pl.vddc_index;
+		current_sclk = pi->boot_pl.sclk;
+	}
+
+	ps->levels[0].vddc_index = current_vddc;
+
+	if (ps->levels[0].sclk > current_sclk)
+		ps->levels[0].sclk = current_sclk;
+
+	ps->levels[0].ss_divider_index =
+		sumo_get_sleep_divider_id_from_clock(rdev, ps->levels[0].sclk, sclk_in_sr);
+
+	ps->levels[0].ds_divider_index =
+		sumo_get_sleep_divider_id_from_clock(rdev, ps->levels[0].sclk, SUMO_MINIMUM_ENGINE_CLOCK);
+
+	if (ps->levels[0].ds_divider_index > ps->levels[0].ss_divider_index + 1)
+		ps->levels[0].ds_divider_index = ps->levels[0].ss_divider_index + 1;
+
+	if (ps->levels[0].ss_divider_index == ps->levels[0].ds_divider_index) {
+		if (ps->levels[0].ss_divider_index > 1)
+			ps->levels[0].ss_divider_index = ps->levels[0].ss_divider_index - 1;
+	}
+
+	if (ps->levels[0].ss_divider_index == 0)
+		ps->levels[0].ds_divider_index = 0;
+
+	if (ps->levels[0].ds_divider_index == 0)
+		ps->levels[0].ss_divider_index = 0;
+}
+
+static void sumo_apply_state_adjust_rules(struct radeon_device *rdev)
+{
+	struct radeon_ps *rps = rdev->pm.dpm.requested_ps;
+	struct sumo_ps *ps = sumo_get_ps(rps);
+	struct sumo_ps *current_ps = sumo_get_ps(rdev->pm.dpm.current_ps);
+	struct sumo_power_info *pi = sumo_get_pi(rdev);
+	u32 min_voltage = 0; /* ??? */
+	u32 min_sclk = pi->sys_info.min_sclk; /* XXX check against disp reqs */
+	u32 sclk_in_sr = pi->sys_info.min_sclk; /* ??? */
+	u32 i;
+
+	if (rps->class & ATOM_PPLIB_CLASSIFICATION_THERMAL)
+		return sumo_patch_thermal_state(rdev, ps, current_ps);
+
+	if (pi->enable_boost) {
+		if (rps->class & ATOM_PPLIB_CLASSIFICATION_UI_PERFORMANCE)
+			ps->flags |= SUMO_POWERSTATE_FLAGS_BOOST_STATE;
+	}
+
+	if ((rps->class & ATOM_PPLIB_CLASSIFICATION_UI_BATTERY) ||
+	    (rps->class & ATOM_PPLIB_CLASSIFICATION_SDSTATE) ||
+	    (rps->class & ATOM_PPLIB_CLASSIFICATION_HDSTATE))
+		ps->flags |= SUMO_POWERSTATE_FLAGS_FORCE_NBPS1_STATE;
+
+	for (i = 0; i < ps->num_levels; i++) {
+		if (ps->levels[i].vddc_index < min_voltage)
+			ps->levels[i].vddc_index = min_voltage;
+
+		if (ps->levels[i].sclk < min_sclk)
+			ps->levels[i].sclk =
+				sumo_get_valid_engine_clock(rdev, min_sclk);
+
+		ps->levels[i].ss_divider_index =
+			sumo_get_sleep_divider_id_from_clock(rdev, ps->levels[i].sclk, sclk_in_sr);
+
+		ps->levels[i].ds_divider_index =
+			sumo_get_sleep_divider_id_from_clock(rdev, ps->levels[i].sclk, SUMO_MINIMUM_ENGINE_CLOCK);
+
+		if (ps->levels[i].ds_divider_index > ps->levels[i].ss_divider_index + 1)
+			ps->levels[i].ds_divider_index = ps->levels[i].ss_divider_index + 1;
+
+		if (ps->levels[i].ss_divider_index == ps->levels[i].ds_divider_index) {
+			if (ps->levels[i].ss_divider_index > 1)
+				ps->levels[i].ss_divider_index = ps->levels[i].ss_divider_index - 1;
+		}
+
+		if (ps->levels[i].ss_divider_index == 0)
+			ps->levels[i].ds_divider_index = 0;
+
+		if (ps->levels[i].ds_divider_index == 0)
+			ps->levels[i].ss_divider_index = 0;
+
+		if (ps->flags & SUMO_POWERSTATE_FLAGS_FORCE_NBPS1_STATE)
+			ps->levels[i].allow_gnb_slow = 1;
+		else if ((rps->class & ATOM_PPLIB_CLASSIFICATION_UVDSTATE) ||
+			 (rps->class2 & ATOM_PPLIB_CLASSIFICATION2_MVC))
+			ps->levels[i].allow_gnb_slow = 0;
+		else if (i == ps->num_levels - 1)
+			ps->levels[i].allow_gnb_slow = 0;
+		else
+			ps->levels[i].allow_gnb_slow = 1;
+	}
+}
+
+static void sumo_cleanup_asic(struct radeon_device *rdev)
+{
+	sumo_take_smu_control(rdev, false);
+}
+
+static int sumo_set_thermal_temperature_range(struct radeon_device *rdev,
+					      int min_temp, int max_temp)
+{
+	int low_temp = 0 * 1000;
+	int high_temp = 255 * 1000;
+
+	if (low_temp < min_temp)
+		low_temp = min_temp;
+	if (high_temp > max_temp)
+		high_temp = max_temp;
+	if (high_temp < low_temp) {
+		DRM_ERROR("invalid thermal range: %d - %d\n", low_temp, high_temp);
+		return -EINVAL;
+	}
+
+	WREG32_P(CG_THERMAL_INT, DIG_THERM_INTH(49 + (high_temp / 1000)), ~DIG_THERM_INTH_MASK);
+	WREG32_P(CG_THERMAL_INT, DIG_THERM_INTL(49 + (low_temp / 1000)), ~DIG_THERM_INTL_MASK);
+
+	rdev->pm.dpm.thermal.min_temp = low_temp;
+	rdev->pm.dpm.thermal.max_temp = high_temp;
+
+	return 0;
+}
+
+int sumo_dpm_enable(struct radeon_device *rdev)
+{
+	struct sumo_power_info *pi = sumo_get_pi(rdev);
+
+	if (sumo_dpm_enabled(rdev))
+		return -EINVAL;
+
+	sumo_enable_clock_power_gating(rdev);
+	sumo_program_bootup_state(rdev);
+	sumo_init_bsp(rdev);
+	sumo_reset_am(rdev);
+	sumo_program_tp(rdev);
+	sumo_program_bootup_at(rdev);
+	sumo_start_am(rdev);
+	if (pi->enable_auto_thermal_throttling) {
+		sumo_program_ttp(rdev);
+		sumo_program_ttt(rdev);
+	}
+	sumo_program_dc_hto(rdev);
+	sumo_program_power_level_enter_state(rdev);
+	sumo_enable_voltage_scaling(rdev, true);
+	sumo_program_sstp(rdev);
+	sumo_program_vc(rdev);
+	sumo_override_cnb_thermal_events(rdev);
+	sumo_start_dpm(rdev);
+	sumo_wait_for_level_0(rdev);
+	if (pi->enable_sclk_ds)
+		sumo_enable_sclk_ds(rdev, true);
+	if (pi->enable_boost)
+		sumo_enable_boost_timer(rdev);
+
+	if (rdev->irq.installed &&
+	    r600_is_internal_thermal_sensor(rdev->pm.int_thermal_type)) {
+		sumo_set_thermal_temperature_range(rdev, R600_TEMP_RANGE_MIN, R600_TEMP_RANGE_MAX);
+		rdev->irq.dpm_thermal = true;
+		radeon_irq_set(rdev);
+	}
+
+	return 0;
+}
+
+void sumo_dpm_disable(struct radeon_device *rdev)
+{
+	struct sumo_power_info *pi = sumo_get_pi(rdev);
+
+	if (!sumo_dpm_enabled(rdev))
+		return;
+	sumo_disable_clock_power_gating(rdev);
+	if (pi->enable_sclk_ds)
+		sumo_enable_sclk_ds(rdev, false);
+	sumo_clear_vc(rdev);
+	sumo_wait_for_level_0(rdev);
+	sumo_stop_dpm(rdev);
+	sumo_enable_voltage_scaling(rdev, false);
+
+	if (rdev->irq.installed &&
+	    r600_is_internal_thermal_sensor(rdev->pm.int_thermal_type)) {
+		rdev->irq.dpm_thermal = false;
+		radeon_irq_set(rdev);
+	}
+}
+
+int sumo_dpm_set_power_state(struct radeon_device *rdev)
+{
+	struct sumo_power_info *pi = sumo_get_pi(rdev);
+
+	if (pi->enable_dynamic_patch_ps)
+		sumo_apply_state_adjust_rules(rdev);
+	sumo_update_current_power_levels(rdev);
+	if (pi->enable_boost) {
+		sumo_enable_boost(rdev, false);
+		sumo_patch_boost_state(rdev);
+	}
+	if (pi->enable_dpm) {
+		sumo_pre_notify_alt_vddnb_change(rdev);
+		sumo_enable_power_level_0(rdev);
+		sumo_set_forced_level_0(rdev);
+		sumo_set_forced_mode_enabled(rdev);
+		sumo_wait_for_level_0(rdev);
+		sumo_program_power_levels_0_to_n(rdev);
+		sumo_program_wl(rdev);
+		sumo_program_bsp(rdev);
+		sumo_program_at(rdev);
+		sumo_force_nbp_state(rdev);
+		sumo_set_forced_mode_disabled(rdev);
+		sumo_set_forced_mode_enabled(rdev);
+		sumo_set_forced_mode_disabled(rdev);
+		sumo_post_notify_alt_vddnb_change(rdev);
+	}
+	if (pi->enable_boost)
+		sumo_enable_boost(rdev, true);
+
+	return 0;
+}
+
+void sumo_dpm_reset_asic(struct radeon_device *rdev)
+{
+	sumo_program_bootup_state(rdev);
+	sumo_enable_power_level_0(rdev);
+	sumo_set_forced_level_0(rdev);
+	sumo_set_forced_mode_enabled(rdev);
+	sumo_wait_for_level_0(rdev);
+	sumo_set_forced_mode_disabled(rdev);
+	sumo_set_forced_mode_enabled(rdev);
+	sumo_set_forced_mode_disabled(rdev);
+}
+
+void sumo_dpm_setup_asic(struct radeon_device *rdev)
+{
+	struct sumo_power_info *pi = sumo_get_pi(rdev);
+
+	sumo_initialize_m3_arb(rdev);
+	pi->fw_version = sumo_get_running_fw_version(rdev);
+	DRM_INFO("Found smc ucode version: 0x%08x\n", pi->fw_version);
+	sumo_program_acpi_power_level(rdev);
+	sumo_enable_acpi_pm(rdev);
+	sumo_take_smu_control(rdev, true);
+}
+
+void sumo_dpm_display_configuration_changed(struct radeon_device *rdev)
+{
+
+}
+
+union power_info {
+	struct _ATOM_POWERPLAY_INFO info;
+	struct _ATOM_POWERPLAY_INFO_V2 info_2;
+	struct _ATOM_POWERPLAY_INFO_V3 info_3;
+	struct _ATOM_PPLIB_POWERPLAYTABLE pplib;
+	struct _ATOM_PPLIB_POWERPLAYTABLE2 pplib2;
+	struct _ATOM_PPLIB_POWERPLAYTABLE3 pplib3;
+};
+
+union pplib_clock_info {
+	struct _ATOM_PPLIB_R600_CLOCK_INFO r600;
+	struct _ATOM_PPLIB_RS780_CLOCK_INFO rs780;
+	struct _ATOM_PPLIB_EVERGREEN_CLOCK_INFO evergreen;
+	struct _ATOM_PPLIB_SUMO_CLOCK_INFO sumo;
+};
+
+union pplib_power_state {
+	struct _ATOM_PPLIB_STATE v1;
+	struct _ATOM_PPLIB_STATE_V2 v2;
+};
+
+static void sumo_patch_boot_state(struct radeon_device *rdev,
+				  struct sumo_ps *ps)
+{
+	struct sumo_power_info *pi = sumo_get_pi(rdev);
+
+	ps->num_levels = 1;
+	ps->flags = 0;
+	ps->levels[0] = pi->boot_pl;
+}
+
+static void sumo_parse_pplib_non_clock_info(struct radeon_device *rdev,
+					    struct radeon_ps *rps,
+					    struct _ATOM_PPLIB_NONCLOCK_INFO *non_clock_info,
+					    u8 table_rev)
+{
+	struct sumo_ps *ps = sumo_get_ps(rps);
+
+	rps->caps = le32_to_cpu(non_clock_info->ulCapsAndSettings);
+	rps->class = le16_to_cpu(non_clock_info->usClassification);
+	rps->class2 = le16_to_cpu(non_clock_info->usClassification2);
+
+	if (ATOM_PPLIB_NONCLOCKINFO_VER1 < table_rev) {
+		rps->vclk = le32_to_cpu(non_clock_info->ulVCLK);
+		rps->dclk = le32_to_cpu(non_clock_info->ulDCLK);
+	} else {
+		rps->vclk = 0;
+		rps->dclk = 0;
+	}
+
+	if (rps->class & ATOM_PPLIB_CLASSIFICATION_BOOT) {
+		rdev->pm.dpm.boot_ps = rps;
+		sumo_patch_boot_state(rdev, ps);
+	}
+	if (rps->class & ATOM_PPLIB_CLASSIFICATION_UVDSTATE)
+		rdev->pm.dpm.uvd_ps = rps;
+}
+
+static void sumo_parse_pplib_clock_info(struct radeon_device *rdev,
+					struct radeon_ps *rps, int index,
+					union pplib_clock_info *clock_info)
+{
+	struct sumo_power_info *pi = sumo_get_pi(rdev);
+	struct sumo_ps *ps = sumo_get_ps(rps);
+	struct sumo_pl *pl = &ps->levels[index];
+	u32 sclk;
+
+	sclk = le16_to_cpu(clock_info->sumo.usEngineClockLow);
+	sclk |= clock_info->sumo.ucEngineClockHigh << 16;
+	pl->sclk = sclk;
+	pl->vddc_index = clock_info->sumo.vddcIndex;
+	pl->sclk_dpm_tdp_limit = clock_info->sumo.tdpLimit;
+
+	ps->num_levels = index + 1;
+
+	if (pi->enable_sclk_ds) {
+		pl->ds_divider_index = 5;
+		pl->ss_divider_index = 4;
+	}
+}
+
+static int sumo_parse_power_table(struct radeon_device *rdev)
+{
+	struct radeon_mode_info *mode_info = &rdev->mode_info;
+	struct _ATOM_PPLIB_NONCLOCK_INFO *non_clock_info;
+	union pplib_power_state *power_state;
+	int i, j, k, non_clock_array_index, clock_array_index;
+	union pplib_clock_info *clock_info;
+	struct _StateArray *state_array;
+	struct _ClockInfoArray *clock_info_array;
+	struct _NonClockInfoArray *non_clock_info_array;
+	union power_info *power_info;
+	int index = GetIndexIntoMasterTable(DATA, PowerPlayInfo);
+        u16 data_offset;
+	u8 frev, crev;
+	u8 *power_state_offset;
+	struct sumo_ps *ps;
+
+	if (!atom_parse_data_header(mode_info->atom_context, index, NULL,
+				   &frev, &crev, &data_offset))
+		return -EINVAL;
+	power_info = (union power_info *)(mode_info->atom_context->bios + data_offset);
+
+	state_array = (struct _StateArray *)
+		(mode_info->atom_context->bios + data_offset +
+		 le16_to_cpu(power_info->pplib.usStateArrayOffset));
+	clock_info_array = (struct _ClockInfoArray *)
+		(mode_info->atom_context->bios + data_offset +
+		 le16_to_cpu(power_info->pplib.usClockInfoArrayOffset));
+	non_clock_info_array = (struct _NonClockInfoArray *)
+		(mode_info->atom_context->bios + data_offset +
+		 le16_to_cpu(power_info->pplib.usNonClockInfoArrayOffset));
+
+	rdev->pm.dpm.ps = kzalloc(sizeof(struct radeon_ps) *
+				  state_array->ucNumEntries, GFP_KERNEL);
+	if (!rdev->pm.dpm.ps)
+		return -ENOMEM;
+	power_state_offset = (u8 *)state_array->states;
+	rdev->pm.dpm.platform_caps = le32_to_cpu(power_info->pplib.ulPlatformCaps);
+	rdev->pm.dpm.backbias_response_time = le16_to_cpu(power_info->pplib.usBackbiasTime);
+	rdev->pm.dpm.voltage_response_time = le16_to_cpu(power_info->pplib.usVoltageTime);
+	for (i = 0; i < state_array->ucNumEntries; i++) {
+		power_state = (union pplib_power_state *)power_state_offset;
+		non_clock_array_index = power_state->v2.nonClockInfoIndex;
+		non_clock_info = (struct _ATOM_PPLIB_NONCLOCK_INFO *)
+			&non_clock_info_array->nonClockInfo[non_clock_array_index];
+		if (!rdev->pm.power_state[i].clock_info)
+			return -EINVAL;
+		ps = kzalloc(sizeof(struct sumo_ps), GFP_KERNEL);
+		if (ps == NULL) {
+			kfree(rdev->pm.dpm.ps);
+			return -ENOMEM;
+		}
+		rdev->pm.dpm.ps[i].ps_priv = ps;
+		k = 0;
+		for (j = 0; j < power_state->v2.ucNumDPMLevels; j++) {
+			clock_array_index = power_state->v2.clockInfoIndex[j];
+			if (k >= SUMO_MAX_HARDWARE_POWERLEVELS)
+				break;
+			clock_info = (union pplib_clock_info *)
+				&clock_info_array->clockInfo[clock_array_index * clock_info_array->ucEntrySize];
+			sumo_parse_pplib_clock_info(rdev,
+						    &rdev->pm.dpm.ps[i], k,
+						    clock_info);
+			k++;
+		}
+		sumo_parse_pplib_non_clock_info(rdev, &rdev->pm.dpm.ps[i],
+						non_clock_info,
+						non_clock_info_array->ucEntrySize);
+		power_state_offset += 2 + power_state->v2.ucNumDPMLevels;
+	}
+	rdev->pm.dpm.num_ps = state_array->ucNumEntries;
+	return 0;
+}
+
+static u32 sumo_convert_vid2_to_vid7(struct radeon_device *rdev, u32 vid_2bit)
+{
+	struct sumo_power_info *pi = sumo_get_pi(rdev);
+	u32 i;
+
+	for (i = 0; i < pi->sys_info.vid_mapping_table.num_entries; i++) {
+		if (pi->sys_info.vid_mapping_table.entries[i].vid_2bit == vid_2bit)
+			return pi->sys_info.vid_mapping_table.entries[i].vid_7bit;
+	}
+
+	return pi->sys_info.vid_mapping_table.entries[pi->sys_info.vid_mapping_table.num_entries - 1].vid_7bit;
+}
+
+static u16 sumo_convert_voltage_index_to_value(struct radeon_device *rdev,
+					       u32 vid_2bit)
+{
+	u32 vid_7bit = sumo_convert_vid2_to_vid7(rdev, vid_2bit);
+
+	if (vid_7bit > 0x7C)
+		return 0;
+
+	return (15500 - vid_7bit * 125 + 5) / 10;
+}
+
+static void sumo_construct_display_voltage_mapping_table(struct radeon_device *rdev,
+							 ATOM_CLK_VOLT_CAPABILITY *table)
+{
+	struct sumo_power_info *pi = sumo_get_pi(rdev);
+	u32 i;
+
+	for (i = 0; i < SUMO_MAX_NUMBER_VOLTAGES; i++) {
+		if (table[i].ulMaximumSupportedCLK == 0)
+			break;
+
+		pi->sys_info.disp_clk_voltage_mapping_table.display_clock_frequency[i] =
+			table[i].ulMaximumSupportedCLK;
+	}
+
+	pi->sys_info.disp_clk_voltage_mapping_table.num_max_voltage_levels = i;
+
+	if (pi->sys_info.disp_clk_voltage_mapping_table.num_max_voltage_levels == 0) {
+		pi->sys_info.disp_clk_voltage_mapping_table.display_clock_frequency[0] = 80000;
+		pi->sys_info.disp_clk_voltage_mapping_table.num_max_voltage_levels = 1;
+	}
+}
+
+static void sumo_construct_sclk_voltage_mapping_table(struct radeon_device *rdev,
+						      ATOM_AVAILABLE_SCLK_LIST *table)
+{
+	struct sumo_power_info *pi = sumo_get_pi(rdev);
+	u32 i;
+	u32 n = 0;
+	u32 prev_sclk = 0;
+
+	for (i = 0; i < SUMO_MAX_HARDWARE_POWERLEVELS; i++) {
+		if (table[i].ulSupportedSCLK > prev_sclk) {
+			pi->sys_info.sclk_voltage_mapping_table.entries[n].sclk_frequency =
+				table[i].ulSupportedSCLK;
+			pi->sys_info.sclk_voltage_mapping_table.entries[n].vid_2bit =
+				table[i].usVoltageIndex;
+			prev_sclk = table[i].ulSupportedSCLK;
+			n++;
+		}
+	}
+
+	pi->sys_info.sclk_voltage_mapping_table.num_max_dpm_entries = n;
+}
+
+static void sumo_construct_vid_mapping_table(struct radeon_device *rdev,
+					     ATOM_AVAILABLE_SCLK_LIST *table)
+{
+	struct sumo_power_info *pi = sumo_get_pi(rdev);
+	u32 i, j;
+
+	for (i = 0; i < SUMO_MAX_HARDWARE_POWERLEVELS; i++) {
+		if (table[i].ulSupportedSCLK != 0) {
+			pi->sys_info.vid_mapping_table.entries[table[i].usVoltageIndex].vid_7bit =
+				table[i].usVoltageID;
+			pi->sys_info.vid_mapping_table.entries[table[i].usVoltageIndex].vid_2bit =
+				table[i].usVoltageIndex;
+		}
+	}
+
+	for (i = 0; i < SUMO_MAX_NUMBER_VOLTAGES; i++) {
+		if (pi->sys_info.vid_mapping_table.entries[i].vid_7bit == 0) {
+			for (j = i + 1; j < SUMO_MAX_NUMBER_VOLTAGES; j++) {
+				if (pi->sys_info.vid_mapping_table.entries[j].vid_7bit != 0) {
+					pi->sys_info.vid_mapping_table.entries[i] =
+						pi->sys_info.vid_mapping_table.entries[j];
+					pi->sys_info.vid_mapping_table.entries[j].vid_7bit = 0;
+					break;
+				}
+			}
+
+			if (j == SUMO_MAX_NUMBER_VOLTAGES)
+				break;
+		}
+	}
+
+	pi->sys_info.vid_mapping_table.num_entries = i;
+}
+
+union igp_info {
+	struct _ATOM_INTEGRATED_SYSTEM_INFO info;
+	struct _ATOM_INTEGRATED_SYSTEM_INFO_V2 info_2;
+	struct _ATOM_INTEGRATED_SYSTEM_INFO_V5 info_5;
+	struct _ATOM_INTEGRATED_SYSTEM_INFO_V6 info_6;
+};
+
+static int sumo_parse_sys_info_table(struct radeon_device *rdev)
+{
+	struct sumo_power_info *pi = sumo_get_pi(rdev);
+	struct radeon_mode_info *mode_info = &rdev->mode_info;
+	int index = GetIndexIntoMasterTable(DATA, IntegratedSystemInfo);
+	union igp_info *igp_info;
+	u8 frev, crev;
+	u16 data_offset;
+	int i;
+
+	if (atom_parse_data_header(mode_info->atom_context, index, NULL,
+				   &frev, &crev, &data_offset)) {
+		igp_info = (union igp_info *)(mode_info->atom_context->bios +
+					      data_offset);
+
+		if (crev != 6) {
+			DRM_ERROR("Unsupported IGP table: %d %d\n", frev, crev);
+			return -EINVAL;
+		}
+		pi->sys_info.bootup_sclk = le32_to_cpu(igp_info->info_6.ulBootUpEngineClock);
+		pi->sys_info.min_sclk = le32_to_cpu(igp_info->info_6.ulMinEngineClock);
+		pi->sys_info.bootup_uma_clk = le32_to_cpu(igp_info->info_6.ulBootUpUMAClock);
+		pi->sys_info.bootup_nb_voltage_index =
+			le16_to_cpu(igp_info->info_6.usBootUpNBVoltage);
+		if (igp_info->info_6.ucHtcTmpLmt == 0)
+			pi->sys_info.htc_tmp_lmt = 203;
+		else
+			pi->sys_info.htc_tmp_lmt = igp_info->info_6.ucHtcTmpLmt;
+		if (igp_info->info_6.ucHtcHystLmt == 0)
+			pi->sys_info.htc_hyst_lmt = 5;
+		else
+			pi->sys_info.htc_hyst_lmt = igp_info->info_6.ucHtcHystLmt;
+		if (pi->sys_info.htc_tmp_lmt <= pi->sys_info.htc_hyst_lmt) {
+			DRM_ERROR("The htcTmpLmt should be larger than htcHystLmt.\n");
+		}
+		for (i = 0; i < NUMBER_OF_M3ARB_PARAM_SETS; i++) {
+			pi->sys_info.csr_m3_arb_cntl_default[i] =
+				le32_to_cpu(igp_info->info_6.ulCSR_M3_ARB_CNTL_DEFAULT[i]);
+			pi->sys_info.csr_m3_arb_cntl_uvd[i] =
+				le32_to_cpu(igp_info->info_6.ulCSR_M3_ARB_CNTL_UVD[i]);
+			pi->sys_info.csr_m3_arb_cntl_fs3d[i] =
+				le32_to_cpu(igp_info->info_6.ulCSR_M3_ARB_CNTL_FS3D[i]);
+		}
+		pi->sys_info.sclk_dpm_boost_margin =
+			le32_to_cpu(igp_info->info_6.SclkDpmBoostMargin);
+		pi->sys_info.sclk_dpm_throttle_margin =
+			le32_to_cpu(igp_info->info_6.SclkDpmThrottleMargin);
+		pi->sys_info.sclk_dpm_tdp_limit_pg =
+			le16_to_cpu(igp_info->info_6.SclkDpmTdpLimitPG);
+		pi->sys_info.gnb_tdp_limit = le16_to_cpu(igp_info->info_6.GnbTdpLimit);
+		pi->sys_info.sclk_dpm_tdp_limit_boost =
+			le16_to_cpu(igp_info->info_6.SclkDpmTdpLimitBoost);
+		pi->sys_info.boost_sclk = le32_to_cpu(igp_info->info_6.ulBoostEngineCLock);
+		pi->sys_info.boost_vid_2bit = igp_info->info_6.ulBoostVid_2bit;
+		if (igp_info->info_6.EnableBoost)
+			pi->sys_info.enable_boost = true;
+		else
+			pi->sys_info.enable_boost = false;
+		sumo_construct_display_voltage_mapping_table(rdev,
+							     igp_info->info_6.sDISPCLK_Voltage);
+		sumo_construct_sclk_voltage_mapping_table(rdev,
+							  igp_info->info_6.sAvail_SCLK);
+		sumo_construct_vid_mapping_table(rdev, igp_info->info_6.sAvail_SCLK);
+
+	}
+	return 0;
+}
+
+static void sumo_construct_boot_and_acpi_state(struct radeon_device *rdev)
+{
+	struct sumo_power_info *pi = sumo_get_pi(rdev);
+
+	pi->boot_pl.sclk = pi->sys_info.bootup_sclk;
+	pi->boot_pl.vddc_index = pi->sys_info.bootup_nb_voltage_index;
+	pi->boot_pl.ds_divider_index = 0;
+	pi->boot_pl.ss_divider_index = 0;
+	pi->boot_pl.allow_gnb_slow = 1;
+	pi->acpi_pl = pi->boot_pl;
+	pi->current_ps.num_levels = 1;
+	pi->current_ps.levels[0] = pi->boot_pl;
+}
+
+int sumo_dpm_init(struct radeon_device *rdev)
+{
+	struct sumo_power_info *pi;
+	u32 hw_rev = (RREG32(HW_REV) & ATI_REV_ID_MASK) >> ATI_REV_ID_SHIFT;
+	int ret;
+
+	pi = kzalloc(sizeof(struct sumo_power_info), GFP_KERNEL);
+	if (pi == NULL)
+		return -ENOMEM;
+	rdev->pm.dpm.priv = pi;
+
+	pi->driver_nbps_policy_disable = false;
+	if ((rdev->family == CHIP_PALM) && (hw_rev < 3))
+		pi->disable_gfx_power_gating_in_uvd = true;
+	else
+		pi->disable_gfx_power_gating_in_uvd = false;
+	pi->enable_alt_vddnb = true;
+	pi->enable_sclk_ds = true;
+	pi->enable_dynamic_m3_arbiter = false;
+	pi->enable_dynamic_patch_ps = true;
+	pi->enable_gfx_power_gating = true;
+	pi->enable_gfx_clock_gating = true;
+	pi->enable_mg_clock_gating = true;
+	pi->enable_auto_thermal_throttling = true;
+
+	ret = sumo_parse_sys_info_table(rdev);
+	if (ret)
+		return ret;
+
+	sumo_construct_boot_and_acpi_state(rdev);
+
+	ret = sumo_parse_power_table(rdev);
+	if (ret)
+		return ret;
+
+	pi->pasi = CYPRESS_HASI_DFLT;
+	pi->asi = RV770_ASI_DFLT;
+	pi->thermal_auto_throttling = pi->sys_info.htc_tmp_lmt;
+	pi->enable_boost = pi->sys_info.enable_boost;
+	pi->enable_dpm = true;
+
+	return 0;
+}
+
+void sumo_dpm_print_power_state(struct radeon_device *rdev,
+				struct radeon_ps *rps)
+{
+	int i;
+	struct sumo_ps *ps = sumo_get_ps(rps);
+
+	r600_dpm_print_class_info(rps->class, rps->class2);
+	r600_dpm_print_cap_info(rps->caps);
+	printk("\tuvd    vclk: %d dclk: %d\n", rps->vclk, rps->dclk);
+	for (i = 0; i < ps->num_levels; i++) {
+		struct sumo_pl *pl = &ps->levels[i];
+		printk("\t\tpower level %d    sclk: %u vddc: %u\n",
+		       i, pl->sclk,
+		       sumo_convert_voltage_index_to_value(rdev, pl->vddc_index));
+	}
+	r600_dpm_print_ps_status(rdev, rps);
+}
+
+void sumo_dpm_fini(struct radeon_device *rdev)
+{
+	int i;
+
+	sumo_cleanup_asic(rdev); /* ??? */
+
+	for (i = 0; i < rdev->pm.dpm.num_ps; i++) {
+		kfree(rdev->pm.dpm.ps[i].ps_priv);
+	}
+	kfree(rdev->pm.dpm.ps);
+	kfree(rdev->pm.dpm.priv);
+}
+
+u32 sumo_dpm_get_sclk(struct radeon_device *rdev, bool low)
+{
+	struct sumo_ps *requested_state = sumo_get_ps(rdev->pm.dpm.requested_ps);
+
+	if (low)
+		return requested_state->levels[0].sclk;
+	else
+		return requested_state->levels[requested_state->num_levels - 1].sclk;
+}
+
+u32 sumo_dpm_get_mclk(struct radeon_device *rdev, bool low)
+{
+	struct sumo_power_info *pi = sumo_get_pi(rdev);
+
+	return pi->sys_info.bootup_uma_clk;
+}
drivers/gpu/drm/radeon/sumo_dpm.h new file +199 -0
new file mode 100644
index 0000000..561bee1
@@ -0,0 +1,199 @@
+/*
+ * Copyright 2012 Advanced Micro Devices, Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ */
+#ifndef __SUMO_DPM_H__
+#define __SUMO_DPM_H__
+
+#define SUMO_MAX_HARDWARE_POWERLEVELS 5
+#define SUMO_PM_NUMBER_OF_TC 15
+
+struct sumo_pl {
+	u32 sclk;
+	u32 vddc_index;
+	u32 ds_divider_index;
+	u32 ss_divider_index;
+	u32 allow_gnb_slow;
+	u32 sclk_dpm_tdp_limit;
+};
+
+/* used for the flags field */
+#define SUMO_POWERSTATE_FLAGS_FORCE_NBPS1_STATE (1 << 0)
+#define SUMO_POWERSTATE_FLAGS_BOOST_STATE       (1 << 1)
+
+struct sumo_ps {
+	struct sumo_pl levels[SUMO_MAX_HARDWARE_POWERLEVELS];
+	u32 num_levels;
+	/* flags */
+	u32 flags;
+};
+
+#define NUMBER_OF_M3ARB_PARAM_SETS 10
+#define SUMO_MAX_NUMBER_VOLTAGES    4
+
+struct sumo_disp_clock_voltage_mapping_table {
+	u32 num_max_voltage_levels;
+	u32 display_clock_frequency[SUMO_MAX_NUMBER_VOLTAGES];
+};
+
+struct sumo_vid_mapping_entry {
+	u16 vid_2bit;
+	u16 vid_7bit;
+};
+
+struct sumo_vid_mapping_table {
+	u32 num_entries;
+	struct sumo_vid_mapping_entry entries[SUMO_MAX_NUMBER_VOLTAGES];
+};
+
+struct sumo_sclk_voltage_mapping_entry {
+	u32 sclk_frequency;
+	u16 vid_2bit;
+	u16 rsv;
+};
+
+struct sumo_sclk_voltage_mapping_table {
+	u32 num_max_dpm_entries;
+	struct sumo_sclk_voltage_mapping_entry entries[SUMO_MAX_HARDWARE_POWERLEVELS];
+};
+
+struct sumo_sys_info {
+	u32 bootup_sclk;
+	u32 min_sclk;
+	u32 bootup_uma_clk;
+	u16 bootup_nb_voltage_index;
+	u8 htc_tmp_lmt;
+	u8 htc_hyst_lmt;
+	struct sumo_sclk_voltage_mapping_table sclk_voltage_mapping_table;
+	struct sumo_disp_clock_voltage_mapping_table disp_clk_voltage_mapping_table;
+	struct sumo_vid_mapping_table vid_mapping_table;
+	u32 csr_m3_arb_cntl_default[NUMBER_OF_M3ARB_PARAM_SETS];
+	u32 csr_m3_arb_cntl_uvd[NUMBER_OF_M3ARB_PARAM_SETS];
+	u32 csr_m3_arb_cntl_fs3d[NUMBER_OF_M3ARB_PARAM_SETS];
+	u32 sclk_dpm_boost_margin;
+	u32 sclk_dpm_throttle_margin;
+	u32 sclk_dpm_tdp_limit_pg;
+	u32 gnb_tdp_limit;
+	u32 sclk_dpm_tdp_limit_boost;
+	u32 boost_sclk;
+	u32 boost_vid_2bit;
+	bool enable_boost;
+};
+
+struct sumo_power_info {
+	u32 asi;
+	u32 pasi;
+	u32 bsp;
+	u32 bsu;
+	u32 pbsp;
+	u32 pbsu;
+	u32 dsp;
+	u32 psp;
+	u32 thermal_auto_throttling;
+	u32 uvd_m3_arbiter;
+	u32 fw_version;
+	struct sumo_sys_info sys_info;
+	struct sumo_pl acpi_pl;
+	struct sumo_pl boot_pl;
+	struct sumo_pl boost_pl;
+	struct sumo_ps current_ps;
+	bool disable_gfx_power_gating_in_uvd;
+	bool driver_nbps_policy_disable;
+	bool enable_alt_vddnb;
+	bool enable_dynamic_m3_arbiter;
+	bool enable_gfx_clock_gating;
+	bool enable_gfx_power_gating;
+	bool enable_mg_clock_gating;
+	bool enable_sclk_ds;
+	bool enable_auto_thermal_throttling;
+	bool enable_dynamic_patch_ps;
+	bool enable_dpm;
+	bool enable_boost;
+};
+
+#define SUMO_UTC_DFLT_00                     0x48
+#define SUMO_UTC_DFLT_01                     0x44
+#define SUMO_UTC_DFLT_02                     0x44
+#define SUMO_UTC_DFLT_03                     0x44
+#define SUMO_UTC_DFLT_04                     0x44
+#define SUMO_UTC_DFLT_05                     0x44
+#define SUMO_UTC_DFLT_06                     0x44
+#define SUMO_UTC_DFLT_07                     0x44
+#define SUMO_UTC_DFLT_08                     0x44
+#define SUMO_UTC_DFLT_09                     0x44
+#define SUMO_UTC_DFLT_10                     0x44
+#define SUMO_UTC_DFLT_11                     0x44
+#define SUMO_UTC_DFLT_12                     0x44
+#define SUMO_UTC_DFLT_13                     0x44
+#define SUMO_UTC_DFLT_14                     0x44
+
+#define SUMO_DTC_DFLT_00                     0x48
+#define SUMO_DTC_DFLT_01                     0x44
+#define SUMO_DTC_DFLT_02                     0x44
+#define SUMO_DTC_DFLT_03                     0x44
+#define SUMO_DTC_DFLT_04                     0x44
+#define SUMO_DTC_DFLT_05                     0x44
+#define SUMO_DTC_DFLT_06                     0x44
+#define SUMO_DTC_DFLT_07                     0x44
+#define SUMO_DTC_DFLT_08                     0x44
+#define SUMO_DTC_DFLT_09                     0x44
+#define SUMO_DTC_DFLT_10                     0x44
+#define SUMO_DTC_DFLT_11                     0x44
+#define SUMO_DTC_DFLT_12                     0x44
+#define SUMO_DTC_DFLT_13                     0x44
+#define SUMO_DTC_DFLT_14                     0x44
+
+#define SUMO_AH_DFLT               5
+
+#define SUMO_R_DFLT0               70
+#define SUMO_R_DFLT1               70
+#define SUMO_R_DFLT2               70
+#define SUMO_R_DFLT3               70
+#define SUMO_R_DFLT4               100
+
+#define SUMO_L_DFLT0               0
+#define SUMO_L_DFLT1               20
+#define SUMO_L_DFLT2               20
+#define SUMO_L_DFLT3               20
+#define SUMO_L_DFLT4               20
+#define SUMO_VRC_DFLT              0x30033
+#define SUMO_MGCGTTLOCAL0_DFLT     0
+#define SUMO_MGCGTTLOCAL1_DFLT     0
+#define SUMO_GICST_DFLT            19
+#define SUMO_SST_DFLT              8
+#define SUMO_VOLTAGEDROPT_DFLT     1
+#define SUMO_GFXPOWERGATINGT_DFLT  100
+
+/* sumo_dpm.c */
+u32 sumo_get_xclk(struct radeon_device *rdev);
+
+
+/* sumo_smc.c */
+void sumo_initialize_m3_arb(struct radeon_device *rdev);
+void sumo_smu_pg_init(struct radeon_device *rdev);
+void sumo_set_tdp_limit(struct radeon_device *rdev, u32 index, u32 tdp_limit);
+void sumo_smu_notify_alt_vddnb_change(struct radeon_device *rdev,
+				      bool powersaving, bool force_nbps1);
+void sumo_boost_state_enable(struct radeon_device *rdev, bool enable);
+void sumo_enable_boost_timer(struct radeon_device *rdev);
+u32 sumo_get_running_fw_version(struct radeon_device *rdev);
+
+#endif
drivers/gpu/drm/radeon/sumo_smc.c new file +167 -0
new file mode 100644
index 0000000..9d0ae9b
@@ -0,0 +1,224 @@
+/*
+ * Copyright 2012 Advanced Micro Devices, Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ */
+
+#include <linux/firmware.h>
+#include "drmP.h"
+#include "radeon.h"
+#include "sumod.h"
+#include "sumo_dpm.h"
+#include "ppsmc.h"
+#include "radeon_ucode.h"
+
+#define SUMO_SMU_SERVICE_ROUTINE_PG_INIT        1
+#define SUMO_SMU_SERVICE_ROUTINE_ALTVDDNB_NOTIFY  27
+#define SUMO_SMU_SERVICE_ROUTINE_GFX_SRV_ID_20  20
+
+struct sumo_ps *sumo_get_ps(struct radeon_ps *rps);
+struct sumo_power_info *sumo_get_pi(struct radeon_device *rdev);
+
+static void sumo_send_msg_to_smu(struct radeon_device *rdev, u32 id)
+{
+	u32 gfx_int_req;
+	int i;
+
+	for (i = 0; i < rdev->usec_timeout; i++) {
+		if (RREG32(GFX_INT_STATUS) & INT_DONE)
+			break;
+		udelay(1);
+	}
+
+	gfx_int_req = SERV_INDEX(id) | INT_REQ;
+	WREG32(GFX_INT_REQ, gfx_int_req);
+
+	for (i = 0; i < rdev->usec_timeout; i++) {
+		if (RREG32(GFX_INT_REQ) & INT_REQ)
+			break;
+		udelay(1);
+	}
+
+	for (i = 0; i < rdev->usec_timeout; i++) {
+		if (RREG32(GFX_INT_STATUS) & INT_ACK)
+			break;
+		udelay(1);
+	}
+
+	for (i = 0; i < rdev->usec_timeout; i++) {
+		if (RREG32(GFX_INT_STATUS) & INT_DONE)
+			break;
+		udelay(1);
+	}
+
+	gfx_int_req &= ~INT_REQ;
+	WREG32(GFX_INT_REQ, gfx_int_req);
+}
+
+void sumo_initialize_m3_arb(struct radeon_device *rdev)
+{
+	struct sumo_power_info *pi = sumo_get_pi(rdev);
+	u32 i;
+
+	if (!pi->enable_dynamic_m3_arbiter)
+		return;
+
+	for (i = 0; i < NUMBER_OF_M3ARB_PARAM_SETS; i++)
+		WREG32_RCU(MCU_M3ARB_PARAMS + (i * 4),
+			   pi->sys_info.csr_m3_arb_cntl_default[i]);
+
+	for (; i < NUMBER_OF_M3ARB_PARAM_SETS * 2; i++)
+		WREG32_RCU(MCU_M3ARB_PARAMS + (i * 4),
+			   pi->sys_info.csr_m3_arb_cntl_uvd[i % NUMBER_OF_M3ARB_PARAM_SETS]);
+
+	for (; i < NUMBER_OF_M3ARB_PARAM_SETS * 3; i++)
+		WREG32_RCU(MCU_M3ARB_PARAMS + (i * 4),
+			   pi->sys_info.csr_m3_arb_cntl_fs3d[i % NUMBER_OF_M3ARB_PARAM_SETS]);
+}
+
+static bool sumo_is_alt_vddnb_supported(struct radeon_device *rdev)
+{
+	struct sumo_power_info *pi = sumo_get_pi(rdev);
+	bool return_code = false;
+
+	if (!pi->enable_alt_vddnb)
+		return return_code;
+
+	if ((rdev->family == CHIP_SUMO) || (rdev->family == CHIP_SUMO2)) {
+		if (pi->fw_version >= 0x00010C00)
+			return_code = true;
+	}
+
+	return return_code;
+}
+
+void sumo_smu_notify_alt_vddnb_change(struct radeon_device *rdev,
+				      bool powersaving, bool force_nbps1)
+{
+	u32 param = 0;
+
+	if (!sumo_is_alt_vddnb_supported(rdev))
+		return;
+
+	if (powersaving)
+		param |= 1;
+
+	if (force_nbps1)
+		param |= 2;
+
+	WREG32_RCU(RCU_ALTVDDNB_NOTIFY, param);
+
+	sumo_send_msg_to_smu(rdev, SUMO_SMU_SERVICE_ROUTINE_ALTVDDNB_NOTIFY);
+}
+
+void sumo_smu_pg_init(struct radeon_device *rdev)
+{
+	sumo_send_msg_to_smu(rdev, SUMO_SMU_SERVICE_ROUTINE_PG_INIT);
+}
+
+static u32 sumo_power_of_4(u32 unit)
+{
+	u32 ret = 1;
+	u32 i;
+
+	for (i = 0; i < unit; i++)
+		ret *= 4;
+
+	return ret;
+}
+
+void sumo_enable_boost_timer(struct radeon_device *rdev)
+{
+	struct sumo_power_info *pi = sumo_get_pi(rdev);
+	u32 period, unit, timer_value;
+	u32 xclk = sumo_get_xclk(rdev);
+
+	unit = (RREG32_RCU(RCU_LCLK_SCALING_CNTL) & LCLK_SCALING_TIMER_PRESCALER_MASK)
+		>> LCLK_SCALING_TIMER_PRESCALER_SHIFT;
+
+	period = 100 * (xclk / 100 / sumo_power_of_4(unit));
+
+	timer_value = (period << 16) | (unit << 4);
+
+	WREG32_RCU(RCU_GNB_PWR_REP_TIMER_CNTL, timer_value);
+	WREG32_RCU(RCU_BOOST_MARGIN, pi->sys_info.sclk_dpm_boost_margin);
+	WREG32_RCU(RCU_THROTTLE_MARGIN, pi->sys_info.sclk_dpm_throttle_margin);
+	WREG32_RCU(GNB_TDP_LIMIT, pi->sys_info.gnb_tdp_limit);
+	WREG32_RCU(RCU_SclkDpmTdpLimitPG, pi->sys_info.sclk_dpm_tdp_limit_pg);
+
+	sumo_send_msg_to_smu(rdev, SUMO_SMU_SERVICE_ROUTINE_GFX_SRV_ID_20);
+}

drivers/gpu/drm/radeon/sumo_smc.c line 177

Quoted 10 lines
drivers/gpu/drm/radeon/sumo_smc.c new file +10 -0
+
+void sumo_set_tdp_limit(struct radeon_device *rdev, u32 index, u32 tdp_limit)
+{
+	u32 regoffset = 0;
+	u32 shift = 0;
+	u32 mask = 0xFFF;
+	u32 sclk_dpm_tdp_limit;
+
+	switch (index) {
+        case 0:

Indentation issue (space instead of tab) same issue for all case below.

Quoted 422 lines
drivers/gpu/drm/radeon/sumo_smc.c new file +47 -0
+		regoffset = RCU_SclkDpmTdpLimit01;
+		shift = 16;
+		break;
+        case 1:
+		regoffset = RCU_SclkDpmTdpLimit01;
+		shift = 0;
+		break;
+        case 2:
+		regoffset = RCU_SclkDpmTdpLimit23;
+		shift = 16;
+		break;
+        case 3:
+		regoffset = RCU_SclkDpmTdpLimit23;
+		shift = 0;
+		break;
+        case 4:
+		regoffset = RCU_SclkDpmTdpLimit47;
+		shift = 16;
+		break;
+        case 7:
+		regoffset = RCU_SclkDpmTdpLimit47;
+		shift = 0;
+		break;
+        default:
+		break;
+	}
+
+	sclk_dpm_tdp_limit = RREG32_RCU(regoffset);
+	sclk_dpm_tdp_limit &= ~(mask << shift);
+	sclk_dpm_tdp_limit |= (tdp_limit << shift);
+	WREG32_RCU(regoffset, sclk_dpm_tdp_limit);
+}
+
+void sumo_boost_state_enable(struct radeon_device *rdev, bool enable)
+{
+	u32 boost_disable = RREG32_RCU(RCU_GPU_BOOST_DISABLE);
+
+	boost_disable &= 0xFFFFFFFE;
+	boost_disable |= (enable ? 0 : 1);
+	WREG32_RCU(RCU_GPU_BOOST_DISABLE, boost_disable);
+}
+
+u32 sumo_get_running_fw_version(struct radeon_device *rdev)
+{
+	return RREG32_RCU(RCU_FW_VERSION);
+}
+
drivers/gpu/drm/radeon/sumod.h new file +362 -0
new file mode 100644
index 0000000..a5deba6
@@ -0,0 +1,362 @@
+/*
+ * Copyright 2012 Advanced Micro Devices, Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: Alex Deucher
+ */
+#ifndef _SUMOD_H_
+#define _SUMOD_H_
+
+/* pm registers */
+
+/* rcu */
+#define RCU_FW_VERSION                                  0x30c
+
+#define RCU_PWR_GATING_SEQ0                             0x408
+#define RCU_PWR_GATING_SEQ1                             0x40c
+#define RCU_PWR_GATING_CNTL                             0x410
+#       define PWR_GATING_EN                            (1 << 0)
+#       define RSVD_MASK                                (0x3 << 1)
+#       define PCV(x)                                   ((x) << 3)
+#       define PCV_MASK                                 (0x1f << 3)
+#       define PCV_SHIFT                                3
+#       define PCP(x)                                   ((x) << 8)
+#       define PCP_MASK                                 (0xf << 8)
+#       define PCP_SHIFT                                8
+#       define RPW(x)                                   ((x) << 16)
+#       define RPW_MASK                                 (0xf << 16)
+#       define RPW_SHIFT                                16
+#       define ID(x)                                    ((x) << 24)
+#       define ID_MASK                                  (0xf << 24)
+#       define ID_SHIFT                                 24
+#       define PGS(x)                                   ((x) << 28)
+#       define PGS_MASK                                 (0xf << 28)
+#       define PGS_SHIFT                                28
+
+#define RCU_ALTVDDNB_NOTIFY                             0x430
+#define RCU_LCLK_SCALING_CNTL                           0x434
+#       define LCLK_SCALING_EN                          (1 << 0)
+#       define LCLK_SCALING_TYPE                        (1 << 1)
+#       define LCLK_SCALING_TIMER_PRESCALER(x)          ((x) << 4)
+#       define LCLK_SCALING_TIMER_PRESCALER_MASK        (0xf << 4)
+#       define LCLK_SCALING_TIMER_PRESCALER_SHIFT       4
+#       define LCLK_SCALING_TIMER_PERIOD(x)             ((x) << 16)
+#       define LCLK_SCALING_TIMER_PERIOD_MASK           (0xf << 16)
+#       define LCLK_SCALING_TIMER_PERIOD_SHIFT          16
+
+#define RCU_PWR_GATING_CNTL_2                           0x4a0
+#       define MPPU(x)                                  ((x) << 0)
+#       define MPPU_MASK                                (0xffff << 0)
+#       define MPPU_SHIFT                               0
+#       define MPPD(x)                                  ((x) << 16)
+#       define MPPD_MASK                                (0xffff << 16)
+#       define MPPD_SHIFT                               16
+#define RCU_PWR_GATING_CNTL_3                           0x4a4
+#       define DPPU(x)                                  ((x) << 0)
+#       define DPPU_MASK                                (0xffff << 0)
+#       define DPPU_SHIFT                               0
+#       define DPPD(x)                                  ((x) << 16)
+#       define DPPD_MASK                                (0xffff << 16)
+#       define DPPD_SHIFT                               16
+#define RCU_PWR_GATING_CNTL_4                           0x4a8
+#       define RT(x)                                    ((x) << 0)
+#       define RT_MASK                                  (0xffff << 0)
+#       define RT_SHIFT                                 0
+#       define IT(x)                                    ((x) << 16)
+#       define IT_MASK                                  (0xffff << 16)
+#       define IT_SHIFT                                 16
+
+/* yes these two have the same address */
+#define RCU_PWR_GATING_CNTL_5                           0x504
+#define RCU_GPU_BOOST_DISABLE                           0x508
+
+#define MCU_M3ARB_INDEX                                 0x504
+#define MCU_M3ARB_PARAMS                                0x508
+
+#define RCU_GNB_PWR_REP_TIMER_CNTL                      0x50C
+
+#define RCU_SclkDpmTdpLimit01                           0x514
+#define RCU_SclkDpmTdpLimit23                           0x518
+#define RCU_SclkDpmTdpLimit47                           0x51C
+#define RCU_SclkDpmTdpLimitPG                           0x520
+
+#define GNB_TDP_LIMIT                                   0x540
+#define RCU_BOOST_MARGIN                                0x544
+#define RCU_THROTTLE_MARGIN                             0x548
+
+#define SMU_PCIE_PG_ARGS                                0x58C
+#define SMU_PCIE_PG_ARGS_2                              0x598
+#define SMU_PCIE_PG_ARGS_3                              0x59C
+
+/* mmio */
+#define RCU_STATUS                                      0x11c
+#       define GMC_PWR_GATER_BUSY                       (1 << 8)
+#       define GFX_PWR_GATER_BUSY                       (1 << 9)
+#       define UVD_PWR_GATER_BUSY                       (1 << 10)
+#       define PCIE_PWR_GATER_BUSY                      (1 << 11)
+#       define GMC_PWR_GATER_STATE                      (1 << 12)
+#       define GFX_PWR_GATER_STATE                      (1 << 13)
+#       define UVD_PWR_GATER_STATE                      (1 << 14)
+#       define PCIE_PWR_GATER_STATE                     (1 << 15)
+#       define GFX1_PWR_GATER_BUSY                      (1 << 16)
+#       define GFX2_PWR_GATER_BUSY                      (1 << 17)
+#       define GFX1_PWR_GATER_STATE                     (1 << 18)
+#       define GFX2_PWR_GATER_STATE                     (1 << 19)
+
+#define GFX_INT_REQ                                     0x120
+#       define INT_REQ                                  (1 << 0)
+#       define SERV_INDEX(x)                            ((x) << 1)
+#       define SERV_INDEX_MASK                          (0xff << 1)
+#       define SERV_INDEX_SHIFT                         1
+#define GFX_INT_STATUS                                  0x124
+#       define INT_ACK                                  (1 << 0)
+#       define INT_DONE                                 (1 << 1)
+
+#define CG_SCLK_CNTL                                    0x600
+#       define SCLK_DIVIDER(x)                          ((x) << 0)
+#       define SCLK_DIVIDER_MASK                        (0x7f << 0)
+#       define SCLK_DIVIDER_SHIFT                       0
+#define CG_SCLK_STATUS                                  0x604
+#       define SCLK_OVERCLK_DETECT                      (1 << 2)
+
+#define GENERAL_PWRMGT                                  0x63c
+#       define STATIC_PM_EN                             (1 << 1)
+
+#define SCLK_PWRMGT_CNTL                                0x644
+#       define SCLK_PWRMGT_OFF                          (1 << 0)
+#       define SCLK_LOW_D1                              (1 << 1)
+#       define FIR_RESET                                (1 << 4)
+#       define FIR_FORCE_TREND_SEL                      (1 << 5)
+#       define FIR_TREND_MODE                           (1 << 6)
+#       define DYN_GFX_CLK_OFF_EN                       (1 << 7)
+#       define GFX_CLK_FORCE_ON                         (1 << 8)
+#       define GFX_CLK_REQUEST_OFF                      (1 << 9)
+#       define GFX_CLK_FORCE_OFF                        (1 << 10)
+#       define GFX_CLK_OFF_ACPI_D1                      (1 << 11)
+#       define GFX_CLK_OFF_ACPI_D2                      (1 << 12)
+#       define GFX_CLK_OFF_ACPI_D3                      (1 << 13)
+#       define GFX_VOLTAGE_CHANGE_EN                    (1 << 16)
+#       define GFX_VOLTAGE_CHANGE_MODE                  (1 << 17)
+
+#define TARGET_AND_CURRENT_PROFILE_INDEX                0x66c
+#       define TARG_SCLK_INDEX(x)                       ((x) << 6)
+#       define TARG_SCLK_INDEX_MASK                     (0x7 << 6)
+#       define TARG_SCLK_INDEX_SHIFT                    6
+#       define CURR_SCLK_INDEX(x)                       ((x) << 9)
+#       define CURR_SCLK_INDEX_MASK                     (0x7 << 9)
+#       define CURR_SCLK_INDEX_SHIFT                    9
+#       define TARG_INDEX(x)                            ((x) << 12)
+#       define TARG_INDEX_MASK                          (0x7 << 12)
+#       define TARG_INDEX_SHIFT                         12
+#       define CURR_INDEX(x)                            ((x) << 15)
+#       define CURR_INDEX_MASK                          (0x7 << 15)
+#       define CURR_INDEX_SHIFT                         15
+
+#define CG_SCLK_DPM_CTRL                                0x684
+#       define SCLK_FSTATE_0_DIV(x)                     ((x) << 0)
+#       define SCLK_FSTATE_0_DIV_MASK                   (0x7f << 0)
+#       define SCLK_FSTATE_0_DIV_SHIFT                  0
+#       define SCLK_FSTATE_0_VLD                        (1 << 7)
+#       define SCLK_FSTATE_1_DIV(x)                     ((x) << 8)
+#       define SCLK_FSTATE_1_DIV_MASK                   (0x7f << 8)
+#       define SCLK_FSTATE_1_DIV_SHIFT                  8
+#       define SCLK_FSTATE_1_VLD                        (1 << 15)
+#       define SCLK_FSTATE_2_DIV(x)                     ((x) << 16)
+#       define SCLK_FSTATE_2_DIV_MASK                   (0x7f << 16)
+#       define SCLK_FSTATE_2_DIV_SHIFT                  16
+#       define SCLK_FSTATE_2_VLD                        (1 << 23)
+#       define SCLK_FSTATE_3_DIV(x)                     ((x) << 24)
+#       define SCLK_FSTATE_3_DIV_MASK                   (0x7f << 24)
+#       define SCLK_FSTATE_3_DIV_SHIFT                  24
+#       define SCLK_FSTATE_3_VLD                        (1 << 31)
+#define CG_SCLK_DPM_CTRL_2                              0x688
+#define CG_GCOOR                                        0x68c
+#       define PHC(x)                                   ((x) << 0)
+#       define PHC_MASK                                 (0x1f << 0)
+#       define PHC_SHIFT                                0
+#       define SDC(x)                                   ((x) << 9)
+#       define SDC_MASK                                 (0x3ff << 9)
+#       define SDC_SHIFT                                9
+#       define SU(x)                                    ((x) << 23)
+#       define SU_MASK                                  (0xf << 23)
+#       define SU_SHIFT                                 23
+#       define DIV_ID(x)                                ((x) << 28)
+#       define DIV_ID_MASK                              (0x7 << 28)
+#       define DIV_ID_SHIFT                             28
+
+#define CG_FTV                                          0x690
+#define CG_FFCT_0                                       0x694
+#       define UTC_0(x)                                 ((x) << 0)
+#       define UTC_0_MASK                               (0x3ff << 0)
+#       define UTC_0_SHIFT                              0
+#       define DTC_0(x)                                 ((x) << 10)
+#       define DTC_0_MASK                               (0x3ff << 10)
+#       define DTC_0_SHIFT                              10
+
+#define CG_GIT                                          0x6d8
+#       define CG_GICST(x)                              ((x) << 0)
+#       define CG_GICST_MASK                            (0xffff << 0)
+#       define CG_GICST_SHIFT                           0
+#       define CG_GIPOT(x)                              ((x) << 16)
+#       define CG_GIPOT_MASK                            (0xffff << 16)
+#       define CG_GIPOT_SHIFT                           16
+
+#define CG_SCLK_DPM_CTRL_3                              0x6e0
+#       define FORCE_SCLK_STATE(x)                      ((x) << 0)
+#       define FORCE_SCLK_STATE_MASK                    (0x7 << 0)
+#       define FORCE_SCLK_STATE_SHIFT                   0
+#       define FORCE_SCLK_STATE_EN                      (1 << 3)
+#       define GNB_TT(x)                                ((x) << 8)
+#       define GNB_TT_MASK                              (0xff << 8)
+#       define GNB_TT_SHIFT                             8
+#       define GNB_THERMTHRO_MASK                       (1 << 16)
+#       define CNB_THERMTHRO_MASK_SCLK                  (1 << 17)
+#       define DPM_SCLK_ENABLE                          (1 << 18)
+#       define GNB_SLOW_FSTATE_0_MASK                   (1 << 23)
+#       define GNB_SLOW_FSTATE_0_SHIFT                  23
+#       define FORCE_NB_PSTATE_1                        (1 << 31)
+
+#define CG_SSP                                          0x6e8
+#       define SST(x)                                   ((x) << 0)
+#       define SST_MASK                                 (0xffff << 0)
+#       define SST_SHIFT                                0
+#       define SSTU(x)                                  ((x) << 16)
+#       define SSTU_MASK                                (0xffff << 16)
+#       define SSTU_SHIFT                               16
+
+#define CG_ACPI_CNTL                                    0x70c
+#       define SCLK_ACPI_DIV(x)                         ((x) << 0)
+#       define SCLK_ACPI_DIV_MASK                       (0x7f << 0)
+#       define SCLK_ACPI_DIV_SHIFT                      0
+
+#define CG_SCLK_DPM_CTRL_4                              0x71c
+#       define DC_HDC(x)                                ((x) << 14)
+#       define DC_HDC_MASK                              (0x3fff << 14)
+#       define DC_HDC_SHIFT                             14
+#       define DC_HU(x)                                 ((x) << 28)
+#       define DC_HU_MASK                               (0xf << 28)
+#       define DC_HU_SHIFT                              28
+#define CG_SCLK_DPM_CTRL_5                              0x720
+#       define SCLK_FSTATE_BOOTUP(x)                    ((x) << 0)
+#       define SCLK_FSTATE_BOOTUP_MASK                  (0x7 << 0)
+#       define SCLK_FSTATE_BOOTUP_SHIFT                 0
+#       define TT_TP(x)                                 ((x) << 3)
+#       define TT_TP_MASK                               (0xffff << 3)
+#       define TT_TP_SHIFT                              3
+#       define TT_TU(x)                                 ((x) << 19)
+#       define TT_TU_MASK                               (0xff << 19)
+#       define TT_TU_SHIFT                              19
+#define CG_SCLK_DPM_CTRL_6                              0x724
+#define CG_AT_0                                         0x728
+#       define CG_R(x)                                  ((x) << 0)
+#       define CG_R_MASK                                (0xffff << 0)
+#       define CG_R_SHIFT                               0
+#       define CG_L(x)                                  ((x) << 16)
+#       define CG_L_MASK                                (0xffff << 16)
+#       define CG_L_SHIFT                               16
+#define CG_AT_1                                         0x72c
+#define CG_AT_2                                         0x730
+#define	CG_THERMAL_INT					0x734
+#define		DIG_THERM_INTH(x)			((x) << 8)
+#define		DIG_THERM_INTH_MASK			0x0000FF00
+#define		DIG_THERM_INTH_SHIFT			8
+#define		DIG_THERM_INTL(x)			((x) << 16)
+#define		DIG_THERM_INTL_MASK			0x00FF0000
+#define		DIG_THERM_INTL_SHIFT			16
+#define 	THERM_INT_MASK_HIGH			(1 << 24)
+#define 	THERM_INT_MASK_LOW			(1 << 25)
+#define CG_AT_3                                         0x738
+#define CG_AT_4                                         0x73c
+#define CG_AT_5                                         0x740
+#define CG_AT_6                                         0x744
+#define CG_AT_7                                         0x748
+
+#define CG_BSP_0                                        0x750
+#       define BSP(x)                                   ((x) << 0)
+#       define BSP_MASK                                 (0xffff << 0)
+#       define BSP_SHIFT                                0
+#       define BSU(x)                                   ((x) << 16)
+#       define BSU_MASK                                 (0xf << 16)
+#       define BSU_SHIFT                                16
+
+#define CG_CG_VOLTAGE_CNTL                              0x770
+#       define REQ                                      (1 << 0)
+#       define LEVEL(x)                                 ((x) << 1)
+#       define LEVEL_MASK                               (0x3 << 1)
+#       define LEVEL_SHIFT                              1
+#       define CG_VOLTAGE_EN                            (1 << 3)
+#       define FORCE                                    (1 << 4)
+#       define PERIOD(x)                                ((x) << 8)
+#       define PERIOD_MASK                              (0xffff << 8)
+#       define PERIOD_SHIFT                             8
+#       define UNIT(x)                                  ((x) << 24)
+#       define UNIT_MASK                                (0xf << 24)
+#       define UNIT_SHIFT                               24
+
+#define CG_ACPI_VOLTAGE_CNTL                            0x780
+#       define ACPI_VOLTAGE_EN                          (1 << 8)
+
+#define CG_DPM_VOLTAGE_CNTL                             0x788
+#       define DPM_STATE0_LEVEL_MASK                    (0x3 << 0)
+#       define DPM_STATE0_LEVEL_SHIFT                   0
+#       define DPM_VOLTAGE_EN                           (1 << 16)
+
+#define CG_PWR_GATING_CNTL                              0x7ac
+#       define DYN_PWR_DOWN_EN                          (1 << 0)
+#       define ACPI_PWR_DOWN_EN                         (1 << 1)
+#       define GFX_CLK_OFF_PWR_DOWN_EN                  (1 << 2)
+#       define IOC_DISGPU_PWR_DOWN_EN                   (1 << 3)
+#       define FORCE_POWR_ON                            (1 << 4)
+#       define PGP(x)                                   ((x) << 8)
+#       define PGP_MASK                                 (0xffff << 8)
+#       define PGP_SHIFT                                8
+#       define PGU(x)                                   ((x) << 24)
+#       define PGU_MASK                                 (0xf << 24)
+#       define PGU_SHIFT                                24
+
+#define CG_CGTT_LOCAL_0                                 0x7d0
+#define CG_CGTT_LOCAL_1                                 0x7d4
+
+#define DEEP_SLEEP_CNTL                                 0x818
+#       define R_DIS                                    (1 << 3)
+#       define HS(x)                                    ((x) << 4)
+#       define HS_MASK                                  (0xfff << 4)
+#       define HS_SHIFT                                 4
+#       define ENABLE_DS                                (1 << 31)
+#define DEEP_SLEEP_CNTL2                                0x81c
+#       define LB_UFP_EN                                (1 << 0)
+#       define INOUT_C(x)                               ((x) << 4)
+#       define INOUT_C_MASK                             (0xff << 4)
+#       define INOUT_C_SHIFT                            4
+
+#define CG_SCRATCH2                                     0x824
+
+#define CG_SCLK_DPM_CTRL_11                             0x830
+
+#define HW_REV   					0x5564
+#       define ATI_REV_ID_MASK                          (0xf << 28)
+#       define ATI_REV_ID_SHIFT                         28
+/* 0 = A0, 1 = A1, 2 = B0, 3 = C0, etc. */
+
+#define DOUT_SCRATCH3   				0x611c
+
+#define GB_ADDR_CONFIG  				0x98f8
+
+#endif
Signature · 6 lines
1.7.7.5

_______________________________________________
dri-devel mailing list
[email protected]
http://lists.freedesktop.org/mailman/listinfo/dri-devel
#95 lore raw

PATCH 81/165 drm/radeon/kms: add dpm support for trinity asics

In reply to [email protected]

From: Alex Deucher <[email protected]>

This adds dpm support for trinity asics. This includes:
- clockgating
- powergating
- dynamic engine clock scaling
- dynamic voltage scaling

set radeon.dpm=1 to enable it.

---
 drivers/gpu/drm/radeon/Makefile      |    3 +-
 drivers/gpu/drm/radeon/evergreen.c   |   13 +-
 drivers/gpu/drm/radeon/evergreend.h  |   10 +
 drivers/gpu/drm/radeon/ppsmc.h       |   10 +-
 drivers/gpu/drm/radeon/radeon_asic.c |   12 +
 drivers/gpu/drm/radeon/radeon_asic.h |   12 +
 drivers/gpu/drm/radeon/radeon_pm.c   |    1 +
 drivers/gpu/drm/radeon/sumo_dpm.c    |   90 +-
 drivers/gpu/drm/radeon/sumo_dpm.h    |   21 +-
 drivers/gpu/drm/radeon/sumo_smc.c    |    2 -
 drivers/gpu/drm/radeon/trinity_dpm.c | 1613 ++++++++++++++++++++++++++++++++++
 drivers/gpu/drm/radeon/trinity_dpm.h |  110 +++
 drivers/gpu/drm/radeon/trinity_smc.c |  110 +++
 drivers/gpu/drm/radeon/trinityd.h    |  223 +++++
 14 files changed, 2179 insertions(+), 51 deletions(-)
 create mode 100644 drivers/gpu/drm/radeon/trinity_dpm.c
 create mode 100644 drivers/gpu/drm/radeon/trinity_dpm.h
 create mode 100644 drivers/gpu/drm/radeon/trinity_smc.c
 create mode 100644 drivers/gpu/drm/radeon/trinityd.h
drivers/gpu/drm/radeon/Makefile +2 -1
index 7c77e1d..2239ec2 100644
@@ -78,7 +78,8 @@ radeon-y += radeon_device.o radeon_asic.o radeon_kms.o \
 	atombios_encoders.o radeon_semaphore.o radeon_sa.o atombios_i2c.o si.o \
 	si_blit_shaders.o radeon_prime.o radeon_uvd.o cik.o cik_blit_shaders.o \
 	r600_dpm.o rs780_dpm.o rv6xx_dpm.o rv770_dpm.o rv730_dpm.o rv740_dpm.o \
-	rv770_smc.o cypress_dpm.o btc_dpm.o sumo_dpm.o sumo_smc.o
+	rv770_smc.o cypress_dpm.o btc_dpm.o sumo_dpm.o sumo_smc.o trinity_dpm.o \
+	trinity_smc.o
 
 radeon-$(CONFIG_COMPAT) += radeon_ioc32.o
 radeon-$(CONFIG_VGA_SWITCHEROO) += radeon_atpx_handler.o
drivers/gpu/drm/radeon/evergreen.c +10 -3
index c91b1e5..6449953 100644
@@ -4187,8 +4187,12 @@ int evergreen_irq_set(struct radeon_device *rdev)
 	hpd4 = RREG32(DC_HPD4_INT_CONTROL) & ~DC_HPDx_INT_EN;
 	hpd5 = RREG32(DC_HPD5_INT_CONTROL) & ~DC_HPDx_INT_EN;
 	hpd6 = RREG32(DC_HPD6_INT_CONTROL) & ~DC_HPDx_INT_EN;
-	thermal_int = RREG32(CG_THERMAL_INT) &
-		~(THERM_INT_MASK_HIGH | THERM_INT_MASK_LOW);
+	if (rdev->family == CHIP_ARUBA)
+		thermal_int = RREG32(TN_CG_THERMAL_INT_CTRL) &
+			~(THERM_INT_MASK_HIGH | THERM_INT_MASK_LOW);
+	else
+		thermal_int = RREG32(CG_THERMAL_INT) &
+			~(THERM_INT_MASK_HIGH | THERM_INT_MASK_LOW);
 
 	afmt1 = RREG32(AFMT_AUDIO_PACKET_CONTROL + EVERGREEN_CRTC0_REGISTER_OFFSET) & ~AFMT_AZ_FORMAT_WTRIG_MASK;
 	afmt2 = RREG32(AFMT_AUDIO_PACKET_CONTROL + EVERGREEN_CRTC1_REGISTER_OFFSET) & ~AFMT_AZ_FORMAT_WTRIG_MASK;
@@ -4360,7 +4364,10 @@ int evergreen_irq_set(struct radeon_device *rdev)
 	WREG32(DC_HPD4_INT_CONTROL, hpd4);
 	WREG32(DC_HPD5_INT_CONTROL, hpd5);
 	WREG32(DC_HPD6_INT_CONTROL, hpd6);
-	WREG32(CG_THERMAL_INT, thermal_int);
+	if (rdev->family == CHIP_ARUBA)
+		WREG32(TN_CG_THERMAL_INT_CTRL, thermal_int);
+	else
+		WREG32(CG_THERMAL_INT, thermal_int);
 
 	WREG32(AFMT_AUDIO_PACKET_CONTROL + EVERGREEN_CRTC0_REGISTER_OFFSET, afmt1);
 	WREG32(AFMT_AUDIO_PACKET_CONTROL + EVERGREEN_CRTC1_REGISTER_OFFSET, afmt2);
drivers/gpu/drm/radeon/evergreend.h +10 -0
index 93b91a3..35e6153 100644
@@ -823,6 +823,16 @@
 #define 	THERM_INT_MASK_HIGH			(1 << 24)
 #define 	THERM_INT_MASK_LOW			(1 << 25)
 
+#define	TN_CG_THERMAL_INT_CTRL				0x738
+#define		TN_DIG_THERM_INTH(x)			((x) << 0)
+#define		TN_DIG_THERM_INTH_MASK			0x000000FF
+#define		TN_DIG_THERM_INTH_SHIFT			0
+#define		TN_DIG_THERM_INTL(x)			((x) << 8)
+#define		TN_DIG_THERM_INTL_MASK			0x0000FF00
+#define		TN_DIG_THERM_INTL_SHIFT			8
+#define 	TN_THERM_INT_MASK_HIGH			(1 << 24)
+#define 	TN_THERM_INT_MASK_LOW			(1 << 25)
+
 #define	CG_MULT_THERMAL_STATUS				0x740
 #define		ASIC_T(x)			        ((x) << 16)
 #define		ASIC_T_MASK			        0x07FF0000
drivers/gpu/drm/radeon/ppsmc.h +9 -1
index 638de17..8ef479a 100644
@@ -69,7 +69,15 @@ typedef uint8_t PPSMC_Result;
 #define PPSMC_MSG_ExitULV                   ((uint8_t)0x65)
 #define PPSMC_MSG_ResetToDefaults           ((uint8_t)0x84)
 
-typedef uint8_t PPSMC_Msg;
+/* TN */
+#define PPSMC_MSG_DPM_Config                ((uint32_t) 0x102)
+#define PPSMC_MSG_DPM_ForceState            ((uint32_t) 0x104)
+#define PPSMC_MSG_PG_SIMD_Config            ((uint32_t) 0x108)
+#define PPSMC_MSG_DCE_RemoveVoltageAdjustment   ((uint32_t) 0x11d)
+#define PPSMC_MSG_DCE_AllowVoltageAdjustment    ((uint32_t) 0x11e)
+
+
+typedef uint16_t PPSMC_Msg;
 
 #pragma pack(pop)
 
drivers/gpu/drm/radeon/radeon_asic.c +12 -0
index 8b541b4..5dcbb28 100644
@@ -1944,6 +1944,18 @@ static struct radeon_asic trinity_asic = {
 		.set_uvd_clocks = &sumo_set_uvd_clocks,
 		.get_temperature = &tn_get_temp,
 	},
+	.dpm = {
+		.init = &trinity_dpm_init,
+		.setup_asic = &trinity_dpm_setup_asic,
+		.enable = &trinity_dpm_enable,
+		.disable = &trinity_dpm_disable,
+		.set_power_state = &trinity_dpm_set_power_state,
+		.display_configuration_changed = &trinity_dpm_display_configuration_changed,
+		.fini = &trinity_dpm_fini,
+		.get_sclk = &trinity_dpm_get_sclk,
+		.get_mclk = &trinity_dpm_get_mclk,
+		.print_power_state = &trinity_dpm_print_power_state,
+	},
 	.pflip = {
 		.pre_page_flip = &evergreen_pre_page_flip,
 		.page_flip = &evergreen_page_flip,
drivers/gpu/drm/radeon/radeon_asic.h +12 -0
index f6c0984..4d3f93d 100644
@@ -581,6 +581,18 @@ bool cayman_gfx_is_lockup(struct radeon_device *rdev, struct radeon_ring *ring);
 bool cayman_dma_is_lockup(struct radeon_device *rdev, struct radeon_ring *ring);
 void cayman_dma_vm_flush(struct radeon_device *rdev, int ridx, struct radeon_vm *vm);
 
+int trinity_dpm_init(struct radeon_device *rdev);
+int trinity_dpm_enable(struct radeon_device *rdev);
+void trinity_dpm_disable(struct radeon_device *rdev);
+int trinity_dpm_set_power_state(struct radeon_device *rdev);
+void trinity_dpm_setup_asic(struct radeon_device *rdev);
+void trinity_dpm_display_configuration_changed(struct radeon_device *rdev);
+void trinity_dpm_fini(struct radeon_device *rdev);
+u32 trinity_dpm_get_sclk(struct radeon_device *rdev, bool low);
+u32 trinity_dpm_get_mclk(struct radeon_device *rdev, bool low);
+void trinity_dpm_print_power_state(struct radeon_device *rdev,
+				   struct radeon_ps *ps);
+
 /* DCE6 - SI */
 void dce6_bandwidth_update(struct radeon_device *rdev);
 
drivers/gpu/drm/radeon/radeon_pm.c +1 -0
index b924bcc1..e6fce0b 100644
@@ -1055,6 +1055,7 @@ int radeon_pm_init(struct radeon_device *rdev)
 	case CHIP_BARTS:
 	case CHIP_TURKS:
 	case CHIP_CAICOS:
+	case CHIP_ARUBA:
 		if (radeon_dpm == 1)
 			rdev->pm.pm_method = PM_METHOD_DPM;
 		else
drivers/gpu/drm/radeon/sumo_dpm.c +47 -43

217 lines not on this page · raw message

drivers/gpu/drm/radeon/sumo_dpm.h +20 -1
index 561bee1..d041a6c 100644
@@ -23,6 +23,8 @@
 #ifndef __SUMO_DPM_H__
 #define __SUMO_DPM_H__
 
+#include "atom.h"
+
 #define SUMO_MAX_HARDWARE_POWERLEVELS 5
 #define SUMO_PM_NUMBER_OF_TC 15
 
@@ -184,7 +186,24 @@ struct sumo_power_info {
 
 /* sumo_dpm.c */
 u32 sumo_get_xclk(struct radeon_device *rdev);
-
+void sumo_gfx_clockgating_initialize(struct radeon_device *rdev);
+void sumo_program_vc(struct radeon_device *rdev, u32 vrc);
+void sumo_clear_vc(struct radeon_device *rdev);
+void sumo_program_sstp(struct radeon_device *rdev);
+void sumo_take_smu_control(struct radeon_device *rdev, bool enable);
+void sumo_construct_sclk_voltage_mapping_table(struct radeon_device *rdev,
+					       struct sumo_sclk_voltage_mapping_table *sclk_voltage_mapping_table,
+					       ATOM_AVAILABLE_SCLK_LIST *table);
+void sumo_construct_vid_mapping_table(struct radeon_device *rdev,
+				      struct sumo_vid_mapping_table *vid_mapping_table,
+				      ATOM_AVAILABLE_SCLK_LIST *table);
+u32 sumo_convert_vid2_to_vid7(struct radeon_device *rdev,
+			      struct sumo_vid_mapping_table *vid_mapping_table,
+			      u32 vid_2bit);
+u32 sumo_get_sleep_divider_from_id(u32 id);
+u32 sumo_get_sleep_divider_id_from_clock(struct radeon_device *rdev,
+					 u32 sclk,
+					 u32 min_sclk_in_sr);
 
 /* sumo_smc.c */
 void sumo_initialize_m3_arb(struct radeon_device *rdev);
drivers/gpu/drm/radeon/sumo_smc.c +0 -2
index 9d0ae9b..bc1a510 100644
@@ -21,13 +21,11 @@
  *
  */
 
-#include <linux/firmware.h>
 #include "drmP.h"
 #include "radeon.h"
 #include "sumod.h"
 #include "sumo_dpm.h"
 #include "ppsmc.h"
-#include "radeon_ucode.h"
 
 #define SUMO_SMU_SERVICE_ROUTINE_PG_INIT        1
 #define SUMO_SMU_SERVICE_ROUTINE_ALTVDDNB_NOTIFY  27
drivers/gpu/drm/radeon/trinity_dpm.c new file +1613 -0

1,613 lines not on this page · raw message

drivers/gpu/drm/radeon/trinity_dpm.h new file +110 -0

110 lines not on this page · raw message

drivers/gpu/drm/radeon/trinity_smc.c new file +110 -0

110 lines not on this page · raw message

drivers/gpu/drm/radeon/trinityd.h new file +223 -0

223 lines not on this page · raw message

Signature · 1 line
1.7.7.5
#96 lore raw

PATCH 82/165 drm/radeon/dpm: let atom control display phy powergating

In reply to [email protected]

From: Alex Deucher <[email protected]>

---
 drivers/gpu/drm/radeon/sumo_dpm.c |    7 +++++++
 1 files changed, 7 insertions(+), 0 deletions(-)
drivers/gpu/drm/radeon/sumo_dpm.c +7 -0
index 67c85c7..f103880 100644
@@ -813,6 +813,12 @@ static void sumo_program_bootup_state(struct radeon_device *rdev)
 
 void sumo_take_smu_control(struct radeon_device *rdev, bool enable)
 {
+/* This bit selects who handles display phy powergating.
+ * Clear the bit to let atom handle it.
+ * Set it to let the driver handle it.
+ * For now we just let atom handle it.
+ */
+#if 0
 	u32 v = RREG32(DOUT_SCRATCH3);
 
 	if (enable)
@@ -821,6 +827,7 @@ void sumo_take_smu_control(struct radeon_device *rdev, bool enable)
 		v &= 0xFFFFFFFB;
 
 	WREG32(DOUT_SCRATCH3, v);
+#endif
 }
 
 static void sumo_enable_sclk_ds(struct radeon_device *rdev, bool enable)
Signature · 1 line
1.7.7.5
#97 lore raw

PATCH 83/165 drm/radeon: add dpm UVD handling for r7xx asics

In reply to [email protected]

From: Alex Deucher <[email protected]>

---
 drivers/gpu/drm/radeon/rv770_dpm.c |   34 ++++++++++++++++++++++++++++++++++
 drivers/gpu/drm/radeon/rv770_dpm.h |    2 ++
 2 files changed, 36 insertions(+), 0 deletions(-)
drivers/gpu/drm/radeon/rv770_dpm.c +34 -0
index 8ea6d69..42f559a 100644
@@ -1427,6 +1427,38 @@ int rv770_set_boot_state(struct radeon_device *rdev)
 	return 0;
 }
 
+void rv770_set_uvd_clock_before_set_eng_clock(struct radeon_device *rdev)
+{
+	struct rv7xx_ps *new_state = rv770_get_ps(rdev->pm.dpm.requested_ps);
+	struct rv7xx_ps *current_state = rv770_get_ps(rdev->pm.dpm.current_ps);
+
+	if ((rdev->pm.dpm.requested_ps->vclk == rdev->pm.dpm.current_ps->vclk) &&
+	    (rdev->pm.dpm.requested_ps->dclk == rdev->pm.dpm.current_ps->dclk))
+		return;
+
+	if (new_state->high.sclk >= current_state->high.sclk)
+		return;
+
+	radeon_set_uvd_clocks(rdev, rdev->pm.dpm.requested_ps->vclk,
+			      rdev->pm.dpm.requested_ps->dclk);
+}
+
+void rv770_set_uvd_clock_after_set_eng_clock(struct radeon_device *rdev)
+{
+	struct rv7xx_ps *new_state = rv770_get_ps(rdev->pm.dpm.requested_ps);
+	struct rv7xx_ps *current_state = rv770_get_ps(rdev->pm.dpm.current_ps);
+
+	if ((rdev->pm.dpm.requested_ps->vclk == rdev->pm.dpm.current_ps->vclk) &&
+	    (rdev->pm.dpm.requested_ps->dclk == rdev->pm.dpm.current_ps->dclk))
+		return;
+
+	if (new_state->high.sclk < current_state->high.sclk)
+		return;
+
+	radeon_set_uvd_clocks(rdev, rdev->pm.dpm.requested_ps->vclk,
+			      rdev->pm.dpm.requested_ps->dclk);
+}
+
 int rv770_restrict_performance_levels_before_switch(struct radeon_device *rdev)
 {
 	if (rv770_send_msg_to_smc(rdev, (PPSMC_Msg)(PPSMC_MSG_NoForcedLevel)) != PPSMC_Result_OK)
@@ -1950,6 +1982,7 @@ int rv770_dpm_set_power_state(struct radeon_device *rdev)
 	struct rv7xx_power_info *pi = rv770_get_pi(rdev);
 
 	rv770_restrict_performance_levels_before_switch(rdev);
+	rv770_set_uvd_clock_before_set_eng_clock(rdev);
 	rv770_halt_smc(rdev);
 	rv770_upload_sw_state(rdev);
 	r7xx_program_memory_timing_parameters(rdev);
@@ -1959,6 +1992,7 @@ int rv770_dpm_set_power_state(struct radeon_device *rdev)
 	rv770_set_sw_state(rdev);
 	if (pi->dcodt)
 		rv770_program_dcodt_after_state_switch(rdev);
+	rv770_set_uvd_clock_after_set_eng_clock(rdev);
 
 	return 0;
 }
drivers/gpu/drm/radeon/rv770_dpm.h +2 -0
index bd6ea7b..e42c064 100644
@@ -262,6 +262,8 @@ int rv770_resume_smc(struct radeon_device *rdev);
 int rv770_set_sw_state(struct radeon_device *rdev);
 int rv770_set_boot_state(struct radeon_device *rdev);
 int rv7xx_parse_power_table(struct radeon_device *rdev);
+void rv770_set_uvd_clock_before_set_eng_clock(struct radeon_device *rdev);
+void rv770_set_uvd_clock_after_set_eng_clock(struct radeon_device *rdev);
 
 /* smc */
 int rv770_read_smc_soft_register(struct radeon_device *rdev,
Signature · 1 line
1.7.7.5
#98 lore raw

PATCH 84/165 drm/radeon: add dpm UVD handling for evergreen/btc asics

In reply to [email protected]

From: Alex Deucher <[email protected]>

---
 drivers/gpu/drm/radeon/btc_dpm.c     |   62 ++++++++++++++++++++++++++++++++++
 drivers/gpu/drm/radeon/btc_dpm.h     |    4 ++
 drivers/gpu/drm/radeon/cypress_dpm.c |   10 +++++-
 drivers/gpu/drm/radeon/cypress_dpm.h |   10 +++++
 drivers/gpu/drm/radeon/rv770_dpm.c   |   30 +++++++++-------
 drivers/gpu/drm/radeon/rv770_dpm.h   |    4 ++
 drivers/gpu/drm/radeon/rv770_smc.h   |    1 +
 7 files changed, 107 insertions(+), 14 deletions(-)
drivers/gpu/drm/radeon/btc_dpm.c +62 -0
index 6780120..2662ef0 100644
@@ -1510,6 +1510,46 @@ static int btc_init_smc_table(struct radeon_device *rdev)
 				       pi->sram_end);
 }
 
+static void btc_set_at_for_uvd(struct radeon_device *rdev)
+{
+	struct rv7xx_power_info *pi = rv770_get_pi(rdev);
+	struct evergreen_power_info *eg_pi = evergreen_get_pi(rdev);
+	struct radeon_ps *radeon_new_state = rdev->pm.dpm.requested_ps;
+	int idx = 0;
+
+	if (r600_is_uvd_state(radeon_new_state->class, radeon_new_state->class2))
+		idx = 1;
+
+	if ((idx == 1) && !eg_pi->smu_uvd_hs) {
+		pi->rlp = 10;
+		pi->rmp = 100;
+		pi->lhp = 100;
+		pi->lmp = 10;
+	} else {
+		pi->rlp = eg_pi->ats[idx].rlp;
+		pi->rmp = eg_pi->ats[idx].rmp;
+		pi->lhp = eg_pi->ats[idx].lhp;
+		pi->lmp = eg_pi->ats[idx].lmp;
+	}
+
+}
+
+static void btc_notify_uvd_to_smc(struct radeon_device *rdev)
+{
+	struct radeon_ps *radeon_new_state = rdev->pm.dpm.requested_ps;
+	struct evergreen_power_info *eg_pi = evergreen_get_pi(rdev);
+
+	if (r600_is_uvd_state(radeon_new_state->class, radeon_new_state->class2)) {
+		rv770_write_smc_soft_register(rdev,
+					      RV770_SMC_SOFT_REGISTER_uvd_enabled, 1);
+		eg_pi->uvd_enabled = true;
+	} else {
+		rv770_write_smc_soft_register(rdev,
+					      RV770_SMC_SOFT_REGISTER_uvd_enabled, 0);
+		eg_pi->uvd_enabled = false;
+	}
+}
+
 static int btc_reset_to_default(struct radeon_device *rdev)
 {
 	if (rv770_send_msg_to_smc(rdev, PPSMC_MSG_ResetToDefaults) != PPSMC_Result_OK)
@@ -1880,7 +1920,11 @@ int btc_dpm_set_power_state(struct radeon_device *rdev)
 	if (eg_pi->pcie_performance_request)
 		cypress_notify_link_speed_change_before_state_change(rdev);
 
+	rv770_set_uvd_clock_before_set_eng_clock(rdev);
 	rv770_halt_smc(rdev);
+	btc_set_at_for_uvd(rdev);
+	if (eg_pi->smu_uvd_hs)
+		btc_notify_uvd_to_smc(rdev);
 	cypress_upload_sw_state(rdev);
 
 	if (eg_pi->dynamic_ac_timing)
@@ -1890,6 +1934,7 @@ int btc_dpm_set_power_state(struct radeon_device *rdev)
 
 	rv770_resume_smc(rdev);
 	rv770_set_sw_state(rdev);
+	rv770_set_uvd_clock_after_set_eng_clock(rdev);
 
 	if (eg_pi->pcie_performance_request)
 		cypress_notify_link_speed_change_after_state_change(rdev);
@@ -2093,6 +2138,23 @@ int btc_dpm_init(struct radeon_device *rdev)
 	pi->mclk_edc_enable_threshold = 40000;
 	eg_pi->mclk_edc_wr_enable_threshold = 40000;
 
+	pi->rlp = RV770_RLP_DFLT;
+	pi->rmp = RV770_RMP_DFLT;
+	pi->lhp = RV770_LHP_DFLT;
+	pi->lmp = RV770_LMP_DFLT;
+
+	eg_pi->ats[0].rlp = RV770_RLP_DFLT;
+	eg_pi->ats[0].rmp = RV770_RMP_DFLT;
+	eg_pi->ats[0].lhp = RV770_LHP_DFLT;
+	eg_pi->ats[0].lmp = RV770_LMP_DFLT;
+
+	eg_pi->ats[1].rlp = BTC_RLP_UVD_DFLT;
+	eg_pi->ats[1].rmp = BTC_RMP_UVD_DFLT;
+	eg_pi->ats[1].lhp = BTC_LHP_UVD_DFLT;
+	eg_pi->ats[1].lmp = BTC_LMP_UVD_DFLT;
+
+	eg_pi->smu_uvd_hs = true;
+
 	pi->voltage_control =
 		radeon_atom_is_voltage_gpio(rdev, SET_VOLTAGE_TYPE_ASIC_VDDC);
 
drivers/gpu/drm/radeon/btc_dpm.h +4 -0
index a095d40..56b1957 100644
@@ -23,6 +23,10 @@
 #ifndef __BTC_DPM_H__
 #define __BTC_DPM_H__
 
+#define BTC_RLP_UVD_DFLT                              20
+#define BTC_RMP_UVD_DFLT                              50
+#define BTC_LHP_UVD_DFLT                              50
+#define BTC_LMP_UVD_DFLT                              20
 #define BARTS_MGCGCGTSSMCTRL_DFLT                     0x81944000
 #define TURKS_MGCGCGTSSMCTRL_DFLT                     0x6e944000
 #define CAICOS_MGCGCGTSSMCTRL_DFLT                    0x46944040
drivers/gpu/drm/radeon/cypress_dpm.c +9 -1
index 2345c81..403ee15 100644
@@ -690,7 +690,8 @@ int cypress_convert_power_level_to_smc(struct radeon_device *rdev,
 
 	level->mcFlags =  0;
 	if (pi->mclk_stutter_mode_threshold &&
-	    (pl->mclk <= pi->mclk_stutter_mode_threshold)) {
+	    (pl->mclk <= pi->mclk_stutter_mode_threshold) &&
+	    !eg_pi->uvd_enabled) {
 		level->mcFlags |= SMC_MC_STUTTER_EN;
 		if (eg_pi->sclk_deep_sleep)
 			level->stateFlags |= PPSMC_STATEFLAG_AUTO_PULSE_SKIP;
@@ -1938,6 +1939,7 @@ int cypress_dpm_set_power_state(struct radeon_device *rdev)
 	if (eg_pi->pcie_performance_request)
 		cypress_notify_link_speed_change_before_state_change(rdev);
 
+	rv770_set_uvd_clock_before_set_eng_clock(rdev);
 	rv770_halt_smc(rdev);
 	cypress_upload_sw_state(rdev);
 
@@ -1948,6 +1950,7 @@ int cypress_dpm_set_power_state(struct radeon_device *rdev)
 
 	rv770_resume_smc(rdev);
 	rv770_set_sw_state(rdev);
+	rv770_set_uvd_clock_after_set_eng_clock(rdev);
 
 	if (eg_pi->pcie_performance_request)
 		cypress_notify_link_speed_change_after_state_change(rdev);
@@ -2010,6 +2013,11 @@ int cypress_dpm_init(struct radeon_device *rdev)
 	pi->mclk_edc_enable_threshold = 40000;
 	eg_pi->mclk_edc_wr_enable_threshold = 40000;
 
+	pi->rlp = RV770_RLP_DFLT;
+	pi->rmp = RV770_RMP_DFLT;
+	pi->lhp = RV770_LHP_DFLT;
+	pi->lmp = RV770_LMP_DFLT;
+
 	pi->voltage_control =
 		radeon_atom_is_voltage_gpio(rdev, SET_VOLTAGE_TYPE_ASIC_VDDC);
 
drivers/gpu/drm/radeon/cypress_dpm.h +10 -0
index 6cc3d3f..029bc9d 100644
@@ -51,6 +51,13 @@ struct evergreen_arb_registers {
 	u32 mc_arb_burst_time;
 };
 
+struct at {
+	u32 rlp;
+	u32 rmp;
+	u32 lhp;
+	u32 lmp;
+};
+
 struct evergreen_power_info {
 	/* must be first! */
 	struct rv7xx_power_info rv7xx;
@@ -66,6 +73,8 @@ struct evergreen_power_info {
 	bool sclk_deep_sleep;
 	bool dll_default_on;
 	bool ls_clock_gating;
+	bool smu_uvd_hs;
+	bool uvd_enabled;
 	/* stored values */
 	u16 acpi_vddci;
 	u8 mvdd_high_index;
@@ -76,6 +85,7 @@ struct evergreen_power_info {
 	struct atom_voltage_table vddci_voltage_table;
 	struct evergreen_arb_registers bootup_arb_registers;
 	struct evergreen_ulv_param ulv;
+	struct at ats[2];
 	/* smc offsets */
 	u16 mc_reg_table_start;
 };
drivers/gpu/drm/radeon/rv770_dpm.c +17 -13
index 42f559a..55e5126 100644
@@ -265,22 +265,21 @@ int rv770_populate_smc_t(struct radeon_device *rdev,
 	l[0] = 0;
 	r[2] = 100;
 
-	a_n = (int)state->medium.sclk * RV770_LMP_DFLT +
-		(int)state->low.sclk * (R600_AH_DFLT - RV770_RLP_DFLT);
-	a_d = (int)state->low.sclk * (100 - (int)RV770_RLP_DFLT) +
-		(int)state->medium.sclk * RV770_LMP_DFLT;
+	a_n = (int)state->medium.sclk * pi->lmp +
+		(int)state->low.sclk * (R600_AH_DFLT - pi->rlp);
+	a_d = (int)state->low.sclk * (100 - (int)pi->rlp) +
+		(int)state->medium.sclk * pi->lmp;
 
-	l[1] = (u8)(RV770_LMP_DFLT - (int)RV770_LMP_DFLT * a_n / a_d);
-	r[0] = (u8)(RV770_RLP_DFLT + (100 - (int)RV770_RLP_DFLT) * a_n / a_d);
+	l[1] = (u8)(pi->lmp - (int)pi->lmp * a_n / a_d);
+	r[0] = (u8)(pi->rlp + (100 - (int)pi->rlp) * a_n / a_d);
 
-	a_n = (int)state->high.sclk * RV770_LHP_DFLT +
-		(int)state->medium.sclk *
-		(R600_AH_DFLT - RV770_RMP_DFLT);
-	a_d = (int)state->medium.sclk * (100 - (int)RV770_RMP_DFLT) +
-		(int)state->high.sclk * RV770_LHP_DFLT;
+	a_n = (int)state->high.sclk * pi->lhp + (int)state->medium.sclk *
+		(R600_AH_DFLT - pi->rmp);
+	a_d = (int)state->medium.sclk * (100 - (int)pi->rmp) +
+		(int)state->high.sclk * pi->lhp;
 
-	l[2] = (u8)(RV770_LHP_DFLT - (int)RV770_LHP_DFLT * a_n / a_d);
-	r[1] = (u8)(RV770_RMP_DFLT + (100 - (int)RV770_RMP_DFLT) * a_n / a_d);
+	l[2] = (u8)(pi->lhp - (int)pi->lhp * a_n / a_d);
+	r[1] = (u8)(pi->rmp + (100 - (int)pi->rmp) * a_n / a_d);
 
 	for (i = 0; i < (RV770_SMC_PERFORMANCE_LEVELS_PER_SWSTATE - 1); i++) {
 		a_t = CG_R(r[i] * pi->bsp / 200) | CG_L(l[i] * pi->bsp / 200);
@@ -2269,6 +2268,11 @@ int rv770_dpm_init(struct radeon_device *rdev)
 	pi->mclk_strobe_mode_threshold = 30000;
 	pi->mclk_edc_enable_threshold = 30000;
 
+	pi->rlp = RV770_RLP_DFLT;
+	pi->rmp = RV770_RMP_DFLT;
+	pi->lhp = RV770_LHP_DFLT;
+	pi->lmp = RV770_LMP_DFLT;
+
 	pi->voltage_control =
 		radeon_atom_is_voltage_gpio(rdev, SET_VOLTAGE_TYPE_ASIC_VDDC);
 
drivers/gpu/drm/radeon/rv770_dpm.h +4 -0
index e42c064..dfb133f 100644
@@ -126,6 +126,10 @@ struct rv7xx_power_info {
 	u32 pasi;
 	u32 vrc;
 	u32 restricted_levels;
+	u32 rlp;
+	u32 rmp;
+	u32 lhp;
+	u32 lmp;
 	/* smc offsets */
 	u16 state_table_start;
 	u16 soft_regs_start;
drivers/gpu/drm/radeon/rv770_smc.h +1 -0
index bdb652c..f78d92a 100644
@@ -184,6 +184,7 @@ typedef struct RV770_SMC_STATETABLE RV770_SMC_STATETABLE;
 #define RV770_SMC_SOFT_REGISTER_mvdd_chg_time           0x68
 #define RV770_SMC_SOFT_REGISTER_mclk_switch_lim         0x78
 #define RV770_SMC_SOFT_REGISTER_mc_block_delay          0x90
+#define RV770_SMC_SOFT_REGISTER_uvd_enabled             0x9C
 #define RV770_SMC_SOFT_REGISTER_is_asic_lombok          0xA0
 
 int rv770_set_smc_sram_address(struct radeon_device *rdev,
Signature · 1 line
1.7.7.5
#99 lore raw

PATCH 85/165 drm/radeon: add dpm UVD handling for sumo asics

In reply to [email protected]

From: Alex Deucher <[email protected]>

---
 drivers/gpu/drm/radeon/sumo_dpm.c |   55 +++++++++++++++++++++++++++++++++++++
 drivers/gpu/drm/radeon/sumod.h    |   10 +++++++
 2 files changed, 65 insertions(+), 0 deletions(-)
drivers/gpu/drm/radeon/sumo_dpm.c +55 -0
index f103880..cef25c4 100644
@@ -811,6 +811,40 @@ static void sumo_program_bootup_state(struct radeon_device *rdev)
 		sumo_power_level_enable(rdev, i, false);
 }
 
+static void sumo_set_uvd_clock_before_set_eng_clock(struct radeon_device *rdev)
+{
+	struct sumo_ps *new_ps = sumo_get_ps(rdev->pm.dpm.requested_ps);
+	struct sumo_ps *current_ps = sumo_get_ps(rdev->pm.dpm.current_ps);
+
+	if ((rdev->pm.dpm.requested_ps->vclk == rdev->pm.dpm.current_ps->vclk) &&
+	    (rdev->pm.dpm.requested_ps->dclk == rdev->pm.dpm.current_ps->dclk))
+		return;
+
+	if (new_ps->levels[new_ps->num_levels - 1].sclk >=
+	    current_ps->levels[current_ps->num_levels - 1].sclk)
+		return;
+
+	radeon_set_uvd_clocks(rdev, rdev->pm.dpm.requested_ps->vclk,
+			      rdev->pm.dpm.requested_ps->dclk);
+}
+
+static void sumo_set_uvd_clock_after_set_eng_clock(struct radeon_device *rdev)
+{
+	struct sumo_ps *new_ps = sumo_get_ps(rdev->pm.dpm.requested_ps);
+	struct sumo_ps *current_ps = sumo_get_ps(rdev->pm.dpm.current_ps);
+
+	if ((rdev->pm.dpm.requested_ps->vclk == rdev->pm.dpm.current_ps->vclk) &&
+	    (rdev->pm.dpm.requested_ps->dclk == rdev->pm.dpm.current_ps->dclk))
+		return;
+
+	if (new_ps->levels[new_ps->num_levels - 1].sclk <
+	    current_ps->levels[current_ps->num_levels - 1].sclk)
+		return;
+
+	radeon_set_uvd_clocks(rdev, rdev->pm.dpm.requested_ps->vclk,
+			      rdev->pm.dpm.requested_ps->dclk);
+}
+
 void sumo_take_smu_control(struct radeon_device *rdev, bool enable)
 {
 /* This bit selects who handles display phy powergating.
@@ -1096,6 +1130,22 @@ static void sumo_cleanup_asic(struct radeon_device *rdev)
 	sumo_take_smu_control(rdev, false);
 }
 
+static void sumo_uvd_init(struct radeon_device *rdev)
+{
+	u32 tmp;
+
+	tmp = RREG32(CG_VCLK_CNTL);
+	tmp &= ~VCLK_DIR_CNTL_EN;
+	WREG32(CG_VCLK_CNTL, tmp);
+
+	tmp = RREG32(CG_DCLK_CNTL);
+	tmp &= ~DCLK_DIR_CNTL_EN;
+	WREG32(CG_DCLK_CNTL, tmp);
+
+	/* 100 Mhz */
+	radeon_set_uvd_clocks(rdev, 10000, 10000);
+}
+
 static int sumo_set_thermal_temperature_range(struct radeon_device *rdev,
 					      int min_temp, int max_temp)
 {
@@ -1188,6 +1238,8 @@ int sumo_dpm_set_power_state(struct radeon_device *rdev)
 
 	if (pi->enable_dynamic_patch_ps)
 		sumo_apply_state_adjust_rules(rdev);
+	if (pi->enable_dpm)
+		sumo_set_uvd_clock_before_set_eng_clock(rdev);
 	sumo_update_current_power_levels(rdev);
 	if (pi->enable_boost) {
 		sumo_enable_boost(rdev, false);
@@ -1211,6 +1263,8 @@ int sumo_dpm_set_power_state(struct radeon_device *rdev)
 	}
 	if (pi->enable_boost)
 		sumo_enable_boost(rdev, true);
+	if (pi->enable_dpm)
+		sumo_set_uvd_clock_after_set_eng_clock(rdev);
 
 	return 0;
 }
@@ -1237,6 +1291,7 @@ void sumo_dpm_setup_asic(struct radeon_device *rdev)
 	sumo_program_acpi_power_level(rdev);
 	sumo_enable_acpi_pm(rdev);
 	sumo_take_smu_control(rdev, true);
+	sumo_uvd_init(rdev);
 }
 
 void sumo_dpm_display_configuration_changed(struct radeon_device *rdev)
drivers/gpu/drm/radeon/sumod.h +10 -0
index a5deba6..7c9c2d4 100644
@@ -136,6 +136,16 @@
 #define CG_SCLK_STATUS                                  0x604
 #       define SCLK_OVERCLK_DETECT                      (1 << 2)
 
+#define CG_DCLK_CNTL                                    0x610
+#       define DCLK_DIVIDER_MASK                        0x7f
+#       define DCLK_DIR_CNTL_EN                         (1 << 8)
+#define CG_DCLK_STATUS                                  0x614
+#       define DCLK_STATUS                              (1 << 0)
+#define CG_VCLK_CNTL                                    0x618
+#       define VCLK_DIVIDER_MASK                        0x7f
+#       define VCLK_DIR_CNTL_EN                         (1 << 8)
+#define CG_VCLK_STATUS                                  0x61c
+
 #define GENERAL_PWRMGT                                  0x63c
 #       define STATIC_PM_EN                             (1 << 1)
 
Signature · 1 line
1.7.7.5
#100 lore raw

PATCH 86/165 drm/radeon: add dpm UVD handling for TN asics (v2)

In reply to [email protected]

From: Alex Deucher <[email protected]>

v2: fix typo noticed by Dan Carpenter

---
 drivers/gpu/drm/radeon/ppsmc.h       |    1 +
 drivers/gpu/drm/radeon/trinity_dpm.c |  220 ++++++++++++++++++++++++++++++++++
 drivers/gpu/drm/radeon/trinity_dpm.h |   18 +++
 drivers/gpu/drm/radeon/trinity_smc.c |    5 +
 drivers/gpu/drm/radeon/trinityd.h    |    5 +
 5 files changed, 249 insertions(+), 0 deletions(-)
drivers/gpu/drm/radeon/ppsmc.h +1 -0
index 8ef479a..3d0786f 100644
@@ -75,6 +75,7 @@ typedef uint8_t PPSMC_Result;
 #define PPSMC_MSG_PG_SIMD_Config            ((uint32_t) 0x108)
 #define PPSMC_MSG_DCE_RemoveVoltageAdjustment   ((uint32_t) 0x11d)
 #define PPSMC_MSG_DCE_AllowVoltageAdjustment    ((uint32_t) 0x11e)
+#define PPSMC_MSG_UVD_DPM_Config            ((uint32_t) 0x124)
 
 
 typedef uint16_t PPSMC_Msg;
drivers/gpu/drm/radeon/trinity_dpm.c +220 -0

274 lines not on this page · raw message

drivers/gpu/drm/radeon/trinity_dpm.h +18 -0
index 15e050f..31100ac 100644
@@ -55,14 +55,29 @@ struct trinity_ps {
 	u8 Dpm0PgNbPsHi;
 	u8 DpmXNbPsLo;
 	u8 DpmXNbPsHi;
+
+	u32 vclk_low_divider;
+	u32 vclk_high_divider;
+	u32 dclk_low_divider;
+	u32 dclk_high_divider;
 };
 
 #define TRINITY_NUM_NBPSTATES   4
 
+struct trinity_uvd_clock_table_entry
+{
+	u32 vclk;
+	u32 dclk;
+	u8 vclk_did;
+	u8 dclk_did;
+	u8 rsv[2];
+};
+
 struct trinity_sys_info {
 	u32 bootup_uma_clk;
 	u32 bootup_sclk;
 	u32 min_sclk;
+	u32 dentist_vco_freq;
 	u32 nb_dpm_enable;
 	u32 nbp_mclk[TRINITY_NUM_NBPSTATES];
 	u32 nbp_nclk[TRINITY_NUM_NBPSTATES];
@@ -73,6 +88,7 @@ struct trinity_sys_info {
 	struct sumo_sclk_voltage_mapping_table sclk_voltage_mapping_table;
 	struct sumo_vid_mapping_table vid_mapping_table;
 	u32 uma_channel_number;
+	struct trinity_uvd_clock_table_entry uvd_clock_table_entries[4];
 };
 
 struct trinity_power_info {
@@ -93,12 +109,14 @@ struct trinity_power_info {
 	bool enable_auto_thermal_throttling;
 	bool enable_dpm;
 	bool enable_sclk_ds;
+	bool uvd_dpm;
 };
 
 #define TRINITY_AT_DFLT            30
 
 /* trinity_smc.c */
 int trinity_dpm_config(struct radeon_device *rdev, bool enable);
+int trinity_uvd_dpm_config(struct radeon_device *rdev);
 int trinity_dpm_force_state(struct radeon_device *rdev, u32 n);
 int trinity_dpm_no_forced_level(struct radeon_device *rdev);
 int trinity_dce_enable_voltage_adjustment(struct radeon_device *rdev,
drivers/gpu/drm/radeon/trinity_smc.c +5 -0
index 60ffc1e..85f86a2 100644
@@ -73,6 +73,11 @@ int trinity_dpm_force_state(struct radeon_device *rdev, u32 n)
 	return trinity_notify_message_to_smu(rdev, PPSMC_MSG_DPM_ForceState);
 }
 
+int trinity_uvd_dpm_config(struct radeon_device *rdev)
+{
+	return trinity_notify_message_to_smu(rdev, PPSMC_MSG_UVD_DPM_Config);
+}
+
 int trinity_dpm_no_forced_level(struct radeon_device *rdev)
 {
 	return trinity_notify_message_to_smu(rdev, PPSMC_MSG_NoForcedLevel);
drivers/gpu/drm/radeon/trinityd.h +5 -0
index b234d36..fd32e27 100644
@@ -100,6 +100,9 @@
 #       define HT_MASK                                  (0xffff << 16)
 #       define HT_SHIFT                                 16
 
+#define SMU_UVD_DPM_STATES                              0x1f1a0
+#define SMU_UVD_DPM_CNTL                                0x1f1a4
+
 #define SMU_S_PG_CNTL                                   0x1f118
 #       define DS_PG_EN(x)                              ((x) << 16)
 #       define DS_PG_EN_MASK                            (0xff << 16)
@@ -198,6 +201,8 @@
 #       define SU_MASK                                  (0xffff << 16)
 #       define SU_SHIFT                                 16
 
+#define CG_MISC_REG                                     0x708
+
 #define CG_THERMAL_INT_CTRL                             0x738
 #       define DIG_THERM_INTH(x)                        ((x) << 0)
 #       define DIG_THERM_INTH_MASK                      (0xff << 0)
Signature · 1 line
1.7.7.5
#101 lore raw

PATCH 87/165 drm/radeon/kms: enable UVD as needed (v9)

In reply to [email protected]

From: Alex Deucher <[email protected]>

When using UVD, the driver must switch to a special UVD power state. In the CS ioctl, switch to the power state and schedule work to change the power state back, when the work comes up, check if uvd is still busy and if not, switch back to the user state, otherwise, reschedule the work.

Note: We really need some better way to decide when to switch out of the uvd power state. Switching power states while playback is active make uvd angry.

V2: fix locking.

V3: switch from timer to delayed work

V4: check fence driver for UVD jobs, reduce timeout to
1 second and rearm timeout on activity

v5: rebase on new dpm tree

v6: rebase on interim uvd on demand changes

v7: fix UVD when DPM is disabled

v8: unify non-DPM and DPM UVD handling

v9: remove leftover idle work struct

---
 drivers/gpu/drm/radeon/radeon.h     |    1 +
 drivers/gpu/drm/radeon/radeon_cs.c  |    1 +
 drivers/gpu/drm/radeon/radeon_pm.c  |   12 +++++++++++-
 drivers/gpu/drm/radeon/radeon_uvd.c |   24 +++++++++++++++++++-----
 4 files changed, 32 insertions(+), 6 deletions(-)
drivers/gpu/drm/radeon/radeon.h +1 -0
index 037773d..3b345cc 100644
@@ -1246,6 +1246,7 @@ struct radeon_dpm {
 	int			current_active_crtc_count;
 	/* special states active */
 	bool                    thermal_active;
+	bool                    uvd_active;
 	/* thermal handling */
 	struct radeon_dpm_thermal thermal;
 };
drivers/gpu/drm/radeon/radeon_cs.c +1 -0
index 7e265a5..4f6b22b 100644
@@ -550,6 +550,7 @@ int radeon_cs_ioctl(struct drm_device *dev, void *data, struct drm_file *filp)
 		return r;
 	}
 
+	/* XXX pick SD/HD/MVC */
 	if (parser.ring == R600_RING_TYPE_UVD_INDEX)
 		radeon_uvd_note_usage(rdev);
 
drivers/gpu/drm/radeon/radeon_pm.c +11 -1
index e6fce0b..5987580 100644
@@ -699,7 +699,8 @@ static void radeon_dpm_change_power_state_locked(struct radeon_device *rdev)
 
 	if (rdev->pm.dpm.user_state != rdev->pm.dpm.state) {
 		/* add other state override checks here */
-		if (!rdev->pm.dpm.thermal_active)
+		if ((!rdev->pm.dpm.thermal_active) &&
+		    (!rdev->pm.dpm.uvd_active))
 			rdev->pm.dpm.state = rdev->pm.dpm.user_state;
 	}
 	dpm_state = rdev->pm.dpm.state;
@@ -769,8 +770,16 @@ void radeon_dpm_enable_power_state(struct radeon_device *rdev,
 	case POWER_STATE_TYPE_INTERNAL_THERMAL:
 		rdev->pm.dpm.thermal_active = true;
 		break;
+	case POWER_STATE_TYPE_INTERNAL_UVD:
+	case POWER_STATE_TYPE_INTERNAL_UVD_SD:
+	case POWER_STATE_TYPE_INTERNAL_UVD_HD:
+	case POWER_STATE_TYPE_INTERNAL_UVD_HD2:
+	case POWER_STATE_TYPE_INTERNAL_UVD_MVC:
+		rdev->pm.dpm.uvd_active = true;
+		break;
 	default:
 		rdev->pm.dpm.thermal_active = false;
+		rdev->pm.dpm.uvd_active = false;
 		break;
 	}
 	rdev->pm.dpm.state = dpm_state;
@@ -1223,6 +1232,7 @@ static void radeon_pm_compute_clocks_dpm(struct radeon_device *rdev)
 	radeon_dpm_change_power_state_locked(rdev);
 
 	mutex_unlock(&rdev->pm.mutex);
+
 }
 
 void radeon_pm_compute_clocks(struct radeon_device *rdev)
drivers/gpu/drm/radeon/radeon_uvd.c +19 -5
index fdc77d1..ce5a10c 100644
@@ -699,11 +699,19 @@ static void radeon_uvd_idle_work_handler(struct work_struct *work)
 	struct radeon_device *rdev =
 		container_of(work, struct radeon_device, uvd.idle_work.work);
 
-	if (radeon_fence_count_emitted(rdev, R600_RING_TYPE_UVD_INDEX) == 0)
-		radeon_set_uvd_clocks(rdev, 0, 0);
-	else
+	if (radeon_fence_count_emitted(rdev, R600_RING_TYPE_UVD_INDEX) == 0) {
+		if ((rdev->pm.pm_method == PM_METHOD_DPM) && rdev->pm.dpm_enabled) {
+			mutex_lock(&rdev->pm.mutex);
+			rdev->pm.dpm.uvd_active = false;
+			mutex_unlock(&rdev->pm.mutex);
+			radeon_pm_compute_clocks(rdev);
+		} else {
+			radeon_set_uvd_clocks(rdev, 0, 0);
+		}
+	} else {
 		schedule_delayed_work(&rdev->uvd.idle_work,
 				      msecs_to_jiffies(UVD_IDLE_TIMEOUT_MS));
+	}
 }
 
 void radeon_uvd_note_usage(struct radeon_device *rdev)
@@ -711,8 +719,14 @@ void radeon_uvd_note_usage(struct radeon_device *rdev)
 	bool set_clocks = !cancel_delayed_work_sync(&rdev->uvd.idle_work);
 	set_clocks &= schedule_delayed_work(&rdev->uvd.idle_work,
 					    msecs_to_jiffies(UVD_IDLE_TIMEOUT_MS));
-	if (set_clocks)
-		radeon_set_uvd_clocks(rdev, 53300, 40000);
+	if (set_clocks) {
+		if ((rdev->pm.pm_method == PM_METHOD_DPM) && rdev->pm.dpm_enabled) {
+			/* XXX pick SD/HD/MVC */
+			radeon_dpm_enable_power_state(rdev, POWER_STATE_TYPE_INTERNAL_UVD);
+		} else {
+			radeon_set_uvd_clocks(rdev, 53300, 40000);
+		}
+	}
 }
 
 static unsigned radeon_uvd_calc_upll_post_div(unsigned vco_freq,
Signature · 6 lines
1.7.7.5

_______________________________________________
dri-devel mailing list
[email protected]
http://lists.freedesktop.org/mailman/listinfo/dri-devel
#102 lore raw

PATCH 88/165 drm/radeon/dpm: add helpers for extended power tables (v2)

In reply to [email protected]

From: Alex Deucher <[email protected]>

This data will be needed for dpm on newer asics.

v2: fix typo in rebase

---
 drivers/gpu/drm/radeon/r600_dpm.c |  179 +++++++++++++++++++++++++++++++++++++
 drivers/gpu/drm/radeon/r600_dpm.h |    3 +
 drivers/gpu/drm/radeon/radeon.h   |   70 ++++++++++++++
 3 files changed, 252 insertions(+), 0 deletions(-)
drivers/gpu/drm/radeon/r600_dpm.c +179 -0
index bf396a0..c9f9647 100644
@@ -721,3 +721,182 @@ bool r600_is_internal_thermal_sensor(enum radeon_int_thermal_type sensor)
 		return false;
 	}
 }
+
+union power_info {
+	struct _ATOM_POWERPLAY_INFO info;
+	struct _ATOM_POWERPLAY_INFO_V2 info_2;
+	struct _ATOM_POWERPLAY_INFO_V3 info_3;
+	struct _ATOM_PPLIB_POWERPLAYTABLE pplib;
+	struct _ATOM_PPLIB_POWERPLAYTABLE2 pplib2;
+	struct _ATOM_PPLIB_POWERPLAYTABLE3 pplib3;
+	struct _ATOM_PPLIB_POWERPLAYTABLE4 pplib4;
+	struct _ATOM_PPLIB_POWERPLAYTABLE5 pplib5;
+};
+
+union fan_info {
+	struct _ATOM_PPLIB_FANTABLE fan;
+	struct _ATOM_PPLIB_FANTABLE2 fan2;
+};
+
+static int r600_parse_clk_voltage_dep_table(struct radeon_clock_voltage_dependency_table *radeon_table,
+					    ATOM_PPLIB_Clock_Voltage_Dependency_Table *atom_table)
+{
+	u32 size = atom_table->ucNumEntries *
+		sizeof(struct radeon_clock_voltage_dependency_entry);
+	int i;
+
+	radeon_table->entries = kzalloc(size, GFP_KERNEL);
+	if (!radeon_table->entries)
+		return -ENOMEM;
+
+	for (i = 0; i < atom_table->ucNumEntries; i++) {
+		radeon_table->entries[i].clk = le16_to_cpu(atom_table->entries[i].usClockLow) |
+			(atom_table->entries[i].ucClockHigh << 16);
+		radeon_table->entries[i].v = le16_to_cpu(atom_table->entries[i].usVoltage);
+	}
+	radeon_table->count = atom_table->ucNumEntries;
+
+	return 0;
+}
+
+int r600_parse_extended_power_table(struct radeon_device *rdev)
+{
+	struct radeon_mode_info *mode_info = &rdev->mode_info;
+	union power_info *power_info;
+	union fan_info *fan_info;
+	ATOM_PPLIB_Clock_Voltage_Dependency_Table *dep_table;
+	int index = GetIndexIntoMasterTable(DATA, PowerPlayInfo);
+        u16 data_offset;
+	u8 frev, crev;
+	int ret, i;
+
+	if (!atom_parse_data_header(mode_info->atom_context, index, NULL,
+				   &frev, &crev, &data_offset))
+		return -EINVAL;
+	power_info = (union power_info *)(mode_info->atom_context->bios + data_offset);
+
+	/* fan table */
+	if (power_info->pplib.usTableSize >= sizeof(struct _ATOM_PPLIB_POWERPLAYTABLE3)) {
+		if (power_info->pplib3.usFanTableOffset) {
+			fan_info = (union fan_info *)(mode_info->atom_context->bios + data_offset +
+						      le16_to_cpu(power_info->pplib3.usFanTableOffset));
+			rdev->pm.dpm.fan.t_hyst = fan_info->fan.ucTHyst;
+			rdev->pm.dpm.fan.t_min = le16_to_cpu(fan_info->fan.usTMin);
+			rdev->pm.dpm.fan.t_med = le16_to_cpu(fan_info->fan.usTMed);
+			rdev->pm.dpm.fan.t_high = le16_to_cpu(fan_info->fan.usTHigh);
+			rdev->pm.dpm.fan.pwm_min = le16_to_cpu(fan_info->fan.usPWMMin);
+			rdev->pm.dpm.fan.pwm_med = le16_to_cpu(fan_info->fan.usPWMMed);
+			rdev->pm.dpm.fan.pwm_high = le16_to_cpu(fan_info->fan.usPWMHigh);
+			if (fan_info->fan.ucFanTableFormat >= 2)
+				rdev->pm.dpm.fan.t_max = le16_to_cpu(fan_info->fan2.usTMax);
+			else
+				rdev->pm.dpm.fan.t_max = 10900;
+			rdev->pm.dpm.fan.cycle_delay = 100000;
+			rdev->pm.dpm.fan.ucode_fan_control = true;
+		}
+	}
+
+	/* clock dependancy tables */
+	if (power_info->pplib.usTableSize >= sizeof(struct _ATOM_PPLIB_POWERPLAYTABLE4)) {
+		if (power_info->pplib4.usVddcDependencyOnSCLKOffset) {
+			dep_table = (ATOM_PPLIB_Clock_Voltage_Dependency_Table *)
+				(mode_info->atom_context->bios + data_offset +
+				 le16_to_cpu(power_info->pplib4.usVddcDependencyOnSCLKOffset));
+			ret = r600_parse_clk_voltage_dep_table(&rdev->pm.dpm.dyn_state.vddc_dependency_on_sclk,
+							       dep_table);
+			if (ret)
+				return ret;
+		}
+		if (power_info->pplib4.usVddciDependencyOnMCLKOffset) {
+			dep_table = (ATOM_PPLIB_Clock_Voltage_Dependency_Table *)
+				(mode_info->atom_context->bios + data_offset +
+				 le16_to_cpu(power_info->pplib4.usVddciDependencyOnMCLKOffset));
+			ret = r600_parse_clk_voltage_dep_table(&rdev->pm.dpm.dyn_state.vddci_dependency_on_mclk,
+							       dep_table);
+			if (ret) {
+				kfree(rdev->pm.dpm.dyn_state.vddc_dependency_on_sclk.entries);
+				return ret;
+			}
+		}
+		if (power_info->pplib4.usVddcDependencyOnMCLKOffset) {
+			dep_table = (ATOM_PPLIB_Clock_Voltage_Dependency_Table *)
+				(mode_info->atom_context->bios + data_offset +
+				 le16_to_cpu(power_info->pplib4.usVddcDependencyOnMCLKOffset));
+			ret = r600_parse_clk_voltage_dep_table(&rdev->pm.dpm.dyn_state.vddc_dependency_on_mclk,
+							       dep_table);
+			if (ret) {
+				kfree(rdev->pm.dpm.dyn_state.vddc_dependency_on_sclk.entries);
+				kfree(rdev->pm.dpm.dyn_state.vddci_dependency_on_mclk.entries);
+				return ret;
+			}
+		}
+		if (power_info->pplib4.usMaxClockVoltageOnDCOffset) {
+			ATOM_PPLIB_Clock_Voltage_Limit_Table *clk_v =
+				(ATOM_PPLIB_Clock_Voltage_Limit_Table *)
+				(mode_info->atom_context->bios + data_offset +
+				 le16_to_cpu(power_info->pplib4.usMaxClockVoltageOnDCOffset));
+			if (clk_v->ucNumEntries) {
+				rdev->pm.dpm.dyn_state.max_clock_voltage_on_dc.sclk =
+					le16_to_cpu(clk_v->entries[0].usSclkLow) |
+					(clk_v->entries[0].ucSclkHigh << 16);
+				rdev->pm.dpm.dyn_state.max_clock_voltage_on_dc.mclk =
+					le16_to_cpu(clk_v->entries[0].usMclkLow) |
+					(clk_v->entries[0].ucMclkHigh << 16);
+				rdev->pm.dpm.dyn_state.max_clock_voltage_on_dc.vddc =
+					le16_to_cpu(clk_v->entries[0].usVddc);
+				rdev->pm.dpm.dyn_state.max_clock_voltage_on_dc.vddci =
+					le16_to_cpu(clk_v->entries[0].usVddci);
+			}
+		}
+	}
+
+	/* cac data */
+	if (power_info->pplib.usTableSize >= sizeof(struct _ATOM_PPLIB_POWERPLAYTABLE5)) {
+		rdev->pm.dpm.tdp_limit = le32_to_cpu(power_info->pplib5.ulTDPLimit);
+		rdev->pm.dpm.near_tdp_limit = le32_to_cpu(power_info->pplib5.ulNearTDPLimit);
+		rdev->pm.dpm.tdp_od_limit = le16_to_cpu(power_info->pplib5.usTDPODLimit);
+		if (rdev->pm.dpm.tdp_od_limit)
+			rdev->pm.dpm.power_control = true;
+		else
+			rdev->pm.dpm.power_control = false;
+		rdev->pm.dpm.tdp_adjustment = 0;
+		rdev->pm.dpm.sq_ramping_threshold = le32_to_cpu(power_info->pplib5.ulSQRampingThreshold);
+		rdev->pm.dpm.cac_leakage = le32_to_cpu(power_info->pplib5.ulCACLeakage);
+		rdev->pm.dpm.load_line_slope = le16_to_cpu(power_info->pplib5.usLoadLineSlope);
+		if (power_info->pplib5.usCACLeakageTableOffset) {
+			ATOM_PPLIB_CAC_Leakage_Table *cac_table =
+				(ATOM_PPLIB_CAC_Leakage_Table *)
+				(mode_info->atom_context->bios + data_offset +
+				 le16_to_cpu(power_info->pplib5.usCACLeakageTableOffset));
+			u32 size = cac_table->ucNumEntries * sizeof(struct radeon_cac_leakage_table);
+			rdev->pm.dpm.dyn_state.cac_leakage_table.entries = kzalloc(size, GFP_KERNEL);
+			if (!rdev->pm.dpm.dyn_state.cac_leakage_table.entries) {
+				kfree(rdev->pm.dpm.dyn_state.vddc_dependency_on_sclk.entries);
+				kfree(rdev->pm.dpm.dyn_state.vddci_dependency_on_mclk.entries);
+				kfree(rdev->pm.dpm.dyn_state.vddc_dependency_on_mclk.entries);
+				return -ENOMEM;
+			}
+			for (i = 0; i < cac_table->ucNumEntries; i++) {
+				rdev->pm.dpm.dyn_state.cac_leakage_table.entries[i].vddc =
+					le16_to_cpu(cac_table->entries[i].usVddc);
+				rdev->pm.dpm.dyn_state.cac_leakage_table.entries[i].leakage =
+					le32_to_cpu(cac_table->entries[i].ulLeakageValue);
+			}
+			rdev->pm.dpm.dyn_state.cac_leakage_table.count = cac_table->ucNumEntries;
+		}
+	}
+
+	return 0;
+}
+
+void r600_free_extended_power_table(struct radeon_device *rdev)
+{
+	if (rdev->pm.dpm.dyn_state.vddc_dependency_on_sclk.entries)
+		kfree(rdev->pm.dpm.dyn_state.vddc_dependency_on_sclk.entries);
+	if (rdev->pm.dpm.dyn_state.vddci_dependency_on_mclk.entries)
+		kfree(rdev->pm.dpm.dyn_state.vddci_dependency_on_mclk.entries);
+	if (rdev->pm.dpm.dyn_state.vddc_dependency_on_mclk.entries)
+		kfree(rdev->pm.dpm.dyn_state.vddc_dependency_on_mclk.entries);
+	if (rdev->pm.dpm.dyn_state.cac_leakage_table.entries)
+		kfree(rdev->pm.dpm.dyn_state.cac_leakage_table.entries);
+}
drivers/gpu/drm/radeon/r600_dpm.h +3 -0
index bd33aa1..c6b9e30 100644
@@ -215,4 +215,7 @@ int r600_set_thermal_temperature_range(struct radeon_device *rdev,
 				       int min_temp, int max_temp);
 bool r600_is_internal_thermal_sensor(enum radeon_int_thermal_type sensor);
 
+int r600_parse_extended_power_table(struct radeon_device *rdev);
+void r600_free_extended_power_table(struct radeon_device *rdev);
+
 #endif
drivers/gpu/drm/radeon/radeon.h +70 -0

82 lines not on this page · raw message

Signature · 1 line
1.7.7.5
#103 lore raw

PATCH 89/165 drm/radeon/dpm: track whether we are on AC or battery

In reply to [email protected]

From: Alex Deucher <[email protected]>

Driver needs this information to validate power states.

---
 drivers/gpu/drm/radeon/radeon.h    |    1 +
 drivers/gpu/drm/radeon/radeon_pm.c |    7 +++++++
 2 files changed, 8 insertions(+), 0 deletions(-)
drivers/gpu/drm/radeon/radeon.h +1 -0
index 5bdb0bd..53aba4f 100644
@@ -1314,6 +1314,7 @@ struct radeon_dpm {
 	u32 tdp_adjustment;
 	u16 load_line_slope;
 	bool power_control;
+	bool ac_power;
 	/* special states active */
 	bool                    thermal_active;
 	bool                    uvd_active;
drivers/gpu/drm/radeon/radeon_pm.c +7 -0
index 5987580..9ac261f 100644
@@ -1218,6 +1218,7 @@ static void radeon_pm_compute_clocks_dpm(struct radeon_device *rdev)
 
 	mutex_lock(&rdev->pm.mutex);
 
+	/* update active crtc counts */
 	rdev->pm.dpm.new_active_crtcs = 0;
 	rdev->pm.dpm.new_active_crtc_count = 0;
 	list_for_each_entry(crtc,
@@ -1229,6 +1230,12 @@ static void radeon_pm_compute_clocks_dpm(struct radeon_device *rdev)
 		}
 	}
 
+	/* update battery/ac status */
+	if (power_supply_is_system_supplied() > 0)
+		rdev->pm.dpm.ac_power = true;
+	else
+		rdev->pm.dpm.ac_power = false;
+
 	radeon_dpm_change_power_state_locked(rdev);
 
 	mutex_unlock(&rdev->pm.mutex);
Signature · 1 line
1.7.7.5
#104 lore raw

PATCH 90/165 drm/radeon/dpm: fixup dynamic state adjust for sumo

In reply to [email protected]

From: Alex Deucher <[email protected]>

Use a dedicated copy of the current power state since we may have to adjust it on the fly.

---
 drivers/gpu/drm/radeon/radeon.h    |    1 +
 drivers/gpu/drm/radeon/radeon_pm.c |   13 ++++++++++++-
 drivers/gpu/drm/radeon/sumo_dpm.c  |    5 +++++
 drivers/gpu/drm/radeon/sumo_dpm.h  |    1 +
 4 files changed, 19 insertions(+), 1 deletions(-)
drivers/gpu/drm/radeon/radeon.h +1 -0
index 53aba4f..a4d8d97 100644
@@ -1294,6 +1294,7 @@ struct radeon_dpm {
 	struct radeon_ps        *boot_ps;
 	/* default uvd power state */
 	struct radeon_ps        *uvd_ps;
+	struct radeon_ps        hw_ps;
 	enum radeon_pm_state_type state;
 	enum radeon_pm_state_type user_state;
 	u32                     platform_caps;
drivers/gpu/drm/radeon/radeon_pm.c +12 -1
index 9ac261f..7ee8cf6 100644
@@ -687,6 +687,17 @@ restart_search:
 	return NULL;
 }
 
+static void radeon_dpm_update_requested_ps(struct radeon_device *rdev,
+					   struct radeon_ps *ps)
+{
+	/* copy the ps to the hw ps and point the requested ps
+	 * at the hw state in case the driver wants to modify
+	 * the state dynamically.
+	 */
+	rdev->pm.dpm.hw_ps = *ps;
+	rdev->pm.dpm.requested_ps = &rdev->pm.dpm.hw_ps;
+}
+
 static void radeon_dpm_change_power_state_locked(struct radeon_device *rdev)
 {
 	int i;
@@ -707,7 +718,7 @@ static void radeon_dpm_change_power_state_locked(struct radeon_device *rdev)
 
 	ps = radeon_dpm_pick_power_state(rdev, dpm_state);
 	if (ps)
-		rdev->pm.dpm.requested_ps = ps;
+		radeon_dpm_update_requested_ps(rdev, ps);
 	else
 		return;
 
drivers/gpu/drm/radeon/sumo_dpm.c +5 -0
index cef25c4..3805302 100644
@@ -1072,6 +1072,11 @@ static void sumo_apply_state_adjust_rules(struct radeon_device *rdev)
 	u32 sclk_in_sr = pi->sys_info.min_sclk; /* ??? */
 	u32 i;
 
+	/* point to the hw copy since this function will modify the ps */
+	pi->hw_ps = *ps;
+	rdev->pm.dpm.hw_ps.ps_priv = &pi->hw_ps;
+	ps = &pi->hw_ps;
+
 	if (rps->class & ATOM_PPLIB_CLASSIFICATION_THERMAL)
 		return sumo_patch_thermal_state(rdev, ps, current_ps);
 
drivers/gpu/drm/radeon/sumo_dpm.h +1 -0
index d041a6c..a40b62a 100644
@@ -129,6 +129,7 @@ struct sumo_power_info {
 	bool enable_dynamic_patch_ps;
 	bool enable_dpm;
 	bool enable_boost;
+	struct sumo_ps hw_ps;
 };
 
 #define SUMO_UTC_DFLT_00                     0x48
Signature · 1 line
1.7.7.5
#105 lore raw

PATCH 91/165 drm/radeon/dpm: fixup dynamic state adjust for TN

In reply to [email protected]

From: Alex Deucher <[email protected]>

Use a dedicated copy of the current power state since we may have to adjust it on the fly.

---
 drivers/gpu/drm/radeon/trinity_dpm.c |    5 +++++
 drivers/gpu/drm/radeon/trinity_dpm.h |    1 +
 2 files changed, 6 insertions(+), 0 deletions(-)
drivers/gpu/drm/radeon/trinity_dpm.c +5 -0
index 1b3822f..0c1b50a 100644
@@ -1379,6 +1379,11 @@ static void trinity_apply_state_adjust_rules(struct radeon_device *rdev)
 	bool force_high;
 	u32 num_active_displays = rdev->pm.dpm.new_active_crtc_count;
 
+	/* point to the hw copy since this function will modify the ps */
+	pi->hw_ps = *ps;
+	rdev->pm.dpm.hw_ps.ps_priv = &pi->hw_ps;
+	ps = &pi->hw_ps;
+
 	if (rps->class & ATOM_PPLIB_CLASSIFICATION_THERMAL)
 		return trinity_patch_thermal_state(rdev, ps, current_ps);
 
drivers/gpu/drm/radeon/trinity_dpm.h +1 -0
index 31100ac..c663aed 100644
@@ -110,6 +110,7 @@ struct trinity_power_info {
 	bool enable_dpm;
 	bool enable_sclk_ds;
 	bool uvd_dpm;
+	struct trinity_ps hw_ps;
 };
 
 #define TRINITY_AT_DFLT            30
Signature · 1 line
1.7.7.5
#106 lore raw

PATCH 92/165 drm/radeon/dpm: fixup dynamic state adjust for btc (v2)

In reply to [email protected]

From: Alex Deucher <[email protected]>

Use a dedicated copy of the current power state since we may have to adjust it on the fly.

v2: fix up redundant state sets

---
 drivers/gpu/drm/radeon/btc_dpm.c     |  340 ++++++++++++++++++++++++++++++++++
 drivers/gpu/drm/radeon/btc_dpm.h     |    2 +
 drivers/gpu/drm/radeon/cypress_dpm.h |    1 +
 drivers/gpu/drm/radeon/radeon.h      |   13 ++
 drivers/gpu/drm/radeon/radeon_pm.c   |   43 ++++-
 drivers/gpu/drm/radeon/rv770_dpm.c   |   10 +
 6 files changed, 400 insertions(+), 9 deletions(-)
drivers/gpu/drm/radeon/btc_dpm.c +340 -0
index 2662ef0..989592e 100644
@@ -1152,6 +1152,164 @@ static const u32 turks_sysls_enable[] =
 
 #endif
 
+u32 btc_valid_sclk[] =
+{
+	5000,   10000,  15000,  20000,  25000,  30000,  35000,  40000,  45000,  50000,
+	55000,  60000,  65000,  70000,  75000,  80000,  85000,  90000,  95000,  100000,
+	105000, 110000, 11500,  120000, 125000, 130000, 135000, 140000, 145000, 150000,
+	155000, 160000, 165000, 170000, 175000, 180000, 185000, 190000, 195000, 200000
+};
+
+static const struct radeon_blacklist_clocks btc_blacklist_clocks[] =
+{
+        { 10000, 30000, RADEON_SCLK_UP },
+        { 15000, 30000, RADEON_SCLK_UP },
+        { 20000, 30000, RADEON_SCLK_UP },
+        { 25000, 30000, RADEON_SCLK_UP }
+};
+
+static void btc_apply_voltage_dependency_rules(struct radeon_clock_voltage_dependency_table *table,
+					       u32 clock, u16 max_voltage, u16 *voltage)
+{
+	u32 i;
+
+	if ((table == NULL) || (table->count == 0))
+		return;
+
+	for (i= 0; i < table->count; i++) {
+		if (clock <= table->entries[i].clk) {
+			if (*voltage < table->entries[i].v)
+				*voltage = (u16)((table->entries[i].v < max_voltage) ?
+						  table->entries[i].v : max_voltage);
+			return;
+		}
+	}
+
+	*voltage = (*voltage > max_voltage) ? *voltage : max_voltage;
+}
+
+static u32 btc_find_valid_clock(struct radeon_clock_array *clocks,
+				u32 max_clock, u32 requested_clock)
+{
+	unsigned int i;
+
+	if ((clocks == NULL) || (clocks->count == 0))
+		return (requested_clock < max_clock) ? requested_clock : max_clock;
+
+	for (i = 0; i < clocks->count; i++) {
+		if (clocks->values[i] >= requested_clock)
+			return (clocks->values[i] < max_clock) ? clocks->values[i] : max_clock;
+	}
+
+	return (clocks->values[clocks->count - 1] < max_clock) ?
+		clocks->values[clocks->count - 1] : max_clock;
+}
+
+static u32 btc_get_valid_mclk(struct radeon_device *rdev,
+			      u32 max_mclk, u32 requested_mclk)
+{
+	return btc_find_valid_clock(&rdev->pm.dpm.dyn_state.valid_mclk_values,
+				    max_mclk, requested_mclk);
+}
+
+static u32 btc_get_valid_sclk(struct radeon_device *rdev,
+			      u32 max_sclk, u32 requested_sclk)
+{
+	return btc_find_valid_clock(&rdev->pm.dpm.dyn_state.valid_sclk_values,
+				    max_sclk, requested_sclk);
+}
+
+static void btc_skip_blacklist_clocks(struct radeon_device *rdev,
+				      const u32 max_sclk, const u32 max_mclk,
+				      u32 *sclk, u32 *mclk)
+{
+	int i, num_blacklist_clocks;
+
+	if ((sclk == NULL) || (mclk == NULL))
+		return;
+
+	num_blacklist_clocks = ARRAY_SIZE(btc_blacklist_clocks);
+
+	for (i = 0; i < num_blacklist_clocks; i++) {
+		if ((btc_blacklist_clocks[i].sclk == *sclk) &&
+		    (btc_blacklist_clocks[i].mclk == *mclk))
+			break;
+	}
+
+	if (i < num_blacklist_clocks) {
+		if (btc_blacklist_clocks[i].action == RADEON_SCLK_UP) {
+			*sclk = btc_get_valid_sclk(rdev, max_sclk, *sclk + 1);
+
+			if (*sclk < max_sclk)
+				btc_skip_blacklist_clocks(rdev, max_sclk, max_mclk, sclk, mclk);
+		}
+	}
+}
+
+static void btc_adjust_clock_combinations(struct radeon_device *rdev,
+					  const struct radeon_clock_and_voltage_limits *max_limits,
+					  struct rv7xx_pl *pl)
+{
+
+	if ((pl->mclk == 0) || (pl->sclk == 0))
+		return;
+
+	if (pl->mclk == pl->sclk)
+		return;
+
+	if (pl->mclk > pl->sclk) {
+		if (((pl->mclk + (pl->sclk - 1)) / pl->sclk) > rdev->pm.dpm.dyn_state.mclk_sclk_ratio)
+			pl->sclk = btc_get_valid_sclk(rdev,
+						      max_limits->sclk,
+						      (pl->mclk +
+						       (rdev->pm.dpm.dyn_state.mclk_sclk_ratio - 1)) /
+						      rdev->pm.dpm.dyn_state.mclk_sclk_ratio);
+	} else {
+		if ((pl->sclk - pl->mclk) > rdev->pm.dpm.dyn_state.sclk_mclk_delta)
+			pl->mclk = btc_get_valid_mclk(rdev,
+						      max_limits->mclk,
+						      pl->sclk -
+						      rdev->pm.dpm.dyn_state.sclk_mclk_delta);
+	}
+}
+
+static u16 btc_find_voltage(struct atom_voltage_table *table, u16 voltage)
+{
+	unsigned int i;
+
+	for (i = 0; i < table->count; i++) {
+		if (voltage <= table->entries[i].value)
+			return table->entries[i].value;
+	}
+
+	return table->entries[table->count - 1].value;
+}
+
+static void btc_apply_voltage_delta_rules(struct radeon_device *rdev,
+					  u16 max_vddc, u16 max_vddci,
+					  u16 *vddc, u16 *vddci)
+{
+	struct evergreen_power_info *eg_pi = evergreen_get_pi(rdev);
+	u16 new_voltage;
+
+	if ((0 == *vddc) || (0 == *vddci))
+		return;
+
+	if (*vddc > *vddci) {
+		if ((*vddc - *vddci) > rdev->pm.dpm.dyn_state.vddc_vddci_delta) {
+			new_voltage = btc_find_voltage(&eg_pi->vddci_voltage_table,
+						       (*vddc - rdev->pm.dpm.dyn_state.vddc_vddci_delta));
+			*vddci = (new_voltage < max_vddci) ? new_voltage : max_vddci;
+		}
+	} else {
+		if ((*vddci - *vddc) > rdev->pm.dpm.dyn_state.vddc_vddci_delta) {
+			new_voltage = btc_find_voltage(&eg_pi->vddc_voltage_table,
+						       (*vddci - rdev->pm.dpm.dyn_state.vddc_vddci_delta));
+			*vddc = (new_voltage < max_vddc) ? new_voltage : max_vddc;
+		}
+	}
+}
+
 static void btc_enable_bif_dynamic_pcie_gen2(struct radeon_device *rdev,
 					     bool enable)
 {
@@ -1901,6 +2059,169 @@ static void btc_init_stutter_mode(struct radeon_device *rdev)
 	}
 }
 
+static void btc_apply_state_adjust_rules(struct radeon_device *rdev)
+{
+	struct evergreen_power_info *eg_pi = evergreen_get_pi(rdev);
+	struct radeon_ps *rps = rdev->pm.dpm.requested_ps;
+	struct rv7xx_ps *ps = rv770_get_ps(rps);
+	struct radeon_clock_and_voltage_limits *max_limits;
+	bool disable_mclk_switching;
+	u32 mclk, sclk;
+	u16 vddc, vddci;
+
+	/* point to the hw copy since this function will modify the ps */
+	eg_pi->hw_ps = *ps;
+	rdev->pm.dpm.hw_ps.ps_priv = &eg_pi->hw_ps;
+	ps = &eg_pi->hw_ps;
+
+	if (rdev->pm.dpm.new_active_crtc_count > 1)
+		disable_mclk_switching = true;
+	else
+		disable_mclk_switching = false;
+
+	if (rdev->pm.dpm.ac_power)
+		max_limits = &rdev->pm.dpm.dyn_state.max_clock_voltage_on_ac;
+	else
+		max_limits = &rdev->pm.dpm.dyn_state.max_clock_voltage_on_dc;
+
+	if (rdev->pm.dpm.ac_power == false) {
+		if (ps->high.mclk > max_limits->mclk)
+			ps->high.mclk = max_limits->mclk;
+		if (ps->high.sclk > max_limits->sclk)
+			ps->high.sclk = max_limits->sclk;
+		if (ps->high.vddc > max_limits->vddc)
+			ps->high.vddc = max_limits->vddc;
+		if (ps->high.vddci > max_limits->vddci)
+			ps->high.vddci = max_limits->vddci;
+
+		if (ps->medium.mclk > max_limits->mclk)
+			ps->medium.mclk = max_limits->mclk;
+		if (ps->medium.sclk > max_limits->sclk)
+			ps->medium.sclk = max_limits->sclk;
+		if (ps->medium.vddc > max_limits->vddc)
+			ps->medium.vddc = max_limits->vddc;
+		if (ps->medium.vddci > max_limits->vddci)
+			ps->medium.vddci = max_limits->vddci;
+
+		if (ps->low.mclk > max_limits->mclk)
+			ps->low.mclk = max_limits->mclk;
+		if (ps->low.sclk > max_limits->sclk)
+			ps->low.sclk = max_limits->sclk;
+		if (ps->low.vddc > max_limits->vddc)
+			ps->low.vddc = max_limits->vddc;
+		if (ps->low.vddci > max_limits->vddci)
+			ps->low.vddci = max_limits->vddci;
+	}
+
+	/* XXX validate the min clocks required for display */
+
+	if (disable_mclk_switching) {
+		sclk = ps->low.sclk;
+		mclk = ps->high.mclk;
+		vddc = ps->low.vddc;
+		vddci = ps->high.vddci;
+	} else {
+		sclk = ps->low.sclk;
+		mclk = ps->low.mclk;
+		vddc = ps->low.vddc;
+		vddci = ps->low.vddci;
+	}
+
+	/* adjusted low state */
+	ps->low.sclk = sclk;
+	ps->low.mclk = mclk;
+	ps->low.vddc = vddc;
+	ps->low.vddci = vddci;
+
+	btc_skip_blacklist_clocks(rdev, max_limits->sclk, max_limits->mclk,
+				  &ps->low.sclk, &ps->low.mclk);
+
+	/* adjusted medium, high states */
+	if (ps->medium.sclk < ps->low.sclk)
+		ps->medium.sclk = ps->low.sclk;
+	if (ps->medium.vddc < ps->low.vddc)
+		ps->medium.vddc = ps->low.vddc;
+	if (ps->high.sclk < ps->medium.sclk)
+		ps->high.sclk = ps->medium.sclk;
+	if (ps->high.vddc < ps->medium.vddc)
+		ps->high.vddc = ps->medium.vddc;
+
+	if (disable_mclk_switching) {
+		mclk = ps->low.mclk;
+		if (mclk < ps->medium.mclk)
+			mclk = ps->medium.mclk;
+		if (mclk < ps->high.mclk)
+			mclk = ps->high.mclk;
+		ps->low.mclk = mclk;
+		ps->low.vddci = vddci;
+		ps->medium.mclk = mclk;
+		ps->medium.vddci = vddci;
+		ps->high.mclk = mclk;
+		ps->high.vddci = vddci;
+	} else {
+		if (ps->medium.mclk < ps->low.mclk)
+			ps->medium.mclk = ps->low.mclk;
+		if (ps->medium.vddci < ps->low.vddci)
+			ps->medium.vddci = ps->low.vddci;
+		if (ps->high.mclk < ps->medium.mclk)
+			ps->high.mclk = ps->medium.mclk;
+		if (ps->high.vddci < ps->medium.vddci)
+			ps->high.vddci = ps->medium.vddci;
+	}
+
+	btc_skip_blacklist_clocks(rdev, max_limits->sclk, max_limits->mclk,
+				  &ps->medium.sclk, &ps->medium.mclk);
+	btc_skip_blacklist_clocks(rdev, max_limits->sclk, max_limits->mclk,
+				  &ps->high.sclk, &ps->high.mclk);
+
+	btc_adjust_clock_combinations(rdev, max_limits, &ps->low);
+	btc_adjust_clock_combinations(rdev, max_limits, &ps->medium);
+	btc_adjust_clock_combinations(rdev, max_limits, &ps->high);
+
+	btc_apply_voltage_dependency_rules(&rdev->pm.dpm.dyn_state.vddc_dependency_on_sclk,
+					   ps->low.sclk, max_limits->vddc, &ps->low.vddc);
+	btc_apply_voltage_dependency_rules(&rdev->pm.dpm.dyn_state.vddci_dependency_on_mclk,
+					   ps->low.mclk, max_limits->vddci, &ps->low.vddci);
+	btc_apply_voltage_dependency_rules(&rdev->pm.dpm.dyn_state.vddc_dependency_on_mclk,
+					   ps->low.mclk, max_limits->vddc, &ps->low.vddc);
+	/* XXX validate the voltage required for display */
+	btc_apply_voltage_dependency_rules(&rdev->pm.dpm.dyn_state.vddc_dependency_on_sclk,
+					   ps->medium.sclk, max_limits->vddc, &ps->medium.vddc);
+	btc_apply_voltage_dependency_rules(&rdev->pm.dpm.dyn_state.vddci_dependency_on_mclk,
+					   ps->medium.mclk, max_limits->vddci, &ps->medium.vddci);
+	btc_apply_voltage_dependency_rules(&rdev->pm.dpm.dyn_state.vddc_dependency_on_mclk,
+					   ps->medium.mclk, max_limits->vddc, &ps->medium.vddc);
+	/* XXX validate the voltage required for display */
+	btc_apply_voltage_dependency_rules(&rdev->pm.dpm.dyn_state.vddc_dependency_on_sclk,
+					   ps->high.sclk, max_limits->vddc, &ps->high.vddc);
+	btc_apply_voltage_dependency_rules(&rdev->pm.dpm.dyn_state.vddci_dependency_on_mclk,
+					   ps->high.mclk, max_limits->vddci, &ps->high.vddci);
+	btc_apply_voltage_dependency_rules(&rdev->pm.dpm.dyn_state.vddc_dependency_on_mclk,
+					   ps->high.mclk, max_limits->vddc, &ps->high.vddc);
+	/* XXX validate the voltage required for display */
+
+	btc_apply_voltage_delta_rules(rdev, max_limits->vddc, max_limits->vddci,
+				      &ps->low.vddc, &ps->low.vddci);
+	btc_apply_voltage_delta_rules(rdev, max_limits->vddc, max_limits->vddci,
+				      &ps->medium.vddc, &ps->medium.vddci);
+	btc_apply_voltage_delta_rules(rdev, max_limits->vddc, max_limits->vddci,
+				      &ps->high.vddc, &ps->high.vddci);
+
+	if ((ps->high.vddc <= rdev->pm.dpm.dyn_state.max_clock_voltage_on_dc.vddc) &&
+	    (ps->medium.vddc <= rdev->pm.dpm.dyn_state.max_clock_voltage_on_dc.vddc) &&
+	    (ps->low.vddc <= rdev->pm.dpm.dyn_state.max_clock_voltage_on_dc.vddc))
+		ps->dc_compatible = true;
+	else
+		ps->dc_compatible = false;
+
+	if (ps->low.vddc < rdev->pm.dpm.dyn_state.min_vddc_for_pcie_gen2)
+		ps->low.flags &= ~ATOM_PPLIB_R600_FLAGS_PCIEGEN2;
+	if (ps->medium.vddc < rdev->pm.dpm.dyn_state.min_vddc_for_pcie_gen2)
+		ps->medium.flags &= ~ATOM_PPLIB_R600_FLAGS_PCIEGEN2;
+	if (ps->high.vddc < rdev->pm.dpm.dyn_state.min_vddc_for_pcie_gen2)
+		ps->high.flags &= ~ATOM_PPLIB_R600_FLAGS_PCIEGEN2;
+}
+
 void btc_dpm_reset_asic(struct radeon_device *rdev)
 {
 	rv770_restrict_performance_levels_before_switch(rdev);
@@ -1913,6 +2234,8 @@ int btc_dpm_set_power_state(struct radeon_device *rdev)
 {
 	struct evergreen_power_info *eg_pi = evergreen_get_pi(rdev);
 
+	btc_apply_state_adjust_rules(rdev);
+
 	btc_disable_ulv(rdev);
 	btc_set_boot_state_timing(rdev);
 	rv770_restrict_performance_levels_before_switch(rdev);
@@ -2121,6 +2444,9 @@ int btc_dpm_init(struct radeon_device *rdev)
 	ret = rv7xx_parse_power_table(rdev);
 	if (ret)
 		return ret;
+	ret = r600_parse_extended_power_table(rdev);
+	if (ret)
+		return ret;
 
 	if (rdev->pm.dpm.voltage_response_time == 0)
 		rdev->pm.dpm.voltage_response_time = R600_VOLTAGERESPONSETIME_DFLT;
@@ -2230,6 +2556,19 @@ int btc_dpm_init(struct radeon_device *rdev)
 
 	pi->sram_end = SMC_RAM_END;
 
+	rdev->pm.dpm.dyn_state.mclk_sclk_ratio = 4;
+	rdev->pm.dpm.dyn_state.vddc_vddci_delta = 200;
+	rdev->pm.dpm.dyn_state.min_vddc_for_pcie_gen2 = 900;
+	rdev->pm.dpm.dyn_state.valid_sclk_values.count = ARRAY_SIZE(btc_valid_sclk);
+	rdev->pm.dpm.dyn_state.valid_sclk_values.values = btc_valid_sclk;
+	rdev->pm.dpm.dyn_state.valid_mclk_values.count = 0;
+	rdev->pm.dpm.dyn_state.valid_mclk_values.values = NULL;
+
+	if (rdev->family == CHIP_TURKS)
+		rdev->pm.dpm.dyn_state.sclk_mclk_delta = 15000;
+	else
+		rdev->pm.dpm.dyn_state.sclk_mclk_delta = 10000;
+
 	return 0;
 }
 
@@ -2242,4 +2581,5 @@ void btc_dpm_fini(struct radeon_device *rdev)
 	}
 	kfree(rdev->pm.dpm.ps);
 	kfree(rdev->pm.dpm.priv);
+	r600_free_extended_power_table(rdev);
 }
drivers/gpu/drm/radeon/btc_dpm.h +2 -0
index 56b1957..807024d 100644
@@ -33,4 +33,6 @@
 #define BTC_CGULVPARAMETER_DFLT                       0x00040035
 #define BTC_CGULVCONTROL_DFLT                         0x00001450
 
+extern u32 btc_valid_sclk[];
+
 #endif
drivers/gpu/drm/radeon/cypress_dpm.h +1 -0
index 029bc9d..9e24d7a 100644
@@ -88,6 +88,7 @@ struct evergreen_power_info {
 	struct at ats[2];
 	/* smc offsets */
 	u16 mc_reg_table_start;
+	struct rv7xx_ps hw_ps;
 };
 
 #define CYPRESS_HASI_DFLT                               400000
drivers/gpu/drm/radeon/radeon.h +13 -0
index a4d8d97..16c7d52 100644
@@ -1222,6 +1222,19 @@ struct radeon_dpm_thermal {
 	bool               high_to_low;
 };
 
+enum radeon_clk_action
+{
+	RADEON_SCLK_UP = 1,
+	RADEON_SCLK_DOWN
+};
+
+struct radeon_blacklist_clocks
+{
+	u32 sclk;
+	u32 mclk;
+	enum radeon_clk_action action;
+};
+
 struct radeon_clock_and_voltage_limits {
 	u32 sclk;
 	u32 mclk;
drivers/gpu/drm/radeon/radeon_pm.c +34 -9

51 lines not on this page · raw message

drivers/gpu/drm/radeon/rv770_dpm.c +10 -0
index 55e5126..f5efa4c 100644
@@ -2165,6 +2165,16 @@ static void rv7xx_parse_pplib_clock_info(struct radeon_device *rdev,
 		pl->vddc = vddc;
 		pl->vddci = vddci;
 	}
+
+	if (rdev->family >= CHIP_BARTS) {
+		if ((rps->class & ATOM_PPLIB_CLASSIFICATION_UI_MASK) ==
+		    ATOM_PPLIB_CLASSIFICATION_UI_PERFORMANCE) {
+			rdev->pm.dpm.dyn_state.max_clock_voltage_on_ac.sclk = pl->sclk;
+			rdev->pm.dpm.dyn_state.max_clock_voltage_on_ac.mclk = pl->mclk;
+			rdev->pm.dpm.dyn_state.max_clock_voltage_on_ac.vddc = pl->vddc;
+			rdev->pm.dpm.dyn_state.max_clock_voltage_on_ac.vddci = pl->vddci;
+		}
+	}
 }
 
 int rv7xx_parse_power_table(struct radeon_device *rdev)
Signature · 1 line
1.7.7.5
#107 lore raw

PATCH 93/165 drm/radeon/kms: add dpm support for cayman

In reply to [email protected]

From: Alex Deucher <[email protected]>

This adds dpm support for cayman asics. This includes:
- clockgating
- dynamic engine clock scaling
- dynamic memory clock scaling
- dynamic voltage scaling
- dynamic pcie gen1/gen2 switching (requires additional acpi support)
- power containment
- shader power scaling

Set radeon.dpm=1 to enable.

---
 drivers/gpu/drm/radeon/Makefile       |    2 +-
 drivers/gpu/drm/radeon/btc_dpm.c      |   36 +-
 drivers/gpu/drm/radeon/btc_dpm.h      |   20 +-
 drivers/gpu/drm/radeon/cypress_dpm.c  |   11 +-
 drivers/gpu/drm/radeon/cypress_dpm.h  |    4 +
 drivers/gpu/drm/radeon/ni.c           |    4 +-
 drivers/gpu/drm/radeon/ni_dpm.c       | 4093 +++++++++++++++++++++++++++++++++
 drivers/gpu/drm/radeon/ni_dpm.h       |  233 ++
 drivers/gpu/drm/radeon/nid.h          |  552 +++++
 drivers/gpu/drm/radeon/nislands_smc.h |  329 +++
 drivers/gpu/drm/radeon/ppsmc.h        |   12 +
 drivers/gpu/drm/radeon/radeon_asic.c  |   12 +
 drivers/gpu/drm/radeon/radeon_asic.h  |   10 +
 drivers/gpu/drm/radeon/radeon_pm.c    |    1 +
 drivers/gpu/drm/radeon/radeon_ucode.h |    5 +
 drivers/gpu/drm/radeon/rv770_smc.c    |   27 +
 16 files changed, 5323 insertions(+), 28 deletions(-)
 create mode 100644 drivers/gpu/drm/radeon/ni_dpm.c
 create mode 100644 drivers/gpu/drm/radeon/ni_dpm.h
 create mode 100644 drivers/gpu/drm/radeon/nislands_smc.h
drivers/gpu/drm/radeon/Makefile +1 -1
index 2239ec2..32d1c7f 100644
@@ -79,7 +79,7 @@ radeon-y += radeon_device.o radeon_asic.o radeon_kms.o \
 	si_blit_shaders.o radeon_prime.o radeon_uvd.o cik.o cik_blit_shaders.o \
 	r600_dpm.o rs780_dpm.o rv6xx_dpm.o rv770_dpm.o rv730_dpm.o rv740_dpm.o \
 	rv770_smc.o cypress_dpm.o btc_dpm.o sumo_dpm.o sumo_smc.o trinity_dpm.o \
-	trinity_smc.o
+	trinity_smc.o ni_dpm.o
 
 radeon-$(CONFIG_COMPAT) += radeon_ioc32.o
 radeon-$(CONFIG_VGA_SWITCHEROO) += radeon_atpx_handler.o
drivers/gpu/drm/radeon/btc_dpm.c +18 -18
index 989592e..79f5ed4 100644
@@ -1152,7 +1152,7 @@ static const u32 turks_sysls_enable[] =
 
 #endif
 
-u32 btc_valid_sclk[] =
+u32 btc_valid_sclk[40] =
 {
 	5000,   10000,  15000,  20000,  25000,  30000,  35000,  40000,  45000,  50000,
 	55000,  60000,  65000,  70000,  75000,  80000,  85000,  90000,  95000,  100000,
@@ -1168,8 +1168,8 @@ static const struct radeon_blacklist_clocks btc_blacklist_clocks[] =
         { 25000, 30000, RADEON_SCLK_UP }
 };
 
-static void btc_apply_voltage_dependency_rules(struct radeon_clock_voltage_dependency_table *table,
-					       u32 clock, u16 max_voltage, u16 *voltage)
+void btc_apply_voltage_dependency_rules(struct radeon_clock_voltage_dependency_table *table,
+					u32 clock, u16 max_voltage, u16 *voltage)
 {
 	u32 i;
 
@@ -1219,9 +1219,9 @@ static u32 btc_get_valid_sclk(struct radeon_device *rdev,
 				    max_sclk, requested_sclk);
 }
 
-static void btc_skip_blacklist_clocks(struct radeon_device *rdev,
-				      const u32 max_sclk, const u32 max_mclk,
-				      u32 *sclk, u32 *mclk)
+void btc_skip_blacklist_clocks(struct radeon_device *rdev,
+			       const u32 max_sclk, const u32 max_mclk,
+			       u32 *sclk, u32 *mclk)
 {
 	int i, num_blacklist_clocks;
 
@@ -1246,9 +1246,9 @@ static void btc_skip_blacklist_clocks(struct radeon_device *rdev,
 	}
 }
 
-static void btc_adjust_clock_combinations(struct radeon_device *rdev,
-					  const struct radeon_clock_and_voltage_limits *max_limits,
-					  struct rv7xx_pl *pl)
+void btc_adjust_clock_combinations(struct radeon_device *rdev,
+				   const struct radeon_clock_and_voltage_limits *max_limits,
+				   struct rv7xx_pl *pl)
 {
 
 	if ((pl->mclk == 0) || (pl->sclk == 0))
@@ -1285,9 +1285,9 @@ static u16 btc_find_voltage(struct atom_voltage_table *table, u16 voltage)
 	return table->entries[table->count - 1].value;
 }
 
-static void btc_apply_voltage_delta_rules(struct radeon_device *rdev,
-					  u16 max_vddc, u16 max_vddci,
-					  u16 *vddc, u16 *vddci)
+void btc_apply_voltage_delta_rules(struct radeon_device *rdev,
+				   u16 max_vddc, u16 max_vddci,
+				   u16 *vddc, u16 *vddci)
 {
 	struct evergreen_power_info *eg_pi = evergreen_get_pi(rdev);
 	u16 new_voltage;
@@ -1417,8 +1417,8 @@ static int btc_populate_smc_acpi_state(struct radeon_device *rdev,
 	return ret;
 }
 
-static void btc_program_mgcg_hw_sequence(struct radeon_device *rdev,
-					 const u32 *sequence, u32 count)
+void btc_program_mgcg_hw_sequence(struct radeon_device *rdev,
+				  const u32 *sequence, u32 count)
 {
 	u32 i, length = count * 3;
 	u32 tmp;
@@ -1596,7 +1596,7 @@ static void btc_ls_clock_gating_enable(struct radeon_device *rdev,
 	btc_program_mgcg_hw_sequence(rdev, p, count);
 }
 
-static bool btc_dpm_enabled(struct radeon_device *rdev)
+bool btc_dpm_enabled(struct radeon_device *rdev)
 {
 	if (rv770_is_smc_running(rdev))
 		return true;
@@ -1692,7 +1692,7 @@ static void btc_set_at_for_uvd(struct radeon_device *rdev)
 
 }
 
-static void btc_notify_uvd_to_smc(struct radeon_device *rdev)
+void btc_notify_uvd_to_smc(struct radeon_device *rdev)
 {
 	struct radeon_ps *radeon_new_state = rdev->pm.dpm.requested_ps;
 	struct evergreen_power_info *eg_pi = evergreen_get_pi(rdev);
@@ -1708,7 +1708,7 @@ static void btc_notify_uvd_to_smc(struct radeon_device *rdev)
 	}
 }
 
-static int btc_reset_to_default(struct radeon_device *rdev)
+int btc_reset_to_default(struct radeon_device *rdev)
 {
 	if (rv770_send_msg_to_smc(rdev, PPSMC_MSG_ResetToDefaults) != PPSMC_Result_OK)
 		return -EINVAL;
@@ -1730,7 +1730,7 @@ static void btc_stop_smc(struct radeon_device *rdev)
 	r7xx_stop_smc(rdev);
 }
 
-static void btc_read_arb_registers(struct radeon_device *rdev)
+void btc_read_arb_registers(struct radeon_device *rdev)
 {
 	struct evergreen_power_info *eg_pi = evergreen_get_pi(rdev);
 	struct evergreen_arb_registers *arb_registers =
drivers/gpu/drm/radeon/btc_dpm.h +19 -1
index 807024d..c22d39f 100644
@@ -33,6 +33,24 @@
 #define BTC_CGULVPARAMETER_DFLT                       0x00040035
 #define BTC_CGULVCONTROL_DFLT                         0x00001450
 
-extern u32 btc_valid_sclk[];
+extern u32 btc_valid_sclk[40];
+
+void btc_read_arb_registers(struct radeon_device *rdev);
+void btc_program_mgcg_hw_sequence(struct radeon_device *rdev,
+				  const u32 *sequence, u32 count);
+void btc_skip_blacklist_clocks(struct radeon_device *rdev,
+			       const u32 max_sclk, const u32 max_mclk,
+			       u32 *sclk, u32 *mclk);
+void btc_adjust_clock_combinations(struct radeon_device *rdev,
+				   const struct radeon_clock_and_voltage_limits *max_limits,
+				   struct rv7xx_pl *pl);
+void btc_apply_voltage_dependency_rules(struct radeon_clock_voltage_dependency_table *table,
+					u32 clock, u16 max_voltage, u16 *voltage);
+void btc_apply_voltage_delta_rules(struct radeon_device *rdev,
+				   u16 max_vddc, u16 max_vddci,
+				   u16 *vddc, u16 *vddci);
+bool btc_dpm_enabled(struct radeon_device *rdev);
+int btc_reset_to_default(struct radeon_device *rdev);
+void btc_notify_uvd_to_smc(struct radeon_device *rdev);
 
 #endif
drivers/gpu/drm/radeon/cypress_dpm.c +4 -7
index 403ee15..22297b1 100644
@@ -45,9 +45,6 @@ struct rv7xx_ps *rv770_get_ps(struct radeon_ps *rps);
 struct rv7xx_power_info *rv770_get_pi(struct radeon_device *rdev);
 struct evergreen_power_info *evergreen_get_pi(struct radeon_device *rdev);
 
-static u8 cypress_get_mclk_frequency_ratio(struct radeon_device *rdev,
-					   u32 memory_clock, bool strobe_mode);
-
 static void cypress_enable_bif_dynamic_pcie_gen2(struct radeon_device *rdev,
 						 bool enable)
 {
@@ -416,7 +413,7 @@ static int cypress_populate_voltage_value(struct radeon_device *rdev,
 	return 0;
 }
 
-static u8 cypress_get_strobe_mode_settings(struct radeon_device *rdev, u32 mclk)
+u8 cypress_get_strobe_mode_settings(struct radeon_device *rdev, u32 mclk)
 {
 	struct rv7xx_power_info *pi = rv770_get_pi(rdev);
 	u8 result = 0;
@@ -434,7 +431,7 @@ static u8 cypress_get_strobe_mode_settings(struct radeon_device *rdev, u32 mclk)
 	return result;
 }
 
-static u32 cypress_map_clkf_to_ibias(struct radeon_device *rdev, u32 clkf)
+u32 cypress_map_clkf_to_ibias(struct radeon_device *rdev, u32 clkf)
 {
 	u32 ref_clk = rdev->clock.mpll.reference_freq;
 	u32 vco = clkf * ref_clk;
@@ -603,8 +600,8 @@ static int cypress_populate_mclk_value(struct radeon_device *rdev,
 	return 0;
 }
 
-static u8 cypress_get_mclk_frequency_ratio(struct radeon_device *rdev,
-					   u32 memory_clock, bool strobe_mode)
+u8 cypress_get_mclk_frequency_ratio(struct radeon_device *rdev,
+				    u32 memory_clock, bool strobe_mode)
 {
 	u8 mc_para_index;
 
drivers/gpu/drm/radeon/cypress_dpm.h +4 -0
index 9e24d7a..9b6198e 100644
@@ -141,5 +141,9 @@ void cypress_enable_mclk_control(struct radeon_device *rdev,
 				 bool enable);
 void cypress_start_dpm(struct radeon_device *rdev);
 void cypress_advertise_gen2_capability(struct radeon_device *rdev);
+u32 cypress_map_clkf_to_ibias(struct radeon_device *rdev, u32 clkf);
+u8 cypress_get_mclk_frequency_ratio(struct radeon_device *rdev,
+				    u32 memory_clock, bool strobe_mode);
+u8 cypress_get_strobe_mode_settings(struct radeon_device *rdev, u32 mclk);
 
 #endif
drivers/gpu/drm/radeon/ni.c +3 -1
index 7407762..ad65143 100644
@@ -194,6 +194,7 @@ MODULE_FIRMWARE("radeon/CAYMAN_pfp.bin");
 MODULE_FIRMWARE("radeon/CAYMAN_me.bin");
 MODULE_FIRMWARE("radeon/CAYMAN_mc.bin");
 MODULE_FIRMWARE("radeon/CAYMAN_rlc.bin");
+MODULE_FIRMWARE("radeon/CAYMAN_smc.bin");
 MODULE_FIRMWARE("radeon/ARUBA_pfp.bin");
 MODULE_FIRMWARE("radeon/ARUBA_me.bin");
 MODULE_FIRMWARE("radeon/ARUBA_rlc.bin");
@@ -734,6 +735,7 @@ int ni_init_microcode(struct radeon_device *rdev)
 		me_req_size = CAYMAN_PM4_UCODE_SIZE * 4;
 		rlc_req_size = CAYMAN_RLC_UCODE_SIZE * 4;
 		mc_req_size = CAYMAN_MC_UCODE_SIZE * 4;
+		smc_req_size = ALIGN(CAYMAN_SMC_UCODE_SIZE, 4);
 		break;
 	case CHIP_ARUBA:
 		chip_name = "ARUBA";
@@ -797,7 +799,7 @@ int ni_init_microcode(struct radeon_device *rdev)
 		}
 	}
 
-	if ((rdev->family >= CHIP_BARTS) && (rdev->family <= CHIP_CAICOS)) {
+	if ((rdev->family >= CHIP_BARTS) && (rdev->family <= CHIP_CAYMAN)) {
 		snprintf(fw_name, sizeof(fw_name), "radeon/%s_smc.bin", chip_name);
 		err = request_firmware(&rdev->smc_fw, fw_name, &pdev->dev);
 		if (err)
drivers/gpu/drm/radeon/ni_dpm.c new file +4093 -0

2,805 lines not on this page · raw message

drivers/gpu/drm/radeon/ni_dpm.h new file +233 -0

233 lines not on this page · raw message

drivers/gpu/drm/radeon/nid.h +552 -0

552 lines not on this page · raw message

drivers/gpu/drm/radeon/nislands_smc.h new file +329 -0

329 lines not on this page · raw message

drivers/gpu/drm/radeon/ppsmc.h +12 -0
index 3d0786f..607982a 100644

Lines of this file are not shown. View the raw message.

drivers/gpu/drm/radeon/radeon_asic.c +12 -0
index 5dcbb28..e6703ef 100644

Lines of this file are not shown. View the raw message.

drivers/gpu/drm/radeon/radeon_asic.h +10 -0
index 4d3f93d..2fef64d 100644

Lines of this file are not shown. View the raw message.

drivers/gpu/drm/radeon/radeon_pm.c +1 -0
index 2eb41be..01ff18b 100644

Lines of this file are not shown. View the raw message.

drivers/gpu/drm/radeon/radeon_ucode.h +5 -0
index e592e27..51beb4c 100644

Lines of this file are not shown. View the raw message.

drivers/gpu/drm/radeon/rv770_smc.c +27 -0
index 0078c59..ab95da5 100644

Lines of this file are not shown. View the raw message.

The rest of this diff is not shown. View the raw message.

Signature · 1 line
1.7.7.5

Part of the diff is not shown here. View the raw message.

Reviewed-by on v1 93/165
#108 lore raw

Re: [PATCH 093/165] drm/radeon/kms: add dpm support for cayman

Quoted 11 lines · On Wed, Jun 26, 2013 at 09:22:53AM -0400, [email protected] wrote:

From: Alex Deucher <[email protected]>

This adds dpm support for cayman asics. This includes:
- clockgating
- dynamic engine clock scaling
- dynamic memory clock scaling
- dynamic voltage scaling
- dynamic pcie gen1/gen2 switching (requires additional acpi support)
- power containment
- shader power scaling

Quoted 3 lines

Set radeon.dpm=1 to enable.

Quoted 1,480 lines
---
 drivers/gpu/drm/radeon/Makefile       |    2 +-
 drivers/gpu/drm/radeon/btc_dpm.c      |   36 +-
 drivers/gpu/drm/radeon/btc_dpm.h      |   20 +-
 drivers/gpu/drm/radeon/cypress_dpm.c  |   11 +-
 drivers/gpu/drm/radeon/cypress_dpm.h  |    4 +
 drivers/gpu/drm/radeon/ni.c           |    4 +-
 drivers/gpu/drm/radeon/ni_dpm.c       | 4093 +++++++++++++++++++++++++++++++++
 drivers/gpu/drm/radeon/ni_dpm.h       |  233 ++
 drivers/gpu/drm/radeon/nid.h          |  552 +++++
 drivers/gpu/drm/radeon/nislands_smc.h |  329 +++
 drivers/gpu/drm/radeon/ppsmc.h        |   12 +
 drivers/gpu/drm/radeon/radeon_asic.c  |   12 +
 drivers/gpu/drm/radeon/radeon_asic.h  |   10 +
 drivers/gpu/drm/radeon/radeon_pm.c    |    1 +
 drivers/gpu/drm/radeon/radeon_ucode.h |    5 +
 drivers/gpu/drm/radeon/rv770_smc.c    |   27 +
 16 files changed, 5323 insertions(+), 28 deletions(-)
 create mode 100644 drivers/gpu/drm/radeon/ni_dpm.c
 create mode 100644 drivers/gpu/drm/radeon/ni_dpm.h
 create mode 100644 drivers/gpu/drm/radeon/nislands_smc.h
drivers/gpu/drm/radeon/Makefile +1 -1
index 2239ec2..32d1c7f 100644
@@ -79,7 +79,7 @@ radeon-y += radeon_device.o radeon_asic.o radeon_kms.o \
 	si_blit_shaders.o radeon_prime.o radeon_uvd.o cik.o cik_blit_shaders.o \
 	r600_dpm.o rs780_dpm.o rv6xx_dpm.o rv770_dpm.o rv730_dpm.o rv740_dpm.o \
 	rv770_smc.o cypress_dpm.o btc_dpm.o sumo_dpm.o sumo_smc.o trinity_dpm.o \
-	trinity_smc.o
+	trinity_smc.o ni_dpm.o
 
 radeon-$(CONFIG_COMPAT) += radeon_ioc32.o
 radeon-$(CONFIG_VGA_SWITCHEROO) += radeon_atpx_handler.o
drivers/gpu/drm/radeon/btc_dpm.c +18 -18
index 989592e..79f5ed4 100644
@@ -1152,7 +1152,7 @@ static const u32 turks_sysls_enable[] =
 
 #endif
 
-u32 btc_valid_sclk[] =
+u32 btc_valid_sclk[40] =
 {
 	5000,   10000,  15000,  20000,  25000,  30000,  35000,  40000,  45000,  50000,
 	55000,  60000,  65000,  70000,  75000,  80000,  85000,  90000,  95000,  100000,
@@ -1168,8 +1168,8 @@ static const struct radeon_blacklist_clocks btc_blacklist_clocks[] =
         { 25000, 30000, RADEON_SCLK_UP }
 };
 
-static void btc_apply_voltage_dependency_rules(struct radeon_clock_voltage_dependency_table *table,
-					       u32 clock, u16 max_voltage, u16 *voltage)
+void btc_apply_voltage_dependency_rules(struct radeon_clock_voltage_dependency_table *table,
+					u32 clock, u16 max_voltage, u16 *voltage)
 {
 	u32 i;
 
@@ -1219,9 +1219,9 @@ static u32 btc_get_valid_sclk(struct radeon_device *rdev,
 				    max_sclk, requested_sclk);
 }
 
-static void btc_skip_blacklist_clocks(struct radeon_device *rdev,
-				      const u32 max_sclk, const u32 max_mclk,
-				      u32 *sclk, u32 *mclk)
+void btc_skip_blacklist_clocks(struct radeon_device *rdev,
+			       const u32 max_sclk, const u32 max_mclk,
+			       u32 *sclk, u32 *mclk)
 {
 	int i, num_blacklist_clocks;
 
@@ -1246,9 +1246,9 @@ static void btc_skip_blacklist_clocks(struct radeon_device *rdev,
 	}
 }
 
-static void btc_adjust_clock_combinations(struct radeon_device *rdev,
-					  const struct radeon_clock_and_voltage_limits *max_limits,
-					  struct rv7xx_pl *pl)
+void btc_adjust_clock_combinations(struct radeon_device *rdev,
+				   const struct radeon_clock_and_voltage_limits *max_limits,
+				   struct rv7xx_pl *pl)
 {
 
 	if ((pl->mclk == 0) || (pl->sclk == 0))
@@ -1285,9 +1285,9 @@ static u16 btc_find_voltage(struct atom_voltage_table *table, u16 voltage)
 	return table->entries[table->count - 1].value;
 }
 
-static void btc_apply_voltage_delta_rules(struct radeon_device *rdev,
-					  u16 max_vddc, u16 max_vddci,
-					  u16 *vddc, u16 *vddci)
+void btc_apply_voltage_delta_rules(struct radeon_device *rdev,
+				   u16 max_vddc, u16 max_vddci,
+				   u16 *vddc, u16 *vddci)
 {
 	struct evergreen_power_info *eg_pi = evergreen_get_pi(rdev);
 	u16 new_voltage;
@@ -1417,8 +1417,8 @@ static int btc_populate_smc_acpi_state(struct radeon_device *rdev,
 	return ret;
 }
 
-static void btc_program_mgcg_hw_sequence(struct radeon_device *rdev,
-					 const u32 *sequence, u32 count)
+void btc_program_mgcg_hw_sequence(struct radeon_device *rdev,
+				  const u32 *sequence, u32 count)
 {
 	u32 i, length = count * 3;
 	u32 tmp;
@@ -1596,7 +1596,7 @@ static void btc_ls_clock_gating_enable(struct radeon_device *rdev,
 	btc_program_mgcg_hw_sequence(rdev, p, count);
 }
 
-static bool btc_dpm_enabled(struct radeon_device *rdev)
+bool btc_dpm_enabled(struct radeon_device *rdev)
 {
 	if (rv770_is_smc_running(rdev))
 		return true;
@@ -1692,7 +1692,7 @@ static void btc_set_at_for_uvd(struct radeon_device *rdev)
 
 }
 
-static void btc_notify_uvd_to_smc(struct radeon_device *rdev)
+void btc_notify_uvd_to_smc(struct radeon_device *rdev)
 {
 	struct radeon_ps *radeon_new_state = rdev->pm.dpm.requested_ps;
 	struct evergreen_power_info *eg_pi = evergreen_get_pi(rdev);
@@ -1708,7 +1708,7 @@ static void btc_notify_uvd_to_smc(struct radeon_device *rdev)
 	}
 }
 
-static int btc_reset_to_default(struct radeon_device *rdev)
+int btc_reset_to_default(struct radeon_device *rdev)
 {
 	if (rv770_send_msg_to_smc(rdev, PPSMC_MSG_ResetToDefaults) != PPSMC_Result_OK)
 		return -EINVAL;
@@ -1730,7 +1730,7 @@ static void btc_stop_smc(struct radeon_device *rdev)
 	r7xx_stop_smc(rdev);
 }
 
-static void btc_read_arb_registers(struct radeon_device *rdev)
+void btc_read_arb_registers(struct radeon_device *rdev)
 {
 	struct evergreen_power_info *eg_pi = evergreen_get_pi(rdev);
 	struct evergreen_arb_registers *arb_registers =
drivers/gpu/drm/radeon/btc_dpm.h +19 -1
index 807024d..c22d39f 100644
@@ -33,6 +33,24 @@
 #define BTC_CGULVPARAMETER_DFLT                       0x00040035
 #define BTC_CGULVCONTROL_DFLT                         0x00001450
 
-extern u32 btc_valid_sclk[];
+extern u32 btc_valid_sclk[40];
+
+void btc_read_arb_registers(struct radeon_device *rdev);
+void btc_program_mgcg_hw_sequence(struct radeon_device *rdev,
+				  const u32 *sequence, u32 count);
+void btc_skip_blacklist_clocks(struct radeon_device *rdev,
+			       const u32 max_sclk, const u32 max_mclk,
+			       u32 *sclk, u32 *mclk);
+void btc_adjust_clock_combinations(struct radeon_device *rdev,
+				   const struct radeon_clock_and_voltage_limits *max_limits,
+				   struct rv7xx_pl *pl);
+void btc_apply_voltage_dependency_rules(struct radeon_clock_voltage_dependency_table *table,
+					u32 clock, u16 max_voltage, u16 *voltage);
+void btc_apply_voltage_delta_rules(struct radeon_device *rdev,
+				   u16 max_vddc, u16 max_vddci,
+				   u16 *vddc, u16 *vddci);
+bool btc_dpm_enabled(struct radeon_device *rdev);
+int btc_reset_to_default(struct radeon_device *rdev);
+void btc_notify_uvd_to_smc(struct radeon_device *rdev);
 
 #endif
drivers/gpu/drm/radeon/cypress_dpm.c +4 -7
index 403ee15..22297b1 100644
@@ -45,9 +45,6 @@ struct rv7xx_ps *rv770_get_ps(struct radeon_ps *rps);
 struct rv7xx_power_info *rv770_get_pi(struct radeon_device *rdev);
 struct evergreen_power_info *evergreen_get_pi(struct radeon_device *rdev);
 
-static u8 cypress_get_mclk_frequency_ratio(struct radeon_device *rdev,
-					   u32 memory_clock, bool strobe_mode);
-
 static void cypress_enable_bif_dynamic_pcie_gen2(struct radeon_device *rdev,
 						 bool enable)
 {
@@ -416,7 +413,7 @@ static int cypress_populate_voltage_value(struct radeon_device *rdev,
 	return 0;
 }
 
-static u8 cypress_get_strobe_mode_settings(struct radeon_device *rdev, u32 mclk)
+u8 cypress_get_strobe_mode_settings(struct radeon_device *rdev, u32 mclk)
 {
 	struct rv7xx_power_info *pi = rv770_get_pi(rdev);
 	u8 result = 0;
@@ -434,7 +431,7 @@ static u8 cypress_get_strobe_mode_settings(struct radeon_device *rdev, u32 mclk)
 	return result;
 }
 
-static u32 cypress_map_clkf_to_ibias(struct radeon_device *rdev, u32 clkf)
+u32 cypress_map_clkf_to_ibias(struct radeon_device *rdev, u32 clkf)
 {
 	u32 ref_clk = rdev->clock.mpll.reference_freq;
 	u32 vco = clkf * ref_clk;
@@ -603,8 +600,8 @@ static int cypress_populate_mclk_value(struct radeon_device *rdev,
 	return 0;
 }
 
-static u8 cypress_get_mclk_frequency_ratio(struct radeon_device *rdev,
-					   u32 memory_clock, bool strobe_mode)
+u8 cypress_get_mclk_frequency_ratio(struct radeon_device *rdev,
+				    u32 memory_clock, bool strobe_mode)
 {
 	u8 mc_para_index;
 
drivers/gpu/drm/radeon/cypress_dpm.h +4 -0
index 9e24d7a..9b6198e 100644
@@ -141,5 +141,9 @@ void cypress_enable_mclk_control(struct radeon_device *rdev,
 				 bool enable);
 void cypress_start_dpm(struct radeon_device *rdev);
 void cypress_advertise_gen2_capability(struct radeon_device *rdev);
+u32 cypress_map_clkf_to_ibias(struct radeon_device *rdev, u32 clkf);
+u8 cypress_get_mclk_frequency_ratio(struct radeon_device *rdev,
+				    u32 memory_clock, bool strobe_mode);
+u8 cypress_get_strobe_mode_settings(struct radeon_device *rdev, u32 mclk);
 
 #endif
drivers/gpu/drm/radeon/ni.c +3 -1
index 7407762..ad65143 100644
@@ -194,6 +194,7 @@ MODULE_FIRMWARE("radeon/CAYMAN_pfp.bin");
 MODULE_FIRMWARE("radeon/CAYMAN_me.bin");
 MODULE_FIRMWARE("radeon/CAYMAN_mc.bin");
 MODULE_FIRMWARE("radeon/CAYMAN_rlc.bin");
+MODULE_FIRMWARE("radeon/CAYMAN_smc.bin");
 MODULE_FIRMWARE("radeon/ARUBA_pfp.bin");
 MODULE_FIRMWARE("radeon/ARUBA_me.bin");
 MODULE_FIRMWARE("radeon/ARUBA_rlc.bin");
@@ -734,6 +735,7 @@ int ni_init_microcode(struct radeon_device *rdev)
 		me_req_size = CAYMAN_PM4_UCODE_SIZE * 4;
 		rlc_req_size = CAYMAN_RLC_UCODE_SIZE * 4;
 		mc_req_size = CAYMAN_MC_UCODE_SIZE * 4;
+		smc_req_size = ALIGN(CAYMAN_SMC_UCODE_SIZE, 4);
 		break;
 	case CHIP_ARUBA:
 		chip_name = "ARUBA";
@@ -797,7 +799,7 @@ int ni_init_microcode(struct radeon_device *rdev)
 		}
 	}
 
-	if ((rdev->family >= CHIP_BARTS) && (rdev->family <= CHIP_CAICOS)) {
+	if ((rdev->family >= CHIP_BARTS) && (rdev->family <= CHIP_CAYMAN)) {
 		snprintf(fw_name, sizeof(fw_name), "radeon/%s_smc.bin", chip_name);
 		err = request_firmware(&rdev->smc_fw, fw_name, &pdev->dev);
 		if (err)
drivers/gpu/drm/radeon/ni_dpm.c new file +1213 -0
new file mode 100644
index 0000000..635bf04
@@ -0,0 +1,4093 @@
+/*
+ * Copyright 2012 Advanced Micro Devices, Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ */
+
+#include "drmP.h"
+#include "radeon.h"
+#include "nid.h"
+#include "r600_dpm.h"
+#include "ni_dpm.h"
+#include "atom.h"
+
+#define MC_CG_ARB_FREQ_F0           0x0a
+#define MC_CG_ARB_FREQ_F1           0x0b
+#define MC_CG_ARB_FREQ_F2           0x0c
+#define MC_CG_ARB_FREQ_F3           0x0d
+
+#define SMC_RAM_END 0xC000
+
+static const struct ni_cac_weights cac_weights_cayman_xt =
+{
+	0x15,
+	0x2,
+	0x19,
+	0x2,
+	0x8,
+	0x14,
+	0x2,
+	0x16,
+	0xE,
+	0x17,
+	0x13,
+	0x2B,
+	0x10,
+	0x7,
+	0x5,
+	0x5,
+	0x5,
+	0x2,
+	0x3,
+	0x9,
+	0x10,
+	0x10,
+	0x2B,
+	0xA,
+	0x9,
+	0x4,
+	0xD,
+	0xD,
+	0x3E,
+	0x18,
+	0x14,
+	0,
+	0x3,
+	0x3,
+	0x5,
+	0,
+	0x2,
+	0,
+	0,
+	0,
+	0,
+	0,
+	0,
+	0,
+	0,
+	0,
+	0x1CC,
+	0,
+	0x164,
+	1,
+	1,
+	1,
+	1,
+	12,
+	12,
+	12,
+	0x12,
+	0x1F,
+	132,
+	5,
+	7,
+	0,
+	{ 0, 0, 0, 0, 0, 0, 0, 0 },
+	{ 0, 0, 0, 0 },
+	true
+};
+
+static const struct ni_cac_weights cac_weights_cayman_pro =
+{
+	0x16,
+	0x4,
+	0x10,
+	0x2,
+	0xA,
+	0x16,
+	0x2,
+	0x18,
+	0x10,
+	0x1A,
+	0x16,
+	0x2D,
+	0x12,
+	0xA,
+	0x6,
+	0x6,
+	0x6,
+	0x2,
+	0x4,
+	0xB,
+	0x11,
+	0x11,
+	0x2D,
+	0xC,
+	0xC,
+	0x7,
+	0x10,
+	0x10,
+	0x3F,
+	0x1A,
+	0x16,
+	0,
+	0x7,
+	0x4,
+	0x6,
+	1,
+	0x2,
+	0x1,
+	0,
+	0,
+	0,
+	0,
+	0,
+	0,
+	0x30,
+	0,
+	0x1CF,
+	0,
+	0x166,
+	1,
+	1,
+	1,
+	1,
+	12,
+	12,
+	12,
+	0x15,
+	0x1F,
+	132,
+	6,
+	6,
+	0,
+	{ 0, 0, 0, 0, 0, 0, 0, 0 },
+	{ 0, 0, 0, 0 },
+	true
+};
+
+static const struct ni_cac_weights cac_weights_cayman_le =
+{
+	0x7,
+	0xE,
+	0x1,
+	0xA,
+	0x1,
+	0x3F,
+	0x2,
+	0x18,
+	0x10,
+	0x1A,
+	0x1,
+	0x3F,
+	0x1,
+	0xE,
+	0x6,
+	0x6,
+	0x6,
+	0x2,
+	0x4,
+	0x9,
+	0x1A,
+	0x1A,
+	0x2C,
+	0xA,
+	0x11,
+	0x8,
+	0x19,
+	0x19,
+	0x1,
+	0x1,
+	0x1A,
+	0,
+	0x8,
+	0x5,
+	0x8,
+	0x1,
+	0x3,
+	0x1,
+	0,
+	0,
+	0,
+	0,
+	0,
+	0,
+	0x38,
+	0x38,
+	0x239,
+	0x3,
+	0x18A,
+	1,
+	1,
+	1,
+	1,
+	12,
+	12,
+	12,
+	0x15,
+	0x22,
+	132,
+	6,
+	6,
+	0,
+	{ 0, 0, 0, 0, 0, 0, 0, 0 },
+	{ 0, 0, 0, 0 },
+	true
+};
+
+#define NISLANDS_MGCG_SEQUENCE  300
+
+static const u32 cayman_cgcg_cgls_default[] =
+{
+	0x000008f8, 0x00000010, 0xffffffff,
+	0x000008fc, 0x00000000, 0xffffffff,
+	0x000008f8, 0x00000011, 0xffffffff,
+	0x000008fc, 0x00000000, 0xffffffff,
+	0x000008f8, 0x00000012, 0xffffffff,
+	0x000008fc, 0x00000000, 0xffffffff,
+	0x000008f8, 0x00000013, 0xffffffff,
+	0x000008fc, 0x00000000, 0xffffffff,
+	0x000008f8, 0x00000014, 0xffffffff,
+	0x000008fc, 0x00000000, 0xffffffff,
+	0x000008f8, 0x00000015, 0xffffffff,
+	0x000008fc, 0x00000000, 0xffffffff,
+	0x000008f8, 0x00000016, 0xffffffff,
+	0x000008fc, 0x00000000, 0xffffffff,
+	0x000008f8, 0x00000017, 0xffffffff,
+	0x000008fc, 0x00000000, 0xffffffff,
+	0x000008f8, 0x00000018, 0xffffffff,
+	0x000008fc, 0x00000000, 0xffffffff,
+	0x000008f8, 0x00000019, 0xffffffff,
+	0x000008fc, 0x00000000, 0xffffffff,
+	0x000008f8, 0x0000001a, 0xffffffff,
+	0x000008fc, 0x00000000, 0xffffffff,
+	0x000008f8, 0x0000001b, 0xffffffff,
+	0x000008fc, 0x00000000, 0xffffffff,
+	0x000008f8, 0x00000020, 0xffffffff,
+	0x000008fc, 0x00000000, 0xffffffff,
+	0x000008f8, 0x00000021, 0xffffffff,
+	0x000008fc, 0x00000000, 0xffffffff,
+	0x000008f8, 0x00000022, 0xffffffff,
+	0x000008fc, 0x00000000, 0xffffffff,
+	0x000008f8, 0x00000023, 0xffffffff,
+	0x000008fc, 0x00000000, 0xffffffff,
+	0x000008f8, 0x00000024, 0xffffffff,
+	0x000008fc, 0x00000000, 0xffffffff,
+	0x000008f8, 0x00000025, 0xffffffff,
+	0x000008fc, 0x00000000, 0xffffffff,
+	0x000008f8, 0x00000026, 0xffffffff,
+	0x000008fc, 0x00000000, 0xffffffff,
+	0x000008f8, 0x00000027, 0xffffffff,
+	0x000008fc, 0x00000000, 0xffffffff,
+	0x000008f8, 0x00000028, 0xffffffff,
+	0x000008fc, 0x00000000, 0xffffffff,
+	0x000008f8, 0x00000029, 0xffffffff,
+	0x000008fc, 0x00000000, 0xffffffff,
+	0x000008f8, 0x0000002a, 0xffffffff,
+	0x000008fc, 0x00000000, 0xffffffff,
+	0x000008f8, 0x0000002b, 0xffffffff,
+	0x000008fc, 0x00000000, 0xffffffff
+};
+#define CAYMAN_CGCG_CGLS_DEFAULT_LENGTH sizeof(cayman_cgcg_cgls_default) / (3 * sizeof(u32))
+
+static const u32 cayman_cgcg_cgls_disable[] =
+{
+	0x000008f8, 0x00000010, 0xffffffff,
+	0x000008fc, 0xffffffff, 0xffffffff,
+	0x000008f8, 0x00000011, 0xffffffff,
+	0x000008fc, 0xffffffff, 0xffffffff,
+	0x000008f8, 0x00000012, 0xffffffff,
+	0x000008fc, 0xffffffff, 0xffffffff,
+	0x000008f8, 0x00000013, 0xffffffff,
+	0x000008fc, 0xffffffff, 0xffffffff,
+	0x000008f8, 0x00000014, 0xffffffff,
+	0x000008fc, 0xffffffff, 0xffffffff,
+	0x000008f8, 0x00000015, 0xffffffff,
+	0x000008fc, 0xffffffff, 0xffffffff,
+	0x000008f8, 0x00000016, 0xffffffff,
+	0x000008fc, 0xffffffff, 0xffffffff,
+	0x000008f8, 0x00000017, 0xffffffff,
+	0x000008fc, 0xffffffff, 0xffffffff,
+	0x000008f8, 0x00000018, 0xffffffff,
+	0x000008fc, 0xffffffff, 0xffffffff,
+	0x000008f8, 0x00000019, 0xffffffff,
+	0x000008fc, 0xffffffff, 0xffffffff,
+	0x000008f8, 0x0000001a, 0xffffffff,
+	0x000008fc, 0xffffffff, 0xffffffff,
+	0x000008f8, 0x0000001b, 0xffffffff,
+	0x000008fc, 0xffffffff, 0xffffffff,
+	0x000008f8, 0x00000020, 0xffffffff,
+	0x000008fc, 0x00000000, 0xffffffff,
+	0x000008f8, 0x00000021, 0xffffffff,
+	0x000008fc, 0x00000000, 0xffffffff,
+	0x000008f8, 0x00000022, 0xffffffff,
+	0x000008fc, 0x00000000, 0xffffffff,
+	0x000008f8, 0x00000023, 0xffffffff,
+	0x000008fc, 0x00000000, 0xffffffff,
+	0x000008f8, 0x00000024, 0xffffffff,
+	0x000008fc, 0x00000000, 0xffffffff,
+	0x000008f8, 0x00000025, 0xffffffff,
+	0x000008fc, 0x00000000, 0xffffffff,
+	0x000008f8, 0x00000026, 0xffffffff,
+	0x000008fc, 0x00000000, 0xffffffff,
+	0x000008f8, 0x00000027, 0xffffffff,
+	0x000008fc, 0x00000000, 0xffffffff,
+	0x000008f8, 0x00000028, 0xffffffff,
+	0x000008fc, 0x00000000, 0xffffffff,
+	0x000008f8, 0x00000029, 0xffffffff,
+	0x000008fc, 0x00000000, 0xffffffff,
+	0x000008f8, 0x0000002a, 0xffffffff,
+	0x000008fc, 0x00000000, 0xffffffff,
+	0x000008f8, 0x0000002b, 0xffffffff,
+	0x000008fc, 0x00000000, 0xffffffff,
+	0x00000644, 0x000f7902, 0x001f4180,
+	0x00000644, 0x000f3802, 0x001f4180
+};
+#define CAYMAN_CGCG_CGLS_DISABLE_LENGTH sizeof(cayman_cgcg_cgls_disable) / (3 * sizeof(u32))
+
+static const u32 cayman_cgcg_cgls_enable[] =
+{
+	0x00000644, 0x000f7882, 0x001f4080,
+	0x000008f8, 0x00000010, 0xffffffff,
+	0x000008fc, 0x00000000, 0xffffffff,
+	0x000008f8, 0x00000011, 0xffffffff,
+	0x000008fc, 0x00000000, 0xffffffff,
+	0x000008f8, 0x00000012, 0xffffffff,
+	0x000008fc, 0x00000000, 0xffffffff,
+	0x000008f8, 0x00000013, 0xffffffff,
+	0x000008fc, 0x00000000, 0xffffffff,
+	0x000008f8, 0x00000014, 0xffffffff,
+	0x000008fc, 0x00000000, 0xffffffff,
+	0x000008f8, 0x00000015, 0xffffffff,
+	0x000008fc, 0x00000000, 0xffffffff,
+	0x000008f8, 0x00000016, 0xffffffff,
+	0x000008fc, 0x00000000, 0xffffffff,
+	0x000008f8, 0x00000017, 0xffffffff,
+	0x000008fc, 0x00000000, 0xffffffff,
+	0x000008f8, 0x00000018, 0xffffffff,
+	0x000008fc, 0x00000000, 0xffffffff,
+	0x000008f8, 0x00000019, 0xffffffff,
+	0x000008fc, 0x00000000, 0xffffffff,
+	0x000008f8, 0x0000001a, 0xffffffff,
+	0x000008fc, 0x00000000, 0xffffffff,
+	0x000008f8, 0x0000001b, 0xffffffff,
+	0x000008fc, 0x00000000, 0xffffffff,
+	0x000008f8, 0x00000020, 0xffffffff,
+	0x000008fc, 0xffffffff, 0xffffffff,
+	0x000008f8, 0x00000021, 0xffffffff,
+	0x000008fc, 0xffffffff, 0xffffffff,
+	0x000008f8, 0x00000022, 0xffffffff,
+	0x000008fc, 0xffffffff, 0xffffffff,
+	0x000008f8, 0x00000023, 0xffffffff,
+	0x000008fc, 0xffffffff, 0xffffffff,
+	0x000008f8, 0x00000024, 0xffffffff,
+	0x000008fc, 0xffffffff, 0xffffffff,
+	0x000008f8, 0x00000025, 0xffffffff,
+	0x000008fc, 0xffffffff, 0xffffffff,
+	0x000008f8, 0x00000026, 0xffffffff,
+	0x000008fc, 0xffffffff, 0xffffffff,
+	0x000008f8, 0x00000027, 0xffffffff,
+	0x000008fc, 0xffffffff, 0xffffffff,
+	0x000008f8, 0x00000028, 0xffffffff,
+	0x000008fc, 0xffffffff, 0xffffffff,
+	0x000008f8, 0x00000029, 0xffffffff,
+	0x000008fc, 0xffffffff, 0xffffffff,
+	0x000008f8, 0x0000002a, 0xffffffff,
+	0x000008fc, 0xffffffff, 0xffffffff,
+	0x000008f8, 0x0000002b, 0xffffffff,
+	0x000008fc, 0xffffffff, 0xffffffff
+};
+#define CAYMAN_CGCG_CGLS_ENABLE_LENGTH  sizeof(cayman_cgcg_cgls_enable) / (3 * sizeof(u32))
+
+static const u32 cayman_mgcg_default[] =
+{
+	0x0000802c, 0xc0000000, 0xffffffff,
+	0x00003fc4, 0xc0000000, 0xffffffff,
+	0x00005448, 0x00000100, 0xffffffff,
+	0x000055e4, 0x00000100, 0xffffffff,
+	0x0000160c, 0x00000100, 0xffffffff,
+	0x00008984, 0x06000100, 0xffffffff,
+	0x0000c164, 0x00000100, 0xffffffff,
+	0x00008a18, 0x00000100, 0xffffffff,
+	0x0000897c, 0x06000100, 0xffffffff,
+	0x00008b28, 0x00000100, 0xffffffff,
+	0x00009144, 0x00800200, 0xffffffff,
+	0x00009a60, 0x00000100, 0xffffffff,
+	0x00009868, 0x00000100, 0xffffffff,
+	0x00008d58, 0x00000100, 0xffffffff,
+	0x00009510, 0x00000100, 0xffffffff,
+	0x0000949c, 0x00000100, 0xffffffff,
+	0x00009654, 0x00000100, 0xffffffff,
+	0x00009030, 0x00000100, 0xffffffff,
+	0x00009034, 0x00000100, 0xffffffff,
+	0x00009038, 0x00000100, 0xffffffff,
+	0x0000903c, 0x00000100, 0xffffffff,
+	0x00009040, 0x00000100, 0xffffffff,
+	0x0000a200, 0x00000100, 0xffffffff,
+	0x0000a204, 0x00000100, 0xffffffff,
+	0x0000a208, 0x00000100, 0xffffffff,
+	0x0000a20c, 0x00000100, 0xffffffff,
+	0x00009744, 0x00000100, 0xffffffff,
+	0x00003f80, 0x00000100, 0xffffffff,
+	0x0000a210, 0x00000100, 0xffffffff,
+	0x0000a214, 0x00000100, 0xffffffff,
+	0x000004d8, 0x00000100, 0xffffffff,
+	0x00009664, 0x00000100, 0xffffffff,
+	0x00009698, 0x00000100, 0xffffffff,
+	0x000004d4, 0x00000200, 0xffffffff,
+	0x000004d0, 0x00000000, 0xffffffff,
+	0x000030cc, 0x00000104, 0xffffffff,
+	0x0000d0c0, 0x00000100, 0xffffffff,
+	0x0000d8c0, 0x00000100, 0xffffffff,
+	0x0000802c, 0x40000000, 0xffffffff,
+	0x00003fc4, 0x40000000, 0xffffffff,
+	0x0000915c, 0x00010000, 0xffffffff,
+	0x00009160, 0x00030002, 0xffffffff,
+	0x00009164, 0x00050004, 0xffffffff,
+	0x00009168, 0x00070006, 0xffffffff,
+	0x00009178, 0x00070000, 0xffffffff,
+	0x0000917c, 0x00030002, 0xffffffff,
+	0x00009180, 0x00050004, 0xffffffff,
+	0x0000918c, 0x00010006, 0xffffffff,
+	0x00009190, 0x00090008, 0xffffffff,
+	0x00009194, 0x00070000, 0xffffffff,
+	0x00009198, 0x00030002, 0xffffffff,
+	0x0000919c, 0x00050004, 0xffffffff,
+	0x000091a8, 0x00010006, 0xffffffff,
+	0x000091ac, 0x00090008, 0xffffffff,
+	0x000091b0, 0x00070000, 0xffffffff,
+	0x000091b4, 0x00030002, 0xffffffff,
+	0x000091b8, 0x00050004, 0xffffffff,
+	0x000091c4, 0x00010006, 0xffffffff,
+	0x000091c8, 0x00090008, 0xffffffff,
+	0x000091cc, 0x00070000, 0xffffffff,
+	0x000091d0, 0x00030002, 0xffffffff,
+	0x000091d4, 0x00050004, 0xffffffff,
+	0x000091e0, 0x00010006, 0xffffffff,
+	0x000091e4, 0x00090008, 0xffffffff,
+	0x000091e8, 0x00000000, 0xffffffff,
+	0x000091ec, 0x00070000, 0xffffffff,
+	0x000091f0, 0x00030002, 0xffffffff,
+	0x000091f4, 0x00050004, 0xffffffff,
+	0x00009200, 0x00010006, 0xffffffff,
+	0x00009204, 0x00090008, 0xffffffff,
+	0x00009208, 0x00070000, 0xffffffff,
+	0x0000920c, 0x00030002, 0xffffffff,
+	0x00009210, 0x00050004, 0xffffffff,
+	0x0000921c, 0x00010006, 0xffffffff,
+	0x00009220, 0x00090008, 0xffffffff,
+	0x00009224, 0x00070000, 0xffffffff,
+	0x00009228, 0x00030002, 0xffffffff,
+	0x0000922c, 0x00050004, 0xffffffff,
+	0x00009238, 0x00010006, 0xffffffff,
+	0x0000923c, 0x00090008, 0xffffffff,
+	0x00009240, 0x00070000, 0xffffffff,
+	0x00009244, 0x00030002, 0xffffffff,
+	0x00009248, 0x00050004, 0xffffffff,
+	0x00009254, 0x00010006, 0xffffffff,
+	0x00009258, 0x00090008, 0xffffffff,
+	0x0000925c, 0x00070000, 0xffffffff,
+	0x00009260, 0x00030002, 0xffffffff,
+	0x00009264, 0x00050004, 0xffffffff,
+	0x00009270, 0x00010006, 0xffffffff,
+	0x00009274, 0x00090008, 0xffffffff,
+	0x00009278, 0x00070000, 0xffffffff,
+	0x0000927c, 0x00030002, 0xffffffff,
+	0x00009280, 0x00050004, 0xffffffff,
+	0x0000928c, 0x00010006, 0xffffffff,
+	0x00009290, 0x00090008, 0xffffffff,
+	0x000092a8, 0x00070000, 0xffffffff,
+	0x000092ac, 0x00030002, 0xffffffff,
+	0x000092b0, 0x00050004, 0xffffffff,
+	0x000092bc, 0x00010006, 0xffffffff,
+	0x000092c0, 0x00090008, 0xffffffff,
+	0x000092c4, 0x00070000, 0xffffffff,
+	0x000092c8, 0x00030002, 0xffffffff,
+	0x000092cc, 0x00050004, 0xffffffff,
+	0x000092d8, 0x00010006, 0xffffffff,
+	0x000092dc, 0x00090008, 0xffffffff,
+	0x00009294, 0x00000000, 0xffffffff,
+	0x0000802c, 0x40010000, 0xffffffff,
+	0x00003fc4, 0x40010000, 0xffffffff,
+	0x0000915c, 0x00010000, 0xffffffff,
+	0x00009160, 0x00030002, 0xffffffff,
+	0x00009164, 0x00050004, 0xffffffff,
+	0x00009168, 0x00070006, 0xffffffff,
+	0x00009178, 0x00070000, 0xffffffff,
+	0x0000917c, 0x00030002, 0xffffffff,
+	0x00009180, 0x00050004, 0xffffffff,
+	0x0000918c, 0x00010006, 0xffffffff,
+	0x00009190, 0x00090008, 0xffffffff,
+	0x00009194, 0x00070000, 0xffffffff,
+	0x00009198, 0x00030002, 0xffffffff,
+	0x0000919c, 0x00050004, 0xffffffff,
+	0x000091a8, 0x00010006, 0xffffffff,
+	0x000091ac, 0x00090008, 0xffffffff,
+	0x000091b0, 0x00070000, 0xffffffff,
+	0x000091b4, 0x00030002, 0xffffffff,
+	0x000091b8, 0x00050004, 0xffffffff,
+	0x000091c4, 0x00010006, 0xffffffff,
+	0x000091c8, 0x00090008, 0xffffffff,
+	0x000091cc, 0x00070000, 0xffffffff,
+	0x000091d0, 0x00030002, 0xffffffff,
+	0x000091d4, 0x00050004, 0xffffffff,
+	0x000091e0, 0x00010006, 0xffffffff,
+	0x000091e4, 0x00090008, 0xffffffff,
+	0x000091e8, 0x00000000, 0xffffffff,
+	0x000091ec, 0x00070000, 0xffffffff,
+	0x000091f0, 0x00030002, 0xffffffff,
+	0x000091f4, 0x00050004, 0xffffffff,
+	0x00009200, 0x00010006, 0xffffffff,
+	0x00009204, 0x00090008, 0xffffffff,
+	0x00009208, 0x00070000, 0xffffffff,
+	0x0000920c, 0x00030002, 0xffffffff,
+	0x00009210, 0x00050004, 0xffffffff,
+	0x0000921c, 0x00010006, 0xffffffff,
+	0x00009220, 0x00090008, 0xffffffff,
+	0x00009224, 0x00070000, 0xffffffff,
+	0x00009228, 0x00030002, 0xffffffff,
+	0x0000922c, 0x00050004, 0xffffffff,
+	0x00009238, 0x00010006, 0xffffffff,
+	0x0000923c, 0x00090008, 0xffffffff,
+	0x00009240, 0x00070000, 0xffffffff,
+	0x00009244, 0x00030002, 0xffffffff,
+	0x00009248, 0x00050004, 0xffffffff,
+	0x00009254, 0x00010006, 0xffffffff,
+	0x00009258, 0x00090008, 0xffffffff,
+	0x0000925c, 0x00070000, 0xffffffff,
+	0x00009260, 0x00030002, 0xffffffff,
+	0x00009264, 0x00050004, 0xffffffff,
+	0x00009270, 0x00010006, 0xffffffff,
+	0x00009274, 0x00090008, 0xffffffff,
+	0x00009278, 0x00070000, 0xffffffff,
+	0x0000927c, 0x00030002, 0xffffffff,
+	0x00009280, 0x00050004, 0xffffffff,
+	0x0000928c, 0x00010006, 0xffffffff,
+	0x00009290, 0x00090008, 0xffffffff,
+	0x000092a8, 0x00070000, 0xffffffff,
+	0x000092ac, 0x00030002, 0xffffffff,
+	0x000092b0, 0x00050004, 0xffffffff,
+	0x000092bc, 0x00010006, 0xffffffff,
+	0x000092c0, 0x00090008, 0xffffffff,
+	0x000092c4, 0x00070000, 0xffffffff,
+	0x000092c8, 0x00030002, 0xffffffff,
+	0x000092cc, 0x00050004, 0xffffffff,
+	0x000092d8, 0x00010006, 0xffffffff,
+	0x000092dc, 0x00090008, 0xffffffff,
+	0x00009294, 0x00000000, 0xffffffff,
+	0x0000802c, 0xc0000000, 0xffffffff,
+	0x00003fc4, 0xc0000000, 0xffffffff,
+	0x000008f8, 0x00000010, 0xffffffff,
+	0x000008fc, 0x00000000, 0xffffffff,
+	0x000008f8, 0x00000011, 0xffffffff,
+	0x000008fc, 0x00000000, 0xffffffff,
+	0x000008f8, 0x00000012, 0xffffffff,
+	0x000008fc, 0x00000000, 0xffffffff,
+	0x000008f8, 0x00000013, 0xffffffff,
+	0x000008fc, 0x00000000, 0xffffffff,
+	0x000008f8, 0x00000014, 0xffffffff,
+	0x000008fc, 0x00000000, 0xffffffff,
+	0x000008f8, 0x00000015, 0xffffffff,
+	0x000008fc, 0x00000000, 0xffffffff,
+	0x000008f8, 0x00000016, 0xffffffff,
+	0x000008fc, 0x00000000, 0xffffffff,
+	0x000008f8, 0x00000017, 0xffffffff,
+	0x000008fc, 0x00000000, 0xffffffff,
+	0x000008f8, 0x00000018, 0xffffffff,
+	0x000008fc, 0x00000000, 0xffffffff,
+	0x000008f8, 0x00000019, 0xffffffff,
+	0x000008fc, 0x00000000, 0xffffffff,
+	0x000008f8, 0x0000001a, 0xffffffff,
+	0x000008fc, 0x00000000, 0xffffffff,
+	0x000008f8, 0x0000001b, 0xffffffff,
+	0x000008fc, 0x00000000, 0xffffffff
+};
+#define CAYMAN_MGCG_DEFAULT_LENGTH sizeof(cayman_mgcg_default) / (3 * sizeof(u32))
+
+static const u32 cayman_mgcg_disable[] =
+{
+	0x0000802c, 0xc0000000, 0xffffffff,
+	0x000008f8, 0x00000000, 0xffffffff,
+	0x000008fc, 0xffffffff, 0xffffffff,
+	0x000008f8, 0x00000001, 0xffffffff,
+	0x000008fc, 0xffffffff, 0xffffffff,
+	0x000008f8, 0x00000002, 0xffffffff,
+	0x000008fc, 0xffffffff, 0xffffffff,
+	0x000008f8, 0x00000003, 0xffffffff,
+	0x000008fc, 0xffffffff, 0xffffffff,
+	0x00009150, 0x00600000, 0xffffffff
+};
+#define CAYMAN_MGCG_DISABLE_LENGTH   sizeof(cayman_mgcg_disable) / (3 * sizeof(u32))
+
+static const u32 cayman_mgcg_enable[] =
+{
+	0x0000802c, 0xc0000000, 0xffffffff,
+	0x000008f8, 0x00000000, 0xffffffff,
+	0x000008fc, 0x00000000, 0xffffffff,
+	0x000008f8, 0x00000001, 0xffffffff,
+	0x000008fc, 0x00000000, 0xffffffff,
+	0x000008f8, 0x00000002, 0xffffffff,
+	0x000008fc, 0x00600000, 0xffffffff,
+	0x000008f8, 0x00000003, 0xffffffff,
+	0x000008fc, 0x00000000, 0xffffffff,
+	0x00009150, 0x96944200, 0xffffffff
+};
+
+#define CAYMAN_MGCG_ENABLE_LENGTH   sizeof(cayman_mgcg_enable) / (3 * sizeof(u32))
+
+#define NISLANDS_SYSLS_SEQUENCE  100
+
+static const u32 cayman_sysls_default[] =
+{
+	/* Register,   Value,     Mask bits */
+	0x000055e8, 0x00000000, 0xffffffff,
+	0x0000d0bc, 0x00000000, 0xffffffff,
+	0x0000d8bc, 0x00000000, 0xffffffff,
+	0x000015c0, 0x000c1401, 0xffffffff,
+	0x0000264c, 0x000c0400, 0xffffffff,
+	0x00002648, 0x000c0400, 0xffffffff,
+	0x00002650, 0x000c0400, 0xffffffff,
+	0x000020b8, 0x000c0400, 0xffffffff,
+	0x000020bc, 0x000c0400, 0xffffffff,
+	0x000020c0, 0x000c0c80, 0xffffffff,
+	0x0000f4a0, 0x000000c0, 0xffffffff,
+	0x0000f4a4, 0x00680fff, 0xffffffff,
+	0x00002f50, 0x00000404, 0xffffffff,
+	0x000004c8, 0x00000001, 0xffffffff,
+	0x000064ec, 0x00000000, 0xffffffff,
+	0x00000c7c, 0x00000000, 0xffffffff,
+	0x00008dfc, 0x00000000, 0xffffffff
+};
+#define CAYMAN_SYSLS_DEFAULT_LENGTH sizeof(cayman_sysls_default) / (3 * sizeof(u32))
+
+static const u32 cayman_sysls_disable[] =
+{
+	/* Register,   Value,     Mask bits */
+	0x0000d0c0, 0x00000000, 0xffffffff,
+	0x0000d8c0, 0x00000000, 0xffffffff,
+	0x000055e8, 0x00000000, 0xffffffff,
+	0x0000d0bc, 0x00000000, 0xffffffff,
+	0x0000d8bc, 0x00000000, 0xffffffff,
+	0x000015c0, 0x00041401, 0xffffffff,
+	0x0000264c, 0x00040400, 0xffffffff,
+	0x00002648, 0x00040400, 0xffffffff,
+	0x00002650, 0x00040400, 0xffffffff,
+	0x000020b8, 0x00040400, 0xffffffff,
+	0x000020bc, 0x00040400, 0xffffffff,
+	0x000020c0, 0x00040c80, 0xffffffff,
+	0x0000f4a0, 0x000000c0, 0xffffffff,
+	0x0000f4a4, 0x00680000, 0xffffffff,
+	0x00002f50, 0x00000404, 0xffffffff,
+	0x000004c8, 0x00000001, 0xffffffff,
+	0x000064ec, 0x00007ffd, 0xffffffff,
+	0x00000c7c, 0x0000ff00, 0xffffffff,
+	0x00008dfc, 0x0000007f, 0xffffffff
+};
+#define CAYMAN_SYSLS_DISABLE_LENGTH sizeof(cayman_sysls_disable) / (3 * sizeof(u32))
+
+static const u32 cayman_sysls_enable[] =
+{
+	/* Register,   Value,     Mask bits */
+	0x000055e8, 0x00000001, 0xffffffff,
+	0x0000d0bc, 0x00000100, 0xffffffff,
+	0x0000d8bc, 0x00000100, 0xffffffff,
+	0x000015c0, 0x000c1401, 0xffffffff,
+	0x0000264c, 0x000c0400, 0xffffffff,
+	0x00002648, 0x000c0400, 0xffffffff,
+	0x00002650, 0x000c0400, 0xffffffff,
+	0x000020b8, 0x000c0400, 0xffffffff,
+	0x000020bc, 0x000c0400, 0xffffffff,
+	0x000020c0, 0x000c0c80, 0xffffffff,
+	0x0000f4a0, 0x000000c0, 0xffffffff,
+	0x0000f4a4, 0x00680fff, 0xffffffff,
+	0x00002f50, 0x00000903, 0xffffffff,
+	0x000004c8, 0x00000000, 0xffffffff,
+	0x000064ec, 0x00000000, 0xffffffff,
+	0x00000c7c, 0x00000000, 0xffffffff,
+	0x00008dfc, 0x00000000, 0xffffffff
+};
+#define CAYMAN_SYSLS_ENABLE_LENGTH sizeof(cayman_sysls_enable) / (3 * sizeof(u32))
+
+struct rv7xx_power_info *rv770_get_pi(struct radeon_device *rdev);
+struct evergreen_power_info *evergreen_get_pi(struct radeon_device *rdev);
+
+static struct ni_power_info *ni_get_pi(struct radeon_device *rdev)
+{
+        struct ni_power_info *pi = rdev->pm.dpm.priv;
+
+        return pi;
+}
+
+struct ni_ps *ni_get_ps(struct radeon_ps *rps)
+{
+	struct ni_ps *ps = rps->ps_priv;
+
+	return ps;
+}
+
+/* XXX: fix for kernel use  */
+#if 0
+static double ni_exp(double x)
+{
+	int count = 1;
+	double sum = 1.0, term, tolerance = 0.000000001, y = x;
+
+	if (x < 0)
+		y = -1 * x;
+	term  = y;
+
+	while (term >= tolerance) {
+		sum = sum + term;
+		count = count + 1;
+		term  = term * (y / count);
+	}
+
+	if (x < 0)
+		sum = 1.0 / sum;
+
+	return sum;
+}
+#endif
+
+static void ni_calculate_leakage_for_v_and_t_formula(const struct ni_leakage_coeffients *coeff,
+						     u16 v, s32 t,
+						     u32 ileakage,
+						     u32 *leakage)
+{
+/* XXX: fix for kernel use  */
+#if 0
+	double kt, kv, leakage_w, i_leakage, vddc, temperature;
+
+	i_leakage   = ((double)ileakage) / 1000;
+	vddc        = ((double)v) / 1000;
+	temperature = ((double)t) / 1000;
+
+	kt = (((double)(coeff->at)) / 1000) * ni_exp((((double)(coeff->bt)) / 1000) * temperature);
+	kv = (((double)(coeff->av)) / 1000) * ni_exp((((double)(coeff->bv)) / 1000) * vddc);
+
+	leakage_w = i_leakage * kt * kv * vddc;
+
+	*leakage = (u32)(leakage_w * 1000);
+#endif
+}
+
+static void ni_calculate_leakage_for_v_and_t(struct radeon_device *rdev,
+					     const struct ni_leakage_coeffients *coeff,
+					     u16 v,
+					     s32 t,
+					     u32 i_leakage,
+					     u32 *leakage)
+{
+	ni_calculate_leakage_for_v_and_t_formula(coeff, v, t, i_leakage, leakage);
+}
+
+static void ni_apply_state_adjust_rules(struct radeon_device *rdev)
+{
+	struct ni_power_info *ni_pi = ni_get_pi(rdev);
+	struct radeon_ps *rps = rdev->pm.dpm.requested_ps;
+	struct ni_ps *ps = ni_get_ps(rps);
+	struct radeon_clock_and_voltage_limits *max_limits;
+	bool disable_mclk_switching;
+	u32 mclk, sclk;
+	u16 vddc, vddci;
+	int i;
+
+	/* point to the hw copy since this function will modify the ps */
+	ni_pi->hw_ps = *ps;
+	rdev->pm.dpm.hw_ps.ps_priv = &ni_pi->hw_ps;
+	ps = &ni_pi->hw_ps;
+
+	if (rdev->pm.dpm.new_active_crtc_count > 1)
+		disable_mclk_switching = true;
+	else
+		disable_mclk_switching = false;
+
+	if (rdev->pm.dpm.ac_power)
+		max_limits = &rdev->pm.dpm.dyn_state.max_clock_voltage_on_ac;
+	else
+		max_limits = &rdev->pm.dpm.dyn_state.max_clock_voltage_on_dc;
+
+	if (rdev->pm.dpm.ac_power == false) {
+		for (i = 0; i < ps->performance_level_count; i++) {
+			if (ps->performance_levels[i].mclk > max_limits->mclk)
+				ps->performance_levels[i].mclk = max_limits->mclk;
+			if (ps->performance_levels[i].sclk > max_limits->sclk)
+				ps->performance_levels[i].sclk = max_limits->sclk;
+			if (ps->performance_levels[i].vddc > max_limits->vddc)
+				ps->performance_levels[i].vddc = max_limits->vddc;
+			if (ps->performance_levels[i].vddci > max_limits->vddci)
+				ps->performance_levels[i].vddci = max_limits->vddci;
+		}
+	}
+
+	/* XXX validate the min clocks required for display */
+
+	if (disable_mclk_switching) {
+		mclk  = ps->performance_levels[ps->performance_level_count - 1].mclk;
+		sclk = ps->performance_levels[0].sclk;
+		vddc = ps->performance_levels[0].vddc;
+		vddci = ps->performance_levels[ps->performance_level_count - 1].vddci;
+	} else {
+		sclk = ps->performance_levels[0].sclk;
+		mclk = ps->performance_levels[0].mclk;
+		vddc = ps->performance_levels[0].vddc;
+		vddci = ps->performance_levels[0].vddci;
+	}
+
+	/* adjusted low state */
+	ps->performance_levels[0].sclk = sclk;
+	ps->performance_levels[0].mclk = mclk;
+	ps->performance_levels[0].vddc = vddc;
+	ps->performance_levels[0].vddci = vddci;
+
+	btc_skip_blacklist_clocks(rdev, max_limits->sclk, max_limits->mclk,
+				  &ps->performance_levels[0].sclk,
+				  &ps->performance_levels[0].mclk);
+
+	for (i = 1; i < ps->performance_level_count; i++) {
+		if (ps->performance_levels[i].sclk < ps->performance_levels[i - 1].sclk)
+			ps->performance_levels[i].sclk = ps->performance_levels[i - 1].sclk;
+		if (ps->performance_levels[i].vddc < ps->performance_levels[i - 1].vddc)
+			ps->performance_levels[i].vddc = ps->performance_levels[i - 1].vddc;
+	}
+
+	if (disable_mclk_switching) {
+		mclk = ps->performance_levels[0].mclk;
+		for (i = 1; i < ps->performance_level_count; i++) {
+			if (mclk < ps->performance_levels[i].mclk)
+				mclk = ps->performance_levels[i].mclk;
+		}
+		for (i = 0; i < ps->performance_level_count; i++) {
+			ps->performance_levels[i].mclk = mclk;
+			ps->performance_levels[i].vddci = vddci;
+		}
+	} else {
+		for (i = 1; i < ps->performance_level_count; i++) {
+			if (ps->performance_levels[i].mclk < ps->performance_levels[i - 1].mclk)
+				ps->performance_levels[i].mclk = ps->performance_levels[i - 1].mclk;
+			if (ps->performance_levels[i].vddci < ps->performance_levels[i - 1].vddci)
+				ps->performance_levels[i].vddci = ps->performance_levels[i - 1].vddci;
+		}
+	}
+
+	for (i = 1; i < ps->performance_level_count; i++)
+		btc_skip_blacklist_clocks(rdev, max_limits->sclk, max_limits->mclk,
+					  &ps->performance_levels[i].sclk,
+					  &ps->performance_levels[i].mclk);
+
+	for (i = 0; i < ps->performance_level_count; i++)
+		btc_adjust_clock_combinations(rdev, max_limits,
+					      &ps->performance_levels[i]);
+
+	for (i = 0; i < ps->performance_level_count; i++) {
+		btc_apply_voltage_dependency_rules(&rdev->pm.dpm.dyn_state.vddc_dependency_on_sclk,
+						   ps->performance_levels[i].sclk,
+						   max_limits->vddc,  &ps->performance_levels[i].vddc);
+		btc_apply_voltage_dependency_rules(&rdev->pm.dpm.dyn_state.vddci_dependency_on_mclk,
+						   ps->performance_levels[i].mclk,
+						   max_limits->vddci, &ps->performance_levels[i].vddci);
+		btc_apply_voltage_dependency_rules(&rdev->pm.dpm.dyn_state.vddc_dependency_on_mclk,
+						   ps->performance_levels[i].mclk,
+						   max_limits->vddc,  &ps->performance_levels[i].vddc);
+		/* XXX validate the voltage required for display */
+	}
+
+	for (i = 0; i < ps->performance_level_count; i++) {
+		btc_apply_voltage_delta_rules(rdev,
+					      max_limits->vddc, max_limits->vddci,
+					      &ps->performance_levels[i].vddc,
+					      &ps->performance_levels[i].vddci);
+	}
+
+	ps->dc_compatible = true;
+	for (i = 0; i < ps->performance_level_count; i++) {
+		if (ps->performance_levels[i].vddc > rdev->pm.dpm.dyn_state.max_clock_voltage_on_dc.vddc)
+			ps->dc_compatible = false;
+
+		if (ps->performance_levels[i].vddc < rdev->pm.dpm.dyn_state.min_vddc_for_pcie_gen2)
+			ps->performance_levels[i].flags &= ~ATOM_PPLIB_R600_FLAGS_PCIEGEN2;
+	}
+}
+
+static void ni_cg_clockgating_default(struct radeon_device *rdev)
+{
+	u32 count;
+	const u32 *ps = NULL;
+
+	ps = (const u32 *)&cayman_cgcg_cgls_default;
+	count = CAYMAN_CGCG_CGLS_DEFAULT_LENGTH;
+
+	btc_program_mgcg_hw_sequence(rdev, ps, count);
+}
+
+static void ni_gfx_clockgating_enable(struct radeon_device *rdev,
+				      bool enable)
+{
+	u32 count;
+	const u32 *ps = NULL;
+
+	if (enable) {
+		ps = (const u32 *)&cayman_cgcg_cgls_enable;
+		count = CAYMAN_CGCG_CGLS_ENABLE_LENGTH;
+	} else {
+		ps = (const u32 *)&cayman_cgcg_cgls_disable;
+		count = CAYMAN_CGCG_CGLS_DISABLE_LENGTH;
+	}
+
+	btc_program_mgcg_hw_sequence(rdev, ps, count);
+}
+
+static void ni_mg_clockgating_default(struct radeon_device *rdev)
+{
+	u32 count;
+	const u32 *ps = NULL;
+
+	ps = (const u32 *)&cayman_mgcg_default;
+	count = CAYMAN_MGCG_DEFAULT_LENGTH;
+
+	btc_program_mgcg_hw_sequence(rdev, ps, count);
+}
+
+static void ni_mg_clockgating_enable(struct radeon_device *rdev,
+				     bool enable)
+{
+	u32 count;
+	const u32 *ps = NULL;
+
+	if (enable) {
+		ps = (const u32 *)&cayman_mgcg_enable;
+		count = CAYMAN_MGCG_ENABLE_LENGTH;
+	} else {
+		ps = (const u32 *)&cayman_mgcg_disable;
+		count = CAYMAN_MGCG_DISABLE_LENGTH;
+	}
+
+	btc_program_mgcg_hw_sequence(rdev, ps, count);
+}
+
+static void ni_ls_clockgating_default(struct radeon_device *rdev)
+{
+	u32 count;
+	const u32 *ps = NULL;
+
+	ps = (const u32 *)&cayman_sysls_default;
+	count = CAYMAN_SYSLS_DEFAULT_LENGTH;
+
+	btc_program_mgcg_hw_sequence(rdev, ps, count);
+}
+
+static void ni_ls_clockgating_enable(struct radeon_device *rdev,
+				     bool enable)
+{
+	u32 count;
+	const u32 *ps = NULL;
+
+	if (enable) {
+		ps = (const u32 *)&cayman_sysls_enable;
+		count = CAYMAN_SYSLS_ENABLE_LENGTH;
+	} else {
+		ps = (const u32 *)&cayman_sysls_disable;
+		count = CAYMAN_SYSLS_DISABLE_LENGTH;
+	}
+
+	btc_program_mgcg_hw_sequence(rdev, ps, count);
+
+}
+
+static int ni_patch_single_dependency_table_based_on_leakage(struct radeon_device *rdev,
+							     struct radeon_clock_voltage_dependency_table *table)
+{
+	struct rv7xx_power_info *pi = rv770_get_pi(rdev);
+	u32 i;
+
+	if (table) {
+		for (i = 0; i < table->count; i++) {
+			if (0xff01 == table->entries[i].v) {
+				if (pi->max_vddc == 0)
+					return -EINVAL;
+				table->entries[i].v = pi->max_vddc;
+			}
+		}
+	}
+	return 0;
+}
+
+static int ni_patch_dependency_tables_based_on_leakage(struct radeon_device *rdev)
+{
+	int ret = 0;
+
+	ret = ni_patch_single_dependency_table_based_on_leakage(rdev,
+								&rdev->pm.dpm.dyn_state.vddc_dependency_on_sclk);
+
+	ret = ni_patch_single_dependency_table_based_on_leakage(rdev,
+								&rdev->pm.dpm.dyn_state.vddc_dependency_on_mclk);
+	return ret;
+}
+
+static void ni_stop_dpm(struct radeon_device *rdev)
+{
+	WREG32_P(GENERAL_PWRMGT, 0, ~GLOBAL_PWRMGT_EN);
+}
+
+#if 0
+static int ni_notify_hw_of_power_source(struct radeon_device *rdev,
+					bool ac_power)
+{
+	if (ac_power)
+		return (rv770_send_msg_to_smc(rdev, PPSMC_MSG_RunningOnAC) == PPSMC_Result_OK) ?
+			0 : -EINVAL;
+
+	return 0;
+}
+#endif
+
+static PPSMC_Result ni_send_msg_to_smc_with_parameter(struct radeon_device *rdev,
+						      PPSMC_Msg msg, u32 parameter)
+{
+	WREG32(SMC_SCRATCH0, parameter);
+	return rv770_send_msg_to_smc(rdev, msg);
+}
+
+static int ni_restrict_performance_levels_before_switch(struct radeon_device *rdev)
+{
+	if (rv770_send_msg_to_smc(rdev, PPSMC_MSG_NoForcedLevel) != PPSMC_Result_OK)
+		return -EINVAL;
+
+	return (ni_send_msg_to_smc_with_parameter(rdev, PPSMC_MSG_SetEnabledLevels, 1) == PPSMC_Result_OK) ?
+		0 : -EINVAL;
+}
+
+static void ni_stop_smc(struct radeon_device *rdev)
+{
+	u32 tmp;
+	int i;
+
+	for (i = 0; i < rdev->usec_timeout; i++) {
+		tmp = RREG32(LB_SYNC_RESET_SEL) & LB_SYNC_RESET_SEL_MASK;
+		if (tmp != 1)
+			break;
+		udelay(1);
+	}
+
+	udelay(100);
+
+	r7xx_stop_smc(rdev);
+}
+
+static int ni_process_firmware_header(struct radeon_device *rdev)
+{
+        struct rv7xx_power_info *pi = rv770_get_pi(rdev);
+        struct evergreen_power_info *eg_pi = evergreen_get_pi(rdev);
+        struct ni_power_info *ni_pi = ni_get_pi(rdev);
+	u32 tmp;
+	int ret;
+
+	ret = rv770_read_smc_sram_dword(rdev,
+					NISLANDS_SMC_FIRMWARE_HEADER_LOCATION +
+					NISLANDS_SMC_FIRMWARE_HEADER_stateTable,
+					&tmp, pi->sram_end);
+
+	if (ret)
+		return ret;
+
+	pi->state_table_start = (u16)tmp;
+
+	ret = rv770_read_smc_sram_dword(rdev,
+					NISLANDS_SMC_FIRMWARE_HEADER_LOCATION +
+					NISLANDS_SMC_FIRMWARE_HEADER_softRegisters,
+					&tmp, pi->sram_end);
+
+	if (ret)
+		return ret;
+
+	pi->soft_regs_start = (u16)tmp;
+
+	ret = rv770_read_smc_sram_dword(rdev,
+					NISLANDS_SMC_FIRMWARE_HEADER_LOCATION +
+					NISLANDS_SMC_FIRMWARE_HEADER_mcRegisterTable,
+					&tmp, pi->sram_end);
+
+	if (ret)
+		return ret;
+
+	eg_pi->mc_reg_table_start = (u16)tmp;
+
+	ret = rv770_read_smc_sram_dword(rdev,
+					NISLANDS_SMC_FIRMWARE_HEADER_LOCATION +
+					NISLANDS_SMC_FIRMWARE_HEADER_fanTable,
+					&tmp, pi->sram_end);
+
+	if (ret)
+		return ret;
+
+	ni_pi->fan_table_start = (u16)tmp;
+
+	ret = rv770_read_smc_sram_dword(rdev,
+					NISLANDS_SMC_FIRMWARE_HEADER_LOCATION +
+					NISLANDS_SMC_FIRMWARE_HEADER_mcArbDramAutoRefreshTable,
+					&tmp, pi->sram_end);
+
+	if (ret)
+		return ret;
+
+	ni_pi->arb_table_start = (u16)tmp;
+
+	ret = rv770_read_smc_sram_dword(rdev,
+					NISLANDS_SMC_FIRMWARE_HEADER_LOCATION +
+					NISLANDS_SMC_FIRMWARE_HEADER_cacTable,
+					&tmp, pi->sram_end);
+
+	if (ret)
+		return ret;
+
+	ni_pi->cac_table_start = (u16)tmp;
+
+	ret = rv770_read_smc_sram_dword(rdev,
+					NISLANDS_SMC_FIRMWARE_HEADER_LOCATION +
+					NISLANDS_SMC_FIRMWARE_HEADER_spllTable,
+					&tmp, pi->sram_end);
+
+	if (ret)
+		return ret;
+
+	ni_pi->spll_table_start = (u16)tmp;
+
+
+	return ret;
+}
+
+static void ni_read_clock_registers(struct radeon_device *rdev)
+{
+	struct ni_power_info *ni_pi = ni_get_pi(rdev);
+
+	ni_pi->clock_registers.cg_spll_func_cntl = RREG32(CG_SPLL_FUNC_CNTL);
+	ni_pi->clock_registers.cg_spll_func_cntl_2 = RREG32(CG_SPLL_FUNC_CNTL_2);
+	ni_pi->clock_registers.cg_spll_func_cntl_3 = RREG32(CG_SPLL_FUNC_CNTL_3);
+	ni_pi->clock_registers.cg_spll_func_cntl_4 = RREG32(CG_SPLL_FUNC_CNTL_4);
+	ni_pi->clock_registers.cg_spll_spread_spectrum = RREG32(CG_SPLL_SPREAD_SPECTRUM);
+	ni_pi->clock_registers.cg_spll_spread_spectrum_2 = RREG32(CG_SPLL_SPREAD_SPECTRUM_2);
+	ni_pi->clock_registers.mpll_ad_func_cntl = RREG32(MPLL_AD_FUNC_CNTL);
+	ni_pi->clock_registers.mpll_ad_func_cntl_2 = RREG32(MPLL_AD_FUNC_CNTL_2);
+	ni_pi->clock_registers.mpll_dq_func_cntl = RREG32(MPLL_DQ_FUNC_CNTL);
+	ni_pi->clock_registers.mpll_dq_func_cntl_2 = RREG32(MPLL_DQ_FUNC_CNTL_2);
+	ni_pi->clock_registers.mclk_pwrmgt_cntl = RREG32(MCLK_PWRMGT_CNTL);
+	ni_pi->clock_registers.dll_cntl = RREG32(DLL_CNTL);
+	ni_pi->clock_registers.mpll_ss1 = RREG32(MPLL_SS1);
+	ni_pi->clock_registers.mpll_ss2 = RREG32(MPLL_SS2);
+}
+
+#if 0
+static int ni_enter_ulp_state(struct radeon_device *rdev)
+{
+	struct rv7xx_power_info *pi = rv770_get_pi(rdev);
+
+	if (pi->gfx_clock_gating) {
+                WREG32_P(SCLK_PWRMGT_CNTL, 0, ~DYN_GFX_CLK_OFF_EN);
+		WREG32_P(SCLK_PWRMGT_CNTL, GFX_CLK_FORCE_ON, ~GFX_CLK_FORCE_ON);
+                WREG32_P(SCLK_PWRMGT_CNTL, 0, ~GFX_CLK_FORCE_ON);
+		RREG32(GB_ADDR_CONFIG);
+        }
+
+	WREG32_P(SMC_MSG, HOST_SMC_MSG(PPSMC_MSG_SwitchToMinimumPower),
+                 ~HOST_SMC_MSG_MASK);
+
+	udelay(25000);
+
+	return 0;
+}
+#endif
+
+static void ni_program_response_times(struct radeon_device *rdev)
+{
+	u32 voltage_response_time, backbias_response_time, acpi_delay_time, vbi_time_out;
+	u32 vddc_dly, bb_dly, acpi_dly, vbi_dly, mclk_switch_limit;
+	u32 reference_clock;
+
+	rv770_write_smc_soft_register(rdev, NI_SMC_SOFT_REGISTER_mvdd_chg_time, 1);

drivers/gpu/drm/radeon/ni_dpm.c line 1223

Quoted 10 lines
drivers/gpu/drm/radeon/ni_dpm.c new file +10 -0
+
+        voltage_response_time = (u32)rdev->pm.dpm.voltage_response_time;
+        backbias_response_time = (u32)rdev->pm.dpm.backbias_response_time;
+
+        if (voltage_response_time == 0)
+                voltage_response_time = 1000;
+
+        if (backbias_response_time == 0)
+                backbias_response_time = 1000;
+

^
Broken indentation.

Quoted 27 lines
drivers/gpu/drm/radeon/ni_dpm.c new file +27 -0
+	acpi_delay_time = 15000;
+	vbi_time_out = 100000;
+
+	reference_clock = radeon_get_xclk(rdev);
+
+	vddc_dly = (voltage_response_time  * reference_clock) / 1600;
+	bb_dly   = (backbias_response_time * reference_clock) / 1600;
+	acpi_dly = (acpi_delay_time * reference_clock) / 1600;
+	vbi_dly  = (vbi_time_out * reference_clock) / 1600;
+
+	mclk_switch_limit = (460 * reference_clock) / 100;
+
+	rv770_write_smc_soft_register(rdev, NI_SMC_SOFT_REGISTER_delay_vreg,  vddc_dly);
+	rv770_write_smc_soft_register(rdev, NI_SMC_SOFT_REGISTER_delay_bbias, bb_dly);
+	rv770_write_smc_soft_register(rdev, NI_SMC_SOFT_REGISTER_delay_acpi,  acpi_dly);
+	rv770_write_smc_soft_register(rdev, NI_SMC_SOFT_REGISTER_mclk_chg_timeout, vbi_dly);
+	rv770_write_smc_soft_register(rdev, NI_SMC_SOFT_REGISTER_mc_block_delay, 0xAA);
+	rv770_write_smc_soft_register(rdev, NI_SMC_SOFT_REGISTER_mclk_switch_lim, mclk_switch_limit);
+}
+
+static void ni_populate_smc_voltage_table(struct radeon_device *rdev,
+					  struct atom_voltage_table *voltage_table,
+					  NISLANDS_SMC_STATETABLE *table)
+{
+	unsigned int i;
+
+	for (i = 0; i < voltage_table->count; i++) {

drivers/gpu/drm/radeon/ni_dpm.c line 1260

Quoted 10 lines
drivers/gpu/drm/radeon/ni_dpm.c new file +10 -0
+		table->highSMIO[i] = 0;
+		table->lowSMIO[i] |= cpu_to_be32(voltage_table->entries[i].smio_low);
+	}
+}
+
+static void ni_populate_smc_voltage_tables(struct radeon_device *rdev,
+					   NISLANDS_SMC_STATETABLE *table)
+{
+	struct rv7xx_power_info *pi = rv770_get_pi(rdev);
+        struct evergreen_power_info *eg_pi = evergreen_get_pi(rdev);

^
Broken indentation.

Quoted 42 lines
drivers/gpu/drm/radeon/ni_dpm.c new file +42 -0
+	unsigned char i;
+
+	if (eg_pi->vddc_voltage_table.count) {
+		ni_populate_smc_voltage_table(rdev, &eg_pi->vddc_voltage_table, table);
+		table->voltageMaskTable.highMask[NISLANDS_SMC_VOLTAGEMASK_VDDC] = 0;
+		table->voltageMaskTable.lowMask[NISLANDS_SMC_VOLTAGEMASK_VDDC] =
+			cpu_to_be32(eg_pi->vddc_voltage_table.mask_low);
+
+		for (i = 0; i < eg_pi->vddc_voltage_table.count; i++) {
+			if (pi->max_vddc_in_table <= eg_pi->vddc_voltage_table.entries[i].value) {
+				table->maxVDDCIndexInPPTable = i;
+				break;
+			}
+		}
+	}
+
+	if (eg_pi->vddci_voltage_table.count) {
+		ni_populate_smc_voltage_table(rdev, &eg_pi->vddci_voltage_table, table);
+
+		table->voltageMaskTable.highMask[NISLANDS_SMC_VOLTAGEMASK_VDDCI] = 0;
+		table->voltageMaskTable.lowMask[NISLANDS_SMC_VOLTAGEMASK_VDDCI] =
+			cpu_to_be32(eg_pi->vddc_voltage_table.mask_low);
+	}
+}
+
+static int ni_populate_voltage_value(struct radeon_device *rdev,
+				     struct atom_voltage_table *table,
+				     u16 value,
+				     NISLANDS_SMC_VOLTAGE_VALUE *voltage)
+{
+	unsigned int i;
+
+	for (i = 0; i < table->count; i++) {
+		if (value <= table->entries[i].value) {
+			voltage->index = (u8)i;
+			voltage->value = cpu_to_be16(table->entries[i].value);
+			break;
+		}
+	}
+
+	if (i >= table->count)
+		return -EINVAL;

drivers/gpu/drm/radeon/ni_dpm.c line 1312

Quoted 10 lines
drivers/gpu/drm/radeon/ni_dpm.c new file +10 -0
+
+	return 0;
+}
+
+static void ni_populate_mvdd_value(struct radeon_device *rdev,
+				   u32 mclk,
+				   NISLANDS_SMC_VOLTAGE_VALUE *voltage)
+{
+        struct rv7xx_power_info *pi = rv770_get_pi(rdev);
+        struct evergreen_power_info *eg_pi = evergreen_get_pi(rdev);

^
Broken indentation.

drivers/gpu/drm/radeon/ni_dpm.c line 1322

Quoted 10 lines
drivers/gpu/drm/radeon/ni_dpm.c new file +10 -0
+
+	if (!pi->mvdd_control) {
+		voltage->index = eg_pi->mvdd_high_index;
+                voltage->value = cpu_to_be16(MVDD_HIGH_VALUE);
+		return;
+        }
+
+        if (mclk <= pi->mvdd_split_frequency) {
+                voltage->index = eg_pi->mvdd_low_index;
+                voltage->value = cpu_to_be16(MVDD_LOW_VALUE);

^
Broken indentation.

drivers/gpu/drm/radeon/ni_dpm.c line 1326

Quoted 4 lines
drivers/gpu/drm/radeon/ni_dpm.c new file +4 -0
+	} else {
+		voltage->index = eg_pi->mvdd_high_index;
+		voltage->value = cpu_to_be16(MVDD_HIGH_VALUE);
+        }

^
Broken indentation.

Quoted 202 lines
drivers/gpu/drm/radeon/ni_dpm.c new file +202 -0
+}
+
+static int ni_get_std_voltage_value(struct radeon_device *rdev,
+				    NISLANDS_SMC_VOLTAGE_VALUE *voltage,
+				    u16 *std_voltage)
+{
+	if (rdev->pm.dpm.dyn_state.cac_leakage_table.entries &&
+	    ((u32)voltage->index < rdev->pm.dpm.dyn_state.cac_leakage_table.count))
+		*std_voltage = rdev->pm.dpm.dyn_state.cac_leakage_table.entries[voltage->index].vddc;
+	else
+		*std_voltage = be16_to_cpu(voltage->value);
+
+	return 0;
+}
+
+static void ni_populate_std_voltage_value(struct radeon_device *rdev,
+					  u16 value, u8 index,
+					  NISLANDS_SMC_VOLTAGE_VALUE *voltage)
+{
+	voltage->index = index;
+	voltage->value = cpu_to_be16(value);
+}
+
+static u32 ni_get_smc_power_scaling_factor(struct radeon_device *rdev)
+{
+	u32 xclk_period;
+	u32 xclk = radeon_get_xclk(rdev);
+	u32 tmp = RREG32(CG_CAC_CTRL) & TID_CNT_MASK;
+
+	xclk_period = (1000000000UL / xclk);
+	xclk_period /= 10000UL;
+
+	return tmp * xclk_period;
+}
+
+static u32 ni_scale_power_for_smc(u32 power_in_watts, u32 scaling_factor)
+{
+	return (power_in_watts * scaling_factor) << 2;
+}
+
+static u32 ni_calculate_power_boost_limit(struct radeon_device *rdev,
+					  struct radeon_ps *radeon_state,
+					  u32 near_tdp_limit)
+{
+	struct ni_ps *state = ni_get_ps(radeon_state);
+	struct evergreen_power_info *eg_pi = evergreen_get_pi(rdev);
+	struct ni_power_info *ni_pi = ni_get_pi(rdev);
+	u32 power_boost_limit = 0;
+	int ret;
+
+	if (ni_pi->enable_power_containment &&
+	    ni_pi->use_power_boost_limit) {
+		NISLANDS_SMC_VOLTAGE_VALUE vddc;
+		u16 std_vddc_med;
+		u16 std_vddc_high;
+		u64 tmp;
+
+		if (state->performance_level_count < 3)
+			return 0;
+
+		ret = ni_populate_voltage_value(rdev, &eg_pi->vddc_voltage_table,
+						state->performance_levels[state->performance_level_count - 2].vddc,
+						&vddc);
+		if (ret)
+			return 0;
+
+		ret = ni_get_std_voltage_value(rdev, &vddc, &std_vddc_med);
+		if (ret)
+			return 0;
+
+		ret = ni_populate_voltage_value(rdev, &eg_pi->vddc_voltage_table,
+						state->performance_levels[state->performance_level_count - 1].vddc,
+						&vddc);
+		if (ret)
+			return 0;
+
+		ret = ni_get_std_voltage_value(rdev, &vddc, &std_vddc_high);
+		if (ret)
+			return 0;
+
+		tmp = ((u64)near_tdp_limit * ((u64)std_vddc_med * (u64)std_vddc_med) * 90) /
+			((u64)std_vddc_high * (u64)std_vddc_high * 100);
+		if (tmp >> 32)
+			return 0;
+		power_boost_limit = (u32)tmp;
+	}
+
+	return power_boost_limit;
+}
+
+static int ni_calculate_adjusted_tdp_limits(struct radeon_device *rdev,
+					    bool adjust_polarity,
+					    u32 tdp_adjustment,
+					    u32 *tdp_limit,
+					    u32 *near_tdp_limit)
+{
+	if (tdp_adjustment > (u32)rdev->pm.dpm.tdp_od_limit)
+		return -EINVAL;
+
+	if (adjust_polarity) {
+		*tdp_limit = ((100 + tdp_adjustment) * rdev->pm.dpm.tdp_limit) / 100;
+		*near_tdp_limit = rdev->pm.dpm.near_tdp_limit + (*tdp_limit - rdev->pm.dpm.tdp_limit);
+	} else {
+		*tdp_limit = ((100 - tdp_adjustment) * rdev->pm.dpm.tdp_limit) / 100;
+		*near_tdp_limit = rdev->pm.dpm.near_tdp_limit - (rdev->pm.dpm.tdp_limit - *tdp_limit);
+	}
+
+	return 0;
+}
+
+static int ni_populate_smc_tdp_limits(struct radeon_device *rdev)
+{
+	struct rv7xx_power_info *pi = rv770_get_pi(rdev);
+	struct ni_power_info *ni_pi = ni_get_pi(rdev);
+
+	if (ni_pi->enable_power_containment) {
+		struct radeon_ps *radeon_state = rdev->pm.dpm.requested_ps;
+		NISLANDS_SMC_STATETABLE *smc_table = &ni_pi->smc_statetable;
+		u32 scaling_factor = ni_get_smc_power_scaling_factor(rdev);
+		u32 tdp_limit;
+		u32 near_tdp_limit;
+		u32 power_boost_limit;
+		int ret;
+
+		if (scaling_factor == 0)
+			return -EINVAL;
+
+		memset(smc_table, 0, sizeof(NISLANDS_SMC_STATETABLE));
+
+		ret = ni_calculate_adjusted_tdp_limits(rdev,
+						       false, /* ??? */
+						       rdev->pm.dpm.tdp_adjustment,
+						       &tdp_limit,
+						       &near_tdp_limit);
+		if (ret)
+			return ret;
+
+		power_boost_limit = ni_calculate_power_boost_limit(rdev, radeon_state,
+								   near_tdp_limit);
+
+		smc_table->dpm2Params.TDPLimit =
+			cpu_to_be32(ni_scale_power_for_smc(tdp_limit, scaling_factor));
+		smc_table->dpm2Params.NearTDPLimit =
+			cpu_to_be32(ni_scale_power_for_smc(near_tdp_limit, scaling_factor));
+		smc_table->dpm2Params.SafePowerLimit =
+			cpu_to_be32(ni_scale_power_for_smc((near_tdp_limit * NISLANDS_DPM2_TDP_SAFE_LIMIT_PERCENT) / 100,
+							   scaling_factor));
+		smc_table->dpm2Params.PowerBoostLimit =
+			cpu_to_be32(ni_scale_power_for_smc(power_boost_limit, scaling_factor));
+
+		ret = rv770_copy_bytes_to_smc(rdev,
+					      (u16)(pi->state_table_start + offsetof(NISLANDS_SMC_STATETABLE, dpm2Params) +
+						    offsetof(PP_NIslands_DPM2Parameters, TDPLimit)),
+					      (u8 *)(&smc_table->dpm2Params.TDPLimit),
+					      sizeof(u32) * 4, pi->sram_end);
+		if (ret)
+			return ret;
+	}
+
+	return 0;
+}
+
+static int ni_copy_and_switch_arb_sets(struct radeon_device *rdev,
+				       u32 arb_freq_src, u32 arb_freq_dest)
+{
+	u32 mc_arb_dram_timing;
+	u32 mc_arb_dram_timing2;
+	u32 burst_time;
+	u32 mc_cg_config;
+
+	switch (arb_freq_src) {
+        case MC_CG_ARB_FREQ_F0:
+		mc_arb_dram_timing  = RREG32(MC_ARB_DRAM_TIMING);
+		mc_arb_dram_timing2 = RREG32(MC_ARB_DRAM_TIMING2);
+		burst_time = (RREG32(MC_ARB_BURST_TIME) & STATE0_MASK) >> STATE0_SHIFT;
+		break;
+        case MC_CG_ARB_FREQ_F1:
+		mc_arb_dram_timing  = RREG32(MC_ARB_DRAM_TIMING_1);
+		mc_arb_dram_timing2 = RREG32(MC_ARB_DRAM_TIMING2_1);
+		burst_time = (RREG32(MC_ARB_BURST_TIME) & STATE1_MASK) >> STATE1_SHIFT;
+		break;
+        case MC_CG_ARB_FREQ_F2:
+		mc_arb_dram_timing  = RREG32(MC_ARB_DRAM_TIMING_2);
+		mc_arb_dram_timing2 = RREG32(MC_ARB_DRAM_TIMING2_2);
+		burst_time = (RREG32(MC_ARB_BURST_TIME) & STATE2_MASK) >> STATE2_SHIFT;
+		break;
+        case MC_CG_ARB_FREQ_F3:
+		mc_arb_dram_timing  = RREG32(MC_ARB_DRAM_TIMING_3);
+		mc_arb_dram_timing2 = RREG32(MC_ARB_DRAM_TIMING2_3);
+		burst_time = (RREG32(MC_ARB_BURST_TIME) & STATE3_MASK) >> STATE3_SHIFT;
+		break;
+        default:
+		return -EINVAL;
+	}
+
+	switch (arb_freq_dest) {
+        case MC_CG_ARB_FREQ_F0:
+		WREG32(MC_ARB_DRAM_TIMING, mc_arb_dram_timing);
+		WREG32(MC_ARB_DRAM_TIMING2, mc_arb_dram_timing2);
+		WREG32_P(MC_ARB_BURST_TIME, STATE0(burst_time), ~STATE0_MASK);
+		break;
+        case MC_CG_ARB_FREQ_F1:

drivers/gpu/drm/radeon/ni_dpm.c line 1538

Quoted 10 lines
drivers/gpu/drm/radeon/ni_dpm.c new file +10 -0
+		WREG32(MC_ARB_DRAM_TIMING_1, mc_arb_dram_timing);
+		WREG32(MC_ARB_DRAM_TIMING2_1, mc_arb_dram_timing2);
+		WREG32_P(MC_ARB_BURST_TIME, STATE1(burst_time), ~STATE1_MASK);
+		break;
+        case MC_CG_ARB_FREQ_F2:
+		WREG32(MC_ARB_DRAM_TIMING_2, mc_arb_dram_timing);
+		WREG32(MC_ARB_DRAM_TIMING2_2, mc_arb_dram_timing2);
+		WREG32_P(MC_ARB_BURST_TIME, STATE2(burst_time), ~STATE2_MASK);
+		break;
+        case MC_CG_ARB_FREQ_F3:

^
Broken indentation.

drivers/gpu/drm/radeon/ni_dpm.c line 1543

Quoted 5 lines
drivers/gpu/drm/radeon/ni_dpm.c new file +5 -0
+		WREG32(MC_ARB_DRAM_TIMING_3, mc_arb_dram_timing);
+		WREG32(MC_ARB_DRAM_TIMING2_3, mc_arb_dram_timing2);
+		WREG32_P(MC_ARB_BURST_TIME, STATE3(burst_time), ~STATE3_MASK);
+		break;
+        default:

^
Broken indentation.

Quoted 315 lines
drivers/gpu/drm/radeon/ni_dpm.c new file +315 -0
+		return -EINVAL;
+	}
+
+	mc_cg_config = RREG32(MC_CG_CONFIG) | 0x0000000F;
+	WREG32(MC_CG_CONFIG, mc_cg_config);
+	WREG32_P(MC_ARB_CG, CG_ARB_REQ(arb_freq_dest), ~CG_ARB_REQ_MASK);
+
+	return 0;
+}
+
+static int ni_init_arb_table_index(struct radeon_device *rdev)
+{
+	struct rv7xx_power_info *pi = rv770_get_pi(rdev);
+	struct ni_power_info *ni_pi = ni_get_pi(rdev);
+	u32 tmp;
+	int ret;
+
+	ret = rv770_read_smc_sram_dword(rdev, ni_pi->arb_table_start,
+					&tmp, pi->sram_end);
+	if (ret)
+		return ret;
+
+	tmp &= 0x00FFFFFF;
+	tmp |= ((u32)MC_CG_ARB_FREQ_F1) << 24;
+
+	return rv770_write_smc_sram_dword(rdev, ni_pi->arb_table_start,
+					  tmp, pi->sram_end);
+}
+
+static int ni_initial_switch_from_arb_f0_to_f1(struct radeon_device *rdev)
+{
+	return ni_copy_and_switch_arb_sets(rdev, MC_CG_ARB_FREQ_F0, MC_CG_ARB_FREQ_F1);
+}
+
+static int ni_force_switch_to_arb_f0(struct radeon_device *rdev)
+{
+	struct rv7xx_power_info *pi = rv770_get_pi(rdev);
+	struct ni_power_info *ni_pi = ni_get_pi(rdev);
+	u32 tmp;
+	int ret;
+
+	ret = rv770_read_smc_sram_dword(rdev, ni_pi->arb_table_start,
+					&tmp, pi->sram_end);
+	if (ret)
+		return ret;
+
+	tmp = (tmp >> 24) & 0xff;
+
+	if (tmp == MC_CG_ARB_FREQ_F0)
+		return 0;
+
+	return ni_copy_and_switch_arb_sets(rdev, tmp, MC_CG_ARB_FREQ_F0);
+}
+
+static int ni_populate_memory_timing_parameters(struct radeon_device *rdev,
+						struct rv7xx_pl *pl,
+						SMC_NIslands_MCArbDramTimingRegisterSet *arb_regs)
+{
+	u32 dram_timing;
+	u32 dram_timing2;
+
+	arb_regs->mc_arb_rfsh_rate =
+		(u8)rv770_calculate_memory_refresh_rate(rdev, pl->sclk);
+
+
+	radeon_atom_set_engine_dram_timings(rdev,
+                                            pl->sclk,
+                                            pl->mclk);
+
+	dram_timing = RREG32(MC_ARB_DRAM_TIMING);
+	dram_timing2 = RREG32(MC_ARB_DRAM_TIMING2);
+
+	arb_regs->mc_arb_dram_timing  = cpu_to_be32(dram_timing);
+	arb_regs->mc_arb_dram_timing2 = cpu_to_be32(dram_timing2);
+
+	return 0;
+}
+
+static int ni_do_program_memory_timing_parameters(struct radeon_device *rdev,
+						  struct radeon_ps *radeon_state,
+						  unsigned int first_arb_set)
+{
+	struct rv7xx_power_info *pi = rv770_get_pi(rdev);
+	struct ni_power_info *ni_pi = ni_get_pi(rdev);
+	struct ni_ps *state = ni_get_ps(radeon_state);
+	SMC_NIslands_MCArbDramTimingRegisterSet arb_regs = { 0 };
+	int i, ret = 0;
+
+	for (i = 0; i < state->performance_level_count; i++) {
+		ret = ni_populate_memory_timing_parameters(rdev, &state->performance_levels[i], &arb_regs);
+		if (ret)
+			break;
+
+		ret = rv770_copy_bytes_to_smc(rdev,
+					      (u16)(ni_pi->arb_table_start +
+						    offsetof(SMC_NIslands_MCArbDramTimingRegisters, data) +
+						    sizeof(SMC_NIslands_MCArbDramTimingRegisterSet) * (first_arb_set + i)),
+					      (u8 *)&arb_regs,
+					      (u16)sizeof(SMC_NIslands_MCArbDramTimingRegisterSet),
+					      pi->sram_end);
+		if (ret)
+			break;
+	}
+	return ret;
+}
+
+static int ni_program_memory_timing_parameters(struct radeon_device *rdev)
+{
+	struct radeon_ps *radeon_new_state = rdev->pm.dpm.requested_ps;
+
+	return ni_do_program_memory_timing_parameters(rdev, radeon_new_state,
+						      NISLANDS_DRIVER_STATE_ARB_INDEX);
+}
+
+static void ni_populate_initial_mvdd_value(struct radeon_device *rdev,
+					   struct NISLANDS_SMC_VOLTAGE_VALUE *voltage)
+{
+	struct evergreen_power_info *eg_pi = evergreen_get_pi(rdev);
+
+	voltage->index = eg_pi->mvdd_high_index;
+	voltage->value = cpu_to_be16(MVDD_HIGH_VALUE);
+}
+
+static int ni_populate_smc_initial_state(struct radeon_device *rdev,
+					 struct radeon_ps *radeon_initial_state,
+					 NISLANDS_SMC_STATETABLE *table)
+{
+	struct ni_ps *initial_state = ni_get_ps(radeon_initial_state);
+	struct rv7xx_power_info *pi = rv770_get_pi(rdev);
+	struct evergreen_power_info *eg_pi = evergreen_get_pi(rdev);
+	struct ni_power_info *ni_pi = ni_get_pi(rdev);
+	u32 reg;
+	int ret;
+
+	table->initialState.levels[0].mclk.vMPLL_AD_FUNC_CNTL =
+		cpu_to_be32(ni_pi->clock_registers.mpll_ad_func_cntl);
+	table->initialState.levels[0].mclk.vMPLL_AD_FUNC_CNTL_2 =
+		cpu_to_be32(ni_pi->clock_registers.mpll_ad_func_cntl_2);
+	table->initialState.levels[0].mclk.vMPLL_DQ_FUNC_CNTL =
+		cpu_to_be32(ni_pi->clock_registers.mpll_dq_func_cntl);
+	table->initialState.levels[0].mclk.vMPLL_DQ_FUNC_CNTL_2 =
+		cpu_to_be32(ni_pi->clock_registers.mpll_dq_func_cntl_2);
+	table->initialState.levels[0].mclk.vMCLK_PWRMGT_CNTL =
+		cpu_to_be32(ni_pi->clock_registers.mclk_pwrmgt_cntl);
+	table->initialState.levels[0].mclk.vDLL_CNTL =
+		cpu_to_be32(ni_pi->clock_registers.dll_cntl);
+	table->initialState.levels[0].mclk.vMPLL_SS =
+		cpu_to_be32(ni_pi->clock_registers.mpll_ss1);
+	table->initialState.levels[0].mclk.vMPLL_SS2 =
+		cpu_to_be32(ni_pi->clock_registers.mpll_ss2);
+	table->initialState.levels[0].mclk.mclk_value =
+		cpu_to_be32(initial_state->performance_levels[0].mclk);
+
+	table->initialState.levels[0].sclk.vCG_SPLL_FUNC_CNTL =
+		cpu_to_be32(ni_pi->clock_registers.cg_spll_func_cntl);
+	table->initialState.levels[0].sclk.vCG_SPLL_FUNC_CNTL_2 =
+		cpu_to_be32(ni_pi->clock_registers.cg_spll_func_cntl_2);
+	table->initialState.levels[0].sclk.vCG_SPLL_FUNC_CNTL_3 =
+		cpu_to_be32(ni_pi->clock_registers.cg_spll_func_cntl_3);
+	table->initialState.levels[0].sclk.vCG_SPLL_FUNC_CNTL_4 =
+		cpu_to_be32(ni_pi->clock_registers.cg_spll_func_cntl_4);
+	table->initialState.levels[0].sclk.vCG_SPLL_SPREAD_SPECTRUM =
+		cpu_to_be32(ni_pi->clock_registers.cg_spll_spread_spectrum);
+	table->initialState.levels[0].sclk.vCG_SPLL_SPREAD_SPECTRUM_2 =
+		cpu_to_be32(ni_pi->clock_registers.cg_spll_spread_spectrum_2);
+	table->initialState.levels[0].sclk.sclk_value =
+		cpu_to_be32(initial_state->performance_levels[0].sclk);
+	table->initialState.levels[0].arbRefreshState =
+		NISLANDS_INITIAL_STATE_ARB_INDEX;
+
+	table->initialState.levels[0].ACIndex = 0;
+
+	ret = ni_populate_voltage_value(rdev, &eg_pi->vddc_voltage_table,
+					initial_state->performance_levels[0].vddc,
+					&table->initialState.levels[0].vddc);
+	if (!ret) {
+		u16 std_vddc;
+
+		ret = ni_get_std_voltage_value(rdev,
+					       &table->initialState.levels[0].vddc,
+					       &std_vddc);
+		if (!ret)
+			ni_populate_std_voltage_value(rdev, std_vddc,
+						      table->initialState.levels[0].vddc.index,
+						      &table->initialState.levels[0].std_vddc);
+	}
+
+	if (eg_pi->vddci_control)
+		ni_populate_voltage_value(rdev,
+					  &eg_pi->vddci_voltage_table,
+					  initial_state->performance_levels[0].vddci,
+					  &table->initialState.levels[0].vddci);
+
+	ni_populate_initial_mvdd_value(rdev, &table->initialState.levels[0].mvdd);
+
+	reg = CG_R(0xffff) | CG_L(0);
+	table->initialState.levels[0].aT = cpu_to_be32(reg);
+
+	table->initialState.levels[0].bSP = cpu_to_be32(pi->dsp);
+
+	if (pi->boot_in_gen2)
+		table->initialState.levels[0].gen2PCIE = 1;
+	else
+		table->initialState.levels[0].gen2PCIE = 0;
+
+	if (pi->mem_gddr5) {
+		table->initialState.levels[0].strobeMode =
+			cypress_get_strobe_mode_settings(rdev,
+							 initial_state->performance_levels[0].mclk);
+
+		if (initial_state->performance_levels[0].mclk > pi->mclk_edc_enable_threshold)
+			table->initialState.levels[0].mcFlags = NISLANDS_SMC_MC_EDC_RD_FLAG | NISLANDS_SMC_MC_EDC_WR_FLAG;
+		else
+			table->initialState.levels[0].mcFlags =  0;
+	}
+
+	table->initialState.levelCount = 1;
+
+	table->initialState.flags |= PPSMC_SWSTATE_FLAG_DC;
+
+	table->initialState.levels[0].dpm2.MaxPS = 0;
+	table->initialState.levels[0].dpm2.NearTDPDec = 0;
+	table->initialState.levels[0].dpm2.AboveSafeInc = 0;
+	table->initialState.levels[0].dpm2.BelowSafeInc = 0;
+
+	reg = MIN_POWER_MASK | MAX_POWER_MASK;
+	table->initialState.levels[0].SQPowerThrottle = cpu_to_be32(reg);
+
+	reg = MAX_POWER_DELTA_MASK | STI_SIZE_MASK | LTI_RATIO_MASK;
+	table->initialState.levels[0].SQPowerThrottle_2 = cpu_to_be32(reg);
+
+	return 0;
+}
+
+static int ni_populate_smc_acpi_state(struct radeon_device *rdev,
+				      NISLANDS_SMC_STATETABLE *table)
+{
+	struct rv7xx_power_info *pi = rv770_get_pi(rdev);
+	struct evergreen_power_info *eg_pi = evergreen_get_pi(rdev);
+	struct ni_power_info *ni_pi = ni_get_pi(rdev);
+	u32 mpll_ad_func_cntl   = ni_pi->clock_registers.mpll_ad_func_cntl;
+	u32 mpll_ad_func_cntl_2 = ni_pi->clock_registers.mpll_ad_func_cntl_2;
+	u32 mpll_dq_func_cntl   = ni_pi->clock_registers.mpll_dq_func_cntl;
+	u32 mpll_dq_func_cntl_2 = ni_pi->clock_registers.mpll_dq_func_cntl_2;
+	u32 spll_func_cntl      = ni_pi->clock_registers.cg_spll_func_cntl;
+	u32 spll_func_cntl_2    = ni_pi->clock_registers.cg_spll_func_cntl_2;
+	u32 spll_func_cntl_3    = ni_pi->clock_registers.cg_spll_func_cntl_3;
+	u32 spll_func_cntl_4    = ni_pi->clock_registers.cg_spll_func_cntl_4;
+	u32 mclk_pwrmgt_cntl    = ni_pi->clock_registers.mclk_pwrmgt_cntl;
+	u32 dll_cntl            = ni_pi->clock_registers.dll_cntl;
+	u32 reg;
+	int ret;
+
+	table->ACPIState = table->initialState;
+
+	table->ACPIState.flags &= ~PPSMC_SWSTATE_FLAG_DC;
+
+	if (pi->acpi_vddc) {
+		ret = ni_populate_voltage_value(rdev,
+						&eg_pi->vddc_voltage_table,
+						pi->acpi_vddc, &table->ACPIState.levels[0].vddc);
+		if (!ret) {
+			u16 std_vddc;
+
+			ret = ni_get_std_voltage_value(rdev,
+						       &table->ACPIState.levels[0].vddc, &std_vddc);
+			if (!ret)
+				ni_populate_std_voltage_value(rdev, std_vddc,
+							      table->ACPIState.levels[0].vddc.index,
+							      &table->ACPIState.levels[0].std_vddc);
+		}
+
+		if (pi->pcie_gen2) {
+			if (pi->acpi_pcie_gen2)
+				table->ACPIState.levels[0].gen2PCIE = 1;
+			else
+				table->ACPIState.levels[0].gen2PCIE = 0;
+		} else {
+			table->ACPIState.levels[0].gen2PCIE = 0;
+		}
+	} else {
+		ret = ni_populate_voltage_value(rdev,
+						&eg_pi->vddc_voltage_table,
+						pi->min_vddc_in_table,
+						&table->ACPIState.levels[0].vddc);
+		if (!ret) {
+			u16 std_vddc;
+
+			ret = ni_get_std_voltage_value(rdev,
+						       &table->ACPIState.levels[0].vddc,
+						       &std_vddc);
+			if (!ret)
+				ni_populate_std_voltage_value(rdev, std_vddc,
+							      table->ACPIState.levels[0].vddc.index,
+							      &table->ACPIState.levels[0].std_vddc);
+		}
+		table->ACPIState.levels[0].gen2PCIE = 0;
+	}
+
+	if (eg_pi->acpi_vddci) {
+		if (eg_pi->vddci_control)
+			ni_populate_voltage_value(rdev,
+						  &eg_pi->vddci_voltage_table,
+						  eg_pi->acpi_vddci,
+						  &table->ACPIState.levels[0].vddci);
+	}
+
+
+	mpll_ad_func_cntl &= ~PDNB;
+
+	mpll_ad_func_cntl_2 |= BIAS_GEN_PDNB | RESET_EN;
+
+        if (pi->mem_gddr5)
+                mpll_dq_func_cntl &= ~PDNB;
+        mpll_dq_func_cntl_2 |= BIAS_GEN_PDNB | RESET_EN | BYPASS;

drivers/gpu/drm/radeon/ni_dpm.c line 1868

Quoted 10 lines
drivers/gpu/drm/radeon/ni_dpm.c new file +10 -0
+
+
+        mclk_pwrmgt_cntl |= (MRDCKA0_RESET |
+                             MRDCKA1_RESET |
+                             MRDCKB0_RESET |
+                             MRDCKB1_RESET |
+                             MRDCKC0_RESET |
+                             MRDCKC1_RESET |
+                             MRDCKD0_RESET |
+                             MRDCKD1_RESET);

^
Broken indentation.

Quoted 8 lines
drivers/gpu/drm/radeon/ni_dpm.c new file +8 -0
+
+        mclk_pwrmgt_cntl &= ~(MRDCKA0_PDNB |
+                              MRDCKA1_PDNB |
+			      MRDCKB0_PDNB |
+                              MRDCKB1_PDNB |
+			      MRDCKC0_PDNB |
+                              MRDCKC1_PDNB |
+                              MRDCKD0_PDNB |

drivers/gpu/drm/radeon/ni_dpm.c line 1886

Quoted 10 lines
drivers/gpu/drm/radeon/ni_dpm.c new file +10 -0
+                              MRDCKD1_PDNB);
+
+	dll_cntl |= (MRDCKA0_BYPASS |
+                     MRDCKA1_BYPASS |
+                     MRDCKB0_BYPASS |
+                     MRDCKB1_BYPASS |
+                     MRDCKC0_BYPASS |
+                     MRDCKC1_BYPASS |
+                     MRDCKD0_BYPASS |
+                     MRDCKD1_BYPASS);

^
Broken indentation.

Quoted 48 lines
drivers/gpu/drm/radeon/ni_dpm.c new file +48 -0
+
+        spll_func_cntl_2 &= ~SCLK_MUX_SEL_MASK;
+	spll_func_cntl_2 |= SCLK_MUX_SEL(4);
+
+	table->ACPIState.levels[0].mclk.vMPLL_AD_FUNC_CNTL = cpu_to_be32(mpll_ad_func_cntl);
+	table->ACPIState.levels[0].mclk.vMPLL_AD_FUNC_CNTL_2 = cpu_to_be32(mpll_ad_func_cntl_2);
+	table->ACPIState.levels[0].mclk.vMPLL_DQ_FUNC_CNTL = cpu_to_be32(mpll_dq_func_cntl);
+	table->ACPIState.levels[0].mclk.vMPLL_DQ_FUNC_CNTL_2 = cpu_to_be32(mpll_dq_func_cntl_2);
+	table->ACPIState.levels[0].mclk.vMCLK_PWRMGT_CNTL = cpu_to_be32(mclk_pwrmgt_cntl);
+	table->ACPIState.levels[0].mclk.vDLL_CNTL = cpu_to_be32(dll_cntl);
+
+	table->ACPIState.levels[0].mclk.mclk_value = 0;
+
+	table->ACPIState.levels[0].sclk.vCG_SPLL_FUNC_CNTL = cpu_to_be32(spll_func_cntl);
+	table->ACPIState.levels[0].sclk.vCG_SPLL_FUNC_CNTL_2 = cpu_to_be32(spll_func_cntl_2);
+	table->ACPIState.levels[0].sclk.vCG_SPLL_FUNC_CNTL_3 = cpu_to_be32(spll_func_cntl_3);
+	table->ACPIState.levels[0].sclk.vCG_SPLL_FUNC_CNTL_4 = cpu_to_be32(spll_func_cntl_4);
+
+	table->ACPIState.levels[0].sclk.sclk_value = 0;
+
+	ni_populate_mvdd_value(rdev, 0, &table->ACPIState.levels[0].mvdd);
+
+	if (eg_pi->dynamic_ac_timing)
+		table->ACPIState.levels[0].ACIndex = 1;
+
+	table->ACPIState.levels[0].dpm2.MaxPS = 0;
+	table->ACPIState.levels[0].dpm2.NearTDPDec = 0;
+	table->ACPIState.levels[0].dpm2.AboveSafeInc = 0;
+	table->ACPIState.levels[0].dpm2.BelowSafeInc = 0;
+
+	reg = MIN_POWER_MASK | MAX_POWER_MASK;
+	table->ACPIState.levels[0].SQPowerThrottle = cpu_to_be32(reg);
+
+	reg = MAX_POWER_DELTA_MASK | STI_SIZE_MASK | LTI_RATIO_MASK;
+	table->ACPIState.levels[0].SQPowerThrottle_2 = cpu_to_be32(reg);
+
+	return 0;
+}
+
+static int ni_init_smc_table(struct radeon_device *rdev)
+{
+	struct rv7xx_power_info *pi = rv770_get_pi(rdev);
+	struct ni_power_info *ni_pi = ni_get_pi(rdev);
+	int ret;
+	struct radeon_ps *radeon_boot_state = rdev->pm.dpm.boot_ps;
+	NISLANDS_SMC_STATETABLE *table = &ni_pi->smc_statetable;
+
+	memset(table, 0, sizeof(NISLANDS_SMC_STATETABLE));

drivers/gpu/drm/radeon/ni_dpm.c line 1944

Quoted 10 lines
drivers/gpu/drm/radeon/ni_dpm.c new file +10 -0
+
+	ni_populate_smc_voltage_tables(rdev, table);
+
+        switch (rdev->pm.int_thermal_type) {
+        case THERMAL_TYPE_NI:
+        case THERMAL_TYPE_EMC2103_WITH_INTERNAL:
+                table->thermalProtectType = PPSMC_THERMAL_PROTECT_TYPE_INTERNAL;
+                break;
+        case THERMAL_TYPE_NONE:
+                table->thermalProtectType = PPSMC_THERMAL_PROTECT_TYPE_NONE;

^
Broken indentation.

Quoted 34 lines
drivers/gpu/drm/radeon/ni_dpm.c new file +34 -0
+		break;
+        default:
+                table->thermalProtectType = PPSMC_THERMAL_PROTECT_TYPE_EXTERNAL;
+                break;
+        }
+
+	if (rdev->pm.dpm.platform_caps & ATOM_PP_PLATFORM_CAP_HARDWAREDC)
+		table->systemFlags |= PPSMC_SYSTEMFLAG_GPIO_DC;
+
+	if (rdev->pm.dpm.platform_caps & ATOM_PP_PLATFORM_CAP_REGULATOR_HOT)
+		table->systemFlags |= PPSMC_SYSTEMFLAG_REGULATOR_HOT;
+
+	if (rdev->pm.dpm.platform_caps & ATOM_PP_PLATFORM_CAP_STEPVDDC)
+		table->systemFlags |= PPSMC_SYSTEMFLAG_STEPVDDC;
+
+	if (pi->mem_gddr5)
+		table->systemFlags |= PPSMC_SYSTEMFLAG_GDDR5;
+
+	ret = ni_populate_smc_initial_state(rdev, radeon_boot_state, table);
+	if (ret)
+		return ret;
+
+	ret = ni_populate_smc_acpi_state(rdev, table);
+	if (ret)
+		return ret;
+
+	table->driverState = table->initialState;
+
+	table->ULVState = table->initialState;
+
+	ret = ni_do_program_memory_timing_parameters(rdev, radeon_boot_state,
+						     NISLANDS_INITIAL_STATE_ARB_INDEX);
+	if (ret)
+		return ret;

drivers/gpu/drm/radeon/ni_dpm.c line 1988

Quoted 10 lines
drivers/gpu/drm/radeon/ni_dpm.c new file +10 -0
+
+	return rv770_copy_bytes_to_smc(rdev, pi->state_table_start, (u8 *)table,
+				       sizeof(NISLANDS_SMC_STATETABLE), pi->sram_end);
+}
+
+static int ni_calculate_sclk_params(struct radeon_device *rdev,
+				    u32 engine_clock,
+				    NISLANDS_SMC_SCLK_VALUE *sclk)
+{
+        struct rv7xx_power_info *pi = rv770_get_pi(rdev);

^
Broken indentation.

Quoted 21 lines
drivers/gpu/drm/radeon/ni_dpm.c new file +21 -0
+	struct ni_power_info *ni_pi = ni_get_pi(rdev);
+	struct atom_clock_dividers dividers;
+	u32 spll_func_cntl = ni_pi->clock_registers.cg_spll_func_cntl;
+	u32 spll_func_cntl_2 = ni_pi->clock_registers.cg_spll_func_cntl_2;
+	u32 spll_func_cntl_3 = ni_pi->clock_registers.cg_spll_func_cntl_3;
+	u32 spll_func_cntl_4 = ni_pi->clock_registers.cg_spll_func_cntl_4;
+	u32 cg_spll_spread_spectrum = ni_pi->clock_registers.cg_spll_spread_spectrum;
+	u32 cg_spll_spread_spectrum_2 = ni_pi->clock_registers.cg_spll_spread_spectrum_2;
+	u64 tmp;
+	u32 reference_clock = rdev->clock.spll.reference_freq;
+	u32 reference_divider;
+	u32 fbdiv;
+	int ret;
+
+        ret = radeon_atom_get_clock_dividers(rdev, COMPUTE_ENGINE_PLL_PARAM,
+                                             engine_clock, false, &dividers);
+	if (ret)
+		return ret;
+
+	reference_divider = 1 + dividers.ref_div;
+

drivers/gpu/drm/radeon/ni_dpm.c line 2019

Quoted 10 lines
drivers/gpu/drm/radeon/ni_dpm.c new file +10 -0
+	tmp = (u64) engine_clock * reference_divider * dividers.post_div;
+
+	fbdiv = (u32) ((16384 * tmp) / reference_clock);
+
+        spll_func_cntl &= ~(SPLL_PDIV_A_MASK | SPLL_REF_DIV_MASK);
+        spll_func_cntl |= SPLL_REF_DIV(dividers.ref_div);
+        spll_func_cntl |= SPLL_PDIV_A(dividers.post_div);
+
+        spll_func_cntl_2 &= ~SCLK_MUX_SEL_MASK;
+        spll_func_cntl_2 |= SCLK_MUX_SEL(2);

^
Broken indentation.

Quoted 10 lines
drivers/gpu/drm/radeon/ni_dpm.c new file +10 -0
+
+	spll_func_cntl_3 &= ~SPLL_FB_DIV_MASK;
+        spll_func_cntl_3 |= SPLL_FB_DIV(fbdiv);
+        spll_func_cntl_3 |= SPLL_DITHEN;
+
+	if (pi->sclk_ss) {
+                struct radeon_atom_ss ss;
+                u32 vco_freq = engine_clock * dividers.post_div;
+
+                if (radeon_atombios_get_asic_ss_info(rdev, &ss,

drivers/gpu/drm/radeon/ni_dpm.c line 2039

Quoted 10 lines
drivers/gpu/drm/radeon/ni_dpm.c new file +10 -0
+                                                     ASIC_INTERNAL_ENGINE_SS, vco_freq)) {
+                        u32 clk_s = reference_clock * 5 / (reference_divider * ss.rate);
+                        u32 clk_v = 4 * ss.percentage * fbdiv / (clk_s * 10000);
+
+                        cg_spll_spread_spectrum &= ~CLK_S_MASK;
+			cg_spll_spread_spectrum |= CLK_S(clk_s);
+                        cg_spll_spread_spectrum |= SSEN;
+
+                        cg_spll_spread_spectrum_2 &= ~CLK_V_MASK;
+                        cg_spll_spread_spectrum_2 |= CLK_V(clk_v);

^
Broken indentation.

Quoted 120 lines
drivers/gpu/drm/radeon/ni_dpm.c new file +120 -0
+		}
+	}
+
+	sclk->sclk_value = engine_clock;
+	sclk->vCG_SPLL_FUNC_CNTL = spll_func_cntl;
+	sclk->vCG_SPLL_FUNC_CNTL_2 = spll_func_cntl_2;
+	sclk->vCG_SPLL_FUNC_CNTL_3 = spll_func_cntl_3;
+	sclk->vCG_SPLL_FUNC_CNTL_4 = spll_func_cntl_4;
+	sclk->vCG_SPLL_SPREAD_SPECTRUM = cg_spll_spread_spectrum;
+	sclk->vCG_SPLL_SPREAD_SPECTRUM_2 = cg_spll_spread_spectrum_2;
+
+	return 0;
+}
+
+static int ni_populate_sclk_value(struct radeon_device *rdev,
+				  u32 engine_clock,
+				  NISLANDS_SMC_SCLK_VALUE *sclk)
+{
+	NISLANDS_SMC_SCLK_VALUE sclk_tmp;
+	int ret;
+
+	ret = ni_calculate_sclk_params(rdev, engine_clock, &sclk_tmp);
+	if (!ret) {
+		sclk->sclk_value = cpu_to_be32(sclk_tmp.sclk_value);
+		sclk->vCG_SPLL_FUNC_CNTL = cpu_to_be32(sclk_tmp.vCG_SPLL_FUNC_CNTL);
+		sclk->vCG_SPLL_FUNC_CNTL_2 = cpu_to_be32(sclk_tmp.vCG_SPLL_FUNC_CNTL_2);
+		sclk->vCG_SPLL_FUNC_CNTL_3 = cpu_to_be32(sclk_tmp.vCG_SPLL_FUNC_CNTL_3);
+		sclk->vCG_SPLL_FUNC_CNTL_4 = cpu_to_be32(sclk_tmp.vCG_SPLL_FUNC_CNTL_4);
+		sclk->vCG_SPLL_SPREAD_SPECTRUM = cpu_to_be32(sclk_tmp.vCG_SPLL_SPREAD_SPECTRUM);
+		sclk->vCG_SPLL_SPREAD_SPECTRUM_2 = cpu_to_be32(sclk_tmp.vCG_SPLL_SPREAD_SPECTRUM_2);
+	}
+
+	return ret;
+}
+
+static int ni_init_smc_spll_table(struct radeon_device *rdev)
+{
+        struct rv7xx_power_info *pi = rv770_get_pi(rdev);
+	struct ni_power_info *ni_pi = ni_get_pi(rdev);
+	SMC_NISLANDS_SPLL_DIV_TABLE *spll_table;
+	NISLANDS_SMC_SCLK_VALUE sclk_params;
+	u32 fb_div;
+	u32 p_div;
+	u32 clk_s;
+	u32 clk_v;
+	u32 sclk = 0;
+	int i, ret;
+	u32 tmp;
+
+	if (ni_pi->spll_table_start == 0)
+		return -EINVAL;
+
+	spll_table = kzalloc(sizeof(SMC_NISLANDS_SPLL_DIV_TABLE), GFP_KERNEL);
+	if (spll_table == NULL)
+		return -ENOMEM;
+
+	for (i = 0; i < 256; i++) {
+		ret = ni_calculate_sclk_params(rdev, sclk, &sclk_params);
+		if (ret)
+			break;
+
+		p_div = (sclk_params.vCG_SPLL_FUNC_CNTL & SPLL_PDIV_A_MASK) >> SPLL_PDIV_A_SHIFT;
+		fb_div = (sclk_params.vCG_SPLL_FUNC_CNTL_3 & SPLL_FB_DIV_MASK) >> SPLL_FB_DIV_SHIFT;
+		clk_s = (sclk_params.vCG_SPLL_SPREAD_SPECTRUM & CLK_S_MASK) >> CLK_S_SHIFT;
+		clk_v = (sclk_params.vCG_SPLL_SPREAD_SPECTRUM_2 & CLK_V_MASK) >> CLK_V_SHIFT;
+
+		fb_div &= ~0x00001FFF;
+		fb_div >>= 1;
+		clk_v >>= 6;
+
+		if (p_div & ~(SMC_NISLANDS_SPLL_DIV_TABLE_PDIV_MASK >> SMC_NISLANDS_SPLL_DIV_TABLE_PDIV_SHIFT))
+			ret = -EINVAL;
+
+		if (clk_s & ~(SMC_NISLANDS_SPLL_DIV_TABLE_CLKS_MASK >> SMC_NISLANDS_SPLL_DIV_TABLE_CLKS_SHIFT))
+			ret = -EINVAL;
+
+		if (clk_s & ~(SMC_NISLANDS_SPLL_DIV_TABLE_CLKS_MASK >> SMC_NISLANDS_SPLL_DIV_TABLE_CLKS_SHIFT))
+			ret = -EINVAL;
+
+		if (clk_v & ~(SMC_NISLANDS_SPLL_DIV_TABLE_CLKV_MASK >> SMC_NISLANDS_SPLL_DIV_TABLE_CLKV_SHIFT))
+			ret = -EINVAL;
+
+		if (ret)
+			break;
+
+		tmp = ((fb_div << SMC_NISLANDS_SPLL_DIV_TABLE_FBDIV_SHIFT) & SMC_NISLANDS_SPLL_DIV_TABLE_FBDIV_MASK) |
+			((p_div << SMC_NISLANDS_SPLL_DIV_TABLE_PDIV_SHIFT) & SMC_NISLANDS_SPLL_DIV_TABLE_PDIV_MASK);
+		spll_table->freq[i] = cpu_to_be32(tmp);
+
+		tmp = ((clk_v << SMC_NISLANDS_SPLL_DIV_TABLE_CLKV_SHIFT) & SMC_NISLANDS_SPLL_DIV_TABLE_CLKV_MASK) |
+			((clk_s << SMC_NISLANDS_SPLL_DIV_TABLE_CLKS_SHIFT) & SMC_NISLANDS_SPLL_DIV_TABLE_CLKS_MASK);
+		spll_table->ss[i] = cpu_to_be32(tmp);
+
+		sclk += 512;
+	}
+
+	if (!ret)
+		ret = rv770_copy_bytes_to_smc(rdev, ni_pi->spll_table_start, (u8 *)spll_table,
+					      sizeof(SMC_NISLANDS_SPLL_DIV_TABLE), pi->sram_end);
+
+	kfree(spll_table);
+
+	return ret;
+}
+
+static int ni_populate_mclk_value(struct radeon_device *rdev,
+				  u32 engine_clock,
+				  u32 memory_clock,
+				  NISLANDS_SMC_MCLK_VALUE *mclk,
+				  bool strobe_mode,
+				  bool dll_state_on)
+{
+	struct rv7xx_power_info *pi = rv770_get_pi(rdev);
+	struct ni_power_info *ni_pi = ni_get_pi(rdev);
+	u32 mpll_ad_func_cntl = ni_pi->clock_registers.mpll_ad_func_cntl;
+	u32 mpll_ad_func_cntl_2 = ni_pi->clock_registers.mpll_ad_func_cntl_2;
+	u32 mpll_dq_func_cntl = ni_pi->clock_registers.mpll_dq_func_cntl;
+	u32 mpll_dq_func_cntl_2 = ni_pi->clock_registers.mpll_dq_func_cntl_2;
+	u32 mclk_pwrmgt_cntl = ni_pi->clock_registers.mclk_pwrmgt_cntl;
+	u32 dll_cntl = ni_pi->clock_registers.dll_cntl;

drivers/gpu/drm/radeon/ni_dpm.c line 2169

Quoted 10 lines
drivers/gpu/drm/radeon/ni_dpm.c new file +10 -0
+	u32 mpll_ss1 = ni_pi->clock_registers.mpll_ss1;
+	u32 mpll_ss2 = ni_pi->clock_registers.mpll_ss2;
+	struct atom_clock_dividers dividers;
+	u32 ibias;
+	u32 dll_speed;
+	int ret;
+	u32 mc_seq_misc7;
+
+        ret = radeon_atom_get_clock_dividers(rdev, COMPUTE_MEMORY_PLL_PARAM,
+                                             memory_clock, strobe_mode, &dividers);

^
Broken indentation.

Quoted 11 lines
drivers/gpu/drm/radeon/ni_dpm.c new file +11 -0
+	if (ret)
+		return ret;
+
+	if (!strobe_mode) {
+		mc_seq_misc7 = RREG32(MC_SEQ_MISC7);
+
+		if (mc_seq_misc7 & 0x8000000)
+			dividers.post_div = 1;
+	}
+
+	ibias = cypress_map_clkf_to_ibias(rdev, dividers.whole_fb_div);

drivers/gpu/drm/radeon/ni_dpm.c line 2190

Quoted 10 lines
drivers/gpu/drm/radeon/ni_dpm.c new file +10 -0
+
+        mpll_ad_func_cntl &= ~(CLKR_MASK |
+                               YCLK_POST_DIV_MASK |
+                               CLKF_MASK |
+                               CLKFRAC_MASK |
+                               IBIAS_MASK);
+        mpll_ad_func_cntl |= CLKR(dividers.ref_div);
+        mpll_ad_func_cntl |= YCLK_POST_DIV(dividers.post_div);
+        mpll_ad_func_cntl |= CLKF(dividers.whole_fb_div);
+        mpll_ad_func_cntl |= CLKFRAC(dividers.frac_fb_div);

^
Broken indentation.

drivers/gpu/drm/radeon/ni_dpm.c line 2193

Quoted 3 lines
drivers/gpu/drm/radeon/ni_dpm.c new file +3 -0
+	mpll_ad_func_cntl |= IBIAS(ibias);
+
+        if (dividers.vco_mode)

^
Broken indentation.

Quoted 3,200 lines
drivers/gpu/drm/radeon/ni_dpm.c new file +1900 -0
+		mpll_ad_func_cntl_2 |= VCO_MODE;
+	else
+		mpll_ad_func_cntl_2 &= ~VCO_MODE;
+
+	if (pi->mem_gddr5) {
+                mpll_dq_func_cntl &= ~(CLKR_MASK |
+                                       YCLK_POST_DIV_MASK |
+                                       CLKF_MASK |
+                                       CLKFRAC_MASK |
+                                       IBIAS_MASK);
+                mpll_dq_func_cntl |= CLKR(dividers.ref_div);
+                mpll_dq_func_cntl |= YCLK_POST_DIV(dividers.post_div);
+                mpll_dq_func_cntl |= CLKF(dividers.whole_fb_div);
+                mpll_dq_func_cntl |= CLKFRAC(dividers.frac_fb_div);
+                mpll_dq_func_cntl |= IBIAS(ibias);
+
+		if (strobe_mode)
+			mpll_dq_func_cntl &= ~PDNB;
+                else
+			mpll_dq_func_cntl |= PDNB;
+
+		if (dividers.vco_mode)
+			mpll_dq_func_cntl_2 |= VCO_MODE;
+		else
+                        mpll_dq_func_cntl_2 &= ~VCO_MODE;
+	}
+
+	if (pi->mclk_ss) {
+                struct radeon_atom_ss ss;
+                u32 vco_freq = memory_clock * dividers.post_div;
+
+                if (radeon_atombios_get_asic_ss_info(rdev, &ss,
+						     ASIC_INTERNAL_MEMORY_SS, vco_freq)) {
+			u32 reference_clock = rdev->clock.mpll.reference_freq;
+                        u32 decoded_ref = rv740_get_decoded_reference_divider(dividers.ref_div);
+			u32 clk_s = reference_clock * 5 / (decoded_ref * ss.rate);
+                        u32 clk_v = ss.percentage *
+                                (0x4000 * dividers.whole_fb_div + 0x800 * dividers.frac_fb_div) / (clk_s * 625);
+
+                        mpll_ss1 &= ~CLKV_MASK;
+                        mpll_ss1 |= CLKV(clk_v);
+
+                        mpll_ss2 &= ~CLKS_MASK;
+                        mpll_ss2 |= CLKS(clk_s);
+		}
+	}
+
+        dll_speed = rv740_get_dll_speed(pi->mem_gddr5,
+                                        memory_clock);
+
+        mclk_pwrmgt_cntl &= ~DLL_SPEED_MASK;
+        mclk_pwrmgt_cntl |= DLL_SPEED(dll_speed);
+        if (dll_state_on)
+                mclk_pwrmgt_cntl |= (MRDCKA0_PDNB |
+                                     MRDCKA1_PDNB |
+                                     MRDCKB0_PDNB |
+                                     MRDCKB1_PDNB |
+                                     MRDCKC0_PDNB |
+                                     MRDCKC1_PDNB |
+                                     MRDCKD0_PDNB |
+                                     MRDCKD1_PDNB);
+        else
+                mclk_pwrmgt_cntl &= ~(MRDCKA0_PDNB |
+                                      MRDCKA1_PDNB |
+                                      MRDCKB0_PDNB |
+                                      MRDCKB1_PDNB |
+                                      MRDCKC0_PDNB |
+                                      MRDCKC1_PDNB |
+                                      MRDCKD0_PDNB |
+                                      MRDCKD1_PDNB);
+
+
+	mclk->mclk_value = cpu_to_be32(memory_clock);
+	mclk->vMPLL_AD_FUNC_CNTL = cpu_to_be32(mpll_ad_func_cntl);
+	mclk->vMPLL_AD_FUNC_CNTL_2 = cpu_to_be32(mpll_ad_func_cntl_2);
+	mclk->vMPLL_DQ_FUNC_CNTL = cpu_to_be32(mpll_dq_func_cntl);
+	mclk->vMPLL_DQ_FUNC_CNTL_2 = cpu_to_be32(mpll_dq_func_cntl_2);
+	mclk->vMCLK_PWRMGT_CNTL = cpu_to_be32(mclk_pwrmgt_cntl);
+	mclk->vDLL_CNTL = cpu_to_be32(dll_cntl);
+	mclk->vMPLL_SS = cpu_to_be32(mpll_ss1);
+	mclk->vMPLL_SS2 = cpu_to_be32(mpll_ss2);
+
+	return 0;
+}
+
+static void ni_populate_smc_sp(struct radeon_device *rdev,
+			       struct radeon_ps *radeon_state,
+			       NISLANDS_SMC_SWSTATE *smc_state)
+{
+	struct ni_ps *ps = ni_get_ps(radeon_state);
+	struct rv7xx_power_info *pi = rv770_get_pi(rdev);
+	int i;
+
+	for (i = 0; i < ps->performance_level_count - 1; i++)
+		smc_state->levels[i].bSP = cpu_to_be32(pi->dsp);
+
+	smc_state->levels[ps->performance_level_count - 1].bSP =
+		cpu_to_be32(pi->psp);
+}
+
+static int ni_convert_power_level_to_smc(struct radeon_device *rdev,
+					 struct rv7xx_pl *pl,
+					 NISLANDS_SMC_HW_PERFORMANCE_LEVEL *level)
+{
+	struct rv7xx_power_info *pi = rv770_get_pi(rdev);
+        struct evergreen_power_info *eg_pi = evergreen_get_pi(rdev);
+        struct ni_power_info *ni_pi = ni_get_pi(rdev);
+	int ret;
+	bool dll_state_on;
+	u16 std_vddc;
+	u32 tmp = RREG32(DC_STUTTER_CNTL);
+
+	level->gen2PCIE = pi->pcie_gen2 ?
+		((pl->flags & ATOM_PPLIB_R600_FLAGS_PCIEGEN2) ? 1 : 0) : 0;
+
+	ret = ni_populate_sclk_value(rdev, pl->sclk, &level->sclk);
+	if (ret)
+		return ret;
+
+	level->mcFlags =  0;
+	if (pi->mclk_stutter_mode_threshold &&
+	    (pl->mclk <= pi->mclk_stutter_mode_threshold) &&
+	    !eg_pi->uvd_enabled &&
+	    (tmp & DC_STUTTER_ENABLE_A) &&
+	    (tmp & DC_STUTTER_ENABLE_B))
+		level->mcFlags |= NISLANDS_SMC_MC_STUTTER_EN;
+
+	if (pi->mem_gddr5) {
+		if (pl->mclk > pi->mclk_edc_enable_threshold)
+			level->mcFlags |= NISLANDS_SMC_MC_EDC_RD_FLAG;
+		if (pl->mclk > eg_pi->mclk_edc_wr_enable_threshold)
+			level->mcFlags |= NISLANDS_SMC_MC_EDC_WR_FLAG;
+
+		level->strobeMode = cypress_get_strobe_mode_settings(rdev, pl->mclk);
+
+		if (level->strobeMode & NISLANDS_SMC_STROBE_ENABLE) {
+			if (cypress_get_mclk_frequency_ratio(rdev, pl->mclk, true) >=
+			    ((RREG32(MC_SEQ_MISC7) >> 16) & 0xf))
+				dll_state_on = ((RREG32(MC_SEQ_MISC5) >> 1) & 0x1) ? true : false;
+			else
+				dll_state_on = ((RREG32(MC_SEQ_MISC6) >> 1) & 0x1) ? true : false;
+		} else {
+			dll_state_on = false;
+			if (pl->mclk > ni_pi->mclk_rtt_mode_threshold)
+				level->mcFlags |= NISLANDS_SMC_MC_RTT_ENABLE;
+		}
+
+		ret = ni_populate_mclk_value(rdev, pl->sclk, pl->mclk,
+					     &level->mclk,
+					     (level->strobeMode & NISLANDS_SMC_STROBE_ENABLE) != 0,
+					     dll_state_on);
+	} else
+		ret = ni_populate_mclk_value(rdev, pl->sclk, pl->mclk, &level->mclk, 1, 1);
+
+	if (ret)
+		return ret;
+
+	ret = ni_populate_voltage_value(rdev, &eg_pi->vddc_voltage_table,
+					pl->vddc, &level->vddc);
+	if (ret)
+		return ret;
+
+	ret = ni_get_std_voltage_value(rdev, &level->vddc, &std_vddc);
+	if (ret)
+		return ret;
+
+	ni_populate_std_voltage_value(rdev, std_vddc,
+				      level->vddc.index, &level->std_vddc);
+
+	if (eg_pi->vddci_control) {
+		ret = ni_populate_voltage_value(rdev, &eg_pi->vddci_voltage_table,
+						pl->vddci, &level->vddci);
+		if (ret)
+			return ret;
+	}
+
+	ni_populate_mvdd_value(rdev, pl->mclk, &level->mvdd);
+
+	return ret;
+}
+
+static int ni_populate_smc_t(struct radeon_device *rdev,
+			     struct radeon_ps *radeon_state,
+			     NISLANDS_SMC_SWSTATE *smc_state)
+{
+        struct rv7xx_power_info *pi = rv770_get_pi(rdev);
+        struct evergreen_power_info *eg_pi = evergreen_get_pi(rdev);
+	struct ni_ps *state = ni_get_ps(radeon_state);
+	u32 a_t;
+	u32 t_l, t_h;
+	u32 high_bsp;
+	int i, ret;
+
+	if (state->performance_level_count >= 9)
+		return -EINVAL;
+
+	if (state->performance_level_count < 2) {
+		a_t = CG_R(0xffff) | CG_L(0);
+		smc_state->levels[0].aT = cpu_to_be32(a_t);
+		return 0;
+	}
+
+	smc_state->levels[0].aT = cpu_to_be32(0);
+
+	for (i = 0; i <= state->performance_level_count - 2; i++) {
+		if (eg_pi->uvd_enabled)
+			ret = r600_calculate_at(
+				1000 * (i * (eg_pi->smu_uvd_hs ? 2 : 8) + 2),
+				100 * R600_AH_DFLT,
+				state->performance_levels[i + 1].sclk,
+				state->performance_levels[i].sclk,
+				&t_l,
+				&t_h);
+		else
+			ret = r600_calculate_at(
+				1000 * (i + 1),
+				100 * R600_AH_DFLT,
+				state->performance_levels[i + 1].sclk,
+				state->performance_levels[i].sclk,
+				&t_l,
+				&t_h);
+
+		if (ret) {
+			t_h = (i + 1) * 1000 - 50 * R600_AH_DFLT;
+			t_l = (i + 1) * 1000 + 50 * R600_AH_DFLT;
+		}
+
+		a_t = be32_to_cpu(smc_state->levels[i].aT) & ~CG_R_MASK;
+		a_t |= CG_R(t_l * pi->bsp / 20000);
+		smc_state->levels[i].aT = cpu_to_be32(a_t);
+
+		high_bsp = (i == state->performance_level_count - 2) ?
+			pi->pbsp : pi->bsp;
+
+		a_t = CG_R(0xffff) | CG_L(t_h * high_bsp / 20000);
+		smc_state->levels[i + 1].aT = cpu_to_be32(a_t);
+	}
+
+	return 0;
+}
+
+static int ni_populate_power_containment_values(struct radeon_device *rdev,
+						struct radeon_ps *radeon_state,
+						NISLANDS_SMC_SWSTATE *smc_state)
+{
+        struct rv7xx_power_info *pi = rv770_get_pi(rdev);
+        struct evergreen_power_info *eg_pi = evergreen_get_pi(rdev);
+	struct ni_power_info *ni_pi = ni_get_pi(rdev);
+	struct ni_ps *state = ni_get_ps(radeon_state);
+	u32 prev_sclk;
+	u32 max_sclk;
+	u32 min_sclk;
+	int i, ret;
+	u32 tdp_limit;
+	u32 near_tdp_limit;
+	u32 power_boost_limit;
+	u8 max_ps_percent;
+
+	if (ni_pi->enable_power_containment == false)
+		return 0;
+
+	if (state->performance_level_count == 0)
+		return -EINVAL;
+
+	if (smc_state->levelCount != state->performance_level_count)
+		return -EINVAL;
+
+	ret = ni_calculate_adjusted_tdp_limits(rdev,
+					       false, /* ??? */
+					       rdev->pm.dpm.tdp_adjustment,
+					       &tdp_limit,
+					       &near_tdp_limit);
+	if (ret)
+		return ret;
+
+	power_boost_limit = ni_calculate_power_boost_limit(rdev, radeon_state, near_tdp_limit);
+
+	ret = rv770_write_smc_sram_dword(rdev,
+					 pi->state_table_start +
+					 offsetof(NISLANDS_SMC_STATETABLE, dpm2Params) +
+					 offsetof(PP_NIslands_DPM2Parameters, PowerBoostLimit),
+					 ni_scale_power_for_smc(power_boost_limit, ni_get_smc_power_scaling_factor(rdev)),
+					 pi->sram_end);
+	if (ret)
+		power_boost_limit = 0;
+
+	smc_state->levels[0].dpm2.MaxPS = 0;
+	smc_state->levels[0].dpm2.NearTDPDec = 0;
+	smc_state->levels[0].dpm2.AboveSafeInc = 0;
+	smc_state->levels[0].dpm2.BelowSafeInc = 0;
+	smc_state->levels[0].stateFlags |= power_boost_limit ? PPSMC_STATEFLAG_POWERBOOST : 0;
+
+	for (i = 1; i < state->performance_level_count; i++) {
+		prev_sclk = state->performance_levels[i-1].sclk;
+		max_sclk  = state->performance_levels[i].sclk;
+		max_ps_percent = (i != (state->performance_level_count - 1)) ?
+			NISLANDS_DPM2_MAXPS_PERCENT_M : NISLANDS_DPM2_MAXPS_PERCENT_H;
+
+		if (max_sclk < prev_sclk)
+			return -EINVAL;
+
+		if ((max_ps_percent == 0) || (prev_sclk == max_sclk) || eg_pi->uvd_enabled)
+			min_sclk = max_sclk;
+		else if (1 == i)
+			min_sclk = prev_sclk;
+		else
+			min_sclk = (prev_sclk * (u32)max_ps_percent) / 100;
+
+		if (min_sclk < state->performance_levels[0].sclk)
+			min_sclk = state->performance_levels[0].sclk;
+
+		if (min_sclk == 0)
+			return -EINVAL;
+
+		smc_state->levels[i].dpm2.MaxPS =
+			(u8)((NISLANDS_DPM2_MAX_PULSE_SKIP * (max_sclk - min_sclk)) / max_sclk);
+		smc_state->levels[i].dpm2.NearTDPDec = NISLANDS_DPM2_NEAR_TDP_DEC;
+		smc_state->levels[i].dpm2.AboveSafeInc = NISLANDS_DPM2_ABOVE_SAFE_INC;
+		smc_state->levels[i].dpm2.BelowSafeInc = NISLANDS_DPM2_BELOW_SAFE_INC;
+		smc_state->levels[i].stateFlags |=
+			((i != (state->performance_level_count - 1)) && power_boost_limit) ?
+			PPSMC_STATEFLAG_POWERBOOST : 0;
+	}
+
+	return 0;
+}
+
+static int ni_populate_sq_ramping_values(struct radeon_device *rdev,
+					 struct radeon_ps *radeon_state,
+					 NISLANDS_SMC_SWSTATE *smc_state)
+{
+	struct ni_power_info *ni_pi = ni_get_pi(rdev);
+	struct ni_ps *state = ni_get_ps(radeon_state);
+	u32 sq_power_throttle;
+	u32 sq_power_throttle2;
+	bool enable_sq_ramping = ni_pi->enable_sq_ramping;
+	int i;
+
+	if (state->performance_level_count == 0)
+		return -EINVAL;
+
+	if (smc_state->levelCount != state->performance_level_count)
+		return -EINVAL;
+
+	if (rdev->pm.dpm.sq_ramping_threshold == 0)
+		return -EINVAL;
+
+	if (NISLANDS_DPM2_SQ_RAMP_MAX_POWER > (MAX_POWER_MASK >> MAX_POWER_SHIFT))
+		enable_sq_ramping = false;
+
+	if (NISLANDS_DPM2_SQ_RAMP_MIN_POWER > (MIN_POWER_MASK >> MIN_POWER_SHIFT))
+		enable_sq_ramping = false;
+
+	if (NISLANDS_DPM2_SQ_RAMP_MAX_POWER_DELTA > (MAX_POWER_DELTA_MASK >> MAX_POWER_DELTA_SHIFT))
+		enable_sq_ramping = false;
+
+	if (NISLANDS_DPM2_SQ_RAMP_STI_SIZE > (STI_SIZE_MASK >> STI_SIZE_SHIFT))
+		enable_sq_ramping = false;
+
+	if (NISLANDS_DPM2_SQ_RAMP_LTI_RATIO <= (LTI_RATIO_MASK >> LTI_RATIO_SHIFT))
+		enable_sq_ramping = false;
+
+	for (i = 0; i < state->performance_level_count; i++) {
+		sq_power_throttle  = 0;
+		sq_power_throttle2 = 0;
+
+		if ((state->performance_levels[i].sclk >= rdev->pm.dpm.sq_ramping_threshold) &&
+		    enable_sq_ramping) {
+			sq_power_throttle |= MAX_POWER(NISLANDS_DPM2_SQ_RAMP_MAX_POWER);
+			sq_power_throttle |= MIN_POWER(NISLANDS_DPM2_SQ_RAMP_MIN_POWER);
+			sq_power_throttle2 |= MAX_POWER_DELTA(NISLANDS_DPM2_SQ_RAMP_MAX_POWER_DELTA);
+			sq_power_throttle2 |= STI_SIZE(NISLANDS_DPM2_SQ_RAMP_STI_SIZE);
+			sq_power_throttle2 |= LTI_RATIO(NISLANDS_DPM2_SQ_RAMP_LTI_RATIO);
+		} else {
+			sq_power_throttle |= MAX_POWER_MASK | MIN_POWER_MASK;
+			sq_power_throttle2 |= MAX_POWER_DELTA_MASK | STI_SIZE_MASK | LTI_RATIO_MASK;
+		}
+
+		smc_state->levels[i].SQPowerThrottle   = cpu_to_be32(sq_power_throttle);
+		smc_state->levels[i].SQPowerThrottle_2 = cpu_to_be32(sq_power_throttle2);
+	}
+
+	return 0;
+}
+
+static int ni_enable_power_containment(struct radeon_device *rdev, bool enable)
+{
+        struct ni_power_info *ni_pi = ni_get_pi(rdev);
+	PPSMC_Result smc_result;
+	int ret = 0;
+
+	if (ni_pi->enable_power_containment) {
+		if (enable) {
+			struct radeon_ps *radeon_new_state = rdev->pm.dpm.requested_ps;
+
+			if (!r600_is_uvd_state(radeon_new_state->class, radeon_new_state->class2)) {
+				smc_result = rv770_send_msg_to_smc(rdev, PPSMC_TDPClampingActive);
+				if (smc_result != PPSMC_Result_OK) {
+					ret = -EINVAL;
+					ni_pi->pc_enabled = false;
+				} else {
+					ni_pi->pc_enabled = true;
+				}
+			}
+		} else {
+			smc_result = rv770_send_msg_to_smc(rdev, PPSMC_TDPClampingInactive);
+			if (smc_result != PPSMC_Result_OK)
+				ret = -EINVAL;
+			ni_pi->pc_enabled = false;
+		}
+	}
+
+	return ret;
+}
+
+static int ni_convert_power_state_to_smc(struct radeon_device *rdev,
+					 struct radeon_ps *radeon_state,
+					 NISLANDS_SMC_SWSTATE *smc_state)
+{
+        struct evergreen_power_info *eg_pi = evergreen_get_pi(rdev);
+	struct ni_power_info *ni_pi = ni_get_pi(rdev);
+	struct ni_ps *state = ni_get_ps(radeon_state);
+	int i, ret;
+	u32 threshold = state->performance_levels[state->performance_level_count - 1].sclk * 100 / 100;
+
+	if (!(radeon_state->caps & ATOM_PPLIB_DISALLOW_ON_DC))
+		smc_state->flags |= PPSMC_SWSTATE_FLAG_DC;
+
+	smc_state->levelCount = 0;
+
+	if (state->performance_level_count > NISLANDS_MAX_SMC_PERFORMANCE_LEVELS_PER_SWSTATE)
+		return -EINVAL;
+
+	for (i = 0; i < state->performance_level_count; i++) {
+		ret = ni_convert_power_level_to_smc(rdev, &state->performance_levels[i],
+						    &smc_state->levels[i]);
+		smc_state->levels[i].arbRefreshState =
+			(u8)(NISLANDS_DRIVER_STATE_ARB_INDEX + i);
+
+		if (ret)
+			return ret;
+
+		if (ni_pi->enable_power_containment)
+			smc_state->levels[i].displayWatermark =
+				(state->performance_levels[i].sclk < threshold) ?
+				PPSMC_DISPLAY_WATERMARK_LOW : PPSMC_DISPLAY_WATERMARK_HIGH;
+		else
+			smc_state->levels[i].displayWatermark = (i < 2) ?
+				PPSMC_DISPLAY_WATERMARK_LOW : PPSMC_DISPLAY_WATERMARK_HIGH;
+
+		if (eg_pi->dynamic_ac_timing)
+			smc_state->levels[i].ACIndex = NISLANDS_MCREGISTERTABLE_FIRST_DRIVERSTATE_SLOT + i;
+		else
+			smc_state->levels[i].ACIndex = 0;
+
+		smc_state->levelCount++;
+	}
+
+	rv770_write_smc_soft_register(rdev, NI_SMC_SOFT_REGISTER_watermark_threshold,
+				      cpu_to_be32(threshold / 512));
+
+	ni_populate_smc_sp(rdev, radeon_state, smc_state);
+
+	ret = ni_populate_power_containment_values(rdev, radeon_state, smc_state);
+	if (ret)
+		ni_pi->enable_power_containment = false;
+
+	ret = ni_populate_sq_ramping_values(rdev, radeon_state, smc_state);
+	if (ret)
+		ni_pi->enable_sq_ramping = false;
+
+	return ni_populate_smc_t(rdev, radeon_state, smc_state);
+}
+
+static int ni_upload_sw_state(struct radeon_device *rdev)
+{
+	struct rv7xx_power_info *pi = rv770_get_pi(rdev);
+	struct radeon_ps *radeon_new_state = rdev->pm.dpm.requested_ps;
+	u16 address = pi->state_table_start +
+		offsetof(NISLANDS_SMC_STATETABLE, driverState);
+	u16 state_size = sizeof(NISLANDS_SMC_SWSTATE) +
+		((NISLANDS_MAX_SMC_PERFORMANCE_LEVELS_PER_SWSTATE - 1) * sizeof(NISLANDS_SMC_HW_PERFORMANCE_LEVEL));
+	int ret;
+	NISLANDS_SMC_SWSTATE *smc_state = kzalloc(state_size, GFP_KERNEL);
+
+	if (smc_state == NULL)
+		return -ENOMEM;
+
+	ret = ni_convert_power_state_to_smc(rdev, radeon_new_state, smc_state);
+	if (ret)
+		goto done;
+
+	ret = rv770_copy_bytes_to_smc(rdev, address, (u8 *)smc_state, state_size, pi->sram_end);
+
+done:
+	kfree(smc_state);
+
+	return ret;
+}
+
+static int ni_set_mc_special_registers(struct radeon_device *rdev,
+				       struct ni_mc_reg_table *table)
+{
+	struct rv7xx_power_info *pi = rv770_get_pi(rdev);
+	u8 i, j, k;
+	u32 temp_reg;
+
+	for (i = 0, j = table->last; i < table->last; i++) {
+		switch (table->mc_reg_address[i].s1) {
+		case MC_SEQ_MISC1 >> 2:
+			if (j >= SMC_NISLANDS_MC_REGISTER_ARRAY_SIZE)
+				return -EINVAL;
+			temp_reg = RREG32(MC_PMG_CMD_EMRS);
+			table->mc_reg_address[j].s1 = MC_PMG_CMD_EMRS >> 2;
+			table->mc_reg_address[j].s0 = MC_SEQ_PMG_CMD_EMRS_LP >> 2;
+			for (k = 0; k < table->num_entries; k++)
+				table->mc_reg_table_entry[k].mc_data[j] =
+					((temp_reg & 0xffff0000)) |
+					((table->mc_reg_table_entry[k].mc_data[i] & 0xffff0000) >> 16);
+			j++;
+			if (j >= SMC_NISLANDS_MC_REGISTER_ARRAY_SIZE)
+				return -EINVAL;
+
+			temp_reg = RREG32(MC_PMG_CMD_MRS);
+			table->mc_reg_address[j].s1 = MC_PMG_CMD_MRS >> 2;
+			table->mc_reg_address[j].s0 = MC_SEQ_PMG_CMD_MRS_LP >> 2;
+			for(k = 0; k < table->num_entries; k++) {
+				table->mc_reg_table_entry[k].mc_data[j] =
+					(temp_reg & 0xffff0000) |
+					(table->mc_reg_table_entry[k].mc_data[i] & 0x0000ffff);
+				if (!pi->mem_gddr5)
+					table->mc_reg_table_entry[k].mc_data[j] |= 0x100;
+			}
+			j++;
+			if (j > SMC_NISLANDS_MC_REGISTER_ARRAY_SIZE)
+				return -EINVAL;
+			break;
+		case MC_SEQ_RESERVE_M >> 2:
+			temp_reg = RREG32(MC_PMG_CMD_MRS1);
+			table->mc_reg_address[j].s1 = MC_PMG_CMD_MRS1 >> 2;
+			table->mc_reg_address[j].s0 = MC_SEQ_PMG_CMD_MRS1_LP >> 2;
+			for (k = 0; k < table->num_entries; k++)
+				table->mc_reg_table_entry[k].mc_data[j] =
+					(temp_reg & 0xffff0000) |
+					(table->mc_reg_table_entry[k].mc_data[i] & 0x0000ffff);
+			j++;
+			if (j > SMC_NISLANDS_MC_REGISTER_ARRAY_SIZE)
+				return -EINVAL;
+			break;
+		default:
+			break;
+		}
+	}
+
+	table->last = j;
+
+	return 0;
+}
+
+static bool ni_check_s0_mc_reg_index(u16 in_reg, u16 *out_reg)
+{
+	bool result = true;
+
+	switch (in_reg) {
+        case  MC_SEQ_RAS_TIMING >> 2:
+		*out_reg = MC_SEQ_RAS_TIMING_LP >> 2;
+		break;
+        case MC_SEQ_CAS_TIMING >> 2:
+		*out_reg = MC_SEQ_CAS_TIMING_LP >> 2;
+		break;
+        case MC_SEQ_MISC_TIMING >> 2:
+		*out_reg = MC_SEQ_MISC_TIMING_LP >> 2;
+		break;
+        case MC_SEQ_MISC_TIMING2 >> 2:
+		*out_reg = MC_SEQ_MISC_TIMING2_LP >> 2;
+		break;
+        case MC_SEQ_RD_CTL_D0 >> 2:
+		*out_reg = MC_SEQ_RD_CTL_D0_LP >> 2;
+		break;
+        case MC_SEQ_RD_CTL_D1 >> 2:
+		*out_reg = MC_SEQ_RD_CTL_D1_LP >> 2;
+		break;
+        case MC_SEQ_WR_CTL_D0 >> 2:
+		*out_reg = MC_SEQ_WR_CTL_D0_LP >> 2;
+		break;
+        case MC_SEQ_WR_CTL_D1 >> 2:
+		*out_reg = MC_SEQ_WR_CTL_D1_LP >> 2;
+		break;
+        case MC_PMG_CMD_EMRS >> 2:
+		*out_reg = MC_SEQ_PMG_CMD_EMRS_LP >> 2;
+		break;
+        case MC_PMG_CMD_MRS >> 2:
+		*out_reg = MC_SEQ_PMG_CMD_MRS_LP >> 2;
+		break;
+        case MC_PMG_CMD_MRS1 >> 2:
+		*out_reg = MC_SEQ_PMG_CMD_MRS1_LP >> 2;
+		break;
+        case MC_SEQ_PMG_TIMING >> 2:
+		*out_reg = MC_SEQ_PMG_TIMING_LP >> 2;
+		break;
+        case MC_PMG_CMD_MRS2 >> 2:
+		*out_reg = MC_SEQ_PMG_CMD_MRS2_LP >> 2;
+		break;
+        default:
+		result = false;
+		break;
+	}
+
+	return result;
+}
+
+static void ni_set_valid_flag(struct ni_mc_reg_table *table)
[… more lines in the raw message]

Lines of this file are not shown. View the raw message.

drivers/gpu/drm/radeon/ni_dpm.h new file +233 -0
new file mode 100644
index 0000000..e10f747

Lines of this file are not shown. View the raw message.

drivers/gpu/drm/radeon/nid.h +552 -0
index 7b8da52..1775043 100644

Lines of this file are not shown. View the raw message.

drivers/gpu/drm/radeon/nislands_smc.h new file +329 -0
new file mode 100644
index 0000000..3cf8fc0

Lines of this file are not shown. View the raw message.

drivers/gpu/drm/radeon/ppsmc.h +12 -0
index 3d0786f..607982a 100644

Lines of this file are not shown. View the raw message.

drivers/gpu/drm/radeon/radeon_asic.c +12 -0
index 5dcbb28..e6703ef 100644

Lines of this file are not shown. View the raw message.

drivers/gpu/drm/radeon/radeon_asic.h +10 -0
index 4d3f93d..2fef64d 100644

Lines of this file are not shown. View the raw message.

drivers/gpu/drm/radeon/radeon_pm.c +1 -0
index 2eb41be..01ff18b 100644

Lines of this file are not shown. View the raw message.

drivers/gpu/drm/radeon/radeon_ucode.h +5 -0
index e592e27..51beb4c 100644

Lines of this file are not shown. View the raw message.

drivers/gpu/drm/radeon/rv770_smc.c +27 -0
index 0078c59..ab95da5 100644

Lines of this file are not shown. View the raw message.

The rest of this diff is not shown. View the raw message.

Signature · 6 lines
1.7.7.5

_______________________________________________
dri-devel mailing list
[email protected]
http://lists.freedesktop.org/mailman/listinfo/dri-devel

Part of the diff is not shown here. View the raw message.

#109 lore raw

PATCH 94/165 drm/radeon/cayman: update tdp limits in set_power_state

In reply to [email protected]

From: Alex Deucher <[email protected]>

---
 drivers/gpu/drm/radeon/ni_dpm.c |    1 +
 1 files changed, 1 insertions(+), 0 deletions(-)
drivers/gpu/drm/radeon/ni_dpm.c +1 -0
index 635bf04..44016f2 100644
@@ -3644,6 +3644,7 @@ int ni_dpm_set_power_state(struct radeon_device *rdev)
 	ret = ni_program_memory_timing_parameters(rdev);
 	if (ret)
 		return ret;
+	ni_populate_smc_tdp_limits(rdev);
 	rv770_resume_smc(rdev);
 	rv770_set_sw_state(rdev);
 	ni_enable_smc_cac(rdev, true);
Signature · 1 line
1.7.7.5
#110 lore raw

PATCH 95/165 drm/radeon/dpm/rs780: restructure code

In reply to [email protected]

From: Alex Deucher <[email protected]>

Needed to properly handle dynamic state adjustment.

---
 drivers/gpu/drm/radeon/rs780_dpm.c |   52 ++++++++++++++++++++++--------------
 1 files changed, 32 insertions(+), 20 deletions(-)
drivers/gpu/drm/radeon/rs780_dpm.c +32 -20
index a1497a6..8af1a04 100644
@@ -71,10 +71,11 @@ static void rs780_get_pm_mode_parameters(struct radeon_device *rdev)
 
 static void rs780_voltage_scaling_enable(struct radeon_device *rdev, bool enable);
 
-static int rs780_initialize_dpm_power_state(struct radeon_device *rdev)
+static int rs780_initialize_dpm_power_state(struct radeon_device *rdev,
+					    struct radeon_ps *boot_ps)
 {
 	struct atom_clock_dividers dividers;
-	struct igp_ps *default_state = rs780_get_ps(rdev->pm.dpm.boot_ps);
+	struct igp_ps *default_state = rs780_get_ps(boot_ps);
 	int i, ret;
 
 	ret = radeon_atom_get_clock_dividers(rdev, COMPUTE_ENGINE_PLL_PARAM,
@@ -104,7 +105,8 @@ static int rs780_initialize_dpm_power_state(struct radeon_device *rdev)
 	return 0;
 }
 
-static int rs780_initialize_dpm_parameters(struct radeon_device *rdev)
+static int rs780_initialize_dpm_parameters(struct radeon_device *rdev,
+					   struct radeon_ps *boot_ps)
 {
 	int ret = 0;
 	int i;
@@ -140,7 +142,7 @@ static int rs780_initialize_dpm_parameters(struct radeon_device *rdev)
 	r600_vid_rt_set_vrt(rdev, R600_VOLTAGERESPONSETIME_DFLT);
 	r600_vid_rt_set_ssu(rdev, R600_SPLLSTEPUNIT_DFLT);
 
-	ret = rs780_initialize_dpm_power_state(rdev);
+	ret = rs780_initialize_dpm_power_state(rdev, boot_ps);
 
 	r600_power_level_set_voltage_index(rdev, R600_POWER_LEVEL_LOW,     0);
 	r600_power_level_set_voltage_index(rdev, R600_POWER_LEVEL_MEDIUM,  0);
@@ -401,11 +403,13 @@ static void rs780_force_voltage_to_high(struct radeon_device *rdev)
 	WREG32_P(GFX_MACRO_BYPASS_CNTL, 0, ~SPLL_BYPASS_CNTL);
 }
 
-static int rs780_set_engine_clock_scaling(struct radeon_device *rdev)
+static int rs780_set_engine_clock_scaling(struct radeon_device *rdev,
+					  struct radeon_ps *new_ps,
+					  struct radeon_ps *old_ps)
 {
 	struct atom_clock_dividers min_dividers, max_dividers, current_max_dividers;
-	struct igp_ps *new_state = rs780_get_ps(rdev->pm.dpm.requested_ps);
-	struct igp_ps *old_state = rs780_get_ps(rdev->pm.dpm.current_ps);
+	struct igp_ps *new_state = rs780_get_ps(new_ps);
+	struct igp_ps *old_state = rs780_get_ps(old_ps);
 	int ret;
 
 	if ((new_state->sclk_high == old_state->sclk_high) &&
@@ -451,10 +455,12 @@ static int rs780_set_engine_clock_scaling(struct radeon_device *rdev)
 	return 0;
 }
 
-static void rs780_set_engine_clock_spc(struct radeon_device *rdev)
+static void rs780_set_engine_clock_spc(struct radeon_device *rdev,
+				       struct radeon_ps *new_ps,
+				       struct radeon_ps *old_ps)
 {
-	struct igp_ps *new_state = rs780_get_ps(rdev->pm.dpm.requested_ps);
-	struct igp_ps *old_state = rs780_get_ps(rdev->pm.dpm.current_ps);
+	struct igp_ps *new_state = rs780_get_ps(new_ps);
+	struct igp_ps *old_state = rs780_get_ps(old_ps);
 	struct igp_power_info *pi = rs780_get_pi(rdev);
 
 	if ((new_state->sclk_high == old_state->sclk_high) &&
@@ -468,10 +474,12 @@ static void rs780_set_engine_clock_spc(struct radeon_device *rdev)
 
 }
 
-static void rs780_activate_engine_clk_scaling(struct radeon_device *rdev)
+static void rs780_activate_engine_clk_scaling(struct radeon_device *rdev,
+					      struct radeon_ps *new_ps,
+					      struct radeon_ps *old_ps)
 {
-	struct igp_ps *new_state = rs780_get_ps(rdev->pm.dpm.requested_ps);
-	struct igp_ps *old_state = rs780_get_ps(rdev->pm.dpm.current_ps);
+	struct igp_ps *new_state = rs780_get_ps(new_ps);
+	struct igp_ps *old_state = rs780_get_ps(old_ps);
 
 	if ((new_state->sclk_high == old_state->sclk_high) &&
 	    (new_state->sclk_low == old_state->sclk_low))
@@ -493,9 +501,10 @@ static u32 rs780_get_voltage_for_vddc_level(struct radeon_device *rdev,
 		return pi->max_voltage;
 }
 
-static void rs780_enable_voltage_scaling(struct radeon_device *rdev)
+static void rs780_enable_voltage_scaling(struct radeon_device *rdev,
+					 struct radeon_ps *new_ps)
 {
-	struct igp_ps *new_state = rs780_get_ps(rdev->pm.dpm.requested_ps);
+	struct igp_ps *new_state = rs780_get_ps(new_ps);
 	struct igp_power_info *pi = rs780_get_pi(rdev);
 	enum rs780_vddc_level vddc_high, vddc_low;
 
@@ -536,13 +545,14 @@ static void rs780_enable_voltage_scaling(struct radeon_device *rdev)
 int rs780_dpm_enable(struct radeon_device *rdev)
 {
 	struct igp_power_info *pi = rs780_get_pi(rdev);
+	struct radeon_ps *boot_ps = rdev->pm.dpm.boot_ps;
 
 	rs780_get_pm_mode_parameters(rdev);
 	rs780_disable_vbios_powersaving(rdev);
 
 	if (r600_dynamicpm_enabled(rdev))
 		return -EINVAL;
-	if (rs780_initialize_dpm_parameters(rdev))
+	if (rs780_initialize_dpm_parameters(rdev, boot_ps))
 		return -EINVAL;
 	rs780_start_dpm(rdev);
 
@@ -591,6 +601,8 @@ void rs780_dpm_disable(struct radeon_device *rdev)
 int rs780_dpm_set_power_state(struct radeon_device *rdev)
 {
 	struct igp_power_info *pi = rs780_get_pi(rdev);
+	struct radeon_ps *new_ps = rdev->pm.dpm.requested_ps;
+	struct radeon_ps *old_ps = rdev->pm.dpm.current_ps;
 
 	rs780_get_pm_mode_parameters(rdev);
 
@@ -599,13 +611,13 @@ int rs780_dpm_set_power_state(struct radeon_device *rdev)
 		mdelay(5);
 	}
 
-	rs780_set_engine_clock_scaling(rdev);
-	rs780_set_engine_clock_spc(rdev);
+	rs780_set_engine_clock_scaling(rdev, new_ps, old_ps);
+	rs780_set_engine_clock_spc(rdev, new_ps, old_ps);
 
-	rs780_activate_engine_clk_scaling(rdev);
+	rs780_activate_engine_clk_scaling(rdev, new_ps, old_ps);
 
 	if (pi->voltage_control)
-		rs780_enable_voltage_scaling(rdev);
+		rs780_enable_voltage_scaling(rdev, new_ps);
 
 	return 0;
 }
Signature · 1 line
1.7.7.5
#111 lore raw

PATCH 96/165 drm/radeon/dpm/rv6xx: restructure code

In reply to [email protected]

From: Alex Deucher <[email protected]>

Needed to properly handle dynamic state adjustment.

---
 drivers/gpu/drm/radeon/rv6xx_dpm.c |  115 +++++++++++++++++++++--------------
 1 files changed, 69 insertions(+), 46 deletions(-)
drivers/gpu/drm/radeon/rv6xx_dpm.c +69 -46
index fa4beb2..e8f07b1 100644
@@ -961,9 +961,11 @@ static void rv6xx_program_voltage_gpio_pins(struct radeon_device *rdev)
 					 rv6xx_get_master_voltage_mask(rdev));
 }
 
-static void rv6xx_enable_static_voltage_control(struct radeon_device *rdev, bool enable)
+static void rv6xx_enable_static_voltage_control(struct radeon_device *rdev,
+						struct radeon_ps *new_ps,
+						bool enable)
 {
-	struct rv6xx_ps *new_state = rv6xx_get_ps(rdev->pm.dpm.requested_ps);
+	struct rv6xx_ps *new_state = rv6xx_get_ps(new_ps);
 
 	if (enable)
 		radeon_atom_set_voltage(rdev,
@@ -1039,9 +1041,10 @@ static void rv6xx_calculate_ap(struct radeon_device *rdev,
 
 }
 
-static void rv6xx_calculate_stepping_parameters(struct radeon_device *rdev)
+static void rv6xx_calculate_stepping_parameters(struct radeon_device *rdev,
+						struct radeon_ps *new_ps)
 {
-	struct rv6xx_ps *new_state = rv6xx_get_ps(rdev->pm.dpm.requested_ps);
+	struct rv6xx_ps *new_state = rv6xx_get_ps(new_ps);
 
 	rv6xx_calculate_engine_speed_stepping_parameters(rdev, new_state);
 	rv6xx_calculate_memory_clock_stepping_parameters(rdev, new_state);
@@ -1191,10 +1194,12 @@ static void rv6xx_program_display_gap(struct radeon_device *rdev)
 	WREG32(CG_DISPLAY_GAP_CNTL, tmp);
 }
 
-static void rv6xx_set_sw_voltage_to_safe(struct radeon_device *rdev)
+static void rv6xx_set_sw_voltage_to_safe(struct radeon_device *rdev,
+					 struct radeon_ps *new_ps,
+					 struct radeon_ps *old_ps)
 {
-	struct rv6xx_ps *new_state = rv6xx_get_ps(rdev->pm.dpm.requested_ps);
-	struct rv6xx_ps *old_state = rv6xx_get_ps(rdev->pm.dpm.current_ps);
+	struct rv6xx_ps *new_state = rv6xx_get_ps(new_ps);
+	struct rv6xx_ps *old_state = rv6xx_get_ps(old_ps);
 	u16 safe_voltage;
 
 	safe_voltage = (new_state->low.vddc >= old_state->low.vddc) ?
@@ -1207,9 +1212,10 @@ static void rv6xx_set_sw_voltage_to_safe(struct radeon_device *rdev)
 		 ~SW_GPIO_INDEX_MASK);
 }
 
-static void rv6xx_set_sw_voltage_to_low(struct radeon_device *rdev)
+static void rv6xx_set_sw_voltage_to_low(struct radeon_device *rdev,
+					struct radeon_ps *old_ps)
 {
-	struct rv6xx_ps *old_state = rv6xx_get_ps(rdev->pm.dpm.current_ps);
+	struct rv6xx_ps *old_state = rv6xx_get_ps(old_ps);
 
 	rv6xx_program_voltage_stepping_entry(rdev, R600_POWER_LEVEL_CTXSW,
 					     old_state->low.vddc);
@@ -1218,10 +1224,12 @@ static void rv6xx_set_sw_voltage_to_low(struct radeon_device *rdev)
 		~SW_GPIO_INDEX_MASK);
 }
 
-static void rv6xx_set_safe_backbias(struct radeon_device *rdev)
+static void rv6xx_set_safe_backbias(struct radeon_device *rdev,
+				    struct radeon_ps *new_ps,
+				    struct radeon_ps *old_ps)
 {
-	struct rv6xx_ps *new_state = rv6xx_get_ps(rdev->pm.dpm.requested_ps);
-	struct rv6xx_ps *old_state = rv6xx_get_ps(rdev->pm.dpm.current_ps);
+	struct rv6xx_ps *new_state = rv6xx_get_ps(new_ps);
+	struct rv6xx_ps *old_state = rv6xx_get_ps(old_ps);
 
 	if ((new_state->low.flags & ATOM_PPLIB_R600_FLAGS_BACKBIASENABLE) &&
 	    (old_state->low.flags & ATOM_PPLIB_R600_FLAGS_BACKBIASENABLE))
@@ -1230,10 +1238,12 @@ static void rv6xx_set_safe_backbias(struct radeon_device *rdev)
 		WREG32_P(GENERAL_PWRMGT, 0, ~BACKBIAS_VALUE);
 }
 
-static void rv6xx_set_safe_pcie_gen2(struct radeon_device *rdev)
+static void rv6xx_set_safe_pcie_gen2(struct radeon_device *rdev,
+				     struct radeon_ps *new_ps,
+				     struct radeon_ps *old_ps)
 {
-	struct rv6xx_ps *new_state = rv6xx_get_ps(rdev->pm.dpm.requested_ps);
-	struct rv6xx_ps *old_state = rv6xx_get_ps(rdev->pm.dpm.current_ps);
+	struct rv6xx_ps *new_state = rv6xx_get_ps(new_ps);
+	struct rv6xx_ps *old_state = rv6xx_get_ps(old_ps);
 
 	if ((new_state->low.flags & ATOM_PPLIB_R600_FLAGS_PCIEGEN2) !=
 	    (old_state->low.flags & ATOM_PPLIB_R600_FLAGS_PCIEGEN2))
@@ -1290,10 +1300,12 @@ static int rv6xx_step_sw_voltage(struct radeon_device *rdev,
 	return 0;
 }
 
-static int rv6xx_step_voltage_if_increasing(struct radeon_device *rdev)
+static int rv6xx_step_voltage_if_increasing(struct radeon_device *rdev,
+					    struct radeon_ps *new_ps,
+					    struct radeon_ps *old_ps)
 {
-	struct rv6xx_ps *new_state = rv6xx_get_ps(rdev->pm.dpm.requested_ps);
-	struct rv6xx_ps *old_state = rv6xx_get_ps(rdev->pm.dpm.current_ps);
+	struct rv6xx_ps *new_state = rv6xx_get_ps(new_ps);
+	struct rv6xx_ps *old_state = rv6xx_get_ps(old_ps);
 
 	if (new_state->low.vddc > old_state->low.vddc)
 		return rv6xx_step_sw_voltage(rdev,
@@ -1303,10 +1315,12 @@ static int rv6xx_step_voltage_if_increasing(struct radeon_device *rdev)
 	return 0;
 }
 
-static int rv6xx_step_voltage_if_decreasing(struct radeon_device *rdev)
+static int rv6xx_step_voltage_if_decreasing(struct radeon_device *rdev,
+					    struct radeon_ps *new_ps,
+					    struct radeon_ps *old_ps)
 {
-	struct rv6xx_ps *new_state = rv6xx_get_ps(rdev->pm.dpm.requested_ps);
-	struct rv6xx_ps *old_state = rv6xx_get_ps(rdev->pm.dpm.current_ps);
+	struct rv6xx_ps *new_state = rv6xx_get_ps(new_ps);
+	struct rv6xx_ps *old_state = rv6xx_get_ps(old_ps);
 
 	if (new_state->low.vddc < old_state->low.vddc)
 		return rv6xx_step_sw_voltage(rdev,
@@ -1399,10 +1413,12 @@ static void rv6xx_enable_thermal_protection(struct radeon_device *rdev,
 		r600_enable_thermal_protection(rdev, enable);
 }
 
-static void rv6xx_generate_transition_stepping(struct radeon_device *rdev)
+static void rv6xx_generate_transition_stepping(struct radeon_device *rdev,
+					       struct radeon_ps *new_ps,
+					       struct radeon_ps *old_ps)
 {
-	struct rv6xx_ps *new_state = rv6xx_get_ps(rdev->pm.dpm.requested_ps);
-	struct rv6xx_ps *old_state = rv6xx_get_ps(rdev->pm.dpm.current_ps);
+	struct rv6xx_ps *new_state = rv6xx_get_ps(new_ps);
+	struct rv6xx_ps *old_state = rv6xx_get_ps(old_ps);
 	struct rv6xx_power_info *pi = rv6xx_get_pi(rdev);
 
 	rv6xx_generate_steps(rdev,
@@ -1411,9 +1427,10 @@ static void rv6xx_generate_transition_stepping(struct radeon_device *rdev)
 			     0, &pi->hw.medium_sclk_index);
 }
 
-static void rv6xx_generate_low_step(struct radeon_device *rdev)
+static void rv6xx_generate_low_step(struct radeon_device *rdev,
+				    struct radeon_ps *new_ps)
 {
-	struct rv6xx_ps *new_state = rv6xx_get_ps(rdev->pm.dpm.requested_ps);
+	struct rv6xx_ps *new_state = rv6xx_get_ps(new_ps);
 	struct rv6xx_power_info *pi = rv6xx_get_pi(rdev);
 
 	pi->hw.low_sclk_index = 0;
@@ -1430,9 +1447,10 @@ static void rv6xx_invalidate_intermediate_steps(struct radeon_device *rdev)
 						  pi->hw.medium_sclk_index);
 }
 
-static void rv6xx_generate_stepping_table(struct radeon_device *rdev)
+static void rv6xx_generate_stepping_table(struct radeon_device *rdev,
+					  struct radeon_ps *new_ps)
 {
-	struct rv6xx_ps *new_state = rv6xx_get_ps(rdev->pm.dpm.requested_ps);
+	struct rv6xx_ps *new_state = rv6xx_get_ps(new_ps);
 	struct rv6xx_power_info *pi = rv6xx_get_pi(rdev);
 
 	pi->hw.low_sclk_index = 0;
@@ -1472,9 +1490,10 @@ static void rv6xx_reset_lvtm_data_sync(struct radeon_device *rdev)
 }
 
 static void rv6xx_enable_dynamic_pcie_gen2(struct radeon_device *rdev,
+					   struct radeon_ps *new_ps,
 					   bool enable)
 {
-	struct rv6xx_ps *new_state = rv6xx_get_ps(rdev->pm.dpm.requested_ps);
+	struct rv6xx_ps *new_state = rv6xx_get_ps(new_ps);
 
 	if (enable) {
 		rv6xx_enable_bif_dynamic_pcie_gen2(rdev, true);
@@ -1491,6 +1510,7 @@ static void rv6xx_enable_dynamic_pcie_gen2(struct radeon_device *rdev,
 int rv6xx_dpm_enable(struct radeon_device *rdev)
 {
 	struct rv6xx_power_info *pi = rv6xx_get_pi(rdev);
+	struct radeon_ps *boot_ps = rdev->pm.dpm.boot_ps;
 
 	if (r600_dynamicpm_enabled(rdev))
 		return -EINVAL;
@@ -1518,12 +1538,12 @@ int rv6xx_dpm_enable(struct radeon_device *rdev)
 
 	rv6xx_program_power_level_enter_state(rdev);
 
-	rv6xx_calculate_stepping_parameters(rdev);
+	rv6xx_calculate_stepping_parameters(rdev, boot_ps);
 
 	if (pi->voltage_control)
 		rv6xx_program_voltage_gpio_pins(rdev);
 
-	rv6xx_generate_stepping_table(rdev);
+	rv6xx_generate_stepping_table(rdev, boot_ps);
 
 	rv6xx_program_stepping_parameters_except_lowest_entry(rdev);
 	rv6xx_program_stepping_parameters_lowest_entry(rdev);
@@ -1550,10 +1570,10 @@ int rv6xx_dpm_enable(struct radeon_device *rdev)
 	r600_start_dpm(rdev);
 
 	if (pi->voltage_control)
-		rv6xx_enable_static_voltage_control(rdev, false);
+		rv6xx_enable_static_voltage_control(rdev, boot_ps, false);
 
 	if (pi->dynamic_pcie_gen2)
-		rv6xx_enable_dynamic_pcie_gen2(rdev, true);
+		rv6xx_enable_dynamic_pcie_gen2(rdev, boot_ps, true);
 
 	if (pi->gfx_clock_gating)
 		r600_gfx_clockgating_enable(rdev, true);
@@ -1564,6 +1584,7 @@ int rv6xx_dpm_enable(struct radeon_device *rdev)
 void rv6xx_dpm_disable(struct radeon_device *rdev)
 {
 	struct rv6xx_power_info *pi = rv6xx_get_pi(rdev);
+	struct radeon_ps *boot_ps = rdev->pm.dpm.boot_ps;
 
 	if (!r600_dynamicpm_enabled(rdev))
 		return;
@@ -1587,10 +1608,10 @@ void rv6xx_dpm_disable(struct radeon_device *rdev)
 	rv6xx_enable_spread_spectrum(rdev, false);
 
 	if (pi->voltage_control)
-		rv6xx_enable_static_voltage_control(rdev, true);
+		rv6xx_enable_static_voltage_control(rdev, boot_ps, true);
 
 	if (pi->dynamic_pcie_gen2)
-		rv6xx_enable_dynamic_pcie_gen2(rdev, false);
+		rv6xx_enable_dynamic_pcie_gen2(rdev, boot_ps, false);
 
 	if (rdev->irq.installed &&
 	    r600_is_internal_thermal_sensor(rdev->pm.int_thermal_type)) {
@@ -1607,6 +1628,8 @@ void rv6xx_dpm_disable(struct radeon_device *rdev)
 int rv6xx_dpm_set_power_state(struct radeon_device *rdev)
 {
 	struct rv6xx_power_info *pi = rv6xx_get_pi(rdev);
+	struct radeon_ps *new_ps = rdev->pm.dpm.requested_ps;
+	struct radeon_ps *old_ps = rdev->pm.dpm.current_ps;
 
 	rv6xx_clear_vc(rdev);
 	r600_power_level_enable(rdev, R600_POWER_LEVEL_LOW, true);
@@ -1619,20 +1642,20 @@ int rv6xx_dpm_set_power_state(struct radeon_device *rdev)
 	r600_power_level_enable(rdev, R600_POWER_LEVEL_HIGH, false);
 	r600_power_level_enable(rdev, R600_POWER_LEVEL_MEDIUM, false);
 
-	rv6xx_generate_transition_stepping(rdev);
+	rv6xx_generate_transition_stepping(rdev, new_ps, old_ps);
 	rv6xx_program_power_level_medium_for_transition(rdev);
 
 	if (pi->voltage_control) {
-		rv6xx_set_sw_voltage_to_safe(rdev);
+		rv6xx_set_sw_voltage_to_safe(rdev, new_ps, old_ps);
 		if (rdev->pm.dpm.platform_caps & ATOM_PP_PLATFORM_CAP_STEPVDDC)
-			rv6xx_set_sw_voltage_to_low(rdev);
+			rv6xx_set_sw_voltage_to_low(rdev, old_ps);
 	}
 
 	if (rdev->pm.dpm.platform_caps & ATOM_PP_PLATFORM_CAP_BACKBIAS)
-		rv6xx_set_safe_backbias(rdev);
+		rv6xx_set_safe_backbias(rdev, new_ps, old_ps);
 
 	if (pi->dynamic_pcie_gen2)
-		rv6xx_set_safe_pcie_gen2(rdev);
+		rv6xx_set_safe_pcie_gen2(rdev, new_ps, old_ps);
 
 	if (pi->voltage_control)
 		rv6xx_enable_dynamic_voltage_control(rdev, false);
@@ -1642,7 +1665,7 @@ int rv6xx_dpm_set_power_state(struct radeon_device *rdev)
 
 	if (pi->voltage_control) {
 		if (rdev->pm.dpm.platform_caps & ATOM_PP_PLATFORM_CAP_STEPVDDC)
-			rv6xx_step_voltage_if_increasing(rdev);
+			rv6xx_step_voltage_if_increasing(rdev, new_ps, old_ps);
 		msleep((rdev->pm.dpm.voltage_response_time + 999) / 1000);
 	}
 
@@ -1650,9 +1673,9 @@ int rv6xx_dpm_set_power_state(struct radeon_device *rdev)
 	r600_power_level_enable(rdev, R600_POWER_LEVEL_LOW, false);
 	r600_wait_for_power_level_unequal(rdev, R600_POWER_LEVEL_LOW);
 
-	rv6xx_generate_low_step(rdev);
+	rv6xx_generate_low_step(rdev, new_ps);
 	rv6xx_invalidate_intermediate_steps(rdev);
-	rv6xx_calculate_stepping_parameters(rdev);
+	rv6xx_calculate_stepping_parameters(rdev, new_ps);
 	rv6xx_program_stepping_parameters_lowest_entry(rdev);
 	rv6xx_program_power_level_low_to_lowest_state(rdev);
 
@@ -1662,7 +1685,7 @@ int rv6xx_dpm_set_power_state(struct radeon_device *rdev)
 
 	if (pi->voltage_control) {
 		if (rdev->pm.dpm.platform_caps & ATOM_PP_PLATFORM_CAP_STEPVDDC)
-			rv6xx_step_voltage_if_decreasing(rdev);
+			rv6xx_step_voltage_if_decreasing(rdev, new_ps, old_ps);
 		rv6xx_enable_dynamic_voltage_control(rdev, true);
 	}
 
@@ -1670,11 +1693,11 @@ int rv6xx_dpm_set_power_state(struct radeon_device *rdev)
 		rv6xx_enable_dynamic_backbias_control(rdev, true);
 
 	if (pi->dynamic_pcie_gen2)
-		rv6xx_enable_dynamic_pcie_gen2(rdev, true);
+		rv6xx_enable_dynamic_pcie_gen2(rdev, new_ps, true);
 
 	rv6xx_reset_lvtm_data_sync(rdev);
 
-	rv6xx_generate_stepping_table(rdev);
+	rv6xx_generate_stepping_table(rdev, new_ps);
 	rv6xx_program_stepping_parameters_except_lowest_entry(rdev);
 	rv6xx_program_power_level_low(rdev);
 	rv6xx_program_power_level_medium(rdev);
Signature · 1 line
1.7.7.5
#112 lore raw

PATCH 97/165 drm/radeon/dpm/rv7xx: restructure code

In reply to [email protected]

From: Alex Deucher <[email protected]>

Needed to properly handle dynamic state adjustment.

---
 drivers/gpu/drm/radeon/btc_dpm.c     |    6 ++-
 drivers/gpu/drm/radeon/cypress_dpm.c |    6 ++-
 drivers/gpu/drm/radeon/rv740_dpm.c   |    1 -
 drivers/gpu/drm/radeon/rv770_dpm.c   |   77 ++++++++++++++++++----------------
 drivers/gpu/drm/radeon/rv770_dpm.h   |    8 +++-
 5 files changed, 55 insertions(+), 43 deletions(-)
drivers/gpu/drm/radeon/btc_dpm.c +4 -2
index 79f5ed4..3ae4de6 100644
@@ -2233,6 +2233,8 @@ void btc_dpm_reset_asic(struct radeon_device *rdev)
 int btc_dpm_set_power_state(struct radeon_device *rdev)
 {
 	struct evergreen_power_info *eg_pi = evergreen_get_pi(rdev);
+	struct radeon_ps *new_ps = rdev->pm.dpm.requested_ps;
+	struct radeon_ps *old_ps = rdev->pm.dpm.current_ps;
 
 	btc_apply_state_adjust_rules(rdev);
 
@@ -2243,7 +2245,7 @@ int btc_dpm_set_power_state(struct radeon_device *rdev)
 	if (eg_pi->pcie_performance_request)
 		cypress_notify_link_speed_change_before_state_change(rdev);
 
-	rv770_set_uvd_clock_before_set_eng_clock(rdev);
+	rv770_set_uvd_clock_before_set_eng_clock(rdev, new_ps, old_ps);
 	rv770_halt_smc(rdev);
 	btc_set_at_for_uvd(rdev);
 	if (eg_pi->smu_uvd_hs)
@@ -2257,7 +2259,7 @@ int btc_dpm_set_power_state(struct radeon_device *rdev)
 
 	rv770_resume_smc(rdev);
 	rv770_set_sw_state(rdev);
-	rv770_set_uvd_clock_after_set_eng_clock(rdev);
+	rv770_set_uvd_clock_after_set_eng_clock(rdev, new_ps, old_ps);
 
 	if (eg_pi->pcie_performance_request)
 		cypress_notify_link_speed_change_after_state_change(rdev);
drivers/gpu/drm/radeon/cypress_dpm.c +4 -2
index 22297b1..c9026ed 100644
@@ -1930,13 +1930,15 @@ void cypress_dpm_disable(struct radeon_device *rdev)
 int cypress_dpm_set_power_state(struct radeon_device *rdev)
 {
 	struct evergreen_power_info *eg_pi = evergreen_get_pi(rdev);
+	struct radeon_ps *new_ps = rdev->pm.dpm.requested_ps;
+	struct radeon_ps *old_ps = rdev->pm.dpm.current_ps;
 
 	rv770_restrict_performance_levels_before_switch(rdev);
 
 	if (eg_pi->pcie_performance_request)
 		cypress_notify_link_speed_change_before_state_change(rdev);
 
-	rv770_set_uvd_clock_before_set_eng_clock(rdev);
+	rv770_set_uvd_clock_before_set_eng_clock(rdev, new_ps, old_ps);
 	rv770_halt_smc(rdev);
 	cypress_upload_sw_state(rdev);
 
@@ -1947,7 +1949,7 @@ int cypress_dpm_set_power_state(struct radeon_device *rdev)
 
 	rv770_resume_smc(rdev);
 	rv770_set_sw_state(rdev);
-	rv770_set_uvd_clock_after_set_eng_clock(rdev);
+	rv770_set_uvd_clock_after_set_eng_clock(rdev, new_ps, old_ps);
 
 	if (eg_pi->pcie_performance_request)
 		cypress_notify_link_speed_change_after_state_change(rdev);
drivers/gpu/drm/radeon/rv740_dpm.c +0 -1
index d0d750e..7aa1608 100644
@@ -29,7 +29,6 @@
 #include "rv770_dpm.h"
 #include "atom.h"
 
-struct rv7xx_ps *rv770_get_ps(struct radeon_ps *rps);
 struct rv7xx_power_info *rv770_get_pi(struct radeon_device *rdev);
 
 u32 rv740_get_decoded_reference_divider(u32 encoded_ref)
drivers/gpu/drm/radeon/rv770_dpm.c +41 -36

174 lines not on this page · raw message

drivers/gpu/drm/radeon/rv770_dpm.h +6 -2
index dfb133f..22586df 100644
@@ -266,8 +266,12 @@ int rv770_resume_smc(struct radeon_device *rdev);
 int rv770_set_sw_state(struct radeon_device *rdev);
 int rv770_set_boot_state(struct radeon_device *rdev);
 int rv7xx_parse_power_table(struct radeon_device *rdev);
-void rv770_set_uvd_clock_before_set_eng_clock(struct radeon_device *rdev);
-void rv770_set_uvd_clock_after_set_eng_clock(struct radeon_device *rdev);
+void rv770_set_uvd_clock_before_set_eng_clock(struct radeon_device *rdev,
+					      struct radeon_ps *new_ps,
+					      struct radeon_ps *old_ps);
+void rv770_set_uvd_clock_after_set_eng_clock(struct radeon_device *rdev,
+					     struct radeon_ps *new_ps,
+					     struct radeon_ps *old_ps);
 
 /* smc */
 int rv770_read_smc_soft_register(struct radeon_device *rdev,
Signature · 1 line
1.7.7.5
#113 lore raw

PATCH 98/165 drm/radeon/dpm/evergreen: restructure code

In reply to [email protected]

From: Alex Deucher <[email protected]>

Needed to properly handle dynamic state adjustment.

---
 drivers/gpu/drm/radeon/btc_dpm.c     |   13 ++++---
 drivers/gpu/drm/radeon/cypress_dpm.c |   62 +++++++++++++++++----------------
 drivers/gpu/drm/radeon/cypress_dpm.h |   20 ++++++++---
 3 files changed, 53 insertions(+), 42 deletions(-)
drivers/gpu/drm/radeon/btc_dpm.c +7 -6
index 3ae4de6..73a0ba3 100644
@@ -2243,26 +2243,26 @@ int btc_dpm_set_power_state(struct radeon_device *rdev)
 	rv770_restrict_performance_levels_before_switch(rdev);
 
 	if (eg_pi->pcie_performance_request)
-		cypress_notify_link_speed_change_before_state_change(rdev);
+		cypress_notify_link_speed_change_before_state_change(rdev, new_ps, old_ps);
 
 	rv770_set_uvd_clock_before_set_eng_clock(rdev, new_ps, old_ps);
 	rv770_halt_smc(rdev);
 	btc_set_at_for_uvd(rdev);
 	if (eg_pi->smu_uvd_hs)
 		btc_notify_uvd_to_smc(rdev);
-	cypress_upload_sw_state(rdev);
+	cypress_upload_sw_state(rdev, new_ps);
 
 	if (eg_pi->dynamic_ac_timing)
-		cypress_upload_mc_reg_table(rdev);
+		cypress_upload_mc_reg_table(rdev, new_ps);
 
-	cypress_program_memory_timing_parameters(rdev);
+	cypress_program_memory_timing_parameters(rdev, new_ps);
 
 	rv770_resume_smc(rdev);
 	rv770_set_sw_state(rdev);
 	rv770_set_uvd_clock_after_set_eng_clock(rdev, new_ps, old_ps);
 
 	if (eg_pi->pcie_performance_request)
-		cypress_notify_link_speed_change_after_state_change(rdev);
+		cypress_notify_link_speed_change_after_state_change(rdev, new_ps, old_ps);
 
 	btc_set_power_state_conditionally_enable_ulv(rdev);
 
@@ -2273,6 +2273,7 @@ int btc_dpm_enable(struct radeon_device *rdev)
 {
 	struct rv7xx_power_info *pi = rv770_get_pi(rdev);
 	struct evergreen_power_info *eg_pi = evergreen_get_pi(rdev);
+	struct radeon_ps *boot_ps = rdev->pm.dpm.boot_ps;
 
 	if (pi->gfx_clock_gating)
 		btc_cg_clock_gating_default(rdev);
@@ -2325,7 +2326,7 @@ int btc_dpm_enable(struct radeon_device *rdev)
 	btc_init_smc_table(rdev);
 
 	if (eg_pi->dynamic_ac_timing)
-		cypress_populate_mc_reg_table(rdev);
+		cypress_populate_mc_reg_table(rdev, boot_ps);
 
 	cypress_program_response_times(rdev);
 	r7xx_start_smc(rdev);
drivers/gpu/drm/radeon/cypress_dpm.c +32 -30

183 lines not on this page · raw message

drivers/gpu/drm/radeon/cypress_dpm.h +14 -6
index 9b6198e..5b19364 100644
@@ -120,18 +120,26 @@ int cypress_populate_smc_initial_state(struct radeon_device *rdev,
 				       RV770_SMC_STATETABLE *table);
 u32 cypress_calculate_burst_time(struct radeon_device *rdev,
 				 u32 engine_clock, u32 memory_clock);
-void cypress_notify_link_speed_change_before_state_change(struct radeon_device *rdev);
-int cypress_upload_sw_state(struct radeon_device *rdev);
-int cypress_upload_mc_reg_table(struct radeon_device *rdev);
-void cypress_program_memory_timing_parameters(struct radeon_device *rdev);
-void cypress_notify_link_speed_change_after_state_change(struct radeon_device *rdev);
+void cypress_notify_link_speed_change_before_state_change(struct radeon_device *rdev,
+							  struct radeon_ps *radeon_new_state,
+							  struct radeon_ps *radeon_current_state);
+int cypress_upload_sw_state(struct radeon_device *rdev,
+			    struct radeon_ps *radeon_new_state);
+int cypress_upload_mc_reg_table(struct radeon_device *rdev,
+				struct radeon_ps *radeon_new_state);
+void cypress_program_memory_timing_parameters(struct radeon_device *rdev,
+					      struct radeon_ps *radeon_new_state);
+void cypress_notify_link_speed_change_after_state_change(struct radeon_device *rdev,
+							 struct radeon_ps *radeon_new_state,
+							 struct radeon_ps *radeon_current_state);
 int cypress_construct_voltage_tables(struct radeon_device *rdev);
 int cypress_get_mvdd_configuration(struct radeon_device *rdev);
 void cypress_enable_spread_spectrum(struct radeon_device *rdev,
 				    bool enable);
 void cypress_enable_display_gap(struct radeon_device *rdev);
 int cypress_get_table_locations(struct radeon_device *rdev);
-int cypress_populate_mc_reg_table(struct radeon_device *rdev);
+int cypress_populate_mc_reg_table(struct radeon_device *rdev,
+				  struct radeon_ps *radeon_boot_state);
 void cypress_program_response_times(struct radeon_device *rdev);
 int cypress_notify_smc_display_change(struct radeon_device *rdev,
 				      bool has_display);
Signature · 1 line
1.7.7.5
#114 lore raw

PATCH 99/165 drm/radeon/dpm/btc: restructure code

In reply to [email protected]

From: Alex Deucher <[email protected]>

Needed to properly handle dynamic state adjustment.

---
 drivers/gpu/drm/radeon/btc_dpm.c |   30 +++++++++++++++---------------
 drivers/gpu/drm/radeon/btc_dpm.h |    3 ++-
 drivers/gpu/drm/radeon/ni_dpm.c  |    3 ++-
 3 files changed, 19 insertions(+), 17 deletions(-)
drivers/gpu/drm/radeon/btc_dpm.c +15 -15
index 73a0ba3..30aed00 100644
@@ -1604,11 +1604,11 @@ bool btc_dpm_enabled(struct radeon_device *rdev)
 		return false;
 }
 
-static int btc_init_smc_table(struct radeon_device *rdev)
+static int btc_init_smc_table(struct radeon_device *rdev,
+			      struct radeon_ps *radeon_boot_state)
 {
 	struct rv7xx_power_info *pi = rv770_get_pi(rdev);
 	struct evergreen_power_info *eg_pi = evergreen_get_pi(rdev);
-	struct radeon_ps *radeon_boot_state = rdev->pm.dpm.boot_ps;
 	RV770_SMC_STATETABLE *table = &pi->smc_statetable;
 	int ret;
 
@@ -1668,11 +1668,11 @@ static int btc_init_smc_table(struct radeon_device *rdev)
 				       pi->sram_end);
 }
 
-static void btc_set_at_for_uvd(struct radeon_device *rdev)
+static void btc_set_at_for_uvd(struct radeon_device *rdev,
+			       struct radeon_ps *radeon_new_state)
 {
 	struct rv7xx_power_info *pi = rv770_get_pi(rdev);
 	struct evergreen_power_info *eg_pi = evergreen_get_pi(rdev);
-	struct radeon_ps *radeon_new_state = rdev->pm.dpm.requested_ps;
 	int idx = 0;
 
 	if (r600_is_uvd_state(radeon_new_state->class, radeon_new_state->class2))
@@ -1692,9 +1692,9 @@ static void btc_set_at_for_uvd(struct radeon_device *rdev)
 
 }
 
-void btc_notify_uvd_to_smc(struct radeon_device *rdev)
+void btc_notify_uvd_to_smc(struct radeon_device *rdev,
+			   struct radeon_ps *radeon_new_state)
 {
-	struct radeon_ps *radeon_new_state = rdev->pm.dpm.requested_ps;
 	struct evergreen_power_info *eg_pi = evergreen_get_pi(rdev);
 
 	if (r600_is_uvd_state(radeon_new_state->class, radeon_new_state->class2)) {
@@ -1814,11 +1814,11 @@ static int btc_enable_ulv(struct radeon_device *rdev)
 	return 0;
 }
 
-static int btc_set_power_state_conditionally_enable_ulv(struct radeon_device *rdev)
+static int btc_set_power_state_conditionally_enable_ulv(struct radeon_device *rdev,
+							struct radeon_ps *radeon_new_state)
 {
 	int ret = 0;
 	struct evergreen_power_info *eg_pi = evergreen_get_pi(rdev);
-	struct radeon_ps *radeon_new_state = rdev->pm.dpm.requested_ps;
 
 	if (eg_pi->ulv.supported) {
 		if (btc_is_state_ulv_compatible(rdev, radeon_new_state)) {
@@ -2059,10 +2059,10 @@ static void btc_init_stutter_mode(struct radeon_device *rdev)
 	}
 }
 
-static void btc_apply_state_adjust_rules(struct radeon_device *rdev)
+static void btc_apply_state_adjust_rules(struct radeon_device *rdev,
+					 struct radeon_ps *rps)
 {
 	struct evergreen_power_info *eg_pi = evergreen_get_pi(rdev);
-	struct radeon_ps *rps = rdev->pm.dpm.requested_ps;
 	struct rv7xx_ps *ps = rv770_get_ps(rps);
 	struct radeon_clock_and_voltage_limits *max_limits;
 	bool disable_mclk_switching;
@@ -2236,7 +2236,7 @@ int btc_dpm_set_power_state(struct radeon_device *rdev)
 	struct radeon_ps *new_ps = rdev->pm.dpm.requested_ps;
 	struct radeon_ps *old_ps = rdev->pm.dpm.current_ps;
 
-	btc_apply_state_adjust_rules(rdev);
+	btc_apply_state_adjust_rules(rdev, new_ps);
 
 	btc_disable_ulv(rdev);
 	btc_set_boot_state_timing(rdev);
@@ -2247,9 +2247,9 @@ int btc_dpm_set_power_state(struct radeon_device *rdev)
 
 	rv770_set_uvd_clock_before_set_eng_clock(rdev, new_ps, old_ps);
 	rv770_halt_smc(rdev);
-	btc_set_at_for_uvd(rdev);
+	btc_set_at_for_uvd(rdev, new_ps);
 	if (eg_pi->smu_uvd_hs)
-		btc_notify_uvd_to_smc(rdev);
+		btc_notify_uvd_to_smc(rdev, new_ps);
 	cypress_upload_sw_state(rdev, new_ps);
 
 	if (eg_pi->dynamic_ac_timing)
@@ -2264,7 +2264,7 @@ int btc_dpm_set_power_state(struct radeon_device *rdev)
 	if (eg_pi->pcie_performance_request)
 		cypress_notify_link_speed_change_after_state_change(rdev, new_ps, old_ps);
 
-	btc_set_power_state_conditionally_enable_ulv(rdev);
+	btc_set_power_state_conditionally_enable_ulv(rdev, new_ps);
 
 	return 0;
 }
@@ -2323,7 +2323,7 @@ int btc_dpm_enable(struct radeon_device *rdev)
 		return -EINVAL;
 
 	cypress_get_table_locations(rdev);
-	btc_init_smc_table(rdev);
+	btc_init_smc_table(rdev, boot_ps);
 
 	if (eg_pi->dynamic_ac_timing)
 		cypress_populate_mc_reg_table(rdev, boot_ps);
drivers/gpu/drm/radeon/btc_dpm.h +2 -1
index c22d39f..1a15e0e 100644
@@ -51,6 +51,7 @@ void btc_apply_voltage_delta_rules(struct radeon_device *rdev,
 				   u16 *vddc, u16 *vddci);
 bool btc_dpm_enabled(struct radeon_device *rdev);
 int btc_reset_to_default(struct radeon_device *rdev);
-void btc_notify_uvd_to_smc(struct radeon_device *rdev);
+void btc_notify_uvd_to_smc(struct radeon_device *rdev,
+			   struct radeon_ps *radeon_new_state);
 
 #endif
drivers/gpu/drm/radeon/ni_dpm.c +2 -1
index 44016f2..9f68115 100644
@@ -3628,6 +3628,7 @@ int ni_power_control_set_level(struct radeon_device *rdev)
 int ni_dpm_set_power_state(struct radeon_device *rdev)
 {
 	struct evergreen_power_info *eg_pi = evergreen_get_pi(rdev);
+	struct radeon_ps *new_ps = rdev->pm.dpm.requested_ps;
 	int ret;
 
 	ni_apply_state_adjust_rules(rdev);
@@ -3637,7 +3638,7 @@ int ni_dpm_set_power_state(struct radeon_device *rdev)
 	ni_enable_smc_cac(rdev, false);
 	rv770_halt_smc(rdev);
 	if (eg_pi->smu_uvd_hs)
-		btc_notify_uvd_to_smc(rdev);
+		btc_notify_uvd_to_smc(rdev, new_ps);
 	ni_upload_sw_state(rdev);
 	if (eg_pi->dynamic_ac_timing)
 		ni_upload_mc_reg_table(rdev);
Signature · 1 line
1.7.7.5
#115 lore raw

PATCH 100/165 drm/radeon/dpm/cayman: restructure code

In reply to [email protected]

From: Alex Deucher <[email protected]>

Needed to properly handle dynamic state adjustment.

---
 drivers/gpu/drm/radeon/ni_dpm.c |   69 ++++++++++++++++++++------------------
 1 files changed, 36 insertions(+), 33 deletions(-)
drivers/gpu/drm/radeon/ni_dpm.c +36 -33
index 9f68115..ebc9837 100644
@@ -788,10 +788,10 @@ static void ni_calculate_leakage_for_v_and_t(struct radeon_device *rdev,
 	ni_calculate_leakage_for_v_and_t_formula(coeff, v, t, i_leakage, leakage);
 }
 
-static void ni_apply_state_adjust_rules(struct radeon_device *rdev)
+static void ni_apply_state_adjust_rules(struct radeon_device *rdev,
+					struct radeon_ps *rps)
 {
 	struct ni_power_info *ni_pi = ni_get_pi(rdev);
-	struct radeon_ps *rps = rdev->pm.dpm.requested_ps;
 	struct ni_ps *ps = ni_get_ps(rps);
 	struct radeon_clock_and_voltage_limits *max_limits;
 	bool disable_mclk_switching;
@@ -1434,13 +1434,13 @@ static int ni_calculate_adjusted_tdp_limits(struct radeon_device *rdev,
 	return 0;
 }
 
-static int ni_populate_smc_tdp_limits(struct radeon_device *rdev)
+static int ni_populate_smc_tdp_limits(struct radeon_device *rdev,
+				      struct radeon_ps *radeon_state)
 {
 	struct rv7xx_power_info *pi = rv770_get_pi(rdev);
 	struct ni_power_info *ni_pi = ni_get_pi(rdev);
 
 	if (ni_pi->enable_power_containment) {
-		struct radeon_ps *radeon_state = rdev->pm.dpm.requested_ps;
 		NISLANDS_SMC_STATETABLE *smc_table = &ni_pi->smc_statetable;
 		u32 scaling_factor = ni_get_smc_power_scaling_factor(rdev);
 		u32 tdp_limit;
@@ -1647,10 +1647,9 @@ static int ni_do_program_memory_timing_parameters(struct radeon_device *rdev,
 	return ret;
 }
 
-static int ni_program_memory_timing_parameters(struct radeon_device *rdev)
+static int ni_program_memory_timing_parameters(struct radeon_device *rdev,
+					       struct radeon_ps *radeon_new_state)
 {
-	struct radeon_ps *radeon_new_state = rdev->pm.dpm.requested_ps;
-
 	return ni_do_program_memory_timing_parameters(rdev, radeon_new_state,
 						      NISLANDS_DRIVER_STATE_ARB_INDEX);
 }
@@ -2576,7 +2575,9 @@ static int ni_populate_sq_ramping_values(struct radeon_device *rdev,
 	return 0;
 }
 
-static int ni_enable_power_containment(struct radeon_device *rdev, bool enable)
+static int ni_enable_power_containment(struct radeon_device *rdev,
+				       struct radeon_ps *radeon_new_state,
+				       bool enable)
 {
         struct ni_power_info *ni_pi = ni_get_pi(rdev);
 	PPSMC_Result smc_result;
@@ -2584,8 +2585,6 @@ static int ni_enable_power_containment(struct radeon_device *rdev, bool enable)
 
 	if (ni_pi->enable_power_containment) {
 		if (enable) {
-			struct radeon_ps *radeon_new_state = rdev->pm.dpm.requested_ps;
-
 			if (!r600_is_uvd_state(radeon_new_state->class, radeon_new_state->class2)) {
 				smc_result = rv770_send_msg_to_smc(rdev, PPSMC_TDPClampingActive);
 				if (smc_result != PPSMC_Result_OK) {
@@ -2665,10 +2664,10 @@ static int ni_convert_power_state_to_smc(struct radeon_device *rdev,
 	return ni_populate_smc_t(rdev, radeon_state, smc_state);
 }
 
-static int ni_upload_sw_state(struct radeon_device *rdev)
+static int ni_upload_sw_state(struct radeon_device *rdev,
+			      struct radeon_ps *radeon_new_state)
 {
 	struct rv7xx_power_info *pi = rv770_get_pi(rdev);
-	struct radeon_ps *radeon_new_state = rdev->pm.dpm.requested_ps;
 	u16 address = pi->state_table_start +
 		offsetof(NISLANDS_SMC_STATETABLE, driverState);
 	u16 state_size = sizeof(NISLANDS_SMC_SWSTATE) +
@@ -2974,12 +2973,12 @@ static void ni_convert_mc_reg_table_to_smc(struct radeon_device *rdev,
 	}
 }
 
-static int ni_populate_mc_reg_table(struct radeon_device *rdev)
+static int ni_populate_mc_reg_table(struct radeon_device *rdev,
+				    struct radeon_ps *radeon_boot_state)
 {
 	struct rv7xx_power_info *pi = rv770_get_pi(rdev);
 	struct evergreen_power_info *eg_pi = evergreen_get_pi(rdev);
         struct ni_power_info *ni_pi = ni_get_pi(rdev);
-        struct radeon_ps *radeon_boot_state = rdev->pm.dpm.boot_ps;
 	struct ni_ps *boot_state = ni_get_ps(radeon_boot_state);
 	SMC_NIslands_MCRegisters *mc_reg_table = &ni_pi->smc_mc_reg_table;
 
@@ -3005,12 +3004,12 @@ static int ni_populate_mc_reg_table(struct radeon_device *rdev)
 				       pi->sram_end);
 }
 
-static int ni_upload_mc_reg_table(struct radeon_device *rdev)
+static int ni_upload_mc_reg_table(struct radeon_device *rdev,
+				  struct radeon_ps *radeon_new_state)
 {
 	struct rv7xx_power_info *pi = rv770_get_pi(rdev);
 	struct evergreen_power_info *eg_pi = evergreen_get_pi(rdev);
         struct ni_power_info *ni_pi = ni_get_pi(rdev);
-	struct radeon_ps *radeon_new_state = rdev->pm.dpm.requested_ps;
 	struct ni_ps *ni_new_state = ni_get_ps(radeon_new_state);
 	SMC_NIslands_MCRegisters *mc_reg_table = &ni_pi->smc_mc_reg_table;
 	u16 address;
@@ -3359,7 +3358,9 @@ static int ni_initialize_hardware_cac_manager(struct radeon_device *rdev)
 	return 0;
 }
 
-static int ni_enable_smc_cac(struct radeon_device *rdev, bool enable)
+static int ni_enable_smc_cac(struct radeon_device *rdev,
+			     struct radeon_ps *radeon_new_state,
+			     bool enable)
 {
 	struct ni_power_info *ni_pi = ni_get_pi(rdev);
 	int ret = 0;
@@ -3367,8 +3368,6 @@ static int ni_enable_smc_cac(struct radeon_device *rdev, bool enable)
 
 	if (ni_pi->enable_cac) {
 		if (enable) {
-			struct radeon_ps *radeon_new_state = rdev->pm.dpm.requested_ps;
-
 			if (!r600_is_uvd_state(radeon_new_state->class, radeon_new_state->class2)) {
 				smc_result = rv770_send_msg_to_smc(rdev, PPSMC_MSG_CollectCAC_PowerCorreln);
 
@@ -3507,6 +3506,7 @@ int ni_dpm_enable(struct radeon_device *rdev)
 {
 	struct rv7xx_power_info *pi = rv770_get_pi(rdev);
 	struct evergreen_power_info *eg_pi = evergreen_get_pi(rdev);
+	struct radeon_ps *boot_ps = rdev->pm.dpm.boot_ps;
 
 	if (pi->gfx_clock_gating)
 		ni_cg_clockgating_default(rdev);
@@ -3543,10 +3543,10 @@ int ni_dpm_enable(struct radeon_device *rdev)
 	ni_init_smc_spll_table(rdev);
 	ni_init_arb_table_index(rdev);
 	if (eg_pi->dynamic_ac_timing)
-		ni_populate_mc_reg_table(rdev);
+		ni_populate_mc_reg_table(rdev, boot_ps);
 	ni_initialize_smc_cac_tables(rdev);
 	ni_initialize_hardware_cac_manager(rdev);
-	ni_populate_smc_tdp_limits(rdev);
+	ni_populate_smc_tdp_limits(rdev, boot_ps);
 	ni_program_response_times(rdev);
 	r7xx_start_smc(rdev);
 	cypress_notify_smc_display_change(rdev, false);
@@ -3583,14 +3583,15 @@ void ni_dpm_disable(struct radeon_device *rdev)
 {
 	struct rv7xx_power_info *pi = rv770_get_pi(rdev);
 	struct evergreen_power_info *eg_pi = evergreen_get_pi(rdev);
+	struct radeon_ps *boot_ps = rdev->pm.dpm.boot_ps;
 
 	if (!btc_dpm_enabled(rdev))
 		return;
 	rv770_clear_vc(rdev);
 	if (pi->thermal_protection)
 		rv770_enable_thermal_protection(rdev, false);
-	ni_enable_power_containment(rdev, false);
-	ni_enable_smc_cac(rdev, false);
+	ni_enable_power_containment(rdev, boot_ps, false);
+	ni_enable_smc_cac(rdev, boot_ps, false);
 	cypress_enable_spread_spectrum(rdev, false);
 	rv770_enable_auto_throttle_source(rdev, RADEON_DPM_AUTO_THROTTLE_SRC_THERMAL, false);
 	if (pi->dynamic_pcie_gen2)
@@ -3616,9 +3617,11 @@ void ni_dpm_disable(struct radeon_device *rdev)
 
 int ni_power_control_set_level(struct radeon_device *rdev)
 {
+	struct radeon_ps *new_ps = rdev->pm.dpm.requested_ps;
+
 	ni_restrict_performance_levels_before_switch(rdev);
 	rv770_halt_smc(rdev);
-	ni_populate_smc_tdp_limits(rdev);
+	ni_populate_smc_tdp_limits(rdev, new_ps);
 	rv770_resume_smc(rdev);
 	rv770_set_sw_state(rdev);
 
@@ -3631,25 +3634,25 @@ int ni_dpm_set_power_state(struct radeon_device *rdev)
 	struct radeon_ps *new_ps = rdev->pm.dpm.requested_ps;
 	int ret;
 
-	ni_apply_state_adjust_rules(rdev);
+	ni_apply_state_adjust_rules(rdev, new_ps);
 
 	ni_restrict_performance_levels_before_switch(rdev);
-	ni_enable_power_containment(rdev, false);
-	ni_enable_smc_cac(rdev, false);
+	ni_enable_power_containment(rdev, new_ps, false);
+	ni_enable_smc_cac(rdev, new_ps, false);
 	rv770_halt_smc(rdev);
 	if (eg_pi->smu_uvd_hs)
 		btc_notify_uvd_to_smc(rdev, new_ps);
-	ni_upload_sw_state(rdev);
+	ni_upload_sw_state(rdev, new_ps);
 	if (eg_pi->dynamic_ac_timing)
-		ni_upload_mc_reg_table(rdev);
-	ret = ni_program_memory_timing_parameters(rdev);
+		ni_upload_mc_reg_table(rdev, new_ps);
+	ret = ni_program_memory_timing_parameters(rdev, new_ps);
 	if (ret)
 		return ret;
-	ni_populate_smc_tdp_limits(rdev);
+	ni_populate_smc_tdp_limits(rdev, new_ps);
 	rv770_resume_smc(rdev);
 	rv770_set_sw_state(rdev);
-	ni_enable_smc_cac(rdev, true);
-	ni_enable_power_containment(rdev, true);
+	ni_enable_smc_cac(rdev, new_ps, true);
+	ni_enable_power_containment(rdev, new_ps, true);
 
 	return 0;
 }
Signature · 1 line
1.7.7.5
#116 lore raw

PATCH 101/165 drm/radeon/dpm/sumo: restructure code

In reply to [email protected]

From: Alex Deucher <[email protected]>

Needed to properly handle dynamic state adjustment.

---
 drivers/gpu/drm/radeon/sumo_dpm.c |  143 +++++++++++++++++++++----------------
 1 files changed, 81 insertions(+), 62 deletions(-)
drivers/gpu/drm/radeon/sumo_dpm.c +81 -62
index 3805302..f5de850 100644
@@ -342,10 +342,11 @@ static void sumo_init_bsp(struct radeon_device *rdev)
 }
 
 
-static void sumo_program_bsp(struct radeon_device *rdev)
+static void sumo_program_bsp(struct radeon_device *rdev,
+			     struct radeon_ps *rps)
 {
 	struct sumo_power_info *pi = sumo_get_pi(rdev);
-	struct sumo_ps *ps = sumo_get_ps(rdev->pm.dpm.requested_ps);
+	struct sumo_ps *ps = sumo_get_ps(rps);
 	u32 i;
 	u32 highest_engine_clock = ps->levels[ps->num_levels - 1].sclk;
 
@@ -384,10 +385,11 @@ static void sumo_write_at(struct radeon_device *rdev,
 		WREG32(CG_AT_7, value);
 }
 
-static void sumo_program_at(struct radeon_device *rdev)
+static void sumo_program_at(struct radeon_device *rdev,
+			    struct radeon_ps *rps)
 {
 	struct sumo_power_info *pi = sumo_get_pi(rdev);
-	struct sumo_ps *ps = sumo_get_ps(rdev->pm.dpm.requested_ps);
+	struct sumo_ps *ps = sumo_get_ps(rps);
 	u32 asi;
 	u32 i;
 	u32 m_a;
@@ -662,10 +664,11 @@ static void sumo_enable_power_level_0(struct radeon_device *rdev)
 	sumo_power_level_enable(rdev, 0, true);
 }
 
-static void sumo_patch_boost_state(struct radeon_device *rdev)
+static void sumo_patch_boost_state(struct radeon_device *rdev,
+				   struct radeon_ps *rps)
 {
 	struct sumo_power_info *pi = sumo_get_pi(rdev);
-	struct sumo_ps *new_ps = sumo_get_ps(rdev->pm.dpm.requested_ps);
+	struct sumo_ps *new_ps = sumo_get_ps(rps);
 
 	if (new_ps->flags & SUMO_POWERSTATE_FLAGS_BOOST_STATE) {
 		pi->boost_pl = new_ps->levels[new_ps->num_levels - 1];
@@ -675,10 +678,12 @@ static void sumo_patch_boost_state(struct radeon_device *rdev)
 	}
 }
 
-static void sumo_pre_notify_alt_vddnb_change(struct radeon_device *rdev)
+static void sumo_pre_notify_alt_vddnb_change(struct radeon_device *rdev,
+					     struct radeon_ps *new_rps,
+					     struct radeon_ps *old_rps)
 {
-	struct sumo_ps *new_ps = sumo_get_ps(rdev->pm.dpm.requested_ps);
-	struct sumo_ps *old_ps = sumo_get_ps(rdev->pm.dpm.current_ps);
+	struct sumo_ps *new_ps = sumo_get_ps(new_rps);
+	struct sumo_ps *old_ps = sumo_get_ps(old_rps);
 	u32 nbps1_old = 0;
 	u32 nbps1_new = 0;
 
@@ -691,10 +696,12 @@ static void sumo_pre_notify_alt_vddnb_change(struct radeon_device *rdev)
 		sumo_smu_notify_alt_vddnb_change(rdev, 0, 0);
 }
 
-static void sumo_post_notify_alt_vddnb_change(struct radeon_device *rdev)
+static void sumo_post_notify_alt_vddnb_change(struct radeon_device *rdev,
+					      struct radeon_ps *new_rps,
+					      struct radeon_ps *old_rps)
 {
-	struct sumo_ps *new_ps = sumo_get_ps(rdev->pm.dpm.requested_ps);
-	struct sumo_ps *old_ps = sumo_get_ps(rdev->pm.dpm.current_ps);
+	struct sumo_ps *new_ps = sumo_get_ps(new_rps);
+	struct sumo_ps *old_ps = sumo_get_ps(old_rps);
 	u32 nbps1_old = 0;
 	u32 nbps1_new = 0;
 
@@ -707,9 +714,11 @@ static void sumo_post_notify_alt_vddnb_change(struct radeon_device *rdev)
 		sumo_smu_notify_alt_vddnb_change(rdev, 1, 1);
 }
 
-static void sumo_enable_boost(struct radeon_device *rdev, bool enable)
+static void sumo_enable_boost(struct radeon_device *rdev,
+			      struct radeon_ps *rps,
+			      bool enable)
 {
-	struct sumo_ps *new_ps = sumo_get_ps(rdev->pm.dpm.requested_ps);
+	struct sumo_ps *new_ps = sumo_get_ps(rps);
 
 	if (enable) {
 		if (new_ps->flags & SUMO_POWERSTATE_FLAGS_BOOST_STATE)
@@ -718,9 +727,10 @@ static void sumo_enable_boost(struct radeon_device *rdev, bool enable)
 		sumo_boost_state_enable(rdev, false);
 }
 
-static void sumo_update_current_power_levels(struct radeon_device *rdev)
+static void sumo_update_current_power_levels(struct radeon_device *rdev,
+					     struct radeon_ps *rps)
 {
-	struct sumo_ps *new_ps = sumo_get_ps(rdev->pm.dpm.requested_ps);
+	struct sumo_ps *new_ps = sumo_get_ps(rps);
 	struct sumo_power_info *pi = sumo_get_pi(rdev);
 
 	pi->current_ps = *new_ps;
@@ -736,9 +746,10 @@ static void sumo_set_forced_level_0(struct radeon_device *rdev)
 	sumo_set_forced_level(rdev, 0);
 }
 
-static void sumo_program_wl(struct radeon_device *rdev)
+static void sumo_program_wl(struct radeon_device *rdev,
+			    struct radeon_ps *rps)
 {
-	struct sumo_ps *new_ps = sumo_get_ps(rdev->pm.dpm.requested_ps);
+	struct sumo_ps *new_ps = sumo_get_ps(rps);
 	u32 dpm_ctrl4 = RREG32(CG_SCLK_DPM_CTRL_4);
 
 	dpm_ctrl4 &= 0xFFFFFF00;
@@ -750,11 +761,13 @@ static void sumo_program_wl(struct radeon_device *rdev)
 	WREG32(CG_SCLK_DPM_CTRL_4, dpm_ctrl4);
 }
 
-static void sumo_program_power_levels_0_to_n(struct radeon_device *rdev)
+static void sumo_program_power_levels_0_to_n(struct radeon_device *rdev,
+					     struct radeon_ps *new_rps,
+					     struct radeon_ps *old_rps)
 {
 	struct sumo_power_info *pi = sumo_get_pi(rdev);
-	struct sumo_ps *new_ps = sumo_get_ps(rdev->pm.dpm.requested_ps);
-	struct sumo_ps *old_ps = sumo_get_ps(rdev->pm.dpm.current_ps);
+	struct sumo_ps *new_ps = sumo_get_ps(new_rps);
+	struct sumo_ps *old_ps = sumo_get_ps(old_rps);
 	u32 i;
 	u32 n_current_state_levels = (old_ps == NULL) ? 1 : old_ps->num_levels;
 
@@ -811,38 +824,40 @@ static void sumo_program_bootup_state(struct radeon_device *rdev)
 		sumo_power_level_enable(rdev, i, false);
 }
 
-static void sumo_set_uvd_clock_before_set_eng_clock(struct radeon_device *rdev)
+static void sumo_set_uvd_clock_before_set_eng_clock(struct radeon_device *rdev,
+						    struct radeon_ps *new_rps,
+						    struct radeon_ps *old_rps)
 {
-	struct sumo_ps *new_ps = sumo_get_ps(rdev->pm.dpm.requested_ps);
-	struct sumo_ps *current_ps = sumo_get_ps(rdev->pm.dpm.current_ps);
+	struct sumo_ps *new_ps = sumo_get_ps(new_rps);
+	struct sumo_ps *current_ps = sumo_get_ps(old_rps);
 
-	if ((rdev->pm.dpm.requested_ps->vclk == rdev->pm.dpm.current_ps->vclk) &&
-	    (rdev->pm.dpm.requested_ps->dclk == rdev->pm.dpm.current_ps->dclk))
+	if ((new_rps->vclk == old_rps->vclk) &&
+	    (new_rps->dclk == old_rps->dclk))
 		return;
 
 	if (new_ps->levels[new_ps->num_levels - 1].sclk >=
 	    current_ps->levels[current_ps->num_levels - 1].sclk)
 		return;
 
-	radeon_set_uvd_clocks(rdev, rdev->pm.dpm.requested_ps->vclk,
-			      rdev->pm.dpm.requested_ps->dclk);
+	radeon_set_uvd_clocks(rdev, new_rps->vclk, new_rps->dclk);
 }
 
-static void sumo_set_uvd_clock_after_set_eng_clock(struct radeon_device *rdev)
+static void sumo_set_uvd_clock_after_set_eng_clock(struct radeon_device *rdev,
+						   struct radeon_ps *new_rps,
+						   struct radeon_ps *old_rps)
 {
-	struct sumo_ps *new_ps = sumo_get_ps(rdev->pm.dpm.requested_ps);
-	struct sumo_ps *current_ps = sumo_get_ps(rdev->pm.dpm.current_ps);
+	struct sumo_ps *new_ps = sumo_get_ps(new_rps);
+	struct sumo_ps *current_ps = sumo_get_ps(old_rps);
 
-	if ((rdev->pm.dpm.requested_ps->vclk == rdev->pm.dpm.current_ps->vclk) &&
-	    (rdev->pm.dpm.requested_ps->dclk == rdev->pm.dpm.current_ps->dclk))
+	if ((new_rps->vclk == old_rps->vclk) &&
+	    (new_rps->dclk == old_rps->dclk))
 		return;
 
 	if (new_ps->levels[new_ps->num_levels - 1].sclk <
 	    current_ps->levels[current_ps->num_levels - 1].sclk)
 		return;
 
-	radeon_set_uvd_clocks(rdev, rdev->pm.dpm.requested_ps->vclk,
-			      rdev->pm.dpm.requested_ps->dclk);
+	radeon_set_uvd_clocks(rdev, new_rps->vclk, new_rps->dclk);
 }
 
 void sumo_take_smu_control(struct radeon_device *rdev, bool enable)
@@ -960,10 +975,11 @@ static void sumo_program_dc_hto(struct radeon_device *rdev)
 	WREG32(CG_SCLK_DPM_CTRL_4, cg_sclk_dpm_ctrl_4);
 }
 
-static void sumo_force_nbp_state(struct radeon_device *rdev)
+static void sumo_force_nbp_state(struct radeon_device *rdev,
+				 struct radeon_ps *rps)
 {
 	struct sumo_power_info *pi = sumo_get_pi(rdev);
-	struct sumo_ps *new_ps = sumo_get_ps(rdev->pm.dpm.requested_ps);
+	struct sumo_ps *new_ps = sumo_get_ps(rps);
 
 	if (!pi->driver_nbps_policy_disable) {
 		if (new_ps->flags & SUMO_POWERSTATE_FLAGS_FORCE_NBPS1_STATE)
@@ -1061,11 +1077,12 @@ static void sumo_patch_thermal_state(struct radeon_device *rdev,
 		ps->levels[0].ss_divider_index = 0;
 }
 
-static void sumo_apply_state_adjust_rules(struct radeon_device *rdev)
+static void sumo_apply_state_adjust_rules(struct radeon_device *rdev,
+					  struct radeon_ps *new_rps,
+					  struct radeon_ps *old_rps)
 {
-	struct radeon_ps *rps = rdev->pm.dpm.requested_ps;
-	struct sumo_ps *ps = sumo_get_ps(rps);
-	struct sumo_ps *current_ps = sumo_get_ps(rdev->pm.dpm.current_ps);
+	struct sumo_ps *ps = sumo_get_ps(new_rps);
+	struct sumo_ps *current_ps = sumo_get_ps(old_rps);
 	struct sumo_power_info *pi = sumo_get_pi(rdev);
 	u32 min_voltage = 0; /* ??? */
 	u32 min_sclk = pi->sys_info.min_sclk; /* XXX check against disp reqs */
@@ -1077,17 +1094,17 @@ static void sumo_apply_state_adjust_rules(struct radeon_device *rdev)
 	rdev->pm.dpm.hw_ps.ps_priv = &pi->hw_ps;
 	ps = &pi->hw_ps;
 
-	if (rps->class & ATOM_PPLIB_CLASSIFICATION_THERMAL)
+	if (new_rps->class & ATOM_PPLIB_CLASSIFICATION_THERMAL)
 		return sumo_patch_thermal_state(rdev, ps, current_ps);
 
 	if (pi->enable_boost) {
-		if (rps->class & ATOM_PPLIB_CLASSIFICATION_UI_PERFORMANCE)
+		if (new_rps->class & ATOM_PPLIB_CLASSIFICATION_UI_PERFORMANCE)
 			ps->flags |= SUMO_POWERSTATE_FLAGS_BOOST_STATE;
 	}
 
-	if ((rps->class & ATOM_PPLIB_CLASSIFICATION_UI_BATTERY) ||
-	    (rps->class & ATOM_PPLIB_CLASSIFICATION_SDSTATE) ||
-	    (rps->class & ATOM_PPLIB_CLASSIFICATION_HDSTATE))
+	if ((new_rps->class & ATOM_PPLIB_CLASSIFICATION_UI_BATTERY) ||
+	    (new_rps->class & ATOM_PPLIB_CLASSIFICATION_SDSTATE) ||
+	    (new_rps->class & ATOM_PPLIB_CLASSIFICATION_HDSTATE))
 		ps->flags |= SUMO_POWERSTATE_FLAGS_FORCE_NBPS1_STATE;
 
 	for (i = 0; i < ps->num_levels; i++) {
@@ -1120,8 +1137,8 @@ static void sumo_apply_state_adjust_rules(struct radeon_device *rdev)
 
 		if (ps->flags & SUMO_POWERSTATE_FLAGS_FORCE_NBPS1_STATE)
 			ps->levels[i].allow_gnb_slow = 1;
-		else if ((rps->class & ATOM_PPLIB_CLASSIFICATION_UVDSTATE) ||
-			 (rps->class2 & ATOM_PPLIB_CLASSIFICATION2_MVC))
+		else if ((new_rps->class & ATOM_PPLIB_CLASSIFICATION_UVDSTATE) ||
+			 (new_rps->class2 & ATOM_PPLIB_CLASSIFICATION2_MVC))
 			ps->levels[i].allow_gnb_slow = 0;
 		else if (i == ps->num_levels - 1)
 			ps->levels[i].allow_gnb_slow = 0;
@@ -1240,36 +1257,38 @@ void sumo_dpm_disable(struct radeon_device *rdev)
 int sumo_dpm_set_power_state(struct radeon_device *rdev)
 {
 	struct sumo_power_info *pi = sumo_get_pi(rdev);
+	struct radeon_ps *new_ps = rdev->pm.dpm.requested_ps;
+	struct radeon_ps *old_ps = rdev->pm.dpm.current_ps;
 
 	if (pi->enable_dynamic_patch_ps)
-		sumo_apply_state_adjust_rules(rdev);
+		sumo_apply_state_adjust_rules(rdev, new_ps, old_ps);
 	if (pi->enable_dpm)
-		sumo_set_uvd_clock_before_set_eng_clock(rdev);
-	sumo_update_current_power_levels(rdev);
+		sumo_set_uvd_clock_before_set_eng_clock(rdev, new_ps, old_ps);
+	sumo_update_current_power_levels(rdev, new_ps);
 	if (pi->enable_boost) {
-		sumo_enable_boost(rdev, false);
-		sumo_patch_boost_state(rdev);
+		sumo_enable_boost(rdev, new_ps, false);
+		sumo_patch_boost_state(rdev, new_ps);
 	}
 	if (pi->enable_dpm) {
-		sumo_pre_notify_alt_vddnb_change(rdev);
+		sumo_pre_notify_alt_vddnb_change(rdev, new_ps, old_ps);
 		sumo_enable_power_level_0(rdev);
 		sumo_set_forced_level_0(rdev);
 		sumo_set_forced_mode_enabled(rdev);
 		sumo_wait_for_level_0(rdev);
-		sumo_program_power_levels_0_to_n(rdev);
-		sumo_program_wl(rdev);
-		sumo_program_bsp(rdev);
-		sumo_program_at(rdev);
-		sumo_force_nbp_state(rdev);
+		sumo_program_power_levels_0_to_n(rdev, new_ps, old_ps);
+		sumo_program_wl(rdev, new_ps);
+		sumo_program_bsp(rdev, new_ps);
+		sumo_program_at(rdev, new_ps);
+		sumo_force_nbp_state(rdev, new_ps);
 		sumo_set_forced_mode_disabled(rdev);
 		sumo_set_forced_mode_enabled(rdev);
 		sumo_set_forced_mode_disabled(rdev);
-		sumo_post_notify_alt_vddnb_change(rdev);
+		sumo_post_notify_alt_vddnb_change(rdev, new_ps, old_ps);
 	}
 	if (pi->enable_boost)
-		sumo_enable_boost(rdev, true);
+		sumo_enable_boost(rdev, new_ps, true);
 	if (pi->enable_dpm)
-		sumo_set_uvd_clock_after_set_eng_clock(rdev);
+		sumo_set_uvd_clock_after_set_eng_clock(rdev, new_ps, old_ps);
 
 	return 0;
 }
Signature · 1 line
1.7.7.5
#117 lore raw

PATCH 102/165 drm/radeon/dpm/tn: restructure code

In reply to [email protected]

From: Alex Deucher <[email protected]>

Needed to properly handle dynamic state adjustment.

---
 drivers/gpu/drm/radeon/trinity_dpm.c |   93 +++++++++++++++++++---------------
 1 files changed, 52 insertions(+), 41 deletions(-)
drivers/gpu/drm/radeon/trinity_dpm.c +52 -41
index 0c1b50a..103efbc 100644
@@ -337,7 +337,9 @@ static const u32 trinity_override_mgpg_sequences[] =
 static void trinity_program_clk_gating_hw_sequence(struct radeon_device *rdev,
 						   const u32 *seq, u32 count);
 static void trinity_override_dynamic_mg_powergating(struct radeon_device *rdev);
-static void trinity_apply_state_adjust_rules(struct radeon_device *rdev);
+static void trinity_apply_state_adjust_rules(struct radeon_device *rdev,
+					     struct radeon_ps *new_rps,
+					     struct radeon_ps *old_rps);
 
 struct trinity_ps *trinity_get_ps(struct radeon_ps *rps)
 {
@@ -830,18 +832,21 @@ static void trinity_unforce_levels(struct radeon_device *rdev)
 	trinity_dpm_no_forced_level(rdev);
 }
 
-static void trinity_update_current_power_levels(struct radeon_device *rdev)
+static void trinity_update_current_power_levels(struct radeon_device *rdev,
+						struct radeon_ps *rps)
 {
-	struct trinity_ps *new_ps = trinity_get_ps(rdev->pm.dpm.requested_ps);
+	struct trinity_ps *new_ps = trinity_get_ps(rps);
 	struct trinity_power_info *pi = trinity_get_pi(rdev);
 
 	pi->current_ps = *new_ps;
 }
 
-static void trinity_program_power_levels_0_to_n(struct radeon_device *rdev)
+static void trinity_program_power_levels_0_to_n(struct radeon_device *rdev,
+						struct radeon_ps *new_rps,
+						struct radeon_ps *old_rps)
 {
-	struct trinity_ps *new_ps = trinity_get_ps(rdev->pm.dpm.requested_ps);
-	struct trinity_ps *old_ps = trinity_get_ps(rdev->pm.dpm.current_ps);
+	struct trinity_ps *new_ps = trinity_get_ps(new_rps);
+	struct trinity_ps *old_ps = trinity_get_ps(old_rps);
 	u32 i;
 	u32 n_current_state_levels = (old_ps == NULL) ? 1 : old_ps->num_levels;
 
@@ -919,19 +924,19 @@ static bool trinity_uvd_clocks_equal(struct radeon_ps *rps1,
 }
 
 static void trinity_setup_uvd_clocks(struct radeon_device *rdev,
-				     struct radeon_ps *current_rps,
-				     struct radeon_ps *new_rps)
+				     struct radeon_ps *new_rps,
+				     struct radeon_ps *old_rps)
 {
 	struct trinity_power_info *pi = trinity_get_pi(rdev);
 
 	if (pi->uvd_dpm) {
 		if (trinity_uvd_clocks_zero(new_rps) &&
-		    !trinity_uvd_clocks_zero(current_rps)) {
+		    !trinity_uvd_clocks_zero(old_rps)) {
 			trinity_setup_uvd_dpm_interval(rdev, 0);
 		} else if (!trinity_uvd_clocks_zero(new_rps)) {
 			trinity_setup_uvd_clock_table(rdev, new_rps);
 
-			if (trinity_uvd_clocks_zero(current_rps)) {
+			if (trinity_uvd_clocks_zero(old_rps)) {
 				u32 tmp = RREG32(CG_MISC_REG);
 				tmp &= 0xfffffffd;
 				WREG32(CG_MISC_REG, tmp);
@@ -944,37 +949,39 @@ static void trinity_setup_uvd_clocks(struct radeon_device *rdev,
 		trinity_uvd_dpm_config(rdev);
 	} else {
 		if (trinity_uvd_clocks_zero(new_rps) ||
-		    trinity_uvd_clocks_equal(new_rps, current_rps))
+		    trinity_uvd_clocks_equal(new_rps, old_rps))
 			return;
 
 		radeon_set_uvd_clocks(rdev, new_rps->vclk, new_rps->dclk);
 	}
 }
 
-static void trinity_set_uvd_clock_before_set_eng_clock(struct radeon_device *rdev)
+static void trinity_set_uvd_clock_before_set_eng_clock(struct radeon_device *rdev,
+						       struct radeon_ps *new_rps,
+						       struct radeon_ps *old_rps)
 {
-	struct trinity_ps *new_ps = trinity_get_ps(rdev->pm.dpm.requested_ps);
-	struct trinity_ps *current_ps = trinity_get_ps(rdev->pm.dpm.current_ps);
+	struct trinity_ps *new_ps = trinity_get_ps(new_rps);
+	struct trinity_ps *current_ps = trinity_get_ps(new_rps);
 
 	if (new_ps->levels[new_ps->num_levels - 1].sclk >=
 	    current_ps->levels[current_ps->num_levels - 1].sclk)
 		return;
 
-	trinity_setup_uvd_clocks(rdev, rdev->pm.dpm.current_ps,
-				 rdev->pm.dpm.requested_ps);
+	trinity_setup_uvd_clocks(rdev, new_rps, old_rps);
 }
 
-static void trinity_set_uvd_clock_after_set_eng_clock(struct radeon_device *rdev)
+static void trinity_set_uvd_clock_after_set_eng_clock(struct radeon_device *rdev,
+						      struct radeon_ps *new_rps,
+						      struct radeon_ps *old_rps)
 {
-	struct trinity_ps *new_ps = trinity_get_ps(rdev->pm.dpm.requested_ps);
-	struct trinity_ps *current_ps = trinity_get_ps(rdev->pm.dpm.current_ps);
+	struct trinity_ps *new_ps = trinity_get_ps(new_rps);
+	struct trinity_ps *current_ps = trinity_get_ps(old_rps);
 
 	if (new_ps->levels[new_ps->num_levels - 1].sclk <
 	    current_ps->levels[current_ps->num_levels - 1].sclk)
 		return;
 
-	trinity_setup_uvd_clocks(rdev, rdev->pm.dpm.current_ps,
-				 rdev->pm.dpm.requested_ps);
+	trinity_setup_uvd_clocks(rdev, new_rps, old_rps);
 }
 
 static void trinity_program_ttt(struct radeon_device *rdev)
@@ -1102,10 +1109,11 @@ static void trinity_get_min_sclk_divider(struct radeon_device *rdev)
 		(RREG32_SMC(CC_SMU_MISC_FUSES) & MinSClkDid_MASK) >> MinSClkDid_SHIFT;
 }
 
-static void trinity_setup_nbp_sim(struct radeon_device *rdev)
+static void trinity_setup_nbp_sim(struct radeon_device *rdev,
+				  struct radeon_ps *rps)
 {
 	struct trinity_power_info *pi = trinity_get_pi(rdev);
-	struct trinity_ps *new_ps = trinity_get_ps(rdev->pm.dpm.requested_ps);
+	struct trinity_ps *new_ps = trinity_get_ps(rps);
 	u32 nbpsconfig;
 
 	if (pi->sys_info.nb_dpm_enable) {
@@ -1122,21 +1130,23 @@ static void trinity_setup_nbp_sim(struct radeon_device *rdev)
 int trinity_dpm_set_power_state(struct radeon_device *rdev)
 {
 	struct trinity_power_info *pi = trinity_get_pi(rdev);
+	struct radeon_ps *new_ps = rdev->pm.dpm.requested_ps;
+	struct radeon_ps *old_ps = rdev->pm.dpm.current_ps;
 
-	trinity_apply_state_adjust_rules(rdev);
-	trinity_update_current_power_levels(rdev);
+	trinity_apply_state_adjust_rules(rdev, new_ps, old_ps);
+	trinity_update_current_power_levels(rdev, new_ps);
 
 	trinity_acquire_mutex(rdev);
 	if (pi->enable_dpm) {
-		trinity_set_uvd_clock_before_set_eng_clock(rdev);
+		trinity_set_uvd_clock_before_set_eng_clock(rdev, new_ps, old_ps);
 		trinity_enable_power_level_0(rdev);
 		trinity_force_level_0(rdev);
 		trinity_wait_for_level_0(rdev);
-		trinity_setup_nbp_sim(rdev);
-		trinity_program_power_levels_0_to_n(rdev);
+		trinity_setup_nbp_sim(rdev, new_ps);
+		trinity_program_power_levels_0_to_n(rdev, new_ps, old_ps);
 		trinity_force_level_0(rdev);
 		trinity_unforce_levels(rdev);
-		trinity_set_uvd_clock_after_set_eng_clock(rdev);
+		trinity_set_uvd_clock_after_set_eng_clock(rdev, new_ps, old_ps);
 	}
 	trinity_release_mutex(rdev);
 
@@ -1366,11 +1376,12 @@ static void trinity_adjust_uvd_state(struct radeon_device *rdev,
 
 
 
-static void trinity_apply_state_adjust_rules(struct radeon_device *rdev)
+static void trinity_apply_state_adjust_rules(struct radeon_device *rdev,
+					     struct radeon_ps *new_rps,
+					     struct radeon_ps *old_rps)
 {
-	struct radeon_ps *rps = rdev->pm.dpm.requested_ps;
-	struct trinity_ps *ps = trinity_get_ps(rps);
-	struct trinity_ps *current_ps = trinity_get_ps(rdev->pm.dpm.current_ps);
+	struct trinity_ps *ps = trinity_get_ps(new_rps);
+	struct trinity_ps *current_ps = trinity_get_ps(old_rps);
 	struct trinity_power_info *pi = trinity_get_pi(rdev);
 	u32 min_voltage = 0; /* ??? */
 	u32 min_sclk = pi->sys_info.min_sclk; /* XXX check against disp reqs */
@@ -1384,10 +1395,10 @@ static void trinity_apply_state_adjust_rules(struct radeon_device *rdev)
 	rdev->pm.dpm.hw_ps.ps_priv = &pi->hw_ps;
 	ps = &pi->hw_ps;
 
-	if (rps->class & ATOM_PPLIB_CLASSIFICATION_THERMAL)
+	if (new_rps->class & ATOM_PPLIB_CLASSIFICATION_THERMAL)
 		return trinity_patch_thermal_state(rdev, ps, current_ps);
 
-	trinity_adjust_uvd_state(rdev, rps);
+	trinity_adjust_uvd_state(rdev, new_rps);
 
 	for (i = 0; i < ps->num_levels; i++) {
 		if (ps->levels[i].vddc_index < min_voltage)
@@ -1410,8 +1421,8 @@ static void trinity_apply_state_adjust_rules(struct radeon_device *rdev)
 			trinity_calculate_vce_wm(rdev, ps->levels[0].sclk);
 	}
 
-	if ((rps->class & (ATOM_PPLIB_CLASSIFICATION_HDSTATE | ATOM_PPLIB_CLASSIFICATION_SDSTATE)) ||
-	    ((rps->class & ATOM_PPLIB_CLASSIFICATION_UI_MASK) == ATOM_PPLIB_CLASSIFICATION_UI_BATTERY))
+	if ((new_rps->class & (ATOM_PPLIB_CLASSIFICATION_HDSTATE | ATOM_PPLIB_CLASSIFICATION_SDSTATE)) ||
+	    ((new_rps->class & ATOM_PPLIB_CLASSIFICATION_UI_MASK) == ATOM_PPLIB_CLASSIFICATION_UI_BATTERY))
 		ps->bapm_flags |= TRINITY_POWERSTATE_FLAGS_BAPM_DISABLE;
 
 	if (pi->sys_info.nb_dpm_enable) {
@@ -1420,10 +1431,10 @@ static void trinity_apply_state_adjust_rules(struct radeon_device *rdev)
 		ps->DpmXNbPsLo = 0x2;
 		ps->DpmXNbPsHi = 0x1;
 
-		if ((rps->class & (ATOM_PPLIB_CLASSIFICATION_HDSTATE | ATOM_PPLIB_CLASSIFICATION_SDSTATE)) ||
-		    ((rps->class & ATOM_PPLIB_CLASSIFICATION_UI_MASK) == ATOM_PPLIB_CLASSIFICATION_UI_BATTERY)) {
-			force_high = ((rps->class & ATOM_PPLIB_CLASSIFICATION_HDSTATE) ||
-				      ((rps->class & ATOM_PPLIB_CLASSIFICATION_SDSTATE) &&
+		if ((new_rps->class & (ATOM_PPLIB_CLASSIFICATION_HDSTATE | ATOM_PPLIB_CLASSIFICATION_SDSTATE)) ||
+		    ((new_rps->class & ATOM_PPLIB_CLASSIFICATION_UI_MASK) == ATOM_PPLIB_CLASSIFICATION_UI_BATTERY)) {
+			force_high = ((new_rps->class & ATOM_PPLIB_CLASSIFICATION_HDSTATE) ||
+				      ((new_rps->class & ATOM_PPLIB_CLASSIFICATION_SDSTATE) &&
 				       (pi->sys_info.uma_channel_number == 1)));
 			force_high = (num_active_displays >= 3) || force_high;
 			ps->Dpm0PgNbPsLo = force_high ? 0x2 : 0x3;
Signature · 1 line
1.7.7.5
#118 lore raw

PATCH 103/165 drm/radeon/dpm: add new pre/post_set_power_state callbacks

In reply to [email protected]

From: Alex Deucher <[email protected]>

Needed to properly handle dynamic state adjustment.

---
 drivers/gpu/drm/radeon/radeon.h    |    4 ++++
 drivers/gpu/drm/radeon/radeon_pm.c |   11 +++++++++++
 2 files changed, 15 insertions(+), 0 deletions(-)
drivers/gpu/drm/radeon/radeon.h +4 -0
index 16c7d52..657d224 100644
@@ -1616,7 +1616,9 @@ struct radeon_asic {
 		void (*setup_asic)(struct radeon_device *rdev);
 		int (*enable)(struct radeon_device *rdev);
 		void (*disable)(struct radeon_device *rdev);
+		int (*pre_set_power_state)(struct radeon_device *rdev);
 		int (*set_power_state)(struct radeon_device *rdev);
+		void (*post_set_power_state)(struct radeon_device *rdev);
 		void (*display_configuration_changed)(struct radeon_device *rdev);
 		void (*fini)(struct radeon_device *rdev);
 		u32 (*get_sclk)(struct radeon_device *rdev, bool low);
@@ -2326,7 +2328,9 @@ void radeon_ring_write(struct radeon_ring *ring, uint32_t v);
 #define radeon_dpm_setup_asic(rdev) rdev->asic->dpm.setup_asic((rdev))
 #define radeon_dpm_enable(rdev) rdev->asic->dpm.enable((rdev))
 #define radeon_dpm_disable(rdev) rdev->asic->dpm.disable((rdev))
+#define radeon_dpm_pre_set_power_state(rdev) rdev->asic->dpm.pre_set_power_state((rdev))
 #define radeon_dpm_set_power_state(rdev) rdev->asic->dpm.set_power_state((rdev))
+#define radeon_dpm_post_set_power_state(rdev) rdev->asic->dpm.post_set_power_state((rdev))
 #define radeon_dpm_display_configuration_changed(rdev) rdev->asic->dpm.display_configuration_changed((rdev))
 #define radeon_dpm_fini(rdev) rdev->asic->dpm.fini((rdev))
 #define radeon_dpm_get_sclk(rdev, l) rdev->asic->dpm.get_sclk((rdev), (l))
drivers/gpu/drm/radeon/radeon_pm.c +11 -0
index 01ff18b..a50efb0 100644
@@ -703,6 +703,7 @@ static void radeon_dpm_change_power_state_locked(struct radeon_device *rdev)
 	int i;
 	struct radeon_ps *ps;
 	enum radeon_pm_state_type dpm_state;
+	int ret;
 
 	/* if dpm init failed */
 	if (!rdev->pm.dpm_enabled)
@@ -769,6 +770,12 @@ static void radeon_dpm_change_power_state_locked(struct radeon_device *rdev)
 	down_write(&rdev->pm.mclk_lock);
 	mutex_lock(&rdev->ring_lock);
 
+	if (rdev->asic->dpm.pre_set_power_state) {
+		ret = radeon_dpm_pre_set_power_state(rdev);
+		if (ret)
+			goto done;
+	}
+
 	/* update display watermarks based on new power state */
 	radeon_bandwidth_update(rdev);
 	/* update displays */
@@ -790,6 +797,10 @@ static void radeon_dpm_change_power_state_locked(struct radeon_device *rdev)
 	/* update current power state */
 	rdev->pm.dpm.current_ps = rdev->pm.dpm.requested_ps;
 
+	if (rdev->asic->dpm.post_set_power_state)
+		radeon_dpm_post_set_power_state(rdev);
+
+done:
 	mutex_unlock(&rdev->ring_lock);
 	up_write(&rdev->pm.mclk_lock);
 	mutex_unlock(&rdev->ddev->struct_mutex);
Signature · 1 line
1.7.7.5
#119 lore raw

PATCH 104/165 drm/radeon/dpm: add pre/post_set_power_state callbacks (6xx-eg)

In reply to [email protected]

From: Alex Deucher <[email protected]>

For r6xx-evergreen, they are no-ops as they don't support any dynamic state adjustment.

---
 drivers/gpu/drm/radeon/r600_dpm.c    |   10 ++++++++++
 drivers/gpu/drm/radeon/radeon_asic.c |    8 ++++++++
 drivers/gpu/drm/radeon/radeon_asic.h |    2 ++
 3 files changed, 20 insertions(+), 0 deletions(-)
drivers/gpu/drm/radeon/r600_dpm.c +10 -0
index c9f9647..bcb1967 100644
@@ -662,6 +662,16 @@ void r600_stop_dpm(struct radeon_device *rdev)
 	r600_dynamicpm_enable(rdev, false);
 }
 
+int r600_dpm_pre_set_power_state(struct radeon_device *rdev)
+{
+	return 0;
+}
+
+void r600_dpm_post_set_power_state(struct radeon_device *rdev)
+{
+
+}
+
 bool r600_is_uvd_state(u32 class, u32 class2)
 {
 	if (class & ATOM_PPLIB_CLASSIFICATION_UVDSTATE)
drivers/gpu/drm/radeon/radeon_asic.c +8 -0
index e6703ef..5014bd1 100644
@@ -1110,7 +1110,9 @@ static struct radeon_asic rv6xx_asic = {
 		.setup_asic = &rv6xx_setup_asic,
 		.enable = &rv6xx_dpm_enable,
 		.disable = &rv6xx_dpm_disable,
+		.pre_set_power_state = &r600_dpm_pre_set_power_state,
 		.set_power_state = &rv6xx_dpm_set_power_state,
+		.post_set_power_state = &r600_dpm_post_set_power_state,
 		.display_configuration_changed = &rv6xx_dpm_display_configuration_changed,
 		.fini = &rv6xx_dpm_fini,
 		.get_sclk = &rv6xx_dpm_get_sclk,
@@ -1211,7 +1213,9 @@ static struct radeon_asic rs780_asic = {
 		.setup_asic = &rs780_dpm_setup_asic,
 		.enable = &rs780_dpm_enable,
 		.disable = &rs780_dpm_disable,
+		.pre_set_power_state = &r600_dpm_pre_set_power_state,
 		.set_power_state = &rs780_dpm_set_power_state,
+		.post_set_power_state = &r600_dpm_post_set_power_state,
 		.display_configuration_changed = &rs780_dpm_display_configuration_changed,
 		.fini = &rs780_dpm_fini,
 		.get_sclk = &rs780_dpm_get_sclk,
@@ -1322,7 +1326,9 @@ static struct radeon_asic rv770_asic = {
 		.setup_asic = &rv770_dpm_setup_asic,
 		.enable = &rv770_dpm_enable,
 		.disable = &rv770_dpm_disable,
+		.pre_set_power_state = &r600_dpm_pre_set_power_state,
 		.set_power_state = &rv770_dpm_set_power_state,
+		.post_set_power_state = &r600_dpm_post_set_power_state,
 		.display_configuration_changed = &rv770_dpm_display_configuration_changed,
 		.fini = &rv770_dpm_fini,
 		.get_sclk = &rv770_dpm_get_sclk,
@@ -1433,7 +1439,9 @@ static struct radeon_asic evergreen_asic = {
 		.setup_asic = &cypress_dpm_setup_asic,
 		.enable = &cypress_dpm_enable,
 		.disable = &cypress_dpm_disable,
+		.pre_set_power_state = &r600_dpm_pre_set_power_state,
 		.set_power_state = &cypress_dpm_set_power_state,
+		.post_set_power_state = &r600_dpm_post_set_power_state,
 		.display_configuration_changed = &cypress_dpm_display_configuration_changed,
 		.fini = &cypress_dpm_fini,
 		.get_sclk = &rv770_dpm_get_sclk,
drivers/gpu/drm/radeon/radeon_asic.h +2 -0
index 2fef64d..d7d4662 100644
@@ -396,6 +396,8 @@ int r600_mc_wait_for_idle(struct radeon_device *rdev);
 u32 r600_get_xclk(struct radeon_device *rdev);
 uint64_t r600_get_gpu_clock_counter(struct radeon_device *rdev);
 int rv6xx_get_temp(struct radeon_device *rdev);
+int r600_dpm_pre_set_power_state(struct radeon_device *rdev);
+void r600_dpm_post_set_power_state(struct radeon_device *rdev);
 /* rv6xx dpm */
 int rv6xx_dpm_init(struct radeon_device *rdev);
 int rv6xx_dpm_enable(struct radeon_device *rdev);
Signature · 1 line
1.7.7.5
#120 lore raw

PATCH 105/165 drm/radeon/dpm: add pre/post_set_power_state callback (sumo)

In reply to [email protected]

From: Alex Deucher <[email protected]>

This properly implemented dynamic state adjustment by using a working copy of the requested and current power states.

---
 drivers/gpu/drm/radeon/radeon_asic.c |    2 +
 drivers/gpu/drm/radeon/radeon_asic.h |    2 +
 drivers/gpu/drm/radeon/sumo_dpm.c    |   74 ++++++++++++++++++++++++---------
 drivers/gpu/drm/radeon/sumo_dpm.h    |    6 ++-
 4 files changed, 62 insertions(+), 22 deletions(-)
drivers/gpu/drm/radeon/radeon_asic.c +2 -0
index 5014bd1..c5d70da 100644
@@ -1552,7 +1552,9 @@ static struct radeon_asic sumo_asic = {
 		.setup_asic = &sumo_dpm_setup_asic,
 		.enable = &sumo_dpm_enable,
 		.disable = &sumo_dpm_disable,
+		.pre_set_power_state = &sumo_dpm_pre_set_power_state,
 		.set_power_state = &sumo_dpm_set_power_state,
+		.post_set_power_state = &sumo_dpm_post_set_power_state,
 		.display_configuration_changed = &sumo_dpm_display_configuration_changed,
 		.fini = &sumo_dpm_fini,
 		.get_sclk = &sumo_dpm_get_sclk,
drivers/gpu/drm/radeon/radeon_asic.h +2 -0
index d7d4662..817fc26 100644
@@ -541,7 +541,9 @@ void btc_dpm_fini(struct radeon_device *rdev);
 int sumo_dpm_init(struct radeon_device *rdev);
 int sumo_dpm_enable(struct radeon_device *rdev);
 void sumo_dpm_disable(struct radeon_device *rdev);
+int sumo_dpm_pre_set_power_state(struct radeon_device *rdev);
 int sumo_dpm_set_power_state(struct radeon_device *rdev);
+void sumo_dpm_post_set_power_state(struct radeon_device *rdev);
 void sumo_dpm_setup_asic(struct radeon_device *rdev);
 void sumo_dpm_display_configuration_changed(struct radeon_device *rdev);
 void sumo_dpm_fini(struct radeon_device *rdev);
drivers/gpu/drm/radeon/sumo_dpm.c +54 -20

124 lines not on this page · raw message

drivers/gpu/drm/radeon/sumo_dpm.h +4 -2
index a40b62a..a3a7a61 100644
@@ -116,7 +116,6 @@ struct sumo_power_info {
 	struct sumo_pl acpi_pl;
 	struct sumo_pl boot_pl;
 	struct sumo_pl boost_pl;
-	struct sumo_ps current_ps;
 	bool disable_gfx_power_gating_in_uvd;
 	bool driver_nbps_policy_disable;
 	bool enable_alt_vddnb;
@@ -129,7 +128,10 @@ struct sumo_power_info {
 	bool enable_dynamic_patch_ps;
 	bool enable_dpm;
 	bool enable_boost;
-	struct sumo_ps hw_ps;
+	struct radeon_ps current_rps;
+	struct sumo_ps current_ps;
+	struct radeon_ps requested_rps;
+	struct sumo_ps requested_ps;
 };
 
 #define SUMO_UTC_DFLT_00                     0x48
Signature · 1 line
1.7.7.5
#121 lore raw

PATCH 106/165 drm/radeon/dpm: add pre/post_set_power_state callback (TN)

In reply to [email protected]

From: Alex Deucher <[email protected]>

This properly implemented dynamic state adjustment by using a working copy of the requested and current power states.

---
 drivers/gpu/drm/radeon/radeon_asic.c |    2 +
 drivers/gpu/drm/radeon/radeon_asic.h |    2 +
 drivers/gpu/drm/radeon/trinity_dpm.c |   73 ++++++++++++++++++++++++---------
 drivers/gpu/drm/radeon/trinity_dpm.h |    6 ++-
 4 files changed, 61 insertions(+), 22 deletions(-)
drivers/gpu/drm/radeon/radeon_asic.c +2 -0
index c5d70da..c78519c 100644
@@ -1971,7 +1971,9 @@ static struct radeon_asic trinity_asic = {
 		.setup_asic = &trinity_dpm_setup_asic,
 		.enable = &trinity_dpm_enable,
 		.disable = &trinity_dpm_disable,
+		.pre_set_power_state = &trinity_dpm_pre_set_power_state,
 		.set_power_state = &trinity_dpm_set_power_state,
+		.post_set_power_state = &trinity_dpm_post_set_power_state,
 		.display_configuration_changed = &trinity_dpm_display_configuration_changed,
 		.fini = &trinity_dpm_fini,
 		.get_sclk = &trinity_dpm_get_sclk,
drivers/gpu/drm/radeon/radeon_asic.h +2 -0
index 817fc26..14d992d 100644
@@ -598,7 +598,9 @@ void ni_dpm_print_power_state(struct radeon_device *rdev,
 int trinity_dpm_init(struct radeon_device *rdev);
 int trinity_dpm_enable(struct radeon_device *rdev);
 void trinity_dpm_disable(struct radeon_device *rdev);
+int trinity_dpm_pre_set_power_state(struct radeon_device *rdev);
 int trinity_dpm_set_power_state(struct radeon_device *rdev);
+void trinity_dpm_post_set_power_state(struct radeon_device *rdev);
 void trinity_dpm_setup_asic(struct radeon_device *rdev);
 void trinity_dpm_display_configuration_changed(struct radeon_device *rdev);
 void trinity_dpm_fini(struct radeon_device *rdev);
drivers/gpu/drm/radeon/trinity_dpm.c +53 -20

124 lines not on this page · raw message

drivers/gpu/drm/radeon/trinity_dpm.h +4 -2
index c663aed..c621b84 100644
@@ -97,7 +97,6 @@ struct trinity_power_info {
 	u32 thermal_auto_throttling;
 	struct trinity_sys_info sys_info;
 	struct trinity_pl boot_pl;
-	struct trinity_ps current_ps;
 	u32 min_sclk_did;
 	bool enable_nbps_policy;
 	bool voltage_drop_in_dce;
@@ -110,7 +109,10 @@ struct trinity_power_info {
 	bool enable_dpm;
 	bool enable_sclk_ds;
 	bool uvd_dpm;
-	struct trinity_ps hw_ps;
+	struct radeon_ps current_rps;
+	struct trinity_ps current_ps;
+	struct radeon_ps requested_rps;
+	struct trinity_ps requested_ps;
 };
 
 #define TRINITY_AT_DFLT            30
Signature · 1 line
1.7.7.5
#122 lore raw

PATCH 107/165 drm/radeon/dpm: add pre/post_set_power_state callback (BTC)

In reply to [email protected]

From: Alex Deucher <[email protected]>

This properly implemented dynamic state adjustment by using a working copy of the requested and current power states.

---
 drivers/gpu/drm/radeon/btc_dpm.c     |   81 +++++++++++++++++++++++++++++----
 drivers/gpu/drm/radeon/cypress_dpm.h |    5 ++-
 drivers/gpu/drm/radeon/radeon_asic.c |    6 ++-
 drivers/gpu/drm/radeon/radeon_asic.h |    4 ++
 4 files changed, 83 insertions(+), 13 deletions(-)
drivers/gpu/drm/radeon/btc_dpm.c +71 -10
index 30aed00..7c7d58f 100644
@@ -2062,18 +2062,12 @@ static void btc_init_stutter_mode(struct radeon_device *rdev)
 static void btc_apply_state_adjust_rules(struct radeon_device *rdev,
 					 struct radeon_ps *rps)
 {
-	struct evergreen_power_info *eg_pi = evergreen_get_pi(rdev);
 	struct rv7xx_ps *ps = rv770_get_ps(rps);
 	struct radeon_clock_and_voltage_limits *max_limits;
 	bool disable_mclk_switching;
 	u32 mclk, sclk;
 	u16 vddc, vddci;
 
-	/* point to the hw copy since this function will modify the ps */
-	eg_pi->hw_ps = *ps;
-	rdev->pm.dpm.hw_ps.ps_priv = &eg_pi->hw_ps;
-	ps = &eg_pi->hw_ps;
-
 	if (rdev->pm.dpm.new_active_crtc_count > 1)
 		disable_mclk_switching = true;
 	else
@@ -2222,6 +2216,28 @@ static void btc_apply_state_adjust_rules(struct radeon_device *rdev,
 		ps->high.flags &= ~ATOM_PPLIB_R600_FLAGS_PCIEGEN2;
 }
 
+static void btc_update_current_ps(struct radeon_device *rdev,
+				  struct radeon_ps *rps)
+{
+	struct rv7xx_ps *new_ps = rv770_get_ps(rps);
+	struct evergreen_power_info *eg_pi = evergreen_get_pi(rdev);
+
+	eg_pi->current_rps = *rps;
+	eg_pi->current_ps = *new_ps;
+	eg_pi->current_rps.ps_priv = &eg_pi->current_ps;
+}
+
+static void btc_update_requested_ps(struct radeon_device *rdev,
+				    struct radeon_ps *rps)
+{
+	struct rv7xx_ps *new_ps = rv770_get_ps(rps);
+	struct evergreen_power_info *eg_pi = evergreen_get_pi(rdev);
+
+	eg_pi->requested_rps = *rps;
+	eg_pi->requested_ps = *new_ps;
+	eg_pi->requested_rps.ps_priv = &eg_pi->requested_ps;
+}
+
 void btc_dpm_reset_asic(struct radeon_device *rdev)
 {
 	rv770_restrict_performance_levels_before_switch(rdev);
@@ -2230,13 +2246,24 @@ void btc_dpm_reset_asic(struct radeon_device *rdev)
 	rv770_set_boot_state(rdev);
 }
 
-int btc_dpm_set_power_state(struct radeon_device *rdev)
+int btc_dpm_pre_set_power_state(struct radeon_device *rdev)
 {
 	struct evergreen_power_info *eg_pi = evergreen_get_pi(rdev);
-	struct radeon_ps *new_ps = rdev->pm.dpm.requested_ps;
-	struct radeon_ps *old_ps = rdev->pm.dpm.current_ps;
+	struct radeon_ps requested_ps = *rdev->pm.dpm.requested_ps;
+	struct radeon_ps *new_ps = &requested_ps;
+
+	btc_update_requested_ps(rdev, new_ps);
+
+	btc_apply_state_adjust_rules(rdev, &eg_pi->requested_rps);
 
-	btc_apply_state_adjust_rules(rdev, new_ps);
+	return 0;
+}
+
+int btc_dpm_set_power_state(struct radeon_device *rdev)
+{
+	struct evergreen_power_info *eg_pi = evergreen_get_pi(rdev);
+	struct radeon_ps *new_ps = &eg_pi->requested_rps;
+	struct radeon_ps *old_ps = &eg_pi->current_rps;
 
 	btc_disable_ulv(rdev);
 	btc_set_boot_state_timing(rdev);
@@ -2269,6 +2296,14 @@ int btc_dpm_set_power_state(struct radeon_device *rdev)
 	return 0;
 }
 
+void btc_dpm_post_set_power_state(struct radeon_device *rdev)
+{
+	struct evergreen_power_info *eg_pi = evergreen_get_pi(rdev);
+	struct radeon_ps *new_ps = &eg_pi->requested_rps;
+
+	btc_update_current_ps(rdev, new_ps);
+}
+
 int btc_dpm_enable(struct radeon_device *rdev)
 {
 	struct rv7xx_power_info *pi = rv770_get_pi(rdev);
@@ -2364,6 +2399,8 @@ int btc_dpm_enable(struct radeon_device *rdev)
 
 	btc_init_stutter_mode(rdev);
 
+	btc_update_current_ps(rdev, rdev->pm.dpm.boot_ps);
+
 	return 0;
 };
 
@@ -2402,6 +2439,8 @@ void btc_dpm_disable(struct radeon_device *rdev)
 	btc_reset_to_default(rdev);
 	btc_stop_smc(rdev);
 	cypress_enable_spread_spectrum(rdev, false);
+
+	btc_update_current_ps(rdev, rdev->pm.dpm.boot_ps);
 }
 
 void btc_dpm_setup_asic(struct radeon_device *rdev)
@@ -2586,3 +2625,25 @@ void btc_dpm_fini(struct radeon_device *rdev)
 	kfree(rdev->pm.dpm.priv);
 	r600_free_extended_power_table(rdev);
 }
+
+u32 btc_dpm_get_sclk(struct radeon_device *rdev, bool low)
+{
+	struct evergreen_power_info *eg_pi = evergreen_get_pi(rdev);
+	struct rv7xx_ps *requested_state = rv770_get_ps(&eg_pi->requested_rps);
+
+	if (low)
+		return requested_state->low.sclk;
+	else
+		return requested_state->high.sclk;
+}
+
+u32 btc_dpm_get_mclk(struct radeon_device *rdev, bool low)
+{
+	struct evergreen_power_info *eg_pi = evergreen_get_pi(rdev);
+	struct rv7xx_ps *requested_state = rv770_get_ps(&eg_pi->requested_rps);
+
+	if (low)
+		return requested_state->low.mclk;
+	else
+		return requested_state->high.mclk;
+}
drivers/gpu/drm/radeon/cypress_dpm.h +4 -1
index 5b19364..4c3f18c 100644
@@ -88,7 +88,10 @@ struct evergreen_power_info {
 	struct at ats[2];
 	/* smc offsets */
 	u16 mc_reg_table_start;
-	struct rv7xx_ps hw_ps;
+	struct radeon_ps current_rps;
+	struct rv7xx_ps current_ps;
+	struct radeon_ps requested_rps;
+	struct rv7xx_ps requested_ps;
 };
 
 #define CYPRESS_HASI_DFLT                               400000
drivers/gpu/drm/radeon/radeon_asic.c +4 -2
index c78519c..25eeaa4 100644
@@ -1665,11 +1665,13 @@ static struct radeon_asic btc_asic = {
 		.setup_asic = &btc_dpm_setup_asic,
 		.enable = &btc_dpm_enable,
 		.disable = &btc_dpm_disable,
+		.pre_set_power_state = &btc_dpm_pre_set_power_state,
 		.set_power_state = &btc_dpm_set_power_state,
+		.post_set_power_state = &btc_dpm_post_set_power_state,
 		.display_configuration_changed = &cypress_dpm_display_configuration_changed,
 		.fini = &btc_dpm_fini,
-		.get_sclk = &rv770_dpm_get_sclk,
-		.get_mclk = &rv770_dpm_get_mclk,
+		.get_sclk = &btc_dpm_get_sclk,
+		.get_mclk = &btc_dpm_get_mclk,
 		.print_power_state = &rv770_dpm_print_power_state,
 	},
 	.pflip = {
drivers/gpu/drm/radeon/radeon_asic.h +4 -0
index 14d992d..696d6e9 100644
@@ -536,8 +536,12 @@ int btc_dpm_init(struct radeon_device *rdev);
 void btc_dpm_setup_asic(struct radeon_device *rdev);
 int btc_dpm_enable(struct radeon_device *rdev);
 void btc_dpm_disable(struct radeon_device *rdev);
+int btc_dpm_pre_set_power_state(struct radeon_device *rdev);
 int btc_dpm_set_power_state(struct radeon_device *rdev);
+void btc_dpm_post_set_power_state(struct radeon_device *rdev);
 void btc_dpm_fini(struct radeon_device *rdev);
+u32 btc_dpm_get_sclk(struct radeon_device *rdev, bool low);
+u32 btc_dpm_get_mclk(struct radeon_device *rdev, bool low);
 int sumo_dpm_init(struct radeon_device *rdev);
 int sumo_dpm_enable(struct radeon_device *rdev);
 void sumo_dpm_disable(struct radeon_device *rdev);
Signature · 1 line
1.7.7.5
#123 lore raw

PATCH 108/165 drm/radeon/dpm: add pre/post_set_power_state callback (cayman)

In reply to [email protected]

From: Alex Deucher <[email protected]>

This properly implemented dynamic state adjustment by using a working copy of the requested and current power states.

---
 drivers/gpu/drm/radeon/ni_dpm.c      |   65 ++++++++++++++++++++++++++++------
 drivers/gpu/drm/radeon/ni_dpm.h      |    3 +-
 drivers/gpu/drm/radeon/radeon_asic.c |    2 +
 drivers/gpu/drm/radeon/radeon_asic.h |    2 +
 4 files changed, 60 insertions(+), 12 deletions(-)
drivers/gpu/drm/radeon/ni_dpm.c +54 -11
index ebc9837..01ecb80 100644
@@ -791,7 +791,6 @@ static void ni_calculate_leakage_for_v_and_t(struct radeon_device *rdev,
 static void ni_apply_state_adjust_rules(struct radeon_device *rdev,
 					struct radeon_ps *rps)
 {
-	struct ni_power_info *ni_pi = ni_get_pi(rdev);
 	struct ni_ps *ps = ni_get_ps(rps);
 	struct radeon_clock_and_voltage_limits *max_limits;
 	bool disable_mclk_switching;
@@ -799,11 +798,6 @@ static void ni_apply_state_adjust_rules(struct radeon_device *rdev,
 	u16 vddc, vddci;
 	int i;
 
-	/* point to the hw copy since this function will modify the ps */
-	ni_pi->hw_ps = *ps;
-	rdev->pm.dpm.hw_ps.ps_priv = &ni_pi->hw_ps;
-	ps = &ni_pi->hw_ps;
-
 	if (rdev->pm.dpm.new_active_crtc_count > 1)
 		disable_mclk_switching = true;
 	else
@@ -3502,6 +3496,30 @@ void ni_dpm_setup_asic(struct radeon_device *rdev)
 	rv770_enable_acpi_pm(rdev);
 }
 
+static void ni_update_current_ps(struct radeon_device *rdev,
+				 struct radeon_ps *rps)
+{
+	struct ni_ps *new_ps = ni_get_ps(rps);
+	struct evergreen_power_info *eg_pi = evergreen_get_pi(rdev);
+        struct ni_power_info *ni_pi = ni_get_pi(rdev);
+
+	eg_pi->current_rps = *rps;
+	ni_pi->current_ps = *new_ps;
+	eg_pi->current_rps.ps_priv = &ni_pi->current_ps;
+}
+
+static void ni_update_requested_ps(struct radeon_device *rdev,
+				   struct radeon_ps *rps)
+{
+	struct ni_ps *new_ps = ni_get_ps(rps);
+	struct evergreen_power_info *eg_pi = evergreen_get_pi(rdev);
+        struct ni_power_info *ni_pi = ni_get_pi(rdev);
+
+	eg_pi->requested_rps = *rps;
+	ni_pi->requested_ps = *new_ps;
+	eg_pi->requested_rps.ps_priv = &ni_pi->requested_ps;
+}
+
 int ni_dpm_enable(struct radeon_device *rdev)
 {
 	struct rv7xx_power_info *pi = rv770_get_pi(rdev);
@@ -3576,6 +3594,8 @@ int ni_dpm_enable(struct radeon_device *rdev)
 
 	rv770_enable_auto_throttle_source(rdev, RADEON_DPM_AUTO_THROTTLE_SRC_THERMAL, true);
 
+	ni_update_current_ps(rdev, boot_ps);
+
 	return 0;
 }
 
@@ -3613,6 +3633,8 @@ void ni_dpm_disable(struct radeon_device *rdev)
 	btc_reset_to_default(rdev);
 	ni_stop_smc(rdev);
 	ni_force_switch_to_arb_f0(rdev);
+
+	ni_update_current_ps(rdev, boot_ps);
 }
 
 int ni_power_control_set_level(struct radeon_device *rdev)
@@ -3628,14 +3650,25 @@ int ni_power_control_set_level(struct radeon_device *rdev)
 	return 0;
 }
 
+int ni_dpm_pre_set_power_state(struct radeon_device *rdev)
+{
+	struct evergreen_power_info *eg_pi = evergreen_get_pi(rdev);
+	struct radeon_ps requested_ps = *rdev->pm.dpm.requested_ps;
+	struct radeon_ps *new_ps = &requested_ps;
+
+	ni_update_requested_ps(rdev, new_ps);
+
+	ni_apply_state_adjust_rules(rdev, &eg_pi->requested_rps);
+
+	return 0;
+}
+
 int ni_dpm_set_power_state(struct radeon_device *rdev)
 {
 	struct evergreen_power_info *eg_pi = evergreen_get_pi(rdev);
-	struct radeon_ps *new_ps = rdev->pm.dpm.requested_ps;
+	struct radeon_ps *new_ps = &eg_pi->requested_rps;
 	int ret;
 
-	ni_apply_state_adjust_rules(rdev, new_ps);
-
 	ni_restrict_performance_levels_before_switch(rdev);
 	ni_enable_power_containment(rdev, new_ps, false);
 	ni_enable_smc_cac(rdev, new_ps, false);
@@ -3657,6 +3690,14 @@ int ni_dpm_set_power_state(struct radeon_device *rdev)
 	return 0;
 }
 
+void ni_dpm_post_set_power_state(struct radeon_device *rdev)
+{
+	struct evergreen_power_info *eg_pi = evergreen_get_pi(rdev);
+	struct radeon_ps *new_ps = &eg_pi->requested_rps;
+
+	ni_update_current_ps(rdev, new_ps);
+}
+
 void ni_dpm_reset_asic(struct radeon_device *rdev)
 {
 	ni_restrict_performance_levels_before_switch(rdev);
@@ -4078,7 +4119,8 @@ void ni_dpm_print_power_state(struct radeon_device *rdev,
 
 u32 ni_dpm_get_sclk(struct radeon_device *rdev, bool low)
 {
-	struct ni_ps *requested_state = ni_get_ps(rdev->pm.dpm.requested_ps);
+	struct evergreen_power_info *eg_pi = evergreen_get_pi(rdev);
+	struct ni_ps *requested_state = ni_get_ps(&eg_pi->requested_rps);
 
 	if (low)
 		return requested_state->performance_levels[0].sclk;
@@ -4088,7 +4130,8 @@ u32 ni_dpm_get_sclk(struct radeon_device *rdev, bool low)
 
 u32 ni_dpm_get_mclk(struct radeon_device *rdev, bool low)
 {
-	struct ni_ps *requested_state = ni_get_ps(rdev->pm.dpm.requested_ps);
+	struct evergreen_power_info *eg_pi = evergreen_get_pi(rdev);
+	struct ni_ps *requested_state = ni_get_ps(&eg_pi->requested_rps);
 
 	if (low)
 		return requested_state->performance_levels[0].mclk;
drivers/gpu/drm/radeon/ni_dpm.h +2 -1
index e10f747..59c1692 100644
@@ -202,7 +202,8 @@ struct ni_power_info {
 	const struct ni_cac_weights *cac_weights;
 	u8 lta_window_size;
 	u8 lts_truncate;
-	struct ni_ps hw_ps;
+	struct ni_ps current_ps;
+	struct ni_ps requested_ps;
 	/* scratch structs */
 	SMC_NIslands_MCRegisters smc_mc_reg_table;
 	NISLANDS_SMC_STATETABLE smc_statetable;
drivers/gpu/drm/radeon/radeon_asic.c +2 -0
index 25eeaa4..e7162b1 100644
@@ -1821,7 +1821,9 @@ static struct radeon_asic cayman_asic = {
 		.setup_asic = &ni_dpm_setup_asic,
 		.enable = &ni_dpm_enable,
 		.disable = &ni_dpm_disable,
+		.pre_set_power_state = &ni_dpm_pre_set_power_state,
 		.set_power_state = &ni_dpm_set_power_state,
+		.post_set_power_state = &ni_dpm_post_set_power_state,
 		.display_configuration_changed = &cypress_dpm_display_configuration_changed,
 		.fini = &ni_dpm_fini,
 		.get_sclk = &ni_dpm_get_sclk,
drivers/gpu/drm/radeon/radeon_asic.h +2 -0
index 696d6e9..7b898bc 100644
@@ -593,7 +593,9 @@ int ni_dpm_init(struct radeon_device *rdev);
 void ni_dpm_setup_asic(struct radeon_device *rdev);
 int ni_dpm_enable(struct radeon_device *rdev);
 void ni_dpm_disable(struct radeon_device *rdev);
+int ni_dpm_pre_set_power_state(struct radeon_device *rdev);
 int ni_dpm_set_power_state(struct radeon_device *rdev);
+void ni_dpm_post_set_power_state(struct radeon_device *rdev);
 void ni_dpm_fini(struct radeon_device *rdev);
 u32 ni_dpm_get_sclk(struct radeon_device *rdev, bool low);
 u32 ni_dpm_get_mclk(struct radeon_device *rdev, bool low);
Signature · 1 line
1.7.7.5
#124 lore raw

PATCH 109/165 drm/radeon/dpm: remove broken dyn state remnants

In reply to [email protected]

From: Alex Deucher <[email protected]>

Now that the proper fix has been implemented I can remove the last remnants of the initial implementation.

---
 drivers/gpu/drm/radeon/radeon.h    |    1 -
 drivers/gpu/drm/radeon/radeon_pm.c |   24 +++++-------------------
 2 files changed, 5 insertions(+), 20 deletions(-)
drivers/gpu/drm/radeon/radeon.h +0 -1
index 657d224..0c6676a 100644
@@ -1307,7 +1307,6 @@ struct radeon_dpm {
 	struct radeon_ps        *boot_ps;
 	/* default uvd power state */
 	struct radeon_ps        *uvd_ps;
-	struct radeon_ps        hw_ps;
 	enum radeon_pm_state_type state;
 	enum radeon_pm_state_type user_state;
 	u32                     platform_caps;
drivers/gpu/drm/radeon/radeon_pm.c +5 -19
index a50efb0..c8688b3 100644
@@ -687,17 +687,6 @@ restart_search:
 	return NULL;
 }
 
-static void radeon_dpm_update_requested_ps(struct radeon_device *rdev,
-					   struct radeon_ps *ps)
-{
-	/* copy the ps to the hw ps and point the requested ps
-	 * at the hw state in case the driver wants to modify
-	 * the state dynamically.
-	 */
-	rdev->pm.dpm.hw_ps = *ps;
-	rdev->pm.dpm.requested_ps = &rdev->pm.dpm.hw_ps;
-}
-
 static void radeon_dpm_change_power_state_locked(struct radeon_device *rdev)
 {
 	int i;
@@ -719,7 +708,7 @@ static void radeon_dpm_change_power_state_locked(struct radeon_device *rdev)
 
 	ps = radeon_dpm_pick_power_state(rdev, dpm_state);
 	if (ps)
-		radeon_dpm_update_requested_ps(rdev, ps);
+		rdev->pm.dpm.requested_ps = ps;
 	else
 		return;
 
@@ -770,11 +759,9 @@ static void radeon_dpm_change_power_state_locked(struct radeon_device *rdev)
 	down_write(&rdev->pm.mclk_lock);
 	mutex_lock(&rdev->ring_lock);
 
-	if (rdev->asic->dpm.pre_set_power_state) {
-		ret = radeon_dpm_pre_set_power_state(rdev);
-		if (ret)
-			goto done;
-	}
+	ret = radeon_dpm_pre_set_power_state(rdev);
+	if (ret)
+		goto done;
 
 	/* update display watermarks based on new power state */
 	radeon_bandwidth_update(rdev);
@@ -797,8 +784,7 @@ static void radeon_dpm_change_power_state_locked(struct radeon_device *rdev)
 	/* update current power state */
 	rdev->pm.dpm.current_ps = rdev->pm.dpm.requested_ps;
 
-	if (rdev->asic->dpm.post_set_power_state)
-		radeon_dpm_post_set_power_state(rdev);
+	radeon_dpm_post_set_power_state(rdev);
 
 done:
 	mutex_unlock(&rdev->ring_lock);
Signature · 1 line
1.7.7.5
#125 lore raw

PATCH 110/165 drm/radeon: add missing UVD clock set in cayman dpm code

In reply to [email protected]

From: Alex Deucher <[email protected]>

---
 drivers/gpu/drm/radeon/ni_dpm.c |    3 +++
 1 files changed, 3 insertions(+), 0 deletions(-)
drivers/gpu/drm/radeon/ni_dpm.c +3 -0
index 01ecb80..a88f0cb 100644
@@ -3667,9 +3667,11 @@ int ni_dpm_set_power_state(struct radeon_device *rdev)
 {
 	struct evergreen_power_info *eg_pi = evergreen_get_pi(rdev);
 	struct radeon_ps *new_ps = &eg_pi->requested_rps;
+	struct radeon_ps *old_ps = &eg_pi->current_rps;
 	int ret;
 
 	ni_restrict_performance_levels_before_switch(rdev);
+	rv770_set_uvd_clock_before_set_eng_clock(rdev, new_ps, old_ps);
 	ni_enable_power_containment(rdev, new_ps, false);
 	ni_enable_smc_cac(rdev, new_ps, false);
 	rv770_halt_smc(rdev);
@@ -3684,6 +3686,7 @@ int ni_dpm_set_power_state(struct radeon_device *rdev)
 	ni_populate_smc_tdp_limits(rdev, new_ps);
 	rv770_resume_smc(rdev);
 	rv770_set_sw_state(rdev);
+	rv770_set_uvd_clock_after_set_eng_clock(rdev, new_ps, old_ps);
 	ni_enable_smc_cac(rdev, new_ps, true);
 	ni_enable_power_containment(rdev, new_ps, true);
 
Signature · 1 line
1.7.7.5
#126 lore raw

PATCH 111/165 drm/radeon/dpm: remove local sumo_get_xclk()

In reply to [email protected]

From: Alex Deucher <[email protected]>

Use the new asic callback instead.

---
 drivers/gpu/drm/radeon/sumo_dpm.c    |   19 +++++++------------
 drivers/gpu/drm/radeon/sumo_dpm.h    |    1 -
 drivers/gpu/drm/radeon/sumo_smc.c    |    2 +-
 drivers/gpu/drm/radeon/trinity_dpm.c |    6 +++---
 4 files changed, 11 insertions(+), 17 deletions(-)
drivers/gpu/drm/radeon/sumo_dpm.c +7 -12
index 10700e1..80fb3ac 100644
@@ -84,11 +84,6 @@ struct sumo_power_info *sumo_get_pi(struct radeon_device *rdev)
 	return pi;
 }
 
-u32 sumo_get_xclk(struct radeon_device *rdev)
-{
-	return rdev->clock.spll.reference_freq;
-}
-
 static void sumo_gfx_clockgating_enable(struct radeon_device *rdev, bool enable)
 {
 	if (enable)
@@ -124,7 +119,7 @@ static void sumo_mg_clockgating_enable(struct radeon_device *rdev, bool enable)
 static void sumo_program_git(struct radeon_device *rdev)
 {
 	u32 p, u;
-	u32 xclk = sumo_get_xclk(rdev);
+	u32 xclk = radeon_get_xclk(rdev);
 
 	r600_calculate_u_and_p(SUMO_GICST_DFLT,
 			       xclk, 16, &p, &u);
@@ -135,7 +130,7 @@ static void sumo_program_git(struct radeon_device *rdev)
 static void sumo_program_grsd(struct radeon_device *rdev)
 {
 	u32 p, u;
-	u32 xclk = sumo_get_xclk(rdev);
+	u32 xclk = radeon_get_xclk(rdev);
 	u32 grs = 256 * 25 / 100;
 
 	r600_calculate_u_and_p(1, xclk, 14, &p, &u);
@@ -155,7 +150,7 @@ static void sumo_gfx_powergating_initialize(struct radeon_device *rdev)
 	u32 p, u;
 	u32 p_c, p_p, d_p;
 	u32 r_t, i_t;
-	u32 xclk = sumo_get_xclk(rdev);
+	u32 xclk = radeon_get_xclk(rdev);
 
 	if (rdev->family == CHIP_PALM) {
 		p_c = 4;
@@ -319,7 +314,7 @@ static void sumo_calculate_bsp(struct radeon_device *rdev,
 			       u32 high_clk)
 {
 	struct sumo_power_info *pi = sumo_get_pi(rdev);
-	u32 xclk = sumo_get_xclk(rdev);
+	u32 xclk = radeon_get_xclk(rdev);
 
 	pi->pasi = 65535 * 100 / high_clk;
 	pi->asi = 65535 * 100 / high_clk;
@@ -466,7 +461,7 @@ void sumo_clear_vc(struct radeon_device *rdev)
 void sumo_program_sstp(struct radeon_device *rdev)
 {
 	u32 p, u;
-	u32 xclk = sumo_get_xclk(rdev);
+	u32 xclk = radeon_get_xclk(rdev);
 
 	r600_calculate_u_and_p(SUMO_SST_DFLT,
 			       xclk, 16, &p, &u);
@@ -909,7 +904,7 @@ static void sumo_start_am(struct radeon_device *rdev)
 
 static void sumo_program_ttp(struct radeon_device *rdev)
 {
-	u32 xclk = sumo_get_xclk(rdev);
+	u32 xclk = radeon_get_xclk(rdev);
 	u32 p, u;
 	u32 cg_sclk_dpm_ctrl_5 = RREG32(CG_SCLK_DPM_CTRL_5);
 
@@ -955,7 +950,7 @@ static void sumo_program_dc_hto(struct radeon_device *rdev)
 {
 	u32 cg_sclk_dpm_ctrl_4 = RREG32(CG_SCLK_DPM_CTRL_4);
 	u32 p, u;
-	u32 xclk = sumo_get_xclk(rdev);
+	u32 xclk = radeon_get_xclk(rdev);
 
 	r600_calculate_u_and_p(100000,
 			       xclk, 14, &p, &u);
drivers/gpu/drm/radeon/sumo_dpm.h +0 -1
index a3a7a61..07dda29 100644
@@ -188,7 +188,6 @@ struct sumo_power_info {
 #define SUMO_GFXPOWERGATINGT_DFLT  100
 
 /* sumo_dpm.c */
-u32 sumo_get_xclk(struct radeon_device *rdev);
 void sumo_gfx_clockgating_initialize(struct radeon_device *rdev);
 void sumo_program_vc(struct radeon_device *rdev, u32 vrc);
 void sumo_clear_vc(struct radeon_device *rdev);
drivers/gpu/drm/radeon/sumo_smc.c +1 -1
index bc1a510..9cbf0b2 100644
@@ -146,7 +146,7 @@ void sumo_enable_boost_timer(struct radeon_device *rdev)
 {
 	struct sumo_power_info *pi = sumo_get_pi(rdev);
 	u32 period, unit, timer_value;
-	u32 xclk = sumo_get_xclk(rdev);
+	u32 xclk = radeon_get_xclk(rdev);
 
 	unit = (RREG32_RCU(RCU_LCLK_SCALING_CNTL) & LCLK_SCALING_TIMER_PRESCALER_MASK)
 		>> LCLK_SCALING_TIMER_PRESCALER_SHIFT;
drivers/gpu/drm/radeon/trinity_dpm.c +3 -3
index 1699e93..b2dc905 100644
@@ -361,7 +361,7 @@ static void trinity_gfx_powergating_initialize(struct radeon_device *rdev)
 	u32 p, u;
 	u32 value;
 	struct atom_clock_dividers dividers;
-	u32 xclk = sumo_get_xclk(rdev);
+	u32 xclk = radeon_get_xclk(rdev);
 	u32 sssd = 1;
 	int ret;
 	u32 hw_rev = (RREG32(HW_REV) & ATI_REV_ID_MASK) >> ATI_REV_ID_SHIFT;
@@ -880,7 +880,7 @@ static void trinity_setup_uvd_dpm_interval(struct radeon_device *rdev,
 	u32 p, u;
 	u32 tp = RREG32_SMC(PM_TP);
 	u32 val;
-	u32 xclk = sumo_get_xclk(rdev);
+	u32 xclk = radeon_get_xclk(rdev);
 
 	r600_calculate_u_and_p(interval, xclk, 16, &p, &u);
 
@@ -1000,7 +1000,7 @@ static void trinity_program_sclk_dpm(struct radeon_device *rdev)
 	u32 p, u;
 	u32 tp = RREG32_SMC(PM_TP);
 	u32 ni;
-	u32 xclk = sumo_get_xclk(rdev);
+	u32 xclk = radeon_get_xclk(rdev);
 	u32 value;
 
 	r600_calculate_u_and_p(400, xclk, 16, &p, &u);
Signature · 1 line
1.7.7.5
Reviewed-by on the v1 series
#127 lore raw
In reply to [email protected]
Quoted 8 lines · On Wed, Jun 26, 2013 at 09:21:20AM -0400, [email protected] wrote:

From: Alex Deucher <[email protected]>

These are the radeon patches for 3.11. Some of these patches are huge so, it might be easier to review things here:
http://cgit.freedesktop.org/~agd5f/linux/log/?h=drm-next-3.11-wip

I'll send a formal pull in request in the next day or two.

Quoted 8 lines

Highlights of this series:
- DPM support (Dynamic Power Management) for r6xx-SI
- Support for CIK (Sea Islands): modesetting, 3D, compute, UVD
- ASPM support for R6xx-SI

Since this is the initial public DPM code, it's still disabled by default until we get more community testing. Pass dpm=1 to the radeon module to enable it.

So for the serie (except one i replied to) got my :

I mostly checked the logic behind function ie what function is supose to do and does it do it properly. I didn't do any tedious check like is it using proper define for this generation.

I wish more of the acronym related to power management were documented. There is so many magic name that it's often hard to understand the logic of the code, what it's doing and what is it that it's computing.

Regarding CIK i fear that the hsa addition doesn't fit very well with our ring stuff, we probably don't want a ring struct for each of the 32 or 64 queues. But as right now we are only using few queues, that's probably alright.

Cheers,
Jerome

Quoted 316 lines

Alex Deucher (164):
drm/radeon: fix AVI infoframe generation
drm/radeon: add backlight quirk for hybrid mac drm/radeon: add a reset work handler
drm/radeon: add CIK chip families
drm/radeon: add DCE8 macro for CIK
drm/radeon: adapt to PCI BAR changes on CIK drm/radeon: add gpu init support for CIK (v9) drm/radeon: Add support for CIK GPU reset (v2) drm/radeon: add support for MC/VM setup on CIK (v6) drm/radeon/cik: stop page faults from hanging the system (v2) drm/radeon: add initial ucode loading for CIK (v5) drm/radeon: add support mc ucode loading on CIK (v2) drm/radeon: Add CP init for CIK (v7)
drm/radeon: add IB and fence dispatch functions for CIK gfx (v7) drm/radeon: add ring and IB tests for CIK (v3) drm/radeon: implement async vm_flush for the CP (v7) drm/radeon: Add support for RLC init on CIK (v4) drm/radeon: add support for interrupts on CIK (v5) drm/radeon/cik: log and handle VM page fault interrupts drm/radeon/cik: add support for sDMA dma engines (v8) drm/radeon: implement async vm_flush for the sDMA (v6) drm/radeon/cik: add support for doing async VM pt updates (v5) drm/radeon/cik: fill in startup/shutdown callbacks (v4) drm/radeon: upstream ObjectID.h updates (v2) drm/radeon: upstream atombios.h updates (v2) drm/radeon: atombios power table updates (v2) drm/radeon: handle the integrated thermal controller on CI drm/radeon: update power state parsing for CI drm/radeon/dce8: add support for display watermark setup drm/radeon/cik: add hw cursor support (v2) drm/radeon/dce8: properly handle interlaced timing drm/radeon/dce8: crtc_set_base updates drm/radeon/atom: add DCE8 encoder support drm/radeon/atom: add support for new DVO tables drm/radeon: update DISPCLK programming for DCE8 drm/radeon: add support pll selection for DCE8 (v4) drm/radeon: Handle PPLL0 powerdown on DCE8
drm/radeon: use frac fb div on DCE8
drm/radeon: add SS override support for KB/KV drm/radeon: Update radeon_info_ioctl for CIK (v2) drm/radeon: add get_gpu_clock_counter() callback for cik drm/radeon: update CIK soft reset
drm/radeon: add indirect register accessors for SMC registers drm/radeon: add get_xclk() callback for CIK drm/radeon/cik: add pcie_port indirect register accessors drm/radeon: update radeon_atom_get_clock_dividers() for SI drm/radeon: update radeon_atom_get_clock_dividers for CIK drm/radeon/cik: add srbm_select function
drm/radeon: use callbacks for ring pointer handling drm/radeon: implement simple doorbell page allocator drm/radeon/cik: Add support for compute queues (v2) drm/radeon/cik: switch to type3 nop packet for compute rings drm/radeon: fix up ring functions for compute rings drm/radeon/cik: add support for compute interrupts drm/radeon/cik: add support for golden register init drm/radeon: add radeon_asic struct for CIK (v11) drm/radeon: add cik tile mode array query
drm/radeon: add current Bonaire PCI ids
drm/radeon: add current KB pci ids
drm/radeon/kms: add accessors for RCU indirect space drm/radeon/evergreen: add indirect register accessors for CG
registers
drm/radeon: make get_temperature functions a callback drm/radeon: add support for thermal sensor on tn drm/radeon/kms: move ucode defines to a separate header drm/radeon: properly set up the RLC on ON/LN/TN (v3) drm/radeon/kms: add atom helper functions for dpm (v3) drm/radeon/kms: add new asic struct for rv6xx (v3) drm/radeon/kms: add common dpm infrastructure drm/radeon/kms: fix up rs780/rs880 display watermark calc for dpm drm/radeon/kms: fix up 6xx/7xx display watermark calc for dpm drm/radeon/kms: fix up dce4/5 display watermark calc for dpm drm/radeon/kms: fix up dce6 display watermark calc for dpm drm/radeon/kms: add common r600 dpm functions drm/radeon/kms: add dpm support for rs780/rs880 drm/radeon/kms: add dpm support for rv6xx drm/radeon/kms: add dpm support for rv7xx (v2) drm/radeon/kms: add dpm support for evergreen (v2) drm/radeon/kms: add dpm support for btc (v2) drm/radeon/kms: add dpm support for sumo asics drm/radeon/kms: add dpm support for trinity asics drm/radeon/dpm: let atom control display phy powergating drm/radeon: add dpm UVD handling for r7xx asics drm/radeon: add dpm UVD handling for evergreen/btc asics drm/radeon: add dpm UVD handling for sumo asics drm/radeon: add dpm UVD handling for TN asics (v2) drm/radeon/kms: enable UVD as needed (v9) drm/radeon/dpm: add helpers for extended power tables (v2) drm/radeon/dpm: track whether we are on AC or battery drm/radeon/dpm: fixup dynamic state adjust for sumo drm/radeon/dpm: fixup dynamic state adjust for TN drm/radeon/dpm: fixup dynamic state adjust for btc (v2) drm/radeon/kms: add dpm support for cayman drm/radeon/cayman: update tdp limits in set_power_state drm/radeon/dpm/rs780: restructure code drm/radeon/dpm/rv6xx: restructure code drm/radeon/dpm/rv7xx: restructure code drm/radeon/dpm/evergreen: restructure code drm/radeon/dpm/btc: restructure code drm/radeon/dpm/cayman: restructure code drm/radeon/dpm/sumo: restructure code drm/radeon/dpm/tn: restructure code
drm/radeon/dpm: add new pre/post_set_power_state callbacks drm/radeon/dpm: add pre/post_set_power_state callbacks (6xx-eg) drm/radeon/dpm: add pre/post_set_power_state callback (sumo) drm/radeon/dpm: add pre/post_set_power_state callback (TN) drm/radeon/dpm: add pre/post_set_power_state callback (BTC) drm/radeon/dpm: add pre/post_set_power_state callback (cayman) drm/radeon/dpm: remove broken dyn state remnants drm/radeon: add missing UVD clock set in cayman dpm code drm/radeon/dpm: remove local sumo_get_xclk() drm/radeon: implement apci perf request drm/radeon/atom: add helper to calcuate mpll params drm/radeon: update radeon_atom_is_voltage_gpio() for SI drm/radeon: update radeon_atom_get_voltage_table() for SI drm/radeon: implement pcie gen2/3 support for SI drm/radeon: add accessors of pif_phy indirect register space drm/radeon: add support for ASPM on evergreen asics drm/radeon: add support for ASPM on SI asics (v2) drm/radeon: enable additional power gating features on trinity drm/radeon: update rlc programming sequence on SI drm/radeon: add atom get leakage vddc function drm/radeon: add indirect accessors for UVD CTX registers drm/radeon: initialize save/restore buffer for pg on verde drm/radeon: add clearstate init for verde power gating drm/radeon: implement clock and power gating for SI drm/radeon/dpm: add an enum for pcie gen selection drm/radeon/dpm: pull in phase shedding limits from atom drm/radeon/dpm: endian fixes for extended power tables drm/radeon/dpm: pull in ppm info from atom drm/radeon/dpm: save some display parameters for DPM drm/radeon: minor sid.h cleanup
drm: add some additional fixed point helpers (v2) drm/radeon/dpm/cayman: use new fixed point functions drm/radeon: fix some memory leaks in extended table parsing drm/radeon/dpm: validate voltages against dispclk requirements drm/radeon: update radeon_atombios_get_default_voltages for mvdd drm/radeon/dpm: add pcie gen helper function drm/radeon: fix typo in atom voltage table handling (6xx-ni) drm/radeon: fix typo in atom voltage table handling (si+) drm/radeon/atom: fix voltage table parsing drm/radeon/dpm/ni: properly catch errors in dpm setup drm/radeon/dpm/btc: properly catch errors in dpm setup drm/radeon/dpm/evergreen: properly catch errors in dpm setup drm/radeon/dpm/sumo: properly catch errors in dpm setup drm/radeon/dpm/trinity: properly catch errors in dpm setup drm/radeon/dpm/r7xx: properly catch errors in dpm setup drm/radeon/dpm/r6xx: properly catch errors in dpm setup drm/radeon/dpm/rs780: properly catch errors in dpm setup drm/radeon: add SI to r600_is_internal_thermal_sensor() drm/radeon: switch SI to use radeon_ucode.h drm/radeon/kms: add dpm support for SI (v3) drm/radeon/dpm: add dpm_enable failure output (7xx-ni) drm/radeon/dpm: add dpm_enable failure output (si) drm/radeon/dpm: add dpm_set_power_state failure output (7xx-ni) drm/radeon/dpm: add dpm_set_power_state failure output (si) drm/radeon/dpm: fix typo in setting uvd clock drm/radeon/si: fix typo in function name
drm/radeon: fix typo in cik_select_se_sh()
drm/radeon: fix typo in ni_print_power_state drm/radeon/dpm: add support for setting UVD clock on rs780 drm/radeon/dpm: add support for setting UVD clock on rv6xx drm/radeon/dpm: fix UVD clock setting on cayman drm/radeon/dpm: fix UVD clock setting on SI drm/radeon: fix endian issues in atombios dpm code

Christian König (1):
drm/radeon: add UVD support for CIK (v3)

 drivers/gpu/drm/radeon/Makefile               |    5 +-
 drivers/gpu/drm/radeon/ObjectID.h             |   40 +
 drivers/gpu/drm/radeon/atombios.h             |  547 ++-
 drivers/gpu/drm/radeon/atombios_crtc.c        |   88 +-
 drivers/gpu/drm/radeon/atombios_encoders.c    |   51 +-
 drivers/gpu/drm/radeon/btc_dpm.c              | 2731 ++++++++++
 drivers/gpu/drm/radeon/btc_dpm.h              |   57 +
 drivers/gpu/drm/radeon/btcd.h                 |  181 +
 drivers/gpu/drm/radeon/cik.c                  | 6995 +++++++++++++++++++++++++
 drivers/gpu/drm/radeon/cik_blit_shaders.c     |  246 +
 drivers/gpu/drm/radeon/cik_blit_shaders.h     |   32 +
 drivers/gpu/drm/radeon/cik_reg.h              |  147 +
 drivers/gpu/drm/radeon/cikd.h                 | 1297 +++++
 drivers/gpu/drm/radeon/clearstate_cayman.h    | 1081 ++++
 drivers/gpu/drm/radeon/clearstate_defs.h      |   44 +
 drivers/gpu/drm/radeon/clearstate_evergreen.h | 1080 ++++
 drivers/gpu/drm/radeon/clearstate_si.h        |  941 ++++
 drivers/gpu/drm/radeon/cypress_dpm.c          | 2170 ++++++++
 drivers/gpu/drm/radeon/cypress_dpm.h          |  160 +
 drivers/gpu/drm/radeon/evergreen.c            |  644 +++-
 drivers/gpu/drm/radeon/evergreen_hdmi.c       |   11 +-
 drivers/gpu/drm/radeon/evergreen_reg.h        |   12 +
 drivers/gpu/drm/radeon/evergreen_smc.h        |   67 +
 drivers/gpu/drm/radeon/evergreend.h           |  389 ++-
 drivers/gpu/drm/radeon/ni.c                   |  198 +-
 drivers/gpu/drm/radeon/ni_dpm.c               | 4288 +++++++++++++++
 drivers/gpu/drm/radeon/ni_dpm.h               |  248 +
 drivers/gpu/drm/radeon/nid.h                  |  561 ++
 drivers/gpu/drm/radeon/nislands_smc.h         |  329 ++
 drivers/gpu/drm/radeon/ppsmc.h                |  110 +
 drivers/gpu/drm/radeon/r600.c                 |  147 +-
 drivers/gpu/drm/radeon/r600_dpm.c             | 1024 ++++
 drivers/gpu/drm/radeon/r600_dpm.h             |  226 +
 drivers/gpu/drm/radeon/r600_hdmi.c            |   11 +-
 drivers/gpu/drm/radeon/r600_reg.h             |    6 +
 drivers/gpu/drm/radeon/r600d.h                |  232 +-
 drivers/gpu/drm/radeon/radeon.h               |  517 ++-
 drivers/gpu/drm/radeon/radeon_acpi.c          |  145 +
 drivers/gpu/drm/radeon/radeon_asic.c          |  524 ++-
 drivers/gpu/drm/radeon/radeon_asic.h          |  166 +
 drivers/gpu/drm/radeon/radeon_atombios.c      |  880 +++-
 drivers/gpu/drm/radeon/radeon_cs.c            |    1 +
 drivers/gpu/drm/radeon/radeon_cursor.c        |   10 +-
 drivers/gpu/drm/radeon/radeon_device.c        |  106 +-
 drivers/gpu/drm/radeon/radeon_display.c       |   21 +-
 drivers/gpu/drm/radeon/radeon_drv.c           |    7 +-
 drivers/gpu/drm/radeon/radeon_family.h        |    3 +
 drivers/gpu/drm/radeon/radeon_irq_kms.c       |   20 +
 drivers/gpu/drm/radeon/radeon_kms.c           |   41 +-
 drivers/gpu/drm/radeon/radeon_mode.h          |   93 +
 drivers/gpu/drm/radeon/radeon_pm.c            |  610 ++-
 drivers/gpu/drm/radeon/radeon_reg.h           |    1 +
 drivers/gpu/drm/radeon/radeon_ring.c          |   55 +-
 drivers/gpu/drm/radeon/radeon_ucode.h         |  129 +
 drivers/gpu/drm/radeon/radeon_uvd.c           |   32 +-
 drivers/gpu/drm/radeon/rs690.c                |  291 +-
 drivers/gpu/drm/radeon/rs780_dpm.c            |  963 ++++
 drivers/gpu/drm/radeon/rs780_dpm.h            |  109 +
 drivers/gpu/drm/radeon/rs780d.h               |  168 +
 drivers/gpu/drm/radeon/rv515.c                |  224 +-
 drivers/gpu/drm/radeon/rv6xx_dpm.c            | 2059 ++++++++
 drivers/gpu/drm/radeon/rv6xx_dpm.h            |   95 +
 drivers/gpu/drm/radeon/rv6xxd.h               |  246 +
 drivers/gpu/drm/radeon/rv730_dpm.c            |  508 ++
 drivers/gpu/drm/radeon/rv730d.h               |  165 +
 drivers/gpu/drm/radeon/rv740_dpm.c            |  416 ++
 drivers/gpu/drm/radeon/rv740d.h               |  117 +
 drivers/gpu/drm/radeon/rv770_dpm.c            | 2446 +++++++++
 drivers/gpu/drm/radeon/rv770_dpm.h            |  287 +
 drivers/gpu/drm/radeon/rv770_smc.c            |  621 +++
 drivers/gpu/drm/radeon/rv770_smc.h            |  209 +
 drivers/gpu/drm/radeon/rv770d.h               |  279 +-
 drivers/gpu/drm/radeon/si.c                   | 1337 +++++-
 drivers/gpu/drm/radeon/si_dpm.c               | 6369 ++++++++++++++++++++++
 drivers/gpu/drm/radeon/si_dpm.h               |  227 +
 drivers/gpu/drm/radeon/si_smc.c               |  284 +
 drivers/gpu/drm/radeon/sid.h                  |  599 ++-
 drivers/gpu/drm/radeon/sislands_smc.h         |  397 ++
 drivers/gpu/drm/radeon/sumo_dpm.c             | 1801 +++++++
 drivers/gpu/drm/radeon/sumo_dpm.h             |  220 +
 drivers/gpu/drm/radeon/sumo_smc.c             |  222 +
 drivers/gpu/drm/radeon/sumod.h                |  372 ++
 drivers/gpu/drm/radeon/trinity_dpm.c          | 1887 +++++++
 drivers/gpu/drm/radeon/trinity_dpm.h          |  131 +
 drivers/gpu/drm/radeon/trinity_smc.c          |  115 +
 drivers/gpu/drm/radeon/trinityd.h             |  228 +
 include/drm/drm_fixed.h                       |   96 +
 include/drm/drm_pciids.h                      |   24 +
 88 files changed, 52708 insertions(+), 561 deletions(-)
 create mode 100644 drivers/gpu/drm/radeon/btc_dpm.c
 create mode 100644 drivers/gpu/drm/radeon/btc_dpm.h
 create mode 100644 drivers/gpu/drm/radeon/btcd.h
 create mode 100644 drivers/gpu/drm/radeon/cik.c
 create mode 100644 drivers/gpu/drm/radeon/cik_blit_shaders.c
 create mode 100644 drivers/gpu/drm/radeon/cik_blit_shaders.h
 create mode 100644 drivers/gpu/drm/radeon/cik_reg.h
 create mode 100644 drivers/gpu/drm/radeon/cikd.h
 create mode 100644 drivers/gpu/drm/radeon/clearstate_cayman.h
 create mode 100644 drivers/gpu/drm/radeon/clearstate_defs.h
 create mode 100644 drivers/gpu/drm/radeon/clearstate_evergreen.h
 create mode 100644 drivers/gpu/drm/radeon/clearstate_si.h
 create mode 100644 drivers/gpu/drm/radeon/cypress_dpm.c
 create mode 100644 drivers/gpu/drm/radeon/cypress_dpm.h
 create mode 100644 drivers/gpu/drm/radeon/evergreen_smc.h
 create mode 100644 drivers/gpu/drm/radeon/ni_dpm.c
 create mode 100644 drivers/gpu/drm/radeon/ni_dpm.h
 create mode 100644 drivers/gpu/drm/radeon/nislands_smc.h
 create mode 100644 drivers/gpu/drm/radeon/ppsmc.h
 create mode 100644 drivers/gpu/drm/radeon/r600_dpm.c
 create mode 100644 drivers/gpu/drm/radeon/r600_dpm.h
 create mode 100644 drivers/gpu/drm/radeon/radeon_ucode.h
 create mode 100644 drivers/gpu/drm/radeon/rs780_dpm.c
 create mode 100644 drivers/gpu/drm/radeon/rs780_dpm.h
 create mode 100644 drivers/gpu/drm/radeon/rs780d.h
 create mode 100644 drivers/gpu/drm/radeon/rv6xx_dpm.c
 create mode 100644 drivers/gpu/drm/radeon/rv6xx_dpm.h
 create mode 100644 drivers/gpu/drm/radeon/rv6xxd.h
 create mode 100644 drivers/gpu/drm/radeon/rv730_dpm.c
 create mode 100644 drivers/gpu/drm/radeon/rv730d.h
 create mode 100644 drivers/gpu/drm/radeon/rv740_dpm.c
 create mode 100644 drivers/gpu/drm/radeon/rv740d.h
 create mode 100644 drivers/gpu/drm/radeon/rv770_dpm.c
 create mode 100644 drivers/gpu/drm/radeon/rv770_dpm.h
 create mode 100644 drivers/gpu/drm/radeon/rv770_smc.c
 create mode 100644 drivers/gpu/drm/radeon/rv770_smc.h
 create mode 100644 drivers/gpu/drm/radeon/si_dpm.c
 create mode 100644 drivers/gpu/drm/radeon/si_dpm.h
 create mode 100644 drivers/gpu/drm/radeon/si_smc.c
 create mode 100644 drivers/gpu/drm/radeon/sislands_smc.h
 create mode 100644 drivers/gpu/drm/radeon/sumo_dpm.c
 create mode 100644 drivers/gpu/drm/radeon/sumo_dpm.h
 create mode 100644 drivers/gpu/drm/radeon/sumo_smc.c
 create mode 100644 drivers/gpu/drm/radeon/sumod.h
 create mode 100644 drivers/gpu/drm/radeon/trinity_dpm.c
 create mode 100644 drivers/gpu/drm/radeon/trinity_dpm.h
 create mode 100644 drivers/gpu/drm/radeon/trinity_smc.c
 create mode 100644 drivers/gpu/drm/radeon/trinityd.h
Signature · 6 lines
1.7.7.5

_______________________________________________
dri-devel mailing list
[email protected]
http://lists.freedesktop.org/mailman/listinfo/dri-devel
#128 lore raw

cover radeon drm-next patches

In reply to [email protected]

Hi,

I just tried the DPM support out on a E-450 APU (HD6320) and it did not work like expected. In the terminal everything seemed ok but when I started a display manager, the screen showed garbage and the system basically locked up. The radeon and drm related parts of the syslog are below.

If you need further information, feel free to ask.

Best regards,
Julian Wollrath

[   14.926970] [drm] Initialized drm 1.1.0 20060810
[   15.607011] [drm] radeon kernel modesetting enabled.
[   15.608158] [drm] initializing kernel modesetting (PALM 0x1002:0x9806 0x17AA:0x21EC).
[   15.608242] [drm] register mmio base: 0xF0300000
[   15.608247] [drm] register mmio size: 262144
[   15.608438] ATOM BIOS: Lenovo
[   15.608544] radeon 0000:00:01.0: VRAM: 384M 0x0000000000000000 - 0x0000000017FFFFFF (384M used)
[   15.608554] radeon 0000:00:01.0: GTT: 512M 0x0000000018000000 - 0x0000000037FFFFFF
[   15.609062] [drm] Detected VRAM RAM=384M, BAR=256M
[   15.609077] [drm] RAM width 32bits DDR
[   15.609442] [TTM] Zone  kernel: Available graphics memory: 1821260 kiB
[   15.609453] [TTM] Initializing pool allocator
[   15.609469] [TTM] Initializing DMA pool allocator
[   15.609553] [drm] radeon: 384M of VRAM memory ready
[   15.609560] [drm] radeon: 512M of GTT memory ready.
[   15.785368] radeon 0000:00:01.0: ffff880119401000 unpin not necessary
[   15.911347] radeon 0000:00:01.0: fence driver on ring 5 use gpu addr 0x0000000000072118 and cpu addr 0xffffc90002ce6118
[   15.911374] [drm] GART: num cpu pages 131072, num gpu pages 131072
[   15.915577] [drm] Loading PALM Microcode
[   16.354967] [drm] PCIE GART of 512M enabled (table at 0x0000000000040000).
[   16.355272] radeon 0000:00:01.0: WB enabled
[   16.355287] radeon 0000:00:01.0: fence driver on ring 0 use gpu addr 0x0000000018000c00 and cpu addr 0xffff880115f44c00
[   16.355297] radeon 0000:00:01.0: fence driver on ring 3 use gpu addr 0x0000000018000c0c and cpu addr 0xffff880115f44c0c
[   16.359306] radeon 0000:00:01.0: fence driver on ring 5 use gpu addr 0x0000000000177118 and cpu addr 0xffffc90003032118
[   16.359326] [drm] Supports vblank timestamp caching Rev 1 (10.10.2010).
[   16.359330] [drm] Driver supports precise vblank timestamp query.
[   16.359391] radeon 0000:00:01.0: irq 46 for MSI/MSI-X
[   16.359432] radeon 0000:00:01.0: radeon: using MSI.
[   16.359528] [drm] radeon: irq initialized.
[   16.379053] [drm] ring test on 0 succeeded in 1 usecs
[   16.379120] [drm] ring test on 3 succeeded in 1 usecs
[   16.434367] [drm] ring test on 5 succeeded in 1 usecs
[   16.434384] [drm] UVD initialized successfully.
[   16.455934] [drm] ib test on ring 0 succeeded in 0 usecs
[   16.455984] [drm] ib test on ring 3 succeeded in 0 usecs
[   16.476866] [drm] ib test on ring 5 succeeded
[   16.549696] [drm] radeon atom DIG backlight initialized
[   16.549718] [drm] Radeon Display Connectors
[   16.549724] [drm] Connector 0:
[   16.549731] [drm]   LVDS-1
[   16.549736] [drm]   HPD1
[   16.549744] [drm]   DDC: 0x6430 0x6430 0x6434 0x6434 0x6438 0x6438 0x643c 0x643c
[   16.549748] [drm]   Encoders:
[   16.549753] [drm]     LCD1: INTERNAL_UNIPHY
[   16.549757] [drm] Connector 1:
[   16.549762] [drm]   HDMI-A-1
[   16.549766] [drm]   HPD2
[   16.549773] [drm]   DDC: 0x6440 0x6440 0x6444 0x6444 0x6448 0x6448 0x644c 0x644c
[   16.549776] [drm]   Encoders:
[   16.549780] [drm]     DFP1: INTERNAL_UNIPHY
[   16.549784] [drm] Connector 2:
[   16.549788] [drm]   VGA-1
[   16.549795] [drm]   DDC: 0x64d8 0x64d8 0x64dc 0x64dc 0x64e0 0x64e0 0x64e4 0x64e4
[   16.549799] [drm]   Encoders:
[   16.549803] [drm]     CRT1: INTERNAL_KLDSCP_DAC1
[   16.549900] [drm] Internal thermal controller without fan control
[   16.550073] == power state 0 ==
[   16.550079] 	ui class: none
[   16.550085] 	internal class: uvd_hd 
[   16.550091] 	caps: 
[   16.550096] 	uvd    vclk: 38824 dclk: 30000
[   16.550102] 		power level 0    sclk: 27500 vddc: 875
[   16.550106] 	status: 
[   16.550110] == power state 1 ==
[   16.550113] 	ui class: none
[   16.550117] 	internal class: uvd 
[   16.550122] 	caps: 
[   16.550127] 	uvd    vclk: 55000 dclk: 41250
[   16.550132] 		power level 0    sclk: 50770 vddc: 950
[   16.550135] 	status: 
[   16.550139] == power state 2 ==
[   16.550142] 	ui class: battery
[   16.550146] 	internal class: none
[   16.550151] 	caps: 
[   16.550155] 	uvd    vclk: 0 dclk: 0
[   16.550160] 		power level 0    sclk: 27500 vddc: 875
[   16.550163] 	status: 
[   16.550167] == power state 3 ==
[   16.550170] 	ui class: performance
[   16.550174] 	internal class: none
[   16.550179] 	caps: 
[   16.550184] 	uvd    vclk: 0 dclk: 0
[   16.550188] 		power level 0    sclk: 27500 vddc: 875
[   16.550193] 		power level 1    sclk: 50770 vddc: 950
[   16.550196] 	status: 
[   16.550200] == power state 4 ==
[   16.550203] 	ui class: none
[   16.550207] 	internal class: boot 
[   16.550212] 	caps: 
[   16.550216] 	uvd    vclk: 0 dclk: 0
[   16.550221] 		power level 0    sclk: 20000 vddc: 975
[   16.550224] 	status: c r b 
[   16.550232] == power state 5 ==
[   16.550235] 	ui class: none
[   16.550239] 	internal class: thermal 
[   16.550243] 	caps: 
[   16.550248] 	uvd    vclk: 0 dclk: 0
[   16.550252] 		power level 0    sclk: 17369 vddc: 875
[   16.550255] 	status: 
[   16.550263] [drm] Found smc ucode version: 0x00010601
[   16.576523] switching from power state:
[   16.576539] 	ui class: none
[   16.576545] 	internal class: boot 
[   16.576551] 	caps: 
[   16.576557] 	uvd    vclk: 0 dclk: 0
[   16.576565] 		power level 0    sclk: 20000 vddc: 975
[   16.576569] 	status: c b 
[   16.576575] switching to power state:
[   16.576578] 	ui class: performance
[   16.576582] 	internal class: none
[   16.576588] 	caps: 
[   16.576592] 	uvd    vclk: 0 dclk: 0
[   16.576598] 		power level 0    sclk: 27500 vddc: 875
[   16.576603] 		power level 1    sclk: 50770 vddc: 950
[   16.576606] 	status: r 
[   16.576735] [drm] radeon: dpm initialized
[   17.000309] [drm] fb mappable at 0xE0378000
[   17.000317] [drm] vram apper at 0xE0000000
[   17.000319] [drm] size 4325376
[   17.000322] [drm] fb depth is 24
[   17.000324] [drm]    pitch is 5632
[   17.000438] fbcon: radeondrmfb (fb0) is primary device
[   17.563999] Console: switching to colour frame buffer device 170x48
[   17.577133] radeon 0000:00:01.0: fb0: radeondrmfb frame buffer device
[   17.577141] radeon 0000:00:01.0: registered panic notifier
[   17.577820] [drm] Initialized radeon 2.34.0 20080528 for 0000:00:01.0 on minor 0
[  159.318231] radeon 0000:00:01.0: GPU lockup CP stall for more than 10000msec
[  159.318252] radeon 0000:00:01.0: GPU lockup (waiting for 0x0000000000000004 last fence id 0x0000000000000001)
[  159.369796] radeon 0000:00:01.0: fence driver on ring 5 use gpu addr 0x0000000000177118 and cpu addr 0xffffc9000301b118
[  159.370844] radeon 0000:00:01.0: Saved 87 dwords of commands on ring 0.
[  159.370856] radeon 0000:00:01.0: GPU softreset: 0x00000009
[  159.370861] radeon 0000:00:01.0:   GRBM_STATUS               = 0xB2433828
[  159.370865] radeon 0000:00:01.0:   GRBM_STATUS_SE0           = 0x08000007
[  159.370869] radeon 0000:00:01.0:   GRBM_STATUS_SE1           = 0x00000007
[  159.370872] radeon 0000:00:01.0:   SRBM_STATUS               = 0x20000040
[  159.370876] radeon 0000:00:01.0:   SRBM_STATUS2              = 0x00000000
[  159.370880] radeon 0000:00:01.0:   R_008674_CP_STALLED_STAT1 = 0x00000000
[  159.370884] radeon 0000:00:01.0:   R_008678_CP_STALLED_STAT2 = 0x40000000
[  159.370888] radeon 0000:00:01.0:   R_00867C_CP_BUSY_STAT     = 0x00008000
[  159.370891] radeon 0000:00:01.0:   R_008680_CP_STAT          = 0x80228643
[  159.370895] radeon 0000:00:01.0:   R_00D034_DMA_STATUS_REG   = 0x44C83D57
[  159.386016] radeon 0000:00:01.0: GRBM_SOFT_RESET=0x00007F6B
[  159.386093] radeon 0000:00:01.0: SRBM_SOFT_RESET=0x00000100
[  159.387279] radeon 0000:00:01.0:   GRBM_STATUS               = 0x00003828
[  159.387282] radeon 0000:00:01.0:   GRBM_STATUS_SE0           = 0x00000007
[  159.387286] radeon 0000:00:01.0:   GRBM_STATUS_SE1           = 0x00000007
[  159.387289] radeon 0000:00:01.0:   SRBM_STATUS               = 0x20000040
[  159.387293] radeon 0000:00:01.0:   SRBM_STATUS2              = 0x00000000
[  159.387296] radeon 0000:00:01.0:   R_008674_CP_STALLED_STAT1 = 0x00000000
[  159.387300] radeon 0000:00:01.0:   R_008678_CP_STALLED_STAT2 = 0x00000000
[  159.387303] radeon 0000:00:01.0:   R_00867C_CP_BUSY_STAT     = 0x00000000
[  159.387307] radeon 0000:00:01.0:   R_008680_CP_STAT          = 0x00000000
[  159.387310] radeon 0000:00:01.0:   R_00D034_DMA_STATUS_REG   = 0x44C83D57
[  159.387316] radeon 0000:00:01.0: GPU reset succeeded, trying to resume
[  159.407287] [drm] PCIE GART of 512M enabled (table at 0x0000000000040000).
[  159.407562] radeon 0000:00:01.0: WB enabled
[  159.407576] radeon 0000:00:01.0: fence driver on ring 0 use gpu addr 0x0000000018000c00 and cpu addr 0xffff880115f44c00
[  159.407587] radeon 0000:00:01.0: fence driver on ring 3 use gpu addr 0x0000000018000c0c and cpu addr 0xffff880115f44c0c
[  159.410849] radeon 0000:00:01.0: fence driver on ring 5 use gpu addr 0x0000000000177118 and cpu addr 0xffffc90003eb2118
[  159.427563] [drm] ring test on 0 succeeded in 1 usecs
[  159.427634] [drm] ring test on 3 succeeded in 1 usecs
[  159.472928] [drm] ring test on 5 succeeded in 1 usecs
[  159.472958] [drm] UVD initialized successfully.
[  164.422044] SysRq : Keyboard mode set to system default
[  164.646822] SysRq : Terminate All Tasks
[   14.301299] [drm] Initialized drm 1.1.0 20060810
[   14.906930] [drm] radeon kernel modesetting enabled.
[   14.975218] [drm] initializing kernel modesetting (PALM 0x1002:0x9806 0x17AA:0x21EC).
[   14.975271] [drm] register mmio base: 0xF0300000
[   14.975273] [drm] register mmio size: 262144
[   14.975377] ATOM BIOS: Lenovo
[   14.975453] radeon 0000:00:01.0: VRAM: 384M 0x0000000000000000 - 0x0000000017FFFFFF (384M used)
[   14.975459] radeon 0000:00:01.0: GTT: 512M 0x0000000018000000 - 0x0000000037FFFFFF
[   14.975657] [drm] Detected VRAM RAM=384M, BAR=256M
[   14.975667] [drm] RAM width 32bits DDR
[   14.976352] [TTM] Zone  kernel: Available graphics memory: 1821260 kiB
[   14.976356] [TTM] Initializing pool allocator
[   14.976364] [TTM] Initializing DMA pool allocator
[   14.976404] [drm] radeon: 384M of VRAM memory ready
[   14.976408] [drm] radeon: 512M of GTT memory ready.
[   15.719064] radeon 0000:00:01.0: ffff8801196f1800 unpin not necessary
[   15.856057] radeon 0000:00:01.0: fence driver on ring 5 use gpu addr 0x0000000000072118 and cpu addr 0xffffc90002ce6118
[   15.856075] [drm] GART: num cpu pages 131072, num gpu pages 131072
[   15.858815] [drm] Loading PALM Microcode
[   16.363243] [drm] PCIE GART of 512M enabled (table at 0x0000000000040000).
[   16.363537] radeon 0000:00:01.0: WB enabled
[   16.363545] radeon 0000:00:01.0: fence driver on ring 0 use gpu addr 0x0000000018000c00 and cpu addr 0xffff880115f8bc00
[   16.363550] radeon 0000:00:01.0: fence driver on ring 3 use gpu addr 0x0000000018000c0c and cpu addr 0xffff880115f8bc0c
[   16.365611] radeon 0000:00:01.0: fence driver on ring 5 use gpu addr 0x0000000000177118 and cpu addr 0xffffc90002ab2118
[   16.365623] [drm] Supports vblank timestamp caching Rev 1 (10.10.2010).
[   16.365626] [drm] Driver supports precise vblank timestamp query.
[   16.365666] radeon 0000:00:01.0: irq 46 for MSI/MSI-X
[   16.365692] radeon 0000:00:01.0: radeon: using MSI.
[   16.365733] [drm] radeon: irq initialized.
[   16.383123] [drm] ring test on 0 succeeded in 1 usecs
[   16.383199] [drm] ring test on 3 succeeded in 1 usecs
[   16.438468] [drm] ring test on 5 succeeded in 1 usecs
[   16.438479] [drm] UVD initialized successfully.
[   16.459644] [drm] ib test on ring 0 succeeded in 0 usecs
[   16.459693] [drm] ib test on ring 3 succeeded in 0 usecs
[   16.480537] [drm] ib test on ring 5 succeeded
[   16.556037] [drm] radeon atom DIG backlight initialized
[   16.556058] [drm] Radeon Display Connectors
[   16.556064] [drm] Connector 0:
[   16.556072] [drm]   LVDS-1
[   16.556077] [drm]   HPD1
[   16.556085] [drm]   DDC: 0x6430 0x6430 0x6434 0x6434 0x6438 0x6438 0x643c 0x643c
[   16.556089] [drm]   Encoders:
[   16.556094] [drm]     LCD1: INTERNAL_UNIPHY
[   16.556099] [drm] Connector 1:
[   16.556104] [drm]   HDMI-A-1
[   16.556107] [drm]   HPD2
[   16.556114] [drm]   DDC: 0x6440 0x6440 0x6444 0x6444 0x6448 0x6448 0x644c 0x644c
[   16.556118] [drm]   Encoders:
[   16.556122] [drm]     DFP1: INTERNAL_UNIPHY
[   16.556126] [drm] Connector 2:
[   16.556131] [drm]   VGA-1
[   16.556137] [drm]   DDC: 0x64d8 0x64d8 0x64dc 0x64dc 0x64e0 0x64e0 0x64e4 0x64e4
[   16.556141] [drm]   Encoders:
[   16.556145] [drm]     CRT1: INTERNAL_KLDSCP_DAC1
[   16.556242] [drm] Internal thermal controller without fan control
[   16.556392] == power state 0 ==
[   16.556398] 	ui class: none
[   16.556404] 	internal class: uvd_hd 
[   16.556410] 	caps: 
[   16.556416] 	uvd    vclk: 38824 dclk: 30000
[   16.556422] 		power level 0    sclk: 27500 vddc: 875
[   16.556425] 	status: 
[   16.556430] == power state 1 ==
[   16.556433] 	ui class: none
[   16.556437] 	internal class: uvd 
[   16.556442] 	caps: 
[   16.556447] 	uvd    vclk: 55000 dclk: 41250
[   16.556452] 		power level 0    sclk: 50770 vddc: 950
[   16.556455] 	status: 
[   16.556459] == power state 2 ==
[   16.556462] 	ui class: battery
[   16.556466] 	internal class: none
[   16.556471] 	caps: 
[   16.556475] 	uvd    vclk: 0 dclk: 0
[   16.556480] 		power level 0    sclk: 27500 vddc: 875
[   16.556483] 	status: 
[   16.556487] == power state 3 ==
[   16.556491] 	ui class: performance
[   16.556494] 	internal class: none
[   16.556499] 	caps: 
[   16.556504] 	uvd    vclk: 0 dclk: 0
[   16.556509] 		power level 0    sclk: 27500 vddc: 875
[   16.556514] 		power level 1    sclk: 50770 vddc: 950
[   16.556517] 	status: 
[   16.556521] == power state 4 ==
[   16.556524] 	ui class: none
[   16.556528] 	internal class: boot 
[   16.556533] 	caps: 
[   16.556537] 	uvd    vclk: 0 dclk: 0
[   16.556542] 		power level 0    sclk: 20000 vddc: 975
[   16.556545] 	status: c r b 
[   16.556553] == power state 5 ==
[   16.556556] 	ui class: none
[   16.556560] 	internal class: thermal 
[   16.556564] 	caps: 
[   16.556569] 	uvd    vclk: 0 dclk: 0
[   16.556574] 		power level 0    sclk: 17369 vddc: 875
[   16.556577] 	status: 
[   16.556584] [drm] Found smc ucode version: 0x00010601
[   16.577725] switching from power state:
[   16.577737] 	ui class: none
[   16.577740] 	internal class: boot 
[   16.577744] 	caps: 
[   16.577747] 	uvd    vclk: 0 dclk: 0
[   16.577751] 		power level 0    sclk: 20000 vddc: 975
[   16.577753] 	status: c b 
[   16.577757] switching to power state:
[   16.577758] 	ui class: performance
[   16.577760] 	internal class: none
[   16.577763] 	caps: 
[   16.577765] 	uvd    vclk: 0 dclk: 0
[   16.577768] 		power level 0    sclk: 27500 vddc: 875
[   16.577771] 		power level 1    sclk: 50770 vddc: 950
[   16.577772] 	status: r 
[   16.577868] [drm] radeon: dpm initialized
[   16.694706] ieee80211 phy0: Selected rate control algorithm 'iwl-agn-rs'
[   16.997044] [drm] fb mappable at 0xE0378000
[   16.997057] [drm] vram apper at 0xE0000000
[   16.997062] [drm] size 4325376
[   16.997067] [drm] fb depth is 24
[   16.997072] [drm]    pitch is 5632
[   16.997267] fbcon: radeondrmfb (fb0) is primary device
[   17.565597] Console: switching to colour frame buffer device 170x48
[   17.578692] radeon 0000:00:01.0: fb0: radeondrmfb frame buffer device
[   17.578701] radeon 0000:00:01.0: registered panic notifier
[   17.579385] [drm] Initialized radeon 2.34.0 20080528 for 0000:00:01.0 on minor 0
[  195.823063] radeon 0000:00:01.0: GPU lockup CP stall for more than 10000msec
[  195.827260] radeon 0000:00:01.0: GPU lockup (waiting for 0x0000000000000004 last fence id 0x0000000000000001)
[  195.879857] radeon 0000:00:01.0: fence driver on ring 5 use gpu addr 0x0000000000177118 and cpu addr 0xffffc90002832118
[  195.880922] radeon 0000:00:01.0: Saved 87 dwords of commands on ring 0.
[  195.880935] radeon 0000:00:01.0: GPU softreset: 0x00000009
[  195.880941] radeon 0000:00:01.0:   GRBM_STATUS               = 0xB2433828
[  195.880946] radeon 0000:00:01.0:   GRBM_STATUS_SE0           = 0x08000007
[  195.880951] radeon 0000:00:01.0:   GRBM_STATUS_SE1           = 0x00000007
[  195.880956] radeon 0000:00:01.0:   SRBM_STATUS               = 0x20000040
[  195.880960] radeon 0000:00:01.0:   SRBM_STATUS2              = 0x00000000
[  195.880965] radeon 0000:00:01.0:   R_008674_CP_STALLED_STAT1 = 0x00000000
[  195.880970] radeon 0000:00:01.0:   R_008678_CP_STALLED_STAT2 = 0x40000000
[  195.880974] radeon 0000:00:01.0:   R_00867C_CP_BUSY_STAT     = 0x00008000
[  195.880979] radeon 0000:00:01.0:   R_008680_CP_STAT          = 0x80228643
[  195.880983] radeon 0000:00:01.0:   R_00D034_DMA_STATUS_REG   = 0x44C83D57
[  195.895865] radeon 0000:00:01.0: GRBM_SOFT_RESET=0x00007F6B
[  195.895921] radeon 0000:00:01.0: SRBM_SOFT_RESET=0x00000100
[  195.897108] radeon 0000:00:01.0:   GRBM_STATUS               = 0x00003828
[  195.897113] radeon 0000:00:01.0:   GRBM_STATUS_SE0           = 0x00000007
[  195.897117] radeon 0000:00:01.0:   GRBM_STATUS_SE1           = 0x00000007
[  195.897121] radeon 0000:00:01.0:   SRBM_STATUS               = 0x20000040
[  195.897126] radeon 0000:00:01.0:   SRBM_STATUS2              = 0x00000000
[  195.897130] radeon 0000:00:01.0:   R_008674_CP_STALLED_STAT1 = 0x00000000
[  195.897134] radeon 0000:00:01.0:   R_008678_CP_STALLED_STAT2 = 0x00000000
[  195.897138] radeon 0000:00:01.0:   R_00867C_CP_BUSY_STAT     = 0x00000000
[  195.897143] radeon 0000:00:01.0:   R_008680_CP_STAT          = 0x00000000
[  195.897147] radeon 0000:00:01.0:   R_00D034_DMA_STATUS_REG   = 0x44C83D57
[  195.897154] radeon 0000:00:01.0: GPU reset succeeded, trying to resume
[  195.917323] [drm] PCIE GART of 512M enabled (table at 0x0000000000040000).
[  195.917553] radeon 0000:00:01.0: WB enabled
[  195.917567] radeon 0000:00:01.0: fence driver on ring 0 use gpu addr 0x0000000018000c00 and cpu addr 0xffff880115f8bc00
[  195.917578] radeon 0000:00:01.0: fence driver on ring 3 use gpu addr 0x0000000018000c0c and cpu addr 0xffff880115f8bc0c
[  195.920890] radeon 0000:00:01.0: fence driver on ring 5 use gpu addr 0x0000000000177118 and cpu addr 0xffffc90003c32118
[  195.937779] [drm] ring test on 0 succeeded in 1 usecs
[  195.937858] [drm] ring test on 3 succeeded in 1 usecs
[  195.983131] [drm] ring test on 5 succeeded in 1 usecs
[  195.983148] [drm] UVD initialized successfully.
[  206.009333] radeon 0000:00:01.0: GPU lockup CP stall for more than 10000msec
[  206.013681] radeon 0000:00:01.0: GPU lockup (waiting for 0x0000000000000005 last fence id 0x0000000000000001)
[  206.013692] [drm:r600_ib_test] *ERROR* radeon: fence wait failed (-35).
[  206.018028] [drm:radeon_ib_ring_tests] *ERROR* radeon: failed testing IB on GFX ring (-35).
[  206.022364] radeon 0000:00:01.0: ib ring test failed (-35).
[  206.075249] radeon 0000:00:01.0: fence driver on ring 5 use gpu addr 0x0000000000177118 and cpu addr 0xffffc90002832118
[  206.076352] radeon 0000:00:01.0: GPU softreset: 0x00000009
[  206.076362] radeon 0000:00:01.0:   GRBM_STATUS               = 0xB3533828
[  206.076370] radeon 0000:00:01.0:   GRBM_STATUS_SE0           = 0x2C000007
[  206.076378] radeon 0000:00:01.0:   GRBM_STATUS_SE1           = 0x00000007
[  206.076386] radeon 0000:00:01.0:   SRBM_STATUS               = 0x20000040
[  206.076393] radeon 0000:00:01.0:   SRBM_STATUS2              = 0x00000000
[  206.076401] radeon 0000:00:01.0:   R_008674_CP_STALLED_STAT1 = 0x00000000
[  206.076408] radeon 0000:00:01.0:   R_008678_CP_STALLED_STAT2 = 0x400C0000
[  206.076415] radeon 0000:00:01.0:   R_00867C_CP_BUSY_STAT     = 0x00048000
[  206.076422] radeon 0000:00:01.0:   R_008680_CP_STAT          = 0x80268643
[  206.076429] radeon 0000:00:01.0:   R_00D034_DMA_STATUS_REG   = 0x44C83D57
[  206.076620] radeon 0000:00:01.0: GRBM_SOFT_RESET=0x00007F6B
[  206.076678] radeon 0000:00:01.0: SRBM_SOFT_RESET=0x00000100
[  206.077871] radeon 0000:00:01.0:   GRBM_STATUS               = 0x00003828
[  206.077878] radeon 0000:00:01.0:   GRBM_STATUS_SE0           = 0x00000007
[  206.077885] radeon 0000:00:01.0:   GRBM_STATUS_SE1           = 0x00000007
[  206.077892] radeon 0000:00:01.0:   SRBM_STATUS               = 0x20000040
[  206.077899] radeon 0000:00:01.0:   SRBM_STATUS2              = 0x00000000
[  206.077905] radeon 0000:00:01.0:   R_008674_CP_STALLED_STAT1 = 0x00000000
[  206.077912] radeon 0000:00:01.0:   R_008678_CP_STALLED_STAT2 = 0x00000000
[  206.077919] radeon 0000:00:01.0:   R_00867C_CP_BUSY_STAT     = 0x00000000
[  206.077926] radeon 0000:00:01.0:   R_008680_CP_STAT          = 0x00000000
[  206.077932] radeon 0000:00:01.0:   R_00D034_DMA_STATUS_REG   = 0x44C83D57
[  206.077943] radeon 0000:00:01.0: GPU reset succeeded, trying to resume
[  206.082896] [drm] PCIE GART of 512M enabled (table at 0x0000000000040000).
[  206.083120] radeon 0000:00:01.0: WB enabled
[  206.083134] radeon 0000:00:01.0: fence driver on ring 0 use gpu addr 0x0000000018000c00 and cpu addr 0xffff880115f8bc00
[  206.083143] radeon 0000:00:01.0: fence driver on ring 3 use gpu addr 0x0000000018000c0c and cpu addr 0xffff880115f8bc0c
[  206.086489] radeon 0000:00:01.0: fence driver on ring 5 use gpu addr 0x0000000000177118 and cpu addr 0xffffc90003c32118
[  206.103118] [drm] ring test on 0 succeeded in 1 usecs
[  206.103188] [drm] ring test on 3 succeeded in 1 usecs
[  206.148514] [drm] ring test on 5 succeeded in 1 usecs
[  206.148531] [drm] UVD initialized successfully.
[  206.867862] SysRq : Keyboard mode set to system default
[  207.151608] SysRq : Terminate All Tasks
#129 lore raw

Hi,

Quoted 5 lines

I just tried the DPM support out on a E-450 APU (HD6320) and it did not work like expected. In the terminal everything seemed ok but when I started a display manager, the screen showed garbage and the system basically locked up. The radeon and drm related parts of the syslog are below.

I saw, that you updated the patches, therefore I tried out the branch drm-next-3.11-wip-2 and I got, additionally to the problem mentioned in my first e-mail, the following warning:

[   14.274349] ------------[ cut here ]------------
[   14.274369] WARNING: at kernel/workqueue.c:1365 __queue_work+0x260/0x2c0()
[   14.274374] Modules linked in: bluetooth crc16 acpi_cpufreq snd_hda_codec_hdmi iwlwifi uvcvideo mperf radeon(+) videobuf2_vmalloc cfg80211 snd_hda_intel(+) battery processor button thinkpad_acpi video nvram rfkill videobuf2_memops videobuf2_core videodev snd_hda_codec kvm_amd i2c_algo_bit kvm snd_hwdep snd_pcm snd_timer snd_page_alloc ac drm_kms_helper ttm snd drm soundcore wmi i2c_piix4 agpgart pcspkr i2c_core evdev k10temp psmouse serio_raw sha256_ssse3 sha256_generic twofish_x86_64_3way glue_helper xts lrw gf128mul twofish_x86_64 twofish_common cbc dm_crypt dm_mod sd_mod crc_t10dif rtsx_pci_sdmmc mmc_core microcode thermal thermal_sys ahci libahci ohci_hcd ehci_pci ehci_hcd rtsx_pci mfd_core usbcore usb_common libata scsi_mod
[   14.274517] CPU: 1 PID: 497 Comm: modprobe Not tainted 3.10.0-rc7-wl+ #3
[   14.274524] Hardware name: LENOVO 30515YG/30515YG, BIOS 8RET52WW (1.15 ) 11/15/2011
[   14.274530]  ffffffff813fc83e ffffffff81037a7a ffff88011ec12540 ffff88011ed15d00
[   14.274539]  ffff8801164a5bc8 0000000000000002 ffff88011e060a00 ffffffff81053590
[   14.274548]  0000000000000002 ffff8801164a5e9c 0000000000000001 0000000000000010
[   14.274558] Call Trace:
[   14.274563]  <IRQ>  [<ffffffff813fc83e>] ? dump_stack+0xc/0x15
[   14.274582]  [<ffffffff81037a7a>] ? warn_slowpath_common+0x6a/0xa0
[   14.274594]  [<ffffffff81053590>] ? __queue_work+0x260/0x2c0
[   14.274605]  [<ffffffff8105360d>] ? queue_work_on+0x1d/0x30
[   14.274703]  [<ffffffffa045ac26>] ? evergreen_irq_process+0x906/0xd20 [radeon]
[   14.274715]  [<ffffffff810a0a2d>] ? handle_irq_event_percpu+0x2d/0x1a0
[   14.274724]  [<ffffffff810a0bd6>] ? handle_irq_event+0x36/0x60
[   14.274734]  [<ffffffff810a3487>] ? handle_edge_irq+0x67/0x110
[   14.274743]  [<ffffffff810045d5>] ? handle_irq+0x15/0x20
[   14.274751]  [<ffffffff81004261>] ? do_IRQ+0x51/0xd0
[   14.274761]  [<ffffffff814009ea>] ? common_interrupt+0x6a/0x6a
[   14.274765]  <EOI>  [<ffffffff812369a9>] ? delay_tsc+0x29/0x60
[   14.274850]  [<ffffffffa0455cda>] ? sumo_set_uvd_clock+0x8a/0xb0 [radeon]
[   14.274926]  [<ffffffffa0455dfd>] ? sumo_set_uvd_clocks+0x4d/0xe0 [radeon]
[   14.274999]  [<ffffffffa043f775>] ? r600_uvd_init+0x25/0x390 [radeon]
[   14.275073]  [<ffffffffa045d652>] ? evergreen_startup+0x1952/0x1960 [radeon]
[   14.275146]  [<ffffffffa045d85b>] ? evergreen_init+0x17b/0x2c0 [radeon]
[   14.275208]  [<ffffffffa03f96a5>] ? radeon_device_init+0x5b5/0x6d0 [radeon]
[   14.275219]  [<ffffffff8124d975>] ? pci_find_capability+0x45/0x60
[   14.275279]  [<ffffffffa03fb234>] ? radeon_driver_load_kms+0x84/0x140 [radeon]
[   14.275303]  [<ffffffffa01d84ad>] ? drm_get_pci_dev+0x17d/0x290 [drm]
[   14.275314]  [<ffffffff812521b8>] ? pci_device_probe+0x98/0xe0
[   14.275325]  [<ffffffff812d9ed8>] ? driver_probe_device+0x68/0x210
[   14.275333]  [<ffffffff812da173>] ? __driver_attach+0x93/0xa0
[   14.275341]  [<ffffffff812da0e0>] ? __device_attach+0x60/0x60
[   14.275351]  [<ffffffff812d81b3>] ? bus_for_each_dev+0x53/0x90
[   14.275359]  [<ffffffff812d96a0>] ? bus_add_driver+0x1c0/0x250
[   14.275367]  [<ffffffff812da709>] ? driver_register+0x69/0x140
[   14.275380]  [<ffffffffa050b000>] ? 0xffffffffa050afff
[   14.275390]  [<ffffffffa050b000>] ? 0xffffffffa050afff
[   14.275399]  [<ffffffff810002da>] ? do_one_initcall+0x10a/0x160
[   14.275408]  [<ffffffff8108e508>] ? load_module+0x1cd8/0x2390
[   14.275416]  [<ffffffff8108a540>] ? store_uevent+0x50/0x50
[   14.275427]  [<ffffffff8108ec78>] ? SyS_init_module+0xb8/0xe0
[   14.275438]  [<ffffffff81401112>] ? system_call_fastpath+0x16/0x1b
[   14.275444] ---[ end trace 1f1cbf85b14e84a1 ]---

With best regards,
Julian Wollrath

#130 lore raw
Quoted 57 lines · Julian Wollrath

Hi,

Quoted 5 lines

I just tried the DPM support out on a E-450 APU (HD6320) and it did not work like expected. In the terminal everything seemed ok but when I started a display manager, the screen showed garbage and the system basically locked up. The radeon and drm related parts of the syslog are below.

I saw, that you updated the patches, therefore I tried out the branch drm-next-3.11-wip-2 and I got, additionally to the problem mentioned in my first e-mail, the following warning:

[   14.274349] ------------[ cut here ]------------
[   14.274369] WARNING: at kernel/workqueue.c:1365 __queue_work+0x260/0x2c0()
[   14.274374] Modules linked in: bluetooth crc16 acpi_cpufreq snd_hda_codec_hdmi iwlwifi uvcvideo mperf radeon(+) videobuf2_vmalloc cfg80211 snd_hda_intel(+) battery processor button thinkpad_acpi video nvram rfkill videobuf2_memops videobuf2_core videodev snd_hda_codec kvm_amd i2c_algo_bit kvm snd_hwdep snd_pcm snd_timer snd_page_alloc ac drm_kms_helper ttm snd drm soundcore wmi i2c_piix4 agpgart pcspkr i2c_core evdev k10temp psmouse serio_raw sha256_ssse3 sha256_generic twofish_x86_64_3way glue_helper xts lrw gf128mul twofish_x86_64 twofish_common cbc dm_crypt dm_mod sd_mod crc_t10dif rtsx_pci_sdmmc mmc_core microcode thermal thermal_sys ahci libahci ohci_hcd ehci_pci ehci_hcd rtsx_pci mfd_core usbcore usb_common libata scsi_mod
[   14.274517] CPU: 1 PID: 497 Comm: modprobe Not tainted 3.10.0-rc7-wl+ #3
[   14.274524] Hardware name: LENOVO 30515YG/30515YG, BIOS 8RET52WW (1.15 ) 11/15/2011
[   14.274530]  ffffffff813fc83e ffffffff81037a7a ffff88011ec12540 ffff88011ed15d00
[   14.274539]  ffff8801164a5bc8 0000000000000002 ffff88011e060a00 ffffffff81053590
[   14.274548]  0000000000000002 ffff8801164a5e9c 0000000000000001 0000000000000010
[   14.274558] Call Trace:
[   14.274563]  <IRQ>  [<ffffffff813fc83e>] ? dump_stack+0xc/0x15
[   14.274582]  [<ffffffff81037a7a>] ? warn_slowpath_common+0x6a/0xa0
[   14.274594]  [<ffffffff81053590>] ? __queue_work+0x260/0x2c0
[   14.274605]  [<ffffffff8105360d>] ? queue_work_on+0x1d/0x30
[   14.274703]  [<ffffffffa045ac26>] ? evergreen_irq_process+0x906/0xd20 [radeon]
[   14.274715]  [<ffffffff810a0a2d>] ? handle_irq_event_percpu+0x2d/0x1a0
[   14.274724]  [<ffffffff810a0bd6>] ? handle_irq_event+0x36/0x60
[   14.274734]  [<ffffffff810a3487>] ? handle_edge_irq+0x67/0x110
[   14.274743]  [<ffffffff810045d5>] ? handle_irq+0x15/0x20
[   14.274751]  [<ffffffff81004261>] ? do_IRQ+0x51/0xd0
[   14.274761]  [<ffffffff814009ea>] ? common_interrupt+0x6a/0x6a
[   14.274765]  <EOI>  [<ffffffff812369a9>] ? delay_tsc+0x29/0x60
[   14.274850]  [<ffffffffa0455cda>] ? sumo_set_uvd_clock+0x8a/0xb0 [radeon]
[   14.274926]  [<ffffffffa0455dfd>] ? sumo_set_uvd_clocks+0x4d/0xe0 [radeon]
[   14.274999]  [<ffffffffa043f775>] ? r600_uvd_init+0x25/0x390 [radeon]
[   14.275073]  [<ffffffffa045d652>] ? evergreen_startup+0x1952/0x1960 [radeon]
[   14.275146]  [<ffffffffa045d85b>] ? evergreen_init+0x17b/0x2c0 [radeon]
[   14.275208]  [<ffffffffa03f96a5>] ? radeon_device_init+0x5b5/0x6d0 [radeon]
[   14.275219]  [<ffffffff8124d975>] ? pci_find_capability+0x45/0x60
[   14.275279]  [<ffffffffa03fb234>] ? radeon_driver_load_kms+0x84/0x140 [radeon]
[   14.275303]  [<ffffffffa01d84ad>] ? drm_get_pci_dev+0x17d/0x290 [drm]
[   14.275314]  [<ffffffff812521b8>] ? pci_device_probe+0x98/0xe0
[   14.275325]  [<ffffffff812d9ed8>] ? driver_probe_device+0x68/0x210
[   14.275333]  [<ffffffff812da173>] ? __driver_attach+0x93/0xa0
[   14.275341]  [<ffffffff812da0e0>] ? __device_attach+0x60/0x60
[   14.275351]  [<ffffffff812d81b3>] ? bus_for_each_dev+0x53/0x90
[   14.275359]  [<ffffffff812d96a0>] ? bus_add_driver+0x1c0/0x250
[   14.275367]  [<ffffffff812da709>] ? driver_register+0x69/0x140
[   14.275380]  [<ffffffffa050b000>] ? 0xffffffffa050afff
[   14.275390]  [<ffffffffa050b000>] ? 0xffffffffa050afff
[   14.275399]  [<ffffffff810002da>] ? do_one_initcall+0x10a/0x160
[   14.275408]  [<ffffffff8108e508>] ? load_module+0x1cd8/0x2390
[   14.275416]  [<ffffffff8108a540>] ? store_uevent+0x50/0x50
[   14.275427]  [<ffffffff8108ec78>] ? SyS_init_module+0xb8/0xe0
[   14.275438]  [<ffffffff81401112>] ? system_call_fastpath+0x16/0x1b
[   14.275444] ---[ end trace 1f1cbf85b14e84a1 ]---
Quoted 2 lines

With best regards,
Julian Wollrath

This patch should fix your issue :

http://people.freedesktop.org/~glisse/0001-radeon-do-no-schedule-thermal-work-if-dpm-is-not-ena.patch

Cheers,
Jerome

#132 lore raw
In reply to Julian Wollrath
Quoted 10 lines · Julian Wollrath

Hi,

I just tried the DPM support out on a E-450 APU (HD6320) and it did not work like expected. In the terminal everything seemed ok but when I started a display manager, the screen showed garbage and the system basically locked up. The radeon and drm related parts of the syslog are below.

If you need further information, feel free to ask.

I have the same problem with the same APU. Disabling power gating (set enable_gfx_power_gating to false in sumo_dpm.c:sumo_dpm_init) fixes it. So this problem may related to power gating.

The difference in power consumption seems to be small, but I'd still prefer it working.

By the way, the "disable_gfx_power_gating_in_uvd" quirk is not actually used, seems to be some leftover from debugging or such.

Best regards
Grigori

#133 lore raw
In reply to [email protected]
Quoted 5 lines · On Wed, Jun 26, 2013 at 9:21 AM, <[email protected]> wrote:

From: Alex Deucher <[email protected]>

These are the radeon patches for 3.11. Some of these patches are huge so, it might be easier to review things here:
http://cgit.freedesktop.org/~agd5f/linux/log/?h=drm-next-3.11-wip

Updated branch:
http://cgit.freedesktop.org/~agd5f/linux/log/?h=drm-next-3.11-wip-2
Takes into account comments from Jerome a Christian and contains a few DPM fixes.

Alex

#134 lore raw
Quoted 11 lines · Alex Deucher
Quoted 5 lines · On Wed, Jun 26, 2013 at 9:21 AM, <[email protected]> wrote:

From: Alex Deucher <[email protected]>

These are the radeon patches for 3.11. Some of these patches are huge so, it might be easier to review things here:
http://cgit.freedesktop.org/~agd5f/linux/log/?h=drm-next-3.11-wip

Updated branch:
http://cgit.freedesktop.org/~agd5f/linux/log/?h=drm-next-3.11-wip-2
Takes into account comments from Jerome a Christian and contains a few DPM fixes.

I see there's a 3 now - I tested that (I guess currently it's the same as 2 anyway).

On my rv790 there are no regressions so far, but whatever I do it stays low.

echo profile > /sys/class/drm/card0/device/power_method = write error, is there a way to go back to manual setting with dpm?

I haven't tried rv670 yet - I couldn't see a new firmware for that, does it just not need one?

#135 lore raw
Quoted 17 lines · Andy Furniss
Quoted 10 lines · Alex Deucher
Quoted 6 lines · On Wed, Jun 26, 2013 at 9:21 AM, <[email protected]> wrote:

From: Alex Deucher <[email protected]>

These are the radeon patches for 3.11. Some of these patches are huge so, it might be easier to review things here:
http://cgit.freedesktop.org/~agd5f/linux/log/?h=drm-next-3.11-wip

Quoted 4 lines

Updated branch:
http://cgit.freedesktop.org/~agd5f/linux/log/?h=drm-next-3.11-wip-2
Takes into account comments from Jerome a Christian and contains a few DPM fixes.

Quoted 5 lines

I see there's a 3 now - I tested that (I guess currently it's the same as 2 anyway).

On my rv790 there are no regressions so far, but whatever I do it stays low.

We may need to tweak the scaling parameters a bit to force higher states more readily. They are pretty conservative right now.

Quoted 2 lines

echo profile > /sys/class/drm/card0/device/power_method = write error, is there a way to go back to manual setting with dpm?

Not yet. I'm working on an infrastructure to force DPM modes, but it's not ready yet.

Quoted 4 lines

I haven't tried rv670 yet - I couldn't see a new firmware for that, does it just not need one?

Nope. 6xx and APUs do not require ucode. only 7xx+ dGPUs.

Alex

#136 lore raw
Quoted 1 line
Quoted 1 line
Quoted 1 line
Quoted 1 line
Quoted 1 line

"AD" == Alex Deucher <[email protected]> writes:

AD> Nope. 6xx and APUs do not require ucode. only 7xx+ dGPUs.

Does that mean that APUs do not require *any* ucode blobs?

Or just that they do not require updated or additional blobs for the new functionality like DPM?

-JimC

Signature · 1 line
James Cloos <[email protected]>         OpenPGP: 1024D/ED7DAEA6
#137 lore raw
Quoted 11 lines · James Cloos
Quoted 1 line
Quoted 1 line
Quoted 1 line
Quoted 1 line
Quoted 1 line

"AD" == Alex Deucher <[email protected]> writes:

AD> Nope. 6xx and APUs do not require ucode. only 7xx+ dGPUs.

Does that mean that APUs do not require *any* ucode blobs?

Or just that they do not require updated or additional blobs for the new functionality like DPM?

-JimC
--

They don't require any ucode blob for the power management. They do require ucode blob for 3d acceleration, compute, well anything that want to use the gpu really.

Cheers,
Jerome

#138 lore raw
In reply to Andy Furniss
Quoted 17 lines · Andy Furniss
Quoted 10 lines · Alex Deucher
Quoted 6 lines · On Wed, Jun 26, 2013 at 9:21 AM, <[email protected]> wrote:

From: Alex Deucher <[email protected]>

These are the radeon patches for 3.11. Some of these patches are huge so, it might be easier to review things here:
http://cgit.freedesktop.org/~agd5f/linux/log/?h=drm-next-3.11-wip

Quoted 4 lines

Updated branch:
http://cgit.freedesktop.org/~agd5f/linux/log/?h=drm-next-3.11-wip-2
Takes into account comments from Jerome a Christian and contains a few DPM fixes.

Quoted 4 lines

I see there's a 3 now - I tested that (I guess currently it's the same as 2 anyway).

On my rv790 there are no regressions so far, but whatever I do it stays low.

This should work much better with with wip-5.

Alex

#139 lore raw
Quoted 23 lines · Alex Deucher
Quoted 17 lines · Andy Furniss
Quoted 10 lines · Alex Deucher
Quoted 6 lines · On Wed, Jun 26, 2013 at 9:21 AM, <[email protected]> wrote:

From: Alex Deucher <[email protected]>

These are the radeon patches for 3.11. Some of these patches are huge so, it might be easier to review things here:
http://cgit.freedesktop.org/~agd5f/linux/log/?h=drm-next-3.11-wip

Quoted 4 lines

Updated branch:
http://cgit.freedesktop.org/~agd5f/linux/log/?h=drm-next-3.11-wip-2
Takes into account comments from Jerome a Christian and contains a few DPM fixes.

Quoted 4 lines

I see there's a 3 now - I tested that (I guess currently it's the same as 2 anyway).

On my rv790 there are no regressions so far, but whatever I do it stays low.

Quoted 8 lines

This should work much better with with wip-5.

Alex
_______________________________________________
dri-devel mailing list
[email protected]
http://lists.freedesktop.org/mailman/listinfo/dri-devel

Just tested, and my card (HD6870) is still stuck at low.

(tested with HL2 and wine/furmark)

++

Signature · 3 lines
Laurent Carlier
ArchLinux Developer
http://www.archlinux.org

_______________________________________________
dri-devel mailing list
[email protected]
http://lists.freedesktop.org/mailman/listinfo/dri-devel

#140 lore raw
In reply to Alex Deucher
Quoted 18 lines · Alex Deucher
Quoted 17 lines · Andy Furniss
Quoted 14 lines · Alex Deucher
Quoted 6 lines · On Wed, Jun 26, 2013 at 9:21 AM, <[email protected]> wrote:

From: Alex Deucher <[email protected]>

These are the radeon patches for 3.11. Some of these patches are huge so, it might be easier to review things here:
http://cgit.freedesktop.org/~agd5f/linux/log/?h=drm-next-3.11-wip

Updated branch:
http://cgit.freedesktop.org/~agd5f/linux/log/?h=drm-next-3.11-wip-2
Takes into account comments from Jerome a Christian and contains a few DPM fixes.

Quoted 6 lines
Quoted 4 lines

I see there's a 3 now - I tested that (I guess currently it's the same as 2 anyway).

On my rv790 there are no regressions so far, but whatever I do it stays low.

This should work much better with with wip-5.

Yes, this works on my rv790 games get high and using vdpau/gl for video stays low (which is nice as the fan on my card is too noisy on high).

One thing which I guess 99.999% of people won't notice is that doing any thing with plain X + fluxbox (so no compositing) very briefly ramps up the speed.

As my fan is just audible on low but very quick to respond I can hear every time the screen gets updated eg. switching desktops, browsing+scrolling or switching tabs, even typing dmesg in an xterm which time shows as taking < 0.1 sec results in a fan change.

#141 lore raw

Hi,

Quoted 1 line

Yes, this works on my rv790 games get high and using vdpau/gl for video

stays low (which is nice as the fan on my card is too noisy on high).

Quoted 2 lines

One thing which I guess 99.999% of people won't notice is that doing any

thing with plain X + fluxbox (so no compositing) very briefly ramps up the speed.

Quoted 2 lines

As my fan is just audible on low but very quick to respond I can hear

every time the screen gets updated eg. switching desktops, browsing+scrolling or switching tabs, even typing dmesg in an xterm which time shows as taking < 0.1 sec results in a fan change.

Probably a low-pass filter is needed/has to be configured in front of the freq. scaling engine?

Ilyes

Quoted 7 lines

_______________________________________________
dri-devel mailing list
[email protected]
http://lists.freedesktop.org/mailman/listinfo/dri-devel

_______________________________________________
dri-devel mailing list
[email protected]
http://lists.freedesktop.org/mailman/listinfo/dri-devel