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/dcn10_hwseq.h"
31 #include "dce110/dce110_hwseq.h"
32 #include "dce/dce_hwseq.h"
33 #include "abm.h"
34 #include "dmcu.h"
35 #include "dcn10/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 "dcn10/dcn10_hubp.h"
44 #include "dcn10/dcn10_hubbub.h"
45 #include "dcn10_cm_common.h"
46 #include "clk_mgr.h"
47 
48 __printf(3, 4)
snprintf_count(char * pbuf,unsigned int bufsize,char * fmt,...)49 unsigned int snprintf_count(char *pbuf, unsigned int bufsize, char *fmt, ...)
50 {
51 	int ret_vsnprintf;
52 	unsigned int chars_printed;
53 
54 	va_list args;
55 	va_start(args, fmt);
56 
57 	ret_vsnprintf = vsnprintf(pbuf, bufsize, fmt, args);
58 
59 	va_end(args);
60 
61 	if (ret_vsnprintf > 0) {
62 		if (ret_vsnprintf < bufsize)
63 			chars_printed = ret_vsnprintf;
64 		else
65 			chars_printed = bufsize - 1;
66 	} else
67 		chars_printed = 0;
68 
69 	return chars_printed;
70 }
71 
dcn10_get_hubbub_state(struct dc * dc,char * pBuf,unsigned int bufSize)72 static unsigned int dcn10_get_hubbub_state(struct dc *dc, char *pBuf, unsigned int bufSize)
73 {
74 	struct dc_context *dc_ctx = dc->ctx;
75 	struct dcn_hubbub_wm wm;
76 	int i;
77 
78 	unsigned int chars_printed = 0;
79 	unsigned int remaining_buffer = bufSize;
80 
81 	const uint32_t ref_clk_mhz = dc_ctx->dc->res_pool->ref_clocks.dchub_ref_clock_inKhz / 1000;
82 	static const unsigned int frac = 1000;
83 
84 	memset(&wm, 0, sizeof(struct dcn_hubbub_wm));
85 	dc->res_pool->hubbub->funcs->wm_read_state(dc->res_pool->hubbub, &wm);
86 
87 	chars_printed = snprintf_count(pBuf, remaining_buffer, "wm_set_index,data_urgent,pte_meta_urgent,sr_enter,sr_exit,dram_clk_change\n");
88 	remaining_buffer -= chars_printed;
89 	pBuf += chars_printed;
90 
91 	for (i = 0; i < 4; i++) {
92 		struct dcn_hubbub_wm_set *s;
93 
94 		s = &wm.sets[i];
95 
96 		chars_printed = snprintf_count(pBuf, remaining_buffer, "%x,%d.%03d,%d.%03d,%d.%03d,%d.%03d,%d.%03d\n",
97 			s->wm_set,
98 			(s->data_urgent * frac) / ref_clk_mhz / frac, (s->data_urgent * frac) / ref_clk_mhz % frac,
99 			(s->pte_meta_urgent * frac) / ref_clk_mhz / frac, (s->pte_meta_urgent * frac) / ref_clk_mhz % frac,
100 			(s->sr_enter * frac) / ref_clk_mhz / frac, (s->sr_enter * frac) / ref_clk_mhz % frac,
101 			(s->sr_exit * frac) / ref_clk_mhz / frac, (s->sr_exit * frac) / ref_clk_mhz % frac,
102 			(s->dram_clk_change * frac) / ref_clk_mhz / frac, (s->dram_clk_change * frac) / ref_clk_mhz % frac);
103 		remaining_buffer -= chars_printed;
104 		pBuf += chars_printed;
105 	}
106 
107 	return bufSize - remaining_buffer;
108 }
109 
dcn10_get_hubp_states(struct dc * dc,char * pBuf,unsigned int bufSize,bool invarOnly)110 static unsigned int dcn10_get_hubp_states(struct dc *dc, char *pBuf, unsigned int bufSize, bool invarOnly)
111 {
112 	struct dc_context *dc_ctx = dc->ctx;
113 	struct resource_pool *pool = dc->res_pool;
114 	int i;
115 
116 	unsigned int chars_printed = 0;
117 	unsigned int remaining_buffer = bufSize;
118 
119 	const uint32_t ref_clk_mhz = dc_ctx->dc->res_pool->ref_clocks.dchub_ref_clock_inKhz / 1000;
120 	static const unsigned int frac = 1000;
121 
122 	if (invarOnly)
123 		chars_printed = snprintf_count(pBuf, remaining_buffer, "instance,format,addr_hi,width,height,rotation,mirror,sw_mode,dcc_en,blank_en,ttu_dis,underflow,"
124 			"min_ttu_vblank,qos_low_wm,qos_high_wm"
125 			"\n");
126 	else
127 		chars_printed = snprintf_count(pBuf, remaining_buffer, "instance,format,addr_hi,addr_lo,width,height,rotation,mirror,sw_mode,dcc_en,blank_en,ttu_dis,underflow,"
128 					"min_ttu_vblank,qos_low_wm,qos_high_wm"
129 					"\n");
130 
131 	remaining_buffer -= chars_printed;
132 	pBuf += chars_printed;
133 
134 	for (i = 0; i < pool->pipe_count; i++) {
135 		struct hubp *hubp = pool->hubps[i];
136 		struct dcn_hubp_state *s = &(TO_DCN10_HUBP(hubp)->state);
137 
138 		hubp->funcs->hubp_read_state(hubp);
139 
140 		if (!s->blank_en) {
141 			if (invarOnly)
142 				chars_printed = snprintf_count(pBuf, remaining_buffer, "%x,%x,%x,%d,%d,%x,%x,%x,%x,%x,%x,%x,"
143 					"%d.%03d,%d.%03d,%d.%03d"
144 					"\n",
145 					hubp->inst,
146 					s->pixel_format,
147 					s->inuse_addr_hi,
148 					s->viewport_width,
149 					s->viewport_height,
150 					s->rotation_angle,
151 					s->h_mirror_en,
152 					s->sw_mode,
153 					s->dcc_en,
154 					s->blank_en,
155 					s->ttu_disable,
156 					s->underflow_status,
157 					(s->min_ttu_vblank * frac) / ref_clk_mhz / frac, (s->min_ttu_vblank * frac) / ref_clk_mhz % frac,
158 					(s->qos_level_low_wm * frac) / ref_clk_mhz / frac, (s->qos_level_low_wm * frac) / ref_clk_mhz % frac,
159 					(s->qos_level_high_wm * frac) / ref_clk_mhz / frac, (s->qos_level_high_wm * frac) / ref_clk_mhz % frac);
160 			else
161 				chars_printed = snprintf_count(pBuf, remaining_buffer, "%x,%x,%x,%x,%d,%d,%x,%x,%x,%x,%x,%x,%x,"
162 					"%d.%03d,%d.%03d,%d.%03d"
163 					"\n",
164 					hubp->inst,
165 					s->pixel_format,
166 					s->inuse_addr_hi,
167 					s->inuse_addr_lo,
168 					s->viewport_width,
169 					s->viewport_height,
170 					s->rotation_angle,
171 					s->h_mirror_en,
172 					s->sw_mode,
173 					s->dcc_en,
174 					s->blank_en,
175 					s->ttu_disable,
176 					s->underflow_status,
177 					(s->min_ttu_vblank * frac) / ref_clk_mhz / frac, (s->min_ttu_vblank * frac) / ref_clk_mhz % frac,
178 					(s->qos_level_low_wm * frac) / ref_clk_mhz / frac, (s->qos_level_low_wm * frac) / ref_clk_mhz % frac,
179 					(s->qos_level_high_wm * frac) / ref_clk_mhz / frac, (s->qos_level_high_wm * frac) / ref_clk_mhz % frac);
180 
181 			remaining_buffer -= chars_printed;
182 			pBuf += chars_printed;
183 		}
184 	}
185 
186 	return bufSize - remaining_buffer;
187 }
188 
dcn10_get_rq_states(struct dc * dc,char * pBuf,unsigned int bufSize)189 static unsigned int dcn10_get_rq_states(struct dc *dc, char *pBuf, unsigned int bufSize)
190 {
191 	struct resource_pool *pool = dc->res_pool;
192 	int i;
193 
194 	unsigned int chars_printed = 0;
195 	unsigned int remaining_buffer = bufSize;
196 
197 	chars_printed = snprintf_count(pBuf, remaining_buffer, "instance,drq_exp_m,prq_exp_m,mrq_exp_m,crq_exp_m,plane1_ba,"
198 		"luma_chunk_s,luma_min_chu_s,luma_meta_ch_s,luma_min_m_c_s,luma_dpte_gr_s,luma_mpte_gr_s,luma_swath_hei,luma_pte_row_h,"
199 		"chroma_chunk_s,chroma_min_chu_s,chroma_meta_ch_s,chroma_min_m_c_s,chroma_dpte_gr_s,chroma_mpte_gr_s,chroma_swath_hei,chroma_pte_row_h"
200 		"\n");
201 	remaining_buffer -= chars_printed;
202 	pBuf += chars_printed;
203 
204 	for (i = 0; i < pool->pipe_count; i++) {
205 		struct dcn_hubp_state *s = &(TO_DCN10_HUBP(pool->hubps[i])->state);
206 		struct _vcs_dpi_display_rq_regs_st *rq_regs = &s->rq_regs;
207 
208 		if (!s->blank_en) {
209 			chars_printed = snprintf_count(pBuf, remaining_buffer, "%x,%x,%x,%x,%x,%x,"
210 				"%x,%x,%x,%x,%x,%x,%x,%x,"
211 				"%x,%x,%x,%x,%x,%x,%x,%x"
212 				"\n",
213 				pool->hubps[i]->inst, rq_regs->drq_expansion_mode, rq_regs->prq_expansion_mode, rq_regs->mrq_expansion_mode,
214 				rq_regs->crq_expansion_mode, rq_regs->plane1_base_address, rq_regs->rq_regs_l.chunk_size,
215 				rq_regs->rq_regs_l.min_chunk_size, rq_regs->rq_regs_l.meta_chunk_size,
216 				rq_regs->rq_regs_l.min_meta_chunk_size, rq_regs->rq_regs_l.dpte_group_size,
217 				rq_regs->rq_regs_l.mpte_group_size, rq_regs->rq_regs_l.swath_height,
218 				rq_regs->rq_regs_l.pte_row_height_linear, rq_regs->rq_regs_c.chunk_size, rq_regs->rq_regs_c.min_chunk_size,
219 				rq_regs->rq_regs_c.meta_chunk_size, rq_regs->rq_regs_c.min_meta_chunk_size,
220 				rq_regs->rq_regs_c.dpte_group_size, rq_regs->rq_regs_c.mpte_group_size,
221 				rq_regs->rq_regs_c.swath_height, rq_regs->rq_regs_c.pte_row_height_linear);
222 
223 			remaining_buffer -= chars_printed;
224 			pBuf += chars_printed;
225 		}
226 	}
227 
228 	return bufSize - remaining_buffer;
229 }
230 
dcn10_get_dlg_states(struct dc * dc,char * pBuf,unsigned int bufSize)231 static unsigned int dcn10_get_dlg_states(struct dc *dc, char *pBuf, unsigned int bufSize)
232 {
233 	struct resource_pool *pool = dc->res_pool;
234 	int i;
235 
236 	unsigned int chars_printed = 0;
237 	unsigned int remaining_buffer = bufSize;
238 
239 	chars_printed = snprintf_count(pBuf, remaining_buffer, "instance,rc_hbe,dlg_vbe,min_d_y_n,rc_per_ht,rc_x_a_s,"
240 		"dst_y_a_s,dst_y_pf,dst_y_vvb,dst_y_rvb,dst_y_vfl,dst_y_rfl,rf_pix_fq,"
241 		"vratio_pf,vrat_pf_c,rc_pg_vbl,rc_pg_vbc,rc_mc_vbl,rc_mc_vbc,rc_pg_fll,"
242 		"rc_pg_flc,rc_mc_fll,rc_mc_flc,pr_nom_l,pr_nom_c,rc_pg_nl,rc_pg_nc,"
243 		"mr_nom_l,mr_nom_c,rc_mc_nl,rc_mc_nc,rc_ld_pl,rc_ld_pc,rc_ld_l,"
244 		"rc_ld_c,cha_cur0,ofst_cur1,cha_cur1,vr_af_vc0,ddrq_limt,x_rt_dlay,x_rp_dlay,x_rr_sfl"
245 		"\n");
246 	remaining_buffer -= chars_printed;
247 	pBuf += chars_printed;
248 
249 	for (i = 0; i < pool->pipe_count; i++) {
250 		struct dcn_hubp_state *s = &(TO_DCN10_HUBP(pool->hubps[i])->state);
251 		struct _vcs_dpi_display_dlg_regs_st *dlg_regs = &s->dlg_attr;
252 
253 		if (!s->blank_en) {
254 			chars_printed = snprintf_count(pBuf, remaining_buffer, "%x,%x,%x,%x,%x,"
255 				"%x,%x,%x,%x,%x,%x,%x,"
256 				"%x,%x,%x,%x,%x,%x,%x,"
257 				"%x,%x,%x,%x,%x,%x,%x,"
258 				"%x,%x,%x,%x,%x,%x,%x,"
259 				"%x,%x,%x,%x,%x,%x,%x,%x,%x,%x"
260 				"\n",
261 				pool->hubps[i]->inst, dlg_regs->refcyc_h_blank_end, dlg_regs->dlg_vblank_end, dlg_regs->min_dst_y_next_start,
262 				dlg_regs->refcyc_per_htotal, dlg_regs->refcyc_x_after_scaler, dlg_regs->dst_y_after_scaler,
263 				dlg_regs->dst_y_prefetch, dlg_regs->dst_y_per_vm_vblank, dlg_regs->dst_y_per_row_vblank,
264 				dlg_regs->dst_y_per_vm_flip, dlg_regs->dst_y_per_row_flip, dlg_regs->ref_freq_to_pix_freq,
265 				dlg_regs->vratio_prefetch, dlg_regs->vratio_prefetch_c, dlg_regs->refcyc_per_pte_group_vblank_l,
266 				dlg_regs->refcyc_per_pte_group_vblank_c, dlg_regs->refcyc_per_meta_chunk_vblank_l,
267 				dlg_regs->refcyc_per_meta_chunk_vblank_c, dlg_regs->refcyc_per_pte_group_flip_l,
268 				dlg_regs->refcyc_per_pte_group_flip_c, dlg_regs->refcyc_per_meta_chunk_flip_l,
269 				dlg_regs->refcyc_per_meta_chunk_flip_c, dlg_regs->dst_y_per_pte_row_nom_l,
270 				dlg_regs->dst_y_per_pte_row_nom_c, dlg_regs->refcyc_per_pte_group_nom_l,
271 				dlg_regs->refcyc_per_pte_group_nom_c, dlg_regs->dst_y_per_meta_row_nom_l,
272 				dlg_regs->dst_y_per_meta_row_nom_c, dlg_regs->refcyc_per_meta_chunk_nom_l,
273 				dlg_regs->refcyc_per_meta_chunk_nom_c, dlg_regs->refcyc_per_line_delivery_pre_l,
274 				dlg_regs->refcyc_per_line_delivery_pre_c, dlg_regs->refcyc_per_line_delivery_l,
275 				dlg_regs->refcyc_per_line_delivery_c, dlg_regs->chunk_hdl_adjust_cur0, dlg_regs->dst_y_offset_cur1,
276 				dlg_regs->chunk_hdl_adjust_cur1, dlg_regs->vready_after_vcount0, dlg_regs->dst_y_delta_drq_limit,
277 				dlg_regs->xfc_reg_transfer_delay, dlg_regs->xfc_reg_precharge_delay,
278 				dlg_regs->xfc_reg_remote_surface_flip_latency);
279 
280 			remaining_buffer -= chars_printed;
281 			pBuf += chars_printed;
282 		}
283 	}
284 
285 	return bufSize - remaining_buffer;
286 }
287 
dcn10_get_ttu_states(struct dc * dc,char * pBuf,unsigned int bufSize)288 static unsigned int dcn10_get_ttu_states(struct dc *dc, char *pBuf, unsigned int bufSize)
289 {
290 	struct resource_pool *pool = dc->res_pool;
291 	int i;
292 
293 	unsigned int chars_printed = 0;
294 	unsigned int remaining_buffer = bufSize;
295 
296 	chars_printed = snprintf_count(pBuf, remaining_buffer, "instance,qos_ll_wm,qos_lh_wm,mn_ttu_vb,qos_l_flp,rc_rd_p_l,rc_rd_l,rc_rd_p_c,"
297 		"rc_rd_c,rc_rd_c0,rc_rd_pc0,rc_rd_c1,rc_rd_pc1,qos_lf_l,qos_rds_l,"
298 		"qos_lf_c,qos_rds_c,qos_lf_c0,qos_rds_c0,qos_lf_c1,qos_rds_c1"
299 		"\n");
300 	remaining_buffer -= chars_printed;
301 	pBuf += chars_printed;
302 
303 	for (i = 0; i < pool->pipe_count; i++) {
304 		struct dcn_hubp_state *s = &(TO_DCN10_HUBP(pool->hubps[i])->state);
305 		struct _vcs_dpi_display_ttu_regs_st *ttu_regs = &s->ttu_attr;
306 
307 		if (!s->blank_en) {
308 			chars_printed = snprintf_count(pBuf, remaining_buffer, "%x,%x,%x,%x,%x,%x,%x,%x,"
309 				"%x,%x,%x,%x,%x,%x,%x,"
310 				"%x,%x,%x,%x,%x,%x"
311 				"\n",
312 				pool->hubps[i]->inst, ttu_regs->qos_level_low_wm, ttu_regs->qos_level_high_wm, ttu_regs->min_ttu_vblank,
313 				ttu_regs->qos_level_flip, ttu_regs->refcyc_per_req_delivery_pre_l, ttu_regs->refcyc_per_req_delivery_l,
314 				ttu_regs->refcyc_per_req_delivery_pre_c, ttu_regs->refcyc_per_req_delivery_c, ttu_regs->refcyc_per_req_delivery_cur0,
315 				ttu_regs->refcyc_per_req_delivery_pre_cur0, ttu_regs->refcyc_per_req_delivery_cur1,
316 				ttu_regs->refcyc_per_req_delivery_pre_cur1, ttu_regs->qos_level_fixed_l, ttu_regs->qos_ramp_disable_l,
317 				ttu_regs->qos_level_fixed_c, ttu_regs->qos_ramp_disable_c, ttu_regs->qos_level_fixed_cur0,
318 				ttu_regs->qos_ramp_disable_cur0, ttu_regs->qos_level_fixed_cur1, ttu_regs->qos_ramp_disable_cur1);
319 
320 			remaining_buffer -= chars_printed;
321 			pBuf += chars_printed;
322 		}
323 	}
324 
325 	return bufSize - remaining_buffer;
326 }
327 
dcn10_get_cm_states(struct dc * dc,char * pBuf,unsigned int bufSize)328 static unsigned int dcn10_get_cm_states(struct dc *dc, char *pBuf, unsigned int bufSize)
329 {
330 	struct resource_pool *pool = dc->res_pool;
331 	int i;
332 
333 	unsigned int chars_printed = 0;
334 	unsigned int remaining_buffer = bufSize;
335 
336 	chars_printed = snprintf_count(pBuf, remaining_buffer, "instance,igam_format,igam_mode,dgam_mode,rgam_mode,gamut_mode,"
337 		"c11_c12,c13_c14,c21_c22,c23_c24,c31_c32,c33_c34"
338 		"\n");
339 	remaining_buffer -= chars_printed;
340 	pBuf += chars_printed;
341 
342 	for (i = 0; i < pool->pipe_count; i++) {
343 		struct dpp *dpp = pool->dpps[i];
344 		struct dcn_dpp_state s = {0};
345 
346 		dpp->funcs->dpp_read_state(dpp, &s);
347 
348 		if (s.is_enabled) {
349 			chars_printed = snprintf_count(pBuf, remaining_buffer, "%x,%x,"
350 					"%s,%s,%s,"
351 					"%x,%08x,%08x,%08x,%08x,%08x,%08x"
352 				"\n",
353 				dpp->inst, s.igam_input_format,
354 				(s.igam_lut_mode == 0) ? "BypassFixed" :
355 					((s.igam_lut_mode == 1) ? "BypassFloat" :
356 					((s.igam_lut_mode == 2) ? "RAM" :
357 					((s.igam_lut_mode == 3) ? "RAM" :
358 								 "Unknown"))),
359 				(s.dgam_lut_mode == 0) ? "Bypass" :
360 					((s.dgam_lut_mode == 1) ? "sRGB" :
361 					((s.dgam_lut_mode == 2) ? "Ycc" :
362 					((s.dgam_lut_mode == 3) ? "RAM" :
363 					((s.dgam_lut_mode == 4) ? "RAM" :
364 								 "Unknown")))),
365 				(s.rgam_lut_mode == 0) ? "Bypass" :
366 					((s.rgam_lut_mode == 1) ? "sRGB" :
367 					((s.rgam_lut_mode == 2) ? "Ycc" :
368 					((s.rgam_lut_mode == 3) ? "RAM" :
369 					((s.rgam_lut_mode == 4) ? "RAM" :
370 								 "Unknown")))),
371 				s.gamut_remap_mode, s.gamut_remap_c11_c12,
372 				s.gamut_remap_c13_c14, s.gamut_remap_c21_c22, s.gamut_remap_c23_c24,
373 				s.gamut_remap_c31_c32, s.gamut_remap_c33_c34);
374 
375 			remaining_buffer -= chars_printed;
376 			pBuf += chars_printed;
377 		}
378 	}
379 
380 	return bufSize - remaining_buffer;
381 }
382 
dcn10_get_mpcc_states(struct dc * dc,char * pBuf,unsigned int bufSize)383 static unsigned int dcn10_get_mpcc_states(struct dc *dc, char *pBuf, unsigned int bufSize)
384 {
385 	struct resource_pool *pool = dc->res_pool;
386 	int i;
387 
388 	unsigned int chars_printed = 0;
389 	unsigned int remaining_buffer = bufSize;
390 
391 	chars_printed = snprintf_count(pBuf, remaining_buffer, "instance,opp,dpp,mpccbot,mode,alpha_mode,premult,overlap_only,idle\n");
392 	remaining_buffer -= chars_printed;
393 	pBuf += chars_printed;
394 
395 	for (i = 0; i < pool->mpcc_count; i++) {
396 		struct mpcc_state s = {0};
397 
398 		pool->mpc->funcs->read_mpcc_state(pool->mpc, i, &s);
399 
400 		if (s.opp_id != 0xf) {
401 			chars_printed = snprintf_count(pBuf, remaining_buffer, "%x,%x,%x,%x,%x,%x,%x,%x,%x\n",
402 				i, s.opp_id, s.dpp_id, s.bot_mpcc_id,
403 				s.mode, s.alpha_mode, s.pre_multiplied_alpha, s.overlap_only,
404 				s.idle);
405 
406 			remaining_buffer -= chars_printed;
407 			pBuf += chars_printed;
408 		}
409 	}
410 
411 	return bufSize - remaining_buffer;
412 }
413 
dcn10_get_otg_states(struct dc * dc,char * pBuf,unsigned int bufSize)414 static unsigned int dcn10_get_otg_states(struct dc *dc, char *pBuf, unsigned int bufSize)
415 {
416 	struct resource_pool *pool = dc->res_pool;
417 	int i;
418 
419 	unsigned int chars_printed = 0;
420 	unsigned int remaining_buffer = bufSize;
421 
422 	chars_printed = snprintf_count(pBuf, remaining_buffer, "instance,v_bs,v_be,v_ss,v_se,vpol,vmax,vmin,vmax_sel,vmin_sel,"
423 			"h_bs,h_be,h_ss,h_se,hpol,htot,vtot,underflow,pixelclk[khz]\n");
424 	remaining_buffer -= chars_printed;
425 	pBuf += chars_printed;
426 
427 	for (i = 0; i < pool->timing_generator_count; i++) {
428 		struct timing_generator *tg = pool->timing_generators[i];
429 		struct dcn_otg_state s = {0};
430 		int pix_clk = 0;
431 
432 		optc1_read_otg_state(DCN10TG_FROM_TG(tg), &s);
433 		pix_clk = dc->current_state->res_ctx.pipe_ctx[i].stream_res.pix_clk_params.requested_pix_clk_100hz / 10;
434 
435 		//only print if OTG master is enabled
436 		if (s.otg_enabled & 1) {
437 			chars_printed = snprintf_count(pBuf, remaining_buffer, "%x,%d,%d,%d,%d,%d,%d,%d,%d,%d,"
438 				"%d,%d,%d,%d,%d,%d,%d,%d,%d"
439 				"\n",
440 				tg->inst,
441 				s.v_blank_start,
442 				s.v_blank_end,
443 				s.v_sync_a_start,
444 				s.v_sync_a_end,
445 				s.v_sync_a_pol,
446 				s.v_total_max,
447 				s.v_total_min,
448 				s.v_total_max_sel,
449 				s.v_total_min_sel,
450 				s.h_blank_start,
451 				s.h_blank_end,
452 				s.h_sync_a_start,
453 				s.h_sync_a_end,
454 				s.h_sync_a_pol,
455 				s.h_total,
456 				s.v_total,
457 				s.underflow_occurred_status,
458 				pix_clk);
459 
460 			remaining_buffer -= chars_printed;
461 			pBuf += chars_printed;
462 		}
463 	}
464 
465 	return bufSize - remaining_buffer;
466 }
467 
dcn10_get_clock_states(struct dc * dc,char * pBuf,unsigned int bufSize)468 static unsigned int dcn10_get_clock_states(struct dc *dc, char *pBuf, unsigned int bufSize)
469 {
470 	unsigned int chars_printed = 0;
471 	unsigned int remaining_buffer = bufSize;
472 
473 	chars_printed = snprintf_count(pBuf, bufSize, "dcfclk,dcfclk_deep_sleep,dispclk,"
474 		"dppclk,fclk,socclk\n"
475 		"%d,%d,%d,%d,%d,%d\n",
476 		dc->current_state->bw_ctx.bw.dcn.clk.dcfclk_khz,
477 		dc->current_state->bw_ctx.bw.dcn.clk.dcfclk_deep_sleep_khz,
478 		dc->current_state->bw_ctx.bw.dcn.clk.dispclk_khz,
479 		dc->current_state->bw_ctx.bw.dcn.clk.dppclk_khz,
480 		dc->current_state->bw_ctx.bw.dcn.clk.fclk_khz,
481 		dc->current_state->bw_ctx.bw.dcn.clk.socclk_khz);
482 
483 	remaining_buffer -= chars_printed;
484 	pBuf += chars_printed;
485 
486 	return bufSize - remaining_buffer;
487 }
488 
dcn10_clear_otpc_underflow(struct dc * dc)489 static void dcn10_clear_otpc_underflow(struct dc *dc)
490 {
491 	struct resource_pool *pool = dc->res_pool;
492 	int i;
493 
494 	for (i = 0; i < pool->timing_generator_count; i++) {
495 		struct timing_generator *tg = pool->timing_generators[i];
496 		struct dcn_otg_state s = {0};
497 
498 		optc1_read_otg_state(DCN10TG_FROM_TG(tg), &s);
499 
500 		if (s.otg_enabled & 1)
501 			tg->funcs->clear_optc_underflow(tg);
502 	}
503 }
504 
dcn10_clear_hubp_underflow(struct dc * dc)505 static void dcn10_clear_hubp_underflow(struct dc *dc)
506 {
507 	struct resource_pool *pool = dc->res_pool;
508 	int i;
509 
510 	for (i = 0; i < pool->pipe_count; i++) {
511 		struct hubp *hubp = pool->hubps[i];
512 		struct dcn_hubp_state *s = &(TO_DCN10_HUBP(hubp)->state);
513 
514 		hubp->funcs->hubp_read_state(hubp);
515 
516 		if (!s->blank_en)
517 			hubp->funcs->hubp_clear_underflow(hubp);
518 	}
519 }
520 
dcn10_clear_status_bits(struct dc * dc,unsigned int mask)521 void dcn10_clear_status_bits(struct dc *dc, unsigned int mask)
522 {
523 	/*
524 	 *  Mask Format
525 	 *  Bit 0 - 31: Status bit to clear
526 	 *
527 	 *  Mask = 0x0 means clear all status bits
528 	 */
529 	const unsigned int DC_HW_STATE_MASK_HUBP_UNDERFLOW	= 0x1;
530 	const unsigned int DC_HW_STATE_MASK_OTPC_UNDERFLOW	= 0x2;
531 
532 	if (mask == 0x0)
533 		mask = 0xFFFFFFFF;
534 
535 	if (mask & DC_HW_STATE_MASK_HUBP_UNDERFLOW)
536 		dcn10_clear_hubp_underflow(dc);
537 
538 	if (mask & DC_HW_STATE_MASK_OTPC_UNDERFLOW)
539 		dcn10_clear_otpc_underflow(dc);
540 }
541 
dcn10_get_hw_state(struct dc * dc,char * pBuf,unsigned int bufSize,unsigned int mask)542 void dcn10_get_hw_state(struct dc *dc, char *pBuf, unsigned int bufSize, unsigned int mask)
543 {
544 	/*
545 	 *  Mask Format
546 	 *  Bit 0 - 15: Hardware block mask
547 	 *  Bit 15: 1 = Invariant Only, 0 = All
548 	 */
549 	const unsigned int DC_HW_STATE_MASK_HUBBUB			= 0x1;
550 	const unsigned int DC_HW_STATE_MASK_HUBP			= 0x2;
551 	const unsigned int DC_HW_STATE_MASK_RQ				= 0x4;
552 	const unsigned int DC_HW_STATE_MASK_DLG				= 0x8;
553 	const unsigned int DC_HW_STATE_MASK_TTU				= 0x10;
554 	const unsigned int DC_HW_STATE_MASK_CM				= 0x20;
555 	const unsigned int DC_HW_STATE_MASK_MPCC			= 0x40;
556 	const unsigned int DC_HW_STATE_MASK_OTG				= 0x80;
557 	const unsigned int DC_HW_STATE_MASK_CLOCKS			= 0x100;
558 	const unsigned int DC_HW_STATE_INVAR_ONLY			= 0x8000;
559 
560 	unsigned int chars_printed = 0;
561 	unsigned int remaining_buf_size = bufSize;
562 
563 	if (mask == 0x0)
564 		mask = 0xFFFF; // Default, capture all, invariant only
565 
566 	if ((mask & DC_HW_STATE_MASK_HUBBUB) && remaining_buf_size > 0) {
567 		chars_printed = dcn10_get_hubbub_state(dc, pBuf, remaining_buf_size);
568 		pBuf += chars_printed;
569 		remaining_buf_size -= chars_printed;
570 	}
571 
572 	if ((mask & DC_HW_STATE_MASK_HUBP) && remaining_buf_size > 0) {
573 		chars_printed = dcn10_get_hubp_states(dc, pBuf, remaining_buf_size, mask & DC_HW_STATE_INVAR_ONLY);
574 		pBuf += chars_printed;
575 		remaining_buf_size -= chars_printed;
576 	}
577 
578 	if ((mask & DC_HW_STATE_MASK_RQ) && remaining_buf_size > 0) {
579 		chars_printed = dcn10_get_rq_states(dc, pBuf, remaining_buf_size);
580 		pBuf += chars_printed;
581 		remaining_buf_size -= chars_printed;
582 	}
583 
584 	if ((mask & DC_HW_STATE_MASK_DLG) && remaining_buf_size > 0) {
585 		chars_printed = dcn10_get_dlg_states(dc, pBuf, remaining_buf_size);
586 		pBuf += chars_printed;
587 		remaining_buf_size -= chars_printed;
588 	}
589 
590 	if ((mask & DC_HW_STATE_MASK_TTU) && remaining_buf_size > 0) {
591 		chars_printed = dcn10_get_ttu_states(dc, pBuf, remaining_buf_size);
592 		pBuf += chars_printed;
593 		remaining_buf_size -= chars_printed;
594 	}
595 
596 	if ((mask & DC_HW_STATE_MASK_CM) && remaining_buf_size > 0) {
597 		chars_printed = dcn10_get_cm_states(dc, pBuf, remaining_buf_size);
598 		pBuf += chars_printed;
599 		remaining_buf_size -= chars_printed;
600 	}
601 
602 	if ((mask & DC_HW_STATE_MASK_MPCC) && remaining_buf_size > 0) {
603 		chars_printed = dcn10_get_mpcc_states(dc, pBuf, remaining_buf_size);
604 		pBuf += chars_printed;
605 		remaining_buf_size -= chars_printed;
606 	}
607 
608 	if ((mask & DC_HW_STATE_MASK_OTG) && remaining_buf_size > 0) {
609 		chars_printed = dcn10_get_otg_states(dc, pBuf, remaining_buf_size);
610 		pBuf += chars_printed;
611 		remaining_buf_size -= chars_printed;
612 	}
613 
614 	if ((mask & DC_HW_STATE_MASK_CLOCKS) && remaining_buf_size > 0) {
615 		chars_printed = dcn10_get_clock_states(dc, pBuf, remaining_buf_size);
616 		pBuf += chars_printed;
617 		remaining_buf_size -= chars_printed;
618 	}
619 }
620