Commit 88ef4c5b authored by Samson Tam's avatar Samson Tam Committed by Alex Deucher
Browse files

drm/amd/display: Apply ODM 2:1 policy for single display configuration



[Why]
Most of the time, a single display uses the ODM combine. When using
multi-display, we use ODM combine only if it is necessary. These cases
are not flexible enough for us, and we can improve them to take
advantage of our hardware. We want to have more control over the ODM
policy.

[How]
This commit add a new debug flag named
enable_single_display_2to1_odm_policy to control the ODM policy and
another flag named enable_dp_dig_pixel_rate_div_policy to fine control
the ODM combine. This is possible by adding a new "pipe.dest" parameter
that can be set to ODM 2:1 combined if we use a single display. For
dynamic ODM combine, when using DP-DIG, DCN applies K2=2 settings for
ODM combine. Note that this feature affects the following registers:

- timing.pix_clk_100khz -> DP_VID_M, DP_VID_N
- requested_pix_clk_100hz -> DP_DTOn_PHASE
- OTGn_PIXEL_RATE_DIVK2
- DP_PIXEL_PER_CYCLE_PROCESSING_MODE
- DIG_FIFO_OUTPUT_PIXEL_MODE
- DP_VID_N_MUL

Acked-by: default avatarRodrigo Siqueira <Rodrigo.Siqueira@amd.com>
Signed-off-by: default avatarSamson Tam <Samson.Tam@amd.com>
Tested-by: default avatarDaniel Wheeler <daniel.wheeler@amd.com>
Signed-off-by: default avatarAlex Deucher <alexander.deucher@amd.com>
parent 64a30aaf
Loading
Loading
Loading
Loading
+2 −0
Original line number Diff line number Diff line
@@ -748,6 +748,8 @@ struct dc_debug_options {
	enum dml_hostvm_override_opts dml_hostvm_override;
	bool use_legacy_soc_bb_mechanism;
	bool exit_idle_opt_for_cursor_updates;
	bool enable_single_display_2to1_odm_policy;
	bool enable_dp_dig_pixel_rate_div_policy;
};

