]> git.dujemihanovic.xyz Git - linux.git/commitdiff
drm/amd/display: Implement new DPCD register handling
authorRyan Seto <ryanseto@amd.com>
Mon, 19 Aug 2024 21:06:56 +0000 (17:06 -0400)
committerAlex Deucher <alexander.deucher@amd.com>
Wed, 18 Sep 2024 20:15:06 +0000 (16:15 -0400)
[WHY]
There are some monitor timings that seem to be supported without
DSC but actually require DSC to be displayed. A VESA SCR introduced
a new max uncompressed pixel rate cap register that we can use to
handle these edge cases.

[HOW]
SST: Read caps from link and invalidate timings that exceed the
max limit but do not support DSC. Then check for options override
when determining BPP.

MST: Read caps from virtual DPCD peer device or daisy chained SST
monitor and set validation set BPPs to max if pixel rate exceeds
uncompressed limit. Validation set optimization continues as normal.

Reviewed-by: Wenjing Liu <wenjing.liu@amd.com>
Signed-off-by: Ryan Seto <ryanseto@amd.com>
Signed-off-by: Alex Hung <alex.hung@amd.com>
Tested-by: Daniel Wheeler <daniel.wheeler@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
drivers/gpu/drm/amd/display/dc/dc_dp_types.h
drivers/gpu/drm/amd/display/dc/dc_dsc.h
drivers/gpu/drm/amd/display/dc/dsc/dc_dsc.c
drivers/gpu/drm/amd/display/dc/link/link_validation.c
drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_capability.c

index 519c3df78ee5b263d5e6d131623c2888a248988c..41bd95e9177a419c6ebe568aec1c2ef05947ae0e 100644 (file)
@@ -969,6 +969,14 @@ union dp_sink_video_fallback_formats {
        uint8_t raw;
 };
 
