File Index
Files and directories
Sign in
FILE

dcn35_hwseq.c

File preview with syntax highlighting.

linux-6.19.14/drivers/gpu/drm/amd/display/dc/hwss/dcn35/dcn35_hwseq.c C
   1/* SPDX-License-Identifier: MIT */
   2/*
   3 * Copyright 2023 Advanced Micro Devices, Inc.
   4 *
   5 * Permission is hereby granted, free of charge, to any person obtaining a
   6 * copy of this software and associated documentation files (the "Software"),
   7 * to deal in the Software without restriction, including without limitation
   8 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
   9 * and/or sell copies of the Software, and to permit persons to whom the
  10 * Software is furnished to do so, subject to the following conditions:
  11 *
  12 * The above copyright notice and this permission notice shall be included in
  13 * all copies or substantial portions of the Software.
  14 *
  15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
  18 * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
  19 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
  20 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
  21 * OTHER DEALINGS IN THE SOFTWARE.
  22 *
  23 * Authors: AMD
  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 "dcn35_hwseq.h"
  45#include "dcn35/dcn35_dccg.h"
  46#include "link_hwss.h"
  47#include "dpcd_defs.h"
  48#include "dce/dmub_outbox.h"
  49#include "link_service.h"
  50#include "dcn10/dcn10_hwseq.h"
  51#include "inc/link_enc_cfg.h"
  52#include "dcn30/dcn30_vpg.h"
  53#include "dce/dce_i2c_hw.h"
  54#include "dsc.h"
  55#include "dcn20/dcn20_optc.h"
  56#include "dcn30/dcn30_cm_common.h"
  57#include "dcn31/dcn31_hwseq.h"
  58#include "dcn20/dcn20_hwseq.h"
  59#include "dc_state_priv.h"
  60
  61#define DC_LOGGER_INIT(logger) \
  62	struct dal_logger *dc_logger = logger
  63
  64#define CTX \
  65	hws->ctx
  66#define REG(reg)\
  67	hws->regs->reg
  68#define DC_LOGGER \
  69	dc_logger
  70
  71
  72#undef FN
  73#define FN(reg_name, field_name) \
  74	hws->shifts->field_name, hws->masks->field_name
  75#if 0
  76static void enable_memory_low_power(struct dc *dc)
  77{
  78	struct dce_hwseq *hws = dc->hwseq;
  79	int i;
  80
  81	if (dc->debug.enable_mem_low_power.bits.dmcu) {
  82		// Force ERAM to shutdown if DMCU is not enabled
  83		if (dc->debug.disable_dmcu || dc->config.disable_dmcu) {
  84			REG_UPDATE(DMU_MEM_PWR_CNTL, DMCU_ERAM_MEM_PWR_FORCE, 3);
  85		}
  86	}
  87	/*dcn35 has default MEM_PWR enabled, make sure wake them up*/
  88	// Set default OPTC memory power states
  89	if (dc->debug.enable_mem_low_power.bits.optc) {
  90		// Shutdown when unassigned and light sleep in VBLANK
  91		REG_SET_2(ODM_MEM_PWR_CTRL3, 0, ODM_MEM_UNASSIGNED_PWR_MODE, 3, ODM_MEM_VBLANK_PWR_MODE, 1);
  92	}
  93
  94	if (dc->debug.enable_mem_low_power.bits.vga) {
  95		// Power down VGA memory
  96		REG_UPDATE(MMHUBBUB_MEM_PWR_CNTL, VGA_MEM_PWR_FORCE, 1);
  97	}
  98
  99	if (dc->debug.enable_mem_low_power.bits.mpc &&
 100		dc->res_pool->mpc->funcs->set_mpc_mem_lp_mode)
 101		dc->res_pool->mpc->funcs->set_mpc_mem_lp_mode(dc->res_pool->mpc);
 102
 103	if (dc->debug.enable_mem_low_power.bits.vpg && dc->res_pool->stream_enc[0]->vpg->funcs->vpg_powerdown) {
 104		// Power down VPGs
 105		for (i = 0; i < dc->res_pool->stream_enc_count; i++)
 106			dc->res_pool->stream_enc[i]->vpg->funcs->vpg_powerdown(dc->res_pool->stream_enc[i]->vpg);
 107#if defined(CONFIG_DRM_AMD_DC_DP2_0)
 108		for (i = 0; i < dc->res_pool->hpo_dp_stream_enc_count; i++)
 109			dc->res_pool->hpo_dp_stream_enc[i]->vpg->funcs->vpg_powerdown(dc->res_pool->hpo_dp_stream_enc[i]->vpg);
 110#endif
 111	}
 112
 113}
 114#endif
 115
 116static void print_pg_status(struct dc *dc, const char *debug_func, const char *debug_log)
 117{
 118	if (dc->debug.enable_pg_cntl_debug_logs && dc->res_pool->pg_cntl) {
 119		if (dc->res_pool->pg_cntl->funcs->print_pg_status)
 120			dc->res_pool->pg_cntl->funcs->print_pg_status(dc->res_pool->pg_cntl, debug_func, debug_log);
 121	}
 122}
 123
 124void dcn35_set_dmu_fgcg(struct dce_hwseq *hws, bool enable)
 125{
 126	REG_UPDATE_3(DMU_CLK_CNTL,
 127		RBBMIF_FGCG_REP_DIS, !enable,
 128		IHC_FGCG_REP_DIS, !enable,
 129		LONO_FGCG_REP_DIS, !enable
 130	);
 131}
 132
 133void dcn35_setup_hpo_hw_control(const struct dce_hwseq *hws, bool enable)
 134{
 135	REG_UPDATE(HPO_TOP_HW_CONTROL, HPO_IO_EN, !!enable);
 136}
 137
 138void dcn35_init_hw(struct dc *dc)
 139{
 140	struct abm **abms = dc->res_pool->multiple_abms;
 141	struct dce_hwseq *hws = dc->hwseq;
 142	struct dc_bios *dcb = dc->ctx->dc_bios;
 143	struct resource_pool *res_pool = dc->res_pool;
 144	uint32_t backlight = MAX_BACKLIGHT_LEVEL;
 145	uint32_t user_level = MAX_BACKLIGHT_LEVEL;
 146	int i;
 147
 148	print_pg_status(dc, __func__, ": start");
 149
 150	if (dc->clk_mgr && dc->clk_mgr->funcs->init_clocks)
 151		dc->clk_mgr->funcs->init_clocks(dc->clk_mgr);
 152
 153	//dcn35_set_dmu_fgcg(hws, dc->debug.enable_fine_grain_clock_gating.bits.dmu);
 154
 155	if (!dcb->funcs->is_accelerated_mode(dcb)) {
 156		/*this calls into dmubfw to do the init*/
 157		hws->funcs.bios_golden_init(dc);
 158	}
 159
 160	// Initialize the dccg
 161	if (res_pool->dccg->funcs->dccg_init)
 162		res_pool->dccg->funcs->dccg_init(res_pool->dccg);
 163
 164	//enable_memory_low_power(dc);
 165
 166	if (dc->ctx->dc_bios->fw_info_valid) {
 167		res_pool->ref_clocks.xtalin_clock_inKhz =
 168				dc->ctx->dc_bios->fw_info.pll_info.crystal_frequency;
 169
 170		if (res_pool->hubbub) {
 171
 172			(res_pool->dccg->funcs->get_dccg_ref_freq)(res_pool->dccg,
 173				dc->ctx->dc_bios->fw_info.pll_info.crystal_frequency,
 174				&res_pool->ref_clocks.dccg_ref_clock_inKhz);
 175
 176			(res_pool->hubbub->funcs->get_dchub_ref_freq)(res_pool->hubbub,
 177				res_pool->ref_clocks.dccg_ref_clock_inKhz,
 178				&res_pool->ref_clocks.dchub_ref_clock_inKhz);
 179		} else {
 180			// Not all ASICs have DCCG sw component
 181			res_pool->ref_clocks.dccg_ref_clock_inKhz =
 182				res_pool->ref_clocks.xtalin_clock_inKhz;
 183			res_pool->ref_clocks.dchub_ref_clock_inKhz =
 184				res_pool->ref_clocks.xtalin_clock_inKhz;
 185		}
 186	} else
 187		ASSERT_CRITICAL(false);
 188
 189	for (i = 0; i < dc->link_count; i++) {
 190		/* Power up AND update implementation according to the
 191		 * required signal (which may be different from the
 192		 * default signal on connector).
 193		 */
 194		struct dc_link *link = dc->links[i];
 195
 196		if (link->ep_type != DISPLAY_ENDPOINT_PHY)
 197			continue;
 198
 199		link->link_enc->funcs->hw_init(link->link_enc);
 200
 201		/* Check for enabled DIG to identify enabled display */
 202		if (link->link_enc->funcs->is_dig_enabled &&
 203			link->link_enc->funcs->is_dig_enabled(link->link_enc)) {
 204			link->link_status.link_active = true;
 205			if (link->link_enc->funcs->fec_is_active &&
 206					link->link_enc->funcs->fec_is_active(link->link_enc))
 207				link->fec_state = dc_link_fec_enabled;
 208		}
 209	}
 210
 211	/* we want to turn off all dp displays before doing detection */
 212	dc->link_srv->blank_all_dp_displays(dc);
 213
 214	if (res_pool->hubbub && res_pool->hubbub->funcs->dchubbub_init)
 215		res_pool->hubbub->funcs->dchubbub_init(dc->res_pool->hubbub);
 216	/* If taking control over from VBIOS, we may want to optimize our first
 217	 * mode set, so we need to skip powering down pipes until we know which
 218	 * pipes we want to use.
 219	 * Otherwise, if taking control is not possible, we need to power
 220	 * everything down.
 221	 */
 222	if (dcb->funcs->is_accelerated_mode(dcb) || !dc->config.seamless_boot_edp_requested) {
 223
 224		// we want to turn off edp displays if odm is enabled and no seamless boot
 225		if (!dc->caps.seamless_odm) {
 226			for (i = 0; i < dc->res_pool->timing_generator_count; i++) {
 227				struct timing_generator *tg = dc->res_pool->timing_generators[i];
 228				uint32_t num_opps, opp_id_src0, opp_id_src1;
 229
 230				num_opps = 1;
 231				if (tg) {
 232					if (tg->funcs->is_tg_enabled(tg) && tg->funcs->get_optc_source) {
 233						tg->funcs->get_optc_source(tg, &num_opps,
 234								&opp_id_src0, &opp_id_src1);
 235					}
 236				}
 237
 238				if (num_opps > 1) {
 239					dc->link_srv->blank_all_edp_displays(dc);
 240					break;
 241				}
 242			}
 243		}
 244
 245		hws->funcs.init_pipes(dc, dc->current_state);
 246		print_pg_status(dc, __func__, ": after init_pipes");
 247
 248		if (dc->res_pool->hubbub->funcs->allow_self_refresh_control &&
 249			!dc->res_pool->hubbub->ctx->dc->debug.disable_stutter)
 250			dc->res_pool->hubbub->funcs->allow_self_refresh_control(dc->res_pool->hubbub,
 251					!dc->res_pool->hubbub->ctx->dc->debug.disable_stutter);
 252	}
 253	for (i = 0; i < res_pool->audio_count; i++) {
 254		struct audio *audio = res_pool->audios[i];
 255
 256		audio->funcs->hw_init(audio);
 257	}
 258
 259	for (i = 0; i < dc->link_count; i++) {
 260		struct dc_link *link = dc->links[i];
 261
 262		if (link->panel_cntl) {
 263			backlight = link->panel_cntl->funcs->hw_init(link->panel_cntl);
 264			user_level = link->panel_cntl->stored_backlight_registers.USER_LEVEL;
 265		}
 266	}
 267	if (dc->ctx->dmub_srv) {
 268	for (i = 0; i < dc->res_pool->pipe_count; i++) {
 269		if (abms[i] != NULL && abms[i]->funcs != NULL)
 270			abms[i]->funcs->abm_init(abms[i], backlight, user_level);
 271		}
 272	}
 273
 274	/* power AFMT HDMI memory TODO: may move to dis/en output save power*/
 275	REG_WRITE(DIO_MEM_PWR_CTRL, 0);
 276
 277	// Set i2c to light sleep until engine is setup
 278	if (dc->debug.enable_mem_low_power.bits.i2c)
 279		REG_UPDATE(DIO_MEM_PWR_CTRL, I2C_LIGHT_SLEEP_FORCE, 0);
 280
 281	if (hws->funcs.setup_hpo_hw_control)
 282		hws->funcs.setup_hpo_hw_control(hws, false);
 283
 284	if (!dc->debug.disable_clock_gate) {
 285		/* enable all DCN clock gating */
 286		REG_UPDATE(DCFCLK_CNTL, DCFCLK_GATE_DIS, 0);
 287	}
 288
 289	if (dc->debug.disable_mem_low_power) {
 290		REG_UPDATE(DC_MEM_GLOBAL_PWR_REQ_CNTL, DC_MEM_GLOBAL_PWR_REQ_DIS, 1);
 291	}
 292	if (!dcb->funcs->is_accelerated_mode(dcb) && dc->res_pool->hubbub->funcs->init_watermarks)
 293		dc->res_pool->hubbub->funcs->init_watermarks(dc->res_pool->hubbub);
 294
 295	if (dc->clk_mgr && dc->clk_mgr->funcs->notify_wm_ranges)
 296		dc->clk_mgr->funcs->notify_wm_ranges(dc->clk_mgr);
 297
 298	if (dc->clk_mgr && dc->clk_mgr->funcs->set_hard_max_memclk && !dc->clk_mgr->dc_mode_softmax_enabled)
 299		dc->clk_mgr->funcs->set_hard_max_memclk(dc->clk_mgr);
 300
 301
 302
 303	if (dc->res_pool->hubbub->funcs->force_pstate_change_control)
 304		dc->res_pool->hubbub->funcs->force_pstate_change_control(
 305				dc->res_pool->hubbub, false, false);
 306
 307	if (dc->res_pool->hubbub->funcs->init_crb)
 308		dc->res_pool->hubbub->funcs->init_crb(dc->res_pool->hubbub);
 309
 310	if (dc->res_pool->hubbub->funcs->set_request_limit && dc->config.sdpif_request_limit_words_per_umc > 0)
 311		dc->res_pool->hubbub->funcs->set_request_limit(dc->res_pool->hubbub, dc->ctx->dc_bios->vram_info.num_chans, dc->config.sdpif_request_limit_words_per_umc);
 312	// Get DMCUB capabilities
 313	if (dc->ctx->dmub_srv) {
 314		dc_dmub_srv_query_caps_cmd(dc->ctx->dmub_srv);
 315		dc->caps.dmub_caps.psr = dc->ctx->dmub_srv->dmub->feature_caps.psr;
 316		dc->caps.dmub_caps.mclk_sw = dc->ctx->dmub_srv->dmub->feature_caps.fw_assisted_mclk_switch_ver;
 317		dc->caps.dmub_caps.aux_backlight_support = dc->ctx->dmub_srv->dmub->feature_caps.abm_aux_backlight_support;
 318	}
 319
 320	if (dc->res_pool->pg_cntl) {
 321		if (dc->res_pool->pg_cntl->funcs->init_pg_status)
 322			dc->res_pool->pg_cntl->funcs->init_pg_status(dc->res_pool->pg_cntl);
 323	}
 324	print_pg_status(dc, __func__, ": after init_pg_status");
 325}
 326
 327static void update_dsc_on_stream(struct pipe_ctx *pipe_ctx, bool enable)
 328{
 329	struct display_stream_compressor *dsc = pipe_ctx->stream_res.dsc;
 330	struct dc_stream_state *stream = pipe_ctx->stream;
 331	struct pipe_ctx *odm_pipe;
 332	int opp_cnt = 1;
 333
 334	DC_LOGGER_INIT(stream->ctx->logger);
 335
 336	ASSERT(dsc);
 337	for (odm_pipe = pipe_ctx->next_odm_pipe; odm_pipe; odm_pipe = odm_pipe->next_odm_pipe)
 338		opp_cnt++;
 339
 340	if (enable) {
 341		struct dsc_config dsc_cfg;
 342		struct dsc_optc_config dsc_optc_cfg = {0};
 343		enum optc_dsc_mode optc_dsc_mode;
 344		struct dcn_dsc_state dsc_state = {0};
 345
 346		if (!dsc) {
 347			DC_LOG_DSC("DSC is NULL for tg instance %d:", pipe_ctx->stream_res.tg->inst);
 348			return;
 349		}
 350
 351		if (dsc->funcs->dsc_read_state) {
 352			dsc->funcs->dsc_read_state(dsc, &dsc_state);
 353			if (!dsc_state.dsc_fw_en) {
 354				DC_LOG_DSC("DSC has been disabled for tg instance %d:", pipe_ctx->stream_res.tg->inst);
 355				return;
 356			}
 357		}
 358		/* Enable DSC hw block */
 359		dsc_cfg.pic_width = (stream->timing.h_addressable + stream->timing.h_border_left + stream->timing.h_border_right) / opp_cnt;
 360		dsc_cfg.pic_height = stream->timing.v_addressable + stream->timing.v_border_top + stream->timing.v_border_bottom;
 361		dsc_cfg.pixel_encoding = stream->timing.pixel_encoding;
 362		dsc_cfg.color_depth = stream->timing.display_color_depth;
 363		dsc_cfg.is_odm = pipe_ctx->next_odm_pipe ? true : false;
 364		dsc_cfg.dc_dsc_cfg = stream->timing.dsc_cfg;
 365		ASSERT(dsc_cfg.dc_dsc_cfg.num_slices_h % opp_cnt == 0);
 366		dsc_cfg.dc_dsc_cfg.num_slices_h /= opp_cnt;
 367		dsc_cfg.dsc_padding = 0;
 368
 369		dsc->funcs->dsc_set_config(dsc, &dsc_cfg, &dsc_optc_cfg);
 370		dsc->funcs->dsc_enable(dsc, pipe_ctx->stream_res.opp->inst);
 371		for (odm_pipe = pipe_ctx->next_odm_pipe; odm_pipe; odm_pipe = odm_pipe->next_odm_pipe) {
 372			struct display_stream_compressor *odm_dsc = odm_pipe->stream_res.dsc;
 373
 374			ASSERT(odm_dsc);
 375			odm_dsc->funcs->dsc_set_config(odm_dsc, &dsc_cfg, &dsc_optc_cfg);
 376			odm_dsc->funcs->dsc_enable(odm_dsc, odm_pipe->stream_res.opp->inst);
 377		}
 378		dsc_cfg.dc_dsc_cfg.num_slices_h *= opp_cnt;
 379		dsc_cfg.pic_width *= opp_cnt;
 380
 381		optc_dsc_mode = dsc_optc_cfg.is_pixel_format_444 ? OPTC_DSC_ENABLED_444 : OPTC_DSC_ENABLED_NATIVE_SUBSAMPLED;
 382
 383		/* Enable DSC in OPTC */
 384		DC_LOG_DSC("Setting optc DSC config for tg instance %d:", pipe_ctx->stream_res.tg->inst);
 385		pipe_ctx->stream_res.tg->funcs->set_dsc_config(pipe_ctx->stream_res.tg,
 386							optc_dsc_mode,
 387							dsc_optc_cfg.bytes_per_pixel,
 388							dsc_optc_cfg.slice_width);
 389	} else {
 390		/* disable DSC in OPTC */
 391		pipe_ctx->stream_res.tg->funcs->set_dsc_config(
 392				pipe_ctx->stream_res.tg,
 393				OPTC_DSC_DISABLED, 0, 0);
 394
 395		/* disable DSC block */
 396		dsc->funcs->dsc_disable(pipe_ctx->stream_res.dsc);
 397		for (odm_pipe = pipe_ctx->next_odm_pipe; odm_pipe; odm_pipe = odm_pipe->next_odm_pipe) {
 398			ASSERT(odm_pipe->stream_res.dsc);
 399			odm_pipe->stream_res.dsc->funcs->dsc_disable(odm_pipe->stream_res.dsc);
 400		}
 401	}
 402}
 403
 404// Given any pipe_ctx, return the total ODM combine factor, and optionally return
 405// the OPPids which are used
 406static unsigned int get_odm_config(struct pipe_ctx *pipe_ctx, unsigned int *opp_instances)
 407{
 408	unsigned int opp_count = 1;
 409	struct pipe_ctx *odm_pipe;
 410
 411	// First get to the top pipe
 412	for (odm_pipe = pipe_ctx; odm_pipe->prev_odm_pipe; odm_pipe = odm_pipe->prev_odm_pipe)
 413		;
 414
 415	// First pipe is always used
 416	if (opp_instances)
 417		opp_instances[0] = odm_pipe->stream_res.opp->inst;
 418
 419	// Find and count odm pipes, if any
 420	for (odm_pipe = odm_pipe->next_odm_pipe; odm_pipe; odm_pipe = odm_pipe->next_odm_pipe) {
 421		if (opp_instances)
 422			opp_instances[opp_count] = odm_pipe->stream_res.opp->inst;
 423		opp_count++;
 424	}
 425
 426	return opp_count;
 427}
 428
 429void dcn35_update_odm(struct dc *dc, struct dc_state *context, struct pipe_ctx *pipe_ctx)
 430{
 431	struct pipe_ctx *odm_pipe;
 432	int opp_cnt = 0;
 433	int opp_inst[MAX_PIPES] = {0};
 434	int odm_slice_width = resource_get_odm_slice_dst_width(pipe_ctx, false);
 435	int last_odm_slice_width = resource_get_odm_slice_dst_width(pipe_ctx, true);
 436	struct mpc *mpc = dc->res_pool->mpc;
 437	int i;
 438
 439	opp_cnt = get_odm_config(pipe_ctx, opp_inst);
 440
 441	if (opp_cnt > 1)
 442		pipe_ctx->stream_res.tg->funcs->set_odm_combine(
 443				pipe_ctx->stream_res.tg,
 444				opp_inst, opp_cnt,
 445				odm_slice_width, last_odm_slice_width);
 446	else
 447		pipe_ctx->stream_res.tg->funcs->set_odm_bypass(
 448				pipe_ctx->stream_res.tg, &pipe_ctx->stream->timing);
 449
 450	if (mpc->funcs->set_out_rate_control) {
 451		for (i = 0; i < opp_cnt; ++i) {
 452			mpc->funcs->set_out_rate_control(
 453					mpc, opp_inst[i],
 454					false,
 455					0,
 456					NULL);
 457		}
 458	}
 459
 460	for (odm_pipe = pipe_ctx->next_odm_pipe; odm_pipe; odm_pipe = odm_pipe->next_odm_pipe) {
 461		odm_pipe->stream_res.opp->funcs->opp_pipe_clock_control(
 462				odm_pipe->stream_res.opp,
 463				true);
 464	}
 465
 466	if (pipe_ctx->stream_res.dsc) {
 467		struct pipe_ctx *current_pipe_ctx = &dc->current_state->res_ctx.pipe_ctx[pipe_ctx->pipe_idx];
 468
 469		update_dsc_on_stream(pipe_ctx, pipe_ctx->stream->timing.flags.DSC);
 470
 471		/* Check if no longer using pipe for ODM, then need to disconnect DSC for that pipe */
 472		if (!pipe_ctx->next_odm_pipe && current_pipe_ctx->next_odm_pipe &&
 473				current_pipe_ctx->next_odm_pipe->stream_res.dsc) {
 474			struct display_stream_compressor *dsc = current_pipe_ctx->next_odm_pipe->stream_res.dsc;
 475			/* disconnect DSC block from stream */
 476			dsc->funcs->dsc_disconnect(dsc);
 477		}
 478	}
 479}
 480
 481void dcn35_dpp_root_clock_control(struct dce_hwseq *hws, unsigned int dpp_inst, bool clock_on)
 482{
 483	if (!hws->ctx->dc->debug.root_clock_optimization.bits.dpp)
 484		return;
 485
 486	if (hws->ctx->dc->res_pool->dccg->funcs->dpp_root_clock_control) {
 487		hws->ctx->dc->res_pool->dccg->funcs->dpp_root_clock_control(
 488			hws->ctx->dc->res_pool->dccg, dpp_inst, clock_on);
 489	}
 490}
 491
 492void dcn35_dpstream_root_clock_control(struct dce_hwseq *hws, unsigned int dp_hpo_inst, bool clock_on)
 493{
 494	if (!hws->ctx->dc->debug.root_clock_optimization.bits.dpstream)
 495		return;
 496
 497	if (hws->ctx->dc->res_pool->dccg->funcs->set_dpstreamclk_root_clock_gating) {
 498		hws->ctx->dc->res_pool->dccg->funcs->set_dpstreamclk_root_clock_gating(
 499			hws->ctx->dc->res_pool->dccg, dp_hpo_inst, clock_on);
 500	}
 501}
 502
 503void dcn35_physymclk_root_clock_control(struct dce_hwseq *hws, unsigned int phy_inst, bool clock_on)
 504{
 505	if (!hws->ctx->dc->debug.root_clock_optimization.bits.physymclk)
 506		return;
 507
 508	if (hws->ctx->dc->res_pool->dccg->funcs->set_physymclk_root_clock_gating) {
 509		hws->ctx->dc->res_pool->dccg->funcs->set_physymclk_root_clock_gating(
 510			hws->ctx->dc->res_pool->dccg, phy_inst, clock_on);
 511	}
 512}
 513
 514/* In headless boot cases, DIG may be turned
 515 * on which causes HW/SW discrepancies.
 516 * To avoid this, power down hardware on boot
 517 * if DIG is turned on
 518 */
 519void dcn35_power_down_on_boot(struct dc *dc)
 520{
 521	struct dc_link *edp_links[MAX_NUM_EDP];
 522	struct dc_link *edp_link = NULL;
 523	int edp_num;
 524	int i = 0;
 525
 526	dc_get_edp_links(dc, edp_links, &edp_num);
 527	if (edp_num)
 528		edp_link = edp_links[0];
 529
 530	if (edp_link && edp_link->link_enc->funcs->is_dig_enabled &&
 531			edp_link->link_enc->funcs->is_dig_enabled(edp_link->link_enc) &&
 532			dc->hwseq->funcs.edp_backlight_control &&
 533			dc->hwseq->funcs.power_down &&
 534			dc->hwss.edp_power_control) {
 535		dc->hwseq->funcs.edp_backlight_control(edp_link, false);
 536		dc->hwseq->funcs.power_down(dc);
 537		dc->hwss.edp_power_control(edp_link, false);
 538	} else {
 539		for (i = 0; i < dc->link_count; i++) {
 540			struct dc_link *link = dc->links[i];
 541
 542			if (link->link_enc && link->link_enc->funcs->is_dig_enabled &&
 543					link->link_enc->funcs->is_dig_enabled(link->link_enc) &&
 544					dc->hwseq->funcs.power_down) {
 545				dc->hwseq->funcs.power_down(dc);
 546				break;
 547			}
 548
 549		}
 550	}
 551
 552	/*
 553	 * Call update_clocks with empty context
 554	 * to send DISPLAY_OFF
 555	 * Otherwise DISPLAY_OFF may not be asserted
 556	 */
 557	if (dc->clk_mgr->funcs->set_low_power_state)
 558		dc->clk_mgr->funcs->set_low_power_state(dc->clk_mgr);
 559
 560	if (dc->clk_mgr->clks.pwr_state == DCN_PWR_STATE_LOW_POWER)
 561		dc_allow_idle_optimizations(dc, true);
 562}
 563
 564bool dcn35_apply_idle_power_optimizations(struct dc *dc, bool enable)
 565{
 566	if (dc->debug.dmcub_emulation)
 567		return true;
 568
 569	if (enable) {
 570		uint32_t num_active_edp = 0;
 571		int i;
 572
 573		for (i = 0; i < dc->current_state->stream_count; ++i) {
 574			struct dc_stream_state *stream = dc->current_state->streams[i];
 575			struct dc_link *link = stream->link;
 576			bool is_psr = link && !link->panel_config.psr.disable_psr &&
 577				      (link->psr_settings.psr_version == DC_PSR_VERSION_1 ||
 578				       link->psr_settings.psr_version == DC_PSR_VERSION_SU_1);
 579			bool is_replay = link && link->replay_settings.replay_feature_enabled;
 580
 581			/* Ignore streams that disabled. */
 582			if (stream->dpms_off)
 583				continue;
 584
 585			/* Active external displays block idle optimizations. */
 586			if (!dc_is_embedded_signal(stream->signal))
 587				return false;
 588
 589			/* If not PWRSEQ0 can't enter idle optimizations */
 590			if (link && link->link_index != 0)
 591				return false;
 592
 593			/* Check for panel power features required for idle optimizations. */
 594			if (!is_psr && !is_replay)
 595				return false;
 596
 597			num_active_edp += 1;
 598		}
 599
 600		/* If more than one active eDP then disallow. */
 601		if (num_active_edp > 1)
 602			return false;
 603	}
 604
 605	// TODO: review other cases when idle optimization is allowed
 606	dc_dmub_srv_apply_idle_power_optimizations(dc, enable);
 607
 608	return true;
 609}
 610
 611void dcn35_z10_restore(const struct dc *dc)
 612{
 613	if (dc->debug.disable_z10)
 614		return;
 615
 616	dc_dmub_srv_apply_idle_power_optimizations(dc, false);
 617
 618	dcn31_z10_restore(dc);
 619}
 620
 621void dcn35_init_pipes(struct dc *dc, struct dc_state *context)
 622{
 623	int i;
 624	struct dce_hwseq *hws = dc->hwseq;
 625	struct hubbub *hubbub = dc->res_pool->hubbub;
 626	struct pg_cntl *pg_cntl = dc->res_pool->pg_cntl;
 627	bool can_apply_seamless_boot = false;
 628	bool tg_enabled[MAX_PIPES] = {false};
 629
 630	for (i = 0; i < context->stream_count; i++) {
 631		if (context->streams[i]->apply_seamless_boot_optimization) {
 632			can_apply_seamless_boot = true;
 633			break;
 634		}
 635	}
 636
 637	for (i = 0; i < dc->res_pool->pipe_count; i++) {
 638		struct timing_generator *tg = dc->res_pool->timing_generators[i];
 639		struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[i];
 640
 641		/* There is assumption that pipe_ctx is not mapping irregularly
 642		 * to non-preferred front end. If pipe_ctx->stream is not NULL,
 643		 * we will use the pipe, so don't disable
 644		 */
 645		if (pipe_ctx->stream != NULL && can_apply_seamless_boot)
 646			continue;
 647
 648		/* Blank controller using driver code instead of
 649		 * command table.
 650		 */
 651		if (tg->funcs->is_tg_enabled(tg)) {
 652			if (hws->funcs.init_blank != NULL) {
 653				hws->funcs.init_blank(dc, tg);
 654				tg->funcs->lock(tg);
 655			} else {
 656				tg->funcs->lock(tg);
 657				tg->funcs->set_blank(tg, true);
 658				hwss_wait_for_blank_complete(tg);
 659			}
 660		}
 661	}
 662
 663	/* Reset det size */
 664	for (i = 0; i < dc->res_pool->pipe_count; i++) {
 665		struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[i];
 666		struct hubp *hubp = dc->res_pool->hubps[i];
 667
 668		/* Do not need to reset for seamless boot */
 669		if (pipe_ctx->stream != NULL && can_apply_seamless_boot)
 670			continue;
 671
 672		if (hubbub && hubp) {
 673			if (hubbub->funcs->program_det_size)
 674				hubbub->funcs->program_det_size(hubbub, hubp->inst, 0);
 675			if (hubbub->funcs->program_det_segments)
 676				hubbub->funcs->program_det_segments(hubbub, hubp->inst, 0);
 677		}
 678	}
 679
 680	/* num_opp will be equal to number of mpcc */
 681	for (i = 0; i < dc->res_pool->res_cap->num_opp; i++) {
 682		struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[i];
 683
 684		/* Cannot reset the MPC mux if seamless boot */
 685		if (pipe_ctx->stream != NULL && can_apply_seamless_boot)
 686			continue;
 687
 688		dc->res_pool->mpc->funcs->mpc_init_single_inst(
 689				dc->res_pool->mpc, i);
 690	}
 691
 692	for (i = 0; i < dc->res_pool->pipe_count; i++) {
 693		struct timing_generator *tg = dc->res_pool->timing_generators[i];
 694		struct hubp *hubp = dc->res_pool->hubps[i];
 695		struct dpp *dpp = dc->res_pool->dpps[i];
 696		struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[i];
 697
 698		/* There is assumption that pipe_ctx is not mapping irregularly
 699		 * to non-preferred front end. If pipe_ctx->stream is not NULL,
 700		 * we will use the pipe, so don't disable
 701		 */
 702		if (can_apply_seamless_boot &&
 703			pipe_ctx->stream != NULL &&
 704			pipe_ctx->stream_res.tg->funcs->is_tg_enabled(
 705				pipe_ctx->stream_res.tg)) {
 706			// Enable double buffering for OTG_BLANK no matter if
 707			// seamless boot is enabled or not to suppress global sync
 708			// signals when OTG blanked. This is to prevent pipe from
 709			// requesting data while in PSR.
 710			tg->funcs->tg_init(tg);
 711			hubp->power_gated = true;
 712			tg_enabled[i] = true;
 713			continue;
 714		}
 715
 716		/* Disable on the current state so the new one isn't cleared. */
 717		pipe_ctx = &dc->current_state->res_ctx.pipe_ctx[i];
 718
 719		hubp->funcs->hubp_reset(hubp);
 720		dpp->funcs->dpp_reset(dpp);
 721
 722		pipe_ctx->stream_res.tg = tg;
 723		pipe_ctx->pipe_idx = i;
 724
 725		pipe_ctx->plane_res.hubp = hubp;
 726		pipe_ctx->plane_res.dpp = dpp;
 727		pipe_ctx->plane_res.mpcc_inst = dpp->inst;
 728		hubp->mpcc_id = dpp->inst;
 729		hubp->opp_id = OPP_ID_INVALID;
 730		hubp->power_gated = false;
 731
 732		dc->res_pool->opps[i]->mpc_tree_params.opp_id = dc->res_pool->opps[i]->inst;
 733		dc->res_pool->opps[i]->mpc_tree_params.opp_list = NULL;
 734		dc->res_pool->opps[i]->mpcc_disconnect_pending[pipe_ctx->plane_res.mpcc_inst] = true;
 735		pipe_ctx->stream_res.opp = dc->res_pool->opps[i];
 736
 737		hws->funcs.plane_atomic_disconnect(dc, context, pipe_ctx);
 738
 739		if (tg->funcs->is_tg_enabled(tg))
 740			tg->funcs->unlock(tg);
 741
 742		dc->hwss.disable_plane(dc, context, pipe_ctx);
 743
 744		pipe_ctx->stream_res.tg = NULL;
 745		pipe_ctx->plane_res.hubp = NULL;
 746
 747		if (tg->funcs->is_tg_enabled(tg)) {
 748			if (tg->funcs->init_odm)
 749				tg->funcs->init_odm(tg);
 750		}
 751
 752		tg->funcs->tg_init(tg);
 753	}
 754
 755	/* Clean up MPC tree */
 756	for (i = 0; i < dc->res_pool->pipe_count; i++) {
 757		if (tg_enabled[i]) {
 758			if (dc->res_pool->opps[i]->mpc_tree_params.opp_list) {
 759				if (dc->res_pool->opps[i]->mpc_tree_params.opp_list->mpcc_bot) {
 760					int bot_id = dc->res_pool->opps[i]->mpc_tree_params.opp_list->mpcc_bot->mpcc_id;
 761
 762					if ((bot_id < MAX_MPCC) && (bot_id < MAX_PIPES) && (!tg_enabled[bot_id]))
 763						dc->res_pool->opps[i]->mpc_tree_params.opp_list = NULL;
 764				}
 765			}
 766		}
 767	}
 768
 769	if (pg_cntl != NULL) {
 770		if (pg_cntl->funcs->dsc_pg_control != NULL) {
 771			uint32_t num_opps = 0;
 772			uint32_t opp_id_src0 = OPP_ID_INVALID;
 773			uint32_t opp_id_src1 = OPP_ID_INVALID;
 774			uint32_t optc_dsc_state = 0;
 775
 776			// Step 1: To find out which OPTC is running & OPTC DSC is ON
 777			// We can't use res_pool->res_cap->num_timing_generator to check
 778			// Because it records display pipes default setting built in driver,
 779			// not display pipes of the current chip.
 780			// Some ASICs would be fused display pipes less than the default setting.
 781			// In dcnxx_resource_construct function, driver would obatin real information.
 782			for (i = 0; i < dc->res_pool->timing_generator_count; i++) {
 783				struct timing_generator *tg = dc->res_pool->timing_generators[i];
 784
 785				if (tg->funcs->is_tg_enabled(tg)) {
 786					if (tg->funcs->get_dsc_status)
 787						tg->funcs->get_dsc_status(tg, &optc_dsc_state);
 788					// Only one OPTC with DSC is ON, so if we got one result,
 789					// we would exit this block. non-zero value is DSC enabled
 790					if (optc_dsc_state != 0) {
 791						tg->funcs->get_optc_source(tg, &num_opps, &opp_id_src0, &opp_id_src1);
 792						break;
 793					}
 794				}
 795			}
 796
 797			// Step 2: To power down DSC but skip DSC of running OPTC
 798			for (i = 0; i < dc->res_pool->res_cap->num_dsc; i++) {
 799				struct dcn_dsc_state s  = {0};
 800
 801				/* avoid reading DSC state when it is not in use as it may be power gated */
 802				if (optc_dsc_state) {
 803					dc->res_pool->dscs[i]->funcs->dsc_read_state(dc->res_pool->dscs[i], &s);
 804
 805					if ((s.dsc_opp_source == opp_id_src0 || s.dsc_opp_source == opp_id_src1) &&
 806						s.dsc_clock_en && s.dsc_fw_en)
 807						continue;
 808				}
 809
 810				pg_cntl->funcs->dsc_pg_control(pg_cntl, dc->res_pool->dscs[i]->inst, false);
 811			}
 812		}
 813	}
 814}
 815
 816void dcn35_enable_plane(struct dc *dc, struct pipe_ctx *pipe_ctx,
 817			       struct dc_state *context)
 818{
 819	struct dpp *dpp = pipe_ctx->plane_res.dpp;
 820
 821	/* enable DCFCLK current DCHUB */
 822	pipe_ctx->plane_res.hubp->funcs->hubp_clk_cntl(pipe_ctx->plane_res.hubp, true);
 823
 824	/* initialize HUBP on power up */
 825	pipe_ctx->plane_res.hubp->funcs->hubp_init(pipe_ctx->plane_res.hubp);
 826	/*make sure DPPCLK is on*/
 827	dpp->funcs->dpp_dppclk_control(dpp, false, true);
 828	/* make sure OPP_PIPE_CLOCK_EN = 1 */
 829	pipe_ctx->stream_res.opp->funcs->opp_pipe_clock_control(
 830			pipe_ctx->stream_res.opp,
 831			true);
 832	/*to do: insert PG here*/
 833	if (dc->vm_pa_config.valid) {
 834		struct vm_system_aperture_param apt;
 835
 836		apt.sys_default.quad_part = 0;
 837
 838		apt.sys_low.quad_part = dc->vm_pa_config.system_aperture.start_addr;
 839		apt.sys_high.quad_part = dc->vm_pa_config.system_aperture.end_addr;
 840
 841		// Program system aperture settings
 842		pipe_ctx->plane_res.hubp->funcs->hubp_set_vm_system_aperture_settings(pipe_ctx->plane_res.hubp, &apt);
 843	}
 844	//DC_LOG_DEBUG("%s: dpp_inst(%d) =\n", __func__, dpp->inst);
 845
 846	if (!pipe_ctx->top_pipe
 847		&& pipe_ctx->plane_state
 848		&& pipe_ctx->plane_state->flip_int_enabled
 849		&& pipe_ctx->plane_res.hubp->funcs->hubp_set_flip_int)
 850		pipe_ctx->plane_res.hubp->funcs->hubp_set_flip_int(pipe_ctx->plane_res.hubp);
 851}
 852
 853/* disable HW used by plane.
 854 * note:  cannot disable until disconnect is complete
 855 */
 856void dcn35_plane_atomic_disable(struct dc *dc, struct pipe_ctx *pipe_ctx)
 857{
 858	struct hubp *hubp = pipe_ctx->plane_res.hubp;
 859	struct dpp *dpp = pipe_ctx->plane_res.dpp;
 860
 861
 862	dc->hwss.wait_for_mpcc_disconnect(dc, dc->res_pool, pipe_ctx);
 863
 864	/* In flip immediate with pipe splitting case GSL is used for
 865	 * synchronization so we must disable it when the plane is disabled.
 866	 */
 867	if (pipe_ctx->stream_res.gsl_group != 0)
 868		dcn20_setup_gsl_group_as_lock(dc, pipe_ctx, false);
 869/*
 870	if (hubp->funcs->hubp_update_mall_sel)
 871		hubp->funcs->hubp_update_mall_sel(hubp, 0, false);
 872*/
 873	dc->hwss.set_flip_control_gsl(pipe_ctx, false);
 874
 875	hubp->funcs->hubp_clk_cntl(hubp, false);
 876
 877	dpp->funcs->dpp_dppclk_control(dpp, false, false);
 878
 879	hubp->power_gated = true;
 880
 881	hubp->funcs->hubp_reset(hubp);
 882	dpp->funcs->dpp_reset(dpp);
 883
 884	pipe_ctx->stream = NULL;
 885	memset(&pipe_ctx->stream_res, 0, sizeof(pipe_ctx->stream_res));
 886	memset(&pipe_ctx->plane_res, 0, sizeof(pipe_ctx->plane_res));
 887	pipe_ctx->top_pipe = NULL;
 888	pipe_ctx->bottom_pipe = NULL;
 889	pipe_ctx->plane_state = NULL;
 890	//DC_LOG_DEBUG("%s: dpp_inst(%d)=\n", __func__, dpp->inst);
 891
 892}
 893
 894void dcn35_disable_plane(struct dc *dc, struct dc_state *state, struct pipe_ctx *pipe_ctx)
 895{
 896	struct dce_hwseq *hws = dc->hwseq;
 897	bool is_phantom = dc_state_get_pipe_subvp_type(state, pipe_ctx) == SUBVP_PHANTOM;
 898	struct timing_generator *tg = is_phantom ? pipe_ctx->stream_res.tg : NULL;
 899
 900	DC_LOGGER_INIT(dc->ctx->logger);
 901
 902	if (!pipe_ctx->plane_res.hubp || pipe_ctx->plane_res.hubp->power_gated)
 903		return;
 904
 905	if (hws->funcs.plane_atomic_disable)
 906		hws->funcs.plane_atomic_disable(dc, pipe_ctx);
 907
 908	/* Turn back off the phantom OTG after the phantom plane is fully disabled
 909	 */
 910	if (is_phantom)
 911		if (tg && tg->funcs->disable_phantom_crtc)
 912			tg->funcs->disable_phantom_crtc(tg);
 913
 914	DC_LOG_DC("Power down front end %d\n",
 915					pipe_ctx->pipe_idx);
 916}
 917
 918void dcn35_calc_blocks_to_gate(struct dc *dc, struct dc_state *context,
 919	struct pg_block_update *update_state)
 920{
 921	bool hpo_frl_stream_enc_acquired = false;
 922	bool hpo_dp_stream_enc_acquired = false;
 923	int i = 0, j = 0;
 924	int edp_num = 0;
 925	struct dc_link *edp_links[MAX_NUM_EDP] = { NULL };
 926
 927	memset(update_state, 0, sizeof(struct pg_block_update));
 928
 929	for (i = 0; i < dc->res_pool->hpo_dp_stream_enc_count; i++) {
 930		if (context->res_ctx.is_hpo_dp_stream_enc_acquired[i] &&
 931				dc->res_pool->hpo_dp_stream_enc[i]) {
 932			hpo_dp_stream_enc_acquired = true;
 933			break;
 934		}
 935	}
 936
 937	if (!hpo_frl_stream_enc_acquired && !hpo_dp_stream_enc_acquired)
 938		update_state->pg_res_update[PG_HPO] = true;
 939
 940	update_state->pg_res_update[PG_DWB] = true;
 941
 942	for (i = 0; i < dc->res_pool->pipe_count; i++) {
 943		struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[i];
 944
 945		for (j = 0; j < PG_HW_PIPE_RESOURCES_NUM_ELEMENT; j++)
 946			update_state->pg_pipe_res_update[j][i] = true;
 947
 948		if (!pipe_ctx)
 949			continue;
 950
 951		if (pipe_ctx->plane_res.hubp)
 952			update_state->pg_pipe_res_update[PG_HUBP][pipe_ctx->plane_res.hubp->inst] = false;
 953
 954		if (pipe_ctx->plane_res.dpp && pipe_ctx->plane_res.hubp)
 955			update_state->pg_pipe_res_update[PG_DPP][pipe_ctx->plane_res.hubp->inst] = false;
 956
 957		if (pipe_ctx->plane_res.dpp || pipe_ctx->stream_res.opp)
 958			update_state->pg_pipe_res_update[PG_MPCC][pipe_ctx->plane_res.mpcc_inst] = false;
 959
 960		if (pipe_ctx->stream_res.dsc) {
 961			update_state->pg_pipe_res_update[PG_DSC][pipe_ctx->stream_res.dsc->inst] = false;
 962			if (dc->caps.sequential_ono) {
 963				update_state->pg_pipe_res_update[PG_HUBP][pipe_ctx->stream_res.dsc->inst] = false;
 964				update_state->pg_pipe_res_update[PG_DPP][pipe_ctx->stream_res.dsc->inst] = false;
 965
 966				/* All HUBP/DPP instances must be powered if the DSC inst != HUBP inst */
 967				if (!pipe_ctx->top_pipe && pipe_ctx->plane_res.hubp &&
 968				    pipe_ctx->plane_res.hubp->inst != pipe_ctx->stream_res.dsc->inst) {
 969					for (j = 0; j < dc->res_pool->pipe_count; ++j) {
 970						update_state->pg_pipe_res_update[PG_HUBP][j] = false;
 971						update_state->pg_pipe_res_update[PG_DPP][j] = false;
 972					}
 973				}
 974			}
 975		}
 976
 977		if (pipe_ctx->stream_res.opp)
 978			update_state->pg_pipe_res_update[PG_OPP][pipe_ctx->stream_res.opp->inst] = false;
 979
 980		if (pipe_ctx->stream_res.hpo_dp_stream_enc)
 981			update_state->pg_pipe_res_update[PG_DPSTREAM][pipe_ctx->stream_res.hpo_dp_stream_enc->inst] = false;
 982	}
 983
 984	for (i = 0; i < dc->link_count; i++) {
 985		update_state->pg_pipe_res_update[PG_PHYSYMCLK][dc->links[i]->link_enc_hw_inst] = true;
 986		if (dc->links[i]->type != dc_connection_none)
 987			update_state->pg_pipe_res_update[PG_PHYSYMCLK][dc->links[i]->link_enc_hw_inst] = false;
 988	}
 989
 990	/*domain24 controls all the otg, mpc, opp, as long as one otg is still up, avoid enabling OTG PG*/
 991	for (i = 0; i < dc->res_pool->timing_generator_count; i++) {
 992		struct timing_generator *tg = dc->res_pool->timing_generators[i];
 993		if (tg && tg->funcs->is_tg_enabled(tg)) {
 994			update_state->pg_pipe_res_update[PG_OPTC][i] = false;
 995			break;
 996		}
 997	}
 998
 999	dc_get_edp_links(dc, edp_links, &edp_num);
1000	if (edp_num == 0 ||
1001		((!edp_links[0] || !edp_links[0]->edp_sink_present) &&
1002			(!edp_links[1] || !edp_links[1]->edp_sink_present))) {
1003		/*eDP not exist on this config, keep Domain24 power on, for S0i3, this will be handled in dmubfw*/
1004		update_state->pg_pipe_res_update[PG_OPTC][0] = false;
1005	}
1006
1007	if (dc->caps.sequential_ono) {
1008		for (i = dc->res_pool->pipe_count - 1; i >= 0; i--) {
1009			if (!update_state->pg_pipe_res_update[PG_HUBP][i] &&
1010			    !update_state->pg_pipe_res_update[PG_DPP][i]) {
1011				for (j = i - 1; j >= 0; j--) {
1012					update_state->pg_pipe_res_update[PG_HUBP][j] = false;
1013					update_state->pg_pipe_res_update[PG_DPP][j] = false;
1014				}
1015
1016				break;
1017			}
1018		}
1019	}
1020}
1021
1022void dcn35_calc_blocks_to_ungate(struct dc *dc, struct dc_state *context,
1023	struct pg_block_update *update_state)
1024{
1025	bool hpo_frl_stream_enc_acquired = false;
1026	bool hpo_dp_stream_enc_acquired = false;
1027	int i = 0, j = 0;
1028
1029	memset(update_state, 0, sizeof(struct pg_block_update));
1030
1031	for (i = 0; i < dc->res_pool->pipe_count; i++) {
1032		struct pipe_ctx *cur_pipe = &dc->current_state->res_ctx.pipe_ctx[i];
1033		struct pipe_ctx *new_pipe = &context->res_ctx.pipe_ctx[i];
1034
1035		if (cur_pipe == NULL || new_pipe == NULL)
1036			continue;
1037
1038		if ((!cur_pipe->plane_state && new_pipe->plane_state) ||
1039			(!cur_pipe->stream && new_pipe->stream) ||
1040			(cur_pipe->stream != new_pipe->stream && new_pipe->stream)) {
1041			// New pipe addition
1042			for (j = 0; j < PG_HW_PIPE_RESOURCES_NUM_ELEMENT; j++) {
1043				if (j == PG_HUBP && new_pipe->plane_res.hubp)
1044					update_state->pg_pipe_res_update[j][new_pipe->plane_res.hubp->inst] = true;
1045
1046				if (j == PG_DPP && new_pipe->plane_res.dpp)
1047					update_state->pg_pipe_res_update[j][new_pipe->plane_res.dpp->inst] = true;
1048
1049				if (j == PG_MPCC && new_pipe->plane_res.dpp)
1050					update_state->pg_pipe_res_update[j][new_pipe->plane_res.mpcc_inst] = true;
1051
1052				if (j == PG_DSC && new_pipe->stream_res.dsc)
1053					update_state->pg_pipe_res_update[j][new_pipe->stream_res.dsc->inst] = true;
1054
1055				if (j == PG_OPP && new_pipe->stream_res.opp)
1056					update_state->pg_pipe_res_update[j][new_pipe->stream_res.opp->inst] = true;
1057
1058				if (j == PG_OPTC && new_pipe->stream_res.tg)
1059					update_state->pg_pipe_res_update[j][new_pipe->stream_res.tg->inst] = true;
1060
1061				if (j == PG_DPSTREAM && new_pipe->stream_res.hpo_dp_stream_enc)
1062					update_state->pg_pipe_res_update[j][new_pipe->stream_res.hpo_dp_stream_enc->inst] = true;
1063			}
1064		} else if (cur_pipe->plane_state == new_pipe->plane_state ||
1065				cur_pipe == new_pipe) {
1066			//unchanged pipes
1067			for (j = 0; j < PG_HW_PIPE_RESOURCES_NUM_ELEMENT; j++) {
1068				if (j == PG_HUBP &&
1069					cur_pipe->plane_res.hubp != new_pipe->plane_res.hubp &&
1070					new_pipe->plane_res.hubp)
1071					update_state->pg_pipe_res_update[j][new_pipe->plane_res.hubp->inst] = true;
1072
1073				if (j == PG_DPP &&
1074					cur_pipe->plane_res.dpp != new_pipe->plane_res.dpp &&
1075					new_pipe->plane_res.dpp)
1076					update_state->pg_pipe_res_update[j][new_pipe->plane_res.dpp->inst] = true;
1077
1078				if (j == PG_OPP &&
1079					cur_pipe->stream_res.opp != new_pipe->stream_res.opp &&
1080					new_pipe->stream_res.opp)
1081					update_state->pg_pipe_res_update[j][new_pipe->stream_res.opp->inst] = true;
1082
1083				if (j == PG_DSC &&
1084					cur_pipe->stream_res.dsc != new_pipe->stream_res.dsc &&
1085					new_pipe->stream_res.dsc)
1086					update_state->pg_pipe_res_update[j][new_pipe->stream_res.dsc->inst] = true;
1087
1088				if (j == PG_OPTC &&
1089					cur_pipe->stream_res.tg != new_pipe->stream_res.tg &&
1090					new_pipe->stream_res.tg)
1091					update_state->pg_pipe_res_update[j][new_pipe->stream_res.tg->inst] = true;
1092
1093				if (j == PG_DPSTREAM &&
1094					cur_pipe->stream_res.hpo_dp_stream_enc != new_pipe->stream_res.hpo_dp_stream_enc &&
1095					new_pipe->stream_res.hpo_dp_stream_enc)
1096					update_state->pg_pipe_res_update[j][new_pipe->stream_res.hpo_dp_stream_enc->inst] = true;
1097			}
1098		}
1099	}
1100
1101	for (i = 0; i < dc->link_count; i++)
1102		if (dc->links[i]->type != dc_connection_none)
1103			update_state->pg_pipe_res_update[PG_PHYSYMCLK][dc->links[i]->link_enc_hw_inst] = true;
1104
1105	for (i = 0; i < dc->res_pool->hpo_dp_stream_enc_count; i++) {
1106		if (context->res_ctx.is_hpo_dp_stream_enc_acquired[i] &&
1107				dc->res_pool->hpo_dp_stream_enc[i]) {
1108			hpo_dp_stream_enc_acquired = true;
1109			break;
1110		}
1111	}
1112
1113	if (hpo_frl_stream_enc_acquired || hpo_dp_stream_enc_acquired)
1114		update_state->pg_res_update[PG_HPO] = true;
1115
1116	if (hpo_frl_stream_enc_acquired)
1117		update_state->pg_pipe_res_update[PG_HDMISTREAM][0] = true;
1118
1119	if (dc->caps.sequential_ono) {
1120		for (i = 0; i < dc->res_pool->pipe_count; i++) {
1121			struct pipe_ctx *new_pipe = &context->res_ctx.pipe_ctx[i];
1122
1123			if (new_pipe->stream_res.dsc && !new_pipe->top_pipe &&
1124			    update_state->pg_pipe_res_update[PG_DSC][new_pipe->stream_res.dsc->inst]) {
1125				update_state->pg_pipe_res_update[PG_HUBP][new_pipe->stream_res.dsc->inst] = true;
1126				update_state->pg_pipe_res_update[PG_DPP][new_pipe->stream_res.dsc->inst] = true;
1127
1128				/* All HUBP/DPP instances must be powered if the DSC inst != HUBP inst */
1129				if (new_pipe->plane_res.hubp &&
1130				    new_pipe->plane_res.hubp->inst != new_pipe->stream_res.dsc->inst) {
1131					for (j = 0; j < dc->res_pool->pipe_count; ++j) {
1132						update_state->pg_pipe_res_update[PG_HUBP][j] = true;
1133						update_state->pg_pipe_res_update[PG_DPP][j] = true;
1134					}
1135				}
1136			}
1137		}
1138
1139		for (i = dc->res_pool->pipe_count - 1; i >= 0; i--) {
1140			if (update_state->pg_pipe_res_update[PG_HUBP][i] &&
1141			    update_state->pg_pipe_res_update[PG_DPP][i]) {
1142				for (j = i - 1; j >= 0; j--) {
1143					update_state->pg_pipe_res_update[PG_HUBP][j] = true;
1144					update_state->pg_pipe_res_update[PG_DPP][j] = true;
1145				}
1146
1147				break;
1148			}
1149		}
1150	}
1151}
1152
1153/**
1154 * dcn35_hw_block_power_down() - power down sequence
1155 *
1156 * The following sequence describes the ON-OFF (ONO) for power down:
1157 *
1158 *	ONO Region 3, DCPG 25: hpo - SKIPPED
1159 *	ONO Region 4, DCPG 0: dchubp0, dpp0
1160 *	ONO Region 6, DCPG 1: dchubp1, dpp1
1161 *	ONO Region 8, DCPG 2: dchubp2, dpp2
1162 *	ONO Region 10, DCPG 3: dchubp3, dpp3
1163 *	ONO Region 1, DCPG 23: dchubbub dchvm dchubbubmem - SKIPPED. PMFW will pwr dwn at IPS2 entry
1164 *	ONO Region 5, DCPG 16: dsc0
1165 *	ONO Region 7, DCPG 17: dsc1
1166 *	ONO Region 9, DCPG 18: dsc2
1167 *	ONO Region 11, DCPG 19: dsc3
1168 *	ONO Region 2, DCPG 24: mpc opp optc dwb
1169 *	ONO Region 0, DCPG 22: dccg dio dcio - SKIPPED. will be pwr dwn after lono timer is armed
1170 *
1171 * If sequential ONO is specified the order is modified from ONO Region 11 -> ONO Region 0 descending.
1172 *
1173 * @dc: Current DC state
1174 * @update_state: update PG sequence states for HW block
1175 */
1176void dcn35_hw_block_power_down(struct dc *dc,
1177	struct pg_block_update *update_state)
1178{
1179	int i = 0;
1180	struct pg_cntl *pg_cntl = dc->res_pool->pg_cntl;
1181
1182	if (!pg_cntl)
1183		return;
1184	if (dc->debug.ignore_pg)
1185		return;
1186
1187	if (update_state->pg_res_update[PG_HPO]) {
1188		if (pg_cntl->funcs->hpo_pg_control)
1189			pg_cntl->funcs->hpo_pg_control(pg_cntl, false);
1190	}
1191
1192	if (!dc->caps.sequential_ono) {
1193		for (i = 0; i < dc->res_pool->pipe_count; i++) {
1194			if (update_state->pg_pipe_res_update[PG_HUBP][i] &&
1195			    update_state->pg_pipe_res_update[PG_DPP][i]) {
1196				if (pg_cntl->funcs->hubp_dpp_pg_control)
1197					pg_cntl->funcs->hubp_dpp_pg_control(pg_cntl, i, false);
1198			}
1199		}
1200
1201		for (i = 0; i < dc->res_pool->res_cap->num_dsc; i++) {
1202			if (update_state->pg_pipe_res_update[PG_DSC][i]) {
1203				if (pg_cntl->funcs->dsc_pg_control)
1204					pg_cntl->funcs->dsc_pg_control(pg_cntl, i, false);
1205			}
1206		}
1207	} else {
1208		for (i = dc->res_pool->pipe_count - 1; i >= 0; i--) {
1209			if (update_state->pg_pipe_res_update[PG_DSC][i]) {
1210				if (pg_cntl->funcs->dsc_pg_control)
1211					pg_cntl->funcs->dsc_pg_control(pg_cntl, i, false);
1212			}
1213
1214			if (update_state->pg_pipe_res_update[PG_HUBP][i] &&
1215			    update_state->pg_pipe_res_update[PG_DPP][i]) {
1216				if (pg_cntl->funcs->hubp_dpp_pg_control)
1217					pg_cntl->funcs->hubp_dpp_pg_control(pg_cntl, i, false);
1218			}
1219		}
1220	}
1221
1222	/*this will need all the clients to unregister optc interruts let dmubfw handle this*/
1223	if (pg_cntl->funcs->plane_otg_pg_control)
1224		pg_cntl->funcs->plane_otg_pg_control(pg_cntl, false);
1225
1226	//domain22, 23, 25 currently always on.
1227
1228}
1229
1230/**
1231 * dcn35_hw_block_power_up() - power up sequence
1232 *
1233 * The following sequence describes the ON-OFF (ONO) for power up:
1234 *
1235 *	ONO Region 0, DCPG 22: dccg dio dcio - SKIPPED
1236 *	ONO Region 2, DCPG 24: mpc opp optc dwb
1237 *	ONO Region 5, DCPG 16: dsc0
1238 *	ONO Region 7, DCPG 17: dsc1
1239 *	ONO Region 9, DCPG 18: dsc2
1240 *	ONO Region 11, DCPG 19: dsc3
1241 *	ONO Region 1, DCPG 23: dchubbub dchvm dchubbubmem - SKIPPED. PMFW will power up at IPS2 exit
1242 *	ONO Region 4, DCPG 0: dchubp0, dpp0
1243 *	ONO Region 6, DCPG 1: dchubp1, dpp1
1244 *	ONO Region 8, DCPG 2: dchubp2, dpp2
1245 *	ONO Region 10, DCPG 3: dchubp3, dpp3
1246 *	ONO Region 3, DCPG 25: hpo - SKIPPED
1247 *
1248 * If sequential ONO is specified the order is modified from ONO Region 0 -> ONO Region 11 ascending.
1249 *
1250 * @dc: Current DC state
1251 * @update_state: update PG sequence states for HW block
1252 */
1253void dcn35_hw_block_power_up(struct dc *dc,
1254	struct pg_block_update *update_state)
1255{
1256	int i = 0;
1257	struct pg_cntl *pg_cntl = dc->res_pool->pg_cntl;
1258
1259	if (!pg_cntl)
1260		return;
1261	if (dc->debug.ignore_pg)
1262		return;
1263	//domain22, 23, 25 currently always on.
1264	/*this will need all the clients to unregister optc interruts let dmubfw handle this*/
1265	if (pg_cntl->funcs->plane_otg_pg_control)
1266		pg_cntl->funcs->plane_otg_pg_control(pg_cntl, true);
1267
1268	if (!dc->caps.sequential_ono) {
1269		for (i = 0; i < dc->res_pool->res_cap->num_dsc; i++)
1270			if (update_state->pg_pipe_res_update[PG_DSC][i]) {
1271				if (pg_cntl->funcs->dsc_pg_control)
1272					pg_cntl->funcs->dsc_pg_control(pg_cntl, i, true);
1273			}
1274	}
1275
1276	for (i = 0; i < dc->res_pool->pipe_count; i++) {
1277		if (update_state->pg_pipe_res_update[PG_HUBP][i] &&
1278			update_state->pg_pipe_res_update[PG_DPP][i]) {
1279			if (pg_cntl->funcs->hubp_dpp_pg_control)
1280				pg_cntl->funcs->hubp_dpp_pg_control(pg_cntl, i, true);
1281		}
1282
1283		if (dc->caps.sequential_ono) {
1284			if (update_state->pg_pipe_res_update[PG_DSC][i]) {
1285				if (pg_cntl->funcs->dsc_pg_control)
1286					pg_cntl->funcs->dsc_pg_control(pg_cntl, i, true);
1287			}
1288		}
1289	}
1290	if (update_state->pg_res_update[PG_HPO]) {
1291		if (pg_cntl->funcs->hpo_pg_control)
1292			pg_cntl->funcs->hpo_pg_control(pg_cntl, true);
1293	}
1294}
1295void dcn35_root_clock_control(struct dc *dc,
1296	struct pg_block_update *update_state, bool power_on)
1297{
1298	int i = 0;
1299	struct pg_cntl *pg_cntl = dc->res_pool->pg_cntl;
1300
1301	if (!pg_cntl)
1302		return;
1303	/*enable root clock first when power up*/
1304	if (power_on) {
1305		for (i = 0; i < dc->res_pool->pipe_count; i++) {
1306			if (update_state->pg_pipe_res_update[PG_HUBP][i] &&
1307				update_state->pg_pipe_res_update[PG_DPP][i]) {
1308				if (dc->hwseq->funcs.dpp_root_clock_control)
1309					dc->hwseq->funcs.dpp_root_clock_control(dc->hwseq, i, power_on);
1310			}
1311			if (update_state->pg_pipe_res_update[PG_DPSTREAM][i])
1312				if (dc->hwseq->funcs.dpstream_root_clock_control)
1313					dc->hwseq->funcs.dpstream_root_clock_control(dc->hwseq, i, power_on);
1314		}
1315
1316		for (i = 0; i < dc->res_pool->dig_link_enc_count; i++)
1317			if (update_state->pg_pipe_res_update[PG_PHYSYMCLK][i])
1318				if (dc->hwseq->funcs.physymclk_root_clock_control)
1319					dc->hwseq->funcs.physymclk_root_clock_control(dc->hwseq, i, power_on);
1320
1321	}
1322	for (i = 0; i < dc->res_pool->res_cap->num_dsc; i++) {
1323		if (update_state->pg_pipe_res_update[PG_DSC][i]) {
1324			if (power_on) {
1325				if (dc->res_pool->dccg->funcs->enable_dsc)
1326					dc->res_pool->dccg->funcs->enable_dsc(dc->res_pool->dccg, i);
1327			} else {
1328				if (dc->res_pool->dccg->funcs->disable_dsc)
1329					dc->res_pool->dccg->funcs->disable_dsc(dc->res_pool->dccg, i);
1330			}
1331		}
1332	}
1333	/*disable root clock first when power down*/
1334	if (!power_on) {
1335		for (i = 0; i < dc->res_pool->pipe_count; i++) {
1336			if (update_state->pg_pipe_res_update[PG_HUBP][i] &&
1337				update_state->pg_pipe_res_update[PG_DPP][i]) {
1338				if (dc->hwseq->funcs.dpp_root_clock_control)
1339					dc->hwseq->funcs.dpp_root_clock_control(dc->hwseq, i, power_on);
1340			}
1341			if (update_state->pg_pipe_res_update[PG_DPSTREAM][i])
1342				if (dc->hwseq->funcs.dpstream_root_clock_control)
1343					dc->hwseq->funcs.dpstream_root_clock_control(dc->hwseq, i, power_on);
1344		}
1345
1346		for (i = 0; i < dc->res_pool->dig_link_enc_count; i++)
1347			if (update_state->pg_pipe_res_update[PG_PHYSYMCLK][i])
1348				if (dc->hwseq->funcs.physymclk_root_clock_control)
1349					dc->hwseq->funcs.physymclk_root_clock_control(dc->hwseq, i, power_on);
1350
1351	}
1352}
1353
1354void dcn35_prepare_bandwidth(
1355		struct dc *dc,
1356		struct dc_state *context)
1357{
1358	struct pg_block_update pg_update_state;
1359
1360	if (dc->hwss.calc_blocks_to_ungate) {
1361		dc->hwss.calc_blocks_to_ungate(dc, context, &pg_update_state);
1362
1363		if (dc->hwss.root_clock_control)
1364			dc->hwss.root_clock_control(dc, &pg_update_state, true);
1365		/*power up required HW block*/
1366		if (dc->hwss.hw_block_power_up)
1367			dc->hwss.hw_block_power_up(dc, &pg_update_state);
1368	}
1369
1370	dcn20_prepare_bandwidth(dc, context);
1371
1372	print_pg_status(dc, __func__, ": after rcg and power up");
1373}
1374
1375void dcn35_optimize_bandwidth(
1376		struct dc *dc,
1377		struct dc_state *context)
1378{
1379	struct pg_block_update pg_update_state;
1380
1381	print_pg_status(dc, __func__, ": before rcg and power up");
1382
1383	dcn20_optimize_bandwidth(dc, context);
1384
1385	if (dc->hwss.calc_blocks_to_gate) {
1386		dc->hwss.calc_blocks_to_gate(dc, context, &pg_update_state);
1387		/*try to power down unused block*/
1388		if (dc->hwss.hw_block_power_down)
1389			dc->hwss.hw_block_power_down(dc, &pg_update_state);
1390
1391		if (dc->hwss.root_clock_control)
1392			dc->hwss.root_clock_control(dc, &pg_update_state, false);
1393	}
1394
1395	print_pg_status(dc, __func__, ": after rcg and power up");
1396}
1397
1398void dcn35_set_drr(struct pipe_ctx **pipe_ctx,
1399		int num_pipes, struct dc_crtc_timing_adjust adjust)
1400{
1401	int i = 0;
1402	struct drr_params params = {0};
1403	// DRR set trigger event mapped to OTG_TRIG_A
1404	unsigned int event_triggers = 0x2;//Bit[1]: OTG_TRIG_A
1405	// Note DRR trigger events are generated regardless of whether num frames met.
1406	unsigned int num_frames = 2;
1407
1408	params.vertical_total_max = adjust.v_total_max;
1409	params.vertical_total_min = adjust.v_total_min;
1410	params.vertical_total_mid = adjust.v_total_mid;
1411	params.vertical_total_mid_frame_num = adjust.v_total_mid_frame_num;
1412
1413	for (i = 0; i < num_pipes; i++) {
1414		/* dc_state_destruct() might null the stream resources, so fetch tg
1415		 * here first to avoid a race condition. The lifetime of the pointee
1416		 * itself (the timing_generator object) is not a problem here.
1417		 */
1418		struct timing_generator *tg = pipe_ctx[i]->stream_res.tg;
1419
1420		if ((tg != NULL) && tg->funcs) {
1421			if (pipe_ctx[i]->stream && pipe_ctx[i]->stream->ctx->dc->debug.static_screen_wait_frames) {
1422				struct dc_crtc_timing *timing = &pipe_ctx[i]->stream->timing;
1423				struct dc *dc = pipe_ctx[i]->stream->ctx->dc;
1424				unsigned int frame_rate = timing->pix_clk_100hz / (timing->h_total * timing->v_total);
1425
1426				if (frame_rate >= 120 && dc->caps.ips_support &&
1427					dc->config.disable_ips != DMUB_IPS_DISABLE_ALL) {
1428					/*ips enable case*/
1429					num_frames = 2 * (frame_rate % 60);
1430				}
1431			}
1432			set_drr_and_clear_adjust_pending(pipe_ctx[i], pipe_ctx[i]->stream, &params);
1433			if (adjust.v_total_max != 0 && adjust.v_total_min != 0)
1434				if (tg->funcs->set_static_screen_control)
1435					tg->funcs->set_static_screen_control(
1436						tg, event_triggers, num_frames);
1437		}
1438	}
1439}
1440void dcn35_set_static_screen_control(struct pipe_ctx **pipe_ctx,
1441		int num_pipes, const struct dc_static_screen_params *params)
1442{
1443	unsigned int i;
1444	unsigned int triggers = 0;
1445
1446	if (params->triggers.surface_update)
1447		triggers |= 0x200;/*bit 9  : 10 0000 0000*/
1448	if (params->triggers.cursor_update)
1449		triggers |= 0x8;/*bit3*/
1450	if (params->triggers.force_trigger)
1451		triggers |= 0x1;
1452	for (i = 0; i < num_pipes; i++)
1453		pipe_ctx[i]->stream_res.tg->funcs->
1454			set_static_screen_control(pipe_ctx[i]->stream_res.tg,
1455					triggers, params->num_frames);
1456}
1457
1458void dcn35_set_long_vblank(struct pipe_ctx **pipe_ctx,
1459		int num_pipes, uint32_t v_total_min, uint32_t v_total_max)
1460{
1461	int i = 0;
1462	struct long_vtotal_params params = {0};
1463
1464	params.vertical_total_max = v_total_max;
1465	params.vertical_total_min = v_total_min;
1466
1467	for (i = 0; i < num_pipes; i++) {
1468		if (!pipe_ctx[i])
1469			continue;
1470
1471		if (pipe_ctx[i]->stream) {
1472			struct dc_crtc_timing *timing = &pipe_ctx[i]->stream->timing;
1473
1474			if (timing)
1475				params.vertical_blank_start = timing->v_total - timing->v_front_porch;
1476			else
1477				params.vertical_blank_start = 0;
1478
1479			if ((pipe_ctx[i]->stream_res.tg != NULL) && pipe_ctx[i]->stream_res.tg->funcs &&
1480				pipe_ctx[i]->stream_res.tg->funcs->set_long_vtotal)
1481				pipe_ctx[i]->stream_res.tg->funcs->set_long_vtotal(pipe_ctx[i]->stream_res.tg, &params);
1482		}
1483	}
1484}
1485
1486static bool should_avoid_empty_tu(struct pipe_ctx *pipe_ctx)
1487{
1488	/* Calculate average pixel count per TU, return false if under ~2.00 to
1489	 * avoid empty TUs. This is only required for DPIA tunneling as empty TUs
1490	 * are legal to generate for native DP links. Assume TU size 64 as there
1491	 * is currently no scenario where it's reprogrammed from HW default.
1492	 * MTPs have no such limitation, so this does not affect MST use cases.
1493	 */
1494	unsigned int pix_clk_mhz;
1495	unsigned int symclk_mhz;
1496	unsigned int avg_pix_per_tu_x1000;
1497	unsigned int tu_size_bytes = 64;
1498	struct dc_crtc_timing *timing = &pipe_ctx->stream->timing;
1499	struct dc_link_settings *link_settings = &pipe_ctx->link_config.dp_link_settings;
1500	const struct dc *dc = pipe_ctx->stream->link->dc;
1501
1502	if (pipe_ctx->link_config.dp_tunnel_settings.should_enable_dp_tunneling == false)
1503		return false;
1504
1505	// Not necessary for MST configurations
1506	if (pipe_ctx->stream->signal == SIGNAL_TYPE_DISPLAY_PORT_MST)
1507		return false;
1508
1509	pix_clk_mhz = timing->pix_clk_100hz / 10000;
1510
1511	// If this is true, can't block due to dynamic ODM
1512	if (pix_clk_mhz > dc->clk_mgr->bw_params->clk_table.entries[0].dispclk_mhz)
1513		return false;
1514
1515	switch (link_settings->link_rate) {
1516	case LINK_RATE_LOW:
1517		symclk_mhz = 162;
1518		break;
1519	case LINK_RATE_HIGH:
1520		symclk_mhz = 270;
1521		break;
1522	case LINK_RATE_HIGH2:
1523		symclk_mhz = 540;
1524		break;
1525	case LINK_RATE_HIGH3:
1526		symclk_mhz = 810;
1527		break;
1528	default:
1529		// We shouldn't be tunneling any other rates, something is wrong
1530		ASSERT(0);
1531		return false;
1532	}
1533
1534	avg_pix_per_tu_x1000 = (1000 * pix_clk_mhz * tu_size_bytes)
1535		/ (symclk_mhz * link_settings->lane_count);
1536
1537	// Add small empirically-decided margin to account for potential jitter
1538	return (avg_pix_per_tu_x1000 < 2020);
1539}
1540
1541bool dcn35_is_dp_dig_pixel_rate_div_policy(struct pipe_ctx *pipe_ctx)
1542{
1543	struct dc *dc = pipe_ctx->stream->ctx->dc;
1544
1545	if (!is_h_timing_divisible_by_2(pipe_ctx->stream))
1546		return false;
1547
1548	if (should_avoid_empty_tu(pipe_ctx))
1549		return false;
1550
1551	if (dc_is_dp_signal(pipe_ctx->stream->signal) && !dc->link_srv->dp_is_128b_132b_signal(pipe_ctx) &&
1552		dc->debug.enable_dp_dig_pixel_rate_div_policy)
1553		return true;
1554
1555	return false;
1556}
1557
1558/*
1559 * Set powerup to true for every pipe to match pre-OS configuration.
1560 */
1561static void dcn35_calc_blocks_to_ungate_for_hw_release(struct dc *dc, struct pg_block_update *update_state)
1562{
1563	int i = 0, j = 0;
1564
1565	memset(update_state, 0, sizeof(struct pg_block_update));
1566
1567	for (i = 0; i < dc->res_pool->pipe_count; i++)
1568		for (j = 0; j < PG_HW_PIPE_RESOURCES_NUM_ELEMENT; j++)
1569			update_state->pg_pipe_res_update[j][i] = true;
1570
1571	update_state->pg_res_update[PG_HPO] = true;
1572	update_state->pg_res_update[PG_DWB] = true;
1573}
1574
1575/*
1576 * The purpose is to power up all gatings to restore optimization to pre-OS env.
1577 * Re-use hwss func and existing PG&RCG flags to decide powerup sequence.
1578 */
1579void dcn35_hardware_release(struct dc *dc)
1580{
1581	struct pg_block_update pg_update_state;
1582
1583	dcn35_calc_blocks_to_ungate_for_hw_release(dc, &pg_update_state);
1584
1585	if (dc->hwss.root_clock_control)
1586		dc->hwss.root_clock_control(dc, &pg_update_state, true);
1587	/*power up required HW block*/
1588	if (dc->hwss.hw_block_power_up)
1589		dc->hwss.hw_block_power_up(dc, &pg_update_state);
1590}
1591
1592void dcn35_abort_cursor_offload_update(struct dc *dc, const struct pipe_ctx *pipe)
1593{
1594	if (!dc_dmub_srv_is_cursor_offload_enabled(dc))
1595		return;
1596
1597	/*
1598	 * Insert a blank update to modify the write index and set pipe_mask to 0.
1599	 *
1600	 * While the DMU is interlocked with driver full pipe programming via
1601	 * the DMU HW lock, if the cursor update begins to execute after a full
1602	 * pipe programming occurs there are two possible issues:
1603	 *
1604	 * 1. Outdated cursor information is programmed, replacing the current update
1605	 * 2. The cursor update in firmware holds the cursor lock, preventing
1606	 *    the current update from being latched atomically in the same frame
1607	 *    as the rest of the update.
1608	 *
1609	 * This blank update, treated as a no-op, will allow the firmware to skip
1610	 * the programming.
1611	 */
1612
1613	if (dc->hwss.begin_cursor_offload_update)
1614		dc->hwss.begin_cursor_offload_update(dc, pipe);
1615
1616	if (dc->hwss.commit_cursor_offload_update)
1617		dc->hwss.commit_cursor_offload_update(dc, pipe);
1618}
1619
1620void dcn35_begin_cursor_offload_update(struct dc *dc, const struct pipe_ctx *pipe)
1621{
1622	volatile struct dmub_cursor_offload_v1 *cs = dc->ctx->dmub_srv->dmub->cursor_offload_v1;
1623	const struct pipe_ctx *top_pipe = resource_get_otg_master(pipe);
1624	uint32_t stream_idx, write_idx, payload_idx;
1625
1626	if (!top_pipe)
1627		return;
1628
1629	stream_idx = top_pipe->pipe_idx;
1630	write_idx = cs->offload_streams[stream_idx].write_idx + 1; /*  new payload (+1) */
1631	payload_idx = write_idx % ARRAY_SIZE(cs->offload_streams[stream_idx].payloads);
1632
1633	cs->offload_streams[stream_idx].payloads[payload_idx].write_idx_start = write_idx;
1634
1635	if (pipe->plane_res.hubp)
1636		pipe->plane_res.hubp->cursor_offload = true;
1637
1638	if (pipe->plane_res.dpp)
1639		pipe->plane_res.dpp->cursor_offload = true;
1640}
1641
1642void dcn35_commit_cursor_offload_update(struct dc *dc, const struct pipe_ctx *pipe)
1643{
1644	volatile struct dmub_cursor_offload_v1 *cs = dc->ctx->dmub_srv->dmub->cursor_offload_v1;
1645	volatile struct dmub_shared_state_cursor_offload_stream_v1 *shared_stream;
1646	const struct pipe_ctx *top_pipe = resource_get_otg_master(pipe);
1647	uint32_t stream_idx, write_idx, payload_idx;
1648
1649	if (pipe->plane_res.hubp)
1650		pipe->plane_res.hubp->cursor_offload = false;
1651
1652	if (pipe->plane_res.dpp)
1653		pipe->plane_res.dpp->cursor_offload = false;
1654
1655	if (!top_pipe)
1656		return;
1657
1658	stream_idx = top_pipe->pipe_idx;
1659	write_idx = cs->offload_streams[stream_idx].write_idx + 1; /*  new payload (+1) */
1660	payload_idx = write_idx % ARRAY_SIZE(cs->offload_streams[stream_idx].payloads);
1661
1662	shared_stream = &dc->ctx->dmub_srv->dmub->shared_state[DMUB_SHARED_STATE_FEATURE__CURSOR_OFFLOAD_V1]
1663				 .data.cursor_offload_v1.offload_streams[stream_idx];
1664
1665	shared_stream->last_write_idx = write_idx;
1666
1667	cs->offload_streams[stream_idx].write_idx = write_idx;
1668	cs->offload_streams[stream_idx].payloads[payload_idx].write_idx_finish = write_idx;
1669}
1670
1671void dcn35_update_cursor_offload_pipe(struct dc *dc, const struct pipe_ctx *pipe)
1672{
1673	volatile struct dmub_cursor_offload_v1 *cs = dc->ctx->dmub_srv->dmub->cursor_offload_v1;
1674	const struct pipe_ctx *top_pipe = resource_get_otg_master(pipe);
1675	const struct hubp *hubp = pipe->plane_res.hubp;
1676	const struct dpp *dpp = pipe->plane_res.dpp;
1677	volatile struct dmub_cursor_offload_pipe_data_dcn30_v1 *p;
1678	uint32_t stream_idx, write_idx, payload_idx;
1679
1680	if (!top_pipe || !hubp || !dpp)
1681		return;
1682
1683	stream_idx = top_pipe->pipe_idx;
1684	write_idx = cs->offload_streams[stream_idx].write_idx + 1; /*  new payload (+1) */
1685	payload_idx = write_idx % ARRAY_SIZE(cs->offload_streams[stream_idx].payloads);
1686
1687	p = &cs->offload_streams[stream_idx].payloads[payload_idx].pipe_data[pipe->pipe_idx].dcn30;
1688
1689	p->CURSOR0_0_CURSOR_SURFACE_ADDRESS = hubp->att.SURFACE_ADDR;
1690	p->CURSOR0_0_CURSOR_SURFACE_ADDRESS_HIGH = hubp->att.SURFACE_ADDR_HIGH;
1691	p->CURSOR0_0_CURSOR_SIZE__CURSOR_WIDTH = hubp->att.size.bits.width;
1692	p->CURSOR0_0_CURSOR_SIZE__CURSOR_HEIGHT = hubp->att.size.bits.height;
1693	p->CURSOR0_0_CURSOR_POSITION__CURSOR_X_POSITION = hubp->pos.position.bits.x_pos;
1694	p->CURSOR0_0_CURSOR_POSITION__CURSOR_Y_POSITION = hubp->pos.position.bits.y_pos;
1695	p->CURSOR0_0_CURSOR_HOT_SPOT__CURSOR_HOT_SPOT_X = hubp->pos.hot_spot.bits.x_hot;
1696	p->CURSOR0_0_CURSOR_HOT_SPOT__CURSOR_HOT_SPOT_Y = hubp->pos.hot_spot.bits.y_hot;
1697	p->CURSOR0_0_CURSOR_DST_OFFSET__CURSOR_DST_X_OFFSET = hubp->pos.dst_offset.bits.dst_x_offset;
1698	p->CURSOR0_0_CURSOR_CONTROL__CURSOR_ENABLE = hubp->pos.cur_ctl.bits.cur_enable;
1699	p->CURSOR0_0_CURSOR_CONTROL__CURSOR_MODE = hubp->att.cur_ctl.bits.mode;
1700	p->CURSOR0_0_CURSOR_CONTROL__CURSOR_2X_MAGNIFY = hubp->pos.cur_ctl.bits.cur_2x_magnify;
1701	p->CURSOR0_0_CURSOR_CONTROL__CURSOR_PITCH = hubp->att.cur_ctl.bits.pitch;
1702	p->CURSOR0_0_CURSOR_CONTROL__CURSOR_LINES_PER_CHUNK = hubp->att.cur_ctl.bits.line_per_chunk;
1703
1704	p->CNVC_CUR0_CURSOR0_CONTROL__CUR0_ENABLE = dpp->att.cur0_ctl.bits.cur0_enable;
1705	p->CNVC_CUR0_CURSOR0_CONTROL__CUR0_MODE = dpp->att.cur0_ctl.bits.mode;
1706	p->CNVC_CUR0_CURSOR0_CONTROL__CUR0_EXPANSION_MODE = dpp->att.cur0_ctl.bits.expansion_mode;
1707	p->CNVC_CUR0_CURSOR0_CONTROL__CUR0_ROM_EN = dpp->att.cur0_ctl.bits.cur0_rom_en;
1708	p->CNVC_CUR0_CURSOR0_COLOR0__CUR0_COLOR0 = 0x000000;
1709	p->CNVC_CUR0_CURSOR0_COLOR1__CUR0_COLOR1 = 0xFFFFFF;
1710	p->CNVC_CUR0_CURSOR0_FP_SCALE_BIAS__CUR0_FP_BIAS = dpp->att.fp_scale_bias.bits.fp_bias;
1711	p->CNVC_CUR0_CURSOR0_FP_SCALE_BIAS__CUR0_FP_SCALE = dpp->att.fp_scale_bias.bits.fp_scale;
1712
1713	p->HUBPREQ0_CURSOR_SETTINGS__CURSOR0_DST_Y_OFFSET = hubp->att.settings.bits.dst_y_offset;
1714	p->HUBPREQ0_CURSOR_SETTINGS__CURSOR0_CHUNK_HDL_ADJUST = hubp->att.settings.bits.chunk_hdl_adjust;
1715
1716	cs->offload_streams[stream_idx].payloads[payload_idx].pipe_mask |= (1u << pipe->pipe_idx);
1717}
1718
1719void dcn35_notify_cursor_offload_drr_update(struct dc *dc, struct dc_state *context,
1720					    const struct dc_stream_state *stream)
1721{
1722	dc_dmub_srv_control_cursor_offload(dc, context, stream, true);
1723}
1724
1725void dcn35_program_cursor_offload_now(struct dc *dc, const struct pipe_ctx *pipe)
1726{
1727	dc_dmub_srv_program_cursor_now(dc, pipe);
1728}
1729
1730static void disable_link_output_symclk_on_tx_off(struct dc_link *link, enum dp_link_encoding link_encoding)
1731{
1732	struct dc *dc = link->ctx->dc;
1733	struct pipe_ctx *pipe_ctx = NULL;
1734	uint8_t i;
1735
1736	for (i = 0; i < MAX_PIPES; i++) {
1737		pipe_ctx = &dc->current_state->res_ctx.pipe_ctx[i];
1738		if (pipe_ctx->stream && pipe_ctx->stream->link == link && pipe_ctx->top_pipe == NULL) {
1739			pipe_ctx->clock_source->funcs->program_pix_clk(
1740					pipe_ctx->clock_source,
1741					&pipe_ctx->stream_res.pix_clk_params,
1742					link_encoding,
1743					&pipe_ctx->pll_settings);
1744			break;
1745		}
1746	}
1747}
1748
1749void dcn35_disable_link_output(struct dc_link *link,
1750		const struct link_resource *link_res,
1751		enum signal_type signal)
1752{
1753	struct dc *dc = link->ctx->dc;
1754	const struct link_hwss *link_hwss = get_link_hwss(link, link_res);
1755	struct dmcu *dmcu = dc->res_pool->dmcu;
1756
1757	if (signal == SIGNAL_TYPE_EDP &&
1758			link->dc->hwss.edp_backlight_control &&
1759			!link->skip_implict_edp_power_control)
1760		link->dc->hwss.edp_backlight_control(link, false);
1761	else if (dmcu != NULL && dmcu->funcs->lock_phy)
1762		dmcu->funcs->lock_phy(dmcu);
1763
1764	if (dc_is_tmds_signal(signal) && link->phy_state.symclk_ref_cnts.otg > 0) {
1765		disable_link_output_symclk_on_tx_off(link, DP_UNKNOWN_ENCODING);
1766		link->phy_state.symclk_state = SYMCLK_ON_TX_OFF;
1767	} else {
1768		link_hwss->disable_link_output(link, link_res, signal);
1769		link->phy_state.symclk_state = SYMCLK_OFF_TX_OFF;
1770	}
1771	/*
1772	 * Add the logic to extract BOTH power up and power down sequences
1773	 * from enable/disable link output and only call edp panel control
1774	 * in enable_link_dp and disable_link_dp once.
1775	 */
1776	if (dmcu != NULL && dmcu->funcs->unlock_phy)
1777		dmcu->funcs->unlock_phy(dmcu);
1778
1779	dc->link_srv->dp_trace_source_sequence(link, DPCD_SOURCE_SEQ_AFTER_DISABLE_LINK_PHY);
1780}
~/ Read-only file preview.