]> git.proxmox.com Git - mirror_ubuntu-artful-kernel.git/blobdiff - drivers/gpu/drm/i915/i915_drv.c
drm/i915: Abstract PPGTT enabling
[mirror_ubuntu-artful-kernel.git] / drivers / gpu / drm / i915 / i915_drv.c
index e9b57893db2b1ebba1348a71e37c845f98c3286b..70d10de73bbd21303c8a5d9756be3d59e051e1f7 100644 (file)
@@ -121,9 +121,7 @@ MODULE_PARM_DESC(i915_enable_ppgtt,
 unsigned int i915_preliminary_hw_support __read_mostly = 0;
 module_param_named(preliminary_hw_support, i915_preliminary_hw_support, int, 0600);
 MODULE_PARM_DESC(preliminary_hw_support,
-               "Enable preliminary hardware support. "
-               "Enable Haswell and ValleyView Support. "
-               "(default: false)");
+               "Enable preliminary hardware support. (default: false)");
 
 int i915_disable_power_well __read_mostly = 0;
 module_param_named(disable_power_well, i915_disable_power_well, int, 0600);
@@ -142,75 +140,85 @@ extern int intel_agp_enabled;
        .subdevice = PCI_ANY_ID,                \
        .driver_data = (unsigned long) info }
 
