[PATCH 04/41] drm/amd/display: Dependent changes for DCN6
<[email protected]> Fri, 31 Jul 2026 17:12:25 -0400
| Newsgroups | org.freedesktop.lists.amd-gfx |
|---|---|
| Message-ID | <[email protected]> |
From: Aurabindo Pillai <[email protected]> changes needed to enable DCN6 asic Signed-off-by: Aurabindo Pillai <[email protected]> Signed-off-by: Roman Li <[email protected]> Reviewed-by: Ivan Lipski <[email protected]> --- .../amd/display/amdgpu_dm/amdgpu_dm_audio.h | 2 +- .../amd/display/amdgpu_dm/amdgpu_dm_helpers.c | 6 + .../gpu/drm/amd/display/dc/clk_mgr/clk_mgr.c | 15 + drivers/gpu/drm/amd/display/dc/core/dc.c | 10 +- .../drm/amd/display/dc/core/dc_hw_sequencer.c | 410 +++++++++++++++ .../gpu/drm/amd/display/dc/core/dc_resource.c | 47 ++ .../gpu/drm/amd/display/dc/core/dc_state.c | 12 + .../gpu/drm/amd/display/dc/core/dc_stream.c | 24 + drivers/gpu/drm/amd/display/dc/dc.h | 26 +- drivers/gpu/drm/amd/display/dc/dc_dmub_srv.c | 44 ++ drivers/gpu/drm/amd/display/dc/dc_dmub_srv.h | 23 + drivers/gpu/drm/amd/display/dc/dc_helper.c | 2 + drivers/gpu/drm/amd/display/dc/dc_hw_types.h | 53 +- .../gpu/drm/amd/display/dc/dc_spl_translate.c | 32 +- .../gpu/drm/amd/display/dc/dc_state_priv.h | 1 + drivers/gpu/drm/amd/display/dc/dc_stream.h | 5 + drivers/gpu/drm/amd/display/dc/dc_types.h | 10 + .../amd/display/dc/dccg/dcn20/dcn20_dccg.h | 10 + .../drm/amd/display/dc/dce/dce_clock_source.c | 24 + .../drm/amd/display/dc/dce/dce_clock_source.h | 9 + .../display/dc/dio/dcn10/dcn10_link_encoder.h | 16 + .../dc/dio/dcn401/dcn401_dio_link_encoder.c | 15 + .../dc/dio/dcn401/dcn401_dio_link_encoder.h | 10 + drivers/gpu/drm/amd/display/dc/dm_helpers.h | 8 + .../dml2_0/dml21/dml21_translation_helper.c | 57 +- .../amd/display/dc/dml2_0/dml21/dml21_utils.c | 129 ++++- .../dml21/inc/dml_top_display_cfg_types.h | 10 + .../dml21/inc/dml_top_soc_parameter_types.h | 2 + .../dc/dml2_0/dml21/inc/dml_top_types.h | 45 ++ .../src/dml2_core/dml2_core_dcn4_calcs.c | 1 + .../dml21/src/dml2_core/dml2_core_factory.c | 25 + .../src/dml2_core/dml2_core_shared_types.h | 160 ++++++ .../dml21/src/dml2_dpmm/dml2_dpmm_factory.c | 12 + .../dml21/src/dml2_mcg/dml2_mcg_factory.c | 5 + .../dml21/src/dml2_pmo/dml2_pmo_dcn4_fams2.c | 57 ++ .../dml21/src/dml2_pmo/dml2_pmo_factory.c | 34 ++ .../dml21/src/dml2_top/dml2_top_interfaces.c | 7 + .../src/inc/dml2_internal_shared_types.h | 485 ++++++++++++++++++ .../drm/amd/display/dc/dml2_0/dml2_wrapper.h | 8 + .../amd/display/dc/dpp/dcn401/dcn401_dpp.h | 41 ++ .../display/dc/dpp/dcn401/dcn401_dpp_dscl.c | 26 +- .../drm/amd/display/dc/dpp/dcn42/dcn42_dpp.c | 7 +- .../drm/amd/display/dc/dpp/dcn42/dcn42_dpp.h | 6 + .../gpu/drm/amd/display/dc/gpio/ddc_regs.h | 15 + drivers/gpu/drm/amd/display/dc/gpio/hw_ddc.c | 302 +++++++++++ drivers/gpu/drm/amd/display/dc/gpio/hw_ddc.h | 28 + .../gpu/drm/amd/display/dc/gpio/hw_factory.c | 4 + .../drm/amd/display/dc/gpio/hw_translate.c | 4 + .../gpu/drm/amd/display/dc/hdcp/hdcp_msg.c | 9 + .../display/dc/hubbub/dcn10/dcn10_hubbub.h | 108 ++++ .../amd/display/dc/hubp/dcn20/dcn20_hubp.h | 29 ++ .../drm/amd/display/dc/hwss/dce/dce_hwseq.h | 9 + .../amd/display/dc/hwss/dce110/dce110_hwseq.c | 11 + .../amd/display/dc/hwss/dcn10/dcn10_hwseq.c | 3 +- .../amd/display/dc/hwss/dcn20/dcn20_hwseq.c | 3 +- .../amd/display/dc/hwss/dcn30/dcn30_hwseq.c | 3 +- .../amd/display/dc/hwss/dcn32/dcn32_hwseq.c | 5 +- .../amd/display/dc/hwss/dcn35/dcn35_hwseq.c | 1 + .../amd/display/dc/hwss/dcn401/dcn401_hwseq.c | 32 ++ .../drm/amd/display/dc/hwss/hw_sequencer.h | 17 + .../gpu/drm/amd/display/dc/inc/core_types.h | 1 + .../amd/display/dc/inc/hw/clk_mgr_internal.h | 22 + .../amd/display/dc/inc/hw/cursor_reg_cache.h | 3 +- drivers/gpu/drm/amd/display/dc/inc/hw/dpp.h | 7 + .../drm/amd/display/dc/inc/hw/link_encoder.h | 6 + .../gpu/drm/amd/display/dc/inc/hw/transform.h | 1 + drivers/gpu/drm/amd/display/dc/inc/resource.h | 2 + .../drm/amd/display/dc/link/link_detection.c | 29 ++ .../drm/amd/display/dc/link/link_factory.c | 5 + .../amd/display/dc/link/protocols/link_ddc.c | 8 + .../display/dc/link/protocols/link_hdmi_frl.c | 5 + .../amd/display/dc/optc/dcn42/dcn42_optc.c | 4 +- .../amd/display/dc/optc/dcn42/dcn42_optc.h | 2 + .../dc/resource/dcn10/dcn10_resource.c | 1 + .../dc/resource/dcn20/dcn20_resource.c | 1 + .../dc/resource/dcn201/dcn201_resource.c | 1 + .../dc/resource/dcn21/dcn21_resource.c | 1 + .../dc/resource/dcn30/dcn30_resource.c | 1 + .../dc/resource/dcn301/dcn301_resource.c | 1 + .../dc/resource/dcn302/dcn302_resource.c | 1 + .../dc/resource/dcn303/dcn303_resource.c | 1 + .../dc/resource/dcn314/dcn314_resource.c | 1 + .../dc/resource/dcn315/dcn315_resource.c | 1 + .../dc/resource/dcn32/dcn32_resource.c | 1 + .../dc/resource/dcn321/dcn321_resource.c | 1 + .../dc/resource/dcn35/dcn35_resource.c | 1 + .../dc/resource/dcn351/dcn351_resource.c | 1 + .../dc/resource/dcn36/dcn36_resource.c | 1 + .../dc/resource/dcn401/dcn401_resource.c | 33 +- .../dc/resource/dcn401/dcn401_resource.h | 4 + .../dc/resource/dcn42/dcn42_resource.c | 1 + .../soc_and_ip_translator.c | 4 + drivers/gpu/drm/amd/display/dmub/dmub_srv.h | 5 + .../gpu/drm/amd/display/dmub/inc/dmub_cmd.h | 175 ++++++- .../gpu/drm/amd/display/dmub/src/dmub_srv.c | 52 ++ .../gpu/drm/amd/display/include/dal_asic_id.h | 18 + 96 files changed, 2871 insertions(+), 45 deletions(-) diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_audio.h b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_audio.h index e57e2ed20d56..7ccb026ece56 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_audio.h +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_audio.h @@ -28,7 +28,7 @@ struct amdgpu_device; struct drm_device; -struct drm_atomic_state; +struct drm_atomic_commit; struct drm_connector; struct audio_info; struct dc_sink; diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c index c720c319e795..d451082552e8 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c @@ -1903,3 +1903,9 @@ void dm_helpers_mccs_vcp_set(struct dc_context *ctx, struct dc_link *link, } EXPORT_IF_KUNIT(dm_helpers_mccs_vcp_set); +bool dm_helpers_submit_i2c_over_aux(struct ddc_service *ddc, uint32_t address, uint8_t offset, + uint8_t *cmdBuffer, uint32_t len, bool read) +{ + //TODO: Implement this + return false; +} diff --git a/drivers/gpu/drm/amd/display/dc/clk_mgr/clk_mgr.c b/drivers/gpu/drm/amd/display/dc/clk_mgr/clk_mgr.c index 2a1353cb7e7d..e2148cb3b8ab 100644 --- a/drivers/gpu/drm/amd/display/dc/clk_mgr/clk_mgr.c +++ b/drivers/gpu/drm/amd/display/dc/clk_mgr/clk_mgr.c @@ -50,6 +50,7 @@ #include "dcn401/dcn401_clk_mgr.h" #include "dcn42/dcn42_clk_mgr.h" #include "dcn42b/dcn42b_clk_mgr.h" +#include "dcn60/dcn60_clk_mgr.h" int clk_mgr_helper_get_active_display_cnt( struct dc *dc, @@ -387,6 +388,17 @@ struct clk_mgr *dc_clk_mgr_create(struct dc_context *ctx, struct pp_smu_funcs *p return &clk_mgr->base.base; } break; + case AMDGPU_FAMILY_GC_13_0_1: { + struct clk_mgr_internal *clk_mgr = dcn60_clk_mgr_construct(ctx, dccg); + + if (clk_mgr == NULL) { + BREAK_TO_DEBUGGER(); + return NULL; + } + + return &clk_mgr->base; + } + #endif /* CONFIG_DRM_AMD_DC_FP */ default: ASSERT(0); /* Unknown Asic */ @@ -451,6 +463,9 @@ void dc_destroy_clk_mgr(struct clk_mgr *clk_mgr_base) case AMDGPU_FAMILY_GC_11_5_4: dcn42_clk_mgr_destroy(clk_mgr); break; + case AMDGPU_FAMILY_GC_13_0_1: + dcn60_clk_mgr_destroy(clk_mgr); + break; default: break; diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c index 6c1a8ecc2cb5..7f378b5e896c 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc.c @@ -3099,7 +3099,8 @@ static struct dc_update_descriptor det_surface_update( update_bits->gamut_remap_change || update_bits->input_csc_change || update_bits->cm_hist_change || - update_bits->coeff_reduction_change)) { + update_bits->coeff_reduction_change || + update_bits->cursor_csc_color_matrix_change)) { elevate_update_type(&overall_type, UPDATE_TYPE_FULL, LOCK_DESCRIPTOR_GLOBAL); } return overall_type; @@ -3403,6 +3404,10 @@ static void copy_surface_update_to_plane( srf_update->plane_info->dcc; surface->layer_index = srf_update->plane_info->layer_index; + surface->scaling_linearity = + srf_update->plane_info->scaling_linearity; + surface->cositing = + srf_update->plane_info->cositing; } if (srf_update->gamma) { @@ -3658,6 +3663,9 @@ static void copy_stream_update_to_stream(struct dc *dc, if (update->sharpening_required) stream->sharpening_required = *update->sharpening_required; + if (update->blending_linearity) + stream->blending_linearity = *update->blending_linearity; + if (update->drr_trigger_mode) { stream->drr_trigger_mode = *update->drr_trigger_mode; } diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/core/dc_hw_sequencer.c index 11411fa94665..8878652434d2 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_hw_sequencer.c @@ -41,6 +41,7 @@ #include "dcn10/dcn10_hubbub.h" #include "dce/dmub_hw_lock_mgr.h" #include "link_service.h" +#include "custom_float.h" #define MAX_NUM_MCACHE 8 @@ -729,6 +730,386 @@ void get_fams2_visual_confirm_color( } } +static bool get_update_dchubp_dpp_flags_status(struct pipe_ctx *pipe) +{ + if (!pipe->plane_state) { + return false; + } + + if ((pipe->update_flags.raw || + dc_pipe_update_bits_is_any_set(&pipe->plane_state->update_bits) || + pipe->stream->update_flags.raw)) { + return true; + } + + return false; +} + +// Function to check if any update flags are set +static bool get_pipe_update_bits_status(struct pipe_ctx *pipe, struct dc_plane_state *plane, struct dc_stream_state *stream) +{ + (void)stream; + if (plane) { + return (pipe->update_flags.bits.enable || + pipe->update_flags.bits.plane_changed || + pipe->update_flags.bits.opp_changed || + plane->update_bits.pixel_format_change || + plane->update_bits.horizontal_mirror_change || + plane->update_bits.rotation_change || + plane->update_bits.swizzle_change || + plane->update_bits.dcc_change || + plane->update_bits.bpp_change || + plane->update_bits.scaling_change || + plane->update_bits.plane_size_change); + } + return false; +} + +void hwss_build_full_sequence(struct dc *dc, + struct block_sequence block_sequence[MAX_HWSS_BLOCK_SEQUENCE_SIZE], + unsigned int *num_steps, + struct dc_state *context, bool program_phantom_pipe) +{ + (void)program_phantom_pipe; + struct dc_plane_state *plane = NULL; + struct dc_stream_state *stream = NULL; + struct pipe_ctx *current_pipe = NULL; + struct pipe_ctx *pipe = NULL; + struct dce_hwseq *hws = dc->hwseq; + unsigned int i; + *num_steps = 0; // Initialize to 0 + struct block_sequence_state seq_state = { .steps = block_sequence, .num_steps = num_steps }; + + for (i = 0; i < dc->res_pool->pipe_count; i++) + dc->hwss.detect_pipe_changes(dc->current_state, context, &dc->current_state->res_ctx.pipe_ctx[i], + &context->res_ctx.pipe_ctx[i]); + + /* Program triplebuffer if enabled */ + if (dc->hwss.program_triplebuffer != NULL && dc->debug.enable_tri_buf) { + for (i = 0; i < dc->res_pool->pipe_count; i++) { + pipe = &context->res_ctx.pipe_ctx[i]; + + if (pipe->plane_state) { + /* Turn off triple buffer for full update */ + hwss_add_hubp_program_triplebuffer(&seq_state, dc, pipe, pipe->plane_state->triplebuffer_flips); + } + } + } + + /* Count hubp usage and force pstate change if needed */ + unsigned int prev_hubp_count = 0; + unsigned int hubp_count = 0; + + for (i = 0; i < dc->res_pool->pipe_count; i++) { + if (dc->current_state->res_ctx.pipe_ctx[i].plane_state) + prev_hubp_count++; + if (context->res_ctx.pipe_ctx[i].plane_state) + hubp_count++; + } + + if (prev_hubp_count == 0 && hubp_count > 0) { + if (dc->res_pool->hubbub->funcs->force_pstate_change_control) + hwss_add_hubbub_force_pstate_change_control(&seq_state, dc->res_pool->hubbub, true, false); + } + + /* When disabling phantom pipes, turn on phantom OTG first */ + for (i = 0; i < dc->res_pool->pipe_count; i++) { + struct dc_stream_state *pipe_stream = dc->current_state->res_ctx.pipe_ctx[i].stream; + + pipe = &dc->current_state->res_ctx.pipe_ctx[i]; + + if (context->res_ctx.pipe_ctx[i].update_flags.bits.disable && pipe_stream && + dc_state_get_pipe_subvp_type(dc->current_state, pipe) == SUBVP_PHANTOM) { + struct timing_generator *tg = dc->current_state->res_ctx.pipe_ctx[i].stream_res.tg; + + if (tg->funcs->enable_crtc) { + if (dc->hwseq->funcs.blank_pixel_data_sequence) + dc->hwseq->funcs.blank_pixel_data_sequence(dc, pipe, true, &seq_state); + hwss_add_tg_enable_crtc(&seq_state, tg); + } + } + } + + /* OTG blank before disabling all front ends */ + for (i = 0; i < dc->res_pool->pipe_count; i++) { + if (context->res_ctx.pipe_ctx[i].update_flags.bits.disable + && !context->res_ctx.pipe_ctx[i].top_pipe + && !context->res_ctx.pipe_ctx[i].prev_odm_pipe + && context->res_ctx.pipe_ctx[i].stream) { + + if (dc->hwseq->funcs.blank_pixel_data_sequence) { + dc->hwseq->funcs.blank_pixel_data_sequence(dc, &context->res_ctx.pipe_ctx[i], + true, &seq_state); + } + } + } + + /* Disconnect mpcc for pipes being disabled or with opp changes */ + for (i = 0; i < dc->res_pool->pipe_count; i++) { + if (context->res_ctx.pipe_ctx[i].update_flags.bits.disable + || context->res_ctx.pipe_ctx[i].update_flags.bits.opp_changed) { + struct hubbub *hubbub = dc->res_pool->hubbub; + + /* Phantom pipe DET should be 0, but if a pipe in use is being transitioned to phantom + * then we want to do the programming here (effectively it's being disabled). If we do + * the programming later the DET won't be updated until the OTG for the phantom pipe is + * turned on (i.e. in an MCLK switch) which can come in too late and cause issues with + * DET allocation. + */ + if ((context->res_ctx.pipe_ctx[i].update_flags.bits.disable || + (context->res_ctx.pipe_ctx[i].plane_state && + dc_state_get_pipe_subvp_type(context, &context->res_ctx.pipe_ctx[i]) == + SUBVP_PHANTOM))) { + + if (hubbub->funcs->program_det_size) { + hwss_add_hubp_program_det_size(&seq_state, hubbub, + dc->current_state->res_ctx.pipe_ctx[i].plane_res.hubp->inst, 0); + } + + if (dc->res_pool->hubbub->funcs->program_det_segments) { + hwss_add_hubp_program_det_segments(&seq_state, hubbub, + dc->current_state->res_ctx.pipe_ctx[i].plane_res.hubp->inst, 0); + } + } + + if (hws->funcs.plane_atomic_disconnect_sequence) + hws->funcs.plane_atomic_disconnect_sequence(dc, dc->current_state, + &dc->current_state->res_ctx.pipe_ctx[i], &seq_state); + } + } + + /* update ODM for blanked OTG master pipes */ + for (i = 0; i < dc->res_pool->pipe_count; i++) { + pipe = &context->res_ctx.pipe_ctx[i]; + if (resource_is_pipe_type(pipe, OTG_MASTER) && + !resource_is_pipe_type(pipe, DPP_PIPE) && + pipe->update_flags.bits.odm) { + if (hws->funcs.update_odm_sequence) + hws->funcs.update_odm_sequence(dc, context, pipe, &seq_state); + } + } + + for (i = 0; i < dc->res_pool->pipe_count; i++) { + pipe = &context->res_ctx.pipe_ctx[i]; + if (pipe->update_flags.bits.disable) { + struct cm_hist_control hist_disable = { .channels_enabled = 0 }; + + hwss_add_dpp_program_cm_hist(&seq_state, pipe->plane_res.dpp, + hist_disable, COLOR_SPACE_UNKNOWN); + } + } + + for (i = 0; i < dc->res_pool->pipe_count; i++) { + pipe = &context->res_ctx.pipe_ctx[i]; + + if (pipe->plane_state && !pipe->top_pipe) { + while (pipe) { + if (pipe->stream && + dc_state_get_pipe_subvp_type(context, pipe) != SUBVP_PHANTOM) { + if (hws->funcs.program_pipe_sequence) + hws->funcs.program_pipe_sequence(dc, pipe, context, &seq_state); + } + + pipe = pipe->bottom_pipe; + } + } + + /* Program secondary blending tree and writeback pipes */ + pipe = &context->res_ctx.pipe_ctx[i]; + if (!pipe->top_pipe && !pipe->prev_odm_pipe + && pipe->stream && pipe->stream->num_wb_info > 0 + && (pipe->update_flags.raw || (pipe->plane_state && dc_pipe_update_bits_is_any_set(&pipe->plane_state->update_bits)) + || pipe->stream->update_flags.raw)) { + + if (hws->funcs.program_all_writeback_pipes_in_tree_sequence) + hws->funcs.program_all_writeback_pipes_in_tree_sequence(dc, pipe->stream, + context, &seq_state); + } + + /* Avoid underflow by check of pipe line read when adding 2nd plane. */ + if (hws->wa.wait_hubpret_read_start_during_mpo_transition && + !pipe->top_pipe && + pipe->stream && + pipe->plane_res.hubp->funcs->hubp_wait_pipe_read_start && + dc->current_state->stream_status[0].plane_count == 1 && + context->stream_status[0].plane_count > 1) { + hwss_add_hubp_wait_pipe_read_start(&seq_state, pipe->plane_res.hubp); + } + } + + for (i = 0; i < dc->res_pool->pipe_count; i++) { + current_pipe = &context->res_ctx.pipe_ctx[i]; + + while (current_pipe) { + plane = current_pipe->plane_state; + stream = current_pipe->stream; + bool is_phantom = (dc_state_get_pipe_subvp_type(context, current_pipe) == SUBVP_PHANTOM); + + if (get_update_dchubp_dpp_flags_status(current_pipe)) { + if (!is_phantom && plane && stream) { + if (get_pipe_update_bits_status(current_pipe, plane, stream)) { + struct plane_size size = plane->plane_size; + + size.surface_size = current_pipe->plane_res.scl_data.viewport; + hwss_add_hubp_program_surface_config(&seq_state, current_pipe->plane_res.hubp, + plane->format, &plane->tiling_info, size, plane->rotation, &plane->dcc, + plane->horizontal_mirror, 0); + } + + if (current_pipe->plane_res.hubp->funcs->hubp_program_mcache_id_and_split_coordinate) + hwss_add_hubp_program_mcache_id(&seq_state, current_pipe->plane_res.hubp, ¤t_pipe->mcache_regs); + + if (current_pipe->plane_res.dpp->funcs->dpp_program_upsp) { + block_sequence[*num_steps].params.program_upsp_params.pipe_ctx = current_pipe; + block_sequence[*num_steps].func = DPP_PROGRAM_UPSP; + (*num_steps)++; + } + } + } + current_pipe = current_pipe->bottom_pipe; + } + } +} + +void hwss_build_post_unlock_full_sequence(struct dc *dc, + struct block_sequence block_sequence[MAX_HWSS_BLOCK_SEQUENCE_SIZE], + unsigned int *num_steps, + struct dc_state *context) +{ + unsigned int i; + struct dce_hwseq *hwseq = dc->hwseq; + *num_steps = 0; // Initialize to 0 + struct block_sequence_state seq_state = { .steps = block_sequence, .num_steps = num_steps }; + + /* Reset OPP for pipes transitioning from OPP_HEAD to non-OPP_HEAD */ + for (i = 0; i < dc->res_pool->pipe_count; i++) { + if (resource_is_pipe_type(&dc->current_state->res_ctx.pipe_ctx[i], OPP_HEAD) && + !resource_is_pipe_type(&context->res_ctx.pipe_ctx[i], OPP_HEAD)) { + + if (dc->hwss.post_unlock_reset_opp_sequence) + dc->hwss.post_unlock_reset_opp_sequence(dc, &dc->current_state->res_ctx.pipe_ctx[i], + &seq_state); + } + } + + /* Disable planes that are being disabled */ + for (i = 0; i < dc->res_pool->pipe_count; i++) { + if (context->res_ctx.pipe_ctx[i].update_flags.bits.disable) { + if (dc->hwss.disable_plane_sequence) + dc->hwss.disable_plane_sequence(dc, dc->current_state, &dc->current_state->res_ctx.pipe_ctx[i], + &seq_state); + } + } + + /* Wait for flip pending on pipes being enabled */ + for (i = 0; i < dc->res_pool->pipe_count; i++) { + struct pipe_ctx *pipe = &context->res_ctx.pipe_ctx[i]; + + if (pipe->plane_state && !pipe->top_pipe && pipe->update_flags.bits.enable && + dc_state_get_pipe_subvp_type(context, pipe) != SUBVP_PHANTOM) { + + unsigned int polling_interval_us; + polling_interval_us = 1; + hwss_add_hubp_wait_flip_pending(&seq_state, pipe->plane_res.hubp, 100000, polling_interval_us); + } + } + + /* Wait for double buffer pending when ODM slice count increases */ + for (i = 0; i < dc->res_pool->pipe_count; i++) { + struct pipe_ctx *pipe = &context->res_ctx.pipe_ctx[i]; + struct pipe_ctx *old_pipe = &dc->current_state->res_ctx.pipe_ctx[i]; + + if (resource_is_pipe_type(old_pipe, OTG_MASTER) && resource_is_pipe_type(pipe, OTG_MASTER) && + resource_get_odm_slice_count(old_pipe) < resource_get_odm_slice_count(pipe) && + dc_state_get_pipe_subvp_type(context, pipe) != SUBVP_PHANTOM) { + + unsigned int polling_interval_us; + polling_interval_us = 1; + hwss_add_tg_wait_double_buffer_pending(&seq_state, pipe->stream_res.tg, 100000, polling_interval_us); + } + } + + /* Force pstate change control to false */ + if (dc->res_pool->hubbub->funcs->force_pstate_change_control) + hwss_add_hubbub_force_pstate_change_control(&seq_state, dc->res_pool->hubbub, false, false); + + /* Program phantom pipes */ + for (i = 0; i < dc->res_pool->pipe_count; i++) { + struct pipe_ctx *pipe = &context->res_ctx.pipe_ctx[i]; + + if (pipe->plane_state && !pipe->top_pipe) { + while (pipe) { + if (pipe->stream && dc_state_get_pipe_subvp_type(context, pipe) == SUBVP_PHANTOM) { + /* Apply update flags for phantom pipes using existing HWS functions */ + if (dc->hwss.apply_update_flags_for_phantom) + hwss_add_hws_apply_update_flags_for_phantom(&seq_state, pipe); + if (dc->hwss.update_phantom_vp_position) + hwss_add_hws_update_phantom_vp_position(&seq_state, dc, context, pipe); + + /* Program the phantom pipe - use program_pipe_sequence if available */ + if (dc->hwseq && dc->hwseq->funcs.program_pipe_sequence) + dc->hwseq->funcs.program_pipe_sequence(dc, pipe, context, &seq_state); + } + pipe = pipe->bottom_pipe; + } + } + } + + for (i = 0; i < dc->res_pool->pipe_count; i++) { + struct pipe_ctx *pipe = &context->res_ctx.pipe_ctx[i]; + + while (pipe) { + struct dc_plane_state *plane = pipe->plane_state; + struct dc_stream_state *stream = pipe->stream; + bool is_phantom = (dc_state_get_pipe_subvp_type(context, pipe) == SUBVP_PHANTOM); + + if (get_update_dchubp_dpp_flags_status(pipe)) { + if (is_phantom && plane && stream) { + if (get_pipe_update_bits_status(pipe, plane, stream)) { + struct plane_size size = plane->plane_size; + + size.surface_size = pipe->plane_res.scl_data.viewport; + hwss_add_hubp_program_surface_config(&seq_state, pipe->plane_res.hubp, + plane->format, &plane->tiling_info, size, plane->rotation, &plane->dcc, + plane->horizontal_mirror, 0); + } + + if (pipe->plane_res.hubp->funcs->hubp_program_mcache_id_and_split_coordinate) + hwss_add_hubp_program_mcache_id(&seq_state, pipe->plane_res.hubp, &pipe->mcache_regs); + } + } + pipe = pipe->bottom_pipe; + } + } + + /* Update force pstate if hwseq is available */ + if (hwseq && hwseq->funcs.update_force_pstate) + hwss_add_update_force_pstate(&seq_state, dc, context); + + /* Program MALL pipe configuration */ + if (hwseq && hwseq->funcs.program_mall_pipe_config_sequence) + hwseq->funcs.program_mall_pipe_config_sequence(dc, context, &seq_state); + + /* Apply DEDCN21 147 WA if needed */ + if (hwseq && hwseq->wa.DEGVIDCN21) + hwss_add_hubbub_apply_dedcn21_147_wa(&seq_state, dc->res_pool->hubbub); + + /* Handle stutter underflow WA during MPO transitions */ + if (hwseq && hwseq->wa.disallow_self_refresh_during_multi_plane_transition && + dc->current_state->stream_status[0].plane_count == 1 && + context->stream_status[0].plane_count > 1) { + + hwss_add_hubbub_allow_self_refresh_control(&seq_state, dc->res_pool->hubbub, false, + &hwseq->wa_state.disallow_self_refresh_during_multi_plane_transition_applied); + + /* Get frame count for WA state tracking - this needs to be done immediately after the above call */ + if (dc->res_pool->timing_generators[0]->funcs->get_frame_count) { + hwss_add_tg_get_frame_count(&seq_state, dc->res_pool->timing_generators[0], + &hwseq->wa_state.disallow_self_refresh_during_multi_plane_transition_applied_on_frame); + } + } +} + void hwss_build_fast_sequence(struct dc *dc, struct dc_dmub_cmd *dc_dmub_cmd, unsigned int dmub_cmd_count, @@ -1058,6 +1439,16 @@ void hwss_build_fast_sequence(struct dc *dc, (*num_steps)++; } + if (current_mpc_pipe->plane_state->update_bits.lut_3d && + current_mpc_pipe->plane_state->cm.flags.bits.lut3d_dma_enable && + current_mpc_pipe->plane_state->cm.flags.bits.shaper_enable && + current_mpc_pipe->plane_state->cm.flags.bits.lut3d_enable && + current_mpc_pipe->plane_res.hubp->funcs->hubp_enable_3dlut_fl) { + block_sequence[*num_steps].params.hubp_enable_3dlut_fl_params.hubp = + current_mpc_pipe->plane_res.hubp; + block_sequence[*num_steps].func = HUBP_ENABLE_3DLUT_FL; + (*num_steps)++; + } if (hws->funcs.set_input_transfer_func && current_mpc_pipe->plane_state->update_bits.gamma_change) { block_sequence[*num_steps].params.set_input_transfer_func_params.dc = dc; block_sequence[*num_steps].params.set_input_transfer_func_params.pipe_ctx = current_mpc_pipe; @@ -1279,6 +1670,9 @@ void hwss_execute_sequence(struct dc *dc, case DPP_SET_OUTPUT_TRANSFER_FUNC: hws->funcs.set_output_transfer_func(¶ms->set_output_transfer_func_params); break; + case DPP_PROGRAM_UPSP: + hwss_program_upsp(params); + break; case MPC_UPDATE_VISUAL_CONFIRM: dc->hwss.update_visual_confirm_color(params->update_visual_confirm_params.dc, params->update_visual_confirm_params.pipe_ctx, @@ -2448,6 +2842,22 @@ void hwss_program_bias_and_scale(union block_sequence_params *params) dpp->funcs->dpp_program_bias_and_scale(dpp, &bns_params); } +void hwss_program_upsp(union block_sequence_params *params) +{ + struct pipe_ctx *pipe_ctx = params->program_upsp_params.pipe_ctx; + struct dpp *dpp = pipe_ctx->plane_res.dpp; + struct dscl_prog_data *dscl_prog_data = &pipe_ctx->plane_res.scl_data.dscl_prog_data; + + if (!dpp || !dscl_prog_data) + return; + + if (dpp && dpp->funcs->dpp_program_upsp) { + // program upsampler + dpp->funcs->dpp_program_upsp(dpp, + dscl_prog_data); + } +} + void hwss_power_on_mpc_mem_pwr(union block_sequence_params *params) { struct mpc *mpc = params->power_on_mpc_mem_pwr_params.mpc; diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c index b970f152d67f..7eaaf38cd9ab 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c @@ -80,6 +80,7 @@ #include "dcn401/dcn401_resource.h" #include "dcn42/dcn42_resource.h" #include "dcn42b/dcn42b_resource.h" +#include "dcn60/dcn60_resource.h" #if defined(CONFIG_DRM_AMD_DC_FP) #include "dc_spl_translate.h" #endif @@ -261,6 +262,9 @@ enum dce_version resource_parse_asic_id(struct hw_asic_id asic_id) case AMDGPU_FAMILY_GC_11_5_4: dc_version = DCN_VERSION_4_2; break; + case AMDGPU_FAMILY_GC_13_0_1: + dc_version = DCN_VERSION_6_0; + break; default: dc_version = DCE_VERSION_UNKNOWN; break; @@ -383,6 +387,9 @@ struct resource_pool *dc_create_resource_pool(struct dc *dc, case DCN_VERSION_4_2B: res_pool = dcn42b_create_resource_pool(init_data, dc); break; + case DCN_VERSION_6_0: + res_pool = dcn60_create_resource_pool(init_data, dc); + break; #endif /* CONFIG_DRM_AMD_DC_FP */ default: break; @@ -818,6 +825,36 @@ static enum dc_pixel_format convert_pixel_format_to_dalsurface( case SURFACE_PIXEL_FORMAT_VIDEO_420_10bpc_YCrCb: dal_pixel_format = PIXEL_FORMAT_420BPP10; break; + case SURFACE_PIXEL_FORMAT_VIDEO_422_CrCb_P208: + case SURFACE_PIXEL_FORMAT_VIDEO_422_CbCr_P208: + dal_pixel_format = PIXEL_FORMAT_422BPP8; + break; + case SURFACE_PIXEL_FORMAT_VIDEO_422_CrCb_P210: + case SURFACE_PIXEL_FORMAT_VIDEO_422_CbCr_P210: + dal_pixel_format = PIXEL_FORMAT_422BPP10; + break; + case SURFACE_PIXEL_FORMAT_VIDEO_422_CrCb_P212: + case SURFACE_PIXEL_FORMAT_VIDEO_422_CbCr_P212: + dal_pixel_format = PIXEL_FORMAT_422BPP12; + break; + case SURFACE_PIXEL_FORMAT_VIDEO_422_YCrYCb: + case SURFACE_PIXEL_FORMAT_VIDEO_422_YCbYCr: + case SURFACE_PIXEL_FORMAT_VIDEO_422_CrYCbY: + case SURFACE_PIXEL_FORMAT_VIDEO_422_CbYCrY: + dal_pixel_format = PIXEL_FORMAT_422BPP8; + break; + case SURFACE_PIXEL_FORMAT_VIDEO_422_10bpc_YCrYCb: + case SURFACE_PIXEL_FORMAT_VIDEO_422_10bpc_YCbYCr: + case SURFACE_PIXEL_FORMAT_VIDEO_422_10bpc_CrYCbY: + case SURFACE_PIXEL_FORMAT_VIDEO_422_10bpc_CbYCrY: + dal_pixel_format = PIXEL_FORMAT_422BPP10; + break; + case SURFACE_PIXEL_FORMAT_VIDEO_422_12bpc_YCrYCb: + case SURFACE_PIXEL_FORMAT_VIDEO_422_12bpc_YCbYCr: + case SURFACE_PIXEL_FORMAT_VIDEO_422_12bpc_CrYCbY: + case SURFACE_PIXEL_FORMAT_VIDEO_422_12bpc_CbYCrY: + dal_pixel_format = PIXEL_FORMAT_422BPP12; + break; case SURFACE_PIXEL_FORMAT_GRPH_ARGB16161616: case SURFACE_PIXEL_FORMAT_GRPH_ABGR16161616: default: @@ -1516,6 +1553,15 @@ void resource_build_test_pattern_params(struct resource_context *res_ctx, } } +enum upsp_mode resource_is_upsp_required(enum surface_pixel_format format) +{ + if (format >= SURFACE_PIXEL_FORMAT_VIDEO_BEGIN && format <= SURFACE_PIXEL_FORMAT_VIDEO_420_10bpc_YCrCb) //420 Formats + return UPSP_HORIZONTAL_VERTICAL_UPSAMPLING; + if (format > SURFACE_PIXEL_FORMAT_VIDEO_420_10bpc_YCrCb && format < SURFACE_PIXEL_FORMAT_SUBSAMPLE_END) //422 Formats + return UPSP_HORIZONTAL_UPSAMPLING_ONLY; + return UPSP_BYPASS; +} + bool resource_build_scaling_params(struct pipe_ctx *pipe_ctx) { const struct dc_plane_state *plane_state = pipe_ctx->plane_state; @@ -1561,6 +1607,7 @@ bool resource_build_scaling_params(struct pipe_ctx *pipe_ctx) pipe_ctx->plane_res.scl_data.lb_params.depth = LB_PIXEL_DEPTH_30BPP; pipe_ctx->plane_res.scl_data.lb_params.alpha_en = plane_state->per_pixel_alpha; + pipe_ctx->plane_res.scl_data.upsp = resource_is_upsp_required(plane_state->format); // Convert pipe_ctx to respective input params for SPL translate_SPL_in_params_from_pipe_ctx(pipe_ctx, spl_in); diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_state.c b/drivers/gpu/drm/amd/display/dc/core/dc_state.c index b534b1a641af..666212cac105 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_state.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_state.c @@ -1155,3 +1155,15 @@ bool dc_state_is_subvp_in_use(struct dc_state *state) return false; } +bool dc_state_is_alt_in_use(const struct dc *dc, const struct dc_state *state) +{ + uint32_t i; + const struct pipe_ctx *pipe; + + for (i = 0; i < dc->res_pool->pipe_count; i++) { + pipe = &state->res_ctx.pipe_ctx[i]; + if (pipe->p_state_type == P_STATE_ALT) + return true; + } + return false; +} diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_stream.c b/drivers/gpu/drm/amd/display/dc/core/dc_stream.c index cdcf140bc1bb..ce5b9e82db8d 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_stream.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_stream.c @@ -405,6 +405,7 @@ bool dc_stream_program_cursor_attributes( { struct dc *dc; bool reset_idle_optimizations = false; + bool should_release_dmub_hw_control_lock = false; if (!stream) return false; @@ -413,6 +414,13 @@ bool dc_stream_program_cursor_attributes( if (dc_stream_set_cursor_attributes(stream, attributes)) { dc_z10_restore(dc); + if (dc->hwss.dmub_hw_control_lock) { + if (dc_state_is_alt_in_use(dc, dc->current_state) && + !dc_dmub_srv_is_cursor_offload_enabled(dc)) { + dc->hwss.dmub_hw_control_lock(dc, dc->current_state, true); + should_release_dmub_hw_control_lock = true; + } + } /* disable idle optimizations while updating cursor */ if (dc->idle_optimizations_allowed) { dc_allow_idle_optimizations(dc, false); @@ -425,6 +433,10 @@ bool dc_stream_program_cursor_attributes( if (reset_idle_optimizations && !dc->debug.disable_dmub_reallow_idle) dc_allow_idle_optimizations(dc, true); + if (dc->hwss.dmub_hw_control_lock) { + if (should_release_dmub_hw_control_lock) + dc->hwss.dmub_hw_control_lock(dc, dc->current_state, false); + } return true; } @@ -507,6 +519,7 @@ bool dc_stream_program_cursor_position( struct dc *dc; bool reset_idle_optimizations = false; const struct dc_cursor_position *old_position; + bool should_release_dmub_hw_control_lock = false; if (!stream) return false; @@ -517,6 +530,13 @@ bool dc_stream_program_cursor_position( if (dc_stream_set_cursor_position(stream, position)) { dc_z10_restore(dc); + if (dc->hwss.dmub_hw_control_lock) { + if (dc_state_is_alt_in_use(dc, dc->current_state) && + !dc_dmub_srv_is_cursor_offload_enabled(dc)) { + dc->hwss.dmub_hw_control_lock(dc, dc->current_state, true); + should_release_dmub_hw_control_lock = true; + } + } /* disable idle optimizations if enabling cursor */ if (dc->idle_optimizations_allowed && (!old_position->enable || dc->debug.exit_idle_opt_for_cursor_updates) && @@ -567,6 +587,10 @@ bool dc_stream_program_cursor_position( } } + if (dc->hwss.dmub_hw_control_lock) { + if (should_release_dmub_hw_control_lock) + dc->hwss.dmub_hw_control_lock(dc, dc->current_state, false); + } return true; } diff --git a/drivers/gpu/drm/amd/display/dc/dc.h b/drivers/gpu/drm/amd/display/dc/dc.h index 63c0dec85697..cc029af0cef2 100644 --- a/drivers/gpu/drm/amd/display/dc/dc.h +++ b/drivers/gpu/drm/amd/display/dc/dc.h @@ -174,6 +174,13 @@ struct dc_plane_cap { uint32_t fp16 : 1; uint32_t p010 : 1; uint32_t ayuv : 1; + uint32_t yuy2 : 1; // Packed 422 8bpc + uint32_t y210 : 1; // Packed 422 10bpc + uint32_t y212 : 1; // Packed 422 12bpc + uint32_t p208 : 1; // Planar 422 8bpc + uint32_t p210 : 1; // Planar 422 10bpc + uint32_t p212 : 1; // Planar 422 12bpc + /* Not all caps will be used/supported */ } pixel_format_support; // max upscaling factor x1000 // upscaling factors are always >= 1 @@ -240,6 +247,7 @@ struct rom_curve_caps { * @ogam_ram: programmable out/blend gamma LUT * @ocsc: output color space conversion * @dgam_rom_for_yuv: pre-defined degamma LUT for YUV planes + * @upsp_pre_scaler: Ability to upsample 420/422 before scaling * @dgam_rom_caps: pre-definied curve caps for degamma 1D LUT * @ogam_rom_caps: pre-definied curve caps for regamma 1D LUT * @@ -256,6 +264,7 @@ struct dpp_color_caps { uint16_t ogam_ram : 1; uint16_t ocsc : 1; uint16_t dgam_rom_for_yuv : 1; + uint16_t upsp_pre_scaler : 1; struct rom_curve_caps dgam_rom_caps; struct rom_curve_caps ogam_rom_caps; }; @@ -617,6 +626,7 @@ struct dc_config { bool unify_link_enc_assignment; bool enable_cursor_offload; bool dp_connector_no_native_i2c; + unsigned int link_index_with_no_ddc; bool frame_update_cmd_version2; struct spl_sharpness_range dcn_sharpness_range; struct spl_sharpness_range dcn_override_sharpness_range; @@ -785,6 +795,7 @@ struct dc_clocks { */ bool fw_based_mclk_switching; bool fw_based_mclk_switching_shut_down; + bool alt_ch_pstate_switch; int prev_num_ways; enum dtm_pstate dtm_level; int max_supported_dppclk_khz; @@ -795,6 +806,18 @@ struct dc_clocks { int idle_fclk_khz; int subvp_prefetch_dramclk_khz; int subvp_prefetch_fclk_khz; + /* deprecated: use _KBps variants — will be removed after DML update */ + unsigned int utm_urgent_bandwidth_lb_Kbps; + unsigned int utm_nominal_bandwidth_lb_Kbps; + unsigned int utm_urgent_bandwidth_lb_KBps; + unsigned int utm_nominal_bandwidth_lb_KBps; + unsigned int utm_latency_ub_index; + unsigned int utm_lsdma_bandwidth_lb_KBps; + unsigned int utm_nominal_max_latency_ub_ns; + unsigned int utm_nominal_avg_latency_ub_ns; + /* deprecated: use _KBps variant — will be removed after DML update */ + unsigned int required_avg_active_bandwidth_Kbps; + unsigned int required_avg_active_bandwidth_KBps; /* Stutter efficiency is technically not clock values * but stored here so the values are part of the update_clocks call similar to num_ways @@ -1739,7 +1762,7 @@ struct dc_plane_state { bool adaptive_sharpness_en; int adaptive_sharpness_policy; unsigned int sharpness_level; - enum linear_light_scaling linear_light_scaling; + enum dc_scaling_linearity scaling_linearity; unsigned int sdr_white_level_nits; struct cm_hist_control cm_hist_control; struct spl_sharpness_range sharpness_range; @@ -1763,6 +1786,7 @@ struct dc_plane_info { bool input_csc_enabled; unsigned int layer_index; enum chroma_cositing cositing; + enum dc_scaling_linearity scaling_linearity; }; #include "dc_stream.h" diff --git a/drivers/gpu/drm/amd/display/dc/dc_dmub_srv.c b/drivers/gpu/drm/amd/display/dc/dc_dmub_srv.c index 80a21d7cae90..47fa3d4265e0 100644 --- a/drivers/gpu/drm/amd/display/dc/dc_dmub_srv.c +++ b/drivers/gpu/drm/amd/display/dc/dc_dmub_srv.c @@ -2431,3 +2431,47 @@ void dc_dmub_srv_log_preos_dmcub_info(struct dc_dmub_srv *dc_dmub_srv) DC_LOG_DEBUG("fb_offset : 0x%016llx", dmub->preos_info.fb_offset); } } + +bool dc_dmub_srv_ihc_set_dig_hdcp_interrupt_dest( + struct dc_dmub_srv *dc_dmub_srv, + uint8_t dig_id, + bool to_dmu) +{ + union dmub_rb_cmd cmd; + + if (!dc_dmub_srv || !dc_dmub_srv->dmub) + return false; + + memset(&cmd, 0, sizeof(cmd)); + + cmd.ihc.header.type = DMUB_CMD__IHC; + cmd.ihc.header.sub_type = DMUB_CMD__IHC_SET_DIG_HDCP_INTERRUPT_DEST; + cmd.ihc.header.payload_bytes = sizeof(cmd.ihc.data); + + cmd.ihc.data.dig_id = dig_id; + cmd.ihc.data.to_dmu = to_dmu ? 1 : 0; + + dc_wake_and_execute_dmub_cmd(dc_dmub_srv->ctx, &cmd, DM_DMUB_WAIT_TYPE_WAIT); + + return true; +} + +void dc_dmub_srv_get_fams2_debug_meta(struct dc_dmub_srv *dc_dmub_srv) +{ + union dmub_rb_cmd cmd; + + memset(&cmd, 0, sizeof(cmd)); + + cmd.ib_fams2_debug_meta.header.type = DMUB_CMD__FW_ASSISTED_MCLK_SWITCH; + cmd.ib_fams2_debug_meta.header.sub_type = DMUB_CMD__FAMS2_IB_DEBUG_META; + + cmd.ib_fams2_debug_meta.ib_data.src.quad_part = dc_dmub_srv->dmub->ib_mem_gart.gpu_addr; + cmd.ib_fams2_debug_meta.ib_data.size = dc_dmub_srv->dmub->ib_mem_gart.size > 0xFFFF ? + 0xFFFF : (uint16_t)dc_dmub_srv->dmub->ib_mem_gart.size; + + /* flush any existing writes to the buffer to prevent conflicts */ + dmub_srv_flush_buffer_mem(dc_dmub_srv->dmub, &dc_dmub_srv->dmub->ib_mem_gart); + + dm_execute_dmub_cmd_list(dc_dmub_srv->ctx, 1, &cmd, DM_DMUB_WAIT_TYPE_WAIT); + +} diff --git a/drivers/gpu/drm/amd/display/dc/dc_dmub_srv.h b/drivers/gpu/drm/amd/display/dc/dc_dmub_srv.h index 8bdaac0b0f98..6d15ed77c17d 100644 --- a/drivers/gpu/drm/amd/display/dc/dc_dmub_srv.h +++ b/drivers/gpu/drm/amd/display/dc/dc_dmub_srv.h @@ -401,4 +401,27 @@ void dc_dmub_srv_release_hw(const struct dc *dc); * @dc - pointer to DC object */ void dc_dmub_srv_log_preos_dmcub_info(struct dc_dmub_srv *dc_dmub_srv); + +/** + * dc_dmub_srv_ihc_set_dig_hdcp_interrupt_dest() - Configure IHC interrupt destination. + * @dc_dmub_srv: DMUB service handle + * @dig_id: DIG engine ID (0-3) + * @to_dmu: Route interrupt to DMU (true) or not (false) + * + * Sends command to DMUB firmware to configure IHC interrupt routing + * for HDCP I2C transfer requests. + * + * Return: true on success, false on failure + */ +bool dc_dmub_srv_ihc_set_dig_hdcp_interrupt_dest( + struct dc_dmub_srv *dc_dmub_srv, + uint8_t dig_id, + bool to_dmu); + +/** + * dc_dmub_srv_get_fams2_debug_meta() - Queries for FAMS2 debug metadata from DMUB and logs it. + * + * @dc_dmub_srv - pointer to DMUB service object + */ +void dc_dmub_srv_get_fams2_debug_meta(struct dc_dmub_srv *dc_dmub_srv); #endif /* _DMUB_DC_SRV_H_ */ diff --git a/drivers/gpu/drm/amd/display/dc/dc_helper.c b/drivers/gpu/drm/amd/display/dc/dc_helper.c index cc7fea613d9e..c1d9c3ef0a4b 100644 --- a/drivers/gpu/drm/amd/display/dc/dc_helper.c +++ b/drivers/gpu/drm/amd/display/dc/dc_helper.c @@ -530,6 +530,8 @@ char *dce_version_to_string(const int version) return "DCN 4.2"; case DCN_VERSION_4_2B: return "DCN 4.2B"; + case DCN_VERSION_6_0: + return "DCN 6.0"; default: return "Unknown"; } diff --git a/drivers/gpu/drm/amd/display/dc/dc_hw_types.h b/drivers/gpu/drm/amd/display/dc/dc_hw_types.h index a0272ee92285..aeac5a45e13b 100644 --- a/drivers/gpu/drm/amd/display/dc/dc_hw_types.h +++ b/drivers/gpu/drm/amd/display/dc/dc_hw_types.h @@ -205,9 +205,32 @@ enum surface_pixel_format { SURFACE_PIXEL_FORMAT_VIDEO_420_YCrCb, SURFACE_PIXEL_FORMAT_VIDEO_420_10bpc_YCbCr, SURFACE_PIXEL_FORMAT_VIDEO_420_10bpc_YCrCb, + /* Planar 422 Formats*/ + SURFACE_PIXEL_FORMAT_VIDEO_422_CrCb_P208, // 8 bpc + SURFACE_PIXEL_FORMAT_VIDEO_422_CbCr_P208, // 8 bpc + SURFACE_PIXEL_FORMAT_VIDEO_422_CrCb_P210, // 10 bpc + SURFACE_PIXEL_FORMAT_VIDEO_422_CbCr_P210, // 10 bpc + SURFACE_PIXEL_FORMAT_VIDEO_422_CrCb_P212, // 12 bpc + SURFACE_PIXEL_FORMAT_VIDEO_422_CbCr_P212, // 12 bpc SURFACE_PIXEL_FORMAT_SUBSAMPLE_END, SURFACE_PIXEL_FORMAT_VIDEO_ACrYCb2101010 = SURFACE_PIXEL_FORMAT_SUBSAMPLE_END, + /* packed 422 formats, they should reside here as the necessity for programming chroma parameters are determined wrt SURFACE_PIXEL_FORMAT_SUBSAMPLE_END*/ + /* Packed 422 Format, 8bpc*/ + SURFACE_PIXEL_FORMAT_VIDEO_422_YCrYCb, + SURFACE_PIXEL_FORMAT_VIDEO_422_YCbYCr, + SURFACE_PIXEL_FORMAT_VIDEO_422_CrYCbY, + SURFACE_PIXEL_FORMAT_VIDEO_422_CbYCrY, + /* Packed 422 Format, 10bpc*/ + SURFACE_PIXEL_FORMAT_VIDEO_422_10bpc_YCrYCb, + SURFACE_PIXEL_FORMAT_VIDEO_422_10bpc_YCbYCr, + SURFACE_PIXEL_FORMAT_VIDEO_422_10bpc_CrYCbY, + SURFACE_PIXEL_FORMAT_VIDEO_422_10bpc_CbYCrY, + /* Packed 422 Format, 12bpc*/ + SURFACE_PIXEL_FORMAT_VIDEO_422_12bpc_YCrYCb, + SURFACE_PIXEL_FORMAT_VIDEO_422_12bpc_YCbYCr, + SURFACE_PIXEL_FORMAT_VIDEO_422_12bpc_CrYCbY, + SURFACE_PIXEL_FORMAT_VIDEO_422_12bpc_CbYCrY, SURFACE_PIXEL_FORMAT_VIDEO_CrYCbA1010102, SURFACE_PIXEL_FORMAT_VIDEO_AYCrCb8888, SURFACE_PIXEL_FORMAT_INVALID @@ -230,13 +253,19 @@ enum dc_pixel_format { /*video*/ PIXEL_FORMAT_420BPP8, PIXEL_FORMAT_420BPP10, + // Align with SPL formats + PIXEL_FORMAT_422BPP8, + PIXEL_FORMAT_422BPP10, + PIXEL_FORMAT_422BPP12, + PIXEL_FORMAT_444BPP8, + PIXEL_FORMAT_444BPP10, /*end of pixel format definition*/ PIXEL_FORMAT_INVALID, PIXEL_FORMAT_GRPH_BEGIN = PIXEL_FORMAT_INDEX8, PIXEL_FORMAT_GRPH_END = PIXEL_FORMAT_FP16, PIXEL_FORMAT_VIDEO_BEGIN = PIXEL_FORMAT_420BPP8, - PIXEL_FORMAT_VIDEO_END = PIXEL_FORMAT_420BPP10, + PIXEL_FORMAT_VIDEO_END = PIXEL_FORMAT_444BPP10, PIXEL_FORMAT_UNKNOWN }; @@ -651,6 +680,7 @@ struct dc_cursor_attributes { enum dc_rotation_angle rotation_angle; union dc_cursor_attribute_flags attribute_flags; + bool force_cursor_to_disp_pref; }; struct dpp_cursor_attributes { @@ -1249,5 +1279,26 @@ struct cm_hist { uint32_t ch2[256]; uint32_t ch3[256]; }; + +enum pregam_mode { + PREGAM_BYPASS = 0, + PREGAM_DEGAM, + PREGAM_REGAM +}; + +enum degam_lut { + DEGAM_SRGB = 0, + DEGAM_GAMMA_22, + DEGAM_GAMMA_24, + DEGAM_GAMMA_26, + DEGAM_BT2020, + DEGAM_BT2100PQ, + DEGAM_BT2100HLG +}; + +enum regam_lut { + REGAM_20 = 0, + REGAM_24 +}; #endif /* DC_HW_TYPES_H */ diff --git a/drivers/gpu/drm/amd/display/dc/dc_spl_translate.c b/drivers/gpu/drm/amd/display/dc/dc_spl_translate.c index bc55f10fba7c..76c0d62031b6 100644 --- a/drivers/gpu/drm/amd/display/dc/dc_spl_translate.c +++ b/drivers/gpu/drm/amd/display/dc/dc_spl_translate.c @@ -16,6 +16,9 @@ static struct spl_callbacks dcn32_spl_callbacks = { static struct spl_callbacks dcn401_spl_callbacks = { .spl_calc_lb_num_partitions = dscl401_spl_calc_lb_num_partitions, }; +static struct spl_callbacks dcn50_spl_callbacks = { + .spl_calc_lb_num_partitions = dscl401_spl_calc_lb_num_partitions, +}; static void populate_splrect_from_rect(struct spl_rect *spl_rect, const struct rect *rect) { spl_rect->x = rect->x; @@ -71,6 +74,23 @@ static void populate_splformat_from_format(enum spl_pixel_format *spl_pixel_form else *spl_pixel_format = SPL_PIXEL_FORMAT_INVALID; } +static void set_linear_light_scaling_preference(const struct dc_plane_state *plane_state, struct spl_in *spl_in) +{ + if (plane_state != NULL) { + switch (plane_state->scaling_linearity) { + case DC_SCALING_LINEARITY_LINEAR: + spl_in->lls_pref = LLS_PREF_YES; + break; + case DC_SCALING_LINEARITY_SOURCE: + spl_in->lls_pref = LLS_PREF_NO; + break; + default: + spl_in->lls_pref = LLS_PREF_DONT_CARE; + break; + } + } else + spl_in->lls_pref = LLS_PREF_DONT_CARE; +} /// @brief Translate SPL input parameters from pipe context /// @param pipe_ctx /// @param spl_in @@ -94,6 +114,9 @@ void translate_SPL_in_params_from_pipe_ctx(struct pipe_ctx *pipe_ctx, struct spl case DCN_VERSION_4_2B: spl_in->callbacks = dcn401_spl_callbacks; break; + case DCN_VERSION_6_0: + spl_in->callbacks = dcn50_spl_callbacks; + break; default: spl_in->callbacks = dcn2_spl_callbacks; } @@ -189,7 +212,14 @@ void translate_SPL_in_params_from_pipe_ctx(struct pipe_ctx *pipe_ctx, struct spl if (pipe_ctx->stream->ctx->dc->debug.force_lls > 0) spl_in->lls_pref = pipe_ctx->stream->ctx->dc->debug.force_lls; else - spl_in->lls_pref = plane_state->linear_light_scaling; + if ((plane_state->ctx->dce_version == DCN_VERSION_4_01) || + (plane_state->ctx->dce_version == DCN_VERSION_4_2) || + (plane_state->ctx->dce_version == DCN_VERSION_4_2B)) + spl_in->lls_pref = LLS_PREF_DONT_CARE; + else + set_linear_light_scaling_preference(plane_state, spl_in); + /* Translate upsampling mode*/ + spl_in->upsp_mode = pipe_ctx->plane_res.scl_data.upsp; /* Translate chroma subsampling offset ( cositing ) */ if (pipe_ctx->stream->ctx->dc->debug.force_cositing) spl_in->basic_in.cositing = pipe_ctx->stream->ctx->dc->debug.force_cositing - 1; diff --git a/drivers/gpu/drm/amd/display/dc/dc_state_priv.h b/drivers/gpu/drm/amd/display/dc/dc_state_priv.h index 1d9bae56ff6a..191bb431991f 100644 --- a/drivers/gpu/drm/amd/display/dc/dc_state_priv.h +++ b/drivers/gpu/drm/amd/display/dc/dc_state_priv.h @@ -125,4 +125,5 @@ bool dc_state_can_clear_stream_cursor_subvp_limit(const struct dc_stream_state * bool dc_state_is_subvp_in_use(struct dc_state *state); +bool dc_state_is_alt_in_use(const struct dc *dc, const struct dc_state *state); #endif /* _DC_STATE_PRIV_H_ */ diff --git a/drivers/gpu/drm/amd/display/dc/dc_stream.h b/drivers/gpu/drm/amd/display/dc/dc_stream.h index 4530f294f1c2..934ae381e730 100644 --- a/drivers/gpu/drm/amd/display/dc/dc_stream.h +++ b/drivers/gpu/drm/amd/display/dc/dc_stream.h @@ -329,6 +329,9 @@ struct dc_stream_state { enum dc_drr_trigger_mode drr_trigger_mode; + + enum dc_blending_linearity blending_linearity; + struct dc_update_scratch_space *update_scratch; bool firmware_controlled_hdr_info_packet; }; @@ -380,6 +383,8 @@ struct dc_stream_update { bool *scaler_sharpener_update; bool *sharpening_required; + enum dc_blending_linearity *blending_linearity; + enum dc_drr_trigger_mode *drr_trigger_mode; }; diff --git a/drivers/gpu/drm/amd/display/dc/dc_types.h b/drivers/gpu/drm/amd/display/dc/dc_types.h index 3edeb94fba23..b14d882e08d4 100644 --- a/drivers/gpu/drm/amd/display/dc/dc_types.h +++ b/drivers/gpu/drm/amd/display/dc/dc_types.h @@ -389,6 +389,16 @@ struct dc_csc_adjustments { struct fixed31_32 hue; }; +enum dc_scaling_linearity { + DC_SCALING_LINEARITY_LINEAR, + DC_SCALING_LINEARITY_SOURCE, +}; + +enum dc_blending_linearity { + DC_BLENDING_LINEARITY_LINEAR, + DC_BLENDING_LINEARITY_SOURCE, +}; + /* Scaling format */ enum scaling_transformation { SCALING_TRANSFORMATION_UNINITIALIZED, diff --git a/drivers/gpu/drm/amd/display/dc/dccg/dcn20/dcn20_dccg.h b/drivers/gpu/drm/amd/display/dc/dccg/dcn20/dcn20_dccg.h index 088cf305a772..cecfb0a68030 100644 --- a/drivers/gpu/drm/amd/display/dc/dccg/dcn20/dcn20_dccg.h +++ b/drivers/gpu/drm/amd/display/dc/dccg/dcn20/dcn20_dccg.h @@ -377,6 +377,13 @@ type OTG3_DROP_PIXEL;\ type RESYNC_FIFO_LEVEL_ADJUST_EN; +#define DCCG60_REG_FIELD_LIST(type) \ + type OTG_ADD_DROP_PIXEL_DONE;\ + type DSCCLK0_SRC_SEL;\ + type DSCCLK1_SRC_SEL;\ + type DSCCLK2_SRC_SEL;\ + type DSCCLK3_SRC_SEL; + struct dccg_shift { DCCG_REG_FIELD_LIST(uint8_t) DCCG3_REG_FIELD_LIST(uint8_t) @@ -386,6 +393,7 @@ struct dccg_shift { DCCG35_REG_FIELD_LIST(uint8_t) DCCG401_REG_FIELD_LIST(uint8_t) DCCG42_REG_FIELD_LIST(uint8_t) + DCCG60_REG_FIELD_LIST(uint8_t) }; struct dccg_mask { @@ -397,6 +405,7 @@ struct dccg_mask { DCCG35_REG_FIELD_LIST(uint32_t) DCCG401_REG_FIELD_LIST(uint32_t) DCCG42_REG_FIELD_LIST(uint32_t) + DCCG60_REG_FIELD_LIST(uint32_t) }; #define DCCG_REG_VARIABLE_LIST \ @@ -511,6 +520,7 @@ struct dccg_mask { struct dccg_registers { DCCG_REG_VARIABLE_LIST; uint32_t OTG_ADD_DROP_PIXEL_CNTL; + uint32_t DSCCLK_SRC_SEL; }; struct dcn_dccg { diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_clock_source.c b/drivers/gpu/drm/amd/display/dc/dce/dce_clock_source.c index ecb8493ec523..e52fb7248a88 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_clock_source.c +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_clock_source.c @@ -1496,6 +1496,13 @@ static const struct clock_source_funcs dcn401_clk_src_funcs = { .get_dp_dto_frequency_100hz = dcn401_get_dp_dto_frequency_100hz }; +static const struct clock_source_funcs dcn50_clk_src_funcs = { + .cs_power_down = dce110_clock_source_power_down, + .program_pix_clk = dcn401_program_pix_clk, + .get_pix_clk_dividers = dcn3_get_pix_clk_dividers, + .get_dp_dto_frequency_100hz = dcn401_get_dp_dto_frequency_100hz +}; + /*****************************************/ /* Constructor */ /*****************************************/ @@ -1924,6 +1931,23 @@ bool dcn401_clk_src_construct( return ret; } + +bool dcn50_clk_src_construct( + struct dce110_clk_src *clk_src, + struct dc_context *ctx, + struct dc_bios *bios, + enum clock_source_id id, + const struct dce110_clk_src_regs *regs, + const struct dce110_clk_src_shift *cs_shift, + const struct dce110_clk_src_mask *cs_mask) +{ + bool ret = dce112_clk_src_construct(clk_src, ctx, bios, id, regs, cs_shift, cs_mask); + + clk_src->base.funcs = &dcn50_clk_src_funcs; + + return ret; +} + bool dcn301_clk_src_construct( struct dce110_clk_src *clk_src, struct dc_context *ctx, diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_clock_source.h b/drivers/gpu/drm/amd/display/dc/dce/dce_clock_source.h index 55c96b4b7765..6eca94e99d96 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_clock_source.h +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_clock_source.h @@ -339,6 +339,15 @@ bool dcn401_clk_src_construct( const struct dce110_clk_src_regs *regs, const struct dce110_clk_src_shift *cs_shift, const struct dce110_clk_src_mask *cs_mask); +bool dcn50_clk_src_construct( + struct dce110_clk_src *clk_src, + struct dc_context *ctx, + struct dc_bios *bios, + enum clock_source_id id, + const struct dce110_clk_src_regs *regs, + const struct dce110_clk_src_shift *cs_shift, + const struct dce110_clk_src_mask *cs_mask); + /* this table is use to find *1.001 and /1.001 pixel rates from non-precise pixel rate */ struct pixel_rate_range_table_entry { unsigned int range_min_khz; diff --git a/drivers/gpu/drm/amd/display/dc/dio/dcn10/dcn10_link_encoder.h b/drivers/gpu/drm/amd/display/dc/dio/dcn10/dcn10_link_encoder.h index eedbd5d2756e..a99879c58027 100644 --- a/drivers/gpu/drm/amd/display/dc/dio/dcn10/dcn10_link_encoder.h +++ b/drivers/gpu/drm/amd/display/dc/dio/dcn10/dcn10_link_encoder.h @@ -75,12 +75,14 @@ struct dcn10_link_enc_aux_registers { uint32_t AUX_DPHY_RX_CONTROL0; uint32_t AUX_DPHY_TX_CONTROL; uint32_t AUX_DPHY_RX_CONTROL1; + uint32_t DC_GPIO_DDC; }; struct dcn10_link_enc_hpd_registers { uint32_t DC_HPD_CONTROL; uint32_t DC_HPD_INT_STATUS; uint32_t DC_HPD_TOGGLE_FILT_CNTL; + uint32_t HPD_CTRL; }; struct dcn10_link_enc_registers { @@ -171,6 +173,8 @@ struct dcn10_link_enc_registers { uint32_t DIO_LINKF_CNTL; uint32_t DIO_CLK_CNTL; uint32_t DIG_BE_CLK_CNTL; + uint32_t HDCP_I2C_CONTROL_0; + uint32_t HDCP_INT_CONTROL; }; #define LE_SF(reg_name, field_name, post_fix)\ @@ -508,12 +512,23 @@ struct dcn10_link_enc_registers { type SYMCLKF_G_HDCP_GATE_DIS;\ type SYMCLKG_G_HDCP_GATE_DIS +#define DCN60_LINK_ENCODER_REG_FIELD_LIST(type) \ + type HDCP_I2C_DISABLE;\ + type HDCP_I2C_DDC_SELECT;\ + type HDCP_I2C_XFER_REQ_MASK;\ + type AUX_PAD1_MODE;\ + type HPD1_Y_POL_INVERT;\ + type HPD2_Y_POL_INVERT;\ + type HPD3_Y_POL_INVERT;\ + type HPD4_Y_POL_INVERT + struct dcn10_link_enc_shift { DCN_LINK_ENCODER_REG_FIELD_LIST(uint8_t); DCN20_LINK_ENCODER_REG_FIELD_LIST(uint8_t); DCN30_LINK_ENCODER_REG_FIELD_LIST(uint8_t); DCN31_LINK_ENCODER_REG_FIELD_LIST(uint8_t); DCN35_LINK_ENCODER_REG_FIELD_LIST(uint8_t); + DCN60_LINK_ENCODER_REG_FIELD_LIST(uint8_t); }; struct dcn10_link_enc_mask { @@ -522,6 +537,7 @@ struct dcn10_link_enc_mask { DCN30_LINK_ENCODER_REG_FIELD_LIST(uint32_t); DCN31_LINK_ENCODER_REG_FIELD_LIST(uint32_t); DCN35_LINK_ENCODER_REG_FIELD_LIST(uint32_t); + DCN60_LINK_ENCODER_REG_FIELD_LIST(uint32_t); }; struct dcn10_link_encoder { diff --git a/drivers/gpu/drm/amd/display/dc/dio/dcn401/dcn401_dio_link_encoder.c b/drivers/gpu/drm/amd/display/dc/dio/dcn401/dcn401_dio_link_encoder.c index 2aaf06d48771..dad4ef565168 100644 --- a/drivers/gpu/drm/amd/display/dc/dio/dcn401/dcn401_dio_link_encoder.c +++ b/drivers/gpu/drm/amd/display/dc/dio/dcn401/dcn401_dio_link_encoder.c @@ -384,6 +384,20 @@ enum signal_type dcn401_get_dig_mode( } } +void dcn401_setup_ri_pj_check_in_sw_or_hw_mode( + struct link_encoder *enc, + unsigned char aux_or_ddc_instance, + bool enable_sw_mode) +{ + struct dcn10_link_encoder *enc10 = TO_DCN10_LINK_ENC(enc); + + REG_UPDATE_2(HDCP_I2C_CONTROL_0, + HDCP_I2C_DISABLE, enable_sw_mode, + HDCP_I2C_DDC_SELECT, aux_or_ddc_instance); + + REG_UPDATE(HDCP_INT_CONTROL, HDCP_I2C_XFER_REQ_MASK, enable_sw_mode); +} + static const struct link_encoder_funcs dcn401_link_enc_funcs = { .read_state = link_enc2_read_state, .validate_output_with_stream = @@ -423,6 +437,7 @@ static const struct link_encoder_funcs dcn401_link_enc_funcs = { .get_txffe = dpcs401_get_txffe, .set_txffe = dpcs401_set_txffe, .set_dio_phy_mux = dcn31_link_encoder_set_dio_phy_mux, + .setup_ri_pj_check_in_sw_or_hw_mode = dcn401_setup_ri_pj_check_in_sw_or_hw_mode, .get_hpd_state = dcn10_get_hpd_state, .program_hpd_filter = dcn10_program_hpd_filter, }; diff --git a/drivers/gpu/drm/amd/display/dc/dio/dcn401/dcn401_dio_link_encoder.h b/drivers/gpu/drm/amd/display/dc/dio/dcn401/dcn401_dio_link_encoder.h index a40c479fada8..62f8f9098b53 100644 --- a/drivers/gpu/drm/amd/display/dc/dio/dcn401/dcn401_dio_link_encoder.h +++ b/drivers/gpu/drm/amd/display/dc/dio/dcn401/dcn401_dio_link_encoder.h @@ -104,6 +104,11 @@ LE_SF(DP_AUX0_AUX_DPHY_RX_CONTROL1, AUX_RX_TIMEOUT_LEN, mask_sh),\ LE_SF(DP_AUX0_AUX_DPHY_RX_CONTROL1, AUX_RX_TIMEOUT_LEN_MUL, mask_sh) +#define LINK_ENCODER_MASK_SH_LIST_DCN60_ON_DCN401(mask_sh) \ + LE_SF(DIG0_HDCP_I2C_CONTROL_0, HDCP_I2C_DISABLE, mask_sh),\ + LE_SF(DIG0_HDCP_I2C_CONTROL_0, HDCP_I2C_DDC_SELECT, mask_sh),\ + LE_SF(DIG0_HDCP_INT_CONTROL, HDCP_I2C_XFER_REQ_MASK, mask_sh) + void dcn401_link_encoder_construct( struct dcn20_link_encoder *enc20, const struct encoder_init_data *init_data, @@ -147,4 +152,9 @@ enum signal_type dcn401_get_dig_mode( bool dcn401_is_dig_enabled(struct link_encoder *enc); enum signal_type dcn401_get_dig_mode(struct link_encoder *enc); + +void dcn401_setup_ri_pj_check_in_sw_or_hw_mode( + struct link_encoder *enc, + unsigned char aux_or_ddc_instance, + bool enable_sw_mode); #endif /* __DC_LINK_ENCODER__DCN401_H__ */ diff --git a/drivers/gpu/drm/amd/display/dc/dm_helpers.h b/drivers/gpu/drm/amd/display/dc/dm_helpers.h index f5252931ce35..c887fdcba049 100644 --- a/drivers/gpu/drm/amd/display/dc/dm_helpers.h +++ b/drivers/gpu/drm/amd/display/dc/dm_helpers.h @@ -203,6 +203,14 @@ void dm_helpers_mccs_vcp_set( #define EXPORT_IF_KUNIT(symbol) #endif +bool dm_helpers_submit_i2c_over_aux( + struct ddc_service *ddc, + uint32_t address, + uint8_t offset, + uint8_t *cmdBuffer, + uint32_t len, + bool read); + bool dm_helpers_dp_handle_test_pattern_request( struct dc_context *ctx, const struct dc_link *link, diff --git a/drivers/gpu/drm/amd/display/dc/dml2_0/dml21/dml21_translation_helper.c b/drivers/gpu/drm/amd/display/dc/dml2_0/dml21/dml21_translation_helper.c index 47164fa150d9..1b0d55e2d7b0 100644 --- a/drivers/gpu/drm/amd/display/dc/dml2_0/dml21/dml21_translation_helper.c +++ b/drivers/gpu/drm/amd/display/dc/dml2_0/dml21/dml21_translation_helper.c @@ -40,10 +40,10 @@ static void dml21_populate_pmo_options(struct dml2_pmo_options *pmo_options, pmo_options->force_mandatory_uclk_pstate_support = config->pmo.force_mandatory_uclk_pstate_support; } -static enum dml2_project_id dml21_dcn_revision_to_dml2_project_id(enum dce_version dcn_version) +static enum dml2_project_id dml21_dcn_revision_to_dml2_project_id(const struct dc *in_dc) { enum dml2_project_id project_id; - switch (dcn_version) { + switch (in_dc->ctx->dce_version) { case DCN_VERSION_4_01: project_id = dml2_project_dcn4x_stage2_auto_drr_svp; break; @@ -51,6 +51,9 @@ static enum dml2_project_id dml21_dcn_revision_to_dml2_project_id(enum dce_versi case DCN_VERSION_4_2B: project_id = dml2_project_dcn42; break; + case DCN_VERSION_6_0: + project_id = dml2_project_dcn6x_soc_var_a; + break; default: project_id = dml2_project_invalid; DC_ERR("unsupported dcn version for DML21!"); @@ -64,7 +67,7 @@ void dml21_populate_dml_init_params(struct dml2_initialize_instance_in_out *dml_ const struct dml2_configuration_options *config, const struct dc *in_dc) { - dml_init->options.project_id = dml21_dcn_revision_to_dml2_project_id(in_dc->ctx->dce_version); + dml_init->options.project_id = dml21_dcn_revision_to_dml2_project_id(in_dc); if (config->use_native_soc_bb_construction) { in_dc->soc_and_ip_translator->translator_funcs->get_soc_bb(&dml_init->soc_bb, in_dc, config); @@ -75,6 +78,9 @@ void dml21_populate_dml_init_params(struct dml2_initialize_instance_in_out *dml_ } dml21_populate_pmo_options(&dml_init->options.pmo_options, in_dc, config); + + if (in_dc->clk_mgr && in_dc->clk_mgr->bw_params) + dml_init->overrides.explicit_qos_model = in_dc->clk_mgr->bw_params->utm_qos_model; } static unsigned int calc_max_hardware_v_total(const struct dc_stream_state *stream) @@ -528,7 +534,6 @@ static void populate_dml21_surface_config_from_plane_state( switch (plane_state->tiling_info.gfxversion) { case DcGfxVersion7: case DcGfxVersion8: - break; case DcGfxVersion9: case DcGfxVersion10: case DcGfxVersion11: @@ -606,6 +611,36 @@ static void populate_dml21_plane_config_from_plane_state(struct dml2_context *dm case SURFACE_PIXEL_FORMAT_GRPH_RGBE_ALPHA: plane->pixel_format = dml2_rgbe_alpha; break; + case SURFACE_PIXEL_FORMAT_VIDEO_422_CrCb_P208: + case SURFACE_PIXEL_FORMAT_VIDEO_422_CbCr_P208: + plane->pixel_format = dml2_422_planar_8; + break; + case SURFACE_PIXEL_FORMAT_VIDEO_422_CrCb_P210: + case SURFACE_PIXEL_FORMAT_VIDEO_422_CbCr_P210: + plane->pixel_format = dml2_422_planar_10; + break; + case SURFACE_PIXEL_FORMAT_VIDEO_422_CrCb_P212: + case SURFACE_PIXEL_FORMAT_VIDEO_422_CbCr_P212: + plane->pixel_format = dml2_422_planar_12; + break; + case SURFACE_PIXEL_FORMAT_VIDEO_422_YCrYCb: + case SURFACE_PIXEL_FORMAT_VIDEO_422_YCbYCr: + case SURFACE_PIXEL_FORMAT_VIDEO_422_CrYCbY: + case SURFACE_PIXEL_FORMAT_VIDEO_422_CbYCrY: + plane->pixel_format = dml2_422_packed_8; + break; + case SURFACE_PIXEL_FORMAT_VIDEO_422_10bpc_YCrYCb: + case SURFACE_PIXEL_FORMAT_VIDEO_422_10bpc_YCbYCr: + case SURFACE_PIXEL_FORMAT_VIDEO_422_10bpc_CrYCbY: + case SURFACE_PIXEL_FORMAT_VIDEO_422_10bpc_CbYCrY: + plane->pixel_format = dml2_422_packed_10; + break; + case SURFACE_PIXEL_FORMAT_VIDEO_422_12bpc_YCrYCb: + case SURFACE_PIXEL_FORMAT_VIDEO_422_12bpc_YCbYCr: + case SURFACE_PIXEL_FORMAT_VIDEO_422_12bpc_CrYCbY: + case SURFACE_PIXEL_FORMAT_VIDEO_422_12bpc_CbYCrY: + plane->pixel_format = dml2_422_packed_12; + break; default: plane->pixel_format = dml2_444_32; break; @@ -640,6 +675,8 @@ static void populate_dml21_plane_config_from_plane_state(struct dml2_context *dm plane->composition.scaler_info.enabled = true; } + plane->composition.scaler_info.upsp_enabled = (scaler_data->upsp != UPSP_BYPASS); + /* always_scale is only used for debug purposes not used in production but has to be * maintained for certain complainces. */ if (plane_state->ctx->dc->debug.always_scale == true) { @@ -836,6 +873,9 @@ static enum dml2_uclk_pstate_change_strategy dml21_force_pstate_method_to_uclk_s case dml2_force_pstate_method_subvp: val = dml2_uclk_pstate_change_strategy_force_mall_svp; break; + case dml2_force_pstate_method_alternate: + val = dml2_uclk_pstate_change_strategy_force_alternate; + break; case dml2_force_pstate_method_auto: default: val = dml2_uclk_pstate_change_strategy_auto; @@ -952,6 +992,9 @@ void dml21_copy_clocks_to_dc_state(struct dml2_context *in_ctx, struct dc_state context->bw_ctx.bw.dcn.clk.socclk_khz = in_ctx->v21.mode_programming.programming->min_clocks.dcn4x.socclk_khz; context->bw_ctx.bw.dcn.clk.subvp_prefetch_dramclk_khz = in_ctx->v21.mode_programming.programming->min_clocks.dcn4x.svp_prefetch_no_throttle.uclk_khz; context->bw_ctx.bw.dcn.clk.subvp_prefetch_fclk_khz = in_ctx->v21.mode_programming.programming->min_clocks.dcn4x.svp_prefetch_no_throttle.fclk_khz; + context->bw_ctx.bw.dcn.clk.utm_latency_ub_index = 0; /* TODO - derive from qos model */ + context->bw_ctx.bw.dcn.clk.utm_nominal_bandwidth_lb_Kbps = (unsigned int) in_ctx->v21.mode_programming.programming->qos_bound.bandwidth_lb.dcn5.non_urgent_bandwidth_kbps; + context->bw_ctx.bw.dcn.clk.utm_urgent_bandwidth_lb_Kbps = (unsigned int) in_ctx->v21.mode_programming.programming->qos_bound.bandwidth_lb.dcn5.urgent_bandwidth_kbps; context->bw_ctx.bw.dcn.clk.stutter_efficiency.base_efficiency = (uint8_t)in_ctx->v21.mode_programming.programming->stutter.base_percent_efficiency; context->bw_ctx.bw.dcn.clk.stutter_efficiency.low_power_efficiency = (uint8_t)in_ctx->v21.mode_programming.programming->stutter.low_power_percent_efficiency; context->bw_ctx.bw.dcn.clk.stutter_efficiency.z8_stutter_efficiency = (uint8_t)in_ctx->v21.mode_programming.programming->informative.power_management.z8.stutter_efficiency; @@ -1060,6 +1103,9 @@ void dml21_set_dc_p_state_type( else pipe_ctx->p_state_type = P_STATE_FPO; break; + case dml2_pstate_method_alternate: + pipe_ctx->p_state_type = P_STATE_ALT; + break; default: pipe_ctx->p_state_type = P_STATE_UNKNOWN; break; @@ -1087,6 +1133,9 @@ void dml21_init_min_clocks_for_dc_state(struct dml2_context *in_ctx, struct dc_s min_clocks->subvp_prefetch_dramclk_khz = 0; min_clocks->subvp_prefetch_fclk_khz = 0; min_clocks->phyclk_khz = in_ctx->v21.dml_init.soc_bb.clk_table.phyclk.clk_values_khz[lowest_dpm_state_index]; + min_clocks->utm_latency_ub_index = 0; /* TODO - derive from qos model */ + min_clocks->utm_nominal_bandwidth_lb_Kbps = 0; + min_clocks->utm_urgent_bandwidth_lb_Kbps = 0; min_clocks->stutter_efficiency.base_efficiency = 1; min_clocks->stutter_efficiency.low_power_efficiency = 1; min_clocks->stutter_efficiency.z8_stutter_efficiency = 1; diff --git a/drivers/gpu/drm/amd/display/dc/dml2_0/dml21/dml21_utils.c b/drivers/gpu/drm/amd/display/dc/dml2_0/dml21/dml21_utils.c index 012dff4cf3fa..1ade48b8b621 100644 --- a/drivers/gpu/drm/amd/display/dc/dml2_0/dml21/dml21_utils.c +++ b/drivers/gpu/drm/amd/display/dc/dml2_0/dml21/dml21_utils.c @@ -375,6 +375,130 @@ void dml21_handle_phantom_streams_planes(const struct dc *dc, struct dc_state *c dml2_map_dc_pipes(dml_ctx, context, NULL, &dml_ctx->v21.dml_to_dc_pipe_mapping, dc->current_state); } +static uint32_t calc_svp_size_64kb(uint32_t total_size_bytes) +{ + return (total_size_bytes + 0xFFFF) >> 16; +} + +static unsigned int dml21_build_fams2_stream_programming_v3(const struct dc *dc, + struct dc_state *context, + struct dml2_context *dml_ctx) +{ + int dml_stream_idx, dc_stream_idx, dc_plane_idx, svp_idx; + unsigned int dc_pipe_idx; + unsigned int num_fams2_streams = 0; + unsigned int svp_size_64kb[2] = {0}; + struct pipe_ctx *pipe; + + for (dc_stream_idx = 0; dc_stream_idx < context->stream_count; dc_stream_idx++) { + enum fams2_stream_type type = 0; + + union dmub_cmd_fams2_config *static_base_state = &context->bw_ctx.bw.dcn.fams2_stream_base_params[num_fams2_streams]; + struct dmub_fams2_cmd_alternate_stream_static_state *alternate_static_state; + + struct dc_stream_state *stream = context->streams[dc_stream_idx]; + + if (context->stream_status[dc_stream_idx].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_base_state, + &dml_ctx->v21.mode_programming.programming->stream_programming[dml_stream_idx].fams2_base_params, + sizeof(union dmub_cmd_fams2_config)); + + memcpy(&context->bw_ctx.bw.dcn.fams2_stream_sub_params_v2[num_fams2_streams], + &dml_ctx->v21.mode_programming.programming->stream_programming[dml_stream_idx].fams2_sub_params_v2, + sizeof(union dmub_fams2_stream_static_sub_state_v2)); + + type = static_base_state->stream_v1.base.type; + + /* get information from context */ + ASSERT(context->stream_status[dc_stream_idx].plane_count >= 0 && + context->stream_status[dc_stream_idx].plane_count <= 0xFF); + ASSERT(context->stream_status[dc_stream_idx].primary_otg_inst >= 0 && + context->stream_status[dc_stream_idx].primary_otg_inst <= 0xFF); + static_base_state->stream_v1.base.num_planes = (uint8_t)context->stream_status[dc_stream_idx].plane_count; + static_base_state->stream_v1.base.otg_inst = (uint8_t)context->stream_status[dc_stream_idx].primary_otg_inst; + + /* populate pipe masks for planes */ + for (dc_plane_idx = 0; dc_plane_idx < context->stream_status[dc_stream_idx].plane_count; dc_plane_idx++) { + for (dc_pipe_idx = 0; dc_pipe_idx < dc->res_pool->pipe_count; dc_pipe_idx++) { + if (context->res_ctx.pipe_ctx[dc_pipe_idx].stream && + context->res_ctx.pipe_ctx[dc_pipe_idx].stream->stream_id == stream->stream_id && + context->res_ctx.pipe_ctx[dc_pipe_idx].plane_state == context->stream_status[dc_stream_idx].plane_states[dc_plane_idx]) { + static_base_state->stream_v1.base.pipe_mask |= (1 << dc_pipe_idx); + static_base_state->stream_v1.base.plane_pipe_masks[dc_plane_idx] |= (1 << dc_pipe_idx); + } + } + } + + /* get per method programming */ + switch (type) { + case FAMS2_STREAM_TYPE_VBLANK: + case FAMS2_STREAM_TYPE_VACTIVE: + case FAMS2_STREAM_TYPE_DRR: + break; + case FAMS2_STREAM_TYPE_ALTERNATE: + alternate_static_state = &context->bw_ctx.bw.dcn.fams2_stream_sub_params_v2[num_fams2_streams].alternate; + + for (dc_plane_idx = 0; dc_plane_idx < context->stream_status[dc_stream_idx].plane_count; dc_plane_idx++) { + for (dc_pipe_idx = 0; dc_pipe_idx < dc->res_pool->pipe_count; dc_pipe_idx++) { + pipe = &context->res_ctx.pipe_ctx[dc_pipe_idx]; + if (pipe->plane_state != context->stream_status[dc_stream_idx].plane_states[dc_plane_idx]) + continue; + // TODO: Mapping between plane_idx within stream_res and plane_idx within alternate_stream_static_state + // should be matching, but it's better to have an explicit map / check (future improvement) + ASSERT(pipe->plane_res.scl_data.viewport.height >= 0 && pipe->plane_res.scl_data.viewport.height <= 0xFFFF); + ASSERT(pipe->plane_res.scl_data.viewport.width >= 0 && pipe->plane_res.scl_data.viewport.width <= 0xFFFF); + ASSERT(pipe->plane_res.scl_data.viewport.x >= 0 && pipe->plane_res.scl_data.viewport.x <= 0xFFFF); + ASSERT(pipe->plane_res.scl_data.viewport.y >= 0 && pipe->plane_res.scl_data.viewport.y <= 0xFFFF); + alternate_static_state->pipe_viewports[dc_pipe_idx].luma.height = (uint16_t)pipe->plane_res.scl_data.viewport.height; + alternate_static_state->pipe_viewports[dc_pipe_idx].luma.width = (uint16_t)pipe->plane_res.scl_data.viewport.width; + alternate_static_state->pipe_viewports[dc_pipe_idx].luma.x = (uint16_t)pipe->plane_res.scl_data.viewport.x; + alternate_static_state->pipe_viewports[dc_pipe_idx].luma.y = (uint16_t)pipe->plane_res.scl_data.viewport.y; + if (alternate_static_state->config[dc_plane_idx].bits.is_multi_planar) { + ASSERT(pipe->plane_res.scl_data.viewport_c.height >= 0 && pipe->plane_res.scl_data.viewport_c.height <= 0xFFFF); + ASSERT(pipe->plane_res.scl_data.viewport_c.width >= 0 && pipe->plane_res.scl_data.viewport_c.width <= 0xFFFF); + ASSERT(pipe->plane_res.scl_data.viewport_c.x >= 0 && pipe->plane_res.scl_data.viewport_c.x <= 0xFFFF); + ASSERT(pipe->plane_res.scl_data.viewport_c.y >= 0 && pipe->plane_res.scl_data.viewport_c.y <= 0xFFFF); + alternate_static_state->pipe_viewports[dc_pipe_idx].chroma.height = (uint16_t)pipe->plane_res.scl_data.viewport_c.height; + alternate_static_state->pipe_viewports[dc_pipe_idx].chroma.width = (uint16_t)pipe->plane_res.scl_data.viewport_c.width; + alternate_static_state->pipe_viewports[dc_pipe_idx].chroma.x = (uint16_t)pipe->plane_res.scl_data.viewport_c.x; + alternate_static_state->pipe_viewports[dc_pipe_idx].chroma.y = (uint16_t)pipe->plane_res.scl_data.viewport_c.y; + } + for (svp_idx = 0; svp_idx < 2; svp_idx++) { + alternate_static_state->pipe_copy_addr_47_16[svp_idx][dc_pipe_idx] = + dml_ctx->config.alt_ch_cfg.region_base_addr_47_16[svp_idx] + svp_size_64kb[svp_idx]; + svp_size_64kb[svp_idx] += calc_svp_size_64kb(alternate_static_state->pipe_copy_max_size[svp_idx][dc_plane_idx]); + if (alternate_static_state->config[dc_plane_idx].bits.is_multi_planar) { + alternate_static_state->pipe_copy_addr_47_16_c[svp_idx][dc_pipe_idx] = + dml_ctx->config.alt_ch_cfg.region_base_addr_47_16[svp_idx] + svp_size_64kb[svp_idx]; + svp_size_64kb[svp_idx] += calc_svp_size_64kb(alternate_static_state->pipe_copy_max_size_c[svp_idx][dc_plane_idx]); + } + } + } + } + break; + case FAMS2_STREAM_TYPE_SUBVP: + default: + ASSERT(false); + break; + } + + num_fams2_streams++; + } + + return num_fams2_streams; +} static unsigned int dml21_build_fams2_stream_programming_v2(const struct dc *dc, struct dc_state *context, @@ -509,7 +633,9 @@ void dml21_build_fams2_programming(const struct dc *dc, if (dml_ctx->v21.mode_programming.programming->fams2_required || dml_ctx->v21.mode_programming.programming->legacy_pstate_info_for_dmu) { - if (dc->debug.fams_version.major == 2) { + if (dc->debug.fams_version.major == 3) { + num_fams2_streams = dml21_build_fams2_stream_programming_v3(dc, context, dml_ctx); + } else if (dc->debug.fams_version.major == 2) { num_fams2_streams = dml21_build_fams2_stream_programming_v2(dc, context, dml_ctx); } } @@ -525,6 +651,7 @@ void dml21_build_fams2_programming(const struct dc *dc, context->bw_ctx.bw.dcn.clk.fw_based_mclk_switching = (context->bw_ctx.bw.dcn.fams2_global_config.features.bits.enable != 0); + context->bw_ctx.bw.dcn.clk.alt_ch_pstate_switch = dc_state_is_alt_in_use(dc, context); } bool dml21_is_plane1_enabled(enum dml2_source_format_class source_format) diff --git a/drivers/gpu/drm/amd/display/dc/dml2_0/dml21/inc/dml_top_display_cfg_types.h b/drivers/gpu/drm/amd/display/dc/dml2_0/dml21/inc/dml_top_display_cfg_types.h index 79dfba54344c..f402bb933f7d 100644 --- a/drivers/gpu/drm/amd/display/dc/dml2_0/dml21/inc/dml_top_display_cfg_types.h +++ b/drivers/gpu/drm/amd/display/dc/dml2_0/dml21/inc/dml_top_display_cfg_types.h @@ -102,6 +102,7 @@ enum dml2_uclk_pstate_change_strategy { dml2_uclk_pstate_change_strategy_force_drr = 3, dml2_uclk_pstate_change_strategy_force_mall_svp = 4, dml2_uclk_pstate_change_strategy_force_mall_full_frame = 5, + dml2_uclk_pstate_change_strategy_force_alternate = 6, }; enum dml2_svp_mode_override { @@ -474,6 +475,15 @@ struct dml2_display_cfg { bool value; } force_nom_det_size_kbytes; + struct { + bool enable; // So copy time can be forced to 0 + unsigned int copy_time_us; + } force_alt_chan_copy_time; + + struct { + bool enable; // So fw delay can be forced to 0 + unsigned int fw_delay_us; + } force_alt_chan_fw_delay; bool mode_support_check_disable; bool mcache_admissibility_check_disable; bool surface_viewport_size_check_disable; diff --git a/drivers/gpu/drm/amd/display/dc/dml2_0/dml21/inc/dml_top_soc_parameter_types.h b/drivers/gpu/drm/amd/display/dc/dml2_0/dml21/inc/dml_top_soc_parameter_types.h index 672b96a3da74..b830e95b27c8 100644 --- a/drivers/gpu/drm/amd/display/dc/dml2_0/dml21/inc/dml_top_soc_parameter_types.h +++ b/drivers/gpu/drm/amd/display/dc/dml2_0/dml21/inc/dml_top_soc_parameter_types.h @@ -117,6 +117,7 @@ struct dml2_soc_power_management_parameters { double g6_temp_read_blackout_us[DML_MAX_CLK_TABLE_SIZE]; double type_b_dram_clk_change_blackout_us; double type_b_ppt_blackout_us; + unsigned int alternate_dram_carveout_size_mb; // size per aperture - assumed same for both apertures for now }; struct dml2_clk_table { @@ -213,6 +214,7 @@ struct dml2_ip_capabilities { unsigned int ppt_max_allow_delay_us; unsigned int temp_read_max_allow_delay_us; unsigned int dummy_pstate_max_allow_delay_us; + unsigned int vblank_nom_default_us; /* FAMS2 delays */ struct { unsigned int max_allow_delay_us; diff --git a/drivers/gpu/drm/amd/display/dc/dml2_0/dml21/inc/dml_top_types.h b/drivers/gpu/drm/amd/display/dc/dml2_0/dml21/inc/dml_top_types.h index f00ca2983ff5..bf71f4e1a451 100644 --- a/drivers/gpu/drm/amd/display/dc/dml2_0/dml21/inc/dml_top_types.h +++ b/drivers/gpu/drm/amd/display/dc/dml2_0/dml21/inc/dml_top_types.h @@ -20,6 +20,12 @@ enum dml2_project_id { dml2_project_dcn4x_stage2, dml2_project_dcn4x_stage2_auto_drr_svp, dml2_project_dcn42, + dml2_project_dcn4x_utm, + dml2_project_dcn5x, + dml2_project_dcn5x_utm, + dml2_project_dcn6x_soc_var_a, + dml2_project_dcn6x_soc_var_b, + dml2_project_dcn6x = dml2_project_dcn6x_soc_var_b, }; enum dml2_pstate_change_support { @@ -72,6 +78,10 @@ struct dml2_pmo_options { bool disable_dyn_odm_for_multi_stream; bool disable_dyn_odm_for_stream_with_svp; bool force_mandatory_uclk_pstate_support; + bool disable_alternate_memory_training; + bool force_optional_uclk_pstate_support; + bool force_optional_mcache_support; + bool force_optional_ppt_temp_read_admissibility; struct dml2_pmo_pstate_strategy *override_strategy_lists[DML2_MAX_PLANES]; unsigned int num_override_strategies_per_list[DML2_MAX_PLANES]; }; @@ -81,6 +91,7 @@ struct dml2_options { struct dml2_pmo_options pmo_options; }; +struct utm_qos_mode; struct dml2_initialize_instance_in_out { struct dml2_instance *dml2_instance; @@ -91,6 +102,7 @@ struct dml2_initialize_instance_in_out { struct { void *explicit_ip_bb; unsigned int explicit_ip_bb_size; + const struct utm_qos_model *explicit_qos_model; } overrides; }; @@ -214,6 +226,7 @@ enum dml2_pstate_method { dml2_pstate_method_reserved_fw_drr_clamped = 20, dml2_pstate_method_fw_drr = 21, dml2_pstate_method_reserved_fw_drr_var = 22, + dml2_pstate_method_alternate, dml2_pstate_method_count }; @@ -369,6 +382,36 @@ struct dml2_mode_support_info { bool dcfclk_support; }; // dml2_mode_support_info +struct dml2_memory_path_latency { + union { + struct { + double urgent_ramp; + double t_trip; + double meta_trip_to_mem; + double max_req_latency_urg; + double avg_req_latency_urg; + double max_req_latency_non_urg; + double avg_req_latency_non_urg; + double df_response_time_us; + } dcn5; + }; +}; + +struct dml2_memory_path_bandwidth { + union { + struct { + double urgent_bandwidth_kbps; // kbytes per sec + double non_urgent_bandwidth_kbps; // kbytes per sec + } dcn5; + }; +}; + +struct dml2_qos_bound { + struct dml2_memory_path_latency latency_ub; + struct dml2_memory_path_bandwidth bandwidth_lb; + double lsdma_bandwidth_lb_kbps; +}; + struct dml2_display_cfg_programming { struct dml2_display_cfg display_config; @@ -418,6 +461,8 @@ struct dml2_display_cfg_programming { } dcn4x; } min_clocks; + struct dml2_qos_bound qos_bound; + unsigned int min_sop_index; bool uclk_pstate_supported; bool fclk_pstate_supported; diff --git a/drivers/gpu/drm/amd/display/dc/dml2_0/dml21/src/dml2_core/dml2_core_dcn4_calcs.c b/drivers/gpu/drm/amd/display/dc/dml2_0/dml21/src/dml2_core/dml2_core_dcn4_calcs.c index 09452f3e49db..72acf12e9251 100644 --- a/drivers/gpu/drm/amd/display/dc/dml2_0/dml21/src/dml2_core/dml2_core_dcn4_calcs.c +++ b/drivers/gpu/drm/amd/display/dc/dml2_0/dml21/src/dml2_core/dml2_core_dcn4_calcs.c @@ -13094,6 +13094,7 @@ void dml2_core_calcs_get_stream_fams2_programming(const struct dml2_core_interna (uint16_t)stream_pstate_meta->method_subvp.common.allow_end_otg_vline; base_programming->config.bits.clamp_vtotal_min = true; break; + case dml2_pstate_method_alternate: case dml2_pstate_method_reserved_hw: case dml2_pstate_method_reserved_fw: case dml2_pstate_method_reserved_fw_drr_clamped: diff --git a/drivers/gpu/drm/amd/display/dc/dml2_0/dml21/src/dml2_core/dml2_core_factory.c b/drivers/gpu/drm/amd/display/dc/dml2_0/dml21/src/dml2_core/dml2_core_factory.c index 9f1222f5a835..0800c667f204 100644 --- a/drivers/gpu/drm/amd/display/dc/dml2_0/dml21/src/dml2_core/dml2_core_factory.c +++ b/drivers/gpu/drm/amd/display/dc/dml2_0/dml21/src/dml2_core/dml2_core_factory.c @@ -4,6 +4,12 @@ #include "dml2_core_factory.h" #include "dml2_core_dcn4.h" +#include "dml2_core_dcn5_funcs_initialize.h" +#include "dml2_core_dcn5_funcs_mode_support.h" +#include "dml2_core_dcn5_funcs_mode_programming.h" +#include "dml2_core_dcn6_funcs_initialize.h" +#include "dml2_core_dcn6_funcs_mode_support.h" +#include "dml2_core_dcn6_funcs_mode_programming.h" #include "dml2_external_lib_deps.h" bool dml2_core_create(enum dml2_project_id project_id, struct dml2_core_instance *out) @@ -36,6 +42,25 @@ bool dml2_core_create(enum dml2_project_id project_id, struct dml2_core_instance out->calculate_mcache_allocation = &core_dcn4_calculate_mcache_allocation; result = true; break; + case dml2_project_dcn5x_utm: + out->initialize = &dml2_core_dcn5_funcs_initialize; + out->validate_solution = &dml2_core_dcn5_funcs_validate_solution; + out->populate_programming = &dml2_core_dcn5_funcs_populate_programming; + out->populate_informative = &core_dcn4_populate_informative; + out->calculate_mcache_allocation = &core_dcn4_calculate_mcache_allocation; + result = true; + break; + case dml2_project_dcn6x_soc_var_a: + case dml2_project_dcn6x_soc_var_b: + out->initialize = &dml2_core_dcn6_funcs_initialize; + out->validate_solution = &dml2_core_dcn6_funcs_validate_solution; + out->populate_programming = &dml2_core_dcn6_funcs_populate_programming; + out->populate_informative = &core_dcn4_populate_informative; + out->calculate_mcache_allocation = &core_dcn4_calculate_mcache_allocation; + result = true; + break; + case dml2_project_dcn4x_utm: + case dml2_project_dcn5x: case dml2_project_invalid: default: break; diff --git a/drivers/gpu/drm/amd/display/dc/dml2_0/dml21/src/dml2_core/dml2_core_shared_types.h b/drivers/gpu/drm/amd/display/dc/dml2_0/dml21/src/dml2_core/dml2_core_shared_types.h index b8af72392176..8a371bd1a7a5 100644 --- a/drivers/gpu/drm/amd/display/dc/dml2_0/dml21/src/dml2_core/dml2_core_shared_types.h +++ b/drivers/gpu/drm/amd/display/dc/dml2_0/dml21/src/dml2_core/dml2_core_shared_types.h @@ -14,6 +14,7 @@ #define __DML2_CALCS_MAX_VRATIO_PRE_OTO__ 4.0 //<brief max vratio for one-to-one prefetch bw scheduling #define __DML2_CALCS_MAX_VRATIO_PRE_EQU__ 6.0 //<brief max vratio for equalized prefetch bw scheduling #define __DML2_CALCS_MAX_VRATIO_PRE__ 8.0 //<brief max prefetch vratio register limit +#define __DML2_CALCS_MAX_VSTARTUP__ 1023.0 // <brief max vstartup lines supported by hardware #define __DML2_CALCS_DPP_INVALID__ 0 #define __DML2_CALCS_DCFCLK_FACTOR__ 1.15 //<brief fudge factor for min dcfclk calclation @@ -51,6 +52,7 @@ struct dml2_core_ip_params { unsigned int max_vscl_taps; unsigned int odm_combine_support_mask; unsigned int num_dsc; + unsigned int maximum_dsc_slices_per_pipe; unsigned int maximum_dsc_bits_per_component; unsigned int maximum_pixels_per_line_per_dsc_unit; bool dsc422_native_support; @@ -86,6 +88,7 @@ struct dml2_core_ip_params { unsigned int subvp_swath_height_margin_lines; unsigned int subvp_fw_processing_delay_us; unsigned int subvp_pstate_allow_width_us; + unsigned int alt_chan_fw_delay_us; // FW delay value required in mode support calculation // MRQ bool dcn_mrq_present; unsigned int zero_size_buffer_entries; @@ -96,6 +99,11 @@ struct dml2_core_ip_params { unsigned int dchub_arb_to_ret_delay; // num of dcfclk unsigned int hostvm_mode; + unsigned int fams2_max_allow_delay_us; + unsigned int fams2_min_allow_width_us; + unsigned int ppt_max_allow_delay_us; + unsigned int temp_read_max_allow_delay_us; + bool use_legacy_dsc_delay_formula; }; struct dml2_core_internal_DmlPipe { @@ -335,6 +343,7 @@ struct dml2_core_internal_mode_support_info { double non_urg_bandwidth_required[dml2_core_internal_soc_state_max][dml2_core_internal_bw_max]; // same as urg_bandwidth, except not scaled by urg burst factor double non_urg_bandwidth_required_flip[dml2_core_internal_soc_state_max][dml2_core_internal_bw_max]; bool avg_bandwidth_support_ok[dml2_core_internal_soc_state_max][dml2_core_internal_bw_max]; + struct dml2_memory_path_bandwidth bandwidth_upper_bound; double max_urgent_latency_us; double max_non_urgent_latency_us; double avg_non_urgent_latency_us; @@ -348,6 +357,7 @@ struct dml2_core_internal_mode_support_info { struct dml2_core_internal_watermarks watermarks; bool dcfclk_support; bool qos_bandwidth_support; + bool alternate_channel_size_support; }; struct dml2_core_internal_mode_support { @@ -535,6 +545,7 @@ struct dml2_core_internal_mode_support { double DesiredOutputBpp[DML2_MAX_PLANES]; double PixelClockBackEnd[DML2_MAX_PLANES]; unsigned int DSCDelay[DML2_MAX_PLANES]; + bool use_legacy_dsc_delay_formula; enum dml2_core_internal_output_type OutputType[DML2_MAX_PLANES]; enum dml2_core_internal_output_type_rate OutputRate[DML2_MAX_PLANES]; bool TotalAvailablePipesSupportNoDSC; @@ -654,6 +665,42 @@ struct dml2_core_internal_mode_support { unsigned int DSTXAfterScaler[DML2_MAX_PLANES]; enum dml2_pstate_method uclk_pstate_switch_modes[DML2_MAX_PLANES]; + unsigned int svp0_max_bytes; + unsigned int svp1_max_bytes; + unsigned int svp0_max_bytes_per_dpp[DML2_MAX_PLANES]; // max bytes for any DPP under a given plane + unsigned int svp0_max_bytes_per_dpp_c[DML2_MAX_PLANES]; // max bytes for any DPP under a given plane + unsigned int svp1_max_bytes_per_dpp[DML2_MAX_PLANES]; // max bytes for any DPP under a given plane + unsigned int svp1_max_bytes_per_dpp_c[DML2_MAX_PLANES]; // max bytes for any DPP under a given plane + unsigned int svp0_dst_lines[DML2_MAX_PLANES]; // per stream + unsigned int svp1_dst_lines[DML2_MAX_PLANES]; // per stream + unsigned int svp_req_limit[DML2_MAX_PLANES]; // per stream, should be the same value in time between all streams max(2 swaths, dst_y_pre) over all planes + unsigned int nom_req_limit_alt[DML2_MAX_PLANES]; + unsigned int min_lead_dst_lines[DML2_MAX_PLANES]; + unsigned int total_swaths[DML2_MAX_PLANES]; + unsigned int total_swaths_c[DML2_MAX_PLANES]; + unsigned int prefetch_swaths[DML2_MAX_PLANES]; + unsigned int prefetch_swaths_c[DML2_MAX_PLANES]; + double prefetch_hdl_delta[DML2_MAX_PLANES]; // in dst + double recout_hdl_delta[DML2_MAX_PLANES]; // in dst + double prefetch_hdl_delta_c[DML2_MAX_PLANES]; // in dst + double recout_hdl_delta_c[DML2_MAX_PLANES]; // in dst + unsigned int max_prefetch_in_lines[DML2_MAX_PLANES]; // max prefetch time over all planes converted to lines for the given stream + double lsdma_bw_req_for_alt_kbps; + + // Synchronized timing group assignement + unsigned int timing_group_id[DML2_MAX_PLANES]; // timing group id for the given plane + unsigned int timing_group_count; + + bool fclk_pstate_required; + bool ppt_pstate_required; + bool temp_read_pstate_required; + // P-state schedule windows + double fclk_pstate_allow_start_us[DML2_MAX_PLANES]; + double fclk_pstate_allow_end_us[DML2_MAX_PLANES]; + double ppt_pstate_allow_start_us[DML2_MAX_PLANES]; + double ppt_pstate_allow_end_us[DML2_MAX_PLANES]; + double temp_read_pstate_allow_start_us[DML2_MAX_PLANES]; + double temp_read_pstate_allow_end_us[DML2_MAX_PLANES]; }; /// @brief A mega structure that houses various info for model programming step. @@ -705,6 +752,7 @@ struct dml2_core_internal_mode_program { double PSCL_THROUGHPUT[DML2_MAX_PLANES]; double PSCL_THROUGHPUT_CHROMA[DML2_MAX_PLANES]; unsigned int DSCDelay[DML2_MAX_PLANES]; + bool use_legacy_dsc_delay_formula; double DPPCLKUsingSingleDPP[DML2_MAX_PLANES]; unsigned int Read256BlockHeightY[DML2_MAX_PLANES]; @@ -845,6 +893,26 @@ struct dml2_core_internal_mode_program { double df_response_time_us; enum dml2_pstate_method uclk_pstate_switch_modes[DML2_MAX_PLANES]; + unsigned int svp0_max_bytes; + unsigned int svp1_max_bytes; + unsigned int svp0_max_bytes_per_dpp[DML2_MAX_PLANES]; // max bytes for any DPP under a given plane + unsigned int svp0_max_bytes_per_dpp_c[DML2_MAX_PLANES]; // max bytes for any DPP under a given plane + unsigned int svp1_max_bytes_per_dpp[DML2_MAX_PLANES]; // max bytes for any DPP under a given plane + unsigned int svp1_max_bytes_per_dpp_c[DML2_MAX_PLANES]; // max bytes for any DPP under a given plane + unsigned int svp0_dst_lines[DML2_MAX_PLANES]; // per stream + unsigned int svp1_dst_lines[DML2_MAX_PLANES]; // per stream + unsigned int min_lead_dst_lines[DML2_MAX_PLANES]; // per stream, should be max(nominal_req_limit, vstartup_to_vactive). Does not have to be maxed over all planes + unsigned int svp_req_limit[DML2_MAX_PLANES]; // per stream, should be the same value in time between all streams max(2 swaths, dst_y_pre) over all planes + unsigned int nom_req_limit_alt[DML2_MAX_PLANES]; // per stream + unsigned int total_swaths[DML2_MAX_PLANES]; + unsigned int total_swaths_c[DML2_MAX_PLANES]; + unsigned int prefetch_swaths[DML2_MAX_PLANES]; + unsigned int prefetch_swaths_c[DML2_MAX_PLANES]; + double prefetch_hdl_delta[DML2_MAX_PLANES]; // in dst + double recout_hdl_delta[DML2_MAX_PLANES]; // in dst + double prefetch_hdl_delta_c[DML2_MAX_PLANES]; // in dst + double recout_hdl_delta_c[DML2_MAX_PLANES]; // in dst + unsigned int max_prefetch_in_lines[DML2_MAX_PLANES]; // max prefetch time over all planes converted to lines for the given stream // ------------------- // Output // ------------------- @@ -1281,6 +1349,7 @@ struct dml2_core_calcs_CalculateWatermarksMALLUseAndDRAMSpeedChangeSupport_local double ActiveClockChangeLatencyHidingY; double ActiveClockChangeLatencyHidingC; double ActiveClockChangeLatencyHiding; + double peak_vactive_p_vblank_latency_hiding_us; unsigned int dst_y_pstate; unsigned int src_y_pstate_l; unsigned int src_y_pstate_c; @@ -2180,6 +2249,90 @@ struct dml2_core_calcs_calculate_mcache_setting_params { bool *lc_comb_mcache; }; + +struct dml2_core_calcs_calculate_alternate_lead_lines { + /* input params */ + const struct dml2_display_cfg *display_cfg; + unsigned int *VStartup; + double *VActiveLatencyHidingUs; + + /* output params */ + unsigned int *min_lead_dst_lines; +}; + +struct dml2_core_calcs_calculate_alternate_svp_lines { + /* input params */ + const struct dml2_display_cfg *display_cfg; + unsigned int *SwathHeightY; + unsigned int *SwathHeightC; + unsigned int *DETBufferSizeY; + double *BytePerPixelInDETC; + double dram_blackout_us; + + /* output params */ + unsigned int *svp0_dst_lines; + unsigned int *svp1_dst_lines; + unsigned int *svp_req_limit; +}; + +struct dml2_core_calcs_calculate_alternate_params { + /* input params */ + const struct dml2_display_cfg *display_cfg; + double *dst_y_prefetch; + unsigned int *SwathHeightY; + unsigned int *SwathHeightC; + unsigned int *SwathWidthY; + unsigned int *SwathWidthC; + unsigned int *DETBufferSizeY; + unsigned int *DETBufferSizeC; + unsigned int *BytePerPixelY; + unsigned int *BytePerPixelC; + double *BytePerPixelInDETY; + double *BytePerPixelInDETC; + unsigned int *Read256BlockWidthY; + unsigned int *Read256BlockHeightY; + unsigned int *Read256BlockWidthC; + unsigned int *Read256BlockHeightC; + unsigned int *MacroTileWidthY; + unsigned int *MacroTileWidthC; + unsigned int *VInitPrefillY; + unsigned int *VInitPrefillC; + double *VRatioPrefetchY; + double *VRatioPrefetchC; + unsigned int *NoOfDPP; + unsigned int max_num_dpp; + double dram_blackout_us; + double *VActiveLatencyHidingUs; + unsigned int *svp0_dst_lines; + unsigned int *svp1_dst_lines; + unsigned int *svp_req_limit; + double dcn_non_urgent_bandwidth_kbps; + unsigned int alt_chan_fw_delay_us; + double *dst_y_per_vm_vblank; + double *dst_y_per_row_vblank; + unsigned int *DSTYAfterScaler; + enum dml2_odm_mode *ODMMode; + + /* output params */ + unsigned int *svp0_max_bytes; + unsigned int *svp1_max_bytes; + unsigned int *svp0_max_bytes_per_dpp; + unsigned int *svp0_max_bytes_per_dpp_c; + unsigned int *svp1_max_bytes_per_dpp; + unsigned int *svp1_max_bytes_per_dpp_c; + unsigned int *nom_req_limit_alt; + unsigned int *min_lead_dst_lines; + unsigned int *total_swaths; + unsigned int *total_swaths_c; + unsigned int *prefetch_swaths; + unsigned int *prefetch_swaths_c; + double *prefetch_hdl_delta; + double *recout_hdl_delta; + double *prefetch_hdl_delta_c; + double *recout_hdl_delta_c; + unsigned int *max_prefetch_in_lines; + double *lsdma_bw_req_for_alt_kbps; +}; struct dml2_core_calcs_calculate_tdlut_setting_params { // input params double dispclk_mhz; @@ -2307,6 +2460,9 @@ struct dml2_core_internal_scratch { struct dml2_core_shared_CalculateMetaAndPTETimes_params CalculateMetaAndPTETimes_params; struct dml2_core_calcs_calculate_peak_bandwidth_required_params calculate_peak_bandwidth_params; struct dml2_core_calcs_calculate_bytes_to_fetch_required_to_hide_latency_params calculate_bytes_to_fetch_required_to_hide_latency_params; + struct dml2_core_calcs_calculate_alternate_params calculate_alternate_params; + struct dml2_core_calcs_calculate_alternate_svp_lines calculate_alternate_svp_lines; + struct dml2_core_calcs_calculate_alternate_lead_lines calculate_alternate_lead_lines; }; //struct dml2_svp_mode_override; @@ -2331,6 +2487,7 @@ struct dml2_core_calcs_mode_support_ex { const struct dml2_display_cfg *in_display_cfg; const struct dml2_mcg_min_clock_table *min_clk_table; int min_clk_index; + const struct dml2_utm_soc_bb *utm_soc_bb; //unsigned int in_state_index; struct dml2_core_internal_mode_support_info *out_evaluation_info; const enum dml2_pstate_method *uclk_pstate_switch_modes; @@ -2344,6 +2501,9 @@ struct dml2_core_calcs_mode_programming_ex { const struct dml2_mcg_min_clock_table *min_clk_table; const struct core_display_cfg_support_info *cfg_support_info; int min_clk_index; + const struct dml2_uclk_pstate_params *uclk_params; + const struct dml2_display_solution *solution; + const struct dml2_utm_soc_bb *utm_soc_bb; struct dml2_display_cfg_programming *programming; }; diff --git a/drivers/gpu/drm/amd/display/dc/dml2_0/dml21/src/dml2_dpmm/dml2_dpmm_factory.c b/drivers/gpu/drm/amd/display/dc/dml2_0/dml21/src/dml2_dpmm/dml2_dpmm_factory.c index be0517e10104..528ebadb87e1 100644 --- a/drivers/gpu/drm/amd/display/dc/dml2_0/dml21/src/dml2_dpmm/dml2_dpmm_factory.c +++ b/drivers/gpu/drm/amd/display/dc/dml2_0/dml21/src/dml2_dpmm/dml2_dpmm_factory.c @@ -5,6 +5,7 @@ #include "dml2_dpmm_factory.h" #include "dml2_dpmm_dcn4.h" #include "dml2_external_lib_deps.h" +#include "dml2_dpmm_dcn5.h" static bool dummy_map_mode_to_soc_dpm(struct dml2_dpmm_map_mode_to_soc_dpm_params_in_out *in_out) { @@ -48,6 +49,17 @@ bool dml2_dpmm_create(enum dml2_project_id project_id, struct dml2_dpmm_instance out->map_watermarks = &dpmm_dcn42_map_watermarks; result = true; break; + case dml2_project_dcn5x_utm: + out->map_mode_to_soc_dpm = &dpmm_dcn5_map_mode_to_soc_dpm; + result = true; + break; + case dml2_project_dcn6x_soc_var_a: + case dml2_project_dcn6x_soc_var_b: + /* dpmm is deprecated */ + result = true; + break; + case dml2_project_dcn4x_utm: + case dml2_project_dcn5x: case dml2_project_invalid: default: break; diff --git a/drivers/gpu/drm/amd/display/dc/dml2_0/dml21/src/dml2_mcg/dml2_mcg_factory.c b/drivers/gpu/drm/amd/display/dc/dml2_0/dml21/src/dml2_mcg/dml2_mcg_factory.c index 270283332cc1..a1d63148b6e5 100644 --- a/drivers/gpu/drm/amd/display/dc/dml2_0/dml21/src/dml2_mcg/dml2_mcg_factory.c +++ b/drivers/gpu/drm/amd/display/dc/dml2_0/dml21/src/dml2_mcg/dml2_mcg_factory.c @@ -36,6 +36,11 @@ bool dml2_mcg_create(enum dml2_project_id project_id, struct dml2_mcg_instance * out->build_min_clock_table = &mcg_dcn42_build_min_clock_table; result = true; break; + case dml2_project_dcn4x_utm: + case dml2_project_dcn5x: + case dml2_project_dcn5x_utm: + case dml2_project_dcn6x_soc_var_a: + case dml2_project_dcn6x_soc_var_b: case dml2_project_invalid: default: break; diff --git a/drivers/gpu/drm/amd/display/dc/dml2_0/dml21/src/dml2_pmo/dml2_pmo_dcn4_fams2.c b/drivers/gpu/drm/amd/display/dc/dml2_0/dml21/src/dml2_pmo/dml2_pmo_dcn4_fams2.c index 8f481ef9316f..7ae02eccd598 100644 --- a/drivers/gpu/drm/amd/display/dc/dml2_0/dml21/src/dml2_pmo/dml2_pmo_dcn4_fams2.c +++ b/drivers/gpu/drm/amd/display/dc/dml2_0/dml21/src/dml2_pmo/dml2_pmo_dcn4_fams2.c @@ -23,6 +23,11 @@ static const struct dml2_pmo_pstate_strategy base_strategy_list_1_display[] = { .allow_state_increase = true, }, + // Even-Odd + { + .per_stream_pstate_method = { dml2_pstate_method_alternate, dml2_pstate_method_na, dml2_pstate_method_na, dml2_pstate_method_na }, + .allow_state_increase = true, + }, // Then VBlank { @@ -54,6 +59,11 @@ static const struct dml2_pmo_pstate_strategy base_strategy_list_2_display[] = { .allow_state_increase = true, }, + // Even-Odd + { + .per_stream_pstate_method = { dml2_pstate_method_alternate, dml2_pstate_method_alternate, dml2_pstate_method_na, dml2_pstate_method_na }, + .allow_state_increase = true, + }, // Then VActive + VBlank { @@ -115,6 +125,11 @@ static const struct dml2_pmo_pstate_strategy base_strategy_list_3_display[] = { .allow_state_increase = true, }, + // Even-Odd + { + .per_stream_pstate_method = { dml2_pstate_method_alternate, dml2_pstate_method_alternate, dml2_pstate_method_alternate, dml2_pstate_method_na }, + .allow_state_increase = true, + }, // VActive + 1 VBlank { @@ -152,6 +167,11 @@ static const struct dml2_pmo_pstate_strategy base_strategy_list_4_display[] = { .allow_state_increase = true, }, + // Even-Odd + { + .per_stream_pstate_method = { dml2_pstate_method_alternate, dml2_pstate_method_alternate, dml2_pstate_method_alternate, dml2_pstate_method_alternate }, + .allow_state_increase = true, + }, // VActive + 1 VBlank { @@ -381,6 +401,7 @@ static enum dml2_pstate_method convert_strategy_to_drr_variant(const enum dml2_p case dml2_pstate_method_reserved_fw: case dml2_pstate_method_reserved_fw_drr_clamped: case dml2_pstate_method_reserved_fw_drr_var: + case dml2_pstate_method_alternate: case dml2_pstate_method_count: case dml2_pstate_method_na: default: @@ -665,6 +686,7 @@ bool pmo_dcn4_fams2_initialize(struct dml2_pmo_initialize_in_out *in_out) pmo->fams_params.v2.drr.refresh_rate_limit_min = 119; pmo->options = in_out->options; + pmo->options->disable_alternate_memory_training = true; /* generate permutations of p-state configs from base strategy list */ for (i = 0; i < PMO_DCN4_MAX_DISPLAYS; i++) { @@ -1204,6 +1226,9 @@ enum dml2_pstate_method dcn4_uclk_pstate_strategy_override_to_pstate_method(cons case dml2_uclk_pstate_change_strategy_force_mall_svp: method = dml2_pstate_method_fw_svp; break; + case dml2_uclk_pstate_change_strategy_force_alternate: + method = dml2_pstate_method_alternate; + break; case dml2_uclk_pstate_change_strategy_force_mall_full_frame: case dml2_uclk_pstate_change_strategy_auto: default: @@ -1233,6 +1258,9 @@ static enum dml2_uclk_pstate_change_strategy pstate_method_to_uclk_pstate_strate case dml2_pstate_method_fw_drr: override_strategy = dml2_uclk_pstate_change_strategy_force_drr; break; + case dml2_pstate_method_alternate: + override_strategy = dml2_uclk_pstate_change_strategy_force_alternate; + break; case dml2_pstate_method_reserved_hw: case dml2_pstate_method_reserved_fw: case dml2_pstate_method_reserved_fw_drr_clamped: @@ -1291,6 +1319,7 @@ static struct dml2_pstate_per_method_common_meta *get_per_method_common_meta( break; case dml2_pstate_method_vblank: case dml2_pstate_method_fw_vblank_drr: + case dml2_pstate_method_alternate: stream_method_pstate_meta = &pmo->scratch.pmo_dcn4.stream_pstate_meta[stream_idx].method_vblank.common; break; case dml2_pstate_method_fw_svp: @@ -1609,6 +1638,8 @@ static bool validate_pstate_support_strategy_cofunctionality(struct dml2_pmo_ins unsigned int vactive_stream_mask = 0; unsigned int vblank_count = 0; unsigned int vblank_stream_mask = 0; + unsigned int alternate_count = 0; + unsigned int alternate_stream_mask = 0; bool strategy_matches_forced_requirements = true; bool strategy_matches_drr_requirements = true; @@ -1640,6 +1671,9 @@ static bool validate_pstate_support_strategy_cofunctionality(struct dml2_pmo_ins pstate_strategy->per_stream_pstate_method[stream_index] == dml2_pstate_method_fw_vblank_drr) { vblank_count++; set_bit_in_bitfield(&vblank_stream_mask, stream_index); + } else if (pstate_strategy->per_stream_pstate_method[stream_index] == dml2_pstate_method_alternate) { + alternate_count++; + set_bit_in_bitfield(&alternate_stream_mask, stream_index); } } @@ -1658,6 +1692,8 @@ static bool validate_pstate_support_strategy_cofunctionality(struct dml2_pmo_ins if (svp_count > 0 && (pmo->options->disable_svp || !all_timings_support_svp(pmo, display_cfg, svp_stream_mask))) return false; + if (alternate_count > 0 && pmo->options->disable_alternate_memory_training) + return false; return is_config_schedulable(pmo, display_cfg, pstate_strategy); } @@ -1989,6 +2025,25 @@ static void reset_display_configuration(struct display_configuation_with_meta *d } } +static void setup_planes_for_alternate_by_mask(struct display_configuation_with_meta *display_config, + struct dml2_pmo_instance *pmo, + int plane_mask) +{ + (void)pmo; + unsigned int plane_index; + struct dml2_plane_parameters *plane; + + for (plane_index = 0; plane_index < display_config->display_config.num_planes; plane_index++) { + if (is_bit_set_in_bitfield(plane_mask, plane_index)) { + plane = &display_config->display_config.plane_descriptors[plane_index]; + + // Setup DRR + plane->overrides.uclk_pstate_change_strategy = dml2_uclk_pstate_change_strategy_force_alternate; + + display_config->stage3.pstate_switch_modes[plane_index] = dml2_pstate_method_alternate; + } + } +} static void setup_planes_for_drr_by_mask(struct display_configuation_with_meta *display_config, struct dml2_pmo_instance *pmo, @@ -2168,6 +2223,8 @@ static bool setup_display_config(struct display_configuation_with_meta *display_ } else if (scratch->pmo_dcn4.pstate_strategy_candidates[strategy_index].per_stream_pstate_method[stream_index] == dml2_pstate_method_fw_drr) { fams2_required = true; setup_planes_for_drr_by_mask(display_config, pmo, scratch->pmo_dcn4.stream_plane_mask[stream_index]); + } else if (scratch->pmo_dcn4.pstate_strategy_candidates[strategy_index].per_stream_pstate_method[stream_index] == dml2_pstate_method_alternate) { + setup_planes_for_alternate_by_mask(display_config, pmo, scratch->pmo_dcn4.stream_plane_mask[stream_index]); } } diff --git a/drivers/gpu/drm/amd/display/dc/dml2_0/dml21/src/dml2_pmo/dml2_pmo_factory.c b/drivers/gpu/drm/amd/display/dc/dml2_0/dml21/src/dml2_pmo/dml2_pmo_factory.c index 21109a19f177..44438792931c 100644 --- a/drivers/gpu/drm/amd/display/dc/dml2_0/dml21/src/dml2_pmo/dml2_pmo_factory.c +++ b/drivers/gpu/drm/amd/display/dc/dml2_0/dml21/src/dml2_pmo/dml2_pmo_factory.c @@ -7,6 +7,8 @@ #include "dml2_pmo_dcn3.h" #include "dml2_pmo_dcn42.h" #include "dml2_external_lib_deps.h" +#include "dml2_pmo_dcn5.h" +#include "dml2_pmo_dcn6.h" static bool dummy_init_for_stutter(struct dml2_pmo_init_for_stutter_in_out *in_out) { @@ -94,6 +96,38 @@ bool dml2_pmo_create(enum dml2_project_id project_id, struct dml2_pmo_instance * out->optimize_for_stutter = pmo_dcn4_fams2_optimize_for_stutter; result = true; break; + case dml2_project_dcn5x_utm: + out->initialize = dml2_pmo_dcn5_initialize; + out->get_ordered_mandatory_stage_optimizers = dml2_pmo_dcn5_get_ordered_mandatory_stage_optimizers; + out->get_ordered_optional_stage_optimizers = dml2_pmo_dcn5_get_ordered_optional_stages_optimizers; + out->initialize_worksheet = dml2_pmo_dcn5_initialize_worksheet; + out->optional_sanity_check = dml2_pmo_dcn5_sanity_check; + out->convert_worksheet_to_solution = dml2_pmo_dcn5_convert_worksheet_to_solution; + out->clear_pre_validation_states = dml2_pmo_dcn5_clear_pre_validation_states; + result = true; + break; + case dml2_project_dcn6x_soc_var_a: + out->initialize = dml2_pmo_dcn6a_initialize; + out->get_ordered_mandatory_stage_optimizers = dml2_pmo_dcn6a_get_ordered_mandatory_stage_optimizers; + out->get_ordered_optional_stage_optimizers = dml2_pmo_dcn6a_get_ordered_optional_stages_optimizers; + out->initialize_worksheet = dml2_pmo_dcn5_initialize_worksheet; + out->optional_sanity_check = dml2_pmo_dcn5_sanity_check; + out->convert_worksheet_to_solution = dml2_pmo_dcn6_convert_worksheet_to_solution; + out->clear_pre_validation_states = dml2_pmo_dcn5_clear_pre_validation_states; + result = true; + break; + case dml2_project_dcn6x_soc_var_b: + out->initialize = dml2_pmo_dcn6b_initialize; + out->get_ordered_mandatory_stage_optimizers = dml2_pmo_dcn6b_get_ordered_mandatory_stage_optimizers; + out->get_ordered_optional_stage_optimizers = dml2_pmo_dcn6b_get_ordered_optional_stages_optimizers; + out->initialize_worksheet = dml2_pmo_dcn5_initialize_worksheet; + out->optional_sanity_check = dml2_pmo_dcn5_sanity_check; + out->convert_worksheet_to_solution = dml2_pmo_dcn6_convert_worksheet_to_solution; + out->clear_pre_validation_states = dml2_pmo_dcn5_clear_pre_validation_states; + result = true; + break; + case dml2_project_dcn4x_utm: + case dml2_project_dcn5x: case dml2_project_invalid: default: break; diff --git a/drivers/gpu/drm/amd/display/dc/dml2_0/dml21/src/dml2_top/dml2_top_interfaces.c b/drivers/gpu/drm/amd/display/dc/dml2_0/dml21/src/dml2_top/dml2_top_interfaces.c index 04860b6790df..aaca0a450f0e 100644 --- a/drivers/gpu/drm/amd/display/dc/dml2_0/dml21/src/dml2_top/dml2_top_interfaces.c +++ b/drivers/gpu/drm/amd/display/dc/dml2_0/dml21/src/dml2_top/dml2_top_interfaces.c @@ -5,6 +5,7 @@ #include "dml_top.h" #include "dml2_internal_shared_types.h" #include "dml2_top_soc15.h" +#include "dml2_top_utm.h" unsigned int dml2_get_instance_size_bytes(void) { @@ -19,6 +20,12 @@ bool dml2_initialize_instance(struct dml2_initialize_instance_in_out *in_out) case dml2_project_dcn4x_stage2_auto_drr_svp: case dml2_project_dcn42: return dml2_top_soc15_initialize_instance(in_out); + case dml2_project_dcn5x_utm: + case dml2_project_dcn6x_soc_var_a: + case dml2_project_dcn6x_soc_var_b: + return dml2_top_utm_initialize_instance(in_out); + case dml2_project_dcn4x_utm: + case dml2_project_dcn5x: case dml2_project_invalid: default: return false; diff --git a/drivers/gpu/drm/amd/display/dc/dml2_0/dml21/src/inc/dml2_internal_shared_types.h b/drivers/gpu/drm/amd/display/dc/dml2_0/dml21/src/inc/dml2_internal_shared_types.h index 3ae817ea2aad..a18f067fe53f 100644 --- a/drivers/gpu/drm/amd/display/dc/dml2_0/dml21/src/inc/dml2_internal_shared_types.h +++ b/drivers/gpu/drm/amd/display/dc/dml2_0/dml21/src/inc/dml2_internal_shared_types.h @@ -8,6 +8,9 @@ #include "dml2_external_lib_deps.h" #include "dml_top_types.h" #include "dml2_core_shared_types.h" +#include "bounding_boxes/utm_qos_model_dchub_v1.h" +#include "bounding_boxes/utm_qos_model_dchub_v2.h" +#include "bounding_boxes/utm_qos_model_dchub_v3.h" /* * DML2 MCG Types and Interfaces */ @@ -69,6 +72,153 @@ struct dml2_mcg_build_min_clock_table_params_in_out { */ struct dml2_mcg_min_clock_table *min_clk_table; }; + +struct dml2_soc_operating_point { + unsigned int uclk_khz; + unsigned int fclk_khz; + unsigned int dcfclk_khz; + unsigned int socclk_khz; +}; + +struct dml2_sop_constraint { + union { + struct { + unsigned int min_sop_index; + struct dml2_memory_path_latency latency; + struct dml2_soc_operating_point clocks; + double min_available_urgent_bandwidth_KBps; // minimum guaranteed urgent bandwidth at active + } dcn5; + }; +}; + +struct dml2_sop_table { + bool is_initialized; + const struct utm_qos_model *model; + uint32_t sop_min_available_urgent_bandwidths_KBps[MAX_UTM_SOP_COUNT]; + uint32_t sop_optimal_dcfclks_khz[MAX_UTM_SOP_COUNT]; + unsigned int (*get_highest_sop_index)(const struct dml2_sop_table *sop_table); + void (*get_sop_constraint_at_index)(const struct dml2_sop_table *sop_table, unsigned int index, struct dml2_sop_constraint *constraint); + bool (*is_bw_supported_at_index)(const struct dml2_sop_table *sop_table, const struct dml2_memory_path_bandwidth *bw, unsigned int index); + void (*get_max_sop)(const struct dml2_sop_table *sop_table, struct dml2_soc_operating_point *sop); + void (*get_min_sop)(const struct dml2_sop_table *sop_table, struct dml2_soc_operating_point *sop); +}; + +struct dml2_utm_soc_bb { + struct dml2_sop_table sop_table; + struct dml2_soc_power_management_parameters power_management_parameters; + struct dml2_soc_vmin_clock_limits vmin_limit; + struct dml2_dram_params dram_config; + struct utm_qos_model qos_model; + union { + struct utm_qos_model_dchub_v1 qos_model_dchub_v1; + struct utm_qos_model_dchub_v2 qos_model_dchub_v2; + struct utm_qos_model_dchub_v3 qos_model_dchub_v3; + }; + double lower_bound_bandwidth_dchub; + double fraction_of_urgent_bandwidth_nominal_target; + double fraction_of_urgent_bandwidth_flip_target; + unsigned int dchub_refclk_mhz; + unsigned int max_outstanding_reqs; + unsigned long return_bus_width_bytes; + double phy_downspread_percent; + double dcn_downspread_percent; + double nominal_sdp_derate_percent; + double urgent_sdp_derate_percent; + double dispclk_dppclk_vco_speed_mhz; + bool no_dfs; + unsigned int mem_word_bytes; + unsigned int num_dcc_mcaches; + unsigned int mcache_size_bytes; + unsigned int mcache_line_size_bytes; + unsigned int writeback_base_latency_us; + unsigned int max_dispclk_khz; + unsigned int max_dppclk_khz; + unsigned int max_dscclk_khz; + unsigned int max_dtbclk_khz; + unsigned int max_phyclk_khz; + unsigned int max_phyclk_d18_khz; + unsigned int max_phyclk_d32_khz; + unsigned int min_socclk_khz; + unsigned int max_dcfclk_khz; + unsigned int min_dcfclk_khz; + /* TODO: remove once DML Core no longer depends on max SOP clocks */ + unsigned int max_uclk_khz; + unsigned int max_fclk_khz; +}; + +struct dml2_clock_granularity_adjuster; +struct dml2_cga_initialize_in_out { + struct dml2_clock_granularity_adjuster *adjuster; + const struct dml2_soc_bb *soc_bb; + const struct dml2_core_ip_params *ip; +}; + +struct dml2_clock_granularity_adjuster { + double dcn_downspread_percent; + double dispclk_dppclk_vco_speed_mhz; + double dispclk_ramp_margin_percent; + double max_dispclk_mhz; + void (*initialize)(const struct dml2_cga_initialize_in_out *in_out); + double (*adjust_dispclk_mhz)(const struct dml2_clock_granularity_adjuster *adjuster, double dispclk_mhz); + void (*adjust_dppclks_mhz)(const struct dml2_clock_granularity_adjuster *adjuster, unsigned int count, + const double *dppclks_mhz, double *adjusted_dppclks_mhz, double *adjusted_dpprefclk_mhz); + void (*adjust_dtbclks_mhz)(const struct dml2_clock_granularity_adjuster *adjuster, unsigned int count, + const double *dtbclks_mhz, double *adjusted_dtbclks_mhz, double *adjusted_dtbrefclk_mhz); + double (*adjust_dcfclk_deepsleep_mhz)(const struct dml2_clock_granularity_adjuster *adjuster, + double dcfclk_deepsleep_mhz); +}; + +#define DML2_STATUS_LIST(FORMAT) \ + /* Generic */ \ + FORMAT(DML2_STATUS_OK) \ + FORMAT(DML2_STATUS_UNKNOWN) \ + /* Validate */ \ + FORMAT(DML2_STATUS_VALIDATE_FAIL_MODE_SUPPORT) \ + FORMAT(DML2_STATUS_VALIDATE_FAIL_MODE_SUPPORT_PREFETCH) \ + FORMAT(DML2_STATUS_VALIDATE_FAIL_MODE_SUPPORT_PREFETCH_URGENT) \ + FORMAT(DML2_STATUS_VALIDATE_FAIL_MODE_SUPPORT_QOS_BANDWIDTH) \ + FORMAT(DML2_STATUS_VALIDATE_FAIL_MODE_SUPPORT_DCFCLK) \ + FORMAT(DML2_STATUS_VALIDATE_FAIL_PREFETCH) \ + FORMAT(DML2_STATUS_VALIDATE_FAIL_MCACHE) \ + FORMAT(DML2_STATUS_VALIDATE_FAIL_PMO_SANITY_TOTAL_PIPE_USAGE) \ + FORMAT(DML2_STATUS_VALIDATE_FAIL_PMO_SANITY_ODM_DIVISIBILITY) \ + FORMAT(DML2_STATUS_VALIDATE_FAIL_PSTATE_SCHEDULE) \ + FORMAT(DML2_STATUS_PSTATE_UNEXPECTED_PSTATE) \ + FORMAT(DML2_STATUS_PSTATE_NOT_ADMISSIBLE) \ + /* Optimize */ \ + FORMAT(DML2_STATUS_OPTIMIZE_FAIL_MCACHE) \ + FORMAT(DML2_STATUS_OPTIMIZE_FAIL_UCLK_PSTATE) \ + FORMAT(DML2_STATUS_OPTIMIZE_FAIL_QOS) \ + FORMAT(DML2_STATUS_OPTIMIZE_FAIL_VMIN) \ + FORMAT(DML2_STATUS_OPTIMIZE_FAIL_STUTTER) \ + FORMAT(DML2_STATUS_OPTIMIZE_FAIL_FCLK_PSTATE_UNSYNCHRONIZABLE_TIMINGS) \ + FORMAT(DML2_STATUS_OPTIMIZE_FAIL_FCLK_PSTATE_INSUFFICENT_HIDING) \ + FORMAT(DML2_STATUS_OPTIMIZE_FAIL_VMIN_DCFCLK) \ + FORMAT(DML2_STATUS_OPTIMIZE_FAIL_EXCEED_MAX_ITERATION) \ + /* Populate */ \ + FORMAT(DML2_STATUS_POPULATE_FAIL_MIN_CLOCK_STATE) \ + FORMAT(DML2_STATUS_POPULATE_FAIL_PROGRAMMING) \ + FORMAT(DML2_STATUS_POPULATE_FAIL_PROGRAMMING_PREFETCH) \ + FORMAT(DML2_STATUS_POPULATE_FAIL_PROGRAMMING_PREFETCH_URGENT) \ + FORMAT(DML2_STATUS_POPULATE_FAIL_PROGRAMMING_FLIP_BANDWIDTH) \ + FORMAT(DML2_STATUS_POPULATE_FAIL_PROGRAMMING_DCFCLK) + +#define ENUM_FORMAT(entry) entry, +#define CASE_FORMAT(entry) case entry: return #entry; + +enum dml2_status { + DML2_STATUS_LIST(ENUM_FORMAT) +}; + +static inline const char *dml2_status_str(enum dml2_status status) +{ + switch (status) { + DML2_STATUS_LIST(CASE_FORMAT) + } + + return ""; +} + struct dml2_mcg_instance { bool (*build_min_clock_table)(struct dml2_mcg_build_min_clock_table_params_in_out *in_out); }; @@ -85,6 +235,8 @@ struct dml2_dpmm_map_mode_to_soc_dpm_params_in_out { struct dml2_soc_bb *soc_bb; struct dml2_mcg_min_clock_table *min_clk_table; const struct display_configuation_with_meta *display_cfg; + const struct dml2_utm_soc_bb *utm_soc_bb; + const struct dml2_display_solution *solution; struct { bool perform_pseudo_map; struct dml2_core_internal_soc_bb *soc_bb; @@ -101,6 +253,7 @@ struct dml2_dpmm_map_watermarks_params_in_out { * Input */ const struct display_configuation_with_meta *display_cfg; + const struct dml2_display_solution *solution; const struct dml2_core_instance *core; /* @@ -131,6 +284,8 @@ struct dml2_core_initialize_in_out { struct dml2_ip_capabilities *ip_caps; struct dml2_mcg_min_clock_table *minimum_clock_table; + const struct dml2_utm_soc_bb *utm_soc_bb; + const struct dml2_clock_granularity_adjuster *clock_adjuster; void *explicit_ip_bb; unsigned int explicit_ip_bb_size; @@ -169,6 +324,11 @@ struct core_stream_support_info { int vblank_reserved_time_us; int num_dsc_slices; bool dsc_enable; + unsigned int alternate_svp0_dst_lines; + unsigned int alternate_svp1_dst_lines; + unsigned int max_vstartup_lines; + unsigned int max_dst_y_after_scaler; + unsigned int max_dst_y_prefetch; }; struct core_display_cfg_support_info { @@ -210,6 +370,9 @@ struct dml2_core_mode_support_result { unsigned int uclk_pstate_supported; unsigned int fclk_pstate_supported; + unsigned int alternate_total_bytes_copy_svp0; + unsigned int alternate_total_bytes_copy_svp1; + unsigned int lsdma_bw_req_for_alt_kbps; struct dml2_core_internal_watermarks watermarks; } global; @@ -226,6 +389,7 @@ struct dml2_core_mode_support_result { } per_plane[DML2_MAX_PLANES]; struct core_display_cfg_support_info cfg_support_info; + struct dml2_memory_path_bandwidth bandwidth_upper_bound; }; struct dml2_optimization_stage1_state { @@ -305,6 +469,11 @@ struct dml2_pstate_meta { unsigned long phantom_vtotal; struct dml2_pstate_per_method_common_meta common; } method_subvp; + struct { + int programming_delay_otg_vlines; // DMCUB <-> PMFW delays + any DMCUB/PMFW programming delays required + int pmfw_throttle_delay_otg_vlines; // PMFW time it takes to throttle other clients + assert DF P-State allow + struct dml2_pstate_per_method_common_meta common; + } method_alternate; struct { int programming_delay_otg_vlines; int stretched_vtotal; @@ -379,6 +548,203 @@ struct dml2_pmo_pstate_strategy { enum dml2_pstate_method per_stream_pstate_method[DML2_MAX_PLANES]; bool allow_state_increase; }; + +struct dml2_validation_result { + bool is_mode_support_valid; + bool is_prefetch_valid; + struct dml2_core_mode_support_result mode_support; + bool is_mcache_allocation_valid; + struct dml2_mcache_surface_allocation mcache_allocations[DML2_MAX_PLANES]; +}; + +struct dml2_optimization_change { + union { + struct { + bool sop_index : 1; // bit 0 + bool mpc_combine_overrides : 1; + bool odm_combine_overrides : 1; + bool reserved_vblank_time : 1; + bool mcache_allocation : 1; + bool uclk_pstate_method : 1; + bool fclk_pstate_support : 1; + bool stutter_support : 1; + bool dcfclk_override : 1; // bit 8 + bool ppt_temp_read_pstate_support : 1; + unsigned char reserved : 6; + } bits; + unsigned short raw; + }; +}; + +struct dml2_optimization_worksheet { + const struct dml2_display_cfg *orig_dispcfg; + + unsigned int timing_group_ids[DML2_MAX_PLANES]; // per plane + unsigned int timing_group_count; + + struct { + bool is_default_pipe_usage_attempted; + bool is_single_stream_odm_case; + bool per_plane_status[DML2_MAX_PLANES]; + struct { + int pipe_vp_startx[DML2_MAX_DCN_PIPES]; + int pipe_vp_endx[DML2_MAX_DCN_PIPES]; + } plane0; + struct { + int pipe_vp_startx[DML2_MAX_DCN_PIPES]; + int pipe_vp_endx[DML2_MAX_DCN_PIPES]; + } plane1; + } mcache; + + struct { + unsigned int stream_plane_mask[DML2_MAX_PLANES]; + + struct dml2_pstate_meta stream_pstate_meta[DML2_MAX_PLANES]; // per stream + + // Meta-data for implicit SVP generation, indexed by stream index + struct dml2_implicit_svp_meta stream_svp_meta[DML2_MAX_PLANES]; + + struct dml2_pmo_pstate_strategy pstate_strategy_candidates[DML2_PMO_PSTATE_CANDIDATE_LIST_SIZE]; + int num_pstate_candidates; + int cur_pstate_candidate; + + // Initial value of reserved vblank time as pstate optimize may overwrite and clear current + long init_reserved_vblank_time_ns[DML2_MAX_PLANES]; + unsigned int init_max_vactive_det_fill_delay_us[DML2_MAX_PLANES]; // per plane + } uclk_pstate; + + struct { + bool is_initialized; + bool unoptimizable_streams[DML2_MAX_DCN_PIPES]; + unsigned int init_odms_used[DML2_MAX_DCN_PIPES]; + } vmin; + + struct { + long init_reserved_vblank_time_ns[DML2_MAX_PLANES]; + bool should_optimize_z8_stutter; + bool is_z8_stutter_attempted; + bool should_optimize_stutter; + bool is_stutter_attempted; + } stutter; + + struct { + unsigned int passing_index; + unsigned int failing_index; + bool is_index0_tested; + } qos; + + struct { + double max_available_bandwidth_kbps; + } dcfclk_vmin; + + struct { + bool is_attempted; + } fclk_ppt_temp_read_pstate; + + /* + * unified structure for storing current optimization tuning variables. Please only store the final tuning knobs + * we should see exactly what will be optimized in display solution at a quick glance. + */ + struct dml2_optimization_config { + struct { + unsigned int min_sop_index; + unsigned int mpc_combine_overrides[DML2_MAX_PLANES]; // per plane + unsigned int odm_combine_overrides[DML2_MAX_PLANES]; // per stream + long reserved_vblank_time_ns[DML2_MAX_PLANES]; + struct dml2_mcache_surface_allocation mcache_allocations[DML2_MAX_PLANES]; + + bool uclk_pstate_support; + enum dml2_pstate_method uclk_pstate_switch_modes[DML2_MAX_PLANES]; // per plane + int max_vactive_det_fill_delay_us[DML2_MAX_PLANES][dml2_pstate_type_count]; // per plane + // Meta-data for FAMS2 + bool fams2_required; + bool legacy_pstate_info_for_dmu; + struct dml2_pstate_meta stream_pstate_meta[DML2_MAX_PLANES]; // per stream + bool fclk_pstate_support; + bool ppt_temp_read_support; + bool stutter_support_in_vblank; + bool z8_stutter_support_in_vblank; + bool enable_vmin_dcfclk; + } config; + /* changes that have not yet been validated */ + struct dml2_optimization_change unvalidated_change; + } cur; + + /* post validation */ + struct dml2_validation_result validation_result; +}; + +struct dml2_display_solution { + const struct dml2_display_cfg *orig_dispcfg; + + /* current display configuration */ + struct dml2_display_cfg dispcfg; + unsigned int timing_group_ids[DML2_MAX_PLANES]; // per plane + unsigned int timing_group_count; + + /* additional DML internally decided configurations */ + struct dml2_sop_constraint sop_constraint; + struct dml2_mcache_surface_allocation mcache_allocations[DML2_MAX_PLANES]; + struct dml2_uclk_pstate_params { + bool support; + /* Uclk pstate related*/ + enum dml2_pstate_method pstate_switch_modes[DML2_MAX_PLANES]; + // Meta-data for FAMS2 + bool fams2_required; + bool legacy_pstate_info_for_dmu; + struct dml2_pstate_meta stream_pstate_meta[DML2_MAX_PLANES]; // per stream + } uclk_pstate_params; + bool fclk_pstate_support; + bool ppt_temp_read_support; + bool stutter_support_in_vblank; + bool z8_stutter_support_in_vblank; + + /* pre-validation states */ + struct dml2_optimization_change unvalidated_change; + + /* post validation */ + struct dml2_validation_result validation_result; +}; + +struct dml2_pmo_stage_optimizer { + const struct dml2_pmo_instance *pmo; + /* + * to optimize stack memory usage, large local variables are pre-allocated in this heap memory. The scope of + * func_locals is bounded by each optimizer's function defined in the union. To share states across an + * optimizer's functions, define it in the dedicated optimizer state in optimization worksheet. + */ + union dml2_stage_optimizer_function_locals *func_locals; + /* + * init interface builds the initial states associated with the current stage optimizer into the worksheet. It + * is for state initialization only. It should not apply new optimization or cause changes to current validation + * result. It is safe to assume that the worksheet passed in or exited from this interface is always validated. + */ + void (*init)(struct dml2_pmo_stage_optimizer *stage, struct dml2_optimization_worksheet *worksheet); + /* + * optimize_next interface controls current optimization's stop conditions. When the interface returns false, it + * means the stage optimizer no longer needs to attempt further optimization. The current worksheet should be + * left unmodified. When the interface returns true, it means the stage optimizer applied new optimization to + * the worksheet. DML top will need to validate and test permissibility again. The worksheet passed in is based + * off the optimization decision from last attempt. It may or may not be validated or permissible. It is upto + * DML top to keep track of the last valid permissible worksheet. This interface is also responsible to clear + * corresponding valid bits in worksheet's validation result based on what optimization it gets applied. When + * the valid bits are cleared, it will be revalidated by top. Otherwise, DML top will assume it is safe to skip + * certain re-validations based on the remaining valid bits. Stage optimizers should clear only the necessary + * valid bits based on the optimization applied to speed up the process. + */ + bool (*optimize_next)(struct dml2_pmo_stage_optimizer *stage, struct dml2_optimization_worksheet *worksheet); + /* + * test_permissibility interface should only check against current optimizer policy specific + * minimum requirements. Test permissibility result is orthogonal to validation result. It is + * safe to assume the worksheet constant passed in is always validated. The interface checks if + * the validated result fulfills the minimum requirements additionally imposed by current stage + * optimizer in order to consider the current optimization as a potential candidate. Stage + * optimizer may still attempt further optimization even if the current one is permissible. + */ + enum dml2_status (*test_permissibility)(struct dml2_pmo_stage_optimizer *stage, + const struct dml2_optimization_worksheet *worksheet); +}; + struct dml2_core_mode_support_in_out { /* * Inputs @@ -464,9 +830,27 @@ struct dml2_core_internal_state_intermediates { unsigned int dummy; }; +struct dml2_core_calculate_mp_context { + const struct dml2_display_cfg *display_cfg; + const struct dml2_core_ip_params *ip; + const struct dml2_utm_soc_bb *soc_bb; + const struct dml2_core_internal_mode_support *ms; + struct dml2_core_calcs_mode_programming_locals *dummies; + struct dml2_core_internal_scratch *func_params; +}; +struct dml2_core_calculate_ms_context { + const struct dml2_display_cfg *display_cfg; + const struct dml2_core_ip_params *ip; + const struct dml2_utm_soc_bb *soc_bb; + const struct dml2_clock_granularity_adjuster *clock_adjuster; + struct dml2_core_calcs_mode_support_locals *dummies; + struct dml2_core_internal_scratch *func_params; +}; + struct dml2_core_mode_support_locals { union { struct dml2_core_calcs_mode_support_ex mode_support_ex_params; + struct dml2_core_calculate_ms_context calc_ms_ctx; }; struct dml2_display_cfg svp_expanded_display_cfg; struct dml2_calculate_mcache_allocation_in_out calc_mcache_allocation_params; @@ -475,8 +859,10 @@ struct dml2_core_mode_support_locals { struct dml2_core_mode_programming_locals { union { struct dml2_core_calcs_mode_programming_ex mode_programming_ex_params; + struct dml2_core_calculate_mp_context calc_mp_ctx; }; struct dml2_display_cfg svp_expanded_display_cfg; + struct dml2_validation_result temp_result; }; struct dml2_core_scratch { @@ -490,6 +876,8 @@ struct dml2_core_scratch { struct dml2_core_instance { struct dml2_mcg_min_clock_table *minimum_clock_table; + const struct dml2_utm_soc_bb *utm_soc_bb; + const struct dml2_clock_granularity_adjuster *clock_adjuster; struct dml2_core_internal_state_inputs inputs; struct dml2_core_internal_state_intermediates intermediates; @@ -497,6 +885,12 @@ struct dml2_core_instance { bool (*initialize)(struct dml2_core_initialize_in_out *in_out); bool (*mode_support)(struct dml2_core_mode_support_in_out *in_out); + enum dml2_status (*validate_solution)(struct dml2_core_instance *core, + const struct dml2_display_solution *solution, + struct dml2_validation_result *validation_result); + enum dml2_status (*populate_programming)(struct dml2_core_instance *core, + const struct dml2_display_solution *solution, + struct dml2_display_cfg_programming *programming); bool (*mode_programming)(struct dml2_core_mode_programming_in_out *in_out); bool (*populate_informative)(struct dml2_core_populate_informative_in_out *in_out); bool (*calculate_mcache_allocation)(struct dml2_calculate_mcache_allocation_in_out *in_out); @@ -520,6 +914,7 @@ struct dml2_pmo_initialize_in_out { struct dml2_ip_capabilities *ip_caps; struct dml2_pmo_options *options; int mcg_clock_table_size; + const struct dml2_utm_soc_bb *utm_soc_bb; }; struct dml2_pmo_optimize_dcc_mcache_in_out { @@ -692,6 +1087,35 @@ struct dml2_pmo_scratch { unsigned int sorted_group_gtl_period_index[DML2_MAX_PLANES]; double group_phase_offset[DML2_MAX_PLANES]; } pmo_dcn4; + struct { + union dml2_stage_optimizer_function_locals { + struct dml2_stage_optimizer_uclk_pstate_init_locals { + double allow_delay_us; + double blackout_us; + double watermark_us; + + unsigned int stream_vactive_capability_mask; + + struct dml2_pmo_pstate_strategy expanded_override_strategy_list[2 * 2 * 2 * 2]; + unsigned int num_expanded_override_strategies; + + /* mask of synchronized timings by stream index */ + struct dml2_pmo_synchronized_timing_groups synchronized_timing_groups; + + /* scheduling check locals */ + struct dml2_scheduling_check_locals scheduling_check_locals; + } uclk_pstate_init; + struct dml2_stage_optimizer_fclk_ppt_temp_read_pstate_optimize_locals { + double pstate_blackout_us; + double pstate_watermark_us; + double pstate_allow_delay_us; + + struct dml2_pstate_meta per_stream_pstate_meta[DML2_MAX_PLANES]; + enum dml2_pstate_method per_stream_pstate_method[DML2_MAX_PLANES]; + struct dml2_scheduling_check_locals scheduling_check_locals; + } fclk_ppt_temp_read_pstate_optimize; + } func_locals; + } pmo_dcn5; }; }; @@ -708,6 +1132,18 @@ struct dml2_pmo_init_data { }; }; +enum dml2_pmo_stage_index { + dml2_pmo_stage_index_start = 0, + dml2_pmo_stage_index_mcache = dml2_pmo_stage_index_start, + dml2_pmo_stage_index_uclk_pstate, + dml2_pmo_stage_index_qos, + dml2_pmo_stage_index_vmin, + dml2_pmo_stage_index_stutter, + dml2_pmo_stage_index_vmin_dcfclk, + dml2_pmo_stage_index_fclk_ppt_temp_read_pstate, + dml2_pmo_stage_index_max, +}; + struct dml2_pmo_instance { struct dml2_soc_bb *soc_bb; struct dml2_ip_capabilities *ip_caps; @@ -718,6 +1154,7 @@ struct dml2_pmo_instance { int mpc_combine_limit; int odm_combine_limit; int mcg_clock_table_size; + const struct dml2_utm_soc_bb *utm_soc_bb; union { struct { struct { @@ -754,9 +1191,52 @@ struct dml2_pmo_instance { bool (*test_for_stutter)(struct dml2_pmo_test_for_stutter_in_out *in_out); bool (*optimize_for_stutter)(struct dml2_pmo_optimize_for_stutter_in_out *in_out); + /* + * obtain a list of mandatory stage optimizers ordered by priority. Caller must perform stage optimization in + * the same order. + * return - stage optimizer count + */ + int (*get_ordered_mandatory_stage_optimizers)(struct dml2_pmo_instance *pmo, + struct dml2_pmo_stage_optimizer **optimers); + /* + * obtain a list of option stage optimizers ordered by priority, Caller must perform stage optimization in the + * same order. Caller must complete stage optimization for all mandatory stage optimizers before performing + * optional stage optimization. + * return - stage optimizer count + */ + int (*get_ordered_optional_stage_optimizers)(struct dml2_pmo_instance *pmo, + struct dml2_pmo_stage_optimizer **optimers); + /* + * initialize an optimization worksheet based on the display config passed in. + */ + void (*initialize_worksheet)(struct dml2_pmo_instance *pmo, + const struct dml2_display_cfg *dispcfg, + struct dml2_optimization_worksheet *worksheet); + /* + * convert an optimization worksheet to a display solution. + */ + void (*convert_worksheet_to_solution)(struct dml2_pmo_instance *pmo, + const struct dml2_optimization_worksheet *worksheet, + struct dml2_display_solution *solution); + /* + * when validation is completed with an updated worksheet's validation result, PMO needs to reset pre validation + * states stored in worksheet. + */ + void (*clear_pre_validation_states)(struct dml2_pmo_instance *pmo, + struct dml2_optimization_worksheet *worksheet); + /* + * perform a mini validate solution to rule out common optimization config problems after optimize_next is + * called. This interface is a performance optimization to avoid of performing expensive full validate solution + * for common optimization problems. It also generalizes sanity check for all stage optimizers. So the concern + * of sanity check optimization config is isolated out of each stage optimizer. + */ + enum dml2_status (*optional_sanity_check)(struct dml2_pmo_instance *pmo, + const struct dml2_optimization_worksheet *worksheet); + struct dml2_pmo_init_data init_data; struct dml2_pmo_scratch scratch; + struct dml2_pmo_stage_optimizer stage_optimizers[dml2_pmo_stage_index_max]; }; /* @@ -993,6 +1473,8 @@ struct dml2_instance { struct dml2_ip_capabilities ip_caps; struct dml2_mcg_min_clock_table min_clk_table; + struct dml2_utm_soc_bb utm_soc_bb; + struct dml2_clock_granularity_adjuster clock_adjuster; struct dml2_pmo_options pmo_options; struct dml2_top_funcs funcs; @@ -1002,6 +1484,9 @@ struct dml2_instance { struct dml2_top_mcache_validate_admissability_locals mcache_validate_admissability_locals; struct dml2_check_mode_supported_locals check_mode_supported_locals; struct dml2_build_mode_programming_locals build_mode_programming_locals; + struct dml2_optimization_worksheet worksheet; + struct dml2_optimization_worksheet worksheet_backup; + struct dml2_display_solution solution; } scratch; struct { diff --git a/drivers/gpu/drm/amd/display/dc/dml2_0/dml2_wrapper.h b/drivers/gpu/drm/amd/display/dc/dml2_0/dml2_wrapper.h index 2f2ae05dd59c..68ae013b026e 100644 --- a/drivers/gpu/drm/amd/display/dc/dml2_0/dml2_wrapper.h +++ b/drivers/gpu/drm/amd/display/dc/dml2_0/dml2_wrapper.h @@ -55,6 +55,12 @@ struct dml2_soc_mall_info { unsigned int mblk_height_8bpe_pixels; }; +struct dml2_soc_alt_ch_info { + unsigned int region_size_bytes[2]; + /* bits 47:16 of the base address */ + unsigned int region_base_addr_47_16[2]; +}; + // Output of DML2 for clock requirements struct dml2_dcn_clocks { unsigned int dispclk_khz; @@ -204,6 +210,7 @@ enum dml2_force_pstate_methods { dml2_force_pstate_method_vblank, dml2_force_pstate_method_drr, dml2_force_pstate_method_subvp, + dml2_force_pstate_method_alternate, }; struct dml2_configuration_options { @@ -226,6 +233,7 @@ struct dml2_configuration_options { struct dml2_dc_svp_callbacks callbacks; } svp_pstate; struct dml2_soc_mall_info mall_cfg; + struct dml2_soc_alt_ch_info alt_ch_cfg; struct dml2_soc_bbox_overrides bbox_overrides; unsigned int max_segments_per_hubp; unsigned int det_segment_size; diff --git a/drivers/gpu/drm/amd/display/dc/dpp/dcn401/dcn401_dpp.h b/drivers/gpu/drm/amd/display/dc/dpp/dcn401/dcn401_dpp.h index debcf308cb3b..a57eb1cd77a6 100644 --- a/drivers/gpu/drm/amd/display/dc/dpp/dcn401/dcn401_dpp.h +++ b/drivers/gpu/drm/amd/display/dc/dpp/dcn401/dcn401_dpp.h @@ -749,4 +749,45 @@ void dpp401_set_cursor_matrix( enum dc_color_space color_space, struct dc_csc_transform cursor_csc_color_matrix); +enum dcn401_dscl_mode_sel dpp401_dscl_get_dscl_mode( + struct dpp *dpp_base, + const struct scaler_data *data, + bool dbg_always_scale); + +void dpp401_power_on_dscl( + struct dpp *dpp_base, + bool power_on); + +void dpp401_dscl_set_recout( + struct dcn401_dpp *dpp, + const struct rect *recout); + +enum lb_memory_config dpp401_dscl_find_lb_memory_config( + struct dcn401_dpp *dpp, + const struct scaler_data *scl_data); + +void dpp401_dscl_program_isharp( + struct dpp *dpp_base, + const struct scaler_data *scl_data, + bool program_isharp_1dlut, + bool *bs_coeffs_updated); + +void dpp401_dscl_set_isharp_filter( + struct dcn401_dpp *dpp, + const uint32_t *filter); + +void dpp401_dscl_set_scl_filter( + struct dcn401_dpp *dpp, + const struct scaler_data *scl_data, + bool chroma_coef_mode, + bool force_coeffs_update); + +void dpp401_dscl_disable_easf( + struct dpp *dpp_base, + const struct scaler_data *scl_data); + +void dpp401_dscl_program_easf( + struct dpp *dpp_base, + const struct scaler_data *scl_data); + #endif /* __DCN401_DPP_H__ */ diff --git a/drivers/gpu/drm/amd/display/dc/dpp/dcn401/dcn401_dpp_dscl.c b/drivers/gpu/drm/amd/display/dc/dpp/dcn401/dcn401_dpp_dscl.c index e0ee00c955bc..81f287c89562 100644 --- a/drivers/gpu/drm/amd/display/dc/dpp/dcn401/dcn401_dpp_dscl.c +++ b/drivers/gpu/drm/amd/display/dc/dpp/dcn401/dcn401_dpp_dscl.c @@ -112,7 +112,7 @@ static bool dpp401_dscl_is_420_format(enum dc_pixel_format format) return false; } -static enum dcn401_dscl_mode_sel dpp401_dscl_get_dscl_mode( +enum dcn401_dscl_mode_sel dpp401_dscl_get_dscl_mode( struct dpp *dpp_base, const struct scaler_data *data, bool dbg_always_scale) @@ -146,7 +146,7 @@ static enum dcn401_dscl_mode_sel dpp401_dscl_get_dscl_mode( return DCN401_DSCL_MODE_SCALING_420_YCBCR_ENABLE; } -static void dpp401_power_on_dscl( +void dpp401_power_on_dscl( struct dpp *dpp_base, bool power_on) { @@ -273,7 +273,7 @@ static void dpp401_dscl_set_scaler_filter( } -static void dpp401_dscl_set_scl_filter( +void dpp401_dscl_set_scl_filter( struct dcn401_dpp *dpp, const struct scaler_data *scl_data, bool chroma_coef_mode, @@ -468,7 +468,7 @@ static bool dpp401_dscl_is_lb_conf_valid(int ceil_vratio, int num_partitions, in } /*find first match configuration which meets the min required lb size*/ -static enum lb_memory_config dpp401_dscl_find_lb_memory_config(struct dcn401_dpp *dpp, +enum lb_memory_config dpp401_dscl_find_lb_memory_config(struct dcn401_dpp *dpp, const struct scaler_data *scl_data) { int num_part_y, num_part_c; @@ -637,8 +637,8 @@ static void dpp401_dscl_set_manual_ratio_init( * * Note: This function only have effect if AutoCal is disabled. */ -static void dpp401_dscl_set_recout(struct dcn401_dpp *dpp, - const struct rect *recout) +void dpp401_dscl_set_recout(struct dcn401_dpp *dpp, + const struct rect *recout) { REG_SET_2(RECOUT_START, 0, /* First pixel of RECOUT in the active OTG area */ @@ -881,7 +881,7 @@ static void dpp401_dscl_program_easf_h(struct dpp *dpp_base, const struct scaler * This is the primary function to program EASF * */ -static void dpp401_dscl_program_easf(struct dpp *dpp_base, const struct scaler_data *scl_data) +void dpp401_dscl_program_easf(struct dpp *dpp_base, const struct scaler_data *scl_data) { struct dcn401_dpp *dpp = TO_DCN401_DPP(dpp_base); @@ -910,7 +910,7 @@ static void dpp401_dscl_program_easf(struct dpp *dpp_base, const struct scaler_d * When we have 1:1 scaling, we need to disable EASF * */ -static void dpp401_dscl_disable_easf(struct dpp *dpp_base, const struct scaler_data *scl_data) +void dpp401_dscl_disable_easf(struct dpp *dpp_base, const struct scaler_data *scl_data) { struct dcn401_dpp *dpp = TO_DCN401_DPP(dpp_base); @@ -923,7 +923,7 @@ static void dpp401_dscl_disable_easf(struct dpp *dpp_base, const struct scaler_d SCL_EASF_H_EN, scl_data->dscl_prog_data.easf_h_en); PERF_TRACE(); } -static void dpp401_dscl_set_isharp_filter( +void dpp401_dscl_set_isharp_filter( struct dcn401_dpp *dpp, const uint32_t *filter) { int level; @@ -953,10 +953,10 @@ static void dpp401_dscl_set_isharp_filter( * This is the primary function to program isharp * */ -static void dpp401_dscl_program_isharp(struct dpp *dpp_base, - const struct scaler_data *scl_data, - bool program_isharp_1dlut, - bool *bs_coeffs_updated) +void dpp401_dscl_program_isharp(struct dpp *dpp_base, + const struct scaler_data *scl_data, + bool program_isharp_1dlut, + bool *bs_coeffs_updated) { struct dcn401_dpp *dpp = TO_DCN401_DPP(dpp_base); *bs_coeffs_updated = false; diff --git a/drivers/gpu/drm/amd/display/dc/dpp/dcn42/dcn42_dpp.c b/drivers/gpu/drm/amd/display/dc/dpp/dcn42/dcn42_dpp.c index f60e084068c8..eed86f5ae731 100644 --- a/drivers/gpu/drm/amd/display/dc/dpp/dcn42/dcn42_dpp.c +++ b/drivers/gpu/drm/amd/display/dc/dpp/dcn42/dcn42_dpp.c @@ -35,10 +35,7 @@ static const uint32_t *get_hist_rgb_luma_coefs(enum dc_color_space color_space) } } -static void dpp42_dpp_cm_hist_control( - struct dpp *dpp_base, - struct cm_hist_control cntl, - enum dc_color_space color_space) +void dpp42_dpp_cm_hist_control(struct dpp *dpp_base, struct cm_hist_control cntl, enum dc_color_space color_space) { struct dcn42_dpp *dpp = TO_DCN42_DPP(dpp_base); @@ -68,7 +65,7 @@ static void dpp42_dpp_cm_hist_control( } } -static bool dpp42_dpp_cm_hist_read(struct dpp *dpp_base, struct cm_hist *hist_out) +bool dpp42_dpp_cm_hist_read(struct dpp *dpp_base, struct cm_hist *hist_out) { struct dcn42_dpp *dpp = TO_DCN42_DPP(dpp_base); uint32_t channel_mask = 0; diff --git a/drivers/gpu/drm/amd/display/dc/dpp/dcn42/dcn42_dpp.h b/drivers/gpu/drm/amd/display/dc/dpp/dcn42/dcn42_dpp.h index f4ee419eabf7..76e2ab10a3a0 100644 --- a/drivers/gpu/drm/amd/display/dc/dpp/dcn42/dcn42_dpp.h +++ b/drivers/gpu/drm/amd/display/dc/dpp/dcn42/dcn42_dpp.h @@ -465,5 +465,11 @@ bool dpp42_construct(struct dcn42_dpp *dpp42, const struct dcn42_dpp_shift *tf_shift, const struct dcn42_dpp_mask *tf_mask); +void dpp42_dpp_cm_hist_control(struct dpp *dpp_base, + struct cm_hist_control cntl, + enum dc_color_space color_space); + +bool dpp42_dpp_cm_hist_read(struct dpp *dpp_base, + struct cm_hist *hist_out); #endif /* __DCN42_DPP_H__ */ diff --git a/drivers/gpu/drm/amd/display/dc/gpio/ddc_regs.h b/drivers/gpu/drm/amd/display/dc/gpio/ddc_regs.h index 4a2bf81286d8..8de9a889886a 100644 --- a/drivers/gpu/drm/amd/display/dc/gpio/ddc_regs.h +++ b/drivers/gpu/drm/amd/display/dc/gpio/ddc_regs.h @@ -125,6 +125,8 @@ struct ddc_registers { uint32_t ddc_setup; uint32_t phy_aux_cntl; uint32_t dc_gpio_aux_ctrl_5; + uint32_t dc_i3cpad_control0; + uint32_t dc_i3cpad_control1; }; struct ddc_sh_mask { @@ -142,6 +144,19 @@ struct ddc_sh_mask { //phy_aux_cntl uint32_t AUX_PAD_RXSEL; uint32_t DDC_PAD_I2CMODE; + //dc_i3cpad_control0 + uint32_t DC_I3CPAD_DDCCLK_MASK; + uint32_t DC_I3CPAD_DDCDATA_MASK; + uint32_t DC_I3CPAD_PD_EN; + uint32_t DC_I3CPAD_CLK_A; + uint32_t DC_I3CPAD_DATA_A; + uint32_t DC_I3CPAD_CLK_EN; + uint32_t DC_I3CPAD_DATA_EN; + uint32_t DC_I3CPAD_CLK_Y; + uint32_t DC_I3CPAD_DATA_Y; + //dc_i3cpad_control1 + uint32_t DC_I3CPAD_STR; + uint32_t DC_I3CPAD_RXSEL; }; diff --git a/drivers/gpu/drm/amd/display/dc/gpio/hw_ddc.c b/drivers/gpu/drm/amd/display/dc/gpio/hw_ddc.c index a76884a069e8..b75bfea635fd 100644 --- a/drivers/gpu/drm/amd/display/dc/gpio/hw_ddc.c +++ b/drivers/gpu/drm/amd/display/dc/gpio/hw_ddc.c @@ -248,3 +248,305 @@ struct hw_gpio_pin *dal_hw_ddc_get_pin(struct gpio *gpio) return &hw_ddc->base.base; } + +static void store_registers_ddc_i3cpad( + struct hw_ddc *ddc) +{ + switch (ddc->base.base.id) { + case GPIO_ID_DDC_DATA: + REG_GET(dc_i3cpad_control0, DC_I3CPAD_DDCDATA_MASK, &ddc->base.store.mask); + REG_GET(dc_i3cpad_control0, DC_I3CPAD_DATA_A, &ddc->base.store.a); + REG_GET(dc_i3cpad_control0, DC_I3CPAD_DATA_EN, &ddc->base.store.en); + break; + case GPIO_ID_DDC_CLOCK: + REG_GET(dc_i3cpad_control0, DC_I3CPAD_DDCCLK_MASK, &ddc->base.store.mask); + REG_GET(dc_i3cpad_control0, DC_I3CPAD_CLK_A, &ddc->base.store.a); + REG_GET(dc_i3cpad_control0, DC_I3CPAD_CLK_EN, &ddc->base.store.en); + break; + default: + break; + } +} + +static void restore_registers_ddc_i3cpad( + struct hw_ddc *ddc) +{ + switch (ddc->base.base.id) { + case GPIO_ID_DDC_DATA: + REG_UPDATE(dc_i3cpad_control0, DC_I3CPAD_DDCDATA_MASK, ddc->base.store.mask); + REG_UPDATE(dc_i3cpad_control0, DC_I3CPAD_DATA_A, ddc->base.store.a); + REG_UPDATE(dc_i3cpad_control0, DC_I3CPAD_DATA_EN, ddc->base.store.en); + break; + case GPIO_ID_DDC_CLOCK: + REG_UPDATE(dc_i3cpad_control0, DC_I3CPAD_DDCCLK_MASK, ddc->base.store.mask); + REG_UPDATE(dc_i3cpad_control0, DC_I3CPAD_CLK_A, ddc->base.store.a); + REG_UPDATE(dc_i3cpad_control0, DC_I3CPAD_CLK_EN, ddc->base.store.en); + break; + default: + break; + } +} + +bool dal_hw_ddc_open_i3cpad( + struct hw_gpio_pin *ptr, + enum gpio_mode mode) +{ + struct hw_ddc *ddc = HW_DDC_FROM_BASE(ptr); + + store_registers_ddc_i3cpad(ddc); + + ptr->opened = (dal_hw_ddc_config_mode_i3cpad(ddc, mode) == GPIO_RESULT_OK); + + return ptr->opened; +} + +enum gpio_result dal_hw_ddc_get_value_i3cpad( + const struct hw_gpio_pin *ptr, + uint32_t *value) +{ + struct hw_ddc *ddc = HW_DDC_FROM_BASE(ptr); + enum gpio_result result = GPIO_RESULT_OK; + + switch (ptr->mode) { + case GPIO_MODE_INPUT: + case GPIO_MODE_OUTPUT: + case GPIO_MODE_HARDWARE: + case GPIO_MODE_FAST_OUTPUT: + switch (ddc->base.base.id) { + case GPIO_ID_DDC_DATA: + REG_GET(dc_i3cpad_control0, DC_I3CPAD_DATA_Y, value); + break; + case GPIO_ID_DDC_CLOCK: + REG_GET(dc_i3cpad_control0, DC_I3CPAD_CLK_Y, value); + break; + default: + break; + } + break; + default: + result = GPIO_RESULT_NON_SPECIFIC_ERROR; + } + return result; +} + +enum gpio_result dal_hw_ddc_set_value_i3cpad( + const struct hw_gpio_pin *ptr, + uint32_t value) +{ + struct hw_ddc *ddc = HW_DDC_FROM_BASE(ptr); + + switch (ptr->mode) { + case GPIO_MODE_OUTPUT: + switch (ddc->base.base.id) { + case GPIO_ID_DDC_DATA: + REG_UPDATE(dc_i3cpad_control0, DC_I3CPAD_DATA_A, value); + break; + case GPIO_ID_DDC_CLOCK: + REG_UPDATE(dc_i3cpad_control0, DC_I3CPAD_CLK_A, value); + break; + default: + break; + } + return GPIO_RESULT_OK; + case GPIO_MODE_FAST_OUTPUT: + /* We use (EN) to faster switch (used in DDC GPIO). + * So (A) is grounded, output is driven by (EN = 0) + * to pull the line down (output == 0) and (EN=1) + * then output is tri-state */ + switch (ddc->base.base.id) { + case GPIO_ID_DDC_DATA: + REG_UPDATE(dc_i3cpad_control0, DC_I3CPAD_DATA_EN, value); + break; + case GPIO_ID_DDC_CLOCK: + REG_UPDATE(dc_i3cpad_control0, DC_I3CPAD_CLK_EN, value); + break; + default: + break; + } + return GPIO_RESULT_OK; + default: + return GPIO_RESULT_NON_SPECIFIC_ERROR; + } +} + +enum gpio_result dal_hw_ddc_change_mode_i3cpad( + struct hw_gpio_pin *ptr, + enum gpio_mode mode) +{ + struct hw_ddc *ddc = HW_DDC_FROM_BASE(ptr); + + return dal_hw_ddc_config_mode_i3cpad(ddc, mode); +} + +enum gpio_result dal_hw_ddc_config_mode_i3cpad( + struct hw_ddc *ddc, + enum gpio_mode mode) +{ + ddc->base.base.mode = mode; + + switch (mode) { + case GPIO_MODE_INPUT: + /* turn off output enable, act as input pin; + * program the pin as GPIO, mask out signal driven by HW + */ + switch (ddc->base.base.id) { + case GPIO_ID_DDC_DATA: + REG_UPDATE(dc_i3cpad_control0, DC_I3CPAD_DATA_EN, 0); + REG_UPDATE(dc_i3cpad_control0, DC_I3CPAD_DDCDATA_MASK, 1); + break; + case GPIO_ID_DDC_CLOCK: + REG_UPDATE(dc_i3cpad_control0, DC_I3CPAD_CLK_EN, 0); + REG_UPDATE(dc_i3cpad_control0, DC_I3CPAD_DDCCLK_MASK, 1); + break; + default: + break; + } + return GPIO_RESULT_OK; + + case GPIO_MODE_OUTPUT: + /* turn on output enable, act as output pin; + * program the pin as GPIO, mask out signal driven by HW + */ + switch (ddc->base.base.id) { + case GPIO_ID_DDC_DATA: + REG_UPDATE(dc_i3cpad_control0, DC_I3CPAD_DATA_A, 0); + REG_UPDATE(dc_i3cpad_control0, DC_I3CPAD_DDCDATA_MASK, 1); + break; + case GPIO_ID_DDC_CLOCK: + REG_UPDATE(dc_i3cpad_control0, DC_I3CPAD_CLK_A, 0); + REG_UPDATE(dc_i3cpad_control0, DC_I3CPAD_DDCCLK_MASK, 1); + break; + default: + break; + } + return GPIO_RESULT_OK; + + case GPIO_MODE_FAST_OUTPUT: + /* grounding the A register then use the EN register bit + * will have faster effect on the rise time + */ + switch (ddc->base.base.id) { + case GPIO_ID_DDC_DATA: + REG_UPDATE(dc_i3cpad_control0, DC_I3CPAD_DATA_A, 0); + REG_UPDATE(dc_i3cpad_control0, DC_I3CPAD_DDCDATA_MASK, 1); + break; + case GPIO_ID_DDC_CLOCK: + REG_UPDATE(dc_i3cpad_control0, DC_I3CPAD_CLK_A, 0); + REG_UPDATE(dc_i3cpad_control0, DC_I3CPAD_DDCCLK_MASK, 1); + break; + default: + break; + } + return GPIO_RESULT_OK; + + case GPIO_MODE_HARDWARE: + /* program the pin as tri-state, pin is driven by HW */ + switch (ddc->base.base.id) { + case GPIO_ID_DDC_DATA: + REG_UPDATE(dc_i3cpad_control0, DC_I3CPAD_DDCDATA_MASK, 0); + break; + case GPIO_ID_DDC_CLOCK: + REG_UPDATE(dc_i3cpad_control0, DC_I3CPAD_DDCCLK_MASK, 0); + break; + default: + break; + } + return GPIO_RESULT_OK; + + default: + case GPIO_MODE_INTERRUPT: + /* Interrupt mode supported only by HPD (IrqGpio) old pins. */ + return GPIO_RESULT_NON_SPECIFIC_ERROR; + } +} + +static enum gpio_result dal_hw_ddc_set_config_i3cpad( + struct hw_gpio_pin *ptr, + const struct gpio_config_data *config_data) +{ + struct hw_ddc *ddc = HW_DDC_FROM_BASE(ptr); + + switch (config_data->config.ddc.type) { + /* For ASICs with i3cpad module there is no dual pad mode for i3cpads */ + case GPIO_DDC_CONFIG_TYPE_MODE_I2C: + /* Enable the RX for the PAD (it is disabled by default). */ + REG_UPDATE(dc_i3cpad_control1, DC_I3CPAD_RXSEL, 0); + return GPIO_RESULT_OK; + case GPIO_DDC_CONFIG_TYPE_MODE_AUX: + return GPIO_RESULT_OK; + + case GPIO_DDC_CONFIG_TYPE_POLL_FOR_CONNECT: + REG_UPDATE_3(ddc_setup, + DC_I2C_DDC1_ENABLE, 1, + DC_I2C_DDC1_EDID_DETECT_ENABLE, 1, + DC_I2C_DDC1_EDID_DETECT_MODE, 0); + return GPIO_RESULT_OK; + + case GPIO_DDC_CONFIG_TYPE_POLL_FOR_DISCONNECT: + REG_UPDATE_3(ddc_setup, + DC_I2C_DDC1_ENABLE, 1, + DC_I2C_DDC1_EDID_DETECT_ENABLE, 1, + DC_I2C_DDC1_EDID_DETECT_MODE, 1); + return GPIO_RESULT_OK; + + case GPIO_DDC_CONFIG_TYPE_DISABLE_POLLING: + REG_UPDATE_2(ddc_setup, + DC_I2C_DDC1_ENABLE, 0, + DC_I2C_DDC1_EDID_DETECT_ENABLE, 0); + return GPIO_RESULT_OK; + } + + BREAK_TO_DEBUGGER(); + return GPIO_RESULT_NON_SPECIFIC_ERROR; +} + +void dal_hw_ddc_close_i3cpad( + struct hw_gpio_pin *ptr) +{ + struct hw_ddc *ddc = HW_DDC_FROM_BASE(ptr); + + restore_registers_ddc_i3cpad(ddc); + + ptr->mode = GPIO_MODE_UNKNOWN; + ptr->opened = false; +} + +static const struct hw_gpio_pin_funcs funcs_i3cpad = { + .destroy = dal_hw_ddc_destroy, + .open = dal_hw_ddc_open_i3cpad, + .get_value = dal_hw_ddc_get_value_i3cpad, + .set_value = dal_hw_ddc_set_value_i3cpad, + .set_config = dal_hw_ddc_set_config_i3cpad, + .change_mode = dal_hw_ddc_change_mode_i3cpad, + .close = dal_hw_ddc_close_i3cpad, +}; + +static void dal_hw_ddc_construct_i3cpad( + struct hw_ddc *ddc, + enum gpio_id id, + uint32_t en, + struct dc_context *ctx) +{ + dal_hw_gpio_construct(&ddc->base, id, en, ctx); + ddc->base.base.funcs = &funcs_i3cpad; +} + +void dal_hw_ddc_init_i3cpad( + struct hw_ddc **hw_ddc, + struct dc_context *ctx, + enum gpio_id id, + uint32_t en) +{ + if (en > GPIO_DDC_LINE_MAX) { + ASSERT_CRITICAL(false); + *hw_ddc = NULL; + } + + *hw_ddc = kzalloc(sizeof(struct hw_ddc), GFP_KERNEL); + if (!*hw_ddc) { + ASSERT_CRITICAL(false); + return; + } + + dal_hw_ddc_construct_i3cpad(*hw_ddc, id, en, ctx); +} diff --git a/drivers/gpu/drm/amd/display/dc/gpio/hw_ddc.h b/drivers/gpu/drm/amd/display/dc/gpio/hw_ddc.h index cc30e65df431..ac2c87d30cf4 100644 --- a/drivers/gpu/drm/amd/display/dc/gpio/hw_ddc.h +++ b/drivers/gpu/drm/amd/display/dc/gpio/hw_ddc.h @@ -46,4 +46,32 @@ void dal_hw_ddc_init( struct hw_gpio_pin *dal_hw_ddc_get_pin(struct gpio *gpio); +void dal_hw_ddc_init_i3cpad( + struct hw_ddc **hw_ddc, + struct dc_context *ctx, + enum gpio_id id, + uint32_t en); + +bool dal_hw_ddc_open_i3cpad( + struct hw_gpio_pin *ptr, + enum gpio_mode mode); + +enum gpio_result dal_hw_ddc_get_value_i3cpad( + const struct hw_gpio_pin *ptr, + uint32_t *value); + +enum gpio_result dal_hw_ddc_set_value_i3cpad( + const struct hw_gpio_pin *ptr, + uint32_t value); + +enum gpio_result dal_hw_ddc_config_mode_i3cpad( + struct hw_ddc *ddc, + enum gpio_mode mode); + +enum gpio_result dal_hw_ddc_change_mode_i3cpad( + struct hw_gpio_pin *ptr, + enum gpio_mode mode); + +void dal_hw_ddc_close_i3cpad( + struct hw_gpio_pin *ptr); #endif diff --git a/drivers/gpu/drm/amd/display/dc/gpio/hw_factory.c b/drivers/gpu/drm/amd/display/dc/gpio/hw_factory.c index a907f7d0628b..3300dbc67f32 100644 --- a/drivers/gpu/drm/amd/display/dc/gpio/hw_factory.c +++ b/drivers/gpu/drm/amd/display/dc/gpio/hw_factory.c @@ -55,6 +55,7 @@ #include "dcn401/hw_factory_dcn401.h" #include "dcn42/hw_factory_dcn42.h" #include "dcn42b/hw_factory_dcn42b.h" +#include "dcn60/hw_factory_dcn60.h" bool dal_hw_factory_init( struct hw_factory *factory, @@ -127,6 +128,9 @@ bool dal_hw_factory_init( case DCN_VERSION_4_2B: dal_hw_factory_dcn42b_init(factory); return true; + case DCN_VERSION_6_0: + dal_hw_factory_dcn60_init(factory); + return true; default: ASSERT_CRITICAL(false); return false; diff --git a/drivers/gpu/drm/amd/display/dc/gpio/hw_translate.c b/drivers/gpu/drm/amd/display/dc/gpio/hw_translate.c index b58af86dee10..5a231f97aee3 100644 --- a/drivers/gpu/drm/amd/display/dc/gpio/hw_translate.c +++ b/drivers/gpu/drm/amd/display/dc/gpio/hw_translate.c @@ -55,6 +55,7 @@ #include "dcn401/hw_translate_dcn401.h" #include "dcn42/hw_translate_dcn42.h" #include "dcn42b/hw_translate_dcn42b.h" +#include "dcn60/hw_translate_dcn60.h" /* * This unit @@ -128,6 +129,9 @@ bool dal_hw_translate_init( case DCN_VERSION_4_2B: dal_hw_translate_dcn42b_init(translate); return true; + case DCN_VERSION_6_0: + dal_hw_translate_dcn60_init(translate); + return true; default: BREAK_TO_DEBUGGER(); return false; diff --git a/drivers/gpu/drm/amd/display/dc/hdcp/hdcp_msg.c b/drivers/gpu/drm/amd/display/dc/hdcp/hdcp_msg.c index 34fc9f56dbef..f3413d743107 100644 --- a/drivers/gpu/drm/amd/display/dc/hdcp/hdcp_msg.c +++ b/drivers/gpu/drm/amd/display/dc/hdcp/hdcp_msg.c @@ -177,6 +177,15 @@ static bool hdmi_14_process_transaction( i2c_command.engine = I2C_COMMAND_ENGINE_HW;//only HW i2c_command.speed = link->ddc->ctx->dc->caps.i2c_speed_in_khz; + if (link->force_to_use_aux) + result = dm_helpers_submit_i2c_over_aux( + link->ddc, + hdcp_i2c_addr_link_primary, + offset, + message_info->data, + message_info->length, + hdcp_cmd_is_read[message_info->msg_id]); + else result = dm_helpers_submit_i2c( link->ctx, link, diff --git a/drivers/gpu/drm/amd/display/dc/hubbub/dcn10/dcn10_hubbub.h b/drivers/gpu/drm/amd/display/dc/hubbub/dcn10/dcn10_hubbub.h index ff9a1ae29474..accb79c6dde5 100644 --- a/drivers/gpu/drm/amd/display/dc/hubbub/dcn10/dcn10_hubbub.h +++ b/drivers/gpu/drm/amd/display/dc/hubbub/dcn10/dcn10_hubbub.h @@ -201,6 +201,20 @@ struct dcn_hubbub_registers { uint32_t DCHUBBUB_TIMEOUT_DETECTION_CTRL1; uint32_t DCHUBBUB_TIMEOUT_DETECTION_CTRL2; uint32_t DCHUBBUB_CTRL_STATUS; + uint32_t DCHUBBUB_ARB_BUFFER_FULLNESS_WATERMARK_A; + uint32_t DCHUBBUB_ARB_BUFFER_FULLNESS_WATERMARK_B; + uint32_t DCHUBBUB_PERFORMANCE_MEASUREMENT_CNTL; + uint32_t DCHUBBUB_PERFORMANCE_MEASUREMENT_CNTL2; + uint32_t DC_PERFMON5_PERFCOUNTER_CNTL; + uint32_t DC_PERFMON5_PERFCOUNTER_CNTL2; + uint32_t DC_PERFMON5_PERFCOUNTER_STATE; + uint32_t DC_PERFMON5_PERFMON_CNTL; + uint32_t DC_PERFMON5_PERFMON_CNTL2; + uint32_t DC_PERFMON5_PERFMON_CVALUE_INT_MISC; + uint32_t DC_PERFMON5_PERFMON_CVALUE_LOW; + uint32_t DC_PERFMON5_PERFMON_HI; + uint32_t DC_PERFMON5_PERFMON_LOW; + uint32_t FMON_CTRL; }; #define HUBBUB_REG_FIELD_LIST_DCN32(type) \ @@ -443,6 +457,96 @@ struct dcn_hubbub_registers { #define HUBBUB_REG_FIELD_LIST_DCN4_2(type) \ type URGENT_ZERO_SIZE_REQ_EN + +#define HUBBUB_PERFMON_REG_FIELD_LIST(type) \ + type DCHUBBUB_LATENCY_CNT_EN;\ + type DCHUBBUB_DF_REQ_CMD_LATENCY_SEL;\ + type ARB_LATENCY_PIPE_SEL;\ + type ARB_LATENCY_REQ_TYPE_SEL;\ + type ROB_FIFO_LEVEL;\ + type REQ_UNIT_ID_MASK;\ + type REQ_UNIT_ID_SEL;\ + type DCHUBBUB_LATENCY_FRAME_WIN_EN;\ + type DCHUBBUB_LATENCY_FRAME_WIN_SRC_SEL;\ + type DCHUBBUB_LATENCY_FRAME_WIN_DUR;\ + type LATENCY_SOURCE_SEL;\ + type LATENCY_DEBUG_SEL;\ + type UTM_FILTER_SEL;\ + type ROB_MAX_FIFO_LEVEL;\ + type ROB_MAX_FIFO_LEVEL_RESET;\ + type PERFCOUNTER_EVENT_SEL;\ + type PERFCOUNTER_CVALUE_SEL;\ + type PERFCOUNTER_INC_MODE;\ + type PERFCOUNTER_HW_CNTL_SEL;\ + type PERFCOUNTER_RUNEN_MODE;\ + type PERFCOUNTER_CNTOFF_START_DIS;\ + type PERFCOUNTER_RESTART_EN;\ + type PERFCOUNTER_INT_EN;\ + type PERFCOUNTER_OFF_MASK;\ + type PERFCOUNTER_ACTIVE;\ + type PERFCOUNTER_CNTL_SEL;\ + type PERFCOUNTER_COUNTED_VALUE_TYPE;\ + type PERFCOUNTER_HW_STOP1_SEL;\ + type PERFCOUNTER_HW_STOP2_SEL;\ + type PERFCOUNTER_CNTOFF_SEL;\ + type PERFCOUNTER_CNTL2_SEL;\ + type PERFCOUNTER_CNT0_STATE;\ + type PERFCOUNTER_STATE_SEL0;\ + type PERFCOUNTER_CNT1_STATE;\ + type PERFCOUNTER_STATE_SEL1;\ + type PERFCOUNTER_CNT2_STATE;\ + type PERFCOUNTER_STATE_SEL2;\ + type PERFCOUNTER_CNT3_STATE;\ + type PERFCOUNTER_STATE_SEL3;\ + type PERFCOUNTER_CNT4_STATE;\ + type PERFCOUNTER_STATE_SEL4;\ + type PERFCOUNTER_CNT5_STATE;\ + type PERFCOUNTER_STATE_SEL5;\ + type PERFCOUNTER_CNT6_STATE;\ + type PERFCOUNTER_STATE_SEL6;\ + type PERFCOUNTER_CNT7_STATE;\ + type PERFCOUNTER_STATE_SEL7;\ + type PERFMON_STATE;\ + type PERFMON_RPT_COUNT;\ + type PERFMON_CNTOFF_AND_OR;\ + type PERFMON_CNTOFF_INT_EN;\ + type PERFMON_CNTOFF_INT_STATUS;\ + type PERFMON_CNTOFF_INT_ACK;\ + type PERFMON_CNTOFF_INT_TYPE;\ + type PERFMON_CLK_ENABLE;\ + type PERFMON_RUN_ENABLE_START_SEL;\ + type PERFMON_RUN_ENABLE_STOP_SEL;\ + type PERFCOUNTER_INT0_STATUS;\ + type PERFCOUNTER_INT1_STATUS;\ + type PERFCOUNTER_INT2_STATUS;\ + type PERFCOUNTER_INT3_STATUS;\ + type PERFCOUNTER_INT4_STATUS;\ + type PERFCOUNTER_INT5_STATUS;\ + type PERFCOUNTER_INT6_STATUS;\ + type PERFCOUNTER_INT7_STATUS;\ + type PERFCOUNTER_INT0_ACK;\ + type PERFCOUNTER_INT1_ACK;\ + type PERFCOUNTER_INT2_ACK;\ + type PERFCOUNTER_INT3_ACK;\ + type PERFCOUNTER_INT4_ACK;\ + type PERFCOUNTER_INT5_ACK;\ + type PERFCOUNTER_INT6_ACK;\ + type PERFCOUNTER_INT7_ACK;\ + type PERFMON_CVALUE_HI;\ + type PERFMON_CVALUE_LOW;\ + type PERFMON_HI;\ + type PERFMON_READ_SEL;\ + type PERFMON_LOW;\ + type FMON_MODE;\ + type DCHUBBUB_ARB_UTM_FORCE_URGENT;\ + type DCHUBBUB_ARB_UTM_FORCE_BANDWIDTH_OVERHEAD;\ + type DCHUBBUB_ARB_UTM_FORCE_ENABLE;\ + type DCHUBBUB_ARB_DO_NOT_FORCE_URGENCY_DURING_PSTATE_CHANGE_REQUEST + +#define HUBBUB_REG_FIELD_LIST_DCN60(type) \ + type DCHUBBUB_ARB_BUFFER_FULLNESS_WATERMARK_A;\ + type DCHUBBUB_ARB_BUFFER_FULLNESS_WATERMARK_B + struct dcn_hubbub_shift { DCN_HUBBUB_REG_FIELD_LIST(uint8_t); HUBBUB_STUTTER_REG_FIELD_LIST(uint8_t); @@ -453,6 +557,8 @@ struct dcn_hubbub_shift { HUBBUB_REG_FIELD_LIST_DCN4_01(uint8_t); HUBBUB_REG_FIELD_LIST_DCN4_2(uint8_t); + HUBBUB_REG_FIELD_LIST_DCN60(uint8_t); + HUBBUB_PERFMON_REG_FIELD_LIST(uint8_t); }; struct dcn_hubbub_mask { @@ -465,6 +571,8 @@ struct dcn_hubbub_mask { HUBBUB_REG_FIELD_LIST_DCN4_01(uint32_t); HUBBUB_REG_FIELD_LIST_DCN4_2(uint8_t); + HUBBUB_REG_FIELD_LIST_DCN60(uint32_t); + HUBBUB_PERFMON_REG_FIELD_LIST(uint32_t); }; struct dc; diff --git a/drivers/gpu/drm/amd/display/dc/hubp/dcn20/dcn20_hubp.h b/drivers/gpu/drm/amd/display/dc/hubp/dcn20/dcn20_hubp.h index 2595c6441f00..ea90dee05d5f 100644 --- a/drivers/gpu/drm/amd/display/dc/hubp/dcn20/dcn20_hubp.h +++ b/drivers/gpu/drm/amd/display/dc/hubp/dcn20/dcn20_hubp.h @@ -182,6 +182,9 @@ uint32_t DCHUBP_ADDR_CONFIG;\ uint32_t HUBP_MALL_STATUS +#define DCN60_HUBP_REG_VARIABLE_LIST \ + uint32_t DCSURF_LEGACY_ADDR_CONFIG;\ + uint32_t DST_Y_ALT_CH_DRQ_LIMIT #define DCN2_HUBP_REG_FIELD_VARIABLE_LIST(type) \ DCN_HUBP_REG_FIELD_BASE_LIST(type); \ type DMDATA_ADDRESS_HIGH;\ @@ -293,18 +296,44 @@ type HUBP_3DLUT_CROSSBAR_SEL_G;\ type HUBP_3DLUT_CROSSBAR_SEL_B;\ type HUBP_3DLUT_CROSSBAR_SEL_R +#define DCN60_HUBP_REG_FIELD_VARIABLE_LIST(type) \ + type COMPAT_LEVEL; \ + type LEGACY_PIPE_INTERLEAVE;\ + type ARRAY_MODE;\ + type PIPE_CONFIG;\ + type MICRO_TILE_MODE_NEW;\ + type TILE_SPLIT; \ + type BANK_WIDTH; \ + type BANK_HEIGHT;\ + type MACRO_TILE_ASPECT;\ + type LEGACY_NUM_BANKS;\ + type FORCE_URGENT_FLIP;\ + type FORCE_URGENT_VM_PREFETCH;\ + type URGENT_FORCE_VALUE;\ + type URGENT_FORCE_EN;\ + type FORCE_DISP_PREF_TO_VBLANK;\ + type DST_Y_ALT_CH_DRQ_LIMIT;\ + type FORCE_CURSOR_TO_DISP_PREF +/* + type HUBP_3DLUT_CROSSBAR_SEL_B;\ + type HUBP_3DLUT_CROSSBAR_SEL_G;\ + type HUBP_3DLUT_CROSSBAR_SEL_R; +*/ struct dcn_hubp2_registers { DCN401_HUBP_REG_COMMON_VARIABLE_LIST; + DCN60_HUBP_REG_VARIABLE_LIST; }; struct dcn_hubp2_shift { DCN401_HUBP_REG_FIELD_VARIABLE_LIST(uint8_t); DCN42_HUBP_REG_FIELD_VARIABLE_LIST(uint8_t); + DCN60_HUBP_REG_FIELD_VARIABLE_LIST(uint8_t); }; struct dcn_hubp2_mask { DCN401_HUBP_REG_FIELD_VARIABLE_LIST(uint32_t); DCN42_HUBP_REG_FIELD_VARIABLE_LIST(uint32_t); + DCN60_HUBP_REG_FIELD_VARIABLE_LIST(uint32_t); }; struct dcn20_hubp { diff --git a/drivers/gpu/drm/amd/display/dc/hwss/dce/dce_hwseq.h b/drivers/gpu/drm/amd/display/dc/hwss/dce/dce_hwseq.h index dc8feca578c5..2cc4e7516a5d 100644 --- a/drivers/gpu/drm/amd/display/dc/hwss/dce/dce_hwseq.h +++ b/drivers/gpu/drm/amd/display/dc/hwss/dce/dce_hwseq.h @@ -702,6 +702,7 @@ struct dce_hwseq_registers { uint32_t DOMAIN25_PG_STATUS; uint32_t DOMAIN26_PG_CONFIG; uint32_t DOMAIN26_PG_STATUS; + uint32_t HDCP_INTERRUPT_DEST; }; /* set field name */ #define HWS_SF(blk_name, reg_name, field_name, post_fix)\ @@ -1254,6 +1255,12 @@ struct dce_hwseq_registers { type DOMAIN26_POWER_GATE; \ type DOMAIN26_PGFSM_PWR_STATUS; +#define HWSEQ_DCN60_REG_FIELD_LIST(type) \ + type DOUT_IHC_HDCP0_I2C_XFER_REQ_INTERRUPT_DEST; \ + type DOUT_IHC_HDCP1_I2C_XFER_REQ_INTERRUPT_DEST; \ + type DOUT_IHC_HDCP2_I2C_XFER_REQ_INTERRUPT_DEST; \ + type DOUT_IHC_HDCP3_I2C_XFER_REQ_INTERRUPT_DEST; + struct dce_hwseq_shift { HWSEQ_REG_FIELD_LIST(uint8_t) HWSEQ_DCN_REG_FIELD_LIST(uint8_t) @@ -1263,6 +1270,7 @@ struct dce_hwseq_shift { HWSEQ_DCN35_REG_FIELD_LIST(uint8_t) HWSEQ_DCN401_REG_FIELD_LIST(uint8_t) HWSEQ_DCN42_REG_FIELD_LIST(uint8_t) + HWSEQ_DCN60_REG_FIELD_LIST(uint8_t) }; struct dce_hwseq_mask { @@ -1274,6 +1282,7 @@ struct dce_hwseq_mask { HWSEQ_DCN35_REG_FIELD_LIST(uint32_t) HWSEQ_DCN401_REG_FIELD_LIST(uint32_t) HWSEQ_DCN42_REG_FIELD_LIST(uint32_t) + HWSEQ_DCN60_REG_FIELD_LIST(uint32_t) }; diff --git a/drivers/gpu/drm/amd/display/dc/hwss/dce110/dce110_hwseq.c b/drivers/gpu/drm/amd/display/dc/hwss/dce110/dce110_hwseq.c index f91ce2b4b1bf..5fcf30b448a5 100644 --- a/drivers/gpu/drm/amd/display/dc/hwss/dce110/dce110_hwseq.c +++ b/drivers/gpu/drm/amd/display/dc/hwss/dce110/dce110_hwseq.c @@ -3487,6 +3487,17 @@ void dce110_enable_tmds_link_output(struct dc_link *link, signal, pixel_clock); link->phy_state.symclk_state = SYMCLK_ON_TX_ON; + + // For dongle Type 2 with no I2C support on board, setup sw mode of Ri/Pj check with proper aux instance + if (link->force_to_use_aux) { + if (link->link_enc && link->link_enc->funcs->setup_ri_pj_check_in_sw_or_hw_mode) + link->link_enc->funcs->setup_ri_pj_check_in_sw_or_hw_mode(link->link_enc, + link->aux_hw_inst, true); + } else + // For HDMI setup hw mode of Ri/Pj check with proper ddc pin instance + if (link->link_enc && link->link_enc->funcs->setup_ri_pj_check_in_sw_or_hw_mode) + link->link_enc->funcs->setup_ri_pj_check_in_sw_or_hw_mode(link->link_enc, + link->ddc_hw_inst, false); } static void dce110_enable_analog_link_output( diff --git a/drivers/gpu/drm/amd/display/dc/hwss/dcn10/dcn10_hwseq.c b/drivers/gpu/drm/amd/display/dc/hwss/dcn10/dcn10_hwseq.c index 22c7535fd9c4..097e4ac2df05 100644 --- a/drivers/gpu/drm/amd/display/dc/hwss/dcn10/dcn10_hwseq.c +++ b/drivers/gpu/drm/amd/display/dc/hwss/dcn10/dcn10_hwseq.c @@ -524,7 +524,7 @@ static void dcn10_log_color_state(struct dc *dc, DTN_INFO("DPP Color Caps: input_lut_shared:%d icsc:%d" " dgam_ram:%d dgam_rom: srgb:%d,bt2020:%d,gamma2_2:%d,pq:%d,hlg:%d" " post_csc:%d gamcor:%d dgam_rom_for_yuv:%d 3d_lut:%d" - " blnd_lut:%d oscs:%d\n\n", + " upsp_pre_scaler:%d blnd_lut:%d oscs:%d\n\n", dc->caps.color.dpp.input_lut_shared, dc->caps.color.dpp.icsc, dc->caps.color.dpp.dgam_ram, @@ -537,6 +537,7 @@ static void dcn10_log_color_state(struct dc *dc, dc->caps.color.dpp.gamma_corr, dc->caps.color.dpp.dgam_rom_for_yuv, dc->caps.color.dpp.hw_3d_lut, + dc->caps.color.dpp.upsp_pre_scaler, dc->caps.color.dpp.ogam_ram, dc->caps.color.dpp.ocsc); diff --git a/drivers/gpu/drm/amd/display/dc/hwss/dcn20/dcn20_hwseq.c b/drivers/gpu/drm/amd/display/dc/hwss/dcn20/dcn20_hwseq.c index 98778d5e114e..16bb6f678567 100644 --- a/drivers/gpu/drm/amd/display/dc/hwss/dcn20/dcn20_hwseq.c +++ b/drivers/gpu/drm/amd/display/dc/hwss/dcn20/dcn20_hwseq.c @@ -148,7 +148,7 @@ void dcn20_log_color_state(struct dc *dc, DTN_INFO("DPP Color Caps: input_lut_shared:%d icsc:%d" " dgam_ram:%d dgam_rom: srgb:%d,bt2020:%d,gamma2_2:%d,pq:%d,hlg:%d" " post_csc:%d gamcor:%d dgam_rom_for_yuv:%d 3d_lut:%d" - " blnd_lut:%d oscs:%d\n\n", + " upsp_pre_scaler:%d blnd_lut:%d oscs:%d\n\n", dc->caps.color.dpp.input_lut_shared, dc->caps.color.dpp.icsc, dc->caps.color.dpp.dgam_ram, @@ -161,6 +161,7 @@ void dcn20_log_color_state(struct dc *dc, dc->caps.color.dpp.gamma_corr, dc->caps.color.dpp.dgam_rom_for_yuv, dc->caps.color.dpp.hw_3d_lut, + dc->caps.color.dpp.upsp_pre_scaler, dc->caps.color.dpp.ogam_ram, dc->caps.color.dpp.ocsc); diff --git a/drivers/gpu/drm/amd/display/dc/hwss/dcn30/dcn30_hwseq.c b/drivers/gpu/drm/amd/display/dc/hwss/dcn30/dcn30_hwseq.c index 59184e146fc9..cb163902e12e 100644 --- a/drivers/gpu/drm/amd/display/dc/hwss/dcn30/dcn30_hwseq.c +++ b/drivers/gpu/drm/amd/display/dc/hwss/dcn30/dcn30_hwseq.c @@ -157,7 +157,7 @@ void dcn30_log_color_state(struct dc *dc, DTN_INFO("DPP Color Caps: input_lut_shared:%d icsc:%d" " dgam_ram:%d dgam_rom: srgb:%d,bt2020:%d,gamma2_2:%d,pq:%d,hlg:%d" " post_csc:%d gamcor:%d dgam_rom_for_yuv:%d 3d_lut:%d" - " blnd_lut:%d oscs:%d\n\n", + " upsp_pre_scaler:%d blnd_lut:%d oscs:%d\n\n", dc->caps.color.dpp.input_lut_shared, dc->caps.color.dpp.icsc, dc->caps.color.dpp.dgam_ram, @@ -170,6 +170,7 @@ void dcn30_log_color_state(struct dc *dc, dc->caps.color.dpp.gamma_corr, dc->caps.color.dpp.dgam_rom_for_yuv, dc->caps.color.dpp.hw_3d_lut, + dc->caps.color.dpp.upsp_pre_scaler, dc->caps.color.dpp.ogam_ram, dc->caps.color.dpp.ocsc); diff --git a/drivers/gpu/drm/amd/display/dc/hwss/dcn32/dcn32_hwseq.c b/drivers/gpu/drm/amd/display/dc/hwss/dcn32/dcn32_hwseq.c index c5f6eb482f07..51fd2b3fe106 100644 --- a/drivers/gpu/drm/amd/display/dc/hwss/dcn32/dcn32_hwseq.c +++ b/drivers/gpu/drm/amd/display/dc/hwss/dcn32/dcn32_hwseq.c @@ -544,7 +544,10 @@ bool dcn32_set_input_transfer_func(struct dc *dc, if (plane_state->in_transfer_func.type == TF_TYPE_PREDEFINED) tf = plane_state->in_transfer_func.tf; - dpp_base->funcs->dpp_set_pre_degam(dpp_base, tf); + if (dpp_base->funcs->dpp_set_pregam_state) + dpp_base->funcs->dpp_set_pregam_state(dpp_base, tf, plane_state->scaling_linearity); + else + dpp_base->funcs->dpp_set_pre_degam(dpp_base, tf); if (plane_state->in_transfer_func.type == TF_TYPE_HWPWL) params = &plane_state->in_transfer_func.pwl; diff --git a/drivers/gpu/drm/amd/display/dc/hwss/dcn35/dcn35_hwseq.c b/drivers/gpu/drm/amd/display/dc/hwss/dcn35/dcn35_hwseq.c index f14c39a643da..08f1f307657c 100644 --- a/drivers/gpu/drm/amd/display/dc/hwss/dcn35/dcn35_hwseq.c +++ b/drivers/gpu/drm/amd/display/dc/hwss/dcn35/dcn35_hwseq.c @@ -48,6 +48,7 @@ #include "dpcd_defs.h" #include "dce/dmub_outbox.h" #include "link_service.h" +#include "dce/dmub_hw_lock_mgr.h" #include "dcn10/dcn10_hwseq.h" #include "inc/link_enc_cfg.h" #include "dcn30/dcn30_vpg.h" diff --git a/drivers/gpu/drm/amd/display/dc/hwss/dcn401/dcn401_hwseq.c b/drivers/gpu/drm/amd/display/dc/hwss/dcn401/dcn401_hwseq.c index fa9a5d8065d3..b89010a88b44 100644 --- a/drivers/gpu/drm/amd/display/dc/hwss/dcn401/dcn401_hwseq.c +++ b/drivers/gpu/drm/amd/display/dc/hwss/dcn401/dcn401_hwseq.c @@ -348,6 +348,11 @@ void dcn401_init_hw(struct dc *dc) dal_gpio_destroy_ddc(&ddc_pin); } } + //Setup corresponding HDCP XFER DEST interrupt to go to DMUCB + dc_dmub_srv_ihc_set_dig_hdcp_interrupt_dest( + dc->ctx->dmub_srv, + link->eng_id, + true); } } @@ -1099,6 +1104,12 @@ void dcn401_disable_link_output(struct dc_link *link, dmcu->funcs->lock_phy(dmcu); if (dc_is_tmds_signal(signal) && link->phy_state.symclk_ref_cnts.otg > 0) { + // Disable interrupt, setup default hw mode of Ri/Pj check with proper aux instance + if (link->force_to_use_aux) { + if (link->link_enc && link->link_enc->funcs->setup_ri_pj_check_in_sw_or_hw_mode) + link->link_enc->funcs->setup_ri_pj_check_in_sw_or_hw_mode(link->link_enc, + link->aux_hw_inst, false); + } disable_link_output_symclk_on_tx_off(link, DP_UNKNOWN_ENCODING); link->phy_state.symclk_state = SYMCLK_ON_TX_OFF; } else { @@ -2609,6 +2620,16 @@ void dcn401_program_front_end_for_ctx( if (resource_is_pipe_topology_changed(dc->current_state, context)) resource_log_pipe_topology_update(dc, context); + if (dc->debug.enable_block_sequence_programming) { + hwss_build_full_sequence(dc, + context->block_sequence, + &(context->block_sequence_steps), + context, false); + hwss_execute_sequence(dc, + context->block_sequence, + context->block_sequence_steps); + return; + } if (dc->hwss.program_triplebuffer != NULL && dc->debug.enable_tri_buf) { for (i = 0; i < dc->res_pool->pipe_count; i++) { @@ -2770,6 +2791,17 @@ void dcn401_post_unlock_program_front_end( struct dce_hwseq *hwseq = dc->hwseq; unsigned int i; + if (dc->debug.enable_block_sequence_programming) { + hwss_build_post_unlock_full_sequence(dc, + context->block_sequence, + &(context->block_sequence_steps), + context); + hwss_execute_sequence(dc, + context->block_sequence, + context->block_sequence_steps); + return; + } + for (i = 0; i < dc->res_pool->pipe_count; i++) if (resource_is_pipe_type(&dc->current_state->res_ctx.pipe_ctx[i], OPP_HEAD) && !resource_is_pipe_type(&context->res_ctx.pipe_ctx[i], OPP_HEAD)) diff --git a/drivers/gpu/drm/amd/display/dc/hwss/hw_sequencer.h b/drivers/gpu/drm/amd/display/dc/hwss/hw_sequencer.h index 4549c435501a..c4296b8390f2 100644 --- a/drivers/gpu/drm/amd/display/dc/hwss/hw_sequencer.h +++ b/drivers/gpu/drm/amd/display/dc/hwss/hw_sequencer.h @@ -145,6 +145,9 @@ struct set_output_transfer_func_params { bool is_top_pipe; const struct dc_stream_state *stream; }; +struct program_upsp_params { + struct pipe_ctx *pipe_ctx; +}; struct update_visual_confirm_params { struct dc *dc; @@ -1030,6 +1033,7 @@ union block_sequence_params { struct setup_dpp_params setup_dpp_params; struct program_bias_and_scale_params program_bias_and_scale_params; struct set_output_transfer_func_params set_output_transfer_func_params; + struct program_upsp_params program_upsp_params; struct update_visual_confirm_params update_visual_confirm_params; struct power_on_mpc_mem_pwr_params power_on_mpc_mem_pwr_params; struct set_output_csc_params set_output_csc_params; @@ -1207,6 +1211,7 @@ enum block_sequence_func { DPP_PROGRAM_BIAS_AND_SCALE, DPP_SET_OUTPUT_TRANSFER_FUNC, DPP_SET_HDR_MULTIPLIER, + DPP_PROGRAM_UPSP, MPC_UPDATE_VISUAL_CONFIRM, MPC_POWER_ON_MPC_MEM_PWR, MPC_SET_OUTPUT_CSC, @@ -1783,6 +1788,16 @@ void hwss_build_fast_sequence(struct dc *dc, struct dc_stream_status *stream_status, struct dc_state *context); +void hwss_build_full_sequence(struct dc *dc, + struct block_sequence block_sequence[MAX_HWSS_BLOCK_SEQUENCE_SIZE], + unsigned int *num_steps, + struct dc_state *context, bool program_phantom_pipe); + +void hwss_build_post_unlock_full_sequence(struct dc *dc, + struct block_sequence block_sequence[MAX_HWSS_BLOCK_SEQUENCE_SIZE], + unsigned int *num_steps, + struct dc_state *context); + void hwss_wait_for_all_blank_complete(struct dc *dc, struct dc_state *context); @@ -1806,6 +1821,8 @@ void hwss_setup_dpp(union block_sequence_params *params); void hwss_program_bias_and_scale(union block_sequence_params *params); +void hwss_program_upsp(union block_sequence_params *params); + void hwss_power_on_mpc_mem_pwr(union block_sequence_params *params); void hwss_set_output_csc(union block_sequence_params *params); diff --git a/drivers/gpu/drm/amd/display/dc/inc/core_types.h b/drivers/gpu/drm/amd/display/dc/inc/core_types.h index e87f9fd60bcb..b18d607fb222 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/core_types.h +++ b/drivers/gpu/drm/amd/display/dc/inc/core_types.h @@ -447,6 +447,7 @@ enum p_state_switch_method { P_STATE_SUB_VP, P_STATE_DRR_SUB_VP, P_STATE_V_BLANK_SUB_VP, + P_STATE_ALT, }; struct dsc_padding_params { diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw/clk_mgr_internal.h b/drivers/gpu/drm/amd/display/dc/inc/hw/clk_mgr_internal.h index 23c9798936c2..d735eb1e7f43 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/hw/clk_mgr_internal.h +++ b/drivers/gpu/drm/amd/display/dc/inc/hw/clk_mgr_internal.h @@ -293,6 +293,27 @@ enum dentist_divider_range { CLK_SF(CLK5_CLK2_DS_CNTL, CLK2_ALLOW_DS, mask_sh), \ CLK_SF(CLK5_CLK3_DS_CNTL, CLK3_ALLOW_DS, mask_sh) +#define CLK_REG_LIST_DCN60() \ + CLK_SR_DCN60(CLK8_CLK_TICK_CNT_CONFIG_REG, CLK08, 0), \ + CLK_SR_DCN60(CLK8_CLK0_CURRENT_CNT, CLK08, 0), \ + CLK_SR_DCN60(CLK8_CLK1_CURRENT_CNT, CLK08, 0), \ + CLK_SR_DCN60(CLK8_CLK2_CURRENT_CNT, CLK08, 0), \ + CLK_SR_DCN60(CLK8_CLK3_CURRENT_CNT, CLK08, 0), \ + CLK_SR_DCN60(CLK8_CLK4_CURRENT_CNT, CLK08, 0), \ + CLK_SR_DCN60(CLK8_CLK0_BYPASS_CNTL, CLK08, 0), \ + CLK_SR_DCN60(CLK8_CLK1_BYPASS_CNTL, CLK08, 0), \ + CLK_SR_DCN60(CLK8_CLK2_BYPASS_CNTL, CLK08, 0), \ + CLK_SR_DCN60(CLK8_CLK3_BYPASS_CNTL, CLK08, 0), \ + CLK_SR_DCN60(CLK8_CLK4_BYPASS_CNTL, CLK08, 0), \ + CLK_SR_DCN60(CLK8_CLK0_DS_CNTL, CLK08, 0), \ + CLK_SR_DCN60(CLK8_CLK1_DS_CNTL, CLK08, 0), \ + CLK_SR_DCN60(CLK8_CLK2_DS_CNTL, CLK08, 0), \ + CLK_SR_DCN60(CLK8_CLK3_DS_CNTL, CLK08, 0), \ + CLK_SR_DCN60(CLK8_CLK4_DS_CNTL, CLK08, 0) + +#define CLK_COMMON_MASK_SH_LIST_DCN60(mask_sh) \ + CLK_COMMON_MASK_SH_LIST_DCN42(mask_sh) + #define CLK_REG_FIELD_LIST(type) \ type DPREFCLK_SRC_SEL; \ type DENTIST_DPREFCLK_WDIVIDER; \ @@ -406,6 +427,7 @@ struct clk_mgr_registers { uint32_t CLK6_spll_field_8; CLK42_REG_LIST(8, uint32_t) CLK42_REG_LIST(5, uint32_t) + uint32_t CLK8_CLK0_ALLOW_DS; }; struct clk_mgr_shift { diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw/cursor_reg_cache.h b/drivers/gpu/drm/amd/display/dc/inc/hw/cursor_reg_cache.h index 7ce2f417f86a..3932a4f766e2 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/hw/cursor_reg_cache.h +++ b/drivers/gpu/drm/amd/display/dc/inc/hw/cursor_reg_cache.h @@ -59,7 +59,8 @@ struct cursor_attribute_cache_hubp { struct { uint32_t dst_y_offset: 8; uint32_t chunk_hdl_adjust: 2; - uint32_t reserved: 22; + uint32_t force_cursor_to_disp_pref: 1; + uint32_t reserved: 21; } bits; uint32_t raw; } settings; diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw/dpp.h b/drivers/gpu/drm/amd/display/dc/inc/hw/dpp.h index 39215ecb480e..b31b144d2e8f 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/hw/dpp.h +++ b/drivers/gpu/drm/amd/display/dc/inc/hw/dpp.h @@ -375,6 +375,13 @@ struct dpp_funcs { bool (*dpp_cm_hist_read)( struct dpp *dpp_base, struct cm_hist *cm_hist); + void (*dpp_set_pregam_state)( + struct dpp *dpp_base, + enum dc_transfer_func_predefined tr, + enum dc_scaling_linearity scaling); + void (*dpp_program_upsp)( + struct dpp *dpp_base, + const struct dscl_prog_data *dscl_prog_data); }; diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw/link_encoder.h b/drivers/gpu/drm/amd/display/dc/inc/hw/link_encoder.h index e7727ed3300c..70545df981ef 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/hw/link_encoder.h +++ b/drivers/gpu/drm/amd/display/dc/inc/hw/link_encoder.h @@ -52,6 +52,7 @@ struct encoder_init_data { enum engine_id analog_engine; struct dc_context *ctx; enum transmitter transmitter; + bool hpd_active_high; }; struct encoder_feature_support { @@ -106,6 +107,7 @@ struct link_encoder { enum hpd_source_id hpd_source; bool usbc_combo_phy; uint8_t txffe_state; + bool hpd_active_high; }; struct link_enc_state { @@ -242,6 +244,10 @@ struct link_encoder_funcs { uint8_t digmode); bool (*get_hpd_state)(struct link_encoder *enc); bool (*program_hpd_filter)(struct link_encoder *enc, int delay_on_connect_in_ms, int delay_on_disconnect_in_ms); + + void (*setup_ri_pj_check_in_sw_or_hw_mode)(struct link_encoder *link_enc, + unsigned char aux_or_ddc_instance, + bool ri_pj_sw_mode); }; /* diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw/transform.h b/drivers/gpu/drm/amd/display/dc/inc/hw/transform.h index 30990355985d..d67373ec8e36 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/hw/transform.h +++ b/drivers/gpu/drm/amd/display/dc/inc/hw/transform.h @@ -164,6 +164,7 @@ struct scaler_data { struct line_buffer_params lb_params; // Below struct holds the scaler values to program hw registers struct dscl_prog_data dscl_prog_data; + enum upsp_mode upsp; }; struct transform_funcs { diff --git a/drivers/gpu/drm/amd/display/dc/inc/resource.h b/drivers/gpu/drm/amd/display/dc/inc/resource.h index d3171e70e07c..8e21aaac06b3 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/resource.h +++ b/drivers/gpu/drm/amd/display/dc/inc/resource.h @@ -123,6 +123,8 @@ void resource_build_test_pattern_params( struct resource_context *res_ctx, struct pipe_ctx *pipe_ctx); +enum upsp_mode resource_is_upsp_required(enum surface_pixel_format format); + bool resource_build_scaling_params(struct pipe_ctx *pipe_ctx); enum dc_status resource_build_scaling_params_for_context( diff --git a/drivers/gpu/drm/amd/display/dc/link/link_detection.c b/drivers/gpu/drm/amd/display/dc/link/link_detection.c index 4f18b668340c..22ad6a743038 100644 --- a/drivers/gpu/drm/amd/display/dc/link/link_detection.c +++ b/drivers/gpu/drm/amd/display/dc/link/link_detection.c @@ -336,6 +336,34 @@ static void query_dp_dual_mode_adaptor( sink_cap->max_hdmi_pixel_clock = DP_ADAPTOR_DVI_MAX_TMDS_CLK; /* Read DP-HDMI dongle I2c (no response interpreted as DP-DVI dongle)*/ + if (link->force_to_use_aux) { + + if (!dm_helpers_submit_i2c_over_aux( + ddc, + DP_HDMI_DONGLE_ADDRESS, + 0, + type2_dongle_buf, + sizeof(type2_dongle_buf), + true)) { + + /* Use same approach as below with native i2c - HDMI dongles can sometimes fail here without retrying*/ + while (retry_count > 0) { + if (dm_helpers_submit_i2c_over_aux( + ddc, + DP_HDMI_DONGLE_ADDRESS, + 0, + type2_dongle_buf, + sizeof(type2_dongle_buf), + true)) + break; + retry_count--; + } + /* In case I2C over Aux no response, it is interpreted as DISPLAY_DONGLE_NONE */ + if (retry_count == 0) { + return; + } + } + } else { if (!i2c_read( ddc, DP_HDMI_DONGLE_ADDRESS, @@ -360,6 +388,7 @@ static void query_dp_dual_mode_adaptor( return; } } + } /* Check if Type 2 dongle.*/ if (type2_dongle_buf[DP_ADAPTOR_TYPE2_REG_ID] == DP_ADAPTOR_TYPE2_ID) diff --git a/drivers/gpu/drm/amd/display/dc/link/link_factory.c b/drivers/gpu/drm/amd/display/dc/link/link_factory.c index 67ce8d95bbd6..89265b083935 100644 --- a/drivers/gpu/drm/amd/display/dc/link/link_factory.c +++ b/drivers/gpu/drm/amd/display/dc/link/link_factory.c @@ -577,6 +577,10 @@ static bool construct_phy(struct dc_link *link, link->is_internal_display = (disp_connect_caps_info.INTERNAL_DISPLAY != 0); DC_LOG_DC("BIOS object table - is_internal_display: %d", link->is_internal_display); link->no_ddc_pin = disp_connect_caps_info.NO_DDC_PIN != 0; + //reworked DP port on N-1 board, for testing on N-1, to be removed when IFWI ready + if (link->dc->config.dp_connector_no_native_i2c && + (link->link_id.enum_id == link->dc->config.link_index_with_no_ddc)) + link->no_ddc_pin = true; link->force_to_use_aux = link->dc->config.dp_connector_no_native_i2c && link->no_ddc_pin; } @@ -642,6 +646,7 @@ static bool construct_phy(struct dc_link *link, link->hpd_src = hpd_info.hpd_int_gpio_uid - 1; link->irq_source_hpd = DC_IRQ_SOURCE_HPD1 + link->hpd_src; enc_init_data.hpd_source = link->hpd_src; + enc_init_data.hpd_active_high = (hpd_info.hpd_active == 0) ? true : false; DC_LOG_DC("BIOS object table - hpd_int_gpio_uid id: %d", hpd_info.hpd_int_gpio_uid); } else { ASSERT(0); diff --git a/drivers/gpu/drm/amd/display/dc/link/protocols/link_ddc.c b/drivers/gpu/drm/amd/display/dc/link/protocols/link_ddc.c index f9d5a2441e38..6123b10977bf 100644 --- a/drivers/gpu/drm/amd/display/dc/link/protocols/link_ddc.c +++ b/drivers/gpu/drm/amd/display/dc/link/protocols/link_ddc.c @@ -423,6 +423,14 @@ int link_aux_transfer_raw(struct ddc_service *ddc, struct aux_payload *payload, enum aux_return_code_type *operation_result) { + if (ddc->ctx->dc->config.dp_connector_no_native_i2c && ddc->link->no_ddc_pin) { + /* Check whether aux to be processed via dmub or dcn directly */ + if (ddc->ctx->dc->debug.enable_dmub_aux_for_legacy_ddc) { + return dce_aux_transfer_dmub_raw(ddc, payload, operation_result); + } else { + return dce_aux_transfer_raw_without_ddc_pin(ddc, payload, operation_result); + } + } return dce_aux_transfer_raw(ddc, payload, operation_result); } diff --git a/drivers/gpu/drm/amd/display/dc/link/protocols/link_hdmi_frl.c b/drivers/gpu/drm/amd/display/dc/link/protocols/link_hdmi_frl.c index 2afdfc113675..75ec3b701d81 100644 --- a/drivers/gpu/drm/amd/display/dc/link/protocols/link_hdmi_frl.c +++ b/drivers/gpu/drm/amd/display/dc/link/protocols/link_hdmi_frl.c @@ -144,6 +144,11 @@ void hdmi_frl_retrieve_link_cap(struct dc_link *link, struct dc_sink *sink) if (link->link_enc->features.flags.bits.IS_FRL_12G_CAPABLE) encoder_link_rate = HDMI_FRL_LINK_RATE_12GBPS; + if (link->link_enc->features.flags.bits.IS_FRL_16G_CAPABLE) + encoder_link_rate = HDMI_FRL_LINK_RATE_16GBPS; + + if (link->link_enc->features.flags.bits.IS_FRL_20G_CAPABLE) + encoder_link_rate = HDMI_FRL_LINK_RATE_20GBPS; if (link->dc->debug.max_frl_rate != 0 && encoder_link_rate > link->dc->debug.max_frl_rate) encoder_link_rate = link->dc->debug.max_frl_rate; diff --git a/drivers/gpu/drm/amd/display/dc/optc/dcn42/dcn42_optc.c b/drivers/gpu/drm/amd/display/dc/optc/dcn42/dcn42_optc.c index a3431ec2f058..4370d64259e7 100644 --- a/drivers/gpu/drm/amd/display/dc/optc/dcn42/dcn42_optc.c +++ b/drivers/gpu/drm/amd/display/dc/optc/dcn42/dcn42_optc.c @@ -40,8 +40,8 @@ * results in the parameters. */ -static bool optc42_get_crc(struct timing_generator *optc, uint8_t idx, - uint32_t *r_cr, uint32_t *g_y, uint32_t *b_cb) +bool optc42_get_crc(struct timing_generator *optc, uint8_t idx, + uint32_t *r_cr, uint32_t *g_y, uint32_t *b_cb) { uint32_t field = 0; struct optc *optc1 = DCN10TG_FROM_TG(optc); diff --git a/drivers/gpu/drm/amd/display/dc/optc/dcn42/dcn42_optc.h b/drivers/gpu/drm/amd/display/dc/optc/dcn42/dcn42_optc.h index d652358eea22..758cddd9e64f 100644 --- a/drivers/gpu/drm/amd/display/dc/optc/dcn42/dcn42_optc.h +++ b/drivers/gpu/drm/amd/display/dc/optc/dcn42/dcn42_optc.h @@ -395,4 +395,6 @@ void optc42_clear_optc_underflow(struct timing_generator *optc); bool optc42_is_optc_underflow_occurred(struct timing_generator *optc); bool optc42_disable_crtc(struct timing_generator *optc); void optc42_lock_doublebuffer_enable(struct timing_generator *optc); +bool optc42_get_crc(struct timing_generator *optc, uint8_t idx, + uint32_t *r_cr, uint32_t *g_y, uint32_t *b_cb); #endif /* __DC_OPTC_DCN42_H__ */ diff --git a/drivers/gpu/drm/amd/display/dc/resource/dcn10/dcn10_resource.c b/drivers/gpu/drm/amd/display/dc/resource/dcn10/dcn10_resource.c index db1b6a1b92e8..37974c45b44a 100644 --- a/drivers/gpu/drm/amd/display/dc/resource/dcn10/dcn10_resource.c +++ b/drivers/gpu/drm/amd/display/dc/resource/dcn10/dcn10_resource.c @@ -1419,6 +1419,7 @@ static bool dcn10_resource_construct( dc->caps.color.dpp.post_csc = 0; dc->caps.color.dpp.gamma_corr = 0; dc->caps.color.dpp.dgam_rom_for_yuv = 1; + dc->caps.color.dpp.upsp_pre_scaler = 0; dc->caps.color.dpp.hw_3d_lut = 0; dc->caps.color.dpp.ogam_ram = 1; // RGAM on DCN1 diff --git a/drivers/gpu/drm/amd/display/dc/resource/dcn20/dcn20_resource.c b/drivers/gpu/drm/amd/display/dc/resource/dcn20/dcn20_resource.c index 95abc4c38eae..996fce26941f 100644 --- a/drivers/gpu/drm/amd/display/dc/resource/dcn20/dcn20_resource.c +++ b/drivers/gpu/drm/amd/display/dc/resource/dcn20/dcn20_resource.c @@ -2502,6 +2502,7 @@ static bool dcn20_resource_construct( dc->caps.color.dpp.post_csc = 0; dc->caps.color.dpp.gamma_corr = 0; dc->caps.color.dpp.dgam_rom_for_yuv = 1; + dc->caps.color.dpp.upsp_pre_scaler = 0; dc->caps.color.dpp.hw_3d_lut = 1; dc->caps.color.dpp.ogam_ram = 1; diff --git a/drivers/gpu/drm/amd/display/dc/resource/dcn201/dcn201_resource.c b/drivers/gpu/drm/amd/display/dc/resource/dcn201/dcn201_resource.c index 02b7dc07ad53..765c63513a31 100644 --- a/drivers/gpu/drm/amd/display/dc/resource/dcn201/dcn201_resource.c +++ b/drivers/gpu/drm/amd/display/dc/resource/dcn201/dcn201_resource.c @@ -1165,6 +1165,7 @@ static bool dcn201_resource_construct( dc->caps.color.dpp.post_csc = 0; dc->caps.color.dpp.gamma_corr = 0; dc->caps.color.dpp.dgam_rom_for_yuv = 1; + dc->caps.color.dpp.upsp_pre_scaler = 0; dc->caps.color.dpp.hw_3d_lut = 1; dc->caps.color.dpp.ogam_ram = 1; diff --git a/drivers/gpu/drm/amd/display/dc/resource/dcn21/dcn21_resource.c b/drivers/gpu/drm/amd/display/dc/resource/dcn21/dcn21_resource.c index b653f951e104..4095a850ebc6 100644 --- a/drivers/gpu/drm/amd/display/dc/resource/dcn21/dcn21_resource.c +++ b/drivers/gpu/drm/amd/display/dc/resource/dcn21/dcn21_resource.c @@ -1478,6 +1478,7 @@ static bool dcn21_resource_construct( dc->caps.color.dpp.post_csc = 0; dc->caps.color.dpp.gamma_corr = 0; dc->caps.color.dpp.dgam_rom_for_yuv = 1; + dc->caps.color.dpp.upsp_pre_scaler = 0; dc->caps.color.dpp.hw_3d_lut = 1; dc->caps.color.dpp.ogam_ram = 1; diff --git a/drivers/gpu/drm/amd/display/dc/resource/dcn30/dcn30_resource.c b/drivers/gpu/drm/amd/display/dc/resource/dcn30/dcn30_resource.c index 40fc66e64c1b..f09bbb932150 100644 --- a/drivers/gpu/drm/amd/display/dc/resource/dcn30/dcn30_resource.c +++ b/drivers/gpu/drm/amd/display/dc/resource/dcn30/dcn30_resource.c @@ -2496,6 +2496,7 @@ static bool dcn30_resource_construct( dc->caps.color.dpp.post_csc = 1; dc->caps.color.dpp.gamma_corr = 1; dc->caps.color.dpp.dgam_rom_for_yuv = 0; + dc->caps.color.dpp.upsp_pre_scaler = 0; dc->caps.color.dpp.hw_3d_lut = 1; dc->caps.color.dpp.ogam_ram = 1; diff --git a/drivers/gpu/drm/amd/display/dc/resource/dcn301/dcn301_resource.c b/drivers/gpu/drm/amd/display/dc/resource/dcn301/dcn301_resource.c index 551565ae9ef2..29113f518c53 100644 --- a/drivers/gpu/drm/amd/display/dc/resource/dcn301/dcn301_resource.c +++ b/drivers/gpu/drm/amd/display/dc/resource/dcn301/dcn301_resource.c @@ -1497,6 +1497,7 @@ static bool dcn301_resource_construct( dc->caps.color.dpp.post_csc = 1; dc->caps.color.dpp.gamma_corr = 1; dc->caps.color.dpp.dgam_rom_for_yuv = 0; + dc->caps.color.dpp.upsp_pre_scaler = 0; dc->caps.color.dpp.hw_3d_lut = 1; dc->caps.color.dpp.ogam_ram = 1; diff --git a/drivers/gpu/drm/amd/display/dc/resource/dcn302/dcn302_resource.c b/drivers/gpu/drm/amd/display/dc/resource/dcn302/dcn302_resource.c index 2574e706631d..d6b036e3933e 100644 --- a/drivers/gpu/drm/amd/display/dc/resource/dcn302/dcn302_resource.c +++ b/drivers/gpu/drm/amd/display/dc/resource/dcn302/dcn302_resource.c @@ -1397,6 +1397,7 @@ static bool dcn302_resource_construct( dc->caps.color.dpp.post_csc = 1; dc->caps.color.dpp.gamma_corr = 1; dc->caps.color.dpp.dgam_rom_for_yuv = 0; + dc->caps.color.dpp.upsp_pre_scaler = 0; dc->caps.color.dpp.hw_3d_lut = 1; dc->caps.color.dpp.ogam_ram = 1; diff --git a/drivers/gpu/drm/amd/display/dc/resource/dcn303/dcn303_resource.c b/drivers/gpu/drm/amd/display/dc/resource/dcn303/dcn303_resource.c index 8b24628e3e14..c8598ba23dd0 100644 --- a/drivers/gpu/drm/amd/display/dc/resource/dcn303/dcn303_resource.c +++ b/drivers/gpu/drm/amd/display/dc/resource/dcn303/dcn303_resource.c @@ -1341,6 +1341,7 @@ static bool dcn303_resource_construct( dc->caps.color.dpp.post_csc = 1; dc->caps.color.dpp.gamma_corr = 1; dc->caps.color.dpp.dgam_rom_for_yuv = 0; + dc->caps.color.dpp.upsp_pre_scaler = 0; dc->caps.color.dpp.hw_3d_lut = 1; dc->caps.color.dpp.ogam_ram = 1; diff --git a/drivers/gpu/drm/amd/display/dc/resource/dcn314/dcn314_resource.c b/drivers/gpu/drm/amd/display/dc/resource/dcn314/dcn314_resource.c index 372e05487847..5f08fb136b14 100644 --- a/drivers/gpu/drm/amd/display/dc/resource/dcn314/dcn314_resource.c +++ b/drivers/gpu/drm/amd/display/dc/resource/dcn314/dcn314_resource.c @@ -2032,6 +2032,7 @@ static bool dcn314_resource_construct( dc->caps.color.dpp.post_csc = 1; dc->caps.color.dpp.gamma_corr = 1; dc->caps.color.dpp.dgam_rom_for_yuv = 0; + dc->caps.color.dpp.upsp_pre_scaler = 0; dc->caps.color.dpp.hw_3d_lut = 1; dc->caps.color.dpp.ogam_ram = 1; diff --git a/drivers/gpu/drm/amd/display/dc/resource/dcn315/dcn315_resource.c b/drivers/gpu/drm/amd/display/dc/resource/dcn315/dcn315_resource.c index 6e112ef0a49a..7c78f8ba40ef 100644 --- a/drivers/gpu/drm/amd/display/dc/resource/dcn315/dcn315_resource.c +++ b/drivers/gpu/drm/amd/display/dc/resource/dcn315/dcn315_resource.c @@ -2076,6 +2076,7 @@ static bool dcn315_resource_construct( dc->caps.color.dpp.post_csc = 1; dc->caps.color.dpp.gamma_corr = 1; dc->caps.color.dpp.dgam_rom_for_yuv = 0; + dc->caps.color.dpp.upsp_pre_scaler = 0; dc->caps.color.dpp.hw_3d_lut = 1; dc->caps.color.dpp.ogam_ram = 1; diff --git a/drivers/gpu/drm/amd/display/dc/resource/dcn32/dcn32_resource.c b/drivers/gpu/drm/amd/display/dc/resource/dcn32/dcn32_resource.c index cd9d2087d14e..a20ff9f0c3f8 100644 --- a/drivers/gpu/drm/amd/display/dc/resource/dcn32/dcn32_resource.c +++ b/drivers/gpu/drm/amd/display/dc/resource/dcn32/dcn32_resource.c @@ -2428,6 +2428,7 @@ static bool dcn32_resource_construct( dc->caps.color.dpp.post_csc = 1; dc->caps.color.dpp.gamma_corr = 1; dc->caps.color.dpp.dgam_rom_for_yuv = 0; + dc->caps.color.dpp.upsp_pre_scaler = 0; dc->caps.color.dpp.hw_3d_lut = 0; dc->caps.color.dpp.ogam_ram = 0; // no OGAM in DPP since DCN1 diff --git a/drivers/gpu/drm/amd/display/dc/resource/dcn321/dcn321_resource.c b/drivers/gpu/drm/amd/display/dc/resource/dcn321/dcn321_resource.c index ff9c1379896e..105fba8ff171 100644 --- a/drivers/gpu/drm/amd/display/dc/resource/dcn321/dcn321_resource.c +++ b/drivers/gpu/drm/amd/display/dc/resource/dcn321/dcn321_resource.c @@ -1919,6 +1919,7 @@ static bool dcn321_resource_construct( dc->caps.color.dpp.post_csc = 1; dc->caps.color.dpp.gamma_corr = 1; dc->caps.color.dpp.dgam_rom_for_yuv = 0; + dc->caps.color.dpp.upsp_pre_scaler = 0; dc->caps.color.dpp.hw_3d_lut = 0; dc->caps.color.dpp.ogam_ram = 0; diff --git a/drivers/gpu/drm/amd/display/dc/resource/dcn35/dcn35_resource.c b/drivers/gpu/drm/amd/display/dc/resource/dcn35/dcn35_resource.c index 1b9b6eb8b322..a92e0dc5ad6a 100644 --- a/drivers/gpu/drm/amd/display/dc/resource/dcn35/dcn35_resource.c +++ b/drivers/gpu/drm/amd/display/dc/resource/dcn35/dcn35_resource.c @@ -2058,6 +2058,7 @@ static bool dcn35_resource_construct( dc->caps.color.dpp.post_csc = 1; dc->caps.color.dpp.gamma_corr = 1; dc->caps.color.dpp.dgam_rom_for_yuv = 0; + dc->caps.color.dpp.upsp_pre_scaler = 0; dc->caps.color.dpp.hw_3d_lut = 0; dc->caps.color.dpp.ogam_ram = 0; // no OGAM in DPP since DCN1 diff --git a/drivers/gpu/drm/amd/display/dc/resource/dcn351/dcn351_resource.c b/drivers/gpu/drm/amd/display/dc/resource/dcn351/dcn351_resource.c index 2268ced16969..68a2169da0c1 100644 --- a/drivers/gpu/drm/amd/display/dc/resource/dcn351/dcn351_resource.c +++ b/drivers/gpu/drm/amd/display/dc/resource/dcn351/dcn351_resource.c @@ -2031,6 +2031,7 @@ static bool dcn351_resource_construct( dc->caps.color.dpp.post_csc = 1; dc->caps.color.dpp.gamma_corr = 1; dc->caps.color.dpp.dgam_rom_for_yuv = 0; + dc->caps.color.dpp.upsp_pre_scaler = 0; dc->caps.color.dpp.hw_3d_lut = 0; dc->caps.color.dpp.ogam_ram = 0; // no OGAM in DPP since DCN1 diff --git a/drivers/gpu/drm/amd/display/dc/resource/dcn36/dcn36_resource.c b/drivers/gpu/drm/amd/display/dc/resource/dcn36/dcn36_resource.c index b1323e76801e..ba04e8b9b569 100644 --- a/drivers/gpu/drm/amd/display/dc/resource/dcn36/dcn36_resource.c +++ b/drivers/gpu/drm/amd/display/dc/resource/dcn36/dcn36_resource.c @@ -2028,6 +2028,7 @@ static bool dcn36_resource_construct( dc->caps.color.dpp.post_csc = 1; dc->caps.color.dpp.gamma_corr = 1; dc->caps.color.dpp.dgam_rom_for_yuv = 0; + dc->caps.color.dpp.upsp_pre_scaler = 0; dc->caps.color.dpp.hw_3d_lut = 0; dc->caps.color.dpp.ogam_ram = 0; // no OGAM in DPP since DCN1 diff --git a/drivers/gpu/drm/amd/display/dc/resource/dcn401/dcn401_resource.c b/drivers/gpu/drm/amd/display/dc/resource/dcn401/dcn401_resource.c index 181cb7135dfb..fff84f9ce816 100644 --- a/drivers/gpu/drm/amd/display/dc/resource/dcn401/dcn401_resource.c +++ b/drivers/gpu/drm/amd/display/dc/resource/dcn401/dcn401_resource.c @@ -305,19 +305,21 @@ static struct dcn10_link_enc_aux_registers link_enc_aux_regs[5]; static struct dcn10_link_enc_hpd_registers link_enc_hpd_regs[5]; -#define link_regs_init(id, phyid)\ - LE_DCN401_REG_LIST_RI(id) +#define link_regs_init(id, phyid) \ + LE_DCN401_REG_LIST_RI(id), \ + LE_DCN60_REG_LIST_RI(id) static struct dcn10_link_enc_registers link_enc_regs[4]; static const struct dcn10_link_enc_shift le_shift = { - LINK_ENCODER_MASK_SH_LIST_DCN401(__SHIFT) + LINK_ENCODER_MASK_SH_LIST_DCN401(__SHIFT), \ + LINK_ENCODER_MASK_SH_LIST_DCN60_ON_DCN401(__SHIFT) }; - static const struct dcn10_link_enc_mask le_mask = { - LINK_ENCODER_MASK_SH_LIST_DCN401(_MASK) + LINK_ENCODER_MASK_SH_LIST_DCN401(_MASK), \ + LINK_ENCODER_MASK_SH_LIST_DCN60_ON_DCN401(_MASK) }; @@ -602,8 +604,12 @@ static const struct dccg_mask dccg_mask = { static struct dce_hwseq_registers hwseq_reg; -#define hwseq_reg_init()\ - HWSEQ_DCN401_REG_LIST() +#define HWSEQ_DCN60_REG_LIST() \ + SR(HDCP_INTERRUPT_DEST) + +#define hwseq_reg_init() \ + HWSEQ_DCN401_REG_LIST(), \ + HWSEQ_DCN60_REG_LIST() #define HWSEQ_DCN401_MASK_SH_LIST(mask_sh)\ HWSEQ_DCN_MASK_SH_LIST(mask_sh), \ @@ -651,12 +657,20 @@ static struct dce_hwseq_registers hwseq_reg; HWS_SF(, ODM_MEM_PWR_CTRL3, ODM_MEM_UNASSIGNED_PWR_MODE, mask_sh), \ HWS_SF(, ODM_MEM_PWR_CTRL3, ODM_MEM_VBLANK_PWR_MODE, mask_sh) +#define HWSEQ_DCN60_MASK_SH_LIST(mask_sh) \ + HWS_SF(, HDCP_INTERRUPT_DEST, DOUT_IHC_HDCP0_I2C_XFER_REQ_INTERRUPT_DEST, mask_sh), \ + HWS_SF(, HDCP_INTERRUPT_DEST, DOUT_IHC_HDCP1_I2C_XFER_REQ_INTERRUPT_DEST, mask_sh), \ + HWS_SF(, HDCP_INTERRUPT_DEST, DOUT_IHC_HDCP2_I2C_XFER_REQ_INTERRUPT_DEST, mask_sh), \ + HWS_SF(, HDCP_INTERRUPT_DEST, DOUT_IHC_HDCP3_I2C_XFER_REQ_INTERRUPT_DEST, mask_sh) + static const struct dce_hwseq_shift hwseq_shift = { - HWSEQ_DCN401_MASK_SH_LIST(__SHIFT) + HWSEQ_DCN401_MASK_SH_LIST(__SHIFT), \ + HWSEQ_DCN60_MASK_SH_LIST(__SHIFT) }; static const struct dce_hwseq_mask hwseq_mask = { - HWSEQ_DCN401_MASK_SH_LIST(_MASK) + HWSEQ_DCN401_MASK_SH_LIST(_MASK), \ + HWSEQ_DCN60_MASK_SH_LIST(_MASK) }; #define vmid_regs_init(id)\ @@ -2111,6 +2125,7 @@ static bool dcn401_resource_construct( dc->caps.color.dpp.post_csc = 1; dc->caps.color.dpp.gamma_corr = 1; dc->caps.color.dpp.dgam_rom_for_yuv = 0; + dc->caps.color.dpp.upsp_pre_scaler = 0; dc->caps.color.dpp.hw_3d_lut = 0; dc->caps.color.dpp.ogam_ram = 0; diff --git a/drivers/gpu/drm/amd/display/dc/resource/dcn401/dcn401_resource.h b/drivers/gpu/drm/amd/display/dc/resource/dcn401/dcn401_resource.h index 42a0986d6fe2..8e3473f86490 100644 --- a/drivers/gpu/drm/amd/display/dc/resource/dcn401/dcn401_resource.h +++ b/drivers/gpu/drm/amd/display/dc/resource/dcn401/dcn401_resource.h @@ -236,6 +236,10 @@ int dcn401_get_power_profile(const struct dc_state *context); SRI_ARR(DIG_BE_CLK_CNTL, DIG, id),\ SR_ARR(DIO_CLK_CNTL, id) +#define LE_DCN60_REG_LIST_RI(id) \ + SRI_ARR(HDCP_I2C_CONTROL_0, DIG, id), \ + SRI_ARR(HDCP_INT_CONTROL, DIG, id) + /* DPP */ #define DPP_REG_LIST_DCN401_COMMON_RI(id) \ SRI_ARR(CM_DEALPHA, CM, id), SRI_ARR(CM_MEM_PWR_STATUS, CM, id), \ diff --git a/drivers/gpu/drm/amd/display/dc/resource/dcn42/dcn42_resource.c b/drivers/gpu/drm/amd/display/dc/resource/dcn42/dcn42_resource.c index dba1b69137f9..7507994f12d8 100644 --- a/drivers/gpu/drm/amd/display/dc/resource/dcn42/dcn42_resource.c +++ b/drivers/gpu/drm/amd/display/dc/resource/dcn42/dcn42_resource.c @@ -2066,6 +2066,7 @@ static bool dcn42_resource_construct( dc->caps.color.dpp.post_csc = 1; dc->caps.color.dpp.gamma_corr = 1; dc->caps.color.dpp.dgam_rom_for_yuv = 0; + dc->caps.color.dpp.upsp_pre_scaler = 0; dc->caps.color.dpp.hw_3d_lut = 0; dc->caps.color.dpp.ogam_ram = 0; diff --git a/drivers/gpu/drm/amd/display/dc/soc_and_ip_translator/soc_and_ip_translator.c b/drivers/gpu/drm/amd/display/dc/soc_and_ip_translator/soc_and_ip_translator.c index 1e3ee25732fa..3821846aa2d0 100644 --- a/drivers/gpu/drm/amd/display/dc/soc_and_ip_translator/soc_and_ip_translator.c +++ b/drivers/gpu/drm/amd/display/dc/soc_and_ip_translator/soc_and_ip_translator.c @@ -6,6 +6,7 @@ #include "soc_and_ip_translator/dcn401/dcn401_soc_and_ip_translator.h" #include "soc_and_ip_translator/dcn42/dcn42_soc_and_ip_translator.h" #include "soc_and_ip_translator/dcn42b/dcn42b_soc_and_ip_translator.h" +#include "soc_and_ip_translator/dcn60/dcn60_soc_and_ip_translator.h" static void dc_construct_soc_and_ip_translator(struct soc_and_ip_translator *soc_and_ip_translator, enum dce_version dc_version) @@ -20,6 +21,9 @@ static void dc_construct_soc_and_ip_translator(struct soc_and_ip_translator *soc case DCN_VERSION_4_2B: dcn42b_construct_soc_and_ip_translator(soc_and_ip_translator); break; + case DCN_VERSION_6_0: + dcn60_construct_soc_and_ip_translator(soc_and_ip_translator); + break; default: break; } diff --git a/drivers/gpu/drm/amd/display/dmub/dmub_srv.h b/drivers/gpu/drm/amd/display/dmub/dmub_srv.h index 94d4b40ee16a..d8a18cd97811 100644 --- a/drivers/gpu/drm/amd/display/dmub/dmub_srv.h +++ b/drivers/gpu/drm/amd/display/dmub/dmub_srv.h @@ -122,6 +122,8 @@ enum dmub_asic { DMUB_ASIC_DCN401, DMUB_ASIC_DCN42, DMUB_ASIC_DCN42B, + DMUB_ASIC_DCN60, + DMUB_ASIC_MAX, }; @@ -318,6 +320,8 @@ struct dmub_srv_fb_info { struct dmub_soc_fb_info { uint64_t fb_base; uint64_t fb_offset; + uint32_t alt_channel_region_size[2]; + uint64_t alt_channel_region_base[2]; /* mc address */ }; /* @@ -608,6 +612,7 @@ struct dmub_srv { struct dmub_srv_dcn35_regs *regs_dcn35; const struct dmub_srv_dcn401_regs *regs_dcn401; struct dmub_srv_dcn42_regs *regs_dcn42; + const struct dmub_srv_dcn60_regs *regs_dcn60; struct dmub_srv_base_funcs funcs; struct dmub_srv_hw_funcs hw_funcs; struct dmub_srv_inbox inbox1; diff --git a/drivers/gpu/drm/amd/display/dmub/inc/dmub_cmd.h b/drivers/gpu/drm/amd/display/dmub/inc/dmub_cmd.h index e7879bd81f83..44aefa3608ec 100644 --- a/drivers/gpu/drm/amd/display/dmub/inc/dmub_cmd.h +++ b/drivers/gpu/drm/amd/display/dmub/inc/dmub_cmd.h @@ -910,6 +910,41 @@ struct dmub_cursor_offload_pipe_data_dcn401_v1 { uint32_t reserved2[3]; }; +/** + * struct dmub_cursor_offload_pipe_data_dcn60_v1 - DCN60 per pipe data. + */ +struct dmub_cursor_offload_pipe_data_dcn60_v1 { + uint32_t CURSOR0_0_CURSOR_SURFACE_ADDRESS; + uint32_t CURSOR0_0_CURSOR_SURFACE_ADDRESS_HIGH; + uint32_t CURSOR0_0_CURSOR_SIZE__CURSOR_WIDTH : 16; + uint32_t CURSOR0_0_CURSOR_SIZE__CURSOR_HEIGHT : 16; + uint32_t CURSOR0_0_CURSOR_POSITION__CURSOR_X_POSITION : 16; + uint32_t CURSOR0_0_CURSOR_POSITION__CURSOR_Y_POSITION : 16; + uint32_t CURSOR0_0_CURSOR_HOT_SPOT__CURSOR_HOT_SPOT_X : 16; + uint32_t CURSOR0_0_CURSOR_HOT_SPOT__CURSOR_HOT_SPOT_Y : 16; + uint32_t CURSOR0_0_CURSOR_DST_OFFSET__CURSOR_DST_X_OFFSET : 13; + uint32_t CURSOR0_0_CURSOR_CONTROL__CURSOR_ENABLE : 1; + uint32_t CURSOR0_0_CURSOR_CONTROL__CURSOR_MODE : 3; + uint32_t CURSOR0_0_CURSOR_CONTROL__CURSOR_2X_MAGNIFY : 1; + uint32_t CURSOR0_0_CURSOR_CONTROL__CURSOR_PITCH : 2; + uint32_t CURSOR0_0_CURSOR_CONTROL__CURSOR_LINES_PER_CHUNK : 5; + uint32_t reserved0[4]; + uint32_t CM_CUR0_CURSOR0_CONTROL__CUR0_ENABLE : 1; + uint32_t CM_CUR0_CURSOR0_CONTROL__CUR0_MODE : 3; + uint32_t CM_CUR0_CURSOR0_CONTROL__CUR0_EXPANSION_MODE : 1; + uint32_t CM_CUR0_CURSOR0_CONTROL__CUR0_ROM_EN : 1; + uint32_t CM_CUR0_CURSOR0_COLOR0__CUR0_COLOR0 : 24; + uint32_t CM_CUR0_CURSOR0_COLOR1__CUR0_COLOR1 : 24; + uint32_t CM_CUR0_CURSOR0_FP_SCALE_BIAS_G_Y__CUR0_FP_BIAS_G_Y : 16; + uint32_t CM_CUR0_CURSOR0_FP_SCALE_BIAS_G_Y__CUR0_FP_SCALE_G_Y, : 16; + uint32_t CM_CUR0_CURSOR0_FP_SCALE_BIAS_RB_CRCB__CUR0_FP_BIAS_RB_CRCB : 16; + uint32_t CM_CUR0_CURSOR0_FP_SCALE_BIAS_RB_CRCB__CUR0_FP_SCALE_RB_CRCB : 16; + uint32_t reserved1[4]; + uint32_t HUBPREQ0_CURSOR_SETTINGS__CURSOR0_DST_Y_OFFSET : 8; + uint32_t HUBPREQ0_CURSOR_SETTINGS__CURSOR0_CHUNK_HDL_ADJUST : 8; + uint32_t HUBPREQ0_CURSOR_SETTINGS__FORCE_CURSOR_TO_DISP_PREF : 1; + uint32_t reserved2[3]; +}; /** * struct dmub_cursor_offload_pipe_data_v1 - Per pipe data for cursor offload. */ @@ -917,6 +952,7 @@ struct dmub_cursor_offload_pipe_data_v1 { union { struct dmub_cursor_offload_pipe_data_dcn30_v1 dcn30; /**< DCN30 cursor data. */ struct dmub_cursor_offload_pipe_data_dcn401_v1 dcn401; /**< DCN401 cursor data. */ + struct dmub_cursor_offload_pipe_data_dcn60_v1 dcn60; /**< DCN60 cursor data. */ uint8_t payload[96]; /**< Guarantees the cursor pipe data size per-pipe. */ }; }; @@ -2465,6 +2501,7 @@ enum fams2_stream_type { FAMS2_STREAM_TYPE_VACTIVE = 2, FAMS2_STREAM_TYPE_DRR = 3, FAMS2_STREAM_TYPE_SUBVP = 4, + FAMS2_STREAM_TYPE_ALTERNATE = 5, }; struct dmub_rect16 { @@ -2489,6 +2526,140 @@ struct dmub_rect16 { uint16_t height; }; +struct plane_pipe_rect { + struct dmub_rect16 luma; + struct dmub_rect16 chroma; +}; + +/** + * Structure to hold the LSDMA source / dest copy parameters. + * Each field is an array of [2][4]: + * [2] - Instance 0 is the copy for current frame, instance 1 is the copy for next frame (instance 1 potentially unused if no next) + * [4] - One instance per pipe + */ + +struct lsdma_outputs { + uint16_t src_x[2][4]; // src x position for the copy. Array of [2][4] for curr vs. next and each pipe + uint16_t src_y[2][4]; // src y position for the copy + uint16_t dst_x[2][4]; // dst x position for the copy (can change for curr vs. next) + uint16_t dst_y[2][4]; // dst y position for the copy (can change for curr vs. next) + uint16_t width[2][4]; // src and dst width for the copy (src and dst must match) + uint16_t height[2][4]; // src and dst height for the copy (src and dst must match) + uint16_t dst_pitch[4]; // dst pitch for the copy (same for curr and next) +}; + +struct dmub_fams2_alternate_stream_dynamic_state { + uint64_t earliest_init_tick; // track earliest possible init tick for calculating is_tick_in_allow + uint32_t otg_frame_pending_clear[3]; // In this context pending means prefetch has never been completed for this frame yet + uint8_t flip_pending_clear_order[3]; + uint8_t num_pending_flips; + uint32_t prefetch_start_line_x1000[3]; // can compute from existing params, but store because we use this multiple times + uint16_t prefetch_end_line[3]; // can compute from existing params, but store because we use this multiple times + uint16_t recout_y[3]; + uint8_t flip_pending[3]; + uint8_t copy_from_earliest[3]; + uint16_t lsdma_bandwidth_mbps; + uint16_t vstartup_line; + uint16_t vready_line; + uint8_t cursor_size[3]; // Cursor array per plane for now - if we assume a single cursor, then we don't need an array + uint8_t pad; // to maintain alignment for below fields - re-arrange structure once all fields are finalized + /* outputs: */ + uint16_t subvp_start_line_a[3]; + uint16_t subvp_height_a[3]; + uint16_t subvp_next_start_line_a[3]; + uint16_t subvp_next_height_a[3]; + uint16_t subvp_start_line_b[3]; + uint16_t subvp_height_b[3]; + uint16_t subvp_next_start_line_b[3]; + uint16_t subvp_next_height_b[3]; + uint16_t subvp_c_start_line_a[3]; + uint16_t subvp_c_height_a[3]; + uint16_t subvp_c_next_start_line_a[3]; + uint16_t subvp_c_next_height_a[3]; + uint16_t subvp_c_start_line_b[3]; + uint16_t subvp_c_height_b[3]; + uint16_t subvp_c_next_start_line_b[3]; + uint16_t subvp_c_next_height_b[3]; + uint8_t subvp_position[3]; + uint8_t pad1[1]; // to maintain alignment for below fields - re-arrange structure once all fields are finalized + uint32_t program_go_line; + uint32_t program_go_frame_count; + uint16_t svp0_start_dst_line; + uint16_t svp0_end_dst_line; + uint16_t svp1_start_dst_line; + uint16_t svp1_end_dst_line; + struct lsdma_outputs lsdma[2]; // [2] - instance per SVP0 and SVP1 + struct lsdma_outputs lsdma_c[2]; // [2] - instance per SVP0 and SVP1 +}; +struct dmub_fams2_cmd_alternate_stream_static_state { + uint32_t total_bytes_to_copy; + uint16_t svp0_dst_lines; // per stream + uint16_t svp1_dst_lines; // per stream + uint16_t min_lead_dst_lines; // per stream, should be max(nominal_req_limit, vstartup_to_vactive). Does not have to be maxed over all planes + uint16_t svp_req_limit; // per stream, should be the same value in time between all streams max(2 swaths, dst_y_pre) over all planes + uint16_t fw_delays; + uint16_t vstartup_start; + uint16_t rec_height[3]; + uint16_t viewport_start[3]; + uint16_t viewport_size[3]; // for now size will be the number of lines perpendicular to scan direction (height for 0 / 180, width for 90 and 270) + uint16_t viewport_start_c[3]; + uint16_t viewport_size_c[3]; + uint16_t surface_pitch[3]; + uint16_t surface_pitch_c[3]; + uint16_t surface_height[3]; + uint16_t surface_height_c[3]; + uint8_t element_size[3]; + uint8_t element_size_c[3]; + uint8_t swizzle_mode[3]; // TODO: Add mapping, should be value used in LSDMA command + uint8_t vready_offset_lines; // vready offset from vstartup in lines (rounded up, as the actual offset may be a fraction of a line) + uint16_t dst_y_prefetch_x1000[3]; + uint16_t total_swaths[3]; + uint16_t total_swaths_c[3]; + uint8_t prefetch_swaths[3]; + uint8_t prefetch_swaths_c[3]; + uint8_t swath_height[3]; + uint8_t swath_height_c[3]; + uint16_t block_256b_width[3]; + uint16_t block_256b_height[3]; + uint16_t block_256b_width_c[3]; + uint16_t block_256b_height_c[3]; + uint16_t macro_tile_width[3]; + uint16_t macro_tile_width_c[3]; + union { + struct { + uint8_t is_multi_planar : 1; + uint8_t is_yuv420 : 1; + uint8_t prefetch_relative_vblank : 1; + uint8_t vertical_access : 1; // vertical_access = 1 means 90 or 270 rotation + uint8_t access_direction : 1; // access_direction = 1 means bigger to smaller coordinations (e.g., scan from 2160 to 0 as opposed to regular 0 to 2160) + uint8_t dcc : 1; + uint8_t tmz : 1; // TODO: Need to assign outside of DML (DML not aware of TMZ) + } bits; + uint8_t all; + } config[3]; + uint8_t max_cursor_size; + uint16_t pre_hdl_delta_x1000[3]; + uint16_t pre_hdl_delta_c_x1000[3]; + uint16_t rec_hdl_delta_x1000[3]; + uint16_t rec_hdl_delta_c_x1000[3]; + uint16_t dst_y_per_vm_vblank_x1000[3]; + uint16_t dst_y_per_row_vblank_x1000[3]; + uint16_t dst_y_after_scaler[3]; + uint16_t vinit_prefill[3]; + uint16_t vinit_prefill_c[3]; + uint16_t vratio_x1000[3]; + uint16_t vratio_c_x1000[3]; + struct plane_pipe_rect pipe_viewports[4]; + /* TODO - remove these deprecated vars */ + uint32_t pipe_copy_offset[2][4]; // [2] - SVP0/1, [4] - 4 pipes + uint32_t pipe_copy_offset_c[2][4]; + /* bits 47:16 of the surface address */ + uint32_t pipe_copy_addr_47_16[2][4]; // [2] - SVP0/1, [4] - 4 pipes + uint32_t pipe_copy_addr_47_16_c[2][4]; + uint32_t pipe_copy_max_size[2][4]; + uint32_t pipe_copy_max_size_c[2][4]; +}; + /* static stream state */ struct dmub_fams2_legacy_stream_static_state { uint8_t vactive_det_fill_delay_otg_vlines; @@ -2567,6 +2738,7 @@ union dmub_fams2_cmd_stream_static_sub_state { union dmub_fams2_stream_static_sub_state_v2 { COMMON_STREAM_STATIC_SUB_STATE + struct dmub_fams2_cmd_alternate_stream_static_state alternate; }; //v2 struct dmub_fams2_stream_static_state { @@ -2660,7 +2832,8 @@ union dmub_fams2_global_feature_config { uint32_t enable_visual_confirm: 1; uint32_t allow_delay_check_mode: 2; uint32_t legacy_method_no_fams2 : 1; - uint32_t reserved : 23; + uint32_t alternate_channel_workaround : 1; + uint32_t reserved: 22; } bits; uint32_t all; }; diff --git a/drivers/gpu/drm/amd/display/dmub/src/dmub_srv.c b/drivers/gpu/drm/amd/display/dmub/src/dmub_srv.c index 5a1a2276c432..204375f1eff8 100644 --- a/drivers/gpu/drm/amd/display/dmub/src/dmub_srv.c +++ b/drivers/gpu/drm/amd/display/dmub/src/dmub_srv.c @@ -42,6 +42,7 @@ #include "dmub_dcn401.h" #include "dmub_dcn42.h" #include "dmub_dcn42b.h" +#include "dmub_dcn60.h" #include "os_types.h" /* * Note: the DMUB service is standalone. No additional headers should be @@ -528,6 +529,57 @@ static bool dmub_srv_hw_setup(struct dmub_srv *dmub, enum dmub_asic asic) funcs->enable_reg_inbox0_rsp_int = dmub_dcn401_enable_reg_inbox0_rsp_int; funcs->enable_reg_outbox0_rdy_int = dmub_dcn401_enable_reg_outbox0_rdy_int; break; + case DMUB_ASIC_DCN60: + dmub->regs_dcn60 = &dmub_srv_dcn60_regs; + funcs->configure_dmub_in_system_memory = dmub_dcn60_configure_dmub_in_system_memory; + funcs->send_inbox0_cmd = dmub_dcn60_send_inbox0_cmd; + funcs->clear_inbox0_ack_register = dmub_dcn60_clear_inbox0_ack_register; + funcs->read_inbox0_ack_register = dmub_dcn60_read_inbox0_ack_register; + funcs->reset = dmub_dcn60_reset; + funcs->reset_release = dmub_dcn60_reset_release; + funcs->backdoor_load = dmub_dcn60_backdoor_load; + funcs->backdoor_load_zfb_mode = dmub_dcn60_backdoor_load_zfb_mode; + funcs->setup_windows = dmub_dcn60_setup_windows; + funcs->setup_mailbox = dmub_dcn60_setup_mailbox; + funcs->get_inbox1_wptr = dmub_dcn60_get_inbox1_wptr; + funcs->get_inbox1_rptr = dmub_dcn60_get_inbox1_rptr; + funcs->set_inbox1_wptr = dmub_dcn60_set_inbox1_wptr; + funcs->setup_out_mailbox = dmub_dcn60_setup_out_mailbox; + funcs->get_outbox1_wptr = dmub_dcn60_get_outbox1_wptr; + funcs->set_outbox1_rptr = dmub_dcn60_set_outbox1_rptr; + funcs->is_supported = dmub_dcn60_is_supported; + funcs->is_hw_init = dmub_dcn60_is_hw_init; + funcs->set_gpint = dmub_dcn60_set_gpint; + funcs->is_gpint_acked = dmub_dcn60_is_gpint_acked; + funcs->get_gpint_response = dmub_dcn60_get_gpint_response; + funcs->get_gpint_dataout = dmub_dcn60_get_gpint_dataout; + funcs->get_fw_status = dmub_dcn60_get_fw_boot_status; + funcs->enable_dmub_boot_options = dmub_dcn60_enable_dmub_boot_options; + funcs->skip_dmub_panel_power_sequence = dmub_dcn60_skip_dmub_panel_power_sequence; + //outbox0 call stacks + funcs->setup_outbox0 = dmub_dcn60_setup_outbox0; + funcs->get_outbox0_wptr = dmub_dcn60_get_outbox0_wptr; + funcs->set_outbox0_rptr = dmub_dcn60_set_outbox0_rptr; + + funcs->get_current_time = dmub_dcn60_get_current_time; + funcs->get_diagnostic_data = dmub_dcn60_get_diagnostic_data; + + funcs->send_reg_inbox0_cmd_msg = dmub_dcn60_send_reg_inbox0_cmd_msg; + funcs->read_reg_inbox0_rsp_int_status = dmub_dcn60_read_reg_inbox0_rsp_int_status; + funcs->read_reg_inbox0_cmd_rsp = dmub_dcn60_read_reg_inbox0_cmd_rsp; + funcs->write_reg_inbox0_rsp_int_ack = dmub_dcn60_write_reg_inbox0_rsp_int_ack; + funcs->clear_reg_inbox0_rsp_int_ack = dmub_dcn60_clear_reg_inbox0_rsp_int_ack; + funcs->enable_reg_inbox0_rsp_int = dmub_dcn60_enable_reg_inbox0_rsp_int; + default_inbox_type = DMUB_CMD_INTERFACE_FB; // still default to FB for now + + funcs->write_reg_outbox0_rdy_int_ack = dmub_dcn60_write_reg_outbox0_rdy_int_ack; + funcs->read_reg_outbox0_msg = dmub_dcn60_read_reg_outbox0_msg; + funcs->write_reg_outbox0_rsp = dmub_dcn60_write_reg_outbox0_rsp; + funcs->read_reg_outbox0_rdy_int_status = dmub_dcn60_read_reg_outbox0_rdy_int_status; + funcs->read_reg_outbox0_rsp_int_status = dmub_dcn60_read_reg_outbox0_rsp_int_status; + funcs->enable_reg_inbox0_rsp_int = dmub_dcn60_enable_reg_inbox0_rsp_int; + funcs->enable_reg_outbox0_rdy_int = dmub_dcn60_enable_reg_outbox0_rdy_int; + break; default: return false; } diff --git a/drivers/gpu/drm/amd/display/include/dal_asic_id.h b/drivers/gpu/drm/amd/display/include/dal_asic_id.h index ca77d29ebacc..7ed785be8473 100644 --- a/drivers/gpu/drm/amd/display/include/dal_asic_id.h +++ b/drivers/gpu/drm/amd/display/include/dal_asic_id.h @@ -266,6 +266,24 @@ enum { #define ASICREV_IS_DCN36(eChipRev) ((eChipRev) >= 0x50 && (eChipRev) < 0xC0) #define AMDGPU_FAMILY_GC_12_0_0 152 /* GC 12.0.0 */ +#define AMDGPU_FAMILY_GC_13_0_1 153 /*We may need an update if we find DCN5 and DCN6 + do not share the same GFX version*/ +enum { + DCN6_VARIANT0_A0 = 0x1, + DCN6_VARIANT1_A0 = DCN6_VARIANT0_A0, + DCN6_VARIANT2_A0 = 0x10, + DCN6_VARIANT2_B0 = 0x11, + DCN6_VARIANT3_A0 = 0x20, + DCN6_VARIANT3_UPPER = 0x2F, + DCN6_UNKNOWN = 0xFF +}; + +#define ASICREV_IS_DCN6_VARIANT0(eChipRev) (eChipRev < DCN6_VARIANT2_A0) +#define ASICREV_IS_DCN6_VARIANT1(eChipRev) ASICREV_IS_DCN_VARIANT0(eChipRev) +#define ASICREV_IS_DCN6_VARIANT2(eChipRev) (eChipRev >= DCN6_VARIANT2_A0 && eChipRev < DCN6_VARIANT3_A0) +#define ASICREV_IS_DCN6_VARIANT2_A0(eChipRev) (eChipRev >= DCN6_VARIANT2_A0 && eChipRev < DCN6_VARIANT2_B0) +#define ASICREV_IS_DCN6_VARIANT2_B0(eChipRev) (eChipRev >= DCN6_VARIANT2_B0 && eChipRev < DCN6_VARIANT3_A0) +#define ASICREV_IS_DCN6_VARIANT3(eChipRev) (eChipRev >= DCN6_VARIANT3_A0 && eChipRev <= DCN6_VARIANT3_UPPER) enum { GC_12_0_0_A0 = 0x50, -- 2.34.1