Commit 5dc0ec78 authored by Muhammad Ahmed's avatar Muhammad Ahmed Committed by Alex Deucher
Browse files

drm/amd/display: Adding interface to log hw state when underflow happens



[why]
Will help us better debug underflow issues.

Reviewed-by: default avatarNicholas Kazlauskas <nicholas.kazlauskas@amd.com>
Signed-off-by: default avatarMuhammad Ahmed <Muhammad.Ahmed@amd.com>
Signed-off-by: default avatarRoman Li <roman.li@amd.com>
Tested-by: default avatarDaniel Wheeler <daniel.wheeler@amd.com>
Signed-off-by: default avatarAlex Deucher <alexander.deucher@amd.com>
parent 20ea30a7
Loading
Loading
Loading
Loading
+18 −0
Original line number Diff line number Diff line
@@ -6339,3 +6339,21 @@ bool dc_can_clear_cursor_limit(struct dc *dc)

	return false;
}

void dc_get_underflow_debug_data_for_otg(struct dc *dc, int primary_otg_inst,
				struct dc_underflow_debug_data *out_data)
{
	struct timing_generator *tg = NULL;

	for (int i = 0; i < MAX_PIPES; i++) {
		if (dc->res_pool->timing_generators[i] &&
			dc->res_pool->timing_generators[i]->inst == primary_otg_inst) {
				tg = dc->res_pool->timing_generators[i];
				break;
		}
	}

	dc_exit_ips_for_hw_access(dc);
	if (dc->hwss.get_underflow_debug_data)
		dc->hwss.get_underflow_debug_data(dc, tg, out_data);
}
+30 −0
Original line number Diff line number Diff line
@@ -1819,6 +1819,23 @@ struct dc_surface_update {
	struct dc_bias_and_scale bias_and_scale;
};

struct dc_underflow_debug_data {
	uint32_t otg_inst;
	uint32_t otg_underflow;
	uint32_t h_position;
	uint32_t v_position;
	uint32_t otg_frame_count;
	struct dc_underflow_per_hubp_debug_data {
		uint32_t hubp_underflow;
		uint32_t hubp_in_blank;
		uint32_t hubp_readline;
		uint32_t det_config_error;
	} hubps[MAX_PIPES];
	uint32_t curr_det_sizes[MAX_PIPES];
	uint32_t target_det_sizes[MAX_PIPES];
	uint32_t compbuf_config_error;
};

/*
 * Create a new surface with default parameters;
 */
@@ -2713,4 +2730,17 @@ bool dc_is_timing_changed(struct dc_stream_state *cur_stream,
bool dc_is_cursor_limit_pending(struct dc *dc);
bool dc_can_clear_cursor_limit(struct dc *dc);

/**
 * dc_get_underflow_debug_data_for_otg() - Retrieve underflow debug data.
 *
 * @dc: Pointer to the display core context.
 * @primary_otg_inst: Instance index of the primary OTG that underflowed.
 * @out_data: Pointer to a dc_underflow_debug_data struct to be filled with debug information.
 *
 * This function collects and logs underflow-related HW states when underflow happens,
 * including OTG underflow status, current read positions, frame count, and per-HUBP debug data.
 * The results are stored in the provided out_data structure for further analysis or logging.
 */
void dc_get_underflow_debug_data_for_otg(struct dc *dc, int primary_otg_inst, struct dc_underflow_debug_data *out_data);

#endif /* DC_INTERFACE_H_ */
+31 −0
Original line number Diff line number Diff line
@@ -440,6 +440,35 @@ void hubbub3_init_watermarks(struct hubbub *hubbub)
	REG_WRITE(DCHUBBUB_ARB_ALLOW_DRAM_CLK_CHANGE_WATERMARK_D, reg);
}

void hubbub3_get_det_sizes(struct hubbub *hubbub, uint32_t *curr_det_sizes, uint32_t *target_det_sizes)
{
	struct dcn20_hubbub *hubbub1 = TO_DCN20_HUBBUB(hubbub);

	REG_GET_2(DCHUBBUB_DET0_CTRL, DET0_SIZE_CURRENT, &curr_det_sizes[0],
		DET0_SIZE, &target_det_sizes[0]);

	REG_GET_2(DCHUBBUB_DET1_CTRL, DET1_SIZE_CURRENT, &curr_det_sizes[1],
		DET1_SIZE, &target_det_sizes[1]);

	REG_GET_2(DCHUBBUB_DET2_CTRL, DET2_SIZE_CURRENT, &curr_det_sizes[2],
		DET2_SIZE, &target_det_sizes[2]);

	REG_GET_2(DCHUBBUB_DET3_CTRL, DET3_SIZE_CURRENT, &curr_det_sizes[3],
		DET3_SIZE, &target_det_sizes[3]);

}

uint32_t hubbub3_compbuf_config_error(struct hubbub *hubbub)
{
	struct dcn20_hubbub *hubbub1 = TO_DCN20_HUBBUB(hubbub);
	uint32_t compbuf_config_error = 0;

	REG_GET(DCHUBBUB_COMPBUF_CTRL, CONFIG_ERROR,
		&compbuf_config_error);

	return compbuf_config_error;
}

static const struct hubbub_funcs hubbub30_funcs = {
	.update_dchub = hubbub2_update_dchub,
	.init_dchub_sys_ctx = hubbub3_init_dchub_sys_ctx,
@@ -457,6 +486,8 @@ static const struct hubbub_funcs hubbub30_funcs = {
	.force_pstate_change_control = hubbub3_force_pstate_change_control,
	.init_watermarks = hubbub3_init_watermarks,
	.hubbub_read_state = hubbub2_read_state,
	.get_det_sizes = hubbub3_get_det_sizes,
	.compbuf_config_error = hubbub3_compbuf_config_error,
};

void hubbub3_construct(struct dcn20_hubbub *hubbub3,
+6 −0
Original line number Diff line number Diff line
@@ -133,4 +133,10 @@ void hubbub3_force_pstate_change_control(struct hubbub *hubbub,

void hubbub3_init_watermarks(struct hubbub *hubbub);

void hubbub3_get_det_sizes(struct hubbub *hubbub,
	uint32_t *curr_det_sizes,
	uint32_t *target_det_sizes);

uint32_t hubbub3_compbuf_config_error(struct hubbub *hubbub);

#endif
+2 −0
Original line number Diff line number Diff line
@@ -1071,6 +1071,8 @@ static const struct hubbub_funcs hubbub31_funcs = {
	.program_compbuf_size = dcn31_program_compbuf_size,
	.init_crb = dcn31_init_crb,
	.hubbub_read_state = hubbub2_read_state,
	.get_det_sizes = hubbub3_get_det_sizes,
	.compbuf_config_error = hubbub3_compbuf_config_error,
};

void hubbub31_construct(struct dcn20_hubbub *hubbub31,
Loading