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