]> git.proxmox.com Git - mirror_ubuntu-bionic-kernel.git/commitdiff
Merge tag 'drm-intel-next-2014-02-14' of ssh://git.freedesktop.org/git/drm-intel...
authorDave Airlie <airlied@redhat.com>
Mon, 3 Mar 2014 21:51:41 +0000 (07:51 +1000)
committerDave Airlie <airlied@redhat.com>
Mon, 3 Mar 2014 21:51:41 +0000 (07:51 +1000)
- Fix the execbuf rebind performance regression due to topic/ppgtt (Chris).
- Fix up the connector cleanup ordering for sdvod i2c and dp aux devices (Imre).
- Try to preserve the firmware modeset config on driver load. And a bit of prep
  work for smooth takeover of the fb contents (Jesse).
- Prep cleanup for larger gtt address spaces on bdw (Ben).
- Improve our vblank_wait code to make hsw modesets faster (Paulo).
- Display debugfs file (Jesse).
- DRRS prep work from Vandana Kannan.
- pipestat interrupt handler to fix a few races around vblank/pageflip handling
  on byt (Imre).
- Improve display fuse handling for display-less SKUs (Damien).
- Drop locks while stalling for the gpu when serving pagefaults to improve
  interactivity (Chris).
- And as usual piles of other improvements and small fixes all over.

* tag 'drm-intel-next-2014-02-14' of ssh://git.freedesktop.org/git/drm-intel: (65 commits)
  drm/i915: fix NULL deref in the load detect code
  drm/i915: Only bind each object rather than for every execbuffer
  drm/i915: Directly return the vma from bind_to_vm
  drm/i915: Simplify i915_gem_object_ggtt_unpin
  drm/i915: Allow blocking in the PDE alloc when running low on gtt space
  drm/i915: Don't allocate context pages as mappable
  drm/i915: Handle set_cache_level errors in the status page setup
  drm/i915: Don't pin the status page as mappable
  drm/i915: Don't set PIN_MAPPABLE for legacy ringbuffers
  drm/i915: Handle set_cache_level errors in the pipe control scratch setup
  drm/i915: split PIN_GLOBAL out from PIN_MAPPABLE
  drm/i915: Consolidate binding parameters into flags
  drm/i915: sdvo: add i2c sysfs symlink to the connector's directory
  drm/i915: sdvo: fix error path in sdvo_connector_init
  drm/i915: dp: fix order of dp aux i2c device cleanup
  drm/i915: add unregister callback to connector
  drm/i915: don't reference null pointer at i915_sink_crc
  drm/i915/lvds: Remove dead code from failing case
  drm/i915: don't preserve inherited configs with nothing on v2
  drm/i915/bdw: Split up PPGTT cleanup
  ...

1  2 
drivers/gpu/drm/i915/i915_drv.h
drivers/gpu/drm/i915/i915_gem_gtt.c
drivers/gpu/drm/i915/i915_irq.c
drivers/gpu/drm/i915/intel_display.c
drivers/gpu/drm/i915/intel_dp.c
drivers/gpu/drm/i915/intel_ringbuffer.c
include/drm/drm_crtc.h

index 9d8ca2a36fde7c7ce5c42963e8ba0f81f7c502c5,b4587ac4053a5fe3a790c11b37b825dd42868d56..05cfcc163a72024c15ceed9be3fb5b3286049834
@@@ -79,7 -79,7 +79,7 @@@ enum plane 
  };
  #define plane_name(p) ((p) + 'A')
  
- #define sprite_name(p, s) ((p) * dev_priv->num_plane + (s) + 'A')
+ #define sprite_name(p, s) ((p) * INTEL_INFO(dev)->num_sprites + (s) + 'A')
  
  enum port {
        PORT_A = 0,
@@@ -164,6 -164,10 +164,10 @@@ enum hpd_pin 
        list_for_each_entry((intel_encoder), &(dev)->mode_config.encoder_list, base.head) \
                if ((intel_encoder)->base.crtc == (__crtc))
  
+ #define for_each_connector_on_encoder(dev, __encoder, intel_connector) \
+       list_for_each_entry((intel_connector), &(dev)->mode_config.connector_list, base.head) \
+               if ((intel_connector)->base.encoder == (__encoder))
  struct drm_i915_private;
  
  enum intel_dpll_id {
@@@ -530,6 -534,7 +534,7 @@@ struct intel_uncore 
  struct intel_device_info {
        u32 display_mmio_offset;
        u8 num_pipes:3;
+       u8 num_sprites:2;
        u8 gen;
        u8 ring_mask; /* Rings supported by the HW */
        DEV_INFO_FOR_EACH_FLAG(DEFINE_FLAG, SEP_SEMICOLON);
@@@ -1390,7 -1395,7 +1395,7 @@@ typedef struct drm_i915_private 
        struct drm_device *dev;
        struct kmem_cache *slab;
  
-       const struct intel_device_info *info;
+       const struct intel_device_info info;
  
        int relative_constants_mode;
  
        };
        u32 gt_irq_mask;
        u32 pm_irq_mask;
+       u32 pipestat_irq_mask[I915_MAX_PIPES];
  
        struct work_struct hotplug_work;
        bool enable_hotplug_processing;
        u32 hpd_event_bits;
        struct timer_list hotplug_reenable_timer;
  
-       int num_plane;
        struct i915_fbc fbc;
        struct intel_opregion opregion;
        struct intel_vbt_data vbt;
  
        struct sdvo_device_mapping sdvo_mappings[2];
  
-       struct drm_crtc *plane_to_crtc_mapping[3];
-       struct drm_crtc *pipe_to_crtc_mapping[3];
+       struct drm_crtc *plane_to_crtc_mapping[I915_MAX_PIPES];
+       struct drm_crtc *pipe_to_crtc_mapping[I915_MAX_PIPES];
        wait_queue_head_t pending_flip_queue;
  
  #ifdef CONFIG_DEBUG_FS
@@@ -1799,7 -1803,7 +1803,7 @@@ struct drm_i915_file_private 
        atomic_t rps_wait_boost;
  };
  
- #define INTEL_INFO(dev)       (to_i915(dev)->info)
+ #define INTEL_INFO(dev)       (&to_i915(dev)->info)
  
  #define IS_I830(dev)          ((dev)->pdev->device == 0x3577)
  #define IS_845G(dev)          ((dev)->pdev->device == 0x2562)
  
  /* Early gen2 have a totally busted CS tlb and require pinned batches. */
  #define HAS_BROKEN_CS_TLB(dev)                (IS_I830(dev) || IS_845G(dev))
 +/*
 + * dp aux and gmbus irq on gen4 seems to be able to generate legacy interrupts
 + * even when in MSI mode. This results in spurious interrupt warnings if the
 + * legacy irq no. is shared with another device. The kernel then disables that
 + * interrupt source and so prevents the other device from working properly.
 + */
 +#define HAS_AUX_IRQ(dev) (INTEL_INFO(dev)->gen >= 5)
 +#define HAS_GMBUS_IRQ(dev) (INTEL_INFO(dev)->gen >= 5)
  
  /* With the 945 and later, Y tiling got adjusted so that it was 32 128-byte
   * rows, which changed the alignment requirements and fence programming.
@@@ -1953,18 -1949,20 +1957,20 @@@ struct i915_params 
        int vbt_sdvo_panel_type;
        int enable_rc6;
        int enable_fbc;
-       bool enable_hangcheck;
        int enable_ppgtt;
        int enable_psr;
        unsigned int preliminary_hw_support;
        int disable_power_well;
        int enable_ips;
-       bool fastboot;
        int enable_pc8;
        int pc8_timeout;
+       int invert_brightness;
+       /* leave bools at the end to not create holes */
+       bool enable_hangcheck;
+       bool fastboot;
        bool prefault_disable;
        bool reset;
-       int invert_brightness;
+       bool disable_display;
  };
  extern struct i915_params i915 __read_mostly;
  
