On Tue, 2014-09-30 at 10:56 +0200, Daniel Vetter wrote:
> Geez is the audio hack ugly.
> 
> Signed-off-by: Daniel Vetter <daniel.vet...@intel.com>

Looks ok, but needs to be rebased on

commit 08524a9ffa396c56ff3fbec9cfd80edd3fa6a058
Author: Satheeshakrishna M <satheeshakrishn...@intel.com>
Date:   Tue Apr 8 15:46:56 2014 +0530

    drm/i915/skl: Restore pipe B/C interrupts

> ---
>  drivers/gpu/drm/i915/Makefile           |    4 +-
>  drivers/gpu/drm/i915/intel_drv.h        |   39 +-
>  drivers/gpu/drm/i915/intel_pm.c         | 1158 ------------------------------
>  drivers/gpu/drm/i915/intel_runtime_pm.c | 1190 
> +++++++++++++++++++++++++++++++
>  4 files changed, 1214 insertions(+), 1177 deletions(-)
>  create mode 100644 drivers/gpu/drm/i915/intel_runtime_pm.c
> 
> diff --git a/drivers/gpu/drm/i915/Makefile b/drivers/gpu/drm/i915/Makefile
> index 2d8317d36e09..3a6bce047f6f 100644
> --- a/drivers/gpu/drm/i915/Makefile
> +++ b/drivers/gpu/drm/i915/Makefile
> @@ -11,7 +11,9 @@ i915-y := i915_drv.o \
>         i915_params.o \
>            i915_suspend.o \
>         i915_sysfs.o \
> -       intel_pm.o
> +       intel_pm.o \
> +       intel_runtime_pm.o
> +
>  i915-$(CONFIG_COMPAT)   += i915_ioc32.o
>  i915-$(CONFIG_DEBUG_FS) += i915_debugfs.o
>  
> diff --git a/drivers/gpu/drm/i915/intel_drv.h 
> b/drivers/gpu/drm/i915/intel_drv.h
> index 617126786819..a963dd870994 100644
> --- a/drivers/gpu/drm/i915/intel_drv.h
> +++ b/drivers/gpu/drm/i915/intel_drv.h
> @@ -1073,6 +1073,27 @@ extern struct drm_display_mode 
> *intel_find_panel_downclock(
>                               struct drm_display_mode *fixed_mode,
>                               struct drm_connector *connector);
>  
> +/* intel_runtime_pm.c */
> +int intel_power_domains_init(struct drm_i915_private *);
> +void intel_power_domains_remove(struct drm_i915_private *);
> +void intel_power_domains_init_hw(struct drm_i915_private *dev_priv);
> +void intel_init_runtime_pm(struct drm_i915_private *dev_priv);
> +void intel_fini_runtime_pm(struct drm_i915_private *dev_priv);
> +
> +bool intel_display_power_enabled(struct drm_i915_private *dev_priv,
> +                              enum intel_display_power_domain domain);
> +bool intel_display_power_enabled_unlocked(struct drm_i915_private *dev_priv,
> +                                       enum intel_display_power_domain 
> domain);
> +void intel_display_power_get(struct drm_i915_private *dev_priv,
> +                          enum intel_display_power_domain domain);
> +void intel_display_power_put(struct drm_i915_private *dev_priv,
> +                          enum intel_display_power_domain domain);
> +void intel_aux_display_runtime_get(struct drm_i915_private *dev_priv);
> +void intel_aux_display_runtime_put(struct drm_i915_private *dev_priv);
> +void intel_runtime_pm_get(struct drm_i915_private *dev_priv);
> +void intel_runtime_pm_get_noresume(struct drm_i915_private *dev_priv);
> +void intel_runtime_pm_put(struct drm_i915_private *dev_priv);
> +
>  /* intel_pm.c */
>  void intel_init_clock_gating(struct drm_device *dev);
>  void intel_suspend_hw(struct drm_device *dev);
> @@ -1090,17 +1111,6 @@ bool intel_fbc_enabled(struct drm_device *dev);
>  void intel_update_fbc(struct drm_device *dev);
>  void intel_gpu_ips_init(struct drm_i915_private *dev_priv);
>  void intel_gpu_ips_teardown(void);
> -int intel_power_domains_init(struct drm_i915_private *);
> -void intel_power_domains_remove(struct drm_i915_private *);
> -bool intel_display_power_enabled(struct drm_i915_private *dev_priv,
> -                              enum intel_display_power_domain domain);
> -bool intel_display_power_enabled_unlocked(struct drm_i915_private *dev_priv,
> -                                       enum intel_display_power_domain 
> domain);
> -void intel_display_power_get(struct drm_i915_private *dev_priv,
> -                          enum intel_display_power_domain domain);
> -void intel_display_power_put(struct drm_i915_private *dev_priv,
> -                          enum intel_display_power_domain domain);
> -void intel_power_domains_init_hw(struct drm_i915_private *dev_priv);
>  void intel_init_gt_powersave(struct drm_device *dev);
>  void intel_cleanup_gt_powersave(struct drm_device *dev);
>  void intel_enable_gt_powersave(struct drm_device *dev);
> @@ -1111,13 +1121,6 @@ void ironlake_teardown_rc6(struct drm_device *dev);
>  void gen6_update_ring_freq(struct drm_device *dev);
>  void gen6_rps_idle(struct drm_i915_private *dev_priv);
>  void gen6_rps_boost(struct drm_i915_private *dev_priv);
> -void intel_aux_display_runtime_get(struct drm_i915_private *dev_priv);
> -void intel_aux_display_runtime_put(struct drm_i915_private *dev_priv);
> -void intel_runtime_pm_get(struct drm_i915_private *dev_priv);
> -void intel_runtime_pm_get_noresume(struct drm_i915_private *dev_priv);
> -void intel_runtime_pm_put(struct drm_i915_private *dev_priv);
> -void intel_init_runtime_pm(struct drm_i915_private *dev_priv);
> -void intel_fini_runtime_pm(struct drm_i915_private *dev_priv);
>  void ilk_wm_get_hw_state(struct drm_device *dev);
>  
> 
> diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c
> index 6b416201240f..06c1ea0a7bfd 100644
> --- a/drivers/gpu/drm/i915/intel_pm.c
> +++ b/drivers/gpu/drm/i915/intel_pm.c
> @@ -30,9 +30,6 @@
>  #include "intel_drv.h"
>  #include "../../../platform/x86/intel_ips.h"
>  #include <linux/module.h>
> -#include <linux/vgaarb.h>
> -#include <drm/i915_powerwell.h>
> -#include <linux/pm_runtime.h>
>  
>  /**
>   * RC6 is a special power stage which allows the GPU to enter an very
> @@ -6206,1162 +6203,7 @@ void intel_suspend_hw(struct drm_device *dev)
>               lpt_suspend_hw(dev);
>  }
>  
> -#define for_each_power_well(i, power_well, domain_mask, power_domains)       
> \
> -     for (i = 0;                                                     \
> -          i < (power_domains)->power_well_count &&                   \
> -              ((power_well) = &(power_domains)->power_wells[i]);     \
> -          i++)                                                       \
> -             if ((power_well)->domains & (domain_mask))
>  
> -#define for_each_power_well_rev(i, power_well, domain_mask, power_domains) \
> -     for (i = (power_domains)->power_well_count - 1;                  \
> -          i >= 0 && ((power_well) = &(power_domains)->power_wells[i]);\
> -          i--)                                                        \
> -             if ((power_well)->domains & (domain_mask))
> -
> -/**
> - * We should only use the power well if we explicitly asked the hardware to
> - * enable it, so check if it's enabled and also check if we've requested it 
> to
> - * be enabled.
> - */
> -static bool hsw_power_well_enabled(struct drm_i915_private *dev_priv,
> -                                struct i915_power_well *power_well)
> -{
> -     return I915_READ(HSW_PWR_WELL_DRIVER) ==
> -                  (HSW_PWR_WELL_ENABLE_REQUEST | HSW_PWR_WELL_STATE_ENABLED);
> -}
> -
> -bool intel_display_power_enabled_unlocked(struct drm_i915_private *dev_priv,
> -                                       enum intel_display_power_domain 
> domain)
> -{
> -     struct i915_power_domains *power_domains;
> -     struct i915_power_well *power_well;
> -     bool is_enabled;
> -     int i;
> -
> -     if (dev_priv->pm.suspended)
> -             return false;
> -
> -     power_domains = &dev_priv->power_domains;
> -
> -     is_enabled = true;
> -
> -     for_each_power_well_rev(i, power_well, BIT(domain), power_domains) {
> -             if (power_well->always_on)
> -                     continue;
> -
> -             if (!power_well->hw_enabled) {
> -                     is_enabled = false;
> -                     break;
> -             }
> -     }
> -
> -     return is_enabled;
> -}
> -
> -bool intel_display_power_enabled(struct drm_i915_private *dev_priv,
> -                              enum intel_display_power_domain domain)
> -{
> -     struct i915_power_domains *power_domains;
> -     bool ret;
> -
> -     power_domains = &dev_priv->power_domains;
> -
> -     mutex_lock(&power_domains->lock);
> -     ret = intel_display_power_enabled_unlocked(dev_priv, domain);
> -     mutex_unlock(&power_domains->lock);
> -
> -     return ret;
> -}
> -
> -/*
> - * Starting with Haswell, we have a "Power Down Well" that can be turned off
> - * when not needed anymore. We have 4 registers that can request the power 
> well
> - * to be enabled, and it will only be disabled if none of the registers is
> - * requesting it to be enabled.
> - */
> -static void hsw_power_well_post_enable(struct drm_i915_private *dev_priv)
> -{
> -     struct drm_device *dev = dev_priv->dev;
> -
> -     /*
> -      * After we re-enable the power well, if we touch VGA register 0x3d5
> -      * we'll get unclaimed register interrupts. This stops after we write
> -      * anything to the VGA MSR register. The vgacon module uses this
> -      * register all the time, so if we unbind our driver and, as a
> -      * consequence, bind vgacon, we'll get stuck in an infinite loop at
> -      * console_unlock(). So make here we touch the VGA MSR register, making
> -      * sure vgacon can keep working normally without triggering interrupts
> -      * and error messages.
> -      */
> -     vga_get_uninterruptible(dev->pdev, VGA_RSRC_LEGACY_IO);
> -     outb(inb(VGA_MSR_READ), VGA_MSR_WRITE);
> -     vga_put(dev->pdev, VGA_RSRC_LEGACY_IO);
> -
> -     if (IS_BROADWELL(dev))
> -             gen8_irq_power_well_post_enable(dev_priv);
> -}
> -
> -static void hsw_set_power_well(struct drm_i915_private *dev_priv,
> -                            struct i915_power_well *power_well, bool enable)
> -{
> -     bool is_enabled, enable_requested;
> -     uint32_t tmp;
> -
> -     tmp = I915_READ(HSW_PWR_WELL_DRIVER);
> -     is_enabled = tmp & HSW_PWR_WELL_STATE_ENABLED;
> -     enable_requested = tmp & HSW_PWR_WELL_ENABLE_REQUEST;
> -
> -     if (enable) {
> -             if (!enable_requested)
> -                     I915_WRITE(HSW_PWR_WELL_DRIVER,
> -                                HSW_PWR_WELL_ENABLE_REQUEST);
> -
> -             if (!is_enabled) {
> -                     DRM_DEBUG_KMS("Enabling power well\n");
> -                     if (wait_for((I915_READ(HSW_PWR_WELL_DRIVER) &
> -                                   HSW_PWR_WELL_STATE_ENABLED), 20))
> -                             DRM_ERROR("Timeout enabling power well\n");
> -             }
> -
> -             hsw_power_well_post_enable(dev_priv);
> -     } else {
> -             if (enable_requested) {
> -                     I915_WRITE(HSW_PWR_WELL_DRIVER, 0);
> -                     POSTING_READ(HSW_PWR_WELL_DRIVER);
> -                     DRM_DEBUG_KMS("Requesting to disable the power well\n");
> -             }
> -     }
> -}
> -
> -static void hsw_power_well_sync_hw(struct drm_i915_private *dev_priv,
> -                                struct i915_power_well *power_well)
> -{
> -     hsw_set_power_well(dev_priv, power_well, power_well->count > 0);
> -
> -     /*
> -      * We're taking over the BIOS, so clear any requests made by it since
> -      * the driver is in charge now.
> -      */
> -     if (I915_READ(HSW_PWR_WELL_BIOS) & HSW_PWR_WELL_ENABLE_REQUEST)
> -             I915_WRITE(HSW_PWR_WELL_BIOS, 0);
> -}
> -
> -static void hsw_power_well_enable(struct drm_i915_private *dev_priv,
> -                               struct i915_power_well *power_well)
> -{
> -     hsw_set_power_well(dev_priv, power_well, true);
> -}
> -
> -static void hsw_power_well_disable(struct drm_i915_private *dev_priv,
> -                                struct i915_power_well *power_well)
> -{
> -     hsw_set_power_well(dev_priv, power_well, false);
> -}
> -
> -static void i9xx_always_on_power_well_noop(struct drm_i915_private *dev_priv,
> -                                        struct i915_power_well *power_well)
> -{
> -}
> -
> -static bool i9xx_always_on_power_well_enabled(struct drm_i915_private 
> *dev_priv,
> -                                          struct i915_power_well *power_well)
> -{
> -     return true;
> -}
> -
> -static void vlv_set_power_well(struct drm_i915_private *dev_priv,
> -                            struct i915_power_well *power_well, bool enable)
> -{
> -     enum punit_power_well power_well_id = power_well->data;
> -     u32 mask;
> -     u32 state;
> -     u32 ctrl;
> -
> -     mask = PUNIT_PWRGT_MASK(power_well_id);
> -     state = enable ? PUNIT_PWRGT_PWR_ON(power_well_id) :
> -                      PUNIT_PWRGT_PWR_GATE(power_well_id);
> -
> -     mutex_lock(&dev_priv->rps.hw_lock);
> -
> -#define COND \
> -     ((vlv_punit_read(dev_priv, PUNIT_REG_PWRGT_STATUS) & mask) == state)
> -
> -     if (COND)
> -             goto out;
> -
> -     ctrl = vlv_punit_read(dev_priv, PUNIT_REG_PWRGT_CTRL);
> -     ctrl &= ~mask;
> -     ctrl |= state;
> -     vlv_punit_write(dev_priv, PUNIT_REG_PWRGT_CTRL, ctrl);
> -
> -     if (wait_for(COND, 100))
> -             DRM_ERROR("timout setting power well state %08x (%08x)\n",
> -                       state,
> -                       vlv_punit_read(dev_priv, PUNIT_REG_PWRGT_CTRL));
> -
> -#undef COND
> -
> -out:
> -     mutex_unlock(&dev_priv->rps.hw_lock);
> -}
> -
> -static void vlv_power_well_sync_hw(struct drm_i915_private *dev_priv,
> -                                struct i915_power_well *power_well)
> -{
> -     vlv_set_power_well(dev_priv, power_well, power_well->count > 0);
> -}
> -
> -static void vlv_power_well_enable(struct drm_i915_private *dev_priv,
> -                               struct i915_power_well *power_well)
> -{
> -     vlv_set_power_well(dev_priv, power_well, true);
> -}
> -
> -static void vlv_power_well_disable(struct drm_i915_private *dev_priv,
> -                                struct i915_power_well *power_well)
> -{
> -     vlv_set_power_well(dev_priv, power_well, false);
> -}
> -
> -static bool vlv_power_well_enabled(struct drm_i915_private *dev_priv,
> -                                struct i915_power_well *power_well)
> -{
> -     int power_well_id = power_well->data;
> -     bool enabled = false;
> -     u32 mask;
> -     u32 state;
> -     u32 ctrl;
> -
> -     mask = PUNIT_PWRGT_MASK(power_well_id);
> -     ctrl = PUNIT_PWRGT_PWR_ON(power_well_id);
> -
> -     mutex_lock(&dev_priv->rps.hw_lock);
> -
> -     state = vlv_punit_read(dev_priv, PUNIT_REG_PWRGT_STATUS) & mask;
> -     /*
> -      * We only ever set the power-on and power-gate states, anything
> -      * else is unexpected.
> -      */
> -     WARN_ON(state != PUNIT_PWRGT_PWR_ON(power_well_id) &&
> -             state != PUNIT_PWRGT_PWR_GATE(power_well_id));
> -     if (state == ctrl)
> -             enabled = true;
> -
> -     /*
> -      * A transient state at this point would mean some unexpected party
> -      * is poking at the power controls too.
> -      */
> -     ctrl = vlv_punit_read(dev_priv, PUNIT_REG_PWRGT_CTRL) & mask;
> -     WARN_ON(ctrl != state);
> -
> -     mutex_unlock(&dev_priv->rps.hw_lock);
> -
> -     return enabled;
> -}
> -
> -static void vlv_display_power_well_enable(struct drm_i915_private *dev_priv,
> -                                       struct i915_power_well *power_well)
> -{
> -     WARN_ON_ONCE(power_well->data != PUNIT_POWER_WELL_DISP2D);
> -
> -     vlv_set_power_well(dev_priv, power_well, true);
> -
> -     spin_lock_irq(&dev_priv->irq_lock);
> -     valleyview_enable_display_irqs(dev_priv);
> -     spin_unlock_irq(&dev_priv->irq_lock);
> -
> -     /*
> -      * During driver initialization/resume we can avoid restoring the
> -      * part of the HW/SW state that will be inited anyway explicitly.
> -      */
> -     if (dev_priv->power_domains.initializing)
> -             return;
> -
> -     intel_hpd_init(dev_priv->dev);
> -
> -     i915_redisable_vga_power_on(dev_priv->dev);
> -}
> -
> -static void vlv_display_power_well_disable(struct drm_i915_private *dev_priv,
> -                                        struct i915_power_well *power_well)
> -{
> -     WARN_ON_ONCE(power_well->data != PUNIT_POWER_WELL_DISP2D);
> -
> -     spin_lock_irq(&dev_priv->irq_lock);
> -     valleyview_disable_display_irqs(dev_priv);
> -     spin_unlock_irq(&dev_priv->irq_lock);
> -
> -     vlv_set_power_well(dev_priv, power_well, false);
> -
> -     vlv_power_sequencer_reset(dev_priv);
> -}
> -
> -static void vlv_dpio_cmn_power_well_enable(struct drm_i915_private *dev_priv,
> -                                        struct i915_power_well *power_well)
> -{
> -     WARN_ON_ONCE(power_well->data != PUNIT_POWER_WELL_DPIO_CMN_BC);
> -
> -     /*
> -      * Enable the CRI clock source so we can get at the
> -      * display and the reference clock for VGA
> -      * hotplug / manual detection.
> -      */
> -     I915_WRITE(DPLL(PIPE_B), I915_READ(DPLL(PIPE_B)) |
> -                DPLL_REFA_CLK_ENABLE_VLV | DPLL_INTEGRATED_CRI_CLK_VLV);
> -     udelay(1); /* >10ns for cmnreset, >0ns for sidereset */
> -
> -     vlv_set_power_well(dev_priv, power_well, true);
> -
> -     /*
> -      * From VLV2A0_DP_eDP_DPIO_driver_vbios_notes_10.docx -
> -      *  6.  De-assert cmn_reset/side_reset. Same as VLV X0.
> -      *   a. GUnit 0x2110 bit[0] set to 1 (def 0)
> -      *   b. The other bits such as sfr settings / modesel may all
> -      *      be set to 0.
> -      *
> -      * This should only be done on init and resume from S3 with
> -      * both PLLs disabled, or we risk losing DPIO and PLL
> -      * synchronization.
> -      */
> -     I915_WRITE(DPIO_CTL, I915_READ(DPIO_CTL) | DPIO_CMNRST);
> -}
> -
> -static void vlv_dpio_cmn_power_well_disable(struct drm_i915_private 
> *dev_priv,
> -                                         struct i915_power_well *power_well)
> -{
> -     enum pipe pipe;
> -
> -     WARN_ON_ONCE(power_well->data != PUNIT_POWER_WELL_DPIO_CMN_BC);
> -
> -     for_each_pipe(dev_priv, pipe)
> -             assert_pll_disabled(dev_priv, pipe);
> -
> -     /* Assert common reset */
> -     I915_WRITE(DPIO_CTL, I915_READ(DPIO_CTL) & ~DPIO_CMNRST);
> -
> -     vlv_set_power_well(dev_priv, power_well, false);
> -}
> -
> -static void chv_dpio_cmn_power_well_enable(struct drm_i915_private *dev_priv,
> -                                        struct i915_power_well *power_well)
> -{
> -     enum dpio_phy phy;
> -
> -     WARN_ON_ONCE(power_well->data != PUNIT_POWER_WELL_DPIO_CMN_BC &&
> -                  power_well->data != PUNIT_POWER_WELL_DPIO_CMN_D);
> -
> -     /*
> -      * Enable the CRI clock source so we can get at the
> -      * display and the reference clock for VGA
> -      * hotplug / manual detection.
> -      */
> -     if (power_well->data == PUNIT_POWER_WELL_DPIO_CMN_BC) {
> -             phy = DPIO_PHY0;
> -             I915_WRITE(DPLL(PIPE_B), I915_READ(DPLL(PIPE_B)) |
> -                        DPLL_REFA_CLK_ENABLE_VLV);
> -             I915_WRITE(DPLL(PIPE_B), I915_READ(DPLL(PIPE_B)) |
> -                        DPLL_REFA_CLK_ENABLE_VLV | 
> DPLL_INTEGRATED_CRI_CLK_VLV);
> -     } else {
> -             phy = DPIO_PHY1;
> -             I915_WRITE(DPLL(PIPE_C), I915_READ(DPLL(PIPE_C)) |
> -                        DPLL_REFA_CLK_ENABLE_VLV | 
> DPLL_INTEGRATED_CRI_CLK_VLV);
> -     }
> -     udelay(1); /* >10ns for cmnreset, >0ns for sidereset */
> -     vlv_set_power_well(dev_priv, power_well, true);
> -
> -     /* Poll for phypwrgood signal */
> -     if (wait_for(I915_READ(DISPLAY_PHY_STATUS) & PHY_POWERGOOD(phy), 1))
> -             DRM_ERROR("Display PHY %d is not power up\n", phy);
> -
> -     I915_WRITE(DISPLAY_PHY_CONTROL, I915_READ(DISPLAY_PHY_CONTROL) |
> -                PHY_COM_LANE_RESET_DEASSERT(phy));
> -}
> -
> -static void chv_dpio_cmn_power_well_disable(struct drm_i915_private 
> *dev_priv,
> -                                         struct i915_power_well *power_well)
> -{
> -     enum dpio_phy phy;
> -
> -     WARN_ON_ONCE(power_well->data != PUNIT_POWER_WELL_DPIO_CMN_BC &&
> -                  power_well->data != PUNIT_POWER_WELL_DPIO_CMN_D);
> -
> -     if (power_well->data == PUNIT_POWER_WELL_DPIO_CMN_BC) {
> -             phy = DPIO_PHY0;
> -             assert_pll_disabled(dev_priv, PIPE_A);
> -             assert_pll_disabled(dev_priv, PIPE_B);
> -     } else {
> -             phy = DPIO_PHY1;
> -             assert_pll_disabled(dev_priv, PIPE_C);
> -     }
> -
> -     I915_WRITE(DISPLAY_PHY_CONTROL, I915_READ(DISPLAY_PHY_CONTROL) &
> -                ~PHY_COM_LANE_RESET_DEASSERT(phy));
> -
> -     vlv_set_power_well(dev_priv, power_well, false);
> -}
> -
> -static bool chv_pipe_power_well_enabled(struct drm_i915_private *dev_priv,
> -                                     struct i915_power_well *power_well)
> -{
> -     enum pipe pipe = power_well->data;
> -     bool enabled;
> -     u32 state, ctrl;
> -
> -     mutex_lock(&dev_priv->rps.hw_lock);
> -
> -     state = vlv_punit_read(dev_priv, PUNIT_REG_DSPFREQ) & DP_SSS_MASK(pipe);
> -     /*
> -      * We only ever set the power-on and power-gate states, anything
> -      * else is unexpected.
> -      */
> -     WARN_ON(state != DP_SSS_PWR_ON(pipe) && state != DP_SSS_PWR_GATE(pipe));
> -     enabled = state == DP_SSS_PWR_ON(pipe);
> -
> -     /*
> -      * A transient state at this point would mean some unexpected party
> -      * is poking at the power controls too.
> -      */
> -     ctrl = vlv_punit_read(dev_priv, PUNIT_REG_DSPFREQ) & DP_SSC_MASK(pipe);
> -     WARN_ON(ctrl << 16 != state);
> -
> -     mutex_unlock(&dev_priv->rps.hw_lock);
> -
> -     return enabled;
> -}
> -
> -static void chv_set_pipe_power_well(struct drm_i915_private *dev_priv,
> -                                 struct i915_power_well *power_well,
> -                                 bool enable)
> -{
> -     enum pipe pipe = power_well->data;
> -     u32 state;
> -     u32 ctrl;
> -
> -     state = enable ? DP_SSS_PWR_ON(pipe) : DP_SSS_PWR_GATE(pipe);
> -
> -     mutex_lock(&dev_priv->rps.hw_lock);
> -
> -#define COND \
> -     ((vlv_punit_read(dev_priv, PUNIT_REG_DSPFREQ) & DP_SSS_MASK(pipe)) == 
> state)
> -
> -     if (COND)
> -             goto out;
> -
> -     ctrl = vlv_punit_read(dev_priv, PUNIT_REG_DSPFREQ);
> -     ctrl &= ~DP_SSC_MASK(pipe);
> -     ctrl |= enable ? DP_SSC_PWR_ON(pipe) : DP_SSC_PWR_GATE(pipe);
> -     vlv_punit_write(dev_priv, PUNIT_REG_DSPFREQ, ctrl);
> -
> -     if (wait_for(COND, 100))
> -             DRM_ERROR("timout setting power well state %08x (%08x)\n",
> -                       state,
> -                       vlv_punit_read(dev_priv, PUNIT_REG_DSPFREQ));
> -
> -#undef COND
> -
> -out:
> -     mutex_unlock(&dev_priv->rps.hw_lock);
> -}
> -
> -static void chv_pipe_power_well_sync_hw(struct drm_i915_private *dev_priv,
> -                                     struct i915_power_well *power_well)
> -{
> -     chv_set_pipe_power_well(dev_priv, power_well, power_well->count > 0);
> -}
> -
> -static void chv_pipe_power_well_enable(struct drm_i915_private *dev_priv,
> -                                    struct i915_power_well *power_well)
> -{
> -     WARN_ON_ONCE(power_well->data != PIPE_A &&
> -                  power_well->data != PIPE_B &&
> -                  power_well->data != PIPE_C);
> -
> -     chv_set_pipe_power_well(dev_priv, power_well, true);
> -}
> -
> -static void chv_pipe_power_well_disable(struct drm_i915_private *dev_priv,
> -                                     struct i915_power_well *power_well)
> -{
> -     WARN_ON_ONCE(power_well->data != PIPE_A &&
> -                  power_well->data != PIPE_B &&
> -                  power_well->data != PIPE_C);
> -
> -     chv_set_pipe_power_well(dev_priv, power_well, false);
> -}
> -
> -static void check_power_well_state(struct drm_i915_private *dev_priv,
> -                                struct i915_power_well *power_well)
> -{
> -     bool enabled = power_well->ops->is_enabled(dev_priv, power_well);
> -
> -     if (power_well->always_on || !i915.disable_power_well) {
> -             if (!enabled)
> -                     goto mismatch;
> -
> -             return;
> -     }
> -
> -     if (enabled != (power_well->count > 0))
> -             goto mismatch;
> -
> -     return;
> -
> -mismatch:
> -     WARN(1, "state mismatch for '%s' (always_on %d hw state %d use-count %d 
> disable_power_well %d\n",
> -               power_well->name, power_well->always_on, enabled,
> -               power_well->count, i915.disable_power_well);
> -}
> -
> -void intel_display_power_get(struct drm_i915_private *dev_priv,
> -                          enum intel_display_power_domain domain)
> -{
> -     struct i915_power_domains *power_domains;
> -     struct i915_power_well *power_well;
> -     int i;
> -
> -     intel_runtime_pm_get(dev_priv);
> -
> -     power_domains = &dev_priv->power_domains;
> -
> -     mutex_lock(&power_domains->lock);
> -
> -     for_each_power_well(i, power_well, BIT(domain), power_domains) {
> -             if (!power_well->count++) {
> -                     DRM_DEBUG_KMS("enabling %s\n", power_well->name);
> -                     power_well->ops->enable(dev_priv, power_well);
> -                     power_well->hw_enabled = true;
> -             }
> -
> -             check_power_well_state(dev_priv, power_well);
> -     }
> -
> -     power_domains->domain_use_count[domain]++;
> -
> -     mutex_unlock(&power_domains->lock);
> -}
> -
> -void intel_display_power_put(struct drm_i915_private *dev_priv,
> -                          enum intel_display_power_domain domain)
> -{
> -     struct i915_power_domains *power_domains;
> -     struct i915_power_well *power_well;
> -     int i;
> -
> -     power_domains = &dev_priv->power_domains;
> -
> -     mutex_lock(&power_domains->lock);
> -
> -     WARN_ON(!power_domains->domain_use_count[domain]);
> -     power_domains->domain_use_count[domain]--;
> -
> -     for_each_power_well_rev(i, power_well, BIT(domain), power_domains) {
> -             WARN_ON(!power_well->count);
> -
> -             if (!--power_well->count && i915.disable_power_well) {
> -                     DRM_DEBUG_KMS("disabling %s\n", power_well->name);
> -                     power_well->hw_enabled = false;
> -                     power_well->ops->disable(dev_priv, power_well);
> -             }
> -
> -             check_power_well_state(dev_priv, power_well);
> -     }
> -
> -     mutex_unlock(&power_domains->lock);
> -
> -     intel_runtime_pm_put(dev_priv);
> -}
> -
> -static struct i915_power_domains *hsw_pwr;
> -
> -/* Display audio driver power well request */
> -int i915_request_power_well(void)
> -{
> -     struct drm_i915_private *dev_priv;
> -
> -     if (!hsw_pwr)
> -             return -ENODEV;
> -
> -     dev_priv = container_of(hsw_pwr, struct drm_i915_private,
> -                             power_domains);
> -     intel_display_power_get(dev_priv, POWER_DOMAIN_AUDIO);
> -     return 0;
> -}
> -EXPORT_SYMBOL_GPL(i915_request_power_well);
> -
> -/* Display audio driver power well release */
> -int i915_release_power_well(void)
> -{
> -     struct drm_i915_private *dev_priv;
> -
> -     if (!hsw_pwr)
> -             return -ENODEV;
> -
> -     dev_priv = container_of(hsw_pwr, struct drm_i915_private,
> -                             power_domains);
> -     intel_display_power_put(dev_priv, POWER_DOMAIN_AUDIO);
> -     return 0;
> -}
> -EXPORT_SYMBOL_GPL(i915_release_power_well);
> -
> -/*
> - * Private interface for the audio driver to get CDCLK in kHz.
> - *
> - * Caller must request power well using i915_request_power_well() prior to
> - * making the call.
> - */
> -int i915_get_cdclk_freq(void)
> -{
> -     struct drm_i915_private *dev_priv;
> -
> -     if (!hsw_pwr)
> -             return -ENODEV;
> -
> -     dev_priv = container_of(hsw_pwr, struct drm_i915_private,
> -                             power_domains);
> -
> -     return intel_ddi_get_cdclk_freq(dev_priv);
> -}
> -EXPORT_SYMBOL_GPL(i915_get_cdclk_freq);
> -
> -
> -#define POWER_DOMAIN_MASK (BIT(POWER_DOMAIN_NUM) - 1)
> -
> -#define HSW_ALWAYS_ON_POWER_DOMAINS (                        \
> -     BIT(POWER_DOMAIN_PIPE_A) |                      \
> -     BIT(POWER_DOMAIN_TRANSCODER_EDP) |              \
> -     BIT(POWER_DOMAIN_PORT_DDI_A_2_LANES) |          \
> -     BIT(POWER_DOMAIN_PORT_DDI_A_4_LANES) |          \
> -     BIT(POWER_DOMAIN_PORT_DDI_B_2_LANES) |          \
> -     BIT(POWER_DOMAIN_PORT_DDI_B_4_LANES) |          \
> -     BIT(POWER_DOMAIN_PORT_DDI_C_2_LANES) |          \
> -     BIT(POWER_DOMAIN_PORT_DDI_C_4_LANES) |          \
> -     BIT(POWER_DOMAIN_PORT_DDI_D_2_LANES) |          \
> -     BIT(POWER_DOMAIN_PORT_DDI_D_4_LANES) |          \
> -     BIT(POWER_DOMAIN_PORT_CRT) |                    \
> -     BIT(POWER_DOMAIN_PLLS) |                        \
> -     BIT(POWER_DOMAIN_INIT))
> -#define HSW_DISPLAY_POWER_DOMAINS (                          \
> -     (POWER_DOMAIN_MASK & ~HSW_ALWAYS_ON_POWER_DOMAINS) |    \
> -     BIT(POWER_DOMAIN_INIT))
> -
> -#define BDW_ALWAYS_ON_POWER_DOMAINS (                        \
> -     HSW_ALWAYS_ON_POWER_DOMAINS |                   \
> -     BIT(POWER_DOMAIN_PIPE_A_PANEL_FITTER))
> -#define BDW_DISPLAY_POWER_DOMAINS (                          \
> -     (POWER_DOMAIN_MASK & ~BDW_ALWAYS_ON_POWER_DOMAINS) |    \
> -     BIT(POWER_DOMAIN_INIT))
> -
> -#define VLV_ALWAYS_ON_POWER_DOMAINS  BIT(POWER_DOMAIN_INIT)
> -#define VLV_DISPLAY_POWER_DOMAINS    POWER_DOMAIN_MASK
> -
> -#define VLV_DPIO_CMN_BC_POWER_DOMAINS (              \
> -     BIT(POWER_DOMAIN_PORT_DDI_B_2_LANES) |  \
> -     BIT(POWER_DOMAIN_PORT_DDI_B_4_LANES) |  \
> -     BIT(POWER_DOMAIN_PORT_DDI_C_2_LANES) |  \
> -     BIT(POWER_DOMAIN_PORT_DDI_C_4_LANES) |  \
> -     BIT(POWER_DOMAIN_PORT_CRT) |            \
> -     BIT(POWER_DOMAIN_INIT))
> -
> -#define VLV_DPIO_TX_B_LANES_01_POWER_DOMAINS (       \
> -     BIT(POWER_DOMAIN_PORT_DDI_B_2_LANES) |  \
> -     BIT(POWER_DOMAIN_PORT_DDI_B_4_LANES) |  \
> -     BIT(POWER_DOMAIN_INIT))
> -
> -#define VLV_DPIO_TX_B_LANES_23_POWER_DOMAINS (       \
> -     BIT(POWER_DOMAIN_PORT_DDI_B_4_LANES) |  \
> -     BIT(POWER_DOMAIN_INIT))
> -
> -#define VLV_DPIO_TX_C_LANES_01_POWER_DOMAINS (       \
> -     BIT(POWER_DOMAIN_PORT_DDI_C_2_LANES) |  \
> -     BIT(POWER_DOMAIN_PORT_DDI_C_4_LANES) |  \
> -     BIT(POWER_DOMAIN_INIT))
> -
> -#define VLV_DPIO_TX_C_LANES_23_POWER_DOMAINS (       \
> -     BIT(POWER_DOMAIN_PORT_DDI_C_4_LANES) |  \
> -     BIT(POWER_DOMAIN_INIT))
> -
> -#define CHV_PIPE_A_POWER_DOMAINS (   \
> -     BIT(POWER_DOMAIN_PIPE_A) |      \
> -     BIT(POWER_DOMAIN_INIT))
> -
> -#define CHV_PIPE_B_POWER_DOMAINS (   \
> -     BIT(POWER_DOMAIN_PIPE_B) |      \
> -     BIT(POWER_DOMAIN_INIT))
> -
> -#define CHV_PIPE_C_POWER_DOMAINS (   \
> -     BIT(POWER_DOMAIN_PIPE_C) |      \
> -     BIT(POWER_DOMAIN_INIT))
> -
> -#define CHV_DPIO_CMN_BC_POWER_DOMAINS (              \
> -     BIT(POWER_DOMAIN_PORT_DDI_B_2_LANES) |  \
> -     BIT(POWER_DOMAIN_PORT_DDI_B_4_LANES) |  \
> -     BIT(POWER_DOMAIN_PORT_DDI_C_2_LANES) |  \
> -     BIT(POWER_DOMAIN_PORT_DDI_C_4_LANES) |  \
> -     BIT(POWER_DOMAIN_INIT))
> -
> -#define CHV_DPIO_CMN_D_POWER_DOMAINS (               \
> -     BIT(POWER_DOMAIN_PORT_DDI_D_2_LANES) |  \
> -     BIT(POWER_DOMAIN_PORT_DDI_D_4_LANES) |  \
> -     BIT(POWER_DOMAIN_INIT))
> -
> -#define CHV_DPIO_TX_D_LANES_01_POWER_DOMAINS (       \
> -     BIT(POWER_DOMAIN_PORT_DDI_D_2_LANES) |  \
> -     BIT(POWER_DOMAIN_PORT_DDI_D_4_LANES) |  \
> -     BIT(POWER_DOMAIN_INIT))
> -
> -#define CHV_DPIO_TX_D_LANES_23_POWER_DOMAINS (       \
> -     BIT(POWER_DOMAIN_PORT_DDI_D_4_LANES) |  \
> -     BIT(POWER_DOMAIN_INIT))
> -
> -static const struct i915_power_well_ops i9xx_always_on_power_well_ops = {
> -     .sync_hw = i9xx_always_on_power_well_noop,
> -     .enable = i9xx_always_on_power_well_noop,
> -     .disable = i9xx_always_on_power_well_noop,
> -     .is_enabled = i9xx_always_on_power_well_enabled,
> -};
> -
> -static const struct i915_power_well_ops chv_pipe_power_well_ops = {
> -     .sync_hw = chv_pipe_power_well_sync_hw,
> -     .enable = chv_pipe_power_well_enable,
> -     .disable = chv_pipe_power_well_disable,
> -     .is_enabled = chv_pipe_power_well_enabled,
> -};
> -
> -static const struct i915_power_well_ops chv_dpio_cmn_power_well_ops = {
> -     .sync_hw = vlv_power_well_sync_hw,
> -     .enable = chv_dpio_cmn_power_well_enable,
> -     .disable = chv_dpio_cmn_power_well_disable,
> -     .is_enabled = vlv_power_well_enabled,
> -};
> -
> -static struct i915_power_well i9xx_always_on_power_well[] = {
> -     {
> -             .name = "always-on",
> -             .always_on = 1,
> -             .domains = POWER_DOMAIN_MASK,
> -             .ops = &i9xx_always_on_power_well_ops,
> -     },
> -};
> -
> -static const struct i915_power_well_ops hsw_power_well_ops = {
> -     .sync_hw = hsw_power_well_sync_hw,
> -     .enable = hsw_power_well_enable,
> -     .disable = hsw_power_well_disable,
> -     .is_enabled = hsw_power_well_enabled,
> -};
> -
> -static struct i915_power_well hsw_power_wells[] = {
> -     {
> -             .name = "always-on",
> -             .always_on = 1,
> -             .domains = HSW_ALWAYS_ON_POWER_DOMAINS,
> -             .ops = &i9xx_always_on_power_well_ops,
> -     },
> -     {
> -             .name = "display",
> -             .domains = HSW_DISPLAY_POWER_DOMAINS,
> -             .ops = &hsw_power_well_ops,
> -     },
> -};
> -
> -static struct i915_power_well bdw_power_wells[] = {
> -     {
> -             .name = "always-on",
> -             .always_on = 1,
> -             .domains = BDW_ALWAYS_ON_POWER_DOMAINS,
> -             .ops = &i9xx_always_on_power_well_ops,
> -     },
> -     {
> -             .name = "display",
> -             .domains = BDW_DISPLAY_POWER_DOMAINS,
> -             .ops = &hsw_power_well_ops,
> -     },
> -};
> -
> -static const struct i915_power_well_ops vlv_display_power_well_ops = {
> -     .sync_hw = vlv_power_well_sync_hw,
> -     .enable = vlv_display_power_well_enable,
> -     .disable = vlv_display_power_well_disable,
> -     .is_enabled = vlv_power_well_enabled,
> -};
> -
> -static const struct i915_power_well_ops vlv_dpio_cmn_power_well_ops = {
> -     .sync_hw = vlv_power_well_sync_hw,
> -     .enable = vlv_dpio_cmn_power_well_enable,
> -     .disable = vlv_dpio_cmn_power_well_disable,
> -     .is_enabled = vlv_power_well_enabled,
> -};
> -
> -static const struct i915_power_well_ops vlv_dpio_power_well_ops = {
> -     .sync_hw = vlv_power_well_sync_hw,
> -     .enable = vlv_power_well_enable,
> -     .disable = vlv_power_well_disable,
> -     .is_enabled = vlv_power_well_enabled,
> -};
> -
> -static struct i915_power_well vlv_power_wells[] = {
> -     {
> -             .name = "always-on",
> -             .always_on = 1,
> -             .domains = VLV_ALWAYS_ON_POWER_DOMAINS,
> -             .ops = &i9xx_always_on_power_well_ops,
> -     },
> -     {
> -             .name = "display",
> -             .domains = VLV_DISPLAY_POWER_DOMAINS,
> -             .data = PUNIT_POWER_WELL_DISP2D,
> -             .ops = &vlv_display_power_well_ops,
> -     },
> -     {
> -             .name = "dpio-tx-b-01",
> -             .domains = VLV_DPIO_TX_B_LANES_01_POWER_DOMAINS |
> -                        VLV_DPIO_TX_B_LANES_23_POWER_DOMAINS |
> -                        VLV_DPIO_TX_C_LANES_01_POWER_DOMAINS |
> -                        VLV_DPIO_TX_C_LANES_23_POWER_DOMAINS,
> -             .ops = &vlv_dpio_power_well_ops,
> -             .data = PUNIT_POWER_WELL_DPIO_TX_B_LANES_01,
> -     },
> -     {
> -             .name = "dpio-tx-b-23",
> -             .domains = VLV_DPIO_TX_B_LANES_01_POWER_DOMAINS |
> -                        VLV_DPIO_TX_B_LANES_23_POWER_DOMAINS |
> -                        VLV_DPIO_TX_C_LANES_01_POWER_DOMAINS |
> -                        VLV_DPIO_TX_C_LANES_23_POWER_DOMAINS,
> -             .ops = &vlv_dpio_power_well_ops,
> -             .data = PUNIT_POWER_WELL_DPIO_TX_B_LANES_23,
> -     },
> -     {
> -             .name = "dpio-tx-c-01",
> -             .domains = VLV_DPIO_TX_B_LANES_01_POWER_DOMAINS |
> -                        VLV_DPIO_TX_B_LANES_23_POWER_DOMAINS |
> -                        VLV_DPIO_TX_C_LANES_01_POWER_DOMAINS |
> -                        VLV_DPIO_TX_C_LANES_23_POWER_DOMAINS,
> -             .ops = &vlv_dpio_power_well_ops,
> -             .data = PUNIT_POWER_WELL_DPIO_TX_C_LANES_01,
> -     },
> -     {
> -             .name = "dpio-tx-c-23",
> -             .domains = VLV_DPIO_TX_B_LANES_01_POWER_DOMAINS |
> -                        VLV_DPIO_TX_B_LANES_23_POWER_DOMAINS |
> -                        VLV_DPIO_TX_C_LANES_01_POWER_DOMAINS |
> -                        VLV_DPIO_TX_C_LANES_23_POWER_DOMAINS,
> -             .ops = &vlv_dpio_power_well_ops,
> -             .data = PUNIT_POWER_WELL_DPIO_TX_C_LANES_23,
> -     },
> -     {
> -             .name = "dpio-common",
> -             .domains = VLV_DPIO_CMN_BC_POWER_DOMAINS,
> -             .data = PUNIT_POWER_WELL_DPIO_CMN_BC,
> -             .ops = &vlv_dpio_cmn_power_well_ops,
> -     },
> -};
> -
> -static struct i915_power_well chv_power_wells[] = {
> -     {
> -             .name = "always-on",
> -             .always_on = 1,
> -             .domains = VLV_ALWAYS_ON_POWER_DOMAINS,
> -             .ops = &i9xx_always_on_power_well_ops,
> -     },
> -#if 0
> -     {
> -             .name = "display",
> -             .domains = VLV_DISPLAY_POWER_DOMAINS,
> -             .data = PUNIT_POWER_WELL_DISP2D,
> -             .ops = &vlv_display_power_well_ops,
> -     },
> -     {
> -             .name = "pipe-a",
> -             .domains = CHV_PIPE_A_POWER_DOMAINS,
> -             .data = PIPE_A,
> -             .ops = &chv_pipe_power_well_ops,
> -     },
> -     {
> -             .name = "pipe-b",
> -             .domains = CHV_PIPE_B_POWER_DOMAINS,
> -             .data = PIPE_B,
> -             .ops = &chv_pipe_power_well_ops,
> -     },
> -     {
> -             .name = "pipe-c",
> -             .domains = CHV_PIPE_C_POWER_DOMAINS,
> -             .data = PIPE_C,
> -             .ops = &chv_pipe_power_well_ops,
> -     },
> -#endif
> -     {
> -             .name = "dpio-common-bc",
> -             /*
> -              * XXX: cmnreset for one PHY seems to disturb the other.
> -              * As a workaround keep both powered on at the same
> -              * time for now.
> -              */
> -             .domains = CHV_DPIO_CMN_BC_POWER_DOMAINS | 
> CHV_DPIO_CMN_D_POWER_DOMAINS,
> -             .data = PUNIT_POWER_WELL_DPIO_CMN_BC,
> -             .ops = &chv_dpio_cmn_power_well_ops,
> -     },
> -     {
> -             .name = "dpio-common-d",
> -             /*
> -              * XXX: cmnreset for one PHY seems to disturb the other.
> -              * As a workaround keep both powered on at the same
> -              * time for now.
> -              */
> -             .domains = CHV_DPIO_CMN_BC_POWER_DOMAINS | 
> CHV_DPIO_CMN_D_POWER_DOMAINS,
> -             .data = PUNIT_POWER_WELL_DPIO_CMN_D,
> -             .ops = &chv_dpio_cmn_power_well_ops,
> -     },
> -#if 0
> -     {
> -             .name = "dpio-tx-b-01",
> -             .domains = VLV_DPIO_TX_B_LANES_01_POWER_DOMAINS |
> -                        VLV_DPIO_TX_B_LANES_23_POWER_DOMAINS,
> -             .ops = &vlv_dpio_power_well_ops,
> -             .data = PUNIT_POWER_WELL_DPIO_TX_B_LANES_01,
> -     },
> -     {
> -             .name = "dpio-tx-b-23",
> -             .domains = VLV_DPIO_TX_B_LANES_01_POWER_DOMAINS |
> -                        VLV_DPIO_TX_B_LANES_23_POWER_DOMAINS,
> -             .ops = &vlv_dpio_power_well_ops,
> -             .data = PUNIT_POWER_WELL_DPIO_TX_B_LANES_23,
> -     },
> -     {
> -             .name = "dpio-tx-c-01",
> -             .domains = VLV_DPIO_TX_C_LANES_01_POWER_DOMAINS |
> -                        VLV_DPIO_TX_C_LANES_23_POWER_DOMAINS,
> -             .ops = &vlv_dpio_power_well_ops,
> -             .data = PUNIT_POWER_WELL_DPIO_TX_C_LANES_01,
> -     },
> -     {
> -             .name = "dpio-tx-c-23",
> -             .domains = VLV_DPIO_TX_C_LANES_01_POWER_DOMAINS |
> -                        VLV_DPIO_TX_C_LANES_23_POWER_DOMAINS,
> -             .ops = &vlv_dpio_power_well_ops,
> -             .data = PUNIT_POWER_WELL_DPIO_TX_C_LANES_23,
> -     },
> -     {
> -             .name = "dpio-tx-d-01",
> -             .domains = CHV_DPIO_TX_D_LANES_01_POWER_DOMAINS |
> -                        CHV_DPIO_TX_D_LANES_23_POWER_DOMAINS,
> -             .ops = &vlv_dpio_power_well_ops,
> -             .data = PUNIT_POWER_WELL_DPIO_TX_D_LANES_01,
> -     },
> -     {
> -             .name = "dpio-tx-d-23",
> -             .domains = CHV_DPIO_TX_D_LANES_01_POWER_DOMAINS |
> -                        CHV_DPIO_TX_D_LANES_23_POWER_DOMAINS,
> -             .ops = &vlv_dpio_power_well_ops,
> -             .data = PUNIT_POWER_WELL_DPIO_TX_D_LANES_23,
> -     },
> -#endif
> -};
> -
> -static struct i915_power_well *lookup_power_well(struct drm_i915_private 
> *dev_priv,
> -                                              enum punit_power_well 
> power_well_id)
> -{
> -     struct i915_power_domains *power_domains = &dev_priv->power_domains;
> -     struct i915_power_well *power_well;
> -     int i;
> -
> -     for_each_power_well(i, power_well, POWER_DOMAIN_MASK, power_domains) {
> -             if (power_well->data == power_well_id)
> -                     return power_well;
> -     }
> -
> -     return NULL;
> -}
> -
> -#define set_power_wells(power_domains, __power_wells) ({             \
> -     (power_domains)->power_wells = (__power_wells);                 \
> -     (power_domains)->power_well_count = ARRAY_SIZE(__power_wells);  \
> -})
> -
> -int intel_power_domains_init(struct drm_i915_private *dev_priv)
> -{
> -     struct i915_power_domains *power_domains = &dev_priv->power_domains;
> -
> -     mutex_init(&power_domains->lock);
> -
> -     /*
> -      * The enabling order will be from lower to higher indexed wells,
> -      * the disabling order is reversed.
> -      */
> -     if (IS_HASWELL(dev_priv->dev)) {
> -             set_power_wells(power_domains, hsw_power_wells);
> -             hsw_pwr = power_domains;
> -     } else if (IS_BROADWELL(dev_priv->dev)) {
> -             set_power_wells(power_domains, bdw_power_wells);
> -             hsw_pwr = power_domains;
> -     } else if (IS_CHERRYVIEW(dev_priv->dev)) {
> -             set_power_wells(power_domains, chv_power_wells);
> -     } else if (IS_VALLEYVIEW(dev_priv->dev)) {
> -             set_power_wells(power_domains, vlv_power_wells);
> -     } else {
> -             set_power_wells(power_domains, i9xx_always_on_power_well);
> -     }
> -
> -     return 0;
> -}
> -
> -void intel_power_domains_remove(struct drm_i915_private *dev_priv)
> -{
> -     hsw_pwr = NULL;
> -}
> -
> -static void intel_power_domains_resume(struct drm_i915_private *dev_priv)
> -{
> -     struct i915_power_domains *power_domains = &dev_priv->power_domains;
> -     struct i915_power_well *power_well;
> -     int i;
> -
> -     mutex_lock(&power_domains->lock);
> -     for_each_power_well(i, power_well, POWER_DOMAIN_MASK, power_domains) {
> -             power_well->ops->sync_hw(dev_priv, power_well);
> -             power_well->hw_enabled = power_well->ops->is_enabled(dev_priv,
> -                                                                  
> power_well);
> -     }
> -     mutex_unlock(&power_domains->lock);
> -}
> -
> -static void vlv_cmnlane_wa(struct drm_i915_private *dev_priv)
> -{
> -     struct i915_power_well *cmn =
> -             lookup_power_well(dev_priv, PUNIT_POWER_WELL_DPIO_CMN_BC);
> -     struct i915_power_well *disp2d =
> -             lookup_power_well(dev_priv, PUNIT_POWER_WELL_DISP2D);
> -
> -     /* nothing to do if common lane is already off */
> -     if (!cmn->ops->is_enabled(dev_priv, cmn))
> -             return;
> -
> -     /* If the display might be already active skip this */
> -     if (disp2d->ops->is_enabled(dev_priv, disp2d) &&
> -         I915_READ(DPIO_CTL) & DPIO_CMNRST)
> -             return;
> -
> -     DRM_DEBUG_KMS("toggling display PHY side reset\n");
> -
> -     /* cmnlane needs DPLL registers */
> -     disp2d->ops->enable(dev_priv, disp2d);
> -
> -     /*
> -      * From VLV2A0_DP_eDP_HDMI_DPIO_driver_vbios_notes_11.docx:
> -      * Need to assert and de-assert PHY SB reset by gating the
> -      * common lane power, then un-gating it.
> -      * Simply ungating isn't enough to reset the PHY enough to get
> -      * ports and lanes running.
> -      */
> -     cmn->ops->disable(dev_priv, cmn);
> -}
> -
> -void intel_power_domains_init_hw(struct drm_i915_private *dev_priv)
> -{
> -     struct drm_device *dev = dev_priv->dev;
> -     struct i915_power_domains *power_domains = &dev_priv->power_domains;
> -
> -     power_domains->initializing = true;
> -
> -     if (IS_VALLEYVIEW(dev) && !IS_CHERRYVIEW(dev)) {
> -             mutex_lock(&power_domains->lock);
> -             vlv_cmnlane_wa(dev_priv);
> -             mutex_unlock(&power_domains->lock);
> -     }
> -
> -     /* For now, we need the power well to be always enabled. */
> -     intel_display_set_init_power(dev_priv, true);
> -     intel_power_domains_resume(dev_priv);
> -     power_domains->initializing = false;
> -}
> -
> -void intel_aux_display_runtime_get(struct drm_i915_private *dev_priv)
> -{
> -     intel_runtime_pm_get(dev_priv);
> -}
> -
> -void intel_aux_display_runtime_put(struct drm_i915_private *dev_priv)
> -{
> -     intel_runtime_pm_put(dev_priv);
> -}
> -
> -void intel_runtime_pm_get(struct drm_i915_private *dev_priv)
> -{
> -     struct drm_device *dev = dev_priv->dev;
> -     struct device *device = &dev->pdev->dev;
> -
> -     if (!HAS_RUNTIME_PM(dev))
> -             return;
> -
> -     pm_runtime_get_sync(device);
> -     WARN(dev_priv->pm.suspended, "Device still suspended.\n");
> -}
> -
> -void intel_runtime_pm_get_noresume(struct drm_i915_private *dev_priv)
> -{
> -     struct drm_device *dev = dev_priv->dev;
> -     struct device *device = &dev->pdev->dev;
> -
> -     if (!HAS_RUNTIME_PM(dev))
> -             return;
> -
> -     WARN(dev_priv->pm.suspended, "Getting nosync-ref while suspended.\n");
> -     pm_runtime_get_noresume(device);
> -}
> -
> -void intel_runtime_pm_put(struct drm_i915_private *dev_priv)
> -{
> -     struct drm_device *dev = dev_priv->dev;
> -     struct device *device = &dev->pdev->dev;
> -
> -     if (!HAS_RUNTIME_PM(dev))
> -             return;
> -
> -     pm_runtime_mark_last_busy(device);
> -     pm_runtime_put_autosuspend(device);
> -}
> -
> -void intel_init_runtime_pm(struct drm_i915_private *dev_priv)
> -{
> -     struct drm_device *dev = dev_priv->dev;
> -     struct device *device = &dev->pdev->dev;
> -
> -     if (!HAS_RUNTIME_PM(dev))
> -             return;
> -
> -     pm_runtime_set_active(device);
> -
> -     /*
> -      * RPM depends on RC6 to save restore the GT HW context, so make RC6 a
> -      * requirement.
> -      */
> -     if (!intel_enable_rc6(dev)) {
> -             DRM_INFO("RC6 disabled, disabling runtime PM support\n");
> -             return;
> -     }
> -
> -     pm_runtime_set_autosuspend_delay(device, 10000); /* 10s */
> -     pm_runtime_mark_last_busy(device);
> -     pm_runtime_use_autosuspend(device);
> -
> -     pm_runtime_put_autosuspend(device);
> -}
> -
> -void intel_fini_runtime_pm(struct drm_i915_private *dev_priv)
> -{
> -     struct drm_device *dev = dev_priv->dev;
> -     struct device *device = &dev->pdev->dev;
> -
> -     if (!HAS_RUNTIME_PM(dev))
> -             return;
> -
> -     if (!intel_enable_rc6(dev))
> -             return;
> -
> -     /* Make sure we're not suspended first. */
> -     pm_runtime_get_sync(device);
> -     pm_runtime_disable(device);
> -}
>  
>  static void intel_init_fbc(struct drm_i915_private *dev_priv)
>  {
> diff --git a/drivers/gpu/drm/i915/intel_runtime_pm.c 
> b/drivers/gpu/drm/i915/intel_runtime_pm.c
> new file mode 100644
> index 000000000000..23f97ee79fde
> --- /dev/null
> +++ b/drivers/gpu/drm/i915/intel_runtime_pm.c
> @@ -0,0 +1,1190 @@
> +/*
> + * Copyright © 2012-2014 Intel Corporation
> + *
> + * Permission is hereby granted, free of charge, to any person obtaining a
> + * copy of this software and associated documentation files (the "Software"),
> + * to deal in the Software without restriction, including without limitation
> + * the rights to use, copy, modify, merge, publish, distribute, sublicense,
> + * and/or sell copies of the Software, and to permit persons to whom the
> + * Software is furnished to do so, subject to the following conditions:
> + *
> + * The above copyright notice and this permission notice (including the next
> + * paragraph) shall be included in all copies or substantial portions of the
> + * Software.
> + *
> + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
> + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
> + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
> + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
> + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
> + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 
> DEALINGS
> + * IN THE SOFTWARE.
> + *
> + * Authors:
> + *    Eugeni Dodonov <eugeni.dodo...@intel.com>
> + *    Daniel Vetter <daniel.vet...@ffwll.ch>
> + *
> + */
> +
> +#include <linux/pm_runtime.h>
> +#include <linux/vgaarb.h>
> +
> +#include "i915_drv.h"
> +#include "intel_drv.h"
> +#include <drm/i915_powerwell.h>
> +
> +static struct i915_power_domains *hsw_pwr;
> +
> +#define for_each_power_well(i, power_well, domain_mask, power_domains)       
> \
> +     for (i = 0;                                                     \
> +          i < (power_domains)->power_well_count &&                   \
> +              ((power_well) = &(power_domains)->power_wells[i]);     \
> +          i++)                                                       \
> +             if ((power_well)->domains & (domain_mask))
> +
> +#define for_each_power_well_rev(i, power_well, domain_mask, power_domains) \
> +     for (i = (power_domains)->power_well_count - 1;                  \
> +          i >= 0 && ((power_well) = &(power_domains)->power_wells[i]);\
> +          i--)                                                        \
> +             if ((power_well)->domains & (domain_mask))
> +
> +/**
> + * We should only use the power well if we explicitly asked the hardware to
> + * enable it, so check if it's enabled and also check if we've requested it 
> to
> + * be enabled.
> + */
> +static bool hsw_power_well_enabled(struct drm_i915_private *dev_priv,
> +                                struct i915_power_well *power_well)
> +{
> +     return I915_READ(HSW_PWR_WELL_DRIVER) ==
> +                  (HSW_PWR_WELL_ENABLE_REQUEST | HSW_PWR_WELL_STATE_ENABLED);
> +}
> +
> +bool intel_display_power_enabled_unlocked(struct drm_i915_private *dev_priv,
> +                                       enum intel_display_power_domain 
> domain)
> +{
> +     struct i915_power_domains *power_domains;
> +     struct i915_power_well *power_well;
> +     bool is_enabled;
> +     int i;
> +
> +     if (dev_priv->pm.suspended)
> +             return false;
> +
> +     power_domains = &dev_priv->power_domains;
> +
> +     is_enabled = true;
> +
> +     for_each_power_well_rev(i, power_well, BIT(domain), power_domains) {
> +             if (power_well->always_on)
> +                     continue;
> +
> +             if (!power_well->hw_enabled) {
> +                     is_enabled = false;
> +                     break;
> +             }
> +     }
> +
> +     return is_enabled;
> +}
> +
> +bool intel_display_power_enabled(struct drm_i915_private *dev_priv,
> +                              enum intel_display_power_domain domain)
> +{
> +     struct i915_power_domains *power_domains;
> +     bool ret;
> +
> +     power_domains = &dev_priv->power_domains;
> +
> +     mutex_lock(&power_domains->lock);
> +     ret = intel_display_power_enabled_unlocked(dev_priv, domain);
> +     mutex_unlock(&power_domains->lock);
> +
> +     return ret;
> +}
> +
> +/*
> + * Starting with Haswell, we have a "Power Down Well" that can be turned off
> + * when not needed anymore. We have 4 registers that can request the power 
> well
> + * to be enabled, and it will only be disabled if none of the registers is
> + * requesting it to be enabled.
> + */
> +static void hsw_power_well_post_enable(struct drm_i915_private *dev_priv)
> +{
> +     struct drm_device *dev = dev_priv->dev;
> +
> +     /*
> +      * After we re-enable the power well, if we touch VGA register 0x3d5
> +      * we'll get unclaimed register interrupts. This stops after we write
> +      * anything to the VGA MSR register. The vgacon module uses this
> +      * register all the time, so if we unbind our driver and, as a
> +      * consequence, bind vgacon, we'll get stuck in an infinite loop at
> +      * console_unlock(). So make here we touch the VGA MSR register, making
> +      * sure vgacon can keep working normally without triggering interrupts
> +      * and error messages.
> +      */
> +     vga_get_uninterruptible(dev->pdev, VGA_RSRC_LEGACY_IO);
> +     outb(inb(VGA_MSR_READ), VGA_MSR_WRITE);
> +     vga_put(dev->pdev, VGA_RSRC_LEGACY_IO);
> +
> +     if (IS_BROADWELL(dev))
> +             gen8_irq_power_well_post_enable(dev_priv);
> +}
> +
> +static void hsw_set_power_well(struct drm_i915_private *dev_priv,
> +                            struct i915_power_well *power_well, bool enable)
> +{
> +     bool is_enabled, enable_requested;
> +     uint32_t tmp;
> +
> +     tmp = I915_READ(HSW_PWR_WELL_DRIVER);
> +     is_enabled = tmp & HSW_PWR_WELL_STATE_ENABLED;
> +     enable_requested = tmp & HSW_PWR_WELL_ENABLE_REQUEST;
> +
> +     if (enable) {
> +             if (!enable_requested)
> +                     I915_WRITE(HSW_PWR_WELL_DRIVER,
> +                                HSW_PWR_WELL_ENABLE_REQUEST);
> +
> +             if (!is_enabled) {
> +                     DRM_DEBUG_KMS("Enabling power well\n");
> +                     if (wait_for((I915_READ(HSW_PWR_WELL_DRIVER) &
> +                                   HSW_PWR_WELL_STATE_ENABLED), 20))
> +                             DRM_ERROR("Timeout enabling power well\n");
> +             }
> +
> +             hsw_power_well_post_enable(dev_priv);
> +     } else {
> +             if (enable_requested) {
> +                     I915_WRITE(HSW_PWR_WELL_DRIVER, 0);
> +                     POSTING_READ(HSW_PWR_WELL_DRIVER);
> +                     DRM_DEBUG_KMS("Requesting to disable the power well\n");
> +             }
> +     }
> +}
> +
> +static void hsw_power_well_sync_hw(struct drm_i915_private *dev_priv,
> +                                struct i915_power_well *power_well)
> +{
> +     hsw_set_power_well(dev_priv, power_well, power_well->count > 0);
> +
> +     /*
> +      * We're taking over the BIOS, so clear any requests made by it since
> +      * the driver is in charge now.
> +      */
> +     if (I915_READ(HSW_PWR_WELL_BIOS) & HSW_PWR_WELL_ENABLE_REQUEST)
> +             I915_WRITE(HSW_PWR_WELL_BIOS, 0);
> +}
> +
> +static void hsw_power_well_enable(struct drm_i915_private *dev_priv,
> +                               struct i915_power_well *power_well)
> +{
> +     hsw_set_power_well(dev_priv, power_well, true);
> +}
> +
> +static void hsw_power_well_disable(struct drm_i915_private *dev_priv,
> +                                struct i915_power_well *power_well)
> +{
> +     hsw_set_power_well(dev_priv, power_well, false);
> +}
> +
> +static void i9xx_always_on_power_well_noop(struct drm_i915_private *dev_priv,
> +                                        struct i915_power_well *power_well)
> +{
> +}
> +
> +static bool i9xx_always_on_power_well_enabled(struct drm_i915_private 
> *dev_priv,
> +                                          struct i915_power_well *power_well)
> +{
> +     return true;
> +}
> +
> +static void vlv_set_power_well(struct drm_i915_private *dev_priv,
> +                            struct i915_power_well *power_well, bool enable)
> +{
> +     enum punit_power_well power_well_id = power_well->data;
> +     u32 mask;
> +     u32 state;
> +     u32 ctrl;
> +
> +     mask = PUNIT_PWRGT_MASK(power_well_id);
> +     state = enable ? PUNIT_PWRGT_PWR_ON(power_well_id) :
> +                      PUNIT_PWRGT_PWR_GATE(power_well_id);
> +
> +     mutex_lock(&dev_priv->rps.hw_lock);
> +
> +#define COND \
> +     ((vlv_punit_read(dev_priv, PUNIT_REG_PWRGT_STATUS) & mask) == state)
> +
> +     if (COND)
> +             goto out;
> +
> +     ctrl = vlv_punit_read(dev_priv, PUNIT_REG_PWRGT_CTRL);
> +     ctrl &= ~mask;
> +     ctrl |= state;
> +     vlv_punit_write(dev_priv, PUNIT_REG_PWRGT_CTRL, ctrl);
> +
> +     if (wait_for(COND, 100))
> +             DRM_ERROR("timout setting power well state %08x (%08x)\n",
> +                       state,
> +                       vlv_punit_read(dev_priv, PUNIT_REG_PWRGT_CTRL));
> +
> +#undef COND
> +
> +out:
> +     mutex_unlock(&dev_priv->rps.hw_lock);
> +}
> +
> +static void vlv_power_well_sync_hw(struct drm_i915_private *dev_priv,
> +                                struct i915_power_well *power_well)
> +{
> +     vlv_set_power_well(dev_priv, power_well, power_well->count > 0);
> +}
> +
> +static void vlv_power_well_enable(struct drm_i915_private *dev_priv,
> +                               struct i915_power_well *power_well)
> +{
> +     vlv_set_power_well(dev_priv, power_well, true);
> +}
> +
> +static void vlv_power_well_disable(struct drm_i915_private *dev_priv,
> +                                struct i915_power_well *power_well)
> +{
> +     vlv_set_power_well(dev_priv, power_well, false);
> +}
> +
> +static bool vlv_power_well_enabled(struct drm_i915_private *dev_priv,
> +                                struct i915_power_well *power_well)
> +{
> +     int power_well_id = power_well->data;
> +     bool enabled = false;
> +     u32 mask;
> +     u32 state;
> +     u32 ctrl;
> +
> +     mask = PUNIT_PWRGT_MASK(power_well_id);
> +     ctrl = PUNIT_PWRGT_PWR_ON(power_well_id);
> +
> +     mutex_lock(&dev_priv->rps.hw_lock);
> +
> +     state = vlv_punit_read(dev_priv, PUNIT_REG_PWRGT_STATUS) & mask;
> +     /*
> +      * We only ever set the power-on and power-gate states, anything
> +      * else is unexpected.
> +      */
> +     WARN_ON(state != PUNIT_PWRGT_PWR_ON(power_well_id) &&
> +             state != PUNIT_PWRGT_PWR_GATE(power_well_id));
> +     if (state == ctrl)
> +             enabled = true;
> +
> +     /*
> +      * A transient state at this point would mean some unexpected party
> +      * is poking at the power controls too.
> +      */
> +     ctrl = vlv_punit_read(dev_priv, PUNIT_REG_PWRGT_CTRL) & mask;
> +     WARN_ON(ctrl != state);
> +
> +     mutex_unlock(&dev_priv->rps.hw_lock);
> +
> +     return enabled;
> +}
> +
> +static void vlv_display_power_well_enable(struct drm_i915_private *dev_priv,
> +                                       struct i915_power_well *power_well)
> +{
> +     WARN_ON_ONCE(power_well->data != PUNIT_POWER_WELL_DISP2D);
> +
> +     vlv_set_power_well(dev_priv, power_well, true);
> +
> +     spin_lock_irq(&dev_priv->irq_lock);
> +     valleyview_enable_display_irqs(dev_priv);
> +     spin_unlock_irq(&dev_priv->irq_lock);
> +
> +     /*
> +      * During driver initialization/resume we can avoid restoring the
> +      * part of the HW/SW state that will be inited anyway explicitly.
> +      */
> +     if (dev_priv->power_domains.initializing)
> +             return;
> +
> +     intel_hpd_init(dev_priv->dev);
> +
> +     i915_redisable_vga_power_on(dev_priv->dev);
> +}
> +
> +static void vlv_display_power_well_disable(struct drm_i915_private *dev_priv,
> +                                        struct i915_power_well *power_well)
> +{
> +     WARN_ON_ONCE(power_well->data != PUNIT_POWER_WELL_DISP2D);
> +
> +     spin_lock_irq(&dev_priv->irq_lock);
> +     valleyview_disable_display_irqs(dev_priv);
> +     spin_unlock_irq(&dev_priv->irq_lock);
> +
> +     vlv_set_power_well(dev_priv, power_well, false);
> +
> +     vlv_power_sequencer_reset(dev_priv);
> +}
> +
> +static void vlv_dpio_cmn_power_well_enable(struct drm_i915_private *dev_priv,
> +                                        struct i915_power_well *power_well)
> +{
> +     WARN_ON_ONCE(power_well->data != PUNIT_POWER_WELL_DPIO_CMN_BC);
> +
> +     /*
> +      * Enable the CRI clock source so we can get at the
> +      * display and the reference clock for VGA
> +      * hotplug / manual detection.
> +      */
> +     I915_WRITE(DPLL(PIPE_B), I915_READ(DPLL(PIPE_B)) |
> +                DPLL_REFA_CLK_ENABLE_VLV | DPLL_INTEGRATED_CRI_CLK_VLV);
> +     udelay(1); /* >10ns for cmnreset, >0ns for sidereset */
> +
> +     vlv_set_power_well(dev_priv, power_well, true);
> +
> +     /*
> +      * From VLV2A0_DP_eDP_DPIO_driver_vbios_notes_10.docx -
> +      *  6.  De-assert cmn_reset/side_reset. Same as VLV X0.
> +      *   a. GUnit 0x2110 bit[0] set to 1 (def 0)
> +      *   b. The other bits such as sfr settings / modesel may all
> +      *      be set to 0.
> +      *
> +      * This should only be done on init and resume from S3 with
> +      * both PLLs disabled, or we risk losing DPIO and PLL
> +      * synchronization.
> +      */
> +     I915_WRITE(DPIO_CTL, I915_READ(DPIO_CTL) | DPIO_CMNRST);
> +}
> +
> +static void vlv_dpio_cmn_power_well_disable(struct drm_i915_private 
> *dev_priv,
> +                                         struct i915_power_well *power_well)
> +{
> +     enum pipe pipe;
> +
> +     WARN_ON_ONCE(power_well->data != PUNIT_POWER_WELL_DPIO_CMN_BC);
> +
> +     for_each_pipe(dev_priv, pipe)
> +             assert_pll_disabled(dev_priv, pipe);
> +
> +     /* Assert common reset */
> +     I915_WRITE(DPIO_CTL, I915_READ(DPIO_CTL) & ~DPIO_CMNRST);
> +
> +     vlv_set_power_well(dev_priv, power_well, false);
> +}
> +
> +static void chv_dpio_cmn_power_well_enable(struct drm_i915_private *dev_priv,
> +                                        struct i915_power_well *power_well)
> +{
> +     enum dpio_phy phy;
> +
> +     WARN_ON_ONCE(power_well->data != PUNIT_POWER_WELL_DPIO_CMN_BC &&
> +                  power_well->data != PUNIT_POWER_WELL_DPIO_CMN_D);
> +
> +     /*
> +      * Enable the CRI clock source so we can get at the
> +      * display and the reference clock for VGA
> +      * hotplug / manual detection.
> +      */
> +     if (power_well->data == PUNIT_POWER_WELL_DPIO_CMN_BC) {
> +             phy = DPIO_PHY0;
> +             I915_WRITE(DPLL(PIPE_B), I915_READ(DPLL(PIPE_B)) |
> +                        DPLL_REFA_CLK_ENABLE_VLV);
> +             I915_WRITE(DPLL(PIPE_B), I915_READ(DPLL(PIPE_B)) |
> +                        DPLL_REFA_CLK_ENABLE_VLV | 
> DPLL_INTEGRATED_CRI_CLK_VLV);
> +     } else {
> +             phy = DPIO_PHY1;
> +             I915_WRITE(DPLL(PIPE_C), I915_READ(DPLL(PIPE_C)) |
> +                        DPLL_REFA_CLK_ENABLE_VLV | 
> DPLL_INTEGRATED_CRI_CLK_VLV);
> +     }
> +     udelay(1); /* >10ns for cmnreset, >0ns for sidereset */
> +     vlv_set_power_well(dev_priv, power_well, true);
> +
> +     /* Poll for phypwrgood signal */
> +     if (wait_for(I915_READ(DISPLAY_PHY_STATUS) & PHY_POWERGOOD(phy), 1))
> +             DRM_ERROR("Display PHY %d is not power up\n", phy);
> +
> +     I915_WRITE(DISPLAY_PHY_CONTROL, I915_READ(DISPLAY_PHY_CONTROL) |
> +                PHY_COM_LANE_RESET_DEASSERT(phy));
> +}
> +
> +static void chv_dpio_cmn_power_well_disable(struct drm_i915_private 
> *dev_priv,
> +                                         struct i915_power_well *power_well)
> +{
> +     enum dpio_phy phy;
> +
> +     WARN_ON_ONCE(power_well->data != PUNIT_POWER_WELL_DPIO_CMN_BC &&
> +                  power_well->data != PUNIT_POWER_WELL_DPIO_CMN_D);
> +
> +     if (power_well->data == PUNIT_POWER_WELL_DPIO_CMN_BC) {
> +             phy = DPIO_PHY0;
> +             assert_pll_disabled(dev_priv, PIPE_A);
> +             assert_pll_disabled(dev_priv, PIPE_B);
> +     } else {
> +             phy = DPIO_PHY1;
> +             assert_pll_disabled(dev_priv, PIPE_C);
> +     }
> +
> +     I915_WRITE(DISPLAY_PHY_CONTROL, I915_READ(DISPLAY_PHY_CONTROL) &
> +                ~PHY_COM_LANE_RESET_DEASSERT(phy));
> +
> +     vlv_set_power_well(dev_priv, power_well, false);
> +}
> +
> +static bool chv_pipe_power_well_enabled(struct drm_i915_private *dev_priv,
> +                                     struct i915_power_well *power_well)
> +{
> +     enum pipe pipe = power_well->data;
> +     bool enabled;
> +     u32 state, ctrl;
> +
> +     mutex_lock(&dev_priv->rps.hw_lock);
> +
> +     state = vlv_punit_read(dev_priv, PUNIT_REG_DSPFREQ) & DP_SSS_MASK(pipe);
> +     /*
> +      * We only ever set the power-on and power-gate states, anything
> +      * else is unexpected.
> +      */
> +     WARN_ON(state != DP_SSS_PWR_ON(pipe) && state != DP_SSS_PWR_GATE(pipe));
> +     enabled = state == DP_SSS_PWR_ON(pipe);
> +
> +     /*
> +      * A transient state at this point would mean some unexpected party
> +      * is poking at the power controls too.
> +      */
> +     ctrl = vlv_punit_read(dev_priv, PUNIT_REG_DSPFREQ) & DP_SSC_MASK(pipe);
> +     WARN_ON(ctrl << 16 != state);
> +
> +     mutex_unlock(&dev_priv->rps.hw_lock);
> +
> +     return enabled;
> +}
> +
> +static void chv_set_pipe_power_well(struct drm_i915_private *dev_priv,
> +                                 struct i915_power_well *power_well,
> +                                 bool enable)
> +{
> +     enum pipe pipe = power_well->data;
> +     u32 state;
> +     u32 ctrl;
> +
> +     state = enable ? DP_SSS_PWR_ON(pipe) : DP_SSS_PWR_GATE(pipe);
> +
> +     mutex_lock(&dev_priv->rps.hw_lock);
> +
> +#define COND \
> +     ((vlv_punit_read(dev_priv, PUNIT_REG_DSPFREQ) & DP_SSS_MASK(pipe)) == 
> state)
> +
> +     if (COND)
> +             goto out;
> +
> +     ctrl = vlv_punit_read(dev_priv, PUNIT_REG_DSPFREQ);
> +     ctrl &= ~DP_SSC_MASK(pipe);
> +     ctrl |= enable ? DP_SSC_PWR_ON(pipe) : DP_SSC_PWR_GATE(pipe);
> +     vlv_punit_write(dev_priv, PUNIT_REG_DSPFREQ, ctrl);
> +
> +     if (wait_for(COND, 100))
> +             DRM_ERROR("timout setting power well state %08x (%08x)\n",
> +                       state,
> +                       vlv_punit_read(dev_priv, PUNIT_REG_DSPFREQ));
> +
> +#undef COND
> +
> +out:
> +     mutex_unlock(&dev_priv->rps.hw_lock);
> +}
> +
> +static void chv_pipe_power_well_sync_hw(struct drm_i915_private *dev_priv,
> +                                     struct i915_power_well *power_well)
> +{
> +     chv_set_pipe_power_well(dev_priv, power_well, power_well->count > 0);
> +}
> +
> +static void chv_pipe_power_well_enable(struct drm_i915_private *dev_priv,
> +                                    struct i915_power_well *power_well)
> +{
> +     WARN_ON_ONCE(power_well->data != PIPE_A &&
> +                  power_well->data != PIPE_B &&
> +                  power_well->data != PIPE_C);
> +
> +     chv_set_pipe_power_well(dev_priv, power_well, true);
> +}
> +
> +static void chv_pipe_power_well_disable(struct drm_i915_private *dev_priv,
> +                                     struct i915_power_well *power_well)
> +{
> +     WARN_ON_ONCE(power_well->data != PIPE_A &&
> +                  power_well->data != PIPE_B &&
> +                  power_well->data != PIPE_C);
> +
> +     chv_set_pipe_power_well(dev_priv, power_well, false);
> +}
> +
> +static void check_power_well_state(struct drm_i915_private *dev_priv,
> +                                struct i915_power_well *power_well)
> +{
> +     bool enabled = power_well->ops->is_enabled(dev_priv, power_well);
> +
> +     if (power_well->always_on || !i915.disable_power_well) {
> +             if (!enabled)
> +                     goto mismatch;
> +
> +             return;
> +     }
> +
> +     if (enabled != (power_well->count > 0))
> +             goto mismatch;
> +
> +     return;
> +
> +mismatch:
> +     WARN(1, "state mismatch for '%s' (always_on %d hw state %d use-count %d 
> disable_power_well %d\n",
> +               power_well->name, power_well->always_on, enabled,
> +               power_well->count, i915.disable_power_well);
> +}
> +
> +void intel_display_power_get(struct drm_i915_private *dev_priv,
> +                          enum intel_display_power_domain domain)
> +{
> +     struct i915_power_domains *power_domains;
> +     struct i915_power_well *power_well;
> +     int i;
> +
> +     intel_runtime_pm_get(dev_priv);
> +
> +     power_domains = &dev_priv->power_domains;
> +
> +     mutex_lock(&power_domains->lock);
> +
> +     for_each_power_well(i, power_well, BIT(domain), power_domains) {
> +             if (!power_well->count++) {
> +                     DRM_DEBUG_KMS("enabling %s\n", power_well->name);
> +                     power_well->ops->enable(dev_priv, power_well);
> +                     power_well->hw_enabled = true;
> +             }
> +
> +             check_power_well_state(dev_priv, power_well);
> +     }
> +
> +     power_domains->domain_use_count[domain]++;
> +
> +     mutex_unlock(&power_domains->lock);
> +}
> +
> +void intel_display_power_put(struct drm_i915_private *dev_priv,
> +                          enum intel_display_power_domain domain)
> +{
> +     struct i915_power_domains *power_domains;
> +     struct i915_power_well *power_well;
> +     int i;
> +
> +     power_domains = &dev_priv->power_domains;
> +
> +     mutex_lock(&power_domains->lock);
> +
> +     WARN_ON(!power_domains->domain_use_count[domain]);
> +     power_domains->domain_use_count[domain]--;
> +
> +     for_each_power_well_rev(i, power_well, BIT(domain), power_domains) {
> +             WARN_ON(!power_well->count);
> +
> +             if (!--power_well->count && i915.disable_power_well) {
> +                     DRM_DEBUG_KMS("disabling %s\n", power_well->name);
> +                     power_well->hw_enabled = false;
> +                     power_well->ops->disable(dev_priv, power_well);
> +             }
> +
> +             check_power_well_state(dev_priv, power_well);
> +     }
> +
> +     mutex_unlock(&power_domains->lock);
> +
> +     intel_runtime_pm_put(dev_priv);
> +}
> +
> +#define POWER_DOMAIN_MASK (BIT(POWER_DOMAIN_NUM) - 1)
> +
> +#define HSW_ALWAYS_ON_POWER_DOMAINS (                        \
> +     BIT(POWER_DOMAIN_PIPE_A) |                      \
> +     BIT(POWER_DOMAIN_TRANSCODER_EDP) |              \
> +     BIT(POWER_DOMAIN_PORT_DDI_A_2_LANES) |          \
> +     BIT(POWER_DOMAIN_PORT_DDI_A_4_LANES) |          \
> +     BIT(POWER_DOMAIN_PORT_DDI_B_2_LANES) |          \
> +     BIT(POWER_DOMAIN_PORT_DDI_B_4_LANES) |          \
> +     BIT(POWER_DOMAIN_PORT_DDI_C_2_LANES) |          \
> +     BIT(POWER_DOMAIN_PORT_DDI_C_4_LANES) |          \
> +     BIT(POWER_DOMAIN_PORT_DDI_D_2_LANES) |          \
> +     BIT(POWER_DOMAIN_PORT_DDI_D_4_LANES) |          \
> +     BIT(POWER_DOMAIN_PORT_CRT) |                    \
> +     BIT(POWER_DOMAIN_PLLS) |                        \
> +     BIT(POWER_DOMAIN_INIT))
> +#define HSW_DISPLAY_POWER_DOMAINS (                          \
> +     (POWER_DOMAIN_MASK & ~HSW_ALWAYS_ON_POWER_DOMAINS) |    \
> +     BIT(POWER_DOMAIN_INIT))
> +
> +#define BDW_ALWAYS_ON_POWER_DOMAINS (                        \
> +     HSW_ALWAYS_ON_POWER_DOMAINS |                   \
> +     BIT(POWER_DOMAIN_PIPE_A_PANEL_FITTER))
> +#define BDW_DISPLAY_POWER_DOMAINS (                          \
> +     (POWER_DOMAIN_MASK & ~BDW_ALWAYS_ON_POWER_DOMAINS) |    \
> +     BIT(POWER_DOMAIN_INIT))
> +
> +#define VLV_ALWAYS_ON_POWER_DOMAINS  BIT(POWER_DOMAIN_INIT)
> +#define VLV_DISPLAY_POWER_DOMAINS    POWER_DOMAIN_MASK
> +
> +#define VLV_DPIO_CMN_BC_POWER_DOMAINS (              \
> +     BIT(POWER_DOMAIN_PORT_DDI_B_2_LANES) |  \
> +     BIT(POWER_DOMAIN_PORT_DDI_B_4_LANES) |  \
> +     BIT(POWER_DOMAIN_PORT_DDI_C_2_LANES) |  \
> +     BIT(POWER_DOMAIN_PORT_DDI_C_4_LANES) |  \
> +     BIT(POWER_DOMAIN_PORT_CRT) |            \
> +     BIT(POWER_DOMAIN_INIT))
> +
> +#define VLV_DPIO_TX_B_LANES_01_POWER_DOMAINS (       \
> +     BIT(POWER_DOMAIN_PORT_DDI_B_2_LANES) |  \
> +     BIT(POWER_DOMAIN_PORT_DDI_B_4_LANES) |  \
> +     BIT(POWER_DOMAIN_INIT))
> +
> +#define VLV_DPIO_TX_B_LANES_23_POWER_DOMAINS (       \
> +     BIT(POWER_DOMAIN_PORT_DDI_B_4_LANES) |  \
> +     BIT(POWER_DOMAIN_INIT))
> +
> +#define VLV_DPIO_TX_C_LANES_01_POWER_DOMAINS (       \
> +     BIT(POWER_DOMAIN_PORT_DDI_C_2_LANES) |  \
> +     BIT(POWER_DOMAIN_PORT_DDI_C_4_LANES) |  \
> +     BIT(POWER_DOMAIN_INIT))
> +
> +#define VLV_DPIO_TX_C_LANES_23_POWER_DOMAINS (       \
> +     BIT(POWER_DOMAIN_PORT_DDI_C_4_LANES) |  \
> +     BIT(POWER_DOMAIN_INIT))
> +
> +#define CHV_PIPE_A_POWER_DOMAINS (   \
> +     BIT(POWER_DOMAIN_PIPE_A) |      \
> +     BIT(POWER_DOMAIN_INIT))
> +
> +#define CHV_PIPE_B_POWER_DOMAINS (   \
> +     BIT(POWER_DOMAIN_PIPE_B) |      \
> +     BIT(POWER_DOMAIN_INIT))
> +
> +#define CHV_PIPE_C_POWER_DOMAINS (   \
> +     BIT(POWER_DOMAIN_PIPE_C) |      \
> +     BIT(POWER_DOMAIN_INIT))
> +
> +#define CHV_DPIO_CMN_BC_POWER_DOMAINS (              \
> +     BIT(POWER_DOMAIN_PORT_DDI_B_2_LANES) |  \
> +     BIT(POWER_DOMAIN_PORT_DDI_B_4_LANES) |  \
> +     BIT(POWER_DOMAIN_PORT_DDI_C_2_LANES) |  \
> +     BIT(POWER_DOMAIN_PORT_DDI_C_4_LANES) |  \
> +     BIT(POWER_DOMAIN_INIT))
> +
> +#define CHV_DPIO_CMN_D_POWER_DOMAINS (               \
> +     BIT(POWER_DOMAIN_PORT_DDI_D_2_LANES) |  \
> +     BIT(POWER_DOMAIN_PORT_DDI_D_4_LANES) |  \
> +     BIT(POWER_DOMAIN_INIT))
> +
> +#define CHV_DPIO_TX_D_LANES_01_POWER_DOMAINS (       \
> +     BIT(POWER_DOMAIN_PORT_DDI_D_2_LANES) |  \
> +     BIT(POWER_DOMAIN_PORT_DDI_D_4_LANES) |  \
> +     BIT(POWER_DOMAIN_INIT))
> +
> +#define CHV_DPIO_TX_D_LANES_23_POWER_DOMAINS (       \
> +     BIT(POWER_DOMAIN_PORT_DDI_D_4_LANES) |  \
> +     BIT(POWER_DOMAIN_INIT))
> +
> +static const struct i915_power_well_ops i9xx_always_on_power_well_ops = {
> +     .sync_hw = i9xx_always_on_power_well_noop,
> +     .enable = i9xx_always_on_power_well_noop,
> +     .disable = i9xx_always_on_power_well_noop,
> +     .is_enabled = i9xx_always_on_power_well_enabled,
> +};
> +
> +static const struct i915_power_well_ops chv_pipe_power_well_ops = {
> +     .sync_hw = chv_pipe_power_well_sync_hw,
> +     .enable = chv_pipe_power_well_enable,
> +     .disable = chv_pipe_power_well_disable,
> +     .is_enabled = chv_pipe_power_well_enabled,
> +};
> +
> +static const struct i915_power_well_ops chv_dpio_cmn_power_well_ops = {
> +     .sync_hw = vlv_power_well_sync_hw,
> +     .enable = chv_dpio_cmn_power_well_enable,
> +     .disable = chv_dpio_cmn_power_well_disable,
> +     .is_enabled = vlv_power_well_enabled,
> +};
> +
> +static struct i915_power_well i9xx_always_on_power_well[] = {
> +     {
> +             .name = "always-on",
> +             .always_on = 1,
> +             .domains = POWER_DOMAIN_MASK,
> +             .ops = &i9xx_always_on_power_well_ops,
> +     },
> +};
> +
> +static const struct i915_power_well_ops hsw_power_well_ops = {
> +     .sync_hw = hsw_power_well_sync_hw,
> +     .enable = hsw_power_well_enable,
> +     .disable = hsw_power_well_disable,
> +     .is_enabled = hsw_power_well_enabled,
> +};
> +
> +static struct i915_power_well hsw_power_wells[] = {
> +     {
> +             .name = "always-on",
> +             .always_on = 1,
> +             .domains = HSW_ALWAYS_ON_POWER_DOMAINS,
> +             .ops = &i9xx_always_on_power_well_ops,
> +     },
> +     {
> +             .name = "display",
> +             .domains = HSW_DISPLAY_POWER_DOMAINS,
> +             .ops = &hsw_power_well_ops,
> +     },
> +};
> +
> +static struct i915_power_well bdw_power_wells[] = {
> +     {
> +             .name = "always-on",
> +             .always_on = 1,
> +             .domains = BDW_ALWAYS_ON_POWER_DOMAINS,
> +             .ops = &i9xx_always_on_power_well_ops,
> +     },
> +     {
> +             .name = "display",
> +             .domains = BDW_DISPLAY_POWER_DOMAINS,
> +             .ops = &hsw_power_well_ops,
> +     },
> +};
> +
> +static const struct i915_power_well_ops vlv_display_power_well_ops = {
> +     .sync_hw = vlv_power_well_sync_hw,
> +     .enable = vlv_display_power_well_enable,
> +     .disable = vlv_display_power_well_disable,
> +     .is_enabled = vlv_power_well_enabled,
> +};
> +
> +static const struct i915_power_well_ops vlv_dpio_cmn_power_well_ops = {
> +     .sync_hw = vlv_power_well_sync_hw,
> +     .enable = vlv_dpio_cmn_power_well_enable,
> +     .disable = vlv_dpio_cmn_power_well_disable,
> +     .is_enabled = vlv_power_well_enabled,
> +};
> +
> +static const struct i915_power_well_ops vlv_dpio_power_well_ops = {
> +     .sync_hw = vlv_power_well_sync_hw,
> +     .enable = vlv_power_well_enable,
> +     .disable = vlv_power_well_disable,
> +     .is_enabled = vlv_power_well_enabled,
> +};
> +
> +static struct i915_power_well vlv_power_wells[] = {
> +     {
> +             .name = "always-on",
> +             .always_on = 1,
> +             .domains = VLV_ALWAYS_ON_POWER_DOMAINS,
> +             .ops = &i9xx_always_on_power_well_ops,
> +     },
> +     {
> +             .name = "display",
> +             .domains = VLV_DISPLAY_POWER_DOMAINS,
> +             .data = PUNIT_POWER_WELL_DISP2D,
> +             .ops = &vlv_display_power_well_ops,
> +     },
> +     {
> +             .name = "dpio-tx-b-01",
> +             .domains = VLV_DPIO_TX_B_LANES_01_POWER_DOMAINS |
> +                        VLV_DPIO_TX_B_LANES_23_POWER_DOMAINS |
> +                        VLV_DPIO_TX_C_LANES_01_POWER_DOMAINS |
> +                        VLV_DPIO_TX_C_LANES_23_POWER_DOMAINS,
> +             .ops = &vlv_dpio_power_well_ops,
> +             .data = PUNIT_POWER_WELL_DPIO_TX_B_LANES_01,
> +     },
> +     {
> +             .name = "dpio-tx-b-23",
> +             .domains = VLV_DPIO_TX_B_LANES_01_POWER_DOMAINS |
> +                        VLV_DPIO_TX_B_LANES_23_POWER_DOMAINS |
> +                        VLV_DPIO_TX_C_LANES_01_POWER_DOMAINS |
> +                        VLV_DPIO_TX_C_LANES_23_POWER_DOMAINS,
> +             .ops = &vlv_dpio_power_well_ops,
> +             .data = PUNIT_POWER_WELL_DPIO_TX_B_LANES_23,
> +     },
> +     {
> +             .name = "dpio-tx-c-01",
> +             .domains = VLV_DPIO_TX_B_LANES_01_POWER_DOMAINS |
> +                        VLV_DPIO_TX_B_LANES_23_POWER_DOMAINS |
> +                        VLV_DPIO_TX_C_LANES_01_POWER_DOMAINS |
> +                        VLV_DPIO_TX_C_LANES_23_POWER_DOMAINS,
> +             .ops = &vlv_dpio_power_well_ops,
> +             .data = PUNIT_POWER_WELL_DPIO_TX_C_LANES_01,
> +     },
> +     {
> +             .name = "dpio-tx-c-23",
> +             .domains = VLV_DPIO_TX_B_LANES_01_POWER_DOMAINS |
> +                        VLV_DPIO_TX_B_LANES_23_POWER_DOMAINS |
> +                        VLV_DPIO_TX_C_LANES_01_POWER_DOMAINS |
> +                        VLV_DPIO_TX_C_LANES_23_POWER_DOMAINS,
> +             .ops = &vlv_dpio_power_well_ops,
> +             .data = PUNIT_POWER_WELL_DPIO_TX_C_LANES_23,
> +     },
> +     {
> +             .name = "dpio-common",
> +             .domains = VLV_DPIO_CMN_BC_POWER_DOMAINS,
> +             .data = PUNIT_POWER_WELL_DPIO_CMN_BC,
> +             .ops = &vlv_dpio_cmn_power_well_ops,
> +     },
> +};
> +
> +static struct i915_power_well chv_power_wells[] = {
> +     {
> +             .name = "always-on",
> +             .always_on = 1,
> +             .domains = VLV_ALWAYS_ON_POWER_DOMAINS,
> +             .ops = &i9xx_always_on_power_well_ops,
> +     },
> +#if 0
> +     {
> +             .name = "display",
> +             .domains = VLV_DISPLAY_POWER_DOMAINS,
> +             .data = PUNIT_POWER_WELL_DISP2D,
> +             .ops = &vlv_display_power_well_ops,
> +     },
> +     {
> +             .name = "pipe-a",
> +             .domains = CHV_PIPE_A_POWER_DOMAINS,
> +             .data = PIPE_A,
> +             .ops = &chv_pipe_power_well_ops,
> +     },
> +     {
> +             .name = "pipe-b",
> +             .domains = CHV_PIPE_B_POWER_DOMAINS,
> +             .data = PIPE_B,
> +             .ops = &chv_pipe_power_well_ops,
> +     },
> +     {
> +             .name = "pipe-c",
> +             .domains = CHV_PIPE_C_POWER_DOMAINS,
> +             .data = PIPE_C,
> +             .ops = &chv_pipe_power_well_ops,
> +     },
> +#endif
> +     {
> +             .name = "dpio-common-bc",
> +             /*
> +              * XXX: cmnreset for one PHY seems to disturb the other.
> +              * As a workaround keep both powered on at the same
> +              * time for now.
> +              */
> +             .domains = CHV_DPIO_CMN_BC_POWER_DOMAINS | 
> CHV_DPIO_CMN_D_POWER_DOMAINS,
> +             .data = PUNIT_POWER_WELL_DPIO_CMN_BC,
> +             .ops = &chv_dpio_cmn_power_well_ops,
> +     },
> +     {
> +             .name = "dpio-common-d",
> +             /*
> +              * XXX: cmnreset for one PHY seems to disturb the other.
> +              * As a workaround keep both powered on at the same
> +              * time for now.
> +              */
> +             .domains = CHV_DPIO_CMN_BC_POWER_DOMAINS | 
> CHV_DPIO_CMN_D_POWER_DOMAINS,
> +             .data = PUNIT_POWER_WELL_DPIO_CMN_D,
> +             .ops = &chv_dpio_cmn_power_well_ops,
> +     },
> +#if 0
> +     {
> +             .name = "dpio-tx-b-01",
> +             .domains = VLV_DPIO_TX_B_LANES_01_POWER_DOMAINS |
> +                        VLV_DPIO_TX_B_LANES_23_POWER_DOMAINS,
> +             .ops = &vlv_dpio_power_well_ops,
> +             .data = PUNIT_POWER_WELL_DPIO_TX_B_LANES_01,
> +     },
> +     {
> +             .name = "dpio-tx-b-23",
> +             .domains = VLV_DPIO_TX_B_LANES_01_POWER_DOMAINS |
> +                        VLV_DPIO_TX_B_LANES_23_POWER_DOMAINS,
> +             .ops = &vlv_dpio_power_well_ops,
> +             .data = PUNIT_POWER_WELL_DPIO_TX_B_LANES_23,
> +     },
> +     {
> +             .name = "dpio-tx-c-01",
> +             .domains = VLV_DPIO_TX_C_LANES_01_POWER_DOMAINS |
> +                        VLV_DPIO_TX_C_LANES_23_POWER_DOMAINS,
> +             .ops = &vlv_dpio_power_well_ops,
> +             .data = PUNIT_POWER_WELL_DPIO_TX_C_LANES_01,
> +     },
> +     {
> +             .name = "dpio-tx-c-23",
> +             .domains = VLV_DPIO_TX_C_LANES_01_POWER_DOMAINS |
> +                        VLV_DPIO_TX_C_LANES_23_POWER_DOMAINS,
> +             .ops = &vlv_dpio_power_well_ops,
> +             .data = PUNIT_POWER_WELL_DPIO_TX_C_LANES_23,
> +     },
> +     {
> +             .name = "dpio-tx-d-01",
> +             .domains = CHV_DPIO_TX_D_LANES_01_POWER_DOMAINS |
> +                        CHV_DPIO_TX_D_LANES_23_POWER_DOMAINS,
> +             .ops = &vlv_dpio_power_well_ops,
> +             .data = PUNIT_POWER_WELL_DPIO_TX_D_LANES_01,
> +     },
> +     {
> +             .name = "dpio-tx-d-23",
> +             .domains = CHV_DPIO_TX_D_LANES_01_POWER_DOMAINS |
> +                        CHV_DPIO_TX_D_LANES_23_POWER_DOMAINS,
> +             .ops = &vlv_dpio_power_well_ops,
> +             .data = PUNIT_POWER_WELL_DPIO_TX_D_LANES_23,
> +     },
> +#endif
> +};
> +
> +static struct i915_power_well *lookup_power_well(struct drm_i915_private 
> *dev_priv,
> +                                              enum punit_power_well 
> power_well_id)
> +{
> +     struct i915_power_domains *power_domains = &dev_priv->power_domains;
> +     struct i915_power_well *power_well;
> +     int i;
> +
> +     for_each_power_well(i, power_well, POWER_DOMAIN_MASK, power_domains) {
> +             if (power_well->data == power_well_id)
> +                     return power_well;
> +     }
> +
> +     return NULL;
> +}
> +
> +#define set_power_wells(power_domains, __power_wells) ({             \
> +     (power_domains)->power_wells = (__power_wells);                 \
> +     (power_domains)->power_well_count = ARRAY_SIZE(__power_wells);  \
> +})
> +
> +int intel_power_domains_init(struct drm_i915_private *dev_priv)
> +{
> +     struct i915_power_domains *power_domains = &dev_priv->power_domains;
> +
> +     mutex_init(&power_domains->lock);
> +
> +     /*
> +      * The enabling order will be from lower to higher indexed wells,
> +      * the disabling order is reversed.
> +      */
> +     if (IS_HASWELL(dev_priv->dev)) {
> +             set_power_wells(power_domains, hsw_power_wells);
> +             hsw_pwr = power_domains;
> +     } else if (IS_BROADWELL(dev_priv->dev)) {
> +             set_power_wells(power_domains, bdw_power_wells);
> +             hsw_pwr = power_domains;
> +     } else if (IS_CHERRYVIEW(dev_priv->dev)) {
> +             set_power_wells(power_domains, chv_power_wells);
> +     } else if (IS_VALLEYVIEW(dev_priv->dev)) {
> +             set_power_wells(power_domains, vlv_power_wells);
> +     } else {
> +             set_power_wells(power_domains, i9xx_always_on_power_well);
> +     }
> +
> +     return 0;
> +}
> +
> +void intel_power_domains_remove(struct drm_i915_private *dev_priv)
> +{
> +     hsw_pwr = NULL;
> +}
> +
> +static void intel_power_domains_resume(struct drm_i915_private *dev_priv)
> +{
> +     struct i915_power_domains *power_domains = &dev_priv->power_domains;
> +     struct i915_power_well *power_well;
> +     int i;
> +
> +     mutex_lock(&power_domains->lock);
> +     for_each_power_well(i, power_well, POWER_DOMAIN_MASK, power_domains) {
> +             power_well->ops->sync_hw(dev_priv, power_well);
> +             power_well->hw_enabled = power_well->ops->is_enabled(dev_priv,
> +                                                                  
> power_well);
> +     }
> +     mutex_unlock(&power_domains->lock);
> +}
> +
> +static void vlv_cmnlane_wa(struct drm_i915_private *dev_priv)
> +{
> +     struct i915_power_well *cmn =
> +             lookup_power_well(dev_priv, PUNIT_POWER_WELL_DPIO_CMN_BC);
> +     struct i915_power_well *disp2d =
> +             lookup_power_well(dev_priv, PUNIT_POWER_WELL_DISP2D);
> +
> +     /* nothing to do if common lane is already off */
> +     if (!cmn->ops->is_enabled(dev_priv, cmn))
> +             return;
> +
> +     /* If the display might be already active skip this */
> +     if (disp2d->ops->is_enabled(dev_priv, disp2d) &&
> +         I915_READ(DPIO_CTL) & DPIO_CMNRST)
> +             return;
> +
> +     DRM_DEBUG_KMS("toggling display PHY side reset\n");
> +
> +     /* cmnlane needs DPLL registers */
> +     disp2d->ops->enable(dev_priv, disp2d);
> +
> +     /*
> +      * From VLV2A0_DP_eDP_HDMI_DPIO_driver_vbios_notes_11.docx:
> +      * Need to assert and de-assert PHY SB reset by gating the
> +      * common lane power, then un-gating it.
> +      * Simply ungating isn't enough to reset the PHY enough to get
> +      * ports and lanes running.
> +      */
> +     cmn->ops->disable(dev_priv, cmn);
> +}
> +
> +void intel_power_domains_init_hw(struct drm_i915_private *dev_priv)
> +{
> +     struct drm_device *dev = dev_priv->dev;
> +     struct i915_power_domains *power_domains = &dev_priv->power_domains;
> +
> +     power_domains->initializing = true;
> +
> +     if (IS_VALLEYVIEW(dev) && !IS_CHERRYVIEW(dev)) {
> +             mutex_lock(&power_domains->lock);
> +             vlv_cmnlane_wa(dev_priv);
> +             mutex_unlock(&power_domains->lock);
> +     }
> +
> +     /* For now, we need the power well to be always enabled. */
> +     intel_display_set_init_power(dev_priv, true);
> +     intel_power_domains_resume(dev_priv);
> +     power_domains->initializing = false;
> +}
> +
> +void intel_aux_display_runtime_get(struct drm_i915_private *dev_priv)
> +{
> +     intel_runtime_pm_get(dev_priv);
> +}
> +
> +void intel_aux_display_runtime_put(struct drm_i915_private *dev_priv)
> +{
> +     intel_runtime_pm_put(dev_priv);
> +}
> +
> +void intel_runtime_pm_get(struct drm_i915_private *dev_priv)
> +{
> +     struct drm_device *dev = dev_priv->dev;
> +     struct device *device = &dev->pdev->dev;
> +
> +     if (!HAS_RUNTIME_PM(dev))
> +             return;
> +
> +     pm_runtime_get_sync(device);
> +     WARN(dev_priv->pm.suspended, "Device still suspended.\n");
> +}
> +
> +void intel_runtime_pm_get_noresume(struct drm_i915_private *dev_priv)
> +{
> +     struct drm_device *dev = dev_priv->dev;
> +     struct device *device = &dev->pdev->dev;
> +
> +     if (!HAS_RUNTIME_PM(dev))
> +             return;
> +
> +     WARN(dev_priv->pm.suspended, "Getting nosync-ref while suspended.\n");
> +     pm_runtime_get_noresume(device);
> +}
> +
> +void intel_runtime_pm_put(struct drm_i915_private *dev_priv)
> +{
> +     struct drm_device *dev = dev_priv->dev;
> +     struct device *device = &dev->pdev->dev;
> +
> +     if (!HAS_RUNTIME_PM(dev))
> +             return;
> +
> +     pm_runtime_mark_last_busy(device);
> +     pm_runtime_put_autosuspend(device);
> +}
> +
> +void intel_init_runtime_pm(struct drm_i915_private *dev_priv)
> +{
> +     struct drm_device *dev = dev_priv->dev;
> +     struct device *device = &dev->pdev->dev;
> +
> +     if (!HAS_RUNTIME_PM(dev))
> +             return;
> +
> +     pm_runtime_set_active(device);
> +
> +     /*
> +      * RPM depends on RC6 to save restore the GT HW context, so make RC6 a
> +      * requirement.
> +      */
> +     if (!intel_enable_rc6(dev)) {
> +             DRM_INFO("RC6 disabled, disabling runtime PM support\n");
> +             return;
> +     }
> +
> +     pm_runtime_set_autosuspend_delay(device, 10000); /* 10s */
> +     pm_runtime_mark_last_busy(device);
> +     pm_runtime_use_autosuspend(device);
> +
> +     pm_runtime_put_autosuspend(device);
> +}
> +
> +void intel_fini_runtime_pm(struct drm_i915_private *dev_priv)
> +{
> +     struct drm_device *dev = dev_priv->dev;
> +     struct device *device = &dev->pdev->dev;
> +
> +     if (!HAS_RUNTIME_PM(dev))
> +             return;
> +
> +     if (!intel_enable_rc6(dev))
> +             return;
> +
> +     /* Make sure we're not suspended first. */
> +     pm_runtime_get_sync(device);
> +     pm_runtime_disable(device);
> +}
> +
> +/* Display audio driver power well request */
> +int i915_request_power_well(void)
> +{
> +     struct drm_i915_private *dev_priv;
> +
> +     if (!hsw_pwr)
> +             return -ENODEV;
> +
> +     dev_priv = container_of(hsw_pwr, struct drm_i915_private,
> +                             power_domains);
> +     intel_display_power_get(dev_priv, POWER_DOMAIN_AUDIO);
> +     return 0;
> +}
> +EXPORT_SYMBOL_GPL(i915_request_power_well);
> +
> +/* Display audio driver power well release */
> +int i915_release_power_well(void)
> +{
> +     struct drm_i915_private *dev_priv;
> +
> +     if (!hsw_pwr)
> +             return -ENODEV;
> +
> +     dev_priv = container_of(hsw_pwr, struct drm_i915_private,
> +                             power_domains);
> +     intel_display_power_put(dev_priv, POWER_DOMAIN_AUDIO);
> +     return 0;
> +}
> +EXPORT_SYMBOL_GPL(i915_release_power_well);
> +
> +/*
> + * Private interface for the audio driver to get CDCLK in kHz.
> + *
> + * Caller must request power well using i915_request_power_well() prior to
> + * making the call.
> + */
> +int i915_get_cdclk_freq(void)
> +{
> +     struct drm_i915_private *dev_priv;
> +
> +     if (!hsw_pwr)
> +             return -ENODEV;
> +
> +     dev_priv = container_of(hsw_pwr, struct drm_i915_private,
> +                             power_domains);
> +
> +     return intel_ddi_get_cdclk_freq(dev_priv);
> +}
> +EXPORT_SYMBOL_GPL(i915_get_cdclk_freq);


_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx

Reply via email to