drm/amd/display: add dsc policy getter
authorWenjing Liu <Wenjing.Liu@amd.com>
Fri, 15 Nov 2019 16:24:54 +0000 (11:24 -0500)
committerAlex Deucher <alexander.deucher@amd.com>
Thu, 5 Dec 2019 21:31:51 +0000 (16:31 -0500)
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>
drivers/gpu/drm/amd/display/dc/dc_dsc.h
drivers/gpu/drm/amd/display/dc/dsc/dc_dsc.c

index d98b89b..8ec0981 100644 (file)
@@ -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
index febae6c..d2423ad 100644 (file)
 #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;
 }