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 5450bee2ae2SLyude Paul /** 5460bee2ae2SLyude Paul * struct drm_dp_mst_atomic_payload - Atomic state struct for an MST payload 5470bee2ae2SLyude Paul * 5480bee2ae2SLyude Paul * The primary atomic state structure for a given MST payload. Stores information like current 5490bee2ae2SLyude Paul * bandwidth allocation, intended action for this payload, etc. 5500bee2ae2SLyude Paul */ 55148b6b372SLyude Paul struct drm_dp_mst_atomic_payload { 5520bee2ae2SLyude 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; 5610bee2ae2SLyude Paul /** @pbn: The payload bandwidth for this payload */ 562da68386dSThomas Zimmermann int pbn; 563*6366fc70SLyude Paul 564*6366fc70SLyude Paul /** @delete: Whether or not we intend to delete this payload during this atomic commit */ 565*6366fc70SLyude Paul bool delete : 1; 5660bee2ae2SLyude Paul /** @dsc_enabled: Whether or not this payload has DSC enabled */ 567*6366fc70SLyude Paul bool dsc_enabled : 1; 5680bee2ae2SLyude Paul 5690bee2ae2SLyude Paul /** @next: The list node for this payload */ 570da68386dSThomas Zimmermann struct list_head next; 571da68386dSThomas Zimmermann }; 572da68386dSThomas Zimmermann 5730bee2ae2SLyude Paul /** 5740bee2ae2SLyude Paul * struct drm_dp_mst_topology_state - DisplayPort MST topology atomic state 5750bee2ae2SLyude Paul * 5760bee2ae2SLyude Paul * This struct represents the atomic state of the toplevel DisplayPort MST manager 5770bee2ae2SLyude Paul */ 578da68386dSThomas Zimmermann struct drm_dp_mst_topology_state { 5790bee2ae2SLyude Paul /** @base: Base private state for atomic */ 580da68386dSThomas Zimmermann struct drm_private_state base; 5810bee2ae2SLyude Paul 5820bee2ae2SLyude Paul /** @payloads: The list of payloads being created/destroyed in this state */ 58348b6b372SLyude Paul struct list_head payloads; 5840bee2ae2SLyude Paul /** @mgr: The topology manager */ 585da68386dSThomas Zimmermann struct drm_dp_mst_topology_mgr *mgr; 5860bee2ae2SLyude Paul 587a5c2c0d1SLyude Paul /** 588a5c2c0d1SLyude Paul * @pending_crtc_mask: A bitmask of all CRTCs this topology state touches, drivers may 589a5c2c0d1SLyude Paul * modify this to add additional dependencies if needed. 590a5c2c0d1SLyude Paul */ 591a5c2c0d1SLyude Paul u32 pending_crtc_mask; 592a5c2c0d1SLyude Paul /** 593a5c2c0d1SLyude Paul * @commit_deps: A list of all CRTC commits affecting this topology, this field isn't 594a5c2c0d1SLyude Paul * populated until drm_dp_mst_atomic_wait_for_dependencies() is called. 595a5c2c0d1SLyude Paul */ 596a5c2c0d1SLyude Paul struct drm_crtc_commit **commit_deps; 597a5c2c0d1SLyude Paul /** @num_commit_deps: The number of CRTC commits in @commit_deps */ 598a5c2c0d1SLyude Paul size_t num_commit_deps; 599a5c2c0d1SLyude Paul 6000bee2ae2SLyude Paul /** @total_avail_slots: The total number of slots this topology can handle (63 or 64) */ 601da68386dSThomas Zimmermann u8 total_avail_slots; 6020bee2ae2SLyude Paul /** @start_slot: The first usable time slot in this topology (1 or 0) */ 603da68386dSThomas Zimmermann u8 start_slot; 604da68386dSThomas Zimmermann }; 605da68386dSThomas Zimmermann 606da68386dSThomas Zimmermann #define to_dp_mst_topology_mgr(x) container_of(x, struct drm_dp_mst_topology_mgr, base) 607da68386dSThomas Zimmermann 608da68386dSThomas Zimmermann /** 609da68386dSThomas Zimmermann * struct drm_dp_mst_topology_mgr - DisplayPort MST manager 610da68386dSThomas Zimmermann * 611da68386dSThomas Zimmermann * This struct represents the toplevel displayport MST topology manager. 612da68386dSThomas Zimmermann * There should be one instance of this for every MST capable DP connector 613da68386dSThomas Zimmermann * on the GPU. 614da68386dSThomas Zimmermann */ 615da68386dSThomas Zimmermann struct drm_dp_mst_topology_mgr { 616da68386dSThomas Zimmermann /** 617da68386dSThomas Zimmermann * @base: Base private object for atomic 618da68386dSThomas Zimmermann */ 619da68386dSThomas Zimmermann struct drm_private_obj base; 620da68386dSThomas Zimmermann 621da68386dSThomas Zimmermann /** 622da68386dSThomas Zimmermann * @dev: device pointer for adding i2c devices etc. 623da68386dSThomas Zimmermann */ 624da68386dSThomas Zimmermann struct drm_device *dev; 625da68386dSThomas Zimmermann /** 626da68386dSThomas Zimmermann * @cbs: callbacks for connector addition and destruction. 627da68386dSThomas Zimmermann */ 628da68386dSThomas Zimmermann const struct drm_dp_mst_topology_cbs *cbs; 629da68386dSThomas Zimmermann /** 630da68386dSThomas Zimmermann * @max_dpcd_transaction_bytes: maximum number of bytes to read/write 631da68386dSThomas Zimmermann * in one go. 632da68386dSThomas Zimmermann */ 633da68386dSThomas Zimmermann int max_dpcd_transaction_bytes; 634da68386dSThomas Zimmermann /** 635da68386dSThomas Zimmermann * @aux: AUX channel for the DP MST connector this topolgy mgr is 636da68386dSThomas Zimmermann * controlling. 637da68386dSThomas Zimmermann */ 638da68386dSThomas Zimmermann struct drm_dp_aux *aux; 639da68386dSThomas Zimmermann /** 640da68386dSThomas Zimmermann * @max_payloads: maximum number of payloads the GPU can generate. 641da68386dSThomas Zimmermann */ 642da68386dSThomas Zimmermann int max_payloads; 643da68386dSThomas Zimmermann /** 644da68386dSThomas Zimmermann * @max_lane_count: maximum number of lanes the GPU can drive. 645da68386dSThomas Zimmermann */ 646da68386dSThomas Zimmermann int max_lane_count; 647da68386dSThomas Zimmermann /** 648da68386dSThomas Zimmermann * @max_link_rate: maximum link rate per lane GPU can output, in kHz. 649da68386dSThomas Zimmermann */ 650da68386dSThomas Zimmermann int max_link_rate; 651da68386dSThomas Zimmermann /** 652da68386dSThomas Zimmermann * @conn_base_id: DRM connector ID this mgr is connected to. Only used 653da68386dSThomas Zimmermann * to build the MST connector path value. 654da68386dSThomas Zimmermann */ 655da68386dSThomas Zimmermann int conn_base_id; 656da68386dSThomas Zimmermann 657da68386dSThomas Zimmermann /** 658da68386dSThomas Zimmermann * @up_req_recv: Message receiver state for up requests. 659da68386dSThomas Zimmermann */ 660da68386dSThomas Zimmermann struct drm_dp_sideband_msg_rx up_req_recv; 661da68386dSThomas Zimmermann 662da68386dSThomas Zimmermann /** 663da68386dSThomas Zimmermann * @down_rep_recv: Message receiver state for replies to down 664da68386dSThomas Zimmermann * requests. 665da68386dSThomas Zimmermann */ 666da68386dSThomas Zimmermann struct drm_dp_sideband_msg_rx down_rep_recv; 667da68386dSThomas Zimmermann 668da68386dSThomas Zimmermann /** 669da68386dSThomas Zimmermann * @lock: protects @mst_state, @mst_primary, @dpcd, and 670da68386dSThomas Zimmermann * @payload_id_table_cleared. 671da68386dSThomas Zimmermann */ 672da68386dSThomas Zimmermann struct mutex lock; 673da68386dSThomas Zimmermann 674da68386dSThomas Zimmermann /** 675da68386dSThomas Zimmermann * @probe_lock: Prevents @work and @up_req_work, the only writers of 676da68386dSThomas Zimmermann * &drm_dp_mst_port.mstb and &drm_dp_mst_branch.ports, from racing 677da68386dSThomas Zimmermann * while they update the topology. 678da68386dSThomas Zimmermann */ 679da68386dSThomas Zimmermann struct mutex probe_lock; 680da68386dSThomas Zimmermann 681da68386dSThomas Zimmermann /** 682da68386dSThomas Zimmermann * @mst_state: If this manager is enabled for an MST capable port. False 683da68386dSThomas Zimmermann * if no MST sink/branch devices is connected. 684da68386dSThomas Zimmermann */ 685da68386dSThomas Zimmermann bool mst_state : 1; 686da68386dSThomas Zimmermann 687da68386dSThomas Zimmermann /** 688da68386dSThomas Zimmermann * @payload_id_table_cleared: Whether or not we've cleared the payload 689da68386dSThomas Zimmermann * ID table for @mst_primary. Protected by @lock. 690da68386dSThomas Zimmermann */ 691da68386dSThomas Zimmermann bool payload_id_table_cleared : 1; 692da68386dSThomas Zimmermann 693da68386dSThomas Zimmermann /** 694da68386dSThomas Zimmermann * @mst_primary: Pointer to the primary/first branch device. 695da68386dSThomas Zimmermann */ 696da68386dSThomas Zimmermann struct drm_dp_mst_branch *mst_primary; 697da68386dSThomas Zimmermann 698da68386dSThomas Zimmermann /** 699da68386dSThomas Zimmermann * @dpcd: Cache of DPCD for primary port. 700da68386dSThomas Zimmermann */ 701da68386dSThomas Zimmermann u8 dpcd[DP_RECEIVER_CAP_SIZE]; 702da68386dSThomas Zimmermann /** 703da68386dSThomas Zimmermann * @sink_count: Sink count from DEVICE_SERVICE_IRQ_VECTOR_ESI0. 704da68386dSThomas Zimmermann */ 705da68386dSThomas Zimmermann u8 sink_count; 706da68386dSThomas Zimmermann /** 707da68386dSThomas Zimmermann * @pbn_div: PBN to slots divisor. 708da68386dSThomas Zimmermann */ 709da68386dSThomas Zimmermann int pbn_div; 710da68386dSThomas Zimmermann 711da68386dSThomas Zimmermann /** 712da68386dSThomas Zimmermann * @funcs: Atomic helper callbacks 713da68386dSThomas Zimmermann */ 714da68386dSThomas Zimmermann const struct drm_private_state_funcs *funcs; 715da68386dSThomas Zimmermann 716da68386dSThomas Zimmermann /** 717da68386dSThomas Zimmermann * @qlock: protects @tx_msg_downq and &drm_dp_sideband_msg_tx.state 718da68386dSThomas Zimmermann */ 719da68386dSThomas Zimmermann struct mutex qlock; 720da68386dSThomas Zimmermann 721da68386dSThomas Zimmermann /** 722da68386dSThomas Zimmermann * @tx_msg_downq: List of pending down requests 723da68386dSThomas Zimmermann */ 724da68386dSThomas Zimmermann struct list_head tx_msg_downq; 725da68386dSThomas Zimmermann 726da68386dSThomas Zimmermann /** 727da68386dSThomas Zimmermann * @payload_lock: Protect payload information. 728da68386dSThomas Zimmermann */ 729da68386dSThomas Zimmermann struct mutex payload_lock; 730da68386dSThomas Zimmermann /** 731da68386dSThomas Zimmermann * @proposed_vcpis: Array of pointers for the new VCPI allocation. The 732da68386dSThomas Zimmermann * VCPI structure itself is &drm_dp_mst_port.vcpi, and the size of 733da68386dSThomas Zimmermann * this array is determined by @max_payloads. 734da68386dSThomas Zimmermann */ 735da68386dSThomas Zimmermann struct drm_dp_vcpi **proposed_vcpis; 736da68386dSThomas Zimmermann /** 737da68386dSThomas Zimmermann * @payloads: Array of payloads. The size of this array is determined 738da68386dSThomas Zimmermann * by @max_payloads. 739da68386dSThomas Zimmermann */ 740da68386dSThomas Zimmermann struct drm_dp_payload *payloads; 741da68386dSThomas Zimmermann /** 742da68386dSThomas Zimmermann * @payload_mask: Elements of @payloads actually in use. Since 743da68386dSThomas Zimmermann * reallocation of active outputs isn't possible gaps can be created by 744da68386dSThomas Zimmermann * disabling outputs out of order compared to how they've been enabled. 745da68386dSThomas Zimmermann */ 746da68386dSThomas Zimmermann unsigned long payload_mask; 747da68386dSThomas Zimmermann /** 748da68386dSThomas Zimmermann * @vcpi_mask: Similar to @payload_mask, but for @proposed_vcpis. 749da68386dSThomas Zimmermann */ 750da68386dSThomas Zimmermann unsigned long vcpi_mask; 751da68386dSThomas Zimmermann 752da68386dSThomas Zimmermann /** 753da68386dSThomas Zimmermann * @tx_waitq: Wait to queue stall for the tx worker. 754da68386dSThomas Zimmermann */ 755da68386dSThomas Zimmermann wait_queue_head_t tx_waitq; 756da68386dSThomas Zimmermann /** 757da68386dSThomas Zimmermann * @work: Probe work. 758da68386dSThomas Zimmermann */ 759da68386dSThomas Zimmermann struct work_struct work; 760da68386dSThomas Zimmermann /** 761da68386dSThomas Zimmermann * @tx_work: Sideband transmit worker. This can nest within the main 762da68386dSThomas Zimmermann * @work worker for each transaction @work launches. 763da68386dSThomas Zimmermann */ 764da68386dSThomas Zimmermann struct work_struct tx_work; 765da68386dSThomas Zimmermann 766da68386dSThomas Zimmermann /** 767da68386dSThomas Zimmermann * @destroy_port_list: List of to be destroyed connectors. 768da68386dSThomas Zimmermann */ 769da68386dSThomas Zimmermann struct list_head destroy_port_list; 770da68386dSThomas Zimmermann /** 771da68386dSThomas Zimmermann * @destroy_branch_device_list: List of to be destroyed branch 772da68386dSThomas Zimmermann * devices. 773da68386dSThomas Zimmermann */ 774da68386dSThomas Zimmermann struct list_head destroy_branch_device_list; 775da68386dSThomas Zimmermann /** 776da68386dSThomas Zimmermann * @delayed_destroy_lock: Protects @destroy_port_list and 777da68386dSThomas Zimmermann * @destroy_branch_device_list. 778da68386dSThomas Zimmermann */ 779da68386dSThomas Zimmermann struct mutex delayed_destroy_lock; 780da68386dSThomas Zimmermann 781da68386dSThomas Zimmermann /** 782da68386dSThomas Zimmermann * @delayed_destroy_wq: Workqueue used for delayed_destroy_work items. 783da68386dSThomas Zimmermann * A dedicated WQ makes it possible to drain any requeued work items 784da68386dSThomas Zimmermann * on it. 785da68386dSThomas Zimmermann */ 786da68386dSThomas Zimmermann struct workqueue_struct *delayed_destroy_wq; 787da68386dSThomas Zimmermann 788da68386dSThomas Zimmermann /** 789da68386dSThomas Zimmermann * @delayed_destroy_work: Work item to destroy MST port and branch 790da68386dSThomas Zimmermann * devices, needed to avoid locking inversion. 791da68386dSThomas Zimmermann */ 792da68386dSThomas Zimmermann struct work_struct delayed_destroy_work; 793da68386dSThomas Zimmermann 794da68386dSThomas Zimmermann /** 795da68386dSThomas Zimmermann * @up_req_list: List of pending up requests from the topology that 796da68386dSThomas Zimmermann * need to be processed, in chronological order. 797da68386dSThomas Zimmermann */ 798da68386dSThomas Zimmermann struct list_head up_req_list; 799da68386dSThomas Zimmermann /** 800da68386dSThomas Zimmermann * @up_req_lock: Protects @up_req_list 801da68386dSThomas Zimmermann */ 802da68386dSThomas Zimmermann struct mutex up_req_lock; 803da68386dSThomas Zimmermann /** 804da68386dSThomas Zimmermann * @up_req_work: Work item to process up requests received from the 805da68386dSThomas Zimmermann * topology. Needed to avoid blocking hotplug handling and sideband 806da68386dSThomas Zimmermann * transmissions. 807da68386dSThomas Zimmermann */ 808da68386dSThomas Zimmermann struct work_struct up_req_work; 809da68386dSThomas Zimmermann 810da68386dSThomas Zimmermann #if IS_ENABLED(CONFIG_DRM_DEBUG_DP_MST_TOPOLOGY_REFS) 811da68386dSThomas Zimmermann /** 812da68386dSThomas Zimmermann * @topology_ref_history_lock: protects 813da68386dSThomas Zimmermann * &drm_dp_mst_port.topology_ref_history and 814da68386dSThomas Zimmermann * &drm_dp_mst_branch.topology_ref_history. 815da68386dSThomas Zimmermann */ 816da68386dSThomas Zimmermann struct mutex topology_ref_history_lock; 817da68386dSThomas Zimmermann #endif 818da68386dSThomas Zimmermann }; 819da68386dSThomas Zimmermann 820da68386dSThomas Zimmermann int drm_dp_mst_topology_mgr_init(struct drm_dp_mst_topology_mgr *mgr, 821da68386dSThomas Zimmermann struct drm_device *dev, struct drm_dp_aux *aux, 822da68386dSThomas Zimmermann int max_dpcd_transaction_bytes, 823da68386dSThomas Zimmermann int max_payloads, 824da68386dSThomas Zimmermann int max_lane_count, int max_link_rate, 825da68386dSThomas Zimmermann int conn_base_id); 826da68386dSThomas Zimmermann 827da68386dSThomas Zimmermann void drm_dp_mst_topology_mgr_destroy(struct drm_dp_mst_topology_mgr *mgr); 828da68386dSThomas Zimmermann 829da68386dSThomas Zimmermann bool drm_dp_read_mst_cap(struct drm_dp_aux *aux, const u8 dpcd[DP_RECEIVER_CAP_SIZE]); 830da68386dSThomas Zimmermann int drm_dp_mst_topology_mgr_set_mst(struct drm_dp_mst_topology_mgr *mgr, bool mst_state); 831da68386dSThomas Zimmermann 832da68386dSThomas Zimmermann int drm_dp_mst_hpd_irq(struct drm_dp_mst_topology_mgr *mgr, u8 *esi, bool *handled); 833da68386dSThomas Zimmermann 834da68386dSThomas Zimmermann 835da68386dSThomas Zimmermann int 836da68386dSThomas Zimmermann drm_dp_mst_detect_port(struct drm_connector *connector, 837da68386dSThomas Zimmermann struct drm_modeset_acquire_ctx *ctx, 838da68386dSThomas Zimmermann struct drm_dp_mst_topology_mgr *mgr, 839da68386dSThomas Zimmermann struct drm_dp_mst_port *port); 840da68386dSThomas Zimmermann 841da68386dSThomas 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); 842da68386dSThomas Zimmermann 843da68386dSThomas Zimmermann int drm_dp_get_vc_payload_bw(const struct drm_dp_mst_topology_mgr *mgr, 844da68386dSThomas Zimmermann int link_rate, int link_lane_count); 845da68386dSThomas Zimmermann 846da68386dSThomas Zimmermann int drm_dp_calc_pbn_mode(int clock, int bpp, bool dsc); 847da68386dSThomas Zimmermann 848da68386dSThomas Zimmermann bool drm_dp_mst_allocate_vcpi(struct drm_dp_mst_topology_mgr *mgr, 849da68386dSThomas Zimmermann struct drm_dp_mst_port *port, int pbn, int slots); 850da68386dSThomas Zimmermann 851da68386dSThomas Zimmermann int drm_dp_mst_get_vcpi_slots(struct drm_dp_mst_topology_mgr *mgr, struct drm_dp_mst_port *port); 852da68386dSThomas Zimmermann 853da68386dSThomas Zimmermann 854da68386dSThomas Zimmermann void drm_dp_mst_reset_vcpi_slots(struct drm_dp_mst_topology_mgr *mgr, struct drm_dp_mst_port *port); 855da68386dSThomas Zimmermann 856da68386dSThomas Zimmermann void drm_dp_mst_update_slots(struct drm_dp_mst_topology_state *mst_state, uint8_t link_encoding_cap); 857da68386dSThomas Zimmermann 858da68386dSThomas Zimmermann void drm_dp_mst_deallocate_vcpi(struct drm_dp_mst_topology_mgr *mgr, 859da68386dSThomas Zimmermann struct drm_dp_mst_port *port); 860da68386dSThomas Zimmermann 861da68386dSThomas Zimmermann 862da68386dSThomas Zimmermann int drm_dp_find_vcpi_slots(struct drm_dp_mst_topology_mgr *mgr, 863da68386dSThomas Zimmermann int pbn); 864da68386dSThomas Zimmermann 865da68386dSThomas Zimmermann 866da68386dSThomas Zimmermann int drm_dp_update_payload_part1(struct drm_dp_mst_topology_mgr *mgr, int start_slot); 867da68386dSThomas Zimmermann 868da68386dSThomas Zimmermann 869da68386dSThomas Zimmermann int drm_dp_update_payload_part2(struct drm_dp_mst_topology_mgr *mgr); 870da68386dSThomas Zimmermann 871da68386dSThomas Zimmermann int drm_dp_check_act_status(struct drm_dp_mst_topology_mgr *mgr); 872da68386dSThomas Zimmermann 873da68386dSThomas Zimmermann void drm_dp_mst_dump_topology(struct seq_file *m, 874da68386dSThomas Zimmermann struct drm_dp_mst_topology_mgr *mgr); 875da68386dSThomas Zimmermann 876da68386dSThomas Zimmermann void drm_dp_mst_topology_mgr_suspend(struct drm_dp_mst_topology_mgr *mgr); 877da68386dSThomas Zimmermann int __must_check 878da68386dSThomas Zimmermann drm_dp_mst_topology_mgr_resume(struct drm_dp_mst_topology_mgr *mgr, 879da68386dSThomas Zimmermann bool sync); 880da68386dSThomas Zimmermann 881da68386dSThomas Zimmermann ssize_t drm_dp_mst_dpcd_read(struct drm_dp_aux *aux, 882da68386dSThomas Zimmermann unsigned int offset, void *buffer, size_t size); 883da68386dSThomas Zimmermann ssize_t drm_dp_mst_dpcd_write(struct drm_dp_aux *aux, 884da68386dSThomas Zimmermann unsigned int offset, void *buffer, size_t size); 885da68386dSThomas Zimmermann 886da68386dSThomas Zimmermann int drm_dp_mst_connector_late_register(struct drm_connector *connector, 887da68386dSThomas Zimmermann struct drm_dp_mst_port *port); 888da68386dSThomas Zimmermann void drm_dp_mst_connector_early_unregister(struct drm_connector *connector, 889da68386dSThomas Zimmermann struct drm_dp_mst_port *port); 890da68386dSThomas Zimmermann 891da68386dSThomas Zimmermann struct drm_dp_mst_topology_state *drm_atomic_get_mst_topology_state(struct drm_atomic_state *state, 892da68386dSThomas Zimmermann struct drm_dp_mst_topology_mgr *mgr); 893da68386dSThomas Zimmermann int __must_check 894df78f7f6SLyude Paul drm_dp_atomic_find_time_slots(struct drm_atomic_state *state, 895da68386dSThomas Zimmermann struct drm_dp_mst_topology_mgr *mgr, 896da68386dSThomas Zimmermann struct drm_dp_mst_port *port, int pbn, 897da68386dSThomas Zimmermann int pbn_div); 898da68386dSThomas Zimmermann int drm_dp_mst_atomic_enable_dsc(struct drm_atomic_state *state, 899da68386dSThomas Zimmermann struct drm_dp_mst_port *port, 900da68386dSThomas Zimmermann int pbn, int pbn_div, 901da68386dSThomas Zimmermann bool enable); 902da68386dSThomas Zimmermann int __must_check 903da68386dSThomas Zimmermann drm_dp_mst_add_affected_dsc_crtcs(struct drm_atomic_state *state, 904da68386dSThomas Zimmermann struct drm_dp_mst_topology_mgr *mgr); 905da68386dSThomas Zimmermann int __must_check 906df78f7f6SLyude Paul drm_dp_atomic_release_time_slots(struct drm_atomic_state *state, 907da68386dSThomas Zimmermann struct drm_dp_mst_topology_mgr *mgr, 908da68386dSThomas Zimmermann struct drm_dp_mst_port *port); 909a5c2c0d1SLyude Paul void drm_dp_mst_atomic_wait_for_dependencies(struct drm_atomic_state *state); 910a5c2c0d1SLyude Paul int __must_check drm_dp_mst_atomic_setup_commit(struct drm_atomic_state *state); 911da68386dSThomas Zimmermann int drm_dp_send_power_updown_phy(struct drm_dp_mst_topology_mgr *mgr, 912da68386dSThomas Zimmermann struct drm_dp_mst_port *port, bool power_up); 913da68386dSThomas Zimmermann int drm_dp_send_query_stream_enc_status(struct drm_dp_mst_topology_mgr *mgr, 914da68386dSThomas Zimmermann struct drm_dp_mst_port *port, 915da68386dSThomas Zimmermann struct drm_dp_query_stream_enc_status_ack_reply *status); 916da68386dSThomas Zimmermann int __must_check drm_dp_mst_atomic_check(struct drm_atomic_state *state); 917a76eb429SLyude Paul int __must_check drm_dp_mst_root_conn_atomic_check(struct drm_connector_state *new_conn_state, 918a76eb429SLyude Paul struct drm_dp_mst_topology_mgr *mgr); 919da68386dSThomas Zimmermann 920da68386dSThomas Zimmermann void drm_dp_mst_get_port_malloc(struct drm_dp_mst_port *port); 921da68386dSThomas Zimmermann void drm_dp_mst_put_port_malloc(struct drm_dp_mst_port *port); 922da68386dSThomas Zimmermann 923da68386dSThomas Zimmermann struct drm_dp_aux *drm_dp_mst_dsc_aux_for_port(struct drm_dp_mst_port *port); 924da68386dSThomas Zimmermann 925da68386dSThomas Zimmermann extern const struct drm_private_state_funcs drm_dp_mst_topology_state_funcs; 926da68386dSThomas Zimmermann 927da68386dSThomas Zimmermann /** 928da68386dSThomas Zimmermann * __drm_dp_mst_state_iter_get - private atomic state iterator function for 929da68386dSThomas Zimmermann * macro-internal use 930da68386dSThomas Zimmermann * @state: &struct drm_atomic_state pointer 931da68386dSThomas Zimmermann * @mgr: pointer to the &struct drm_dp_mst_topology_mgr iteration cursor 932da68386dSThomas Zimmermann * @old_state: optional pointer to the old &struct drm_dp_mst_topology_state 933da68386dSThomas Zimmermann * iteration cursor 934da68386dSThomas Zimmermann * @new_state: optional pointer to the new &struct drm_dp_mst_topology_state 935da68386dSThomas Zimmermann * iteration cursor 936da68386dSThomas Zimmermann * @i: int iteration cursor, for macro-internal use 937da68386dSThomas Zimmermann * 938da68386dSThomas Zimmermann * Used by for_each_oldnew_mst_mgr_in_state(), 939da68386dSThomas Zimmermann * for_each_old_mst_mgr_in_state(), and for_each_new_mst_mgr_in_state(). Don't 940da68386dSThomas Zimmermann * call this directly. 941da68386dSThomas Zimmermann * 942da68386dSThomas Zimmermann * Returns: 943da68386dSThomas Zimmermann * True if the current &struct drm_private_obj is a &struct 944da68386dSThomas Zimmermann * drm_dp_mst_topology_mgr, false otherwise. 945da68386dSThomas Zimmermann */ 946da68386dSThomas Zimmermann static inline bool 947da68386dSThomas Zimmermann __drm_dp_mst_state_iter_get(struct drm_atomic_state *state, 948da68386dSThomas Zimmermann struct drm_dp_mst_topology_mgr **mgr, 949da68386dSThomas Zimmermann struct drm_dp_mst_topology_state **old_state, 950da68386dSThomas Zimmermann struct drm_dp_mst_topology_state **new_state, 951da68386dSThomas Zimmermann int i) 952da68386dSThomas Zimmermann { 953da68386dSThomas Zimmermann struct __drm_private_objs_state *objs_state = &state->private_objs[i]; 954da68386dSThomas Zimmermann 955da68386dSThomas Zimmermann if (objs_state->ptr->funcs != &drm_dp_mst_topology_state_funcs) 956da68386dSThomas Zimmermann return false; 957da68386dSThomas Zimmermann 958da68386dSThomas Zimmermann *mgr = to_dp_mst_topology_mgr(objs_state->ptr); 959da68386dSThomas Zimmermann if (old_state) 960da68386dSThomas Zimmermann *old_state = to_dp_mst_topology_state(objs_state->old_state); 961da68386dSThomas Zimmermann if (new_state) 962da68386dSThomas Zimmermann *new_state = to_dp_mst_topology_state(objs_state->new_state); 963da68386dSThomas Zimmermann 964da68386dSThomas Zimmermann return true; 965da68386dSThomas Zimmermann } 966da68386dSThomas Zimmermann 967da68386dSThomas Zimmermann /** 968da68386dSThomas Zimmermann * for_each_oldnew_mst_mgr_in_state - iterate over all DP MST topology 969da68386dSThomas Zimmermann * managers in an atomic update 970da68386dSThomas Zimmermann * @__state: &struct drm_atomic_state pointer 971da68386dSThomas Zimmermann * @mgr: &struct drm_dp_mst_topology_mgr iteration cursor 972da68386dSThomas Zimmermann * @old_state: &struct drm_dp_mst_topology_state iteration cursor for the old 973da68386dSThomas Zimmermann * state 974da68386dSThomas Zimmermann * @new_state: &struct drm_dp_mst_topology_state iteration cursor for the new 975da68386dSThomas Zimmermann * state 976da68386dSThomas Zimmermann * @__i: int iteration cursor, for macro-internal use 977da68386dSThomas Zimmermann * 978da68386dSThomas Zimmermann * This iterates over all DRM DP MST topology managers in an atomic update, 979da68386dSThomas Zimmermann * tracking both old and new state. This is useful in places where the state 980da68386dSThomas Zimmermann * delta needs to be considered, for example in atomic check functions. 981da68386dSThomas Zimmermann */ 982da68386dSThomas Zimmermann #define for_each_oldnew_mst_mgr_in_state(__state, mgr, old_state, new_state, __i) \ 983da68386dSThomas Zimmermann for ((__i) = 0; (__i) < (__state)->num_private_objs; (__i)++) \ 984da68386dSThomas Zimmermann for_each_if(__drm_dp_mst_state_iter_get((__state), &(mgr), &(old_state), &(new_state), (__i))) 985da68386dSThomas Zimmermann 986da68386dSThomas Zimmermann /** 987da68386dSThomas Zimmermann * for_each_old_mst_mgr_in_state - iterate over all DP MST topology managers 988da68386dSThomas Zimmermann * in an atomic update 989da68386dSThomas Zimmermann * @__state: &struct drm_atomic_state pointer 990da68386dSThomas Zimmermann * @mgr: &struct drm_dp_mst_topology_mgr iteration cursor 991da68386dSThomas Zimmermann * @old_state: &struct drm_dp_mst_topology_state iteration cursor for the old 992da68386dSThomas Zimmermann * state 993da68386dSThomas Zimmermann * @__i: int iteration cursor, for macro-internal use 994da68386dSThomas Zimmermann * 995da68386dSThomas Zimmermann * This iterates over all DRM DP MST topology managers in an atomic update, 996da68386dSThomas Zimmermann * tracking only the old state. This is useful in disable functions, where we 997da68386dSThomas Zimmermann * need the old state the hardware is still in. 998da68386dSThomas Zimmermann */ 999da68386dSThomas Zimmermann #define for_each_old_mst_mgr_in_state(__state, mgr, old_state, __i) \ 1000da68386dSThomas Zimmermann for ((__i) = 0; (__i) < (__state)->num_private_objs; (__i)++) \ 1001da68386dSThomas Zimmermann for_each_if(__drm_dp_mst_state_iter_get((__state), &(mgr), &(old_state), NULL, (__i))) 1002da68386dSThomas Zimmermann 1003da68386dSThomas Zimmermann /** 1004da68386dSThomas Zimmermann * for_each_new_mst_mgr_in_state - iterate over all DP MST topology managers 1005da68386dSThomas Zimmermann * in an atomic update 1006da68386dSThomas Zimmermann * @__state: &struct drm_atomic_state pointer 1007da68386dSThomas Zimmermann * @mgr: &struct drm_dp_mst_topology_mgr iteration cursor 1008da68386dSThomas Zimmermann * @new_state: &struct drm_dp_mst_topology_state iteration cursor for the new 1009da68386dSThomas Zimmermann * state 1010da68386dSThomas Zimmermann * @__i: int iteration cursor, for macro-internal use 1011da68386dSThomas Zimmermann * 1012da68386dSThomas Zimmermann * This iterates over all DRM DP MST topology managers in an atomic update, 1013da68386dSThomas Zimmermann * tracking only the new state. This is useful in enable functions, where we 1014da68386dSThomas Zimmermann * need the new state the hardware should be in when the atomic commit 1015da68386dSThomas Zimmermann * operation has completed. 1016da68386dSThomas Zimmermann */ 1017da68386dSThomas Zimmermann #define for_each_new_mst_mgr_in_state(__state, mgr, new_state, __i) \ 1018da68386dSThomas Zimmermann for ((__i) = 0; (__i) < (__state)->num_private_objs; (__i)++) \ 1019da68386dSThomas Zimmermann for_each_if(__drm_dp_mst_state_iter_get((__state), &(mgr), NULL, &(new_state), (__i))) 1020da68386dSThomas Zimmermann 1021da68386dSThomas Zimmermann #endif 1022