Commit 8fa6f4c5 authored by Yi-Ling Chen's avatar Yi-Ling Chen Committed by Alex Deucher
Browse files

drm/amd/display: fixed the DSC power off sequence during Driver PnP



[WHY]
After unloading driver, driver would not disable DSC function.
At next loading driver, driver would power all DSC engines off.
When driver powered the active DSC off, the screen would be gray
until reprograming DSC relatived register correcntly.

[HOW]
1. Remove DSC Power down code into init_pipes()
2. Depend on  the OTG mapping information and DSC status to skip
power off for the working DSC.

Reviewed-by: default avatarAnthony Koo <Anthony.Koo@amd.com>
Acked-by: default avatarWayne Lin <wayne.lin@amd.com>
Signed-off-by: default avatarYi-Ling Chen <Yi-Ling.Chen2@amd.com>
Tested-by: default avatarDaniel Wheeler <daniel.wheeler@amd.com>
Signed-off-by: default avatarAlex Deucher <alexander.deucher@amd.com>
parent 3f232a0f
Loading
Loading
Loading
Loading
+37 −0
Original line number Diff line number Diff line
@@ -1362,6 +1362,43 @@ void dcn10_init_pipes(struct dc *dc, struct dc_state *context)

		tg->funcs->tg_init(tg);
	}

	/* Power gate DSCs */
	if (hws->funcs.dsc_pg_control != NULL) {
		uint32_t num_opps = 0;
		uint32_t opp_id_src0 = OPP_ID_INVALID;
		uint32_t opp_id_src1 = OPP_ID_INVALID;

		// Step 1: To find out which OPTC is running & OPTC DSC is ON
		for (i = 0; i < dc->res_pool->res_cap->num_timing_generator; i++) {
			uint32_t optc_dsc_state = 0;
			struct timing_generator *tg = dc->res_pool->timing_generators[i];

			if (tg->funcs->is_tg_enabled(tg)) {
				if (tg->funcs->get_dsc_status)
					tg->funcs->get_dsc_status(tg, &optc_dsc_state);
				// Only one OPTC with DSC is ON, so if we got one result, we would exit this block.
				// non-zero value is DSC enabled
				if (optc_dsc_state != 0) {
					tg->funcs->get_optc_source(tg, &num_opps, &opp_id_src0, &opp_id_src1);
					break;
				}
			}
		}

		// Step 2: To power down DSC but skip DSC  of running OPTC
		for (i = 0; i < dc->res_pool->res_cap->num_dsc; i++) {
			struct dcn_dsc_state s  = {0};

			dc->res_pool->dscs[i]->funcs->dsc_read_state(dc->res_pool->dscs[i], &s);

			if ((s.dsc_opp_source == opp_id_src0 || s.dsc_opp_source == opp_id_src1) &&
				s.dsc_clock_en && s.dsc_fw_en)
				continue;

			hws->funcs.dsc_pg_control(hws, dc->res_pool->dscs[i]->inst, false);
		}
	}
}

void dcn10_init_hw(struct dc *dc)
+2 −0
Original line number Diff line number Diff line
@@ -162,6 +162,8 @@ static void dsc2_read_state(struct display_stream_compressor *dsc, struct dcn_ds
	REG_GET(DSCC_PPS_CONFIG2, PIC_WIDTH, &s->dsc_pic_width);
	REG_GET(DSCC_PPS_CONFIG2, PIC_HEIGHT, &s->dsc_pic_height);
	REG_GET(DSCC_PPS_CONFIG7, SLICE_BPG_OFFSET, &s->dsc_slice_bpg_offset);
	REG_GET_2(DSCRM_DSC_FORWARD_CONFIG, DSCRM_DSC_FORWARD_EN, &s->dsc_fw_en,
		DSCRM_DSC_OPP_PIPE_SOURCE, &s->dsc_opp_source);
}


+14 −0
Original line number Diff line number Diff line
@@ -190,6 +190,19 @@ void optc2_set_dsc_config(struct timing_generator *optc,
		OPTC_DSC_SLICE_WIDTH, dsc_slice_width);
}

/* Get DSC-related configuration.
 *   dsc_mode: 0 disables DSC, other values enable DSC in specified format
 */
void optc2_get_dsc_status(struct timing_generator *optc,
					uint32_t *dsc_mode)
{
	struct optc *optc1 = DCN10TG_FROM_TG(optc);

	REG_GET(OPTC_DATA_FORMAT_CONTROL,
		OPTC_DSC_MODE, dsc_mode);
}


/*TEMP: Need to figure out inheritance model here.*/
bool optc2_is_two_pixels_per_containter(const struct dc_crtc_timing *timing)
{
@@ -579,6 +592,7 @@ static struct timing_generator_funcs dcn20_tg_funcs = {
		.get_crc = optc1_get_crc,
		.configure_crc = optc2_configure_crc,
		.set_dsc_config = optc2_set_dsc_config,
		.get_dsc_status = optc2_get_dsc_status,
		.set_dwb_source = optc2_set_dwb_source,
		.set_odm_bypass = optc2_set_odm_bypass,
		.set_odm_combine = optc2_set_odm_combine,
+3 −0
Original line number Diff line number Diff line
@@ -98,6 +98,9 @@ void optc2_set_dsc_config(struct timing_generator *optc,
					uint32_t dsc_bytes_per_pixel,
					uint32_t dsc_slice_width);

void optc2_get_dsc_status(struct timing_generator *optc,
					uint32_t *dsc_mode);

void optc2_set_odm_bypass(struct timing_generator *optc,
		const struct dc_crtc_timing *dc_crtc_timing);

+1 −0
Original line number Diff line number Diff line
@@ -332,6 +332,7 @@ static struct timing_generator_funcs dcn30_tg_funcs = {
		.get_crc = optc1_get_crc,
		.configure_crc = optc2_configure_crc,
		.set_dsc_config = optc3_set_dsc_config,
		.get_dsc_status = optc2_get_dsc_status,
		.set_dwb_source = NULL,
		.set_odm_bypass = optc3_set_odm_bypass,
		.set_odm_combine = optc3_set_odm_combine,
Loading