Commit 637c7aa2 authored by Imre Deak's avatar Imre Deak
Browse files

drm/i915: Factor out function to get/put AUX_IO power for main link



Factor out functions to get/put the AUX_IO power domain for the main
link on DDI ports.

While at it clarify the corresponding code comment.

No functional change.

v2:
- s/(get/put)_aux_power_for_main_link/main_link_aux_power_domain_(get/put)
  (Jani)
- Clarify in the code comment that AUX_IO is needed only by TypeC besides
  eDP/PSR.
v3:
- Rebased on checking intel_encoder_can_psr() instead of crtc->has_psr.
v4:
- Don't call fetch_and_zero() with side-effect during variable
  declaration. (Ville)

Cc: Jani Nikula <jani.nikula@intel.com>
Cc: Ville Syrjälä <ville.syrjala@linux.intel.com>
Signed-off-by: default avatarImre Deak <imre.deak@intel.com>
Reviewed-by: default avatarVille Syrjälä <ville.syrjala@linux.intel.com>
Link: https://patchwork.freedesktop.org/patch/msgid/20221114122251.21327-9-imre.deak@intel.com
parent 406a95df
Loading
Loading
Loading
Loading
+52 −33
Original line number Diff line number Diff line
@@ -848,26 +848,64 @@ bool intel_ddi_get_hw_state(struct intel_encoder *encoder,
}

static enum intel_display_power_domain
intel_ddi_main_link_aux_domain(struct intel_digital_port *dig_port)
intel_ddi_main_link_aux_domain(struct intel_digital_port *dig_port,
			       const struct intel_crtc_state *crtc_state)
{
	struct drm_i915_private *i915 = to_i915(dig_port->base.base.dev);
	enum phy phy = intel_port_to_phy(i915, dig_port->base.port);

	/* ICL+ HW requires corresponding AUX IOs to be powered up for PSR with
	/*
	 * ICL+ HW requires corresponding AUX IOs to be powered up for PSR with
	 * DC states enabled at the same time, while for driver initiated AUX
	 * transfers we need the same AUX IOs to be powered but with DC states
	 * disabled. Accordingly use the AUX power domain here which leaves DC
	 * states enabled.
	 * However, for non-A AUX ports the corresponding non-EDP transcoders
	 * would have already enabled power well 2 and DC_OFF. This means we can
	 * acquire a wider POWER_DOMAIN_AUX_{B,C,D,F} reference instead of a
	 * specific AUX_IO reference without powering up any extra wells.
	 * Note that PSR is enabled only on Port A even though this function
	 * returns the correct domain for other ports too.
	 * disabled. Accordingly use the AUX_IO_<port> power domain here which
	 * leaves DC states enabled.
	 *
	 * Before MTL TypeC PHYs (in all TypeC modes and both DP/HDMI) also require
	 * AUX IO to be enabled, but all these require DC_OFF to be enabled as
	 * well, so we can acquire a wider AUX_<port> power domain reference
	 * instead of a specific AUX_IO_<port> reference without powering up any
	 * extra wells.
	 */
	if (intel_encoder_can_psr(&dig_port->base))
		return intel_display_power_aux_io_domain(i915, dig_port->aux_ch);
	else
	else if (intel_crtc_has_dp_encoder(crtc_state) ||
		 intel_phy_is_tc(i915, phy))
		return intel_aux_power_domain(dig_port);
	else
		return POWER_DOMAIN_INVALID;
}

static void
main_link_aux_power_domain_get(struct intel_digital_port *dig_port,
			       const struct intel_crtc_state *crtc_state)
{
	struct drm_i915_private *i915 = to_i915(dig_port->base.base.dev);
	enum intel_display_power_domain domain =
		intel_ddi_main_link_aux_domain(dig_port, crtc_state);

	drm_WARN_ON(&i915->drm, dig_port->aux_wakeref);

	if (domain == POWER_DOMAIN_INVALID)
		return;

	dig_port->aux_wakeref = intel_display_power_get(i915, domain);
}

static void
main_link_aux_power_domain_put(struct intel_digital_port *dig_port,
			       const struct intel_crtc_state *crtc_state)
{
	struct drm_i915_private *i915 = to_i915(dig_port->base.base.dev);
	enum intel_display_power_domain domain =
		intel_ddi_main_link_aux_domain(dig_port, crtc_state);
	intel_wakeref_t wf;

	wf = fetch_and_zero(&dig_port->aux_wakeref);
	if (!wf)
		return;

	intel_display_power_put(i915, domain, wf);
}

static void intel_ddi_get_power_domains(struct intel_encoder *encoder,
@@ -875,7 +913,6 @@ static void intel_ddi_get_power_domains(struct intel_encoder *encoder,
{
	struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
	struct intel_digital_port *dig_port;
	enum phy phy = intel_port_to_phy(dev_priv, encoder->port);

	/*
	 * TODO: Add support for MST encoders. Atm, the following should never
@@ -894,17 +931,7 @@ static void intel_ddi_get_power_domains(struct intel_encoder *encoder,
								   dig_port->ddi_io_power_domain);
	}

	/*
	 * AUX power is only needed for (e)DP mode, and for HDMI mode on TC
	 * ports.
	 */
	if (intel_crtc_has_dp_encoder(crtc_state) ||
	    intel_phy_is_tc(dev_priv, phy)) {
		drm_WARN_ON(&dev_priv->drm, dig_port->aux_wakeref);
		dig_port->aux_wakeref =
			intel_display_power_get(dev_priv,
						intel_ddi_main_link_aux_domain(dig_port));
	}
	main_link_aux_power_domain_get(dig_port, crtc_state);
}

void intel_ddi_enable_pipe_clock(struct intel_encoder *encoder,
@@ -2743,10 +2770,7 @@ static void intel_ddi_post_disable(struct intel_atomic_state *state,
		intel_ddi_post_disable_dp(state, encoder, old_crtc_state,
					  old_conn_state);

	if (intel_crtc_has_dp_encoder(old_crtc_state) || is_tc_port)
		intel_display_power_put(dev_priv,
					intel_ddi_main_link_aux_domain(dig_port),
					fetch_and_zero(&dig_port->aux_wakeref));
	main_link_aux_power_domain_put(dig_port, old_crtc_state);

	if (is_tc_port)
		intel_tc_port_put_link(dig_port);
@@ -3067,12 +3091,7 @@ intel_ddi_pre_pll_enable(struct intel_atomic_state *state,
	if (is_tc_port)
		intel_tc_port_get_link(dig_port, crtc_state->lane_count);

	if (intel_crtc_has_dp_encoder(crtc_state) || is_tc_port) {
		drm_WARN_ON(&dev_priv->drm, dig_port->aux_wakeref);
		dig_port->aux_wakeref =
			intel_display_power_get(dev_priv,
						intel_ddi_main_link_aux_domain(dig_port));
	}
	main_link_aux_power_domain_get(dig_port, crtc_state);

	if (is_tc_port && !intel_tc_port_in_tbt_alt_mode(dig_port))
		/*