Commit 4d4d3ff1 authored by Webb Chen's avatar Webb Chen Committed by Alex Deucher
Browse files

drm/amd/display: Keep VBios pixel rate div setting util next mode set



[why]
VBios & Driver may have differnet pixel rate div policy.
If the policy is not same and fast boot is enabled,
it would cause the pixel rate is too high
after driver only performs stream blank & unblank.

[how]
We would keep pixel rate div setting by VBios until next mode set.

Reviewed-by: default avatarJun Lei <jun.lei@amd.com>
Acked-by: default avatarAurabindo Pillai <aurabindo.pillai@amd.com>
Signed-off-by: default avatarWebb Chen <yi-lchen@amd.com>
Tested-by: default avatarDaniel Wheeler <daniel.wheeler@amd.com>
Signed-off-by: default avatarAlex Deucher <alexander.deucher@amd.com>
parent a8ac994c
Loading
Loading
Loading
Loading
+4 −0
Original line number Diff line number Diff line
@@ -49,6 +49,7 @@
#include "link/hwss/link_hwss_hpo_dp.h"
#include "link/hwss/link_hwss_dio_fixed_vs_pe_retimer.h"
#include "link/hwss/link_hwss_hpo_fixed_vs_pe_retimer_dp.h"
#include "hw_sequencer_private.h"

