1d99f1387SBhawanpreet Lakha /* 2d99f1387SBhawanpreet Lakha * Copyright 2020 Advanced Micro Devices, Inc. 3d99f1387SBhawanpreet Lakha * 4d99f1387SBhawanpreet Lakha * Permission is hereby granted, free of charge, to any person obtaining a 5d99f1387SBhawanpreet Lakha * copy of this software and associated documentation files (the "Software"), 6d99f1387SBhawanpreet Lakha * to deal in the Software without restriction, including without limitation 7d99f1387SBhawanpreet Lakha * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8d99f1387SBhawanpreet Lakha * and/or sell copies of the Software, and to permit persons to whom the 9d99f1387SBhawanpreet Lakha * Software is furnished to do so, subject to the following conditions: 10d99f1387SBhawanpreet Lakha * 11d99f1387SBhawanpreet Lakha * The above copyright notice and this permission notice shall be included in 12d99f1387SBhawanpreet Lakha * all copies or substantial portions of the Software. 13d99f1387SBhawanpreet Lakha * 14d99f1387SBhawanpreet Lakha * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15d99f1387SBhawanpreet Lakha * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16d99f1387SBhawanpreet Lakha * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 17d99f1387SBhawanpreet Lakha * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR 18d99f1387SBhawanpreet Lakha * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 19d99f1387SBhawanpreet Lakha * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 20d99f1387SBhawanpreet Lakha * OTHER DEALINGS IN THE SOFTWARE. 21d99f1387SBhawanpreet Lakha * 22d99f1387SBhawanpreet Lakha * Authors: AMD 23d99f1387SBhawanpreet Lakha * 24d99f1387SBhawanpreet Lakha */ 25d99f1387SBhawanpreet Lakha 26d99f1387SBhawanpreet Lakha 27d99f1387SBhawanpreet Lakha #include "dm_services.h" 28d99f1387SBhawanpreet Lakha #include "dm_helpers.h" 29d99f1387SBhawanpreet Lakha #include "core_types.h" 30d99f1387SBhawanpreet Lakha #include "resource.h" 31d99f1387SBhawanpreet Lakha #include "dcn30_hwseq.h" 32d99f1387SBhawanpreet Lakha #include "dccg.h" 33d99f1387SBhawanpreet Lakha #include "dce/dce_hwseq.h" 34d99f1387SBhawanpreet Lakha #include "dcn30_mpc.h" 35d99f1387SBhawanpreet Lakha #include "dcn30_dpp.h" 36d99f1387SBhawanpreet Lakha #include "dcn10/dcn10_cm_common.h" 37d99f1387SBhawanpreet Lakha #include "dcn30_cm_common.h" 38d99f1387SBhawanpreet Lakha #include "reg_helper.h" 39d99f1387SBhawanpreet Lakha #include "abm.h" 40d99f1387SBhawanpreet Lakha #include "clk_mgr.h" 41d99f1387SBhawanpreet Lakha #include "hubp.h" 42d99f1387SBhawanpreet Lakha #include "dchubbub.h" 43d99f1387SBhawanpreet Lakha #include "timing_generator.h" 44d99f1387SBhawanpreet Lakha #include "opp.h" 45d99f1387SBhawanpreet Lakha #include "ipp.h" 46d99f1387SBhawanpreet Lakha #include "mpc.h" 47d99f1387SBhawanpreet Lakha #include "mcif_wb.h" 48d99f1387SBhawanpreet Lakha #include "dc_dmub_srv.h" 490f782777SMartin Leung #include "link_hwss.h" 500f782777SMartin Leung #include "dpcd_defs.h" 51c5bc8c1bSWesley Chalmers #include "inc/dc_link_dp.h" 5230adeee5SWesley Chalmers #include "inc/link_dpcd.h" 53d99f1387SBhawanpreet Lakha 54d99f1387SBhawanpreet Lakha 55d99f1387SBhawanpreet Lakha 56d99f1387SBhawanpreet Lakha 57d99f1387SBhawanpreet Lakha #define DC_LOGGER_INIT(logger) 58d99f1387SBhawanpreet Lakha 59d99f1387SBhawanpreet Lakha #define CTX \ 60d99f1387SBhawanpreet Lakha hws->ctx 61d99f1387SBhawanpreet Lakha #define REG(reg)\ 62d99f1387SBhawanpreet Lakha hws->regs->reg 63d99f1387SBhawanpreet Lakha #define DC_LOGGER \ 64d99f1387SBhawanpreet Lakha dc->ctx->logger 65d99f1387SBhawanpreet Lakha 66d99f1387SBhawanpreet Lakha 67d99f1387SBhawanpreet Lakha #undef FN 68d99f1387SBhawanpreet Lakha #define FN(reg_name, field_name) \ 69d99f1387SBhawanpreet Lakha hws->shifts->field_name, hws->masks->field_name 70d99f1387SBhawanpreet Lakha 71d99f1387SBhawanpreet Lakha bool dcn30_set_blend_lut( 72d99f1387SBhawanpreet Lakha struct pipe_ctx *pipe_ctx, const struct dc_plane_state *plane_state) 73d99f1387SBhawanpreet Lakha { 74d99f1387SBhawanpreet Lakha struct dpp *dpp_base = pipe_ctx->plane_res.dpp; 75d99f1387SBhawanpreet Lakha bool result = true; 76d99f1387SBhawanpreet Lakha struct pwl_params *blend_lut = NULL; 77d99f1387SBhawanpreet Lakha 78d99f1387SBhawanpreet Lakha if (plane_state->blend_tf) { 79d99f1387SBhawanpreet Lakha if (plane_state->blend_tf->type == TF_TYPE_HWPWL) 80d99f1387SBhawanpreet Lakha blend_lut = &plane_state->blend_tf->pwl; 81d99f1387SBhawanpreet Lakha else if (plane_state->blend_tf->type == TF_TYPE_DISTRIBUTED_POINTS) { 82d99f1387SBhawanpreet Lakha cm3_helper_translate_curve_to_hw_format( 83d99f1387SBhawanpreet Lakha plane_state->blend_tf, &dpp_base->regamma_params, false); 84d99f1387SBhawanpreet Lakha blend_lut = &dpp_base->regamma_params; 85d99f1387SBhawanpreet Lakha } 86d99f1387SBhawanpreet Lakha } 87d99f1387SBhawanpreet Lakha result = dpp_base->funcs->dpp_program_blnd_lut(dpp_base, blend_lut); 88d99f1387SBhawanpreet Lakha 89d99f1387SBhawanpreet Lakha return result; 90d99f1387SBhawanpreet Lakha } 91d99f1387SBhawanpreet Lakha 92d99f1387SBhawanpreet Lakha static bool dcn30_set_mpc_shaper_3dlut( 93d99f1387SBhawanpreet Lakha struct pipe_ctx *pipe_ctx, const struct dc_stream_state *stream) 94d99f1387SBhawanpreet Lakha { 95d99f1387SBhawanpreet Lakha struct dpp *dpp_base = pipe_ctx->plane_res.dpp; 96d99f1387SBhawanpreet Lakha int mpcc_id = pipe_ctx->plane_res.hubp->inst; 97d99f1387SBhawanpreet Lakha struct mpc *mpc = pipe_ctx->stream_res.opp->ctx->dc->res_pool->mpc; 98d99f1387SBhawanpreet Lakha bool result = false; 99d99f1387SBhawanpreet Lakha int acquired_rmu = 0; 100d99f1387SBhawanpreet Lakha int mpcc_id_projected = 0; 101d99f1387SBhawanpreet Lakha 102d99f1387SBhawanpreet Lakha const struct pwl_params *shaper_lut = NULL; 103d99f1387SBhawanpreet Lakha //get the shaper lut params 104d99f1387SBhawanpreet Lakha if (stream->func_shaper) { 105d99f1387SBhawanpreet Lakha if (stream->func_shaper->type == TF_TYPE_HWPWL) 106d99f1387SBhawanpreet Lakha shaper_lut = &stream->func_shaper->pwl; 107d99f1387SBhawanpreet Lakha else if (stream->func_shaper->type == TF_TYPE_DISTRIBUTED_POINTS) { 108d99f1387SBhawanpreet Lakha cm_helper_translate_curve_to_hw_format( 109d99f1387SBhawanpreet Lakha stream->func_shaper, 110d99f1387SBhawanpreet Lakha &dpp_base->shaper_params, true); 111d99f1387SBhawanpreet Lakha shaper_lut = &dpp_base->shaper_params; 112d99f1387SBhawanpreet Lakha } 113d99f1387SBhawanpreet Lakha } 114d99f1387SBhawanpreet Lakha 115d99f1387SBhawanpreet Lakha if (stream->lut3d_func && 116d99f1387SBhawanpreet Lakha stream->lut3d_func->state.bits.initialized == 1 && 117d99f1387SBhawanpreet Lakha stream->lut3d_func->state.bits.rmu_idx_valid == 1) { 118d99f1387SBhawanpreet Lakha if (stream->lut3d_func->state.bits.rmu_mux_num == 0) 119d99f1387SBhawanpreet Lakha mpcc_id_projected = stream->lut3d_func->state.bits.mpc_rmu0_mux; 120d99f1387SBhawanpreet Lakha else if (stream->lut3d_func->state.bits.rmu_mux_num == 1) 121d99f1387SBhawanpreet Lakha mpcc_id_projected = stream->lut3d_func->state.bits.mpc_rmu1_mux; 122d99f1387SBhawanpreet Lakha else if (stream->lut3d_func->state.bits.rmu_mux_num == 2) 123d99f1387SBhawanpreet Lakha mpcc_id_projected = stream->lut3d_func->state.bits.mpc_rmu2_mux; 124d99f1387SBhawanpreet Lakha if (mpcc_id_projected != mpcc_id) 125d99f1387SBhawanpreet Lakha BREAK_TO_DEBUGGER(); 126d99f1387SBhawanpreet Lakha /*find the reason why logical layer assigned a differant mpcc_id into acquire_post_bldn_3dlut*/ 127d99f1387SBhawanpreet Lakha acquired_rmu = mpc->funcs->acquire_rmu(mpc, mpcc_id, 128d99f1387SBhawanpreet Lakha stream->lut3d_func->state.bits.rmu_mux_num); 129d99f1387SBhawanpreet Lakha if (acquired_rmu != stream->lut3d_func->state.bits.rmu_mux_num) 130d99f1387SBhawanpreet Lakha BREAK_TO_DEBUGGER(); 131d99f1387SBhawanpreet Lakha result = mpc->funcs->program_3dlut(mpc, 132d99f1387SBhawanpreet Lakha &stream->lut3d_func->lut_3d, 133d99f1387SBhawanpreet Lakha stream->lut3d_func->state.bits.rmu_mux_num); 134d99f1387SBhawanpreet Lakha result = mpc->funcs->program_shaper(mpc, shaper_lut, 135d99f1387SBhawanpreet Lakha stream->lut3d_func->state.bits.rmu_mux_num); 136d99f1387SBhawanpreet Lakha } else 137d99f1387SBhawanpreet Lakha /*loop through the available mux and release the requested mpcc_id*/ 138d99f1387SBhawanpreet Lakha mpc->funcs->release_rmu(mpc, mpcc_id); 139d99f1387SBhawanpreet Lakha 140d99f1387SBhawanpreet Lakha 141d99f1387SBhawanpreet Lakha return result; 142d99f1387SBhawanpreet Lakha } 143d99f1387SBhawanpreet Lakha 144d99f1387SBhawanpreet Lakha bool dcn30_set_input_transfer_func(struct dc *dc, 145d99f1387SBhawanpreet Lakha struct pipe_ctx *pipe_ctx, 146d99f1387SBhawanpreet Lakha const struct dc_plane_state *plane_state) 147d99f1387SBhawanpreet Lakha { 148d99f1387SBhawanpreet Lakha struct dce_hwseq *hws = dc->hwseq; 149d99f1387SBhawanpreet Lakha struct dpp *dpp_base = pipe_ctx->plane_res.dpp; 150d99f1387SBhawanpreet Lakha enum dc_transfer_func_predefined tf; 151d99f1387SBhawanpreet Lakha bool result = true; 152d99f1387SBhawanpreet Lakha struct pwl_params *params = NULL; 153d99f1387SBhawanpreet Lakha 154d99f1387SBhawanpreet Lakha if (dpp_base == NULL || plane_state == NULL) 155d99f1387SBhawanpreet Lakha return false; 156d99f1387SBhawanpreet Lakha 157d99f1387SBhawanpreet Lakha tf = TRANSFER_FUNCTION_UNITY; 158d99f1387SBhawanpreet Lakha 159d99f1387SBhawanpreet Lakha if (plane_state->in_transfer_func && 160d99f1387SBhawanpreet Lakha plane_state->in_transfer_func->type == TF_TYPE_PREDEFINED) 161d99f1387SBhawanpreet Lakha tf = plane_state->in_transfer_func->tf; 162d99f1387SBhawanpreet Lakha 163d99f1387SBhawanpreet Lakha dpp_base->funcs->dpp_set_pre_degam(dpp_base, tf); 164d99f1387SBhawanpreet Lakha 165d99f1387SBhawanpreet Lakha if (plane_state->in_transfer_func) { 166d99f1387SBhawanpreet Lakha if (plane_state->in_transfer_func->type == TF_TYPE_HWPWL) 167d99f1387SBhawanpreet Lakha params = &plane_state->in_transfer_func->pwl; 168d99f1387SBhawanpreet Lakha else if (plane_state->in_transfer_func->type == TF_TYPE_DISTRIBUTED_POINTS && 169d99f1387SBhawanpreet Lakha cm3_helper_translate_curve_to_hw_format(plane_state->in_transfer_func, 170d99f1387SBhawanpreet Lakha &dpp_base->degamma_params, false)) 171d99f1387SBhawanpreet Lakha params = &dpp_base->degamma_params; 172d99f1387SBhawanpreet Lakha } 173d99f1387SBhawanpreet Lakha 174d99f1387SBhawanpreet Lakha result = dpp_base->funcs->dpp_program_gamcor_lut(dpp_base, params); 175d99f1387SBhawanpreet Lakha 176d99f1387SBhawanpreet Lakha if (pipe_ctx->stream_res.opp && pipe_ctx->stream_res.opp->ctx) { 177d99f1387SBhawanpreet Lakha if (dpp_base->funcs->dpp_program_blnd_lut) 178d99f1387SBhawanpreet Lakha hws->funcs.set_blend_lut(pipe_ctx, plane_state); 179d99f1387SBhawanpreet Lakha if (dpp_base->funcs->dpp_program_shaper_lut && 180d99f1387SBhawanpreet Lakha dpp_base->funcs->dpp_program_3dlut) 181d99f1387SBhawanpreet Lakha hws->funcs.set_shaper_3dlut(pipe_ctx, plane_state); 182d99f1387SBhawanpreet Lakha } 183d99f1387SBhawanpreet Lakha 184d99f1387SBhawanpreet Lakha return result; 185d99f1387SBhawanpreet Lakha } 186d99f1387SBhawanpreet Lakha 187d99f1387SBhawanpreet Lakha bool dcn30_set_output_transfer_func(struct dc *dc, 188d99f1387SBhawanpreet Lakha struct pipe_ctx *pipe_ctx, 189d99f1387SBhawanpreet Lakha const struct dc_stream_state *stream) 190d99f1387SBhawanpreet Lakha { 191d99f1387SBhawanpreet Lakha int mpcc_id = pipe_ctx->plane_res.hubp->inst; 192d99f1387SBhawanpreet Lakha struct mpc *mpc = pipe_ctx->stream_res.opp->ctx->dc->res_pool->mpc; 193d99f1387SBhawanpreet Lakha struct pwl_params *params = NULL; 194d99f1387SBhawanpreet Lakha bool ret = false; 195d99f1387SBhawanpreet Lakha 196d99f1387SBhawanpreet Lakha /* program OGAM or 3DLUT only for the top pipe*/ 197d99f1387SBhawanpreet Lakha if (pipe_ctx->top_pipe == NULL) { 198d99f1387SBhawanpreet Lakha /*program rmu shaper and 3dlut in MPC*/ 199d99f1387SBhawanpreet Lakha ret = dcn30_set_mpc_shaper_3dlut(pipe_ctx, stream); 200d99f1387SBhawanpreet Lakha if (ret == false && mpc->funcs->set_output_gamma && stream->out_transfer_func) { 201d99f1387SBhawanpreet Lakha if (stream->out_transfer_func->type == TF_TYPE_HWPWL) 202d99f1387SBhawanpreet Lakha params = &stream->out_transfer_func->pwl; 203d99f1387SBhawanpreet Lakha else if (pipe_ctx->stream->out_transfer_func->type == 204d99f1387SBhawanpreet Lakha TF_TYPE_DISTRIBUTED_POINTS && 205d99f1387SBhawanpreet Lakha cm3_helper_translate_curve_to_hw_format( 206d99f1387SBhawanpreet Lakha stream->out_transfer_func, 207d99f1387SBhawanpreet Lakha &mpc->blender_params, false)) 208d99f1387SBhawanpreet Lakha params = &mpc->blender_params; 209d99f1387SBhawanpreet Lakha /* there are no ROM LUTs in OUTGAM */ 210d99f1387SBhawanpreet Lakha if (stream->out_transfer_func->type == TF_TYPE_PREDEFINED) 211d99f1387SBhawanpreet Lakha BREAK_TO_DEBUGGER(); 212d99f1387SBhawanpreet Lakha } 213d99f1387SBhawanpreet Lakha } 214d99f1387SBhawanpreet Lakha 215d99f1387SBhawanpreet Lakha mpc->funcs->set_output_gamma(mpc, mpcc_id, params); 216d99f1387SBhawanpreet Lakha return ret; 217d99f1387SBhawanpreet Lakha } 218d99f1387SBhawanpreet Lakha 219d99f1387SBhawanpreet Lakha static void dcn30_set_writeback( 220d99f1387SBhawanpreet Lakha struct dc *dc, 221d99f1387SBhawanpreet Lakha struct dc_writeback_info *wb_info, 222d99f1387SBhawanpreet Lakha struct dc_state *context) 223d99f1387SBhawanpreet Lakha { 224d99f1387SBhawanpreet Lakha struct mcif_wb *mcif_wb; 225d99f1387SBhawanpreet Lakha struct mcif_buf_params *mcif_buf_params; 226d99f1387SBhawanpreet Lakha 227d99f1387SBhawanpreet Lakha ASSERT(wb_info->dwb_pipe_inst < MAX_DWB_PIPES); 228d99f1387SBhawanpreet Lakha ASSERT(wb_info->wb_enabled); 229d99f1387SBhawanpreet Lakha ASSERT(wb_info->mpcc_inst >= 0); 2300b02e1fdSJoshua Aberback ASSERT(wb_info->mpcc_inst < dc->res_pool->mpcc_count); 231d99f1387SBhawanpreet Lakha mcif_wb = dc->res_pool->mcif_wb[wb_info->dwb_pipe_inst]; 232d99f1387SBhawanpreet Lakha mcif_buf_params = &wb_info->mcif_buf_params; 233d99f1387SBhawanpreet Lakha 234d99f1387SBhawanpreet Lakha /* set DWB MPC mux */ 235d99f1387SBhawanpreet Lakha dc->res_pool->mpc->funcs->set_dwb_mux(dc->res_pool->mpc, 236d99f1387SBhawanpreet Lakha wb_info->dwb_pipe_inst, wb_info->mpcc_inst); 237d99f1387SBhawanpreet Lakha /* set MCIF_WB buffer and arbitration configuration */ 238d99f1387SBhawanpreet Lakha mcif_wb->funcs->config_mcif_buf(mcif_wb, mcif_buf_params, wb_info->dwb_params.dest_height); 239d99f1387SBhawanpreet Lakha mcif_wb->funcs->config_mcif_arb(mcif_wb, &context->bw_ctx.bw.dcn.bw_writeback.mcif_wb_arb[wb_info->dwb_pipe_inst]); 240d99f1387SBhawanpreet Lakha } 241d99f1387SBhawanpreet Lakha 242d99f1387SBhawanpreet Lakha void dcn30_update_writeback( 243d99f1387SBhawanpreet Lakha struct dc *dc, 244d99f1387SBhawanpreet Lakha struct dc_writeback_info *wb_info, 245d99f1387SBhawanpreet Lakha struct dc_state *context) 246d99f1387SBhawanpreet Lakha { 247d99f1387SBhawanpreet Lakha struct dwbc *dwb; 248d99f1387SBhawanpreet Lakha dwb = dc->res_pool->dwbc[wb_info->dwb_pipe_inst]; 249d99f1387SBhawanpreet Lakha DC_LOG_DWB("%s dwb_pipe_inst = %d, mpcc_inst = %d",\ 250d99f1387SBhawanpreet Lakha __func__, wb_info->dwb_pipe_inst,\ 251d99f1387SBhawanpreet Lakha wb_info->mpcc_inst); 252d99f1387SBhawanpreet Lakha 253d99f1387SBhawanpreet Lakha dcn30_set_writeback(dc, wb_info, context); 254d99f1387SBhawanpreet Lakha 255d99f1387SBhawanpreet Lakha /* update DWB */ 256d99f1387SBhawanpreet Lakha dwb->funcs->update(dwb, &wb_info->dwb_params); 257d99f1387SBhawanpreet Lakha } 258d99f1387SBhawanpreet Lakha 259d99f1387SBhawanpreet Lakha bool dcn30_mmhubbub_warmup( 260d99f1387SBhawanpreet Lakha struct dc *dc, 261d99f1387SBhawanpreet Lakha unsigned int num_dwb, 262d99f1387SBhawanpreet Lakha struct dc_writeback_info *wb_info) 263d99f1387SBhawanpreet Lakha { 264d99f1387SBhawanpreet Lakha struct dwbc *dwb; 265d99f1387SBhawanpreet Lakha struct mcif_wb *mcif_wb; 266d99f1387SBhawanpreet Lakha struct mcif_warmup_params warmup_params = {0}; 267d99f1387SBhawanpreet Lakha unsigned int i, i_buf; 268d99f1387SBhawanpreet Lakha /*make sure there is no active DWB eanbled */ 269d99f1387SBhawanpreet Lakha for (i = 0; i < num_dwb; i++) { 270d99f1387SBhawanpreet Lakha dwb = dc->res_pool->dwbc[wb_info[i].dwb_pipe_inst]; 271d99f1387SBhawanpreet Lakha if (dwb->dwb_is_efc_transition || dwb->dwb_is_drc) { 272d99f1387SBhawanpreet Lakha /*can not do warmup while any dwb enabled*/ 273d99f1387SBhawanpreet Lakha return false; 274d99f1387SBhawanpreet Lakha } 275d99f1387SBhawanpreet Lakha } 276d99f1387SBhawanpreet Lakha 277d99f1387SBhawanpreet Lakha if (wb_info->mcif_warmup_params.p_vmid == 0) 278d99f1387SBhawanpreet Lakha return false; 279d99f1387SBhawanpreet Lakha 280d99f1387SBhawanpreet Lakha /*check whether this is new interface: warmup big buffer once*/ 281d99f1387SBhawanpreet Lakha if (wb_info->mcif_warmup_params.start_address.quad_part != 0 && 282d99f1387SBhawanpreet Lakha wb_info->mcif_warmup_params.region_size != 0) { 283d99f1387SBhawanpreet Lakha /*mmhubbub is shared, so it does not matter which MCIF*/ 284d99f1387SBhawanpreet Lakha mcif_wb = dc->res_pool->mcif_wb[0]; 285d99f1387SBhawanpreet Lakha /*warmup a big chunk of VM buffer at once*/ 286d99f1387SBhawanpreet Lakha warmup_params.start_address.quad_part = wb_info->mcif_warmup_params.start_address.quad_part; 287d99f1387SBhawanpreet Lakha warmup_params.address_increment = wb_info->mcif_warmup_params.region_size; 288d99f1387SBhawanpreet Lakha warmup_params.region_size = wb_info->mcif_warmup_params.region_size; 289d99f1387SBhawanpreet Lakha warmup_params.p_vmid = wb_info->mcif_warmup_params.p_vmid; 290d99f1387SBhawanpreet Lakha 291d99f1387SBhawanpreet Lakha if (warmup_params.address_increment == 0) 292d99f1387SBhawanpreet Lakha warmup_params.address_increment = dc->dml.soc.vmm_page_size_bytes; 293d99f1387SBhawanpreet Lakha 294d99f1387SBhawanpreet Lakha mcif_wb->funcs->warmup_mcif(mcif_wb, &warmup_params); 295d99f1387SBhawanpreet Lakha return true; 296d99f1387SBhawanpreet Lakha } 297d99f1387SBhawanpreet Lakha /*following is the original: warmup each DWB's mcif buffer*/ 298d99f1387SBhawanpreet Lakha for (i = 0; i < num_dwb; i++) { 299d99f1387SBhawanpreet Lakha dwb = dc->res_pool->dwbc[wb_info[i].dwb_pipe_inst]; 300d99f1387SBhawanpreet Lakha mcif_wb = dc->res_pool->mcif_wb[wb_info[i].dwb_pipe_inst]; 301d99f1387SBhawanpreet Lakha /*warmup is for VM mode only*/ 302d99f1387SBhawanpreet Lakha if (wb_info[i].mcif_buf_params.p_vmid == 0) 303d99f1387SBhawanpreet Lakha return false; 304d99f1387SBhawanpreet Lakha 305d99f1387SBhawanpreet Lakha /* Warmup MCIF_WB */ 306d99f1387SBhawanpreet Lakha for (i_buf = 0; i_buf < MCIF_BUF_COUNT; i_buf++) { 307d99f1387SBhawanpreet Lakha warmup_params.start_address.quad_part = wb_info[i].mcif_buf_params.luma_address[i_buf]; 308d99f1387SBhawanpreet Lakha warmup_params.address_increment = dc->dml.soc.vmm_page_size_bytes; 309d99f1387SBhawanpreet Lakha warmup_params.region_size = wb_info[i].mcif_buf_params.luma_pitch * wb_info[i].dwb_params.dest_height; 310d99f1387SBhawanpreet Lakha warmup_params.p_vmid = wb_info[i].mcif_buf_params.p_vmid; 311d99f1387SBhawanpreet Lakha mcif_wb->funcs->warmup_mcif(mcif_wb, &warmup_params); 312d99f1387SBhawanpreet Lakha } 313d99f1387SBhawanpreet Lakha } 314d99f1387SBhawanpreet Lakha return true; 315d99f1387SBhawanpreet Lakha } 316d99f1387SBhawanpreet Lakha 317d99f1387SBhawanpreet Lakha void dcn30_enable_writeback( 318d99f1387SBhawanpreet Lakha struct dc *dc, 319d99f1387SBhawanpreet Lakha struct dc_writeback_info *wb_info, 320d99f1387SBhawanpreet Lakha struct dc_state *context) 321d99f1387SBhawanpreet Lakha { 322d99f1387SBhawanpreet Lakha struct dwbc *dwb; 323d99f1387SBhawanpreet Lakha struct mcif_wb *mcif_wb; 324d99f1387SBhawanpreet Lakha struct timing_generator *optc; 325d99f1387SBhawanpreet Lakha 326d99f1387SBhawanpreet Lakha dwb = dc->res_pool->dwbc[wb_info->dwb_pipe_inst]; 327d99f1387SBhawanpreet Lakha mcif_wb = dc->res_pool->mcif_wb[wb_info->dwb_pipe_inst]; 328d99f1387SBhawanpreet Lakha 329d99f1387SBhawanpreet Lakha /* set the OPTC source mux */ 330d99f1387SBhawanpreet Lakha optc = dc->res_pool->timing_generators[dwb->otg_inst]; 331d99f1387SBhawanpreet Lakha DC_LOG_DWB("%s dwb_pipe_inst = %d, mpcc_inst = %d",\ 332d99f1387SBhawanpreet Lakha __func__, wb_info->dwb_pipe_inst,\ 333d99f1387SBhawanpreet Lakha wb_info->mpcc_inst); 334d99f1387SBhawanpreet Lakha if (IS_DIAG_DC(dc->ctx->dce_environment)) { 335d99f1387SBhawanpreet Lakha /*till diags switch to warmup interface*/ 336d99f1387SBhawanpreet Lakha dcn30_mmhubbub_warmup(dc, 1, wb_info); 337d99f1387SBhawanpreet Lakha } 338d99f1387SBhawanpreet Lakha /* Update writeback pipe */ 339d99f1387SBhawanpreet Lakha dcn30_set_writeback(dc, wb_info, context); 340d99f1387SBhawanpreet Lakha 341d99f1387SBhawanpreet Lakha /* Enable MCIF_WB */ 342d99f1387SBhawanpreet Lakha mcif_wb->funcs->enable_mcif(mcif_wb); 343d99f1387SBhawanpreet Lakha /* Enable DWB */ 344d99f1387SBhawanpreet Lakha dwb->funcs->enable(dwb, &wb_info->dwb_params); 345d99f1387SBhawanpreet Lakha } 346d99f1387SBhawanpreet Lakha 347d99f1387SBhawanpreet Lakha void dcn30_disable_writeback( 348d99f1387SBhawanpreet Lakha struct dc *dc, 349d99f1387SBhawanpreet Lakha unsigned int dwb_pipe_inst) 350d99f1387SBhawanpreet Lakha { 351d99f1387SBhawanpreet Lakha struct dwbc *dwb; 352d99f1387SBhawanpreet Lakha struct mcif_wb *mcif_wb; 353d99f1387SBhawanpreet Lakha 354d99f1387SBhawanpreet Lakha ASSERT(dwb_pipe_inst < MAX_DWB_PIPES); 355d99f1387SBhawanpreet Lakha dwb = dc->res_pool->dwbc[dwb_pipe_inst]; 356d99f1387SBhawanpreet Lakha mcif_wb = dc->res_pool->mcif_wb[dwb_pipe_inst]; 357d99f1387SBhawanpreet Lakha DC_LOG_DWB("%s dwb_pipe_inst = %d",\ 358d99f1387SBhawanpreet Lakha __func__, dwb_pipe_inst); 359d99f1387SBhawanpreet Lakha 360d99f1387SBhawanpreet Lakha /* disable DWB */ 361d99f1387SBhawanpreet Lakha dwb->funcs->disable(dwb); 362d99f1387SBhawanpreet Lakha /* disable MCIF */ 363d99f1387SBhawanpreet Lakha mcif_wb->funcs->disable_mcif(mcif_wb); 364d99f1387SBhawanpreet Lakha /* disable MPC DWB mux */ 365d99f1387SBhawanpreet Lakha dc->res_pool->mpc->funcs->disable_dwb_mux(dc->res_pool->mpc, dwb_pipe_inst); 366d99f1387SBhawanpreet Lakha } 367d99f1387SBhawanpreet Lakha 368d99f1387SBhawanpreet Lakha void dcn30_program_all_writeback_pipes_in_tree( 369d99f1387SBhawanpreet Lakha struct dc *dc, 370d99f1387SBhawanpreet Lakha const struct dc_stream_state *stream, 371d99f1387SBhawanpreet Lakha struct dc_state *context) 372d99f1387SBhawanpreet Lakha { 373d99f1387SBhawanpreet Lakha struct dc_writeback_info wb_info; 374d99f1387SBhawanpreet Lakha struct dwbc *dwb; 375d99f1387SBhawanpreet Lakha struct dc_stream_status *stream_status = NULL; 376d99f1387SBhawanpreet Lakha int i_wb, i_pipe, i_stream; 377d99f1387SBhawanpreet Lakha DC_LOG_DWB("%s", __func__); 378d99f1387SBhawanpreet Lakha 379d99f1387SBhawanpreet Lakha ASSERT(stream); 380d99f1387SBhawanpreet Lakha for (i_stream = 0; i_stream < context->stream_count; i_stream++) { 381d99f1387SBhawanpreet Lakha if (context->streams[i_stream] == stream) { 382d99f1387SBhawanpreet Lakha stream_status = &context->stream_status[i_stream]; 383d99f1387SBhawanpreet Lakha break; 384d99f1387SBhawanpreet Lakha } 385d99f1387SBhawanpreet Lakha } 386d99f1387SBhawanpreet Lakha ASSERT(stream_status); 387d99f1387SBhawanpreet Lakha 388d99f1387SBhawanpreet Lakha ASSERT(stream->num_wb_info <= dc->res_pool->res_cap->num_dwb); 389d99f1387SBhawanpreet Lakha /* For each writeback pipe */ 390d99f1387SBhawanpreet Lakha for (i_wb = 0; i_wb < stream->num_wb_info; i_wb++) { 391d99f1387SBhawanpreet Lakha 392d99f1387SBhawanpreet Lakha /* copy writeback info to local non-const so mpcc_inst can be set */ 393d99f1387SBhawanpreet Lakha wb_info = stream->writeback_info[i_wb]; 394d99f1387SBhawanpreet Lakha if (wb_info.wb_enabled) { 395d99f1387SBhawanpreet Lakha 396d99f1387SBhawanpreet Lakha /* get the MPCC instance for writeback_source_plane */ 397d99f1387SBhawanpreet Lakha wb_info.mpcc_inst = -1; 398d99f1387SBhawanpreet Lakha for (i_pipe = 0; i_pipe < dc->res_pool->pipe_count; i_pipe++) { 399d99f1387SBhawanpreet Lakha struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[i_pipe]; 400d99f1387SBhawanpreet Lakha 401d99f1387SBhawanpreet Lakha if (pipe_ctx->plane_state == wb_info.writeback_source_plane) { 402d99f1387SBhawanpreet Lakha wb_info.mpcc_inst = pipe_ctx->plane_res.mpcc_inst; 403d99f1387SBhawanpreet Lakha break; 404d99f1387SBhawanpreet Lakha } 405d99f1387SBhawanpreet Lakha } 406d99f1387SBhawanpreet Lakha ASSERT(wb_info.mpcc_inst != -1); 407d99f1387SBhawanpreet Lakha 408d99f1387SBhawanpreet Lakha ASSERT(wb_info.dwb_pipe_inst < dc->res_pool->res_cap->num_dwb); 409d99f1387SBhawanpreet Lakha dwb = dc->res_pool->dwbc[wb_info.dwb_pipe_inst]; 410d99f1387SBhawanpreet Lakha if (dwb->funcs->is_enabled(dwb)) { 411d99f1387SBhawanpreet Lakha /* writeback pipe already enabled, only need to update */ 412d99f1387SBhawanpreet Lakha dc->hwss.update_writeback(dc, &wb_info, context); 413d99f1387SBhawanpreet Lakha } else { 414d99f1387SBhawanpreet Lakha /* Enable writeback pipe and connect to MPCC */ 415d99f1387SBhawanpreet Lakha dc->hwss.enable_writeback(dc, &wb_info, context); 416d99f1387SBhawanpreet Lakha } 417d99f1387SBhawanpreet Lakha } else { 418d99f1387SBhawanpreet Lakha /* Disable writeback pipe and disconnect from MPCC */ 419d99f1387SBhawanpreet Lakha dc->hwss.disable_writeback(dc, wb_info.dwb_pipe_inst); 420d99f1387SBhawanpreet Lakha } 421d99f1387SBhawanpreet Lakha } 422d99f1387SBhawanpreet Lakha } 423d99f1387SBhawanpreet Lakha 424d99f1387SBhawanpreet Lakha void dcn30_init_hw(struct dc *dc) 425d99f1387SBhawanpreet Lakha { 426d99f1387SBhawanpreet Lakha struct abm **abms = dc->res_pool->multiple_abms; 427d99f1387SBhawanpreet Lakha struct dce_hwseq *hws = dc->hwseq; 428d99f1387SBhawanpreet Lakha struct dc_bios *dcb = dc->ctx->dc_bios; 429d99f1387SBhawanpreet Lakha struct resource_pool *res_pool = dc->res_pool; 43045a1261bSJake Wang int i, j; 43145a1261bSJake Wang int edp_num; 432d99f1387SBhawanpreet Lakha uint32_t backlight = MAX_BACKLIGHT_LEVEL; 433d99f1387SBhawanpreet Lakha 434d99f1387SBhawanpreet Lakha if (dc->clk_mgr && dc->clk_mgr->funcs->init_clocks) 435d99f1387SBhawanpreet Lakha dc->clk_mgr->funcs->init_clocks(dc->clk_mgr); 436d99f1387SBhawanpreet Lakha 437d99f1387SBhawanpreet Lakha // Initialize the dccg 438d99f1387SBhawanpreet Lakha if (res_pool->dccg->funcs->dccg_init) 439d99f1387SBhawanpreet Lakha res_pool->dccg->funcs->dccg_init(res_pool->dccg); 440d99f1387SBhawanpreet Lakha 441d99f1387SBhawanpreet Lakha if (IS_FPGA_MAXIMUS_DC(dc->ctx->dce_environment)) { 442d99f1387SBhawanpreet Lakha 443d99f1387SBhawanpreet Lakha REG_WRITE(REFCLK_CNTL, 0); 4440f782777SMartin Leung REG_UPDATE(DCHUBBUB_GLOBAL_TIMER_CNTL, DCHUBBUB_GLOBAL_TIMER_ENABLE, 1); 4450f782777SMartin Leung REG_WRITE(DIO_MEM_PWR_CTRL, 0); 4460f782777SMartin Leung 4470f782777SMartin Leung if (!dc->debug.disable_clock_gate) { 4480f782777SMartin Leung /* enable all DCN clock gating */ 4490f782777SMartin Leung REG_WRITE(DCCG_GATE_DISABLE_CNTL, 0); 4500f782777SMartin Leung 4510f782777SMartin Leung REG_WRITE(DCCG_GATE_DISABLE_CNTL2, 0); 4520f782777SMartin Leung 4530f782777SMartin Leung REG_UPDATE(DCFCLK_CNTL, DCFCLK_GATE_DIS, 0); 4540f782777SMartin Leung } 4550f782777SMartin Leung 4560f782777SMartin Leung //Enable ability to power gate / don't force power on permanently 4570f782777SMartin Leung if (hws->funcs.enable_power_gating_plane) 4580f782777SMartin Leung hws->funcs.enable_power_gating_plane(hws, true); 4590f782777SMartin Leung 4600f782777SMartin Leung return; 4610f782777SMartin Leung } 4620f782777SMartin Leung 463d99f1387SBhawanpreet Lakha if (!dcb->funcs->is_accelerated_mode(dcb)) { 464d99f1387SBhawanpreet Lakha hws->funcs.bios_golden_init(dc); 465d99f1387SBhawanpreet Lakha hws->funcs.disable_vga(dc->hwseq); 466d99f1387SBhawanpreet Lakha } 467d99f1387SBhawanpreet Lakha 46896879ad3SJacky Liao if (dc->debug.enable_mem_low_power.bits.dmcu) { 46996879ad3SJacky Liao // Force ERAM to shutdown if DMCU is not enabled 47096879ad3SJacky Liao if (dc->debug.disable_dmcu || dc->config.disable_dmcu) { 47196879ad3SJacky Liao REG_UPDATE(DMU_MEM_PWR_CNTL, DMCU_ERAM_MEM_PWR_FORCE, 3); 47296879ad3SJacky Liao } 47396879ad3SJacky Liao } 47496879ad3SJacky Liao 475cae78e03SJacky Liao // Set default OPTC memory power states 476cae78e03SJacky Liao if (dc->debug.enable_mem_low_power.bits.optc) { 477cae78e03SJacky Liao // Shutdown when unassigned and light sleep in VBLANK 478cae78e03SJacky Liao REG_SET_2(ODM_MEM_PWR_CTRL3, 0, ODM_MEM_UNASSIGNED_PWR_MODE, 3, ODM_MEM_VBLANK_PWR_MODE, 1); 479cae78e03SJacky Liao } 480cae78e03SJacky Liao 481d99f1387SBhawanpreet Lakha if (dc->ctx->dc_bios->fw_info_valid) { 482d99f1387SBhawanpreet Lakha res_pool->ref_clocks.xtalin_clock_inKhz = 483d99f1387SBhawanpreet Lakha dc->ctx->dc_bios->fw_info.pll_info.crystal_frequency; 484d99f1387SBhawanpreet Lakha 485d99f1387SBhawanpreet Lakha if (!IS_FPGA_MAXIMUS_DC(dc->ctx->dce_environment)) { 486d99f1387SBhawanpreet Lakha if (res_pool->dccg && res_pool->hubbub) { 487d99f1387SBhawanpreet Lakha 488d99f1387SBhawanpreet Lakha (res_pool->dccg->funcs->get_dccg_ref_freq)(res_pool->dccg, 489d99f1387SBhawanpreet Lakha dc->ctx->dc_bios->fw_info.pll_info.crystal_frequency, 490d99f1387SBhawanpreet Lakha &res_pool->ref_clocks.dccg_ref_clock_inKhz); 491d99f1387SBhawanpreet Lakha 492d99f1387SBhawanpreet Lakha (res_pool->hubbub->funcs->get_dchub_ref_freq)(res_pool->hubbub, 493d99f1387SBhawanpreet Lakha res_pool->ref_clocks.dccg_ref_clock_inKhz, 494d99f1387SBhawanpreet Lakha &res_pool->ref_clocks.dchub_ref_clock_inKhz); 495d99f1387SBhawanpreet Lakha } else { 496d99f1387SBhawanpreet Lakha // Not all ASICs have DCCG sw component 497d99f1387SBhawanpreet Lakha res_pool->ref_clocks.dccg_ref_clock_inKhz = 498d99f1387SBhawanpreet Lakha res_pool->ref_clocks.xtalin_clock_inKhz; 499d99f1387SBhawanpreet Lakha res_pool->ref_clocks.dchub_ref_clock_inKhz = 500d99f1387SBhawanpreet Lakha res_pool->ref_clocks.xtalin_clock_inKhz; 501d99f1387SBhawanpreet Lakha } 502d99f1387SBhawanpreet Lakha } 503d99f1387SBhawanpreet Lakha } else 504d99f1387SBhawanpreet Lakha ASSERT_CRITICAL(false); 505d99f1387SBhawanpreet Lakha 506d99f1387SBhawanpreet Lakha for (i = 0; i < dc->link_count; i++) { 507d99f1387SBhawanpreet Lakha /* Power up AND update implementation according to the 508d99f1387SBhawanpreet Lakha * required signal (which may be different from the 509d99f1387SBhawanpreet Lakha * default signal on connector). 510d99f1387SBhawanpreet Lakha */ 511d99f1387SBhawanpreet Lakha struct dc_link *link = dc->links[i]; 512d99f1387SBhawanpreet Lakha 513d99f1387SBhawanpreet Lakha link->link_enc->funcs->hw_init(link->link_enc); 5140f782777SMartin Leung 5150f782777SMartin Leung /* Check for enabled DIG to identify enabled display */ 5160f782777SMartin Leung if (link->link_enc->funcs->is_dig_enabled && 5170f782777SMartin Leung link->link_enc->funcs->is_dig_enabled(link->link_enc)) 5180f782777SMartin Leung link->link_status.link_active = true; 519d99f1387SBhawanpreet Lakha } 520d99f1387SBhawanpreet Lakha 521d99f1387SBhawanpreet Lakha /* Power gate DSCs */ 522d99f1387SBhawanpreet Lakha for (i = 0; i < res_pool->res_cap->num_dsc; i++) 5230f782777SMartin Leung if (hws->funcs.dsc_pg_control != NULL) 524d99f1387SBhawanpreet Lakha hws->funcs.dsc_pg_control(hws, res_pool->dscs[i]->inst, false); 525d99f1387SBhawanpreet Lakha 5260f782777SMartin Leung /* we want to turn off all dp displays before doing detection */ 5270f782777SMartin Leung if (dc->config.power_down_display_on_boot) { 5280f782777SMartin Leung uint8_t dpcd_power_state = '\0'; 5290f782777SMartin Leung enum dc_status status = DC_ERROR_UNEXPECTED; 530d99f1387SBhawanpreet Lakha 5310f782777SMartin Leung for (i = 0; i < dc->link_count; i++) { 5320f782777SMartin Leung if (dc->links[i]->connector_signal != SIGNAL_TYPE_DISPLAY_PORT) 5330f782777SMartin Leung continue; 534c5bc8c1bSWesley Chalmers /* DP 2.0 states that LTTPR regs must be read first */ 535c5bc8c1bSWesley Chalmers dp_retrieve_lttpr_cap(dc->links[i]); 5360f782777SMartin Leung 5370f782777SMartin Leung /* if any of the displays are lit up turn them off */ 5380f782777SMartin Leung status = core_link_read_dpcd(dc->links[i], DP_SET_POWER, 5390f782777SMartin Leung &dpcd_power_state, sizeof(dpcd_power_state)); 5400f782777SMartin Leung if (status == DC_OK && dpcd_power_state == DP_POWER_STATE_D0) { 5410f782777SMartin Leung /* blank dp stream before power off receiver*/ 5420f782777SMartin Leung if (dc->links[i]->link_enc->funcs->get_dig_frontend) { 5430f782777SMartin Leung unsigned int fe; 5440f782777SMartin Leung 5450f782777SMartin Leung fe = dc->links[i]->link_enc->funcs->get_dig_frontend( 5460f782777SMartin Leung dc->links[i]->link_enc); 5470885fe46SEric Bernstein if (fe == ENGINE_ID_UNKNOWN) 5480885fe46SEric Bernstein continue; 5490f782777SMartin Leung 5500f782777SMartin Leung for (j = 0; j < dc->res_pool->stream_enc_count; j++) { 5510f782777SMartin Leung if (fe == dc->res_pool->stream_enc[j]->id) { 5520f782777SMartin Leung dc->res_pool->stream_enc[j]->funcs->dp_blank( 5530f782777SMartin Leung dc->res_pool->stream_enc[j]); 5540f782777SMartin Leung break; 5550f782777SMartin Leung } 5560f782777SMartin Leung } 5570f782777SMartin Leung } 5580f782777SMartin Leung dp_receiver_power_ctrl(dc->links[i], false); 5590f782777SMartin Leung } 5600f782777SMartin Leung } 561d99f1387SBhawanpreet Lakha } 562d99f1387SBhawanpreet Lakha 5630f782777SMartin Leung /* If taking control over from VBIOS, we may want to optimize our first 5640f782777SMartin Leung * mode set, so we need to skip powering down pipes until we know which 5650f782777SMartin Leung * pipes we want to use. 5660f782777SMartin Leung * Otherwise, if taking control is not possible, we need to power 5670f782777SMartin Leung * everything down. 5680f782777SMartin Leung */ 5690f782777SMartin Leung if (dcb->funcs->is_accelerated_mode(dcb) || dc->config.power_down_display_on_boot) { 5700f782777SMartin Leung hws->funcs.init_pipes(dc, dc->current_state); 5710f782777SMartin Leung if (dc->res_pool->hubbub->funcs->allow_self_refresh_control) 5720f782777SMartin Leung dc->res_pool->hubbub->funcs->allow_self_refresh_control(dc->res_pool->hubbub, 5730f782777SMartin Leung !dc->res_pool->hubbub->ctx->dc->debug.disable_stutter); 574d99f1387SBhawanpreet Lakha } 575d99f1387SBhawanpreet Lakha 5760f782777SMartin Leung /* In headless boot cases, DIG may be turned 5770f782777SMartin Leung * on which causes HW/SW discrepancies. 5780f782777SMartin Leung * To avoid this, power down hardware on boot 5790f782777SMartin Leung * if DIG is turned on and seamless boot not enabled 5800f782777SMartin Leung */ 5810f782777SMartin Leung if (dc->config.power_down_display_on_boot) { 58245a1261bSJake Wang struct dc_link *edp_links[MAX_NUM_EDP]; 583*3addbde2SJake Wang struct dc_link *edp_link = NULL; 584d99f1387SBhawanpreet Lakha 58545a1261bSJake Wang get_edp_links(dc, edp_links, &edp_num); 586*3addbde2SJake Wang if (edp_num) 587*3addbde2SJake Wang edp_link = edp_links[0]; 588*3addbde2SJake Wang if (edp_link && edp_link->link_enc->funcs->is_dig_enabled && 5890f782777SMartin Leung edp_link->link_enc->funcs->is_dig_enabled(edp_link->link_enc) && 5900f782777SMartin Leung dc->hwss.edp_backlight_control && 5910f782777SMartin Leung dc->hwss.power_down && 5920f782777SMartin Leung dc->hwss.edp_power_control) { 5930f782777SMartin Leung dc->hwss.edp_backlight_control(edp_link, false); 5940f782777SMartin Leung dc->hwss.power_down(dc); 5950f782777SMartin Leung dc->hwss.edp_power_control(edp_link, false); 5960f782777SMartin Leung } else { 5970f782777SMartin Leung for (i = 0; i < dc->link_count; i++) { 5980f782777SMartin Leung struct dc_link *link = dc->links[i]; 5990f782777SMartin Leung 6000f782777SMartin Leung if (link->link_enc->funcs->is_dig_enabled && 6010f782777SMartin Leung link->link_enc->funcs->is_dig_enabled(link->link_enc) && 6020f782777SMartin Leung dc->hwss.power_down) { 6030f782777SMartin Leung dc->hwss.power_down(dc); 6040f782777SMartin Leung break; 605d99f1387SBhawanpreet Lakha } 606d99f1387SBhawanpreet Lakha 607d99f1387SBhawanpreet Lakha } 608d99f1387SBhawanpreet Lakha } 609d99f1387SBhawanpreet Lakha } 610d99f1387SBhawanpreet Lakha 611d99f1387SBhawanpreet Lakha for (i = 0; i < res_pool->audio_count; i++) { 612d99f1387SBhawanpreet Lakha struct audio *audio = res_pool->audios[i]; 613d99f1387SBhawanpreet Lakha 614d99f1387SBhawanpreet Lakha audio->funcs->hw_init(audio); 615d99f1387SBhawanpreet Lakha } 616d99f1387SBhawanpreet Lakha 617d99f1387SBhawanpreet Lakha for (i = 0; i < dc->link_count; i++) { 618d99f1387SBhawanpreet Lakha struct dc_link *link = dc->links[i]; 619d99f1387SBhawanpreet Lakha 620d99f1387SBhawanpreet Lakha if (link->panel_cntl) 621d99f1387SBhawanpreet Lakha backlight = link->panel_cntl->funcs->hw_init(link->panel_cntl); 622d99f1387SBhawanpreet Lakha } 623d99f1387SBhawanpreet Lakha 624d99f1387SBhawanpreet Lakha for (i = 0; i < dc->res_pool->pipe_count; i++) { 625d99f1387SBhawanpreet Lakha if (abms[i] != NULL) 626d99f1387SBhawanpreet Lakha abms[i]->funcs->abm_init(abms[i], backlight); 627d99f1387SBhawanpreet Lakha } 628d99f1387SBhawanpreet Lakha 629d99f1387SBhawanpreet Lakha /* power AFMT HDMI memory TODO: may move to dis/en output save power*/ 630d99f1387SBhawanpreet Lakha REG_WRITE(DIO_MEM_PWR_CTRL, 0); 631d99f1387SBhawanpreet Lakha 632d99f1387SBhawanpreet Lakha if (!dc->debug.disable_clock_gate) { 633d99f1387SBhawanpreet Lakha /* enable all DCN clock gating */ 634d99f1387SBhawanpreet Lakha REG_WRITE(DCCG_GATE_DISABLE_CNTL, 0); 635d99f1387SBhawanpreet Lakha 636d99f1387SBhawanpreet Lakha REG_WRITE(DCCG_GATE_DISABLE_CNTL2, 0); 637d99f1387SBhawanpreet Lakha 638d99f1387SBhawanpreet Lakha REG_UPDATE(DCFCLK_CNTL, DCFCLK_GATE_DIS, 0); 639d99f1387SBhawanpreet Lakha } 6400f782777SMartin Leung if (hws->funcs.enable_power_gating_plane) 6410f782777SMartin Leung hws->funcs.enable_power_gating_plane(dc->hwseq, true); 642d99f1387SBhawanpreet Lakha 64354e8094aSYongqiang Sun if (!dcb->funcs->is_accelerated_mode(dcb) && dc->res_pool->hubbub->funcs->init_watermarks) 64454e8094aSYongqiang Sun dc->res_pool->hubbub->funcs->init_watermarks(dc->res_pool->hubbub); 64554e8094aSYongqiang Sun 646d99f1387SBhawanpreet Lakha if (dc->clk_mgr->funcs->notify_wm_ranges) 647d99f1387SBhawanpreet Lakha dc->clk_mgr->funcs->notify_wm_ranges(dc->clk_mgr); 648d99f1387SBhawanpreet Lakha 649d99f1387SBhawanpreet Lakha if (dc->clk_mgr->funcs->set_hard_max_memclk) 650d99f1387SBhawanpreet Lakha dc->clk_mgr->funcs->set_hard_max_memclk(dc->clk_mgr); 6513e190955SJoshua Aberback 6523e190955SJoshua Aberback if (dc->res_pool->hubbub->funcs->force_pstate_change_control) 6533e190955SJoshua Aberback dc->res_pool->hubbub->funcs->force_pstate_change_control( 6543e190955SJoshua Aberback dc->res_pool->hubbub, false, false); 655ba5a5371SNicholas Kazlauskas if (dc->res_pool->hubbub->funcs->init_crb) 656ba5a5371SNicholas Kazlauskas dc->res_pool->hubbub->funcs->init_crb(dc->res_pool->hubbub); 657ba5a5371SNicholas Kazlauskas 658d99f1387SBhawanpreet Lakha } 659d99f1387SBhawanpreet Lakha 660d99f1387SBhawanpreet Lakha void dcn30_set_avmute(struct pipe_ctx *pipe_ctx, bool enable) 661d99f1387SBhawanpreet Lakha { 662d99f1387SBhawanpreet Lakha if (pipe_ctx == NULL) 663d99f1387SBhawanpreet Lakha return; 664d99f1387SBhawanpreet Lakha 665399d9bd6SChris Park if (dc_is_hdmi_signal(pipe_ctx->stream->signal) && pipe_ctx->stream_res.stream_enc != NULL) 666d99f1387SBhawanpreet Lakha pipe_ctx->stream_res.stream_enc->funcs->set_avmute( 667d99f1387SBhawanpreet Lakha pipe_ctx->stream_res.stream_enc, 668d99f1387SBhawanpreet Lakha enable); 669d99f1387SBhawanpreet Lakha } 670d99f1387SBhawanpreet Lakha 671d99f1387SBhawanpreet Lakha void dcn30_update_info_frame(struct pipe_ctx *pipe_ctx) 672d99f1387SBhawanpreet Lakha { 673d99f1387SBhawanpreet Lakha bool is_hdmi_tmds; 674d99f1387SBhawanpreet Lakha bool is_dp; 675d99f1387SBhawanpreet Lakha 676d99f1387SBhawanpreet Lakha ASSERT(pipe_ctx->stream); 677d99f1387SBhawanpreet Lakha 678d99f1387SBhawanpreet Lakha if (pipe_ctx->stream_res.stream_enc == NULL) 679d99f1387SBhawanpreet Lakha return; /* this is not root pipe */ 680d99f1387SBhawanpreet Lakha 681d99f1387SBhawanpreet Lakha is_hdmi_tmds = dc_is_hdmi_tmds_signal(pipe_ctx->stream->signal); 682d99f1387SBhawanpreet Lakha is_dp = dc_is_dp_signal(pipe_ctx->stream->signal); 683d99f1387SBhawanpreet Lakha 68409b07f7aSLeo (Hanghong) Ma if (!is_hdmi_tmds && !is_dp) 685d99f1387SBhawanpreet Lakha return; 686d99f1387SBhawanpreet Lakha 687d99f1387SBhawanpreet Lakha if (is_hdmi_tmds) 688d99f1387SBhawanpreet Lakha pipe_ctx->stream_res.stream_enc->funcs->update_hdmi_info_packets( 689d99f1387SBhawanpreet Lakha pipe_ctx->stream_res.stream_enc, 690d99f1387SBhawanpreet Lakha &pipe_ctx->stream_res.encoder_info_frame); 691d99f1387SBhawanpreet Lakha else 692d99f1387SBhawanpreet Lakha pipe_ctx->stream_res.stream_enc->funcs->update_dp_info_packets( 693d99f1387SBhawanpreet Lakha pipe_ctx->stream_res.stream_enc, 694d99f1387SBhawanpreet Lakha &pipe_ctx->stream_res.encoder_info_frame); 695d99f1387SBhawanpreet Lakha } 696d99f1387SBhawanpreet Lakha 697d99f1387SBhawanpreet Lakha void dcn30_program_dmdata_engine(struct pipe_ctx *pipe_ctx) 698d99f1387SBhawanpreet Lakha { 699d99f1387SBhawanpreet Lakha struct dc_stream_state *stream = pipe_ctx->stream; 700d99f1387SBhawanpreet Lakha struct hubp *hubp = pipe_ctx->plane_res.hubp; 701d99f1387SBhawanpreet Lakha bool enable = false; 702d99f1387SBhawanpreet Lakha struct stream_encoder *stream_enc = pipe_ctx->stream_res.stream_enc; 703d99f1387SBhawanpreet Lakha enum dynamic_metadata_mode mode = dc_is_dp_signal(stream->signal) 704d99f1387SBhawanpreet Lakha ? dmdata_dp 705d99f1387SBhawanpreet Lakha : dmdata_hdmi; 706d99f1387SBhawanpreet Lakha 707d99f1387SBhawanpreet Lakha /* if using dynamic meta, don't set up generic infopackets */ 708d99f1387SBhawanpreet Lakha if (pipe_ctx->stream->dmdata_address.quad_part != 0) { 709d99f1387SBhawanpreet Lakha pipe_ctx->stream_res.encoder_info_frame.hdrsmd.valid = false; 710d99f1387SBhawanpreet Lakha enable = true; 711d99f1387SBhawanpreet Lakha } 712d99f1387SBhawanpreet Lakha 713d99f1387SBhawanpreet Lakha if (!hubp) 714d99f1387SBhawanpreet Lakha return; 715d99f1387SBhawanpreet Lakha 716d99f1387SBhawanpreet Lakha if (!stream_enc || !stream_enc->funcs->set_dynamic_metadata) 717d99f1387SBhawanpreet Lakha return; 718d99f1387SBhawanpreet Lakha 719d99f1387SBhawanpreet Lakha stream_enc->funcs->set_dynamic_metadata(stream_enc, enable, 720d99f1387SBhawanpreet Lakha hubp->inst, mode); 721d99f1387SBhawanpreet Lakha } 722d99f1387SBhawanpreet Lakha 723d99f1387SBhawanpreet Lakha bool dcn30_apply_idle_power_optimizations(struct dc *dc, bool enable) 724d99f1387SBhawanpreet Lakha { 72552f2e83eSBhawanpreet Lakha union dmub_rb_cmd cmd; 72652f2e83eSBhawanpreet Lakha uint32_t tmr_delay = 0, tmr_scale = 0; 727ea7154d8SBhawanpreet Lakha struct dc_cursor_attributes cursor_attr; 728ea7154d8SBhawanpreet Lakha bool cursor_cache_enable = false; 729ea7154d8SBhawanpreet Lakha struct dc_stream_state *stream = NULL; 730ea7154d8SBhawanpreet Lakha struct dc_plane_state *plane = NULL; 73152f2e83eSBhawanpreet Lakha 732d99f1387SBhawanpreet Lakha if (!dc->ctx->dmub_srv) 733d99f1387SBhawanpreet Lakha return false; 734d99f1387SBhawanpreet Lakha 735d99f1387SBhawanpreet Lakha if (enable) { 73648e48e59SZhan Liu if (dc->current_state) { 73748e48e59SZhan Liu int i; 738d99f1387SBhawanpreet Lakha 73948e48e59SZhan Liu /* First, check no-memory-requests case */ 74048e48e59SZhan Liu for (i = 0; i < dc->current_state->stream_count; i++) { 741ea7154d8SBhawanpreet Lakha if (dc->current_state->stream_status[i].plane_count) 74248e48e59SZhan Liu /* Fail eligibility on a visible stream */ 74348e48e59SZhan Liu break; 74448e48e59SZhan Liu } 74552f2e83eSBhawanpreet Lakha 746ea7154d8SBhawanpreet Lakha if (i == dc->current_state->stream_count) { 747ea7154d8SBhawanpreet Lakha /* Enable no-memory-requests case */ 748ea7154d8SBhawanpreet Lakha memset(&cmd, 0, sizeof(cmd)); 749ea7154d8SBhawanpreet Lakha cmd.mall.header.type = DMUB_CMD__MALL; 750ea7154d8SBhawanpreet Lakha cmd.mall.header.sub_type = DMUB_CMD__MALL_ACTION_NO_DF_REQ; 751ea7154d8SBhawanpreet Lakha cmd.mall.header.payload_bytes = sizeof(cmd.mall) - sizeof(cmd.mall.header); 752ea7154d8SBhawanpreet Lakha 753ea7154d8SBhawanpreet Lakha dc_dmub_srv_cmd_queue(dc->ctx->dmub_srv, &cmd); 754ea7154d8SBhawanpreet Lakha dc_dmub_srv_cmd_execute(dc->ctx->dmub_srv); 755ea7154d8SBhawanpreet Lakha 756ea7154d8SBhawanpreet Lakha return true; 757a87a9a73SAlex Deucher } 758a87a9a73SAlex Deucher 759ea7154d8SBhawanpreet Lakha stream = dc->current_state->streams[0]; 760ea7154d8SBhawanpreet Lakha plane = (stream ? dc->current_state->stream_status[0].plane_states[0] : NULL); 761ea7154d8SBhawanpreet Lakha 762ea7154d8SBhawanpreet Lakha if (stream && plane) { 763ea7154d8SBhawanpreet Lakha cursor_cache_enable = stream->cursor_position.enable && 764ea7154d8SBhawanpreet Lakha plane->address.grph.cursor_cache_addr.quad_part; 765ea7154d8SBhawanpreet Lakha cursor_attr = stream->cursor_attributes; 766ea7154d8SBhawanpreet Lakha } 76752f2e83eSBhawanpreet Lakha 76852f2e83eSBhawanpreet Lakha /* 769ea7154d8SBhawanpreet Lakha * Second, check MALL eligibility 770ea7154d8SBhawanpreet Lakha * 771ea7154d8SBhawanpreet Lakha * single display only, single surface only, 8 and 16 bit formats only, no VM, 772ea7154d8SBhawanpreet Lakha * do not use MALL for displays that support PSR as they use D0i3.2 in DMCUB FW 773ea7154d8SBhawanpreet Lakha * 774ea7154d8SBhawanpreet Lakha * TODO: When we implement multi-display, PSR displays will be allowed if there is 775ea7154d8SBhawanpreet Lakha * a non-PSR display present, since in that case we can't do D0i3.2 776ea7154d8SBhawanpreet Lakha */ 777ea7154d8SBhawanpreet Lakha if (dc->current_state->stream_count == 1 && 778ea7154d8SBhawanpreet Lakha stream->link->psr_settings.psr_version == DC_PSR_VERSION_UNSUPPORTED && 779ea7154d8SBhawanpreet Lakha dc->current_state->stream_status[0].plane_count == 1 && 780ea7154d8SBhawanpreet Lakha plane->format <= SURFACE_PIXEL_FORMAT_GRPH_ABGR16161616F && 781ea7154d8SBhawanpreet Lakha plane->format >= SURFACE_PIXEL_FORMAT_GRPH_ARGB8888 && 782ea7154d8SBhawanpreet Lakha plane->address.page_table_base.quad_part == 0 && 783ea7154d8SBhawanpreet Lakha dc->hwss.does_plane_fit_in_mall && 784ea7154d8SBhawanpreet Lakha dc->hwss.does_plane_fit_in_mall(dc, plane, 785ea7154d8SBhawanpreet Lakha cursor_cache_enable ? &cursor_attr : NULL)) { 786ea7154d8SBhawanpreet Lakha unsigned int v_total = stream->adjust.v_total_max ? 787ea7154d8SBhawanpreet Lakha stream->adjust.v_total_max : stream->timing.v_total; 7889024fb08SLang Yu unsigned int refresh_hz = div_u64((unsigned long long) stream->timing.pix_clk_100hz * 7899024fb08SLang Yu 100LL, (v_total * stream->timing.h_total)); 790ea7154d8SBhawanpreet Lakha 791ea7154d8SBhawanpreet Lakha /* 792ea7154d8SBhawanpreet Lakha * one frame time in microsec: 793ea7154d8SBhawanpreet Lakha * Delay_Us = 1000000 / refresh 794ea7154d8SBhawanpreet Lakha * dynamic_delay_us = 1000000 / refresh + 2 * stutter_period 795ea7154d8SBhawanpreet Lakha * 796ea7154d8SBhawanpreet Lakha * one frame time modified by 'additional timer percent' (p): 797ea7154d8SBhawanpreet Lakha * Delay_Us_modified = dynamic_delay_us + dynamic_delay_us * p / 100 798ea7154d8SBhawanpreet Lakha * = dynamic_delay_us * (1 + p / 100) 799ea7154d8SBhawanpreet Lakha * = (1000000 / refresh + 2 * stutter_period) * (100 + p) / 100 800ea7154d8SBhawanpreet Lakha * = (1000000 + 2 * stutter_period * refresh) * (100 + p) / (100 * refresh) 801ea7154d8SBhawanpreet Lakha * 802ea7154d8SBhawanpreet Lakha * formula for timer duration based on parameters, from regspec: 803ea7154d8SBhawanpreet Lakha * dynamic_delay_us = 65.28 * (64 + MallFrameCacheTmrDly) * 2^MallFrameCacheTmrScale 804ea7154d8SBhawanpreet Lakha * 805ea7154d8SBhawanpreet Lakha * dynamic_delay_us / 65.28 = (64 + MallFrameCacheTmrDly) * 2^MallFrameCacheTmrScale 806ea7154d8SBhawanpreet Lakha * (dynamic_delay_us / 65.28) / 2^MallFrameCacheTmrScale = 64 + MallFrameCacheTmrDly 807ea7154d8SBhawanpreet Lakha * MallFrameCacheTmrDly = ((dynamic_delay_us / 65.28) / 2^MallFrameCacheTmrScale) - 64 808ea7154d8SBhawanpreet Lakha * = (1000000 + 2 * stutter_period * refresh) * (100 + p) / (100 * refresh) / 65.28 / 2^MallFrameCacheTmrScale - 64 809ea7154d8SBhawanpreet Lakha * = (1000000 + 2 * stutter_period * refresh) * (100 + p) / (refresh * 6528 * 2^MallFrameCacheTmrScale) - 64 81052f2e83eSBhawanpreet Lakha * 81152f2e83eSBhawanpreet Lakha * need to round up the result of the division before the subtraction 81252f2e83eSBhawanpreet Lakha */ 813ea7154d8SBhawanpreet Lakha unsigned int denom = refresh_hz * 6528; 814ea7154d8SBhawanpreet Lakha unsigned int stutter_period = dc->current_state->perf_params.stutter_period_us; 815ea7154d8SBhawanpreet Lakha 8169024fb08SLang Yu tmr_delay = div_u64(((1000000LL + 2 * stutter_period * refresh_hz) * 8179024fb08SLang Yu (100LL + dc->debug.mall_additional_timer_percent) + denom - 1), 818ea7154d8SBhawanpreet Lakha denom) - 64LL; 81952f2e83eSBhawanpreet Lakha 8203bb68cecSBhawanpreet Lakha /* In some cases the stutter period is really big (tiny modes) in these 8213bb68cecSBhawanpreet Lakha * cases MALL cant be enabled, So skip these cases to avoid a ASSERT() 8223bb68cecSBhawanpreet Lakha * 8233bb68cecSBhawanpreet Lakha * We can check if stutter_period is more than 1/10th the frame time to 8243bb68cecSBhawanpreet Lakha * consider if we can actually meet the range of hysteresis timer 8253bb68cecSBhawanpreet Lakha */ 8263bb68cecSBhawanpreet Lakha if (stutter_period > 100000/refresh_hz) 8273bb68cecSBhawanpreet Lakha return false; 8283bb68cecSBhawanpreet Lakha 82952f2e83eSBhawanpreet Lakha /* scale should be increased until it fits into 6 bits */ 83052f2e83eSBhawanpreet Lakha while (tmr_delay & ~0x3F) { 83152f2e83eSBhawanpreet Lakha tmr_scale++; 83252f2e83eSBhawanpreet Lakha 83352f2e83eSBhawanpreet Lakha if (tmr_scale > 3) { 834ea7154d8SBhawanpreet Lakha /* Delay exceeds range of hysteresis timer */ 83552f2e83eSBhawanpreet Lakha ASSERT(false); 83652f2e83eSBhawanpreet Lakha return false; 83752f2e83eSBhawanpreet Lakha } 83852f2e83eSBhawanpreet Lakha 83952f2e83eSBhawanpreet Lakha denom *= 2; 8409024fb08SLang Yu tmr_delay = div_u64(((1000000LL + 2 * stutter_period * refresh_hz) * 8419024fb08SLang Yu (100LL + dc->debug.mall_additional_timer_percent) + denom - 1), 842ea7154d8SBhawanpreet Lakha denom) - 64LL; 843ea7154d8SBhawanpreet Lakha } 844ea7154d8SBhawanpreet Lakha 845ea7154d8SBhawanpreet Lakha /* Copy HW cursor */ 846ea7154d8SBhawanpreet Lakha if (cursor_cache_enable) { 847ea7154d8SBhawanpreet Lakha memset(&cmd, 0, sizeof(cmd)); 848ea7154d8SBhawanpreet Lakha cmd.mall.header.type = DMUB_CMD__MALL; 849ea7154d8SBhawanpreet Lakha cmd.mall.header.sub_type = DMUB_CMD__MALL_ACTION_COPY_CURSOR; 850ea7154d8SBhawanpreet Lakha cmd.mall.header.payload_bytes = 851ea7154d8SBhawanpreet Lakha sizeof(cmd.mall) - sizeof(cmd.mall.header); 852ea7154d8SBhawanpreet Lakha 853ea7154d8SBhawanpreet Lakha switch (cursor_attr.color_format) { 854ea7154d8SBhawanpreet Lakha case CURSOR_MODE_MONO: 855ea7154d8SBhawanpreet Lakha cmd.mall.cursor_bpp = 2; 856ea7154d8SBhawanpreet Lakha break; 857ea7154d8SBhawanpreet Lakha case CURSOR_MODE_COLOR_1BIT_AND: 858ea7154d8SBhawanpreet Lakha case CURSOR_MODE_COLOR_PRE_MULTIPLIED_ALPHA: 859ea7154d8SBhawanpreet Lakha case CURSOR_MODE_COLOR_UN_PRE_MULTIPLIED_ALPHA: 860ea7154d8SBhawanpreet Lakha cmd.mall.cursor_bpp = 32; 861ea7154d8SBhawanpreet Lakha break; 862ea7154d8SBhawanpreet Lakha 863ea7154d8SBhawanpreet Lakha case CURSOR_MODE_COLOR_64BIT_FP_PRE_MULTIPLIED: 864ea7154d8SBhawanpreet Lakha case CURSOR_MODE_COLOR_64BIT_FP_UN_PRE_MULTIPLIED: 865ea7154d8SBhawanpreet Lakha cmd.mall.cursor_bpp = 64; 866ea7154d8SBhawanpreet Lakha break; 867ea7154d8SBhawanpreet Lakha } 868ea7154d8SBhawanpreet Lakha 869ea7154d8SBhawanpreet Lakha cmd.mall.cursor_copy_src.quad_part = cursor_attr.address.quad_part; 870ea7154d8SBhawanpreet Lakha cmd.mall.cursor_copy_dst.quad_part = 871554ba183SJoshua Aberback (plane->address.grph.cursor_cache_addr.quad_part + 2047) & ~2047; 872ea7154d8SBhawanpreet Lakha cmd.mall.cursor_width = cursor_attr.width; 873ea7154d8SBhawanpreet Lakha cmd.mall.cursor_height = cursor_attr.height; 874ea7154d8SBhawanpreet Lakha cmd.mall.cursor_pitch = cursor_attr.pitch; 875ea7154d8SBhawanpreet Lakha 876ea7154d8SBhawanpreet Lakha dc_dmub_srv_cmd_queue(dc->ctx->dmub_srv, &cmd); 877ea7154d8SBhawanpreet Lakha dc_dmub_srv_cmd_execute(dc->ctx->dmub_srv); 878ea7154d8SBhawanpreet Lakha dc_dmub_srv_wait_idle(dc->ctx->dmub_srv); 879ea7154d8SBhawanpreet Lakha 880ea7154d8SBhawanpreet Lakha /* Use copied cursor, and it's okay to not switch back */ 881554ba183SJoshua Aberback cursor_attr.address.quad_part = cmd.mall.cursor_copy_dst.quad_part; 882ea7154d8SBhawanpreet Lakha dc_stream_set_cursor_attributes(stream, &cursor_attr); 88352f2e83eSBhawanpreet Lakha } 88452f2e83eSBhawanpreet Lakha 88552f2e83eSBhawanpreet Lakha /* Enable MALL */ 88652f2e83eSBhawanpreet Lakha memset(&cmd, 0, sizeof(cmd)); 88752f2e83eSBhawanpreet Lakha cmd.mall.header.type = DMUB_CMD__MALL; 888ea7154d8SBhawanpreet Lakha cmd.mall.header.sub_type = DMUB_CMD__MALL_ACTION_ALLOW; 889ea7154d8SBhawanpreet Lakha cmd.mall.header.payload_bytes = sizeof(cmd.mall) - sizeof(cmd.mall.header); 89052f2e83eSBhawanpreet Lakha cmd.mall.tmr_delay = tmr_delay; 89152f2e83eSBhawanpreet Lakha cmd.mall.tmr_scale = tmr_scale; 892ea7154d8SBhawanpreet Lakha cmd.mall.debug_bits = dc->debug.mall_error_as_fatal; 89352f2e83eSBhawanpreet Lakha 89452f2e83eSBhawanpreet Lakha dc_dmub_srv_cmd_queue(dc->ctx->dmub_srv, &cmd); 89552f2e83eSBhawanpreet Lakha dc_dmub_srv_cmd_execute(dc->ctx->dmub_srv); 89652f2e83eSBhawanpreet Lakha 89752f2e83eSBhawanpreet Lakha return true; 89852f2e83eSBhawanpreet Lakha } 899d99f1387SBhawanpreet Lakha } 900d99f1387SBhawanpreet Lakha 90148e48e59SZhan Liu /* No applicable optimizations */ 902d99f1387SBhawanpreet Lakha return false; 903d99f1387SBhawanpreet Lakha } 904d99f1387SBhawanpreet Lakha 90552f2e83eSBhawanpreet Lakha /* Disable MALL */ 90652f2e83eSBhawanpreet Lakha memset(&cmd, 0, sizeof(cmd)); 90752f2e83eSBhawanpreet Lakha cmd.mall.header.type = DMUB_CMD__MALL; 90852f2e83eSBhawanpreet Lakha cmd.mall.header.sub_type = DMUB_CMD__MALL_ACTION_DISALLOW; 90952f2e83eSBhawanpreet Lakha cmd.mall.header.payload_bytes = 91052f2e83eSBhawanpreet Lakha sizeof(cmd.mall) - sizeof(cmd.mall.header); 91152f2e83eSBhawanpreet Lakha 91252f2e83eSBhawanpreet Lakha dc_dmub_srv_cmd_queue(dc->ctx->dmub_srv, &cmd); 91352f2e83eSBhawanpreet Lakha dc_dmub_srv_cmd_execute(dc->ctx->dmub_srv); 91452f2e83eSBhawanpreet Lakha dc_dmub_srv_wait_idle(dc->ctx->dmub_srv); 91552f2e83eSBhawanpreet Lakha 916d99f1387SBhawanpreet Lakha return true; 917d99f1387SBhawanpreet Lakha } 9183e190955SJoshua Aberback 9197fc75382SBhawanpreet Lakha bool dcn30_does_plane_fit_in_mall(struct dc *dc, struct dc_plane_state *plane, struct dc_cursor_attributes *cursor_attr) 920e74c8a46SJoshua Aberback { 921e74c8a46SJoshua Aberback // add meta size? 922e74c8a46SJoshua Aberback unsigned int surface_size = plane->plane_size.surface_pitch * plane->plane_size.surface_size.height * 923e74c8a46SJoshua Aberback (plane->format >= SURFACE_PIXEL_FORMAT_GRPH_ARGB16161616 ? 8 : 4); 924e74c8a46SJoshua Aberback unsigned int mall_size = dc->caps.mall_size_total; 9257fc75382SBhawanpreet Lakha unsigned int cursor_size = 0; 926e74c8a46SJoshua Aberback 927e74c8a46SJoshua Aberback if (dc->debug.mall_size_override) 928e74c8a46SJoshua Aberback mall_size = 1024 * 1024 * dc->debug.mall_size_override; 929e74c8a46SJoshua Aberback 9307fc75382SBhawanpreet Lakha if (cursor_attr) { 9317fc75382SBhawanpreet Lakha cursor_size = dc->caps.max_cursor_size * dc->caps.max_cursor_size; 9327fc75382SBhawanpreet Lakha 9337fc75382SBhawanpreet Lakha switch (cursor_attr->color_format) { 9347fc75382SBhawanpreet Lakha case CURSOR_MODE_MONO: 9357fc75382SBhawanpreet Lakha cursor_size /= 2; 9367fc75382SBhawanpreet Lakha break; 9377fc75382SBhawanpreet Lakha case CURSOR_MODE_COLOR_1BIT_AND: 9387fc75382SBhawanpreet Lakha case CURSOR_MODE_COLOR_PRE_MULTIPLIED_ALPHA: 9397fc75382SBhawanpreet Lakha case CURSOR_MODE_COLOR_UN_PRE_MULTIPLIED_ALPHA: 9407fc75382SBhawanpreet Lakha cursor_size *= 4; 9417fc75382SBhawanpreet Lakha break; 9427fc75382SBhawanpreet Lakha 9437fc75382SBhawanpreet Lakha case CURSOR_MODE_COLOR_64BIT_FP_PRE_MULTIPLIED: 9447fc75382SBhawanpreet Lakha case CURSOR_MODE_COLOR_64BIT_FP_UN_PRE_MULTIPLIED: 9457fc75382SBhawanpreet Lakha cursor_size *= 8; 9467fc75382SBhawanpreet Lakha break; 9477fc75382SBhawanpreet Lakha } 9487fc75382SBhawanpreet Lakha } 9497fc75382SBhawanpreet Lakha 9507fc75382SBhawanpreet Lakha return (surface_size + cursor_size) < mall_size; 951e74c8a46SJoshua Aberback } 952e74c8a46SJoshua Aberback 9533e190955SJoshua Aberback void dcn30_hardware_release(struct dc *dc) 9543e190955SJoshua Aberback { 9553e190955SJoshua Aberback /* if pstate unsupported, force it supported */ 9563e190955SJoshua Aberback if (!dc->clk_mgr->clks.p_state_change_support && 9573e190955SJoshua Aberback dc->res_pool->hubbub->funcs->force_pstate_change_control) 9583e190955SJoshua Aberback dc->res_pool->hubbub->funcs->force_pstate_change_control( 9593e190955SJoshua Aberback dc->res_pool->hubbub, true, true); 9603e190955SJoshua Aberback } 96136f87850SJoshua Aberback 962dbf5256bSJoshua Aberback void dcn30_set_disp_pattern_generator(const struct dc *dc, 963dbf5256bSJoshua Aberback struct pipe_ctx *pipe_ctx, 964dbf5256bSJoshua Aberback enum controller_dp_test_pattern test_pattern, 965dbf5256bSJoshua Aberback enum controller_dp_color_space color_space, 966dbf5256bSJoshua Aberback enum dc_color_depth color_depth, 967dbf5256bSJoshua Aberback const struct tg_color *solid_color, 968dbf5256bSJoshua Aberback int width, int height, int offset) 96936f87850SJoshua Aberback { 970d209124dSBhawanpreet Lakha struct stream_resource *stream_res = &pipe_ctx->stream_res; 9710b7421f0SAurabindo Pillai struct pipe_ctx *mpcc_pipe; 972d209124dSBhawanpreet Lakha 973d209124dSBhawanpreet Lakha if (test_pattern != CONTROLLER_DP_TEST_PATTERN_VIDEOMODE) { 974d209124dSBhawanpreet Lakha pipe_ctx->vtp_locked = false; 975d209124dSBhawanpreet Lakha /* turning on DPG */ 976d209124dSBhawanpreet Lakha stream_res->opp->funcs->opp_set_disp_pattern_generator(stream_res->opp, test_pattern, color_space, 977d209124dSBhawanpreet Lakha color_depth, solid_color, width, height, offset); 978d209124dSBhawanpreet Lakha 979d209124dSBhawanpreet Lakha /* Defer hubp blank if tg is locked */ 980d209124dSBhawanpreet Lakha if (stream_res->tg->funcs->is_tg_enabled(stream_res->tg)) { 981d209124dSBhawanpreet Lakha if (stream_res->tg->funcs->is_locked(stream_res->tg)) 982d209124dSBhawanpreet Lakha pipe_ctx->vtp_locked = true; 9830b7421f0SAurabindo Pillai else { 9840b7421f0SAurabindo Pillai /* Blank HUBP to allow p-state during blank on all timings */ 9850b7421f0SAurabindo Pillai pipe_ctx->plane_res.hubp->funcs->set_blank(pipe_ctx->plane_res.hubp, true); 9860b7421f0SAurabindo Pillai 9870b7421f0SAurabindo Pillai for (mpcc_pipe = pipe_ctx->bottom_pipe; mpcc_pipe; mpcc_pipe = mpcc_pipe->bottom_pipe) 9880b7421f0SAurabindo Pillai mpcc_pipe->plane_res.hubp->funcs->set_blank(mpcc_pipe->plane_res.hubp, true); 9890b7421f0SAurabindo Pillai } 990d209124dSBhawanpreet Lakha } 991d209124dSBhawanpreet Lakha } else { 992d209124dSBhawanpreet Lakha /* turning off DPG */ 9930b7421f0SAurabindo Pillai pipe_ctx->plane_res.hubp->funcs->set_blank(pipe_ctx->plane_res.hubp, false); 9940b7421f0SAurabindo Pillai for (mpcc_pipe = pipe_ctx->bottom_pipe; mpcc_pipe; mpcc_pipe = mpcc_pipe->bottom_pipe) 9950b7421f0SAurabindo Pillai mpcc_pipe->plane_res.hubp->funcs->set_blank(mpcc_pipe->plane_res.hubp, false); 9960b7421f0SAurabindo Pillai 997d209124dSBhawanpreet Lakha stream_res->opp->funcs->opp_set_disp_pattern_generator(stream_res->opp, test_pattern, color_space, 998d209124dSBhawanpreet Lakha color_depth, solid_color, width, height, offset); 999d209124dSBhawanpreet Lakha } 100036f87850SJoshua Aberback } 1001