drm/radeon/kms: add dpm support for KB/KV

This adds dpm support for KB/KV asics.  This includes:
- dynamic engine clock scaling
- dynamic voltage scaling
- power containment
- shader power scaling

Set radeon.dpm=1 to enable.

Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
This commit is contained in:
Alex Deucher 2013-08-14 01:01:40 -04:00
parent 6bb5c0d74c
commit 41a524abff
12 changed files with 3576 additions and 4 deletions

View File

@ -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 ni_dpm.o si_smc.o si_dpm.o
trinity_smc.o ni_dpm.o si_smc.o si_dpm.o kv_smc.o kv_dpm.o
radeon-$(CONFIG_COMPAT) += radeon_ioc32.o
radeon-$(CONFIG_VGA_SWITCHEROO) += radeon_atpx_handler.o

View File

@ -6593,6 +6593,7 @@ int cik_irq_set(struct radeon_device *rdev)
u32 hpd1, hpd2, hpd3, hpd4, hpd5, hpd6;
u32 grbm_int_cntl = 0;
u32 dma_cntl, dma_cntl1;
u32 thermal_int;
if (!rdev->irq.installed) {
WARN(1, "Can't enable IRQ/MSI because no handler is installed\n");
@ -6625,6 +6626,9 @@ int cik_irq_set(struct radeon_device *rdev)
cp_m2p2 = RREG32(CP_ME2_PIPE2_INT_CNTL) & ~TIME_STAMP_INT_ENABLE;
cp_m2p3 = RREG32(CP_ME2_PIPE3_INT_CNTL) & ~TIME_STAMP_INT_ENABLE;
thermal_int = RREG32_SMC(CG_THERMAL_INT_CTRL) &
~(THERM_INTH_MASK | THERM_INTL_MASK);
/* enable CP interrupts on all rings */
if (atomic_read(&rdev->irq.ring_int[RADEON_RING_TYPE_GFX_INDEX])) {
DRM_DEBUG("cik_irq_set: sw int gfx\n");
@ -6782,6 +6786,11 @@ int cik_irq_set(struct radeon_device *rdev)
hpd6 |= DC_HPDx_INT_EN;
}
if (rdev->irq.dpm_thermal) {
DRM_DEBUG("dpm thermal\n");
thermal_int |= THERM_INTH_MASK | THERM_INTL_MASK;
}
WREG32(CP_INT_CNTL_RING0, cp_int_cntl);
WREG32(SDMA0_CNTL + SDMA0_REGISTER_OFFSET, dma_cntl);
@ -6816,6 +6825,8 @@ int cik_irq_set(struct radeon_device *rdev)
WREG32(DC_HPD5_INT_CONTROL, hpd5);
WREG32(DC_HPD6_INT_CONTROL, hpd6);
WREG32_SMC(CG_THERMAL_INT_CTRL, thermal_int);
return 0;
}
@ -7027,6 +7038,7 @@ int cik_irq_process(struct radeon_device *rdev)
bool queue_hotplug = false;
bool queue_reset = false;
u32 addr, status, mc_client;
bool queue_thermal = false;
if (!rdev->ih.enabled || rdev->shutdown)
return IRQ_NONE;
@ -7377,6 +7389,19 @@ restart_ih:
break;
}
break;
case 230: /* thermal low to high */
DRM_DEBUG("IH: thermal low to high\n");
rdev->pm.dpm.thermal.high_to_low = false;
queue_thermal = true;
break;
case 231: /* thermal high to low */
DRM_DEBUG("IH: thermal high to low\n");
rdev->pm.dpm.thermal.high_to_low = true;
queue_thermal = true;
break;
case 233: /* GUI IDLE */
DRM_DEBUG("IH: GUI idle\n");
break;
case 241: /* SDMA Privileged inst */
case 247: /* SDMA Privileged inst */
DRM_ERROR("Illegal instruction in SDMA command stream\n");
@ -7416,9 +7441,6 @@ restart_ih:
break;
}
break;
case 233: /* GUI IDLE */
DRM_DEBUG("IH: GUI idle\n");
break;
default:
DRM_DEBUG("Unhandled interrupt: %d %d\n", src_id, src_data);
break;
@ -7432,6 +7454,8 @@ restart_ih:
schedule_work(&rdev->hotplug_work);
if (queue_reset)
schedule_work(&rdev->reset_work);
if (queue_thermal)
schedule_work(&rdev->pm.dpm.thermal.work);
rdev->ih.rptr = rptr;
WREG32(IH_RB_RPTR, rdev->ih.rptr);
atomic_set(&rdev->ih.lock, 0);

View File