#if defined(CONFIG_DRM_AMD_DC_SI)
#include "dce60/dce60_resource.h"
@@ -3902,6 +3903,9 @@ enum dc_status dc_validate_with_context(struct dc *dc,
		if (res != DC_OK)
			goto fail;

		if (dc->hwseq->funcs.calculate_pix_rate_divider)
			dc->hwseq->funcs.calculate_pix_rate_divider(dc, context, add_streams[i]);

		if (!add_all_planes_for_stream(dc, add_streams[i], set, set_count, context)) {
			res = DC_FAIL_ATTACH_SURFACES;
			goto fail;
+7 −5
Original line number Diff line number Diff line
@@ -58,8 +58,8 @@ static void dccg314_trigger_dio_fifo_resync(
static void dccg314_get_pixel_rate_div(
		struct dccg *dccg,
		uint32_t otg_inst,
		enum pixel_rate_div *k1,
		enum pixel_rate_div *k2)
		uint32_t *k1,
		uint32_t *k2)
{
	struct dcn_dccg *dccg_dcn = TO_DCN_DCCG(dccg);
	uint32_t val_k1 = PIXEL_RATE_DIV_NA, val_k2 = PIXEL_RATE_DIV_NA;
@@ -93,8 +93,8 @@ static void dccg314_get_pixel_rate_div(
		return;
	}

	*k1 = (enum pixel_rate_div)val_k1;
	*k2 = (enum pixel_rate_div)val_k2;
	*k1 = val_k1;
	*k2 = val_k2;
}

static void dccg314_set_pixel_rate_div(
@@ -104,7 +104,8 @@ static void dccg314_set_pixel_rate_div(
		enum pixel_rate_div k2)
{
	struct dcn_dccg *dccg_dcn = TO_DCN_DCCG(dccg);
	enum pixel_rate_div cur_k1 = PIXEL_RATE_DIV_NA, cur_k2 = PIXEL_RATE_DIV_NA;
	uint32_t cur_k1 = PIXEL_RATE_DIV_NA;
	uint32_t cur_k2 = PIXEL_RATE_DIV_NA;

	// Don't program 0xF into the register field. Not valid since
	// K1 / K2 field is only 1 / 2 bits wide
@@ -373,6 +374,7 @@ static const struct dccg_funcs dccg314_funcs = {
	.disable_dsc = dccg31_disable_dscclk,
	.enable_dsc = dccg31_enable_dscclk,
	.set_pixel_rate_div = dccg314_set_pixel_rate_div,
	.get_pixel_rate_div = dccg314_get_pixel_rate_div,
	.trigger_dio_fifo_resync = dccg314_trigger_dio_fifo_resync,
	.set_valid_pixel_rate = dccg314_set_valid_pixel_rate,
	.set_dtbclk_p_src = dccg314_set_dtbclk_p_src
+7 −6
Original line number Diff line number Diff line
@@ -58,8 +58,8 @@ static void dccg32_trigger_dio_fifo_resync(
static void dccg32_get_pixel_rate_div(
		struct dccg *dccg,
		uint32_t otg_inst,
		enum pixel_rate_div *k1,
		enum pixel_rate_div *k2)
		uint32_t *k1,
		uint32_t *k2)
{
	struct dcn_dccg *dccg_dcn = TO_DCN_DCCG(dccg);
	uint32_t val_k1 = PIXEL_RATE_DIV_NA, val_k2 = PIXEL_RATE_DIV_NA;
@@ -93,8 +93,8 @@ static void dccg32_get_pixel_rate_div(
		return;
	}

	*k1 = (enum pixel_rate_div)val_k1;
	*k2 = (enum pixel_rate_div)val_k2;
	*k1 = val_k1;
	*k2 = val_k2;
}

static void dccg32_set_pixel_rate_div(
@@ -104,8 +104,8 @@ static void dccg32_set_pixel_rate_div(
		enum pixel_rate_div k2)
{
	struct dcn_dccg *dccg_dcn = TO_DCN_DCCG(dccg);

	enum pixel_rate_div cur_k1 = PIXEL_RATE_DIV_NA, cur_k2 = PIXEL_RATE_DIV_NA;
	uint32_t cur_k1 = PIXEL_RATE_DIV_NA;
	uint32_t cur_k2 = PIXEL_RATE_DIV_NA;

	// Don't program 0xF into the register field. Not valid since
	// K1 / K2 field is only 1 / 2 bits wide
@@ -344,6 +344,7 @@ static const struct dccg_funcs dccg32_funcs = {
	.otg_add_pixel = dccg32_otg_add_pixel,
	.otg_drop_pixel = dccg32_otg_drop_pixel,
	.set_pixel_rate_div = dccg32_set_pixel_rate_div,
	.get_pixel_rate_div = dccg32_get_pixel_rate_div,
	.trigger_dio_fifo_resync = dccg32_trigger_dio_fifo_resync,
	.set_dtbclk_p_src = dccg32_set_dtbclk_p_src,
};
+3 −37
Original line number Diff line number Diff line
@@ -52,11 +52,11 @@

static void enc32_dp_set_odm_combine(
	struct stream_encoder *enc,
	bool odm_combine)
	bool two_pixel_per_cyle)
{
	struct dcn10_stream_encoder *enc1 = DCN10STRENC_FROM_STRENC(enc);

	REG_UPDATE(DP_PIXEL_FORMAT, DP_PIXEL_PER_CYCLE_PROCESSING_MODE, odm_combine ? 1 : 0);
	REG_UPDATE(DP_PIXEL_FORMAT, DP_PIXEL_PER_CYCLE_PROCESSING_MODE, two_pixel_per_cyle ? 1 : 0);
}

/* setup stream encoder in dvi mode */
@@ -241,46 +241,12 @@ static bool is_two_pixels_per_containter(const struct dc_crtc_timing *timing)
	return two_pix;
}

static bool is_h_timing_divisible_by_2(const struct dc_crtc_timing *timing)
{
	/* math borrowed from function of same name in inc/resource
	 * checks if h_timing is divisible by 2
	 */

	bool divisible = false;
	uint16_t h_blank_start = 0;
	uint16_t h_blank_end = 0;

	if (timing) {
		h_blank_start = timing->h_total - timing->h_front_porch;
		h_blank_end = h_blank_start - timing->h_addressable;

		/* HTOTAL, Hblank start/end, and Hsync start/end all must be
		 * divisible by 2 in order for the horizontal timing params
		 * to be considered divisible by 2. Hsync start is always 0.
		 */
		divisible = (timing->h_total % 2 == 0) &&
				(h_blank_start % 2 == 0) &&
				(h_blank_end % 2 == 0) &&
				(timing->h_sync_width % 2 == 0);
	}
	return divisible;
}

static bool is_dp_dig_pixel_rate_div_policy(struct dc *dc, const struct dc_crtc_timing *timing)
{
	/* should be functionally the same as dcn32_is_dp_dig_pixel_rate_div_policy for DP encoders*/
	return is_h_timing_divisible_by_2(timing) &&
		dc->debug.enable_dp_dig_pixel_rate_div_policy;
}

void enc32_stream_encoder_dp_unblank(
	struct dc_link *link,
	struct stream_encoder *enc,
	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;
@@ -291,7 +257,7 @@ void enc32_stream_encoder_dp_unblank(

		/* 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
			|| is_dp_dig_pixel_rate_div_policy(dc, &param->timing)) {
			|| param->pix_per_cycle > 1) {
			/*this logic should be the same in get_pixel_clock_parameters() */
			n_multiply = 1;
			pix_per_cycle = 1;
+5 −3
Original line number Diff line number Diff line
@@ -137,8 +137,8 @@ static void dccg35_set_dppclk_root_clock_gating(struct dccg *dccg,
static void dccg35_get_pixel_rate_div(
		struct dccg *dccg,
		uint32_t otg_inst,
		enum pixel_rate_div *k1,
		enum pixel_rate_div *k2)
		uint32_t *k1,
		uint32_t *k2)
{
	struct dcn_dccg *dccg_dcn = TO_DCN_DCCG(dccg);
	uint32_t val_k1 = PIXEL_RATE_DIV_NA, val_k2 = PIXEL_RATE_DIV_NA;
@@ -183,7 +183,8 @@ static void dccg35_set_pixel_rate_div(
		enum pixel_rate_div k2)
{
	struct dcn_dccg *dccg_dcn = TO_DCN_DCCG(dccg);
	enum pixel_rate_div cur_k1 = PIXEL_RATE_DIV_NA, cur_k2 = PIXEL_RATE_DIV_NA;
	uint32_t cur_k1 = PIXEL_RATE_DIV_NA;
	uint32_t cur_k2 = PIXEL_RATE_DIV_NA;

	// Don't program 0xF into the register field. Not valid since
	// K1 / K2 field is only 1 / 2 bits wide
@@ -1054,6 +1055,7 @@ static const struct dccg_funcs dccg35_funcs = {
	.disable_dsc = dccg35_disable_dscclk,
	.enable_dsc = dccg35_enable_dscclk,
	.set_pixel_rate_div = dccg35_set_pixel_rate_div,
	.get_pixel_rate_div = dccg35_get_pixel_rate_div,
	.set_valid_pixel_rate = dccg35_set_valid_pixel_rate,
	.enable_symclk_se = dccg35_enable_symclk_se,
	.disable_symclk_se = dccg35_disable_symclk_se,
Loading