+union dpcd_max_uncompressed_pixel_rate_cap {
+       struct {
+               uint16_t max_uncompressed_pixel_rate_cap        :15;
+               uint16_t valid                  :1;
+       } bits;
+       uint8_t raw[2];
+};
+
 union dp_fec_capability1 {
        struct {
                uint8_t AGGREGATED_ERROR_COUNTERS_CAPABLE       :1;
@@ -1170,6 +1178,7 @@ struct dpcd_caps {
        struct dc_lttpr_caps lttpr_caps;
        struct adaptive_sync_caps adaptive_sync_caps;
        struct dpcd_usb4_dp_tunneling_info usb4_dp_tun_info;
+       union dpcd_max_uncompressed_pixel_rate_cap max_uncompressed_pixel_rate_cap;
 
        union dp_128b_132b_supported_link_rates dp_128b_132b_supported_link_rates;
        union dp_main_line_channel_coding_cap channel_coding_cap;
@@ -1340,6 +1349,9 @@ struct dp_trace {
 #ifndef DP_CABLE_ATTRIBUTES_UPDATED_BY_DPTX
 #define DP_CABLE_ATTRIBUTES_UPDATED_BY_DPTX            0x110
 #endif
+#ifndef DPCD_MAX_UNCOMPRESSED_PIXEL_RATE_CAP
+#define DPCD_MAX_UNCOMPRESSED_PIXEL_RATE_CAP    0x221c
+#endif
 #ifndef DP_REPEATER_CONFIGURATION_AND_STATUS_SIZE
 #define DP_REPEATER_CONFIGURATION_AND_STATUS_SIZE      0x50
 #endif
index fe3078b8789ef142ea4e3eb9b1c6792ac3aea5cb..2a5120ecf48be693242932b84efef57c632b900d 100644 (file)
@@ -59,6 +59,7 @@ struct dc_dsc_config_options {
        uint32_t max_target_bpp_limit_override_x16;
        uint32_t slice_height_granularity;
        uint32_t dsc_force_odm_hslice_override;
+       bool force_dsc_when_not_needed;
 };
 
 bool dc_dsc_parse_dsc_dpcd(const struct dc *dc,
index a1727e5bf024796fa75da8d55ec88fe4e0ade228..79c426425911f06b0fb9ca096a0b94ec1bf81742 100644 (file)
@@ -668,6 +668,7 @@ static bool decide_dsc_bandwidth_range(
  */
 static bool decide_dsc_target_bpp_x16(
                const struct dc_dsc_policy *policy,
+               const struct dc_dsc_config_options *options,
                const struct dsc_enc_caps *dsc_common_caps,
                const int target_bandwidth_kbps,
                const struct dc_crtc_timing *timing,
@@ -682,7 +683,7 @@ static bool decide_dsc_target_bpp_x16(
        if (decide_dsc_bandwidth_range(policy->min_target_bpp * 16, policy->max_target_bpp * 16,
                        num_slices_h, dsc_common_caps, timing, link_encoding, &range)) {
                if (target_bandwidth_kbps >= range.stream_kbps) {
-                       if (policy->enable_dsc_when_not_needed)
+                       if (policy->enable_dsc_when_not_needed || options->force_dsc_when_not_needed)
                                /* enable max bpp even dsc is not needed */
                                *target_bpp_x16 = range.max_target_bpp_x16;
                } else if (target_bandwidth_kbps >= range.max_kbps) {
@@ -1080,6 +1081,7 @@ static bool setup_dsc_config(
        if (target_bandwidth_kbps > 0) {
                is_dsc_possible = decide_dsc_target_bpp_x16(
                                &policy,
+                               options,
                                &dsc_common_caps,
                                target_bandwidth_kbps,
                                timing,
@@ -1235,10 +1237,7 @@ void dc_dsc_get_policy_for_timing(const struct dc_crtc_timing *timing,
                policy->max_target_bpp = max_target_bpp_limit_override_x16 / 16;
 
        /* enable DSC when not needed, default false */
-       if (dsc_policy_enable_dsc_when_not_needed)
-               policy->enable_dsc_when_not_needed = dsc_policy_enable_dsc_when_not_needed;
-       else
-               policy->enable_dsc_when_not_needed = false;
+       policy->enable_dsc_when_not_needed = dsc_policy_enable_dsc_when_not_needed;
 }
 
 void dc_dsc_policy_set_max_target_bpp_limit(uint32_t limit)
@@ -1267,4 +1266,5 @@ void dc_dsc_get_default_config_option(const struct dc *dc, struct dc_dsc_config_
        options->dsc_force_odm_hslice_override = dc->debug.force_odm_combine;
        options->max_target_bpp_limit_override_x16 = 0;
        options->slice_height_granularity = 1;
+       options->force_dsc_when_not_needed = false;
 }
index 1aed55b0ab6a09486068c284dd480e44f7186895..60f15a9ba7a5e11acac4595e99a9e16c93770431 100644 (file)
@@ -287,6 +287,13 @@ static bool dp_validate_mode_timing(
        req_bw = dc_bandwidth_in_kbps_from_timing(timing, dc_link_get_highest_encoding_format(link));
        max_bw = dp_link_bandwidth_kbps(link, link_setting);
 
+       bool is_max_uncompressed_pixel_rate_exceeded = link->dpcd_caps.max_uncompressed_pixel_rate_cap.bits.valid &&
+                       timing->pix_clk_100hz > link->dpcd_caps.max_uncompressed_pixel_rate_cap.bits.max_uncompressed_pixel_rate_cap * 10000;
+
+       if (is_max_uncompressed_pixel_rate_exceeded && !timing->flags.DSC) {
+               return false;
+       }
+
        if (req_bw <= max_bw) {
                /* remember the biggest mode here, during
                 * initial link training (to get
index 34a618a7278b0af014ef300b0a30d28f7318f2aa..d78c8ec4de79e7407a857303bd1864728145a575 100644 (file)
@@ -1942,6 +1942,11 @@ static bool retrieve_link_cap(struct dc_link *link)
                        DC_LOG_DP2("\tFEC aggregated error counters are supported");
        }
 
+       core_link_read_dpcd(link,
+                       DPCD_MAX_UNCOMPRESSED_PIXEL_RATE_CAP,
+                       link->dpcd_caps.max_uncompressed_pixel_rate_cap.raw,
+                       sizeof(link->dpcd_caps.max_uncompressed_pixel_rate_cap.raw));
+
        retrieve_cable_id(link);
        dpcd_write_cable_id_to_dprx(link);