]> Git Repo - linux.git/commitdiff
Merge tag 'drm-intel-next-2014-09-05' of git://anongit.freedesktop.org/drm-intel...
authorDave Airlie <[email protected]>
Tue, 16 Sep 2014 06:02:09 +0000 (16:02 +1000)
committerDave Airlie <[email protected]>
Tue, 16 Sep 2014 06:02:09 +0000 (16:02 +1000)
- final bits (again) for the rotation support (Sonika Jindal)
- support bl_power in the intel backlight (Jani)
- vdd handling improvements from Ville
- i830M fixes from Ville
- piles of prep work all over to make skl enabling just plug in (Damien, Sonika)
- rename DP training defines to reflect latest edp standards, this touches all
  drm drivers supporting DP (Sonika Jindal)
- cache edids during single detect cycle to avoid re-reading it for e.g. audio,
  from Chris
- move w/a for registers which are stored in the hw context to the context init
  code (Arun&Damien)
- edp panel power sequencer fixes, helps chv a lot (Ville)
- piles of other chv fixes all over
- much more paranoid pageflip handling with stall detection and better recovery
  from Chris
- small things all over, as usual

* tag 'drm-intel-next-2014-09-05' of git://anongit.freedesktop.org/drm-intel: (114 commits)
  drm/i915: Update DRIVER_DATE to 20140905
  drm/i915: Decouple the stuck pageflip on modeset
  drm/i915: Check for a stalled page flip after each vblank
  drm/i915: Introduce a for_each_plane() macro
  drm/i915: Rewrite ABS_DIFF() in a safer manner
  drm/i915: Add comments explaining the vdd on/off functions
  drm/i915: Move DP port disable to post_disable for pch platforms
  drm/i915: Enable DP port earlier
  drm/i915: Turn on panel power before doing aux transfers
  drm/i915: Be more careful when picking the initial power sequencer pipe
  drm/i915: Reset power sequencer pipe tracking when disp2d is off
  drm/i915: Track which port is using which pipe's power sequencer
  drm/i915: Fix edp vdd locking
  drm/i915: Reset the HEAD pointer for the ring after writing START
  drm/i915: Fix unsafe vma iteration in i915_drop_caches
  drm/i915: init sprites with univeral plane init function
  drm/i915: Check of !HAS_PCH_SPLIT() in PCH transcoder funcs
  drm/i915: Use HAS_GMCH_DISPLAY un underrun reporting code
  drm/i915: Use IS_BROADWELL() instead of IS_GEN8() in forcewake code
  drm/i915: Don't call gen8_fbc_sw_flush() on chv
  ...

14 files changed:
1  2 
MAINTAINERS
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_irq.c
drivers/gpu/drm/i915/i915_reg.h
drivers/gpu/drm/i915/intel_bios.c
drivers/gpu/drm/i915/intel_display.c
drivers/gpu/drm/i915/intel_dp.c
drivers/gpu/drm/i915/intel_hdmi.c
drivers/gpu/drm/i915/intel_panel.c
drivers/gpu/drm/i915/intel_ringbuffer.c
drivers/gpu/drm/radeon/atombios_dp.c

diff --combined MAINTAINERS
index 809ecd680d8829f6148ababe654d30a7882b11fe,655e927c087e4d8e7d0783189def0bf314acc9f0..dd31933400e8d49b1e8de6c19da5d4be72fbd179
@@@ -1279,13 -1279,8 +1279,13 @@@ M:    Heiko Stuebner <[email protected]
  L:    [email protected] (moderated for non-subscribers)
  L:    [email protected]
  S:    Maintained
 +F:    arch/arm/boot/dts/rk3*
  F:    arch/arm/mach-rockchip/
 +F:    drivers/clk/rockchip/
 +F:    drivers/i2c/busses/i2c-rk3x.c
  F:    drivers/*/*rockchip*
 +F:    drivers/*/*/*rockchip*
 +F:    sound/soc/rockchip/
  
  ARM/SAMSUNG ARM ARCHITECTURES
  M:    Ben Dooks <[email protected]>
@@@ -3091,7 -3086,7 +3091,7 @@@ F:      include/drm/drm_panel.
  F:    Documentation/devicetree/bindings/panel/
  
  INTEL DRM DRIVERS (excluding Poulsbo, Moorestown and derivative chipsets)
- M:    Daniel Vetter <daniel.vetter@ffwll.ch>
+ M:    Daniel Vetter <daniel.vetter@intel.com>
  M:    Jani Nikula <[email protected]>
  L:    [email protected]
  L:    [email protected]
@@@ -6424,8 -6419,7 +6424,8 @@@ F:      Documentation/scsi/NinjaSCSI.tx
  F:    drivers/scsi/nsp32*
  
  NTB DRIVER
 -M:    Jon Mason <[email protected]>
 +M:    Jon Mason <[email protected]>
 +M:    Dave Jiang <[email protected]>
  S:    Supported
  W:    https://github.com/jonmason/ntb/wiki
  T:    git git://github.com/jonmason/ntb.git
@@@ -7054,7 -7048,7 +7054,7 @@@ S:      Maintaine
  F:    drivers/pinctrl/sh-pfc/
  
  PIN CONTROLLER - SAMSUNG
 -M:    Tomasz Figa <t.figa@samsung.com>
 +M:    Tomasz Figa <tomasz.figa@gmail.com>
  M:    Thomas Abraham <[email protected]>
  L:    [email protected] (moderated for non-subscribers)
  L:    [email protected] (moderated for non-subscribers)
@@@ -7900,8 -7894,7 +7900,8 @@@ S:      Supporte
  F:    drivers/media/i2c/s5k5baf.c
  
  SAMSUNG SOC CLOCK DRIVERS
 -M:    Tomasz Figa <[email protected]>
 +M:    Sylwester Nawrocki <[email protected]>
 +M:    Tomasz Figa <[email protected]>
  S:    Supported
  L:    [email protected] (moderated for non-subscribers)
  F:    drivers/clk/samsung/
@@@ -7914,19 -7907,6 +7914,19 @@@ S:    Supporte
  L:    [email protected]
  F:    drivers/net/ethernet/samsung/sxgbe/
  
 +SAMSUNG USB2 PHY DRIVER
 +M:    Kamil Debski <[email protected]>
 +L:    [email protected]
 +S:    Supported
 +F:    Documentation/devicetree/bindings/phy/samsung-phy.txt
 +F:    Documentation/phy/samsung-usb2.txt
 +F:    drivers/phy/phy-exynos4210-usb2.c
 +F:    drivers/phy/phy-exynos4x12-usb2.c
 +F:    drivers/phy/phy-exynos5250-usb2.c
 +F:    drivers/phy/phy-s5pv210-usb2.c
 +F:    drivers/phy/phy-samsung-usb2.c
 +F:    drivers/phy/phy-samsung-usb2.h
 +
  SERIAL DRIVERS
  M:    Greg Kroah-Hartman <[email protected]>
  L:    [email protected]
@@@ -9577,14 -9557,6 +9577,14 @@@ S:    Maintaine
  F:    Documentation/usb/ohci.txt
  F:    drivers/usb/host/ohci*
  
 +USB OVER IP DRIVER
 +M:    Valentina Manea <[email protected]>
 +M:    Shuah Khan <[email protected]>
 +L:    [email protected]
 +S:    Maintained
 +F:    drivers/usb/usbip/
 +F:    tools/usb/usbip/
 +
  USB PEGASUS DRIVER
  M:    Petko Manolov <[email protected]>
  L:    [email protected]
@@@ -10085,9 -10057,9 +10085,9 @@@ F:   Documentation/x86
  F:    arch/x86/
  
  X86 PLATFORM DRIVERS
 -M:    Matthew Garrett <[email protected]>
 +M:    Darren Hart <[email protected]>
  L:    [email protected]
 -T:    git git://cavan.codon.org.uk/platform-drivers-x86.git
 +T:    git git://git.infradead.org/users/dvhart/linux-platform-drivers-x86.git
  S:    Maintained
  F:    drivers/platform/x86/
  
index 272d3d16147cee0e96c7fbb7c7b50f4b4f5a1cf8,a58fed951ddbb4cba1cc6c3aef62bda15fac0879..1403b01e821695cce6c42cb8b3704eb284aba17e
  
  #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
  
+ #include <linux/async.h>
  #include <drm/drmP.h>
  #include <drm/drm_crtc_helper.h>
  #include <drm/drm_fb_helper.h>
 +#include <drm/drm_legacy.h>
  #include "intel_drv.h"
  #include <drm/i915_drm.h>
  #include "i915_drv.h"
@@@ -197,7 -197,7 +198,7 @@@ static int i915_initialize(struct drm_d
        struct drm_i915_master_private *master_priv = dev->primary->master->driver_priv;
        int ret;
  
 -      master_priv->sarea = drm_getsarea(dev);
 +      master_priv->sarea = drm_legacy_getsarea(dev);
        if (master_priv->sarea) {
                master_priv->sarea_priv = (drm_i915_sarea_t *)
                        ((u8 *)master_priv->sarea->handle + init->sarea_priv_offset);
@@@ -1337,17 -1337,12 +1338,17 @@@ static int i915_load_modeset_init(struc
  
        intel_power_domains_init_hw(dev_priv);
  
 +      /*
 +       * We enable some interrupt sources in our postinstall hooks, so mark
 +       * interrupts as enabled _before_ actually enabling them to avoid
 +       * special cases in our ordering checks.
 +       */
 +      dev_priv->pm._irqs_disabled = false;
 +
        ret = drm_irq_install(dev, dev->pdev->irq);
        if (ret)
                goto cleanup_gem_stolen;
  
 -      dev_priv->pm._irqs_disabled = false;
 -
        /* Important: The output setup functions called by modeset_init need
         * working irqs for e.g. gmbus and dp aux transfers. */
        intel_modeset_init(dev);
         * scanning against hotplug events. Hence do this first and ignore the
         * tiny window where we will loose hotplug notifactions.
         */
-       intel_fbdev_initial_config(dev);
+       async_schedule(intel_fbdev_initial_config, dev_priv);
  
        drm_kms_helper_poll_init(dev);
  
@@@ -1534,10 -1529,10 +1535,10 @@@ static void intel_device_info_runtime_i
        info = (struct intel_device_info *)&dev_priv->info;
  
        if (IS_VALLEYVIEW(dev))
-               for_each_pipe(pipe)
+               for_each_pipe(dev_priv, pipe)
                        info->num_sprites[pipe] = 2;
        else
