]> asedeno.scripts.mit.edu Git - linux.git/blobdiff - include/drm/drm_dp_mst_helper.h
drm/dp_mst: Add DSC enablement helpers to DRM
[linux.git] / include / drm / drm_dp_mst_helper.h
index a448d701dc7ecb621625201a89d69e3c5ca49d52..14ccda19d9cc06380a64d04539f047f54097539c 100644 (file)
 #include <drm/drm_dp_helper.h>
 #include <drm/drm_atomic.h>
 
+#if IS_ENABLED(CONFIG_DRM_DEBUG_DP_MST_TOPOLOGY_REFS)
+#include <linux/stackdepot.h>
+#include <linux/timekeeping.h>
+
+enum drm_dp_mst_topology_ref_type {
+       DRM_DP_MST_TOPOLOGY_REF_GET,
+       DRM_DP_MST_TOPOLOGY_REF_PUT,
+};
+
+struct drm_dp_mst_topology_ref_history {
+       struct drm_dp_mst_topology_ref_entry {
+               enum drm_dp_mst_topology_ref_type type;
+               int count;
+               ktime_t ts_nsec;
+               depot_stack_handle_t backtrace;
+       } *entries;
+       int len;
+};
+#endif /* IS_ENABLED(CONFIG_DRM_DEBUG_DP_MST_TOPOLOGY_REFS) */
+
 struct drm_dp_mst_branch;
 
 /**
@@ -45,21 +65,31 @@ struct drm_dp_vcpi {
 /**
  * struct drm_dp_mst_port - MST port
  * @port_num: port number
- * @input: if this port is an input port.
- * @mcs: message capability status - DP 1.2 spec.
- * @ddps: DisplayPort Device Plug Status - DP 1.2
- * @pdt: Peer Device Type
- * @ldps: Legacy Device Plug Status
- * @dpcd_rev: DPCD revision of device on this port
- * @num_sdp_streams: Number of simultaneous streams
- * @num_sdp_stream_sinks: Number of stream sinks
- * @available_pbn: Available bandwidth for this port.
+ * @input: if this port is an input port. Protected by
+ * &drm_dp_mst_topology_mgr.base.lock.
+ * @mcs: message capability status - DP 1.2 spec. Protected by
+ * &drm_dp_mst_topology_mgr.base.lock.
+ * @ddps: DisplayPort Device Plug Status - DP 1.2. Protected by
+ * &drm_dp_mst_topology_mgr.base.lock.
+ * @pdt: Peer Device Type. Protected by
+ * &drm_dp_mst_topology_mgr.base.lock.
+ * @ldps: Legacy Device Plug Status. Protected by
+ * &drm_dp_mst_topology_mgr.base.lock.
+ * @dpcd_rev: DPCD revision of device on this port. Protected by
+ * &drm_dp_mst_topology_mgr.base.lock.
+ * @num_sdp_streams: Number of simultaneous streams. Protected by
+ * &drm_dp_mst_topology_mgr.base.lock.
+ * @num_sdp_stream_sinks: Number of stream sinks. Protected by
+ * &drm_dp_mst_topology_mgr.base.lock.
+ * @available_pbn: Available bandwidth for this port. Protected by
+ * &drm_dp_mst_topology_mgr.base.lock.
  * @next: link to next port on this branch device
- * @mstb: branch device attach below this port
- * @aux: i2c aux transport to talk to device connected to this port.
+ * @aux: i2c aux transport to talk to device connected to this port, protected
+ * by &drm_dp_mst_topology_mgr.base.lock.
  * @parent: branch device parent of this port
  * @vcpi: Virtual Channel Payload info for this port.
- * @connector: DRM connector this port is connected to.
+ * @connector: DRM connector this port is connected to. Protected by
+ * &drm_dp_mst_topology_mgr.base.lock.
  * @mgr: topology manager this port lives under.
  *
  * This structure represents an MST port endpoint on a device somewhere
@@ -79,6 +109,14 @@ struct drm_dp_mst_port {
         */
        struct kref malloc_kref;
 
+#if IS_ENABLED(CONFIG_DRM_DEBUG_DP_MST_TOPOLOGY_REFS)
+       /**
+        * @topology_ref_history: A history of each topology
+        * reference/dereference. See CONFIG_DRM_DEBUG_DP_MST_TOPOLOGY_REFS.
+        */
+       struct drm_dp_mst_topology_ref_history topology_ref_history;
+#endif
+
        u8 port_num;
        bool input;
        bool mcs;
