LCOV - code coverage report
Current view: top level - drivers/gpu/drm/amd/display/dc/dcn31 - dcn31_hwseq.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 0 284 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             : 
      27             : #include "dm_services.h"
      28             : #include "dm_helpers.h"
      29             : #include "core_types.h"
      30             : #include "resource.h"
      31             : #include "dccg.h"
      32             : #include "dce/dce_hwseq.h"
      33             : #include "clk_mgr.h"
      34             : #include "reg_helper.h"
      35             : #include "abm.h"
      36             : #include "hubp.h"
      37             : #include "dchubbub.h"
      38             : #include "timing_generator.h"
      39             : #include "opp.h"
      40             : #include "ipp.h"
      41             : #include "mpc.h"
      42             : #include "mcif_wb.h"
      43             : #include "dc_dmub_srv.h"
      44             : #include "dcn31_hwseq.h"
      45             : #include "link_hwss.h"
      46             : #include "dpcd_defs.h"
      47             : #include "dce/dmub_outbox.h"
      48             : #include "dc_link_dp.h"
      49             : #include "inc/link_dpcd.h"
      50             : #include "dcn10/dcn10_hw_sequencer.h"
      51             : #include "inc/link_enc_cfg.h"
      52             : #include "dcn30/dcn30_vpg.h"
      53             : #include "dce/dce_i2c_hw.h"
      54             : 
      55             : #define DC_LOGGER_INIT(logger)
      56             : 
      57             : #define CTX \
      58             :         hws->ctx
      59             : #define REG(reg)\
      60             :         hws->regs->reg
      61             : #define DC_LOGGER \
      62             :                 dc->ctx->logger
      63             : 
      64             : 
      65             : #undef FN
      66             : #define FN(reg_name, field_name) \
      67             :         hws->shifts->field_name, hws->masks->field_name
      68             : 
      69           0 : static void enable_memory_low_power(struct dc *dc)
      70             : {
      71           0 :         struct dce_hwseq *hws = dc->hwseq;
      72             :         int i;
      73             : 
      74           0 :         if (dc->debug.enable_mem_low_power.bits.dmcu) {
      75             :                 // Force ERAM to shutdown if DMCU is not enabled
      76           0 :                 if (dc->debug.disable_dmcu || dc->config.disable_dmcu) {
      77           0 :                         REG_UPDATE(DMU_MEM_PWR_CNTL, DMCU_ERAM_MEM_PWR_FORCE, 3);
      78             :                 }
      79             :         }
      80             : 
      81             :         // Set default OPTC memory power states
      82           0 :         if (dc->debug.enable_mem_low_power.bits.optc) {
      83             :                 // Shutdown when unassigned and light sleep in VBLANK
      84           0 :                 REG_SET_2(ODM_MEM_PWR_CTRL3, 0, ODM_MEM_UNASSIGNED_PWR_MODE, 3, ODM_MEM_VBLANK_PWR_MODE, 1);
      85             :         }
      86             : 
      87           0 :         if (dc->debug.enable_mem_low_power.bits.vga) {
      88             :                 // Power down VGA memory
      89           0 :                 REG_UPDATE(MMHUBBUB_MEM_PWR_CNTL, VGA_MEM_PWR_FORCE, 1);
      90             :         }
      91             : 
      92           0 :         if (dc->debug.enable_mem_low_power.bits.mpc)
      93           0 :                 dc->res_pool->mpc->funcs->set_mpc_mem_lp_mode(dc->res_pool->mpc);
      94             : 
      95             : 
      96           0 :         if (dc->debug.enable_mem_low_power.bits.vpg && dc->res_pool->stream_enc[0]->vpg->funcs->vpg_powerdown) {
      97             :                 // Power down VPGs
      98           0 :                 for (i = 0; i < dc->res_pool->stream_enc_count; i++)
      99           0 :                         dc->res_pool->stream_enc[i]->vpg->funcs->vpg_powerdown(dc->res_pool->stream_enc[i]->vpg);
     100             : #if defined(CONFIG_DRM_AMD_DC_DCN)
     101           0 :                 for (i = 0; i < dc->res_pool->hpo_dp_stream_enc_count; i++)
     102           0 :                         dc->res_pool->hpo_dp_stream_enc[i]->vpg->funcs->vpg_powerdown(dc->res_pool->hpo_dp_stream_enc[i]->vpg);
     103             : #endif
     104             :         }
     105             : 
     106           0 : }
     107             : 
     108           0 : void dcn31_init_hw(struct dc *dc)
     109             : {
     110           0 :         struct abm **abms = dc->res_pool->multiple_abms;
     111           0 :         struct dce_hwseq *hws = dc->hwseq;
     112           0 :         struct dc_bios *dcb = dc->ctx->dc_bios;
     113           0 :         struct resource_pool *res_pool = dc->res_pool;
     114           0 :         uint32_t backlight = MAX_BACKLIGHT_LEVEL;
     115             :         int i;
     116             : 
     117           0 :         if (dc->clk_mgr && dc->clk_mgr->funcs->init_clocks)
     118           0 :                 dc->clk_mgr->funcs->init_clocks(dc->clk_mgr);
     119             : 
     120           0 :         if (IS_FPGA_MAXIMUS_DC(dc->ctx->dce_environment)) {
     121             : 
     122           0 :                 REG_WRITE(REFCLK_CNTL, 0);
     123           0 :                 REG_UPDATE(DCHUBBUB_GLOBAL_TIMER_CNTL, DCHUBBUB_GLOBAL_TIMER_ENABLE, 1);
     124           0 :                 REG_WRITE(DIO_MEM_PWR_CTRL, 0);
     125             : 
     126           0 :                 if (!dc->debug.disable_clock_gate) {
     127             :                         /* enable all DCN clock gating */
     128           0 :                         REG_WRITE(DCCG_GATE_DISABLE_CNTL, 0);
     129             : 
     130           0 :                         REG_WRITE(DCCG_GATE_DISABLE_CNTL2, 0);
     131             : 
     132           0 :                         REG_UPDATE(DCFCLK_CNTL, DCFCLK_GATE_DIS, 0);
     133             :                 }
     134             : 
     135             :                 //Enable ability to power gate / don't force power on permanently
     136           0 :                 if (hws->funcs.enable_power_gating_plane)
     137           0 :                         hws->funcs.enable_power_gating_plane(hws, true);
     138             : 
     139             :                 return;
     140             :         }
     141             : 
     142           0 :         if (!dcb->funcs->is_accelerated_mode(dcb)) {
     143           0 :                 hws->funcs.bios_golden_init(dc);
     144           0 :                 hws->funcs.disable_vga(dc->hwseq);
     145             :         }
     146             :         // Initialize the dccg
     147           0 :         if (res_pool->dccg->funcs->dccg_init)
     148           0 :                 res_pool->dccg->funcs->dccg_init(res_pool->dccg);
     149             : 
     150           0 :         enable_memory_low_power(dc);
     151             : 
     152           0 :         if (dc->ctx->dc_bios->fw_info_valid) {
     153           0 :                 res_pool->ref_clocks.xtalin_clock_inKhz =
     154           0 :                                 dc->ctx->dc_bios->fw_info.pll_info.crystal_frequency;
     155             : 
     156           0 :                 if (!IS_FPGA_MAXIMUS_DC(dc->ctx->dce_environment)) {
     157           0 :                         if (res_pool->dccg && res_pool->hubbub) {
     158             : 
     159           0 :                                 (res_pool->dccg->funcs->get_dccg_ref_freq)(res_pool->dccg,
     160           0 :                                                 dc->ctx->dc_bios->fw_info.pll_info.crystal_frequency,
     161             :                                                 &res_pool->ref_clocks.dccg_ref_clock_inKhz);
     162             : 
     163           0 :                                 (res_pool->hubbub->funcs->get_dchub_ref_freq)(res_pool->hubbub,
     164             :                                                 res_pool->ref_clocks.dccg_ref_clock_inKhz,
     165             :                                                 &res_pool->ref_clocks.dchub_ref_clock_inKhz);
     166             :                         } else {
     167             :                                 // Not all ASICs have DCCG sw component
     168           0 :                                 res_pool->ref_clocks.dccg_ref_clock_inKhz =
     169             :                                                 res_pool->ref_clocks.xtalin_clock_inKhz;
     170           0 :                                 res_pool->ref_clocks.dchub_ref_clock_inKhz =
     171             :                                                 res_pool->ref_clocks.xtalin_clock_inKhz;
     172             :                         }
     173             :                 }
     174             :         } else
     175           0 :                 ASSERT_CRITICAL(false);
     176             : 
     177           0 :         for (i = 0; i < dc->link_count; i++) {
     178             :                 /* Power up AND update implementation according to the
     179             :                  * required signal (which may be different from the
     180             :                  * default signal on connector).
     181             :                  */
     182           0 :                 struct dc_link *link = dc->links[i];
     183             : 
     184           0 :                 if (link->ep_type != DISPLAY_ENDPOINT_PHY)
     185           0 :                         continue;
     186             : 
     187           0 :                 link->link_enc->funcs->hw_init(link->link_enc);
     188             : 
     189             :                 /* Check for enabled DIG to identify enabled display */
     190           0 :                 if (link->link_enc->funcs->is_dig_enabled &&
     191           0 :                         link->link_enc->funcs->is_dig_enabled(link->link_enc)) {
     192           0 :                         link->link_status.link_active = true;
     193           0 :                         if (link->link_enc->funcs->fec_is_active &&
     194           0 :                                         link->link_enc->funcs->fec_is_active(link->link_enc))
     195           0 :                                 link->fec_state = dc_link_fec_enabled;
     196             :                 }
     197             :         }
     198             : 
     199             :         /* Enables outbox notifications for usb4 dpia */
     200           0 :         if (dc->res_pool->usb4_dpia_count)
     201           0 :                 dmub_enable_outbox_notification(dc->ctx->dmub_srv);
     202             : 
     203             :         /* we want to turn off all dp displays before doing detection */
     204           0 :         dc_link_blank_all_dp_displays(dc);
     205             : 
     206           0 :         if (hws->funcs.enable_power_gating_plane)
     207           0 :                 hws->funcs.enable_power_gating_plane(dc->hwseq, true);
     208             : 
     209             :         /* If taking control over from VBIOS, we may want to optimize our first
     210             :          * mode set, so we need to skip powering down pipes until we know which
     211             :          * pipes we want to use.
     212             :          * Otherwise, if taking control is not possible, we need to power
     213             :          * everything down.
     214             :          */
     215           0 :         if (dcb->funcs->is_accelerated_mode(dcb) || !dc->config.seamless_boot_edp_requested) {
     216             : 
     217             :                 // we want to turn off edp displays if odm is enabled and no seamless boot
     218           0 :                 if (!dc->caps.seamless_odm) {
     219           0 :                         for (i = 0; i < dc->res_pool->timing_generator_count; i++) {
     220           0 :                                 struct timing_generator *tg = dc->res_pool->timing_generators[i];
     221             :                                 uint32_t num_opps, opp_id_src0, opp_id_src1;
     222             : 
     223           0 :                                 num_opps = 1;
     224           0 :                                 if (tg) {
     225           0 :                                         if (tg->funcs->is_tg_enabled(tg) && tg->funcs->get_optc_source) {
     226           0 :                                                 tg->funcs->get_optc_source(tg, &num_opps,
     227             :                                                                 &opp_id_src0, &opp_id_src1);
     228             :                                         }
     229             :                                 }
     230             : 
     231           0 :                                 if (num_opps > 1) {
     232           0 :                                         dc_link_blank_all_edp_displays(dc);
     233           0 :                                         break;
     234             :                                 }
     235             :                         }
     236             :                 }
     237             : 
     238           0 :                 hws->funcs.init_pipes(dc, dc->current_state);
     239           0 :                 if (dc->res_pool->hubbub->funcs->allow_self_refresh_control)
     240           0 :                         dc->res_pool->hubbub->funcs->allow_self_refresh_control(dc->res_pool->hubbub,
     241           0 :                                         !dc->res_pool->hubbub->ctx->dc->debug.disable_stutter);
     242             :         }
     243             : 
     244           0 :         for (i = 0; i < res_pool->audio_count; i++) {
     245           0 :                 struct audio *audio = res_pool->audios[i];
     246             : 
     247           0 :                 audio->funcs->hw_init(audio);
     248             :         }
     249             : 
     250           0 :         for (i = 0; i < dc->link_count; i++) {
     251           0 :                 struct dc_link *link = dc->links[i];
     252             : 
     253           0 :                 if (link->panel_cntl)
     254           0 :                         backlight = link->panel_cntl->funcs->hw_init(link->panel_cntl);
     255             :         }
     256             : 
     257           0 :         for (i = 0; i < dc->res_pool->pipe_count; i++) {
     258           0 :                 if (abms[i] != NULL)
     259           0 :                         abms[i]->funcs->abm_init(abms[i], backlight);
     260             :         }
     261             : 
     262             :         /* power AFMT HDMI memory TODO: may move to dis/en output save power*/
     263           0 :         REG_WRITE(DIO_MEM_PWR_CTRL, 0);
     264             : 
     265             :         // Set i2c to light sleep until engine is setup
     266           0 :         if (dc->debug.enable_mem_low_power.bits.i2c)
     267           0 :                 REG_UPDATE(DIO_MEM_PWR_CTRL, I2C_LIGHT_SLEEP_FORCE, 1);
     268             : 
     269           0 :         if (hws->funcs.setup_hpo_hw_control)
     270           0 :                 hws->funcs.setup_hpo_hw_control(hws, false);
     271             : 
     272           0 :         if (!dc->debug.disable_clock_gate) {
     273             :                 /* enable all DCN clock gating */
     274           0 :                 REG_WRITE(DCCG_GATE_DISABLE_CNTL, 0);
     275             : 
     276           0 :                 REG_WRITE(DCCG_GATE_DISABLE_CNTL2, 0);
     277             : 
     278           0 :                 REG_UPDATE(DCFCLK_CNTL, DCFCLK_GATE_DIS, 0);
     279             :         }
     280             : 
     281           0 :         if (!dcb->funcs->is_accelerated_mode(dcb) && dc->res_pool->hubbub->funcs->init_watermarks)
     282           0 :                 dc->res_pool->hubbub->funcs->init_watermarks(dc->res_pool->hubbub);
     283             : 
     284           0 :         if (dc->clk_mgr->funcs->notify_wm_ranges)
     285           0 :                 dc->clk_mgr->funcs->notify_wm_ranges(dc->clk_mgr);
     286             : 
     287           0 :         if (dc->clk_mgr->funcs->set_hard_max_memclk)
     288           0 :                 dc->clk_mgr->funcs->set_hard_max_memclk(dc->clk_mgr);
     289             : 
     290           0 :         if (dc->res_pool->hubbub->funcs->force_pstate_change_control)
     291           0 :                 dc->res_pool->hubbub->funcs->force_pstate_change_control(
     292             :                                 dc->res_pool->hubbub, false, false);
     293             : #if defined(CONFIG_DRM_AMD_DC_DCN)
     294           0 :         if (dc->res_pool->hubbub->funcs->init_crb)
     295           0 :                 dc->res_pool->hubbub->funcs->init_crb(dc->res_pool->hubbub);
     296             : #endif
     297             : }
     298             : 
     299           0 : void dcn31_dsc_pg_control(
     300             :                 struct dce_hwseq *hws,
     301             :                 unsigned int dsc_inst,
     302             :                 bool power_on)
     303             : {
     304           0 :         uint32_t power_gate = power_on ? 0 : 1;
     305           0 :         uint32_t pwr_status = power_on ? 0 : 2;
     306           0 :         uint32_t org_ip_request_cntl = 0;
     307             : 
     308           0 :         if (hws->ctx->dc->debug.disable_dsc_power_gate)
     309           0 :                 return;
     310             : 
     311           0 :         if (hws->ctx->dc->debug.root_clock_optimization.bits.dsc &&
     312           0 :                 hws->ctx->dc->res_pool->dccg->funcs->enable_dsc &&
     313             :                 power_on)
     314           0 :                 hws->ctx->dc->res_pool->dccg->funcs->enable_dsc(
     315             :                         hws->ctx->dc->res_pool->dccg, dsc_inst);
     316             : 
     317           0 :         REG_GET(DC_IP_REQUEST_CNTL, IP_REQUEST_EN, &org_ip_request_cntl);
     318           0 :         if (org_ip_request_cntl == 0)
     319           0 :                 REG_SET(DC_IP_REQUEST_CNTL, 0, IP_REQUEST_EN, 1);
     320             : 
     321           0 :         switch (dsc_inst) {
     322             :         case 0: /* DSC0 */
     323           0 :                 REG_UPDATE(DOMAIN16_PG_CONFIG,
     324             :                                 DOMAIN_POWER_GATE, power_gate);
     325             : 
     326           0 :                 REG_WAIT(DOMAIN16_PG_STATUS,
     327             :                                 DOMAIN_PGFSM_PWR_STATUS, pwr_status,
     328             :                                 1, 1000);
     329           0 :                 break;
     330             :         case 1: /* DSC1 */
     331           0 :                 REG_UPDATE(DOMAIN17_PG_CONFIG,
     332             :                                 DOMAIN_POWER_GATE, power_gate);
     333             : 
     334           0 :                 REG_WAIT(DOMAIN17_PG_STATUS,
     335             :                                 DOMAIN_PGFSM_PWR_STATUS, pwr_status,
     336             :                                 1, 1000);
     337           0 :                 break;
     338             :         case 2: /* DSC2 */
     339           0 :                 REG_UPDATE(DOMAIN18_PG_CONFIG,
     340             :                                 DOMAIN_POWER_GATE, power_gate);
     341             : 
     342           0 :                 REG_WAIT(DOMAIN18_PG_STATUS,
     343             :                                 DOMAIN_PGFSM_PWR_STATUS, pwr_status,
     344             :                                 1, 1000);
     345           0 :                 break;
     346             :         default:
     347           0 :                 BREAK_TO_DEBUGGER();
     348           0 :                 break;
     349             :         }
     350             : 
     351           0 :         if (org_ip_request_cntl == 0)
     352           0 :                 REG_SET(DC_IP_REQUEST_CNTL, 0, IP_REQUEST_EN, 0);
     353             : 
     354           0 :         if (hws->ctx->dc->debug.root_clock_optimization.bits.dsc) {
     355           0 :                 if (hws->ctx->dc->res_pool->dccg->funcs->disable_dsc && !power_on)
     356           0 :                         hws->ctx->dc->res_pool->dccg->funcs->disable_dsc(
     357             :                                 hws->ctx->dc->res_pool->dccg, dsc_inst);
     358             :         }
     359             : 
     360             : }
     361             : 
     362             : 
     363           0 : void dcn31_enable_power_gating_plane(
     364             :         struct dce_hwseq *hws,
     365             :         bool enable)
     366             : {
     367           0 :         bool force_on = true; /* disable power gating */
     368           0 :         uint32_t org_ip_request_cntl = 0;
     369             : 
     370           0 :         if (enable && !hws->ctx->dc->debug.disable_hubp_power_gate)
     371           0 :                 force_on = false;
     372             : 
     373           0 :         REG_GET(DC_IP_REQUEST_CNTL, IP_REQUEST_EN, &org_ip_request_cntl);
     374           0 :         if (org_ip_request_cntl == 0)
     375           0 :                 REG_SET(DC_IP_REQUEST_CNTL, 0, IP_REQUEST_EN, 1);
     376             :         /* DCHUBP0/1/2/3/4/5 */
     377           0 :         REG_UPDATE(DOMAIN0_PG_CONFIG, DOMAIN_POWER_FORCEON, force_on);
     378           0 :         REG_UPDATE(DOMAIN2_PG_CONFIG, DOMAIN_POWER_FORCEON, force_on);
     379             :         /* DPP0/1/2/3/4/5 */
     380           0 :         REG_UPDATE(DOMAIN1_PG_CONFIG, DOMAIN_POWER_FORCEON, force_on);
     381           0 :         REG_UPDATE(DOMAIN3_PG_CONFIG, DOMAIN_POWER_FORCEON, force_on);
     382             : 
     383           0 :         force_on = true; /* disable power gating */
     384           0 :         if (enable && !hws->ctx->dc->debug.disable_dsc_power_gate)
     385           0 :                 force_on = false;
     386             : 
     387             :         /* DCS0/1/2/3/4/5 */
     388           0 :         REG_UPDATE(DOMAIN16_PG_CONFIG, DOMAIN_POWER_FORCEON, force_on);
     389           0 :         REG_UPDATE(DOMAIN17_PG_CONFIG, DOMAIN_POWER_FORCEON, force_on);
     390           0 :         REG_UPDATE(DOMAIN18_PG_CONFIG, DOMAIN_POWER_FORCEON, force_on);
     391             : 
     392           0 :         if (org_ip_request_cntl == 0)
     393           0 :                 REG_SET(DC_IP_REQUEST_CNTL, 0, IP_REQUEST_EN, 0);
     394           0 : }
     395             : 
     396           0 : void dcn31_update_info_frame(struct pipe_ctx *pipe_ctx)
     397             : {
     398             :         bool is_hdmi_tmds;
     399             :         bool is_dp;
     400             : 
     401           0 :         ASSERT(pipe_ctx->stream);
     402             : 
     403           0 :         if (pipe_ctx->stream_res.stream_enc == NULL)
     404             :                 return;  /* this is not root pipe */
     405             : 
     406           0 :         is_hdmi_tmds = dc_is_hdmi_tmds_signal(pipe_ctx->stream->signal);
     407           0 :         is_dp = dc_is_dp_signal(pipe_ctx->stream->signal);
     408             : 
     409           0 :         if (!is_hdmi_tmds && !is_dp)
     410             :                 return;
     411             : 
     412           0 :         if (is_hdmi_tmds)
     413           0 :                 pipe_ctx->stream_res.stream_enc->funcs->update_hdmi_info_packets(
     414             :                         pipe_ctx->stream_res.stream_enc,
     415           0 :                         &pipe_ctx->stream_res.encoder_info_frame);
     416             :         else {
     417           0 :                 pipe_ctx->stream_res.stream_enc->funcs->update_dp_info_packets(
     418             :                         pipe_ctx->stream_res.stream_enc,
     419           0 :                         &pipe_ctx->stream_res.encoder_info_frame);
     420             :         }
     421             : }
     422           0 : void dcn31_z10_save_init(struct dc *dc)
     423             : {
     424             :         union dmub_rb_cmd cmd;
     425             : 
     426           0 :         memset(&cmd, 0, sizeof(cmd));
     427           0 :         cmd.dcn_restore.header.type = DMUB_CMD__IDLE_OPT;
     428           0 :         cmd.dcn_restore.header.sub_type = DMUB_CMD__IDLE_OPT_DCN_SAVE_INIT;
     429             : 
     430           0 :         dc_dmub_srv_cmd_queue(dc->ctx->dmub_srv, &cmd);
     431           0 :         dc_dmub_srv_cmd_execute(dc->ctx->dmub_srv);
     432           0 :         dc_dmub_srv_wait_idle(dc->ctx->dmub_srv);
     433           0 : }
     434             : 
     435           0 : void dcn31_z10_restore(const struct dc *dc)
     436             : {
     437             :         union dmub_rb_cmd cmd;
     438             : 
     439             :         /*
     440             :          * DMUB notifies whether restore is required.
     441             :          * Optimization to avoid sending commands when not required.
     442             :          */
     443           0 :         if (!dc_dmub_srv_is_restore_required(dc->ctx->dmub_srv))
     444           0 :                 return;
     445             : 
     446           0 :         memset(&cmd, 0, sizeof(cmd));
     447           0 :         cmd.dcn_restore.header.type = DMUB_CMD__IDLE_OPT;
     448           0 :         cmd.dcn_restore.header.sub_type = DMUB_CMD__IDLE_OPT_DCN_RESTORE;
     449             : 
     450           0 :         dc_dmub_srv_cmd_queue(dc->ctx->dmub_srv, &cmd);
     451           0 :         dc_dmub_srv_cmd_execute(dc->ctx->dmub_srv);
     452           0 :         dc_dmub_srv_wait_idle(dc->ctx->dmub_srv);
     453             : }
     454             : 
     455           0 : void dcn31_hubp_pg_control(struct dce_hwseq *hws, unsigned int hubp_inst, bool power_on)
     456             : {
     457           0 :         uint32_t power_gate = power_on ? 0 : 1;
     458           0 :         uint32_t pwr_status = power_on ? 0 : 2;
     459             :         uint32_t org_ip_request_cntl;
     460           0 :         if (hws->ctx->dc->debug.disable_hubp_power_gate)
     461           0 :                 return;
     462             : 
     463           0 :         if (REG(DOMAIN0_PG_CONFIG) == 0)
     464             :                 return;
     465           0 :         REG_GET(DC_IP_REQUEST_CNTL, IP_REQUEST_EN, &org_ip_request_cntl);
     466           0 :         if (org_ip_request_cntl == 0)
     467           0 :                 REG_SET(DC_IP_REQUEST_CNTL, 0, IP_REQUEST_EN, 1);
     468             : 
     469           0 :         switch (hubp_inst) {
     470             :         case 0:
     471           0 :                 REG_SET(DOMAIN0_PG_CONFIG, 0, DOMAIN_POWER_GATE, power_gate);
     472           0 :                 REG_WAIT(DOMAIN0_PG_STATUS, DOMAIN_PGFSM_PWR_STATUS, pwr_status, 1, 1000);
     473           0 :                 break;
     474             :         case 1:
     475           0 :                 REG_SET(DOMAIN1_PG_CONFIG, 0, DOMAIN_POWER_GATE, power_gate);
     476           0 :                 REG_WAIT(DOMAIN1_PG_STATUS, DOMAIN_PGFSM_PWR_STATUS, pwr_status, 1, 1000);
     477           0 :                 break;
     478             :         case 2:
     479           0 :                 REG_SET(DOMAIN2_PG_CONFIG, 0, DOMAIN_POWER_GATE, power_gate);
     480           0 :                 REG_WAIT(DOMAIN2_PG_STATUS, DOMAIN_PGFSM_PWR_STATUS, pwr_status, 1, 1000);
     481           0 :                 break;
     482             :         case 3:
     483           0 :                 REG_SET(DOMAIN3_PG_CONFIG, 0, DOMAIN_POWER_GATE, power_gate);
     484           0 :                 REG_WAIT(DOMAIN3_PG_STATUS, DOMAIN_PGFSM_PWR_STATUS, pwr_status, 1, 1000);
     485           0 :                 break;
     486             :         default:
     487           0 :                 BREAK_TO_DEBUGGER();
     488           0 :                 break;
     489             :         }
     490           0 :         if (org_ip_request_cntl == 0)
     491           0 :                 REG_SET(DC_IP_REQUEST_CNTL, 0, IP_REQUEST_EN, 0);
     492             : }
     493             : 
     494           0 : int dcn31_init_sys_ctx(struct dce_hwseq *hws, struct dc *dc, struct dc_phy_addr_space_config *pa_config)
     495             : {
     496             :         struct dcn_hubbub_phys_addr_config config;
     497             : 
     498           0 :         config.system_aperture.fb_top = pa_config->system_aperture.fb_top;
     499           0 :         config.system_aperture.fb_offset = pa_config->system_aperture.fb_offset;
     500           0 :         config.system_aperture.fb_base = pa_config->system_aperture.fb_base;
     501           0 :         config.system_aperture.agp_top = pa_config->system_aperture.agp_top;
     502           0 :         config.system_aperture.agp_bot = pa_config->system_aperture.agp_bot;
     503           0 :         config.system_aperture.agp_base = pa_config->system_aperture.agp_base;
     504           0 :         config.gart_config.page_table_start_addr = pa_config->gart_config.page_table_start_addr;
     505           0 :         config.gart_config.page_table_end_addr = pa_config->gart_config.page_table_end_addr;
     506             : 
     507           0 :         if (pa_config->gart_config.base_addr_is_mc_addr) {
     508             :                 /* Convert from MC address to offset into FB */
     509           0 :                 config.gart_config.page_table_base_addr = pa_config->gart_config.page_table_base_addr -
     510           0 :                                 pa_config->system_aperture.fb_base +
     511             :                                 pa_config->system_aperture.fb_offset;
     512             :         } else
     513           0 :                 config.gart_config.page_table_base_addr = pa_config->gart_config.page_table_base_addr;
     514             : 
     515           0 :         return dc->res_pool->hubbub->funcs->init_dchub_sys_ctx(dc->res_pool->hubbub, &config);
     516             : }
     517             : 
     518           0 : static void dcn31_reset_back_end_for_pipe(
     519             :                 struct dc *dc,
     520             :                 struct pipe_ctx *pipe_ctx,
     521             :                 struct dc_state *context)
     522             : {
     523             :         struct dc_link *link;
     524             : 
     525             :         DC_LOGGER_INIT(dc->ctx->logger);
     526           0 :         if (pipe_ctx->stream_res.stream_enc == NULL) {
     527           0 :                 pipe_ctx->stream = NULL;
     528             :                 return;
     529             :         }
     530           0 :         ASSERT(!pipe_ctx->top_pipe);
     531             : 
     532           0 :         dc->hwss.set_abm_immediate_disable(pipe_ctx);
     533             : 
     534           0 :         pipe_ctx->stream_res.tg->funcs->set_dsc_config(
     535             :                         pipe_ctx->stream_res.tg,
     536             :                         OPTC_DSC_DISABLED, 0, 0);
     537           0 :         pipe_ctx->stream_res.tg->funcs->disable_crtc(pipe_ctx->stream_res.tg);
     538             : 
     539           0 :         pipe_ctx->stream_res.tg->funcs->enable_optc_clock(pipe_ctx->stream_res.tg, false);
     540           0 :         if (pipe_ctx->stream_res.tg->funcs->set_odm_bypass)
     541           0 :                 pipe_ctx->stream_res.tg->funcs->set_odm_bypass(
     542           0 :                                 pipe_ctx->stream_res.tg, &pipe_ctx->stream->timing);
     543             : 
     544           0 :         if (pipe_ctx->stream_res.tg->funcs->set_drr)
     545           0 :                 pipe_ctx->stream_res.tg->funcs->set_drr(
     546             :                                 pipe_ctx->stream_res.tg, NULL);
     547             : 
     548           0 :         if (!IS_FPGA_MAXIMUS_DC(dc->ctx->dce_environment)) {
     549           0 :                 link = pipe_ctx->stream->link;
     550             :                 /* DPMS may already disable or */
     551             :                 /* dpms_off status is incorrect due to fastboot
     552             :                  * feature. When system resume from S4 with second
     553             :                  * screen only, the dpms_off would be true but
     554             :                  * VBIOS lit up eDP, so check link status too.
     555             :                  */
     556           0 :                 if (!pipe_ctx->stream->dpms_off || link->link_status.link_active) {
     557           0 :                         if (dc->hwss.update_phy_state)
     558           0 :                                 dc->hwss.update_phy_state(dc->current_state, pipe_ctx, TX_OFF_SYMCLK_OFF);
     559             :                         else
     560           0 :                                 core_link_disable_stream(pipe_ctx);
     561           0 :                 } else if (pipe_ctx->stream_res.audio)
     562           0 :                         dc->hwss.disable_audio_stream(pipe_ctx);
     563             : 
     564             :                 /* free acquired resources */
     565           0 :                 if (pipe_ctx->stream_res.audio) {
     566             :                         /*disable az_endpoint*/
     567           0 :                         pipe_ctx->stream_res.audio->funcs->az_disable(pipe_ctx->stream_res.audio);
     568             : 
     569             :                         /*free audio*/
     570           0 :                         if (dc->caps.dynamic_audio == true) {
     571             :                                 /*we have to dynamic arbitrate the audio endpoints*/
     572             :                                 /*we free the resource, need reset is_audio_acquired*/
     573           0 :                                 update_audio_usage(&dc->current_state->res_ctx, dc->res_pool,
     574             :                                                 pipe_ctx->stream_res.audio, false);
     575           0 :                                 pipe_ctx->stream_res.audio = NULL;
     576             :                         }
     577             :                 }
     578           0 :         } else if (pipe_ctx->stream_res.dsc) {
     579           0 :                         dp_set_dsc_enable(pipe_ctx, false);
     580             :         }
     581             : 
     582           0 :         pipe_ctx->stream = NULL;
     583           0 :         DC_LOG_DEBUG("Reset back end for pipe %d, tg:%d\n",
     584             :                                         pipe_ctx->pipe_idx, pipe_ctx->stream_res.tg->inst);
     585             : }
     586             : 
     587           0 : void dcn31_reset_hw_ctx_wrap(
     588             :                 struct dc *dc,
     589             :                 struct dc_state *context)
     590             : {
     591             :         int i;
     592           0 :         struct dce_hwseq *hws = dc->hwseq;
     593             : 
     594             :         /* Reset Back End*/
     595           0 :         for (i = dc->res_pool->pipe_count - 1; i >= 0 ; i--) {
     596           0 :                 struct pipe_ctx *pipe_ctx_old =
     597           0 :                         &dc->current_state->res_ctx.pipe_ctx[i];
     598           0 :                 struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[i];
     599             : 
     600           0 :                 if (!pipe_ctx_old->stream)
     601           0 :                         continue;
     602             : 
     603           0 :                 if (pipe_ctx_old->top_pipe || pipe_ctx_old->prev_odm_pipe)
     604           0 :                         continue;
     605             : 
     606           0 :                 if (!pipe_ctx->stream ||
     607           0 :                                 pipe_need_reprogram(pipe_ctx_old, pipe_ctx)) {
     608           0 :                         struct clock_source *old_clk = pipe_ctx_old->clock_source;
     609             : 
     610           0 :                         dcn31_reset_back_end_for_pipe(dc, pipe_ctx_old, dc->current_state);
     611           0 :                         if (hws->funcs.enable_stream_gating)
     612           0 :                                 hws->funcs.enable_stream_gating(dc, pipe_ctx_old);
     613           0 :                         if (old_clk)
     614           0 :                                 old_clk->funcs->cs_power_down(old_clk);
     615             :                 }
     616             :         }
     617             : 
     618             :         /* New dc_state in the process of being applied to hardware. */
     619           0 :         link_enc_cfg_set_transient_mode(dc, dc->current_state, context);
     620           0 : }
     621             : 
     622           0 : void dcn31_setup_hpo_hw_control(const struct dce_hwseq *hws, bool enable)
     623             : {
     624           0 :         if (hws->ctx->dc->debug.hpo_optimization)
     625           0 :                 REG_UPDATE(HPO_TOP_HW_CONTROL, HPO_IO_EN, !!enable);
     626           0 : }

Generated by: LCOV version 1.14