-               for_each_pipe(pipe)
+               for_each_pipe(dev_priv, pipe)
                        info->num_sprites[pipe] = 1;
  
        if (i915.disable_display) {
index cdd95956811d4f5431b005cab9f73fe68fb7bdc1,8ff375538b5d92dbe33c5ad61598c9fcca1e7fbd..3870c7359a161c854ed90bcf4179e4fb051a70d4
@@@ -844,7 -844,13 +844,13 @@@ int i915_reset(struct drm_device *dev
                        !dev_priv->ums.mm_suspended) {
                dev_priv->ums.mm_suspended = 0;
  
+               /* Used to prevent gem_check_wedged returning -EAGAIN during gpu reset */
+               dev_priv->gpu_error.reload_in_reset = true;
                ret = i915_gem_init_hw(dev);
+               dev_priv->gpu_error.reload_in_reset = false;
                mutex_unlock(&dev->struct_mutex);
                if (ret) {
                        DRM_ERROR("Failed hw init on reset %d\n", ret);
@@@ -1456,13 -1462,29 +1462,29 @@@ static int intel_runtime_suspend(struc
        dev_priv->pm.suspended = true;
  
        /*
-        * current versions of firmware which depend on this opregion
-        * notification have repurposed the D1 definition to mean
-        * "runtime suspended" vs. what you would normally expect (D3)
-        * to distinguish it from notifications that might be sent
-        * via the suspend path.
+        * FIXME: We really should find a document that references the arguments
+        * used below!
         */
-       intel_opregion_notify_adapter(dev, PCI_D1);
+       if (IS_HASWELL(dev)) {
+               /*
+                * current versions of firmware which depend on this opregion
+                * notification have repurposed the D1 definition to mean
+                * "runtime suspended" vs. what you would normally expect (D3)
+                * to distinguish it from notifications that might be sent via
+                * the suspend path.
+                */
+               intel_opregion_notify_adapter(dev, PCI_D1);
+       } else {
+               /*
+                * On Broadwell, if we use PCI_D1 the PCH DDI ports will stop
+                * being detected, and the call we do at intel_runtime_resume()
+                * won't be able to restore them. Since PCI_D3hot matches the
+                * actual specification and appears to be working, use it. Let's
+                * assume the other non-Haswell platforms will stay the same as
+                * Broadwell.
+                */
+               intel_opregion_notify_adapter(dev, PCI_D3hot);
+       }
  
        DRM_DEBUG_KMS("Device suspended\n");
        return 0;
@@@ -1593,7 -1615,6 +1615,7 @@@ static struct drm_driver driver = 
        .lastclose = i915_driver_lastclose,
        .preclose = i915_driver_preclose,
        .postclose = i915_driver_postclose,
 +      .set_busid = drm_pci_set_busid,
  
        /* Used in place of i915_pm_ops for non-DRIVER_MODESET */
        .suspend = i915_suspend,
@@@ -1685,6 -1706,8 +1707,8 @@@ static void __exit i915_exit(void
  module_init(i915_init);
  module_exit(i915_exit);
  
- MODULE_AUTHOR(DRIVER_AUTHOR);
+ MODULE_AUTHOR("Tungsten Graphics, Inc.");
+ MODULE_AUTHOR("Intel Corporation");
  MODULE_DESCRIPTION(DRIVER_DESC);
  MODULE_LICENSE("GPL and additional rights");
index 357913c4f2c6a256b4acc24cadbdab02c525af3d,b52d7b60e49d3b3cfa483c8661a8bdbc5f1f2ec4..88a8b72b553e8e0e46e8692f56569d6bf2c0d148
  #include "intel_ringbuffer.h"
  #include "intel_lrc.h"
  #include "i915_gem_gtt.h"
+ #include "i915_gem_render_state.h"
  #include <linux/io-mapping.h>
  #include <linux/i2c.h>
  #include <linux/i2c-algo-bit.h>
  #include <drm/intel-gtt.h>
 +#include <drm/drm_legacy.h> /* for struct drm_dma_handle */
  #include <linux/backlight.h>
  #include <linux/hashtable.h>
  #include <linux/intel-iommu.h>
  /* General customization:
   */
  
- #define DRIVER_AUTHOR         "Tungsten Graphics, Inc."
  #define DRIVER_NAME           "i915"
  #define DRIVER_DESC           "Intel Graphics"
- #define DRIVER_DATE           "20140822"
+ #define DRIVER_DATE           "20140905"
  
  enum pipe {
        INVALID_PIPE = -1,
@@@ -164,7 -162,10 +163,10 @@@ enum hpd_pin 
         I915_GEM_DOMAIN_INSTRUCTION | \
         I915_GEM_DOMAIN_VERTEX)
  
- #define for_each_pipe(p) for ((p) = 0; (p) < INTEL_INFO(dev)->num_pipes; (p)++)
+ #define for_each_pipe(__dev_priv, __p) \
+       for ((__p) = 0; (__p) < INTEL_INFO(__dev_priv)->num_pipes; (__p)++)
+ #define for_each_plane(pipe, p) \
+       for ((p) = 0; (p) < INTEL_INFO(dev)->num_sprites[(pipe)] + 1; (p)++)
  #define for_each_sprite(p, s) for ((s) = 0; (s) < INTEL_INFO(dev)->num_sprites[(p)]; (s)++)
  
  #define for_each_crtc(dev, crtc) \
                if ((1 << (domain)) & (mask))
  
  struct drm_i915_private;
 +struct i915_mm_struct;
  struct i915_mmu_object;
  
  enum intel_dpll_id {
@@@ -287,10 -287,8 +289,10 @@@ struct intel_opregion 
  struct intel_overlay;
  struct intel_overlay_error_state;
  
 +struct drm_local_map;
 +
  struct drm_i915_master_private {
 -      drm_local_map_t *sarea;
 +      struct drm_local_map *sarea;
        struct _drm_i915_sarea *sarea_priv;
  };
  #define I915_FENCE_REG_NONE -1
@@@ -639,6 -637,7 +641,7 @@@ struct intel_context 
        } legacy_hw_ctx;
  
        /* Execlists */
+       bool rcs_initialized;
        struct {
                struct drm_i915_gem_object *state;
                struct intel_ringbuffer *ringbuf;
@@@ -712,6 -711,7 +715,7 @@@ enum intel_sbi_destination 
  #define QUIRK_LVDS_SSC_DISABLE (1<<1)
  #define QUIRK_INVERT_BRIGHTNESS (1<<2)
  #define QUIRK_BACKLIGHT_PRESENT (1<<3)
+ #define QUIRK_PIPEB_FORCE (1<<4)
  
  struct intel_fbdev;
  struct intel_fbc_work;
@@@ -941,6 -941,23 +945,23 @@@ struct intel_rps_ei 
        u32 media_c0;
  };
  
+ struct intel_rps_bdw_cal {
+       u32 it_threshold_pct; /* interrupt, in percentage */
+       u32 eval_interval; /* evaluation interval, in us */
+       u32 last_ts;
+       u32 last_c0;
+       bool is_up;
+ };
+ struct intel_rps_bdw_turbo {
+       struct intel_rps_bdw_cal up;
+       struct intel_rps_bdw_cal down;
+       struct timer_list flip_timer;
+       u32 timeout;
+       atomic_t flip_received;
+       struct work_struct work_max_freq;
+ };
  struct intel_gen6_power_mgmt {
        /* work and pm_iir are protected by dev_priv->irq_lock */
        struct work_struct work;
        bool enabled;
        struct delayed_work delayed_resume_work;
  
+       bool is_bdw_sw_turbo;   /* Switch of BDW software turbo */
+       struct intel_rps_bdw_turbo sw_turbo; /* Calculate RP interrupt timing */
        /* manual wa residency calculations */
        struct intel_rps_ei up_ei, down_ei;
  
@@@ -1171,6 -1191,7 +1195,7 @@@ struct i915_gem_mm 
  };
  
  struct drm_i915_error_state_buf {
+       struct drm_i915_private *i915;
        unsigned bytes;
        unsigned size;
        int err;
@@@ -1243,6 -1264,9 +1268,9 @@@ struct i915_gpu_error 
  
        /* For missed irq/seqno simulation. */
        unsigned int test_irq_rings;
+       /* Used to prevent gem_check_wedged returning -EAGAIN during gpu reset   */
+       bool reload_in_reset;
  };
  
  enum modeset_restore {
@@@ -1451,7 -1475,7 +1479,7 @@@ struct drm_i915_private 
        struct drm_i915_gem_object *semaphore_obj;
        uint32_t last_seqno, next_seqno;
  
 -      drm_dma_handle_t *status_page_dmah;
 +      struct drm_dma_handle *status_page_dmah;
        struct resource mch_res;
  
        /* protects the irq masks */
        /* LVDS info */
        bool no_aux_handshake;
  
+       /* protects panel power sequencer state */
+       struct mutex pps_mutex;
        struct drm_i915_fence_reg fence_regs[I915_MAX_NUM_FENCES]; /* assume 965 */
        int fence_reg_start; /* 4 if userland hasn't ioctl'd us yet */
        int num_fence_regs; /* 8 on pre-965, 16 otherwise */
        struct i915_gtt gtt; /* VM representing the global address space */
  
        struct i915_gem_mm mm;
 -#if defined(CONFIG_MMU_NOTIFIER)
 -      DECLARE_HASHTABLE(mmu_notifiers, 7);
 -#endif
 +      DECLARE_HASHTABLE(mm_structs, 7);
 +      struct mutex mm_lock;
  
        /* Kernel Modesetting */
  
        struct intel_shared_dpll shared_dplls[I915_NUM_PLLS];
        int dpio_phy_iosf_port[I915_NUM_PHYS_VLV];
  
+       /*
+        * workarounds are currently applied at different places and
+        * changes are being done to consolidate them so exact count is
+        * not clear at this point, use a max value for now.
+        */
+ #define I915_MAX_WA_REGS  16
+       struct {
+               u32 addr;
+               u32 value;
+               /* bitmask representing WA bits */
+               u32 mask;
+       } intel_wa_regs[I915_MAX_WA_REGS];
+       u32 num_wa_regs;
        /* Reclocking support */
        bool render_reclock_avail;
        bool lvds_downclock_avail;
         */
        struct workqueue_struct *dp_wq;
  
+       uint32_t bios_vgacntr;
        /* Old dri1 support infrastructure, beware the dragons ya fools entering
         * here! */
        struct i915_dri1_state dri1;
@@@ -1837,7 -1881,7 +1884,7 @@@ struct drm_i915_gem_object 
        struct drm_file *pin_filp;
  
        /** for phy allocated objects */
 -      drm_dma_handle_t *phys_handle;
 +      struct drm_dma_handle *phys_handle;
  
        union {
                struct i915_gem_userptr {
                        unsigned workers :4;
  #define I915_GEM_USERPTR_MAX_WORKERS 15
  
 -                      struct mm_struct *mm;
 -                      struct i915_mmu_object *mn;
 +                      struct i915_mm_struct *mm;
 +                      struct i915_mmu_object *mmu_object;
                        struct work_struct *work;
                } userptr;
        };
@@@ -2596,8 -2640,6 +2643,6 @@@ int i915_gem_context_create_ioctl(struc
  int i915_gem_context_destroy_ioctl(struct drm_device *dev, void *data,
                                   struct drm_file *file);
  
- /* i915_gem_render_state.c */
- int i915_gem_render_state_init(struct intel_engine_cs *ring);
  /* i915_gem_evict.c */
  int __must_check i915_gem_evict_something(struct drm_device *dev,
                                          struct i915_address_space *vm,
@@@ -2665,6 -2707,7 +2710,7 @@@ void i915_error_printf(struct drm_i915_
  int i915_error_state_to_str(struct drm_i915_error_state_buf *estr,
                            const struct i915_error_state_file_priv *error);
  int i915_error_state_buf_init(struct drm_i915_error_state_buf *eb,
+                             struct drm_i915_private *i915,
                              size_t count, loff_t pos);
  static inline void i915_error_state_buf_release(
        struct drm_i915_error_state_buf *eb)
@@@ -2679,7 -2722,7 +2725,7 @@@ void i915_error_state_put(struct i915_e
  void i915_destroy_error_state(struct drm_device *dev);
  
  void i915_get_extra_instdone(struct drm_device *dev, uint32_t *instdone);
- const char *i915_cache_level_str(int type);
+ const char *i915_cache_level_str(struct drm_i915_private *i915, int type);
  
  /* i915_cmd_parser.c */
  int i915_cmd_parser_get_version(void);
@@@ -2771,10 -2814,13 +2817,13 @@@ extern void intel_modeset_setup_hw_stat
  extern void i915_redisable_vga(struct drm_device *dev);
  extern void i915_redisable_vga_power_on(struct drm_device *dev);
  extern bool intel_fbc_enabled(struct drm_device *dev);
+ extern void gen8_fbc_sw_flush(struct drm_device *dev, u32 value);
  extern void intel_disable_fbc(struct drm_device *dev);
  extern bool ironlake_set_drps(struct drm_device *dev, u8 val);
  extern void intel_init_pch_refclk(struct drm_device *dev);
  extern void gen6_set_rps(struct drm_device *dev, u8 val);
+ extern void bdw_software_turbo(struct drm_device *dev);
+ extern void gen8_flip_interrupt(struct drm_device *dev);
  extern void valleyview_set_rps(struct drm_device *dev, u8 val);
  extern void intel_set_memory_cxsr(struct drm_i915_private *dev_priv,
                                  bool enable);
index 1133bb3b2766057a8353d824a9f3c3b06c89ba50,6c685708a516985da9be91be8055714767424ab4..4ca3a6dcf10bdc7dc30d4e40e074a0fac9c76561
@@@ -1085,7 -1085,13 +1085,13 @@@ i915_gem_check_wedge(struct i915_gpu_er
                if (i915_terminally_wedged(error))
                        return -EIO;
  
-               return -EAGAIN;
+               /*
+                * Check if GPU Reset is in progress - we need intel_ring_begin
+                * to work properly to reinit the hw state while the gpu is
+                * still marked as reset-in-progress. Handle this with a flag.
+                */
+               if (!error->reload_in_reset)
+                       return -EAGAIN;
        }
  
        return 0;
@@@ -1590,13 -1596,10 +1596,13 @@@ unlock
  out:
        switch (ret) {
        case -EIO:
 -              /* If this -EIO is due to a gpu hang, give the reset code a
 -               * chance to clean up the mess. Otherwise return the proper
 -               * SIGBUS. */
 -              if (i915_terminally_wedged(&dev_priv->gpu_error)) {
 +              /*
 +               * We eat errors when the gpu is terminally wedged to avoid
 +               * userspace unduly crashing (gl has no provisions for mmaps to
 +               * fail). But any other -EIO isn't ours (e.g. swap in failure)
 +               * and so needs to be reported.
 +               */
 +              if (!i915_terminally_wedged(&dev_priv->gpu_error)) {
                        ret = VM_FAULT_SIGBUS;
                        break;
                }
@@@ -2982,9 -2985,11 +2988,11 @@@ int i915_gpu_idle(struct drm_device *de
  
        /* Flush everything onto the inactive list. */
        for_each_ring(ring, dev_priv, i) {
-               ret = i915_switch_context(ring, ring->default_context);
-               if (ret)
-                       return ret;
+               if (!i915.enable_execlists) {
+                       ret = i915_switch_context(ring, ring->default_context);
+                       if (ret)
+                               return ret;
+               }
  
                ret = intel_ring_idle(ring);
                if (ret)
@@@ -4658,11 -4663,46 +4666,46 @@@ intel_enable_blt(struct drm_device *dev
        return true;
  }
  
+ static void init_unused_ring(struct drm_device *dev, u32 base)
+ {
+       struct drm_i915_private *dev_priv = dev->dev_private;
+       I915_WRITE(RING_CTL(base), 0);
+       I915_WRITE(RING_HEAD(base), 0);
+       I915_WRITE(RING_TAIL(base), 0);
+       I915_WRITE(RING_START(base), 0);
+ }
+ static void init_unused_rings(struct drm_device *dev)
+ {
+       if (IS_I830(dev)) {
+               init_unused_ring(dev, PRB1_BASE);
+               init_unused_ring(dev, SRB0_BASE);
+               init_unused_ring(dev, SRB1_BASE);
+               init_unused_ring(dev, SRB2_BASE);
+               init_unused_ring(dev, SRB3_BASE);
+       } else if (IS_GEN2(dev)) {
+               init_unused_ring(dev, SRB0_BASE);
+               init_unused_ring(dev, SRB1_BASE);
+       } else if (IS_GEN3(dev)) {
+               init_unused_ring(dev, PRB1_BASE);
+               init_unused_ring(dev, PRB2_BASE);
+       }
+ }
  int i915_gem_init_rings(struct drm_device *dev)
  {
        struct drm_i915_private *dev_priv = dev->dev_private;
        int ret;
  
+       /*
+        * At least 830 can leave some of the unused rings
+        * "active" (ie. head != tail) after resume which
+        * will prevent c3 entry. Makes sure all unused rings
+        * are totally idle.
+        */
+       init_unused_rings(dev);
        ret = intel_init_render_ring_buffer(dev);
        if (ret)
                return ret;
index 7391697c25e794236be351a495c9e621d418fd9e,9f097537bbc982e764487a6342d22954e2fedb06..c96ddc9535319993597e418edba751b061cad97c
@@@ -238,7 -238,7 +238,7 @@@ static bool ivb_can_enable_err_int(stru
  
        assert_spin_locked(&dev_priv->irq_lock);
  
-       for_each_pipe(pipe) {
+       for_each_pipe(dev_priv, pipe) {
                crtc = to_intel_crtc(dev_priv->pipe_to_crtc_mapping[pipe]);
  
                if (crtc->cpu_fifo_underrun_disabled)
@@@ -296,7 -296,7 +296,7 @@@ static bool cpt_can_enable_serr_int(str
  
        assert_spin_locked(&dev_priv->irq_lock);
  
-       for_each_pipe(pipe) {
+       for_each_pipe(dev_priv, pipe) {
                crtc = to_intel_crtc(dev_priv->pipe_to_crtc_mapping[pipe]);
  
                if (crtc->pch_fifo_underrun_disabled)
@@@ -497,7 -497,7 +497,7 @@@ static bool __intel_set_cpu_fifo_underr
        old = !intel_crtc->cpu_fifo_underrun_disabled;
        intel_crtc->cpu_fifo_underrun_disabled = !enable;
  
-       if (INTEL_INFO(dev)->gen < 5 || IS_VALLEYVIEW(dev))
+       if (HAS_GMCH_DISPLAY(dev))
                i9xx_set_fifo_underrun_reporting(dev, pipe, enable, old);
        else if (IS_GEN5(dev) || IS_GEN6(dev))
                ironlake_set_fifo_underrun_reporting(dev, pipe, enable);
@@@ -1020,7 -1020,7 +1020,7 @@@ static int i915_get_crtc_scanoutpos(str
  
        /* In vblank? */
        if (in_vbl)
 -              ret |= DRM_SCANOUTPOS_INVBL;
 +              ret |= DRM_SCANOUTPOS_IN_VBLANK;
  
        return ret;
  }
@@@ -1979,6 -1979,27 +1979,27 @@@ static void i9xx_pipe_crc_irq_handler(s
                                     res1, res2);
  }
  
+ void gen8_flip_interrupt(struct drm_device *dev)
+ {
+       struct drm_i915_private *dev_priv = dev->dev_private;
+       if (!dev_priv->rps.is_bdw_sw_turbo)
+               return;
+       if(atomic_read(&dev_priv->rps.sw_turbo.flip_received)) {
+               mod_timer(&dev_priv->rps.sw_turbo.flip_timer,
+                               usecs_to_jiffies(dev_priv->rps.sw_turbo.timeout) + jiffies);
+       }
+       else {
+               dev_priv->rps.sw_turbo.flip_timer.expires =
+                               usecs_to_jiffies(dev_priv->rps.sw_turbo.timeout) + jiffies;
+               add_timer(&dev_priv->rps.sw_turbo.flip_timer);
+               atomic_set(&dev_priv->rps.sw_turbo.flip_received, true);
+       }
+       bdw_software_turbo(dev);
+ }
  /* The RPS events need forcewake, so we add them to a work queue and mask their
   * IMR bits until the work is done. Other interrupts can be processed without
   * the work queue. */
@@@ -2020,7 -2041,7 +2041,7 @@@ static void valleyview_pipestat_irq_han
        int pipe;
  
        spin_lock(&dev_priv->irq_lock);
-       for_each_pipe(pipe) {
+       for_each_pipe(dev_priv, pipe) {
                int reg;
                u32 mask, iir_bit = 0;
  
        }
        spin_unlock(&dev_priv->irq_lock);
  
-       for_each_pipe(pipe) {
-               if (pipe_stats[pipe] & PIPE_START_VBLANK_INTERRUPT_STATUS)
-                       intel_pipe_handle_vblank(dev, pipe);
+       for_each_pipe(dev_priv, pipe) {
+               if (pipe_stats[pipe] & PIPE_START_VBLANK_INTERRUPT_STATUS &&
+                   intel_pipe_handle_vblank(dev, pipe))
+                       intel_check_page_flip(dev, pipe);
  
                if (pipe_stats[pipe] & PLANE_FLIP_DONE_INT_STATUS_VLV) {
                        intel_prepare_page_flip(dev, pipe);
@@@ -2234,7 -2256,7 +2256,7 @@@ static void ibx_irq_handler(struct drm_
                DRM_ERROR("PCH poison interrupt\n");
  
        if (pch_iir & SDE_FDI_MASK)
-               for_each_pipe(pipe)
+               for_each_pipe(dev_priv, pipe)
                        DRM_DEBUG_DRIVER("  pipe %c FDI IIR: 0x%08x\n",
                                         pipe_name(pipe),
                                         I915_READ(FDI_RX_IIR(pipe)));
@@@ -2265,7 -2287,7 +2287,7 @@@ static void ivb_err_int_handler(struct 
        if (err_int & ERR_INT_POISON)
                DRM_ERROR("Poison interrupt\n");
  
-       for_each_pipe(pipe) {
+       for_each_pipe(dev_priv, pipe) {
                if (err_int & ERR_INT_FIFO_UNDERRUN(pipe)) {
                        if (intel_set_cpu_fifo_underrun_reporting(dev, pipe,
                                                                  false))
@@@ -2342,7 -2364,7 +2364,7 @@@ static void cpt_irq_handler(struct drm_
                DRM_DEBUG_DRIVER("Audio CP change interrupt\n");
  
        if (pch_iir & SDE_FDI_MASK_CPT)
-               for_each_pipe(pipe)
+               for_each_pipe(dev_priv, pipe)
                        DRM_DEBUG_DRIVER("  pipe %c FDI IIR: 0x%08x\n",
                                         pipe_name(pipe),
                                         I915_READ(FDI_RX_IIR(pipe)));
@@@ -2365,9 -2387,10 +2387,10 @@@ static void ilk_display_irq_handler(str
        if (de_iir & DE_POISON)
                DRM_ERROR("Poison interrupt\n");
  
-       for_each_pipe(pipe) {
-               if (de_iir & DE_PIPE_VBLANK(pipe))
-                       intel_pipe_handle_vblank(dev, pipe);
+       for_each_pipe(dev_priv, pipe) {
+               if (de_iir & DE_PIPE_VBLANK(pipe) &&
+                   intel_pipe_handle_vblank(dev, pipe))
+                       intel_check_page_flip(dev, pipe);
  
                if (de_iir & DE_PIPE_FIFO_UNDERRUN(pipe))
                        if (intel_set_cpu_fifo_underrun_reporting(dev, pipe, false))
@@@ -2415,9 -2438,10 +2438,10 @@@ static void ivb_display_irq_handler(str
        if (de_iir & DE_GSE_IVB)
                intel_opregion_asle_intr(dev);
  
-       for_each_pipe(pipe) {
-               if (de_iir & (DE_PIPE_VBLANK_IVB(pipe)))
-                       intel_pipe_handle_vblank(dev, pipe);
+       for_each_pipe(dev_priv, pipe) {
+               if (de_iir & (DE_PIPE_VBLANK_IVB(pipe)) &&
+                   intel_pipe_handle_vblank(dev, pipe))
+                       intel_check_page_flip(dev, pipe);
  
                /* plane/pipes map 1:1 on ilk+ */
                if (de_iir & DE_PLANE_FLIP_DONE_IVB(pipe)) {
@@@ -2562,7 -2586,7 +2586,7 @@@ static irqreturn_t gen8_irq_handler(in
                        DRM_ERROR("The master control interrupt lied (DE PORT)!\n");
        }
  
-       for_each_pipe(pipe) {
+       for_each_pipe(dev_priv, pipe) {
                uint32_t pipe_iir;
  
                if (!(master_ctl & GEN8_DE_PIPE_IRQ(pipe)))
                if (pipe_iir) {
                        ret = IRQ_HANDLED;
                        I915_WRITE(GEN8_DE_PIPE_IIR(pipe), pipe_iir);
-                       if (pipe_iir & GEN8_PIPE_VBLANK)
-                               intel_pipe_handle_vblank(dev, pipe);
+                       if (pipe_iir & GEN8_PIPE_VBLANK &&
+                           intel_pipe_handle_vblank(dev, pipe))
+                               intel_check_page_flip(dev, pipe);
  
                        if (pipe_iir & GEN8_PIPE_PRIMARY_FLIP_DONE) {
                                intel_prepare_page_flip(dev, pipe);
@@@ -2781,7 -2806,7 +2806,7 @@@ static void i915_report_and_clear_eir(s
  
        if (eir & I915_ERROR_MEMORY_REFRESH) {
                pr_err("memory refresh error:\n");
-               for_each_pipe(pipe)
+               for_each_pipe(dev_priv, pipe)
                        pr_err("pipe %c stat: 0x%08x\n",
                               pipe_name(pipe), I915_READ(PIPESTAT(pipe)));
                /* pipestat has already been acked */
@@@ -2878,52 -2903,6 +2903,6 @@@ void i915_handle_error(struct drm_devic
        schedule_work(&dev_priv->gpu_error.work);
  }
  
- static void __always_unused i915_pageflip_stall_check(struct drm_device *dev, int 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);
-       struct drm_i915_gem_object *obj;
-       struct intel_unpin_work *work;
-       unsigned long flags;
-       bool stall_detected;
-       /* Ignore early vblank irqs */
-       if (intel_crtc == NULL)
-               return;
-       spin_lock_irqsave(&dev->event_lock, flags);
-       work = intel_crtc->unpin_work;
-       if (work == NULL ||
-           atomic_read(&work->pending) >= INTEL_FLIP_COMPLETE ||
-           !work->enable_stall_check) {
-               /* Either the pending flip IRQ arrived, or we're too early. Don't check */
-               spin_unlock_irqrestore(&dev->event_lock, flags);
-               return;
-       }
-       /* Potential stall - if we see that the flip has happened, assume a missed interrupt */
-       obj = work->pending_flip_obj;
-       if (INTEL_INFO(dev)->gen >= 4) {
-               int dspsurf = DSPSURF(intel_crtc->plane);
-               stall_detected = I915_HI_DISPBASE(I915_READ(dspsurf)) ==
-                                       i915_gem_obj_ggtt_offset(obj);
-       } else {
-               int dspaddr = DSPADDR(intel_crtc->plane);
-               stall_detected = I915_READ(dspaddr) == (i915_gem_obj_ggtt_offset(obj) +
-                                                       crtc->y * crtc->primary->fb->pitches[0] +
-                                                       crtc->x * crtc->primary->fb->bits_per_pixel/8);
-       }
-       spin_unlock_irqrestore(&dev->event_lock, flags);
-       if (stall_detected) {
-               DRM_DEBUG_DRIVER("Pageflip stall detected\n");
-               intel_prepare_page_flip(dev, intel_crtc->plane);
-       }
- }
  /* Called from drm generic code, passed 'crtc' which
   * we use as a pipe index
   */
@@@ -3459,7 -3438,7 +3438,7 @@@ static void valleyview_irq_preinstall(s
  
        I915_WRITE(PORT_HOTPLUG_EN, 0);
        I915_WRITE(PORT_HOTPLUG_STAT, I915_READ(PORT_HOTPLUG_STAT));
-       for_each_pipe(pipe)
+       for_each_pipe(dev_priv, pipe)
                I915_WRITE(PIPESTAT(pipe), 0xffff);
        I915_WRITE(VLV_IIR, 0xffffffff);
        I915_WRITE(VLV_IMR, 0xffffffff);
@@@ -3485,7 -3464,7 +3464,7 @@@ static void gen8_irq_reset(struct drm_d
  
        gen8_gt_irq_reset(dev_priv);
  
-       for_each_pipe(pipe)
+       for_each_pipe(dev_priv, pipe)
                if (intel_display_power_enabled(dev_priv,
                                                POWER_DOMAIN_PIPE(pipe)))
                        GEN8_IRQ_RESET_NDX(DE_PIPE, pipe);
@@@ -3528,7 -3507,7 +3507,7 @@@ static void cherryview_irq_preinstall(s
        I915_WRITE(PORT_HOTPLUG_EN, 0);
        I915_WRITE(PORT_HOTPLUG_STAT, I915_READ(PORT_HOTPLUG_STAT));
  
-       for_each_pipe(pipe)
+       for_each_pipe(dev_priv, pipe)
                I915_WRITE(PIPESTAT(pipe), 0xffff);
  
        I915_WRITE(VLV_IMR, 0xffffffff);
@@@ -3799,8 -3778,6 +3778,6 @@@ static int valleyview_irq_postinstall(s
  
  static void gen8_gt_irq_postinstall(struct drm_i915_private *dev_priv)
  {
-       int i;
        /* These are interrupts we'll toggle with the ring mask register */
        uint32_t gt_interrupts[] = {
                GT_RENDER_USER_INTERRUPT << GEN8_RCS_IRQ_SHIFT |
                        GT_CONTEXT_SWITCH_INTERRUPT << GEN8_VECS_IRQ_SHIFT
                };
  
-       for (i = 0; i < ARRAY_SIZE(gt_interrupts); i++)
-               GEN8_IRQ_INIT_NDX(GT, i, ~gt_interrupts[i], gt_interrupts[i]);
        dev_priv->pm_irq_mask = 0xffffffff;
+       GEN8_IRQ_INIT_NDX(GT, 0, ~gt_interrupts[0], gt_interrupts[0]);
+       GEN8_IRQ_INIT_NDX(GT, 1, ~gt_interrupts[1], gt_interrupts[1]);
+       GEN8_IRQ_INIT_NDX(GT, 2, dev_priv->pm_irq_mask, dev_priv->pm_rps_events);
+       GEN8_IRQ_INIT_NDX(GT, 3, ~gt_interrupts[3], gt_interrupts[3]);
  }
  
  static void gen8_de_irq_postinstall(struct drm_i915_private *dev_priv)
  {
-       struct drm_device *dev = dev_priv->dev;
        uint32_t de_pipe_masked = GEN8_PIPE_PRIMARY_FLIP_DONE |
                GEN8_PIPE_CDCLK_CRC_DONE |
                GEN8_DE_PIPE_IRQ_FAULT_ERRORS;
        dev_priv->de_irq_mask[PIPE_B] = ~de_pipe_masked;
        dev_priv->de_irq_mask[PIPE_C] = ~de_pipe_masked;
  
-       for_each_pipe(pipe)
+       for_each_pipe(dev_priv, pipe)
                if (intel_display_power_enabled(dev_priv,
                                POWER_DOMAIN_PIPE(pipe)))
                        GEN8_IRQ_INIT_NDX(DE_PIPE, pipe,
@@@ -3881,12 -3858,12 +3858,12 @@@ static int cherryview_irq_postinstall(s
         */
        dev_priv->irq_mask = ~enable_mask;
  
-       for_each_pipe(pipe)
+       for_each_pipe(dev_priv, pipe)
                I915_WRITE(PIPESTAT(pipe), 0xffff);
  
        spin_lock_irqsave(&dev_priv->irq_lock, irqflags);
        i915_enable_pipestat(dev_priv, PIPE_A, PIPE_GMBUS_INTERRUPT_STATUS);
-       for_each_pipe(pipe)
+       for_each_pipe(dev_priv, pipe)
                i915_enable_pipestat(dev_priv, pipe, pipestat_enable);
        spin_unlock_irqrestore(&dev_priv->irq_lock, irqflags);
  
@@@ -3923,7 -3900,7 +3900,7 @@@ static void valleyview_irq_uninstall(st
  
        I915_WRITE(VLV_MASTER_IER, 0);
  
-       for_each_pipe(pipe)
+       for_each_pipe(dev_priv, pipe)
                I915_WRITE(PIPESTAT(pipe), 0xffff);
  
        I915_WRITE(HWSTAM, 0xffffffff);
@@@ -3985,7 -3962,7 +3962,7 @@@ do {                                                    
        I915_WRITE(PORT_HOTPLUG_EN, 0);
        I915_WRITE(PORT_HOTPLUG_STAT, I915_READ(PORT_HOTPLUG_STAT));
  
-       for_each_pipe(pipe)
+       for_each_pipe(dev_priv, pipe)
                I915_WRITE(PIPESTAT(pipe), 0xffff);
  
        I915_WRITE(VLV_IMR, 0xffffffff);
@@@ -4009,7 -3986,7 +3986,7 @@@ static void i8xx_irq_preinstall(struct 
        struct drm_i915_private *dev_priv = dev->dev_private;
        int pipe;
  
-       for_each_pipe(pipe)
+       for_each_pipe(dev_priv, pipe)
                I915_WRITE(PIPESTAT(pipe), 0);
        I915_WRITE16(IMR, 0xffff);
        I915_WRITE16(IER, 0x0);
@@@ -4063,7 -4040,7 +4040,7 @@@ static bool i8xx_handle_vblank(struct d
                return false;
  
        if ((iir & flip_pending) == 0)
-               return false;
+               goto check_page_flip;
  
        intel_prepare_page_flip(dev, plane);
  
         * an interrupt per se, we watch for the change at vblank.
         */
        if (I915_READ16(ISR) & flip_pending)
-               return false;
+               goto check_page_flip;
  
        intel_finish_page_flip(dev, pipe);
        return true;
+ check_page_flip:
+       intel_check_page_flip(dev, pipe);
+       return false;
  }
  
  static irqreturn_t i8xx_irq_handler(int irq, void *arg)
                                          "Command parser error, iir 0x%08x",
                                          iir);
  
-               for_each_pipe(pipe) {
+               for_each_pipe(dev_priv, pipe) {
                        int reg = PIPESTAT(pipe);
                        pipe_stats[pipe] = I915_READ(reg);
  
                if (iir & I915_USER_INTERRUPT)
                        notify_ring(dev, &dev_priv->ring[RCS]);
  
-               for_each_pipe(pipe) {
+               for_each_pipe(dev_priv, pipe) {
                        int plane = pipe;
                        if (HAS_FBC(dev))
                                plane = !plane;
@@@ -4157,7 -4137,7 +4137,7 @@@ static void i8xx_irq_uninstall(struct d
        struct drm_i915_private *dev_priv = dev->dev_private;
        int pipe;
  
-       for_each_pipe(pipe) {
+       for_each_pipe(dev_priv, pipe) {
                /* Clear enable bits; then clear status bits */
                I915_WRITE(PIPESTAT(pipe), 0);
                I915_WRITE(PIPESTAT(pipe), I915_READ(PIPESTAT(pipe)));
@@@ -4178,7 -4158,7 +4158,7 @@@ static void i915_irq_preinstall(struct 
        }
  
        I915_WRITE16(HWSTAM, 0xeffe);
-       for_each_pipe(pipe)
+       for_each_pipe(dev_priv, pipe)
                I915_WRITE(PIPESTAT(pipe), 0);
        I915_WRITE(IMR, 0xffffffff);
        I915_WRITE(IER, 0x0);
@@@ -4248,7 -4228,7 +4228,7 @@@ static bool i915_handle_vblank(struct d
                return false;
  
        if ((iir & flip_pending) == 0)
-               return false;
+               goto check_page_flip;
  
        intel_prepare_page_flip(dev, plane);
  
         * an interrupt per se, we watch for the change at vblank.
         */
        if (I915_READ(ISR) & flip_pending)
-               return false;
+               goto check_page_flip;
  
        intel_finish_page_flip(dev, pipe);
        return true;
+ check_page_flip:
+       intel_check_page_flip(dev, pipe);
+       return false;
  }
  
  static irqreturn_t i915_irq_handler(int irq, void *arg)
                                          "Command parser error, iir 0x%08x",
                                          iir);
  
-               for_each_pipe(pipe) {
+               for_each_pipe(dev_priv, pipe) {
                        int reg = PIPESTAT(pipe);
                        pipe_stats[pipe] = I915_READ(reg);
  
                if (iir & I915_USER_INTERRUPT)
                        notify_ring(dev, &dev_priv->ring[RCS]);
  
-               for_each_pipe(pipe) {
+               for_each_pipe(dev_priv, pipe) {
                        int plane = pipe;
                        if (HAS_FBC(dev))
                                plane = !plane;
@@@ -4377,7 -4360,7 +4360,7 @@@ static void i915_irq_uninstall(struct d
        }
  
        I915_WRITE16(HWSTAM, 0xffff);
-       for_each_pipe(pipe) {
+       for_each_pipe(dev_priv, pipe) {
                /* Clear enable bits; then clear status bits */
                I915_WRITE(PIPESTAT(pipe), 0);
                I915_WRITE(PIPESTAT(pipe), I915_READ(PIPESTAT(pipe)));
@@@ -4397,7 -4380,7 +4380,7 @@@ static void i965_irq_preinstall(struct 
        I915_WRITE(PORT_HOTPLUG_STAT, I915_READ(PORT_HOTPLUG_STAT));
  
        I915_WRITE(HWSTAM, 0xeffe);
-       for_each_pipe(pipe)
+       for_each_pipe(dev_priv, pipe)
                I915_WRITE(PIPESTAT(pipe), 0);
        I915_WRITE(IMR, 0xffffffff);
        I915_WRITE(IER, 0x0);
@@@ -4522,7 -4505,7 +4505,7 @@@ static irqreturn_t i965_irq_handler(in
                                          "Command parser error, iir 0x%08x",
                                          iir);
  
-               for_each_pipe(pipe) {
+               for_each_pipe(dev_priv, pipe) {
                        int reg = PIPESTAT(pipe);
                        pipe_stats[pipe] = I915_READ(reg);
  
                if (iir & I915_BSD_USER_INTERRUPT)
                        notify_ring(dev, &dev_priv->ring[VCS]);
  
-               for_each_pipe(pipe) {
+               for_each_pipe(dev_priv, pipe) {
                        if (pipe_stats[pipe] & PIPE_START_VBLANK_INTERRUPT_STATUS &&
                            i915_handle_vblank(dev, pipe, pipe, iir))
                                flip_mask &= ~DISPLAY_PLANE_FLIP_PENDING(pipe);
@@@ -4610,12 -4593,12 +4593,12 @@@ static void i965_irq_uninstall(struct d
        I915_WRITE(PORT_HOTPLUG_STAT, I915_READ(PORT_HOTPLUG_STAT));
  
        I915_WRITE(HWSTAM, 0xffffffff);
-       for_each_pipe(pipe)
+       for_each_pipe(dev_priv, pipe)
                I915_WRITE(PIPESTAT(pipe), 0);
        I915_WRITE(IMR, 0xffffffff);
        I915_WRITE(IER, 0x0);
  
-       for_each_pipe(pipe)
+       for_each_pipe(dev_priv, pipe)
                I915_WRITE(PIPESTAT(pipe),
                           I915_READ(PIPESTAT(pipe)) & 0x8000ffff);
        I915_WRITE(IIR, I915_READ(IIR));
@@@ -4673,8 -4656,8 +4656,8 @@@ void intel_irq_init(struct drm_device *
        INIT_WORK(&dev_priv->l3_parity.error_work, ivybridge_parity_work);
  
        /* Let's track the enabled rps events */
-       if (IS_VALLEYVIEW(dev))
-               /* WaGsvRC0ResidenncyMethod:VLV */
+       if (IS_VALLEYVIEW(dev) && !IS_CHERRYVIEW(dev))
+               /* WaGsvRC0ResidencyMethod:vlv */
                dev_priv->pm_rps_events = GEN6_PM_RP_UP_EI_EXPIRED;
        else
                dev_priv->pm_rps_events = GEN6_PM_RPS_EVENTS;
                dev->max_vblank_count = 0xffffff; /* only 24 bits of frame count */
        }
  
 +      /*
 +       * Opt out of the vblank disable timer on everything except gen2.
 +       * Gen2 doesn't have a hardware frame counter and so depends on
 +       * vblank interrupts to produce sane vblank seuquence numbers.
 +       */
 +      if (!IS_GEN2(dev))
 +              dev->vblank_disable_immediate = true;
 +
        if (drm_core_check_feature(dev, DRIVER_MODESET)) {
                dev->driver->get_vblank_timestamp = i915_get_vblank_timestamp;
                dev->driver->get_scanout_position = i915_get_crtc_scanoutpos;
index 1e4fb846d9a52822060c7dc0e2edac0dd9a0de33,15c0eaa9f97f52360e0477d169a09de3678e9207..b65bdfc23ccb9213b7acd7425cdd6d5e324a06e8
  #define GFX_OP_DESTBUFFER_INFO         ((0x3<<29)|(0x1d<<24)|(0x8e<<16)|1)
  #define GFX_OP_DRAWRECT_INFO     ((0x3<<29)|(0x1d<<24)|(0x80<<16)|(0x3))
  #define GFX_OP_DRAWRECT_INFO_I965  ((0x7900<<16)|0x2)
 -#define SRC_COPY_BLT_CMD                ((2<<29)|(0x43<<22)|4)
 +
 +#define COLOR_BLT_CMD                 (2<<29 | 0x40<<22 | (5-2))
 +#define SRC_COPY_BLT_CMD              ((2<<29)|(0x43<<22)|4)
  #define XY_SRC_COPY_BLT_CMD           ((2<<29)|(0x53<<22)|6)
  #define XY_MONO_SRC_COPY_IMM_BLT      ((2<<29)|(0x71<<22)|5)
 -#define XY_SRC_COPY_BLT_WRITE_ALPHA   (1<<21)
 -#define XY_SRC_COPY_BLT_WRITE_RGB     (1<<20)
 +#define   BLT_WRITE_A                 (2<<20)
 +#define   BLT_WRITE_RGB                       (1<<20)
 +#define   BLT_WRITE_RGBA              (BLT_WRITE_RGB | BLT_WRITE_A)
  #define   BLT_DEPTH_8                 (0<<24)
  #define   BLT_DEPTH_16_565            (1<<24)
  #define   BLT_DEPTH_16_1555           (2<<24)
  #define   BLT_DEPTH_32                        (3<<24)
 -#define   BLT_ROP_GXCOPY              (0xcc<<16)
 +#define   BLT_ROP_SRC_COPY            (0xcc<<16)
 +#define   BLT_ROP_COLOR_COPY          (0xf0<<16)
  #define XY_SRC_COPY_BLT_SRC_TILED     (1<<15) /* 965+ only */
  #define XY_SRC_COPY_BLT_DST_TILED     (1<<11) /* 965+ only */
  #define CMD_OP_DISPLAYBUFFER_INFO ((0x0<<29)|(0x14<<23)|2)
@@@ -1030,6 -1026,13 +1030,13 @@@ enum punit_power_well 
  #define   PGTBL_ADDRESS_LO_MASK       0xfffff000 /* bits [31:12] */
  #define   PGTBL_ADDRESS_HI_MASK       0x000000f0 /* bits [35:32] (gen4) */
  #define PGTBL_ER      0x02024
+ #define PRB0_BASE (0x2030-0x30)
+ #define PRB1_BASE (0x2040-0x30) /* 830,gen3 */
+ #define PRB2_BASE (0x2050-0x30) /* gen3 */
+ #define SRB0_BASE (0x2100-0x30) /* gen2 */
+ #define SRB1_BASE (0x2110-0x30) /* gen2 */
+ #define SRB2_BASE (0x2120-0x30) /* 830 */
+ #define SRB3_BASE (0x2130-0x30) /* 830 */
  #define RENDER_RING_BASE      0x02000
  #define BSD_RING_BASE         0x04000
  #define GEN6_BSD_RING_BASE    0x12000
  #define   INSTPM_TLB_INVALIDATE       (1<<9)
  #define   INSTPM_SYNC_FLUSH   (1<<5)
  #define ACTHD         0x020c8
+ #define MEM_MODE      0x020cc
+ #define   MEM_DISPLAY_B_TRICKLE_FEED_DISABLE (1<<3) /* 830 only */
+ #define   MEM_DISPLAY_A_TRICKLE_FEED_DISABLE (1<<2) /* 830/845 only */
+ #define   MEM_DISPLAY_TRICKLE_FEED_DISABLE (1<<2) /* 85x only */
  #define FW_BLC                0x020d8
  #define FW_BLC2               0x020dc
  #define FW_BLC_SELF   0x020e0 /* 915+ only */
  #define   DISPPLANE_NO_LINE_DOUBLE            0
  #define   DISPPLANE_STEREO_POLARITY_FIRST     0
  #define   DISPPLANE_STEREO_POLARITY_SECOND    (1<<18)
+ #define   DISPPLANE_ROTATE_180         (1<<15)
  #define   DISPPLANE_TRICKLE_FEED_DISABLE      (1<<14) /* Ironlake */
  #define   DISPPLANE_TILED                     (1<<10)
  #define _DSPAADDR                             0x70184
  #define PIPEA_PP_STATUS         (VLV_DISPLAY_BASE + 0x61200)
  #define PIPEA_PP_CONTROL        (VLV_DISPLAY_BASE + 0x61204)
  #define PIPEA_PP_ON_DELAYS      (VLV_DISPLAY_BASE + 0x61208)
- #define  PANEL_PORT_SELECT_DPB_VLV    (1 << 30)
- #define  PANEL_PORT_SELECT_DPC_VLV    (2 << 30)
+ #define  PANEL_PORT_SELECT_VLV(port)  ((port) << 30)
  #define PIPEA_PP_OFF_DELAYS     (VLV_DISPLAY_BASE + 0x6120c)
  #define PIPEA_PP_DIVISOR        (VLV_DISPLAY_BASE + 0x61210)
  
  #define GEN8_UCGCTL6                          0x9430
  #define   GEN8_SDEUNIT_CLOCK_GATE_DISABLE     (1<<14)
  
+ #define TIMESTAMP_CTR         0x44070
+ #define FREQ_1_28_US(us)      (((us) * 100) >> 7)
+ #define MCHBAR_PCU_C0         (MCHBAR_MIRROR_BASE_SNB + 0x5960)
  #define GEN6_GFXPAUSE                         0xA000
  #define GEN6_RPNSWREQ                         0xA008
  #define   GEN6_TURBO_DISABLE                  (1<<31)
                                                 GEN6_PM_RP_DOWN_THRESHOLD | \
                                                 GEN6_PM_RP_DOWN_TIMEOUT)
  
- #define CHV_CZ_CLOCK_FREQ_MODE_200                    200
- #define CHV_CZ_CLOCK_FREQ_MODE_267                    267
- #define CHV_CZ_CLOCK_FREQ_MODE_320                    320
- #define CHV_CZ_CLOCK_FREQ_MODE_333                    333
- #define CHV_CZ_CLOCK_FREQ_MODE_400                    400
  #define GEN7_GT_SCRATCH_BASE                  0x4F100
  #define GEN7_GT_SCRATCH_REG_NUM                       8
  
  #define DDI_BUF_CTL_B                         0x64100
  #define DDI_BUF_CTL(port) _PORT(port, DDI_BUF_CTL_A, DDI_BUF_CTL_B)
  #define  DDI_BUF_CTL_ENABLE                   (1<<31)
- #define  DDI_BUF_EMP_400MV_0DB_HSW            (0<<24)   /* Sel0 */
- #define  DDI_BUF_EMP_400MV_3_5DB_HSW          (1<<24)   /* Sel1 */
- #define  DDI_BUF_EMP_400MV_6DB_HSW            (2<<24)   /* Sel2 */
- #define  DDI_BUF_EMP_400MV_9_5DB_HSW          (3<<24)   /* Sel3 */
- #define  DDI_BUF_EMP_600MV_0DB_HSW            (4<<24)   /* Sel4 */
- #define  DDI_BUF_EMP_600MV_3_5DB_HSW          (5<<24)   /* Sel5 */
- #define  DDI_BUF_EMP_600MV_6DB_HSW            (6<<24)   /* Sel6 */
- #define  DDI_BUF_EMP_800MV_0DB_HSW            (7<<24)   /* Sel7 */
- #define  DDI_BUF_EMP_800MV_3_5DB_HSW          (8<<24)   /* Sel8 */
+ #define  DDI_BUF_TRANS_SELECT(n)      ((n) << 24)
  #define  DDI_BUF_EMP_MASK                     (0xf<<24)
  #define  DDI_BUF_PORT_REVERSAL                        (1<<16)
  #define  DDI_BUF_IS_IDLE                      (1<<7)
index 32d22339c130e4a7c9e3a6b9ced2a590a841472f,e871f6846534b7b9bd95a8e4bbc2d9fbde6f7e96..b3e579b4428e5989f0404813621a0750cc859abb
@@@ -627,16 -627,16 +627,16 @@@ parse_edp(struct drm_i915_private *dev_
  
        switch (edp_link_params->preemphasis) {
        case EDP_PREEMPHASIS_NONE:
-               dev_priv->vbt.edp_preemphasis = DP_TRAIN_PRE_EMPHASIS_0;
+               dev_priv->vbt.edp_preemphasis = DP_TRAIN_PRE_EMPH_LEVEL_0;
                break;
        case EDP_PREEMPHASIS_3_5dB:
-               dev_priv->vbt.edp_preemphasis = DP_TRAIN_PRE_EMPHASIS_3_5;
+               dev_priv->vbt.edp_preemphasis = DP_TRAIN_PRE_EMPH_LEVEL_1;
                break;
        case EDP_PREEMPHASIS_6dB:
-               dev_priv->vbt.edp_preemphasis = DP_TRAIN_PRE_EMPHASIS_6;
+               dev_priv->vbt.edp_preemphasis = DP_TRAIN_PRE_EMPH_LEVEL_2;
                break;
        case EDP_PREEMPHASIS_9_5dB:
-               dev_priv->vbt.edp_preemphasis = DP_TRAIN_PRE_EMPHASIS_9_5;
+               dev_priv->vbt.edp_preemphasis = DP_TRAIN_PRE_EMPH_LEVEL_3;
                break;
        default:
                DRM_DEBUG_KMS("VBT has unknown eDP pre-emphasis value %u\n",
  
        switch (edp_link_params->vswing) {
        case EDP_VSWING_0_4V:
-               dev_priv->vbt.edp_vswing = DP_TRAIN_VOLTAGE_SWING_400;
+               dev_priv->vbt.edp_vswing = DP_TRAIN_VOLTAGE_SWING_LEVEL_0;
                break;
        case EDP_VSWING_0_6V:
-               dev_priv->vbt.edp_vswing = DP_TRAIN_VOLTAGE_SWING_600;
+               dev_priv->vbt.edp_vswing = DP_TRAIN_VOLTAGE_SWING_LEVEL_1;
                break;
        case EDP_VSWING_0_8V:
-               dev_priv->vbt.edp_vswing = DP_TRAIN_VOLTAGE_SWING_800;
+               dev_priv->vbt.edp_vswing = DP_TRAIN_VOLTAGE_SWING_LEVEL_2;
                break;
        case EDP_VSWING_1_2V:
-               dev_priv->vbt.edp_vswing = DP_TRAIN_VOLTAGE_SWING_1200;
+               dev_priv->vbt.edp_vswing = DP_TRAIN_VOLTAGE_SWING_LEVEL_3;
                break;
        default:
                DRM_DEBUG_KMS("VBT has unknown eDP voltage swing value %u\n",
@@@ -1120,7 -1120,7 +1120,7 @@@ init_vbt_defaults(struct drm_i915_priva
        }
  }
  
 -static int __init intel_no_opregion_vbt_callback(const struct dmi_system_id *id)
 +static int intel_no_opregion_vbt_callback(const struct dmi_system_id *id)
  {
        DRM_DEBUG_KMS("Falling back to manually reading VBT from "
                      "VBIOS ROM for %s\n",
index 32ede71fbe7f8500a200807409b26b8a6d58f539,b912107a139249a98439941311518f24d167f9fa..1386086ec245e4fcfadae4655a08e0d0413e97b6
@@@ -900,7 -900,8 +900,8 @@@ static void g4x_wait_for_vblank(struct 
        frame = I915_READ(frame_reg);
  
        if (wait_for(I915_READ_NOTRACE(frame_reg) != frame, 50))
-               WARN(1, "vblank wait timed out\n");
+               WARN(1, "vblank wait on pipe %c timed out\n",
+                    pipe_name(pipe));
  }
  
  /**
@@@ -941,7 -942,8 +942,8 @@@ void intel_wait_for_vblank(struct drm_d
        if (wait_for(I915_READ(pipestat_reg) &
                     PIPE_VBLANK_INTERRUPT_STATUS,
                     50))
-               DRM_DEBUG_KMS("vblank wait timed out\n");
+               DRM_DEBUG_KMS("vblank wait on pipe %c timed out\n",
+                             pipe_name(pipe));
  }
  
  static bool pipe_dsl_stopped(struct drm_device *dev, enum pipe pipe)
  
  /*
   * intel_wait_for_pipe_off - wait for pipe to turn off
-  * @dev: drm device
-  * @pipe: pipe to wait for
+  * @crtc: crtc whose pipe to wait for
   *
   * After disabling a pipe, we can't wait for vblank in the usual way,
   * spinning on the vblank interrupt status bit, since we won't actually
   *   ends up stopping at the start of the next frame).
   *
   */
void intel_wait_for_pipe_off(struct drm_device *dev, int pipe)
static void intel_wait_for_pipe_off(struct intel_crtc *crtc)
  {
+       struct drm_device *dev = crtc->base.dev;
        struct drm_i915_private *dev_priv = dev->dev_private;
-       enum transcoder cpu_transcoder = intel_pipe_to_cpu_transcoder(dev_priv,
-                                                                     pipe);
+       enum transcoder cpu_transcoder = crtc->config.cpu_transcoder;
+       enum pipe pipe = crtc->pipe;
  
        if (INTEL_INFO(dev)->gen >= 4) {
                int reg = PIPECONF(cpu_transcoder);
@@@ -1193,27 -1195,40 +1195,40 @@@ void assert_fdi_rx_pll(struct drm_i915_
  static void assert_panel_unlocked(struct drm_i915_private *dev_priv,
                                  enum pipe pipe)
  {
-       int pp_reg, lvds_reg;
+       struct drm_device *dev = dev_priv->dev;
+       int pp_reg;
        u32 val;
        enum pipe panel_pipe = PIPE_A;
        bool locked = true;
  
-       if (HAS_PCH_SPLIT(dev_priv->dev)) {
+       if (WARN_ON(HAS_DDI(dev)))
+               return;
+       if (HAS_PCH_SPLIT(dev)) {
+               u32 port_sel;
                pp_reg = PCH_PP_CONTROL;
-               lvds_reg = PCH_LVDS;
+               port_sel = I915_READ(PCH_PP_ON_DELAYS) & PANEL_PORT_SELECT_MASK;
+               if (port_sel == PANEL_PORT_SELECT_LVDS &&
+                   I915_READ(PCH_LVDS) & LVDS_PIPEB_SELECT)
+                       panel_pipe = PIPE_B;
+               /* XXX: else fix for eDP */
+       } else if (IS_VALLEYVIEW(dev)) {
+               /* presumably write lock depends on pipe, not port select */
+               pp_reg = VLV_PIPE_PP_CONTROL(pipe);
+               panel_pipe = pipe;
        } else {
                pp_reg = PP_CONTROL;
-               lvds_reg = LVDS;
+               if (I915_READ(LVDS) & LVDS_PIPEB_SELECT)
+                       panel_pipe = PIPE_B;
        }
  
        val = I915_READ(pp_reg);
        if (!(val & PANEL_POWER_ON) ||
-           ((val & PANEL_UNLOCK_REGS) == PANEL_UNLOCK_REGS))
+           ((val & PANEL_UNLOCK_MASK) == PANEL_UNLOCK_REGS))
                locked = false;
  
-       if (I915_READ(lvds_reg) & LVDS_PIPEB_SELECT)
-               panel_pipe = PIPE_B;
        WARN(panel_pipe == pipe && locked,
             "panel assertion failure, pipe %c regs locked\n",
             pipe_name(pipe));
@@@ -1246,8 -1261,9 +1261,9 @@@ void assert_pipe(struct drm_i915_privat
        enum transcoder cpu_transcoder = intel_pipe_to_cpu_transcoder(dev_priv,
                                                                      pipe);
  
-       /* if we need the pipe A quirk it must be always on */
-       if (pipe == PIPE_A && dev_priv->quirks & QUIRK_PIPEA_FORCE)
+       /* if we need the pipe quirk it must be always on */
+       if ((pipe == PIPE_A && dev_priv->quirks & QUIRK_PIPEA_FORCE) ||
+           (pipe == PIPE_B && dev_priv->quirks & QUIRK_PIPEB_FORCE))
                state = true;
  
        if (!intel_display_power_enabled(dev_priv,
@@@ -1301,7 -1317,7 +1317,7 @@@ static void assert_planes_disabled(stru
        }
  
        /* Need to check both planes against the pipe */
-       for_each_pipe(i) {
+       for_each_pipe(dev_priv, i) {
                reg = DSPCNTR(i);
                val = I915_READ(reg);
                cur_pipe = (val & DISPPLANE_SEL_PIPE_MASK) >>
@@@ -1342,12 -1358,6 +1358,12 @@@ static void assert_sprites_disabled(str
        }
  }
  
 +static void assert_vblank_disabled(struct drm_crtc *crtc)
 +{
 +      if (WARN_ON(drm_crtc_vblank_get(crtc) == 0))
 +              drm_crtc_vblank_put(crtc);
 +}
 +
  static void ibx_assert_pch_refclk_enabled(struct drm_i915_private *dev_priv)
  {
        u32 val;
@@@ -1533,7 -1543,7 +1549,7 @@@ static void vlv_enable_pll(struct intel
        BUG_ON(!IS_VALLEYVIEW(dev_priv->dev));
  
        /* PLL is protected by panel, make sure we can write it */
-       if (IS_MOBILE(dev_priv->dev) && !IS_I830(dev_priv->dev))
+       if (IS_MOBILE(dev_priv->dev))
                assert_panel_unlocked(dev_priv, crtc->pipe);
  
        I915_WRITE(reg, dpll);
@@@ -1653,8 -1663,9 +1669,9 @@@ static void i9xx_enable_pll(struct inte
   */
  static void i9xx_disable_pll(struct drm_i915_private *dev_priv, enum pipe pipe)
  {
-       /* Don't disable pipe A or pipe A PLLs if needed */
-       if (pipe == PIPE_A && (dev_priv->quirks & QUIRK_PIPEA_FORCE))
+       /* Don't disable pipe or pipe PLLs if needed */
+       if ((pipe == PIPE_A && dev_priv->quirks & QUIRK_PIPEA_FORCE) ||
+           (pipe == PIPE_B && dev_priv->quirks & QUIRK_PIPEB_FORCE))
                return;
  
        /* Make sure the pipe isn't still relying on us */
@@@ -1847,7 -1858,7 +1864,7 @@@ static void ironlake_enable_pch_transco
        uint32_t reg, val, pipeconf_val;
  
        /* PCH only available on ILK+ */
-       BUG_ON(INTEL_INFO(dev)->gen < 5);
+       BUG_ON(!HAS_PCH_SPLIT(dev));
  
        /* Make sure PCH DPLL is enabled */
        assert_shared_dpll_enabled(dev_priv,
@@@ -1900,7 -1911,7 +1917,7 @@@ static void lpt_enable_pch_transcoder(s
        u32 val, pipeconf_val;
  
        /* PCH only available on ILK+ */
-       BUG_ON(INTEL_INFO(dev_priv->dev)->gen < 5);
+       BUG_ON(!HAS_PCH_SPLIT(dev_priv->dev));
  
        /* FDI must be feeding us bits for PCH ports */
        assert_fdi_tx_enabled(dev_priv, (enum pipe) cpu_transcoder);
@@@ -2022,8 -2033,8 +2039,8 @@@ static void intel_enable_pipe(struct in
        reg = PIPECONF(cpu_transcoder);
        val = I915_READ(reg);
        if (val & PIPECONF_ENABLE) {
-               WARN_ON(!(pipe == PIPE_A &&
-                         dev_priv->quirks & QUIRK_PIPEA_FORCE));
+               WARN_ON(!((pipe == PIPE_A && dev_priv->quirks & QUIRK_PIPEA_FORCE) ||
+                         (pipe == PIPE_B && dev_priv->quirks & QUIRK_PIPEB_FORCE)));
                return;
        }
  
  
  /**
   * intel_disable_pipe - disable a pipe, asserting requirements
-  * @dev_priv: i915 private structure
-  * @pipe: pipe to disable
-  *
-  * Disable @pipe, making sure that various hardware specific requirements
-  * are met, if applicable, e.g. plane disabled, panel fitter off, etc.
+  * @crtc: crtc whose pipes is to be disabled
   *
-  * @pipe should be %PIPE_A or %PIPE_B.
+  * Disable the pipe of @crtc, making sure that various hardware
+  * specific requirements are met, if applicable, e.g. plane
+  * disabled, panel fitter off, etc.
   *
   * Will wait until the pipe has shut down before returning.
   */
- static void intel_disable_pipe(struct drm_i915_private *dev_priv,
-                              enum pipe pipe)
+ static void intel_disable_pipe(struct intel_crtc *crtc)
  {
-       enum transcoder cpu_transcoder = intel_pipe_to_cpu_transcoder(dev_priv,
-                                                                     pipe);
+       struct drm_i915_private *dev_priv = crtc->base.dev->dev_private;
+       enum transcoder cpu_transcoder = crtc->config.cpu_transcoder;
+       enum pipe pipe = crtc->pipe;
        int reg;
        u32 val;
  
        assert_cursor_disabled(dev_priv, pipe);
        assert_sprites_disabled(dev_priv, pipe);
  
-       /* Don't disable pipe A or pipe A PLLs if needed */
-       if (pipe == PIPE_A && (dev_priv->quirks & QUIRK_PIPEA_FORCE))
-               return;
        reg = PIPECONF(cpu_transcoder);
        val = I915_READ(reg);
        if ((val & PIPECONF_ENABLE) == 0)
                return;
  
-       I915_WRITE(reg, val & ~PIPECONF_ENABLE);
-       intel_wait_for_pipe_off(dev_priv->dev, pipe);
+       /*
+        * Double wide has implications for planes
+        * so best keep it disabled when not needed.
+        */
+       if (crtc->config.double_wide)
+               val &= ~PIPECONF_DOUBLE_WIDE;
+       /* Don't disable pipe or pipe PLLs if needed */
+       if (!(pipe == PIPE_A && dev_priv->quirks & QUIRK_PIPEA_FORCE) &&
+           !(pipe == PIPE_B && dev_priv->quirks & QUIRK_PIPEB_FORCE))
+               val &= ~PIPECONF_ENABLE;
+       I915_WRITE(reg, val);
+       if ((val & PIPECONF_ENABLE) == 0)
+               intel_wait_for_pipe_off(crtc);
  }
  
  /*
@@@ -2201,15 -2219,6 +2225,15 @@@ intel_pin_and_fence_fb_obj(struct drm_d
        if (need_vtd_wa(dev) && alignment < 256 * 1024)
                alignment = 256 * 1024;
  
 +      /*
 +       * Global gtt pte registers are special registers which actually forward
 +       * writes to a chunk of system memory. Which means that there is no risk
 +       * that the register values disappear as soon as we call
 +       * intel_runtime_pm_put(), so it is correct to wrap only the
 +       * pin/unpin/fence and not more.
 +       */
 +      intel_runtime_pm_get(dev_priv);
 +
        dev_priv->mm.interruptible = false;
        ret = i915_gem_object_pin_to_display_plane(obj, alignment, pipelined);
        if (ret)
        i915_gem_object_pin_fence(obj);
  
        dev_priv->mm.interruptible = true;
 +      intel_runtime_pm_put(dev_priv);
        return 0;
  
  err_unpin:
        i915_gem_object_unpin_from_display_plane(obj);
  err_interruptible:
        dev_priv->mm.interruptible = true;
 +      intel_runtime_pm_put(dev_priv);
        return ret;
  }
  
@@@ -2390,11 -2397,12 +2414,12 @@@ static void i9xx_update_primary_plane(s
        struct drm_device *dev = crtc->dev;
        struct drm_i915_private *dev_priv = dev->dev_private;
        struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
-       struct drm_i915_gem_object *obj = intel_fb_obj(fb);
+       struct drm_i915_gem_object *obj;
        int plane = intel_crtc->plane;
        unsigned long linear_offset;
        u32 dspcntr;
        u32 reg = DSPCNTR(plane);
+       int pixel_size;
  
        if (!intel_crtc->primary_enabled) {
                I915_WRITE(reg, 0);
                return;
        }
  
+       obj = intel_fb_obj(fb);
+       if (WARN_ON(obj == NULL))
+               return;
+       pixel_size = drm_format_plane_cpp(fb->pixel_format, 0);
        dspcntr = DISPPLANE_GAMMA_ENABLE;
  
        dspcntr |= DISPLAY_PLANE_ENABLE;
        if (IS_G4X(dev))
                dspcntr |= DISPPLANE_TRICKLE_FEED_DISABLE;
  
-       I915_WRITE(reg, dspcntr);
-       linear_offset = y * fb->pitches[0] + x * (fb->bits_per_pixel / 8);
+       linear_offset = y * fb->pitches[0] + x * pixel_size;
  
        if (INTEL_INFO(dev)->gen >= 4) {
                intel_crtc->dspaddr_offset =
                        intel_gen4_compute_page_offset(&x, &y, obj->tiling_mode,
-                                                      fb->bits_per_pixel / 8,
+                                                      pixel_size,
                                                       fb->pitches[0]);
                linear_offset -= intel_crtc->dspaddr_offset;
        } else {
                intel_crtc->dspaddr_offset = linear_offset;
        }
  
+       if (to_intel_plane(crtc->primary)->rotation == BIT(DRM_ROTATE_180)) {
+               dspcntr |= DISPPLANE_ROTATE_180;
+               x += (intel_crtc->config.pipe_src_w - 1);
+               y += (intel_crtc->config.pipe_src_h - 1);
+               /* Finding the last pixel of the last line of the display
+               data and adding to linear_offset*/
+               linear_offset +=
+                       (intel_crtc->config.pipe_src_h - 1) * fb->pitches[0] +
+                       (intel_crtc->config.pipe_src_w - 1) * pixel_size;
+       }
+       I915_WRITE(reg, dspcntr);
        DRM_DEBUG_KMS("Writing base %08lX %08lX %d %d %d\n",
                      i915_gem_obj_ggtt_offset(obj), linear_offset, x, y,
                      fb->pitches[0]);
@@@ -2496,11 -2523,12 +2540,12 @@@ static void ironlake_update_primary_pla
        struct drm_device *dev = crtc->dev;
        struct drm_i915_private *dev_priv = dev->dev_private;
        struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
-       struct drm_i915_gem_object *obj = intel_fb_obj(fb);
+       struct drm_i915_gem_object *obj;
        int plane = intel_crtc->plane;
        unsigned long linear_offset;
        u32 dspcntr;
        u32 reg = DSPCNTR(plane);
+       int pixel_size;
  
        if (!intel_crtc->primary_enabled) {
                I915_WRITE(reg, 0);
                return;
        }
  
+       obj = intel_fb_obj(fb);
+       if (WARN_ON(obj == NULL))
+               return;
+       pixel_size = drm_format_plane_cpp(fb->pixel_format, 0);
        dspcntr = DISPPLANE_GAMMA_ENABLE;
  
        dspcntr |= DISPLAY_PLANE_ENABLE;
        if (!IS_HASWELL(dev) && !IS_BROADWELL(dev))
                dspcntr |= DISPPLANE_TRICKLE_FEED_DISABLE;
  
-       I915_WRITE(reg, dspcntr);
-       linear_offset = y * fb->pitches[0] + x * (fb->bits_per_pixel / 8);
+       linear_offset = y * fb->pitches[0] + x * pixel_size;
        intel_crtc->dspaddr_offset =
                intel_gen4_compute_page_offset(&x, &y, obj->tiling_mode,
-                                              fb->bits_per_pixel / 8,
+                                              pixel_size,
                                               fb->pitches[0]);
        linear_offset -= intel_crtc->dspaddr_offset;
+       if (to_intel_plane(crtc->primary)->rotation == BIT(DRM_ROTATE_180)) {
+               dspcntr |= DISPPLANE_ROTATE_180;
+               if (!IS_HASWELL(dev) && !IS_BROADWELL(dev)) {
+                       x += (intel_crtc->config.pipe_src_w - 1);
+                       y += (intel_crtc->config.pipe_src_h - 1);
+                       /* Finding the last pixel of the last line of the display
+                       data and adding to linear_offset*/
+                       linear_offset +=
+                               (intel_crtc->config.pipe_src_h - 1) * fb->pitches[0] +
+                               (intel_crtc->config.pipe_src_w - 1) * pixel_size;
+               }
+       }
+       I915_WRITE(reg, dspcntr);
  
        DRM_DEBUG_KMS("Writing base %08lX %08lX %d %d %d\n",
                      i915_gem_obj_ggtt_offset(obj), linear_offset, x, y,
@@@ -3340,23 -3388,54 +3405,54 @@@ bool intel_has_pending_fb_unpin(struct 
        return false;
  }
  
+ static void page_flip_completed(struct intel_crtc *intel_crtc)
+ {
+       struct drm_i915_private *dev_priv = to_i915(intel_crtc->base.dev);
+       struct intel_unpin_work *work = intel_crtc->unpin_work;
+       /* ensure that the unpin work is consistent wrt ->pending. */
+       smp_rmb();
+       intel_crtc->unpin_work = NULL;
+       if (work->event)
+               drm_send_vblank_event(intel_crtc->base.dev,
+                                     intel_crtc->pipe,
+                                     work->event);
+       drm_crtc_vblank_put(&intel_crtc->base);
+       wake_up_all(&dev_priv->pending_flip_queue);
+       queue_work(dev_priv->wq, &work->work);
+       trace_i915_flip_complete(intel_crtc->plane,
+                                work->pending_flip_obj);
+ }
  void intel_crtc_wait_for_pending_flips(struct drm_crtc *crtc)
  {
        struct drm_device *dev = crtc->dev;
        struct drm_i915_private *dev_priv = dev->dev_private;
  
-       if (crtc->primary->fb == NULL)
-               return;
        WARN_ON(waitqueue_active(&dev_priv->pending_flip_queue));
+       if (WARN_ON(wait_event_timeout(dev_priv->pending_flip_queue,
+                                      !intel_crtc_has_pending_flip(crtc),
+                                      60*HZ) == 0)) {
+               struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
+               unsigned long flags;
  
-       WARN_ON(wait_event_timeout(dev_priv->pending_flip_queue,
-                                  !intel_crtc_has_pending_flip(crtc),
-                                  60*HZ) == 0);
+               spin_lock_irqsave(&dev->event_lock, flags);
+               if (intel_crtc->unpin_work) {
+                       WARN_ONCE(1, "Removing stuck page flip\n");
+                       page_flip_completed(intel_crtc);
+               }
+               spin_unlock_irqrestore(&dev->event_lock, flags);
+       }
  
-       mutex_lock(&dev->struct_mutex);
-       intel_finish_fb(crtc->primary->fb);
-       mutex_unlock(&dev->struct_mutex);
+       if (crtc->primary->fb) {
+               mutex_lock(&dev->struct_mutex);
+               intel_finish_fb(crtc->primary->fb);
+               mutex_unlock(&dev->struct_mutex);
+       }
  }
  
  /* Program iCLKIP clock to the desired frequency */
@@@ -3908,8 -3987,6 +4004,8 @@@ static void intel_crtc_enable_planes(st
        struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
        int pipe = intel_crtc->pipe;
  
 +      assert_vblank_disabled(crtc);
 +
        drm_vblank_on(dev, pipe);
  
        intel_enable_primary_hw_plane(crtc->primary, crtc);
@@@ -3959,8 -4036,6 +4055,8 @@@ static void intel_crtc_disable_planes(s
        intel_frontbuffer_flip(dev, INTEL_FRONTBUFFER_ALL_MASK(pipe));
  
        drm_vblank_off(dev, pipe);
 +
 +      assert_vblank_disabled(crtc);
  }
  
  static void ironlake_crtc_enable(struct drm_crtc *crtc)
@@@ -4178,7 -4253,11 +4274,8 @@@ static void ironlake_crtc_disable(struc
        if (intel_crtc->config.has_pch_encoder)
                intel_set_pch_fifo_underrun_reporting(dev, pipe, false);
  
-       intel_disable_pipe(dev_priv, pipe);
+       intel_disable_pipe(intel_crtc);
 -      if (intel_crtc->config.dp_encoder_is_mst)
 -              intel_ddi_set_vc_payload_alloc(crtc, false);
 -
        ironlake_pfit_disable(intel_crtc);
  
        for_each_encoder_on_crtc(dev, crtc, encoder)
@@@ -4226,7 -4305,6 +4323,6 @@@ static void haswell_crtc_disable(struc
        struct drm_i915_private *dev_priv = dev->dev_private;
        struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
        struct intel_encoder *encoder;
-       int pipe = intel_crtc->pipe;
        enum transcoder cpu_transcoder = intel_crtc->config.cpu_transcoder;
  
        if (!intel_crtc->active)
  
        if (intel_crtc->config.has_pch_encoder)
                intel_set_pch_fifo_underrun_reporting(dev, TRANSCODER_A, false);
-       intel_disable_pipe(dev_priv, pipe);
+       intel_disable_pipe(intel_crtc);
  
 +      if (intel_crtc->config.dp_encoder_is_mst)
 +              intel_ddi_set_vc_payload_alloc(crtc, false);
 +
        intel_ddi_disable_transcoder_func(dev_priv, cpu_transcoder);
  
        ironlake_pfit_disable(intel_crtc);
@@@ -4831,7 -4906,7 +4927,7 @@@ static void i9xx_crtc_disable(struct dr
         */
        intel_wait_for_vblank(dev, pipe);
  
-       intel_disable_pipe(dev_priv, pipe);
+       intel_disable_pipe(intel_crtc);
  
        i9xx_pfit_disable(intel_crtc);
  
@@@ -6000,9 -6075,9 +6096,9 @@@ static void i9xx_set_pipeconf(struct in
  
        pipeconf = 0;
  
-       if (dev_priv->quirks & QUIRK_PIPEA_FORCE &&
-           I915_READ(PIPECONF(intel_crtc->pipe)) & PIPECONF_ENABLE)
-               pipeconf |= PIPECONF_ENABLE;
+       if ((intel_crtc->pipe == PIPE_A && dev_priv->quirks & QUIRK_PIPEA_FORCE) ||
+           (intel_crtc->pipe == PIPE_B && dev_priv->quirks & QUIRK_PIPEB_FORCE))
+               pipeconf |= I915_READ(PIPECONF(intel_crtc->pipe)) & PIPECONF_ENABLE;
  
        if (intel_crtc->config.double_wide)
                pipeconf |= PIPECONF_DOUBLE_WIDE;
@@@ -8263,7 -8338,6 +8359,7 @@@ static int intel_crtc_cursor_set_obj(st
                                     uint32_t width, uint32_t height)
  {
        struct drm_device *dev = crtc->dev;
 +      struct drm_i915_private *dev_priv = dev->dev_private;
        struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
        enum pipe pipe = intel_crtc->pipe;
        unsigned old_width, stride;
        if (!obj) {
                DRM_DEBUG_KMS("cursor off\n");
                addr = 0;
-               obj = NULL;
                mutex_lock(&dev->struct_mutex);
                goto finish;
        }
                        goto fail_locked;
                }
  
 +              /*
 +               * Global gtt pte registers are special registers which actually
 +               * forward writes to a chunk of system memory. Which means that
 +               * there is no risk that the register values disappear as soon
 +               * as we call intel_runtime_pm_put(), so it is correct to wrap
 +               * only the pin/unpin/fence and not more.
 +               */
 +              intel_runtime_pm_get(dev_priv);
 +
                /* Note that the w/a also requires 2 PTE of padding following
                 * the bo. We currently fill all unused PTE with the shadow
                 * page and so we should always have valid PTE following the
                ret = i915_gem_object_pin_to_display_plane(obj, alignment, NULL);
                if (ret) {
                        DRM_DEBUG_KMS("failed to move cursor bo into the GTT\n");
 +                      intel_runtime_pm_put(dev_priv);
                        goto fail_locked;
                }
  
                ret = i915_gem_object_put_fence(obj);
                if (ret) {
                        DRM_DEBUG_KMS("failed to release fence for cursor");
 +                      intel_runtime_pm_put(dev_priv);
                        goto fail_unpin;
                }
  
                addr = i915_gem_obj_ggtt_offset(obj);
 +
 +              intel_runtime_pm_put(dev_priv);
        } else {
                int align = IS_I830(dev) ? 16 * 1024 : 256;
                ret = i915_gem_object_attach_phys(obj, align);
@@@ -8994,12 -9054,13 +9089,13 @@@ static void intel_mark_fb_busy(struct d
                               unsigned frontbuffer_bits,
                               struct intel_engine_cs *ring)
  {
+       struct drm_i915_private *dev_priv = dev->dev_private;
        enum pipe pipe;
  
        if (!i915.powersave)
                return;
  
-       for_each_pipe(pipe) {
+       for_each_pipe(dev_priv, pipe) {
                if (!(frontbuffer_bits & INTEL_FRONTBUFFER_ALL_MASK(pipe)))
                        continue;
  
@@@ -9069,6 -9130,14 +9165,14 @@@ void intel_frontbuffer_flush(struct drm
        intel_mark_fb_busy(dev, frontbuffer_bits, NULL);
  
        intel_edp_psr_flush(dev, frontbuffer_bits);
+       /*
+        * FIXME: Unconditional fbc flushing here is a rather gross hack and
+        * needs to be reworked into a proper frontbuffer tracking scheme like
+        * psr employs.
+        */
+       if (IS_BROADWELL(dev))
+               gen8_fbc_sw_flush(dev, FBC_REND_CACHE_CLEAN);
  }
  
  /**
@@@ -9201,7 -9270,6 +9305,6 @@@ static void intel_unpin_work_fn(struct 
  static void do_intel_finish_page_flip(struct drm_device *dev,
                                      struct drm_crtc *crtc)
  {
-       struct drm_i915_private *dev_priv = dev->dev_private;
        struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
        struct intel_unpin_work *work;
        unsigned long flags;
                return;
        }
  
-       /* and that the unpin work is consistent wrt ->pending. */
-       smp_rmb();
-       intel_crtc->unpin_work = NULL;
-       if (work->event)
-               drm_send_vblank_event(dev, intel_crtc->pipe, work->event);
-       drm_crtc_vblank_put(crtc);
+       page_flip_completed(intel_crtc);
  
        spin_unlock_irqrestore(&dev->event_lock, flags);
-       wake_up_all(&dev_priv->pending_flip_queue);
-       queue_work(dev_priv->wq, &work->work);
-       trace_i915_flip_complete(intel_crtc->plane, work->pending_flip_obj);
  }
  
  void intel_finish_page_flip(struct drm_device *dev, int pipe)
@@@ -9717,6 -9771,65 +9806,65 @@@ static int intel_default_queue_flip(str
        return -ENODEV;
  }
  
+ static bool __intel_pageflip_stall_check(struct drm_device *dev,
+                                        struct drm_crtc *crtc)
+ {
+       struct drm_i915_private *dev_priv = dev->dev_private;
+       struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
+       struct intel_unpin_work *work = intel_crtc->unpin_work;
+       u32 addr;
+       if (atomic_read(&work->pending) >= INTEL_FLIP_COMPLETE)
+               return true;
+       if (!work->enable_stall_check)
+               return false;
+       if (work->flip_ready_vblank == 0) {
+               if (work->flip_queued_ring &&
+                   !i915_seqno_passed(work->flip_queued_ring->get_seqno(work->flip_queued_ring, true),
+                                      work->flip_queued_seqno))
+                       return false;
+               work->flip_ready_vblank = drm_vblank_count(dev, intel_crtc->pipe);
+       }
+       if (drm_vblank_count(dev, intel_crtc->pipe) - work->flip_ready_vblank < 3)
+               return false;
+       /* Potential stall - if we see that the flip has happened,
+        * assume a missed interrupt. */
+       if (INTEL_INFO(dev)->gen >= 4)
+               addr = I915_HI_DISPBASE(I915_READ(DSPSURF(intel_crtc->plane)));
+       else
+               addr = I915_READ(DSPADDR(intel_crtc->plane));
+       /* There is a potential issue here with a false positive after a flip
+        * to the same address. We could address this by checking for a
+        * non-incrementing frame counter.
+        */
+       return addr == work->gtt_offset;
+ }
+ void intel_check_page_flip(struct drm_device *dev, int 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);
+       unsigned long flags;
+       if (crtc == NULL)
+               return;
+       spin_lock_irqsave(&dev->event_lock, flags);
+       if (intel_crtc->unpin_work && __intel_pageflip_stall_check(dev, crtc)) {
+               WARN_ONCE(1, "Kicking stuck page flip: queued at %d, now %d\n",
+                        intel_crtc->unpin_work->flip_queued_vblank, drm_vblank_count(dev, pipe));
+               page_flip_completed(intel_crtc);
+       }
+       spin_unlock_irqrestore(&dev->event_lock, flags);
+ }
  static int intel_crtc_page_flip(struct drm_crtc *crtc,
                                struct drm_framebuffer *fb,
                                struct drm_pending_vblank_event *event,
        unsigned long flags;
        int ret;
  
+       //trigger software GT busyness calculation
+       gen8_flip_interrupt(dev);
        /*
         * drm_mode_page_flip_ioctl() should already catch this, but double
         * check to be safe.  In the future we may enable pageflipping from
        /* We borrow the event spin lock for protecting unpin_work */
        spin_lock_irqsave(&dev->event_lock, flags);
        if (intel_crtc->unpin_work) {
-               spin_unlock_irqrestore(&dev->event_lock, flags);
-               kfree(work);
-               drm_crtc_vblank_put(crtc);
+               /* Before declaring the flip queue wedged, check if
+                * the hardware completed the operation behind our backs.
+                */
+               if (__intel_pageflip_stall_check(dev, crtc)) {
+                       DRM_DEBUG_DRIVER("flip queue: previous flip completed, continuing\n");
+                       page_flip_completed(intel_crtc);
+               } else {
+                       DRM_DEBUG_DRIVER("flip queue: crtc already busy\n");
+                       spin_unlock_irqrestore(&dev->event_lock, flags);
  
-               DRM_DEBUG_DRIVER("flip queue: crtc already busy\n");
-               return -EBUSY;
+                       drm_crtc_vblank_put(crtc);
+                       kfree(work);
+                       return -EBUSY;
+               }
        }
        intel_crtc->unpin_work = work;
        spin_unlock_irqrestore(&dev->event_lock, flags);
  
        work->pending_flip_obj = obj;
  
-       work->enable_stall_check = true;
        atomic_inc(&intel_crtc->unpin_work_count);
        intel_crtc->reset_counter = atomic_read(&dev_priv->gpu_error.reset_counter);
  
        work->gtt_offset =
                i915_gem_obj_ggtt_offset(obj) + intel_crtc->dspaddr_offset;
  
-       if (use_mmio_flip(ring, obj))
+       if (use_mmio_flip(ring, obj)) {
                ret = intel_queue_mmio_flip(dev, crtc, fb, obj, ring,
                                            page_flip_flags);
-       else
+               if (ret)
+                       goto cleanup_unpin;
+               work->flip_queued_seqno = obj->last_write_seqno;
+               work->flip_queued_ring = obj->ring;
+       } else {
                ret = dev_priv->display.queue_flip(dev, crtc, fb, obj, ring,
-                               page_flip_flags);
-       if (ret)
-               goto cleanup_unpin;
+                                                  page_flip_flags);
+               if (ret)
+                       goto cleanup_unpin;
+               work->flip_queued_seqno = intel_ring_get_seqno(ring);
+               work->flip_queued_ring = ring;
+       }
+       work->flip_queued_vblank = drm_vblank_count(dev, intel_crtc->pipe);
+       work->enable_stall_check = true;
  
        i915_gem_track_fb(work->old_fb_obj, obj,
                          INTEL_FRONTBUFFER_PRIMARY(pipe));
@@@ -10723,8 -10857,9 +10892,9 @@@ check_crtc_state(struct drm_device *dev
                active = dev_priv->display.get_pipe_config(crtc,
                                                           &pipe_config);
  
-               /* hw state is inconsistent with the pipe A quirk */
-               if (crtc->pipe == PIPE_A && dev_priv->quirks & QUIRK_PIPEA_FORCE)
+               /* hw state is inconsistent with the pipe quirk */
+               if ((crtc->pipe == PIPE_A && dev_priv->quirks & QUIRK_PIPEA_FORCE) ||
+                   (crtc->pipe == PIPE_B && dev_priv->quirks & QUIRK_PIPEB_FORCE))
                        active = crtc->active;
  
                for_each_intel_encoder(dev, encoder) {
@@@ -11596,6 -11731,7 +11766,7 @@@ intel_primary_plane_setplane(struct drm
                             uint32_t src_w, uint32_t src_h)
  {
        struct drm_device *dev = crtc->dev;
+       struct drm_i915_private *dev_priv = dev->dev_private;
        struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
        struct drm_i915_gem_object *obj = intel_fb_obj(fb);
        struct drm_i915_gem_object *old_obj = intel_fb_obj(plane->fb);
                .x2 = intel_crtc->active ? intel_crtc->config.pipe_src_w : 0,
                .y2 = intel_crtc->active ? intel_crtc->config.pipe_src_h : 0,
        };
+       const struct {
+               int crtc_x, crtc_y;
+               unsigned int crtc_w, crtc_h;
+               uint32_t src_x, src_y, src_w, src_h;
+       } orig = {
+               .crtc_x = crtc_x,
+               .crtc_y = crtc_y,
+               .crtc_w = crtc_w,
+               .crtc_h = crtc_h,
+               .src_x = src_x,
+               .src_y = src_y,
+               .src_w = src_w,
+               .src_h = src_h,
+       };
+       struct intel_plane *intel_plane = to_intel_plane(plane);
        bool visible;
        int ret;
  
  
                mutex_unlock(&dev->struct_mutex);
  
-               return 0;
-       }
+       } else {
+               if (intel_crtc && intel_crtc->active &&
+                   intel_crtc->primary_enabled) {
+                       /*
+                        * FBC does not work on some platforms for rotated
+                        * planes, so disable it when rotation is not 0 and
+                        * update it when rotation is set back to 0.
+                        *
+                        * FIXME: This is redundant with the fbc update done in
+                        * the primary plane enable function except that that
+                        * one is done too late. We eventually need to unify
+                        * this.
+                        */
+                       if (INTEL_INFO(dev)->gen <= 4 && !IS_G4X(dev) &&
+                           dev_priv->fbc.plane == intel_crtc->plane &&
+                           intel_plane->rotation != BIT(DRM_ROTATE_0)) {
+                               intel_disable_fbc(dev);
+                       }
+               }
+               ret = intel_pipe_set_base(crtc, src.x1, src.y1, fb);
+               if (ret)
+                       return ret;
  
-       ret = intel_pipe_set_base(crtc, src.x1, src.y1, fb);
-       if (ret)
-               return ret;
+               if (!intel_crtc->primary_enabled)
+                       intel_enable_primary_hw_plane(plane, crtc);
+       }
  
-       if (!intel_crtc->primary_enabled)
-               intel_enable_primary_hw_plane(plane, crtc);
+       intel_plane->crtc_x = orig.crtc_x;
+       intel_plane->crtc_y = orig.crtc_y;
+       intel_plane->crtc_w = orig.crtc_w;
+       intel_plane->crtc_h = orig.crtc_h;
+       intel_plane->src_x = orig.src_x;
+       intel_plane->src_y = orig.src_y;
+       intel_plane->src_w = orig.src_w;
+       intel_plane->src_h = orig.src_h;
+       intel_plane->obj = obj;
  
        return 0;
  }
@@@ -11717,6 -11895,7 +11930,7 @@@ static const struct drm_plane_funcs int
        .update_plane = intel_primary_plane_setplane,
        .disable_plane = intel_primary_plane_disable,
        .destroy = intel_plane_destroy,
+       .set_property = intel_plane_set_property
  };
  
  static struct drm_plane *intel_primary_plane_create(struct drm_device *dev,
        primary->max_downscale = 1;
        primary->pipe = pipe;
        primary->plane = pipe;
+       primary->rotation = BIT(DRM_ROTATE_0);
        if (HAS_FBC(dev) && INTEL_INFO(dev)->gen < 4)
                primary->plane = !pipe;
  
                                 &intel_primary_plane_funcs,
                                 intel_primary_formats, num_formats,
                                 DRM_PLANE_TYPE_PRIMARY);
+       if (INTEL_INFO(dev)->gen >= 4) {
+               if (!dev->mode_config.rotation_property)
+                       dev->mode_config.rotation_property =
+                               drm_mode_create_rotation_property(dev,
+                                                       BIT(DRM_ROTATE_0) |
+                                                       BIT(DRM_ROTATE_180));
+               if (dev->mode_config.rotation_property)
+                       drm_object_attach_property(&primary->base.base,
+                               dev->mode_config.rotation_property,
+                               primary->rotation);
+       }
        return &primary->base;
  }
  
@@@ -12423,7 -12616,7 +12651,7 @@@ static void intel_init_display(struct d
                dev_priv->display.write_eld = ironlake_write_eld;
                dev_priv->display.modeset_global_resources =
                        ivb_modeset_global_resources;
-       } else if (IS_HASWELL(dev) || IS_GEN8(dev)) {
+       } else if (IS_HASWELL(dev) || IS_BROADWELL(dev)) {
                dev_priv->display.fdi_link_train = hsw_fdi_link_train;
                dev_priv->display.write_eld = haswell_write_eld;
                dev_priv->display.modeset_global_resources =
        }
  
        intel_panel_init_backlight_funcs(dev);
+       mutex_init(&dev_priv->pps_mutex);
  }
  
  /*
@@@ -12476,6 -12671,14 +12706,14 @@@ static void quirk_pipea_force(struct dr
        DRM_INFO("applying pipe a force quirk\n");
  }
  
+ static void quirk_pipeb_force(struct drm_device *dev)
+ {
+       struct drm_i915_private *dev_priv = dev->dev_private;
+       dev_priv->quirks |= QUIRK_PIPEB_FORCE;
+       DRM_INFO("applying pipe b force quirk\n");
+ }
  /*
   * Some machines (Lenovo U160) do not work with SSC on LVDS for some reason
   */
@@@ -12550,6 -12753,12 +12788,12 @@@ static struct intel_quirk intel_quirks[
        /* ThinkPad T60 needs pipe A force quirk (bug #16494) */
        { 0x2782, 0x17aa, 0x201a, quirk_pipea_force },
  
+       /* 830 needs to leave pipe A & dpll A up */
+       { 0x3577, PCI_ANY_ID, PCI_ANY_ID, quirk_pipea_force },
+       /* 830 needs to leave pipe B & dpll B up */
+       { 0x3577, PCI_ANY_ID, PCI_ANY_ID, quirk_pipeb_force },
        /* Lenovo U160 cannot use SSC on LVDS */
        { 0x0046, 0x17aa, 0x3920, quirk_ssc_force_disable },
  
        /* Acer C720 and C720P Chromebooks (Celeron 2955U) have backlights */
        { 0x0a06, 0x1025, 0x0a11, quirk_backlight_present },
  
 +      /* Acer C720 Chromebook (Core i3 4005U) */
 +      { 0x0a16, 0x1025, 0x0a11, quirk_backlight_present },
 +
        /* Toshiba CB35 Chromebook (Celeron 2955U) */
        { 0x0a06, 0x1179, 0x0a88, quirk_backlight_present },
  
@@@ -12623,7 -12829,11 +12867,11 @@@ static void i915_disable_vga(struct drm
        vga_put(dev->pdev, VGA_RSRC_LEGACY_IO);
        udelay(300);
  
-       I915_WRITE(vga_reg, VGA_DISP_DISABLE);
+       /*
+        * Fujitsu-Siemens Lifebook S6010 (830) has problems resuming
+        * from S3 without preserving (some of?) the other bits.
+        */
+       I915_WRITE(vga_reg, dev_priv->bios_vgacntr | VGA_DISP_DISABLE);
        POSTING_READ(vga_reg);
  }
  
@@@ -12698,7 -12908,7 +12946,7 @@@ void intel_modeset_init(struct drm_devi
                      INTEL_INFO(dev)->num_pipes,
                      INTEL_INFO(dev)->num_pipes > 1 ? "s" : "");
  
-       for_each_pipe(pipe) {
+       for_each_pipe(dev_priv, pipe) {
                intel_crtc_init(dev, pipe);
                for_each_sprite(pipe, sprite) {
                        ret = intel_plane_init(dev, pipe, sprite);
  
        intel_shared_dpll_init(dev);
  
+       /* save the BIOS value before clobbering it */
+       dev_priv->bios_vgacntr = I915_READ(i915_vgacntrl_reg(dev));
        /* Just disable it once at startup */
        i915_disable_vga(dev);
        intel_setup_outputs(dev);
@@@ -12803,10 -13015,9 +13053,10 @@@ static void intel_sanitize_crtc(struct 
        I915_WRITE(reg, I915_READ(reg) & ~PIPECONF_FRAME_START_DELAY_MASK);
  
        /* restore vblank interrupts to correct state */
 -      if (crtc->active)
 +      if (crtc->active) {
 +              update_scanline_offset(crtc);
                drm_vblank_on(dev, crtc->pipe);
 -      else
 +      else
                drm_vblank_off(dev, crtc->pipe);
  
        /* We need to sanitize the plane -> pipe mapping first because this will
                }
        }
  
-       if (crtc->active || IS_VALLEYVIEW(dev) || INTEL_INFO(dev)->gen < 5) {
+       if (crtc->active || HAS_GMCH_DISPLAY(dev)) {
                /*
                 * We start out with underrun reporting disabled to avoid races.
                 * For correct bookkeeping mark this on active crtcs.
                 */
                crtc->cpu_fifo_underrun_disabled = true;
                crtc->pch_fifo_underrun_disabled = true;
 -
 -              update_scanline_offset(crtc);
        }
  }
  
@@@ -13104,7 -13317,7 +13354,7 @@@ void intel_modeset_setup_hw_state(struc
                intel_sanitize_encoder(encoder);
        }
  
-       for_each_pipe(pipe) {
+       for_each_pipe(dev_priv, pipe) {
                crtc = to_intel_crtc(dev_priv->pipe_to_crtc_mapping[pipe]);
                intel_sanitize_crtc(crtc);
                intel_dump_pipe_config(crtc, &crtc->config, "[setup_hw_state]");
                 * We need to use raw interfaces for restoring state to avoid
                 * checking (bogus) intermediate states.
                 */
-               for_each_pipe(pipe) {
+               for_each_pipe(dev_priv, pipe) {
                        struct drm_crtc *crtc =
                                dev_priv->pipe_to_crtc_mapping[pipe];
  
@@@ -13353,7 -13566,7 +13603,7 @@@ intel_display_capture_error_state(struc
        if (IS_HASWELL(dev) || IS_BROADWELL(dev))
                error->power_well_driver = I915_READ(HSW_PWR_WELL_DRIVER);
  
-       for_each_pipe(i) {
+       for_each_pipe(dev_priv, i) {
                error->pipe[i].power_domain_on =
                        intel_display_power_enabled_unlocked(dev_priv,
                                                           POWER_DOMAIN_PIPE(i));
@@@ -13417,6 -13630,7 +13667,7 @@@ intel_display_print_error_state(struct 
                                struct drm_device *dev,
                                struct intel_display_error_state *error)
  {
+       struct drm_i915_private *dev_priv = dev->dev_private;
        int i;
  
        if (!error)
        if (IS_HASWELL(dev) || IS_BROADWELL(dev))
                err_printf(m, "PWR_WELL_CTL2: %08x\n",
                           error->power_well_driver);
-       for_each_pipe(i) {
+       for_each_pipe(dev_priv, i) {
                err_printf(m, "Pipe [%d]:\n", i);
                err_printf(m, "  Power: %s\n",
                           error->pipe[i].power_domain_on ? "on" : "off");
index a12a4d3363fd838c6425839a6968b373a4fe910d,97c5a0d11f6f5dc8e92d4f2fac5b193d948dbfda..2a26774ddb68771e9eb73c269a455c09a7c4c229
@@@ -111,7 -111,7 +111,7 @@@ static struct intel_dp *intel_attached_
  }
  
  static void intel_dp_link_down(struct intel_dp *intel_dp);
- static bool _edp_panel_vdd_on(struct intel_dp *intel_dp);
+ static bool edp_panel_vdd_on(struct intel_dp *intel_dp);
  static void edp_panel_vdd_off(struct intel_dp *intel_dp, bool sync);
  
  int
@@@ -290,32 -290,201 +290,201 @@@ intel_dp_init_panel_power_sequencer_reg
                                              struct intel_dp *intel_dp,
                                              struct edp_power_seq *out);
  
+ static void pps_lock(struct intel_dp *intel_dp)
+ {
+       struct intel_digital_port *intel_dig_port = dp_to_dig_port(intel_dp);
+       struct intel_encoder *encoder = &intel_dig_port->base;
+       struct drm_device *dev = encoder->base.dev;
+       struct drm_i915_private *dev_priv = dev->dev_private;
+       enum intel_display_power_domain power_domain;
+       /*
+        * See vlv_power_sequencer_reset() why we need
+        * a power domain reference here.
+        */
+       power_domain = intel_display_port_power_domain(encoder);
+       intel_display_power_get(dev_priv, power_domain);
+       mutex_lock(&dev_priv->pps_mutex);
+ }
+ static void pps_unlock(struct intel_dp *intel_dp)
+ {
+       struct intel_digital_port *intel_dig_port = dp_to_dig_port(intel_dp);
+       struct intel_encoder *encoder = &intel_dig_port->base;
+       struct drm_device *dev = encoder->base.dev;
+       struct drm_i915_private *dev_priv = dev->dev_private;
+       enum intel_display_power_domain power_domain;
+       mutex_unlock(&dev_priv->pps_mutex);
+       power_domain = intel_display_port_power_domain(encoder);
+       intel_display_power_put(dev_priv, power_domain);
+ }
  static enum pipe
  vlv_power_sequencer_pipe(struct intel_dp *intel_dp)
  {
        struct intel_digital_port *intel_dig_port = dp_to_dig_port(intel_dp);
-       struct drm_crtc *crtc = intel_dig_port->base.base.crtc;
        struct drm_device *dev = intel_dig_port->base.base.dev;
        struct drm_i915_private *dev_priv = dev->dev_private;
-       enum port port = intel_dig_port->port;
-       enum pipe pipe;
+       struct intel_encoder *encoder;
+       unsigned int pipes = (1 << PIPE_A) | (1 << PIPE_B);
+       struct edp_power_seq power_seq;
+       lockdep_assert_held(&dev_priv->pps_mutex);
+       if (intel_dp->pps_pipe != INVALID_PIPE)
+               return intel_dp->pps_pipe;
+       /*
+        * We don't have power sequencer currently.
+        * Pick one that's not used by other ports.
+        */
+       list_for_each_entry(encoder, &dev->mode_config.encoder_list,
+                           base.head) {
+               struct intel_dp *tmp;
+               if (encoder->type != INTEL_OUTPUT_EDP)
+                       continue;
+               tmp = enc_to_intel_dp(&encoder->base);
+               if (tmp->pps_pipe != INVALID_PIPE)
+                       pipes &= ~(1 << tmp->pps_pipe);
+       }
+       /*
+        * Didn't find one. This should not happen since there
+        * are two power sequencers and up to two eDP ports.
+        */
+       if (WARN_ON(pipes == 0))
+               return PIPE_A;
+       intel_dp->pps_pipe = ffs(pipes) - 1;
+       DRM_DEBUG_KMS("picked pipe %c power sequencer for port %c\n",
+                     pipe_name(intel_dp->pps_pipe),
+                     port_name(intel_dig_port->port));
+       /* 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);
+       return intel_dp->pps_pipe;
+ }
+ typedef bool (*vlv_pipe_check)(struct drm_i915_private *dev_priv,
+                              enum pipe pipe);
+ static bool vlv_pipe_has_pp_on(struct drm_i915_private *dev_priv,
+                              enum pipe pipe)
+ {
+       return I915_READ(VLV_PIPE_PP_STATUS(pipe)) & PP_ON;
+ }
+ static bool vlv_pipe_has_vdd_on(struct drm_i915_private *dev_priv,
+                               enum pipe pipe)
+ {
+       return I915_READ(VLV_PIPE_PP_CONTROL(pipe)) & EDP_FORCE_VDD;
+ }
+ static bool vlv_pipe_any(struct drm_i915_private *dev_priv,
+                        enum pipe pipe)
+ {
+       return true;
+ }
  
-       /* modeset should have pipe */
-       if (crtc)
-               return to_intel_crtc(crtc)->pipe;
+ static enum pipe
+ vlv_initial_pps_pipe(struct drm_i915_private *dev_priv,
+                    enum port port,
+                    vlv_pipe_check pipe_check)
+ {
+       enum pipe pipe;
  
-       /* init time, try to find a pipe with this port selected */
        for (pipe = PIPE_A; pipe <= PIPE_B; pipe++) {
                u32 port_sel = I915_READ(VLV_PIPE_PP_ON_DELAYS(pipe)) &
                        PANEL_PORT_SELECT_MASK;
-               if (port_sel == PANEL_PORT_SELECT_DPB_VLV && port == PORT_B)
-                       return pipe;
-               if (port_sel == PANEL_PORT_SELECT_DPC_VLV && port == PORT_C)
-                       return pipe;
+               if (port_sel != PANEL_PORT_SELECT_VLV(port))
+                       continue;
+               if (!pipe_check(dev_priv, pipe))
+                       continue;
+               return pipe;
+       }
+       return INVALID_PIPE;
+ }
+ static void
+ vlv_initial_power_sequencer_setup(struct intel_dp *intel_dp)
+ {
+       struct intel_digital_port *intel_dig_port = dp_to_dig_port(intel_dp);
+       struct drm_device *dev = intel_dig_port->base.base.dev;
+       struct drm_i915_private *dev_priv = dev->dev_private;
+       struct edp_power_seq power_seq;
+       enum port port = intel_dig_port->port;
+       lockdep_assert_held(&dev_priv->pps_mutex);
+       /* try to find a pipe with this port selected */
+       /* first pick one where the panel is on */
+       intel_dp->pps_pipe = vlv_initial_pps_pipe(dev_priv, port,
+                                                 vlv_pipe_has_pp_on);
+       /* didn't find one? pick one where vdd is on */
+       if (intel_dp->pps_pipe == INVALID_PIPE)
+               intel_dp->pps_pipe = vlv_initial_pps_pipe(dev_priv, port,
+                                                         vlv_pipe_has_vdd_on);
+       /* didn't find one? pick one with just the correct port */
+       if (intel_dp->pps_pipe == INVALID_PIPE)
+               intel_dp->pps_pipe = vlv_initial_pps_pipe(dev_priv, port,
+                                                         vlv_pipe_any);
+       /* didn't find one? just let vlv_power_sequencer_pipe() pick one when needed */
+       if (intel_dp->pps_pipe == INVALID_PIPE) {
+               DRM_DEBUG_KMS("no initial power sequencer for port %c\n",
+                             port_name(port));
+               return;
        }
  
-       /* shrug */
-       return PIPE_A;
+       DRM_DEBUG_KMS("initial power sequencer for port %c: pipe %c\n",
+                     port_name(port), pipe_name(intel_dp->pps_pipe));
+       intel_dp_init_panel_power_sequencer(dev, intel_dp, &power_seq);
+       intel_dp_init_panel_power_sequencer_registers(dev, intel_dp,
+                                                     &power_seq);
+ }
+ void vlv_power_sequencer_reset(struct drm_i915_private *dev_priv)
+ {
+       struct drm_device *dev = dev_priv->dev;
+       struct intel_encoder *encoder;
+       if (WARN_ON(!IS_VALLEYVIEW(dev)))
+               return;
+       /*
+        * We can't grab pps_mutex here due to deadlock with power_domain
+        * mutex when power_domain functions are called while holding pps_mutex.
+        * That also means that in order to use pps_pipe the code needs to
+        * hold both a power domain reference and pps_mutex, and the power domain
+        * reference get/put must be done while _not_ holding pps_mutex.
+        * pps_{lock,unlock}() do these steps in the correct order, so one
+        * should use them always.
+        */
+       list_for_each_entry(encoder, &dev->mode_config.encoder_list, base.head) {
+               struct intel_dp *intel_dp;
+               if (encoder->type != INTEL_OUTPUT_EDP)
+                       continue;
+               intel_dp = enc_to_intel_dp(&encoder->base);
+               intel_dp->pps_pipe = INVALID_PIPE;
+       }
  }
  
  static u32 _pp_ctrl_reg(struct intel_dp *intel_dp)
@@@ -349,12 -518,15 +518,15 @@@ static int edp_notify_handler(struct no
        struct drm_i915_private *dev_priv = dev->dev_private;
        u32 pp_div;
        u32 pp_ctrl_reg, pp_div_reg;
-       enum pipe pipe = vlv_power_sequencer_pipe(intel_dp);
  
        if (!is_edp(intel_dp) || code != SYS_RESTART)
                return 0;
  
+       pps_lock(intel_dp);
        if (IS_VALLEYVIEW(dev)) {
+               enum pipe pipe = vlv_power_sequencer_pipe(intel_dp);
                pp_ctrl_reg = VLV_PIPE_PP_CONTROL(pipe);
                pp_div_reg  = VLV_PIPE_PP_DIVISOR(pipe);
                pp_div = I915_READ(pp_div_reg);
                msleep(intel_dp->panel_power_cycle_delay);
        }
  
+       pps_unlock(intel_dp);
        return 0;
  }
  
@@@ -374,6 -548,8 +548,8 @@@ static bool edp_have_panel_power(struc
        struct drm_device *dev = intel_dp_to_dev(intel_dp);
        struct drm_i915_private *dev_priv = dev->dev_private;
  
+       lockdep_assert_held(&dev_priv->pps_mutex);
        return (I915_READ(_pp_stat_reg(intel_dp)) & PP_ON) != 0;
  }
  
@@@ -381,13 -557,10 +557,10 @@@ static bool edp_have_panel_vdd(struct i
  {
        struct drm_device *dev = intel_dp_to_dev(intel_dp);
        struct drm_i915_private *dev_priv = dev->dev_private;
-       struct intel_digital_port *intel_dig_port = dp_to_dig_port(intel_dp);
-       struct intel_encoder *intel_encoder = &intel_dig_port->base;
-       enum intel_display_power_domain power_domain;
  
-       power_domain = intel_display_port_power_domain(intel_encoder);
-       return intel_display_power_enabled(dev_priv, power_domain) &&
-              (I915_READ(_pp_ctrl_reg(intel_dp)) & EDP_FORCE_VDD) != 0;
+       lockdep_assert_held(&dev_priv->pps_mutex);
+       return I915_READ(_pp_ctrl_reg(intel_dp)) & EDP_FORCE_VDD;
  }
  
  static void
@@@ -535,7 -708,15 +708,15 @@@ intel_dp_aux_ch(struct intel_dp *intel_
        bool has_aux_irq = HAS_AUX_IRQ(dev);
        bool vdd;
  
-       vdd = _edp_panel_vdd_on(intel_dp);
+       pps_lock(intel_dp);
+       /*
+        * We will be called with VDD already enabled for dpcd/edid/oui reads.
+        * In such cases we want to leave VDD enabled and it's up to upper layers
+        * to turn it off. But for eg. i2c-dev access we need to turn it on/off
+        * ourselves.
+        */
+       vdd = edp_panel_vdd_on(intel_dp);
  
        /* dp aux is extremely sensitive to irq latency, hence request the
         * lowest possible wakeup latency and so prevent the cpu from going into
@@@ -644,6 -825,8 +825,8 @@@ out
        if (vdd)
                edp_panel_vdd_off(intel_dp, false);
  
+       pps_unlock(intel_dp);
        return ret;
  }
  
@@@ -1098,6 -1281,8 +1281,8 @@@ static void wait_panel_status(struct in
        struct drm_i915_private *dev_priv = dev->dev_private;
        u32 pp_stat_reg, pp_ctrl_reg;
  
+       lockdep_assert_held(&dev_priv->pps_mutex);
        pp_stat_reg = _pp_stat_reg(intel_dp);
        pp_ctrl_reg = _pp_ctrl_reg(intel_dp);
  
@@@ -1161,13 -1346,20 +1346,20 @@@ static  u32 ironlake_get_pp_control(str
        struct drm_i915_private *dev_priv = dev->dev_private;
        u32 control;
  
+       lockdep_assert_held(&dev_priv->pps_mutex);
        control = I915_READ(_pp_ctrl_reg(intel_dp));
        control &= ~PANEL_UNLOCK_MASK;
        control |= PANEL_UNLOCK_REGS;
        return control;
  }
  
- static bool _edp_panel_vdd_on(struct intel_dp *intel_dp)
+ /*
+  * Must be paired with edp_panel_vdd_off().
+  * Must hold pps_mutex around the whole on/off sequence.
+  * Can be nested with intel_edp_panel_vdd_{on,off}() calls.
+  */
+ static bool edp_panel_vdd_on(struct intel_dp *intel_dp)
  {
        struct drm_device *dev = intel_dp_to_dev(intel_dp);
        struct intel_digital_port *intel_dig_port = dp_to_dig_port(intel_dp);
        u32 pp_stat_reg, pp_ctrl_reg;
        bool need_to_disable = !intel_dp->want_panel_vdd;
  
+       lockdep_assert_held(&dev_priv->pps_mutex);
        if (!is_edp(intel_dp))
                return false;
  
        return need_to_disable;
  }
  
+ /*
+  * Must be paired with intel_edp_panel_vdd_off() or
+  * intel_edp_panel_off().
+  * Nested calls to these functions are not allowed since
+  * we drop the lock. Caller must use some higher level
+  * locking to prevent nested calls from other threads.
+  */
  void intel_edp_panel_vdd_on(struct intel_dp *intel_dp)
  {
-       if (is_edp(intel_dp)) {
-               bool vdd = _edp_panel_vdd_on(intel_dp);
+       bool vdd;
  
-               WARN(!vdd, "eDP VDD already requested on\n");
-       }
+       if (!is_edp(intel_dp))
+               return;
+       pps_lock(intel_dp);
+       vdd = edp_panel_vdd_on(intel_dp);
+       pps_unlock(intel_dp);
+       WARN(!vdd, "eDP VDD already requested on\n");
  }
  
  static void edp_panel_vdd_off_sync(struct intel_dp *intel_dp)
  {
        struct drm_device *dev = intel_dp_to_dev(intel_dp);
        struct drm_i915_private *dev_priv = dev->dev_private;
+       struct intel_digital_port *intel_dig_port =
+               dp_to_dig_port(intel_dp);
+       struct intel_encoder *intel_encoder = &intel_dig_port->base;
+       enum intel_display_power_domain power_domain;
        u32 pp;
        u32 pp_stat_reg, pp_ctrl_reg;
  
-       WARN_ON(!drm_modeset_is_locked(&dev->mode_config.connection_mutex));
+       lockdep_assert_held(&dev_priv->pps_mutex);
  
-       if (!intel_dp->want_panel_vdd && edp_have_panel_vdd(intel_dp)) {
-               struct intel_digital_port *intel_dig_port =
-                                               dp_to_dig_port(intel_dp);
-               struct intel_encoder *intel_encoder = &intel_dig_port->base;
-               enum intel_display_power_domain power_domain;
+       WARN_ON(intel_dp->want_panel_vdd);
  
-               DRM_DEBUG_KMS("Turning eDP VDD off\n");
+       if (!edp_have_panel_vdd(intel_dp))
+               return;
  
-               pp = ironlake_get_pp_control(intel_dp);
-               pp &= ~EDP_FORCE_VDD;
+       DRM_DEBUG_KMS("Turning eDP VDD off\n");
  
-               pp_ctrl_reg = _pp_ctrl_reg(intel_dp);
-               pp_stat_reg = _pp_stat_reg(intel_dp);
+       pp = ironlake_get_pp_control(intel_dp);
+       pp &= ~EDP_FORCE_VDD;
  
-               I915_WRITE(pp_ctrl_reg, pp);
-               POSTING_READ(pp_ctrl_reg);
+       pp_ctrl_reg = _pp_ctrl_reg(intel_dp);
+       pp_stat_reg = _pp_stat_reg(intel_dp);
+       I915_WRITE(pp_ctrl_reg, pp);
+       POSTING_READ(pp_ctrl_reg);
  
-               /* Make sure sequencer is idle before allowing subsequent activity */
-               DRM_DEBUG_KMS("PP_STATUS: 0x%08x PP_CONTROL: 0x%08x\n",
-               I915_READ(pp_stat_reg), I915_READ(pp_ctrl_reg));
+       /* Make sure sequencer is idle before allowing subsequent activity */
+       DRM_DEBUG_KMS("PP_STATUS: 0x%08x PP_CONTROL: 0x%08x\n",
+       I915_READ(pp_stat_reg), I915_READ(pp_ctrl_reg));
  
-               if ((pp & POWER_TARGET_ON) == 0)
-                       intel_dp->last_power_cycle = jiffies;
+       if ((pp & POWER_TARGET_ON) == 0)
+               intel_dp->last_power_cycle = jiffies;
  
-               power_domain = intel_display_port_power_domain(intel_encoder);
-               intel_display_power_put(dev_priv, power_domain);
-       }
+       power_domain = intel_display_port_power_domain(intel_encoder);
+       intel_display_power_put(dev_priv, power_domain);
  }
  
  static void edp_panel_vdd_work(struct work_struct *__work)
  {
        struct intel_dp *intel_dp = container_of(to_delayed_work(__work),
                                                 struct intel_dp, panel_vdd_work);
-       struct drm_device *dev = intel_dp_to_dev(intel_dp);
  
-       drm_modeset_lock(&dev->mode_config.connection_mutex, NULL);
-       edp_panel_vdd_off_sync(intel_dp);
-       drm_modeset_unlock(&dev->mode_config.connection_mutex);
+       pps_lock(intel_dp);
+       if (!intel_dp->want_panel_vdd)
+               edp_panel_vdd_off_sync(intel_dp);
+       pps_unlock(intel_dp);
  }
  
  static void edp_panel_vdd_schedule_off(struct intel_dp *intel_dp)
        schedule_delayed_work(&intel_dp->panel_vdd_work, delay);
  }
  
+ /*
+  * Must be paired with edp_panel_vdd_on().
+  * Must hold pps_mutex around the whole on/off sequence.
+  * Can be nested with intel_edp_panel_vdd_{on,off}() calls.
+  */
  static void edp_panel_vdd_off(struct intel_dp *intel_dp, bool sync)
  {
+       struct drm_i915_private *dev_priv =
+               intel_dp_to_dev(intel_dp)->dev_private;
+       lockdep_assert_held(&dev_priv->pps_mutex);
        if (!is_edp(intel_dp))
                return;
  
                edp_panel_vdd_schedule_off(intel_dp);
  }
  
+ /*
+  * Must be paired with intel_edp_panel_vdd_on().
+  * Nested calls to these functions are not allowed since
+  * we drop the lock. Caller must use some higher level
+  * locking to prevent nested calls from other threads.
+  */
+ static void intel_edp_panel_vdd_off(struct intel_dp *intel_dp, bool sync)
+ {
+       if (!is_edp(intel_dp))
+               return;
+       pps_lock(intel_dp);
+       edp_panel_vdd_off(intel_dp, sync);
+       pps_unlock(intel_dp);
+ }
  void intel_edp_panel_on(struct intel_dp *intel_dp)
  {
        struct drm_device *dev = intel_dp_to_dev(intel_dp);
  
        DRM_DEBUG_KMS("Turn eDP power on\n");
  
+       pps_lock(intel_dp);
        if (edp_have_panel_power(intel_dp)) {
                DRM_DEBUG_KMS("eDP power already on\n");
-               return;
+               goto out;
        }
  
        wait_panel_power_cycle(intel_dp);
                I915_WRITE(pp_ctrl_reg, pp);
                POSTING_READ(pp_ctrl_reg);
        }
+  out:
+       pps_unlock(intel_dp);
  }
  
  void intel_edp_panel_off(struct intel_dp *intel_dp)
  
        DRM_DEBUG_KMS("Turn eDP power off\n");
  
+       pps_lock(intel_dp);
        WARN(!intel_dp->want_panel_vdd, "Need VDD to turn off panel\n");
  
        pp = ironlake_get_pp_control(intel_dp);
        /* We got a reference when we enabled the VDD. */
        power_domain = intel_display_port_power_domain(intel_encoder);
        intel_display_power_put(dev_priv, power_domain);
+       pps_unlock(intel_dp);
  }
  
- void intel_edp_backlight_on(struct intel_dp *intel_dp)
+ /* Enable backlight in the panel power control. */
+ static void _intel_edp_backlight_on(struct intel_dp *intel_dp)
  {
        struct intel_digital_port *intel_dig_port = dp_to_dig_port(intel_dp);
        struct drm_device *dev = intel_dig_port->base.base.dev;
        u32 pp;
        u32 pp_ctrl_reg;
  
-       if (!is_edp(intel_dp))
-               return;
-       DRM_DEBUG_KMS("\n");
-       intel_panel_enable_backlight(intel_dp->attached_connector);
        /*
         * If we enable the backlight right away following a panel power
         * on, we may see slight flicker as the panel syncs with the eDP
         * allowing it to appear.
         */
        wait_backlight_on(intel_dp);
+       pps_lock(intel_dp);
        pp = ironlake_get_pp_control(intel_dp);
        pp |= EDP_BLC_ENABLE;
  
  
        I915_WRITE(pp_ctrl_reg, pp);
        POSTING_READ(pp_ctrl_reg);
+       pps_unlock(intel_dp);
  }
  
- void intel_edp_backlight_off(struct intel_dp *intel_dp)
+ /* Enable backlight PWM and backlight PP control. */
+ void intel_edp_backlight_on(struct intel_dp *intel_dp)
+ {
+       if (!is_edp(intel_dp))
+               return;
+       DRM_DEBUG_KMS("\n");
+       intel_panel_enable_backlight(intel_dp->attached_connector);
+       _intel_edp_backlight_on(intel_dp);
+ }
+ /* Disable backlight in the panel power control. */
+ static void _intel_edp_backlight_off(struct intel_dp *intel_dp)
  {
        struct drm_device *dev = intel_dp_to_dev(intel_dp);
        struct drm_i915_private *dev_priv = dev->dev_private;
        if (!is_edp(intel_dp))
                return;
  
-       DRM_DEBUG_KMS("\n");
+       pps_lock(intel_dp);
        pp = ironlake_get_pp_control(intel_dp);
        pp &= ~EDP_BLC_ENABLE;
  
  
        I915_WRITE(pp_ctrl_reg, pp);
        POSTING_READ(pp_ctrl_reg);
-       intel_dp->last_backlight_off = jiffies;
  
+       pps_unlock(intel_dp);
+       intel_dp->last_backlight_off = jiffies;
        edp_wait_backlight_off(intel_dp);
+ }
  
+ /* Disable backlight PP control and backlight PWM. */
+ void intel_edp_backlight_off(struct intel_dp *intel_dp)
+ {
+       if (!is_edp(intel_dp))
+               return;
+       DRM_DEBUG_KMS("\n");
+       _intel_edp_backlight_off(intel_dp);
        intel_panel_disable_backlight(intel_dp->attached_connector);
  }
  
+ /*
+  * Hook for controlling the panel power control backlight through the bl_power
+  * sysfs attribute. Take care to handle multiple calls.
+  */
+ static void intel_edp_backlight_power(struct intel_connector *connector,
+                                     bool enable)
+ {
+       struct intel_dp *intel_dp = intel_attached_dp(&connector->base);
+       bool is_enabled;
+       pps_lock(intel_dp);
+       is_enabled = ironlake_get_pp_control(intel_dp) & EDP_BLC_ENABLE;
+       pps_unlock(intel_dp);
+       if (is_enabled == enable)
+               return;
+       DRM_DEBUG_KMS("panel power control backlight %s\n",
+                     enable ? "enable" : "disable");
+       if (enable)
+               _intel_edp_backlight_on(intel_dp);
+       else
+               _intel_edp_backlight_off(intel_dp);
+ }
  static void ironlake_edp_pll_on(struct intel_dp *intel_dp)
  {
        struct intel_digital_port *intel_dig_port = dp_to_dig_port(intel_dp);
@@@ -1503,8 -1797,6 +1797,6 @@@ void intel_dp_sink_dpms(struct intel_d
        if (mode != DRM_MODE_DPMS_ON) {
                ret = drm_dp_dpcd_writeb(&intel_dp->aux, DP_SET_POWER,
                                         DP_SET_POWER_D3);
-               if (ret != 1)
-                       DRM_DEBUG_DRIVER("failed to write sink power state\n");
        } else {
                /*
                 * When turning on, we need to retry for 1ms to give the sink
                        msleep(1);
                }
        }
+       if (ret != 1)
+               DRM_DEBUG_KMS("failed to %s sink power state\n",
+                             mode == DRM_MODE_DPMS_ON ? "enable" : "disable");
  }
  
  static bool intel_dp_get_hw_state(struct intel_encoder *encoder,
                        return true;
                }
  
-               for_each_pipe(i) {
+               for_each_pipe(dev_priv, i) {
                        trans_dp = I915_READ(TRANS_DP_CTL(i));
                        if ((trans_dp & TRANS_DP_PORT_SEL_MASK) == trans_sel) {
                                *pipe = i;
@@@ -2020,7 -2316,6 +2316,6 @@@ void intel_edp_psr_init(struct drm_devi
  static void intel_disable_dp(struct intel_encoder *encoder)
  {
        struct intel_dp *intel_dp = enc_to_intel_dp(&encoder->base);
-       enum port port = dp_to_dig_port(intel_dp)->port;
        struct drm_device *dev = encoder->base.dev;
  
        /* Make sure the panel is off before trying to change the mode. But also
        intel_dp_sink_dpms(intel_dp, DRM_MODE_DPMS_OFF);
        intel_edp_panel_off(intel_dp);
  
-       /* cpu edp my only be disable _after_ the cpu pipe/plane is disabled. */
-       if (!(port == PORT_A || IS_VALLEYVIEW(dev)))
+       /* disable the port before the pipe on g4x */
+       if (INTEL_INFO(dev)->gen < 5)
                intel_dp_link_down(intel_dp);
  }
  
- static void g4x_post_disable_dp(struct intel_encoder *encoder)
+ static void ilk_post_disable_dp(struct intel_encoder *encoder)
  {
        struct intel_dp *intel_dp = enc_to_intel_dp(&encoder->base);
        enum port port = dp_to_dig_port(intel_dp)->port;
  
-       if (port != PORT_A)
-               return;
        intel_dp_link_down(intel_dp);
-       ironlake_edp_pll_off(intel_dp);
+       if (port == PORT_A)
+               ironlake_edp_pll_off(intel_dp);
  }
  
  static void vlv_post_disable_dp(struct intel_encoder *encoder)
@@@ -2090,6 -2383,104 +2383,104 @@@ static void chv_post_disable_dp(struct 
        mutex_unlock(&dev_priv->dpio_lock);
  }
  
+ static void
+ _intel_dp_set_link_train(struct intel_dp *intel_dp,
+                        uint32_t *DP,
+                        uint8_t dp_train_pat)
+ {
+       struct intel_digital_port *intel_dig_port = dp_to_dig_port(intel_dp);
+       struct drm_device *dev = intel_dig_port->base.base.dev;
+       struct drm_i915_private *dev_priv = dev->dev_private;
+       enum port port = intel_dig_port->port;
+       if (HAS_DDI(dev)) {
+               uint32_t temp = I915_READ(DP_TP_CTL(port));
+               if (dp_train_pat & DP_LINK_SCRAMBLING_DISABLE)
+                       temp |= DP_TP_CTL_SCRAMBLE_DISABLE;
+               else
+                       temp &= ~DP_TP_CTL_SCRAMBLE_DISABLE;
+               temp &= ~DP_TP_CTL_LINK_TRAIN_MASK;
+               switch (dp_train_pat & DP_TRAINING_PATTERN_MASK) {
+               case DP_TRAINING_PATTERN_DISABLE:
+                       temp |= DP_TP_CTL_LINK_TRAIN_NORMAL;
+                       break;
+               case DP_TRAINING_PATTERN_1:
+                       temp |= DP_TP_CTL_LINK_TRAIN_PAT1;
+                       break;
+               case DP_TRAINING_PATTERN_2:
+                       temp |= DP_TP_CTL_LINK_TRAIN_PAT2;
+                       break;
+               case DP_TRAINING_PATTERN_3:
+                       temp |= DP_TP_CTL_LINK_TRAIN_PAT3;
+                       break;
+               }
+               I915_WRITE(DP_TP_CTL(port), temp);
+       } else if (HAS_PCH_CPT(dev) && (IS_GEN7(dev) || port != PORT_A)) {
+               *DP &= ~DP_LINK_TRAIN_MASK_CPT;
+               switch (dp_train_pat & DP_TRAINING_PATTERN_MASK) {
+               case DP_TRAINING_PATTERN_DISABLE:
+                       *DP |= DP_LINK_TRAIN_OFF_CPT;
+                       break;
+               case DP_TRAINING_PATTERN_1:
+                       *DP |= DP_LINK_TRAIN_PAT_1_CPT;
+                       break;
+               case DP_TRAINING_PATTERN_2:
+                       *DP |= DP_LINK_TRAIN_PAT_2_CPT;
+                       break;
+               case DP_TRAINING_PATTERN_3:
+                       DRM_ERROR("DP training pattern 3 not supported\n");
+                       *DP |= DP_LINK_TRAIN_PAT_2_CPT;
+                       break;
+               }
+       } else {
+               if (IS_CHERRYVIEW(dev))
+                       *DP &= ~DP_LINK_TRAIN_MASK_CHV;
+               else
+                       *DP &= ~DP_LINK_TRAIN_MASK;
+               switch (dp_train_pat & DP_TRAINING_PATTERN_MASK) {
+               case DP_TRAINING_PATTERN_DISABLE:
+                       *DP |= DP_LINK_TRAIN_OFF;
+                       break;
+               case DP_TRAINING_PATTERN_1:
+                       *DP |= DP_LINK_TRAIN_PAT_1;
+                       break;
+               case DP_TRAINING_PATTERN_2:
+                       *DP |= DP_LINK_TRAIN_PAT_2;
+                       break;
+               case DP_TRAINING_PATTERN_3:
+                       if (IS_CHERRYVIEW(dev)) {
+                               *DP |= DP_LINK_TRAIN_PAT_3_CHV;
+                       } else {
+                               DRM_ERROR("DP training pattern 3 not supported\n");
+                               *DP |= DP_LINK_TRAIN_PAT_2;
+                       }
+                       break;
+               }
+       }
+ }
+ static void intel_dp_enable_port(struct intel_dp *intel_dp)
+ {
+       struct drm_device *dev = intel_dp_to_dev(intel_dp);
+       struct drm_i915_private *dev_priv = dev->dev_private;
+       intel_dp->DP |= DP_PORT_EN;
+       /* enable with pattern 1 (as per spec) */
+       _intel_dp_set_link_train(intel_dp, &intel_dp->DP,
+                                DP_TRAINING_PATTERN_1);
+       I915_WRITE(intel_dp->output_reg, intel_dp->DP);
+       POSTING_READ(intel_dp->output_reg);
+ }
  static void intel_enable_dp(struct intel_encoder *encoder)
  {
        struct intel_dp *intel_dp = enc_to_intel_dp(&encoder->base);
        if (WARN_ON(dp_reg & DP_PORT_EN))
                return;
  
+       intel_dp_enable_port(intel_dp);
        intel_edp_panel_vdd_on(intel_dp);
+       intel_edp_panel_on(intel_dp);
+       intel_edp_panel_vdd_off(intel_dp, true);
        intel_dp_sink_dpms(intel_dp, DRM_MODE_DPMS_ON);
        intel_dp_start_link_train(intel_dp);
-       intel_edp_panel_on(intel_dp);
-       edp_panel_vdd_off(intel_dp, true);
        intel_dp_complete_link_train(intel_dp);
        intel_dp_stop_link_train(intel_dp);
  }
@@@ -2138,6 -2530,78 +2530,78 @@@ static void g4x_pre_enable_dp(struct in
        }
  }
  
+ static void vlv_steal_power_sequencer(struct drm_device *dev,
+                                     enum pipe pipe)
+ {
+       struct drm_i915_private *dev_priv = dev->dev_private;
+       struct intel_encoder *encoder;
+       lockdep_assert_held(&dev_priv->pps_mutex);
+       list_for_each_entry(encoder, &dev->mode_config.encoder_list,
+                           base.head) {
+               struct intel_dp *intel_dp;
+               enum port port;
+               if (encoder->type != INTEL_OUTPUT_EDP)
+                       continue;
+               intel_dp = enc_to_intel_dp(&encoder->base);
+               port = dp_to_dig_port(intel_dp)->port;
+               if (intel_dp->pps_pipe != pipe)
+                       continue;
+               DRM_DEBUG_KMS("stealing pipe %c power sequencer from port %c\n",
+                             pipe_name(pipe), port_name(port));
+               /* make sure vdd is off before we steal it */
+               edp_panel_vdd_off_sync(intel_dp);
+               intel_dp->pps_pipe = INVALID_PIPE;
+       }
+ }
+ static void vlv_init_panel_power_sequencer(struct intel_dp *intel_dp)
+ {
+       struct intel_digital_port *intel_dig_port = dp_to_dig_port(intel_dp);
+       struct intel_encoder *encoder = &intel_dig_port->base;
+       struct drm_device *dev = encoder->base.dev;
+       struct drm_i915_private *dev_priv = dev->dev_private;
+       struct intel_crtc *crtc = to_intel_crtc(encoder->base.crtc);
+       struct edp_power_seq power_seq;
+       lockdep_assert_held(&dev_priv->pps_mutex);
+       if (intel_dp->pps_pipe == crtc->pipe)
+               return;
+       /*
+        * If another power sequencer was being used on this
+        * port previously make sure to turn off vdd there while
+        * we still have control of it.
+        */
+       if (intel_dp->pps_pipe != INVALID_PIPE)
+               edp_panel_vdd_off_sync(intel_dp);
+       /*
+        * We may be stealing the power
+        * sequencer from another port.
+        */
+       vlv_steal_power_sequencer(dev, crtc->pipe);
+       /* now it's all ours */
+       intel_dp->pps_pipe = crtc->pipe;
+       DRM_DEBUG_KMS("initializing pipe %c power sequencer for port %c\n",
+                     pipe_name(intel_dp->pps_pipe), port_name(intel_dig_port->port));
+       /* 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);
+ }
  static void vlv_pre_enable_dp(struct intel_encoder *encoder)
  {
        struct intel_dp *intel_dp = enc_to_intel_dp(&encoder->base);
        struct intel_crtc *intel_crtc = to_intel_crtc(encoder->base.crtc);
        enum dpio_channel port = vlv_dport_to_channel(dport);
        int pipe = intel_crtc->pipe;
-       struct edp_power_seq power_seq;
        u32 val;
  
        mutex_lock(&dev_priv->dpio_lock);
        mutex_unlock(&dev_priv->dpio_lock);
  
        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);
+               pps_lock(intel_dp);
+               vlv_init_panel_power_sequencer(intel_dp);
+               pps_unlock(intel_dp);
        }
  
        intel_enable_dp(encoder);
@@@ -2213,7 -2675,6 +2675,6 @@@ static void chv_pre_enable_dp(struct in
        struct intel_digital_port *dport = dp_to_dig_port(intel_dp);
        struct drm_device *dev = encoder->base.dev;
        struct drm_i915_private *dev_priv = dev->dev_private;
-       struct edp_power_seq power_seq;
        struct intel_crtc *intel_crtc =
                to_intel_crtc(encoder->base.crtc);
        enum dpio_channel ch = vlv_dport_to_channel(dport);
        mutex_unlock(&dev_priv->dpio_lock);
  
        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);
+               pps_lock(intel_dp);
+               vlv_init_panel_power_sequencer(intel_dp);
+               pps_unlock(intel_dp);
        }
  
        intel_enable_dp(encoder);
@@@ -2381,13 -2841,13 +2841,13 @@@ intel_dp_voltage_max(struct intel_dp *i
        enum port port = dp_to_dig_port(intel_dp)->port;
  
        if (IS_VALLEYVIEW(dev))
-               return DP_TRAIN_VOLTAGE_SWING_1200;
+               return DP_TRAIN_VOLTAGE_SWING_LEVEL_3;
        else if (IS_GEN7(dev) && port == PORT_A)
-               return DP_TRAIN_VOLTAGE_SWING_800;
+               return DP_TRAIN_VOLTAGE_SWING_LEVEL_2;
        else if (HAS_PCH_CPT(dev) && port != PORT_A)
-               return DP_TRAIN_VOLTAGE_SWING_1200;
+               return DP_TRAIN_VOLTAGE_SWING_LEVEL_3;
        else
-               return DP_TRAIN_VOLTAGE_SWING_800;
+               return DP_TRAIN_VOLTAGE_SWING_LEVEL_2;
  }
  
  static uint8_t
@@@ -2398,49 -2858,49 +2858,49 @@@ intel_dp_pre_emphasis_max(struct intel_
  
        if (IS_HASWELL(dev) || IS_BROADWELL(dev)) {
                switch (voltage_swing & DP_TRAIN_VOLTAGE_SWING_MASK) {
-               case DP_TRAIN_VOLTAGE_SWING_400:
-                       return DP_TRAIN_PRE_EMPHASIS_9_5;
-               case DP_TRAIN_VOLTAGE_SWING_600:
-                       return DP_TRAIN_PRE_EMPHASIS_6;
-               case DP_TRAIN_VOLTAGE_SWING_800:
-                       return DP_TRAIN_PRE_EMPHASIS_3_5;
-               case DP_TRAIN_VOLTAGE_SWING_1200:
+               case DP_TRAIN_VOLTAGE_SWING_LEVEL_0:
+                       return DP_TRAIN_PRE_EMPH_LEVEL_3;
+               case DP_TRAIN_VOLTAGE_SWING_LEVEL_1:
+                       return DP_TRAIN_PRE_EMPH_LEVEL_2;
+               case DP_TRAIN_VOLTAGE_SWING_LEVEL_2:
+                       return DP_TRAIN_PRE_EMPH_LEVEL_1;
+               case DP_TRAIN_VOLTAGE_SWING_LEVEL_3:
                default:
-                       return DP_TRAIN_PRE_EMPHASIS_0;
+                       return DP_TRAIN_PRE_EMPH_LEVEL_0;
                }
        } else if (IS_VALLEYVIEW(dev)) {
                switch (voltage_swing & DP_TRAIN_VOLTAGE_SWING_MASK) {
-               case DP_TRAIN_VOLTAGE_SWING_400:
-                       return DP_TRAIN_PRE_EMPHASIS_9_5;
-               case DP_TRAIN_VOLTAGE_SWING_600:
-                       return DP_TRAIN_PRE_EMPHASIS_6;
-               case DP_TRAIN_VOLTAGE_SWING_800:
-                       return DP_TRAIN_PRE_EMPHASIS_3_5;
-               case DP_TRAIN_VOLTAGE_SWING_1200:
+               case DP_TRAIN_VOLTAGE_SWING_LEVEL_0:
+                       return DP_TRAIN_PRE_EMPH_LEVEL_3;
+               case DP_TRAIN_VOLTAGE_SWING_LEVEL_1:
+                       return DP_TRAIN_PRE_EMPH_LEVEL_2;
+               case DP_TRAIN_VOLTAGE_SWING_LEVEL_2:
+                       return DP_TRAIN_PRE_EMPH_LEVEL_1;
+               case DP_TRAIN_VOLTAGE_SWING_LEVEL_3:
                default:
-                       return DP_TRAIN_PRE_EMPHASIS_0;
+                       return DP_TRAIN_PRE_EMPH_LEVEL_0;
                }
        } else if (IS_GEN7(dev) && port == PORT_A) {
                switch (voltage_swing & DP_TRAIN_VOLTAGE_SWING_MASK) {
-               case DP_TRAIN_VOLTAGE_SWING_400:
-                       return DP_TRAIN_PRE_EMPHASIS_6;
-               case DP_TRAIN_VOLTAGE_SWING_600:
-               case DP_TRAIN_VOLTAGE_SWING_800:
-                       return DP_TRAIN_PRE_EMPHASIS_3_5;
+               case DP_TRAIN_VOLTAGE_SWING_LEVEL_0:
+                       return DP_TRAIN_PRE_EMPH_LEVEL_2;
+               case DP_TRAIN_VOLTAGE_SWING_LEVEL_1:
+               case DP_TRAIN_VOLTAGE_SWING_LEVEL_2:
+                       return DP_TRAIN_PRE_EMPH_LEVEL_1;
                default:
-                       return DP_TRAIN_PRE_EMPHASIS_0;
+                       return DP_TRAIN_PRE_EMPH_LEVEL_0;
                }
        } else {
                switch (voltage_swing & DP_TRAIN_VOLTAGE_SWING_MASK) {
-               case DP_TRAIN_VOLTAGE_SWING_400:
-                       return DP_TRAIN_PRE_EMPHASIS_6;
-               case DP_TRAIN_VOLTAGE_SWING_600:
-                       return DP_TRAIN_PRE_EMPHASIS_6;
-               case DP_TRAIN_VOLTAGE_SWING_800:
-                       return DP_TRAIN_PRE_EMPHASIS_3_5;
-               case DP_TRAIN_VOLTAGE_SWING_1200:
+               case DP_TRAIN_VOLTAGE_SWING_LEVEL_0:
+                       return DP_TRAIN_PRE_EMPH_LEVEL_2;
+               case DP_TRAIN_VOLTAGE_SWING_LEVEL_1:
+                       return DP_TRAIN_PRE_EMPH_LEVEL_2;
+               case DP_TRAIN_VOLTAGE_SWING_LEVEL_2:
+                       return DP_TRAIN_PRE_EMPH_LEVEL_1;
+               case DP_TRAIN_VOLTAGE_SWING_LEVEL_3:
                default:
-                       return DP_TRAIN_PRE_EMPHASIS_0;
+                       return DP_TRAIN_PRE_EMPH_LEVEL_0;
                }
        }
  }
@@@ -2459,22 -2919,22 +2919,22 @@@ static uint32_t intel_vlv_signal_levels
        int pipe = intel_crtc->pipe;
  
        switch (train_set & DP_TRAIN_PRE_EMPHASIS_MASK) {
-       case DP_TRAIN_PRE_EMPHASIS_0:
+       case DP_TRAIN_PRE_EMPH_LEVEL_0:
                preemph_reg_value = 0x0004000;
                switch (train_set & DP_TRAIN_VOLTAGE_SWING_MASK) {
-               case DP_TRAIN_VOLTAGE_SWING_400:
+               case DP_TRAIN_VOLTAGE_SWING_LEVEL_0:
                        demph_reg_value = 0x2B405555;
                        uniqtranscale_reg_value = 0x552AB83A;
                        break;
-               case DP_TRAIN_VOLTAGE_SWING_600:
+               case DP_TRAIN_VOLTAGE_SWING_LEVEL_1:
                        demph_reg_value = 0x2B404040;
                        uniqtranscale_reg_value = 0x5548B83A;
                        break;
-               case DP_TRAIN_VOLTAGE_SWING_800:
+               case DP_TRAIN_VOLTAGE_SWING_LEVEL_2:
                        demph_reg_value = 0x2B245555;
                        uniqtranscale_reg_value = 0x5560B83A;
                        break;
-               case DP_TRAIN_VOLTAGE_SWING_1200:
+               case DP_TRAIN_VOLTAGE_SWING_LEVEL_3:
                        demph_reg_value = 0x2B405555;
                        uniqtranscale_reg_value = 0x5598DA3A;
                        break;
                        return 0;
                }
                break;
-       case DP_TRAIN_PRE_EMPHASIS_3_5:
+       case DP_TRAIN_PRE_EMPH_LEVEL_1:
                preemph_reg_value = 0x0002000;
                switch (train_set & DP_TRAIN_VOLTAGE_SWING_MASK) {
-               case DP_TRAIN_VOLTAGE_SWING_400:
+               case DP_TRAIN_VOLTAGE_SWING_LEVEL_0:
                        demph_reg_value = 0x2B404040;
                        uniqtranscale_reg_value = 0x5552B83A;
                        break;
-               case DP_TRAIN_VOLTAGE_SWING_600:
+               case DP_TRAIN_VOLTAGE_SWING_LEVEL_1:
                        demph_reg_value = 0x2B404848;
                        uniqtranscale_reg_value = 0x5580B83A;
                        break;
-               case DP_TRAIN_VOLTAGE_SWING_800:
+               case DP_TRAIN_VOLTAGE_SWING_LEVEL_2:
                        demph_reg_value = 0x2B404040;
                        uniqtranscale_reg_value = 0x55ADDA3A;
                        break;
                        return 0;
                }
                break;
-       case DP_TRAIN_PRE_EMPHASIS_6:
+       case DP_TRAIN_PRE_EMPH_LEVEL_2:
                preemph_reg_value = 0x0000000;
                switch (train_set & DP_TRAIN_VOLTAGE_SWING_MASK) {
-               case DP_TRAIN_VOLTAGE_SWING_400:
+               case DP_TRAIN_VOLTAGE_SWING_LEVEL_0:
                        demph_reg_value = 0x2B305555;
                        uniqtranscale_reg_value = 0x5570B83A;
                        break;
-               case DP_TRAIN_VOLTAGE_SWING_600:
+               case DP_TRAIN_VOLTAGE_SWING_LEVEL_1:
                        demph_reg_value = 0x2B2B4040;
                        uniqtranscale_reg_value = 0x55ADDA3A;
                        break;
                        return 0;
                }
                break;
-       case DP_TRAIN_PRE_EMPHASIS_9_5:
+       case DP_TRAIN_PRE_EMPH_LEVEL_3:
                preemph_reg_value = 0x0006000;
                switch (train_set & DP_TRAIN_VOLTAGE_SWING_MASK) {
-               case DP_TRAIN_VOLTAGE_SWING_400:
+               case DP_TRAIN_VOLTAGE_SWING_LEVEL_0:
                        demph_reg_value = 0x1B405555;
                        uniqtranscale_reg_value = 0x55ADDA3A;
                        break;
@@@ -2558,21 -3018,21 +3018,21 @@@ static uint32_t intel_chv_signal_levels
        int i;
  
        switch (train_set & DP_TRAIN_PRE_EMPHASIS_MASK) {
-       case DP_TRAIN_PRE_EMPHASIS_0:
+       case DP_TRAIN_PRE_EMPH_LEVEL_0:
                switch (train_set & DP_TRAIN_VOLTAGE_SWING_MASK) {
-               case DP_TRAIN_VOLTAGE_SWING_400:
+               case DP_TRAIN_VOLTAGE_SWING_LEVEL_0:
                        deemph_reg_value = 128;
                        margin_reg_value = 52;
                        break;
-               case DP_TRAIN_VOLTAGE_SWING_600:
+               case DP_TRAIN_VOLTAGE_SWING_LEVEL_1:
                        deemph_reg_value = 128;
                        margin_reg_value = 77;
                        break;
-               case DP_TRAIN_VOLTAGE_SWING_800:
+               case DP_TRAIN_VOLTAGE_SWING_LEVEL_2:
                        deemph_reg_value = 128;
                        margin_reg_value = 102;
                        break;
-               case DP_TRAIN_VOLTAGE_SWING_1200:
+               case DP_TRAIN_VOLTAGE_SWING_LEVEL_3:
                        deemph_reg_value = 128;
                        margin_reg_value = 154;
                        /* FIXME extra to set for 1200 */
                        return 0;
                }
                break;
-       case DP_TRAIN_PRE_EMPHASIS_3_5:
+       case DP_TRAIN_PRE_EMPH_LEVEL_1:
                switch (train_set & DP_TRAIN_VOLTAGE_SWING_MASK) {
-               case DP_TRAIN_VOLTAGE_SWING_400:
+               case DP_TRAIN_VOLTAGE_SWING_LEVEL_0:
                        deemph_reg_value = 85;
                        margin_reg_value = 78;
                        break;
-               case DP_TRAIN_VOLTAGE_SWING_600:
+               case DP_TRAIN_VOLTAGE_SWING_LEVEL_1:
                        deemph_reg_value = 85;
                        margin_reg_value = 116;
                        break;
-               case DP_TRAIN_VOLTAGE_SWING_800:
+               case DP_TRAIN_VOLTAGE_SWING_LEVEL_2:
                        deemph_reg_value = 85;
                        margin_reg_value = 154;
                        break;
                        return 0;
                }
                break;
-       case DP_TRAIN_PRE_EMPHASIS_6:
+       case DP_TRAIN_PRE_EMPH_LEVEL_2:
                switch (train_set & DP_TRAIN_VOLTAGE_SWING_MASK) {
-               case DP_TRAIN_VOLTAGE_SWING_400:
+               case DP_TRAIN_VOLTAGE_SWING_LEVEL_0:
                        deemph_reg_value = 64;
                        margin_reg_value = 104;
                        break;
-               case DP_TRAIN_VOLTAGE_SWING_600:
+               case DP_TRAIN_VOLTAGE_SWING_LEVEL_1:
                        deemph_reg_value = 64;
                        margin_reg_value = 154;
                        break;
                        return 0;
                }
                break;
-       case DP_TRAIN_PRE_EMPHASIS_9_5:
+       case DP_TRAIN_PRE_EMPH_LEVEL_3:
                switch (train_set & DP_TRAIN_VOLTAGE_SWING_MASK) {
-               case DP_TRAIN_VOLTAGE_SWING_400:
+               case DP_TRAIN_VOLTAGE_SWING_LEVEL_0:
                        deemph_reg_value = 43;
                        margin_reg_value = 154;
                        break;
        }
  
        if (((train_set & DP_TRAIN_PRE_EMPHASIS_MASK)
-                       == DP_TRAIN_PRE_EMPHASIS_0) &&
+                       == DP_TRAIN_PRE_EMPH_LEVEL_0) &&
                ((train_set & DP_TRAIN_VOLTAGE_SWING_MASK)
-                       == DP_TRAIN_VOLTAGE_SWING_1200)) {
+                       == DP_TRAIN_VOLTAGE_SWING_LEVEL_3)) {
  
                /*
                 * The document said it needs to set bit 27 for ch0 and bit 26
@@@ -2743,32 -3203,32 +3203,32 @@@ intel_gen4_signal_levels(uint8_t train_
        uint32_t        signal_levels = 0;
  
        switch (train_set & DP_TRAIN_VOLTAGE_SWING_MASK) {
-       case DP_TRAIN_VOLTAGE_SWING_400:
+       case DP_TRAIN_VOLTAGE_SWING_LEVEL_0:
        default:
                signal_levels |= DP_VOLTAGE_0_4;
                break;
-       case DP_TRAIN_VOLTAGE_SWING_600:
+       case DP_TRAIN_VOLTAGE_SWING_LEVEL_1:
                signal_levels |= DP_VOLTAGE_0_6;
                break;
-       case DP_TRAIN_VOLTAGE_SWING_800:
+       case DP_TRAIN_VOLTAGE_SWING_LEVEL_2:
                signal_levels |= DP_VOLTAGE_0_8;
                break;
-       case DP_TRAIN_VOLTAGE_SWING_1200:
+       case DP_TRAIN_VOLTAGE_SWING_LEVEL_3:
                signal_levels |= DP_VOLTAGE_1_2;
                break;
        }
        switch (train_set & DP_TRAIN_PRE_EMPHASIS_MASK) {
-       case DP_TRAIN_PRE_EMPHASIS_0:
+       case DP_TRAIN_PRE_EMPH_LEVEL_0:
        default:
                signal_levels |= DP_PRE_EMPHASIS_0;
                break;
-       case DP_TRAIN_PRE_EMPHASIS_3_5:
+       case DP_TRAIN_PRE_EMPH_LEVEL_1:
                signal_levels |= DP_PRE_EMPHASIS_3_5;
                break;
-       case DP_TRAIN_PRE_EMPHASIS_6:
+       case DP_TRAIN_PRE_EMPH_LEVEL_2:
                signal_levels |= DP_PRE_EMPHASIS_6;
                break;
-       case DP_TRAIN_PRE_EMPHASIS_9_5:
+       case DP_TRAIN_PRE_EMPH_LEVEL_3:
                signal_levels |= DP_PRE_EMPHASIS_9_5;
                break;
        }
@@@ -2782,19 -3242,19 +3242,19 @@@ intel_gen6_edp_signal_levels(uint8_t tr
        int signal_levels = train_set & (DP_TRAIN_VOLTAGE_SWING_MASK |
                                         DP_TRAIN_PRE_EMPHASIS_MASK);
        switch (signal_levels) {
-       case DP_TRAIN_VOLTAGE_SWING_400 | DP_TRAIN_PRE_EMPHASIS_0:
-       case DP_TRAIN_VOLTAGE_SWING_600 | DP_TRAIN_PRE_EMPHASIS_0:
+       case DP_TRAIN_VOLTAGE_SWING_LEVEL_0 | DP_TRAIN_PRE_EMPH_LEVEL_0:
+       case DP_TRAIN_VOLTAGE_SWING_LEVEL_1 | DP_TRAIN_PRE_EMPH_LEVEL_0:
                return EDP_LINK_TRAIN_400_600MV_0DB_SNB_B;
-       case DP_TRAIN_VOLTAGE_SWING_400 | DP_TRAIN_PRE_EMPHASIS_3_5:
+       case DP_TRAIN_VOLTAGE_SWING_LEVEL_0 | DP_TRAIN_PRE_EMPH_LEVEL_1:
                return EDP_LINK_TRAIN_400MV_3_5DB_SNB_B;
-       case DP_TRAIN_VOLTAGE_SWING_400 | DP_TRAIN_PRE_EMPHASIS_6:
-       case DP_TRAIN_VOLTAGE_SWING_600 | DP_TRAIN_PRE_EMPHASIS_6:
+       case DP_TRAIN_VOLTAGE_SWING_LEVEL_0 | DP_TRAIN_PRE_EMPH_LEVEL_2:
+       case DP_TRAIN_VOLTAGE_SWING_LEVEL_1 | DP_TRAIN_PRE_EMPH_LEVEL_2:
                return EDP_LINK_TRAIN_400_600MV_6DB_SNB_B;
-       case DP_TRAIN_VOLTAGE_SWING_600 | DP_TRAIN_PRE_EMPHASIS_3_5:
-       case DP_TRAIN_VOLTAGE_SWING_800 | DP_TRAIN_PRE_EMPHASIS_3_5:
+       case DP_TRAIN_VOLTAGE_SWING_LEVEL_1 | DP_TRAIN_PRE_EMPH_LEVEL_1:
+       case DP_TRAIN_VOLTAGE_SWING_LEVEL_2 | DP_TRAIN_PRE_EMPH_LEVEL_1:
                return EDP_LINK_TRAIN_600_800MV_3_5DB_SNB_B;
-       case DP_TRAIN_VOLTAGE_SWING_800 | DP_TRAIN_PRE_EMPHASIS_0:
-       case DP_TRAIN_VOLTAGE_SWING_1200 | DP_TRAIN_PRE_EMPHASIS_0:
+       case DP_TRAIN_VOLTAGE_SWING_LEVEL_2 | DP_TRAIN_PRE_EMPH_LEVEL_0:
+       case DP_TRAIN_VOLTAGE_SWING_LEVEL_3 | DP_TRAIN_PRE_EMPH_LEVEL_0:
                return EDP_LINK_TRAIN_800_1200MV_0DB_SNB_B;
        default:
                DRM_DEBUG_KMS("Unsupported voltage swing/pre-emphasis level:"
@@@ -2810,21 -3270,21 +3270,21 @@@ intel_gen7_edp_signal_levels(uint8_t tr
        int signal_levels = train_set & (DP_TRAIN_VOLTAGE_SWING_MASK |
                                         DP_TRAIN_PRE_EMPHASIS_MASK);
        switch (signal_levels) {
-       case DP_TRAIN_VOLTAGE_SWING_400 | DP_TRAIN_PRE_EMPHASIS_0:
+       case DP_TRAIN_VOLTAGE_SWING_LEVEL_0 | DP_TRAIN_PRE_EMPH_LEVEL_0:
                return EDP_LINK_TRAIN_400MV_0DB_IVB;
-       case DP_TRAIN_VOLTAGE_SWING_400 | DP_TRAIN_PRE_EMPHASIS_3_5:
+       case DP_TRAIN_VOLTAGE_SWING_LEVEL_0 | DP_TRAIN_PRE_EMPH_LEVEL_1:
                return EDP_LINK_TRAIN_400MV_3_5DB_IVB;
-       case DP_TRAIN_VOLTAGE_SWING_400 | DP_TRAIN_PRE_EMPHASIS_6:
+       case DP_TRAIN_VOLTAGE_SWING_LEVEL_0 | DP_TRAIN_PRE_EMPH_LEVEL_2:
                return EDP_LINK_TRAIN_400MV_6DB_IVB;
  
-       case DP_TRAIN_VOLTAGE_SWING_600 | DP_TRAIN_PRE_EMPHASIS_0:
+       case DP_TRAIN_VOLTAGE_SWING_LEVEL_1 | DP_TRAIN_PRE_EMPH_LEVEL_0:
                return EDP_LINK_TRAIN_600MV_0DB_IVB;
-       case DP_TRAIN_VOLTAGE_SWING_600 | DP_TRAIN_PRE_EMPHASIS_3_5:
+       case DP_TRAIN_VOLTAGE_SWING_LEVEL_1 | DP_TRAIN_PRE_EMPH_LEVEL_1:
                return EDP_LINK_TRAIN_600MV_3_5DB_IVB;
  
-       case DP_TRAIN_VOLTAGE_SWING_800 | DP_TRAIN_PRE_EMPHASIS_0:
+       case DP_TRAIN_VOLTAGE_SWING_LEVEL_2 | DP_TRAIN_PRE_EMPH_LEVEL_0:
                return EDP_LINK_TRAIN_800MV_0DB_IVB;
-       case DP_TRAIN_VOLTAGE_SWING_800 | DP_TRAIN_PRE_EMPHASIS_3_5:
+       case DP_TRAIN_VOLTAGE_SWING_LEVEL_2 | DP_TRAIN_PRE_EMPH_LEVEL_1:
                return EDP_LINK_TRAIN_800MV_3_5DB_IVB;
  
        default:
@@@ -2841,30 -3301,30 +3301,30 @@@ intel_hsw_signal_levels(uint8_t train_s
        int signal_levels = train_set & (DP_TRAIN_VOLTAGE_SWING_MASK |
                                         DP_TRAIN_PRE_EMPHASIS_MASK);
        switch (signal_levels) {
-       case DP_TRAIN_VOLTAGE_SWING_400 | DP_TRAIN_PRE_EMPHASIS_0:
-               return DDI_BUF_EMP_400MV_0DB_HSW;
-       case DP_TRAIN_VOLTAGE_SWING_400 | DP_TRAIN_PRE_EMPHASIS_3_5:
-               return DDI_BUF_EMP_400MV_3_5DB_HSW;
-       case DP_TRAIN_VOLTAGE_SWING_400 | DP_TRAIN_PRE_EMPHASIS_6:
-               return DDI_BUF_EMP_400MV_6DB_HSW;
-       case DP_TRAIN_VOLTAGE_SWING_400 | DP_TRAIN_PRE_EMPHASIS_9_5:
-               return DDI_BUF_EMP_400MV_9_5DB_HSW;
-       case DP_TRAIN_VOLTAGE_SWING_600 | DP_TRAIN_PRE_EMPHASIS_0:
-               return DDI_BUF_EMP_600MV_0DB_HSW;
-       case DP_TRAIN_VOLTAGE_SWING_600 | DP_TRAIN_PRE_EMPHASIS_3_5:
-               return DDI_BUF_EMP_600MV_3_5DB_HSW;
-       case DP_TRAIN_VOLTAGE_SWING_600 | DP_TRAIN_PRE_EMPHASIS_6:
-               return DDI_BUF_EMP_600MV_6DB_HSW;
-       case DP_TRAIN_VOLTAGE_SWING_800 | DP_TRAIN_PRE_EMPHASIS_0:
-               return DDI_BUF_EMP_800MV_0DB_HSW;
-       case DP_TRAIN_VOLTAGE_SWING_800 | DP_TRAIN_PRE_EMPHASIS_3_5:
-               return DDI_BUF_EMP_800MV_3_5DB_HSW;
+       case DP_TRAIN_VOLTAGE_SWING_LEVEL_0 | DP_TRAIN_PRE_EMPH_LEVEL_0:
+               return DDI_BUF_TRANS_SELECT(0);
+       case DP_TRAIN_VOLTAGE_SWING_LEVEL_0 | DP_TRAIN_PRE_EMPH_LEVEL_1:
+               return DDI_BUF_TRANS_SELECT(1);
+       case DP_TRAIN_VOLTAGE_SWING_LEVEL_0 | DP_TRAIN_PRE_EMPH_LEVEL_2:
+               return DDI_BUF_TRANS_SELECT(2);
+       case DP_TRAIN_VOLTAGE_SWING_LEVEL_0 | DP_TRAIN_PRE_EMPH_LEVEL_3:
+               return DDI_BUF_TRANS_SELECT(3);
+       case DP_TRAIN_VOLTAGE_SWING_LEVEL_1 | DP_TRAIN_PRE_EMPH_LEVEL_0:
+               return DDI_BUF_TRANS_SELECT(4);
+       case DP_TRAIN_VOLTAGE_SWING_LEVEL_1 | DP_TRAIN_PRE_EMPH_LEVEL_1:
+               return DDI_BUF_TRANS_SELECT(5);
+       case DP_TRAIN_VOLTAGE_SWING_LEVEL_1 | DP_TRAIN_PRE_EMPH_LEVEL_2:
+               return DDI_BUF_TRANS_SELECT(6);
+       case DP_TRAIN_VOLTAGE_SWING_LEVEL_2 | DP_TRAIN_PRE_EMPH_LEVEL_0:
+               return DDI_BUF_TRANS_SELECT(7);
+       case DP_TRAIN_VOLTAGE_SWING_LEVEL_2 | DP_TRAIN_PRE_EMPH_LEVEL_1:
+               return DDI_BUF_TRANS_SELECT(8);
        default:
                DRM_DEBUG_KMS("Unsupported voltage swing/pre-emphasis level:"
                              "0x%x\n", signal_levels);
-               return DDI_BUF_EMP_400MV_0DB_HSW;
+               return DDI_BUF_TRANS_SELECT(0);
        }
  }
  
@@@ -2911,81 -3371,10 +3371,10 @@@ intel_dp_set_link_train(struct intel_d
        struct intel_digital_port *intel_dig_port = dp_to_dig_port(intel_dp);
        struct drm_device *dev = intel_dig_port->base.base.dev;
        struct drm_i915_private *dev_priv = dev->dev_private;
-       enum port port = intel_dig_port->port;
        uint8_t buf[sizeof(intel_dp->train_set) + 1];
        int ret, len;
  
-       if (HAS_DDI(dev)) {
-               uint32_t temp = I915_READ(DP_TP_CTL(port));
-               if (dp_train_pat & DP_LINK_SCRAMBLING_DISABLE)
-                       temp |= DP_TP_CTL_SCRAMBLE_DISABLE;
-               else
-                       temp &= ~DP_TP_CTL_SCRAMBLE_DISABLE;
-               temp &= ~DP_TP_CTL_LINK_TRAIN_MASK;
-               switch (dp_train_pat & DP_TRAINING_PATTERN_MASK) {
-               case DP_TRAINING_PATTERN_DISABLE:
-                       temp |= DP_TP_CTL_LINK_TRAIN_NORMAL;
-                       break;
-               case DP_TRAINING_PATTERN_1:
-                       temp |= DP_TP_CTL_LINK_TRAIN_PAT1;
-                       break;
-               case DP_TRAINING_PATTERN_2:
-                       temp |= DP_TP_CTL_LINK_TRAIN_PAT2;
-                       break;
-               case DP_TRAINING_PATTERN_3:
-                       temp |= DP_TP_CTL_LINK_TRAIN_PAT3;
-                       break;
-               }
-               I915_WRITE(DP_TP_CTL(port), temp);
-       } else if (HAS_PCH_CPT(dev) && (IS_GEN7(dev) || port != PORT_A)) {
-               *DP &= ~DP_LINK_TRAIN_MASK_CPT;
-               switch (dp_train_pat & DP_TRAINING_PATTERN_MASK) {
-               case DP_TRAINING_PATTERN_DISABLE:
-                       *DP |= DP_LINK_TRAIN_OFF_CPT;
-                       break;
-               case DP_TRAINING_PATTERN_1:
-                       *DP |= DP_LINK_TRAIN_PAT_1_CPT;
-                       break;
-               case DP_TRAINING_PATTERN_2:
-                       *DP |= DP_LINK_TRAIN_PAT_2_CPT;
-                       break;
-               case DP_TRAINING_PATTERN_3:
-                       DRM_ERROR("DP training pattern 3 not supported\n");
-                       *DP |= DP_LINK_TRAIN_PAT_2_CPT;
-                       break;
-               }
-       } else {
-               if (IS_CHERRYVIEW(dev))
-                       *DP &= ~DP_LINK_TRAIN_MASK_CHV;
-               else
-                       *DP &= ~DP_LINK_TRAIN_MASK;
-               switch (dp_train_pat & DP_TRAINING_PATTERN_MASK) {
-               case DP_TRAINING_PATTERN_DISABLE:
-                       *DP |= DP_LINK_TRAIN_OFF;
-                       break;
-               case DP_TRAINING_PATTERN_1:
-                       *DP |= DP_LINK_TRAIN_PAT_1;
-                       break;
-               case DP_TRAINING_PATTERN_2:
-                       *DP |= DP_LINK_TRAIN_PAT_2;
-                       break;
-               case DP_TRAINING_PATTERN_3:
-                       if (IS_CHERRYVIEW(dev)) {
-                               *DP |= DP_LINK_TRAIN_PAT_3_CHV;
-                       } else {
-                               DRM_ERROR("DP training pattern 3 not supported\n");
-                               *DP |= DP_LINK_TRAIN_PAT_2;
-                       }
-                       break;
-               }
-       }
+       _intel_dp_set_link_train(intel_dp, DP, dp_train_pat);
  
        I915_WRITE(intel_dp->output_reg, *DP);
        POSTING_READ(intel_dp->output_reg);
@@@ -3318,15 -3707,11 +3707,11 @@@ intel_dp_get_dpcd(struct intel_dp *inte
        struct drm_device *dev = dig_port->base.base.dev;
        struct drm_i915_private *dev_priv = dev->dev_private;
  
-       char dpcd_hex_dump[sizeof(intel_dp->dpcd) * 3];
        if (intel_dp_dpcd_read_wake(&intel_dp->aux, 0x000, intel_dp->dpcd,
                                    sizeof(intel_dp->dpcd)) < 0)
                return false; /* aux transfer failed */
  
-       hex_dump_to_buffer(intel_dp->dpcd, sizeof(intel_dp->dpcd),
-                          32, 1, dpcd_hex_dump, sizeof(dpcd_hex_dump), false);
-       DRM_DEBUG_KMS("DPCD: %s\n", dpcd_hex_dump);
+       DRM_DEBUG_KMS("DPCD: %*ph\n", (int) sizeof(intel_dp->dpcd), intel_dp->dpcd);
  
        if (intel_dp->dpcd[DP_DPCD_REV] == 0)
                return false; /* DPCD not present */
@@@ -3384,7 -3769,7 +3769,7 @@@ intel_dp_probe_oui(struct intel_dp *int
                DRM_DEBUG_KMS("Branch OUI: %02hx%02hx%02hx\n",
                              buf[0], buf[1], buf[2]);
  
-       edp_panel_vdd_off(intel_dp, false);
+       intel_edp_panel_vdd_off(intel_dp, false);
  }
  
  static bool
@@@ -3398,7 -3783,7 +3783,7 @@@ intel_dp_probe_mst(struct intel_dp *int
        if (intel_dp->dpcd[DP_DPCD_REV] < 0x12)
                return false;
  
-       _edp_panel_vdd_on(intel_dp);
+       intel_edp_panel_vdd_on(intel_dp);
        if (intel_dp_dpcd_read_wake(&intel_dp->aux, DP_MSTM_CAP, buf, 1)) {
                if (buf[0] & DP_MST_CAP) {
                        DRM_DEBUG_KMS("Sink is MST capable\n");
                        intel_dp->is_mst = false;
                }
        }
-       edp_panel_vdd_off(intel_dp, false);
+       intel_edp_panel_vdd_off(intel_dp, false);
  
        drm_dp_mst_topology_mgr_set_mst(&intel_dp->mst_mgr, intel_dp->is_mst);
        return intel_dp->is_mst;
@@@ -3639,21 -4024,25 +4024,25 @@@ intel_dp_detect_dpcd(struct intel_dp *i
        return connector_status_disconnected;
  }
  
+ static enum drm_connector_status
+ edp_detect(struct intel_dp *intel_dp)
+ {
+       struct drm_device *dev = intel_dp_to_dev(intel_dp);
+       enum drm_connector_status status;
+       status = intel_panel_detect(dev);
+       if (status == connector_status_unknown)
+               status = connector_status_connected;
+       return status;
+ }
  static enum drm_connector_status
  ironlake_dp_detect(struct intel_dp *intel_dp)
  {
        struct drm_device *dev = intel_dp_to_dev(intel_dp);
        struct drm_i915_private *dev_priv = dev->dev_private;
        struct intel_digital_port *intel_dig_port = dp_to_dig_port(intel_dp);
-       enum drm_connector_status status;
-       /* Can't disconnect eDP, but you can close the lid... */
-       if (is_edp(intel_dp)) {
-               status = intel_panel_detect(dev);
-               if (status == connector_status_unknown)
-                       status = connector_status_connected;
-               return status;
-       }
  
        if (!ibx_digital_port_connected(dev_priv, intel_dig_port))
                return connector_status_disconnected;
        return intel_dp_detect_dpcd(intel_dp);
  }
  
 -static enum drm_connector_status
 -g4x_dp_detect(struct intel_dp *intel_dp)
 +static int g4x_digital_port_connected(struct drm_device *dev,
 +                                     struct intel_digital_port *intel_dig_port)
  {
 -      struct drm_device *dev = intel_dp_to_dev(intel_dp);
        struct drm_i915_private *dev_priv = dev->dev_private;
 -      struct intel_digital_port *intel_dig_port = dp_to_dig_port(intel_dp);
        uint32_t bit;
  
        if (IS_VALLEYVIEW(dev)) {
                        bit = PORTD_HOTPLUG_LIVE_STATUS_VLV;
                        break;
                default:
 -                      return connector_status_unknown;
 +                      return -EINVAL;
                }
        } else {
                switch (intel_dig_port->port) {
                        bit = PORTD_HOTPLUG_LIVE_STATUS_G4X;
                        break;
                default:
 -                      return connector_status_unknown;
 +                      return -EINVAL;
                }
        }
  
        if ((I915_READ(PORT_HOTPLUG_STAT) & bit) == 0)
 +              return 0;
 +      return 1;
 +}
 +
 +static enum drm_connector_status
 +g4x_dp_detect(struct intel_dp *intel_dp)
 +{
 +      struct drm_device *dev = intel_dp_to_dev(intel_dp);
 +      struct intel_digital_port *intel_dig_port = dp_to_dig_port(intel_dp);
 +      int ret;
 +
 +      /* Can't disconnect eDP, but you can close the lid... */
 +      if (is_edp(intel_dp)) {
 +              enum drm_connector_status status;
 +
 +              status = intel_panel_detect(dev);
 +              if (status == connector_status_unknown)
 +                      status = connector_status_connected;
 +              return status;
 +      }
 +
 +      ret = g4x_digital_port_connected(dev, intel_dig_port);
 +      if (ret == -EINVAL)
 +              return connector_status_unknown;
 +      else if (ret == 0)
                return connector_status_disconnected;
  
        return intel_dp_detect_dpcd(intel_dp);
  }
  
  static struct edid *
- intel_dp_get_edid(struct drm_connector *connector, struct i2c_adapter *adapter)
+ intel_dp_get_edid(struct intel_dp *intel_dp)
  {
-       struct intel_connector *intel_connector = to_intel_connector(connector);
+       struct intel_connector *intel_connector = intel_dp->attached_connector;
  
        /* use cached edid if we have one */
        if (intel_connector->edid) {
                        return NULL;
  
                return drm_edid_duplicate(intel_connector->edid);
-       }
+       } else
+               return drm_get_edid(&intel_connector->base,
+                                   &intel_dp->aux.ddc);
+ }
+ static void
+ intel_dp_set_edid(struct intel_dp *intel_dp)
+ {
+       struct intel_connector *intel_connector = intel_dp->attached_connector;
+       struct edid *edid;
  
-       return drm_get_edid(connector, adapter);
+       edid = intel_dp_get_edid(intel_dp);
+       intel_connector->detect_edid = edid;
+       if (intel_dp->force_audio != HDMI_AUDIO_AUTO)
+               intel_dp->has_audio = intel_dp->force_audio == HDMI_AUDIO_ON;
+       else
+               intel_dp->has_audio = drm_detect_monitor_audio(edid);
  }
  
- static int
- intel_dp_get_edid_modes(struct drm_connector *connector, struct i2c_adapter *adapter)
+ static void
+ intel_dp_unset_edid(struct intel_dp *intel_dp)
  {
-       struct intel_connector *intel_connector = to_intel_connector(connector);
+       struct intel_connector *intel_connector = intel_dp->attached_connector;
  
-       /* use cached edid if we have one */
-       if (intel_connector->edid) {
-               /* invalid edid */
-               if (IS_ERR(intel_connector->edid))
-                       return 0;
+       kfree(intel_connector->detect_edid);
+       intel_connector->detect_edid = NULL;
  
-               return intel_connector_update_modes(connector,
-                                                   intel_connector->edid);
-       }
+       intel_dp->has_audio = false;
+ }
+ static enum intel_display_power_domain
+ intel_dp_power_get(struct intel_dp *dp)
+ {
+       struct intel_encoder *encoder = &dp_to_dig_port(dp)->base;
+       enum intel_display_power_domain power_domain;
+       power_domain = intel_display_port_power_domain(encoder);
+       intel_display_power_get(to_i915(encoder->base.dev), power_domain);
+       return power_domain;
+ }
  
-       return intel_ddc_get_modes(connector, adapter);
+ static void
+ intel_dp_power_put(struct intel_dp *dp,
+                  enum intel_display_power_domain power_domain)
+ {
+       struct intel_encoder *encoder = &dp_to_dig_port(dp)->base;
+       intel_display_power_put(to_i915(encoder->base.dev), power_domain);
  }
  
  static enum drm_connector_status
@@@ -3770,33 -4164,30 +4187,30 @@@ intel_dp_detect(struct drm_connector *c
        struct intel_digital_port *intel_dig_port = dp_to_dig_port(intel_dp);
        struct intel_encoder *intel_encoder = &intel_dig_port->base;
        struct drm_device *dev = connector->dev;
-       struct drm_i915_private *dev_priv = dev->dev_private;
        enum drm_connector_status status;
        enum intel_display_power_domain power_domain;
-       struct edid *edid = NULL;
        bool ret;
  
-       power_domain = intel_display_port_power_domain(intel_encoder);
-       intel_display_power_get(dev_priv, power_domain);
        DRM_DEBUG_KMS("[CONNECTOR:%d:%s]\n",
                      connector->base.id, connector->name);
+       intel_dp_unset_edid(intel_dp);
  
        if (intel_dp->is_mst) {
                /* MST devices are disconnected from a monitor POV */
                if (intel_encoder->type != INTEL_OUTPUT_EDP)
                        intel_encoder->type = INTEL_OUTPUT_DISPLAYPORT;
-               status = connector_status_disconnected;
-               goto out;
+               return connector_status_disconnected;
        }
  
-       intel_dp->has_audio = false;
+       power_domain = intel_dp_power_get(intel_dp);
  
-       if (HAS_PCH_SPLIT(dev))
+       /* Can't disconnect eDP, but you can close the lid... */
+       if (is_edp(intel_dp))
+               status = edp_detect(intel_dp);
+       else if (HAS_PCH_SPLIT(dev))
                status = ironlake_dp_detect(intel_dp);
        else
                status = g4x_dp_detect(intel_dp);
        if (status != connector_status_connected)
                goto out;
  
                goto out;
        }
  
-       if (intel_dp->force_audio != HDMI_AUDIO_AUTO) {
-               intel_dp->has_audio = (intel_dp->force_audio == HDMI_AUDIO_ON);
-       } else {
-               edid = intel_dp_get_edid(connector, &intel_dp->aux.ddc);
-               if (edid) {
-                       intel_dp->has_audio = drm_detect_monitor_audio(edid);
-                       kfree(edid);
-               }
-       }
+       intel_dp_set_edid(intel_dp);
  
        if (intel_encoder->type != INTEL_OUTPUT_EDP)
                intel_encoder->type = INTEL_OUTPUT_DISPLAYPORT;
        status = connector_status_connected;
  
  out:
-       intel_display_power_put(dev_priv, power_domain);
+       intel_dp_power_put(intel_dp, power_domain);
        return status;
  }
  
- static int intel_dp_get_modes(struct drm_connector *connector)
+ static void
+ intel_dp_force(struct drm_connector *connector)
  {
        struct intel_dp *intel_dp = intel_attached_dp(connector);
-       struct intel_digital_port *intel_dig_port = dp_to_dig_port(intel_dp);
-       struct intel_encoder *intel_encoder = &intel_dig_port->base;
-       struct intel_connector *intel_connector = to_intel_connector(connector);
-       struct drm_device *dev = connector->dev;
-       struct drm_i915_private *dev_priv = dev->dev_private;
+       struct intel_encoder *intel_encoder = &dp_to_dig_port(intel_dp)->base;
        enum intel_display_power_domain power_domain;
-       int ret;
  
-       /* We should parse the EDID data and find out if it has an audio sink
-        */
+       DRM_DEBUG_KMS("[CONNECTOR:%d:%s]\n",
+                     connector->base.id, connector->name);
+       intel_dp_unset_edid(intel_dp);
  
-       power_domain = intel_display_port_power_domain(intel_encoder);
-       intel_display_power_get(dev_priv, power_domain);
+       if (connector->status != connector_status_connected)
+               return;
  
-       ret = intel_dp_get_edid_modes(connector, &intel_dp->aux.ddc);
-       intel_display_power_put(dev_priv, power_domain);
-       if (ret)
-               return ret;
+       power_domain = intel_dp_power_get(intel_dp);
+       intel_dp_set_edid(intel_dp);
+       intel_dp_power_put(intel_dp, power_domain);
+       if (intel_encoder->type != INTEL_OUTPUT_EDP)
+               intel_encoder->type = INTEL_OUTPUT_DISPLAYPORT;
+ }
+ static int intel_dp_get_modes(struct drm_connector *connector)
+ {
+       struct intel_connector *intel_connector = to_intel_connector(connector);
+       struct edid *edid;
+       edid = intel_connector->detect_edid;
+       if (edid) {
+               int ret = intel_connector_update_modes(connector, edid);
+               if (ret)
+                       return ret;
+       }
  
        /* if eDP has no EDID, fall back to fixed mode */
-       if (is_edp(intel_dp) && intel_connector->panel.fixed_mode) {
+       if (is_edp(intel_attached_dp(connector)) &&
+           intel_connector->panel.fixed_mode) {
                struct drm_display_mode *mode;
-               mode = drm_mode_duplicate(dev,
+               mode = drm_mode_duplicate(connector->dev,
                                          intel_connector->panel.fixed_mode);
                if (mode) {
                        drm_mode_probed_add(connector, mode);
                        return 1;
                }
        }
        return 0;
  }
  
  static bool
  intel_dp_detect_audio(struct drm_connector *connector)
  {
-       struct intel_dp *intel_dp = intel_attached_dp(connector);
-       struct intel_digital_port *intel_dig_port = dp_to_dig_port(intel_dp);
-       struct intel_encoder *intel_encoder = &intel_dig_port->base;
-       struct drm_device *dev = connector->dev;
-       struct drm_i915_private *dev_priv = dev->dev_private;
-       enum intel_display_power_domain power_domain;
-       struct edid *edid;
        bool has_audio = false;
+       struct edid *edid;
  
-       power_domain = intel_display_port_power_domain(intel_encoder);
-       intel_display_power_get(dev_priv, power_domain);
-       edid = intel_dp_get_edid(connector, &intel_dp->aux.ddc);
-       if (edid) {
+       edid = to_intel_connector(connector)->detect_edid;
+       if (edid)
                has_audio = drm_detect_monitor_audio(edid);
-               kfree(edid);
-       }
-       intel_display_power_put(dev_priv, power_domain);
  
        return has_audio;
  }
@@@ -3985,6 -4372,8 +4395,8 @@@ intel_dp_connector_destroy(struct drm_c
  {
        struct intel_connector *intel_connector = to_intel_connector(connector);
  
+       intel_dp_unset_edid(intel_attached_dp(connector));
        if (!IS_ERR_OR_NULL(intel_connector->edid))
                kfree(intel_connector->edid);
  
@@@ -4001,16 -4390,20 +4413,20 @@@ void intel_dp_encoder_destroy(struct dr
  {
        struct intel_digital_port *intel_dig_port = enc_to_dig_port(encoder);
        struct intel_dp *intel_dp = &intel_dig_port->dp;
-       struct drm_device *dev = intel_dp_to_dev(intel_dp);
  
        drm_dp_aux_unregister(&intel_dp->aux);
        intel_dp_mst_encoder_cleanup(intel_dig_port);
        drm_encoder_cleanup(encoder);
        if (is_edp(intel_dp)) {
                cancel_delayed_work_sync(&intel_dp->panel_vdd_work);
-               drm_modeset_lock(&dev->mode_config.connection_mutex, NULL);
+               /*
+                * vdd might still be enabled do to the delayed vdd off.
+                * Make sure vdd is actually turned off here.
+                */
+               pps_lock(intel_dp);
                edp_panel_vdd_off_sync(intel_dp);
-               drm_modeset_unlock(&dev->mode_config.connection_mutex);
+               pps_unlock(intel_dp);
                if (intel_dp->edp_notifier.notifier_call) {
                        unregister_reboot_notifier(&intel_dp->edp_notifier);
                        intel_dp->edp_notifier.notifier_call = NULL;
@@@ -4026,7 -4419,13 +4442,13 @@@ static void intel_dp_encoder_suspend(st
        if (!is_edp(intel_dp))
                return;
  
+       /*
+        * vdd might still be enabled do to the delayed vdd off.
+        * Make sure vdd is actually turned off here.
+        */
+       pps_lock(intel_dp);
        edp_panel_vdd_off_sync(intel_dp);
+       pps_unlock(intel_dp);
  }
  
  static void intel_dp_encoder_reset(struct drm_encoder *encoder)
  static const struct drm_connector_funcs intel_dp_connector_funcs = {
        .dpms = intel_connector_dpms,
        .detect = intel_dp_detect,
+       .force = intel_dp_force,
        .fill_modes = drm_helper_probe_single_connector_modes,
        .set_property = intel_dp_set_property,
        .destroy = intel_dp_connector_destroy,
@@@ -4080,14 -4480,8 +4503,14 @@@ intel_dp_hpd_pulse(struct intel_digital
        intel_display_power_get(dev_priv, power_domain);
  
        if (long_hpd) {
 -              if (!ibx_digital_port_connected(dev_priv, intel_dig_port))
 -                      goto mst_fail;
 +
 +              if (HAS_PCH_SPLIT(dev)) {
 +                      if (!ibx_digital_port_connected(dev_priv, intel_dig_port))
 +                              goto mst_fail;
 +              } else {
 +                      if (g4x_digital_port_connected(dev, intel_dig_port) != 1)
 +                              goto mst_fail;
 +              }
  
                if (!intel_dp_get_dpcd(intel_dp)) {
                        goto mst_fail;
@@@ -4213,6 -4607,8 +4636,8 @@@ intel_dp_init_panel_power_sequencer(str
        u32 pp_on, pp_off, pp_div, pp;
        int pp_ctrl_reg, pp_on_reg, pp_off_reg, pp_div_reg;
  
+       lockdep_assert_held(&dev_priv->pps_mutex);
        if (HAS_PCH_SPLIT(dev)) {
                pp_ctrl_reg = PCH_PP_CONTROL;
                pp_on_reg = PCH_PP_ON_DELAYS;
@@@ -4312,6 -4708,9 +4737,9 @@@ intel_dp_init_panel_power_sequencer_reg
        u32 pp_on, pp_off, pp_div, port_sel = 0;
        int div = HAS_PCH_SPLIT(dev) ? intel_pch_rawclk(dev) : intel_hrawclk(dev);
        int pp_on_reg, pp_off_reg, pp_div_reg;
+       enum port port = dp_to_dig_port(intel_dp)->port;
+       lockdep_assert_held(&dev_priv->pps_mutex);
  
        if (HAS_PCH_SPLIT(dev)) {
                pp_on_reg = PCH_PP_ON_DELAYS;
        /* Haswell doesn't have any port selection bits for the panel
         * power sequencer any more. */
        if (IS_VALLEYVIEW(dev)) {
-               if (dp_to_dig_port(intel_dp)->port == PORT_B)
-                       port_sel = PANEL_PORT_SELECT_DPB_VLV;
-               else
-                       port_sel = PANEL_PORT_SELECT_DPC_VLV;
+               port_sel = PANEL_PORT_SELECT_VLV(port);
        } else if (HAS_PCH_IBX(dev) || HAS_PCH_CPT(dev)) {
-               if (dp_to_dig_port(intel_dp)->port == PORT_A)
+               if (port == PORT_A)
                        port_sel = PANEL_PORT_SELECT_DPA;
                else
                        port_sel = PANEL_PORT_SELECT_DPD;
@@@ -4509,8 -4905,11 +4934,11 @@@ void intel_edp_panel_vdd_sanitize(struc
                return;
  
        intel_dp = enc_to_intel_dp(&intel_encoder->base);
+       pps_lock(intel_dp);
        if (!edp_have_panel_vdd(intel_dp))
-               return;
+               goto out;
        /*
         * The VDD bit needs a power domain reference, so if the bit is
         * already enabled when we boot or resume, grab this reference and
        intel_display_power_get(dev_priv, power_domain);
  
        edp_panel_vdd_schedule_off(intel_dp);
+  out:
+       pps_unlock(intel_dp);
  }
  
  static bool intel_edp_init_connector(struct intel_dp *intel_dp,
        /* Cache DPCD and EDID for edp. */
        intel_edp_panel_vdd_on(intel_dp);
        has_dpcd = intel_dp_get_dpcd(intel_dp);
-       edp_panel_vdd_off(intel_dp, false);
+       intel_edp_panel_vdd_off(intel_dp, false);
  
        if (has_dpcd) {
                if (intel_dp->dpcd[DP_DPCD_REV] >= 0x11)
        }
  
        /* We now know it's not a ghost, init power sequence regs. */
+       pps_lock(intel_dp);
        intel_dp_init_panel_power_sequencer_registers(dev, intel_dp, power_seq);
+       pps_unlock(intel_dp);
  
        mutex_lock(&dev->mode_config.mutex);
        edid = drm_get_edid(connector, &intel_dp->aux.ddc);
        }
  
        intel_panel_init(&intel_connector->panel, fixed_mode, downclock_mode);
+       intel_connector->panel.backlight_power = intel_edp_backlight_power;
        intel_panel_setup_backlight(connector);
  
        return true;
@@@ -4625,6 -5029,8 +5058,8 @@@ intel_dp_init_connector(struct intel_di
        struct edp_power_seq power_seq = { 0 };
        int type;
  
+       intel_dp->pps_pipe = INVALID_PIPE;
        /* intel_dp vfuncs */
        if (IS_VALLEYVIEW(dev))
                intel_dp->get_aux_clock_divider = vlv_get_aux_clock_divider;
        }
  
        if (is_edp(intel_dp)) {
-               intel_dp_init_panel_power_timestamps(intel_dp);
-               intel_dp_init_panel_power_sequencer(dev, intel_dp, &power_seq);
+               pps_lock(intel_dp);
+               if (IS_VALLEYVIEW(dev)) {
+                       vlv_initial_power_sequencer_setup(intel_dp);
+               } else {
+                       intel_dp_init_panel_power_timestamps(intel_dp);
+                       intel_dp_init_panel_power_sequencer(dev, intel_dp,
+                                                           &power_seq);
+               }
+               pps_unlock(intel_dp);
        }
  
        intel_dp_aux_init(intel_dp, intel_connector);
        /* init MST on ports that can support it */
        if (IS_HASWELL(dev) || IS_BROADWELL(dev)) {
                if (port == PORT_B || port == PORT_C || port == PORT_D) {
-                       intel_dp_mst_encoder_init(intel_dig_port, intel_connector->base.base.id);
+                       intel_dp_mst_encoder_init(intel_dig_port,
+                                                 intel_connector->base.base.id);
                }
        }
  
                drm_dp_aux_unregister(&intel_dp->aux);
                if (is_edp(intel_dp)) {
                        cancel_delayed_work_sync(&intel_dp->panel_vdd_work);
-                       drm_modeset_lock(&dev->mode_config.connection_mutex, NULL);
+                       /*
+                        * vdd might still be enabled do to the delayed vdd off.
+                        * Make sure vdd is actually turned off here.
+                        */
+                       pps_lock(intel_dp);
                        edp_panel_vdd_off_sync(intel_dp);
-                       drm_modeset_unlock(&dev->mode_config.connection_mutex);
+                       pps_unlock(intel_dp);
                }
                drm_connector_unregister(connector);
                drm_connector_cleanup(connector);
@@@ -4778,7 -5196,8 +5225,8 @@@ intel_dp_init(struct drm_device *dev, i
        } else {
                intel_encoder->pre_enable = g4x_pre_enable_dp;
                intel_encoder->enable = g4x_enable_dp;
-               intel_encoder->post_disable = g4x_post_disable_dp;
+               if (INTEL_INFO(dev)->gen >= 5)
+                       intel_encoder->post_disable = ilk_post_disable_dp;
        }
  
        intel_dig_port->port = port;
index 96957683032e868b74aa734f168fec613794dc19,3b21a769ef5447c13149a1501aa7573f2dcc6eab..c5861736b4b0f97fbea8f73554e525303ee8f8fb
@@@ -864,15 -864,10 +864,15 @@@ static enum drm_mode_statu
  intel_hdmi_mode_valid(struct drm_connector *connector,
                      struct drm_display_mode *mode)
  {
 -      if (mode->clock > hdmi_portclock_limit(intel_attached_hdmi(connector),
 -                                             true))
 +      int clock = mode->clock;
 +
 +      if (mode->flags & DRM_MODE_FLAG_DBLCLK)
 +              clock *= 2;
 +
 +      if (clock > hdmi_portclock_limit(intel_attached_hdmi(connector),
 +                                       true))
                return MODE_CLOCK_HIGH;
 -      if (mode->clock < 20000)
 +      if (clock < 20000)
                return MODE_CLOCK_LOW;
  
        if (mode->flags & DRM_MODE_FLAG_DBLSCAN)
@@@ -926,10 -921,6 +926,10 @@@ bool intel_hdmi_compute_config(struct i
                        intel_hdmi->color_range = 0;
        }
  
 +      if (adjusted_mode->flags & DRM_MODE_FLAG_DBLCLK) {
 +              pipe_config->pixel_multiplier = 2;
 +      }
 +
        if (intel_hdmi->color_range)
                pipe_config->limited_color_range = true;
  
        return true;
  }
  
- static enum drm_connector_status
- intel_hdmi_detect(struct drm_connector *connector, bool force)
+ static void
+ intel_hdmi_unset_edid(struct drm_connector *connector)
  {
-       struct drm_device *dev = connector->dev;
        struct intel_hdmi *intel_hdmi = intel_attached_hdmi(connector);
-       struct intel_digital_port *intel_dig_port =
-               hdmi_to_dig_port(intel_hdmi);
-       struct intel_encoder *intel_encoder = &intel_dig_port->base;
-       struct drm_i915_private *dev_priv = dev->dev_private;
-       struct edid *edid;
-       enum intel_display_power_domain power_domain;
-       enum drm_connector_status status = connector_status_disconnected;
  
-       DRM_DEBUG_KMS("[CONNECTOR:%d:%s]\n",
-                     connector->base.id, connector->name);
+       intel_hdmi->has_hdmi_sink = false;
+       intel_hdmi->has_audio = false;
+       intel_hdmi->rgb_quant_range_selectable = false;
+       kfree(to_intel_connector(connector)->detect_edid);
+       to_intel_connector(connector)->detect_edid = NULL;
+ }
+ static bool
+ intel_hdmi_set_edid(struct drm_connector *connector)
+ {
+       struct drm_i915_private *dev_priv = to_i915(connector->dev);
+       struct intel_hdmi *intel_hdmi = intel_attached_hdmi(connector);
+       struct intel_encoder *intel_encoder =
+               &hdmi_to_dig_port(intel_hdmi)->base;
+       enum intel_display_power_domain power_domain;
+       struct edid *edid;
+       bool connected = false;
  
        power_domain = intel_display_port_power_domain(intel_encoder);
        intel_display_power_get(dev_priv, power_domain);
  
-       intel_hdmi->has_hdmi_sink = false;
-       intel_hdmi->has_audio = false;
-       intel_hdmi->rgb_quant_range_selectable = false;
        edid = drm_get_edid(connector,
                            intel_gmbus_get_adapter(dev_priv,
                                                    intel_hdmi->ddc_bus));
  
-       if (edid) {
-               if (edid->input & DRM_EDID_INPUT_DIGITAL) {
-                       status = connector_status_connected;
-                       if (intel_hdmi->force_audio != HDMI_AUDIO_OFF_DVI)
-                               intel_hdmi->has_hdmi_sink =
-                                               drm_detect_hdmi_monitor(edid);
-                       intel_hdmi->has_audio = drm_detect_monitor_audio(edid);
-                       intel_hdmi->rgb_quant_range_selectable =
-                               drm_rgb_quant_range_selectable(edid);
-               }
-               kfree(edid);
-       }
+       intel_display_power_put(dev_priv, power_domain);
  
-       if (status == connector_status_connected) {
+       to_intel_connector(connector)->detect_edid = edid;
+       if (edid && edid->input & DRM_EDID_INPUT_DIGITAL) {
+               intel_hdmi->rgb_quant_range_selectable =
+                       drm_rgb_quant_range_selectable(edid);
+               intel_hdmi->has_audio = drm_detect_monitor_audio(edid);
                if (intel_hdmi->force_audio != HDMI_AUDIO_AUTO)
                        intel_hdmi->has_audio =
-                               (intel_hdmi->force_audio == HDMI_AUDIO_ON);
-               intel_encoder->type = INTEL_OUTPUT_HDMI;
+                               intel_hdmi->force_audio == HDMI_AUDIO_ON;
+               if (intel_hdmi->force_audio != HDMI_AUDIO_OFF_DVI)
+                       intel_hdmi->has_hdmi_sink =
+                               drm_detect_hdmi_monitor(edid);
+               connected = true;
        }
  
-       intel_display_power_put(dev_priv, power_domain);
+       return connected;
+ }
+ static enum drm_connector_status
+ intel_hdmi_detect(struct drm_connector *connector, bool force)
+ {
+       enum drm_connector_status status;
+       DRM_DEBUG_KMS("[CONNECTOR:%d:%s]\n",
+                     connector->base.id, connector->name);
+       intel_hdmi_unset_edid(connector);
+       if (intel_hdmi_set_edid(connector)) {
+               struct intel_hdmi *intel_hdmi = intel_attached_hdmi(connector);
+               hdmi_to_dig_port(intel_hdmi)->base.type = INTEL_OUTPUT_HDMI;
+               status = connector_status_connected;
+       } else
+               status = connector_status_disconnected;
  
        return status;
  }
  
- static int intel_hdmi_get_modes(struct drm_connector *connector)
+ static void
+ intel_hdmi_force(struct drm_connector *connector)
  {
-       struct intel_encoder *intel_encoder = intel_attached_encoder(connector);
-       struct intel_hdmi *intel_hdmi = enc_to_intel_hdmi(&intel_encoder->base);
-       struct drm_i915_private *dev_priv = connector->dev->dev_private;
-       enum intel_display_power_domain power_domain;
-       int ret;
+       struct intel_hdmi *intel_hdmi = intel_attached_hdmi(connector);
  
-       /* We should parse the EDID data and find out if it's an HDMI sink so
-        * we can send audio to it.
-        */
+       DRM_DEBUG_KMS("[CONNECTOR:%d:%s]\n",
+                     connector->base.id, connector->name);
  
-       power_domain = intel_display_port_power_domain(intel_encoder);
-       intel_display_power_get(dev_priv, power_domain);
+       intel_hdmi_unset_edid(connector);
  
-       ret = intel_ddc_get_modes(connector,
-                                  intel_gmbus_get_adapter(dev_priv,
-                                                          intel_hdmi->ddc_bus));
+       if (connector->status != connector_status_connected)
+               return;
  
-       intel_display_power_put(dev_priv, power_domain);
+       intel_hdmi_set_edid(connector);
+       hdmi_to_dig_port(intel_hdmi)->base.type = INTEL_OUTPUT_HDMI;
+ }
  
-       return ret;
+ static int intel_hdmi_get_modes(struct drm_connector *connector)
+ {
+       struct edid *edid;
+       edid = to_intel_connector(connector)->detect_edid;
+       if (edid == NULL)
+               return 0;
+       return intel_connector_update_modes(connector, edid);
  }
  
  static bool
  intel_hdmi_detect_audio(struct drm_connector *connector)
  {
-       struct intel_encoder *intel_encoder = intel_attached_encoder(connector);
-       struct intel_hdmi *intel_hdmi = enc_to_intel_hdmi(&intel_encoder->base);
-       struct drm_i915_private *dev_priv = connector->dev->dev_private;
-       enum intel_display_power_domain power_domain;
-       struct edid *edid;
        bool has_audio = false;
+       struct edid *edid;
  
-       power_domain = intel_display_port_power_domain(intel_encoder);
-       intel_display_power_get(dev_priv, power_domain);
-       edid = drm_get_edid(connector,
-                           intel_gmbus_get_adapter(dev_priv,
-                                                   intel_hdmi->ddc_bus));
-       if (edid) {
-               if (edid->input & DRM_EDID_INPUT_DIGITAL)
-                       has_audio = drm_detect_monitor_audio(edid);
-               kfree(edid);
-       }
-       intel_display_power_put(dev_priv, power_domain);
+       edid = to_intel_connector(connector)->detect_edid;
+       if (edid && edid->input & DRM_EDID_INPUT_DIGITAL)
+               has_audio = drm_detect_monitor_audio(edid);
  
        return has_audio;
  }
@@@ -1488,6 -1492,7 +1501,7 @@@ static void chv_hdmi_pre_enable(struct 
  
  static void intel_hdmi_destroy(struct drm_connector *connector)
  {
+       intel_hdmi_unset_edid(connector);
        drm_connector_cleanup(connector);
        kfree(connector);
  }
  static const struct drm_connector_funcs intel_hdmi_connector_funcs = {
        .dpms = intel_connector_dpms,
        .detect = intel_hdmi_detect,
+       .force = intel_hdmi_force,
        .fill_modes = drm_helper_probe_single_connector_modes,
        .set_property = intel_hdmi_set_property,
        .destroy = intel_hdmi_destroy,
index 8e374449c6b562356f47ac2ba169f974f8e7226f,fd6f1f89865e10b3f3d27af5acf19dc6ed1dc3b0..18784470a760def6c6fd4af4938e53145acd4cab
@@@ -751,6 -751,8 +751,8 @@@ void intel_panel_disable_backlight(stru
  
        spin_lock_irqsave(&dev_priv->backlight_lock, flags);
  
+       if (panel->backlight.device)
+               panel->backlight.device->props.power = FB_BLANK_POWERDOWN;
        panel->backlight.enabled = false;
        dev_priv->display.disable_backlight(connector);
  
@@@ -801,7 -803,7 +803,7 @@@ static void pch_enable_backlight(struc
  
        cpu_ctl2 = I915_READ(BLC_PWM_CPU_CTL2);
        if (cpu_ctl2 & BLM_PWM_ENABLE) {
 -              WARN(1, "cpu backlight already enabled\n");
 +              DRM_DEBUG_KMS("cpu backlight already enabled\n");
                cpu_ctl2 &= ~BLM_PWM_ENABLE;
                I915_WRITE(BLC_PWM_CPU_CTL2, cpu_ctl2);
        }
@@@ -845,7 -847,7 +847,7 @@@ static void i9xx_enable_backlight(struc
  
        ctl = I915_READ(BLC_PWM_CTL);
        if (ctl & BACKLIGHT_DUTY_CYCLE_MASK_PNV) {
 -              WARN(1, "backlight already enabled\n");
 +              DRM_DEBUG_KMS("backlight already enabled\n");
                I915_WRITE(BLC_PWM_CTL, 0);
        }
  
@@@ -876,7 -878,7 +878,7 @@@ static void i965_enable_backlight(struc
  
        ctl2 = I915_READ(BLC_PWM_CTL2);
        if (ctl2 & BLM_PWM_ENABLE) {
 -              WARN(1, "backlight already enabled\n");
 +              DRM_DEBUG_KMS("backlight already enabled\n");
                ctl2 &= ~BLM_PWM_ENABLE;
                I915_WRITE(BLC_PWM_CTL2, ctl2);
        }
@@@ -910,7 -912,7 +912,7 @@@ static void vlv_enable_backlight(struc
  
        ctl2 = I915_READ(VLV_BLC_PWM_CTL2(pipe));
        if (ctl2 & BLM_PWM_ENABLE) {
 -              WARN(1, "backlight already enabled\n");
 +              DRM_DEBUG_KMS("backlight already enabled\n");
                ctl2 &= ~BLM_PWM_ENABLE;
                I915_WRITE(VLV_BLC_PWM_CTL2(pipe), ctl2);
        }
@@@ -957,6 -959,8 +959,8 @@@ void intel_panel_enable_backlight(struc
  
        dev_priv->display.enable_backlight(connector);
        panel->backlight.enabled = true;
+       if (panel->backlight.device)
+               panel->backlight.device->props.power = FB_BLANK_UNBLANK;
  
        spin_unlock_irqrestore(&dev_priv->backlight_lock, flags);
  }
  static int intel_backlight_device_update_status(struct backlight_device *bd)
  {
        struct intel_connector *connector = bl_get_data(bd);
+       struct intel_panel *panel = &connector->panel;
        struct drm_device *dev = connector->base.dev;
  
        drm_modeset_lock(&dev->mode_config.connection_mutex, NULL);
                      bd->props.brightness, bd->props.max_brightness);
        intel_panel_set_backlight(connector, bd->props.brightness,
                                  bd->props.max_brightness);
+       /*
+        * Allow flipping bl_power as a sub-state of enabled. Sadly the
+        * backlight class device does not make it easy to to differentiate
+        * between callbacks for brightness and bl_power, so our backlight_power
+        * callback needs to take this into account.
+        */
+       if (panel->backlight.enabled) {
+               if (panel->backlight_power) {
+                       bool enable = bd->props.power == FB_BLANK_UNBLANK &&
+                               bd->props.brightness != 0;
+                       panel->backlight_power(connector, enable);
+               }
+       } else {
+               bd->props.power = FB_BLANK_POWERDOWN;
+       }
        drm_modeset_unlock(&dev->mode_config.connection_mutex);
        return 0;
  }
@@@ -1023,6 -1045,11 +1045,11 @@@ static int intel_backlight_device_regis
                                            panel->backlight.level,
                                            props.max_brightness);
  
+       if (panel->backlight.enabled)
+               props.power = FB_BLANK_UNBLANK;
+       else
+               props.power = FB_BLANK_POWERDOWN;
        /*
         * Note: using the same name independent of the connector prevents
         * registration of multiple backlight devices in the driver.
@@@ -1203,7 -1230,7 +1230,7 @@@ static int vlv_setup_backlight(struct i
        enum pipe pipe;
        u32 ctl, ctl2, val;
  
-       for_each_pipe(pipe) {
+       for_each_pipe(dev_priv, pipe) {
                u32 cur_val = I915_READ(VLV_BLC_PWM_CTL(pipe));
  
                /* Skip if the modulation freq is already set */
index 3c7283d8f1609682809b8539149a7a83cf7f15fe,85fc2b1a124ad5e3fe72f97371c6fc3719ade829..109de2eeb9a812a9045403542560c9d953754418
@@@ -444,7 -444,14 +444,14 @@@ gen8_render_ring_flush(struct intel_eng
                        return ret;
        }
  
-       return gen8_emit_pipe_control(ring, flags, scratch_addr);
+       ret = gen8_emit_pipe_control(ring, flags, scratch_addr);
+       if (ret)
+               return ret;
+       if (!invalidate_domains && flush_domains)
+               return gen7_ring_fbc_flush(ring, FBC_REND_NUKE);
+       return 0;
  }
  
  static void ring_write_tail(struct intel_engine_cs *ring,
@@@ -556,6 -563,14 +563,14 @@@ static int init_ring_common(struct inte
         * also enforces ordering), otherwise the hw might lose the new ring
         * register values. */
        I915_WRITE_START(ring, i915_gem_obj_ggtt_offset(obj));
+       /* WaClearRingBufHeadRegAtInit:ctg,elk */
+       if (I915_READ_HEAD(ring))
+               DRM_DEBUG("%s initialization failed [head=%08x], fudging\n",
+                         ring->name, I915_READ_HEAD(ring));
+       I915_WRITE_HEAD(ring, 0);
+       (void)I915_READ_HEAD(ring);
        I915_WRITE_CTL(ring,
                        ((ringbuf->size - PAGE_SIZE) & RING_NR_PAGES)
                        | RING_VALID);
@@@ -650,6 -665,146 +665,146 @@@ err
        return ret;
  }
  
+ static inline void intel_ring_emit_wa(struct intel_engine_cs *ring,
+                                      u32 addr, u32 value)
+ {
+       struct drm_device *dev = ring->dev;
+       struct drm_i915_private *dev_priv = dev->dev_private;
+       if (WARN_ON(dev_priv->num_wa_regs >= I915_MAX_WA_REGS))
+               return;
+       intel_ring_emit(ring, MI_LOAD_REGISTER_IMM(1));
+       intel_ring_emit(ring, addr);
+       intel_ring_emit(ring, value);
+       dev_priv->intel_wa_regs[dev_priv->num_wa_regs].addr = addr;
+       dev_priv->intel_wa_regs[dev_priv->num_wa_regs].mask = value & 0xFFFF;
+       /* value is updated with the status of remaining bits of this
+        * register when it is read from debugfs file
+        */
+       dev_priv->intel_wa_regs[dev_priv->num_wa_regs].value = value;
+       dev_priv->num_wa_regs++;
+       return;
+ }
+ static int bdw_init_workarounds(struct intel_engine_cs *ring)
+ {
+       int ret;
+       struct drm_device *dev = ring->dev;
+       struct drm_i915_private *dev_priv = dev->dev_private;
+       /*
+        * workarounds applied in this fn are part of register state context,
+        * they need to be re-initialized followed by gpu reset, suspend/resume,
+        * module reload.
+        */
+       dev_priv->num_wa_regs = 0;
+       memset(dev_priv->intel_wa_regs, 0, sizeof(dev_priv->intel_wa_regs));
+       /*
+        * update the number of dwords required based on the
+        * actual number of workarounds applied
+        */
+       ret = intel_ring_begin(ring, 24);
+       if (ret)
+               return ret;
+       /* WaDisablePartialInstShootdown:bdw */
+       /* WaDisableThreadStallDopClockGating:bdw */
+       /* FIXME: Unclear whether we really need this on production bdw. */
+       intel_ring_emit_wa(ring, GEN8_ROW_CHICKEN,
+                          _MASKED_BIT_ENABLE(PARTIAL_INSTRUCTION_SHOOTDOWN_DISABLE
+                                            | STALL_DOP_GATING_DISABLE));
+       /* WaDisableDopClockGating:bdw May not be needed for production */
+       intel_ring_emit_wa(ring, GEN7_ROW_CHICKEN2,
+                          _MASKED_BIT_ENABLE(DOP_CLOCK_GATING_DISABLE));
+       /*
+        * This GEN8_CENTROID_PIXEL_OPT_DIS W/A is only needed for
+        * pre-production hardware
+        */
+       intel_ring_emit_wa(ring, HALF_SLICE_CHICKEN3,
+                          _MASKED_BIT_ENABLE(GEN8_CENTROID_PIXEL_OPT_DIS
+                                             | GEN8_SAMPLER_POWER_BYPASS_DIS));
+       intel_ring_emit_wa(ring, GEN7_HALF_SLICE_CHICKEN1,
+                          _MASKED_BIT_ENABLE(GEN7_SINGLE_SUBSCAN_DISPATCH_ENABLE));
+       intel_ring_emit_wa(ring, COMMON_SLICE_CHICKEN2,
+                          _MASKED_BIT_ENABLE(GEN8_CSC2_SBE_VUE_CACHE_CONSERVATIVE));
+       /* Use Force Non-Coherent whenever executing a 3D context. This is a
+        * workaround for for a possible hang in the unlikely event a TLB
+        * invalidation occurs during a PSD flush.
+        */
+       intel_ring_emit_wa(ring, HDC_CHICKEN0,
+                          _MASKED_BIT_ENABLE(HDC_FORCE_NON_COHERENT));
+       /* Wa4x4STCOptimizationDisable:bdw */
+       intel_ring_emit_wa(ring, CACHE_MODE_1,
+                          _MASKED_BIT_ENABLE(GEN8_4x4_STC_OPTIMIZATION_DISABLE));
+       /*
+        * BSpec recommends 8x4 when MSAA is used,
+        * however in practice 16x4 seems fastest.
+        *
+        * Note that PS/WM thread counts depend on the WIZ hashing
+        * disable bit, which we don't touch here, but it's good
+        * to keep in mind (see 3DSTATE_PS and 3DSTATE_WM).
+        */
+       intel_ring_emit_wa(ring, GEN7_GT_MODE,
+                          GEN6_WIZ_HASHING_MASK | GEN6_WIZ_HASHING_16x4);
+       intel_ring_advance(ring);
+       DRM_DEBUG_DRIVER("Number of Workarounds applied: %d\n",
+                        dev_priv->num_wa_regs);
+       return 0;
+ }
+ static int chv_init_workarounds(struct intel_engine_cs *ring)
+ {
+       int ret;
+       struct drm_device *dev = ring->dev;
+       struct drm_i915_private *dev_priv = dev->dev_private;
+       /*
+        * workarounds applied in this fn are part of register state context,
+        * they need to be re-initialized followed by gpu reset, suspend/resume,
+        * module reload.
+        */
+       dev_priv->num_wa_regs = 0;
+       memset(dev_priv->intel_wa_regs, 0, sizeof(dev_priv->intel_wa_regs));
+       ret = intel_ring_begin(ring, 12);
+       if (ret)
+               return ret;
+       /* WaDisablePartialInstShootdown:chv */
+       intel_ring_emit_wa(ring, GEN8_ROW_CHICKEN,
+                          _MASKED_BIT_ENABLE(PARTIAL_INSTRUCTION_SHOOTDOWN_DISABLE));
+       /* WaDisableThreadStallDopClockGating:chv */
+       intel_ring_emit_wa(ring, GEN8_ROW_CHICKEN,
+                          _MASKED_BIT_ENABLE(STALL_DOP_GATING_DISABLE));
+       /* WaDisableDopClockGating:chv (pre-production hw) */
+       intel_ring_emit_wa(ring, GEN7_ROW_CHICKEN2,
+                          _MASKED_BIT_ENABLE(DOP_CLOCK_GATING_DISABLE));
+       /* WaDisableSamplerPowerBypass:chv (pre-production hw) */
+       intel_ring_emit_wa(ring, HALF_SLICE_CHICKEN3,
+                          _MASKED_BIT_ENABLE(GEN8_SAMPLER_POWER_BYPASS_DIS));
+       intel_ring_advance(ring);
+       return 0;
+ }
  static int init_render_ring(struct intel_engine_cs *ring)
  {
        struct drm_device *dev = ring->dev;
@@@ -1387,66 -1542,54 +1542,66 @@@ i965_dispatch_execbuffer(struct intel_e
  
  /* Just userspace ABI convention to limit the wa batch bo to a resonable size */
  #define I830_BATCH_LIMIT (256*1024)
 +#define I830_TLB_ENTRIES (2)
 +#define I830_WA_SIZE max(I830_TLB_ENTRIES*4096, I830_BATCH_LIMIT)
  static int
  i830_dispatch_execbuffer(struct intel_engine_cs *ring,
                                u64 offset, u32 len,
                                unsigned flags)
  {
 +      u32 cs_offset = ring->scratch.gtt_offset;
        int ret;
  
 -      if (flags & I915_DISPATCH_PINNED) {
 -              ret = intel_ring_begin(ring, 4);
 -              if (ret)
 -                      return ret;
 +      ret = intel_ring_begin(ring, 6);
 +      if (ret)
 +              return ret;
  
 -              intel_ring_emit(ring, MI_BATCH_BUFFER);
 -              intel_ring_emit(ring, offset | (flags & I915_DISPATCH_SECURE ? 0 : MI_BATCH_NON_SECURE));
 -              intel_ring_emit(ring, offset + len - 8);
 -              intel_ring_emit(ring, MI_NOOP);
 -              intel_ring_advance(ring);
 -      } else {
 -              u32 cs_offset = ring->scratch.gtt_offset;
 +      /* Evict the invalid PTE TLBs */
 +      intel_ring_emit(ring, COLOR_BLT_CMD | BLT_WRITE_RGBA);
 +      intel_ring_emit(ring, BLT_DEPTH_32 | BLT_ROP_COLOR_COPY | 4096);
 +      intel_ring_emit(ring, I830_TLB_ENTRIES << 16 | 4); /* load each page */
 +      intel_ring_emit(ring, cs_offset);
 +      intel_ring_emit(ring, 0xdeadbeef);
 +      intel_ring_emit(ring, MI_NOOP);
 +      intel_ring_advance(ring);
  
 +      if ((flags & I915_DISPATCH_PINNED) == 0) {
                if (len > I830_BATCH_LIMIT)
                        return -ENOSPC;
  
 -              ret = intel_ring_begin(ring, 9+3);
 +              ret = intel_ring_begin(ring, 6 + 2);
                if (ret)
                        return ret;
 -              /* Blit the batch (which has now all relocs applied) to the stable batch
 -               * scratch bo area (so that the CS never stumbles over its tlb
 -               * invalidation bug) ... */
 -              intel_ring_emit(ring, XY_SRC_COPY_BLT_CMD |
 -                              XY_SRC_COPY_BLT_WRITE_ALPHA |
 -                              XY_SRC_COPY_BLT_WRITE_RGB);
 -              intel_ring_emit(ring, BLT_DEPTH_32 | BLT_ROP_GXCOPY | 4096);
 -              intel_ring_emit(ring, 0);
 -              intel_ring_emit(ring, (DIV_ROUND_UP(len, 4096) << 16) | 1024);
 +
 +              /* Blit the batch (which has now all relocs applied) to the
 +               * stable batch scratch bo area (so that the CS never
 +               * stumbles over its tlb invalidation bug) ...
 +               */
 +              intel_ring_emit(ring, SRC_COPY_BLT_CMD | BLT_WRITE_RGBA);
 +              intel_ring_emit(ring, BLT_DEPTH_32 | BLT_ROP_SRC_COPY | 4096);
 +              intel_ring_emit(ring, DIV_ROUND_UP(len, 4096) << 16 | 1024);
                intel_ring_emit(ring, cs_offset);
 -              intel_ring_emit(ring, 0);
                intel_ring_emit(ring, 4096);
                intel_ring_emit(ring, offset);
 +
                intel_ring_emit(ring, MI_FLUSH);
 +              intel_ring_emit(ring, MI_NOOP);
 +              intel_ring_advance(ring);
  
                /* ... and execute it. */
 -              intel_ring_emit(ring, MI_BATCH_BUFFER);
 -              intel_ring_emit(ring, cs_offset | (flags & I915_DISPATCH_SECURE ? 0 : MI_BATCH_NON_SECURE));
 -              intel_ring_emit(ring, cs_offset + len - 8);
 -              intel_ring_advance(ring);
 +              offset = cs_offset;
        }
  
 +      ret = intel_ring_begin(ring, 4);
 +      if (ret)
 +              return ret;
 +
 +      intel_ring_emit(ring, MI_BATCH_BUFFER);
 +      intel_ring_emit(ring, offset | (flags & I915_DISPATCH_SECURE ? 0 : MI_BATCH_NON_SECURE));
 +      intel_ring_emit(ring, offset + len - 8);
 +      intel_ring_emit(ring, MI_NOOP);
 +      intel_ring_advance(ring);
 +
        return 0;
  }
  
@@@ -2148,6 -2291,10 +2303,10 @@@ int intel_init_render_ring_buffer(struc
                                        dev_priv->semaphore_obj = obj;
                        }
                }
+               if (IS_CHERRYVIEW(dev))
+                       ring->init_context = chv_init_workarounds;
+               else
+                       ring->init_context = bdw_init_workarounds;
                ring->add_request = gen6_add_request;
                ring->flush = gen8_render_ring_flush;
                ring->irq_get = gen8_ring_get_irq;
  
        /* Workaround batchbuffer to combat CS tlb bug. */
        if (HAS_BROKEN_CS_TLB(dev)) {
 -              obj = i915_gem_alloc_object(dev, I830_BATCH_LIMIT);
 +              obj = i915_gem_alloc_object(dev, I830_WA_SIZE);
                if (obj == NULL) {
                        DRM_ERROR("Failed to allocate batch bo\n");
                        return -ENOMEM;
index ac14b67621d36f7a068de85103e06ba644915ea3,95ea276928bd0b363225af80305498fa8adf53b0..95d5d4ab3335edd2c86146c487c9cbd7bc269182
@@@ -232,8 -232,8 +232,8 @@@ void radeon_dp_aux_init(struct radeon_c
  
  /***** general DP utility functions *****/
  
- #define DP_VOLTAGE_MAX         DP_TRAIN_VOLTAGE_SWING_1200
- #define DP_PRE_EMPHASIS_MAX    DP_TRAIN_PRE_EMPHASIS_9_5
+ #define DP_VOLTAGE_MAX         DP_TRAIN_VOLTAGE_SWING_LEVEL_3
+ #define DP_PRE_EMPHASIS_MAX    DP_TRAIN_PRE_EMPH_LEVEL_3
  
  static void dp_get_adjust_train(u8 link_status[DP_LINK_STATUS_SIZE],
                                int lane_count,
@@@ -405,13 -405,16 +405,13 @@@ bool radeon_dp_getdpcd(struct radeon_co
        u8 msg[DP_DPCD_SIZE];
        int ret;
  
 -      char dpcd_hex_dump[DP_DPCD_SIZE * 3];
 -
        ret = drm_dp_dpcd_read(&radeon_connector->ddc_bus->aux, DP_DPCD_REV, msg,
                               DP_DPCD_SIZE);
        if (ret > 0) {
                memcpy(dig_connector->dpcd, msg, DP_DPCD_SIZE);
  
 -              hex_dump_to_buffer(dig_connector->dpcd, sizeof(dig_connector->dpcd),
 -                                 32, 1, dpcd_hex_dump, sizeof(dpcd_hex_dump), false);
 -              DRM_DEBUG_KMS("DPCD: %s\n", dpcd_hex_dump);
 +              DRM_DEBUG_KMS("DPCD: %*ph\n", (int)sizeof(dig_connector->dpcd),
 +                            dig_connector->dpcd);
  
                radeon_dp_probe_oui(radeon_connector);
  
This page took 0.31735 seconds and 4 git commands to generate.