summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--drivers/gpu/drm/amd/display/dc/dc_dsc.h14
-rw-r--r--drivers/gpu/drm/amd/display/dc/dsc/dc_dsc.c103
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;
}