1da68386dSThomas Zimmermann /* 2da68386dSThomas Zimmermann * Copyright © 2014 Red Hat. 3da68386dSThomas Zimmermann * 4da68386dSThomas Zimmermann * Permission to use, copy, modify, distribute, and sell this software and its 5da68386dSThomas Zimmermann * documentation for any purpose is hereby granted without fee, provided that 6da68386dSThomas Zimmermann * the above copyright notice appear in all copies and that both that copyright 7da68386dSThomas Zimmermann * notice and this permission notice appear in supporting documentation, and 8da68386dSThomas Zimmermann * that the name of the copyright holders not be used in advertising or 9da68386dSThomas Zimmermann * publicity pertaining to distribution of the software without specific, 10da68386dSThomas Zimmermann * written prior permission. The copyright holders make no representations 11da68386dSThomas Zimmermann * about the suitability of this software for any purpose. It is provided "as 12da68386dSThomas Zimmermann * is" without express or implied warranty. 13da68386dSThomas Zimmermann * 14da68386dSThomas Zimmermann * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, 15da68386dSThomas Zimmermann * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO 16da68386dSThomas Zimmermann * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR 17da68386dSThomas Zimmermann * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, 18da68386dSThomas Zimmermann * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER 19da68386dSThomas Zimmermann * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE 20da68386dSThomas Zimmermann * OF THIS SOFTWARE. 21da68386dSThomas Zimmermann */ 22da68386dSThomas Zimmermann #ifndef _DRM_DP_MST_HELPER_H_ 23da68386dSThomas Zimmermann #define _DRM_DP_MST_HELPER_H_ 24da68386dSThomas Zimmermann 25da68386dSThomas Zimmermann #include <linux/types.h> 26da68386dSThomas Zimmermann #include <drm/display/drm_dp_helper.h> 27da68386dSThomas Zimmermann #include <drm/drm_atomic.h> 28da68386dSThomas Zimmermann 29da68386dSThomas Zimmermann #if IS_ENABLED(CONFIG_DRM_DEBUG_DP_MST_TOPOLOGY_REFS) 30da68386dSThomas Zimmermann #include <linux/stackdepot.h> 31da68386dSThomas Zimmermann #include <linux/timekeeping.h> 32da68386dSThomas Zimmermann 33da68386dSThomas Zimmermann enum drm_dp_mst_topology_ref_type { 34da68386dSThomas Zimmermann DRM_DP_MST_TOPOLOGY_REF_GET, 35da68386dSThomas Zimmermann DRM_DP_MST_TOPOLOGY_REF_PUT, 36da68386dSThomas Zimmermann }; 37da68386dSThomas Zimmermann 38da68386dSThomas Zimmermann struct drm_dp_mst_topology_ref_history { 39da68386dSThomas Zimmermann struct drm_dp_mst_topology_ref_entry { 40da68386dSThomas Zimmermann enum drm_dp_mst_topology_ref_type type; 41da68386dSThomas Zimmermann int count; 42da68386dSThomas Zimmermann ktime_t ts_nsec; 43da68386dSThomas Zimmermann depot_stack_handle_t backtrace; 44da68386dSThomas Zimmermann } *entries; 45da68386dSThomas Zimmermann int len; 46da68386dSThomas Zimmermann }; 47da68386dSThomas Zimmermann #endif /* IS_ENABLED(CONFIG_DRM_DEBUG_DP_MST_TOPOLOGY_REFS) */ 48da68386dSThomas Zimmermann 49da68386dSThomas Zimmermann struct drm_dp_mst_branch; 50da68386dSThomas Zimmermann 51da68386dSThomas Zimmermann /** 52da68386dSThomas Zimmermann * struct drm_dp_vcpi - Virtual Channel Payload Identifier 53da68386dSThomas Zimmermann * @vcpi: Virtual channel ID. 54da68386dSThomas Zimmermann * @pbn: Payload Bandwidth Number for this channel 55da68386dSThomas Zimmermann * @aligned_pbn: PBN aligned with slot size 56da68386dSThomas Zimmermann * @num_slots: number of slots for this PBN 57da68386dSThomas Zimmermann */ 58da68386dSThomas Zimmermann struct drm_dp_vcpi { 59da68386dSThomas Zimmermann int vcpi; 60da68386dSThomas Zimmermann int pbn; 61da68386dSThomas Zimmermann int aligned_pbn; 62da68386dSThomas Zimmermann int num_slots; 63da68386dSThomas Zimmermann }; 64da68386dSThomas Zimmermann 65da68386dSThomas Zimmermann /** 66da68386dSThomas Zimmermann * struct drm_dp_mst_port - MST port 67da68386dSThomas Zimmermann * @port_num: port number 68da68386dSThomas Zimmermann * @input: if this port is an input port. Protected by 69da68386dSThomas Zimmermann * &drm_dp_mst_topology_mgr.base.lock. 70da68386dSThomas Zimmermann * @mcs: message capability status - DP 1.2 spec. Protected by 71da68386dSThomas Zimmermann * &drm_dp_mst_topology_mgr.base.lock. 72da68386dSThomas Zimmermann * @ddps: DisplayPort Device Plug Status - DP 1.2. Protected by 73da68386dSThomas Zimmermann * &drm_dp_mst_topology_mgr.base.lock. 74da68386dSThomas Zimmermann * @pdt: Peer Device Type. Protected by 75da68386dSThomas Zimmermann * &drm_dp_mst_topology_mgr.base.lock. 76da68386dSThomas Zimmermann * @ldps: Legacy Device Plug Status. Protected by 77da68386dSThomas Zimmermann * &drm_dp_mst_topology_mgr.base.lock. 78da68386dSThomas Zimmermann * @dpcd_rev: DPCD revision of device on this port. Protected by 79da68386dSThomas Zimmermann * &drm_dp_mst_topology_mgr.base.lock. 80da68386dSThomas Zimmermann * @num_sdp_streams: Number of simultaneous streams. Protected by 81da68386dSThomas Zimmermann * &drm_dp_mst_topology_mgr.base.lock. 82da68386dSThomas Zimmermann * @num_sdp_stream_sinks: Number of stream sinks. Protected by 83da68386dSThomas Zimmermann * &drm_dp_mst_topology_mgr.base.lock. 84da68386dSThomas Zimmermann * @full_pbn: Max possible bandwidth for this port. Protected by 85da68386dSThomas Zimmermann * &drm_dp_mst_topology_mgr.base.lock. 86da68386dSThomas Zimmermann * @next: link to next port on this branch device 87da68386dSThomas Zimmermann * @aux: i2c aux transport to talk to device connected to this port, protected 88da68386dSThomas Zimmermann * by &drm_dp_mst_topology_mgr.base.lock. 89da68386dSThomas Zimmermann * @parent: branch device parent of this port 90da68386dSThomas Zimmermann * @vcpi: Virtual Channel Payload info for this port. 91da68386dSThomas Zimmermann * @connector: DRM connector this port is connected to. Protected by 92da68386dSThomas Zimmermann * &drm_dp_mst_topology_mgr.base.lock. 93da68386dSThomas Zimmermann * @mgr: topology manager this port lives under. 94da68386dSThomas Zimmermann * 95da68386dSThomas Zimmermann * This structure represents an MST port endpoint on a device somewhere 96da68386dSThomas Zimmermann * in the MST topology. 97da68386dSThomas Zimmermann */ 98da68386dSThomas Zimmermann struct drm_dp_mst_port { 99da68386dSThomas Zimmermann /** 100da68386dSThomas Zimmermann * @topology_kref: refcount for this port's lifetime in the topology, 101da68386dSThomas Zimmermann * only the DP MST helpers should need to touch this 102da68386dSThomas Zimmermann */ 103da68386dSThomas Zimmermann struct kref topology_kref; 104da68386dSThomas Zimmermann 105da68386dSThomas Zimmermann /** 106da68386dSThomas Zimmermann * @malloc_kref: refcount for the memory allocation containing this 107da68386dSThomas Zimmermann * structure. See drm_dp_mst_get_port_malloc() and 108da68386dSThomas Zimmermann * drm_dp_mst_put_port_malloc(). 109da68386dSThomas Zimmermann */ 110da68386dSThomas Zimmermann struct kref malloc_kref; 111da68386dSThomas Zimmermann 112da68386dSThomas Zimmermann #if IS_ENABLED(CONFIG_DRM_DEBUG_DP_MST_TOPOLOGY_REFS) 113da68386dSThomas Zimmermann /** 114da68386dSThomas Zimmermann * @topology_ref_history: A history of each topology 115da68386dSThomas Zimmermann * reference/dereference. See CONFIG_DRM_DEBUG_DP_MST_TOPOLOGY_REFS. 116da68386dSThomas Zimmermann */ 117da68386dSThomas Zimmermann struct drm_dp_mst_topology_ref_history topology_ref_history; 118da68386dSThomas Zimmermann #endif 119da68386dSThomas Zimmermann 120da68386dSThomas Zimmermann u8 port_num; 121da68386dSThomas Zimmermann bool input; 122da68386dSThomas Zimmermann bool mcs; 123da68386dSThomas Zimmermann bool ddps; 124da68386dSThomas Zimmermann u8 pdt; 125da68386dSThomas Zimmermann bool ldps; 126da68386dSThomas Zimmermann u8 dpcd_rev; 127da68386dSThomas Zimmermann u8 num_sdp_streams; 128da68386dSThomas Zimmermann u8 num_sdp_stream_sinks; 129da68386dSThomas Zimmermann uint16_t full_pbn; 130da68386dSThomas Zimmermann struct list_head next; 131da68386dSThomas Zimmermann /** 132da68386dSThomas Zimmermann * @mstb: the branch device connected to this port, if there is one. 133da68386dSThomas Zimmermann * This should be considered protected for reading by 134da68386dSThomas Zimmermann * &drm_dp_mst_topology_mgr.lock. There are two exceptions to this: 135da68386dSThomas Zimmermann * &drm_dp_mst_topology_mgr.up_req_work and 136da68386dSThomas Zimmermann * &drm_dp_mst_topology_mgr.work, which do not grab 137da68386dSThomas Zimmermann * &drm_dp_mst_topology_mgr.lock during reads but are the only 138da68386dSThomas Zimmermann * updaters of this list and are protected from writing concurrently 139da68386dSThomas Zimmermann * by &drm_dp_mst_topology_mgr.probe_lock. 140da68386dSThomas Zimmermann */ 141da68386dSThomas Zimmermann struct drm_dp_mst_branch *mstb; 142da68386dSThomas Zimmermann struct drm_dp_aux aux; /* i2c bus for this port? */ 143da68386dSThomas Zimmermann struct drm_dp_mst_branch *parent; 144da68386dSThomas Zimmermann 145da68386dSThomas Zimmermann struct drm_dp_vcpi vcpi; 146da68386dSThomas Zimmermann struct drm_connector *connector; 147da68386dSThomas Zimmermann struct drm_dp_mst_topology_mgr *mgr; 148da68386dSThomas Zimmermann 149da68386dSThomas Zimmermann /** 150da68386dSThomas Zimmermann * @cached_edid: for DP logical ports - make tiling work by ensuring 151da68386dSThomas Zimmermann * that the EDID for all connectors is read immediately. 152da68386dSThomas Zimmermann */ 153da68386dSThomas Zimmermann struct edid *cached_edid; 154da68386dSThomas Zimmermann /** 155da68386dSThomas Zimmermann * @has_audio: Tracks whether the sink connector to this port is 156da68386dSThomas Zimmermann * audio-capable. 157da68386dSThomas Zimmermann */ 158da68386dSThomas Zimmermann bool has_audio; 159da68386dSThomas Zimmermann 160da68386dSThomas Zimmermann /** 161da68386dSThomas Zimmermann * @fec_capable: bool indicating if FEC can be supported up to that 162da68386dSThomas Zimmermann * point in the MST topology. 163da68386dSThomas Zimmermann */ 164da68386dSThomas Zimmermann bool fec_capable; 165da68386dSThomas Zimmermann }; 166da68386dSThomas Zimmermann 167da68386dSThomas Zimmermann /* sideband msg header - not bit struct */ 168da68386dSThomas Zimmermann struct drm_dp_sideband_msg_hdr { 169da68386dSThomas Zimmermann u8 lct; 170da68386dSThomas Zimmermann u8 lcr; 171da68386dSThomas Zimmermann u8 rad[8]; 172da68386dSThomas Zimmermann bool broadcast; 173da68386dSThomas Zimmermann bool path_msg; 174da68386dSThomas Zimmermann u8 msg_len; 175da68386dSThomas Zimmermann bool somt; 176da68386dSThomas Zimmermann bool eomt; 177da68386dSThomas Zimmermann bool seqno; 178da68386dSThomas Zimmermann }; 179da68386dSThomas Zimmermann 180da68386dSThomas Zimmermann struct drm_dp_sideband_msg_rx { 181da68386dSThomas Zimmermann u8 chunk[48]; 182da68386dSThomas Zimmermann u8 msg[256]; 183da68386dSThomas Zimmermann u8 curchunk_len; 184da68386dSThomas Zimmermann u8 curchunk_idx; /* chunk we are parsing now */ 185da68386dSThomas Zimmermann u8 curchunk_hdrlen; 186da68386dSThomas Zimmermann u8 curlen; /* total length of the msg */ 187da68386dSThomas Zimmermann bool have_somt; 188da68386dSThomas Zimmermann bool have_eomt; 189da68386dSThomas Zimmermann struct drm_dp_sideband_msg_hdr initial_hdr; 190da68386dSThomas Zimmermann }; 191da68386dSThomas Zimmermann 192da68386dSThomas Zimmermann /** 193da68386dSThomas Zimmermann * struct drm_dp_mst_branch - MST branch device. 194da68386dSThomas Zimmermann * @rad: Relative Address to talk to this branch device. 195da68386dSThomas Zimmermann * @lct: Link count total to talk to this branch device. 196da68386dSThomas Zimmermann * @num_ports: number of ports on the branch. 197da68386dSThomas Zimmermann * @port_parent: pointer to the port parent, NULL if toplevel. 198da68386dSThomas Zimmermann * @mgr: topology manager for this branch device. 199da68386dSThomas Zimmermann * @link_address_sent: if a link address message has been sent to this device yet. 200da68386dSThomas Zimmermann * @guid: guid for DP 1.2 branch device. port under this branch can be 201da68386dSThomas Zimmermann * identified by port #. 202da68386dSThomas Zimmermann * 203da68386dSThomas Zimmermann * This structure represents an MST branch device, there is one 204da68386dSThomas Zimmermann * primary branch device at the root, along with any other branches connected 205da68386dSThomas Zimmermann * to downstream port of parent branches. 206da68386dSThomas Zimmermann */ 207da68386dSThomas Zimmermann struct drm_dp_mst_branch { 208da68386dSThomas Zimmermann /** 209da68386dSThomas Zimmermann * @topology_kref: refcount for this branch device's lifetime in the 210da68386dSThomas Zimmermann * topology, only the DP MST helpers should need to touch this 211da68386dSThomas Zimmermann */ 212da68386dSThomas Zimmermann struct kref topology_kref; 213da68386dSThomas Zimmermann 214da68386dSThomas Zimmermann /** 215da68386dSThomas Zimmermann * @malloc_kref: refcount for the memory allocation containing this 216da68386dSThomas Zimmermann * structure. See drm_dp_mst_get_mstb_malloc() and 217da68386dSThomas Zimmermann * drm_dp_mst_put_mstb_malloc(). 218da68386dSThomas Zimmermann */ 219da68386dSThomas Zimmermann struct kref malloc_kref; 220da68386dSThomas Zimmermann 221da68386dSThomas Zimmermann #if IS_ENABLED(CONFIG_DRM_DEBUG_DP_MST_TOPOLOGY_REFS) 222da68386dSThomas Zimmermann /** 223da68386dSThomas Zimmermann * @topology_ref_history: A history of each topology 224da68386dSThomas Zimmermann * reference/dereference. See CONFIG_DRM_DEBUG_DP_MST_TOPOLOGY_REFS. 225da68386dSThomas Zimmermann */ 226da68386dSThomas Zimmermann struct drm_dp_mst_topology_ref_history topology_ref_history; 227da68386dSThomas Zimmermann #endif 228da68386dSThomas Zimmermann 229da68386dSThomas Zimmermann /** 230da68386dSThomas Zimmermann * @destroy_next: linked-list entry used by 231da68386dSThomas Zimmermann * drm_dp_delayed_destroy_work() 232da68386dSThomas Zimmermann */ 233da68386dSThomas Zimmermann struct list_head destroy_next; 234da68386dSThomas Zimmermann 235da68386dSThomas Zimmermann u8 rad[8]; 236da68386dSThomas Zimmermann u8 lct; 237da68386dSThomas Zimmermann int num_ports; 238da68386dSThomas Zimmermann 239da68386dSThomas Zimmermann /** 240da68386dSThomas Zimmermann * @ports: the list of ports on this branch device. This should be 241da68386dSThomas Zimmermann * considered protected for reading by &drm_dp_mst_topology_mgr.lock. 242da68386dSThomas Zimmermann * There are two exceptions to this: 243da68386dSThomas Zimmermann * &drm_dp_mst_topology_mgr.up_req_work and 244da68386dSThomas Zimmermann * &drm_dp_mst_topology_mgr.work, which do not grab 245da68386dSThomas Zimmermann * &drm_dp_mst_topology_mgr.lock during reads but are the only 246da68386dSThomas Zimmermann * updaters of this list and are protected from updating the list 247da68386dSThomas Zimmermann * concurrently by @drm_dp_mst_topology_mgr.probe_lock 248da68386dSThomas Zimmermann */ 249da68386dSThomas Zimmermann struct list_head ports; 250da68386dSThomas Zimmermann 251da68386dSThomas Zimmermann struct drm_dp_mst_port *port_parent; 252da68386dSThomas Zimmermann struct drm_dp_mst_topology_mgr *mgr; 253da68386dSThomas Zimmermann 254da68386dSThomas Zimmermann bool link_address_sent; 255da68386dSThomas Zimmermann 256da68386dSThomas Zimmermann /* global unique identifier to identify branch devices */ 257da68386dSThomas Zimmermann u8 guid[16]; 258da68386dSThomas Zimmermann }; 259da68386dSThomas Zimmermann 260da68386dSThomas Zimmermann 261da68386dSThomas Zimmermann struct drm_dp_nak_reply { 262da68386dSThomas Zimmermann u8 guid[16]; 263da68386dSThomas Zimmermann u8 reason; 264da68386dSThomas Zimmermann u8 nak_data; 265da68386dSThomas Zimmermann }; 266da68386dSThomas Zimmermann 267da68386dSThomas Zimmermann struct drm_dp_link_address_ack_reply { 268da68386dSThomas Zimmermann u8 guid[16]; 269da68386dSThomas Zimmermann u8 nports; 270da68386dSThomas Zimmermann struct drm_dp_link_addr_reply_port { 271da68386dSThomas Zimmermann bool input_port; 272da68386dSThomas Zimmermann u8 peer_device_type; 273da68386dSThomas Zimmermann u8 port_number; 274da68386dSThomas Zimmermann bool mcs; 275da68386dSThomas Zimmermann bool ddps; 276da68386dSThomas Zimmermann bool legacy_device_plug_status; 277da68386dSThomas Zimmermann u8 dpcd_revision; 278da68386dSThomas Zimmermann u8 peer_guid[16]; 279da68386dSThomas Zimmermann u8 num_sdp_streams; 280da68386dSThomas Zimmermann u8 num_sdp_stream_sinks; 281da68386dSThomas Zimmermann } ports[16]; 282da68386dSThomas Zimmermann }; 283da68386dSThomas Zimmermann 284da68386dSThomas Zimmermann struct drm_dp_remote_dpcd_read_ack_reply { 285da68386dSThomas Zimmermann u8 port_number; 286da68386dSThomas Zimmermann u8 num_bytes; 287da68386dSThomas Zimmermann u8 bytes[255]; 288da68386dSThomas Zimmermann }; 289da68386dSThomas Zimmermann 290da68386dSThomas Zimmermann struct drm_dp_remote_dpcd_write_ack_reply { 291da68386dSThomas Zimmermann u8 port_number; 292da68386dSThomas Zimmermann }; 293da68386dSThomas Zimmermann 294da68386dSThomas Zimmermann struct drm_dp_remote_dpcd_write_nak_reply { 295da68386dSThomas Zimmermann u8 port_number; 296da68386dSThomas Zimmermann u8 reason; 297da68386dSThomas Zimmermann u8 bytes_written_before_failure; 298da68386dSThomas Zimmermann }; 299da68386dSThomas Zimmermann 300da68386dSThomas Zimmermann struct drm_dp_remote_i2c_read_ack_reply { 301da68386dSThomas Zimmermann u8 port_number; 302da68386dSThomas Zimmermann u8 num_bytes; 303da68386dSThomas Zimmermann u8 bytes[255]; 304da68386dSThomas Zimmermann }; 305da68386dSThomas Zimmermann 306da68386dSThomas Zimmermann struct drm_dp_remote_i2c_read_nak_reply { 307da68386dSThomas Zimmermann u8 port_number; 308da68386dSThomas Zimmermann u8 nak_reason; 309da68386dSThomas Zimmermann u8 i2c_nak_transaction; 310da68386dSThomas Zimmermann }; 311da68386dSThomas Zimmermann 312da68386dSThomas Zimmermann struct drm_dp_remote_i2c_write_ack_reply { 313da68386dSThomas Zimmermann u8 port_number; 314da68386dSThomas Zimmermann }; 315da68386dSThomas Zimmermann 316da68386dSThomas Zimmermann struct drm_dp_query_stream_enc_status_ack_reply { 317da68386dSThomas Zimmermann /* Bit[23:16]- Stream Id */ 318da68386dSThomas Zimmermann u8 stream_id; 319da68386dSThomas Zimmermann 320da68386dSThomas Zimmermann /* Bit[15]- Signed */ 321da68386dSThomas Zimmermann bool reply_signed; 322da68386dSThomas Zimmermann 323da68386dSThomas Zimmermann /* Bit[10:8]- Stream Output Sink Type */ 324da68386dSThomas Zimmermann bool unauthorizable_device_present; 325da68386dSThomas Zimmermann bool legacy_device_present; 326da68386dSThomas Zimmermann bool query_capable_device_present; 327da68386dSThomas Zimmermann 328da68386dSThomas Zimmermann /* Bit[12:11]- Stream Output CP Type */ 329da68386dSThomas Zimmermann bool hdcp_1x_device_present; 330da68386dSThomas Zimmermann bool hdcp_2x_device_present; 331da68386dSThomas Zimmermann 332da68386dSThomas Zimmermann /* Bit[4]- Stream Authentication */ 333da68386dSThomas Zimmermann bool auth_completed; 334da68386dSThomas Zimmermann 335da68386dSThomas Zimmermann /* Bit[3]- Stream Encryption */ 336da68386dSThomas Zimmermann bool encryption_enabled; 337da68386dSThomas Zimmermann 338da68386dSThomas Zimmermann /* Bit[2]- Stream Repeater Function Present */ 339da68386dSThomas Zimmermann bool repeater_present; 340da68386dSThomas Zimmermann 341da68386dSThomas Zimmermann /* Bit[1:0]- Stream State */ 342da68386dSThomas Zimmermann u8 state; 343da68386dSThomas Zimmermann }; 344da68386dSThomas Zimmermann 345da68386dSThomas Zimmermann #define DRM_DP_MAX_SDP_STREAMS 16 346da68386dSThomas Zimmermann struct drm_dp_allocate_payload { 347da68386dSThomas Zimmermann u8 port_number; 348da68386dSThomas Zimmermann u8 number_sdp_streams; 349da68386dSThomas Zimmermann u8 vcpi; 350da68386dSThomas Zimmermann u16 pbn; 351da68386dSThomas Zimmermann u8 sdp_stream_sink[DRM_DP_MAX_SDP_STREAMS]; 352da68386dSThomas Zimmermann }; 353da68386dSThomas Zimmermann 354da68386dSThomas Zimmermann struct drm_dp_allocate_payload_ack_reply { 355da68386dSThomas Zimmermann u8 port_number; 356da68386dSThomas Zimmermann u8 vcpi; 357da68386dSThomas Zimmermann u16 allocated_pbn; 358da68386dSThomas Zimmermann }; 359da68386dSThomas Zimmermann 360da68386dSThomas Zimmermann struct drm_dp_connection_status_notify { 361da68386dSThomas Zimmermann u8 guid[16]; 362da68386dSThomas Zimmermann u8 port_number; 363da68386dSThomas Zimmermann bool legacy_device_plug_status; 364da68386dSThomas Zimmermann bool displayport_device_plug_status; 365da68386dSThomas Zimmermann bool message_capability_status; 366da68386dSThomas Zimmermann bool input_port; 367da68386dSThomas Zimmermann u8 peer_device_type; 368da68386dSThomas Zimmermann }; 369da68386dSThomas Zimmermann 370da68386dSThomas Zimmermann struct drm_dp_remote_dpcd_read { 371da68386dSThomas Zimmermann u8 port_number; 372da68386dSThomas Zimmermann u32 dpcd_address; 373da68386dSThomas Zimmermann u8 num_bytes; 374da68386dSThomas Zimmermann }; 375da68386dSThomas Zimmermann 376da68386dSThomas Zimmermann struct drm_dp_remote_dpcd_write { 377da68386dSThomas Zimmermann u8 port_number; 378da68386dSThomas Zimmermann u32 dpcd_address; 379da68386dSThomas Zimmermann u8 num_bytes; 380da68386dSThomas Zimmermann u8 *bytes; 381da68386dSThomas Zimmermann }; 382da68386dSThomas Zimmermann 383da68386dSThomas Zimmermann #define DP_REMOTE_I2C_READ_MAX_TRANSACTIONS 4 384da68386dSThomas Zimmermann struct drm_dp_remote_i2c_read { 385da68386dSThomas Zimmermann u8 num_transactions; 386da68386dSThomas Zimmermann u8 port_number; 387da68386dSThomas Zimmermann struct drm_dp_remote_i2c_read_tx { 388da68386dSThomas Zimmermann u8 i2c_dev_id; 389da68386dSThomas Zimmermann u8 num_bytes; 390da68386dSThomas Zimmermann u8 *bytes; 391da68386dSThomas Zimmermann u8 no_stop_bit; 392da68386dSThomas Zimmermann u8 i2c_transaction_delay; 393da68386dSThomas Zimmermann } transactions[DP_REMOTE_I2C_READ_MAX_TRANSACTIONS]; 394da68386dSThomas Zimmermann u8 read_i2c_device_id; 395da68386dSThomas Zimmermann u8 num_bytes_read; 396da68386dSThomas Zimmermann }; 397da68386dSThomas Zimmermann 398da68386dSThomas Zimmermann struct drm_dp_remote_i2c_write { 399da68386dSThomas Zimmermann u8 port_number; 400da68386dSThomas Zimmermann u8 write_i2c_device_id; 401da68386dSThomas Zimmermann u8 num_bytes; 402da68386dSThomas Zimmermann u8 *bytes; 403da68386dSThomas Zimmermann }; 404da68386dSThomas Zimmermann 405da68386dSThomas Zimmermann struct drm_dp_query_stream_enc_status { 406da68386dSThomas Zimmermann u8 stream_id; 407da68386dSThomas Zimmermann u8 client_id[7]; /* 56-bit nonce */ 408da68386dSThomas Zimmermann u8 stream_event; 409da68386dSThomas Zimmermann bool valid_stream_event; 410da68386dSThomas Zimmermann u8 stream_behavior; 411da68386dSThomas Zimmermann u8 valid_stream_behavior; 412da68386dSThomas Zimmermann }; 413da68386dSThomas Zimmermann 414da68386dSThomas Zimmermann /* this covers ENUM_RESOURCES, POWER_DOWN_PHY, POWER_UP_PHY */ 415da68386dSThomas Zimmermann struct drm_dp_port_number_req { 416da68386dSThomas Zimmermann u8 port_number; 417da68386dSThomas Zimmermann }; 418da68386dSThomas Zimmermann 419da68386dSThomas Zimmermann struct drm_dp_enum_path_resources_ack_reply { 420da68386dSThomas Zimmermann u8 port_number; 421da68386dSThomas Zimmermann bool fec_capable; 422da68386dSThomas Zimmermann u16 full_payload_bw_number; 423da68386dSThomas Zimmermann u16 avail_payload_bw_number; 424da68386dSThomas Zimmermann }; 425da68386dSThomas Zimmermann 426da68386dSThomas Zimmermann /* covers POWER_DOWN_PHY, POWER_UP_PHY */ 427da68386dSThomas Zimmermann struct drm_dp_port_number_rep { 428da68386dSThomas Zimmermann u8 port_number; 429da68386dSThomas Zimmermann }; 430da68386dSThomas Zimmermann 431da68386dSThomas Zimmermann struct drm_dp_query_payload { 432da68386dSThomas Zimmermann u8 port_number; 433da68386dSThomas Zimmermann u8 vcpi; 434da68386dSThomas Zimmermann }; 435da68386dSThomas Zimmermann 436da68386dSThomas Zimmermann struct drm_dp_resource_status_notify { 437da68386dSThomas Zimmermann u8 port_number; 438da68386dSThomas Zimmermann u8 guid[16]; 439da68386dSThomas Zimmermann u16 available_pbn; 440da68386dSThomas Zimmermann }; 441da68386dSThomas Zimmermann 442da68386dSThomas Zimmermann struct drm_dp_query_payload_ack_reply { 443da68386dSThomas Zimmermann u8 port_number; 444da68386dSThomas Zimmermann u16 allocated_pbn; 445da68386dSThomas Zimmermann }; 446da68386dSThomas Zimmermann 447da68386dSThomas Zimmermann struct drm_dp_sideband_msg_req_body { 448da68386dSThomas Zimmermann u8 req_type; 449da68386dSThomas Zimmermann union ack_req { 450da68386dSThomas Zimmermann struct drm_dp_connection_status_notify conn_stat; 451da68386dSThomas Zimmermann struct drm_dp_port_number_req port_num; 452da68386dSThomas Zimmermann struct drm_dp_resource_status_notify resource_stat; 453da68386dSThomas Zimmermann 454da68386dSThomas Zimmermann struct drm_dp_query_payload query_payload; 455da68386dSThomas Zimmermann struct drm_dp_allocate_payload allocate_payload; 456da68386dSThomas Zimmermann 457da68386dSThomas Zimmermann struct drm_dp_remote_dpcd_read dpcd_read; 458da68386dSThomas Zimmermann struct drm_dp_remote_dpcd_write dpcd_write; 459da68386dSThomas Zimmermann 460da68386dSThomas Zimmermann struct drm_dp_remote_i2c_read i2c_read; 461da68386dSThomas Zimmermann struct drm_dp_remote_i2c_write i2c_write; 462da68386dSThomas Zimmermann 463da68386dSThomas Zimmermann struct drm_dp_query_stream_enc_status enc_status; 464da68386dSThomas Zimmermann } u; 465da68386dSThomas Zimmermann }; 466da68386dSThomas Zimmermann 467da68386dSThomas Zimmermann struct drm_dp_sideband_msg_reply_body { 468da68386dSThomas Zimmermann u8 reply_type; 469da68386dSThomas Zimmermann u8 req_type; 470da68386dSThomas Zimmermann union ack_replies { 471da68386dSThomas Zimmermann struct drm_dp_nak_reply nak; 472da68386dSThomas Zimmermann struct drm_dp_link_address_ack_reply link_addr; 473da68386dSThomas Zimmermann struct drm_dp_port_number_rep port_number; 474da68386dSThomas Zimmermann 475da68386dSThomas Zimmermann struct drm_dp_enum_path_resources_ack_reply path_resources; 476da68386dSThomas Zimmermann struct drm_dp_allocate_payload_ack_reply allocate_payload; 477da68386dSThomas Zimmermann struct drm_dp_query_payload_ack_reply query_payload; 478da68386dSThomas Zimmermann 479da68386dSThomas Zimmermann struct drm_dp_remote_dpcd_read_ack_reply remote_dpcd_read_ack; 480da68386dSThomas Zimmermann struct drm_dp_remote_dpcd_write_ack_reply remote_dpcd_write_ack; 481da68386dSThomas Zimmermann struct drm_dp_remote_dpcd_write_nak_reply remote_dpcd_write_nack; 482da68386dSThomas Zimmermann 483da68386dSThomas Zimmermann struct drm_dp_remote_i2c_read_ack_reply remote_i2c_read_ack; 484da68386dSThomas Zimmermann struct drm_dp_remote_i2c_read_nak_reply remote_i2c_read_nack; 485da68386dSThomas Zimmermann struct drm_dp_remote_i2c_write_ack_reply remote_i2c_write_ack; 486da68386dSThomas Zimmermann 487da68386dSThomas Zimmermann struct drm_dp_query_stream_enc_status_ack_reply enc_status; 488da68386dSThomas Zimmermann } u; 489da68386dSThomas Zimmermann }; 490da68386dSThomas Zimmermann 491da68386dSThomas Zimmermann /* msg is queued to be put into a slot */ 492da68386dSThomas Zimmermann #define DRM_DP_SIDEBAND_TX_QUEUED 0 493da68386dSThomas Zimmermann /* msg has started transmitting on a slot - still on msgq */ 494da68386dSThomas Zimmermann #define DRM_DP_SIDEBAND_TX_START_SEND 1 495da68386dSThomas Zimmermann /* msg has finished transmitting on a slot - removed from msgq only in slot */ 496da68386dSThomas Zimmermann #define DRM_DP_SIDEBAND_TX_SENT 2 497da68386dSThomas Zimmermann /* msg has received a response - removed from slot */ 498da68386dSThomas Zimmermann #define DRM_DP_SIDEBAND_TX_RX 3 499da68386dSThomas Zimmermann #define DRM_DP_SIDEBAND_TX_TIMEOUT 4 500da68386dSThomas Zimmermann 501da68386dSThomas Zimmermann struct drm_dp_sideband_msg_tx { 502da68386dSThomas Zimmermann u8 msg[256]; 503da68386dSThomas Zimmermann u8 chunk[48]; 504da68386dSThomas Zimmermann u8 cur_offset; 505da68386dSThomas Zimmermann u8 cur_len; 506da68386dSThomas Zimmermann struct drm_dp_mst_branch *dst; 507da68386dSThomas Zimmermann struct list_head next; 508da68386dSThomas Zimmermann int seqno; 509da68386dSThomas Zimmermann int state; 510da68386dSThomas Zimmermann bool path_msg; 511da68386dSThomas Zimmermann struct drm_dp_sideband_msg_reply_body reply; 512da68386dSThomas Zimmermann }; 513da68386dSThomas Zimmermann 514da68386dSThomas Zimmermann /* sideband msg handler */ 515da68386dSThomas Zimmermann struct drm_dp_mst_topology_mgr; 516da68386dSThomas Zimmermann struct drm_dp_mst_topology_cbs { 517da68386dSThomas Zimmermann /* create a connector for a port */ 518da68386dSThomas Zimmermann struct drm_connector *(*add_connector)(struct drm_dp_mst_topology_mgr *mgr, struct drm_dp_mst_port *port, const char *path); 519da68386dSThomas Zimmermann /* 520da68386dSThomas Zimmermann * Checks for any pending MST interrupts, passing them to MST core for 521da68386dSThomas Zimmermann * processing, the same way an HPD IRQ pulse handler would do this. 522da68386dSThomas Zimmermann * If provided MST core calls this callback from a poll-waiting loop 523da68386dSThomas Zimmermann * when waiting for MST down message replies. The driver is expected 524da68386dSThomas Zimmermann * to guard against a race between this callback and the driver's HPD 525da68386dSThomas Zimmermann * IRQ pulse handler. 526da68386dSThomas Zimmermann */ 527da68386dSThomas Zimmermann void (*poll_hpd_irq)(struct drm_dp_mst_topology_mgr *mgr); 528da68386dSThomas Zimmermann }; 529da68386dSThomas Zimmermann 530da68386dSThomas Zimmermann #define DP_MAX_PAYLOAD (sizeof(unsigned long) * 8) 531da68386dSThomas Zimmermann 532da68386dSThomas Zimmermann #define DP_PAYLOAD_LOCAL 1 533da68386dSThomas Zimmermann #define DP_PAYLOAD_REMOTE 2 534da68386dSThomas Zimmermann #define DP_PAYLOAD_DELETE_LOCAL 3 535da68386dSThomas Zimmermann 536da68386dSThomas Zimmermann struct drm_dp_payload { 537da68386dSThomas Zimmermann int payload_state; 538da68386dSThomas Zimmermann int start_slot; 539da68386dSThomas Zimmermann int num_slots; 540da68386dSThomas Zimmermann int vcpi; 541da68386dSThomas Zimmermann }; 542da68386dSThomas Zimmermann 543da68386dSThomas Zimmermann #define to_dp_mst_topology_state(x) container_of(x, struct drm_dp_mst_topology_state, base) 544da68386dSThomas Zimmermann 545*0bee2ae2SLyude Paul /** 546*0bee2ae2SLyude Paul * struct drm_dp_mst_atomic_payload - Atomic state struct for an MST payload 547*0bee2ae2SLyude Paul * 548*0bee2ae2SLyude Paul * The primary atomic state structure for a given MST payload. Stores information like current 549*0bee2ae2SLyude Paul * bandwidth allocation, intended action for this payload, etc. 550*0bee2ae2SLyude Paul */ 55148b6b372SLyude Paul struct drm_dp_mst_atomic_payload { 552*0bee2ae2SLyude Paul /** @port: The MST port assigned to this payload */ 553da68386dSThomas Zimmermann struct drm_dp_mst_port *port; 554df78f7f6SLyude Paul 555df78f7f6SLyude Paul /** 556df78f7f6SLyude Paul * @time_slots: 557df78f7f6SLyude Paul * The number of timeslots allocated to this payload from the source DP Tx to 558df78f7f6SLyude Paul * the immediate downstream DP Rx 559df78f7f6SLyude Paul */ 560df78f7f6SLyude Paul int time_slots; 561*0bee2ae2SLyude Paul /** @pbn: The payload bandwidth for this payload */ 562da68386dSThomas Zimmermann int pbn; 563*0bee2ae2SLyude Paul /** @dsc_enabled: Whether or not this payload has DSC enabled */ 564da68386dSThomas Zimmermann bool dsc_enabled; 565*0bee2ae2SLyude Paul 566*0bee2ae2SLyude Paul /** @next: The list node for this payload */ 567da68386dSThomas Zimmermann struct list_head next; 568da68386dSThomas Zimmermann }; 569da68386dSThomas Zimmermann 570*0bee2ae2SLyude Paul /** 571*0bee2ae2SLyude Paul * struct drm_dp_mst_topology_state - DisplayPort MST topology atomic state 572*0bee2ae2SLyude Paul * 573*0bee2ae2SLyude Paul * This struct represents the atomic state of the toplevel DisplayPort MST manager 574*0bee2ae2SLyude Paul */ 575da68386dSThomas Zimmermann struct drm_dp_mst_topology_state { 576*0bee2ae2SLyude Paul /** @base: Base private state for atomic */ 577da68386dSThomas Zimmermann struct drm_private_state base; 578*0bee2ae2SLyude Paul 579*0bee2ae2SLyude Paul /** @payloads: The list of payloads being created/destroyed in this state */ 58048b6b372SLyude Paul struct list_head payloads; 581*0bee2ae2SLyude Paul /** @mgr: The topology manager */ 582da68386dSThomas Zimmermann struct drm_dp_mst_topology_mgr *mgr; 583*0bee2ae2SLyude Paul 584*0bee2ae2SLyude Paul /** @total_avail_slots: The total number of slots this topology can handle (63 or 64) */ 585da68386dSThomas Zimmermann u8 total_avail_slots; 586*0bee2ae2SLyude Paul /** @start_slot: The first usable time slot in this topology (1 or 0) */ 587da68386dSThomas Zimmermann u8 start_slot; 588da68386dSThomas Zimmermann }; 589da68386dSThomas Zimmermann 590da68386dSThomas Zimmermann #define to_dp_mst_topology_mgr(x) container_of(x, struct drm_dp_mst_topology_mgr, base) 591da68386dSThomas Zimmermann 592da68386dSThomas Zimmermann /** 593da68386dSThomas Zimmermann * struct drm_dp_mst_topology_mgr - DisplayPort MST manager 594da68386dSThomas Zimmermann * 595da68386dSThomas Zimmermann * This struct represents the toplevel displayport MST topology manager. 596da68386dSThomas Zimmermann * There should be one instance of this for every MST capable DP connector 597da68386dSThomas Zimmermann * on the GPU. 598da68386dSThomas Zimmermann */ 599da68386dSThomas Zimmermann struct drm_dp_mst_topology_mgr { 600da68386dSThomas Zimmermann /** 601da68386dSThomas Zimmermann * @base: Base private object for atomic 602da68386dSThomas Zimmermann */ 603da68386dSThomas Zimmermann struct drm_private_obj base; 604da68386dSThomas Zimmermann 605da68386dSThomas Zimmermann /** 606da68386dSThomas Zimmermann * @dev: device pointer for adding i2c devices etc. 607da68386dSThomas Zimmermann */ 608da68386dSThomas Zimmermann struct drm_device *dev; 609da68386dSThomas Zimmermann /** 610da68386dSThomas Zimmermann * @cbs: callbacks for connector addition and destruction. 611da68386dSThomas Zimmermann */ 612da68386dSThomas Zimmermann const struct drm_dp_mst_topology_cbs *cbs; 613da68386dSThomas Zimmermann /** 614da68386dSThomas Zimmermann * @max_dpcd_transaction_bytes: maximum number of bytes to read/write 615da68386dSThomas Zimmermann * in one go. 616da68386dSThomas Zimmermann */ 617da68386dSThomas Zimmermann int max_dpcd_transaction_bytes; 618da68386dSThomas Zimmermann /** 619da68386dSThomas Zimmermann * @aux: AUX channel for the DP MST connector this topolgy mgr is 620da68386dSThomas Zimmermann * controlling. 621da68386dSThomas Zimmermann */ 622da68386dSThomas Zimmermann struct drm_dp_aux *aux; 623da68386dSThomas Zimmermann /** 624da68386dSThomas Zimmermann * @max_payloads: maximum number of payloads the GPU can generate. 625da68386dSThomas Zimmermann */ 626da68386dSThomas Zimmermann int max_payloads; 627da68386dSThomas Zimmermann /** 628da68386dSThomas Zimmermann * @max_lane_count: maximum number of lanes the GPU can drive. 629da68386dSThomas Zimmermann */ 630da68386dSThomas Zimmermann int max_lane_count; 631da68386dSThomas Zimmermann /** 632da68386dSThomas Zimmermann * @max_link_rate: maximum link rate per lane GPU can output, in kHz. 633da68386dSThomas Zimmermann */ 634da68386dSThomas Zimmermann int max_link_rate; 635da68386dSThomas Zimmermann /** 636da68386dSThomas Zimmermann * @conn_base_id: DRM connector ID this mgr is connected to. Only used 637da68386dSThomas Zimmermann * to build the MST connector path value. 638da68386dSThomas Zimmermann */ 639da68386dSThomas Zimmermann int conn_base_id; 640da68386dSThomas Zimmermann 641da68386dSThomas Zimmermann /** 642da68386dSThomas Zimmermann * @up_req_recv: Message receiver state for up requests. 643da68386dSThomas Zimmermann */ 644da68386dSThomas Zimmermann struct drm_dp_sideband_msg_rx up_req_recv; 645da68386dSThomas Zimmermann 646da68386dSThomas Zimmermann /** 647da68386dSThomas Zimmermann * @down_rep_recv: Message receiver state for replies to down 648da68386dSThomas Zimmermann * requests. 649da68386dSThomas Zimmermann */ 650da68386dSThomas Zimmermann struct drm_dp_sideband_msg_rx down_rep_recv; 651da68386dSThomas Zimmermann 652da68386dSThomas Zimmermann /** 653da68386dSThomas Zimmermann * @lock: protects @mst_state, @mst_primary, @dpcd, and 654da68386dSThomas Zimmermann * @payload_id_table_cleared. 655da68386dSThomas Zimmermann */ 656da68386dSThomas Zimmermann struct mutex lock; 657da68386dSThomas Zimmermann 658da68386dSThomas Zimmermann /** 659da68386dSThomas Zimmermann * @probe_lock: Prevents @work and @up_req_work, the only writers of 660da68386dSThomas Zimmermann * &drm_dp_mst_port.mstb and &drm_dp_mst_branch.ports, from racing 661da68386dSThomas Zimmermann * while they update the topology. 662da68386dSThomas Zimmermann */ 663da68386dSThomas Zimmermann struct mutex probe_lock; 664da68386dSThomas Zimmermann 665da68386dSThomas Zimmermann /** 666da68386dSThomas Zimmermann * @mst_state: If this manager is enabled for an MST capable port. False 667da68386dSThomas Zimmermann * if no MST sink/branch devices is connected. 668da68386dSThomas Zimmermann */ 669da68386dSThomas Zimmermann bool mst_state : 1; 670da68386dSThomas Zimmermann 671da68386dSThomas Zimmermann /** 672da68386dSThomas Zimmermann * @payload_id_table_cleared: Whether or not we've cleared the payload 673da68386dSThomas Zimmermann * ID table for @mst_primary. Protected by @lock. 674da68386dSThomas Zimmermann */ 675da68386dSThomas Zimmermann bool payload_id_table_cleared : 1; 676da68386dSThomas Zimmermann 677da68386dSThomas Zimmermann /** 678da68386dSThomas Zimmermann * @mst_primary: Pointer to the primary/first branch device. 679da68386dSThomas Zimmermann */ 680da68386dSThomas Zimmermann struct drm_dp_mst_branch *mst_primary; 681da68386dSThomas Zimmermann 682da68386dSThomas Zimmermann /** 683da68386dSThomas Zimmermann * @dpcd: Cache of DPCD for primary port. 684da68386dSThomas Zimmermann */ 685da68386dSThomas Zimmermann u8 dpcd[DP_RECEIVER_CAP_SIZE]; 686da68386dSThomas Zimmermann /** 687da68386dSThomas Zimmermann * @sink_count: Sink count from DEVICE_SERVICE_IRQ_VECTOR_ESI0. 688da68386dSThomas Zimmermann */ 689da68386dSThomas Zimmermann u8 sink_count; 690da68386dSThomas Zimmermann /** 691da68386dSThomas Zimmermann * @pbn_div: PBN to slots divisor. 692da68386dSThomas Zimmermann */ 693da68386dSThomas Zimmermann int pbn_div; 694da68386dSThomas Zimmermann 695da68386dSThomas Zimmermann /** 696da68386dSThomas Zimmermann * @funcs: Atomic helper callbacks 697da68386dSThomas Zimmermann */ 698da68386dSThomas Zimmermann const struct drm_private_state_funcs *funcs; 699da68386dSThomas Zimmermann 700da68386dSThomas Zimmermann /** 701da68386dSThomas Zimmermann * @qlock: protects @tx_msg_downq and &drm_dp_sideband_msg_tx.state 702da68386dSThomas Zimmermann */ 703da68386dSThomas Zimmermann struct mutex qlock; 704da68386dSThomas Zimmermann 705da68386dSThomas Zimmermann /** 706da68386dSThomas Zimmermann * @tx_msg_downq: List of pending down requests 707da68386dSThomas Zimmermann */ 708da68386dSThomas Zimmermann struct list_head tx_msg_downq; 709da68386dSThomas Zimmermann 710da68386dSThomas Zimmermann /** 711da68386dSThomas Zimmermann * @payload_lock: Protect payload information. 712da68386dSThomas Zimmermann */ 713da68386dSThomas Zimmermann struct mutex payload_lock; 714da68386dSThomas Zimmermann /** 715da68386dSThomas Zimmermann * @proposed_vcpis: Array of pointers for the new VCPI allocation. The 716da68386dSThomas Zimmermann * VCPI structure itself is &drm_dp_mst_port.vcpi, and the size of 717da68386dSThomas Zimmermann * this array is determined by @max_payloads. 718da68386dSThomas Zimmermann */ 719da68386dSThomas Zimmermann struct drm_dp_vcpi **proposed_vcpis; 720da68386dSThomas Zimmermann /** 721da68386dSThomas Zimmermann * @payloads: Array of payloads. The size of this array is determined 722da68386dSThomas Zimmermann * by @max_payloads. 723da68386dSThomas Zimmermann */ 724da68386dSThomas Zimmermann struct drm_dp_payload *payloads; 725da68386dSThomas Zimmermann /** 726da68386dSThomas Zimmermann * @payload_mask: Elements of @payloads actually in use. Since 727da68386dSThomas Zimmermann * reallocation of active outputs isn't possible gaps can be created by 728da68386dSThomas Zimmermann * disabling outputs out of order compared to how they've been enabled. 729da68386dSThomas Zimmermann */ 730da68386dSThomas Zimmermann unsigned long payload_mask; 731da68386dSThomas Zimmermann /** 732da68386dSThomas Zimmermann * @vcpi_mask: Similar to @payload_mask, but for @proposed_vcpis. 733da68386dSThomas Zimmermann */ 734da68386dSThomas Zimmermann unsigned long vcpi_mask; 735da68386dSThomas Zimmermann 736da68386dSThomas Zimmermann /** 737da68386dSThomas Zimmermann * @tx_waitq: Wait to queue stall for the tx worker. 738da68386dSThomas Zimmermann */ 739da68386dSThomas Zimmermann wait_queue_head_t tx_waitq; 740da68386dSThomas Zimmermann /** 741da68386dSThomas Zimmermann * @work: Probe work. 742da68386dSThomas Zimmermann */ 743da68386dSThomas Zimmermann struct work_struct work; 744da68386dSThomas Zimmermann /** 745da68386dSThomas Zimmermann * @tx_work: Sideband transmit worker. This can nest within the main 746da68386dSThomas Zimmermann * @work worker for each transaction @work launches. 747da68386dSThomas Zimmermann */ 748da68386dSThomas Zimmermann struct work_struct tx_work; 749da68386dSThomas Zimmermann 750da68386dSThomas Zimmermann /** 751da68386dSThomas Zimmermann * @destroy_port_list: List of to be destroyed connectors. 752da68386dSThomas Zimmermann */ 753da68386dSThomas Zimmermann struct list_head destroy_port_list; 754da68386dSThomas Zimmermann /** 755da68386dSThomas Zimmermann * @destroy_branch_device_list: List of to be destroyed branch 756da68386dSThomas Zimmermann * devices. 757da68386dSThomas Zimmermann */ 758da68386dSThomas Zimmermann struct list_head destroy_branch_device_list; 759da68386dSThomas Zimmermann /** 760da68386dSThomas Zimmermann * @delayed_destroy_lock: Protects @destroy_port_list and 761da68386dSThomas Zimmermann * @destroy_branch_device_list. 762da68386dSThomas Zimmermann */ 763da68386dSThomas Zimmermann struct mutex delayed_destroy_lock; 764da68386dSThomas Zimmermann 765da68386dSThomas Zimmermann /** 766da68386dSThomas Zimmermann * @delayed_destroy_wq: Workqueue used for delayed_destroy_work items. 767da68386dSThomas Zimmermann * A dedicated WQ makes it possible to drain any requeued work items 768da68386dSThomas Zimmermann * on it. 769da68386dSThomas Zimmermann */ 770da68386dSThomas Zimmermann struct workqueue_struct *delayed_destroy_wq; 771da68386dSThomas Zimmermann 772da68386dSThomas Zimmermann /** 773da68386dSThomas Zimmermann * @delayed_destroy_work: Work item to destroy MST port and branch 774da68386dSThomas Zimmermann * devices, needed to avoid locking inversion. 775da68386dSThomas Zimmermann */ 776da68386dSThomas Zimmermann struct work_struct delayed_destroy_work; 777da68386dSThomas Zimmermann 778da68386dSThomas Zimmermann /** 779da68386dSThomas Zimmermann * @up_req_list: List of pending up requests from the topology that 780da68386dSThomas Zimmermann * need to be processed, in chronological order. 781da68386dSThomas Zimmermann */ 782da68386dSThomas Zimmermann struct list_head up_req_list; 783da68386dSThomas Zimmermann /** 784da68386dSThomas Zimmermann * @up_req_lock: Protects @up_req_list 785da68386dSThomas Zimmermann */ 786da68386dSThomas Zimmermann struct mutex up_req_lock; 787da68386dSThomas Zimmermann /** 788da68386dSThomas Zimmermann * @up_req_work: Work item to process up requests received from the 789da68386dSThomas Zimmermann * topology. Needed to avoid blocking hotplug handling and sideband 790da68386dSThomas Zimmermann * transmissions. 791da68386dSThomas Zimmermann */ 792da68386dSThomas Zimmermann struct work_struct up_req_work; 793da68386dSThomas Zimmermann 794da68386dSThomas Zimmermann #if IS_ENABLED(CONFIG_DRM_DEBUG_DP_MST_TOPOLOGY_REFS) 795da68386dSThomas Zimmermann /** 796da68386dSThomas Zimmermann * @topology_ref_history_lock: protects 797da68386dSThomas Zimmermann * &drm_dp_mst_port.topology_ref_history and 798da68386dSThomas Zimmermann * &drm_dp_mst_branch.topology_ref_history. 799da68386dSThomas Zimmermann */ 800da68386dSThomas Zimmermann struct mutex topology_ref_history_lock; 801da68386dSThomas Zimmermann #endif 802da68386dSThomas Zimmermann }; 803da68386dSThomas Zimmermann 804da68386dSThomas Zimmermann int drm_dp_mst_topology_mgr_init(struct drm_dp_mst_topology_mgr *mgr, 805da68386dSThomas Zimmermann struct drm_device *dev, struct drm_dp_aux *aux, 806da68386dSThomas Zimmermann int max_dpcd_transaction_bytes, 807da68386dSThomas Zimmermann int max_payloads, 808da68386dSThomas Zimmermann int max_lane_count, int max_link_rate, 809da68386dSThomas Zimmermann int conn_base_id); 810da68386dSThomas Zimmermann 811da68386dSThomas Zimmermann void drm_dp_mst_topology_mgr_destroy(struct drm_dp_mst_topology_mgr *mgr); 812da68386dSThomas Zimmermann 813da68386dSThomas Zimmermann bool drm_dp_read_mst_cap(struct drm_dp_aux *aux, const u8 dpcd[DP_RECEIVER_CAP_SIZE]); 814da68386dSThomas Zimmermann int drm_dp_mst_topology_mgr_set_mst(struct drm_dp_mst_topology_mgr *mgr, bool mst_state); 815da68386dSThomas Zimmermann 816da68386dSThomas Zimmermann int drm_dp_mst_hpd_irq(struct drm_dp_mst_topology_mgr *mgr, u8 *esi, bool *handled); 817da68386dSThomas Zimmermann 818da68386dSThomas Zimmermann 819da68386dSThomas Zimmermann int 820da68386dSThomas Zimmermann drm_dp_mst_detect_port(struct drm_connector *connector, 821da68386dSThomas Zimmermann struct drm_modeset_acquire_ctx *ctx, 822da68386dSThomas Zimmermann struct drm_dp_mst_topology_mgr *mgr, 823da68386dSThomas Zimmermann struct drm_dp_mst_port *port); 824da68386dSThomas Zimmermann 825da68386dSThomas Zimmermann struct edid *drm_dp_mst_get_edid(struct drm_connector *connector, struct drm_dp_mst_topology_mgr *mgr, struct drm_dp_mst_port *port); 826da68386dSThomas Zimmermann 827da68386dSThomas Zimmermann int drm_dp_get_vc_payload_bw(const struct drm_dp_mst_topology_mgr *mgr, 828da68386dSThomas Zimmermann int link_rate, int link_lane_count); 829da68386dSThomas Zimmermann 830da68386dSThomas Zimmermann int drm_dp_calc_pbn_mode(int clock, int bpp, bool dsc); 831da68386dSThomas Zimmermann 832da68386dSThomas Zimmermann bool drm_dp_mst_allocate_vcpi(struct drm_dp_mst_topology_mgr *mgr, 833da68386dSThomas Zimmermann struct drm_dp_mst_port *port, int pbn, int slots); 834da68386dSThomas Zimmermann 835da68386dSThomas Zimmermann int drm_dp_mst_get_vcpi_slots(struct drm_dp_mst_topology_mgr *mgr, struct drm_dp_mst_port *port); 836da68386dSThomas Zimmermann 837da68386dSThomas Zimmermann 838da68386dSThomas Zimmermann void drm_dp_mst_reset_vcpi_slots(struct drm_dp_mst_topology_mgr *mgr, struct drm_dp_mst_port *port); 839da68386dSThomas Zimmermann 840da68386dSThomas Zimmermann void drm_dp_mst_update_slots(struct drm_dp_mst_topology_state *mst_state, uint8_t link_encoding_cap); 841da68386dSThomas Zimmermann 842da68386dSThomas Zimmermann void drm_dp_mst_deallocate_vcpi(struct drm_dp_mst_topology_mgr *mgr, 843da68386dSThomas Zimmermann struct drm_dp_mst_port *port); 844da68386dSThomas Zimmermann 845da68386dSThomas Zimmermann 846da68386dSThomas Zimmermann int drm_dp_find_vcpi_slots(struct drm_dp_mst_topology_mgr *mgr, 847da68386dSThomas Zimmermann int pbn); 848da68386dSThomas Zimmermann 849da68386dSThomas Zimmermann 850da68386dSThomas Zimmermann int drm_dp_update_payload_part1(struct drm_dp_mst_topology_mgr *mgr, int start_slot); 851da68386dSThomas Zimmermann 852da68386dSThomas Zimmermann 853da68386dSThomas Zimmermann int drm_dp_update_payload_part2(struct drm_dp_mst_topology_mgr *mgr); 854da68386dSThomas Zimmermann 855da68386dSThomas Zimmermann int drm_dp_check_act_status(struct drm_dp_mst_topology_mgr *mgr); 856da68386dSThomas Zimmermann 857da68386dSThomas Zimmermann void drm_dp_mst_dump_topology(struct seq_file *m, 858da68386dSThomas Zimmermann struct drm_dp_mst_topology_mgr *mgr); 859da68386dSThomas Zimmermann 860da68386dSThomas Zimmermann void drm_dp_mst_topology_mgr_suspend(struct drm_dp_mst_topology_mgr *mgr); 861da68386dSThomas Zimmermann int __must_check 862da68386dSThomas Zimmermann drm_dp_mst_topology_mgr_resume(struct drm_dp_mst_topology_mgr *mgr, 863da68386dSThomas Zimmermann bool sync); 864da68386dSThomas Zimmermann 865da68386dSThomas Zimmermann ssize_t drm_dp_mst_dpcd_read(struct drm_dp_aux *aux, 866da68386dSThomas Zimmermann unsigned int offset, void *buffer, size_t size); 867da68386dSThomas Zimmermann ssize_t drm_dp_mst_dpcd_write(struct drm_dp_aux *aux, 868da68386dSThomas Zimmermann unsigned int offset, void *buffer, size_t size); 869da68386dSThomas Zimmermann 870da68386dSThomas Zimmermann int drm_dp_mst_connector_late_register(struct drm_connector *connector, 871da68386dSThomas Zimmermann struct drm_dp_mst_port *port); 872da68386dSThomas Zimmermann void drm_dp_mst_connector_early_unregister(struct drm_connector *connector, 873da68386dSThomas Zimmermann struct drm_dp_mst_port *port); 874da68386dSThomas Zimmermann 875da68386dSThomas Zimmermann struct drm_dp_mst_topology_state *drm_atomic_get_mst_topology_state(struct drm_atomic_state *state, 876da68386dSThomas Zimmermann struct drm_dp_mst_topology_mgr *mgr); 877da68386dSThomas Zimmermann int __must_check 878df78f7f6SLyude Paul drm_dp_atomic_find_time_slots(struct drm_atomic_state *state, 879da68386dSThomas Zimmermann struct drm_dp_mst_topology_mgr *mgr, 880da68386dSThomas Zimmermann struct drm_dp_mst_port *port, int pbn, 881da68386dSThomas Zimmermann int pbn_div); 882da68386dSThomas Zimmermann int drm_dp_mst_atomic_enable_dsc(struct drm_atomic_state *state, 883da68386dSThomas Zimmermann struct drm_dp_mst_port *port, 884da68386dSThomas Zimmermann int pbn, int pbn_div, 885da68386dSThomas Zimmermann bool enable); 886da68386dSThomas Zimmermann int __must_check 887da68386dSThomas Zimmermann drm_dp_mst_add_affected_dsc_crtcs(struct drm_atomic_state *state, 888da68386dSThomas Zimmermann struct drm_dp_mst_topology_mgr *mgr); 889da68386dSThomas Zimmermann int __must_check 890df78f7f6SLyude Paul drm_dp_atomic_release_time_slots(struct drm_atomic_state *state, 891da68386dSThomas Zimmermann struct drm_dp_mst_topology_mgr *mgr, 892da68386dSThomas Zimmermann struct drm_dp_mst_port *port); 893da68386dSThomas Zimmermann int drm_dp_send_power_updown_phy(struct drm_dp_mst_topology_mgr *mgr, 894da68386dSThomas Zimmermann struct drm_dp_mst_port *port, bool power_up); 895da68386dSThomas Zimmermann int drm_dp_send_query_stream_enc_status(struct drm_dp_mst_topology_mgr *mgr, 896da68386dSThomas Zimmermann struct drm_dp_mst_port *port, 897da68386dSThomas Zimmermann struct drm_dp_query_stream_enc_status_ack_reply *status); 898da68386dSThomas Zimmermann int __must_check drm_dp_mst_atomic_check(struct drm_atomic_state *state); 899da68386dSThomas Zimmermann 900da68386dSThomas Zimmermann void drm_dp_mst_get_port_malloc(struct drm_dp_mst_port *port); 901da68386dSThomas Zimmermann void drm_dp_mst_put_port_malloc(struct drm_dp_mst_port *port); 902da68386dSThomas Zimmermann 903da68386dSThomas Zimmermann struct drm_dp_aux *drm_dp_mst_dsc_aux_for_port(struct drm_dp_mst_port *port); 904da68386dSThomas Zimmermann 905da68386dSThomas Zimmermann extern const struct drm_private_state_funcs drm_dp_mst_topology_state_funcs; 906da68386dSThomas Zimmermann 907da68386dSThomas Zimmermann /** 908da68386dSThomas Zimmermann * __drm_dp_mst_state_iter_get - private atomic state iterator function for 909da68386dSThomas Zimmermann * macro-internal use 910da68386dSThomas Zimmermann * @state: &struct drm_atomic_state pointer 911da68386dSThomas Zimmermann * @mgr: pointer to the &struct drm_dp_mst_topology_mgr iteration cursor 912da68386dSThomas Zimmermann * @old_state: optional pointer to the old &struct drm_dp_mst_topology_state 913da68386dSThomas Zimmermann * iteration cursor 914da68386dSThomas Zimmermann * @new_state: optional pointer to the new &struct drm_dp_mst_topology_state 915da68386dSThomas Zimmermann * iteration cursor 916da68386dSThomas Zimmermann * @i: int iteration cursor, for macro-internal use 917da68386dSThomas Zimmermann * 918da68386dSThomas Zimmermann * Used by for_each_oldnew_mst_mgr_in_state(), 919da68386dSThomas Zimmermann * for_each_old_mst_mgr_in_state(), and for_each_new_mst_mgr_in_state(). Don't 920da68386dSThomas Zimmermann * call this directly. 921da68386dSThomas Zimmermann * 922da68386dSThomas Zimmermann * Returns: 923da68386dSThomas Zimmermann * True if the current &struct drm_private_obj is a &struct 924da68386dSThomas Zimmermann * drm_dp_mst_topology_mgr, false otherwise. 925da68386dSThomas Zimmermann */ 926da68386dSThomas Zimmermann static inline bool 927da68386dSThomas Zimmermann __drm_dp_mst_state_iter_get(struct drm_atomic_state *state, 928da68386dSThomas Zimmermann struct drm_dp_mst_topology_mgr **mgr, 929da68386dSThomas Zimmermann struct drm_dp_mst_topology_state **old_state, 930da68386dSThomas Zimmermann struct drm_dp_mst_topology_state **new_state, 931da68386dSThomas Zimmermann int i) 932da68386dSThomas Zimmermann { 933da68386dSThomas Zimmermann struct __drm_private_objs_state *objs_state = &state->private_objs[i]; 934da68386dSThomas Zimmermann 935da68386dSThomas Zimmermann if (objs_state->ptr->funcs != &drm_dp_mst_topology_state_funcs) 936da68386dSThomas Zimmermann return false; 937da68386dSThomas Zimmermann 938da68386dSThomas Zimmermann *mgr = to_dp_mst_topology_mgr(objs_state->ptr); 939da68386dSThomas Zimmermann if (old_state) 940da68386dSThomas Zimmermann *old_state = to_dp_mst_topology_state(objs_state->old_state); 941da68386dSThomas Zimmermann if (new_state) 942da68386dSThomas Zimmermann *new_state = to_dp_mst_topology_state(objs_state->new_state); 943da68386dSThomas Zimmermann 944da68386dSThomas Zimmermann return true; 945da68386dSThomas Zimmermann } 946da68386dSThomas Zimmermann 947da68386dSThomas Zimmermann /** 948da68386dSThomas Zimmermann * for_each_oldnew_mst_mgr_in_state - iterate over all DP MST topology 949da68386dSThomas Zimmermann * managers in an atomic update 950da68386dSThomas Zimmermann * @__state: &struct drm_atomic_state pointer 951da68386dSThomas Zimmermann * @mgr: &struct drm_dp_mst_topology_mgr iteration cursor 952da68386dSThomas Zimmermann * @old_state: &struct drm_dp_mst_topology_state iteration cursor for the old 953da68386dSThomas Zimmermann * state 954da68386dSThomas Zimmermann * @new_state: &struct drm_dp_mst_topology_state iteration cursor for the new 955da68386dSThomas Zimmermann * state 956da68386dSThomas Zimmermann * @__i: int iteration cursor, for macro-internal use 957da68386dSThomas Zimmermann * 958da68386dSThomas Zimmermann * This iterates over all DRM DP MST topology managers in an atomic update, 959da68386dSThomas Zimmermann * tracking both old and new state. This is useful in places where the state 960da68386dSThomas Zimmermann * delta needs to be considered, for example in atomic check functions. 961da68386dSThomas Zimmermann */ 962da68386dSThomas Zimmermann #define for_each_oldnew_mst_mgr_in_state(__state, mgr, old_state, new_state, __i) \ 963da68386dSThomas Zimmermann for ((__i) = 0; (__i) < (__state)->num_private_objs; (__i)++) \ 964da68386dSThomas Zimmermann for_each_if(__drm_dp_mst_state_iter_get((__state), &(mgr), &(old_state), &(new_state), (__i))) 965da68386dSThomas Zimmermann 966da68386dSThomas Zimmermann /** 967da68386dSThomas Zimmermann * for_each_old_mst_mgr_in_state - iterate over all DP MST topology managers 968da68386dSThomas Zimmermann * in an atomic update 969da68386dSThomas Zimmermann * @__state: &struct drm_atomic_state pointer 970da68386dSThomas Zimmermann * @mgr: &struct drm_dp_mst_topology_mgr iteration cursor 971da68386dSThomas Zimmermann * @old_state: &struct drm_dp_mst_topology_state iteration cursor for the old 972da68386dSThomas Zimmermann * state 973da68386dSThomas Zimmermann * @__i: int iteration cursor, for macro-internal use 974da68386dSThomas Zimmermann * 975da68386dSThomas Zimmermann * This iterates over all DRM DP MST topology managers in an atomic update, 976da68386dSThomas Zimmermann * tracking only the old state. This is useful in disable functions, where we 977da68386dSThomas Zimmermann * need the old state the hardware is still in. 978da68386dSThomas Zimmermann */ 979da68386dSThomas Zimmermann #define for_each_old_mst_mgr_in_state(__state, mgr, old_state, __i) \ 980da68386dSThomas Zimmermann for ((__i) = 0; (__i) < (__state)->num_private_objs; (__i)++) \ 981da68386dSThomas Zimmermann for_each_if(__drm_dp_mst_state_iter_get((__state), &(mgr), &(old_state), NULL, (__i))) 982da68386dSThomas Zimmermann 983da68386dSThomas Zimmermann /** 984da68386dSThomas Zimmermann * for_each_new_mst_mgr_in_state - iterate over all DP MST topology managers 985da68386dSThomas Zimmermann * in an atomic update 986da68386dSThomas Zimmermann * @__state: &struct drm_atomic_state pointer 987da68386dSThomas Zimmermann * @mgr: &struct drm_dp_mst_topology_mgr iteration cursor 988da68386dSThomas Zimmermann * @new_state: &struct drm_dp_mst_topology_state iteration cursor for the new 989da68386dSThomas Zimmermann * state 990da68386dSThomas Zimmermann * @__i: int iteration cursor, for macro-internal use 991da68386dSThomas Zimmermann * 992da68386dSThomas Zimmermann * This iterates over all DRM DP MST topology managers in an atomic update, 993da68386dSThomas Zimmermann * tracking only the new state. This is useful in enable functions, where we 994da68386dSThomas Zimmermann * need the new state the hardware should be in when the atomic commit 995da68386dSThomas Zimmermann * operation has completed. 996da68386dSThomas Zimmermann */ 997da68386dSThomas Zimmermann #define for_each_new_mst_mgr_in_state(__state, mgr, new_state, __i) \ 998da68386dSThomas Zimmermann for ((__i) = 0; (__i) < (__state)->num_private_objs; (__i)++) \ 999da68386dSThomas Zimmermann for_each_if(__drm_dp_mst_state_iter_get((__state), &(mgr), NULL, &(new_state), (__i))) 1000da68386dSThomas Zimmermann 1001da68386dSThomas Zimmermann #endif 1002