diff options
Diffstat (limited to 'drivers/gpu/drm/i915/intel_runtime_pm.c')
| -rw-r--r-- | drivers/gpu/drm/i915/intel_runtime_pm.c | 1028 | 
1 files changed, 492 insertions, 536 deletions
| diff --git a/drivers/gpu/drm/i915/intel_runtime_pm.c b/drivers/gpu/drm/i915/intel_runtime_pm.c index efe80ed5fd4d..b66d8e136aa3 100644 --- a/drivers/gpu/drm/i915/intel_runtime_pm.c +++ b/drivers/gpu/drm/i915/intel_runtime_pm.c @@ -50,10 +50,11 @@   */  bool intel_display_power_well_is_enabled(struct drm_i915_private *dev_priv, -				    int power_well_id); +					 enum i915_power_well_id power_well_id);  static struct i915_power_well * -lookup_power_well(struct drm_i915_private *dev_priv, int power_well_id); +lookup_power_well(struct drm_i915_private *dev_priv, +		  enum i915_power_well_id power_well_id);  const char *  intel_display_power_domain_str(enum intel_display_power_domain domain) @@ -168,18 +169,6 @@ static void intel_power_well_put(struct drm_i915_private *dev_priv,  		intel_power_well_disable(dev_priv, power_well);  } -/* - * We should only use the power well if we explicitly asked the hardware to - * enable it, so check if it's enabled and also check if we've requested it to - * be enabled. - */ -static bool hsw_power_well_enabled(struct drm_i915_private *dev_priv, -				   struct i915_power_well *power_well) -{ -	return I915_READ(HSW_PWR_WELL_DRIVER) == -		     (HSW_PWR_WELL_ENABLE_REQUEST | HSW_PWR_WELL_STATE_ENABLED); -} -  /**   * __intel_display_power_is_enabled - unlocked check for a power domain   * @dev_priv: i915 device instance @@ -278,7 +267,8 @@ void intel_display_set_init_power(struct drm_i915_private *dev_priv,   * to be enabled, and it will only be disabled if none of the registers is   * requesting it to be enabled.   */ -static void hsw_power_well_post_enable(struct drm_i915_private *dev_priv) +static void hsw_power_well_post_enable(struct drm_i915_private *dev_priv, +				       u8 irq_pipe_mask, bool has_vga)  {  	struct pci_dev *pdev = dev_priv->drm.pdev; @@ -292,264 +282,158 @@ static void hsw_power_well_post_enable(struct drm_i915_private *dev_priv)  	 * sure vgacon can keep working normally without triggering interrupts  	 * and error messages.  	 */ -	vga_get_uninterruptible(pdev, VGA_RSRC_LEGACY_IO); -	outb(inb(VGA_MSR_READ), VGA_MSR_WRITE); -	vga_put(pdev, VGA_RSRC_LEGACY_IO); +	if (has_vga) { +		vga_get_uninterruptible(pdev, VGA_RSRC_LEGACY_IO); +		outb(inb(VGA_MSR_READ), VGA_MSR_WRITE); +		vga_put(pdev, VGA_RSRC_LEGACY_IO); +	} -	if (IS_BROADWELL(dev_priv)) -		gen8_irq_power_well_post_enable(dev_priv, -						1 << PIPE_C | 1 << PIPE_B); +	if (irq_pipe_mask) +		gen8_irq_power_well_post_enable(dev_priv, irq_pipe_mask);  } -static void hsw_power_well_pre_disable(struct drm_i915_private *dev_priv) +static void hsw_power_well_pre_disable(struct drm_i915_private *dev_priv, +				       u8 irq_pipe_mask)  { -	if (IS_BROADWELL(dev_priv)) -		gen8_irq_power_well_pre_disable(dev_priv, -						1 << PIPE_C | 1 << PIPE_B); +	if (irq_pipe_mask) +		gen8_irq_power_well_pre_disable(dev_priv, irq_pipe_mask);  } -static void skl_power_well_post_enable(struct drm_i915_private *dev_priv, -				       struct i915_power_well *power_well) + +static void hsw_wait_for_power_well_enable(struct drm_i915_private *dev_priv, +					   struct i915_power_well *power_well)  { -	struct pci_dev *pdev = dev_priv->drm.pdev; +	enum i915_power_well_id id = power_well->id; + +	/* Timeout for PW1:10 us, AUX:not specified, other PWs:20 us. */ +	WARN_ON(intel_wait_for_register(dev_priv, +					HSW_PWR_WELL_CTL_DRIVER(id), +					HSW_PWR_WELL_CTL_STATE(id), +					HSW_PWR_WELL_CTL_STATE(id), +					1)); +} + +static u32 hsw_power_well_requesters(struct drm_i915_private *dev_priv, +				     enum i915_power_well_id id) +{ +	u32 req_mask = HSW_PWR_WELL_CTL_REQ(id); +	u32 ret; + +	ret = I915_READ(HSW_PWR_WELL_CTL_BIOS(id)) & req_mask ? 1 : 0; +	ret |= I915_READ(HSW_PWR_WELL_CTL_DRIVER(id)) & req_mask ? 2 : 0; +	ret |= I915_READ(HSW_PWR_WELL_CTL_KVMR) & req_mask ? 4 : 0; +	ret |= I915_READ(HSW_PWR_WELL_CTL_DEBUG(id)) & req_mask ? 8 : 0; + +	return ret; +} + +static void hsw_wait_for_power_well_disable(struct drm_i915_private *dev_priv, +					    struct i915_power_well *power_well) +{ +	enum i915_power_well_id id = power_well->id; +	bool disabled; +	u32 reqs;  	/* -	 * After we re-enable the power well, if we touch VGA register 0x3d5 -	 * we'll get unclaimed register interrupts. This stops after we write -	 * anything to the VGA MSR register. The vgacon module uses this -	 * register all the time, so if we unbind our driver and, as a -	 * consequence, bind vgacon, we'll get stuck in an infinite loop at -	 * console_unlock(). So make here we touch the VGA MSR register, making -	 * sure vgacon can keep working normally without triggering interrupts -	 * and error messages. +	 * Bspec doesn't require waiting for PWs to get disabled, but still do +	 * this for paranoia. The known cases where a PW will be forced on: +	 * - a KVMR request on any power well via the KVMR request register +	 * - a DMC request on PW1 and MISC_IO power wells via the BIOS and +	 *   DEBUG request registers +	 * Skip the wait in case any of the request bits are set and print a +	 * diagnostic message.  	 */ -	if (power_well->id == SKL_DISP_PW_2) { -		vga_get_uninterruptible(pdev, VGA_RSRC_LEGACY_IO); -		outb(inb(VGA_MSR_READ), VGA_MSR_WRITE); -		vga_put(pdev, VGA_RSRC_LEGACY_IO); +	wait_for((disabled = !(I915_READ(HSW_PWR_WELL_CTL_DRIVER(id)) & +			       HSW_PWR_WELL_CTL_STATE(id))) || +		 (reqs = hsw_power_well_requesters(dev_priv, id)), 1); +	if (disabled) +		return; -		gen8_irq_power_well_post_enable(dev_priv, -						1 << PIPE_C | 1 << PIPE_B); -	} +	DRM_DEBUG_KMS("%s forced on (bios:%d driver:%d kvmr:%d debug:%d)\n", +		      power_well->name, +		      !!(reqs & 1), !!(reqs & 2), !!(reqs & 4), !!(reqs & 8));  } -static void skl_power_well_pre_disable(struct drm_i915_private *dev_priv, -				       struct i915_power_well *power_well) +static void gen9_wait_for_power_well_fuses(struct drm_i915_private *dev_priv, +					   enum skl_power_gate pg)  { -	if (power_well->id == SKL_DISP_PW_2) -		gen8_irq_power_well_pre_disable(dev_priv, -						1 << PIPE_C | 1 << PIPE_B); +	/* Timeout 5us for PG#0, for other PGs 1us */ +	WARN_ON(intel_wait_for_register(dev_priv, SKL_FUSE_STATUS, +					SKL_FUSE_PG_DIST_STATUS(pg), +					SKL_FUSE_PG_DIST_STATUS(pg), 1));  } -static void hsw_set_power_well(struct drm_i915_private *dev_priv, -			       struct i915_power_well *power_well, bool enable) +static void hsw_power_well_enable(struct drm_i915_private *dev_priv, +				  struct i915_power_well *power_well)  { -	bool is_enabled, enable_requested; -	uint32_t tmp; - -	tmp = I915_READ(HSW_PWR_WELL_DRIVER); -	is_enabled = tmp & HSW_PWR_WELL_STATE_ENABLED; -	enable_requested = tmp & HSW_PWR_WELL_ENABLE_REQUEST; - -	if (enable) { -		if (!enable_requested) -			I915_WRITE(HSW_PWR_WELL_DRIVER, -				   HSW_PWR_WELL_ENABLE_REQUEST); - -		if (!is_enabled) { -			DRM_DEBUG_KMS("Enabling power well\n"); -			if (intel_wait_for_register(dev_priv, -						    HSW_PWR_WELL_DRIVER, -						    HSW_PWR_WELL_STATE_ENABLED, -						    HSW_PWR_WELL_STATE_ENABLED, -						    20)) -				DRM_ERROR("Timeout enabling power well\n"); -			hsw_power_well_post_enable(dev_priv); -		} +	enum i915_power_well_id id = power_well->id; +	bool wait_fuses = power_well->hsw.has_fuses; +	enum skl_power_gate pg; +	u32 val; -	} else { -		if (enable_requested) { -			hsw_power_well_pre_disable(dev_priv); -			I915_WRITE(HSW_PWR_WELL_DRIVER, 0); -			POSTING_READ(HSW_PWR_WELL_DRIVER); -			DRM_DEBUG_KMS("Requesting to disable the power well\n"); -		} +	if (wait_fuses) { +		pg = SKL_PW_TO_PG(id); +		/* +		 * For PW1 we have to wait both for the PW0/PG0 fuse state +		 * before enabling the power well and PW1/PG1's own fuse +		 * state after the enabling. For all other power wells with +		 * fuses we only have to wait for that PW/PG's fuse state +		 * after the enabling. +		 */ +		if (pg == SKL_PG1) +			gen9_wait_for_power_well_fuses(dev_priv, SKL_PG0);  	} + +	val = I915_READ(HSW_PWR_WELL_CTL_DRIVER(id)); +	I915_WRITE(HSW_PWR_WELL_CTL_DRIVER(id), val | HSW_PWR_WELL_CTL_REQ(id)); +	hsw_wait_for_power_well_enable(dev_priv, power_well); + +	if (wait_fuses) +		gen9_wait_for_power_well_fuses(dev_priv, pg); + +	hsw_power_well_post_enable(dev_priv, power_well->hsw.irq_pipe_mask, +				   power_well->hsw.has_vga);  } -#define SKL_DISPLAY_POWERWELL_2_POWER_DOMAINS (		\ -	BIT_ULL(POWER_DOMAIN_TRANSCODER_A) |		\ -	BIT_ULL(POWER_DOMAIN_PIPE_B) |			\ -	BIT_ULL(POWER_DOMAIN_TRANSCODER_B) |		\ -	BIT_ULL(POWER_DOMAIN_PIPE_C) |			\ -	BIT_ULL(POWER_DOMAIN_TRANSCODER_C) |		\ -	BIT_ULL(POWER_DOMAIN_PIPE_B_PANEL_FITTER) |		\ -	BIT_ULL(POWER_DOMAIN_PIPE_C_PANEL_FITTER) |		\ -	BIT_ULL(POWER_DOMAIN_PORT_DDI_B_LANES) |		\ -	BIT_ULL(POWER_DOMAIN_PORT_DDI_C_LANES) |		\ -	BIT_ULL(POWER_DOMAIN_PORT_DDI_D_LANES) |		\ -	BIT_ULL(POWER_DOMAIN_PORT_DDI_E_LANES) |		\ -	BIT_ULL(POWER_DOMAIN_AUX_B) |                       \ -	BIT_ULL(POWER_DOMAIN_AUX_C) |			\ -	BIT_ULL(POWER_DOMAIN_AUX_D) |			\ -	BIT_ULL(POWER_DOMAIN_AUDIO) |			\ -	BIT_ULL(POWER_DOMAIN_VGA) |				\ -	BIT_ULL(POWER_DOMAIN_INIT)) -#define SKL_DISPLAY_DDI_IO_A_E_POWER_DOMAINS (		\ -	BIT_ULL(POWER_DOMAIN_PORT_DDI_A_IO) |		\ -	BIT_ULL(POWER_DOMAIN_PORT_DDI_E_IO) |		\ -	BIT_ULL(POWER_DOMAIN_INIT)) -#define SKL_DISPLAY_DDI_IO_B_POWER_DOMAINS (		\ -	BIT_ULL(POWER_DOMAIN_PORT_DDI_B_IO) |		\ -	BIT_ULL(POWER_DOMAIN_INIT)) -#define SKL_DISPLAY_DDI_IO_C_POWER_DOMAINS (		\ -	BIT_ULL(POWER_DOMAIN_PORT_DDI_C_IO) |		\ -	BIT_ULL(POWER_DOMAIN_INIT)) -#define SKL_DISPLAY_DDI_IO_D_POWER_DOMAINS (		\ -	BIT_ULL(POWER_DOMAIN_PORT_DDI_D_IO) |		\ -	BIT_ULL(POWER_DOMAIN_INIT)) -#define SKL_DISPLAY_DC_OFF_POWER_DOMAINS (		\ -	SKL_DISPLAY_POWERWELL_2_POWER_DOMAINS |		\ -	BIT_ULL(POWER_DOMAIN_MODESET) |			\ -	BIT_ULL(POWER_DOMAIN_AUX_A) |			\ -	BIT_ULL(POWER_DOMAIN_INIT)) +static void hsw_power_well_disable(struct drm_i915_private *dev_priv, +				   struct i915_power_well *power_well) +{ +	enum i915_power_well_id id = power_well->id; +	u32 val; -#define BXT_DISPLAY_POWERWELL_2_POWER_DOMAINS (		\ -	BIT_ULL(POWER_DOMAIN_TRANSCODER_A) |		\ -	BIT_ULL(POWER_DOMAIN_PIPE_B) |			\ -	BIT_ULL(POWER_DOMAIN_TRANSCODER_B) |		\ -	BIT_ULL(POWER_DOMAIN_PIPE_C) |			\ -	BIT_ULL(POWER_DOMAIN_TRANSCODER_C) |		\ -	BIT_ULL(POWER_DOMAIN_PIPE_B_PANEL_FITTER) |		\ -	BIT_ULL(POWER_DOMAIN_PIPE_C_PANEL_FITTER) |		\ -	BIT_ULL(POWER_DOMAIN_PORT_DDI_B_LANES) |		\ -	BIT_ULL(POWER_DOMAIN_PORT_DDI_C_LANES) |		\ -	BIT_ULL(POWER_DOMAIN_AUX_B) |			\ -	BIT_ULL(POWER_DOMAIN_AUX_C) |			\ -	BIT_ULL(POWER_DOMAIN_AUDIO) |			\ -	BIT_ULL(POWER_DOMAIN_VGA) |				\ -	BIT_ULL(POWER_DOMAIN_GMBUS) |			\ -	BIT_ULL(POWER_DOMAIN_INIT)) -#define BXT_DISPLAY_DC_OFF_POWER_DOMAINS (		\ -	BXT_DISPLAY_POWERWELL_2_POWER_DOMAINS |		\ -	BIT_ULL(POWER_DOMAIN_MODESET) |			\ -	BIT_ULL(POWER_DOMAIN_AUX_A) |			\ -	BIT_ULL(POWER_DOMAIN_INIT)) -#define BXT_DPIO_CMN_A_POWER_DOMAINS (			\ -	BIT_ULL(POWER_DOMAIN_PORT_DDI_A_LANES) |		\ -	BIT_ULL(POWER_DOMAIN_AUX_A) |			\ -	BIT_ULL(POWER_DOMAIN_INIT)) -#define BXT_DPIO_CMN_BC_POWER_DOMAINS (			\ -	BIT_ULL(POWER_DOMAIN_PORT_DDI_B_LANES) |		\ -	BIT_ULL(POWER_DOMAIN_PORT_DDI_C_LANES) |		\ -	BIT_ULL(POWER_DOMAIN_AUX_B) |			\ -	BIT_ULL(POWER_DOMAIN_AUX_C) |			\ -	BIT_ULL(POWER_DOMAIN_INIT)) +	hsw_power_well_pre_disable(dev_priv, power_well->hsw.irq_pipe_mask); -#define GLK_DISPLAY_POWERWELL_2_POWER_DOMAINS (		\ -	BIT_ULL(POWER_DOMAIN_TRANSCODER_A) |		\ -	BIT_ULL(POWER_DOMAIN_PIPE_B) |			\ -	BIT_ULL(POWER_DOMAIN_TRANSCODER_B) |		\ -	BIT_ULL(POWER_DOMAIN_PIPE_C) |			\ -	BIT_ULL(POWER_DOMAIN_TRANSCODER_C) |		\ -	BIT_ULL(POWER_DOMAIN_PIPE_B_PANEL_FITTER) |		\ -	BIT_ULL(POWER_DOMAIN_PIPE_C_PANEL_FITTER) |		\ -	BIT_ULL(POWER_DOMAIN_PORT_DDI_B_LANES) |		\ -	BIT_ULL(POWER_DOMAIN_PORT_DDI_C_LANES) |		\ -	BIT_ULL(POWER_DOMAIN_AUX_B) |                       \ -	BIT_ULL(POWER_DOMAIN_AUX_C) |			\ -	BIT_ULL(POWER_DOMAIN_AUDIO) |			\ -	BIT_ULL(POWER_DOMAIN_VGA) |				\ -	BIT_ULL(POWER_DOMAIN_INIT)) -#define GLK_DISPLAY_DDI_IO_A_POWER_DOMAINS (		\ -	BIT_ULL(POWER_DOMAIN_PORT_DDI_A_IO)) -#define GLK_DISPLAY_DDI_IO_B_POWER_DOMAINS (		\ -	BIT_ULL(POWER_DOMAIN_PORT_DDI_B_IO)) -#define GLK_DISPLAY_DDI_IO_C_POWER_DOMAINS (		\ -	BIT_ULL(POWER_DOMAIN_PORT_DDI_C_IO)) -#define GLK_DPIO_CMN_A_POWER_DOMAINS (			\ -	BIT_ULL(POWER_DOMAIN_PORT_DDI_A_LANES) |		\ -	BIT_ULL(POWER_DOMAIN_AUX_A) |			\ -	BIT_ULL(POWER_DOMAIN_INIT)) -#define GLK_DPIO_CMN_B_POWER_DOMAINS (			\ -	BIT_ULL(POWER_DOMAIN_PORT_DDI_B_LANES) |		\ -	BIT_ULL(POWER_DOMAIN_AUX_B) |			\ -	BIT_ULL(POWER_DOMAIN_INIT)) -#define GLK_DPIO_CMN_C_POWER_DOMAINS (			\ -	BIT_ULL(POWER_DOMAIN_PORT_DDI_C_LANES) |		\ -	BIT_ULL(POWER_DOMAIN_AUX_C) |			\ -	BIT_ULL(POWER_DOMAIN_INIT)) -#define GLK_DISPLAY_AUX_A_POWER_DOMAINS (		\ -	BIT_ULL(POWER_DOMAIN_AUX_A) |		\ -	BIT_ULL(POWER_DOMAIN_INIT)) -#define GLK_DISPLAY_AUX_B_POWER_DOMAINS (		\ -	BIT_ULL(POWER_DOMAIN_AUX_B) |		\ -	BIT_ULL(POWER_DOMAIN_INIT)) -#define GLK_DISPLAY_AUX_C_POWER_DOMAINS (		\ -	BIT_ULL(POWER_DOMAIN_AUX_C) |		\ -	BIT_ULL(POWER_DOMAIN_INIT)) -#define GLK_DISPLAY_DC_OFF_POWER_DOMAINS (		\ -	GLK_DISPLAY_POWERWELL_2_POWER_DOMAINS |		\ -	BIT_ULL(POWER_DOMAIN_MODESET) |			\ -	BIT_ULL(POWER_DOMAIN_AUX_A) |			\ -	BIT_ULL(POWER_DOMAIN_INIT)) +	val = I915_READ(HSW_PWR_WELL_CTL_DRIVER(id)); +	I915_WRITE(HSW_PWR_WELL_CTL_DRIVER(id), +		   val & ~HSW_PWR_WELL_CTL_REQ(id)); +	hsw_wait_for_power_well_disable(dev_priv, power_well); +} -#define CNL_DISPLAY_POWERWELL_2_POWER_DOMAINS (		\ -	BIT_ULL(POWER_DOMAIN_TRANSCODER_A) |		\ -	BIT_ULL(POWER_DOMAIN_PIPE_B) |			\ -	BIT_ULL(POWER_DOMAIN_TRANSCODER_B) |		\ -	BIT_ULL(POWER_DOMAIN_PIPE_C) |			\ -	BIT_ULL(POWER_DOMAIN_TRANSCODER_C) |		\ -	BIT_ULL(POWER_DOMAIN_PIPE_B_PANEL_FITTER) |		\ -	BIT_ULL(POWER_DOMAIN_PIPE_C_PANEL_FITTER) |		\ -	BIT_ULL(POWER_DOMAIN_PORT_DDI_B_LANES) |		\ -	BIT_ULL(POWER_DOMAIN_PORT_DDI_C_LANES) |		\ -	BIT_ULL(POWER_DOMAIN_PORT_DDI_D_LANES) |		\ -	BIT_ULL(POWER_DOMAIN_PORT_DDI_E_LANES) |		\ -	BIT_ULL(POWER_DOMAIN_AUX_B) |                       \ -	BIT_ULL(POWER_DOMAIN_AUX_C) |			\ -	BIT_ULL(POWER_DOMAIN_AUX_D) |			\ -	BIT_ULL(POWER_DOMAIN_AUDIO) |			\ -	BIT_ULL(POWER_DOMAIN_VGA) |				\ -	BIT_ULL(POWER_DOMAIN_INIT)) -#define CNL_DISPLAY_DDI_A_IO_POWER_DOMAINS (		\ -	BIT_ULL(POWER_DOMAIN_PORT_DDI_A_IO) |		\ -	BIT_ULL(POWER_DOMAIN_PORT_DDI_E_IO) |		\ -	BIT_ULL(POWER_DOMAIN_INIT)) -#define CNL_DISPLAY_DDI_B_IO_POWER_DOMAINS (		\ -	BIT_ULL(POWER_DOMAIN_PORT_DDI_B_IO) |		\ -	BIT_ULL(POWER_DOMAIN_INIT)) -#define CNL_DISPLAY_DDI_C_IO_POWER_DOMAINS (		\ -	BIT_ULL(POWER_DOMAIN_PORT_DDI_C_IO) |		\ -	BIT_ULL(POWER_DOMAIN_INIT)) -#define CNL_DISPLAY_DDI_D_IO_POWER_DOMAINS (		\ -	BIT_ULL(POWER_DOMAIN_PORT_DDI_D_IO) |		\ -	BIT_ULL(POWER_DOMAIN_INIT)) -#define CNL_DISPLAY_AUX_A_POWER_DOMAINS (		\ -	BIT_ULL(POWER_DOMAIN_AUX_A) |			\ -	BIT_ULL(POWER_DOMAIN_INIT)) -#define CNL_DISPLAY_AUX_B_POWER_DOMAINS (		\ -	BIT_ULL(POWER_DOMAIN_AUX_B) |			\ -	BIT_ULL(POWER_DOMAIN_INIT)) -#define CNL_DISPLAY_AUX_C_POWER_DOMAINS (		\ -	BIT_ULL(POWER_DOMAIN_AUX_C) |			\ -	BIT_ULL(POWER_DOMAIN_INIT)) -#define CNL_DISPLAY_AUX_D_POWER_DOMAINS (		\ -	BIT_ULL(POWER_DOMAIN_AUX_D) |			\ -	BIT_ULL(POWER_DOMAIN_INIT)) -#define CNL_DISPLAY_DC_OFF_POWER_DOMAINS (		\ -	CNL_DISPLAY_POWERWELL_2_POWER_DOMAINS |		\ -	BIT_ULL(POWER_DOMAIN_MODESET) |			\ -	BIT_ULL(POWER_DOMAIN_AUX_A) |			\ -	BIT_ULL(POWER_DOMAIN_INIT)) +/* + * We should only use the power well if we explicitly asked the hardware to + * enable it, so check if it's enabled and also check if we've requested it to + * be enabled. + */ +static bool hsw_power_well_enabled(struct drm_i915_private *dev_priv, +				   struct i915_power_well *power_well) +{ +	enum i915_power_well_id id = power_well->id; +	u32 mask = HSW_PWR_WELL_CTL_REQ(id) | HSW_PWR_WELL_CTL_STATE(id); + +	return (I915_READ(HSW_PWR_WELL_CTL_DRIVER(id)) & mask) == mask; +}  static void assert_can_enable_dc9(struct drm_i915_private *dev_priv)  { +	enum i915_power_well_id id = SKL_DISP_PW_2; +  	WARN_ONCE((I915_READ(DC_STATE_EN) & DC_STATE_EN_DC9),  		  "DC9 already programmed to be enabled.\n");  	WARN_ONCE(I915_READ(DC_STATE_EN) & DC_STATE_EN_UPTO_DC5,  		  "DC5 still not disabled to enable DC9.\n"); -	WARN_ONCE(I915_READ(HSW_PWR_WELL_DRIVER), "Power well on.\n"); +	WARN_ONCE(I915_READ(HSW_PWR_WELL_CTL_DRIVER(id)) & +		  HSW_PWR_WELL_CTL_REQ(id), +		  "Power well 2 on.\n");  	WARN_ONCE(intel_irqs_enabled(dev_priv),  		  "Interrupts not disabled yet.\n"); @@ -744,223 +628,39 @@ void skl_disable_dc6(struct drm_i915_private *dev_priv)  	gen9_set_dc_state(dev_priv, DC_STATE_DISABLE);  } -static void -gen9_sanitize_power_well_requests(struct drm_i915_private *dev_priv, -				  struct i915_power_well *power_well) -{ -	enum skl_disp_power_wells power_well_id = power_well->id; -	u32 val; -	u32 mask; - -	mask = SKL_POWER_WELL_REQ(power_well_id); - -	val = I915_READ(HSW_PWR_WELL_KVMR); -	if (WARN_ONCE(val & mask, "Clearing unexpected KVMR request for %s\n", -		      power_well->name)) -		I915_WRITE(HSW_PWR_WELL_KVMR, val & ~mask); - -	val = I915_READ(HSW_PWR_WELL_BIOS); -	val |= I915_READ(HSW_PWR_WELL_DEBUG); - -	if (!(val & mask)) -		return; - -	/* -	 * DMC is known to force on the request bits for power well 1 on SKL -	 * and BXT and the misc IO power well on SKL but we don't expect any -	 * other request bits to be set, so WARN for those. -	 */ -	if (power_well_id == SKL_DISP_PW_1 || -	    (IS_GEN9_BC(dev_priv) && -	     power_well_id == SKL_DISP_PW_MISC_IO)) -		DRM_DEBUG_DRIVER("Clearing auxiliary requests for %s forced on " -				 "by DMC\n", power_well->name); -	else -		WARN_ONCE(1, "Clearing unexpected auxiliary requests for %s\n", -			  power_well->name); - -	I915_WRITE(HSW_PWR_WELL_BIOS, val & ~mask); -	I915_WRITE(HSW_PWR_WELL_DEBUG, val & ~mask); -} - -static void skl_set_power_well(struct drm_i915_private *dev_priv, -			       struct i915_power_well *power_well, bool enable) -{ -	uint32_t tmp, fuse_status; -	uint32_t req_mask, state_mask; -	bool is_enabled, enable_requested, check_fuse_status = false; - -	tmp = I915_READ(HSW_PWR_WELL_DRIVER); -	fuse_status = I915_READ(SKL_FUSE_STATUS); - -	switch (power_well->id) { -	case SKL_DISP_PW_1: -		if (intel_wait_for_register(dev_priv, -					    SKL_FUSE_STATUS, -					    SKL_FUSE_PG0_DIST_STATUS, -					    SKL_FUSE_PG0_DIST_STATUS, -					    1)) { -			DRM_ERROR("PG0 not enabled\n"); -			return; -		} -		break; -	case SKL_DISP_PW_2: -		if (!(fuse_status & SKL_FUSE_PG1_DIST_STATUS)) { -			DRM_ERROR("PG1 in disabled state\n"); -			return; -		} -		break; -	case SKL_DISP_PW_MISC_IO: -	case SKL_DISP_PW_DDI_A_E: /* GLK_DISP_PW_DDI_A, CNL_DISP_PW_DDI_A */ -	case SKL_DISP_PW_DDI_B: -	case SKL_DISP_PW_DDI_C: -	case SKL_DISP_PW_DDI_D: -	case GLK_DISP_PW_AUX_A: /* CNL_DISP_PW_AUX_A */ -	case GLK_DISP_PW_AUX_B: /* CNL_DISP_PW_AUX_B */ -	case GLK_DISP_PW_AUX_C: /* CNL_DISP_PW_AUX_C */ -	case CNL_DISP_PW_AUX_D: -		break; -	default: -		WARN(1, "Unknown power well %lu\n", power_well->id); -		return; -	} - -	req_mask = SKL_POWER_WELL_REQ(power_well->id); -	enable_requested = tmp & req_mask; -	state_mask = SKL_POWER_WELL_STATE(power_well->id); -	is_enabled = tmp & state_mask; - -	if (!enable && enable_requested) -		skl_power_well_pre_disable(dev_priv, power_well); - -	if (enable) { -		if (!enable_requested) { -			WARN((tmp & state_mask) && -				!I915_READ(HSW_PWR_WELL_BIOS), -				"Invalid for power well status to be enabled, unless done by the BIOS, \ -				when request is to disable!\n"); -			I915_WRITE(HSW_PWR_WELL_DRIVER, tmp | req_mask); -		} - -		if (!is_enabled) { -			DRM_DEBUG_KMS("Enabling %s\n", power_well->name); -			check_fuse_status = true; -		} -	} else { -		if (enable_requested) { -			I915_WRITE(HSW_PWR_WELL_DRIVER,	tmp & ~req_mask); -			POSTING_READ(HSW_PWR_WELL_DRIVER); -			DRM_DEBUG_KMS("Disabling %s\n", power_well->name); -		} - -		gen9_sanitize_power_well_requests(dev_priv, power_well); -	} - -	if (wait_for(!!(I915_READ(HSW_PWR_WELL_DRIVER) & state_mask) == enable, -		     1)) -		DRM_ERROR("%s %s timeout\n", -			  power_well->name, enable ? "enable" : "disable"); - -	if (check_fuse_status) { -		if (power_well->id == SKL_DISP_PW_1) { -			if (intel_wait_for_register(dev_priv, -						    SKL_FUSE_STATUS, -						    SKL_FUSE_PG1_DIST_STATUS, -						    SKL_FUSE_PG1_DIST_STATUS, -						    1)) -				DRM_ERROR("PG1 distributing status timeout\n"); -		} else if (power_well->id == SKL_DISP_PW_2) { -			if (intel_wait_for_register(dev_priv, -						    SKL_FUSE_STATUS, -						    SKL_FUSE_PG2_DIST_STATUS, -						    SKL_FUSE_PG2_DIST_STATUS, -						    1)) -				DRM_ERROR("PG2 distributing status timeout\n"); -		} -	} - -	if (enable && !is_enabled) -		skl_power_well_post_enable(dev_priv, power_well); -} -  static void hsw_power_well_sync_hw(struct drm_i915_private *dev_priv,  				   struct i915_power_well *power_well)  { -	/* Take over the request bit if set by BIOS. */ -	if (I915_READ(HSW_PWR_WELL_BIOS) & HSW_PWR_WELL_ENABLE_REQUEST) { -		if (!(I915_READ(HSW_PWR_WELL_DRIVER) & -		      HSW_PWR_WELL_ENABLE_REQUEST)) -			I915_WRITE(HSW_PWR_WELL_DRIVER, -				   HSW_PWR_WELL_ENABLE_REQUEST); -		I915_WRITE(HSW_PWR_WELL_BIOS, 0); -	} -} - -static void hsw_power_well_enable(struct drm_i915_private *dev_priv, -				  struct i915_power_well *power_well) -{ -	hsw_set_power_well(dev_priv, power_well, true); -} - -static void hsw_power_well_disable(struct drm_i915_private *dev_priv, -				   struct i915_power_well *power_well) -{ -	hsw_set_power_well(dev_priv, power_well, false); -} - -static bool skl_power_well_enabled(struct drm_i915_private *dev_priv, -					struct i915_power_well *power_well) -{ -	uint32_t mask = SKL_POWER_WELL_REQ(power_well->id) | -		SKL_POWER_WELL_STATE(power_well->id); - -	return (I915_READ(HSW_PWR_WELL_DRIVER) & mask) == mask; -} - -static void skl_power_well_sync_hw(struct drm_i915_private *dev_priv, -				struct i915_power_well *power_well) -{ -	uint32_t mask = SKL_POWER_WELL_REQ(power_well->id); -	uint32_t bios_req = I915_READ(HSW_PWR_WELL_BIOS); +	enum i915_power_well_id id = power_well->id; +	u32 mask = HSW_PWR_WELL_CTL_REQ(id); +	u32 bios_req = I915_READ(HSW_PWR_WELL_CTL_BIOS(id));  	/* Take over the request bit if set by BIOS. */  	if (bios_req & mask) { -		uint32_t drv_req = I915_READ(HSW_PWR_WELL_DRIVER); +		u32 drv_req = I915_READ(HSW_PWR_WELL_CTL_DRIVER(id));  		if (!(drv_req & mask)) -			I915_WRITE(HSW_PWR_WELL_DRIVER, drv_req | mask); -		I915_WRITE(HSW_PWR_WELL_BIOS, bios_req & ~mask); +			I915_WRITE(HSW_PWR_WELL_CTL_DRIVER(id), drv_req | mask); +		I915_WRITE(HSW_PWR_WELL_CTL_BIOS(id), bios_req & ~mask);  	}  } -static void skl_power_well_enable(struct drm_i915_private *dev_priv, -				struct i915_power_well *power_well) -{ -	skl_set_power_well(dev_priv, power_well, true); -} - -static void skl_power_well_disable(struct drm_i915_private *dev_priv, -				struct i915_power_well *power_well) -{ -	skl_set_power_well(dev_priv, power_well, false); -} -  static void bxt_dpio_cmn_power_well_enable(struct drm_i915_private *dev_priv,  					   struct i915_power_well *power_well)  { -	bxt_ddi_phy_init(dev_priv, power_well->data); +	bxt_ddi_phy_init(dev_priv, power_well->bxt.phy);  }  static void bxt_dpio_cmn_power_well_disable(struct drm_i915_private *dev_priv,  					    struct i915_power_well *power_well)  { -	bxt_ddi_phy_uninit(dev_priv, power_well->data); +	bxt_ddi_phy_uninit(dev_priv, power_well->bxt.phy);  }  static bool bxt_dpio_cmn_power_well_enabled(struct drm_i915_private *dev_priv,  					    struct i915_power_well *power_well)  { -	return bxt_ddi_phy_is_enabled(dev_priv, power_well->data); +	return bxt_ddi_phy_is_enabled(dev_priv, power_well->bxt.phy);  }  static void bxt_verify_ddi_phy_power_wells(struct drm_i915_private *dev_priv) @@ -969,16 +669,16 @@ static void bxt_verify_ddi_phy_power_wells(struct drm_i915_private *dev_priv)  	power_well = lookup_power_well(dev_priv, BXT_DPIO_CMN_A);  	if (power_well->count > 0) -		bxt_ddi_phy_verify_state(dev_priv, power_well->data); +		bxt_ddi_phy_verify_state(dev_priv, power_well->bxt.phy);  	power_well = lookup_power_well(dev_priv, BXT_DPIO_CMN_BC);  	if (power_well->count > 0) -		bxt_ddi_phy_verify_state(dev_priv, power_well->data); +		bxt_ddi_phy_verify_state(dev_priv, power_well->bxt.phy);  	if (IS_GEMINILAKE(dev_priv)) {  		power_well = lookup_power_well(dev_priv, GLK_DPIO_CMN_C);  		if (power_well->count > 0) -			bxt_ddi_phy_verify_state(dev_priv, power_well->data); +			bxt_ddi_phy_verify_state(dev_priv, power_well->bxt.phy);  	}  } @@ -1076,7 +776,7 @@ static void i830_pipes_power_well_sync_hw(struct drm_i915_private *dev_priv,  static void vlv_set_power_well(struct drm_i915_private *dev_priv,  			       struct i915_power_well *power_well, bool enable)  { -	enum punit_power_well power_well_id = power_well->id; +	enum i915_power_well_id power_well_id = power_well->id;  	u32 mask;  	u32 state;  	u32 ctrl; @@ -1124,7 +824,7 @@ static void vlv_power_well_disable(struct drm_i915_private *dev_priv,  static bool vlv_power_well_enabled(struct drm_i915_private *dev_priv,  				   struct i915_power_well *power_well)  { -	int power_well_id = power_well->id; +	enum i915_power_well_id power_well_id = power_well->id;  	bool enabled = false;  	u32 mask;  	u32 state; @@ -1311,8 +1011,9 @@ static void vlv_dpio_cmn_power_well_disable(struct drm_i915_private *dev_priv,  #define POWER_DOMAIN_MASK (GENMASK_ULL(POWER_DOMAIN_NUM - 1, 0)) -static struct i915_power_well *lookup_power_well(struct drm_i915_private *dev_priv, -						 int power_well_id) +static struct i915_power_well * +lookup_power_well(struct drm_i915_private *dev_priv, +		  enum i915_power_well_id power_well_id)  {  	struct i915_power_domains *power_domains = &dev_priv->power_domains;  	int i; @@ -1659,7 +1360,7 @@ void chv_phy_powergate_lanes(struct intel_encoder *encoder,  static bool chv_pipe_power_well_enabled(struct drm_i915_private *dev_priv,  					struct i915_power_well *power_well)  { -	enum pipe pipe = power_well->id; +	enum pipe pipe = PIPE_A;  	bool enabled;  	u32 state, ctrl; @@ -1689,7 +1390,7 @@ static void chv_set_pipe_power_well(struct drm_i915_private *dev_priv,  				    struct i915_power_well *power_well,  				    bool enable)  { -	enum pipe pipe = power_well->id; +	enum pipe pipe = PIPE_A;  	u32 state;  	u32 ctrl; @@ -1722,7 +1423,7 @@ out:  static void chv_pipe_power_well_enable(struct drm_i915_private *dev_priv,  				       struct i915_power_well *power_well)  { -	WARN_ON_ONCE(power_well->id != PIPE_A); +	WARN_ON_ONCE(power_well->id != CHV_DISP_PW_PIPE_A);  	chv_set_pipe_power_well(dev_priv, power_well, true); @@ -1732,7 +1433,7 @@ static void chv_pipe_power_well_enable(struct drm_i915_private *dev_priv,  static void chv_pipe_power_well_disable(struct drm_i915_private *dev_priv,  					struct i915_power_well *power_well)  { -	WARN_ON_ONCE(power_well->id != PIPE_A); +	WARN_ON_ONCE(power_well->id != CHV_DISP_PW_PIPE_A);  	vlv_display_power_well_deinit(dev_priv); @@ -1848,37 +1549,13 @@ void intel_display_power_put(struct drm_i915_private *dev_priv,  	intel_runtime_pm_put(dev_priv);  } -#define HSW_DISPLAY_POWER_DOMAINS (			\ -	BIT_ULL(POWER_DOMAIN_PIPE_B) |			\ -	BIT_ULL(POWER_DOMAIN_PIPE_C) |			\ -	BIT_ULL(POWER_DOMAIN_PIPE_A_PANEL_FITTER) |		\ -	BIT_ULL(POWER_DOMAIN_PIPE_B_PANEL_FITTER) |		\ -	BIT_ULL(POWER_DOMAIN_PIPE_C_PANEL_FITTER) |		\ -	BIT_ULL(POWER_DOMAIN_TRANSCODER_A) |		\ -	BIT_ULL(POWER_DOMAIN_TRANSCODER_B) |		\ -	BIT_ULL(POWER_DOMAIN_TRANSCODER_C) |		\ -	BIT_ULL(POWER_DOMAIN_PORT_DDI_B_LANES) |		\ -	BIT_ULL(POWER_DOMAIN_PORT_DDI_C_LANES) |		\ -	BIT_ULL(POWER_DOMAIN_PORT_DDI_D_LANES) |		\ -	BIT_ULL(POWER_DOMAIN_PORT_CRT) | /* DDI E */	\ -	BIT_ULL(POWER_DOMAIN_VGA) |				\ -	BIT_ULL(POWER_DOMAIN_AUDIO) |			\ -	BIT_ULL(POWER_DOMAIN_INIT)) - -#define BDW_DISPLAY_POWER_DOMAINS (			\ -	BIT_ULL(POWER_DOMAIN_PIPE_B) |			\ -	BIT_ULL(POWER_DOMAIN_PIPE_C) |			\ -	BIT_ULL(POWER_DOMAIN_PIPE_B_PANEL_FITTER) |		\ -	BIT_ULL(POWER_DOMAIN_PIPE_C_PANEL_FITTER) |		\ -	BIT_ULL(POWER_DOMAIN_TRANSCODER_A) |		\ -	BIT_ULL(POWER_DOMAIN_TRANSCODER_B) |		\ -	BIT_ULL(POWER_DOMAIN_TRANSCODER_C) |		\ -	BIT_ULL(POWER_DOMAIN_PORT_DDI_B_LANES) |		\ -	BIT_ULL(POWER_DOMAIN_PORT_DDI_C_LANES) |		\ -	BIT_ULL(POWER_DOMAIN_PORT_DDI_D_LANES) |		\ -	BIT_ULL(POWER_DOMAIN_PORT_CRT) | /* DDI E */	\ -	BIT_ULL(POWER_DOMAIN_VGA) |				\ -	BIT_ULL(POWER_DOMAIN_AUDIO) |			\ +#define I830_PIPES_POWER_DOMAINS (		\ +	BIT_ULL(POWER_DOMAIN_PIPE_A) |		\ +	BIT_ULL(POWER_DOMAIN_PIPE_B) |		\ +	BIT_ULL(POWER_DOMAIN_PIPE_A_PANEL_FITTER) |	\ +	BIT_ULL(POWER_DOMAIN_PIPE_B_PANEL_FITTER) |	\ +	BIT_ULL(POWER_DOMAIN_TRANSCODER_A) |	\ +	BIT_ULL(POWER_DOMAIN_TRANSCODER_B) |	\  	BIT_ULL(POWER_DOMAIN_INIT))  #define VLV_DISPLAY_POWER_DOMAINS (		\ @@ -1961,13 +1638,201 @@ void intel_display_power_put(struct drm_i915_private *dev_priv,  	BIT_ULL(POWER_DOMAIN_AUX_D) |		\  	BIT_ULL(POWER_DOMAIN_INIT)) -#define I830_PIPES_POWER_DOMAINS (		\ -	BIT_ULL(POWER_DOMAIN_PIPE_A) |		\ -	BIT_ULL(POWER_DOMAIN_PIPE_B) |		\ -	BIT_ULL(POWER_DOMAIN_PIPE_A_PANEL_FITTER) |	\ -	BIT_ULL(POWER_DOMAIN_PIPE_B_PANEL_FITTER) |	\ -	BIT_ULL(POWER_DOMAIN_TRANSCODER_A) |	\ -	BIT_ULL(POWER_DOMAIN_TRANSCODER_B) |	\ +#define HSW_DISPLAY_POWER_DOMAINS (			\ +	BIT_ULL(POWER_DOMAIN_PIPE_B) |			\ +	BIT_ULL(POWER_DOMAIN_PIPE_C) |			\ +	BIT_ULL(POWER_DOMAIN_PIPE_A_PANEL_FITTER) |		\ +	BIT_ULL(POWER_DOMAIN_PIPE_B_PANEL_FITTER) |		\ +	BIT_ULL(POWER_DOMAIN_PIPE_C_PANEL_FITTER) |		\ +	BIT_ULL(POWER_DOMAIN_TRANSCODER_A) |		\ +	BIT_ULL(POWER_DOMAIN_TRANSCODER_B) |		\ +	BIT_ULL(POWER_DOMAIN_TRANSCODER_C) |		\ +	BIT_ULL(POWER_DOMAIN_PORT_DDI_B_LANES) |		\ +	BIT_ULL(POWER_DOMAIN_PORT_DDI_C_LANES) |		\ +	BIT_ULL(POWER_DOMAIN_PORT_DDI_D_LANES) |		\ +	BIT_ULL(POWER_DOMAIN_PORT_CRT) | /* DDI E */	\ +	BIT_ULL(POWER_DOMAIN_VGA) |				\ +	BIT_ULL(POWER_DOMAIN_AUDIO) |			\ +	BIT_ULL(POWER_DOMAIN_INIT)) + +#define BDW_DISPLAY_POWER_DOMAINS (			\ +	BIT_ULL(POWER_DOMAIN_PIPE_B) |			\ +	BIT_ULL(POWER_DOMAIN_PIPE_C) |			\ +	BIT_ULL(POWER_DOMAIN_PIPE_B_PANEL_FITTER) |		\ +	BIT_ULL(POWER_DOMAIN_PIPE_C_PANEL_FITTER) |		\ +	BIT_ULL(POWER_DOMAIN_TRANSCODER_A) |		\ +	BIT_ULL(POWER_DOMAIN_TRANSCODER_B) |		\ +	BIT_ULL(POWER_DOMAIN_TRANSCODER_C) |		\ +	BIT_ULL(POWER_DOMAIN_PORT_DDI_B_LANES) |		\ +	BIT_ULL(POWER_DOMAIN_PORT_DDI_C_LANES) |		\ +	BIT_ULL(POWER_DOMAIN_PORT_DDI_D_LANES) |		\ +	BIT_ULL(POWER_DOMAIN_PORT_CRT) | /* DDI E */	\ +	BIT_ULL(POWER_DOMAIN_VGA) |				\ +	BIT_ULL(POWER_DOMAIN_AUDIO) |			\ +	BIT_ULL(POWER_DOMAIN_INIT)) + +#define SKL_DISPLAY_POWERWELL_2_POWER_DOMAINS (		\ +	BIT_ULL(POWER_DOMAIN_TRANSCODER_A) |		\ +	BIT_ULL(POWER_DOMAIN_PIPE_B) |			\ +	BIT_ULL(POWER_DOMAIN_TRANSCODER_B) |		\ +	BIT_ULL(POWER_DOMAIN_PIPE_C) |			\ +	BIT_ULL(POWER_DOMAIN_TRANSCODER_C) |		\ +	BIT_ULL(POWER_DOMAIN_PIPE_B_PANEL_FITTER) |		\ +	BIT_ULL(POWER_DOMAIN_PIPE_C_PANEL_FITTER) |		\ +	BIT_ULL(POWER_DOMAIN_PORT_DDI_B_LANES) |		\ +	BIT_ULL(POWER_DOMAIN_PORT_DDI_C_LANES) |		\ +	BIT_ULL(POWER_DOMAIN_PORT_DDI_D_LANES) |		\ +	BIT_ULL(POWER_DOMAIN_PORT_DDI_E_LANES) |		\ +	BIT_ULL(POWER_DOMAIN_AUX_B) |                       \ +	BIT_ULL(POWER_DOMAIN_AUX_C) |			\ +	BIT_ULL(POWER_DOMAIN_AUX_D) |			\ +	BIT_ULL(POWER_DOMAIN_AUDIO) |			\ +	BIT_ULL(POWER_DOMAIN_VGA) |				\ +	BIT_ULL(POWER_DOMAIN_INIT)) +#define SKL_DISPLAY_DDI_IO_A_E_POWER_DOMAINS (		\ +	BIT_ULL(POWER_DOMAIN_PORT_DDI_A_IO) |		\ +	BIT_ULL(POWER_DOMAIN_PORT_DDI_E_IO) |		\ +	BIT_ULL(POWER_DOMAIN_INIT)) +#define SKL_DISPLAY_DDI_IO_B_POWER_DOMAINS (		\ +	BIT_ULL(POWER_DOMAIN_PORT_DDI_B_IO) |		\ +	BIT_ULL(POWER_DOMAIN_INIT)) +#define SKL_DISPLAY_DDI_IO_C_POWER_DOMAINS (		\ +	BIT_ULL(POWER_DOMAIN_PORT_DDI_C_IO) |		\ +	BIT_ULL(POWER_DOMAIN_INIT)) +#define SKL_DISPLAY_DDI_IO_D_POWER_DOMAINS (		\ +	BIT_ULL(POWER_DOMAIN_PORT_DDI_D_IO) |		\ +	BIT_ULL(POWER_DOMAIN_INIT)) +#define SKL_DISPLAY_DC_OFF_POWER_DOMAINS (		\ +	SKL_DISPLAY_POWERWELL_2_POWER_DOMAINS |		\ +	BIT_ULL(POWER_DOMAIN_MODESET) |			\ +	BIT_ULL(POWER_DOMAIN_AUX_A) |			\ +	BIT_ULL(POWER_DOMAIN_INIT)) + +#define BXT_DISPLAY_POWERWELL_2_POWER_DOMAINS (		\ +	BIT_ULL(POWER_DOMAIN_TRANSCODER_A) |		\ +	BIT_ULL(POWER_DOMAIN_PIPE_B) |			\ +	BIT_ULL(POWER_DOMAIN_TRANSCODER_B) |		\ +	BIT_ULL(POWER_DOMAIN_PIPE_C) |			\ +	BIT_ULL(POWER_DOMAIN_TRANSCODER_C) |		\ +	BIT_ULL(POWER_DOMAIN_PIPE_B_PANEL_FITTER) |		\ +	BIT_ULL(POWER_DOMAIN_PIPE_C_PANEL_FITTER) |		\ +	BIT_ULL(POWER_DOMAIN_PORT_DDI_B_LANES) |		\ +	BIT_ULL(POWER_DOMAIN_PORT_DDI_C_LANES) |		\ +	BIT_ULL(POWER_DOMAIN_AUX_B) |			\ +	BIT_ULL(POWER_DOMAIN_AUX_C) |			\ +	BIT_ULL(POWER_DOMAIN_AUDIO) |			\ +	BIT_ULL(POWER_DOMAIN_VGA) |				\ +	BIT_ULL(POWER_DOMAIN_GMBUS) |			\ +	BIT_ULL(POWER_DOMAIN_INIT)) +#define BXT_DISPLAY_DC_OFF_POWER_DOMAINS (		\ +	BXT_DISPLAY_POWERWELL_2_POWER_DOMAINS |		\ +	BIT_ULL(POWER_DOMAIN_MODESET) |			\ +	BIT_ULL(POWER_DOMAIN_AUX_A) |			\ +	BIT_ULL(POWER_DOMAIN_INIT)) +#define BXT_DPIO_CMN_A_POWER_DOMAINS (			\ +	BIT_ULL(POWER_DOMAIN_PORT_DDI_A_LANES) |		\ +	BIT_ULL(POWER_DOMAIN_AUX_A) |			\ +	BIT_ULL(POWER_DOMAIN_INIT)) +#define BXT_DPIO_CMN_BC_POWER_DOMAINS (			\ +	BIT_ULL(POWER_DOMAIN_PORT_DDI_B_LANES) |		\ +	BIT_ULL(POWER_DOMAIN_PORT_DDI_C_LANES) |		\ +	BIT_ULL(POWER_DOMAIN_AUX_B) |			\ +	BIT_ULL(POWER_DOMAIN_AUX_C) |			\ +	BIT_ULL(POWER_DOMAIN_INIT)) + +#define GLK_DISPLAY_POWERWELL_2_POWER_DOMAINS (		\ +	BIT_ULL(POWER_DOMAIN_TRANSCODER_A) |		\ +	BIT_ULL(POWER_DOMAIN_PIPE_B) |			\ +	BIT_ULL(POWER_DOMAIN_TRANSCODER_B) |		\ +	BIT_ULL(POWER_DOMAIN_PIPE_C) |			\ +	BIT_ULL(POWER_DOMAIN_TRANSCODER_C) |		\ +	BIT_ULL(POWER_DOMAIN_PIPE_B_PANEL_FITTER) |		\ +	BIT_ULL(POWER_DOMAIN_PIPE_C_PANEL_FITTER) |		\ +	BIT_ULL(POWER_DOMAIN_PORT_DDI_B_LANES) |		\ +	BIT_ULL(POWER_DOMAIN_PORT_DDI_C_LANES) |		\ +	BIT_ULL(POWER_DOMAIN_AUX_B) |                       \ +	BIT_ULL(POWER_DOMAIN_AUX_C) |			\ +	BIT_ULL(POWER_DOMAIN_AUDIO) |			\ +	BIT_ULL(POWER_DOMAIN_VGA) |				\ +	BIT_ULL(POWER_DOMAIN_INIT)) +#define GLK_DISPLAY_DDI_IO_A_POWER_DOMAINS (		\ +	BIT_ULL(POWER_DOMAIN_PORT_DDI_A_IO)) +#define GLK_DISPLAY_DDI_IO_B_POWER_DOMAINS (		\ +	BIT_ULL(POWER_DOMAIN_PORT_DDI_B_IO)) +#define GLK_DISPLAY_DDI_IO_C_POWER_DOMAINS (		\ +	BIT_ULL(POWER_DOMAIN_PORT_DDI_C_IO)) +#define GLK_DPIO_CMN_A_POWER_DOMAINS (			\ +	BIT_ULL(POWER_DOMAIN_PORT_DDI_A_LANES) |		\ +	BIT_ULL(POWER_DOMAIN_AUX_A) |			\ +	BIT_ULL(POWER_DOMAIN_INIT)) +#define GLK_DPIO_CMN_B_POWER_DOMAINS (			\ +	BIT_ULL(POWER_DOMAIN_PORT_DDI_B_LANES) |		\ +	BIT_ULL(POWER_DOMAIN_AUX_B) |			\ +	BIT_ULL(POWER_DOMAIN_INIT)) +#define GLK_DPIO_CMN_C_POWER_DOMAINS (			\ +	BIT_ULL(POWER_DOMAIN_PORT_DDI_C_LANES) |		\ +	BIT_ULL(POWER_DOMAIN_AUX_C) |			\ +	BIT_ULL(POWER_DOMAIN_INIT)) +#define GLK_DISPLAY_AUX_A_POWER_DOMAINS (		\ +	BIT_ULL(POWER_DOMAIN_AUX_A) |		\ +	BIT_ULL(POWER_DOMAIN_INIT)) +#define GLK_DISPLAY_AUX_B_POWER_DOMAINS (		\ +	BIT_ULL(POWER_DOMAIN_AUX_B) |		\ +	BIT_ULL(POWER_DOMAIN_INIT)) +#define GLK_DISPLAY_AUX_C_POWER_DOMAINS (		\ +	BIT_ULL(POWER_DOMAIN_AUX_C) |		\ +	BIT_ULL(POWER_DOMAIN_INIT)) +#define GLK_DISPLAY_DC_OFF_POWER_DOMAINS (		\ +	GLK_DISPLAY_POWERWELL_2_POWER_DOMAINS |		\ +	BIT_ULL(POWER_DOMAIN_MODESET) |			\ +	BIT_ULL(POWER_DOMAIN_AUX_A) |			\ +	BIT_ULL(POWER_DOMAIN_INIT)) + +#define CNL_DISPLAY_POWERWELL_2_POWER_DOMAINS (		\ +	BIT_ULL(POWER_DOMAIN_TRANSCODER_A) |		\ +	BIT_ULL(POWER_DOMAIN_PIPE_B) |			\ +	BIT_ULL(POWER_DOMAIN_TRANSCODER_B) |		\ +	BIT_ULL(POWER_DOMAIN_PIPE_C) |			\ +	BIT_ULL(POWER_DOMAIN_TRANSCODER_C) |		\ +	BIT_ULL(POWER_DOMAIN_PIPE_B_PANEL_FITTER) |		\ +	BIT_ULL(POWER_DOMAIN_PIPE_C_PANEL_FITTER) |		\ +	BIT_ULL(POWER_DOMAIN_PORT_DDI_B_LANES) |		\ +	BIT_ULL(POWER_DOMAIN_PORT_DDI_C_LANES) |		\ +	BIT_ULL(POWER_DOMAIN_PORT_DDI_D_LANES) |		\ +	BIT_ULL(POWER_DOMAIN_AUX_B) |                       \ +	BIT_ULL(POWER_DOMAIN_AUX_C) |			\ +	BIT_ULL(POWER_DOMAIN_AUX_D) |			\ +	BIT_ULL(POWER_DOMAIN_AUDIO) |			\ +	BIT_ULL(POWER_DOMAIN_VGA) |				\ +	BIT_ULL(POWER_DOMAIN_INIT)) +#define CNL_DISPLAY_DDI_A_IO_POWER_DOMAINS (		\ +	BIT_ULL(POWER_DOMAIN_PORT_DDI_A_IO) |		\ +	BIT_ULL(POWER_DOMAIN_INIT)) +#define CNL_DISPLAY_DDI_B_IO_POWER_DOMAINS (		\ +	BIT_ULL(POWER_DOMAIN_PORT_DDI_B_IO) |		\ +	BIT_ULL(POWER_DOMAIN_INIT)) +#define CNL_DISPLAY_DDI_C_IO_POWER_DOMAINS (		\ +	BIT_ULL(POWER_DOMAIN_PORT_DDI_C_IO) |		\ +	BIT_ULL(POWER_DOMAIN_INIT)) +#define CNL_DISPLAY_DDI_D_IO_POWER_DOMAINS (		\ +	BIT_ULL(POWER_DOMAIN_PORT_DDI_D_IO) |		\ +	BIT_ULL(POWER_DOMAIN_INIT)) +#define CNL_DISPLAY_AUX_A_POWER_DOMAINS (		\ +	BIT_ULL(POWER_DOMAIN_AUX_A) |			\ +	BIT_ULL(POWER_DOMAIN_INIT)) +#define CNL_DISPLAY_AUX_B_POWER_DOMAINS (		\ +	BIT_ULL(POWER_DOMAIN_AUX_B) |			\ +	BIT_ULL(POWER_DOMAIN_INIT)) +#define CNL_DISPLAY_AUX_C_POWER_DOMAINS (		\ +	BIT_ULL(POWER_DOMAIN_AUX_C) |			\ +	BIT_ULL(POWER_DOMAIN_INIT)) +#define CNL_DISPLAY_AUX_D_POWER_DOMAINS (		\ +	BIT_ULL(POWER_DOMAIN_AUX_D) |			\ +	BIT_ULL(POWER_DOMAIN_INIT)) +#define CNL_DISPLAY_DC_OFF_POWER_DOMAINS (		\ +	CNL_DISPLAY_POWERWELL_2_POWER_DOMAINS |		\ +	BIT_ULL(POWER_DOMAIN_MODESET) |			\ +	BIT_ULL(POWER_DOMAIN_AUX_A) |			\  	BIT_ULL(POWER_DOMAIN_INIT))  static const struct i915_power_well_ops i9xx_always_on_power_well_ops = { @@ -1997,6 +1862,7 @@ static struct i915_power_well i9xx_always_on_power_well[] = {  		.always_on = 1,  		.domains = POWER_DOMAIN_MASK,  		.ops = &i9xx_always_on_power_well_ops, +		.id = I915_DISP_PW_ALWAYS_ON,  	},  }; @@ -2013,11 +1879,13 @@ static struct i915_power_well i830_power_wells[] = {  		.always_on = 1,  		.domains = POWER_DOMAIN_MASK,  		.ops = &i9xx_always_on_power_well_ops, +		.id = I915_DISP_PW_ALWAYS_ON,  	},  	{  		.name = "pipes",  		.domains = I830_PIPES_POWER_DOMAINS,  		.ops = &i830_pipes_power_well_ops, +		.id = I830_DISP_PW_PIPES,  	},  }; @@ -2028,13 +1896,6 @@ static const struct i915_power_well_ops hsw_power_well_ops = {  	.is_enabled = hsw_power_well_enabled,  }; -static const struct i915_power_well_ops skl_power_well_ops = { -	.sync_hw = skl_power_well_sync_hw, -	.enable = skl_power_well_enable, -	.disable = skl_power_well_disable, -	.is_enabled = skl_power_well_enabled, -}; -  static const struct i915_power_well_ops gen9_dc_off_power_well_ops = {  	.sync_hw = i9xx_power_well_sync_hw_noop,  	.enable = gen9_dc_off_power_well_enable, @@ -2055,11 +1916,16 @@ static struct i915_power_well hsw_power_wells[] = {  		.always_on = 1,  		.domains = POWER_DOMAIN_MASK,  		.ops = &i9xx_always_on_power_well_ops, +		.id = I915_DISP_PW_ALWAYS_ON,  	},  	{  		.name = "display",  		.domains = HSW_DISPLAY_POWER_DOMAINS,  		.ops = &hsw_power_well_ops, +		.id = HSW_DISP_PW_GLOBAL, +		{ +			.hsw.has_vga = true, +		},  	},  }; @@ -2069,11 +1935,17 @@ static struct i915_power_well bdw_power_wells[] = {  		.always_on = 1,  		.domains = POWER_DOMAIN_MASK,  		.ops = &i9xx_always_on_power_well_ops, +		.id = I915_DISP_PW_ALWAYS_ON,  	},  	{  		.name = "display",  		.domains = BDW_DISPLAY_POWER_DOMAINS,  		.ops = &hsw_power_well_ops, +		.id = HSW_DISP_PW_GLOBAL, +		{ +			.hsw.irq_pipe_mask = BIT(PIPE_B) | BIT(PIPE_C), +			.hsw.has_vga = true, +		},  	},  }; @@ -2104,7 +1976,7 @@ static struct i915_power_well vlv_power_wells[] = {  		.always_on = 1,  		.domains = POWER_DOMAIN_MASK,  		.ops = &i9xx_always_on_power_well_ops, -		.id = PUNIT_POWER_WELL_ALWAYS_ON, +		.id = I915_DISP_PW_ALWAYS_ON,  	},  	{  		.name = "display", @@ -2162,6 +2034,7 @@ static struct i915_power_well chv_power_wells[] = {  		.always_on = 1,  		.domains = POWER_DOMAIN_MASK,  		.ops = &i9xx_always_on_power_well_ops, +		.id = I915_DISP_PW_ALWAYS_ON,  	},  	{  		.name = "display", @@ -2171,7 +2044,7 @@ static struct i915_power_well chv_power_wells[] = {  		 * required for any pipe to work.  		 */  		.domains = CHV_DISPLAY_POWER_DOMAINS, -		.id = PIPE_A, +		.id = CHV_DISP_PW_PIPE_A,  		.ops = &chv_pipe_power_well_ops,  	},  	{ @@ -2189,7 +2062,7 @@ static struct i915_power_well chv_power_wells[] = {  };  bool intel_display_power_well_is_enabled(struct drm_i915_private *dev_priv, -				    int power_well_id) +					 enum i915_power_well_id power_well_id)  {  	struct i915_power_well *power_well;  	bool ret; @@ -2206,20 +2079,23 @@ static struct i915_power_well skl_power_wells[] = {  		.always_on = 1,  		.domains = POWER_DOMAIN_MASK,  		.ops = &i9xx_always_on_power_well_ops, -		.id = SKL_DISP_PW_ALWAYS_ON, +		.id = I915_DISP_PW_ALWAYS_ON,  	},  	{  		.name = "power well 1",  		/* Handled by the DMC firmware */  		.domains = 0, -		.ops = &skl_power_well_ops, +		.ops = &hsw_power_well_ops,  		.id = SKL_DISP_PW_1, +		{ +			.hsw.has_fuses = true, +		},  	},  	{  		.name = "MISC IO power well",  		/* Handled by the DMC firmware */  		.domains = 0, -		.ops = &skl_power_well_ops, +		.ops = &hsw_power_well_ops,  		.id = SKL_DISP_PW_MISC_IO,  	},  	{ @@ -2231,31 +2107,36 @@ static struct i915_power_well skl_power_wells[] = {  	{  		.name = "power well 2",  		.domains = SKL_DISPLAY_POWERWELL_2_POWER_DOMAINS, -		.ops = &skl_power_well_ops, +		.ops = &hsw_power_well_ops,  		.id = SKL_DISP_PW_2, +		{ +			.hsw.irq_pipe_mask = BIT(PIPE_B) | BIT(PIPE_C), +			.hsw.has_vga = true, +			.hsw.has_fuses = true, +		},  	},  	{  		.name = "DDI A/E IO power well",  		.domains = SKL_DISPLAY_DDI_IO_A_E_POWER_DOMAINS, -		.ops = &skl_power_well_ops, +		.ops = &hsw_power_well_ops,  		.id = SKL_DISP_PW_DDI_A_E,  	},  	{  		.name = "DDI B IO power well",  		.domains = SKL_DISPLAY_DDI_IO_B_POWER_DOMAINS, -		.ops = &skl_power_well_ops, +		.ops = &hsw_power_well_ops,  		.id = SKL_DISP_PW_DDI_B,  	},  	{  		.name = "DDI C IO power well",  		.domains = SKL_DISPLAY_DDI_IO_C_POWER_DOMAINS, -		.ops = &skl_power_well_ops, +		.ops = &hsw_power_well_ops,  		.id = SKL_DISP_PW_DDI_C,  	},  	{  		.name = "DDI D IO power well",  		.domains = SKL_DISPLAY_DDI_IO_D_POWER_DOMAINS, -		.ops = &skl_power_well_ops, +		.ops = &hsw_power_well_ops,  		.id = SKL_DISP_PW_DDI_D,  	},  }; @@ -2266,12 +2147,16 @@ static struct i915_power_well bxt_power_wells[] = {  		.always_on = 1,  		.domains = POWER_DOMAIN_MASK,  		.ops = &i9xx_always_on_power_well_ops, +		.id = I915_DISP_PW_ALWAYS_ON,  	},  	{  		.name = "power well 1",  		.domains = 0, -		.ops = &skl_power_well_ops, +		.ops = &hsw_power_well_ops,  		.id = SKL_DISP_PW_1, +		{ +			.hsw.has_fuses = true, +		},  	},  	{  		.name = "DC off", @@ -2282,22 +2167,31 @@ static struct i915_power_well bxt_power_wells[] = {  	{  		.name = "power well 2",  		.domains = BXT_DISPLAY_POWERWELL_2_POWER_DOMAINS, -		.ops = &skl_power_well_ops, +		.ops = &hsw_power_well_ops,  		.id = SKL_DISP_PW_2, +		{ +			.hsw.irq_pipe_mask = BIT(PIPE_B) | BIT(PIPE_C), +			.hsw.has_vga = true, +			.hsw.has_fuses = true, +		},  	},  	{  		.name = "dpio-common-a",  		.domains = BXT_DPIO_CMN_A_POWER_DOMAINS,  		.ops = &bxt_dpio_cmn_power_well_ops,  		.id = BXT_DPIO_CMN_A, -		.data = DPIO_PHY1, +		{ +			.bxt.phy = DPIO_PHY1, +		},  	},  	{  		.name = "dpio-common-bc",  		.domains = BXT_DPIO_CMN_BC_POWER_DOMAINS,  		.ops = &bxt_dpio_cmn_power_well_ops,  		.id = BXT_DPIO_CMN_BC, -		.data = DPIO_PHY0, +		{ +			.bxt.phy = DPIO_PHY0, +		},  	},  }; @@ -2307,13 +2201,17 @@ static struct i915_power_well glk_power_wells[] = {  		.always_on = 1,  		.domains = POWER_DOMAIN_MASK,  		.ops = &i9xx_always_on_power_well_ops, +		.id = I915_DISP_PW_ALWAYS_ON,  	},  	{  		.name = "power well 1",  		/* Handled by the DMC firmware */  		.domains = 0, -		.ops = &skl_power_well_ops, +		.ops = &hsw_power_well_ops,  		.id = SKL_DISP_PW_1, +		{ +			.hsw.has_fuses = true, +		},  	},  	{  		.name = "DC off", @@ -2324,64 +2222,75 @@ static struct i915_power_well glk_power_wells[] = {  	{  		.name = "power well 2",  		.domains = GLK_DISPLAY_POWERWELL_2_POWER_DOMAINS, -		.ops = &skl_power_well_ops, +		.ops = &hsw_power_well_ops,  		.id = SKL_DISP_PW_2, +		{ +			.hsw.irq_pipe_mask = BIT(PIPE_B) | BIT(PIPE_C), +			.hsw.has_vga = true, +			.hsw.has_fuses = true, +		},  	},  	{  		.name = "dpio-common-a",  		.domains = GLK_DPIO_CMN_A_POWER_DOMAINS,  		.ops = &bxt_dpio_cmn_power_well_ops,  		.id = BXT_DPIO_CMN_A, -		.data = DPIO_PHY1, +		{ +			.bxt.phy = DPIO_PHY1, +		},  	},  	{  		.name = "dpio-common-b",  		.domains = GLK_DPIO_CMN_B_POWER_DOMAINS,  		.ops = &bxt_dpio_cmn_power_well_ops,  		.id = BXT_DPIO_CMN_BC, -		.data = DPIO_PHY0, +		{ +			.bxt.phy = DPIO_PHY0, +		},  	},  	{  		.name = "dpio-common-c",  		.domains = GLK_DPIO_CMN_C_POWER_DOMAINS,  		.ops = &bxt_dpio_cmn_power_well_ops,  		.id = GLK_DPIO_CMN_C, -		.data = DPIO_PHY2, +		{ +			.bxt.phy = DPIO_PHY2, +		},  	},  	{  		.name = "AUX A",  		.domains = GLK_DISPLAY_AUX_A_POWER_DOMAINS, -		.ops = &skl_power_well_ops, +		.ops = &hsw_power_well_ops,  		.id = GLK_DISP_PW_AUX_A,  	},  	{  		.name = "AUX B",  		.domains = GLK_DISPLAY_AUX_B_POWER_DOMAINS, -		.ops = &skl_power_well_ops, +		.ops = &hsw_power_well_ops,  		.id = GLK_DISP_PW_AUX_B,  	},  	{  		.name = "AUX C",  		.domains = GLK_DISPLAY_AUX_C_POWER_DOMAINS, -		.ops = &skl_power_well_ops, +		.ops = &hsw_power_well_ops,  		.id = GLK_DISP_PW_AUX_C,  	},  	{  		.name = "DDI A IO power well",  		.domains = GLK_DISPLAY_DDI_IO_A_POWER_DOMAINS, -		.ops = &skl_power_well_ops, +		.ops = &hsw_power_well_ops,  		.id = GLK_DISP_PW_DDI_A,  	},  	{  		.name = "DDI B IO power well",  		.domains = GLK_DISPLAY_DDI_IO_B_POWER_DOMAINS, -		.ops = &skl_power_well_ops, +		.ops = &hsw_power_well_ops,  		.id = SKL_DISP_PW_DDI_B,  	},  	{  		.name = "DDI C IO power well",  		.domains = GLK_DISPLAY_DDI_IO_C_POWER_DOMAINS, -		.ops = &skl_power_well_ops, +		.ops = &hsw_power_well_ops,  		.id = SKL_DISP_PW_DDI_C,  	},  }; @@ -2392,36 +2301,40 @@ static struct i915_power_well cnl_power_wells[] = {  		.always_on = 1,  		.domains = POWER_DOMAIN_MASK,  		.ops = &i9xx_always_on_power_well_ops, +		.id = I915_DISP_PW_ALWAYS_ON,  	},  	{  		.name = "power well 1",  		/* Handled by the DMC firmware */  		.domains = 0, -		.ops = &skl_power_well_ops, +		.ops = &hsw_power_well_ops,  		.id = SKL_DISP_PW_1, +		{ +			.hsw.has_fuses = true, +		},  	},  	{  		.name = "AUX A",  		.domains = CNL_DISPLAY_AUX_A_POWER_DOMAINS, -		.ops = &skl_power_well_ops, +		.ops = &hsw_power_well_ops,  		.id = CNL_DISP_PW_AUX_A,  	},  	{  		.name = "AUX B",  		.domains = CNL_DISPLAY_AUX_B_POWER_DOMAINS, -		.ops = &skl_power_well_ops, +		.ops = &hsw_power_well_ops,  		.id = CNL_DISP_PW_AUX_B,  	},  	{  		.name = "AUX C",  		.domains = CNL_DISPLAY_AUX_C_POWER_DOMAINS, -		.ops = &skl_power_well_ops, +		.ops = &hsw_power_well_ops,  		.id = CNL_DISP_PW_AUX_C,  	},  	{  		.name = "AUX D",  		.domains = CNL_DISPLAY_AUX_D_POWER_DOMAINS, -		.ops = &skl_power_well_ops, +		.ops = &hsw_power_well_ops,  		.id = CNL_DISP_PW_AUX_D,  	},  	{ @@ -2433,31 +2346,36 @@ static struct i915_power_well cnl_power_wells[] = {  	{  		.name = "power well 2",  		.domains = CNL_DISPLAY_POWERWELL_2_POWER_DOMAINS, -		.ops = &skl_power_well_ops, +		.ops = &hsw_power_well_ops,  		.id = SKL_DISP_PW_2, +		{ +			.hsw.irq_pipe_mask = BIT(PIPE_B) | BIT(PIPE_C), +			.hsw.has_vga = true, +			.hsw.has_fuses = true, +		},  	},  	{  		.name = "DDI A IO power well",  		.domains = CNL_DISPLAY_DDI_A_IO_POWER_DOMAINS, -		.ops = &skl_power_well_ops, +		.ops = &hsw_power_well_ops,  		.id = CNL_DISP_PW_DDI_A,  	},  	{  		.name = "DDI B IO power well",  		.domains = CNL_DISPLAY_DDI_B_IO_POWER_DOMAINS, -		.ops = &skl_power_well_ops, +		.ops = &hsw_power_well_ops,  		.id = SKL_DISP_PW_DDI_B,  	},  	{  		.name = "DDI C IO power well",  		.domains = CNL_DISPLAY_DDI_C_IO_POWER_DOMAINS, -		.ops = &skl_power_well_ops, +		.ops = &hsw_power_well_ops,  		.id = SKL_DISP_PW_DDI_C,  	},  	{  		.name = "DDI D IO power well",  		.domains = CNL_DISPLAY_DDI_D_IO_POWER_DOMAINS, -		.ops = &skl_power_well_ops, +		.ops = &hsw_power_well_ops,  		.id = SKL_DISP_PW_DDI_D,  	},  }; @@ -2479,7 +2397,7 @@ static uint32_t get_allowed_dc_mask(const struct drm_i915_private *dev_priv,  	int requested_dc;  	int max_dc; -	if (IS_GEN9_BC(dev_priv)) { +	if (IS_GEN9_BC(dev_priv) || IS_CANNONLAKE(dev_priv)) {  		max_dc = 2;  		mask = 0;  	} else if (IS_GEN9_LP(dev_priv)) { @@ -2521,6 +2439,22 @@ static uint32_t get_allowed_dc_mask(const struct drm_i915_private *dev_priv,  	return mask;  } +static void assert_power_well_ids_unique(struct drm_i915_private *dev_priv) +{ +	struct i915_power_domains *power_domains = &dev_priv->power_domains; +	u64 power_well_ids; +	int i; + +	power_well_ids = 0; +	for (i = 0; i < power_domains->power_well_count; i++) { +		enum i915_power_well_id id = power_domains->power_wells[i].id; + +		WARN_ON(id >= sizeof(power_well_ids) * 8); +		WARN_ON(power_well_ids & BIT_ULL(id)); +		power_well_ids |= BIT_ULL(id); +	} +} +  #define set_power_wells(power_domains, __power_wells) ({		\  	(power_domains)->power_wells = (__power_wells);			\  	(power_domains)->power_well_count = ARRAY_SIZE(__power_wells);	\ @@ -2572,6 +2506,8 @@ int intel_power_domains_init(struct drm_i915_private *dev_priv)  		set_power_wells(power_domains, i9xx_always_on_power_well);  	} +	assert_power_well_ids_unique(dev_priv); +  	return 0;  } @@ -2694,13 +2630,18 @@ static void skl_display_core_uninit(struct drm_i915_private *dev_priv)  	mutex_lock(&power_domains->lock); -	well = lookup_power_well(dev_priv, SKL_DISP_PW_MISC_IO); -	intel_power_well_disable(dev_priv, well); - +	/* +	 * BSpec says to keep the MISC IO power well enabled here, only +	 * remove our request for power well 1. +	 * Note that even though the driver's request is removed power well 1 +	 * may stay enabled after this due to DMC's own request on it. +	 */  	well = lookup_power_well(dev_priv, SKL_DISP_PW_1);  	intel_power_well_disable(dev_priv, well);  	mutex_unlock(&power_domains->lock); + +	usleep_range(10, 30);		/* 10 us delay per Bspec */  }  void bxt_display_core_init(struct drm_i915_private *dev_priv, @@ -2751,13 +2692,19 @@ void bxt_display_core_uninit(struct drm_i915_private *dev_priv)  	/* The spec doesn't call for removing the reset handshake flag */ -	/* Disable PG1 */ +	/* +	 * Disable PW1 (PG1). +	 * Note that even though the driver's request is removed power well 1 +	 * may stay enabled after this due to DMC's own request on it. +	 */  	mutex_lock(&power_domains->lock);  	well = lookup_power_well(dev_priv, SKL_DISP_PW_1);  	intel_power_well_disable(dev_priv, well);  	mutex_unlock(&power_domains->lock); + +	usleep_range(10, 30);		/* 10 us delay per Bspec */  }  #define CNL_PROCMON_IDX(val) \ @@ -2796,7 +2743,7 @@ static void cnl_display_core_init(struct drm_i915_private *dev_priv, bool resume  	/* 2. Enable Comp */  	val = I915_READ(CHICKEN_MISC_2); -	val &= ~COMP_PWR_DOWN; +	val &= ~CNL_COMP_PWR_DOWN;  	I915_WRITE(CHICKEN_MISC_2, val);  	val = I915_READ(CNL_PORT_COMP_DW3); @@ -2821,7 +2768,10 @@ static void cnl_display_core_init(struct drm_i915_private *dev_priv, bool resume  	val |= CL_POWER_DOWN_ENABLE;  	I915_WRITE(CNL_PORT_CL1CM_DW5, val); -	/* 4. Enable Power Well 1 (PG1) and Aux IO Power */ +	/* +	 * 4. Enable Power Well 1 (PG1). +	 *    The AUX IO power wells will be enabled on demand. +	 */  	mutex_lock(&power_domains->lock);  	well = lookup_power_well(dev_priv, SKL_DISP_PW_1);  	intel_power_well_enable(dev_priv, well); @@ -2853,15 +2803,21 @@ static void cnl_display_core_uninit(struct drm_i915_private *dev_priv)  	/* 3. Disable CD clock */  	cnl_uninit_cdclk(dev_priv); -	/* 4. Disable Power Well 1 (PG1) and Aux IO Power */ +	/* +	 * 4. Disable Power Well 1 (PG1). +	 *    The AUX IO power wells are toggled on demand, so they are already +	 *    disabled at this point. +	 */  	mutex_lock(&power_domains->lock);  	well = lookup_power_well(dev_priv, SKL_DISP_PW_1);  	intel_power_well_disable(dev_priv, well);  	mutex_unlock(&power_domains->lock); +	usleep_range(10, 30);		/* 10 us delay per Bspec */ +  	/* 5. Disable Comp */  	val = I915_READ(CHICKEN_MISC_2); -	val |= COMP_PWR_DOWN; +	val |= CNL_COMP_PWR_DOWN;  	I915_WRITE(CHICKEN_MISC_2, val);  } | 
