18c2ecf20Sopenharmony_ci/* 28c2ecf20Sopenharmony_ci * Copyright © 2014 Red Hat. 38c2ecf20Sopenharmony_ci * 48c2ecf20Sopenharmony_ci * Permission to use, copy, modify, distribute, and sell this software and its 58c2ecf20Sopenharmony_ci * documentation for any purpose is hereby granted without fee, provided that 68c2ecf20Sopenharmony_ci * the above copyright notice appear in all copies and that both that copyright 78c2ecf20Sopenharmony_ci * notice and this permission notice appear in supporting documentation, and 88c2ecf20Sopenharmony_ci * that the name of the copyright holders not be used in advertising or 98c2ecf20Sopenharmony_ci * publicity pertaining to distribution of the software without specific, 108c2ecf20Sopenharmony_ci * written prior permission. The copyright holders make no representations 118c2ecf20Sopenharmony_ci * about the suitability of this software for any purpose. It is provided "as 128c2ecf20Sopenharmony_ci * is" without express or implied warranty. 138c2ecf20Sopenharmony_ci * 148c2ecf20Sopenharmony_ci * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, 158c2ecf20Sopenharmony_ci * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO 168c2ecf20Sopenharmony_ci * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR 178c2ecf20Sopenharmony_ci * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, 188c2ecf20Sopenharmony_ci * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER 198c2ecf20Sopenharmony_ci * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE 208c2ecf20Sopenharmony_ci * OF THIS SOFTWARE. 218c2ecf20Sopenharmony_ci */ 228c2ecf20Sopenharmony_ci#ifndef _DRM_DP_MST_HELPER_H_ 238c2ecf20Sopenharmony_ci#define _DRM_DP_MST_HELPER_H_ 248c2ecf20Sopenharmony_ci 258c2ecf20Sopenharmony_ci#include <linux/types.h> 268c2ecf20Sopenharmony_ci#include <drm/drm_dp_helper.h> 278c2ecf20Sopenharmony_ci#include <drm/drm_atomic.h> 288c2ecf20Sopenharmony_ci 298c2ecf20Sopenharmony_ci#if IS_ENABLED(CONFIG_DRM_DEBUG_DP_MST_TOPOLOGY_REFS) 308c2ecf20Sopenharmony_ci#include <linux/stackdepot.h> 318c2ecf20Sopenharmony_ci#include <linux/timekeeping.h> 328c2ecf20Sopenharmony_ci 338c2ecf20Sopenharmony_cienum drm_dp_mst_topology_ref_type { 348c2ecf20Sopenharmony_ci DRM_DP_MST_TOPOLOGY_REF_GET, 358c2ecf20Sopenharmony_ci DRM_DP_MST_TOPOLOGY_REF_PUT, 368c2ecf20Sopenharmony_ci}; 378c2ecf20Sopenharmony_ci 388c2ecf20Sopenharmony_cistruct drm_dp_mst_topology_ref_history { 398c2ecf20Sopenharmony_ci struct drm_dp_mst_topology_ref_entry { 408c2ecf20Sopenharmony_ci enum drm_dp_mst_topology_ref_type type; 418c2ecf20Sopenharmony_ci int count; 428c2ecf20Sopenharmony_ci ktime_t ts_nsec; 438c2ecf20Sopenharmony_ci depot_stack_handle_t backtrace; 448c2ecf20Sopenharmony_ci } *entries; 458c2ecf20Sopenharmony_ci int len; 468c2ecf20Sopenharmony_ci}; 478c2ecf20Sopenharmony_ci#endif /* IS_ENABLED(CONFIG_DRM_DEBUG_DP_MST_TOPOLOGY_REFS) */ 488c2ecf20Sopenharmony_ci 498c2ecf20Sopenharmony_cistruct drm_dp_mst_branch; 508c2ecf20Sopenharmony_ci 518c2ecf20Sopenharmony_ci/** 528c2ecf20Sopenharmony_ci * struct drm_dp_vcpi - Virtual Channel Payload Identifier 538c2ecf20Sopenharmony_ci * @vcpi: Virtual channel ID. 548c2ecf20Sopenharmony_ci * @pbn: Payload Bandwidth Number for this channel 558c2ecf20Sopenharmony_ci * @aligned_pbn: PBN aligned with slot size 568c2ecf20Sopenharmony_ci * @num_slots: number of slots for this PBN 578c2ecf20Sopenharmony_ci */ 588c2ecf20Sopenharmony_cistruct drm_dp_vcpi { 598c2ecf20Sopenharmony_ci int vcpi; 608c2ecf20Sopenharmony_ci int pbn; 618c2ecf20Sopenharmony_ci int aligned_pbn; 628c2ecf20Sopenharmony_ci int num_slots; 638c2ecf20Sopenharmony_ci}; 648c2ecf20Sopenharmony_ci 658c2ecf20Sopenharmony_ci/** 668c2ecf20Sopenharmony_ci * struct drm_dp_mst_port - MST port 678c2ecf20Sopenharmony_ci * @port_num: port number 688c2ecf20Sopenharmony_ci * @input: if this port is an input port. Protected by 698c2ecf20Sopenharmony_ci * &drm_dp_mst_topology_mgr.base.lock. 708c2ecf20Sopenharmony_ci * @mcs: message capability status - DP 1.2 spec. Protected by 718c2ecf20Sopenharmony_ci * &drm_dp_mst_topology_mgr.base.lock. 728c2ecf20Sopenharmony_ci * @ddps: DisplayPort Device Plug Status - DP 1.2. Protected by 738c2ecf20Sopenharmony_ci * &drm_dp_mst_topology_mgr.base.lock. 748c2ecf20Sopenharmony_ci * @pdt: Peer Device Type. Protected by 758c2ecf20Sopenharmony_ci * &drm_dp_mst_topology_mgr.base.lock. 768c2ecf20Sopenharmony_ci * @ldps: Legacy Device Plug Status. Protected by 778c2ecf20Sopenharmony_ci * &drm_dp_mst_topology_mgr.base.lock. 788c2ecf20Sopenharmony_ci * @dpcd_rev: DPCD revision of device on this port. Protected by 798c2ecf20Sopenharmony_ci * &drm_dp_mst_topology_mgr.base.lock. 808c2ecf20Sopenharmony_ci * @num_sdp_streams: Number of simultaneous streams. Protected by 818c2ecf20Sopenharmony_ci * &drm_dp_mst_topology_mgr.base.lock. 828c2ecf20Sopenharmony_ci * @num_sdp_stream_sinks: Number of stream sinks. Protected by 838c2ecf20Sopenharmony_ci * &drm_dp_mst_topology_mgr.base.lock. 848c2ecf20Sopenharmony_ci * @full_pbn: Max possible bandwidth for this port. Protected by 858c2ecf20Sopenharmony_ci * &drm_dp_mst_topology_mgr.base.lock. 868c2ecf20Sopenharmony_ci * @next: link to next port on this branch device 878c2ecf20Sopenharmony_ci * @aux: i2c aux transport to talk to device connected to this port, protected 888c2ecf20Sopenharmony_ci * by &drm_dp_mst_topology_mgr.base.lock. 898c2ecf20Sopenharmony_ci * @parent: branch device parent of this port 908c2ecf20Sopenharmony_ci * @vcpi: Virtual Channel Payload info for this port. 918c2ecf20Sopenharmony_ci * @connector: DRM connector this port is connected to. Protected by 928c2ecf20Sopenharmony_ci * &drm_dp_mst_topology_mgr.base.lock. 938c2ecf20Sopenharmony_ci * @mgr: topology manager this port lives under. 948c2ecf20Sopenharmony_ci * 958c2ecf20Sopenharmony_ci * This structure represents an MST port endpoint on a device somewhere 968c2ecf20Sopenharmony_ci * in the MST topology. 978c2ecf20Sopenharmony_ci */ 988c2ecf20Sopenharmony_cistruct drm_dp_mst_port { 998c2ecf20Sopenharmony_ci /** 1008c2ecf20Sopenharmony_ci * @topology_kref: refcount for this port's lifetime in the topology, 1018c2ecf20Sopenharmony_ci * only the DP MST helpers should need to touch this 1028c2ecf20Sopenharmony_ci */ 1038c2ecf20Sopenharmony_ci struct kref topology_kref; 1048c2ecf20Sopenharmony_ci 1058c2ecf20Sopenharmony_ci /** 1068c2ecf20Sopenharmony_ci * @malloc_kref: refcount for the memory allocation containing this 1078c2ecf20Sopenharmony_ci * structure. See drm_dp_mst_get_port_malloc() and 1088c2ecf20Sopenharmony_ci * drm_dp_mst_put_port_malloc(). 1098c2ecf20Sopenharmony_ci */ 1108c2ecf20Sopenharmony_ci struct kref malloc_kref; 1118c2ecf20Sopenharmony_ci 1128c2ecf20Sopenharmony_ci#if IS_ENABLED(CONFIG_DRM_DEBUG_DP_MST_TOPOLOGY_REFS) 1138c2ecf20Sopenharmony_ci /** 1148c2ecf20Sopenharmony_ci * @topology_ref_history: A history of each topology 1158c2ecf20Sopenharmony_ci * reference/dereference. See CONFIG_DRM_DEBUG_DP_MST_TOPOLOGY_REFS. 1168c2ecf20Sopenharmony_ci */ 1178c2ecf20Sopenharmony_ci struct drm_dp_mst_topology_ref_history topology_ref_history; 1188c2ecf20Sopenharmony_ci#endif 1198c2ecf20Sopenharmony_ci 1208c2ecf20Sopenharmony_ci u8 port_num; 1218c2ecf20Sopenharmony_ci bool input; 1228c2ecf20Sopenharmony_ci bool mcs; 1238c2ecf20Sopenharmony_ci bool ddps; 1248c2ecf20Sopenharmony_ci u8 pdt; 1258c2ecf20Sopenharmony_ci bool ldps; 1268c2ecf20Sopenharmony_ci u8 dpcd_rev; 1278c2ecf20Sopenharmony_ci u8 num_sdp_streams; 1288c2ecf20Sopenharmony_ci u8 num_sdp_stream_sinks; 1298c2ecf20Sopenharmony_ci uint16_t full_pbn; 1308c2ecf20Sopenharmony_ci struct list_head next; 1318c2ecf20Sopenharmony_ci /** 1328c2ecf20Sopenharmony_ci * @mstb: the branch device connected to this port, if there is one. 1338c2ecf20Sopenharmony_ci * This should be considered protected for reading by 1348c2ecf20Sopenharmony_ci * &drm_dp_mst_topology_mgr.lock. There are two exceptions to this: 1358c2ecf20Sopenharmony_ci * &drm_dp_mst_topology_mgr.up_req_work and 1368c2ecf20Sopenharmony_ci * &drm_dp_mst_topology_mgr.work, which do not grab 1378c2ecf20Sopenharmony_ci * &drm_dp_mst_topology_mgr.lock during reads but are the only 1388c2ecf20Sopenharmony_ci * updaters of this list and are protected from writing concurrently 1398c2ecf20Sopenharmony_ci * by &drm_dp_mst_topology_mgr.probe_lock. 1408c2ecf20Sopenharmony_ci */ 1418c2ecf20Sopenharmony_ci struct drm_dp_mst_branch *mstb; 1428c2ecf20Sopenharmony_ci struct drm_dp_aux aux; /* i2c bus for this port? */ 1438c2ecf20Sopenharmony_ci struct drm_dp_mst_branch *parent; 1448c2ecf20Sopenharmony_ci 1458c2ecf20Sopenharmony_ci struct drm_dp_vcpi vcpi; 1468c2ecf20Sopenharmony_ci struct drm_connector *connector; 1478c2ecf20Sopenharmony_ci struct drm_dp_mst_topology_mgr *mgr; 1488c2ecf20Sopenharmony_ci 1498c2ecf20Sopenharmony_ci /** 1508c2ecf20Sopenharmony_ci * @cached_edid: for DP logical ports - make tiling work by ensuring 1518c2ecf20Sopenharmony_ci * that the EDID for all connectors is read immediately. 1528c2ecf20Sopenharmony_ci */ 1538c2ecf20Sopenharmony_ci struct edid *cached_edid; 1548c2ecf20Sopenharmony_ci /** 1558c2ecf20Sopenharmony_ci * @has_audio: Tracks whether the sink connector to this port is 1568c2ecf20Sopenharmony_ci * audio-capable. 1578c2ecf20Sopenharmony_ci */ 1588c2ecf20Sopenharmony_ci bool has_audio; 1598c2ecf20Sopenharmony_ci 1608c2ecf20Sopenharmony_ci /** 1618c2ecf20Sopenharmony_ci * @fec_capable: bool indicating if FEC can be supported up to that 1628c2ecf20Sopenharmony_ci * point in the MST topology. 1638c2ecf20Sopenharmony_ci */ 1648c2ecf20Sopenharmony_ci bool fec_capable; 1658c2ecf20Sopenharmony_ci}; 1668c2ecf20Sopenharmony_ci 1678c2ecf20Sopenharmony_ci/* sideband msg header - not bit struct */ 1688c2ecf20Sopenharmony_cistruct drm_dp_sideband_msg_hdr { 1698c2ecf20Sopenharmony_ci u8 lct; 1708c2ecf20Sopenharmony_ci u8 lcr; 1718c2ecf20Sopenharmony_ci u8 rad[8]; 1728c2ecf20Sopenharmony_ci bool broadcast; 1738c2ecf20Sopenharmony_ci bool path_msg; 1748c2ecf20Sopenharmony_ci u8 msg_len; 1758c2ecf20Sopenharmony_ci bool somt; 1768c2ecf20Sopenharmony_ci bool eomt; 1778c2ecf20Sopenharmony_ci bool seqno; 1788c2ecf20Sopenharmony_ci}; 1798c2ecf20Sopenharmony_ci 1808c2ecf20Sopenharmony_cistruct drm_dp_sideband_msg_rx { 1818c2ecf20Sopenharmony_ci u8 chunk[48]; 1828c2ecf20Sopenharmony_ci u8 msg[256]; 1838c2ecf20Sopenharmony_ci u8 curchunk_len; 1848c2ecf20Sopenharmony_ci u8 curchunk_idx; /* chunk we are parsing now */ 1858c2ecf20Sopenharmony_ci u8 curchunk_hdrlen; 1868c2ecf20Sopenharmony_ci u8 curlen; /* total length of the msg */ 1878c2ecf20Sopenharmony_ci bool have_somt; 1888c2ecf20Sopenharmony_ci bool have_eomt; 1898c2ecf20Sopenharmony_ci struct drm_dp_sideband_msg_hdr initial_hdr; 1908c2ecf20Sopenharmony_ci}; 1918c2ecf20Sopenharmony_ci 1928c2ecf20Sopenharmony_ci/** 1938c2ecf20Sopenharmony_ci * struct drm_dp_mst_branch - MST branch device. 1948c2ecf20Sopenharmony_ci * @rad: Relative Address to talk to this branch device. 1958c2ecf20Sopenharmony_ci * @lct: Link count total to talk to this branch device. 1968c2ecf20Sopenharmony_ci * @num_ports: number of ports on the branch. 1978c2ecf20Sopenharmony_ci * @port_parent: pointer to the port parent, NULL if toplevel. 1988c2ecf20Sopenharmony_ci * @mgr: topology manager for this branch device. 1998c2ecf20Sopenharmony_ci * @link_address_sent: if a link address message has been sent to this device yet. 2008c2ecf20Sopenharmony_ci * @guid: guid for DP 1.2 branch device. port under this branch can be 2018c2ecf20Sopenharmony_ci * identified by port #. 2028c2ecf20Sopenharmony_ci * 2038c2ecf20Sopenharmony_ci * This structure represents an MST branch device, there is one 2048c2ecf20Sopenharmony_ci * primary branch device at the root, along with any other branches connected 2058c2ecf20Sopenharmony_ci * to downstream port of parent branches. 2068c2ecf20Sopenharmony_ci */ 2078c2ecf20Sopenharmony_cistruct drm_dp_mst_branch { 2088c2ecf20Sopenharmony_ci /** 2098c2ecf20Sopenharmony_ci * @topology_kref: refcount for this branch device's lifetime in the 2108c2ecf20Sopenharmony_ci * topology, only the DP MST helpers should need to touch this 2118c2ecf20Sopenharmony_ci */ 2128c2ecf20Sopenharmony_ci struct kref topology_kref; 2138c2ecf20Sopenharmony_ci 2148c2ecf20Sopenharmony_ci /** 2158c2ecf20Sopenharmony_ci * @malloc_kref: refcount for the memory allocation containing this 2168c2ecf20Sopenharmony_ci * structure. See drm_dp_mst_get_mstb_malloc() and 2178c2ecf20Sopenharmony_ci * drm_dp_mst_put_mstb_malloc(). 2188c2ecf20Sopenharmony_ci */ 2198c2ecf20Sopenharmony_ci struct kref malloc_kref; 2208c2ecf20Sopenharmony_ci 2218c2ecf20Sopenharmony_ci#if IS_ENABLED(CONFIG_DRM_DEBUG_DP_MST_TOPOLOGY_REFS) 2228c2ecf20Sopenharmony_ci /** 2238c2ecf20Sopenharmony_ci * @topology_ref_history: A history of each topology 2248c2ecf20Sopenharmony_ci * reference/dereference. See CONFIG_DRM_DEBUG_DP_MST_TOPOLOGY_REFS. 2258c2ecf20Sopenharmony_ci */ 2268c2ecf20Sopenharmony_ci struct drm_dp_mst_topology_ref_history topology_ref_history; 2278c2ecf20Sopenharmony_ci#endif 2288c2ecf20Sopenharmony_ci 2298c2ecf20Sopenharmony_ci /** 2308c2ecf20Sopenharmony_ci * @destroy_next: linked-list entry used by 2318c2ecf20Sopenharmony_ci * drm_dp_delayed_destroy_work() 2328c2ecf20Sopenharmony_ci */ 2338c2ecf20Sopenharmony_ci struct list_head destroy_next; 2348c2ecf20Sopenharmony_ci 2358c2ecf20Sopenharmony_ci u8 rad[8]; 2368c2ecf20Sopenharmony_ci u8 lct; 2378c2ecf20Sopenharmony_ci int num_ports; 2388c2ecf20Sopenharmony_ci 2398c2ecf20Sopenharmony_ci /** 2408c2ecf20Sopenharmony_ci * @ports: the list of ports on this branch device. This should be 2418c2ecf20Sopenharmony_ci * considered protected for reading by &drm_dp_mst_topology_mgr.lock. 2428c2ecf20Sopenharmony_ci * There are two exceptions to this: 2438c2ecf20Sopenharmony_ci * &drm_dp_mst_topology_mgr.up_req_work and 2448c2ecf20Sopenharmony_ci * &drm_dp_mst_topology_mgr.work, which do not grab 2458c2ecf20Sopenharmony_ci * &drm_dp_mst_topology_mgr.lock during reads but are the only 2468c2ecf20Sopenharmony_ci * updaters of this list and are protected from updating the list 2478c2ecf20Sopenharmony_ci * concurrently by @drm_dp_mst_topology_mgr.probe_lock 2488c2ecf20Sopenharmony_ci */ 2498c2ecf20Sopenharmony_ci struct list_head ports; 2508c2ecf20Sopenharmony_ci 2518c2ecf20Sopenharmony_ci struct drm_dp_mst_port *port_parent; 2528c2ecf20Sopenharmony_ci struct drm_dp_mst_topology_mgr *mgr; 2538c2ecf20Sopenharmony_ci 2548c2ecf20Sopenharmony_ci bool link_address_sent; 2558c2ecf20Sopenharmony_ci 2568c2ecf20Sopenharmony_ci /* global unique identifier to identify branch devices */ 2578c2ecf20Sopenharmony_ci u8 guid[16]; 2588c2ecf20Sopenharmony_ci}; 2598c2ecf20Sopenharmony_ci 2608c2ecf20Sopenharmony_ci 2618c2ecf20Sopenharmony_cistruct drm_dp_nak_reply { 2628c2ecf20Sopenharmony_ci u8 guid[16]; 2638c2ecf20Sopenharmony_ci u8 reason; 2648c2ecf20Sopenharmony_ci u8 nak_data; 2658c2ecf20Sopenharmony_ci}; 2668c2ecf20Sopenharmony_ci 2678c2ecf20Sopenharmony_cistruct drm_dp_link_address_ack_reply { 2688c2ecf20Sopenharmony_ci u8 guid[16]; 2698c2ecf20Sopenharmony_ci u8 nports; 2708c2ecf20Sopenharmony_ci struct drm_dp_link_addr_reply_port { 2718c2ecf20Sopenharmony_ci bool input_port; 2728c2ecf20Sopenharmony_ci u8 peer_device_type; 2738c2ecf20Sopenharmony_ci u8 port_number; 2748c2ecf20Sopenharmony_ci bool mcs; 2758c2ecf20Sopenharmony_ci bool ddps; 2768c2ecf20Sopenharmony_ci bool legacy_device_plug_status; 2778c2ecf20Sopenharmony_ci u8 dpcd_revision; 2788c2ecf20Sopenharmony_ci u8 peer_guid[16]; 2798c2ecf20Sopenharmony_ci u8 num_sdp_streams; 2808c2ecf20Sopenharmony_ci u8 num_sdp_stream_sinks; 2818c2ecf20Sopenharmony_ci } ports[16]; 2828c2ecf20Sopenharmony_ci}; 2838c2ecf20Sopenharmony_ci 2848c2ecf20Sopenharmony_cistruct drm_dp_remote_dpcd_read_ack_reply { 2858c2ecf20Sopenharmony_ci u8 port_number; 2868c2ecf20Sopenharmony_ci u8 num_bytes; 2878c2ecf20Sopenharmony_ci u8 bytes[255]; 2888c2ecf20Sopenharmony_ci}; 2898c2ecf20Sopenharmony_ci 2908c2ecf20Sopenharmony_cistruct drm_dp_remote_dpcd_write_ack_reply { 2918c2ecf20Sopenharmony_ci u8 port_number; 2928c2ecf20Sopenharmony_ci}; 2938c2ecf20Sopenharmony_ci 2948c2ecf20Sopenharmony_cistruct drm_dp_remote_dpcd_write_nak_reply { 2958c2ecf20Sopenharmony_ci u8 port_number; 2968c2ecf20Sopenharmony_ci u8 reason; 2978c2ecf20Sopenharmony_ci u8 bytes_written_before_failure; 2988c2ecf20Sopenharmony_ci}; 2998c2ecf20Sopenharmony_ci 3008c2ecf20Sopenharmony_cistruct drm_dp_remote_i2c_read_ack_reply { 3018c2ecf20Sopenharmony_ci u8 port_number; 3028c2ecf20Sopenharmony_ci u8 num_bytes; 3038c2ecf20Sopenharmony_ci u8 bytes[255]; 3048c2ecf20Sopenharmony_ci}; 3058c2ecf20Sopenharmony_ci 3068c2ecf20Sopenharmony_cistruct drm_dp_remote_i2c_read_nak_reply { 3078c2ecf20Sopenharmony_ci u8 port_number; 3088c2ecf20Sopenharmony_ci u8 nak_reason; 3098c2ecf20Sopenharmony_ci u8 i2c_nak_transaction; 3108c2ecf20Sopenharmony_ci}; 3118c2ecf20Sopenharmony_ci 3128c2ecf20Sopenharmony_cistruct drm_dp_remote_i2c_write_ack_reply { 3138c2ecf20Sopenharmony_ci u8 port_number; 3148c2ecf20Sopenharmony_ci}; 3158c2ecf20Sopenharmony_ci 3168c2ecf20Sopenharmony_cistruct drm_dp_query_stream_enc_status_ack_reply { 3178c2ecf20Sopenharmony_ci /* Bit[23:16]- Stream Id */ 3188c2ecf20Sopenharmony_ci u8 stream_id; 3198c2ecf20Sopenharmony_ci 3208c2ecf20Sopenharmony_ci /* Bit[15]- Signed */ 3218c2ecf20Sopenharmony_ci bool reply_signed; 3228c2ecf20Sopenharmony_ci 3238c2ecf20Sopenharmony_ci /* Bit[10:8]- Stream Output Sink Type */ 3248c2ecf20Sopenharmony_ci bool unauthorizable_device_present; 3258c2ecf20Sopenharmony_ci bool legacy_device_present; 3268c2ecf20Sopenharmony_ci bool query_capable_device_present; 3278c2ecf20Sopenharmony_ci 3288c2ecf20Sopenharmony_ci /* Bit[12:11]- Stream Output CP Type */ 3298c2ecf20Sopenharmony_ci bool hdcp_1x_device_present; 3308c2ecf20Sopenharmony_ci bool hdcp_2x_device_present; 3318c2ecf20Sopenharmony_ci 3328c2ecf20Sopenharmony_ci /* Bit[4]- Stream Authentication */ 3338c2ecf20Sopenharmony_ci bool auth_completed; 3348c2ecf20Sopenharmony_ci 3358c2ecf20Sopenharmony_ci /* Bit[3]- Stream Encryption */ 3368c2ecf20Sopenharmony_ci bool encryption_enabled; 3378c2ecf20Sopenharmony_ci 3388c2ecf20Sopenharmony_ci /* Bit[2]- Stream Repeater Function Present */ 3398c2ecf20Sopenharmony_ci bool repeater_present; 3408c2ecf20Sopenharmony_ci 3418c2ecf20Sopenharmony_ci /* Bit[1:0]- Stream State */ 3428c2ecf20Sopenharmony_ci u8 state; 3438c2ecf20Sopenharmony_ci}; 3448c2ecf20Sopenharmony_ci 3458c2ecf20Sopenharmony_ci#define DRM_DP_MAX_SDP_STREAMS 16 3468c2ecf20Sopenharmony_cistruct drm_dp_allocate_payload { 3478c2ecf20Sopenharmony_ci u8 port_number; 3488c2ecf20Sopenharmony_ci u8 number_sdp_streams; 3498c2ecf20Sopenharmony_ci u8 vcpi; 3508c2ecf20Sopenharmony_ci u16 pbn; 3518c2ecf20Sopenharmony_ci u8 sdp_stream_sink[DRM_DP_MAX_SDP_STREAMS]; 3528c2ecf20Sopenharmony_ci}; 3538c2ecf20Sopenharmony_ci 3548c2ecf20Sopenharmony_cistruct drm_dp_allocate_payload_ack_reply { 3558c2ecf20Sopenharmony_ci u8 port_number; 3568c2ecf20Sopenharmony_ci u8 vcpi; 3578c2ecf20Sopenharmony_ci u16 allocated_pbn; 3588c2ecf20Sopenharmony_ci}; 3598c2ecf20Sopenharmony_ci 3608c2ecf20Sopenharmony_cistruct drm_dp_connection_status_notify { 3618c2ecf20Sopenharmony_ci u8 guid[16]; 3628c2ecf20Sopenharmony_ci u8 port_number; 3638c2ecf20Sopenharmony_ci bool legacy_device_plug_status; 3648c2ecf20Sopenharmony_ci bool displayport_device_plug_status; 3658c2ecf20Sopenharmony_ci bool message_capability_status; 3668c2ecf20Sopenharmony_ci bool input_port; 3678c2ecf20Sopenharmony_ci u8 peer_device_type; 3688c2ecf20Sopenharmony_ci}; 3698c2ecf20Sopenharmony_ci 3708c2ecf20Sopenharmony_cistruct drm_dp_remote_dpcd_read { 3718c2ecf20Sopenharmony_ci u8 port_number; 3728c2ecf20Sopenharmony_ci u32 dpcd_address; 3738c2ecf20Sopenharmony_ci u8 num_bytes; 3748c2ecf20Sopenharmony_ci}; 3758c2ecf20Sopenharmony_ci 3768c2ecf20Sopenharmony_cistruct drm_dp_remote_dpcd_write { 3778c2ecf20Sopenharmony_ci u8 port_number; 3788c2ecf20Sopenharmony_ci u32 dpcd_address; 3798c2ecf20Sopenharmony_ci u8 num_bytes; 3808c2ecf20Sopenharmony_ci u8 *bytes; 3818c2ecf20Sopenharmony_ci}; 3828c2ecf20Sopenharmony_ci 3838c2ecf20Sopenharmony_ci#define DP_REMOTE_I2C_READ_MAX_TRANSACTIONS 4 3848c2ecf20Sopenharmony_cistruct drm_dp_remote_i2c_read { 3858c2ecf20Sopenharmony_ci u8 num_transactions; 3868c2ecf20Sopenharmony_ci u8 port_number; 3878c2ecf20Sopenharmony_ci struct drm_dp_remote_i2c_read_tx { 3888c2ecf20Sopenharmony_ci u8 i2c_dev_id; 3898c2ecf20Sopenharmony_ci u8 num_bytes; 3908c2ecf20Sopenharmony_ci u8 *bytes; 3918c2ecf20Sopenharmony_ci u8 no_stop_bit; 3928c2ecf20Sopenharmony_ci u8 i2c_transaction_delay; 3938c2ecf20Sopenharmony_ci } transactions[DP_REMOTE_I2C_READ_MAX_TRANSACTIONS]; 3948c2ecf20Sopenharmony_ci u8 read_i2c_device_id; 3958c2ecf20Sopenharmony_ci u8 num_bytes_read; 3968c2ecf20Sopenharmony_ci}; 3978c2ecf20Sopenharmony_ci 3988c2ecf20Sopenharmony_cistruct drm_dp_remote_i2c_write { 3998c2ecf20Sopenharmony_ci u8 port_number; 4008c2ecf20Sopenharmony_ci u8 write_i2c_device_id; 4018c2ecf20Sopenharmony_ci u8 num_bytes; 4028c2ecf20Sopenharmony_ci u8 *bytes; 4038c2ecf20Sopenharmony_ci}; 4048c2ecf20Sopenharmony_ci 4058c2ecf20Sopenharmony_cistruct drm_dp_query_stream_enc_status { 4068c2ecf20Sopenharmony_ci u8 stream_id; 4078c2ecf20Sopenharmony_ci u8 client_id[7]; /* 56-bit nonce */ 4088c2ecf20Sopenharmony_ci u8 stream_event; 4098c2ecf20Sopenharmony_ci bool valid_stream_event; 4108c2ecf20Sopenharmony_ci u8 stream_behavior; 4118c2ecf20Sopenharmony_ci u8 valid_stream_behavior; 4128c2ecf20Sopenharmony_ci}; 4138c2ecf20Sopenharmony_ci 4148c2ecf20Sopenharmony_ci/* this covers ENUM_RESOURCES, POWER_DOWN_PHY, POWER_UP_PHY */ 4158c2ecf20Sopenharmony_cistruct drm_dp_port_number_req { 4168c2ecf20Sopenharmony_ci u8 port_number; 4178c2ecf20Sopenharmony_ci}; 4188c2ecf20Sopenharmony_ci 4198c2ecf20Sopenharmony_cistruct drm_dp_enum_path_resources_ack_reply { 4208c2ecf20Sopenharmony_ci u8 port_number; 4218c2ecf20Sopenharmony_ci bool fec_capable; 4228c2ecf20Sopenharmony_ci u16 full_payload_bw_number; 4238c2ecf20Sopenharmony_ci u16 avail_payload_bw_number; 4248c2ecf20Sopenharmony_ci}; 4258c2ecf20Sopenharmony_ci 4268c2ecf20Sopenharmony_ci/* covers POWER_DOWN_PHY, POWER_UP_PHY */ 4278c2ecf20Sopenharmony_cistruct drm_dp_port_number_rep { 4288c2ecf20Sopenharmony_ci u8 port_number; 4298c2ecf20Sopenharmony_ci}; 4308c2ecf20Sopenharmony_ci 4318c2ecf20Sopenharmony_cistruct drm_dp_query_payload { 4328c2ecf20Sopenharmony_ci u8 port_number; 4338c2ecf20Sopenharmony_ci u8 vcpi; 4348c2ecf20Sopenharmony_ci}; 4358c2ecf20Sopenharmony_ci 4368c2ecf20Sopenharmony_cistruct drm_dp_resource_status_notify { 4378c2ecf20Sopenharmony_ci u8 port_number; 4388c2ecf20Sopenharmony_ci u8 guid[16]; 4398c2ecf20Sopenharmony_ci u16 available_pbn; 4408c2ecf20Sopenharmony_ci}; 4418c2ecf20Sopenharmony_ci 4428c2ecf20Sopenharmony_cistruct drm_dp_query_payload_ack_reply { 4438c2ecf20Sopenharmony_ci u8 port_number; 4448c2ecf20Sopenharmony_ci u16 allocated_pbn; 4458c2ecf20Sopenharmony_ci}; 4468c2ecf20Sopenharmony_ci 4478c2ecf20Sopenharmony_cistruct drm_dp_sideband_msg_req_body { 4488c2ecf20Sopenharmony_ci u8 req_type; 4498c2ecf20Sopenharmony_ci union ack_req { 4508c2ecf20Sopenharmony_ci struct drm_dp_connection_status_notify conn_stat; 4518c2ecf20Sopenharmony_ci struct drm_dp_port_number_req port_num; 4528c2ecf20Sopenharmony_ci struct drm_dp_resource_status_notify resource_stat; 4538c2ecf20Sopenharmony_ci 4548c2ecf20Sopenharmony_ci struct drm_dp_query_payload query_payload; 4558c2ecf20Sopenharmony_ci struct drm_dp_allocate_payload allocate_payload; 4568c2ecf20Sopenharmony_ci 4578c2ecf20Sopenharmony_ci struct drm_dp_remote_dpcd_read dpcd_read; 4588c2ecf20Sopenharmony_ci struct drm_dp_remote_dpcd_write dpcd_write; 4598c2ecf20Sopenharmony_ci 4608c2ecf20Sopenharmony_ci struct drm_dp_remote_i2c_read i2c_read; 4618c2ecf20Sopenharmony_ci struct drm_dp_remote_i2c_write i2c_write; 4628c2ecf20Sopenharmony_ci 4638c2ecf20Sopenharmony_ci struct drm_dp_query_stream_enc_status enc_status; 4648c2ecf20Sopenharmony_ci } u; 4658c2ecf20Sopenharmony_ci}; 4668c2ecf20Sopenharmony_ci 4678c2ecf20Sopenharmony_cistruct drm_dp_sideband_msg_reply_body { 4688c2ecf20Sopenharmony_ci u8 reply_type; 4698c2ecf20Sopenharmony_ci u8 req_type; 4708c2ecf20Sopenharmony_ci union ack_replies { 4718c2ecf20Sopenharmony_ci struct drm_dp_nak_reply nak; 4728c2ecf20Sopenharmony_ci struct drm_dp_link_address_ack_reply link_addr; 4738c2ecf20Sopenharmony_ci struct drm_dp_port_number_rep port_number; 4748c2ecf20Sopenharmony_ci 4758c2ecf20Sopenharmony_ci struct drm_dp_enum_path_resources_ack_reply path_resources; 4768c2ecf20Sopenharmony_ci struct drm_dp_allocate_payload_ack_reply allocate_payload; 4778c2ecf20Sopenharmony_ci struct drm_dp_query_payload_ack_reply query_payload; 4788c2ecf20Sopenharmony_ci 4798c2ecf20Sopenharmony_ci struct drm_dp_remote_dpcd_read_ack_reply remote_dpcd_read_ack; 4808c2ecf20Sopenharmony_ci struct drm_dp_remote_dpcd_write_ack_reply remote_dpcd_write_ack; 4818c2ecf20Sopenharmony_ci struct drm_dp_remote_dpcd_write_nak_reply remote_dpcd_write_nack; 4828c2ecf20Sopenharmony_ci 4838c2ecf20Sopenharmony_ci struct drm_dp_remote_i2c_read_ack_reply remote_i2c_read_ack; 4848c2ecf20Sopenharmony_ci struct drm_dp_remote_i2c_read_nak_reply remote_i2c_read_nack; 4858c2ecf20Sopenharmony_ci struct drm_dp_remote_i2c_write_ack_reply remote_i2c_write_ack; 4868c2ecf20Sopenharmony_ci 4878c2ecf20Sopenharmony_ci struct drm_dp_query_stream_enc_status_ack_reply enc_status; 4888c2ecf20Sopenharmony_ci } u; 4898c2ecf20Sopenharmony_ci}; 4908c2ecf20Sopenharmony_ci 4918c2ecf20Sopenharmony_ci/* msg is queued to be put into a slot */ 4928c2ecf20Sopenharmony_ci#define DRM_DP_SIDEBAND_TX_QUEUED 0 4938c2ecf20Sopenharmony_ci/* msg has started transmitting on a slot - still on msgq */ 4948c2ecf20Sopenharmony_ci#define DRM_DP_SIDEBAND_TX_START_SEND 1 4958c2ecf20Sopenharmony_ci/* msg has finished transmitting on a slot - removed from msgq only in slot */ 4968c2ecf20Sopenharmony_ci#define DRM_DP_SIDEBAND_TX_SENT 2 4978c2ecf20Sopenharmony_ci/* msg has received a response - removed from slot */ 4988c2ecf20Sopenharmony_ci#define DRM_DP_SIDEBAND_TX_RX 3 4998c2ecf20Sopenharmony_ci#define DRM_DP_SIDEBAND_TX_TIMEOUT 4 5008c2ecf20Sopenharmony_ci 5018c2ecf20Sopenharmony_cistruct drm_dp_sideband_msg_tx { 5028c2ecf20Sopenharmony_ci u8 msg[256]; 5038c2ecf20Sopenharmony_ci u8 chunk[48]; 5048c2ecf20Sopenharmony_ci u8 cur_offset; 5058c2ecf20Sopenharmony_ci u8 cur_len; 5068c2ecf20Sopenharmony_ci struct drm_dp_mst_branch *dst; 5078c2ecf20Sopenharmony_ci struct list_head next; 5088c2ecf20Sopenharmony_ci int seqno; 5098c2ecf20Sopenharmony_ci int state; 5108c2ecf20Sopenharmony_ci bool path_msg; 5118c2ecf20Sopenharmony_ci struct drm_dp_sideband_msg_reply_body reply; 5128c2ecf20Sopenharmony_ci}; 5138c2ecf20Sopenharmony_ci 5148c2ecf20Sopenharmony_ci/* sideband msg handler */ 5158c2ecf20Sopenharmony_cistruct drm_dp_mst_topology_mgr; 5168c2ecf20Sopenharmony_cistruct drm_dp_mst_topology_cbs { 5178c2ecf20Sopenharmony_ci /* create a connector for a port */ 5188c2ecf20Sopenharmony_ci struct drm_connector *(*add_connector)(struct drm_dp_mst_topology_mgr *mgr, struct drm_dp_mst_port *port, const char *path); 5198c2ecf20Sopenharmony_ci /* 5208c2ecf20Sopenharmony_ci * Checks for any pending MST interrupts, passing them to MST core for 5218c2ecf20Sopenharmony_ci * processing, the same way an HPD IRQ pulse handler would do this. 5228c2ecf20Sopenharmony_ci * If provided MST core calls this callback from a poll-waiting loop 5238c2ecf20Sopenharmony_ci * when waiting for MST down message replies. The driver is expected 5248c2ecf20Sopenharmony_ci * to guard against a race between this callback and the driver's HPD 5258c2ecf20Sopenharmony_ci * IRQ pulse handler. 5268c2ecf20Sopenharmony_ci */ 5278c2ecf20Sopenharmony_ci void (*poll_hpd_irq)(struct drm_dp_mst_topology_mgr *mgr); 5288c2ecf20Sopenharmony_ci}; 5298c2ecf20Sopenharmony_ci 5308c2ecf20Sopenharmony_ci#define DP_MAX_PAYLOAD (sizeof(unsigned long) * 8) 5318c2ecf20Sopenharmony_ci 5328c2ecf20Sopenharmony_ci#define DP_PAYLOAD_LOCAL 1 5338c2ecf20Sopenharmony_ci#define DP_PAYLOAD_REMOTE 2 5348c2ecf20Sopenharmony_ci#define DP_PAYLOAD_DELETE_LOCAL 3 5358c2ecf20Sopenharmony_ci 5368c2ecf20Sopenharmony_cistruct drm_dp_payload { 5378c2ecf20Sopenharmony_ci int payload_state; 5388c2ecf20Sopenharmony_ci int start_slot; 5398c2ecf20Sopenharmony_ci int num_slots; 5408c2ecf20Sopenharmony_ci int vcpi; 5418c2ecf20Sopenharmony_ci}; 5428c2ecf20Sopenharmony_ci 5438c2ecf20Sopenharmony_ci#define to_dp_mst_topology_state(x) container_of(x, struct drm_dp_mst_topology_state, base) 5448c2ecf20Sopenharmony_ci 5458c2ecf20Sopenharmony_cistruct drm_dp_vcpi_allocation { 5468c2ecf20Sopenharmony_ci struct drm_dp_mst_port *port; 5478c2ecf20Sopenharmony_ci int vcpi; 5488c2ecf20Sopenharmony_ci int pbn; 5498c2ecf20Sopenharmony_ci bool dsc_enabled; 5508c2ecf20Sopenharmony_ci struct list_head next; 5518c2ecf20Sopenharmony_ci}; 5528c2ecf20Sopenharmony_ci 5538c2ecf20Sopenharmony_cistruct drm_dp_mst_topology_state { 5548c2ecf20Sopenharmony_ci struct drm_private_state base; 5558c2ecf20Sopenharmony_ci struct list_head vcpis; 5568c2ecf20Sopenharmony_ci struct drm_dp_mst_topology_mgr *mgr; 5578c2ecf20Sopenharmony_ci}; 5588c2ecf20Sopenharmony_ci 5598c2ecf20Sopenharmony_ci#define to_dp_mst_topology_mgr(x) container_of(x, struct drm_dp_mst_topology_mgr, base) 5608c2ecf20Sopenharmony_ci 5618c2ecf20Sopenharmony_ci/** 5628c2ecf20Sopenharmony_ci * struct drm_dp_mst_topology_mgr - DisplayPort MST manager 5638c2ecf20Sopenharmony_ci * 5648c2ecf20Sopenharmony_ci * This struct represents the toplevel displayport MST topology manager. 5658c2ecf20Sopenharmony_ci * There should be one instance of this for every MST capable DP connector 5668c2ecf20Sopenharmony_ci * on the GPU. 5678c2ecf20Sopenharmony_ci */ 5688c2ecf20Sopenharmony_cistruct drm_dp_mst_topology_mgr { 5698c2ecf20Sopenharmony_ci /** 5708c2ecf20Sopenharmony_ci * @base: Base private object for atomic 5718c2ecf20Sopenharmony_ci */ 5728c2ecf20Sopenharmony_ci struct drm_private_obj base; 5738c2ecf20Sopenharmony_ci 5748c2ecf20Sopenharmony_ci /** 5758c2ecf20Sopenharmony_ci * @dev: device pointer for adding i2c devices etc. 5768c2ecf20Sopenharmony_ci */ 5778c2ecf20Sopenharmony_ci struct drm_device *dev; 5788c2ecf20Sopenharmony_ci /** 5798c2ecf20Sopenharmony_ci * @cbs: callbacks for connector addition and destruction. 5808c2ecf20Sopenharmony_ci */ 5818c2ecf20Sopenharmony_ci const struct drm_dp_mst_topology_cbs *cbs; 5828c2ecf20Sopenharmony_ci /** 5838c2ecf20Sopenharmony_ci * @max_dpcd_transaction_bytes: maximum number of bytes to read/write 5848c2ecf20Sopenharmony_ci * in one go. 5858c2ecf20Sopenharmony_ci */ 5868c2ecf20Sopenharmony_ci int max_dpcd_transaction_bytes; 5878c2ecf20Sopenharmony_ci /** 5888c2ecf20Sopenharmony_ci * @aux: AUX channel for the DP MST connector this topolgy mgr is 5898c2ecf20Sopenharmony_ci * controlling. 5908c2ecf20Sopenharmony_ci */ 5918c2ecf20Sopenharmony_ci struct drm_dp_aux *aux; 5928c2ecf20Sopenharmony_ci /** 5938c2ecf20Sopenharmony_ci * @max_payloads: maximum number of payloads the GPU can generate. 5948c2ecf20Sopenharmony_ci */ 5958c2ecf20Sopenharmony_ci int max_payloads; 5968c2ecf20Sopenharmony_ci /** 5978c2ecf20Sopenharmony_ci * @conn_base_id: DRM connector ID this mgr is connected to. Only used 5988c2ecf20Sopenharmony_ci * to build the MST connector path value. 5998c2ecf20Sopenharmony_ci */ 6008c2ecf20Sopenharmony_ci int conn_base_id; 6018c2ecf20Sopenharmony_ci 6028c2ecf20Sopenharmony_ci /** 6038c2ecf20Sopenharmony_ci * @up_req_recv: Message receiver state for up requests. 6048c2ecf20Sopenharmony_ci */ 6058c2ecf20Sopenharmony_ci struct drm_dp_sideband_msg_rx up_req_recv; 6068c2ecf20Sopenharmony_ci 6078c2ecf20Sopenharmony_ci /** 6088c2ecf20Sopenharmony_ci * @down_rep_recv: Message receiver state for replies to down 6098c2ecf20Sopenharmony_ci * requests. 6108c2ecf20Sopenharmony_ci */ 6118c2ecf20Sopenharmony_ci struct drm_dp_sideband_msg_rx down_rep_recv; 6128c2ecf20Sopenharmony_ci 6138c2ecf20Sopenharmony_ci /** 6148c2ecf20Sopenharmony_ci * @lock: protects @mst_state, @mst_primary, @dpcd, and 6158c2ecf20Sopenharmony_ci * @payload_id_table_cleared. 6168c2ecf20Sopenharmony_ci */ 6178c2ecf20Sopenharmony_ci struct mutex lock; 6188c2ecf20Sopenharmony_ci 6198c2ecf20Sopenharmony_ci /** 6208c2ecf20Sopenharmony_ci * @probe_lock: Prevents @work and @up_req_work, the only writers of 6218c2ecf20Sopenharmony_ci * &drm_dp_mst_port.mstb and &drm_dp_mst_branch.ports, from racing 6228c2ecf20Sopenharmony_ci * while they update the topology. 6238c2ecf20Sopenharmony_ci */ 6248c2ecf20Sopenharmony_ci struct mutex probe_lock; 6258c2ecf20Sopenharmony_ci 6268c2ecf20Sopenharmony_ci /** 6278c2ecf20Sopenharmony_ci * @mst_state: If this manager is enabled for an MST capable port. False 6288c2ecf20Sopenharmony_ci * if no MST sink/branch devices is connected. 6298c2ecf20Sopenharmony_ci */ 6308c2ecf20Sopenharmony_ci bool mst_state : 1; 6318c2ecf20Sopenharmony_ci 6328c2ecf20Sopenharmony_ci /** 6338c2ecf20Sopenharmony_ci * @payload_id_table_cleared: Whether or not we've cleared the payload 6348c2ecf20Sopenharmony_ci * ID table for @mst_primary. Protected by @lock. 6358c2ecf20Sopenharmony_ci */ 6368c2ecf20Sopenharmony_ci bool payload_id_table_cleared : 1; 6378c2ecf20Sopenharmony_ci 6388c2ecf20Sopenharmony_ci /** 6398c2ecf20Sopenharmony_ci * @mst_primary: Pointer to the primary/first branch device. 6408c2ecf20Sopenharmony_ci */ 6418c2ecf20Sopenharmony_ci struct drm_dp_mst_branch *mst_primary; 6428c2ecf20Sopenharmony_ci 6438c2ecf20Sopenharmony_ci /** 6448c2ecf20Sopenharmony_ci * @dpcd: Cache of DPCD for primary port. 6458c2ecf20Sopenharmony_ci */ 6468c2ecf20Sopenharmony_ci u8 dpcd[DP_RECEIVER_CAP_SIZE]; 6478c2ecf20Sopenharmony_ci /** 6488c2ecf20Sopenharmony_ci * @sink_count: Sink count from DEVICE_SERVICE_IRQ_VECTOR_ESI0. 6498c2ecf20Sopenharmony_ci */ 6508c2ecf20Sopenharmony_ci u8 sink_count; 6518c2ecf20Sopenharmony_ci /** 6528c2ecf20Sopenharmony_ci * @pbn_div: PBN to slots divisor. 6538c2ecf20Sopenharmony_ci */ 6548c2ecf20Sopenharmony_ci int pbn_div; 6558c2ecf20Sopenharmony_ci 6568c2ecf20Sopenharmony_ci /** 6578c2ecf20Sopenharmony_ci * @funcs: Atomic helper callbacks 6588c2ecf20Sopenharmony_ci */ 6598c2ecf20Sopenharmony_ci const struct drm_private_state_funcs *funcs; 6608c2ecf20Sopenharmony_ci 6618c2ecf20Sopenharmony_ci /** 6628c2ecf20Sopenharmony_ci * @qlock: protects @tx_msg_downq and &drm_dp_sideband_msg_tx.state 6638c2ecf20Sopenharmony_ci */ 6648c2ecf20Sopenharmony_ci struct mutex qlock; 6658c2ecf20Sopenharmony_ci 6668c2ecf20Sopenharmony_ci /** 6678c2ecf20Sopenharmony_ci * @tx_msg_downq: List of pending down requests 6688c2ecf20Sopenharmony_ci */ 6698c2ecf20Sopenharmony_ci struct list_head tx_msg_downq; 6708c2ecf20Sopenharmony_ci 6718c2ecf20Sopenharmony_ci /** 6728c2ecf20Sopenharmony_ci * @payload_lock: Protect payload information. 6738c2ecf20Sopenharmony_ci */ 6748c2ecf20Sopenharmony_ci struct mutex payload_lock; 6758c2ecf20Sopenharmony_ci /** 6768c2ecf20Sopenharmony_ci * @proposed_vcpis: Array of pointers for the new VCPI allocation. The 6778c2ecf20Sopenharmony_ci * VCPI structure itself is &drm_dp_mst_port.vcpi, and the size of 6788c2ecf20Sopenharmony_ci * this array is determined by @max_payloads. 6798c2ecf20Sopenharmony_ci */ 6808c2ecf20Sopenharmony_ci struct drm_dp_vcpi **proposed_vcpis; 6818c2ecf20Sopenharmony_ci /** 6828c2ecf20Sopenharmony_ci * @payloads: Array of payloads. The size of this array is determined 6838c2ecf20Sopenharmony_ci * by @max_payloads. 6848c2ecf20Sopenharmony_ci */ 6858c2ecf20Sopenharmony_ci struct drm_dp_payload *payloads; 6868c2ecf20Sopenharmony_ci /** 6878c2ecf20Sopenharmony_ci * @payload_mask: Elements of @payloads actually in use. Since 6888c2ecf20Sopenharmony_ci * reallocation of active outputs isn't possible gaps can be created by 6898c2ecf20Sopenharmony_ci * disabling outputs out of order compared to how they've been enabled. 6908c2ecf20Sopenharmony_ci */ 6918c2ecf20Sopenharmony_ci unsigned long payload_mask; 6928c2ecf20Sopenharmony_ci /** 6938c2ecf20Sopenharmony_ci * @vcpi_mask: Similar to @payload_mask, but for @proposed_vcpis. 6948c2ecf20Sopenharmony_ci */ 6958c2ecf20Sopenharmony_ci unsigned long vcpi_mask; 6968c2ecf20Sopenharmony_ci 6978c2ecf20Sopenharmony_ci /** 6988c2ecf20Sopenharmony_ci * @tx_waitq: Wait to queue stall for the tx worker. 6998c2ecf20Sopenharmony_ci */ 7008c2ecf20Sopenharmony_ci wait_queue_head_t tx_waitq; 7018c2ecf20Sopenharmony_ci /** 7028c2ecf20Sopenharmony_ci * @work: Probe work. 7038c2ecf20Sopenharmony_ci */ 7048c2ecf20Sopenharmony_ci struct work_struct work; 7058c2ecf20Sopenharmony_ci /** 7068c2ecf20Sopenharmony_ci * @tx_work: Sideband transmit worker. This can nest within the main 7078c2ecf20Sopenharmony_ci * @work worker for each transaction @work launches. 7088c2ecf20Sopenharmony_ci */ 7098c2ecf20Sopenharmony_ci struct work_struct tx_work; 7108c2ecf20Sopenharmony_ci 7118c2ecf20Sopenharmony_ci /** 7128c2ecf20Sopenharmony_ci * @destroy_port_list: List of to be destroyed connectors. 7138c2ecf20Sopenharmony_ci */ 7148c2ecf20Sopenharmony_ci struct list_head destroy_port_list; 7158c2ecf20Sopenharmony_ci /** 7168c2ecf20Sopenharmony_ci * @destroy_branch_device_list: List of to be destroyed branch 7178c2ecf20Sopenharmony_ci * devices. 7188c2ecf20Sopenharmony_ci */ 7198c2ecf20Sopenharmony_ci struct list_head destroy_branch_device_list; 7208c2ecf20Sopenharmony_ci /** 7218c2ecf20Sopenharmony_ci * @delayed_destroy_lock: Protects @destroy_port_list and 7228c2ecf20Sopenharmony_ci * @destroy_branch_device_list. 7238c2ecf20Sopenharmony_ci */ 7248c2ecf20Sopenharmony_ci struct mutex delayed_destroy_lock; 7258c2ecf20Sopenharmony_ci 7268c2ecf20Sopenharmony_ci /** 7278c2ecf20Sopenharmony_ci * @delayed_destroy_wq: Workqueue used for delayed_destroy_work items. 7288c2ecf20Sopenharmony_ci * A dedicated WQ makes it possible to drain any requeued work items 7298c2ecf20Sopenharmony_ci * on it. 7308c2ecf20Sopenharmony_ci */ 7318c2ecf20Sopenharmony_ci struct workqueue_struct *delayed_destroy_wq; 7328c2ecf20Sopenharmony_ci 7338c2ecf20Sopenharmony_ci /** 7348c2ecf20Sopenharmony_ci * @delayed_destroy_work: Work item to destroy MST port and branch 7358c2ecf20Sopenharmony_ci * devices, needed to avoid locking inversion. 7368c2ecf20Sopenharmony_ci */ 7378c2ecf20Sopenharmony_ci struct work_struct delayed_destroy_work; 7388c2ecf20Sopenharmony_ci 7398c2ecf20Sopenharmony_ci /** 7408c2ecf20Sopenharmony_ci * @up_req_list: List of pending up requests from the topology that 7418c2ecf20Sopenharmony_ci * need to be processed, in chronological order. 7428c2ecf20Sopenharmony_ci */ 7438c2ecf20Sopenharmony_ci struct list_head up_req_list; 7448c2ecf20Sopenharmony_ci /** 7458c2ecf20Sopenharmony_ci * @up_req_lock: Protects @up_req_list 7468c2ecf20Sopenharmony_ci */ 7478c2ecf20Sopenharmony_ci struct mutex up_req_lock; 7488c2ecf20Sopenharmony_ci /** 7498c2ecf20Sopenharmony_ci * @up_req_work: Work item to process up requests received from the 7508c2ecf20Sopenharmony_ci * topology. Needed to avoid blocking hotplug handling and sideband 7518c2ecf20Sopenharmony_ci * transmissions. 7528c2ecf20Sopenharmony_ci */ 7538c2ecf20Sopenharmony_ci struct work_struct up_req_work; 7548c2ecf20Sopenharmony_ci 7558c2ecf20Sopenharmony_ci#if IS_ENABLED(CONFIG_DRM_DEBUG_DP_MST_TOPOLOGY_REFS) 7568c2ecf20Sopenharmony_ci /** 7578c2ecf20Sopenharmony_ci * @topology_ref_history_lock: protects 7588c2ecf20Sopenharmony_ci * &drm_dp_mst_port.topology_ref_history and 7598c2ecf20Sopenharmony_ci * &drm_dp_mst_branch.topology_ref_history. 7608c2ecf20Sopenharmony_ci */ 7618c2ecf20Sopenharmony_ci struct mutex topology_ref_history_lock; 7628c2ecf20Sopenharmony_ci#endif 7638c2ecf20Sopenharmony_ci}; 7648c2ecf20Sopenharmony_ci 7658c2ecf20Sopenharmony_ciint drm_dp_mst_topology_mgr_init(struct drm_dp_mst_topology_mgr *mgr, 7668c2ecf20Sopenharmony_ci struct drm_device *dev, struct drm_dp_aux *aux, 7678c2ecf20Sopenharmony_ci int max_dpcd_transaction_bytes, 7688c2ecf20Sopenharmony_ci int max_payloads, int conn_base_id); 7698c2ecf20Sopenharmony_ci 7708c2ecf20Sopenharmony_civoid drm_dp_mst_topology_mgr_destroy(struct drm_dp_mst_topology_mgr *mgr); 7718c2ecf20Sopenharmony_ci 7728c2ecf20Sopenharmony_cibool drm_dp_read_mst_cap(struct drm_dp_aux *aux, const u8 dpcd[DP_RECEIVER_CAP_SIZE]); 7738c2ecf20Sopenharmony_ciint drm_dp_mst_topology_mgr_set_mst(struct drm_dp_mst_topology_mgr *mgr, bool mst_state); 7748c2ecf20Sopenharmony_ci 7758c2ecf20Sopenharmony_ciint drm_dp_mst_hpd_irq(struct drm_dp_mst_topology_mgr *mgr, u8 *esi, bool *handled); 7768c2ecf20Sopenharmony_ci 7778c2ecf20Sopenharmony_ci 7788c2ecf20Sopenharmony_ciint 7798c2ecf20Sopenharmony_cidrm_dp_mst_detect_port(struct drm_connector *connector, 7808c2ecf20Sopenharmony_ci struct drm_modeset_acquire_ctx *ctx, 7818c2ecf20Sopenharmony_ci struct drm_dp_mst_topology_mgr *mgr, 7828c2ecf20Sopenharmony_ci struct drm_dp_mst_port *port); 7838c2ecf20Sopenharmony_ci 7848c2ecf20Sopenharmony_cistruct edid *drm_dp_mst_get_edid(struct drm_connector *connector, struct drm_dp_mst_topology_mgr *mgr, struct drm_dp_mst_port *port); 7858c2ecf20Sopenharmony_ci 7868c2ecf20Sopenharmony_ciint drm_dp_get_vc_payload_bw(int link_rate, int link_lane_count); 7878c2ecf20Sopenharmony_ci 7888c2ecf20Sopenharmony_ciint drm_dp_calc_pbn_mode(int clock, int bpp, bool dsc); 7898c2ecf20Sopenharmony_ci 7908c2ecf20Sopenharmony_cibool drm_dp_mst_allocate_vcpi(struct drm_dp_mst_topology_mgr *mgr, 7918c2ecf20Sopenharmony_ci struct drm_dp_mst_port *port, int pbn, int slots); 7928c2ecf20Sopenharmony_ci 7938c2ecf20Sopenharmony_ciint drm_dp_mst_get_vcpi_slots(struct drm_dp_mst_topology_mgr *mgr, struct drm_dp_mst_port *port); 7948c2ecf20Sopenharmony_ci 7958c2ecf20Sopenharmony_ci 7968c2ecf20Sopenharmony_civoid drm_dp_mst_reset_vcpi_slots(struct drm_dp_mst_topology_mgr *mgr, struct drm_dp_mst_port *port); 7978c2ecf20Sopenharmony_ci 7988c2ecf20Sopenharmony_ci 7998c2ecf20Sopenharmony_civoid drm_dp_mst_deallocate_vcpi(struct drm_dp_mst_topology_mgr *mgr, 8008c2ecf20Sopenharmony_ci struct drm_dp_mst_port *port); 8018c2ecf20Sopenharmony_ci 8028c2ecf20Sopenharmony_ci 8038c2ecf20Sopenharmony_ciint drm_dp_find_vcpi_slots(struct drm_dp_mst_topology_mgr *mgr, 8048c2ecf20Sopenharmony_ci int pbn); 8058c2ecf20Sopenharmony_ci 8068c2ecf20Sopenharmony_ci 8078c2ecf20Sopenharmony_ciint drm_dp_update_payload_part1(struct drm_dp_mst_topology_mgr *mgr); 8088c2ecf20Sopenharmony_ci 8098c2ecf20Sopenharmony_ci 8108c2ecf20Sopenharmony_ciint drm_dp_update_payload_part2(struct drm_dp_mst_topology_mgr *mgr); 8118c2ecf20Sopenharmony_ci 8128c2ecf20Sopenharmony_ciint drm_dp_check_act_status(struct drm_dp_mst_topology_mgr *mgr); 8138c2ecf20Sopenharmony_ci 8148c2ecf20Sopenharmony_civoid drm_dp_mst_dump_topology(struct seq_file *m, 8158c2ecf20Sopenharmony_ci struct drm_dp_mst_topology_mgr *mgr); 8168c2ecf20Sopenharmony_ci 8178c2ecf20Sopenharmony_civoid drm_dp_mst_topology_mgr_suspend(struct drm_dp_mst_topology_mgr *mgr); 8188c2ecf20Sopenharmony_ciint __must_check 8198c2ecf20Sopenharmony_cidrm_dp_mst_topology_mgr_resume(struct drm_dp_mst_topology_mgr *mgr, 8208c2ecf20Sopenharmony_ci bool sync); 8218c2ecf20Sopenharmony_ci 8228c2ecf20Sopenharmony_cissize_t drm_dp_mst_dpcd_read(struct drm_dp_aux *aux, 8238c2ecf20Sopenharmony_ci unsigned int offset, void *buffer, size_t size); 8248c2ecf20Sopenharmony_cissize_t drm_dp_mst_dpcd_write(struct drm_dp_aux *aux, 8258c2ecf20Sopenharmony_ci unsigned int offset, void *buffer, size_t size); 8268c2ecf20Sopenharmony_ci 8278c2ecf20Sopenharmony_ciint drm_dp_mst_connector_late_register(struct drm_connector *connector, 8288c2ecf20Sopenharmony_ci struct drm_dp_mst_port *port); 8298c2ecf20Sopenharmony_civoid drm_dp_mst_connector_early_unregister(struct drm_connector *connector, 8308c2ecf20Sopenharmony_ci struct drm_dp_mst_port *port); 8318c2ecf20Sopenharmony_ci 8328c2ecf20Sopenharmony_cistruct drm_dp_mst_topology_state *drm_atomic_get_mst_topology_state(struct drm_atomic_state *state, 8338c2ecf20Sopenharmony_ci struct drm_dp_mst_topology_mgr *mgr); 8348c2ecf20Sopenharmony_ciint __must_check 8358c2ecf20Sopenharmony_cidrm_dp_atomic_find_vcpi_slots(struct drm_atomic_state *state, 8368c2ecf20Sopenharmony_ci struct drm_dp_mst_topology_mgr *mgr, 8378c2ecf20Sopenharmony_ci struct drm_dp_mst_port *port, int pbn, 8388c2ecf20Sopenharmony_ci int pbn_div); 8398c2ecf20Sopenharmony_ciint drm_dp_mst_atomic_enable_dsc(struct drm_atomic_state *state, 8408c2ecf20Sopenharmony_ci struct drm_dp_mst_port *port, 8418c2ecf20Sopenharmony_ci int pbn, int pbn_div, 8428c2ecf20Sopenharmony_ci bool enable); 8438c2ecf20Sopenharmony_ciint __must_check 8448c2ecf20Sopenharmony_cidrm_dp_mst_add_affected_dsc_crtcs(struct drm_atomic_state *state, 8458c2ecf20Sopenharmony_ci struct drm_dp_mst_topology_mgr *mgr); 8468c2ecf20Sopenharmony_ciint __must_check 8478c2ecf20Sopenharmony_cidrm_dp_atomic_release_vcpi_slots(struct drm_atomic_state *state, 8488c2ecf20Sopenharmony_ci struct drm_dp_mst_topology_mgr *mgr, 8498c2ecf20Sopenharmony_ci struct drm_dp_mst_port *port); 8508c2ecf20Sopenharmony_ciint drm_dp_send_power_updown_phy(struct drm_dp_mst_topology_mgr *mgr, 8518c2ecf20Sopenharmony_ci struct drm_dp_mst_port *port, bool power_up); 8528c2ecf20Sopenharmony_ciint drm_dp_send_query_stream_enc_status(struct drm_dp_mst_topology_mgr *mgr, 8538c2ecf20Sopenharmony_ci struct drm_dp_mst_port *port, 8548c2ecf20Sopenharmony_ci struct drm_dp_query_stream_enc_status_ack_reply *status); 8558c2ecf20Sopenharmony_ciint __must_check drm_dp_mst_atomic_check(struct drm_atomic_state *state); 8568c2ecf20Sopenharmony_ci 8578c2ecf20Sopenharmony_civoid drm_dp_mst_get_port_malloc(struct drm_dp_mst_port *port); 8588c2ecf20Sopenharmony_civoid drm_dp_mst_put_port_malloc(struct drm_dp_mst_port *port); 8598c2ecf20Sopenharmony_ci 8608c2ecf20Sopenharmony_cistruct drm_dp_aux *drm_dp_mst_dsc_aux_for_port(struct drm_dp_mst_port *port); 8618c2ecf20Sopenharmony_ci 8628c2ecf20Sopenharmony_ciextern const struct drm_private_state_funcs drm_dp_mst_topology_state_funcs; 8638c2ecf20Sopenharmony_ci 8648c2ecf20Sopenharmony_ci/** 8658c2ecf20Sopenharmony_ci * __drm_dp_mst_state_iter_get - private atomic state iterator function for 8668c2ecf20Sopenharmony_ci * macro-internal use 8678c2ecf20Sopenharmony_ci * @state: &struct drm_atomic_state pointer 8688c2ecf20Sopenharmony_ci * @mgr: pointer to the &struct drm_dp_mst_topology_mgr iteration cursor 8698c2ecf20Sopenharmony_ci * @old_state: optional pointer to the old &struct drm_dp_mst_topology_state 8708c2ecf20Sopenharmony_ci * iteration cursor 8718c2ecf20Sopenharmony_ci * @new_state: optional pointer to the new &struct drm_dp_mst_topology_state 8728c2ecf20Sopenharmony_ci * iteration cursor 8738c2ecf20Sopenharmony_ci * @i: int iteration cursor, for macro-internal use 8748c2ecf20Sopenharmony_ci * 8758c2ecf20Sopenharmony_ci * Used by for_each_oldnew_mst_mgr_in_state(), 8768c2ecf20Sopenharmony_ci * for_each_old_mst_mgr_in_state(), and for_each_new_mst_mgr_in_state(). Don't 8778c2ecf20Sopenharmony_ci * call this directly. 8788c2ecf20Sopenharmony_ci * 8798c2ecf20Sopenharmony_ci * Returns: 8808c2ecf20Sopenharmony_ci * True if the current &struct drm_private_obj is a &struct 8818c2ecf20Sopenharmony_ci * drm_dp_mst_topology_mgr, false otherwise. 8828c2ecf20Sopenharmony_ci */ 8838c2ecf20Sopenharmony_cistatic inline bool 8848c2ecf20Sopenharmony_ci__drm_dp_mst_state_iter_get(struct drm_atomic_state *state, 8858c2ecf20Sopenharmony_ci struct drm_dp_mst_topology_mgr **mgr, 8868c2ecf20Sopenharmony_ci struct drm_dp_mst_topology_state **old_state, 8878c2ecf20Sopenharmony_ci struct drm_dp_mst_topology_state **new_state, 8888c2ecf20Sopenharmony_ci int i) 8898c2ecf20Sopenharmony_ci{ 8908c2ecf20Sopenharmony_ci struct __drm_private_objs_state *objs_state = &state->private_objs[i]; 8918c2ecf20Sopenharmony_ci 8928c2ecf20Sopenharmony_ci if (objs_state->ptr->funcs != &drm_dp_mst_topology_state_funcs) 8938c2ecf20Sopenharmony_ci return false; 8948c2ecf20Sopenharmony_ci 8958c2ecf20Sopenharmony_ci *mgr = to_dp_mst_topology_mgr(objs_state->ptr); 8968c2ecf20Sopenharmony_ci if (old_state) 8978c2ecf20Sopenharmony_ci *old_state = to_dp_mst_topology_state(objs_state->old_state); 8988c2ecf20Sopenharmony_ci if (new_state) 8998c2ecf20Sopenharmony_ci *new_state = to_dp_mst_topology_state(objs_state->new_state); 9008c2ecf20Sopenharmony_ci 9018c2ecf20Sopenharmony_ci return true; 9028c2ecf20Sopenharmony_ci} 9038c2ecf20Sopenharmony_ci 9048c2ecf20Sopenharmony_ci/** 9058c2ecf20Sopenharmony_ci * for_each_oldnew_mst_mgr_in_state - iterate over all DP MST topology 9068c2ecf20Sopenharmony_ci * managers in an atomic update 9078c2ecf20Sopenharmony_ci * @__state: &struct drm_atomic_state pointer 9088c2ecf20Sopenharmony_ci * @mgr: &struct drm_dp_mst_topology_mgr iteration cursor 9098c2ecf20Sopenharmony_ci * @old_state: &struct drm_dp_mst_topology_state iteration cursor for the old 9108c2ecf20Sopenharmony_ci * state 9118c2ecf20Sopenharmony_ci * @new_state: &struct drm_dp_mst_topology_state iteration cursor for the new 9128c2ecf20Sopenharmony_ci * state 9138c2ecf20Sopenharmony_ci * @__i: int iteration cursor, for macro-internal use 9148c2ecf20Sopenharmony_ci * 9158c2ecf20Sopenharmony_ci * This iterates over all DRM DP MST topology managers in an atomic update, 9168c2ecf20Sopenharmony_ci * tracking both old and new state. This is useful in places where the state 9178c2ecf20Sopenharmony_ci * delta needs to be considered, for example in atomic check functions. 9188c2ecf20Sopenharmony_ci */ 9198c2ecf20Sopenharmony_ci#define for_each_oldnew_mst_mgr_in_state(__state, mgr, old_state, new_state, __i) \ 9208c2ecf20Sopenharmony_ci for ((__i) = 0; (__i) < (__state)->num_private_objs; (__i)++) \ 9218c2ecf20Sopenharmony_ci for_each_if(__drm_dp_mst_state_iter_get((__state), &(mgr), &(old_state), &(new_state), (__i))) 9228c2ecf20Sopenharmony_ci 9238c2ecf20Sopenharmony_ci/** 9248c2ecf20Sopenharmony_ci * for_each_old_mst_mgr_in_state - iterate over all DP MST topology managers 9258c2ecf20Sopenharmony_ci * in an atomic update 9268c2ecf20Sopenharmony_ci * @__state: &struct drm_atomic_state pointer 9278c2ecf20Sopenharmony_ci * @mgr: &struct drm_dp_mst_topology_mgr iteration cursor 9288c2ecf20Sopenharmony_ci * @old_state: &struct drm_dp_mst_topology_state iteration cursor for the old 9298c2ecf20Sopenharmony_ci * state 9308c2ecf20Sopenharmony_ci * @__i: int iteration cursor, for macro-internal use 9318c2ecf20Sopenharmony_ci * 9328c2ecf20Sopenharmony_ci * This iterates over all DRM DP MST topology managers in an atomic update, 9338c2ecf20Sopenharmony_ci * tracking only the old state. This is useful in disable functions, where we 9348c2ecf20Sopenharmony_ci * need the old state the hardware is still in. 9358c2ecf20Sopenharmony_ci */ 9368c2ecf20Sopenharmony_ci#define for_each_old_mst_mgr_in_state(__state, mgr, old_state, __i) \ 9378c2ecf20Sopenharmony_ci for ((__i) = 0; (__i) < (__state)->num_private_objs; (__i)++) \ 9388c2ecf20Sopenharmony_ci for_each_if(__drm_dp_mst_state_iter_get((__state), &(mgr), &(old_state), NULL, (__i))) 9398c2ecf20Sopenharmony_ci 9408c2ecf20Sopenharmony_ci/** 9418c2ecf20Sopenharmony_ci * for_each_new_mst_mgr_in_state - iterate over all DP MST topology managers 9428c2ecf20Sopenharmony_ci * in an atomic update 9438c2ecf20Sopenharmony_ci * @__state: &struct drm_atomic_state pointer 9448c2ecf20Sopenharmony_ci * @mgr: &struct drm_dp_mst_topology_mgr iteration cursor 9458c2ecf20Sopenharmony_ci * @new_state: &struct drm_dp_mst_topology_state iteration cursor for the new 9468c2ecf20Sopenharmony_ci * state 9478c2ecf20Sopenharmony_ci * @__i: int iteration cursor, for macro-internal use 9488c2ecf20Sopenharmony_ci * 9498c2ecf20Sopenharmony_ci * This iterates over all DRM DP MST topology managers in an atomic update, 9508c2ecf20Sopenharmony_ci * tracking only the new state. This is useful in enable functions, where we 9518c2ecf20Sopenharmony_ci * need the new state the hardware should be in when the atomic commit 9528c2ecf20Sopenharmony_ci * operation has completed. 9538c2ecf20Sopenharmony_ci */ 9548c2ecf20Sopenharmony_ci#define for_each_new_mst_mgr_in_state(__state, mgr, new_state, __i) \ 9558c2ecf20Sopenharmony_ci for ((__i) = 0; (__i) < (__state)->num_private_objs; (__i)++) \ 9568c2ecf20Sopenharmony_ci for_each_if(__drm_dp_mst_state_iter_get((__state), &(mgr), NULL, &(new_state), (__i))) 9578c2ecf20Sopenharmony_ci 9588c2ecf20Sopenharmony_ci#endif 959