linux/include/drm/display/drm_dp_mst_helper.h

/*
 * Copyright © 2014 Red Hat.
 *
 * Permission to use, copy, modify, distribute, and sell this software and its
 * documentation for any purpose is hereby granted without fee, provided that
 * the above copyright notice appear in all copies and that both that copyright
 * notice and this permission notice appear in supporting documentation, and
 * that the name of the copyright holders not be used in advertising or
 * publicity pertaining to distribution of the software without specific,
 * written prior permission.  The copyright holders make no representations
 * about the suitability of this software for any purpose.  It is provided "as
 * is" without express or implied warranty.
 *
 * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
 * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
 * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
 * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
 * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
 * OF THIS SOFTWARE.
 */
#ifndef _DRM_DP_MST_HELPER_H_
#define _DRM_DP_MST_HELPER_H_

#include <linux/types.h>
#include <drm/display/drm_dp_helper.h>
#include <drm/drm_atomic.h>
#include <drm/drm_fixed.h>

#if IS_ENABLED(CONFIG_DRM_DEBUG_DP_MST_TOPOLOGY_REFS)
#include <linux/stackdepot.h>
#include <linux/timekeeping.h>

enum drm_dp_mst_topology_ref_type {};

struct drm_dp_mst_topology_ref_history {};
#endif /* IS_ENABLED(CONFIG_DRM_DEBUG_DP_MST_TOPOLOGY_REFS) */

enum drm_dp_mst_payload_allocation {};

struct drm_dp_mst_branch;

/**
 * struct drm_dp_mst_port - MST port
 * @port_num: port number
 * @input: if this port is an input port. Protected by
 * &drm_dp_mst_topology_mgr.base.lock.
 * @mcs: message capability status - DP 1.2 spec. Protected by
 * &drm_dp_mst_topology_mgr.base.lock.
 * @ddps: DisplayPort Device Plug Status - DP 1.2. Protected by
 * &drm_dp_mst_topology_mgr.base.lock.
 * @pdt: Peer Device Type. Protected by
 * &drm_dp_mst_topology_mgr.base.lock.
 * @ldps: Legacy Device Plug Status. Protected by
 * &drm_dp_mst_topology_mgr.base.lock.
 * @dpcd_rev: DPCD revision of device on this port. Protected by
 * &drm_dp_mst_topology_mgr.base.lock.
 * @num_sdp_streams: Number of simultaneous streams. Protected by
 * &drm_dp_mst_topology_mgr.base.lock.
 * @num_sdp_stream_sinks: Number of stream sinks. Protected by
 * &drm_dp_mst_topology_mgr.base.lock.
 * @full_pbn: Max possible bandwidth for this port. Protected by
 * &drm_dp_mst_topology_mgr.base.lock.
 * @next: link to next port on this branch device
 * @aux: i2c aux transport to talk to device connected to this port, protected
 * by &drm_dp_mst_topology_mgr.base.lock.
 * @passthrough_aux: parent aux to which DSC pass-through requests should be
 * sent, only set if DSC pass-through is possible.
 * @parent: branch device parent of this port
 * @connector: DRM connector this port is connected to. Protected by
 * &drm_dp_mst_topology_mgr.base.lock.
 * @mgr: topology manager this port lives under.
 *
 * This structure represents an MST port endpoint on a device somewhere
 * in the MST topology.
 */
struct drm_dp_mst_port {};

/* sideband msg header - not bit struct */
struct drm_dp_sideband_msg_hdr {};

struct drm_dp_sideband_msg_rx {};

/**
 * struct drm_dp_mst_branch - MST branch device.
 * @rad: Relative Address to talk to this branch device.
 * @lct: Link count total to talk to this branch device.
 * @num_ports: number of ports on the branch.
 * @port_parent: pointer to the port parent, NULL if toplevel.
 * @mgr: topology manager for this branch device.
 * @link_address_sent: if a link address message has been sent to this device yet.
 * @guid: guid for DP 1.2 branch device. port under this branch can be
 * identified by port #.
 *
 * This structure represents an MST branch device, there is one
 * primary branch device at the root, along with any other branches connected
 * to downstream port of parent branches.
 */
struct drm_dp_mst_branch {};


struct drm_dp_nak_reply {};

struct drm_dp_link_address_ack_reply {};

struct drm_dp_remote_dpcd_read_ack_reply {};

struct drm_dp_remote_dpcd_write_ack_reply {};

struct drm_dp_remote_dpcd_write_nak_reply {};

struct drm_dp_remote_i2c_read_ack_reply {};

