diff options
-rw-r--r-- | drivers/gpu/drm/amd/display/dc/dc_dsc.h | 14 | ||||
-rw-r--r-- | drivers/gpu/drm/amd/display/dc/dsc/dc_dsc.c | 103 |
2 files changed, 75 insertions, 42 deletions
diff --git a/drivers/gpu/drm/amd/display/dc/dc_dsc.h b/drivers/gpu/drm/amd/display/dc/dc_dsc.h index d98b89bad353..8ec09813ee17 100644 --- a/drivers/gpu/drm/amd/display/dc/dc_dsc.h +++ b/drivers/gpu/drm/amd/display/dc/dc_dsc.h @@ -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 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 febae6cc7295..d2423ad1fac2 100644 --- a/drivers/gpu/drm/amd/display/dc/dsc/dc_dsc.c +++ b/drivers/gpu/drm/amd/display/dc/dsc/dc_dsc.c @@ -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; } |