drm/amd/display: Validate DSC caps on MST endpoints
authorDavid Francis <David.Francis@amd.com>
Wed, 19 Jun 2019 18:47:33 +0000 (14:47 -0400)
committerAlex Deucher <alexander.deucher@amd.com>
Thu, 9 Jan 2020 23:07:47 +0000 (18:07 -0500)
During MST mode enumeration, if a new dc_sink is created,
populate it with dsc caps as appropriate.

Use drm_dp_mst_dsc_aux_for_port to get the raw caps,
then parse them onto dc_sink with dc_dsc_parse_dsc_dpcd.

Reviewed-by: Wenjing Liu <Wenjing.Liu@amd.com>
Signed-off-by: David Francis <David.Francis@amd.com>
Signed-off-by: Mikita Lipski <mikita.lipski@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h
drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c

index b7240ed..7ea9acb 100644 (file)
@@ -330,6 +330,7 @@ struct amdgpu_dm_connector {
        struct drm_dp_mst_port *port;
        struct amdgpu_dm_connector *mst_port;
        struct amdgpu_encoder *mst_encoder;
+       struct drm_dp_aux *dsc_aux;
 
        /* TODO see if we can merge with ddc_bus or make a dm_connector */
        struct amdgpu_i2c_adapter *i2c;
index 81367c8..6b33a01 100644 (file)
@@ -25,6 +25,7 @@
 
 #include <linux/version.h>
 #include <drm/drm_atomic_helper.h>
+#include <drm/drm_dp_mst_helper.h>
 #include "dm_services.h"
 #include "amdgpu.h"
 #include "amdgpu_dm.h"
@@ -180,6 +181,28 @@ static const struct drm_connector_funcs dm_dp_mst_connector_funcs = {
        .early_unregister = amdgpu_dm_mst_connector_early_unregister,
 };
 
+static bool validate_dsc_caps_on_connector(struct amdgpu_dm_connector *aconnector)
+{
+       struct dc_sink *dc_sink = aconnector->dc_sink;
+       struct drm_dp_mst_port *port = aconnector->port;
+       u8 dsc_caps[16] = { 0 };
+
+       aconnector->dsc_aux = drm_dp_mst_dsc_aux_for_port(port);
+
+       if (!aconnector->dsc_aux)
+               return false;
+
+       if (drm_dp_dpcd_read(aconnector->dsc_aux, DP_DSC_SUPPORT, dsc_caps, 16) < 0)
+               return false;
+
+       if (!dc_dsc_parse_dsc_dpcd(aconnector->dc_link->ctx->dc,
+                                  dsc_caps, NULL,
+                                  &dc_sink->sink_dsc_caps.dsc_dec_caps))
+               return false;
+
+       return true;
+}
+
 static int dm_dp_mst_get_modes(struct drm_connector *connector)
 {
        struct amdgpu_dm_connector *aconnector = to_amdgpu_dm_connector(connector);
@@ -222,10 +245,14 @@ static int dm_dp_mst_get_modes(struct drm_connector *connector)
                /* dc_link_add_remote_sink returns a new reference */
                aconnector->dc_sink = dc_sink;
 
-               if (aconnector->dc_sink)
+               if (aconnector->dc_sink) {
                        amdgpu_dm_update_freesync_caps(
                                        connector, aconnector->edid);
 
+                       if (!validate_dsc_caps_on_connector(aconnector))
+                               memset(&aconnector->dc_sink->sink_dsc_caps,
+                                      0, sizeof(aconnector->dc_sink->sink_dsc_caps));
+               }
        }
 
        drm_connector_update_edid_property(