+#define INTEL_QUANTA_VGA_DEVICE(info) {                \
+       .class = PCI_BASE_CLASS_DISPLAY << 16,  \
+       .class_mask = 0xff0000,                 \
+       .vendor = 0x8086,                       \
+       .device = 0x16a,                        \
+       .subvendor = 0x152d,                    \
+       .subdevice = 0x8990,                    \
+       .driver_data = (unsigned long) info }
+
+
 static const struct intel_device_info intel_i830_info = {
-       .gen = 2, .is_mobile = 1, .cursor_needs_physical = 1,
+       .gen = 2, .is_mobile = 1, .cursor_needs_physical = 1, .num_pipes = 2,
        .has_overlay = 1, .overlay_needs_physical = 1,
 };
 
 static const struct intel_device_info intel_845g_info = {
-       .gen = 2,
+       .gen = 2, .num_pipes = 1,
        .has_overlay = 1, .overlay_needs_physical = 1,
 };
 
 static const struct intel_device_info intel_i85x_info = {
-       .gen = 2, .is_i85x = 1, .is_mobile = 1,
+       .gen = 2, .is_i85x = 1, .is_mobile = 1, .num_pipes = 2,
        .cursor_needs_physical = 1,
        .has_overlay = 1, .overlay_needs_physical = 1,
 };
 
 static const struct intel_device_info intel_i865g_info = {
-       .gen = 2,
+       .gen = 2, .num_pipes = 1,
        .has_overlay = 1, .overlay_needs_physical = 1,
 };
 
 static const struct intel_device_info intel_i915g_info = {
-       .gen = 3, .is_i915g = 1, .cursor_needs_physical = 1,
+       .gen = 3, .is_i915g = 1, .cursor_needs_physical = 1, .num_pipes = 2,
        .has_overlay = 1, .overlay_needs_physical = 1,
 };
 static const struct intel_device_info intel_i915gm_info = {
-       .gen = 3, .is_mobile = 1,
+       .gen = 3, .is_mobile = 1, .num_pipes = 2,
        .cursor_needs_physical = 1,
        .has_overlay = 1, .overlay_needs_physical = 1,
        .supports_tv = 1,
 };
 static const struct intel_device_info intel_i945g_info = {
-       .gen = 3, .has_hotplug = 1, .cursor_needs_physical = 1,
+       .gen = 3, .has_hotplug = 1, .cursor_needs_physical = 1, .num_pipes = 2,
        .has_overlay = 1, .overlay_needs_physical = 1,
 };
 static const struct intel_device_info intel_i945gm_info = {
-       .gen = 3, .is_i945gm = 1, .is_mobile = 1,
+       .gen = 3, .is_i945gm = 1, .is_mobile = 1, .num_pipes = 2,
        .has_hotplug = 1, .cursor_needs_physical = 1,
        .has_overlay = 1, .overlay_needs_physical = 1,
        .supports_tv = 1,
 };
 
 static const struct intel_device_info intel_i965g_info = {
-       .gen = 4, .is_broadwater = 1,
+       .gen = 4, .is_broadwater = 1, .num_pipes = 2,
        .has_hotplug = 1,
        .has_overlay = 1,
 };
 
 static const struct intel_device_info intel_i965gm_info = {
-       .gen = 4, .is_crestline = 1,
+       .gen = 4, .is_crestline = 1, .num_pipes = 2,
        .is_mobile = 1, .has_fbc = 1, .has_hotplug = 1,
        .has_overlay = 1,
        .supports_tv = 1,
 };
 
 static const struct intel_device_info intel_g33_info = {
-       .gen = 3, .is_g33 = 1,
+       .gen = 3, .is_g33 = 1, .num_pipes = 2,
        .need_gfx_hws = 1, .has_hotplug = 1,
        .has_overlay = 1,
 };
 
 static const struct intel_device_info intel_g45_info = {
-       .gen = 4, .is_g4x = 1, .need_gfx_hws = 1,
+       .gen = 4, .is_g4x = 1, .need_gfx_hws = 1, .num_pipes = 2,
        .has_pipe_cxsr = 1, .has_hotplug = 1,
        .has_bsd_ring = 1,
 };
 
 static const struct intel_device_info intel_gm45_info = {
-       .gen = 4, .is_g4x = 1,
+       .gen = 4, .is_g4x = 1, .num_pipes = 2,
        .is_mobile = 1, .need_gfx_hws = 1, .has_fbc = 1,
        .has_pipe_cxsr = 1, .has_hotplug = 1,
        .supports_tv = 1,
@@ -218,26 +226,26 @@ static const struct intel_device_info intel_gm45_info = {
 };
 
 static const struct intel_device_info intel_pineview_info = {
-       .gen = 3, .is_g33 = 1, .is_pineview = 1, .is_mobile = 1,
+       .gen = 3, .is_g33 = 1, .is_pineview = 1, .is_mobile = 1, .num_pipes = 2,
        .need_gfx_hws = 1, .has_hotplug = 1,
        .has_overlay = 1,
 };
 
 static const struct intel_device_info intel_ironlake_d_info = {
-       .gen = 5,
+       .gen = 5, .num_pipes = 2,
        .need_gfx_hws = 1, .has_hotplug = 1,
        .has_bsd_ring = 1,
 };
 
 static const struct intel_device_info intel_ironlake_m_info = {
-       .gen = 5, .is_mobile = 1,
+       .gen = 5, .is_mobile = 1, .num_pipes = 2,
        .need_gfx_hws = 1, .has_hotplug = 1,
        .has_fbc = 1,
        .has_bsd_ring = 1,
 };
 
 static const struct intel_device_info intel_sandybridge_d_info = {
-       .gen = 6,
+       .gen = 6, .num_pipes = 2,
        .need_gfx_hws = 1, .has_hotplug = 1,
        .has_bsd_ring = 1,
        .has_blt_ring = 1,
@@ -246,7 +254,7 @@ static const struct intel_device_info intel_sandybridge_d_info = {
 };
 
 static const struct intel_device_info intel_sandybridge_m_info = {
-       .gen = 6, .is_mobile = 1,
+       .gen = 6, .is_mobile = 1, .num_pipes = 2,
        .need_gfx_hws = 1, .has_hotplug = 1,
        .has_fbc = 1,
        .has_bsd_ring = 1,
@@ -255,61 +263,55 @@ static const struct intel_device_info intel_sandybridge_m_info = {
        .has_force_wake = 1,
 };
 
+#define GEN7_FEATURES  \
+       .gen = 7, .num_pipes = 3, \
+       .need_gfx_hws = 1, .has_hotplug = 1, \
+       .has_bsd_ring = 1, \
+       .has_blt_ring = 1, \
+       .has_llc = 1, \
+       .has_force_wake = 1
+
 static const struct intel_device_info intel_ivybridge_d_info = {
-       .is_ivybridge = 1, .gen = 7,
-       .need_gfx_hws = 1, .has_hotplug = 1,
-       .has_bsd_ring = 1,
-       .has_blt_ring = 1,
-       .has_llc = 1,
-       .has_force_wake = 1,
+       GEN7_FEATURES,
+       .is_ivybridge = 1,
 };
 
 static const struct intel_device_info intel_ivybridge_m_info = {
-       .is_ivybridge = 1, .gen = 7, .is_mobile = 1,
-       .need_gfx_hws = 1, .has_hotplug = 1,
-       .has_fbc = 0,   /* FBC is not enabled on Ivybridge mobile yet */
-       .has_bsd_ring = 1,
-       .has_blt_ring = 1,
-       .has_llc = 1,
-       .has_force_wake = 1,
+       GEN7_FEATURES,
+       .is_ivybridge = 1,
+       .is_mobile = 1,
+};
+
+static const struct intel_device_info intel_ivybridge_q_info = {
+       GEN7_FEATURES,
+       .is_ivybridge = 1,
+       .num_pipes = 0, /* legal, last one wins */
 };
 
 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,
+       GEN7_FEATURES,
+       .is_mobile = 1,
+       .num_pipes = 2,
        .is_valleyview = 1,
        .display_mmio_offset = VLV_DISPLAY_BASE,
 };
 
 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,
+       GEN7_FEATURES,
+       .num_pipes = 2,
        .is_valleyview = 1,
        .display_mmio_offset = VLV_DISPLAY_BASE,
 };
 
 static const struct intel_device_info intel_haswell_d_info = {
-       .is_haswell = 1, .gen = 7,
-       .need_gfx_hws = 1, .has_hotplug = 1,
-       .has_bsd_ring = 1,
-       .has_blt_ring = 1,
-       .has_llc = 1,
-       .has_force_wake = 1,
+       GEN7_FEATURES,
+       .is_haswell = 1,
 };
 
 static const struct intel_device_info intel_haswell_m_info = {
-       .is_haswell = 1, .gen = 7, .is_mobile = 1,
-       .need_gfx_hws = 1, .has_hotplug = 1,
-       .has_bsd_ring = 1,
-       .has_blt_ring = 1,
-       .has_llc = 1,
-       .has_force_wake = 1,
+       GEN7_FEATURES,
+       .is_haswell = 1,
+       .is_mobile = 1,
 };
 
 static const struct pci_device_id pciidlist[] = {              /* aka */
@@ -356,6 +358,7 @@ static const struct pci_device_id pciidlist[] = {           /* aka */
        INTEL_VGA_DEVICE(0x0152, &intel_ivybridge_d_info), /* GT1 desktop */
        INTEL_VGA_DEVICE(0x0162, &intel_ivybridge_d_info), /* GT2 desktop */
        INTEL_VGA_DEVICE(0x015a, &intel_ivybridge_d_info), /* GT1 server */
+       INTEL_QUANTA_VGA_DEVICE(&intel_ivybridge_q_info), /* Quanta transcode */
        INTEL_VGA_DEVICE(0x016a, &intel_ivybridge_d_info), /* GT2 server */
        INTEL_VGA_DEVICE(0x0402, &intel_haswell_d_info), /* GT1 desktop */
        INTEL_VGA_DEVICE(0x0412, &intel_haswell_d_info), /* GT2 desktop */
@@ -394,6 +397,9 @@ static const struct pci_device_id pciidlist[] = {           /* aka */
        INTEL_VGA_DEVICE(0x0D16, &intel_haswell_m_info), /* CRW GT2 mobile */
        INTEL_VGA_DEVICE(0x0D26, &intel_haswell_m_info), /* CRW GT2 mobile */
        INTEL_VGA_DEVICE(0x0f30, &intel_valleyview_m_info),
+       INTEL_VGA_DEVICE(0x0f31, &intel_valleyview_m_info),
+       INTEL_VGA_DEVICE(0x0f32, &intel_valleyview_m_info),
+       INTEL_VGA_DEVICE(0x0f33, &intel_valleyview_m_info),
        INTEL_VGA_DEVICE(0x0157, &intel_valleyview_m_info),
        INTEL_VGA_DEVICE(0x0155, &intel_valleyview_d_info),
        {0, 0, 0}
@@ -408,6 +414,15 @@ void intel_detect_pch(struct drm_device *dev)
        struct drm_i915_private *dev_priv = dev->dev_private;
        struct pci_dev *pch;
 
+       /* In all current cases, num_pipes is equivalent to the PCH_NOP setting
+        * (which really amounts to a PCH but no South Display).
+        */
+       if (INTEL_INFO(dev)->num_pipes == 0) {
+               dev_priv->pch_type = PCH_NOP;
+               dev_priv->num_pch_pll = 0;
+               return;
+       }
+
        /*
         * The reason to probe ISA bridge instead of Dev31:Fun0 is to
         * make graphics device passthrough work easy for VMM, that only
@@ -474,6 +489,7 @@ bool i915_semaphore_is_enabled(struct drm_device *dev)
 static int i915_drm_freeze(struct drm_device *dev)
 {
        struct drm_i915_private *dev_priv = dev->dev_private;
+       struct drm_crtc *crtc;
 
        /* ignore lid events during suspend */
        mutex_lock(&dev_priv->modeset_restore_lock);
@@ -497,10 +513,14 @@ static int i915_drm_freeze(struct drm_device *dev)
 
                cancel_delayed_work_sync(&dev_priv->rps.delayed_resume_work);
 
-               intel_modeset_disable(dev);
-
                drm_irq_uninstall(dev);
                dev_priv->enable_hotplug_processing = false;
+               /*
+                * Disable CRTCs directly since we want to preserve sw state
+                * for _thaw.
+                */
+               list_for_each_entry(crtc, &dev->mode_config.crtc_list, head)
+                       dev_priv->display.crtc_disable(crtc);
        }
 
        i915_save_state(dev);
@@ -556,6 +576,24 @@ void intel_console_resume(struct work_struct *work)
        console_unlock();
 }
 
+static void intel_resume_hotplug(struct drm_device *dev)
+{
+       struct drm_mode_config *mode_config = &dev->mode_config;
+       struct intel_encoder *encoder;
+
+       mutex_lock(&mode_config->mutex);
+       DRM_DEBUG_KMS("running encoder hotplug functions\n");
+
+       list_for_each_entry(encoder, &mode_config->encoder_list, base.head)
+               if (encoder->hot_plug)
+                       encoder->hot_plug(encoder);
+
+       mutex_unlock(&mode_config->mutex);
+
+       /* Just fire off a uevent and let userspace tell us what to do */
+       drm_helper_hpd_irq_event(dev);
+}
+
 static int __i915_drm_thaw(struct drm_device *dev)
 {
        struct drm_i915_private *dev_priv = dev->dev_private;
@@ -578,7 +616,10 @@ static int __i915_drm_thaw(struct drm_device *dev)
                drm_irq_install(dev);
 
                intel_modeset_init_hw(dev);
-               intel_modeset_setup_hw_state(dev, false);
+
+               drm_modeset_lock_all(dev);
+               intel_modeset_setup_hw_state(dev, true);
+               drm_modeset_unlock_all(dev);
 
                /*
                 * ... but also need to make sure that hotplug processing
@@ -588,6 +629,8 @@ static int __i915_drm_thaw(struct drm_device *dev)
                 * */
                intel_hpd_init(dev);
                dev_priv->enable_hotplug_processing = true;
+               /* Config may have changed between suspend and resume */
+               intel_resume_hotplug(dev);
        }
 
        intel_opregion_init(dev);
@@ -732,6 +775,7 @@ static int ironlake_do_reset(struct drm_device *dev)
        int ret;
 
        gdrst = I915_READ(MCHBAR_MIRROR_BASE + ILK_GDSR);
+       gdrst &= ~GRDOM_MASK;
        I915_WRITE(MCHBAR_MIRROR_BASE + ILK_GDSR,
                   gdrst | GRDOM_RENDER | GRDOM_RESET_ENABLE);
        ret = wait_for(I915_READ(MCHBAR_MIRROR_BASE + ILK_GDSR) & 0x1, 500);
@@ -740,6 +784,7 @@ static int ironlake_do_reset(struct drm_device *dev)
 
        /* We can't reset render&media without also resetting display ... */
        gdrst = I915_READ(MCHBAR_MIRROR_BASE + ILK_GDSR);
+       gdrst &= ~GRDOM_MASK;
        I915_WRITE(MCHBAR_MIRROR_BASE + ILK_GDSR,
                   gdrst | GRDOM_MEDIA | GRDOM_RESET_ENABLE);
        return wait_for(I915_READ(MCHBAR_MIRROR_BASE + ILK_GDSR) & 0x1, 500);
@@ -803,7 +848,7 @@ int intel_gpu_reset(struct drm_device *dev)
 
        /* Also reset the gpu hangman. */
        if (dev_priv->gpu_error.stop_rings) {
-               DRM_DEBUG("Simulated gpu hang, resetting stop_rings\n");
+               DRM_INFO("Simulated gpu hang, resetting stop_rings\n");
                dev_priv->gpu_error.stop_rings = 0;
                if (ret == -ENODEV) {
                        DRM_ERROR("Reset not implemented, but ignoring "
@@ -882,7 +927,8 @@ int i915_reset(struct drm_device *dev)
                        ring->init(ring);
 
                i915_gem_context_init(dev);
-               i915_gem_init_ppgtt(dev);
+               if (dev_priv->mm.aliasing_ppgtt)
+                       dev_priv->mm.aliasing_ppgtt->enable(dev);
 
                /*
                 * It would make sense to re-init all the other hw state, at
@@ -1147,6 +1193,27 @@ ilk_dummy_write(struct drm_i915_private *dev_priv)
        I915_WRITE_NOTRACE(MI_MODE, 0);
 }
 
+static void
+hsw_unclaimed_reg_clear(struct drm_i915_private *dev_priv, u32 reg)
+{
+       if (IS_HASWELL(dev_priv->dev) &&
+           (I915_READ_NOTRACE(FPGA_DBG) & FPGA_DBG_RM_NOCLAIM)) {
+               DRM_ERROR("Unknown unclaimed register before writing to %x\n",
+                         reg);
+               I915_WRITE_NOTRACE(FPGA_DBG, FPGA_DBG_RM_NOCLAIM);
+       }
+}
+
+static void
+hsw_unclaimed_reg_check(struct drm_i915_private *dev_priv, u32 reg)
+{
+       if (IS_HASWELL(dev_priv->dev) &&
+           (I915_READ_NOTRACE(FPGA_DBG) & FPGA_DBG_RM_NOCLAIM)) {
+               DRM_ERROR("Unclaimed write to %x\n", reg);
+               I915_WRITE_NOTRACE(FPGA_DBG, FPGA_DBG_RM_NOCLAIM);
+       }
+}
+
 #define __i915_read(x, y) \
 u##x i915_read##x(struct drm_i915_private *dev_priv, u32 reg) { \
        u##x val = 0; \
@@ -1183,18 +1250,12 @@ void i915_write##x(struct drm_i915_private *dev_priv, u32 reg, u##x val) { \
        } \
        if (IS_GEN5(dev_priv->dev)) \
                ilk_dummy_write(dev_priv); \
-       if (IS_HASWELL(dev_priv->dev) && (I915_READ_NOTRACE(GEN7_ERR_INT) & ERR_INT_MMIO_UNCLAIMED)) { \
-               DRM_ERROR("Unknown unclaimed register before writing to %x\n", reg); \
-               I915_WRITE_NOTRACE(GEN7_ERR_INT, ERR_INT_MMIO_UNCLAIMED); \
-       } \
+       hsw_unclaimed_reg_clear(dev_priv, reg); \
        write##y(val, dev_priv->regs + reg); \
        if (unlikely(__fifo_ret)) { \
                gen6_gt_check_fifodbg(dev_priv); \
        } \
-       if (IS_HASWELL(dev_priv->dev) && (I915_READ_NOTRACE(GEN7_ERR_INT) & ERR_INT_MMIO_UNCLAIMED)) { \
-               DRM_ERROR("Unclaimed write to %x\n", reg); \
-               writel(ERR_INT_MMIO_UNCLAIMED, dev_priv->regs + GEN7_ERR_INT);  \
-       } \
+       hsw_unclaimed_reg_check(dev_priv, reg); \
 }
 __i915_write(8, b)
 __i915_write(16, w)