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: Imre Deak <imre.deak@intel.com>
Reviewed-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
Link: https://patchwork.freedesktop.org/patch/msgid/20221114122251.21327-9-imre.deak@intel.com
This commit is contained in:
Imre Deak 2022-11-14 14:22:50 +02:00
parent 406a95df61
commit 637c7aa261
1 changed files with 52 additions and 33 deletions

View File

@ -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))
/*