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

          Line data    Source code
       1             : /*
       2             :  * Copyright 2016 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             : #include "dm_services.h"
      27             : #include "basics/dc_common.h"
      28             : #include "core_types.h"
      29             : #include "resource.h"
      30             : #include "dcn201_hwseq.h"
      31             : #include "dcn201_optc.h"
      32             : #include "dce/dce_hwseq.h"
      33             : #include "hubp.h"
      34             : #include "dchubbub.h"
      35             : #include "timing_generator.h"
      36             : #include "opp.h"
      37             : #include "ipp.h"
      38             : #include "mpc.h"
      39             : #include "dccg.h"
      40             : #include "clk_mgr.h"
      41             : #include "reg_helper.h"
      42             : 
      43             : #define CTX \
      44             :         hws->ctx
      45             : 
      46             : #define REG(reg)\
      47             :         hws->regs->reg
      48             : 
      49             : #define DC_LOGGER \
      50             :         dc->ctx->logger
      51             : 
      52             : #undef FN
      53             : #define FN(reg_name, field_name) \
      54             :         hws->shifts->field_name, hws->masks->field_name
      55             : 
      56           0 : static bool patch_address_for_sbs_tb_stereo(
      57             :                 struct pipe_ctx *pipe_ctx, PHYSICAL_ADDRESS_LOC *addr)
      58             : {
      59           0 :         struct dc_plane_state *plane_state = pipe_ctx->plane_state;
      60           0 :         bool sec_split = pipe_ctx->top_pipe &&
      61           0 :                 pipe_ctx->top_pipe->plane_state == pipe_ctx->plane_state;
      62             : 
      63           0 :         if (sec_split && plane_state->address.type == PLN_ADDR_TYPE_GRPH_STEREO &&
      64           0 :                 (pipe_ctx->stream->timing.timing_3d_format ==
      65           0 :                         TIMING_3D_FORMAT_SIDE_BY_SIDE ||
      66             :                 pipe_ctx->stream->timing.timing_3d_format ==
      67             :                         TIMING_3D_FORMAT_TOP_AND_BOTTOM)) {
      68           0 :                 *addr = plane_state->address.grph_stereo.left_addr;
      69           0 :                 plane_state->address.grph_stereo.left_addr =
      70             :                         plane_state->address.grph_stereo.right_addr;
      71           0 :                 return true;
      72             :         } else {
      73           0 :                 if (pipe_ctx->stream->view_format != VIEW_3D_FORMAT_NONE &&
      74           0 :                         plane_state->address.type != PLN_ADDR_TYPE_GRPH_STEREO) {
      75           0 :                         plane_state->address.type = PLN_ADDR_TYPE_GRPH_STEREO;
      76           0 :                         plane_state->address.grph_stereo.right_addr =
      77             :                         plane_state->address.grph_stereo.left_addr;
      78           0 :                         plane_state->address.grph_stereo.right_meta_addr =
      79             :                         plane_state->address.grph_stereo.left_meta_addr;
      80             :                 }
      81             :         }
      82             :         return false;
      83             : }
      84             : 
      85             : static void gpu_addr_to_uma(struct dce_hwseq *hwseq,
      86             :                 PHYSICAL_ADDRESS_LOC *addr)
      87             : {
      88             :         bool is_in_uma;
      89             : 
      90           0 :         if (hwseq->fb_base.quad_part <= addr->quad_part &&
      91           0 :                         addr->quad_part < hwseq->fb_top.quad_part) {
      92           0 :                 addr->quad_part -= hwseq->fb_base.quad_part;
      93           0 :                 addr->quad_part += hwseq->fb_offset.quad_part;
      94           0 :                 is_in_uma = true;
      95             :         } else if (hwseq->fb_offset.quad_part <= addr->quad_part &&
      96             :                         addr->quad_part <= hwseq->uma_top.quad_part) {
      97             :                 is_in_uma = true;
      98             :         } else {
      99             :                 is_in_uma = false;
     100             :         }
     101             : }
     102             : 
     103           0 : static void plane_address_in_gpu_space_to_uma(struct dce_hwseq *hwseq,
     104             :                 struct dc_plane_address *addr)
     105             : {
     106           0 :         switch (addr->type) {
     107             :         case PLN_ADDR_TYPE_GRAPHICS:
     108           0 :                 gpu_addr_to_uma(hwseq, &addr->grph.addr);
     109           0 :                 gpu_addr_to_uma(hwseq, &addr->grph.meta_addr);
     110             :                 break;
     111             :         case PLN_ADDR_TYPE_GRPH_STEREO:
     112           0 :                 gpu_addr_to_uma(hwseq, &addr->grph_stereo.left_addr);
     113           0 :                 gpu_addr_to_uma(hwseq, &addr->grph_stereo.left_meta_addr);
     114           0 :                 gpu_addr_to_uma(hwseq, &addr->grph_stereo.right_addr);
     115           0 :                 gpu_addr_to_uma(hwseq, &addr->grph_stereo.right_meta_addr);
     116             :                 break;
     117             :         case PLN_ADDR_TYPE_VIDEO_PROGRESSIVE:
     118           0 :                 gpu_addr_to_uma(hwseq, &addr->video_progressive.luma_addr);
     119           0 :                 gpu_addr_to_uma(hwseq, &addr->video_progressive.luma_meta_addr);
     120           0 :                 gpu_addr_to_uma(hwseq, &addr->video_progressive.chroma_addr);
     121           0 :                 gpu_addr_to_uma(hwseq, &addr->video_progressive.chroma_meta_addr);
     122             :                 break;
     123             :         default:
     124           0 :                 BREAK_TO_DEBUGGER();
     125           0 :                 break;
     126             :         }
     127           0 : }
     128             : 
     129           0 : void dcn201_update_plane_addr(const struct dc *dc, struct pipe_ctx *pipe_ctx)
     130             : {
     131           0 :         bool addr_patched = false;
     132             :         PHYSICAL_ADDRESS_LOC addr;
     133           0 :         struct dc_plane_state *plane_state = pipe_ctx->plane_state;
     134           0 :         struct dce_hwseq *hws = dc->hwseq;
     135             :         struct dc_plane_address uma;
     136             : 
     137           0 :         if (plane_state == NULL)
     138           0 :                 return;
     139             : 
     140           0 :         uma = plane_state->address;
     141           0 :         addr_patched = patch_address_for_sbs_tb_stereo(pipe_ctx, &addr);
     142             : 
     143           0 :         plane_address_in_gpu_space_to_uma(hws, &uma);
     144             : 
     145           0 :         pipe_ctx->plane_res.hubp->funcs->hubp_program_surface_flip_and_addr(
     146             :                         pipe_ctx->plane_res.hubp,
     147             :                         &uma,
     148           0 :                         plane_state->flip_immediate);
     149             : 
     150           0 :         plane_state->status.requested_address = plane_state->address;
     151             : 
     152           0 :         if (plane_state->flip_immediate)
     153           0 :                 plane_state->status.current_address = plane_state->address;
     154             : 
     155           0 :         if (addr_patched)
     156           0 :                 pipe_ctx->plane_state->address.grph_stereo.left_addr = addr;
     157             : }
     158             : 
     159             : /* Blank pixel data during initialization */
     160           0 : void dcn201_init_blank(
     161             :                 struct dc *dc,
     162             :                 struct timing_generator *tg)
     163             : {
     164           0 :         struct dce_hwseq *hws = dc->hwseq;
     165             :         enum dc_color_space color_space;
     166           0 :         struct tg_color black_color = {0};
     167           0 :         struct output_pixel_processor *opp = NULL;
     168             :         uint32_t num_opps, opp_id_src0, opp_id_src1;
     169             :         uint32_t otg_active_width, otg_active_height;
     170             : 
     171             :         /* program opp dpg blank color */
     172           0 :         color_space = COLOR_SPACE_SRGB;
     173           0 :         color_space_to_black_color(dc, color_space, &black_color);
     174             : 
     175             :         /* get the OTG active size */
     176           0 :         tg->funcs->get_otg_active_size(tg,
     177             :                         &otg_active_width,
     178             :                         &otg_active_height);
     179             : 
     180             :         /* get the OPTC source */
     181           0 :         tg->funcs->get_optc_source(tg, &num_opps, &opp_id_src0, &opp_id_src1);
     182           0 :         ASSERT(opp_id_src0 < dc->res_pool->res_cap->num_opp);
     183           0 :         opp = dc->res_pool->opps[opp_id_src0];
     184             : 
     185           0 :         opp->funcs->opp_set_disp_pattern_generator(
     186             :                         opp,
     187             :                         CONTROLLER_DP_TEST_PATTERN_SOLID_COLOR,
     188             :                         CONTROLLER_DP_COLOR_SPACE_UDEFINED,
     189             :                         COLOR_DEPTH_UNDEFINED,
     190             :                         &black_color,
     191             :                         otg_active_width,
     192             :                         otg_active_height,
     193             :                         0);
     194             : 
     195           0 :         hws->funcs.wait_for_blank_complete(opp);
     196           0 : }
     197             : 
     198           0 : static void read_mmhub_vm_setup(struct dce_hwseq *hws)
     199             : {
     200           0 :         uint32_t fb_base = REG_READ(MC_VM_FB_LOCATION_BASE);
     201           0 :         uint32_t fb_top = REG_READ(MC_VM_FB_LOCATION_TOP);
     202           0 :         uint32_t fb_offset = REG_READ(MC_VM_FB_OFFSET);
     203             : 
     204             :         /* MC_VM_FB_LOCATION_TOP is in pages, actual top should add 1 */
     205           0 :         fb_top++;
     206             : 
     207             :         /* bit 23:0 in register map to bit 47:24 in address */
     208           0 :         hws->fb_base.low_part = fb_base;
     209           0 :         hws->fb_base.quad_part <<= 24;
     210             : 
     211           0 :         hws->fb_top.low_part  = fb_top;
     212           0 :         hws->fb_top.quad_part <<= 24;
     213           0 :         hws->fb_offset.low_part = fb_offset;
     214           0 :         hws->fb_offset.quad_part <<= 24;
     215             : 
     216           0 :         hws->uma_top.quad_part = hws->fb_top.quad_part
     217           0 :                         - hws->fb_base.quad_part + hws->fb_offset.quad_part;
     218           0 : }
     219             : 
     220           0 : void dcn201_init_hw(struct dc *dc)
     221             : {
     222             :         int i, j;
     223           0 :         struct dce_hwseq *hws = dc->hwseq;
     224           0 :         struct resource_pool *res_pool = dc->res_pool;
     225           0 :         struct dc_state  *context = dc->current_state;
     226             : 
     227           0 :         if (res_pool->dccg->funcs->dccg_init)
     228           0 :                 res_pool->dccg->funcs->dccg_init(res_pool->dccg);
     229             : 
     230           0 :         if (dc->clk_mgr && dc->clk_mgr->funcs->init_clocks)
     231           0 :                 dc->clk_mgr->funcs->init_clocks(dc->clk_mgr);
     232             : 
     233           0 :         if (IS_FPGA_MAXIMUS_DC(dc->ctx->dce_environment)) {
     234           0 :                 REG_WRITE(RBBMIF_TIMEOUT_DIS, 0xFFFFFFFF);
     235           0 :                 REG_WRITE(RBBMIF_TIMEOUT_DIS_2, 0xFFFFFFFF);
     236             : 
     237           0 :                 hws->funcs.dccg_init(hws);
     238             : 
     239           0 :                 REG_UPDATE(DCHUBBUB_GLOBAL_TIMER_CNTL, DCHUBBUB_GLOBAL_TIMER_REFDIV, 2);
     240           0 :                 REG_UPDATE(DCHUBBUB_GLOBAL_TIMER_CNTL, DCHUBBUB_GLOBAL_TIMER_ENABLE, 1);
     241           0 :                 REG_WRITE(REFCLK_CNTL, 0);
     242             :         } else {
     243           0 :                 hws->funcs.bios_golden_init(dc);
     244             : 
     245           0 :                 if (dc->ctx->dc_bios->fw_info_valid) {
     246           0 :                         res_pool->ref_clocks.xtalin_clock_inKhz =
     247           0 :                                 dc->ctx->dc_bios->fw_info.pll_info.crystal_frequency;
     248             : 
     249           0 :                         if (!IS_FPGA_MAXIMUS_DC(dc->ctx->dce_environment)) {
     250           0 :                                 if (res_pool->dccg && res_pool->hubbub) {
     251           0 :                                         (res_pool->dccg->funcs->get_dccg_ref_freq)(res_pool->dccg,
     252           0 :                                                         dc->ctx->dc_bios->fw_info.pll_info.crystal_frequency,
     253             :                                                         &res_pool->ref_clocks.dccg_ref_clock_inKhz);
     254             : 
     255           0 :                                         (res_pool->hubbub->funcs->get_dchub_ref_freq)(res_pool->hubbub,
     256             :                                                         res_pool->ref_clocks.dccg_ref_clock_inKhz,
     257             :                                                         &res_pool->ref_clocks.dchub_ref_clock_inKhz);
     258             :                                 } else {
     259           0 :                                         res_pool->ref_clocks.dccg_ref_clock_inKhz =
     260             :                                                         res_pool->ref_clocks.xtalin_clock_inKhz;
     261           0 :                                         res_pool->ref_clocks.dchub_ref_clock_inKhz =
     262             :                                                         res_pool->ref_clocks.xtalin_clock_inKhz;
     263             :                                 }
     264             :                         }
     265             :                 } else
     266           0 :                         ASSERT_CRITICAL(false);
     267           0 :                 for (i = 0; i < dc->link_count; i++) {
     268             :                         /* Power up AND update implementation according to the
     269             :                          * required signal (which may be different from the
     270             :                          * default signal on connector).
     271             :                          */
     272           0 :                         struct dc_link *link = dc->links[i];
     273             : 
     274           0 :                         link->link_enc->funcs->hw_init(link->link_enc);
     275             :                 }
     276           0 :                 if (hws->fb_offset.quad_part == 0)
     277           0 :                         read_mmhub_vm_setup(hws);
     278             :         }
     279             : 
     280             :         /* Blank pixel data with OPP DPG */
     281           0 :         for (i = 0; i < res_pool->timing_generator_count; i++) {
     282           0 :                 struct timing_generator *tg = res_pool->timing_generators[i];
     283             : 
     284           0 :                 if (tg->funcs->is_tg_enabled(tg)) {
     285           0 :                         dcn201_init_blank(dc, tg);
     286             :                 }
     287             :         }
     288             : 
     289           0 :         for (i = 0; i < res_pool->timing_generator_count; i++) {
     290           0 :                 struct timing_generator *tg = res_pool->timing_generators[i];
     291             : 
     292           0 :                 if (tg->funcs->is_tg_enabled(tg))
     293           0 :                         tg->funcs->lock(tg);
     294             :         }
     295             : 
     296           0 :         for (i = 0; i < res_pool->pipe_count; i++) {
     297           0 :                 struct dpp *dpp = res_pool->dpps[i];
     298             : 
     299           0 :                 dpp->funcs->dpp_reset(dpp);
     300             :         }
     301             : 
     302             :         /* Reset all MPCC muxes */
     303           0 :         res_pool->mpc->funcs->mpc_init(res_pool->mpc);
     304             : 
     305             :         /* initialize OPP mpc_tree parameter */
     306           0 :         for (i = 0; i < res_pool->res_cap->num_opp; i++) {
     307           0 :                 res_pool->opps[i]->mpc_tree_params.opp_id = res_pool->opps[i]->inst;
     308           0 :                 res_pool->opps[i]->mpc_tree_params.opp_list = NULL;
     309           0 :                 for (j = 0; j < MAX_PIPES; j++)
     310           0 :                         res_pool->opps[i]->mpcc_disconnect_pending[j] = false;
     311             :         }
     312             : 
     313           0 :         for (i = 0; i < res_pool->timing_generator_count; i++) {
     314           0 :                 struct timing_generator *tg = res_pool->timing_generators[i];
     315           0 :                 struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[i];
     316           0 :                 struct hubp *hubp = res_pool->hubps[i];
     317           0 :                 struct dpp *dpp = res_pool->dpps[i];
     318             : 
     319           0 :                 pipe_ctx->stream_res.tg = tg;
     320           0 :                 pipe_ctx->pipe_idx = i;
     321             : 
     322           0 :                 pipe_ctx->plane_res.hubp = hubp;
     323           0 :                 pipe_ctx->plane_res.dpp = dpp;
     324           0 :                 pipe_ctx->plane_res.mpcc_inst = dpp->inst;
     325           0 :                 hubp->mpcc_id = dpp->inst;
     326           0 :                 hubp->opp_id = OPP_ID_INVALID;
     327           0 :                 hubp->power_gated = false;
     328           0 :                 pipe_ctx->stream_res.opp = NULL;
     329             : 
     330           0 :                 hubp->funcs->hubp_init(hubp);
     331             : 
     332           0 :                 res_pool->opps[i]->mpcc_disconnect_pending[pipe_ctx->plane_res.mpcc_inst] = true;
     333           0 :                 pipe_ctx->stream_res.opp = res_pool->opps[i];
     334             :                 /*To do: number of MPCC != number of opp*/
     335           0 :                 hws->funcs.plane_atomic_disconnect(dc, pipe_ctx);
     336             :         }
     337             : 
     338             :         /* initialize DWB pointer to MCIF_WB */
     339           0 :         for (i = 0; i < res_pool->res_cap->num_dwb; i++)
     340           0 :                 res_pool->dwbc[i]->mcif = res_pool->mcif_wb[i];
     341             : 
     342           0 :         for (i = 0; i < res_pool->timing_generator_count; i++) {
     343           0 :                 struct timing_generator *tg = res_pool->timing_generators[i];
     344             : 
     345           0 :                 if (tg->funcs->is_tg_enabled(tg))
     346           0 :                         tg->funcs->unlock(tg);
     347             :         }
     348             : 
     349           0 :         for (i = 0; i < res_pool->pipe_count; i++) {
     350           0 :                 struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[i];
     351             : 
     352           0 :                 dc->hwss.disable_plane(dc, pipe_ctx);
     353             : 
     354           0 :                 pipe_ctx->stream_res.tg = NULL;
     355           0 :                 pipe_ctx->plane_res.hubp = NULL;
     356             :         }
     357             : 
     358           0 :         for (i = 0; i < res_pool->timing_generator_count; i++) {
     359           0 :                 struct timing_generator *tg = res_pool->timing_generators[i];
     360             : 
     361           0 :                 tg->funcs->tg_init(tg);
     362             :         }
     363             : 
     364             :         /* end of FPGA. Below if real ASIC */
     365           0 :         if (IS_FPGA_MAXIMUS_DC(dc->ctx->dce_environment))
     366             :                 return;
     367             : 
     368           0 :         for (i = 0; i < res_pool->audio_count; i++) {
     369           0 :                 struct audio *audio = res_pool->audios[i];
     370             : 
     371           0 :                 audio->funcs->hw_init(audio);
     372             :         }
     373             : 
     374             :         /* power AFMT HDMI memory TODO: may move to dis/en output save power*/
     375           0 :         REG_WRITE(DIO_MEM_PWR_CTRL, 0);
     376             : 
     377           0 :         if (!dc->debug.disable_clock_gate) {
     378             :                 /* enable all DCN clock gating */
     379           0 :                 REG_WRITE(DCCG_GATE_DISABLE_CNTL, 0);
     380             : 
     381           0 :                 REG_WRITE(DCCG_GATE_DISABLE_CNTL2, 0);
     382             : 
     383           0 :                 REG_UPDATE(DCFCLK_CNTL, DCFCLK_GATE_DIS, 0);
     384             :         }
     385             : }
     386             : 
     387             : /* trigger HW to start disconnect plane from stream on the next vsync */
     388           0 : void dcn201_plane_atomic_disconnect(struct dc *dc, struct pipe_ctx *pipe_ctx)
     389             : {
     390           0 :         struct dce_hwseq *hws = dc->hwseq;
     391           0 :         struct hubp *hubp = pipe_ctx->plane_res.hubp;
     392           0 :         int dpp_id = pipe_ctx->plane_res.dpp->inst;
     393           0 :         struct mpc *mpc = dc->res_pool->mpc;
     394             :         struct mpc_tree *mpc_tree_params;
     395           0 :         struct mpcc *mpcc_to_remove = NULL;
     396           0 :         struct output_pixel_processor *opp = pipe_ctx->stream_res.opp;
     397           0 :         bool mpcc_removed = false;
     398             : 
     399           0 :         mpc_tree_params = &(opp->mpc_tree_params);
     400             : 
     401             :         /* check if this plane is being used by an MPCC in the secondary blending chain */
     402           0 :         if (mpc->funcs->get_mpcc_for_dpp_from_secondary)
     403           0 :                 mpcc_to_remove = mpc->funcs->get_mpcc_for_dpp_from_secondary(mpc_tree_params, dpp_id);
     404             : 
     405             :         /* remove MPCC from secondary if being used */
     406           0 :         if (mpcc_to_remove != NULL && mpc->funcs->remove_mpcc_from_secondary) {
     407           0 :                 mpc->funcs->remove_mpcc_from_secondary(mpc, mpc_tree_params, mpcc_to_remove);
     408           0 :                 mpcc_removed = true;
     409             :         }
     410             : 
     411             :         /* check if this MPCC is already being used for this plane (dpp) in the primary blending chain */
     412           0 :         mpcc_to_remove = mpc->funcs->get_mpcc_for_dpp(mpc_tree_params, dpp_id);
     413           0 :         if (mpcc_to_remove != NULL) {
     414           0 :                 mpc->funcs->remove_mpcc(mpc, mpc_tree_params, mpcc_to_remove);
     415           0 :                 mpcc_removed = true;
     416             :         }
     417             : 
     418             :         /*Already reset*/
     419           0 :         if (mpcc_removed == false)
     420             :                 return;
     421             : 
     422           0 :         if (opp != NULL)
     423           0 :                 opp->mpcc_disconnect_pending[pipe_ctx->plane_res.mpcc_inst] = true;
     424             : 
     425           0 :         dc->optimized_required = true;
     426             : 
     427           0 :         if (hubp->funcs->hubp_disconnect)
     428           0 :                 hubp->funcs->hubp_disconnect(hubp);
     429             : 
     430           0 :         if (dc->debug.sanity_checks)
     431           0 :                 hws->funcs.verify_allow_pstate_change_high(dc);
     432             : }
     433             : 
     434           0 : void dcn201_update_mpcc(struct dc *dc, struct pipe_ctx *pipe_ctx)
     435             : {
     436           0 :         struct hubp *hubp = pipe_ctx->plane_res.hubp;
     437             :         struct mpcc_blnd_cfg blnd_cfg;
     438           0 :         bool per_pixel_alpha = pipe_ctx->plane_state->per_pixel_alpha && pipe_ctx->bottom_pipe;
     439             :         int mpcc_id, dpp_id;
     440             :         struct mpcc *new_mpcc;
     441           0 :         struct mpcc *remove_mpcc = NULL;
     442           0 :         struct mpc *mpc = dc->res_pool->mpc;
     443           0 :         struct mpc_tree *mpc_tree_params = &(pipe_ctx->stream_res.opp->mpc_tree_params);
     444             : 
     445           0 :         if (dc->debug.visual_confirm == VISUAL_CONFIRM_HDR) {
     446           0 :                 get_hdr_visual_confirm_color(
     447             :                                 pipe_ctx, &blnd_cfg.black_color);
     448           0 :         } else if (dc->debug.visual_confirm == VISUAL_CONFIRM_SURFACE) {
     449           0 :                 get_surface_visual_confirm_color(
     450             :                                 pipe_ctx, &blnd_cfg.black_color);
     451             :         } else {
     452           0 :                 color_space_to_black_color(
     453           0 :                                 dc, pipe_ctx->stream->output_color_space,
     454             :                                 &blnd_cfg.black_color);
     455             :         }
     456             : 
     457           0 :         if (per_pixel_alpha)
     458           0 :                 blnd_cfg.alpha_mode = MPCC_ALPHA_BLEND_MODE_PER_PIXEL_ALPHA;
     459             :         else
     460           0 :                 blnd_cfg.alpha_mode = MPCC_ALPHA_BLEND_MODE_GLOBAL_ALPHA;
     461             : 
     462           0 :         blnd_cfg.overlap_only = false;
     463             : 
     464           0 :         if (pipe_ctx->plane_state->global_alpha_value)
     465           0 :                 blnd_cfg.global_alpha = pipe_ctx->plane_state->global_alpha_value;
     466             :         else
     467           0 :                 blnd_cfg.global_alpha = 0xff;
     468             : 
     469           0 :         blnd_cfg.global_gain = 0xff;
     470           0 :         blnd_cfg.background_color_bpc = 4;
     471           0 :         blnd_cfg.bottom_gain_mode = 0;
     472           0 :         blnd_cfg.top_gain = 0x1f000;
     473           0 :         blnd_cfg.bottom_inside_gain = 0x1f000;
     474           0 :         blnd_cfg.bottom_outside_gain = 0x1f000;
     475             :         /*the input to MPCC is RGB*/
     476           0 :         blnd_cfg.black_color.color_b_cb = 0;
     477           0 :         blnd_cfg.black_color.color_g_y = 0;
     478           0 :         blnd_cfg.black_color.color_r_cr = 0;
     479             : 
     480             :         /* DCN1.0 has output CM before MPC which seems to screw with
     481             :          * pre-multiplied alpha. This is a w/a hopefully unnecessary for DCN2.
     482             :          */
     483           0 :         blnd_cfg.pre_multiplied_alpha = per_pixel_alpha;
     484             : 
     485             :         /*
     486             :          * TODO: remove hack
     487             :          * Note: currently there is a bug in init_hw such that
     488             :          * on resume from hibernate, BIOS sets up MPCC0, and
     489             :          * we do mpcc_remove but the mpcc cannot go to idle
     490             :          * after remove. This cause us to pick mpcc1 here,
     491             :          * which causes a pstate hang for yet unknown reason.
     492             :          */
     493           0 :         dpp_id = hubp->inst;
     494           0 :         mpcc_id = dpp_id;
     495             : 
     496             :         /* If there is no full update, don't need to touch MPC tree*/
     497           0 :         if (!pipe_ctx->plane_state->update_flags.bits.full_update) {
     498           0 :                 dc->hwss.update_visual_confirm_color(dc, pipe_ctx, &blnd_cfg.black_color, mpcc_id);
     499           0 :                 mpc->funcs->update_blending(mpc, &blnd_cfg, mpcc_id);
     500           0 :                 return;
     501             :         }
     502             : 
     503             :         /* check if this plane is being used by an MPCC in the secondary blending chain */
     504           0 :         if (mpc->funcs->get_mpcc_for_dpp_from_secondary)
     505           0 :                 remove_mpcc = mpc->funcs->get_mpcc_for_dpp_from_secondary(mpc_tree_params, dpp_id);
     506             : 
     507             :         /* remove MPCC from secondary if being used */
     508           0 :         if (remove_mpcc != NULL && mpc->funcs->remove_mpcc_from_secondary)
     509           0 :                 mpc->funcs->remove_mpcc_from_secondary(mpc, mpc_tree_params, remove_mpcc);
     510             : 
     511             :         /* check if this MPCC is already being used for this plane (dpp) in the primary blending chain */
     512           0 :         remove_mpcc = mpc->funcs->get_mpcc_for_dpp(mpc_tree_params, dpp_id);
     513             :         /* remove MPCC if being used */
     514             : 
     515           0 :         if (remove_mpcc != NULL)
     516           0 :                 mpc->funcs->remove_mpcc(mpc, mpc_tree_params, remove_mpcc);
     517             :         else
     518           0 :                 if (dc->debug.sanity_checks)
     519           0 :                         mpc->funcs->assert_mpcc_idle_before_connect(
     520           0 :                                         dc->res_pool->mpc, mpcc_id);
     521             : 
     522             :         /* Call MPC to insert new plane */
     523           0 :         dc->hwss.update_visual_confirm_color(dc, pipe_ctx, &blnd_cfg.black_color, mpcc_id);
     524           0 :         new_mpcc = mpc->funcs->insert_plane(dc->res_pool->mpc,
     525             :                         mpc_tree_params,
     526             :                         &blnd_cfg,
     527             :                         NULL,
     528             :                         NULL,
     529             :                         dpp_id,
     530             :                         mpcc_id);
     531             : 
     532           0 :         ASSERT(new_mpcc != NULL);
     533           0 :         hubp->opp_id = pipe_ctx->stream_res.opp->inst;
     534           0 :         hubp->mpcc_id = mpcc_id;
     535             : }
     536             : 
     537           0 : void dcn201_pipe_control_lock(
     538             :         struct dc *dc,
     539             :         struct pipe_ctx *pipe,
     540             :         bool lock)
     541             : {
     542           0 :         struct dce_hwseq *hws = dc->hwseq;
     543           0 :         struct hubp *hubp = NULL;
     544           0 :         hubp = dc->res_pool->hubps[pipe->pipe_idx];
     545             :         /* use TG master update lock to lock everything on the TG
     546             :          * therefore only top pipe need to lock
     547             :          */
     548           0 :         if (pipe->top_pipe)
     549             :                 return;
     550             : 
     551           0 :         if (dc->debug.sanity_checks)
     552           0 :                 hws->funcs.verify_allow_pstate_change_high(dc);
     553             : 
     554           0 :         if (pipe->plane_state != NULL && pipe->plane_state->triplebuffer_flips) {
     555           0 :                 if (lock)
     556           0 :                         pipe->stream_res.tg->funcs->triplebuffer_lock(pipe->stream_res.tg);
     557             :                 else
     558           0 :                         pipe->stream_res.tg->funcs->triplebuffer_unlock(pipe->stream_res.tg);
     559             :         } else {
     560           0 :                 if (lock)
     561           0 :                         pipe->stream_res.tg->funcs->lock(pipe->stream_res.tg);
     562             :                 else
     563           0 :                         pipe->stream_res.tg->funcs->unlock(pipe->stream_res.tg);
     564             :         }
     565             : 
     566           0 :         if (dc->debug.sanity_checks)
     567           0 :                 hws->funcs.verify_allow_pstate_change_high(dc);
     568             : }
     569             : 
     570           0 : void dcn201_set_cursor_attribute(struct pipe_ctx *pipe_ctx)
     571             : {
     572           0 :         struct dc_cursor_attributes *attributes = &pipe_ctx->stream->cursor_attributes;
     573             : 
     574           0 :         gpu_addr_to_uma(pipe_ctx->stream->ctx->dc->hwseq, &attributes->address);
     575             : 
     576           0 :         pipe_ctx->plane_res.hubp->funcs->set_cursor_attributes(
     577             :                         pipe_ctx->plane_res.hubp, attributes);
     578           0 :         pipe_ctx->plane_res.dpp->funcs->set_cursor_attributes(
     579             :                 pipe_ctx->plane_res.dpp, attributes);
     580           0 : }
     581             : 
     582           0 : void dcn201_set_dmdata_attributes(struct pipe_ctx *pipe_ctx)
     583             : {
     584           0 :         struct dc_dmdata_attributes attr = { 0 };
     585           0 :         struct hubp *hubp = pipe_ctx->plane_res.hubp;
     586             : 
     587           0 :         gpu_addr_to_uma(pipe_ctx->stream->ctx->dc->hwseq,
     588           0 :                         &pipe_ctx->stream->dmdata_address);
     589             : 
     590           0 :         attr.dmdata_mode = DMDATA_HW_MODE;
     591           0 :         attr.dmdata_size =
     592           0 :                 dc_is_hdmi_signal(pipe_ctx->stream->signal) ? 32 : 36;
     593           0 :         attr.address.quad_part =
     594           0 :                         pipe_ctx->stream->dmdata_address.quad_part;
     595             :         attr.dmdata_dl_delta = 0;
     596             :         attr.dmdata_qos_mode = 0;
     597             :         attr.dmdata_qos_level = 0;
     598           0 :         attr.dmdata_repeat = 1; /* always repeat */
     599           0 :         attr.dmdata_updated = 1;
     600             :         attr.dmdata_sw_data = NULL;
     601             : 
     602           0 :         hubp->funcs->dmdata_set_attributes(hubp, &attr);
     603           0 : }
     604             : 
     605           0 : void dcn201_unblank_stream(struct pipe_ctx *pipe_ctx,
     606             :                 struct dc_link_settings *link_settings)
     607             : {
     608           0 :         struct encoder_unblank_param params = { { 0 } };
     609           0 :         struct dc_stream_state *stream = pipe_ctx->stream;
     610           0 :         struct dc_link *link = stream->link;
     611           0 :         struct dce_hwseq *hws = link->dc->hwseq;
     612             : 
     613             :         /* only 3 items below are used by unblank */
     614           0 :         params.timing = pipe_ctx->stream->timing;
     615             : 
     616           0 :         params.link_settings.link_rate = link_settings->link_rate;
     617             : 
     618           0 :         if (dc_is_dp_signal(pipe_ctx->stream->signal)) {
     619             :                 /*check whether it is half the rate*/
     620           0 :                 if (optc201_is_two_pixels_per_containter(&stream->timing))
     621           0 :                         params.timing.pix_clk_100hz /= 2;
     622             : 
     623           0 :                 pipe_ctx->stream_res.stream_enc->funcs->dp_unblank(link, pipe_ctx->stream_res.stream_enc, &params);
     624             :         }
     625             : 
     626           0 :         if (link->local_sink && link->local_sink->sink_signal == SIGNAL_TYPE_EDP) {
     627           0 :                 hws->funcs.edp_backlight_control(link, true);
     628             :         }
     629           0 : }

Generated by: LCOV version 1.14