struct drm_dp_remote_i2c_read_nak_reply {};

struct drm_dp_remote_i2c_write_ack_reply {};

struct drm_dp_query_stream_enc_status_ack_reply {};

#define DRM_DP_MAX_SDP_STREAMS
struct drm_dp_allocate_payload {};

struct drm_dp_allocate_payload_ack_reply {};

struct drm_dp_connection_status_notify {};

struct drm_dp_remote_dpcd_read {};

struct drm_dp_remote_dpcd_write {};

#define DP_REMOTE_I2C_READ_MAX_TRANSACTIONS
struct drm_dp_remote_i2c_read {};

struct drm_dp_remote_i2c_write {};

struct drm_dp_query_stream_enc_status {};

/* this covers ENUM_RESOURCES, POWER_DOWN_PHY, POWER_UP_PHY */
struct drm_dp_port_number_req {};

struct drm_dp_enum_path_resources_ack_reply {};

/* covers POWER_DOWN_PHY, POWER_UP_PHY */
struct drm_dp_port_number_rep {};

struct drm_dp_query_payload {};

struct drm_dp_resource_status_notify {};

struct drm_dp_query_payload_ack_reply {};

struct drm_dp_sideband_msg_req_body {};

struct drm_dp_sideband_msg_reply_body {};

/* msg is queued to be put into a slot */
#define DRM_DP_SIDEBAND_TX_QUEUED
/* msg has started transmitting on a slot - still on msgq */
#define DRM_DP_SIDEBAND_TX_START_SEND
/* msg has finished transmitting on a slot - removed from msgq only in slot */
#define DRM_DP_SIDEBAND_TX_SENT
/* msg has received a response - removed from slot */
#define DRM_DP_SIDEBAND_TX_RX
#define DRM_DP_SIDEBAND_TX_TIMEOUT

struct drm_dp_sideband_msg_tx {};

/* sideband msg handler */
struct drm_dp_mst_topology_mgr;
struct drm_dp_mst_topology_cbs {};

#define to_dp_mst_topology_state(x)

/**
 * struct drm_dp_mst_atomic_payload - Atomic state struct for an MST payload
 *
 * The primary atomic state structure for a given MST payload. Stores information like current
 * bandwidth allocation, intended action for this payload, etc.
 */
struct drm_dp_mst_atomic_payload {};

/**
 * struct drm_dp_mst_topology_state - DisplayPort MST topology atomic state
 *
 * This struct represents the atomic state of the toplevel DisplayPort MST manager
 */
struct drm_dp_mst_topology_state {};

#define to_dp_mst_topology_mgr(x)

/**
 * struct drm_dp_mst_topology_mgr - DisplayPort MST manager
 *
 * This struct represents the toplevel displayport MST topology manager.
 * There should be one instance of this for every MST capable DP connector
 * on the GPU.
 */
struct drm_dp_mst_topology_mgr {};

int drm_dp_mst_topology_mgr_init(struct drm_dp_mst_topology_mgr *mgr,
				 struct drm_device *dev, struct drm_dp_aux *aux,
				 int max_dpcd_transaction_bytes,
				 int max_payloads, int conn_base_id);

void drm_dp_mst_topology_mgr_destroy(struct drm_dp_mst_topology_mgr *mgr);

/**
 * enum drm_dp_mst_mode - sink's MST mode capability
 */
enum drm_dp_mst_mode {};

enum drm_dp_mst_mode drm_dp_read_mst_cap(struct drm_dp_aux *aux, const u8 dpcd[DP_RECEIVER_CAP_SIZE]);
int drm_dp_mst_topology_mgr_set_mst(struct drm_dp_mst_topology_mgr *mgr, bool mst_state);

int drm_dp_mst_hpd_irq_handle_event(struct drm_dp_mst_topology_mgr *mgr,
				    const u8 *esi,
				    u8 *ack,
				    bool *handled);
void drm_dp_mst_hpd_irq_send_new_request(struct drm_dp_mst_topology_mgr *mgr);

int
drm_dp_mst_detect_port(struct drm_connector *connector,
		       struct drm_modeset_acquire_ctx *ctx,
		       struct drm_dp_mst_topology_mgr *mgr,
		       struct drm_dp_mst_port *port);

const struct drm_edid *drm_dp_mst_edid_read(struct drm_connector *connector,
					    struct drm_dp_mst_topology_mgr *mgr,
					    struct drm_dp_mst_port *port);
struct edid *drm_dp_mst_get_edid(struct drm_connector *connector,
				 struct drm_dp_mst_topology_mgr *mgr,
				 struct drm_dp_mst_port *port);

