mirror of
https://github.com/torvalds/linux.git
synced 2024-09-20 06:53:04 +00:00
drm/amd/display: Export additional FAMS2 global configuration options from DML
[WHY&HOW] Some global configuration options were previously hardcoded in DC, now they are exported by DML and sent to FW. Reviewed-by: Martin Leung <martin.leung@amd.com> Signed-off-by: Jerry Zuo <jerry.zuo@amd.com> Signed-off-by: Dillon Varone <dillon.varone@amd.com> Tested-by: Daniel Wheeler <daniel.wheeler@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
This commit is contained in:
parent
b8d3782da3
commit
08cbe68d4a
|
@ -967,10 +967,10 @@ bool dc_state_is_fams2_in_use(
|
|||
bool is_fams2_in_use = false;
|
||||
|
||||
if (state)
|
||||
is_fams2_in_use |= state->bw_ctx.bw.dcn.fams2_stream_count > 0;
|
||||
is_fams2_in_use |= state->bw_ctx.bw.dcn.fams2_global_config.features.bits.enable;
|
||||
|
||||
if (dc->current_state)
|
||||
is_fams2_in_use |= dc->current_state->bw_ctx.bw.dcn.fams2_stream_count > 0;
|
||||
is_fams2_in_use |= dc->current_state->bw_ctx.bw.dcn.fams2_global_config.features.bits.enable;
|
||||
|
||||
return is_fams2_in_use;
|
||||
}
|
||||
|
|
|
@ -1672,22 +1672,17 @@ void dc_dmub_srv_fams2_update_config(struct dc *dc,
|
|||
global_cmd->header.sub_type = DMUB_CMD__FAMS2_CONFIG;
|
||||
global_cmd->header.payload_bytes = sizeof(struct dmub_rb_cmd_fams2) - sizeof(struct dmub_cmd_header);
|
||||
|
||||
/* send global configuration parameters */
|
||||
global_cmd->config.global.max_allow_delay_us = 100 * 1000; //100ms
|
||||
global_cmd->config.global.lock_wait_time_us = 5000; //5ms
|
||||
global_cmd->config.global.recovery_timeout_us = 5000; //5ms
|
||||
global_cmd->config.global.hwfq_flip_programming_delay_us = 100; //100us
|
||||
|
||||
/* copy static feature configuration */
|
||||
global_cmd->config.global.features.all = dc->debug.fams2_config.all;
|
||||
|
||||
/* apply feature configuration based on current driver state */
|
||||
global_cmd->config.global.features.bits.enable_visual_confirm = dc->debug.visual_confirm == VISUAL_CONFIRM_FAMS2;
|
||||
global_cmd->config.global.features.bits.enable = enable;
|
||||
|
||||
/* construct per-stream configs */
|
||||
if (enable) {
|
||||
for (i = 0; i < context->bw_ctx.bw.dcn.fams2_stream_count; i++) {
|
||||
/* send global configuration parameters */
|
||||
memcpy(&global_cmd->config.global, &context->bw_ctx.bw.dcn.fams2_global_config, sizeof(struct dmub_cmd_fams2_global_config));
|
||||
|
||||
/* copy static feature configuration overrides */
|
||||
global_cmd->config.global.features.bits.enable_stall_recovery = dc->debug.fams2_config.bits.enable_stall_recovery;
|
||||
global_cmd->config.global.features.bits.enable_debug = dc->debug.fams2_config.bits.enable_debug;
|
||||
global_cmd->config.global.features.bits.enable_offload_flip = dc->debug.fams2_config.bits.enable_offload_flip;
|
||||
|
||||
/* construct per-stream configs */
|
||||
for (i = 0; i < context->bw_ctx.bw.dcn.fams2_global_config.num_streams; i++) {
|
||||
struct dmub_rb_cmd_fams2 *stream_cmd = &cmd[i+1].fams2_config;
|
||||
|
||||
/* configure command header */
|
||||
|
@ -1702,12 +1697,15 @@ void dc_dmub_srv_fams2_update_config(struct dc *dc,
|
|||
}
|
||||
}
|
||||
|
||||
if (enable && context->bw_ctx.bw.dcn.fams2_stream_count) {
|
||||
/* apply feature configuration based on current driver state */
|
||||
global_cmd->config.global.features.bits.enable_visual_confirm = dc->debug.visual_confirm == VISUAL_CONFIRM_FAMS2;
|
||||
global_cmd->config.global.features.bits.enable = enable;
|
||||
|
||||
if (enable && context->bw_ctx.bw.dcn.fams2_global_config.features.bits.enable) {
|
||||
/* set multi pending for global, and unset for last stream cmd */
|
||||
global_cmd->config.global.num_streams = context->bw_ctx.bw.dcn.fams2_stream_count;
|
||||
global_cmd->header.multi_cmd_pending = 1;
|
||||
cmd[context->bw_ctx.bw.dcn.fams2_stream_count].fams2_config.header.multi_cmd_pending = 0;
|
||||
num_cmds += context->bw_ctx.bw.dcn.fams2_stream_count;
|
||||
cmd[context->bw_ctx.bw.dcn.fams2_global_config.num_streams].fams2_config.header.multi_cmd_pending = 0;
|
||||
num_cmds += context->bw_ctx.bw.dcn.fams2_global_config.num_streams;
|
||||
}
|
||||
|
||||
dm_execute_dmub_cmd_list(dc->ctx, num_cmds, cmd, DM_DMUB_WAIT_TYPE_WAIT);
|
||||
|
|
|
@ -461,94 +461,103 @@ void dml21_build_fams2_programming(const struct dc *dc,
|
|||
struct dml2_context *dml_ctx)
|
||||
{
|
||||
int i, j, k;
|
||||
unsigned int num_fams2_streams = 0;
|
||||
|
||||
/* reset fams2 data */
|
||||
context->bw_ctx.bw.dcn.fams2_stream_count = 0;
|
||||
memset(&context->bw_ctx.bw.dcn.fams2_stream_params, 0, sizeof(struct dmub_fams2_stream_static_state) * DML2_MAX_PLANES);
|
||||
memset(&context->bw_ctx.bw.dcn.fams2_global_config, 0, sizeof(struct dmub_cmd_fams2_global_config));
|
||||
|
||||
if (!dml_ctx->v21.mode_programming.programming->fams2_required)
|
||||
return;
|
||||
if (dml_ctx->v21.mode_programming.programming->fams2_required) {
|
||||
for (i = 0; i < context->stream_count; i++) {
|
||||
int dml_stream_idx;
|
||||
struct dc_stream_state *phantom_stream;
|
||||
struct dc_stream_status *phantom_status;
|
||||
|
||||
for (i = 0; i < context->stream_count; i++) {
|
||||
int dml_stream_idx;
|
||||
struct dc_stream_state *phantom_stream;
|
||||
struct dc_stream_status *phantom_status;
|
||||
struct dmub_fams2_stream_static_state *static_state = &context->bw_ctx.bw.dcn.fams2_stream_params[num_fams2_streams];
|
||||
|
||||
struct dmub_fams2_stream_static_state *static_state = &context->bw_ctx.bw.dcn.fams2_stream_params[context->bw_ctx.bw.dcn.fams2_stream_count];
|
||||
struct dc_stream_state *stream = context->streams[i];
|
||||
|
||||
struct dc_stream_state *stream = context->streams[i];
|
||||
|
||||
if (context->stream_status[i].plane_count == 0 ||
|
||||
dml_ctx->config.svp_pstate.callbacks.get_stream_subvp_type(context, stream) == SUBVP_PHANTOM) {
|
||||
/* can ignore blanked or phantom streams */
|
||||
continue;
|
||||
}
|
||||
|
||||
dml_stream_idx = dml21_helper_find_dml_pipe_idx_by_stream_id(dml_ctx, stream->stream_id);
|
||||
if (dml_stream_idx < 0) {
|
||||
ASSERT(dml_stream_idx >= 0);
|
||||
continue;
|
||||
}
|
||||
|
||||
/* copy static state from PMO */
|
||||
memcpy(static_state,
|
||||
&dml_ctx->v21.mode_programming.programming->stream_programming[dml_stream_idx].fams2_params,
|
||||
sizeof(struct dmub_fams2_stream_static_state));
|
||||
|
||||
/* get information from context */
|
||||
static_state->num_planes = context->stream_status[i].plane_count;
|
||||
static_state->otg_inst = context->stream_status[i].primary_otg_inst;
|
||||
|
||||
/* populate pipe masks for planes */
|
||||
for (j = 0; j < context->stream_status[i].plane_count; j++) {
|
||||
for (k = 0; k < dc->res_pool->pipe_count; k++) {
|
||||
if (context->res_ctx.pipe_ctx[k].stream &&
|
||||
context->res_ctx.pipe_ctx[k].stream->stream_id == stream->stream_id &&
|
||||
context->res_ctx.pipe_ctx[k].plane_state == context->stream_status[i].plane_states[j]) {
|
||||
static_state->pipe_mask |= (1 << k);
|
||||
static_state->plane_pipe_masks[j] |= (1 << k);
|
||||
}
|
||||
if (context->stream_status[i].plane_count == 0 ||
|
||||
dml_ctx->config.svp_pstate.callbacks.get_stream_subvp_type(context, stream) == SUBVP_PHANTOM) {
|
||||
/* can ignore blanked or phantom streams */
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
/* get per method programming */
|
||||
switch (static_state->type) {
|
||||
case FAMS2_STREAM_TYPE_VBLANK:
|
||||
case FAMS2_STREAM_TYPE_VACTIVE:
|
||||
case FAMS2_STREAM_TYPE_DRR:
|
||||
break;
|
||||
case FAMS2_STREAM_TYPE_SUBVP:
|
||||
phantom_stream = dml_ctx->config.svp_pstate.callbacks.get_paired_subvp_stream(context, stream);
|
||||
if (!phantom_stream)
|
||||
break;
|
||||
dml_stream_idx = dml21_helper_find_dml_pipe_idx_by_stream_id(dml_ctx, stream->stream_id);
|
||||
if (dml_stream_idx < 0) {
|
||||
ASSERT(dml_stream_idx >= 0);
|
||||
continue;
|
||||
}
|
||||
|
||||
phantom_status = dml_ctx->config.callbacks.get_stream_status(context, phantom_stream);
|
||||
/* copy static state from PMO */
|
||||
memcpy(static_state,
|
||||
&dml_ctx->v21.mode_programming.programming->stream_programming[dml_stream_idx].fams2_params,
|
||||
sizeof(struct dmub_fams2_stream_static_state));
|
||||
|
||||
/* phantom status should always be present */
|
||||
ASSERT(phantom_status);
|
||||
static_state->sub_state.subvp.phantom_otg_inst = phantom_status->primary_otg_inst;
|
||||
/* get information from context */
|
||||
static_state->num_planes = context->stream_status[i].plane_count;
|
||||
static_state->otg_inst = context->stream_status[i].primary_otg_inst;
|
||||
|
||||
/* populate pipe masks for phantom planes */
|
||||
for (j = 0; j < phantom_status->plane_count; j++) {
|
||||
/* populate pipe masks for planes */
|
||||
for (j = 0; j < context->stream_status[i].plane_count; j++) {
|
||||
for (k = 0; k < dc->res_pool->pipe_count; k++) {
|
||||
if (context->res_ctx.pipe_ctx[k].stream &&
|
||||
context->res_ctx.pipe_ctx[k].stream->stream_id == phantom_stream->stream_id &&
|
||||
context->res_ctx.pipe_ctx[k].plane_state == phantom_status->plane_states[j]) {
|
||||
static_state->sub_state.subvp.phantom_pipe_mask |= (1 << k);
|
||||
static_state->sub_state.subvp.phantom_plane_pipe_masks[j] |= (1 << k);
|
||||
context->res_ctx.pipe_ctx[k].stream->stream_id == stream->stream_id &&
|
||||
context->res_ctx.pipe_ctx[k].plane_state == context->stream_status[i].plane_states[j]) {
|
||||
static_state->pipe_mask |= (1 << k);
|
||||
static_state->plane_pipe_masks[j] |= (1 << k);
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
default:
|
||||
ASSERT(false);
|
||||
break;
|
||||
}
|
||||
|
||||
context->bw_ctx.bw.dcn.fams2_stream_count++;
|
||||
/* get per method programming */
|
||||
switch (static_state->type) {
|
||||
case FAMS2_STREAM_TYPE_VBLANK:
|
||||
case FAMS2_STREAM_TYPE_VACTIVE:
|
||||
case FAMS2_STREAM_TYPE_DRR:
|
||||
break;
|
||||
case FAMS2_STREAM_TYPE_SUBVP:
|
||||
phantom_stream = dml_ctx->config.svp_pstate.callbacks.get_paired_subvp_stream(context, stream);
|
||||
if (!phantom_stream)
|
||||
break;
|
||||
|
||||
phantom_status = dml_ctx->config.callbacks.get_stream_status(context, phantom_stream);
|
||||
|
||||
/* phantom status should always be present */
|
||||
ASSERT(phantom_status);
|
||||
static_state->sub_state.subvp.phantom_otg_inst = phantom_status->primary_otg_inst;
|
||||
|
||||
/* populate pipe masks for phantom planes */
|
||||
for (j = 0; j < phantom_status->plane_count; j++) {
|
||||
for (k = 0; k < dc->res_pool->pipe_count; k++) {
|
||||
if (context->res_ctx.pipe_ctx[k].stream &&
|
||||
context->res_ctx.pipe_ctx[k].stream->stream_id == phantom_stream->stream_id &&
|
||||
context->res_ctx.pipe_ctx[k].plane_state == phantom_status->plane_states[j]) {
|
||||
static_state->sub_state.subvp.phantom_pipe_mask |= (1 << k);
|
||||
static_state->sub_state.subvp.phantom_plane_pipe_masks[j] |= (1 << k);
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
default:
|
||||
ASSERT(false);
|
||||
break;
|
||||
}
|
||||
|
||||
num_fams2_streams++;
|
||||
}
|
||||
}
|
||||
|
||||
context->bw_ctx.bw.dcn.clk.fw_based_mclk_switching = context->bw_ctx.bw.dcn.fams2_stream_count > 0;
|
||||
if (num_fams2_streams > 0) {
|
||||
/* copy FAMS2 configuration */
|
||||
memcpy(&context->bw_ctx.bw.dcn.fams2_global_config,
|
||||
&dml_ctx->v21.mode_programming.programming->fams2_global_config,
|
||||
sizeof(struct dmub_cmd_fams2_global_config));
|
||||
|
||||
context->bw_ctx.bw.dcn.fams2_global_config.num_streams = num_fams2_streams;
|
||||
}
|
||||
|
||||
context->bw_ctx.bw.dcn.clk.fw_based_mclk_switching = context->bw_ctx.bw.dcn.fams2_global_config.features.bits.enable;
|
||||
}
|
||||
|
||||
bool dml21_is_plane1_enabled(enum dml2_source_format_class source_format)
|
||||
|
|
|
@ -351,6 +351,7 @@ static void pack_mode_programming_params_with_implicit_subvp(struct dml2_core_in
|
|||
programming->fams2_required = display_cfg->stage3.fams2_required;
|
||||
|
||||
dml2_core_calcs_get_global_fams2_programming(&core->clean_me_up.mode_lib, display_cfg, &programming->fams2_global_config);
|
||||
programming->fams2_global_config.features.bits.enable = display_cfg->stage3.fams2_required;
|
||||
}
|
||||
|
||||
// Only loop over all the main streams (the implicit svp streams will be packed as part of the main stream)
|
||||
|
|
|
@ -12221,12 +12221,19 @@ void dml2_core_calcs_get_global_fams2_programming(const struct dml2_core_interna
|
|||
const struct display_configuation_with_meta *display_cfg,
|
||||
struct dmub_cmd_fams2_global_config *fams2_global_config)
|
||||
{
|
||||
fams2_global_config->max_allow_delay_us = mode_lib->ip_caps.fams2.max_allow_delay_us;
|
||||
fams2_global_config->lock_wait_time_us = mode_lib->ip_caps.fams2.lock_timeout_us;
|
||||
fams2_global_config->recovery_timeout_us = mode_lib->ip_caps.fams2.recovery_timeout_us;
|
||||
fams2_global_config->hwfq_flip_programming_delay_us = mode_lib->ip_caps.fams2.flip_programming_delay_us;
|
||||
fams2_global_config->features.bits.enable = display_cfg->stage3.fams2_required;
|
||||
|
||||
fams2_global_config->num_streams = display_cfg->display_config.num_streams;
|
||||
if (fams2_global_config->features.bits.enable) {
|
||||
fams2_global_config->features.bits.enable_stall_recovery = true;
|
||||
fams2_global_config->features.bits.allow_delay_check_mode = FAMS2_ALLOW_DELAY_CHECK_FROM_START;
|
||||
|
||||
fams2_global_config->max_allow_delay_us = mode_lib->ip_caps.fams2.max_allow_delay_us;
|
||||
fams2_global_config->lock_wait_time_us = mode_lib->ip_caps.fams2.lock_timeout_us;
|
||||
fams2_global_config->recovery_timeout_us = mode_lib->ip_caps.fams2.recovery_timeout_us;
|
||||
fams2_global_config->hwfq_flip_programming_delay_us = mode_lib->ip_caps.fams2.flip_programming_delay_us;
|
||||
|
||||
fams2_global_config->num_streams = display_cfg->display_config.num_streams;
|
||||
}
|
||||
}
|
||||
|
||||
void dml2_core_calcs_get_stream_fams2_programming(const struct dml2_core_internal_display_mode_lib *mode_lib,
|
||||
|
|
|
@ -1531,7 +1531,7 @@ void dcn401_fams2_update_config(struct dc *dc, struct dc_state *context, bool en
|
|||
if (!dc->ctx || !dc->ctx->dmub_srv || !dc->debug.fams2_config.bits.enable)
|
||||
return;
|
||||
|
||||
fams2_required = context->bw_ctx.bw.dcn.fams2_stream_count > 0;
|
||||
fams2_required = context->bw_ctx.bw.dcn.fams2_global_config.features.bits.enable;
|
||||
|
||||
dc_dmub_srv_fams2_update_config(dc, context, enable && fams2_required);
|
||||
}
|
||||
|
@ -1656,7 +1656,7 @@ void dcn401_hardware_release(struct dc *dc)
|
|||
*/
|
||||
if (dc->current_state) {
|
||||
if ((!dc->clk_mgr->clks.p_state_change_support ||
|
||||
dc->current_state->bw_ctx.bw.dcn.fams2_stream_count > 0) &&
|
||||
dc->current_state->bw_ctx.bw.dcn.fams2_global_config.features.bits.enable) &&
|
||||
dc->res_pool->hubbub->funcs->force_pstate_change_control)
|
||||
dc->res_pool->hubbub->funcs->force_pstate_change_control(
|
||||
dc->res_pool->hubbub, true, true);
|
||||
|
|
|
@ -534,8 +534,8 @@ struct dcn_bw_output {
|
|||
unsigned int legacy_svp_drr_stream_index;
|
||||
bool legacy_svp_drr_stream_index_valid;
|
||||
struct dml2_mcache_surface_allocation mcache_allocations[DML2_MAX_PLANES];
|
||||
struct dmub_cmd_fams2_global_config fams2_global_config;
|
||||
struct dmub_fams2_stream_static_state fams2_stream_params[DML2_MAX_PLANES];
|
||||
unsigned fams2_stream_count;
|
||||
struct dml2_display_arb_regs arb_regs;
|
||||
};
|
||||
|
||||
|
|
Loading…
Reference in New Issue
Block a user