Commit ae8cf977 authored by Leo (Hanghong) Ma's avatar Leo (Hanghong) Ma Committed by Alex Deucher
Browse files

drm/amd/display: Add some hardware status in DTN log debugfs



[Why]
For debug purpose, we need to check the following hardware status
in DTN log debugfs:
1.dpp & hubp clock enable;
2.crtc blank enable;
3.link phy status;

[How]
Add the upper information in the amdgpu_dm_dtn_log debugfs.

For CRTC blanked status, since DCN2 and greater reports it on the OPP
instead of OTG, we patch it in after calling optc1_read_otg_states.
Ideally, this should be done in the DCN version specific function hooks.
It has been left as a TODO item.

Signed-off-by: default avatarLeo (Hanghong) Ma <hanghong.ma@amd.com>
Reviewed-by: default avatarMikita Lipski <Mikita.Lipski@amd.com>
Acked-by: default avatarBhawanpreet Lakha <Bhawanpreet.Lakha@amd.com>
Acked-by: default avatarHarry Wentland <Harry.Wentland@amd.com>
Signed-off-by: default avatarAlex Deucher <alexander.deucher@amd.com>
parent eb7d81af
Loading
Loading
Loading
Loading
+3 −0
Original line number Diff line number Diff line
@@ -1014,6 +1014,9 @@ void hubp1_read_state_common(struct hubp *hubp)
			HUBP_TTU_DISABLE, &s->ttu_disable,
			HUBP_UNDERFLOW_STATUS, &s->underflow_status);

	REG_GET(HUBP_CLK_CNTL,
			HUBP_CLOCK_ENABLE, &s->clock_en);

	REG_GET(DCN_GLOBAL_TTU_CNTL,
			MIN_TTU_VBLANK, &s->min_ttu_vblank);

