OSDN Git Service

drm/amd/display: Add MST capability to trigger_hotplug interface
authorMikita Lipski <mikita.lipski@amd.com>
Tue, 15 Sep 2020 12:50:49 +0000 (08:50 -0400)
committerAlex Deucher <alexander.deucher@amd.com>
Fri, 9 Apr 2021 20:53:12 +0000 (16:53 -0400)
[Why]
Need to be able to trigger software hotplug for MST connectors

[How]
For unplug the driver calls to disable topologies manager
that connector is attached to. For plugging in it does the
whole rediscovery of all connectors in drm device and enbles their
topologies if attached.

The interface for MST connectors works in the following way:

1. To disconnect all MST topologies currently connected:
   echo 0 > /sys/kernel/debug/dri/0/amdgpu_dm_trigger_hpd_mst

2. To reconnect/rediscover all topologies that are physically
connected to the card:
   echo 1 > /sys/kernel/debug/dri/0/amdgpu_dm_trigger_hpd_mst

A related fix which has been merged with this patch
Leo Ma(Hanghong Ma)'s work:

Set power states before disable MST topology
[Why]
When we try to disable MST topology from the
debugfs entry, some receiver will hang.
[How]
Set DPCD 600h power states to
2(power down mode)before disable MST topology.

Signed-off-by: Mikita Lipski <mikita.lipski@amd.com>
Reviewed-by: Sun peng Li <Sunpeng.Li@amd.com>
Acked-by: Qingqing Zhuo <qingqing.zhuo@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_debugfs.c

index 6659e7c..9a13f47 100644 (file)
@@ -2980,7 +2980,73 @@ static int mst_topo_show(struct seq_file *m, void *unused)
 }
 
 /*
- * Sets the force_timing_sync debug optino from the given string.
+ * Sets trigger hpd for MST topologies.
+ * All connected connectors will be rediscovered and re started as needed if val of 1 is sent.
+ * All topologies will be disconnected if val of 0 is set .
+ * Usage to enable topologies: echo 1 > /sys/kernel/debug/dri/0/amdgpu_dm_trigger_hpd_mst
+ * Usage to disable topologies: echo 0 > /sys/kernel/debug/dri/0/amdgpu_dm_trigger_hpd_mst
+ */
+static int trigger_hpd_mst_set(void *data, u64 val)
+{
+       struct amdgpu_device *adev = data;
+       struct drm_device *dev = adev_to_drm(adev);
+       struct drm_connector_list_iter iter;
+       struct amdgpu_dm_connector *aconnector;
+       struct drm_connector *connector;
+       struct dc_link *link = NULL;
+
+       if (val == 1) {
+               drm_connector_list_iter_begin(dev, &iter);
+               drm_for_each_connector_iter(connector, &iter) {
+                       aconnector = to_amdgpu_dm_connector(connector);
+                       if (aconnector->dc_link->type == dc_connection_mst_branch &&
+                           aconnector->mst_mgr.aux) {
+                               dc_link_detect(aconnector->dc_link, DETECT_REASON_HPD);
+                               drm_dp_mst_topology_mgr_set_mst(&aconnector->mst_mgr, true);
+                       }
+               }
+       } else if (val == 0) {
+               drm_connector_list_iter_begin(dev, &iter);
+               drm_for_each_connector_iter(connector, &iter) {
+                       aconnector = to_amdgpu_dm_connector(connector);
+                       if (!aconnector->dc_link)
+                               continue;
+
+                       if (!(aconnector->port && &aconnector->mst_port->mst_mgr))
+                               continue;
+
+                       link = aconnector->dc_link;
+                       dp_receiver_power_ctrl(link, false);
+                       drm_dp_mst_topology_mgr_set_mst(&aconnector->mst_port->mst_mgr, false);
+                       link->mst_stream_alloc_table.stream_count = 0;
+                       memset(link->mst_stream_alloc_table.stream_allocations, 0,
+                                       sizeof(link->mst_stream_alloc_table.stream_allocations));
+               }
+       } else {
+               return 0;
+       }
+       drm_kms_helper_hotplug_event(dev);
+
+       return 0;
+}
+
+/*
+ * The interface doesn't need get function, so it will return the
+ * value of zero
+ * Usage: cat /sys/kernel/debug/dri/0/amdgpu_dm_trigger_hpd_mst
+ */
+static int trigger_hpd_mst_get(void *data, u64 *val)
+{
+       *val = 0;
+       return 0;
+}
+
+DEFINE_DEBUGFS_ATTRIBUTE(trigger_hpd_mst_ops, trigger_hpd_mst_get,
+                        trigger_hpd_mst_set, "%llu\n");
+
+
+/*
+ * Sets the force_timing_sync debug option from the given string.
  * All connected displays will be force synchronized immediately.
  * Usage: echo 1 > /sys/kernel/debug/dri/0/amdgpu_dm_force_timing_sync
  */
@@ -3142,6 +3208,9 @@ void dtn_debugfs_init(struct amdgpu_device *adev)
        debugfs_create_file_unsafe("amdgpu_dm_dmcub_trace_event_en", 0644, root,
                                   adev, &dmcub_trace_event_state_fops);
 
+       debugfs_create_file_unsafe("amdgpu_dm_trigger_hpd_mst", 0644, root,
+                                  adev, &trigger_hpd_mst_ops);
+
        debugfs_create_file_unsafe("amdgpu_dm_dcc_en", 0644, root, adev,
                                   &dcc_en_bits_fops);
 }