mirror of
https://github.com/torvalds/linux
synced 2024-10-05 19:02:12 +00:00
amd-drm-fixes-6.8-2024-01-25:
amdgpu: - AC/DC power supply tracking fix - Don't show invalid vram vendor data - SMU 13.0.x fixes - GART fix for umr on systems without VRAM - GFX 10/11 UNORD_DISPATCH fixes - IPS display fixes (required for S0ix on some platforms) - Misc fixes -----BEGIN PGP SIGNATURE----- iHUEABYKAB0WIQQgO5Idg2tXNTSZAr293/aFa7yZ2AUCZbLbpwAKCRC93/aFa7yZ 2D2cAQCbpuo2Yuxo+LyfB7+k8NzcnNRIJTRsTfsiGVk/wx4hNQEA0DIq1Ellldpx yMfwQzbZPoY/KacrVySTSWDTs0BNBAE= =V5bS -----END PGP SIGNATURE----- Merge tag 'amd-drm-fixes-6.8-2024-01-25' of https://gitlab.freedesktop.org/agd5f/linux into drm-fixes amd-drm-fixes-6.8-2024-01-25: amdgpu: - AC/DC power supply tracking fix - Don't show invalid vram vendor data - SMU 13.0.x fixes - GART fix for umr on systems without VRAM - GFX 10/11 UNORD_DISPATCH fixes - IPS display fixes (required for S0ix on some platforms) - Misc fixes Signed-off-by: Dave Airlie <airlied@redhat.com> From: Alex Deucher <alexander.deucher@amd.com> Link: https://patchwork.freedesktop.org/patch/msgid/20240125221503.5019-1-alexander.deucher@amd.com
This commit is contained in:
commit
77fe8f1957
|
@ -121,6 +121,7 @@ int amdgpu_gart_table_ram_alloc(struct amdgpu_device *adev)
|
|||
struct amdgpu_bo_param bp;
|
||||
dma_addr_t dma_addr;
|
||||
struct page *p;
|
||||
unsigned long x;
|
||||
int ret;
|
||||
|
||||
if (adev->gart.bo != NULL)
|
||||
|
@ -130,6 +131,10 @@ int amdgpu_gart_table_ram_alloc(struct amdgpu_device *adev)
|
|||
if (!p)
|
||||
return -ENOMEM;
|
||||
|
||||
/* assign pages to this device */
|
||||
for (x = 0; x < (1UL << order); x++)
|
||||
p[x].mapping = adev->mman.bdev.dev_mapping;
|
||||
|
||||
/* If the hardware does not support UTCL2 snooping of the CPU caches
|
||||
* then set_memory_wc() could be used as a workaround to mark the pages
|
||||
* as write combine memory.
|
||||
|
@ -223,6 +228,7 @@ void amdgpu_gart_table_ram_free(struct amdgpu_device *adev)
|
|||
unsigned int order = get_order(adev->gart.table_size);
|
||||
struct sg_table *sg = adev->gart.bo->tbo.sg;
|
||||
struct page *p;
|
||||
unsigned long x;
|
||||
int ret;
|
||||
|
||||
ret = amdgpu_bo_reserve(adev->gart.bo, false);
|
||||
|
@ -234,6 +240,8 @@ void amdgpu_gart_table_ram_free(struct amdgpu_device *adev)
|
|||
sg_free_table(sg);
|
||||
kfree(sg);
|
||||
p = virt_to_page(adev->gart.ptr);
|
||||
for (x = 0; x < (1UL << order); x++)
|
||||
p[x].mapping = NULL;
|
||||
__free_pages(p, order);
|
||||
|
||||
adev->gart.ptr = NULL;
|
||||
|
|
|
@ -221,8 +221,23 @@ static struct attribute *amdgpu_vram_mgr_attributes[] = {
|
|||
NULL
|
||||
};
|
||||
|
||||
static umode_t amdgpu_vram_attrs_is_visible(struct kobject *kobj,
|
||||
struct attribute *attr, int i)
|
||||
{
|
||||
struct device *dev = kobj_to_dev(kobj);
|
||||
struct drm_device *ddev = dev_get_drvdata(dev);
|
||||
struct amdgpu_device *adev = drm_to_adev(ddev);
|
||||
|
||||
if (attr == &dev_attr_mem_info_vram_vendor.attr &&
|
||||
!adev->gmc.vram_vendor)
|
||||
return 0;
|
||||
|
||||
return attr->mode;
|
||||
}
|
||||
|
||||
const struct attribute_group amdgpu_vram_mgr_attr_group = {
|
||||
.attrs = amdgpu_vram_mgr_attributes
|
||||
.attrs = amdgpu_vram_mgr_attributes,
|
||||
.is_visible = amdgpu_vram_attrs_is_visible
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
|
@ -6589,7 +6589,7 @@ static int gfx_v10_0_compute_mqd_init(struct amdgpu_device *adev, void *m,
|
|||
#ifdef __BIG_ENDIAN
|
||||
tmp = REG_SET_FIELD(tmp, CP_HQD_PQ_CONTROL, ENDIAN_SWAP, 1);
|
||||
#endif
|
||||
tmp = REG_SET_FIELD(tmp, CP_HQD_PQ_CONTROL, UNORD_DISPATCH, 0);
|
||||
tmp = REG_SET_FIELD(tmp, CP_HQD_PQ_CONTROL, UNORD_DISPATCH, 1);
|
||||
tmp = REG_SET_FIELD(tmp, CP_HQD_PQ_CONTROL, TUNNEL_DISPATCH,
|
||||
prop->allow_tunneling);
|
||||
tmp = REG_SET_FIELD(tmp, CP_HQD_PQ_CONTROL, PRIV_STATE, 1);
|
||||
|
|
|
@ -3846,7 +3846,7 @@ static int gfx_v11_0_compute_mqd_init(struct amdgpu_device *adev, void *m,
|
|||
(order_base_2(prop->queue_size / 4) - 1));
|
||||
tmp = REG_SET_FIELD(tmp, CP_HQD_PQ_CONTROL, RPTR_BLOCK_SIZE,
|
||||
(order_base_2(AMDGPU_GPU_PAGE_SIZE / 4) - 1));
|
||||
tmp = REG_SET_FIELD(tmp, CP_HQD_PQ_CONTROL, UNORD_DISPATCH, 0);
|
||||
tmp = REG_SET_FIELD(tmp, CP_HQD_PQ_CONTROL, UNORD_DISPATCH, 1);
|
||||
tmp = REG_SET_FIELD(tmp, CP_HQD_PQ_CONTROL, TUNNEL_DISPATCH,
|
||||
prop->allow_tunneling);
|
||||
tmp = REG_SET_FIELD(tmp, CP_HQD_PQ_CONTROL, PRIV_STATE, 1);
|
||||
|
|
|
@ -1950,7 +1950,8 @@ static void gmc_v9_4_3_init_vram_info(struct amdgpu_device *adev)
|
|||
static const u32 regBIF_BIOS_SCRATCH_4 = 0x50;
|
||||
u32 vram_info;
|
||||
|
||||
if (!amdgpu_sriov_vf(adev)) {
|
||||
/* Only for dGPU, vendor informaton is reliable */
|
||||
if (!amdgpu_sriov_vf(adev) && !(adev->flags & AMD_IS_APU)) {
|
||||
vram_info = RREG32(regBIF_BIOS_SCRATCH_4);
|
||||
adev->gmc.vram_vendor = vram_info & 0xF;
|
||||
}
|
||||
|
|
|
@ -170,6 +170,7 @@ static void update_mqd(struct mqd_manager *mm, void *mqd,
|
|||
m->cp_hqd_pq_control = 5 << CP_HQD_PQ_CONTROL__RPTR_BLOCK_SIZE__SHIFT;
|
||||
m->cp_hqd_pq_control |=
|
||||
ffs(q->queue_size / sizeof(unsigned int)) - 1 - 1;
|
||||
m->cp_hqd_pq_control |= CP_HQD_PQ_CONTROL__UNORD_DISPATCH_MASK;
|
||||
pr_debug("cp_hqd_pq_control 0x%x\n", m->cp_hqd_pq_control);
|
||||
|
||||
m->cp_hqd_pq_base_lo = lower_32_bits((uint64_t)q->queue_address >> 8);
|
||||
|
|
|
@ -224,6 +224,7 @@ static void update_mqd(struct mqd_manager *mm, void *mqd,
|
|||
m->cp_hqd_pq_control = 5 << CP_HQD_PQ_CONTROL__RPTR_BLOCK_SIZE__SHIFT;
|
||||
m->cp_hqd_pq_control |=
|
||||
ffs(q->queue_size / sizeof(unsigned int)) - 1 - 1;
|
||||
m->cp_hqd_pq_control |= CP_HQD_PQ_CONTROL__UNORD_DISPATCH_MASK;
|
||||
pr_debug("cp_hqd_pq_control 0x%x\n", m->cp_hqd_pq_control);
|
||||
|
||||
m->cp_hqd_pq_base_lo = lower_32_bits((uint64_t)q->queue_address >> 8);
|
||||
|
|
|
@ -272,6 +272,7 @@ static int dm_crtc_get_scanoutpos(struct amdgpu_device *adev, int crtc,
|
|||
{
|
||||
u32 v_blank_start, v_blank_end, h_position, v_position;
|
||||
struct amdgpu_crtc *acrtc = NULL;
|
||||
struct dc *dc = adev->dm.dc;
|
||||
|
||||
if ((crtc < 0) || (crtc >= adev->mode_info.num_crtc))
|
||||
return -EINVAL;
|
||||
|
@ -284,6 +285,9 @@ static int dm_crtc_get_scanoutpos(struct amdgpu_device *adev, int crtc,
|
|||
return 0;
|
||||
}
|
||||
|
||||
if (dc && dc->caps.ips_support && dc->idle_optimizations_allowed)
|
||||
dc_allow_idle_optimizations(dc, false);
|
||||
|
||||
/*
|
||||
* TODO rework base driver to use values directly.
|
||||
* for now parse it back into reg-format
|
||||
|
@ -1715,7 +1719,10 @@ static int amdgpu_dm_init(struct amdgpu_device *adev)
|
|||
init_data.nbio_reg_offsets = adev->reg_offset[NBIO_HWIP][0];
|
||||
init_data.clk_reg_offsets = adev->reg_offset[CLK_HWIP][0];
|
||||
|
||||
init_data.flags.disable_ips = DMUB_IPS_DISABLE_ALL;
|
||||
if (amdgpu_dc_debug_mask & DC_DISABLE_IPS)
|
||||
init_data.flags.disable_ips = DMUB_IPS_DISABLE_ALL;
|
||||
|
||||
init_data.flags.disable_ips_in_vpb = 1;
|
||||
|
||||
/* Enable DWB for tested platforms only */
|
||||
if (amdgpu_ip_version(adev, DCE_HWIP, 0) >= IP_VERSION(3, 0, 0))
|
||||
|
@ -8976,16 +8983,8 @@ static void amdgpu_dm_atomic_commit_tail(struct drm_atomic_state *state)
|
|||
|
||||
trace_amdgpu_dm_atomic_commit_tail_begin(state);
|
||||
|
||||
if (dm->dc->caps.ips_support) {
|
||||
for_each_oldnew_connector_in_state(state, connector, old_con_state, new_con_state, i) {
|
||||
if (new_con_state->crtc &&
|
||||
new_con_state->crtc->state->active &&
|
||||
drm_atomic_crtc_needs_modeset(new_con_state->crtc->state)) {
|
||||
dc_dmub_srv_apply_idle_power_optimizations(dm->dc, false);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (dm->dc->caps.ips_support && dm->dc->idle_optimizations_allowed)
|
||||
dc_allow_idle_optimizations(dm->dc, false);
|
||||
|
||||
drm_atomic_helper_update_legacy_modeset_state(dev, state);
|
||||
drm_dp_mst_atomic_wait_for_dependencies(state);
|
||||
|
|
|
@ -711,7 +711,7 @@ static inline int dm_irq_state(struct amdgpu_device *adev,
|
|||
{
|
||||
bool st;
|
||||
enum dc_irq_source irq_source;
|
||||
|
||||
struct dc *dc = adev->dm.dc;
|
||||
struct amdgpu_crtc *acrtc = adev->mode_info.crtcs[crtc_id];
|
||||
|
||||
if (!acrtc) {
|
||||
|
@ -729,6 +729,9 @@ static inline int dm_irq_state(struct amdgpu_device *adev,
|
|||
|
||||
st = (state == AMDGPU_IRQ_STATE_ENABLE);
|
||||
|
||||
if (dc && dc->caps.ips_support && dc->idle_optimizations_allowed)
|
||||
dc_allow_idle_optimizations(dc, false);
|
||||
|
||||
dc_interrupt_set(adev->dm.dc, irq_source, st);
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -434,6 +434,7 @@ struct dc_config {
|
|||
bool EnableMinDispClkODM;
|
||||
bool enable_auto_dpm_test_logs;
|
||||
unsigned int disable_ips;
|
||||
unsigned int disable_ips_in_vpb;
|
||||
};
|
||||
|
||||
enum visual_confirm {
|
||||
|
|
|
@ -1034,6 +1034,7 @@ enum replay_FW_Message_type {
|
|||
Replay_Msg_Not_Support = -1,
|
||||
Replay_Set_Timing_Sync_Supported,
|
||||
Replay_Set_Residency_Frameupdate_Timer,
|
||||
Replay_Set_Pseudo_VTotal,
|
||||
};
|
||||
|
||||
union replay_error_status {
|
||||
|
@ -1089,6 +1090,10 @@ struct replay_settings {
|
|||
uint16_t coasting_vtotal_table[PR_COASTING_TYPE_NUM];
|
||||
/* Maximum link off frame count */
|
||||
enum replay_link_off_frame_count_level link_off_frame_count_level;
|
||||
/* Replay pseudo vtotal for abm + ips on full screen video which can improve ips residency */
|
||||
uint16_t abm_with_ips_on_full_screen_video_pseudo_vtotal;
|
||||
/* Replay last pseudo vtotal set to DMUB */
|
||||
uint16_t last_pseudo_vtotal;
|
||||
};
|
||||
|
||||
/* To split out "global" and "per-panel" config settings.
|
||||
|
|
|
@ -680,7 +680,7 @@ void dcn35_power_down_on_boot(struct dc *dc)
|
|||
bool dcn35_apply_idle_power_optimizations(struct dc *dc, bool enable)
|
||||
{
|
||||
struct dc_link *edp_links[MAX_NUM_EDP];
|
||||
int edp_num;
|
||||
int i, edp_num;
|
||||
if (dc->debug.dmcub_emulation)
|
||||
return true;
|
||||
|
||||
|
@ -688,6 +688,13 @@ bool dcn35_apply_idle_power_optimizations(struct dc *dc, bool enable)
|
|||
dc_get_edp_links(dc, edp_links, &edp_num);
|
||||
if (edp_num == 0 || edp_num > 1)
|
||||
return false;
|
||||
|
||||
for (i = 0; i < dc->current_state->stream_count; ++i) {
|
||||
struct dc_stream_state *stream = dc->current_state->streams[i];
|
||||
|
||||
if (!stream->dpms_off && !dc_is_embedded_signal(stream->signal))
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: review other cases when idle optimization is allowed
|
||||
|
|
|
@ -205,7 +205,7 @@ enum dc_status core_link_read_dpcd(
|
|||
uint32_t extended_size;
|
||||
/* size of the remaining partitioned address space */
|
||||
uint32_t size_left_to_read;
|
||||
enum dc_status status;
|
||||
enum dc_status status = DC_ERROR_UNEXPECTED;
|
||||
/* size of the next partition to be read from */
|
||||
uint32_t partition_size;
|
||||
uint32_t data_index = 0;
|
||||
|
@ -234,7 +234,7 @@ enum dc_status core_link_write_dpcd(
|
|||
{
|
||||
uint32_t partition_size;
|
||||
uint32_t data_index = 0;
|
||||
enum dc_status status;
|
||||
enum dc_status status = DC_ERROR_UNEXPECTED;
|
||||
|
||||
while (size) {
|
||||
partition_size = dpcd_get_next_partition_size(address, size);
|
||||
|
|
|
@ -2832,6 +2832,7 @@ struct dmub_rb_cmd_psr_set_power_opt {
|
|||
#define REPLAY_RESIDENCY_MODE_MASK (0x1 << REPLAY_RESIDENCY_MODE_SHIFT)
|
||||
# define REPLAY_RESIDENCY_MODE_PHY (0x0 << REPLAY_RESIDENCY_MODE_SHIFT)
|
||||
# define REPLAY_RESIDENCY_MODE_ALPM (0x1 << REPLAY_RESIDENCY_MODE_SHIFT)
|
||||
# define REPLAY_RESIDENCY_MODE_IPS 0x10
|
||||
|
||||
#define REPLAY_RESIDENCY_ENABLE_MASK (0x1 << REPLAY_RESIDENCY_ENABLE_SHIFT)
|
||||
# define REPLAY_RESIDENCY_DISABLE (0x0 << REPLAY_RESIDENCY_ENABLE_SHIFT)
|
||||
|
@ -2894,6 +2895,10 @@ enum dmub_cmd_replay_type {
|
|||
* Set Residency Frameupdate Timer.
|
||||
*/
|
||||
DMUB_CMD__REPLAY_SET_RESIDENCY_FRAMEUPDATE_TIMER = 6,
|
||||
/**
|
||||
* Set pseudo vtotal
|
||||
*/
|
||||
DMUB_CMD__REPLAY_SET_PSEUDO_VTOTAL = 7,
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -3076,6 +3081,26 @@ struct dmub_cmd_replay_set_timing_sync_data {
|
|||
uint8_t pad[2];
|
||||
};
|
||||
|
||||
/**
|
||||
* Data passed from driver to FW in a DMUB_CMD__REPLAY_SET_PSEUDO_VTOTAL command.
|
||||
*/
|
||||
struct dmub_cmd_replay_set_pseudo_vtotal {
|
||||
/**
|
||||
* Panel Instance.
|
||||
* Panel isntance to identify which replay_state to use
|
||||
* Currently the support is only for 0 or 1
|
||||
*/
|
||||
uint8_t panel_inst;
|
||||
/**
|
||||
* Source Vtotal that Replay + IPS + ABM full screen video src vtotal
|
||||
*/
|
||||
uint16_t vtotal;
|
||||
/**
|
||||
* Explicit padding to 4 byte boundary.
|
||||
*/
|
||||
uint8_t pad;
|
||||
};
|
||||
|
||||
/**
|
||||
* Definition of a DMUB_CMD__SET_REPLAY_POWER_OPT command.
|
||||
*/
|
||||
|
@ -3156,6 +3181,20 @@ struct dmub_rb_cmd_replay_set_timing_sync {
|
|||
struct dmub_cmd_replay_set_timing_sync_data replay_set_timing_sync_data;
|
||||
};
|
||||
|
||||
/**
|
||||
* Definition of a DMUB_CMD__REPLAY_SET_PSEUDO_VTOTAL command.
|
||||
*/
|
||||
struct dmub_rb_cmd_replay_set_pseudo_vtotal {
|
||||
/**
|
||||
* Command header.
|
||||
*/
|
||||
struct dmub_cmd_header header;
|
||||
/**
|
||||
* Definition of DMUB_CMD__REPLAY_SET_PSEUDO_VTOTAL command.
|
||||
*/
|
||||
struct dmub_cmd_replay_set_pseudo_vtotal data;
|
||||
};
|
||||
|
||||
/**
|
||||
* Data passed from driver to FW in DMUB_CMD__REPLAY_SET_RESIDENCY_FRAMEUPDATE_TIMER command.
|
||||
*/
|
||||
|
@ -3207,6 +3246,10 @@ union dmub_replay_cmd_set {
|
|||
* Definition of DMUB_CMD__REPLAY_SET_RESIDENCY_FRAMEUPDATE_TIMER command data.
|
||||
*/
|
||||
struct dmub_cmd_replay_frameupdate_timer_data timer_data;
|
||||
/**
|
||||
* Definition of DMUB_CMD__REPLAY_SET_PSEUDO_VTOTAL command data.
|
||||
*/
|
||||
struct dmub_cmd_replay_set_pseudo_vtotal pseudo_vtotal_data;
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -4358,6 +4401,10 @@ union dmub_rb_cmd {
|
|||
* Definition of a DMUB_CMD__REPLAY_SET_RESIDENCY_FRAMEUPDATE_TIMER command.
|
||||
*/
|
||||
struct dmub_rb_cmd_replay_set_frameupdate_timer replay_set_frameupdate_timer;
|
||||
/**
|
||||
* Definition of a DMUB_CMD__REPLAY_SET_PSEUDO_VTOTAL command.
|
||||
*/
|
||||
struct dmub_rb_cmd_replay_set_pseudo_vtotal replay_set_pseudo_vtotal;
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
|
@ -980,6 +980,11 @@ void set_replay_coasting_vtotal(struct dc_link *link,
|
|||
link->replay_settings.coasting_vtotal_table[type] = vtotal;
|
||||
}
|
||||
|
||||
void set_replay_ips_full_screen_video_src_vtotal(struct dc_link *link, uint16_t vtotal)
|
||||
{
|
||||
link->replay_settings.abm_with_ips_on_full_screen_video_pseudo_vtotal = vtotal;
|
||||
}
|
||||
|
||||
void calculate_replay_link_off_frame_count(struct dc_link *link,
|
||||
uint16_t vtotal, uint16_t htotal)
|
||||
{
|
||||
|
|
|
@ -57,6 +57,7 @@ void init_replay_config(struct dc_link *link, struct replay_config *pr_config);
|
|||
void set_replay_coasting_vtotal(struct dc_link *link,
|
||||
enum replay_coasting_vtotal_type type,
|
||||
uint16_t vtotal);
|
||||
void set_replay_ips_full_screen_video_src_vtotal(struct dc_link *link, uint16_t vtotal);
|
||||
void calculate_replay_link_off_frame_count(struct dc_link *link,
|
||||
uint16_t vtotal, uint16_t htotal);
|
||||
|
||||
|
|
|
@ -258,6 +258,7 @@ enum DC_DEBUG_MASK {
|
|||
DC_ENABLE_DML2 = 0x100,
|
||||
DC_DISABLE_PSR_SU = 0x200,
|
||||
DC_DISABLE_REPLAY = 0x400,
|
||||
DC_DISABLE_IPS = 0x800,
|
||||
};
|
||||
|
||||
enum amd_dpm_forced_level;
|
||||
|
|
|
@ -138,7 +138,7 @@ static inline size_t amdgpu_reginst_size(uint16_t num_inst, size_t inst_size,
|
|||
}
|
||||
|
||||
#define amdgpu_asic_get_reg_state_supported(adev) \
|
||||
((adev)->asic_funcs->get_reg_state ? 1 : 0)
|
||||
(((adev)->asic_funcs && (adev)->asic_funcs->get_reg_state) ? 1 : 0)
|
||||
|
||||
#define amdgpu_asic_get_reg_state(adev, state, buf, size) \
|
||||
((adev)->asic_funcs->get_reg_state ? \
|
||||
|
|
|
@ -24,6 +24,7 @@
|
|||
|
||||
#include <linux/firmware.h>
|
||||
#include <linux/pci.h>
|
||||
#include <linux/power_supply.h>
|
||||
#include <linux/reboot.h>
|
||||
|
||||
#include "amdgpu.h"
|
||||
|
@ -817,16 +818,8 @@ static int smu_late_init(void *handle)
|
|||
* handle the switch automatically. Driver involvement
|
||||
* is unnecessary.
|
||||
*/
|
||||
if (!smu->dc_controlled_by_gpio) {
|
||||
ret = smu_set_power_source(smu,
|
||||
adev->pm.ac_power ? SMU_POWER_SOURCE_AC :
|
||||
SMU_POWER_SOURCE_DC);
|
||||
if (ret) {
|
||||
dev_err(adev->dev, "Failed to switch to %s mode!\n",
|
||||
adev->pm.ac_power ? "AC" : "DC");
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
adev->pm.ac_power = power_supply_is_system_supplied() > 0;
|
||||
smu_set_ac_dc(smu);
|
||||
|
||||
if ((amdgpu_ip_version(adev, MP1_HWIP, 0) == IP_VERSION(13, 0, 1)) ||
|
||||
(amdgpu_ip_version(adev, MP1_HWIP, 0) == IP_VERSION(13, 0, 3)))
|
||||
|
@ -2710,6 +2703,7 @@ int smu_get_power_limit(void *handle,
|
|||
case SMU_PPT_LIMIT_CURRENT:
|
||||
switch (amdgpu_ip_version(adev, MP1_HWIP, 0)) {
|
||||
case IP_VERSION(13, 0, 2):
|
||||
case IP_VERSION(13, 0, 6):
|
||||
case IP_VERSION(11, 0, 7):
|
||||
case IP_VERSION(11, 0, 11):
|
||||
case IP_VERSION(11, 0, 12):
|
||||
|
|
|
@ -1442,10 +1442,12 @@ static int smu_v11_0_irq_process(struct amdgpu_device *adev,
|
|||
case 0x3:
|
||||
dev_dbg(adev->dev, "Switched to AC mode!\n");
|
||||
schedule_work(&smu->interrupt_work);
|
||||
adev->pm.ac_power = true;
|
||||
break;
|
||||
case 0x4:
|
||||
dev_dbg(adev->dev, "Switched to DC mode!\n");
|
||||
schedule_work(&smu->interrupt_work);
|
||||
adev->pm.ac_power = false;
|
||||
break;
|
||||
case 0x7:
|
||||
/*
|
||||
|
|
|
@ -1379,10 +1379,12 @@ static int smu_v13_0_irq_process(struct amdgpu_device *adev,
|
|||
case 0x3:
|
||||
dev_dbg(adev->dev, "Switched to AC mode!\n");
|
||||
smu_v13_0_ack_ac_dc_interrupt(smu);
|
||||
adev->pm.ac_power = true;
|
||||
break;
|
||||
case 0x4:
|
||||
dev_dbg(adev->dev, "Switched to DC mode!\n");
|
||||
smu_v13_0_ack_ac_dc_interrupt(smu);
|
||||
adev->pm.ac_power = false;
|
||||
break;
|
||||
case 0x7:
|
||||
/*
|
||||
|
|
|
@ -2357,6 +2357,7 @@ static int smu_v13_0_0_get_power_limit(struct smu_context *smu,
|
|||
PPTable_t *pptable = table_context->driver_pptable;
|
||||
SkuTable_t *skutable = &pptable->SkuTable;
|
||||
uint32_t power_limit, od_percent_upper, od_percent_lower;
|
||||
uint32_t msg_limit = skutable->MsgLimits.Power[PPT_THROTTLER_PPT0][POWER_SOURCE_AC];
|
||||
|
||||
if (smu_v13_0_get_current_power_limit(smu, &power_limit))
|
||||
power_limit = smu->adev->pm.ac_power ?
|
||||
|
@ -2380,7 +2381,7 @@ static int smu_v13_0_0_get_power_limit(struct smu_context *smu,
|
|||
od_percent_upper, od_percent_lower, power_limit);
|
||||
|
||||
if (max_power_limit) {
|
||||
*max_power_limit = power_limit * (100 + od_percent_upper);
|
||||
*max_power_limit = msg_limit * (100 + od_percent_upper);
|
||||
*max_power_limit /= 100;
|
||||
}
|
||||
|
||||
|
@ -2959,6 +2960,55 @@ static bool smu_v13_0_0_wbrf_support_check(struct smu_context *smu)
|
|||
}
|
||||
}
|
||||
|
||||
static int smu_v13_0_0_set_power_limit(struct smu_context *smu,
|
||||
enum smu_ppt_limit_type limit_type,
|
||||
uint32_t limit)
|
||||
{
|
||||
PPTable_t *pptable = smu->smu_table.driver_pptable;
|
||||
SkuTable_t *skutable = &pptable->SkuTable;
|
||||
uint32_t msg_limit = skutable->MsgLimits.Power[PPT_THROTTLER_PPT0][POWER_SOURCE_AC];
|
||||
struct smu_table_context *table_context = &smu->smu_table;
|
||||
OverDriveTableExternal_t *od_table =
|
||||
(OverDriveTableExternal_t *)table_context->overdrive_table;
|
||||
int ret = 0;
|
||||
|
||||
if (limit_type != SMU_DEFAULT_PPT_LIMIT)
|
||||
return -EINVAL;
|
||||
|
||||
if (limit <= msg_limit) {
|
||||
if (smu->current_power_limit > msg_limit) {
|
||||
od_table->OverDriveTable.Ppt = 0;
|
||||
od_table->OverDriveTable.FeatureCtrlMask |= 1U << PP_OD_FEATURE_PPT_BIT;
|
||||
|
||||
ret = smu_v13_0_0_upload_overdrive_table(smu, od_table);
|
||||
if (ret) {
|
||||
dev_err(smu->adev->dev, "Failed to upload overdrive table!\n");
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
return smu_v13_0_set_power_limit(smu, limit_type, limit);
|
||||
} else if (smu->od_enabled) {
|
||||
ret = smu_v13_0_set_power_limit(smu, limit_type, msg_limit);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
od_table->OverDriveTable.Ppt = (limit * 100) / msg_limit - 100;
|
||||
od_table->OverDriveTable.FeatureCtrlMask |= 1U << PP_OD_FEATURE_PPT_BIT;
|
||||
|
||||
ret = smu_v13_0_0_upload_overdrive_table(smu, od_table);
|
||||
if (ret) {
|
||||
dev_err(smu->adev->dev, "Failed to upload overdrive table!\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
smu->current_power_limit = limit;
|
||||
} else {
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct pptable_funcs smu_v13_0_0_ppt_funcs = {
|
||||
.get_allowed_feature_mask = smu_v13_0_0_get_allowed_feature_mask,
|
||||
.set_default_dpm_table = smu_v13_0_0_set_default_dpm_table,
|
||||
|
@ -3013,7 +3063,7 @@ static const struct pptable_funcs smu_v13_0_0_ppt_funcs = {
|
|||
.set_fan_control_mode = smu_v13_0_set_fan_control_mode,
|
||||
.enable_mgpu_fan_boost = smu_v13_0_0_enable_mgpu_fan_boost,
|
||||
.get_power_limit = smu_v13_0_0_get_power_limit,
|
||||
.set_power_limit = smu_v13_0_set_power_limit,
|
||||
.set_power_limit = smu_v13_0_0_set_power_limit,
|
||||
.set_power_source = smu_v13_0_set_power_source,
|
||||
.get_power_profile_mode = smu_v13_0_0_get_power_profile_mode,
|
||||
.set_power_profile_mode = smu_v13_0_0_set_power_profile_mode,
|
||||
|
|
|
@ -160,8 +160,8 @@ static const struct cmn2asic_msg_mapping smu_v13_0_6_message_map[SMU_MSG_MAX_COU
|
|||
MSG_MAP(GfxDriverResetRecovery, PPSMC_MSG_GfxDriverResetRecovery, 0),
|
||||
MSG_MAP(GetMinGfxclkFrequency, PPSMC_MSG_GetMinGfxDpmFreq, 1),
|
||||
MSG_MAP(GetMaxGfxclkFrequency, PPSMC_MSG_GetMaxGfxDpmFreq, 1),
|
||||
MSG_MAP(SetSoftMinGfxclk, PPSMC_MSG_SetSoftMinGfxClk, 0),
|
||||
MSG_MAP(SetSoftMaxGfxClk, PPSMC_MSG_SetSoftMaxGfxClk, 0),
|
||||
MSG_MAP(SetSoftMinGfxclk, PPSMC_MSG_SetSoftMinGfxClk, 1),
|
||||
MSG_MAP(SetSoftMaxGfxClk, PPSMC_MSG_SetSoftMaxGfxClk, 1),
|
||||
MSG_MAP(PrepareMp1ForUnload, PPSMC_MSG_PrepareForDriverUnload, 0),
|
||||
MSG_MAP(GetCTFLimit, PPSMC_MSG_GetCTFLimit, 0),
|
||||
MSG_MAP(GetThermalLimit, PPSMC_MSG_ReadThrottlerLimit, 0),
|
||||
|
|
|
@ -2321,6 +2321,7 @@ static int smu_v13_0_7_get_power_limit(struct smu_context *smu,
|
|||
PPTable_t *pptable = table_context->driver_pptable;
|
||||
SkuTable_t *skutable = &pptable->SkuTable;
|
||||
uint32_t power_limit, od_percent_upper, od_percent_lower;
|
||||
uint32_t msg_limit = skutable->MsgLimits.Power[PPT_THROTTLER_PPT0][POWER_SOURCE_AC];
|
||||
|
||||
if (smu_v13_0_get_current_power_limit(smu, &power_limit))
|
||||
power_limit = smu->adev->pm.ac_power ?
|
||||
|
@ -2344,7 +2345,7 @@ static int smu_v13_0_7_get_power_limit(struct smu_context *smu,
|
|||
od_percent_upper, od_percent_lower, power_limit);
|
||||
|
||||
if (max_power_limit) {
|
||||
*max_power_limit = power_limit * (100 + od_percent_upper);
|
||||
*max_power_limit = msg_limit * (100 + od_percent_upper);
|
||||
*max_power_limit /= 100;
|
||||
}
|
||||
|
||||
|
@ -2545,6 +2546,55 @@ static bool smu_v13_0_7_wbrf_support_check(struct smu_context *smu)
|
|||
return smu->smc_fw_version > 0x00524600;
|
||||
}
|
||||
|
||||
static int smu_v13_0_7_set_power_limit(struct smu_context *smu,
|
||||
enum smu_ppt_limit_type limit_type,
|
||||
uint32_t limit)
|
||||
{
|
||||
PPTable_t *pptable = smu->smu_table.driver_pptable;
|
||||
SkuTable_t *skutable = &pptable->SkuTable;
|
||||
uint32_t msg_limit = skutable->MsgLimits.Power[PPT_THROTTLER_PPT0][POWER_SOURCE_AC];
|
||||
struct smu_table_context *table_context = &smu->smu_table;
|
||||
OverDriveTableExternal_t *od_table =
|
||||
(OverDriveTableExternal_t *)table_context->overdrive_table;
|
||||
int ret = 0;
|
||||
|
||||
if (limit_type != SMU_DEFAULT_PPT_LIMIT)
|
||||
return -EINVAL;
|
||||
|
||||
if (limit <= msg_limit) {
|
||||
if (smu->current_power_limit > msg_limit) {
|
||||
od_table->OverDriveTable.Ppt = 0;
|
||||
od_table->OverDriveTable.FeatureCtrlMask |= 1U << PP_OD_FEATURE_PPT_BIT;
|
||||
|
||||
ret = smu_v13_0_7_upload_overdrive_table(smu, od_table);
|
||||
if (ret) {
|
||||
dev_err(smu->adev->dev, "Failed to upload overdrive table!\n");
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
return smu_v13_0_set_power_limit(smu, limit_type, limit);
|
||||
} else if (smu->od_enabled) {
|
||||
ret = smu_v13_0_set_power_limit(smu, limit_type, msg_limit);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
od_table->OverDriveTable.Ppt = (limit * 100) / msg_limit - 100;
|
||||
od_table->OverDriveTable.FeatureCtrlMask |= 1U << PP_OD_FEATURE_PPT_BIT;
|
||||
|
||||
ret = smu_v13_0_7_upload_overdrive_table(smu, od_table);
|
||||
if (ret) {
|
||||
dev_err(smu->adev->dev, "Failed to upload overdrive table!\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
smu->current_power_limit = limit;
|
||||
} else {
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct pptable_funcs smu_v13_0_7_ppt_funcs = {
|
||||
.get_allowed_feature_mask = smu_v13_0_7_get_allowed_feature_mask,
|
||||
.set_default_dpm_table = smu_v13_0_7_set_default_dpm_table,
|
||||
|
@ -2596,7 +2646,7 @@ static const struct pptable_funcs smu_v13_0_7_ppt_funcs = {
|
|||
.set_fan_control_mode = smu_v13_0_set_fan_control_mode,
|
||||
.enable_mgpu_fan_boost = smu_v13_0_7_enable_mgpu_fan_boost,
|
||||
.get_power_limit = smu_v13_0_7_get_power_limit,
|
||||
.set_power_limit = smu_v13_0_set_power_limit,
|
||||
.set_power_limit = smu_v13_0_7_set_power_limit,
|
||||
.set_power_source = smu_v13_0_set_power_source,
|
||||
.get_power_profile_mode = smu_v13_0_7_get_power_profile_mode,
|
||||
.set_power_profile_mode = smu_v13_0_7_set_power_profile_mode,
|
||||
|
|
Loading…
Reference in a new issue