xref: /dflybsd-src/sys/dev/drm/i915/intel_runtime_pm.c (revision 3f2dd94a569761201b5b0a18b2f697f97fe1b9dc)
12c9916cdSFrançois Tigeot /*
22c9916cdSFrançois Tigeot  * Copyright © 2012-2014 Intel Corporation
32c9916cdSFrançois Tigeot  *
42c9916cdSFrançois Tigeot  * Permission is hereby granted, free of charge, to any person obtaining a
52c9916cdSFrançois Tigeot  * copy of this software and associated documentation files (the "Software"),
62c9916cdSFrançois Tigeot  * to deal in the Software without restriction, including without limitation
72c9916cdSFrançois Tigeot  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
82c9916cdSFrançois Tigeot  * and/or sell copies of the Software, and to permit persons to whom the
92c9916cdSFrançois Tigeot  * Software is furnished to do so, subject to the following conditions:
102c9916cdSFrançois Tigeot  *
112c9916cdSFrançois Tigeot  * The above copyright notice and this permission notice (including the next
122c9916cdSFrançois Tigeot  * paragraph) shall be included in all copies or substantial portions of the
132c9916cdSFrançois Tigeot  * Software.
142c9916cdSFrançois Tigeot  *
152c9916cdSFrançois Tigeot  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
162c9916cdSFrançois Tigeot  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
172c9916cdSFrançois Tigeot  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
182c9916cdSFrançois Tigeot  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
192c9916cdSFrançois Tigeot  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
202c9916cdSFrançois Tigeot  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
212c9916cdSFrançois Tigeot  * IN THE SOFTWARE.
222c9916cdSFrançois Tigeot  *
232c9916cdSFrançois Tigeot  * Authors:
242c9916cdSFrançois Tigeot  *    Eugeni Dodonov <eugeni.dodonov@intel.com>
252c9916cdSFrançois Tigeot  *    Daniel Vetter <daniel.vetter@ffwll.ch>
262c9916cdSFrançois Tigeot  *
272c9916cdSFrançois Tigeot  */
282c9916cdSFrançois Tigeot 
291487f786SFrançois Tigeot #include <linux/pm_runtime.h>
301487f786SFrançois Tigeot #include <linux/vgaarb.h>
311487f786SFrançois Tigeot 
322c9916cdSFrançois Tigeot #include "i915_drv.h"
332c9916cdSFrançois Tigeot #include "intel_drv.h"
342c9916cdSFrançois Tigeot 
352c9916cdSFrançois Tigeot /**
362c9916cdSFrançois Tigeot  * DOC: runtime pm
372c9916cdSFrançois Tigeot  *
382c9916cdSFrançois Tigeot  * The i915 driver supports dynamic enabling and disabling of entire hardware
392c9916cdSFrançois Tigeot  * blocks at runtime. This is especially important on the display side where
402c9916cdSFrançois Tigeot  * software is supposed to control many power gates manually on recent hardware,
412c9916cdSFrançois Tigeot  * since on the GT side a lot of the power management is done by the hardware.
422c9916cdSFrançois Tigeot  * But even there some manual control at the device level is required.
432c9916cdSFrançois Tigeot  *
442c9916cdSFrançois Tigeot  * Since i915 supports a diverse set of platforms with a unified codebase and
452c9916cdSFrançois Tigeot  * hardware engineers just love to shuffle functionality around between power
462c9916cdSFrançois Tigeot  * domains there's a sizeable amount of indirection required. This file provides
472c9916cdSFrançois Tigeot  * generic functions to the driver for grabbing and releasing references for
482c9916cdSFrançois Tigeot  * abstract power domains. It then maps those to the actual power wells
492c9916cdSFrançois Tigeot  * present for a given platform.
502c9916cdSFrançois Tigeot  */
512c9916cdSFrançois Tigeot 
5219c468b4SFrançois Tigeot bool intel_display_power_well_is_enabled(struct drm_i915_private *dev_priv,
53*3f2dd94aSFrançois Tigeot 					 enum i915_power_well_id power_well_id);
5419c468b4SFrançois Tigeot 
551487f786SFrançois Tigeot static struct i915_power_well *
56*3f2dd94aSFrançois Tigeot lookup_power_well(struct drm_i915_private *dev_priv,
57*3f2dd94aSFrançois Tigeot 		  enum i915_power_well_id power_well_id);
581487f786SFrançois Tigeot 
59aee94f86SFrançois Tigeot const char *
intel_display_power_domain_str(enum intel_display_power_domain domain)60aee94f86SFrançois Tigeot intel_display_power_domain_str(enum intel_display_power_domain domain)
61aee94f86SFrançois Tigeot {
62aee94f86SFrançois Tigeot 	switch (domain) {
63aee94f86SFrançois Tigeot 	case POWER_DOMAIN_PIPE_A:
64aee94f86SFrançois Tigeot 		return "PIPE_A";
65aee94f86SFrançois Tigeot 	case POWER_DOMAIN_PIPE_B:
66aee94f86SFrançois Tigeot 		return "PIPE_B";
67aee94f86SFrançois Tigeot 	case POWER_DOMAIN_PIPE_C:
68aee94f86SFrançois Tigeot 		return "PIPE_C";
69aee94f86SFrançois Tigeot 	case POWER_DOMAIN_PIPE_A_PANEL_FITTER:
70aee94f86SFrançois Tigeot 		return "PIPE_A_PANEL_FITTER";
71aee94f86SFrançois Tigeot 	case POWER_DOMAIN_PIPE_B_PANEL_FITTER:
72aee94f86SFrançois Tigeot 		return "PIPE_B_PANEL_FITTER";
73aee94f86SFrançois Tigeot 	case POWER_DOMAIN_PIPE_C_PANEL_FITTER:
74aee94f86SFrançois Tigeot 		return "PIPE_C_PANEL_FITTER";
75aee94f86SFrançois Tigeot 	case POWER_DOMAIN_TRANSCODER_A:
76aee94f86SFrançois Tigeot 		return "TRANSCODER_A";
77aee94f86SFrançois Tigeot 	case POWER_DOMAIN_TRANSCODER_B:
78aee94f86SFrançois Tigeot 		return "TRANSCODER_B";
79aee94f86SFrançois Tigeot 	case POWER_DOMAIN_TRANSCODER_C:
80aee94f86SFrançois Tigeot 		return "TRANSCODER_C";
81aee94f86SFrançois Tigeot 	case POWER_DOMAIN_TRANSCODER_EDP:
82aee94f86SFrançois Tigeot 		return "TRANSCODER_EDP";
838621f407SFrançois Tigeot 	case POWER_DOMAIN_TRANSCODER_DSI_A:
848621f407SFrançois Tigeot 		return "TRANSCODER_DSI_A";
858621f407SFrançois Tigeot 	case POWER_DOMAIN_TRANSCODER_DSI_C:
868621f407SFrançois Tigeot 		return "TRANSCODER_DSI_C";
87aee94f86SFrançois Tigeot 	case POWER_DOMAIN_PORT_DDI_A_LANES:
88aee94f86SFrançois Tigeot 		return "PORT_DDI_A_LANES";
89aee94f86SFrançois Tigeot 	case POWER_DOMAIN_PORT_DDI_B_LANES:
90aee94f86SFrançois Tigeot 		return "PORT_DDI_B_LANES";
91aee94f86SFrançois Tigeot 	case POWER_DOMAIN_PORT_DDI_C_LANES:
92aee94f86SFrançois Tigeot 		return "PORT_DDI_C_LANES";
93aee94f86SFrançois Tigeot 	case POWER_DOMAIN_PORT_DDI_D_LANES:
94aee94f86SFrançois Tigeot 		return "PORT_DDI_D_LANES";
95aee94f86SFrançois Tigeot 	case POWER_DOMAIN_PORT_DDI_E_LANES:
96aee94f86SFrançois Tigeot 		return "PORT_DDI_E_LANES";
97a85cb24fSFrançois Tigeot 	case POWER_DOMAIN_PORT_DDI_A_IO:
98a85cb24fSFrançois Tigeot 		return "PORT_DDI_A_IO";
99a85cb24fSFrançois Tigeot 	case POWER_DOMAIN_PORT_DDI_B_IO:
100a85cb24fSFrançois Tigeot 		return "PORT_DDI_B_IO";
101a85cb24fSFrançois Tigeot 	case POWER_DOMAIN_PORT_DDI_C_IO:
102a85cb24fSFrançois Tigeot 		return "PORT_DDI_C_IO";
103a85cb24fSFrançois Tigeot 	case POWER_DOMAIN_PORT_DDI_D_IO:
104a85cb24fSFrançois Tigeot 		return "PORT_DDI_D_IO";
105a85cb24fSFrançois Tigeot 	case POWER_DOMAIN_PORT_DDI_E_IO:
106a85cb24fSFrançois Tigeot 		return "PORT_DDI_E_IO";
107aee94f86SFrançois Tigeot 	case POWER_DOMAIN_PORT_DSI:
108aee94f86SFrançois Tigeot 		return "PORT_DSI";
109aee94f86SFrançois Tigeot 	case POWER_DOMAIN_PORT_CRT:
110aee94f86SFrançois Tigeot 		return "PORT_CRT";
111aee94f86SFrançois Tigeot 	case POWER_DOMAIN_PORT_OTHER:
112aee94f86SFrançois Tigeot 		return "PORT_OTHER";
113aee94f86SFrançois Tigeot 	case POWER_DOMAIN_VGA:
114aee94f86SFrançois Tigeot 		return "VGA";
115aee94f86SFrançois Tigeot 	case POWER_DOMAIN_AUDIO:
116aee94f86SFrançois Tigeot 		return "AUDIO";
117aee94f86SFrançois Tigeot 	case POWER_DOMAIN_PLLS:
118aee94f86SFrançois Tigeot 		return "PLLS";
119aee94f86SFrançois Tigeot 	case POWER_DOMAIN_AUX_A:
120aee94f86SFrançois Tigeot 		return "AUX_A";
121aee94f86SFrançois Tigeot 	case POWER_DOMAIN_AUX_B:
122aee94f86SFrançois Tigeot 		return "AUX_B";
123aee94f86SFrançois Tigeot 	case POWER_DOMAIN_AUX_C:
124aee94f86SFrançois Tigeot 		return "AUX_C";
125aee94f86SFrançois Tigeot 	case POWER_DOMAIN_AUX_D:
126aee94f86SFrançois Tigeot 		return "AUX_D";
127aee94f86SFrançois Tigeot 	case POWER_DOMAIN_GMBUS:
128aee94f86SFrançois Tigeot 		return "GMBUS";
129aee94f86SFrançois Tigeot 	case POWER_DOMAIN_INIT:
130aee94f86SFrançois Tigeot 		return "INIT";
131aee94f86SFrançois Tigeot 	case POWER_DOMAIN_MODESET:
132aee94f86SFrançois Tigeot 		return "MODESET";
133aee94f86SFrançois Tigeot 	default:
134aee94f86SFrançois Tigeot 		MISSING_CASE(domain);
135aee94f86SFrançois Tigeot 		return "?";
136aee94f86SFrançois Tigeot 	}
137aee94f86SFrançois Tigeot }
138aee94f86SFrançois Tigeot 
intel_power_well_enable(struct drm_i915_private * dev_priv,struct i915_power_well * power_well)139a05eeebfSFrançois Tigeot static void intel_power_well_enable(struct drm_i915_private *dev_priv,
140a05eeebfSFrançois Tigeot 				    struct i915_power_well *power_well)
141a05eeebfSFrançois Tigeot {
142a05eeebfSFrançois Tigeot 	DRM_DEBUG_KMS("enabling %s\n", power_well->name);
143a05eeebfSFrançois Tigeot 	power_well->ops->enable(dev_priv, power_well);
144a05eeebfSFrançois Tigeot 	power_well->hw_enabled = true;
145a05eeebfSFrançois Tigeot }
146a05eeebfSFrançois Tigeot 
intel_power_well_disable(struct drm_i915_private * dev_priv,struct i915_power_well * power_well)147a05eeebfSFrançois Tigeot static void intel_power_well_disable(struct drm_i915_private *dev_priv,
148a05eeebfSFrançois Tigeot 				     struct i915_power_well *power_well)
149a05eeebfSFrançois Tigeot {
150a05eeebfSFrançois Tigeot 	DRM_DEBUG_KMS("disabling %s\n", power_well->name);
151a05eeebfSFrançois Tigeot 	power_well->hw_enabled = false;
152a05eeebfSFrançois Tigeot 	power_well->ops->disable(dev_priv, power_well);
153a05eeebfSFrançois Tigeot }
154a05eeebfSFrançois Tigeot 
intel_power_well_get(struct drm_i915_private * dev_priv,struct i915_power_well * power_well)1551487f786SFrançois Tigeot static void intel_power_well_get(struct drm_i915_private *dev_priv,
1561487f786SFrançois Tigeot 				 struct i915_power_well *power_well)
1571487f786SFrançois Tigeot {
1581487f786SFrançois Tigeot 	if (!power_well->count++)
1591487f786SFrançois Tigeot 		intel_power_well_enable(dev_priv, power_well);
1601487f786SFrançois Tigeot }
1611487f786SFrançois Tigeot 
intel_power_well_put(struct drm_i915_private * dev_priv,struct i915_power_well * power_well)1621487f786SFrançois Tigeot static void intel_power_well_put(struct drm_i915_private *dev_priv,
1631487f786SFrançois Tigeot 				 struct i915_power_well *power_well)
1641487f786SFrançois Tigeot {
1651487f786SFrançois Tigeot 	WARN(!power_well->count, "Use count on power well %s is already zero",
1661487f786SFrançois Tigeot 	     power_well->name);
1671487f786SFrançois Tigeot 
1681487f786SFrançois Tigeot 	if (!--power_well->count)
1691487f786SFrançois Tigeot 		intel_power_well_disable(dev_priv, power_well);
1701487f786SFrançois Tigeot }
1711487f786SFrançois Tigeot 
1722c9916cdSFrançois Tigeot /**
1732c9916cdSFrançois Tigeot  * __intel_display_power_is_enabled - unlocked check for a power domain
1742c9916cdSFrançois Tigeot  * @dev_priv: i915 device instance
1752c9916cdSFrançois Tigeot  * @domain: power domain to check
1762c9916cdSFrançois Tigeot  *
1772c9916cdSFrançois Tigeot  * This is the unlocked version of intel_display_power_is_enabled() and should
1782c9916cdSFrançois Tigeot  * only be used from error capture and recovery code where deadlocks are
1792c9916cdSFrançois Tigeot  * possible.
1802c9916cdSFrançois Tigeot  *
1812c9916cdSFrançois Tigeot  * Returns:
1822c9916cdSFrançois Tigeot  * True when the power domain is enabled, false otherwise.
1832c9916cdSFrançois Tigeot  */
__intel_display_power_is_enabled(struct drm_i915_private * dev_priv,enum intel_display_power_domain domain)1842c9916cdSFrançois Tigeot bool __intel_display_power_is_enabled(struct drm_i915_private *dev_priv,
1852c9916cdSFrançois Tigeot 				      enum intel_display_power_domain domain)
1862c9916cdSFrançois Tigeot {
1872c9916cdSFrançois Tigeot 	struct i915_power_well *power_well;
1882c9916cdSFrançois Tigeot 	bool is_enabled;
1892c9916cdSFrançois Tigeot 
190*3f2dd94aSFrançois Tigeot 	if (dev_priv->runtime_pm.suspended)
1912c9916cdSFrançois Tigeot 		return false;
1922c9916cdSFrançois Tigeot 
1932c9916cdSFrançois Tigeot 	is_enabled = true;
1942c9916cdSFrançois Tigeot 
195a85cb24fSFrançois Tigeot 	for_each_power_domain_well_rev(dev_priv, power_well, BIT_ULL(domain)) {
1962c9916cdSFrançois Tigeot 		if (power_well->always_on)
1972c9916cdSFrançois Tigeot 			continue;
1982c9916cdSFrançois Tigeot 
1992c9916cdSFrançois Tigeot 		if (!power_well->hw_enabled) {
2002c9916cdSFrançois Tigeot 			is_enabled = false;
2012c9916cdSFrançois Tigeot 			break;
2022c9916cdSFrançois Tigeot 		}
2032c9916cdSFrançois Tigeot 	}
2042c9916cdSFrançois Tigeot 
2052c9916cdSFrançois Tigeot 	return is_enabled;
2062c9916cdSFrançois Tigeot }
2072c9916cdSFrançois Tigeot 
2082c9916cdSFrançois Tigeot /**
2092c9916cdSFrançois Tigeot  * intel_display_power_is_enabled - check for a power domain
2102c9916cdSFrançois Tigeot  * @dev_priv: i915 device instance
2112c9916cdSFrançois Tigeot  * @domain: power domain to check
2122c9916cdSFrançois Tigeot  *
2132c9916cdSFrançois Tigeot  * This function can be used to check the hw power domain state. It is mostly
2142c9916cdSFrançois Tigeot  * used in hardware state readout functions. Everywhere else code should rely
2152c9916cdSFrançois Tigeot  * upon explicit power domain reference counting to ensure that the hardware
2162c9916cdSFrançois Tigeot  * block is powered up before accessing it.
2172c9916cdSFrançois Tigeot  *
2182c9916cdSFrançois Tigeot  * Callers must hold the relevant modesetting locks to ensure that concurrent
2192c9916cdSFrançois Tigeot  * threads can't disable the power well while the caller tries to read a few
2202c9916cdSFrançois Tigeot  * registers.
2212c9916cdSFrançois Tigeot  *
2222c9916cdSFrançois Tigeot  * Returns:
2232c9916cdSFrançois Tigeot  * True when the power domain is enabled, false otherwise.
2242c9916cdSFrançois Tigeot  */
intel_display_power_is_enabled(struct drm_i915_private * dev_priv,enum intel_display_power_domain domain)2252c9916cdSFrançois Tigeot bool intel_display_power_is_enabled(struct drm_i915_private *dev_priv,
2262c9916cdSFrançois Tigeot 				    enum intel_display_power_domain domain)
2272c9916cdSFrançois Tigeot {
2282c9916cdSFrançois Tigeot 	struct i915_power_domains *power_domains;
2292c9916cdSFrançois Tigeot 	bool ret;
2302c9916cdSFrançois Tigeot 
2312c9916cdSFrançois Tigeot 	power_domains = &dev_priv->power_domains;
2322c9916cdSFrançois Tigeot 
2332c9916cdSFrançois Tigeot 	mutex_lock(&power_domains->lock);
2342c9916cdSFrançois Tigeot 	ret = __intel_display_power_is_enabled(dev_priv, domain);
2352c9916cdSFrançois Tigeot 	mutex_unlock(&power_domains->lock);
2362c9916cdSFrançois Tigeot 
2372c9916cdSFrançois Tigeot 	return ret;
2382c9916cdSFrançois Tigeot }
2392c9916cdSFrançois Tigeot 
2402c9916cdSFrançois Tigeot /**
2412c9916cdSFrançois Tigeot  * intel_display_set_init_power - set the initial power domain state
2422c9916cdSFrançois Tigeot  * @dev_priv: i915 device instance
2432c9916cdSFrançois Tigeot  * @enable: whether to enable or disable the initial power domain state
2442c9916cdSFrançois Tigeot  *
2452c9916cdSFrançois Tigeot  * For simplicity our driver load/unload and system suspend/resume code assumes
2462c9916cdSFrançois Tigeot  * that all power domains are always enabled. This functions controls the state
2472c9916cdSFrançois Tigeot  * of this little hack. While the initial power domain state is enabled runtime
2482c9916cdSFrançois Tigeot  * pm is effectively disabled.
2492c9916cdSFrançois Tigeot  */
intel_display_set_init_power(struct drm_i915_private * dev_priv,bool enable)2502c9916cdSFrançois Tigeot void intel_display_set_init_power(struct drm_i915_private *dev_priv,
2512c9916cdSFrançois Tigeot 				  bool enable)
2522c9916cdSFrançois Tigeot {
2532c9916cdSFrançois Tigeot 	if (dev_priv->power_domains.init_power_on == enable)
2542c9916cdSFrançois Tigeot 		return;
2552c9916cdSFrançois Tigeot 
2562c9916cdSFrançois Tigeot 	if (enable)
2572c9916cdSFrançois Tigeot 		intel_display_power_get(dev_priv, POWER_DOMAIN_INIT);
2582c9916cdSFrançois Tigeot 	else
2592c9916cdSFrançois Tigeot 		intel_display_power_put(dev_priv, POWER_DOMAIN_INIT);
2602c9916cdSFrançois Tigeot 
2612c9916cdSFrançois Tigeot 	dev_priv->power_domains.init_power_on = enable;
2622c9916cdSFrançois Tigeot }
2632c9916cdSFrançois Tigeot 
2642c9916cdSFrançois Tigeot /*
2652c9916cdSFrançois Tigeot  * Starting with Haswell, we have a "Power Down Well" that can be turned off
2662c9916cdSFrançois Tigeot  * when not needed anymore. We have 4 registers that can request the power well
2672c9916cdSFrançois Tigeot  * to be enabled, and it will only be disabled if none of the registers is
2682c9916cdSFrançois Tigeot  * requesting it to be enabled.
2692c9916cdSFrançois Tigeot  */
hsw_power_well_post_enable(struct drm_i915_private * dev_priv,u8 irq_pipe_mask,bool has_vga)270*3f2dd94aSFrançois Tigeot static void hsw_power_well_post_enable(struct drm_i915_private *dev_priv,
271*3f2dd94aSFrançois Tigeot 				       u8 irq_pipe_mask, bool has_vga)
2722c9916cdSFrançois Tigeot {
2731e12ee3bSFrançois Tigeot 	struct pci_dev *pdev = dev_priv->drm.pdev;
2742c9916cdSFrançois Tigeot 
2752c9916cdSFrançois Tigeot 	/*
2762c9916cdSFrançois Tigeot 	 * After we re-enable the power well, if we touch VGA register 0x3d5
2772c9916cdSFrançois Tigeot 	 * we'll get unclaimed register interrupts. This stops after we write
2782c9916cdSFrançois Tigeot 	 * anything to the VGA MSR register. The vgacon module uses this
2792c9916cdSFrançois Tigeot 	 * register all the time, so if we unbind our driver and, as a
2802c9916cdSFrançois Tigeot 	 * consequence, bind vgacon, we'll get stuck in an infinite loop at
2812c9916cdSFrançois Tigeot 	 * console_unlock(). So make here we touch the VGA MSR register, making
2822c9916cdSFrançois Tigeot 	 * sure vgacon can keep working normally without triggering interrupts
2832c9916cdSFrançois Tigeot 	 * and error messages.
2842c9916cdSFrançois Tigeot 	 */
285*3f2dd94aSFrançois Tigeot 	if (has_vga) {
2861e12ee3bSFrançois Tigeot 		vga_get_uninterruptible(pdev, VGA_RSRC_LEGACY_IO);
2872c9916cdSFrançois Tigeot 		outb(inb(VGA_MSR_READ), VGA_MSR_WRITE);
2881e12ee3bSFrançois Tigeot 		vga_put(pdev, VGA_RSRC_LEGACY_IO);
289477eb7f9SFrançois Tigeot 	}
290477eb7f9SFrançois Tigeot 
291*3f2dd94aSFrançois Tigeot 	if (irq_pipe_mask)
292*3f2dd94aSFrançois Tigeot 		gen8_irq_power_well_post_enable(dev_priv, irq_pipe_mask);
293*3f2dd94aSFrançois Tigeot }
294*3f2dd94aSFrançois Tigeot 
hsw_power_well_pre_disable(struct drm_i915_private * dev_priv,u8 irq_pipe_mask)295*3f2dd94aSFrançois Tigeot static void hsw_power_well_pre_disable(struct drm_i915_private *dev_priv,
296*3f2dd94aSFrançois Tigeot 				       u8 irq_pipe_mask)
297c0e85e96SFrançois Tigeot {
298*3f2dd94aSFrançois Tigeot 	if (irq_pipe_mask)
299*3f2dd94aSFrançois Tigeot 		gen8_irq_power_well_pre_disable(dev_priv, irq_pipe_mask);
300c0e85e96SFrançois Tigeot }
301c0e85e96SFrançois Tigeot 
302*3f2dd94aSFrançois Tigeot 
hsw_wait_for_power_well_enable(struct drm_i915_private * dev_priv,struct i915_power_well * power_well)303*3f2dd94aSFrançois Tigeot static void hsw_wait_for_power_well_enable(struct drm_i915_private *dev_priv,
304477eb7f9SFrançois Tigeot 					   struct i915_power_well *power_well)
305477eb7f9SFrançois Tigeot {
306*3f2dd94aSFrançois Tigeot 	enum i915_power_well_id id = power_well->id;
307*3f2dd94aSFrançois Tigeot 
308*3f2dd94aSFrançois Tigeot 	/* Timeout for PW1:10 us, AUX:not specified, other PWs:20 us. */
309*3f2dd94aSFrançois Tigeot 	WARN_ON(intel_wait_for_register(dev_priv,
310*3f2dd94aSFrançois Tigeot 					HSW_PWR_WELL_CTL_DRIVER(id),
311*3f2dd94aSFrançois Tigeot 					HSW_PWR_WELL_CTL_STATE(id),
312*3f2dd94aSFrançois Tigeot 					HSW_PWR_WELL_CTL_STATE(id),
313*3f2dd94aSFrançois Tigeot 					1));
314*3f2dd94aSFrançois Tigeot }
315*3f2dd94aSFrançois Tigeot 
hsw_power_well_requesters(struct drm_i915_private * dev_priv,enum i915_power_well_id id)316*3f2dd94aSFrançois Tigeot static u32 hsw_power_well_requesters(struct drm_i915_private *dev_priv,
317*3f2dd94aSFrançois Tigeot 				     enum i915_power_well_id id)
318*3f2dd94aSFrançois Tigeot {
319*3f2dd94aSFrançois Tigeot 	u32 req_mask = HSW_PWR_WELL_CTL_REQ(id);
320*3f2dd94aSFrançois Tigeot 	u32 ret;
321*3f2dd94aSFrançois Tigeot 
322*3f2dd94aSFrançois Tigeot 	ret = I915_READ(HSW_PWR_WELL_CTL_BIOS(id)) & req_mask ? 1 : 0;
323*3f2dd94aSFrançois Tigeot 	ret |= I915_READ(HSW_PWR_WELL_CTL_DRIVER(id)) & req_mask ? 2 : 0;
324*3f2dd94aSFrançois Tigeot 	ret |= I915_READ(HSW_PWR_WELL_CTL_KVMR) & req_mask ? 4 : 0;
325*3f2dd94aSFrançois Tigeot 	ret |= I915_READ(HSW_PWR_WELL_CTL_DEBUG(id)) & req_mask ? 8 : 0;
326*3f2dd94aSFrançois Tigeot 
327*3f2dd94aSFrançois Tigeot 	return ret;
328*3f2dd94aSFrançois Tigeot }
329*3f2dd94aSFrançois Tigeot 
hsw_wait_for_power_well_disable(struct drm_i915_private * dev_priv,struct i915_power_well * power_well)330*3f2dd94aSFrançois Tigeot static void hsw_wait_for_power_well_disable(struct drm_i915_private *dev_priv,
331*3f2dd94aSFrançois Tigeot 					    struct i915_power_well *power_well)
332*3f2dd94aSFrançois Tigeot {
333*3f2dd94aSFrançois Tigeot 	enum i915_power_well_id id = power_well->id;
334*3f2dd94aSFrançois Tigeot 	bool disabled;
335*3f2dd94aSFrançois Tigeot 	u32 reqs;
336477eb7f9SFrançois Tigeot 
337477eb7f9SFrançois Tigeot 	/*
338*3f2dd94aSFrançois Tigeot 	 * Bspec doesn't require waiting for PWs to get disabled, but still do
339*3f2dd94aSFrançois Tigeot 	 * this for paranoia. The known cases where a PW will be forced on:
340*3f2dd94aSFrançois Tigeot 	 * - a KVMR request on any power well via the KVMR request register
341*3f2dd94aSFrançois Tigeot 	 * - a DMC request on PW1 and MISC_IO power wells via the BIOS and
342*3f2dd94aSFrançois Tigeot 	 *   DEBUG request registers
343*3f2dd94aSFrançois Tigeot 	 * Skip the wait in case any of the request bits are set and print a
344*3f2dd94aSFrançois Tigeot 	 * diagnostic message.
345477eb7f9SFrançois Tigeot 	 */
346*3f2dd94aSFrançois Tigeot 	wait_for((disabled = !(I915_READ(HSW_PWR_WELL_CTL_DRIVER(id)) &
347*3f2dd94aSFrançois Tigeot 			       HSW_PWR_WELL_CTL_STATE(id))) ||
348*3f2dd94aSFrançois Tigeot 		 (reqs = hsw_power_well_requesters(dev_priv, id)), 1);
349*3f2dd94aSFrançois Tigeot 	if (disabled)
350*3f2dd94aSFrançois Tigeot 		return;
351477eb7f9SFrançois Tigeot 
352*3f2dd94aSFrançois Tigeot 	DRM_DEBUG_KMS("%s forced on (bios:%d driver:%d kvmr:%d debug:%d)\n",
353*3f2dd94aSFrançois Tigeot 		      power_well->name,
354*3f2dd94aSFrançois Tigeot 		      !!(reqs & 1), !!(reqs & 2), !!(reqs & 4), !!(reqs & 8));
3552c9916cdSFrançois Tigeot }
3562c9916cdSFrançois Tigeot 
gen9_wait_for_power_well_fuses(struct drm_i915_private * dev_priv,enum skl_power_gate pg)357*3f2dd94aSFrançois Tigeot static void gen9_wait_for_power_well_fuses(struct drm_i915_private *dev_priv,
358*3f2dd94aSFrançois Tigeot 					   enum skl_power_gate pg)
359*3f2dd94aSFrançois Tigeot {
360*3f2dd94aSFrançois Tigeot 	/* Timeout 5us for PG#0, for other PGs 1us */
361*3f2dd94aSFrançois Tigeot 	WARN_ON(intel_wait_for_register(dev_priv, SKL_FUSE_STATUS,
362*3f2dd94aSFrançois Tigeot 					SKL_FUSE_PG_DIST_STATUS(pg),
363*3f2dd94aSFrançois Tigeot 					SKL_FUSE_PG_DIST_STATUS(pg), 1));
364*3f2dd94aSFrançois Tigeot }
365*3f2dd94aSFrançois Tigeot 
hsw_power_well_enable(struct drm_i915_private * dev_priv,struct i915_power_well * power_well)366*3f2dd94aSFrançois Tigeot static void hsw_power_well_enable(struct drm_i915_private *dev_priv,
367c0e85e96SFrançois Tigeot 				  struct i915_power_well *power_well)
368c0e85e96SFrançois Tigeot {
369*3f2dd94aSFrançois Tigeot 	enum i915_power_well_id id = power_well->id;
370*3f2dd94aSFrançois Tigeot 	bool wait_fuses = power_well->hsw.has_fuses;
371*3f2dd94aSFrançois Tigeot 	enum skl_power_gate pg;
372*3f2dd94aSFrançois Tigeot 	u32 val;
373*3f2dd94aSFrançois Tigeot 
374*3f2dd94aSFrançois Tigeot 	if (wait_fuses) {
375*3f2dd94aSFrançois Tigeot 		pg = SKL_PW_TO_PG(id);
376*3f2dd94aSFrançois Tigeot 		/*
377*3f2dd94aSFrançois Tigeot 		 * For PW1 we have to wait both for the PW0/PG0 fuse state
378*3f2dd94aSFrançois Tigeot 		 * before enabling the power well and PW1/PG1's own fuse
379*3f2dd94aSFrançois Tigeot 		 * state after the enabling. For all other power wells with
380*3f2dd94aSFrançois Tigeot 		 * fuses we only have to wait for that PW/PG's fuse state
381*3f2dd94aSFrançois Tigeot 		 * after the enabling.
382*3f2dd94aSFrançois Tigeot 		 */
383*3f2dd94aSFrançois Tigeot 		if (pg == SKL_PG1)
384*3f2dd94aSFrançois Tigeot 			gen9_wait_for_power_well_fuses(dev_priv, SKL_PG0);
385c0e85e96SFrançois Tigeot 	}
386c0e85e96SFrançois Tigeot 
387*3f2dd94aSFrançois Tigeot 	val = I915_READ(HSW_PWR_WELL_CTL_DRIVER(id));
388*3f2dd94aSFrançois Tigeot 	I915_WRITE(HSW_PWR_WELL_CTL_DRIVER(id), val | HSW_PWR_WELL_CTL_REQ(id));
389*3f2dd94aSFrançois Tigeot 	hsw_wait_for_power_well_enable(dev_priv, power_well);
390*3f2dd94aSFrançois Tigeot 
391*3f2dd94aSFrançois Tigeot 	if (wait_fuses)
392*3f2dd94aSFrançois Tigeot 		gen9_wait_for_power_well_fuses(dev_priv, pg);
393*3f2dd94aSFrançois Tigeot 
394*3f2dd94aSFrançois Tigeot 	hsw_power_well_post_enable(dev_priv, power_well->hsw.irq_pipe_mask,
395*3f2dd94aSFrançois Tigeot 				   power_well->hsw.has_vga);
396*3f2dd94aSFrançois Tigeot }
397*3f2dd94aSFrançois Tigeot 
hsw_power_well_disable(struct drm_i915_private * dev_priv,struct i915_power_well * power_well)398*3f2dd94aSFrançois Tigeot static void hsw_power_well_disable(struct drm_i915_private *dev_priv,
399*3f2dd94aSFrançois Tigeot 				   struct i915_power_well *power_well)
4002c9916cdSFrançois Tigeot {
401*3f2dd94aSFrançois Tigeot 	enum i915_power_well_id id = power_well->id;
402*3f2dd94aSFrançois Tigeot 	u32 val;
4032c9916cdSFrançois Tigeot 
404*3f2dd94aSFrançois Tigeot 	hsw_power_well_pre_disable(dev_priv, power_well->hsw.irq_pipe_mask);
4052c9916cdSFrançois Tigeot 
406*3f2dd94aSFrançois Tigeot 	val = I915_READ(HSW_PWR_WELL_CTL_DRIVER(id));
407*3f2dd94aSFrançois Tigeot 	I915_WRITE(HSW_PWR_WELL_CTL_DRIVER(id),
408*3f2dd94aSFrançois Tigeot 		   val & ~HSW_PWR_WELL_CTL_REQ(id));
409*3f2dd94aSFrançois Tigeot 	hsw_wait_for_power_well_disable(dev_priv, power_well);
4102c9916cdSFrançois Tigeot }
4112c9916cdSFrançois Tigeot 
412*3f2dd94aSFrançois Tigeot /*
413*3f2dd94aSFrançois Tigeot  * We should only use the power well if we explicitly asked the hardware to
414*3f2dd94aSFrançois Tigeot  * enable it, so check if it's enabled and also check if we've requested it to
415*3f2dd94aSFrançois Tigeot  * be enabled.
416*3f2dd94aSFrançois Tigeot  */
hsw_power_well_enabled(struct drm_i915_private * dev_priv,struct i915_power_well * power_well)417*3f2dd94aSFrançois Tigeot static bool hsw_power_well_enabled(struct drm_i915_private *dev_priv,
418*3f2dd94aSFrançois Tigeot 				   struct i915_power_well *power_well)
419*3f2dd94aSFrançois Tigeot {
420*3f2dd94aSFrançois Tigeot 	enum i915_power_well_id id = power_well->id;
421*3f2dd94aSFrançois Tigeot 	u32 mask = HSW_PWR_WELL_CTL_REQ(id) | HSW_PWR_WELL_CTL_STATE(id);
4222c9916cdSFrançois Tigeot 
423*3f2dd94aSFrançois Tigeot 	return (I915_READ(HSW_PWR_WELL_CTL_DRIVER(id)) & mask) == mask;
424*3f2dd94aSFrançois Tigeot }
42519c468b4SFrançois Tigeot 
assert_can_enable_dc9(struct drm_i915_private * dev_priv)42619c468b4SFrançois Tigeot static void assert_can_enable_dc9(struct drm_i915_private *dev_priv)
42719c468b4SFrançois Tigeot {
428*3f2dd94aSFrançois Tigeot 	enum i915_power_well_id id = SKL_DISP_PW_2;
429*3f2dd94aSFrançois Tigeot 
4308621f407SFrançois Tigeot 	WARN_ONCE((I915_READ(DC_STATE_EN) & DC_STATE_EN_DC9),
43119c468b4SFrançois Tigeot 		  "DC9 already programmed to be enabled.\n");
4328621f407SFrançois Tigeot 	WARN_ONCE(I915_READ(DC_STATE_EN) & DC_STATE_EN_UPTO_DC5,
43319c468b4SFrançois Tigeot 		  "DC5 still not disabled to enable DC9.\n");
434*3f2dd94aSFrançois Tigeot 	WARN_ONCE(I915_READ(HSW_PWR_WELL_CTL_DRIVER(id)) &
435*3f2dd94aSFrançois Tigeot 		  HSW_PWR_WELL_CTL_REQ(id),
436*3f2dd94aSFrançois Tigeot 		  "Power well 2 on.\n");
4378621f407SFrançois Tigeot 	WARN_ONCE(intel_irqs_enabled(dev_priv),
4388621f407SFrançois Tigeot 		  "Interrupts not disabled yet.\n");
43919c468b4SFrançois Tigeot 
44019c468b4SFrançois Tigeot 	 /*
44119c468b4SFrançois Tigeot 	  * TODO: check for the following to verify the conditions to enter DC9
44219c468b4SFrançois Tigeot 	  * state are satisfied:
44319c468b4SFrançois Tigeot 	  * 1] Check relevant display engine registers to verify if mode set
44419c468b4SFrançois Tigeot 	  * disable sequence was followed.
44519c468b4SFrançois Tigeot 	  * 2] Check if display uninitialize sequence is initialized.
44619c468b4SFrançois Tigeot 	  */
44719c468b4SFrançois Tigeot }
44819c468b4SFrançois Tigeot 
assert_can_disable_dc9(struct drm_i915_private * dev_priv)44919c468b4SFrançois Tigeot static void assert_can_disable_dc9(struct drm_i915_private *dev_priv)
45019c468b4SFrançois Tigeot {
4518621f407SFrançois Tigeot 	WARN_ONCE(intel_irqs_enabled(dev_priv),
4528621f407SFrançois Tigeot 		  "Interrupts not disabled yet.\n");
4538621f407SFrançois Tigeot 	WARN_ONCE(I915_READ(DC_STATE_EN) & DC_STATE_EN_UPTO_DC5,
45419c468b4SFrançois Tigeot 		  "DC5 still not disabled.\n");
45519c468b4SFrançois Tigeot 
45619c468b4SFrançois Tigeot 	 /*
45719c468b4SFrançois Tigeot 	  * TODO: check for the following to verify DC9 state was indeed
45819c468b4SFrançois Tigeot 	  * entered before programming to disable it:
45919c468b4SFrançois Tigeot 	  * 1] Check relevant display engine registers to verify if mode
46019c468b4SFrançois Tigeot 	  *  set disable sequence was followed.
46119c468b4SFrançois Tigeot 	  * 2] Check if display uninitialize sequence is initialized.
46219c468b4SFrançois Tigeot 	  */
46319c468b4SFrançois Tigeot }
46419c468b4SFrançois Tigeot 
gen9_write_dc_state(struct drm_i915_private * dev_priv,u32 state)465aee94f86SFrançois Tigeot static void gen9_write_dc_state(struct drm_i915_private *dev_priv,
466aee94f86SFrançois Tigeot 				u32 state)
467aee94f86SFrançois Tigeot {
468aee94f86SFrançois Tigeot 	int rewrites = 0;
469aee94f86SFrançois Tigeot 	int rereads = 0;
470aee94f86SFrançois Tigeot 	u32 v;
471aee94f86SFrançois Tigeot 
472aee94f86SFrançois Tigeot 	I915_WRITE(DC_STATE_EN, state);
473aee94f86SFrançois Tigeot 
474aee94f86SFrançois Tigeot 	/* It has been observed that disabling the dc6 state sometimes
475aee94f86SFrançois Tigeot 	 * doesn't stick and dmc keeps returning old value. Make sure
476aee94f86SFrançois Tigeot 	 * the write really sticks enough times and also force rewrite until
477aee94f86SFrançois Tigeot 	 * we are confident that state is exactly what we want.
478aee94f86SFrançois Tigeot 	 */
479aee94f86SFrançois Tigeot 	do  {
480aee94f86SFrançois Tigeot 		v = I915_READ(DC_STATE_EN);
481aee94f86SFrançois Tigeot 
482aee94f86SFrançois Tigeot 		if (v != state) {
483aee94f86SFrançois Tigeot 			I915_WRITE(DC_STATE_EN, state);
484aee94f86SFrançois Tigeot 			rewrites++;
485aee94f86SFrançois Tigeot 			rereads = 0;
486aee94f86SFrançois Tigeot 		} else if (rereads++ > 5) {
487aee94f86SFrançois Tigeot 			break;
488aee94f86SFrançois Tigeot 		}
489aee94f86SFrançois Tigeot 
490aee94f86SFrançois Tigeot 	} while (rewrites < 100);
491aee94f86SFrançois Tigeot 
492aee94f86SFrançois Tigeot 	if (v != state)
493aee94f86SFrançois Tigeot 		DRM_ERROR("Writing dc state to 0x%x failed, now 0x%x\n",
494aee94f86SFrançois Tigeot 			  state, v);
495aee94f86SFrançois Tigeot 
496aee94f86SFrançois Tigeot 	/* Most of the times we need one retry, avoid spam */
497aee94f86SFrançois Tigeot 	if (rewrites > 1)
498aee94f86SFrançois Tigeot 		DRM_DEBUG_KMS("Rewrote dc state to 0x%x %d times\n",
499aee94f86SFrançois Tigeot 			      state, rewrites);
500aee94f86SFrançois Tigeot }
501aee94f86SFrançois Tigeot 
gen9_dc_mask(struct drm_i915_private * dev_priv)5028621f407SFrançois Tigeot static u32 gen9_dc_mask(struct drm_i915_private *dev_priv)
503aee94f86SFrançois Tigeot {
5048621f407SFrançois Tigeot 	u32 mask;
505aee94f86SFrançois Tigeot 
506aee94f86SFrançois Tigeot 	mask = DC_STATE_EN_UPTO_DC5;
507a85cb24fSFrançois Tigeot 	if (IS_GEN9_LP(dev_priv))
508aee94f86SFrançois Tigeot 		mask |= DC_STATE_EN_DC9;
509aee94f86SFrançois Tigeot 	else
510aee94f86SFrançois Tigeot 		mask |= DC_STATE_EN_UPTO_DC6;
511aee94f86SFrançois Tigeot 
5128621f407SFrançois Tigeot 	return mask;
5138621f407SFrançois Tigeot }
514aee94f86SFrançois Tigeot 
gen9_sanitize_dc_state(struct drm_i915_private * dev_priv)5158621f407SFrançois Tigeot void gen9_sanitize_dc_state(struct drm_i915_private *dev_priv)
5168621f407SFrançois Tigeot {
5178621f407SFrançois Tigeot 	u32 val;
5188621f407SFrançois Tigeot 
5198621f407SFrançois Tigeot 	val = I915_READ(DC_STATE_EN) & gen9_dc_mask(dev_priv);
5208621f407SFrançois Tigeot 
5218621f407SFrançois Tigeot 	DRM_DEBUG_KMS("Resetting DC state tracking from %02x to %02x\n",
5228621f407SFrançois Tigeot 		      dev_priv->csr.dc_state, val);
5238621f407SFrançois Tigeot 	dev_priv->csr.dc_state = val;
5248621f407SFrançois Tigeot }
5258621f407SFrançois Tigeot 
gen9_set_dc_state(struct drm_i915_private * dev_priv,uint32_t state)5268621f407SFrançois Tigeot static void gen9_set_dc_state(struct drm_i915_private *dev_priv, uint32_t state)
5278621f407SFrançois Tigeot {
5288621f407SFrançois Tigeot 	uint32_t val;
5298621f407SFrançois Tigeot 	uint32_t mask;
5308621f407SFrançois Tigeot 
5318621f407SFrançois Tigeot 	if (WARN_ON_ONCE(state & ~dev_priv->csr.allowed_dc_mask))
5328621f407SFrançois Tigeot 		state &= dev_priv->csr.allowed_dc_mask;
533aee94f86SFrançois Tigeot 
534aee94f86SFrançois Tigeot 	val = I915_READ(DC_STATE_EN);
5358621f407SFrançois Tigeot 	mask = gen9_dc_mask(dev_priv);
536aee94f86SFrançois Tigeot 	DRM_DEBUG_KMS("Setting DC state from %02x to %02x\n",
537aee94f86SFrançois Tigeot 		      val & mask, state);
538aee94f86SFrançois Tigeot 
539aee94f86SFrançois Tigeot 	/* Check if DMC is ignoring our DC state requests */
540aee94f86SFrançois Tigeot 	if ((val & mask) != dev_priv->csr.dc_state)
541aee94f86SFrançois Tigeot 		DRM_ERROR("DC state mismatch (0x%x -> 0x%x)\n",
542aee94f86SFrançois Tigeot 			  dev_priv->csr.dc_state, val & mask);
543aee94f86SFrançois Tigeot 
544aee94f86SFrançois Tigeot 	val &= ~mask;
545aee94f86SFrançois Tigeot 	val |= state;
546aee94f86SFrançois Tigeot 
547aee94f86SFrançois Tigeot 	gen9_write_dc_state(dev_priv, val);
548aee94f86SFrançois Tigeot 
549aee94f86SFrançois Tigeot 	dev_priv->csr.dc_state = val & mask;
550aee94f86SFrançois Tigeot }
551aee94f86SFrançois Tigeot 
bxt_enable_dc9(struct drm_i915_private * dev_priv)552aee94f86SFrançois Tigeot void bxt_enable_dc9(struct drm_i915_private *dev_priv)
553aee94f86SFrançois Tigeot {
554aee94f86SFrançois Tigeot 	assert_can_enable_dc9(dev_priv);
555aee94f86SFrançois Tigeot 
556aee94f86SFrançois Tigeot 	DRM_DEBUG_KMS("Enabling DC9\n");
557aee94f86SFrançois Tigeot 
5581487f786SFrançois Tigeot 	intel_power_sequencer_reset(dev_priv);
559aee94f86SFrançois Tigeot 	gen9_set_dc_state(dev_priv, DC_STATE_EN_DC9);
560aee94f86SFrançois Tigeot }
561aee94f86SFrançois Tigeot 
bxt_disable_dc9(struct drm_i915_private * dev_priv)562aee94f86SFrançois Tigeot void bxt_disable_dc9(struct drm_i915_private *dev_priv)
563aee94f86SFrançois Tigeot {
564aee94f86SFrançois Tigeot 	assert_can_disable_dc9(dev_priv);
565aee94f86SFrançois Tigeot 
566aee94f86SFrançois Tigeot 	DRM_DEBUG_KMS("Disabling DC9\n");
567aee94f86SFrançois Tigeot 
568aee94f86SFrançois Tigeot 	gen9_set_dc_state(dev_priv, DC_STATE_DISABLE);
5691e12ee3bSFrançois Tigeot 
5701e12ee3bSFrançois Tigeot 	intel_pps_unlock_regs_wa(dev_priv);
571aee94f86SFrançois Tigeot }
572aee94f86SFrançois Tigeot 
assert_csr_loaded(struct drm_i915_private * dev_priv)573aee94f86SFrançois Tigeot static void assert_csr_loaded(struct drm_i915_private *dev_priv)
574aee94f86SFrançois Tigeot {
575aee94f86SFrançois Tigeot 	WARN_ONCE(!I915_READ(CSR_PROGRAM(0)),
576aee94f86SFrançois Tigeot 		  "CSR program storage start is NULL\n");
577aee94f86SFrançois Tigeot 	WARN_ONCE(!I915_READ(CSR_SSP_BASE), "CSR SSP Base Not fine\n");
578aee94f86SFrançois Tigeot 	WARN_ONCE(!I915_READ(CSR_HTP_SKL), "CSR HTP Not fine\n");
579aee94f86SFrançois Tigeot }
580aee94f86SFrançois Tigeot 
assert_can_enable_dc5(struct drm_i915_private * dev_priv)58119c468b4SFrançois Tigeot static void assert_can_enable_dc5(struct drm_i915_private *dev_priv)
58219c468b4SFrançois Tigeot {
58319c468b4SFrançois Tigeot 	bool pg2_enabled = intel_display_power_well_is_enabled(dev_priv,
58419c468b4SFrançois Tigeot 					SKL_DISP_PW_2);
58519c468b4SFrançois Tigeot 
586352ff8bdSFrançois Tigeot 	WARN_ONCE(pg2_enabled, "PG2 not disabled to enable DC5.\n");
58719c468b4SFrançois Tigeot 
588352ff8bdSFrançois Tigeot 	WARN_ONCE((I915_READ(DC_STATE_EN) & DC_STATE_EN_UPTO_DC5),
58919c468b4SFrançois Tigeot 		  "DC5 already programmed to be enabled.\n");
590aee94f86SFrançois Tigeot 	assert_rpm_wakelock_held(dev_priv);
59119c468b4SFrançois Tigeot 
59219c468b4SFrançois Tigeot 	assert_csr_loaded(dev_priv);
59319c468b4SFrançois Tigeot }
59419c468b4SFrançois Tigeot 
gen9_enable_dc5(struct drm_i915_private * dev_priv)5958621f407SFrançois Tigeot void gen9_enable_dc5(struct drm_i915_private *dev_priv)
59619c468b4SFrançois Tigeot {
59719c468b4SFrançois Tigeot 	assert_can_enable_dc5(dev_priv);
59819c468b4SFrançois Tigeot 
59919c468b4SFrançois Tigeot 	DRM_DEBUG_KMS("Enabling DC5\n");
60019c468b4SFrançois Tigeot 
601*3f2dd94aSFrançois Tigeot 	/* Wa Display #1183: skl,kbl,cfl */
602*3f2dd94aSFrançois Tigeot 	if (IS_GEN9_BC(dev_priv))
603*3f2dd94aSFrançois Tigeot 		I915_WRITE(GEN8_CHICKEN_DCPR_1, I915_READ(GEN8_CHICKEN_DCPR_1) |
604*3f2dd94aSFrançois Tigeot 			   SKL_SELECT_ALTERNATE_DC_EXIT);
605*3f2dd94aSFrançois Tigeot 
606aee94f86SFrançois Tigeot 	gen9_set_dc_state(dev_priv, DC_STATE_EN_UPTO_DC5);
60719c468b4SFrançois Tigeot }
60819c468b4SFrançois Tigeot 
assert_can_enable_dc6(struct drm_i915_private * dev_priv)60919c468b4SFrançois Tigeot static void assert_can_enable_dc6(struct drm_i915_private *dev_priv)
61019c468b4SFrançois Tigeot {
611352ff8bdSFrançois Tigeot 	WARN_ONCE(I915_READ(UTIL_PIN_CTL) & UTIL_PIN_ENABLE,
61219c468b4SFrançois Tigeot 		  "Backlight is not disabled.\n");
613352ff8bdSFrançois Tigeot 	WARN_ONCE((I915_READ(DC_STATE_EN) & DC_STATE_EN_UPTO_DC6),
61419c468b4SFrançois Tigeot 		  "DC6 already programmed to be enabled.\n");
61519c468b4SFrançois Tigeot 
61619c468b4SFrançois Tigeot 	assert_csr_loaded(dev_priv);
61719c468b4SFrançois Tigeot }
61819c468b4SFrançois Tigeot 
skl_enable_dc6(struct drm_i915_private * dev_priv)619aee94f86SFrançois Tigeot void skl_enable_dc6(struct drm_i915_private *dev_priv)
620aee94f86SFrançois Tigeot {
62119c468b4SFrançois Tigeot 	assert_can_enable_dc6(dev_priv);
62219c468b4SFrançois Tigeot 
62319c468b4SFrançois Tigeot 	DRM_DEBUG_KMS("Enabling DC6\n");
62419c468b4SFrançois Tigeot 
625aee94f86SFrançois Tigeot 	gen9_set_dc_state(dev_priv, DC_STATE_EN_UPTO_DC6);
62619c468b4SFrançois Tigeot 
62719c468b4SFrançois Tigeot }
62819c468b4SFrançois Tigeot 
skl_disable_dc6(struct drm_i915_private * dev_priv)629aee94f86SFrançois Tigeot void skl_disable_dc6(struct drm_i915_private *dev_priv)
63019c468b4SFrançois Tigeot {
63119c468b4SFrançois Tigeot 	DRM_DEBUG_KMS("Disabling DC6\n");
63219c468b4SFrançois Tigeot 
633*3f2dd94aSFrançois Tigeot 	/* Wa Display #1183: skl,kbl,cfl */
634*3f2dd94aSFrançois Tigeot 	if (IS_GEN9_BC(dev_priv))
635*3f2dd94aSFrançois Tigeot 		I915_WRITE(GEN8_CHICKEN_DCPR_1, I915_READ(GEN8_CHICKEN_DCPR_1) |
636*3f2dd94aSFrançois Tigeot 			   SKL_SELECT_ALTERNATE_DC_EXIT);
637*3f2dd94aSFrançois Tigeot 
638aee94f86SFrançois Tigeot 	gen9_set_dc_state(dev_priv, DC_STATE_DISABLE);
63919c468b4SFrançois Tigeot }
64019c468b4SFrançois Tigeot 
hsw_power_well_sync_hw(struct drm_i915_private * dev_priv,struct i915_power_well * power_well)6412c9916cdSFrançois Tigeot static void hsw_power_well_sync_hw(struct drm_i915_private *dev_priv,
6422c9916cdSFrançois Tigeot 				   struct i915_power_well *power_well)
6432c9916cdSFrançois Tigeot {
644*3f2dd94aSFrançois Tigeot 	enum i915_power_well_id id = power_well->id;
645*3f2dd94aSFrançois Tigeot 	u32 mask = HSW_PWR_WELL_CTL_REQ(id);
646*3f2dd94aSFrançois Tigeot 	u32 bios_req = I915_READ(HSW_PWR_WELL_CTL_BIOS(id));
647477eb7f9SFrançois Tigeot 
648a85cb24fSFrançois Tigeot 	/* Take over the request bit if set by BIOS. */
649a85cb24fSFrançois Tigeot 	if (bios_req & mask) {
650*3f2dd94aSFrançois Tigeot 		u32 drv_req = I915_READ(HSW_PWR_WELL_CTL_DRIVER(id));
651a85cb24fSFrançois Tigeot 
652a85cb24fSFrançois Tigeot 		if (!(drv_req & mask))
653*3f2dd94aSFrançois Tigeot 			I915_WRITE(HSW_PWR_WELL_CTL_DRIVER(id), drv_req | mask);
654*3f2dd94aSFrançois Tigeot 		I915_WRITE(HSW_PWR_WELL_CTL_BIOS(id), bios_req & ~mask);
655a85cb24fSFrançois Tigeot 	}
656477eb7f9SFrançois Tigeot }
657477eb7f9SFrançois Tigeot 
bxt_dpio_cmn_power_well_enable(struct drm_i915_private * dev_priv,struct i915_power_well * power_well)6581487f786SFrançois Tigeot static void bxt_dpio_cmn_power_well_enable(struct drm_i915_private *dev_priv,
6591487f786SFrançois Tigeot 					   struct i915_power_well *power_well)
6601487f786SFrançois Tigeot {
661*3f2dd94aSFrançois Tigeot 	bxt_ddi_phy_init(dev_priv, power_well->bxt.phy);
6621487f786SFrançois Tigeot }
6631487f786SFrançois Tigeot 
bxt_dpio_cmn_power_well_disable(struct drm_i915_private * dev_priv,struct i915_power_well * power_well)6641487f786SFrançois Tigeot static void bxt_dpio_cmn_power_well_disable(struct drm_i915_private *dev_priv,
6651487f786SFrançois Tigeot 					    struct i915_power_well *power_well)
6661487f786SFrançois Tigeot {
667*3f2dd94aSFrançois Tigeot 	bxt_ddi_phy_uninit(dev_priv, power_well->bxt.phy);
6681487f786SFrançois Tigeot }
6691487f786SFrançois Tigeot 
bxt_dpio_cmn_power_well_enabled(struct drm_i915_private * dev_priv,struct i915_power_well * power_well)6701487f786SFrançois Tigeot static bool bxt_dpio_cmn_power_well_enabled(struct drm_i915_private *dev_priv,
6711487f786SFrançois Tigeot 					    struct i915_power_well *power_well)
6721487f786SFrançois Tigeot {
673*3f2dd94aSFrançois Tigeot 	return bxt_ddi_phy_is_enabled(dev_priv, power_well->bxt.phy);
6741487f786SFrançois Tigeot }
6751487f786SFrançois Tigeot 
bxt_verify_ddi_phy_power_wells(struct drm_i915_private * dev_priv)6761487f786SFrançois Tigeot static void bxt_verify_ddi_phy_power_wells(struct drm_i915_private *dev_priv)
6771487f786SFrançois Tigeot {
6781487f786SFrançois Tigeot 	struct i915_power_well *power_well;
6791487f786SFrançois Tigeot 
6801487f786SFrançois Tigeot 	power_well = lookup_power_well(dev_priv, BXT_DPIO_CMN_A);
6811487f786SFrançois Tigeot 	if (power_well->count > 0)
682*3f2dd94aSFrançois Tigeot 		bxt_ddi_phy_verify_state(dev_priv, power_well->bxt.phy);
6831487f786SFrançois Tigeot 
6841487f786SFrançois Tigeot 	power_well = lookup_power_well(dev_priv, BXT_DPIO_CMN_BC);
6851487f786SFrançois Tigeot 	if (power_well->count > 0)
686*3f2dd94aSFrançois Tigeot 		bxt_ddi_phy_verify_state(dev_priv, power_well->bxt.phy);
687a85cb24fSFrançois Tigeot 
688a85cb24fSFrançois Tigeot 	if (IS_GEMINILAKE(dev_priv)) {
689a85cb24fSFrançois Tigeot 		power_well = lookup_power_well(dev_priv, GLK_DPIO_CMN_C);
690a85cb24fSFrançois Tigeot 		if (power_well->count > 0)
691*3f2dd94aSFrançois Tigeot 			bxt_ddi_phy_verify_state(dev_priv, power_well->bxt.phy);
692a85cb24fSFrançois Tigeot 	}
6931487f786SFrançois Tigeot }
6941487f786SFrançois Tigeot 
gen9_dc_off_power_well_enabled(struct drm_i915_private * dev_priv,struct i915_power_well * power_well)695aee94f86SFrançois Tigeot static bool gen9_dc_off_power_well_enabled(struct drm_i915_private *dev_priv,
696aee94f86SFrançois Tigeot 					   struct i915_power_well *power_well)
697aee94f86SFrançois Tigeot {
698aee94f86SFrançois Tigeot 	return (I915_READ(DC_STATE_EN) & DC_STATE_EN_UPTO_DC5_DC6_MASK) == 0;
699aee94f86SFrançois Tigeot }
700aee94f86SFrançois Tigeot 
gen9_assert_dbuf_enabled(struct drm_i915_private * dev_priv)7011487f786SFrançois Tigeot static void gen9_assert_dbuf_enabled(struct drm_i915_private *dev_priv)
7021487f786SFrançois Tigeot {
7031487f786SFrançois Tigeot 	u32 tmp = I915_READ(DBUF_CTL);
7041487f786SFrançois Tigeot 
7051487f786SFrançois Tigeot 	WARN((tmp & (DBUF_POWER_STATE | DBUF_POWER_REQUEST)) !=
7061487f786SFrançois Tigeot 	     (DBUF_POWER_STATE | DBUF_POWER_REQUEST),
7071487f786SFrançois Tigeot 	     "Unexpected DBuf power power state (0x%08x)\n", tmp);
7081487f786SFrançois Tigeot }
7091487f786SFrançois Tigeot 
gen9_dc_off_power_well_enable(struct drm_i915_private * dev_priv,struct i915_power_well * power_well)710aee94f86SFrançois Tigeot static void gen9_dc_off_power_well_enable(struct drm_i915_private *dev_priv,
711aee94f86SFrançois Tigeot 					  struct i915_power_well *power_well)
712aee94f86SFrançois Tigeot {
713a85cb24fSFrançois Tigeot 	struct intel_cdclk_state cdclk_state = {};
714a85cb24fSFrançois Tigeot 
7158621f407SFrançois Tigeot 	gen9_set_dc_state(dev_priv, DC_STATE_DISABLE);
7168621f407SFrançois Tigeot 
717a85cb24fSFrançois Tigeot 	dev_priv->display.get_cdclk(dev_priv, &cdclk_state);
718a85cb24fSFrançois Tigeot 	WARN_ON(!intel_cdclk_state_compare(&dev_priv->cdclk.hw, &cdclk_state));
7191487f786SFrançois Tigeot 
7201487f786SFrançois Tigeot 	gen9_assert_dbuf_enabled(dev_priv);
7211487f786SFrançois Tigeot 
722a85cb24fSFrançois Tigeot 	if (IS_GEN9_LP(dev_priv))
7231487f786SFrançois Tigeot 		bxt_verify_ddi_phy_power_wells(dev_priv);
724aee94f86SFrançois Tigeot }
725aee94f86SFrançois Tigeot 
gen9_dc_off_power_well_disable(struct drm_i915_private * dev_priv,struct i915_power_well * power_well)726aee94f86SFrançois Tigeot static void gen9_dc_off_power_well_disable(struct drm_i915_private *dev_priv,
727aee94f86SFrançois Tigeot 					   struct i915_power_well *power_well)
728aee94f86SFrançois Tigeot {
7298621f407SFrançois Tigeot 	if (!dev_priv->csr.dmc_payload)
7308621f407SFrançois Tigeot 		return;
7318621f407SFrançois Tigeot 
7328621f407SFrançois Tigeot 	if (dev_priv->csr.allowed_dc_mask & DC_STATE_EN_UPTO_DC6)
733aee94f86SFrançois Tigeot 		skl_enable_dc6(dev_priv);
7348621f407SFrançois Tigeot 	else if (dev_priv->csr.allowed_dc_mask & DC_STATE_EN_UPTO_DC5)
735aee94f86SFrançois Tigeot 		gen9_enable_dc5(dev_priv);
736aee94f86SFrançois Tigeot }
737aee94f86SFrançois Tigeot 
i9xx_power_well_sync_hw_noop(struct drm_i915_private * dev_priv,struct i915_power_well * power_well)738a85cb24fSFrançois Tigeot static void i9xx_power_well_sync_hw_noop(struct drm_i915_private *dev_priv,
739aee94f86SFrançois Tigeot 					 struct i915_power_well *power_well)
740aee94f86SFrançois Tigeot {
741aee94f86SFrançois Tigeot }
742aee94f86SFrançois Tigeot 
i9xx_always_on_power_well_noop(struct drm_i915_private * dev_priv,struct i915_power_well * power_well)7432c9916cdSFrançois Tigeot static void i9xx_always_on_power_well_noop(struct drm_i915_private *dev_priv,
7442c9916cdSFrançois Tigeot 					   struct i915_power_well *power_well)
7452c9916cdSFrançois Tigeot {
7462c9916cdSFrançois Tigeot }
7472c9916cdSFrançois Tigeot 
i9xx_always_on_power_well_enabled(struct drm_i915_private * dev_priv,struct i915_power_well * power_well)7482c9916cdSFrançois Tigeot static bool i9xx_always_on_power_well_enabled(struct drm_i915_private *dev_priv,
7492c9916cdSFrançois Tigeot 					     struct i915_power_well *power_well)
7502c9916cdSFrançois Tigeot {
7512c9916cdSFrançois Tigeot 	return true;
7522c9916cdSFrançois Tigeot }
7532c9916cdSFrançois Tigeot 
i830_pipes_power_well_enable(struct drm_i915_private * dev_priv,struct i915_power_well * power_well)754*3f2dd94aSFrançois Tigeot static void i830_pipes_power_well_enable(struct drm_i915_private *dev_priv,
755*3f2dd94aSFrançois Tigeot 					 struct i915_power_well *power_well)
756*3f2dd94aSFrançois Tigeot {
757*3f2dd94aSFrançois Tigeot 	if ((I915_READ(PIPECONF(PIPE_A)) & PIPECONF_ENABLE) == 0)
758*3f2dd94aSFrançois Tigeot 		i830_enable_pipe(dev_priv, PIPE_A);
759*3f2dd94aSFrançois Tigeot 	if ((I915_READ(PIPECONF(PIPE_B)) & PIPECONF_ENABLE) == 0)
760*3f2dd94aSFrançois Tigeot 		i830_enable_pipe(dev_priv, PIPE_B);
761*3f2dd94aSFrançois Tigeot }
762*3f2dd94aSFrançois Tigeot 
i830_pipes_power_well_disable(struct drm_i915_private * dev_priv,struct i915_power_well * power_well)763*3f2dd94aSFrançois Tigeot static void i830_pipes_power_well_disable(struct drm_i915_private *dev_priv,
764*3f2dd94aSFrançois Tigeot 					  struct i915_power_well *power_well)
765*3f2dd94aSFrançois Tigeot {
766*3f2dd94aSFrançois Tigeot 	i830_disable_pipe(dev_priv, PIPE_B);
767*3f2dd94aSFrançois Tigeot 	i830_disable_pipe(dev_priv, PIPE_A);
768*3f2dd94aSFrançois Tigeot }
769*3f2dd94aSFrançois Tigeot 
i830_pipes_power_well_enabled(struct drm_i915_private * dev_priv,struct i915_power_well * power_well)770*3f2dd94aSFrançois Tigeot static bool i830_pipes_power_well_enabled(struct drm_i915_private *dev_priv,
771*3f2dd94aSFrançois Tigeot 					  struct i915_power_well *power_well)
772*3f2dd94aSFrançois Tigeot {
773*3f2dd94aSFrançois Tigeot 	return I915_READ(PIPECONF(PIPE_A)) & PIPECONF_ENABLE &&
774*3f2dd94aSFrançois Tigeot 		I915_READ(PIPECONF(PIPE_B)) & PIPECONF_ENABLE;
775*3f2dd94aSFrançois Tigeot }
776*3f2dd94aSFrançois Tigeot 
i830_pipes_power_well_sync_hw(struct drm_i915_private * dev_priv,struct i915_power_well * power_well)777*3f2dd94aSFrançois Tigeot static void i830_pipes_power_well_sync_hw(struct drm_i915_private *dev_priv,
778*3f2dd94aSFrançois Tigeot 					  struct i915_power_well *power_well)
779*3f2dd94aSFrançois Tigeot {
780*3f2dd94aSFrançois Tigeot 	if (power_well->count > 0)
781*3f2dd94aSFrançois Tigeot 		i830_pipes_power_well_enable(dev_priv, power_well);
782*3f2dd94aSFrançois Tigeot 	else
783*3f2dd94aSFrançois Tigeot 		i830_pipes_power_well_disable(dev_priv, power_well);
784*3f2dd94aSFrançois Tigeot }
785*3f2dd94aSFrançois Tigeot 
vlv_set_power_well(struct drm_i915_private * dev_priv,struct i915_power_well * power_well,bool enable)7862c9916cdSFrançois Tigeot static void vlv_set_power_well(struct drm_i915_private *dev_priv,
7872c9916cdSFrançois Tigeot 			       struct i915_power_well *power_well, bool enable)
7882c9916cdSFrançois Tigeot {
789*3f2dd94aSFrançois Tigeot 	enum i915_power_well_id power_well_id = power_well->id;
7902c9916cdSFrançois Tigeot 	u32 mask;
7912c9916cdSFrançois Tigeot 	u32 state;
7922c9916cdSFrançois Tigeot 	u32 ctrl;
7932c9916cdSFrançois Tigeot 
7942c9916cdSFrançois Tigeot 	mask = PUNIT_PWRGT_MASK(power_well_id);
7952c9916cdSFrançois Tigeot 	state = enable ? PUNIT_PWRGT_PWR_ON(power_well_id) :
7962c9916cdSFrançois Tigeot 			 PUNIT_PWRGT_PWR_GATE(power_well_id);
7972c9916cdSFrançois Tigeot 
798*3f2dd94aSFrançois Tigeot 	mutex_lock(&dev_priv->pcu_lock);
7992c9916cdSFrançois Tigeot 
8002c9916cdSFrançois Tigeot #define COND \
8012c9916cdSFrançois Tigeot 	((vlv_punit_read(dev_priv, PUNIT_REG_PWRGT_STATUS) & mask) == state)
8022c9916cdSFrançois Tigeot 
8032c9916cdSFrançois Tigeot 	if (COND)
8042c9916cdSFrançois Tigeot 		goto out;
8052c9916cdSFrançois Tigeot 
8062c9916cdSFrançois Tigeot 	ctrl = vlv_punit_read(dev_priv, PUNIT_REG_PWRGT_CTRL);
8072c9916cdSFrançois Tigeot 	ctrl &= ~mask;
8082c9916cdSFrançois Tigeot 	ctrl |= state;
8092c9916cdSFrançois Tigeot 	vlv_punit_write(dev_priv, PUNIT_REG_PWRGT_CTRL, ctrl);
8102c9916cdSFrançois Tigeot 
8112c9916cdSFrançois Tigeot 	if (wait_for(COND, 100))
81219c468b4SFrançois Tigeot 		DRM_ERROR("timeout setting power well state %08x (%08x)\n",
8132c9916cdSFrançois Tigeot 			  state,
8142c9916cdSFrançois Tigeot 			  vlv_punit_read(dev_priv, PUNIT_REG_PWRGT_CTRL));
8152c9916cdSFrançois Tigeot 
8162c9916cdSFrançois Tigeot #undef COND
8172c9916cdSFrançois Tigeot 
8182c9916cdSFrançois Tigeot out:
819*3f2dd94aSFrançois Tigeot 	mutex_unlock(&dev_priv->pcu_lock);
8202c9916cdSFrançois Tigeot }
8212c9916cdSFrançois Tigeot 
vlv_power_well_enable(struct drm_i915_private * dev_priv,struct i915_power_well * power_well)8222c9916cdSFrançois Tigeot static void vlv_power_well_enable(struct drm_i915_private *dev_priv,
8232c9916cdSFrançois Tigeot 				  struct i915_power_well *power_well)
8242c9916cdSFrançois Tigeot {
8252c9916cdSFrançois Tigeot 	vlv_set_power_well(dev_priv, power_well, true);
8262c9916cdSFrançois Tigeot }
8272c9916cdSFrançois Tigeot 
vlv_power_well_disable(struct drm_i915_private * dev_priv,struct i915_power_well * power_well)8282c9916cdSFrançois Tigeot static void vlv_power_well_disable(struct drm_i915_private *dev_priv,
8292c9916cdSFrançois Tigeot 				   struct i915_power_well *power_well)
8302c9916cdSFrançois Tigeot {
8312c9916cdSFrançois Tigeot 	vlv_set_power_well(dev_priv, power_well, false);
8322c9916cdSFrançois Tigeot }
8332c9916cdSFrançois Tigeot 
vlv_power_well_enabled(struct drm_i915_private * dev_priv,struct i915_power_well * power_well)8342c9916cdSFrançois Tigeot static bool vlv_power_well_enabled(struct drm_i915_private *dev_priv,
8352c9916cdSFrançois Tigeot 				   struct i915_power_well *power_well)
8362c9916cdSFrançois Tigeot {
837*3f2dd94aSFrançois Tigeot 	enum i915_power_well_id power_well_id = power_well->id;
8382c9916cdSFrançois Tigeot 	bool enabled = false;
8392c9916cdSFrançois Tigeot 	u32 mask;
8402c9916cdSFrançois Tigeot 	u32 state;
8412c9916cdSFrançois Tigeot 	u32 ctrl;
8422c9916cdSFrançois Tigeot 
8432c9916cdSFrançois Tigeot 	mask = PUNIT_PWRGT_MASK(power_well_id);
8442c9916cdSFrançois Tigeot 	ctrl = PUNIT_PWRGT_PWR_ON(power_well_id);
8452c9916cdSFrançois Tigeot 
846*3f2dd94aSFrançois Tigeot 	mutex_lock(&dev_priv->pcu_lock);
8472c9916cdSFrançois Tigeot 
8482c9916cdSFrançois Tigeot 	state = vlv_punit_read(dev_priv, PUNIT_REG_PWRGT_STATUS) & mask;
8492c9916cdSFrançois Tigeot 	/*
8502c9916cdSFrançois Tigeot 	 * We only ever set the power-on and power-gate states, anything
8512c9916cdSFrançois Tigeot 	 * else is unexpected.
8522c9916cdSFrançois Tigeot 	 */
8532c9916cdSFrançois Tigeot 	WARN_ON(state != PUNIT_PWRGT_PWR_ON(power_well_id) &&
8542c9916cdSFrançois Tigeot 		state != PUNIT_PWRGT_PWR_GATE(power_well_id));
8552c9916cdSFrançois Tigeot 	if (state == ctrl)
8562c9916cdSFrançois Tigeot 		enabled = true;
8572c9916cdSFrançois Tigeot 
8582c9916cdSFrançois Tigeot 	/*
8592c9916cdSFrançois Tigeot 	 * A transient state at this point would mean some unexpected party
8602c9916cdSFrançois Tigeot 	 * is poking at the power controls too.
8612c9916cdSFrançois Tigeot 	 */
8622c9916cdSFrançois Tigeot 	ctrl = vlv_punit_read(dev_priv, PUNIT_REG_PWRGT_CTRL) & mask;
8632c9916cdSFrançois Tigeot 	WARN_ON(ctrl != state);
8642c9916cdSFrançois Tigeot 
865*3f2dd94aSFrançois Tigeot 	mutex_unlock(&dev_priv->pcu_lock);
8662c9916cdSFrançois Tigeot 
8672c9916cdSFrançois Tigeot 	return enabled;
8682c9916cdSFrançois Tigeot }
8692c9916cdSFrançois Tigeot 
vlv_init_display_clock_gating(struct drm_i915_private * dev_priv)8708621f407SFrançois Tigeot static void vlv_init_display_clock_gating(struct drm_i915_private *dev_priv)
8718621f407SFrançois Tigeot {
8724be47400SFrançois Tigeot 	u32 val;
8734be47400SFrançois Tigeot 
8744be47400SFrançois Tigeot 	/*
8754be47400SFrançois Tigeot 	 * On driver load, a pipe may be active and driving a DSI display.
8764be47400SFrançois Tigeot 	 * Preserve DPOUNIT_CLOCK_GATE_DISABLE to avoid the pipe getting stuck
8774be47400SFrançois Tigeot 	 * (and never recovering) in this case. intel_dsi_post_disable() will
8784be47400SFrançois Tigeot 	 * clear it when we turn off the display.
8794be47400SFrançois Tigeot 	 */
8804be47400SFrançois Tigeot 	val = I915_READ(DSPCLK_GATE_D);
8814be47400SFrançois Tigeot 	val &= DPOUNIT_CLOCK_GATE_DISABLE;
8824be47400SFrançois Tigeot 	val |= VRHUNIT_CLOCK_GATE_DISABLE;
8834be47400SFrançois Tigeot 	I915_WRITE(DSPCLK_GATE_D, val);
8848621f407SFrançois Tigeot 
8858621f407SFrançois Tigeot 	/*
8868621f407SFrançois Tigeot 	 * Disable trickle feed and enable pnd deadline calculation
8878621f407SFrançois Tigeot 	 */
8888621f407SFrançois Tigeot 	I915_WRITE(MI_ARB_VLV, MI_ARB_DISPLAY_TRICKLE_FEED_DISABLE);
8898621f407SFrançois Tigeot 	I915_WRITE(CBR1_VLV, 0);
8901487f786SFrançois Tigeot 
8911487f786SFrançois Tigeot 	WARN_ON(dev_priv->rawclk_freq == 0);
8921487f786SFrançois Tigeot 
8931487f786SFrançois Tigeot 	I915_WRITE(RAWCLK_FREQ_VLV,
8941487f786SFrançois Tigeot 		   DIV_ROUND_CLOSEST(dev_priv->rawclk_freq, 1000));
8958621f407SFrançois Tigeot }
8968621f407SFrançois Tigeot 
vlv_display_power_well_init(struct drm_i915_private * dev_priv)897a05eeebfSFrançois Tigeot static void vlv_display_power_well_init(struct drm_i915_private *dev_priv)
8982c9916cdSFrançois Tigeot {
899bf017597SFrançois Tigeot 	struct intel_encoder *encoder;
900352ff8bdSFrançois Tigeot 	enum i915_pipe pipe;
901352ff8bdSFrançois Tigeot 
902352ff8bdSFrançois Tigeot 	/*
903352ff8bdSFrançois Tigeot 	 * Enable the CRI clock source so we can get at the
904352ff8bdSFrançois Tigeot 	 * display and the reference clock for VGA
905352ff8bdSFrançois Tigeot 	 * hotplug / manual detection. Supposedly DSI also
906352ff8bdSFrançois Tigeot 	 * needs the ref clock up and running.
907352ff8bdSFrançois Tigeot 	 *
908352ff8bdSFrançois Tigeot 	 * CHV DPLL B/C have some issues if VGA mode is enabled.
909352ff8bdSFrançois Tigeot 	 */
9104be47400SFrançois Tigeot 	for_each_pipe(dev_priv, pipe) {
911352ff8bdSFrançois Tigeot 		u32 val = I915_READ(DPLL(pipe));
912352ff8bdSFrançois Tigeot 
913352ff8bdSFrançois Tigeot 		val |= DPLL_REF_CLK_ENABLE_VLV | DPLL_VGA_MODE_DIS;
914352ff8bdSFrançois Tigeot 		if (pipe != PIPE_A)
915352ff8bdSFrançois Tigeot 			val |= DPLL_INTEGRATED_CRI_CLK_VLV;
916352ff8bdSFrançois Tigeot 
917352ff8bdSFrançois Tigeot 		I915_WRITE(DPLL(pipe), val);
918352ff8bdSFrançois Tigeot 	}
9192c9916cdSFrançois Tigeot 
9208621f407SFrançois Tigeot 	vlv_init_display_clock_gating(dev_priv);
9218621f407SFrançois Tigeot 
9224db2f768SFrançois Tigeot 	spin_lock_irq(&dev_priv->irq_lock);
9232c9916cdSFrançois Tigeot 	valleyview_enable_display_irqs(dev_priv);
9244db2f768SFrançois Tigeot 	spin_unlock_irq(&dev_priv->irq_lock);
9252c9916cdSFrançois Tigeot 
9262c9916cdSFrançois Tigeot 	/*
9272c9916cdSFrançois Tigeot 	 * During driver initialization/resume we can avoid restoring the
9282c9916cdSFrançois Tigeot 	 * part of the HW/SW state that will be inited anyway explicitly.
9292c9916cdSFrançois Tigeot 	 */
9302c9916cdSFrançois Tigeot 	if (dev_priv->power_domains.initializing)
9312c9916cdSFrançois Tigeot 		return;
9322c9916cdSFrançois Tigeot 
9332c9916cdSFrançois Tigeot 	intel_hpd_init(dev_priv);
9342c9916cdSFrançois Tigeot 
935bf017597SFrançois Tigeot 	/* Re-enable the ADPA, if we have one */
936bf017597SFrançois Tigeot 	for_each_intel_encoder(&dev_priv->drm, encoder) {
937bf017597SFrançois Tigeot 		if (encoder->type == INTEL_OUTPUT_ANALOG)
938bf017597SFrançois Tigeot 			intel_crt_reset(&encoder->base);
939bf017597SFrançois Tigeot 	}
940bf017597SFrançois Tigeot 
9414be47400SFrançois Tigeot 	i915_redisable_vga_power_on(dev_priv);
9421e12ee3bSFrançois Tigeot 
9431e12ee3bSFrançois Tigeot 	intel_pps_unlock_regs_wa(dev_priv);
9442c9916cdSFrançois Tigeot }
9452c9916cdSFrançois Tigeot 
vlv_display_power_well_deinit(struct drm_i915_private * dev_priv)946a05eeebfSFrançois Tigeot static void vlv_display_power_well_deinit(struct drm_i915_private *dev_priv)
947a05eeebfSFrançois Tigeot {
9484db2f768SFrançois Tigeot 	spin_lock_irq(&dev_priv->irq_lock);
949a05eeebfSFrançois Tigeot 	valleyview_disable_display_irqs(dev_priv);
9504db2f768SFrançois Tigeot 	spin_unlock_irq(&dev_priv->irq_lock);
951a05eeebfSFrançois Tigeot 
952c0e85e96SFrançois Tigeot 	/* make sure we're done processing display irqs */
953303bf270SFrançois Tigeot 	synchronize_irq(dev_priv->drm.irq);
954c0e85e96SFrançois Tigeot 
9551487f786SFrançois Tigeot 	intel_power_sequencer_reset(dev_priv);
956bf017597SFrançois Tigeot 
9574be47400SFrançois Tigeot 	/* Prevent us from re-enabling polling on accident in late suspend */
9584be47400SFrançois Tigeot 	if (!dev_priv->drm.dev->power.is_suspended)
959bf017597SFrançois Tigeot 		intel_hpd_poll_init(dev_priv);
960a05eeebfSFrançois Tigeot }
961a05eeebfSFrançois Tigeot 
vlv_display_power_well_enable(struct drm_i915_private * dev_priv,struct i915_power_well * power_well)962a05eeebfSFrançois Tigeot static void vlv_display_power_well_enable(struct drm_i915_private *dev_priv,
963a05eeebfSFrançois Tigeot 					  struct i915_power_well *power_well)
964a05eeebfSFrançois Tigeot {
9654be47400SFrançois Tigeot 	WARN_ON_ONCE(power_well->id != PUNIT_POWER_WELL_DISP2D);
966a05eeebfSFrançois Tigeot 
967a05eeebfSFrançois Tigeot 	vlv_set_power_well(dev_priv, power_well, true);
968a05eeebfSFrançois Tigeot 
969a05eeebfSFrançois Tigeot 	vlv_display_power_well_init(dev_priv);
970a05eeebfSFrançois Tigeot }
971a05eeebfSFrançois Tigeot 
vlv_display_power_well_disable(struct drm_i915_private * dev_priv,struct i915_power_well * power_well)9722c9916cdSFrançois Tigeot static void vlv_display_power_well_disable(struct drm_i915_private *dev_priv,
9732c9916cdSFrançois Tigeot 					   struct i915_power_well *power_well)
9742c9916cdSFrançois Tigeot {
9754be47400SFrançois Tigeot 	WARN_ON_ONCE(power_well->id != PUNIT_POWER_WELL_DISP2D);
9762c9916cdSFrançois Tigeot 
977a05eeebfSFrançois Tigeot 	vlv_display_power_well_deinit(dev_priv);
9782c9916cdSFrançois Tigeot 
9792c9916cdSFrançois Tigeot 	vlv_set_power_well(dev_priv, power_well, false);
9802c9916cdSFrançois Tigeot }
9812c9916cdSFrançois Tigeot 
vlv_dpio_cmn_power_well_enable(struct drm_i915_private * dev_priv,struct i915_power_well * power_well)9822c9916cdSFrançois Tigeot static void vlv_dpio_cmn_power_well_enable(struct drm_i915_private *dev_priv,
9832c9916cdSFrançois Tigeot 					   struct i915_power_well *power_well)
9842c9916cdSFrançois Tigeot {
9854be47400SFrançois Tigeot 	WARN_ON_ONCE(power_well->id != PUNIT_POWER_WELL_DPIO_CMN_BC);
9862c9916cdSFrançois Tigeot 
987352ff8bdSFrançois Tigeot 	/* since ref/cri clock was enabled */
9882c9916cdSFrançois Tigeot 	udelay(1); /* >10ns for cmnreset, >0ns for sidereset */
9892c9916cdSFrançois Tigeot 
9902c9916cdSFrançois Tigeot 	vlv_set_power_well(dev_priv, power_well, true);
9912c9916cdSFrançois Tigeot 
9922c9916cdSFrançois Tigeot 	/*
9932c9916cdSFrançois Tigeot 	 * From VLV2A0_DP_eDP_DPIO_driver_vbios_notes_10.docx -
9942c9916cdSFrançois Tigeot 	 *  6.	De-assert cmn_reset/side_reset. Same as VLV X0.
9952c9916cdSFrançois Tigeot 	 *   a.	GUnit 0x2110 bit[0] set to 1 (def 0)
9962c9916cdSFrançois Tigeot 	 *   b.	The other bits such as sfr settings / modesel may all
9972c9916cdSFrançois Tigeot 	 *	be set to 0.
9982c9916cdSFrançois Tigeot 	 *
9992c9916cdSFrançois Tigeot 	 * This should only be done on init and resume from S3 with
10002c9916cdSFrançois Tigeot 	 * both PLLs disabled, or we risk losing DPIO and PLL
10012c9916cdSFrançois Tigeot 	 * synchronization.
10022c9916cdSFrançois Tigeot 	 */
10032c9916cdSFrançois Tigeot 	I915_WRITE(DPIO_CTL, I915_READ(DPIO_CTL) | DPIO_CMNRST);
10042c9916cdSFrançois Tigeot }
10052c9916cdSFrançois Tigeot 
vlv_dpio_cmn_power_well_disable(struct drm_i915_private * dev_priv,struct i915_power_well * power_well)10062c9916cdSFrançois Tigeot static void vlv_dpio_cmn_power_well_disable(struct drm_i915_private *dev_priv,
10072c9916cdSFrançois Tigeot 					    struct i915_power_well *power_well)
10082c9916cdSFrançois Tigeot {
10092c9916cdSFrançois Tigeot 	enum i915_pipe pipe;
10102c9916cdSFrançois Tigeot 
10114be47400SFrançois Tigeot 	WARN_ON_ONCE(power_well->id != PUNIT_POWER_WELL_DPIO_CMN_BC);
10122c9916cdSFrançois Tigeot 
10132c9916cdSFrançois Tigeot 	for_each_pipe(dev_priv, pipe)
10142c9916cdSFrançois Tigeot 		assert_pll_disabled(dev_priv, pipe);
10152c9916cdSFrançois Tigeot 
10162c9916cdSFrançois Tigeot 	/* Assert common reset */
10172c9916cdSFrançois Tigeot 	I915_WRITE(DPIO_CTL, I915_READ(DPIO_CTL) & ~DPIO_CMNRST);
10182c9916cdSFrançois Tigeot 
10192c9916cdSFrançois Tigeot 	vlv_set_power_well(dev_priv, power_well, false);
10202c9916cdSFrançois Tigeot }
10212c9916cdSFrançois Tigeot 
1022a85cb24fSFrançois Tigeot #define POWER_DOMAIN_MASK (GENMASK_ULL(POWER_DOMAIN_NUM - 1, 0))
1023352ff8bdSFrançois Tigeot 
1024*3f2dd94aSFrançois Tigeot static struct i915_power_well *
lookup_power_well(struct drm_i915_private * dev_priv,enum i915_power_well_id power_well_id)1025*3f2dd94aSFrançois Tigeot lookup_power_well(struct drm_i915_private *dev_priv,
1026*3f2dd94aSFrançois Tigeot 		  enum i915_power_well_id power_well_id)
1027352ff8bdSFrançois Tigeot {
1028352ff8bdSFrançois Tigeot 	struct i915_power_domains *power_domains = &dev_priv->power_domains;
1029352ff8bdSFrançois Tigeot 	int i;
1030352ff8bdSFrançois Tigeot 
1031aee94f86SFrançois Tigeot 	for (i = 0; i < power_domains->power_well_count; i++) {
1032aee94f86SFrançois Tigeot 		struct i915_power_well *power_well;
1033aee94f86SFrançois Tigeot 
1034aee94f86SFrançois Tigeot 		power_well = &power_domains->power_wells[i];
10354be47400SFrançois Tigeot 		if (power_well->id == power_well_id)
1036352ff8bdSFrançois Tigeot 			return power_well;
1037352ff8bdSFrançois Tigeot 	}
1038352ff8bdSFrançois Tigeot 
1039352ff8bdSFrançois Tigeot 	return NULL;
1040352ff8bdSFrançois Tigeot }
1041352ff8bdSFrançois Tigeot 
1042352ff8bdSFrançois Tigeot #define BITS_SET(val, bits) (((val) & (bits)) == (bits))
1043352ff8bdSFrançois Tigeot 
assert_chv_phy_status(struct drm_i915_private * dev_priv)1044352ff8bdSFrançois Tigeot static void assert_chv_phy_status(struct drm_i915_private *dev_priv)
1045352ff8bdSFrançois Tigeot {
1046352ff8bdSFrançois Tigeot 	struct i915_power_well *cmn_bc =
1047352ff8bdSFrançois Tigeot 		lookup_power_well(dev_priv, PUNIT_POWER_WELL_DPIO_CMN_BC);
1048352ff8bdSFrançois Tigeot 	struct i915_power_well *cmn_d =
1049352ff8bdSFrançois Tigeot 		lookup_power_well(dev_priv, PUNIT_POWER_WELL_DPIO_CMN_D);
1050352ff8bdSFrançois Tigeot 	u32 phy_control = dev_priv->chv_phy_control;
1051352ff8bdSFrançois Tigeot 	u32 phy_status = 0;
1052352ff8bdSFrançois Tigeot 	u32 phy_status_mask = 0xffffffff;
1053352ff8bdSFrançois Tigeot 
1054352ff8bdSFrançois Tigeot 	/*
1055352ff8bdSFrançois Tigeot 	 * The BIOS can leave the PHY is some weird state
1056352ff8bdSFrançois Tigeot 	 * where it doesn't fully power down some parts.
1057352ff8bdSFrançois Tigeot 	 * Disable the asserts until the PHY has been fully
1058352ff8bdSFrançois Tigeot 	 * reset (ie. the power well has been disabled at
1059352ff8bdSFrançois Tigeot 	 * least once).
1060352ff8bdSFrançois Tigeot 	 */
1061352ff8bdSFrançois Tigeot 	if (!dev_priv->chv_phy_assert[DPIO_PHY0])
1062352ff8bdSFrançois Tigeot 		phy_status_mask &= ~(PHY_STATUS_CMN_LDO(DPIO_PHY0, DPIO_CH0) |
1063352ff8bdSFrançois Tigeot 				     PHY_STATUS_SPLINE_LDO(DPIO_PHY0, DPIO_CH0, 0) |
1064352ff8bdSFrançois Tigeot 				     PHY_STATUS_SPLINE_LDO(DPIO_PHY0, DPIO_CH0, 1) |
1065352ff8bdSFrançois Tigeot 				     PHY_STATUS_CMN_LDO(DPIO_PHY0, DPIO_CH1) |
1066352ff8bdSFrançois Tigeot 				     PHY_STATUS_SPLINE_LDO(DPIO_PHY0, DPIO_CH1, 0) |
1067352ff8bdSFrançois Tigeot 				     PHY_STATUS_SPLINE_LDO(DPIO_PHY0, DPIO_CH1, 1));
1068352ff8bdSFrançois Tigeot 
1069352ff8bdSFrançois Tigeot 	if (!dev_priv->chv_phy_assert[DPIO_PHY1])
1070352ff8bdSFrançois Tigeot 		phy_status_mask &= ~(PHY_STATUS_CMN_LDO(DPIO_PHY1, DPIO_CH0) |
1071352ff8bdSFrançois Tigeot 				     PHY_STATUS_SPLINE_LDO(DPIO_PHY1, DPIO_CH0, 0) |
1072352ff8bdSFrançois Tigeot 				     PHY_STATUS_SPLINE_LDO(DPIO_PHY1, DPIO_CH0, 1));
1073352ff8bdSFrançois Tigeot 
1074352ff8bdSFrançois Tigeot 	if (cmn_bc->ops->is_enabled(dev_priv, cmn_bc)) {
1075352ff8bdSFrançois Tigeot 		phy_status |= PHY_POWERGOOD(DPIO_PHY0);
1076352ff8bdSFrançois Tigeot 
1077352ff8bdSFrançois Tigeot 		/* this assumes override is only used to enable lanes */
1078352ff8bdSFrançois Tigeot 		if ((phy_control & PHY_CH_POWER_DOWN_OVRD_EN(DPIO_PHY0, DPIO_CH0)) == 0)
1079352ff8bdSFrançois Tigeot 			phy_control |= PHY_CH_POWER_DOWN_OVRD(0xf, DPIO_PHY0, DPIO_CH0);
1080352ff8bdSFrançois Tigeot 
1081352ff8bdSFrançois Tigeot 		if ((phy_control & PHY_CH_POWER_DOWN_OVRD_EN(DPIO_PHY0, DPIO_CH1)) == 0)
1082352ff8bdSFrançois Tigeot 			phy_control |= PHY_CH_POWER_DOWN_OVRD(0xf, DPIO_PHY0, DPIO_CH1);
1083352ff8bdSFrançois Tigeot 
1084352ff8bdSFrançois Tigeot 		/* CL1 is on whenever anything is on in either channel */
1085352ff8bdSFrançois Tigeot 		if (BITS_SET(phy_control,
1086352ff8bdSFrançois Tigeot 			     PHY_CH_POWER_DOWN_OVRD(0xf, DPIO_PHY0, DPIO_CH0) |
1087352ff8bdSFrançois Tigeot 			     PHY_CH_POWER_DOWN_OVRD(0xf, DPIO_PHY0, DPIO_CH1)))
1088352ff8bdSFrançois Tigeot 			phy_status |= PHY_STATUS_CMN_LDO(DPIO_PHY0, DPIO_CH0);
1089352ff8bdSFrançois Tigeot 
1090352ff8bdSFrançois Tigeot 		/*
1091352ff8bdSFrançois Tigeot 		 * The DPLLB check accounts for the pipe B + port A usage
1092352ff8bdSFrançois Tigeot 		 * with CL2 powered up but all the lanes in the second channel
1093352ff8bdSFrançois Tigeot 		 * powered down.
1094352ff8bdSFrançois Tigeot 		 */
1095352ff8bdSFrançois Tigeot 		if (BITS_SET(phy_control,
1096352ff8bdSFrançois Tigeot 			     PHY_CH_POWER_DOWN_OVRD(0xf, DPIO_PHY0, DPIO_CH1)) &&
1097352ff8bdSFrançois Tigeot 		    (I915_READ(DPLL(PIPE_B)) & DPLL_VCO_ENABLE) == 0)
1098352ff8bdSFrançois Tigeot 			phy_status |= PHY_STATUS_CMN_LDO(DPIO_PHY0, DPIO_CH1);
1099352ff8bdSFrançois Tigeot 
1100352ff8bdSFrançois Tigeot 		if (BITS_SET(phy_control,
1101352ff8bdSFrançois Tigeot 			     PHY_CH_POWER_DOWN_OVRD(0x3, DPIO_PHY0, DPIO_CH0)))
1102352ff8bdSFrançois Tigeot 			phy_status |= PHY_STATUS_SPLINE_LDO(DPIO_PHY0, DPIO_CH0, 0);
1103352ff8bdSFrançois Tigeot 		if (BITS_SET(phy_control,
1104352ff8bdSFrançois Tigeot 			     PHY_CH_POWER_DOWN_OVRD(0xc, DPIO_PHY0, DPIO_CH0)))
1105352ff8bdSFrançois Tigeot 			phy_status |= PHY_STATUS_SPLINE_LDO(DPIO_PHY0, DPIO_CH0, 1);
1106352ff8bdSFrançois Tigeot 
1107352ff8bdSFrançois Tigeot 		if (BITS_SET(phy_control,
1108352ff8bdSFrançois Tigeot 			     PHY_CH_POWER_DOWN_OVRD(0x3, DPIO_PHY0, DPIO_CH1)))
1109352ff8bdSFrançois Tigeot 			phy_status |= PHY_STATUS_SPLINE_LDO(DPIO_PHY0, DPIO_CH1, 0);
1110352ff8bdSFrançois Tigeot 		if (BITS_SET(phy_control,
1111352ff8bdSFrançois Tigeot 			     PHY_CH_POWER_DOWN_OVRD(0xc, DPIO_PHY0, DPIO_CH1)))
1112352ff8bdSFrançois Tigeot 			phy_status |= PHY_STATUS_SPLINE_LDO(DPIO_PHY0, DPIO_CH1, 1);
1113352ff8bdSFrançois Tigeot 	}
1114352ff8bdSFrançois Tigeot 
1115352ff8bdSFrançois Tigeot 	if (cmn_d->ops->is_enabled(dev_priv, cmn_d)) {
1116352ff8bdSFrançois Tigeot 		phy_status |= PHY_POWERGOOD(DPIO_PHY1);
1117352ff8bdSFrançois Tigeot 
1118352ff8bdSFrançois Tigeot 		/* this assumes override is only used to enable lanes */
1119352ff8bdSFrançois Tigeot 		if ((phy_control & PHY_CH_POWER_DOWN_OVRD_EN(DPIO_PHY1, DPIO_CH0)) == 0)
1120352ff8bdSFrançois Tigeot 			phy_control |= PHY_CH_POWER_DOWN_OVRD(0xf, DPIO_PHY1, DPIO_CH0);
1121352ff8bdSFrançois Tigeot 
1122352ff8bdSFrançois Tigeot 		if (BITS_SET(phy_control,
1123352ff8bdSFrançois Tigeot 			     PHY_CH_POWER_DOWN_OVRD(0xf, DPIO_PHY1, DPIO_CH0)))
1124352ff8bdSFrançois Tigeot 			phy_status |= PHY_STATUS_CMN_LDO(DPIO_PHY1, DPIO_CH0);
1125352ff8bdSFrançois Tigeot 
1126352ff8bdSFrançois Tigeot 		if (BITS_SET(phy_control,
1127352ff8bdSFrançois Tigeot 			     PHY_CH_POWER_DOWN_OVRD(0x3, DPIO_PHY1, DPIO_CH0)))
1128352ff8bdSFrançois Tigeot 			phy_status |= PHY_STATUS_SPLINE_LDO(DPIO_PHY1, DPIO_CH0, 0);
1129352ff8bdSFrançois Tigeot 		if (BITS_SET(phy_control,
1130352ff8bdSFrançois Tigeot 			     PHY_CH_POWER_DOWN_OVRD(0xc, DPIO_PHY1, DPIO_CH0)))
1131352ff8bdSFrançois Tigeot 			phy_status |= PHY_STATUS_SPLINE_LDO(DPIO_PHY1, DPIO_CH0, 1);
1132352ff8bdSFrançois Tigeot 	}
1133352ff8bdSFrançois Tigeot 
1134352ff8bdSFrançois Tigeot 	phy_status &= phy_status_mask;
1135352ff8bdSFrançois Tigeot 
1136352ff8bdSFrançois Tigeot 	/*
1137352ff8bdSFrançois Tigeot 	 * The PHY may be busy with some initial calibration and whatnot,
1138352ff8bdSFrançois Tigeot 	 * so the power state can take a while to actually change.
1139352ff8bdSFrançois Tigeot 	 */
11401487f786SFrançois Tigeot 	if (intel_wait_for_register(dev_priv,
11411487f786SFrançois Tigeot 				    DISPLAY_PHY_STATUS,
11421487f786SFrançois Tigeot 				    phy_status_mask,
11431487f786SFrançois Tigeot 				    phy_status,
11441487f786SFrançois Tigeot 				    10))
11451487f786SFrançois Tigeot 		DRM_ERROR("Unexpected PHY_STATUS 0x%08x, expected 0x%08x (PHY_CONTROL=0x%08x)\n",
11461487f786SFrançois Tigeot 			  I915_READ(DISPLAY_PHY_STATUS) & phy_status_mask,
11471487f786SFrançois Tigeot 			   phy_status, dev_priv->chv_phy_control);
1148352ff8bdSFrançois Tigeot }
1149352ff8bdSFrançois Tigeot 
1150352ff8bdSFrançois Tigeot #undef BITS_SET
1151352ff8bdSFrançois Tigeot 
chv_dpio_cmn_power_well_enable(struct drm_i915_private * dev_priv,struct i915_power_well * power_well)11522c9916cdSFrançois Tigeot static void chv_dpio_cmn_power_well_enable(struct drm_i915_private *dev_priv,
11532c9916cdSFrançois Tigeot 					   struct i915_power_well *power_well)
11542c9916cdSFrançois Tigeot {
11552c9916cdSFrançois Tigeot 	enum dpio_phy phy;
1156352ff8bdSFrançois Tigeot 	enum i915_pipe pipe;
1157352ff8bdSFrançois Tigeot 	uint32_t tmp;
11582c9916cdSFrançois Tigeot 
11594be47400SFrançois Tigeot 	WARN_ON_ONCE(power_well->id != PUNIT_POWER_WELL_DPIO_CMN_BC &&
11604be47400SFrançois Tigeot 		     power_well->id != PUNIT_POWER_WELL_DPIO_CMN_D);
11612c9916cdSFrançois Tigeot 
11624be47400SFrançois Tigeot 	if (power_well->id == PUNIT_POWER_WELL_DPIO_CMN_BC) {
1163352ff8bdSFrançois Tigeot 		pipe = PIPE_A;
11642c9916cdSFrançois Tigeot 		phy = DPIO_PHY0;
11652c9916cdSFrançois Tigeot 	} else {
1166352ff8bdSFrançois Tigeot 		pipe = PIPE_C;
11672c9916cdSFrançois Tigeot 		phy = DPIO_PHY1;
11682c9916cdSFrançois Tigeot 	}
1169352ff8bdSFrançois Tigeot 
1170352ff8bdSFrançois Tigeot 	/* since ref/cri clock was enabled */
11712c9916cdSFrançois Tigeot 	udelay(1); /* >10ns for cmnreset, >0ns for sidereset */
11722c9916cdSFrançois Tigeot 	vlv_set_power_well(dev_priv, power_well, true);
11732c9916cdSFrançois Tigeot 
11742c9916cdSFrançois Tigeot 	/* Poll for phypwrgood signal */
11751487f786SFrançois Tigeot 	if (intel_wait_for_register(dev_priv,
11761487f786SFrançois Tigeot 				    DISPLAY_PHY_STATUS,
11771487f786SFrançois Tigeot 				    PHY_POWERGOOD(phy),
11781487f786SFrançois Tigeot 				    PHY_POWERGOOD(phy),
11791487f786SFrançois Tigeot 				    1))
11802c9916cdSFrançois Tigeot 		DRM_ERROR("Display PHY %d is not power up\n", phy);
11812c9916cdSFrançois Tigeot 
1182352ff8bdSFrançois Tigeot 	mutex_lock(&dev_priv->sb_lock);
1183352ff8bdSFrançois Tigeot 
1184352ff8bdSFrançois Tigeot 	/* Enable dynamic power down */
1185352ff8bdSFrançois Tigeot 	tmp = vlv_dpio_read(dev_priv, pipe, CHV_CMN_DW28);
1186352ff8bdSFrançois Tigeot 	tmp |= DPIO_DYNPWRDOWNEN_CH0 | DPIO_CL1POWERDOWNEN |
1187352ff8bdSFrançois Tigeot 		DPIO_SUS_CLK_CONFIG_GATE_CLKREQ;
1188352ff8bdSFrançois Tigeot 	vlv_dpio_write(dev_priv, pipe, CHV_CMN_DW28, tmp);
1189352ff8bdSFrançois Tigeot 
11904be47400SFrançois Tigeot 	if (power_well->id == PUNIT_POWER_WELL_DPIO_CMN_BC) {
1191352ff8bdSFrançois Tigeot 		tmp = vlv_dpio_read(dev_priv, pipe, _CHV_CMN_DW6_CH1);
1192352ff8bdSFrançois Tigeot 		tmp |= DPIO_DYNPWRDOWNEN_CH1;
1193352ff8bdSFrançois Tigeot 		vlv_dpio_write(dev_priv, pipe, _CHV_CMN_DW6_CH1, tmp);
1194352ff8bdSFrançois Tigeot 	} else {
1195352ff8bdSFrançois Tigeot 		/*
1196352ff8bdSFrançois Tigeot 		 * Force the non-existing CL2 off. BXT does this
1197352ff8bdSFrançois Tigeot 		 * too, so maybe it saves some power even though
1198352ff8bdSFrançois Tigeot 		 * CL2 doesn't exist?
1199352ff8bdSFrançois Tigeot 		 */
1200352ff8bdSFrançois Tigeot 		tmp = vlv_dpio_read(dev_priv, pipe, CHV_CMN_DW30);
1201352ff8bdSFrançois Tigeot 		tmp |= DPIO_CL2_LDOFUSE_PWRENB;
1202352ff8bdSFrançois Tigeot 		vlv_dpio_write(dev_priv, pipe, CHV_CMN_DW30, tmp);
1203352ff8bdSFrançois Tigeot 	}
1204352ff8bdSFrançois Tigeot 
1205352ff8bdSFrançois Tigeot 	mutex_unlock(&dev_priv->sb_lock);
1206352ff8bdSFrançois Tigeot 
120719c468b4SFrançois Tigeot 	dev_priv->chv_phy_control |= PHY_COM_LANE_RESET_DEASSERT(phy);
120819c468b4SFrançois Tigeot 	I915_WRITE(DISPLAY_PHY_CONTROL, dev_priv->chv_phy_control);
1209352ff8bdSFrançois Tigeot 
1210352ff8bdSFrançois Tigeot 	DRM_DEBUG_KMS("Enabled DPIO PHY%d (PHY_CONTROL=0x%08x)\n",
1211352ff8bdSFrançois Tigeot 		      phy, dev_priv->chv_phy_control);
1212352ff8bdSFrançois Tigeot 
1213352ff8bdSFrançois Tigeot 	assert_chv_phy_status(dev_priv);
12142c9916cdSFrançois Tigeot }
12152c9916cdSFrançois Tigeot 
chv_dpio_cmn_power_well_disable(struct drm_i915_private * dev_priv,struct i915_power_well * power_well)12162c9916cdSFrançois Tigeot static void chv_dpio_cmn_power_well_disable(struct drm_i915_private *dev_priv,
12172c9916cdSFrançois Tigeot 					    struct i915_power_well *power_well)
12182c9916cdSFrançois Tigeot {
12192c9916cdSFrançois Tigeot 	enum dpio_phy phy;
12202c9916cdSFrançois Tigeot 
12214be47400SFrançois Tigeot 	WARN_ON_ONCE(power_well->id != PUNIT_POWER_WELL_DPIO_CMN_BC &&
12224be47400SFrançois Tigeot 		     power_well->id != PUNIT_POWER_WELL_DPIO_CMN_D);
12232c9916cdSFrançois Tigeot 
12244be47400SFrançois Tigeot 	if (power_well->id == PUNIT_POWER_WELL_DPIO_CMN_BC) {
12252c9916cdSFrançois Tigeot 		phy = DPIO_PHY0;
12262c9916cdSFrançois Tigeot 		assert_pll_disabled(dev_priv, PIPE_A);
12272c9916cdSFrançois Tigeot 		assert_pll_disabled(dev_priv, PIPE_B);
12282c9916cdSFrançois Tigeot 	} else {
12292c9916cdSFrançois Tigeot 		phy = DPIO_PHY1;
12302c9916cdSFrançois Tigeot 		assert_pll_disabled(dev_priv, PIPE_C);
12312c9916cdSFrançois Tigeot 	}
12322c9916cdSFrançois Tigeot 
123319c468b4SFrançois Tigeot 	dev_priv->chv_phy_control &= ~PHY_COM_LANE_RESET_DEASSERT(phy);
123419c468b4SFrançois Tigeot 	I915_WRITE(DISPLAY_PHY_CONTROL, dev_priv->chv_phy_control);
12352c9916cdSFrançois Tigeot 
12362c9916cdSFrançois Tigeot 	vlv_set_power_well(dev_priv, power_well, false);
1237352ff8bdSFrançois Tigeot 
1238352ff8bdSFrançois Tigeot 	DRM_DEBUG_KMS("Disabled DPIO PHY%d (PHY_CONTROL=0x%08x)\n",
1239352ff8bdSFrançois Tigeot 		      phy, dev_priv->chv_phy_control);
1240352ff8bdSFrançois Tigeot 
1241352ff8bdSFrançois Tigeot 	/* PHY is fully reset now, so we can enable the PHY state asserts */
1242352ff8bdSFrançois Tigeot 	dev_priv->chv_phy_assert[phy] = true;
1243352ff8bdSFrançois Tigeot 
1244352ff8bdSFrançois Tigeot 	assert_chv_phy_status(dev_priv);
1245352ff8bdSFrançois Tigeot }
1246352ff8bdSFrançois Tigeot 
assert_chv_phy_powergate(struct drm_i915_private * dev_priv,enum dpio_phy phy,enum dpio_channel ch,bool override,unsigned int mask)1247352ff8bdSFrançois Tigeot static void assert_chv_phy_powergate(struct drm_i915_private *dev_priv, enum dpio_phy phy,
1248352ff8bdSFrançois Tigeot 				     enum dpio_channel ch, bool override, unsigned int mask)
1249352ff8bdSFrançois Tigeot {
1250352ff8bdSFrançois Tigeot 	enum i915_pipe pipe = phy == DPIO_PHY0 ? PIPE_A : PIPE_C;
1251352ff8bdSFrançois Tigeot 	u32 reg, val, expected, actual;
1252352ff8bdSFrançois Tigeot 
1253352ff8bdSFrançois Tigeot 	/*
1254352ff8bdSFrançois Tigeot 	 * The BIOS can leave the PHY is some weird state
1255352ff8bdSFrançois Tigeot 	 * where it doesn't fully power down some parts.
1256352ff8bdSFrançois Tigeot 	 * Disable the asserts until the PHY has been fully
1257352ff8bdSFrançois Tigeot 	 * reset (ie. the power well has been disabled at
1258352ff8bdSFrançois Tigeot 	 * least once).
1259352ff8bdSFrançois Tigeot 	 */
1260352ff8bdSFrançois Tigeot 	if (!dev_priv->chv_phy_assert[phy])
1261352ff8bdSFrançois Tigeot 		return;
1262352ff8bdSFrançois Tigeot 
1263352ff8bdSFrançois Tigeot 	if (ch == DPIO_CH0)
1264352ff8bdSFrançois Tigeot 		reg = _CHV_CMN_DW0_CH0;
1265352ff8bdSFrançois Tigeot 	else
1266352ff8bdSFrançois Tigeot 		reg = _CHV_CMN_DW6_CH1;
1267352ff8bdSFrançois Tigeot 
1268352ff8bdSFrançois Tigeot 	mutex_lock(&dev_priv->sb_lock);
1269352ff8bdSFrançois Tigeot 	val = vlv_dpio_read(dev_priv, pipe, reg);
1270352ff8bdSFrançois Tigeot 	mutex_unlock(&dev_priv->sb_lock);
1271352ff8bdSFrançois Tigeot 
1272352ff8bdSFrançois Tigeot 	/*
1273352ff8bdSFrançois Tigeot 	 * This assumes !override is only used when the port is disabled.
1274352ff8bdSFrançois Tigeot 	 * All lanes should power down even without the override when
1275352ff8bdSFrançois Tigeot 	 * the port is disabled.
1276352ff8bdSFrançois Tigeot 	 */
1277352ff8bdSFrançois Tigeot 	if (!override || mask == 0xf) {
1278352ff8bdSFrançois Tigeot 		expected = DPIO_ALLDL_POWERDOWN | DPIO_ANYDL_POWERDOWN;
1279352ff8bdSFrançois Tigeot 		/*
1280352ff8bdSFrançois Tigeot 		 * If CH1 common lane is not active anymore
1281352ff8bdSFrançois Tigeot 		 * (eg. for pipe B DPLL) the entire channel will
1282352ff8bdSFrançois Tigeot 		 * shut down, which causes the common lane registers
1283352ff8bdSFrançois Tigeot 		 * to read as 0. That means we can't actually check
1284352ff8bdSFrançois Tigeot 		 * the lane power down status bits, but as the entire
1285352ff8bdSFrançois Tigeot 		 * register reads as 0 it's a good indication that the
1286352ff8bdSFrançois Tigeot 		 * channel is indeed entirely powered down.
1287352ff8bdSFrançois Tigeot 		 */
1288352ff8bdSFrançois Tigeot 		if (ch == DPIO_CH1 && val == 0)
1289352ff8bdSFrançois Tigeot 			expected = 0;
1290352ff8bdSFrançois Tigeot 	} else if (mask != 0x0) {
1291352ff8bdSFrançois Tigeot 		expected = DPIO_ANYDL_POWERDOWN;
1292352ff8bdSFrançois Tigeot 	} else {
1293352ff8bdSFrançois Tigeot 		expected = 0;
1294352ff8bdSFrançois Tigeot 	}
1295352ff8bdSFrançois Tigeot 
1296352ff8bdSFrançois Tigeot 	if (ch == DPIO_CH0)
1297352ff8bdSFrançois Tigeot 		actual = val >> DPIO_ANYDL_POWERDOWN_SHIFT_CH0;
1298352ff8bdSFrançois Tigeot 	else
1299352ff8bdSFrançois Tigeot 		actual = val >> DPIO_ANYDL_POWERDOWN_SHIFT_CH1;
1300352ff8bdSFrançois Tigeot 	actual &= DPIO_ALLDL_POWERDOWN | DPIO_ANYDL_POWERDOWN;
1301352ff8bdSFrançois Tigeot 
1302352ff8bdSFrançois Tigeot 	WARN(actual != expected,
1303352ff8bdSFrançois Tigeot 	     "Unexpected DPIO lane power down: all %d, any %d. Expected: all %d, any %d. (0x%x = 0x%08x)\n",
1304352ff8bdSFrançois Tigeot 	     !!(actual & DPIO_ALLDL_POWERDOWN), !!(actual & DPIO_ANYDL_POWERDOWN),
1305352ff8bdSFrançois Tigeot 	     !!(expected & DPIO_ALLDL_POWERDOWN), !!(expected & DPIO_ANYDL_POWERDOWN),
1306352ff8bdSFrançois Tigeot 	     reg, val);
1307352ff8bdSFrançois Tigeot }
1308352ff8bdSFrançois Tigeot 
chv_phy_powergate_ch(struct drm_i915_private * dev_priv,enum dpio_phy phy,enum dpio_channel ch,bool override)1309352ff8bdSFrançois Tigeot bool chv_phy_powergate_ch(struct drm_i915_private *dev_priv, enum dpio_phy phy,
1310352ff8bdSFrançois Tigeot 			  enum dpio_channel ch, bool override)
1311352ff8bdSFrançois Tigeot {
1312352ff8bdSFrançois Tigeot 	struct i915_power_domains *power_domains = &dev_priv->power_domains;
1313352ff8bdSFrançois Tigeot 	bool was_override;
1314352ff8bdSFrançois Tigeot 
1315352ff8bdSFrançois Tigeot 	mutex_lock(&power_domains->lock);
1316352ff8bdSFrançois Tigeot 
1317352ff8bdSFrançois Tigeot 	was_override = dev_priv->chv_phy_control & PHY_CH_POWER_DOWN_OVRD_EN(phy, ch);
1318352ff8bdSFrançois Tigeot 
1319352ff8bdSFrançois Tigeot 	if (override == was_override)
1320352ff8bdSFrançois Tigeot 		goto out;
1321352ff8bdSFrançois Tigeot 
1322352ff8bdSFrançois Tigeot 	if (override)
1323352ff8bdSFrançois Tigeot 		dev_priv->chv_phy_control |= PHY_CH_POWER_DOWN_OVRD_EN(phy, ch);
1324352ff8bdSFrançois Tigeot 	else
1325352ff8bdSFrançois Tigeot 		dev_priv->chv_phy_control &= ~PHY_CH_POWER_DOWN_OVRD_EN(phy, ch);
1326352ff8bdSFrançois Tigeot 
1327352ff8bdSFrançois Tigeot 	I915_WRITE(DISPLAY_PHY_CONTROL, dev_priv->chv_phy_control);
1328352ff8bdSFrançois Tigeot 
1329352ff8bdSFrançois Tigeot 	DRM_DEBUG_KMS("Power gating DPIO PHY%d CH%d (DPIO_PHY_CONTROL=0x%08x)\n",
1330352ff8bdSFrançois Tigeot 		      phy, ch, dev_priv->chv_phy_control);
1331352ff8bdSFrançois Tigeot 
1332352ff8bdSFrançois Tigeot 	assert_chv_phy_status(dev_priv);
1333352ff8bdSFrançois Tigeot 
1334352ff8bdSFrançois Tigeot out:
1335352ff8bdSFrançois Tigeot 	mutex_unlock(&power_domains->lock);
1336352ff8bdSFrançois Tigeot 
1337352ff8bdSFrançois Tigeot 	return was_override;
1338352ff8bdSFrançois Tigeot }
1339352ff8bdSFrançois Tigeot 
chv_phy_powergate_lanes(struct intel_encoder * encoder,bool override,unsigned int mask)1340352ff8bdSFrançois Tigeot void chv_phy_powergate_lanes(struct intel_encoder *encoder,
1341352ff8bdSFrançois Tigeot 			     bool override, unsigned int mask)
1342352ff8bdSFrançois Tigeot {
1343352ff8bdSFrançois Tigeot 	struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
1344352ff8bdSFrançois Tigeot 	struct i915_power_domains *power_domains = &dev_priv->power_domains;
1345352ff8bdSFrançois Tigeot 	enum dpio_phy phy = vlv_dport_to_phy(enc_to_dig_port(&encoder->base));
1346352ff8bdSFrançois Tigeot 	enum dpio_channel ch = vlv_dport_to_channel(enc_to_dig_port(&encoder->base));
1347352ff8bdSFrançois Tigeot 
1348352ff8bdSFrançois Tigeot 	mutex_lock(&power_domains->lock);
1349352ff8bdSFrançois Tigeot 
1350352ff8bdSFrançois Tigeot 	dev_priv->chv_phy_control &= ~PHY_CH_POWER_DOWN_OVRD(0xf, phy, ch);
1351352ff8bdSFrançois Tigeot 	dev_priv->chv_phy_control |= PHY_CH_POWER_DOWN_OVRD(mask, phy, ch);
1352352ff8bdSFrançois Tigeot 
1353352ff8bdSFrançois Tigeot 	if (override)
1354352ff8bdSFrançois Tigeot 		dev_priv->chv_phy_control |= PHY_CH_POWER_DOWN_OVRD_EN(phy, ch);
1355352ff8bdSFrançois Tigeot 	else
1356352ff8bdSFrançois Tigeot 		dev_priv->chv_phy_control &= ~PHY_CH_POWER_DOWN_OVRD_EN(phy, ch);
1357352ff8bdSFrançois Tigeot 
1358352ff8bdSFrançois Tigeot 	I915_WRITE(DISPLAY_PHY_CONTROL, dev_priv->chv_phy_control);
1359352ff8bdSFrançois Tigeot 
1360352ff8bdSFrançois Tigeot 	DRM_DEBUG_KMS("Power gating DPIO PHY%d CH%d lanes 0x%x (PHY_CONTROL=0x%08x)\n",
1361352ff8bdSFrançois Tigeot 		      phy, ch, mask, dev_priv->chv_phy_control);
1362352ff8bdSFrançois Tigeot 
1363352ff8bdSFrançois Tigeot 	assert_chv_phy_status(dev_priv);
1364352ff8bdSFrançois Tigeot 
1365352ff8bdSFrançois Tigeot 	assert_chv_phy_powergate(dev_priv, phy, ch, override, mask);
1366352ff8bdSFrançois Tigeot 
1367352ff8bdSFrançois Tigeot 	mutex_unlock(&power_domains->lock);
13682c9916cdSFrançois Tigeot }
13692c9916cdSFrançois Tigeot 
chv_pipe_power_well_enabled(struct drm_i915_private * dev_priv,struct i915_power_well * power_well)13702c9916cdSFrançois Tigeot static bool chv_pipe_power_well_enabled(struct drm_i915_private *dev_priv,
13712c9916cdSFrançois Tigeot 					struct i915_power_well *power_well)
13722c9916cdSFrançois Tigeot {
1373*3f2dd94aSFrançois Tigeot 	enum i915_pipe pipe = PIPE_A;
13742c9916cdSFrançois Tigeot 	bool enabled;
13752c9916cdSFrançois Tigeot 	u32 state, ctrl;
13762c9916cdSFrançois Tigeot 
1377*3f2dd94aSFrançois Tigeot 	mutex_lock(&dev_priv->pcu_lock);
13782c9916cdSFrançois Tigeot 
13792c9916cdSFrançois Tigeot 	state = vlv_punit_read(dev_priv, PUNIT_REG_DSPFREQ) & DP_SSS_MASK(pipe);
13802c9916cdSFrançois Tigeot 	/*
13812c9916cdSFrançois Tigeot 	 * We only ever set the power-on and power-gate states, anything
13822c9916cdSFrançois Tigeot 	 * else is unexpected.
13832c9916cdSFrançois Tigeot 	 */
13842c9916cdSFrançois Tigeot 	WARN_ON(state != DP_SSS_PWR_ON(pipe) && state != DP_SSS_PWR_GATE(pipe));
13852c9916cdSFrançois Tigeot 	enabled = state == DP_SSS_PWR_ON(pipe);
13862c9916cdSFrançois Tigeot 
13872c9916cdSFrançois Tigeot 	/*
13882c9916cdSFrançois Tigeot 	 * A transient state at this point would mean some unexpected party
13892c9916cdSFrançois Tigeot 	 * is poking at the power controls too.
13902c9916cdSFrançois Tigeot 	 */
13912c9916cdSFrançois Tigeot 	ctrl = vlv_punit_read(dev_priv, PUNIT_REG_DSPFREQ) & DP_SSC_MASK(pipe);
13922c9916cdSFrançois Tigeot 	WARN_ON(ctrl << 16 != state);
13932c9916cdSFrançois Tigeot 
1394*3f2dd94aSFrançois Tigeot 	mutex_unlock(&dev_priv->pcu_lock);
13952c9916cdSFrançois Tigeot 
13962c9916cdSFrançois Tigeot 	return enabled;
13972c9916cdSFrançois Tigeot }
13982c9916cdSFrançois Tigeot 
chv_set_pipe_power_well(struct drm_i915_private * dev_priv,struct i915_power_well * power_well,bool enable)13992c9916cdSFrançois Tigeot static void chv_set_pipe_power_well(struct drm_i915_private *dev_priv,
14002c9916cdSFrançois Tigeot 				    struct i915_power_well *power_well,
14012c9916cdSFrançois Tigeot 				    bool enable)
14022c9916cdSFrançois Tigeot {
1403*3f2dd94aSFrançois Tigeot 	enum i915_pipe pipe = PIPE_A;
14042c9916cdSFrançois Tigeot 	u32 state;
14052c9916cdSFrançois Tigeot 	u32 ctrl;
14062c9916cdSFrançois Tigeot 
14072c9916cdSFrançois Tigeot 	state = enable ? DP_SSS_PWR_ON(pipe) : DP_SSS_PWR_GATE(pipe);
14082c9916cdSFrançois Tigeot 
1409*3f2dd94aSFrançois Tigeot 	mutex_lock(&dev_priv->pcu_lock);
14102c9916cdSFrançois Tigeot 
14112c9916cdSFrançois Tigeot #define COND \
14122c9916cdSFrançois Tigeot 	((vlv_punit_read(dev_priv, PUNIT_REG_DSPFREQ) & DP_SSS_MASK(pipe)) == state)
14132c9916cdSFrançois Tigeot 
14142c9916cdSFrançois Tigeot 	if (COND)
14152c9916cdSFrançois Tigeot 		goto out;
14162c9916cdSFrançois Tigeot 
14172c9916cdSFrançois Tigeot 	ctrl = vlv_punit_read(dev_priv, PUNIT_REG_DSPFREQ);
14182c9916cdSFrançois Tigeot 	ctrl &= ~DP_SSC_MASK(pipe);
14192c9916cdSFrançois Tigeot 	ctrl |= enable ? DP_SSC_PWR_ON(pipe) : DP_SSC_PWR_GATE(pipe);
14202c9916cdSFrançois Tigeot 	vlv_punit_write(dev_priv, PUNIT_REG_DSPFREQ, ctrl);
14212c9916cdSFrançois Tigeot 
14222c9916cdSFrançois Tigeot 	if (wait_for(COND, 100))
142319c468b4SFrançois Tigeot 		DRM_ERROR("timeout setting power well state %08x (%08x)\n",
14242c9916cdSFrançois Tigeot 			  state,
14252c9916cdSFrançois Tigeot 			  vlv_punit_read(dev_priv, PUNIT_REG_DSPFREQ));
14262c9916cdSFrançois Tigeot 
14272c9916cdSFrançois Tigeot #undef COND
14282c9916cdSFrançois Tigeot 
14292c9916cdSFrançois Tigeot out:
1430*3f2dd94aSFrançois Tigeot 	mutex_unlock(&dev_priv->pcu_lock);
14312c9916cdSFrançois Tigeot }
14322c9916cdSFrançois Tigeot 
chv_pipe_power_well_enable(struct drm_i915_private * dev_priv,struct i915_power_well * power_well)14332c9916cdSFrançois Tigeot static void chv_pipe_power_well_enable(struct drm_i915_private *dev_priv,
14342c9916cdSFrançois Tigeot 				       struct i915_power_well *power_well)
14352c9916cdSFrançois Tigeot {
1436*3f2dd94aSFrançois Tigeot 	WARN_ON_ONCE(power_well->id != CHV_DISP_PW_PIPE_A);
14372c9916cdSFrançois Tigeot 
14382c9916cdSFrançois Tigeot 	chv_set_pipe_power_well(dev_priv, power_well, true);
14392c9916cdSFrançois Tigeot 
1440a05eeebfSFrançois Tigeot 	vlv_display_power_well_init(dev_priv);
14412c9916cdSFrançois Tigeot }
14422c9916cdSFrançois Tigeot 
chv_pipe_power_well_disable(struct drm_i915_private * dev_priv,struct i915_power_well * power_well)14432c9916cdSFrançois Tigeot static void chv_pipe_power_well_disable(struct drm_i915_private *dev_priv,
14442c9916cdSFrançois Tigeot 					struct i915_power_well *power_well)
14452c9916cdSFrançois Tigeot {
1446*3f2dd94aSFrançois Tigeot 	WARN_ON_ONCE(power_well->id != CHV_DISP_PW_PIPE_A);
14472c9916cdSFrançois Tigeot 
1448a05eeebfSFrançois Tigeot 	vlv_display_power_well_deinit(dev_priv);
14492c9916cdSFrançois Tigeot 
14502c9916cdSFrançois Tigeot 	chv_set_pipe_power_well(dev_priv, power_well, false);
14512c9916cdSFrançois Tigeot }
14522c9916cdSFrançois Tigeot 
1453aee94f86SFrançois Tigeot static void
__intel_display_power_get_domain(struct drm_i915_private * dev_priv,enum intel_display_power_domain domain)1454aee94f86SFrançois Tigeot __intel_display_power_get_domain(struct drm_i915_private *dev_priv,
1455aee94f86SFrançois Tigeot 				 enum intel_display_power_domain domain)
1456aee94f86SFrançois Tigeot {
1457aee94f86SFrançois Tigeot 	struct i915_power_domains *power_domains = &dev_priv->power_domains;
1458aee94f86SFrançois Tigeot 	struct i915_power_well *power_well;
1459aee94f86SFrançois Tigeot 
1460a85cb24fSFrançois Tigeot 	for_each_power_domain_well(dev_priv, power_well, BIT_ULL(domain))
14611487f786SFrançois Tigeot 		intel_power_well_get(dev_priv, power_well);
1462aee94f86SFrançois Tigeot 
1463aee94f86SFrançois Tigeot 	power_domains->domain_use_count[domain]++;
1464aee94f86SFrançois Tigeot }
1465aee94f86SFrançois Tigeot 
14662c9916cdSFrançois Tigeot /**
14672c9916cdSFrançois Tigeot  * intel_display_power_get - grab a power domain reference
14682c9916cdSFrançois Tigeot  * @dev_priv: i915 device instance
14692c9916cdSFrançois Tigeot  * @domain: power domain to reference
14702c9916cdSFrançois Tigeot  *
14712c9916cdSFrançois Tigeot  * This function grabs a power domain reference for @domain and ensures that the
14722c9916cdSFrançois Tigeot  * power domain and all its parents are powered up. Therefore users should only
14732c9916cdSFrançois Tigeot  * grab a reference to the innermost power domain they need.
14742c9916cdSFrançois Tigeot  *
14752c9916cdSFrançois Tigeot  * Any power domain reference obtained by this function must have a symmetric
14762c9916cdSFrançois Tigeot  * call to intel_display_power_put() to release the reference again.
14772c9916cdSFrançois Tigeot  */
intel_display_power_get(struct drm_i915_private * dev_priv,enum intel_display_power_domain domain)14782c9916cdSFrançois Tigeot void intel_display_power_get(struct drm_i915_private *dev_priv,
14792c9916cdSFrançois Tigeot 			     enum intel_display_power_domain domain)
14802c9916cdSFrançois Tigeot {
1481aee94f86SFrançois Tigeot 	struct i915_power_domains *power_domains = &dev_priv->power_domains;
14822c9916cdSFrançois Tigeot 
14832c9916cdSFrançois Tigeot 	intel_runtime_pm_get(dev_priv);
14842c9916cdSFrançois Tigeot 
1485aee94f86SFrançois Tigeot 	mutex_lock(&power_domains->lock);
1486aee94f86SFrançois Tigeot 
1487aee94f86SFrançois Tigeot 	__intel_display_power_get_domain(dev_priv, domain);
1488aee94f86SFrançois Tigeot 
1489aee94f86SFrançois Tigeot 	mutex_unlock(&power_domains->lock);
1490aee94f86SFrançois Tigeot }
1491aee94f86SFrançois Tigeot 
1492aee94f86SFrançois Tigeot /**
1493aee94f86SFrançois Tigeot  * intel_display_power_get_if_enabled - grab a reference for an enabled display power domain
1494aee94f86SFrançois Tigeot  * @dev_priv: i915 device instance
1495aee94f86SFrançois Tigeot  * @domain: power domain to reference
1496aee94f86SFrançois Tigeot  *
1497aee94f86SFrançois Tigeot  * This function grabs a power domain reference for @domain and ensures that the
1498aee94f86SFrançois Tigeot  * power domain and all its parents are powered up. Therefore users should only
1499aee94f86SFrançois Tigeot  * grab a reference to the innermost power domain they need.
1500aee94f86SFrançois Tigeot  *
1501aee94f86SFrançois Tigeot  * Any power domain reference obtained by this function must have a symmetric
1502aee94f86SFrançois Tigeot  * call to intel_display_power_put() to release the reference again.
1503aee94f86SFrançois Tigeot  */
intel_display_power_get_if_enabled(struct drm_i915_private * dev_priv,enum intel_display_power_domain domain)1504aee94f86SFrançois Tigeot bool intel_display_power_get_if_enabled(struct drm_i915_private *dev_priv,
1505aee94f86SFrançois Tigeot 					enum intel_display_power_domain domain)
1506aee94f86SFrançois Tigeot {
1507aee94f86SFrançois Tigeot 	struct i915_power_domains *power_domains = &dev_priv->power_domains;
1508aee94f86SFrançois Tigeot 	bool is_enabled;
1509aee94f86SFrançois Tigeot 
1510aee94f86SFrançois Tigeot 	if (!intel_runtime_pm_get_if_in_use(dev_priv))
1511aee94f86SFrançois Tigeot 		return false;
15122c9916cdSFrançois Tigeot 
15132c9916cdSFrançois Tigeot 	mutex_lock(&power_domains->lock);
15142c9916cdSFrançois Tigeot 
1515aee94f86SFrançois Tigeot 	if (__intel_display_power_is_enabled(dev_priv, domain)) {
1516aee94f86SFrançois Tigeot 		__intel_display_power_get_domain(dev_priv, domain);
1517aee94f86SFrançois Tigeot 		is_enabled = true;
1518aee94f86SFrançois Tigeot 	} else {
1519aee94f86SFrançois Tigeot 		is_enabled = false;
15202c9916cdSFrançois Tigeot 	}
15212c9916cdSFrançois Tigeot 
15222c9916cdSFrançois Tigeot 	mutex_unlock(&power_domains->lock);
1523aee94f86SFrançois Tigeot 
1524aee94f86SFrançois Tigeot 	if (!is_enabled)
1525aee94f86SFrançois Tigeot 		intel_runtime_pm_put(dev_priv);
1526aee94f86SFrançois Tigeot 
1527aee94f86SFrançois Tigeot 	return is_enabled;
15282c9916cdSFrançois Tigeot }
15292c9916cdSFrançois Tigeot 
15302c9916cdSFrançois Tigeot /**
15312c9916cdSFrançois Tigeot  * intel_display_power_put - release a power domain reference
15322c9916cdSFrançois Tigeot  * @dev_priv: i915 device instance
15332c9916cdSFrançois Tigeot  * @domain: power domain to reference
15342c9916cdSFrançois Tigeot  *
15352c9916cdSFrançois Tigeot  * This function drops the power domain reference obtained by
15362c9916cdSFrançois Tigeot  * intel_display_power_get() and might power down the corresponding hardware
15372c9916cdSFrançois Tigeot  * block right away if this is the last reference.
15382c9916cdSFrançois Tigeot  */
intel_display_power_put(struct drm_i915_private * dev_priv,enum intel_display_power_domain domain)15392c9916cdSFrançois Tigeot void intel_display_power_put(struct drm_i915_private *dev_priv,
15402c9916cdSFrançois Tigeot 			     enum intel_display_power_domain domain)
15412c9916cdSFrançois Tigeot {
15422c9916cdSFrançois Tigeot 	struct i915_power_domains *power_domains;
15432c9916cdSFrançois Tigeot 	struct i915_power_well *power_well;
15442c9916cdSFrançois Tigeot 
15452c9916cdSFrançois Tigeot 	power_domains = &dev_priv->power_domains;
15462c9916cdSFrançois Tigeot 
15472c9916cdSFrançois Tigeot 	mutex_lock(&power_domains->lock);
15482c9916cdSFrançois Tigeot 
1549aee94f86SFrançois Tigeot 	WARN(!power_domains->domain_use_count[domain],
1550aee94f86SFrançois Tigeot 	     "Use count on domain %s is already zero\n",
1551aee94f86SFrançois Tigeot 	     intel_display_power_domain_str(domain));
15522c9916cdSFrançois Tigeot 	power_domains->domain_use_count[domain]--;
15532c9916cdSFrançois Tigeot 
1554a85cb24fSFrançois Tigeot 	for_each_power_domain_well_rev(dev_priv, power_well, BIT_ULL(domain))
15551487f786SFrançois Tigeot 		intel_power_well_put(dev_priv, power_well);
15562c9916cdSFrançois Tigeot 
15572c9916cdSFrançois Tigeot 	mutex_unlock(&power_domains->lock);
15582c9916cdSFrançois Tigeot 
15592c9916cdSFrançois Tigeot 	intel_runtime_pm_put(dev_priv);
15602c9916cdSFrançois Tigeot }
15612c9916cdSFrançois Tigeot 
1562*3f2dd94aSFrançois Tigeot #define I830_PIPES_POWER_DOMAINS (		\
1563*3f2dd94aSFrançois Tigeot 	BIT_ULL(POWER_DOMAIN_PIPE_A) |		\
1564a85cb24fSFrançois Tigeot 	BIT_ULL(POWER_DOMAIN_PIPE_B) |		\
1565a85cb24fSFrançois Tigeot 	BIT_ULL(POWER_DOMAIN_PIPE_A_PANEL_FITTER) |	\
1566a85cb24fSFrançois Tigeot 	BIT_ULL(POWER_DOMAIN_PIPE_B_PANEL_FITTER) |	\
1567a85cb24fSFrançois Tigeot 	BIT_ULL(POWER_DOMAIN_TRANSCODER_A) |	\
1568a85cb24fSFrançois Tigeot 	BIT_ULL(POWER_DOMAIN_TRANSCODER_B) |	\
1569a85cb24fSFrançois Tigeot 	BIT_ULL(POWER_DOMAIN_INIT))
15708621f407SFrançois Tigeot 
15718621f407SFrançois Tigeot #define VLV_DISPLAY_POWER_DOMAINS (		\
1572a85cb24fSFrançois Tigeot 	BIT_ULL(POWER_DOMAIN_PIPE_A) |		\
1573a85cb24fSFrançois Tigeot 	BIT_ULL(POWER_DOMAIN_PIPE_B) |		\
1574a85cb24fSFrançois Tigeot 	BIT_ULL(POWER_DOMAIN_PIPE_A_PANEL_FITTER) |	\
1575a85cb24fSFrançois Tigeot 	BIT_ULL(POWER_DOMAIN_PIPE_B_PANEL_FITTER) |	\
1576a85cb24fSFrançois Tigeot 	BIT_ULL(POWER_DOMAIN_TRANSCODER_A) |	\
1577a85cb24fSFrançois Tigeot 	BIT_ULL(POWER_DOMAIN_TRANSCODER_B) |	\
1578a85cb24fSFrançois Tigeot 	BIT_ULL(POWER_DOMAIN_PORT_DDI_B_LANES) |	\
1579a85cb24fSFrançois Tigeot 	BIT_ULL(POWER_DOMAIN_PORT_DDI_C_LANES) |	\
1580a85cb24fSFrançois Tigeot 	BIT_ULL(POWER_DOMAIN_PORT_DSI) |		\
1581a85cb24fSFrançois Tigeot 	BIT_ULL(POWER_DOMAIN_PORT_CRT) |		\
1582a85cb24fSFrançois Tigeot 	BIT_ULL(POWER_DOMAIN_VGA) |			\
1583a85cb24fSFrançois Tigeot 	BIT_ULL(POWER_DOMAIN_AUDIO) |		\
1584a85cb24fSFrançois Tigeot 	BIT_ULL(POWER_DOMAIN_AUX_B) |		\
1585a85cb24fSFrançois Tigeot 	BIT_ULL(POWER_DOMAIN_AUX_C) |		\
1586a85cb24fSFrançois Tigeot 	BIT_ULL(POWER_DOMAIN_GMBUS) |		\
1587a85cb24fSFrançois Tigeot 	BIT_ULL(POWER_DOMAIN_INIT))
15882c9916cdSFrançois Tigeot 
15892c9916cdSFrançois Tigeot #define VLV_DPIO_CMN_BC_POWER_DOMAINS (		\
1590a85cb24fSFrançois Tigeot 	BIT_ULL(POWER_DOMAIN_PORT_DDI_B_LANES) |	\
1591a85cb24fSFrançois Tigeot 	BIT_ULL(POWER_DOMAIN_PORT_DDI_C_LANES) |	\
1592a85cb24fSFrançois Tigeot 	BIT_ULL(POWER_DOMAIN_PORT_CRT) |		\
1593a85cb24fSFrançois Tigeot 	BIT_ULL(POWER_DOMAIN_AUX_B) |		\
1594a85cb24fSFrançois Tigeot 	BIT_ULL(POWER_DOMAIN_AUX_C) |		\
1595a85cb24fSFrançois Tigeot 	BIT_ULL(POWER_DOMAIN_INIT))
15962c9916cdSFrançois Tigeot 
15972c9916cdSFrançois Tigeot #define VLV_DPIO_TX_B_LANES_01_POWER_DOMAINS (	\
1598a85cb24fSFrançois Tigeot 	BIT_ULL(POWER_DOMAIN_PORT_DDI_B_LANES) |	\
1599a85cb24fSFrançois Tigeot 	BIT_ULL(POWER_DOMAIN_AUX_B) |		\
1600a85cb24fSFrançois Tigeot 	BIT_ULL(POWER_DOMAIN_INIT))
16012c9916cdSFrançois Tigeot 
16022c9916cdSFrançois Tigeot #define VLV_DPIO_TX_B_LANES_23_POWER_DOMAINS (	\
1603a85cb24fSFrançois Tigeot 	BIT_ULL(POWER_DOMAIN_PORT_DDI_B_LANES) |	\
1604a85cb24fSFrançois Tigeot 	BIT_ULL(POWER_DOMAIN_AUX_B) |		\
1605a85cb24fSFrançois Tigeot 	BIT_ULL(POWER_DOMAIN_INIT))
16062c9916cdSFrançois Tigeot 
16072c9916cdSFrançois Tigeot #define VLV_DPIO_TX_C_LANES_01_POWER_DOMAINS (	\
1608a85cb24fSFrançois Tigeot 	BIT_ULL(POWER_DOMAIN_PORT_DDI_C_LANES) |	\
1609a85cb24fSFrançois Tigeot 	BIT_ULL(POWER_DOMAIN_AUX_C) |		\
1610a85cb24fSFrançois Tigeot 	BIT_ULL(POWER_DOMAIN_INIT))
16112c9916cdSFrançois Tigeot 
16122c9916cdSFrançois Tigeot #define VLV_DPIO_TX_C_LANES_23_POWER_DOMAINS (	\
1613a85cb24fSFrançois Tigeot 	BIT_ULL(POWER_DOMAIN_PORT_DDI_C_LANES) |	\
1614a85cb24fSFrançois Tigeot 	BIT_ULL(POWER_DOMAIN_AUX_C) |		\
1615a85cb24fSFrançois Tigeot 	BIT_ULL(POWER_DOMAIN_INIT))
16162c9916cdSFrançois Tigeot 
16178621f407SFrançois Tigeot #define CHV_DISPLAY_POWER_DOMAINS (		\
1618a85cb24fSFrançois Tigeot 	BIT_ULL(POWER_DOMAIN_PIPE_A) |		\
1619a85cb24fSFrançois Tigeot 	BIT_ULL(POWER_DOMAIN_PIPE_B) |		\
1620a85cb24fSFrançois Tigeot 	BIT_ULL(POWER_DOMAIN_PIPE_C) |		\
1621a85cb24fSFrançois Tigeot 	BIT_ULL(POWER_DOMAIN_PIPE_A_PANEL_FITTER) |	\
1622a85cb24fSFrançois Tigeot 	BIT_ULL(POWER_DOMAIN_PIPE_B_PANEL_FITTER) |	\
1623a85cb24fSFrançois Tigeot 	BIT_ULL(POWER_DOMAIN_PIPE_C_PANEL_FITTER) |	\
1624a85cb24fSFrançois Tigeot 	BIT_ULL(POWER_DOMAIN_TRANSCODER_A) |	\
1625a85cb24fSFrançois Tigeot 	BIT_ULL(POWER_DOMAIN_TRANSCODER_B) |	\
1626a85cb24fSFrançois Tigeot 	BIT_ULL(POWER_DOMAIN_TRANSCODER_C) |	\
1627a85cb24fSFrançois Tigeot 	BIT_ULL(POWER_DOMAIN_PORT_DDI_B_LANES) |	\
1628a85cb24fSFrançois Tigeot 	BIT_ULL(POWER_DOMAIN_PORT_DDI_C_LANES) |	\
1629a85cb24fSFrançois Tigeot 	BIT_ULL(POWER_DOMAIN_PORT_DDI_D_LANES) |	\
1630a85cb24fSFrançois Tigeot 	BIT_ULL(POWER_DOMAIN_PORT_DSI) |		\
1631a85cb24fSFrançois Tigeot 	BIT_ULL(POWER_DOMAIN_VGA) |			\
1632a85cb24fSFrançois Tigeot 	BIT_ULL(POWER_DOMAIN_AUDIO) |		\
1633a85cb24fSFrançois Tigeot 	BIT_ULL(POWER_DOMAIN_AUX_B) |		\
1634a85cb24fSFrançois Tigeot 	BIT_ULL(POWER_DOMAIN_AUX_C) |		\
1635a85cb24fSFrançois Tigeot 	BIT_ULL(POWER_DOMAIN_AUX_D) |		\
1636a85cb24fSFrançois Tigeot 	BIT_ULL(POWER_DOMAIN_GMBUS) |		\
1637a85cb24fSFrançois Tigeot 	BIT_ULL(POWER_DOMAIN_INIT))
16388621f407SFrançois Tigeot 
16392c9916cdSFrançois Tigeot #define CHV_DPIO_CMN_BC_POWER_DOMAINS (		\
1640a85cb24fSFrançois Tigeot 	BIT_ULL(POWER_DOMAIN_PORT_DDI_B_LANES) |	\
1641a85cb24fSFrançois Tigeot 	BIT_ULL(POWER_DOMAIN_PORT_DDI_C_LANES) |	\
1642a85cb24fSFrançois Tigeot 	BIT_ULL(POWER_DOMAIN_AUX_B) |		\
1643a85cb24fSFrançois Tigeot 	BIT_ULL(POWER_DOMAIN_AUX_C) |		\
1644a85cb24fSFrançois Tigeot 	BIT_ULL(POWER_DOMAIN_INIT))
16452c9916cdSFrançois Tigeot 
16462c9916cdSFrançois Tigeot #define CHV_DPIO_CMN_D_POWER_DOMAINS (		\
1647a85cb24fSFrançois Tigeot 	BIT_ULL(POWER_DOMAIN_PORT_DDI_D_LANES) |	\
1648a85cb24fSFrançois Tigeot 	BIT_ULL(POWER_DOMAIN_AUX_D) |		\
1649a85cb24fSFrançois Tigeot 	BIT_ULL(POWER_DOMAIN_INIT))
16502c9916cdSFrançois Tigeot 
1651*3f2dd94aSFrançois Tigeot #define HSW_DISPLAY_POWER_DOMAINS (			\
1652*3f2dd94aSFrançois Tigeot 	BIT_ULL(POWER_DOMAIN_PIPE_B) |			\
1653*3f2dd94aSFrançois Tigeot 	BIT_ULL(POWER_DOMAIN_PIPE_C) |			\
1654*3f2dd94aSFrançois Tigeot 	BIT_ULL(POWER_DOMAIN_PIPE_A_PANEL_FITTER) |		\
1655*3f2dd94aSFrançois Tigeot 	BIT_ULL(POWER_DOMAIN_PIPE_B_PANEL_FITTER) |		\
1656*3f2dd94aSFrançois Tigeot 	BIT_ULL(POWER_DOMAIN_PIPE_C_PANEL_FITTER) |		\
1657*3f2dd94aSFrançois Tigeot 	BIT_ULL(POWER_DOMAIN_TRANSCODER_A) |		\
1658*3f2dd94aSFrançois Tigeot 	BIT_ULL(POWER_DOMAIN_TRANSCODER_B) |		\
1659*3f2dd94aSFrançois Tigeot 	BIT_ULL(POWER_DOMAIN_TRANSCODER_C) |		\
1660*3f2dd94aSFrançois Tigeot 	BIT_ULL(POWER_DOMAIN_PORT_DDI_B_LANES) |		\
1661*3f2dd94aSFrançois Tigeot 	BIT_ULL(POWER_DOMAIN_PORT_DDI_C_LANES) |		\
1662*3f2dd94aSFrançois Tigeot 	BIT_ULL(POWER_DOMAIN_PORT_DDI_D_LANES) |		\
1663*3f2dd94aSFrançois Tigeot 	BIT_ULL(POWER_DOMAIN_PORT_CRT) | /* DDI E */	\
1664*3f2dd94aSFrançois Tigeot 	BIT_ULL(POWER_DOMAIN_VGA) |				\
1665*3f2dd94aSFrançois Tigeot 	BIT_ULL(POWER_DOMAIN_AUDIO) |			\
1666*3f2dd94aSFrançois Tigeot 	BIT_ULL(POWER_DOMAIN_INIT))
1667*3f2dd94aSFrançois Tigeot 
1668*3f2dd94aSFrançois Tigeot #define BDW_DISPLAY_POWER_DOMAINS (			\
1669*3f2dd94aSFrançois Tigeot 	BIT_ULL(POWER_DOMAIN_PIPE_B) |			\
1670*3f2dd94aSFrançois Tigeot 	BIT_ULL(POWER_DOMAIN_PIPE_C) |			\
1671*3f2dd94aSFrançois Tigeot 	BIT_ULL(POWER_DOMAIN_PIPE_B_PANEL_FITTER) |		\
1672*3f2dd94aSFrançois Tigeot 	BIT_ULL(POWER_DOMAIN_PIPE_C_PANEL_FITTER) |		\
1673*3f2dd94aSFrançois Tigeot 	BIT_ULL(POWER_DOMAIN_TRANSCODER_A) |		\
1674*3f2dd94aSFrançois Tigeot 	BIT_ULL(POWER_DOMAIN_TRANSCODER_B) |		\
1675*3f2dd94aSFrançois Tigeot 	BIT_ULL(POWER_DOMAIN_TRANSCODER_C) |		\
1676*3f2dd94aSFrançois Tigeot 	BIT_ULL(POWER_DOMAIN_PORT_DDI_B_LANES) |		\
1677*3f2dd94aSFrançois Tigeot 	BIT_ULL(POWER_DOMAIN_PORT_DDI_C_LANES) |		\
1678*3f2dd94aSFrançois Tigeot 	BIT_ULL(POWER_DOMAIN_PORT_DDI_D_LANES) |		\
1679*3f2dd94aSFrançois Tigeot 	BIT_ULL(POWER_DOMAIN_PORT_CRT) | /* DDI E */	\
1680*3f2dd94aSFrançois Tigeot 	BIT_ULL(POWER_DOMAIN_VGA) |				\
1681*3f2dd94aSFrançois Tigeot 	BIT_ULL(POWER_DOMAIN_AUDIO) |			\
1682*3f2dd94aSFrançois Tigeot 	BIT_ULL(POWER_DOMAIN_INIT))
1683*3f2dd94aSFrançois Tigeot 
1684*3f2dd94aSFrançois Tigeot #define SKL_DISPLAY_POWERWELL_2_POWER_DOMAINS (		\
1685*3f2dd94aSFrançois Tigeot 	BIT_ULL(POWER_DOMAIN_TRANSCODER_A) |		\
1686*3f2dd94aSFrançois Tigeot 	BIT_ULL(POWER_DOMAIN_PIPE_B) |			\
1687*3f2dd94aSFrançois Tigeot 	BIT_ULL(POWER_DOMAIN_TRANSCODER_B) |		\
1688*3f2dd94aSFrançois Tigeot 	BIT_ULL(POWER_DOMAIN_PIPE_C) |			\
1689*3f2dd94aSFrançois Tigeot 	BIT_ULL(POWER_DOMAIN_TRANSCODER_C) |		\
1690*3f2dd94aSFrançois Tigeot 	BIT_ULL(POWER_DOMAIN_PIPE_B_PANEL_FITTER) |		\
1691*3f2dd94aSFrançois Tigeot 	BIT_ULL(POWER_DOMAIN_PIPE_C_PANEL_FITTER) |		\
1692*3f2dd94aSFrançois Tigeot 	BIT_ULL(POWER_DOMAIN_PORT_DDI_B_LANES) |		\
1693*3f2dd94aSFrançois Tigeot 	BIT_ULL(POWER_DOMAIN_PORT_DDI_C_LANES) |		\
1694*3f2dd94aSFrançois Tigeot 	BIT_ULL(POWER_DOMAIN_PORT_DDI_D_LANES) |		\
1695*3f2dd94aSFrançois Tigeot 	BIT_ULL(POWER_DOMAIN_PORT_DDI_E_LANES) |		\
1696*3f2dd94aSFrançois Tigeot 	BIT_ULL(POWER_DOMAIN_AUX_B) |                       \
1697*3f2dd94aSFrançois Tigeot 	BIT_ULL(POWER_DOMAIN_AUX_C) |			\
1698*3f2dd94aSFrançois Tigeot 	BIT_ULL(POWER_DOMAIN_AUX_D) |			\
1699*3f2dd94aSFrançois Tigeot 	BIT_ULL(POWER_DOMAIN_AUDIO) |			\
1700*3f2dd94aSFrançois Tigeot 	BIT_ULL(POWER_DOMAIN_VGA) |				\
1701*3f2dd94aSFrançois Tigeot 	BIT_ULL(POWER_DOMAIN_INIT))
1702*3f2dd94aSFrançois Tigeot #define SKL_DISPLAY_DDI_IO_A_E_POWER_DOMAINS (		\
1703*3f2dd94aSFrançois Tigeot 	BIT_ULL(POWER_DOMAIN_PORT_DDI_A_IO) |		\
1704*3f2dd94aSFrançois Tigeot 	BIT_ULL(POWER_DOMAIN_PORT_DDI_E_IO) |		\
1705*3f2dd94aSFrançois Tigeot 	BIT_ULL(POWER_DOMAIN_INIT))
1706*3f2dd94aSFrançois Tigeot #define SKL_DISPLAY_DDI_IO_B_POWER_DOMAINS (		\
1707*3f2dd94aSFrançois Tigeot 	BIT_ULL(POWER_DOMAIN_PORT_DDI_B_IO) |		\
1708*3f2dd94aSFrançois Tigeot 	BIT_ULL(POWER_DOMAIN_INIT))
1709*3f2dd94aSFrançois Tigeot #define SKL_DISPLAY_DDI_IO_C_POWER_DOMAINS (		\
1710*3f2dd94aSFrançois Tigeot 	BIT_ULL(POWER_DOMAIN_PORT_DDI_C_IO) |		\
1711*3f2dd94aSFrançois Tigeot 	BIT_ULL(POWER_DOMAIN_INIT))
1712*3f2dd94aSFrançois Tigeot #define SKL_DISPLAY_DDI_IO_D_POWER_DOMAINS (		\
1713*3f2dd94aSFrançois Tigeot 	BIT_ULL(POWER_DOMAIN_PORT_DDI_D_IO) |		\
1714*3f2dd94aSFrançois Tigeot 	BIT_ULL(POWER_DOMAIN_INIT))
1715*3f2dd94aSFrançois Tigeot #define SKL_DISPLAY_DC_OFF_POWER_DOMAINS (		\
1716*3f2dd94aSFrançois Tigeot 	SKL_DISPLAY_POWERWELL_2_POWER_DOMAINS |		\
1717*3f2dd94aSFrançois Tigeot 	BIT_ULL(POWER_DOMAIN_MODESET) |			\
1718*3f2dd94aSFrançois Tigeot 	BIT_ULL(POWER_DOMAIN_AUX_A) |			\
1719*3f2dd94aSFrançois Tigeot 	BIT_ULL(POWER_DOMAIN_INIT))
1720*3f2dd94aSFrançois Tigeot 
1721*3f2dd94aSFrançois Tigeot #define BXT_DISPLAY_POWERWELL_2_POWER_DOMAINS (		\
1722*3f2dd94aSFrançois Tigeot 	BIT_ULL(POWER_DOMAIN_TRANSCODER_A) |		\
1723*3f2dd94aSFrançois Tigeot 	BIT_ULL(POWER_DOMAIN_PIPE_B) |			\
1724*3f2dd94aSFrançois Tigeot 	BIT_ULL(POWER_DOMAIN_TRANSCODER_B) |		\
1725*3f2dd94aSFrançois Tigeot 	BIT_ULL(POWER_DOMAIN_PIPE_C) |			\
1726*3f2dd94aSFrançois Tigeot 	BIT_ULL(POWER_DOMAIN_TRANSCODER_C) |		\
1727*3f2dd94aSFrançois Tigeot 	BIT_ULL(POWER_DOMAIN_PIPE_B_PANEL_FITTER) |		\
1728*3f2dd94aSFrançois Tigeot 	BIT_ULL(POWER_DOMAIN_PIPE_C_PANEL_FITTER) |		\
1729*3f2dd94aSFrançois Tigeot 	BIT_ULL(POWER_DOMAIN_PORT_DDI_B_LANES) |		\
1730*3f2dd94aSFrançois Tigeot 	BIT_ULL(POWER_DOMAIN_PORT_DDI_C_LANES) |		\
1731*3f2dd94aSFrançois Tigeot 	BIT_ULL(POWER_DOMAIN_AUX_B) |			\
1732*3f2dd94aSFrançois Tigeot 	BIT_ULL(POWER_DOMAIN_AUX_C) |			\
1733*3f2dd94aSFrançois Tigeot 	BIT_ULL(POWER_DOMAIN_AUDIO) |			\
1734*3f2dd94aSFrançois Tigeot 	BIT_ULL(POWER_DOMAIN_VGA) |				\
1735*3f2dd94aSFrançois Tigeot 	BIT_ULL(POWER_DOMAIN_GMBUS) |			\
1736*3f2dd94aSFrançois Tigeot 	BIT_ULL(POWER_DOMAIN_INIT))
1737*3f2dd94aSFrançois Tigeot #define BXT_DISPLAY_DC_OFF_POWER_DOMAINS (		\
1738*3f2dd94aSFrançois Tigeot 	BXT_DISPLAY_POWERWELL_2_POWER_DOMAINS |		\
1739*3f2dd94aSFrançois Tigeot 	BIT_ULL(POWER_DOMAIN_MODESET) |			\
1740*3f2dd94aSFrançois Tigeot 	BIT_ULL(POWER_DOMAIN_AUX_A) |			\
1741*3f2dd94aSFrançois Tigeot 	BIT_ULL(POWER_DOMAIN_INIT))
1742*3f2dd94aSFrançois Tigeot #define BXT_DPIO_CMN_A_POWER_DOMAINS (			\
1743*3f2dd94aSFrançois Tigeot 	BIT_ULL(POWER_DOMAIN_PORT_DDI_A_LANES) |		\
1744*3f2dd94aSFrançois Tigeot 	BIT_ULL(POWER_DOMAIN_AUX_A) |			\
1745*3f2dd94aSFrançois Tigeot 	BIT_ULL(POWER_DOMAIN_INIT))
1746*3f2dd94aSFrançois Tigeot #define BXT_DPIO_CMN_BC_POWER_DOMAINS (			\
1747*3f2dd94aSFrançois Tigeot 	BIT_ULL(POWER_DOMAIN_PORT_DDI_B_LANES) |		\
1748*3f2dd94aSFrançois Tigeot 	BIT_ULL(POWER_DOMAIN_PORT_DDI_C_LANES) |		\
1749*3f2dd94aSFrançois Tigeot 	BIT_ULL(POWER_DOMAIN_AUX_B) |			\
1750*3f2dd94aSFrançois Tigeot 	BIT_ULL(POWER_DOMAIN_AUX_C) |			\
1751*3f2dd94aSFrançois Tigeot 	BIT_ULL(POWER_DOMAIN_INIT))
1752*3f2dd94aSFrançois Tigeot 
1753*3f2dd94aSFrançois Tigeot #define GLK_DISPLAY_POWERWELL_2_POWER_DOMAINS (		\
1754*3f2dd94aSFrançois Tigeot 	BIT_ULL(POWER_DOMAIN_TRANSCODER_A) |		\
1755*3f2dd94aSFrançois Tigeot 	BIT_ULL(POWER_DOMAIN_PIPE_B) |			\
1756*3f2dd94aSFrançois Tigeot 	BIT_ULL(POWER_DOMAIN_TRANSCODER_B) |		\
1757*3f2dd94aSFrançois Tigeot 	BIT_ULL(POWER_DOMAIN_PIPE_C) |			\
1758*3f2dd94aSFrançois Tigeot 	BIT_ULL(POWER_DOMAIN_TRANSCODER_C) |		\
1759*3f2dd94aSFrançois Tigeot 	BIT_ULL(POWER_DOMAIN_PIPE_B_PANEL_FITTER) |		\
1760*3f2dd94aSFrançois Tigeot 	BIT_ULL(POWER_DOMAIN_PIPE_C_PANEL_FITTER) |		\
1761*3f2dd94aSFrançois Tigeot 	BIT_ULL(POWER_DOMAIN_PORT_DDI_B_LANES) |		\
1762*3f2dd94aSFrançois Tigeot 	BIT_ULL(POWER_DOMAIN_PORT_DDI_C_LANES) |		\
1763*3f2dd94aSFrançois Tigeot 	BIT_ULL(POWER_DOMAIN_AUX_B) |                       \
1764*3f2dd94aSFrançois Tigeot 	BIT_ULL(POWER_DOMAIN_AUX_C) |			\
1765*3f2dd94aSFrançois Tigeot 	BIT_ULL(POWER_DOMAIN_AUDIO) |			\
1766*3f2dd94aSFrançois Tigeot 	BIT_ULL(POWER_DOMAIN_VGA) |				\
1767*3f2dd94aSFrançois Tigeot 	BIT_ULL(POWER_DOMAIN_INIT))
1768*3f2dd94aSFrançois Tigeot #define GLK_DISPLAY_DDI_IO_A_POWER_DOMAINS (		\
1769*3f2dd94aSFrançois Tigeot 	BIT_ULL(POWER_DOMAIN_PORT_DDI_A_IO))
1770*3f2dd94aSFrançois Tigeot #define GLK_DISPLAY_DDI_IO_B_POWER_DOMAINS (		\
1771*3f2dd94aSFrançois Tigeot 	BIT_ULL(POWER_DOMAIN_PORT_DDI_B_IO))
1772*3f2dd94aSFrançois Tigeot #define GLK_DISPLAY_DDI_IO_C_POWER_DOMAINS (		\
1773*3f2dd94aSFrançois Tigeot 	BIT_ULL(POWER_DOMAIN_PORT_DDI_C_IO))
1774*3f2dd94aSFrançois Tigeot #define GLK_DPIO_CMN_A_POWER_DOMAINS (			\
1775*3f2dd94aSFrançois Tigeot 	BIT_ULL(POWER_DOMAIN_PORT_DDI_A_LANES) |		\
1776*3f2dd94aSFrançois Tigeot 	BIT_ULL(POWER_DOMAIN_AUX_A) |			\
1777*3f2dd94aSFrançois Tigeot 	BIT_ULL(POWER_DOMAIN_INIT))
1778*3f2dd94aSFrançois Tigeot #define GLK_DPIO_CMN_B_POWER_DOMAINS (			\
1779*3f2dd94aSFrançois Tigeot 	BIT_ULL(POWER_DOMAIN_PORT_DDI_B_LANES) |		\
1780*3f2dd94aSFrançois Tigeot 	BIT_ULL(POWER_DOMAIN_AUX_B) |			\
1781*3f2dd94aSFrançois Tigeot 	BIT_ULL(POWER_DOMAIN_INIT))
1782*3f2dd94aSFrançois Tigeot #define GLK_DPIO_CMN_C_POWER_DOMAINS (			\
1783*3f2dd94aSFrançois Tigeot 	BIT_ULL(POWER_DOMAIN_PORT_DDI_C_LANES) |		\
1784*3f2dd94aSFrançois Tigeot 	BIT_ULL(POWER_DOMAIN_AUX_C) |			\
1785*3f2dd94aSFrançois Tigeot 	BIT_ULL(POWER_DOMAIN_INIT))
1786*3f2dd94aSFrançois Tigeot #define GLK_DISPLAY_AUX_A_POWER_DOMAINS (		\
1787*3f2dd94aSFrançois Tigeot 	BIT_ULL(POWER_DOMAIN_AUX_A) |		\
1788*3f2dd94aSFrançois Tigeot 	BIT_ULL(POWER_DOMAIN_INIT))
1789*3f2dd94aSFrançois Tigeot #define GLK_DISPLAY_AUX_B_POWER_DOMAINS (		\
1790*3f2dd94aSFrançois Tigeot 	BIT_ULL(POWER_DOMAIN_AUX_B) |		\
1791*3f2dd94aSFrançois Tigeot 	BIT_ULL(POWER_DOMAIN_INIT))
1792*3f2dd94aSFrançois Tigeot #define GLK_DISPLAY_AUX_C_POWER_DOMAINS (		\
1793*3f2dd94aSFrançois Tigeot 	BIT_ULL(POWER_DOMAIN_AUX_C) |		\
1794*3f2dd94aSFrançois Tigeot 	BIT_ULL(POWER_DOMAIN_INIT))
1795*3f2dd94aSFrançois Tigeot #define GLK_DISPLAY_DC_OFF_POWER_DOMAINS (		\
1796*3f2dd94aSFrançois Tigeot 	GLK_DISPLAY_POWERWELL_2_POWER_DOMAINS |		\
1797*3f2dd94aSFrançois Tigeot 	BIT_ULL(POWER_DOMAIN_MODESET) |			\
1798*3f2dd94aSFrançois Tigeot 	BIT_ULL(POWER_DOMAIN_AUX_A) |			\
1799*3f2dd94aSFrançois Tigeot 	BIT_ULL(POWER_DOMAIN_GMBUS) |			\
1800*3f2dd94aSFrançois Tigeot 	BIT_ULL(POWER_DOMAIN_INIT))
1801*3f2dd94aSFrançois Tigeot 
1802*3f2dd94aSFrançois Tigeot #define CNL_DISPLAY_POWERWELL_2_POWER_DOMAINS (		\
1803*3f2dd94aSFrançois Tigeot 	BIT_ULL(POWER_DOMAIN_TRANSCODER_A) |		\
1804*3f2dd94aSFrançois Tigeot 	BIT_ULL(POWER_DOMAIN_PIPE_B) |			\
1805*3f2dd94aSFrançois Tigeot 	BIT_ULL(POWER_DOMAIN_TRANSCODER_B) |		\
1806*3f2dd94aSFrançois Tigeot 	BIT_ULL(POWER_DOMAIN_PIPE_C) |			\
1807*3f2dd94aSFrançois Tigeot 	BIT_ULL(POWER_DOMAIN_TRANSCODER_C) |		\
1808*3f2dd94aSFrançois Tigeot 	BIT_ULL(POWER_DOMAIN_PIPE_B_PANEL_FITTER) |		\
1809*3f2dd94aSFrançois Tigeot 	BIT_ULL(POWER_DOMAIN_PIPE_C_PANEL_FITTER) |		\
1810*3f2dd94aSFrançois Tigeot 	BIT_ULL(POWER_DOMAIN_PORT_DDI_B_LANES) |		\
1811*3f2dd94aSFrançois Tigeot 	BIT_ULL(POWER_DOMAIN_PORT_DDI_C_LANES) |		\
1812*3f2dd94aSFrançois Tigeot 	BIT_ULL(POWER_DOMAIN_PORT_DDI_D_LANES) |		\
1813*3f2dd94aSFrançois Tigeot 	BIT_ULL(POWER_DOMAIN_AUX_B) |                       \
1814*3f2dd94aSFrançois Tigeot 	BIT_ULL(POWER_DOMAIN_AUX_C) |			\
1815*3f2dd94aSFrançois Tigeot 	BIT_ULL(POWER_DOMAIN_AUX_D) |			\
1816*3f2dd94aSFrançois Tigeot 	BIT_ULL(POWER_DOMAIN_AUDIO) |			\
1817*3f2dd94aSFrançois Tigeot 	BIT_ULL(POWER_DOMAIN_VGA) |				\
1818*3f2dd94aSFrançois Tigeot 	BIT_ULL(POWER_DOMAIN_INIT))
1819*3f2dd94aSFrançois Tigeot #define CNL_DISPLAY_DDI_A_IO_POWER_DOMAINS (		\
1820*3f2dd94aSFrançois Tigeot 	BIT_ULL(POWER_DOMAIN_PORT_DDI_A_IO) |		\
1821*3f2dd94aSFrançois Tigeot 	BIT_ULL(POWER_DOMAIN_INIT))
1822*3f2dd94aSFrançois Tigeot #define CNL_DISPLAY_DDI_B_IO_POWER_DOMAINS (		\
1823*3f2dd94aSFrançois Tigeot 	BIT_ULL(POWER_DOMAIN_PORT_DDI_B_IO) |		\
1824*3f2dd94aSFrançois Tigeot 	BIT_ULL(POWER_DOMAIN_INIT))
1825*3f2dd94aSFrançois Tigeot #define CNL_DISPLAY_DDI_C_IO_POWER_DOMAINS (		\
1826*3f2dd94aSFrançois Tigeot 	BIT_ULL(POWER_DOMAIN_PORT_DDI_C_IO) |		\
1827*3f2dd94aSFrançois Tigeot 	BIT_ULL(POWER_DOMAIN_INIT))
1828*3f2dd94aSFrançois Tigeot #define CNL_DISPLAY_DDI_D_IO_POWER_DOMAINS (		\
1829*3f2dd94aSFrançois Tigeot 	BIT_ULL(POWER_DOMAIN_PORT_DDI_D_IO) |		\
1830*3f2dd94aSFrançois Tigeot 	BIT_ULL(POWER_DOMAIN_INIT))
1831*3f2dd94aSFrançois Tigeot #define CNL_DISPLAY_AUX_A_POWER_DOMAINS (		\
1832*3f2dd94aSFrançois Tigeot 	BIT_ULL(POWER_DOMAIN_AUX_A) |			\
1833*3f2dd94aSFrançois Tigeot 	BIT_ULL(POWER_DOMAIN_INIT))
1834*3f2dd94aSFrançois Tigeot #define CNL_DISPLAY_AUX_B_POWER_DOMAINS (		\
1835*3f2dd94aSFrançois Tigeot 	BIT_ULL(POWER_DOMAIN_AUX_B) |			\
1836*3f2dd94aSFrançois Tigeot 	BIT_ULL(POWER_DOMAIN_INIT))
1837*3f2dd94aSFrançois Tigeot #define CNL_DISPLAY_AUX_C_POWER_DOMAINS (		\
1838*3f2dd94aSFrançois Tigeot 	BIT_ULL(POWER_DOMAIN_AUX_C) |			\
1839*3f2dd94aSFrançois Tigeot 	BIT_ULL(POWER_DOMAIN_INIT))
1840*3f2dd94aSFrançois Tigeot #define CNL_DISPLAY_AUX_D_POWER_DOMAINS (		\
1841*3f2dd94aSFrançois Tigeot 	BIT_ULL(POWER_DOMAIN_AUX_D) |			\
1842*3f2dd94aSFrançois Tigeot 	BIT_ULL(POWER_DOMAIN_INIT))
1843*3f2dd94aSFrançois Tigeot #define CNL_DISPLAY_DC_OFF_POWER_DOMAINS (		\
1844*3f2dd94aSFrançois Tigeot 	CNL_DISPLAY_POWERWELL_2_POWER_DOMAINS |		\
1845*3f2dd94aSFrançois Tigeot 	BIT_ULL(POWER_DOMAIN_MODESET) |			\
1846*3f2dd94aSFrançois Tigeot 	BIT_ULL(POWER_DOMAIN_AUX_A) |			\
1847*3f2dd94aSFrançois Tigeot 	BIT_ULL(POWER_DOMAIN_GMBUS) |			\
1848*3f2dd94aSFrançois Tigeot 	BIT_ULL(POWER_DOMAIN_INIT))
1849*3f2dd94aSFrançois Tigeot 
18502c9916cdSFrançois Tigeot static const struct i915_power_well_ops i9xx_always_on_power_well_ops = {
1851a85cb24fSFrançois Tigeot 	.sync_hw = i9xx_power_well_sync_hw_noop,
18522c9916cdSFrançois Tigeot 	.enable = i9xx_always_on_power_well_noop,
18532c9916cdSFrançois Tigeot 	.disable = i9xx_always_on_power_well_noop,
18542c9916cdSFrançois Tigeot 	.is_enabled = i9xx_always_on_power_well_enabled,
18552c9916cdSFrançois Tigeot };
18562c9916cdSFrançois Tigeot 
18572c9916cdSFrançois Tigeot static const struct i915_power_well_ops chv_pipe_power_well_ops = {
1858a85cb24fSFrançois Tigeot 	.sync_hw = i9xx_power_well_sync_hw_noop,
18592c9916cdSFrançois Tigeot 	.enable = chv_pipe_power_well_enable,
18602c9916cdSFrançois Tigeot 	.disable = chv_pipe_power_well_disable,
18612c9916cdSFrançois Tigeot 	.is_enabled = chv_pipe_power_well_enabled,
18622c9916cdSFrançois Tigeot };
18632c9916cdSFrançois Tigeot 
18642c9916cdSFrançois Tigeot static const struct i915_power_well_ops chv_dpio_cmn_power_well_ops = {
1865a85cb24fSFrançois Tigeot 	.sync_hw = i9xx_power_well_sync_hw_noop,
18662c9916cdSFrançois Tigeot 	.enable = chv_dpio_cmn_power_well_enable,
18672c9916cdSFrançois Tigeot 	.disable = chv_dpio_cmn_power_well_disable,
18682c9916cdSFrançois Tigeot 	.is_enabled = vlv_power_well_enabled,
18692c9916cdSFrançois Tigeot };
18702c9916cdSFrançois Tigeot 
18712c9916cdSFrançois Tigeot static struct i915_power_well i9xx_always_on_power_well[] = {
18722c9916cdSFrançois Tigeot 	{
18732c9916cdSFrançois Tigeot 		.name = "always-on",
18742c9916cdSFrançois Tigeot 		.always_on = 1,
18752c9916cdSFrançois Tigeot 		.domains = POWER_DOMAIN_MASK,
18762c9916cdSFrançois Tigeot 		.ops = &i9xx_always_on_power_well_ops,
1877*3f2dd94aSFrançois Tigeot 		.id = I915_DISP_PW_ALWAYS_ON,
1878*3f2dd94aSFrançois Tigeot 	},
1879*3f2dd94aSFrançois Tigeot };
1880*3f2dd94aSFrançois Tigeot 
1881*3f2dd94aSFrançois Tigeot static const struct i915_power_well_ops i830_pipes_power_well_ops = {
1882*3f2dd94aSFrançois Tigeot 	.sync_hw = i830_pipes_power_well_sync_hw,
1883*3f2dd94aSFrançois Tigeot 	.enable = i830_pipes_power_well_enable,
1884*3f2dd94aSFrançois Tigeot 	.disable = i830_pipes_power_well_disable,
1885*3f2dd94aSFrançois Tigeot 	.is_enabled = i830_pipes_power_well_enabled,
1886*3f2dd94aSFrançois Tigeot };
1887*3f2dd94aSFrançois Tigeot 
1888*3f2dd94aSFrançois Tigeot static struct i915_power_well i830_power_wells[] = {
1889*3f2dd94aSFrançois Tigeot 	{
1890*3f2dd94aSFrançois Tigeot 		.name = "always-on",
1891*3f2dd94aSFrançois Tigeot 		.always_on = 1,
1892*3f2dd94aSFrançois Tigeot 		.domains = POWER_DOMAIN_MASK,
1893*3f2dd94aSFrançois Tigeot 		.ops = &i9xx_always_on_power_well_ops,
1894*3f2dd94aSFrançois Tigeot 		.id = I915_DISP_PW_ALWAYS_ON,
1895*3f2dd94aSFrançois Tigeot 	},
1896*3f2dd94aSFrançois Tigeot 	{
1897*3f2dd94aSFrançois Tigeot 		.name = "pipes",
1898*3f2dd94aSFrançois Tigeot 		.domains = I830_PIPES_POWER_DOMAINS,
1899*3f2dd94aSFrançois Tigeot 		.ops = &i830_pipes_power_well_ops,
1900*3f2dd94aSFrançois Tigeot 		.id = I830_DISP_PW_PIPES,
19012c9916cdSFrançois Tigeot 	},
19022c9916cdSFrançois Tigeot };
19032c9916cdSFrançois Tigeot 
19042c9916cdSFrançois Tigeot static const struct i915_power_well_ops hsw_power_well_ops = {
19052c9916cdSFrançois Tigeot 	.sync_hw = hsw_power_well_sync_hw,
19062c9916cdSFrançois Tigeot 	.enable = hsw_power_well_enable,
19072c9916cdSFrançois Tigeot 	.disable = hsw_power_well_disable,
19082c9916cdSFrançois Tigeot 	.is_enabled = hsw_power_well_enabled,
19092c9916cdSFrançois Tigeot };
19102c9916cdSFrançois Tigeot 
1911aee94f86SFrançois Tigeot static const struct i915_power_well_ops gen9_dc_off_power_well_ops = {
1912a85cb24fSFrançois Tigeot 	.sync_hw = i9xx_power_well_sync_hw_noop,
1913aee94f86SFrançois Tigeot 	.enable = gen9_dc_off_power_well_enable,
1914aee94f86SFrançois Tigeot 	.disable = gen9_dc_off_power_well_disable,
1915aee94f86SFrançois Tigeot 	.is_enabled = gen9_dc_off_power_well_enabled,
1916aee94f86SFrançois Tigeot };
1917aee94f86SFrançois Tigeot 
19181487f786SFrançois Tigeot static const struct i915_power_well_ops bxt_dpio_cmn_power_well_ops = {
1919a85cb24fSFrançois Tigeot 	.sync_hw = i9xx_power_well_sync_hw_noop,
19201487f786SFrançois Tigeot 	.enable = bxt_dpio_cmn_power_well_enable,
19211487f786SFrançois Tigeot 	.disable = bxt_dpio_cmn_power_well_disable,
19221487f786SFrançois Tigeot 	.is_enabled = bxt_dpio_cmn_power_well_enabled,
19231487f786SFrançois Tigeot };
19241487f786SFrançois Tigeot 
19252c9916cdSFrançois Tigeot static struct i915_power_well hsw_power_wells[] = {
19262c9916cdSFrançois Tigeot 	{
19272c9916cdSFrançois Tigeot 		.name = "always-on",
19282c9916cdSFrançois Tigeot 		.always_on = 1,
19298621f407SFrançois Tigeot 		.domains = POWER_DOMAIN_MASK,
19302c9916cdSFrançois Tigeot 		.ops = &i9xx_always_on_power_well_ops,
1931*3f2dd94aSFrançois Tigeot 		.id = I915_DISP_PW_ALWAYS_ON,
19322c9916cdSFrançois Tigeot 	},
19332c9916cdSFrançois Tigeot 	{
19342c9916cdSFrançois Tigeot 		.name = "display",
19352c9916cdSFrançois Tigeot 		.domains = HSW_DISPLAY_POWER_DOMAINS,
19362c9916cdSFrançois Tigeot 		.ops = &hsw_power_well_ops,
1937*3f2dd94aSFrançois Tigeot 		.id = HSW_DISP_PW_GLOBAL,
1938*3f2dd94aSFrançois Tigeot 		{
1939*3f2dd94aSFrançois Tigeot 			.hsw.has_vga = true,
1940*3f2dd94aSFrançois Tigeot 		},
19412c9916cdSFrançois Tigeot 	},
19422c9916cdSFrançois Tigeot };
19432c9916cdSFrançois Tigeot 
19442c9916cdSFrançois Tigeot static struct i915_power_well bdw_power_wells[] = {
19452c9916cdSFrançois Tigeot 	{
19462c9916cdSFrançois Tigeot 		.name = "always-on",
19472c9916cdSFrançois Tigeot 		.always_on = 1,
19488621f407SFrançois Tigeot 		.domains = POWER_DOMAIN_MASK,
19492c9916cdSFrançois Tigeot 		.ops = &i9xx_always_on_power_well_ops,
1950*3f2dd94aSFrançois Tigeot 		.id = I915_DISP_PW_ALWAYS_ON,
19512c9916cdSFrançois Tigeot 	},
19522c9916cdSFrançois Tigeot 	{
19532c9916cdSFrançois Tigeot 		.name = "display",
19542c9916cdSFrançois Tigeot 		.domains = BDW_DISPLAY_POWER_DOMAINS,
19552c9916cdSFrançois Tigeot 		.ops = &hsw_power_well_ops,
1956*3f2dd94aSFrançois Tigeot 		.id = HSW_DISP_PW_GLOBAL,
1957*3f2dd94aSFrançois Tigeot 		{
1958*3f2dd94aSFrançois Tigeot 			.hsw.irq_pipe_mask = BIT(PIPE_B) | BIT(PIPE_C),
1959*3f2dd94aSFrançois Tigeot 			.hsw.has_vga = true,
1960*3f2dd94aSFrançois Tigeot 		},
19612c9916cdSFrançois Tigeot 	},
19622c9916cdSFrançois Tigeot };
19632c9916cdSFrançois Tigeot 
19642c9916cdSFrançois Tigeot static const struct i915_power_well_ops vlv_display_power_well_ops = {
1965a85cb24fSFrançois Tigeot 	.sync_hw = i9xx_power_well_sync_hw_noop,
19662c9916cdSFrançois Tigeot 	.enable = vlv_display_power_well_enable,
19672c9916cdSFrançois Tigeot 	.disable = vlv_display_power_well_disable,
19682c9916cdSFrançois Tigeot 	.is_enabled = vlv_power_well_enabled,
19692c9916cdSFrançois Tigeot };
19702c9916cdSFrançois Tigeot 
19712c9916cdSFrançois Tigeot static const struct i915_power_well_ops vlv_dpio_cmn_power_well_ops = {
1972a85cb24fSFrançois Tigeot 	.sync_hw = i9xx_power_well_sync_hw_noop,
19732c9916cdSFrançois Tigeot 	.enable = vlv_dpio_cmn_power_well_enable,
19742c9916cdSFrançois Tigeot 	.disable = vlv_dpio_cmn_power_well_disable,
19752c9916cdSFrançois Tigeot 	.is_enabled = vlv_power_well_enabled,
19762c9916cdSFrançois Tigeot };
19772c9916cdSFrançois Tigeot 
19782c9916cdSFrançois Tigeot static const struct i915_power_well_ops vlv_dpio_power_well_ops = {
1979a85cb24fSFrançois Tigeot 	.sync_hw = i9xx_power_well_sync_hw_noop,
19802c9916cdSFrançois Tigeot 	.enable = vlv_power_well_enable,
19812c9916cdSFrançois Tigeot 	.disable = vlv_power_well_disable,
19822c9916cdSFrançois Tigeot 	.is_enabled = vlv_power_well_enabled,
19832c9916cdSFrançois Tigeot };
19842c9916cdSFrançois Tigeot 
19852c9916cdSFrançois Tigeot static struct i915_power_well vlv_power_wells[] = {
19862c9916cdSFrançois Tigeot 	{
19872c9916cdSFrançois Tigeot 		.name = "always-on",
19882c9916cdSFrançois Tigeot 		.always_on = 1,
19898621f407SFrançois Tigeot 		.domains = POWER_DOMAIN_MASK,
19902c9916cdSFrançois Tigeot 		.ops = &i9xx_always_on_power_well_ops,
1991*3f2dd94aSFrançois Tigeot 		.id = I915_DISP_PW_ALWAYS_ON,
19922c9916cdSFrançois Tigeot 	},
19932c9916cdSFrançois Tigeot 	{
19942c9916cdSFrançois Tigeot 		.name = "display",
19952c9916cdSFrançois Tigeot 		.domains = VLV_DISPLAY_POWER_DOMAINS,
19964be47400SFrançois Tigeot 		.id = PUNIT_POWER_WELL_DISP2D,
19972c9916cdSFrançois Tigeot 		.ops = &vlv_display_power_well_ops,
19982c9916cdSFrançois Tigeot 	},
19992c9916cdSFrançois Tigeot 	{
20002c9916cdSFrançois Tigeot 		.name = "dpio-tx-b-01",
20012c9916cdSFrançois Tigeot 		.domains = VLV_DPIO_TX_B_LANES_01_POWER_DOMAINS |
20022c9916cdSFrançois Tigeot 			   VLV_DPIO_TX_B_LANES_23_POWER_DOMAINS |
20032c9916cdSFrançois Tigeot 			   VLV_DPIO_TX_C_LANES_01_POWER_DOMAINS |
20042c9916cdSFrançois Tigeot 			   VLV_DPIO_TX_C_LANES_23_POWER_DOMAINS,
20052c9916cdSFrançois Tigeot 		.ops = &vlv_dpio_power_well_ops,
20064be47400SFrançois Tigeot 		.id = PUNIT_POWER_WELL_DPIO_TX_B_LANES_01,
20072c9916cdSFrançois Tigeot 	},
20082c9916cdSFrançois Tigeot 	{
20092c9916cdSFrançois Tigeot 		.name = "dpio-tx-b-23",
20102c9916cdSFrançois Tigeot 		.domains = VLV_DPIO_TX_B_LANES_01_POWER_DOMAINS |
20112c9916cdSFrançois Tigeot 			   VLV_DPIO_TX_B_LANES_23_POWER_DOMAINS |
20122c9916cdSFrançois Tigeot 			   VLV_DPIO_TX_C_LANES_01_POWER_DOMAINS |
20132c9916cdSFrançois Tigeot 			   VLV_DPIO_TX_C_LANES_23_POWER_DOMAINS,
20142c9916cdSFrançois Tigeot 		.ops = &vlv_dpio_power_well_ops,
20154be47400SFrançois Tigeot 		.id = PUNIT_POWER_WELL_DPIO_TX_B_LANES_23,
20162c9916cdSFrançois Tigeot 	},
20172c9916cdSFrançois Tigeot 	{
20182c9916cdSFrançois Tigeot 		.name = "dpio-tx-c-01",
20192c9916cdSFrançois Tigeot 		.domains = VLV_DPIO_TX_B_LANES_01_POWER_DOMAINS |
20202c9916cdSFrançois Tigeot 			   VLV_DPIO_TX_B_LANES_23_POWER_DOMAINS |
20212c9916cdSFrançois Tigeot 			   VLV_DPIO_TX_C_LANES_01_POWER_DOMAINS |
20222c9916cdSFrançois Tigeot 			   VLV_DPIO_TX_C_LANES_23_POWER_DOMAINS,
20232c9916cdSFrançois Tigeot 		.ops = &vlv_dpio_power_well_ops,
20244be47400SFrançois Tigeot 		.id = PUNIT_POWER_WELL_DPIO_TX_C_LANES_01,
20252c9916cdSFrançois Tigeot 	},
20262c9916cdSFrançois Tigeot 	{
20272c9916cdSFrançois Tigeot 		.name = "dpio-tx-c-23",
20282c9916cdSFrançois Tigeot 		.domains = VLV_DPIO_TX_B_LANES_01_POWER_DOMAINS |
20292c9916cdSFrançois Tigeot 			   VLV_DPIO_TX_B_LANES_23_POWER_DOMAINS |
20302c9916cdSFrançois Tigeot 			   VLV_DPIO_TX_C_LANES_01_POWER_DOMAINS |
20312c9916cdSFrançois Tigeot 			   VLV_DPIO_TX_C_LANES_23_POWER_DOMAINS,
20322c9916cdSFrançois Tigeot 		.ops = &vlv_dpio_power_well_ops,
20334be47400SFrançois Tigeot 		.id = PUNIT_POWER_WELL_DPIO_TX_C_LANES_23,
20342c9916cdSFrançois Tigeot 	},
20352c9916cdSFrançois Tigeot 	{
20362c9916cdSFrançois Tigeot 		.name = "dpio-common",
20372c9916cdSFrançois Tigeot 		.domains = VLV_DPIO_CMN_BC_POWER_DOMAINS,
20384be47400SFrançois Tigeot 		.id = PUNIT_POWER_WELL_DPIO_CMN_BC,
20392c9916cdSFrançois Tigeot 		.ops = &vlv_dpio_cmn_power_well_ops,
20402c9916cdSFrançois Tigeot 	},
20412c9916cdSFrançois Tigeot };
20422c9916cdSFrançois Tigeot 
20432c9916cdSFrançois Tigeot static struct i915_power_well chv_power_wells[] = {
20442c9916cdSFrançois Tigeot 	{
20452c9916cdSFrançois Tigeot 		.name = "always-on",
20462c9916cdSFrançois Tigeot 		.always_on = 1,
20478621f407SFrançois Tigeot 		.domains = POWER_DOMAIN_MASK,
20482c9916cdSFrançois Tigeot 		.ops = &i9xx_always_on_power_well_ops,
2049*3f2dd94aSFrançois Tigeot 		.id = I915_DISP_PW_ALWAYS_ON,
20502c9916cdSFrançois Tigeot 	},
20512c9916cdSFrançois Tigeot 	{
20522c9916cdSFrançois Tigeot 		.name = "display",
20532c9916cdSFrançois Tigeot 		/*
205419c468b4SFrançois Tigeot 		 * Pipe A power well is the new disp2d well. Pipe B and C
205519c468b4SFrançois Tigeot 		 * power wells don't actually exist. Pipe A power well is
205619c468b4SFrançois Tigeot 		 * required for any pipe to work.
20572c9916cdSFrançois Tigeot 		 */
20588621f407SFrançois Tigeot 		.domains = CHV_DISPLAY_POWER_DOMAINS,
2059*3f2dd94aSFrançois Tigeot 		.id = CHV_DISP_PW_PIPE_A,
20602c9916cdSFrançois Tigeot 		.ops = &chv_pipe_power_well_ops,
20612c9916cdSFrançois Tigeot 	},
20622c9916cdSFrançois Tigeot 	{
20632c9916cdSFrançois Tigeot 		.name = "dpio-common-bc",
206419c468b4SFrançois Tigeot 		.domains = CHV_DPIO_CMN_BC_POWER_DOMAINS,
20654be47400SFrançois Tigeot 		.id = PUNIT_POWER_WELL_DPIO_CMN_BC,
20662c9916cdSFrançois Tigeot 		.ops = &chv_dpio_cmn_power_well_ops,
20672c9916cdSFrançois Tigeot 	},
20682c9916cdSFrançois Tigeot 	{
20692c9916cdSFrançois Tigeot 		.name = "dpio-common-d",
207019c468b4SFrançois Tigeot 		.domains = CHV_DPIO_CMN_D_POWER_DOMAINS,
20714be47400SFrançois Tigeot 		.id = PUNIT_POWER_WELL_DPIO_CMN_D,
20722c9916cdSFrançois Tigeot 		.ops = &chv_dpio_cmn_power_well_ops,
20732c9916cdSFrançois Tigeot 	},
20742c9916cdSFrançois Tigeot };
20752c9916cdSFrançois Tigeot 
intel_display_power_well_is_enabled(struct drm_i915_private * dev_priv,enum i915_power_well_id power_well_id)207619c468b4SFrançois Tigeot bool intel_display_power_well_is_enabled(struct drm_i915_private *dev_priv,
2077*3f2dd94aSFrançois Tigeot 					 enum i915_power_well_id power_well_id)
207819c468b4SFrançois Tigeot {
207919c468b4SFrançois Tigeot 	struct i915_power_well *power_well;
208019c468b4SFrançois Tigeot 	bool ret;
208119c468b4SFrançois Tigeot 
208219c468b4SFrançois Tigeot 	power_well = lookup_power_well(dev_priv, power_well_id);
208319c468b4SFrançois Tigeot 	ret = power_well->ops->is_enabled(dev_priv, power_well);
208419c468b4SFrançois Tigeot 
208519c468b4SFrançois Tigeot 	return ret;
208619c468b4SFrançois Tigeot }
208719c468b4SFrançois Tigeot 
2088477eb7f9SFrançois Tigeot static struct i915_power_well skl_power_wells[] = {
2089477eb7f9SFrançois Tigeot 	{
2090477eb7f9SFrançois Tigeot 		.name = "always-on",
2091477eb7f9SFrançois Tigeot 		.always_on = 1,
20928621f407SFrançois Tigeot 		.domains = POWER_DOMAIN_MASK,
2093477eb7f9SFrançois Tigeot 		.ops = &i9xx_always_on_power_well_ops,
2094*3f2dd94aSFrançois Tigeot 		.id = I915_DISP_PW_ALWAYS_ON,
2095477eb7f9SFrançois Tigeot 	},
2096477eb7f9SFrançois Tigeot 	{
2097477eb7f9SFrançois Tigeot 		.name = "power well 1",
2098aee94f86SFrançois Tigeot 		/* Handled by the DMC firmware */
2099aee94f86SFrançois Tigeot 		.domains = 0,
2100*3f2dd94aSFrançois Tigeot 		.ops = &hsw_power_well_ops,
21014be47400SFrançois Tigeot 		.id = SKL_DISP_PW_1,
2102*3f2dd94aSFrançois Tigeot 		{
2103*3f2dd94aSFrançois Tigeot 			.hsw.has_fuses = true,
2104*3f2dd94aSFrançois Tigeot 		},
2105477eb7f9SFrançois Tigeot 	},
2106477eb7f9SFrançois Tigeot 	{
2107477eb7f9SFrançois Tigeot 		.name = "MISC IO power well",
2108aee94f86SFrançois Tigeot 		/* Handled by the DMC firmware */
2109aee94f86SFrançois Tigeot 		.domains = 0,
2110*3f2dd94aSFrançois Tigeot 		.ops = &hsw_power_well_ops,
21114be47400SFrançois Tigeot 		.id = SKL_DISP_PW_MISC_IO,
2112477eb7f9SFrançois Tigeot 	},
2113477eb7f9SFrançois Tigeot 	{
2114aee94f86SFrançois Tigeot 		.name = "DC off",
2115aee94f86SFrançois Tigeot 		.domains = SKL_DISPLAY_DC_OFF_POWER_DOMAINS,
2116aee94f86SFrançois Tigeot 		.ops = &gen9_dc_off_power_well_ops,
21174be47400SFrançois Tigeot 		.id = SKL_DISP_PW_DC_OFF,
2118aee94f86SFrançois Tigeot 	},
2119aee94f86SFrançois Tigeot 	{
2120477eb7f9SFrançois Tigeot 		.name = "power well 2",
2121477eb7f9SFrançois Tigeot 		.domains = SKL_DISPLAY_POWERWELL_2_POWER_DOMAINS,
2122*3f2dd94aSFrançois Tigeot 		.ops = &hsw_power_well_ops,
21234be47400SFrançois Tigeot 		.id = SKL_DISP_PW_2,
2124*3f2dd94aSFrançois Tigeot 		{
2125*3f2dd94aSFrançois Tigeot 			.hsw.irq_pipe_mask = BIT(PIPE_B) | BIT(PIPE_C),
2126*3f2dd94aSFrançois Tigeot 			.hsw.has_vga = true,
2127*3f2dd94aSFrançois Tigeot 			.hsw.has_fuses = true,
2128*3f2dd94aSFrançois Tigeot 		},
2129477eb7f9SFrançois Tigeot 	},
2130477eb7f9SFrançois Tigeot 	{
2131a85cb24fSFrançois Tigeot 		.name = "DDI A/E IO power well",
2132a85cb24fSFrançois Tigeot 		.domains = SKL_DISPLAY_DDI_IO_A_E_POWER_DOMAINS,
2133*3f2dd94aSFrançois Tigeot 		.ops = &hsw_power_well_ops,
21344be47400SFrançois Tigeot 		.id = SKL_DISP_PW_DDI_A_E,
2135477eb7f9SFrançois Tigeot 	},
2136477eb7f9SFrançois Tigeot 	{
2137a85cb24fSFrançois Tigeot 		.name = "DDI B IO power well",
2138a85cb24fSFrançois Tigeot 		.domains = SKL_DISPLAY_DDI_IO_B_POWER_DOMAINS,
2139*3f2dd94aSFrançois Tigeot 		.ops = &hsw_power_well_ops,
21404be47400SFrançois Tigeot 		.id = SKL_DISP_PW_DDI_B,
2141477eb7f9SFrançois Tigeot 	},
2142477eb7f9SFrançois Tigeot 	{
2143a85cb24fSFrançois Tigeot 		.name = "DDI C IO power well",
2144a85cb24fSFrançois Tigeot 		.domains = SKL_DISPLAY_DDI_IO_C_POWER_DOMAINS,
2145*3f2dd94aSFrançois Tigeot 		.ops = &hsw_power_well_ops,
21464be47400SFrançois Tigeot 		.id = SKL_DISP_PW_DDI_C,
2147477eb7f9SFrançois Tigeot 	},
2148477eb7f9SFrançois Tigeot 	{
2149a85cb24fSFrançois Tigeot 		.name = "DDI D IO power well",
2150a85cb24fSFrançois Tigeot 		.domains = SKL_DISPLAY_DDI_IO_D_POWER_DOMAINS,
2151*3f2dd94aSFrançois Tigeot 		.ops = &hsw_power_well_ops,
21524be47400SFrançois Tigeot 		.id = SKL_DISP_PW_DDI_D,
2153477eb7f9SFrançois Tigeot 	},
2154477eb7f9SFrançois Tigeot };
2155477eb7f9SFrançois Tigeot 
215619c468b4SFrançois Tigeot static struct i915_power_well bxt_power_wells[] = {
215719c468b4SFrançois Tigeot 	{
215819c468b4SFrançois Tigeot 		.name = "always-on",
215919c468b4SFrançois Tigeot 		.always_on = 1,
21608621f407SFrançois Tigeot 		.domains = POWER_DOMAIN_MASK,
216119c468b4SFrançois Tigeot 		.ops = &i9xx_always_on_power_well_ops,
2162*3f2dd94aSFrançois Tigeot 		.id = I915_DISP_PW_ALWAYS_ON,
216319c468b4SFrançois Tigeot 	},
216419c468b4SFrançois Tigeot 	{
216519c468b4SFrançois Tigeot 		.name = "power well 1",
21668621f407SFrançois Tigeot 		.domains = 0,
2167*3f2dd94aSFrançois Tigeot 		.ops = &hsw_power_well_ops,
21684be47400SFrançois Tigeot 		.id = SKL_DISP_PW_1,
2169*3f2dd94aSFrançois Tigeot 		{
2170*3f2dd94aSFrançois Tigeot 			.hsw.has_fuses = true,
2171*3f2dd94aSFrançois Tigeot 		},
217219c468b4SFrançois Tigeot 	},
217319c468b4SFrançois Tigeot 	{
2174aee94f86SFrançois Tigeot 		.name = "DC off",
2175aee94f86SFrançois Tigeot 		.domains = BXT_DISPLAY_DC_OFF_POWER_DOMAINS,
2176aee94f86SFrançois Tigeot 		.ops = &gen9_dc_off_power_well_ops,
21774be47400SFrançois Tigeot 		.id = SKL_DISP_PW_DC_OFF,
2178aee94f86SFrançois Tigeot 	},
2179aee94f86SFrançois Tigeot 	{
218019c468b4SFrançois Tigeot 		.name = "power well 2",
218119c468b4SFrançois Tigeot 		.domains = BXT_DISPLAY_POWERWELL_2_POWER_DOMAINS,
2182*3f2dd94aSFrançois Tigeot 		.ops = &hsw_power_well_ops,
21834be47400SFrançois Tigeot 		.id = SKL_DISP_PW_2,
2184*3f2dd94aSFrançois Tigeot 		{
2185*3f2dd94aSFrançois Tigeot 			.hsw.irq_pipe_mask = BIT(PIPE_B) | BIT(PIPE_C),
2186*3f2dd94aSFrançois Tigeot 			.hsw.has_vga = true,
2187*3f2dd94aSFrançois Tigeot 			.hsw.has_fuses = true,
2188*3f2dd94aSFrançois Tigeot 		},
2189aee94f86SFrançois Tigeot 	},
21901487f786SFrançois Tigeot 	{
21911487f786SFrançois Tigeot 		.name = "dpio-common-a",
21921487f786SFrançois Tigeot 		.domains = BXT_DPIO_CMN_A_POWER_DOMAINS,
21931487f786SFrançois Tigeot 		.ops = &bxt_dpio_cmn_power_well_ops,
21944be47400SFrançois Tigeot 		.id = BXT_DPIO_CMN_A,
2195*3f2dd94aSFrançois Tigeot 		{
2196*3f2dd94aSFrançois Tigeot 			.bxt.phy = DPIO_PHY1,
2197*3f2dd94aSFrançois Tigeot 		},
21981487f786SFrançois Tigeot 	},
21991487f786SFrançois Tigeot 	{
22001487f786SFrançois Tigeot 		.name = "dpio-common-bc",
22011487f786SFrançois Tigeot 		.domains = BXT_DPIO_CMN_BC_POWER_DOMAINS,
22021487f786SFrançois Tigeot 		.ops = &bxt_dpio_cmn_power_well_ops,
22034be47400SFrançois Tigeot 		.id = BXT_DPIO_CMN_BC,
2204*3f2dd94aSFrançois Tigeot 		{
2205*3f2dd94aSFrançois Tigeot 			.bxt.phy = DPIO_PHY0,
2206*3f2dd94aSFrançois Tigeot 		},
22071487f786SFrançois Tigeot 	},
220819c468b4SFrançois Tigeot };
220919c468b4SFrançois Tigeot 
2210a85cb24fSFrançois Tigeot static struct i915_power_well glk_power_wells[] = {
2211a85cb24fSFrançois Tigeot 	{
2212a85cb24fSFrançois Tigeot 		.name = "always-on",
2213a85cb24fSFrançois Tigeot 		.always_on = 1,
2214a85cb24fSFrançois Tigeot 		.domains = POWER_DOMAIN_MASK,
2215a85cb24fSFrançois Tigeot 		.ops = &i9xx_always_on_power_well_ops,
2216*3f2dd94aSFrançois Tigeot 		.id = I915_DISP_PW_ALWAYS_ON,
2217a85cb24fSFrançois Tigeot 	},
2218a85cb24fSFrançois Tigeot 	{
2219a85cb24fSFrançois Tigeot 		.name = "power well 1",
2220a85cb24fSFrançois Tigeot 		/* Handled by the DMC firmware */
2221a85cb24fSFrançois Tigeot 		.domains = 0,
2222*3f2dd94aSFrançois Tigeot 		.ops = &hsw_power_well_ops,
2223a85cb24fSFrançois Tigeot 		.id = SKL_DISP_PW_1,
2224*3f2dd94aSFrançois Tigeot 		{
2225*3f2dd94aSFrançois Tigeot 			.hsw.has_fuses = true,
2226*3f2dd94aSFrançois Tigeot 		},
2227a85cb24fSFrançois Tigeot 	},
2228a85cb24fSFrançois Tigeot 	{
2229a85cb24fSFrançois Tigeot 		.name = "DC off",
2230a85cb24fSFrançois Tigeot 		.domains = GLK_DISPLAY_DC_OFF_POWER_DOMAINS,
2231a85cb24fSFrançois Tigeot 		.ops = &gen9_dc_off_power_well_ops,
2232a85cb24fSFrançois Tigeot 		.id = SKL_DISP_PW_DC_OFF,
2233a85cb24fSFrançois Tigeot 	},
2234a85cb24fSFrançois Tigeot 	{
2235a85cb24fSFrançois Tigeot 		.name = "power well 2",
2236a85cb24fSFrançois Tigeot 		.domains = GLK_DISPLAY_POWERWELL_2_POWER_DOMAINS,
2237*3f2dd94aSFrançois Tigeot 		.ops = &hsw_power_well_ops,
2238a85cb24fSFrançois Tigeot 		.id = SKL_DISP_PW_2,
2239*3f2dd94aSFrançois Tigeot 		{
2240*3f2dd94aSFrançois Tigeot 			.hsw.irq_pipe_mask = BIT(PIPE_B) | BIT(PIPE_C),
2241*3f2dd94aSFrançois Tigeot 			.hsw.has_vga = true,
2242*3f2dd94aSFrançois Tigeot 			.hsw.has_fuses = true,
2243*3f2dd94aSFrançois Tigeot 		},
2244a85cb24fSFrançois Tigeot 	},
2245a85cb24fSFrançois Tigeot 	{
2246a85cb24fSFrançois Tigeot 		.name = "dpio-common-a",
2247a85cb24fSFrançois Tigeot 		.domains = GLK_DPIO_CMN_A_POWER_DOMAINS,
2248a85cb24fSFrançois Tigeot 		.ops = &bxt_dpio_cmn_power_well_ops,
2249a85cb24fSFrançois Tigeot 		.id = BXT_DPIO_CMN_A,
2250*3f2dd94aSFrançois Tigeot 		{
2251*3f2dd94aSFrançois Tigeot 			.bxt.phy = DPIO_PHY1,
2252*3f2dd94aSFrançois Tigeot 		},
2253a85cb24fSFrançois Tigeot 	},
2254a85cb24fSFrançois Tigeot 	{
2255a85cb24fSFrançois Tigeot 		.name = "dpio-common-b",
2256a85cb24fSFrançois Tigeot 		.domains = GLK_DPIO_CMN_B_POWER_DOMAINS,
2257a85cb24fSFrançois Tigeot 		.ops = &bxt_dpio_cmn_power_well_ops,
2258a85cb24fSFrançois Tigeot 		.id = BXT_DPIO_CMN_BC,
2259*3f2dd94aSFrançois Tigeot 		{
2260*3f2dd94aSFrançois Tigeot 			.bxt.phy = DPIO_PHY0,
2261*3f2dd94aSFrançois Tigeot 		},
2262a85cb24fSFrançois Tigeot 	},
2263a85cb24fSFrançois Tigeot 	{
2264a85cb24fSFrançois Tigeot 		.name = "dpio-common-c",
2265a85cb24fSFrançois Tigeot 		.domains = GLK_DPIO_CMN_C_POWER_DOMAINS,
2266a85cb24fSFrançois Tigeot 		.ops = &bxt_dpio_cmn_power_well_ops,
2267a85cb24fSFrançois Tigeot 		.id = GLK_DPIO_CMN_C,
2268*3f2dd94aSFrançois Tigeot 		{
2269*3f2dd94aSFrançois Tigeot 			.bxt.phy = DPIO_PHY2,
2270*3f2dd94aSFrançois Tigeot 		},
2271a85cb24fSFrançois Tigeot 	},
2272a85cb24fSFrançois Tigeot 	{
2273a85cb24fSFrançois Tigeot 		.name = "AUX A",
2274a85cb24fSFrançois Tigeot 		.domains = GLK_DISPLAY_AUX_A_POWER_DOMAINS,
2275*3f2dd94aSFrançois Tigeot 		.ops = &hsw_power_well_ops,
2276a85cb24fSFrançois Tigeot 		.id = GLK_DISP_PW_AUX_A,
2277a85cb24fSFrançois Tigeot 	},
2278a85cb24fSFrançois Tigeot 	{
2279a85cb24fSFrançois Tigeot 		.name = "AUX B",
2280a85cb24fSFrançois Tigeot 		.domains = GLK_DISPLAY_AUX_B_POWER_DOMAINS,
2281*3f2dd94aSFrançois Tigeot 		.ops = &hsw_power_well_ops,
2282a85cb24fSFrançois Tigeot 		.id = GLK_DISP_PW_AUX_B,
2283a85cb24fSFrançois Tigeot 	},
2284a85cb24fSFrançois Tigeot 	{
2285a85cb24fSFrançois Tigeot 		.name = "AUX C",
2286a85cb24fSFrançois Tigeot 		.domains = GLK_DISPLAY_AUX_C_POWER_DOMAINS,
2287*3f2dd94aSFrançois Tigeot 		.ops = &hsw_power_well_ops,
2288a85cb24fSFrançois Tigeot 		.id = GLK_DISP_PW_AUX_C,
2289a85cb24fSFrançois Tigeot 	},
2290a85cb24fSFrançois Tigeot 	{
2291a85cb24fSFrançois Tigeot 		.name = "DDI A IO power well",
2292a85cb24fSFrançois Tigeot 		.domains = GLK_DISPLAY_DDI_IO_A_POWER_DOMAINS,
2293*3f2dd94aSFrançois Tigeot 		.ops = &hsw_power_well_ops,
2294a85cb24fSFrançois Tigeot 		.id = GLK_DISP_PW_DDI_A,
2295a85cb24fSFrançois Tigeot 	},
2296a85cb24fSFrançois Tigeot 	{
2297a85cb24fSFrançois Tigeot 		.name = "DDI B IO power well",
2298a85cb24fSFrançois Tigeot 		.domains = GLK_DISPLAY_DDI_IO_B_POWER_DOMAINS,
2299*3f2dd94aSFrançois Tigeot 		.ops = &hsw_power_well_ops,
2300a85cb24fSFrançois Tigeot 		.id = SKL_DISP_PW_DDI_B,
2301a85cb24fSFrançois Tigeot 	},
2302a85cb24fSFrançois Tigeot 	{
2303a85cb24fSFrançois Tigeot 		.name = "DDI C IO power well",
2304a85cb24fSFrançois Tigeot 		.domains = GLK_DISPLAY_DDI_IO_C_POWER_DOMAINS,
2305*3f2dd94aSFrançois Tigeot 		.ops = &hsw_power_well_ops,
2306a85cb24fSFrançois Tigeot 		.id = SKL_DISP_PW_DDI_C,
2307a85cb24fSFrançois Tigeot 	},
2308a85cb24fSFrançois Tigeot };
2309a85cb24fSFrançois Tigeot 
2310*3f2dd94aSFrançois Tigeot static struct i915_power_well cnl_power_wells[] = {
2311*3f2dd94aSFrançois Tigeot 	{
2312*3f2dd94aSFrançois Tigeot 		.name = "always-on",
2313*3f2dd94aSFrançois Tigeot 		.always_on = 1,
2314*3f2dd94aSFrançois Tigeot 		.domains = POWER_DOMAIN_MASK,
2315*3f2dd94aSFrançois Tigeot 		.ops = &i9xx_always_on_power_well_ops,
2316*3f2dd94aSFrançois Tigeot 		.id = I915_DISP_PW_ALWAYS_ON,
2317*3f2dd94aSFrançois Tigeot 	},
2318*3f2dd94aSFrançois Tigeot 	{
2319*3f2dd94aSFrançois Tigeot 		.name = "power well 1",
2320*3f2dd94aSFrançois Tigeot 		/* Handled by the DMC firmware */
2321*3f2dd94aSFrançois Tigeot 		.domains = 0,
2322*3f2dd94aSFrançois Tigeot 		.ops = &hsw_power_well_ops,
2323*3f2dd94aSFrançois Tigeot 		.id = SKL_DISP_PW_1,
2324*3f2dd94aSFrançois Tigeot 		{
2325*3f2dd94aSFrançois Tigeot 			.hsw.has_fuses = true,
2326*3f2dd94aSFrançois Tigeot 		},
2327*3f2dd94aSFrançois Tigeot 	},
2328*3f2dd94aSFrançois Tigeot 	{
2329*3f2dd94aSFrançois Tigeot 		.name = "AUX A",
2330*3f2dd94aSFrançois Tigeot 		.domains = CNL_DISPLAY_AUX_A_POWER_DOMAINS,
2331*3f2dd94aSFrançois Tigeot 		.ops = &hsw_power_well_ops,
2332*3f2dd94aSFrançois Tigeot 		.id = CNL_DISP_PW_AUX_A,
2333*3f2dd94aSFrançois Tigeot 	},
2334*3f2dd94aSFrançois Tigeot 	{
2335*3f2dd94aSFrançois Tigeot 		.name = "AUX B",
2336*3f2dd94aSFrançois Tigeot 		.domains = CNL_DISPLAY_AUX_B_POWER_DOMAINS,
2337*3f2dd94aSFrançois Tigeot 		.ops = &hsw_power_well_ops,
2338*3f2dd94aSFrançois Tigeot 		.id = CNL_DISP_PW_AUX_B,
2339*3f2dd94aSFrançois Tigeot 	},
2340*3f2dd94aSFrançois Tigeot 	{
2341*3f2dd94aSFrançois Tigeot 		.name = "AUX C",
2342*3f2dd94aSFrançois Tigeot 		.domains = CNL_DISPLAY_AUX_C_POWER_DOMAINS,
2343*3f2dd94aSFrançois Tigeot 		.ops = &hsw_power_well_ops,
2344*3f2dd94aSFrançois Tigeot 		.id = CNL_DISP_PW_AUX_C,
2345*3f2dd94aSFrançois Tigeot 	},
2346*3f2dd94aSFrançois Tigeot 	{
2347*3f2dd94aSFrançois Tigeot 		.name = "AUX D",
2348*3f2dd94aSFrançois Tigeot 		.domains = CNL_DISPLAY_AUX_D_POWER_DOMAINS,
2349*3f2dd94aSFrançois Tigeot 		.ops = &hsw_power_well_ops,
2350*3f2dd94aSFrançois Tigeot 		.id = CNL_DISP_PW_AUX_D,
2351*3f2dd94aSFrançois Tigeot 	},
2352*3f2dd94aSFrançois Tigeot 	{
2353*3f2dd94aSFrançois Tigeot 		.name = "DC off",
2354*3f2dd94aSFrançois Tigeot 		.domains = CNL_DISPLAY_DC_OFF_POWER_DOMAINS,
2355*3f2dd94aSFrançois Tigeot 		.ops = &gen9_dc_off_power_well_ops,
2356*3f2dd94aSFrançois Tigeot 		.id = SKL_DISP_PW_DC_OFF,
2357*3f2dd94aSFrançois Tigeot 	},
2358*3f2dd94aSFrançois Tigeot 	{
2359*3f2dd94aSFrançois Tigeot 		.name = "power well 2",
2360*3f2dd94aSFrançois Tigeot 		.domains = CNL_DISPLAY_POWERWELL_2_POWER_DOMAINS,
2361*3f2dd94aSFrançois Tigeot 		.ops = &hsw_power_well_ops,
2362*3f2dd94aSFrançois Tigeot 		.id = SKL_DISP_PW_2,
2363*3f2dd94aSFrançois Tigeot 		{
2364*3f2dd94aSFrançois Tigeot 			.hsw.irq_pipe_mask = BIT(PIPE_B) | BIT(PIPE_C),
2365*3f2dd94aSFrançois Tigeot 			.hsw.has_vga = true,
2366*3f2dd94aSFrançois Tigeot 			.hsw.has_fuses = true,
2367*3f2dd94aSFrançois Tigeot 		},
2368*3f2dd94aSFrançois Tigeot 	},
2369*3f2dd94aSFrançois Tigeot 	{
2370*3f2dd94aSFrançois Tigeot 		.name = "DDI A IO power well",
2371*3f2dd94aSFrançois Tigeot 		.domains = CNL_DISPLAY_DDI_A_IO_POWER_DOMAINS,
2372*3f2dd94aSFrançois Tigeot 		.ops = &hsw_power_well_ops,
2373*3f2dd94aSFrançois Tigeot 		.id = CNL_DISP_PW_DDI_A,
2374*3f2dd94aSFrançois Tigeot 	},
2375*3f2dd94aSFrançois Tigeot 	{
2376*3f2dd94aSFrançois Tigeot 		.name = "DDI B IO power well",
2377*3f2dd94aSFrançois Tigeot 		.domains = CNL_DISPLAY_DDI_B_IO_POWER_DOMAINS,
2378*3f2dd94aSFrançois Tigeot 		.ops = &hsw_power_well_ops,
2379*3f2dd94aSFrançois Tigeot 		.id = SKL_DISP_PW_DDI_B,
2380*3f2dd94aSFrançois Tigeot 	},
2381*3f2dd94aSFrançois Tigeot 	{
2382*3f2dd94aSFrançois Tigeot 		.name = "DDI C IO power well",
2383*3f2dd94aSFrançois Tigeot 		.domains = CNL_DISPLAY_DDI_C_IO_POWER_DOMAINS,
2384*3f2dd94aSFrançois Tigeot 		.ops = &hsw_power_well_ops,
2385*3f2dd94aSFrançois Tigeot 		.id = SKL_DISP_PW_DDI_C,
2386*3f2dd94aSFrançois Tigeot 	},
2387*3f2dd94aSFrançois Tigeot 	{
2388*3f2dd94aSFrançois Tigeot 		.name = "DDI D IO power well",
2389*3f2dd94aSFrançois Tigeot 		.domains = CNL_DISPLAY_DDI_D_IO_POWER_DOMAINS,
2390*3f2dd94aSFrançois Tigeot 		.ops = &hsw_power_well_ops,
2391*3f2dd94aSFrançois Tigeot 		.id = SKL_DISP_PW_DDI_D,
2392*3f2dd94aSFrançois Tigeot 	},
2393*3f2dd94aSFrançois Tigeot };
2394*3f2dd94aSFrançois Tigeot 
2395352ff8bdSFrançois Tigeot static int
sanitize_disable_power_well_option(const struct drm_i915_private * dev_priv,int disable_power_well)2396352ff8bdSFrançois Tigeot sanitize_disable_power_well_option(const struct drm_i915_private *dev_priv,
2397352ff8bdSFrançois Tigeot 				   int disable_power_well)
2398352ff8bdSFrançois Tigeot {
2399352ff8bdSFrançois Tigeot 	if (disable_power_well >= 0)
2400352ff8bdSFrançois Tigeot 		return !!disable_power_well;
2401352ff8bdSFrançois Tigeot 
24028621f407SFrançois Tigeot 	return 1;
2403352ff8bdSFrançois Tigeot }
2404352ff8bdSFrançois Tigeot 
get_allowed_dc_mask(const struct drm_i915_private * dev_priv,int enable_dc)24058621f407SFrançois Tigeot static uint32_t get_allowed_dc_mask(const struct drm_i915_private *dev_priv,
24068621f407SFrançois Tigeot 				    int enable_dc)
24078621f407SFrançois Tigeot {
24088621f407SFrançois Tigeot 	uint32_t mask;
24098621f407SFrançois Tigeot 	int requested_dc;
24108621f407SFrançois Tigeot 	int max_dc;
24118621f407SFrançois Tigeot 
2412*3f2dd94aSFrançois Tigeot 	if (IS_GEN9_BC(dev_priv) || IS_CANNONLAKE(dev_priv)) {
24138621f407SFrançois Tigeot 		max_dc = 2;
24148621f407SFrançois Tigeot 		mask = 0;
2415a85cb24fSFrançois Tigeot 	} else if (IS_GEN9_LP(dev_priv)) {
24168621f407SFrançois Tigeot 		max_dc = 1;
24178621f407SFrançois Tigeot 		/*
24188621f407SFrançois Tigeot 		 * DC9 has a separate HW flow from the rest of the DC states,
24198621f407SFrançois Tigeot 		 * not depending on the DMC firmware. It's needed by system
24208621f407SFrançois Tigeot 		 * suspend/resume, so allow it unconditionally.
24218621f407SFrançois Tigeot 		 */
24228621f407SFrançois Tigeot 		mask = DC_STATE_EN_DC9;
24238621f407SFrançois Tigeot 	} else {
24248621f407SFrançois Tigeot 		max_dc = 0;
24258621f407SFrançois Tigeot 		mask = 0;
24268621f407SFrançois Tigeot 	}
24278621f407SFrançois Tigeot 
2428*3f2dd94aSFrançois Tigeot 	if (!i915_modparams.disable_power_well)
24298621f407SFrançois Tigeot 		max_dc = 0;
24308621f407SFrançois Tigeot 
24318621f407SFrançois Tigeot 	if (enable_dc >= 0 && enable_dc <= max_dc) {
24328621f407SFrançois Tigeot 		requested_dc = enable_dc;
24338621f407SFrançois Tigeot 	} else if (enable_dc == -1) {
24348621f407SFrançois Tigeot 		requested_dc = max_dc;
24358621f407SFrançois Tigeot 	} else if (enable_dc > max_dc && enable_dc <= 2) {
24368621f407SFrançois Tigeot 		DRM_DEBUG_KMS("Adjusting requested max DC state (%d->%d)\n",
24378621f407SFrançois Tigeot 			      enable_dc, max_dc);
24388621f407SFrançois Tigeot 		requested_dc = max_dc;
24398621f407SFrançois Tigeot 	} else {
24408621f407SFrançois Tigeot 		DRM_ERROR("Unexpected value for enable_dc (%d)\n", enable_dc);
24418621f407SFrançois Tigeot 		requested_dc = max_dc;
24428621f407SFrançois Tigeot 	}
24438621f407SFrançois Tigeot 
24448621f407SFrançois Tigeot 	if (requested_dc > 1)
24458621f407SFrançois Tigeot 		mask |= DC_STATE_EN_UPTO_DC6;
24468621f407SFrançois Tigeot 	if (requested_dc > 0)
24478621f407SFrançois Tigeot 		mask |= DC_STATE_EN_UPTO_DC5;
24488621f407SFrançois Tigeot 
24498621f407SFrançois Tigeot 	DRM_DEBUG_KMS("Allowed DC state mask %02x\n", mask);
24508621f407SFrançois Tigeot 
24518621f407SFrançois Tigeot 	return mask;
2452352ff8bdSFrançois Tigeot }
2453352ff8bdSFrançois Tigeot 
assert_power_well_ids_unique(struct drm_i915_private * dev_priv)2454*3f2dd94aSFrançois Tigeot static void assert_power_well_ids_unique(struct drm_i915_private *dev_priv)
2455*3f2dd94aSFrançois Tigeot {
2456*3f2dd94aSFrançois Tigeot 	struct i915_power_domains *power_domains = &dev_priv->power_domains;
2457*3f2dd94aSFrançois Tigeot 	u64 power_well_ids;
2458*3f2dd94aSFrançois Tigeot 	int i;
2459*3f2dd94aSFrançois Tigeot 
2460*3f2dd94aSFrançois Tigeot 	power_well_ids = 0;
2461*3f2dd94aSFrançois Tigeot 	for (i = 0; i < power_domains->power_well_count; i++) {
2462*3f2dd94aSFrançois Tigeot 		enum i915_power_well_id id = power_domains->power_wells[i].id;
2463*3f2dd94aSFrançois Tigeot 
2464*3f2dd94aSFrançois Tigeot 		WARN_ON(id >= sizeof(power_well_ids) * 8);
2465*3f2dd94aSFrançois Tigeot 		WARN_ON(power_well_ids & BIT_ULL(id));
2466*3f2dd94aSFrançois Tigeot 		power_well_ids |= BIT_ULL(id);
2467*3f2dd94aSFrançois Tigeot 	}
2468*3f2dd94aSFrançois Tigeot }
2469*3f2dd94aSFrançois Tigeot 
24702c9916cdSFrançois Tigeot #define set_power_wells(power_domains, __power_wells) ({		\
24712c9916cdSFrançois Tigeot 	(power_domains)->power_wells = (__power_wells);			\
24722c9916cdSFrançois Tigeot 	(power_domains)->power_well_count = ARRAY_SIZE(__power_wells);	\
24732c9916cdSFrançois Tigeot })
24742c9916cdSFrançois Tigeot 
24752c9916cdSFrançois Tigeot /**
24762c9916cdSFrançois Tigeot  * intel_power_domains_init - initializes the power domain structures
24772c9916cdSFrançois Tigeot  * @dev_priv: i915 device instance
24782c9916cdSFrançois Tigeot  *
24792c9916cdSFrançois Tigeot  * Initializes the power domain structures for @dev_priv depending upon the
24802c9916cdSFrançois Tigeot  * supported platform.
24812c9916cdSFrançois Tigeot  */
intel_power_domains_init(struct drm_i915_private * dev_priv)24822c9916cdSFrançois Tigeot int intel_power_domains_init(struct drm_i915_private *dev_priv)
24832c9916cdSFrançois Tigeot {
24842c9916cdSFrançois Tigeot 	struct i915_power_domains *power_domains = &dev_priv->power_domains;
24852c9916cdSFrançois Tigeot 
2486*3f2dd94aSFrançois Tigeot 	i915_modparams.disable_power_well =
2487*3f2dd94aSFrançois Tigeot 		sanitize_disable_power_well_option(dev_priv,
2488*3f2dd94aSFrançois Tigeot 						   i915_modparams.disable_power_well);
2489*3f2dd94aSFrançois Tigeot 	dev_priv->csr.allowed_dc_mask =
2490*3f2dd94aSFrançois Tigeot 		get_allowed_dc_mask(dev_priv, i915_modparams.enable_dc);
2491352ff8bdSFrançois Tigeot 
2492a85cb24fSFrançois Tigeot 	BUILD_BUG_ON(POWER_DOMAIN_NUM > 64);
2493352ff8bdSFrançois Tigeot 
24942c9916cdSFrançois Tigeot 	lockinit(&power_domains->lock, "i915pl", 0, LK_CANRECURSE);
24952c9916cdSFrançois Tigeot 
24962c9916cdSFrançois Tigeot 	/*
24972c9916cdSFrançois Tigeot 	 * The enabling order will be from lower to higher indexed wells,
24982c9916cdSFrançois Tigeot 	 * the disabling order is reversed.
24992c9916cdSFrançois Tigeot 	 */
25008621f407SFrançois Tigeot 	if (IS_HASWELL(dev_priv)) {
25012c9916cdSFrançois Tigeot 		set_power_wells(power_domains, hsw_power_wells);
25028621f407SFrançois Tigeot 	} else if (IS_BROADWELL(dev_priv)) {
25032c9916cdSFrançois Tigeot 		set_power_wells(power_domains, bdw_power_wells);
2504a85cb24fSFrançois Tigeot 	} else if (IS_GEN9_BC(dev_priv)) {
2505477eb7f9SFrançois Tigeot 		set_power_wells(power_domains, skl_power_wells);
2506*3f2dd94aSFrançois Tigeot 	} else if (IS_CANNONLAKE(dev_priv)) {
2507*3f2dd94aSFrançois Tigeot 		set_power_wells(power_domains, cnl_power_wells);
25088621f407SFrançois Tigeot 	} else if (IS_BROXTON(dev_priv)) {
250919c468b4SFrançois Tigeot 		set_power_wells(power_domains, bxt_power_wells);
2510a85cb24fSFrançois Tigeot 	} else if (IS_GEMINILAKE(dev_priv)) {
2511a85cb24fSFrançois Tigeot 		set_power_wells(power_domains, glk_power_wells);
25128621f407SFrançois Tigeot 	} else if (IS_CHERRYVIEW(dev_priv)) {
25132c9916cdSFrançois Tigeot 		set_power_wells(power_domains, chv_power_wells);
25148621f407SFrançois Tigeot 	} else if (IS_VALLEYVIEW(dev_priv)) {
25152c9916cdSFrançois Tigeot 		set_power_wells(power_domains, vlv_power_wells);
2516*3f2dd94aSFrançois Tigeot 	} else if (IS_I830(dev_priv)) {
2517*3f2dd94aSFrançois Tigeot 		set_power_wells(power_domains, i830_power_wells);
25182c9916cdSFrançois Tigeot 	} else {
25192c9916cdSFrançois Tigeot 		set_power_wells(power_domains, i9xx_always_on_power_well);
25202c9916cdSFrançois Tigeot 	}
25212c9916cdSFrançois Tigeot 
2522*3f2dd94aSFrançois Tigeot 	assert_power_well_ids_unique(dev_priv);
2523*3f2dd94aSFrançois Tigeot 
25242c9916cdSFrançois Tigeot 	return 0;
25252c9916cdSFrançois Tigeot }
25262c9916cdSFrançois Tigeot 
25272c9916cdSFrançois Tigeot /**
25282c9916cdSFrançois Tigeot  * intel_power_domains_fini - finalizes the power domain structures
25292c9916cdSFrançois Tigeot  * @dev_priv: i915 device instance
25302c9916cdSFrançois Tigeot  *
25312c9916cdSFrançois Tigeot  * Finalizes the power domain structures for @dev_priv depending upon the
25322c9916cdSFrançois Tigeot  * supported platform. This function also disables runtime pm and ensures that
25332c9916cdSFrançois Tigeot  * the device stays powered up so that the driver can be reloaded.
25342c9916cdSFrançois Tigeot  */
intel_power_domains_fini(struct drm_i915_private * dev_priv)25352c9916cdSFrançois Tigeot void intel_power_domains_fini(struct drm_i915_private *dev_priv)
25362c9916cdSFrançois Tigeot {
2537aee94f86SFrançois Tigeot #if 0
25381e12ee3bSFrançois Tigeot 	struct device *kdev = &dev_priv->drm.pdev->dev;
2539aee94f86SFrançois Tigeot #endif
25402c9916cdSFrançois Tigeot 
2541aee94f86SFrançois Tigeot 	/*
2542aee94f86SFrançois Tigeot 	 * The i915.ko module is still not prepared to be loaded when
25432c9916cdSFrançois Tigeot 	 * the power well is not enabled, so just enable it in case
2544aee94f86SFrançois Tigeot 	 * we're going to unload/reload.
2545aee94f86SFrançois Tigeot 	 * The following also reacquires the RPM reference the core passed
2546aee94f86SFrançois Tigeot 	 * to the driver during loading, which is dropped in
2547aee94f86SFrançois Tigeot 	 * intel_runtime_pm_enable(). We have to hand back the control of the
2548aee94f86SFrançois Tigeot 	 * device to the core with this reference held.
2549aee94f86SFrançois Tigeot 	 */
25502c9916cdSFrançois Tigeot 	intel_display_set_init_power(dev_priv, true);
2551aee94f86SFrançois Tigeot 
2552aee94f86SFrançois Tigeot 	/* Remove the refcount we took to keep power well support disabled. */
2553*3f2dd94aSFrançois Tigeot 	if (!i915_modparams.disable_power_well)
2554aee94f86SFrançois Tigeot 		intel_display_power_put(dev_priv, POWER_DOMAIN_INIT);
2555aee94f86SFrançois Tigeot 
2556aee94f86SFrançois Tigeot 	/*
2557aee94f86SFrançois Tigeot 	 * Remove the refcount we took in intel_runtime_pm_enable() in case
2558aee94f86SFrançois Tigeot 	 * the platform doesn't support runtime PM.
2559aee94f86SFrançois Tigeot 	 */
2560aee94f86SFrançois Tigeot #if 0
2561aee94f86SFrançois Tigeot 	if (!HAS_RUNTIME_PM(dev_priv))
25621e12ee3bSFrançois Tigeot 		pm_runtime_put(kdev);
2563aee94f86SFrançois Tigeot #endif
25642c9916cdSFrançois Tigeot }
25652c9916cdSFrançois Tigeot 
intel_power_domains_sync_hw(struct drm_i915_private * dev_priv)2566aee94f86SFrançois Tigeot static void intel_power_domains_sync_hw(struct drm_i915_private *dev_priv)
25672c9916cdSFrançois Tigeot {
25682c9916cdSFrançois Tigeot 	struct i915_power_domains *power_domains = &dev_priv->power_domains;
25692c9916cdSFrançois Tigeot 	struct i915_power_well *power_well;
25702c9916cdSFrançois Tigeot 
25712c9916cdSFrançois Tigeot 	mutex_lock(&power_domains->lock);
2572a85cb24fSFrançois Tigeot 	for_each_power_well(dev_priv, power_well) {
25732c9916cdSFrançois Tigeot 		power_well->ops->sync_hw(dev_priv, power_well);
25742c9916cdSFrançois Tigeot 		power_well->hw_enabled = power_well->ops->is_enabled(dev_priv,
25752c9916cdSFrançois Tigeot 								     power_well);
25762c9916cdSFrançois Tigeot 	}
25772c9916cdSFrançois Tigeot 	mutex_unlock(&power_domains->lock);
25782c9916cdSFrançois Tigeot }
25792c9916cdSFrançois Tigeot 
gen9_dbuf_enable(struct drm_i915_private * dev_priv)25801487f786SFrançois Tigeot static void gen9_dbuf_enable(struct drm_i915_private *dev_priv)
25811487f786SFrançois Tigeot {
25821487f786SFrançois Tigeot 	I915_WRITE(DBUF_CTL, I915_READ(DBUF_CTL) | DBUF_POWER_REQUEST);
25831487f786SFrançois Tigeot 	POSTING_READ(DBUF_CTL);
25841487f786SFrançois Tigeot 
25851487f786SFrançois Tigeot 	udelay(10);
25861487f786SFrançois Tigeot 
25871487f786SFrançois Tigeot 	if (!(I915_READ(DBUF_CTL) & DBUF_POWER_STATE))
25881487f786SFrançois Tigeot 		DRM_ERROR("DBuf power enable timeout\n");
25891487f786SFrançois Tigeot }
25901487f786SFrançois Tigeot 
gen9_dbuf_disable(struct drm_i915_private * dev_priv)25911487f786SFrançois Tigeot static void gen9_dbuf_disable(struct drm_i915_private *dev_priv)
25921487f786SFrançois Tigeot {
25931487f786SFrançois Tigeot 	I915_WRITE(DBUF_CTL, I915_READ(DBUF_CTL) & ~DBUF_POWER_REQUEST);
25941487f786SFrançois Tigeot 	POSTING_READ(DBUF_CTL);
25951487f786SFrançois Tigeot 
25961487f786SFrançois Tigeot 	udelay(10);
25971487f786SFrançois Tigeot 
25981487f786SFrançois Tigeot 	if (I915_READ(DBUF_CTL) & DBUF_POWER_STATE)
25991487f786SFrançois Tigeot 		DRM_ERROR("DBuf power disable timeout!\n");
26001487f786SFrançois Tigeot }
26011487f786SFrançois Tigeot 
skl_display_core_init(struct drm_i915_private * dev_priv,bool resume)2602aee94f86SFrançois Tigeot static void skl_display_core_init(struct drm_i915_private *dev_priv,
2603aee94f86SFrançois Tigeot 				   bool resume)
2604aee94f86SFrançois Tigeot {
2605aee94f86SFrançois Tigeot 	struct i915_power_domains *power_domains = &dev_priv->power_domains;
26068621f407SFrançois Tigeot 	struct i915_power_well *well;
2607aee94f86SFrançois Tigeot 	uint32_t val;
2608aee94f86SFrançois Tigeot 
2609aee94f86SFrançois Tigeot 	gen9_set_dc_state(dev_priv, DC_STATE_DISABLE);
2610aee94f86SFrançois Tigeot 
2611aee94f86SFrançois Tigeot 	/* enable PCH reset handshake */
2612aee94f86SFrançois Tigeot 	val = I915_READ(HSW_NDE_RSTWRN_OPT);
2613aee94f86SFrançois Tigeot 	I915_WRITE(HSW_NDE_RSTWRN_OPT, val | RESET_PCH_HANDSHAKE_ENABLE);
2614aee94f86SFrançois Tigeot 
2615aee94f86SFrançois Tigeot 	/* enable PG1 and Misc I/O */
2616aee94f86SFrançois Tigeot 	mutex_lock(&power_domains->lock);
26178621f407SFrançois Tigeot 
26188621f407SFrançois Tigeot 	well = lookup_power_well(dev_priv, SKL_DISP_PW_1);
26198621f407SFrançois Tigeot 	intel_power_well_enable(dev_priv, well);
26208621f407SFrançois Tigeot 
26218621f407SFrançois Tigeot 	well = lookup_power_well(dev_priv, SKL_DISP_PW_MISC_IO);
26228621f407SFrançois Tigeot 	intel_power_well_enable(dev_priv, well);
26238621f407SFrançois Tigeot 
2624aee94f86SFrançois Tigeot 	mutex_unlock(&power_domains->lock);
2625aee94f86SFrançois Tigeot 
2626aee94f86SFrançois Tigeot 	skl_init_cdclk(dev_priv);
2627aee94f86SFrançois Tigeot 
26281487f786SFrançois Tigeot 	gen9_dbuf_enable(dev_priv);
26291487f786SFrançois Tigeot 
26301487f786SFrançois Tigeot 	if (resume && dev_priv->csr.dmc_payload)
26318621f407SFrançois Tigeot 		intel_csr_load_program(dev_priv);
2632aee94f86SFrançois Tigeot }
2633aee94f86SFrançois Tigeot 
skl_display_core_uninit(struct drm_i915_private * dev_priv)2634aee94f86SFrançois Tigeot static void skl_display_core_uninit(struct drm_i915_private *dev_priv)
2635aee94f86SFrançois Tigeot {
2636aee94f86SFrançois Tigeot 	struct i915_power_domains *power_domains = &dev_priv->power_domains;
26378621f407SFrançois Tigeot 	struct i915_power_well *well;
2638aee94f86SFrançois Tigeot 
2639aee94f86SFrançois Tigeot 	gen9_set_dc_state(dev_priv, DC_STATE_DISABLE);
2640aee94f86SFrançois Tigeot 
26411487f786SFrançois Tigeot 	gen9_dbuf_disable(dev_priv);
26421487f786SFrançois Tigeot 
2643aee94f86SFrançois Tigeot 	skl_uninit_cdclk(dev_priv);
2644aee94f86SFrançois Tigeot 
2645aee94f86SFrançois Tigeot 	/* The spec doesn't call for removing the reset handshake flag */
2646aee94f86SFrançois Tigeot 	/* disable PG1 and Misc I/O */
26478621f407SFrançois Tigeot 
2648aee94f86SFrançois Tigeot 	mutex_lock(&power_domains->lock);
26498621f407SFrançois Tigeot 
2650*3f2dd94aSFrançois Tigeot 	/*
2651*3f2dd94aSFrançois Tigeot 	 * BSpec says to keep the MISC IO power well enabled here, only
2652*3f2dd94aSFrançois Tigeot 	 * remove our request for power well 1.
2653*3f2dd94aSFrançois Tigeot 	 * Note that even though the driver's request is removed power well 1
2654*3f2dd94aSFrançois Tigeot 	 * may stay enabled after this due to DMC's own request on it.
2655*3f2dd94aSFrançois Tigeot 	 */
26568621f407SFrançois Tigeot 	well = lookup_power_well(dev_priv, SKL_DISP_PW_1);
26578621f407SFrançois Tigeot 	intel_power_well_disable(dev_priv, well);
26588621f407SFrançois Tigeot 
26598621f407SFrançois Tigeot 	mutex_unlock(&power_domains->lock);
2660*3f2dd94aSFrançois Tigeot 
2661*3f2dd94aSFrançois Tigeot 	usleep_range(10, 30);		/* 10 us delay per Bspec */
26628621f407SFrançois Tigeot }
26638621f407SFrançois Tigeot 
bxt_display_core_init(struct drm_i915_private * dev_priv,bool resume)26648621f407SFrançois Tigeot void bxt_display_core_init(struct drm_i915_private *dev_priv,
26658621f407SFrançois Tigeot 			   bool resume)
26668621f407SFrançois Tigeot {
26678621f407SFrançois Tigeot 	struct i915_power_domains *power_domains = &dev_priv->power_domains;
26688621f407SFrançois Tigeot 	struct i915_power_well *well;
26698621f407SFrançois Tigeot 	uint32_t val;
26708621f407SFrançois Tigeot 
26718621f407SFrançois Tigeot 	gen9_set_dc_state(dev_priv, DC_STATE_DISABLE);
26728621f407SFrançois Tigeot 
26738621f407SFrançois Tigeot 	/*
26748621f407SFrançois Tigeot 	 * NDE_RSTWRN_OPT RST PCH Handshake En must always be 0b on BXT
26758621f407SFrançois Tigeot 	 * or else the reset will hang because there is no PCH to respond.
26768621f407SFrançois Tigeot 	 * Move the handshake programming to initialization sequence.
26778621f407SFrançois Tigeot 	 * Previously was left up to BIOS.
26788621f407SFrançois Tigeot 	 */
26798621f407SFrançois Tigeot 	val = I915_READ(HSW_NDE_RSTWRN_OPT);
26808621f407SFrançois Tigeot 	val &= ~RESET_PCH_HANDSHAKE_ENABLE;
26818621f407SFrançois Tigeot 	I915_WRITE(HSW_NDE_RSTWRN_OPT, val);
26828621f407SFrançois Tigeot 
26838621f407SFrançois Tigeot 	/* Enable PG1 */
26848621f407SFrançois Tigeot 	mutex_lock(&power_domains->lock);
26858621f407SFrançois Tigeot 
26868621f407SFrançois Tigeot 	well = lookup_power_well(dev_priv, SKL_DISP_PW_1);
26878621f407SFrançois Tigeot 	intel_power_well_enable(dev_priv, well);
26888621f407SFrançois Tigeot 
26898621f407SFrançois Tigeot 	mutex_unlock(&power_domains->lock);
26908621f407SFrançois Tigeot 
26911487f786SFrançois Tigeot 	bxt_init_cdclk(dev_priv);
26928621f407SFrançois Tigeot 
26931487f786SFrançois Tigeot 	gen9_dbuf_enable(dev_priv);
26948621f407SFrançois Tigeot 
26958621f407SFrançois Tigeot 	if (resume && dev_priv->csr.dmc_payload)
26968621f407SFrançois Tigeot 		intel_csr_load_program(dev_priv);
26978621f407SFrançois Tigeot }
26988621f407SFrançois Tigeot 
bxt_display_core_uninit(struct drm_i915_private * dev_priv)26998621f407SFrançois Tigeot void bxt_display_core_uninit(struct drm_i915_private *dev_priv)
27008621f407SFrançois Tigeot {
27018621f407SFrançois Tigeot 	struct i915_power_domains *power_domains = &dev_priv->power_domains;
27028621f407SFrançois Tigeot 	struct i915_power_well *well;
27038621f407SFrançois Tigeot 
27048621f407SFrançois Tigeot 	gen9_set_dc_state(dev_priv, DC_STATE_DISABLE);
27058621f407SFrançois Tigeot 
27061487f786SFrançois Tigeot 	gen9_dbuf_disable(dev_priv);
27071487f786SFrançois Tigeot 
27081487f786SFrançois Tigeot 	bxt_uninit_cdclk(dev_priv);
27098621f407SFrançois Tigeot 
27108621f407SFrançois Tigeot 	/* The spec doesn't call for removing the reset handshake flag */
27118621f407SFrançois Tigeot 
2712*3f2dd94aSFrançois Tigeot 	/*
2713*3f2dd94aSFrançois Tigeot 	 * Disable PW1 (PG1).
2714*3f2dd94aSFrançois Tigeot 	 * Note that even though the driver's request is removed power well 1
2715*3f2dd94aSFrançois Tigeot 	 * may stay enabled after this due to DMC's own request on it.
2716*3f2dd94aSFrançois Tigeot 	 */
27178621f407SFrançois Tigeot 	mutex_lock(&power_domains->lock);
27188621f407SFrançois Tigeot 
27198621f407SFrançois Tigeot 	well = lookup_power_well(dev_priv, SKL_DISP_PW_1);
27208621f407SFrançois Tigeot 	intel_power_well_disable(dev_priv, well);
27218621f407SFrançois Tigeot 
2722aee94f86SFrançois Tigeot 	mutex_unlock(&power_domains->lock);
2723*3f2dd94aSFrançois Tigeot 
2724*3f2dd94aSFrançois Tigeot 	usleep_range(10, 30);		/* 10 us delay per Bspec */
2725*3f2dd94aSFrançois Tigeot }
2726*3f2dd94aSFrançois Tigeot 
2727*3f2dd94aSFrançois Tigeot enum {
2728*3f2dd94aSFrançois Tigeot 	PROCMON_0_85V_DOT_0,
2729*3f2dd94aSFrançois Tigeot 	PROCMON_0_95V_DOT_0,
2730*3f2dd94aSFrançois Tigeot 	PROCMON_0_95V_DOT_1,
2731*3f2dd94aSFrançois Tigeot 	PROCMON_1_05V_DOT_0,
2732*3f2dd94aSFrançois Tigeot 	PROCMON_1_05V_DOT_1,
2733*3f2dd94aSFrançois Tigeot };
2734*3f2dd94aSFrançois Tigeot 
2735*3f2dd94aSFrançois Tigeot static const struct cnl_procmon {
2736*3f2dd94aSFrançois Tigeot 	u32 dw1, dw9, dw10;
2737*3f2dd94aSFrançois Tigeot } cnl_procmon_values[] = {
2738*3f2dd94aSFrançois Tigeot 	[PROCMON_0_85V_DOT_0] =
2739*3f2dd94aSFrançois Tigeot 		{ .dw1 = 0x00000000, .dw9 = 0x62AB67BB, .dw10 = 0x51914F96, },
2740*3f2dd94aSFrançois Tigeot 	[PROCMON_0_95V_DOT_0] =
2741*3f2dd94aSFrançois Tigeot 		{ .dw1 = 0x00000000, .dw9 = 0x86E172C7, .dw10 = 0x77CA5EAB, },
2742*3f2dd94aSFrançois Tigeot 	[PROCMON_0_95V_DOT_1] =
2743*3f2dd94aSFrançois Tigeot 		{ .dw1 = 0x00000000, .dw9 = 0x93F87FE1, .dw10 = 0x8AE871C5, },
2744*3f2dd94aSFrançois Tigeot 	[PROCMON_1_05V_DOT_0] =
2745*3f2dd94aSFrançois Tigeot 		{ .dw1 = 0x00000000, .dw9 = 0x98FA82DD, .dw10 = 0x89E46DC1, },
2746*3f2dd94aSFrançois Tigeot 	[PROCMON_1_05V_DOT_1] =
2747*3f2dd94aSFrançois Tigeot 		{ .dw1 = 0x00440000, .dw9 = 0x9A00AB25, .dw10 = 0x8AE38FF1, },
2748*3f2dd94aSFrançois Tigeot };
2749*3f2dd94aSFrançois Tigeot 
cnl_set_procmon_ref_values(struct drm_i915_private * dev_priv)2750*3f2dd94aSFrançois Tigeot static void cnl_set_procmon_ref_values(struct drm_i915_private *dev_priv)
2751*3f2dd94aSFrançois Tigeot {
2752*3f2dd94aSFrançois Tigeot 	const struct cnl_procmon *procmon;
2753*3f2dd94aSFrançois Tigeot 	u32 val;
2754*3f2dd94aSFrançois Tigeot 
2755*3f2dd94aSFrançois Tigeot 	val = I915_READ(CNL_PORT_COMP_DW3);
2756*3f2dd94aSFrançois Tigeot 	switch (val & (PROCESS_INFO_MASK | VOLTAGE_INFO_MASK)) {
2757*3f2dd94aSFrançois Tigeot 	default:
2758*3f2dd94aSFrançois Tigeot 		MISSING_CASE(val);
2759*3f2dd94aSFrançois Tigeot 	case VOLTAGE_INFO_0_85V | PROCESS_INFO_DOT_0:
2760*3f2dd94aSFrançois Tigeot 		procmon = &cnl_procmon_values[PROCMON_0_85V_DOT_0];
2761*3f2dd94aSFrançois Tigeot 		break;
2762*3f2dd94aSFrançois Tigeot 	case VOLTAGE_INFO_0_95V | PROCESS_INFO_DOT_0:
2763*3f2dd94aSFrançois Tigeot 		procmon = &cnl_procmon_values[PROCMON_0_95V_DOT_0];
2764*3f2dd94aSFrançois Tigeot 		break;
2765*3f2dd94aSFrançois Tigeot 	case VOLTAGE_INFO_0_95V | PROCESS_INFO_DOT_1:
2766*3f2dd94aSFrançois Tigeot 		procmon = &cnl_procmon_values[PROCMON_0_95V_DOT_1];
2767*3f2dd94aSFrançois Tigeot 		break;
2768*3f2dd94aSFrançois Tigeot 	case VOLTAGE_INFO_1_05V | PROCESS_INFO_DOT_0:
2769*3f2dd94aSFrançois Tigeot 		procmon = &cnl_procmon_values[PROCMON_1_05V_DOT_0];
2770*3f2dd94aSFrançois Tigeot 		break;
2771*3f2dd94aSFrançois Tigeot 	case VOLTAGE_INFO_1_05V | PROCESS_INFO_DOT_1:
2772*3f2dd94aSFrançois Tigeot 		procmon = &cnl_procmon_values[PROCMON_1_05V_DOT_1];
2773*3f2dd94aSFrançois Tigeot 		break;
2774*3f2dd94aSFrançois Tigeot 	}
2775*3f2dd94aSFrançois Tigeot 
2776*3f2dd94aSFrançois Tigeot 	val = I915_READ(CNL_PORT_COMP_DW1);
2777*3f2dd94aSFrançois Tigeot 	val &= ~((0xff << 16) | 0xff);
2778*3f2dd94aSFrançois Tigeot 	val |= procmon->dw1;
2779*3f2dd94aSFrançois Tigeot 	I915_WRITE(CNL_PORT_COMP_DW1, val);
2780*3f2dd94aSFrançois Tigeot 
2781*3f2dd94aSFrançois Tigeot 	I915_WRITE(CNL_PORT_COMP_DW9, procmon->dw9);
2782*3f2dd94aSFrançois Tigeot 	I915_WRITE(CNL_PORT_COMP_DW10, procmon->dw10);
2783*3f2dd94aSFrançois Tigeot }
2784*3f2dd94aSFrançois Tigeot 
cnl_display_core_init(struct drm_i915_private * dev_priv,bool resume)2785*3f2dd94aSFrançois Tigeot static void cnl_display_core_init(struct drm_i915_private *dev_priv, bool resume)
2786*3f2dd94aSFrançois Tigeot {
2787*3f2dd94aSFrançois Tigeot 	struct i915_power_domains *power_domains = &dev_priv->power_domains;
2788*3f2dd94aSFrançois Tigeot 	struct i915_power_well *well;
2789*3f2dd94aSFrançois Tigeot 	u32 val;
2790*3f2dd94aSFrançois Tigeot 
2791*3f2dd94aSFrançois Tigeot 	gen9_set_dc_state(dev_priv, DC_STATE_DISABLE);
2792*3f2dd94aSFrançois Tigeot 
2793*3f2dd94aSFrançois Tigeot 	/* 1. Enable PCH Reset Handshake */
2794*3f2dd94aSFrançois Tigeot 	val = I915_READ(HSW_NDE_RSTWRN_OPT);
2795*3f2dd94aSFrançois Tigeot 	val |= RESET_PCH_HANDSHAKE_ENABLE;
2796*3f2dd94aSFrançois Tigeot 	I915_WRITE(HSW_NDE_RSTWRN_OPT, val);
2797*3f2dd94aSFrançois Tigeot 
2798*3f2dd94aSFrançois Tigeot 	/* 2. Enable Comp */
2799*3f2dd94aSFrançois Tigeot 	val = I915_READ(CHICKEN_MISC_2);
2800*3f2dd94aSFrançois Tigeot 	val &= ~CNL_COMP_PWR_DOWN;
2801*3f2dd94aSFrançois Tigeot 	I915_WRITE(CHICKEN_MISC_2, val);
2802*3f2dd94aSFrançois Tigeot 
2803*3f2dd94aSFrançois Tigeot 	cnl_set_procmon_ref_values(dev_priv);
2804*3f2dd94aSFrançois Tigeot 
2805*3f2dd94aSFrançois Tigeot 	val = I915_READ(CNL_PORT_COMP_DW0);
2806*3f2dd94aSFrançois Tigeot 	val |= COMP_INIT;
2807*3f2dd94aSFrançois Tigeot 	I915_WRITE(CNL_PORT_COMP_DW0, val);
2808*3f2dd94aSFrançois Tigeot 
2809*3f2dd94aSFrançois Tigeot 	/* 3. */
2810*3f2dd94aSFrançois Tigeot 	val = I915_READ(CNL_PORT_CL1CM_DW5);
2811*3f2dd94aSFrançois Tigeot 	val |= CL_POWER_DOWN_ENABLE;
2812*3f2dd94aSFrançois Tigeot 	I915_WRITE(CNL_PORT_CL1CM_DW5, val);
2813*3f2dd94aSFrançois Tigeot 
2814*3f2dd94aSFrançois Tigeot 	/*
2815*3f2dd94aSFrançois Tigeot 	 * 4. Enable Power Well 1 (PG1).
2816*3f2dd94aSFrançois Tigeot 	 *    The AUX IO power wells will be enabled on demand.
2817*3f2dd94aSFrançois Tigeot 	 */
2818*3f2dd94aSFrançois Tigeot 	mutex_lock(&power_domains->lock);
2819*3f2dd94aSFrançois Tigeot 	well = lookup_power_well(dev_priv, SKL_DISP_PW_1);
2820*3f2dd94aSFrançois Tigeot 	intel_power_well_enable(dev_priv, well);
2821*3f2dd94aSFrançois Tigeot 	mutex_unlock(&power_domains->lock);
2822*3f2dd94aSFrançois Tigeot 
2823*3f2dd94aSFrançois Tigeot 	/* 5. Enable CD clock */
2824*3f2dd94aSFrançois Tigeot 	cnl_init_cdclk(dev_priv);
2825*3f2dd94aSFrançois Tigeot 
2826*3f2dd94aSFrançois Tigeot 	/* 6. Enable DBUF */
2827*3f2dd94aSFrançois Tigeot 	gen9_dbuf_enable(dev_priv);
2828*3f2dd94aSFrançois Tigeot 
2829*3f2dd94aSFrançois Tigeot 	if (resume && dev_priv->csr.dmc_payload)
2830*3f2dd94aSFrançois Tigeot 		intel_csr_load_program(dev_priv);
2831*3f2dd94aSFrançois Tigeot }
2832*3f2dd94aSFrançois Tigeot 
cnl_display_core_uninit(struct drm_i915_private * dev_priv)2833*3f2dd94aSFrançois Tigeot static void cnl_display_core_uninit(struct drm_i915_private *dev_priv)
2834*3f2dd94aSFrançois Tigeot {
2835*3f2dd94aSFrançois Tigeot 	struct i915_power_domains *power_domains = &dev_priv->power_domains;
2836*3f2dd94aSFrançois Tigeot 	struct i915_power_well *well;
2837*3f2dd94aSFrançois Tigeot 	u32 val;
2838*3f2dd94aSFrançois Tigeot 
2839*3f2dd94aSFrançois Tigeot 	gen9_set_dc_state(dev_priv, DC_STATE_DISABLE);
2840*3f2dd94aSFrançois Tigeot 
2841*3f2dd94aSFrançois Tigeot 	/* 1. Disable all display engine functions -> aready done */
2842*3f2dd94aSFrançois Tigeot 
2843*3f2dd94aSFrançois Tigeot 	/* 2. Disable DBUF */
2844*3f2dd94aSFrançois Tigeot 	gen9_dbuf_disable(dev_priv);
2845*3f2dd94aSFrançois Tigeot 
2846*3f2dd94aSFrançois Tigeot 	/* 3. Disable CD clock */
2847*3f2dd94aSFrançois Tigeot 	cnl_uninit_cdclk(dev_priv);
2848*3f2dd94aSFrançois Tigeot 
2849*3f2dd94aSFrançois Tigeot 	/*
2850*3f2dd94aSFrançois Tigeot 	 * 4. Disable Power Well 1 (PG1).
2851*3f2dd94aSFrançois Tigeot 	 *    The AUX IO power wells are toggled on demand, so they are already
2852*3f2dd94aSFrançois Tigeot 	 *    disabled at this point.
2853*3f2dd94aSFrançois Tigeot 	 */
2854*3f2dd94aSFrançois Tigeot 	mutex_lock(&power_domains->lock);
2855*3f2dd94aSFrançois Tigeot 	well = lookup_power_well(dev_priv, SKL_DISP_PW_1);
2856*3f2dd94aSFrançois Tigeot 	intel_power_well_disable(dev_priv, well);
2857*3f2dd94aSFrançois Tigeot 	mutex_unlock(&power_domains->lock);
2858*3f2dd94aSFrançois Tigeot 
2859*3f2dd94aSFrançois Tigeot 	usleep_range(10, 30);		/* 10 us delay per Bspec */
2860*3f2dd94aSFrançois Tigeot 
2861*3f2dd94aSFrançois Tigeot 	/* 5. Disable Comp */
2862*3f2dd94aSFrançois Tigeot 	val = I915_READ(CHICKEN_MISC_2);
2863*3f2dd94aSFrançois Tigeot 	val |= CNL_COMP_PWR_DOWN;
2864*3f2dd94aSFrançois Tigeot 	I915_WRITE(CHICKEN_MISC_2, val);
2865aee94f86SFrançois Tigeot }
2866aee94f86SFrançois Tigeot 
chv_phy_control_init(struct drm_i915_private * dev_priv)286719c468b4SFrançois Tigeot static void chv_phy_control_init(struct drm_i915_private *dev_priv)
286819c468b4SFrançois Tigeot {
286919c468b4SFrançois Tigeot 	struct i915_power_well *cmn_bc =
287019c468b4SFrançois Tigeot 		lookup_power_well(dev_priv, PUNIT_POWER_WELL_DPIO_CMN_BC);
287119c468b4SFrançois Tigeot 	struct i915_power_well *cmn_d =
287219c468b4SFrançois Tigeot 		lookup_power_well(dev_priv, PUNIT_POWER_WELL_DPIO_CMN_D);
287319c468b4SFrançois Tigeot 
287419c468b4SFrançois Tigeot 	/*
287519c468b4SFrançois Tigeot 	 * DISPLAY_PHY_CONTROL can get corrupted if read. As a
287619c468b4SFrançois Tigeot 	 * workaround never ever read DISPLAY_PHY_CONTROL, and
287719c468b4SFrançois Tigeot 	 * instead maintain a shadow copy ourselves. Use the actual
2878352ff8bdSFrançois Tigeot 	 * power well state and lane status to reconstruct the
2879352ff8bdSFrançois Tigeot 	 * expected initial value.
288019c468b4SFrançois Tigeot 	 */
288119c468b4SFrançois Tigeot 	dev_priv->chv_phy_control =
288219c468b4SFrançois Tigeot 		PHY_LDO_SEQ_DELAY(PHY_LDO_DELAY_600NS, DPIO_PHY0) |
288319c468b4SFrançois Tigeot 		PHY_LDO_SEQ_DELAY(PHY_LDO_DELAY_600NS, DPIO_PHY1) |
2884352ff8bdSFrançois Tigeot 		PHY_CH_POWER_MODE(PHY_CH_DEEP_PSR, DPIO_PHY0, DPIO_CH0) |
2885352ff8bdSFrançois Tigeot 		PHY_CH_POWER_MODE(PHY_CH_DEEP_PSR, DPIO_PHY0, DPIO_CH1) |
2886352ff8bdSFrançois Tigeot 		PHY_CH_POWER_MODE(PHY_CH_DEEP_PSR, DPIO_PHY1, DPIO_CH0);
2887352ff8bdSFrançois Tigeot 
2888352ff8bdSFrançois Tigeot 	/*
2889352ff8bdSFrançois Tigeot 	 * If all lanes are disabled we leave the override disabled
2890352ff8bdSFrançois Tigeot 	 * with all power down bits cleared to match the state we
2891352ff8bdSFrançois Tigeot 	 * would use after disabling the port. Otherwise enable the
2892352ff8bdSFrançois Tigeot 	 * override and set the lane powerdown bits accding to the
2893352ff8bdSFrançois Tigeot 	 * current lane status.
2894352ff8bdSFrançois Tigeot 	 */
2895352ff8bdSFrançois Tigeot 	if (cmn_bc->ops->is_enabled(dev_priv, cmn_bc)) {
2896352ff8bdSFrançois Tigeot 		uint32_t status = I915_READ(DPLL(PIPE_A));
2897352ff8bdSFrançois Tigeot 		unsigned int mask;
2898352ff8bdSFrançois Tigeot 
2899352ff8bdSFrançois Tigeot 		mask = status & DPLL_PORTB_READY_MASK;
2900352ff8bdSFrançois Tigeot 		if (mask == 0xf)
2901352ff8bdSFrançois Tigeot 			mask = 0x0;
2902352ff8bdSFrançois Tigeot 		else
2903352ff8bdSFrançois Tigeot 			dev_priv->chv_phy_control |=
2904352ff8bdSFrançois Tigeot 				PHY_CH_POWER_DOWN_OVRD_EN(DPIO_PHY0, DPIO_CH0);
2905352ff8bdSFrançois Tigeot 
2906352ff8bdSFrançois Tigeot 		dev_priv->chv_phy_control |=
2907352ff8bdSFrançois Tigeot 			PHY_CH_POWER_DOWN_OVRD(mask, DPIO_PHY0, DPIO_CH0);
2908352ff8bdSFrançois Tigeot 
2909352ff8bdSFrançois Tigeot 		mask = (status & DPLL_PORTC_READY_MASK) >> 4;
2910352ff8bdSFrançois Tigeot 		if (mask == 0xf)
2911352ff8bdSFrançois Tigeot 			mask = 0x0;
2912352ff8bdSFrançois Tigeot 		else
2913352ff8bdSFrançois Tigeot 			dev_priv->chv_phy_control |=
2914352ff8bdSFrançois Tigeot 				PHY_CH_POWER_DOWN_OVRD_EN(DPIO_PHY0, DPIO_CH1);
2915352ff8bdSFrançois Tigeot 
2916352ff8bdSFrançois Tigeot 		dev_priv->chv_phy_control |=
2917352ff8bdSFrançois Tigeot 			PHY_CH_POWER_DOWN_OVRD(mask, DPIO_PHY0, DPIO_CH1);
2918352ff8bdSFrançois Tigeot 
291919c468b4SFrançois Tigeot 		dev_priv->chv_phy_control |= PHY_COM_LANE_RESET_DEASSERT(DPIO_PHY0);
2920352ff8bdSFrançois Tigeot 
2921352ff8bdSFrançois Tigeot 		dev_priv->chv_phy_assert[DPIO_PHY0] = false;
2922352ff8bdSFrançois Tigeot 	} else {
2923352ff8bdSFrançois Tigeot 		dev_priv->chv_phy_assert[DPIO_PHY0] = true;
2924352ff8bdSFrançois Tigeot 	}
2925352ff8bdSFrançois Tigeot 
2926352ff8bdSFrançois Tigeot 	if (cmn_d->ops->is_enabled(dev_priv, cmn_d)) {
2927352ff8bdSFrançois Tigeot 		uint32_t status = I915_READ(DPIO_PHY_STATUS);
2928352ff8bdSFrançois Tigeot 		unsigned int mask;
2929352ff8bdSFrançois Tigeot 
2930352ff8bdSFrançois Tigeot 		mask = status & DPLL_PORTD_READY_MASK;
2931352ff8bdSFrançois Tigeot 
2932352ff8bdSFrançois Tigeot 		if (mask == 0xf)
2933352ff8bdSFrançois Tigeot 			mask = 0x0;
2934352ff8bdSFrançois Tigeot 		else
2935352ff8bdSFrançois Tigeot 			dev_priv->chv_phy_control |=
2936352ff8bdSFrançois Tigeot 				PHY_CH_POWER_DOWN_OVRD_EN(DPIO_PHY1, DPIO_CH0);
2937352ff8bdSFrançois Tigeot 
2938352ff8bdSFrançois Tigeot 		dev_priv->chv_phy_control |=
2939352ff8bdSFrançois Tigeot 			PHY_CH_POWER_DOWN_OVRD(mask, DPIO_PHY1, DPIO_CH0);
2940352ff8bdSFrançois Tigeot 
294119c468b4SFrançois Tigeot 		dev_priv->chv_phy_control |= PHY_COM_LANE_RESET_DEASSERT(DPIO_PHY1);
2942352ff8bdSFrançois Tigeot 
2943352ff8bdSFrançois Tigeot 		dev_priv->chv_phy_assert[DPIO_PHY1] = false;
2944352ff8bdSFrançois Tigeot 	} else {
2945352ff8bdSFrançois Tigeot 		dev_priv->chv_phy_assert[DPIO_PHY1] = true;
2946352ff8bdSFrançois Tigeot 	}
2947352ff8bdSFrançois Tigeot 
2948352ff8bdSFrançois Tigeot 	I915_WRITE(DISPLAY_PHY_CONTROL, dev_priv->chv_phy_control);
2949352ff8bdSFrançois Tigeot 
2950352ff8bdSFrançois Tigeot 	DRM_DEBUG_KMS("Initial PHY_CONTROL=0x%08x\n",
2951352ff8bdSFrançois Tigeot 		      dev_priv->chv_phy_control);
295219c468b4SFrançois Tigeot }
295319c468b4SFrançois Tigeot 
vlv_cmnlane_wa(struct drm_i915_private * dev_priv)29542c9916cdSFrançois Tigeot static void vlv_cmnlane_wa(struct drm_i915_private *dev_priv)
29552c9916cdSFrançois Tigeot {
29562c9916cdSFrançois Tigeot 	struct i915_power_well *cmn =
29572c9916cdSFrançois Tigeot 		lookup_power_well(dev_priv, PUNIT_POWER_WELL_DPIO_CMN_BC);
29582c9916cdSFrançois Tigeot 	struct i915_power_well *disp2d =
29592c9916cdSFrançois Tigeot 		lookup_power_well(dev_priv, PUNIT_POWER_WELL_DISP2D);
29602c9916cdSFrançois Tigeot 
29612c9916cdSFrançois Tigeot 	/* If the display might be already active skip this */
29622c9916cdSFrançois Tigeot 	if (cmn->ops->is_enabled(dev_priv, cmn) &&
29632c9916cdSFrançois Tigeot 	    disp2d->ops->is_enabled(dev_priv, disp2d) &&
29642c9916cdSFrançois Tigeot 	    I915_READ(DPIO_CTL) & DPIO_CMNRST)
29652c9916cdSFrançois Tigeot 		return;
29662c9916cdSFrançois Tigeot 
29672c9916cdSFrançois Tigeot 	DRM_DEBUG_KMS("toggling display PHY side reset\n");
29682c9916cdSFrançois Tigeot 
29692c9916cdSFrançois Tigeot 	/* cmnlane needs DPLL registers */
29702c9916cdSFrançois Tigeot 	disp2d->ops->enable(dev_priv, disp2d);
29712c9916cdSFrançois Tigeot 
29722c9916cdSFrançois Tigeot 	/*
29732c9916cdSFrançois Tigeot 	 * From VLV2A0_DP_eDP_HDMI_DPIO_driver_vbios_notes_11.docx:
29742c9916cdSFrançois Tigeot 	 * Need to assert and de-assert PHY SB reset by gating the
29752c9916cdSFrançois Tigeot 	 * common lane power, then un-gating it.
29762c9916cdSFrançois Tigeot 	 * Simply ungating isn't enough to reset the PHY enough to get
29772c9916cdSFrançois Tigeot 	 * ports and lanes running.
29782c9916cdSFrançois Tigeot 	 */
29792c9916cdSFrançois Tigeot 	cmn->ops->disable(dev_priv, cmn);
29802c9916cdSFrançois Tigeot }
29812c9916cdSFrançois Tigeot 
29822c9916cdSFrançois Tigeot /**
29832c9916cdSFrançois Tigeot  * intel_power_domains_init_hw - initialize hardware power domain state
29842c9916cdSFrançois Tigeot  * @dev_priv: i915 device instance
29851487f786SFrançois Tigeot  * @resume: Called from resume code paths or not
29862c9916cdSFrançois Tigeot  *
29872c9916cdSFrançois Tigeot  * This function initializes the hardware power domain state and enables all
2988a85cb24fSFrançois Tigeot  * power wells belonging to the INIT power domain. Power wells in other
2989a85cb24fSFrançois Tigeot  * domains (and not in the INIT domain) are referenced or disabled during the
2990a85cb24fSFrançois Tigeot  * modeset state HW readout. After that the reference count of each power well
2991a85cb24fSFrançois Tigeot  * must match its HW enabled state, see intel_power_domains_verify_state().
29922c9916cdSFrançois Tigeot  */
intel_power_domains_init_hw(struct drm_i915_private * dev_priv,bool resume)2993aee94f86SFrançois Tigeot void intel_power_domains_init_hw(struct drm_i915_private *dev_priv, bool resume)
29942c9916cdSFrançois Tigeot {
29952c9916cdSFrançois Tigeot 	struct i915_power_domains *power_domains = &dev_priv->power_domains;
29962c9916cdSFrançois Tigeot 
29972c9916cdSFrançois Tigeot 	power_domains->initializing = true;
29982c9916cdSFrançois Tigeot 
2999*3f2dd94aSFrançois Tigeot 	if (IS_CANNONLAKE(dev_priv)) {
3000*3f2dd94aSFrançois Tigeot 		cnl_display_core_init(dev_priv, resume);
3001*3f2dd94aSFrançois Tigeot 	} else if (IS_GEN9_BC(dev_priv)) {
3002aee94f86SFrançois Tigeot 		skl_display_core_init(dev_priv, resume);
3003a85cb24fSFrançois Tigeot 	} else if (IS_GEN9_LP(dev_priv)) {
30048621f407SFrançois Tigeot 		bxt_display_core_init(dev_priv, resume);
30051e12ee3bSFrançois Tigeot 	} else if (IS_CHERRYVIEW(dev_priv)) {
3006352ff8bdSFrançois Tigeot 		mutex_lock(&power_domains->lock);
300719c468b4SFrançois Tigeot 		chv_phy_control_init(dev_priv);
3008352ff8bdSFrançois Tigeot 		mutex_unlock(&power_domains->lock);
30091e12ee3bSFrançois Tigeot 	} else if (IS_VALLEYVIEW(dev_priv)) {
30102c9916cdSFrançois Tigeot 		mutex_lock(&power_domains->lock);
30112c9916cdSFrançois Tigeot 		vlv_cmnlane_wa(dev_priv);
30122c9916cdSFrançois Tigeot 		mutex_unlock(&power_domains->lock);
30132c9916cdSFrançois Tigeot 	}
30142c9916cdSFrançois Tigeot 
30152c9916cdSFrançois Tigeot 	/* For now, we need the power well to be always enabled. */
30162c9916cdSFrançois Tigeot 	intel_display_set_init_power(dev_priv, true);
3017aee94f86SFrançois Tigeot 	/* Disable power support if the user asked so. */
3018*3f2dd94aSFrançois Tigeot 	if (!i915_modparams.disable_power_well)
3019aee94f86SFrançois Tigeot 		intel_display_power_get(dev_priv, POWER_DOMAIN_INIT);
3020aee94f86SFrançois Tigeot 	intel_power_domains_sync_hw(dev_priv);
30212c9916cdSFrançois Tigeot 	power_domains->initializing = false;
30222c9916cdSFrançois Tigeot }
30232c9916cdSFrançois Tigeot 
30242c9916cdSFrançois Tigeot /**
3025aee94f86SFrançois Tigeot  * intel_power_domains_suspend - suspend power domain state
3026aee94f86SFrançois Tigeot  * @dev_priv: i915 device instance
3027aee94f86SFrançois Tigeot  *
3028aee94f86SFrançois Tigeot  * This function prepares the hardware power domain state before entering
3029aee94f86SFrançois Tigeot  * system suspend. It must be paired with intel_power_domains_init_hw().
3030aee94f86SFrançois Tigeot  */
intel_power_domains_suspend(struct drm_i915_private * dev_priv)3031aee94f86SFrançois Tigeot void intel_power_domains_suspend(struct drm_i915_private *dev_priv)
3032aee94f86SFrançois Tigeot {
3033aee94f86SFrançois Tigeot 	/*
3034aee94f86SFrançois Tigeot 	 * Even if power well support was disabled we still want to disable
3035aee94f86SFrançois Tigeot 	 * power wells while we are system suspended.
3036aee94f86SFrançois Tigeot 	 */
3037*3f2dd94aSFrançois Tigeot 	if (!i915_modparams.disable_power_well)
3038aee94f86SFrançois Tigeot 		intel_display_power_put(dev_priv, POWER_DOMAIN_INIT);
3039aee94f86SFrançois Tigeot 
3040*3f2dd94aSFrançois Tigeot 	if (IS_CANNONLAKE(dev_priv))
3041*3f2dd94aSFrançois Tigeot 		cnl_display_core_uninit(dev_priv);
3042*3f2dd94aSFrançois Tigeot 	else if (IS_GEN9_BC(dev_priv))
3043aee94f86SFrançois Tigeot 		skl_display_core_uninit(dev_priv);
3044a85cb24fSFrançois Tigeot 	else if (IS_GEN9_LP(dev_priv))
30458621f407SFrançois Tigeot 		bxt_display_core_uninit(dev_priv);
3046aee94f86SFrançois Tigeot }
3047aee94f86SFrançois Tigeot 
intel_power_domains_dump_info(struct drm_i915_private * dev_priv)3048a85cb24fSFrançois Tigeot static void intel_power_domains_dump_info(struct drm_i915_private *dev_priv)
3049a85cb24fSFrançois Tigeot {
3050a85cb24fSFrançois Tigeot 	struct i915_power_domains *power_domains = &dev_priv->power_domains;
3051a85cb24fSFrançois Tigeot 	struct i915_power_well *power_well;
3052a85cb24fSFrançois Tigeot 
3053a85cb24fSFrançois Tigeot 	for_each_power_well(dev_priv, power_well) {
3054a85cb24fSFrançois Tigeot 		enum intel_display_power_domain domain;
3055a85cb24fSFrançois Tigeot 
3056a85cb24fSFrançois Tigeot 		DRM_DEBUG_DRIVER("%-25s %d\n",
3057a85cb24fSFrançois Tigeot 				 power_well->name, power_well->count);
3058a85cb24fSFrançois Tigeot 
3059a85cb24fSFrançois Tigeot 		for_each_power_domain(domain, power_well->domains)
3060a85cb24fSFrançois Tigeot 			DRM_DEBUG_DRIVER("  %-23s %d\n",
3061a85cb24fSFrançois Tigeot 					 intel_display_power_domain_str(domain),
3062a85cb24fSFrançois Tigeot 					 power_domains->domain_use_count[domain]);
3063a85cb24fSFrançois Tigeot 	}
3064a85cb24fSFrançois Tigeot }
3065a85cb24fSFrançois Tigeot 
3066a85cb24fSFrançois Tigeot /**
3067a85cb24fSFrançois Tigeot  * intel_power_domains_verify_state - verify the HW/SW state for all power wells
3068a85cb24fSFrançois Tigeot  * @dev_priv: i915 device instance
3069a85cb24fSFrançois Tigeot  *
3070a85cb24fSFrançois Tigeot  * Verify if the reference count of each power well matches its HW enabled
3071a85cb24fSFrançois Tigeot  * state and the total refcount of the domains it belongs to. This must be
3072a85cb24fSFrançois Tigeot  * called after modeset HW state sanitization, which is responsible for
3073a85cb24fSFrançois Tigeot  * acquiring reference counts for any power wells in use and disabling the
3074a85cb24fSFrançois Tigeot  * ones left on by BIOS but not required by any active output.
3075a85cb24fSFrançois Tigeot  */
intel_power_domains_verify_state(struct drm_i915_private * dev_priv)3076a85cb24fSFrançois Tigeot void intel_power_domains_verify_state(struct drm_i915_private *dev_priv)
3077a85cb24fSFrançois Tigeot {
3078a85cb24fSFrançois Tigeot 	struct i915_power_domains *power_domains = &dev_priv->power_domains;
3079a85cb24fSFrançois Tigeot 	struct i915_power_well *power_well;
3080a85cb24fSFrançois Tigeot 	bool dump_domain_info;
3081a85cb24fSFrançois Tigeot 
3082a85cb24fSFrançois Tigeot 	mutex_lock(&power_domains->lock);
3083a85cb24fSFrançois Tigeot 
3084a85cb24fSFrançois Tigeot 	dump_domain_info = false;
3085a85cb24fSFrançois Tigeot 	for_each_power_well(dev_priv, power_well) {
3086a85cb24fSFrançois Tigeot 		enum intel_display_power_domain domain;
3087a85cb24fSFrançois Tigeot 		int domains_count;
3088a85cb24fSFrançois Tigeot 		bool enabled;
3089a85cb24fSFrançois Tigeot 
3090a85cb24fSFrançois Tigeot 		/*
3091a85cb24fSFrançois Tigeot 		 * Power wells not belonging to any domain (like the MISC_IO
3092a85cb24fSFrançois Tigeot 		 * and PW1 power wells) are under FW control, so ignore them,
3093a85cb24fSFrançois Tigeot 		 * since their state can change asynchronously.
3094a85cb24fSFrançois Tigeot 		 */
3095a85cb24fSFrançois Tigeot 		if (!power_well->domains)
3096a85cb24fSFrançois Tigeot 			continue;
3097a85cb24fSFrançois Tigeot 
3098a85cb24fSFrançois Tigeot 		enabled = power_well->ops->is_enabled(dev_priv, power_well);
3099a85cb24fSFrançois Tigeot 		if ((power_well->count || power_well->always_on) != enabled)
3100a85cb24fSFrançois Tigeot 			DRM_ERROR("power well %s state mismatch (refcount %d/enabled %d)",
3101a85cb24fSFrançois Tigeot 				  power_well->name, power_well->count, enabled);
3102a85cb24fSFrançois Tigeot 
3103a85cb24fSFrançois Tigeot 		domains_count = 0;
3104a85cb24fSFrançois Tigeot 		for_each_power_domain(domain, power_well->domains)
3105a85cb24fSFrançois Tigeot 			domains_count += power_domains->domain_use_count[domain];
3106a85cb24fSFrançois Tigeot 
3107a85cb24fSFrançois Tigeot 		if (power_well->count != domains_count) {
3108a85cb24fSFrançois Tigeot 			DRM_ERROR("power well %s refcount/domain refcount mismatch "
3109a85cb24fSFrançois Tigeot 				  "(refcount %d/domains refcount %d)\n",
3110a85cb24fSFrançois Tigeot 				  power_well->name, power_well->count,
3111a85cb24fSFrançois Tigeot 				  domains_count);
3112a85cb24fSFrançois Tigeot 			dump_domain_info = true;
3113a85cb24fSFrançois Tigeot 		}
3114a85cb24fSFrançois Tigeot 	}
3115a85cb24fSFrançois Tigeot 
3116a85cb24fSFrançois Tigeot 	if (dump_domain_info) {
3117a85cb24fSFrançois Tigeot 		static bool dumped;
3118a85cb24fSFrançois Tigeot 
3119a85cb24fSFrançois Tigeot 		if (!dumped) {
3120a85cb24fSFrançois Tigeot 			intel_power_domains_dump_info(dev_priv);
3121a85cb24fSFrançois Tigeot 			dumped = true;
3122a85cb24fSFrançois Tigeot 		}
3123a85cb24fSFrançois Tigeot 	}
3124a85cb24fSFrançois Tigeot 
3125a85cb24fSFrançois Tigeot 	mutex_unlock(&power_domains->lock);
3126a85cb24fSFrançois Tigeot }
3127a85cb24fSFrançois Tigeot 
3128aee94f86SFrançois Tigeot /**
31292c9916cdSFrançois Tigeot  * intel_runtime_pm_get - grab a runtime pm reference
31302c9916cdSFrançois Tigeot  * @dev_priv: i915 device instance
31312c9916cdSFrançois Tigeot  *
31322c9916cdSFrançois Tigeot  * This function grabs a device-level runtime pm reference (mostly used for GEM
31332c9916cdSFrançois Tigeot  * code to ensure the GTT or GT is on) and ensures that it is powered up.
31342c9916cdSFrançois Tigeot  *
31352c9916cdSFrançois Tigeot  * Any runtime pm reference obtained by this function must have a symmetric
31362c9916cdSFrançois Tigeot  * call to intel_runtime_pm_put() to release the reference again.
31372c9916cdSFrançois Tigeot  */
intel_runtime_pm_get(struct drm_i915_private * dev_priv)31382c9916cdSFrançois Tigeot void intel_runtime_pm_get(struct drm_i915_private *dev_priv)
31392c9916cdSFrançois Tigeot {
31401e12ee3bSFrançois Tigeot 	struct pci_dev *pdev = dev_priv->drm.pdev;
31411e12ee3bSFrançois Tigeot 	struct device *kdev = &pdev->dev;
3142a85cb24fSFrançois Tigeot 	int ret;
31432c9916cdSFrançois Tigeot 
3144a85cb24fSFrançois Tigeot 	ret = pm_runtime_get_sync(kdev);
3145a85cb24fSFrançois Tigeot 	WARN_ONCE(ret < 0, "pm_runtime_get_sync() failed: %d\n", ret);
3146aee94f86SFrançois Tigeot 
3147*3f2dd94aSFrançois Tigeot 	atomic_inc(&dev_priv->runtime_pm.wakeref_count);
3148aee94f86SFrançois Tigeot 	assert_rpm_wakelock_held(dev_priv);
3149aee94f86SFrançois Tigeot }
3150aee94f86SFrançois Tigeot 
3151aee94f86SFrançois Tigeot /**
3152aee94f86SFrançois Tigeot  * intel_runtime_pm_get_if_in_use - grab a runtime pm reference if device in use
3153aee94f86SFrançois Tigeot  * @dev_priv: i915 device instance
3154aee94f86SFrançois Tigeot  *
3155aee94f86SFrançois Tigeot  * This function grabs a device-level runtime pm reference if the device is
3156aee94f86SFrançois Tigeot  * already in use and ensures that it is powered up.
3157aee94f86SFrançois Tigeot  *
3158aee94f86SFrançois Tigeot  * Any runtime pm reference obtained by this function must have a symmetric
3159aee94f86SFrançois Tigeot  * call to intel_runtime_pm_put() to release the reference again.
3160aee94f86SFrançois Tigeot  */
intel_runtime_pm_get_if_in_use(struct drm_i915_private * dev_priv)3161aee94f86SFrançois Tigeot bool intel_runtime_pm_get_if_in_use(struct drm_i915_private *dev_priv)
3162aee94f86SFrançois Tigeot {
3163aee94f86SFrançois Tigeot #ifndef __DragonFly__
31641e12ee3bSFrançois Tigeot 	struct pci_dev *pdev = dev_priv->drm.pdev;
31651e12ee3bSFrançois Tigeot 	struct device *kdev = &pdev->dev;
3166aee94f86SFrançois Tigeot 
3167aee94f86SFrançois Tigeot 	if (IS_ENABLED(CONFIG_PM)) {
31681e12ee3bSFrançois Tigeot 		int ret = pm_runtime_get_if_in_use(kdev);
3169aee94f86SFrançois Tigeot 
3170aee94f86SFrançois Tigeot 		/*
3171aee94f86SFrançois Tigeot 		 * In cases runtime PM is disabled by the RPM core and we get
3172aee94f86SFrançois Tigeot 		 * an -EINVAL return value we are not supposed to call this
3173aee94f86SFrançois Tigeot 		 * function, since the power state is undefined. This applies
3174aee94f86SFrançois Tigeot 		 * atm to the late/early system suspend/resume handlers.
3175aee94f86SFrançois Tigeot 		 */
3176a85cb24fSFrançois Tigeot 		WARN_ONCE(ret < 0,
3177a85cb24fSFrançois Tigeot 			  "pm_runtime_get_if_in_use() failed: %d\n", ret);
3178aee94f86SFrançois Tigeot 		if (ret <= 0)
3179aee94f86SFrançois Tigeot 			return false;
3180aee94f86SFrançois Tigeot 	}
3181aee94f86SFrançois Tigeot 
3182*3f2dd94aSFrançois Tigeot 	atomic_inc(&dev_priv->runtime_pm.wakeref_count);
3183aee94f86SFrançois Tigeot 	assert_rpm_wakelock_held(dev_priv);
3184aee94f86SFrançois Tigeot #endif
3185aee94f86SFrançois Tigeot 
3186aee94f86SFrançois Tigeot 	return true;
31872c9916cdSFrançois Tigeot }
31882c9916cdSFrançois Tigeot 
31892c9916cdSFrançois Tigeot /**
31902c9916cdSFrançois Tigeot  * intel_runtime_pm_get_noresume - grab a runtime pm reference
31912c9916cdSFrançois Tigeot  * @dev_priv: i915 device instance
31922c9916cdSFrançois Tigeot  *
31932c9916cdSFrançois Tigeot  * This function grabs a device-level runtime pm reference (mostly used for GEM
31942c9916cdSFrançois Tigeot  * code to ensure the GTT or GT is on).
31952c9916cdSFrançois Tigeot  *
31962c9916cdSFrançois Tigeot  * It will _not_ power up the device but instead only check that it's powered
31972c9916cdSFrançois Tigeot  * on.  Therefore it is only valid to call this functions from contexts where
31982c9916cdSFrançois Tigeot  * the device is known to be powered up and where trying to power it up would
31992c9916cdSFrançois Tigeot  * result in hilarity and deadlocks. That pretty much means only the system
32002c9916cdSFrançois Tigeot  * suspend/resume code where this is used to grab runtime pm references for
32012c9916cdSFrançois Tigeot  * delayed setup down in work items.
32022c9916cdSFrançois Tigeot  *
32032c9916cdSFrançois Tigeot  * Any runtime pm reference obtained by this function must have a symmetric
32042c9916cdSFrançois Tigeot  * call to intel_runtime_pm_put() to release the reference again.
32052c9916cdSFrançois Tigeot  */
intel_runtime_pm_get_noresume(struct drm_i915_private * dev_priv)32062c9916cdSFrançois Tigeot void intel_runtime_pm_get_noresume(struct drm_i915_private *dev_priv)
32072c9916cdSFrançois Tigeot {
32082c9916cdSFrançois Tigeot #if 0
32091e12ee3bSFrançois Tigeot 	struct pci_dev *pdev = dev_priv->drm.pdev;
32101e12ee3bSFrançois Tigeot 	struct device *kdev = &pdev->dev;
32112c9916cdSFrançois Tigeot #endif
32122c9916cdSFrançois Tigeot 
3213aee94f86SFrançois Tigeot 	assert_rpm_wakelock_held(dev_priv);
32142c9916cdSFrançois Tigeot #if 0
32151e12ee3bSFrançois Tigeot 	pm_runtime_get_noresume(kdev);
32162c9916cdSFrançois Tigeot #endif
3217aee94f86SFrançois Tigeot 
3218*3f2dd94aSFrançois Tigeot 	atomic_inc(&dev_priv->runtime_pm.wakeref_count);
32192c9916cdSFrançois Tigeot }
32202c9916cdSFrançois Tigeot 
32212c9916cdSFrançois Tigeot /**
32222c9916cdSFrançois Tigeot  * intel_runtime_pm_put - release a runtime pm reference
32232c9916cdSFrançois Tigeot  * @dev_priv: i915 device instance
32242c9916cdSFrançois Tigeot  *
32252c9916cdSFrançois Tigeot  * This function drops the device-level runtime pm reference obtained by
32262c9916cdSFrançois Tigeot  * intel_runtime_pm_get() and might power down the corresponding
32272c9916cdSFrançois Tigeot  * hardware block right away if this is the last reference.
32282c9916cdSFrançois Tigeot  */
intel_runtime_pm_put(struct drm_i915_private * dev_priv)32292c9916cdSFrançois Tigeot void intel_runtime_pm_put(struct drm_i915_private *dev_priv)
32302c9916cdSFrançois Tigeot {
32311e12ee3bSFrançois Tigeot 	struct pci_dev *pdev = dev_priv->drm.pdev;
32321e12ee3bSFrançois Tigeot 	struct device *kdev = &pdev->dev;
32332c9916cdSFrançois Tigeot 
3234aee94f86SFrançois Tigeot 	assert_rpm_wakelock_held(dev_priv);
3235*3f2dd94aSFrançois Tigeot 	atomic_dec(&dev_priv->runtime_pm.wakeref_count);
32362c9916cdSFrançois Tigeot 
32371e12ee3bSFrançois Tigeot 	pm_runtime_mark_last_busy(kdev);
32381e12ee3bSFrançois Tigeot 	pm_runtime_put_autosuspend(kdev);
32392c9916cdSFrançois Tigeot }
32402c9916cdSFrançois Tigeot 
32412c9916cdSFrançois Tigeot /**
32422c9916cdSFrançois Tigeot  * intel_runtime_pm_enable - enable runtime pm
32432c9916cdSFrançois Tigeot  * @dev_priv: i915 device instance
32442c9916cdSFrançois Tigeot  *
32452c9916cdSFrançois Tigeot  * This function enables runtime pm at the end of the driver load sequence.
32462c9916cdSFrançois Tigeot  *
32472c9916cdSFrançois Tigeot  * Note that this function does currently not enable runtime pm for the
32482c9916cdSFrançois Tigeot  * subordinate display power domains. That is only done on the first modeset
32492c9916cdSFrançois Tigeot  * using intel_display_set_init_power().
32502c9916cdSFrançois Tigeot  */
intel_runtime_pm_enable(struct drm_i915_private * dev_priv)32512c9916cdSFrançois Tigeot void intel_runtime_pm_enable(struct drm_i915_private *dev_priv)
32522c9916cdSFrançois Tigeot {
3253aee94f86SFrançois Tigeot #if 0
32541e12ee3bSFrançois Tigeot 	struct pci_dev *pdev = dev_priv->drm.pdev;
32551e12ee3bSFrançois Tigeot 	struct device *kdev = &pdev->dev;
32562c9916cdSFrançois Tigeot 
32571e12ee3bSFrançois Tigeot 	pm_runtime_set_autosuspend_delay(kdev, 10000); /* 10s */
32581e12ee3bSFrançois Tigeot 	pm_runtime_mark_last_busy(kdev);
32592c9916cdSFrançois Tigeot 
3260aee94f86SFrançois Tigeot 	/*
3261aee94f86SFrançois Tigeot 	 * Take a permanent reference to disable the RPM functionality and drop
3262aee94f86SFrançois Tigeot 	 * it only when unloading the driver. Use the low level get/put helpers,
3263aee94f86SFrançois Tigeot 	 * so the driver's own RPM reference tracking asserts also work on
3264aee94f86SFrançois Tigeot 	 * platforms without RPM support.
3265aee94f86SFrançois Tigeot 	 */
32661e12ee3bSFrançois Tigeot 	if (!HAS_RUNTIME_PM(dev_priv)) {
3267a85cb24fSFrançois Tigeot 		int ret;
3268a85cb24fSFrançois Tigeot 
32691e12ee3bSFrançois Tigeot 		pm_runtime_dont_use_autosuspend(kdev);
3270a85cb24fSFrançois Tigeot 		ret = pm_runtime_get_sync(kdev);
3271a85cb24fSFrançois Tigeot 		WARN(ret < 0, "pm_runtime_get_sync() failed: %d\n", ret);
3272aee94f86SFrançois Tigeot 	} else {
32731e12ee3bSFrançois Tigeot 		pm_runtime_use_autosuspend(kdev);
3274aee94f86SFrançois Tigeot 	}
3275aee94f86SFrançois Tigeot 
3276aee94f86SFrançois Tigeot 	/*
3277aee94f86SFrançois Tigeot 	 * The core calls the driver load handler with an RPM reference held.
3278aee94f86SFrançois Tigeot 	 * We drop that here and will reacquire it during unloading in
3279aee94f86SFrançois Tigeot 	 * intel_power_domains_fini().
3280aee94f86SFrançois Tigeot 	 */
32811e12ee3bSFrançois Tigeot 	pm_runtime_put_autosuspend(kdev);
32822c9916cdSFrançois Tigeot #endif
32832c9916cdSFrançois Tigeot }
3284