]> git.karo-electronics.de Git - linux-beck.git/commitdiff
drm/i915: fix intel_init_power_wells
authorPaulo Zanoni <paulo.r.zanoni@intel.com>
Fri, 25 Jan 2013 18:59:11 +0000 (16:59 -0200)
committerDaniel Vetter <daniel.vetter@ffwll.ch>
Sat, 26 Jan 2013 16:54:28 +0000 (17:54 +0100)
The current code was wrong in many different ways, so this is a full
rewrite. We don't have "different power wells for different parts of
the GPU", we have a single power well, but we have multiple registers
that can be used to request enabling/disabling the power well. So
let's be a good citizen and only use the register we're suppose to
use, except when we're loading the driver, where we clear the request
made by the BIOS.

If any of the registers is requesting the power well to be enabled, it
will be enabled. If none of the registers is requesting the power well
to be enabled, it will be disabled.

For now we're just forcing the power well to be enabled, but in the
next commits we'll change this.

V2:
  - Remove debug messages that could be misleading due to possible
    race conditions with KVMr, Debug and BIOS.
  - Don't wait on disabling: after a conversaion with a hardware
    engineer we discovered that the "restriction" on bit 31 is just
    for the "enable" case, and we don't even need to wait on the
    "disable" case.

Signed-off-by: Paulo Zanoni <paulo.r.zanoni@intel.com>
Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
drivers/gpu/drm/i915/i915_reg.h
drivers/gpu/drm/i915/intel_display.c
drivers/gpu/drm/i915/intel_drv.h
drivers/gpu/drm/i915/intel_pm.c

index 215443c378cc0d6bd7b39953bc16396ebff793ad..a18218ccac1ecde14ff32c4e177e5f29ce2e2deb 100644 (file)
 #define   AUDIO_CP_READY_C             (1<<9)
 
 /* HSW Power Wells */
-#define HSW_PWR_WELL_CTL1                      0x45400 /* BIOS */
-#define HSW_PWR_WELL_CTL2                      0x45404 /* Driver */
-#define HSW_PWR_WELL_CTL3                      0x45408 /* KVMR */
-#define HSW_PWR_WELL_CTL4                      0x4540C /* Debug */
+#define HSW_PWR_WELL_BIOS                      0x45400 /* CTL1 */
+#define HSW_PWR_WELL_DRIVER                    0x45404 /* CTL2 */
+#define HSW_PWR_WELL_KVMR                      0x45408 /* CTL3 */
+#define HSW_PWR_WELL_DEBUG                     0x4540C /* CTL4 */
 #define   HSW_PWR_WELL_ENABLE                  (1<<31)
 #define   HSW_PWR_WELL_STATE                   (1<<30)
 #define HSW_PWR_WELL_CTL5                      0x45410
index c5997d260172f265e607048de71f1ccc93a2952d..19ab75f307e5346b094d60d842424013d8ad1372 100644 (file)
@@ -8659,10 +8659,7 @@ static void i915_disable_vga(struct drm_device *dev)
 
 void intel_modeset_init_hw(struct drm_device *dev)
 {
-       /* We attempt to init the necessary power wells early in the initialization
-        * time, so the subsystems that expect power to be enabled can work.
-        */
-       intel_init_power_wells(dev);
+       intel_init_power_well(dev);
 
        intel_prepare_ddi(dev);
 
index 66619d80348fbda937a4dc5ee744d53d8ff50d70..32c30423eaca56ee297ab9f4851ab912a593fcbf 100644 (file)
@@ -667,7 +667,7 @@ extern void intel_update_fbc(struct drm_device *dev);
 extern void intel_gpu_ips_init(struct drm_i915_private *dev_priv);
 extern void intel_gpu_ips_teardown(void);
 
-extern void intel_init_power_wells(struct drm_device *dev);
+extern void intel_init_power_well(struct drm_device *dev);
 extern void intel_enable_gt_powersave(struct drm_device *dev);
 extern void intel_disable_gt_powersave(struct drm_device *dev);
 extern void gen6_gt_check_fifodbg(struct drm_i915_private *dev_priv);
index 5a8a72c5a89d2ccf1a84dc6133304fe10d58f792..b8cf16c06b1bdd3df62faf9b22dcfb44e994b906 100644 (file)
@@ -4043,33 +4043,56 @@ void intel_init_clock_gating(struct drm_device *dev)
        dev_priv->display.init_clock_gating(dev);
 }
 
-/* Starting with Haswell, we have different power wells for
- * different parts of the GPU. This attempts to enable them all.
+static void intel_set_power_well(struct drm_device *dev, bool enable)
+{
+       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;
+       enable_requested = tmp & HSW_PWR_WELL_ENABLE;
+
+       if (enable) {
+               if (!enable_requested)
+                       I915_WRITE(HSW_PWR_WELL_DRIVER, HSW_PWR_WELL_ENABLE);
+
+               if (!is_enabled) {
+                       DRM_DEBUG_KMS("Enabling power well\n");
+                       if (wait_for((I915_READ(HSW_PWR_WELL_DRIVER) &
+                                     HSW_PWR_WELL_STATE), 20))
+                               DRM_ERROR("Timeout enabling power well\n");
+               }
+       } else {
+               if (enable_requested) {
+                       I915_WRITE(HSW_PWR_WELL_DRIVER, 0);
+                       DRM_DEBUG_KMS("Requesting to disable the power well\n");
+               }
+       }
+}
+
+/*
+ * 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.
  */
-void intel_init_power_wells(struct drm_device *dev)
+void intel_init_power_well(struct drm_device *dev)
 {
        struct drm_i915_private *dev_priv = dev->dev_private;
-       unsigned long power_wells[] = {
-               HSW_PWR_WELL_CTL1,
-               HSW_PWR_WELL_CTL2,
-               HSW_PWR_WELL_CTL4
-       };
-       int i;
 
        if (!IS_HASWELL(dev))
                return;
 
        mutex_lock(&dev->struct_mutex);
 
-       for (i = 0; i < ARRAY_SIZE(power_wells); i++) {
-               int well = I915_READ(power_wells[i]);
+       /* For now, we need the power well to be always enabled. */
+       intel_set_power_well(dev, true);
 
-               if ((well & HSW_PWR_WELL_STATE) == 0) {
-                       I915_WRITE(power_wells[i], well & HSW_PWR_WELL_ENABLE);
-                       if (wait_for((I915_READ(power_wells[i]) & HSW_PWR_WELL_STATE), 20))
-                               DRM_ERROR("Error enabling power well %lx\n", power_wells[i]);
-               }
-       }
+       /* 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)
+               I915_WRITE(HSW_PWR_WELL_BIOS, 0);
 
        mutex_unlock(&dev->struct_mutex);
 }