fixed20_12 drm_dp_get_vc_payload_bw(const struct drm_dp_mst_topology_mgr *mgr,
				    int link_rate, int link_lane_count);

int drm_dp_calc_pbn_mode(int clock, int bpp);

void drm_dp_mst_update_slots(struct drm_dp_mst_topology_state *mst_state, uint8_t link_encoding_cap);

int drm_dp_add_payload_part1(struct drm_dp_mst_topology_mgr *mgr,
			     struct drm_dp_mst_topology_state *mst_state,
			     struct drm_dp_mst_atomic_payload *payload);
int drm_dp_add_payload_part2(struct drm_dp_mst_topology_mgr *mgr,
			     struct drm_dp_mst_atomic_payload *payload);
void drm_dp_remove_payload_part1(struct drm_dp_mst_topology_mgr *mgr,
				 struct drm_dp_mst_topology_state *mst_state,
				 struct drm_dp_mst_atomic_payload *payload);
void drm_dp_remove_payload_part2(struct drm_dp_mst_topology_mgr *mgr,
				 struct drm_dp_mst_topology_state *mst_state,
				 const struct drm_dp_mst_atomic_payload *old_payload,
				 struct drm_dp_mst_atomic_payload *new_payload);

int drm_dp_check_act_status(struct drm_dp_mst_topology_mgr *mgr);

void drm_dp_mst_dump_topology(struct seq_file *m,
			      struct drm_dp_mst_topology_mgr *mgr);

void drm_dp_mst_topology_mgr_suspend(struct drm_dp_mst_topology_mgr *mgr);
int __must_check
drm_dp_mst_topology_mgr_resume(struct drm_dp_mst_topology_mgr *mgr,
			       bool sync);

ssize_t drm_dp_mst_dpcd_read(struct drm_dp_aux *aux,
			     unsigned int offset, void *buffer, size_t size);
ssize_t drm_dp_mst_dpcd_write(struct drm_dp_aux *aux,
			      unsigned int offset, void *buffer, size_t size);

int drm_dp_mst_connector_late_register(struct drm_connector *connector,
				       struct drm_dp_mst_port *port);
void drm_dp_mst_connector_early_unregister(struct drm_connector *connector,
					   struct drm_dp_mst_port *port);

struct drm_dp_mst_topology_state *
drm_atomic_get_mst_topology_state(struct drm_atomic_state *state,
				  struct drm_dp_mst_topology_mgr *mgr);
struct drm_dp_mst_topology_state *
drm_atomic_get_old_mst_topology_state(struct drm_atomic_state *state,
				      struct drm_dp_mst_topology_mgr *mgr);
struct drm_dp_mst_topology_state *
drm_atomic_get_new_mst_topology_state(struct drm_atomic_state *state,
				      struct drm_dp_mst_topology_mgr *mgr);
struct drm_dp_mst_atomic_payload *
drm_atomic_get_mst_payload_state(struct drm_dp_mst_topology_state *state,
				 struct drm_dp_mst_port *port);
bool drm_dp_mst_port_downstream_of_parent(struct drm_dp_mst_topology_mgr *mgr,
					  struct drm_dp_mst_port *port,
					  struct drm_dp_mst_port *parent);
int __must_check
drm_dp_atomic_find_time_slots(struct drm_atomic_state *state,
			      struct drm_dp_mst_topology_mgr *mgr,
			      struct drm_dp_mst_port *port, int pbn);
int drm_dp_mst_atomic_enable_dsc(struct drm_atomic_state *state,
				 struct drm_dp_mst_port *port,
				 int pbn, bool enable);
int __must_check
drm_dp_mst_add_affected_dsc_crtcs(struct drm_atomic_state *state,
				  struct drm_dp_mst_topology_mgr *mgr);
int __must_check
drm_dp_atomic_release_time_slots(struct drm_atomic_state *state,
				 struct drm_dp_mst_topology_mgr *mgr,
				 struct drm_dp_mst_port *port);
void drm_dp_mst_atomic_wait_for_dependencies(struct drm_atomic_state *state);
int __must_check drm_dp_mst_atomic_setup_commit(struct drm_atomic_state *state);
int drm_dp_send_power_updown_phy(struct drm_dp_mst_topology_mgr *mgr,
				 struct drm_dp_mst_port *port, bool power_up);
int drm_dp_send_query_stream_enc_status(struct drm_dp_mst_topology_mgr *mgr,
		struct drm_dp_mst_port *port,
		struct drm_dp_query_stream_enc_status_ack_reply *status);
