Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit eb6b29d6 authored by Jun Lei's avatar Jun Lei Committed by Alex Deucher
Browse files

drm/amd/display: make underflow status clear explicit



[why]
HUBP underflow is never cleared, which causes underflow in one
test to fail another test, violating the independence requirements

[how]
Rather than make clearing implicit, we explicitly clear underflow
status in DTN.

Signed-off-by: default avatarJun Lei <Jun.Lei@amd.com>
Reviewed-by: default avatarTony Cheng <Tony.Cheng@amd.com>
Acked-by: default avatarBhawanpreet Lakha <Bhawanpreet.Lakha@amd.com>
Signed-off-by: default avatarAlex Deucher <alexander.deucher@amd.com>
parent 261f3924
Loading
Loading
Loading
Loading
+9 −0
Original line number Original line Diff line number Diff line
@@ -99,6 +99,14 @@ static unsigned int hubp1_get_underflow_status(struct hubp *hubp)
	return hubp_underflow;
	return hubp_underflow;
}
}



void hubp1_clear_underflow(struct hubp *hubp)
{
	struct dcn10_hubp *hubp1 = TO_DCN10_HUBP(hubp);

	REG_UPDATE(DCHUBP_CNTL, HUBP_UNDERFLOW_CLEAR, 1);
}

static void hubp1_set_hubp_blank_en(struct hubp *hubp, bool blank)
static void hubp1_set_hubp_blank_en(struct hubp *hubp, bool blank)
{
{
	struct dcn10_hubp *hubp1 = TO_DCN10_HUBP(hubp);
	struct dcn10_hubp *hubp1 = TO_DCN10_HUBP(hubp);
@@ -1190,6 +1198,7 @@ static const struct hubp_funcs dcn10_hubp_funcs = {
	.hubp_clk_cntl = hubp1_clk_cntl,
	.hubp_clk_cntl = hubp1_clk_cntl,
	.hubp_vtg_sel = hubp1_vtg_sel,
	.hubp_vtg_sel = hubp1_vtg_sel,
	.hubp_read_state = hubp1_read_state,
	.hubp_read_state = hubp1_read_state,
	.hubp_clear_underflow = hubp1_clear_underflow,
	.hubp_disable_control =  hubp1_disable_control,
	.hubp_disable_control =  hubp1_disable_control,
	.hubp_get_underflow_status = hubp1_get_underflow_status,
	.hubp_get_underflow_status = hubp1_get_underflow_status,


+3 −0
Original line number Original line Diff line number Diff line
@@ -251,6 +251,7 @@
	HUBP_SF(HUBP0_DCHUBP_CNTL, HUBP_BLANK_EN, mask_sh),\
	HUBP_SF(HUBP0_DCHUBP_CNTL, HUBP_BLANK_EN, mask_sh),\
	HUBP_SF(HUBP0_DCHUBP_CNTL, HUBP_TTU_DISABLE, mask_sh),\
	HUBP_SF(HUBP0_DCHUBP_CNTL, HUBP_TTU_DISABLE, mask_sh),\
	HUBP_SF(HUBP0_DCHUBP_CNTL, HUBP_UNDERFLOW_STATUS, mask_sh),\
	HUBP_SF(HUBP0_DCHUBP_CNTL, HUBP_UNDERFLOW_STATUS, mask_sh),\
	HUBP_SF(HUBP0_DCHUBP_CNTL, HUBP_UNDERFLOW_CLEAR, mask_sh),\
	HUBP_SF(HUBP0_DCHUBP_CNTL, HUBP_NO_OUTSTANDING_REQ, mask_sh),\
	HUBP_SF(HUBP0_DCHUBP_CNTL, HUBP_NO_OUTSTANDING_REQ, mask_sh),\
	HUBP_SF(HUBP0_DCHUBP_CNTL, HUBP_VTG_SEL, mask_sh),\
	HUBP_SF(HUBP0_DCHUBP_CNTL, HUBP_VTG_SEL, mask_sh),\
	HUBP_SF(HUBP0_DCHUBP_CNTL, HUBP_DISABLE, mask_sh),\
	HUBP_SF(HUBP0_DCHUBP_CNTL, HUBP_DISABLE, mask_sh),\
@@ -435,6 +436,7 @@
	type HUBP_NO_OUTSTANDING_REQ;\
	type HUBP_NO_OUTSTANDING_REQ;\
	type HUBP_VTG_SEL;\
	type HUBP_VTG_SEL;\
	type HUBP_UNDERFLOW_STATUS;\
	type HUBP_UNDERFLOW_STATUS;\
	type HUBP_UNDERFLOW_CLEAR;\
	type NUM_PIPES;\
	type NUM_PIPES;\
	type NUM_BANKS;\
	type NUM_BANKS;\
	type PIPE_INTERLEAVE;\
	type PIPE_INTERLEAVE;\
@@ -739,6 +741,7 @@ void dcn10_hubp_construct(
	const struct dcn_mi_mask *hubp_mask);
	const struct dcn_mi_mask *hubp_mask);


void hubp1_read_state(struct hubp *hubp);
void hubp1_read_state(struct hubp *hubp);
void hubp1_clear_underflow(struct hubp *hubp);


enum cursor_pitch hubp1_get_cursor_pitch(unsigned int pitch);
enum cursor_pitch hubp1_get_cursor_pitch(unsigned int pitch);


+1 −0
Original line number Original line Diff line number Diff line
@@ -2710,6 +2710,7 @@ static const struct hw_sequencer_funcs dcn10_funcs = {
	.set_avmute = dce110_set_avmute,
	.set_avmute = dce110_set_avmute,
	.log_hw_state = dcn10_log_hw_state,
	.log_hw_state = dcn10_log_hw_state,
	.get_hw_state = dcn10_get_hw_state,
	.get_hw_state = dcn10_get_hw_state,
	.clear_status_bits = dcn10_clear_status_bits,
	.wait_for_mpcc_disconnect = dcn10_wait_for_mpcc_disconnect,
	.wait_for_mpcc_disconnect = dcn10_wait_for_mpcc_disconnect,
	.edp_backlight_control = hwss_edp_backlight_control,
	.edp_backlight_control = hwss_edp_backlight_control,
	.edp_power_control = hwss_edp_power_control,
	.edp_power_control = hwss_edp_power_control,
+2 −0
Original line number Original line Diff line number Diff line
@@ -51,6 +51,8 @@ void dcn10_get_hw_state(
		char *pBuf, unsigned int bufSize,
		char *pBuf, unsigned int bufSize,
		unsigned int mask);
		unsigned int mask);


void dcn10_clear_status_bits(struct dc *dc, unsigned int mask);

bool is_lower_pipe_tree_visible(struct pipe_ctx *pipe_ctx);
bool is_lower_pipe_tree_visible(struct pipe_ctx *pipe_ctx);


bool is_upper_pipe_tree_visible(struct pipe_ctx *pipe_ctx);
bool is_upper_pipe_tree_visible(struct pipe_ctx *pipe_ctx);
+53 −6
Original line number Original line Diff line number Diff line
@@ -454,12 +454,6 @@ static unsigned int dcn10_get_otg_states(struct dc *dc, char *pBuf, unsigned int


			remaining_buffer -= chars_printed;
			remaining_buffer -= chars_printed;
			pBuf += chars_printed;
			pBuf += chars_printed;

			// Clear underflow for debug purposes
			// We want to keep underflow sticky bit on for the longevity tests outside of test environment.
			// This function is called only from Windows or Diags test environment, hence it's safe to clear
			// it from here without affecting the original intent.
			tg->funcs->clear_optc_underflow(tg);
		}
		}
	}
	}


