Commit 799a5f74 authored by Wenjing Liu's avatar Wenjing Liu Committed by Alex Deucher
Browse files

drm/amd/display: add dsc policy getter



dc needs to expose its internal dsc policy.

Signed-off-by: default avatarWenjing Liu <Wenjing.Liu@amd.com>
Reviewed-by: default avatarNikola Cornij <Nikola.Cornij@amd.com>
Acked-by: default avatarLeo Li <sunpeng.li@amd.com>
Signed-off-by: default avatarAlex Deucher <alexander.deucher@amd.com>
parent c5e53707
Loading
Loading
Loading
Loading
+11 −3
Original line number Diff line number Diff line
@@ -45,6 +45,14 @@ struct display_stream_compressor {
	int inst;
};

struct dc_dsc_policy {
	bool use_min_slices_h;
	int max_slices_h; // Maximum available if 0
	int min_slice_height; // Must not be less than 8
	uint32_t max_target_bpp;
	uint32_t min_target_bpp;
};

bool dc_dsc_parse_dsc_dpcd(const uint8_t *dpcd_dsc_basic_data,
		const uint8_t *dpcd_dsc_ext_data,
		struct dsc_dec_dpcd_caps *dsc_sink_caps);
@@ -66,7 +74,7 @@ bool dc_dsc_compute_config(
		const struct dc_crtc_timing *timing,
		struct dc_dsc_config *dsc_cfg);

bool dc_dsc_get_bpp_range_for_pixel_encoding(enum dc_pixel_encoding pixel_enc,
		uint32_t *min_bpp,
		uint32_t *max_bpp);
void dc_dsc_get_policy_for_timing(const struct dc_crtc_timing *timing,
		struct dc_dsc_policy *policy);

#endif
+64 −39
Original line number Diff line number Diff line
@@ -27,19 +27,6 @@
#include <drm/drm_dp_helper.h>
#include "dc.h"

struct dc_dsc_policy {
	bool use_min_slices_h;
	int max_slices_h; // Maximum available if 0
	int min_sice_height; // Must not be less than 8
};

const struct dc_dsc_policy dsc_policy = {
	.use_min_slices_h = true, // DSC Policy: Use minimum number of slices that fits the pixel clock
	.max_slices_h = 0, // DSC Policy: Use max available slices (in our case 4 for or 8, depending on the mode)
	.min_sice_height = 108, // DSC Policy: Use slice height recommended by VESA DSC Spreadsheet user guide
};


/* This module's internal functions */