@@ -90,7 +128,17 @@ struct drm_dp_mst_port {
        u8 num_sdp_stream_sinks;
        uint16_t available_pbn;
        struct list_head next;
-       struct drm_dp_mst_branch *mstb; /* pointer to an mstb if this port has one */
+       /**
+        * @mstb: the branch device connected to this port, if there is one.
+        * This should be considered protected for reading by
+        * &drm_dp_mst_topology_mgr.lock. There are two exceptions to this:
+        * &drm_dp_mst_topology_mgr.up_req_work and
+        * &drm_dp_mst_topology_mgr.work, which do not grab
+        * &drm_dp_mst_topology_mgr.lock during reads but are the only
+        * updaters of this list and are protected from writing concurrently
+        * by &drm_dp_mst_topology_mgr.probe_lock.
+        */
+       struct drm_dp_mst_branch *mstb;
        struct drm_dp_aux aux; /* i2c bus for this port? */
        struct drm_dp_mst_branch *parent;
 
@@ -108,6 +156,8 @@ struct drm_dp_mst_port {
         * audio-capable.
         */
        bool has_audio;
+
+       bool fec_capable;
 };
 
 /**
@@ -116,7 +166,6 @@ struct drm_dp_mst_port {
  * @lct: Link count total to talk to this branch device.
  * @num_ports: number of ports on the branch.
  * @msg_slots: one bit per transmitted msg slot.
- * @ports: linked list of ports on this branch.
  * @port_parent: pointer to the port parent, NULL if toplevel.
  * @mgr: topology manager for this branch device.
  * @tx_slots: transmission slots for this device.
@@ -143,11 +192,35 @@ struct drm_dp_mst_branch {
         */
        struct kref malloc_kref;
 
+#if IS_ENABLED(CONFIG_DRM_DEBUG_DP_MST_TOPOLOGY_REFS)
+       /**
+        * @topology_ref_history: A history of each topology
+        * reference/dereference. See CONFIG_DRM_DEBUG_DP_MST_TOPOLOGY_REFS.
+        */
+       struct drm_dp_mst_topology_ref_history topology_ref_history;
+#endif
+
+       /**
+        * @destroy_next: linked-list entry used by
+        * drm_dp_delayed_destroy_work()
+        */
+       struct list_head destroy_next;
+
        u8 rad[8];
        u8 lct;
        int num_ports;
 
        int msg_slots;
+       /**
+        * @ports: the list of ports on this branch device. This should be
+        * considered protected for reading by &drm_dp_mst_topology_mgr.lock.
+        * There are two exceptions to this:
+        * &drm_dp_mst_topology_mgr.up_req_work and
+        * &drm_dp_mst_topology_mgr.work, which do not grab
+        * &drm_dp_mst_topology_mgr.lock during reads but are the only
+        * updaters of this list and are protected from updating the list
+        * concurrently by @drm_dp_mst_topology_mgr.probe_lock
+        */
        struct list_head ports;
 
        /* list of tx ops queue for this port */
@@ -312,6 +385,7 @@ struct drm_dp_port_number_req {
 
 struct drm_dp_enum_path_resources_ack_reply {
        u8 port_number;
+       bool fec_capable;
        u16 full_payload_bw_number;
        u16 avail_payload_bw_number;
 };
@@ -428,6 +502,7 @@ struct drm_dp_payload {
 struct drm_dp_vcpi_allocation {
        struct drm_dp_mst_port *port;
        int vcpi;
+       bool dsc_enabled;
        struct list_head next;
 };
 
@@ -496,8 +571,15 @@ struct drm_dp_mst_topology_mgr {
        struct mutex lock;
 
        /**
-        * @mst_state: If this manager is enabled for an MST capable port.
-        * False if no MST sink/branch devices is connected.
+        * @probe_lock: Prevents @work and @up_req_work, the only writers of
+        * &drm_dp_mst_port.mstb and &drm_dp_mst_branch.ports, from racing
+        * while they update the topology.
+        */
+       struct mutex probe_lock;
+
+       /**
+        * @mst_state: If this manager is enabled for an MST capable port. False
+        * if no MST sink/branch devices is connected.
         */
        bool mst_state : 1;
 
@@ -579,18 +661,49 @@ struct drm_dp_mst_topology_mgr {
        struct work_struct tx_work;
 
        /**
-        * @destroy_connector_list: List of to be destroyed connectors.
+        * @destroy_port_list: List of to be destroyed connectors.
+        */
+       struct list_head destroy_port_list;
+       /**
+        * @destroy_branch_device_list: List of to be destroyed branch
+        * devices.
         */
-       struct list_head destroy_connector_list;
+       struct list_head destroy_branch_device_list;
        /**
-        * @destroy_connector_lock: Protects @connector_list.
+        * @delayed_destroy_lock: Protects @destroy_port_list and
+        * @destroy_branch_device_list.
         */
-       struct mutex destroy_connector_lock;
+       struct mutex delayed_destroy_lock;
        /**
-        * @destroy_connector_work: Work item to destroy connectors. Needed to
-        * avoid locking inversion.
+        * @delayed_destroy_work: Work item to destroy MST port and branch
+        * devices, needed to avoid locking inversion.
         */
-       struct work_struct destroy_connector_work;
+       struct work_struct delayed_destroy_work;
+
+       /**
+        * @up_req_list: List of pending up requests from the topology that
+        * need to be processed, in chronological order.
+        */
+       struct list_head up_req_list;
+       /**
+        * @up_req_lock: Protects @up_req_list
+        */
+       struct mutex up_req_lock;
+       /**
+        * @up_req_work: Work item to process up requests received from the
+        * topology. Needed to avoid blocking hotplug handling and sideband
+        * transmissions.
+        */
+       struct work_struct up_req_work;
+
+#if IS_ENABLED(CONFIG_DRM_DEBUG_DP_MST_TOPOLOGY_REFS)
+       /**
+        * @topology_ref_history_lock: protects
+        * &drm_dp_mst_port.topology_ref_history and
+        * &drm_dp_mst_branch.topology_ref_history.
+        */
+       struct mutex topology_ref_history_lock;
+#endif
 };
 
 int drm_dp_mst_topology_mgr_init(struct drm_dp_mst_topology_mgr *mgr,
@@ -607,15 +720,18 @@ int drm_dp_mst_topology_mgr_set_mst(struct drm_dp_mst_topology_mgr *mgr, bool ms
 int drm_dp_mst_hpd_irq(struct drm_dp_mst_topology_mgr *mgr, u8 *esi, bool *handled);
 
 
-enum drm_connector_status drm_dp_mst_detect_port(struct drm_connector *connector, struct drm_dp_mst_topology_mgr *mgr, struct drm_dp_mst_port *port);
+int
+drm_dp_mst_detect_port(struct drm_connector *connector,
+                      struct drm_modeset_acquire_ctx *ctx,
+                      struct drm_dp_mst_topology_mgr *mgr,
+                      struct drm_dp_mst_port *port);
 
 bool drm_dp_mst_port_has_audio(struct drm_dp_mst_topology_mgr *mgr,
                                        struct drm_dp_mst_port *port);
 struct edid *drm_dp_mst_get_edid(struct drm_connector *connector, struct drm_dp_mst_topology_mgr *mgr, struct drm_dp_mst_port *port);
 
 
-int drm_dp_calc_pbn_mode(int clock, int bpp);
-
+int drm_dp_calc_pbn_mode(int clock, int bpp, bool dsc);
 
 bool drm_dp_mst_allocate_vcpi(struct drm_dp_mst_topology_mgr *mgr,
                              struct drm_dp_mst_port *port, int pbn, int slots);
@@ -646,7 +762,8 @@ void drm_dp_mst_dump_topology(struct seq_file *m,
 
 void drm_dp_mst_topology_mgr_suspend(struct drm_dp_mst_topology_mgr *mgr);
 int __must_check
-drm_dp_mst_topology_mgr_resume(struct drm_dp_mst_topology_mgr *mgr);
+drm_dp_mst_topology_mgr_resume(struct drm_dp_mst_topology_mgr *mgr,
+                              bool sync);
 
 ssize_t drm_dp_mst_dpcd_read(struct drm_dp_aux *aux,
                             unsigned int offset, void *buffer, size_t size);
@@ -663,7 +780,12 @@ struct drm_dp_mst_topology_state *drm_atomic_get_mst_topology_state(struct drm_a
 int __must_check
 drm_dp_atomic_find_vcpi_slots(struct drm_atomic_state *state,
                              struct drm_dp_mst_topology_mgr *mgr,
-                             struct drm_dp_mst_port *port, int pbn);
+                             struct drm_dp_mst_port *port, int pbn,
+                             int pbn_div);
+int drm_dp_mst_atomic_enable_dsc(struct drm_atomic_state *state,
+                                struct drm_dp_mst_port *port,
+                                int pbn, int pbn_div,
+                                bool enable);
 int __must_check
 drm_dp_atomic_release_vcpi_slots(struct drm_atomic_state *state,
                                 struct drm_dp_mst_topology_mgr *mgr,
@@ -675,6 +797,8 @@ int __must_check drm_dp_mst_atomic_check(struct drm_atomic_state *state);
 void drm_dp_mst_get_port_malloc(struct drm_dp_mst_port *port);
 void drm_dp_mst_put_port_malloc(struct drm_dp_mst_port *port);
 
+struct drm_dp_aux *drm_dp_mst_dsc_aux_for_port(struct drm_dp_mst_port *port);
+
 extern const struct drm_private_state_funcs drm_dp_mst_topology_state_funcs;
 
 /**