@@@ -2012,10 -2010,12 +2018,12 @@@ extern void intel_uncore_check_errors(s
  extern void intel_uncore_fini(struct drm_device *dev);
  
  void
- i915_enable_pipestat(drm_i915_private_t *dev_priv, enum pipe pipe, u32 mask);
+ i915_enable_pipestat(drm_i915_private_t *dev_priv, enum pipe pipe,
+                    u32 status_mask);
  
  void
- i915_disable_pipestat(drm_i915_private_t *dev_priv, enum pipe pipe, u32 mask);
+ i915_disable_pipestat(drm_i915_private_t *dev_priv, enum pipe pipe,
+                     u32 status_mask);
  
  /* i915_gem.c */
  int i915_gem_init_ioctl(struct drm_device *dev, void *data,
@@@ -2076,14 -2076,14 +2084,14 @@@ void i915_init_vm(struct drm_i915_priva
  void i915_gem_free_object(struct drm_gem_object *obj);
  void i915_gem_vma_destroy(struct i915_vma *vma);
  
+ #define PIN_MAPPABLE 0x1
+ #define PIN_NONBLOCK 0x2
+ #define PIN_GLOBAL 0x4
  int __must_check i915_gem_object_pin(struct drm_i915_gem_object *obj,
                                     struct i915_address_space *vm,
                                     uint32_t alignment,
-                                    bool map_and_fenceable,
-                                    bool nonblocking);
- void i915_gem_object_ggtt_unpin(struct drm_i915_gem_object *obj);
+                                    unsigned flags);
  int __must_check i915_vma_unbind(struct i915_vma *vma);
- int __must_check i915_gem_object_ggtt_unbind(struct drm_i915_gem_object *obj);
  int i915_gem_object_put_pages(struct drm_i915_gem_object *obj);
  void i915_gem_release_all_mmaps(struct drm_i915_private *dev_priv);
  void i915_gem_release_mmap(struct drm_i915_gem_object *obj);
@@@ -2283,13 -2283,19 +2291,19 @@@ i915_gem_obj_ggtt_size(struct drm_i915_
  static inline int __must_check
  i915_gem_obj_ggtt_pin(struct drm_i915_gem_object *obj,
                      uint32_t alignment,
-                     bool map_and_fenceable,
-                     bool nonblocking)
+                     unsigned flags)
  {
-       return i915_gem_object_pin(obj, obj_to_ggtt(obj), alignment,
-                                  map_and_fenceable, nonblocking);
+       return i915_gem_object_pin(obj, obj_to_ggtt(obj), alignment, flags | PIN_GLOBAL);
  }
  
+ static inline int
+ i915_gem_object_ggtt_unbind(struct drm_i915_gem_object *obj)
+ {
+       return i915_vma_unbind(i915_gem_obj_to_ggtt(obj));
+ }
+ void i915_gem_object_ggtt_unpin(struct drm_i915_gem_object *obj);
  /* i915_gem_context.c */
  #define ctx_to_ppgtt(ctx) container_of((ctx)->vm, struct i915_hw_ppgtt, base)
  int __must_check i915_gem_context_init(struct drm_device *dev);
@@@ -2331,8 -2337,7 +2345,7 @@@ int __must_check i915_gem_evict_somethi
                                          int min_size,
                                          unsigned alignment,
                                          unsigned cache_level,
-                                         bool mappable,
-                                         bool nonblock);
+                                         unsigned flags);
  int i915_gem_evict_vm(struct i915_address_space *vm, bool do_idle);
  int i915_gem_evict_everything(struct drm_device *dev);
  
@@@ -2506,8 -2511,8 +2519,8 @@@ extern void intel_i2c_reset(struct drm_
  
  /* intel_opregion.c */
  struct intel_encoder;
 -extern int intel_opregion_setup(struct drm_device *dev);
  #ifdef CONFIG_ACPI
 +extern int intel_opregion_setup(struct drm_device *dev);
  extern void intel_opregion_init(struct drm_device *dev);
  extern void intel_opregion_fini(struct drm_device *dev);
  extern void intel_opregion_asle_intr(struct drm_device *dev);
@@@ -2516,7 -2521,6 +2529,7 @@@ extern int intel_opregion_notify_encode
  extern int intel_opregion_notify_adapter(struct drm_device *dev,
                                         pci_power_t state);
  #else
 +static inline int intel_opregion_setup(struct drm_device *dev) { return 0; }
  static inline void intel_opregion_init(struct drm_device *dev) { return; }
  static inline void intel_opregion_fini(struct drm_device *dev) { return; }
  static inline void intel_opregion_asle_intr(struct drm_device *dev) { return; }
@@@ -2547,6 -2551,7 +2560,7 @@@ extern void intel_modeset_suspend_hw(st
  extern void intel_modeset_init(struct drm_device *dev);
  extern void intel_modeset_gem_init(struct drm_device *dev);
  extern void intel_modeset_cleanup(struct drm_device *dev);
+ extern void intel_connector_unregister(struct intel_connector *);
  extern int intel_modeset_vga_set_state(struct drm_device *dev, bool state);
  extern void intel_modeset_setup_hw_state(struct drm_device *dev,
                                         bool force_restore);
index a4364ae1a2d66a62e3cd106f7c6d982c304f6315,69a88d41a2a7e72df69b43d790a21c2966041793..9673cffb07f346dd11dbf486cb0b4ec28eb2ba1d
@@@ -319,36 -319,53 +319,53 @@@ static void gen8_ppgtt_insert_entries(s
                kunmap_atomic(pt_vaddr);
  }
  
- static void gen8_ppgtt_cleanup(struct i915_address_space *vm)
+ static void gen8_ppgtt_free(struct i915_hw_ppgtt *ppgtt)
+ {
+       int i;
+       for (i = 0; i < ppgtt->num_pd_pages ; i++)
+               kfree(ppgtt->gen8_pt_dma_addr[i]);
+       __free_pages(ppgtt->gen8_pt_pages, get_order(ppgtt->num_pt_pages << PAGE_SHIFT));
+       __free_pages(ppgtt->pd_pages, get_order(ppgtt->num_pd_pages << PAGE_SHIFT));
+ }
+ static void gen8_ppgtt_unmap_pages(struct i915_hw_ppgtt *ppgtt)
  {
-       struct i915_hw_ppgtt *ppgtt =
-               container_of(vm, struct i915_hw_ppgtt, base);
        int i, j;
  
-       list_del(&vm->global_link);
-       drm_mm_takedown(&vm->mm);
+       for (i = 0; i < ppgtt->num_pd_pages; i++) {
+               /* TODO: In the future we'll support sparse mappings, so this
+                * will have to change. */
+               if (!ppgtt->pd_dma_addr[i])
+                       continue;
  
-       for (i = 0; i < ppgtt->num_pd_pages ; i++) {
-               if (ppgtt->pd_dma_addr[i]) {
-                       pci_unmap_page(ppgtt->base.dev->pdev,
-                                      ppgtt->pd_dma_addr[i],
-                                      PAGE_SIZE, PCI_DMA_BIDIRECTIONAL);
+               pci_unmap_page(ppgtt->base.dev->pdev,
+                              ppgtt->pd_dma_addr[i],
+                              PAGE_SIZE, PCI_DMA_BIDIRECTIONAL);
  
-                       for (j = 0; j < GEN8_PDES_PER_PAGE; j++) {
-                               dma_addr_t addr = ppgtt->gen8_pt_dma_addr[i][j];
-                               if (addr)
-                                       pci_unmap_page(ppgtt->base.dev->pdev,
-                                                      addr,
-                                                      PAGE_SIZE,
-                                                      PCI_DMA_BIDIRECTIONAL);
+               for (j = 0; j < GEN8_PDES_PER_PAGE; j++) {
+                       dma_addr_t addr = ppgtt->gen8_pt_dma_addr[i][j];
+                       if (addr)
+                               pci_unmap_page(ppgtt->base.dev->pdev,
+                                      addr,
+                                      PAGE_SIZE,
+                                      PCI_DMA_BIDIRECTIONAL);
  
-                       }
                }
-               kfree(ppgtt->gen8_pt_dma_addr[i]);
        }
+ }
  
-       __free_pages(ppgtt->gen8_pt_pages, get_order(ppgtt->num_pt_pages << PAGE_SHIFT));
-       __free_pages(ppgtt->pd_pages, get_order(ppgtt->num_pd_pages << PAGE_SHIFT));
+ static void gen8_ppgtt_cleanup(struct i915_address_space *vm)
+ {
+       struct i915_hw_ppgtt *ppgtt =
+               container_of(vm, struct i915_hw_ppgtt, base);
+       list_del(&vm->global_link);
+       drm_mm_takedown(&vm->mm);
+       gen8_ppgtt_unmap_pages(ppgtt);
+       gen8_ppgtt_free(ppgtt);
  }
  
  /**
@@@ -868,7 -885,7 +885,7 @@@ alloc
        if (ret == -ENOSPC && !retried) {
                ret = i915_gem_evict_something(dev, &dev_priv->gtt.base,
                                               GEN6_PD_SIZE, GEN6_PD_ALIGN,
-                                              I915_CACHE_NONE, false, true);
+                                              I915_CACHE_NONE, 0);
                if (ret)
                        return ret;
  
@@@ -1567,14 -1584,14 +1584,14 @@@ static int ggtt_probe_common(struct drm
                             size_t gtt_size)
  {
        struct drm_i915_private *dev_priv = dev->dev_private;
 -      phys_addr_t gtt_bus_addr;
 +      phys_addr_t gtt_phys_addr;
        int ret;
  
        /* For Modern GENs the PTEs and register space are split in the BAR */
 -      gtt_bus_addr = pci_resource_start(dev->pdev, 0) +
 +      gtt_phys_addr = pci_resource_start(dev->pdev, 0) +
                (pci_resource_len(dev->pdev, 0) / 2);
  
 -      dev_priv->gtt.gsm = ioremap_wc(gtt_bus_addr, gtt_size);
 +      dev_priv->gtt.gsm = ioremap_wc(gtt_phys_addr, gtt_size);
        if (!dev_priv->gtt.gsm) {
                DRM_ERROR("Failed to map the gtt page table\n");
                return -ENOMEM;
index e9c94c91c6a59a40a45d11cccf90f9d9cfd2e637,69f2ebbd6af1b7aa965c5cf6ce4400cb555c3fff..f68aee31e565d757d21bb1895178ef0f52224ab7
@@@ -419,6 -419,16 +419,16 @@@ done
        return ret;
  }
  
+ static bool __cpu_fifo_underrun_reporting_enabled(struct drm_device *dev,
+                                                 enum pipe pipe)
+ {
+       struct drm_i915_private *dev_priv = dev->dev_private;
+       struct drm_crtc *crtc = dev_priv->pipe_to_crtc_mapping[pipe];
+       struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
+       return !intel_crtc->cpu_fifo_underrun_disabled;
+ }
  /**
   * intel_set_pch_fifo_underrun_reporting - enable/disable FIFO underrun messages
   * @dev: drm device
@@@ -473,38 -483,102 +483,102 @@@ done
  
  
  void
- i915_enable_pipestat(drm_i915_private_t *dev_priv, enum pipe pipe, u32 mask)
+ __i915_enable_pipestat(struct drm_i915_private *dev_priv, enum pipe pipe,
+                      u32 enable_mask, u32 status_mask)
  {
        u32 reg = PIPESTAT(pipe);
-       u32 pipestat = I915_READ(reg) & 0x7fff0000;
+       u32 pipestat = I915_READ(reg) & PIPESTAT_INT_ENABLE_MASK;
  
        assert_spin_locked(&dev_priv->irq_lock);
  
-       if ((pipestat & mask) == mask)
+       if (WARN_ON_ONCE(enable_mask & ~PIPESTAT_INT_ENABLE_MASK ||
+                        status_mask & ~PIPESTAT_INT_STATUS_MASK))
+               return;
+       if ((pipestat & enable_mask) == enable_mask)
                return;
  
+       dev_priv->pipestat_irq_mask[pipe] |= status_mask;
        /* Enable the interrupt, clear any pending status */
-       pipestat |= mask | (mask >> 16);
+       pipestat |= enable_mask | status_mask;
        I915_WRITE(reg, pipestat);
        POSTING_READ(reg);
  }
  
  void
- i915_disable_pipestat(drm_i915_private_t *dev_priv, enum pipe pipe, u32 mask)
+ __i915_disable_pipestat(struct drm_i915_private *dev_priv, enum pipe pipe,
+                       u32 enable_mask, u32 status_mask)
  {
        u32 reg = PIPESTAT(pipe);
-       u32 pipestat = I915_READ(reg) & 0x7fff0000;
+       u32 pipestat = I915_READ(reg) & PIPESTAT_INT_ENABLE_MASK;
  
        assert_spin_locked(&dev_priv->irq_lock);
  
-       if ((pipestat & mask) == 0)
+       if (WARN_ON_ONCE(enable_mask & ~PIPESTAT_INT_ENABLE_MASK ||
+                        status_mask & ~PIPESTAT_INT_STATUS_MASK))
+               return;
+       if ((pipestat & enable_mask) == 0)
                return;
  
-       pipestat &= ~mask;
+       dev_priv->pipestat_irq_mask[pipe] &= ~status_mask;
+       pipestat &= ~enable_mask;
        I915_WRITE(reg, pipestat);
        POSTING_READ(reg);
  }
  
+ static u32 vlv_get_pipestat_enable_mask(struct drm_device *dev, u32 status_mask)
+ {
+       u32 enable_mask = status_mask << 16;
+       /*
+        * On pipe A we don't support the PSR interrupt yet, on pipe B the
+        * same bit MBZ.
+        */
+       if (WARN_ON_ONCE(status_mask & PIPE_A_PSR_STATUS_VLV))
+               return 0;
+       enable_mask &= ~(PIPE_FIFO_UNDERRUN_STATUS |
+                        SPRITE0_FLIP_DONE_INT_EN_VLV |
+                        SPRITE1_FLIP_DONE_INT_EN_VLV);
+       if (status_mask & SPRITE0_FLIP_DONE_INT_STATUS_VLV)
+               enable_mask |= SPRITE0_FLIP_DONE_INT_EN_VLV;
+       if (status_mask & SPRITE1_FLIP_DONE_INT_STATUS_VLV)
+               enable_mask |= SPRITE1_FLIP_DONE_INT_EN_VLV;
+       return enable_mask;
+ }
+ void
+ i915_enable_pipestat(struct drm_i915_private *dev_priv, enum pipe pipe,
+                    u32 status_mask)
+ {
+       u32 enable_mask;
+       if (IS_VALLEYVIEW(dev_priv->dev))
+               enable_mask = vlv_get_pipestat_enable_mask(dev_priv->dev,
+                                                          status_mask);
+       else
+               enable_mask = status_mask << 16;
+       __i915_enable_pipestat(dev_priv, pipe, enable_mask, status_mask);
+ }
+ void
+ i915_disable_pipestat(struct drm_i915_private *dev_priv, enum pipe pipe,
+                     u32 status_mask)
+ {
+       u32 enable_mask;
+       if (IS_VALLEYVIEW(dev_priv->dev))
+               enable_mask = vlv_get_pipestat_enable_mask(dev_priv->dev,
+                                                          status_mask);
+       else
+               enable_mask = status_mask << 16;
+       __i915_disable_pipestat(dev_priv, pipe, enable_mask, status_mask);
+ }
  /**
   * i915_enable_asle_pipestat - enable ASLE pipestat for OpRegion
   */
@@@ -518,10 -592,10 +592,10 @@@ static void i915_enable_asle_pipestat(s
  
        spin_lock_irqsave(&dev_priv->irq_lock, irqflags);
  
-       i915_enable_pipestat(dev_priv, PIPE_B, PIPE_LEGACY_BLC_EVENT_ENABLE);
+       i915_enable_pipestat(dev_priv, PIPE_B, PIPE_LEGACY_BLC_EVENT_STATUS);
        if (INTEL_INFO(dev)->gen >= 4)
                i915_enable_pipestat(dev_priv, PIPE_A,
-                                    PIPE_LEGACY_BLC_EVENT_ENABLE);
+                                    PIPE_LEGACY_BLC_EVENT_STATUS);
  
        spin_unlock_irqrestore(&dev_priv->irq_lock, irqflags);
  }
@@@ -581,7 -655,8 +655,7 @@@ static u32 i915_get_vblank_counter(stru
  
                vbl_start = mode->crtc_vblank_start * mode->crtc_htotal;
        } else {
 -              enum transcoder cpu_transcoder =
 -                      intel_pipe_to_cpu_transcoder(dev_priv, pipe);
 +              enum transcoder cpu_transcoder = (enum transcoder) pipe;
                u32 htotal;
  
                htotal = ((I915_READ(HTOTAL(cpu_transcoder)) >> 16) & 0x1fff) + 1;
@@@ -1479,18 -1554,48 +1553,48 @@@ static void gen6_rps_irq_handler(struc
  static void valleyview_pipestat_irq_handler(struct drm_device *dev, u32 iir)
  {
        struct drm_i915_private *dev_priv = dev->dev_private;
-       u32 pipe_stats[I915_MAX_PIPES];
+       u32 pipe_stats[I915_MAX_PIPES] = { };
        int pipe;
  
        spin_lock(&dev_priv->irq_lock);
        for_each_pipe(pipe) {
-               int reg = PIPESTAT(pipe);
-               pipe_stats[pipe] = I915_READ(reg);
+               int reg;
+               u32 mask, iir_bit = 0;
+               /*
+                * PIPESTAT bits get signalled even when the interrupt is
+                * disabled with the mask bits, and some of the status bits do
+                * not generate interrupts at all (like the underrun bit). Hence
+                * we need to be careful that we only handle what we want to
+                * handle.
+                */
+               mask = 0;
+               if (__cpu_fifo_underrun_reporting_enabled(dev, pipe))
+                       mask |= PIPE_FIFO_UNDERRUN_STATUS;
+               switch (pipe) {
+               case PIPE_A:
+                       iir_bit = I915_DISPLAY_PIPE_A_EVENT_INTERRUPT;
+                       break;
+               case PIPE_B:
+                       iir_bit = I915_DISPLAY_PIPE_B_EVENT_INTERRUPT;
+                       break;
+               }
+               if (iir & iir_bit)
+                       mask |= dev_priv->pipestat_irq_mask[pipe];
+               if (!mask)
+                       continue;
+               reg = PIPESTAT(pipe);
+               mask |= PIPESTAT_INT_ENABLE_MASK;
+               pipe_stats[pipe] = I915_READ(reg) & mask;
  
                /*
                 * Clear the PIPE*STAT regs before the IIR
                 */
-               if (pipe_stats[pipe] & 0x8000ffff)
+               if (pipe_stats[pipe] & (PIPE_FIFO_UNDERRUN_STATUS |
+                                       PIPESTAT_INT_STATUS_MASK))
                        I915_WRITE(reg, pipe_stats[pipe]);
        }
        spin_unlock(&dev_priv->irq_lock);
@@@ -2269,13 -2374,13 +2373,13 @@@ static int i915_enable_vblank(struct dr
        spin_lock_irqsave(&dev_priv->irq_lock, irqflags);
        if (INTEL_INFO(dev)->gen >= 4)
                i915_enable_pipestat(dev_priv, pipe,
-                                    PIPE_START_VBLANK_INTERRUPT_ENABLE);
+                                    PIPE_START_VBLANK_INTERRUPT_STATUS);
        else
                i915_enable_pipestat(dev_priv, pipe,
-                                    PIPE_VBLANK_INTERRUPT_ENABLE);
+                                    PIPE_VBLANK_INTERRUPT_STATUS);
  
        /* maintain vblank delivery even in deep C-states */
-       if (dev_priv->info->gen == 3)
+       if (INTEL_INFO(dev)->gen == 3)
                I915_WRITE(INSTPM, _MASKED_BIT_DISABLE(INSTPM_AGPBUSY_DIS));
        spin_unlock_irqrestore(&dev_priv->irq_lock, irqflags);
  
@@@ -2309,7 -2414,7 +2413,7 @@@ static int valleyview_enable_vblank(str
  
        spin_lock_irqsave(&dev_priv->irq_lock, irqflags);
        i915_enable_pipestat(dev_priv, pipe,
-                            PIPE_START_VBLANK_INTERRUPT_ENABLE);
+                            PIPE_START_VBLANK_INTERRUPT_STATUS);
        spin_unlock_irqrestore(&dev_priv->irq_lock, irqflags);
  
        return 0;
@@@ -2340,12 -2445,12 +2444,12 @@@ static void i915_disable_vblank(struct 
        unsigned long irqflags;
  
        spin_lock_irqsave(&dev_priv->irq_lock, irqflags);
-       if (dev_priv->info->gen == 3)
+       if (INTEL_INFO(dev)->gen == 3)
                I915_WRITE(INSTPM, _MASKED_BIT_ENABLE(INSTPM_AGPBUSY_DIS));
  
        i915_disable_pipestat(dev_priv, pipe,
-                             PIPE_VBLANK_INTERRUPT_ENABLE |
-                             PIPE_START_VBLANK_INTERRUPT_ENABLE);
+                             PIPE_VBLANK_INTERRUPT_STATUS |
+                             PIPE_START_VBLANK_INTERRUPT_STATUS);
        spin_unlock_irqrestore(&dev_priv->irq_lock, irqflags);
  }
  
@@@ -2368,7 -2473,7 +2472,7 @@@ static void valleyview_disable_vblank(s
  
        spin_lock_irqsave(&dev_priv->irq_lock, irqflags);
        i915_disable_pipestat(dev_priv, pipe,
-                             PIPE_START_VBLANK_INTERRUPT_ENABLE);
+                             PIPE_START_VBLANK_INTERRUPT_STATUS);
        spin_unlock_irqrestore(&dev_priv->irq_lock, irqflags);
  }
  
@@@ -2916,8 -3021,8 +3020,8 @@@ static int valleyview_irq_postinstall(s
  {
        drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
        u32 enable_mask;
-       u32 pipestat_enable = PLANE_FLIP_DONE_INT_EN_VLV |
-               PIPE_CRC_DONE_ENABLE;
+       u32 pipestat_enable = PLANE_FLIP_DONE_INT_STATUS_VLV |
+               PIPE_CRC_DONE_INTERRUPT_STATUS;
        unsigned long irqflags;
  
        enable_mask = I915_DISPLAY_PORT_INTERRUPT;
         * just to make the assert_spin_locked check happy. */
        spin_lock_irqsave(&dev_priv->irq_lock, irqflags);
        i915_enable_pipestat(dev_priv, PIPE_A, pipestat_enable);
-       i915_enable_pipestat(dev_priv, PIPE_A, PIPE_GMBUS_EVENT_ENABLE);
+       i915_enable_pipestat(dev_priv, PIPE_A, PIPE_GMBUS_INTERRUPT_STATUS);
        i915_enable_pipestat(dev_priv, PIPE_B, pipestat_enable);
        spin_unlock_irqrestore(&dev_priv->irq_lock, irqflags);
  
@@@ -3171,8 -3276,8 +3275,8 @@@ static int i8xx_irq_postinstall(struct 
        /* Interrupt setup is already guaranteed to be single-threaded, this is
         * just to make the assert_spin_locked check happy. */
        spin_lock_irqsave(&dev_priv->irq_lock, irqflags);
-       i915_enable_pipestat(dev_priv, PIPE_A, PIPE_CRC_DONE_ENABLE);
-       i915_enable_pipestat(dev_priv, PIPE_B, PIPE_CRC_DONE_ENABLE);
+       i915_enable_pipestat(dev_priv, PIPE_A, PIPE_CRC_DONE_INTERRUPT_STATUS);
+       i915_enable_pipestat(dev_priv, PIPE_B, PIPE_CRC_DONE_INTERRUPT_STATUS);
        spin_unlock_irqrestore(&dev_priv->irq_lock, irqflags);
  
        return 0;
@@@ -3354,8 -3459,8 +3458,8 @@@ static int i915_irq_postinstall(struct 
        /* Interrupt setup is already guaranteed to be single-threaded, this is
         * just to make the assert_spin_locked check happy. */
        spin_lock_irqsave(&dev_priv->irq_lock, irqflags);
-       i915_enable_pipestat(dev_priv, PIPE_A, PIPE_CRC_DONE_ENABLE);
-       i915_enable_pipestat(dev_priv, PIPE_B, PIPE_CRC_DONE_ENABLE);
+       i915_enable_pipestat(dev_priv, PIPE_A, PIPE_CRC_DONE_INTERRUPT_STATUS);
+       i915_enable_pipestat(dev_priv, PIPE_B, PIPE_CRC_DONE_INTERRUPT_STATUS);
        spin_unlock_irqrestore(&dev_priv->irq_lock, irqflags);
  
        return 0;
@@@ -3564,9 -3669,9 +3668,9 @@@ static int i965_irq_postinstall(struct 
        /* Interrupt setup is already guaranteed to be single-threaded, this is
         * just to make the assert_spin_locked check happy. */
        spin_lock_irqsave(&dev_priv->irq_lock, irqflags);
-       i915_enable_pipestat(dev_priv, PIPE_A, PIPE_GMBUS_EVENT_ENABLE);
-       i915_enable_pipestat(dev_priv, PIPE_A, PIPE_CRC_DONE_ENABLE);
-       i915_enable_pipestat(dev_priv, PIPE_B, PIPE_CRC_DONE_ENABLE);
+       i915_enable_pipestat(dev_priv, PIPE_A, PIPE_GMBUS_INTERRUPT_STATUS);
+       i915_enable_pipestat(dev_priv, PIPE_A, PIPE_CRC_DONE_INTERRUPT_STATUS);
+       i915_enable_pipestat(dev_priv, PIPE_B, PIPE_CRC_DONE_INTERRUPT_STATUS);
        spin_unlock_irqrestore(&dev_priv->irq_lock, irqflags);
  
        /*
index 0f4cbd0aa59e03cd2ea1030d09069a97ee5cd25e,e0b7d06687f71a4356b8866c4757d2aabc64f64c..f19e6ea36dc4f0eb28462d8744fb6d51b97d5951
@@@ -51,7 -51,10 +51,10 @@@ static void ironlake_pch_clock_get(stru
  
  static int intel_set_mode(struct drm_crtc *crtc, struct drm_display_mode *mode,
                          int x, int y, struct drm_framebuffer *old_fb);
+ static int intel_framebuffer_init(struct drm_device *dev,
+                                 struct intel_framebuffer *ifb,
+                                 struct drm_mode_fb_cmd2 *mode_cmd,
+                                 struct drm_i915_gem_object *obj);
  
  typedef struct {
        int     min, max;
@@@ -1030,7 -1033,7 +1033,7 @@@ static void assert_fdi_tx_pll_enabled(s
        u32 val;
  
        /* ILK FDI PLL is always enabled */
-       if (dev_priv->info->gen == 5)
+       if (INTEL_INFO(dev_priv->dev)->gen == 5)
                return;
  
        /* On Haswell, DDI ports are responsible for the FDI PLL setup */
@@@ -1189,7 -1192,7 +1192,7 @@@ static void assert_sprites_disabled(str
        u32 val;
  
        if (IS_VALLEYVIEW(dev)) {
-               for (i = 0; i < dev_priv->num_plane; i++) {
+               for (i = 0; i < INTEL_INFO(dev)->num_sprites; i++) {
                        reg = SPCNTR(pipe, i);
                        val = I915_READ(reg);
                        WARN((val & SP_ENABLE),
@@@ -1443,7 -1446,7 +1446,7 @@@ static void i9xx_enable_pll(struct inte
        assert_pipe_disabled(dev_priv, crtc->pipe);
  
        /* No really, not for ILK+ */
-       BUG_ON(dev_priv->info->gen >= 5);
+       BUG_ON(INTEL_INFO(dev)->gen >= 5);
  
        /* PLL is protected by panel, make sure we can write it */
        if (IS_MOBILE(dev) && !IS_I830(dev))
@@@ -1549,11 -1552,12 +1552,12 @@@ void vlv_wait_port_ready(struct drm_i91
   */
  static void ironlake_enable_shared_dpll(struct intel_crtc *crtc)
  {
-       struct drm_i915_private *dev_priv = crtc->base.dev->dev_private;
+       struct drm_device *dev = crtc->base.dev;
+       struct drm_i915_private *dev_priv = dev->dev_private;
        struct intel_shared_dpll *pll = intel_crtc_to_shared_dpll(crtc);
  
        /* PCH PLLs only available on ILK, SNB and IVB */
-       BUG_ON(dev_priv->info->gen < 5);
+       BUG_ON(INTEL_INFO(dev)->gen < 5);
        if (WARN_ON(pll == NULL))
                return;
  
  
  static void intel_disable_shared_dpll(struct intel_crtc *crtc)
  {
-       struct drm_i915_private *dev_priv = crtc->base.dev->dev_private;
+       struct drm_device *dev = crtc->base.dev;
+       struct drm_i915_private *dev_priv = dev->dev_private;
        struct intel_shared_dpll *pll = intel_crtc_to_shared_dpll(crtc);
  
        /* PCH only available on ILK+ */
-       BUG_ON(dev_priv->info->gen < 5);
+       BUG_ON(INTEL_INFO(dev)->gen < 5);
        if (WARN_ON(pll == NULL))
               return;
  
@@@ -1617,7 -1622,7 +1622,7 @@@ static void ironlake_enable_pch_transco
        uint32_t reg, val, pipeconf_val;
  
        /* PCH only available on ILK+ */
-       BUG_ON(dev_priv->info->gen < 5);
+       BUG_ON(INTEL_INFO(dev)->gen < 5);
  
        /* Make sure PCH DPLL is enabled */
        assert_shared_dpll_enabled(dev_priv,
@@@ -1670,7 -1675,7 +1675,7 @@@ static void lpt_enable_pch_transcoder(s
        u32 val, pipeconf_val;
  
        /* PCH only available on ILK+ */
-       BUG_ON(dev_priv->info->gen < 5);
+       BUG_ON(INTEL_INFO(dev_priv->dev)->gen < 5);
  
        /* FDI must be feeding us bits for PCH ports */
        assert_fdi_tx_enabled(dev_priv, (enum pipe) cpu_transcoder);
@@@ -1744,21 -1749,16 +1749,16 @@@ static void lpt_disable_pch_transcoder(
  
  /**
   * intel_enable_pipe - enable a pipe, asserting requirements
-  * @dev_priv: i915 private structure
-  * @pipe: pipe to enable
-  * @pch_port: on ILK+, is this pipe driving a PCH port or not
+  * @crtc: crtc responsible for the pipe
   *
-  * Enable @pipe, making sure that various hardware specific requirements
+  * Enable @crtc's pipe, making sure that various hardware specific requirements
   * are met, if applicable, e.g. PLL enabled, LVDS pairs enabled, etc.
-  *
-  * @pipe should be %PIPE_A or %PIPE_B.
-  *
-  * Will wait until the pipe is actually running (i.e. first vblank) before
-  * returning.
   */
- static void intel_enable_pipe(struct drm_i915_private *dev_priv, enum pipe pipe,
-                             bool pch_port, bool dsi)
+ static void intel_enable_pipe(struct intel_crtc *crtc)
  {
+       struct drm_device *dev = crtc->base.dev;
+       struct drm_i915_private *dev_priv = dev->dev_private;
+       enum pipe pipe = crtc->pipe;
        enum transcoder cpu_transcoder = intel_pipe_to_cpu_transcoder(dev_priv,
                                                                      pipe);
        enum pipe pch_transcoder;
         * need the check.
         */
        if (!HAS_PCH_SPLIT(dev_priv->dev))
-               if (dsi)
+               if (intel_pipe_has_type(&crtc->base, INTEL_OUTPUT_DSI))
                        assert_dsi_pll_enabled(dev_priv);
                else
                        assert_pll_enabled(dev_priv, pipe);
        else {
-               if (pch_port) {
+               if (crtc->config.has_pch_encoder) {
                        /* if driving the PCH, we need FDI enabled */
                        assert_fdi_rx_pll_enabled(dev_priv, pch_transcoder);
                        assert_fdi_tx_pll_enabled(dev_priv,
  
        reg = PIPECONF(cpu_transcoder);
        val = I915_READ(reg);
-       if (val & PIPECONF_ENABLE)
+       if (val & PIPECONF_ENABLE) {
+               WARN_ON(!(pipe == PIPE_A &&
+                         dev_priv->quirks & QUIRK_PIPEA_FORCE));
                return;
+       }
  
        I915_WRITE(reg, val | PIPECONF_ENABLE);
-       intel_wait_for_vblank(dev_priv->dev, pipe);
+       POSTING_READ(reg);
+       /*
+        * There's no guarantee the pipe will really start running now. It
+        * depends on the Gen, the output type and the relative order between
+        * pipe and plane enabling. Avoid waiting on HSW+ since it's not
+        * necessary.
+        * TODO: audit the previous gens.
+        */
+       if (INTEL_INFO(dev)->gen <= 7 && !IS_HASWELL(dev))
+               intel_wait_for_vblank(dev_priv->dev, pipe);
  }
  
  /**
@@@ -1851,7 -1864,8 +1864,8 @@@ static void intel_disable_pipe(struct d
  void intel_flush_primary_plane(struct drm_i915_private *dev_priv,
                               enum plane plane)
  {
-       u32 reg = dev_priv->info->gen >= 4 ? DSPSURF(plane) : DSPADDR(plane);
+       struct drm_device *dev = dev_priv->dev;
+       u32 reg = INTEL_INFO(dev)->gen >= 4 ? DSPSURF(plane) : DSPADDR(plane);
  
        I915_WRITE(reg, I915_READ(reg));
        POSTING_READ(reg);
@@@ -1929,6 -1943,14 +1943,14 @@@ static bool need_vtd_wa(struct drm_devi
        return false;
  }
  
+ static int intel_align_height(struct drm_device *dev, int height, bool tiled)
+ {
+       int tile_height;
+       tile_height = tiled ? (IS_GEN2(dev) ? 16 : 8) : 1;
+       return ALIGN(height, tile_height);
+ }
  int
  intel_pin_and_fence_fb_obj(struct drm_device *dev,
                           struct drm_i915_gem_object *obj,
@@@ -2299,33 -2321,6 +2321,6 @@@ intel_finish_fb(struct drm_framebuffer 
        return ret;
  }
  
- static void intel_crtc_update_sarea_pos(struct drm_crtc *crtc, int x, int y)
- {
-       struct drm_device *dev = crtc->dev;
-       struct drm_i915_master_private *master_priv;
-       struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
-       if (!dev->primary->master)
-               return;
-       master_priv = dev->primary->master->driver_priv;
-       if (!master_priv->sarea_priv)
-               return;
-       switch (intel_crtc->pipe) {
-       case 0:
-               master_priv->sarea_priv->pipeA_x = x;
-               master_priv->sarea_priv->pipeA_y = y;
-               break;
-       case 1:
-               master_priv->sarea_priv->pipeB_x = x;
-               master_priv->sarea_priv->pipeB_y = y;
-               break;
-       default:
-               break;
-       }
- }
  static int
  intel_pipe_set_base(struct drm_crtc *crtc, int x, int y,
                    struct drm_framebuffer *fb)
        intel_edp_psr_update(dev);
        mutex_unlock(&dev->struct_mutex);
  
-       intel_crtc_update_sarea_pos(crtc, x, y);
        return 0;
  }
  
@@@ -3587,8 -3580,7 +3580,7 @@@ static void ironlake_crtc_enable(struc
        intel_crtc_load_lut(crtc);
  
        intel_update_watermarks(crtc);
-       intel_enable_pipe(dev_priv, pipe,
-                         intel_crtc->config.has_pch_encoder, false);
+       intel_enable_pipe(intel_crtc);
        intel_enable_primary_plane(dev_priv, plane, pipe);
        intel_enable_planes(crtc);
        intel_crtc_update_cursor(crtc, true);
@@@ -3733,8 -3725,7 +3725,7 @@@ static void haswell_crtc_enable(struct 
        intel_ddi_enable_transcoder_func(crtc);
  
        intel_update_watermarks(crtc);
-       intel_enable_pipe(dev_priv, pipe,
-                         intel_crtc->config.has_pch_encoder, false);
+       intel_enable_pipe(intel_crtc);
  
        if (intel_crtc->config.has_pch_encoder)
                lpt_pch_enable(crtc);
         * to change the workaround. */
        haswell_mode_set_planes_workaround(intel_crtc);
        haswell_crtc_enable_planes(crtc);
-       /*
-        * There seems to be a race in PCH platform hw (at least on some
-        * outputs) where an enabled pipe still completes any pageflip right
-        * away (as if the pipe is off) instead of waiting for vblank. As soon
-        * as the first vblank happend, everything works as expected. Hence just
-        * wait for one vblank before returning to avoid strange things
-        * happening.
-        */
-       intel_wait_for_vblank(dev, intel_crtc->pipe);
  }
  
  static void ironlake_pfit_disable(struct intel_crtc *crtc)
@@@ -4169,7 -4150,7 +4150,7 @@@ static void valleyview_crtc_enable(stru
        intel_crtc_load_lut(crtc);
  
        intel_update_watermarks(crtc);
-       intel_enable_pipe(dev_priv, pipe, false, is_dsi);
+       intel_enable_pipe(intel_crtc);
        intel_set_cpu_fifo_underrun_reporting(dev, pipe, true);
        intel_enable_primary_plane(dev_priv, plane, pipe);
        intel_enable_planes(crtc);
@@@ -4208,7 -4189,7 +4189,7 @@@ static void i9xx_crtc_enable(struct drm
        intel_crtc_load_lut(crtc);
  
        intel_update_watermarks(crtc);
-       intel_enable_pipe(dev_priv, pipe, false, false);
+       intel_enable_pipe(intel_crtc);
        intel_set_cpu_fifo_underrun_reporting(dev, pipe, true);
        intel_enable_primary_plane(dev_priv, plane, pipe);
        intel_enable_planes(crtc);
@@@ -5256,25 -5237,23 +5237,23 @@@ static void intel_get_pipe_timings(stru
        pipe_config->requested_mode.hdisplay = pipe_config->pipe_src_w;
  }
  
static void intel_crtc_mode_from_pipe_config(struct intel_crtc *intel_crtc,
-                                            struct intel_crtc_config *pipe_config)
void intel_mode_from_pipe_config(struct drm_display_mode *mode,
+                                struct intel_crtc_config *pipe_config)
  {
-       struct drm_crtc *crtc = &intel_crtc->base;
+       mode->hdisplay = pipe_config->adjusted_mode.crtc_hdisplay;
+       mode->htotal = pipe_config->adjusted_mode.crtc_htotal;
+       mode->hsync_start = pipe_config->adjusted_mode.crtc_hsync_start;
+       mode->hsync_end = pipe_config->adjusted_mode.crtc_hsync_end;
  
-       crtc->mode.hdisplay = pipe_config->adjusted_mode.crtc_hdisplay;
-       crtc->mode.htotal = pipe_config->adjusted_mode.crtc_htotal;
-       crtc->mode.hsync_start = pipe_config->adjusted_mode.crtc_hsync_start;
-       crtc->mode.hsync_end = pipe_config->adjusted_mode.crtc_hsync_end;
+       mode->vdisplay = pipe_config->adjusted_mode.crtc_vdisplay;
+       mode->vtotal = pipe_config->adjusted_mode.crtc_vtotal;
+       mode->vsync_start = pipe_config->adjusted_mode.crtc_vsync_start;
+       mode->vsync_end = pipe_config->adjusted_mode.crtc_vsync_end;
  
-       crtc->mode.vdisplay = pipe_config->adjusted_mode.crtc_vdisplay;
-       crtc->mode.vtotal = pipe_config->adjusted_mode.crtc_vtotal;
-       crtc->mode.vsync_start = pipe_config->adjusted_mode.crtc_vsync_start;
-       crtc->mode.vsync_end = pipe_config->adjusted_mode.crtc_vsync_end;
+       mode->flags = pipe_config->adjusted_mode.flags;
  
-       crtc->mode.flags = pipe_config->adjusted_mode.flags;
-       crtc->mode.clock = pipe_config->adjusted_mode.crtc_clock;
-       crtc->mode.flags |= pipe_config->adjusted_mode.flags;
+       mode->clock = pipe_config->adjusted_mode.crtc_clock;
+       mode->flags |= pipe_config->adjusted_mode.flags;
  }
  
  static void i9xx_set_pipeconf(struct intel_crtc *intel_crtc)
@@@ -7577,7 -7556,7 +7556,7 @@@ static int intel_crtc_cursor_set(struc
  
        /* we only need to pin inside GTT if cursor is non-phy */
        mutex_lock(&dev->struct_mutex);
-       if (!dev_priv->info->cursor_needs_physical) {
+       if (!INTEL_INFO(dev)->cursor_needs_physical) {
                unsigned alignment;
  
                if (obj->tiling_mode) {
  
   finish:
        if (intel_crtc->cursor_bo) {
-               if (dev_priv->info->cursor_needs_physical) {
+               if (INTEL_INFO(dev)->cursor_needs_physical) {
                        if (intel_crtc->cursor_bo != obj)
                                i915_gem_detach_phys_object(dev, intel_crtc->cursor_bo);
                } else
@@@ -7687,10 -7666,10 +7666,10 @@@ static struct drm_display_mode load_det
                 704, 832, 0, 480, 489, 491, 520, 0, DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC),
  };
  
- static struct drm_framebuffer *
- intel_framebuffer_create(struct drm_device *dev,
-                        struct drm_mode_fb_cmd2 *mode_cmd,
-                        struct drm_i915_gem_object *obj)
+ struct drm_framebuffer *
__intel_framebuffer_create(struct drm_device *dev,
+                          struct drm_mode_fb_cmd2 *mode_cmd,
+                          struct drm_i915_gem_object *obj)
  {
        struct intel_framebuffer *intel_fb;
        int ret;
                return ERR_PTR(-ENOMEM);
        }
  
-       ret = i915_mutex_lock_interruptible(dev);
-       if (ret)
-               goto err;
        ret = intel_framebuffer_init(dev, intel_fb, mode_cmd, obj);
-       mutex_unlock(&dev->struct_mutex);
        if (ret)
                goto err;
  
        return ERR_PTR(ret);
  }
  
+ struct drm_framebuffer *
+ intel_framebuffer_create(struct drm_device *dev,
+                        struct drm_mode_fb_cmd2 *mode_cmd,
+                        struct drm_i915_gem_object *obj)
+ {
+       struct drm_framebuffer *fb;
+       int ret;
+       ret = i915_mutex_lock_interruptible(dev);
+       if (ret)
+               return ERR_PTR(ret);
+       fb = __intel_framebuffer_create(dev, mode_cmd, obj);
+       mutex_unlock(&dev->struct_mutex);
+       return fb;
+ }
  static u32
  intel_framebuffer_pitch_for_width(int width, int bpp)
  {
@@@ -7763,14 -7754,16 +7754,16 @@@ mode_fits_in_fbdev(struct drm_device *d
        struct drm_i915_gem_object *obj;
        struct drm_framebuffer *fb;
  
-       if (dev_priv->fbdev == NULL)
+       if (!dev_priv->fbdev)
                return NULL;
  
-       obj = dev_priv->fbdev->ifb.obj;
-       if (obj == NULL)
+       if (!dev_priv->fbdev->fb)
                return NULL;
  
-       fb = &dev_priv->fbdev->ifb.base;
+       obj = dev_priv->fbdev->fb->obj;
+       BUG_ON(!obj);
+       fb = &dev_priv->fbdev->fb->base;
        if (fb->pitches[0] < intel_framebuffer_pitch_for_width(mode->hdisplay,
                                                               fb->bits_per_pixel))
                return NULL;
@@@ -8220,7 -8213,7 +8213,7 @@@ void intel_mark_idle(struct drm_device 
                intel_decrease_pllclock(crtc);
        }
  
-       if (dev_priv->info->gen >= 6)
+       if (INTEL_INFO(dev)->gen >= 6)
                gen6_rps_idle(dev->dev_private);
  }
  
@@@ -8595,20 -8588,6 +8588,20 @@@ static int intel_gen7_queue_flip(struc
        if (ring->id == RCS)
                len += 6;
  
 +      /*
 +       * BSpec MI_DISPLAY_FLIP for IVB:
 +       * "The full packet must be contained within the same cache line."
 +       *
 +       * Currently the LRI+SRM+MI_DISPLAY_FLIP all fit within the same
 +       * cacheline, if we ever start emitting more commands before
 +       * the MI_DISPLAY_FLIP we may need to first emit everything else,
 +       * then do the cacheline alignment, and finally emit the
 +       * MI_DISPLAY_FLIP.
 +       */
 +      ret = intel_ring_cacheline_align(ring);
 +      if (ret)
 +              goto err_unpin;
 +
        ret = intel_ring_begin(ring, len);
        if (ret)
                goto err_unpin;
@@@ -10384,8 -10363,7 +10377,7 @@@ static bool has_edp_a(struct drm_devic
        if ((I915_READ(DP_A) & DP_DETECTED) == 0)
                return false;
  
-       if (IS_GEN5(dev) &&
-           (I915_READ(ILK_DISPLAY_CHICKEN_FUSES) & ILK_eDP_A_DISABLE))
+       if (IS_GEN5(dev) && (I915_READ(FUSE_STRAP) & ILK_eDP_A_DISABLE))
                return false;
  
        return true;
@@@ -10538,18 -10516,13 +10530,13 @@@ static void intel_setup_outputs(struct 
        drm_helper_move_panel_connectors_to_head(dev);
  }
  
- void intel_framebuffer_fini(struct intel_framebuffer *fb)
- {
-       drm_framebuffer_cleanup(&fb->base);
-       WARN_ON(!fb->obj->framebuffer_references--);
-       drm_gem_object_unreference_unlocked(&fb->obj->base);
- }
  static void intel_user_framebuffer_destroy(struct drm_framebuffer *fb)
  {
        struct intel_framebuffer *intel_fb = to_intel_framebuffer(fb);
  
-       intel_framebuffer_fini(intel_fb);
+       drm_framebuffer_cleanup(fb);
+       WARN_ON(!intel_fb->obj->framebuffer_references--);
+       drm_gem_object_unreference_unlocked(&intel_fb->obj->base);
        kfree(intel_fb);
  }
  
@@@ -10573,7 -10546,7 +10560,7 @@@ int intel_framebuffer_init(struct drm_d
                           struct drm_mode_fb_cmd2 *mode_cmd,
                           struct drm_i915_gem_object *obj)
  {
-       int aligned_height, tile_height;
+       int aligned_height;
        int pitch_limit;
        int ret;
  
        if (mode_cmd->offsets[0] != 0)
                return -EINVAL;
  
-       tile_height = IS_GEN2(dev) ? 16 : 8;
-       aligned_height = ALIGN(mode_cmd->height,
-                              obj->tiling_mode ? tile_height : 1);
+       aligned_height = intel_align_height(dev, mode_cmd->height,
+                                           obj->tiling_mode);
        /* FIXME drm helper for size checks (especially planar formats)? */
        if (obj->base.size < aligned_height * mode_cmd->pitches[0])
                return -EINVAL;
@@@ -11049,7 -11021,7 +11035,7 @@@ void intel_modeset_init(struct drm_devi
  
        for_each_pipe(i) {
                intel_crtc_init(dev, i);
-               for (j = 0; j < dev_priv->num_plane; j++) {
+               for (j = 0; j < INTEL_INFO(dev)->num_sprites; j++) {
                        ret = intel_plane_init(dev, i, j);
                        if (ret)
                                DRM_DEBUG_KMS("pipe %c sprite %c init failed: %d\n",
  
        /* Just in case the BIOS is doing something questionable. */
        intel_disable_fbc(dev);
+       intel_modeset_setup_hw_state(dev, false);
  }
  
  static void
@@@ -11375,8 -11349,7 +11363,7 @@@ void intel_modeset_setup_hw_state(struc
        list_for_each_entry(crtc, &dev->mode_config.crtc_list,
                            base.head) {
                if (crtc->active && i915.fastboot) {
-                       intel_crtc_mode_from_pipe_config(crtc, &crtc->config);
+                       intel_mode_from_pipe_config(&crtc->base.mode, &crtc->config);
                        DRM_DEBUG_KMS("[CRTC:%d] found active mode: ",
                                      crtc->base.base.id);
                        drm_mode_debug_printmodeline(&crtc->base.mode);
@@@ -11436,10 -11409,14 +11423,14 @@@ void intel_modeset_gem_init(struct drm_
        intel_modeset_init_hw(dev);
  
        intel_setup_overlay(dev);
+ }
  
-       mutex_lock(&dev->mode_config.mutex);
-       intel_modeset_setup_hw_state(dev, false);
-       mutex_unlock(&dev->mode_config.mutex);
+ void intel_connector_unregister(struct intel_connector *intel_connector)
+ {
+       struct drm_connector *connector = &intel_connector->base;
+       intel_panel_destroy_backlight(connector);
+       drm_sysfs_connector_remove(connector);
  }
  
  void intel_modeset_cleanup(struct drm_device *dev)
  
        /* destroy the backlight and sysfs files before encoders/connectors */
        list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
-               intel_panel_destroy_backlight(connector);
-               drm_sysfs_connector_remove(connector);
+               struct intel_connector *intel_connector;
+               intel_connector = to_intel_connector(connector);
+               intel_connector->unregister(intel_connector);
        }
  
        drm_mode_config_cleanup(dev);
@@@ -11520,12 -11499,24 +11513,24 @@@ int intel_modeset_vga_set_state(struct 
        unsigned reg = INTEL_INFO(dev)->gen >= 6 ? SNB_GMCH_CTRL : INTEL_GMCH_CTRL;
        u16 gmch_ctrl;
  
-       pci_read_config_word(dev_priv->bridge_dev, reg, &gmch_ctrl);
+       if (pci_read_config_word(dev_priv->bridge_dev, reg, &gmch_ctrl)) {
+               DRM_ERROR("failed to read control word\n");
+               return -EIO;
+       }
+       if (!!(gmch_ctrl & INTEL_GMCH_VGA_DISABLE) == !state)
+               return 0;
        if (state)
                gmch_ctrl &= ~INTEL_GMCH_VGA_DISABLE;
        else
                gmch_ctrl |= INTEL_GMCH_VGA_DISABLE;
-       pci_write_config_word(dev_priv->bridge_dev, reg, gmch_ctrl);
+       if (pci_write_config_word(dev_priv->bridge_dev, reg, gmch_ctrl)) {
+               DRM_ERROR("failed to write control word\n");
+               return -EIO;
+       }
        return 0;
  }
  
index bd1df502bc34faaf36effec0665d45d5019f20a8,1ac4b11765c722c33522b068dc2d9542ca2b221f..c512d78af271aff044ad853f0cdeb8f0ed002fa1
@@@ -459,7 -459,7 +459,7 @@@ intel_dp_aux_ch(struct intel_dp *intel_
        int i, ret, recv_bytes;
        uint32_t status;
        int try, clock = 0;
 -      bool has_aux_irq = true;
 +      bool has_aux_irq = HAS_AUX_IRQ(dev);
  
        /* dp aux is extremely sensitive to irq latency, hence request the
         * lowest possible wakeup latency and so prevent the cpu from going into
@@@ -577,7 -577,6 +577,7 @@@ intel_dp_aux_native_write(struct intel_
        uint8_t msg[20];
        int msg_bytes;
        uint8_t ack;
 +      int retry;
  
        if (WARN_ON(send_bytes > 16))
                return -E2BIG;
        msg[3] = send_bytes - 1;
        memcpy(&msg[4], send, send_bytes);
        msg_bytes = send_bytes + 4;
 -      for (;;) {
 +      for (retry = 0; retry < 7; retry++) {
                ret = intel_dp_aux_ch(intel_dp, msg, msg_bytes, &ack, 1);
                if (ret < 0)
                        return ret;
                ack >>= 4;
                if ((ack & DP_AUX_NATIVE_REPLY_MASK) == DP_AUX_NATIVE_REPLY_ACK)
 -                      break;
 +                      return send_bytes;
                else if ((ack & DP_AUX_NATIVE_REPLY_MASK) == DP_AUX_NATIVE_REPLY_DEFER)
 -                      udelay(100);
 +                      usleep_range(400, 500);
                else
                        return -EIO;
        }
 -      return send_bytes;
 +
 +      DRM_ERROR("too many retries, giving up\n");
 +      return -EIO;
  }
  
  /* Write a single byte to the aux channel in native mode */
@@@ -625,7 -622,6 +625,7 @@@ intel_dp_aux_native_read(struct intel_d
        int reply_bytes;
        uint8_t ack;
        int ret;
 +      int retry;
  
        if (WARN_ON(recv_bytes > 19))
                return -E2BIG;
        msg_bytes = 4;
        reply_bytes = recv_bytes + 1;
  
 -      for (;;) {
 +      for (retry = 0; retry < 7; retry++) {
                ret = intel_dp_aux_ch(intel_dp, msg, msg_bytes,
                                      reply, reply_bytes);
                if (ret == 0)
                        return ret - 1;
                }
                else if ((ack & DP_AUX_NATIVE_REPLY_MASK) == DP_AUX_NATIVE_REPLY_DEFER)
 -                      udelay(100);
 +                      usleep_range(400, 500);
                else
                        return -EIO;
        }
 +
 +      DRM_ERROR("too many retries, giving up\n");
 +      return -EIO;
  }
  
  static int
@@@ -784,6 -777,16 +784,16 @@@ out
        return ret;
  }
  
+ static void
+ intel_dp_connector_unregister(struct intel_connector *intel_connector)
+ {
+       struct intel_dp *intel_dp = intel_attached_dp(&intel_connector->base);
+       sysfs_remove_link(&intel_connector->base.kdev->kobj,
+                         intel_dp->adapter.dev.kobj.name);
+       intel_connector_unregister(intel_connector);
+ }
  static int
  intel_dp_i2c_init(struct intel_dp *intel_dp,
                  struct intel_connector *intel_connector, const char *name)
        strncpy(intel_dp->adapter.name, name, sizeof(intel_dp->adapter.name) - 1);
        intel_dp->adapter.name[sizeof(intel_dp->adapter.name) - 1] = '\0';
        intel_dp->adapter.algo_data = &intel_dp->algo;
-       intel_dp->adapter.dev.parent = intel_connector->base.kdev;
+       intel_dp->adapter.dev.parent = intel_connector->base.dev->dev;
  
        ret = i2c_dp_aux_add_bus(&intel_dp->adapter);
+       if (ret < 0)
+               return ret;
+       ret = sysfs_create_link(&intel_connector->base.kdev->kobj,
+                               &intel_dp->adapter.dev.kobj,
+                               intel_dp->adapter.dev.kobj.name);
+       if (ret < 0)
+               i2c_del_adapter(&intel_dp->adapter);
        return ret;
  }
  
@@@ -1940,12 -1953,10 +1960,12 @@@ static void vlv_pre_enable_dp(struct in
  
        mutex_unlock(&dev_priv->dpio_lock);
  
 -      /* init power sequencer on this pipe and port */
 -      intel_dp_init_panel_power_sequencer(dev, intel_dp, &power_seq);
 -      intel_dp_init_panel_power_sequencer_registers(dev, intel_dp,
 -                                                    &power_seq);
 +      if (is_edp(intel_dp)) {
 +              /* init power sequencer on this pipe and port */
 +              intel_dp_init_panel_power_sequencer(dev, intel_dp, &power_seq);
 +              intel_dp_init_panel_power_sequencer_registers(dev, intel_dp,
 +                                                            &power_seq);
 +      }
  
        intel_enable_dp(encoder);
  
@@@ -3739,7 -3750,7 +3759,7 @@@ static bool intel_edp_init_connector(st
                        fixed_mode->type |= DRM_MODE_TYPE_PREFERRED;
        }
  
-       intel_panel_init(&intel_connector->panel, fixed_mode);
+       intel_panel_init(&intel_connector->panel, fixed_mode, NULL);
        intel_panel_setup_backlight(connector);
  
        return true;
@@@ -3808,6 -3819,7 +3828,7 @@@ intel_dp_init_connector(struct intel_di
                intel_connector->get_hw_state = intel_ddi_connector_get_hw_state;
        else
                intel_connector->get_hw_state = intel_connector_get_hw_state;
+       intel_connector->unregister = intel_dp_connector_unregister;
  
        intel_dp->aux_ch_ctl_reg = intel_dp->output_reg + 0x10;
        if (HAS_DDI(dev)) {
index 8c1c0bc3e630868ca98980bab93a6f6d75fac5cf,76162acf70155f3fed53926dab410e15a287977b..b340c7587629379a34f4db7753a87e25d7a7728f
@@@ -531,9 -531,11 +531,11 @@@ init_pipe_control(struct intel_ring_buf
                goto err;
        }
  
-       i915_gem_object_set_cache_level(ring->scratch.obj, I915_CACHE_LLC);
+       ret = i915_gem_object_set_cache_level(ring->scratch.obj, I915_CACHE_LLC);
+       if (ret)
+               goto err_unref;
  
-       ret = i915_gem_obj_ggtt_pin(ring->scratch.obj, 4096, true, false);
+       ret = i915_gem_obj_ggtt_pin(ring->scratch.obj, 4096, 0);
        if (ret)
                goto err_unref;
  
@@@ -1271,12 -1273,13 +1273,13 @@@ static int init_status_page(struct inte
                goto err;
        }
  
-       i915_gem_object_set_cache_level(obj, I915_CACHE_LLC);
+       ret = i915_gem_object_set_cache_level(obj, I915_CACHE_LLC);
+       if (ret)
+               goto err_unref;
  
-       ret = i915_gem_obj_ggtt_pin(obj, 4096, true, false);
-       if (ret != 0) {
+       ret = i915_gem_obj_ggtt_pin(obj, 4096, 0);
+       if (ret)
                goto err_unref;
-       }
  
        ring->status_page.gfx_addr = i915_gem_obj_ggtt_offset(obj);
        ring->status_page.page_addr = kmap(sg_page(obj->pages->sgl));
@@@ -1356,7 -1359,7 +1359,7 @@@ static int intel_init_ring_buffer(struc
  
        ring->obj = obj;
  
-       ret = i915_gem_obj_ggtt_pin(obj, PAGE_SIZE, true, false);
+       ret = i915_gem_obj_ggtt_pin(obj, PAGE_SIZE, PIN_MAPPABLE);
        if (ret)
                goto err_unref;
  
@@@ -1513,7 -1516,8 +1516,8 @@@ static int ring_wait_for_space(struct i
                        return 0;
                }
  
-               if (dev->primary->master) {
+               if (!drm_core_check_feature(dev, DRIVER_MODESET) &&
+                   dev->primary->master) {
                        struct drm_i915_master_private *master_priv = dev->primary->master->driver_priv;
                        if (master_priv->sarea_priv)
                                master_priv->sarea_priv->perf_boxes |= I915_BOX_WAIT;
@@@ -1638,27 -1642,6 +1642,27 @@@ int intel_ring_begin(struct intel_ring_
        return 0;
  }
  
 +/* Align the ring tail to a cacheline boundary */
 +int intel_ring_cacheline_align(struct intel_ring_buffer *ring)
 +{
 +      int num_dwords = (64 - (ring->tail & 63)) / sizeof(uint32_t);
 +      int ret;
 +
 +      if (num_dwords == 0)
 +              return 0;
 +
 +      ret = intel_ring_begin(ring, num_dwords);
 +      if (ret)
 +              return ret;
 +
 +      while (num_dwords--)
 +              intel_ring_emit(ring, MI_NOOP);
 +
 +      intel_ring_advance(ring);
 +
 +      return 0;
 +}
 +
  void intel_ring_init_seqno(struct intel_ring_buffer *ring, u32 seqno)
  {
        struct drm_i915_private *dev_priv = ring->dev->dev_private;
@@@ -1939,7 -1922,7 +1943,7 @@@ int intel_init_render_ring_buffer(struc
                        return -ENOMEM;
                }
  
-               ret = i915_gem_obj_ggtt_pin(obj, 0, true, false);
+               ret = i915_gem_obj_ggtt_pin(obj, 0, 0);
                if (ret != 0) {
                        drm_gem_object_unreference(&obj->base);
                        DRM_ERROR("Failed to ping batch bo\n");
diff --combined include/drm/drm_crtc.h
index 8f3dee09757999c7c959e284250142c143d37d7d,ce9ee60f4d68a8b72ddaebef0c9df1c425e1c207..f7646548660d7e98e160d2dac40d1f12b310a48d
@@@ -907,9 -907,6 +907,9 @@@ struct drm_mode_config 
  
        /* whether async page flip is supported or not */
        bool async_page_flip;
 +
 +      /* cursor size */
 +      uint32_t cursor_width, cursor_height;
  };
  
  #define obj_to_crtc(x) container_of(x, struct drm_crtc, base)
@@@ -994,6 -991,7 +994,7 @@@ extern void drm_encoder_cleanup(struct 
  
  extern const char *drm_get_connector_name(const struct drm_connector *connector);
  extern const char *drm_get_connector_status_name(enum drm_connector_status status);
+ extern const char *drm_get_subpixel_order_name(enum subpixel_order order);
  extern const char *drm_get_dpms_name(int val);
  extern const char *drm_get_dvi_i_subconnector_name(int val);
  extern const char *drm_get_dvi_i_select_name(int val);