static uint32_t dc_dsc_bandwidth_in_kbps_from_timing(
@@ -370,6 +357,7 @@ static void get_dsc_bandwidth_range(
 *        or if it couldn't be applied based on DSC policy.
 */
static bool decide_dsc_target_bpp_x16(
		const struct dc_dsc_policy *policy,
		const struct dsc_enc_caps *dsc_common_caps,
		const int target_bandwidth_kbps,
		const struct dc_crtc_timing *timing,
@@ -377,13 +365,10 @@ static bool decide_dsc_target_bpp_x16(
{
	bool should_use_dsc = false;
	struct dc_dsc_bw_range range;
	uint32_t min_target_bpp = 0;
	uint32_t max_target_bpp = 0;

	memset(&range, 0, sizeof(range));

	dc_dsc_get_bpp_range_for_pixel_encoding(timing->pixel_encoding, &min_target_bpp, &max_target_bpp);
	get_dsc_bandwidth_range(min_target_bpp, max_target_bpp,
	get_dsc_bandwidth_range(policy->min_target_bpp, policy->max_target_bpp,
			dsc_common_caps, timing, &range);
	if (target_bandwidth_kbps >= range.stream_kbps) {
		/* enough bandwidth without dsc */
@@ -579,9 +564,11 @@ static bool setup_dsc_config(
	bool is_dsc_possible = false;
	int pic_height;
	int slice_height;
	struct dc_dsc_policy policy;

	memset(dsc_cfg, 0, sizeof(struct dc_dsc_config));

	dc_dsc_get_policy_for_timing(timing, &policy);
	pic_width = timing->h_addressable + timing->h_border_left + timing->h_border_right;
	pic_height = timing->v_addressable + timing->v_border_top + timing->v_border_bottom;

@@ -597,7 +584,12 @@ static bool setup_dsc_config(
		goto done;

	if (target_bandwidth_kbps > 0) {
		is_dsc_possible = decide_dsc_target_bpp_x16(&dsc_common_caps, target_bandwidth_kbps, timing, &target_bpp);
		is_dsc_possible = decide_dsc_target_bpp_x16(
				&policy,
				&dsc_common_caps,
				target_bandwidth_kbps,
				timing,
				&target_bpp);
		dsc_cfg->bits_per_pixel = target_bpp;
	}
	if (!is_dsc_possible)
@@ -699,20 +691,20 @@ static bool setup_dsc_config(
	if (!is_dsc_possible)
		goto done;

	if (dsc_policy.use_min_slices_h) {
	if (policy.use_min_slices_h) {
		if (min_slices_h > 0)
			num_slices_h = min_slices_h;
		else if (max_slices_h > 0) { // Fall back to max slices if min slices is not working out
			if (dsc_policy.max_slices_h)
				num_slices_h = min(dsc_policy.max_slices_h, max_slices_h);
			if (policy.max_slices_h)
				num_slices_h = min(policy.max_slices_h, max_slices_h);
			else
				num_slices_h = max_slices_h;
		} else
			is_dsc_possible = false;
	} else {
		if (max_slices_h > 0) {
			if (dsc_policy.max_slices_h)
				num_slices_h = min(dsc_policy.max_slices_h, max_slices_h);
			if (policy.max_slices_h)
				num_slices_h = min(policy.max_slices_h, max_slices_h);
			else
				num_slices_h = max_slices_h;
		} else if (min_slices_h > 0) // Fall back to min slices if max slices is not possible
@@ -734,7 +726,7 @@ static bool setup_dsc_config(
	// Slice height (i.e. number of slices per column): start with policy and pick the first one that height is divisible by.
	// For 4:2:0 make sure the slice height is divisible by 2 as well.
	if (min_slice_height_override == 0)
		slice_height = min(dsc_policy.min_sice_height, pic_height);
		slice_height = min(policy.min_slice_height, pic_height);
	else
		slice_height = min(min_slice_height_override, pic_height);

@@ -905,28 +897,61 @@ bool dc_dsc_compute_config(
	return is_dsc_possible;
}

bool dc_dsc_get_bpp_range_for_pixel_encoding(enum dc_pixel_encoding pixel_enc,
		uint32_t *min_bpp,
		uint32_t *max_bpp)
void dc_dsc_get_policy_for_timing(const struct dc_crtc_timing *timing, struct dc_dsc_policy *policy)
{
	bool result = true;
	uint32_t bpc = 0;

	policy->min_target_bpp = 0;
	policy->max_target_bpp = 0;

	/* DSC Policy: Use minimum number of slices that fits the pixel clock */
	policy->use_min_slices_h = true;

	switch (pixel_enc) {
	/* DSC Policy: Use max available slices
	 * (in our case 4 for or 8, depending on the mode)
	 */
	policy->max_slices_h = 0;

	/* DSC Policy: Use slice height recommended
	 * by VESA DSC Spreadsheet user guide
	 */
	policy->min_slice_height = 108;

	/* DSC Policy: follow DP specs with an internal upper limit to 16 bpp
	 * for better interoperability
	 */
	switch (timing->display_color_depth) {
	case COLOR_DEPTH_888:
		bpc = 8;
		break;
	case COLOR_DEPTH_101010:
		bpc = 10;
		break;
	case COLOR_DEPTH_121212:
		bpc = 12;
		break;
	default:
		return;
	}
	switch (timing->pixel_encoding) {
	case PIXEL_ENCODING_RGB:
	case PIXEL_ENCODING_YCBCR444:
	case PIXEL_ENCODING_YCBCR422:
		*min_bpp = 8;
		*max_bpp = 16;
	case PIXEL_ENCODING_YCBCR422: /* assume no YCbCr422 native support */
		/* DP specs limits to 8 */
		policy->min_target_bpp = 8;
		/* DP specs limits to 3 x bpc */
		policy->max_target_bpp = 3 * bpc;
		break;
	case PIXEL_ENCODING_YCBCR420:
		*min_bpp = 6;
		*max_bpp = 16;
		/* DP specs limits to 6 */
		policy->min_target_bpp = 6;
		/* DP specs limits to 1.5 x bpc assume bpc is an even number */
		policy->max_target_bpp = bpc * 3 / 2;
		break;
	default:
		*min_bpp = 0;
		*max_bpp = 0;
		result = false;
		return;
	}

	return result;
	/* internal upper limit to 16 bpp */
	if (policy->max_target_bpp > 16)
		policy->max_target_bpp = 16;
}