@ -28,10 +28,59 @@
#define CIK_RB_BITMAP_WIDTH_PER_SH 2
/* DIDT IND registers */
#define DIDT_SQ_CTRL0 0x0
# define DIDT_CTRL_EN (1 << 0)
#define DIDT_DB_CTRL0 0x20
#define DIDT_TD_CTRL0 0x40
#define DIDT_TCP_CTRL0 0x60
/* SMC IND registers */
#define NB_DPM_CONFIG_1 0x3F9E8
# define Dpm0PgNbPsLo(x) ((x) << 0)
# define Dpm0PgNbPsLo_MASK 0x000000ff
# define Dpm0PgNbPsLo_SHIFT 0
# define Dpm0PgNbPsHi(x) ((x) << 8)
# define Dpm0PgNbPsHi_MASK 0x0000ff00
# define Dpm0PgNbPsHi_SHIFT 8
# define DpmXNbPsLo(x) ((x) << 16)
# define DpmXNbPsLo_MASK 0x00ff0000
# define DpmXNbPsLo_SHIFT 16
# define DpmXNbPsHi(x) ((x) << 24)
# define DpmXNbPsHi_MASK 0xff000000
# define DpmXNbPsHi_SHIFT 24
#define SMC_SYSCON_MSG_ARG_0 0x80000068
#define GENERAL_PWRMGT 0xC0200000
# define GLOBAL_PWRMGT_EN (1 << 0)
# define GPU_COUNTER_CLK (1 << 15)
#define SCLK_PWRMGT_CNTL 0xC0200008
# define RESET_BUSY_CNT (1 << 4)
# define RESET_SCLK_CNT (1 << 5)
# define DYNAMIC_PM_EN (1 << 21)
#define CG_FTV_0 0xC02001A8
#define LCAC_SX0_OVR_SEL 0xC0400D04
#define LCAC_SX0_OVR_VAL 0xC0400D08
#define LCAC_MC0_OVR_SEL 0xC0400D34
#define LCAC_MC0_OVR_VAL 0xC0400D38
#define LCAC_MC1_OVR_SEL 0xC0400D40
#define LCAC_MC1_OVR_VAL 0xC0400D44
#define LCAC_MC2_OVR_SEL 0xC0400D4C
#define LCAC_MC2_OVR_VAL 0xC0400D50
#define LCAC_MC3_OVR_SEL 0xC0400D58
#define LCAC_MC3_OVR_VAL 0xC0400D5C
#define LCAC_CPL_OVR_SEL 0xC0400D84
#define LCAC_CPL_OVR_VAL 0xC0400D88
#define CG_MULT_THERMAL_STATUS 0xC0300014
#define ASIC_MAX_TEMP(x) ((x) << 0)
#define ASIC_MAX_TEMP_MASK 0x000001ff
@ -60,6 +109,16 @@
# define ZCLK_SEL(x) ((x) << 8)
# define ZCLK_SEL_MASK 0xFF00
#define CG_THERMAL_INT_CTRL 0xC2100028
#define DIG_THERM_INTH(x) ((x) << 0)
#define DIG_THERM_INTH_MASK 0x000000FF
#define DIG_THERM_INTH_SHIFT 0
#define DIG_THERM_INTL(x) ((x) << 8)
#define DIG_THERM_INTL_MASK 0x0000FF00
#define DIG_THERM_INTL_SHIFT 8
#define THERM_INTH_MASK (1 << 24)
#define THERM_INTL_MASK (1 << 25)
/* PCIE registers idx/data 0x38/0x3c */
#define PB0_PIF_PWRDOWN_0 0x1100012 /* PCIE */
# define PLL_POWER_STATE_IN_TXS2_0(x) ((x) << 7)
@ -173,6 +232,19 @@
#define PCIE_INDEX 0x38
#define PCIE_DATA 0x3C
#define SMC_IND_INDEX_0 0x200
#define SMC_IND_DATA_0 0x204
#define SMC_IND_ACCESS_CNTL 0x240
#define AUTO_INCREMENT_IND_0 (1 << 0)
#define SMC_MESSAGE_0 0x250
#define SMC_MSG_MASK 0xffff
#define SMC_RESP_0 0x254
#define SMC_RESP_MASK 0xffff
#define SMC_MSG_ARG_0 0x290
#define VGA_HDP_CONTROL 0x328
#define VGA_MEMORY_DISABLE (1 << 4)

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,199 @@
/*
* Copyright 2013 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 __KV_DPM_H__
#define __KV_DPM_H__
#define SMU__NUM_SCLK_DPM_STATE 8
#define SMU__NUM_MCLK_DPM_LEVELS 4
#define SMU__NUM_LCLK_DPM_LEVELS 8
#define SMU__NUM_PCIE_DPM_LEVELS 0 /* ??? */
#include "smu7_fusion.h"
#include "trinity_dpm.h"
#include "ppsmc.h"
#define KV_NUM_NBPSTATES 4
enum kv_pt_config_reg_type {
KV_CONFIGREG_MMR = 0,
KV_CONFIGREG_SMC_IND,
KV_CONFIGREG_DIDT_IND,
KV_CONFIGREG_CACHE,
KV_CONFIGREG_MAX
};
struct kv_pt_config_reg {
u32 offset;
u32 mask;
u32 shift;
u32 value;
enum kv_pt_config_reg_type type;
};
struct kv_lcac_config_values {
u32 block_id;
u32 signal_id;
u32 t;
};
struct kv_lcac_config_reg {
u32 cntl;
u32 block_mask;
u32 block_shift;
u32 signal_mask;
u32 signal_shift;
u32 t_mask;
u32 t_shift;
u32 enable_mask;
u32 enable_shift;
};
struct kv_pl {
u32 sclk;
u8 vddc_index;
u8 ds_divider_index;
u8 ss_divider_index;
u8 allow_gnb_slow;
u8 force_nbp_state;
u8 display_wm;
u8 vce_wm;
};
struct kv_ps {
struct kv_pl levels[SUMO_MAX_HARDWARE_POWERLEVELS];
u32 num_levels;
bool need_dfs_bypass;
u8 dpm0_pg_nb_ps_lo;
u8 dpm0_pg_nb_ps_hi;
u8 dpmx_nb_ps_lo;
u8 dpmx_nb_ps_hi;
};
struct kv_sys_info {
u32 bootup_uma_clk;
u32 bootup_sclk;
u32 dentist_vco_freq;
u32 nb_dpm_enable;
u32 nbp_memory_clock[KV_NUM_NBPSTATES];
u32 nbp_n_clock[KV_NUM_NBPSTATES];
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_vid_mapping_table vid_mapping_table;
u32 uma_channel_number;
};
struct kv_power_info {
u32 at[SUMO_MAX_HARDWARE_POWERLEVELS];
u32 voltage_drop_t;
struct kv_sys_info sys_info;
struct kv_pl boot_pl;
bool enable_nb_ps_policy;
bool disable_nb_ps3_in_battery;
bool video_start;
bool battery_state;
u32 lowest_valid;
u32 highest_valid;
u16 high_voltage_t;
bool cac_enabled;
bool bapm_enable;
/* smc offsets */
u32 sram_end;
u32 dpm_table_start;
u32 soft_regs_start;
/* dpm SMU tables */
u8 graphics_dpm_level_count;
u8 uvd_level_count;
u8 vce_level_count;
u8 acp_level_count;
u8 samu_level_count;
u16 fps_high_t;
SMU7_Fusion_GraphicsLevel graphics_level[SMU__NUM_SCLK_DPM_STATE];
SMU7_Fusion_ACPILevel acpi_level;
SMU7_Fusion_UvdLevel uvd_level[SMU7_MAX_LEVELS_UVD];
SMU7_Fusion_ExtClkLevel vce_level[SMU7_MAX_LEVELS_VCE];
SMU7_Fusion_ExtClkLevel acp_level[SMU7_MAX_LEVELS_ACP];
SMU7_Fusion_ExtClkLevel samu_level[SMU7_MAX_LEVELS_SAMU];
u8 uvd_boot_level;
u8 vce_boot_level;
u8 acp_boot_level;
u8 samu_boot_level;
u8 uvd_interval;
u8 vce_interval;
u8 acp_interval;
u8 samu_interval;
u8 graphics_boot_level;
u8 graphics_interval;
u8 graphics_therm_throttle_enable;
u8 graphics_voltage_change_enable;
u8 graphics_clk_slow_enable;
u8 graphics_clk_slow_divider;
u8 fps_low_t;
u32 low_sclk_interrupt_t;
bool uvd_power_gated;
bool vce_power_gated;
bool acp_power_gated;
bool samu_power_gated;
bool nb_dpm_enabled;
/* flags */
bool enable_didt;
bool enable_dpm;
bool enable_auto_thermal_throttling;
bool enable_nb_dpm;
/* caps */
bool caps_cac;
bool caps_power_containment;
bool caps_sq_ramping;
bool caps_db_ramping;
bool caps_td_ramping;
bool caps_tcp_ramping;
bool caps_sclk_throttle_low_notification;
bool caps_fps;
bool caps_uvd_dpm;
bool caps_uvd_pg;
bool caps_vce_pg;
bool caps_samu_pg;
bool caps_acp_pg;
bool caps_stable_p_state;
bool caps_enable_dfs_bypass;
bool caps_sclk_ds;
struct radeon_ps current_rps;
struct kv_ps current_ps;
struct radeon_ps requested_rps;
struct kv_ps requested_ps;
};
/* kv_smc.c */
int kv_notify_message_to_smu(struct radeon_device *rdev, u32 id);
int kv_dpm_get_enable_mask(struct radeon_device *rdev, u32 *enable_mask);
int kv_send_msg_to_smc_with_parameter(struct radeon_device *rdev,
PPSMC_Msg msg, u32 parameter);
int kv_read_smc_sram_dword(struct radeon_device *rdev, u32 smc_address,
u32 *value, u32 limit);
int kv_smc_dpm_enable(struct radeon_device *rdev, bool enable);
int kv_copy_bytes_to_smc(struct radeon_device *rdev,
u32 smc_start_address,
const u8 *src, u32 byte_count, u32 limit);
#endif

