Commit 6979cb9a authored by Imre Deak's avatar Imre Deak

drm/i915: Factor out helpers to get/put a set of tracked power domains

Factor out helper functions to get/put a set of power domains that are
tracked using their wakeref handles. The same is needed by the next
patch adding tracking for enabled CRTC power domains.

v2: s/uint64_t/u64/ (Chris)

Cc: Chris Wilson <chris@chris-wilson.co.uk>
Signed-off-by: default avatarImre Deak <imre.deak@intel.com>
Reviewed-by: default avatarChris Wilson <chris@chris-wilson.co.uk>
Link: https://patchwork.freedesktop.org/patch/msgid/20201201161340.2879202-1-imre.deak@intel.com
parent a9b5e83a
......@@ -11227,16 +11227,13 @@ static void hsw_get_ddi_pll(struct drm_i915_private *dev_priv, enum port port,
static bool hsw_get_transcoder_state(struct intel_crtc *crtc,
struct intel_crtc_state *pipe_config,
u64 *power_domain_mask,
intel_wakeref_t *wakerefs)
struct intel_display_power_domain_set *power_domain_set)
{
struct drm_device *dev = crtc->base.dev;
struct drm_i915_private *dev_priv = to_i915(dev);
enum intel_display_power_domain power_domain;
unsigned long panel_transcoder_mask = BIT(TRANSCODER_EDP);
unsigned long enabled_panel_transcoders = 0;
enum transcoder panel_transcoder;
intel_wakeref_t wf;
u32 tmp;
if (INTEL_GEN(dev_priv) >= 11)
......@@ -11307,16 +11304,10 @@ static bool hsw_get_transcoder_state(struct intel_crtc *crtc,
drm_WARN_ON(dev, (enabled_panel_transcoders & BIT(TRANSCODER_EDP)) &&
enabled_panel_transcoders != BIT(TRANSCODER_EDP));
power_domain = POWER_DOMAIN_TRANSCODER(pipe_config->cpu_transcoder);
drm_WARN_ON(dev, *power_domain_mask & BIT_ULL(power_domain));
wf = intel_display_power_get_if_enabled(dev_priv, power_domain);
if (!wf)
if (!intel_display_power_get_in_set_if_enabled(dev_priv, power_domain_set,
POWER_DOMAIN_TRANSCODER(pipe_config->cpu_transcoder)))
return false;
wakerefs[power_domain] = wf;
*power_domain_mask |= BIT_ULL(power_domain);
tmp = intel_de_read(dev_priv, PIPECONF(pipe_config->cpu_transcoder));
return tmp & PIPECONF_ENABLE;
......@@ -11324,14 +11315,11 @@ static bool hsw_get_transcoder_state(struct intel_crtc *crtc,
static bool bxt_get_dsi_transcoder_state(struct intel_crtc *crtc,
struct intel_crtc_state *pipe_config,
u64 *power_domain_mask,
intel_wakeref_t *wakerefs)
struct intel_display_power_domain_set *power_domain_set)
{
struct drm_device *dev = crtc->base.dev;
struct drm_i915_private *dev_priv = to_i915(dev);
enum intel_display_power_domain power_domain;
enum transcoder cpu_transcoder;
intel_wakeref_t wf;
enum port port;
u32 tmp;
......@@ -11341,16 +11329,10 @@ static bool bxt_get_dsi_transcoder_state(struct intel_crtc *crtc,
else
cpu_transcoder = TRANSCODER_DSI_C;
power_domain = POWER_DOMAIN_TRANSCODER(cpu_transcoder);
drm_WARN_ON(dev, *power_domain_mask & BIT_ULL(power_domain));
wf = intel_display_power_get_if_enabled(dev_priv, power_domain);
if (!wf)
if (!intel_display_power_get_in_set_if_enabled(dev_priv, power_domain_set,
POWER_DOMAIN_TRANSCODER(cpu_transcoder)))
continue;
wakerefs[power_domain] = wf;
*power_domain_mask |= BIT_ULL(power_domain);
/*
* The PLL needs to be enabled with a valid divider
* configuration, otherwise accessing DSI registers will hang
......@@ -11433,30 +11415,22 @@ static bool hsw_get_pipe_config(struct intel_crtc *crtc,
struct intel_crtc_state *pipe_config)
{
struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
intel_wakeref_t wakerefs[POWER_DOMAIN_NUM], wf;
enum intel_display_power_domain power_domain;
u64 power_domain_mask;
struct intel_display_power_domain_set power_domain_set = { };
bool active;
u32 tmp;
pipe_config->master_transcoder = INVALID_TRANSCODER;
power_domain = POWER_DOMAIN_PIPE(crtc->pipe);
wf = intel_display_power_get_if_enabled(dev_priv, power_domain);
if (!wf)
if (!intel_display_power_get_in_set_if_enabled(dev_priv, &power_domain_set,
POWER_DOMAIN_PIPE(crtc->pipe)))
return false;
wakerefs[power_domain] = wf;
power_domain_mask = BIT_ULL(power_domain);
pipe_config->shared_dpll = NULL;
active = hsw_get_transcoder_state(crtc, pipe_config,
&power_domain_mask, wakerefs);
active = hsw_get_transcoder_state(crtc, pipe_config, &power_domain_set);
if (IS_GEN9_LP(dev_priv) &&
bxt_get_dsi_transcoder_state(crtc, pipe_config,
&power_domain_mask, wakerefs)) {
bxt_get_dsi_transcoder_state(crtc, pipe_config, &power_domain_set)) {
drm_WARN_ON(&dev_priv->drm, active);
active = true;
}
......@@ -11520,14 +11494,8 @@ static bool hsw_get_pipe_config(struct intel_crtc *crtc,
pipe_config->ips_linetime =
REG_FIELD_GET(HSW_IPS_LINETIME_MASK, tmp);
power_domain = POWER_DOMAIN_PIPE_PANEL_FITTER(crtc->pipe);
drm_WARN_ON(&dev_priv->drm, power_domain_mask & BIT_ULL(power_domain));
wf = intel_display_power_get_if_enabled(dev_priv, power_domain);
if (wf) {
wakerefs[power_domain] = wf;
power_domain_mask |= BIT_ULL(power_domain);
if (intel_display_power_get_in_set_if_enabled(dev_priv, &power_domain_set,
POWER_DOMAIN_PIPE_PANEL_FITTER(crtc->pipe))) {
if (INTEL_GEN(dev_priv) >= 9)
skl_get_pfit_config(pipe_config);
else
......@@ -11561,9 +11529,7 @@ static bool hsw_get_pipe_config(struct intel_crtc *crtc,
}
out:
for_each_power_domain(power_domain, power_domain_mask)
intel_display_power_put(dev_priv,
power_domain, wakerefs[power_domain]);
intel_display_power_put_all_in_set(dev_priv, &power_domain_set);
return active;
}
......
......@@ -2412,6 +2412,63 @@ void intel_display_power_put(struct drm_i915_private *dev_priv,
}
#endif
void
intel_display_power_get_in_set(struct drm_i915_private *i915,
struct intel_display_power_domain_set *power_domain_set,
enum intel_display_power_domain domain)
{
intel_wakeref_t __maybe_unused wf;
drm_WARN_ON(&i915->drm, power_domain_set->mask & BIT_ULL(domain));
wf = intel_display_power_get(i915, domain);
#if IS_ENABLED(CONFIG_DRM_I915_DEBUG_RUNTIME_PM)
power_domain_set->wakerefs[domain] = wf;
#endif
power_domain_set->mask |= BIT_ULL(domain);
}
bool
intel_display_power_get_in_set_if_enabled(struct drm_i915_private *i915,
struct intel_display_power_domain_set *power_domain_set,
enum intel_display_power_domain domain)
{
intel_wakeref_t wf;
drm_WARN_ON(&i915->drm, power_domain_set->mask & BIT_ULL(domain));
wf = intel_display_power_get_if_enabled(i915, domain);
if (!wf)
return false;
#if IS_ENABLED(CONFIG_DRM_I915_DEBUG_RUNTIME_PM)
power_domain_set->wakerefs[domain] = wf;
#endif
power_domain_set->mask |= BIT_ULL(domain);
return true;
}
void
intel_display_power_put_mask_in_set(struct drm_i915_private *i915,
struct intel_display_power_domain_set *power_domain_set,
u64 mask)
{
enum intel_display_power_domain domain;
drm_WARN_ON(&i915->drm, mask & ~power_domain_set->mask);
for_each_power_domain(domain, mask) {
intel_wakeref_t __maybe_unused wf = -1;
#if IS_ENABLED(CONFIG_DRM_I915_DEBUG_RUNTIME_PM)
wf = fetch_and_zero(&power_domain_set->wakerefs[domain]);
#endif
intel_display_power_put(i915, domain, wf);
power_domain_set->mask &= ~BIT_ULL(domain);
}
}
#define I830_PIPES_POWER_DOMAINS ( \
BIT_ULL(POWER_DOMAIN_PIPE_A) | \
BIT_ULL(POWER_DOMAIN_PIPE_B) | \
......
......@@ -224,6 +224,13 @@ struct i915_power_domains {
struct i915_power_well *power_wells;
};
struct intel_display_power_domain_set {
u64 mask;
#ifdef CONFIG_DRM_I915_DEBUG_RUNTIME_PM
intel_wakeref_t wakerefs[POWER_DOMAIN_NUM];
#endif
};
#define for_each_power_domain(domain, mask) \
for ((domain) = 0; (domain) < POWER_DOMAIN_NUM; (domain)++) \
for_each_if(BIT_ULL(domain) & (mask))
......@@ -314,6 +321,28 @@ intel_display_power_put_async(struct drm_i915_private *i915,
}
#endif
void
intel_display_power_get_in_set(struct drm_i915_private *i915,
struct intel_display_power_domain_set *power_domain_set,
enum intel_display_power_domain domain);
bool
intel_display_power_get_in_set_if_enabled(struct drm_i915_private *i915,
struct intel_display_power_domain_set *power_domain_set,
enum intel_display_power_domain domain);
void
intel_display_power_put_mask_in_set(struct drm_i915_private *i915,
struct intel_display_power_domain_set *power_domain_set,
u64 mask);
static inline void
intel_display_power_put_all_in_set(struct drm_i915_private *i915,
struct intel_display_power_domain_set *power_domain_set)
{
intel_display_power_put_mask_in_set(i915, power_domain_set, power_domain_set->mask);
}
enum dbuf_slice {
DBUF_S1,
DBUF_S2,
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment