Merge tag 'topic/drm-misc-2015-10-19' of git://anongit.freedesktop.org/drm-intel...
[linux-drm-fsl-dcu.git] / drivers / gpu / drm / i915 / i915_dma.c
index 68b0c9eb9282e00154dbec5a8c997aceb6222a31..2336af92d94bb5c5d3d101227cce4b8041feffb7 100644 (file)
@@ -335,12 +335,12 @@ static void i915_switcheroo_set_state(struct pci_dev *pdev, enum vga_switcheroo_
                dev->switch_power_state = DRM_SWITCH_POWER_CHANGING;
                /* i915 resume handler doesn't set to D0 */
                pci_set_power_state(dev->pdev, PCI_D0);
-               i915_resume_legacy(dev);
+               i915_resume_switcheroo(dev);
                dev->switch_power_state = DRM_SWITCH_POWER_ON;
        } else {
                pr_err("switched off\n");
                dev->switch_power_state = DRM_SWITCH_POWER_CHANGING;
-               i915_suspend_legacy(dev, pmm);
+               i915_suspend_switcheroo(dev, pmm);
                dev->switch_power_state = DRM_SWITCH_POWER_OFF;
        }
 }
@@ -406,6 +406,11 @@ static int i915_load_modeset_init(struct drm_device *dev)
         * working irqs for e.g. gmbus and dp aux transfers. */
        intel_modeset_init(dev);
 
+       /* intel_guc_ucode_init() needs the mutex to allocate GEM objects */
+       mutex_lock(&dev->struct_mutex);
+       intel_guc_ucode_init(dev);
+       mutex_unlock(&dev->struct_mutex);
+
        ret = i915_gem_init(dev);
        if (ret)
                goto cleanup_irq;
@@ -447,6 +452,9 @@ cleanup_gem:
        i915_gem_context_fini(dev);
        mutex_unlock(&dev->struct_mutex);
 cleanup_irq:
+       mutex_lock(&dev->struct_mutex);
+       intel_guc_ucode_fini(dev);
+       mutex_unlock(&dev->struct_mutex);
        drm_irq_uninstall(dev);
 cleanup_gem_stolen:
        i915_gem_cleanup_stolen(dev);
@@ -594,17 +602,6 @@ static void gen9_sseu_info_init(struct drm_device *dev)
        u32 fuse2, s_enable, ss_disable, eu_disable;
        u8 eu_mask = 0xff;
 
-       /*
-        * BXT has a single slice. BXT also has at most 6 EU per subslice,
-        * and therefore only the lowest 6 bits of the 8-bit EU disable
-        * fields are valid.
-       */
-       if (IS_BROXTON(dev)) {
-               s_max = 1;
-               eu_max = 6;
-               eu_mask = 0x3f;
-       }
-
        info = (struct intel_device_info *)&dev_priv->info;
        fuse2 = I915_READ(GEN8_FUSE2);
        s_enable = (fuse2 & GEN8_F2_S_ENA_MASK) >>
@@ -676,6 +673,82 @@ static void gen9_sseu_info_init(struct drm_device *dev)
        info->has_eu_pg = (info->eu_per_subslice > 2);
 }
 
