linux/drivers/gpu/drm/i915/display/intel_tc.c

// SPDX-License-Identifier: MIT
/*
 * Copyright © 2019 Intel Corporation
 */

#include "i915_drv.h"
#include "i915_reg.h"
#include "intel_atomic.h"
#include "intel_cx0_phy_regs.h"
#include "intel_ddi.h"
#include "intel_de.h"
#include "intel_display.h"
#include "intel_display_driver.h"
#include "intel_display_power_map.h"
#include "intel_display_types.h"
#include "intel_dkl_phy_regs.h"
#include "intel_dp.h"
#include "intel_dp_mst.h"
#include "intel_mg_phy_regs.h"
#include "intel_modeset_lock.h"
#include "intel_tc.h"

#define DP_PIN_ASSIGNMENT_C
#define DP_PIN_ASSIGNMENT_D
#define DP_PIN_ASSIGNMENT_E

enum tc_port_mode {};

struct intel_tc_port;

struct intel_tc_phy_ops {};

struct intel_tc_port {};

static enum intel_display_power_domain
tc_phy_cold_off_domain(struct intel_tc_port *);
static u32 tc_phy_hpd_live_status(struct intel_tc_port *tc);
static bool tc_phy_is_ready(struct intel_tc_port *tc);
static bool tc_phy_wait_for_ready(struct intel_tc_port *tc);
static enum tc_port_mode tc_phy_get_current_mode(struct intel_tc_port *tc);

static const char *tc_port_mode_name(enum tc_port_mode mode)
{}

static struct intel_tc_port *to_tc_port(struct intel_digital_port *dig_port)
{}

static struct drm_i915_private *tc_to_i915(struct intel_tc_port *tc)
{}

static bool intel_tc_port_in_mode(struct intel_digital_port *dig_port,
				  enum tc_port_mode mode)
{}

bool intel_tc_port_in_tbt_alt_mode(struct intel_digital_port *dig_port)
{}

bool intel_tc_port_in_dp_alt_mode(struct intel_digital_port *dig_port)
{}

bool intel_tc_port_in_legacy_mode(struct intel_digital_port *dig_port)
{}

bool intel_tc_port_handles_hpd_glitches(struct intel_digital_port *dig_port)
{}

/*
 * The display power domains used for TC ports depending on the
 * platform and TC mode (legacy, DP-alt, TBT):
 *
 * POWER_DOMAIN_DISPLAY_CORE:
 * --------------------------
 * ADLP/all modes:
 *   - TCSS/IOM access for PHY ready state.
 * ADLP+/all modes:
 *   - DE/north-,south-HPD ISR access for HPD live state.
 *
 * POWER_DOMAIN_PORT_DDI_LANES_<port>:
 * -----------------------------------
 * ICL+/all modes:
 *   - DE/DDI_BUF access for port enabled state.
 * ADLP/all modes:
 *   - DE/DDI_BUF access for PHY owned state.
 *
 * POWER_DOMAIN_AUX_USBC<TC port index>:
 * -------------------------------------
 * ICL/legacy mode:
 *   - TCSS/IOM,FIA access for PHY ready, owned and HPD live state
 *   - TCSS/PHY: block TC-cold power state for using the PHY AUX and
 *     main lanes.
 * ADLP/legacy, DP-alt modes:
 *   - TCSS/PHY: block TC-cold power state for using the PHY AUX and
 *     main lanes.
 *
 * POWER_DOMAIN_TC_COLD_OFF:
 * -------------------------
 * ICL/DP-alt, TBT mode:
 *   - TCSS/TBT: block TC-cold power state for using the (direct or
 *     TBT DP-IN) AUX and main lanes.
 *
 * TGL/all modes:
 *   - TCSS/IOM,FIA access for PHY ready, owned and HPD live state
 *   - TCSS/PHY: block TC-cold power state for using the (direct or
 *     TBT DP-IN) AUX and main lanes.
 *
 * ADLP/TBT mode:
 *   - TCSS/TBT: block TC-cold power state for using the (TBT DP-IN)
 *     AUX and main lanes.
 *
 * XELPDP+/all modes:
 *   - TCSS/IOM,FIA access for PHY ready, owned state
 *   - TCSS/PHY: block TC-cold power state for using the (direct or
 *     TBT DP-IN) AUX and main lanes.
 */
bool intel_tc_cold_requires_aux_pw(struct intel_digital_port *dig_port)
{}