View File

@ -0,0 +1,207 @@
/*
* Copyright 2013 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
*/
#include "drmP.h"
#include "radeon.h"
#include "cikd.h"
#include "kv_dpm.h"
int kv_notify_message_to_smu(struct radeon_device *rdev, u32 id)
{
u32 i;
u32 tmp = 0;
WREG32(SMC_MESSAGE_0, id & SMC_MSG_MASK);
for (i = 0; i < rdev->usec_timeout; i++) {
if ((RREG32(SMC_RESP_0) & SMC_RESP_MASK) != 0)
break;
udelay(1);
}
tmp = RREG32(SMC_RESP_0) & SMC_RESP_MASK;
if (tmp != 1) {
if (tmp == 0xFF)
return -EINVAL;
else if (tmp == 0xFE)
return -EINVAL;
}
return 0;
}
int kv_dpm_get_enable_mask(struct radeon_device *rdev, u32 *enable_mask)
{
int ret;
ret = kv_notify_message_to_smu(rdev, PPSMC_MSG_SCLKDPM_GetEnabledMask);
if (ret == 0)
*enable_mask = RREG32_SMC(SMC_SYSCON_MSG_ARG_0);
return ret;
}
int kv_send_msg_to_smc_with_parameter(struct radeon_device *rdev,
PPSMC_Msg msg, u32 parameter)
{
WREG32(SMC_MSG_ARG_0, parameter);
return kv_notify_message_to_smu(rdev, msg);
}
static int kv_set_smc_sram_address(struct radeon_device *rdev,
u32 smc_address, u32 limit)
{
if (smc_address & 3)
return -EINVAL;
if ((smc_address + 3) > limit)
return -EINVAL;
WREG32(SMC_IND_INDEX_0, smc_address);
WREG32_P(SMC_IND_ACCESS_CNTL, 0, ~AUTO_INCREMENT_IND_0);
return 0;
}
int kv_read_smc_sram_dword(struct radeon_device *rdev, u32 smc_address,
u32 *value, u32 limit)
{
int ret;
ret = kv_set_smc_sram_address(rdev, smc_address, limit);
if (ret)
return ret;
*value = RREG32(SMC_IND_DATA_0);
return 0;
}
int kv_smc_dpm_enable(struct radeon_device *rdev, bool enable)
{
if (enable)
return kv_notify_message_to_smu(rdev, PPSMC_MSG_DPM_Enable);
else
return kv_notify_message_to_smu(rdev, PPSMC_MSG_DPM_Disable);
}
int kv_copy_bytes_to_smc(struct radeon_device *rdev,
u32 smc_start_address,
const u8 *src, u32 byte_count, u32 limit)
{
int ret;
u32 data, original_data, addr, extra_shift, t_byte, count, mask;
if ((smc_start_address + byte_count) > limit)
return -EINVAL;
addr = smc_start_address;
t_byte = addr & 3;
/* RMW for the initial bytes */
if (t_byte != 0) {
addr -= t_byte;
ret = kv_set_smc_sram_address(rdev, addr, limit);
if (ret)
return ret;
original_data = RREG32(SMC_IND_DATA_0);
data = 0;
mask = 0;
count = 4;
while (count > 0) {
if (t_byte > 0) {
mask = (mask << 8) | 0xff;
t_byte--;
} else if (byte_count > 0) {
data = (data << 8) + *src++;
byte_count--;
mask <<= 8;
} else {
data <<= 8;
mask = (mask << 8) | 0xff;
}
count--;
}
data |= original_data & mask;
ret = kv_set_smc_sram_address(rdev, addr, limit);
if (ret)
return ret;
WREG32(SMC_IND_DATA_0, data);
addr += 4;
}
while (byte_count >= 4) {
/* SMC address space is BE */
data = (src[0] << 24) + (src[1] << 16) + (src[2] << 8) + src[3];
ret = kv_set_smc_sram_address(rdev, addr, limit);
if (ret)
return ret;
WREG32(SMC_IND_DATA_0, data);
src += 4;
byte_count -= 4;
addr += 4;
}
/* RMW for the final bytes */
if (byte_count > 0) {
data = 0;
ret = kv_set_smc_sram_address(rdev, addr, limit);
if (ret)
return ret;
original_data= RREG32(SMC_IND_DATA_0);
extra_shift = 8 * (4 - byte_count);
while (byte_count > 0) {
/* SMC address space is BE */
data = (data << 8) + *src++;
byte_count--;
}
data <<= extra_shift;
data |= (original_data & ~((~0UL) << extra_shift));
ret = kv_set_smc_sram_address(rdev, addr, limit);
if (ret)
return ret;
WREG32(SMC_IND_DATA_0, data);
}
return 0;
}

