Had to conditionalize some HSW bits and add virtual functions for
get/set on the power wells.

Signed-off-by: Jesse Barnes <[email protected]>
---
 drivers/gpu/drm/i915/i915_drv.h     |  10 +-
 drivers/gpu/drm/i915/intel_drv.h    |   2 +
 drivers/gpu/drm/i915/intel_pm.c     | 128 +++-------------------
 drivers/gpu/drm/i915/intel_uncore.c | 211 ++++++++++++++++++++++++++++++++++++
 4 files changed, 238 insertions(+), 113 deletions(-)

diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
index ca74ef2..4e97840 100644
--- a/drivers/gpu/drm/i915/i915_drv.h
+++ b/drivers/gpu/drm/i915/i915_drv.h
@@ -401,6 +401,14 @@ struct drm_i915_display_funcs {
 struct intel_uncore_funcs {
        void (*force_wake_get)(struct drm_i915_private *dev_priv);
        void (*force_wake_put)(struct drm_i915_private *dev_priv);
+       void (*set_display_power)(struct drm_i915_private *dev_priv,
+                                 bool enable);
+       bool (*display_power_enabled)(struct drm_i915_private *dev_priv,
+                                     enum intel_display_power_domain domain);
+       void (*display_power_get)(struct drm_i915_private *dev_priv,
+                                 enum intel_display_power_domain domain);
+       void (*display_power_put)(struct drm_i915_private *dev_priv,
+                                 enum intel_display_power_domain domain);
 };
 
 struct intel_uncore {
@@ -1702,7 +1710,7 @@ struct drm_i915_file_private {
 #define HAS_IPS(dev)           (IS_ULT(dev))
 
 #define HAS_DDI(dev)           (INTEL_INFO(dev)->has_ddi)
-#define HAS_POWER_WELL(dev)    (IS_HASWELL(dev))
+#define HAS_POWER_WELL(dev)    (IS_HASWELL(dev) || IS_VALLEYVIEW(dev))
 #define HAS_FPGA_DBG_UNCLAIMED(dev)    (INTEL_INFO(dev)->has_fpga_dbg)
 #define HAS_PSR(dev)           (IS_HASWELL(dev))
 
diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
index 476d98b..9317383 100644
--- a/drivers/gpu/drm/i915/intel_drv.h
+++ b/drivers/gpu/drm/i915/intel_drv.h
@@ -798,6 +798,8 @@ void intel_display_power_get(struct drm_device *dev,
                             enum intel_display_power_domain domain);
 void intel_display_power_put(struct drm_device *dev,
                             enum intel_display_power_domain domain);
+void __intel_power_well_get(struct i915_power_well *power_well);
+void __intel_power_well_put(struct i915_power_well *power_well);
 void intel_init_power_well(struct drm_device *dev);
 void intel_set_power_well(struct drm_device *dev, bool enable);
 void intel_enable_gt_powersave(struct drm_device *dev);
diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c
index 0b4de57..d1abc42 100644
--- a/drivers/gpu/drm/i915/intel_pm.c
+++ b/drivers/gpu/drm/i915/intel_pm.c
@@ -5367,146 +5367,48 @@ bool intel_display_power_enabled(struct drm_device 
*dev,
        if (!HAS_POWER_WELL(dev))
                return true;
 
-       switch (domain) {
-       case POWER_DOMAIN_PIPE_A:
-       case POWER_DOMAIN_TRANSCODER_EDP:
-               return true;
-       case POWER_DOMAIN_VGA:
-       case POWER_DOMAIN_PIPE_B:
-       case POWER_DOMAIN_PIPE_C:
-       case POWER_DOMAIN_PIPE_A_PANEL_FITTER:
-       case POWER_DOMAIN_PIPE_B_PANEL_FITTER:
-       case POWER_DOMAIN_PIPE_C_PANEL_FITTER:
-       case POWER_DOMAIN_TRANSCODER_A:
-       case POWER_DOMAIN_TRANSCODER_B:
-       case POWER_DOMAIN_TRANSCODER_C:
-               return I915_READ(HSW_PWR_WELL_DRIVER) ==
-                    (HSW_PWR_WELL_ENABLE_REQUEST | HSW_PWR_WELL_STATE_ENABLED);
-       default:
-               BUG();
-       }
+       return dev_priv->uncore.funcs.display_power_enabled(dev_priv, domain);
 }
 
-static void __intel_set_power_well(struct drm_device *dev, bool enable)
+void __intel_power_well_get(struct i915_power_well *power_well)
 {
+       struct drm_device *dev = power_well->device;
        struct drm_i915_private *dev_priv = dev->dev_private;
-       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");
-               }
-       } else {
-               if (enable_requested) {
-                       unsigned long irqflags;
-                       enum pipe p;
-
-                       I915_WRITE(HSW_PWR_WELL_DRIVER, 0);
-                       POSTING_READ(HSW_PWR_WELL_DRIVER);
-                       DRM_DEBUG_KMS("Requesting to disable the power well\n");
-
-                       /*
-                        * After this, the registers on the pipes that are part
-                        * of the power well will become zero, so we have to
-                        * adjust our counters according to that.
-                        *
-                        * FIXME: Should we do this in general in
-                        * drm_vblank_post_modeset?
-                        */
-                       spin_lock_irqsave(&dev->vbl_lock, irqflags);
-                       for_each_pipe(p)
-                               if (p != PIPE_A)
-                                       dev->last_vblank[p] = 0;
-                       spin_unlock_irqrestore(&dev->vbl_lock, irqflags);
-               }
-       }
-}
-
-static void __intel_power_well_get(struct i915_power_well *power_well)
-{
        if (!power_well->count++)
-               __intel_set_power_well(power_well->device, true);
+               dev_priv->uncore.funcs.set_display_power(dev_priv, true);
 }
 
-static void __intel_power_well_put(struct i915_power_well *power_well)
+void __intel_power_well_put(struct i915_power_well *power_well)
 {
+       struct drm_device *dev = power_well->device;
+       struct drm_i915_private *dev_priv = dev->dev_private;
+
        WARN_ON(!power_well->count);
        if (!--power_well->count)
-               __intel_set_power_well(power_well->device, false);
+               dev_priv->uncore.funcs.set_display_power(dev_priv, false);
 }
 
 void intel_display_power_get(struct drm_device *dev,
                             enum intel_display_power_domain domain)
 {
        struct drm_i915_private *dev_priv = dev->dev_private;
-       struct i915_power_well *power_well = &dev_priv->power_well;
 
        if (!HAS_POWER_WELL(dev))
                return;
 
-       switch (domain) {
-       case POWER_DOMAIN_PIPE_A:
-       case POWER_DOMAIN_TRANSCODER_EDP:
-               return;
-       case POWER_DOMAIN_VGA:
-       case POWER_DOMAIN_PIPE_B:
-       case POWER_DOMAIN_PIPE_C:
-       case POWER_DOMAIN_PIPE_A_PANEL_FITTER:
-       case POWER_DOMAIN_PIPE_B_PANEL_FITTER:
-       case POWER_DOMAIN_PIPE_C_PANEL_FITTER:
-       case POWER_DOMAIN_TRANSCODER_A:
-       case POWER_DOMAIN_TRANSCODER_B:
-       case POWER_DOMAIN_TRANSCODER_C:
-               spin_lock_irq(&power_well->lock);
-               __intel_power_well_get(power_well);
-               spin_unlock_irq(&power_well->lock);
-               return;
-       default:
-               BUG();
-       }
+       dev_priv->uncore.funcs.display_power_get(dev_priv, domain);
 }
 
 void intel_display_power_put(struct drm_device *dev,
                             enum intel_display_power_domain domain)
 {
        struct drm_i915_private *dev_priv = dev->dev_private;
-       struct i915_power_well *power_well = &dev_priv->power_well;
 
        if (!HAS_POWER_WELL(dev))
                return;
 
-       switch (domain) {
-       case POWER_DOMAIN_PIPE_A:
-       case POWER_DOMAIN_TRANSCODER_EDP:
-               return;
-       case POWER_DOMAIN_VGA:
-       case POWER_DOMAIN_PIPE_B:
-       case POWER_DOMAIN_PIPE_C:
-       case POWER_DOMAIN_PIPE_A_PANEL_FITTER:
-       case POWER_DOMAIN_PIPE_B_PANEL_FITTER:
-       case POWER_DOMAIN_PIPE_C_PANEL_FITTER:
-       case POWER_DOMAIN_TRANSCODER_A:
-       case POWER_DOMAIN_TRANSCODER_B:
-       case POWER_DOMAIN_TRANSCODER_C:
-               spin_lock_irq(&power_well->lock);
-               __intel_power_well_put(power_well);
-               spin_unlock_irq(&power_well->lock);
-               return;
-       default:
-               BUG();
-       }
+       dev_priv->uncore.funcs.display_power_put(dev_priv, domain);
 }
 
 static struct i915_power_well *hsw_pwr;
@@ -5595,7 +5497,8 @@ static void intel_resume_power_well(struct drm_device 
*dev)
                return;
 
        spin_lock_irq(&power_well->lock);
-       __intel_set_power_well(dev, power_well->count > 0);
+       dev_priv->uncore.funcs.set_display_power(dev_priv,
+                                                power_well->count > 0);
        spin_unlock_irq(&power_well->lock);
 }
 