@@ -484,6 +478,59 @@ static unsigned int dcn10_get_clock_states(struct dc *dc, char *pBuf, unsigned i
	return chars_printed;
	return chars_printed;
}
}


static void dcn10_clear_otpc_underflow(struct dc *dc)
{
	struct resource_pool *pool = dc->res_pool;
	int i;

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

		optc1_read_otg_state(DCN10TG_FROM_TG(tg), &s);

		if (s.otg_enabled & 1)
			tg->funcs->clear_optc_underflow(tg);
	}
}

static void dcn10_clear_hubp_underflow(struct dc *dc)
{
	struct resource_pool *pool = dc->res_pool;
	int i;

	for (i = 0; i < pool->pipe_count; i++) {
		struct hubp *hubp = pool->hubps[i];
		struct dcn_hubp_state *s = &(TO_DCN10_HUBP(hubp)->state);

		hubp->funcs->hubp_read_state(hubp);

		if (!s->blank_en)
			hubp->funcs->hubp_clear_underflow(hubp);
	}
}

void dcn10_clear_status_bits(struct dc *dc, unsigned int mask)
{
	/*
	 *  Mask Format
	 *  Bit 0 - 31: Status bit to clear
	 *
	 *  Mask = 0x0 means clear all status bits
	 */
	const unsigned int DC_HW_STATE_MASK_HUBP_UNDERFLOW	= 0x1;
	const unsigned int DC_HW_STATE_MASK_OTPC_UNDERFLOW	= 0x2;

	if (mask == 0x0)
		mask = 0xFFFFFFFF;

	if (mask & DC_HW_STATE_MASK_HUBP_UNDERFLOW)
		dcn10_clear_hubp_underflow(dc);

	if (mask & DC_HW_STATE_MASK_OTPC_UNDERFLOW)
		dcn10_clear_otpc_underflow(dc);
}

void dcn10_get_hw_state(struct dc *dc, char *pBuf, unsigned int bufSize, unsigned int mask)
void dcn10_get_hw_state(struct dc *dc, char *pBuf, unsigned int bufSize, unsigned int mask)
{
{
	/*
	/*
Loading