+1 −0
Original line number Diff line number Diff line
@@ -670,6 +670,7 @@ struct dcn_hubp_state {
	uint32_t sw_mode;
	uint32_t dcc_en;
	uint32_t blank_en;
	uint32_t clock_en;
	uint32_t underflow_status;
	uint32_t ttu_disable;
	uint32_t min_ttu_vblank;
+29 −14
Original line number Diff line number Diff line
@@ -129,9 +129,8 @@ static void dcn10_log_hubp_states(struct dc *dc, void *log_ctx)
	struct resource_pool *pool = dc->res_pool;
	int i;

	DTN_INFO("HUBP:  format  addr_hi  width  height"
			"  rot  mir  sw_mode  dcc_en  blank_en  ttu_dis  underflow"
			"   min_ttu_vblank       qos_low_wm      qos_high_wm\n");
	DTN_INFO(
		"HUBP:  format  addr_hi  width  height  rot  mir  sw_mode  dcc_en  blank_en  clock_en  ttu_dis  underflow   min_ttu_vblank       qos_low_wm      qos_high_wm\n");
	for (i = 0; i < pool->pipe_count; i++) {
		struct hubp *hubp = pool->hubps[i];
		struct dcn_hubp_state *s = &(TO_DCN10_HUBP(hubp)->state);
@@ -139,8 +138,7 @@ static void dcn10_log_hubp_states(struct dc *dc, void *log_ctx)
		hubp->funcs->hubp_read_state(hubp);

		if (!s->blank_en) {
			DTN_INFO("[%2d]:  %5xh  %6xh  %5d  %6d  %2xh  %2xh  %6xh"
					"  %6d  %8d  %7d  %8xh",
			DTN_INFO("[%2d]:  %5xh  %6xh  %5d  %6d  %2xh  %2xh  %6xh  %6d  %8d  %8d  %7d  %8xh",
					hubp->inst,
					s->pixel_format,
					s->inuse_addr_hi,
@@ -151,6 +149,7 @@ static void dcn10_log_hubp_states(struct dc *dc, void *log_ctx)
					s->sw_mode,
					s->dcc_en,
					s->blank_en,
					s->clock_en,
					s->ttu_disable,
					s->underflow_status);
			DTN_INFO_MICRO_SEC(s->min_ttu_vblank);
@@ -308,21 +307,35 @@ void dcn10_log_hw_state(struct dc *dc,
	}
	DTN_INFO("\n");

	DTN_INFO("OTG:  v_bs  v_be  v_ss  v_se  vpol  vmax  vmin  vmax_sel  vmin_sel"
			"  h_bs  h_be  h_ss  h_se  hpol  htot  vtot  underflow\n");
	DTN_INFO("OTG:  v_bs  v_be  v_ss  v_se  vpol  vmax  vmin  vmax_sel  vmin_sel  h_bs  h_be  h_ss  h_se  hpol  htot  vtot  underflow blank_en\n");

	for (i = 0; i < pool->timing_generator_count; i++) {
		struct timing_generator *tg = pool->timing_generators[i];
		struct dcn_otg_state s = {0};

		/* Read shared OTG state registers for all DCNx */
		optc1_read_otg_state(DCN10TG_FROM_TG(tg), &s);

#ifdef CONFIG_DRM_AMD_DC_DCN2_0
		/*
		 * For DCN2 and greater, a register on the OPP is used to
		 * determine if the CRTC is blanked instead of the OTG. So use
		 * dpg_is_blanked() if exists, otherwise fallback on otg.
		 *
		 * TODO: Implement DCN-specific read_otg_state hooks.
		 */
		if (pool->opps[i]->funcs->dpg_is_blanked)
			s.blank_enabled = pool->opps[i]->funcs->dpg_is_blanked(pool->opps[i]);
		else
			s.blank_enabled = tg->funcs->is_blanked(tg);
#else
		s.blank_enabled = tg->funcs->is_blanked(tg);
#endif

		//only print if OTG master is enabled
		if ((s.otg_enabled & 1) == 0)
			continue;

		DTN_INFO("[%d]: %5d %5d %5d %5d %5d %5d %5d %9d %9d %5d %5d %5d"
				" %5d %5d %5d %5d  %9d\n",
		DTN_INFO("[%d]: %5d %5d %5d %5d %5d %5d %5d %9d %9d %5d %5d %5d %5d %5d %5d %5d  %9d %8d\n",
				tg->inst,
				s.v_blank_start,
				s.v_blank_end,
@@ -340,7 +353,8 @@ void dcn10_log_hw_state(struct dc *dc,
				s.h_sync_a_pol,
				s.h_total,
				s.v_total,
				s.underflow_occurred_status);
				s.underflow_occurred_status,
				s.blank_enabled);

		// Clear underflow for debug purposes
		// We want to keep underflow sticky bit on for the longevity tests outside of test environment.
@@ -387,7 +401,7 @@ void dcn10_log_hw_state(struct dc *dc,
	}
	DTN_INFO("\n");

	DTN_INFO("L_ENC: DPHY_FEC_EN  DPHY_FEC_READY_SHADOW  DPHY_FEC_ACTIVE_STATUS\n");
	DTN_INFO("L_ENC: DPHY_FEC_EN  DPHY_FEC_READY_SHADOW  DPHY_FEC_ACTIVE_STATUS  DP_LINK_TRAINING_COMPLETE\n");
	for (i = 0; i < dc->link_count; i++) {
		struct link_encoder *lenc = dc->links[i]->link_enc;

@@ -395,11 +409,12 @@ void dcn10_log_hw_state(struct dc *dc,

		if (lenc->funcs->read_state) {
			lenc->funcs->read_state(lenc, &s);
			DTN_INFO("[%-3d]: %-12d %-22d %-22d\n",
			DTN_INFO("[%-3d]: %-12d %-22d %-22d %-25d\n",
				i,
				s.dphy_fec_en,
				s.dphy_fec_ready_shadow,
				s.dphy_fec_active_status);
				s.dphy_fec_active_status,
				s.dp_link_training_complete);
			DTN_INFO("\n");
		}
	}
+1 −0
Original line number Diff line number Diff line
@@ -406,6 +406,7 @@ static const struct opp_funcs dcn10_opp_funcs = {
		.opp_pipe_clock_control = opp1_pipe_clock_control,
#if defined(CONFIG_DRM_AMD_DC_DCN2_0)
		.opp_set_disp_pattern_generator = NULL,
		.dpg_is_blanked = NULL,
#endif
		.opp_destroy = opp1_destroy
};
+1 −0
Original line number Diff line number Diff line
@@ -542,6 +542,7 @@ struct dcn_otg_state {
	uint32_t h_total;
	uint32_t underflow_occurred_status;
	uint32_t otg_enabled;
	uint32_t blank_enabled;
};

void optc1_read_otg_state(struct optc *optc1,
Loading