static intel_wakeref_t
__tc_cold_block(struct intel_tc_port *tc, enum intel_display_power_domain *domain)
{}

static intel_wakeref_t
tc_cold_block(struct intel_tc_port *tc)
{}

static void
__tc_cold_unblock(struct intel_tc_port *tc, enum intel_display_power_domain domain,
		  intel_wakeref_t wakeref)
{}

static void
tc_cold_unblock(struct intel_tc_port *tc, intel_wakeref_t wakeref)
{}

static void
assert_display_core_power_enabled(struct intel_tc_port *tc)
{}

static void
assert_tc_cold_blocked(struct intel_tc_port *tc)
{}

static enum intel_display_power_domain
tc_port_power_domain(struct intel_tc_port *tc)
{}

static void
assert_tc_port_power_enabled(struct intel_tc_port *tc)
{}

static u32 intel_tc_port_get_lane_mask(struct intel_digital_port *dig_port)
{}

u32 intel_tc_port_get_pin_assignment_mask(struct intel_digital_port *dig_port)
{}

static int lnl_tc_port_get_max_lane_count(struct intel_digital_port *dig_port)
{}

static int mtl_tc_port_get_max_lane_count(struct intel_digital_port *dig_port)
{}

static int intel_tc_port_get_max_lane_count(struct intel_digital_port *dig_port)
{}

int intel_tc_port_max_lane_count(struct intel_digital_port *dig_port)
{}

void intel_tc_port_set_fia_lane_count(struct intel_digital_port *dig_port,
				      int required_lanes)
{}

static void tc_port_fixup_legacy_flag(struct intel_tc_port *tc,
				      u32 live_status_mask)
{}

static void tc_phy_load_fia_params(struct intel_tc_port *tc, bool modular_fia)
{}

/*
 * ICL TC PHY handlers
 * -------------------
 */
static enum intel_display_power_domain
icl_tc_phy_cold_off_domain(struct intel_tc_port *tc)
{}

static u32 icl_tc_phy_hpd_live_status(struct intel_tc_port *tc)
{}

/*
 * Return the PHY status complete flag indicating that display can acquire the
 * PHY ownership. The IOM firmware sets this flag when a DP-alt or legacy sink
 * is connected and it's ready to switch the ownership to display. The flag
 * will be left cleared when a TBT-alt sink is connected, where the PHY is
 * owned by the TBT subsystem and so switching the ownership to display is not
 * required.
 */
static bool icl_tc_phy_is_ready(struct intel_tc_port *tc)
{}

static bool icl_tc_phy_take_ownership(struct intel_tc_port *tc,
				      bool take)
{}

static bool icl_tc_phy_is_owned(struct intel_tc_port *tc)
{}

static void icl_tc_phy_get_hw_state(struct intel_tc_port *tc)
{}

/*
 * This function implements the first part of the Connect Flow described by our
 * specification, Gen11 TypeC Programming chapter. The rest of the flow (reading
 * lanes, EDID, etc) is done as needed in the typical places.
 *
 * Unlike the other ports, type-C ports are not available to use as soon as we
 * get a hotplug. The type-C PHYs can be shared between multiple controllers:
 * display, USB, etc. As a result, handshaking through FIA is required around
 * connect and disconnect to cleanly transfer ownership with the controller and
 * set the type-C power state.
 */
static bool tc_phy_verify_legacy_or_dp_alt_mode(struct intel_tc_port *tc,
						int required_lanes)
{}

static bool icl_tc_phy_connect(struct intel_tc_port *tc,
			       int required_lanes)
{}

/*
 * See the comment at the connect function. This implements the Disconnect
 * Flow.
 */
static void icl_tc_phy_disconnect(struct intel_tc_port *tc)
{}

static void icl_tc_phy_init(struct intel_tc_port *tc)
{}

static const struct intel_tc_phy_ops icl_tc_phy_ops =;

/*
 * TGL TC PHY handlers
 * -------------------
 */
static enum intel_display_power_domain
tgl_tc_phy_cold_off_domain(struct intel_tc_port *tc)
{}

static void tgl_tc_phy_init(struct intel_tc_port *tc)
{}

static const struct intel_tc_phy_ops tgl_tc_phy_ops =;

/*
 * ADLP TC PHY handlers
 * --------------------
 */
static enum intel_display_power_domain
adlp_tc_phy_cold_off_domain(struct intel_tc_port *tc)
{}

