2
0
mirror of git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git synced 2025-09-04 20:19:47 +08:00

amd-drm-fixes-6.17-2025-08-20:

amdgpu:
 - Replay fixes
 - SMU14 fix
 - Null check DC fixes
 - DCE6 DC fixes
 - Misc DC fixes
 -----BEGIN PGP SIGNATURE-----
 
 iHUEABYKAB0WIQQgO5Idg2tXNTSZAr293/aFa7yZ2AUCaKYjMgAKCRC93/aFa7yZ
 2BHyAQCZLYCzi23q0qGS7vPS7dTzdvwji7luhWqqBX7lTGmB2AD/U3fE9kVg6Itv
 PjPxfA6E3A1UDJGKdSaJkFtXQRx4+wo=
 =LUbK
 -----END PGP SIGNATURE-----

Merge tag 'amd-drm-fixes-6.17-2025-08-20' of https://gitlab.freedesktop.org/agd5f/linux into drm-fixes

amd-drm-fixes-6.17-2025-08-20:

amdgpu:
- Replay fixes
- SMU14 fix
- Null check DC fixes
- DCE6 DC fixes
- Misc DC fixes

Signed-off-by: Dave Airlie <airlied@redhat.com>

From: Alex Deucher <alexander.deucher@amd.com>
Link: https://lore.kernel.org/r/20250820194636.101975-1-alexander.deucher@amd.com
This commit is contained in:
Dave Airlie 2025-08-21 16:26:47 +10:00
commit dbb2c3adc4
15 changed files with 112 additions and 125 deletions

View File

