Commit 0c0a1943 authored by Chris Park's avatar Chris Park Committed by Alex Deucher
Browse files

drm/amd/display: Add hblank borrowing support



[WHY]
Some DSC timing failed at bandwidth validation due to hactive
can't be evenly divided on each ODM segment.

[HOW]
Borrow from hblank to increase hactive to support these timing.

Cc: Mario Limonciello <mario.limonciello@amd.com>
Cc: Alex Deucher <alexander.deucher@amd.com>
Cc: stable@vger.kernel.org
Reviewed-by: default avatarWenjing Liu <wenjing.liu@amd.com>
Signed-off-by: default avatarChris Park <chris.park@amd.com>
Signed-off-by: default avatarAlex Hung <alex.hung@amd.com>
Tested-by: default avatarDaniel Wheeler <daniel.wheeler@amd.com>
Signed-off-by: default avatarAlex Deucher <alexander.deucher@amd.com>
parent a29997b7
Loading
Loading
Loading
Loading
+41 −1
Original line number Diff line number Diff line
@@ -2094,7 +2094,8 @@ int resource_get_odm_slice_dst_width(struct pipe_ctx *otg_master,
	count = resource_get_odm_slice_count(otg_master);
	h_active = timing->h_addressable +
			timing->h_border_left +
			timing->h_border_right;
			timing->h_border_right +
			otg_master->hblank_borrow;
	width = h_active / count;

	if (otg_master->stream_res.tg)
@@ -4026,6 +4027,41 @@ enum dc_status dc_validate_with_context(struct dc *dc,
	return res;
}

/**
 * decide_hblank_borrow - Decides the horizontal blanking borrow value for a given pipe context.
 * @pipe_ctx: Pointer to the pipe context structure.
 *
 * This function calculates the horizontal blanking borrow value for a given pipe context based on the
 * display stream compression (DSC) configuration. If the horizontal active pixels (hactive) are less
 * than the total width of the DSC slices, it sets the hblank_borrow value to the difference. If the
 * total horizontal timing minus the hblank_borrow value is less than 32, it resets the hblank_borrow
 * value to 0.
 */
static void decide_hblank_borrow(struct pipe_ctx *pipe_ctx)
{
	uint32_t hactive;
	uint32_t ceil_slice_width;
	struct dc_stream_state *stream = NULL;

	if (!pipe_ctx)
		return;

	stream = pipe_ctx->stream;

	if (stream->timing.flags.DSC) {
		hactive = stream->timing.h_addressable + stream->timing.h_border_left + stream->timing.h_border_right;

		/* Assume if determined slices does not divide Hactive evenly, Hborrow is needed for padding*/
		if (hactive % stream->timing.dsc_cfg.num_slices_h != 0) {
			ceil_slice_width = (hactive / stream->timing.dsc_cfg.num_slices_h) + 1;
			pipe_ctx->hblank_borrow = ceil_slice_width * stream->timing.dsc_cfg.num_slices_h - hactive;

			if (stream->timing.h_total - hactive - pipe_ctx->hblank_borrow < 32)
				pipe_ctx->hblank_borrow = 0;
		}
	}
}

/**
 * dc_validate_global_state() - Determine if hardware can support a given state
 *
@@ -4064,6 +4100,10 @@ enum dc_status dc_validate_global_state(
			if (pipe_ctx->stream != stream)
				continue;

			/* Decide whether hblank borrow is needed and save it in pipe_ctx */
			if (dc->debug.enable_hblank_borrow)
				decide_hblank_borrow(pipe_ctx);

			if (dc->res_pool->funcs->patch_unknown_plane_state &&
					pipe_ctx->plane_state &&
					pipe_ctx->plane_state->tiling_info.gfx9.swizzle == DC_SW_UNKNOWN) {
+1 −0
Original line number Diff line number Diff line
@@ -1069,6 +1069,7 @@ struct dc_debug_options {
	unsigned int scale_to_sharpness_policy;
	bool skip_full_updated_if_possible;
	unsigned int enable_oled_edp_power_up_opt;
	bool enable_hblank_borrow;
};


+1 −1
Original line number Diff line number Diff line
@@ -120,7 +120,7 @@ void translate_SPL_in_params_from_pipe_ctx(struct pipe_ctx *pipe_ctx, struct spl
	spl_in->odm_slice_index = resource_get_odm_slice_index(pipe_ctx);
	// Make spl input basic out info output_size width point to stream h active
	spl_in->basic_out.output_size.width =
		stream->timing.h_addressable + stream->timing.h_border_left + stream->timing.h_border_right;
		stream->timing.h_addressable + stream->timing.h_border_left + stream->timing.h_border_right + pipe_ctx->hblank_borrow;
	// Make spl input basic out info output_size height point to v active
	spl_in->basic_out.output_size.height =
		stream->timing.v_addressable + stream->timing.v_border_bottom + stream->timing.v_border_top;
+19 −2
Original line number Diff line number Diff line
@@ -445,6 +445,21 @@ static void populate_dml21_timing_config_from_stream_state(struct dml2_timing_cf
	timing->vblank_nom = timing->v_total - timing->v_active;
}

/**
 * adjust_dml21_hblank_timing_config_from_pipe_ctx - Adjusts the horizontal blanking timing configuration
 *                                                   based on the pipe context.
 * @timing: Pointer to the dml2_timing_cfg structure to be adjusted.
 * @pipe: Pointer to the pipe_ctx structure containing the horizontal blanking borrow value.
 *
 * This function modifies the horizontal active and blank end timings by adding and subtracting
 * the horizontal blanking borrow value from the pipe context, respectively.
 */
static void adjust_dml21_hblank_timing_config_from_pipe_ctx(struct dml2_timing_cfg *timing, struct pipe_ctx *pipe)
{
	timing->h_active += pipe->hblank_borrow;
	timing->h_blank_end -= pipe->hblank_borrow;
}

static void populate_dml21_output_config_from_stream_state(struct dml2_link_output_cfg *output,
		struct dc_stream_state *stream, const struct pipe_ctx *pipe)
{
@@ -732,6 +747,7 @@ static const struct scaler_data *get_scaler_data_for_plane(
			temp_pipe->plane_state = pipe->plane_state;
			temp_pipe->plane_res.scl_data.taps = pipe->plane_res.scl_data.taps;
			temp_pipe->stream_res = pipe->stream_res;
			temp_pipe->hblank_borrow = pipe->hblank_borrow;
			dml_ctx->config.callbacks.build_scaling_params(temp_pipe);
			break;
		}
@@ -996,6 +1012,7 @@ bool dml21_map_dc_state_into_dml_display_cfg(const struct dc *in_dc, struct dc_s

		ASSERT(disp_cfg_stream_location >= 0 && disp_cfg_stream_location <= __DML2_WRAPPER_MAX_STREAMS_PLANES__);
		populate_dml21_timing_config_from_stream_state(&dml_dispcfg->stream_descriptors[disp_cfg_stream_location].timing, context->streams[stream_index], dml_ctx);
		adjust_dml21_hblank_timing_config_from_pipe_ctx(&dml_dispcfg->stream_descriptors[disp_cfg_stream_location].timing, &context->res_ctx.pipe_ctx[stream_index]);
		populate_dml21_output_config_from_stream_state(&dml_dispcfg->stream_descriptors[disp_cfg_stream_location].output, context->streams[stream_index], &context->res_ctx.pipe_ctx[stream_index]);
		populate_dml21_stream_overrides_from_stream_state(&dml_dispcfg->stream_descriptors[disp_cfg_stream_location], context->streams[stream_index]);

@@ -1134,12 +1151,12 @@ void dml21_populate_pipe_ctx_dlg_params(struct dml2_context *dml_ctx, struct dc_
	struct dc_crtc_timing *timing = &pipe_ctx->stream->timing;
	union dml2_global_sync_programming *global_sync = &stream_programming->global_sync;

	hactive = timing->h_addressable + timing->h_border_left + timing->h_border_right;
	hactive = timing->h_addressable + timing->h_border_left + timing->h_border_right + pipe_ctx->hblank_borrow;
	vactive = timing->v_addressable + timing->v_border_bottom + timing->v_border_top;
	hblank_start = pipe_ctx->stream->timing.h_total - pipe_ctx->stream->timing.h_front_porch;
	vblank_start = pipe_ctx->stream->timing.v_total - pipe_ctx->stream->timing.v_front_porch;

	hblank_end = hblank_start - timing->h_addressable - timing->h_border_left - timing->h_border_right;
	hblank_end = hblank_start - timing->h_addressable - timing->h_border_left - timing->h_border_right - pipe_ctx->hblank_borrow;
	vblank_end = vblank_start - timing->v_addressable - timing->v_border_top - timing->v_border_bottom;

	if (dml_ctx->config.svp_pstate.callbacks.get_pipe_subvp_type(context, pipe_ctx) == SUBVP_PHANTOM) {
+2 −1
Original line number Diff line number Diff line
@@ -1049,7 +1049,8 @@ void dcn32_update_dsc_on_stream(struct pipe_ctx *pipe_ctx, bool enable)
		}

		/* Enable DSC hw block */
		dsc_cfg.pic_width = (stream->timing.h_addressable + stream->timing.h_border_left + stream->timing.h_border_right) / opp_cnt;
		dsc_cfg.pic_width = (stream->timing.h_addressable + pipe_ctx->hblank_borrow +
				stream->timing.h_border_left + stream->timing.h_border_right) / opp_cnt;
		dsc_cfg.pic_height = stream->timing.v_addressable + stream->timing.v_border_top + stream->timing.v_border_bottom;
		dsc_cfg.pixel_encoding = stream->timing.pixel_encoding;
		dsc_cfg.color_depth = stream->timing.display_color_depth;
Loading