View File

@ -99,11 +99,45 @@ typedef uint8_t PPSMC_Result;
#define PPSMC_MSG_ThrottleOVRDSCLKDS ((uint8_t)0x96)
#define PPSMC_MSG_CancelThrottleOVRDSCLKDS ((uint8_t)0x97)
/* KV/KB */
#define PPSMC_MSG_UVDDPM_SetEnabledMask ((uint16_t) 0x12D)
#define PPSMC_MSG_VCEDPM_SetEnabledMask ((uint16_t) 0x12E)
#define PPSMC_MSG_ACPDPM_SetEnabledMask ((uint16_t) 0x12F)
#define PPSMC_MSG_SAMUDPM_SetEnabledMask ((uint16_t) 0x130)
#define PPSMC_MSG_MCLKDPM_ForceState ((uint16_t) 0x131)
#define PPSMC_MSG_MCLKDPM_NoForcedLevel ((uint16_t) 0x132)
#define PPSMC_MSG_Voltage_Cntl_Disable ((uint16_t) 0x135)
#define PPSMC_MSG_PCIeDPM_Enable ((uint16_t) 0x136)
#define PPSMC_MSG_ACPPowerOFF ((uint16_t) 0x137)
#define PPSMC_MSG_ACPPowerON ((uint16_t) 0x138)
#define PPSMC_MSG_SAMPowerOFF ((uint16_t) 0x139)
#define PPSMC_MSG_SAMPowerON ((uint16_t) 0x13a)
#define PPSMC_MSG_PCIeDPM_Disable ((uint16_t) 0x13d)
#define PPSMC_MSG_NBDPM_Enable ((uint16_t) 0x140)
#define PPSMC_MSG_NBDPM_Disable ((uint16_t) 0x141)
#define PPSMC_MSG_SCLKDPM_SetEnabledMask ((uint16_t) 0x145)
#define PPSMC_MSG_DPM_Enable ((uint16_t) 0x14e)
#define PPSMC_MSG_DPM_Disable ((uint16_t) 0x14f)
#define PPSMC_MSG_UVDDPM_Enable ((uint16_t) 0x154)
#define PPSMC_MSG_UVDDPM_Disable ((uint16_t) 0x155)
#define PPSMC_MSG_SAMUDPM_Enable ((uint16_t) 0x156)
#define PPSMC_MSG_SAMUDPM_Disable ((uint16_t) 0x157)
#define PPSMC_MSG_ACPDPM_Enable ((uint16_t) 0x158)
#define PPSMC_MSG_ACPDPM_Disable ((uint16_t) 0x159)
#define PPSMC_MSG_VCEDPM_Enable ((uint16_t) 0x15a)
#define PPSMC_MSG_VCEDPM_Disable ((uint16_t) 0x15b)
#define PPSMC_MSG_SCLKDPM_GetEnabledMask ((uint16_t) 0x162)
#define PPSMC_MSG_SCLKDPM_FreezeLevel ((uint16_t) 0x189)
#define PPSMC_MSG_SCLKDPM_UnfreezeLevel ((uint16_t) 0x18A)
/* 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_DPM_N_LevelsDisabled ((uint32_t) 0x112)
#define PPSMC_MSG_Voltage_Cntl_Enable ((uint32_t) 0x109)
#define PPSMC_MSG_VCEPowerOFF ((uint32_t) 0x10e)
#define PPSMC_MSG_VCEPowerON ((uint32_t) 0x10f)
#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)

View File

@ -2610,6 +2610,20 @@ static struct radeon_asic kv_asic = {
.set_uvd_clocks = &cik_set_uvd_clocks,
.get_temperature = &kv_get_temp,
},
.dpm = {
.init = &kv_dpm_init,
.setup_asic = &kv_dpm_setup_asic,
.enable = &kv_dpm_enable,
.disable = &kv_dpm_disable,
.pre_set_power_state = &kv_dpm_pre_set_power_state,
.set_power_state = &kv_dpm_set_power_state,
.post_set_power_state = &kv_dpm_post_set_power_state,
.display_configuration_changed = &kv_dpm_display_configuration_changed,
.fini = &kv_dpm_fini,
.get_sclk = &kv_dpm_get_sclk,
.get_mclk = &kv_dpm_get_mclk,
.print_power_state = &kv_dpm_print_power_state,
},
.pflip = {
.pre_page_flip = &evergreen_pre_page_flip,
.page_flip = &evergreen_page_flip,

View File

@ -750,4 +750,18 @@ void cik_compute_ring_set_wptr(struct radeon_device *rdev,
int ci_get_temp(struct radeon_device *rdev);
int kv_get_temp(struct radeon_device *rdev);
int kv_dpm_init(struct radeon_device *rdev);
int kv_dpm_enable(struct radeon_device *rdev);
void kv_dpm_disable(struct radeon_device *rdev);
int kv_dpm_pre_set_power_state(struct radeon_device *rdev);
int kv_dpm_set_power_state(struct radeon_device *rdev);
void kv_dpm_post_set_power_state(struct radeon_device *rdev);
void kv_dpm_setup_asic(struct radeon_device *rdev);
void kv_dpm_display_configuration_changed(struct radeon_device *rdev);
void kv_dpm_fini(struct radeon_device *rdev);
u32 kv_dpm_get_sclk(struct radeon_device *rdev, bool low);
u32 kv_dpm_get_mclk(struct radeon_device *rdev, bool low);
void kv_dpm_print_power_state(struct radeon_device *rdev,
struct radeon_ps *ps);
#endif

View File

@ -1202,6 +1202,8 @@ int radeon_pm_init(struct radeon_device *rdev)
case CHIP_VERDE:
case CHIP_OLAND:
case CHIP_HAINAN:
case CHIP_KABINI:
case CHIP_KAVERI:
/* DPM requires the RLC, RV770+ dGPU requires SMC */
if (!rdev->rlc_fw)
rdev->pm.pm_method = PM_METHOD_PROFILE;