+static void broadwell_sseu_info_init(struct drm_device *dev)
+{
+       struct drm_i915_private *dev_priv = dev->dev_private;
+       struct intel_device_info *info;
+       const int s_max = 3, ss_max = 3, eu_max = 8;
+       int s, ss;
+       u32 fuse2, eu_disable[s_max], s_enable, ss_disable;
+
+       fuse2 = I915_READ(GEN8_FUSE2);
+       s_enable = (fuse2 & GEN8_F2_S_ENA_MASK) >> GEN8_F2_S_ENA_SHIFT;
+       ss_disable = (fuse2 & GEN8_F2_SS_DIS_MASK) >> GEN8_F2_SS_DIS_SHIFT;
+
+       eu_disable[0] = I915_READ(GEN8_EU_DISABLE0) & GEN8_EU_DIS0_S0_MASK;
+       eu_disable[1] = (I915_READ(GEN8_EU_DISABLE0) >> GEN8_EU_DIS0_S1_SHIFT) |
+                       ((I915_READ(GEN8_EU_DISABLE1) & GEN8_EU_DIS1_S1_MASK) <<
+                        (32 - GEN8_EU_DIS0_S1_SHIFT));
+       eu_disable[2] = (I915_READ(GEN8_EU_DISABLE1) >> GEN8_EU_DIS1_S2_SHIFT) |
+                       ((I915_READ(GEN8_EU_DISABLE2) & GEN8_EU_DIS2_S2_MASK) <<
+                        (32 - GEN8_EU_DIS1_S2_SHIFT));
+
+
+       info = (struct intel_device_info *)&dev_priv->info;
+       info->slice_total = hweight32(s_enable);
+
+       /*
+        * The subslice disable field is global, i.e. it applies
+        * to each of the enabled slices.
+        */
+       info->subslice_per_slice = ss_max - hweight32(ss_disable);
+       info->subslice_total = info->slice_total * info->subslice_per_slice;
+
+       /*
+        * Iterate through enabled slices and subslices to
+        * count the total enabled EU.
+        */
+       for (s = 0; s < s_max; s++) {
+               if (!(s_enable & (0x1 << s)))
+                       /* skip disabled slice */
+                       continue;
+
+               for (ss = 0; ss < ss_max; ss++) {
+                       u32 n_disabled;
+
+                       if (ss_disable & (0x1 << ss))
+                               /* skip disabled subslice */
+                               continue;
+
+                       n_disabled = hweight8(eu_disable[s] >> (ss * eu_max));
+
+                       /*
+                        * Record which subslices have 7 EUs.
+                        */
+                       if (eu_max - n_disabled == 7)
+                               info->subslice_7eu[s] |= 1 << ss;
+
+                       info->eu_total += eu_max - n_disabled;
+               }
+       }
+
+       /*
+        * BDW is expected to always have a uniform distribution of EU across
+        * subslices with the exception that any one EU in any one subslice may
+        * be fused off for die recovery.
+        */
+       info->eu_per_subslice = info->subslice_total ?
+               DIV_ROUND_UP(info->eu_total, info->subslice_total) : 0;
+
+       /*
+        * BDW supports slice power gating on devices with more than
+        * one slice.
+        */
+       info->has_slice_pg = (info->slice_total > 1);
+       info->has_subslice_pg = 0;
+       info->has_eu_pg = 0;
+}
+
 /*
  * Determine various intel_device_info fields at runtime.
  *
@@ -746,6 +819,8 @@ static void intel_device_info_runtime_init(struct drm_device *dev)
        /* Initialize slice/subslice/EU info */
        if (IS_CHERRYVIEW(dev))
                cherryview_sseu_info_init(dev);
+       else if (IS_BROADWELL(dev))
+               broadwell_sseu_info_init(dev);
        else if (INTEL_INFO(dev)->gen >= 9)
                gen9_sseu_info_init(dev);
 
@@ -762,6 +837,24 @@ static void intel_device_info_runtime_init(struct drm_device *dev)
                         info->has_eu_pg ? "y" : "n");
 }
 
