diff --git a/drivers/gpu/drm/i915/display/intel_dp.c b/drivers/gpu/drm/i915/display/intel_dp.c index f01a6eed3839..9589fed7a40a 100644 --- a/drivers/gpu/drm/i915/display/intel_dp.c +++ b/drivers/gpu/drm/i915/display/intel_dp.c @@ -2165,17 +2165,56 @@ static int dsc_compute_link_config(struct intel_dp *intel_dp, return -EINVAL; } +static u16 intel_dp_dsc_max_delta_bppx16(const struct intel_connector *connector, + enum intel_output_format output_format) +{ + const u8 *dsc_dpcd = connector->dp.dsc_dpcd; + u8 max_bpp_delta_v1 = dsc_dpcd[DP_DSC_MAX_BPP_DELTA_VERSION_1 - DP_DSC_SUPPORT]; + int max_bpp; + + if (!(dsc_dpcd[DP_DSC_MAX_BITS_PER_PIXEL_HI - DP_DSC_SUPPORT] & + DP_DSC_MAX_BPP_DELTA_AVAILABILITY)) + return 0; + + switch (output_format) { + case INTEL_OUTPUT_FORMAT_RGB: + case INTEL_OUTPUT_FORMAT_YCBCR444: + max_bpp = max_bpp_delta_v1 & DP_DSC_RGB_YCbCr444_MAX_BPP_DELTA_MASK; + if (max_bpp >= 1 && max_bpp <= 21) + max_bpp = max_bpp + DP_DSC_BPP_DELTA_444 - 1; + else + max_bpp = 0; + break; + case INTEL_OUTPUT_FORMAT_YCBCR420: + max_bpp = (max_bpp_delta_v1 & DP_DSC_NATIVE_YCbCr420_MAX_BPP_DELTA_MASK) >> + DP_DSC_BPP_DELTA_SHIFT_420; + if (max_bpp >= 1 && max_bpp <= 7) + max_bpp = max_bpp + DP_DSC_BPP_DELTA_420 - 1; + break; + default: + MISSING_CASE(output_format); + return 0; + } + + return max_bpp << 4; +} + static u16 intel_dp_dsc_max_sink_compressed_bppx16(const struct intel_connector *connector, enum intel_output_format output_format, int bpc) { - u16 max_bppx16 = drm_edp_dsc_sink_output_bpp(connector->dp.dsc_dpcd); + u16 max_bppx16 = intel_dp_dsc_max_delta_bppx16(connector, output_format); + + if (max_bppx16) + return max_bppx16; + + max_bppx16 = drm_edp_dsc_sink_output_bpp(connector->dp.dsc_dpcd); if (max_bppx16) return max_bppx16; /* - * If support not given in DPCD 67h, 68h use the Maximum Allowed bit rate + * If support not given in DPCD 67h, 68h, 6Eh, 6Fh use the Maximum Allowed bit rate * values as given in spec Table 2-157 DP v2.0 */ switch (output_format) {