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

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
Loading
Loading
Loading
Loading
+14 −48
Original line number Diff line number Diff line
@@ -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;
}
+57 −0
Original line number Diff line number Diff line
@@ -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) |		\
+29 −0
Original line number Diff line number Diff line
@@ -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,