diff options
Diffstat (limited to 'drivers/gpu/drm/amd/display/dc/dcn32')
16 files changed, 313 insertions, 1979 deletions
diff --git a/drivers/gpu/drm/amd/display/dc/dcn32/Makefile b/drivers/gpu/drm/amd/display/dc/dcn32/Makefile index e943b643ab..8bb2513072 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn32/Makefile +++ b/drivers/gpu/drm/amd/display/dc/dcn32/Makefile @@ -10,7 +10,7 @@ # # Makefile for dcn32. -DCN32 = dcn32_resource.o dcn32_hubbub.o dcn32_hwseq.o dcn32_init.o \ +DCN32 = dcn32_resource.o dcn32_hubbub.o dcn32_init.o dcn32_dccg.o \ dcn32_dccg.o dcn32_optc.o dcn32_mmhubbub.o dcn32_hubp.o dcn32_dpp.o \ dcn32_dio_stream_encoder.o dcn32_dio_link_encoder.o dcn32_hpo_dp_link_encoder.o \ dcn32_resource_helpers.o dcn32_mpc.o diff --git a/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_dccg.c b/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_dccg.c index 921f58c0c7..036d05468d 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_dccg.c +++ b/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_dccg.c @@ -345,6 +345,7 @@ static const struct dccg_funcs dccg32_funcs = { .otg_drop_pixel = dccg32_otg_drop_pixel, .set_pixel_rate_div = dccg32_set_pixel_rate_div, .trigger_dio_fifo_resync = dccg32_trigger_dio_fifo_resync, + .set_dtbclk_p_src = dccg32_set_dtbclk_p_src, }; struct dccg *dccg32_create( diff --git a/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_dio_link_encoder.c b/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_dio_link_encoder.c index 5013880148..d761b0df28 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_dio_link_encoder.c +++ b/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_dio_link_encoder.c @@ -203,12 +203,12 @@ void dcn32_link_encoder_construct( enc10->base.hpd_source = init_data->hpd_source; enc10->base.connector = init_data->connector; - if (enc10->base.connector.id == CONNECTOR_ID_USBC) - enc10->base.features.flags.bits.DP_IS_USB_C = 1; enc10->base.preferred_engine = ENGINE_ID_UNKNOWN; enc10->base.features = *enc_features; + if (enc10->base.connector.id == CONNECTOR_ID_USBC) + enc10->base.features.flags.bits.DP_IS_USB_C = 1; enc10->base.transmitter = init_data->transmitter; diff --git a/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_hubbub.c b/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_hubbub.c index 8bfef6d095..88dfc90755 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_hubbub.c +++ b/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_hubbub.c @@ -945,6 +945,17 @@ void hubbub32_force_wm_propagate_to_pipes(struct hubbub *hubbub) DCHUBBUB_ARB_DATA_URGENCY_WATERMARK_A, prog_wm_value); } +void hubbub32_get_mall_en(struct hubbub *hubbub, unsigned int *mall_in_use) +{ + struct dcn20_hubbub *hubbub2 = TO_DCN20_HUBBUB(hubbub); + uint32_t prefetch_complete, mall_en; + + REG_GET_2(DCHUBBUB_ARB_MALL_CNTL, MALL_IN_USE, &mall_en, + MALL_PREFETCH_COMPLETE, &prefetch_complete); + + *mall_in_use = prefetch_complete && mall_en; +} + void hubbub32_init(struct hubbub *hubbub) { struct dcn20_hubbub *hubbub2 = TO_DCN20_HUBBUB(hubbub); @@ -995,7 +1006,8 @@ static const struct hubbub_funcs hubbub32_funcs = { .init_crb = dcn32_init_crb, .hubbub_read_state = hubbub2_read_state, .force_usr_retraining_allow = hubbub32_force_usr_retraining_allow, - .set_request_limit = hubbub32_set_request_limit + .set_request_limit = hubbub32_set_request_limit, + .get_mall_en = hubbub32_get_mall_en, }; void hubbub32_construct(struct dcn20_hubbub *hubbub2, diff --git a/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_hubbub.h b/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_hubbub.h index ad33427192..f073839a4b 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_hubbub.h +++ b/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_hubbub.h @@ -110,7 +110,9 @@ HUBBUB_SF(DCHUBBUB_CLOCK_CNTL, DCFCLK_R_DCHUBBUB_GATE_DIS, mask_sh),\ HUBBUB_SF(DCHUBBUB_SDPIF_CFG0, SDPIF_PORT_CONTROL, mask_sh),\ HUBBUB_SF(DCHUBBUB_SDPIF_CFG1, SDPIF_MAX_NUM_OUTSTANDING, mask_sh),\ - HUBBUB_SF(DCHUBBUB_MEM_PWR_MODE_CTRL, DET_MEM_PWR_LS_MODE, mask_sh) + HUBBUB_SF(DCHUBBUB_MEM_PWR_MODE_CTRL, DET_MEM_PWR_LS_MODE, mask_sh),\ + HUBBUB_SF(DCHUBBUB_ARB_MALL_CNTL, MALL_PREFETCH_COMPLETE, mask_sh),\ + HUBBUB_SF(DCHUBBUB_ARB_MALL_CNTL, MALL_IN_USE, mask_sh) @@ -157,4 +159,6 @@ void hubbub32_construct(struct dcn20_hubbub *hubbub2, void hubbub32_set_request_limit(struct hubbub *hubbub, int umc_count, int words_per_umc); +void hubbub32_get_mall_en(struct hubbub *hubbub, unsigned int *mall_in_use); + #endif diff --git a/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_hwseq.c b/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_hwseq.c deleted file mode 100644 index 650e1598bd..0000000000 --- a/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_hwseq.c +++ /dev/null @@ -1,1675 +0,0 @@ -/* - * Copyright 2016 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 "dm_services.h" -#include "dm_helpers.h" -#include "core_types.h" -#include "resource.h" -#include "dccg.h" -#include "dce/dce_hwseq.h" -#include "dcn30/dcn30_cm_common.h" -#include "reg_helper.h" -#include "abm.h" -#include "hubp.h" -#include "dchubbub.h" -#include "timing_generator.h" -#include "opp.h" -#include "ipp.h" -#include "mpc.h" -#include "mcif_wb.h" -#include "dc_dmub_srv.h" -#include "link_hwss.h" -#include "dpcd_defs.h" -#include "dcn32_hwseq.h" -#include "clk_mgr.h" -#include "dsc.h" -#include "dcn20/dcn20_optc.h" -#include "dce/dmub_hw_lock_mgr.h" -#include "dcn32_resource.h" -#include "link.h" - -#define DC_LOGGER_INIT(logger) - -#define CTX \ - hws->ctx -#define REG(reg)\ - hws->regs->reg -#define DC_LOGGER \ - dc->ctx->logger - - -#undef FN -#define FN(reg_name, field_name) \ - hws->shifts->field_name, hws->masks->field_name - -void dcn32_dsc_pg_control( - struct dce_hwseq *hws, - unsigned int dsc_inst, - bool power_on) -{ - uint32_t power_gate = power_on ? 0 : 1; - uint32_t pwr_status = power_on ? 0 : 2; - uint32_t org_ip_request_cntl = 0; - - if (hws->ctx->dc->debug.disable_dsc_power_gate) - return; - - if (!hws->ctx->dc->debug.enable_double_buffered_dsc_pg_support) - return; - - REG_GET(DC_IP_REQUEST_CNTL, IP_REQUEST_EN, &org_ip_request_cntl); - if (org_ip_request_cntl == 0) - REG_SET(DC_IP_REQUEST_CNTL, 0, IP_REQUEST_EN, 1); - - switch (dsc_inst) { - case 0: /* DSC0 */ - REG_UPDATE(DOMAIN16_PG_CONFIG, - DOMAIN_POWER_GATE, power_gate); - - REG_WAIT(DOMAIN16_PG_STATUS, - DOMAIN_PGFSM_PWR_STATUS, pwr_status, - 1, 1000); - break; - case 1: /* DSC1 */ - REG_UPDATE(DOMAIN17_PG_CONFIG, - DOMAIN_POWER_GATE, power_gate); - - REG_WAIT(DOMAIN17_PG_STATUS, - DOMAIN_PGFSM_PWR_STATUS, pwr_status, - 1, 1000); - break; - case 2: /* DSC2 */ - REG_UPDATE(DOMAIN18_PG_CONFIG, - DOMAIN_POWER_GATE, power_gate); - - REG_WAIT(DOMAIN18_PG_STATUS, - DOMAIN_PGFSM_PWR_STATUS, pwr_status, - 1, 1000); - break; - case 3: /* DSC3 */ - REG_UPDATE(DOMAIN19_PG_CONFIG, - DOMAIN_POWER_GATE, power_gate); - - REG_WAIT(DOMAIN19_PG_STATUS, - DOMAIN_PGFSM_PWR_STATUS, pwr_status, - 1, 1000); - break; - default: - BREAK_TO_DEBUGGER(); - break; - } - - if (org_ip_request_cntl == 0) - REG_SET(DC_IP_REQUEST_CNTL, 0, IP_REQUEST_EN, 0); -} - - -void dcn32_enable_power_gating_plane( - struct dce_hwseq *hws, - bool enable) -{ - bool force_on = true; /* disable power gating */ - uint32_t org_ip_request_cntl = 0; - - if (enable) - force_on = false; - - REG_GET(DC_IP_REQUEST_CNTL, IP_REQUEST_EN, &org_ip_request_cntl); - if (org_ip_request_cntl == 0) - REG_SET(DC_IP_REQUEST_CNTL, 0, IP_REQUEST_EN, 1); - - /* DCHUBP0/1/2/3 */ - REG_UPDATE(DOMAIN0_PG_CONFIG, DOMAIN_POWER_FORCEON, force_on); - REG_UPDATE(DOMAIN1_PG_CONFIG, DOMAIN_POWER_FORCEON, force_on); - REG_UPDATE(DOMAIN2_PG_CONFIG, DOMAIN_POWER_FORCEON, force_on); - REG_UPDATE(DOMAIN3_PG_CONFIG, DOMAIN_POWER_FORCEON, force_on); - - /* DCS0/1/2/3 */ - REG_UPDATE(DOMAIN16_PG_CONFIG, DOMAIN_POWER_FORCEON, force_on); - REG_UPDATE(DOMAIN17_PG_CONFIG, DOMAIN_POWER_FORCEON, force_on); - REG_UPDATE(DOMAIN18_PG_CONFIG, DOMAIN_POWER_FORCEON, force_on); - REG_UPDATE(DOMAIN19_PG_CONFIG, DOMAIN_POWER_FORCEON, force_on); - - if (org_ip_request_cntl == 0) - REG_SET(DC_IP_REQUEST_CNTL, 0, IP_REQUEST_EN, 0); -} - -void dcn32_hubp_pg_control(struct dce_hwseq *hws, unsigned int hubp_inst, bool power_on) -{ - uint32_t power_gate = power_on ? 0 : 1; - uint32_t pwr_status = power_on ? 0 : 2; - - if (hws->ctx->dc->debug.disable_hubp_power_gate) - return; - - if (REG(DOMAIN0_PG_CONFIG) == 0) - return; - - switch (hubp_inst) { - case 0: - REG_SET(DOMAIN0_PG_CONFIG, 0, DOMAIN_POWER_GATE, power_gate); - REG_WAIT(DOMAIN0_PG_STATUS, DOMAIN_PGFSM_PWR_STATUS, pwr_status, 1, 1000); - break; - case 1: - REG_SET(DOMAIN1_PG_CONFIG, 0, DOMAIN_POWER_GATE, power_gate); - REG_WAIT(DOMAIN1_PG_STATUS, DOMAIN_PGFSM_PWR_STATUS, pwr_status, 1, 1000); - break; - case 2: - REG_SET(DOMAIN2_PG_CONFIG, 0, DOMAIN_POWER_GATE, power_gate); - REG_WAIT(DOMAIN2_PG_STATUS, DOMAIN_PGFSM_PWR_STATUS, pwr_status, 1, 1000); - break; - case 3: - REG_SET(DOMAIN3_PG_CONFIG, 0, DOMAIN_POWER_GATE, power_gate); - REG_WAIT(DOMAIN3_PG_STATUS, DOMAIN_PGFSM_PWR_STATUS, pwr_status, 1, 1000); - break; - default: - BREAK_TO_DEBUGGER(); - break; - } -} - -static bool dcn32_check_no_memory_request_for_cab(struct dc *dc) -{ - int i; - - /* First, check no-memory-request case */ - for (i = 0; i < dc->current_state->stream_count; i++) { - if ((dc->current_state->stream_status[i].plane_count) && - (dc->current_state->streams[i]->link->psr_settings.psr_version == DC_PSR_VERSION_UNSUPPORTED)) - /* Fail eligibility on a visible stream */ - break; - } - - if (i == dc->current_state->stream_count) - return true; - - return false; -} - - -/* This function loops through every surface that needs to be cached in CAB for SS, - * and calculates the total number of ways required to store all surfaces (primary, - * meta, cursor). - */ -static uint32_t dcn32_calculate_cab_allocation(struct dc *dc, struct dc_state *ctx) -{ - int i; - uint32_t num_ways = 0; - uint32_t mall_ss_size_bytes = 0; - - mall_ss_size_bytes = ctx->bw_ctx.bw.dcn.mall_ss_size_bytes; - // TODO add additional logic for PSR active stream exclusion optimization - // mall_ss_psr_active_size_bytes = ctx->bw_ctx.bw.dcn.mall_ss_psr_active_size_bytes; - - // Include cursor size for CAB allocation - for (i = 0; i < dc->res_pool->pipe_count; i++) { - struct pipe_ctx *pipe = &ctx->res_ctx.pipe_ctx[i]; - - if (!pipe->stream || !pipe->plane_state) - continue; - - mall_ss_size_bytes += dcn32_helper_calculate_mall_bytes_for_cursor(dc, pipe, false); - } - - // Convert number of cache lines required to number of ways - if (dc->debug.force_mall_ss_num_ways > 0) { - num_ways = dc->debug.force_mall_ss_num_ways; - } else { - num_ways = dcn32_helper_mall_bytes_to_ways(dc, mall_ss_size_bytes); - } - - return num_ways; -} - -bool dcn32_apply_idle_power_optimizations(struct dc *dc, bool enable) -{ - union dmub_rb_cmd cmd; - uint8_t i; - uint32_t ways; - int j; - bool mall_ss_unsupported = false; - struct dc_plane_state *plane = NULL; - - if (!dc->ctx->dmub_srv) - return false; - - for (i = 0; i < dc->current_state->stream_count; i++) { - /* MALL SS messaging is not supported with PSR at this time */ - if (dc->current_state->streams[i] != NULL && - dc->current_state->streams[i]->link->psr_settings.psr_version != DC_PSR_VERSION_UNSUPPORTED) - return false; - } - - if (enable) { - if (dc->current_state) { - - /* 1. Check no memory request case for CAB. - * If no memory request case, send CAB_ACTION NO_DF_REQ DMUB message - */ - if (dcn32_check_no_memory_request_for_cab(dc)) { - /* Enable no-memory-requests case */ - memset(&cmd, 0, sizeof(cmd)); - cmd.cab.header.type = DMUB_CMD__CAB_FOR_SS; - cmd.cab.header.sub_type = DMUB_CMD__CAB_NO_DCN_REQ; - cmd.cab.header.payload_bytes = sizeof(cmd.cab) - sizeof(cmd.cab.header); - - dm_execute_dmub_cmd(dc->ctx, &cmd, DM_DMUB_WAIT_TYPE_NO_WAIT); - - return true; - } - - /* 2. Check if all surfaces can fit in CAB. - * If surfaces can fit into CAB, send CAB_ACTION_ALLOW DMUB message - * and configure HUBP's to fetch from MALL - */ - ways = dcn32_calculate_cab_allocation(dc, dc->current_state); - - /* MALL not supported with Stereo3D or TMZ surface. If any plane is using stereo, - * or TMZ surface, don't try to enter MALL. - */ - for (i = 0; i < dc->current_state->stream_count; i++) { - for (j = 0; j < dc->current_state->stream_status[i].plane_count; j++) { - plane = dc->current_state->stream_status[i].plane_states[j]; - - if (plane->address.type == PLN_ADDR_TYPE_GRPH_STEREO || - plane->address.tmz_surface) { - mall_ss_unsupported = true; - break; - } - } - if (mall_ss_unsupported) - break; - } - if (ways <= dc->caps.cache_num_ways && !mall_ss_unsupported) { - memset(&cmd, 0, sizeof(cmd)); - cmd.cab.header.type = DMUB_CMD__CAB_FOR_SS; - cmd.cab.header.sub_type = DMUB_CMD__CAB_DCN_SS_FIT_IN_CAB; - cmd.cab.header.payload_bytes = sizeof(cmd.cab) - sizeof(cmd.cab.header); - cmd.cab.cab_alloc_ways = (uint8_t)ways; - - dm_execute_dmub_cmd(dc->ctx, &cmd, DM_DMUB_WAIT_TYPE_NO_WAIT); - - return true; - } - - } - return false; - } - - /* Disable CAB */ - memset(&cmd, 0, sizeof(cmd)); - cmd.cab.header.type = DMUB_CMD__CAB_FOR_SS; - cmd.cab.header.sub_type = DMUB_CMD__CAB_NO_IDLE_OPTIMIZATION; - cmd.cab.header.payload_bytes = - sizeof(cmd.cab) - sizeof(cmd.cab.header); - - dm_execute_dmub_cmd(dc->ctx, &cmd, DM_DMUB_WAIT_TYPE_WAIT); - - return true; -} - -/* Send DMCUB message with SubVP pipe info - * - For each pipe in context, populate payload with required SubVP information - * if the pipe is using SubVP for MCLK switch - * - This function must be called while the DMUB HW lock is acquired by driver - */ -void dcn32_commit_subvp_config(struct dc *dc, struct dc_state *context) -{ - int i; - bool enable_subvp = false; - - if (!dc->ctx || !dc->ctx->dmub_srv) - return; - - for (i = 0; i < dc->res_pool->pipe_count; i++) { - struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[i]; - - if (pipe_ctx->stream && pipe_ctx->stream->mall_stream_config.paired_stream && - pipe_ctx->stream->mall_stream_config.type == SUBVP_MAIN) { - // There is at least 1 SubVP pipe, so enable SubVP - enable_subvp = true; - break; - } - } - dc_dmub_setup_subvp_dmub_command(dc, context, enable_subvp); -} - -/* Sub-Viewport DMUB lock needs to be acquired by driver whenever SubVP is active and: - * 1. Any full update for any SubVP main pipe - * 2. Any immediate flip for any SubVP pipe - * 3. Any flip for DRR pipe - * 4. If SubVP was previously in use (i.e. in old context) - */ -void dcn32_subvp_pipe_control_lock(struct dc *dc, - struct dc_state *context, - bool lock, - bool should_lock_all_pipes, - struct pipe_ctx *top_pipe_to_program, - bool subvp_prev_use) -{ - unsigned int i = 0; - bool subvp_immediate_flip = false; - bool subvp_in_use = false; - struct pipe_ctx *pipe; - - for (i = 0; i < dc->res_pool->pipe_count; i++) { - pipe = &context->res_ctx.pipe_ctx[i]; - - if (pipe->stream && pipe->plane_state && pipe->stream->mall_stream_config.type == SUBVP_MAIN) { - subvp_in_use = true; - break; - } - } - - if (top_pipe_to_program && top_pipe_to_program->stream && top_pipe_to_program->plane_state) { - if (top_pipe_to_program->stream->mall_stream_config.type == SUBVP_MAIN && - top_pipe_to_program->plane_state->flip_immediate) - subvp_immediate_flip = true; - } - - // Don't need to lock for DRR VSYNC flips -- FW will wait for DRR pending update cleared. - if ((subvp_in_use && (should_lock_all_pipes || subvp_immediate_flip)) || (!subvp_in_use && subvp_prev_use)) { - union dmub_inbox0_cmd_lock_hw hw_lock_cmd = { 0 }; - - if (!lock) { - for (i = 0; i < dc->res_pool->pipe_count; i++) { - pipe = &context->res_ctx.pipe_ctx[i]; - if (pipe->stream && pipe->plane_state && pipe->stream->mall_stream_config.type == SUBVP_MAIN && - should_lock_all_pipes) - pipe->stream_res.tg->funcs->wait_for_state(pipe->stream_res.tg, CRTC_STATE_VBLANK); - } - } - - hw_lock_cmd.bits.command_code = DMUB_INBOX0_CMD__HW_LOCK; - hw_lock_cmd.bits.hw_lock_client = HW_LOCK_CLIENT_DRIVER; - hw_lock_cmd.bits.lock = lock; - hw_lock_cmd.bits.should_release = !lock; - dmub_hw_lock_mgr_inbox0_cmd(dc->ctx->dmub_srv, hw_lock_cmd); - } -} - -void dcn32_subvp_pipe_control_lock_fast(union block_sequence_params *params) -{ - struct dc *dc = params->subvp_pipe_control_lock_fast_params.dc; - bool lock = params->subvp_pipe_control_lock_fast_params.lock; - struct pipe_ctx *pipe_ctx = params->subvp_pipe_control_lock_fast_params.pipe_ctx; - bool subvp_immediate_flip = false; - - if (pipe_ctx && pipe_ctx->stream && pipe_ctx->plane_state) { - if (pipe_ctx->stream->mall_stream_config.type == SUBVP_MAIN && - pipe_ctx->plane_state->flip_immediate) - subvp_immediate_flip = true; - } - - // Don't need to lock for DRR VSYNC flips -- FW will wait for DRR pending update cleared. - if (subvp_immediate_flip) { - union dmub_inbox0_cmd_lock_hw hw_lock_cmd = { 0 }; - - hw_lock_cmd.bits.command_code = DMUB_INBOX0_CMD__HW_LOCK; - hw_lock_cmd.bits.hw_lock_client = HW_LOCK_CLIENT_DRIVER; - hw_lock_cmd.bits.lock = lock; - hw_lock_cmd.bits.should_release = !lock; - dmub_hw_lock_mgr_inbox0_cmd(dc->ctx->dmub_srv, hw_lock_cmd); - } -} - -bool dcn32_set_mpc_shaper_3dlut( - struct pipe_ctx *pipe_ctx, const struct dc_stream_state *stream) -{ - struct dpp *dpp_base = pipe_ctx->plane_res.dpp; - int mpcc_id = pipe_ctx->plane_res.hubp->inst; - struct mpc *mpc = pipe_ctx->stream_res.opp->ctx->dc->res_pool->mpc; - bool result = false; - - const struct pwl_params *shaper_lut = NULL; - //get the shaper lut params - if (stream->func_shaper) { - if (stream->func_shaper->type == TF_TYPE_HWPWL) - shaper_lut = &stream->func_shaper->pwl; - else if (stream->func_shaper->type == TF_TYPE_DISTRIBUTED_POINTS) { - cm_helper_translate_curve_to_hw_format(stream->ctx, - stream->func_shaper, - &dpp_base->shaper_params, true); - shaper_lut = &dpp_base->shaper_params; - } - } - - if (stream->lut3d_func && - stream->lut3d_func->state.bits.initialized == 1) { - - result = mpc->funcs->program_3dlut(mpc, - &stream->lut3d_func->lut_3d, - mpcc_id); - - result = mpc->funcs->program_shaper(mpc, - shaper_lut, - mpcc_id); - } - - return result; -} - -bool dcn32_set_mcm_luts( - struct pipe_ctx *pipe_ctx, const struct dc_plane_state *plane_state) -{ - struct dpp *dpp_base = pipe_ctx->plane_res.dpp; - int mpcc_id = pipe_ctx->plane_res.hubp->inst; - struct mpc *mpc = pipe_ctx->stream_res.opp->ctx->dc->res_pool->mpc; - bool result = true; - struct pwl_params *lut_params = NULL; - - // 1D LUT - if (plane_state->blend_tf) { - if (plane_state->blend_tf->type == TF_TYPE_HWPWL) - lut_params = &plane_state->blend_tf->pwl; - else if (plane_state->blend_tf->type == TF_TYPE_DISTRIBUTED_POINTS) { - cm3_helper_translate_curve_to_hw_format(plane_state->blend_tf, - &dpp_base->regamma_params, false); - lut_params = &dpp_base->regamma_params; - } - } - result = mpc->funcs->program_1dlut(mpc, lut_params, mpcc_id); - - // Shaper - if (plane_state->in_shaper_func) { - if (plane_state->in_shaper_func->type == TF_TYPE_HWPWL) - lut_params = &plane_state->in_shaper_func->pwl; - else if (plane_state->in_shaper_func->type == TF_TYPE_DISTRIBUTED_POINTS) { - // TODO: dpp_base replace - ASSERT(false); - cm3_helper_translate_curve_to_hw_format(plane_state->in_shaper_func, - &dpp_base->shaper_params, true); - lut_params = &dpp_base->shaper_params; - } - } - - result = mpc->funcs->program_shaper(mpc, lut_params, mpcc_id); - - // 3D - if (plane_state->lut3d_func && plane_state->lut3d_func->state.bits.initialized == 1) - result = mpc->funcs->program_3dlut(mpc, &plane_state->lut3d_func->lut_3d, mpcc_id); - else - result = mpc->funcs->program_3dlut(mpc, NULL, mpcc_id); - - return result; -} - -bool dcn32_set_input_transfer_func(struct dc *dc, - struct pipe_ctx *pipe_ctx, - const struct dc_plane_state *plane_state) -{ - struct dce_hwseq *hws = dc->hwseq; - struct mpc *mpc = dc->res_pool->mpc; - struct dpp *dpp_base = pipe_ctx->plane_res.dpp; - - enum dc_transfer_func_predefined tf; - bool result = true; - struct pwl_params *params = NULL; - - if (mpc == NULL || plane_state == NULL) - return false; - - tf = TRANSFER_FUNCTION_UNITY; - - if (plane_state->in_transfer_func && - plane_state->in_transfer_func->type == TF_TYPE_PREDEFINED) - tf = plane_state->in_transfer_func->tf; - - dpp_base->funcs->dpp_set_pre_degam(dpp_base, tf); - - if (plane_state->in_transfer_func) { - if (plane_state->in_transfer_func->type == TF_TYPE_HWPWL) - params = &plane_state->in_transfer_func->pwl; - else if (plane_state->in_transfer_func->type == TF_TYPE_DISTRIBUTED_POINTS && - cm3_helper_translate_curve_to_hw_format(plane_state->in_transfer_func, - &dpp_base->degamma_params, false)) - params = &dpp_base->degamma_params; - } - - dpp_base->funcs->dpp_program_gamcor_lut(dpp_base, params); - - if (pipe_ctx->stream_res.opp && - pipe_ctx->stream_res.opp->ctx && - hws->funcs.set_mcm_luts) - result = hws->funcs.set_mcm_luts(pipe_ctx, plane_state); - - return result; -} - -bool dcn32_set_output_transfer_func(struct dc *dc, - struct pipe_ctx *pipe_ctx, - const struct dc_stream_state *stream) -{ - int mpcc_id = pipe_ctx->plane_res.hubp->inst; - struct mpc *mpc = pipe_ctx->stream_res.opp->ctx->dc->res_pool->mpc; - struct pwl_params *params = NULL; - bool ret = false; - - /* program OGAM or 3DLUT only for the top pipe*/ - if (resource_is_pipe_type(pipe_ctx, OPP_HEAD)) { - /*program shaper and 3dlut in MPC*/ - ret = dcn32_set_mpc_shaper_3dlut(pipe_ctx, stream); - if (ret == false && mpc->funcs->set_output_gamma && stream->out_transfer_func) { - if (stream->out_transfer_func->type == TF_TYPE_HWPWL) - params = &stream->out_transfer_func->pwl; - else if (pipe_ctx->stream->out_transfer_func->type == - TF_TYPE_DISTRIBUTED_POINTS && - cm3_helper_translate_curve_to_hw_format( - stream->out_transfer_func, - &mpc->blender_params, false)) - params = &mpc->blender_params; - /* there are no ROM LUTs in OUTGAM */ - if (stream->out_transfer_func->type == TF_TYPE_PREDEFINED) - BREAK_TO_DEBUGGER(); - } - } - - mpc->funcs->set_output_gamma(mpc, mpcc_id, params); - return ret; -} - -/* Program P-State force value according to if pipe is using SubVP / FPO or not: - * 1. Reset P-State force on all pipes first - * 2. For each main pipe, force P-State disallow (P-State allow moderated by DMUB) - */ -void dcn32_update_force_pstate(struct dc *dc, struct dc_state *context) -{ - int i; - - /* Unforce p-state for each pipe if it is not FPO or SubVP. - * For FPO and SubVP, if it's already forced disallow, leave - * it as disallow. - */ - for (i = 0; i < dc->res_pool->pipe_count; i++) { - struct pipe_ctx *pipe = &context->res_ctx.pipe_ctx[i]; - struct hubp *hubp = pipe->plane_res.hubp; - - if (!pipe->stream || !(pipe->stream->mall_stream_config.type == SUBVP_MAIN || - pipe->stream->fpo_in_use)) { - if (hubp && hubp->funcs->hubp_update_force_pstate_disallow) - hubp->funcs->hubp_update_force_pstate_disallow(hubp, false); - } - - /* Today only FPO uses cursor P-State force. Only clear cursor P-State force - * if it's not FPO. - */ - if (!pipe->stream || !pipe->stream->fpo_in_use) { - if (hubp && hubp->funcs->hubp_update_force_cursor_pstate_disallow) - hubp->funcs->hubp_update_force_cursor_pstate_disallow(hubp, false); - } - } - - /* Loop through each pipe -- for each subvp main pipe force p-state allow equal to false. - */ - for (i = 0; i < dc->res_pool->pipe_count; i++) { - struct pipe_ctx *pipe = &context->res_ctx.pipe_ctx[i]; - struct hubp *hubp = pipe->plane_res.hubp; - - if (pipe->stream && pipe->plane_state && pipe->stream->mall_stream_config.type == SUBVP_MAIN) { - if (hubp && hubp->funcs->hubp_update_force_pstate_disallow) - hubp->funcs->hubp_update_force_pstate_disallow(hubp, true); - } - - if (pipe->stream && pipe->stream->fpo_in_use) { - if (hubp && hubp->funcs->hubp_update_force_pstate_disallow) - hubp->funcs->hubp_update_force_pstate_disallow(hubp, true); - /* For now only force cursor p-state disallow for FPO - * Needs to be added for subvp once FW side gets updated - */ - if (hubp && hubp->funcs->hubp_update_force_cursor_pstate_disallow) - hubp->funcs->hubp_update_force_cursor_pstate_disallow(hubp, true); - } - } -} - -/* Update MALL_SEL register based on if pipe / plane - * is a phantom pipe, main pipe, and if using MALL - * for SS. - */ -void dcn32_update_mall_sel(struct dc *dc, struct dc_state *context) -{ - int i; - unsigned int num_ways = dcn32_calculate_cab_allocation(dc, context); - bool cache_cursor = false; - - for (i = 0; i < dc->res_pool->pipe_count; i++) { - struct pipe_ctx *pipe = &context->res_ctx.pipe_ctx[i]; - struct hubp *hubp = pipe->plane_res.hubp; - - if (pipe->stream && pipe->plane_state && hubp && hubp->funcs->hubp_update_mall_sel) { - int cursor_size = hubp->curs_attr.pitch * hubp->curs_attr.height; - - switch (hubp->curs_attr.color_format) { - case CURSOR_MODE_MONO: - cursor_size /= 2; - break; - case CURSOR_MODE_COLOR_1BIT_AND: - case CURSOR_MODE_COLOR_PRE_MULTIPLIED_ALPHA: - case CURSOR_MODE_COLOR_UN_PRE_MULTIPLIED_ALPHA: - cursor_size *= 4; - break; - - case CURSOR_MODE_COLOR_64BIT_FP_PRE_MULTIPLIED: - case CURSOR_MODE_COLOR_64BIT_FP_UN_PRE_MULTIPLIED: - default: - cursor_size *= 8; - break; - } - - if (cursor_size > 16384) - cache_cursor = true; - - if (pipe->stream->mall_stream_config.type == SUBVP_PHANTOM) { - hubp->funcs->hubp_update_mall_sel(hubp, 1, false); - } else { - // MALL not supported with Stereo3D - hubp->funcs->hubp_update_mall_sel(hubp, - num_ways <= dc->caps.cache_num_ways && - pipe->stream->link->psr_settings.psr_version == DC_PSR_VERSION_UNSUPPORTED && - pipe->plane_state->address.type != PLN_ADDR_TYPE_GRPH_STEREO && - !pipe->plane_state->address.tmz_surface ? 2 : 0, - cache_cursor); - } - } - } -} - -/* Program the sub-viewport pipe configuration after the main / phantom pipes - * have been programmed in hardware. - * 1. Update force P-State for all the main pipes (disallow P-state) - * 2. Update MALL_SEL register - * 3. Program FORCE_ONE_ROW_FOR_FRAME for main subvp pipes - */ -void dcn32_program_mall_pipe_config(struct dc *dc, struct dc_state *context) -{ - int i; - struct dce_hwseq *hws = dc->hwseq; - - // Don't force p-state disallow -- can't block dummy p-state - - // Update MALL_SEL register for each pipe - if (hws && hws->funcs.update_mall_sel) - hws->funcs.update_mall_sel(dc, context); - - // Program FORCE_ONE_ROW_FOR_FRAME and CURSOR_REQ_MODE for main subvp pipes - for (i = 0; i < dc->res_pool->pipe_count; i++) { - struct pipe_ctx *pipe = &context->res_ctx.pipe_ctx[i]; - struct hubp *hubp = pipe->plane_res.hubp; - - if (pipe->stream && hubp && hubp->funcs->hubp_prepare_subvp_buffering) { - /* TODO - remove setting CURSOR_REQ_MODE to 0 for legacy cases - * - need to investigate single pipe MPO + SubVP case to - * see if CURSOR_REQ_MODE will be back to 1 for SubVP - * when it should be 0 for MPO - */ - if (pipe->stream->mall_stream_config.type == SUBVP_MAIN) { - hubp->funcs->hubp_prepare_subvp_buffering(hubp, true); - } - } - } -} - -static void dcn32_initialize_min_clocks(struct dc *dc) -{ - struct dc_clocks *clocks = &dc->current_state->bw_ctx.bw.dcn.clk; - - clocks->dcfclk_deep_sleep_khz = DCN3_2_DCFCLK_DS_INIT_KHZ; - clocks->dcfclk_khz = dc->clk_mgr->bw_params->clk_table.entries[0].dcfclk_mhz * 1000; - clocks->socclk_khz = dc->clk_mgr->bw_params->clk_table.entries[0].socclk_mhz * 1000; - clocks->dramclk_khz = dc->clk_mgr->bw_params->clk_table.entries[0].memclk_mhz * 1000; - clocks->dppclk_khz = dc->clk_mgr->bw_params->clk_table.entries[0].dppclk_mhz * 1000; - clocks->ref_dtbclk_khz = dc->clk_mgr->bw_params->clk_table.entries[0].dtbclk_mhz * 1000; - clocks->fclk_p_state_change_support = true; - clocks->p_state_change_support = true; - if (dc->debug.disable_boot_optimizations) { - clocks->dispclk_khz = dc->clk_mgr->bw_params->clk_table.entries[0].dispclk_mhz * 1000; - } else { - /* Even though DPG_EN = 1 for the connected display, it still requires the - * correct timing so we cannot set DISPCLK to min freq or it could cause - * audio corruption. Read current DISPCLK from DENTIST and request the same - * freq to ensure that the timing is valid and unchanged. - */ - clocks->dispclk_khz = dc->clk_mgr->funcs->get_dispclk_from_dentist(dc->clk_mgr); - } - - dc->clk_mgr->funcs->update_clocks( - dc->clk_mgr, - dc->current_state, - true); -} - -void dcn32_init_hw(struct dc *dc) -{ - struct abm **abms = dc->res_pool->multiple_abms; - struct dce_hwseq *hws = dc->hwseq; - struct dc_bios *dcb = dc->ctx->dc_bios; - struct resource_pool *res_pool = dc->res_pool; - int i; - int edp_num; - uint32_t backlight = MAX_BACKLIGHT_LEVEL; - - if (dc->clk_mgr && dc->clk_mgr->funcs->init_clocks) - dc->clk_mgr->funcs->init_clocks(dc->clk_mgr); - - // Initialize the dccg - if (res_pool->dccg->funcs->dccg_init) - res_pool->dccg->funcs->dccg_init(res_pool->dccg); - - if (!dcb->funcs->is_accelerated_mode(dcb)) { - hws->funcs.bios_golden_init(dc); - hws->funcs.disable_vga(dc->hwseq); - } - - // Set default OPTC memory power states - if (dc->debug.enable_mem_low_power.bits.optc) { - // Shutdown when unassigned and light sleep in VBLANK - REG_SET_2(ODM_MEM_PWR_CTRL3, 0, ODM_MEM_UNASSIGNED_PWR_MODE, 3, ODM_MEM_VBLANK_PWR_MODE, 1); - } - - if (dc->debug.enable_mem_low_power.bits.vga) { - // Power down VGA memory - REG_UPDATE(MMHUBBUB_MEM_PWR_CNTL, VGA_MEM_PWR_FORCE, 1); - } - - if (dc->ctx->dc_bios->fw_info_valid) { - res_pool->ref_clocks.xtalin_clock_inKhz = - dc->ctx->dc_bios->fw_info.pll_info.crystal_frequency; - - if (res_pool->dccg && res_pool->hubbub) { - (res_pool->dccg->funcs->get_dccg_ref_freq)(res_pool->dccg, - dc->ctx->dc_bios->fw_info.pll_info.crystal_frequency, - &res_pool->ref_clocks.dccg_ref_clock_inKhz); - - (res_pool->hubbub->funcs->get_dchub_ref_freq)(res_pool->hubbub, - res_pool->ref_clocks.dccg_ref_clock_inKhz, - &res_pool->ref_clocks.dchub_ref_clock_inKhz); - } else { - // Not all ASICs have DCCG sw component - res_pool->ref_clocks.dccg_ref_clock_inKhz = - res_pool->ref_clocks.xtalin_clock_inKhz; - res_pool->ref_clocks.dchub_ref_clock_inKhz = - res_pool->ref_clocks.xtalin_clock_inKhz; - } - } else - ASSERT_CRITICAL(false); - - for (i = 0; i < dc->link_count; i++) { - /* Power up AND update implementation according to the - * required signal (which may be different from the - * default signal on connector). - */ - struct dc_link *link = dc->links[i]; - - link->link_enc->funcs->hw_init(link->link_enc); - - /* Check for enabled DIG to identify enabled display */ - if (link->link_enc->funcs->is_dig_enabled && - link->link_enc->funcs->is_dig_enabled(link->link_enc)) { - link->link_status.link_active = true; - link->phy_state.symclk_state = SYMCLK_ON_TX_ON; - if (link->link_enc->funcs->fec_is_active && - link->link_enc->funcs->fec_is_active(link->link_enc)) - link->fec_state = dc_link_fec_enabled; - } - } - - /* enable_power_gating_plane before dsc_pg_control because - * FORCEON = 1 with hw default value on bootup, resume from s3 - */ - if (hws->funcs.enable_power_gating_plane) - hws->funcs.enable_power_gating_plane(dc->hwseq, true); - - /* we want to turn off all dp displays before doing detection */ - dc->link_srv->blank_all_dp_displays(dc); - - /* If taking control over from VBIOS, we may want to optimize our first - * mode set, so we need to skip powering down pipes until we know which - * pipes we want to use. - * Otherwise, if taking control is not possible, we need to power - * everything down. - */ - if (dcb->funcs->is_accelerated_mode(dcb) || !dc->config.seamless_boot_edp_requested) { - /* Disable boot optimizations means power down everything including PHY, DIG, - * and OTG (i.e. the boot is not optimized because we do a full power down). - */ - if (dc->hwss.enable_accelerated_mode && dc->debug.disable_boot_optimizations) - dc->hwss.enable_accelerated_mode(dc, dc->current_state); - else - hws->funcs.init_pipes(dc, dc->current_state); - - if (dc->res_pool->hubbub->funcs->allow_self_refresh_control) - dc->res_pool->hubbub->funcs->allow_self_refresh_control(dc->res_pool->hubbub, - !dc->res_pool->hubbub->ctx->dc->debug.disable_stutter); - - dcn32_initialize_min_clocks(dc); - - /* On HW init, allow idle optimizations after pipes have been turned off. - * - * In certain D3 cases (i.e. BOCO / BOMACO) it's possible that hardware state - * is reset (i.e. not in idle at the time hw init is called), but software state - * still has idle_optimizations = true, so we must disable idle optimizations first - * (i.e. set false), then re-enable (set true). - */ - dc_allow_idle_optimizations(dc, false); - dc_allow_idle_optimizations(dc, true); - } - - /* 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 (!dc->config.seamless_boot_edp_requested) { - struct dc_link *edp_links[MAX_NUM_EDP]; - struct dc_link *edp_link; - - dc_get_edp_links(dc, edp_links, &edp_num); - if (edp_num) { - for (i = 0; i < edp_num; i++) { - edp_link = edp_links[i]; - if (edp_link->link_enc->funcs->is_dig_enabled && - edp_link->link_enc->funcs->is_dig_enabled(edp_link->link_enc) && - dc->hwss.edp_backlight_control && - dc->hwss.power_down && - dc->hwss.edp_power_control) { - dc->hwss.edp_backlight_control(edp_link, false); - dc->hwss.power_down(dc); - dc->hwss.edp_power_control(edp_link, false); - } - } - } else { - for (i = 0; i < dc->link_count; i++) { - struct dc_link *link = dc->links[i]; - - if (link->link_enc->funcs->is_dig_enabled && - link->link_enc->funcs->is_dig_enabled(link->link_enc) && - dc->hwss.power_down) { - dc->hwss.power_down(dc); - break; - } - - } - } - } - - for (i = 0; i < res_pool->audio_count; i++) { - struct audio *audio = res_pool->audios[i]; - - audio->funcs->hw_init(audio); - } - - for (i = 0; i < dc->link_count; i++) { - struct dc_link *link = dc->links[i]; - - if (link->panel_cntl) - backlight = link->panel_cntl->funcs->hw_init(link->panel_cntl); - } - - for (i = 0; i < dc->res_pool->pipe_count; i++) { - if (abms[i] != NULL && abms[i]->funcs != NULL) - abms[i]->funcs->abm_init(abms[i], backlight); - } - - /* power AFMT HDMI memory TODO: may move to dis/en output save power*/ - REG_WRITE(DIO_MEM_PWR_CTRL, 0); - - if (!dc->debug.disable_clock_gate) { - /* enable all DCN clock gating */ - REG_WRITE(DCCG_GATE_DISABLE_CNTL, 0); - - REG_WRITE(DCCG_GATE_DISABLE_CNTL2, 0); - - REG_UPDATE(DCFCLK_CNTL, DCFCLK_GATE_DIS, 0); - } - - if (!dcb->funcs->is_accelerated_mode(dcb) && dc->res_pool->hubbub->funcs->init_watermarks) - dc->res_pool->hubbub->funcs->init_watermarks(dc->res_pool->hubbub); - - if (dc->clk_mgr->funcs->notify_wm_ranges) - dc->clk_mgr->funcs->notify_wm_ranges(dc->clk_mgr); - - if (dc->clk_mgr->funcs->set_hard_max_memclk && !dc->clk_mgr->dc_mode_softmax_enabled) - dc->clk_mgr->funcs->set_hard_max_memclk(dc->clk_mgr); - - if (dc->res_pool->hubbub->funcs->force_pstate_change_control) - dc->res_pool->hubbub->funcs->force_pstate_change_control( - dc->res_pool->hubbub, false, false); - - if (dc->res_pool->hubbub->funcs->init_crb) - dc->res_pool->hubbub->funcs->init_crb(dc->res_pool->hubbub); - - if (dc->res_pool->hubbub->funcs->set_request_limit && dc->config.sdpif_request_limit_words_per_umc > 0) - dc->res_pool->hubbub->funcs->set_request_limit(dc->res_pool->hubbub, dc->ctx->dc_bios->vram_info.num_chans, dc->config.sdpif_request_limit_words_per_umc); - - // Get DMCUB capabilities - if (dc->ctx->dmub_srv) { - dc_dmub_srv_query_caps_cmd(dc->ctx->dmub_srv); - dc->caps.dmub_caps.psr = dc->ctx->dmub_srv->dmub->feature_caps.psr; - dc->caps.dmub_caps.subvp_psr = dc->ctx->dmub_srv->dmub->feature_caps.subvp_psr_support; - dc->caps.dmub_caps.gecc_enable = dc->ctx->dmub_srv->dmub->feature_caps.gecc_enable; - dc->caps.dmub_caps.mclk_sw = dc->ctx->dmub_srv->dmub->feature_caps.fw_assisted_mclk_switch; - } -} - -static int calc_mpc_flow_ctrl_cnt(const struct dc_stream_state *stream, - int opp_cnt) -{ - bool hblank_halved = optc2_is_two_pixels_per_containter(&stream->timing); - int flow_ctrl_cnt; - - if (opp_cnt >= 2) - hblank_halved = true; - - flow_ctrl_cnt = stream->timing.h_total - stream->timing.h_addressable - - stream->timing.h_border_left - - stream->timing.h_border_right; - - if (hblank_halved) - flow_ctrl_cnt /= 2; - - /* ODM combine 4:1 case */ - if (opp_cnt == 4) - flow_ctrl_cnt /= 2; - - return flow_ctrl_cnt; -} - -static void update_dsc_on_stream(struct pipe_ctx *pipe_ctx, bool enable) -{ - struct display_stream_compressor *dsc = pipe_ctx->stream_res.dsc; - struct dc_stream_state *stream = pipe_ctx->stream; - struct pipe_ctx *odm_pipe; - int opp_cnt = 1; - - ASSERT(dsc); - for (odm_pipe = pipe_ctx->next_odm_pipe; odm_pipe; odm_pipe = odm_pipe->next_odm_pipe) - opp_cnt++; - - if (enable) { - struct dsc_config dsc_cfg; - struct dsc_optc_config dsc_optc_cfg; - enum optc_dsc_mode optc_dsc_mode; - - /* Enable DSC hw block */ - dsc_cfg.pic_width = (stream->timing.h_addressable + stream->timing.h_border_left + stream->timing.h_border_right) / opp_cnt; - dsc_cfg.pic_height = stream->timing.v_addressable + stream->timing.v_border_top + stream->timing.v_border_bottom; - dsc_cfg.pixel_encoding = stream->timing.pixel_encoding; - dsc_cfg.color_depth = stream->timing.display_color_depth; - dsc_cfg.is_odm = pipe_ctx->next_odm_pipe ? true : false; - dsc_cfg.dc_dsc_cfg = stream->timing.dsc_cfg; - ASSERT(dsc_cfg.dc_dsc_cfg.num_slices_h % opp_cnt == 0); - dsc_cfg.dc_dsc_cfg.num_slices_h /= opp_cnt; - - dsc->funcs->dsc_set_config(dsc, &dsc_cfg, &dsc_optc_cfg); - dsc->funcs->dsc_enable(dsc, pipe_ctx->stream_res.opp->inst); - for (odm_pipe = pipe_ctx->next_odm_pipe; odm_pipe; odm_pipe = odm_pipe->next_odm_pipe) { - struct display_stream_compressor *odm_dsc = odm_pipe->stream_res.dsc; - - ASSERT(odm_dsc); - odm_dsc->funcs->dsc_set_config(odm_dsc, &dsc_cfg, &dsc_optc_cfg); - odm_dsc->funcs->dsc_enable(odm_dsc, odm_pipe->stream_res.opp->inst); - } - dsc_cfg.dc_dsc_cfg.num_slices_h *= opp_cnt; - dsc_cfg.pic_width *= opp_cnt; - - optc_dsc_mode = dsc_optc_cfg.is_pixel_format_444 ? OPTC_DSC_ENABLED_444 : OPTC_DSC_ENABLED_NATIVE_SUBSAMPLED; - - /* Enable DSC in OPTC */ - DC_LOG_DSC("Setting optc DSC config for tg instance %d:", pipe_ctx->stream_res.tg->inst); - pipe_ctx->stream_res.tg->funcs->set_dsc_config(pipe_ctx->stream_res.tg, - optc_dsc_mode, - dsc_optc_cfg.bytes_per_pixel, - dsc_optc_cfg.slice_width); - } else { - /* disable DSC in OPTC */ - pipe_ctx->stream_res.tg->funcs->set_dsc_config( - pipe_ctx->stream_res.tg, - OPTC_DSC_DISABLED, 0, 0); - - /* disable DSC block */ - dsc->funcs->dsc_disable(pipe_ctx->stream_res.dsc); - for (odm_pipe = pipe_ctx->next_odm_pipe; odm_pipe; odm_pipe = odm_pipe->next_odm_pipe) { - ASSERT(odm_pipe->stream_res.dsc); - odm_pipe->stream_res.dsc->funcs->dsc_disable(odm_pipe->stream_res.dsc); - } - } -} - -/* -* Given any pipe_ctx, return the total ODM combine factor, and optionally return -* the OPPids which are used -* */ -static unsigned int get_odm_config(struct pipe_ctx *pipe_ctx, unsigned int *opp_instances) -{ - unsigned int opp_count = 1; - struct pipe_ctx *odm_pipe; - - /* First get to the top pipe */ - for (odm_pipe = pipe_ctx; odm_pipe->prev_odm_pipe; odm_pipe = odm_pipe->prev_odm_pipe) - ; - - /* First pipe is always used */ - if (opp_instances) - opp_instances[0] = odm_pipe->stream_res.opp->inst; - - /* Find and count odm pipes, if any */ - for (odm_pipe = odm_pipe->next_odm_pipe; odm_pipe; odm_pipe = odm_pipe->next_odm_pipe) { - if (opp_instances) - opp_instances[opp_count] = odm_pipe->stream_res.opp->inst; - opp_count++; - } - - return opp_count; -} - -void dcn32_update_odm(struct dc *dc, struct dc_state *context, struct pipe_ctx *pipe_ctx) -{ - struct pipe_ctx *odm_pipe; - int opp_cnt = 0; - int opp_inst[MAX_PIPES] = {0}; - bool rate_control_2x_pclk = (pipe_ctx->stream->timing.flags.INTERLACE || optc2_is_two_pixels_per_containter(&pipe_ctx->stream->timing)); - struct mpc_dwb_flow_control flow_control; - struct mpc *mpc = dc->res_pool->mpc; - int i; - - opp_cnt = get_odm_config(pipe_ctx, opp_inst); - - if (opp_cnt > 1) - pipe_ctx->stream_res.tg->funcs->set_odm_combine( - pipe_ctx->stream_res.tg, - opp_inst, opp_cnt, - &pipe_ctx->stream->timing); - else - pipe_ctx->stream_res.tg->funcs->set_odm_bypass( - pipe_ctx->stream_res.tg, &pipe_ctx->stream->timing); - - rate_control_2x_pclk = rate_control_2x_pclk || opp_cnt > 1; - flow_control.flow_ctrl_mode = 0; - flow_control.flow_ctrl_cnt0 = 0x80; - flow_control.flow_ctrl_cnt1 = calc_mpc_flow_ctrl_cnt(pipe_ctx->stream, opp_cnt); - if (mpc->funcs->set_out_rate_control) { - for (i = 0; i < opp_cnt; ++i) { - mpc->funcs->set_out_rate_control( - mpc, opp_inst[i], - true, - rate_control_2x_pclk, - &flow_control); - } - } - - for (odm_pipe = pipe_ctx->next_odm_pipe; odm_pipe; odm_pipe = odm_pipe->next_odm_pipe) { - odm_pipe->stream_res.opp->funcs->opp_pipe_clock_control( - odm_pipe->stream_res.opp, - true); - } - - if (pipe_ctx->stream_res.dsc) { - struct pipe_ctx *current_pipe_ctx = &dc->current_state->res_ctx.pipe_ctx[pipe_ctx->pipe_idx]; - - update_dsc_on_stream(pipe_ctx, pipe_ctx->stream->timing.flags.DSC); - - /* Check if no longer using pipe for ODM, then need to disconnect DSC for that pipe */ - if (!pipe_ctx->next_odm_pipe && current_pipe_ctx->next_odm_pipe && - current_pipe_ctx->next_odm_pipe->stream_res.dsc) { - struct display_stream_compressor *dsc = current_pipe_ctx->next_odm_pipe->stream_res.dsc; - /* disconnect DSC block from stream */ - dsc->funcs->dsc_disconnect(dsc); - } - } -} - -unsigned int dcn32_calculate_dccg_k1_k2_values(struct pipe_ctx *pipe_ctx, unsigned int *k1_div, unsigned int *k2_div) -{ - struct dc_stream_state *stream = pipe_ctx->stream; - unsigned int odm_combine_factor = 0; - bool two_pix_per_container = false; - - two_pix_per_container = optc2_is_two_pixels_per_containter(&stream->timing); - odm_combine_factor = get_odm_config(pipe_ctx, NULL); - - if (stream->ctx->dc->link_srv->dp_is_128b_132b_signal(pipe_ctx)) { - *k1_div = PIXEL_RATE_DIV_BY_1; - *k2_div = PIXEL_RATE_DIV_BY_1; - } else if (dc_is_hdmi_tmds_signal(stream->signal) || dc_is_dvi_signal(stream->signal)) { - *k1_div = PIXEL_RATE_DIV_BY_1; - if (stream->timing.pixel_encoding == PIXEL_ENCODING_YCBCR420) - *k2_div = PIXEL_RATE_DIV_BY_2; - else - *k2_div = PIXEL_RATE_DIV_BY_4; - } else if (dc_is_dp_signal(stream->signal) || dc_is_virtual_signal(stream->signal)) { - if (two_pix_per_container) { - *k1_div = PIXEL_RATE_DIV_BY_1; - *k2_div = PIXEL_RATE_DIV_BY_2; - } else { - *k1_div = PIXEL_RATE_DIV_BY_1; - *k2_div = PIXEL_RATE_DIV_BY_4; - if ((odm_combine_factor == 2) || dcn32_is_dp_dig_pixel_rate_div_policy(pipe_ctx)) - *k2_div = PIXEL_RATE_DIV_BY_2; - } - } - - if ((*k1_div == PIXEL_RATE_DIV_NA) && (*k2_div == PIXEL_RATE_DIV_NA)) - ASSERT(false); - - return odm_combine_factor; -} - -void dcn32_set_pixels_per_cycle(struct pipe_ctx *pipe_ctx) -{ - uint32_t pix_per_cycle = 1; - uint32_t odm_combine_factor = 1; - - if (!pipe_ctx || !pipe_ctx->stream || !pipe_ctx->stream_res.stream_enc) - return; - - odm_combine_factor = get_odm_config(pipe_ctx, NULL); - if (optc2_is_two_pixels_per_containter(&pipe_ctx->stream->timing) || odm_combine_factor > 1 - || dcn32_is_dp_dig_pixel_rate_div_policy(pipe_ctx)) - pix_per_cycle = 2; - - if (pipe_ctx->stream_res.stream_enc->funcs->set_input_mode) - pipe_ctx->stream_res.stream_enc->funcs->set_input_mode(pipe_ctx->stream_res.stream_enc, - pix_per_cycle); -} - -void dcn32_resync_fifo_dccg_dio(struct dce_hwseq *hws, struct dc *dc, struct dc_state *context) -{ - unsigned int i; - struct pipe_ctx *pipe = NULL; - bool otg_disabled[MAX_PIPES] = {false}; - - for (i = 0; i < dc->res_pool->pipe_count; i++) { - pipe = &dc->current_state->res_ctx.pipe_ctx[i]; - - if (!resource_is_pipe_type(pipe, OTG_MASTER)) - continue; - - if ((pipe->stream->dpms_off || dc_is_virtual_signal(pipe->stream->signal)) - && pipe->stream->mall_stream_config.type != SUBVP_PHANTOM) { - pipe->stream_res.tg->funcs->disable_crtc(pipe->stream_res.tg); - reset_sync_context_for_pipe(dc, context, i); - otg_disabled[i] = true; - } - } - - hws->ctx->dc->res_pool->dccg->funcs->trigger_dio_fifo_resync(hws->ctx->dc->res_pool->dccg); - - for (i = 0; i < dc->res_pool->pipe_count; i++) { - pipe = &dc->current_state->res_ctx.pipe_ctx[i]; - - if (otg_disabled[i]) - pipe->stream_res.tg->funcs->enable_crtc(pipe->stream_res.tg); - } -} - -void dcn32_unblank_stream(struct pipe_ctx *pipe_ctx, - struct dc_link_settings *link_settings) -{ - struct encoder_unblank_param params = {0}; - struct dc_stream_state *stream = pipe_ctx->stream; - struct dc_link *link = stream->link; - struct dce_hwseq *hws = link->dc->hwseq; - struct pipe_ctx *odm_pipe; - uint32_t pix_per_cycle = 1; - - params.opp_cnt = 1; - for (odm_pipe = pipe_ctx->next_odm_pipe; odm_pipe; odm_pipe = odm_pipe->next_odm_pipe) - params.opp_cnt++; - - /* only 3 items below are used by unblank */ - params.timing = pipe_ctx->stream->timing; - - params.link_settings.link_rate = link_settings->link_rate; - - if (link->dc->link_srv->dp_is_128b_132b_signal(pipe_ctx)) { - /* TODO - DP2.0 HW: Set ODM mode in dp hpo encoder here */ - pipe_ctx->stream_res.hpo_dp_stream_enc->funcs->dp_unblank( - pipe_ctx->stream_res.hpo_dp_stream_enc, - pipe_ctx->stream_res.tg->inst); - } else if (dc_is_dp_signal(pipe_ctx->stream->signal)) { - if (optc2_is_two_pixels_per_containter(&stream->timing) || params.opp_cnt > 1 - || dcn32_is_dp_dig_pixel_rate_div_policy(pipe_ctx)) { - params.timing.pix_clk_100hz /= 2; - pix_per_cycle = 2; - } - pipe_ctx->stream_res.stream_enc->funcs->dp_set_odm_combine( - pipe_ctx->stream_res.stream_enc, pix_per_cycle > 1); - pipe_ctx->stream_res.stream_enc->funcs->dp_unblank(link, pipe_ctx->stream_res.stream_enc, ¶ms); - } - - if (link->local_sink && link->local_sink->sink_signal == SIGNAL_TYPE_EDP) - hws->funcs.edp_backlight_control(link, true); -} - -bool dcn32_is_dp_dig_pixel_rate_div_policy(struct pipe_ctx *pipe_ctx) -{ - struct dc *dc = pipe_ctx->stream->ctx->dc; - - if (!is_h_timing_divisible_by_2(pipe_ctx->stream)) - return false; - - if (dc_is_dp_signal(pipe_ctx->stream->signal) && !dc->link_srv->dp_is_128b_132b_signal(pipe_ctx) && - dc->debug.enable_dp_dig_pixel_rate_div_policy) - return true; - return false; -} - -static void apply_symclk_on_tx_off_wa(struct dc_link *link) -{ - /* There are use cases where SYMCLK is referenced by OTG. For instance - * for TMDS signal, OTG relies SYMCLK even if TX video output is off. - * However current link interface will power off PHY when disabling link - * output. This will turn off SYMCLK generated by PHY. The workaround is - * to identify such case where SYMCLK is still in use by OTG when we - * power off PHY. When this is detected, we will temporarily power PHY - * back on and move PHY's SYMCLK state to SYMCLK_ON_TX_OFF by calling - * program_pix_clk interface. When OTG is disabled, we will then power - * off PHY by calling disable link output again. - * - * In future dcn generations, we plan to rework transmitter control - * interface so that we could have an option to set SYMCLK ON TX OFF - * state in one step without this workaround - */ - - struct dc *dc = link->ctx->dc; - struct pipe_ctx *pipe_ctx = NULL; - uint8_t i; - - if (link->phy_state.symclk_ref_cnts.otg > 0) { - for (i = 0; i < MAX_PIPES; i++) { - pipe_ctx = &dc->current_state->res_ctx.pipe_ctx[i]; - if (resource_is_pipe_type(pipe_ctx, OPP_HEAD) && pipe_ctx->stream->link == link) { - pipe_ctx->clock_source->funcs->program_pix_clk( - pipe_ctx->clock_source, - &pipe_ctx->stream_res.pix_clk_params, - dc->link_srv->dp_get_encoding_format( - &pipe_ctx->link_config.dp_link_settings), - &pipe_ctx->pll_settings); - link->phy_state.symclk_state = SYMCLK_ON_TX_OFF; - break; - } - } - } -} - -void dcn32_disable_link_output(struct dc_link *link, - const struct link_resource *link_res, - enum signal_type signal) -{ - struct dc *dc = link->ctx->dc; - const struct link_hwss *link_hwss = get_link_hwss(link, link_res); - struct dmcu *dmcu = dc->res_pool->dmcu; - - if (signal == SIGNAL_TYPE_EDP && - link->dc->hwss.edp_backlight_control) - link->dc->hwss.edp_backlight_control(link, false); - else if (dmcu != NULL && dmcu->funcs->lock_phy) - dmcu->funcs->lock_phy(dmcu); - - link_hwss->disable_link_output(link, link_res, signal); - link->phy_state.symclk_state = SYMCLK_OFF_TX_OFF; - - if (signal == SIGNAL_TYPE_EDP && - link->dc->hwss.edp_backlight_control) - link->dc->hwss.edp_power_control(link, false); - else if (dmcu != NULL && dmcu->funcs->lock_phy) - dmcu->funcs->unlock_phy(dmcu); - - dc->link_srv->dp_trace_source_sequence(link, DPCD_SOURCE_SEQ_AFTER_DISABLE_LINK_PHY); - - apply_symclk_on_tx_off_wa(link); -} - -/* For SubVP the main pipe can have a viewport position change - * without a full update. In this case we must also update the - * viewport positions for the phantom pipe accordingly. - */ -void dcn32_update_phantom_vp_position(struct dc *dc, - struct dc_state *context, - struct pipe_ctx *phantom_pipe) -{ - uint32_t i; - struct dc_plane_state *phantom_plane = phantom_pipe->plane_state; - - for (i = 0; i < dc->res_pool->pipe_count; i++) { - struct pipe_ctx *pipe = &context->res_ctx.pipe_ctx[i]; - - if (pipe->stream && pipe->stream->mall_stream_config.type == SUBVP_MAIN && - pipe->stream->mall_stream_config.paired_stream == phantom_pipe->stream) { - if (pipe->plane_state && pipe->plane_state->update_flags.bits.position_change) { - - phantom_plane->src_rect.x = pipe->plane_state->src_rect.x; - phantom_plane->src_rect.y = pipe->plane_state->src_rect.y; - phantom_plane->clip_rect.x = pipe->plane_state->clip_rect.x; - phantom_plane->dst_rect.x = pipe->plane_state->dst_rect.x; - phantom_plane->dst_rect.y = pipe->plane_state->dst_rect.y; - - phantom_pipe->plane_state->update_flags.bits.position_change = 1; - resource_build_scaling_params(phantom_pipe); - return; - } - } - } -} - -/* Treat the phantom pipe as if it needs to be fully enabled. - * If the pipe was previously in use but not phantom, it would - * have been disabled earlier in the sequence so we need to run - * the full enable sequence. - */ -void dcn32_apply_update_flags_for_phantom(struct pipe_ctx *phantom_pipe) -{ - phantom_pipe->update_flags.raw = 0; - if (phantom_pipe->stream && phantom_pipe->stream->mall_stream_config.type == SUBVP_PHANTOM) { - if (resource_is_pipe_type(phantom_pipe, DPP_PIPE)) { - phantom_pipe->update_flags.bits.enable = 1; - phantom_pipe->update_flags.bits.mpcc = 1; - phantom_pipe->update_flags.bits.dppclk = 1; - phantom_pipe->update_flags.bits.hubp_interdependent = 1; - phantom_pipe->update_flags.bits.hubp_rq_dlg_ttu = 1; - phantom_pipe->update_flags.bits.gamut_remap = 1; - phantom_pipe->update_flags.bits.scaler = 1; - phantom_pipe->update_flags.bits.viewport = 1; - phantom_pipe->update_flags.bits.det_size = 1; - if (resource_is_pipe_type(phantom_pipe, OTG_MASTER)) { - phantom_pipe->update_flags.bits.odm = 1; - phantom_pipe->update_flags.bits.global_sync = 1; - } - } - } -} - -bool dcn32_dsc_pg_status( - struct dce_hwseq *hws, - unsigned int dsc_inst) -{ - uint32_t pwr_status = 0; - - switch (dsc_inst) { - case 0: /* DSC0 */ - REG_GET(DOMAIN16_PG_STATUS, - DOMAIN_PGFSM_PWR_STATUS, &pwr_status); - break; - case 1: /* DSC1 */ - - REG_GET(DOMAIN17_PG_STATUS, - DOMAIN_PGFSM_PWR_STATUS, &pwr_status); - break; - case 2: /* DSC2 */ - REG_GET(DOMAIN18_PG_STATUS, - DOMAIN_PGFSM_PWR_STATUS, &pwr_status); - break; - case 3: /* DSC3 */ - REG_GET(DOMAIN19_PG_STATUS, - DOMAIN_PGFSM_PWR_STATUS, &pwr_status); - break; - default: - BREAK_TO_DEBUGGER(); - break; - } - - return pwr_status == 0; -} - -void dcn32_update_dsc_pg(struct dc *dc, - struct dc_state *context, - bool safe_to_disable) -{ - struct dce_hwseq *hws = dc->hwseq; - int i; - - for (i = 0; i < dc->res_pool->res_cap->num_dsc; i++) { - struct display_stream_compressor *dsc = dc->res_pool->dscs[i]; - bool is_dsc_ungated = hws->funcs.dsc_pg_status(hws, dsc->inst); - - if (context->res_ctx.is_dsc_acquired[i]) { - if (!is_dsc_ungated) { - hws->funcs.dsc_pg_control(hws, dsc->inst, true); - } - } else if (safe_to_disable) { - if (is_dsc_ungated) { - hws->funcs.dsc_pg_control(hws, dsc->inst, false); - } - } - } -} - -void dcn32_enable_phantom_streams(struct dc *dc, struct dc_state *context) -{ - unsigned int i; - - for (i = 0; i < dc->res_pool->pipe_count; i++) { - struct pipe_ctx *pipe = &context->res_ctx.pipe_ctx[i]; - struct pipe_ctx *old_pipe = &dc->current_state->res_ctx.pipe_ctx[i]; - - /* If an active, non-phantom pipe is being transitioned into a phantom - * pipe, wait for the double buffer update to complete first before we do - * ANY phantom pipe programming. - */ - if (pipe->stream && pipe->stream->mall_stream_config.type == SUBVP_PHANTOM && - old_pipe->stream && old_pipe->stream->mall_stream_config.type != SUBVP_PHANTOM) { - old_pipe->stream_res.tg->funcs->wait_for_state( - old_pipe->stream_res.tg, - CRTC_STATE_VBLANK); - old_pipe->stream_res.tg->funcs->wait_for_state( - old_pipe->stream_res.tg, - CRTC_STATE_VACTIVE); - } - } - for (i = 0; i < dc->res_pool->pipe_count; i++) { - struct pipe_ctx *new_pipe = &context->res_ctx.pipe_ctx[i]; - - if (new_pipe->stream && new_pipe->stream->mall_stream_config.type == SUBVP_PHANTOM) { - // If old context or new context has phantom pipes, apply - // the phantom timings now. We can't change the phantom - // pipe configuration safely without driver acquiring - // the DMCUB lock first. - dc->hwss.apply_ctx_to_hw(dc, context); - break; - } - } -} - -/* Blank pixel data during initialization */ -void dcn32_init_blank( - struct dc *dc, - struct timing_generator *tg) -{ - struct dce_hwseq *hws = dc->hwseq; - enum dc_color_space color_space; - struct tg_color black_color = {0}; - struct output_pixel_processor *opp = NULL; - struct output_pixel_processor *bottom_opp = NULL; - uint32_t num_opps, opp_id_src0, opp_id_src1; - uint32_t otg_active_width, otg_active_height; - uint32_t i; - - /* program opp dpg blank color */ - color_space = COLOR_SPACE_SRGB; - color_space_to_black_color(dc, color_space, &black_color); - - /* get the OTG active size */ - tg->funcs->get_otg_active_size(tg, - &otg_active_width, - &otg_active_height); - - /* get the OPTC source */ - tg->funcs->get_optc_source(tg, &num_opps, &opp_id_src0, &opp_id_src1); - - if (opp_id_src0 >= dc->res_pool->res_cap->num_opp) { - ASSERT(false); - return; - } - - for (i = 0; i < dc->res_pool->res_cap->num_opp; i++) { - if (dc->res_pool->opps[i] != NULL && dc->res_pool->opps[i]->inst == opp_id_src0) { - opp = dc->res_pool->opps[i]; - break; - } - } - - if (num_opps == 2) { - otg_active_width = otg_active_width / 2; - - if (opp_id_src1 >= dc->res_pool->res_cap->num_opp) { - ASSERT(false); - return; - } - for (i = 0; i < dc->res_pool->res_cap->num_opp; i++) { - if (dc->res_pool->opps[i] != NULL && dc->res_pool->opps[i]->inst == opp_id_src1) { - bottom_opp = dc->res_pool->opps[i]; - break; - } - } - } - - if (opp && opp->funcs->opp_set_disp_pattern_generator) - opp->funcs->opp_set_disp_pattern_generator( - opp, - CONTROLLER_DP_TEST_PATTERN_SOLID_COLOR, - CONTROLLER_DP_COLOR_SPACE_UDEFINED, - COLOR_DEPTH_UNDEFINED, - &black_color, - otg_active_width, - otg_active_height, - 0); - - if (num_opps == 2) { - if (bottom_opp && bottom_opp->funcs->opp_set_disp_pattern_generator) { - bottom_opp->funcs->opp_set_disp_pattern_generator( - bottom_opp, - CONTROLLER_DP_TEST_PATTERN_SOLID_COLOR, - CONTROLLER_DP_COLOR_SPACE_UDEFINED, - COLOR_DEPTH_UNDEFINED, - &black_color, - otg_active_width, - otg_active_height, - 0); - hws->funcs.wait_for_blank_complete(bottom_opp); - } - } - - if (opp) - hws->funcs.wait_for_blank_complete(opp); -} - -void dcn32_blank_phantom(struct dc *dc, - struct timing_generator *tg, - int width, - int height) -{ - struct dce_hwseq *hws = dc->hwseq; - enum dc_color_space color_space; - struct tg_color black_color = {0}; - struct output_pixel_processor *opp = NULL; - uint32_t num_opps, opp_id_src0, opp_id_src1; - uint32_t otg_active_width, otg_active_height; - uint32_t i; - - /* program opp dpg blank color */ - color_space = COLOR_SPACE_SRGB; - color_space_to_black_color(dc, color_space, &black_color); - - otg_active_width = width; - otg_active_height = height; - - /* get the OPTC source */ - tg->funcs->get_optc_source(tg, &num_opps, &opp_id_src0, &opp_id_src1); - ASSERT(opp_id_src0 < dc->res_pool->res_cap->num_opp); - - for (i = 0; i < dc->res_pool->res_cap->num_opp; i++) { - if (dc->res_pool->opps[i] != NULL && dc->res_pool->opps[i]->inst == opp_id_src0) { - opp = dc->res_pool->opps[i]; - break; - } - } - - if (opp && opp->funcs->opp_set_disp_pattern_generator) - opp->funcs->opp_set_disp_pattern_generator( - opp, - CONTROLLER_DP_TEST_PATTERN_SOLID_COLOR, - CONTROLLER_DP_COLOR_SPACE_UDEFINED, - COLOR_DEPTH_UNDEFINED, - &black_color, - otg_active_width, - otg_active_height, - 0); - - if (tg->funcs->is_tg_enabled(tg)) - hws->funcs.wait_for_blank_complete(opp); -} - -bool dcn32_is_pipe_topology_transition_seamless(struct dc *dc, - const struct dc_state *cur_ctx, - const struct dc_state *new_ctx) -{ - int i; - const struct pipe_ctx *cur_pipe, *new_pipe; - bool is_seamless = true; - - for (i = 0; i < dc->res_pool->pipe_count; i++) { - cur_pipe = &cur_ctx->res_ctx.pipe_ctx[i]; - new_pipe = &new_ctx->res_ctx.pipe_ctx[i]; - - if (resource_is_pipe_type(cur_pipe, FREE_PIPE) || - resource_is_pipe_type(new_pipe, FREE_PIPE)) - /* adding or removing free pipes is always seamless */ - continue; - else if (resource_is_pipe_type(cur_pipe, OTG_MASTER)) { - if (resource_is_pipe_type(new_pipe, OTG_MASTER)) - if (cur_pipe->stream->stream_id == new_pipe->stream->stream_id) - /* OTG master with the same stream is seamless */ - continue; - } else if (resource_is_pipe_type(cur_pipe, OPP_HEAD)) { - if (resource_is_pipe_type(new_pipe, OPP_HEAD)) { - if (cur_pipe->stream_res.tg == new_pipe->stream_res.tg) - /* - * OPP heads sharing the same timing - * generator is seamless - */ - continue; - } - } else if (resource_is_pipe_type(cur_pipe, DPP_PIPE)) { - if (resource_is_pipe_type(new_pipe, DPP_PIPE)) { - if (cur_pipe->stream_res.opp == new_pipe->stream_res.opp) - /* - * DPP pipes sharing the same OPP head is - * seamless - */ - continue; - } - } - - /* - * This pipe's transition doesn't fall under any seamless - * conditions - */ - is_seamless = false; - break; - } - - return is_seamless; -} diff --git a/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_hwseq.h b/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_hwseq.h deleted file mode 100644 index 9992e40acd..0000000000 --- a/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_hwseq.h +++ /dev/null @@ -1,127 +0,0 @@ -/* -* Copyright 2016 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 __DC_HWSS_DCN32_H__ -#define __DC_HWSS_DCN32_H__ - -#include "hw_sequencer_private.h" - -struct dc; - -void dcn32_dsc_pg_control( - struct dce_hwseq *hws, - unsigned int dsc_inst, - bool power_on); - -void dcn32_enable_power_gating_plane( - struct dce_hwseq *hws, - bool enable); - -void dcn32_hubp_pg_control(struct dce_hwseq *hws, unsigned int hubp_inst, bool power_on); - -bool dcn32_apply_idle_power_optimizations(struct dc *dc, bool enable); - -void dcn32_cab_for_ss_control(struct dc *dc, bool enable); - -void dcn32_commit_subvp_config(struct dc *dc, struct dc_state *context); - -bool dcn32_set_mcm_luts(struct pipe_ctx *pipe_ctx, - const struct dc_plane_state *plane_state); - -bool dcn32_set_input_transfer_func(struct dc *dc, - struct pipe_ctx *pipe_ctx, - const struct dc_plane_state *plane_state); - -bool dcn32_set_mpc_shaper_3dlut( - struct pipe_ctx *pipe_ctx, const struct dc_stream_state *stream); - -bool dcn32_set_output_transfer_func(struct dc *dc, - struct pipe_ctx *pipe_ctx, - const struct dc_stream_state *stream); - -void dcn32_init_hw(struct dc *dc); - -void dcn32_program_mall_pipe_config(struct dc *dc, struct dc_state *context); - -void dcn32_update_mall_sel(struct dc *dc, struct dc_state *context); - -void dcn32_update_force_pstate(struct dc *dc, struct dc_state *context); - -void dcn32_update_odm(struct dc *dc, struct dc_state *context, struct pipe_ctx *pipe_ctx); - -unsigned int dcn32_calculate_dccg_k1_k2_values(struct pipe_ctx *pipe_ctx, unsigned int *k1_div, unsigned int *k2_div); - -void dcn32_set_pixels_per_cycle(struct pipe_ctx *pipe_ctx); - -void dcn32_resync_fifo_dccg_dio(struct dce_hwseq *hws, struct dc *dc, struct dc_state *context); - -void dcn32_subvp_pipe_control_lock(struct dc *dc, - struct dc_state *context, - bool lock, - bool should_lock_all_pipes, - struct pipe_ctx *top_pipe_to_program, - bool subvp_prev_use); - -void dcn32_subvp_pipe_control_lock_fast(union block_sequence_params *params); - -void dcn32_unblank_stream(struct pipe_ctx *pipe_ctx, - struct dc_link_settings *link_settings); - -bool dcn32_is_dp_dig_pixel_rate_div_policy(struct pipe_ctx *pipe_ctx); - -void dcn32_disable_link_output(struct dc_link *link, - const struct link_resource *link_res, - enum signal_type signal); - -void dcn32_update_phantom_vp_position(struct dc *dc, - struct dc_state *context, - struct pipe_ctx *phantom_pipe); - -void dcn32_apply_update_flags_for_phantom(struct pipe_ctx *phantom_pipe); - -bool dcn32_dsc_pg_status( - struct dce_hwseq *hws, - unsigned int dsc_inst); - -void dcn32_update_dsc_pg(struct dc *dc, - struct dc_state *context, - bool safe_to_disable); - -void dcn32_enable_phantom_streams(struct dc *dc, struct dc_state *context); - -void dcn32_init_blank( - struct dc *dc, - struct timing_generator *tg); - -void dcn32_blank_phantom(struct dc *dc, - struct timing_generator *tg, - int width, - int height); - -bool dcn32_is_pipe_topology_transition_seamless(struct dc *dc, - const struct dc_state *cur_ctx, - const struct dc_state *new_ctx); - -#endif /* __DC_HWSS_DCN32_H__ */ diff --git a/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_init.c b/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_init.c index 1edadff39a..427cfc8c24 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_init.c +++ b/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_init.c @@ -23,17 +23,17 @@ * */ -#include "dce110/dce110_hw_sequencer.h" -#include "dcn10/dcn10_hw_sequencer.h" +#include "dce110/dce110_hwseq.h" +#include "dcn10/dcn10_hwseq.h" #include "dcn20/dcn20_hwseq.h" #include "dcn21/dcn21_hwseq.h" #include "dcn30/dcn30_hwseq.h" #include "dcn31/dcn31_hwseq.h" -#include "dcn32_hwseq.h" +#include "dcn32/dcn32_hwseq.h" #include "dcn32_init.h" static const struct hw_sequencer_funcs dcn32_funcs = { - .program_gamut_remap = dcn10_program_gamut_remap, + .program_gamut_remap = dcn30_program_gamut_remap, .init_hw = dcn32_init_hw, .apply_ctx_to_hw = dce110_apply_ctx_to_hw, .apply_ctx_for_surface = NULL, @@ -60,7 +60,7 @@ static const struct hw_sequencer_funcs dcn32_funcs = { .pipe_control_lock = dcn20_pipe_control_lock, .interdependent_update_lock = dcn10_lock_all_pipes, .cursor_lock = dcn10_cursor_lock, - .prepare_bandwidth = dcn30_prepare_bandwidth, + .prepare_bandwidth = dcn32_prepare_bandwidth, .optimize_bandwidth = dcn20_optimize_bandwidth, .update_bandwidth = dcn20_update_bandwidth, .set_drr = dcn10_set_drr, diff --git a/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_mmhubbub.h b/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_mmhubbub.h index e460cf8d90..ef15b4f1f6 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_mmhubbub.h +++ b/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_mmhubbub.h @@ -43,8 +43,6 @@ SRI2(MCIF_WB_BUF_4_STATUS2, MCIF_WB, inst),\ SRI2(MCIF_WB_ARBITRATION_CONTROL, MCIF_WB, inst),\ SRI2(MCIF_WB_SCLK_CHANGE, MCIF_WB, inst),\ - SRI2(MCIF_WB_TEST_DEBUG_INDEX, MCIF_WB, inst),\ - SRI2(MCIF_WB_TEST_DEBUG_DATA, MCIF_WB, inst),\ SRI2(MCIF_WB_BUF_1_ADDR_Y, MCIF_WB, inst),\ SRI2(MCIF_WB_BUF_1_ADDR_C, MCIF_WB, inst),\ SRI2(MCIF_WB_BUF_2_ADDR_Y, MCIF_WB, inst),\ @@ -157,8 +155,6 @@ SF(MCIF_WB_ARBITRATION_CONTROL, MCIF_WB_CLIENT_ARBITRATION_SLICE, mask_sh),\ SF(MCIF_WB_ARBITRATION_CONTROL, MCIF_WB_TIME_PER_PIXEL, mask_sh),\ SF(MCIF_WB_SCLK_CHANGE, WM_CHANGE_ACK_FORCE_ON, mask_sh),\ - SF(MCIF_WB_TEST_DEBUG_INDEX, MCIF_WB_TEST_DEBUG_INDEX, mask_sh),\ - SF(MCIF_WB_TEST_DEBUG_DATA, MCIF_WB_TEST_DEBUG_DATA, mask_sh),\ SF(MCIF_WB_BUF_1_ADDR_Y, MCIF_WB_BUF_1_ADDR_Y, mask_sh),\ SF(MCIF_WB_BUF_1_ADDR_C, MCIF_WB_BUF_1_ADDR_C, mask_sh),\ SF(MCIF_WB_BUF_2_ADDR_Y, MCIF_WB_BUF_2_ADDR_Y, mask_sh),\ diff --git a/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_mpc.c b/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_mpc.c index 1d052f08af..994b21ed27 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_mpc.c +++ b/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_mpc.c @@ -237,16 +237,19 @@ void mpc32_program_post1dlut_pwl( REG_SET(MPCC_MCM_1DLUT_LUT_DATA[mpcc_id], 0, MPCC_MCM_1DLUT_LUT_DATA, rgb[i].red_reg); REG_SET(MPCC_MCM_1DLUT_LUT_DATA[mpcc_id], 0, MPCC_MCM_1DLUT_LUT_DATA, last_base_value_red); } else { + REG_SET(MPCC_MCM_1DLUT_LUT_INDEX[mpcc_id], 0, MPCC_MCM_1DLUT_LUT_INDEX, 0); REG_UPDATE(MPCC_MCM_1DLUT_LUT_CONTROL[mpcc_id], MPCC_MCM_1DLUT_LUT_WRITE_COLOR_MASK, 4); for (i = 0 ; i < num; i++) REG_SET(MPCC_MCM_1DLUT_LUT_DATA[mpcc_id], 0, MPCC_MCM_1DLUT_LUT_DATA, rgb[i].red_reg); REG_SET(MPCC_MCM_1DLUT_LUT_DATA[mpcc_id], 0, MPCC_MCM_1DLUT_LUT_DATA, last_base_value_red); + REG_SET(MPCC_MCM_1DLUT_LUT_INDEX[mpcc_id], 0, MPCC_MCM_1DLUT_LUT_INDEX, 0); REG_UPDATE(MPCC_MCM_1DLUT_LUT_CONTROL[mpcc_id], MPCC_MCM_1DLUT_LUT_WRITE_COLOR_MASK, 2); for (i = 0 ; i < num; i++) REG_SET(MPCC_MCM_1DLUT_LUT_DATA[mpcc_id], 0, MPCC_MCM_1DLUT_LUT_DATA, rgb[i].green_reg); REG_SET(MPCC_MCM_1DLUT_LUT_DATA[mpcc_id], 0, MPCC_MCM_1DLUT_LUT_DATA, last_base_value_green); + REG_SET(MPCC_MCM_1DLUT_LUT_INDEX[mpcc_id], 0, MPCC_MCM_1DLUT_LUT_INDEX, 0); REG_UPDATE(MPCC_MCM_1DLUT_LUT_CONTROL[mpcc_id], MPCC_MCM_1DLUT_LUT_WRITE_COLOR_MASK, 1); for (i = 0 ; i < num; i++) REG_SET(MPCC_MCM_1DLUT_LUT_DATA[mpcc_id], 0, MPCC_MCM_1DLUT_LUT_DATA, rgb[i].blue_reg); diff --git a/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_mpc.h b/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_mpc.h index 9ac584fa89..9622518826 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_mpc.h +++ b/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_mpc.h @@ -232,7 +232,6 @@ SF(MPCC_OGAM0_MPCC_OGAM_CONTROL, MPCC_OGAM_SELECT_CURRENT, mask_sh),\ SF(MPCC_OGAM0_MPCC_OGAM_LUT_CONTROL, MPCC_OGAM_LUT_WRITE_COLOR_MASK, mask_sh),\ SF(MPCC_OGAM0_MPCC_OGAM_LUT_CONTROL, MPCC_OGAM_LUT_READ_COLOR_SEL, mask_sh),\ - SF(MPCC_OGAM0_MPCC_OGAM_LUT_CONTROL, MPCC_OGAM_LUT_READ_DBG, mask_sh),\ SF(MPCC_OGAM0_MPCC_OGAM_LUT_CONTROL, MPCC_OGAM_LUT_HOST_SEL, mask_sh),\ SF(MPCC_OGAM0_MPCC_OGAM_LUT_CONTROL, MPCC_OGAM_LUT_CONFIG_MODE, mask_sh),\ SF(MPCC_OGAM0_MPCC_OGAM_LUT_DATA, MPCC_OGAM_LUT_DATA, mask_sh),\ @@ -276,7 +275,6 @@ SF(MPCC_MCM0_MPCC_MCM_1DLUT_LUT_DATA, MPCC_MCM_1DLUT_LUT_DATA, mask_sh),\ SF(MPCC_MCM0_MPCC_MCM_1DLUT_LUT_CONTROL, MPCC_MCM_1DLUT_LUT_WRITE_COLOR_MASK, mask_sh),\ SF(MPCC_MCM0_MPCC_MCM_1DLUT_LUT_CONTROL, MPCC_MCM_1DLUT_LUT_READ_COLOR_SEL, mask_sh),\ - SF(MPCC_MCM0_MPCC_MCM_1DLUT_LUT_CONTROL, MPCC_MCM_1DLUT_LUT_READ_DBG, mask_sh),\ SF(MPCC_MCM0_MPCC_MCM_1DLUT_LUT_CONTROL, MPCC_MCM_1DLUT_LUT_HOST_SEL, mask_sh),\ SF(MPCC_MCM0_MPCC_MCM_1DLUT_LUT_CONTROL, MPCC_MCM_1DLUT_LUT_CONFIG_MODE, mask_sh),\ SF(MPCC_MCM0_MPCC_MCM_1DLUT_RAMA_START_CNTL_B, MPCC_MCM_1DLUT_RAMA_EXP_REGION_START_B, mask_sh),\ diff --git a/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_optc.c b/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_optc.c index 8abb94f600..8234935433 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_optc.c +++ b/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_optc.c @@ -98,6 +98,30 @@ static void optc32_set_odm_combine(struct timing_generator *optc, int *opp_id, i optc1->opp_count = opp_cnt; } +void optc32_get_odm_combine_segments(struct timing_generator *tg, int *odm_combine_segments) +{ + struct optc *optc1 = DCN10TG_FROM_TG(tg); + int segments; + + REG_GET(OPTC_DATA_SOURCE_SELECT, OPTC_NUM_OF_INPUT_SEGMENT, &segments); + + switch (segments) { + case 0: + *odm_combine_segments = 1; + break; + case 1: + *odm_combine_segments = 2; + break; + case 3: + *odm_combine_segments = 4; + break; + /* 2 is reserved */ + case 2: + default: + *odm_combine_segments = -1; + } +} + void optc32_set_h_timing_div_manual_mode(struct timing_generator *optc, bool manual_mode) { struct optc *optc1 = DCN10TG_FROM_TG(optc); @@ -142,6 +166,16 @@ static bool optc32_disable_crtc(struct timing_generator *optc) { struct optc *optc1 = DCN10TG_FROM_TG(optc); + REG_UPDATE_5(OPTC_DATA_SOURCE_SELECT, + OPTC_SEG0_SRC_SEL, 0xf, + OPTC_SEG1_SRC_SEL, 0xf, + OPTC_SEG2_SRC_SEL, 0xf, + OPTC_SEG3_SRC_SEL, 0xf, + OPTC_NUM_OF_INPUT_SEGMENT, 0); + + REG_UPDATE(OPTC_MEMORY_CONFIG, + OPTC_MEM_SEL, 0); + /* disable otg request until end of the first line * in the vertical blank region */ @@ -174,10 +208,17 @@ static void optc32_disable_phantom_otg(struct timing_generator *optc) { struct optc *optc1 = DCN10TG_FROM_TG(optc); + REG_UPDATE_5(OPTC_DATA_SOURCE_SELECT, + OPTC_SEG0_SRC_SEL, 0xf, + OPTC_SEG1_SRC_SEL, 0xf, + OPTC_SEG2_SRC_SEL, 0xf, + OPTC_SEG3_SRC_SEL, 0xf, + OPTC_NUM_OF_INPUT_SEGMENT, 0); + REG_UPDATE(OTG_CONTROL, OTG_MASTER_EN, 0); } -static void optc32_set_odm_bypass(struct timing_generator *optc, +void optc32_set_odm_bypass(struct timing_generator *optc, const struct dc_crtc_timing *dc_crtc_timing) { struct optc *optc1 = DCN10TG_FROM_TG(optc); @@ -303,6 +344,7 @@ static struct timing_generator_funcs dcn32_tg_funcs = { .set_dwb_source = NULL, .set_odm_bypass = optc32_set_odm_bypass, .set_odm_combine = optc32_set_odm_combine, + .get_odm_combine_segments = optc32_get_odm_combine_segments, .set_h_timing_div_manual_mode = optc32_set_h_timing_div_manual_mode, .get_optc_source = optc2_get_optc_source, .set_out_mux = optc3_set_out_mux, diff --git a/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_optc.h b/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_optc.h index abf0121a10..8ce3b178ca 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_optc.h +++ b/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_optc.h @@ -180,5 +180,8 @@ void dcn32_timing_generator_init(struct optc *optc1); void optc32_set_h_timing_div_manual_mode(struct timing_generator *optc, bool manual_mode); +void optc32_get_odm_combine_segments(struct timing_generator *tg, int *odm_combine_segments); +void optc32_set_odm_bypass(struct timing_generator *optc, + const struct dc_crtc_timing *dc_crtc_timing); #endif /* __DC_OPTC_DCN32_H__ */ diff --git a/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_resource.c b/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_resource.c index f9d601c8c7..e940dd0f92 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_resource.c @@ -47,7 +47,7 @@ #include "dcn32/dcn32_optc.h" #include "dcn20/dcn20_hwseq.h" #include "dcn30/dcn30_hwseq.h" -#include "dce110/dce110_hw_sequencer.h" +#include "dce110/dce110_hwseq.h" #include "dcn30/dcn30_opp.h" #include "dcn20/dcn20_dsc.h" #include "dcn30/dcn30_vpg.h" @@ -89,6 +89,8 @@ #include "dcn20/dcn20_vmid.h" #include "dml/dcn32/dcn32_fpu.h" +#include "dml2/dml2_wrapper.h" + #define DC_LOGGER_INIT(logger) enum dcn32_clk_src_array_id { @@ -714,6 +716,7 @@ static const struct dc_debug_options debug_defaults_drv = { .use_max_lb = true, .force_disable_subvp = false, .exit_idle_opt_for_cursor_updates = true, + .using_dml2 = false, .enable_single_display_2to1_odm_policy = true, /* Must match enable_single_display_2to1_odm_policy to support dynamic ODM transitions*/ @@ -1805,9 +1808,7 @@ void dcn32_add_phantom_pipes(struct dc *dc, struct dc_state *context, } } -bool dcn32_validate_bandwidth(struct dc *dc, - struct dc_state *context, - bool fast_validate) +static bool dml1_validate(struct dc *dc, struct dc_state *context, bool fast_validate) { bool out = false; @@ -1885,6 +1886,19 @@ validate_out: return out; } +bool dcn32_validate_bandwidth(struct dc *dc, + struct dc_state *context, + bool fast_validate) +{ + bool out = false; + + if (dc->debug.using_dml2) + out = dml2_validate(dc, context, fast_validate); + else + out = dml1_validate(dc, context, fast_validate); + return out; +} + int dcn32_populate_dml_pipes_from_context( struct dc *dc, struct dc_state *context, display_e2e_pipe_params_st *pipes, @@ -1895,38 +1909,9 @@ int dcn32_populate_dml_pipes_from_context( struct pipe_ctx *pipe = NULL; bool subvp_in_use = false; struct dc_crtc_timing *timing; - bool vsr_odm_support = false; dcn20_populate_dml_pipes_from_context(dc, context, pipes, fast_validate); - /* Determine whether we will apply ODM 2to1 policy: - * Applies to single display and where the number of planes is less than 3. - * For 3 plane case ( 2 MPO planes ), we will not set the policy for the MPO pipes. - * - * Apply pipe split policy first so we can predict the pipe split correctly - * (dcn32_predict_pipe_split). - */ - for (i = 0, pipe_cnt = 0; i < dc->res_pool->pipe_count; i++) { - if (!res_ctx->pipe_ctx[i].stream) - continue; - pipe = &res_ctx->pipe_ctx[i]; - timing = &pipe->stream->timing; - - pipes[pipe_cnt].pipe.dest.odm_combine_policy = dm_odm_combine_policy_dal; - vsr_odm_support = (res_ctx->pipe_ctx[i].stream->src.width >= 5120 && - res_ctx->pipe_ctx[i].stream->src.width > res_ctx->pipe_ctx[i].stream->dst.width); - if (context->stream_count == 1 && - context->stream_status[0].plane_count == 1 && - !dc_is_hdmi_signal(res_ctx->pipe_ctx[i].stream->signal) && - is_h_timing_divisible_by_2(res_ctx->pipe_ctx[i].stream) && - pipe->stream->timing.pix_clk_100hz * 100 > DCN3_2_VMIN_DISPCLK_HZ && - dc->debug.enable_single_display_2to1_odm_policy && - !vsr_odm_support) { //excluding 2to1 ODM combine on >= 5k vsr - pipes[pipe_cnt].pipe.dest.odm_combine_policy = dm_odm_combine_policy_2to1; - } - pipe_cnt++; - } - for (i = 0, pipe_cnt = 0; i < dc->res_pool->pipe_count; i++) { if (!res_ctx->pipe_ctx[i].stream) @@ -1939,6 +1924,7 @@ int dcn32_populate_dml_pipes_from_context( dcn32_zero_pipe_dcc_fraction(pipes, pipe_cnt); DC_FP_END(); pipes[pipe_cnt].pipe.dest.vfront_porch = timing->v_front_porch; + pipes[pipe_cnt].pipe.dest.odm_combine_policy = dm_odm_combine_policy_dal; pipes[pipe_cnt].pipe.src.gpuvm_min_page_size_kbytes = 256; // according to spreadsheet pipes[pipe_cnt].pipe.src.unbounded_req_mode = false; pipes[pipe_cnt].pipe.scale_ratio_depth.lb_depth = dm_lb_19; @@ -1985,9 +1971,6 @@ int dcn32_populate_dml_pipes_from_context( } } - DC_FP_START(); - dcn32_predict_pipe_split(context, &pipes[pipe_cnt]); - DC_FP_END(); pipe_cnt++; } @@ -2010,7 +1993,8 @@ int dcn32_populate_dml_pipes_from_context( } static struct dc_cap_funcs cap_funcs = { - .get_dcc_compression_cap = dcn20_get_dcc_compression_cap + .get_dcc_compression_cap = dcn20_get_dcc_compression_cap, + .get_subvp_en = dcn32_subvp_in_use, }; void dcn32_calculate_wm_and_dlg(struct dc *dc, struct dc_state *context, @@ -2039,6 +2023,8 @@ static struct resource_funcs dcn32_res_pool_funcs = { .calculate_wm_and_dlg = dcn32_calculate_wm_and_dlg, .populate_dml_pipes = dcn32_populate_dml_pipes_from_context, .acquire_free_pipe_as_secondary_dpp_pipe = dcn32_acquire_free_pipe_as_secondary_dpp_pipe, + .acquire_free_pipe_as_secondary_opp_head = dcn32_acquire_free_pipe_as_secondary_opp_head, + .release_pipe = dcn20_release_pipe, .add_stream_to_ctx = dcn30_add_stream_to_ctx, .add_dsc_to_stream_resource = dcn20_add_dsc_to_stream_resource, .remove_stream_from_ctx = dcn20_remove_stream_from_ctx, @@ -2055,6 +2041,7 @@ static struct resource_funcs dcn32_res_pool_funcs = { .retain_phantom_pipes = dcn32_retain_phantom_pipes, .save_mall_state = dcn32_save_mall_state, .restore_mall_state = dcn32_restore_mall_state, + .build_pipe_pix_clk_params = dcn20_build_pipe_pix_clk_params, }; static uint32_t read_pipe_fuses(struct dc_context *ctx) @@ -2451,6 +2438,53 @@ static bool dcn32_resource_construct( pool->base.oem_device = NULL; } + dc->dml2_options.dcn_pipe_count = pool->base.pipe_count; + dc->dml2_options.use_native_pstate_optimization = false; + dc->dml2_options.use_native_soc_bb_construction = true; + dc->dml2_options.minimize_dispclk_using_odm = true; + + dc->dml2_options.callbacks.dc = dc; + dc->dml2_options.callbacks.build_scaling_params = &resource_build_scaling_params; + dc->dml2_options.callbacks.can_support_mclk_switch_using_fw_based_vblank_stretch = &dcn30_can_support_mclk_switch_using_fw_based_vblank_stretch; + dc->dml2_options.callbacks.acquire_secondary_pipe_for_mpc_odm = &dc_resource_acquire_secondary_pipe_for_mpc_odm_legacy; + dc->dml2_options.callbacks.update_pipes_for_stream_with_slice_count = &resource_update_pipes_for_stream_with_slice_count; + dc->dml2_options.callbacks.update_pipes_for_plane_with_slice_count = &resource_update_pipes_for_plane_with_slice_count; + dc->dml2_options.callbacks.get_mpc_slice_index = &resource_get_mpc_slice_index; + dc->dml2_options.callbacks.get_odm_slice_index = &resource_get_odm_slice_index; + dc->dml2_options.callbacks.get_opp_head = &resource_get_opp_head; + + dc->dml2_options.svp_pstate.callbacks.dc = dc; + dc->dml2_options.svp_pstate.callbacks.add_plane_to_context = &dc_add_plane_to_context; + dc->dml2_options.svp_pstate.callbacks.add_stream_to_ctx = &dc_add_stream_to_ctx; + dc->dml2_options.svp_pstate.callbacks.build_scaling_params = &resource_build_scaling_params; + dc->dml2_options.svp_pstate.callbacks.create_plane = &dc_create_plane_state; + dc->dml2_options.svp_pstate.callbacks.remove_plane_from_context = &dc_remove_plane_from_context; + dc->dml2_options.svp_pstate.callbacks.remove_stream_from_ctx = &dc_remove_stream_from_ctx; + dc->dml2_options.svp_pstate.callbacks.create_stream_for_sink = &dc_create_stream_for_sink; + dc->dml2_options.svp_pstate.callbacks.plane_state_release = &dc_plane_state_release; + dc->dml2_options.svp_pstate.callbacks.stream_release = &dc_stream_release; + dc->dml2_options.svp_pstate.callbacks.release_dsc = &dcn20_release_dsc; + + dc->dml2_options.svp_pstate.subvp_fw_processing_delay_us = dc->caps.subvp_fw_processing_delay_us; + dc->dml2_options.svp_pstate.subvp_prefetch_end_to_mall_start_us = dc->caps.subvp_prefetch_end_to_mall_start_us; + dc->dml2_options.svp_pstate.subvp_pstate_allow_width_us = dc->caps.subvp_pstate_allow_width_us; + dc->dml2_options.svp_pstate.subvp_swath_height_margin_lines = dc->caps.subvp_swath_height_margin_lines; + + dc->dml2_options.svp_pstate.force_disable_subvp = dc->debug.force_disable_subvp; + dc->dml2_options.svp_pstate.force_enable_subvp = dc->debug.force_subvp_mclk_switch; + + dc->dml2_options.mall_cfg.cache_line_size_bytes = dc->caps.cache_line_size; + dc->dml2_options.mall_cfg.cache_num_ways = dc->caps.cache_num_ways; + dc->dml2_options.mall_cfg.max_cab_allocation_bytes = dc->caps.max_cab_allocation_bytes; + dc->dml2_options.mall_cfg.mblk_height_4bpe_pixels = DCN3_2_MBLK_HEIGHT_4BPE; + dc->dml2_options.mall_cfg.mblk_height_8bpe_pixels = DCN3_2_MBLK_HEIGHT_8BPE; + dc->dml2_options.mall_cfg.mblk_size_bytes = DCN3_2_MALL_MBLK_SIZE_BYTES; + dc->dml2_options.mall_cfg.mblk_width_pixels = DCN3_2_MBLK_WIDTH; + + dc->dml2_options.max_segments_per_hubp = 18; + dc->dml2_options.det_segment_size = DCN3_2_DET_SEG_SIZE; + dc->dml2_options.map_dc_pipes_with_callbacks = true; + if (ASICREV_IS_GC_11_0_3(dc->ctx->asic_id.hw_internal_rev) && (dc->config.sdpif_request_limit_words_per_umc == 0)) dc->config.sdpif_request_limit_words_per_umc = 16; @@ -2669,6 +2703,33 @@ static struct pipe_ctx *dcn32_acquire_idle_pipe_for_head_pipe_in_layer( return idle_pipe; } +static int find_optimal_free_pipe_as_secondary_opp_head( + const struct resource_context *cur_res_ctx, + struct resource_context *new_res_ctx, + const struct resource_pool *pool, + const struct pipe_ctx *new_otg_master) +{ + const struct pipe_ctx *cur_otg_master; + int free_pipe_idx; + + cur_otg_master = &cur_res_ctx->pipe_ctx[new_otg_master->pipe_idx]; + free_pipe_idx = resource_find_free_pipe_used_as_sec_opp_head_by_cur_otg_master( + cur_res_ctx, new_res_ctx, cur_otg_master); + + /* Up until here if we have not found a free secondary pipe, we will + * need to wait for at least one frame to complete the transition + * sequence. + */ + if (free_pipe_idx == FREE_PIPE_INDEX_NOT_FOUND) + free_pipe_idx = recource_find_free_pipe_not_used_in_cur_res_ctx( + cur_res_ctx, new_res_ctx, pool); + + if (free_pipe_idx == FREE_PIPE_INDEX_NOT_FOUND) + free_pipe_idx = resource_find_any_free_pipe(new_res_ctx, pool); + + return free_pipe_idx; +} + struct pipe_ctx *dcn32_acquire_free_pipe_as_secondary_dpp_pipe( const struct dc_state *cur_ctx, struct dc_state *new_ctx, @@ -2706,6 +2767,49 @@ struct pipe_ctx *dcn32_acquire_free_pipe_as_secondary_dpp_pipe( return free_pipe; } +struct pipe_ctx *dcn32_acquire_free_pipe_as_secondary_opp_head( + const struct dc_state *cur_ctx, + struct dc_state *new_ctx, + const struct resource_pool *pool, + const struct pipe_ctx *otg_master) +{ + int free_pipe_idx = find_optimal_free_pipe_as_secondary_opp_head( + &cur_ctx->res_ctx, &new_ctx->res_ctx, + pool, otg_master); + struct pipe_ctx *free_pipe; + + if (free_pipe_idx >= 0) { + free_pipe = &new_ctx->res_ctx.pipe_ctx[free_pipe_idx]; + free_pipe->pipe_idx = free_pipe_idx; + free_pipe->stream = otg_master->stream; + free_pipe->stream_res.tg = otg_master->stream_res.tg; + free_pipe->stream_res.dsc = NULL; + free_pipe->stream_res.opp = pool->opps[free_pipe_idx]; + free_pipe->plane_res.mi = pool->mis[free_pipe_idx]; + free_pipe->plane_res.hubp = pool->hubps[free_pipe_idx]; + free_pipe->plane_res.ipp = pool->ipps[free_pipe_idx]; + free_pipe->plane_res.xfm = pool->transforms[free_pipe_idx]; + free_pipe->plane_res.dpp = pool->dpps[free_pipe_idx]; + free_pipe->plane_res.mpcc_inst = pool->dpps[free_pipe_idx]->inst; + if (free_pipe->stream->timing.flags.DSC == 1) { + dcn20_acquire_dsc(free_pipe->stream->ctx->dc, + &new_ctx->res_ctx, + &free_pipe->stream_res.dsc, + free_pipe_idx); + ASSERT(free_pipe->stream_res.dsc); + if (free_pipe->stream_res.dsc == NULL) { + memset(free_pipe, 0, sizeof(*free_pipe)); + free_pipe = NULL; + } + } + } else { + ASSERT(otg_master); + free_pipe = NULL; + } + + return free_pipe; +} + unsigned int dcn32_calc_num_avail_chans_for_mall(struct dc *dc, int num_chans) { /* diff --git a/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_resource.h b/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_resource.h index 103a2b54d0..b931008114 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_resource.h +++ b/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_resource.h @@ -38,7 +38,7 @@ #define DCN3_2_MBLK_HEIGHT_4BPE 128 #define DCN3_2_MBLK_HEIGHT_8BPE 64 #define DCN3_2_DCFCLK_DS_INIT_KHZ 10000 // Choose 10Mhz for init DCFCLK DS freq -#define SUBVP_HIGH_REFRESH_LIST_LEN 3 +#define SUBVP_HIGH_REFRESH_LIST_LEN 4 #define DCN3_2_MAX_SUBVP_PIXEL_RATE_MHZ 1800 #define DCN3_2_VMIN_DISPCLK_HZ 717000000 @@ -142,6 +142,16 @@ struct pipe_ctx *dcn32_acquire_free_pipe_as_secondary_dpp_pipe( const struct resource_pool *pool, const struct pipe_ctx *opp_head_pipe); +struct pipe_ctx *dcn32_acquire_free_pipe_as_secondary_opp_head( + const struct dc_state *cur_ctx, + struct dc_state *new_ctx, + const struct resource_pool *pool, + const struct pipe_ctx *otg_master); + +void dcn32_release_pipe(struct dc_state *context, + struct pipe_ctx *pipe, + const struct resource_pool *pool); + void dcn32_determine_det_override(struct dc *dc, struct dc_state *context, display_e2e_pipe_params_st *pipes); @@ -177,7 +187,6 @@ bool dcn32_subvp_vblank_admissable(struct dc *dc, struct dc_state *context, int /* CLK SRC */ #define CS_COMMON_REG_LIST_DCN3_0_RI(index, pllid) \ - ( \ SRI_ARR_ALPHABET(PIXCLK_RESYNC_CNTL, PHYPLL, index, pllid), \ SRII_ARR_2(PHASE, DP_DTO, 0, index), \ SRII_ARR_2(PHASE, DP_DTO, 1, index), \ @@ -190,12 +199,10 @@ bool dcn32_subvp_vblank_admissable(struct dc *dc, struct dc_state *context, int SRII_ARR_2(PIXEL_RATE_CNTL, OTG, 0, index), \ SRII_ARR_2(PIXEL_RATE_CNTL, OTG, 1, index), \ SRII_ARR_2(PIXEL_RATE_CNTL, OTG, 2, index), \ - SRII_ARR_2(PIXEL_RATE_CNTL, OTG, 3, index) \ - ) + SRII_ARR_2(PIXEL_RATE_CNTL, OTG, 3, index) /* ABM */ #define ABM_DCN32_REG_LIST_RI(id) \ - ( \ SRI_ARR(DC_ABM1_HG_SAMPLE_RATE, ABM, id), \ SRI_ARR(DC_ABM1_LS_SAMPLE_RATE, ABM, id), \ SRI_ARR(BL1_PWM_BL_UPDATE_SAMPLE_RATE, ABM, id), \ @@ -207,12 +214,10 @@ bool dcn32_subvp_vblank_admissable(struct dc *dc, struct dc_state *context, int SRI_ARR(DC_ABM1_LS_MIN_MAX_PIXEL_VALUE_THRES, ABM, id), \ SRI_ARR(DC_ABM1_HGLS_REG_READ_PROGRESS, ABM, id), \ SRI_ARR(DC_ABM1_ACE_OFFSET_SLOPE_0, ABM, id), \ - SRI_ARR(DC_ABM1_ACE_THRES_12, ABM, id), NBIO_SR_ARR(BIOS_SCRATCH_2, id) \ - ) + SRI_ARR(DC_ABM1_ACE_THRES_12, ABM, id), NBIO_SR_ARR(BIOS_SCRATCH_2, id) /* Audio */ #define AUD_COMMON_REG_LIST_RI(id) \ - ( \ SRI_ARR(AZALIA_F0_CODEC_ENDPOINT_INDEX, AZF0ENDPOINT, id), \ SRI_ARR(AZALIA_F0_CODEC_ENDPOINT_DATA, AZF0ENDPOINT, id), \ SR_ARR(AZALIA_F0_CODEC_FUNCTION_PARAMETER_STREAM_FORMATS, id), \ @@ -221,41 +226,33 @@ bool dcn32_subvp_vblank_admissable(struct dc *dc, struct dc_state *context, int SR_ARR(DCCG_AUDIO_DTO_SOURCE, id), SR_ARR(DCCG_AUDIO_DTO0_MODULE, id), \ SR_ARR(DCCG_AUDIO_DTO0_PHASE, id), SR_ARR(DCCG_AUDIO_DTO1_MODULE, id), \ SR_ARR(DCCG_AUDIO_DTO1_PHASE, id) \ - ) /* VPG */ #define VPG_DCN3_REG_LIST_RI(id) \ - ( \ SRI_ARR(VPG_GENERIC_STATUS, VPG, id), \ SRI_ARR(VPG_GENERIC_PACKET_ACCESS_CTRL, VPG, id), \ SRI_ARR(VPG_GENERIC_PACKET_DATA, VPG, id), \ SRI_ARR(VPG_GSP_FRAME_UPDATE_CTRL, VPG, id), \ - SRI_ARR(VPG_GSP_IMMEDIATE_UPDATE_CTRL, VPG, id) \ - ) + SRI_ARR(VPG_GSP_IMMEDIATE_UPDATE_CTRL, VPG, id) /* AFMT */ #define AFMT_DCN3_REG_LIST_RI(id) \ - ( \ SRI_ARR(AFMT_INFOFRAME_CONTROL0, AFMT, id), \ SRI_ARR(AFMT_VBI_PACKET_CONTROL, AFMT, id), \ SRI_ARR(AFMT_AUDIO_PACKET_CONTROL, AFMT, id), \ SRI_ARR(AFMT_AUDIO_PACKET_CONTROL2, AFMT, id), \ SRI_ARR(AFMT_AUDIO_SRC_CONTROL, AFMT, id), \ SRI_ARR(AFMT_60958_0, AFMT, id), SRI_ARR(AFMT_60958_1, AFMT, id), \ - SRI_ARR(AFMT_60958_2, AFMT, id), SRI_ARR(AFMT_MEM_PWR, AFMT, id) \ - ) + SRI_ARR(AFMT_60958_2, AFMT, id), SRI_ARR(AFMT_MEM_PWR, AFMT, id) /* APG */ #define APG_DCN31_REG_LIST_RI(id) \ - (\ SRI_ARR(APG_CONTROL, APG, id), SRI_ARR(APG_CONTROL2, APG, id), \ - SRI_ARR(APG_MEM_PWR, APG, id), SRI_ARR(APG_DBG_GEN_CONTROL, APG, id) \ - ) + SRI_ARR(APG_MEM_PWR, APG, id), SRI_ARR(APG_DBG_GEN_CONTROL, APG, id) /* Stream encoder */ #define SE_DCN32_REG_LIST_RI(id) \ - ( \ SRI_ARR(AFMT_CNTL, DIG, id), SRI_ARR(DIG_FE_CNTL, DIG, id), \ SRI_ARR(HDMI_CONTROL, DIG, id), SRI_ARR(HDMI_DB_CONTROL, DIG, id), \ SRI_ARR(HDMI_GC, DIG, id), \ @@ -299,28 +296,22 @@ bool dcn32_subvp_vblank_admissable(struct dc *dc, struct dc_state *context, int SRI_ARR(DP_SEC_METADATA_TRANSMISSION, DP, id), \ SRI_ARR(HDMI_METADATA_PACKET_CONTROL, DIG, id), \ SRI_ARR(DIG_FE_CNTL, DIG, id), SRI_ARR(DIG_CLOCK_PATTERN, DIG, id), \ - SRI_ARR(DIG_FIFO_CTRL0, DIG, id) \ - ) + SRI_ARR(DIG_FIFO_CTRL0, DIG, id) /* Aux regs */ #define AUX_REG_LIST_RI(id) \ - ( \ SRI_ARR(AUX_CONTROL, DP_AUX, id), SRI_ARR(AUX_DPHY_RX_CONTROL0, DP_AUX, id), \ - SRI_ARR(AUX_DPHY_RX_CONTROL1, DP_AUX, id) \ - ) + SRI_ARR(AUX_DPHY_RX_CONTROL1, DP_AUX, id) #define DCN2_AUX_REG_LIST_RI(id) \ - ( \ - AUX_REG_LIST_RI(id), SRI_ARR(AUX_DPHY_TX_CONTROL, DP_AUX, id) \ - ) + AUX_REG_LIST_RI(id), SRI_ARR(AUX_DPHY_TX_CONTROL, DP_AUX, id) /* HDP */ #define HPD_REG_LIST_RI(id) SRI_ARR(DC_HPD_CONTROL, HPD, id) /* Link encoder */ #define LE_DCN3_REG_LIST_RI(id) \ - ( \ SRI_ARR(DIG_BE_CNTL, DIG, id), SRI_ARR(DIG_BE_EN_CNTL, DIG, id), \ SRI_ARR(TMDS_CTL_BITS, DIG, id), \ SRI_ARR(TMDS_DCBALANCER_CONTROL, DIG, id), SRI_ARR(DP_CONFIG, DP, id), \ @@ -334,26 +325,20 @@ bool dcn32_subvp_vblank_admissable(struct dc *dc, struct dc_state *context, int SRI_ARR(DP_SEC_CNTL, DP, id), SRI_ARR(DP_VID_STREAM_CNTL, DP, id), \ SRI_ARR(DP_DPHY_FAST_TRAINING, DP, id), SRI_ARR(DP_SEC_CNTL1, DP, id), \ SRI_ARR(DP_DPHY_BS_SR_SWAP_CNTL, DP, id), \ - SRI_ARR(DP_DPHY_HBR2_PATTERN_CONTROL, DP, id) \ - ) + SRI_ARR(DP_DPHY_HBR2_PATTERN_CONTROL, DP, id) #define LE_DCN31_REG_LIST_RI(id) \ - ( \ LE_DCN3_REG_LIST_RI(id), SRI_ARR(DP_DPHY_INTERNAL_CTRL, DP, id), \ SR_ARR(DIO_LINKA_CNTL, id), SR_ARR(DIO_LINKB_CNTL, id), \ SR_ARR(DIO_LINKC_CNTL, id), SR_ARR(DIO_LINKD_CNTL, id), \ - SR_ARR(DIO_LINKE_CNTL, id), SR_ARR(DIO_LINKF_CNTL, id) \ - ) + SR_ARR(DIO_LINKE_CNTL, id), SR_ARR(DIO_LINKF_CNTL, id) #define UNIPHY_DCN2_REG_LIST_RI(id, phyid) \ - ( \ SRI_ARR_ALPHABET(CLOCK_ENABLE, SYMCLK, id, phyid), \ - SRI_ARR_ALPHABET(CHANNEL_XBAR_CNTL, UNIPHY, id, phyid) \ - ) + SRI_ARR_ALPHABET(CHANNEL_XBAR_CNTL, UNIPHY, id, phyid) /* HPO DP stream encoder */ #define DCN3_1_HPO_DP_STREAM_ENC_REG_LIST_RI(id) \ - ( \ SR_ARR(DP_STREAM_MAPPER_CONTROL0, id), \ SR_ARR(DP_STREAM_MAPPER_CONTROL1, id), \ SR_ARR(DP_STREAM_MAPPER_CONTROL2, id), \ @@ -388,12 +373,10 @@ bool dcn32_subvp_vblank_admissable(struct dc *dc, struct dc_state *context, int SRI_ARR(DP_SYM32_ENC_SDP_METADATA_PACKET_CONTROL, DP_SYM32_ENC, id), \ SRI_ARR(DP_SYM32_ENC_SDP_AUDIO_CONTROL0, DP_SYM32_ENC, id), \ SRI_ARR(DP_SYM32_ENC_VID_CRC_CONTROL, DP_SYM32_ENC, id), \ - SRI_ARR(DP_SYM32_ENC_HBLANK_CONTROL, DP_SYM32_ENC, id) \ - ) + SRI_ARR(DP_SYM32_ENC_HBLANK_CONTROL, DP_SYM32_ENC, id) /* HPO DP link encoder regs */ #define DCN3_1_HPO_DP_LINK_ENC_REG_LIST_RI(id) \ - ( \ SRI_ARR(DP_LINK_ENC_CLOCK_CONTROL, DP_LINK_ENC, id), \ SRI_ARR(DP_DPHY_SYM32_CONTROL, DP_DPHY_SYM32, id), \ SRI_ARR(DP_DPHY_SYM32_STATUS, DP_DPHY_SYM32, id), \ @@ -422,12 +405,10 @@ bool dcn32_subvp_vblank_admissable(struct dc *dc, struct dc_state *context, int SRI_ARR(DP_DPHY_SYM32_VC_RATE_CNTL1, DP_DPHY_SYM32, id), \ SRI_ARR(DP_DPHY_SYM32_VC_RATE_CNTL2, DP_DPHY_SYM32, id), \ SRI_ARR(DP_DPHY_SYM32_VC_RATE_CNTL3, DP_DPHY_SYM32, id), \ - SRI_ARR(DP_DPHY_SYM32_SAT_UPDATE, DP_DPHY_SYM32, id) \ - ) + SRI_ARR(DP_DPHY_SYM32_SAT_UPDATE, DP_DPHY_SYM32, id) /* DPP */ #define DPP_REG_LIST_DCN30_COMMON_RI(id) \ - ( \ SRI_ARR(CM_DEALPHA, CM, id), SRI_ARR(CM_MEM_PWR_STATUS, CM, id), \ SRI_ARR(CM_BIAS_CR_R, CM, id), SRI_ARR(CM_BIAS_Y_G_CB_B, CM, id), \ SRI_ARR(PRE_DEGAM, CNVC_CFG, id), SRI_ARR(CM_GAMCOR_CONTROL, CM, id), \ @@ -542,12 +523,10 @@ bool dcn32_subvp_vblank_admissable(struct dc *dc, struct dc_state *context, int SRI_ARR(CURSOR_CONTROL, CURSOR0_, id), \ SRI_ARR(OBUF_MEM_PWR_CTRL, DSCL, id), \ SRI_ARR(DSCL_MEM_PWR_STATUS, DSCL, id), \ - SRI_ARR(DSCL_MEM_PWR_CTRL, DSCL, id) \ - ) + SRI_ARR(DSCL_MEM_PWR_CTRL, DSCL, id) /* OPP */ #define OPP_REG_LIST_DCN_RI(id) \ - ( \ SRI_ARR(FMT_BIT_DEPTH_CONTROL, FMT, id), SRI_ARR(FMT_CONTROL, FMT, id), \ SRI_ARR(FMT_DITHER_RAND_R_SEED, FMT, id), \ SRI_ARR(FMT_DITHER_RAND_G_SEED, FMT, id), \ @@ -559,37 +538,29 @@ bool dcn32_subvp_vblank_admissable(struct dc *dc, struct dc_state *context, int SRI_ARR(OPPBUF_3D_PARAMETERS_0, OPPBUF, id), \ SRI_ARR(OPPBUF_3D_PARAMETERS_1, OPPBUF, id), \ SRI_ARR(OPP_PIPE_CONTROL, OPP_PIPE, id) \ - ) #define OPP_REG_LIST_DCN10_RI(id) OPP_REG_LIST_DCN_RI(id) #define OPP_DPG_REG_LIST_RI(id) \ - ( \ SRI_ARR(DPG_CONTROL, DPG, id), SRI_ARR(DPG_DIMENSIONS, DPG, id), \ SRI_ARR(DPG_OFFSET_SEGMENT, DPG, id), SRI_ARR(DPG_COLOUR_B_CB, DPG, id), \ SRI_ARR(DPG_COLOUR_G_Y, DPG, id), SRI_ARR(DPG_COLOUR_R_CR, DPG, id), \ - SRI_ARR(DPG_RAMP_CONTROL, DPG, id), SRI_ARR(DPG_STATUS, DPG, id) \ - ) + SRI_ARR(DPG_RAMP_CONTROL, DPG, id), SRI_ARR(DPG_STATUS, DPG, id) #define OPP_REG_LIST_DCN30_RI(id) \ - ( \ OPP_REG_LIST_DCN10_RI(id), OPP_DPG_REG_LIST_RI(id), \ - SRI_ARR(FMT_422_CONTROL, FMT, id) \ - ) + SRI_ARR(FMT_422_CONTROL, FMT, id) /* Aux engine regs */ #define AUX_COMMON_REG_LIST0_RI(id) \ - ( \ SRI_ARR(AUX_CONTROL, DP_AUX, id), SRI_ARR(AUX_ARB_CONTROL, DP_AUX, id), \ SRI_ARR(AUX_SW_DATA, DP_AUX, id), SRI_ARR(AUX_SW_CONTROL, DP_AUX, id), \ SRI_ARR(AUX_INTERRUPT_CONTROL, DP_AUX, id), \ SRI_ARR(AUX_DPHY_RX_CONTROL1, DP_AUX, id), \ - SRI_ARR(AUX_SW_STATUS, DP_AUX, id) \ - ) + SRI_ARR(AUX_SW_STATUS, DP_AUX, id) /* DWBC */ #define DWBC_COMMON_REG_LIST_DCN30_RI(id) \ - ( \ SR_ARR(DWB_ENABLE_CLK_CTRL, id), SR_ARR(DWB_MEM_PWR_CTRL, id), \ SR_ARR(FC_MODE_CTRL, id), SR_ARR(FC_FLOW_CTRL, id), \ SR_ARR(FC_WINDOW_START, id), SR_ARR(FC_WINDOW_SIZE, id), \ @@ -683,13 +654,11 @@ bool dcn32_subvp_vblank_admissable(struct dc *dc, struct dc_state *context, int SR_ARR(DWB_OGAM_RAMB_REGION_26_27, id), \ SR_ARR(DWB_OGAM_RAMB_REGION_28_29, id), \ SR_ARR(DWB_OGAM_RAMB_REGION_30_31, id), \ - SR_ARR(DWB_OGAM_RAMB_REGION_32_33, id) \ - ) + SR_ARR(DWB_OGAM_RAMB_REGION_32_33, id) /* MCIF */ #define MCIF_WB_COMMON_REG_LIST_DCN32_RI(inst) \ - ( \ SRI2_ARR(MCIF_WB_BUFMGR_SW_CONTROL, MCIF_WB, inst), \ SRI2_ARR(MCIF_WB_BUFMGR_STATUS, MCIF_WB, inst), \ SRI2_ARR(MCIF_WB_BUF_PITCH, MCIF_WB, inst), \ @@ -703,8 +672,6 @@ bool dcn32_subvp_vblank_admissable(struct dc *dc, struct dc_state *context, int SRI2_ARR(MCIF_WB_BUF_4_STATUS2, MCIF_WB, inst), \ SRI2_ARR(MCIF_WB_ARBITRATION_CONTROL, MCIF_WB, inst), \ SRI2_ARR(MCIF_WB_SCLK_CHANGE, MCIF_WB, inst), \ - SRI2_ARR(MCIF_WB_TEST_DEBUG_INDEX, MCIF_WB, inst), \ - SRI2_ARR(MCIF_WB_TEST_DEBUG_DATA, MCIF_WB, inst), \ SRI2_ARR(MCIF_WB_BUF_1_ADDR_Y, MCIF_WB, inst), \ SRI2_ARR(MCIF_WB_BUF_1_ADDR_C, MCIF_WB, inst), \ SRI2_ARR(MCIF_WB_BUF_2_ADDR_Y, MCIF_WB, inst), \ @@ -739,13 +706,11 @@ bool dcn32_subvp_vblank_admissable(struct dc *dc, struct dc_state *context, int SRI2_ARR(MMHUBBUB_WARMUP_ADDR_REGION, MMHUBBUB, inst), \ SRI2_ARR(MMHUBBUB_WARMUP_BASE_ADDR_HIGH, MMHUBBUB, inst), \ SRI2_ARR(MMHUBBUB_WARMUP_BASE_ADDR_LOW, MMHUBBUB, inst), \ - SRI2_ARR(MMHUBBUB_WARMUP_CONTROL_STATUS, MMHUBBUB, inst) \ - ) + SRI2_ARR(MMHUBBUB_WARMUP_CONTROL_STATUS, MMHUBBUB, inst) /* DSC */ #define DSC_REG_LIST_DCN20_RI(id) \ - ( \ SRI_ARR(DSC_TOP_CONTROL, DSC_TOP, id), \ SRI_ARR(DSC_DEBUG_CONTROL, DSC_TOP, id), \ SRI_ARR(DSCC_CONFIG0, DSCC, id), SRI_ARR(DSCC_CONFIG1, DSCC, id), \ @@ -793,8 +758,7 @@ bool dcn32_subvp_vblank_admissable(struct dc *dc, struct dc_state *context, int SRI_ARR(DSCC_RATE_CONTROL_BUFFER3_MAX_FULLNESS_LEVEL, DSCC, id), \ SRI_ARR(DSCCIF_CONFIG0, DSCCIF, id), \ SRI_ARR(DSCCIF_CONFIG1, DSCCIF, id), \ - SRI_ARR(DSCRM_DSC_FORWARD_CONFIG, DSCRM, id) \ - ) + SRI_ARR(DSCRM_DSC_FORWARD_CONFIG, DSCRM, id) /* MPC */ @@ -802,32 +766,25 @@ bool dcn32_subvp_vblank_admissable(struct dc *dc, struct dc_state *context, int SRII_DWB(DWB_MUX, MUX, MPC_DWB, inst) #define MPC_OUT_MUX_COMMON_REG_LIST_DCN1_0_RI(inst) \ - ( \ - SRII(MUX, MPC_OUT, inst), VUPDATE_SRII(CUR, VUPDATE_LOCK_SET, inst) \ - ) + SRII(MUX, MPC_OUT, inst), VUPDATE_SRII(CUR, VUPDATE_LOCK_SET, inst) #define MPC_OUT_MUX_REG_LIST_DCN3_0_RI(inst) \ - ( \ MPC_OUT_MUX_COMMON_REG_LIST_DCN1_0_RI(inst), SRII(CSC_MODE, MPC_OUT, inst), \ SRII(CSC_C11_C12_A, MPC_OUT, inst), SRII(CSC_C33_C34_A, MPC_OUT, inst), \ SRII(CSC_C11_C12_B, MPC_OUT, inst), SRII(CSC_C33_C34_B, MPC_OUT, inst), \ SRII(DENORM_CONTROL, MPC_OUT, inst), \ SRII(DENORM_CLAMP_G_Y, MPC_OUT, inst), \ - SRII(DENORM_CLAMP_B_CB, MPC_OUT, inst), SR(MPC_OUT_CSC_COEF_FORMAT) \ - ) + SRII(DENORM_CLAMP_B_CB, MPC_OUT, inst), SR(MPC_OUT_CSC_COEF_FORMAT) #define MPC_COMMON_REG_LIST_DCN1_0_RI(inst) \ - ( \ SRII(MPCC_TOP_SEL, MPCC, inst), SRII(MPCC_BOT_SEL, MPCC, inst), \ SRII(MPCC_CONTROL, MPCC, inst), SRII(MPCC_STATUS, MPCC, inst), \ SRII(MPCC_OPP_ID, MPCC, inst), SRII(MPCC_BG_G_Y, MPCC, inst), \ SRII(MPCC_BG_R_CR, MPCC, inst), SRII(MPCC_BG_B_CB, MPCC, inst), \ SRII(MPCC_SM_CONTROL, MPCC, inst), \ - SRII(MPCC_UPDATE_LOCK_SEL, MPCC, inst) \ - ) + SRII(MPCC_UPDATE_LOCK_SEL, MPCC, inst) #define MPC_REG_LIST_DCN3_0_RI(inst) \ - ( \ MPC_COMMON_REG_LIST_DCN1_0_RI(inst), SRII(MPCC_TOP_GAIN, MPCC, inst), \ SRII(MPCC_BOT_GAIN_INSIDE, MPCC, inst), \ SRII(MPCC_BOT_GAIN_OUTSIDE, MPCC, inst), \ @@ -881,8 +838,7 @@ bool dcn32_subvp_vblank_admissable(struct dc *dc, struct dc_state *context, int SRII(MPCC_OGAM_RAMB_START_BASE_CNTL_G, MPCC_OGAM, inst), \ SRII(MPCC_OGAM_RAMB_START_BASE_CNTL_R, MPCC_OGAM, inst), \ SRII(MPCC_OGAM_CONTROL, MPCC_OGAM, inst), \ - SRII(MPCC_OGAM_LUT_CONTROL, MPCC_OGAM, inst) \ - ) + SRII(MPCC_OGAM_LUT_CONTROL, MPCC_OGAM, inst) #define MPC_REG_LIST_DCN3_2_RI(inst) \ MPC_REG_LIST_DCN3_0_RI(inst),\ @@ -1026,11 +982,9 @@ bool dcn32_subvp_vblank_admissable(struct dc *dc, struct dc_state *context, int SRII(MPCC_MCM_1DLUT_RAMB_REGION_30_31, MPCC_MCM, inst),\ SRII(MPCC_MCM_1DLUT_RAMB_REGION_32_33, MPCC_MCM, inst),\ SRII(MPCC_MCM_MEM_PWR_CTRL, MPCC_MCM, inst) - /* OPTC */ #define OPTC_COMMON_REG_LIST_DCN3_2_RI(inst) \ - ( \ SRI_ARR(OTG_VSTARTUP_PARAM, OTG, inst), \ SRI_ARR(OTG_VUPDATE_PARAM, OTG, inst), \ SRI_ARR(OTG_VREADY_PARAM, OTG, inst), \ @@ -1092,22 +1046,17 @@ bool dcn32_subvp_vblank_admissable(struct dc *dc, struct dc_state *context, int SRI_ARR(OPTC_BYTES_PER_PIXEL, ODM, inst), \ SRI_ARR(OPTC_WIDTH_CONTROL, ODM, inst), \ SRI_ARR(OPTC_MEMORY_CONFIG, ODM, inst), \ - SRI_ARR(OTG_DRR_CONTROL, OTG, inst) \ - ) + SRI_ARR(OTG_DRR_CONTROL, OTG, inst) /* HUBP */ #define HUBP_REG_LIST_DCN_VM_RI(id) \ - ( \ SRI_ARR(NOM_PARAMETERS_0, HUBPREQ, id), \ SRI_ARR(NOM_PARAMETERS_1, HUBPREQ, id), \ SRI_ARR(NOM_PARAMETERS_2, HUBPREQ, id), \ SRI_ARR(NOM_PARAMETERS_3, HUBPREQ, id), \ - SRI_ARR(DCN_VM_MX_L1_TLB_CNTL, HUBPREQ, id) \ - ) - + SRI_ARR(DCN_VM_MX_L1_TLB_CNTL, HUBPREQ, id) #define HUBP_REG_LIST_DCN_RI(id) \ - ( \ SRI_ARR(DCHUBP_CNTL, HUBP, id), SRI_ARR(HUBPREQ_DEBUG_DB, HUBP, id), \ SRI_ARR(HUBPREQ_DEBUG, HUBP, id), SRI_ARR(DCSURF_ADDR_CONFIG, HUBP, id), \ SRI_ARR(DCSURF_TILING_CONFIG, HUBP, id), \ @@ -1178,11 +1127,8 @@ bool dcn32_subvp_vblank_admissable(struct dc *dc, struct dc_state *context, int SRI_ARR(DCN_SURF1_TTU_CNTL1, HUBPREQ, id), \ SRI_ARR(DCN_CUR0_TTU_CNTL0, HUBPREQ, id), \ SRI_ARR(DCN_CUR0_TTU_CNTL1, HUBPREQ, id), \ - SRI_ARR(HUBP_CLK_CNTL, HUBP, id) \ - ) - + SRI_ARR(HUBP_CLK_CNTL, HUBP, id) #define HUBP_REG_LIST_DCN2_COMMON_RI(id) \ - ( \ HUBP_REG_LIST_DCN_RI(id), HUBP_REG_LIST_DCN_VM_RI(id), \ SRI_ARR(PREFETCH_SETTINGS, HUBPREQ, id), \ SRI_ARR(PREFETCH_SETTINGS_C, HUBPREQ, id), \ @@ -1209,35 +1155,24 @@ bool dcn32_subvp_vblank_admissable(struct dc *dc, struct dc_state *context, int SRI_ARR(DCN_CUR1_TTU_CNTL0, HUBPREQ, id), \ SRI_ARR(DCN_CUR1_TTU_CNTL1, HUBPREQ, id), \ SRI_ARR(DCSURF_FLIP_CONTROL2, HUBPREQ, id), \ - SRI_ARR(VMID_SETTINGS_0, HUBPREQ, id) \ - ) - + SRI_ARR(VMID_SETTINGS_0, HUBPREQ, id) #define HUBP_REG_LIST_DCN21_RI(id) \ - ( \ HUBP_REG_LIST_DCN2_COMMON_RI(id), SRI_ARR(FLIP_PARAMETERS_3, HUBPREQ, id), \ SRI_ARR(FLIP_PARAMETERS_4, HUBPREQ, id), \ SRI_ARR(FLIP_PARAMETERS_5, HUBPREQ, id), \ SRI_ARR(FLIP_PARAMETERS_6, HUBPREQ, id), \ SRI_ARR(VBLANK_PARAMETERS_5, HUBPREQ, id), \ - SRI_ARR(VBLANK_PARAMETERS_6, HUBPREQ, id) \ - ) - + SRI_ARR(VBLANK_PARAMETERS_6, HUBPREQ, id) #define HUBP_REG_LIST_DCN30_RI(id) \ - ( \ - HUBP_REG_LIST_DCN21_RI(id), SRI_ARR(DCN_DMDATA_VM_CNTL, HUBPREQ, id) \ - ) - + HUBP_REG_LIST_DCN21_RI(id), SRI_ARR(DCN_DMDATA_VM_CNTL, HUBPREQ, id) #define HUBP_REG_LIST_DCN32_RI(id) \ - ( \ HUBP_REG_LIST_DCN30_RI(id), SRI_ARR(DCHUBP_MALL_CONFIG, HUBP, id), \ SRI_ARR(DCHUBP_VMPG_CONFIG, HUBP, id), \ - SRI_ARR(UCLK_PSTATE_FORCE, HUBPREQ, id) \ - ) + SRI_ARR(UCLK_PSTATE_FORCE, HUBPREQ, id) /* HUBBUB */ #define HUBBUB_REG_LIST_DCN32_RI(id) \ - ( \ SR(DCHUBBUB_ARB_DATA_URGENCY_WATERMARK_A), \ SR(DCHUBBUB_ARB_DATA_URGENCY_WATERMARK_B), \ SR(DCHUBBUB_ARB_DATA_URGENCY_WATERMARK_C), \ @@ -1275,15 +1210,14 @@ bool dcn32_subvp_vblank_admissable(struct dc *dc, struct dc_state *context, int SR(DCHUBBUB_ARB_FCLK_PSTATE_CHANGE_WATERMARK_B), \ SR(DCHUBBUB_ARB_FCLK_PSTATE_CHANGE_WATERMARK_C), \ SR(DCHUBBUB_ARB_FCLK_PSTATE_CHANGE_WATERMARK_D), \ + SR(DCHUBBUB_ARB_MALL_CNTL), \ SR(DCN_VM_FAULT_ADDR_MSB), SR(DCN_VM_FAULT_ADDR_LSB), \ SR(DCN_VM_FAULT_CNTL), SR(DCN_VM_FAULT_STATUS), \ - SR(SDPIF_REQUEST_RATE_LIMIT) \ - ) + SR(SDPIF_REQUEST_RATE_LIMIT) /* DCCG */ #define DCCG_REG_LIST_DCN32_RI() \ - ( \ SR(DPPCLK_DTO_CTRL), DCCG_SRII(DTO_PARAM, DPPCLK, 0), \ DCCG_SRII(DTO_PARAM, DPPCLK, 1), DCCG_SRII(DTO_PARAM, DPPCLK, 2), \ DCCG_SRII(DTO_PARAM, DPPCLK, 3), DCCG_SRII(CLOCK_CNTL, HDMICHARCLK, 0), \ @@ -1299,38 +1233,31 @@ bool dcn32_subvp_vblank_admissable(struct dc *dc, struct dc_state *context, int DCCG_SRII(PHASE, DTBCLK_DTO, 2), DCCG_SRII(PHASE, DTBCLK_DTO, 3), \ SR(DCCG_AUDIO_DTBCLK_DTO_MODULO), SR(DCCG_AUDIO_DTBCLK_DTO_PHASE), \ SR(OTG_PIXEL_RATE_DIV), SR(DTBCLK_P_CNTL), \ - SR(DCCG_AUDIO_DTO_SOURCE), SR(DENTIST_DISPCLK_CNTL) \ - ) + SR(DCCG_AUDIO_DTO_SOURCE), SR(DENTIST_DISPCLK_CNTL) /* VMID */ #define DCN20_VMID_REG_LIST_RI(id) \ - ( \ SRI_ARR(CNTL, DCN_VM_CONTEXT, id), \ SRI_ARR(PAGE_TABLE_BASE_ADDR_HI32, DCN_VM_CONTEXT, id), \ SRI_ARR(PAGE_TABLE_BASE_ADDR_LO32, DCN_VM_CONTEXT, id), \ SRI_ARR(PAGE_TABLE_START_ADDR_HI32, DCN_VM_CONTEXT, id), \ SRI_ARR(PAGE_TABLE_START_ADDR_LO32, DCN_VM_CONTEXT, id), \ SRI_ARR(PAGE_TABLE_END_ADDR_HI32, DCN_VM_CONTEXT, id), \ - SRI_ARR(PAGE_TABLE_END_ADDR_LO32, DCN_VM_CONTEXT, id) \ - ) + SRI_ARR(PAGE_TABLE_END_ADDR_LO32, DCN_VM_CONTEXT, id) /* I2C HW */ #define I2C_HW_ENGINE_COMMON_REG_LIST_RI(id) \ - ( \ SRI_ARR_I2C(SETUP, DC_I2C_DDC, id), SRI_ARR_I2C(SPEED, DC_I2C_DDC, id), \ SRI_ARR_I2C(HW_STATUS, DC_I2C_DDC, id), \ SR_ARR_I2C(DC_I2C_ARBITRATION, id), \ SR_ARR_I2C(DC_I2C_CONTROL, id), SR_ARR_I2C(DC_I2C_SW_STATUS, id), \ SR_ARR_I2C(DC_I2C_TRANSACTION0, id), SR_ARR_I2C(DC_I2C_TRANSACTION1, id),\ SR_ARR_I2C(DC_I2C_TRANSACTION2, id), SR_ARR_I2C(DC_I2C_TRANSACTION3, id),\ - SR_ARR_I2C(DC_I2C_DATA, id), SR_ARR_I2C(MICROSECOND_TIME_BASE_DIV, id) \ - ) + SR_ARR_I2C(DC_I2C_DATA, id), SR_ARR_I2C(MICROSECOND_TIME_BASE_DIV, id) #define I2C_HW_ENGINE_COMMON_REG_LIST_DCN30_RI(id) \ - ( \ I2C_HW_ENGINE_COMMON_REG_LIST_RI(id), SR_ARR_I2C(DIO_MEM_PWR_CTRL, id), \ - SR_ARR_I2C(DIO_MEM_PWR_STATUS, id) \ - ) + SR_ARR_I2C(DIO_MEM_PWR_STATUS, id) #endif /* _DCN32_RESOURCE_H_ */ diff --git a/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_resource_helpers.c b/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_resource_helpers.c index 3ad2b48954..bc5f0db23d 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_resource_helpers.c +++ b/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_resource_helpers.c @@ -255,6 +255,51 @@ bool dcn32_is_psr_capable(struct pipe_ctx *pipe) return psr_capable; } +static void override_det_for_subvp(struct dc *dc, struct dc_state *context, uint8_t pipe_segments[]) +{ + uint32_t i; + uint8_t fhd_count = 0; + uint8_t subvp_high_refresh_count = 0; + uint8_t stream_count = 0; + + // Do not override if a stream has multiple planes + for (i = 0; i < context->stream_count; i++) { + if (context->stream_status[i].plane_count > 1) { + return; + } + if (context->streams[i]->mall_stream_config.type != SUBVP_PHANTOM) { + stream_count++; + } + } + + for (i = 0; i < dc->res_pool->pipe_count; i++) { + struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[i]; + + if (pipe_ctx->stream && pipe_ctx->plane_state && pipe_ctx->stream->mall_stream_config.type != SUBVP_PHANTOM) { + if (dcn32_allow_subvp_high_refresh_rate(dc, context, pipe_ctx)) { + + if (pipe_ctx->stream->timing.v_addressable == 1080 && pipe_ctx->stream->timing.h_addressable == 1920) { + fhd_count++; + } + subvp_high_refresh_count++; + } + } + } + + if (stream_count == 2 && subvp_high_refresh_count == 2 && fhd_count == 1) { + for (i = 0; i < dc->res_pool->pipe_count; i++) { + struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[i]; + + if (pipe_ctx->stream && pipe_ctx->plane_state && pipe_ctx->stream->mall_stream_config.type != SUBVP_PHANTOM) { + if (pipe_ctx->stream->timing.v_addressable == 1080 && pipe_ctx->stream->timing.h_addressable == 1920) { + if (pipe_segments[i] > 4) + pipe_segments[i] = 4; + } + } + } + } +} + /** * dcn32_determine_det_override(): Determine DET allocation for each pipe * @@ -336,6 +381,7 @@ void dcn32_determine_det_override(struct dc *dc, } } + override_det_for_subvp(dc, context, pipe_segments); for (i = 0, pipe_cnt = 0; i < dc->res_pool->pipe_count; i++) { if (!context->res_ctx.pipe_ctx[i].stream) continue; @@ -660,7 +706,7 @@ bool dcn32_subvp_drr_admissable(struct dc *dc, struct dc_state *context) non_subvp_pipes++; drr_psr_capable = (drr_psr_capable || dcn32_is_psr_capable(pipe)); if (pipe->stream->ignore_msa_timing_param && - (pipe->stream->allow_freesync || pipe->stream->vrr_active_variable)) { + (pipe->stream->allow_freesync || pipe->stream->vrr_active_variable || pipe->stream->vrr_active_fixed)) { drr_pipe_found = true; } } @@ -718,7 +764,7 @@ bool dcn32_subvp_vblank_admissable(struct dc *dc, struct dc_state *context, int non_subvp_pipes++; vblank_psr_capable = (vblank_psr_capable || dcn32_is_psr_capable(pipe)); if (pipe->stream->ignore_msa_timing_param && - (pipe->stream->allow_freesync || pipe->stream->vrr_active_variable)) { + (pipe->stream->allow_freesync || pipe->stream->vrr_active_variable || pipe->stream->vrr_active_fixed)) { drr_pipe_found = true; } } |