+static void intel_init_dpio(struct drm_i915_private *dev_priv)
+{
+       if (!IS_VALLEYVIEW(dev_priv))
+               return;
+
+       /*
+        * IOSF_PORT_DPIO is used for VLV x2 PHY (DP/HDMI B and C),
+        * CHV x1 PHY (DP/HDMI D)
+        * IOSF_PORT_DPIO_2 is used for CHV x2 PHY (DP/HDMI B and C)
+        */
+       if (IS_CHERRYVIEW(dev_priv)) {
+               DPIO_PHY_IOSF_PORT(DPIO_PHY0) = IOSF_PORT_DPIO_2;
+               DPIO_PHY_IOSF_PORT(DPIO_PHY1) = IOSF_PORT_DPIO;
+       } else {
+               DPIO_PHY_IOSF_PORT(DPIO_PHY0) = IOSF_PORT_DPIO;
+       }
+}
+
 /**
  * i915_driver_load - setup chip and create an initial config
  * @dev: DRM device
@@ -803,6 +896,7 @@ int i915_driver_load(struct drm_device *dev, unsigned long flags)
        mutex_init(&dev_priv->sb_lock);
        mutex_init(&dev_priv->modeset_restore_lock);
        mutex_init(&dev_priv->csr_lock);
+       mutex_init(&dev_priv->av_mutex);
 
        intel_pm_setup(dev);
 
@@ -942,8 +1036,6 @@ int i915_driver_load(struct drm_device *dev, unsigned long flags)
        intel_setup_gmbus(dev);
        intel_opregion_setup(dev);
 
-       intel_setup_bios(dev);
-
        i915_gem_load(dev);
 
        /* On the 945G/GM, the chipset reports the MSI capability on the
@@ -962,6 +1054,8 @@ int i915_driver_load(struct drm_device *dev, unsigned long flags)
 
        intel_device_info_runtime_init(dev);
 
+       intel_init_dpio(dev_priv);
+
        if (INTEL_INFO(dev)->num_pipes) {
                ret = drm_vblank_init(dev, INTEL_INFO(dev)->num_pipes);
                if (ret)
@@ -1030,12 +1124,9 @@ out_freecsr:
 put_bridge:
        pci_dev_put(dev_priv->bridge_dev);
 free_priv:
-       if (dev_priv->requests)
-               kmem_cache_destroy(dev_priv->requests);
-       if (dev_priv->vmas)
-               kmem_cache_destroy(dev_priv->vmas);
-       if (dev_priv->objects)
-               kmem_cache_destroy(dev_priv->objects);
+       kmem_cache_destroy(dev_priv->requests);
+       kmem_cache_destroy(dev_priv->vmas);
+       kmem_cache_destroy(dev_priv->objects);
        kfree(dev_priv);
        return ret;
 }
@@ -1082,6 +1173,10 @@ int i915_driver_unload(struct drm_device *dev)
                dev_priv->vbt.child_dev = NULL;
                dev_priv->vbt.child_dev_num = 0;
        }
+       kfree(dev_priv->vbt.sdvo_lvds_vbt_mode);
+       dev_priv->vbt.sdvo_lvds_vbt_mode = NULL;
+       kfree(dev_priv->vbt.lfp_lvds_vbt_mode);
+       dev_priv->vbt.lfp_lvds_vbt_mode = NULL;
 
        vga_switcheroo_unregister_client(dev->pdev);
        vga_client_register(dev->pdev, NULL, NULL, NULL);
@@ -1099,6 +1194,7 @@ int i915_driver_unload(struct drm_device *dev)
        flush_workqueue(dev_priv->wq);
 
        mutex_lock(&dev->struct_mutex);
+       intel_guc_ucode_fini(dev);
        i915_gem_cleanup_ringbuffer(dev);
        i915_gem_context_fini(dev);
        mutex_unlock(&dev->struct_mutex);
@@ -1121,13 +1217,9 @@ int i915_driver_unload(struct drm_device *dev)
        if (dev_priv->regs != NULL)
                pci_iounmap(dev->pdev, dev_priv->regs);
 
-       if (dev_priv->requests)
-               kmem_cache_destroy(dev_priv->requests);
-       if (dev_priv->vmas)
-               kmem_cache_destroy(dev_priv->vmas);
-       if (dev_priv->objects)
-               kmem_cache_destroy(dev_priv->objects);
-
+       kmem_cache_destroy(dev_priv->requests);
+       kmem_cache_destroy(dev_priv->vmas);
+       kmem_cache_destroy(dev_priv->objects);
        pci_dev_put(dev_priv->bridge_dev);
        kfree(dev_priv);