Commit 2d550a15 authored by Martin Leung's avatar Martin Leung Committed by Alex Deucher

drm/amd/display: block odd h_total timings from halving pixel rate

why:
when dynamic odm was turned on, there is also logic to halve the pixelclk
this still turned on when we avoided odm in the case of odd h_total timings

how:
block the pixel clk mechanism also in the case of odd h_total timings
Reviewed-by: default avatarJun Lei <Jun.Lei@amd.com>
Acked-by: default avatarHamza Mahfooz <hamza.mahfooz@amd.com>
Signed-off-by: default avatarMartin Leung <Martin.Leung@amd.com>
Signed-off-by: default avatarAlex Deucher <alexander.deucher@amd.com>
parent 51619c67
...@@ -243,6 +243,39 @@ static bool is_two_pixels_per_containter(const struct dc_crtc_timing *timing) ...@@ -243,6 +243,39 @@ static bool is_two_pixels_per_containter(const struct dc_crtc_timing *timing)
return two_pix; 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;
}
static void enc32_stream_encoder_dp_unblank( static void enc32_stream_encoder_dp_unblank(
struct dc_link *link, struct dc_link *link,
struct stream_encoder *enc, struct stream_encoder *enc,
...@@ -259,7 +292,7 @@ static void enc32_stream_encoder_dp_unblank( ...@@ -259,7 +292,7 @@ static void enc32_stream_encoder_dp_unblank(
/* YCbCr 4:2:0 : Computed VID_M will be 2X the input rate */ /* 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) { || is_dp_dig_pixel_rate_div_policy(dc, &param->timing)) {
/*this logic should be the same in get_pixel_clock_parameters() */ /*this logic should be the same in get_pixel_clock_parameters() */
n_multiply = 1; n_multiply = 1;
} }
......
...@@ -1161,7 +1161,6 @@ unsigned int dcn32_calculate_dccg_k1_k2_values(struct pipe_ctx *pipe_ctx, unsign ...@@ -1161,7 +1161,6 @@ unsigned int dcn32_calculate_dccg_k1_k2_values(struct pipe_ctx *pipe_ctx, unsign
{ {
struct dc_stream_state *stream = pipe_ctx->stream; struct dc_stream_state *stream = pipe_ctx->stream;
unsigned int odm_combine_factor = 0; unsigned int odm_combine_factor = 0;
struct dc *dc = pipe_ctx->stream->ctx->dc;
bool two_pix_per_container = false; bool two_pix_per_container = false;
// For phantom pipes, use the same programming as the main pipes // For phantom pipes, use the same programming as the main pipes
...@@ -1189,7 +1188,7 @@ unsigned int dcn32_calculate_dccg_k1_k2_values(struct pipe_ctx *pipe_ctx, unsign ...@@ -1189,7 +1188,7 @@ unsigned int dcn32_calculate_dccg_k1_k2_values(struct pipe_ctx *pipe_ctx, unsign
} else { } else {
*k1_div = PIXEL_RATE_DIV_BY_1; *k1_div = PIXEL_RATE_DIV_BY_1;
*k2_div = PIXEL_RATE_DIV_BY_4; *k2_div = PIXEL_RATE_DIV_BY_4;
if ((odm_combine_factor == 2) || dc->debug.enable_dp_dig_pixel_rate_div_policy) if ((odm_combine_factor == 2) || dcn32_is_dp_dig_pixel_rate_div_policy(pipe_ctx))
*k2_div = PIXEL_RATE_DIV_BY_2; *k2_div = PIXEL_RATE_DIV_BY_2;
} }
} }
...@@ -1226,7 +1225,6 @@ void dcn32_unblank_stream(struct pipe_ctx *pipe_ctx, ...@@ -1226,7 +1225,6 @@ void dcn32_unblank_stream(struct pipe_ctx *pipe_ctx,
struct dc_link *link = stream->link; struct dc_link *link = stream->link;
struct dce_hwseq *hws = link->dc->hwseq; struct dce_hwseq *hws = link->dc->hwseq;
struct pipe_ctx *odm_pipe; struct pipe_ctx *odm_pipe;
struct dc *dc = pipe_ctx->stream->ctx->dc;
uint32_t pix_per_cycle = 1; uint32_t pix_per_cycle = 1;
params.opp_cnt = 1; params.opp_cnt = 1;
...@@ -1245,7 +1243,7 @@ void dcn32_unblank_stream(struct pipe_ctx *pipe_ctx, ...@@ -1245,7 +1243,7 @@ void dcn32_unblank_stream(struct pipe_ctx *pipe_ctx,
pipe_ctx->stream_res.tg->inst); pipe_ctx->stream_res.tg->inst);
} else if (dc_is_dp_signal(pipe_ctx->stream->signal)) { } else if (dc_is_dp_signal(pipe_ctx->stream->signal)) {
if (optc2_is_two_pixels_per_containter(&stream->timing) || params.opp_cnt > 1 if (optc2_is_two_pixels_per_containter(&stream->timing) || params.opp_cnt > 1
|| dc->debug.enable_dp_dig_pixel_rate_div_policy) { || dcn32_is_dp_dig_pixel_rate_div_policy(pipe_ctx)) {
params.timing.pix_clk_100hz /= 2; params.timing.pix_clk_100hz /= 2;
pix_per_cycle = 2; pix_per_cycle = 2;
} }
...@@ -1262,6 +1260,9 @@ bool dcn32_is_dp_dig_pixel_rate_div_policy(struct pipe_ctx *pipe_ctx) ...@@ -1262,6 +1260,9 @@ bool dcn32_is_dp_dig_pixel_rate_div_policy(struct pipe_ctx *pipe_ctx)
{ {
struct dc *dc = pipe_ctx->stream->ctx->dc; struct dc *dc = pipe_ctx->stream->ctx->dc;
if (!is_h_timing_divisible_by_2(pipe_ctx->stream))
return false;
if (dc_is_dp_signal(pipe_ctx->stream->signal) && !is_dp_128b_132b_signal(pipe_ctx) && 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) dc->debug.enable_dp_dig_pixel_rate_div_policy)
return true; return true;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment