Merge tag 'v3.5-rc4' into drm-intel-next-queued
authorDaniel Vetter <daniel.vetter@ffwll.ch>
Mon, 25 Jun 2012 17:06:12 +0000 (19:06 +0200)
committerDaniel Vetter <daniel.vetter@ffwll.ch>
Mon, 25 Jun 2012 17:10:36 +0000 (19:10 +0200)
I want to merge the "no more fake agp on gen6+" patches into
drm-intel-next (well, the last pieces). But a patch in 3.5-rc4 also
adds a new use of dev->agp. Hence the backmarge to sort this out, for
otherwise drm-intel-next merged into Linus' tree would conflict in the
relevant code, things would compile but nicely OOPS at driver load :(

Conflicts in this merge are just simple cases of "both branches
changed/added lines at the same place". The only tricky part is to
keep the order correct wrt the unwind code in case of errors in
intel_ringbuffer.c (and the MI_DISPLAY_FLIP #defines in i915_reg.h
together, obviously).

Conflicts:
drivers/gpu/drm/i915/i915_reg.h
drivers/gpu/drm/i915/intel_ringbuffer.c

Signed-Off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
33 files changed:
drivers/char/agp/intel-agp.c
drivers/char/agp/intel-agp.h
drivers/char/agp/intel-gtt.c
drivers/gpu/drm/i915/Makefile
drivers/gpu/drm/i915/i915_debugfs.c
drivers/gpu/drm/i915/i915_dma.c
drivers/gpu/drm/i915/i915_drv.c
drivers/gpu/drm/i915/i915_drv.h
drivers/gpu/drm/i915/i915_gem.c
drivers/gpu/drm/i915/i915_gem_context.c [new file with mode: 0644]
drivers/gpu/drm/i915/i915_gem_debug.c
drivers/gpu/drm/i915/i915_gem_execbuffer.c
drivers/gpu/drm/i915/i915_irq.c
drivers/gpu/drm/i915/i915_reg.h
drivers/gpu/drm/i915/i915_sysfs.c
drivers/gpu/drm/i915/i915_trace.h
drivers/gpu/drm/i915/intel_crt.c
drivers/gpu/drm/i915/intel_ddi.c
drivers/gpu/drm/i915/intel_display.c
drivers/gpu/drm/i915/intel_dp.c
drivers/gpu/drm/i915/intel_drv.h
drivers/gpu/drm/i915/intel_fb.c
drivers/gpu/drm/i915/intel_hdmi.c
drivers/gpu/drm/i915/intel_lvds.c
drivers/gpu/drm/i915/intel_overlay.c
drivers/gpu/drm/i915/intel_panel.c
drivers/gpu/drm/i915/intel_pm.c
drivers/gpu/drm/i915/intel_ringbuffer.c
drivers/gpu/drm/i915/intel_ringbuffer.h
drivers/gpu/drm/i915/intel_sdvo.c
drivers/gpu/drm/i915/intel_sprite.c
include/drm/i915_drm.h
include/drm/intel-gtt.h

index 0a41852..92622d4 100644 (file)
@@ -12,6 +12,7 @@
 #include <asm/smp.h>
 #include "agp.h"
 #include "intel-agp.h"
+#include <drm/intel-gtt.h>
 
 int intel_agp_enabled;
 EXPORT_SYMBOL(intel_agp_enabled);
@@ -747,7 +748,7 @@ static int __devinit agp_intel_probe(struct pci_dev *pdev,
 
        bridge->capndx = cap_ptr;
 
-       if (intel_gmch_probe(pdev, bridge))
+       if (intel_gmch_probe(pdev, NULL, bridge))
                goto found_gmch;
 
        for (i = 0; intel_agp_chipsets[i].name != NULL; i++) {
@@ -824,7 +825,7 @@ static void __devexit agp_intel_remove(struct pci_dev *pdev)
 
        agp_remove_bridge(bridge);
 
-       intel_gmch_remove(pdev);
+       intel_gmch_remove();
 
        agp_put_bridge(bridge);
 }
index 8e2d914..5722642 100644 (file)
 #define PCI_DEVICE_ID_INTEL_HASWELL_SDV                0x0c16 /* SDV */
 #define PCI_DEVICE_ID_INTEL_HASWELL_E_HB                       0x0c04
 
-int intel_gmch_probe(struct pci_dev *pdev,
-                              struct agp_bridge_data *bridge);
-void intel_gmch_remove(struct pci_dev *pdev);
 #endif
index 1237e75..9ed92ef 100644 (file)
@@ -66,7 +66,6 @@ static struct _intel_private {
        struct pci_dev *bridge_dev;
        u8 __iomem *registers;
        phys_addr_t gtt_bus_addr;
-       phys_addr_t gma_bus_addr;
        u32 PGETBL_save;
        u32 __iomem *gtt;               /* I915G */
        bool clear_fake_agp; /* on first access via agp, fill with scratch */
@@ -76,6 +75,7 @@ static struct _intel_private {
        struct resource ifp_resource;
        int resource_valid;
        struct page *scratch_page;
+       int refcount;
 } intel_private;
 
 #define INTEL_GTT_GEN  intel_private.driver->gen
@@ -648,6 +648,7 @@ static void intel_gtt_cleanup(void)
 
 static int intel_gtt_init(void)
 {
+       u32 gma_addr;
        u32 gtt_map_size;
        int ret;
 
@@ -694,6 +695,15 @@ static int intel_gtt_init(void)
                return ret;
        }
 
+       if (INTEL_GTT_GEN <= 2)
+               pci_read_config_dword(intel_private.pcidev, I810_GMADDR,
+                                     &gma_addr);
+       else
+               pci_read_config_dword(intel_private.pcidev, I915_GMADDR,
+                                     &gma_addr);
+
+       intel_private.base.gma_bus_addr = (gma_addr & PCI_BASE_ADDRESS_MEM_MASK);
+
        return 0;
 }
 
@@ -767,20 +777,10 @@ static void i830_write_entry(dma_addr_t addr, unsigned int entry,
        writel(addr | pte_flags, intel_private.gtt + entry);
 }
 
-static bool intel_enable_gtt(void)
+bool intel_enable_gtt(void)
 {
-       u32 gma_addr;
        u8 __iomem *reg;
 
-       if (INTEL_GTT_GEN <= 2)
-               pci_read_config_dword(intel_private.pcidev, I810_GMADDR,
-                                     &gma_addr);
-       else
-               pci_read_config_dword(intel_private.pcidev, I915_GMADDR,
-                                     &gma_addr);
-
-       intel_private.gma_bus_addr = (gma_addr & PCI_BASE_ADDRESS_MEM_MASK);
-
        if (INTEL_GTT_GEN >= 6)
            return true;
 
@@ -823,6 +823,7 @@ static bool intel_enable_gtt(void)
 
        return true;
 }
+EXPORT_SYMBOL(intel_enable_gtt);
 
 static int i830_setup(void)
 {
@@ -860,7 +861,7 @@ static int intel_fake_agp_configure(void)
            return -EIO;
 
        intel_private.clear_fake_agp = true;
-       agp_bridge->gart_bus_addr = intel_private.gma_bus_addr;
+       agp_bridge->gart_bus_addr = intel_private.base.gma_bus_addr;
 
        return 0;
 }
@@ -1182,9 +1183,17 @@ static void gen6_write_entry(dma_addr_t addr, unsigned int entry,
 static void valleyview_write_entry(dma_addr_t addr, unsigned int entry,
                                   unsigned int flags)
 {
+       unsigned int type_mask = flags & ~AGP_USER_CACHED_MEMORY_GFDT;
+       unsigned int gfdt = flags & AGP_USER_CACHED_MEMORY_GFDT;
        u32 pte_flags;
 
-       pte_flags = GEN6_PTE_UNCACHED | I810_PTE_VALID;
+       if (type_mask == AGP_USER_MEMORY)
+               pte_flags = GEN6_PTE_UNCACHED | I810_PTE_VALID;
+       else {
+               pte_flags = GEN6_PTE_LLC | I810_PTE_VALID;
+               if (gfdt)
+                       pte_flags |= GEN6_PTE_GFDT;
+       }
 
        /* gen6 has bit11-4 for physical addr bit39-32 */
        addr |= (addr >> 28) & 0xff0;
@@ -1244,6 +1253,7 @@ static int i9xx_setup(void)
                switch (INTEL_GTT_GEN) {
                case 5:
                case 6:
+               case 7:
                        gtt_offset = MB(2);
                        break;
                case 4:
@@ -1379,7 +1389,6 @@ static const struct intel_gtt_driver valleyview_gtt_driver = {
        .write_entry = valleyview_write_entry,
        .dma_mask_size = 40,
        .check_flags = gen6_check_flags,
-       .chipset_flush = i9xx_chipset_flush,
 };
 
 /* Table to describe Intel GMCH and AGP/PCIE GART drivers.  At least one of
@@ -1523,14 +1532,32 @@ static int find_gmch(u16 device)
        return 1;
 }
 
-int intel_gmch_probe(struct pci_dev *pdev,
-                                     struct agp_bridge_data *bridge)
+int intel_gmch_probe(struct pci_dev *bridge_pdev, struct pci_dev *gpu_pdev,
+                    struct agp_bridge_data *bridge)
 {
        int i, mask;
-       intel_private.driver = NULL;
+
+       /*
+        * Can be called from the fake agp driver but also directly from
+        * drm/i915.ko. Hence we need to check whether everything is set up
+        * already.
+        */
+       if (intel_private.driver) {
+               intel_private.refcount++;
+               return 1;
+       }
 
        for (i = 0; intel_gtt_chipsets[i].name != NULL; i++) {
-               if (find_gmch(intel_gtt_chipsets[i].gmch_chip_id)) {
+               if (gpu_pdev) {
+                       if (gpu_pdev->device ==
+                           intel_gtt_chipsets[i].gmch_chip_id) {
+                               intel_private.pcidev = pci_dev_get(gpu_pdev);
+                               intel_private.driver =
+                                       intel_gtt_chipsets[i].gtt_driver;
+
+                               break;
+                       }
+               } else if (find_gmch(intel_gtt_chipsets[i].gmch_chip_id)) {
                        intel_private.driver =
                                intel_gtt_chipsets[i].gtt_driver;
                        break;
@@ -1540,13 +1567,17 @@ int intel_gmch_probe(struct pci_dev *pdev,
        if (!intel_private.driver)
                return 0;
 
-       bridge->driver = &intel_fake_agp_driver;
-       bridge->dev_private_data = &intel_private;
-       bridge->dev = pdev;
+       intel_private.refcount++;
+
+       if (bridge) {
+               bridge->driver = &intel_fake_agp_driver;
+               bridge->dev_private_data = &intel_private;
+               bridge->dev = bridge_pdev;
+       }
 
-       intel_private.bridge_dev = pci_dev_get(pdev);
+       intel_private.bridge_dev = pci_dev_get(bridge_pdev);
 
-       dev_info(&pdev->dev, "Intel %s Chipset\n", intel_gtt_chipsets[i].name);
+       dev_info(&bridge_pdev->dev, "Intel %s Chipset\n", intel_gtt_chipsets[i].name);
 
        mask = intel_private.driver->dma_mask_size;
        if (pci_set_dma_mask(intel_private.pcidev, DMA_BIT_MASK(mask)))
@@ -1556,11 +1587,11 @@ int intel_gmch_probe(struct pci_dev *pdev,
                pci_set_consistent_dma_mask(intel_private.pcidev,
                                            DMA_BIT_MASK(mask));
 
-       /*if (bridge->driver == &intel_810_driver)
-               return 1;*/
+       if (intel_gtt_init() != 0) {
+               intel_gmch_remove();
 
-       if (intel_gtt_init() != 0)
                return 0;
+       }
 
        return 1;
 }
@@ -1579,12 +1610,16 @@ void intel_gtt_chipset_flush(void)
 }
 EXPORT_SYMBOL(intel_gtt_chipset_flush);
 
-void intel_gmch_remove(struct pci_dev *pdev)
+void intel_gmch_remove(void)
 {
+       if (--intel_private.refcount)
+               return;
+
        if (intel_private.pcidev)
                pci_dev_put(intel_private.pcidev);
        if (intel_private.bridge_dev)
                pci_dev_put(intel_private.bridge_dev);
+       intel_private.driver = NULL;
 }
 EXPORT_SYMBOL(intel_gmch_remove);
 
index 2e9268d..b0bacdb 100644 (file)
@@ -7,6 +7,7 @@ i915-y := i915_drv.o i915_dma.o i915_irq.o \
          i915_debugfs.o \
           i915_suspend.o \
          i915_gem.o \
+         i915_gem_context.o \
          i915_gem_debug.o \
          i915_gem_evict.o \
          i915_gem_execbuffer.o \
index 5363e9c..2909b12 100644 (file)
@@ -713,6 +713,7 @@ static int i915_error_state(struct seq_file *m, void *unused)
        seq_printf(m, "EIR: 0x%08x\n", error->eir);
        seq_printf(m, "IER: 0x%08x\n", error->ier);
        seq_printf(m, "PGTBL_ER: 0x%08x\n", error->pgtbl_er);
+       seq_printf(m, "CCID: 0x%08x\n", error->ccid);
 
        for (i = 0; i < dev_priv->num_fence_regs; i++)
                seq_printf(m, "  fence[%d] = %08llx\n", i, error->fence[i]);
@@ -1764,6 +1765,64 @@ static const struct file_operations i915_max_freq_fops = {
        .llseek = default_llseek,
 };
 
+static ssize_t
+i915_min_freq_read(struct file *filp, char __user *ubuf, size_t max,
+                  loff_t *ppos)
+{
+       struct drm_device *dev = filp->private_data;
+       drm_i915_private_t *dev_priv = dev->dev_private;
+       char buf[80];
+       int len;
+
+       len = snprintf(buf, sizeof(buf),
+                      "min freq: %d\n", dev_priv->min_delay * 50);
+
+       if (len > sizeof(buf))
+               len = sizeof(buf);
+
+       return simple_read_from_buffer(ubuf, max, ppos, buf, len);
+}
+
+static ssize_t
+i915_min_freq_write(struct file *filp, const char __user *ubuf, size_t cnt,
+                   loff_t *ppos)
+{
+       struct drm_device *dev = filp->private_data;
+       struct drm_i915_private *dev_priv = dev->dev_private;
+       char buf[20];
+       int val = 1;
+
+       if (cnt > 0) {
+               if (cnt > sizeof(buf) - 1)
+                       return -EINVAL;
+
+               if (copy_from_user(buf, ubuf, cnt))
+                       return -EFAULT;
+               buf[cnt] = 0;
+
+               val = simple_strtoul(buf, NULL, 0);
+       }
+
+       DRM_DEBUG_DRIVER("Manually setting min freq to %d\n", val);
+
+       /*
+        * Turbo will still be enabled, but won't go below the set value.
+        */
+       dev_priv->min_delay = val / 50;
+
+       gen6_set_rps(dev, val / 50);
+
+       return cnt;
+}
+
+static const struct file_operations i915_min_freq_fops = {
+       .owner = THIS_MODULE,
+       .open = simple_open,
+       .read = i915_min_freq_read,
+       .write = i915_min_freq_write,
+       .llseek = default_llseek,
+};
+
 static ssize_t
 i915_cache_sharing_read(struct file *filp,
                   char __user *ubuf,
@@ -1996,6 +2055,12 @@ int i915_debugfs_init(struct drm_minor *minor)
        if (ret)
                return ret;
 
+       ret = i915_debugfs_create(minor->debugfs_root, minor,
+                                 "i915_min_freq",
+                                 &i915_min_freq_fops);
+       if (ret)
+               return ret;
+
        ret = i915_debugfs_create(minor->debugfs_root, minor,
                                  "i915_cache_sharing",
                                  &i915_cache_sharing_fops);
@@ -2028,6 +2093,8 @@ void i915_debugfs_cleanup(struct drm_minor *minor)
                                 1, minor);
        drm_debugfs_remove_files((struct drm_info_list *) &i915_max_freq_fops,
                                 1, minor);
+       drm_debugfs_remove_files((struct drm_info_list *) &i915_min_freq_fops,
+                                1, minor);
        drm_debugfs_remove_files((struct drm_info_list *) &i915_cache_sharing_fops,
                                 1, minor);
        drm_debugfs_remove_files((struct drm_info_list *) &i915_ring_stop_fops,
index f947926..9563ab8 100644 (file)
@@ -1006,6 +1006,9 @@ static int i915_getparam(struct drm_device *dev, void *data,
        case I915_PARAM_HAS_ALIASING_PPGTT:
                value = dev_priv->mm.aliasing_ppgtt ? 1 : 0;
                break;
+       case I915_PARAM_HAS_WAIT_TIMEOUT:
+               value = 1;
+               break;
        default:
                DRM_DEBUG_DRIVER("Unknown parameter %d\n",
                                 param->param);
@@ -1082,8 +1085,8 @@ static int i915_set_status_page(struct drm_device *dev, void *data,
 
        ring->status_page.gfx_addr = hws->addr & (0x1ffff<<12);
 
-       dev_priv->dri1.gfx_hws_cpu_addr = ioremap_wc(dev->agp->base + hws->addr,
-                                                    4096);
+       dev_priv->dri1.gfx_hws_cpu_addr =
+               ioremap_wc(dev_priv->mm.gtt_base_addr + hws->addr, 4096);
        if (dev_priv->dri1.gfx_hws_cpu_addr == NULL) {
                i915_dma_cleanup(dev);
                ring->status_page.gfx_addr = 0;
@@ -1401,6 +1404,27 @@ i915_mtrr_setup(struct drm_i915_private *dev_priv, unsigned long base,
        }
 }
 
+static void i915_kick_out_firmware_fb(struct drm_i915_private *dev_priv)
+{
+       struct apertures_struct *ap;
+       struct pci_dev *pdev = dev_priv->dev->pdev;
+       bool primary;
+
+       ap = alloc_apertures(1);
+       if (!ap)
+               return;
+
+       ap->ranges[0].base = dev_priv->dev->agp->base;
+       ap->ranges[0].size =
+               dev_priv->mm.gtt->gtt_mappable_entries << PAGE_SHIFT;
+       primary =
+               pdev->resource[PCI_ROM_RESOURCE].flags & IORESOURCE_ROM_SHADOW;
+
+       remove_conflicting_framebuffers(ap, "inteldrmfb", primary);
+
+       kfree(ap);
+}
+
 /**
  * i915_driver_load - setup chip and create an initial config
  * @dev: DRM device
@@ -1446,6 +1470,22 @@ int i915_driver_load(struct drm_device *dev, unsigned long flags)
                goto free_priv;
        }
 
+       ret = intel_gmch_probe(dev_priv->bridge_dev, dev->pdev, NULL);
+       if (!ret) {
+               DRM_ERROR("failed to set up gmch\n");
+               ret = -EIO;
+               goto put_bridge;
+       }
+
+       dev_priv->mm.gtt = intel_gtt_get();
+       if (!dev_priv->mm.gtt) {
+               DRM_ERROR("Failed to initialize GTT\n");
+               ret = -ENODEV;
+               goto put_gmch;
+       }
+
+       i915_kick_out_firmware_fb(dev_priv);
+
        pci_set_master(dev->pdev);
 
        /* overlay on gen2 is broken and can't address above 1G */
@@ -1468,26 +1508,22 @@ int i915_driver_load(struct drm_device *dev, unsigned long flags)
        if (!dev_priv->regs) {
                DRM_ERROR("failed to map registers\n");
                ret = -EIO;
-               goto put_bridge;
-       }
-
-       dev_priv->mm.gtt = intel_gtt_get();
-       if (!dev_priv->mm.gtt) {
-               DRM_ERROR("Failed to initialize GTT\n");
-               ret = -ENODEV;
-               goto out_rmmap;
+               goto put_gmch;
        }
 
        aperture_size = dev_priv->mm.gtt->gtt_mappable_entries << PAGE_SHIFT;
+       dev_priv->mm.gtt_base_addr = dev_priv->mm.gtt->gma_bus_addr;
 
        dev_priv->mm.gtt_mapping =
-               io_mapping_create_wc(dev->agp->base, aperture_size);
+               io_mapping_create_wc(dev_priv->mm.gtt_base_addr,
+                                    aperture_size);
        if (dev_priv->mm.gtt_mapping == NULL) {
                ret = -EIO;
                goto out_rmmap;
        }
 
-       i915_mtrr_setup(dev_priv, dev->agp->base, aperture_size);
+       i915_mtrr_setup(dev_priv, dev_priv->mm.gtt_base_addr,
+                       aperture_size);
 
        /* The i915 workqueue is primarily used for batched retirement of
         * requests (and thus managing bo) once the task has been completed
@@ -1599,13 +1635,16 @@ out_gem_unload:
        destroy_workqueue(dev_priv->wq);
 out_mtrrfree:
        if (dev_priv->mm.gtt_mtrr >= 0) {
-               mtrr_del(dev_priv->mm.gtt_mtrr, dev->agp->base,
-                        dev->agp->agp_info.aper_size * 1024 * 1024);
+               mtrr_del(dev_priv->mm.gtt_mtrr,
+                        dev_priv->mm.gtt_base_addr,
+                        aperture_size);
                dev_priv->mm.gtt_mtrr = -1;
        }
        io_mapping_free(dev_priv->mm.gtt_mapping);
 out_rmmap:
        pci_iounmap(dev->pdev, dev_priv->regs);
+put_gmch:
+       intel_gmch_remove();
 put_bridge:
        pci_dev_put(dev_priv->bridge_dev);
 free_priv:
@@ -1637,8 +1676,9 @@ int i915_driver_unload(struct drm_device *dev)
 
        io_mapping_free(dev_priv->mm.gtt_mapping);
        if (dev_priv->mm.gtt_mtrr >= 0) {
-               mtrr_del(dev_priv->mm.gtt_mtrr, dev->agp->base,
-                        dev->agp->agp_info.aper_size * 1024 * 1024);
+               mtrr_del(dev_priv->mm.gtt_mtrr,
+                        dev_priv->mm.gtt_base_addr,
+                        dev_priv->mm.gtt->gtt_mappable_entries * PAGE_SIZE);
                dev_priv->mm.gtt_mtrr = -1;
        }
 
@@ -1679,6 +1719,7 @@ int i915_driver_unload(struct drm_device *dev)
                mutex_lock(&dev->struct_mutex);
                i915_gem_free_all_phys_object(dev);
                i915_gem_cleanup_ringbuffer(dev);
+               i915_gem_context_fini(dev);
                mutex_unlock(&dev->struct_mutex);
                i915_gem_cleanup_aliasing_ppgtt(dev);
                i915_gem_cleanup_stolen(dev);
@@ -1718,6 +1759,8 @@ int i915_driver_open(struct drm_device *dev, struct drm_file *file)
        spin_lock_init(&file_priv->mm.lock);
        INIT_LIST_HEAD(&file_priv->mm.request_list);
 
+       idr_init(&file_priv->context_idr);
+
        return 0;
 }
 
@@ -1750,6 +1793,7 @@ void i915_driver_lastclose(struct drm_device * dev)
 
 void i915_driver_preclose(struct drm_device * dev, struct drm_file *file_priv)
 {
+       i915_gem_context_close(dev, file_priv);
        i915_gem_release(dev, file_priv);
 }
 
@@ -1803,6 +1847,9 @@ struct drm_ioctl_desc i915_ioctls[] = {
        DRM_IOCTL_DEF_DRV(I915_OVERLAY_ATTRS, intel_overlay_attrs, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED),
        DRM_IOCTL_DEF_DRV(I915_SET_SPRITE_COLORKEY, intel_sprite_set_colorkey, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED),
        DRM_IOCTL_DEF_DRV(I915_GET_SPRITE_COLORKEY, intel_sprite_get_colorkey, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED),
+       DRM_IOCTL_DEF_DRV(I915_GEM_WAIT, i915_gem_wait_ioctl, DRM_AUTH|DRM_UNLOCKED),
+       DRM_IOCTL_DEF_DRV(I915_GEM_CONTEXT_CREATE, i915_gem_context_create_ioctl, DRM_UNLOCKED),
+       DRM_IOCTL_DEF_DRV(I915_GEM_CONTEXT_DESTROY, i915_gem_context_destroy_ioctl, DRM_UNLOCKED),
 };
 
 int i915_max_ioctl = DRM_ARRAY_SIZE(i915_ioctls);
index 9fe9ebe..a378c08 100644 (file)
@@ -358,6 +358,9 @@ static const struct pci_device_id pciidlist[] = {           /* aka */
        INTEL_VGA_DEVICE(0x0406, &intel_haswell_m_info), /* GT1 mobile */
        INTEL_VGA_DEVICE(0x0416, &intel_haswell_m_info), /* GT2 mobile */
        INTEL_VGA_DEVICE(0x0c16, &intel_haswell_d_info), /* SDV */
+       INTEL_VGA_DEVICE(0x0f30, &intel_valleyview_m_info),
+       INTEL_VGA_DEVICE(0x0157, &intel_valleyview_m_info),
+       INTEL_VGA_DEVICE(0x0155, &intel_valleyview_d_info),
        {0, 0, 0}
 };
 
@@ -805,7 +808,7 @@ static int gen6_do_reset(struct drm_device *dev)
        return ret;
 }
 
-static int intel_gpu_reset(struct drm_device *dev)
+int intel_gpu_reset(struct drm_device *dev)
 {
        struct drm_i915_private *dev_priv = dev->dev_private;
        int ret = -ENODEV;
@@ -866,8 +869,6 @@ int i915_reset(struct drm_device *dev)
        if (!mutex_trylock(&dev->struct_mutex))
                return -EBUSY;
 
-       dev_priv->stop_rings = 0;
-
        i915_gem_reset(dev);
 
        ret = -ENODEV;
@@ -909,12 +910,16 @@ int i915_reset(struct drm_device *dev)
                for_each_ring(ring, dev_priv, i)
                        ring->init(ring);
 
+               i915_gem_context_init(dev);
                i915_gem_init_ppgtt(dev);
 
-               mutex_unlock(&dev->struct_mutex);
+               /*
+                * It would make sense to re-init all the other hw state, at
+                * least the rps/rc6/emon init done within modeset_init_hw. For
+                * some unknown reason, this blows up my ilk, so don't.
+                */
 
-               if (drm_core_check_feature(dev, DRIVER_MODESET))
-                       intel_modeset_init_hw(dev);
+               mutex_unlock(&dev->struct_mutex);
 
                drm_irq_uninstall(dev);
                drm_irq_install(dev);
@@ -1149,6 +1154,84 @@ MODULE_LICENSE("GPL and additional rights");
         ((reg) < 0x40000) &&            \
         ((reg) != FORCEWAKE))
 
+static bool IS_DISPLAYREG(u32 reg)
+{
+       /*
+        * This should make it easier to transition modules over to the
+        * new register block scheme, since we can do it incrementally.
+        */
+       if (reg >= 0x180000)
+               return false;
+
+       if (reg >= RENDER_RING_BASE &&
+           reg < RENDER_RING_BASE + 0xff)
+               return false;
+       if (reg >= GEN6_BSD_RING_BASE &&
+           reg < GEN6_BSD_RING_BASE + 0xff)
+               return false;
+       if (reg >= BLT_RING_BASE &&
+           reg < BLT_RING_BASE + 0xff)
+               return false;
+
+       if (reg == PGTBL_ER)
+               return false;
+
+       if (reg >= IPEIR_I965 &&
+           reg < HWSTAM)
+               return false;
+
+       if (reg == MI_MODE)
+               return false;
+
+       if (reg == GFX_MODE_GEN7)
+               return false;
+
+       if (reg == RENDER_HWS_PGA_GEN7 ||
+           reg == BSD_HWS_PGA_GEN7 ||
+           reg == BLT_HWS_PGA_GEN7)
+               return false;
+
+       if (reg == GEN6_BSD_SLEEP_PSMI_CONTROL ||
+           reg == GEN6_BSD_RNCID)
+               return false;
+
+       if (reg == GEN6_BLITTER_ECOSKPD)
+               return false;
+
+       if (reg >= 0x4000c &&
+           reg <= 0x4002c)
+               return false;
+
+       if (reg >= 0x4f000 &&
+           reg <= 0x4f08f)
+               return false;
+
+       if (reg >= 0x4f100 &&
+           reg <= 0x4f11f)
+               return false;
+
+       if (reg >= VLV_MASTER_IER &&
+           reg <= GEN6_PMIER)
+               return false;
+
+       if (reg >= FENCE_REG_SANDYBRIDGE_0 &&
+           reg < (FENCE_REG_SANDYBRIDGE_0 + (16*8)))
+               return false;
+
+       if (reg >= VLV_IIR_RW &&
+           reg <= VLV_ISR)
+               return false;
+
+       if (reg == FORCEWAKE_VLV ||
+           reg == FORCEWAKE_ACK_VLV)
+               return false;
+
+       if (reg == GEN6_GDRST)
+               return false;
+
+       return true;
+}
+
 #define __i915_read(x, y) \
 u##x i915_read##x(struct drm_i915_private *dev_priv, u32 reg) { \
        u##x val = 0; \
@@ -1161,6 +1244,8 @@ u##x i915_read##x(struct drm_i915_private *dev_priv, u32 reg) { \
                if (dev_priv->forcewake_count == 0) \
                        dev_priv->display.force_wake_put(dev_priv); \
                spin_unlock_irqrestore(&dev_priv->gt_lock, irqflags); \
+       } else if (IS_VALLEYVIEW(dev_priv->dev) && IS_DISPLAYREG(reg)) { \
+               val = read##y(dev_priv->regs + reg + 0x180000);         \
        } else { \
                val = read##y(dev_priv->regs + reg); \
        } \
@@ -1181,7 +1266,11 @@ void i915_write##x(struct drm_i915_private *dev_priv, u32 reg, u##x val) { \
        if (NEEDS_FORCE_WAKE((dev_priv), (reg))) { \
                __fifo_ret = __gen6_gt_wait_for_fifo(dev_priv); \
        } \
-       write##y(val, dev_priv->regs + reg); \
+       if (IS_VALLEYVIEW(dev_priv->dev) && IS_DISPLAYREG(reg)) { \
+               write##y(val, dev_priv->regs + reg + 0x180000);         \
+       } else {                                                        \
+               write##y(val, dev_priv->regs + reg);                    \
+       }                                                               \
        if (unlikely(__fifo_ret)) { \
                gen6_gt_check_fifodbg(dev_priv); \
        } \
index b0b676a..a0c15ab 100644 (file)
@@ -176,6 +176,7 @@ struct drm_i915_error_state {
        u32 eir;
        u32 pgtbl_er;
        u32 ier;
+       u32 ccid;
        bool waiting[I915_NUM_RINGS];
        u32 pipestat[I915_MAX_PIPES];
        u32 tail[I915_NUM_RINGS];
@@ -309,6 +310,17 @@ struct i915_hw_ppgtt {
        dma_addr_t scratch_page_dma_addr;
 };
 
+
+/* This must match up with the value previously used for execbuf2.rsvd1. */
+#define DEFAULT_CONTEXT_ID 0
+struct i915_hw_context {
+       int id;
+       bool is_initialized;
+       struct drm_i915_file_private *file_priv;
+       struct intel_ring_buffer *ring;
+       struct drm_i915_gem_object *obj;
+};
+
 enum no_fbc_reason {
        FBC_NO_OUTPUT, /* no outputs enabled to compress */
        FBC_STOLEN_TOO_SMALL, /* not enough space to hold compressed buffers */
@@ -652,11 +664,14 @@ typedef struct drm_i915_private {
                unsigned long gtt_end;
 
                struct io_mapping *gtt_mapping;
+               phys_addr_t gtt_base_addr;
                int gtt_mtrr;
 
                /** PPGTT used for aliasing the PPGTT with the GTT */
                struct i915_hw_ppgtt *aliasing_ppgtt;
 
+               u32 *l3_remap_info;
+
                struct shrinker inactive_shrinker;
 
                /**
@@ -817,6 +832,10 @@ typedef struct drm_i915_private {
 
        struct drm_property *broadcast_rgb_property;
        struct drm_property *force_audio_property;
+
+       struct work_struct parity_error_work;
+       bool hw_contexts_disabled;
+       uint32_t hw_context_size;
 } drm_i915_private_t;
 
 /* Iterate over initialised rings */
@@ -1026,6 +1045,7 @@ struct drm_i915_file_private {
                struct spinlock lock;
                struct list_head request_list;
        } mm;
+       struct idr context_idr;
 };
 
 #define INTEL_INFO(dev)        (((struct drm_i915_private *) (dev)->dev_private)->info)
@@ -1071,7 +1091,8 @@ struct drm_i915_file_private {
 #define HAS_LLC(dev)            (INTEL_INFO(dev)->has_llc)
 #define I915_NEED_GFX_HWS(dev) (INTEL_INFO(dev)->need_gfx_hws)
 
-#define HAS_ALIASING_PPGTT(dev)        (INTEL_INFO(dev)->gen >=6)
+#define HAS_HW_CONTEXTS(dev)   (INTEL_INFO(dev)->gen >= 6)
+#define HAS_ALIASING_PPGTT(dev)        (INTEL_INFO(dev)->gen >=6 && !IS_VALLEYVIEW(dev))
 
 #define HAS_OVERLAY(dev)               (INTEL_INFO(dev)->has_overlay)
 #define OVERLAY_NEEDS_PHYSICAL(dev)    (INTEL_INFO(dev)->overlay_needs_physical)
@@ -1166,6 +1187,7 @@ extern long i915_compat_ioctl(struct file *filp, unsigned int cmd,
 extern int i915_emit_box(struct drm_device *dev,
                         struct drm_clip_rect *box,
                         int DR1, int DR4);
+extern int intel_gpu_reset(struct drm_device *dev);
 extern int i915_reset(struct drm_device *dev);
 extern unsigned long i915_chipset_val(struct drm_i915_private *dev_priv);
 extern unsigned long i915_mch_val(struct drm_i915_private *dev_priv);
@@ -1237,6 +1259,8 @@ int i915_gem_get_tiling(struct drm_device *dev, void *data,
                        struct drm_file *file_priv);
 int i915_gem_get_aperture_ioctl(struct drm_device *dev, void *data,
                                struct drm_file *file_priv);
+int i915_gem_wait_ioctl(struct drm_device *dev, void *data,
+                       struct drm_file *file_priv);
 void i915_gem_load(struct drm_device *dev);
 int i915_gem_init_object(struct drm_gem_object *obj);
 int __must_check i915_gem_flush_ring(struct intel_ring_buffer *ring,
@@ -1315,6 +1339,7 @@ int __must_check i915_gem_object_set_domain(struct drm_i915_gem_object *obj,
 int __must_check i915_gem_object_finish_gpu(struct drm_i915_gem_object *obj);
 int __must_check i915_gem_init(struct drm_device *dev);
 int __must_check i915_gem_init_hw(struct drm_device *dev);
+void i915_gem_l3_remap(struct drm_device *dev);
 void i915_gem_init_swizzling(struct drm_device *dev);
 void i915_gem_init_ppgtt(struct drm_device *dev);
 void i915_gem_cleanup_ringbuffer(struct drm_device *dev);
@@ -1323,8 +1348,8 @@ int __must_check i915_gem_idle(struct drm_device *dev);
 int __must_check i915_add_request(struct intel_ring_buffer *ring,
                                  struct drm_file *file,
                                  struct drm_i915_gem_request *request);
-int __must_check i915_wait_request(struct intel_ring_buffer *ring,
-                                  uint32_t seqno);
+int __must_check i915_wait_seqno(struct intel_ring_buffer *ring,
+                                uint32_t seqno);
 int i915_gem_fault(struct vm_area_struct *vma, struct vm_fault *vmf);
 int __must_check
 i915_gem_object_set_to_gtt_domain(struct drm_i915_gem_object *obj,
@@ -1358,6 +1383,16 @@ struct drm_gem_object *i915_gem_prime_import(struct drm_device *dev,
 struct dma_buf *i915_gem_prime_export(struct drm_device *dev,
                                struct drm_gem_object *gem_obj, int flags);
 
+/* i915_gem_context.c */
+void i915_gem_context_init(struct drm_device *dev);
+void i915_gem_context_fini(struct drm_device *dev);
+void i915_gem_context_close(struct drm_device *dev, struct drm_file *file);
+int i915_switch_context(struct intel_ring_buffer *ring,
+                       struct drm_file *file, int to_id);
+int i915_gem_context_create_ioctl(struct drm_device *dev, void *data,
+                                 struct drm_file *file);
+int i915_gem_context_destroy_ioctl(struct drm_device *dev, void *data,
+                                  struct drm_file *file);
 
 /* i915_gem_gtt.c */
 int __must_check i915_gem_init_aliasing_ppgtt(struct drm_device *dev);
index 288d7b8..6a98c06 100644 (file)
@@ -1122,7 +1122,7 @@ int i915_gem_fault(struct vm_area_struct *vma, struct vm_fault *vmf)
 
        obj->fault_mappable = true;
 
-       pfn = ((dev->agp->base + obj->gtt_offset) >> PAGE_SHIFT) +
+       pfn = ((dev_priv->mm.gtt_base_addr + obj->gtt_offset) >> PAGE_SHIFT) +
                page_offset;
 
        /* Finally, remap it using the new GTT offset */
@@ -1568,6 +1568,21 @@ i915_add_request(struct intel_ring_buffer *ring,
        int was_empty;
        int ret;
 
+       /*
+        * Emit any outstanding flushes - execbuf can fail to emit the flush
+        * after having emitted the batchbuffer command. Hence we need to fix
+        * things up similar to emitting the lazy request. The difference here
+        * is that the flush _must_ happen before the next request, no matter
+        * what.
+        */
+       if (ring->gpu_caches_dirty) {
+               ret = i915_gem_flush_ring(ring, 0, I915_GEM_GPU_DOMAINS);
+               if (ret)
+                       return ret;
+
+               ring->gpu_caches_dirty = false;
+       }
+
        BUG_ON(request == NULL);
        seqno = i915_gem_next_request_seqno(ring);
 
@@ -1613,6 +1628,9 @@ i915_add_request(struct intel_ring_buffer *ring,
                        queue_delayed_work(dev_priv->wq,
                                           &dev_priv->mm.retire_work, HZ);
        }
+
+       WARN_ON(!list_empty(&ring->gpu_write_list));
+
        return 0;
 }
 
@@ -1827,14 +1845,11 @@ i915_gem_retire_work_handler(struct work_struct *work)
         */
        idle = true;
        for_each_ring(ring, dev_priv, i) {
-               if (!list_empty(&ring->gpu_write_list)) {
+               if (ring->gpu_caches_dirty) {
                        struct drm_i915_gem_request *request;
-                       int ret;
 
-                       ret = i915_gem_flush_ring(ring,
-                                                 0, I915_GEM_GPU_DOMAINS);
                        request = kzalloc(sizeof(*request), GFP_KERNEL);
-                       if (ret || request == NULL ||
+                       if (request == NULL ||
                            i915_add_request(ring, NULL, request))
                            kfree(request);
                }
@@ -1899,34 +1914,82 @@ i915_gem_check_olr(struct intel_ring_buffer *ring, u32 seqno)
        return ret;
 }
 
+/**
+ * __wait_seqno - wait until execution of seqno has finished
+ * @ring: the ring expected to report seqno
+ * @seqno: duh!
+ * @interruptible: do an interruptible wait (normally yes)
+ * @timeout: in - how long to wait (NULL forever); out - how much time remaining
+ *
+ * Returns 0 if the seqno was found within the alloted time. Else returns the
+ * errno with remaining time filled in timeout argument.
+ */
 static int __wait_seqno(struct intel_ring_buffer *ring, u32 seqno,
-                       bool interruptible)
+                       bool interruptible, struct timespec *timeout)
 {
        drm_i915_private_t *dev_priv = ring->dev->dev_private;
-       int ret = 0;
+       struct timespec before, now, wait_time={1,0};
+       unsigned long timeout_jiffies;
+       long end;
+       bool wait_forever = true;
 
        if (i915_seqno_passed(ring->get_seqno(ring), seqno))
                return 0;
 
        trace_i915_gem_request_wait_begin(ring, seqno);
+
+       if (timeout != NULL) {
+               wait_time = *timeout;
+               wait_forever = false;
+       }
+
+       timeout_jiffies = timespec_to_jiffies(&wait_time);
+
        if (WARN_ON(!ring->irq_get(ring)))
                return -ENODEV;
 
+       /* Record current time in case interrupted by signal, or wedged * */
+       getrawmonotonic(&before);
+
 #define EXIT_COND \
        (i915_seqno_passed(ring->get_seqno(ring), seqno) || \
        atomic_read(&dev_priv->mm.wedged))
+       do {
+               if (interruptible)
+                       end = wait_event_interruptible_timeout(ring->irq_queue,
+                                                              EXIT_COND,
+                                                              timeout_jiffies);
+               else
+                       end = wait_event_timeout(ring->irq_queue, EXIT_COND,
+                                                timeout_jiffies);
 
-       if (interruptible)
-               ret = wait_event_interruptible(ring->irq_queue,
-                                              EXIT_COND);
-       else
-               wait_event(ring->irq_queue, EXIT_COND);
+               if (atomic_read(&dev_priv->mm.wedged))
+                       end = -EAGAIN;
+       } while (end == 0 && wait_forever);
+
+       getrawmonotonic(&now);
 
        ring->irq_put(ring);
        trace_i915_gem_request_wait_end(ring, seqno);
 #undef EXIT_COND
 
-       return ret;
+       if (timeout) {
+               struct timespec sleep_time = timespec_sub(now, before);
+               *timeout = timespec_sub(*timeout, sleep_time);
+       }
+
+       switch (end) {
+       case -EAGAIN: /* Wedged */
+       case -ERESTARTSYS: /* Signal */
+               return (int)end;
+       case 0: /* Timeout */
+               if (timeout)
+                       set_normalized_timespec(timeout, 0, 0);
+               return -ETIME;
+       default: /* Completed */
+               WARN_ON(end < 0); /* We're not aware of other errors */
+               return 0;
+       }
 }
 
 /**
@@ -1934,8 +1997,7 @@ static int __wait_seqno(struct intel_ring_buffer *ring, u32 seqno,
  * request and object lists appropriately for that event.
  */
 int
-i915_wait_request(struct intel_ring_buffer *ring,
-                 uint32_t seqno)
+i915_wait_seqno(struct intel_ring_buffer *ring, uint32_t seqno)
 {
        drm_i915_private_t *dev_priv = ring->dev->dev_private;
        int ret = 0;
@@ -1950,9 +2012,7 @@ i915_wait_request(struct intel_ring_buffer *ring,
        if (ret)
                return ret;
 
-       ret = __wait_seqno(ring, seqno, dev_priv->mm.interruptible);
-       if (atomic_read(&dev_priv->mm.wedged))
-               ret = -EAGAIN;
+       ret = __wait_seqno(ring, seqno, dev_priv->mm.interruptible, NULL);
 
        return ret;
 }
@@ -1975,7 +2035,32 @@ i915_gem_object_wait_rendering(struct drm_i915_gem_object *obj)
         * it.
         */
        if (obj->active) {
-               ret = i915_wait_request(obj->ring, obj->last_rendering_seqno);
+               ret = i915_wait_seqno(obj->ring, obj->last_rendering_seqno);
+               if (ret)
+                       return ret;
+               i915_gem_retire_requests_ring(obj->ring);
+       }
+
+       return 0;
+}
+
+/**
+ * Ensures that an object will eventually get non-busy by flushing any required
+ * write domains, emitting any outstanding lazy request and retiring and
+ * completed requests.
+ */
+static int
+i915_gem_object_flush_active(struct drm_i915_gem_object *obj)
+{
+       int ret;
+
+       if (obj->active) {
+               ret = i915_gem_object_flush_gpu_write_domain(obj);
+               if (ret)
+                       return ret;
+
+               ret = i915_gem_check_olr(obj->ring,
+                                        obj->last_rendering_seqno);
                if (ret)
                        return ret;
                i915_gem_retire_requests_ring(obj->ring);
@@ -1984,6 +2069,90 @@ i915_gem_object_wait_rendering(struct drm_i915_gem_object *obj)
        return 0;
 }
 
+/**
+ * i915_gem_wait_ioctl - implements DRM_IOCTL_I915_GEM_WAIT
+ * @DRM_IOCTL_ARGS: standard ioctl arguments
+ *
+ * Returns 0 if successful, else an error is returned with the remaining time in
+ * the timeout parameter.
+ *  -ETIME: object is still busy after timeout
+ *  -ERESTARTSYS: signal interrupted the wait
+ *  -ENONENT: object doesn't exist
+ * Also possible, but rare:
+ *  -EAGAIN: GPU wedged
+ *  -ENOMEM: damn
+ *  -ENODEV: Internal IRQ fail
+ *  -E?: The add request failed
+ *
+ * The wait ioctl with a timeout of 0 reimplements the busy ioctl. With any
+ * non-zero timeout parameter the wait ioctl will wait for the given number of
+ * nanoseconds on an object becoming unbusy. Since the wait itself does so
+ * without holding struct_mutex the object may become re-busied before this
+ * function completes. A similar but shorter * race condition exists in the busy
+ * ioctl
+ */
+int
+i915_gem_wait_ioctl(struct drm_device *dev, void *data, struct drm_file *file)
+{
+       struct drm_i915_gem_wait *args = data;
+       struct drm_i915_gem_object *obj;
+       struct intel_ring_buffer *ring = NULL;
+       struct timespec timeout_stack, *timeout = NULL;
+       u32 seqno = 0;
+       int ret = 0;
+
+       if (args->timeout_ns >= 0) {
+               timeout_stack = ns_to_timespec(args->timeout_ns);
+               timeout = &timeout_stack;
+       }
+
+       ret = i915_mutex_lock_interruptible(dev);
+       if (ret)
+               return ret;
+
+       obj = to_intel_bo(drm_gem_object_lookup(dev, file, args->bo_handle));
+       if (&obj->base == NULL) {
+               mutex_unlock(&dev->struct_mutex);
+               return -ENOENT;
+       }
+
+       /* Need to make sure the object gets inactive eventually. */
+       ret = i915_gem_object_flush_active(obj);
+       if (ret)
+               goto out;
+
+       if (obj->active) {
+               seqno = obj->last_rendering_seqno;
+               ring = obj->ring;
+       }
+
+       if (seqno == 0)
+                goto out;
+
+       /* Do this after OLR check to make sure we make forward progress polling
+        * on this IOCTL with a 0 timeout (like busy ioctl)
+        */
+       if (!args->timeout_ns) {
+               ret = -ETIME;
+               goto out;
+       }
+
+       drm_gem_object_unreference(&obj->base);
+       mutex_unlock(&dev->struct_mutex);
+
+       ret = __wait_seqno(ring, seqno, true, timeout);
+       if (timeout) {
+               WARN_ON(!timespec_valid(timeout));
+               args->timeout_ns = timespec_to_ns(timeout);
+       }
+       return ret;
+
+out:
+       drm_gem_object_unreference(&obj->base);
+       mutex_unlock(&dev->struct_mutex);
+       return ret;
+}
+
 /**
  * i915_gem_object_sync - sync an object to a ring.
  *
@@ -2160,7 +2329,7 @@ static int i915_ring_idle(struct intel_ring_buffer *ring)
                        return ret;
        }
 
-       return i915_wait_request(ring, i915_gem_next_request_seqno(ring));
+       return i915_wait_seqno(ring, i915_gem_next_request_seqno(ring));
 }
 
 int i915_gpu_idle(struct drm_device *dev)
@@ -2178,6 +2347,10 @@ int i915_gpu_idle(struct drm_device *dev)
                /* Is the device fubar? */
                if (WARN_ON(!list_empty(&ring->gpu_write_list)))
                        return -EBUSY;
+
+               ret = i915_switch_context(ring, NULL, DEFAULT_CONTEXT_ID);
+               if (ret)
+                       return ret;
        }
 
        return 0;
@@ -2364,7 +2537,7 @@ i915_gem_object_flush_fence(struct drm_i915_gem_object *obj)
        }
 
        if (obj->last_fenced_seqno) {
-               ret = i915_wait_request(obj->ring, obj->last_fenced_seqno);
+               ret = i915_wait_seqno(obj->ring, obj->last_fenced_seqno);
                if (ret)
                        return ret;
 
@@ -3030,7 +3203,7 @@ i915_gem_ring_throttle(struct drm_device *dev, struct drm_file *file)
        if (seqno == 0)
                return 0;
 
-       ret = __wait_seqno(ring, seqno, true);
+       ret = __wait_seqno(ring, seqno, true, NULL);
        if (ret == 0)
                queue_delayed_work(dev_priv->wq, &dev_priv->mm.retire_work, 0);
 
@@ -3199,30 +3372,9 @@ i915_gem_busy_ioctl(struct drm_device *dev, void *data,
         * become non-busy without any further actions, therefore emit any
         * necessary flushes here.
         */
-       args->busy = obj->active;
-       if (args->busy) {
-               /* Unconditionally flush objects, even when the gpu still uses this
-                * object. Userspace calling this function indicates that it wants to
-                * use this buffer rather sooner than later, so issuing the required
-                * flush earlier is beneficial.
-                */
-               if (obj->base.write_domain & I915_GEM_GPU_DOMAINS) {
-                       ret = i915_gem_flush_ring(obj->ring,
-                                                 0, obj->base.write_domain);
-               } else {
-                       ret = i915_gem_check_olr(obj->ring,
-                                                obj->last_rendering_seqno);
-               }
+       ret = i915_gem_object_flush_active(obj);
 
-               /* Update the active list for the hardware's current position.
-                * Otherwise this only updates on a delayed timer or when irqs
-                * are actually unmasked, and our working set ends up being
-                * larger than required.
-                */
-               i915_gem_retire_requests_ring(obj->ring);
-
-               args->busy = obj->active;
-       }
+       args->busy = obj->active;
 
        drm_gem_object_unreference(&obj->base);
 unlock:
@@ -3435,6 +3587,38 @@ i915_gem_idle(struct drm_device *dev)
        return 0;
 }
 
+void i915_gem_l3_remap(struct drm_device *dev)
+{
+       drm_i915_private_t *dev_priv = dev->dev_private;
+       u32 misccpctl;
+       int i;
+
+       if (!IS_IVYBRIDGE(dev))
+               return;
+
+       if (!dev_priv->mm.l3_remap_info)
+               return;
+
+       misccpctl = I915_READ(GEN7_MISCCPCTL);
+       I915_WRITE(GEN7_MISCCPCTL, misccpctl & ~GEN7_DOP_CLOCK_GATE_ENABLE);
+       POSTING_READ(GEN7_MISCCPCTL);
+
+       for (i = 0; i < GEN7_L3LOG_SIZE; i += 4) {
+               u32 remap = I915_READ(GEN7_L3LOG_BASE + i);
+               if (remap && remap != dev_priv->mm.l3_remap_info[i/4])
+                       DRM_DEBUG("0x%x was already programmed to %x\n",
+                                 GEN7_L3LOG_BASE + i, remap);
+               if (remap && !dev_priv->mm.l3_remap_info[i/4])
+                       DRM_DEBUG_DRIVER("Clearing remapped register\n");
+               I915_WRITE(GEN7_L3LOG_BASE + i, dev_priv->mm.l3_remap_info[i/4]);
+       }
+
+       /* Make sure all the writes land before disabling dop clock gating */
+       POSTING_READ(GEN7_L3LOG_BASE);
+
+       I915_WRITE(GEN7_MISCCPCTL, misccpctl);
+}
+
 void i915_gem_init_swizzling(struct drm_device *dev)
 {
        drm_i915_private_t *dev_priv = dev->dev_private;
@@ -3524,6 +3708,11 @@ i915_gem_init_hw(struct drm_device *dev)
        drm_i915_private_t *dev_priv = dev->dev_private;
        int ret;
 
+       if (!intel_enable_gtt())
+               return -EIO;
+
+       i915_gem_l3_remap(dev);
+
        i915_gem_init_swizzling(dev);
 
        ret = intel_init_render_ring_buffer(dev);
@@ -3544,6 +3733,11 @@ i915_gem_init_hw(struct drm_device *dev)
 
        dev_priv->next_seqno = 1;
 
+       /*
+        * XXX: There was some w/a described somewhere suggesting loading
+        * contexts before PPGTT.
+        */
+       i915_gem_context_init(dev);
        i915_gem_init_ppgtt(dev);
 
        return 0;
diff --git a/drivers/gpu/drm/i915/i915_gem_context.c b/drivers/gpu/drm/i915/i915_gem_context.c
new file mode 100644 (file)
index 0000000..e58e836
--- /dev/null
@@ -0,0 +1,535 @@
+/*
+ * Copyright Â© 2011-2012 Intel Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ *
+ * Authors:
+ *    Ben Widawsky <ben@bwidawsk.net>
+ *
+ */
+
+/*
+ * This file implements HW context support. On gen5+ a HW context consists of an
+ * opaque GPU object which is referenced at times of context saves and restores.
+ * With RC6 enabled, the context is also referenced as the GPU enters and exists
+ * from RC6 (GPU has it's own internal power context, except on gen5). Though
+ * something like a context does exist for the media ring, the code only
+ * supports contexts for the render ring.
+ *
+ * In software, there is a distinction between contexts created by the user,
+ * and the default HW context. The default HW context is used by GPU clients
+ * that do not request setup of their own hardware context. The default
+ * context's state is never restored to help prevent programming errors. This
+ * would happen if a client ran and piggy-backed off another clients GPU state.
+ * The default context only exists to give the GPU some offset to load as the
+ * current to invoke a save of the context we actually care about. In fact, the
+ * code could likely be constructed, albeit in a more complicated fashion, to
+ * never use the default context, though that limits the driver's ability to
+ * swap out, and/or destroy other contexts.
+ *
+ * All other contexts are created as a request by the GPU client. These contexts
+ * store GPU state, and thus allow GPU clients to not re-emit state (and
+ * potentially query certain state) at any time. The kernel driver makes
+ * certain that the appropriate commands are inserted.
+ *
+ * The context life cycle is semi-complicated in that context BOs may live
+ * longer than the context itself because of the way the hardware, and object
+ * tracking works. Below is a very crude representation of the state machine
+ * describing the context life.
+ *                                         refcount     pincount     active
+ * S0: initial state                          0            0           0
+ * S1: context created                        1            0           0
+ * S2: context is currently running           2            1           X
+ * S3: GPU referenced, but not current        2            0           1
+ * S4: context is current, but destroyed      1            1           0
+ * S5: like S3, but destroyed                 1            0           1
+ *
+ * The most common (but not all) transitions:
+ * S0->S1: client creates a context
+ * S1->S2: client submits execbuf with context
+ * S2->S3: other clients submits execbuf with context
+ * S3->S1: context object was retired
+ * S3->S2: clients submits another execbuf
+ * S2->S4: context destroy called with current context
+ * S3->S5->S0: destroy path
+ * S4->S5->S0: destroy path on current context
+ *
+ * There are two confusing terms used above:
+ *  The "current context" means the context which is currently running on the
+ *  GPU. The GPU has loaded it's state already and has stored away the gtt
+ *  offset of the BO. The GPU is not actively referencing the data at this
+ *  offset, but it will on the next context switch. The only way to avoid this
+ *  is to do a GPU reset.
+ *
+ *  An "active context' is one which was previously the "current context" and is
+ *  on the active list waiting for the next context switch to occur. Until this
+ *  happens, the object must remain at the same gtt offset. It is therefore
+ *  possible to destroy a context, but it is still active.
+ *
+ */
+
+#include "drmP.h"
+#include "i915_drm.h"
+#include "i915_drv.h"
+
+/* This is a HW constraint. The value below is the largest known requirement
+ * I've seen in a spec to date, and that was a workaround for a non-shipping
+ * part. It should be safe to decrease this, but it's more future proof as is.
+ */
+#define CONTEXT_ALIGN (64<<10)
+
+static struct i915_hw_context *
+i915_gem_context_get(struct drm_i915_file_private *file_priv, u32 id);
+static int do_switch(struct drm_i915_gem_object *from_obj,
+                    struct i915_hw_context *to, u32 seqno);
+
+static int get_context_size(struct drm_device *dev)
+{
+       struct drm_i915_private *dev_priv = dev->dev_private;
+       int ret;
+       u32 reg;
+
+       switch (INTEL_INFO(dev)->gen) {
+       case 6:
+               reg = I915_READ(CXT_SIZE);
+               ret = GEN6_CXT_TOTAL_SIZE(reg) * 64;
+               break;
+       case 7:
+               reg = I915_READ(GEN7_CTX_SIZE);
+               ret = GEN7_CTX_TOTAL_SIZE(reg) * 64;
+               break;
+       default:
+               BUG();
+       }
+
+       return ret;
+}
+
+static void do_destroy(struct i915_hw_context *ctx)
+{
+       struct drm_device *dev = ctx->obj->base.dev;
+       struct drm_i915_private *dev_priv = dev->dev_private;
+
+       if (ctx->file_priv)
+               idr_remove(&ctx->file_priv->context_idr, ctx->id);
+       else
+               BUG_ON(ctx != dev_priv->ring[RCS].default_context);
+
+       drm_gem_object_unreference(&ctx->obj->base);
+       kfree(ctx);
+}
+
+static int
+create_hw_context(struct drm_device *dev,
+                 struct drm_i915_file_private *file_priv,
+                 struct i915_hw_context **ctx_out)
+{
+       struct drm_i915_private *dev_priv = dev->dev_private;
+       int ret, id;
+
+       *ctx_out = kzalloc(sizeof(struct drm_i915_file_private), GFP_KERNEL);
+       if (*ctx_out == NULL)
+               return -ENOMEM;
+
+       (*ctx_out)->obj = i915_gem_alloc_object(dev,
+                                               dev_priv->hw_context_size);
+       if ((*ctx_out)->obj == NULL) {
+               kfree(*ctx_out);
+               DRM_DEBUG_DRIVER("Context object allocated failed\n");
+               return -ENOMEM;
+       }
+
+       /* The ring associated with the context object is handled by the normal
+        * object tracking code. We give an initial ring value simple to pass an
+        * assertion in the context switch code.
+        */
+       (*ctx_out)->ring = &dev_priv->ring[RCS];
+
+       /* Default context will never have a file_priv */
+       if (file_priv == NULL)
+               return 0;
+
+       (*ctx_out)->file_priv = file_priv;
+
+again:
+       if (idr_pre_get(&file_priv->context_idr, GFP_KERNEL) == 0) {
+               ret = -ENOMEM;
+               DRM_DEBUG_DRIVER("idr allocation failed\n");
+               goto err_out;
+       }
+
+       ret = idr_get_new_above(&file_priv->context_idr, *ctx_out,
+                               DEFAULT_CONTEXT_ID + 1, &id);
+       if (ret == 0)
+               (*ctx_out)->id = id;
+
+       if (ret == -EAGAIN)
+               goto again;
+       else if (ret)
+               goto err_out;
+
+       return 0;
+
+err_out:
+       do_destroy(*ctx_out);
+       return ret;
+}
+
+static inline bool is_default_context(struct i915_hw_context *ctx)
+{
+       return (ctx == ctx->ring->default_context);
+}
+
+/**
+ * The default context needs to exist per ring that uses contexts. It stores the
+ * context state of the GPU for applications that don't utilize HW contexts, as
+ * well as an idle case.
+ */
+static int create_default_context(struct drm_i915_private *dev_priv)
+{
+       struct i915_hw_context *ctx;
+       int ret;
+
+       BUG_ON(!mutex_is_locked(&dev_priv->dev->struct_mutex));
+
+       ret = create_hw_context(dev_priv->dev, NULL,
+                               &dev_priv->ring[RCS].default_context);
+       if (ret)
+               return ret;
+
+       /* We may need to do things with the shrinker which require us to
+        * immediately switch back to the default context. This can cause a
+        * problem as pinning the default context also requires GTT space which
+        * may not be available. To avoid this we always pin the
+        * default context.
+        */
+       ctx = dev_priv->ring[RCS].default_context;
+       ret = i915_gem_object_pin(ctx->obj, CONTEXT_ALIGN, false);
+       if (ret) {
+               do_destroy(ctx);
+               return ret;
+       }
+
+       ret = do_switch(NULL, ctx, 0);
+       if (ret) {
+               i915_gem_object_unpin(ctx->obj);
+               do_destroy(ctx);
+       } else {
+               DRM_DEBUG_DRIVER("Default HW context loaded\n");
+       }
+
+       return ret;
+}
+
+void i915_gem_context_init(struct drm_device *dev)
+{
+       struct drm_i915_private *dev_priv = dev->dev_private;
+       uint32_t ctx_size;
+
+       if (!HAS_HW_CONTEXTS(dev)) {
+               dev_priv->hw_contexts_disabled = true;
+               return;
+       }
+
+       /* If called from reset, or thaw... we've been here already */
+       if (dev_priv->hw_contexts_disabled ||
+           dev_priv->ring[RCS].default_context)
+               return;
+
+       ctx_size = get_context_size(dev);
+       dev_priv->hw_context_size = get_context_size(dev);
+       dev_priv->hw_context_size = round_up(dev_priv->hw_context_size, 4096);
+
+       if (ctx_size <= 0 || ctx_size > (1<<20)) {
+               dev_priv->hw_contexts_disabled = true;
+               return;
+       }
+
+       if (create_default_context(dev_priv)) {
+               dev_priv->hw_contexts_disabled = true;
+               return;
+       }
+
+       DRM_DEBUG_DRIVER("HW context support initialized\n");
+}
+
+void i915_gem_context_fini(struct drm_device *dev)
+{
+       struct drm_i915_private *dev_priv = dev->dev_private;
+
+       if (dev_priv->hw_contexts_disabled)
+               return;
+
+       /* The only known way to stop the gpu from accessing the hw context is
+        * to reset it. Do this as the very last operation to avoid confusing
+        * other code, leading to spurious errors. */
+       intel_gpu_reset(dev);
+
+       i915_gem_object_unpin(dev_priv->ring[RCS].default_context->obj);
+
+       do_destroy(dev_priv->ring[RCS].default_context);
+}
+
+static int context_idr_cleanup(int id, void *p, void *data)
+{
+       struct i915_hw_context *ctx = p;
+
+       BUG_ON(id == DEFAULT_CONTEXT_ID);
+
+       do_destroy(ctx);
+
+       return 0;
+}
+
+void i915_gem_context_close(struct drm_device *dev, struct drm_file *file)
+{
+       struct drm_i915_file_private *file_priv = file->driver_priv;
+
+       mutex_lock(&dev->struct_mutex);
+       idr_for_each(&file_priv->context_idr, context_idr_cleanup, NULL);
+       idr_destroy(&file_priv->context_idr);
+       mutex_unlock(&dev->struct_mutex);
+}
+
+static struct i915_hw_context *
+i915_gem_context_get(struct drm_i915_file_private *file_priv, u32 id)
+{
+       return (struct i915_hw_context *)idr_find(&file_priv->context_idr, id);
+}
+
+static inline int
+mi_set_context(struct intel_ring_buffer *ring,
+              struct i915_hw_context *new_context,
+              u32 hw_flags)
+{
+       int ret;
+
+       /* w/a: If Flush TLB Invalidation Mode is enabled, driver must do a TLB
+        * invalidation prior to MI_SET_CONTEXT. On GEN6 we don't set the value
+        * explicitly, so we rely on the value at ring init, stored in
+        * itlb_before_ctx_switch.
+        */
+       if (IS_GEN6(ring->dev) && ring->itlb_before_ctx_switch) {
+               ret = ring->flush(ring, 0, 0);
+               if (ret)
+                       return ret;
+       }
+
+       ret = intel_ring_begin(ring, 6);
+       if (ret)
+               return ret;
+
+       if (IS_GEN7(ring->dev))
+               intel_ring_emit(ring, MI_ARB_ON_OFF | MI_ARB_DISABLE);
+       else
+               intel_ring_emit(ring, MI_NOOP);
+
+       intel_ring_emit(ring, MI_NOOP);
+       intel_ring_emit(ring, MI_SET_CONTEXT);
+       intel_ring_emit(ring, new_context->obj->gtt_offset |
+                       MI_MM_SPACE_GTT |
+                       MI_SAVE_EXT_STATE_EN |
+                       MI_RESTORE_EXT_STATE_EN |
+                       hw_flags);
+       /* w/a: MI_SET_CONTEXT must always be followed by MI_NOOP */
+       intel_ring_emit(ring, MI_NOOP);
+
+       if (IS_GEN7(ring->dev))
+               intel_ring_emit(ring, MI_ARB_ON_OFF | MI_ARB_ENABLE);
+       else
+               intel_ring_emit(ring, MI_NOOP);
+
+       intel_ring_advance(ring);
+
+       return ret;
+}
+
+static int do_switch(struct drm_i915_gem_object *from_obj,
+                    struct i915_hw_context *to,
+                    u32 seqno)
+{
+       struct intel_ring_buffer *ring = NULL;
+       u32 hw_flags = 0;
+       int ret;
+
+       BUG_ON(to == NULL);
+       BUG_ON(from_obj != NULL && from_obj->pin_count == 0);
+
+       ret = i915_gem_object_pin(to->obj, CONTEXT_ALIGN, false);
+       if (ret)
+               return ret;
+
+       if (!to->obj->has_global_gtt_mapping)
+               i915_gem_gtt_bind_object(to->obj, to->obj->cache_level);
+
+       if (!to->is_initialized || is_default_context(to))
+               hw_flags |= MI_RESTORE_INHIBIT;
+       else if (WARN_ON_ONCE(from_obj == to->obj)) /* not yet expected */
+               hw_flags |= MI_FORCE_RESTORE;
+
+       ring = to->ring;
+       ret = mi_set_context(ring, to, hw_flags);
+       if (ret) {
+               i915_gem_object_unpin(to->obj);
+               return ret;
+       }
+
+       /* The backing object for the context is done after switching to the
+        * *next* context. Therefore we cannot retire the previous context until
+        * the next context has already started running. In fact, the below code
+        * is a bit suboptimal because the retiring can occur simply after the
+        * MI_SET_CONTEXT instead of when the next seqno has completed.
+        */
+       if (from_obj != NULL) {
+               from_obj->base.read_domains = I915_GEM_DOMAIN_INSTRUCTION;
+               i915_gem_object_move_to_active(from_obj, ring, seqno);
+               /* As long as MI_SET_CONTEXT is serializing, ie. it flushes the
+                * whole damn pipeline, we don't need to explicitly mark the
+                * object dirty. The only exception is that the context must be
+                * correct in case the object gets swapped out. Ideally we'd be
+                * able to defer doing this until we know the object would be
+                * swapped, but there is no way to do that yet.
+                */
+               from_obj->dirty = 1;
+               BUG_ON(from_obj->ring != to->ring);
+               i915_gem_object_unpin(from_obj);
+       }
+
+       ring->last_context_obj = to->obj;
+       to->is_initialized = true;
+
+       return 0;
+}
+
+/**
+ * i915_switch_context() - perform a GPU context switch.
+ * @ring: ring for which we'll execute the context switch
+ * @file_priv: file_priv associated with the context, may be NULL
+ * @id: context id number
+ * @seqno: sequence number by which the new context will be switched to
+ * @flags:
+ *
+ * The context life cycle is simple. The context refcount is incremented and
+ * decremented by 1 and create and destroy. If the context is in use by the GPU,
+ * it will have a refoucnt > 1. This allows us to destroy the context abstract
+ * object while letting the normal object tracking destroy the backing BO.
+ */
+int i915_switch_context(struct intel_ring_buffer *ring,
+                       struct drm_file *file,
+                       int to_id)
+{
+       struct drm_i915_private *dev_priv = ring->dev->dev_private;
+       struct drm_i915_file_private *file_priv = NULL;
+       struct i915_hw_context *to;
+       struct drm_i915_gem_object *from_obj = ring->last_context_obj;
+       int ret;
+
+       if (dev_priv->hw_contexts_disabled)
+               return 0;
+
+       if (ring != &dev_priv->ring[RCS])
+               return 0;
+
+       if (file)
+               file_priv = file->driver_priv;
+
+       if (to_id == DEFAULT_CONTEXT_ID) {
+               to = ring->default_context;
+       } else {
+               to = i915_gem_context_get(file_priv, to_id);
+               if (to == NULL)
+                       return -ENOENT;
+       }
+
+       if (from_obj == to->obj)
+               return 0;
+
+       ret = do_switch(from_obj, to, i915_gem_next_request_seqno(to->ring));
+       if (ret)
+               return ret;
+
+       /* Just to make the code a little cleaner we take the object reference
+        * after the switch was successful. It would be more intuitive to ref
+        * the 'to' object before the switch but we know the refcount must be >0
+        * if context_get() succeeded, and we hold struct mutex. So it's safe to
+        * do this here/now
+        */
+       drm_gem_object_reference(&to->obj->base);
+       if (from_obj != NULL)
+               drm_gem_object_unreference(&from_obj->base);
+       return ret;
+}
+
+int i915_gem_context_create_ioctl(struct drm_device *dev, void *data,
+                                 struct drm_file *file)
+{
+       struct drm_i915_private *dev_priv = dev->dev_private;
+       struct drm_i915_gem_context_create *args = data;
+       struct drm_i915_file_private *file_priv = file->driver_priv;
+       struct i915_hw_context *ctx;
+       int ret;
+
+       if (!(dev->driver->driver_features & DRIVER_GEM))
+               return -ENODEV;
+
+       if (dev_priv->hw_contexts_disabled)
+               return -ENODEV;
+
+       ret = i915_mutex_lock_interruptible(dev);
+       if (ret)
+               return ret;
+
+       ret = create_hw_context(dev, file_priv, &ctx);
+       mutex_unlock(&dev->struct_mutex);
+
+       args->ctx_id = ctx->id;
+       DRM_DEBUG_DRIVER("HW context %d created\n", args->ctx_id);
+
+       return ret;
+}
+
+int i915_gem_context_destroy_ioctl(struct drm_device *dev, void *data,
+                                  struct drm_file *file)
+{
+       struct drm_i915_gem_context_destroy *args = data;
+       struct drm_i915_file_private *file_priv = file->driver_priv;
+       struct i915_hw_context *ctx;
+       int ret;
+
+       if (!(dev->driver->driver_features & DRIVER_GEM))
+               return -ENODEV;
+
+       ret = i915_mutex_lock_interruptible(dev);
+       if (ret)
+               return ret;
+
+       ctx = i915_gem_context_get(file_priv, args->ctx_id);
+       if (!ctx) {
+               mutex_unlock(&dev->struct_mutex);
+               return -ENOENT;
+       }
+
+       do_destroy(ctx);
+
+       mutex_unlock(&dev->struct_mutex);
+
+       DRM_DEBUG_DRIVER("HW context %d destroyed\n", args->ctx_id);
+       return 0;
+}
index a4f6aaa..bddf7be 100644 (file)
@@ -132,7 +132,8 @@ i915_gem_object_check_coherency(struct drm_i915_gem_object *obj, int handle)
                 __func__, obj, obj->gtt_offset, handle,
                 obj->size / 1024);
 
-       gtt_mapping = ioremap(dev->agp->base + obj->gtt_offset, obj->base.size);
+       gtt_mapping = ioremap(dev_priv->mm.gtt_base_addr + obj->gtt_offset,
+                             obj->base.size);
        if (gtt_mapping == NULL) {
                DRM_ERROR("failed to map GTT space\n");
                return;
index 974a9f1..88e2e11 100644 (file)
@@ -810,33 +810,16 @@ err:
        return ret;
 }
 
-static int
+static void
 i915_gem_execbuffer_flush(struct drm_device *dev,
                          uint32_t invalidate_domains,
-                         uint32_t flush_domains,
-                         uint32_t flush_rings)
+                         uint32_t flush_domains)
 {
-       drm_i915_private_t *dev_priv = dev->dev_private;
-       int i, ret;
-
        if (flush_domains & I915_GEM_DOMAIN_CPU)
                intel_gtt_chipset_flush();
 
        if (flush_domains & I915_GEM_DOMAIN_GTT)
                wmb();
-
-       if ((flush_domains | invalidate_domains) & I915_GEM_GPU_DOMAINS) {
-               for (i = 0; i < I915_NUM_RINGS; i++)
-                       if (flush_rings & (1 << i)) {
-                               ret = i915_gem_flush_ring(&dev_priv->ring[i],
-                                                         invalidate_domains,
-                                                         flush_domains);
-                               if (ret)
-                                       return ret;
-                       }
-       }
-
-       return 0;
 }
 
 static int
@@ -885,12 +868,9 @@ i915_gem_execbuffer_move_to_gpu(struct intel_ring_buffer *ring,
                i915_gem_object_set_to_gpu_domain(obj, ring, &cd);
 
        if (cd.invalidate_domains | cd.flush_domains) {
-               ret = i915_gem_execbuffer_flush(ring->dev,
-                                               cd.invalidate_domains,
-                                               cd.flush_domains,
-                                               cd.flush_rings);
-               if (ret)
-                       return ret;
+               i915_gem_execbuffer_flush(ring->dev,
+                                         cd.invalidate_domains,
+                                         cd.flush_domains);
        }
 
        if (cd.flips) {
@@ -905,6 +885,11 @@ i915_gem_execbuffer_move_to_gpu(struct intel_ring_buffer *ring,
                        return ret;
        }
 
+       /* Unconditionally invalidate gpu caches. */
+       ret = i915_gem_flush_ring(ring, I915_GEM_GPU_DOMAINS, 0);
+       if (ret)
+               return ret;
+
        return 0;
 }
 
@@ -983,26 +968,13 @@ i915_gem_execbuffer_retire_commands(struct drm_device *dev,
                                    struct intel_ring_buffer *ring)
 {
        struct drm_i915_gem_request *request;
-       u32 invalidate;
 
-       /*
-        * Ensure that the commands in the batch buffer are
-        * finished before the interrupt fires.
-        *
-        * The sampler always gets flushed on i965 (sigh).
-        */
-       invalidate = I915_GEM_DOMAIN_COMMAND;
-       if (INTEL_INFO(dev)->gen >= 4)
-               invalidate |= I915_GEM_DOMAIN_SAMPLER;
-       if (ring->flush(ring, invalidate, 0)) {
-               i915_gem_next_request_seqno(ring);
-               return;
-       }
+       /* Unconditionally force add_request to emit a full flush. */
+       ring->gpu_caches_dirty = true;
 
        /* Add a breadcrumb for the completion of the batch buffer */
        request = kzalloc(sizeof(*request), GFP_KERNEL);
        if (request == NULL || i915_add_request(ring, file, request)) {
-               i915_gem_next_request_seqno(ring);
                kfree(request);
        }
 }
@@ -1044,6 +1016,7 @@ i915_gem_do_execbuffer(struct drm_device *dev, void *data,
        struct drm_i915_gem_object *batch_obj;
        struct drm_clip_rect *cliprects = NULL;
        struct intel_ring_buffer *ring;
+       u32 ctx_id = i915_execbuffer2_get_context_id(*args);
        u32 exec_start, exec_len;
        u32 seqno;
        u32 mask;
@@ -1065,9 +1038,19 @@ i915_gem_do_execbuffer(struct drm_device *dev, void *data,
                break;
        case I915_EXEC_BSD:
                ring = &dev_priv->ring[VCS];
+               if (ctx_id != 0) {
+                       DRM_DEBUG("Ring %s doesn't support contexts\n",
+                                 ring->name);
+                       return -EPERM;
+               }
                break;
        case I915_EXEC_BLT:
                ring = &dev_priv->ring[BCS];
+               if (ctx_id != 0) {
+                       DRM_DEBUG("Ring %s doesn't support contexts\n",
+                                 ring->name);
+                       return -EPERM;
+               }
                break;
        default:
                DRM_DEBUG("execbuf with unknown ring: %d\n",
@@ -1261,6 +1244,10 @@ i915_gem_do_execbuffer(struct drm_device *dev, void *data,
                        goto err;
        }
 
+       ret = i915_switch_context(ring, file, ctx_id);
+       if (ret)
+               goto err;
+
        trace_i915_gem_ring_dispatch(ring, seqno);
 
        exec_start = batch_obj->gtt_offset + args->batch_start_offset;
@@ -1367,6 +1354,7 @@ i915_gem_execbuffer(struct drm_device *dev, void *data,
        exec2.num_cliprects = args->num_cliprects;
        exec2.cliprects_ptr = args->cliprects_ptr;
        exec2.flags = I915_EXEC_RENDER;
+       i915_execbuffer2_set_context_id(exec2, 0);
 
        ret = i915_gem_do_execbuffer(dev, data, file, &exec2, exec2_list);
        if (!ret) {
index b1fe0ed..23f2ea0 100644 (file)
@@ -375,6 +375,86 @@ static void gen6_pm_rps_work(struct work_struct *work)
        mutex_unlock(&dev_priv->dev->struct_mutex);
 }
 
+
+/**
+ * ivybridge_parity_work - Workqueue called when a parity error interrupt
+ * occurred.
+ * @work: workqueue struct
+ *
+ * Doesn't actually do anything except notify userspace. As a consequence of
+ * this event, userspace should try to remap the bad rows since statistically
+ * it is likely the same row is more likely to go bad again.
+ */
+static void ivybridge_parity_work(struct work_struct *work)
+{
+       drm_i915_private_t *dev_priv = container_of(work, drm_i915_private_t,
+                                                   parity_error_work);
+       u32 error_status, row, bank, subbank;
+       char *parity_event[5];
+       uint32_t misccpctl;
+       unsigned long flags;
+
+       /* We must turn off DOP level clock gating to access the L3 registers.
+        * In order to prevent a get/put style interface, acquire struct mutex
+        * any time we access those registers.
+        */
+       mutex_lock(&dev_priv->dev->struct_mutex);
+
+       misccpctl = I915_READ(GEN7_MISCCPCTL);
+       I915_WRITE(GEN7_MISCCPCTL, misccpctl & ~GEN7_DOP_CLOCK_GATE_ENABLE);
+       POSTING_READ(GEN7_MISCCPCTL);
+
+       error_status = I915_READ(GEN7_L3CDERRST1);
+       row = GEN7_PARITY_ERROR_ROW(error_status);
+       bank = GEN7_PARITY_ERROR_BANK(error_status);
+       subbank = GEN7_PARITY_ERROR_SUBBANK(error_status);
+
+       I915_WRITE(GEN7_L3CDERRST1, GEN7_PARITY_ERROR_VALID |
+                                   GEN7_L3CDERRST1_ENABLE);
+       POSTING_READ(GEN7_L3CDERRST1);
+
+       I915_WRITE(GEN7_MISCCPCTL, misccpctl);
+
+       spin_lock_irqsave(&dev_priv->irq_lock, flags);
+       dev_priv->gt_irq_mask &= ~GT_GEN7_L3_PARITY_ERROR_INTERRUPT;
+       I915_WRITE(GTIMR, dev_priv->gt_irq_mask);
+       spin_unlock_irqrestore(&dev_priv->irq_lock, flags);
+
+       mutex_unlock(&dev_priv->dev->struct_mutex);
+
+       parity_event[0] = "L3_PARITY_ERROR=1";
+       parity_event[1] = kasprintf(GFP_KERNEL, "ROW=%d", row);
+       parity_event[2] = kasprintf(GFP_KERNEL, "BANK=%d", bank);
+       parity_event[3] = kasprintf(GFP_KERNEL, "SUBBANK=%d", subbank);
+       parity_event[4] = NULL;
+
+       kobject_uevent_env(&dev_priv->dev->primary->kdev.kobj,
+                          KOBJ_CHANGE, parity_event);
+
+       DRM_DEBUG("Parity error: Row = %d, Bank = %d, Sub bank = %d.\n",
+                 row, bank, subbank);
+
+       kfree(parity_event[3]);
+       kfree(parity_event[2]);
+       kfree(parity_event[1]);
+}
+
+static void ivybridge_handle_parity_error(struct drm_device *dev)
+{
+       drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
+       unsigned long flags;
+
+       if (!IS_IVYBRIDGE(dev))
+               return;
+
+       spin_lock_irqsave(&dev_priv->irq_lock, flags);
+       dev_priv->gt_irq_mask |= GT_GEN7_L3_PARITY_ERROR_INTERRUPT;
+       I915_WRITE(GTIMR, dev_priv->gt_irq_mask);
+       spin_unlock_irqrestore(&dev_priv->irq_lock, flags);
+
+       queue_work(dev_priv->wq, &dev_priv->parity_error_work);
+}
+
 static void snb_gt_irq_handler(struct drm_device *dev,
                               struct drm_i915_private *dev_priv,
                               u32 gt_iir)
@@ -394,6 +474,9 @@ static void snb_gt_irq_handler(struct drm_device *dev,
                DRM_ERROR("GT error interrupt 0x%08x\n", gt_iir);
                i915_handle_error(dev, false);
        }
+
+       if (gt_iir & GT_GEN7_L3_PARITY_ERROR_INTERRUPT)
+               ivybridge_handle_parity_error(dev);
 }
 
 static void gen6_queue_rps_work(struct drm_i915_private *dev_priv,
@@ -430,15 +513,10 @@ static irqreturn_t valleyview_irq_handler(DRM_IRQ_ARGS)
        unsigned long irqflags;
        int pipe;
        u32 pipe_stats[I915_MAX_PIPES];
-       u32 vblank_status;
-       int vblank = 0;
        bool blc_event;
 
        atomic_inc(&dev_priv->irq_received);
 
-       vblank_status = PIPE_START_VBLANK_INTERRUPT_STATUS |
-               PIPE_VBLANK_INTERRUPT_STATUS;
-
        while (true) {
                iir = I915_READ(VLV_IIR);
                gt_iir = I915_READ(GTIIR);
@@ -468,6 +546,16 @@ static irqreturn_t valleyview_irq_handler(DRM_IRQ_ARGS)
                }
                spin_unlock_irqrestore(&dev_priv->irq_lock, irqflags);
 
+               for_each_pipe(pipe) {
+                       if (pipe_stats[pipe] & PIPE_VBLANK_INTERRUPT_STATUS)
+                               drm_handle_vblank(dev, pipe);
+
+                       if (pipe_stats[pipe] & PLANE_FLIPDONE_INT_STATUS_VLV) {
+                               intel_prepare_page_flip(dev, pipe);
+                               intel_finish_page_flip(dev, pipe);
+                       }
+               }
+
                /* Consume port.  Then clear IIR or we'll miss events */
                if (iir & I915_DISPLAY_PORT_INTERRUPT) {
                        u32 hotplug_status = I915_READ(PORT_HOTPLUG_STAT);
@@ -482,19 +570,6 @@ static irqreturn_t valleyview_irq_handler(DRM_IRQ_ARGS)
                        I915_READ(PORT_HOTPLUG_STAT);
                }
 
-
-               if (iir & I915_DISPLAY_PIPE_A_VBLANK_INTERRUPT) {
-                       drm_handle_vblank(dev, 0);
-                       vblank++;
-                       intel_finish_page_flip(dev, 0);
-               }
-
-               if (iir & I915_DISPLAY_PIPE_B_VBLANK_INTERRUPT) {
-                       drm_handle_vblank(dev, 1);
-                       vblank++;
-                       intel_finish_page_flip(dev, 0);
-               }
-
                if (pipe_stats[pipe] & PIPE_LEGACY_BLC_EVENT_STATUS)
                        blc_event = true;
 
@@ -1105,6 +1180,7 @@ static void i915_capture_error_state(struct drm_device *dev)
        kref_init(&error->ref);
        error->eir = I915_READ(EIR);
        error->pgtbl_er = I915_READ(PGTBL_ER);
+       error->ccid = I915_READ(CCID);
 
        if (HAS_PCH_SPLIT(dev))
                error->ier = I915_READ(DEIER) | I915_READ(GTIER);
@@ -1427,23 +1503,20 @@ static int valleyview_enable_vblank(struct drm_device *dev, int pipe)
 {
        drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
        unsigned long irqflags;
-       u32 dpfl, imr;
+       u32 imr;
 
        if (!i915_pipe_enabled(dev, pipe))
                return -EINVAL;
 
        spin_lock_irqsave(&dev_priv->irq_lock, irqflags);
-       dpfl = I915_READ(VLV_DPFLIPSTAT);
        imr = I915_READ(VLV_IMR);
-       if (pipe == 0) {
-               dpfl |= PIPEA_VBLANK_INT_EN;
+       if (pipe == 0)
                imr &= ~I915_DISPLAY_PIPE_A_VBLANK_INTERRUPT;
-       } else {
-               dpfl |= PIPEA_VBLANK_INT_EN;
+       else
                imr &= ~I915_DISPLAY_PIPE_B_VBLANK_INTERRUPT;
-       }
-       I915_WRITE(VLV_DPFLIPSTAT, dpfl);
        I915_WRITE(VLV_IMR, imr);
+       i915_enable_pipestat(dev_priv, pipe,
+                            PIPE_START_VBLANK_INTERRUPT_ENABLE);
        spin_unlock_irqrestore(&dev_priv->irq_lock, irqflags);
 
        return 0;
@@ -1493,20 +1566,17 @@ static void valleyview_disable_vblank(struct drm_device *dev, int pipe)
 {
        drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
        unsigned long irqflags;
-       u32 dpfl, imr;
+       u32 imr;
 
        spin_lock_irqsave(&dev_priv->irq_lock, irqflags);
-       dpfl = I915_READ(VLV_DPFLIPSTAT);
+       i915_disable_pipestat(dev_priv, pipe,
+                             PIPE_START_VBLANK_INTERRUPT_ENABLE);
        imr = I915_READ(VLV_IMR);
-       if (pipe == 0) {
-               dpfl &= ~PIPEA_VBLANK_INT_EN;
+       if (pipe == 0)
                imr |= I915_DISPLAY_PIPE_A_VBLANK_INTERRUPT;
-       } else {
-               dpfl &= ~PIPEB_VBLANK_INT_EN;
+       else
                imr |= I915_DISPLAY_PIPE_B_VBLANK_INTERRUPT;
-       }
        I915_WRITE(VLV_IMR, imr);
-       I915_WRITE(VLV_DPFLIPSTAT, dpfl);
        spin_unlock_irqrestore(&dev_priv->irq_lock, irqflags);
 }
 
@@ -1649,7 +1719,6 @@ static void ironlake_irq_preinstall(struct drm_device *dev)
 
        atomic_set(&dev_priv->irq_received, 0);
 
-
        I915_WRITE(HWSTAM, 0xeffe);
 
        /* XXX hotplug from PCH */
@@ -1812,13 +1881,13 @@ static int ivybridge_irq_postinstall(struct drm_device *dev)
                   DE_PIPEA_VBLANK_IVB);
        POSTING_READ(DEIER);
 
-       dev_priv->gt_irq_mask = ~0;
+       dev_priv->gt_irq_mask = ~GT_GEN7_L3_PARITY_ERROR_INTERRUPT;
 
        I915_WRITE(GTIIR, I915_READ(GTIIR));
        I915_WRITE(GTIMR, dev_priv->gt_irq_mask);
 
        render_irqs = GT_USER_INTERRUPT | GEN6_BSD_USER_INTERRUPT |
-               GEN6_BLITTER_USER_INTERRUPT;
+               GEN6_BLITTER_USER_INTERRUPT | GT_GEN7_L3_PARITY_ERROR_INTERRUPT;
        I915_WRITE(GTIER, render_irqs);
        POSTING_READ(GTIER);
 
@@ -1841,16 +1910,24 @@ static int ivybridge_irq_postinstall(struct drm_device *dev)
 static int valleyview_irq_postinstall(struct drm_device *dev)
 {
        drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
-       u32 render_irqs;
        u32 enable_mask;
        u32 hotplug_en = I915_READ(PORT_HOTPLUG_EN);
+       u32 pipestat_enable = PLANE_FLIP_DONE_INT_EN_VLV;
        u16 msid;
 
        enable_mask = I915_DISPLAY_PORT_INTERRUPT;
-       enable_mask |= I915_DISPLAY_PIPE_A_VBLANK_INTERRUPT |
+       enable_mask |= I915_DISPLAY_PIPE_A_EVENT_INTERRUPT |
+               I915_DISPLAY_PIPE_A_VBLANK_INTERRUPT |
+               I915_DISPLAY_PIPE_B_EVENT_INTERRUPT |
                I915_DISPLAY_PIPE_B_VBLANK_INTERRUPT;
 
-       dev_priv->irq_mask = ~enable_mask;
+       /*
+        *Leave vblank interrupts masked initially.  enable/disable will
+        * toggle them based on usage.
+        */
+       dev_priv->irq_mask = (~enable_mask) |
+               I915_DISPLAY_PIPE_A_VBLANK_INTERRUPT |
+               I915_DISPLAY_PIPE_B_VBLANK_INTERRUPT;
 
        dev_priv->pipestat[0] = 0;
        dev_priv->pipestat[1] = 0;
@@ -1869,26 +1946,27 @@ static int valleyview_irq_postinstall(struct drm_device *dev)
        I915_WRITE(PIPESTAT(1), 0xffff);
        POSTING_READ(VLV_IER);
 
+       i915_enable_pipestat(dev_priv, 0, pipestat_enable);
+       i915_enable_pipestat(dev_priv, 1, pipestat_enable);
+
        I915_WRITE(VLV_IIR, 0xffffffff);
        I915_WRITE(VLV_IIR, 0xffffffff);
 
-       render_irqs = GT_GEN6_BLT_FLUSHDW_NOTIFY_INTERRUPT |
-               GT_GEN6_BLT_CS_ERROR_INTERRUPT |
-               GT_GEN6_BLT_USER_INTERRUPT |
-               GT_GEN6_BSD_USER_INTERRUPT |
-               GT_GEN6_BSD_CS_ERROR_INTERRUPT |
-               GT_GEN7_L3_PARITY_ERROR_INTERRUPT |
-               GT_PIPE_NOTIFY |
-               GT_RENDER_CS_ERROR_INTERRUPT |
-               GT_SYNC_STATUS |
-               GT_USER_INTERRUPT;
-
-       dev_priv->gt_irq_mask = ~render_irqs;
+       dev_priv->gt_irq_mask = ~0;
 
        I915_WRITE(GTIIR, I915_READ(GTIIR));
        I915_WRITE(GTIIR, I915_READ(GTIIR));
-       I915_WRITE(GTIMR, 0);
-       I915_WRITE(GTIER, render_irqs);
+       I915_WRITE(GTIMR, dev_priv->gt_irq_mask);
+       I915_WRITE(GTIER, GT_GEN6_BLT_FLUSHDW_NOTIFY_INTERRUPT |
+                  GT_GEN6_BLT_CS_ERROR_INTERRUPT |
+                  GT_GEN6_BLT_USER_INTERRUPT |
+                  GT_GEN6_BSD_USER_INTERRUPT |
+                  GT_GEN6_BSD_CS_ERROR_INTERRUPT |
+                  GT_GEN7_L3_PARITY_ERROR_INTERRUPT |
+                  GT_PIPE_NOTIFY |
+                  GT_RENDER_CS_ERROR_INTERRUPT |
+                  GT_SYNC_STATUS |
+                  GT_USER_INTERRUPT);
        POSTING_READ(GTIER);
 
        /* ack & enable invalid PTE error interrupts */
@@ -2167,9 +2245,9 @@ static int i915_irq_postinstall(struct drm_device *dev)
                        hotplug_en |= HDMIC_HOTPLUG_INT_EN;
                if (dev_priv->hotplug_supported_mask & HDMID_HOTPLUG_INT_STATUS)
                        hotplug_en |= HDMID_HOTPLUG_INT_EN;
-               if (dev_priv->hotplug_supported_mask & SDVOC_HOTPLUG_INT_STATUS)
+               if (dev_priv->hotplug_supported_mask & SDVOC_HOTPLUG_INT_STATUS_I915)
                        hotplug_en |= SDVOC_HOTPLUG_INT_EN;
-               if (dev_priv->hotplug_supported_mask & SDVOB_HOTPLUG_INT_STATUS)
+               if (dev_priv->hotplug_supported_mask & SDVOB_HOTPLUG_INT_STATUS_I915)
                        hotplug_en |= SDVOB_HOTPLUG_INT_EN;
                if (dev_priv->hotplug_supported_mask & CRT_HOTPLUG_INT_STATUS) {
                        hotplug_en |= CRT_HOTPLUG_INT_EN;
@@ -2329,10 +2407,8 @@ static void i965_irq_preinstall(struct drm_device * dev)
 
        atomic_set(&dev_priv->irq_received, 0);
 
-       if (I915_HAS_HOTPLUG(dev)) {
-               I915_WRITE(PORT_HOTPLUG_EN, 0);
-               I915_WRITE(PORT_HOTPLUG_STAT, I915_READ(PORT_HOTPLUG_STAT));
-       }
+       I915_WRITE(PORT_HOTPLUG_EN, 0);
+       I915_WRITE(PORT_HOTPLUG_STAT, I915_READ(PORT_HOTPLUG_STAT));
 
        I915_WRITE(HWSTAM, 0xeffe);
        for_each_pipe(pipe)
@@ -2345,11 +2421,13 @@ static void i965_irq_preinstall(struct drm_device * dev)
 static int i965_irq_postinstall(struct drm_device *dev)
 {
        drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
+       u32 hotplug_en;
        u32 enable_mask;
        u32 error_mask;
 
        /* Unmask the interrupts that we always want on. */
        dev_priv->irq_mask = ~(I915_ASLE_INTERRUPT |
+                              I915_DISPLAY_PORT_INTERRUPT |
                               I915_DISPLAY_PIPE_A_EVENT_INTERRUPT |
                               I915_DISPLAY_PIPE_B_EVENT_INTERRUPT |
                               I915_DISPLAY_PLANE_A_FLIP_PENDING_INTERRUPT |
@@ -2365,13 +2443,6 @@ static int i965_irq_postinstall(struct drm_device *dev)
        dev_priv->pipestat[0] = 0;
        dev_priv->pipestat[1] = 0;
 
-       if (I915_HAS_HOTPLUG(dev)) {
-               /* Enable in IER... */
-               enable_mask |= I915_DISPLAY_PORT_INTERRUPT;
-               /* and unmask in IMR */
-               dev_priv->irq_mask &= ~I915_DISPLAY_PORT_INTERRUPT;
-       }
-
        /*
         * Enable some error detection, note the instruction error mask
         * bit is reserved, so we leave it masked.
@@ -2391,36 +2462,40 @@ static int i965_irq_postinstall(struct drm_device *dev)
        I915_WRITE(IER, enable_mask);
        POSTING_READ(IER);
 
-       if (I915_HAS_HOTPLUG(dev)) {
-               u32 hotplug_en = I915_READ(PORT_HOTPLUG_EN);
-
-               /* Note HDMI and DP share bits */
-               if (dev_priv->hotplug_supported_mask & HDMIB_HOTPLUG_INT_STATUS)
-                       hotplug_en |= HDMIB_HOTPLUG_INT_EN;
-               if (dev_priv->hotplug_supported_mask & HDMIC_HOTPLUG_INT_STATUS)
-                       hotplug_en |= HDMIC_HOTPLUG_INT_EN;
-               if (dev_priv->hotplug_supported_mask & HDMID_HOTPLUG_INT_STATUS)
-                       hotplug_en |= HDMID_HOTPLUG_INT_EN;
-               if (dev_priv->hotplug_supported_mask & SDVOC_HOTPLUG_INT_STATUS)
+       /* Note HDMI and DP share hotplug bits */
+       hotplug_en = 0;
+       if (dev_priv->hotplug_supported_mask & HDMIB_HOTPLUG_INT_STATUS)
+               hotplug_en |= HDMIB_HOTPLUG_INT_EN;
+       if (dev_priv->hotplug_supported_mask & HDMIC_HOTPLUG_INT_STATUS)
+               hotplug_en |= HDMIC_HOTPLUG_INT_EN;
+       if (dev_priv->hotplug_supported_mask & HDMID_HOTPLUG_INT_STATUS)
+               hotplug_en |= HDMID_HOTPLUG_INT_EN;
+       if (IS_G4X(dev)) {
+               if (dev_priv->hotplug_supported_mask & SDVOC_HOTPLUG_INT_STATUS_G4X)
                        hotplug_en |= SDVOC_HOTPLUG_INT_EN;
-               if (dev_priv->hotplug_supported_mask & SDVOB_HOTPLUG_INT_STATUS)
+               if (dev_priv->hotplug_supported_mask & SDVOB_HOTPLUG_INT_STATUS_G4X)
                        hotplug_en |= SDVOB_HOTPLUG_INT_EN;
-               if (dev_priv->hotplug_supported_mask & CRT_HOTPLUG_INT_STATUS) {
-                       hotplug_en |= CRT_HOTPLUG_INT_EN;
+       } else {
+               if (dev_priv->hotplug_supported_mask & SDVOC_HOTPLUG_INT_STATUS_I965)
+                       hotplug_en |= SDVOC_HOTPLUG_INT_EN;
+               if (dev_priv->hotplug_supported_mask & SDVOB_HOTPLUG_INT_STATUS_I965)
+                       hotplug_en |= SDVOB_HOTPLUG_INT_EN;
+       }
+       if (dev_priv->hotplug_supported_mask & CRT_HOTPLUG_INT_STATUS) {
+               hotplug_en |= CRT_HOTPLUG_INT_EN;
 
-                       /* Programming the CRT detection parameters tends
-                          to generate a spurious hotplug event about three
-                          seconds later.  So just do it once.
-                       */
-                       if (IS_G4X(dev))
-                               hotplug_en |= CRT_HOTPLUG_ACTIVATION_PERIOD_64;
-                       hotplug_en |= CRT_HOTPLUG_VOLTAGE_COMPARE_50;
-               }
+               /* Programming the CRT detection parameters tends
+                  to generate a spurious hotplug event about three
+                  seconds later.  So just do it once.
+                  */
+               if (IS_G4X(dev))
+                       hotplug_en |= CRT_HOTPLUG_ACTIVATION_PERIOD_64;
+               hotplug_en |= CRT_HOTPLUG_VOLTAGE_COMPARE_50;
+       }
 
-               /* Ignore TV since it's buggy */
+       /* Ignore TV since it's buggy */
 
-               I915_WRITE(PORT_HOTPLUG_EN, hotplug_en);
-       }
+       I915_WRITE(PORT_HOTPLUG_EN, hotplug_en);
 
        intel_opregion_enable_asle(dev);
 
@@ -2478,8 +2553,7 @@ static irqreturn_t i965_irq_handler(DRM_IRQ_ARGS)
                ret = IRQ_HANDLED;
 
                /* Consume port.  Then clear IIR or we'll miss events */
-               if ((I915_HAS_HOTPLUG(dev)) &&
-                   (iir & I915_DISPLAY_PORT_INTERRUPT)) {
+               if (iir & I915_DISPLAY_PORT_INTERRUPT) {
                        u32 hotplug_status = I915_READ(PORT_HOTPLUG_STAT);
 
                        DRM_DEBUG_DRIVER("hotplug event received, stat 0x%08x\n",
@@ -2552,10 +2626,8 @@ static void i965_irq_uninstall(struct drm_device * dev)
        if (!dev_priv)
                return;
 
-       if (I915_HAS_HOTPLUG(dev)) {
-               I915_WRITE(PORT_HOTPLUG_EN, 0);
-               I915_WRITE(PORT_HOTPLUG_STAT, I915_READ(PORT_HOTPLUG_STAT));
-       }
+       I915_WRITE(PORT_HOTPLUG_EN, 0);
+       I915_WRITE(PORT_HOTPLUG_STAT, I915_READ(PORT_HOTPLUG_STAT));
 
        I915_WRITE(HWSTAM, 0xffffffff);
        for_each_pipe(pipe)
@@ -2576,6 +2648,7 @@ void intel_irq_init(struct drm_device *dev)
        INIT_WORK(&dev_priv->hotplug_work, i915_hotplug_work_func);
        INIT_WORK(&dev_priv->error_work, i915_error_work_func);
        INIT_WORK(&dev_priv->rps_work, gen6_pm_rps_work);
+       INIT_WORK(&dev_priv->parity_error_work, ivybridge_parity_work);
 
        dev->driver->get_vblank_counter = i915_get_vblank_counter;
        dev->max_vblank_count = 0xffffff; /* only 24 bits of frame count */
index 48d5e8e..9dfc4c5 100644 (file)
 #define   MI_DISPLAY_FLIP_IVB_SPRITE_B (3 << 19)
 #define   MI_DISPLAY_FLIP_IVB_PLANE_C  (4 << 19)
 #define   MI_DISPLAY_FLIP_IVB_SPRITE_C (5 << 19)
+#define MI_ARB_ON_OFF          MI_INSTR(0x08, 0)
+#define   MI_ARB_ENABLE                        (1<<0)
+#define   MI_ARB_DISABLE               (0<<0)
 
 #define MI_SET_CONTEXT         MI_INSTR(0x18, 0)
 #define   MI_MM_SPACE_GTT              (1<<8)
 #define   DISPLAY_PLANE_B           (1<<20)
 #define GFX_OP_PIPE_CONTROL(len)       ((0x3<<29)|(0x3<<27)|(0x2<<24)|(len-2))
 #define   PIPE_CONTROL_CS_STALL                                (1<<20)
+#define   PIPE_CONTROL_TLB_INVALIDATE                  (1<<18)
 #define   PIPE_CONTROL_QW_WRITE                                (1<<14)
 #define   PIPE_CONTROL_DEPTH_STALL                     (1<<13)
 #define   PIPE_CONTROL_WRITE_FLUSH                     (1<<12)
 #define   DPLL_P2_CLOCK_DIV_MASK       0x03000000 /* i915 */
 #define   DPLL_FPA01_P1_POST_DIV_MASK  0x00ff0000 /* i915 */
 #define   DPLL_FPA01_P1_POST_DIV_MASK_PINEVIEW 0x00ff8000 /* Pineview */
+#define   DPLL_LOCK_VLV                        (1<<15)
 #define   DPLL_INTEGRATED_CLOCK_VLV    (1<<13)
 
 #define SRX_INDEX              0x3c4
  */
 #define CCID                   0x2180
 #define   CCID_EN              (1<<0)
+#define CXT_SIZE               0x21a0
+#define GEN6_CXT_POWER_SIZE(cxt_reg)   ((cxt_reg >> 24) & 0x3f)
+#define GEN6_CXT_RING_SIZE(cxt_reg)    ((cxt_reg >> 18) & 0x3f)
+#define GEN6_CXT_RENDER_SIZE(cxt_reg)  ((cxt_reg >> 12) & 0x3f)
+#define GEN6_CXT_EXTENDED_SIZE(cxt_reg)        ((cxt_reg >> 6) & 0x3f)
+#define GEN6_CXT_PIPELINE_SIZE(cxt_reg)        ((cxt_reg >> 0) & 0x3f)
+#define GEN6_CXT_TOTAL_SIZE(cxt_reg)   (GEN6_CXT_POWER_SIZE(cxt_reg) + \
+                                       GEN6_CXT_RING_SIZE(cxt_reg) + \
+                                       GEN6_CXT_RENDER_SIZE(cxt_reg) + \
+                                       GEN6_CXT_EXTENDED_SIZE(cxt_reg) + \
+                                       GEN6_CXT_PIPELINE_SIZE(cxt_reg))
+#define GEN7_CTX_SIZE          0x21a8
+#define GEN7_CTX_RENDER_SIZE(ctx_reg)  ((ctx_reg >> 16) & 0x3f)
+#define GEN7_CTX_EXTENDED_SIZE(ctx_reg)        ((ctx_reg >> 9) & 0x7f)
+#define GEN7_CTX_GT1_SIZE(ctx_reg)     ((ctx_reg >> 6) & 0x7)
+#define GEN7_CTX_VFSTATE_SIZE(ctx_reg) ((ctx_reg >> 0) & 0x3f)
+#define GEN7_CTX_TOTAL_SIZE(ctx_reg)   (GEN7_CTX_RENDER_SIZE(ctx_reg) + \
+                                        GEN7_CTX_EXTENDED_SIZE(ctx_reg) + \
+                                        GEN7_CTX_GT1_SIZE(ctx_reg) + \
+                                        GEN7_CTX_VFSTATE_SIZE(ctx_reg))
+
 /*
  * Overlay regs
  */
 #define CRT_HOTPLUG_DETECT_VOLTAGE_475MV       (1 << 2)
 
 #define PORT_HOTPLUG_STAT      0x61114
-#define   HDMIB_HOTPLUG_INT_STATUS             (1 << 29)
-#define   DPB_HOTPLUG_INT_STATUS               (1 << 29)
-#define   HDMIC_HOTPLUG_INT_STATUS             (1 << 28)
-#define   DPC_HOTPLUG_INT_STATUS               (1 << 28)
-#define   HDMID_HOTPLUG_INT_STATUS             (1 << 27)
-#define   DPD_HOTPLUG_INT_STATUS               (1 << 27)
+/* HDMI/DP bits are gen4+ */
+#define   DPB_HOTPLUG_LIVE_STATUS               (1 << 29)
+#define   DPC_HOTPLUG_LIVE_STATUS               (1 << 28)
+#define   DPD_HOTPLUG_LIVE_STATUS               (1 << 27)
+#define   DPD_HOTPLUG_INT_STATUS               (3 << 21)
+#define   DPC_HOTPLUG_INT_STATUS               (3 << 19)
+#define   DPB_HOTPLUG_INT_STATUS               (3 << 17)
+/* HDMI bits are shared with the DP bits */
+#define   HDMIB_HOTPLUG_LIVE_STATUS             (1 << 29)
+#define   HDMIC_HOTPLUG_LIVE_STATUS             (1 << 28)
+#define   HDMID_HOTPLUG_LIVE_STATUS             (1 << 27)
+#define   HDMID_HOTPLUG_INT_STATUS             (3 << 21)
+#define   HDMIC_HOTPLUG_INT_STATUS             (3 << 19)
+#define   HDMIB_HOTPLUG_INT_STATUS             (3 << 17)
+/* CRT/TV common between gen3+ */
 #define   CRT_HOTPLUG_INT_STATUS               (1 << 11)
 #define   TV_HOTPLUG_INT_STATUS                        (1 << 10)
 #define   CRT_HOTPLUG_MONITOR_MASK             (3 << 8)
 #define   CRT_HOTPLUG_MONITOR_COLOR            (3 << 8)
 #define   CRT_HOTPLUG_MONITOR_MONO             (2 << 8)
 #define   CRT_HOTPLUG_MONITOR_NONE             (0 << 8)
-#define   SDVOC_HOTPLUG_INT_STATUS             (1 << 7)
-#define   SDVOB_HOTPLUG_INT_STATUS             (1 << 6)
+/* SDVO is different across gen3/4 */
+#define   SDVOC_HOTPLUG_INT_STATUS_G4X         (1 << 3)
+#define   SDVOB_HOTPLUG_INT_STATUS_G4X         (1 << 2)
+#define   SDVOC_HOTPLUG_INT_STATUS_I965                (3 << 4)
+#define   SDVOB_HOTPLUG_INT_STATUS_I965                (3 << 2)
+#define   SDVOC_HOTPLUG_INT_STATUS_I915                (1 << 7)
+#define   SDVOB_HOTPLUG_INT_STATUS_I915                (1 << 6)
 
 /* SDVO port control */
 #define SDVOB                  0x61140
 #define   VIDEO_DIP_PORT_C             (2 << 29)
 #define   VIDEO_DIP_PORT_D             (3 << 29)
 #define   VIDEO_DIP_PORT_MASK          (3 << 29)
+#define   VIDEO_DIP_ENABLE_GCP         (1 << 25)
 #define   VIDEO_DIP_ENABLE_AVI         (1 << 21)
 #define   VIDEO_DIP_ENABLE_VENDOR      (2 << 21)
+#define   VIDEO_DIP_ENABLE_GAMUT       (4 << 21)
 #define   VIDEO_DIP_ENABLE_SPD         (8 << 21)
 #define   VIDEO_DIP_SELECT_AVI         (0 << 19)
 #define   VIDEO_DIP_SELECT_VENDOR      (1 << 19)
 #define   VIDEO_DIP_FREQ_2VSYNC                (2 << 16)
 #define   VIDEO_DIP_FREQ_MASK          (3 << 16)
 /* HSW and later: */
+#define   VIDEO_DIP_ENABLE_VSC_HSW     (1 << 20)
+#define   VIDEO_DIP_ENABLE_GCP_HSW     (1 << 16)
 #define   VIDEO_DIP_ENABLE_AVI_HSW     (1 << 12)
+#define   VIDEO_DIP_ENABLE_VS_HSW      (1 << 8)
+#define   VIDEO_DIP_ENABLE_GMP_HSW     (1 << 4)
 #define   VIDEO_DIP_ENABLE_SPD_HSW     (1 << 0)
 
 /* Panel power sequencing */
 #define PFIT_AUTO_RATIOS 0x61238
 
 /* Backlight control */
-#define BLC_PWM_CTL            0x61254
-#define   BACKLIGHT_MODULATION_FREQ_SHIFT              (17)
 #define BLC_PWM_CTL2           0x61250 /* 965+ only */
-#define   BLM_COMBINATION_MODE (1 << 30)
+#define   BLM_PWM_ENABLE               (1 << 31)
+#define   BLM_COMBINATION_MODE         (1 << 30) /* gen4 only */
+#define   BLM_PIPE_SELECT              (1 << 29)
+#define   BLM_PIPE_SELECT_IVB          (3 << 29)
+#define   BLM_PIPE_A                   (0 << 29)
+#define   BLM_PIPE_B                   (1 << 29)
+#define   BLM_PIPE_C                   (2 << 29) /* ivb + */
+#define   BLM_PIPE(pipe)               ((pipe) << 29)
+#define   BLM_POLARITY_I965            (1 << 28) /* gen4 only */
+#define   BLM_PHASE_IN_INTERUPT_STATUS (1 << 26)
+#define   BLM_PHASE_IN_ENABLE          (1 << 25)
+#define   BLM_PHASE_IN_INTERUPT_ENABL  (1 << 24)
+#define   BLM_PHASE_IN_TIME_BASE_SHIFT (16)
+#define   BLM_PHASE_IN_TIME_BASE_MASK  (0xff << 16)
+#define   BLM_PHASE_IN_COUNT_SHIFT     (8)
+#define   BLM_PHASE_IN_COUNT_MASK      (0xff << 8)
+#define   BLM_PHASE_IN_INCR_SHIFT      (0)
+#define   BLM_PHASE_IN_INCR_MASK       (0xff << 0)
+#define BLC_PWM_CTL            0x61254
 /*
  * This is the most significant 15 bits of the number of backlight cycles in a
  * complete cycle of the modulated backlight control.
  *
  * The actual value is this field multiplied by two.
  */
-#define   BACKLIGHT_MODULATION_FREQ_MASK               (0x7fff << 17)
-#define   BLM_LEGACY_MODE                              (1 << 16)
+#define   BACKLIGHT_MODULATION_FREQ_SHIFT      (17)
+#define   BACKLIGHT_MODULATION_FREQ_MASK       (0x7fff << 17)
+#define   BLM_LEGACY_MODE                      (1 << 16) /* gen2 only */
 /*
  * This is the number of cycles out of the backlight modulation cycle for which
  * the backlight is on.
  */
 #define   BACKLIGHT_DUTY_CYCLE_SHIFT           (0)
 #define   BACKLIGHT_DUTY_CYCLE_MASK            (0xffff)
+#define   BACKLIGHT_DUTY_CYCLE_MASK_PNV                (0xfffe)
+#define   BLM_POLARITY_PNV                     (1 << 0) /* pnv only */
 
 #define BLC_HIST_CTL           0x61260
 
+/* New registers for PCH-split platforms. Safe where new bits show up, the
+ * register layout machtes with gen4 BLC_PWM_CTL[12]. */
+#define BLC_PWM_CPU_CTL2       0x48250
+#define BLC_PWM_CPU_CTL                0x48254
+
+/* PCH CTL1 is totally different, all but the below bits are reserved. CTL2 is
+ * like the normal CTL from gen4 and earlier. Hooray for confusing naming. */
+#define BLC_PWM_PCH_CTL1       0xc8250
+#define   BLM_PCH_PWM_ENABLE                   (1 << 30)
+#define   BLM_PCH_OVERRIDE_ENABLE              (1 << 30)
+#define   BLM_PCH_POLARITY                     (1 << 29)
+#define BLC_PWM_PCH_CTL2       0xc8254
+
 /* TV port control */
 #define TV_CTL                 0x68000
 /** Enables the TV encoder */
 #define PIPESTAT(pipe) _PIPE(pipe, _PIPEASTAT, _PIPEBSTAT)
 
 #define VLV_DPFLIPSTAT                         0x70028
-#define   PIPEB_LINE_COMPARE_STATUS            (1<<29)
+#define   PIPEB_LINE_COMPARE_INT_EN            (1<<29)
 #define   PIPEB_HLINE_INT_EN                   (1<<28)
 #define   PIPEB_VBLANK_INT_EN                  (1<<27)
 #define   SPRITED_FLIPDONE_INT_EN              (1<<26)
 #define   SPRITEC_FLIPDONE_INT_EN              (1<<25)
 #define   PLANEB_FLIPDONE_INT_EN               (1<<24)
-#define   PIPEA_LINE_COMPARE_STATUS            (1<<21)
+#define   PIPEA_LINE_COMPARE_INT_EN            (1<<21)
 #define   PIPEA_HLINE_INT_EN                   (1<<20)
 #define   PIPEA_VBLANK_INT_EN                  (1<<19)
 #define   SPRITEB_FLIPDONE_INT_EN              (1<<18)
 #define  ADPA_CRT_HOTPLUG_FORCE_TRIGGER (1<<16)
 
 /* or SDVOB */
-#define VLV_HDMIB 0x61140
 #define HDMIB   0xe1140
 #define  PORT_ENABLE    (1 << 31)
 #define  TRANSCODER(pipe)       ((pipe) << 30)
 #define PCH_LVDS       0xe1180
 #define  LVDS_DETECTED (1 << 1)
 
-#define BLC_PWM_CPU_CTL2       0x48250
-#define  PWM_ENABLE            (1 << 31)
-#define  PWM_PIPE_A            (0 << 29)
-#define  PWM_PIPE_B            (1 << 29)
-#define BLC_PWM_CPU_CTL                0x48254
-
-#define BLC_PWM_PCH_CTL1       0xc8250
-#define  PWM_PCH_ENABLE                (1 << 31)
-#define  PWM_POLARITY_ACTIVE_LOW       (1 << 29)
-#define  PWM_POLARITY_ACTIVE_HIGH      (0 << 29)
-#define  PWM_POLARITY_ACTIVE_LOW2      (1 << 28)
-#define  PWM_POLARITY_ACTIVE_HIGH2     (0 << 28)
+/* vlv has 2 sets of panel control regs. */
+#define PIPEA_PP_STATUS         0x61200
+#define PIPEA_PP_CONTROL        0x61204
+#define PIPEA_PP_ON_DELAYS      0x61208
+#define PIPEA_PP_OFF_DELAYS     0x6120c
+#define PIPEA_PP_DIVISOR        0x61210
 
-#define BLC_PWM_PCH_CTL2       0xc8254
+#define PIPEB_PP_STATUS         0x61300
+#define PIPEB_PP_CONTROL        0x61304
+#define PIPEB_PP_ON_DELAYS      0x61308
+#define PIPEB_PP_OFF_DELAYS     0x6130c
+#define PIPEB_PP_DIVISOR        0x61310
 
 #define PCH_PP_STATUS          0xc7200
 #define PCH_PP_CONTROL         0xc7204
 # define GEN6_CSUNIT_CLOCK_GATE_DISABLE                        (1 << 7)
 
 #define GEN6_UCGCTL2                           0x9404
+# define GEN7_VDSUNIT_CLOCK_GATE_DISABLE               (1 << 30)
+# define GEN7_TDLUNIT_CLOCK_GATE_DISABLE               (1 << 22)
 # define GEN6_RCZUNIT_CLOCK_GATE_DISABLE               (1 << 13)
 # define GEN6_RCPBUNIT_CLOCK_GATE_DISABLE              (1 << 12)
 # define GEN6_RCCUNIT_CLOCK_GATE_DISABLE               (1 << 11)
 
+#define GEN7_UCGCTL4                           0x940c
+#define  GEN7_L3BANK2X_CLOCK_GATE_DISABLE      (1<<25)
+
 #define GEN6_RPNSWREQ                          0xA008
 #define   GEN6_TURBO_DISABLE                   (1<<31)
 #define   GEN6_FREQUENCY(x)                    ((x)<<25)
 #define   GEN6_RC6                     3
 #define   GEN6_RC7                     4
 
+#define GEN7_MISCCPCTL                 (0x9424)
+#define   GEN7_DOP_CLOCK_GATE_ENABLE   (1<<0)
+
+/* IVYBRIDGE DPF */
+#define GEN7_L3CDERRST1                        0xB008 /* L3CD Error Status 1 */
+#define   GEN7_L3CDERRST1_ROW_MASK     (0x7ff<<14)
+#define   GEN7_PARITY_ERROR_VALID      (1<<13)
+#define   GEN7_L3CDERRST1_BANK_MASK    (3<<11)
+#define   GEN7_L3CDERRST1_SUBBANK_MASK (7<<8)
+#define GEN7_PARITY_ERROR_ROW(reg) \
+               ((reg & GEN7_L3CDERRST1_ROW_MASK) >> 14)
+#define GEN7_PARITY_ERROR_BANK(reg) \
+               ((reg & GEN7_L3CDERRST1_BANK_MASK) >> 11)
+#define GEN7_PARITY_ERROR_SUBBANK(reg) \
+               ((reg & GEN7_L3CDERRST1_SUBBANK_MASK) >> 8)
+#define   GEN7_L3CDERRST1_ENABLE       (1<<7)
+
+#define GEN7_L3LOG_BASE                        0xB070
+#define GEN7_L3LOG_SIZE                        0x80
+
 #define G4X_AUD_VID_DID                        0x62020
 #define INTEL_AUDIO_DEVCL              0x808629FB
 #define INTEL_AUDIO_DEVBLC             0x80862801
index 79f8344..2f5388a 100644 (file)
@@ -29,6 +29,7 @@
 #include <linux/module.h>
 #include <linux/stat.h>
 #include <linux/sysfs.h>
+#include "intel_drv.h"
 #include "i915_drv.h"
 
 static u32 calc_residency(struct drm_device *dev, const u32 reg)
@@ -92,20 +93,134 @@ static struct attribute_group rc6_attr_group = {
        .attrs =  rc6_attrs
 };
 
-void i915_setup_sysfs(struct drm_device *dev)
+static int l3_access_valid(struct drm_device *dev, loff_t offset)
+{
+       if (!IS_IVYBRIDGE(dev))
+               return -EPERM;
+
+       if (offset % 4 != 0)
+               return -EINVAL;
+
+       if (offset >= GEN7_L3LOG_SIZE)
+               return -ENXIO;
+
+       return 0;
+}
+
+static ssize_t
+i915_l3_read(struct file *filp, struct kobject *kobj,
+            struct bin_attribute *attr, char *buf,
+            loff_t offset, size_t count)
+{
+       struct device *dev = container_of(kobj, struct device, kobj);
+       struct drm_minor *dminor = container_of(dev, struct drm_minor, kdev);
+       struct drm_device *drm_dev = dminor->dev;
+       struct drm_i915_private *dev_priv = drm_dev->dev_private;
+       uint32_t misccpctl;
+       int i, ret;
+
+       ret = l3_access_valid(drm_dev, offset);
+       if (ret)
+               return ret;
+
+       ret = i915_mutex_lock_interruptible(drm_dev);
+       if (ret)
+               return ret;
+
+       misccpctl = I915_READ(GEN7_MISCCPCTL);
+       I915_WRITE(GEN7_MISCCPCTL, misccpctl & ~GEN7_DOP_CLOCK_GATE_ENABLE);
+
+       for (i = offset; count >= 4 && i < GEN7_L3LOG_SIZE; i += 4, count -= 4)
+               *((uint32_t *)(&buf[i])) = I915_READ(GEN7_L3LOG_BASE + i);
+
+       I915_WRITE(GEN7_MISCCPCTL, misccpctl);
+
+       mutex_unlock(&drm_dev->struct_mutex);
+
+       return i - offset;
+}
+
+static ssize_t
+i915_l3_write(struct file *filp, struct kobject *kobj,
+             struct bin_attribute *attr, char *buf,
+             loff_t offset, size_t count)
 {
+       struct device *dev = container_of(kobj, struct device, kobj);
+       struct drm_minor *dminor = container_of(dev, struct drm_minor, kdev);
+       struct drm_device *drm_dev = dminor->dev;
+       struct drm_i915_private *dev_priv = drm_dev->dev_private;
+       u32 *temp = NULL; /* Just here to make handling failures easy */
        int ret;
 
-       /* ILK doesn't have any residency information */
-       if (INTEL_INFO(dev)->gen < 6)
-               return;
+       ret = l3_access_valid(drm_dev, offset);
+       if (ret)
+               return ret;
 
-       ret = sysfs_merge_group(&dev->primary->kdev.kobj, &rc6_attr_group);
+       ret = i915_mutex_lock_interruptible(drm_dev);
        if (ret)
-               DRM_ERROR("sysfs setup failed\n");
+               return ret;
+
+       if (!dev_priv->mm.l3_remap_info) {
+               temp = kzalloc(GEN7_L3LOG_SIZE, GFP_KERNEL);
+               if (!temp) {
+                       mutex_unlock(&drm_dev->struct_mutex);
+                       return -ENOMEM;
+               }
+       }
+
+       ret = i915_gpu_idle(drm_dev);
+       if (ret) {
+               kfree(temp);
+               mutex_unlock(&drm_dev->struct_mutex);
+               return ret;
+       }
+
+       /* TODO: Ideally we really want a GPU reset here to make sure errors
+        * aren't propagated. Since I cannot find a stable way to reset the GPU
+        * at this point it is left as a TODO.
+       */
+       if (temp)
+               dev_priv->mm.l3_remap_info = temp;
+
+       memcpy(dev_priv->mm.l3_remap_info + (offset/4),
+              buf + (offset/4),
+              count);
+
+       i915_gem_l3_remap(drm_dev);
+
+       mutex_unlock(&drm_dev->struct_mutex);
+
+       return count;
+}
+
+static struct bin_attribute dpf_attrs = {
+       .attr = {.name = "l3_parity", .mode = (S_IRUSR | S_IWUSR)},
+       .size = GEN7_L3LOG_SIZE,
+       .read = i915_l3_read,
+       .write = i915_l3_write,
+       .mmap = NULL
+};
+
+void i915_setup_sysfs(struct drm_device *dev)
+{
+       int ret;
+
+       if (INTEL_INFO(dev)->gen >= 6) {
+               ret = sysfs_merge_group(&dev->primary->kdev.kobj,
+                                       &rc6_attr_group);
+               if (ret)
+                       DRM_ERROR("RC6 residency sysfs setup failed\n");
+       }
+
+       if (IS_IVYBRIDGE(dev)) {
+               ret = device_create_bin_file(&dev->primary->kdev, &dpf_attrs);
+               if (ret)
+                       DRM_ERROR("l3 parity sysfs setup failed\n");
+       }
 }
 
 void i915_teardown_sysfs(struct drm_device *dev)
 {
+       device_remove_bin_file(&dev->primary->kdev,  &dpf_attrs);
        sysfs_unmerge_group(&dev->primary->kdev.kobj, &rc6_attr_group);
 }
index dac7bba..fe90b3a 100644 (file)
@@ -311,9 +311,33 @@ DEFINE_EVENT(i915_gem_request, i915_gem_request_retire,
            TP_ARGS(ring, seqno)
 );
 
-DEFINE_EVENT(i915_gem_request, i915_gem_request_wait_begin,
+TRACE_EVENT(i915_gem_request_wait_begin,
            TP_PROTO(struct intel_ring_buffer *ring, u32 seqno),
-           TP_ARGS(ring, seqno)
+           TP_ARGS(ring, seqno),
+
+           TP_STRUCT__entry(
+                            __field(u32, dev)
+                            __field(u32, ring)
+                            __field(u32, seqno)
+                            __field(bool, blocking)
+                            ),
+
+           /* NB: the blocking information is racy since mutex_is_locked
+            * doesn't check that the current thread holds the lock. The only
+            * other option would be to pass the boolean information of whether
+            * or not the class was blocking down through the stack which is
+            * less desirable.
+            */
+           TP_fast_assign(
+                          __entry->dev = ring->dev->primary->index;
+                          __entry->ring = ring->id;
+                          __entry->seqno = seqno;
+                          __entry->blocking = mutex_is_locked(&ring->dev->struct_mutex);
+                          ),
+
+           TP_printk("dev=%u, ring=%u, seqno=%u, blocking=%s",
+                     __entry->dev, __entry->ring, __entry->seqno,
+                     __entry->blocking ?  "yes (NB)" : "no")
 );
 
 DEFINE_EVENT(i915_gem_request, i915_gem_request_wait_end,
index 75a70c4..61d55d3 100644 (file)
@@ -88,6 +88,9 @@ static void gmch_crt_dpms(struct drm_encoder *encoder, int mode)
        temp &= ~(ADPA_HSYNC_CNTL_DISABLE | ADPA_VSYNC_CNTL_DISABLE);
        temp &= ~ADPA_DAC_ENABLE;
 
+       if (IS_VALLEYVIEW(dev) && mode != DRM_MODE_DPMS_ON)
+               mode = DRM_MODE_DPMS_OFF;
+
        switch (mode) {
        case DRM_MODE_DPMS_ON:
                temp |= ADPA_DAC_ENABLE;
@@ -230,6 +233,42 @@ static bool intel_ironlake_crt_detect_hotplug(struct drm_connector *connector)
        return ret;
 }
 
+static bool valleyview_crt_detect_hotplug(struct drm_connector *connector)
+{
+       struct drm_device *dev = connector->dev;
+       struct drm_i915_private *dev_priv = dev->dev_private;
+       u32 adpa;
+       bool ret;
+       u32 save_adpa;
+
+       save_adpa = adpa = I915_READ(ADPA);
+       DRM_DEBUG_KMS("trigger hotplug detect cycle: adpa=0x%x\n", adpa);
+
+       adpa |= ADPA_CRT_HOTPLUG_FORCE_TRIGGER;
+
+       I915_WRITE(ADPA, adpa);
+
+       if (wait_for((I915_READ(ADPA) & ADPA_CRT_HOTPLUG_FORCE_TRIGGER) == 0,
+                    1000)) {
+               DRM_DEBUG_KMS("timed out waiting for FORCE_TRIGGER");
+               I915_WRITE(ADPA, save_adpa);
+       }
+
+       /* Check the status to see if both blue and green are on now */
+       adpa = I915_READ(ADPA);
+       if ((adpa & ADPA_CRT_HOTPLUG_MONITOR_MASK) != 0)
+               ret = true;
+       else
+               ret = false;
+
+       DRM_DEBUG_KMS("valleyview hotplug adpa=0x%x, result %d\n", adpa, ret);
+
+       /* FIXME: debug force function and remove */
+       ret = true;
+
+       return ret;
+}
+
 /**
  * Uses CRT_HOTPLUG_EN and CRT_HOTPLUG_STAT to detect CRT presence.
  *
@@ -249,6 +288,9 @@ static bool intel_crt_detect_hotplug(struct drm_connector *connector)
        if (HAS_PCH_SPLIT(dev))
                return intel_ironlake_crt_detect_hotplug(connector);
 
+       if (IS_VALLEYVIEW(dev))
+               return valleyview_crt_detect_hotplug(connector);
+
        /*
         * On 4 series desktop, CRT detect sequence need to be done twice
         * to get a reliable result.
@@ -453,18 +495,27 @@ intel_crt_detect(struct drm_connector *connector, bool force)
        struct intel_load_detect_pipe tmp;
 
        if (I915_HAS_HOTPLUG(dev)) {
+               /* We can not rely on the HPD pin always being correctly wired
+                * up, for example many KVM do not pass it through, and so
+                * only trust an assertion that the monitor is connected.
+                */
                if (intel_crt_detect_hotplug(connector)) {
                        DRM_DEBUG_KMS("CRT detected via hotplug\n");
                        return connector_status_connected;
-               } else {
+               } else
                        DRM_DEBUG_KMS("CRT not detected via hotplug\n");
-                       return connector_status_disconnected;
-               }
        }
 
        if (intel_crt_detect_ddc(connector))
                return connector_status_connected;
 
+       /* Load detection is broken on HPD capable machines. Whoever wants a
+        * broken monitor (without edid) to work behind a broken kvm (that fails
+        * to have the right resistors for HP detection) needs to fix this up.
+        * For now just bail out. */
+       if (I915_HAS_HOTPLUG(dev))
+               return connector_status_disconnected;
+
        if (!force)
                return connector->status;
 
index 46d1e88..f33fe1a 100644 (file)
@@ -726,8 +726,7 @@ void intel_ddi_mode_set(struct drm_encoder *encoder,
 
        I915_WRITE(DDI_FUNC_CTL(pipe), temp);
 
-       intel_hdmi_set_avi_infoframe(encoder, adjusted_mode);
-       intel_hdmi_set_spd_infoframe(encoder);
+       intel_hdmi->set_infoframes(encoder, adjusted_mode);
 }
 
 void intel_ddi_dpms(struct drm_encoder *encoder, int mode)
index a7c727d..b3052ef 100644 (file)
@@ -98,6 +98,11 @@ intel_find_pll_ironlake_dp(const intel_limit_t *, struct drm_crtc *crtc,
                           int target, int refclk, intel_clock_t *match_clock,
                           intel_clock_t *best_clock);
 
+static bool
+intel_vlv_find_best_pll(const intel_limit_t *limit, struct drm_crtc *crtc,
+                       int target, int refclk, intel_clock_t *match_clock,
+                       intel_clock_t *best_clock);
+
 static inline u32 /* units of 100MHz */
 intel_fdi_link_freq(struct drm_device *dev)
 {
@@ -359,6 +364,48 @@ static const intel_limit_t intel_limits_ironlake_display_port = {
        .find_pll = intel_find_pll_ironlake_dp,
 };
 
+static const intel_limit_t intel_limits_vlv_dac = {
+       .dot = { .min = 25000, .max = 270000 },
+       .vco = { .min = 4000000, .max = 6000000 },
+       .n = { .min = 1, .max = 7 },
+       .m = { .min = 22, .max = 450 }, /* guess */
+       .m1 = { .min = 2, .max = 3 },
+       .m2 = { .min = 11, .max = 156 },
+       .p = { .min = 10, .max = 30 },
+       .p1 = { .min = 2, .max = 3 },
+       .p2 = { .dot_limit = 270000,
+               .p2_slow = 2, .p2_fast = 20 },
+       .find_pll = intel_vlv_find_best_pll,
+};
+
+static const intel_limit_t intel_limits_vlv_hdmi = {
+       .dot = { .min = 20000, .max = 165000 },
+       .vco = { .min = 5994000, .max = 4000000 },
+       .n = { .min = 1, .max = 7 },
+       .m = { .min = 60, .max = 300 }, /* guess */
+       .m1 = { .min = 2, .max = 3 },
+       .m2 = { .min = 11, .max = 156 },
+       .p = { .min = 10, .max = 30 },
+       .p1 = { .min = 2, .max = 3 },
+       .p2 = { .dot_limit = 270000,
+               .p2_slow = 2, .p2_fast = 20 },
+       .find_pll = intel_vlv_find_best_pll,
+};
+
+static const intel_limit_t intel_limits_vlv_dp = {
+       .dot = { .min = 162000, .max = 270000 },
+       .vco = { .min = 5994000, .max = 4000000 },
+       .n = { .min = 1, .max = 7 },
+       .m = { .min = 60, .max = 300 }, /* guess */
+       .m1 = { .min = 2, .max = 3 },
+       .m2 = { .min = 11, .max = 156 },
+       .p = { .min = 10, .max = 30 },
+       .p1 = { .min = 2, .max = 3 },
+       .p2 = { .dot_limit = 270000,
+               .p2_slow = 2, .p2_fast = 20 },
+       .find_pll = intel_vlv_find_best_pll,
+};
+
 u32 intel_dpio_read(struct drm_i915_private *dev_priv, int reg)
 {
        unsigned long flags;
@@ -384,6 +431,28 @@ out_unlock:
        return val;
 }
 
+static void intel_dpio_write(struct drm_i915_private *dev_priv, int reg,
+                            u32 val)
+{
+       unsigned long flags;
+
+       spin_lock_irqsave(&dev_priv->dpio_lock, flags);
+       if (wait_for_atomic_us((I915_READ(DPIO_PKT) & DPIO_BUSY) == 0, 100)) {
+               DRM_ERROR("DPIO idle wait timed out\n");
+               goto out_unlock;
+       }
+
+       I915_WRITE(DPIO_DATA, val);
+       I915_WRITE(DPIO_REG, reg);
+       I915_WRITE(DPIO_PKT, DPIO_RID | DPIO_OP_WRITE | DPIO_PORTID |
+                  DPIO_BYTE);
+       if (wait_for_atomic_us((I915_READ(DPIO_PKT) & DPIO_BUSY) == 0, 100))
+               DRM_ERROR("DPIO write wait timed out\n");
+
+out_unlock:
+       spin_unlock_irqrestore(&dev_priv->dpio_lock, flags);
+}
+
 static void vlv_init_dpio(struct drm_device *dev)
 {
        struct drm_i915_private *dev_priv = dev->dev_private;
@@ -434,7 +503,7 @@ static bool is_dual_link_lvds(struct drm_i915_private *dev_priv,
                 * register is uninitialized.
                 */
                val = I915_READ(reg);
-               if (!(val & ~LVDS_DETECTED))
+               if (!(val & ~(LVDS_PIPE_MASK | LVDS_DETECTED)))
                        val = dev_priv->bios_lvds_val;
                dev_priv->lvds_val = val;
        }
@@ -510,6 +579,13 @@ static const intel_limit_t *intel_limit(struct drm_crtc *crtc, int refclk)
                        limit = &intel_limits_pineview_lvds;
                else
                        limit = &intel_limits_pineview_sdvo;
+       } else if (IS_VALLEYVIEW(dev)) {
+               if (intel_pipe_has_type(crtc, INTEL_OUTPUT_ANALOG))
+                       limit = &intel_limits_vlv_dac;
+               else if (intel_pipe_has_type(crtc, INTEL_OUTPUT_HDMI))
+                       limit = &intel_limits_vlv_hdmi;
+               else
+                       limit = &intel_limits_vlv_dp;
        } else if (!IS_GEN2(dev)) {
                if (intel_pipe_has_type(crtc, INTEL_OUTPUT_LVDS))
                        limit = &intel_limits_i9xx_lvds;
@@ -783,6 +859,73 @@ intel_find_pll_g4x_dp(const intel_limit_t *limit, struct drm_crtc *crtc,
        memcpy(best_clock, &clock, sizeof(intel_clock_t));
        return true;
 }
+static bool
+intel_vlv_find_best_pll(const intel_limit_t *limit, struct drm_crtc *crtc,
+                       int target, int refclk, intel_clock_t *match_clock,
+                       intel_clock_t *best_clock)
+{
+       u32 p1, p2, m1, m2, vco, bestn, bestm1, bestm2, bestp1, bestp2;
+       u32 m, n, fastclk;
+       u32 updrate, minupdate, fracbits, p;
+       unsigned long bestppm, ppm, absppm;
+       int dotclk, flag;
+
+       dotclk = target * 1000;
+       bestppm = 1000000;
+       ppm = absppm = 0;
+       fastclk = dotclk / (2*100);
+       updrate = 0;
+       minupdate = 19200;
+       fracbits = 1;
+       n = p = p1 = p2 = m = m1 = m2 = vco = bestn = 0;
+       bestm1 = bestm2 = bestp1 = bestp2 = 0;
+
+       /* based on hardware requirement, prefer smaller n to precision */
+       for (n = limit->n.min; n <= ((refclk) / minupdate); n++) {
+               updrate = refclk / n;
+               for (p1 = limit->p1.max; p1 > limit->p1.min; p1--) {
+                       for (p2 = limit->p2.p2_fast+1; p2 > 0; p2--) {
+                               if (p2 > 10)
+                                       p2 = p2 - 1;
+                               p = p1 * p2;
+                               /* based on hardware requirement, prefer bigger m1,m2 values */
+                               for (m1 = limit->m1.min; m1 <= limit->m1.max; m1++) {
+                                       m2 = (((2*(fastclk * p * n / m1 )) +
+                                              refclk) / (2*refclk));
+                                       m = m1 * m2;
+                                       vco = updrate * m;
+                                       if (vco >= limit->vco.min && vco < limit->vco.max) {
+                                               ppm = 1000000 * ((vco / p) - fastclk) / fastclk;
+                                               absppm = (ppm > 0) ? ppm : (-ppm);
+                                               if (absppm < 100 && ((p1 * p2) > (bestp1 * bestp2))) {
+                                                       bestppm = 0;
+                                                       flag = 1;
+                                               }
+                                               if (absppm < bestppm - 10) {
+                                                       bestppm = absppm;
+                                                       flag = 1;
+                                               }
+                                               if (flag) {
+                                                       bestn = n;
+                                                       bestm1 = m1;
+                                                       bestm2 = m2;
+                                                       bestp1 = p1;
+                                                       bestp2 = p2;
+                                                       flag = 0;
+                                               }
+                                       }
+                               }
+                       }
+               }
+       }
+       best_clock->n = bestn;
+       best_clock->m1 = bestm1;
+       best_clock->m2 = bestm2;
+       best_clock->p1 = bestp1;
+       best_clock->p2 = bestp2;
+
+       return true;
+}
 
 static void ironlake_wait_for_vblank(struct drm_device *dev, int pipe)
 {
@@ -1232,6 +1375,9 @@ static void assert_pch_dp_disabled(struct drm_i915_private *dev_priv,
        WARN(dp_pipe_enabled(dev_priv, pipe, port_sel, val),
             "PCH DP (0x%08x) enabled on transcoder %c, should be disabled\n",
             reg, pipe_name(pipe));
+
+       WARN(HAS_PCH_IBX(dev_priv->dev) && (val & SDVO_PIPE_B_SELECT),
+            "IBX PCH dp port still using transcoder B\n");
 }
 
 static void assert_pch_hdmi_disabled(struct drm_i915_private *dev_priv,
@@ -1241,6 +1387,9 @@ static void assert_pch_hdmi_disabled(struct drm_i915_private *dev_priv,
        WARN(hdmi_pipe_enabled(dev_priv, val, pipe),
             "PCH HDMI (0x%08x) enabled on transcoder %c, should be disabled\n",
             reg, pipe_name(pipe));
+
+       WARN(HAS_PCH_IBX(dev_priv->dev) && (val & SDVO_PIPE_B_SELECT),
+            "IBX PCH hdmi port still using transcoder B\n");
 }
 
 static void assert_pch_ports_disabled(struct drm_i915_private *dev_priv,
@@ -1287,7 +1436,7 @@ static void intel_enable_pll(struct drm_i915_private *dev_priv, enum pipe pipe)
        u32 val;
 
        /* No really, not for ILK+ */
-       BUG_ON(dev_priv->info->gen >= 5);
+       BUG_ON(!IS_VALLEYVIEW(dev_priv->dev) && dev_priv->info->gen >= 5);
 
        /* PLL is protected by panel, make sure we can write it */
        if (IS_MOBILE(dev_priv->dev) && !IS_I830(dev_priv->dev))
@@ -1344,7 +1493,7 @@ intel_sbi_write(struct drm_i915_private *dev_priv, u16 reg, u32 value)
        unsigned long flags;
 
        spin_lock_irqsave(&dev_priv->dpio_lock, flags);
-       if (wait_for((I915_READ(SBI_CTL_STAT) & SBI_READY) == 0,
+       if (wait_for((I915_READ(SBI_CTL_STAT) & SBI_BUSY) == 0,
                                100)) {
                DRM_ERROR("timeout waiting for SBI to become ready\n");
                goto out_unlock;
@@ -1358,7 +1507,7 @@ intel_sbi_write(struct drm_i915_private *dev_priv, u16 reg, u32 value)
                        SBI_BUSY |
                        SBI_CTL_OP_CRWR);
 
-       if (wait_for((I915_READ(SBI_CTL_STAT) & (SBI_READY | SBI_RESPONSE_SUCCESS)) == 0,
+       if (wait_for((I915_READ(SBI_CTL_STAT) & (SBI_BUSY | SBI_RESPONSE_FAIL)) == 0,
                                100)) {
                DRM_ERROR("timeout waiting for SBI to complete write transaction\n");
                goto out_unlock;
@@ -1372,10 +1521,10 @@ static u32
 intel_sbi_read(struct drm_i915_private *dev_priv, u16 reg)
 {
        unsigned long flags;
-       u32 value;
+       u32 value = 0;
 
        spin_lock_irqsave(&dev_priv->dpio_lock, flags);
-       if (wait_for((I915_READ(SBI_CTL_STAT) & SBI_READY) == 0,
+       if (wait_for((I915_READ(SBI_CTL_STAT) & SBI_BUSY) == 0,
                                100)) {
                DRM_ERROR("timeout waiting for SBI to become ready\n");
                goto out_unlock;
@@ -1387,7 +1536,7 @@ intel_sbi_read(struct drm_i915_private *dev_priv, u16 reg)
                        SBI_BUSY |
                        SBI_CTL_OP_CRRD);
 
-       if (wait_for((I915_READ(SBI_CTL_STAT) & (SBI_READY | SBI_RESPONSE_SUCCESS)) == 0,
+       if (wait_for((I915_READ(SBI_CTL_STAT) & (SBI_BUSY | SBI_RESPONSE_FAIL)) == 0,
                                100)) {
                DRM_ERROR("timeout waiting for SBI to complete read transaction\n");
                goto out_unlock;
@@ -3666,13 +3815,37 @@ static bool intel_choose_pipe_bpp_dither(struct drm_crtc *crtc,
        return display_bpc != bpc;
 }
 
+static int vlv_get_refclk(struct drm_crtc *crtc)
+{
+       struct drm_device *dev = crtc->dev;
+       struct drm_i915_private *dev_priv = dev->dev_private;
+       int refclk = 27000; /* for DP & HDMI */
+
+       return 100000; /* only one validated so far */
+
+       if (intel_pipe_has_type(crtc, INTEL_OUTPUT_ANALOG)) {
+               refclk = 96000;
+       } else if (intel_pipe_has_type(crtc, INTEL_OUTPUT_LVDS)) {
+               if (intel_panel_use_ssc(dev_priv))
+                       refclk = 100000;
+               else
+                       refclk = 96000;
+       } else if (intel_pipe_has_type(crtc, INTEL_OUTPUT_EDP)) {
+               refclk = 100000;
+       }
+
+       return refclk;
+}
+
 static int i9xx_get_refclk(struct drm_crtc *crtc, int num_connectors)
 {
        struct drm_device *dev = crtc->dev;
        struct drm_i915_private *dev_priv = dev->dev_private;
        int refclk;
 
-       if (intel_pipe_has_type(crtc, INTEL_OUTPUT_LVDS) &&
+       if (IS_VALLEYVIEW(dev)) {
+               refclk = vlv_get_refclk(crtc);
+       } else if (intel_pipe_has_type(crtc, INTEL_OUTPUT_LVDS) &&
            intel_panel_use_ssc(dev_priv) && num_connectors < 2) {
                refclk = dev_priv->lvds_ssc_freq * 1000;
                DRM_DEBUG_KMS("using SSC reference clock of %d MHz\n",
@@ -3787,6 +3960,72 @@ static void intel_update_lvds(struct drm_crtc *crtc, intel_clock_t *clock,
        I915_WRITE(LVDS, temp);
 }
 
+static void vlv_update_pll(struct drm_crtc *crtc,
+                          struct drm_display_mode *mode,
+                          struct drm_display_mode *adjusted_mode,
+                          intel_clock_t *clock, intel_clock_t *reduced_clock,
+                          int refclk, int num_connectors)
+{
+       struct drm_device *dev = crtc->dev;
+       struct drm_i915_private *dev_priv = dev->dev_private;
+       struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
+       int pipe = intel_crtc->pipe;
+       u32 dpll, mdiv, pdiv;
+       u32 bestn, bestm1, bestm2, bestp1, bestp2;
+       bool is_hdmi;
+
+       is_hdmi = intel_pipe_has_type(crtc, INTEL_OUTPUT_HDMI);
+
+       bestn = clock->n;
+       bestm1 = clock->m1;
+       bestm2 = clock->m2;
+       bestp1 = clock->p1;
+       bestp2 = clock->p2;
+
+       /* Enable DPIO clock input */
+       dpll = DPLL_EXT_BUFFER_ENABLE_VLV | DPLL_REFA_CLK_ENABLE_VLV |
+               DPLL_VGA_MODE_DIS | DPLL_INTEGRATED_CLOCK_VLV;
+       I915_WRITE(DPLL(pipe), dpll);
+       POSTING_READ(DPLL(pipe));
+
+       mdiv = ((bestm1 << DPIO_M1DIV_SHIFT) | (bestm2 & DPIO_M2DIV_MASK));
+       mdiv |= ((bestp1 << DPIO_P1_SHIFT) | (bestp2 << DPIO_P2_SHIFT));
+       mdiv |= ((bestn << DPIO_N_SHIFT));
+       mdiv |= (1 << DPIO_POST_DIV_SHIFT);
+       mdiv |= (1 << DPIO_K_SHIFT);
+       mdiv |= DPIO_ENABLE_CALIBRATION;
+       intel_dpio_write(dev_priv, DPIO_DIV(pipe), mdiv);
+
+       intel_dpio_write(dev_priv, DPIO_CORE_CLK(pipe), 0x01000000);
+
+       pdiv = DPIO_REFSEL_OVERRIDE | (5 << DPIO_PLL_MODESEL_SHIFT) |
+               (3 << DPIO_BIAS_CURRENT_CTL_SHIFT) | (1<<20) |
+               (8 << DPIO_DRIVER_CTL_SHIFT) | (5 << DPIO_CLK_BIAS_CTL_SHIFT);
+       intel_dpio_write(dev_priv, DPIO_REFSFR(pipe), pdiv);
+
+       intel_dpio_write(dev_priv, DPIO_LFP_COEFF(pipe), 0x009f0051);
+
+       dpll |= DPLL_VCO_ENABLE;
+       I915_WRITE(DPLL(pipe), dpll);
+       POSTING_READ(DPLL(pipe));
+       if (wait_for(((I915_READ(DPLL(pipe)) & DPLL_LOCK_VLV) == DPLL_LOCK_VLV), 1))
+               DRM_ERROR("DPLL %d failed to lock\n", pipe);
+
+       if (is_hdmi) {
+               u32 temp = intel_mode_get_pixel_multiplier(adjusted_mode);
+
+               if (temp > 1)
+                       temp = (temp - 1) << DPLL_MD_UDI_MULTIPLIER_SHIFT;
+               else
+                       temp = 0;
+
+               I915_WRITE(DPLL_MD(pipe), temp);
+               POSTING_READ(DPLL_MD(pipe));
+       }
+
+       intel_dpio_write(dev_priv, DPIO_FASTCLK_DISABLE, 0x641); /* ??? */
+}
+
 static void i9xx_update_pll(struct drm_crtc *crtc,
                            struct drm_display_mode *mode,
                            struct drm_display_mode *adjusted_mode,
@@ -4044,6 +4283,9 @@ static int i9xx_crtc_mode_set(struct drm_crtc *crtc,
 
        if (IS_GEN2(dev))
                i8xx_update_pll(crtc, adjusted_mode, &clock, num_connectors);
+       else if (IS_VALLEYVIEW(dev))
+               vlv_update_pll(crtc, mode,adjusted_mode, &clock, NULL,
+                              refclk, num_connectors);
        else
                i9xx_update_pll(crtc, mode, adjusted_mode, &clock,
                                has_reduced_clock ? &reduced_clock : NULL,
@@ -4405,25 +4647,10 @@ static int ironlake_crtc_mode_set(struct drm_crtc *crtc,
                                                    &clock,
                                                    &reduced_clock);
        }
-       /* SDVO TV has fixed PLL values depend on its clock range,
-          this mirrors vbios setting. */
-       if (is_sdvo && is_tv) {
-               if (adjusted_mode->clock >= 100000
-                   && adjusted_mode->clock < 140500) {
-                       clock.p1 = 2;
-                       clock.p2 = 10;
-                       clock.n = 3;
-                       clock.m1 = 16;
-                       clock.m2 = 8;
-               } else if (adjusted_mode->clock >= 140500
-                          && adjusted_mode->clock <= 200000) {
-                       clock.p1 = 1;
-                       clock.p2 = 10;
-                       clock.n = 6;
-                       clock.m1 = 12;
-                       clock.m2 = 8;
-               }
-       }
+
+       if (is_sdvo && is_tv)
+               i9xx_adjust_sdvo_tv_clock(adjusted_mode, &clock);
+
 
        /* FDI link */
        pixel_multiplier = intel_mode_get_pixel_multiplier(adjusted_mode);
@@ -4431,16 +4658,8 @@ static int ironlake_crtc_mode_set(struct drm_crtc *crtc,
        /* CPU eDP doesn't require FDI link, so just set DP M/N
           according to current link config */
        if (is_cpu_edp) {
-               target_clock = mode->clock;
                intel_edp_link_config(edp_encoder, &lane, &link_bw);
        } else {
-               /* [e]DP over FDI requires target mode clock
-                  instead of link clock */
-               if (is_dp)
-                       target_clock = mode->clock;
-               else
-                       target_clock = adjusted_mode->clock;
-
                /* FDI is a binary signal running at ~2.7GHz, encoding
                 * each output octet as 10 bits. The actual frequency
                 * is stored as a divider into a 100MHz clock, and the
@@ -4451,6 +4670,14 @@ static int ironlake_crtc_mode_set(struct drm_crtc *crtc,
                link_bw = intel_fdi_link_freq(dev) * MHz(100)/KHz(1)/10;
        }
 
+       /* [e]DP over FDI requires target mode clock instead of link clock. */
+       if (edp_encoder)
+               target_clock = intel_edp_target_clock(edp_encoder, mode);
+       else if (is_dp)
+               target_clock = mode->clock;
+       else
+               target_clock = adjusted_mode->clock;
+
        /* determine panel color depth */
        temp = I915_READ(PIPECONF(pipe));
        temp &= ~PIPE_BPC_MASK;
@@ -4662,16 +4889,8 @@ static int ironlake_crtc_mode_set(struct drm_crtc *crtc,
                if (is_lvds && has_reduced_clock && i915_powersave) {
                        I915_WRITE(intel_crtc->pch_pll->fp1_reg, fp2);
                        intel_crtc->lowfreq_avail = true;
-                       if (HAS_PIPE_CXSR(dev)) {
-                               DRM_DEBUG_KMS("enabling CxSR downclocking\n");
-                               pipeconf |= PIPECONF_CXSR_DOWNCLOCK;
-                       }
                } else {
                        I915_WRITE(intel_crtc->pch_pll->fp1_reg, fp);
-                       if (HAS_PIPE_CXSR(dev)) {
-                               DRM_DEBUG_KMS("disabling CxSR downclocking\n");
-                               pipeconf &= ~PIPECONF_CXSR_DOWNCLOCK;
-                       }
                }
        }
 
@@ -6566,7 +6785,24 @@ static void intel_setup_outputs(struct drm_device *dev)
 
                if (!dpd_is_edp && (I915_READ(PCH_DP_D) & DP_DETECTED))
                        intel_dp_init(dev, PCH_DP_D);
+       } else if (IS_VALLEYVIEW(dev)) {
+               int found;
+
+               if (I915_READ(SDVOB) & PORT_DETECTED) {
+                       /* SDVOB multiplex with HDMIB */
+                       found = intel_sdvo_init(dev, SDVOB, true);
+                       if (!found)
+                               intel_hdmi_init(dev, SDVOB);
+                       if (!found && (I915_READ(DP_B) & DP_DETECTED))
+                               intel_dp_init(dev, DP_B);
+               }
+
+               if (I915_READ(SDVOC) & PORT_DETECTED)
+                       intel_hdmi_init(dev, SDVOC);
 
+               /* Shares lanes with HDMI on SDVOC */
+               if (I915_READ(DP_C) & DP_DETECTED)
+                       intel_dp_init(dev, DP_C);
        } else if (SUPPORTS_DIGITAL_OUTPUTS(dev)) {
                bool found = false;
 
@@ -6929,9 +7165,9 @@ static void ivb_pch_pwm_override(struct drm_device *dev)
         * IVB has CPU eDP backlight regs too, set things up to let the
         * PCH regs control the backlight
         */
-       I915_WRITE(BLC_PWM_CPU_CTL2, PWM_ENABLE);
+       I915_WRITE(BLC_PWM_CPU_CTL2, BLM_PWM_ENABLE);
        I915_WRITE(BLC_PWM_CPU_CTL, 0);
-       I915_WRITE(BLC_PWM_PCH_CTL1, PWM_ENABLE | (1<<30));
+       I915_WRITE(BLC_PWM_PCH_CTL1, BLM_PCH_PWM_ENABLE | BLM_PCH_OVERRIDE_ENABLE);
 }
 
 void intel_modeset_init_hw(struct drm_device *dev)
@@ -6988,7 +7224,7 @@ void intel_modeset_init(struct drm_device *dev)
                dev->mode_config.max_width = 8192;
                dev->mode_config.max_height = 8192;
        }
-       dev->mode_config.fb_base = dev->agp->base;
+       dev->mode_config.fb_base = dev_priv->mm.gtt_base_addr;
 
        DRM_DEBUG_KMS("%d display pipe%s available.\n",
                      dev_priv->num_pipe, dev_priv->num_pipe > 1 ? "s" : "");
index c044932..76a7080 100644 (file)
@@ -155,6 +155,18 @@ intel_edp_link_config(struct intel_encoder *intel_encoder,
                *link_bw = 270000;
 }
 
+int
+intel_edp_target_clock(struct intel_encoder *intel_encoder,
+                      struct drm_display_mode *mode)
+{
+       struct intel_dp *intel_dp = container_of(intel_encoder, struct intel_dp, base);
+
+       if (intel_dp->panel_fixed_mode)
+               return intel_dp->panel_fixed_mode->clock;
+       else
+               return mode->clock;
+}
+
 static int
 intel_dp_max_lane_count(struct intel_dp *intel_dp)
 {
@@ -225,7 +237,7 @@ intel_dp_max_data_rate(int max_link_clock, int max_lanes)
 static bool
 intel_dp_adjust_dithering(struct intel_dp *intel_dp,
                          struct drm_display_mode *mode,
-                         struct drm_display_mode *adjusted_mode)
+                         bool adjust_mode)
 {
        int max_link_clock = intel_dp_link_clock(intel_dp_max_link_bw(intel_dp));
        int max_lanes = intel_dp_max_lane_count(intel_dp);
@@ -239,8 +251,8 @@ intel_dp_adjust_dithering(struct intel_dp *intel_dp,
                if (mode_rate > max_rate)
                        return false;
 
-               if (adjusted_mode)
-                       adjusted_mode->private_flags
+               if (adjust_mode)
+                       mode->private_flags
                                |= INTEL_MODE_DP_FORCE_6BPC;
 
                return true;
@@ -263,7 +275,7 @@ intel_dp_mode_valid(struct drm_connector *connector,
                        return MODE_PANEL;
        }
 
-       if (!intel_dp_adjust_dithering(intel_dp, mode, NULL))
+       if (!intel_dp_adjust_dithering(intel_dp, mode, false))
                return MODE_CLOCK_HIGH;
 
        if (mode->clock < 10000)
@@ -706,25 +718,20 @@ intel_dp_mode_fixup(struct drm_encoder *encoder, struct drm_display_mode *mode,
                intel_fixed_panel_mode(intel_dp->panel_fixed_mode, adjusted_mode);
                intel_pch_panel_fitting(dev, DRM_MODE_SCALE_FULLSCREEN,
                                        mode, adjusted_mode);
-               /*
-                * the mode->clock is used to calculate the Data&Link M/N
-                * of the pipe. For the eDP the fixed clock should be used.
-                */
-               mode->clock = intel_dp->panel_fixed_mode->clock;
        }
 
-       if (mode->flags & DRM_MODE_FLAG_DBLCLK)
+       if (adjusted_mode->flags & DRM_MODE_FLAG_DBLCLK)
                return false;
 
        DRM_DEBUG_KMS("DP link computation with max lane count %i "
                      "max bw %02x pixel clock %iKHz\n",
-                     max_lane_count, bws[max_clock], mode->clock);
+                     max_lane_count, bws[max_clock], adjusted_mode->clock);
 
-       if (!intel_dp_adjust_dithering(intel_dp, mode, adjusted_mode))
+       if (!intel_dp_adjust_dithering(intel_dp, adjusted_mode, true))
                return false;
 
        bpp = adjusted_mode->private_flags & INTEL_MODE_DP_FORCE_6BPC ? 18 : 24;
-       mode_rate = intel_dp_link_required(mode->clock, bpp);
+       mode_rate = intel_dp_link_required(adjusted_mode->clock, bpp);
 
        for (lane_count = 1; lane_count <= max_lane_count; lane_count <<= 1) {
                for (clock = 0; clock <= max_clock; clock++) {
@@ -1922,7 +1929,7 @@ intel_dp_link_down(struct intel_dp *intel_dp)
                        DP |= DP_LINK_TRAIN_OFF;
        }
 
-       if (!HAS_PCH_CPT(dev) &&
+       if (HAS_PCH_IBX(dev) &&
            I915_READ(intel_dp->output_reg) & DP_PIPEB_SELECT) {
                struct drm_crtc *crtc = intel_dp->base.base.crtc;
 
@@ -2099,25 +2106,23 @@ g4x_dp_detect(struct intel_dp *intel_dp)
 {
        struct drm_device *dev = intel_dp->base.base.dev;
        struct drm_i915_private *dev_priv = dev->dev_private;
-       uint32_t temp, bit;
+       uint32_t bit;
 
        switch (intel_dp->output_reg) {
        case DP_B:
-               bit = DPB_HOTPLUG_INT_STATUS;
+               bit = DPB_HOTPLUG_LIVE_STATUS;
                break;
        case DP_C:
-               bit = DPC_HOTPLUG_INT_STATUS;
+               bit = DPC_HOTPLUG_LIVE_STATUS;
                break;
        case DP_D:
-               bit = DPD_HOTPLUG_INT_STATUS;
+               bit = DPD_HOTPLUG_LIVE_STATUS;
                break;
        default:
                return connector_status_unknown;
        }
 
-       temp = I915_READ(PORT_HOTPLUG_STAT);
-
-       if ((temp & bit) == 0)
+       if ((I915_READ(PORT_HOTPLUG_STAT) & bit) == 0)
                return connector_status_disconnected;
 
        return intel_dp_detect_dpcd(intel_dp);
@@ -2520,19 +2525,19 @@ intel_dp_init(struct drm_device *dev, int output_reg)
                case DP_B:
                case PCH_DP_B:
                        dev_priv->hotplug_supported_mask |=
-                               HDMIB_HOTPLUG_INT_STATUS;
+                               DPB_HOTPLUG_INT_STATUS;
                        name = "DPDDC-B";
                        break;
                case DP_C:
                case PCH_DP_C:
                        dev_priv->hotplug_supported_mask |=
-                               HDMIC_HOTPLUG_INT_STATUS;
+                               DPC_HOTPLUG_INT_STATUS;
                        name = "DPDDC-C";
                        break;
                case DP_D:
                case PCH_DP_D:
                        dev_priv->hotplug_supported_mask |=
-                               HDMID_HOTPLUG_INT_STATUS;
+                               DPD_HOTPLUG_INT_STATUS;
                        name = "DPDDC-D";
                        break;
        }
index 3e09188..5290e9d 100644 (file)
@@ -169,6 +169,7 @@ struct intel_crtc {
        u8 lut_r[256], lut_g[256], lut_b[256];
        int dpms_mode;
        bool active; /* is the crtc on? independent of the dpms mode */
+       bool primary_disabled; /* is the crtc obscured by a plane? */
        bool busy; /* is scanout buffer being updated frequently? */
        struct timer_list idle_timer;
        bool lowfreq_avail;
@@ -191,7 +192,6 @@ struct intel_plane {
        struct drm_plane base;
        enum pipe pipe;
        struct drm_i915_gem_object *obj;
-       bool primary_disabled;
        int max_downscale;
        u32 lut_r[1024], lut_g[1024], lut_b[1024];
        void (*update_plane)(struct drm_plane *plane,
@@ -301,6 +301,8 @@ struct intel_hdmi {
        enum hdmi_force_audio force_audio;
        void (*write_infoframe)(struct drm_encoder *encoder,
                                struct dip_infoframe *frame);
+       void (*set_infoframes)(struct drm_encoder *encoder,
+                              struct drm_display_mode *adjusted_mode);
 };
 
 static inline struct drm_crtc *
@@ -343,9 +345,6 @@ extern void intel_attach_broadcast_rgb_property(struct drm_connector *connector)
 extern void intel_crt_init(struct drm_device *dev);
 extern void intel_hdmi_init(struct drm_device *dev, int sdvox_reg);
 extern struct intel_hdmi *enc_to_intel_hdmi(struct drm_encoder *encoder);
-extern void intel_hdmi_set_avi_infoframe(struct drm_encoder *encoder,
-                           struct drm_display_mode *adjusted_mode);
-extern void intel_hdmi_set_spd_infoframe(struct drm_encoder *encoder);
 extern void intel_dip_infoframe_csum(struct dip_infoframe *avi_if);
 extern bool intel_sdvo_init(struct drm_device *dev, uint32_t sdvo_reg,
                            bool is_sdvob);
@@ -360,6 +359,8 @@ intel_dp_set_m_n(struct drm_crtc *crtc, struct drm_display_mode *mode,
                 struct drm_display_mode *adjusted_mode);
 extern bool intel_dpd_is_edp(struct drm_device *dev);
 extern void intel_edp_link_config(struct intel_encoder *, int *, int *);
+extern int intel_edp_target_clock(struct intel_encoder *,
+                                 struct drm_display_mode *mode);
 extern bool intel_encoder_is_pch_edp(struct drm_encoder *encoder);
 extern int intel_plane_init(struct drm_device *dev, enum pipe pipe);
 extern void intel_flush_display_plane(struct drm_i915_private *dev_priv,
@@ -372,13 +373,14 @@ extern void intel_fixed_panel_mode(struct drm_display_mode *fixed_mode,
                                   struct drm_display_mode *adjusted_mode);
 extern void intel_pch_panel_fitting(struct drm_device *dev,
                                    int fitting_mode,
-                                   struct drm_display_mode *mode,
+                                   const struct drm_display_mode *mode,
                                    struct drm_display_mode *adjusted_mode);
 extern u32 intel_panel_get_max_backlight(struct drm_device *dev);
 extern u32 intel_panel_get_backlight(struct drm_device *dev);
 extern void intel_panel_set_backlight(struct drm_device *dev, u32 level);
 extern int intel_panel_setup_backlight(struct drm_device *dev);
-extern void intel_panel_enable_backlight(struct drm_device *dev);
+extern void intel_panel_enable_backlight(struct drm_device *dev,
+                                        enum pipe pipe);
 extern void intel_panel_disable_backlight(struct drm_device *dev);
 extern void intel_panel_destroy_backlight(struct drm_device *dev);
 extern enum drm_connector_status intel_panel_detect(struct drm_device *dev);
index bf86907..e9f8338 100644 (file)
@@ -140,7 +140,9 @@ static int intelfb_create(struct intel_fbdev *ifbdev,
        info->fix.smem_start = dev->mode_config.fb_base + obj->gtt_offset;
        info->fix.smem_len = size;
 
-       info->screen_base = ioremap_wc(dev->agp->base + obj->gtt_offset, size);
+       info->screen_base =
+               ioremap_wc(dev_priv->mm.gtt_base_addr + obj->gtt_offset,
+                          size);
        if (!info->screen_base) {
                ret = -ENOSPC;
                goto out_unpin;
index 2ead3bf..5b2c88c 100644 (file)
 #include "i915_drm.h"
 #include "i915_drv.h"
 
+static void
+assert_hdmi_port_disabled(struct intel_hdmi *intel_hdmi)
+{
+       struct drm_device *dev = intel_hdmi->base.base.dev;
+       struct drm_i915_private *dev_priv = dev->dev_private;
+       uint32_t enabled_bits;
+
+       enabled_bits = IS_HASWELL(dev) ? DDI_BUF_CTL_ENABLE : SDVO_ENABLE;
+
+       WARN(I915_READ(intel_hdmi->sdvox_reg) & enabled_bits,
+            "HDMI port enabled, expecting disabled\n");
+}
+
 struct intel_hdmi *enc_to_intel_hdmi(struct drm_encoder *encoder)
 {
        return container_of(encoder, struct intel_hdmi, base.base);
@@ -121,36 +134,31 @@ static void g4x_write_infoframe(struct drm_encoder *encoder,
        uint32_t *data = (uint32_t *)frame;
        struct drm_device *dev = encoder->dev;
        struct drm_i915_private *dev_priv = dev->dev_private;
-       struct intel_hdmi *intel_hdmi = enc_to_intel_hdmi(encoder);
        u32 val = I915_READ(VIDEO_DIP_CTL);
        unsigned i, len = DIP_HEADER_SIZE + frame->len;
 
-       val &= ~VIDEO_DIP_PORT_MASK;
-       if (intel_hdmi->sdvox_reg == SDVOB)
-               val |= VIDEO_DIP_PORT_B;
-       else if (intel_hdmi->sdvox_reg == SDVOC)
-               val |= VIDEO_DIP_PORT_C;
-       else
-               return;
+       WARN(!(val & VIDEO_DIP_ENABLE), "Writing DIP with CTL reg disabled\n");
 
        val &= ~(VIDEO_DIP_SELECT_MASK | 0xf); /* clear DIP data offset */
        val |= g4x_infoframe_index(frame);
 
        val &= ~g4x_infoframe_enable(frame);
-       val |= VIDEO_DIP_ENABLE;
 
        I915_WRITE(VIDEO_DIP_CTL, val);
 
+       mmiowb();
        for (i = 0; i < len; i += 4) {
                I915_WRITE(VIDEO_DIP_DATA, *data);
                data++;
        }
+       mmiowb();
 
        val |= g4x_infoframe_enable(frame);
        val &= ~VIDEO_DIP_FREQ_MASK;
        val |= VIDEO_DIP_FREQ_VSYNC;
 
        I915_WRITE(VIDEO_DIP_CTL, val);
+       POSTING_READ(VIDEO_DIP_CTL);
 }
 
 static void ibx_write_infoframe(struct drm_encoder *encoder,
@@ -160,46 +168,32 @@ static void ibx_write_infoframe(struct drm_encoder *encoder,
        struct drm_device *dev = encoder->dev;
        struct drm_i915_private *dev_priv = dev->dev_private;
        struct intel_crtc *intel_crtc = to_intel_crtc(encoder->crtc);
-       struct intel_hdmi *intel_hdmi = enc_to_intel_hdmi(encoder);
        int reg = TVIDEO_DIP_CTL(intel_crtc->pipe);
        unsigned i, len = DIP_HEADER_SIZE + frame->len;
        u32 val = I915_READ(reg);
 
-       val &= ~VIDEO_DIP_PORT_MASK;
-       switch (intel_hdmi->sdvox_reg) {
-       case HDMIB:
-               val |= VIDEO_DIP_PORT_B;
-               break;
-       case HDMIC:
-               val |= VIDEO_DIP_PORT_C;
-               break;
-       case HDMID:
-               val |= VIDEO_DIP_PORT_D;
-               break;
-       default:
-               return;
-       }
-
-       intel_wait_for_vblank(dev, intel_crtc->pipe);
+       WARN(!(val & VIDEO_DIP_ENABLE), "Writing DIP with CTL reg disabled\n");
 
        val &= ~(VIDEO_DIP_SELECT_MASK | 0xf); /* clear DIP data offset */
        val |= g4x_infoframe_index(frame);
 
        val &= ~g4x_infoframe_enable(frame);
-       val |= VIDEO_DIP_ENABLE;
 
        I915_WRITE(reg, val);
 
+       mmiowb();
        for (i = 0; i < len; i += 4) {
                I915_WRITE(TVIDEO_DIP_DATA(intel_crtc->pipe), *data);
                data++;
        }
+       mmiowb();
 
        val |= g4x_infoframe_enable(frame);
        val &= ~VIDEO_DIP_FREQ_MASK;
        val |= VIDEO_DIP_FREQ_VSYNC;
 
        I915_WRITE(reg, val);
+       POSTING_READ(reg);
 }
 
 static void cpt_write_infoframe(struct drm_encoder *encoder,
@@ -213,32 +207,31 @@ static void cpt_write_infoframe(struct drm_encoder *encoder,
        unsigned i, len = DIP_HEADER_SIZE + frame->len;
        u32 val = I915_READ(reg);
 
-       intel_wait_for_vblank(dev, intel_crtc->pipe);
+       WARN(!(val & VIDEO_DIP_ENABLE), "Writing DIP with CTL reg disabled\n");
 
        val &= ~(VIDEO_DIP_SELECT_MASK | 0xf); /* clear DIP data offset */
        val |= g4x_infoframe_index(frame);
 
        /* The DIP control register spec says that we need to update the AVI
         * infoframe without clearing its enable bit */
-       if (frame->type == DIP_TYPE_AVI)
-               val |= VIDEO_DIP_ENABLE_AVI;
-       else
+       if (frame->type != DIP_TYPE_AVI)
                val &= ~g4x_infoframe_enable(frame);
 
-       val |= VIDEO_DIP_ENABLE;
-
        I915_WRITE(reg, val);
 
+       mmiowb();
        for (i = 0; i < len; i += 4) {
                I915_WRITE(TVIDEO_DIP_DATA(intel_crtc->pipe), *data);
                data++;
        }
+       mmiowb();
 
        val |= g4x_infoframe_enable(frame);
        val &= ~VIDEO_DIP_FREQ_MASK;
        val |= VIDEO_DIP_FREQ_VSYNC;
 
        I915_WRITE(reg, val);
+       POSTING_READ(reg);
 }
 
 static void vlv_write_infoframe(struct drm_encoder *encoder,
@@ -252,26 +245,28 @@ static void vlv_write_infoframe(struct drm_encoder *encoder,
        unsigned i, len = DIP_HEADER_SIZE + frame->len;
        u32 val = I915_READ(reg);
 
-       intel_wait_for_vblank(dev, intel_crtc->pipe);
+       WARN(!(val & VIDEO_DIP_ENABLE), "Writing DIP with CTL reg disabled\n");
 
        val &= ~(VIDEO_DIP_SELECT_MASK | 0xf); /* clear DIP data offset */
        val |= g4x_infoframe_index(frame);
 
        val &= ~g4x_infoframe_enable(frame);
-       val |= VIDEO_DIP_ENABLE;
 
        I915_WRITE(reg, val);
 
+       mmiowb();
        for (i = 0; i < len; i += 4) {
                I915_WRITE(VLV_TVIDEO_DIP_DATA(intel_crtc->pipe), *data);
                data++;
        }
+       mmiowb();
 
        val |= g4x_infoframe_enable(frame);
        val &= ~VIDEO_DIP_FREQ_MASK;
        val |= VIDEO_DIP_FREQ_VSYNC;
 
        I915_WRITE(reg, val);
+       POSTING_READ(reg);
 }
 
 static void hsw_write_infoframe(struct drm_encoder *encoder,
@@ -289,18 +284,19 @@ static void hsw_write_infoframe(struct drm_encoder *encoder,
        if (data_reg == 0)
                return;
 
-       intel_wait_for_vblank(dev, intel_crtc->pipe);
-
        val &= ~hsw_infoframe_enable(frame);
        I915_WRITE(ctl_reg, val);
 
+       mmiowb();
        for (i = 0; i < len; i += 4) {
                I915_WRITE(data_reg + i, *data);
                data++;
        }
+       mmiowb();
 
        val |= hsw_infoframe_enable(frame);
        I915_WRITE(ctl_reg, val);
+       POSTING_READ(ctl_reg);
 }
 
 static void intel_set_infoframe(struct drm_encoder *encoder,
@@ -308,14 +304,11 @@ static void intel_set_infoframe(struct drm_encoder *encoder,
 {
        struct intel_hdmi *intel_hdmi = enc_to_intel_hdmi(encoder);
 
-       if (!intel_hdmi->has_hdmi_sink)
-               return;
-
        intel_dip_infoframe_csum(frame);
        intel_hdmi->write_infoframe(encoder, frame);
 }
 
-void intel_hdmi_set_avi_infoframe(struct drm_encoder *encoder,
+static void intel_hdmi_set_avi_infoframe(struct drm_encoder *encoder,
                                         struct drm_display_mode *adjusted_mode)
 {
        struct dip_infoframe avi_if = {
@@ -330,7 +323,7 @@ void intel_hdmi_set_avi_infoframe(struct drm_encoder *encoder,
        intel_set_infoframe(encoder, &avi_if);
 }
 
-void intel_hdmi_set_spd_infoframe(struct drm_encoder *encoder)
+static void intel_hdmi_set_spd_infoframe(struct drm_encoder *encoder)
 {
        struct dip_infoframe spd_if;
 
@@ -345,6 +338,223 @@ void intel_hdmi_set_spd_infoframe(struct drm_encoder *encoder)
        intel_set_infoframe(encoder, &spd_if);
 }
 
+static void g4x_set_infoframes(struct drm_encoder *encoder,
+                              struct drm_display_mode *adjusted_mode)
+{
+       struct drm_i915_private *dev_priv = encoder->dev->dev_private;
+       struct intel_hdmi *intel_hdmi = enc_to_intel_hdmi(encoder);
+       u32 reg = VIDEO_DIP_CTL;
+       u32 val = I915_READ(reg);
+       u32 port;
+
+       assert_hdmi_port_disabled(intel_hdmi);
+
+       /* If the registers were not initialized yet, they might be zeroes,
+        * which means we're selecting the AVI DIP and we're setting its
+        * frequency to once. This seems to really confuse the HW and make
+        * things stop working (the register spec says the AVI always needs to
+        * be sent every VSync). So here we avoid writing to the register more
+        * than we need and also explicitly select the AVI DIP and explicitly
+        * set its frequency to every VSync. Avoiding to write it twice seems to
+        * be enough to solve the problem, but being defensive shouldn't hurt us
+        * either. */
+       val |= VIDEO_DIP_SELECT_AVI | VIDEO_DIP_FREQ_VSYNC;
+
+       if (!intel_hdmi->has_hdmi_sink) {
+               if (!(val & VIDEO_DIP_ENABLE))
+                       return;
+               val &= ~VIDEO_DIP_ENABLE;
+               I915_WRITE(reg, val);
+               POSTING_READ(reg);
+               return;
+       }
+
+       switch (intel_hdmi->sdvox_reg) {
+       case SDVOB:
+               port = VIDEO_DIP_PORT_B;
+               break;
+       case SDVOC:
+               port = VIDEO_DIP_PORT_C;
+               break;
+       default:
+               return;
+       }
+
+       if (port != (val & VIDEO_DIP_PORT_MASK)) {
+               if (val & VIDEO_DIP_ENABLE) {
+                       val &= ~VIDEO_DIP_ENABLE;
+                       I915_WRITE(reg, val);
+                       POSTING_READ(reg);
+               }
+               val &= ~VIDEO_DIP_PORT_MASK;
+               val |= port;
+       }
+
+       val |= VIDEO_DIP_ENABLE;
+       val &= ~VIDEO_DIP_ENABLE_VENDOR;
+
+       I915_WRITE(reg, val);
+       POSTING_READ(reg);
+
+       intel_hdmi_set_avi_infoframe(encoder, adjusted_mode);
+       intel_hdmi_set_spd_infoframe(encoder);
+}
+
+static void ibx_set_infoframes(struct drm_encoder *encoder,
+                              struct drm_display_mode *adjusted_mode)
+{
+       struct drm_i915_private *dev_priv = encoder->dev->dev_private;
+       struct intel_crtc *intel_crtc = to_intel_crtc(encoder->crtc);
+       struct intel_hdmi *intel_hdmi = enc_to_intel_hdmi(encoder);
+       u32 reg = TVIDEO_DIP_CTL(intel_crtc->pipe);
+       u32 val = I915_READ(reg);
+       u32 port;
+
+       assert_hdmi_port_disabled(intel_hdmi);
+
+       /* See the big comment in g4x_set_infoframes() */
+       val |= VIDEO_DIP_SELECT_AVI | VIDEO_DIP_FREQ_VSYNC;
+
+       if (!intel_hdmi->has_hdmi_sink) {
+               if (!(val & VIDEO_DIP_ENABLE))
+                       return;
+               val &= ~VIDEO_DIP_ENABLE;
+               I915_WRITE(reg, val);
+               POSTING_READ(reg);
+               return;
+       }
+
+       switch (intel_hdmi->sdvox_reg) {
+       case HDMIB:
+               port = VIDEO_DIP_PORT_B;
+               break;
+       case HDMIC:
+               port = VIDEO_DIP_PORT_C;
+               break;
+       case HDMID:
+               port = VIDEO_DIP_PORT_D;
+               break;
+       default:
+               return;
+       }
+
+       if (port != (val & VIDEO_DIP_PORT_MASK)) {
+               if (val & VIDEO_DIP_ENABLE) {
+                       val &= ~VIDEO_DIP_ENABLE;
+                       I915_WRITE(reg, val);
+                       POSTING_READ(reg);
+               }
+               val &= ~VIDEO_DIP_PORT_MASK;
+               val |= port;
+       }
+
+       val |= VIDEO_DIP_ENABLE;
+       val &= ~(VIDEO_DIP_ENABLE_VENDOR | VIDEO_DIP_ENABLE_GAMUT |
+                VIDEO_DIP_ENABLE_GCP);
+
+       I915_WRITE(reg, val);
+       POSTING_READ(reg);
+
+       intel_hdmi_set_avi_infoframe(encoder, adjusted_mode);
+       intel_hdmi_set_spd_infoframe(encoder);
+}
+
+static void cpt_set_infoframes(struct drm_encoder *encoder,
+                              struct drm_display_mode *adjusted_mode)
+{
+       struct drm_i915_private *dev_priv = encoder->dev->dev_private;
+       struct intel_crtc *intel_crtc = to_intel_crtc(encoder->crtc);
+       struct intel_hdmi *intel_hdmi = enc_to_intel_hdmi(encoder);
+       u32 reg = TVIDEO_DIP_CTL(intel_crtc->pipe);
+       u32 val = I915_READ(reg);
+
+       assert_hdmi_port_disabled(intel_hdmi);
+
+       /* See the big comment in g4x_set_infoframes() */
+       val |= VIDEO_DIP_SELECT_AVI | VIDEO_DIP_FREQ_VSYNC;
+
+       if (!intel_hdmi->has_hdmi_sink) {
+               if (!(val & VIDEO_DIP_ENABLE))
+                       return;
+               val &= ~(VIDEO_DIP_ENABLE | VIDEO_DIP_ENABLE_AVI);
+               I915_WRITE(reg, val);
+               POSTING_READ(reg);
+               return;
+       }
+
+       /* Set both together, unset both together: see the spec. */
+       val |= VIDEO_DIP_ENABLE | VIDEO_DIP_ENABLE_AVI;
+       val &= ~(VIDEO_DIP_ENABLE_VENDOR | VIDEO_DIP_ENABLE_GAMUT |
+                VIDEO_DIP_ENABLE_GCP);
+
+       I915_WRITE(reg, val);
+       POSTING_READ(reg);
+
+       intel_hdmi_set_avi_infoframe(encoder, adjusted_mode);
+       intel_hdmi_set_spd_infoframe(encoder);
+}
+
+static void vlv_set_infoframes(struct drm_encoder *encoder,
+                              struct drm_display_mode *adjusted_mode)
+{
+       struct drm_i915_private *dev_priv = encoder->dev->dev_private;
+       struct intel_crtc *intel_crtc = to_intel_crtc(encoder->crtc);
+       struct intel_hdmi *intel_hdmi = enc_to_intel_hdmi(encoder);
+       u32 reg = VLV_TVIDEO_DIP_CTL(intel_crtc->pipe);
+       u32 val = I915_READ(reg);
+
+       assert_hdmi_port_disabled(intel_hdmi);
+
+       /* See the big comment in g4x_set_infoframes() */
+       val |= VIDEO_DIP_SELECT_AVI | VIDEO_DIP_FREQ_VSYNC;
+
+       if (!intel_hdmi->has_hdmi_sink) {
+               if (!(val & VIDEO_DIP_ENABLE))
+                       return;
+               val &= ~VIDEO_DIP_ENABLE;
+               I915_WRITE(reg, val);
+               POSTING_READ(reg);
+               return;
+       }
+
+       val |= VIDEO_DIP_ENABLE;
+       val &= ~(VIDEO_DIP_ENABLE_VENDOR | VIDEO_DIP_ENABLE_GAMUT |
+                VIDEO_DIP_ENABLE_GCP);
+
+       I915_WRITE(reg, val);
+       POSTING_READ(reg);
+
+       intel_hdmi_set_avi_infoframe(encoder, adjusted_mode);
+       intel_hdmi_set_spd_infoframe(encoder);
+}
+
+static void hsw_set_infoframes(struct drm_encoder *encoder,
+                              struct drm_display_mode *adjusted_mode)
+{
+       struct drm_i915_private *dev_priv = encoder->dev->dev_private;
+       struct intel_crtc *intel_crtc = to_intel_crtc(encoder->crtc);
+       struct intel_hdmi *intel_hdmi = enc_to_intel_hdmi(encoder);
+       u32 reg = HSW_TVIDEO_DIP_CTL(intel_crtc->pipe);
+       u32 val = I915_READ(reg);
+
+       assert_hdmi_port_disabled(intel_hdmi);
+
+       if (!intel_hdmi->has_hdmi_sink) {
+               I915_WRITE(reg, 0);
+               POSTING_READ(reg);
+               return;
+       }
+
+       val &= ~(VIDEO_DIP_ENABLE_VSC_HSW | VIDEO_DIP_ENABLE_GCP_HSW |
+                VIDEO_DIP_ENABLE_VS_HSW | VIDEO_DIP_ENABLE_GMP_HSW);
+
+       I915_WRITE(reg, val);
+       POSTING_READ(reg);
+
+       intel_hdmi_set_avi_infoframe(encoder, adjusted_mode);
+       intel_hdmi_set_spd_infoframe(encoder);
+}
+
 static void intel_hdmi_mode_set(struct drm_encoder *encoder,
                                struct drm_display_mode *mode,
                                struct drm_display_mode *adjusted_mode)
@@ -355,7 +565,7 @@ static void intel_hdmi_mode_set(struct drm_encoder *encoder,
        struct intel_hdmi *intel_hdmi = enc_to_intel_hdmi(encoder);
        u32 sdvox;
 
-       sdvox = SDVO_ENCODING_HDMI | SDVO_BORDER_ENABLE;
+       sdvox = SDVO_ENCODING_HDMI;
        if (!HAS_PCH_SPLIT(dev))
                sdvox |= intel_hdmi->color_range;
        if (adjusted_mode->flags & DRM_MODE_FLAG_PVSYNC)
@@ -382,14 +592,13 @@ static void intel_hdmi_mode_set(struct drm_encoder *encoder,
 
        if (HAS_PCH_CPT(dev))
                sdvox |= PORT_TRANS_SEL_CPT(intel_crtc->pipe);
-       else if (intel_crtc->pipe == 1)
+       else if (intel_crtc->pipe == PIPE_B)
                sdvox |= SDVO_PIPE_B_SELECT;
 
        I915_WRITE(intel_hdmi->sdvox_reg, sdvox);
        POSTING_READ(intel_hdmi->sdvox_reg);
 
-       intel_hdmi_set_avi_infoframe(encoder, adjusted_mode);
-       intel_hdmi_set_spd_infoframe(encoder);
+       intel_hdmi->set_infoframes(encoder, adjusted_mode);
 }
 
 static void intel_hdmi_dpms(struct drm_encoder *encoder, int mode)
@@ -405,6 +614,36 @@ static void intel_hdmi_dpms(struct drm_encoder *encoder, int mode)
 
        temp = I915_READ(intel_hdmi->sdvox_reg);
 
+       /* HW workaround for IBX, we need to move the port to transcoder A
+        * before disabling it. */
+       if (HAS_PCH_IBX(dev)) {
+               struct drm_crtc *crtc = encoder->crtc;
+               int pipe = crtc ? to_intel_crtc(crtc)->pipe : -1;
+
+               if (mode != DRM_MODE_DPMS_ON) {
+                       if (temp & SDVO_PIPE_B_SELECT) {
+                               temp &= ~SDVO_PIPE_B_SELECT;
+                               I915_WRITE(intel_hdmi->sdvox_reg, temp);
+                               POSTING_READ(intel_hdmi->sdvox_reg);
+
+                               /* Again we need to write this twice. */
+                               I915_WRITE(intel_hdmi->sdvox_reg, temp);
+                               POSTING_READ(intel_hdmi->sdvox_reg);
+
+                               /* Transcoder selection bits only update
+                                * effectively on vblank. */
+                               if (crtc)
+                                       intel_wait_for_vblank(dev, pipe);
+                               else
+                                       msleep(50);
+                       }
+               } else {
+                       /* Restore the transcoder select bit. */
+                       if (pipe == PIPE_B)
+                               enable_bits |= SDVO_PIPE_B_SELECT;
+               }
+       }
+
        /* HW workaround, need to toggle enable bit off and on for 12bpc, but
         * we do this anyway which shows more stable in testing.
         */
@@ -452,6 +691,27 @@ static bool intel_hdmi_mode_fixup(struct drm_encoder *encoder,
        return true;
 }
 
+static bool g4x_hdmi_connected(struct intel_hdmi *intel_hdmi)
+{
+       struct drm_device *dev = intel_hdmi->base.base.dev;
+       struct drm_i915_private *dev_priv = dev->dev_private;
+       uint32_t bit;
+
+       switch (intel_hdmi->sdvox_reg) {
+       case SDVOB:
+               bit = HDMIB_HOTPLUG_LIVE_STATUS;
+               break;
+       case SDVOC:
+               bit = HDMIC_HOTPLUG_LIVE_STATUS;
+               break;
+       default:
+               bit = 0;
+               break;
+       }
+
+       return I915_READ(PORT_HOTPLUG_STAT) & bit;
+}
+
 static enum drm_connector_status
 intel_hdmi_detect(struct drm_connector *connector, bool force)
 {
@@ -460,6 +720,9 @@ intel_hdmi_detect(struct drm_connector *connector, bool force)
        struct edid *edid;
        enum drm_connector_status status = connector_status_disconnected;
 
+       if (IS_G4X(connector->dev) && !g4x_hdmi_connected(intel_hdmi))
+               return status;
+
        intel_hdmi->has_hdmi_sink = false;
        intel_hdmi->has_audio = false;
        edid = drm_get_edid(connector,
@@ -633,7 +896,6 @@ void intel_hdmi_init(struct drm_device *dev, int sdvox_reg)
        struct intel_encoder *intel_encoder;
        struct intel_connector *intel_connector;
        struct intel_hdmi *intel_hdmi;
-       int i;
 
        intel_hdmi = kzalloc(sizeof(struct intel_hdmi), GFP_KERNEL);
        if (!intel_hdmi)
@@ -710,26 +972,19 @@ void intel_hdmi_init(struct drm_device *dev, int sdvox_reg)
 
        if (!HAS_PCH_SPLIT(dev)) {
                intel_hdmi->write_infoframe = g4x_write_infoframe;
-               I915_WRITE(VIDEO_DIP_CTL, 0);
+               intel_hdmi->set_infoframes = g4x_set_infoframes;
        } else if (IS_VALLEYVIEW(dev)) {
                intel_hdmi->write_infoframe = vlv_write_infoframe;
-               for_each_pipe(i)
-                       I915_WRITE(VLV_TVIDEO_DIP_CTL(i), 0);
+               intel_hdmi->set_infoframes = vlv_set_infoframes;
        } else if (IS_HASWELL(dev)) {
-               /* FIXME: Haswell has a new set of DIP frame registers, but we are
-                * just doing the minimal required for HDMI to work at this stage.
-                */
                intel_hdmi->write_infoframe = hsw_write_infoframe;
-               for_each_pipe(i)
-                       I915_WRITE(HSW_TVIDEO_DIP_CTL(i), 0);
+               intel_hdmi->set_infoframes = hsw_set_infoframes;
        } else if (HAS_PCH_IBX(dev)) {
                intel_hdmi->write_infoframe = ibx_write_infoframe;
-               for_each_pipe(i)
-                       I915_WRITE(TVIDEO_DIP_CTL(i), 0);
+               intel_hdmi->set_infoframes = ibx_set_infoframes;
        } else {
                intel_hdmi->write_infoframe = cpt_write_infoframe;
-               for_each_pipe(i)
-                       I915_WRITE(TVIDEO_DIP_CTL(i), 0);
+               intel_hdmi->set_infoframes = cpt_set_infoframes;
        }
 
        if (IS_HASWELL(dev))
index 08eb04c..05fcadb 100644 (file)
@@ -71,6 +71,7 @@ static struct intel_lvds *intel_attached_lvds(struct drm_connector *connector)
 static void intel_lvds_enable(struct intel_lvds *intel_lvds)
 {
        struct drm_device *dev = intel_lvds->base.base.dev;
+       struct intel_crtc *intel_crtc = to_intel_crtc(intel_lvds->base.base.crtc);
        struct drm_i915_private *dev_priv = dev->dev_private;
        u32 ctl_reg, lvds_reg, stat_reg;
 
@@ -107,7 +108,7 @@ static void intel_lvds_enable(struct intel_lvds *intel_lvds)
        if (wait_for((I915_READ(stat_reg) & PP_ON) != 0, 1000))
                DRM_ERROR("timed out waiting for panel to power on\n");
 
-       intel_panel_enable_backlight(dev);
+       intel_panel_enable_backlight(dev, intel_crtc->pipe);
 }
 
 static void intel_lvds_disable(struct intel_lvds *intel_lvds)
@@ -777,6 +778,14 @@ static const struct dmi_system_id intel_no_lvds[] = {
                        DMI_MATCH(DMI_BOARD_NAME, "MS-7469"),
                },
        },
+       {
+               .callback = intel_no_lvds_dmi_callback,
+               .ident = "ZOTAC ZBOXSD-ID12/ID13",
+               .matches = {
+                       DMI_MATCH(DMI_BOARD_VENDOR, "ZOTAC"),
+                       DMI_MATCH(DMI_BOARD_NAME, "ZBOXSD-ID12/ID13"),
+               },
+       },
 
        { }     /* terminating entry */
 };
@@ -967,6 +976,8 @@ bool intel_lvds_init(struct drm_device *dev)
        intel_encoder->clone_mask = (1 << INTEL_LVDS_CLONE_BIT);
        if (HAS_PCH_SPLIT(dev))
                intel_encoder->crtc_mask = (1 << 0) | (1 << 1) | (1 << 2);
+       else if (IS_GEN4(dev))
+               intel_encoder->crtc_mask = (1 << 0) | (1 << 1);
        else
                intel_encoder->crtc_mask = (1 << 1);
 
@@ -1074,35 +1085,14 @@ bool intel_lvds_init(struct drm_device *dev)
                goto failed;
 
 out:
+       /*
+        * Unlock registers and just
+        * leave them unlocked
+        */
        if (HAS_PCH_SPLIT(dev)) {
-               u32 pwm;
-
-               pipe = (I915_READ(PCH_LVDS) & LVDS_PIPEB_SELECT) ? 1 : 0;
-
-               /* make sure PWM is enabled and locked to the LVDS pipe */
-               pwm = I915_READ(BLC_PWM_CPU_CTL2);
-               if (pipe == 0 && (pwm & PWM_PIPE_B))
-                       I915_WRITE(BLC_PWM_CPU_CTL2, pwm & ~PWM_ENABLE);
-               if (pipe)
-                       pwm |= PWM_PIPE_B;
-               else
-                       pwm &= ~PWM_PIPE_B;
-               I915_WRITE(BLC_PWM_CPU_CTL2, pwm | PWM_ENABLE);
-
-               pwm = I915_READ(BLC_PWM_PCH_CTL1);
-               pwm |= PWM_PCH_ENABLE;
-               I915_WRITE(BLC_PWM_PCH_CTL1, pwm);
-               /*
-                * Unlock registers and just
-                * leave them unlocked
-                */
                I915_WRITE(PCH_PP_CONTROL,
                           I915_READ(PCH_PP_CONTROL) | PANEL_UNLOCK_REGS);
        } else {
-               /*
-                * Unlock registers and just
-                * leave them unlocked
-                */
                I915_WRITE(PP_CONTROL,
                           I915_READ(PP_CONTROL) | PANEL_UNLOCK_REGS);
        }
index 458743d..830d0dd 100644 (file)
@@ -226,7 +226,7 @@ static int intel_overlay_do_wait_request(struct intel_overlay *overlay,
        }
        overlay->last_flip_req = request->seqno;
        overlay->flip_tail = tail;
-       ret = i915_wait_request(ring, overlay->last_flip_req);
+       ret = i915_wait_seqno(ring, overlay->last_flip_req);
        if (ret)
                return ret;
        i915_gem_retire_requests(dev);
@@ -452,7 +452,7 @@ static int intel_overlay_recover_from_interrupt(struct intel_overlay *overlay)
        if (overlay->last_flip_req == 0)
                return 0;
 
-       ret = i915_wait_request(ring, overlay->last_flip_req);
+       ret = i915_wait_seqno(ring, overlay->last_flip_req);
        if (ret)
                return ret;
        i915_gem_retire_requests(dev);
index 2a1625d..58c7ee7 100644 (file)
@@ -56,7 +56,7 @@ intel_fixed_panel_mode(struct drm_display_mode *fixed_mode,
 void
 intel_pch_panel_fitting(struct drm_device *dev,
                        int fitting_mode,
-                       struct drm_display_mode *mode,
+                       const struct drm_display_mode *mode,
                        struct drm_display_mode *adjusted_mode)
 {
        struct drm_i915_private *dev_priv = dev->dev_private;
@@ -287,9 +287,18 @@ void intel_panel_disable_backlight(struct drm_device *dev)
 
        dev_priv->backlight_enabled = false;
        intel_panel_actually_set_backlight(dev, 0);
+
+       if (INTEL_INFO(dev)->gen >= 4) {
+               uint32_t reg;
+
+               reg = HAS_PCH_SPLIT(dev) ? BLC_PWM_CPU_CTL2 : BLC_PWM_CTL2;
+
+               I915_WRITE(reg, I915_READ(reg) & ~BLM_PWM_ENABLE);
+       }
 }
 
-void intel_panel_enable_backlight(struct drm_device *dev)
+void intel_panel_enable_backlight(struct drm_device *dev,
+                                 enum pipe pipe)
 {
        struct drm_i915_private *dev_priv = dev->dev_private;
 
@@ -298,6 +307,33 @@ void intel_panel_enable_backlight(struct drm_device *dev)
 
        dev_priv->backlight_enabled = true;
        intel_panel_actually_set_backlight(dev, dev_priv->backlight_level);
+
+       if (INTEL_INFO(dev)->gen >= 4) {
+               uint32_t reg, tmp;
+
+               reg = HAS_PCH_SPLIT(dev) ? BLC_PWM_CPU_CTL2 : BLC_PWM_CTL2;
+
+
+               tmp = I915_READ(reg);
+
+               /* Note that this can also get called through dpms changes. And
+                * we don't track the backlight dpms state, hence check whether
+                * we have to do anything first. */
+               if (tmp & BLM_PWM_ENABLE)
+                       return;
+
+               if (dev_priv->num_pipe == 3)
+                       tmp &= ~BLM_PIPE_SELECT_IVB;
+               else
+                       tmp &= ~BLM_PIPE_SELECT;
+
+               tmp |= BLM_PIPE(pipe);
+               tmp &= ~BLM_PWM_ENABLE;
+
+               I915_WRITE(reg, tmp);
+               POSTING_READ(reg);
+               I915_WRITE(reg, tmp | BLM_PWM_ENABLE);
+       }
 }
 
 static void intel_panel_init_backlight(struct drm_device *dev)
index d0ce2a5..7504fbc 100644 (file)
@@ -405,7 +405,9 @@ void intel_update_fbc(struct drm_device *dev)
         *   - going to an unsupported config (interlace, pixel multiply, etc.)
         */
        list_for_each_entry(tmp_crtc, &dev->mode_config.crtc_list, head) {
-               if (tmp_crtc->enabled && tmp_crtc->fb) {
+               if (tmp_crtc->enabled &&
+                   !to_intel_crtc(tmp_crtc)->primary_disabled &&
+                   tmp_crtc->fb) {
                        if (crtc) {
                                DRM_DEBUG_KMS("more than one pipe active, disabling compression\n");
                                dev_priv->no_fbc_reason = FBC_MULTIPLE_PIPES;
@@ -3328,8 +3330,12 @@ static void gen6_init_clock_gating(struct drm_device *dev)
         *
         * According to the spec, bit 11 (RCCUNIT) must also be set,
         * but we didn't debug actual testcases to find it out.
+        *
+        * Also apply WaDisableVDSUnitClockGating and
+        * WaDisableRCPBUnitClockGating.
         */
        I915_WRITE(GEN6_UCGCTL2,
+                  GEN7_VDSUNIT_CLOCK_GATE_DISABLE |
                   GEN6_RCPBUNIT_CLOCK_GATE_DISABLE |
                   GEN6_RCCUNIT_CLOCK_GATE_DISABLE);
 
@@ -3357,6 +3363,9 @@ static void gen6_init_clock_gating(struct drm_device *dev)
                   ILK_DPARB_CLK_GATE  |
                   ILK_DPFD_CLK_GATE);
 
+       I915_WRITE(GEN6_MBCTL, I915_READ(GEN6_MBCTL) |
+                  GEN6_MBCTL_ENABLE_BOOT_FETCH);
+
        for_each_pipe(pipe) {
                I915_WRITE(DSPCNTR(pipe),
                           I915_READ(DSPCNTR(pipe)) |
@@ -3382,6 +3391,7 @@ static void ivybridge_init_clock_gating(struct drm_device *dev)
        struct drm_i915_private *dev_priv = dev->dev_private;
        int pipe;
        uint32_t dspclk_gate = VRHUNIT_CLOCK_GATE_DISABLE;
+       uint32_t snpcr;
 
        I915_WRITE(PCH_DSPCLK_GATE_D, dspclk_gate);
 
@@ -3389,11 +3399,6 @@ static void ivybridge_init_clock_gating(struct drm_device *dev)
        I915_WRITE(WM2_LP_ILK, 0);
        I915_WRITE(WM1_LP_ILK, 0);
 
-       /* According to the spec, bit 13 (RCZUNIT) must be set on IVB.
-        * This implements the WaDisableRCZUnitClockGating workaround.
-        */
-       I915_WRITE(GEN6_UCGCTL2, GEN6_RCZUNIT_CLOCK_GATE_DISABLE);
-
        I915_WRITE(ILK_DSPCLK_GATE, IVB_VRHUNIT_CLK_GATE);
 
        I915_WRITE(IVB_CHICKEN3,
@@ -3410,6 +3415,23 @@ static void ivybridge_init_clock_gating(struct drm_device *dev)
        I915_WRITE(GEN7_L3_CHICKEN_MODE_REGISTER,
                        GEN7_WA_L3_CHICKEN_MODE);
 
+       /* According to the BSpec vol1g, bit 12 (RCPBUNIT) clock
+        * gating disable must be set.  Failure to set it results in
+        * flickering pixels due to Z write ordering failures after
+        * some amount of runtime in the Mesa "fire" demo, and Unigine
+        * Sanctuary and Tropics, and apparently anything else with
+        * alpha test or pixel discard.
+        *
+        * According to the spec, bit 11 (RCCUNIT) must also be set,
+        * but we didn't debug actual testcases to find it out.
+        *
+        * According to the spec, bit 13 (RCZUNIT) must be set on IVB.
+        * This implements the WaDisableRCZUnitClockGating workaround.
+        */
+       I915_WRITE(GEN6_UCGCTL2,
+                  GEN6_RCZUNIT_CLOCK_GATE_DISABLE |
+                  GEN6_RCCUNIT_CLOCK_GATE_DISABLE);
+
        /* This is required by WaCatErrorRejectionIssue */
        I915_WRITE(GEN7_SQ_CHICKEN_MBCUNIT_CONFIG,
                        I915_READ(GEN7_SQ_CHICKEN_MBCUNIT_CONFIG) |
@@ -3422,11 +3444,19 @@ static void ivybridge_init_clock_gating(struct drm_device *dev)
                intel_flush_display_plane(dev_priv, pipe);
        }
 
+       I915_WRITE(GEN6_MBCTL, I915_READ(GEN6_MBCTL) |
+                  GEN6_MBCTL_ENABLE_BOOT_FETCH);
+
        gen7_setup_fixed_func_scheduler(dev_priv);
 
        /* WaDisable4x2SubspanOptimization */
        I915_WRITE(CACHE_MODE_1,
                   _MASKED_BIT_ENABLE(PIXEL_SUBSPAN_COLLECT_OPT_DISABLE));
+
+       snpcr = I915_READ(GEN6_MBCUNIT_SNPCR);
+       snpcr &= ~GEN6_MBC_SNPCR_MASK;
+       snpcr |= GEN6_MBC_SNPCR_MED;
+       I915_WRITE(GEN6_MBCUNIT_SNPCR, snpcr);
 }
 
 static void valleyview_init_clock_gating(struct drm_device *dev)
@@ -3441,11 +3471,6 @@ static void valleyview_init_clock_gating(struct drm_device *dev)
        I915_WRITE(WM2_LP_ILK, 0);
        I915_WRITE(WM1_LP_ILK, 0);
 
-       /* According to the spec, bit 13 (RCZUNIT) must be set on IVB.
-        * This implements the WaDisableRCZUnitClockGating workaround.
-        */
-       I915_WRITE(GEN6_UCGCTL2, GEN6_RCZUNIT_CLOCK_GATE_DISABLE);
-
        I915_WRITE(ILK_DSPCLK_GATE, IVB_VRHUNIT_CLK_GATE);
 
        I915_WRITE(IVB_CHICKEN3,
@@ -3465,6 +3490,35 @@ static void valleyview_init_clock_gating(struct drm_device *dev)
                   I915_READ(GEN7_SQ_CHICKEN_MBCUNIT_CONFIG) |
                   GEN7_SQ_CHICKEN_MBCUNIT_SQINTMOB);
 
+       I915_WRITE(GEN6_MBCTL, I915_READ(GEN6_MBCTL) |
+                  GEN6_MBCTL_ENABLE_BOOT_FETCH);
+
+
+       /* According to the BSpec vol1g, bit 12 (RCPBUNIT) clock
+        * gating disable must be set.  Failure to set it results in
+        * flickering pixels due to Z write ordering failures after
+        * some amount of runtime in the Mesa "fire" demo, and Unigine
+        * Sanctuary and Tropics, and apparently anything else with
+        * alpha test or pixel discard.
+        *
+        * According to the spec, bit 11 (RCCUNIT) must also be set,
+        * but we didn't debug actual testcases to find it out.
+        *
+        * According to the spec, bit 13 (RCZUNIT) must be set on IVB.
+        * This implements the WaDisableRCZUnitClockGating workaround.
+        *
+        * Also apply WaDisableVDSUnitClockGating and
+        * WaDisableRCPBUnitClockGating.
+        */
+       I915_WRITE(GEN6_UCGCTL2,
+                  GEN7_VDSUNIT_CLOCK_GATE_DISABLE |
+                  GEN7_TDLUNIT_CLOCK_GATE_DISABLE |
+                  GEN6_RCZUNIT_CLOCK_GATE_DISABLE |
+                  GEN6_RCPBUNIT_CLOCK_GATE_DISABLE |
+                  GEN6_RCCUNIT_CLOCK_GATE_DISABLE);
+
+       I915_WRITE(GEN7_UCGCTL4, GEN7_L3BANK2X_CLOCK_GATE_DISABLE);
+
        for_each_pipe(pipe) {
                I915_WRITE(DSPCNTR(pipe),
                           I915_READ(DSPCNTR(pipe)) |
@@ -3474,6 +3528,19 @@ static void valleyview_init_clock_gating(struct drm_device *dev)
 
        I915_WRITE(CACHE_MODE_1,
                   _MASKED_BIT_ENABLE(PIXEL_SUBSPAN_COLLECT_OPT_DISABLE));
+
+       /*
+        * On ValleyView, the GUnit needs to signal the GT
+        * when flip and other events complete.  So enable
+        * all the GUnit->GT interrupts here
+        */
+       I915_WRITE(VLV_DPFLIPSTAT, PIPEB_LINE_COMPARE_INT_EN |
+                  PIPEB_HLINE_INT_EN | PIPEB_VBLANK_INT_EN |
+                  SPRITED_FLIPDONE_INT_EN | SPRITEC_FLIPDONE_INT_EN |
+                  PLANEB_FLIPDONE_INT_EN | PIPEA_LINE_COMPARE_INT_EN |
+                  PIPEA_HLINE_INT_EN | PIPEA_VBLANK_INT_EN |
+                  SPRITEB_FLIPDONE_INT_EN | SPRITEA_FLIPDONE_INT_EN |
+                  PLANEA_FLIPDONE_INT_EN);
 }
 
 static void g4x_init_clock_gating(struct drm_device *dev)
index e5b84ff..f30a53a 100644 (file)
@@ -226,6 +226,7 @@ gen6_render_ring_flush(struct intel_ring_buffer *ring,
         * impact.
         */
        flags |= PIPE_CONTROL_RENDER_TARGET_CACHE_FLUSH;
+       flags |= PIPE_CONTROL_TLB_INVALIDATE;
        flags |= PIPE_CONTROL_INSTRUCTION_CACHE_INVALIDATE;
        flags |= PIPE_CONTROL_TEXTURE_CACHE_INVALIDATE;
        flags |= PIPE_CONTROL_DEPTH_CACHE_FLUSH;
@@ -433,11 +434,21 @@ static int init_render_ring(struct intel_ring_buffer *ring)
                 */
                I915_WRITE(CACHE_MODE_0,
                           _MASKED_BIT_DISABLE(CM0_STC_EVICT_DISABLE_LRA_SNB));
+
+               /* This is not explicitly set for GEN6, so read the register.
+                * see intel_ring_mi_set_context() for why we care.
+                * TODO: consider explicitly setting the bit for GEN5
+                */
+               ring->itlb_before_ctx_switch =
+                       !!(I915_READ(GFX_MODE) & GFX_TLB_INVALIDATE_ALWAYS);
        }
 
        if (INTEL_INFO(dev)->gen >= 6)
                I915_WRITE(INSTPM, _MASKED_BIT_ENABLE(INSTPM_FORCE_ORDERING));
 
+       if (IS_IVYBRIDGE(dev))
+               I915_WRITE_IMR(ring, ~GEN6_RENDER_L3_PARITY_ERROR);
+
        return ret;
 }
 
@@ -825,7 +836,11 @@ gen6_ring_get_irq(struct intel_ring_buffer *ring)
 
        spin_lock_irqsave(&dev_priv->irq_lock, flags);
        if (ring->irq_refcount++ == 0) {
-               I915_WRITE_IMR(ring, ~ring->irq_enable_mask);
+               if (IS_IVYBRIDGE(dev) && ring->id == RCS)
+                       I915_WRITE_IMR(ring, ~(ring->irq_enable_mask |
+                                               GEN6_RENDER_L3_PARITY_ERROR));
+               else
+                       I915_WRITE_IMR(ring, ~ring->irq_enable_mask);
                dev_priv->gt_irq_mask &= ~ring->irq_enable_mask;
                I915_WRITE(GTIMR, dev_priv->gt_irq_mask);
                POSTING_READ(GTIMR);
@@ -844,7 +859,10 @@ gen6_ring_put_irq(struct intel_ring_buffer *ring)
 
        spin_lock_irqsave(&dev_priv->irq_lock, flags);
        if (--ring->irq_refcount == 0) {
-               I915_WRITE_IMR(ring, ~0);
+               if (IS_IVYBRIDGE(dev) && ring->id == RCS)
+                       I915_WRITE_IMR(ring, ~GEN6_RENDER_L3_PARITY_ERROR);
+               else
+                       I915_WRITE_IMR(ring, ~0);
                dev_priv->gt_irq_mask |= ring->irq_enable_mask;
                I915_WRITE(GTIMR, dev_priv->gt_irq_mask);
                POSTING_READ(GTIMR);
@@ -969,6 +987,7 @@ static int intel_init_ring_buffer(struct drm_device *dev,
                                  struct intel_ring_buffer *ring)
 {
        struct drm_i915_gem_object *obj;
+       struct drm_i915_private *dev_priv = dev->dev_private;
        int ret;
 
        ring->dev = dev;
@@ -1002,8 +1021,9 @@ static int intel_init_ring_buffer(struct drm_device *dev,
        if (ret)
                goto err_unpin;
 
-       ring->virtual_start = ioremap_wc(dev->agp->base + obj->gtt_offset,
-                                        ring->size);
+       ring->virtual_start =
+               ioremap_wc(dev_priv->mm.gtt->gma_bus_addr + obj->gtt_offset,
+                          ring->size);
        if (ring->virtual_start == NULL) {
                DRM_ERROR("Failed to map ringbuffer.\n");
                ret = -EINVAL;
@@ -1100,7 +1120,7 @@ static int intel_ring_wait_seqno(struct intel_ring_buffer *ring, u32 seqno)
        was_interruptible = dev_priv->mm.interruptible;
        dev_priv->mm.interruptible = false;
 
-       ret = i915_wait_request(ring, seqno);
+       ret = i915_wait_seqno(ring, seqno);
 
        dev_priv->mm.interruptible = was_interruptible;
        if (!ret)
index 55d3da2..1d3c81f 100644 (file)
@@ -113,9 +113,17 @@ struct  intel_ring_buffer {
         * Do we have some not yet emitted requests outstanding?
         */
        u32 outstanding_lazy_request;
+       bool gpu_caches_dirty;
 
        wait_queue_head_t irq_queue;
 
+       /**
+        * Do an explicit TLB flush before MI_SET_CONTEXT
+        */
+       bool itlb_before_ctx_switch;
+       struct i915_hw_context *default_context;
+       struct drm_i915_gem_object *last_context_obj;
+
        void *private;
 };
 
index b6a9d45..2f5106a 100644 (file)
@@ -140,9 +140,6 @@ struct intel_sdvo {
 
        /* DDC bus used by this SDVO encoder */
        uint8_t ddc_bus;
-
-       /* Input timings for adjusted_mode */
-       struct intel_sdvo_dtd input_dtd;
 };
 
 struct intel_sdvo_connector {
@@ -953,11 +950,15 @@ intel_sdvo_set_output_timings_from_mode(struct intel_sdvo *intel_sdvo,
        return true;
 }
 
+/* Asks the sdvo controller for the preferred input mode given the output mode.
+ * Unfortunately we have to set up the full output mode to do that. */
 static bool
-intel_sdvo_set_input_timings_for_mode(struct intel_sdvo *intel_sdvo,
-                                       struct drm_display_mode *mode,
-                                       struct drm_display_mode *adjusted_mode)
+intel_sdvo_get_preferred_input_mode(struct intel_sdvo *intel_sdvo,
+                                   struct drm_display_mode *mode,
+                                   struct drm_display_mode *adjusted_mode)
 {
+       struct intel_sdvo_dtd input_dtd;
+
        /* Reset the input timing to the screen. Assume always input 0. */
        if (!intel_sdvo_set_target_input(intel_sdvo))
                return false;
@@ -969,10 +970,10 @@ intel_sdvo_set_input_timings_for_mode(struct intel_sdvo *intel_sdvo,
                return false;
 
        if (!intel_sdvo_get_preferred_input_timing(intel_sdvo,
-                                                  &intel_sdvo->input_dtd))
+                                                  &input_dtd))
                return false;
 
-       intel_sdvo_get_mode_from_dtd(adjusted_mode, &intel_sdvo->input_dtd);
+       intel_sdvo_get_mode_from_dtd(adjusted_mode, &input_dtd);
 
        return true;
 }
@@ -993,17 +994,17 @@ static bool intel_sdvo_mode_fixup(struct drm_encoder *encoder,
                if (!intel_sdvo_set_output_timings_from_mode(intel_sdvo, mode))
                        return false;
 
-               (void) intel_sdvo_set_input_timings_for_mode(intel_sdvo,
-                                                            mode,
-                                                            adjusted_mode);
+               (void) intel_sdvo_get_preferred_input_mode(intel_sdvo,
+                                                          mode,
+                                                          adjusted_mode);
        } else if (intel_sdvo->is_lvds) {
                if (!intel_sdvo_set_output_timings_from_mode(intel_sdvo,
                                                             intel_sdvo->sdvo_lvds_fixed_mode))
                        return false;
 
-               (void) intel_sdvo_set_input_timings_for_mode(intel_sdvo,
-                                                            mode,
-                                                            adjusted_mode);
+               (void) intel_sdvo_get_preferred_input_mode(intel_sdvo,
+                                                          mode,
+                                                          adjusted_mode);
        }
 
        /* Make the CRTC code factor in the SDVO pixel multiplier.  The
@@ -1057,7 +1058,9 @@ static void intel_sdvo_mode_set(struct drm_encoder *encoder,
                                             intel_sdvo->sdvo_lvds_fixed_mode);
        else
                intel_sdvo_get_dtd_from_mode(&output_dtd, mode);
-       (void) intel_sdvo_set_output_timing(intel_sdvo, &output_dtd);
+       if (!intel_sdvo_set_output_timing(intel_sdvo, &output_dtd))
+               DRM_INFO("Setting output timings on %s failed\n",
+                        SDVO_NAME(intel_sdvo));
 
        /* Set the input timing to the screen. Assume always input 0. */
        if (!intel_sdvo_set_target_input(intel_sdvo))
@@ -1079,7 +1082,9 @@ static void intel_sdvo_mode_set(struct drm_encoder *encoder,
         * adjusted_mode.
         */
        intel_sdvo_get_dtd_from_mode(&input_dtd, adjusted_mode);
-       (void) intel_sdvo_set_input_timing(intel_sdvo, &input_dtd);
+       if (!intel_sdvo_set_input_timing(intel_sdvo, &input_dtd))
+               DRM_INFO("Setting input timings on %s failed\n",
+                        SDVO_NAME(intel_sdvo));
 
        switch (pixel_multiplier) {
        default:
@@ -1376,7 +1381,7 @@ intel_sdvo_detect(struct drm_connector *connector, bool force)
 
        /* add 30ms delay when the output type might be TV */
        if (intel_sdvo->caps.output_flags & SDVO_TV_MASK)
-               mdelay(30);
+               msleep(30);
 
        if (!intel_sdvo_read_response(intel_sdvo, &response, 2))
                return connector_status_unknown;
@@ -2521,6 +2526,7 @@ bool intel_sdvo_init(struct drm_device *dev, uint32_t sdvo_reg, bool is_sdvob)
        struct drm_i915_private *dev_priv = dev->dev_private;
        struct intel_encoder *intel_encoder;
        struct intel_sdvo *intel_sdvo;
+       u32 hotplug_mask;
        int i;
 
        intel_sdvo = kzalloc(sizeof(struct intel_sdvo), GFP_KERNEL);
@@ -2552,10 +2558,18 @@ bool intel_sdvo_init(struct drm_device *dev, uint32_t sdvo_reg, bool is_sdvob)
                }
        }
 
-       if (intel_sdvo->is_sdvob)
-               dev_priv->hotplug_supported_mask |= SDVOB_HOTPLUG_INT_STATUS;
-       else
-               dev_priv->hotplug_supported_mask |= SDVOC_HOTPLUG_INT_STATUS;
+       hotplug_mask = 0;
+       if (IS_G4X(dev)) {
+               hotplug_mask = intel_sdvo->is_sdvob ?
+                       SDVOB_HOTPLUG_INT_STATUS_G4X : SDVOC_HOTPLUG_INT_STATUS_G4X;
+       } else if (IS_GEN4(dev)) {
+               hotplug_mask = intel_sdvo->is_sdvob ?
+                       SDVOB_HOTPLUG_INT_STATUS_I965 : SDVOC_HOTPLUG_INT_STATUS_I965;
+       } else {
+               hotplug_mask = intel_sdvo->is_sdvob ?
+                       SDVOB_HOTPLUG_INT_STATUS_I915 : SDVOC_HOTPLUG_INT_STATUS_I915;
+       }
+       dev_priv->hotplug_supported_mask |= hotplug_mask;
 
        drm_encoder_helper_add(&intel_encoder->base, &intel_sdvo_helper_funcs);
 
index 2a20fb0..9d7777b 100644 (file)
@@ -326,6 +326,12 @@ intel_enable_primary(struct drm_crtc *crtc)
        struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
        int reg = DSPCNTR(intel_crtc->plane);
 
+       if (!intel_crtc->primary_disabled)
+               return;
+
+       intel_crtc->primary_disabled = false;
+       intel_update_fbc(dev);
+
        I915_WRITE(reg, I915_READ(reg) | DISPLAY_PLANE_ENABLE);
 }
 
@@ -337,7 +343,13 @@ intel_disable_primary(struct drm_crtc *crtc)
        struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
        int reg = DSPCNTR(intel_crtc->plane);
 
+       if (intel_crtc->primary_disabled)
+               return;
+
        I915_WRITE(reg, I915_READ(reg) & ~DISPLAY_PLANE_ENABLE);
+
+       intel_crtc->primary_disabled = true;
+       intel_update_fbc(dev);
 }
 
 static int
@@ -485,18 +497,14 @@ intel_update_plane(struct drm_plane *plane, struct drm_crtc *crtc,
         * Be sure to re-enable the primary before the sprite is no longer
         * covering it fully.
         */
-       if (!disable_primary && intel_plane->primary_disabled) {
+       if (!disable_primary)
                intel_enable_primary(crtc);
-               intel_plane->primary_disabled = false;
-       }
 
        intel_plane->update_plane(plane, fb, obj, crtc_x, crtc_y,
                                  crtc_w, crtc_h, x, y, src_w, src_h);
 
-       if (disable_primary) {
+       if (disable_primary)
                intel_disable_primary(crtc);
-               intel_plane->primary_disabled = true;
-       }
 
        /* Unpin old obj after new one is active to avoid ugliness */
        if (old_obj) {
@@ -527,11 +535,8 @@ intel_disable_plane(struct drm_plane *plane)
        struct intel_plane *intel_plane = to_intel_plane(plane);
        int ret = 0;
 
-       if (intel_plane->primary_disabled) {
+       if (plane->crtc)
                intel_enable_primary(plane->crtc);
-               intel_plane->primary_disabled = false;
-       }
-
        intel_plane->disable_plane(plane);
 
        if (!intel_plane->obj)
index f3f8224..8cc7083 100644 (file)
@@ -200,6 +200,9 @@ typedef struct _drm_i915_sarea {
 #define DRM_I915_GEM_EXECBUFFER2       0x29
 #define DRM_I915_GET_SPRITE_COLORKEY   0x2a
 #define DRM_I915_SET_SPRITE_COLORKEY   0x2b
+#define DRM_I915_GEM_WAIT      0x2c
+#define DRM_I915_GEM_CONTEXT_CREATE    0x2d
+#define DRM_I915_GEM_CONTEXT_DESTROY   0x2e
 
 #define DRM_IOCTL_I915_INIT            DRM_IOW( DRM_COMMAND_BASE + DRM_I915_INIT, drm_i915_init_t)
 #define DRM_IOCTL_I915_FLUSH           DRM_IO ( DRM_COMMAND_BASE + DRM_I915_FLUSH)
@@ -243,6 +246,9 @@ typedef struct _drm_i915_sarea {
 #define DRM_IOCTL_I915_OVERLAY_ATTRS   DRM_IOWR(DRM_COMMAND_BASE + DRM_I915_OVERLAY_ATTRS, struct drm_intel_overlay_attrs)
 #define DRM_IOCTL_I915_SET_SPRITE_COLORKEY DRM_IOWR(DRM_COMMAND_BASE + DRM_I915_SET_SPRITE_COLORKEY, struct drm_intel_sprite_colorkey)
 #define DRM_IOCTL_I915_GET_SPRITE_COLORKEY DRM_IOWR(DRM_COMMAND_BASE + DRM_I915_SET_SPRITE_COLORKEY, struct drm_intel_sprite_colorkey)
+#define DRM_IOCTL_I915_GEM_WAIT                DRM_IOWR(DRM_COMMAND_BASE + DRM_I915_GEM_WAIT, struct drm_i915_gem_wait)
+#define DRM_IOCTL_I915_GEM_CONTEXT_CREATE      DRM_IOWR (DRM_COMMAND_BASE + DRM_I915_GEM_CONTEXT_CREATE, struct drm_i915_gem_context_create)
+#define DRM_IOCTL_I915_GEM_CONTEXT_DESTROY     DRM_IOW (DRM_COMMAND_BASE + DRM_I915_GEM_CONTEXT_DESTROY, struct drm_i915_gem_context_destroy)
 
 /* Allow drivers to submit batchbuffers directly to hardware, relying
  * on the security mechanisms provided by hardware.
@@ -298,6 +304,7 @@ typedef struct drm_i915_irq_wait {
 #define I915_PARAM_HAS_GEN7_SOL_RESET   16
 #define I915_PARAM_HAS_LLC                      17
 #define I915_PARAM_HAS_ALIASING_PPGTT   18
+#define I915_PARAM_HAS_WAIT_TIMEOUT     19
 
 typedef struct drm_i915_getparam {
        int param;
@@ -656,13 +663,19 @@ struct drm_i915_gem_execbuffer2 {
 #define I915_EXEC_CONSTANTS_ABSOLUTE   (1<<6)
 #define I915_EXEC_CONSTANTS_REL_SURFACE (2<<6) /* gen4/5 only */
        __u64 flags;
-       __u64 rsvd1;
+       __u64 rsvd1; /* now used for context info */
        __u64 rsvd2;
 };
 
 /** Resets the SO write offset registers for transform feedback on gen7. */
 #define I915_EXEC_GEN7_SOL_RESET       (1<<8)
 
+#define I915_EXEC_CONTEXT_ID_MASK      (0xffffffff)
+#define i915_execbuffer2_set_context_id(eb2, context) \
+       (eb2).rsvd1 = context & I915_EXEC_CONTEXT_ID_MASK
+#define i915_execbuffer2_get_context_id(eb2) \
+       ((eb2).rsvd1 & I915_EXEC_CONTEXT_ID_MASK)
+
 struct drm_i915_gem_pin {
        /** Handle of the buffer to be pinned. */
        __u32 handle;
@@ -886,4 +899,23 @@ struct drm_intel_sprite_colorkey {
        __u32 flags;
 };
 
+struct drm_i915_gem_wait {
+       /** Handle of BO we shall wait on */
+       __u32 bo_handle;
+       __u32 flags;
+       /** Number of nanoseconds to wait, Returns time remaining. */
+       __s64 timeout_ns;
+};
+
+struct drm_i915_gem_context_create {
+       /*  output: id of new context*/
+       __u32 ctx_id;
+       __u32 pad;
+};
+
+struct drm_i915_gem_context_destroy {
+       __u32 ctx_id;
+       __u32 pad;
+};
+
 #endif                         /* _I915_DRM_H_ */
index 923afb5..8e29d55 100644 (file)
@@ -19,8 +19,16 @@ const struct intel_gtt {
        dma_addr_t scratch_page_dma;
        /* for ppgtt PDE access */
        u32 __iomem *gtt;
+       /* needed for ioremap in drm/i915 */
+       phys_addr_t gma_bus_addr;
 } *intel_gtt_get(void);
 
+int intel_gmch_probe(struct pci_dev *bridge_pdev, struct pci_dev *gpu_pdev,
+                    struct agp_bridge_data *bridge);
+void intel_gmch_remove(void);
+
+bool intel_enable_gtt(void);
+
 void intel_gtt_chipset_flush(void);
 void intel_gtt_unmap_memory(struct scatterlist *sg_list, int num_sg);
 void intel_gtt_clear_range(unsigned int first_entry, unsigned int num_entries);