Commit 176278d8 authored by Wenjing Liu's avatar Wenjing Liu Committed by Alex Deucher
Browse files

drm/amd/display: reset DSC clock in post unlock update



[why]
Switching between DSC clock or disable DSC block are not double buffered update.
Corruption is observed if these updates happen before DSC double buffered
disconnection.

[how]
Move DSC disable and refclk reset to post unlock update. Wait for DSC double buffered
disconnection and all mpccs are disconnected before reset DSC clock.

Reviewed-by: default avatarSamson Tam <samson.tam@amd.com>
Acked-by: default avatarTom Chung <chiahsuan.chung@amd.com>
Signed-off-by: default avatarWenjing Liu <wenjing.liu@amd.com>
Tested-by: default avatarDaniel Wheeler <daniel.wheeler@amd.com>
Signed-off-by: default avatarAlex Deucher <alexander.deucher@amd.com>
parent 3706bf2e
Loading
Loading
Loading
Loading
+10 −21
Original line number Diff line number Diff line
@@ -726,34 +726,35 @@ void dccg401_init(struct dccg *dccg)
	}
}

static void dccg401_set_dto_dscclk(struct dccg *dccg, uint32_t inst)
static void dccg401_set_dto_dscclk(struct dccg *dccg, uint32_t inst, bool enable)
{
	struct dcn_dccg *dccg_dcn = TO_DCN_DCCG(dccg);
	uint32_t phase = enable ? 1 : 0;

	switch (inst) {
	case 0:
		REG_UPDATE_2(DSCCLK_DTO_CTRL, DSCCLK0_EN, 1, DSCCLK0_DTO_DB_EN, 1);
		REG_UPDATE_2(DSCCLK0_DTO_PARAM,
				DSCCLK0_DTO_PHASE, 1,
				DSCCLK0_DTO_PHASE, phase,
				DSCCLK0_DTO_MODULO, 1);
		REG_UPDATE_2(DSCCLK_DTO_CTRL, DSCCLK0_EN, 1, DSCCLK0_DTO_DB_EN, 1);
		break;
	case 1:
		REG_UPDATE_2(DSCCLK_DTO_CTRL, DSCCLK1_EN, 1, DSCCLK1_DTO_DB_EN, 1);
		REG_UPDATE_2(DSCCLK1_DTO_PARAM,
				DSCCLK1_DTO_PHASE, 1,
				DSCCLK1_DTO_PHASE, phase,
				DSCCLK1_DTO_MODULO, 1);
		REG_UPDATE_2(DSCCLK_DTO_CTRL, DSCCLK1_EN, 1, DSCCLK1_DTO_DB_EN, 1);
		break;
	case 2:
		REG_UPDATE_2(DSCCLK_DTO_CTRL, DSCCLK2_EN, 1, DSCCLK2_DTO_DB_EN, 1);
		REG_UPDATE_2(DSCCLK2_DTO_PARAM,
				DSCCLK2_DTO_PHASE, 1,
				DSCCLK2_DTO_PHASE, phase,
				DSCCLK2_DTO_MODULO, 1);
		REG_UPDATE_2(DSCCLK_DTO_CTRL, DSCCLK2_EN, 1, DSCCLK2_DTO_DB_EN, 1);
		break;
	case 3:
		REG_UPDATE_2(DSCCLK_DTO_CTRL, DSCCLK3_EN, 1, DSCCLK3_DTO_DB_EN, 1);
		REG_UPDATE_2(DSCCLK3_DTO_PARAM,
				DSCCLK3_DTO_PHASE, 1,
				DSCCLK3_DTO_PHASE, phase,
				DSCCLK3_DTO_MODULO, 1);
		REG_UPDATE_2(DSCCLK_DTO_CTRL, DSCCLK3_EN, 1, DSCCLK3_DTO_DB_EN, 1);
		break;
	default:
		BREAK_TO_DEBUGGER();
@@ -769,27 +770,15 @@ static void dccg401_set_ref_dscclk(struct dccg *dccg,
	switch (dsc_inst) {
	case 0:
		REG_UPDATE(DSCCLK_DTO_CTRL, DSCCLK0_EN, 0);
		REG_UPDATE_2(DSCCLK0_DTO_PARAM,
				DSCCLK0_DTO_PHASE, 0,
				DSCCLK0_DTO_MODULO, 1);
		break;
	case 1:
		REG_UPDATE(DSCCLK_DTO_CTRL, DSCCLK1_EN, 0);
		REG_UPDATE_2(DSCCLK1_DTO_PARAM,
				DSCCLK1_DTO_PHASE, 0,
				DSCCLK1_DTO_MODULO, 1);
		break;
	case 2:
		REG_UPDATE(DSCCLK_DTO_CTRL, DSCCLK2_EN, 0);
		REG_UPDATE_2(DSCCLK2_DTO_PARAM,
				DSCCLK2_DTO_PHASE, 0,
				DSCCLK2_DTO_MODULO, 1);
		break;
	case 3:
		REG_UPDATE(DSCCLK_DTO_CTRL, DSCCLK3_EN, 0);
		REG_UPDATE_2(DSCCLK3_DTO_PARAM,
				DSCCLK3_DTO_PHASE, 0,
				DSCCLK3_DTO_MODULO, 1);
		break;
	default:
		return;
+11 −7
Original line number Diff line number Diff line
@@ -40,6 +40,7 @@ static void dsc2_set_config(struct display_stream_compressor *dsc, const struct
static void dsc2_enable(struct display_stream_compressor *dsc, int opp_pipe);
static void dsc2_disable(struct display_stream_compressor *dsc);
static void dsc2_disconnect(struct display_stream_compressor *dsc);
static void dsc2_wait_disconnect_pending_clear(struct display_stream_compressor *dsc);

static const struct dsc_funcs dcn20_dsc_funcs = {
	.dsc_get_enc_caps = dsc2_get_enc_caps,
@@ -50,6 +51,7 @@ static const struct dsc_funcs dcn20_dsc_funcs = {
	.dsc_enable = dsc2_enable,
	.dsc_disable = dsc2_disable,
	.dsc_disconnect = dsc2_disconnect,
	.dsc_wait_disconnect_pending_clear = dsc2_wait_disconnect_pending_clear,
};

/* Macro definitios for REG_SET macros*/
@@ -260,16 +262,12 @@ static void dsc2_disable(struct display_stream_compressor *dsc)
{
	struct dcn20_dsc *dsc20 = TO_DCN20_DSC(dsc);
	int dsc_clock_en;
	int dsc_fw_config;
	int enabled_opp_pipe;

	DC_LOG_DSC("disable DSC %d", dsc->inst);

	REG_GET(DSC_TOP_CONTROL, DSC_CLOCK_EN, &dsc_clock_en);
	REG_GET_2(DSCRM_DSC_FORWARD_CONFIG, DSCRM_DSC_FORWARD_EN, &dsc_fw_config, DSCRM_DSC_OPP_PIPE_SOURCE, &enabled_opp_pipe);
	if (!dsc_clock_en || !dsc_fw_config) {
		DC_LOG_DSC("ERROR: DSC %d at opp pipe %d already disabled!", dsc->inst, enabled_opp_pipe);
		ASSERT(0);
	if (!dsc_clock_en) {
		DC_LOG_DSC("DSC %d already disabled!", dsc->inst);
	}

	REG_UPDATE(DSCRM_DSC_FORWARD_CONFIG,
@@ -279,6 +277,13 @@ static void dsc2_disable(struct display_stream_compressor *dsc)
		DSC_CLOCK_EN, 0);
}

static void dsc2_wait_disconnect_pending_clear(struct display_stream_compressor *dsc)
{
	struct dcn20_dsc *dsc20 = TO_DCN20_DSC(dsc);

	REG_WAIT(DSCRM_DSC_FORWARD_CONFIG, DSCRM_DSC_DOUBLE_BUFFER_REG_UPDATE_PENDING, 0, 2, 50000);
}

static void dsc2_disconnect(struct display_stream_compressor *dsc)
{
	struct dcn20_dsc *dsc20 = TO_DCN20_DSC(dsc);
@@ -777,4 +782,3 @@ static void dsc_write_to_registers(struct display_stream_compressor *dsc, const
		RANGE_BPG_OFFSET14, reg_vals->pps.rc_range_params[14].range_bpg_offset);

}
+2 −1
Original line number Diff line number Diff line
@@ -453,7 +453,8 @@
	type DSCCIF_UPDATE_TAKEN_STATUS; \
	type DSCCIF_UPDATE_TAKEN_ACK; \
	type DSCRM_DSC_FORWARD_EN; \
	type DSCRM_DSC_OPP_PIPE_SOURCE
	type DSCRM_DSC_OPP_PIPE_SOURCE; \
	type DSCRM_DSC_DOUBLE_BUFFER_REG_UPDATE_PENDING

struct dcn20_dsc_registers {
	uint32_t DSC_TOP_CONTROL;
+11 −6
Original line number Diff line number Diff line
@@ -21,6 +21,7 @@ static void dsc401_set_config(struct display_stream_compressor *dsc, const struc
static void dsc401_enable(struct display_stream_compressor *dsc, int opp_pipe);
static void dsc401_disable(struct display_stream_compressor *dsc);
static void dsc401_disconnect(struct display_stream_compressor *dsc);
static void dsc401_wait_disconnect_pending_clear(struct display_stream_compressor *dsc);

const struct dsc_funcs dcn401_dsc_funcs = {
	.dsc_get_enc_caps = dsc2_get_enc_caps,
@@ -31,6 +32,7 @@ const struct dsc_funcs dcn401_dsc_funcs = {
	.dsc_enable = dsc401_enable,
	.dsc_disable = dsc401_disable,
	.dsc_disconnect = dsc401_disconnect,
	.dsc_wait_disconnect_pending_clear = dsc401_wait_disconnect_pending_clear,
};

/* Macro definitios for REG_SET macros*/
@@ -231,16 +233,12 @@ static void dsc401_disable(struct display_stream_compressor *dsc)
{
	struct dcn401_dsc *dsc401 = TO_DCN401_DSC(dsc);
	int dsc_clock_en;
	int dsc_fw_config;
	int enabled_opp_pipe;

	DC_LOG_DSC("disable DSC %d", dsc->inst);

	REG_GET(DSC_TOP_CONTROL, DSC_CLOCK_EN, &dsc_clock_en);
	REG_GET_2(DSCRM_DSC_FORWARD_CONFIG, DSCRM_DSC_FORWARD_EN, &dsc_fw_config, DSCRM_DSC_OPP_PIPE_SOURCE, &enabled_opp_pipe);
	if (!dsc_clock_en || !dsc_fw_config) {
		DC_LOG_DSC("ERROR: DSC %d at opp pipe %d already disabled!", dsc->inst, enabled_opp_pipe);
		ASSERT(0);
	if (!dsc_clock_en) {
		DC_LOG_DSC("DSC %d already disabled!", dsc->inst);
	}

	REG_UPDATE(DSCRM_DSC_FORWARD_CONFIG,
@@ -250,6 +248,13 @@ static void dsc401_disable(struct display_stream_compressor *dsc)
		DSC_CLOCK_EN, 0);
}

static void dsc401_wait_disconnect_pending_clear(struct display_stream_compressor *dsc)
{
	struct dcn401_dsc *dsc401 = TO_DCN401_DSC(dsc);

	REG_WAIT(DSCRM_DSC_FORWARD_CONFIG, DSCRM_DSC_DOUBLE_BUFFER_REG_UPDATE_PENDING, 0, 2, 50000);
}

static void dsc401_disconnect(struct display_stream_compressor *dsc)
{
	struct dcn401_dsc *dsc401 = TO_DCN401_DSC(dsc);
+1 −0
Original line number Diff line number Diff line
@@ -107,6 +107,7 @@ struct dsc_funcs {
	void (*dsc_enable)(struct display_stream_compressor *dsc, int opp_pipe);
	void (*dsc_disable)(struct display_stream_compressor *dsc);
	void (*dsc_disconnect)(struct display_stream_compressor *dsc);
	void (*dsc_wait_disconnect_pending_clear)(struct display_stream_compressor *dsc);
};

#endif
Loading