drm/i915: transform HAS_PCH_SPLIT in a feature check
[deliverable/linux.git] / drivers / gpu / drm / i915 / i915_drv.c
index bdf6a1b3622353360e1ad59f5d53097c53104c8a..2fd6694fa21e56d1c8a34cc0ffc6f7951c49ec42 100644 (file)
@@ -80,6 +80,12 @@ MODULE_PARM_DESC(lvds_downclock,
                "Use panel (LVDS/eDP) downclocking for power savings "
                "(default: false)");
 
+int i915_lvds_channel_mode __read_mostly;
+module_param_named(lvds_channel_mode, i915_lvds_channel_mode, int, 0600);
+MODULE_PARM_DESC(lvds_channel_mode,
+                "Specify LVDS channel mode "
+                "(0=probe BIOS [default], 1=single-channel, 2=dual-channel)");
+
 int i915_panel_use_ssc __read_mostly = -1;
 module_param_named(lvds_use_ssc, i915_panel_use_ssc, int, 0600);
 MODULE_PARM_DESC(lvds_use_ssc,
@@ -89,8 +95,8 @@ MODULE_PARM_DESC(lvds_use_ssc,
 int i915_vbt_sdvo_panel_type __read_mostly = -1;
 module_param_named(vbt_sdvo_panel_type, i915_vbt_sdvo_panel_type, int, 0600);
 MODULE_PARM_DESC(vbt_sdvo_panel_type,
-               "Override selection of SDVO panel mode in the VBT "
-               "(default: auto)");
+               "Override/Ignore selection of SDVO panel mode in the VBT "
+               "(-2=ignore, -1=auto [default], index in VBT BIOS table)");
 
 static bool i915_try_reset __read_mostly = true;
 module_param_named(reset, i915_try_reset, bool, 0600);
@@ -103,6 +109,11 @@ MODULE_PARM_DESC(enable_hangcheck,
                "WARNING: Disabling this can cause system wide hangs. "
                "(default: true)");
 
+bool i915_enable_ppgtt __read_mostly = 1;
+module_param_named(i915_enable_ppgtt, i915_enable_ppgtt, bool, 0600);
+MODULE_PARM_DESC(i915_enable_ppgtt,
+               "Enable PPGTT (default: true)");
+
 static struct drm_driver driver;
 extern int intel_agp_enabled;
 
@@ -198,8 +209,9 @@ static const struct intel_device_info intel_pineview_info = {
 
 static const struct intel_device_info intel_ironlake_d_info = {
        .gen = 5,
-       .need_gfx_hws = 1, .has_pipe_cxsr = 1, .has_hotplug = 1,
+       .need_gfx_hws = 1, .has_hotplug = 1,
        .has_bsd_ring = 1,
+       .has_pch_split = 1,
 };
 
 static const struct intel_device_info intel_ironlake_m_info = {
@@ -207,6 +219,7 @@ static const struct intel_device_info intel_ironlake_m_info = {
        .need_gfx_hws = 1, .has_hotplug = 1,
        .has_fbc = 1,
        .has_bsd_ring = 1,
+       .has_pch_split = 1,
 };
 
 static const struct intel_device_info intel_sandybridge_d_info = {
@@ -214,6 +227,8 @@ static const struct intel_device_info intel_sandybridge_d_info = {
        .need_gfx_hws = 1, .has_hotplug = 1,
        .has_bsd_ring = 1,
        .has_blt_ring = 1,
+       .has_llc = 1,
+       .has_pch_split = 1,
 };
 
 static const struct intel_device_info intel_sandybridge_m_info = {
@@ -222,6 +237,8 @@ static const struct intel_device_info intel_sandybridge_m_info = {
        .has_fbc = 1,
        .has_bsd_ring = 1,
        .has_blt_ring = 1,
+       .has_llc = 1,
+       .has_pch_split = 1,
 };
 
 static const struct intel_device_info intel_ivybridge_d_info = {
@@ -229,6 +246,8 @@ static const struct intel_device_info intel_ivybridge_d_info = {
        .need_gfx_hws = 1, .has_hotplug = 1,
        .has_bsd_ring = 1,
        .has_blt_ring = 1,
+       .has_llc = 1,
+       .has_pch_split = 1,
 };
 
 static const struct intel_device_info intel_ivybridge_m_info = {
@@ -237,6 +256,26 @@ static const struct intel_device_info intel_ivybridge_m_info = {
        .has_fbc = 0,   /* FBC is not enabled on Ivybridge mobile yet */
        .has_bsd_ring = 1,
        .has_blt_ring = 1,
+       .has_llc = 1,
+       .has_pch_split = 1,
+};
+
+static const struct intel_device_info intel_valleyview_m_info = {
+       .gen = 7, .is_mobile = 1,
+       .need_gfx_hws = 1, .has_hotplug = 1,
+       .has_fbc = 0,
+       .has_bsd_ring = 1,
+       .has_blt_ring = 1,
+       .is_valleyview = 1,
+};
+
+static const struct intel_device_info intel_valleyview_d_info = {
+       .gen = 7,
+       .need_gfx_hws = 1, .has_hotplug = 1,
+       .has_fbc = 0,
+       .has_bsd_ring = 1,
+       .has_blt_ring = 1,
+       .is_valleyview = 1,
 };
 
 static const struct pci_device_id pciidlist[] = {              /* aka */
@@ -376,16 +415,27 @@ void gen6_gt_force_wake_get(struct drm_i915_private *dev_priv)
        spin_unlock_irqrestore(&dev_priv->gt_lock, irqflags);
 }
 
+static void gen6_gt_check_fifodbg(struct drm_i915_private *dev_priv)
+{
+       u32 gtfifodbg;
+       gtfifodbg = I915_READ_NOTRACE(GTFIFODBG);
+       if (WARN(gtfifodbg & GT_FIFO_CPU_ERROR_MASK,
+            "MMIO read or write has been dropped %x\n", gtfifodbg))
+               I915_WRITE_NOTRACE(GTFIFODBG, GT_FIFO_CPU_ERROR_MASK);
+}
+
 void __gen6_gt_force_wake_put(struct drm_i915_private *dev_priv)
 {
        I915_WRITE_NOTRACE(FORCEWAKE, 0);
-       POSTING_READ(FORCEWAKE);
+       /* The below doubles as a POSTING_READ */
+       gen6_gt_check_fifodbg(dev_priv);
 }
 
 void __gen6_gt_force_wake_mt_put(struct drm_i915_private *dev_priv)
 {
        I915_WRITE_NOTRACE(FORCEWAKE_MT, (1<<16) | 0);
-       POSTING_READ(FORCEWAKE_MT);
+       /* The below doubles as a POSTING_READ */
+       gen6_gt_check_fifodbg(dev_priv);
 }
 
 /*
@@ -401,8 +451,10 @@ void gen6_gt_force_wake_put(struct drm_i915_private *dev_priv)
        spin_unlock_irqrestore(&dev_priv->gt_lock, irqflags);
 }
 
-void __gen6_gt_wait_for_fifo(struct drm_i915_private *dev_priv)
+int __gen6_gt_wait_for_fifo(struct drm_i915_private *dev_priv)
 {
+       int ret = 0;
+
        if (dev_priv->gt_fifo_count < GT_FIFO_NUM_RESERVED_ENTRIES) {
                int loop = 500;
                u32 fifo = I915_READ_NOTRACE(GT_FIFO_FREE_ENTRIES);
@@ -410,10 +462,38 @@ void __gen6_gt_wait_for_fifo(struct drm_i915_private *dev_priv)
                        udelay(10);
                        fifo = I915_READ_NOTRACE(GT_FIFO_FREE_ENTRIES);
                }
-               WARN_ON(loop < 0 && fifo <= GT_FIFO_NUM_RESERVED_ENTRIES);
+               if (WARN_ON(loop < 0 && fifo <= GT_FIFO_NUM_RESERVED_ENTRIES))
+                       ++ret;
                dev_priv->gt_fifo_count = fifo;
        }
        dev_priv->gt_fifo_count--;
+
+       return ret;
+}
+
+void vlv_force_wake_get(struct drm_i915_private *dev_priv)
+{
+       int count;
+
+       count = 0;
+
+       /* Already awake? */
+       if ((I915_READ(0x130094) & 0xa1) == 0xa1)
+               return;
+
+       I915_WRITE_NOTRACE(FORCEWAKE_VLV, 0xffffffff);
+       POSTING_READ(FORCEWAKE_VLV);
+
+       count = 0;
+       while (count++ < 50 && (I915_READ_NOTRACE(FORCEWAKE_ACK_VLV) & 1) == 0)
+               udelay(10);
+}
+
+void vlv_force_wake_put(struct drm_i915_private *dev_priv)
+{
+       I915_WRITE_NOTRACE(FORCEWAKE_VLV, 0xffff0000);
+       /* FIXME: confirm VLV behavior with Punit folks */
+       POSTING_READ(FORCEWAKE_VLV);
 }
 
 static int i915_drm_freeze(struct drm_device *dev)
@@ -494,7 +574,7 @@ static int i915_drm_thaw(struct drm_device *dev)
                mutex_lock(&dev->struct_mutex);
                dev_priv->mm.suspended = 0;
 
-               error = i915_gem_init_ringbuffer(dev);
+               error = i915_gem_init_hw(dev);
                mutex_unlock(&dev->struct_mutex);
 
                if (HAS_PCH_SPLIT(dev))
@@ -600,13 +680,40 @@ static int ironlake_do_reset(struct drm_device *dev, u8 flags)
 static int gen6_do_reset(struct drm_device *dev, u8 flags)
 {
        struct drm_i915_private *dev_priv = dev->dev_private;
+       int     ret;
+       unsigned long irqflags;
+
+       /* Hold gt_lock across reset to prevent any register access
+        * with forcewake not set correctly
+        */
+       spin_lock_irqsave(&dev_priv->gt_lock, irqflags);
+
+       /* Reset the chip */
 
-       I915_WRITE(GEN6_GDRST, GEN6_GRDOM_FULL);
-       return wait_for((I915_READ(GEN6_GDRST) & GEN6_GRDOM_FULL) == 0, 500);
+       /* GEN6_GDRST is not in the gt power well, no need to check
+        * for fifo space for the write or forcewake the chip for
+        * the read
+        */
+       I915_WRITE_NOTRACE(GEN6_GDRST, GEN6_GRDOM_FULL);
+
+       /* Spin waiting for the device to ack the reset request */
+       ret = wait_for((I915_READ_NOTRACE(GEN6_GDRST) & GEN6_GRDOM_FULL) == 0, 500);
+
+       /* If reset with a user forcewake, try to restore, otherwise turn it off */
+       if (dev_priv->forcewake_count)
+               dev_priv->display.force_wake_get(dev_priv);
+       else
+               dev_priv->display.force_wake_put(dev_priv);
+
+       /* Restore fifo count */
+       dev_priv->gt_fifo_count = I915_READ_NOTRACE(GT_FIFO_FREE_ENTRIES);
+
+       spin_unlock_irqrestore(&dev_priv->gt_lock, irqflags);
+       return ret;
 }
 
 /**
- * i965_reset - reset chip after a hang
+ * i915_reset - reset chip after a hang
  * @dev: drm device to reset
  * @flags: reset domains
  *
@@ -629,7 +736,6 @@ int i915_reset(struct drm_device *dev, u8 flags)
         * need to
         */
        bool need_display = true;
-       unsigned long irqflags;
        int ret;
 
        if (!i915_try_reset)
@@ -647,11 +753,6 @@ int i915_reset(struct drm_device *dev, u8 flags)
        case 7:
        case 6:
                ret = gen6_do_reset(dev, flags);
-               /* If reset with a user forcewake, try to restore */
-               spin_lock_irqsave(&dev_priv->gt_lock, irqflags);
-               if (dev_priv->forcewake_count)
-                       dev_priv->display.force_wake_get(dev_priv);
-               spin_unlock_irqrestore(&dev_priv->gt_lock, irqflags);
                break;
        case 5:
                ret = ironlake_do_reset(dev, flags);
@@ -688,12 +789,16 @@ int i915_reset(struct drm_device *dev, u8 flags)
                        !dev_priv->mm.suspended) {
                dev_priv->mm.suspended = 0;
 
+               i915_gem_init_swizzling(dev);
+
                dev_priv->ring[RCS].init(&dev_priv->ring[RCS]);
                if (HAS_BSD(dev))
                    dev_priv->ring[VCS].init(&dev_priv->ring[VCS]);
                if (HAS_BLT(dev))
                    dev_priv->ring[BCS].init(&dev_priv->ring[BCS]);
 
+               i915_gem_init_ppgtt(dev);
+
                mutex_unlock(&dev->struct_mutex);
                drm_irq_uninstall(dev);
                drm_mode_config_reset(dev);
@@ -929,13 +1034,25 @@ MODULE_AUTHOR(DRIVER_AUTHOR);
 MODULE_DESCRIPTION(DRIVER_DESC);
 MODULE_LICENSE("GPL and additional rights");
 
+/* We give fast paths for the really cool registers */
+#define NEEDS_FORCE_WAKE(dev_priv, reg) \
+       (((dev_priv)->info->gen >= 6) && \
+        ((reg) < 0x40000) &&            \
+        ((reg) != FORCEWAKE)) && \
+       (!IS_VALLEYVIEW((dev_priv)->dev))
+
 #define __i915_read(x, y) \
 u##x i915_read##x(struct drm_i915_private *dev_priv, u32 reg) { \
        u##x val = 0; \
        if (NEEDS_FORCE_WAKE((dev_priv), (reg))) { \
-               gen6_gt_force_wake_get(dev_priv); \
+               unsigned long irqflags; \
+               spin_lock_irqsave(&dev_priv->gt_lock, irqflags); \
+               if (dev_priv->forcewake_count == 0) \
+                       dev_priv->display.force_wake_get(dev_priv); \
                val = read##y(dev_priv->regs + reg); \
-               gen6_gt_force_wake_put(dev_priv); \
+               if (dev_priv->forcewake_count == 0) \
+                       dev_priv->display.force_wake_put(dev_priv); \
+               spin_unlock_irqrestore(&dev_priv->gt_lock, irqflags); \
        } else { \
                val = read##y(dev_priv->regs + reg); \
        } \
@@ -951,11 +1068,15 @@ __i915_read(64, q)
 
 #define __i915_write(x, y) \
 void i915_write##x(struct drm_i915_private *dev_priv, u32 reg, u##x val) { \
+       u32 __fifo_ret = 0; \
        trace_i915_reg_rw(true, reg, val, sizeof(val)); \
        if (NEEDS_FORCE_WAKE((dev_priv), (reg))) { \
-               __gen6_gt_wait_for_fifo(dev_priv); \
+               __fifo_ret = __gen6_gt_wait_for_fifo(dev_priv); \
        } \
        write##y(val, dev_priv->regs + reg); \
+       if (unlikely(__fifo_ret)) { \
+               gen6_gt_check_fifodbg(dev_priv); \
+       } \
 }
 __i915_write(8, b)
 __i915_write(16, w)
This page took 0.042394 seconds and 5 git commands to generate.