LCOV - code coverage report
Current view: top level - drivers/gpu/drm/amd/display/dc/dcn30 - dcn30_hwseq.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 0 444 0.0 %
Date: 2022-12-09 01:23:36 Functions: 0 19 0.0 %

          Line data    Source code
       1             : /*
       2             :  * Copyright 2020 Advanced Micro Devices, Inc.
       3             :  *
       4             :  * Permission is hereby granted, free of charge, to any person obtaining a
       5             :  * copy of this software and associated documentation files (the "Software"),
       6             :  * to deal in the Software without restriction, including without limitation
       7             :  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
       8             :  * and/or sell copies of the Software, and to permit persons to whom the
       9             :  * Software is furnished to do so, subject to the following conditions:
      10             :  *
      11             :  * The above copyright notice and this permission notice shall be included in
      12             :  * all copies or substantial portions of the Software.
      13             :  *
      14             :  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
      15             :  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
      16             :  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
      17             :  * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
      18             :  * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
      19             :  * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
      20             :  * OTHER DEALINGS IN THE SOFTWARE.
      21             :  *
      22             :  * Authors: AMD
      23             :  *
      24             :  */
      25             : 
      26             : 
      27             : #include "dm_services.h"
      28             : #include "dm_helpers.h"
      29             : #include "core_types.h"
      30             : #include "resource.h"
      31             : #include "dcn30_hwseq.h"
      32             : #include "dccg.h"
      33             : #include "dce/dce_hwseq.h"
      34             : #include "dcn30_mpc.h"
      35             : #include "dcn30_dpp.h"
      36             : #include "dcn10/dcn10_cm_common.h"
      37             : #include "dcn30_cm_common.h"
      38             : #include "reg_helper.h"
      39             : #include "abm.h"
      40             : #include "clk_mgr.h"
      41             : #include "hubp.h"
      42             : #include "dchubbub.h"
      43             : #include "timing_generator.h"
      44             : #include "opp.h"
      45             : #include "ipp.h"
      46             : #include "mpc.h"
      47             : #include "mcif_wb.h"
      48             : #include "dc_dmub_srv.h"
      49             : #include "link_hwss.h"
      50             : #include "dpcd_defs.h"
      51             : #include "../dcn20/dcn20_hwseq.h"
      52             : #include "dcn30_resource.h"
      53             : #include "inc/dc_link_dp.h"
      54             : #include "inc/link_dpcd.h"
      55             : 
      56             : 
      57             : 
      58             : 
      59             : #define DC_LOGGER_INIT(logger)
      60             : 
      61             : #define CTX \
      62             :         hws->ctx
      63             : #define REG(reg)\
      64             :         hws->regs->reg
      65             : #define DC_LOGGER \
      66             :                 dc->ctx->logger
      67             : 
      68             : 
      69             : #undef FN
      70             : #define FN(reg_name, field_name) \
      71             :         hws->shifts->field_name, hws->masks->field_name
      72             : 
      73           0 : bool dcn30_set_blend_lut(
      74             :         struct pipe_ctx *pipe_ctx, const struct dc_plane_state *plane_state)
      75             : {
      76           0 :         struct dpp *dpp_base = pipe_ctx->plane_res.dpp;
      77           0 :         bool result = true;
      78           0 :         struct pwl_params *blend_lut = NULL;
      79             : 
      80           0 :         if (plane_state->blend_tf) {
      81           0 :                 if (plane_state->blend_tf->type == TF_TYPE_HWPWL)
      82           0 :                         blend_lut = &plane_state->blend_tf->pwl;
      83           0 :                 else if (plane_state->blend_tf->type == TF_TYPE_DISTRIBUTED_POINTS) {
      84           0 :                         cm3_helper_translate_curve_to_hw_format(
      85             :                                         plane_state->blend_tf, &dpp_base->regamma_params, false);
      86           0 :                         blend_lut = &dpp_base->regamma_params;
      87             :                 }
      88             :         }
      89           0 :         result = dpp_base->funcs->dpp_program_blnd_lut(dpp_base, blend_lut);
      90             : 
      91           0 :         return result;
      92             : }
      93             : 
      94           0 : static bool dcn30_set_mpc_shaper_3dlut(
      95             :         struct pipe_ctx *pipe_ctx, const struct dc_stream_state *stream)
      96             : {
      97           0 :         struct dpp *dpp_base = pipe_ctx->plane_res.dpp;
      98           0 :         int mpcc_id = pipe_ctx->plane_res.hubp->inst;
      99           0 :         struct mpc *mpc = pipe_ctx->stream_res.opp->ctx->dc->res_pool->mpc;
     100           0 :         bool result = false;
     101           0 :         int acquired_rmu = 0;
     102           0 :         int mpcc_id_projected = 0;
     103             : 
     104           0 :         const struct pwl_params *shaper_lut = NULL;
     105             :         //get the shaper lut params
     106           0 :         if (stream->func_shaper) {
     107           0 :                 if (stream->func_shaper->type == TF_TYPE_HWPWL)
     108           0 :                         shaper_lut = &stream->func_shaper->pwl;
     109           0 :                 else if (stream->func_shaper->type == TF_TYPE_DISTRIBUTED_POINTS) {
     110           0 :                         cm_helper_translate_curve_to_hw_format(
     111             :                                         stream->func_shaper,
     112             :                                         &dpp_base->shaper_params, true);
     113           0 :                         shaper_lut = &dpp_base->shaper_params;
     114             :                 }
     115             :         }
     116             : 
     117           0 :         if (stream->lut3d_func &&
     118           0 :                 stream->lut3d_func->state.bits.initialized == 1 &&
     119             :                 stream->lut3d_func->state.bits.rmu_idx_valid == 1) {
     120           0 :                 if (stream->lut3d_func->state.bits.rmu_mux_num == 0)
     121           0 :                         mpcc_id_projected = stream->lut3d_func->state.bits.mpc_rmu0_mux;
     122           0 :                 else if (stream->lut3d_func->state.bits.rmu_mux_num == 1)
     123           0 :                         mpcc_id_projected = stream->lut3d_func->state.bits.mpc_rmu1_mux;
     124           0 :                 else if (stream->lut3d_func->state.bits.rmu_mux_num == 2)
     125           0 :                         mpcc_id_projected = stream->lut3d_func->state.bits.mpc_rmu2_mux;
     126           0 :                 if (mpcc_id_projected != mpcc_id)
     127           0 :                         BREAK_TO_DEBUGGER();
     128             :                 /*find the reason why logical layer assigned a differant mpcc_id into acquire_post_bldn_3dlut*/
     129           0 :                 acquired_rmu = mpc->funcs->acquire_rmu(mpc, mpcc_id,
     130           0 :                                 stream->lut3d_func->state.bits.rmu_mux_num);
     131           0 :                 if (acquired_rmu != stream->lut3d_func->state.bits.rmu_mux_num)
     132           0 :                         BREAK_TO_DEBUGGER();
     133           0 :                 result = mpc->funcs->program_3dlut(mpc,
     134             :                                                                 &stream->lut3d_func->lut_3d,
     135           0 :                                                                 stream->lut3d_func->state.bits.rmu_mux_num);
     136           0 :                 result = mpc->funcs->program_shaper(mpc, shaper_lut,
     137           0 :                                 stream->lut3d_func->state.bits.rmu_mux_num);
     138             :         } else
     139             :                 /*loop through the available mux and release the requested mpcc_id*/
     140           0 :                 mpc->funcs->release_rmu(mpc, mpcc_id);
     141             : 
     142             : 
     143           0 :         return result;
     144             : }
     145             : 
     146           0 : bool dcn30_set_input_transfer_func(struct dc *dc,
     147             :                                 struct pipe_ctx *pipe_ctx,
     148             :                                 const struct dc_plane_state *plane_state)
     149             : {
     150           0 :         struct dce_hwseq *hws = dc->hwseq;
     151           0 :         struct dpp *dpp_base = pipe_ctx->plane_res.dpp;
     152             :         enum dc_transfer_func_predefined tf;
     153           0 :         bool result = true;
     154           0 :         struct pwl_params *params = NULL;
     155             : 
     156           0 :         if (dpp_base == NULL || plane_state == NULL)
     157             :                 return false;
     158             : 
     159           0 :         tf = TRANSFER_FUNCTION_UNITY;
     160             : 
     161           0 :         if (plane_state->in_transfer_func &&
     162           0 :                 plane_state->in_transfer_func->type == TF_TYPE_PREDEFINED)
     163           0 :                 tf = plane_state->in_transfer_func->tf;
     164             : 
     165           0 :         dpp_base->funcs->dpp_set_pre_degam(dpp_base, tf);
     166             : 
     167           0 :         if (plane_state->in_transfer_func) {
     168           0 :                 if (plane_state->in_transfer_func->type == TF_TYPE_HWPWL)
     169           0 :                         params = &plane_state->in_transfer_func->pwl;
     170           0 :                 else if (plane_state->in_transfer_func->type == TF_TYPE_DISTRIBUTED_POINTS &&
     171           0 :                         cm3_helper_translate_curve_to_hw_format(plane_state->in_transfer_func,
     172             :                                         &dpp_base->degamma_params, false))
     173           0 :                         params = &dpp_base->degamma_params;
     174             :         }
     175             : 
     176           0 :         result = dpp_base->funcs->dpp_program_gamcor_lut(dpp_base, params);
     177             : 
     178           0 :         if (pipe_ctx->stream_res.opp && pipe_ctx->stream_res.opp->ctx) {
     179           0 :                 if (dpp_base->funcs->dpp_program_blnd_lut)
     180           0 :                         hws->funcs.set_blend_lut(pipe_ctx, plane_state);
     181           0 :                 if (dpp_base->funcs->dpp_program_shaper_lut &&
     182           0 :                                 dpp_base->funcs->dpp_program_3dlut)
     183           0 :                         hws->funcs.set_shaper_3dlut(pipe_ctx, plane_state);
     184             :         }
     185             : 
     186             :         return result;
     187             : }
     188             : 
     189           0 : bool dcn30_set_output_transfer_func(struct dc *dc,
     190             :                                 struct pipe_ctx *pipe_ctx,
     191             :                                 const struct dc_stream_state *stream)
     192             : {
     193           0 :         int mpcc_id = pipe_ctx->plane_res.hubp->inst;
     194           0 :         struct mpc *mpc = pipe_ctx->stream_res.opp->ctx->dc->res_pool->mpc;
     195           0 :         struct pwl_params *params = NULL;
     196           0 :         bool ret = false;
     197             : 
     198             :         /* program OGAM or 3DLUT only for the top pipe*/
     199           0 :         if (pipe_ctx->top_pipe == NULL) {
     200             :                 /*program rmu shaper and 3dlut in MPC*/
     201           0 :                 ret = dcn30_set_mpc_shaper_3dlut(pipe_ctx, stream);
     202           0 :                 if (ret == false && mpc->funcs->set_output_gamma && stream->out_transfer_func) {
     203           0 :                         if (stream->out_transfer_func->type == TF_TYPE_HWPWL)
     204           0 :                                 params = &stream->out_transfer_func->pwl;
     205           0 :                         else if (pipe_ctx->stream->out_transfer_func->type ==
     206           0 :                                         TF_TYPE_DISTRIBUTED_POINTS &&
     207           0 :                                         cm3_helper_translate_curve_to_hw_format(
     208             :                                         stream->out_transfer_func,
     209             :                                         &mpc->blender_params, false))
     210           0 :                                 params = &mpc->blender_params;
     211             :                          /* there are no ROM LUTs in OUTGAM */
     212           0 :                         if (stream->out_transfer_func->type == TF_TYPE_PREDEFINED)
     213           0 :                                 BREAK_TO_DEBUGGER();
     214             :                 }
     215             :         }
     216             : 
     217           0 :         mpc->funcs->set_output_gamma(mpc, mpcc_id, params);
     218           0 :         return ret;
     219             : }
     220             : 
     221           0 : static void dcn30_set_writeback(
     222             :                 struct dc *dc,
     223             :                 struct dc_writeback_info *wb_info,
     224             :                 struct dc_state *context)
     225             : {
     226             :         struct mcif_wb *mcif_wb;
     227             :         struct mcif_buf_params *mcif_buf_params;
     228             : 
     229           0 :         ASSERT(wb_info->dwb_pipe_inst < MAX_DWB_PIPES);
     230           0 :         ASSERT(wb_info->wb_enabled);
     231           0 :         ASSERT(wb_info->mpcc_inst >= 0);
     232           0 :         ASSERT(wb_info->mpcc_inst < dc->res_pool->mpcc_count);
     233           0 :         mcif_wb = dc->res_pool->mcif_wb[wb_info->dwb_pipe_inst];
     234           0 :         mcif_buf_params = &wb_info->mcif_buf_params;
     235             : 
     236             :         /* set DWB MPC mux */
     237           0 :         dc->res_pool->mpc->funcs->set_dwb_mux(dc->res_pool->mpc,
     238             :                         wb_info->dwb_pipe_inst, wb_info->mpcc_inst);
     239             :         /* set MCIF_WB buffer and arbitration configuration */
     240           0 :         mcif_wb->funcs->config_mcif_buf(mcif_wb, mcif_buf_params, wb_info->dwb_params.dest_height);
     241           0 :         mcif_wb->funcs->config_mcif_arb(mcif_wb, &context->bw_ctx.bw.dcn.bw_writeback.mcif_wb_arb[wb_info->dwb_pipe_inst]);
     242           0 : }
     243             : 
     244           0 : void dcn30_update_writeback(
     245             :                 struct dc *dc,
     246             :                 struct dc_writeback_info *wb_info,
     247             :                 struct dc_state *context)
     248             : {
     249             :         struct dwbc *dwb;
     250           0 :         dwb = dc->res_pool->dwbc[wb_info->dwb_pipe_inst];
     251           0 :         DC_LOG_DWB("%s dwb_pipe_inst = %d, mpcc_inst = %d",\
     252             :                 __func__, wb_info->dwb_pipe_inst,\
     253             :                 wb_info->mpcc_inst);
     254             : 
     255           0 :         dcn30_set_writeback(dc, wb_info, context);
     256             : 
     257             :         /* update DWB */
     258           0 :         dwb->funcs->update(dwb, &wb_info->dwb_params);
     259           0 : }
     260             : 
     261           0 : bool dcn30_mmhubbub_warmup(
     262             :         struct dc *dc,
     263             :         unsigned int num_dwb,
     264             :         struct dc_writeback_info *wb_info)
     265             : {
     266             :         struct dwbc *dwb;
     267             :         struct mcif_wb *mcif_wb;
     268           0 :         struct mcif_warmup_params warmup_params = {0};
     269             :         unsigned int  i, i_buf;
     270             :         /*make sure there is no active DWB eanbled */
     271           0 :         for (i = 0; i < num_dwb; i++) {
     272           0 :                 dwb = dc->res_pool->dwbc[wb_info[i].dwb_pipe_inst];
     273           0 :                 if (dwb->dwb_is_efc_transition || dwb->dwb_is_drc) {
     274             :                         /*can not do warmup while any dwb enabled*/
     275             :                         return false;
     276             :                 }
     277             :         }
     278             : 
     279           0 :         if (wb_info->mcif_warmup_params.p_vmid == 0)
     280             :                 return false;
     281             : 
     282             :         /*check whether this is new interface: warmup big buffer once*/
     283           0 :         if (wb_info->mcif_warmup_params.start_address.quad_part != 0 &&
     284           0 :                 wb_info->mcif_warmup_params.region_size != 0) {
     285             :                 /*mmhubbub is shared, so it does not matter which MCIF*/
     286           0 :                 mcif_wb = dc->res_pool->mcif_wb[0];
     287             :                 /*warmup a big chunk of VM buffer at once*/
     288           0 :                 warmup_params.start_address.quad_part = wb_info->mcif_warmup_params.start_address.quad_part;
     289           0 :                 warmup_params.address_increment =  wb_info->mcif_warmup_params.region_size;
     290           0 :                 warmup_params.region_size = wb_info->mcif_warmup_params.region_size;
     291           0 :                 warmup_params.p_vmid = wb_info->mcif_warmup_params.p_vmid;
     292             : 
     293             :                 if (warmup_params.address_increment == 0)
     294             :                         warmup_params.address_increment = dc->dml.soc.vmm_page_size_bytes;
     295             : 
     296           0 :                 mcif_wb->funcs->warmup_mcif(mcif_wb, &warmup_params);
     297           0 :                 return true;
     298             :         }
     299             :         /*following is the original: warmup each DWB's mcif buffer*/
     300           0 :         for (i = 0; i < num_dwb; i++) {
     301           0 :                 dwb = dc->res_pool->dwbc[wb_info[i].dwb_pipe_inst];
     302           0 :                 mcif_wb = dc->res_pool->mcif_wb[wb_info[i].dwb_pipe_inst];
     303             :                 /*warmup is for VM mode only*/
     304           0 :                 if (wb_info[i].mcif_buf_params.p_vmid == 0)
     305             :                         return false;
     306             : 
     307             :                 /* Warmup MCIF_WB */
     308           0 :                 for (i_buf = 0; i_buf < MCIF_BUF_COUNT; i_buf++) {
     309           0 :                         warmup_params.start_address.quad_part = wb_info[i].mcif_buf_params.luma_address[i_buf];
     310           0 :                         warmup_params.address_increment = dc->dml.soc.vmm_page_size_bytes;
     311           0 :                         warmup_params.region_size = wb_info[i].mcif_buf_params.luma_pitch * wb_info[i].dwb_params.dest_height;
     312           0 :                         warmup_params.p_vmid = wb_info[i].mcif_buf_params.p_vmid;
     313           0 :                         mcif_wb->funcs->warmup_mcif(mcif_wb, &warmup_params);
     314             :                 }
     315             :         }
     316             :         return true;
     317             : }
     318             : 
     319           0 : void dcn30_enable_writeback(
     320             :                 struct dc *dc,
     321             :                 struct dc_writeback_info *wb_info,
     322             :                 struct dc_state *context)
     323             : {
     324             :         struct dwbc *dwb;
     325             :         struct mcif_wb *mcif_wb;
     326             :         struct timing_generator *optc;
     327             : 
     328           0 :         dwb = dc->res_pool->dwbc[wb_info->dwb_pipe_inst];
     329           0 :         mcif_wb = dc->res_pool->mcif_wb[wb_info->dwb_pipe_inst];
     330             : 
     331             :         /* set the OPTC source mux */
     332           0 :         optc = dc->res_pool->timing_generators[dwb->otg_inst];
     333           0 :         DC_LOG_DWB("%s dwb_pipe_inst = %d, mpcc_inst = %d",\
     334             :                 __func__, wb_info->dwb_pipe_inst,\
     335             :                 wb_info->mpcc_inst);
     336           0 :         if (IS_DIAG_DC(dc->ctx->dce_environment)) {
     337             :                 /*till diags switch to warmup interface*/
     338           0 :                 dcn30_mmhubbub_warmup(dc, 1, wb_info);
     339             :         }
     340             :         /* Update writeback pipe */
     341           0 :         dcn30_set_writeback(dc, wb_info, context);
     342             : 
     343             :         /* Enable MCIF_WB */
     344           0 :         mcif_wb->funcs->enable_mcif(mcif_wb);
     345             :         /* Enable DWB */
     346           0 :         dwb->funcs->enable(dwb, &wb_info->dwb_params);
     347           0 : }
     348             : 
     349           0 : void dcn30_disable_writeback(
     350             :                 struct dc *dc,
     351             :                 unsigned int dwb_pipe_inst)
     352             : {
     353             :         struct dwbc *dwb;
     354             :         struct mcif_wb *mcif_wb;
     355             : 
     356           0 :         ASSERT(dwb_pipe_inst < MAX_DWB_PIPES);
     357           0 :         dwb = dc->res_pool->dwbc[dwb_pipe_inst];
     358           0 :         mcif_wb = dc->res_pool->mcif_wb[dwb_pipe_inst];
     359           0 :         DC_LOG_DWB("%s dwb_pipe_inst = %d",\
     360             :                 __func__, dwb_pipe_inst);
     361             : 
     362             :         /* disable DWB */
     363           0 :         dwb->funcs->disable(dwb);
     364             :         /* disable MCIF */
     365           0 :         mcif_wb->funcs->disable_mcif(mcif_wb);
     366             :         /* disable MPC DWB mux */
     367           0 :         dc->res_pool->mpc->funcs->disable_dwb_mux(dc->res_pool->mpc, dwb_pipe_inst);
     368           0 : }
     369             : 
     370           0 : void dcn30_program_all_writeback_pipes_in_tree(
     371             :                 struct dc *dc,
     372             :                 const struct dc_stream_state *stream,
     373             :                 struct dc_state *context)
     374             : {
     375             :         struct dc_writeback_info wb_info;
     376             :         struct dwbc *dwb;
     377           0 :         struct dc_stream_status *stream_status = NULL;
     378             :         int i_wb, i_pipe, i_stream;
     379           0 :         DC_LOG_DWB("%s", __func__);
     380             : 
     381           0 :         ASSERT(stream);
     382           0 :         for (i_stream = 0; i_stream < context->stream_count; i_stream++) {
     383           0 :                 if (context->streams[i_stream] == stream) {
     384           0 :                         stream_status = &context->stream_status[i_stream];
     385           0 :                         break;
     386             :                 }
     387             :         }
     388           0 :         ASSERT(stream_status);
     389             : 
     390           0 :         ASSERT(stream->num_wb_info <= dc->res_pool->res_cap->num_dwb);
     391             :         /* For each writeback pipe */
     392           0 :         for (i_wb = 0; i_wb < stream->num_wb_info; i_wb++) {
     393             : 
     394             :                 /* copy writeback info to local non-const so mpcc_inst can be set */
     395           0 :                 wb_info = stream->writeback_info[i_wb];
     396           0 :                 if (wb_info.wb_enabled) {
     397             : 
     398             :                         /* get the MPCC instance for writeback_source_plane */
     399           0 :                         wb_info.mpcc_inst = -1;
     400           0 :                         for (i_pipe = 0; i_pipe < dc->res_pool->pipe_count; i_pipe++) {
     401           0 :                                 struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[i_pipe];
     402             : 
     403           0 :                                 if (!pipe_ctx->plane_state)
     404           0 :                                         continue;
     405             : 
     406           0 :                                 if (pipe_ctx->plane_state == wb_info.writeback_source_plane) {
     407           0 :                                         wb_info.mpcc_inst = pipe_ctx->plane_res.mpcc_inst;
     408           0 :                                         break;
     409             :                                 }
     410             :                         }
     411             : 
     412           0 :                         if (wb_info.mpcc_inst == -1) {
     413             :                                 /* Disable writeback pipe and disconnect from MPCC
     414             :                                  * if source plane has been removed
     415             :                                  */
     416           0 :                                 dc->hwss.disable_writeback(dc, wb_info.dwb_pipe_inst);
     417           0 :                                 continue;
     418             :                         }
     419             : 
     420           0 :                         ASSERT(wb_info.dwb_pipe_inst < dc->res_pool->res_cap->num_dwb);
     421           0 :                         dwb = dc->res_pool->dwbc[wb_info.dwb_pipe_inst];
     422           0 :                         if (dwb->funcs->is_enabled(dwb)) {
     423             :                                 /* writeback pipe already enabled, only need to update */
     424           0 :                                 dc->hwss.update_writeback(dc, &wb_info, context);
     425             :                         } else {
     426             :                                 /* Enable writeback pipe and connect to MPCC */
     427           0 :                                 dc->hwss.enable_writeback(dc, &wb_info, context);
     428             :                         }
     429             :                 } else {
     430             :                         /* Disable writeback pipe and disconnect from MPCC */
     431           0 :                         dc->hwss.disable_writeback(dc, wb_info.dwb_pipe_inst);
     432             :                 }
     433             :         }
     434           0 : }
     435             : 
     436           0 : void dcn30_init_hw(struct dc *dc)
     437             : {
     438           0 :         struct abm **abms = dc->res_pool->multiple_abms;
     439           0 :         struct dce_hwseq *hws = dc->hwseq;
     440           0 :         struct dc_bios *dcb = dc->ctx->dc_bios;
     441           0 :         struct resource_pool *res_pool = dc->res_pool;
     442             :         int i;
     443             :         int edp_num;
     444           0 :         uint32_t backlight = MAX_BACKLIGHT_LEVEL;
     445             : 
     446           0 :         if (dc->clk_mgr && dc->clk_mgr->funcs->init_clocks)
     447           0 :                 dc->clk_mgr->funcs->init_clocks(dc->clk_mgr);
     448             : 
     449             :         // Initialize the dccg
     450           0 :         if (res_pool->dccg->funcs->dccg_init)
     451           0 :                 res_pool->dccg->funcs->dccg_init(res_pool->dccg);
     452             : 
     453           0 :         if (IS_FPGA_MAXIMUS_DC(dc->ctx->dce_environment)) {
     454             : 
     455           0 :                 REG_WRITE(REFCLK_CNTL, 0);
     456           0 :                 REG_UPDATE(DCHUBBUB_GLOBAL_TIMER_CNTL, DCHUBBUB_GLOBAL_TIMER_ENABLE, 1);
     457           0 :                 REG_WRITE(DIO_MEM_PWR_CTRL, 0);
     458             : 
     459           0 :                 if (!dc->debug.disable_clock_gate) {
     460             :                         /* enable all DCN clock gating */
     461           0 :                         REG_WRITE(DCCG_GATE_DISABLE_CNTL, 0);
     462             : 
     463           0 :                         REG_WRITE(DCCG_GATE_DISABLE_CNTL2, 0);
     464             : 
     465           0 :                         REG_UPDATE(DCFCLK_CNTL, DCFCLK_GATE_DIS, 0);
     466             :                 }
     467             : 
     468             :                 //Enable ability to power gate / don't force power on permanently
     469           0 :                 if (hws->funcs.enable_power_gating_plane)
     470           0 :                         hws->funcs.enable_power_gating_plane(hws, true);
     471             : 
     472             :                 return;
     473             :         }
     474             : 
     475           0 :         if (!dcb->funcs->is_accelerated_mode(dcb)) {
     476           0 :                 hws->funcs.bios_golden_init(dc);
     477           0 :                 hws->funcs.disable_vga(dc->hwseq);
     478             :         }
     479             : 
     480           0 :         if (dc->debug.enable_mem_low_power.bits.dmcu) {
     481             :                 // Force ERAM to shutdown if DMCU is not enabled
     482           0 :                 if (dc->debug.disable_dmcu || dc->config.disable_dmcu) {
     483           0 :                         REG_UPDATE(DMU_MEM_PWR_CNTL, DMCU_ERAM_MEM_PWR_FORCE, 3);
     484             :                 }
     485             :         }
     486             : 
     487             :         // Set default OPTC memory power states
     488           0 :         if (dc->debug.enable_mem_low_power.bits.optc) {
     489             :                 // Shutdown when unassigned and light sleep in VBLANK
     490           0 :                 REG_SET_2(ODM_MEM_PWR_CTRL3, 0, ODM_MEM_UNASSIGNED_PWR_MODE, 3, ODM_MEM_VBLANK_PWR_MODE, 1);
     491             :         }
     492             : 
     493           0 :         if (dc->ctx->dc_bios->fw_info_valid) {
     494           0 :                 res_pool->ref_clocks.xtalin_clock_inKhz =
     495           0 :                                 dc->ctx->dc_bios->fw_info.pll_info.crystal_frequency;
     496             : 
     497           0 :                 if (!IS_FPGA_MAXIMUS_DC(dc->ctx->dce_environment)) {
     498           0 :                         if (res_pool->dccg && res_pool->hubbub) {
     499             : 
     500           0 :                                 (res_pool->dccg->funcs->get_dccg_ref_freq)(res_pool->dccg,
     501           0 :                                                 dc->ctx->dc_bios->fw_info.pll_info.crystal_frequency,
     502             :                                                 &res_pool->ref_clocks.dccg_ref_clock_inKhz);
     503             : 
     504           0 :                                 (res_pool->hubbub->funcs->get_dchub_ref_freq)(res_pool->hubbub,
     505             :                                                 res_pool->ref_clocks.dccg_ref_clock_inKhz,
     506             :                                                 &res_pool->ref_clocks.dchub_ref_clock_inKhz);
     507             :                         } else {
     508             :                                 // Not all ASICs have DCCG sw component
     509           0 :                                 res_pool->ref_clocks.dccg_ref_clock_inKhz =
     510             :                                                 res_pool->ref_clocks.xtalin_clock_inKhz;
     511           0 :                                 res_pool->ref_clocks.dchub_ref_clock_inKhz =
     512             :                                                 res_pool->ref_clocks.xtalin_clock_inKhz;
     513             :                         }
     514             :                 }
     515             :         } else
     516           0 :                 ASSERT_CRITICAL(false);
     517             : 
     518           0 :         for (i = 0; i < dc->link_count; i++) {
     519             :                 /* Power up AND update implementation according to the
     520             :                  * required signal (which may be different from the
     521             :                  * default signal on connector).
     522             :                  */
     523           0 :                 struct dc_link *link = dc->links[i];
     524             : 
     525           0 :                 link->link_enc->funcs->hw_init(link->link_enc);
     526             : 
     527             :                 /* Check for enabled DIG to identify enabled display */
     528           0 :                 if (link->link_enc->funcs->is_dig_enabled &&
     529           0 :                         link->link_enc->funcs->is_dig_enabled(link->link_enc)) {
     530           0 :                         link->link_status.link_active = true;
     531           0 :                         if (link->link_enc->funcs->fec_is_active &&
     532           0 :                                         link->link_enc->funcs->fec_is_active(link->link_enc))
     533           0 :                                 link->fec_state = dc_link_fec_enabled;
     534             :                 }
     535             :         }
     536             : 
     537             :         /* Power gate DSCs */
     538           0 :         for (i = 0; i < res_pool->res_cap->num_dsc; i++)
     539           0 :                 if (hws->funcs.dsc_pg_control != NULL)
     540           0 :                         hws->funcs.dsc_pg_control(hws, res_pool->dscs[i]->inst, false);
     541             : 
     542             :         /* we want to turn off all dp displays before doing detection */
     543           0 :         dc_link_blank_all_dp_displays(dc);
     544             : 
     545           0 :         if (hws->funcs.enable_power_gating_plane)
     546           0 :                 hws->funcs.enable_power_gating_plane(dc->hwseq, true);
     547             : 
     548             :         /* If taking control over from VBIOS, we may want to optimize our first
     549             :          * mode set, so we need to skip powering down pipes until we know which
     550             :          * pipes we want to use.
     551             :          * Otherwise, if taking control is not possible, we need to power
     552             :          * everything down.
     553             :          */
     554           0 :         if (dcb->funcs->is_accelerated_mode(dcb) || !dc->config.seamless_boot_edp_requested) {
     555           0 :                 hws->funcs.init_pipes(dc, dc->current_state);
     556           0 :                 if (dc->res_pool->hubbub->funcs->allow_self_refresh_control)
     557           0 :                         dc->res_pool->hubbub->funcs->allow_self_refresh_control(dc->res_pool->hubbub,
     558           0 :                                         !dc->res_pool->hubbub->ctx->dc->debug.disable_stutter);
     559             :         }
     560             : 
     561             :         /* In headless boot cases, DIG may be turned
     562             :          * on which causes HW/SW discrepancies.
     563             :          * To avoid this, power down hardware on boot
     564             :          * if DIG is turned on and seamless boot not enabled
     565             :          */
     566           0 :         if (!dc->config.seamless_boot_edp_requested) {
     567             :                 struct dc_link *edp_links[MAX_NUM_EDP];
     568             :                 struct dc_link *edp_link = NULL;
     569             : 
     570           0 :                 get_edp_links(dc, edp_links, &edp_num);
     571           0 :                 if (edp_num)
     572           0 :                         edp_link = edp_links[0];
     573           0 :                 if (edp_link && edp_link->link_enc->funcs->is_dig_enabled &&
     574           0 :                                 edp_link->link_enc->funcs->is_dig_enabled(edp_link->link_enc) &&
     575           0 :                                 dc->hwss.edp_backlight_control &&
     576           0 :                                 dc->hwss.power_down &&
     577           0 :                                 dc->hwss.edp_power_control) {
     578           0 :                         dc->hwss.edp_backlight_control(edp_link, false);
     579           0 :                         dc->hwss.power_down(dc);
     580           0 :                         dc->hwss.edp_power_control(edp_link, false);
     581             :                 } else {
     582           0 :                         for (i = 0; i < dc->link_count; i++) {
     583           0 :                                 struct dc_link *link = dc->links[i];
     584             : 
     585           0 :                                 if (link->link_enc->funcs->is_dig_enabled &&
     586           0 :                                                 link->link_enc->funcs->is_dig_enabled(link->link_enc) &&
     587           0 :                                                 dc->hwss.power_down) {
     588           0 :                                         dc->hwss.power_down(dc);
     589           0 :                                         break;
     590             :                                 }
     591             : 
     592             :                         }
     593             :                 }
     594             :         }
     595             : 
     596           0 :         for (i = 0; i < res_pool->audio_count; i++) {
     597           0 :                 struct audio *audio = res_pool->audios[i];
     598             : 
     599           0 :                 audio->funcs->hw_init(audio);
     600             :         }
     601             : 
     602           0 :         for (i = 0; i < dc->link_count; i++) {
     603           0 :                 struct dc_link *link = dc->links[i];
     604             : 
     605           0 :                 if (link->panel_cntl)
     606           0 :                         backlight = link->panel_cntl->funcs->hw_init(link->panel_cntl);
     607             :         }
     608             : 
     609           0 :         for (i = 0; i < dc->res_pool->pipe_count; i++) {
     610           0 :                 if (abms[i] != NULL)
     611           0 :                         abms[i]->funcs->abm_init(abms[i], backlight);
     612             :         }
     613             : 
     614             :         /* power AFMT HDMI memory TODO: may move to dis/en output save power*/
     615           0 :         REG_WRITE(DIO_MEM_PWR_CTRL, 0);
     616             : 
     617           0 :         if (!dc->debug.disable_clock_gate) {
     618             :                 /* enable all DCN clock gating */
     619           0 :                 REG_WRITE(DCCG_GATE_DISABLE_CNTL, 0);
     620             : 
     621           0 :                 REG_WRITE(DCCG_GATE_DISABLE_CNTL2, 0);
     622             : 
     623           0 :                 REG_UPDATE(DCFCLK_CNTL, DCFCLK_GATE_DIS, 0);
     624             :         }
     625             : 
     626           0 :         if (!dcb->funcs->is_accelerated_mode(dcb) && dc->res_pool->hubbub->funcs->init_watermarks)
     627           0 :                 dc->res_pool->hubbub->funcs->init_watermarks(dc->res_pool->hubbub);
     628             : 
     629           0 :         if (dc->clk_mgr->funcs->notify_wm_ranges)
     630           0 :                 dc->clk_mgr->funcs->notify_wm_ranges(dc->clk_mgr);
     631             : 
     632           0 :         if (dc->clk_mgr->funcs->set_hard_max_memclk)
     633           0 :                 dc->clk_mgr->funcs->set_hard_max_memclk(dc->clk_mgr);
     634             : 
     635           0 :         if (dc->res_pool->hubbub->funcs->force_pstate_change_control)
     636           0 :                 dc->res_pool->hubbub->funcs->force_pstate_change_control(
     637             :                                 dc->res_pool->hubbub, false, false);
     638           0 :         if (dc->res_pool->hubbub->funcs->init_crb)
     639           0 :                 dc->res_pool->hubbub->funcs->init_crb(dc->res_pool->hubbub);
     640             : 
     641             :         // Get DMCUB capabilities
     642           0 :         dc_dmub_srv_query_caps_cmd(dc->ctx->dmub_srv->dmub);
     643           0 :         dc->caps.dmub_caps.psr = dc->ctx->dmub_srv->dmub->feature_caps.psr;
     644           0 :         dc->caps.dmub_caps.mclk_sw = dc->ctx->dmub_srv->dmub->feature_caps.fw_assisted_mclk_switch;
     645             : }
     646             : 
     647           0 : void dcn30_set_avmute(struct pipe_ctx *pipe_ctx, bool enable)
     648             : {
     649           0 :         if (pipe_ctx == NULL)
     650             :                 return;
     651             : 
     652           0 :         if (dc_is_hdmi_signal(pipe_ctx->stream->signal) && pipe_ctx->stream_res.stream_enc != NULL)
     653           0 :                 pipe_ctx->stream_res.stream_enc->funcs->set_avmute(
     654             :                                 pipe_ctx->stream_res.stream_enc,
     655             :                                 enable);
     656             : }
     657             : 
     658           0 : void dcn30_update_info_frame(struct pipe_ctx *pipe_ctx)
     659             : {
     660             :         bool is_hdmi_tmds;
     661             :         bool is_dp;
     662             : 
     663           0 :         ASSERT(pipe_ctx->stream);
     664             : 
     665           0 :         if (pipe_ctx->stream_res.stream_enc == NULL)
     666             :                 return;  /* this is not root pipe */
     667             : 
     668           0 :         is_hdmi_tmds = dc_is_hdmi_tmds_signal(pipe_ctx->stream->signal);
     669           0 :         is_dp = dc_is_dp_signal(pipe_ctx->stream->signal);
     670             : 
     671           0 :         if (!is_hdmi_tmds && !is_dp)
     672             :                 return;
     673             : 
     674           0 :         if (is_hdmi_tmds)
     675           0 :                 pipe_ctx->stream_res.stream_enc->funcs->update_hdmi_info_packets(
     676             :                         pipe_ctx->stream_res.stream_enc,
     677           0 :                         &pipe_ctx->stream_res.encoder_info_frame);
     678             :         else
     679           0 :                 pipe_ctx->stream_res.stream_enc->funcs->update_dp_info_packets(
     680             :                         pipe_ctx->stream_res.stream_enc,
     681           0 :                         &pipe_ctx->stream_res.encoder_info_frame);
     682             : }
     683             : 
     684           0 : void dcn30_program_dmdata_engine(struct pipe_ctx *pipe_ctx)
     685             : {
     686           0 :         struct dc_stream_state    *stream     = pipe_ctx->stream;
     687           0 :         struct hubp               *hubp       = pipe_ctx->plane_res.hubp;
     688           0 :         bool                       enable     = false;
     689           0 :         struct stream_encoder     *stream_enc = pipe_ctx->stream_res.stream_enc;
     690           0 :         enum dynamic_metadata_mode mode       = dc_is_dp_signal(stream->signal)
     691             :                                                         ? dmdata_dp
     692           0 :                                                         : dmdata_hdmi;
     693             : 
     694             :         /* if using dynamic meta, don't set up generic infopackets */
     695           0 :         if (pipe_ctx->stream->dmdata_address.quad_part != 0) {
     696           0 :                 pipe_ctx->stream_res.encoder_info_frame.hdrsmd.valid = false;
     697           0 :                 enable = true;
     698             :         }
     699             : 
     700           0 :         if (!hubp)
     701             :                 return;
     702             : 
     703           0 :         if (!stream_enc || !stream_enc->funcs->set_dynamic_metadata)
     704             :                 return;
     705             : 
     706           0 :         stream_enc->funcs->set_dynamic_metadata(stream_enc, enable,
     707           0 :                                                         hubp->inst, mode);
     708             : }
     709             : 
     710           0 : bool dcn30_apply_idle_power_optimizations(struct dc *dc, bool enable)
     711             : {
     712             :         union dmub_rb_cmd cmd;
     713           0 :         uint32_t tmr_delay = 0, tmr_scale = 0;
     714             :         struct dc_cursor_attributes cursor_attr;
     715           0 :         bool cursor_cache_enable = false;
     716           0 :         struct dc_stream_state *stream = NULL;
     717           0 :         struct dc_plane_state *plane = NULL;
     718             : 
     719           0 :         if (!dc->ctx->dmub_srv)
     720             :                 return false;
     721             : 
     722           0 :         if (enable) {
     723           0 :                 if (dc->current_state) {
     724             :                         int i;
     725             : 
     726             :                         /* First, check no-memory-requests case */
     727           0 :                         for (i = 0; i < dc->current_state->stream_count; i++) {
     728           0 :                                 if (dc->current_state->stream_status[i].plane_count)
     729             :                                         /* Fail eligibility on a visible stream */
     730             :                                         break;
     731             :                         }
     732             : 
     733           0 :                         if (i == dc->current_state->stream_count) {
     734             :                                 /* Enable no-memory-requests case */
     735           0 :                                 memset(&cmd, 0, sizeof(cmd));
     736           0 :                                 cmd.mall.header.type = DMUB_CMD__MALL;
     737           0 :                                 cmd.mall.header.sub_type = DMUB_CMD__MALL_ACTION_NO_DF_REQ;
     738           0 :                                 cmd.mall.header.payload_bytes = sizeof(cmd.mall) - sizeof(cmd.mall.header);
     739             : 
     740           0 :                                 dc_dmub_srv_cmd_queue(dc->ctx->dmub_srv, &cmd);
     741           0 :                                 dc_dmub_srv_cmd_execute(dc->ctx->dmub_srv);
     742             : 
     743           0 :                                 return true;
     744             :                         }
     745             : 
     746           0 :                         stream = dc->current_state->streams[0];
     747           0 :                         plane = (stream ? dc->current_state->stream_status[0].plane_states[0] : NULL);
     748             : 
     749           0 :                         if (stream && plane) {
     750           0 :                                 cursor_cache_enable = stream->cursor_position.enable &&
     751           0 :                                                 plane->address.grph.cursor_cache_addr.quad_part;
     752           0 :                                 cursor_attr = stream->cursor_attributes;
     753             :                         }
     754             : 
     755             :                         /*
     756             :                          * Second, check MALL eligibility
     757             :                          *
     758             :                          * single display only, single surface only, 8 and 16 bit formats only, no VM,
     759             :                          * do not use MALL for displays that support PSR as they use D0i3.2 in DMCUB FW
     760             :                          *
     761             :                          * TODO: When we implement multi-display, PSR displays will be allowed if there is
     762             :                          * a non-PSR display present, since in that case we can't do D0i3.2
     763             :                          */
     764           0 :                         if (dc->current_state->stream_count == 1 &&
     765           0 :                                         stream->link->psr_settings.psr_version == DC_PSR_VERSION_UNSUPPORTED &&
     766           0 :                                         dc->current_state->stream_status[0].plane_count == 1 &&
     767           0 :                                         plane->format <= SURFACE_PIXEL_FORMAT_GRPH_ABGR16161616F &&
     768           0 :                                         plane->format >= SURFACE_PIXEL_FORMAT_GRPH_ARGB8888 &&
     769           0 :                                         plane->address.page_table_base.quad_part == 0 &&
     770           0 :                                         dc->hwss.does_plane_fit_in_mall &&
     771           0 :                                         dc->hwss.does_plane_fit_in_mall(dc, plane,
     772             :                                                         cursor_cache_enable ? &cursor_attr : NULL)) {
     773           0 :                                 unsigned int v_total = stream->adjust.v_total_max ?
     774           0 :                                                 stream->adjust.v_total_max : stream->timing.v_total;
     775           0 :                                 unsigned int refresh_hz = div_u64((unsigned long long) stream->timing.pix_clk_100hz *
     776           0 :                                                 100LL, (v_total * stream->timing.h_total));
     777             : 
     778             :                                 /*
     779             :                                  * one frame time in microsec:
     780             :                                  * Delay_Us = 1000000 / refresh
     781             :                                  * dynamic_delay_us = 1000000 / refresh + 2 * stutter_period
     782             :                                  *
     783             :                                  * one frame time modified by 'additional timer percent' (p):
     784             :                                  * Delay_Us_modified = dynamic_delay_us + dynamic_delay_us * p / 100
     785             :                                  *                   = dynamic_delay_us * (1 + p / 100)
     786             :                                  *                   = (1000000 / refresh + 2 * stutter_period) * (100 + p) / 100
     787             :                                  *                   = (1000000 + 2 * stutter_period * refresh) * (100 + p) / (100 * refresh)
     788             :                                  *
     789             :                                  * formula for timer duration based on parameters, from regspec:
     790             :                                  * dynamic_delay_us = 65.28 * (64 + MallFrameCacheTmrDly) * 2^MallFrameCacheTmrScale
     791             :                                  *
     792             :                                  * dynamic_delay_us / 65.28 = (64 + MallFrameCacheTmrDly) * 2^MallFrameCacheTmrScale
     793             :                                  * (dynamic_delay_us / 65.28) / 2^MallFrameCacheTmrScale = 64 + MallFrameCacheTmrDly
     794             :                                  * MallFrameCacheTmrDly = ((dynamic_delay_us / 65.28) / 2^MallFrameCacheTmrScale) - 64
     795             :                                  *                      = (1000000 + 2 * stutter_period * refresh) * (100 + p) / (100 * refresh) / 65.28 / 2^MallFrameCacheTmrScale - 64
     796             :                                  *                      = (1000000 + 2 * stutter_period * refresh) * (100 + p) / (refresh * 6528 * 2^MallFrameCacheTmrScale) - 64
     797             :                                  *
     798             :                                  * need to round up the result of the division before the subtraction
     799             :                                  */
     800           0 :                                 unsigned int denom = refresh_hz * 6528;
     801           0 :                                 unsigned int stutter_period = dc->current_state->perf_params.stutter_period_us;
     802             : 
     803           0 :                                 tmr_delay = div_u64(((1000000LL + 2 * stutter_period * refresh_hz) *
     804           0 :                                                 (100LL + dc->debug.mall_additional_timer_percent) + denom - 1),
     805           0 :                                                 denom) - 64LL;
     806             : 
     807             :                                 /* In some cases the stutter period is really big (tiny modes) in these
     808             :                                  * cases MALL cant be enabled, So skip these cases to avoid a ASSERT()
     809             :                                  *
     810             :                                  * We can check if stutter_period is more than 1/10th the frame time to
     811             :                                  * consider if we can actually meet the range of hysteresis timer
     812             :                                  */
     813           0 :                                 if (stutter_period > 100000/refresh_hz)
     814             :                                         return false;
     815             : 
     816             :                                 /* scale should be increased until it fits into 6 bits */
     817           0 :                                 while (tmr_delay & ~0x3F) {
     818           0 :                                         tmr_scale++;
     819             : 
     820           0 :                                         if (tmr_scale > 3) {
     821             :                                                 /* Delay exceeds range of hysteresis timer */
     822           0 :                                                 ASSERT(false);
     823             :                                                 return false;
     824             :                                         }
     825             : 
     826           0 :                                         denom *= 2;
     827           0 :                                         tmr_delay = div_u64(((1000000LL + 2 * stutter_period * refresh_hz) *
     828           0 :                                                         (100LL + dc->debug.mall_additional_timer_percent) + denom - 1),
     829           0 :                                                         denom) - 64LL;
     830             :                                 }
     831             : 
     832             :                                 /* Copy HW cursor */
     833           0 :                                 if (cursor_cache_enable) {
     834           0 :                                         memset(&cmd, 0, sizeof(cmd));
     835           0 :                                         cmd.mall.header.type = DMUB_CMD__MALL;
     836           0 :                                         cmd.mall.header.sub_type = DMUB_CMD__MALL_ACTION_COPY_CURSOR;
     837           0 :                                         cmd.mall.header.payload_bytes =
     838             :                                                         sizeof(cmd.mall) - sizeof(cmd.mall.header);
     839             : 
     840           0 :                                         switch (cursor_attr.color_format) {
     841             :                                         case CURSOR_MODE_MONO:
     842           0 :                                                 cmd.mall.cursor_bpp = 2;
     843           0 :                                                 break;
     844             :                                         case CURSOR_MODE_COLOR_1BIT_AND:
     845             :                                         case CURSOR_MODE_COLOR_PRE_MULTIPLIED_ALPHA:
     846             :                                         case CURSOR_MODE_COLOR_UN_PRE_MULTIPLIED_ALPHA:
     847           0 :                                                 cmd.mall.cursor_bpp = 32;
     848           0 :                                                 break;
     849             : 
     850             :                                         case CURSOR_MODE_COLOR_64BIT_FP_PRE_MULTIPLIED:
     851             :                                         case CURSOR_MODE_COLOR_64BIT_FP_UN_PRE_MULTIPLIED:
     852           0 :                                                 cmd.mall.cursor_bpp = 64;
     853           0 :                                                 break;
     854             :                                         }
     855             : 
     856           0 :                                         cmd.mall.cursor_copy_src.quad_part = cursor_attr.address.quad_part;
     857           0 :                                         cmd.mall.cursor_copy_dst.quad_part =
     858           0 :                                                         (plane->address.grph.cursor_cache_addr.quad_part + 2047) & ~2047;
     859           0 :                                         cmd.mall.cursor_width = cursor_attr.width;
     860           0 :                                         cmd.mall.cursor_height = cursor_attr.height;
     861           0 :                                         cmd.mall.cursor_pitch = cursor_attr.pitch;
     862             : 
     863           0 :                                         dc_dmub_srv_cmd_queue(dc->ctx->dmub_srv, &cmd);
     864           0 :                                         dc_dmub_srv_cmd_execute(dc->ctx->dmub_srv);
     865           0 :                                         dc_dmub_srv_wait_idle(dc->ctx->dmub_srv);
     866             : 
     867             :                                         /* Use copied cursor, and it's okay to not switch back */
     868           0 :                                         cursor_attr.address.quad_part = cmd.mall.cursor_copy_dst.quad_part;
     869           0 :                                         dc_stream_set_cursor_attributes(stream, &cursor_attr);
     870             :                                 }
     871             : 
     872             :                                 /* Enable MALL */
     873           0 :                                 memset(&cmd, 0, sizeof(cmd));
     874           0 :                                 cmd.mall.header.type = DMUB_CMD__MALL;
     875           0 :                                 cmd.mall.header.sub_type = DMUB_CMD__MALL_ACTION_ALLOW;
     876           0 :                                 cmd.mall.header.payload_bytes = sizeof(cmd.mall) - sizeof(cmd.mall.header);
     877           0 :                                 cmd.mall.tmr_delay = tmr_delay;
     878           0 :                                 cmd.mall.tmr_scale = tmr_scale;
     879           0 :                                 cmd.mall.debug_bits = dc->debug.mall_error_as_fatal;
     880             : 
     881           0 :                                 dc_dmub_srv_cmd_queue(dc->ctx->dmub_srv, &cmd);
     882           0 :                                 dc_dmub_srv_cmd_execute(dc->ctx->dmub_srv);
     883             : 
     884           0 :                                 return true;
     885             :                         }
     886             :                 }
     887             : 
     888             :                 /* No applicable optimizations */
     889             :                 return false;
     890             :         }
     891             : 
     892             :         /* Disable MALL */
     893           0 :         memset(&cmd, 0, sizeof(cmd));
     894           0 :         cmd.mall.header.type = DMUB_CMD__MALL;
     895           0 :         cmd.mall.header.sub_type = DMUB_CMD__MALL_ACTION_DISALLOW;
     896           0 :         cmd.mall.header.payload_bytes =
     897             :                 sizeof(cmd.mall) - sizeof(cmd.mall.header);
     898             : 
     899           0 :         dc_dmub_srv_cmd_queue(dc->ctx->dmub_srv, &cmd);
     900           0 :         dc_dmub_srv_cmd_execute(dc->ctx->dmub_srv);
     901           0 :         dc_dmub_srv_wait_idle(dc->ctx->dmub_srv);
     902             : 
     903           0 :         return true;
     904             : }
     905             : 
     906           0 : bool dcn30_does_plane_fit_in_mall(struct dc *dc, struct dc_plane_state *plane, struct dc_cursor_attributes *cursor_attr)
     907             : {
     908             :         // add meta size?
     909           0 :         unsigned int surface_size = plane->plane_size.surface_pitch * plane->plane_size.surface_size.height *
     910           0 :                         (plane->format >= SURFACE_PIXEL_FORMAT_GRPH_ARGB16161616 ? 8 : 4);
     911           0 :         unsigned int mall_size = dc->caps.mall_size_total;
     912           0 :         unsigned int cursor_size = 0;
     913             : 
     914           0 :         if (dc->debug.mall_size_override)
     915           0 :                 mall_size = 1024 * 1024 * dc->debug.mall_size_override;
     916             : 
     917           0 :         if (cursor_attr) {
     918           0 :                 cursor_size = dc->caps.max_cursor_size * dc->caps.max_cursor_size;
     919             : 
     920           0 :                 switch (cursor_attr->color_format) {
     921             :                 case CURSOR_MODE_MONO:
     922           0 :                         cursor_size /= 2;
     923           0 :                         break;
     924             :                 case CURSOR_MODE_COLOR_1BIT_AND:
     925             :                 case CURSOR_MODE_COLOR_PRE_MULTIPLIED_ALPHA:
     926             :                 case CURSOR_MODE_COLOR_UN_PRE_MULTIPLIED_ALPHA:
     927           0 :                         cursor_size *= 4;
     928           0 :                         break;
     929             : 
     930             :                 case CURSOR_MODE_COLOR_64BIT_FP_PRE_MULTIPLIED:
     931             :                 case CURSOR_MODE_COLOR_64BIT_FP_UN_PRE_MULTIPLIED:
     932           0 :                         cursor_size *= 8;
     933           0 :                         break;
     934             :                 }
     935             :         }
     936             : 
     937           0 :         return (surface_size + cursor_size) < mall_size;
     938             : }
     939             : 
     940           0 : void dcn30_hardware_release(struct dc *dc)
     941             : {
     942           0 :         dc_dmub_srv_p_state_delegate(dc, false, NULL);
     943             : 
     944             :         /* If pstate unsupported, or still supported
     945             :          * by firmware, force it supported by dcn
     946             :          */
     947           0 :         if (dc->current_state)
     948           0 :                 if ((!dc->clk_mgr->clks.p_state_change_support ||
     949           0 :                                 dc->current_state->bw_ctx.bw.dcn.clk.fw_based_mclk_switching) &&
     950           0 :                                 dc->res_pool->hubbub->funcs->force_pstate_change_control)
     951           0 :                         dc->res_pool->hubbub->funcs->force_pstate_change_control(
     952             :                                         dc->res_pool->hubbub, true, true);
     953           0 : }
     954             : 
     955           0 : void dcn30_set_disp_pattern_generator(const struct dc *dc,
     956             :                 struct pipe_ctx *pipe_ctx,
     957             :                 enum controller_dp_test_pattern test_pattern,
     958             :                 enum controller_dp_color_space color_space,
     959             :                 enum dc_color_depth color_depth,
     960             :                 const struct tg_color *solid_color,
     961             :                 int width, int height, int offset)
     962             : {
     963           0 :         pipe_ctx->stream_res.opp->funcs->opp_set_disp_pattern_generator(pipe_ctx->stream_res.opp, test_pattern,
     964             :                         color_space, color_depth, solid_color, width, height, offset);
     965           0 : }
     966             : 
     967           0 : void dcn30_prepare_bandwidth(struct dc *dc,
     968             :         struct dc_state *context)
     969             : {
     970           0 :         if (dc->clk_mgr->dc_mode_softmax_enabled)
     971           0 :                 if (dc->clk_mgr->clks.dramclk_khz <= dc->clk_mgr->bw_params->dc_mode_softmax_memclk * 1000 &&
     972           0 :                                 context->bw_ctx.bw.dcn.clk.dramclk_khz > dc->clk_mgr->bw_params->dc_mode_softmax_memclk * 1000)
     973           0 :                         dc->clk_mgr->funcs->set_max_memclk(dc->clk_mgr, dc->clk_mgr->bw_params->clk_table.entries[dc->clk_mgr->bw_params->clk_table.num_entries - 1].memclk_mhz);
     974             : 
     975           0 :         dcn20_prepare_bandwidth(dc, context);
     976             : 
     977           0 :         dc_dmub_srv_p_state_delegate(dc,
     978           0 :                 context->bw_ctx.bw.dcn.clk.fw_based_mclk_switching, context);
     979           0 : }
     980             : 

Generated by: LCOV version 1.14