View File

@ -0,0 +1,170 @@
/*
* Copyright 2013 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 SMU7_H
#define SMU7_H
#pragma pack(push, 1)
#define SMU7_CONTEXT_ID_SMC 1
#define SMU7_CONTEXT_ID_VBIOS 2
#define SMU7_CONTEXT_ID_SMC 1
#define SMU7_CONTEXT_ID_VBIOS 2
#define SMU7_MAX_LEVELS_VDDC 8
#define SMU7_MAX_LEVELS_VDDCI 4
#define SMU7_MAX_LEVELS_MVDD 4
#define SMU7_MAX_LEVELS_VDDNB 8
#define SMU7_MAX_LEVELS_GRAPHICS SMU__NUM_SCLK_DPM_STATE // SCLK + SQ DPM + ULV
#define SMU7_MAX_LEVELS_MEMORY SMU__NUM_MCLK_DPM_LEVELS // MCLK Levels DPM
#define SMU7_MAX_LEVELS_GIO SMU__NUM_LCLK_DPM_LEVELS // LCLK Levels
#define SMU7_MAX_LEVELS_LINK SMU__NUM_PCIE_DPM_LEVELS // PCIe speed and number of lanes.
#define SMU7_MAX_LEVELS_UVD 8 // VCLK/DCLK levels for UVD.
#define SMU7_MAX_LEVELS_VCE 8 // ECLK levels for VCE.
#define SMU7_MAX_LEVELS_ACP 8 // ACLK levels for ACP.
#define SMU7_MAX_LEVELS_SAMU 8 // SAMCLK levels for SAMU.
#define SMU7_MAX_ENTRIES_SMIO 32 // Number of entries in SMIO table.
#define DPM_NO_LIMIT 0
#define DPM_NO_UP 1
#define DPM_GO_DOWN 2
#define DPM_GO_UP 3
#define SMU7_FIRST_DPM_GRAPHICS_LEVEL 0
#define SMU7_FIRST_DPM_MEMORY_LEVEL 0
#define GPIO_CLAMP_MODE_VRHOT 1
#define GPIO_CLAMP_MODE_THERM 2
#define GPIO_CLAMP_MODE_DC 4
#define SCRATCH_B_TARG_PCIE_INDEX_SHIFT 0
#define SCRATCH_B_TARG_PCIE_INDEX_MASK (0x7<<SCRATCH_B_TARG_PCIE_INDEX_SHIFT)
#define SCRATCH_B_CURR_PCIE_INDEX_SHIFT 3
#define SCRATCH_B_CURR_PCIE_INDEX_MASK (0x7<<SCRATCH_B_CURR_PCIE_INDEX_SHIFT)
#define SCRATCH_B_TARG_UVD_INDEX_SHIFT 6
#define SCRATCH_B_TARG_UVD_INDEX_MASK (0x7<<SCRATCH_B_TARG_UVD_INDEX_SHIFT)
#define SCRATCH_B_CURR_UVD_INDEX_SHIFT 9
#define SCRATCH_B_CURR_UVD_INDEX_MASK (0x7<<SCRATCH_B_CURR_UVD_INDEX_SHIFT)
#define SCRATCH_B_TARG_VCE_INDEX_SHIFT 12
#define SCRATCH_B_TARG_VCE_INDEX_MASK (0x7<<SCRATCH_B_TARG_VCE_INDEX_SHIFT)
#define SCRATCH_B_CURR_VCE_INDEX_SHIFT 15
#define SCRATCH_B_CURR_VCE_INDEX_MASK (0x7<<SCRATCH_B_CURR_VCE_INDEX_SHIFT)
#define SCRATCH_B_TARG_ACP_INDEX_SHIFT 18
#define SCRATCH_B_TARG_ACP_INDEX_MASK (0x7<<SCRATCH_B_TARG_ACP_INDEX_SHIFT)
#define SCRATCH_B_CURR_ACP_INDEX_SHIFT 21
#define SCRATCH_B_CURR_ACP_INDEX_MASK (0x7<<SCRATCH_B_CURR_ACP_INDEX_SHIFT)
#define SCRATCH_B_TARG_SAMU_INDEX_SHIFT 24
#define SCRATCH_B_TARG_SAMU_INDEX_MASK (0x7<<SCRATCH_B_TARG_SAMU_INDEX_SHIFT)
#define SCRATCH_B_CURR_SAMU_INDEX_SHIFT 27
#define SCRATCH_B_CURR_SAMU_INDEX_MASK (0x7<<SCRATCH_B_CURR_SAMU_INDEX_SHIFT)
struct SMU7_PIDController
{
uint32_t Ki;
int32_t LFWindupUL;
int32_t LFWindupLL;
uint32_t StatePrecision;
uint32_t LfPrecision;
uint32_t LfOffset;
uint32_t MaxState;
uint32_t MaxLfFraction;
uint32_t StateShift;
};
typedef struct SMU7_PIDController SMU7_PIDController;
// -------------------------------------------------------------------------------------------------------------------------
#define SMU7_MAX_PCIE_LINK_SPEEDS 3 /* 0:Gen1 1:Gen2 2:Gen3 */
#define SMU7_SCLK_DPM_CONFIG_MASK 0x01
#define SMU7_VOLTAGE_CONTROLLER_CONFIG_MASK 0x02
#define SMU7_THERMAL_CONTROLLER_CONFIG_MASK 0x04
#define SMU7_MCLK_DPM_CONFIG_MASK 0x08
#define SMU7_UVD_DPM_CONFIG_MASK 0x10
#define SMU7_VCE_DPM_CONFIG_MASK 0x20
#define SMU7_ACP_DPM_CONFIG_MASK 0x40
#define SMU7_SAMU_DPM_CONFIG_MASK 0x80
#define SMU7_PCIEGEN_DPM_CONFIG_MASK 0x100
#define SMU7_ACP_MCLK_HANDSHAKE_DISABLE 0x00000001
#define SMU7_ACP_SCLK_HANDSHAKE_DISABLE 0x00000002
#define SMU7_UVD_MCLK_HANDSHAKE_DISABLE 0x00000100
#define SMU7_UVD_SCLK_HANDSHAKE_DISABLE 0x00000200
#define SMU7_VCE_MCLK_HANDSHAKE_DISABLE 0x00010000
#define SMU7_VCE_SCLK_HANDSHAKE_DISABLE 0x00020000
struct SMU7_Firmware_Header
{
uint32_t Digest[5];
uint32_t Version;
uint32_t HeaderSize;
uint32_t Flags;
uint32_t EntryPoint;
uint32_t CodeSize;
uint32_t ImageSize;
uint32_t Rtos;
uint32_t SoftRegisters;
uint32_t DpmTable;
uint32_t FanTable;
uint32_t CacConfigTable;
uint32_t CacStatusTable;
uint32_t mcRegisterTable;
uint32_t mcArbDramTimingTable;
uint32_t PmFuseTable;
uint32_t Globals;
uint32_t Reserved[42];
uint32_t Signature;
};
typedef struct SMU7_Firmware_Header SMU7_Firmware_Header;
#define SMU7_FIRMWARE_HEADER_LOCATION 0x20000
enum DisplayConfig {
PowerDown = 1,
DP54x4,
DP54x2,
DP54x1,
DP27x4,
DP27x2,
DP27x1,
HDMI297,
HDMI162,
LVDS,
DP324x4,
DP324x2,
DP324x1
};
#pragma pack(pop)
#endif

