1 /*
2  * Copyright 2016 Advanced Micro Devices, Inc.
3  *
4  * Permission is hereby granted, free of charge, to any person obtaining a
5  * copy of this software and associated documentation files (the "Software"),
6  * to deal in the Software without restriction, including without limitation
7  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8  * and/or sell copies of the Software, and to permit persons to whom the
9  * Software is furnished to do so, subject to the following conditions:
10  *
11  * The above copyright notice and this permission notice shall be included in
12  * all copies or substantial portions of the Software.
13  *
14  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
17  * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
18  * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
19  * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
20  * OTHER DEALINGS IN THE SOFTWARE.
21  *
22  * Authors: AMD
23  *
24  */
25 
26 #include <linux/delay.h>
27 #include "dm_services.h"
28 #include "core_types.h"
29 #include "resource.h"
30 #include "custom_float.h"
31 #include "dcn10_hw_sequencer.h"
32 #include "dce110/dce110_hw_sequencer.h"
33 #include "dce/dce_hwseq.h"
34 #include "abm.h"
35 #include "dmcu.h"
36 #include "dcn10_optc.h"
37 #include "dcn10/dcn10_dpp.h"
38 #include "dcn10/dcn10_mpc.h"
39 #include "timing_generator.h"
40 #include "opp.h"
41 #include "ipp.h"
42 #include "mpc.h"
43 #include "reg_helper.h"
44 #include "custom_float.h"
45 #include "dcn10_hubp.h"
46 #include "dcn10_hubbub.h"
47 #include "dcn10_cm_common.h"
48 
49 #define DC_LOGGER_INIT(logger)
50 
51 #define CTX \
52 	hws->ctx
53 #define REG(reg)\
54 	hws->regs->reg
55 
56 #undef FN
57 #define FN(reg_name, field_name) \
58 	hws->shifts->field_name, hws->masks->field_name
59 
60 /*print is 17 wide, first two characters are spaces*/
61 #define DTN_INFO_MICRO_SEC(ref_cycle) \
62 	print_microsec(dc_ctx, ref_cycle)
63 
64 static
65 void print_microsec(struct dc_context *dc_ctx, uint32_t ref_cycle)
66 {
67 	const uint32_t ref_clk_mhz = dc_ctx->dc->res_pool->ref_clock_inKhz / 1000;
68 	static const unsigned int frac = 1000;
69 	uint32_t us_x10 = (ref_cycle * frac) / ref_clk_mhz;
70 
71 	DTN_INFO("  %11d.%03d",
72 			us_x10 / frac,
73 			us_x10 % frac);
74 }
75 
76 
77 static void log_mpc_crc(struct dc *dc)
78 {
79 	struct dc_context *dc_ctx = dc->ctx;
80 	struct dce_hwseq *hws = dc->hwseq;
81 
82 	if (REG(MPC_CRC_RESULT_GB))
83 		DTN_INFO("MPC_CRC_RESULT_GB:%d MPC_CRC_RESULT_C:%d MPC_CRC_RESULT_AR:%d\n",
84 		REG_READ(MPC_CRC_RESULT_GB), REG_READ(MPC_CRC_RESULT_C), REG_READ(MPC_CRC_RESULT_AR));
85 	if (REG(DPP_TOP0_DPP_CRC_VAL_B_A))
86 		DTN_INFO("DPP_TOP0_DPP_CRC_VAL_B_A:%d DPP_TOP0_DPP_CRC_VAL_R_G:%d\n",
87 		REG_READ(DPP_TOP0_DPP_CRC_VAL_B_A), REG_READ(DPP_TOP0_DPP_CRC_VAL_R_G));
88 }
89 
90 static
91 void dcn10_log_hubbub_state(struct dc *dc)
92 {
93 	struct dc_context *dc_ctx = dc->ctx;
94 	struct dcn_hubbub_wm wm;
95 	int i;
96 
97 	hubbub1_wm_read_state(dc->res_pool->hubbub, &wm);
98 
99 	DTN_INFO("HUBBUB WM:      data_urgent  pte_meta_urgent"
100 			"         sr_enter          sr_exit  dram_clk_change\n");
101 
102 	for (i = 0; i < 4; i++) {
103 		struct dcn_hubbub_wm_set *s;
104 
105 		s = &wm.sets[i];
106 		DTN_INFO("WM_Set[%d]:", s->wm_set);
107 		DTN_INFO_MICRO_SEC(s->data_urgent);
108 		DTN_INFO_MICRO_SEC(s->pte_meta_urgent);
109 		DTN_INFO_MICRO_SEC(s->sr_enter);
110 		DTN_INFO_MICRO_SEC(s->sr_exit);
111 		DTN_INFO_MICRO_SEC(s->dram_clk_chanage);
112 		DTN_INFO("\n");
113 	}
114 
115 	DTN_INFO("\n");
116 }
117 
118 static void dcn10_log_hubp_states(struct dc *dc)
119 {
120 	struct dc_context *dc_ctx = dc->ctx;
121 	struct resource_pool *pool = dc->res_pool;
122 	int i;
123 
124 	DTN_INFO("HUBP:  format  addr_hi  width  height"
125 			"  rot  mir  sw_mode  dcc_en  blank_en  ttu_dis  underflow"
126 			"   min_ttu_vblank       qos_low_wm      qos_high_wm\n");
127 	for (i = 0; i < pool->pipe_count; i++) {
128 		struct hubp *hubp = pool->hubps[i];
129 		struct dcn_hubp_state *s = &(TO_DCN10_HUBP(hubp)->state);
130 
131 		hubp->funcs->hubp_read_state(hubp);
132 
133 		if (!s->blank_en) {
134 			DTN_INFO("[%2d]:  %5xh  %6xh  %5d  %6d  %2xh  %2xh  %6xh"
135 					"  %6d  %8d  %7d  %8xh",
136 					hubp->inst,
137 					s->pixel_format,
138 					s->inuse_addr_hi,
139 					s->viewport_width,
140 					s->viewport_height,
141 					s->rotation_angle,
142 					s->h_mirror_en,
143 					s->sw_mode,
144 					s->dcc_en,
145 					s->blank_en,
146 					s->ttu_disable,
147 					s->underflow_status);
148 			DTN_INFO_MICRO_SEC(s->min_ttu_vblank);
149 			DTN_INFO_MICRO_SEC(s->qos_level_low_wm);
150 			DTN_INFO_MICRO_SEC(s->qos_level_high_wm);
151 			DTN_INFO("\n");
152 		}
153 	}
154 
155 	DTN_INFO("\n=========RQ========\n");
156 	DTN_INFO("HUBP:  drq_exp_m  prq_exp_m  mrq_exp_m  crq_exp_m  plane1_ba  L:chunk_s  min_chu_s  meta_ch_s"
157 		"  min_m_c_s  dpte_gr_s  mpte_gr_s  swath_hei  pte_row_h  C:chunk_s  min_chu_s  meta_ch_s"
158 		"  min_m_c_s  dpte_gr_s  mpte_gr_s  swath_hei  pte_row_h\n");
159 	for (i = 0; i < pool->pipe_count; i++) {
160 		struct dcn_hubp_state *s = &(TO_DCN10_HUBP(pool->hubps[i])->state);
161 		struct _vcs_dpi_display_rq_regs_st *rq_regs = &s->rq_regs;
162 
163 		if (!s->blank_en)
164 			DTN_INFO("[%2d]:  %8xh  %8xh  %8xh  %8xh  %8xh  %8xh  %8xh  %8xh  %8xh  %8xh  %8xh  %8xh  %8xh  %8xh  %8xh  %8xh  %8xh  %8xh  %8xh  %8xh  %8xh\n",
165 				pool->hubps[i]->inst, rq_regs->drq_expansion_mode, rq_regs->prq_expansion_mode, rq_regs->mrq_expansion_mode,
166 				rq_regs->crq_expansion_mode, rq_regs->plane1_base_address, rq_regs->rq_regs_l.chunk_size,
167 				rq_regs->rq_regs_l.min_chunk_size, rq_regs->rq_regs_l.meta_chunk_size,
168 				rq_regs->rq_regs_l.min_meta_chunk_size, rq_regs->rq_regs_l.dpte_group_size,
169 				rq_regs->rq_regs_l.mpte_group_size, rq_regs->rq_regs_l.swath_height,
170 				rq_regs->rq_regs_l.pte_row_height_linear, rq_regs->rq_regs_c.chunk_size, rq_regs->rq_regs_c.min_chunk_size,
171 				rq_regs->rq_regs_c.meta_chunk_size, rq_regs->rq_regs_c.min_meta_chunk_size,
172 				rq_regs->rq_regs_c.dpte_group_size, rq_regs->rq_regs_c.mpte_group_size,
173 				rq_regs->rq_regs_c.swath_height, rq_regs->rq_regs_c.pte_row_height_linear);
174 	}
175 
176 	DTN_INFO("========DLG========\n");
177 	DTN_INFO("HUBP:  rc_hbe     dlg_vbe    min_d_y_n  rc_per_ht  rc_x_a_s "
178 			"  dst_y_a_s  dst_y_pf   dst_y_vvb  dst_y_rvb  dst_y_vfl  dst_y_rfl  rf_pix_fq"
179 			"  vratio_pf  vrat_pf_c  rc_pg_vbl  rc_pg_vbc  rc_mc_vbl  rc_mc_vbc  rc_pg_fll"
180 			"  rc_pg_flc  rc_mc_fll  rc_mc_flc  pr_nom_l   pr_nom_c   rc_pg_nl   rc_pg_nc "
181 			"  mr_nom_l   mr_nom_c   rc_mc_nl   rc_mc_nc   rc_ld_pl   rc_ld_pc   rc_ld_l  "
182 			"  rc_ld_c    cha_cur0   ofst_cur1  cha_cur1   vr_af_vc0  ddrq_limt  x_rt_dlay"
183 			"  x_rp_dlay  x_rr_sfl\n");
184 	for (i = 0; i < pool->pipe_count; i++) {
185 		struct dcn_hubp_state *s = &(TO_DCN10_HUBP(pool->hubps[i])->state);
186 		struct _vcs_dpi_display_dlg_regs_st *dlg_regs = &s->dlg_attr;
187 
188 		if (!s->blank_en)
189 			DTN_INFO("[%2d]:  %8xh  %8xh  %8xh  %8xh  %8xh  %8xh  %8xh  %8xh  %8xh  %8xh  %8xh  %8xh  %8xh"
190 				"%  8xh  %8xh  %8xh  %8xh  %8xh  %8xh  %8xh  %8xh  %8xh  %8xh  %8xh  %8xh  %8xh  %8xh"
191 				"  %8xh  %8xh  %8xh  %8xh  %8xh  %8xh  %8xh  %8xh  %8xh  %8xh  %8xh  %8xh  %8xh  %8xh  %8xh\n",
192 				pool->hubps[i]->inst, dlg_regs->refcyc_h_blank_end, dlg_regs->dlg_vblank_end, dlg_regs->min_dst_y_next_start,
193 				dlg_regs->refcyc_per_htotal, dlg_regs->refcyc_x_after_scaler, dlg_regs->dst_y_after_scaler,
194 				dlg_regs->dst_y_prefetch, dlg_regs->dst_y_per_vm_vblank, dlg_regs->dst_y_per_row_vblank,
195 				dlg_regs->dst_y_per_vm_flip, dlg_regs->dst_y_per_row_flip, dlg_regs->ref_freq_to_pix_freq,
196 				dlg_regs->vratio_prefetch, dlg_regs->vratio_prefetch_c, dlg_regs->refcyc_per_pte_group_vblank_l,
197 				dlg_regs->refcyc_per_pte_group_vblank_c, dlg_regs->refcyc_per_meta_chunk_vblank_l,
198 				dlg_regs->refcyc_per_meta_chunk_vblank_c, dlg_regs->refcyc_per_pte_group_flip_l,
199 				dlg_regs->refcyc_per_pte_group_flip_c, dlg_regs->refcyc_per_meta_chunk_flip_l,
200 				dlg_regs->refcyc_per_meta_chunk_flip_c, dlg_regs->dst_y_per_pte_row_nom_l,
201 				dlg_regs->dst_y_per_pte_row_nom_c, dlg_regs->refcyc_per_pte_group_nom_l,
202 				dlg_regs->refcyc_per_pte_group_nom_c, dlg_regs->dst_y_per_meta_row_nom_l,
203 				dlg_regs->dst_y_per_meta_row_nom_c, dlg_regs->refcyc_per_meta_chunk_nom_l,
204 				dlg_regs->refcyc_per_meta_chunk_nom_c, dlg_regs->refcyc_per_line_delivery_pre_l,
205 				dlg_regs->refcyc_per_line_delivery_pre_c, dlg_regs->refcyc_per_line_delivery_l,
206 				dlg_regs->refcyc_per_line_delivery_c, dlg_regs->chunk_hdl_adjust_cur0, dlg_regs->dst_y_offset_cur1,
207 				dlg_regs->chunk_hdl_adjust_cur1, dlg_regs->vready_after_vcount0, dlg_regs->dst_y_delta_drq_limit,
208 				dlg_regs->xfc_reg_transfer_delay, dlg_regs->xfc_reg_precharge_delay,
209 				dlg_regs->xfc_reg_remote_surface_flip_latency);
210 	}
211 
212 	DTN_INFO("========TTU========\n");
213 	DTN_INFO("HUBP:  qos_ll_wm  qos_lh_wm  mn_ttu_vb  qos_l_flp  rc_rd_p_l  rc_rd_l    rc_rd_p_c"
214 			"  rc_rd_c    rc_rd_c0   rc_rd_pc0  rc_rd_c1   rc_rd_pc1  qos_lf_l   qos_rds_l"
215 			"  qos_lf_c   qos_rds_c  qos_lf_c0  qos_rds_c0 qos_lf_c1  qos_rds_c1\n");
216 	for (i = 0; i < pool->pipe_count; i++) {
217 		struct dcn_hubp_state *s = &(TO_DCN10_HUBP(pool->hubps[i])->state);
218 		struct _vcs_dpi_display_ttu_regs_st *ttu_regs = &s->ttu_attr;
219 
220 		if (!s->blank_en)
221 			DTN_INFO("[%2d]:  %8xh  %8xh  %8xh  %8xh  %8xh  %8xh  %8xh  %8xh  %8xh  %8xh  %8xh  %8xh  %8xh  %8xh  %8xh  %8xh  %8xh  %8xh  %8xh  %8xh\n",
222 				pool->hubps[i]->inst, ttu_regs->qos_level_low_wm, ttu_regs->qos_level_high_wm, ttu_regs->min_ttu_vblank,
223 				ttu_regs->qos_level_flip, ttu_regs->refcyc_per_req_delivery_pre_l, ttu_regs->refcyc_per_req_delivery_l,
224 				ttu_regs->refcyc_per_req_delivery_pre_c, ttu_regs->refcyc_per_req_delivery_c, ttu_regs->refcyc_per_req_delivery_cur0,
225 				ttu_regs->refcyc_per_req_delivery_pre_cur0, ttu_regs->refcyc_per_req_delivery_cur1,
226 				ttu_regs->refcyc_per_req_delivery_pre_cur1, ttu_regs->qos_level_fixed_l, ttu_regs->qos_ramp_disable_l,
227 				ttu_regs->qos_level_fixed_c, ttu_regs->qos_ramp_disable_c, ttu_regs->qos_level_fixed_cur0,
228 				ttu_regs->qos_ramp_disable_cur0, ttu_regs->qos_level_fixed_cur1, ttu_regs->qos_ramp_disable_cur1);
229 	}
230 	DTN_INFO("\n");
231 }
232 
233 static
234 void dcn10_log_hw_state(struct dc *dc)
235 {
236 	struct dc_context *dc_ctx = dc->ctx;
237 	struct resource_pool *pool = dc->res_pool;
238 	int i;
239 
240 	DTN_INFO_BEGIN();
241 
242 	dcn10_log_hubbub_state(dc);
243 
244 	dcn10_log_hubp_states(dc);
245 
246 	DTN_INFO("DPP:    IGAM format  IGAM mode    DGAM mode    RGAM mode"
247 			"  GAMUT mode  C11 C12   C13 C14   C21 C22   C23 C24   "
248 			"C31 C32   C33 C34\n");
249 	for (i = 0; i < pool->pipe_count; i++) {
250 		struct dpp *dpp = pool->dpps[i];
251 		struct dcn_dpp_state s;
252 
253 		dpp->funcs->dpp_read_state(dpp, &s);
254 
255 		DTN_INFO("[%2d]:  %11xh  %-11s  %-11s  %-11s"
256 				"%8x    %08xh %08xh %08xh %08xh %08xh %08xh",
257 				dpp->inst,
258 				s.igam_input_format,
259 				(s.igam_lut_mode == 0) ? "BypassFixed" :
260 					((s.igam_lut_mode == 1) ? "BypassFloat" :
261 					((s.igam_lut_mode == 2) ? "RAM" :
262 					((s.igam_lut_mode == 3) ? "RAM" :
263 								 "Unknown"))),
264 				(s.dgam_lut_mode == 0) ? "Bypass" :
265 					((s.dgam_lut_mode == 1) ? "sRGB" :
266 					((s.dgam_lut_mode == 2) ? "Ycc" :
267 					((s.dgam_lut_mode == 3) ? "RAM" :
268 					((s.dgam_lut_mode == 4) ? "RAM" :
269 								 "Unknown")))),
270 				(s.rgam_lut_mode == 0) ? "Bypass" :
271 					((s.rgam_lut_mode == 1) ? "sRGB" :
272 					((s.rgam_lut_mode == 2) ? "Ycc" :
273 					((s.rgam_lut_mode == 3) ? "RAM" :
274 					((s.rgam_lut_mode == 4) ? "RAM" :
275 								 "Unknown")))),
276 				s.gamut_remap_mode,
277 				s.gamut_remap_c11_c12,
278 				s.gamut_remap_c13_c14,
279 				s.gamut_remap_c21_c22,
280 				s.gamut_remap_c23_c24,
281 				s.gamut_remap_c31_c32,
282 				s.gamut_remap_c33_c34);
283 		DTN_INFO("\n");
284 	}
285 	DTN_INFO("\n");
286 
287 	DTN_INFO("MPCC:  OPP  DPP  MPCCBOT  MODE  ALPHA_MODE  PREMULT  OVERLAP_ONLY  IDLE\n");
288 	for (i = 0; i < pool->pipe_count; i++) {
289 		struct mpcc_state s = {0};
290 
291 		pool->mpc->funcs->read_mpcc_state(pool->mpc, i, &s);
292 		if (s.opp_id != 0xf)
293 			DTN_INFO("[%2d]:  %2xh  %2xh  %6xh  %4d  %10d  %7d  %12d  %4d\n",
294 				i, s.opp_id, s.dpp_id, s.bot_mpcc_id,
295 				s.mode, s.alpha_mode, s.pre_multiplied_alpha, s.overlap_only,
296 				s.idle);
297 	}
298 	DTN_INFO("\n");
299 
300 	DTN_INFO("OTG:  v_bs  v_be  v_ss  v_se  vpol  vmax  vmin  vmax_sel  vmin_sel"
301 			"  h_bs  h_be  h_ss  h_se  hpol  htot  vtot  underflow\n");
302 
303 	for (i = 0; i < pool->timing_generator_count; i++) {
304 		struct timing_generator *tg = pool->timing_generators[i];
305 		struct dcn_otg_state s = {0};
306 
307 		optc1_read_otg_state(DCN10TG_FROM_TG(tg), &s);
308 
309 		//only print if OTG master is enabled
310 		if ((s.otg_enabled & 1) == 0)
311 			continue;
312 
313 		DTN_INFO("[%d]: %5d %5d %5d %5d %5d %5d %5d %9d %9d %5d %5d %5d"
314 				" %5d %5d %5d %5d  %9d\n",
315 				tg->inst,
316 				s.v_blank_start,
317 				s.v_blank_end,
318 				s.v_sync_a_start,
319 				s.v_sync_a_end,
320 				s.v_sync_a_pol,
321 				s.v_total_max,
322 				s.v_total_min,
323 				s.v_total_max_sel,
324 				s.v_total_min_sel,
325 				s.h_blank_start,
326 				s.h_blank_end,
327 				s.h_sync_a_start,
328 				s.h_sync_a_end,
329 				s.h_sync_a_pol,
330 				s.h_total,
331 				s.v_total,
332 				s.underflow_occurred_status);
333 
334 		// Clear underflow for debug purposes
335 		// We want to keep underflow sticky bit on for the longevity tests outside of test environment.
336 		// This function is called only from Windows or Diags test environment, hence it's safe to clear
337 		// it from here without affecting the original intent.
338 		tg->funcs->clear_optc_underflow(tg);
339 	}
340 	DTN_INFO("\n");
341 
342 	DTN_INFO("\nCALCULATED Clocks: dcfclk_khz:%d  dcfclk_deep_sleep_khz:%d  dispclk_khz:%d\n"
343 		"dppclk_khz:%d  max_supported_dppclk_khz:%d  fclk_khz:%d  socclk_khz:%d\n\n",
344 			dc->current_state->bw.dcn.clk.dcfclk_khz,
345 			dc->current_state->bw.dcn.clk.dcfclk_deep_sleep_khz,
346 			dc->current_state->bw.dcn.clk.dispclk_khz,
347 			dc->current_state->bw.dcn.clk.dppclk_khz,
348 			dc->current_state->bw.dcn.clk.max_supported_dppclk_khz,
349 			dc->current_state->bw.dcn.clk.fclk_khz,
350 			dc->current_state->bw.dcn.clk.socclk_khz);
351 
352 	log_mpc_crc(dc);
353 
354 	DTN_INFO_END();
355 }
356 
357 static void enable_power_gating_plane(
358 	struct dce_hwseq *hws,
359 	bool enable)
360 {
361 	bool force_on = 1; /* disable power gating */
362 
363 	if (enable)
364 		force_on = 0;
365 
366 	/* DCHUBP0/1/2/3 */
367 	REG_UPDATE(DOMAIN0_PG_CONFIG, DOMAIN0_POWER_FORCEON, force_on);
368 	REG_UPDATE(DOMAIN2_PG_CONFIG, DOMAIN2_POWER_FORCEON, force_on);
369 	REG_UPDATE(DOMAIN4_PG_CONFIG, DOMAIN4_POWER_FORCEON, force_on);
370 	REG_UPDATE(DOMAIN6_PG_CONFIG, DOMAIN6_POWER_FORCEON, force_on);
371 
372 	/* DPP0/1/2/3 */
373 	REG_UPDATE(DOMAIN1_PG_CONFIG, DOMAIN1_POWER_FORCEON, force_on);
374 	REG_UPDATE(DOMAIN3_PG_CONFIG, DOMAIN3_POWER_FORCEON, force_on);
375 	REG_UPDATE(DOMAIN5_PG_CONFIG, DOMAIN5_POWER_FORCEON, force_on);
376 	REG_UPDATE(DOMAIN7_PG_CONFIG, DOMAIN7_POWER_FORCEON, force_on);
377 }
378 
379 static void disable_vga(
380 	struct dce_hwseq *hws)
381 {
382 	unsigned int in_vga1_mode = 0;
383 	unsigned int in_vga2_mode = 0;
384 	unsigned int in_vga3_mode = 0;
385 	unsigned int in_vga4_mode = 0;
386 
387 	REG_GET(D1VGA_CONTROL, D1VGA_MODE_ENABLE, &in_vga1_mode);
388 	REG_GET(D2VGA_CONTROL, D2VGA_MODE_ENABLE, &in_vga2_mode);
389 	REG_GET(D3VGA_CONTROL, D3VGA_MODE_ENABLE, &in_vga3_mode);
390 	REG_GET(D4VGA_CONTROL, D4VGA_MODE_ENABLE, &in_vga4_mode);
391 
392 	if (in_vga1_mode == 0 && in_vga2_mode == 0 &&
393 			in_vga3_mode == 0 && in_vga4_mode == 0)
394 		return;
395 
396 	REG_WRITE(D1VGA_CONTROL, 0);
397 	REG_WRITE(D2VGA_CONTROL, 0);
398 	REG_WRITE(D3VGA_CONTROL, 0);
399 	REG_WRITE(D4VGA_CONTROL, 0);
400 
401 	/* HW Engineer's Notes:
402 	 *  During switch from vga->extended, if we set the VGA_TEST_ENABLE and
403 	 *  then hit the VGA_TEST_RENDER_START, then the DCHUBP timing gets updated correctly.
404 	 *
405 	 *  Then vBIOS will have it poll for the VGA_TEST_RENDER_DONE and unset
406 	 *  VGA_TEST_ENABLE, to leave it in the same state as before.
407 	 */
408 	REG_UPDATE(VGA_TEST_CONTROL, VGA_TEST_ENABLE, 1);
409 	REG_UPDATE(VGA_TEST_CONTROL, VGA_TEST_RENDER_START, 1);
410 }
411 
412 static void dpp_pg_control(
413 		struct dce_hwseq *hws,
414 		unsigned int dpp_inst,
415 		bool power_on)
416 {
417 	uint32_t power_gate = power_on ? 0 : 1;
418 	uint32_t pwr_status = power_on ? 0 : 2;
419 
420 	if (hws->ctx->dc->debug.disable_dpp_power_gate)
421 		return;
422 	if (REG(DOMAIN1_PG_CONFIG) == 0)
423 		return;
424 
425 	switch (dpp_inst) {
426 	case 0: /* DPP0 */
427 		REG_UPDATE(DOMAIN1_PG_CONFIG,
428 				DOMAIN1_POWER_GATE, power_gate);
429 
430 		REG_WAIT(DOMAIN1_PG_STATUS,
431 				DOMAIN1_PGFSM_PWR_STATUS, pwr_status,
432 				1, 1000);
433 		break;
434 	case 1: /* DPP1 */
435 		REG_UPDATE(DOMAIN3_PG_CONFIG,
436 				DOMAIN3_POWER_GATE, power_gate);
437 
438 		REG_WAIT(DOMAIN3_PG_STATUS,
439 				DOMAIN3_PGFSM_PWR_STATUS, pwr_status,
440 				1, 1000);
441 		break;
442 	case 2: /* DPP2 */
443 		REG_UPDATE(DOMAIN5_PG_CONFIG,
444 				DOMAIN5_POWER_GATE, power_gate);
445 
446 		REG_WAIT(DOMAIN5_PG_STATUS,
447 				DOMAIN5_PGFSM_PWR_STATUS, pwr_status,
448 				1, 1000);
449 		break;
450 	case 3: /* DPP3 */
451 		REG_UPDATE(DOMAIN7_PG_CONFIG,
452 				DOMAIN7_POWER_GATE, power_gate);
453 
454 		REG_WAIT(DOMAIN7_PG_STATUS,
455 				DOMAIN7_PGFSM_PWR_STATUS, pwr_status,
456 				1, 1000);
457 		break;
458 	default:
459 		BREAK_TO_DEBUGGER();
460 		break;
461 	}
462 }
463 
464 static void hubp_pg_control(
465 		struct dce_hwseq *hws,
466 		unsigned int hubp_inst,
467 		bool power_on)
468 {
469 	uint32_t power_gate = power_on ? 0 : 1;
470 	uint32_t pwr_status = power_on ? 0 : 2;
471 
472 	if (hws->ctx->dc->debug.disable_hubp_power_gate)
473 		return;
474 	if (REG(DOMAIN0_PG_CONFIG) == 0)
475 		return;
476 
477 	switch (hubp_inst) {
478 	case 0: /* DCHUBP0 */
479 		REG_UPDATE(DOMAIN0_PG_CONFIG,
480 				DOMAIN0_POWER_GATE, power_gate);
481 
482 		REG_WAIT(DOMAIN0_PG_STATUS,
483 				DOMAIN0_PGFSM_PWR_STATUS, pwr_status,
484 				1, 1000);
485 		break;
486 	case 1: /* DCHUBP1 */
487 		REG_UPDATE(DOMAIN2_PG_CONFIG,
488 				DOMAIN2_POWER_GATE, power_gate);
489 
490 		REG_WAIT(DOMAIN2_PG_STATUS,
491 				DOMAIN2_PGFSM_PWR_STATUS, pwr_status,
492 				1, 1000);
493 		break;
494 	case 2: /* DCHUBP2 */
495 		REG_UPDATE(DOMAIN4_PG_CONFIG,
496 				DOMAIN4_POWER_GATE, power_gate);
497 
498 		REG_WAIT(DOMAIN4_PG_STATUS,
499 				DOMAIN4_PGFSM_PWR_STATUS, pwr_status,
500 				1, 1000);
501 		break;
502 	case 3: /* DCHUBP3 */
503 		REG_UPDATE(DOMAIN6_PG_CONFIG,
504 				DOMAIN6_POWER_GATE, power_gate);
505 
506 		REG_WAIT(DOMAIN6_PG_STATUS,
507 				DOMAIN6_PGFSM_PWR_STATUS, pwr_status,
508 				1, 1000);
509 		break;
510 	default:
511 		BREAK_TO_DEBUGGER();
512 		break;
513 	}
514 }
515 
516 static void power_on_plane(
517 	struct dce_hwseq *hws,
518 	int plane_id)
519 {
520 	DC_LOGGER_INIT(hws->ctx->logger);
521 	if (REG(DC_IP_REQUEST_CNTL)) {
522 		REG_SET(DC_IP_REQUEST_CNTL, 0,
523 				IP_REQUEST_EN, 1);
524 		dpp_pg_control(hws, plane_id, true);
525 		hubp_pg_control(hws, plane_id, true);
526 		REG_SET(DC_IP_REQUEST_CNTL, 0,
527 				IP_REQUEST_EN, 0);
528 		DC_LOG_DEBUG(
529 				"Un-gated front end for pipe %d\n", plane_id);
530 	}
531 }
532 
533 static void undo_DEGVIDCN10_253_wa(struct dc *dc)
534 {
535 	struct dce_hwseq *hws = dc->hwseq;
536 	struct hubp *hubp = dc->res_pool->hubps[0];
537 
538 	if (!hws->wa_state.DEGVIDCN10_253_applied)
539 		return;
540 
541 	hubp->funcs->set_blank(hubp, true);
542 
543 	REG_SET(DC_IP_REQUEST_CNTL, 0,
544 			IP_REQUEST_EN, 1);
545 
546 	hubp_pg_control(hws, 0, false);
547 	REG_SET(DC_IP_REQUEST_CNTL, 0,
548 			IP_REQUEST_EN, 0);
549 
550 	hws->wa_state.DEGVIDCN10_253_applied = false;
551 }
552 
553 static void apply_DEGVIDCN10_253_wa(struct dc *dc)
554 {
555 	struct dce_hwseq *hws = dc->hwseq;
556 	struct hubp *hubp = dc->res_pool->hubps[0];
557 	int i;
558 
559 	if (dc->debug.disable_stutter)
560 		return;
561 
562 	if (!hws->wa.DEGVIDCN10_253)
563 		return;
564 
565 	for (i = 0; i < dc->res_pool->pipe_count; i++) {
566 		if (!dc->res_pool->hubps[i]->power_gated)
567 			return;
568 	}
569 
570 	/* all pipe power gated, apply work around to enable stutter. */
571 
572 	REG_SET(DC_IP_REQUEST_CNTL, 0,
573 			IP_REQUEST_EN, 1);
574 
575 	hubp_pg_control(hws, 0, true);
576 	REG_SET(DC_IP_REQUEST_CNTL, 0,
577 			IP_REQUEST_EN, 0);
578 
579 	hubp->funcs->set_hubp_blank_en(hubp, false);
580 	hws->wa_state.DEGVIDCN10_253_applied = true;
581 }
582 
583 static void bios_golden_init(struct dc *dc)
584 {
585 	struct dc_bios *bp = dc->ctx->dc_bios;
586 	int i;
587 
588 	/* initialize dcn global */
589 	bp->funcs->enable_disp_power_gating(bp,
590 			CONTROLLER_ID_D0, ASIC_PIPE_INIT);
591 
592 	for (i = 0; i < dc->res_pool->pipe_count; i++) {
593 		/* initialize dcn per pipe */
594 		bp->funcs->enable_disp_power_gating(bp,
595 				CONTROLLER_ID_D0 + i, ASIC_PIPE_DISABLE);
596 	}
597 }
598 
599 static void false_optc_underflow_wa(
600 		struct dc *dc,
601 		const struct dc_stream_state *stream,
602 		struct timing_generator *tg)
603 {
604 	int i;
605 	bool underflow;
606 
607 	if (!dc->hwseq->wa.false_optc_underflow)
608 		return;
609 
610 	underflow = tg->funcs->is_optc_underflow_occurred(tg);
611 
612 	for (i = 0; i < dc->res_pool->pipe_count; i++) {
613 		struct pipe_ctx *old_pipe_ctx = &dc->current_state->res_ctx.pipe_ctx[i];
614 
615 		if (old_pipe_ctx->stream != stream)
616 			continue;
617 
618 		dc->hwss.wait_for_mpcc_disconnect(dc, dc->res_pool, old_pipe_ctx);
619 	}
620 
621 	tg->funcs->set_blank_data_double_buffer(tg, true);
622 
623 	if (tg->funcs->is_optc_underflow_occurred(tg) && !underflow)
624 		tg->funcs->clear_optc_underflow(tg);
625 }
626 
627 static enum dc_status dcn10_enable_stream_timing(
628 		struct pipe_ctx *pipe_ctx,
629 		struct dc_state *context,
630 		struct dc *dc)
631 {
632 	struct dc_stream_state *stream = pipe_ctx->stream;
633 	enum dc_color_space color_space;
634 	struct tg_color black_color = {0};
635 
636 	/* by upper caller loop, pipe0 is parent pipe and be called first.
637 	 * back end is set up by for pipe0. Other children pipe share back end
638 	 * with pipe 0. No program is needed.
639 	 */
640 	if (pipe_ctx->top_pipe != NULL)
641 		return DC_OK;
642 
643 	/* TODO check if timing_changed, disable stream if timing changed */
644 
645 	/* HW program guide assume display already disable
646 	 * by unplug sequence. OTG assume stop.
647 	 */
648 	pipe_ctx->stream_res.tg->funcs->enable_optc_clock(pipe_ctx->stream_res.tg, true);
649 
650 	if (false == pipe_ctx->clock_source->funcs->program_pix_clk(
651 			pipe_ctx->clock_source,
652 			&pipe_ctx->stream_res.pix_clk_params,
653 			&pipe_ctx->pll_settings)) {
654 		BREAK_TO_DEBUGGER();
655 		return DC_ERROR_UNEXPECTED;
656 	}
657 	pipe_ctx->stream_res.tg->dlg_otg_param.vready_offset = pipe_ctx->pipe_dlg_param.vready_offset;
658 	pipe_ctx->stream_res.tg->dlg_otg_param.vstartup_start = pipe_ctx->pipe_dlg_param.vstartup_start;
659 	pipe_ctx->stream_res.tg->dlg_otg_param.vupdate_offset = pipe_ctx->pipe_dlg_param.vupdate_offset;
660 	pipe_ctx->stream_res.tg->dlg_otg_param.vupdate_width = pipe_ctx->pipe_dlg_param.vupdate_width;
661 
662 	pipe_ctx->stream_res.tg->dlg_otg_param.signal =  pipe_ctx->stream->signal;
663 
664 	pipe_ctx->stream_res.tg->funcs->program_timing(
665 			pipe_ctx->stream_res.tg,
666 			&stream->timing,
667 			true);
668 
669 #if 0 /* move to after enable_crtc */
670 	/* TODO: OPP FMT, ABM. etc. should be done here. */
671 	/* or FPGA now. instance 0 only. TODO: move to opp.c */
672 
673 	inst_offset = reg_offsets[pipe_ctx->stream_res.tg->inst].fmt;
674 
675 	pipe_ctx->stream_res.opp->funcs->opp_program_fmt(
676 				pipe_ctx->stream_res.opp,
677 				&stream->bit_depth_params,
678 				&stream->clamping);
679 #endif
680 	/* program otg blank color */
681 	color_space = stream->output_color_space;
682 	color_space_to_black_color(dc, color_space, &black_color);
683 
684 	if (pipe_ctx->stream_res.tg->funcs->set_blank_color)
685 		pipe_ctx->stream_res.tg->funcs->set_blank_color(
686 				pipe_ctx->stream_res.tg,
687 				&black_color);
688 
689 	if (pipe_ctx->stream_res.tg->funcs->is_blanked &&
690 			!pipe_ctx->stream_res.tg->funcs->is_blanked(pipe_ctx->stream_res.tg)) {
691 		pipe_ctx->stream_res.tg->funcs->set_blank(pipe_ctx->stream_res.tg, true);
692 		hwss_wait_for_blank_complete(pipe_ctx->stream_res.tg);
693 		false_optc_underflow_wa(dc, pipe_ctx->stream, pipe_ctx->stream_res.tg);
694 	}
695 
696 	/* VTG is  within DCHUB command block. DCFCLK is always on */
697 	if (false == pipe_ctx->stream_res.tg->funcs->enable_crtc(pipe_ctx->stream_res.tg)) {
698 		BREAK_TO_DEBUGGER();
699 		return DC_ERROR_UNEXPECTED;
700 	}
701 
702 	/* TODO program crtc source select for non-virtual signal*/
703 	/* TODO program FMT */
704 	/* TODO setup link_enc */
705 	/* TODO set stream attributes */
706 	/* TODO program audio */
707 	/* TODO enable stream if timing changed */
708 	/* TODO unblank stream if DP */
709 
710 	return DC_OK;
711 }
712 
713 static void reset_back_end_for_pipe(
714 		struct dc *dc,
715 		struct pipe_ctx *pipe_ctx,
716 		struct dc_state *context)
717 {
718 	int i;
719 	DC_LOGGER_INIT(dc->ctx->logger);
720 	if (pipe_ctx->stream_res.stream_enc == NULL) {
721 		pipe_ctx->stream = NULL;
722 		return;
723 	}
724 
725 	if (!IS_FPGA_MAXIMUS_DC(dc->ctx->dce_environment)) {
726 		/* DPMS may already disable */
727 		if (!pipe_ctx->stream->dpms_off)
728 			core_link_disable_stream(pipe_ctx, FREE_ACQUIRED_RESOURCE);
729 		else if (pipe_ctx->stream_res.audio) {
730 			dc->hwss.disable_audio_stream(pipe_ctx, FREE_ACQUIRED_RESOURCE);
731 		}
732 
733 	}
734 
735 	/* by upper caller loop, parent pipe: pipe0, will be reset last.
736 	 * back end share by all pipes and will be disable only when disable
737 	 * parent pipe.
738 	 */
739 	if (pipe_ctx->top_pipe == NULL) {
740 		pipe_ctx->stream_res.tg->funcs->disable_crtc(pipe_ctx->stream_res.tg);
741 
742 		pipe_ctx->stream_res.tg->funcs->enable_optc_clock(pipe_ctx->stream_res.tg, false);
743 	}
744 
745 	for (i = 0; i < dc->res_pool->pipe_count; i++)
746 		if (&dc->current_state->res_ctx.pipe_ctx[i] == pipe_ctx)
747 			break;
748 
749 	if (i == dc->res_pool->pipe_count)
750 		return;
751 
752 	pipe_ctx->stream = NULL;
753 	DC_LOG_DEBUG("Reset back end for pipe %d, tg:%d\n",
754 					pipe_ctx->pipe_idx, pipe_ctx->stream_res.tg->inst);
755 }
756 
757 static bool dcn10_hw_wa_force_recovery(struct dc *dc)
758 {
759 	struct hubp *hubp ;
760 	unsigned int i;
761 	bool need_recover = true;
762 
763 	if (!dc->debug.recovery_enabled)
764 		return false;
765 
766 	for (i = 0; i < dc->res_pool->pipe_count; i++) {
767 		struct pipe_ctx *pipe_ctx =
768 			&dc->current_state->res_ctx.pipe_ctx[i];
769 		if (pipe_ctx != NULL) {
770 			hubp = pipe_ctx->plane_res.hubp;
771 			if (hubp != NULL) {
772 				if (hubp->funcs->hubp_get_underflow_status(hubp) != 0) {
773 					/* one pipe underflow, we will reset all the pipes*/
774 					need_recover = true;
775 				}
776 			}
777 		}
778 	}
779 	if (!need_recover)
780 		return false;
781 	/*
782 	DCHUBP_CNTL:HUBP_BLANK_EN=1
783 	DCHUBBUB_SOFT_RESET:DCHUBBUB_GLOBAL_SOFT_RESET=1
784 	DCHUBP_CNTL:HUBP_DISABLE=1
785 	DCHUBP_CNTL:HUBP_DISABLE=0
786 	DCHUBBUB_SOFT_RESET:DCHUBBUB_GLOBAL_SOFT_RESET=0
787 	DCSURF_PRIMARY_SURFACE_ADDRESS
788 	DCHUBP_CNTL:HUBP_BLANK_EN=0
789 	*/
790 
791 	for (i = 0; i < dc->res_pool->pipe_count; i++) {
792 		struct pipe_ctx *pipe_ctx =
793 			&dc->current_state->res_ctx.pipe_ctx[i];
794 		if (pipe_ctx != NULL) {
795 			hubp = pipe_ctx->plane_res.hubp;
796 			/*DCHUBP_CNTL:HUBP_BLANK_EN=1*/
797 			if (hubp != NULL)
798 				hubp->funcs->set_hubp_blank_en(hubp, true);
799 		}
800 	}
801 	/*DCHUBBUB_SOFT_RESET:DCHUBBUB_GLOBAL_SOFT_RESET=1*/
802 	hubbub1_soft_reset(dc->res_pool->hubbub, true);
803 
804 	for (i = 0; i < dc->res_pool->pipe_count; i++) {
805 		struct pipe_ctx *pipe_ctx =
806 			&dc->current_state->res_ctx.pipe_ctx[i];
807 		if (pipe_ctx != NULL) {
808 			hubp = pipe_ctx->plane_res.hubp;
809 			/*DCHUBP_CNTL:HUBP_DISABLE=1*/
810 			if (hubp != NULL)
811 				hubp->funcs->hubp_disable_control(hubp, true);
812 		}
813 	}
814 	for (i = 0; i < dc->res_pool->pipe_count; i++) {
815 		struct pipe_ctx *pipe_ctx =
816 			&dc->current_state->res_ctx.pipe_ctx[i];
817 		if (pipe_ctx != NULL) {
818 			hubp = pipe_ctx->plane_res.hubp;
819 			/*DCHUBP_CNTL:HUBP_DISABLE=0*/
820 			if (hubp != NULL)
821 				hubp->funcs->hubp_disable_control(hubp, true);
822 		}
823 	}
824 	/*DCHUBBUB_SOFT_RESET:DCHUBBUB_GLOBAL_SOFT_RESET=0*/
825 	hubbub1_soft_reset(dc->res_pool->hubbub, false);
826 	for (i = 0; i < dc->res_pool->pipe_count; i++) {
827 		struct pipe_ctx *pipe_ctx =
828 			&dc->current_state->res_ctx.pipe_ctx[i];
829 		if (pipe_ctx != NULL) {
830 			hubp = pipe_ctx->plane_res.hubp;
831 			/*DCHUBP_CNTL:HUBP_BLANK_EN=0*/
832 			if (hubp != NULL)
833 				hubp->funcs->set_hubp_blank_en(hubp, true);
834 		}
835 	}
836 	return true;
837 
838 }
839 
840 
841 void dcn10_verify_allow_pstate_change_high(struct dc *dc)
842 {
843 	static bool should_log_hw_state; /* prevent hw state log by default */
844 
845 	if (!hubbub1_verify_allow_pstate_change_high(dc->res_pool->hubbub)) {
846 		if (should_log_hw_state) {
847 			dcn10_log_hw_state(dc);
848 		}
849 		BREAK_TO_DEBUGGER();
850 		if (dcn10_hw_wa_force_recovery(dc)) {
851 		/*check again*/
852 			if (!hubbub1_verify_allow_pstate_change_high(dc->res_pool->hubbub))
853 				BREAK_TO_DEBUGGER();
854 		}
855 	}
856 }
857 
858 /* trigger HW to start disconnect plane from stream on the next vsync */
859 void hwss1_plane_atomic_disconnect(struct dc *dc, struct pipe_ctx *pipe_ctx)
860 {
861 	struct hubp *hubp = pipe_ctx->plane_res.hubp;
862 	int dpp_id = pipe_ctx->plane_res.dpp->inst;
863 	struct mpc *mpc = dc->res_pool->mpc;
864 	struct mpc_tree *mpc_tree_params;
865 	struct mpcc *mpcc_to_remove = NULL;
866 	struct output_pixel_processor *opp = pipe_ctx->stream_res.opp;
867 
868 	mpc_tree_params = &(opp->mpc_tree_params);
869 	mpcc_to_remove = mpc->funcs->get_mpcc_for_dpp(mpc_tree_params, dpp_id);
870 
871 	/*Already reset*/
872 	if (mpcc_to_remove == NULL)
873 		return;
874 
875 	mpc->funcs->remove_mpcc(mpc, mpc_tree_params, mpcc_to_remove);
876 	if (opp != NULL)
877 		opp->mpcc_disconnect_pending[pipe_ctx->plane_res.mpcc_inst] = true;
878 
879 	dc->optimized_required = true;
880 
881 	if (hubp->funcs->hubp_disconnect)
882 		hubp->funcs->hubp_disconnect(hubp);
883 
884 	if (dc->debug.sanity_checks)
885 		dcn10_verify_allow_pstate_change_high(dc);
886 }
887 
888 static void plane_atomic_power_down(struct dc *dc, struct pipe_ctx *pipe_ctx)
889 {
890 	struct dce_hwseq *hws = dc->hwseq;
891 	struct dpp *dpp = pipe_ctx->plane_res.dpp;
892 	DC_LOGGER_INIT(dc->ctx->logger);
893 
894 	if (REG(DC_IP_REQUEST_CNTL)) {
895 		REG_SET(DC_IP_REQUEST_CNTL, 0,
896 				IP_REQUEST_EN, 1);
897 		dpp_pg_control(hws, dpp->inst, false);
898 		hubp_pg_control(hws, pipe_ctx->plane_res.hubp->inst, false);
899 		dpp->funcs->dpp_reset(dpp);
900 		REG_SET(DC_IP_REQUEST_CNTL, 0,
901 				IP_REQUEST_EN, 0);
902 		DC_LOG_DEBUG(
903 				"Power gated front end %d\n", pipe_ctx->pipe_idx);
904 	}
905 }
906 
907 /* disable HW used by plane.
908  * note:  cannot disable until disconnect is complete
909  */
910 static void plane_atomic_disable(struct dc *dc, struct pipe_ctx *pipe_ctx)
911 {
912 	struct hubp *hubp = pipe_ctx->plane_res.hubp;
913 	struct dpp *dpp = pipe_ctx->plane_res.dpp;
914 	int opp_id = hubp->opp_id;
915 
916 	dc->hwss.wait_for_mpcc_disconnect(dc, dc->res_pool, pipe_ctx);
917 
918 	hubp->funcs->hubp_clk_cntl(hubp, false);
919 
920 	dpp->funcs->dpp_dppclk_control(dpp, false, false);
921 
922 	if (opp_id != 0xf && pipe_ctx->stream_res.opp->mpc_tree_params.opp_list == NULL)
923 		pipe_ctx->stream_res.opp->funcs->opp_pipe_clock_control(
924 				pipe_ctx->stream_res.opp,
925 				false);
926 
927 	hubp->power_gated = true;
928 	dc->optimized_required = false; /* We're powering off, no need to optimize */
929 
930 	plane_atomic_power_down(dc, pipe_ctx);
931 
932 	pipe_ctx->stream = NULL;
933 	memset(&pipe_ctx->stream_res, 0, sizeof(pipe_ctx->stream_res));
934 	memset(&pipe_ctx->plane_res, 0, sizeof(pipe_ctx->plane_res));
935 	pipe_ctx->top_pipe = NULL;
936 	pipe_ctx->bottom_pipe = NULL;
937 	pipe_ctx->plane_state = NULL;
938 }
939 
940 static void dcn10_disable_plane(struct dc *dc, struct pipe_ctx *pipe_ctx)
941 {
942 	DC_LOGGER_INIT(dc->ctx->logger);
943 
944 	if (!pipe_ctx->plane_res.hubp || pipe_ctx->plane_res.hubp->power_gated)
945 		return;
946 
947 	plane_atomic_disable(dc, pipe_ctx);
948 
949 	apply_DEGVIDCN10_253_wa(dc);
950 
951 	DC_LOG_DC("Power down front end %d\n",
952 					pipe_ctx->pipe_idx);
953 }
954 
955 static void dcn10_init_hw(struct dc *dc)
956 {
957 	int i;
958 	struct abm *abm = dc->res_pool->abm;
959 	struct dmcu *dmcu = dc->res_pool->dmcu;
960 	struct dce_hwseq *hws = dc->hwseq;
961 	struct dc_bios *dcb = dc->ctx->dc_bios;
962 	struct dc_state  *context = dc->current_state;
963 
964 	if (IS_FPGA_MAXIMUS_DC(dc->ctx->dce_environment)) {
965 		REG_WRITE(REFCLK_CNTL, 0);
966 		REG_UPDATE(DCHUBBUB_GLOBAL_TIMER_CNTL, DCHUBBUB_GLOBAL_TIMER_ENABLE, 1);
967 		REG_WRITE(DIO_MEM_PWR_CTRL, 0);
968 
969 		if (!dc->debug.disable_clock_gate) {
970 			/* enable all DCN clock gating */
971 			REG_WRITE(DCCG_GATE_DISABLE_CNTL, 0);
972 
973 			REG_WRITE(DCCG_GATE_DISABLE_CNTL2, 0);
974 
975 			REG_UPDATE(DCFCLK_CNTL, DCFCLK_GATE_DIS, 0);
976 		}
977 
978 		enable_power_gating_plane(dc->hwseq, true);
979 	} else {
980 
981 		if (!dcb->funcs->is_accelerated_mode(dcb)) {
982 			bios_golden_init(dc);
983 			disable_vga(dc->hwseq);
984 		}
985 
986 		for (i = 0; i < dc->link_count; i++) {
987 			/* Power up AND update implementation according to the
988 			 * required signal (which may be different from the
989 			 * default signal on connector).
990 			 */
991 			struct dc_link *link = dc->links[i];
992 
993 			if (link->link_enc->connector.id == CONNECTOR_ID_EDP)
994 				dc->hwss.edp_power_control(link, true);
995 
996 			link->link_enc->funcs->hw_init(link->link_enc);
997 		}
998 	}
999 
1000 	for (i = 0; i < dc->res_pool->pipe_count; i++) {
1001 		struct timing_generator *tg = dc->res_pool->timing_generators[i];
1002 
1003 		if (tg->funcs->is_tg_enabled(tg))
1004 			tg->funcs->lock(tg);
1005 	}
1006 
1007 	/* Blank controller using driver code instead of
1008 	 * command table.
1009 	 */
1010 	for (i = 0; i < dc->res_pool->pipe_count; i++) {
1011 		struct timing_generator *tg = dc->res_pool->timing_generators[i];
1012 
1013 		if (tg->funcs->is_tg_enabled(tg)) {
1014 			tg->funcs->set_blank(tg, true);
1015 			hwss_wait_for_blank_complete(tg);
1016 		}
1017 	}
1018 
1019 	/* Reset all MPCC muxes */
1020 	dc->res_pool->mpc->funcs->mpc_init(dc->res_pool->mpc);
1021 
1022 	for (i = 0; i < dc->res_pool->timing_generator_count; i++) {
1023 		struct timing_generator *tg = dc->res_pool->timing_generators[i];
1024 		struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[i];
1025 		struct hubp *hubp = dc->res_pool->hubps[i];
1026 		struct dpp *dpp = dc->res_pool->dpps[i];
1027 
1028 		pipe_ctx->stream_res.tg = tg;
1029 		pipe_ctx->pipe_idx = i;
1030 
1031 		pipe_ctx->plane_res.hubp = hubp;
1032 		pipe_ctx->plane_res.dpp = dpp;
1033 		pipe_ctx->plane_res.mpcc_inst = dpp->inst;
1034 		hubp->mpcc_id = dpp->inst;
1035 		hubp->opp_id = 0xf;
1036 		hubp->power_gated = false;
1037 
1038 		dc->res_pool->opps[i]->mpc_tree_params.opp_id = dc->res_pool->opps[i]->inst;
1039 		dc->res_pool->opps[i]->mpc_tree_params.opp_list = NULL;
1040 		dc->res_pool->opps[i]->mpcc_disconnect_pending[pipe_ctx->plane_res.mpcc_inst] = true;
1041 		pipe_ctx->stream_res.opp = dc->res_pool->opps[i];
1042 
1043 		hwss1_plane_atomic_disconnect(dc, pipe_ctx);
1044 	}
1045 
1046 	for (i = 0; i < dc->res_pool->pipe_count; i++) {
1047 		struct timing_generator *tg = dc->res_pool->timing_generators[i];
1048 
1049 		if (tg->funcs->is_tg_enabled(tg))
1050 			tg->funcs->unlock(tg);
1051 	}
1052 
1053 	for (i = 0; i < dc->res_pool->pipe_count; i++) {
1054 		struct timing_generator *tg = dc->res_pool->timing_generators[i];
1055 		struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[i];
1056 
1057 		dcn10_disable_plane(dc, pipe_ctx);
1058 
1059 		pipe_ctx->stream_res.tg = NULL;
1060 		pipe_ctx->plane_res.hubp = NULL;
1061 
1062 		tg->funcs->tg_init(tg);
1063 	}
1064 
1065 	/* end of FPGA. Below if real ASIC */
1066 	if (IS_FPGA_MAXIMUS_DC(dc->ctx->dce_environment))
1067 		return;
1068 
1069 	for (i = 0; i < dc->res_pool->audio_count; i++) {
1070 		struct audio *audio = dc->res_pool->audios[i];
1071 
1072 		audio->funcs->hw_init(audio);
1073 	}
1074 
1075 	if (abm != NULL) {
1076 		abm->funcs->init_backlight(abm);
1077 		abm->funcs->abm_init(abm);
1078 	}
1079 
1080 	if (dmcu != NULL)
1081 		dmcu->funcs->dmcu_init(dmcu);
1082 
1083 	/* power AFMT HDMI memory TODO: may move to dis/en output save power*/
1084 	REG_WRITE(DIO_MEM_PWR_CTRL, 0);
1085 
1086 	if (!dc->debug.disable_clock_gate) {
1087 		/* enable all DCN clock gating */
1088 		REG_WRITE(DCCG_GATE_DISABLE_CNTL, 0);
1089 
1090 		REG_WRITE(DCCG_GATE_DISABLE_CNTL2, 0);
1091 
1092 		REG_UPDATE(DCFCLK_CNTL, DCFCLK_GATE_DIS, 0);
1093 	}
1094 
1095 	enable_power_gating_plane(dc->hwseq, true);
1096 
1097 	memset(&dc->res_pool->dccg->clks, 0, sizeof(dc->res_pool->dccg->clks));
1098 }
1099 
1100 static void reset_hw_ctx_wrap(
1101 		struct dc *dc,
1102 		struct dc_state *context)
1103 {
1104 	int i;
1105 
1106 	/* Reset Back End*/
1107 	for (i = dc->res_pool->pipe_count - 1; i >= 0 ; i--) {
1108 		struct pipe_ctx *pipe_ctx_old =
1109 			&dc->current_state->res_ctx.pipe_ctx[i];
1110 		struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[i];
1111 
1112 		if (!pipe_ctx_old->stream)
1113 			continue;
1114 
1115 		if (pipe_ctx_old->top_pipe)
1116 			continue;
1117 
1118 		if (!pipe_ctx->stream ||
1119 				pipe_need_reprogram(pipe_ctx_old, pipe_ctx)) {
1120 			struct clock_source *old_clk = pipe_ctx_old->clock_source;
1121 
1122 			reset_back_end_for_pipe(dc, pipe_ctx_old, dc->current_state);
1123 			if (old_clk)
1124 				old_clk->funcs->cs_power_down(old_clk);
1125 		}
1126 	}
1127 
1128 }
1129 
1130 static bool patch_address_for_sbs_tb_stereo(
1131 		struct pipe_ctx *pipe_ctx, PHYSICAL_ADDRESS_LOC *addr)
1132 {
1133 	struct dc_plane_state *plane_state = pipe_ctx->plane_state;
1134 	bool sec_split = pipe_ctx->top_pipe &&
1135 			pipe_ctx->top_pipe->plane_state == pipe_ctx->plane_state;
1136 	if (sec_split && plane_state->address.type == PLN_ADDR_TYPE_GRPH_STEREO &&
1137 		(pipe_ctx->stream->timing.timing_3d_format ==
1138 		 TIMING_3D_FORMAT_SIDE_BY_SIDE ||
1139 		 pipe_ctx->stream->timing.timing_3d_format ==
1140 		 TIMING_3D_FORMAT_TOP_AND_BOTTOM)) {
1141 		*addr = plane_state->address.grph_stereo.left_addr;
1142 		plane_state->address.grph_stereo.left_addr =
1143 		plane_state->address.grph_stereo.right_addr;
1144 		return true;
1145 	} else {
1146 		if (pipe_ctx->stream->view_format != VIEW_3D_FORMAT_NONE &&
1147 			plane_state->address.type != PLN_ADDR_TYPE_GRPH_STEREO) {
1148 			plane_state->address.type = PLN_ADDR_TYPE_GRPH_STEREO;
1149 			plane_state->address.grph_stereo.right_addr =
1150 			plane_state->address.grph_stereo.left_addr;
1151 		}
1152 	}
1153 	return false;
1154 }
1155 
1156 
1157 
1158 static void dcn10_update_plane_addr(const struct dc *dc, struct pipe_ctx *pipe_ctx)
1159 {
1160 	bool addr_patched = false;
1161 	PHYSICAL_ADDRESS_LOC addr;
1162 	struct dc_plane_state *plane_state = pipe_ctx->plane_state;
1163 
1164 	if (plane_state == NULL)
1165 		return;
1166 
1167 	addr_patched = patch_address_for_sbs_tb_stereo(pipe_ctx, &addr);
1168 
1169 	pipe_ctx->plane_res.hubp->funcs->hubp_program_surface_flip_and_addr(
1170 			pipe_ctx->plane_res.hubp,
1171 			&plane_state->address,
1172 			plane_state->flip_immediate);
1173 
1174 	plane_state->status.requested_address = plane_state->address;
1175 
1176 	if (plane_state->flip_immediate)
1177 		plane_state->status.current_address = plane_state->address;
1178 
1179 	if (addr_patched)
1180 		pipe_ctx->plane_state->address.grph_stereo.left_addr = addr;
1181 }
1182 
1183 static bool dcn10_set_input_transfer_func(struct pipe_ctx *pipe_ctx,
1184 					  const struct dc_plane_state *plane_state)
1185 {
1186 	struct dpp *dpp_base = pipe_ctx->plane_res.dpp;
1187 	const struct dc_transfer_func *tf = NULL;
1188 	bool result = true;
1189 
1190 	if (dpp_base == NULL)
1191 		return false;
1192 
1193 	if (plane_state->in_transfer_func)
1194 		tf = plane_state->in_transfer_func;
1195 
1196 	if (plane_state->gamma_correction &&
1197 		!dpp_base->ctx->dc->debug.always_use_regamma
1198 		&& !plane_state->gamma_correction->is_identity
1199 			&& dce_use_lut(plane_state->format))
1200 		dpp_base->funcs->dpp_program_input_lut(dpp_base, plane_state->gamma_correction);
1201 
1202 	if (tf == NULL)
1203 		dpp_base->funcs->dpp_set_degamma(dpp_base, IPP_DEGAMMA_MODE_BYPASS);
1204 	else if (tf->type == TF_TYPE_PREDEFINED) {
1205 		switch (tf->tf) {
1206 		case TRANSFER_FUNCTION_SRGB:
1207 			dpp_base->funcs->dpp_set_degamma(dpp_base, IPP_DEGAMMA_MODE_HW_sRGB);
1208 			break;
1209 		case TRANSFER_FUNCTION_BT709:
1210 			dpp_base->funcs->dpp_set_degamma(dpp_base, IPP_DEGAMMA_MODE_HW_xvYCC);
1211 			break;
1212 		case TRANSFER_FUNCTION_LINEAR:
1213 			dpp_base->funcs->dpp_set_degamma(dpp_base, IPP_DEGAMMA_MODE_BYPASS);
1214 			break;
1215 		case TRANSFER_FUNCTION_PQ:
1216 		default:
1217 			result = false;
1218 			break;
1219 		}
1220 	} else if (tf->type == TF_TYPE_BYPASS) {
1221 		dpp_base->funcs->dpp_set_degamma(dpp_base, IPP_DEGAMMA_MODE_BYPASS);
1222 	} else {
1223 		cm_helper_translate_curve_to_degamma_hw_format(tf,
1224 					&dpp_base->degamma_params);
1225 		dpp_base->funcs->dpp_program_degamma_pwl(dpp_base,
1226 				&dpp_base->degamma_params);
1227 		result = true;
1228 	}
1229 
1230 	return result;
1231 }
1232 
1233 
1234 
1235 
1236 
1237 static bool
1238 dcn10_set_output_transfer_func(struct pipe_ctx *pipe_ctx,
1239 			       const struct dc_stream_state *stream)
1240 {
1241 	struct dpp *dpp = pipe_ctx->plane_res.dpp;
1242 
1243 	if (dpp == NULL)
1244 		return false;
1245 
1246 	dpp->regamma_params.hw_points_num = GAMMA_HW_POINTS_NUM;
1247 
1248 	if (stream->out_transfer_func &&
1249 	    stream->out_transfer_func->type == TF_TYPE_PREDEFINED &&
1250 	    stream->out_transfer_func->tf == TRANSFER_FUNCTION_SRGB)
1251 		dpp->funcs->dpp_program_regamma_pwl(dpp, NULL, OPP_REGAMMA_SRGB);
1252 
1253 	/* dcn10_translate_regamma_to_hw_format takes 750us, only do it when full
1254 	 * update.
1255 	 */
1256 	else if (cm_helper_translate_curve_to_hw_format(
1257 			stream->out_transfer_func,
1258 			&dpp->regamma_params, false)) {
1259 		dpp->funcs->dpp_program_regamma_pwl(
1260 				dpp,
1261 				&dpp->regamma_params, OPP_REGAMMA_USER);
1262 	} else
1263 		dpp->funcs->dpp_program_regamma_pwl(dpp, NULL, OPP_REGAMMA_BYPASS);
1264 
1265 	return true;
1266 }
1267 
1268 static void dcn10_pipe_control_lock(
1269 	struct dc *dc,
1270 	struct pipe_ctx *pipe,
1271 	bool lock)
1272 {
1273 	/* use TG master update lock to lock everything on the TG
1274 	 * therefore only top pipe need to lock
1275 	 */
1276 	if (pipe->top_pipe)
1277 		return;
1278 
1279 	if (dc->debug.sanity_checks)
1280 		dcn10_verify_allow_pstate_change_high(dc);
1281 
1282 	if (lock)
1283 		pipe->stream_res.tg->funcs->lock(pipe->stream_res.tg);
1284 	else
1285 		pipe->stream_res.tg->funcs->unlock(pipe->stream_res.tg);
1286 
1287 	if (dc->debug.sanity_checks)
1288 		dcn10_verify_allow_pstate_change_high(dc);
1289 }
1290 
1291 static bool wait_for_reset_trigger_to_occur(
1292 	struct dc_context *dc_ctx,
1293 	struct timing_generator *tg)
1294 {
1295 	bool rc = false;
1296 
1297 	/* To avoid endless loop we wait at most
1298 	 * frames_to_wait_on_triggered_reset frames for the reset to occur. */
1299 	const uint32_t frames_to_wait_on_triggered_reset = 10;
1300 	int i;
1301 
1302 	for (i = 0; i < frames_to_wait_on_triggered_reset; i++) {
1303 
1304 		if (!tg->funcs->is_counter_moving(tg)) {
1305 			DC_ERROR("TG counter is not moving!\n");
1306 			break;
1307 		}
1308 
1309 		if (tg->funcs->did_triggered_reset_occur(tg)) {
1310 			rc = true;
1311 			/* usually occurs at i=1 */
1312 			DC_SYNC_INFO("GSL: reset occurred at wait count: %d\n",
1313 					i);
1314 			break;
1315 		}
1316 
1317 		/* Wait for one frame. */
1318 		tg->funcs->wait_for_state(tg, CRTC_STATE_VACTIVE);
1319 		tg->funcs->wait_for_state(tg, CRTC_STATE_VBLANK);
1320 	}
1321 
1322 	if (false == rc)
1323 		DC_ERROR("GSL: Timeout on reset trigger!\n");
1324 
1325 	return rc;
1326 }
1327 
1328 static void dcn10_enable_timing_synchronization(
1329 	struct dc *dc,
1330 	int group_index,
1331 	int group_size,
1332 	struct pipe_ctx *grouped_pipes[])
1333 {
1334 	struct dc_context *dc_ctx = dc->ctx;
1335 	int i;
1336 
1337 	DC_SYNC_INFO("Setting up OTG reset trigger\n");
1338 
1339 	for (i = 1; i < group_size; i++)
1340 		grouped_pipes[i]->stream_res.tg->funcs->enable_reset_trigger(
1341 				grouped_pipes[i]->stream_res.tg,
1342 				grouped_pipes[0]->stream_res.tg->inst);
1343 
1344 	DC_SYNC_INFO("Waiting for trigger\n");
1345 
1346 	/* Need to get only check 1 pipe for having reset as all the others are
1347 	 * synchronized. Look at last pipe programmed to reset.
1348 	 */
1349 
1350 	wait_for_reset_trigger_to_occur(dc_ctx, grouped_pipes[1]->stream_res.tg);
1351 	for (i = 1; i < group_size; i++)
1352 		grouped_pipes[i]->stream_res.tg->funcs->disable_reset_trigger(
1353 				grouped_pipes[i]->stream_res.tg);
1354 
1355 	DC_SYNC_INFO("Sync complete\n");
1356 }
1357 
1358 static void dcn10_enable_per_frame_crtc_position_reset(
1359 	struct dc *dc,
1360 	int group_size,
1361 	struct pipe_ctx *grouped_pipes[])
1362 {
1363 	struct dc_context *dc_ctx = dc->ctx;
1364 	int i;
1365 
1366 	DC_SYNC_INFO("Setting up\n");
1367 	for (i = 0; i < group_size; i++)
1368 		if (grouped_pipes[i]->stream_res.tg->funcs->enable_crtc_reset)
1369 			grouped_pipes[i]->stream_res.tg->funcs->enable_crtc_reset(
1370 					grouped_pipes[i]->stream_res.tg,
1371 					grouped_pipes[i]->stream->triggered_crtc_reset.event_source->status.primary_otg_inst,
1372 					&grouped_pipes[i]->stream->triggered_crtc_reset);
1373 
1374 	DC_SYNC_INFO("Waiting for trigger\n");
1375 
1376 	for (i = 0; i < group_size; i++)
1377 		wait_for_reset_trigger_to_occur(dc_ctx, grouped_pipes[i]->stream_res.tg);
1378 
1379 	DC_SYNC_INFO("Multi-display sync is complete\n");
1380 }
1381 
1382 /*static void print_rq_dlg_ttu(
1383 		struct dc *core_dc,
1384 		struct pipe_ctx *pipe_ctx)
1385 {
1386 	DC_LOG_BANDWIDTH_CALCS(core_dc->ctx->logger,
1387 			"\n============== DML TTU Output parameters [%d] ==============\n"
1388 			"qos_level_low_wm: %d, \n"
1389 			"qos_level_high_wm: %d, \n"
1390 			"min_ttu_vblank: %d, \n"
1391 			"qos_level_flip: %d, \n"
1392 			"refcyc_per_req_delivery_l: %d, \n"
1393 			"qos_level_fixed_l: %d, \n"
1394 			"qos_ramp_disable_l: %d, \n"
1395 			"refcyc_per_req_delivery_pre_l: %d, \n"
1396 			"refcyc_per_req_delivery_c: %d, \n"
1397 			"qos_level_fixed_c: %d, \n"
1398 			"qos_ramp_disable_c: %d, \n"
1399 			"refcyc_per_req_delivery_pre_c: %d\n"
1400 			"=============================================================\n",
1401 			pipe_ctx->pipe_idx,
1402 			pipe_ctx->ttu_regs.qos_level_low_wm,
1403 			pipe_ctx->ttu_regs.qos_level_high_wm,
1404 			pipe_ctx->ttu_regs.min_ttu_vblank,
1405 			pipe_ctx->ttu_regs.qos_level_flip,
1406 			pipe_ctx->ttu_regs.refcyc_per_req_delivery_l,
1407 			pipe_ctx->ttu_regs.qos_level_fixed_l,
1408 			pipe_ctx->ttu_regs.qos_ramp_disable_l,
1409 			pipe_ctx->ttu_regs.refcyc_per_req_delivery_pre_l,
1410 			pipe_ctx->ttu_regs.refcyc_per_req_delivery_c,
1411 			pipe_ctx->ttu_regs.qos_level_fixed_c,
1412 			pipe_ctx->ttu_regs.qos_ramp_disable_c,
1413 			pipe_ctx->ttu_regs.refcyc_per_req_delivery_pre_c
1414 			);
1415 
1416 	DC_LOG_BANDWIDTH_CALCS(core_dc->ctx->logger,
1417 			"\n============== DML DLG Output parameters [%d] ==============\n"
1418 			"refcyc_h_blank_end: %d, \n"
1419 			"dlg_vblank_end: %d, \n"
1420 			"min_dst_y_next_start: %d, \n"
1421 			"refcyc_per_htotal: %d, \n"
1422 			"refcyc_x_after_scaler: %d, \n"
1423 			"dst_y_after_scaler: %d, \n"
1424 			"dst_y_prefetch: %d, \n"
1425 			"dst_y_per_vm_vblank: %d, \n"
1426 			"dst_y_per_row_vblank: %d, \n"
1427 			"ref_freq_to_pix_freq: %d, \n"
1428 			"vratio_prefetch: %d, \n"
1429 			"refcyc_per_pte_group_vblank_l: %d, \n"
1430 			"refcyc_per_meta_chunk_vblank_l: %d, \n"
1431 			"dst_y_per_pte_row_nom_l: %d, \n"
1432 			"refcyc_per_pte_group_nom_l: %d, \n",
1433 			pipe_ctx->pipe_idx,
1434 			pipe_ctx->dlg_regs.refcyc_h_blank_end,
1435 			pipe_ctx->dlg_regs.dlg_vblank_end,
1436 			pipe_ctx->dlg_regs.min_dst_y_next_start,
1437 			pipe_ctx->dlg_regs.refcyc_per_htotal,
1438 			pipe_ctx->dlg_regs.refcyc_x_after_scaler,
1439 			pipe_ctx->dlg_regs.dst_y_after_scaler,
1440 			pipe_ctx->dlg_regs.dst_y_prefetch,
1441 			pipe_ctx->dlg_regs.dst_y_per_vm_vblank,
1442 			pipe_ctx->dlg_regs.dst_y_per_row_vblank,
1443 			pipe_ctx->dlg_regs.ref_freq_to_pix_freq,
1444 			pipe_ctx->dlg_regs.vratio_prefetch,
1445 			pipe_ctx->dlg_regs.refcyc_per_pte_group_vblank_l,
1446 			pipe_ctx->dlg_regs.refcyc_per_meta_chunk_vblank_l,
1447 			pipe_ctx->dlg_regs.dst_y_per_pte_row_nom_l,
1448 			pipe_ctx->dlg_regs.refcyc_per_pte_group_nom_l
1449 			);
1450 
1451 	DC_LOG_BANDWIDTH_CALCS(core_dc->ctx->logger,
1452 			"\ndst_y_per_meta_row_nom_l: %d, \n"
1453 			"refcyc_per_meta_chunk_nom_l: %d, \n"
1454 			"refcyc_per_line_delivery_pre_l: %d, \n"
1455 			"refcyc_per_line_delivery_l: %d, \n"
1456 			"vratio_prefetch_c: %d, \n"
1457 			"refcyc_per_pte_group_vblank_c: %d, \n"
1458 			"refcyc_per_meta_chunk_vblank_c: %d, \n"
1459 			"dst_y_per_pte_row_nom_c: %d, \n"
1460 			"refcyc_per_pte_group_nom_c: %d, \n"
1461 			"dst_y_per_meta_row_nom_c: %d, \n"
1462 			"refcyc_per_meta_chunk_nom_c: %d, \n"
1463 			"refcyc_per_line_delivery_pre_c: %d, \n"
1464 			"refcyc_per_line_delivery_c: %d \n"
1465 			"========================================================\n",
1466 			pipe_ctx->dlg_regs.dst_y_per_meta_row_nom_l,
1467 			pipe_ctx->dlg_regs.refcyc_per_meta_chunk_nom_l,
1468 			pipe_ctx->dlg_regs.refcyc_per_line_delivery_pre_l,
1469 			pipe_ctx->dlg_regs.refcyc_per_line_delivery_l,
1470 			pipe_ctx->dlg_regs.vratio_prefetch_c,
1471 			pipe_ctx->dlg_regs.refcyc_per_pte_group_vblank_c,
1472 			pipe_ctx->dlg_regs.refcyc_per_meta_chunk_vblank_c,
1473 			pipe_ctx->dlg_regs.dst_y_per_pte_row_nom_c,
1474 			pipe_ctx->dlg_regs.refcyc_per_pte_group_nom_c,
1475 			pipe_ctx->dlg_regs.dst_y_per_meta_row_nom_c,
1476 			pipe_ctx->dlg_regs.refcyc_per_meta_chunk_nom_c,
1477 			pipe_ctx->dlg_regs.refcyc_per_line_delivery_pre_c,
1478 			pipe_ctx->dlg_regs.refcyc_per_line_delivery_c
1479 			);
1480 
1481 	DC_LOG_BANDWIDTH_CALCS(core_dc->ctx->logger,
1482 			"\n============== DML RQ Output parameters [%d] ==============\n"
1483 			"chunk_size: %d \n"
1484 			"min_chunk_size: %d \n"
1485 			"meta_chunk_size: %d \n"
1486 			"min_meta_chunk_size: %d \n"
1487 			"dpte_group_size: %d \n"
1488 			"mpte_group_size: %d \n"
1489 			"swath_height: %d \n"
1490 			"pte_row_height_linear: %d \n"
1491 			"========================================================\n",
1492 			pipe_ctx->pipe_idx,
1493 			pipe_ctx->rq_regs.rq_regs_l.chunk_size,
1494 			pipe_ctx->rq_regs.rq_regs_l.min_chunk_size,
1495 			pipe_ctx->rq_regs.rq_regs_l.meta_chunk_size,
1496 			pipe_ctx->rq_regs.rq_regs_l.min_meta_chunk_size,
1497 			pipe_ctx->rq_regs.rq_regs_l.dpte_group_size,
1498 			pipe_ctx->rq_regs.rq_regs_l.mpte_group_size,
1499 			pipe_ctx->rq_regs.rq_regs_l.swath_height,
1500 			pipe_ctx->rq_regs.rq_regs_l.pte_row_height_linear
1501 			);
1502 }
1503 */
1504 
1505 static void mmhub_read_vm_system_aperture_settings(struct dcn10_hubp *hubp1,
1506 		struct vm_system_aperture_param *apt,
1507 		struct dce_hwseq *hws)
1508 {
1509 	PHYSICAL_ADDRESS_LOC physical_page_number;
1510 	uint32_t logical_addr_low;
1511 	uint32_t logical_addr_high;
1512 
1513 	REG_GET(MC_VM_SYSTEM_APERTURE_DEFAULT_ADDR_MSB,
1514 			PHYSICAL_PAGE_NUMBER_MSB, &physical_page_number.high_part);
1515 	REG_GET(MC_VM_SYSTEM_APERTURE_DEFAULT_ADDR_LSB,
1516 			PHYSICAL_PAGE_NUMBER_LSB, &physical_page_number.low_part);
1517 
1518 	REG_GET(MC_VM_SYSTEM_APERTURE_LOW_ADDR,
1519 			LOGICAL_ADDR, &logical_addr_low);
1520 
1521 	REG_GET(MC_VM_SYSTEM_APERTURE_HIGH_ADDR,
1522 			LOGICAL_ADDR, &logical_addr_high);
1523 
1524 	apt->sys_default.quad_part =  physical_page_number.quad_part << 12;
1525 	apt->sys_low.quad_part =  (int64_t)logical_addr_low << 18;
1526 	apt->sys_high.quad_part =  (int64_t)logical_addr_high << 18;
1527 }
1528 
1529 /* Temporary read settings, future will get values from kmd directly */
1530 static void mmhub_read_vm_context0_settings(struct dcn10_hubp *hubp1,
1531 		struct vm_context0_param *vm0,
1532 		struct dce_hwseq *hws)
1533 {
1534 	PHYSICAL_ADDRESS_LOC fb_base;
1535 	PHYSICAL_ADDRESS_LOC fb_offset;
1536 	uint32_t fb_base_value;
1537 	uint32_t fb_offset_value;
1538 
1539 	REG_GET(DCHUBBUB_SDPIF_FB_BASE, SDPIF_FB_BASE, &fb_base_value);
1540 	REG_GET(DCHUBBUB_SDPIF_FB_OFFSET, SDPIF_FB_OFFSET, &fb_offset_value);
1541 
1542 	REG_GET(VM_CONTEXT0_PAGE_TABLE_BASE_ADDR_HI32,
1543 			PAGE_DIRECTORY_ENTRY_HI32, &vm0->pte_base.high_part);
1544 	REG_GET(VM_CONTEXT0_PAGE_TABLE_BASE_ADDR_LO32,
1545 			PAGE_DIRECTORY_ENTRY_LO32, &vm0->pte_base.low_part);
1546 
1547 	REG_GET(VM_CONTEXT0_PAGE_TABLE_START_ADDR_HI32,
1548 			LOGICAL_PAGE_NUMBER_HI4, &vm0->pte_start.high_part);
1549 	REG_GET(VM_CONTEXT0_PAGE_TABLE_START_ADDR_LO32,
1550 			LOGICAL_PAGE_NUMBER_LO32, &vm0->pte_start.low_part);
1551 
1552 	REG_GET(VM_CONTEXT0_PAGE_TABLE_END_ADDR_HI32,
1553 			LOGICAL_PAGE_NUMBER_HI4, &vm0->pte_end.high_part);
1554 	REG_GET(VM_CONTEXT0_PAGE_TABLE_END_ADDR_LO32,
1555 			LOGICAL_PAGE_NUMBER_LO32, &vm0->pte_end.low_part);
1556 
1557 	REG_GET(VM_L2_PROTECTION_FAULT_DEFAULT_ADDR_HI32,
1558 			PHYSICAL_PAGE_ADDR_HI4, &vm0->fault_default.high_part);
1559 	REG_GET(VM_L2_PROTECTION_FAULT_DEFAULT_ADDR_LO32,
1560 			PHYSICAL_PAGE_ADDR_LO32, &vm0->fault_default.low_part);
1561 
1562 	/*
1563 	 * The values in VM_CONTEXT0_PAGE_TABLE_BASE_ADDR is in UMA space.
1564 	 * Therefore we need to do
1565 	 * DCN_VM_CONTEXT0_PAGE_TABLE_BASE_ADDR = VM_CONTEXT0_PAGE_TABLE_BASE_ADDR
1566 	 * - DCHUBBUB_SDPIF_FB_OFFSET + DCHUBBUB_SDPIF_FB_BASE
1567 	 */
1568 	fb_base.quad_part = (uint64_t)fb_base_value << 24;
1569 	fb_offset.quad_part = (uint64_t)fb_offset_value << 24;
1570 	vm0->pte_base.quad_part += fb_base.quad_part;
1571 	vm0->pte_base.quad_part -= fb_offset.quad_part;
1572 }
1573 
1574 
1575 static void dcn10_program_pte_vm(struct dce_hwseq *hws, struct hubp *hubp)
1576 {
1577 	struct dcn10_hubp *hubp1 = TO_DCN10_HUBP(hubp);
1578 	struct vm_system_aperture_param apt = { {{ 0 } } };
1579 	struct vm_context0_param vm0 = { { { 0 } } };
1580 
1581 	mmhub_read_vm_system_aperture_settings(hubp1, &apt, hws);
1582 	mmhub_read_vm_context0_settings(hubp1, &vm0, hws);
1583 
1584 	hubp->funcs->hubp_set_vm_system_aperture_settings(hubp, &apt);
1585 	hubp->funcs->hubp_set_vm_context0_settings(hubp, &vm0);
1586 }
1587 
1588 static void dcn10_enable_plane(
1589 	struct dc *dc,
1590 	struct pipe_ctx *pipe_ctx,
1591 	struct dc_state *context)
1592 {
1593 	struct dce_hwseq *hws = dc->hwseq;
1594 
1595 	if (dc->debug.sanity_checks) {
1596 		dcn10_verify_allow_pstate_change_high(dc);
1597 	}
1598 
1599 	undo_DEGVIDCN10_253_wa(dc);
1600 
1601 	power_on_plane(dc->hwseq,
1602 		pipe_ctx->plane_res.hubp->inst);
1603 
1604 	/* enable DCFCLK current DCHUB */
1605 	pipe_ctx->plane_res.hubp->funcs->hubp_clk_cntl(pipe_ctx->plane_res.hubp, true);
1606 
1607 	/* make sure OPP_PIPE_CLOCK_EN = 1 */
1608 	pipe_ctx->stream_res.opp->funcs->opp_pipe_clock_control(
1609 			pipe_ctx->stream_res.opp,
1610 			true);
1611 
1612 /* TODO: enable/disable in dm as per update type.
1613 	if (plane_state) {
1614 		DC_LOG_DC(dc->ctx->logger,
1615 				"Pipe:%d 0x%x: addr hi:0x%x, "
1616 				"addr low:0x%x, "
1617 				"src: %d, %d, %d,"
1618 				" %d; dst: %d, %d, %d, %d;\n",
1619 				pipe_ctx->pipe_idx,
1620 				plane_state,
1621 				plane_state->address.grph.addr.high_part,
1622 				plane_state->address.grph.addr.low_part,
1623 				plane_state->src_rect.x,
1624 				plane_state->src_rect.y,
1625 				plane_state->src_rect.width,
1626 				plane_state->src_rect.height,
1627 				plane_state->dst_rect.x,
1628 				plane_state->dst_rect.y,
1629 				plane_state->dst_rect.width,
1630 				plane_state->dst_rect.height);
1631 
1632 		DC_LOG_DC(dc->ctx->logger,
1633 				"Pipe %d: width, height, x, y         format:%d\n"
1634 				"viewport:%d, %d, %d, %d\n"
1635 				"recout:  %d, %d, %d, %d\n",
1636 				pipe_ctx->pipe_idx,
1637 				plane_state->format,
1638 				pipe_ctx->plane_res.scl_data.viewport.width,
1639 				pipe_ctx->plane_res.scl_data.viewport.height,
1640 				pipe_ctx->plane_res.scl_data.viewport.x,
1641 				pipe_ctx->plane_res.scl_data.viewport.y,
1642 				pipe_ctx->plane_res.scl_data.recout.width,
1643 				pipe_ctx->plane_res.scl_data.recout.height,
1644 				pipe_ctx->plane_res.scl_data.recout.x,
1645 				pipe_ctx->plane_res.scl_data.recout.y);
1646 		print_rq_dlg_ttu(dc, pipe_ctx);
1647 	}
1648 */
1649 	if (dc->config.gpu_vm_support)
1650 		dcn10_program_pte_vm(hws, pipe_ctx->plane_res.hubp);
1651 
1652 	if (dc->debug.sanity_checks) {
1653 		dcn10_verify_allow_pstate_change_high(dc);
1654 	}
1655 }
1656 
1657 static void program_gamut_remap(struct pipe_ctx *pipe_ctx)
1658 {
1659 	int i = 0;
1660 	struct dpp_grph_csc_adjustment adjust;
1661 	memset(&adjust, 0, sizeof(adjust));
1662 	adjust.gamut_adjust_type = GRAPHICS_GAMUT_ADJUST_TYPE_BYPASS;
1663 
1664 
1665 	if (pipe_ctx->stream->gamut_remap_matrix.enable_remap == true) {
1666 		adjust.gamut_adjust_type = GRAPHICS_GAMUT_ADJUST_TYPE_SW;
1667 		for (i = 0; i < CSC_TEMPERATURE_MATRIX_SIZE; i++)
1668 			adjust.temperature_matrix[i] =
1669 				pipe_ctx->stream->gamut_remap_matrix.matrix[i];
1670 	}
1671 
1672 	pipe_ctx->plane_res.dpp->funcs->dpp_set_gamut_remap(pipe_ctx->plane_res.dpp, &adjust);
1673 }
1674 
1675 
1676 static void program_csc_matrix(struct pipe_ctx *pipe_ctx,
1677 		enum dc_color_space colorspace,
1678 		uint16_t *matrix)
1679 {
1680 	if (pipe_ctx->stream->csc_color_matrix.enable_adjustment == true) {
1681 			if (pipe_ctx->plane_res.dpp->funcs->dpp_set_csc_adjustment != NULL)
1682 				pipe_ctx->plane_res.dpp->funcs->dpp_set_csc_adjustment(pipe_ctx->plane_res.dpp, matrix);
1683 	} else {
1684 		if (pipe_ctx->plane_res.dpp->funcs->dpp_set_csc_default != NULL)
1685 			pipe_ctx->plane_res.dpp->funcs->dpp_set_csc_default(pipe_ctx->plane_res.dpp, colorspace);
1686 	}
1687 }
1688 
1689 static void dcn10_program_output_csc(struct dc *dc,
1690 		struct pipe_ctx *pipe_ctx,
1691 		enum dc_color_space colorspace,
1692 		uint16_t *matrix,
1693 		int opp_id)
1694 {
1695 	if (pipe_ctx->plane_res.dpp->funcs->dpp_set_csc_adjustment != NULL)
1696 		program_csc_matrix(pipe_ctx,
1697 				colorspace,
1698 				matrix);
1699 }
1700 
1701 static bool is_lower_pipe_tree_visible(struct pipe_ctx *pipe_ctx)
1702 {
1703 	if (pipe_ctx->plane_state->visible)
1704 		return true;
1705 	if (pipe_ctx->bottom_pipe && is_lower_pipe_tree_visible(pipe_ctx->bottom_pipe))
1706 		return true;
1707 	return false;
1708 }
1709 
1710 static bool is_upper_pipe_tree_visible(struct pipe_ctx *pipe_ctx)
1711 {
1712 	if (pipe_ctx->plane_state->visible)
1713 		return true;
1714 	if (pipe_ctx->top_pipe && is_upper_pipe_tree_visible(pipe_ctx->top_pipe))
1715 		return true;
1716 	return false;
1717 }
1718 
1719 static bool is_pipe_tree_visible(struct pipe_ctx *pipe_ctx)
1720 {
1721 	if (pipe_ctx->plane_state->visible)
1722 		return true;
1723 	if (pipe_ctx->top_pipe && is_upper_pipe_tree_visible(pipe_ctx->top_pipe))
1724 		return true;
1725 	if (pipe_ctx->bottom_pipe && is_lower_pipe_tree_visible(pipe_ctx->bottom_pipe))
1726 		return true;
1727 	return false;
1728 }
1729 
1730 bool is_rgb_cspace(enum dc_color_space output_color_space)
1731 {
1732 	switch (output_color_space) {
1733 	case COLOR_SPACE_SRGB:
1734 	case COLOR_SPACE_SRGB_LIMITED:
1735 	case COLOR_SPACE_2020_RGB_FULLRANGE:
1736 	case COLOR_SPACE_2020_RGB_LIMITEDRANGE:
1737 	case COLOR_SPACE_ADOBERGB:
1738 		return true;
1739 	case COLOR_SPACE_YCBCR601:
1740 	case COLOR_SPACE_YCBCR709:
1741 	case COLOR_SPACE_YCBCR601_LIMITED:
1742 	case COLOR_SPACE_YCBCR709_LIMITED:
1743 	case COLOR_SPACE_2020_YCBCR:
1744 		return false;
1745 	default:
1746 		/* Add a case to switch */
1747 		BREAK_TO_DEBUGGER();
1748 		return false;
1749 	}
1750 }
1751 
1752 static void dcn10_get_surface_visual_confirm_color(
1753 		const struct pipe_ctx *pipe_ctx,
1754 		struct tg_color *color)
1755 {
1756 	uint32_t color_value = MAX_TG_COLOR_VALUE;
1757 
1758 	switch (pipe_ctx->plane_res.scl_data.format) {
1759 	case PIXEL_FORMAT_ARGB8888:
1760 		/* set boarder color to red */
1761 		color->color_r_cr = color_value;
1762 		break;
1763 
1764 	case PIXEL_FORMAT_ARGB2101010:
1765 		/* set boarder color to blue */
1766 		color->color_b_cb = color_value;
1767 		break;
1768 	case PIXEL_FORMAT_420BPP8:
1769 		/* set boarder color to green */
1770 		color->color_g_y = color_value;
1771 		break;
1772 	case PIXEL_FORMAT_420BPP10:
1773 		/* set boarder color to yellow */
1774 		color->color_g_y = color_value;
1775 		color->color_r_cr = color_value;
1776 		break;
1777 	case PIXEL_FORMAT_FP16:
1778 		/* set boarder color to white */
1779 		color->color_r_cr = color_value;
1780 		color->color_b_cb = color_value;
1781 		color->color_g_y = color_value;
1782 		break;
1783 	default:
1784 		break;
1785 	}
1786 }
1787 
1788 static void dcn10_get_hdr_visual_confirm_color(
1789 		struct pipe_ctx *pipe_ctx,
1790 		struct tg_color *color)
1791 {
1792 	uint32_t color_value = MAX_TG_COLOR_VALUE;
1793 
1794 	// Determine the overscan color based on the top-most (desktop) plane's context
1795 	struct pipe_ctx *top_pipe_ctx  = pipe_ctx;
1796 
1797 	while (top_pipe_ctx->top_pipe != NULL)
1798 		top_pipe_ctx = top_pipe_ctx->top_pipe;
1799 
1800 	switch (top_pipe_ctx->plane_res.scl_data.format) {
1801 	case PIXEL_FORMAT_ARGB2101010:
1802 		if (top_pipe_ctx->stream->out_transfer_func->tf == TRANSFER_FUNCTION_UNITY) {
1803 			/* HDR10, ARGB2101010 - set boarder color to red */
1804 			color->color_r_cr = color_value;
1805 		}
1806 		break;
1807 	case PIXEL_FORMAT_FP16:
1808 		if (top_pipe_ctx->stream->out_transfer_func->tf == TRANSFER_FUNCTION_PQ) {
1809 			/* HDR10, FP16 - set boarder color to blue */
1810 			color->color_b_cb = color_value;
1811 		} else if (top_pipe_ctx->stream->out_transfer_func->tf == TRANSFER_FUNCTION_GAMMA22) {
1812 			/* FreeSync 2 HDR - set boarder color to green */
1813 			color->color_g_y = color_value;
1814 		}
1815 		break;
1816 	default:
1817 		/* SDR - set boarder color to Gray */
1818 		color->color_r_cr = color_value/2;
1819 		color->color_b_cb = color_value/2;
1820 		color->color_g_y = color_value/2;
1821 		break;
1822 	}
1823 }
1824 
1825 static uint16_t fixed_point_to_int_frac(
1826 	struct fixed31_32 arg,
1827 	uint8_t integer_bits,
1828 	uint8_t fractional_bits)
1829 {
1830 	int32_t numerator;
1831 	int32_t divisor = 1 << fractional_bits;
1832 
1833 	uint16_t result;
1834 
1835 	uint16_t d = (uint16_t)dc_fixpt_floor(
1836 		dc_fixpt_abs(
1837 			arg));
1838 
1839 	if (d <= (uint16_t)(1 << integer_bits) - (1 / (uint16_t)divisor))
1840 		numerator = (uint16_t)dc_fixpt_floor(
1841 			dc_fixpt_mul_int(
1842 				arg,
1843 				divisor));
1844 	else {
1845 		numerator = dc_fixpt_floor(
1846 			dc_fixpt_sub(
1847 				dc_fixpt_from_int(
1848 					1LL << integer_bits),
1849 				dc_fixpt_recip(
1850 					dc_fixpt_from_int(
1851 						divisor))));
1852 	}
1853 
1854 	if (numerator >= 0)
1855 		result = (uint16_t)numerator;
1856 	else
1857 		result = (uint16_t)(
1858 		(1 << (integer_bits + fractional_bits + 1)) + numerator);
1859 
1860 	if ((result != 0) && dc_fixpt_lt(
1861 		arg, dc_fixpt_zero))
1862 		result |= 1 << (integer_bits + fractional_bits);
1863 
1864 	return result;
1865 }
1866 
1867 static
1868 void build_prescale_params(struct  dc_bias_and_scale *bias_and_scale,
1869 		const struct dc_plane_state *plane_state)
1870 {
1871 	if (plane_state->format >= SURFACE_PIXEL_FORMAT_VIDEO_BEGIN
1872 			&& plane_state->format != SURFACE_PIXEL_FORMAT_INVALID
1873 			&& plane_state->input_csc_color_matrix.enable_adjustment
1874 			&& plane_state->coeff_reduction_factor.value != 0) {
1875 		bias_and_scale->scale_blue = fixed_point_to_int_frac(
1876 			dc_fixpt_mul(plane_state->coeff_reduction_factor,
1877 					dc_fixpt_from_fraction(256, 255)),
1878 				2,
1879 				13);
1880 		bias_and_scale->scale_red = bias_and_scale->scale_blue;
1881 		bias_and_scale->scale_green = bias_and_scale->scale_blue;
1882 	} else {
1883 		bias_and_scale->scale_blue = 0x2000;
1884 		bias_and_scale->scale_red = 0x2000;
1885 		bias_and_scale->scale_green = 0x2000;
1886 	}
1887 }
1888 
1889 static void update_dpp(struct dpp *dpp, struct dc_plane_state *plane_state)
1890 {
1891 	struct dc_bias_and_scale bns_params = {0};
1892 
1893 	// program the input csc
1894 	dpp->funcs->dpp_setup(dpp,
1895 			plane_state->format,
1896 			EXPANSION_MODE_ZERO,
1897 			plane_state->input_csc_color_matrix,
1898 			plane_state->color_space);
1899 
1900 	//set scale and bias registers
1901 	build_prescale_params(&bns_params, plane_state);
1902 	if (dpp->funcs->dpp_program_bias_and_scale)
1903 		dpp->funcs->dpp_program_bias_and_scale(dpp, &bns_params);
1904 }
1905 
1906 static void dcn10_update_mpcc(struct dc *dc, struct pipe_ctx *pipe_ctx)
1907 {
1908 	struct hubp *hubp = pipe_ctx->plane_res.hubp;
1909 	struct mpcc_blnd_cfg blnd_cfg = {0};
1910 	bool per_pixel_alpha = pipe_ctx->plane_state->per_pixel_alpha && pipe_ctx->bottom_pipe;
1911 	int mpcc_id;
1912 	struct mpcc *new_mpcc;
1913 	struct mpc *mpc = dc->res_pool->mpc;
1914 	struct mpc_tree *mpc_tree_params = &(pipe_ctx->stream_res.opp->mpc_tree_params);
1915 
1916 
1917 
1918 	/* TODO: proper fix once fpga works */
1919 
1920 	if (dc->debug.visual_confirm == VISUAL_CONFIRM_HDR) {
1921 		dcn10_get_hdr_visual_confirm_color(
1922 				pipe_ctx, &blnd_cfg.black_color);
1923 	} else if (dc->debug.visual_confirm == VISUAL_CONFIRM_SURFACE) {
1924 		dcn10_get_surface_visual_confirm_color(
1925 				pipe_ctx, &blnd_cfg.black_color);
1926 	} else {
1927 		color_space_to_black_color(
1928 				dc, pipe_ctx->stream->output_color_space,
1929 				&blnd_cfg.black_color);
1930 	}
1931 
1932 	if (per_pixel_alpha)
1933 		blnd_cfg.alpha_mode = MPCC_ALPHA_BLEND_MODE_PER_PIXEL_ALPHA;
1934 	else
1935 		blnd_cfg.alpha_mode = MPCC_ALPHA_BLEND_MODE_GLOBAL_ALPHA;
1936 
1937 	blnd_cfg.overlap_only = false;
1938 	blnd_cfg.global_alpha = 0xff;
1939 	blnd_cfg.global_gain = 0xff;
1940 
1941 	/* DCN1.0 has output CM before MPC which seems to screw with
1942 	 * pre-multiplied alpha.
1943 	 */
1944 	blnd_cfg.pre_multiplied_alpha = is_rgb_cspace(
1945 			pipe_ctx->stream->output_color_space)
1946 					&& per_pixel_alpha;
1947 
1948 
1949 	/*
1950 	 * TODO: remove hack
1951 	 * Note: currently there is a bug in init_hw such that
1952 	 * on resume from hibernate, BIOS sets up MPCC0, and
1953 	 * we do mpcc_remove but the mpcc cannot go to idle
1954 	 * after remove. This cause us to pick mpcc1 here,
1955 	 * which causes a pstate hang for yet unknown reason.
1956 	 */
1957 	mpcc_id = hubp->inst;
1958 
1959 	/* If there is no full update, don't need to touch MPC tree*/
1960 	if (!pipe_ctx->plane_state->update_flags.bits.full_update) {
1961 		mpc->funcs->update_blending(mpc, &blnd_cfg, mpcc_id);
1962 		return;
1963 	}
1964 
1965 	/* check if this MPCC is already being used */
1966 	new_mpcc = mpc->funcs->get_mpcc_for_dpp(mpc_tree_params, mpcc_id);
1967 	/* remove MPCC if being used */
1968 	if (new_mpcc != NULL)
1969 		mpc->funcs->remove_mpcc(mpc, mpc_tree_params, new_mpcc);
1970 	else
1971 		if (dc->debug.sanity_checks)
1972 			mpc->funcs->assert_mpcc_idle_before_connect(
1973 					dc->res_pool->mpc, mpcc_id);
1974 
1975 	/* Call MPC to insert new plane */
1976 	new_mpcc = mpc->funcs->insert_plane(dc->res_pool->mpc,
1977 			mpc_tree_params,
1978 			&blnd_cfg,
1979 			NULL,
1980 			NULL,
1981 			hubp->inst,
1982 			mpcc_id);
1983 
1984 	ASSERT(new_mpcc != NULL);
1985 
1986 	hubp->opp_id = pipe_ctx->stream_res.opp->inst;
1987 	hubp->mpcc_id = mpcc_id;
1988 }
1989 
1990 static void update_scaler(struct pipe_ctx *pipe_ctx)
1991 {
1992 	bool per_pixel_alpha =
1993 			pipe_ctx->plane_state->per_pixel_alpha && pipe_ctx->bottom_pipe;
1994 
1995 	/* TODO: proper fix once fpga works */
1996 
1997 	pipe_ctx->plane_res.scl_data.lb_params.alpha_en = per_pixel_alpha;
1998 	pipe_ctx->plane_res.scl_data.lb_params.depth = LB_PIXEL_DEPTH_30BPP;
1999 	/* scaler configuration */
2000 	pipe_ctx->plane_res.dpp->funcs->dpp_set_scaler(
2001 			pipe_ctx->plane_res.dpp, &pipe_ctx->plane_res.scl_data);
2002 }
2003 
2004 static void update_dchubp_dpp(
2005 	struct dc *dc,
2006 	struct pipe_ctx *pipe_ctx,
2007 	struct dc_state *context)
2008 {
2009 	struct hubp *hubp = pipe_ctx->plane_res.hubp;
2010 	struct dpp *dpp = pipe_ctx->plane_res.dpp;
2011 	struct dc_plane_state *plane_state = pipe_ctx->plane_state;
2012 	union plane_size size = plane_state->plane_size;
2013 
2014 	/* depends on DML calculation, DPP clock value may change dynamically */
2015 	/* If request max dpp clk is lower than current dispclk, no need to
2016 	 * divided by 2
2017 	 */
2018 	if (plane_state->update_flags.bits.full_update) {
2019 		bool should_divided_by_2 = context->bw.dcn.clk.dppclk_khz <=
2020 				dc->res_pool->dccg->clks.dispclk_khz / 2;
2021 
2022 		dpp->funcs->dpp_dppclk_control(
2023 				dpp,
2024 				should_divided_by_2,
2025 				true);
2026 
2027 		dc->res_pool->dccg->clks.dppclk_khz = should_divided_by_2 ?
2028 						dc->res_pool->dccg->clks.dispclk_khz / 2 :
2029 							dc->res_pool->dccg->clks.dispclk_khz;
2030 	}
2031 
2032 	/* TODO: Need input parameter to tell current DCHUB pipe tie to which OTG
2033 	 * VTG is within DCHUBBUB which is commond block share by each pipe HUBP.
2034 	 * VTG is 1:1 mapping with OTG. Each pipe HUBP will select which VTG
2035 	 */
2036 	if (plane_state->update_flags.bits.full_update) {
2037 		hubp->funcs->hubp_vtg_sel(hubp, pipe_ctx->stream_res.tg->inst);
2038 
2039 		hubp->funcs->hubp_setup(
2040 			hubp,
2041 			&pipe_ctx->dlg_regs,
2042 			&pipe_ctx->ttu_regs,
2043 			&pipe_ctx->rq_regs,
2044 			&pipe_ctx->pipe_dlg_param);
2045 	}
2046 
2047 	size.grph.surface_size = pipe_ctx->plane_res.scl_data.viewport;
2048 
2049 	if (plane_state->update_flags.bits.full_update ||
2050 		plane_state->update_flags.bits.bpp_change)
2051 		update_dpp(dpp, plane_state);
2052 
2053 	if (plane_state->update_flags.bits.full_update ||
2054 		plane_state->update_flags.bits.per_pixel_alpha_change)
2055 		dc->hwss.update_mpcc(dc, pipe_ctx);
2056 
2057 	if (plane_state->update_flags.bits.full_update ||
2058 		plane_state->update_flags.bits.per_pixel_alpha_change ||
2059 		plane_state->update_flags.bits.scaling_change ||
2060 		plane_state->update_flags.bits.position_change) {
2061 		update_scaler(pipe_ctx);
2062 	}
2063 
2064 	if (plane_state->update_flags.bits.full_update ||
2065 		plane_state->update_flags.bits.scaling_change ||
2066 		plane_state->update_flags.bits.position_change) {
2067 		hubp->funcs->mem_program_viewport(
2068 			hubp,
2069 			&pipe_ctx->plane_res.scl_data.viewport,
2070 			&pipe_ctx->plane_res.scl_data.viewport_c);
2071 	}
2072 
2073 	if (pipe_ctx->stream->cursor_attributes.address.quad_part != 0) {
2074 		dc->hwss.set_cursor_position(pipe_ctx);
2075 		dc->hwss.set_cursor_attribute(pipe_ctx);
2076 	}
2077 
2078 	if (plane_state->update_flags.bits.full_update) {
2079 		/*gamut remap*/
2080 		program_gamut_remap(pipe_ctx);
2081 
2082 		dc->hwss.program_output_csc(dc,
2083 				pipe_ctx,
2084 				pipe_ctx->stream->output_color_space,
2085 				pipe_ctx->stream->csc_color_matrix.matrix,
2086 				hubp->opp_id);
2087 	}
2088 
2089 	if (plane_state->update_flags.bits.full_update ||
2090 		plane_state->update_flags.bits.pixel_format_change ||
2091 		plane_state->update_flags.bits.horizontal_mirror_change ||
2092 		plane_state->update_flags.bits.rotation_change ||
2093 		plane_state->update_flags.bits.swizzle_change ||
2094 		plane_state->update_flags.bits.dcc_change ||
2095 		plane_state->update_flags.bits.bpp_change ||
2096 		plane_state->update_flags.bits.scaling_change) {
2097 		hubp->funcs->hubp_program_surface_config(
2098 			hubp,
2099 			plane_state->format,
2100 			&plane_state->tiling_info,
2101 			&size,
2102 			plane_state->rotation,
2103 			&plane_state->dcc,
2104 			plane_state->horizontal_mirror);
2105 	}
2106 
2107 	hubp->power_gated = false;
2108 
2109 	dc->hwss.update_plane_addr(dc, pipe_ctx);
2110 
2111 	if (is_pipe_tree_visible(pipe_ctx))
2112 		hubp->funcs->set_blank(hubp, false);
2113 }
2114 
2115 static void dcn10_blank_pixel_data(
2116 		struct dc *dc,
2117 		struct pipe_ctx *pipe_ctx,
2118 		bool blank)
2119 {
2120 	enum dc_color_space color_space;
2121 	struct tg_color black_color = {0};
2122 	struct stream_resource *stream_res = &pipe_ctx->stream_res;
2123 	struct dc_stream_state *stream = pipe_ctx->stream;
2124 
2125 	/* program otg blank color */
2126 	color_space = stream->output_color_space;
2127 	color_space_to_black_color(dc, color_space, &black_color);
2128 
2129 	/*
2130 	 * The way 420 is packed, 2 channels carry Y component, 1 channel
2131 	 * alternate between Cb and Cr, so both channels need the pixel
2132 	 * value for Y
2133 	 */
2134 	if (stream->timing.pixel_encoding == PIXEL_ENCODING_YCBCR420)
2135 		black_color.color_r_cr = black_color.color_g_y;
2136 
2137 
2138 	if (stream_res->tg->funcs->set_blank_color)
2139 		stream_res->tg->funcs->set_blank_color(
2140 				stream_res->tg,
2141 				&black_color);
2142 
2143 	if (!blank) {
2144 		if (stream_res->tg->funcs->set_blank)
2145 			stream_res->tg->funcs->set_blank(stream_res->tg, blank);
2146 		if (stream_res->abm)
2147 			stream_res->abm->funcs->set_abm_level(stream_res->abm, stream->abm_level);
2148 	} else if (blank) {
2149 		if (stream_res->abm)
2150 			stream_res->abm->funcs->set_abm_immediate_disable(stream_res->abm);
2151 		if (stream_res->tg->funcs->set_blank)
2152 			stream_res->tg->funcs->set_blank(stream_res->tg, blank);
2153 	}
2154 }
2155 
2156 static void set_hdr_multiplier(struct pipe_ctx *pipe_ctx)
2157 {
2158 	struct fixed31_32 multiplier = dc_fixpt_from_fraction(
2159 			pipe_ctx->plane_state->sdr_white_level, 80);
2160 	uint32_t hw_mult = 0x1f000; // 1.0 default multiplier
2161 	struct custom_float_format fmt;
2162 
2163 	fmt.exponenta_bits = 6;
2164 	fmt.mantissa_bits = 12;
2165 	fmt.sign = true;
2166 
2167 	if (pipe_ctx->plane_state->sdr_white_level > 80)
2168 		convert_to_custom_float_format(multiplier, &fmt, &hw_mult);
2169 
2170 	pipe_ctx->plane_res.dpp->funcs->dpp_set_hdr_multiplier(
2171 			pipe_ctx->plane_res.dpp, hw_mult);
2172 }
2173 
2174 void dcn10_program_pipe(
2175 		struct dc *dc,
2176 		struct pipe_ctx *pipe_ctx,
2177 		struct dc_state *context)
2178 {
2179 	if (pipe_ctx->plane_state->update_flags.bits.full_update)
2180 		dcn10_enable_plane(dc, pipe_ctx, context);
2181 
2182 	update_dchubp_dpp(dc, pipe_ctx, context);
2183 
2184 	set_hdr_multiplier(pipe_ctx);
2185 
2186 	if (pipe_ctx->plane_state->update_flags.bits.full_update ||
2187 			pipe_ctx->plane_state->update_flags.bits.in_transfer_func_change ||
2188 			pipe_ctx->plane_state->update_flags.bits.gamma_change)
2189 		dc->hwss.set_input_transfer_func(pipe_ctx, pipe_ctx->plane_state);
2190 
2191 	/* dcn10_translate_regamma_to_hw_format takes 750us to finish
2192 	 * only do gamma programming for full update.
2193 	 * TODO: This can be further optimized/cleaned up
2194 	 * Always call this for now since it does memcmp inside before
2195 	 * doing heavy calculation and programming
2196 	 */
2197 	if (pipe_ctx->plane_state->update_flags.bits.full_update)
2198 		dc->hwss.set_output_transfer_func(pipe_ctx, pipe_ctx->stream);
2199 }
2200 
2201 static void program_all_pipe_in_tree(
2202 		struct dc *dc,
2203 		struct pipe_ctx *pipe_ctx,
2204 		struct dc_state *context)
2205 {
2206 	if (pipe_ctx->top_pipe == NULL) {
2207 		bool blank = !is_pipe_tree_visible(pipe_ctx);
2208 
2209 		pipe_ctx->stream_res.tg->dlg_otg_param.vready_offset = pipe_ctx->pipe_dlg_param.vready_offset;
2210 		pipe_ctx->stream_res.tg->dlg_otg_param.vstartup_start = pipe_ctx->pipe_dlg_param.vstartup_start;
2211 		pipe_ctx->stream_res.tg->dlg_otg_param.vupdate_offset = pipe_ctx->pipe_dlg_param.vupdate_offset;
2212 		pipe_ctx->stream_res.tg->dlg_otg_param.vupdate_width = pipe_ctx->pipe_dlg_param.vupdate_width;
2213 		pipe_ctx->stream_res.tg->dlg_otg_param.signal =  pipe_ctx->stream->signal;
2214 
2215 		pipe_ctx->stream_res.tg->funcs->program_global_sync(
2216 				pipe_ctx->stream_res.tg);
2217 
2218 		dc->hwss.blank_pixel_data(dc, pipe_ctx, blank);
2219 
2220 	}
2221 
2222 	if (pipe_ctx->plane_state != NULL) {
2223 		dcn10_program_pipe(dc, pipe_ctx, context);
2224 	}
2225 
2226 	if (pipe_ctx->bottom_pipe != NULL && pipe_ctx->bottom_pipe != pipe_ctx) {
2227 		program_all_pipe_in_tree(dc, pipe_ctx->bottom_pipe, context);
2228 	}
2229 }
2230 
2231 static void dcn10_pplib_apply_display_requirements(
2232 	struct dc *dc,
2233 	struct dc_state *context)
2234 {
2235 	struct dm_pp_display_configuration *pp_display_cfg = &context->pp_display_cfg;
2236 
2237 	pp_display_cfg->min_engine_clock_khz = dc->res_pool->dccg->clks.dcfclk_khz;
2238 	pp_display_cfg->min_memory_clock_khz = dc->res_pool->dccg->clks.fclk_khz;
2239 	pp_display_cfg->min_engine_clock_deep_sleep_khz = dc->res_pool->dccg->clks.dcfclk_deep_sleep_khz;
2240 	pp_display_cfg->min_dcfc_deep_sleep_clock_khz = dc->res_pool->dccg->clks.dcfclk_deep_sleep_khz;
2241 	pp_display_cfg->min_dcfclock_khz = dc->res_pool->dccg->clks.dcfclk_khz;
2242 	pp_display_cfg->disp_clk_khz = dc->res_pool->dccg->clks.dispclk_khz;
2243 	dce110_fill_display_configs(context, pp_display_cfg);
2244 
2245 	if (memcmp(&dc->prev_display_config, pp_display_cfg, sizeof(
2246 			struct dm_pp_display_configuration)) !=  0)
2247 		dm_pp_apply_display_requirements(dc->ctx, pp_display_cfg);
2248 
2249 	dc->prev_display_config = *pp_display_cfg;
2250 }
2251 
2252 static void optimize_shared_resources(struct dc *dc)
2253 {
2254 	if (dc->current_state->stream_count == 0) {
2255 		/* S0i2 message */
2256 		dcn10_pplib_apply_display_requirements(dc, dc->current_state);
2257 	}
2258 
2259 	if (dc->debug.pplib_wm_report_mode == WM_REPORT_OVERRIDE)
2260 		dcn_bw_notify_pplib_of_wm_ranges(dc);
2261 }
2262 
2263 static void ready_shared_resources(struct dc *dc, struct dc_state *context)
2264 {
2265 	/* S0i2 message */
2266 	if (dc->current_state->stream_count == 0 &&
2267 			context->stream_count != 0)
2268 		dcn10_pplib_apply_display_requirements(dc, context);
2269 }
2270 
2271 static struct pipe_ctx *find_top_pipe_for_stream(
2272 		struct dc *dc,
2273 		struct dc_state *context,
2274 		const struct dc_stream_state *stream)
2275 {
2276 	int i;
2277 
2278 	for (i = 0; i < dc->res_pool->pipe_count; i++) {
2279 		struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[i];
2280 		struct pipe_ctx *old_pipe_ctx =
2281 				&dc->current_state->res_ctx.pipe_ctx[i];
2282 
2283 		if (!pipe_ctx->plane_state && !old_pipe_ctx->plane_state)
2284 			continue;
2285 
2286 		if (pipe_ctx->stream != stream)
2287 			continue;
2288 
2289 		if (!pipe_ctx->top_pipe)
2290 			return pipe_ctx;
2291 	}
2292 	return NULL;
2293 }
2294 
2295 static void dcn10_apply_ctx_for_surface(
2296 		struct dc *dc,
2297 		const struct dc_stream_state *stream,
2298 		int num_planes,
2299 		struct dc_state *context)
2300 {
2301 	int i;
2302 	struct timing_generator *tg;
2303 	bool removed_pipe[4] = { false };
2304 	struct pipe_ctx *top_pipe_to_program =
2305 			find_top_pipe_for_stream(dc, context, stream);
2306 	DC_LOGGER_INIT(dc->ctx->logger);
2307 
2308 	if (!top_pipe_to_program)
2309 		return;
2310 
2311 	tg = top_pipe_to_program->stream_res.tg;
2312 
2313 	dcn10_pipe_control_lock(dc, top_pipe_to_program, true);
2314 
2315 	if (num_planes == 0) {
2316 		/* OTG blank before remove all front end */
2317 		dc->hwss.blank_pixel_data(dc, top_pipe_to_program, true);
2318 	}
2319 
2320 	/* Disconnect unused mpcc */
2321 	for (i = 0; i < dc->res_pool->pipe_count; i++) {
2322 		struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[i];
2323 		struct pipe_ctx *old_pipe_ctx =
2324 				&dc->current_state->res_ctx.pipe_ctx[i];
2325 		/*
2326 		 * Powergate reused pipes that are not powergated
2327 		 * fairly hacky right now, using opp_id as indicator
2328 		 * TODO: After move dc_post to dc_update, this will
2329 		 * be removed.
2330 		 */
2331 		if (pipe_ctx->plane_state && !old_pipe_ctx->plane_state) {
2332 			if (old_pipe_ctx->stream_res.tg == tg &&
2333 				old_pipe_ctx->plane_res.hubp &&
2334 				old_pipe_ctx->plane_res.hubp->opp_id != 0xf) {
2335 				dcn10_disable_plane(dc, old_pipe_ctx);
2336 				/*
2337 				 * power down fe will unlock when calling reset, need
2338 				 * to lock it back here. Messy, need rework.
2339 				 */
2340 				pipe_ctx->stream_res.tg->funcs->lock(pipe_ctx->stream_res.tg);
2341 			}
2342 		}
2343 
2344 		if ((!pipe_ctx->plane_state ||
2345 		     pipe_ctx->stream_res.tg != old_pipe_ctx->stream_res.tg) &&
2346 		    old_pipe_ctx->plane_state &&
2347 		    old_pipe_ctx->stream_res.tg == tg) {
2348 
2349 			dc->hwss.plane_atomic_disconnect(dc, old_pipe_ctx);
2350 			removed_pipe[i] = true;
2351 
2352 			DC_LOG_DC("Reset mpcc for pipe %d\n",
2353 					old_pipe_ctx->pipe_idx);
2354 		}
2355 	}
2356 
2357 	if (num_planes > 0)
2358 		program_all_pipe_in_tree(dc, top_pipe_to_program, context);
2359 
2360 	dcn10_pipe_control_lock(dc, top_pipe_to_program, false);
2361 
2362 	if (num_planes == 0)
2363 		false_optc_underflow_wa(dc, stream, tg);
2364 
2365 	for (i = 0; i < dc->res_pool->pipe_count; i++)
2366 		if (removed_pipe[i])
2367 			dcn10_disable_plane(dc, &dc->current_state->res_ctx.pipe_ctx[i]);
2368 
2369 	if (dc->hwseq->wa.DEGVIDCN10_254)
2370 		hubbub1_wm_change_req_wa(dc->res_pool->hubbub);
2371 }
2372 
2373 static void dcn10_set_bandwidth(
2374 		struct dc *dc,
2375 		struct dc_state *context,
2376 		bool safe_to_lower)
2377 {
2378 	if (dc->debug.sanity_checks)
2379 		dcn10_verify_allow_pstate_change_high(dc);
2380 
2381 	if (!IS_FPGA_MAXIMUS_DC(dc->ctx->dce_environment)) {
2382 		if (context->stream_count == 0)
2383 			context->bw.dcn.clk.phyclk_khz = 0;
2384 
2385 		dc->res_pool->dccg->funcs->update_clocks(
2386 				dc->res_pool->dccg,
2387 				&context->bw.dcn.clk,
2388 				safe_to_lower);
2389 
2390 		dcn10_pplib_apply_display_requirements(dc, context);
2391 	}
2392 
2393 	hubbub1_program_watermarks(dc->res_pool->hubbub,
2394 			&context->bw.dcn.watermarks,
2395 			dc->res_pool->ref_clock_inKhz / 1000,
2396 			true);
2397 
2398 	if (dc->debug.sanity_checks)
2399 		dcn10_verify_allow_pstate_change_high(dc);
2400 }
2401 
2402 static void set_drr(struct pipe_ctx **pipe_ctx,
2403 		int num_pipes, int vmin, int vmax)
2404 {
2405 	int i = 0;
2406 	struct drr_params params = {0};
2407 
2408 	params.vertical_total_max = vmax;
2409 	params.vertical_total_min = vmin;
2410 
2411 	/* TODO: If multiple pipes are to be supported, you need
2412 	 * some GSL stuff
2413 	 */
2414 	for (i = 0; i < num_pipes; i++) {
2415 		pipe_ctx[i]->stream_res.tg->funcs->set_drr(pipe_ctx[i]->stream_res.tg, &params);
2416 	}
2417 }
2418 
2419 static void get_position(struct pipe_ctx **pipe_ctx,
2420 		int num_pipes,
2421 		struct crtc_position *position)
2422 {
2423 	int i = 0;
2424 
2425 	/* TODO: handle pipes > 1
2426 	 */
2427 	for (i = 0; i < num_pipes; i++)
2428 		pipe_ctx[i]->stream_res.tg->funcs->get_position(pipe_ctx[i]->stream_res.tg, position);
2429 }
2430 
2431 static void set_static_screen_control(struct pipe_ctx **pipe_ctx,
2432 		int num_pipes, const struct dc_static_screen_events *events)
2433 {
2434 	unsigned int i;
2435 	unsigned int value = 0;
2436 
2437 	if (events->surface_update)
2438 		value |= 0x80;
2439 	if (events->cursor_update)
2440 		value |= 0x2;
2441 	if (events->force_trigger)
2442 		value |= 0x1;
2443 
2444 	for (i = 0; i < num_pipes; i++)
2445 		pipe_ctx[i]->stream_res.tg->funcs->
2446 			set_static_screen_control(pipe_ctx[i]->stream_res.tg, value);
2447 }
2448 
2449 static void dcn10_config_stereo_parameters(
2450 		struct dc_stream_state *stream, struct crtc_stereo_flags *flags)
2451 {
2452 	enum view_3d_format view_format = stream->view_format;
2453 	enum dc_timing_3d_format timing_3d_format =\
2454 			stream->timing.timing_3d_format;
2455 	bool non_stereo_timing = false;
2456 
2457 	if (timing_3d_format == TIMING_3D_FORMAT_NONE ||
2458 		timing_3d_format == TIMING_3D_FORMAT_SIDE_BY_SIDE ||
2459 		timing_3d_format == TIMING_3D_FORMAT_TOP_AND_BOTTOM)
2460 		non_stereo_timing = true;
2461 
2462 	if (non_stereo_timing == false &&
2463 		view_format == VIEW_3D_FORMAT_FRAME_SEQUENTIAL) {
2464 
2465 		flags->PROGRAM_STEREO         = 1;
2466 		flags->PROGRAM_POLARITY       = 1;
2467 		if (timing_3d_format == TIMING_3D_FORMAT_INBAND_FA ||
2468 			timing_3d_format == TIMING_3D_FORMAT_DP_HDMI_INBAND_FA ||
2469 			timing_3d_format == TIMING_3D_FORMAT_SIDEBAND_FA) {
2470 			enum display_dongle_type dongle = \
2471 					stream->sink->link->ddc->dongle_type;
2472 			if (dongle == DISPLAY_DONGLE_DP_VGA_CONVERTER ||
2473 				dongle == DISPLAY_DONGLE_DP_DVI_CONVERTER ||
2474 				dongle == DISPLAY_DONGLE_DP_HDMI_CONVERTER)
2475 				flags->DISABLE_STEREO_DP_SYNC = 1;
2476 		}
2477 		flags->RIGHT_EYE_POLARITY =\
2478 				stream->timing.flags.RIGHT_EYE_3D_POLARITY;
2479 		if (timing_3d_format == TIMING_3D_FORMAT_HW_FRAME_PACKING)
2480 			flags->FRAME_PACKED = 1;
2481 	}
2482 
2483 	return;
2484 }
2485 
2486 static void dcn10_setup_stereo(struct pipe_ctx *pipe_ctx, struct dc *dc)
2487 {
2488 	struct crtc_stereo_flags flags = { 0 };
2489 	struct dc_stream_state *stream = pipe_ctx->stream;
2490 
2491 	dcn10_config_stereo_parameters(stream, &flags);
2492 
2493 	pipe_ctx->stream_res.opp->funcs->opp_program_stereo(
2494 		pipe_ctx->stream_res.opp,
2495 		flags.PROGRAM_STEREO == 1 ? true:false,
2496 		&stream->timing);
2497 
2498 	pipe_ctx->stream_res.tg->funcs->program_stereo(
2499 		pipe_ctx->stream_res.tg,
2500 		&stream->timing,
2501 		&flags);
2502 
2503 	return;
2504 }
2505 
2506 static struct hubp *get_hubp_by_inst(struct resource_pool *res_pool, int mpcc_inst)
2507 {
2508 	int i;
2509 
2510 	for (i = 0; i < res_pool->pipe_count; i++) {
2511 		if (res_pool->hubps[i]->inst == mpcc_inst)
2512 			return res_pool->hubps[i];
2513 	}
2514 	ASSERT(false);
2515 	return NULL;
2516 }
2517 
2518 static void dcn10_wait_for_mpcc_disconnect(
2519 		struct dc *dc,
2520 		struct resource_pool *res_pool,
2521 		struct pipe_ctx *pipe_ctx)
2522 {
2523 	int mpcc_inst;
2524 
2525 	if (dc->debug.sanity_checks) {
2526 		dcn10_verify_allow_pstate_change_high(dc);
2527 	}
2528 
2529 	if (!pipe_ctx->stream_res.opp)
2530 		return;
2531 
2532 	for (mpcc_inst = 0; mpcc_inst < MAX_PIPES; mpcc_inst++) {
2533 		if (pipe_ctx->stream_res.opp->mpcc_disconnect_pending[mpcc_inst]) {
2534 			struct hubp *hubp = get_hubp_by_inst(res_pool, mpcc_inst);
2535 
2536 			res_pool->mpc->funcs->wait_for_idle(res_pool->mpc, mpcc_inst);
2537 			pipe_ctx->stream_res.opp->mpcc_disconnect_pending[mpcc_inst] = false;
2538 			hubp->funcs->set_blank(hubp, true);
2539 			/*DC_LOG_ERROR(dc->ctx->logger,
2540 					"[debug_mpo: wait_for_mpcc finished waiting on mpcc %d]\n",
2541 					i);*/
2542 		}
2543 	}
2544 
2545 	if (dc->debug.sanity_checks) {
2546 		dcn10_verify_allow_pstate_change_high(dc);
2547 	}
2548 
2549 }
2550 
2551 static bool dcn10_dummy_display_power_gating(
2552 	struct dc *dc,
2553 	uint8_t controller_id,
2554 	struct dc_bios *dcb,
2555 	enum pipe_gating_control power_gating)
2556 {
2557 	return true;
2558 }
2559 
2560 static void dcn10_update_pending_status(struct pipe_ctx *pipe_ctx)
2561 {
2562 	struct dc_plane_state *plane_state = pipe_ctx->plane_state;
2563 	struct timing_generator *tg = pipe_ctx->stream_res.tg;
2564 	bool flip_pending;
2565 
2566 	if (plane_state == NULL)
2567 		return;
2568 
2569 	flip_pending = pipe_ctx->plane_res.hubp->funcs->hubp_is_flip_pending(
2570 					pipe_ctx->plane_res.hubp);
2571 
2572 	plane_state->status.is_flip_pending = flip_pending;
2573 
2574 	if (!flip_pending)
2575 		plane_state->status.current_address = plane_state->status.requested_address;
2576 
2577 	if (plane_state->status.current_address.type == PLN_ADDR_TYPE_GRPH_STEREO &&
2578 			tg->funcs->is_stereo_left_eye) {
2579 		plane_state->status.is_right_eye =
2580 				!tg->funcs->is_stereo_left_eye(pipe_ctx->stream_res.tg);
2581 	}
2582 }
2583 
2584 static void dcn10_update_dchub(struct dce_hwseq *hws, struct dchub_init_data *dh_data)
2585 {
2586 	if (hws->ctx->dc->res_pool->hubbub != NULL) {
2587 		struct hubp *hubp = hws->ctx->dc->res_pool->hubps[0];
2588 
2589 		if (hubp->funcs->hubp_update_dchub)
2590 			hubp->funcs->hubp_update_dchub(hubp, dh_data);
2591 		else
2592 			hubbub1_update_dchub(hws->ctx->dc->res_pool->hubbub, dh_data);
2593 	}
2594 }
2595 
2596 static void dcn10_set_cursor_position(struct pipe_ctx *pipe_ctx)
2597 {
2598 	struct dc_cursor_position pos_cpy = pipe_ctx->stream->cursor_position;
2599 	struct hubp *hubp = pipe_ctx->plane_res.hubp;
2600 	struct dpp *dpp = pipe_ctx->plane_res.dpp;
2601 	struct dc_cursor_mi_param param = {
2602 		.pixel_clk_khz = pipe_ctx->stream->timing.pix_clk_khz,
2603 		.ref_clk_khz = pipe_ctx->stream->ctx->dc->res_pool->ref_clock_inKhz,
2604 		.viewport = pipe_ctx->plane_res.scl_data.viewport,
2605 		.h_scale_ratio = pipe_ctx->plane_res.scl_data.ratios.horz,
2606 		.v_scale_ratio = pipe_ctx->plane_res.scl_data.ratios.vert,
2607 		.rotation = pipe_ctx->plane_state->rotation,
2608 		.mirror = pipe_ctx->plane_state->horizontal_mirror
2609 	};
2610 
2611 	if (pipe_ctx->plane_state->address.type
2612 			== PLN_ADDR_TYPE_VIDEO_PROGRESSIVE)
2613 		pos_cpy.enable = false;
2614 
2615 	if (pipe_ctx->top_pipe && pipe_ctx->plane_state != pipe_ctx->top_pipe->plane_state)
2616 		pos_cpy.enable = false;
2617 
2618 	hubp->funcs->set_cursor_position(hubp, &pos_cpy, &param);
2619 	dpp->funcs->set_cursor_position(dpp, &pos_cpy, &param, hubp->curs_attr.width);
2620 }
2621 
2622 static void dcn10_set_cursor_attribute(struct pipe_ctx *pipe_ctx)
2623 {
2624 	struct dc_cursor_attributes *attributes = &pipe_ctx->stream->cursor_attributes;
2625 
2626 	pipe_ctx->plane_res.hubp->funcs->set_cursor_attributes(
2627 			pipe_ctx->plane_res.hubp, attributes);
2628 	pipe_ctx->plane_res.dpp->funcs->set_cursor_attributes(
2629 		pipe_ctx->plane_res.dpp, attributes->color_format);
2630 }
2631 
2632 static void dcn10_set_cursor_sdr_white_level(struct pipe_ctx *pipe_ctx)
2633 {
2634 	uint32_t sdr_white_level = pipe_ctx->stream->cursor_attributes.sdr_white_level;
2635 	struct fixed31_32 multiplier;
2636 	struct dpp_cursor_attributes opt_attr = { 0 };
2637 	uint32_t hw_scale = 0x3c00; // 1.0 default multiplier
2638 	struct custom_float_format fmt;
2639 
2640 	if (!pipe_ctx->plane_res.dpp->funcs->set_optional_cursor_attributes)
2641 		return;
2642 
2643 	fmt.exponenta_bits = 5;
2644 	fmt.mantissa_bits = 10;
2645 	fmt.sign = true;
2646 
2647 	if (sdr_white_level > 80) {
2648 		multiplier = dc_fixpt_from_fraction(sdr_white_level, 80);
2649 		convert_to_custom_float_format(multiplier, &fmt, &hw_scale);
2650 	}
2651 
2652 	opt_attr.scale = hw_scale;
2653 	opt_attr.bias = 0;
2654 
2655 	pipe_ctx->plane_res.dpp->funcs->set_optional_cursor_attributes(
2656 			pipe_ctx->plane_res.dpp, &opt_attr);
2657 }
2658 
2659 static const struct hw_sequencer_funcs dcn10_funcs = {
2660 	.program_gamut_remap = program_gamut_remap,
2661 	.program_csc_matrix = program_csc_matrix,
2662 	.init_hw = dcn10_init_hw,
2663 	.apply_ctx_to_hw = dce110_apply_ctx_to_hw,
2664 	.apply_ctx_for_surface = dcn10_apply_ctx_for_surface,
2665 	.update_plane_addr = dcn10_update_plane_addr,
2666 	.plane_atomic_disconnect = hwss1_plane_atomic_disconnect,
2667 	.update_dchub = dcn10_update_dchub,
2668 	.update_mpcc = dcn10_update_mpcc,
2669 	.update_pending_status = dcn10_update_pending_status,
2670 	.set_input_transfer_func = dcn10_set_input_transfer_func,
2671 	.set_output_transfer_func = dcn10_set_output_transfer_func,
2672 	.program_output_csc = dcn10_program_output_csc,
2673 	.power_down = dce110_power_down,
2674 	.enable_accelerated_mode = dce110_enable_accelerated_mode,
2675 	.enable_timing_synchronization = dcn10_enable_timing_synchronization,
2676 	.enable_per_frame_crtc_position_reset = dcn10_enable_per_frame_crtc_position_reset,
2677 	.update_info_frame = dce110_update_info_frame,
2678 	.enable_stream = dce110_enable_stream,
2679 	.disable_stream = dce110_disable_stream,
2680 	.unblank_stream = dce110_unblank_stream,
2681 	.blank_stream = dce110_blank_stream,
2682 	.enable_audio_stream = dce110_enable_audio_stream,
2683 	.disable_audio_stream = dce110_disable_audio_stream,
2684 	.enable_display_power_gating = dcn10_dummy_display_power_gating,
2685 	.disable_plane = dcn10_disable_plane,
2686 	.blank_pixel_data = dcn10_blank_pixel_data,
2687 	.pipe_control_lock = dcn10_pipe_control_lock,
2688 	.set_bandwidth = dcn10_set_bandwidth,
2689 	.reset_hw_ctx_wrap = reset_hw_ctx_wrap,
2690 	.enable_stream_timing = dcn10_enable_stream_timing,
2691 	.set_drr = set_drr,
2692 	.get_position = get_position,
2693 	.set_static_screen_control = set_static_screen_control,
2694 	.setup_stereo = dcn10_setup_stereo,
2695 	.set_avmute = dce110_set_avmute,
2696 	.log_hw_state = dcn10_log_hw_state,
2697 	.wait_for_mpcc_disconnect = dcn10_wait_for_mpcc_disconnect,
2698 	.ready_shared_resources = ready_shared_resources,
2699 	.optimize_shared_resources = optimize_shared_resources,
2700 	.pplib_apply_display_requirements =
2701 			dcn10_pplib_apply_display_requirements,
2702 	.edp_backlight_control = hwss_edp_backlight_control,
2703 	.edp_power_control = hwss_edp_power_control,
2704 	.edp_wait_for_hpd_ready = hwss_edp_wait_for_hpd_ready,
2705 	.set_cursor_position = dcn10_set_cursor_position,
2706 	.set_cursor_attribute = dcn10_set_cursor_attribute,
2707 	.set_cursor_sdr_white_level = dcn10_set_cursor_sdr_white_level
2708 };
2709 
2710 
2711 void dcn10_hw_sequencer_construct(struct dc *dc)
2712 {
2713 	dc->hwss = dcn10_funcs;
2714 }
2715 
2716