@ -7792,6 +7792,9 @@ amdgpu_dm_connector_atomic_check(struct drm_connector *conn,
struct amdgpu_dm_connector *aconn = to_amdgpu_dm_connector(conn); struct amdgpu_dm_connector *aconn = to_amdgpu_dm_connector(conn);
int ret; int ret;
if (WARN_ON(unlikely(!old_con_state || !new_con_state)))
return -EINVAL;
trace_amdgpu_dm_connector_atomic_check(new_con_state); trace_amdgpu_dm_connector_atomic_check(new_con_state);
if (conn->connector_type == DRM_MODE_CONNECTOR_DisplayPort) { if (conn->connector_type == DRM_MODE_CONNECTOR_DisplayPort) {

View File

@ -299,6 +299,25 @@ static inline int amdgpu_dm_crtc_set_vblank(struct drm_crtc *crtc, bool enable)
irq_type = amdgpu_display_crtc_idx_to_irq_type(adev, acrtc->crtc_id); irq_type = amdgpu_display_crtc_idx_to_irq_type(adev, acrtc->crtc_id);
if (enable) { if (enable) {
struct dc *dc = adev->dm.dc;
struct drm_vblank_crtc *vblank = drm_crtc_vblank_crtc(crtc);
struct psr_settings *psr = &acrtc_state->stream->link->psr_settings;
struct replay_settings *pr = &acrtc_state->stream->link->replay_settings;
bool sr_supported = (psr->psr_version != DC_PSR_VERSION_UNSUPPORTED) ||
pr->config.replay_supported;
/*
* IPS & self-refresh feature can cause vblank counter resets between
* vblank disable and enable.
* It may cause system stuck due to waiting for the vblank counter.
* Call this function to estimate missed vblanks by using timestamps and
* update the vblank counter in DRM.
*/
if (dc->caps.ips_support &&
dc->config.disable_ips != DMUB_IPS_DISABLE_ALL &&
sr_supported && vblank->config.disable_immediate)
drm_crtc_vblank_restore(crtc);
/* vblank irq on -> Only need vupdate irq in vrr mode */ /* vblank irq on -> Only need vupdate irq in vrr mode */
if (amdgpu_dm_crtc_vrr_active(acrtc_state)) if (amdgpu_dm_crtc_vrr_active(acrtc_state))
rc = amdgpu_dm_crtc_set_vupdate_irq(crtc, true); rc = amdgpu_dm_crtc_set_vupdate_irq(crtc, true);

View File

@ -174,11 +174,8 @@ static struct graphics_object_id bios_parser_get_connector_id(
return object_id; return object_id;
} }
if (tbl->ucNumberOfObjects <= i) { if (tbl->ucNumberOfObjects <= i)
dm_error("Can't find connector id %d in connector table of size %d.\n",
i, tbl->ucNumberOfObjects);
return object_id; return object_id;
}
id = le16_to_cpu(tbl->asObjects[i].usObjectID); id = le16_to_cpu(tbl->asObjects[i].usObjectID);
object_id = object_id_from_bios_object_id(id); object_id = object_id_from_bios_object_id(id);

View File

@ -993,7 +993,7 @@ static enum bp_result set_pixel_clock_v3(
allocation.sPCLKInput.usFbDiv = allocation.sPCLKInput.usFbDiv =
cpu_to_le16((uint16_t)bp_params->feedback_divider); cpu_to_le16((uint16_t)bp_params->feedback_divider);
allocation.sPCLKInput.ucFracFbDiv = allocation.sPCLKInput.ucFracFbDiv =
(uint8_t)bp_params->fractional_feedback_divider; (uint8_t)(bp_params->fractional_feedback_divider / 100000);
allocation.sPCLKInput.ucPostDiv = allocation.sPCLKInput.ucPostDiv =
(uint8_t)bp_params->pixel_clock_post_divider; (uint8_t)bp_params->pixel_clock_post_divider;

View File

@ -72,9 +72,9 @@ static const struct state_dependent_clocks dce80_max_clks_by_state[] = {
/* ClocksStateLow */ /* ClocksStateLow */
{ .display_clk_khz = 352000, .pixel_clk_khz = 330000}, { .display_clk_khz = 352000, .pixel_clk_khz = 330000},
/* ClocksStateNominal */ /* ClocksStateNominal */
{ .display_clk_khz = 600000, .pixel_clk_khz = 400000 }, { .display_clk_khz = 625000, .pixel_clk_khz = 400000 },
/* ClocksStatePerformance */ /* ClocksStatePerformance */
{ .display_clk_khz = 600000, .pixel_clk_khz = 400000 } }; { .display_clk_khz = 625000, .pixel_clk_khz = 400000 } };
int dentist_get_divider_from_did(int did) int dentist_get_divider_from_did(int did)
{ {
@ -391,8 +391,6 @@ static void dce_pplib_apply_display_requirements(
{ {
struct dm_pp_display_configuration *pp_display_cfg = &context->pp_display_cfg; struct dm_pp_display_configuration *pp_display_cfg = &context->pp_display_cfg;
pp_display_cfg->avail_mclk_switch_time_us = dce110_get_min_vblank_time_us(context);
dce110_fill_display_configs(context, pp_display_cfg); dce110_fill_display_configs(context, pp_display_cfg);
if (memcmp(&dc->current_state->pp_display_cfg, pp_display_cfg, sizeof(*pp_display_cfg)) != 0) if (memcmp(&dc->current_state->pp_display_cfg, pp_display_cfg, sizeof(*pp_display_cfg)) != 0)
@ -405,11 +403,9 @@ static void dce_update_clocks(struct clk_mgr *clk_mgr_base,
{ {
struct clk_mgr_internal *clk_mgr_dce = TO_CLK_MGR_INTERNAL(clk_mgr_base); struct clk_mgr_internal *clk_mgr_dce = TO_CLK_MGR_INTERNAL(clk_mgr_base);
struct dm_pp_power_level_change_request level_change_req; struct dm_pp_power_level_change_request level_change_req;
int patched_disp_clk = context->bw_ctx.bw.dce.dispclk_khz; const int max_disp_clk =
clk_mgr_dce->max_clks_by_state[DM_PP_CLOCKS_STATE_PERFORMANCE].display_clk_khz;
/*TODO: W/A for dal3 linux, investigate why this works */ int patched_disp_clk = MIN(max_disp_clk, context->bw_ctx.bw.dce.dispclk_khz);
if (!clk_mgr_dce->dfs_bypass_active)
patched_disp_clk = patched_disp_clk * 115 / 100;
level_change_req.power_level = dce_get_required_clocks_state(clk_mgr_base, context); level_change_req.power_level = dce_get_required_clocks_state(clk_mgr_base, context);
/* get max clock state from PPLIB */ /* get max clock state from PPLIB */

View File

@ -120,9 +120,15 @@ void dce110_fill_display_configs(
const struct dc_state *context, const struct dc_state *context,
struct dm_pp_display_configuration *pp_display_cfg) struct dm_pp_display_configuration *pp_display_cfg)
{ {
struct dc *dc = context->clk_mgr->ctx->dc;
int j; int j;
int num_cfgs = 0; int num_cfgs = 0;
pp_display_cfg->avail_mclk_switch_time_us = dce110_get_min_vblank_time_us(context);
pp_display_cfg->disp_clk_khz = dc->clk_mgr->clks.dispclk_khz;
pp_display_cfg->avail_mclk_switch_time_in_disp_active_us = 0;
pp_display_cfg->crtc_index = dc->res_pool->res_cap->num_timing_generator;
for (j = 0; j < context->stream_count; j++) { for (j = 0; j < context->stream_count; j++) {
int k; int k;
@ -164,6 +170,23 @@ void dce110_fill_display_configs(
cfg->v_refresh /= stream->timing.h_total; cfg->v_refresh /= stream->timing.h_total;
cfg->v_refresh = (cfg->v_refresh + stream->timing.v_total / 2) cfg->v_refresh = (cfg->v_refresh + stream->timing.v_total / 2)
/ stream->timing.v_total; / stream->timing.v_total;
/* Find first CRTC index and calculate its line time.
* This is necessary for DPM on SI GPUs.
*/
if (cfg->pipe_idx < pp_display_cfg->crtc_index) {
const struct dc_crtc_timing *timing =
&context->streams[0]->timing;
pp_display_cfg->crtc_index = cfg->pipe_idx;
pp_display_cfg->line_time_in_us =
timing->h_total * 10000 / timing->pix_clk_100hz;
}
}
if (!num_cfgs) {
pp_display_cfg->crtc_index = 0;
pp_display_cfg->line_time_in_us = 0;
} }
pp_display_cfg->display_count = num_cfgs; pp_display_cfg->display_count = num_cfgs;
@ -223,25 +246,8 @@ void dce11_pplib_apply_display_requirements(
pp_display_cfg->min_engine_clock_deep_sleep_khz pp_display_cfg->min_engine_clock_deep_sleep_khz
= context->bw_ctx.bw.dce.sclk_deep_sleep_khz; = context->bw_ctx.bw.dce.sclk_deep_sleep_khz;
pp_display_cfg->avail_mclk_switch_time_us =
dce110_get_min_vblank_time_us(context);
/* TODO: dce11.2*/
pp_display_cfg->avail_mclk_switch_time_in_disp_active_us = 0;
pp_display_cfg->disp_clk_khz = dc->clk_mgr->clks.dispclk_khz;
dce110_fill_display_configs(context, pp_display_cfg); dce110_fill_display_configs(context, pp_display_cfg);
/* TODO: is this still applicable?*/
if (pp_display_cfg->display_count == 1) {
const struct dc_crtc_timing *timing =
&context->streams[0]->timing;
pp_display_cfg->crtc_index =
pp_display_cfg->disp_configs[0].pipe_idx;
pp_display_cfg->line_time_in_us = timing->h_total * 10000 / timing->pix_clk_100hz;
}
if (memcmp(&dc->current_state->pp_display_cfg, pp_display_cfg, sizeof(*pp_display_cfg)) != 0) if (memcmp(&dc->current_state->pp_display_cfg, pp_display_cfg, sizeof(*pp_display_cfg)) != 0)
dm_pp_apply_display_requirements(dc->ctx, pp_display_cfg); dm_pp_apply_display_requirements(dc->ctx, pp_display_cfg);
} }

View File

@ -83,22 +83,13 @@ static const struct state_dependent_clocks dce60_max_clks_by_state[] = {
static int dce60_get_dp_ref_freq_khz(struct clk_mgr *clk_mgr_base) static int dce60_get_dp_ref_freq_khz(struct clk_mgr *clk_mgr_base)
{ {
struct clk_mgr_internal *clk_mgr = TO_CLK_MGR_INTERNAL(clk_mgr_base); struct clk_mgr_internal *clk_mgr = TO_CLK_MGR_INTERNAL(clk_mgr_base);
int dprefclk_wdivider; struct dc_context *ctx = clk_mgr_base->ctx;
int dp_ref_clk_khz; int dp_ref_clk_khz = 0;
int target_div;
/* DCE6 has no DPREFCLK_CNTL to read DP Reference Clock source */ if (ASIC_REV_IS_TAHITI_P(ctx->asic_id.hw_internal_rev))
dp_ref_clk_khz = ctx->dc_bios->fw_info.default_display_engine_pll_frequency;
/* Read the mmDENTIST_DISPCLK_CNTL to get the currently else
* programmed DID DENTIST_DPREFCLK_WDIVIDER*/ dp_ref_clk_khz = clk_mgr_base->clks.dispclk_khz;
REG_GET(DENTIST_DISPCLK_CNTL, DENTIST_DPREFCLK_WDIVIDER, &dprefclk_wdivider);
/* Convert DENTIST_DPREFCLK_WDIVIDERto actual divider*/
target_div = dentist_get_divider_from_did(dprefclk_wdivider);
/* Calculate the current DFS clock, in kHz.*/
dp_ref_clk_khz = (DENTIST_DIVIDER_RANGE_SCALE_FACTOR
* clk_mgr->base.dentist_vco_freq_khz) / target_div;
return dce_adjust_dp_ref_freq_for_ss(clk_mgr, dp_ref_clk_khz); return dce_adjust_dp_ref_freq_for_ss(clk_mgr, dp_ref_clk_khz);
} }
@ -109,8 +100,6 @@ static void dce60_pplib_apply_display_requirements(
{ {
struct dm_pp_display_configuration *pp_display_cfg = &context->pp_display_cfg; struct dm_pp_display_configuration *pp_display_cfg = &context->pp_display_cfg;
pp_display_cfg->avail_mclk_switch_time_us = dce110_get_min_vblank_time_us(context);
dce110_fill_display_configs(context, pp_display_cfg); dce110_fill_display_configs(context, pp_display_cfg);
if (memcmp(&dc->current_state->pp_display_cfg, pp_display_cfg, sizeof(*pp_display_cfg)) != 0) if (memcmp(&dc->current_state->pp_display_cfg, pp_display_cfg, sizeof(*pp_display_cfg)) != 0)
@ -123,11 +112,9 @@ static void dce60_update_clocks(struct clk_mgr *clk_mgr_base,
{ {
struct clk_mgr_internal *clk_mgr_dce = TO_CLK_MGR_INTERNAL(clk_mgr_base); struct clk_mgr_internal *clk_mgr_dce = TO_CLK_MGR_INTERNAL(clk_mgr_base);
struct dm_pp_power_level_change_request level_change_req; struct dm_pp_power_level_change_request level_change_req;
int patched_disp_clk = context->bw_ctx.bw.dce.dispclk_khz; const int max_disp_clk =
clk_mgr_dce->max_clks_by_state[DM_PP_CLOCKS_STATE_PERFORMANCE].display_clk_khz;
/*TODO: W/A for dal3 linux, investigate why this works */ int patched_disp_clk = MIN(max_disp_clk, context->bw_ctx.bw.dce.dispclk_khz);
if (!clk_mgr_dce->dfs_bypass_active)
patched_disp_clk = patched_disp_clk * 115 / 100;
level_change_req.power_level = dce_get_required_clocks_state(clk_mgr_base, context); level_change_req.power_level = dce_get_required_clocks_state(clk_mgr_base, context);
/* get max clock state from PPLIB */ /* get max clock state from PPLIB */

View File

@ -217,11 +217,24 @@ static bool create_links(
connectors_num, connectors_num,
num_virtual_links); num_virtual_links);
// condition loop on link_count to allow skipping invalid indices /* When getting the number of connectors, the VBIOS reports the number of valid indices,
* but it doesn't say which indices are valid, and not every index has an actual connector.
* So, if we don't find a connector on an index, that is not an error.
*
* - There is no guarantee that the first N indices will be valid
* - VBIOS may report a higher amount of valid indices than there are actual connectors
* - Some VBIOS have valid configurations for more connectors than there actually are
* on the card. This may be because the manufacturer used the same VBIOS for different
* variants of the same card.
*/
for (i = 0; dc->link_count < connectors_num && i < MAX_LINKS; i++) { for (i = 0; dc->link_count < connectors_num && i < MAX_LINKS; i++) {
struct graphics_object_id connector_id = bios->funcs->get_connector_id(bios, i);
struct link_init_data link_init_params = {0}; struct link_init_data link_init_params = {0};
struct dc_link *link; struct dc_link *link;
if (connector_id.id == CONNECTOR_ID_UNKNOWN)
continue;
DC_LOG_DC("BIOS object table - printing link object info for connector number: %d, link_index: %d", i, dc->link_count); DC_LOG_DC("BIOS object table - printing link object info for connector number: %d, link_index: %d", i, dc->link_count);
link_init_params.ctx = dc->ctx; link_init_params.ctx = dc->ctx;

View File

@ -896,13 +896,13 @@ void dce110_link_encoder_construct(
enc110->base.id, &bp_cap_info); enc110->base.id, &bp_cap_info);
/* Override features with DCE-specific values */ /* Override features with DCE-specific values */
if (BP_RESULT_OK == result) { if (result == BP_RESULT_OK) {
enc110->base.features.flags.bits.IS_HBR2_CAPABLE = enc110->base.features.flags.bits.IS_HBR2_CAPABLE =
bp_cap_info.DP_HBR2_EN; bp_cap_info.DP_HBR2_EN;
enc110->base.features.flags.bits.IS_HBR3_CAPABLE = enc110->base.features.flags.bits.IS_HBR3_CAPABLE =
bp_cap_info.DP_HBR3_EN; bp_cap_info.DP_HBR3_EN;
enc110->base.features.flags.bits.HDMI_6GB_EN = bp_cap_info.HDMI_6GB_EN; enc110->base.features.flags.bits.HDMI_6GB_EN = bp_cap_info.HDMI_6GB_EN;
} else { } else if (result != BP_RESULT_NORECORD) {
DC_LOG_WARNING("%s: Failed to get encoder_cap_info from VBIOS with error code %d!\n", DC_LOG_WARNING("%s: Failed to get encoder_cap_info from VBIOS with error code %d!\n",
__func__, __func__,
result); result);
@ -1798,13 +1798,13 @@ void dce60_link_encoder_construct(
enc110->base.id, &bp_cap_info); enc110->base.id, &bp_cap_info);
/* Override features with DCE-specific values */ /* Override features with DCE-specific values */
if (BP_RESULT_OK == result) { if (result == BP_RESULT_OK) {
enc110->base.features.flags.bits.IS_HBR2_CAPABLE = enc110->base.features.flags.bits.IS_HBR2_CAPABLE =
bp_cap_info.DP_HBR2_EN; bp_cap_info.DP_HBR2_EN;
enc110->base.features.flags.bits.IS_HBR3_CAPABLE = enc110->base.features.flags.bits.IS_HBR3_CAPABLE =
bp_cap_info.DP_HBR3_EN; bp_cap_info.DP_HBR3_EN;
enc110->base.features.flags.bits.HDMI_6GB_EN = bp_cap_info.HDMI_6GB_EN; enc110->base.features.flags.bits.HDMI_6GB_EN = bp_cap_info.HDMI_6GB_EN;
} else { } else if (result != BP_RESULT_NORECORD) {
DC_LOG_WARNING("%s: Failed to get encoder_cap_info from VBIOS with error code %d!\n", DC_LOG_WARNING("%s: Failed to get encoder_cap_info from VBIOS with error code %d!\n",
__func__, __func__,
result); result);

View File

@ -4,7 +4,6 @@
#include "dc.h" #include "dc.h"
#include "dc_dmub_srv.h" #include "dc_dmub_srv.h"
#include "dc_dp_types.h"
#include "dmub/dmub_srv.h" #include "dmub/dmub_srv.h"
#include "core_types.h" #include "core_types.h"
#include "dmub_replay.h" #include "dmub_replay.h"
@ -44,45 +43,21 @@ static void dmub_replay_get_state(struct dmub_replay *dmub, enum replay_state *s
/* /*
* Enable/Disable Replay. * Enable/Disable Replay.
*/ */
static void dmub_replay_enable(struct dmub_replay *dmub, bool enable, bool wait, uint8_t panel_inst, static void dmub_replay_enable(struct dmub_replay *dmub, bool enable, bool wait, uint8_t panel_inst)
struct dc_link *link)
{ {
union dmub_rb_cmd cmd; union dmub_rb_cmd cmd;
struct dc_context *dc = dmub->ctx; struct dc_context *dc = dmub->ctx;
uint32_t retry_count; uint32_t retry_count;
enum replay_state state = REPLAY_STATE_0; enum replay_state state = REPLAY_STATE_0;
struct pipe_ctx *pipe_ctx = NULL;
struct resource_context *res_ctx = &link->ctx->dc->current_state->res_ctx;
uint8_t i;
memset(&cmd, 0, sizeof(cmd)); memset(&cmd, 0, sizeof(cmd));
cmd.replay_enable.header.type = DMUB_CMD__REPLAY; cmd.replay_enable.header.type = DMUB_CMD__REPLAY;
cmd.replay_enable.data.panel_inst = panel_inst; cmd.replay_enable.data.panel_inst = panel_inst;
cmd.replay_enable.header.sub_type = DMUB_CMD__REPLAY_ENABLE; cmd.replay_enable.header.sub_type = DMUB_CMD__REPLAY_ENABLE;
if (enable) { if (enable)
cmd.replay_enable.data.enable = REPLAY_ENABLE; cmd.replay_enable.data.enable = REPLAY_ENABLE;
// hpo stream/link encoder assignments are not static, need to update everytime we try to enable replay else
if (link->cur_link_settings.link_rate >= LINK_RATE_UHBR10) {
for (i = 0; i < MAX_PIPES; i++) {
if (res_ctx &&
res_ctx->pipe_ctx[i].stream &&
res_ctx->pipe_ctx[i].stream->link &&
res_ctx->pipe_ctx[i].stream->link == link &&
res_ctx->pipe_ctx[i].stream->link->connector_signal == SIGNAL_TYPE_EDP) {
pipe_ctx = &res_ctx->pipe_ctx[i];
//TODO: refactor for multi edp support
break;
}
}
if (!pipe_ctx)
return;
cmd.replay_enable.data.hpo_stream_enc_inst = pipe_ctx->stream_res.hpo_dp_stream_enc->inst;
cmd.replay_enable.data.hpo_link_enc_inst = pipe_ctx->link_res.hpo_dp_link_enc->inst;
}
} else
cmd.replay_enable.data.enable = REPLAY_DISABLE; cmd.replay_enable.data.enable = REPLAY_DISABLE;
cmd.replay_enable.header.payload_bytes = sizeof(struct dmub_rb_cmd_replay_enable_data); cmd.replay_enable.header.payload_bytes = sizeof(struct dmub_rb_cmd_replay_enable_data);
@ -174,17 +149,6 @@ static bool dmub_replay_copy_settings(struct dmub_replay *dmub,
copy_settings_data->digbe_inst = replay_context->digbe_inst; copy_settings_data->digbe_inst = replay_context->digbe_inst;
copy_settings_data->digfe_inst = replay_context->digfe_inst; copy_settings_data->digfe_inst = replay_context->digfe_inst;
if (link->cur_link_settings.link_rate >= LINK_RATE_UHBR10) {
if (pipe_ctx->stream_res.hpo_dp_stream_enc)
copy_settings_data->hpo_stream_enc_inst = pipe_ctx->stream_res.hpo_dp_stream_enc->inst;
else
copy_settings_data->hpo_stream_enc_inst = 0;
if (pipe_ctx->link_res.hpo_dp_link_enc)
copy_settings_data->hpo_link_enc_inst = pipe_ctx->link_res.hpo_dp_link_enc->inst;
else
copy_settings_data->hpo_link_enc_inst = 0;
}
if (pipe_ctx->plane_res.dpp) if (pipe_ctx->plane_res.dpp)
copy_settings_data->dpp_inst = pipe_ctx->plane_res.dpp->inst; copy_settings_data->dpp_inst = pipe_ctx->plane_res.dpp->inst;
else else
@ -247,7 +211,6 @@ static void dmub_replay_set_coasting_vtotal(struct dmub_replay *dmub,
pCmd->header.type = DMUB_CMD__REPLAY; pCmd->header.type = DMUB_CMD__REPLAY;
pCmd->header.sub_type = DMUB_CMD__REPLAY_SET_COASTING_VTOTAL; pCmd->header.sub_type = DMUB_CMD__REPLAY_SET_COASTING_VTOTAL;
pCmd->header.payload_bytes = sizeof(struct dmub_cmd_replay_set_coasting_vtotal_data); pCmd->header.payload_bytes = sizeof(struct dmub_cmd_replay_set_coasting_vtotal_data);
pCmd->replay_set_coasting_vtotal_data.panel_inst = panel_inst;
pCmd->replay_set_coasting_vtotal_data.coasting_vtotal = (coasting_vtotal & 0xFFFF); pCmd->replay_set_coasting_vtotal_data.coasting_vtotal = (coasting_vtotal & 0xFFFF);
pCmd->replay_set_coasting_vtotal_data.coasting_vtotal_high = (coasting_vtotal & 0xFFFF0000) >> 16; pCmd->replay_set_coasting_vtotal_data.coasting_vtotal_high = (coasting_vtotal & 0xFFFF0000) >> 16;

View File

@ -19,7 +19,7 @@ struct dmub_replay_funcs {
void (*replay_get_state)(struct dmub_replay *dmub, enum replay_state *state, void (*replay_get_state)(struct dmub_replay *dmub, enum replay_state *state,
uint8_t panel_inst); uint8_t panel_inst);
void (*replay_enable)(struct dmub_replay *dmub, bool enable, bool wait, void (*replay_enable)(struct dmub_replay *dmub, bool enable, bool wait,
uint8_t panel_inst, struct dc_link *link); uint8_t panel_inst);
bool (*replay_copy_settings)(struct dmub_replay *dmub, struct dc_link *link, bool (*replay_copy_settings)(struct dmub_replay *dmub, struct dc_link *link,
struct replay_context *replay_context, uint8_t panel_inst); struct replay_context *replay_context, uint8_t panel_inst);
void (*replay_set_power_opt)(struct dmub_replay *dmub, unsigned int power_opt, void (*replay_set_power_opt)(struct dmub_replay *dmub, unsigned int power_opt,

View File

@ -944,7 +944,7 @@ bool edp_set_replay_allow_active(struct dc_link *link, const bool *allow_active,
// TODO: Handle mux change case if force_static is set // TODO: Handle mux change case if force_static is set
// If force_static is set, just change the replay_allow_active state directly // If force_static is set, just change the replay_allow_active state directly
if (replay != NULL && link->replay_settings.replay_feature_enabled) if (replay != NULL && link->replay_settings.replay_feature_enabled)
replay->funcs->replay_enable(replay, *allow_active, wait, panel_inst, link); replay->funcs->replay_enable(replay, *allow_active, wait, panel_inst);
link->replay_settings.replay_allow_active = *allow_active; link->replay_settings.replay_allow_active = *allow_active;
} }

View File

@ -4047,14 +4047,6 @@ struct dmub_cmd_replay_copy_settings_data {
* DIG BE HW instance. * DIG BE HW instance.
*/ */
uint8_t digbe_inst; uint8_t digbe_inst;
/**
* @hpo_stream_enc_inst: HPO stream encoder instance
*/
uint8_t hpo_stream_enc_inst;
/**
* @hpo_link_enc_inst: HPO link encoder instance
*/
uint8_t hpo_link_enc_inst;
/** /**
* AUX HW instance. * AUX HW instance.
*/ */
@ -4159,18 +4151,6 @@ struct dmub_rb_cmd_replay_enable_data {
* This does not support HDMI/DP2 for now. * This does not support HDMI/DP2 for now.
*/ */
uint8_t phy_rate; uint8_t phy_rate;
/**
* @hpo_stream_enc_inst: HPO stream encoder instance
*/
uint8_t hpo_stream_enc_inst;
/**
* @hpo_link_enc_inst: HPO link encoder instance
*/
uint8_t hpo_link_enc_inst;
/**
* @pad: Align structure to 4 byte boundary.
*/
uint8_t pad[2];
}; };
/** /**

View File

@ -260,6 +260,9 @@ enum mod_hdcp_status mod_hdcp_hdcp1_create_session(struct mod_hdcp *hdcp)
return MOD_HDCP_STATUS_FAILURE; return MOD_HDCP_STATUS_FAILURE;
} }
if (!display)
return MOD_HDCP_STATUS_DISPLAY_NOT_FOUND;
hdcp_cmd = (struct ta_hdcp_shared_memory *)psp->hdcp_context.context.mem_context.shared_buf; hdcp_cmd = (struct ta_hdcp_shared_memory *)psp->hdcp_context.context.mem_context.shared_buf;
mutex_lock(&psp->hdcp_context.mutex); mutex_lock(&psp->hdcp_context.mutex);

View File

@ -1697,9 +1697,11 @@ static int smu_v14_0_2_get_power_limit(struct smu_context *smu,
uint32_t *min_power_limit) uint32_t *min_power_limit)
{ {
struct smu_table_context *table_context = &smu->smu_table; struct smu_table_context *table_context = &smu->smu_table;
struct smu_14_0_2_powerplay_table *powerplay_table =
table_context->power_play_table;
PPTable_t *pptable = table_context->driver_pptable; PPTable_t *pptable = table_context->driver_pptable;
CustomSkuTable_t *skutable = &pptable->CustomSkuTable; CustomSkuTable_t *skutable = &pptable->CustomSkuTable;
uint32_t power_limit; uint32_t power_limit, od_percent_upper = 0, od_percent_lower = 0;
uint32_t msg_limit = pptable->SkuTable.MsgLimits.Power[PPT_THROTTLER_PPT0][POWER_SOURCE_AC]; uint32_t msg_limit = pptable->SkuTable.MsgLimits.Power[PPT_THROTTLER_PPT0][POWER_SOURCE_AC];
if (smu_v14_0_get_current_power_limit(smu, &power_limit)) if (smu_v14_0_get_current_power_limit(smu, &power_limit))
@ -1712,11 +1714,29 @@ static int smu_v14_0_2_get_power_limit(struct smu_context *smu,
if (default_power_limit) if (default_power_limit)
*default_power_limit = power_limit; *default_power_limit = power_limit;
if (max_power_limit) if (powerplay_table) {
*max_power_limit = msg_limit; if (smu->od_enabled &&
smu_v14_0_2_is_od_feature_supported(smu, PP_OD_FEATURE_PPT_BIT)) {
od_percent_upper = pptable->SkuTable.OverDriveLimitsBasicMax.Ppt;
od_percent_lower = pptable->SkuTable.OverDriveLimitsBasicMin.Ppt;
} else if (smu_v14_0_2_is_od_feature_supported(smu, PP_OD_FEATURE_PPT_BIT)) {
od_percent_upper = 0;
od_percent_lower = pptable->SkuTable.OverDriveLimitsBasicMin.Ppt;
}
}
if (min_power_limit) dev_dbg(smu->adev->dev, "od percent upper:%d, od percent lower:%d (default power: %d)\n",
*min_power_limit = 0; od_percent_upper, od_percent_lower, power_limit);
if (max_power_limit) {
*max_power_limit = msg_limit * (100 + od_percent_upper);
*max_power_limit /= 100;
}
if (min_power_limit) {
*min_power_limit = power_limit * (100 + od_percent_lower);
*min_power_limit /= 100;
}
return 0; return 0;
} }