diff options
author | Wenjing Liu <wenjing.liu@amd.com> | 2021-04-22 14:01:25 -0400 |
---|---|---|
committer | Alex Deucher <alexander.deucher@amd.com> | 2021-05-10 18:06:44 -0400 |
commit | df0a271cc794639ef537f21c4c56893e40972523 (patch) | |
tree | 69dd34b25616bb4e6a1dcf9bdaece689c3511154 /drivers/gpu | |
parent | cf8b92a75646735136053ce51107bfa8cfc23191 (diff) | |
download | linux-stable-df0a271cc794639ef537f21c4c56893e40972523.tar.gz linux-stable-df0a271cc794639ef537f21c4c56893e40972523.tar.bz2 linux-stable-df0a271cc794639ef537f21c4c56893e40972523.zip |
drm/amd/display: add dsc stream overhead for dp only
[why]
Based on hardware team recommendation this additional dsc overhead
is only required for DP DSC.
[how]
Add a check for is_dp and only apply the overhead if this flag is set.
Signed-off-by: Wenjing Liu <wenjing.liu@amd.com>
Reviewed-by: Chris Park <Chris.Park@amd.com>
Acked-by: Wayne Lin <Wayne.Lin@amd.com>
Tested-by: Daniel Wheeler <daniel.wheeler@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
Diffstat (limited to 'drivers/gpu')
-rw-r--r-- | drivers/gpu/drm/amd/display/dc/core/dc_link.c | 3 | ||||
-rw-r--r-- | drivers/gpu/drm/amd/display/dc/dc_dsc.h | 4 | ||||
-rw-r--r-- | drivers/gpu/drm/amd/display/dc/dc_hw_types.h | 1 | ||||
-rw-r--r-- | drivers/gpu/drm/amd/display/dc/dc_types.h | 1 | ||||
-rw-r--r-- | drivers/gpu/drm/amd/display/dc/dsc/dc_dsc.c | 41 | ||||
-rw-r--r-- | drivers/gpu/drm/amd/display/dc/inc/hw/dsc.h | 1 |
6 files changed, 36 insertions, 15 deletions
diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_link.c b/drivers/gpu/drm/amd/display/dc/core/dc_link.c index 8bbed9c90c5d..488f5a14d0f2 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_link.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_link.c @@ -3489,7 +3489,8 @@ uint32_t dc_bandwidth_in_kbps_from_timing( if (timing->flags.DSC) return dc_dsc_stream_bandwidth_in_kbps(timing, timing->dsc_cfg.bits_per_pixel, - timing->dsc_cfg.num_slices_h); + timing->dsc_cfg.num_slices_h, + timing->dsc_cfg.is_dp); #endif switch (timing->display_color_depth) { diff --git a/drivers/gpu/drm/amd/display/dc/dc_dsc.h b/drivers/gpu/drm/amd/display/dc/dc_dsc.h index afddb8b7d3e4..16cc76ce3739 100644 --- a/drivers/gpu/drm/amd/display/dc/dc_dsc.h +++ b/drivers/gpu/drm/amd/display/dc/dc_dsc.h @@ -79,7 +79,7 @@ bool dc_dsc_compute_config( struct dc_dsc_config *dsc_cfg); uint32_t dc_dsc_stream_bandwidth_in_kbps(const struct dc_crtc_timing *timing, - uint32_t bpp_x16, uint32_t num_slices_h); + uint32_t bpp_x16, uint32_t num_slices_h, bool is_dp); void dc_dsc_get_policy_for_timing(const struct dc_crtc_timing *timing, uint32_t max_target_bpp_limit_override_x16, @@ -89,4 +89,6 @@ void dc_dsc_policy_set_max_target_bpp_limit(uint32_t limit); void dc_dsc_policy_set_enable_dsc_when_not_needed(bool enable); +void dc_dsc_policy_set_disable_dsc_stream_overhead(bool disable); + #endif diff --git a/drivers/gpu/drm/amd/display/dc/dc_hw_types.h b/drivers/gpu/drm/amd/display/dc/dc_hw_types.h index bcec019efa6f..04957a9efab2 100644 --- a/drivers/gpu/drm/amd/display/dc/dc_hw_types.h +++ b/drivers/gpu/drm/amd/display/dc/dc_hw_types.h @@ -739,6 +739,7 @@ struct dc_dsc_config { uint32_t version_minor; /* DSC minor version. Full version is formed as 1.version_minor. */ bool ycbcr422_simple; /* Tell DSC engine to convert YCbCr 4:2:2 to 'YCbCr 4:2:2 simple'. */ int32_t rc_buffer_size; /* DSC RC buffer block size in bytes */ + bool is_dp; /* indicate if DSC is applied based on DP's capability */ }; struct dc_crtc_timing { uint32_t h_total; diff --git a/drivers/gpu/drm/amd/display/dc/dc_types.h b/drivers/gpu/drm/amd/display/dc/dc_types.h index 432754eaf10b..78bc10aeb201 100644 --- a/drivers/gpu/drm/amd/display/dc/dc_types.h +++ b/drivers/gpu/drm/amd/display/dc/dc_types.h @@ -909,6 +909,7 @@ struct dsc_dec_dpcd_caps { uint32_t branch_overall_throughput_0_mps; /* In MPs */ uint32_t branch_overall_throughput_1_mps; /* In MPs */ uint32_t branch_max_line_width; + bool is_dp; }; struct dc_golden_table { diff --git a/drivers/gpu/drm/amd/display/dc/dsc/dc_dsc.c b/drivers/gpu/drm/amd/display/dc/dsc/dc_dsc.c index bfe3ad58070a..f403d8e84a8c 100644 --- a/drivers/gpu/drm/amd/display/dc/dsc/dc_dsc.c +++ b/drivers/gpu/drm/amd/display/dc/dsc/dc_dsc.c @@ -37,6 +37,8 @@ static uint32_t dsc_policy_max_target_bpp_limit = 16; /* default DSC policy enables DSC only when needed */ static bool dsc_policy_enable_dsc_when_not_needed; +static bool dsc_policy_disable_dsc_stream_overhead; + static bool dsc_buff_block_size_from_dpcd(int dpcd_buff_block_size, int *buff_block_size) { @@ -250,6 +252,7 @@ static bool intersect_dsc_caps( if (pixel_encoding == PIXEL_ENCODING_YCBCR422 || pixel_encoding == PIXEL_ENCODING_YCBCR420) dsc_common_caps->bpp_increment_div = min(dsc_common_caps->bpp_increment_div, (uint32_t)8); + dsc_common_caps->is_dp = dsc_sink_caps->is_dp; return true; } @@ -260,11 +263,15 @@ static inline uint32_t dsc_div_by_10_round_up(uint32_t value) static struct fixed31_32 compute_dsc_max_bandwidth_overhead( const struct dc_crtc_timing *timing, - const int num_slices_h) + const int num_slices_h, + const bool is_dp) { struct fixed31_32 max_dsc_overhead; struct fixed31_32 refresh_rate; + if (dsc_policy_disable_dsc_stream_overhead || !is_dp) + return dc_fixpt_from_int(0); + /* use target bpp that can take entire target bandwidth */ refresh_rate = dc_fixpt_from_int(timing->pix_clk_100hz); refresh_rate = dc_fixpt_div_int(refresh_rate, timing->h_total); @@ -272,7 +279,7 @@ static struct fixed31_32 compute_dsc_max_bandwidth_overhead( refresh_rate = dc_fixpt_mul_int(refresh_rate, 100); max_dsc_overhead = dc_fixpt_from_int(num_slices_h); - max_dsc_overhead = dc_fixpt_mul_int(max_dsc_overhead, timing->v_addressable); + max_dsc_overhead = dc_fixpt_mul_int(max_dsc_overhead, timing->v_total); max_dsc_overhead = dc_fixpt_mul_int(max_dsc_overhead, 256); max_dsc_overhead = dc_fixpt_div_int(max_dsc_overhead, 1000); max_dsc_overhead = dc_fixpt_mul(max_dsc_overhead, refresh_rate); @@ -284,14 +291,15 @@ static uint32_t compute_bpp_x16_from_target_bandwidth( const uint32_t bandwidth_in_kbps, const struct dc_crtc_timing *timing, const uint32_t num_slices_h, - const uint32_t bpp_increment_div) + const uint32_t bpp_increment_div, + const bool is_dp) { struct fixed31_32 overhead_in_kbps; struct fixed31_32 effective_bandwidth_in_kbps; struct fixed31_32 bpp_x16; overhead_in_kbps = compute_dsc_max_bandwidth_overhead( - timing, num_slices_h); + timing, num_slices_h, is_dp); effective_bandwidth_in_kbps = dc_fixpt_from_int(bandwidth_in_kbps); effective_bandwidth_in_kbps = dc_fixpt_sub(effective_bandwidth_in_kbps, overhead_in_kbps); @@ -319,19 +327,20 @@ static void get_dsc_bandwidth_range( /* max dsc target bpp */ range->max_kbps = dc_dsc_stream_bandwidth_in_kbps(timing, - max_bpp_x16, num_slices_h); + max_bpp_x16, num_slices_h, dsc_caps->is_dp); range->max_target_bpp_x16 = max_bpp_x16; if (range->max_kbps > range->stream_kbps) { /* max dsc target bpp is capped to native bandwidth */ range->max_kbps = range->stream_kbps; range->max_target_bpp_x16 = compute_bpp_x16_from_target_bandwidth( range->max_kbps, timing, num_slices_h, - dsc_caps->bpp_increment_div); + dsc_caps->bpp_increment_div, + dsc_caps->is_dp); } /* min dsc target bpp */ range->min_kbps = dc_dsc_stream_bandwidth_in_kbps(timing, - min_bpp_x16, num_slices_h); + min_bpp_x16, num_slices_h, dsc_caps->is_dp); range->min_target_bpp_x16 = min_bpp_x16; if (range->min_kbps > range->max_kbps) { /* min dsc target bpp is capped to max dsc bandwidth*/ @@ -378,10 +387,9 @@ static bool decide_dsc_target_bpp_x16( } else if (target_bandwidth_kbps >= range.min_kbps) { /* use target bpp that can take entire target bandwidth */ *target_bpp_x16 = compute_bpp_x16_from_target_bandwidth( - range.max_kbps, timing, num_slices_h, - dsc_common_caps->bpp_increment_div); - if (*target_bpp_x16 < range.min_kbps) - *target_bpp_x16 = range.min_kbps; + target_bandwidth_kbps, timing, num_slices_h, + dsc_common_caps->bpp_increment_div, + dsc_common_caps->is_dp); should_use_dsc = true; } else { /* not enough bandwidth to fulfill minimum requirement */ @@ -751,6 +759,7 @@ static bool setup_dsc_config( dsc_cfg->block_pred_enable = dsc_common_caps.is_block_pred_supported; dsc_cfg->linebuf_depth = dsc_common_caps.lb_bit_depth; dsc_cfg->version_minor = (dsc_common_caps.dsc_version & 0xf0) >> 4; + dsc_cfg->is_dp = dsc_sink_caps->is_dp; } done: @@ -861,6 +870,7 @@ bool dc_dsc_parse_dsc_dpcd(const struct dc *dc, const uint8_t *dpcd_dsc_basic_da dsc_sink_caps->branch_max_line_width = dpcd_dsc_branch_decoder_caps[DP_DSC_BRANCH_MAX_LINE_WIDTH - DP_DSC_BRANCH_OVERALL_THROUGHPUT_0] * 320; ASSERT(dsc_sink_caps->branch_max_line_width == 0 || dsc_sink_caps->branch_max_line_width >= 5120); + dsc_sink_caps->is_dp = true; return true; } @@ -921,14 +931,14 @@ bool dc_dsc_compute_config( } uint32_t dc_dsc_stream_bandwidth_in_kbps(const struct dc_crtc_timing *timing, - uint32_t bpp_x16, uint32_t num_slices_h) + uint32_t bpp_x16, uint32_t num_slices_h, bool is_dp) { struct fixed31_32 overhead_in_kbps; struct fixed31_32 bpp; struct fixed31_32 actual_bandwidth_in_kbps; overhead_in_kbps = compute_dsc_max_bandwidth_overhead( - timing, num_slices_h); + timing, num_slices_h, is_dp); bpp = dc_fixpt_from_fraction(bpp_x16, 16); actual_bandwidth_in_kbps = dc_fixpt_from_fraction(timing->pix_clk_100hz, 10); actual_bandwidth_in_kbps = dc_fixpt_mul(actual_bandwidth_in_kbps, bpp); @@ -1017,3 +1027,8 @@ void dc_dsc_policy_set_enable_dsc_when_not_needed(bool enable) { dsc_policy_enable_dsc_when_not_needed = enable; } + +void dc_dsc_policy_set_disable_dsc_stream_overhead(bool disable) +{ + dsc_policy_disable_dsc_stream_overhead = disable; +} diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw/dsc.h b/drivers/gpu/drm/amd/display/dc/inc/hw/dsc.h index f520e13aee4c..f94135c6e3c2 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/hw/dsc.h +++ b/drivers/gpu/drm/amd/display/dc/inc/hw/dsc.h @@ -88,6 +88,7 @@ struct dsc_enc_caps { int32_t max_total_throughput_mps; /* Maximum total throughput with all the slices combined */ int32_t max_slice_width; uint32_t bpp_increment_div; /* bpp increment divisor, e.g. if 16, it's 1/16th of a bit */ + bool is_dp; }; struct dsc_funcs { |