drm/amd/display: dsc mst re-compute pbn for changes on hub
authorHersen Wu <hersenwu@amd.com>
Wed, 2 Feb 2022 21:08:45 +0000 (16:08 -0500)
committerAlex Deucher <alexander.deucher@amd.com>
Wed, 16 Feb 2022 22:01:48 +0000 (17:01 -0500)
[why]
when unplug 1 dp from dsc mst hub, atomic_check new request
dc_state only include info for the unplug dp. this will not
trigger re-compute pbn for displays still connected to hub.

[how] all displays connected to dsc hub are available in
dc->current_state, by comparing dc->current_state and new
request from atomic_chceck, it will provide info of
displays connected to hub and do pbn re-compute.

Reviewed-by: Roman Li <Roman.Li@amd.com>
Acked-by: Jasdeep Dhillon <jdhillon@amd.com>
Signed-off-by: Hersen Wu <hersenwu@amd.com>
Tested-by: Daniel Wheeler <daniel.wheeler@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c

index d24be9f..0e58c1a 100644 (file)
@@ -911,22 +911,31 @@ static bool is_dsc_need_re_compute(
        struct dc_state *dc_state,
        struct dc_link *dc_link)
 {
-       int i;
+       int i, j;
        bool is_dsc_need_re_compute = false;
+       struct amdgpu_dm_connector *stream_on_link[MAX_PIPES];
+       int new_stream_on_link_num = 0;
+       struct amdgpu_dm_connector *aconnector;
+       struct dc_stream_state *stream;
+       const struct dc *dc = dc_link->dc;
 
-       /* only check phy used by mst branch */
+       /* only check phy used by dsc mst branch */
        if (dc_link->type != dc_connection_mst_branch)
                return false;
 
+       if (!(dc_link->dpcd_caps.dsc_caps.dsc_basic_caps.fields.dsc_support.DSC_SUPPORT ||
+               dc_link->dpcd_caps.dsc_caps.dsc_basic_caps.fields.dsc_support.DSC_PASSTHROUGH_SUPPORT))
+               return false;
+
+       for (i = 0; i < MAX_PIPES; i++)
+               stream_on_link[i] = NULL;
+
        /* check if there is mode change in new request */
        for (i = 0; i < dc_state->stream_count; i++) {
-               struct amdgpu_dm_connector *aconnector;
-               struct dc_stream_state *stream;
                struct drm_crtc_state *new_crtc_state;
                struct drm_connector_state *new_conn_state;
 
                stream = dc_state->streams[i];
-
                if (!stream)
                        continue;
 
@@ -938,8 +947,10 @@ static bool is_dsc_need_re_compute(
                if (!aconnector)
                        continue;
 
-               new_conn_state = drm_atomic_get_new_connector_state(state, &aconnector->base);
+               stream_on_link[new_stream_on_link_num] = aconnector;
+               new_stream_on_link_num++;
 
+               new_conn_state = drm_atomic_get_new_connector_state(state, &aconnector->base);
                if (!new_conn_state)
                        continue;
 
@@ -950,7 +961,6 @@ static bool is_dsc_need_re_compute(
                        continue;
 
                new_crtc_state = drm_atomic_get_new_crtc_state(state, new_conn_state->crtc);
-
                if (!new_crtc_state)
                        continue;
 
@@ -960,7 +970,34 @@ static bool is_dsc_need_re_compute(
                if (new_crtc_state->enable && new_crtc_state->active) {
                        if (new_crtc_state->mode_changed || new_crtc_state->active_changed ||
                                new_crtc_state->connectors_changed)
-                               is_dsc_need_re_compute = true;
+                               return true;
+               }
+       }
+
+       /* check current_state if there stream on link but it is not in
+        * new request state
+        */
+       for (i = 0; i < dc->current_state->stream_count; i++) {
+               stream = dc->current_state->streams[i];
+               /* only check stream on the mst hub */
+               if (stream->link != dc_link)
+                       continue;
+
+               aconnector = (struct amdgpu_dm_connector *)stream->dm_stream_context;
+               if (!aconnector)
+                       continue;
+
+               for (j = 0; j < new_stream_on_link_num; j++) {
+                       if (stream_on_link[j]) {
+                               if (aconnector == stream_on_link[j])
+                                       break;
+                       }
+               }
+
+               if (j == new_stream_on_link_num) {
+                       /* not in new state */
+                       is_dsc_need_re_compute = true;
+                       break;
                }
        }