diff options
author | Wenjing Liu <Wenjing.Liu@amd.com> | 2019-11-15 19:24:54 +0300 |
---|---|---|
committer | Alex Deucher <alexander.deucher@amd.com> | 2019-12-06 00:31:51 +0300 |
commit | 799a5f74d11ef7c2e8d86b143d4f1b64793411b6 (patch) | |
tree | 5c2434e83b458af48e2939d7dfacc591f883c342 /drivers/gpu/drm/amd/display/dc/dsc/dc_dsc.c | |
parent | c5e53707e2606dda260b27f5ded637f1f851a659 (diff) | |
download | linux-799a5f74d11ef7c2e8d86b143d4f1b64793411b6.tar.xz |
drm/amd/display: add dsc policy getter
dc needs to expose its internal dsc policy.
Signed-off-by: Wenjing Liu <Wenjing.Liu@amd.com>
Reviewed-by: Nikola Cornij <Nikola.Cornij@amd.com>
Acked-by: Leo Li <sunpeng.li@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
Diffstat (limited to 'drivers/gpu/drm/amd/display/dc/dsc/dc_dsc.c')
-rw-r--r-- | drivers/gpu/drm/amd/display/dc/dsc/dc_dsc.c | 103 |
1 files changed, 64 insertions, 39 deletions
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; } |