@@ -5618,8 +5521,9 @@ void intel_init_power_well(struct drm_device *dev)
 
        /* 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);
+       if (IS_HASWELL(dev))
+               if (I915_READ(HSW_PWR_WELL_BIOS) & HSW_PWR_WELL_ENABLE_REQUEST)
+                       I915_WRITE(HSW_PWR_WELL_BIOS, 0);
 }
 
 /* Disables PC8 so we can use the GMBUS and DP AUX interrupts. */
diff --git a/drivers/gpu/drm/i915/intel_uncore.c 
b/drivers/gpu/drm/i915/intel_uncore.c
index 288a3a6..ef5d7fd 100644
--- a/drivers/gpu/drm/i915/intel_uncore.c
+++ b/drivers/gpu/drm/i915/intel_uncore.c
@@ -216,6 +216,209 @@ static void gen6_force_wake_work(struct work_struct *work)
        spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags);
 }
 
+static void hsw_display_power_get(struct drm_i915_private *dev_priv,
+                                 enum intel_display_power_domain domain)
+{
+       struct i915_power_well *power_well = &dev_priv->power_well;
+
+       switch (domain) {
+       case POWER_DOMAIN_PIPE_A:
+       case POWER_DOMAIN_TRANSCODER_EDP:
+               return;
+       case POWER_DOMAIN_VGA:
+       case POWER_DOMAIN_PIPE_B:
+       case POWER_DOMAIN_PIPE_C:
+       case POWER_DOMAIN_PIPE_A_PANEL_FITTER:
+       case POWER_DOMAIN_PIPE_B_PANEL_FITTER:
+       case POWER_DOMAIN_PIPE_C_PANEL_FITTER:
+       case POWER_DOMAIN_TRANSCODER_A:
+       case POWER_DOMAIN_TRANSCODER_B:
+       case POWER_DOMAIN_TRANSCODER_C:
+               spin_lock_irq(&power_well->lock);
+               __intel_power_well_get(power_well);
+               spin_unlock_irq(&power_well->lock);
+               return;
+       default:
+               BUG();
+       }
+}
+
+static void hsw_display_power_put(struct drm_i915_private *dev_priv,
+                                 enum intel_display_power_domain domain)
+{
+       struct i915_power_well *power_well = &dev_priv->power_well;
+       switch (domain) {
+       case POWER_DOMAIN_PIPE_A:
+       case POWER_DOMAIN_TRANSCODER_EDP:
+               return;
+       case POWER_DOMAIN_VGA:
+       case POWER_DOMAIN_PIPE_B:
+       case POWER_DOMAIN_PIPE_C:
+       case POWER_DOMAIN_PIPE_A_PANEL_FITTER:
+       case POWER_DOMAIN_PIPE_B_PANEL_FITTER:
+       case POWER_DOMAIN_PIPE_C_PANEL_FITTER:
+       case POWER_DOMAIN_TRANSCODER_A:
+       case POWER_DOMAIN_TRANSCODER_B:
+       case POWER_DOMAIN_TRANSCODER_C:
+               spin_lock_irq(&power_well->lock);
+               __intel_power_well_put(power_well);
+               spin_unlock_irq(&power_well->lock);
+               return;
+       default:
+               BUG();
+       }
+}
+
+static void vlv_display_power_get(struct drm_i915_private *dev_priv,
+                                 enum intel_display_power_domain domain)
+{
+       struct i915_power_well *power_well = &dev_priv->power_well;
+
+       spin_lock_irq(&power_well->lock);
+       __intel_power_well_get(power_well);
+       spin_unlock_irq(&power_well->lock);
+}
+
+static void vlv_display_power_put(struct drm_i915_private *dev_priv,
+                                 enum intel_display_power_domain domain)
+{
+       struct i915_power_well *power_well = &dev_priv->power_well;
+
+       spin_lock_irq(&power_well->lock);
+       __intel_power_well_put(power_well);
+       spin_unlock_irq(&power_well->lock);
+}
+
+static bool hsw_display_power_enabled(struct drm_i915_private *dev_priv,
+                                     enum intel_display_power_domain domain)
+{
+       switch (domain) {
+       case POWER_DOMAIN_PIPE_A:
+       case POWER_DOMAIN_TRANSCODER_EDP:
+               return true;
+       case POWER_DOMAIN_VGA:
+       case POWER_DOMAIN_PIPE_B:
+       case POWER_DOMAIN_PIPE_C:
+       case POWER_DOMAIN_PIPE_A_PANEL_FITTER:
+       case POWER_DOMAIN_PIPE_B_PANEL_FITTER:
+       case POWER_DOMAIN_PIPE_C_PANEL_FITTER:
+       case POWER_DOMAIN_TRANSCODER_A:
+       case POWER_DOMAIN_TRANSCODER_B:
+       case POWER_DOMAIN_TRANSCODER_C:
+               return I915_READ(HSW_PWR_WELL_DRIVER) ==
+                       (HSW_PWR_WELL_ENABLE_REQUEST |
+                        HSW_PWR_WELL_STATE_ENABLED);
+       default:
+               BUG();
+       }
+}
+
+static bool __vlv_get_power_well(struct drm_i915_private *dev_priv,
+                                u32 pwrgt_mask)
+{
+       u32 reg_val;
+
+       mutex_lock(&dev_priv->rps.hw_lock);
+       reg_val = vlv_punit_read(dev_priv, PUNIT_REG_PWRGT_STATUS);
+       mutex_unlock(&dev_priv->rps.hw_lock);
+
+       return !(reg_val & pwrgt_mask);
+}
+
+static bool vlv_display_power_enabled(struct drm_i915_private *dev_priv,
+                                     enum intel_display_power_domain domain)
+{
+       return __vlv_get_power_well(dev_priv, DISP2D_PWRGT);
+}
+
+static void hsw_set_display_power(struct drm_i915_private *dev_priv,
+                                 bool enable)
+{
+       struct drm_device *dev = dev_priv->dev;
+       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");
+               }
+       } else {
+               if (enable_requested) {
+                       unsigned long irqflags;
+                       enum pipe p;
+
+                       I915_WRITE(HSW_PWR_WELL_DRIVER, 0);
+                       POSTING_READ(HSW_PWR_WELL_DRIVER);
+                       DRM_DEBUG_KMS("Requesting to disable the power well\n");
+
+                       /*
+                        * After this, the registers on the pipes that are part
+                        * of the power well will become zero, so we have to
+                        * adjust our counters according to that.
+                        *
+                        * FIXME: Should we do this in general in
+                        * drm_vblank_post_modeset?
+                        */
+                       spin_lock_irqsave(&dev->vbl_lock, irqflags);
+                       for_each_pipe(p)
+                               if (p != PIPE_A)
+                                       dev->last_vblank[p] = 0;
+                       spin_unlock_irqrestore(&dev->vbl_lock, irqflags);
+               }
+       }
+}
+
+static void __vlv_set_power_well(struct drm_i915_private *dev_priv,
+                                u32 pwrgt_mask, bool enable)
+{
+       u32 reg_val;
+
+       mutex_lock(&dev_priv->rps.hw_lock);
+       reg_val = vlv_punit_read(dev_priv, PUNIT_REG_PWRGT_STATUS);
+       if (enable) {
+               if (reg_val & pwrgt_mask) {
+                       reg_val &= ~pwrgt_mask;
+                       vlv_punit_write(dev_priv, PUNIT_REG_PWRGT_CTRL,
+                                       reg_val);
+                       if (wait_for(!(vlv_punit_read(dev_priv, 
PUNIT_REG_PWRGT_STATUS) & pwrgt_mask), 100))
+                               DRM_ERROR("timed out waiting for power well 
enable\n");
+               }
+       } else {
+               reg_val |= pwrgt_mask;
+               vlv_punit_write(dev_priv, PUNIT_REG_PWRGT_CTRL, reg_val);
+               if (wait_for(vlv_punit_read(dev_priv, PUNIT_REG_PWRGT_STATUS) & 
pwrgt_mask, 100))
+                       DRM_ERROR("timed out waiting for power well 
disable\n");        }
+       reg_val = vlv_punit_read(dev_priv, PUNIT_REG_PWRGT_STATUS);
+       mutex_unlock(&dev_priv->rps.hw_lock);
+}
+
+static void vlv_set_display_power(struct drm_i915_private *dev_priv,
+                                 bool enable)
+{
+       __vlv_set_power_well(dev_priv, DISP2D_PWRGT, enable);
+}
+
+static void vlv_set_render_power(struct drm_i915_private *dev_priv, bool 
enable)
+{
+       __vlv_set_power_well(dev_priv, RENDER_PWRGT, enable);
+}
+
+static void vlv_set_media_power(struct drm_i915_private *dev_priv, bool enable)
+{
+       __vlv_set_power_well(dev_priv, MEDIA_PWRGT, enable);
+}
+
 void intel_uncore_early_sanitize(struct drm_device *dev)
 {
        struct drm_i915_private *dev_priv = dev->dev_private;
@@ -234,9 +437,17 @@ void intel_uncore_init(struct drm_device *dev)
        if (IS_VALLEYVIEW(dev)) {
                dev_priv->uncore.funcs.force_wake_get = vlv_force_wake_get;
                dev_priv->uncore.funcs.force_wake_put = vlv_force_wake_put;
+               dev_priv->uncore.funcs.set_display_power = 
vlv_set_display_power;
+               dev_priv->uncore.funcs.display_power_enabled = 
vlv_display_power_enabled;
+               dev_priv->uncore.funcs.display_power_get = 
vlv_display_power_get;
+               dev_priv->uncore.funcs.display_power_put = 
vlv_display_power_put;
        } else if (IS_HASWELL(dev)) {
                dev_priv->uncore.funcs.force_wake_get = 
__gen6_gt_force_wake_mt_get;
                dev_priv->uncore.funcs.force_wake_put = 
__gen6_gt_force_wake_mt_put;
+               dev_priv->uncore.funcs.set_display_power = 
hsw_set_display_power;
+               dev_priv->uncore.funcs.display_power_enabled = 
hsw_display_power_enabled;
+               dev_priv->uncore.funcs.display_power_get = 
hsw_display_power_get;
+               dev_priv->uncore.funcs.display_power_put = 
hsw_display_power_put;
        } else if (IS_IVYBRIDGE(dev)) {
                u32 ecobus;
 
-- 
1.8.3.1

_______________________________________________
Intel-gfx mailing list
[email protected]
http://lists.freedesktop.org/mailman/listinfo/intel-gfx

Reply via email to