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