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