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