struct gpu_info_soc_bounding_box_v1_0;
+7 −0
Original line number Diff line number Diff line
@@ -1237,6 +1237,8 @@ static void get_pixel_clock_parameters(
	int opp_cnt = 1;
	struct dc_link *link = stream->link;
	struct link_encoder *link_enc = NULL;
	struct dc *dc = pipe_ctx->stream->ctx->dc;
	struct dce_hwseq *hws = dc->hwseq;

	for (odm_pipe = pipe_ctx->next_odm_pipe; odm_pipe; odm_pipe = odm_pipe->next_odm_pipe)
		opp_cnt++;
@@ -1268,6 +1270,11 @@ static void get_pixel_clock_parameters(
	else if (optc2_is_two_pixels_per_containter(&stream->timing) || opp_cnt == 2)
		pixel_clk_params->requested_pix_clk_100hz /= 2;

	else if (hws->funcs.is_dp_dig_pixel_rate_div_policy) {
		if (hws->funcs.is_dp_dig_pixel_rate_div_policy(pipe_ctx))
			pixel_clk_params->requested_pix_clk_100hz /= 2;
	}

	if (stream->timing.timing_3d_format == TIMING_3D_FORMAT_HW_FRAME_PACKING)
		pixel_clk_params->requested_pix_clk_100hz *= 2;

+3 −1
Original line number Diff line number Diff line
@@ -249,6 +249,7 @@ static void enc32_stream_encoder_dp_unblank(
		const struct encoder_unblank_param *param)
{
	struct dcn10_stream_encoder *enc1 = DCN10STRENC_FROM_STRENC(enc);
	struct dc *dc = enc->ctx->dc;

	if (param->link_settings.link_rate != LINK_RATE_UNKNOWN) {
		uint32_t n_vid = 0x8000;
@@ -257,7 +258,8 @@ static void enc32_stream_encoder_dp_unblank(
		uint64_t m_vid_l = n_vid;

		/* YCbCr 4:2:0 : Computed VID_M will be 2X the input rate */
		if (is_two_pixels_per_containter(&param->timing) || param->opp_cnt > 1) {
		if (is_two_pixels_per_containter(&param->timing) || param->opp_cnt > 1
			|| dc->debug.enable_dp_dig_pixel_rate_div_policy) {
			/*this logic should be the same in get_pixel_clock_parameters() */
			n_multiply = 1;
		}
+54 −4
Original line number Diff line number Diff line
@@ -1083,6 +1083,7 @@ unsigned int dcn32_calculate_dccg_k1_k2_values(struct pipe_ctx *pipe_ctx, unsign
{
	struct dc_stream_state *stream = pipe_ctx->stream;
	unsigned int odm_combine_factor = 0;
	struct dc *dc = pipe_ctx->stream->ctx->dc;

	odm_combine_factor = get_odm_config(pipe_ctx, NULL);

@@ -1102,9 +1103,7 @@ unsigned int dcn32_calculate_dccg_k1_k2_values(struct pipe_ctx *pipe_ctx, unsign
			*k1_div = PIXEL_RATE_DIV_BY_2;
			*k2_div = PIXEL_RATE_DIV_BY_2;
		} else {
			if (odm_combine_factor == 1)
				*k2_div = PIXEL_RATE_DIV_BY_4;
			else if (odm_combine_factor == 2)
			if ((odm_combine_factor == 2) || dc->debug.enable_dp_dig_pixel_rate_div_policy)
				*k2_div = PIXEL_RATE_DIV_BY_2;
		}
	}
@@ -1124,10 +1123,61 @@ void dcn32_set_pixels_per_cycle(struct pipe_ctx *pipe_ctx)
		return;

	odm_combine_factor = get_odm_config(pipe_ctx, NULL);
	if (optc2_is_two_pixels_per_containter(&pipe_ctx->stream->timing) || odm_combine_factor > 1)
	if (optc2_is_two_pixels_per_containter(&pipe_ctx->stream->timing) || odm_combine_factor > 1
		|| dcn32_is_dp_dig_pixel_rate_div_policy(pipe_ctx))
		pix_per_cycle = 2;

	if (pipe_ctx->stream_res.stream_enc->funcs->set_input_mode)
		pipe_ctx->stream_res.stream_enc->funcs->set_input_mode(pipe_ctx->stream_res.stream_enc,
				pix_per_cycle);
}

void dcn32_unblank_stream(struct pipe_ctx *pipe_ctx,
		struct dc_link_settings *link_settings)
{
	struct encoder_unblank_param params = {0};
	struct dc_stream_state *stream = pipe_ctx->stream;
	struct dc_link *link = stream->link;
	struct dce_hwseq *hws = link->dc->hwseq;
	struct pipe_ctx *odm_pipe;
	struct dc *dc = pipe_ctx->stream->ctx->dc;
	uint32_t pix_per_cycle = 1;

	params.opp_cnt = 1;
	for (odm_pipe = pipe_ctx->next_odm_pipe; odm_pipe; odm_pipe = odm_pipe->next_odm_pipe)
		params.opp_cnt++;

	/* only 3 items below are used by unblank */
	params.timing = pipe_ctx->stream->timing;

	params.link_settings.link_rate = link_settings->link_rate;

	if (is_dp_128b_132b_signal(pipe_ctx)) {
		/* TODO - DP2.0 HW: Set ODM mode in dp hpo encoder here */
		pipe_ctx->stream_res.hpo_dp_stream_enc->funcs->dp_unblank(
				pipe_ctx->stream_res.hpo_dp_stream_enc,
				pipe_ctx->stream_res.tg->inst);
	} else if (dc_is_dp_signal(pipe_ctx->stream->signal)) {
		if (optc2_is_two_pixels_per_containter(&stream->timing) || params.opp_cnt > 1
			|| dc->debug.enable_dp_dig_pixel_rate_div_policy) {
			params.timing.pix_clk_100hz /= 2;
			pix_per_cycle = 2;
		}
		pipe_ctx->stream_res.stream_enc->funcs->dp_set_odm_combine(
				pipe_ctx->stream_res.stream_enc, pix_per_cycle > 1);
		pipe_ctx->stream_res.stream_enc->funcs->dp_unblank(link, pipe_ctx->stream_res.stream_enc, &params);
	}

	if (link->local_sink && link->local_sink->sink_signal == SIGNAL_TYPE_EDP)
		hws->funcs.edp_backlight_control(link, true);
}

bool dcn32_is_dp_dig_pixel_rate_div_policy(struct pipe_ctx *pipe_ctx)
{
	struct dc *dc = pipe_ctx->stream->ctx->dc;

	if (dc_is_dp_signal(pipe_ctx->stream->signal) && !is_dp_128b_132b_signal(pipe_ctx) &&
		dc->debug.enable_dp_dig_pixel_rate_div_policy)
		return true;
	return false;
}
+5 −0
Original line number Diff line number Diff line
@@ -79,4 +79,9 @@ void dcn32_subvp_pipe_control_lock(struct dc *dc,
		struct pipe_ctx *top_pipe_to_program,
		bool subvp_prev_use);

void dcn32_unblank_stream(struct pipe_ctx *pipe_ctx,
		struct dc_link_settings *link_settings);

bool dcn32_is_dp_dig_pixel_rate_div_policy(struct pipe_ctx *pipe_ctx);

#endif /* __DC_HWSS_DCN32_H__ */
Loading