View File

@ -0,0 +1,300 @@
/*
* Copyright 2013 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 SMU7_FUSION_H
#define SMU7_FUSION_H
#include "smu7.h"
#pragma pack(push, 1)
#define SMU7_DTE_ITERATIONS 5
#define SMU7_DTE_SOURCES 5
#define SMU7_DTE_SINKS 3
#define SMU7_NUM_CPU_TES 2
#define SMU7_NUM_GPU_TES 1
#define SMU7_NUM_NON_TES 2
// All 'soft registers' should be uint32_t.
struct SMU7_SoftRegisters
{
uint32_t RefClockFrequency;
uint32_t PmTimerP;
uint32_t FeatureEnables;
uint32_t HandshakeDisables;
uint8_t DisplayPhy1Config;
uint8_t DisplayPhy2Config;
uint8_t DisplayPhy3Config;
uint8_t DisplayPhy4Config;
uint8_t DisplayPhy5Config;
uint8_t DisplayPhy6Config;
uint8_t DisplayPhy7Config;
uint8_t DisplayPhy8Config;
uint32_t AverageGraphicsA;
uint32_t AverageMemoryA;
uint32_t AverageGioA;
uint8_t SClkDpmEnabledLevels;
uint8_t MClkDpmEnabledLevels;
uint8_t LClkDpmEnabledLevels;
uint8_t PCIeDpmEnabledLevels;
uint8_t UVDDpmEnabledLevels;
uint8_t SAMUDpmEnabledLevels;
uint8_t ACPDpmEnabledLevels;
uint8_t VCEDpmEnabledLevels;
uint32_t DRAM_LOG_ADDR_H;
uint32_t DRAM_LOG_ADDR_L;
uint32_t DRAM_LOG_PHY_ADDR_H;
uint32_t DRAM_LOG_PHY_ADDR_L;
uint32_t DRAM_LOG_BUFF_SIZE;
uint32_t UlvEnterC;
uint32_t UlvTime;
uint32_t Reserved[3];
};
typedef struct SMU7_SoftRegisters SMU7_SoftRegisters;
struct SMU7_Fusion_GraphicsLevel
{
uint32_t MinVddNb;
uint32_t SclkFrequency;
uint8_t Vid;
uint8_t VidOffset;
uint16_t AT;
uint8_t PowerThrottle;
uint8_t GnbSlow;
uint8_t ForceNbPs1;
uint8_t SclkDid;
uint8_t DisplayWatermark;
uint8_t EnabledForActivity;
uint8_t EnabledForThrottle;
uint8_t UpH;
uint8_t DownH;
uint8_t VoltageDownH;
uint8_t DeepSleepDivId;
uint8_t ClkBypassCntl;
uint32_t reserved;
};
typedef struct SMU7_Fusion_GraphicsLevel SMU7_Fusion_GraphicsLevel;
struct SMU7_Fusion_GIOLevel
{
uint8_t EnabledForActivity;
uint8_t LclkDid;
uint8_t Vid;
uint8_t VoltageDownH;
uint32_t MinVddNb;
uint16_t ResidencyCounter;
uint8_t UpH;
uint8_t DownH;
uint32_t LclkFrequency;
uint8_t ActivityLevel;
uint8_t EnabledForThrottle;
uint8_t ClkBypassCntl;
uint8_t padding;
};
typedef struct SMU7_Fusion_GIOLevel SMU7_Fusion_GIOLevel;
// UVD VCLK/DCLK state (level) definition.
struct SMU7_Fusion_UvdLevel
{
uint32_t VclkFrequency;
uint32_t DclkFrequency;
uint16_t MinVddNb;
uint8_t VclkDivider;
uint8_t DclkDivider;
uint8_t VClkBypassCntl;
uint8_t DClkBypassCntl;
uint8_t padding[2];
};
typedef struct SMU7_Fusion_UvdLevel SMU7_Fusion_UvdLevel;
// Clocks for other external blocks (VCE, ACP, SAMU).
struct SMU7_Fusion_ExtClkLevel
{
uint32_t Frequency;
uint16_t MinVoltage;
uint8_t Divider;
uint8_t ClkBypassCntl;
uint32_t Reserved;
};
typedef struct SMU7_Fusion_ExtClkLevel SMU7_Fusion_ExtClkLevel;
struct SMU7_Fusion_ACPILevel
{
uint32_t Flags;
uint32_t MinVddNb;
uint32_t SclkFrequency;
uint8_t SclkDid;
uint8_t GnbSlow;
uint8_t ForceNbPs1;
uint8_t DisplayWatermark;
uint8_t DeepSleepDivId;
uint8_t padding[3];
};
typedef struct SMU7_Fusion_ACPILevel SMU7_Fusion_ACPILevel;
struct SMU7_Fusion_NbDpm
{
uint8_t DpmXNbPsHi;
uint8_t DpmXNbPsLo;
uint8_t Dpm0PgNbPsHi;
uint8_t Dpm0PgNbPsLo;
uint8_t EnablePsi1;
uint8_t SkipDPM0;
uint8_t SkipPG;
uint8_t Hysteresis;
uint8_t EnableDpmPstatePoll;
uint8_t padding[3];
};
typedef struct SMU7_Fusion_NbDpm SMU7_Fusion_NbDpm;
struct SMU7_Fusion_StateInfo
{
uint32_t SclkFrequency;
uint32_t LclkFrequency;
uint32_t VclkFrequency;
uint32_t DclkFrequency;
uint32_t SamclkFrequency;
uint32_t AclkFrequency;
uint32_t EclkFrequency;
uint8_t DisplayWatermark;
uint8_t McArbIndex;
int8_t SclkIndex;
int8_t MclkIndex;
};
typedef struct SMU7_Fusion_StateInfo SMU7_Fusion_StateInfo;
struct SMU7_Fusion_DpmTable
{
uint32_t SystemFlags;
SMU7_PIDController GraphicsPIDController;
SMU7_PIDController GioPIDController;
uint8_t GraphicsDpmLevelCount;
uint8_t GIOLevelCount;
uint8_t UvdLevelCount;
uint8_t VceLevelCount;
uint8_t AcpLevelCount;
uint8_t SamuLevelCount;
uint16_t FpsHighT;
SMU7_Fusion_GraphicsLevel GraphicsLevel [SMU__NUM_SCLK_DPM_STATE];
SMU7_Fusion_ACPILevel ACPILevel;
SMU7_Fusion_UvdLevel UvdLevel [SMU7_MAX_LEVELS_UVD];
SMU7_Fusion_ExtClkLevel VceLevel [SMU7_MAX_LEVELS_VCE];
SMU7_Fusion_ExtClkLevel AcpLevel [SMU7_MAX_LEVELS_ACP];
SMU7_Fusion_ExtClkLevel SamuLevel [SMU7_MAX_LEVELS_SAMU];
uint8_t UvdBootLevel;
uint8_t VceBootLevel;
uint8_t AcpBootLevel;
uint8_t SamuBootLevel;
uint8_t UVDInterval;
uint8_t VCEInterval;
uint8_t ACPInterval;
uint8_t SAMUInterval;
uint8_t GraphicsBootLevel;
uint8_t GraphicsInterval;
uint8_t GraphicsThermThrottleEnable;
uint8_t GraphicsVoltageChangeEnable;
uint8_t GraphicsClkSlowEnable;
uint8_t GraphicsClkSlowDivider;
uint16_t FpsLowT;
uint32_t DisplayCac;
uint32_t LowSclkInterruptT;
uint32_t DRAM_LOG_ADDR_H;
uint32_t DRAM_LOG_ADDR_L;
uint32_t DRAM_LOG_PHY_ADDR_H;
uint32_t DRAM_LOG_PHY_ADDR_L;
uint32_t DRAM_LOG_BUFF_SIZE;
};
struct SMU7_Fusion_GIODpmTable
{
SMU7_Fusion_GIOLevel GIOLevel [SMU7_MAX_LEVELS_GIO];
SMU7_PIDController GioPIDController;
uint32_t GIOLevelCount;
uint8_t Enable;
uint8_t GIOVoltageChangeEnable;
uint8_t GIOBootLevel;
uint8_t padding;
uint8_t padding1[2];
uint8_t TargetState;
uint8_t CurrenttState;
uint8_t ThrottleOnHtc;
uint8_t ThermThrottleStatus;
uint8_t ThermThrottleTempSelect;
uint8_t ThermThrottleEnable;
uint16_t TemperatureLimitHigh;
uint16_t TemperatureLimitLow;
};
typedef struct SMU7_Fusion_DpmTable SMU7_Fusion_DpmTable;
typedef struct SMU7_Fusion_GIODpmTable SMU7_Fusion_GIODpmTable;
#pragma pack(pop)
#endif