diff options
Diffstat (limited to 'drivers/gpu/drm/amd/display/dc')
67 files changed, 1335 insertions, 629 deletions
diff --git a/drivers/gpu/drm/amd/display/dc/basics/conversion.c b/drivers/gpu/drm/amd/display/dc/basics/conversion.c index 50b47f11875c..24ed03d8cda7 100644 --- a/drivers/gpu/drm/amd/display/dc/basics/conversion.c +++ b/drivers/gpu/drm/amd/display/dc/basics/conversion.c @@ -24,6 +24,7 @@ */ #include "dm_services.h" +#include "conversion.h" #define DIVIDER 10000 diff --git a/drivers/gpu/drm/amd/display/dc/basics/fixpt31_32.c b/drivers/gpu/drm/amd/display/dc/basics/fixpt31_32.c index 1e9a2d352068..1726bdf89bae 100644 --- a/drivers/gpu/drm/amd/display/dc/basics/fixpt31_32.c +++ b/drivers/gpu/drm/amd/display/dc/basics/fixpt31_32.c @@ -26,6 +26,10 @@ #include "dm_services.h" #include "include/fixed31_32.h" +static const struct fixed31_32 dc_fixpt_two_pi = { 26986075409LL }; +static const struct fixed31_32 dc_fixpt_ln2 = { 2977044471LL }; +static const struct fixed31_32 dc_fixpt_ln2_div_2 = { 1488522236LL }; + static inline unsigned long long abs_i64( long long arg) { diff --git a/drivers/gpu/drm/amd/display/dc/basics/vector.c b/drivers/gpu/drm/amd/display/dc/basics/vector.c index 8f93d25f91ee..706c803c4d3b 100644 --- a/drivers/gpu/drm/amd/display/dc/basics/vector.c +++ b/drivers/gpu/drm/amd/display/dc/basics/vector.c @@ -52,7 +52,7 @@ bool dal_vector_construct( return true; } -bool dal_vector_presized_costruct( +static bool dal_vector_presized_costruct( struct vector *vector, struct dc_context *ctx, uint32_t count, diff --git a/drivers/gpu/drm/amd/display/dc/bios/bios_parser.c b/drivers/gpu/drm/amd/display/dc/bios/bios_parser.c index ad394aefa5d9..23a373ca94b5 100644 --- a/drivers/gpu/drm/amd/display/dc/bios/bios_parser.c +++ b/drivers/gpu/drm/amd/display/dc/bios/bios_parser.c @@ -1198,6 +1198,7 @@ static enum bp_result bios_parser_get_embedded_panel_info( default: break; } + break; default: break; } diff --git a/drivers/gpu/drm/amd/display/dc/bios/bios_parser2.c b/drivers/gpu/drm/amd/display/dc/bios/bios_parser2.c index 43922fa358a9..670c26583817 100644 --- a/drivers/gpu/drm/amd/display/dc/bios/bios_parser2.c +++ b/drivers/gpu/drm/amd/display/dc/bios/bios_parser2.c @@ -903,6 +903,7 @@ static enum bp_result bios_parser_get_soc_bb_info( break; case 4: result = get_soc_bb_info_v4_4(bp, soc_bb_info); + break; default: break; } @@ -1019,6 +1020,7 @@ static enum bp_result bios_parser_get_embedded_panel_info( default: break; } + break; default: break; } @@ -1453,6 +1455,72 @@ static struct atom_encoder_caps_record *get_encoder_cap_record( return NULL; } +static struct atom_disp_connector_caps_record *get_disp_connector_caps_record( + struct bios_parser *bp, + struct atom_display_object_path_v2 *object) +{ + struct atom_common_record_header *header; + uint32_t offset; + + if (!object) { + BREAK_TO_DEBUGGER(); /* Invalid object */ + return NULL; + } + + offset = object->disp_recordoffset + bp->object_info_tbl_offset; + + for (;;) { + header = GET_IMAGE(struct atom_common_record_header, offset); + + if (!header) + return NULL; + + offset += header->record_size; + + if (header->record_type == LAST_RECORD_TYPE || + !header->record_size) + break; + + if (header->record_type != ATOM_DISP_CONNECTOR_CAPS_RECORD_TYPE) + continue; + + if (sizeof(struct atom_disp_connector_caps_record) <= + header->record_size) + return (struct atom_disp_connector_caps_record *)header; + } + + return NULL; +} + +static enum bp_result bios_parser_get_disp_connector_caps_info( + struct dc_bios *dcb, + struct graphics_object_id object_id, + struct bp_disp_connector_caps_info *info) +{ + struct bios_parser *bp = BP_FROM_DCB(dcb); + struct atom_display_object_path_v2 *object; + struct atom_disp_connector_caps_record *record = NULL; + + if (!info) + return BP_RESULT_BADINPUT; + + object = get_bios_object(bp, object_id); + + if (!object) + return BP_RESULT_BADINPUT; + + record = get_disp_connector_caps_record(bp, object); + if (!record) + return BP_RESULT_NORECORD; + + info->INTERNAL_DISPLAY = (record->connectcaps & ATOM_CONNECTOR_CAP_INTERNAL_DISPLAY) + ? 1 : 0; + info->INTERNAL_DISPLAY_BL = (record->connectcaps & ATOM_CONNECTOR_CAP_INTERNAL_DISPLAY_BL) + ? 1 : 0; + + return BP_RESULT_OK; +} + static enum bp_result get_vram_info_v23( struct bios_parser *bp, struct dc_vram_info *info) @@ -2461,6 +2529,8 @@ static const struct dc_vbios_funcs vbios_funcs = { .enable_lvtma_control = bios_parser_enable_lvtma_control, .get_soc_bb_info = bios_parser_get_soc_bb_info, + + .get_disp_connector_caps_info = bios_parser_get_disp_connector_caps_info, }; static bool bios_parser2_construct( 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 73c91027572b..995ffbbf64e7 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 @@ -94,7 +94,7 @@ void clk_mgr_exit_optimized_pwr_state(const struct dc *dc, struct clk_mgr *clk_m if (edp_link) { clk_mgr->psr_allow_active_cache = edp_link->psr_settings.psr_allow_active; - dc_link_set_psr_allow_active(edp_link, false, false); + dc_link_set_psr_allow_active(edp_link, false, false, false); } } @@ -104,7 +104,8 @@ void clk_mgr_optimize_pwr_state(const struct dc *dc, struct clk_mgr *clk_mgr) struct dc_link *edp_link = get_edp_link(dc); if (edp_link) - dc_link_set_psr_allow_active(edp_link, clk_mgr->psr_allow_active_cache, false); + dc_link_set_psr_allow_active(edp_link, + clk_mgr->psr_allow_active_cache, false, false); if (dc->hwss.optimize_pwr_state) dc->hwss.optimize_pwr_state(dc, dc->current_state); diff --git a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn21/rn_clk_mgr.c b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn21/rn_clk_mgr.c index c42d2f4e81e8..6f4fe8fce6b7 100644 --- a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn21/rn_clk_mgr.c +++ b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn21/rn_clk_mgr.c @@ -103,6 +103,31 @@ void rn_set_low_power_state(struct clk_mgr *clk_mgr_base) clk_mgr_base->clks.pwr_state = DCN_PWR_STATE_LOW_POWER; } +static void rn_update_clocks_update_dpp_dto(struct clk_mgr_internal *clk_mgr, + struct dc_state *context, int ref_dpp_clk, bool safe_to_lower) +{ + int i; + + clk_mgr->dccg->ref_dppclk = ref_dpp_clk; + + for (i = 0; i < clk_mgr->base.ctx->dc->res_pool->pipe_count; i++) { + int dpp_inst, dppclk_khz, prev_dppclk_khz; + + /* Loop index will match dpp->inst if resource exists, + * and we want to avoid dependency on dpp object + */ + dpp_inst = i; + dppclk_khz = context->res_ctx.pipe_ctx[i].plane_res.bw.dppclk_khz; + + prev_dppclk_khz = clk_mgr->dccg->pipe_dppclk_khz[i]; + + if (safe_to_lower || prev_dppclk_khz < dppclk_khz) + clk_mgr->dccg->funcs->update_dpp_dto( + clk_mgr->dccg, dpp_inst, dppclk_khz); + } +} + + void rn_update_clocks(struct clk_mgr *clk_mgr_base, struct dc_state *context, bool safe_to_lower) @@ -158,13 +183,20 @@ void rn_update_clocks(struct clk_mgr *clk_mgr_base, // workaround: Limit dppclk to 100Mhz to avoid lower eDP panel switch to plus 4K monitor underflow. // Do not adjust dppclk if dppclk is 0 to avoid unexpected result - if (!IS_DIAG_DC(dc->ctx->dce_environment)) { - if (new_clocks->dppclk_khz < 100000 && new_clocks->dppclk_khz > 0) - new_clocks->dppclk_khz = 100000; + if (new_clocks->dppclk_khz < 100000 && new_clocks->dppclk_khz > 0) + new_clocks->dppclk_khz = 100000; + + /* + * Temporally ignore thew 0 cases for disp and dpp clks. + * We may have a new feature that requires 0 clks in the future. + */ + if (new_clocks->dppclk_khz == 0 || new_clocks->dispclk_khz == 0) { + new_clocks->dppclk_khz = clk_mgr_base->clks.dppclk_khz; + new_clocks->dispclk_khz = clk_mgr_base->clks.dispclk_khz; } - if (should_set_clock(safe_to_lower, new_clocks->dppclk_khz, clk_mgr->base.clks.dppclk_khz)) { - if (clk_mgr->base.clks.dppclk_khz > new_clocks->dppclk_khz) + if (should_set_clock(safe_to_lower, new_clocks->dppclk_khz, clk_mgr_base->clks.dppclk_khz)) { + if (clk_mgr_base->clks.dppclk_khz > new_clocks->dppclk_khz) dpp_clock_lowered = true; clk_mgr_base->clks.dppclk_khz = new_clocks->dppclk_khz; update_dppclk = true; @@ -172,22 +204,42 @@ void rn_update_clocks(struct clk_mgr *clk_mgr_base, if (should_set_clock(safe_to_lower, new_clocks->dispclk_khz, clk_mgr_base->clks.dispclk_khz)) { clk_mgr_base->clks.dispclk_khz = new_clocks->dispclk_khz; - rn_vbios_smu_set_dispclk(clk_mgr, clk_mgr_base->clks.dispclk_khz); + clk_mgr_base->clks.actual_dispclk_khz = rn_vbios_smu_set_dispclk(clk_mgr, clk_mgr_base->clks.dispclk_khz); update_dispclk = true; } if (dpp_clock_lowered) { - // increase per DPP DTO before lowering global dppclk - dcn20_update_clocks_update_dpp_dto(clk_mgr, context, safe_to_lower); - rn_vbios_smu_set_dppclk(clk_mgr, clk_mgr_base->clks.dppclk_khz); + // increase per DPP DTO before lowering global dppclk with requested dppclk + rn_update_clocks_update_dpp_dto( + clk_mgr, + context, + clk_mgr_base->clks.dppclk_khz, + safe_to_lower); + + clk_mgr_base->clks.actual_dppclk_khz = + rn_vbios_smu_set_dppclk(clk_mgr, clk_mgr_base->clks.dppclk_khz); + + //update dpp dto with actual dpp clk. + rn_update_clocks_update_dpp_dto( + clk_mgr, + context, + clk_mgr_base->clks.actual_dppclk_khz, + safe_to_lower); + } else { // increase global DPPCLK before lowering per DPP DTO if (update_dppclk || update_dispclk) - rn_vbios_smu_set_dppclk(clk_mgr, clk_mgr_base->clks.dppclk_khz); + clk_mgr_base->clks.actual_dppclk_khz = + rn_vbios_smu_set_dppclk(clk_mgr, clk_mgr_base->clks.dppclk_khz); + // always update dtos unless clock is lowered and not safe to lower if (new_clocks->dppclk_khz >= dc->current_state->bw_ctx.bw.dcn.clk.dppclk_khz) - dcn20_update_clocks_update_dpp_dto(clk_mgr, context, safe_to_lower); + rn_update_clocks_update_dpp_dto( + clk_mgr, + context, + clk_mgr_base->clks.actual_dppclk_khz, + safe_to_lower); } if (update_dispclk && @@ -198,7 +250,6 @@ void rn_update_clocks(struct clk_mgr *clk_mgr_base, } } - static int get_vco_frequency_from_reg(struct clk_mgr_internal *clk_mgr) { /* get FbMult value */ @@ -570,14 +621,14 @@ static struct clk_bw_params rn_bw_params = { }; -static struct wm_table ddr4_wm_table = { +static struct wm_table ddr4_wm_table_gs = { .entries = { { .wm_inst = WM_A, .wm_type = WM_TYPE_PSTATE_CHG, .pstate_latency_us = 11.72, - .sr_exit_time_us = 6.09, - .sr_enter_plus_exit_time_us = 7.14, + .sr_exit_time_us = 7.09, + .sr_enter_plus_exit_time_us = 8.14, .valid = true, }, { @@ -607,7 +658,7 @@ static struct wm_table ddr4_wm_table = { } }; -static struct wm_table lpddr4_wm_table = { +static struct wm_table lpddr4_wm_table_gs = { .entries = { { .wm_inst = WM_A, @@ -681,6 +732,80 @@ static struct wm_table lpddr4_wm_table_with_disabled_ppt = { } }; +static struct wm_table ddr4_wm_table_rn = { + .entries = { + { + .wm_inst = WM_A, + .wm_type = WM_TYPE_PSTATE_CHG, + .pstate_latency_us = 11.72, + .sr_exit_time_us = 9.09, + .sr_enter_plus_exit_time_us = 10.14, + .valid = true, + }, + { + .wm_inst = WM_B, + .wm_type = WM_TYPE_PSTATE_CHG, + .pstate_latency_us = 11.72, + .sr_exit_time_us = 10.12, + .sr_enter_plus_exit_time_us = 11.48, + .valid = true, + }, + { + .wm_inst = WM_C, + .wm_type = WM_TYPE_PSTATE_CHG, + .pstate_latency_us = 11.72, + .sr_exit_time_us = 10.12, + .sr_enter_plus_exit_time_us = 11.48, + .valid = true, + }, + { + .wm_inst = WM_D, + .wm_type = WM_TYPE_PSTATE_CHG, + .pstate_latency_us = 11.72, + .sr_exit_time_us = 10.12, + .sr_enter_plus_exit_time_us = 11.48, + .valid = true, + }, + } +}; + +static struct wm_table lpddr4_wm_table_rn = { + .entries = { + { + .wm_inst = WM_A, + .wm_type = WM_TYPE_PSTATE_CHG, + .pstate_latency_us = 11.65333, + .sr_exit_time_us = 7.32, + .sr_enter_plus_exit_time_us = 8.38, + .valid = true, + }, + { + .wm_inst = WM_B, + .wm_type = WM_TYPE_PSTATE_CHG, + .pstate_latency_us = 11.65333, + .sr_exit_time_us = 9.82, + .sr_enter_plus_exit_time_us = 11.196, + .valid = true, + }, + { + .wm_inst = WM_C, + .wm_type = WM_TYPE_PSTATE_CHG, + .pstate_latency_us = 11.65333, + .sr_exit_time_us = 9.89, + .sr_enter_plus_exit_time_us = 11.24, + .valid = true, + }, + { + .wm_inst = WM_D, + .wm_type = WM_TYPE_PSTATE_CHG, + .pstate_latency_us = 11.65333, + .sr_exit_time_us = 9.748, + .sr_enter_plus_exit_time_us = 11.102, + .valid = true, + }, + } +}; + static unsigned int find_dcfclk_for_voltage(struct dpm_clocks *clock_table, unsigned int voltage) { int i; @@ -762,6 +887,11 @@ void rn_clk_mgr_construct( struct dc_debug_options *debug = &ctx->dc->debug; struct dpm_clocks clock_table = { 0 }; enum pp_smu_status status = 0; + int is_green_sardine = 0; + +#if defined(CONFIG_DRM_AMD_DC_DCN) + is_green_sardine = ASICREV_IS_GREEN_SARDINE(ctx->asic_id.hw_internal_rev); +#endif clk_mgr->base.ctx = ctx; clk_mgr->base.funcs = &dcn21_funcs; @@ -802,10 +932,16 @@ void rn_clk_mgr_construct( if (clk_mgr->periodic_retraining_disabled) { rn_bw_params.wm_table = lpddr4_wm_table_with_disabled_ppt; } else { - rn_bw_params.wm_table = lpddr4_wm_table; + if (is_green_sardine) + rn_bw_params.wm_table = lpddr4_wm_table_gs; + else + rn_bw_params.wm_table = lpddr4_wm_table_rn; } } else { - rn_bw_params.wm_table = ddr4_wm_table; + if (is_green_sardine) + rn_bw_params.wm_table = ddr4_wm_table_gs; + else + rn_bw_params.wm_table = ddr4_wm_table_rn; } /* Saved clocks configured at boot for debug purposes */ rn_dump_clk_registers(&clk_mgr->base.boot_snapshot, &clk_mgr->base, &log_info); diff --git a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn21/rn_clk_mgr_vbios_smu.c b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn21/rn_clk_mgr_vbios_smu.c index 9a374522e963..11a7b583d561 100644 --- a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn21/rn_clk_mgr_vbios_smu.c +++ b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn21/rn_clk_mgr_vbios_smu.c @@ -136,6 +136,10 @@ int rn_vbios_smu_set_dispclk(struct clk_mgr_internal *clk_mgr, int requested_dis } } + // pmfw always set clock more than or equal requested clock + if (!IS_DIAG_DC(dc->ctx->dce_environment)) + ASSERT(actual_dispclk_set_mhz >= requested_dispclk_khz / 1000); + return actual_dispclk_set_mhz * 1000; } @@ -194,12 +198,16 @@ void rn_vbios_smu_set_phyclk(struct clk_mgr_internal *clk_mgr, int requested_phy int rn_vbios_smu_set_dppclk(struct clk_mgr_internal *clk_mgr, int requested_dpp_khz) { int actual_dppclk_set_mhz = -1; + struct dc *dc = clk_mgr->base.ctx->dc; actual_dppclk_set_mhz = rn_vbios_smu_send_msg_with_param( clk_mgr, VBIOSSMC_MSG_SetDppclkFreq, requested_dpp_khz / 1000); + if (!IS_DIAG_DC(dc->ctx->dce_environment)) + ASSERT(actual_dppclk_set_mhz >= requested_dpp_khz / 1000); + return actual_dppclk_set_mhz * 1000; } @@ -239,5 +247,6 @@ int rn_vbios_smu_is_periodic_retraining_disabled(struct clk_mgr_internal *clk_mg return rn_vbios_smu_send_msg_with_param( clk_mgr, VBIOSSMC_MSG_IsPeriodicRetrainingDisabled, - 0); + 1); // if PMFW doesn't support this message, assume retraining is disabled + // so we only use most optimal watermark if we know retraining is enabled. } diff --git a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn30/dcn30_clk_mgr.c b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn30/dcn30_clk_mgr.c index 82cb688ba5e0..5b466f440d67 100644 --- a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn30/dcn30_clk_mgr.c +++ b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn30/dcn30_clk_mgr.c @@ -499,7 +499,7 @@ static void dcn3_init_clocks_fpga(struct clk_mgr *clk_mgr) /* TODO: Implement the functions and remove the ifndef guard */ } -static struct clk_mgr_funcs dcn3_fpga_funcs = { +struct clk_mgr_funcs dcn3_fpga_funcs = { .get_dp_ref_clk_frequency = dce12_get_dp_ref_freq_khz, .update_clocks = dcn2_update_clocks_fpga, .init_clocks = dcn3_init_clocks_fpga, diff --git a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn301/vg_clk_mgr.c b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn301/vg_clk_mgr.c index 98cbb0ac095c..9a8e66bba9c0 100644 --- a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn301/vg_clk_mgr.c +++ b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn301/vg_clk_mgr.c @@ -32,9 +32,9 @@ // For dcn20_update_clocks_update_dpp_dto #include "dcn20/dcn20_clk_mgr.h" -#include "vg_clk_mgr.h" -#include "dcn301_smu.h" + +#include "vg_clk_mgr.h" #include "reg_helper.h" #include "core_types.h" #include "dm_helpers.h" @@ -631,7 +631,7 @@ static unsigned int find_dcfclk_for_voltage(const struct vg_dpm_clocks *clock_ta return 0; } -static void vg_clk_mgr_helper_populate_bw_params( +void vg_clk_mgr_helper_populate_bw_params( struct clk_mgr_internal *clk_mgr, struct integrated_info *bios_info, const struct vg_dpm_clocks *clock_table) @@ -709,7 +709,7 @@ static struct vg_dpm_clocks dummy_clocks = { static struct watermarks dummy_wms = { 0 }; -static void vg_get_dpm_table_from_smu(struct clk_mgr_internal *clk_mgr, +void vg_get_dpm_table_from_smu(struct clk_mgr_internal *clk_mgr, struct smu_dpm_clks *smu_dpm_clks) { struct vg_dpm_clocks *table = smu_dpm_clks->dpm_clks; diff --git a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn301/vg_clk_mgr.h b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn301/vg_clk_mgr.h index 80497df20ba7..b5115b3123a1 100644 --- a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn301/vg_clk_mgr.h +++ b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn301/vg_clk_mgr.h @@ -39,5 +39,15 @@ void vg_clk_mgr_construct(struct dc_context *ctx, void vg_clk_mgr_destroy(struct clk_mgr_internal *clk_mgr); +#include "dcn301_smu.h" void vg_notify_wm_ranges(struct clk_mgr *clk_mgr_base); + +void vg_get_dpm_table_from_smu(struct clk_mgr_internal *clk_mgr, + struct smu_dpm_clks *smu_dpm_clks); + +void vg_clk_mgr_helper_populate_bw_params( + struct clk_mgr_internal *clk_mgr, + struct integrated_info *bios_info, + const struct vg_dpm_clocks *clock_table); + #endif //__VG_CLK_MGR_H__ diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c index 5951f7d4022f..58eb0d69873a 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc.c @@ -149,6 +149,20 @@ static void destroy_links(struct dc *dc) } } +static uint32_t get_num_of_internal_disp(struct dc_link **links, uint32_t num_links) +{ + int i; + uint32_t count = 0; + + for (i = 0; i < num_links; i++) { + if (links[i]->connector_signal == SIGNAL_TYPE_EDP || + links[i]->is_internal_display) + count++; + } + + return count; +} + static bool create_links( struct dc *dc, uint32_t num_virtual_links) @@ -250,6 +264,8 @@ static bool create_links( virtual_link_encoder_construct(link->link_enc, &enc_init); } + dc->caps.num_of_internal_disp = get_num_of_internal_disp(dc->links, dc->link_count); + return true; failed_alloc: @@ -2782,6 +2798,19 @@ struct dc_stream_state *dc_get_stream_at_index(struct dc *dc, uint8_t i) return NULL; } +struct dc_stream_state *dc_stream_find_from_link(const struct dc_link *link) +{ + uint8_t i; + struct dc_context *ctx = link->ctx; + + for (i = 0; i < ctx->dc->current_state->stream_count; i++) { + if (ctx->dc->current_state->streams[i]->link == link) + return ctx->dc->current_state->streams[i]; + } + + return NULL; +} + enum dc_irq_source dc_interrupt_to_irq_source( struct dc *dc, uint32_t src_id, @@ -3058,9 +3087,9 @@ bool dc_set_psr_allow_active(struct dc *dc, bool enable) if (link->psr_settings.psr_feature_enabled) { if (enable && !link->psr_settings.psr_allow_active) - return dc_link_set_psr_allow_active(link, true, false); + return dc_link_set_psr_allow_active(link, true, false, false); else if (!enable && link->psr_settings.psr_allow_active) - return dc_link_set_psr_allow_active(link, false, true); + return dc_link_set_psr_allow_active(link, false, true, false); } } diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_link.c b/drivers/gpu/drm/amd/display/dc/core/dc_link.c index ea9c459c9130..a901baf2aaef 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_link.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_link.c @@ -1060,6 +1060,7 @@ static bool dc_link_detect_helper(struct dc_link *link, return false; } + break; default: break; } @@ -1368,6 +1369,7 @@ static bool dc_link_construct(struct dc_link *link, struct integrated_info info = {{{ 0 }}}; struct dc_bios *bios = init_params->dc->ctx->dc_bios; const struct dc_vbios_funcs *bp_funcs = bios->funcs; + struct bp_disp_connector_caps_info disp_connect_caps_info = { 0 }; DC_LOGGER_INIT(dc_ctx->logger); @@ -1388,6 +1390,12 @@ static bool dc_link_construct(struct dc_link *link, link->link_id = bios->funcs->get_connector_id(bios, init_params->connector_index); + + if (bios->funcs->get_disp_connector_caps_info) { + bios->funcs->get_disp_connector_caps_info(bios, link->link_id, &disp_connect_caps_info); + link->is_internal_display = disp_connect_caps_info.INTERNAL_DISPLAY; + } + if (link->link_id.type != OBJECT_TYPE_CONNECTOR) { dm_output_to_console("%s: Invalid Connector ObjectID from Adapter Service for connector index:%d! type %d expected %d\n", __func__, init_params->connector_index, @@ -1730,7 +1738,7 @@ static enum dc_status enable_link_dp_mst( /* sink signal type after MST branch is MST. Multiple MST sinks * share one link. Link DP PHY is enable or training only once. */ - if (link->cur_link_settings.lane_count != LANE_COUNT_UNKNOWN) + if (link->link_status.link_active) return DC_OK; /* clear payload table */ @@ -2565,17 +2573,23 @@ bool dc_link_set_backlight_level(const struct dc_link *link, return true; } -bool dc_link_set_psr_allow_active(struct dc_link *link, bool allow_active, bool wait) +bool dc_link_set_psr_allow_active(struct dc_link *link, bool allow_active, + bool wait, bool force_static) { struct dc *dc = link->ctx->dc; struct dmcu *dmcu = dc->res_pool->dmcu; struct dmub_psr *psr = dc->res_pool->psr; + if (psr == NULL && force_static) + return false; + link->psr_settings.psr_allow_active = allow_active; - if (psr != NULL && link->psr_settings.psr_feature_enabled) + if (psr != NULL && link->psr_settings.psr_feature_enabled) { + if (force_static && psr->funcs->psr_force_static) + psr->funcs->psr_force_static(psr); psr->funcs->psr_enable(psr, allow_active, wait); - else if ((dmcu != NULL && dmcu->funcs->is_dmcu_initialized(dmcu)) && link->psr_settings.psr_feature_enabled) + } else if ((dmcu != NULL && dmcu->funcs->is_dmcu_initialized(dmcu)) && link->psr_settings.psr_feature_enabled) dmcu->funcs->set_psr_enable(dmcu, allow_active, wait); else return false; @@ -2583,16 +2597,16 @@ bool dc_link_set_psr_allow_active(struct dc_link *link, bool allow_active, bool return true; } -bool dc_link_get_psr_state(const struct dc_link *link, uint32_t *psr_state) +bool dc_link_get_psr_state(const struct dc_link *link, enum dc_psr_state *state) { struct dc *dc = link->ctx->dc; struct dmcu *dmcu = dc->res_pool->dmcu; struct dmub_psr *psr = dc->res_pool->psr; if (psr != NULL && link->psr_settings.psr_feature_enabled) - psr->funcs->psr_get_state(psr, psr_state); + psr->funcs->psr_get_state(psr, state); else if (dmcu != NULL && link->psr_settings.psr_feature_enabled) - dmcu->funcs->get_psr_state(dmcu, psr_state); + dmcu->funcs->get_psr_state(dmcu, state); return true; } @@ -2751,6 +2765,7 @@ bool dc_link_setup_psr(struct dc_link *link, * (Always set for DAL2, did not check ASIC) */ psr_context->allow_smu_optimizations = psr_config->allow_smu_optimizations; + psr_context->allow_multi_disp_optimizations = psr_config->allow_multi_disp_optimizations; /* Complete PSR entry before aborting to prevent intermittent * freezes on certain eDPs @@ -2777,6 +2792,18 @@ bool dc_link_setup_psr(struct dc_link *link, } +void dc_link_get_psr_residency(const struct dc_link *link, uint32_t *residency) +{ + struct dc *dc = link->ctx->dc; + struct dmub_psr *psr = dc->res_pool->psr; + + // PSR residency measurements only supported on DMCUB + if (psr != NULL && link->psr_settings.psr_feature_enabled) + psr->funcs->psr_get_residency(psr, residency); + else + *residency = 0; +} + const struct dc_link_status *dc_link_get_status(const struct dc_link *link) { return &link->link_status; @@ -2800,15 +2827,12 @@ static struct fixed31_32 get_pbn_per_slot(struct dc_stream_state *stream) return dc_fixpt_div_int(mbytes_per_sec, 54); } -static struct fixed31_32 get_pbn_from_timing(struct pipe_ctx *pipe_ctx) +static struct fixed31_32 get_pbn_from_bw_in_kbps(uint64_t kbps) { - uint64_t kbps; struct fixed31_32 peak_kbps; uint32_t numerator; uint32_t denominator; - kbps = dc_bandwidth_in_kbps_from_timing(&pipe_ctx->stream->timing); - /* * margin 5300ppm + 300ppm ~ 0.6% as per spec, factor is 1.006 * The unit of 54/64Mbytes/sec is an arbitrary unit chosen based on @@ -2828,6 +2852,14 @@ static struct fixed31_32 get_pbn_from_timing(struct pipe_ctx *pipe_ctx) return peak_kbps; } +static struct fixed31_32 get_pbn_from_timing(struct pipe_ctx *pipe_ctx) +{ + uint64_t kbps; + + kbps = dc_bandwidth_in_kbps_from_timing(&pipe_ctx->stream->timing); + return get_pbn_from_bw_in_kbps(kbps); +} + static void update_mst_stream_alloc_table( struct dc_link *link, struct stream_encoder *stream_enc, @@ -2855,6 +2887,7 @@ static void update_mst_stream_alloc_table( proposed_table->stream_allocations[i].vcp_id) { work_table[i] = *dc_alloc; + work_table[i].slot_count = proposed_table->stream_allocations[i].slot_count; break; /* exit j loop */ } } @@ -3234,7 +3267,8 @@ void core_link_enable_stream( } } - dc->hwss.enable_audio_stream(pipe_ctx); +#if defined(CONFIG_DRM_AMD_DC_DCN3_0) +#endif /* turn off otg test pattern if enable */ if (pipe_ctx->stream_res.tg->funcs->set_test_pattern) @@ -3274,6 +3308,9 @@ void core_link_enable_stream( #if defined(CONFIG_DRM_AMD_DC_HDCP) update_psp_stream_config(pipe_ctx, false); #endif + + dc->hwss.enable_audio_stream(pipe_ctx); + } else { // if (IS_FPGA_MAXIMUS_DC(dc->ctx->dce_environment)) if (dc_is_dp_signal(pipe_ctx->stream->signal) || dc_is_virtual_signal(pipe_ctx->stream->signal)) @@ -3301,6 +3338,8 @@ void core_link_disable_stream(struct pipe_ctx *pipe_ctx) core_link_set_avmute(pipe_ctx, true); } + dc->hwss.disable_audio_stream(pipe_ctx); + #if defined(CONFIG_DRM_AMD_DC_HDCP) update_psp_stream_config(pipe_ctx, true); #endif @@ -3408,10 +3447,13 @@ uint32_t dc_bandwidth_in_kbps_from_timing( { uint32_t bits_per_channel = 0; uint32_t kbps; + struct fixed31_32 link_bw_kbps; if (timing->flags.DSC) { - kbps = (timing->pix_clk_100hz * timing->dsc_cfg.bits_per_pixel); - kbps = kbps / 160 + ((kbps % 160) ? 1 : 0); + link_bw_kbps = dc_fixpt_from_int(timing->pix_clk_100hz); + link_bw_kbps = dc_fixpt_div_int(link_bw_kbps, 160); + link_bw_kbps = dc_fixpt_mul_int(link_bw_kbps, timing->dsc_cfg.bits_per_pixel); + kbps = dc_fixpt_ceil(link_bw_kbps); return kbps; } @@ -3435,11 +3477,11 @@ uint32_t dc_bandwidth_in_kbps_from_timing( bits_per_channel = 16; break; default: + ASSERT(bits_per_channel != 0); + bits_per_channel = 8; break; } - ASSERT(bits_per_channel != 0); - kbps = timing->pix_clk_100hz / 10; kbps *= bits_per_channel; diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_link_ddc.c b/drivers/gpu/drm/amd/display/dc/core/dc_link_ddc.c index 54beda4d4e85..c5936e064360 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_link_ddc.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_link_ddc.c @@ -37,6 +37,10 @@ #include "dc_link_ddc.h" #include "dce/dce_aux.h" +/*DP to Dual link DVI converter*/ +static const uint8_t DP_DVI_CONVERTER_ID_4[] = "m2DVIa"; +static const uint8_t DP_DVI_CONVERTER_ID_5[] = "3393N2"; + #define AUX_POWER_UP_WA_DELAY 500 #define I2C_OVER_AUX_DEFER_WA_DELAY 70 #define I2C_OVER_AUX_DEFER_WA_DELAY_1MS 1 diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c b/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c index 8a7c4de49a4b..6b11d4af54af 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c @@ -15,6 +15,11 @@ #include "dc_dmub_srv.h" #include "dce/dmub_hw_lock_mgr.h" +/*Travis*/ +static const uint8_t DP_VGA_LVDS_CONVERTER_ID_2[] = "sivarT"; +/*Nutmeg*/ +static const uint8_t DP_VGA_LVDS_CONVERTER_ID_3[] = "dnomlA"; + #define DC_LOGGER \ link->ctx->logger #define DC_TRACE_LEVEL_MESSAGE(...) /* do nothing */ @@ -1405,15 +1410,24 @@ static void print_status_message( case LINK_RATE_LOW: link_rate = "RBR"; break; + case LINK_RATE_RATE_2: + link_rate = "R2"; + break; + case LINK_RATE_RATE_3: + link_rate = "R3"; + break; case LINK_RATE_HIGH: link_rate = "HBR"; break; - case LINK_RATE_HIGH2: - link_rate = "HBR2"; - break; case LINK_RATE_RBR2: link_rate = "RBR2"; break; + case LINK_RATE_RATE_6: + link_rate = "R6"; + break; + case LINK_RATE_HIGH2: + link_rate = "HBR2"; + break; case LINK_RATE_HIGH3: link_rate = "HBR3"; break; @@ -1860,7 +1874,7 @@ static struct dc_link_settings get_max_link_cap(struct dc_link *link) return max_link_cap; } -static enum dc_status read_hpd_rx_irq_data( +enum dc_status read_hpd_rx_irq_data( struct dc_link *link, union hpd_irq_data *irq_data) { @@ -2565,7 +2579,8 @@ static bool handle_hpd_irq_psr_sink(struct dc_link *link) psr_sink_psr_status.raw = dpcdbuf[2]; if (psr_error_status.bits.LINK_CRC_ERROR || - psr_error_status.bits.RFB_STORAGE_ERROR) { + psr_error_status.bits.RFB_STORAGE_ERROR || + psr_error_status.bits.VSC_SDP_ERROR) { /* Acknowledge and clear error bits */ dm_helpers_dp_write_dpcd( link->ctx, @@ -2575,8 +2590,8 @@ static bool handle_hpd_irq_psr_sink(struct dc_link *link) sizeof(psr_error_status.raw)); /* PSR error, disable and re-enable PSR */ - dc_link_set_psr_allow_active(link, false, true); - dc_link_set_psr_allow_active(link, true, true); + dc_link_set_psr_allow_active(link, false, true, false); + dc_link_set_psr_allow_active(link, true, true, false); return true; } else if (psr_sink_psr_status.bits.SINK_SELF_REFRESH_STATUS == @@ -3740,6 +3755,7 @@ void detect_edp_sink_caps(struct dc_link *link) uint32_t entry; uint32_t link_rate_in_khz; enum dc_link_rate link_rate = LINK_RATE_UNKNOWN; + uint8_t backlight_adj_cap; retrieve_link_cap(link); link->dpcd_caps.edp_supported_link_rates_count = 0; @@ -3770,6 +3786,12 @@ void detect_edp_sink_caps(struct dc_link *link) } link->verified_link_cap = link->reported_link_cap; + core_link_read_dpcd(link, DP_EDP_BACKLIGHT_ADJUSTMENT_CAP, + &backlight_adj_cap, sizeof(backlight_adj_cap)); + + link->dpcd_caps.dynamic_backlight_capable_edp = + (backlight_adj_cap & DP_EDP_DYNAMIC_BACKLIGHT_CAP) ? true:false; + dc_link_set_default_brightness_aux(link); } diff --git a/drivers/gpu/drm/amd/display/dc/dc.h b/drivers/gpu/drm/amd/display/dc/dc.h index 65aabf25cdec..b8f1e2d33423 100644 --- a/drivers/gpu/drm/amd/display/dc/dc.h +++ b/drivers/gpu/drm/amd/display/dc/dc.h @@ -42,7 +42,7 @@ #include "inc/hw/dmcu.h" #include "dml/display_mode_lib.h" -#define DC_VER "3.2.110" +#define DC_VER "3.2.115" #define MAX_SURFACES 3 #define MAX_PLANES 6 @@ -125,6 +125,7 @@ struct dpp_color_caps { uint16_t hw_3d_lut : 1; uint16_t ogam_ram : 1; // blnd gam uint16_t ocsc : 1; + uint16_t dgam_rom_for_yuv : 1; struct rom_curve_caps dgam_rom_caps; struct rom_curve_caps ogam_rom_caps; }; @@ -168,6 +169,7 @@ struct dc_caps { bool psp_setup_panel_mode; bool extended_aux_timeout_support; bool dmcub_support; + uint32_t num_of_internal_disp; enum dp_protocol_version max_dp_protocol_version; struct dc_plane_cap planes[MAX_PLANES]; struct dc_color_caps color; @@ -341,7 +343,9 @@ enum dcn_pwr_state { */ struct dc_clocks { int dispclk_khz; + int actual_dispclk_khz; int dppclk_khz; + int actual_dppclk_khz; int disp_dpp_voltage_level_khz; int dcfclk_khz; int socclk_khz; @@ -416,6 +420,10 @@ struct dc_bw_validation_profile { union mem_low_power_enable_options { struct { + bool i2c: 1; + bool dmcu: 1; + bool dscl: 1; + bool cm: 1; bool mpc: 1; bool optc: 1; } bits; @@ -479,7 +487,7 @@ struct dc_debug_options { bool scl_reset_length10; bool hdmi20_disable; bool skip_detection_link_training; - bool edid_read_retry_times; + uint32_t edid_read_retry_times; bool remove_disconnect_edp; unsigned int force_odm_combine; //bit vector based on otg inst #if defined(CONFIG_DRM_AMD_DC_DCN) @@ -1088,6 +1096,7 @@ struct dpcd_caps { bool panel_mode_edp; bool dpcd_display_control_capable; bool ext_receiver_cap_field_present; + bool dynamic_backlight_capable_edp; union dpcd_fec_capability fec_cap; struct dpcd_dsc_capabilities dsc_caps; struct dc_lttpr_caps lttpr_caps; diff --git a/drivers/gpu/drm/amd/display/dc/dc_bios_types.h b/drivers/gpu/drm/amd/display/dc/dc_bios_types.h index e146e3cba8eb..509d23fdd3c9 100644 --- a/drivers/gpu/drm/amd/display/dc/dc_bios_types.h +++ b/drivers/gpu/drm/amd/display/dc/dc_bios_types.h @@ -144,6 +144,11 @@ struct dc_vbios_funcs { enum bp_result (*get_soc_bb_info)( struct dc_bios *dcb, struct bp_soc_bb_info *soc_bb_info); + + enum bp_result (*get_disp_connector_caps_info)( + struct dc_bios *dcb, + struct graphics_object_id object_id, + struct bp_disp_connector_caps_info *info); }; struct bios_registers { diff --git a/drivers/gpu/drm/amd/display/dc/dc_link.h b/drivers/gpu/drm/amd/display/dc/dc_link.h index 266b93a705d5..6d9a60c9dcc0 100644 --- a/drivers/gpu/drm/amd/display/dc/dc_link.h +++ b/drivers/gpu/drm/amd/display/dc/dc_link.h @@ -101,6 +101,7 @@ struct dc_link { bool aux_access_disabled; bool sync_lt_in_progress; bool lttpr_non_transparent_mode; + bool is_internal_display; /* caps is the same as reported_link_cap. link_traing use * reported_link_cap. Will clean up. TODO @@ -219,14 +220,17 @@ int dc_link_get_backlight_level(const struct dc_link *dc_link); int dc_link_get_target_backlight_pwm(const struct dc_link *link); -bool dc_link_set_psr_allow_active(struct dc_link *dc_link, bool enable, bool wait); +bool dc_link_set_psr_allow_active(struct dc_link *dc_link, bool enable, + bool wait, bool force_static); -bool dc_link_get_psr_state(const struct dc_link *dc_link, uint32_t *psr_state); +bool dc_link_get_psr_state(const struct dc_link *dc_link, enum dc_psr_state *state); bool dc_link_setup_psr(struct dc_link *dc_link, const struct dc_stream_state *stream, struct psr_config *psr_config, struct psr_context *psr_context); +void dc_link_get_psr_residency(const struct dc_link *link, uint32_t *residency); + /* Request DC to detect if there is a Panel connected. * boot - If this call is during initial boot. * Return false for any type of detection failure or MST detection @@ -255,6 +259,10 @@ enum dc_status dc_link_reallocate_mst_payload(struct dc_link *link); bool dc_link_handle_hpd_rx_irq(struct dc_link *dc_link, union hpd_irq_data *hpd_irq_dpcd_data, bool *out_link_loss); +enum dc_status read_hpd_rx_irq_data( + struct dc_link *link, + union hpd_irq_data *irq_data); + struct dc_sink_init_data; struct dc_sink *dc_link_add_remote_sink( diff --git a/drivers/gpu/drm/amd/display/dc/dc_stream.h b/drivers/gpu/drm/amd/display/dc/dc_stream.h index bf090afc2f70..b7910976b81a 100644 --- a/drivers/gpu/drm/amd/display/dc/dc_stream.h +++ b/drivers/gpu/drm/amd/display/dc/dc_stream.h @@ -292,6 +292,7 @@ void dc_stream_log(const struct dc *dc, const struct dc_stream_state *stream); uint8_t dc_get_current_stream_count(struct dc *dc); struct dc_stream_state *dc_get_stream_at_index(struct dc *dc, uint8_t i); +struct dc_stream_state *dc_stream_find_from_link(const struct dc_link *link); /* * Return the current frame counter. diff --git a/drivers/gpu/drm/amd/display/dc/dc_types.h b/drivers/gpu/drm/amd/display/dc/dc_types.h index 53c29d811493..80757a0ea7c6 100644 --- a/drivers/gpu/drm/amd/display/dc/dc_types.h +++ b/drivers/gpu/drm/amd/display/dc/dc_types.h @@ -671,6 +671,25 @@ struct dc_plane_flip_time { unsigned int prev_update_time_in_us; }; +enum dc_psr_state { + PSR_STATE0 = 0x0, + PSR_STATE1, + PSR_STATE1a, + PSR_STATE2, + PSR_STATE2a, + PSR_STATE3, + PSR_STATE3Init, + PSR_STATE4, + PSR_STATE4a, + PSR_STATE4b, + PSR_STATE4c, + PSR_STATE4d, + PSR_STATE5, + PSR_STATE5a, + PSR_STATE5b, + PSR_STATE5c +}; + struct psr_config { unsigned char psr_version; unsigned int psr_rfb_setup_time; @@ -678,6 +697,7 @@ struct psr_config { bool psr_frame_capture_indication_req; unsigned int psr_sdp_transmit_line_num_deadline; bool allow_smu_optimizations; + bool allow_multi_disp_optimizations; }; union dmcu_psr_level { @@ -780,6 +800,7 @@ struct psr_context { */ unsigned int frame_delay; bool allow_smu_optimizations; + bool allow_multi_disp_optimizations; }; struct colorspace_transform { diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_dmcu.c b/drivers/gpu/drm/amd/display/dc/dce/dce_dmcu.c index f0cebe721bcc..f3ed8b619caf 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_dmcu.c +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_dmcu.c @@ -99,7 +99,7 @@ bool dce_dmcu_load_iram(struct dmcu *dmcu, return true; } -static void dce_get_dmcu_psr_state(struct dmcu *dmcu, uint32_t *psr_state) +static void dce_get_dmcu_psr_state(struct dmcu *dmcu, enum dc_psr_state *state) { struct dce_dmcu *dmcu_dce = TO_DCE_DMCU(dmcu); @@ -114,7 +114,7 @@ static void dce_get_dmcu_psr_state(struct dmcu *dmcu, uint32_t *psr_state) REG_WRITE(DMCU_IRAM_RD_CTRL, psr_state_offset); /* Read data from IRAM_RD_DATA in DMCU_IRAM_RD_DATA*/ - *psr_state = REG_READ(DMCU_IRAM_RD_DATA); + *state = (enum dc_psr_state)REG_READ(DMCU_IRAM_RD_DATA); /* Disable write access to IRAM after finished using IRAM * in order to allow dynamic sleep state @@ -129,7 +129,7 @@ static void dce_dmcu_set_psr_enable(struct dmcu *dmcu, bool enable, bool wait) unsigned int dmcu_wait_reg_ready_interval = 100; unsigned int retryCount; - uint32_t psr_state = 0; + enum dc_psr_state state = PSR_STATE0; /* waitDMCUReadyForCmd */ REG_WAIT(MASTER_COMM_CNTL_REG, MASTER_COMM_INTERRUPT, 0, @@ -148,12 +148,12 @@ static void dce_dmcu_set_psr_enable(struct dmcu *dmcu, bool enable, bool wait) REG_UPDATE(MASTER_COMM_CNTL_REG, MASTER_COMM_INTERRUPT, 1); if (wait == true) { for (retryCount = 0; retryCount <= 100; retryCount++) { - dce_get_dmcu_psr_state(dmcu, &psr_state); + dce_get_dmcu_psr_state(dmcu, &state); if (enable) { - if (psr_state != 0) + if (state != PSR_STATE0) break; } else { - if (psr_state == 0) + if (state == PSR_STATE0) break; } udelay(10); @@ -513,7 +513,7 @@ static bool dcn10_dmcu_load_iram(struct dmcu *dmcu, return true; } -static void dcn10_get_dmcu_psr_state(struct dmcu *dmcu, uint32_t *psr_state) +static void dcn10_get_dmcu_psr_state(struct dmcu *dmcu, enum dc_psr_state *state) { struct dce_dmcu *dmcu_dce = TO_DCE_DMCU(dmcu); @@ -532,7 +532,7 @@ static void dcn10_get_dmcu_psr_state(struct dmcu *dmcu, uint32_t *psr_state) REG_WRITE(DMCU_IRAM_RD_CTRL, psr_state_offset); /* Read data from IRAM_RD_DATA in DMCU_IRAM_RD_DATA*/ - *psr_state = REG_READ(DMCU_IRAM_RD_DATA); + *state = (enum dc_psr_state)REG_READ(DMCU_IRAM_RD_DATA); /* Disable write access to IRAM after finished using IRAM * in order to allow dynamic sleep state @@ -547,7 +547,7 @@ static void dcn10_dmcu_set_psr_enable(struct dmcu *dmcu, bool enable, bool wait) unsigned int dmcu_wait_reg_ready_interval = 100; unsigned int retryCount; - uint32_t psr_state = 0; + enum dc_psr_state state = PSR_STATE0; /* If microcontroller is not running, do nothing */ if (dmcu->dmcu_state != DMCU_RUNNING) @@ -575,12 +575,12 @@ static void dcn10_dmcu_set_psr_enable(struct dmcu *dmcu, bool enable, bool wait) */ if (wait == true) { for (retryCount = 0; retryCount <= 1000; retryCount++) { - dcn10_get_dmcu_psr_state(dmcu, &psr_state); + dcn10_get_dmcu_psr_state(dmcu, &state); if (enable) { - if (psr_state != 0) + if (state != PSR_STATE0) break; } else { - if (psr_state == 0) + if (state == PSR_STATE0) break; } udelay(500); diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_hwseq.h b/drivers/gpu/drm/amd/display/dc/dce/dce_hwseq.h index ad0ae1f7b513..fe31abfa6c85 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_hwseq.h +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_hwseq.h @@ -597,6 +597,7 @@ struct dce_hwseq_registers { uint32_t AZALIA_CONTROLLER_CLOCK_GATING; uint32_t HPO_TOP_CLOCK_CONTROL; uint32_t ODM_MEM_PWR_CTRL3; + uint32_t DMU_MEM_PWR_CNTL; }; /* set field name */ #define HWS_SF(blk_name, reg_name, field_name, post_fix)\ @@ -836,7 +837,8 @@ struct dce_hwseq_registers { HWSEQ_DCN2_MASK_SH_LIST(mask_sh), \ HWS_SF(, AZALIA_AUDIO_DTO, AZALIA_AUDIO_DTO_MODULE, mask_sh), \ 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) + HWS_SF(, ODM_MEM_PWR_CTRL3, ODM_MEM_VBLANK_PWR_MODE, mask_sh), \ + HWS_SF(, DMU_MEM_PWR_CNTL, DMCU_ERAM_MEM_PWR_FORCE, mask_sh) #define HWSEQ_DCN301_MASK_SH_LIST(mask_sh)\ HWSEQ_DCN_MASK_SH_LIST(mask_sh), \ @@ -1046,7 +1048,8 @@ struct dce_hwseq_registers { type D4VGA_MODE_ENABLE; \ type AZALIA_AUDIO_DTO_MODULE; \ type ODM_MEM_UNASSIGNED_PWR_MODE; \ - type ODM_MEM_VBLANK_PWR_MODE; + type ODM_MEM_VBLANK_PWR_MODE; \ + type DMCU_ERAM_MEM_PWR_FORCE; #define HWSEQ_DCN3_REG_FIELD_LIST(type) \ type HPO_HDMISTREAMCLK_GATE_DIS; diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_i2c_hw.c b/drivers/gpu/drm/amd/display/dc/dce/dce_i2c_hw.c index 3e34afe8c504..7fbd92fbc63a 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_i2c_hw.c +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_i2c_hw.c @@ -293,6 +293,14 @@ static bool setup_engine( { uint32_t i2c_setup_limit = I2C_SETUP_TIME_LIMIT_DCE; uint32_t reset_length = 0; + + if (dce_i2c_hw->ctx->dc->debug.enable_mem_low_power.bits.i2c) { + if (dce_i2c_hw->regs->DIO_MEM_PWR_CTRL) { + REG_UPDATE(DIO_MEM_PWR_CTRL, I2C_LIGHT_SLEEP_FORCE, 0); + REG_WAIT(DIO_MEM_PWR_STATUS, I2C_MEM_PWR_STATE, 0, 0, 5); + } + } + /* we have checked I2c not used by DMCU, set SW use I2C REQ to 1 to indicate SW using it*/ REG_UPDATE(DC_I2C_ARBITRATION, DC_I2C_SW_USE_I2C_REG_REQ, 1); @@ -369,6 +377,10 @@ static void release_engine( REG_UPDATE_2(DC_I2C_ARBITRATION, DC_I2C_SW_DONE_USING_I2C_REG, 1, DC_I2C_SW_USE_I2C_REG_REQ, 0); + if (dce_i2c_hw->ctx->dc->debug.enable_mem_low_power.bits.i2c) { + if (dce_i2c_hw->regs->DIO_MEM_PWR_CTRL) + REG_UPDATE(DIO_MEM_PWR_CTRL, I2C_LIGHT_SLEEP_FORCE, 1); + } } struct dce_i2c_hw *acquire_i2c_hw_engine( diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_i2c_hw.h b/drivers/gpu/drm/amd/display/dc/dce/dce_i2c_hw.h index fb055e6883c0..2309f2bb162c 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_i2c_hw.h +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_i2c_hw.h @@ -95,6 +95,11 @@ enum { SR(DC_I2C_DATA),\ SR(MICROSECOND_TIME_BASE_DIV) +#define I2C_HW_ENGINE_COMMON_REG_LIST_DCN30(id)\ + I2C_HW_ENGINE_COMMON_REG_LIST(id),\ + SR(DIO_MEM_PWR_CTRL),\ + SR(DIO_MEM_PWR_STATUS) + #define I2C_SF(reg_name, field_name, post_fix)\ .field_name = reg_name ## __ ## field_name ## post_fix @@ -179,6 +184,8 @@ struct dce_i2c_shift { uint8_t XTAL_REF_DIV; uint8_t DC_I2C_DDC1_SEND_RESET_LENGTH; uint8_t DC_I2C_REG_RW_CNTL_STATUS; + uint8_t I2C_LIGHT_SLEEP_FORCE; + uint8_t I2C_MEM_PWR_STATE; }; struct dce_i2c_mask { @@ -220,12 +227,19 @@ struct dce_i2c_mask { uint32_t XTAL_REF_DIV; uint32_t DC_I2C_DDC1_SEND_RESET_LENGTH; uint32_t DC_I2C_REG_RW_CNTL_STATUS; + uint32_t I2C_LIGHT_SLEEP_FORCE; + uint32_t I2C_MEM_PWR_STATE; }; #define I2C_COMMON_MASK_SH_LIST_DCN2(mask_sh)\ I2C_COMMON_MASK_SH_LIST_DCE110(mask_sh),\ I2C_SF(DC_I2C_DDC1_SETUP, DC_I2C_DDC1_SEND_RESET_LENGTH, mask_sh) +#define I2C_COMMON_MASK_SH_LIST_DCN30(mask_sh)\ + I2C_COMMON_MASK_SH_LIST_DCN2(mask_sh),\ + I2C_SF(DIO_MEM_PWR_CTRL, I2C_LIGHT_SLEEP_FORCE, mask_sh),\ + I2C_SF(DIO_MEM_PWR_STATUS, I2C_MEM_PWR_STATE, mask_sh) + struct dce_i2c_registers { uint32_t SETUP; uint32_t SPEED; @@ -239,6 +253,8 @@ struct dce_i2c_registers { uint32_t DC_I2C_TRANSACTION3; uint32_t DC_I2C_DATA; uint32_t MICROSECOND_TIME_BASE_DIV; + uint32_t DIO_MEM_PWR_CTRL; + uint32_t DIO_MEM_PWR_STATUS; }; enum dce_i2c_transaction_address_space { diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_panel_cntl.c b/drivers/gpu/drm/amd/display/dc/dce/dce_panel_cntl.c index 74f7619d4154..761fdfc1f5bd 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_panel_cntl.c +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_panel_cntl.c @@ -108,25 +108,17 @@ static uint32_t dce_panel_cntl_hw_init(struct panel_cntl *panel_cntl) */ REG_GET(BL_PWM_CNTL, BL_ACTIVE_INT_FRAC_CNT, &value); - if (value == 0 || value == 1) { - if (panel_cntl->stored_backlight_registers.BL_PWM_CNTL != 0) { - REG_WRITE(BL_PWM_CNTL, - panel_cntl->stored_backlight_registers.BL_PWM_CNTL); - REG_WRITE(BL_PWM_CNTL2, - panel_cntl->stored_backlight_registers.BL_PWM_CNTL2); - REG_WRITE(BL_PWM_PERIOD_CNTL, - panel_cntl->stored_backlight_registers.BL_PWM_PERIOD_CNTL); - REG_UPDATE(PWRSEQ_REF_DIV, - BL_PWM_REF_DIV, - panel_cntl->stored_backlight_registers.LVTMA_PWRSEQ_REF_DIV_BL_PWM_REF_DIV); - } else { - /* TODO: Note: This should not really happen since VBIOS - * should have initialized PWM registers on boot. - */ - REG_WRITE(BL_PWM_CNTL, 0xC000FA00); - REG_WRITE(BL_PWM_PERIOD_CNTL, 0x000C0FA0); - } - } else { + if (panel_cntl->stored_backlight_registers.BL_PWM_CNTL != 0) { + REG_WRITE(BL_PWM_CNTL, + panel_cntl->stored_backlight_registers.BL_PWM_CNTL); + REG_WRITE(BL_PWM_CNTL2, + panel_cntl->stored_backlight_registers.BL_PWM_CNTL2); + REG_WRITE(BL_PWM_PERIOD_CNTL, + panel_cntl->stored_backlight_registers.BL_PWM_PERIOD_CNTL); + REG_UPDATE(PWRSEQ_REF_DIV, + BL_PWM_REF_DIV, + panel_cntl->stored_backlight_registers.LVTMA_PWRSEQ_REF_DIV_BL_PWM_REF_DIV); + } else if ((value != 0) && (value != 1)) { panel_cntl->stored_backlight_registers.BL_PWM_CNTL = REG_READ(BL_PWM_CNTL); panel_cntl->stored_backlight_registers.BL_PWM_CNTL2 = @@ -136,6 +128,12 @@ static uint32_t dce_panel_cntl_hw_init(struct panel_cntl *panel_cntl) REG_GET(PWRSEQ_REF_DIV, BL_PWM_REF_DIV, &panel_cntl->stored_backlight_registers.LVTMA_PWRSEQ_REF_DIV_BL_PWM_REF_DIV); + } else { + /* TODO: Note: This should not really happen since VBIOS + * should have initialized PWM registers on boot. + */ + REG_WRITE(BL_PWM_CNTL, 0x8000FA00); + REG_WRITE(BL_PWM_PERIOD_CNTL, 0x000C0FA0); } // Have driver take backlight control diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_stream_encoder.c b/drivers/gpu/drm/amd/display/dc/dce/dce_stream_encoder.c index 5054bb567b74..ada57f745fd7 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_stream_encoder.c +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_stream_encoder.c @@ -1062,88 +1062,6 @@ static void dce110_reset_hdmi_stream_attribute( #include "include/audio_types.h" -/** -* speakersToChannels -* -* @brief -* translate speakers to channels -* -* FL - Front Left -* FR - Front Right -* RL - Rear Left -* RR - Rear Right -* RC - Rear Center -* FC - Front Center -* FLC - Front Left Center -* FRC - Front Right Center -* RLC - Rear Left Center -* RRC - Rear Right Center -* LFE - Low Freq Effect -* -* FC -* FLC FRC -* FL FR -* -* LFE -* () -* -* -* RL RR -* RLC RRC -* RC -* -* ch 8 7 6 5 4 3 2 1 -* 0b00000011 - - - - - - FR FL -* 0b00000111 - - - - - LFE FR FL -* 0b00001011 - - - - FC - FR FL -* 0b00001111 - - - - FC LFE FR FL -* 0b00010011 - - - RC - - FR FL -* 0b00010111 - - - RC - LFE FR FL -* 0b00011011 - - - RC FC - FR FL -* 0b00011111 - - - RC FC LFE FR FL -* 0b00110011 - - RR RL - - FR FL -* 0b00110111 - - RR RL - LFE FR FL -* 0b00111011 - - RR RL FC - FR FL -* 0b00111111 - - RR RL FC LFE FR FL -* 0b01110011 - RC RR RL - - FR FL -* 0b01110111 - RC RR RL - LFE FR FL -* 0b01111011 - RC RR RL FC - FR FL -* 0b01111111 - RC RR RL FC LFE FR FL -* 0b11110011 RRC RLC RR RL - - FR FL -* 0b11110111 RRC RLC RR RL - LFE FR FL -* 0b11111011 RRC RLC RR RL FC - FR FL -* 0b11111111 RRC RLC RR RL FC LFE FR FL -* 0b11000011 FRC FLC - - - - FR FL -* 0b11000111 FRC FLC - - - LFE FR FL -* 0b11001011 FRC FLC - - FC - FR FL -* 0b11001111 FRC FLC - - FC LFE FR FL -* 0b11010011 FRC FLC - RC - - FR FL -* 0b11010111 FRC FLC - RC - LFE FR FL -* 0b11011011 FRC FLC - RC FC - FR FL -* 0b11011111 FRC FLC - RC FC LFE FR FL -* 0b11110011 FRC FLC RR RL - - FR FL -* 0b11110111 FRC FLC RR RL - LFE FR FL -* 0b11111011 FRC FLC RR RL FC - FR FL -* 0b11111111 FRC FLC RR RL FC LFE FR FL -* -* @param -* speakers - speaker information as it comes from CEA audio block -*/ -/* translate speakers to channels */ - -union audio_cea_channels { - uint8_t all; - struct audio_cea_channels_bits { - uint32_t FL:1; - uint32_t FR:1; - uint32_t LFE:1; - uint32_t FC:1; - uint32_t RL_RC:1; - uint32_t RR:1; - uint32_t RC_RLC_FLC:1; - uint32_t RRC_FRC:1; - } channels; -}; /* 25.2MHz/1.001*/ /* 25.2MHz/1.001*/ diff --git a/drivers/gpu/drm/amd/display/dc/dce/dmub_psr.c b/drivers/gpu/drm/amd/display/dc/dce/dmub_psr.c index 67af67ef2865..17e84f34ceba 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dmub_psr.c +++ b/drivers/gpu/drm/amd/display/dc/dce/dmub_psr.c @@ -34,55 +34,60 @@ /** * Convert dmcub psr state to dmcu psr state. */ -static void convert_psr_state(uint32_t *psr_state) +static enum dc_psr_state convert_psr_state(uint32_t raw_state) { - if (*psr_state == 0) - *psr_state = 0; - else if (*psr_state == 0x10) - *psr_state = 1; - else if (*psr_state == 0x11) - *psr_state = 2; - else if (*psr_state == 0x20) - *psr_state = 3; - else if (*psr_state == 0x21) - *psr_state = 4; - else if (*psr_state == 0x30) - *psr_state = 5; - else if (*psr_state == 0x31) - *psr_state = 6; - else if (*psr_state == 0x40) - *psr_state = 7; - else if (*psr_state == 0x41) - *psr_state = 8; - else if (*psr_state == 0x42) - *psr_state = 9; - else if (*psr_state == 0x43) - *psr_state = 10; - else if (*psr_state == 0x44) - *psr_state = 11; - else if (*psr_state == 0x50) - *psr_state = 12; - else if (*psr_state == 0x51) - *psr_state = 13; - else if (*psr_state == 0x52) - *psr_state = 14; - else if (*psr_state == 0x53) - *psr_state = 15; + enum dc_psr_state state = PSR_STATE0; + + if (raw_state == 0) + state = PSR_STATE0; + else if (raw_state == 0x10) + state = PSR_STATE1; + else if (raw_state == 0x11) + state = PSR_STATE1a; + else if (raw_state == 0x20) + state = PSR_STATE2; + else if (raw_state == 0x21) + state = PSR_STATE2a; + else if (raw_state == 0x30) + state = PSR_STATE3; + else if (raw_state == 0x31) + state = PSR_STATE3Init; + else if (raw_state == 0x40) + state = PSR_STATE4; + else if (raw_state == 0x41) + state = PSR_STATE4a; + else if (raw_state == 0x42) + state = PSR_STATE4b; + else if (raw_state == 0x43) + state = PSR_STATE4c; + else if (raw_state == 0x44) + state = PSR_STATE4d; + else if (raw_state == 0x50) + state = PSR_STATE5; + else if (raw_state == 0x51) + state = PSR_STATE5a; + else if (raw_state == 0x52) + state = PSR_STATE5b; + else if (raw_state == 0x53) + state = PSR_STATE5c; + + return state; } /** * Get PSR state from firmware. */ -static void dmub_psr_get_state(struct dmub_psr *dmub, uint32_t *psr_state) +static void dmub_psr_get_state(struct dmub_psr *dmub, enum dc_psr_state *state) { struct dmub_srv *srv = dmub->ctx->dmub_srv->dmub; + uint32_t raw_state; // Send gpint command and wait for ack dmub_srv_send_gpint_command(srv, DMUB_GPINT__GET_PSR_STATE, 0, 30); - dmub_srv_get_gpint_response(srv, psr_state); + dmub_srv_get_gpint_response(srv, &raw_state); - convert_psr_state(psr_state); + *state = convert_psr_state(raw_state); } /** @@ -123,7 +128,9 @@ static void dmub_psr_enable(struct dmub_psr *dmub, bool enable, bool wait) { union dmub_rb_cmd cmd; struct dc_context *dc = dmub->ctx; - uint32_t retry_count, psr_state = 0; + uint32_t retry_count; + enum dc_psr_state state = PSR_STATE0; + cmd.psr_enable.header.type = DMUB_CMD__PSR; @@ -144,13 +151,13 @@ static void dmub_psr_enable(struct dmub_psr *dmub, bool enable, bool wait) */ if (wait) { for (retry_count = 0; retry_count <= 1000; retry_count++) { - dmub_psr_get_state(dmub, &psr_state); + dmub_psr_get_state(dmub, &state); if (enable) { - if (psr_state != 0) + if (state != PSR_STATE0) break; } else { - if (psr_state == 0) + if (state == PSR_STATE0) break; } @@ -169,12 +176,12 @@ static void dmub_psr_enable(struct dmub_psr *dmub, bool enable, bool wait) static void dmub_psr_set_level(struct dmub_psr *dmub, uint16_t psr_level) { union dmub_rb_cmd cmd; - uint32_t psr_state = 0; + enum dc_psr_state state = PSR_STATE0; struct dc_context *dc = dmub->ctx; - dmub_psr_get_state(dmub, &psr_state); + dmub_psr_get_state(dmub, &state); - if (psr_state == 0) + if (state == PSR_STATE0) return; cmd.psr_set_level.header.type = DMUB_CMD__PSR; @@ -254,6 +261,7 @@ static bool dmub_psr_copy_settings(struct dmub_psr *dmub, // Misc copy_settings_data->psr_level = psr_context->psr_level.u32all; copy_settings_data->smu_optimizations_en = psr_context->allow_smu_optimizations; + copy_settings_data->multi_disp_optimizations_en = psr_context->allow_multi_disp_optimizations; copy_settings_data->frame_delay = psr_context->frame_delay; copy_settings_data->frame_cap_ind = psr_context->psrFrameCaptureIndicationReq; copy_settings_data->init_sdp_deadline = psr_context->sdpTransmitLineNumDeadline; @@ -269,11 +277,43 @@ static bool dmub_psr_copy_settings(struct dmub_psr *dmub, return true; } +/** + * Send command to PSR to force static ENTER and ignore all state changes until exit + */ +static void dmub_psr_force_static(struct dmub_psr *dmub) +{ + union dmub_rb_cmd cmd; + struct dc_context *dc = dmub->ctx; + + cmd.psr_force_static.header.type = DMUB_CMD__PSR; + cmd.psr_force_static.header.sub_type = DMUB_CMD__PSR_FORCE_STATIC; + cmd.psr_enable.header.payload_bytes = 0; + + dc_dmub_srv_cmd_queue(dc->dmub_srv, &cmd); + dc_dmub_srv_cmd_execute(dc->dmub_srv); + dc_dmub_srv_wait_idle(dc->dmub_srv); +} + +/** + * Get PSR residency from firmware. + */ +static void dmub_psr_get_residency(struct dmub_psr *dmub, uint32_t *residency) +{ + struct dmub_srv *srv = dmub->ctx->dmub_srv->dmub; + + // Send gpint command and wait for ack + dmub_srv_send_gpint_command(srv, DMUB_GPINT__PSR_RESIDENCY, 0, 30); + + dmub_srv_get_gpint_response(srv, residency); +} + static const struct dmub_psr_funcs psr_funcs = { .psr_copy_settings = dmub_psr_copy_settings, .psr_enable = dmub_psr_enable, .psr_get_state = dmub_psr_get_state, .psr_set_level = dmub_psr_set_level, + .psr_force_static = dmub_psr_force_static, + .psr_get_residency = dmub_psr_get_residency, }; /** diff --git a/drivers/gpu/drm/amd/display/dc/dce/dmub_psr.h b/drivers/gpu/drm/amd/display/dc/dce/dmub_psr.h index dc121ed92d2e..fe747c20a0d2 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dmub_psr.h +++ b/drivers/gpu/drm/amd/display/dc/dce/dmub_psr.h @@ -37,8 +37,10 @@ struct dmub_psr { struct dmub_psr_funcs { bool (*psr_copy_settings)(struct dmub_psr *dmub, struct dc_link *link, struct psr_context *psr_context); void (*psr_enable)(struct dmub_psr *dmub, bool enable, bool wait); - void (*psr_get_state)(struct dmub_psr *dmub, uint32_t *psr_state); + void (*psr_get_state)(struct dmub_psr *dmub, enum dc_psr_state *dc_psr_state); void (*psr_set_level)(struct dmub_psr *dmub, uint16_t psr_level); + void (*psr_force_static)(struct dmub_psr *dmub); + void (*psr_get_residency)(struct dmub_psr *dmub, uint32_t *residency); }; struct dmub_psr *dmub_psr_create(struct dc_context *ctx); diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c index 9f56887029ca..4c230f1de9a3 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c @@ -939,12 +939,15 @@ void dce110_edp_backlight_control( return; } - if (enable && link->panel_cntl && - link->panel_cntl->funcs->is_panel_backlight_on(link->panel_cntl)) { - DC_LOG_HW_RESUME_S3( - "%s: panel already powered up. Do nothing.\n", + if (link->panel_cntl) { + bool is_backlight_on = link->panel_cntl->funcs->is_panel_backlight_on(link->panel_cntl); + + if ((enable && is_backlight_on) || (!enable && !is_backlight_on)) { + DC_LOG_HW_RESUME_S3( + "%s: panel already powered up/off. Do nothing.\n", __func__); - return; + return; + } } /* Send VBIOS command to control eDP panel backlight */ @@ -1527,6 +1530,8 @@ static void power_down_encoders(struct dc *dc) dc->links[i]->link_enc, signal); dc->links[i]->link_status.link_active = false; + memset(&dc->links[i]->cur_link_settings, 0, + sizeof(dc->links[i]->cur_link_settings)); } } diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp.h b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp.h index 2edf566b3a72..9a1f40eb5c47 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp.h +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp.h @@ -51,6 +51,8 @@ SRI(CM_GAMUT_REMAP_C33_C34, CM, id),\ SRI(DSCL_EXT_OVERSCAN_LEFT_RIGHT, DSCL, id), \ SRI(DSCL_EXT_OVERSCAN_TOP_BOTTOM, DSCL, id), \ + SRI(DSCL_MEM_PWR_STATUS, DSCL, id), \ + SRI(DSCL_MEM_PWR_CTRL, DSCL, id), \ SRI(OTG_H_BLANK, DSCL, id), \ SRI(OTG_V_BLANK, DSCL, id), \ SRI(SCL_MODE, DSCL, id), \ @@ -252,6 +254,8 @@ TF_SF(DSCL0_SCL_VERT_FILTER_INIT_BOT_C, SCL_V_INIT_INT_BOT_C, mask_sh),\ TF_SF(DSCL0_SCL_MODE, SCL_CHROMA_COEF_MODE, mask_sh),\ TF_SF(DSCL0_SCL_MODE, SCL_COEF_RAM_SELECT_CURRENT, mask_sh), \ + TF_SF(DSCL0_DSCL_MEM_PWR_CTRL, LUT_MEM_PWR_FORCE, mask_sh), \ + TF_SF(DSCL0_DSCL_MEM_PWR_STATUS, LUT_MEM_PWR_STATE, mask_sh), \ TF_SF(CM0_CM_ICSC_CONTROL, CM_ICSC_MODE, mask_sh), \ TF_SF(CM0_CM_ICSC_C11_C12, CM_ICSC_C11, mask_sh), \ TF_SF(CM0_CM_ICSC_C11_C12, CM_ICSC_C12, mask_sh), \ @@ -536,6 +540,8 @@ type SCL_V_INIT_INT_BOT_C; \ type SCL_CHROMA_COEF_MODE; \ type SCL_COEF_RAM_SELECT_CURRENT; \ + type LUT_MEM_PWR_FORCE; \ + type LUT_MEM_PWR_STATE; \ type CM_GAMUT_REMAP_MODE; \ type CM_GAMUT_REMAP_C11; \ type CM_GAMUT_REMAP_C12; \ @@ -1096,6 +1102,8 @@ struct dcn_dpp_mask { uint32_t DSCL_EXT_OVERSCAN_TOP_BOTTOM; \ uint32_t OTG_H_BLANK; \ uint32_t OTG_V_BLANK; \ + uint32_t DSCL_MEM_PWR_CTRL; \ + uint32_t DSCL_MEM_PWR_STATUS; \ uint32_t SCL_MODE; \ uint32_t LB_DATA_FORMAT; \ uint32_t LB_MEMORY_CTRL; \ diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp_dscl.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp_dscl.c index 878b53d85694..efa86d5c6847 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp_dscl.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp_dscl.c @@ -198,6 +198,20 @@ static enum dscl_mode_sel dpp1_dscl_get_dscl_mode( return DSCL_MODE_SCALING_420_YCBCR_ENABLE; } +static void dpp1_power_on_dscl( + struct dpp *dpp_base, + bool power_on) +{ + struct dcn10_dpp *dpp = TO_DCN10_DPP(dpp_base); + + if (dpp->tf_regs->DSCL_MEM_PWR_CTRL) { + REG_UPDATE(DSCL_MEM_PWR_CTRL, LUT_MEM_PWR_FORCE, power_on ? 0 : 3); + if (power_on) + REG_WAIT(DSCL_MEM_PWR_STATUS, LUT_MEM_PWR_STATE, 0, 1, 5); + } +} + + static void dpp1_dscl_set_lb( struct dcn10_dpp *dpp, const struct line_buffer_params *lb_params, @@ -678,6 +692,11 @@ void dpp1_dscl_set_scaler_manual_scale( dpp->scl_data = *scl_data; + if (dpp_base->ctx->dc->debug.enable_mem_low_power.bits.dscl) { + if (dscl_mode != DSCL_MODE_DSCL_BYPASS) + dpp1_power_on_dscl(dpp_base, true); + } + /* Autocal off */ REG_SET_3(DSCL_AUTOCAL, 0, AUTOCAL_MODE, AUTOCAL_MODE_OFF, @@ -697,8 +716,11 @@ void dpp1_dscl_set_scaler_manual_scale( /* SCL mode */ REG_UPDATE(SCL_MODE, DSCL_MODE, dscl_mode); - if (dscl_mode == DSCL_MODE_DSCL_BYPASS) + if (dscl_mode == DSCL_MODE_DSCL_BYPASS) { + if (dpp_base->ctx->dc->debug.enable_mem_low_power.bits.dscl) + dpp1_power_on_dscl(dpp_base, false); return; + } /* LB */ lb_config = dpp1_dscl_find_lb_memory_config(dpp, scl_data); diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c index 8eb88a50af51..9f7d6b087553 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c @@ -1442,16 +1442,13 @@ void dcn10_init_hw(struct dc *dc) /* In headless boot cases, DIG may be turned * on which causes HW/SW discrepancies. * To avoid this, power down hardware on boot - * if DIG is turned on and seamless boot not enabled + * if DIG is turned on */ void dcn10_power_down_on_boot(struct dc *dc) { int i = 0; struct dc_link *edp_link; - if (!dc->config.power_down_display_on_boot) - return; - edp_link = get_edp_link(dc); if (edp_link && edp_link->link_enc->funcs->is_dig_enabled && @@ -3279,6 +3276,8 @@ void dcn10_set_cursor_position(struct pipe_ctx *pipe_ctx) }; bool pipe_split_on = (pipe_ctx->top_pipe != NULL) || (pipe_ctx->bottom_pipe != NULL); + bool odm_combine_on = (pipe_ctx->next_odm_pipe != NULL) || + (pipe_ctx->prev_odm_pipe != NULL); int x_plane = pipe_ctx->plane_state->dst_rect.x; int y_plane = pipe_ctx->plane_state->dst_rect.y; @@ -3362,16 +3361,56 @@ void dcn10_set_cursor_position(struct pipe_ctx *pipe_ctx) uint32_t temp_y = pos_cpy.y; int viewport_height = pipe_ctx->plane_res.scl_data.viewport.height; - - if (pipe_split_on) { + int viewport_y = + pipe_ctx->plane_res.scl_data.viewport.y; + + /** + * Display groups that are 1xnY, have pos_cpy.x > 2 * viewport.height + * For pipe split cases: + * - apply offset of viewport.y to normalize pos_cpy.x + * - calculate the pos_cpy.y as before + * - shift pos_cpy.y back by same offset to get final value + * - since we iterate through both pipes, use the lower + * viewport.y for offset + * For non pipe split cases, use the same calculation for + * pos_cpy.y as the 180 degree rotation case below, + * but use pos_cpy.x as our input because we are rotating + * 270 degrees + */ + if (pipe_split_on || odm_combine_on) { + int pos_cpy_x_offset; + int other_pipe_viewport_y; + + if (pipe_split_on) { + if (pipe_ctx->bottom_pipe) { + other_pipe_viewport_y = + pipe_ctx->bottom_pipe->plane_res.scl_data.viewport.y; + } else { + other_pipe_viewport_y = + pipe_ctx->top_pipe->plane_res.scl_data.viewport.y; + } + } else { + if (pipe_ctx->next_odm_pipe) { + other_pipe_viewport_y = + pipe_ctx->next_odm_pipe->plane_res.scl_data.viewport.y; + } else { + other_pipe_viewport_y = + pipe_ctx->prev_odm_pipe->plane_res.scl_data.viewport.y; + } + } + pos_cpy_x_offset = (viewport_y > other_pipe_viewport_y) ? + other_pipe_viewport_y : viewport_y; + pos_cpy.x -= pos_cpy_x_offset; if (pos_cpy.x > viewport_height) { pos_cpy.x = pos_cpy.x - viewport_height; pos_cpy.y = viewport_height - pos_cpy.x; } else { pos_cpy.y = 2 * viewport_height - pos_cpy.x; } - } else - pos_cpy.y = viewport_height - pos_cpy.x; + pos_cpy.y += pos_cpy_x_offset; + } else { + pos_cpy.y = (2 * viewport_y) + viewport_height - pos_cpy.x; + } pos_cpy.x = temp_y; } // Mirror horizontally and vertically @@ -3381,7 +3420,7 @@ void dcn10_set_cursor_position(struct pipe_ctx *pipe_ctx) int viewport_x = pipe_ctx->plane_res.scl_data.viewport.x; - if (pipe_split_on) { + if (pipe_split_on || odm_combine_on) { if (pos_cpy.x >= viewport_width + viewport_x) { pos_cpy.x = 2 * viewport_width - pos_cpy.x + 2 * viewport_x; @@ -3399,7 +3438,17 @@ void dcn10_set_cursor_position(struct pipe_ctx *pipe_ctx) } else { pos_cpy.x = viewport_width - pos_cpy.x + 2 * viewport_x; } - pos_cpy.y = pipe_ctx->plane_res.scl_data.viewport.height - pos_cpy.y; + + /** + * Display groups that are 1xnY, have pos_cpy.y > viewport.height + * Calculation: + * delta_from_bottom = viewport.y + viewport.height - pos_cpy.y + * pos_cpy.y_new = viewport.y + delta_from_bottom + * Simplify it as: + * pos_cpy.y = viewport.y * 2 + viewport.height - pos_cpy.y + */ + pos_cpy.y = (2 * pipe_ctx->plane_res.scl_data.viewport.y) + + pipe_ctx->plane_res.scl_data.viewport.height - pos_cpy.y; } hubp->funcs->set_cursor_position(hubp, &pos_cpy, ¶m); diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c index e74bb2735885..bdc37831535e 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c @@ -1439,6 +1439,7 @@ static bool dcn10_resource_construct( dc->caps.color.dpp.dgam_rom_caps.hlg = 0; 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.hw_3d_lut = 0; dc->caps.color.dpp.ogam_ram = 1; // RGAM on DCN1 diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_stream_encoder.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_stream_encoder.c index f70fcadf1ee5..73ac78b16bd4 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_stream_encoder.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_stream_encoder.c @@ -1021,88 +1021,6 @@ void enc1_reset_hdmi_stream_attribute( #include "include/audio_types.h" -/** -* speakersToChannels -* -* @brief -* translate speakers to channels -* -* FL - Front Left -* FR - Front Right -* RL - Rear Left -* RR - Rear Right -* RC - Rear Center -* FC - Front Center -* FLC - Front Left Center -* FRC - Front Right Center -* RLC - Rear Left Center -* RRC - Rear Right Center -* LFE - Low Freq Effect -* -* FC -* FLC FRC -* FL FR -* -* LFE -* () -* -* -* RL RR -* RLC RRC -* RC -* -* ch 8 7 6 5 4 3 2 1 -* 0b00000011 - - - - - - FR FL -* 0b00000111 - - - - - LFE FR FL -* 0b00001011 - - - - FC - FR FL -* 0b00001111 - - - - FC LFE FR FL -* 0b00010011 - - - RC - - FR FL -* 0b00010111 - - - RC - LFE FR FL -* 0b00011011 - - - RC FC - FR FL -* 0b00011111 - - - RC FC LFE FR FL -* 0b00110011 - - RR RL - - FR FL -* 0b00110111 - - RR RL - LFE FR FL -* 0b00111011 - - RR RL FC - FR FL -* 0b00111111 - - RR RL FC LFE FR FL -* 0b01110011 - RC RR RL - - FR FL -* 0b01110111 - RC RR RL - LFE FR FL -* 0b01111011 - RC RR RL FC - FR FL -* 0b01111111 - RC RR RL FC LFE FR FL -* 0b11110011 RRC RLC RR RL - - FR FL -* 0b11110111 RRC RLC RR RL - LFE FR FL -* 0b11111011 RRC RLC RR RL FC - FR FL -* 0b11111111 RRC RLC RR RL FC LFE FR FL -* 0b11000011 FRC FLC - - - - FR FL -* 0b11000111 FRC FLC - - - LFE FR FL -* 0b11001011 FRC FLC - - FC - FR FL -* 0b11001111 FRC FLC - - FC LFE FR FL -* 0b11010011 FRC FLC - RC - - FR FL -* 0b11010111 FRC FLC - RC - LFE FR FL -* 0b11011011 FRC FLC - RC FC - FR FL -* 0b11011111 FRC FLC - RC FC LFE FR FL -* 0b11110011 FRC FLC RR RL - - FR FL -* 0b11110111 FRC FLC RR RL - LFE FR FL -* 0b11111011 FRC FLC RR RL FC - FR FL -* 0b11111111 FRC FLC RR RL FC LFE FR FL -* -* @param -* speakers - speaker information as it comes from CEA audio block -*/ -/* translate speakers to channels */ - -union audio_cea_channels { - uint8_t all; - struct audio_cea_channels_bits { - uint32_t FL:1; - uint32_t FR:1; - uint32_t LFE:1; - uint32_t FC:1; - uint32_t RL_RC:1; - uint32_t RR:1; - uint32_t RC_RLC_FLC:1; - uint32_t RRC_FRC:1; - } channels; -}; /* 25.2MHz/1.001*/ /* 25.2MHz/1.001*/ diff --git a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_dpp.h b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_dpp.h index 27610251c57f..e735363d0051 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_dpp.h +++ b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_dpp.h @@ -632,8 +632,7 @@ type CUR0_PIX_INV_MODE; \ type CUR0_PIXEL_ALPHA_MOD_EN; \ type CUR0_ROM_EN;\ - type OBUF_MEM_PWR_FORCE;\ - type LUT_MEM_PWR_FORCE + type OBUF_MEM_PWR_FORCE struct dcn2_dpp_shift { @@ -659,8 +658,7 @@ struct dcn2_dpp_mask { uint32_t COLOR_KEYER_RED; \ uint32_t COLOR_KEYER_GREEN; \ uint32_t COLOR_KEYER_BLUE; \ - uint32_t OBUF_MEM_PWR_CTRL; \ - uint32_t DSCL_MEM_PWR_CTRL + uint32_t OBUF_MEM_PWR_CTRL #define DPP_DCN2_REG_VARIABLE_LIST_CM_APPEND \ uint32_t CM_GAMUT_REMAP_B_C11_C12; \ diff --git a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_hwseq.c b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_hwseq.c index d8d45d860cb7..abcb06044e6e 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_hwseq.c +++ b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_hwseq.c @@ -1163,29 +1163,32 @@ void dcn20_pipe_control_lock( if (pipe->plane_state != NULL) flip_immediate = pipe->plane_state->flip_immediate; - temp_pipe = pipe->bottom_pipe; - while (!flip_immediate && temp_pipe) { - if (temp_pipe->plane_state != NULL) - flip_immediate = temp_pipe->plane_state->flip_immediate; - temp_pipe = temp_pipe->bottom_pipe; + if (pipe->stream_res.gsl_group > 0) { + temp_pipe = pipe->bottom_pipe; + while (!flip_immediate && temp_pipe) { + if (temp_pipe->plane_state != NULL) + flip_immediate = temp_pipe->plane_state->flip_immediate; + temp_pipe = temp_pipe->bottom_pipe; + } } if (flip_immediate && lock) { const int TIMEOUT_FOR_FLIP_PENDING = 100000; int i; - for (i = 0; i < TIMEOUT_FOR_FLIP_PENDING; ++i) { - if (!pipe->plane_res.hubp->funcs->hubp_is_flip_pending(pipe->plane_res.hubp)) - break; - udelay(1); - } - - if (pipe->bottom_pipe != NULL) { - for (i = 0; i < TIMEOUT_FOR_FLIP_PENDING; ++i) { - if (!pipe->bottom_pipe->plane_res.hubp->funcs->hubp_is_flip_pending(pipe->bottom_pipe->plane_res.hubp)) - break; - udelay(1); + temp_pipe = pipe; + while (temp_pipe) { + if (temp_pipe->plane_state && temp_pipe->plane_state->flip_immediate) { + for (i = 0; i < TIMEOUT_FOR_FLIP_PENDING; ++i) { + if (!temp_pipe->plane_res.hubp->funcs->hubp_is_flip_pending(temp_pipe->plane_res.hubp)) + break; + udelay(1); + } + + /* no reason it should take this long for immediate flips */ + ASSERT(i != TIMEOUT_FOR_FLIP_PENDING); } + temp_pipe = temp_pipe->bottom_pipe; } } @@ -1692,6 +1695,15 @@ void dcn20_program_front_end_for_ctx( && context->res_ctx.pipe_ctx[i].stream) hws->funcs.blank_pixel_data(dc, &context->res_ctx.pipe_ctx[i], true); + /* wait for outstanding pending changes before adding or removing planes */ + 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.enable) { + dc->hwss.wait_for_pending_cleared(dc, context); + break; + } + } + /* Disconnect mpcc */ for (i = 0; i < dc->res_pool->pipe_count; i++) if (context->res_ctx.pipe_ctx[i].update_flags.bits.disable diff --git a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_resource.c b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_resource.c index 3fcc31d75792..ff36db5edf6c 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_resource.c @@ -2012,7 +2012,10 @@ void dcn20_populate_dml_writeback_from_context( } int dcn20_populate_dml_pipes_from_context( - struct dc *dc, struct dc_state *context, display_e2e_pipe_params_st *pipes) + struct dc *dc, + struct dc_state *context, + display_e2e_pipe_params_st *pipes, + bool fast_validate) { int pipe_cnt, i; bool synchronized_vblank = true; @@ -2050,6 +2053,7 @@ int dcn20_populate_dml_pipes_from_context( v_total = timing->v_total; front_porch = timing->v_front_porch; + /* todo: pipes[pipe_cnt].pipe.src.dynamic_metadata_enable = 0; pipes[pipe_cnt].pipe.src.dcc = 0; @@ -2827,7 +2831,8 @@ bool dcn20_fast_validate_bw( display_e2e_pipe_params_st *pipes, int *pipe_cnt_out, int *pipe_split_from, - int *vlevel_out) + int *vlevel_out, + bool fast_validate) { bool out = false; int split[MAX_PIPES] = { 0 }; @@ -2839,7 +2844,7 @@ bool dcn20_fast_validate_bw( dcn20_merge_pipes_for_validate(dc, context); - pipe_cnt = dc->res_pool->funcs->populate_dml_pipes(dc, context, pipes); + pipe_cnt = dc->res_pool->funcs->populate_dml_pipes(dc, context, pipes, fast_validate); *pipe_cnt_out = pipe_cnt; @@ -2943,7 +2948,8 @@ static void dcn20_calculate_wm( display_e2e_pipe_params_st *pipes, int *out_pipe_cnt, int *pipe_split_from, - int vlevel) + int vlevel, + bool fast_validate) { int pipe_cnt, i, pipe_idx; @@ -2988,10 +2994,10 @@ static void dcn20_calculate_wm( if (pipe_cnt != pipe_idx) { if (dc->res_pool->funcs->populate_dml_pipes) pipe_cnt = dc->res_pool->funcs->populate_dml_pipes(dc, - context, pipes); + context, pipes, fast_validate); else pipe_cnt = dcn20_populate_dml_pipes_from_context(dc, - context, pipes); + context, pipes, fast_validate); } *out_pipe_cnt = pipe_cnt; @@ -3136,7 +3142,7 @@ static bool dcn20_validate_bandwidth_internal(struct dc *dc, struct dc_state *co BW_VAL_TRACE_COUNT(); - out = dcn20_fast_validate_bw(dc, context, pipes, &pipe_cnt, pipe_split_from, &vlevel); + out = dcn20_fast_validate_bw(dc, context, pipes, &pipe_cnt, pipe_split_from, &vlevel, fast_validate); if (pipe_cnt == 0) goto validate_out; @@ -3151,7 +3157,7 @@ static bool dcn20_validate_bandwidth_internal(struct dc *dc, struct dc_state *co goto validate_out; } - dcn20_calculate_wm(dc, context, pipes, &pipe_cnt, pipe_split_from, vlevel); + dcn20_calculate_wm(dc, context, pipes, &pipe_cnt, pipe_split_from, vlevel, fast_validate); dcn20_calculate_dlg_params(dc, context, pipes, pipe_cnt, vlevel); BW_VAL_TRACE_END_WATERMARKS(); @@ -3814,6 +3820,7 @@ static bool dcn20_resource_construct( dc->caps.color.dpp.dgam_rom_caps.hlg = 0; 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.hw_3d_lut = 1; dc->caps.color.dpp.ogam_ram = 1; diff --git a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_resource.h b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_resource.h index 64bce14fefa3..c8f3127bbcdf 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_resource.h +++ b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_resource.h @@ -50,7 +50,10 @@ unsigned int dcn20_calc_max_scaled_time( enum mmhubbub_wbif_mode mode, unsigned int urgent_watermark); int dcn20_populate_dml_pipes_from_context( - struct dc *dc, struct dc_state *context, display_e2e_pipe_params_st *pipes); + struct dc *dc, + struct dc_state *context, + display_e2e_pipe_params_st *pipes, + bool fast_validate); struct pipe_ctx *dcn20_acquire_idle_pipe_for_layer( struct dc_state *state, const struct resource_pool *pool, @@ -155,7 +158,8 @@ bool dcn20_fast_validate_bw( display_e2e_pipe_params_st *pipes, int *pipe_cnt_out, int *pipe_split_from, - int *vlevel_out); + int *vlevel_out, + bool fast_validate); void dcn20_calculate_dlg_params( struct dc *dc, struct dc_state *context, display_e2e_pipe_params_st *pipes, diff --git a/drivers/gpu/drm/amd/display/dc/dcn21/Makefile b/drivers/gpu/drm/amd/display/dc/dcn21/Makefile index 51a2f3d4c194..1ee5fc03b7b3 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn21/Makefile +++ b/drivers/gpu/drm/amd/display/dc/dcn21/Makefile @@ -3,7 +3,7 @@ # Makefile for DCN21. DCN21 = dcn21_init.o dcn21_hubp.o dcn21_hubbub.o dcn21_resource.o \ - dcn21_hwseq.o dcn21_link_encoder.o + dcn21_hwseq.o dcn21_link_encoder.o dcn21_dccg.o ifdef CONFIG_X86 CFLAGS_$(AMDDALPATH)/dc/dcn21/dcn21_resource.o := -mhard-float -msse diff --git a/drivers/gpu/drm/amd/display/dc/dcn21/dcn21_dccg.c b/drivers/gpu/drm/amd/display/dc/dcn21/dcn21_dccg.c new file mode 100644 index 000000000000..60cf3ff68cb0 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/dcn21/dcn21_dccg.c @@ -0,0 +1,129 @@ +/* + * Copyright 2018 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#include "reg_helper.h" +#include "core_types.h" +#include "dcn20/dcn20_dccg.h" +#include "dcn21_dccg.h" + +#define TO_DCN_DCCG(dccg)\ + container_of(dccg, struct dcn_dccg, base) + +#define REG(reg) \ + (dccg_dcn->regs->reg) + +#undef FN +#define FN(reg_name, field_name) \ + dccg_dcn->dccg_shift->field_name, dccg_dcn->dccg_mask->field_name + +#define CTX \ + dccg_dcn->base.ctx +#define DC_LOGGER \ + dccg->ctx->logger + +void dccg21_update_dpp_dto(struct dccg *dccg, int dpp_inst, int req_dppclk) +{ + struct dcn_dccg *dccg_dcn = TO_DCN_DCCG(dccg); + + if (dccg->ref_dppclk) { + int ref_dppclk = dccg->ref_dppclk; + int modulo = ref_dppclk / 10000; + int phase; + + if (req_dppclk) { + /* + * program DPP DTO phase and modulo as below + * phase = ceiling(dpp_pipe_clk_mhz / 10) + * module = trunc(dpp_global_clk_mhz / 10) + * + * storing frequencies in registers allow dmcub fw + * to run time lower clocks when possible for power saving + * + * ceiling phase and truncate modulo guarentees the divided + * down per pipe dpp clock has high enough frequency + */ + phase = (req_dppclk + 9999) / 10000; + + if (phase > modulo) { + /* phase > modulo result in screen corruption + * ie phase = 30, mod = 29 for 4k@60 HDMI + * in these case we don't want pipe clock to be divided + */ + phase = modulo; + } + } else { + /* + * set phase to 10 if dpp isn't used to + * prevent hard hang if access dpp register + * on unused pipe + * + * DTO should be on to divide down un-used + * pipe clock for power saving + */ + phase = 10; + } + + REG_SET_2(DPPCLK_DTO_PARAM[dpp_inst], 0, + DPPCLK0_DTO_PHASE, phase, + DPPCLK0_DTO_MODULO, modulo); + + REG_UPDATE(DPPCLK_DTO_CTRL, + DPPCLK_DTO_ENABLE[dpp_inst], 1); + } + + dccg->pipe_dppclk_khz[dpp_inst] = req_dppclk; +} + + +static const struct dccg_funcs dccg21_funcs = { + .update_dpp_dto = dccg21_update_dpp_dto, + .get_dccg_ref_freq = dccg2_get_dccg_ref_freq, + .dccg_init = dccg2_init +}; + +struct dccg *dccg21_create( + struct dc_context *ctx, + const struct dccg_registers *regs, + const struct dccg_shift *dccg_shift, + const struct dccg_mask *dccg_mask) +{ + struct dcn_dccg *dccg_dcn = kzalloc(sizeof(*dccg_dcn), GFP_KERNEL); + struct dccg *base; + + if (dccg_dcn == NULL) { + BREAK_TO_DEBUGGER(); + return NULL; + } + + base = &dccg_dcn->base; + base->ctx = ctx; + base->funcs = &dccg21_funcs; + + dccg_dcn->regs = regs; + dccg_dcn->dccg_shift = dccg_shift; + dccg_dcn->dccg_mask = dccg_mask; + + return &dccg_dcn->base; +} diff --git a/drivers/gpu/drm/amd/display/dc/dcn21/dcn21_dccg.h b/drivers/gpu/drm/amd/display/dc/dcn21/dcn21_dccg.h new file mode 100644 index 000000000000..b7efa777ec73 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/dcn21/dcn21_dccg.h @@ -0,0 +1,36 @@ +/* + * Copyright 2018 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#ifndef __DCN21_DCCG_H__ +#define __DCN21_DCCG_H__ + +struct dccg *dccg21_create( + struct dc_context *ctx, + const struct dccg_registers *regs, + const struct dccg_shift *dccg_shift, + const struct dccg_mask *dccg_mask); + + +#endif /* __DCN21_DCCG_H__ */ diff --git a/drivers/gpu/drm/amd/display/dc/dcn21/dcn21_hubbub.c b/drivers/gpu/drm/amd/display/dc/dcn21/dcn21_hubbub.c index 129f0b62f751..42fbb5e6d505 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn21/dcn21_hubbub.c +++ b/drivers/gpu/drm/amd/display/dc/dcn21/dcn21_hubbub.c @@ -99,6 +99,8 @@ void dcn21_dchvm_init(struct hubbub *hubbub) //Poll until HOSTVM_PREFETCH_DONE = 1 REG_WAIT(DCHVM_RIOMMU_STAT0, HOSTVM_PREFETCH_DONE, 1, 5, 100); + + hubbub->riommu_active = true; } } diff --git a/drivers/gpu/drm/amd/display/dc/dcn21/dcn21_hwseq.c b/drivers/gpu/drm/amd/display/dc/dcn21/dcn21_hwseq.c index 1fa193078803..96ee0b82f458 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn21/dcn21_hwseq.c +++ b/drivers/gpu/drm/amd/display/dc/dcn21/dcn21_hwseq.c @@ -171,9 +171,11 @@ void dcn21_set_abm_immediate_disable(struct pipe_ctx *pipe_ctx) return; } - if (abm && panel_cntl) + if (abm && panel_cntl) { dmub_abm_set_pipe(abm, otg_inst, SET_ABM_PIPE_IMMEDIATELY_DISABLE, panel_cntl->inst); + panel_cntl->funcs->store_backlight_level(panel_cntl); + } } void dcn21_set_pipe(struct pipe_ctx *pipe_ctx) diff --git a/drivers/gpu/drm/amd/display/dc/dcn21/dcn21_resource.c b/drivers/gpu/drm/amd/display/dc/dcn21/dcn21_resource.c index 5ae3419682c8..1c88d2edd381 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn21/dcn21_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dcn21/dcn21_resource.c @@ -58,6 +58,7 @@ #include "dce110/dce110_resource.h" #include "dml/display_mode_vba.h" #include "dcn20/dcn20_dccg.h" +#include "dcn21/dcn21_dccg.h" #include "dcn21_hubbub.h" #include "dcn10/dcn10_resource.h" #include "dce110/dce110_resource.h" @@ -301,9 +302,7 @@ struct _vcs_dpi_soc_bounding_box_st dcn2_1_soc = { .xfc_bus_transport_time_us = 4, .xfc_xbuf_latency_tolerance_us = 4, .use_urgent_burst_bw = 1, - .num_states = 8, - .allow_dram_self_refresh_or_dram_clock_change_in_vblank - = dm_allow_self_refresh_and_mclk_switch + .num_states = 8 }; #ifndef MAX @@ -706,7 +705,10 @@ static const struct dcn10_stream_encoder_mask se_mask = { static void dcn21_pp_smu_destroy(struct pp_smu_funcs **pp_smu); static int dcn21_populate_dml_pipes_from_context( - struct dc *dc, struct dc_state *context, display_e2e_pipe_params_st *pipes); + struct dc *dc, + struct dc_state *context, + display_e2e_pipe_params_st *pipes, + bool fast_validate); static struct input_pixel_processor *dcn21_ipp_create( struct dc_context *ctx, uint32_t inst) @@ -1093,7 +1095,8 @@ void dcn21_calculate_wm( display_e2e_pipe_params_st *pipes, int *out_pipe_cnt, int *pipe_split_from, - int vlevel_req) + int vlevel_req, + bool fast_validate) { int pipe_cnt, i, pipe_idx; int vlevel, vlevel_max; @@ -1135,10 +1138,10 @@ void dcn21_calculate_wm( if (pipe_cnt != pipe_idx) { if (dc->res_pool->funcs->populate_dml_pipes) pipe_cnt = dc->res_pool->funcs->populate_dml_pipes(dc, - context, pipes); + context, pipes, fast_validate); else pipe_cnt = dcn21_populate_dml_pipes_from_context(dc, - context, pipes); + context, pipes, fast_validate); } *out_pipe_cnt = pipe_cnt; @@ -1179,7 +1182,8 @@ static bool dcn21_fast_validate_bw( display_e2e_pipe_params_st *pipes, int *pipe_cnt_out, int *pipe_split_from, - int *vlevel_out) + int *vlevel_out, + bool fast_validate) { bool out = false; int split[MAX_PIPES] = { 0 }; @@ -1191,7 +1195,7 @@ static bool dcn21_fast_validate_bw( dcn20_merge_pipes_for_validate(dc, context); - pipe_cnt = dc->res_pool->funcs->populate_dml_pipes(dc, context, pipes); + pipe_cnt = dc->res_pool->funcs->populate_dml_pipes(dc, context, pipes, fast_validate); *pipe_cnt_out = pipe_cnt; @@ -1199,11 +1203,29 @@ static bool dcn21_fast_validate_bw( out = true; goto validate_out; } - + /* + * DML favors voltage over p-state, but we're more interested in + * supporting p-state over voltage. We can't support p-state in + * prefetch mode > 0 so try capping the prefetch mode to start. + */ + context->bw_ctx.dml.soc.allow_dram_self_refresh_or_dram_clock_change_in_vblank = + dm_allow_self_refresh_and_mclk_switch; vlevel = dml_get_voltage_level(&context->bw_ctx.dml, pipes, pipe_cnt); - if (vlevel > context->bw_ctx.dml.soc.num_states) - goto validate_fail; + if (vlevel > context->bw_ctx.dml.soc.num_states) { + /* + * If mode is unsupported or there's still no p-state support then + * fall back to favoring voltage. + * + * We don't actually support prefetch mode 2, so require that we + * at least support prefetch mode 1. + */ + context->bw_ctx.dml.soc.allow_dram_self_refresh_or_dram_clock_change_in_vblank = + dm_allow_self_refresh; + vlevel = dml_get_voltage_level(&context->bw_ctx.dml, pipes, pipe_cnt); + if (vlevel > context->bw_ctx.dml.soc.num_states) + goto validate_fail; + } vlevel = dcn20_validate_apply_pipe_split_flags(dc, context, vlevel, split, NULL); @@ -1323,7 +1345,7 @@ bool dcn21_validate_bandwidth(struct dc *dc, struct dc_state *context, /*Unsafe due to current pipe merge and split logic*/ ASSERT(context != dc->current_state); - out = dcn21_fast_validate_bw(dc, context, pipes, &pipe_cnt, pipe_split_from, &vlevel); + out = dcn21_fast_validate_bw(dc, context, pipes, &pipe_cnt, pipe_split_from, &vlevel, fast_validate); if (pipe_cnt == 0) goto validate_out; @@ -1338,7 +1360,7 @@ bool dcn21_validate_bandwidth(struct dc *dc, struct dc_state *context, goto validate_out; } - dcn21_calculate_wm(dc, context, pipes, &pipe_cnt, pipe_split_from, vlevel); + dcn21_calculate_wm(dc, context, pipes, &pipe_cnt, pipe_split_from, vlevel, fast_validate); dcn20_calculate_dlg_params(dc, context, pipes, pipe_cnt, vlevel); BW_VAL_TRACE_END_WATERMARKS(); @@ -1854,14 +1876,17 @@ static uint32_t read_pipe_fuses(struct dc_context *ctx) } static int dcn21_populate_dml_pipes_from_context( - struct dc *dc, struct dc_state *context, display_e2e_pipe_params_st *pipes) + struct dc *dc, + struct dc_state *context, + display_e2e_pipe_params_st *pipes, + bool fast_validate) { - uint32_t pipe_cnt = dcn20_populate_dml_pipes_from_context(dc, context, pipes); + uint32_t pipe_cnt = dcn20_populate_dml_pipes_from_context(dc, context, pipes, fast_validate); int i; for (i = 0; i < pipe_cnt; i++) { - pipes[i].pipe.src.hostvm = 1; + pipes[i].pipe.src.hostvm = dc->res_pool->hubbub->riommu_active; pipes[i].pipe.src.gpuvm = 1; } @@ -1954,6 +1979,7 @@ static bool dcn21_resource_construct( dc->caps.color.dpp.dgam_rom_caps.hlg = 0; 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.hw_3d_lut = 1; dc->caps.color.dpp.ogam_ram = 1; @@ -2021,7 +2047,7 @@ static bool dcn21_resource_construct( } } - pool->base.dccg = dccg2_create(ctx, &dccg_regs, &dccg_shift, &dccg_mask); + pool->base.dccg = dccg21_create(ctx, &dccg_regs, &dccg_shift, &dccg_mask); if (pool->base.dccg == NULL) { dm_error("DC: failed to create dccg!\n"); BREAK_TO_DEBUGGER(); diff --git a/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_afmt.c b/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_afmt.c index 2b08b1d72177..fa981cd04dd0 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_afmt.c +++ b/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_afmt.c @@ -25,6 +25,7 @@ #include "dc_bios_types.h" +#include "hw_shared.h" #include "dcn30_afmt.h" #include "reg_helper.h" diff --git a/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_afmt.h b/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_afmt.h index 08b2d8a8170c..85d4619207e2 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_afmt.h +++ b/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_afmt.h @@ -100,89 +100,6 @@ struct dcn30_afmt_mask { }; -/** -* speakersToChannels -* -* @brief -* translate speakers to channels -* -* FL - Front Left -* FR - Front Right -* RL - Rear Left -* RR - Rear Right -* RC - Rear Center -* FC - Front Center -* FLC - Front Left Center -* FRC - Front Right Center -* RLC - Rear Left Center -* RRC - Rear Right Center -* LFE - Low Freq Effect -* -* FC -* FLC FRC -* FL FR -* -* LFE -* () -* -* -* RL RR -* RLC RRC -* RC -* -* ch 8 7 6 5 4 3 2 1 -* 0b00000011 - - - - - - FR FL -* 0b00000111 - - - - - LFE FR FL -* 0b00001011 - - - - FC - FR FL -* 0b00001111 - - - - FC LFE FR FL -* 0b00010011 - - - RC - - FR FL -* 0b00010111 - - - RC - LFE FR FL -* 0b00011011 - - - RC FC - FR FL -* 0b00011111 - - - RC FC LFE FR FL -* 0b00110011 - - RR RL - - FR FL -* 0b00110111 - - RR RL - LFE FR FL -* 0b00111011 - - RR RL FC - FR FL -* 0b00111111 - - RR RL FC LFE FR FL -* 0b01110011 - RC RR RL - - FR FL -* 0b01110111 - RC RR RL - LFE FR FL -* 0b01111011 - RC RR RL FC - FR FL -* 0b01111111 - RC RR RL FC LFE FR FL -* 0b11110011 RRC RLC RR RL - - FR FL -* 0b11110111 RRC RLC RR RL - LFE FR FL -* 0b11111011 RRC RLC RR RL FC - FR FL -* 0b11111111 RRC RLC RR RL FC LFE FR FL -* 0b11000011 FRC FLC - - - - FR FL -* 0b11000111 FRC FLC - - - LFE FR FL -* 0b11001011 FRC FLC - - FC - FR FL -* 0b11001111 FRC FLC - - FC LFE FR FL -* 0b11010011 FRC FLC - RC - - FR FL -* 0b11010111 FRC FLC - RC - LFE FR FL -* 0b11011011 FRC FLC - RC FC - FR FL -* 0b11011111 FRC FLC - RC FC LFE FR FL -* 0b11110011 FRC FLC RR RL - - FR FL -* 0b11110111 FRC FLC RR RL - LFE FR FL -* 0b11111011 FRC FLC RR RL FC - FR FL -* 0b11111111 FRC FLC RR RL FC LFE FR FL -* -* @param -* speakers - speaker information as it comes from CEA audio block -*/ -/* translate speakers to channels */ - -union audio_cea_channels { - uint8_t all; - struct audio_cea_channels_bits { - uint32_t FL:1; - uint32_t FR:1; - uint32_t LFE:1; - uint32_t FC:1; - uint32_t RL_RC:1; - uint32_t RR:1; - uint32_t RC_RLC_FLC:1; - uint32_t RRC_FRC:1; - } channels; -}; - struct afmt; struct afmt_funcs { diff --git a/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_dpp.c b/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_dpp.c index 29231528f052..6e864b1a95c4 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_dpp.c +++ b/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_dpp.c @@ -500,9 +500,40 @@ static void dpp3_power_on_blnd_lut( { struct dcn3_dpp *dpp = TO_DCN30_DPP(dpp_base); - REG_SET(CM_MEM_PWR_CTRL, 0, - BLNDGAM_MEM_PWR_FORCE, power_on == true ? 0:1); + if (dpp_base->ctx->dc->debug.enable_mem_low_power.bits.cm) { + REG_UPDATE(CM_MEM_PWR_CTRL, BLNDGAM_MEM_PWR_FORCE, power_on ? 0 : 3); + if (power_on) + REG_WAIT(CM_MEM_PWR_STATUS, BLNDGAM_MEM_PWR_STATE, 0, 1, 5); + } else { + REG_SET(CM_MEM_PWR_CTRL, 0, + BLNDGAM_MEM_PWR_FORCE, power_on == true ? 0 : 1); + } +} +static void dpp3_power_on_hdr3dlut( + struct dpp *dpp_base, + bool power_on) +{ + struct dcn3_dpp *dpp = TO_DCN30_DPP(dpp_base); + + if (dpp_base->ctx->dc->debug.enable_mem_low_power.bits.cm) { + REG_UPDATE(CM_MEM_PWR_CTRL2, HDR3DLUT_MEM_PWR_FORCE, power_on ? 0 : 3); + if (power_on) + REG_WAIT(CM_MEM_PWR_STATUS2, HDR3DLUT_MEM_PWR_STATE, 0, 1, 5); + } +} + +static void dpp3_power_on_shaper( + struct dpp *dpp_base, + bool power_on) +{ + struct dcn3_dpp *dpp = TO_DCN30_DPP(dpp_base); + + if (dpp_base->ctx->dc->debug.enable_mem_low_power.bits.cm) { + REG_UPDATE(CM_MEM_PWR_CTRL2, SHAPER_MEM_PWR_FORCE, power_on ? 0 : 3); + if (power_on) + REG_WAIT(CM_MEM_PWR_STATUS2, SHAPER_MEM_PWR_STATE, 0, 1, 5); + } } static void dpp3_configure_blnd_lut( @@ -675,6 +706,8 @@ bool dpp3_program_blnd_lut( if (params == NULL) { REG_SET(CM_BLNDGAM_CONTROL, 0, CM_BLNDGAM_MODE, 0); + if (dpp_base->ctx->dc->debug.enable_mem_low_power.bits.cm) + dpp3_power_on_blnd_lut(dpp_base, false); return false; } @@ -1088,8 +1121,14 @@ bool dpp3_program_shaper( if (params == NULL) { REG_SET(CM_SHAPER_CONTROL, 0, CM_SHAPER_LUT_MODE, 0); + if (dpp_base->ctx->dc->debug.enable_mem_low_power.bits.cm) + dpp3_power_on_shaper(dpp_base, false); return false; } + + if (dpp_base->ctx->dc->debug.enable_mem_low_power.bits.cm) + dpp3_power_on_shaper(dpp_base, true); + current_mode = dpp3_get_shaper_current(dpp_base); if (current_mode == LUT_BYPASS || current_mode == LUT_RAM_A) @@ -1278,8 +1317,14 @@ bool dpp3_program_3dlut( if (params == NULL) { dpp3_set_3dlut_mode(dpp_base, LUT_BYPASS, false, false); + if (dpp_base->ctx->dc->debug.enable_mem_low_power.bits.cm) + dpp3_power_on_hdr3dlut(dpp_base, false); return false; } + + if (dpp_base->ctx->dc->debug.enable_mem_low_power.bits.cm) + dpp3_power_on_hdr3dlut(dpp_base, true); + mode = get3dlut_config(dpp_base, &is_17x17x17, &is_12bits_color_channel); if (mode == LUT_BYPASS || mode == LUT_RAM_B) diff --git a/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_dpp.h b/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_dpp.h index 81bf2ecc2831..3fa86cd090a0 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_dpp.h +++ b/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_dpp.h @@ -161,6 +161,10 @@ TF_REG_LIST_DCN20_COMMON(id), \ SRI(CM_BLNDGAM_CONTROL, CM, id), \ SRI(CM_SHAPER_LUT_DATA, CM, id),\ + SRI(CM_MEM_PWR_CTRL2, CM, id), \ + SRI(CM_MEM_PWR_STATUS2, CM, id), \ + SRI(DSCL_MEM_PWR_STATUS, DSCL, id), \ + SRI(DSCL_MEM_PWR_CTRL, DSCL, id), \ SRI(CM_BLNDGAM_RAMA_START_SLOPE_CNTL_B, CM, id),\ SRI(CM_BLNDGAM_RAMA_START_SLOPE_CNTL_G, CM, id),\ SRI(CM_BLNDGAM_RAMA_START_SLOPE_CNTL_R, CM, id),\ @@ -340,9 +344,15 @@ TF_SF(CNVC_CUR0_CURSOR0_CONTROL, CUR0_PIXEL_ALPHA_MOD_EN, mask_sh), \ TF_SF(CNVC_CUR0_CURSOR0_CONTROL, CUR0_ROM_EN, mask_sh),\ TF_SF(DSCL0_OBUF_MEM_PWR_CTRL, OBUF_MEM_PWR_FORCE, mask_sh),\ - TF_SF(DSCL0_DSCL_MEM_PWR_CTRL, LUT_MEM_PWR_FORCE, mask_sh) + TF_SF(DSCL0_DSCL_MEM_PWR_CTRL, LUT_MEM_PWR_FORCE, mask_sh),\ + TF_SF(DSCL0_DSCL_MEM_PWR_STATUS, LUT_MEM_PWR_STATE, mask_sh) #define DPP_REG_LIST_SH_MASK_DCN30_UPDATED(mask_sh)\ + TF_SF(CM0_CM_MEM_PWR_STATUS, BLNDGAM_MEM_PWR_STATE, mask_sh), \ + TF_SF(CM0_CM_MEM_PWR_CTRL2, HDR3DLUT_MEM_PWR_FORCE, mask_sh),\ + TF_SF(CM0_CM_MEM_PWR_CTRL2, SHAPER_MEM_PWR_FORCE, mask_sh),\ + TF_SF(CM0_CM_MEM_PWR_STATUS2, HDR3DLUT_MEM_PWR_STATE, mask_sh),\ + TF_SF(CM0_CM_MEM_PWR_STATUS2, SHAPER_MEM_PWR_STATE, mask_sh),\ TF_SF(CM0_CM_BLNDGAM_CONTROL, CM_BLNDGAM_MODE, mask_sh), \ TF_SF(CM0_CM_BLNDGAM_CONTROL, CM_BLNDGAM_MODE_CURRENT, mask_sh), \ TF_SF(CM0_CM_BLNDGAM_CONTROL, CM_BLNDGAM_SELECT_CURRENT, mask_sh), \ @@ -386,6 +396,8 @@ type CM_BIAS_CR_R;\ type GAMCOR_MEM_PWR_DIS; \ type GAMCOR_MEM_PWR_FORCE; \ + type HDR3DLUT_MEM_PWR_FORCE; \ + type SHAPER_MEM_PWR_FORCE; \ type PRE_DEGAM_MODE;\ type PRE_DEGAM_SELECT;\ type CNVC_ALPHA_PLANE_ENABLE; \ @@ -446,7 +458,10 @@ type CM_BLNDGAM_MODE_CURRENT; \ type CM_BLNDGAM_SELECT_CURRENT; \ type CM_BLNDGAM_SELECT; \ - type GAMCOR_MEM_PWR_STATE + type GAMCOR_MEM_PWR_STATE; \ + type BLNDGAM_MEM_PWR_STATE; \ + type HDR3DLUT_MEM_PWR_STATE; \ + type SHAPER_MEM_PWR_STATE struct dcn3_dpp_shift { DPP_REG_FIELD_LIST_DCN3(uint8_t); @@ -459,6 +474,8 @@ struct dcn3_dpp_mask { #define DPP_DCN3_REG_VARIABLE_LIST_COMMON \ DPP_DCN2_REG_VARIABLE_LIST; \ uint32_t CM_MEM_PWR_STATUS;\ + uint32_t CM_MEM_PWR_STATUS2;\ + uint32_t CM_MEM_PWR_CTRL2;\ uint32_t CM_DEALPHA;\ uint32_t CM_BIAS_CR_R;\ uint32_t CM_BIAS_Y_G_CB_B;\ diff --git a/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_dpp_cm.c b/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_dpp_cm.c index 9ab63c72f21c..9da66e491116 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_dpp_cm.c +++ b/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_dpp_cm.c @@ -136,9 +136,13 @@ static void dpp3_power_on_gamcor_lut( uint32_t power_status; struct dcn3_dpp *dpp = TO_DCN30_DPP(dpp_base); - - REG_SET(CM_MEM_PWR_CTRL, 0, - GAMCOR_MEM_PWR_DIS, power_on == true ? 0:1); + if (dpp_base->ctx->dc->debug.enable_mem_low_power.bits.cm) { + REG_UPDATE(CM_MEM_PWR_CTRL, GAMCOR_MEM_PWR_FORCE, power_on ? 0 : 3); + if (power_on) + REG_WAIT(CM_MEM_PWR_STATUS, GAMCOR_MEM_PWR_STATE, 0, 1, 5); + } else + REG_SET(CM_MEM_PWR_CTRL, 0, + GAMCOR_MEM_PWR_DIS, power_on == true ? 0:1); REG_GET(CM_MEM_PWR_STATUS, GAMCOR_MEM_PWR_STATE, &power_status); if (power_status != 0) @@ -229,6 +233,8 @@ bool dpp3_program_gamcor_lut( if (params == NULL) { //bypass if we have no pwl data REG_SET(CM_GAMCOR_CONTROL, 0, CM_GAMCOR_MODE, 0); + if (dpp_base->ctx->dc->debug.enable_mem_low_power.bits.cm) + dpp3_power_on_gamcor_lut(dpp_base, false); return false; } dpp3_power_on_gamcor_lut(dpp_base, true); diff --git a/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_hwseq.c b/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_hwseq.c index e76d6ab8d93a..283995ab9eeb 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_hwseq.c +++ b/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_hwseq.c @@ -462,6 +462,13 @@ void dcn30_init_hw(struct dc *dc) hws->funcs.disable_vga(dc->hwseq); } + if (dc->debug.enable_mem_low_power.bits.dmcu) { + // Force ERAM to shutdown if DMCU is not enabled + if (dc->debug.disable_dmcu || dc->config.disable_dmcu) { + REG_UPDATE(DMU_MEM_PWR_CNTL, DMCU_ERAM_MEM_PWR_FORCE, 3); + } + } + // Set default OPTC memory power states if (dc->debug.enable_mem_low_power.bits.optc) { // Shutdown when unassigned and light sleep in VBLANK @@ -825,5 +832,5 @@ void dcn30_set_disp_pattern_generator(const struct dc *dc, int width, int height, int offset) { pipe_ctx->stream_res.opp->funcs->opp_set_disp_pattern_generator(pipe_ctx->stream_res.opp, test_pattern, - color_space, color_depth, solid_color, width, height, 0); + color_space, color_depth, solid_color, width, height, offset); } diff --git a/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_resource.c b/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_resource.c index 01ac8b2921c6..5e126fdf6ec1 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_resource.c @@ -933,7 +933,7 @@ static struct dce_aux *dcn30_aux_engine_create( return &aux_engine->base; } -#define i2c_inst_regs(id) { I2C_HW_ENGINE_COMMON_REG_LIST(id) } +#define i2c_inst_regs(id) { I2C_HW_ENGINE_COMMON_REG_LIST_DCN30(id) } static const struct dce_i2c_registers i2c_hw_regs[] = { i2c_inst_regs(1), @@ -945,11 +945,11 @@ static const struct dce_i2c_registers i2c_hw_regs[] = { }; static const struct dce_i2c_shift i2c_shifts = { - I2C_COMMON_MASK_SH_LIST_DCN2(__SHIFT) + I2C_COMMON_MASK_SH_LIST_DCN30(__SHIFT) }; static const struct dce_i2c_mask i2c_masks = { - I2C_COMMON_MASK_SH_LIST_DCN2(_MASK) + I2C_COMMON_MASK_SH_LIST_DCN30(_MASK) }; static struct dce_i2c_hw *dcn30_i2c_hw_create( @@ -1451,12 +1451,13 @@ static struct clock_source *dcn30_clock_source_create( int dcn30_populate_dml_pipes_from_context( struct dc *dc, struct dc_state *context, - display_e2e_pipe_params_st *pipes) + display_e2e_pipe_params_st *pipes, + bool fast_validate) { int i, pipe_cnt; struct resource_context *res_ctx = &context->res_ctx; - dcn20_populate_dml_pipes_from_context(dc, context, pipes); + dcn20_populate_dml_pipes_from_context(dc, context, pipes, fast_validate); for (i = 0, pipe_cnt = 0; i < dc->res_pool->pipe_count; i++) { if (!res_ctx->pipe_ctx[i].stream) @@ -1469,20 +1470,8 @@ int dcn30_populate_dml_pipes_from_context( return pipe_cnt; } -/* - * This must be noinline to ensure anything that deals with FP registers - * is contained within this call; previously our compiling with hard-float - * would result in fp instructions being emitted outside of the boundaries - * of the DC_FP_START/END macros, which makes sense as the compiler has no - * idea about what is wrapped and what is not - * - * This is largely just a workaround to avoid breakage introduced with 5.6, - * ideally all fp-using code should be moved into its own file, only that - * should be compiled with hard-float, and all code exported from there - * should be strictly wrapped with DC_FP_START/END - */ -static noinline void dcn30_populate_dml_writeback_from_context_fp( - struct dc *dc, struct resource_context *res_ctx, display_e2e_pipe_params_st *pipes) +void dcn30_populate_dml_writeback_from_context( + struct dc *dc, struct resource_context *res_ctx, display_e2e_pipe_params_st *pipes) { int pipe_cnt, i, j; double max_calc_writeback_dispclk; @@ -1570,14 +1559,6 @@ static noinline void dcn30_populate_dml_writeback_from_context_fp( } -void dcn30_populate_dml_writeback_from_context( - struct dc *dc, struct resource_context *res_ctx, display_e2e_pipe_params_st *pipes) -{ - DC_FP_START(); - dcn30_populate_dml_writeback_from_context_fp(dc, res_ctx, pipes); - DC_FP_END(); -} - unsigned int dcn30_calc_max_scaled_time( unsigned int time_per_pixel, enum mmhubbub_wbif_mode mode, @@ -1976,7 +1957,7 @@ static struct pipe_ctx *dcn30_find_split_pipe( return pipe; } -static bool dcn30_internal_validate_bw( +static noinline bool dcn30_internal_validate_bw( struct dc *dc, struct dc_state *context, display_e2e_pipe_params_st *pipes, @@ -1996,8 +1977,9 @@ static bool dcn30_internal_validate_bw( if (!pipes) return false; - pipe_cnt = dc->res_pool->funcs->populate_dml_pipes(dc, context, pipes); + pipe_cnt = dc->res_pool->funcs->populate_dml_pipes(dc, context, pipes, fast_validate); + DC_FP_START(); if (!pipe_cnt) { out = true; goto validate_out; @@ -2210,7 +2192,7 @@ static bool dcn30_internal_validate_bw( } if (repopulate_pipes) - pipe_cnt = dc->res_pool->funcs->populate_dml_pipes(dc, context, pipes); + pipe_cnt = dc->res_pool->funcs->populate_dml_pipes(dc, context, pipes, fast_validate); *vlevel_out = vlevel; *pipe_cnt_out = pipe_cnt; @@ -2221,6 +2203,7 @@ validate_fail: out = false; validate_out: + DC_FP_END(); return out; } @@ -2403,7 +2386,7 @@ void dcn30_calculate_wm_and_dlg( DC_FP_END(); } -static noinline bool dcn30_validate_bandwidth_fp(struct dc *dc, +bool dcn30_validate_bandwidth(struct dc *dc, struct dc_state *context, bool fast_validate) { @@ -2454,19 +2437,6 @@ validate_out: return out; } -bool dcn30_validate_bandwidth(struct dc *dc, - struct dc_state *context, - bool fast_validate) -{ - bool out; - - DC_FP_START(); - out = dcn30_validate_bandwidth_fp(dc, context, fast_validate); - DC_FP_END(); - - return out; -} - static noinline void get_optimal_dcfclk_fclk_for_uclk(unsigned int uclk_mts, unsigned int *optimal_dcfclk, unsigned int *optimal_fclk) @@ -2680,6 +2650,7 @@ static bool dcn30_resource_construct( dc->caps.color.dpp.dgam_rom_caps.hlg = 1; 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.hw_3d_lut = 1; dc->caps.color.dpp.ogam_ram = 1; diff --git a/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_resource.h b/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_resource.h index d163812af858..8ce7f6d39a20 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_resource.h +++ b/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_resource.h @@ -65,7 +65,8 @@ void dcn30_populate_dml_writeback_from_context( int dcn30_populate_dml_pipes_from_context( struct dc *dc, struct dc_state *context, - display_e2e_pipe_params_st *pipes); + display_e2e_pipe_params_st *pipes, + bool fast_validate); bool dcn30_acquire_post_bldn_3dlut( struct resource_context *res_ctx, diff --git a/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_vpg.c b/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_vpg.c index 9c0020c8a730..8cfd181b4d5f 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_vpg.c +++ b/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_vpg.c @@ -103,69 +103,69 @@ static void vpg3_update_generic_info_packet( } } - /* atomically update double-buffered GENERIC0 registers in frame mode + /* atomically update double-buffered GENERIC0 registers in immediate mode * (update at next block_update when block_update_lock == 0). */ switch (packet_index) { case 0: - REG_UPDATE(VPG_GSP_FRAME_UPDATE_CTRL, - VPG_GENERIC0_FRAME_UPDATE, 1); + REG_UPDATE(VPG_GSP_IMMEDIATE_UPDATE_CTRL, + VPG_GENERIC0_IMMEDIATE_UPDATE, 1); break; case 1: - REG_UPDATE(VPG_GSP_FRAME_UPDATE_CTRL, - VPG_GENERIC1_FRAME_UPDATE, 1); + REG_UPDATE(VPG_GSP_IMMEDIATE_UPDATE_CTRL, + VPG_GENERIC1_IMMEDIATE_UPDATE, 1); break; case 2: - REG_UPDATE(VPG_GSP_FRAME_UPDATE_CTRL, - VPG_GENERIC2_FRAME_UPDATE, 1); + REG_UPDATE(VPG_GSP_IMMEDIATE_UPDATE_CTRL, + VPG_GENERIC2_IMMEDIATE_UPDATE, 1); break; case 3: - REG_UPDATE(VPG_GSP_FRAME_UPDATE_CTRL, - VPG_GENERIC3_FRAME_UPDATE, 1); + REG_UPDATE(VPG_GSP_IMMEDIATE_UPDATE_CTRL, + VPG_GENERIC3_IMMEDIATE_UPDATE, 1); break; case 4: - REG_UPDATE(VPG_GSP_FRAME_UPDATE_CTRL, - VPG_GENERIC4_FRAME_UPDATE, 1); + REG_UPDATE(VPG_GSP_IMMEDIATE_UPDATE_CTRL, + VPG_GENERIC4_IMMEDIATE_UPDATE, 1); break; case 5: - REG_UPDATE(VPG_GSP_FRAME_UPDATE_CTRL, - VPG_GENERIC5_FRAME_UPDATE, 1); + REG_UPDATE(VPG_GSP_IMMEDIATE_UPDATE_CTRL, + VPG_GENERIC5_IMMEDIATE_UPDATE, 1); break; case 6: - REG_UPDATE(VPG_GSP_FRAME_UPDATE_CTRL, - VPG_GENERIC6_FRAME_UPDATE, 1); + REG_UPDATE(VPG_GSP_IMMEDIATE_UPDATE_CTRL, + VPG_GENERIC6_IMMEDIATE_UPDATE, 1); break; case 7: - REG_UPDATE(VPG_GSP_FRAME_UPDATE_CTRL, - VPG_GENERIC7_FRAME_UPDATE, 1); + REG_UPDATE(VPG_GSP_IMMEDIATE_UPDATE_CTRL, + VPG_GENERIC7_IMMEDIATE_UPDATE, 1); break; case 8: - REG_UPDATE(VPG_GSP_FRAME_UPDATE_CTRL, - VPG_GENERIC8_FRAME_UPDATE, 1); + REG_UPDATE(VPG_GSP_IMMEDIATE_UPDATE_CTRL, + VPG_GENERIC8_IMMEDIATE_UPDATE, 1); break; case 9: - REG_UPDATE(VPG_GSP_FRAME_UPDATE_CTRL, - VPG_GENERIC9_FRAME_UPDATE, 1); + REG_UPDATE(VPG_GSP_IMMEDIATE_UPDATE_CTRL, + VPG_GENERIC9_IMMEDIATE_UPDATE, 1); break; case 10: - REG_UPDATE(VPG_GSP_FRAME_UPDATE_CTRL, - VPG_GENERIC10_FRAME_UPDATE, 1); + REG_UPDATE(VPG_GSP_IMMEDIATE_UPDATE_CTRL, + VPG_GENERIC10_IMMEDIATE_UPDATE, 1); break; case 11: - REG_UPDATE(VPG_GSP_FRAME_UPDATE_CTRL, - VPG_GENERIC11_FRAME_UPDATE, 1); + REG_UPDATE(VPG_GSP_IMMEDIATE_UPDATE_CTRL, + VPG_GENERIC11_IMMEDIATE_UPDATE, 1); break; case 12: - REG_UPDATE(VPG_GSP_FRAME_UPDATE_CTRL, - VPG_GENERIC12_FRAME_UPDATE, 1); + REG_UPDATE(VPG_GSP_IMMEDIATE_UPDATE_CTRL, + VPG_GENERIC12_IMMEDIATE_UPDATE, 1); break; case 13: - REG_UPDATE(VPG_GSP_FRAME_UPDATE_CTRL, - VPG_GENERIC13_FRAME_UPDATE, 1); + REG_UPDATE(VPG_GSP_IMMEDIATE_UPDATE_CTRL, + VPG_GENERIC13_IMMEDIATE_UPDATE, 1); break; case 14: - REG_UPDATE(VPG_GSP_FRAME_UPDATE_CTRL, - VPG_GENERIC14_FRAME_UPDATE, 1); + REG_UPDATE(VPG_GSP_IMMEDIATE_UPDATE_CTRL, + VPG_GENERIC14_IMMEDIATE_UPDATE, 1); break; default: break; diff --git a/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_vpg.h b/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_vpg.h index 0284092630f1..6161e9e66355 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_vpg.h +++ b/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_vpg.h @@ -34,13 +34,15 @@ SRI(VPG_GENERIC_STATUS, VPG, id), \ SRI(VPG_GENERIC_PACKET_ACCESS_CTRL, VPG, id), \ SRI(VPG_GENERIC_PACKET_DATA, VPG, id), \ - SRI(VPG_GSP_FRAME_UPDATE_CTRL, VPG, id) + SRI(VPG_GSP_FRAME_UPDATE_CTRL, VPG, id), \ + SRI(VPG_GSP_IMMEDIATE_UPDATE_CTRL, VPG, id) struct dcn30_vpg_registers { uint32_t VPG_GENERIC_STATUS; uint32_t VPG_GENERIC_PACKET_ACCESS_CTRL; uint32_t VPG_GENERIC_PACKET_DATA; uint32_t VPG_GSP_FRAME_UPDATE_CTRL; + uint32_t VPG_GSP_IMMEDIATE_UPDATE_CTRL; }; #define DCN3_VPG_MASK_SH_LIST(mask_sh)\ @@ -65,7 +67,22 @@ struct dcn30_vpg_registers { SE_SF(VPG0_VPG_GSP_FRAME_UPDATE_CTRL, VPG_GENERIC11_FRAME_UPDATE, mask_sh),\ SE_SF(VPG0_VPG_GSP_FRAME_UPDATE_CTRL, VPG_GENERIC12_FRAME_UPDATE, mask_sh),\ SE_SF(VPG0_VPG_GSP_FRAME_UPDATE_CTRL, VPG_GENERIC13_FRAME_UPDATE, mask_sh),\ - SE_SF(VPG0_VPG_GSP_FRAME_UPDATE_CTRL, VPG_GENERIC14_FRAME_UPDATE, mask_sh) + SE_SF(VPG0_VPG_GSP_FRAME_UPDATE_CTRL, VPG_GENERIC14_FRAME_UPDATE, mask_sh),\ + SE_SF(VPG0_VPG_GSP_IMMEDIATE_UPDATE_CTRL, VPG_GENERIC0_IMMEDIATE_UPDATE, mask_sh),\ + SE_SF(VPG0_VPG_GSP_IMMEDIATE_UPDATE_CTRL, VPG_GENERIC1_IMMEDIATE_UPDATE, mask_sh),\ + SE_SF(VPG0_VPG_GSP_IMMEDIATE_UPDATE_CTRL, VPG_GENERIC2_IMMEDIATE_UPDATE, mask_sh),\ + SE_SF(VPG0_VPG_GSP_IMMEDIATE_UPDATE_CTRL, VPG_GENERIC3_IMMEDIATE_UPDATE, mask_sh),\ + SE_SF(VPG0_VPG_GSP_IMMEDIATE_UPDATE_CTRL, VPG_GENERIC4_IMMEDIATE_UPDATE, mask_sh),\ + SE_SF(VPG0_VPG_GSP_IMMEDIATE_UPDATE_CTRL, VPG_GENERIC5_IMMEDIATE_UPDATE, mask_sh),\ + SE_SF(VPG0_VPG_GSP_IMMEDIATE_UPDATE_CTRL, VPG_GENERIC6_IMMEDIATE_UPDATE, mask_sh),\ + SE_SF(VPG0_VPG_GSP_IMMEDIATE_UPDATE_CTRL, VPG_GENERIC7_IMMEDIATE_UPDATE, mask_sh),\ + SE_SF(VPG0_VPG_GSP_IMMEDIATE_UPDATE_CTRL, VPG_GENERIC8_IMMEDIATE_UPDATE, mask_sh),\ + SE_SF(VPG0_VPG_GSP_IMMEDIATE_UPDATE_CTRL, VPG_GENERIC9_IMMEDIATE_UPDATE, mask_sh),\ + SE_SF(VPG0_VPG_GSP_IMMEDIATE_UPDATE_CTRL, VPG_GENERIC10_IMMEDIATE_UPDATE, mask_sh),\ + SE_SF(VPG0_VPG_GSP_IMMEDIATE_UPDATE_CTRL, VPG_GENERIC11_IMMEDIATE_UPDATE, mask_sh),\ + SE_SF(VPG0_VPG_GSP_IMMEDIATE_UPDATE_CTRL, VPG_GENERIC12_IMMEDIATE_UPDATE, mask_sh),\ + SE_SF(VPG0_VPG_GSP_IMMEDIATE_UPDATE_CTRL, VPG_GENERIC13_IMMEDIATE_UPDATE, mask_sh),\ + SE_SF(VPG0_VPG_GSP_IMMEDIATE_UPDATE_CTRL, VPG_GENERIC14_IMMEDIATE_UPDATE, mask_sh) #define VPG_DCN3_REG_FIELD_LIST(type) \ type VPG_GENERIC_CONFLICT_OCCURED;\ @@ -89,7 +106,22 @@ struct dcn30_vpg_registers { type VPG_GENERIC11_FRAME_UPDATE;\ type VPG_GENERIC12_FRAME_UPDATE;\ type VPG_GENERIC13_FRAME_UPDATE;\ - type VPG_GENERIC14_FRAME_UPDATE + type VPG_GENERIC14_FRAME_UPDATE;\ + type VPG_GENERIC0_IMMEDIATE_UPDATE;\ + type VPG_GENERIC1_IMMEDIATE_UPDATE;\ + type VPG_GENERIC2_IMMEDIATE_UPDATE;\ + type VPG_GENERIC3_IMMEDIATE_UPDATE;\ + type VPG_GENERIC4_IMMEDIATE_UPDATE;\ + type VPG_GENERIC5_IMMEDIATE_UPDATE;\ + type VPG_GENERIC6_IMMEDIATE_UPDATE;\ + type VPG_GENERIC7_IMMEDIATE_UPDATE;\ + type VPG_GENERIC8_IMMEDIATE_UPDATE;\ + type VPG_GENERIC9_IMMEDIATE_UPDATE;\ + type VPG_GENERIC10_IMMEDIATE_UPDATE;\ + type VPG_GENERIC11_IMMEDIATE_UPDATE;\ + type VPG_GENERIC12_IMMEDIATE_UPDATE;\ + type VPG_GENERIC13_IMMEDIATE_UPDATE;\ + type VPG_GENERIC14_IMMEDIATE_UPDATE struct dcn30_vpg_shift { diff --git a/drivers/gpu/drm/amd/display/dc/dcn301/dcn301_resource.c b/drivers/gpu/drm/amd/display/dc/dcn301/dcn301_resource.c index 5a47b4106b7b..4825c5c1c6ed 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn301/dcn301_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dcn301/dcn301_resource.c @@ -73,6 +73,9 @@ #include "nbio/nbio_7_2_0_offset.h" +#include "dcn/dpcs_3_0_0_offset.h" +#include "dcn/dpcs_3_0_0_sh_mask.h" + #include "reg_helper.h" #include "dce/dmub_abm.h" #include "dce/dce_aux.h" @@ -164,29 +167,63 @@ struct _vcs_dpi_ip_params_st dcn3_01_ip = { struct _vcs_dpi_soc_bounding_box_st dcn3_01_soc = { .clock_limits = { - /*TODO: fill out defaults once wm plociy is settled*/ { .state = 0, - .dcfclk_mhz = 810.0, - .fabricclk_mhz = 1200.0, + .dram_speed_mts = 2400.0, + .fabricclk_mhz = 600, + .socclk_mhz = 278.0, + .dcfclk_mhz = 400.0, + .dscclk_mhz = 206.0, + .dppclk_mhz = 1015.0, + .dispclk_mhz = 1015.0, + .phyclk_mhz = 600.0, + }, + { + .state = 1, + .dram_speed_mts = 2400.0, + .fabricclk_mhz = 688, + .socclk_mhz = 278.0, + .dcfclk_mhz = 400.0, + .dscclk_mhz = 206.0, + .dppclk_mhz = 1015.0, .dispclk_mhz = 1015.0, + .phyclk_mhz = 600.0, + }, + { + .state = 2, + .dram_speed_mts = 4267.0, + .fabricclk_mhz = 1067, + .socclk_mhz = 278.0, + .dcfclk_mhz = 608.0, + .dscclk_mhz = 296.0, .dppclk_mhz = 1015.0, + .dispclk_mhz = 1015.0, .phyclk_mhz = 810.0, - .socclk_mhz = 1000.0, + }, + + { + .state = 3, + .dram_speed_mts = 4267.0, + .fabricclk_mhz = 1067, + .socclk_mhz = 715.0, + .dcfclk_mhz = 676.0, .dscclk_mhz = 338.0, - .dram_speed_mts = 4266.0, + .dppclk_mhz = 1015.0, + .dispclk_mhz = 1015.0, + .phyclk_mhz = 810.0, }, + { - .state = 1, + .state = 4, + .dram_speed_mts = 4267.0, + .fabricclk_mhz = 1067, + .socclk_mhz = 953.0, .dcfclk_mhz = 810.0, - .fabricclk_mhz = 1200.0, - .dispclk_mhz = 1015.0, + .dscclk_mhz = 338.0, .dppclk_mhz = 1015.0, + .dispclk_mhz = 1015.0, .phyclk_mhz = 810.0, - .socclk_mhz = 1000.0, - .dscclk_mhz = 338.0, - .dram_speed_mts = 4266.0, - } + }, }, .sr_exit_time_us = 9.0, @@ -226,7 +263,7 @@ struct _vcs_dpi_soc_bounding_box_st dcn3_01_soc = { .xfc_bus_transport_time_us = 20, // ? .xfc_xbuf_latency_tolerance_us = 4, // ? .use_urgent_burst_bw = 1, // ? - .num_states = 2, + .num_states = 5, .do_urgent_latency_adjustment = false, .urgent_latency_adjustment_fabric_clock_component_us = 0, .urgent_latency_adjustment_fabric_clock_reference_mhz = 0, @@ -483,10 +520,13 @@ static const struct dcn10_link_enc_hpd_registers link_enc_hpd_regs[] = { hpd_regs(3), }; + #define link_regs(id, phyid)\ [id] = {\ LE_DCN301_REG_LIST(id), \ UNIPHY_DCN2_REG_LIST(phyid), \ + DPCS_DCN2_REG_LIST(id), \ + SRI(DP_DPHY_INTERNAL_CTRL, DP, id) \ } static const struct dce110_aux_registers_shift aux_shift = { @@ -505,11 +545,13 @@ static const struct dcn10_link_enc_registers link_enc_regs[] = { }; static const struct dcn10_link_enc_shift le_shift = { - LINK_ENCODER_MASK_SH_LIST_DCN301(__SHIFT) + LINK_ENCODER_MASK_SH_LIST_DCN301(__SHIFT),\ + DPCS_DCN2_MASK_SH_LIST(__SHIFT) }; static const struct dcn10_link_enc_mask le_mask = { - LINK_ENCODER_MASK_SH_LIST_DCN301(_MASK) + LINK_ENCODER_MASK_SH_LIST_DCN301(_MASK),\ + DPCS_DCN2_MASK_SH_LIST(_MASK) }; #define panel_cntl_regs(id)\ @@ -815,12 +857,11 @@ static const struct dc_debug_options debug_defaults_drv = { .force_abm_enable = false, .timing_trace = false, .clock_trace = true, - .disable_dpp_power_gate = true, - .disable_hubp_power_gate = true, + .disable_dpp_power_gate = false, + .disable_hubp_power_gate = false, .disable_clock_gate = true, .disable_pplib_clock_request = true, .disable_pplib_wm_range = true, - .disable_stutter = true, .pipe_split_policy = MPC_SPLIT_AVOID_MULT_DISP, .force_single_disp_pipe_split = false, .disable_dcc = DCC_ENABLE, @@ -839,8 +880,8 @@ static const struct dc_debug_options debug_defaults_diags = { .force_abm_enable = false, .timing_trace = true, .clock_trace = true, - .disable_dpp_power_gate = true, - .disable_hubp_power_gate = true, + .disable_dpp_power_gate = false, + .disable_hubp_power_gate = false, .disable_clock_gate = true, .disable_pplib_clock_request = true, .disable_pplib_wm_range = true, @@ -1189,8 +1230,6 @@ static const struct resource_create_funcs res_create_maximus_funcs = { .create_hwseq = dcn301_hwseq_create, }; -static void dcn301_pp_smu_destroy(struct pp_smu_funcs **pp_smu); - static void dcn301_destruct(struct dcn301_resource_pool *pool) { unsigned int i; @@ -1311,9 +1350,6 @@ static void dcn301_destruct(struct dcn301_resource_pool *pool) if (pool->base.dccg != NULL) dcn_dccg_destroy(&pool->base.dccg); - - if (pool->base.pp_smu != NULL) - dcn301_pp_smu_destroy(&pool->base.pp_smu); } struct hubp *dcn301_hubp_create( @@ -1566,41 +1602,25 @@ static bool init_soc_bounding_box(struct dc *dc, } } - if (pool->base.pp_smu) { - struct pp_smu_nv_clock_table max_clocks = {0}; - unsigned int uclk_states[8] = {0}; - unsigned int num_states = 0; - enum pp_smu_status status; - bool clock_limits_available = false; - bool uclk_states_available = false; + loaded_ip->max_num_otg = pool->base.res_cap->num_timing_generator; + loaded_ip->max_num_dpp = pool->base.pipe_count; + dcn20_patch_bounding_box(dc, loaded_bb); - if (pool->base.pp_smu->nv_funcs.get_uclk_dpm_states) { - status = (pool->base.pp_smu->nv_funcs.get_uclk_dpm_states) - (&pool->base.pp_smu->nv_funcs.pp_smu, uclk_states, &num_states); + if (!bb && dc->ctx->dc_bios->funcs->get_soc_bb_info) { + struct bp_soc_bb_info bb_info = {0}; - uclk_states_available = (status == PP_SMU_RESULT_OK); - } + if (dc->ctx->dc_bios->funcs->get_soc_bb_info(dc->ctx->dc_bios, &bb_info) == BP_RESULT_OK) { + if (bb_info.dram_clock_change_latency_100ns > 0) + dcn3_01_soc.dram_clock_change_latency_us = bb_info.dram_clock_change_latency_100ns * 10; - if (pool->base.pp_smu->nv_funcs.get_maximum_sustainable_clocks) { - status = (*pool->base.pp_smu->nv_funcs.get_maximum_sustainable_clocks) - (&pool->base.pp_smu->nv_funcs.pp_smu, &max_clocks); - /* SMU cannot set DCF clock to anything equal to or higher than SOC clock - */ - if (max_clocks.dcfClockInKhz >= max_clocks.socClockInKhz) - max_clocks.dcfClockInKhz = max_clocks.socClockInKhz - 1000; - clock_limits_available = (status == PP_SMU_RESULT_OK); - } + if (bb_info.dram_sr_enter_exit_latency_100ns > 0) + dcn3_01_soc.sr_enter_plus_exit_time_us = bb_info.dram_sr_enter_exit_latency_100ns * 10; - if (clock_limits_available && uclk_states_available && num_states) - dcn20_update_bounding_box(dc, loaded_bb, &max_clocks, uclk_states, num_states); - else if (clock_limits_available) - dcn20_cap_soc_clocks(loaded_bb, max_clocks); + if (bb_info.dram_sr_exit_latency_100ns > 0) + dcn3_01_soc.sr_exit_time_us = bb_info.dram_sr_exit_latency_100ns * 10; + } } - loaded_ip->max_num_otg = pool->base.res_cap->num_timing_generator; - loaded_ip->max_num_dpp = pool->base.pipe_count; - dcn20_patch_bounding_box(dc, loaded_bb); - return true; } @@ -1648,36 +1668,58 @@ static void set_wm_ranges( pp_smu->nv_funcs.set_wm_ranges(&pp_smu->nv_funcs.pp_smu, &ranges); } -static struct pp_smu_funcs *dcn301_pp_smu_create(struct dc_context *ctx) +static void dcn301_update_bw_bounding_box(struct dc *dc, struct clk_bw_params *bw_params) { - struct pp_smu_funcs *pp_smu = kzalloc(sizeof(*pp_smu), GFP_KERNEL); - - if (!pp_smu) - return pp_smu; - - if (!IS_FPGA_MAXIMUS_DC(ctx->dce_environment) && !IS_DIAG_DC(ctx->dce_environment)) { - dm_pp_get_funcs(ctx, pp_smu); - - /* TODO: update once we have n21 smu*/ - if (pp_smu->ctx.ver != PP_SMU_VER_NV) - pp_smu = memset(pp_smu, 0, sizeof(struct pp_smu_funcs)); - } - - return pp_smu; -} + struct dcn301_resource_pool *pool = TO_DCN301_RES_POOL(dc->res_pool); + struct clk_limit_table *clk_table = &bw_params->clk_table; + struct _vcs_dpi_voltage_scaling_st clock_limits[DC__VOLTAGE_STATES]; + unsigned int i, closest_clk_lvl; + int j; + + // Default clock levels are used for diags, which may lead to overclocking. + if (!IS_DIAG_DC(dc->ctx->dce_environment)) { + dcn3_01_ip.max_num_otg = pool->base.res_cap->num_timing_generator; + dcn3_01_ip.max_num_dpp = pool->base.pipe_count; + dcn3_01_soc.num_chans = bw_params->num_channels; + + ASSERT(clk_table->num_entries); + for (i = 0; i < clk_table->num_entries; i++) { + /* loop backwards*/ + for (closest_clk_lvl = 0, j = dcn3_01_soc.num_states - 1; j >= 0; j--) { + if ((unsigned int) dcn3_01_soc.clock_limits[j].dcfclk_mhz <= clk_table->entries[i].dcfclk_mhz) { + closest_clk_lvl = j; + break; + } + } -static void dcn301_pp_smu_destroy(struct pp_smu_funcs **pp_smu) -{ - if (pp_smu && *pp_smu) { - kfree(*pp_smu); - *pp_smu = NULL; + clock_limits[i].state = i; + clock_limits[i].dcfclk_mhz = clk_table->entries[i].dcfclk_mhz; + clock_limits[i].fabricclk_mhz = clk_table->entries[i].fclk_mhz; + clock_limits[i].socclk_mhz = clk_table->entries[i].socclk_mhz; + clock_limits[i].dram_speed_mts = clk_table->entries[i].memclk_mhz * 2; + + clock_limits[i].dispclk_mhz = dcn3_01_soc.clock_limits[closest_clk_lvl].dispclk_mhz; + clock_limits[i].dppclk_mhz = dcn3_01_soc.clock_limits[closest_clk_lvl].dppclk_mhz; + clock_limits[i].dram_bw_per_chan_gbps = dcn3_01_soc.clock_limits[closest_clk_lvl].dram_bw_per_chan_gbps; + clock_limits[i].dscclk_mhz = dcn3_01_soc.clock_limits[closest_clk_lvl].dscclk_mhz; + clock_limits[i].dtbclk_mhz = dcn3_01_soc.clock_limits[closest_clk_lvl].dtbclk_mhz; + clock_limits[i].phyclk_d18_mhz = dcn3_01_soc.clock_limits[closest_clk_lvl].phyclk_d18_mhz; + clock_limits[i].phyclk_mhz = dcn3_01_soc.clock_limits[closest_clk_lvl].phyclk_mhz; + } + for (i = 0; i < clk_table->num_entries; i++) + dcn3_01_soc.clock_limits[i] = clock_limits[i]; + if (clk_table->num_entries) { + dcn3_01_soc.num_states = clk_table->num_entries; + /* duplicate last level */ + dcn3_01_soc.clock_limits[dcn3_01_soc.num_states] = dcn3_01_soc.clock_limits[dcn3_01_soc.num_states - 1]; + dcn3_01_soc.clock_limits[dcn3_01_soc.num_states].state = dcn3_01_soc.num_states; + } } -} -static void dcn301_update_bw_bounding_box(struct dc *dc, struct clk_bw_params *bw_params) -{ dcn3_01_soc.dispclk_dppclk_vco_speed_mhz = dc->clk_mgr->dentist_vco_freq_khz / 1000.0; dc->dml.soc.dispclk_dppclk_vco_speed_mhz = dc->clk_mgr->dentist_vco_freq_khz / 1000.0; + + dml_init_instance(&dc->dml, &dcn3_01_soc, &dcn3_01_ip, DML_PROJECT_DCN30); } static struct resource_funcs dcn301_res_pool_funcs = { @@ -1725,7 +1767,9 @@ static bool dcn301_resource_construct( pool->base.mpcc_count = pool->base.res_cap->num_timing_generator; dc->caps.max_downscale_ratio = 600; dc->caps.i2c_speed_in_khz = 100; + dc->caps.i2c_speed_in_khz_hdcp = 5; /*1.4 w/a enabled by default*/ dc->caps.max_cursor_size = 256; + dc->caps.min_horizontal_blanking_period = 80; dc->caps.dmdata_alloc_size = 2048; dc->caps.max_slave_planes = 1; dc->caps.is_apu = true; @@ -1748,6 +1792,7 @@ static bool dcn301_resource_construct( dc->caps.color.dpp.dgam_rom_caps.hlg = 1; 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.hw_3d_lut = 1; dc->caps.color.dpp.ogam_ram = 1; @@ -1825,9 +1870,8 @@ static bool dcn301_resource_construct( goto create_fail; } - /* PP Lib and SMU interfaces */ - pool->base.pp_smu = dcn301_pp_smu_create(ctx); init_soc_bounding_box(dc, pool); + if (!dc->debug.disable_pplib_wm_range && pool->base.pp_smu->nv_funcs.set_wm_ranges) set_wm_ranges(pool->base.pp_smu, &dcn3_01_soc); diff --git a/drivers/gpu/drm/amd/display/dc/dcn302/dcn302_resource.c b/drivers/gpu/drm/amd/display/dc/dcn302/dcn302_resource.c index 2345f12ceab3..808c4dcdb3ac 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn302/dcn302_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dcn302/dcn302_resource.c @@ -60,8 +60,8 @@ #include "vm_helper.h" #include "dimgrey_cavefish_ip_offset.h" -#include "dcn/dcn_3_0_0_offset.h" -#include "dcn/dcn_3_0_0_sh_mask.h" +#include "dcn/dcn_3_0_2_offset.h" +#include "dcn/dcn_3_0_2_sh_mask.h" #include "dcn/dpcs_3_0_0_offset.h" #include "dcn/dpcs_3_0_0_sh_mask.h" #include "nbio/nbio_7_4_offset.h" @@ -967,6 +967,7 @@ static const struct encoder_feature_support link_enc_feature = { [id] = {\ LE_DCN3_REG_LIST(id), \ UNIPHY_DCN2_REG_LIST(phyid), \ + DPCS_DCN2_REG_LIST(id), \ SRI(DP_DPHY_INTERNAL_CTRL, DP, id) \ } @@ -1306,7 +1307,9 @@ static bool dcn302_resource_construct( pool->mpcc_count = pool->res_cap->num_timing_generator; dc->caps.max_downscale_ratio = 600; dc->caps.i2c_speed_in_khz = 100; + dc->caps.i2c_speed_in_khz_hdcp = 5; /*1.4 w/a applied by derfault*/ dc->caps.max_cursor_size = 256; + dc->caps.min_horizontal_blanking_period = 80; dc->caps.dmdata_alloc_size = 2048; dc->caps.max_slave_planes = 1; @@ -1327,6 +1330,7 @@ static bool dcn302_resource_construct( dc->caps.color.dpp.dgam_rom_caps.hlg = 1; 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.hw_3d_lut = 1; dc->caps.color.dpp.ogam_ram = 1; diff --git a/drivers/gpu/drm/amd/display/dc/dm_helpers.h b/drivers/gpu/drm/amd/display/dc/dm_helpers.h index b2cd8491c707..07e349b1067b 100644 --- a/drivers/gpu/drm/amd/display/dc/dm_helpers.h +++ b/drivers/gpu/drm/amd/display/dc/dm_helpers.h @@ -113,7 +113,7 @@ bool dm_helpers_dp_mst_start_top_mgr( void dm_helpers_dp_mst_stop_top_mgr( struct dc_context *ctx, - const struct dc_link *link); + struct dc_link *link); /** * OS specific aux read callback. */ diff --git a/drivers/gpu/drm/amd/display/dc/dml/dcn21/display_mode_vba_21.c b/drivers/gpu/drm/amd/display/dc/dml/dcn21/display_mode_vba_21.c index 367c82b5ab4c..86ff24dffc3e 100644 --- a/drivers/gpu/drm/amd/display/dc/dml/dcn21/display_mode_vba_21.c +++ b/drivers/gpu/drm/amd/display/dc/dml/dcn21/display_mode_vba_21.c @@ -5477,7 +5477,7 @@ static void CalculateWatermarksAndDRAMSpeedChangeSupport( } } - if (mode_lib->vba.MinActiveDRAMClockChangeMargin > 0) { + if (mode_lib->vba.MinActiveDRAMClockChangeMargin > 0 && PrefetchMode == 0) { *DRAMClockChangeSupport = dm_dram_clock_change_vactive; } else if (((mode_lib->vba.SynchronizedVBlank == true || mode_lib->vba.TotalNumberOfActiveOTG == 1 diff --git a/drivers/gpu/drm/amd/display/dc/dml/display_mode_structs.h b/drivers/gpu/drm/amd/display/dc/dml/display_mode_structs.h index 162464261205..dd0c3b1780d7 100644 --- a/drivers/gpu/drm/amd/display/dc/dml/display_mode_structs.h +++ b/drivers/gpu/drm/amd/display/dc/dml/display_mode_structs.h @@ -334,7 +334,6 @@ struct _vcs_dpi_display_pipe_dest_params_st { unsigned int vblank_end; unsigned int htotal; unsigned int vtotal; - unsigned int refresh_rate; unsigned int vfront_porch; unsigned int vactive; unsigned int hactive; @@ -345,7 +344,6 @@ struct _vcs_dpi_display_pipe_dest_params_st { unsigned char interlaced; double pixel_rate_mhz; unsigned char synchronized_vblank_all_planes; - unsigned char synchronize_timing_if_single_refresh_rate; unsigned char otg_inst; unsigned int odm_combine; unsigned char use_maximum_vstartup; diff --git a/drivers/gpu/drm/amd/display/dc/dml/display_mode_vba.c b/drivers/gpu/drm/amd/display/dc/dml/display_mode_vba.c index 62740d4e423d..c9fbb33f05a3 100644 --- a/drivers/gpu/drm/amd/display/dc/dml/display_mode_vba.c +++ b/drivers/gpu/drm/amd/display/dc/dml/display_mode_vba.c @@ -469,8 +469,7 @@ static void fetch_pipe_params(struct display_mode_lib *mode_lib) mode_lib->vba.DSCEnable[mode_lib->vba.NumberOfActivePlanes] = dout->dsc_enable; mode_lib->vba.NumberOfDSCSlices[mode_lib->vba.NumberOfActivePlanes] = dout->dsc_slices; - mode_lib->vba.DSCInputBitPerComponent[mode_lib->vba.NumberOfActivePlanes] = - dout->output_bpc == 0 ? 12 : dout->output_bpc; + mode_lib->vba.DSCInputBitPerComponent[mode_lib->vba.NumberOfActivePlanes] = dout->output_bpc; mode_lib->vba.WritebackEnable[mode_lib->vba.NumberOfActivePlanes] = dout->wb_enable; mode_lib->vba.ActiveWritebacksPerPlane[mode_lib->vba.NumberOfActivePlanes] = dout->num_active_wb; @@ -660,10 +659,8 @@ static void fetch_pipe_params(struct display_mode_lib *mode_lib) // TODO: ODMCombineEnabled => 2 * DPPPerPlane...actually maybe not since all pipes are specified // Do we want the dscclk to automatically be halved? Guess not since the value is specified - mode_lib->vba.SynchronizeTimingsIfSingleRefreshRate = pipes[0].pipe.dest.synchronize_timing_if_single_refresh_rate; mode_lib->vba.SynchronizedVBlank = pipes[0].pipe.dest.synchronized_vblank_all_planes; for (k = 1; k < mode_lib->vba.cache_num_pipes; ++k) { - ASSERT(mode_lib->vba.SynchronizeTimingsIfSingleRefreshRate == pipes[k].pipe.dest.synchronize_timing_if_single_refresh_rate); ASSERT(mode_lib->vba.SynchronizedVBlank == pipes[k].pipe.dest.synchronized_vblank_all_planes); } diff --git a/drivers/gpu/drm/amd/display/dc/dml/display_mode_vba.h b/drivers/gpu/drm/amd/display/dc/dml/display_mode_vba.h index 4d4ed1287673..3529fedc4c52 100644 --- a/drivers/gpu/drm/amd/display/dc/dml/display_mode_vba.h +++ b/drivers/gpu/drm/amd/display/dc/dml/display_mode_vba.h @@ -921,7 +921,6 @@ struct vba_vars_st { bool UseMinimumRequiredDCFCLK; bool ClampMinDCFCLK; bool AllowDramClockChangeOneDisplayVactive; - bool SynchronizeTimingsIfSingleRefreshRate; }; 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 2ce8c39ca6f5..2d77eac66cb0 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/core_types.h +++ b/drivers/gpu/drm/amd/display/dc/inc/core_types.h @@ -109,7 +109,8 @@ struct resource_funcs { int (*populate_dml_pipes)( struct dc *dc, struct dc_state *context, - display_e2e_pipe_params_st *pipes); + display_e2e_pipe_params_st *pipes, + bool fast_validate); enum dc_status (*validate_global)( struct dc *dc, diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw/dchubbub.h b/drivers/gpu/drm/amd/display/dc/inc/hw/dchubbub.h index 5425e92efcb8..d9fd28b34f2a 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/hw/dchubbub.h +++ b/drivers/gpu/drm/amd/display/dc/inc/hw/dchubbub.h @@ -157,6 +157,7 @@ struct hubbub_funcs { struct hubbub { const struct hubbub_funcs *funcs; struct dc_context *ctx; + bool riommu_active; }; #endif diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw/dmcu.h b/drivers/gpu/drm/amd/display/dc/inc/hw/dmcu.h index 5315f1f86b21..69d9fbfb4bec 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/hw/dmcu.h +++ b/drivers/gpu/drm/amd/display/dc/inc/hw/dmcu.h @@ -66,7 +66,7 @@ struct dmcu_funcs { bool (*setup_psr)(struct dmcu *dmcu, struct dc_link *link, struct psr_context *psr_context); - void (*get_psr_state)(struct dmcu *dmcu, uint32_t *psr_state); + void (*get_psr_state)(struct dmcu *dmcu, enum dc_psr_state *dc_psr_state); void (*set_psr_wait_loop)(struct dmcu *dmcu, unsigned int wait_loop_number); void (*get_psr_wait_loop)(struct dmcu *dmcu, 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 6751186f6f90..ddbe4bb52724 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/hw/dpp.h +++ b/drivers/gpu/drm/amd/display/dc/inc/hw/dpp.h @@ -47,7 +47,7 @@ struct dpp_input_csc_matrix { uint16_t regval[12]; }; -static const struct dpp_input_csc_matrix dpp_input_csc_matrix[] = { +static const struct dpp_input_csc_matrix __maybe_unused dpp_input_csc_matrix[] = { {COLOR_SPACE_SRGB, {0x2000, 0, 0, 0, 0, 0x2000, 0, 0, 0, 0, 0x2000, 0} }, {COLOR_SPACE_SRGB_LIMITED, diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw/hw_shared.h b/drivers/gpu/drm/amd/display/dc/inc/hw/hw_shared.h index a3a27c16aa2f..43e33f47734d 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/hw/hw_shared.h +++ b/drivers/gpu/drm/amd/display/dc/inc/hw/hw_shared.h @@ -264,4 +264,88 @@ enum dc_lut_mode { LUT_RAM_A, LUT_RAM_B }; + +/** + * speakersToChannels + * + * @brief + * translate speakers to channels + * + * FL - Front Left + * FR - Front Right + * RL - Rear Left + * RR - Rear Right + * RC - Rear Center + * FC - Front Center + * FLC - Front Left Center + * FRC - Front Right Center + * RLC - Rear Left Center + * RRC - Rear Right Center + * LFE - Low Freq Effect + * + * FC + * FLC FRC + * FL FR + * + * LFE + * () + * + * + * RL RR + * RLC RRC + * RC + * + * ch 8 7 6 5 4 3 2 1 + * 0b00000011 - - - - - - FR FL + * 0b00000111 - - - - - LFE FR FL + * 0b00001011 - - - - FC - FR FL + * 0b00001111 - - - - FC LFE FR FL + * 0b00010011 - - - RC - - FR FL + * 0b00010111 - - - RC - LFE FR FL + * 0b00011011 - - - RC FC - FR FL + * 0b00011111 - - - RC FC LFE FR FL + * 0b00110011 - - RR RL - - FR FL + * 0b00110111 - - RR RL - LFE FR FL + * 0b00111011 - - RR RL FC - FR FL + * 0b00111111 - - RR RL FC LFE FR FL + * 0b01110011 - RC RR RL - - FR FL + * 0b01110111 - RC RR RL - LFE FR FL + * 0b01111011 - RC RR RL FC - FR FL + * 0b01111111 - RC RR RL FC LFE FR FL + * 0b11110011 RRC RLC RR RL - - FR FL + * 0b11110111 RRC RLC RR RL - LFE FR FL + * 0b11111011 RRC RLC RR RL FC - FR FL + * 0b11111111 RRC RLC RR RL FC LFE FR FL + * 0b11000011 FRC FLC - - - - FR FL + * 0b11000111 FRC FLC - - - LFE FR FL + * 0b11001011 FRC FLC - - FC - FR FL + * 0b11001111 FRC FLC - - FC LFE FR FL + * 0b11010011 FRC FLC - RC - - FR FL + * 0b11010111 FRC FLC - RC - LFE FR FL + * 0b11011011 FRC FLC - RC FC - FR FL + * 0b11011111 FRC FLC - RC FC LFE FR FL + * 0b11110011 FRC FLC RR RL - - FR FL + * 0b11110111 FRC FLC RR RL - LFE FR FL + * 0b11111011 FRC FLC RR RL FC - FR FL + * 0b11111111 FRC FLC RR RL FC LFE FR FL + * + * @param + * speakers - speaker information as it comes from CEA audio block + */ +/* translate speakers to channels */ + +union audio_cea_channels { + uint8_t all; + struct audio_cea_channels_bits { + uint32_t FL:1; + uint32_t FR:1; + uint32_t LFE:1; + uint32_t FC:1; + uint32_t RL_RC:1; + uint32_t RR:1; + uint32_t RC_RLC_FLC:1; + uint32_t RRC_FRC:1; + } channels; +}; + #endif /* __DAL_HW_SHARED_H__ */ diff --git a/drivers/gpu/drm/amd/display/dc/irq/dcn20/irq_service_dcn20.c b/drivers/gpu/drm/amd/display/dc/irq/dcn20/irq_service_dcn20.c index 2a1fea501f8c..3f1e7a196a23 100644 --- a/drivers/gpu/drm/amd/display/dc/irq/dcn20/irq_service_dcn20.c +++ b/drivers/gpu/drm/amd/display/dc/irq/dcn20/irq_service_dcn20.c @@ -299,8 +299,8 @@ irq_source_info_dcn20[DAL_IRQ_SOURCES_NUMBER] = { pflip_int_entry(1), pflip_int_entry(2), pflip_int_entry(3), - [DC_IRQ_SOURCE_PFLIP5] = dummy_irq_entry(), - [DC_IRQ_SOURCE_PFLIP6] = dummy_irq_entry(), + pflip_int_entry(4), + pflip_int_entry(5), [DC_IRQ_SOURCE_PFLIP_UNDERLAY0] = dummy_irq_entry(), gpio_pad_int_entry(0), gpio_pad_int_entry(1), |