static u32 adlp_tc_phy_hpd_live_status(struct intel_tc_port *tc)
{}

/*
 * Return the PHY status complete flag indicating that display can acquire the
 * PHY ownership. The IOM firmware sets this flag when it's ready to switch
 * the ownership to display, regardless of what sink is connected (TBT-alt,
 * DP-alt, legacy or nothing). For TBT-alt sinks the PHY is owned by the TBT
 * subsystem and so switching the ownership to display is not required.
 */
static bool adlp_tc_phy_is_ready(struct intel_tc_port *tc)
{}

static bool adlp_tc_phy_take_ownership(struct intel_tc_port *tc,
				       bool take)
{}

static bool adlp_tc_phy_is_owned(struct intel_tc_port *tc)
{}

static void adlp_tc_phy_get_hw_state(struct intel_tc_port *tc)
{}

static bool adlp_tc_phy_connect(struct intel_tc_port *tc, int required_lanes)
{}

static void adlp_tc_phy_disconnect(struct intel_tc_port *tc)
{}

static void adlp_tc_phy_init(struct intel_tc_port *tc)
{}

static const struct intel_tc_phy_ops adlp_tc_phy_ops =;

/*
 * XELPDP TC PHY handlers
 * ----------------------
 */
static u32 xelpdp_tc_phy_hpd_live_status(struct intel_tc_port *tc)
{}

static bool
xelpdp_tc_phy_tcss_power_is_enabled(struct intel_tc_port *tc)
{}

static bool
xelpdp_tc_phy_wait_for_tcss_power(struct intel_tc_port *tc, bool enabled)
{}

static void __xelpdp_tc_phy_enable_tcss_power(struct intel_tc_port *tc, bool enable)
{}

static bool xelpdp_tc_phy_enable_tcss_power(struct intel_tc_port *tc, bool enable)
{}

static void xelpdp_tc_phy_take_ownership(struct intel_tc_port *tc, bool take)
{}

static bool xelpdp_tc_phy_is_owned(struct intel_tc_port *tc)
{}

static void xelpdp_tc_phy_get_hw_state(struct intel_tc_port *tc)
{}

static bool xelpdp_tc_phy_connect(struct intel_tc_port *tc, int required_lanes)
{}

static void xelpdp_tc_phy_disconnect(struct intel_tc_port *tc)
{}

static const struct intel_tc_phy_ops xelpdp_tc_phy_ops =;

/*
 * Generic TC PHY handlers
 * -----------------------
 */
static enum intel_display_power_domain
tc_phy_cold_off_domain(struct intel_tc_port *tc)
{}

static u32 tc_phy_hpd_live_status(struct intel_tc_port *tc)
{}

static bool tc_phy_is_ready(struct intel_tc_port *tc)
{}

static bool tc_phy_is_owned(struct intel_tc_port *tc)
{}

static void tc_phy_get_hw_state(struct intel_tc_port *tc)
{}

static bool tc_phy_is_ready_and_owned(struct intel_tc_port *tc,
				      bool phy_is_ready, bool phy_is_owned)
{}

static bool tc_phy_is_connected(struct intel_tc_port *tc,
				enum icl_port_dpll_id port_pll_type)
{}

static bool tc_phy_wait_for_ready(struct intel_tc_port *tc)
{}

static enum tc_port_mode
hpd_mask_to_tc_mode(u32 live_status_mask)
{}

static enum tc_port_mode
tc_phy_hpd_live_mode(struct intel_tc_port *tc)
{}

static enum tc_port_mode
get_tc_mode_in_phy_owned_state(struct intel_tc_port *tc,
			       enum tc_port_mode live_mode)
{}

static enum tc_port_mode
get_tc_mode_in_phy_not_owned_state(struct intel_tc_port *tc,
				   enum tc_port_mode live_mode)
{}

static enum tc_port_mode
tc_phy_get_current_mode(struct intel_tc_port *tc)
{}

static enum tc_port_mode default_tc_mode(struct intel_tc_port *tc)
{}

static enum tc_port_mode
hpd_mask_to_target_mode(struct intel_tc_port *tc, u32 live_status_mask)
{}

static enum tc_port_mode
tc_phy_get_target_mode(struct intel_tc_port *tc)
{}

static void tc_phy_connect(struct intel_tc_port *tc, int required_lanes)
{}

static void tc_phy_disconnect(struct intel_tc_port *tc)
{}