int __must_check drm_dp_mst_atomic_check_mgr(struct drm_atomic_state *state,
					     struct drm_dp_mst_topology_mgr *mgr,
					     struct drm_dp_mst_topology_state *mst_state,
					     struct drm_dp_mst_port **failing_port);
int __must_check drm_dp_mst_atomic_check(struct drm_atomic_state *state);
int __must_check drm_dp_mst_root_conn_atomic_check(struct drm_connector_state *new_conn_state,
						   struct drm_dp_mst_topology_mgr *mgr);

void drm_dp_mst_get_port_malloc(struct drm_dp_mst_port *port);
void drm_dp_mst_put_port_malloc(struct drm_dp_mst_port *port);

static inline
bool drm_dp_mst_port_is_logical(struct drm_dp_mst_port *port)
{}

struct drm_dp_aux *drm_dp_mst_aux_for_parent(struct drm_dp_mst_port *port);
struct drm_dp_aux *drm_dp_mst_dsc_aux_for_port(struct drm_dp_mst_port *port);

static inline struct drm_dp_mst_topology_state *
to_drm_dp_mst_topology_state(struct drm_private_state *state)
{}

extern const struct drm_private_state_funcs drm_dp_mst_topology_state_funcs;

/**
 * __drm_dp_mst_state_iter_get - private atomic state iterator function for
 * macro-internal use
 * @state: &struct drm_atomic_state pointer
 * @mgr: pointer to the &struct drm_dp_mst_topology_mgr iteration cursor
 * @old_state: optional pointer to the old &struct drm_dp_mst_topology_state
 * iteration cursor
 * @new_state: optional pointer to the new &struct drm_dp_mst_topology_state
 * iteration cursor
 * @i: int iteration cursor, for macro-internal use
 *
 * Used by for_each_oldnew_mst_mgr_in_state(),
 * for_each_old_mst_mgr_in_state(), and for_each_new_mst_mgr_in_state(). Don't
 * call this directly.
 *
 * Returns:
 * True if the current &struct drm_private_obj is a &struct
 * drm_dp_mst_topology_mgr, false otherwise.
 */
static inline bool
__drm_dp_mst_state_iter_get(struct drm_atomic_state *state,
			    struct drm_dp_mst_topology_mgr **mgr,
			    struct drm_dp_mst_topology_state **old_state,
			    struct drm_dp_mst_topology_state **new_state,
			    int i)
{}

/**
 * for_each_oldnew_mst_mgr_in_state - iterate over all DP MST topology
 * managers in an atomic update
 * @__state: &struct drm_atomic_state pointer
 * @mgr: &struct drm_dp_mst_topology_mgr iteration cursor
 * @old_state: &struct drm_dp_mst_topology_state iteration cursor for the old
 * state
 * @new_state: &struct drm_dp_mst_topology_state iteration cursor for the new
 * state
 * @__i: int iteration cursor, for macro-internal use
 *
 * This iterates over all DRM DP MST topology managers in an atomic update,
 * tracking both old and new state. This is useful in places where the state
 * delta needs to be considered, for example in atomic check functions.
 */
#define for_each_oldnew_mst_mgr_in_state(__state, mgr, old_state, new_state, __i)

/**
 * for_each_old_mst_mgr_in_state - iterate over all DP MST topology managers
 * in an atomic update
 * @__state: &struct drm_atomic_state pointer
 * @mgr: &struct drm_dp_mst_topology_mgr iteration cursor
 * @old_state: &struct drm_dp_mst_topology_state iteration cursor for the old
 * state
 * @__i: int iteration cursor, for macro-internal use
 *
 * This iterates over all DRM DP MST topology managers in an atomic update,
 * tracking only the old state. This is useful in disable functions, where we
 * need the old state the hardware is still in.
 */
#define for_each_old_mst_mgr_in_state(__state, mgr, old_state, __i)

/**
 * for_each_new_mst_mgr_in_state - iterate over all DP MST topology managers
 * in an atomic update
 * @__state: &struct drm_atomic_state pointer
 * @mgr: &struct drm_dp_mst_topology_mgr iteration cursor
 * @new_state: &struct drm_dp_mst_topology_state iteration cursor for the new
 * state
 * @__i: int iteration cursor, for macro-internal use
 *
 * This iterates over all DRM DP MST topology managers in an atomic update,
 * tracking only the new state. This is useful in enable functions, where we
 * need the new state the hardware should be in when the atomic commit
 * operation has completed.
 */
#define for_each_new_mst_mgr_in_state(__state, mgr, new_state, __i)

#endif