static void tc_phy_init(struct intel_tc_port *tc)
{}

static void intel_tc_port_reset_mode(struct intel_tc_port *tc,
				     int required_lanes, bool force_disconnect)
{}

static bool intel_tc_port_needs_reset(struct intel_tc_port *tc)
{}

static void intel_tc_port_update_mode(struct intel_tc_port *tc,
				      int required_lanes, bool force_disconnect)
{}

static void __intel_tc_port_get_link(struct intel_tc_port *tc)
{}

static void __intel_tc_port_put_link(struct intel_tc_port *tc)
{}

static bool tc_port_is_enabled(struct intel_tc_port *tc)
{}

/**
 * intel_tc_port_init_mode: Read out HW state and init the given port's TypeC mode
 * @dig_port: digital port
 *
 * Read out the HW state and initialize the TypeC mode of @dig_port. The mode
 * will be locked until intel_tc_port_sanitize_mode() is called.
 */
void intel_tc_port_init_mode(struct intel_digital_port *dig_port)
{}

static bool tc_port_has_active_links(struct intel_tc_port *tc,
				     const struct intel_crtc_state *crtc_state)
{}

/**
 * intel_tc_port_sanitize_mode: Sanitize the given port's TypeC mode
 * @dig_port: digital port
 * @crtc_state: atomic state of CRTC connected to @dig_port
 *
 * Sanitize @dig_port's TypeC mode wrt. the encoder's state right after driver
 * loading and system resume:
 * If the encoder is enabled keep the TypeC mode/PHY connected state locked until
 * the encoder is disabled.
 * If the encoder is disabled make sure the PHY is disconnected.
 * @crtc_state is valid if @dig_port is enabled, NULL otherwise.
 */
void intel_tc_port_sanitize_mode(struct intel_digital_port *dig_port,
				 const struct intel_crtc_state *crtc_state)
{}

/*
 * The type-C ports are different because even when they are connected, they may
 * not be available/usable by the graphics driver: see the comment on
 * icl_tc_phy_connect(). So in our driver instead of adding the additional
 * concept of "usable" and make everything check for "connected and usable" we
 * define a port as "connected" when it is not only connected, but also when it
 * is usable by the rest of the driver. That maintains the old assumption that
 * connected ports are usable, and avoids exposing to the users objects they
 * can't really use.
 */
bool intel_tc_port_connected(struct intel_encoder *encoder)
{}

static bool __intel_tc_port_link_needs_reset(struct intel_tc_port *tc)
{}

bool intel_tc_port_link_needs_reset(struct intel_digital_port *dig_port)
{}

static int reset_link_commit(struct intel_tc_port *tc,
			     struct intel_atomic_state *state,
			     struct drm_modeset_acquire_ctx *ctx)
{}

static int reset_link(struct intel_tc_port *tc)
{}

static void intel_tc_port_link_reset_work(struct work_struct *work)
{}

bool intel_tc_port_link_reset(struct intel_digital_port *dig_port)
{}

void intel_tc_port_link_cancel_reset_work(struct intel_digital_port *dig_port)
{}

static void __intel_tc_port_lock(struct intel_tc_port *tc,
				 int required_lanes)
{}

void intel_tc_port_lock(struct intel_digital_port *dig_port)
{}

/*
 * Disconnect the given digital port from its TypeC PHY (handing back the
 * control of the PHY to the TypeC subsystem). This will happen in a delayed
 * manner after each aux transactions and modeset disables.
 */
static void intel_tc_port_disconnect_phy_work(struct work_struct *work)
{}

/**
 * intel_tc_port_flush_work: flush the work disconnecting the PHY
 * @dig_port: digital port
 *
 * Flush the delayed work disconnecting an idle PHY.
 */
static void intel_tc_port_flush_work(struct intel_digital_port *dig_port)
{}

void intel_tc_port_suspend(struct intel_digital_port *dig_port)
{}

void intel_tc_port_unlock(struct intel_digital_port *dig_port)
{}

bool intel_tc_port_ref_held(struct intel_digital_port *dig_port)
{}

void intel_tc_port_get_link(struct intel_digital_port *dig_port,
			    int required_lanes)
{}

void intel_tc_port_put_link(struct intel_digital_port *dig_port)
{}

int intel_tc_port_init(struct intel_digital_port *dig_port, bool is_legacy)
{}

void intel_tc_port_cleanup(struct intel_digital_port *dig_port)
{}