]> git.karo-electronics.de Git - linux-beck.git/commitdiff
Merge tag 'drm-intel-fixes-2015-08-14' into drm-intel-next-fixes
authorDaniel Vetter <daniel.vetter@ffwll.ch>
Fri, 14 Aug 2015 16:10:35 +0000 (18:10 +0200)
committerDaniel Vetter <daniel.vetter@ffwll.ch>
Fri, 14 Aug 2015 16:11:30 +0000 (18:11 +0200)
Backmerge drm-intel-fixes because a bunch of atomic patch backporting
we had to do lead to horrible conflicts.

Conflicts:
drivers/gpu/drm/drm_crtc.c
Just a bit of context conflict between -next and -fixes.
drivers/gpu/drm/i915/intel_atomic.c
drivers/gpu/drm/i915/intel_display.c
Atomic conflicts, always pick the code from -next.

Signed-off-by: Daniel Vetter <daniel.vetter@intel.com>
18 files changed:
1  2 
MAINTAINERS
drivers/gpu/drm/amd/amdgpu/amdgpu.h
drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c
drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_crtc.c
drivers/gpu/drm/drm_atomic_helper.c
drivers/gpu/drm/drm_crtc.c
drivers/gpu/drm/drm_irq.c
drivers/gpu/drm/i915/i915_drv.h
drivers/gpu/drm/i915/i915_gem_gtt.c
drivers/gpu/drm/i915/i915_gem_tiling.c
drivers/gpu/drm/i915/intel_bios.c
drivers/gpu/drm/i915/intel_display.c
drivers/gpu/drm/i915/intel_dp_mst.c
drivers/gpu/drm/i915/intel_uncore.c
drivers/gpu/drm/nouveau/nouveau_drm.c
include/drm/drmP.h
include/drm/drm_crtc_helper.h
include/uapi/drm/i915_drm.h

diff --combined MAINTAINERS
index 9c9dd5fc7affdd4fd1ba89ac7210a9251bee438f,a9ae6c105520011994801168a7841b4d713b716e..94212186990d96f90d0494a7d5a0a79fc0156a7b
@@@ -636,14 -636,9 +636,14 @@@ M:       Oded Gabbay <oded.gabbay@gmail.com
  L:    dri-devel@lists.freedesktop.org
  T:    git git://people.freedesktop.org/~gabbayo/linux.git
  S:    Supported
 +F:    drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.c
 +F:    drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.h
 +F:    drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gfx_v7.c
 +F:    drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gfx_v8.c
  F:    drivers/gpu/drm/amd/amdkfd/
  F:    drivers/gpu/drm/amd/include/cik_structs.h
  F:    drivers/gpu/drm/amd/include/kgd_kfd_interface.h
 +F:    drivers/gpu/drm/amd/include/vi_structs.h
  F:    drivers/gpu/drm/radeon/radeon_kfd.c
  F:    drivers/gpu/drm/radeon/radeon_kfd.h
  F:    include/uapi/linux/kfd_ioctl.h
@@@ -5605,6 -5600,7 +5605,7 @@@ F:      kernel/irq
  IRQCHIP DRIVERS
  M:    Thomas Gleixner <tglx@linutronix.de>
  M:    Jason Cooper <jason@lakedaemon.net>
+ M:    Marc Zyngier <marc.zyngier@arm.com>
  L:    linux-kernel@vger.kernel.org
  S:    Maintained
  T:    git git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip.git irq/core
@@@ -5613,11 -5609,14 +5614,14 @@@ F:   Documentation/devicetree/bindings/in
  F:    drivers/irqchip/
  
  IRQ DOMAINS (IRQ NUMBER MAPPING LIBRARY)
- M:    Benjamin Herrenschmidt <benh@kernel.crashing.org>
+ M:    Jiang Liu <jiang.liu@linux.intel.com>
+ M:    Marc Zyngier <marc.zyngier@arm.com>
  S:    Maintained
+ T:    git git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip.git irq/core
  F:    Documentation/IRQ-domain.txt
  F:    include/linux/irqdomain.h
  F:    kernel/irq/irqdomain.c
+ F:    kernel/irq/msi.c
  
  ISAPNP
  M:    Jaroslav Kysela <perex@perex.cz>
@@@ -5904,7 -5903,6 +5908,6 @@@ S:      Supporte
  F:    Documentation/s390/kvm.txt
  F:    arch/s390/include/asm/kvm*
  F:    arch/s390/kvm/
- F:    drivers/s390/kvm/
  
  KERNEL VIRTUAL MACHINE (KVM) FOR ARM
  M:    Christoffer Dall <christoffer.dall@linaro.org>
@@@ -6844,6 -6842,12 +6847,12 @@@ T:    git git://linuxtv.org/anttip/media_t
  S:    Maintained
  F:    drivers/media/usb/msi2500/
  
+ MSYSTEMS DISKONCHIP G3 MTD DRIVER
+ M:    Robert Jarzmik <robert.jarzmik@free.fr>
+ L:    linux-mtd@lists.infradead.org
+ S:    Maintained
+ F:    drivers/mtd/devices/docg3*
  MT9M032 APTINA SENSOR DRIVER
  M:    Laurent Pinchart <laurent.pinchart@ideasonboard.com>
  L:    linux-media@vger.kernel.org
@@@ -10901,6 -10905,15 +10910,15 @@@ F: drivers/block/virtio_blk.
  F:    include/linux/virtio_*.h
  F:    include/uapi/linux/virtio_*.h
  
+ VIRTIO DRIVERS FOR S390
+ M:    Christian Borntraeger <borntraeger@de.ibm.com>
+ M:    Cornelia Huck <cornelia.huck@de.ibm.com>
+ L:    linux-s390@vger.kernel.org
+ L:    virtualization@lists.linux-foundation.org
+ L:    kvm@vger.kernel.org
+ S:    Supported
+ F:    drivers/s390/virtio/
  VIRTIO GPU DRIVER
  M:    David Airlie <airlied@linux.ie>
  M:    Gerd Hoffmann <kraxel@redhat.com>
index f3791e0d27d48322ac0c5ba35676a8d07eda0b4d,f7b49d5ce4b81d471fa3c84280560b9d0e774c78..baefa635169a953f4cb41840b24de11b632e7345
@@@ -1130,6 -1130,9 +1130,9 @@@ struct amdgpu_gfx 
        uint32_t                        me_feature_version;
        uint32_t                        ce_feature_version;
        uint32_t                        pfp_feature_version;
+       uint32_t                        rlc_feature_version;
+       uint32_t                        mec_feature_version;
+       uint32_t                        mec2_feature_version;
        struct amdgpu_ring              gfx_ring[AMDGPU_MAX_GFX_RINGS];
        unsigned                        num_gfx_rings;
        struct amdgpu_ring              compute_ring[AMDGPU_MAX_COMPUTE_RINGS];
@@@ -1614,6 -1617,9 +1617,9 @@@ struct amdgpu_uvd 
  #define AMDGPU_MAX_VCE_HANDLES        16
  #define AMDGPU_VCE_FIRMWARE_OFFSET 256
  
+ #define AMDGPU_VCE_HARVEST_VCE0 (1 << 0)
+ #define AMDGPU_VCE_HARVEST_VCE1 (1 << 1)
  struct amdgpu_vce {
        struct amdgpu_bo        *vcpu_bo;
        uint64_t                gpu_addr;
        const struct firmware   *fw;    /* VCE firmware */
        struct amdgpu_ring      ring[AMDGPU_MAX_VCE_RINGS];
        struct amdgpu_irq_src   irq;
+       unsigned                harvest_config;
  };
  
  /*
@@@ -1635,6 -1642,7 +1642,7 @@@ struct amdgpu_sdma 
        /* SDMA firmware */
        const struct firmware   *fw;
        uint32_t                fw_version;
+       uint32_t                feature_version;
  
        struct amdgpu_ring      ring;
  };
@@@ -1862,6 -1870,12 +1870,12 @@@ typedef void (*amdgpu_wreg_t)(struct am
  typedef uint32_t (*amdgpu_block_rreg_t)(struct amdgpu_device*, uint32_t, uint32_t);
  typedef void (*amdgpu_block_wreg_t)(struct amdgpu_device*, uint32_t, uint32_t, uint32_t);
  
+ struct amdgpu_ip_block_status {
+       bool valid;
+       bool sw;
+       bool hw;
+ };
  struct amdgpu_device {
        struct device                   *dev;
        struct drm_device               *ddev;
  
        const struct amdgpu_ip_block_version *ip_blocks;
        int                             num_ip_blocks;
-       bool                            *ip_block_enabled;
+       struct amdgpu_ip_block_status   *ip_block_status;
        struct mutex    mn_lock;
        DECLARE_HASHTABLE(mn_hash, 7);
  
        /* tracking pinned memory */
        u64 vram_pin_size;
        u64 gart_pin_size;
 +
 +      /* amdkfd interface */
 +      struct kfd_dev          *kfd;
  };
  
  bool amdgpu_device_is_px(struct drm_device *dev);
index 8c40a9671b9fb0702765d88d8ee78eddfb040b8c,3bfe67de834904628e0e4e11677c706c4848fde7..93000af92283f3619114c4dfd1f0e916f7adeec8
@@@ -34,7 -34,6 +34,7 @@@
  #include <linux/vga_switcheroo.h>
  #include <linux/slab.h>
  #include <linux/pm_runtime.h>
 +#include "amdgpu_amdkfd.h"
  
  #if defined(CONFIG_VGA_SWITCHEROO)
  bool amdgpu_has_atpx(void);
@@@ -62,8 -61,6 +62,8 @@@ int amdgpu_driver_unload_kms(struct drm
  
        pm_runtime_get_sync(dev->dev);
  
 +      amdgpu_amdkfd_device_fini(adev);
 +
        amdgpu_acpi_fini(adev);
  
        amdgpu_device_fini(adev);
@@@ -121,10 -118,6 +121,10 @@@ int amdgpu_driver_load_kms(struct drm_d
                                "Error during ACPI methods call\n");
        }
  
 +      amdgpu_amdkfd_load_interface(adev);
 +      amdgpu_amdkfd_device_probe(adev);
 +      amdgpu_amdkfd_device_init(adev);
 +
        if (amdgpu_device_is_px(dev)) {
                pm_runtime_use_autosuspend(dev->dev);
                pm_runtime_set_autosuspend_delay(dev->dev, 5000);
@@@ -242,7 -235,7 +242,7 @@@ static int amdgpu_info_ioctl(struct drm
  
                for (i = 0; i < adev->num_ip_blocks; i++) {
                        if (adev->ip_blocks[i].type == type &&
-                           adev->ip_block_enabled[i]) {
+                           adev->ip_block_status[i].valid) {
                                ip.hw_ip_version_major = adev->ip_blocks[i].major;
                                ip.hw_ip_version_minor = adev->ip_blocks[i].minor;
                                ip.capabilities_flags = 0;
  
                for (i = 0; i < adev->num_ip_blocks; i++)
                        if (adev->ip_blocks[i].type == type &&
-                           adev->ip_block_enabled[i] &&
+                           adev->ip_block_status[i].valid &&
                            count < AMDGPU_HW_IP_INSTANCE_MAX_COUNT)
                                count++;
  
                        break;
                case AMDGPU_INFO_FW_GFX_RLC:
                        fw_info.ver = adev->gfx.rlc_fw_version;
-                       fw_info.feature = 0;
+                       fw_info.feature = adev->gfx.rlc_feature_version;
                        break;
                case AMDGPU_INFO_FW_GFX_MEC:
-                       if (info->query_fw.index == 0)
+                       if (info->query_fw.index == 0) {
                                fw_info.ver = adev->gfx.mec_fw_version;
-                       else if (info->query_fw.index == 1)
+                               fw_info.feature = adev->gfx.mec_feature_version;
+                       } else if (info->query_fw.index == 1) {
                                fw_info.ver = adev->gfx.mec2_fw_version;
-                       else
+                               fw_info.feature = adev->gfx.mec2_feature_version;
+                       } else
                                return -EINVAL;
-                       fw_info.feature = 0;
                        break;
                case AMDGPU_INFO_FW_SMC:
                        fw_info.ver = adev->pm.fw_version;
                        if (info->query_fw.index >= 2)
                                return -EINVAL;
                        fw_info.ver = adev->sdma[info->query_fw.index].fw_version;
-                       fw_info.feature = 0;
+                       fw_info.feature = adev->sdma[info->query_fw.index].feature_version;
                        break;
                default:
                        return -EINVAL;
                return n ? -EFAULT : 0;
        }
        case AMDGPU_INFO_DEV_INFO: {
-               struct drm_amdgpu_info_device dev_info;
+               struct drm_amdgpu_info_device dev_info = {};
                struct amdgpu_cu_info cu_info;
  
                dev_info.device_id = dev->pdev->device;
                memcpy(&dev_info.cu_bitmap[0], &cu_info.bitmap[0], sizeof(cu_info.bitmap));
                dev_info.vram_type = adev->mc.vram_type;
                dev_info.vram_bit_width = adev->mc.vram_width;
+               dev_info.vce_harvest_config = adev->vce.harvest_config;
  
                return copy_to_user(out, &dev_info,
                                    min((size_t)size, sizeof(dev_info))) ? -EFAULT : 0;
index 8b8fe3762ca9dba11c73b24f1dea6f75bb0ec009,5ae5c69231280a5e1c23882289388f9ceb75a701..9f6e234e70296a9c35f4877cac98d5ff73b2c73c
@@@ -239,8 -239,7 +239,8 @@@ static int atmel_hlcdc_crtc_atomic_chec
        return atmel_hlcdc_plane_prepare_disc_area(s);
  }
  
 -static void atmel_hlcdc_crtc_atomic_begin(struct drm_crtc *c)
 +static void atmel_hlcdc_crtc_atomic_begin(struct drm_crtc *c,
 +                                        struct drm_crtc_state *old_s)
  {
        struct atmel_hlcdc_crtc *crtc = drm_crtc_to_atmel_hlcdc_crtc(c);
  
        }
  }
  
 -static void atmel_hlcdc_crtc_atomic_flush(struct drm_crtc *crtc)
 +static void atmel_hlcdc_crtc_atomic_flush(struct drm_crtc *crtc,
 +                                        struct drm_crtc_state *old_s)
  {
        /* TODO: write common plane control register if available */
  }
@@@ -357,6 -355,7 +357,7 @@@ int atmel_hlcdc_crtc_create(struct drm_
                planes->overlays[i]->base.possible_crtcs = 1 << crtc->id;
  
        drm_crtc_helper_add(&crtc->base, &lcdc_crtc_helper_funcs);
+       drm_crtc_vblank_reset(&crtc->base);
  
        dc->crtc = &crtc->base;
  
index 0b475fae067d1997f95dbcd921762be3373448fb,9dcc7280e5720255baed2786ab7d8fc11554c845..cf27b6b605d8403270d348378e5720680852f24a
@@@ -89,7 -89,7 +89,7 @@@ get_current_crtc_for_encoder(struct drm
  
        WARN_ON(!drm_modeset_is_locked(&config->connection_mutex));
  
 -      list_for_each_entry(connector, &config->connector_list, head) {
 +      drm_for_each_connector(connector, dev) {
                if (connector->state->best_encoder != encoder)
                        continue;
  
@@@ -124,7 -124,7 +124,7 @@@ steal_encoder(struct drm_atomic_state *
        if (IS_ERR(crtc_state))
                return PTR_ERR(crtc_state);
  
 -      crtc_state->mode_changed = true;
 +      crtc_state->connectors_changed = true;
  
        list_for_each_entry(connector, &config->connector_list, head) {
                if (connector->state->best_encoder != encoder)
@@@ -174,14 -174,14 +174,14 @@@ update_connector_routing(struct drm_ato
                        idx = drm_crtc_index(connector->state->crtc);
  
                        crtc_state = state->crtc_states[idx];
 -                      crtc_state->mode_changed = true;
 +                      crtc_state->connectors_changed = true;
                }
  
                if (connector_state->crtc) {
                        idx = drm_crtc_index(connector_state->crtc);
  
                        crtc_state = state->crtc_states[idx];
 -                      crtc_state->mode_changed = true;
 +                      crtc_state->connectors_changed = true;
                }
        }
  
        }
  
        funcs = connector->helper_private;
-       new_encoder = funcs->best_encoder(connector);
+       if (funcs->atomic_best_encoder)
+               new_encoder = funcs->atomic_best_encoder(connector,
+                                                        connector_state);
+       else
+               new_encoder = funcs->best_encoder(connector);
  
        if (!new_encoder) {
                DRM_DEBUG_ATOMIC("No suitable encoder found for [CONNECTOR:%d:%s]\n",
                }
        }
  
+       if (WARN_ON(!connector_state->crtc))
+               return -EINVAL;
        connector_state->best_encoder = new_encoder;
        idx = drm_crtc_index(connector_state->crtc);
  
        crtc_state = state->crtc_states[idx];
 -      crtc_state->mode_changed = true;
 +      crtc_state->connectors_changed = true;
  
        DRM_DEBUG_ATOMIC("[CONNECTOR:%d:%s] using [ENCODER:%d:%s] on [CRTC:%d]\n",
                         connector->base.id,
@@@ -256,8 -264,7 +264,8 @@@ mode_fixup(struct drm_atomic_state *sta
        bool ret;
  
        for_each_crtc_in_state(state, crtc, crtc_state, i) {
 -              if (!crtc_state->mode_changed)
 +              if (!crtc_state->mode_changed &&
 +                  !crtc_state->connectors_changed)
                        continue;
  
                drm_mode_copy(&crtc_state->adjusted_mode, &crtc_state->mode);
        for_each_crtc_in_state(state, crtc, crtc_state, i) {
                const struct drm_crtc_helper_funcs *funcs;
  
 -              if (!crtc_state->mode_changed)
 +              if (!crtc_state->mode_changed &&
 +                  !crtc_state->connectors_changed)
                        continue;
  
                funcs = crtc->helper_private;
   *
   * Check the state object to see if the requested state is physically possible.
   * This does all the crtc and connector related computations for an atomic
 - * update. It computes and updates crtc_state->mode_changed, adds any additional
 - * connectors needed for full modesets and calls down into ->mode_fixup
 - * functions of the driver backend.
 + * update and adds any additional connectors needed for full modesets and calls
 + * down into ->mode_fixup functions of the driver backend.
 + *
 + * crtc_state->mode_changed is set when the input mode is changed.
 + * crtc_state->connectors_changed is set when a connector is added or
 + * removed from the crtc.
 + * crtc_state->active_changed is set when crtc_state->active changes,
 + * which is used for dpms.
   *
   * IMPORTANT:
   *
@@@ -380,17 -381,7 +388,17 @@@ drm_atomic_helper_check_modeset(struct 
                if (crtc->state->enable != crtc_state->enable) {
                        DRM_DEBUG_ATOMIC("[CRTC:%d] enable changed\n",
                                         crtc->base.id);
 +
 +                      /*
 +                       * For clarity this assignment is done here, but
 +                       * enable == 0 is only true when there are no
 +                       * connectors and a NULL mode.
 +                       *
 +                       * The other way around is true as well. enable != 0
 +                       * iff connectors are attached and a mode is set.
 +                       */
                        crtc_state->mode_changed = true;
 +                      crtc_state->connectors_changed = true;
                }
        }
  
@@@ -465,9 -456,6 +473,9 @@@ EXPORT_SYMBOL(drm_atomic_helper_check_m
   * This does all the plane update related checks using by calling into the
   * ->atomic_check hooks provided by the driver.
   *
 + * It also sets crtc_state->planes_changed to indicate that a crtc has
 + * updated planes.
 + *
   * RETURNS
   * Zero for success or -errno
   */
@@@ -660,29 -648,15 +668,29 @@@ drm_atomic_helper_update_legacy_modeset
        struct drm_crtc_state *old_crtc_state;
        int i;
  
 -      /* clear out existing links */
 +      /* clear out existing links and update dpms */
        for_each_connector_in_state(old_state, connector, old_conn_state, i) {
 -              if (!connector->encoder)
 -                      continue;
 +              if (connector->encoder) {
 +                      WARN_ON(!connector->encoder->crtc);
  
 -              WARN_ON(!connector->encoder->crtc);
 +                      connector->encoder->crtc = NULL;
 +                      connector->encoder = NULL;
 +              }
  
 -              connector->encoder->crtc = NULL;
 -              connector->encoder = NULL;
 +              crtc = connector->state->crtc;
 +              if ((!crtc && old_conn_state->crtc) ||
 +                  (crtc && drm_atomic_crtc_needs_modeset(crtc->state))) {
 +                      struct drm_property *dpms_prop =
 +                              dev->mode_config.dpms_property;
 +                      int mode = DRM_MODE_DPMS_OFF;
 +
 +                      if (crtc && crtc->state->active)
 +                              mode = DRM_MODE_DPMS_ON;
 +
 +                      connector->dpms = mode;
 +                      drm_object_property_set_value(&connector->base,
 +                                                    dpms_prop, mode);
 +              }
        }
  
        /* set new links */
  
        /* set legacy state in the crtc structure */
        for_each_crtc_in_state(old_state, crtc, old_crtc_state, i) {
 +              struct drm_plane *primary = crtc->primary;
 +
                crtc->mode = crtc->state->mode;
                crtc->enabled = crtc->state->enable;
 -              crtc->x = crtc->primary->state->src_x >> 16;
 -              crtc->y = crtc->primary->state->src_y >> 16;
 +
 +              if (drm_atomic_get_existing_plane_state(old_state, primary) &&
 +                  primary->state->crtc == crtc) {
 +                      crtc->x = primary->state->src_x >> 16;
 +                      crtc->y = primary->state->src_y >> 16;
 +              }
  
                if (crtc->state->enable)
                        drm_calc_timestamping_constants(crtc,
@@@ -1178,7 -1146,7 +1186,7 @@@ void drm_atomic_helper_commit_planes(st
                if (!funcs || !funcs->atomic_begin)
                        continue;
  
 -              funcs->atomic_begin(crtc);
 +              funcs->atomic_begin(crtc, old_crtc_state);
        }
  
        for_each_plane_in_state(old_state, plane, old_plane_state, i) {
                if (!funcs || !funcs->atomic_flush)
                        continue;
  
 -              funcs->atomic_flush(crtc);
 +              funcs->atomic_flush(crtc, old_crtc_state);
        }
  }
  EXPORT_SYMBOL(drm_atomic_helper_commit_planes);
@@@ -1244,7 -1212,7 +1252,7 @@@ drm_atomic_helper_commit_planes_on_crtc
  
        crtc_funcs = crtc->helper_private;
        if (crtc_funcs && crtc_funcs->atomic_begin)
 -              crtc_funcs->atomic_begin(crtc);
 +              crtc_funcs->atomic_begin(crtc, old_crtc_state);
  
        drm_for_each_plane_mask(plane, crtc->dev, plane_mask) {
                struct drm_plane_state *old_plane_state =
        }
  
        if (crtc_funcs && crtc_funcs->atomic_flush)
 -              crtc_funcs->atomic_flush(crtc);
 +              crtc_funcs->atomic_flush(crtc, old_crtc_state);
  }
  EXPORT_SYMBOL(drm_atomic_helper_commit_planes_on_crtc);
  
@@@ -1955,6 -1923,10 +1963,6 @@@ retry
        if (ret != 0)
                goto fail;
  
 -      /* TODO: ->page_flip is the only driver callback where the core
 -       * doesn't update plane->fb. For now patch it up here. */
 -      plane->fb = plane->state->fb;
 -
        /* Driver takes ownership of state on successful async commit. */
        return 0;
  fail:
@@@ -1988,12 -1960,9 +1996,12 @@@ EXPORT_SYMBOL(drm_atomic_helper_page_fl
   * implementing the legacy DPMS connector interface. It computes the new desired
   * ->active state for the corresponding CRTC (if the connector is enabled) and
   *  updates it.
 + *
 + * Returns:
 + * Returns 0 on success, negative errno numbers on failure.
   */
 -void drm_atomic_helper_connector_dpms(struct drm_connector *connector,
 -                                    int mode)
 +int drm_atomic_helper_connector_dpms(struct drm_connector *connector,
 +                                   int mode)
  {
        struct drm_mode_config *config = &connector->dev->mode_config;
        struct drm_atomic_state *state;
        struct drm_connector *tmp_connector;
        int ret;
        bool active = false;
 +      int old_mode = connector->dpms;
  
        if (mode != DRM_MODE_DPMS_ON)
                mode = DRM_MODE_DPMS_OFF;
        crtc = connector->state->crtc;
  
        if (!crtc)
 -              return;
 +              return 0;
  
 -      /* FIXME: ->dpms has no return value so can't forward the -ENOMEM. */
        state = drm_atomic_state_alloc(connector->dev);
        if (!state)
 -              return;
 +              return -ENOMEM;
  
        state->acquire_ctx = drm_modeset_legacy_acquire_ctx(crtc);
  retry:
        crtc_state = drm_atomic_get_crtc_state(state, crtc);
 -      if (IS_ERR(crtc_state))
 -              return;
 +      if (IS_ERR(crtc_state)) {
 +              ret = PTR_ERR(crtc_state);
 +              goto fail;
 +      }
  
        WARN_ON(!drm_modeset_is_locked(&config->connection_mutex));
  
 -      list_for_each_entry(tmp_connector, &config->connector_list, head) {
 +      drm_for_each_connector(tmp_connector, connector->dev) {
                if (tmp_connector->state->crtc != crtc)
                        continue;
  
        if (ret != 0)
                goto fail;
  
 -      /* Driver takes ownership of state on successful async commit. */
 -      return;
 +      /* Driver takes ownership of state on successful commit. */
 +      return 0;
  fail:
        if (ret == -EDEADLK)
                goto backoff;
  
 +      connector->dpms = old_mode;
        drm_atomic_state_free(state);
  
 -      WARN(1, "Driver bug: Changing ->active failed with ret=%i\n", ret);
 -
 -      return;
 +      return ret;
  backoff:
        drm_atomic_state_clear(state);
        drm_atomic_legacy_backoff(state);
@@@ -2112,7 -2080,6 +2120,7 @@@ void __drm_atomic_helper_crtc_duplicate
        state->mode_changed = false;
        state->active_changed = false;
        state->planes_changed = false;
 +      state->connectors_changed = false;
        state->event = NULL;
  }
  EXPORT_SYMBOL(__drm_atomic_helper_crtc_duplicate_state);
index dfac394d060207d66121400211f580ff86d7e5cf,fed748311b928cc534f781505a37686ec7a46ba3..ca077657604edb7e9acb6a33785ee2b9b092b1c8
@@@ -615,7 -615,7 +615,7 @@@ void drm_framebuffer_remove(struct drm_
        if (atomic_read(&fb->refcount.refcount) > 1) {
                drm_modeset_lock_all(dev);
                /* remove from any CRTC */
 -              list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
 +              drm_for_each_crtc(crtc, dev) {
                        if (crtc->primary->fb == fb) {
                                /* should turn off the crtc */
                                memset(&set, 0, sizeof(struct drm_mode_set));
                        }
                }
  
 -              list_for_each_entry(plane, &dev->mode_config.plane_list, head) {
 +              drm_for_each_plane(plane, dev) {
                        if (plane->fb == fb)
                                drm_plane_force_disable(plane);
                }
@@@ -736,7 -736,7 +736,7 @@@ unsigned int drm_crtc_index(struct drm_
        unsigned int index = 0;
        struct drm_crtc *tmp;
  
 -      list_for_each_entry(tmp, &crtc->dev->mode_config.crtc_list, head) {
 +      drm_for_each_crtc(tmp, crtc->dev) {
                if (tmp == crtc)
                        return index;
  
@@@ -988,7 -988,7 +988,7 @@@ unsigned int drm_connector_index(struc
  
        WARN_ON(!drm_modeset_is_locked(&config->connection_mutex));
  
 -      list_for_each_entry(tmp, &connector->dev->mode_config.connector_list, head) {
 +      drm_for_each_connector(tmp, connector->dev) {
                if (tmp == connector)
                        return index;
  
@@@ -1054,7 -1054,7 +1054,7 @@@ void drm_connector_unplug_all(struct dr
  {
        struct drm_connector *connector;
  
 -      /* taking the mode config mutex ends up in a clash with sysfs */
 +      /* FIXME: taking the mode config mutex ends up in a clash with sysfs */
        list_for_each_entry(connector, &dev->mode_config.connector_list, head)
                drm_connector_unregister(connector);
  
@@@ -1280,7 -1280,7 +1280,7 @@@ unsigned int drm_plane_index(struct drm
        unsigned int index = 0;
        struct drm_plane *tmp;
  
 -      list_for_each_entry(tmp, &plane->dev->mode_config.plane_list, head) {
 +      drm_for_each_plane(tmp, plane->dev) {
                if (tmp == plane)
                        return index;
  
@@@ -1305,7 -1305,7 +1305,7 @@@ drm_plane_from_index(struct drm_device 
        struct drm_plane *plane;
        unsigned int i = 0;
  
 -      list_for_each_entry(plane, &dev->mode_config.plane_list, head) {
 +      drm_for_each_plane(plane, dev) {
                if (i == idx)
                        return plane;
                i++;
@@@ -1679,6 -1679,70 +1679,6 @@@ int drm_mode_create_suggested_offset_pr
  }
  EXPORT_SYMBOL(drm_mode_create_suggested_offset_properties);
  
 -static int drm_mode_group_init(struct drm_device *dev, struct drm_mode_group *group)
 -{
 -      uint32_t total_objects = 0;
 -
 -      total_objects += dev->mode_config.num_crtc;
 -      total_objects += dev->mode_config.num_connector;
 -      total_objects += dev->mode_config.num_encoder;
 -
 -      group->id_list = kcalloc(total_objects, sizeof(uint32_t), GFP_KERNEL);
 -      if (!group->id_list)
 -              return -ENOMEM;
 -
 -      group->num_crtcs = 0;
 -      group->num_connectors = 0;
 -      group->num_encoders = 0;
 -      return 0;
 -}
 -
 -void drm_mode_group_destroy(struct drm_mode_group *group)
 -{
 -      kfree(group->id_list);
 -      group->id_list = NULL;
 -}
 -
 -/*
 - * NOTE: Driver's shouldn't ever call drm_mode_group_init_legacy_group - it is
 - * the drm core's responsibility to set up mode control groups.
 - */
 -int drm_mode_group_init_legacy_group(struct drm_device *dev,
 -                                   struct drm_mode_group *group)
 -{
 -      struct drm_crtc *crtc;
 -      struct drm_encoder *encoder;
 -      struct drm_connector *connector;
 -      int ret;
 -
 -      ret = drm_mode_group_init(dev, group);
 -      if (ret)
 -              return ret;
 -
 -      list_for_each_entry(crtc, &dev->mode_config.crtc_list, head)
 -              group->id_list[group->num_crtcs++] = crtc->base.id;
 -
 -      list_for_each_entry(encoder, &dev->mode_config.encoder_list, head)
 -              group->id_list[group->num_crtcs + group->num_encoders++] =
 -              encoder->base.id;
 -
 -      list_for_each_entry(connector, &dev->mode_config.connector_list, head)
 -              group->id_list[group->num_crtcs + group->num_encoders +
 -                             group->num_connectors++] = connector->base.id;
 -
 -      return 0;
 -}
 -EXPORT_SYMBOL(drm_mode_group_init_legacy_group);
 -
 -void drm_reinit_primary_mode_group(struct drm_device *dev)
 -{
 -      drm_modeset_lock_all(dev);
 -      drm_mode_group_destroy(&dev->primary->mode_group);
 -      drm_mode_group_init_legacy_group(dev, &dev->primary->mode_group);
 -      drm_modeset_unlock_all(dev);
 -}
 -EXPORT_SYMBOL(drm_reinit_primary_mode_group);
 -
  /**
   * drm_mode_getresources - get graphics configuration
   * @dev: drm device for the ioctl
@@@ -1707,11 -1771,12 +1707,11 @@@ int drm_mode_getresources(struct drm_de
        int crtc_count = 0;
        int fb_count = 0;
        int encoder_count = 0;
 -      int copied = 0, i;
 +      int copied = 0;
        uint32_t __user *fb_id;
        uint32_t __user *crtc_id;
        uint32_t __user *connector_id;
        uint32_t __user *encoder_id;
 -      struct drm_mode_group *mode_group;
  
        if (!drm_core_check_feature(dev, DRIVER_MODESET))
                return -EINVAL;
        /* mode_config.mutex protects the connector list against e.g. DP MST
         * connector hot-adding. CRTC/Plane lists are invariant. */
        mutex_lock(&dev->mode_config.mutex);
 -      if (!drm_is_primary_client(file_priv)) {
 -
 -              mode_group = NULL;
 -              list_for_each(lh, &dev->mode_config.crtc_list)
 -                      crtc_count++;
 -
 -              list_for_each(lh, &dev->mode_config.connector_list)
 -                      connector_count++;
 +      drm_for_each_crtc(crtc, dev)
 +              crtc_count++;
  
 -              list_for_each(lh, &dev->mode_config.encoder_list)
 -                      encoder_count++;
 -      } else {
 +      drm_for_each_connector(connector, dev)
 +              connector_count++;
  
 -              mode_group = &file_priv->master->minor->mode_group;
 -              crtc_count = mode_group->num_crtcs;
 -              connector_count = mode_group->num_connectors;
 -              encoder_count = mode_group->num_encoders;
 -      }
 +      drm_for_each_encoder(encoder, dev)
 +              encoder_count++;
  
        card_res->max_height = dev->mode_config.max_height;
        card_res->min_height = dev->mode_config.min_height;
        if (card_res->count_crtcs >= crtc_count) {
                copied = 0;
                crtc_id = (uint32_t __user *)(unsigned long)card_res->crtc_id_ptr;
 -              if (!mode_group) {
 -                      list_for_each_entry(crtc, &dev->mode_config.crtc_list,
 -                                          head) {
 -                              DRM_DEBUG_KMS("[CRTC:%d]\n", crtc->base.id);
 -                              if (put_user(crtc->base.id, crtc_id + copied)) {
 -                                      ret = -EFAULT;
 -                                      goto out;
 -                              }
 -                              copied++;
 -                      }
 -              } else {
 -                      for (i = 0; i < mode_group->num_crtcs; i++) {
 -                              if (put_user(mode_group->id_list[i],
 -                                           crtc_id + copied)) {
 -                                      ret = -EFAULT;
 -                                      goto out;
 -                              }
 -                              copied++;
 +              drm_for_each_crtc(crtc, dev) {
 +                      DRM_DEBUG_KMS("[CRTC:%d]\n", crtc->base.id);
 +                      if (put_user(crtc->base.id, crtc_id + copied)) {
 +                              ret = -EFAULT;
 +                              goto out;
                        }
 +                      copied++;
                }
        }
        card_res->count_crtcs = crtc_count;
        if (card_res->count_encoders >= encoder_count) {
                copied = 0;
                encoder_id = (uint32_t __user *)(unsigned long)card_res->encoder_id_ptr;
 -              if (!mode_group) {
 -                      list_for_each_entry(encoder,
 -                                          &dev->mode_config.encoder_list,
 -                                          head) {
 -                              DRM_DEBUG_KMS("[ENCODER:%d:%s]\n", encoder->base.id,
 -                                              encoder->name);
 -                              if (put_user(encoder->base.id, encoder_id +
 -                                           copied)) {
 -                                      ret = -EFAULT;
 -                                      goto out;
 -                              }
 -                              copied++;
 -                      }
 -              } else {
 -                      for (i = mode_group->num_crtcs; i < mode_group->num_crtcs + mode_group->num_encoders; i++) {
 -                              if (put_user(mode_group->id_list[i],
 -                                           encoder_id + copied)) {
 -                                      ret = -EFAULT;
 -                                      goto out;
 -                              }
 -                              copied++;
 +              drm_for_each_encoder(encoder, dev) {
 +                      DRM_DEBUG_KMS("[ENCODER:%d:%s]\n", encoder->base.id,
 +                                      encoder->name);
 +                      if (put_user(encoder->base.id, encoder_id +
 +                                   copied)) {
 +                              ret = -EFAULT;
 +                              goto out;
                        }
 -
 +                      copied++;
                }
        }
        card_res->count_encoders = encoder_count;
        if (card_res->count_connectors >= connector_count) {
                copied = 0;
                connector_id = (uint32_t __user *)(unsigned long)card_res->connector_id_ptr;
 -              if (!mode_group) {
 -                      list_for_each_entry(connector,
 -                                          &dev->mode_config.connector_list,
 -                                          head) {
 -                              DRM_DEBUG_KMS("[CONNECTOR:%d:%s]\n",
 -                                      connector->base.id,
 -                                      connector->name);
 -                              if (put_user(connector->base.id,
 -                                           connector_id + copied)) {
 -                                      ret = -EFAULT;
 -                                      goto out;
 -                              }
 -                              copied++;
 -                      }
 -              } else {
 -                      int start = mode_group->num_crtcs +
 -                              mode_group->num_encoders;
 -                      for (i = start; i < start + mode_group->num_connectors; i++) {
 -                              if (put_user(mode_group->id_list[i],
 -                                           connector_id + copied)) {
 -                                      ret = -EFAULT;
 -                                      goto out;
 -                              }
 -                              copied++;
 +              drm_for_each_connector(connector, dev) {
 +                      DRM_DEBUG_KMS("[CONNECTOR:%d:%s]\n",
 +                              connector->base.id,
 +                              connector->name);
 +                      if (put_user(connector->base.id,
 +                                   connector_id + copied)) {
 +                              ret = -EFAULT;
 +                              goto out;
                        }
 +                      copied++;
                }
        }
        card_res->count_connectors = connector_count;
@@@ -2071,7 -2187,7 +2071,7 @@@ static struct drm_crtc *drm_encoder_get
  
        /* For atomic drivers only state objects are synchronously updated and
         * protected by modeset locks, so check those first. */
 -      list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
 +      drm_for_each_connector(connector, dev) {
                if (!connector->state)
                        continue;
  
@@@ -2175,7 -2291,7 +2175,7 @@@ int drm_mode_getplane_res(struct drm_de
                plane_ptr = (uint32_t __user *)(unsigned long)plane_resp->plane_id_ptr;
  
                /* Plane lists are invariant, no locking needed. */
 -              list_for_each_entry(plane, &config->plane_list, head) {
 +              drm_for_each_plane(plane, dev) {
                        /*
                         * Unless userspace set the 'universal planes'
                         * capability bit, only advertise overlays.
@@@ -2480,7 -2596,7 +2480,7 @@@ int drm_mode_set_config_internal(struc
         * connectors from it), hence we need to refcount the fbs across all
         * crtcs. Atomic modeset will have saner semantics ...
         */
 -      list_for_each_entry(tmp, &crtc->dev->mode_config.crtc_list, head)
 +      drm_for_each_crtc(tmp, crtc->dev)
                tmp->primary->old_fb = tmp->primary->fb;
  
        fb = set->fb;
                crtc->primary->fb = fb;
        }
  
 -      list_for_each_entry(tmp, &crtc->dev->mode_config.crtc_list, head) {
 +      drm_for_each_crtc(tmp, crtc->dev) {
                if (tmp->primary->fb)
                        drm_framebuffer_reference(tmp->primary->fb);
                if (tmp->primary->old_fb)
@@@ -4185,6 -4301,7 +4185,6 @@@ void drm_property_unreference_blob(stru
                mutex_unlock(&dev->mode_config.blob_lock);
        else
                might_lock(&dev->mode_config.blob_lock);
 -
  }
  EXPORT_SYMBOL(drm_property_unreference_blob);
  
@@@ -4355,7 -4472,9 +4355,7 @@@ static int drm_property_replace_global_
                        goto err_created;
        }
  
 -      if (old_blob)
 -              drm_property_unreference_blob(old_blob);
 -
 +      drm_property_unreference_blob(old_blob);
        *replace = new_blob;
  
        return 0;
@@@ -4753,9 -4872,9 +4753,9 @@@ static int drm_mode_connector_set_obj_p
  
        /* Do DPMS ourselves */
        if (property == connector->dev->mode_config.dpms_property) {
 -              if (connector->funcs->dpms)
 -                      (*connector->funcs->dpms)(connector, (int)value);
                ret = 0;
 +              if (connector->funcs->dpms)
 +                      ret = (*connector->funcs->dpms)(connector, (int)value);
        } else if (connector->funcs->set_property)
                ret = connector->funcs->set_property(connector, property, value);
  
@@@ -5230,7 -5349,13 +5230,7 @@@ int drm_mode_page_flip_ioctl(struct drm
                /* Keep the old fb, don't unref it. */
                crtc->primary->old_fb = NULL;
        } else {
 -              /*
 -               * Warn if the driver hasn't properly updated the crtc->fb
 -               * field to reflect that the new framebuffer is now used.
 -               * Failing to do so will screw with the reference counting
 -               * on framebuffers.
 -               */
 -              WARN_ON(crtc->primary->fb != fb);
 +              crtc->primary->fb = fb;
                /* Unref only the old framebuffer. */
                fb = NULL;
        }
@@@ -5261,24 -5386,21 +5261,21 @@@ void drm_mode_config_reset(struct drm_d
        struct drm_encoder *encoder;
        struct drm_connector *connector;
  
 -      list_for_each_entry(plane, &dev->mode_config.plane_list, head)
 +      drm_for_each_plane(plane, dev)
                if (plane->funcs->reset)
                        plane->funcs->reset(plane);
  
 -      list_for_each_entry(crtc, &dev->mode_config.crtc_list, head)
 +      drm_for_each_crtc(crtc, dev)
                if (crtc->funcs->reset)
                        crtc->funcs->reset(crtc);
  
 -      list_for_each_entry(encoder, &dev->mode_config.encoder_list, head)
 +      drm_for_each_encoder(encoder, dev)
                if (encoder->funcs->reset)
                        encoder->funcs->reset(encoder);
  
-       drm_for_each_connector(connector, dev) {
-               connector->status = connector_status_unknown;
 -      list_for_each_entry(connector, &dev->mode_config.connector_list, head)
++      drm_for_each_connector(connector, dev)
                if (connector->funcs->reset)
                        connector->funcs->reset(connector);
-       }
  }
  EXPORT_SYMBOL(drm_mode_config_reset);
  
index 9fd784b8966b9743ff29ce5fa3defbf92b292caf,b50fa0afd9071f6c64c36de23253a2ee22ce7480..ee14324522cece2b9316860be6955287caa5ffe1
@@@ -75,7 -75,7 +75,7 @@@ module_param_named(timestamp_precision_
  module_param_named(timestamp_monotonic, drm_timestamp_monotonic, int, 0600);
  
  static void store_vblank(struct drm_device *dev, int crtc,
-                        unsigned vblank_count_inc,
+                        u32 vblank_count_inc,
                         struct timeval *t_vblank)
  {
        struct drm_vblank_crtc *vblank = &dev->vblank[crtc];
@@@ -1267,7 -1267,7 +1267,7 @@@ EXPORT_SYMBOL(drm_crtc_vblank_off)
  
  /**
   * drm_crtc_vblank_reset - reset vblank state to off on a CRTC
 - * @crtc: CRTC in question
 + * @drm_crtc: CRTC in question
   *
   * Drivers can use this function to reset the vblank state to off at load time.
   * Drivers should use this together with the drm_crtc_vblank_off() and
index 5283db90477cbdff59d13ef31c6335946fded9d9,fd1de451c8c6bae13f42eaae5e9cfe572039ea18..01abe13e98e010066576c9173e8cd200ebde0268
@@@ -56,7 -56,7 +56,7 @@@
  
  #define DRIVER_NAME           "i915"
  #define DRIVER_DESC           "Intel Graphics"
 -#define DRIVER_DATE           "20150522"
 +#define DRIVER_DATE           "20150731"
  
  #undef WARN_ON
  /* Many gcc seem to no see through this and fall over :( */
@@@ -206,50 -206,17 +206,50 @@@ enum intel_display_power_domain 
  
  enum hpd_pin {
        HPD_NONE = 0,
 -      HPD_PORT_A = HPD_NONE, /* PORT_A is internal */
        HPD_TV = HPD_NONE,     /* TV is known to be unreliable */
        HPD_CRT,
        HPD_SDVO_B,
        HPD_SDVO_C,
 +      HPD_PORT_A,
        HPD_PORT_B,
        HPD_PORT_C,
        HPD_PORT_D,
        HPD_NUM_PINS
  };
  
 +#define for_each_hpd_pin(__pin) \
 +      for ((__pin) = (HPD_NONE + 1); (__pin) < HPD_NUM_PINS; (__pin)++)
 +
 +struct i915_hotplug {
 +      struct work_struct hotplug_work;
 +
 +      struct {
 +              unsigned long last_jiffies;
 +              int count;
 +              enum {
 +                      HPD_ENABLED = 0,
 +                      HPD_DISABLED = 1,
 +                      HPD_MARK_DISABLED = 2
 +              } state;
 +      } stats[HPD_NUM_PINS];
 +      u32 event_bits;
 +      struct delayed_work reenable_work;
 +
 +      struct intel_digital_port *irq_port[I915_MAX_PORTS];
 +      u32 long_port_mask;
 +      u32 short_port_mask;
 +      struct work_struct dig_port_work;
 +
 +      /*
 +       * if we get a HPD irq from DP and a HPD irq from non-DP
 +       * the non-DP HPD could block the workqueue on a mode config
 +       * mutex getting, that userspace may have taken. However
 +       * userspace is waiting on the DP workqueue to run which is
 +       * blocked behind the non-DP one.
 +       */
 +      struct workqueue_struct *dp_wq;
 +};
 +
  #define I915_GEM_GPU_DOMAINS \
        (I915_GEM_DOMAIN_RENDER | \
         I915_GEM_DOMAIN_SAMPLER | \
                            &dev->mode_config.plane_list,       \
                            base.head)
  
 +#define for_each_intel_plane_on_crtc(dev, intel_crtc, intel_plane)    \
 +      list_for_each_entry(intel_plane,                                \
 +                          &(dev)->mode_config.plane_list,             \
 +                          base.head)                                  \
 +              if ((intel_plane)->pipe == (intel_crtc)->pipe)
 +
  #define for_each_intel_crtc(dev, intel_crtc) \
        list_for_each_entry(intel_crtc, &dev->mode_config.crtc_list, base.head)
  
@@@ -372,8 -333,7 +372,8 @@@ struct intel_dpll_hw_state 
        uint32_t cfgcr1, cfgcr2;
  
        /* bxt */
 -      uint32_t ebb0, pll0, pll1, pll2, pll3, pll6, pll8, pll10, pcsdw12;
 +      uint32_t ebb0, ebb4, pll0, pll1, pll2, pll3, pll6, pll8, pll9, pll10,
 +               pcsdw12;
  };
  
  struct intel_shared_dpll_config {
  
  struct intel_shared_dpll {
        struct intel_shared_dpll_config config;
 -      struct intel_shared_dpll_config *new_config;
  
        int active; /* count of number of active CRTCs (i.e. DPMS on) */
        bool on; /* is the PLL actually active? Disabled during modeset */
@@@ -484,7 -445,6 +484,7 @@@ struct drm_i915_error_state 
        struct timeval time;
  
        char error_msg[128];
 +      int iommu;
        u32 reset_count;
        u32 suspend_count;
  
@@@ -599,6 -559,9 +599,6 @@@ struct intel_limit
  struct dpll;
  
  struct drm_i915_display_funcs {
 -      bool (*fbc_enabled)(struct drm_device *dev);
 -      void (*enable_fbc)(struct drm_crtc *crtc);
 -      void (*disable_fbc)(struct drm_device *dev);
        int (*get_display_clock_speed)(struct drm_device *dev);
        int (*get_fifo_size)(struct drm_device *dev, int plane);
        /**
                                 struct drm_crtc *crtc,
                                 uint32_t sprite_width, uint32_t sprite_height,
                                 int pixel_size, bool enable, bool scaled);
 -      void (*modeset_global_resources)(struct drm_atomic_state *state);
 +      int (*modeset_calc_cdclk)(struct drm_atomic_state *state);
 +      void (*modeset_commit_cdclk)(struct drm_atomic_state *state);
        /* Returns the active state of the crtc, and if the crtc is active,
         * fills out the pipe-config with the hw state. */
        bool (*get_pipe_config)(struct intel_crtc *,
                                  struct intel_crtc_state *crtc_state);
        void (*crtc_enable)(struct drm_crtc *crtc);
        void (*crtc_disable)(struct drm_crtc *crtc);
 -      void (*off)(struct drm_crtc *crtc);
        void (*audio_codec_enable)(struct drm_connector *connector,
                                   struct intel_encoder *encoder,
                                   struct drm_display_mode *mode);
        int (*queue_flip)(struct drm_device *dev, struct drm_crtc *crtc,
                          struct drm_framebuffer *fb,
                          struct drm_i915_gem_object *obj,
 -                        struct intel_engine_cs *ring,
 +                        struct drm_i915_gem_request *req,
                          uint32_t flags);
        void (*update_primary_plane)(struct drm_crtc *crtc,
                                     struct drm_framebuffer *fb,
@@@ -743,7 -706,7 +743,7 @@@ enum csr_state 
  
  struct intel_csr {
        const char *fw_path;
 -      __be32 *dmc_payload;
 +      uint32_t *dmc_payload;
        uint32_t dmc_fw_size;
        uint32_t mmio_count;
        uint32_t mmioaddr[8];
@@@ -842,15 -805,11 +842,15 @@@ struct i915_ctx_hang_stats 
  
  /* This must match up with the value previously used for execbuf2.rsvd1. */
  #define DEFAULT_CONTEXT_HANDLE 0
 +
 +#define CONTEXT_NO_ZEROMAP (1<<0)
  /**
   * struct intel_context - as the name implies, represents a context.
   * @ref: reference count.
   * @user_handle: userspace tracking identity for this context.
   * @remap_slice: l3 row remapping information.
 + * @flags: context specific flags:
 + *         CONTEXT_NO_ZEROMAP: do not allow mapping things to page 0.
   * @file_priv: filp associated with this context (NULL for global default
   *           context).
   * @hang_stats: information about the role of this context in possible GPU
@@@ -868,7 -827,6 +868,7 @@@ struct intel_context 
        int user_handle;
        uint8_t remap_slice;
        struct drm_i915_private *i915;
 +      int flags;
        struct drm_i915_file_private *file_priv;
        struct i915_ctx_hang_stats hang_stats;
        struct i915_hw_ppgtt *ppgtt;
@@@ -895,13 -853,9 +895,13 @@@ enum fb_op_origin 
        ORIGIN_CPU,
        ORIGIN_CS,
        ORIGIN_FLIP,
 +      ORIGIN_DIRTYFB,
  };
  
  struct i915_fbc {
 +      /* This is always the inner lock when overlapping with struct_mutex and
 +       * it's the outer lock when overlapping with stolen_lock. */
 +      struct mutex lock;
        unsigned long uncompressed_size;
        unsigned threshold;
        unsigned int fb_id;
  
        struct intel_fbc_work {
                struct delayed_work work;
 -              struct drm_crtc *crtc;
 +              struct intel_crtc *crtc;
                struct drm_framebuffer *fb;
        } *fbc_work;
  
                FBC_MULTIPLE_PIPES, /* more than one pipe active */
                FBC_MODULE_PARAM,
                FBC_CHIP_DEFAULT, /* disabled by default on this chip */
 +              FBC_ROTATION, /* rotation is not supported */
 +              FBC_IN_DBG_MASTER, /* kernel debugger is active */
        } no_fbc_reason;
 +
 +      bool (*fbc_enabled)(struct drm_i915_private *dev_priv);
 +      void (*enable_fbc)(struct intel_crtc *crtc);
 +      void (*disable_fbc)(struct drm_i915_private *dev_priv);
  };
  
  /**
@@@ -1253,10 -1201,6 +1253,10 @@@ struct intel_l3_parity 
  struct i915_gem_mm {
        /** Memory allocator for GTT stolen memory */
        struct drm_mm stolen;
 +      /** Protects the usage of the GTT stolen memory allocator. This is
 +       * always the inner lock when overlapping with struct_mutex. */
 +      struct mutex stolen_lock;
 +
        /** List of all objects in gtt_space. Used to restore gtt
         * mappings on resume */
        struct list_head bound_list;
@@@ -1410,11 -1354,6 +1410,11 @@@ enum modeset_restore 
        MODESET_SUSPENDED,
  };
  
 +#define DP_AUX_A 0x40
 +#define DP_AUX_B 0x10
 +#define DP_AUX_C 0x20
 +#define DP_AUX_D 0x30
 +
  struct ddi_vbt_port_info {
        /*
         * This is an index in the HDMI/DVI DDI buffer translation table.
        uint8_t supports_dvi:1;
        uint8_t supports_hdmi:1;
        uint8_t supports_dp:1;
 +
 +      uint8_t alternate_aux_channel;
  };
  
  enum psr_lines_to_wait {
@@@ -1524,27 -1461,23 +1524,27 @@@ struct ilk_wm_values 
        enum intel_ddb_partitioning partitioning;
  };
  
 -struct vlv_wm_values {
 -      struct {
 -              uint16_t primary;
 -              uint16_t sprite[2];
 -              uint8_t cursor;
 -      } pipe[3];
 +struct vlv_pipe_wm {
 +      uint16_t primary;
 +      uint16_t sprite[2];
 +      uint8_t cursor;
 +};
  
 -      struct {
 -              uint16_t plane;
 -              uint8_t cursor;
 -      } sr;
 +struct vlv_sr_wm {
 +      uint16_t plane;
 +      uint8_t cursor;
 +};
  
 +struct vlv_wm_values {
 +      struct vlv_pipe_wm pipe[3];
 +      struct vlv_sr_wm sr;
        struct {
                uint8_t cursor;
                uint8_t sprite[2];
                uint8_t primary;
        } ddl[3];
 +      uint8_t level;
 +      bool cxsr;
  };
  
  struct skl_ddb_entry {
@@@ -1678,18 -1611,6 +1678,18 @@@ struct i915_virtual_gpu 
        bool active;
  };
  
 +struct i915_execbuffer_params {
 +      struct drm_device               *dev;
 +      struct drm_file                 *file;
 +      uint32_t                        dispatch_flags;
 +      uint32_t                        args_batch_start_offset;
 +      uint32_t                        batch_obj_vm_offset;
 +      struct intel_engine_cs          *ring;
 +      struct drm_i915_gem_object      *batch_obj;
 +      struct intel_context            *ctx;
 +      struct drm_i915_gem_request     *request;
 +};
 +
  struct drm_i915_private {
        struct drm_device *dev;
        struct kmem_cache *objects;
        u32 pm_rps_events;
        u32 pipestat_irq_mask[I915_MAX_PIPES];
  
 -      struct work_struct hotplug_work;
 -      struct {
 -              unsigned long hpd_last_jiffies;
 -              int hpd_cnt;
 -              enum {
 -                      HPD_ENABLED = 0,
 -                      HPD_DISABLED = 1,
 -                      HPD_MARK_DISABLED = 2
 -              } hpd_mark;
 -      } hpd_stats[HPD_NUM_PINS];
 -      u32 hpd_event_bits;
 -      struct delayed_work hotplug_reenable_work;
 -
 +      struct i915_hotplug hotplug;
        struct i915_fbc fbc;
        struct i915_drrs drrs;
        struct intel_opregion opregion;
  
        unsigned int fsb_freq, mem_freq, is_ddr3;
        unsigned int skl_boot_cdclk;
 -      unsigned int cdclk_freq;
 +      unsigned int cdclk_freq, max_cdclk_freq;
        unsigned int hpll_freq;
  
        /**
  
        /* Reclocking support */
        bool render_reclock_avail;
 -      bool lvds_downclock_avail;
 -      /* indicates the reduced downclock for LVDS*/
 -      int lvds_downclock;
  
        struct i915_frontbuffer_tracking fb_tracking;
  
  
        struct i915_runtime_pm pm;
  
 -      struct intel_digital_port *hpd_irq_port[I915_MAX_PORTS];
 -      u32 long_hpd_port_mask;
 -      u32 short_hpd_port_mask;
 -      struct work_struct dig_port_work;
 -
 -      /*
 -       * if we get a HPD irq from DP and a HPD irq from non-DP
 -       * the non-DP HPD could block the workqueue on a mode config
 -       * mutex getting, that userspace may have taken. However
 -       * userspace is waiting on the DP workqueue to run which is
 -       * blocked behind the non-DP one.
 -       */
 -      struct workqueue_struct *dp_wq;
 -
        /* Abstract the submission mechanism (legacy ringbuffer or execlists) away */
        struct {
 -              int (*execbuf_submit)(struct drm_device *dev, struct drm_file *file,
 -                                    struct intel_engine_cs *ring,
 -                                    struct intel_context *ctx,
 +              int (*execbuf_submit)(struct i915_execbuffer_params *params,
                                      struct drm_i915_gem_execbuffer2 *args,
 -                                    struct list_head *vmas,
 -                                    struct drm_i915_gem_object *batch_obj,
 -                                    u64 exec_start, u32 flags);
 +                                    struct list_head *vmas);
                int (*init_rings)(struct drm_device *dev);
                void (*cleanup_ring)(struct intel_engine_cs *ring);
                void (*stop_ring)(struct intel_engine_cs *ring);
@@@ -2194,8 -2148,7 +2194,8 @@@ struct drm_i915_gem_request 
        struct intel_context *ctx;
        struct intel_ringbuffer *ringbuf;
  
 -      /** Batch buffer related to this request if any */
 +      /** Batch buffer related to this request if any (used for
 +          error state dump only) */
        struct drm_i915_gem_object *batch_obj;
  
        /** Time at which this request was emitted, in jiffies. */
  };
  
  int i915_gem_request_alloc(struct intel_engine_cs *ring,
 -                         struct intel_context *ctx);
 +                         struct intel_context *ctx,
 +                         struct drm_i915_gem_request **req_out);
 +void i915_gem_request_cancel(struct drm_i915_gem_request *req);
  void i915_gem_request_free(struct kref *req_ref);
 +int i915_gem_request_add_to_client(struct drm_i915_gem_request *req,
 +                                 struct drm_file *file);
  
  static inline uint32_t
  i915_gem_request_get_seqno(struct drm_i915_gem_request *req)
@@@ -2442,9 -2391,6 +2442,9 @@@ struct drm_i915_cmd_table 
                                 ((INTEL_DEVID(dev) & 0xf) == 0x6 ||    \
                                 (INTEL_DEVID(dev) & 0xf) == 0xb ||     \
                                 (INTEL_DEVID(dev) & 0xf) == 0xe))
 +/* ULX machines are also considered ULT. */
 +#define IS_BDW_ULX(dev)               (IS_BROADWELL(dev) && \
 +                               (INTEL_DEVID(dev) & 0xf) == 0xe)
  #define IS_BDW_GT3(dev)               (IS_BROADWELL(dev) && \
                                 (INTEL_DEVID(dev) & 0x00F0) == 0x0020)
  #define IS_HSW_ULT(dev)               (IS_HASWELL(dev) && \
  /* ULX machines are also considered ULT. */
  #define IS_HSW_ULX(dev)               (INTEL_DEVID(dev) == 0x0A0E || \
                                 INTEL_DEVID(dev) == 0x0A1E)
 +#define IS_SKL_ULT(dev)               (INTEL_DEVID(dev) == 0x1906 || \
 +                               INTEL_DEVID(dev) == 0x1913 || \
 +                               INTEL_DEVID(dev) == 0x1916 || \
 +                               INTEL_DEVID(dev) == 0x1921 || \
 +                               INTEL_DEVID(dev) == 0x1926)
 +#define IS_SKL_ULX(dev)               (INTEL_DEVID(dev) == 0x190E || \
 +                               INTEL_DEVID(dev) == 0x1915 || \
 +                               INTEL_DEVID(dev) == 0x191E)
  #define IS_PRELIMINARY_HW(intel_info) ((intel_info)->is_preliminary)
  
  #define SKL_REVID_A0          (0x0)
   */
  #define HAS_128_BYTE_Y_TILING(dev) (!IS_GEN2(dev) && !(IS_I915G(dev) || \
                                                      IS_I915GM(dev)))
 -#define SUPPORTS_DIGITAL_OUTPUTS(dev) (!IS_GEN2(dev) && !IS_PINEVIEW(dev))
 -#define SUPPORTS_INTEGRATED_HDMI(dev) (IS_G4X(dev) || IS_GEN5(dev))
 -#define SUPPORTS_INTEGRATED_DP(dev)   (IS_G4X(dev) || IS_GEN5(dev))
  #define SUPPORTS_TV(dev)              (INTEL_INFO(dev)->supports_tv)
  #define I915_HAS_HOTPLUG(dev)          (INTEL_INFO(dev)->has_hotplug)
  
  
  #define HAS_CSR(dev)  (IS_SKYLAKE(dev))
  
 +#define HAS_RESOURCE_STREAMER(dev) (IS_HASWELL(dev) || \
 +                                  INTEL_INFO(dev)->gen >= 8)
 +
 +#define HAS_CORE_RING_FREQ(dev)       (INTEL_INFO(dev)->gen >= 6 && \
 +                               !IS_VALLEYVIEW(dev) && !IS_BROXTON(dev))
 +
  #define INTEL_PCH_DEVICE_ID_MASK              0xff00
  #define INTEL_PCH_IBX_DEVICE_ID_TYPE          0x3b00
  #define INTEL_PCH_CPT_DEVICE_ID_TYPE          0x1c00
@@@ -2598,6 -2533,7 +2598,6 @@@ struct i915_params 
        int modeset;
        int panel_ignore_lid;
        int semaphores;
 -      unsigned int lvds_downclock;
        int lvds_channel_mode;
        int panel_use_ssc;
        int vbt_sdvo_panel_type;
        bool reset;
        bool disable_display;
        bool disable_vtd_wa;
 +      bool enable_guc_submission;
 +      int guc_log_level;
        int use_mmio_flip;
        int mmio_debug;
        bool verbose_state_checks;
 -      bool nuclear_pageflip;
        int edp_vswing;
  };
  extern struct i915_params i915 __read_mostly;
@@@ -2637,27 -2572,21 +2637,27 @@@ extern void i915_driver_preclose(struc
                                 struct drm_file *file);
  extern void i915_driver_postclose(struct drm_device *dev,
                                  struct drm_file *file);
 -extern int i915_driver_device_is_agp(struct drm_device * dev);
  #ifdef CONFIG_COMPAT
  extern long i915_compat_ioctl(struct file *filp, unsigned int cmd,
                              unsigned long arg);
  #endif
  extern int intel_gpu_reset(struct drm_device *dev);
 +extern bool intel_has_gpu_reset(struct drm_device *dev);
  extern int i915_reset(struct drm_device *dev);
  extern unsigned long i915_chipset_val(struct drm_i915_private *dev_priv);
  extern unsigned long i915_mch_val(struct drm_i915_private *dev_priv);
  extern unsigned long i915_gfx_val(struct drm_i915_private *dev_priv);
  extern void i915_update_gfx_val(struct drm_i915_private *dev_priv);
  int vlv_force_gfx_clock(struct drm_i915_private *dev_priv, bool on);
 -void intel_hpd_cancel_work(struct drm_i915_private *dev_priv);
  void i915_firmware_load_error_print(const char *fw_path, int err);
  
 +/* intel_hotplug.c */
 +void intel_hpd_irq_handler(struct drm_device *dev, u32 pin_mask, u32 long_mask);
 +void intel_hpd_init(struct drm_i915_private *dev_priv);
 +void intel_hpd_init_work(struct drm_i915_private *dev_priv);
 +void intel_hpd_cancel_work(struct drm_i915_private *dev_priv);
 +bool intel_hpd_pin_to_port(enum hpd_pin pin, enum port *port);
 +
  /* i915_irq.c */
  void i915_queue_hangcheck(struct drm_device *dev);
  __printf(3, 4)
@@@ -2665,6 -2594,7 +2665,6 @@@ void i915_handle_error(struct drm_devic
                       const char *fmt, ...);
  
  extern void intel_irq_init(struct drm_i915_private *dev_priv);
 -extern void intel_hpd_init(struct drm_i915_private *dev_priv);
  int intel_irq_install(struct drm_i915_private *dev_priv);
  void intel_irq_uninstall(struct drm_i915_private *dev_priv);
  
@@@ -2731,11 -2661,19 +2731,11 @@@ int i915_gem_set_domain_ioctl(struct dr
  int i915_gem_sw_finish_ioctl(struct drm_device *dev, void *data,
                             struct drm_file *file_priv);
  void i915_gem_execbuffer_move_to_active(struct list_head *vmas,
 -                                      struct intel_engine_cs *ring);
 -void i915_gem_execbuffer_retire_commands(struct drm_device *dev,
 -                                       struct drm_file *file,
 -                                       struct intel_engine_cs *ring,
 -                                       struct drm_i915_gem_object *obj);
 -int i915_gem_ringbuffer_submission(struct drm_device *dev,
 -                                 struct drm_file *file,
 -                                 struct intel_engine_cs *ring,
 -                                 struct intel_context *ctx,
 +                                      struct drm_i915_gem_request *req);
 +void i915_gem_execbuffer_retire_commands(struct i915_execbuffer_params *params);
 +int i915_gem_ringbuffer_submission(struct i915_execbuffer_params *params,
                                   struct drm_i915_gem_execbuffer2 *args,
 -                                 struct list_head *vmas,
 -                                 struct drm_i915_gem_object *batch_obj,
 -                                 u64 exec_start, u32 flags);
 +                                 struct list_head *vmas);
  int i915_gem_execbuffer(struct drm_device *dev, void *data,
                        struct drm_file *file_priv);
  int i915_gem_execbuffer2(struct drm_device *dev, void *data,
@@@ -2768,8 -2706,6 +2768,8 @@@ void i915_gem_object_init(struct drm_i9
                         const struct drm_i915_gem_object_ops *ops);
  struct drm_i915_gem_object *i915_gem_alloc_object(struct drm_device *dev,
                                                  size_t size);
 +struct drm_i915_gem_object *i915_gem_object_create_from_data(
 +              struct drm_device *dev, const void *data, size_t size);
  void i915_init_vm(struct drm_i915_private *dev_priv,
                  struct i915_address_space *vm);
  void i915_gem_free_object(struct drm_gem_object *obj);
@@@ -2844,10 -2780,9 +2844,10 @@@ static inline void i915_gem_object_unpi
  
  int __must_check i915_mutex_lock_interruptible(struct drm_device *dev);
  int i915_gem_object_sync(struct drm_i915_gem_object *obj,
 -                       struct intel_engine_cs *to);
 +                       struct intel_engine_cs *to,
 +                       struct drm_i915_gem_request **to_req);
  void i915_vma_move_to_active(struct i915_vma *vma,
 -                           struct intel_engine_cs *ring);
 +                           struct drm_i915_gem_request *req);
  int i915_gem_dumb_create(struct drm_file *file_priv,
                         struct drm_device *dev,
                         struct drm_mode_create_dumb *args);
@@@ -2876,6 -2811,11 +2876,6 @@@ static inline bool i915_gem_request_com
  
  int __must_check i915_gem_get_seqno(struct drm_device *dev, u32 *seqno);
  int __must_check i915_gem_set_seqno(struct drm_device *dev, u32 seqno);
 -int __must_check i915_gem_object_get_fence(struct drm_i915_gem_object *obj);
 -int __must_check i915_gem_object_put_fence(struct drm_i915_gem_object *obj);
 -
 -bool i915_gem_object_pin_fence(struct drm_i915_gem_object *obj);
 -void i915_gem_object_unpin_fence(struct drm_i915_gem_object *obj);
  
  struct drm_i915_gem_request *
  i915_gem_find_active_request(struct intel_engine_cs *ring);
@@@ -2884,6 -2824,7 +2884,6 @@@ bool i915_gem_retire_requests(struct dr
  void i915_gem_retire_requests_ring(struct intel_engine_cs *ring);
  int __must_check i915_gem_check_wedge(struct i915_gpu_error *error,
                                      bool interruptible);
 -int __must_check i915_gem_check_olr(struct drm_i915_gem_request *req);
  
  static inline bool i915_reset_in_progress(struct i915_gpu_error *error)
  {
@@@ -2918,18 -2859,16 +2918,18 @@@ bool i915_gem_clflush_object(struct drm
  int __must_check i915_gem_init(struct drm_device *dev);
  int i915_gem_init_rings(struct drm_device *dev);
  int __must_check i915_gem_init_hw(struct drm_device *dev);
 -int i915_gem_l3_remap(struct intel_engine_cs *ring, int slice);
 +int i915_gem_l3_remap(struct drm_i915_gem_request *req, int slice);
  void i915_gem_init_swizzling(struct drm_device *dev);
  void i915_gem_cleanup_ringbuffer(struct drm_device *dev);
  int __must_check i915_gpu_idle(struct drm_device *dev);
  int __must_check i915_gem_suspend(struct drm_device *dev);
 -int __i915_add_request(struct intel_engine_cs *ring,
 -                     struct drm_file *file,
 -                     struct drm_i915_gem_object *batch_obj);
 -#define i915_add_request(ring) \
 -      __i915_add_request(ring, NULL, NULL)
 +void __i915_add_request(struct drm_i915_gem_request *req,
 +                      struct drm_i915_gem_object *batch_obj,
 +                      bool flush_caches);
 +#define i915_add_request(req) \
 +      __i915_add_request(req, NULL, true)
 +#define i915_add_request_no_flush(req) \
 +      __i915_add_request(req, NULL, false)
  int __i915_wait_request(struct drm_i915_gem_request *req,
                        unsigned reset_counter,
                        bool interruptible,
@@@ -2949,7 -2888,6 +2949,7 @@@ int __must_chec
  i915_gem_object_pin_to_display_plane(struct drm_i915_gem_object *obj,
                                     u32 alignment,
                                     struct intel_engine_cs *pipelined,
 +                                   struct drm_i915_gem_request **pipelined_request,
                                     const struct i915_ggtt_view *view);
  void i915_gem_object_unpin_from_display_plane(struct drm_i915_gem_object *obj,
                                              const struct i915_ggtt_view *view);
@@@ -2973,6 -2911,8 +2973,6 @@@ struct drm_gem_object *i915_gem_prime_i
  struct dma_buf *i915_gem_prime_export(struct drm_device *dev,
                                struct drm_gem_object *gem_obj, int flags);
  
 -void i915_gem_restore_fences(struct drm_device *dev);
 -
  unsigned long
  i915_gem_obj_ggtt_offset_view(struct drm_i915_gem_object *o,
                              const struct i915_ggtt_view *view);
@@@ -3067,27 -3007,15 +3067,27 @@@ i915_gem_object_ggtt_unpin(struct drm_i
        i915_gem_object_ggtt_unpin_view(obj, &i915_ggtt_view_normal);
  }
  
 +/* i915_gem_fence.c */
 +int __must_check i915_gem_object_get_fence(struct drm_i915_gem_object *obj);
 +int __must_check i915_gem_object_put_fence(struct drm_i915_gem_object *obj);
 +
 +bool i915_gem_object_pin_fence(struct drm_i915_gem_object *obj);
 +void i915_gem_object_unpin_fence(struct drm_i915_gem_object *obj);
 +
 +void i915_gem_restore_fences(struct drm_device *dev);
 +
 +void i915_gem_detect_bit_6_swizzle(struct drm_device *dev);
 +void i915_gem_object_do_bit_17_swizzle(struct drm_i915_gem_object *obj);
 +void i915_gem_object_save_bit_17_swizzle(struct drm_i915_gem_object *obj);
 +
  /* i915_gem_context.c */
  int __must_check i915_gem_context_init(struct drm_device *dev);
  void i915_gem_context_fini(struct drm_device *dev);
  void i915_gem_context_reset(struct drm_device *dev);
  int i915_gem_context_open(struct drm_device *dev, struct drm_file *file);
 -int i915_gem_context_enable(struct drm_i915_private *dev_priv);
 +int i915_gem_context_enable(struct drm_i915_gem_request *req);
  void i915_gem_context_close(struct drm_device *dev, struct drm_file *file);
 -int i915_switch_context(struct intel_engine_cs *ring,
 -                      struct intel_context *to);
 +int i915_switch_context(struct drm_i915_gem_request *req);
  struct intel_context *
  i915_gem_context_get(struct drm_i915_file_private *file_priv, u32 id);
  void i915_gem_context_free(struct kref *ctx_ref);
@@@ -3137,12 -3065,9 +3137,12 @@@ static inline void i915_gem_chipset_flu
  }
  
  /* i915_gem_stolen.c */
 +int i915_gem_stolen_insert_node(struct drm_i915_private *dev_priv,
 +                              struct drm_mm_node *node, u64 size,
 +                              unsigned alignment);
 +void i915_gem_stolen_remove_node(struct drm_i915_private *dev_priv,
 +                               struct drm_mm_node *node);
  int i915_gem_init_stolen(struct drm_device *dev);
 -int i915_gem_stolen_setup_compression(struct drm_device *dev, int size, int fb_cpp);
 -void i915_gem_stolen_cleanup_compression(struct drm_device *dev);
  void i915_gem_cleanup_stolen(struct drm_device *dev);
  struct drm_i915_gem_object *
  i915_gem_object_create_stolen(struct drm_device *dev, u32 size);
@@@ -3172,6 -3097,10 +3172,6 @@@ static inline bool i915_gem_object_need
                obj->tiling_mode != I915_TILING_NONE;
  }
  
 -void i915_gem_detect_bit_6_swizzle(struct drm_device *dev);
 -void i915_gem_object_do_bit_17_swizzle(struct drm_i915_gem_object *obj);
 -void i915_gem_object_save_bit_17_swizzle(struct drm_i915_gem_object *obj);
 -
  /* i915_gem_debug.c */
  #if WATCH_LISTS
  int i915_verify_lists(struct drm_device *dev);
@@@ -3293,7 -3222,8 +3293,7 @@@ extern void intel_modeset_gem_init(stru
  extern void intel_modeset_cleanup(struct drm_device *dev);
  extern void intel_connector_unregister(struct intel_connector *);
  extern int intel_modeset_vga_set_state(struct drm_device *dev, bool state);
 -extern void intel_modeset_setup_hw_state(struct drm_device *dev,
 -                                       bool force_restore);
 +extern void intel_display_resume(struct drm_device *dev);
  extern void i915_redisable_vga(struct drm_device *dev);
  extern void i915_redisable_vga_power_on(struct drm_device *dev);
  extern bool ironlake_set_drps(struct drm_device *dev, u8 val);
@@@ -3373,15 -3303,14 +3373,14 @@@ int intel_freq_opcode(struct drm_i915_p
  #define I915_READ64(reg)      dev_priv->uncore.funcs.mmio_readq(dev_priv, (reg), true)
  
  #define I915_READ64_2x32(lower_reg, upper_reg) ({                     \
-               u32 upper = I915_READ(upper_reg);                       \
-               u32 lower = I915_READ(lower_reg);                       \
-               u32 tmp = I915_READ(upper_reg);                         \
-               if (upper != tmp) {                                     \
-                       upper = tmp;                                    \
-                       lower = I915_READ(lower_reg);                   \
-                       WARN_ON(I915_READ(upper_reg) != upper);         \
-               }                                                       \
-               (u64)upper << 32 | lower; })
+       u32 upper, lower, tmp;                                          \
+       tmp = I915_READ(upper_reg);                                     \
+       do {                                                            \
+               upper = tmp;                                            \
+               lower = I915_READ(lower_reg);                           \
+               tmp = I915_READ(upper_reg);                             \
+       } while (upper != tmp);                                         \
+       (u64)upper << 32 | lower; })
  
  #define POSTING_READ(reg)     (void)I915_READ_NOTRACE(reg)
  #define POSTING_READ16(reg)   (void)I915_READ16_NOTRACE(reg)
index c2a291e09bd98222a20239881e8d5cbca6a49d6a,31e8269e6e3dab33d809f693f7cc6ce8cf318975..96054a560f4f8da59f40a1fc532013a1b7c5b374
@@@ -192,8 -192,9 +192,8 @@@ static gen8_pte_t gen8_pte_encode(dma_a
        return pte;
  }
  
 -static gen8_pde_t gen8_pde_encode(struct drm_device *dev,
 -                                dma_addr_t addr,
 -                                enum i915_cache_level level)
 +static gen8_pde_t gen8_pde_encode(const dma_addr_t addr,
 +                                const enum i915_cache_level level)
  {
        gen8_pde_t pde = _PAGE_PRESENT | _PAGE_RW;
        pde |= addr;
@@@ -300,120 -301,75 +300,120 @@@ static gen6_pte_t iris_pte_encode(dma_a
        return pte;
  }
  
 -#define i915_dma_unmap_single(px, dev) \
 -      __i915_dma_unmap_single((px)->daddr, dev)
 -
 -static void __i915_dma_unmap_single(dma_addr_t daddr,
 -                                  struct drm_device *dev)
 +static int __setup_page_dma(struct drm_device *dev,
 +                          struct i915_page_dma *p, gfp_t flags)
  {
        struct device *device = &dev->pdev->dev;
  
 -      dma_unmap_page(device, daddr, 4096, PCI_DMA_BIDIRECTIONAL);
 +      p->page = alloc_page(flags);
 +      if (!p->page)
 +              return -ENOMEM;
 +
 +      p->daddr = dma_map_page(device,
 +                              p->page, 0, 4096, PCI_DMA_BIDIRECTIONAL);
 +
 +      if (dma_mapping_error(device, p->daddr)) {
 +              __free_page(p->page);
 +              return -EINVAL;
 +      }
 +
 +      return 0;
  }
  
 -/**
 - * i915_dma_map_single() - Create a dma mapping for a page table/dir/etc.
 - * @px:       Page table/dir/etc to get a DMA map for
 - * @dev:      drm device
 - *
 - * Page table allocations are unified across all gens. They always require a
 - * single 4k allocation, as well as a DMA mapping. If we keep the structs
 - * symmetric here, the simple macro covers us for every page table type.
 - *
 - * Return: 0 if success.
 - */
 -#define i915_dma_map_single(px, dev) \
 -      i915_dma_map_page_single((px)->page, (dev), &(px)->daddr)
 +static int setup_page_dma(struct drm_device *dev, struct i915_page_dma *p)
 +{
 +      return __setup_page_dma(dev, p, GFP_KERNEL);
 +}
  
 -static int i915_dma_map_page_single(struct page *page,
 -                                  struct drm_device *dev,
 -                                  dma_addr_t *daddr)
 +static void cleanup_page_dma(struct drm_device *dev, struct i915_page_dma *p)
  {
 -      struct device *device = &dev->pdev->dev;
 +      if (WARN_ON(!p->page))
 +              return;
  
 -      *daddr = dma_map_page(device, page, 0, 4096, PCI_DMA_BIDIRECTIONAL);
 -      if (dma_mapping_error(device, *daddr))
 -              return -ENOMEM;
 +      dma_unmap_page(&dev->pdev->dev, p->daddr, 4096, PCI_DMA_BIDIRECTIONAL);
 +      __free_page(p->page);
 +      memset(p, 0, sizeof(*p));
 +}
  
 -      return 0;
 +static void *kmap_page_dma(struct i915_page_dma *p)
 +{
 +      return kmap_atomic(p->page);
  }
  
 -static void unmap_and_free_pt(struct i915_page_table *pt,
 -                             struct drm_device *dev)
 +/* We use the flushing unmap only with ppgtt structures:
 + * page directories, page tables and scratch pages.
 + */
 +static void kunmap_page_dma(struct drm_device *dev, void *vaddr)
  {
 -      if (WARN_ON(!pt->page))
 -              return;
 +      /* There are only few exceptions for gen >=6. chv and bxt.
 +       * And we are not sure about the latter so play safe for now.
 +       */
 +      if (IS_CHERRYVIEW(dev) || IS_BROXTON(dev))
 +              drm_clflush_virt_range(vaddr, PAGE_SIZE);
  
 -      i915_dma_unmap_single(pt, dev);
 -      __free_page(pt->page);
 -      kfree(pt->used_ptes);
 -      kfree(pt);
 +      kunmap_atomic(vaddr);
  }
  
 -static void gen8_initialize_pt(struct i915_address_space *vm,
 -                             struct i915_page_table *pt)
 +#define kmap_px(px) kmap_page_dma(px_base(px))
 +#define kunmap_px(ppgtt, vaddr) kunmap_page_dma((ppgtt)->base.dev, (vaddr))
 +
 +#define setup_px(dev, px) setup_page_dma((dev), px_base(px))
 +#define cleanup_px(dev, px) cleanup_page_dma((dev), px_base(px))
 +#define fill_px(dev, px, v) fill_page_dma((dev), px_base(px), (v))
 +#define fill32_px(dev, px, v) fill_page_dma_32((dev), px_base(px), (v))
 +
 +static void fill_page_dma(struct drm_device *dev, struct i915_page_dma *p,
 +                        const uint64_t val)
  {
 -      gen8_pte_t *pt_vaddr, scratch_pte;
        int i;
 +      uint64_t * const vaddr = kmap_page_dma(p);
  
 -      pt_vaddr = kmap_atomic(pt->page);
 -      scratch_pte = gen8_pte_encode(vm->scratch.addr,
 -                                    I915_CACHE_LLC, true);
 +      for (i = 0; i < 512; i++)
 +              vaddr[i] = val;
 +
 +      kunmap_page_dma(dev, vaddr);
 +}
 +
 +static void fill_page_dma_32(struct drm_device *dev, struct i915_page_dma *p,
 +                           const uint32_t val32)
 +{
 +      uint64_t v = val32;
  
 -      for (i = 0; i < GEN8_PTES; i++)
 -              pt_vaddr[i] = scratch_pte;
 +      v = v << 32 | val32;
  
 -      if (!HAS_LLC(vm->dev))
 -              drm_clflush_virt_range(pt_vaddr, PAGE_SIZE);
 -      kunmap_atomic(pt_vaddr);
 +      fill_page_dma(dev, p, v);
  }
  
 -static struct i915_page_table *alloc_pt_single(struct drm_device *dev)
 +static struct i915_page_scratch *alloc_scratch_page(struct drm_device *dev)
 +{
 +      struct i915_page_scratch *sp;
 +      int ret;
 +
 +      sp = kzalloc(sizeof(*sp), GFP_KERNEL);
 +      if (sp == NULL)
 +              return ERR_PTR(-ENOMEM);
 +
 +      ret = __setup_page_dma(dev, px_base(sp), GFP_DMA32 | __GFP_ZERO);
 +      if (ret) {
 +              kfree(sp);
 +              return ERR_PTR(ret);
 +      }
 +
 +      set_pages_uc(px_page(sp), 1);
 +
 +      return sp;
 +}
 +
 +static void free_scratch_page(struct drm_device *dev,
 +                            struct i915_page_scratch *sp)
 +{
 +      set_pages_wb(px_page(sp), 1);
 +
 +      cleanup_px(dev, sp);
 +      kfree(sp);
 +}
 +
 +static struct i915_page_table *alloc_pt(struct drm_device *dev)
  {
        struct i915_page_table *pt;
        const size_t count = INTEL_INFO(dev)->gen >= 8 ?
        if (!pt->used_ptes)
                goto fail_bitmap;
  
 -      pt->page = alloc_page(GFP_KERNEL);
 -      if (!pt->page)
 -              goto fail_page;
 -
 -      ret = i915_dma_map_single(pt, dev);
 +      ret = setup_px(dev, pt);
        if (ret)
 -              goto fail_dma;
 +              goto fail_page_m;
  
        return pt;
  
 -fail_dma:
 -      __free_page(pt->page);
 -fail_page:
 +fail_page_m:
        kfree(pt->used_ptes);
  fail_bitmap:
        kfree(pt);
        return ERR_PTR(ret);
  }
  
 -static void unmap_and_free_pd(struct i915_page_directory *pd,
 -                            struct drm_device *dev)
 +static void free_pt(struct drm_device *dev, struct i915_page_table *pt)
  {
 -      if (pd->page) {
 -              i915_dma_unmap_single(pd, dev);
 -              __free_page(pd->page);
 -              kfree(pd->used_pdes);
 -              kfree(pd);
 -      }
 +      cleanup_px(dev, pt);
 +      kfree(pt->used_ptes);
 +      kfree(pt);
  }
  
 -static struct i915_page_directory *alloc_pd_single(struct drm_device *dev)
 +static void gen8_initialize_pt(struct i915_address_space *vm,
 +                             struct i915_page_table *pt)
 +{
 +      gen8_pte_t scratch_pte;
 +
 +      scratch_pte = gen8_pte_encode(px_dma(vm->scratch_page),
 +                                    I915_CACHE_LLC, true);
 +
 +      fill_px(vm->dev, pt, scratch_pte);
 +}
 +
 +static void gen6_initialize_pt(struct i915_address_space *vm,
 +                             struct i915_page_table *pt)
 +{
 +      gen6_pte_t scratch_pte;
 +
 +      WARN_ON(px_dma(vm->scratch_page) == 0);
 +
 +      scratch_pte = vm->pte_encode(px_dma(vm->scratch_page),
 +                                   I915_CACHE_LLC, true, 0);
 +
 +      fill32_px(vm->dev, pt, scratch_pte);
 +}
 +
 +static struct i915_page_directory *alloc_pd(struct drm_device *dev)
  {
        struct i915_page_directory *pd;
        int ret = -ENOMEM;
        pd->used_pdes = kcalloc(BITS_TO_LONGS(I915_PDES),
                                sizeof(*pd->used_pdes), GFP_KERNEL);
        if (!pd->used_pdes)
 -              goto free_pd;
 -
 -      pd->page = alloc_page(GFP_KERNEL);
 -      if (!pd->page)
 -              goto free_bitmap;
 +              goto fail_bitmap;
  
 -      ret = i915_dma_map_single(pd, dev);
 +      ret = setup_px(dev, pd);
        if (ret)
 -              goto free_page;
 +              goto fail_page_m;
  
        return pd;
  
 -free_page:
 -      __free_page(pd->page);
 -free_bitmap:
 +fail_page_m:
        kfree(pd->used_pdes);
 -free_pd:
 +fail_bitmap:
        kfree(pd);
  
        return ERR_PTR(ret);
  }
  
 +static void free_pd(struct drm_device *dev, struct i915_page_directory *pd)
 +{
 +      if (px_page(pd)) {
 +              cleanup_px(dev, pd);
 +              kfree(pd->used_pdes);
 +              kfree(pd);
 +      }
 +}
 +
 +static void gen8_initialize_pd(struct i915_address_space *vm,
 +                             struct i915_page_directory *pd)
 +{
 +      gen8_pde_t scratch_pde;
 +
 +      scratch_pde = gen8_pde_encode(px_dma(vm->scratch_pt), I915_CACHE_LLC);
 +
 +      fill_px(vm->dev, pd, scratch_pde);
 +}
 +
  /* Broadwell Page Directory Pointer Descriptors */
 -static int gen8_write_pdp(struct intel_engine_cs *ring,
 +static int gen8_write_pdp(struct drm_i915_gem_request *req,
                          unsigned entry,
                          dma_addr_t addr)
  {
 +      struct intel_engine_cs *ring = req->ring;
        int ret;
  
        BUG_ON(entry >= 4);
  
 -      ret = intel_ring_begin(ring, 6);
 +      ret = intel_ring_begin(req, 6);
        if (ret)
                return ret;
  
  }
  
  static int gen8_mm_switch(struct i915_hw_ppgtt *ppgtt,
 -                        struct intel_engine_cs *ring)
 +                        struct drm_i915_gem_request *req)
  {
        int i, ret;
  
        for (i = GEN8_LEGACY_PDPES - 1; i >= 0; i--) {
 -              struct i915_page_directory *pd = ppgtt->pdp.page_directory[i];
 -              dma_addr_t pd_daddr = pd ? pd->daddr : ppgtt->scratch_pd->daddr;
 -              /* The page directory might be NULL, but we need to clear out
 -               * whatever the previous context might have used. */
 -              ret = gen8_write_pdp(ring, i, pd_daddr);
 +              const dma_addr_t pd_daddr = i915_page_dir_dma_addr(ppgtt, i);
 +
 +              ret = gen8_write_pdp(req, i, pd_daddr);
                if (ret)
                        return ret;
        }
@@@ -577,12 -507,13 +577,12 @@@ static void gen8_ppgtt_clear_range(stru
        unsigned num_entries = length >> PAGE_SHIFT;
        unsigned last_pte, i;
  
 -      scratch_pte = gen8_pte_encode(ppgtt->base.scratch.addr,
 +      scratch_pte = gen8_pte_encode(px_dma(ppgtt->base.scratch_page),
                                      I915_CACHE_LLC, use_scratch);
  
        while (num_entries) {
                struct i915_page_directory *pd;
                struct i915_page_table *pt;
 -              struct page *page_table;
  
                if (WARN_ON(!ppgtt->pdp.page_directory[pdpe]))
                        break;
  
                pt = pd->page_table[pde];
  
 -              if (WARN_ON(!pt->page))
 +              if (WARN_ON(!px_page(pt)))
                        break;
  
 -              page_table = pt->page;
 -
                last_pte = pte + num_entries;
                if (last_pte > GEN8_PTES)
                        last_pte = GEN8_PTES;
  
 -              pt_vaddr = kmap_atomic(page_table);
 +              pt_vaddr = kmap_px(pt);
  
                for (i = pte; i < last_pte; i++) {
                        pt_vaddr[i] = scratch_pte;
                        num_entries--;
                }
  
 -              if (!HAS_LLC(ppgtt->base.dev))
 -                      drm_clflush_virt_range(pt_vaddr, PAGE_SIZE);
 -              kunmap_atomic(pt_vaddr);
 +              kunmap_px(ppgtt, pt);
  
                pte = 0;
                if (++pde == I915_PDES) {
@@@ -640,14 -575,18 +640,14 @@@ static void gen8_ppgtt_insert_entries(s
                if (pt_vaddr == NULL) {
                        struct i915_page_directory *pd = ppgtt->pdp.page_directory[pdpe];
                        struct i915_page_table *pt = pd->page_table[pde];
 -                      struct page *page_table = pt->page;
 -
 -                      pt_vaddr = kmap_atomic(page_table);
 +                      pt_vaddr = kmap_px(pt);
                }
  
                pt_vaddr[pte] =
                        gen8_pte_encode(sg_page_iter_dma_address(&sg_iter),
                                        cache_level, true);
                if (++pte == GEN8_PTES) {
 -                      if (!HAS_LLC(ppgtt->base.dev))
 -                              drm_clflush_virt_range(pt_vaddr, PAGE_SIZE);
 -                      kunmap_atomic(pt_vaddr);
 +                      kunmap_px(ppgtt, pt_vaddr);
                        pt_vaddr = NULL;
                        if (++pde == I915_PDES) {
                                pdpe++;
                        pte = 0;
                }
        }
 -      if (pt_vaddr) {
 -              if (!HAS_LLC(ppgtt->base.dev))
 -                      drm_clflush_virt_range(pt_vaddr, PAGE_SIZE);
 -              kunmap_atomic(pt_vaddr);
 -      }
 -}
 -
 -static void __gen8_do_map_pt(gen8_pde_t * const pde,
 -                           struct i915_page_table *pt,
 -                           struct drm_device *dev)
 -{
 -      gen8_pde_t entry =
 -              gen8_pde_encode(dev, pt->daddr, I915_CACHE_LLC);
 -      *pde = entry;
 -}
  
 -static void gen8_initialize_pd(struct i915_address_space *vm,
 -                             struct i915_page_directory *pd)
 -{
 -      struct i915_hw_ppgtt *ppgtt =
 -                      container_of(vm, struct i915_hw_ppgtt, base);
 -      gen8_pde_t *page_directory;
 -      struct i915_page_table *pt;
 -      int i;
 -
 -      page_directory = kmap_atomic(pd->page);
 -      pt = ppgtt->scratch_pt;
 -      for (i = 0; i < I915_PDES; i++)
 -              /* Map the PDE to the page table */
 -              __gen8_do_map_pt(page_directory + i, pt, vm->dev);
 -
 -      if (!HAS_LLC(vm->dev))
 -              drm_clflush_virt_range(page_directory, PAGE_SIZE);
 -      kunmap_atomic(page_directory);
 +      if (pt_vaddr)
 +              kunmap_px(ppgtt, pt_vaddr);
  }
  
 -static void gen8_free_page_tables(struct i915_page_directory *pd, struct drm_device *dev)
 +static void gen8_free_page_tables(struct drm_device *dev,
 +                                struct i915_page_directory *pd)
  {
        int i;
  
 -      if (!pd->page)
 +      if (!px_page(pd))
                return;
  
        for_each_set_bit(i, pd->used_pdes, I915_PDES) {
                if (WARN_ON(!pd->page_table[i]))
                        continue;
  
 -              unmap_and_free_pt(pd->page_table[i], dev);
 +              free_pt(dev, pd->page_table[i]);
                pd->page_table[i] = NULL;
        }
  }
  
 +static int gen8_init_scratch(struct i915_address_space *vm)
 +{
 +      struct drm_device *dev = vm->dev;
 +
 +      vm->scratch_page = alloc_scratch_page(dev);
 +      if (IS_ERR(vm->scratch_page))
 +              return PTR_ERR(vm->scratch_page);
 +
 +      vm->scratch_pt = alloc_pt(dev);
 +      if (IS_ERR(vm->scratch_pt)) {
 +              free_scratch_page(dev, vm->scratch_page);
 +              return PTR_ERR(vm->scratch_pt);
 +      }
 +
 +      vm->scratch_pd = alloc_pd(dev);
 +      if (IS_ERR(vm->scratch_pd)) {
 +              free_pt(dev, vm->scratch_pt);
 +              free_scratch_page(dev, vm->scratch_page);
 +              return PTR_ERR(vm->scratch_pd);
 +      }
 +
 +      gen8_initialize_pt(vm, vm->scratch_pt);
 +      gen8_initialize_pd(vm, vm->scratch_pd);
 +
 +      return 0;
 +}
 +
 +static void gen8_free_scratch(struct i915_address_space *vm)
 +{
 +      struct drm_device *dev = vm->dev;
 +
 +      free_pd(dev, vm->scratch_pd);
 +      free_pt(dev, vm->scratch_pt);
 +      free_scratch_page(dev, vm->scratch_page);
 +}
 +
  static void gen8_ppgtt_cleanup(struct i915_address_space *vm)
  {
        struct i915_hw_ppgtt *ppgtt =
                if (WARN_ON(!ppgtt->pdp.page_directory[i]))
                        continue;
  
 -              gen8_free_page_tables(ppgtt->pdp.page_directory[i], ppgtt->base.dev);
 -              unmap_and_free_pd(ppgtt->pdp.page_directory[i], ppgtt->base.dev);
 +              gen8_free_page_tables(ppgtt->base.dev,
 +                                    ppgtt->pdp.page_directory[i]);
 +              free_pd(ppgtt->base.dev, ppgtt->pdp.page_directory[i]);
        }
  
 -      unmap_and_free_pd(ppgtt->scratch_pd, ppgtt->base.dev);
 -      unmap_and_free_pt(ppgtt->scratch_pt, ppgtt->base.dev);
 +      gen8_free_scratch(vm);
  }
  
  /**
@@@ -765,24 -698,24 +765,24 @@@ static int gen8_ppgtt_alloc_pagetabs(st
                /* Don't reallocate page tables */
                if (pt) {
                        /* Scratch is never allocated this way */
 -                      WARN_ON(pt == ppgtt->scratch_pt);
 +                      WARN_ON(pt == ppgtt->base.scratch_pt);
                        continue;
                }
  
 -              pt = alloc_pt_single(dev);
 +              pt = alloc_pt(dev);
                if (IS_ERR(pt))
                        goto unwind_out;
  
                gen8_initialize_pt(&ppgtt->base, pt);
                pd->page_table[pde] = pt;
 -              set_bit(pde, new_pts);
 +              __set_bit(pde, new_pts);
        }
  
        return 0;
  
  unwind_out:
        for_each_set_bit(pde, new_pts, I915_PDES)
 -              unmap_and_free_pt(pd->page_table[pde], dev);
 +              free_pt(dev, pd->page_table[pde]);
  
        return -ENOMEM;
  }
@@@ -823,24 -756,27 +823,24 @@@ static int gen8_ppgtt_alloc_page_direct
  
        WARN_ON(!bitmap_empty(new_pds, GEN8_LEGACY_PDPES));
  
 -      /* FIXME: upper bound must not overflow 32 bits  */
 -      WARN_ON((start + length) > (1ULL << 32));
 -
        gen8_for_each_pdpe(pd, pdp, start, length, temp, pdpe) {
                if (pd)
                        continue;
  
 -              pd = alloc_pd_single(dev);
 +              pd = alloc_pd(dev);
                if (IS_ERR(pd))
                        goto unwind_out;
  
                gen8_initialize_pd(&ppgtt->base, pd);
                pdp->page_directory[pdpe] = pd;
 -              set_bit(pdpe, new_pds);
 +              __set_bit(pdpe, new_pds);
        }
  
        return 0;
  
  unwind_out:
        for_each_set_bit(pdpe, new_pds, GEN8_LEGACY_PDPES)
 -              unmap_and_free_pd(pdp->page_directory[pdpe], dev);
 +              free_pd(dev, pdp->page_directory[pdpe]);
  
        return -ENOMEM;
  }
@@@ -894,16 -830,6 +894,16 @@@ err_out
        return -ENOMEM;
  }
  
 +/* PDE TLBs are a pain to invalidate on GEN8+. When we modify
 + * the page table structures, we mark them dirty so that
 + * context switching/execlist queuing code takes extra steps
 + * to ensure that tlbs are flushed.
 + */
 +static void mark_tlbs_dirty(struct i915_hw_ppgtt *ppgtt)
 +{
 +      ppgtt->pd_dirty_rings = INTEL_INFO(ppgtt->base.dev)->ring_mask;
 +}
 +
  static int gen8_alloc_va_range(struct i915_address_space *vm,
                               uint64_t start,
                               uint64_t length)
         * actually use the other side of the canonical address space.
         */
        if (WARN_ON(start + length < start))
 -              return -ERANGE;
 +              return -ENODEV;
 +
 +      if (WARN_ON(start + length > ppgtt->base.total))
 +              return -ENODEV;
  
        ret = alloc_gen8_temp_bitmaps(&new_page_dirs, &new_page_tables);
        if (ret)
        /* Allocations have completed successfully, so set the bitmaps, and do
         * the mappings. */
        gen8_for_each_pdpe(pd, &ppgtt->pdp, start, length, temp, pdpe) {
 -              gen8_pde_t *const page_directory = kmap_atomic(pd->page);
 +              gen8_pde_t *const page_directory = kmap_px(pd);
                struct i915_page_table *pt;
                uint64_t pd_len = gen8_clamp_pd(start, length);
                uint64_t pd_start = start;
                                   gen8_pte_count(pd_start, pd_len));
  
                        /* Our pde is now pointing to the pagetable, pt */
 -                      set_bit(pde, pd->used_pdes);
 +                      __set_bit(pde, pd->used_pdes);
  
                        /* Map the PDE to the page table */
 -                      __gen8_do_map_pt(page_directory + pde, pt, vm->dev);
 +                      page_directory[pde] = gen8_pde_encode(px_dma(pt),
 +                                                            I915_CACHE_LLC);
  
                        /* NB: We haven't yet mapped ptes to pages. At this
                         * point we're still relying on insert_entries() */
                }
  
 -              if (!HAS_LLC(vm->dev))
 -                      drm_clflush_virt_range(page_directory, PAGE_SIZE);
 +              kunmap_px(ppgtt, page_directory);
  
 -              kunmap_atomic(page_directory);
 -
 -              set_bit(pdpe, ppgtt->pdp.used_pdpes);
 +              __set_bit(pdpe, ppgtt->pdp.used_pdpes);
        }
  
        free_gen8_temp_bitmaps(new_page_dirs, new_page_tables);
 +      mark_tlbs_dirty(ppgtt);
        return 0;
  
  err_out:
        while (pdpe--) {
                for_each_set_bit(temp, new_page_tables[pdpe], I915_PDES)
 -                      unmap_and_free_pt(ppgtt->pdp.page_directory[pdpe]->page_table[temp], vm->dev);
 +                      free_pt(vm->dev, ppgtt->pdp.page_directory[pdpe]->page_table[temp]);
        }
  
        for_each_set_bit(pdpe, new_page_dirs, GEN8_LEGACY_PDPES)
 -              unmap_and_free_pd(ppgtt->pdp.page_directory[pdpe], vm->dev);
 +              free_pd(vm->dev, ppgtt->pdp.page_directory[pdpe]);
  
        free_gen8_temp_bitmaps(new_page_dirs, new_page_tables);
 +      mark_tlbs_dirty(ppgtt);
        return ret;
  }
  
   */
  static int gen8_ppgtt_init(struct i915_hw_ppgtt *ppgtt)
  {
 -      ppgtt->scratch_pt = alloc_pt_single(ppgtt->base.dev);
 -      if (IS_ERR(ppgtt->scratch_pt))
 -              return PTR_ERR(ppgtt->scratch_pt);
 -
 -      ppgtt->scratch_pd = alloc_pd_single(ppgtt->base.dev);
 -      if (IS_ERR(ppgtt->scratch_pd))
 -              return PTR_ERR(ppgtt->scratch_pd);
 +      int ret;
  
 -      gen8_initialize_pt(&ppgtt->base, ppgtt->scratch_pt);
 -      gen8_initialize_pd(&ppgtt->base, ppgtt->scratch_pd);
 +      ret = gen8_init_scratch(&ppgtt->base);
 +      if (ret)
 +              return ret;
  
        ppgtt->base.start = 0;
        ppgtt->base.total = 1ULL << 32;
@@@ -1052,13 -980,12 +1052,13 @@@ static void gen6_dump_ppgtt(struct i915
        uint32_t  pte, pde, temp;
        uint32_t start = ppgtt->base.start, length = ppgtt->base.total;
  
 -      scratch_pte = vm->pte_encode(vm->scratch.addr, I915_CACHE_LLC, true, 0);
 +      scratch_pte = vm->pte_encode(px_dma(vm->scratch_page),
 +                                   I915_CACHE_LLC, true, 0);
  
        gen6_for_each_pde(unused, &ppgtt->pd, start, length, temp, pde) {
                u32 expected;
                gen6_pte_t *pt_vaddr;
 -              dma_addr_t pt_addr = ppgtt->pd.page_table[pde]->daddr;
 +              const dma_addr_t pt_addr = px_dma(ppgtt->pd.page_table[pde]);
                pd_entry = readl(ppgtt->pd_addr + pde);
                expected = (GEN6_PDE_ADDR_ENCODE(pt_addr) | GEN6_PDE_VALID);
  
                                   expected);
                seq_printf(m, "\tPDE: %x\n", pd_entry);
  
 -              pt_vaddr = kmap_atomic(ppgtt->pd.page_table[pde]->page);
 +              pt_vaddr = kmap_px(ppgtt->pd.page_table[pde]);
 +
                for (pte = 0; pte < GEN6_PTES; pte+=4) {
                        unsigned long va =
                                (pde * PAGE_SIZE * GEN6_PTES) +
                        }
                        seq_puts(m, "\n");
                }
 -              kunmap_atomic(pt_vaddr);
 +              kunmap_px(ppgtt, pt_vaddr);
        }
  }
  
@@@ -1105,7 -1031,7 +1105,7 @@@ static void gen6_write_pde(struct i915_
                container_of(pd, struct i915_hw_ppgtt, pd);
        u32 pd_entry;
  
 -      pd_entry = GEN6_PDE_ADDR_ENCODE(pt->daddr);
 +      pd_entry = GEN6_PDE_ADDR_ENCODE(px_dma(pt));
        pd_entry |= GEN6_PDE_VALID;
  
        writel(pd_entry, ppgtt->pd_addr + pde);
@@@ -1130,23 -1056,22 +1130,23 @@@ static void gen6_write_page_range(struc
  
  static uint32_t get_pd_offset(struct i915_hw_ppgtt *ppgtt)
  {
 -      BUG_ON(ppgtt->pd.pd_offset & 0x3f);
 +      BUG_ON(ppgtt->pd.base.ggtt_offset & 0x3f);
  
 -      return (ppgtt->pd.pd_offset / 64) << 16;
 +      return (ppgtt->pd.base.ggtt_offset / 64) << 16;
  }
  
  static int hsw_mm_switch(struct i915_hw_ppgtt *ppgtt,
 -                       struct intel_engine_cs *ring)
 +                       struct drm_i915_gem_request *req)
  {
 +      struct intel_engine_cs *ring = req->ring;
        int ret;
  
        /* NB: TLBs must be flushed and invalidated before a switch */
 -      ret = ring->flush(ring, I915_GEM_GPU_DOMAINS, I915_GEM_GPU_DOMAINS);
 +      ret = ring->flush(req, I915_GEM_GPU_DOMAINS, I915_GEM_GPU_DOMAINS);
        if (ret)
                return ret;
  
 -      ret = intel_ring_begin(ring, 6);
 +      ret = intel_ring_begin(req, 6);
        if (ret)
                return ret;
  
  }
  
  static int vgpu_mm_switch(struct i915_hw_ppgtt *ppgtt,
 -                        struct intel_engine_cs *ring)
 +                        struct drm_i915_gem_request *req)
  {
 +      struct intel_engine_cs *ring = req->ring;
        struct drm_i915_private *dev_priv = to_i915(ppgtt->base.dev);
  
        I915_WRITE(RING_PP_DIR_DCLV(ring), PP_DIR_DCLV_2G);
  }
  
  static int gen7_mm_switch(struct i915_hw_ppgtt *ppgtt,
 -                        struct intel_engine_cs *ring)
 +                        struct drm_i915_gem_request *req)
  {
 +      struct intel_engine_cs *ring = req->ring;
        int ret;
  
        /* NB: TLBs must be flushed and invalidated before a switch */
 -      ret = ring->flush(ring, I915_GEM_GPU_DOMAINS, I915_GEM_GPU_DOMAINS);
 +      ret = ring->flush(req, I915_GEM_GPU_DOMAINS, I915_GEM_GPU_DOMAINS);
        if (ret)
                return ret;
  
 -      ret = intel_ring_begin(ring, 6);
 +      ret = intel_ring_begin(req, 6);
        if (ret)
                return ret;
  
  
        /* XXX: RCS is the only one to auto invalidate the TLBs? */
        if (ring->id != RCS) {
 -              ret = ring->flush(ring, I915_GEM_GPU_DOMAINS, I915_GEM_GPU_DOMAINS);
 +              ret = ring->flush(req, I915_GEM_GPU_DOMAINS, I915_GEM_GPU_DOMAINS);
                if (ret)
                        return ret;
        }
  }
  
  static int gen6_mm_switch(struct i915_hw_ppgtt *ppgtt,
 -                        struct intel_engine_cs *ring)
 +                        struct drm_i915_gem_request *req)
  {
 +      struct intel_engine_cs *ring = req->ring;
        struct drm_device *dev = ppgtt->base.dev;
        struct drm_i915_private *dev_priv = dev->dev_private;
  
@@@ -1292,20 -1214,19 +1292,20 @@@ static void gen6_ppgtt_clear_range(stru
        unsigned first_pte = first_entry % GEN6_PTES;
        unsigned last_pte, i;
  
 -      scratch_pte = vm->pte_encode(vm->scratch.addr, I915_CACHE_LLC, true, 0);
 +      scratch_pte = vm->pte_encode(px_dma(vm->scratch_page),
 +                                   I915_CACHE_LLC, true, 0);
  
        while (num_entries) {
                last_pte = first_pte + num_entries;
                if (last_pte > GEN6_PTES)
                        last_pte = GEN6_PTES;
  
 -              pt_vaddr = kmap_atomic(ppgtt->pd.page_table[act_pt]->page);
 +              pt_vaddr = kmap_px(ppgtt->pd.page_table[act_pt]);
  
                for (i = first_pte; i < last_pte; i++)
                        pt_vaddr[i] = scratch_pte;
  
 -              kunmap_atomic(pt_vaddr);
 +              kunmap_px(ppgtt, pt_vaddr);
  
                num_entries -= last_pte - first_pte;
                first_pte = 0;
@@@ -1329,25 -1250,54 +1329,25 @@@ static void gen6_ppgtt_insert_entries(s
        pt_vaddr = NULL;
        for_each_sg_page(pages->sgl, &sg_iter, pages->nents, 0) {
                if (pt_vaddr == NULL)
 -                      pt_vaddr = kmap_atomic(ppgtt->pd.page_table[act_pt]->page);
 +                      pt_vaddr = kmap_px(ppgtt->pd.page_table[act_pt]);
  
                pt_vaddr[act_pte] =
                        vm->pte_encode(sg_page_iter_dma_address(&sg_iter),
                                       cache_level, true, flags);
  
                if (++act_pte == GEN6_PTES) {
 -                      kunmap_atomic(pt_vaddr);
 +                      kunmap_px(ppgtt, pt_vaddr);
                        pt_vaddr = NULL;
                        act_pt++;
                        act_pte = 0;
                }
        }
        if (pt_vaddr)
 -              kunmap_atomic(pt_vaddr);
 -}
 -
 -/* PDE TLBs are a pain invalidate pre GEN8. It requires a context reload. If we
 - * are switching between contexts with the same LRCA, we also must do a force
 - * restore.
 - */
 -static void mark_tlbs_dirty(struct i915_hw_ppgtt *ppgtt)
 -{
 -      /* If current vm != vm, */
 -      ppgtt->pd_dirty_rings = INTEL_INFO(ppgtt->base.dev)->ring_mask;
 -}
 -
 -static void gen6_initialize_pt(struct i915_address_space *vm,
 -              struct i915_page_table *pt)
 -{
 -      gen6_pte_t *pt_vaddr, scratch_pte;
 -      int i;
 -
 -      WARN_ON(vm->scratch.addr == 0);
 -
 -      scratch_pte = vm->pte_encode(vm->scratch.addr,
 -                      I915_CACHE_LLC, true, 0);
 -
 -      pt_vaddr = kmap_atomic(pt->page);
 -
 -      for (i = 0; i < GEN6_PTES; i++)
 -              pt_vaddr[i] = scratch_pte;
 -
 -      kunmap_atomic(pt_vaddr);
 +              kunmap_px(ppgtt, pt_vaddr);
  }
  
  static int gen6_alloc_va_range(struct i915_address_space *vm,
 -                             uint64_t start, uint64_t length)
 +                             uint64_t start_in, uint64_t length_in)
  {
        DECLARE_BITMAP(new_page_tables, I915_PDES);
        struct drm_device *dev = vm->dev;
        struct i915_hw_ppgtt *ppgtt =
                                container_of(vm, struct i915_hw_ppgtt, base);
        struct i915_page_table *pt;
 -      const uint32_t start_save = start, length_save = length;
 +      uint32_t start, length, start_save, length_save;
        uint32_t pde, temp;
        int ret;
  
 -      WARN_ON(upper_32_bits(start));
 +      if (WARN_ON(start_in + length_in > ppgtt->base.total))
 +              return -ENODEV;
 +
 +      start = start_save = start_in;
 +      length = length_save = length_in;
  
        bitmap_zero(new_page_tables, I915_PDES);
  
         * tables.
         */
        gen6_for_each_pde(pt, &ppgtt->pd, start, length, temp, pde) {
 -              if (pt != ppgtt->scratch_pt) {
 +              if (pt != vm->scratch_pt) {
                        WARN_ON(bitmap_empty(pt->used_ptes, GEN6_PTES));
                        continue;
                }
                /* We've already allocated a page table */
                WARN_ON(!bitmap_empty(pt->used_ptes, GEN6_PTES));
  
 -              pt = alloc_pt_single(dev);
 +              pt = alloc_pt(dev);
                if (IS_ERR(pt)) {
                        ret = PTR_ERR(pt);
                        goto unwind_out;
                gen6_initialize_pt(vm, pt);
  
                ppgtt->pd.page_table[pde] = pt;
 -              set_bit(pde, new_page_tables);
 +              __set_bit(pde, new_page_tables);
                trace_i915_page_table_entry_alloc(vm, pde, start, GEN6_PDE_SHIFT);
        }
  
                bitmap_set(tmp_bitmap, gen6_pte_index(start),
                           gen6_pte_count(start, length));
  
 -              if (test_and_clear_bit(pde, new_page_tables))
 +              if (__test_and_clear_bit(pde, new_page_tables))
                        gen6_write_pde(&ppgtt->pd, pde, pt);
  
                trace_i915_page_table_entry_map(vm, pde, pt,
@@@ -1428,41 -1374,14 +1428,41 @@@ unwind_out
        for_each_set_bit(pde, new_page_tables, I915_PDES) {
                struct i915_page_table *pt = ppgtt->pd.page_table[pde];
  
 -              ppgtt->pd.page_table[pde] = ppgtt->scratch_pt;
 -              unmap_and_free_pt(pt, vm->dev);
 +              ppgtt->pd.page_table[pde] = vm->scratch_pt;
 +              free_pt(vm->dev, pt);
        }
  
        mark_tlbs_dirty(ppgtt);
        return ret;
  }
  
 +static int gen6_init_scratch(struct i915_address_space *vm)
 +{
 +      struct drm_device *dev = vm->dev;
 +
 +      vm->scratch_page = alloc_scratch_page(dev);
 +      if (IS_ERR(vm->scratch_page))
 +              return PTR_ERR(vm->scratch_page);
 +
 +      vm->scratch_pt = alloc_pt(dev);
 +      if (IS_ERR(vm->scratch_pt)) {
 +              free_scratch_page(dev, vm->scratch_page);
 +              return PTR_ERR(vm->scratch_pt);
 +      }
 +
 +      gen6_initialize_pt(vm, vm->scratch_pt);
 +
 +      return 0;
 +}
 +
 +static void gen6_free_scratch(struct i915_address_space *vm)
 +{
 +      struct drm_device *dev = vm->dev;
 +
 +      free_pt(dev, vm->scratch_pt);
 +      free_scratch_page(dev, vm->scratch_page);
 +}
 +
  static void gen6_ppgtt_cleanup(struct i915_address_space *vm)
  {
        struct i915_hw_ppgtt *ppgtt =
        struct i915_page_table *pt;
        uint32_t pde;
  
 -
        drm_mm_remove_node(&ppgtt->node);
  
        gen6_for_all_pdes(pt, ppgtt, pde) {
 -              if (pt != ppgtt->scratch_pt)
 -                      unmap_and_free_pt(pt, ppgtt->base.dev);
 +              if (pt != vm->scratch_pt)
 +                      free_pt(ppgtt->base.dev, pt);
        }
  
 -      unmap_and_free_pt(ppgtt->scratch_pt, ppgtt->base.dev);
 -      unmap_and_free_pd(&ppgtt->pd, ppgtt->base.dev);
 +      gen6_free_scratch(vm);
  }
  
  static int gen6_ppgtt_allocate_page_directories(struct i915_hw_ppgtt *ppgtt)
  {
 +      struct i915_address_space *vm = &ppgtt->base;
        struct drm_device *dev = ppgtt->base.dev;
        struct drm_i915_private *dev_priv = dev->dev_private;
        bool retried = false;
         * size. We allocate at the top of the GTT to avoid fragmentation.
         */
        BUG_ON(!drm_mm_initialized(&dev_priv->gtt.base.mm));
 -      ppgtt->scratch_pt = alloc_pt_single(ppgtt->base.dev);
 -      if (IS_ERR(ppgtt->scratch_pt))
 -              return PTR_ERR(ppgtt->scratch_pt);
  
 -      gen6_initialize_pt(&ppgtt->base, ppgtt->scratch_pt);
 +      ret = gen6_init_scratch(vm);
 +      if (ret)
 +              return ret;
  
  alloc:
        ret = drm_mm_insert_node_in_range_generic(&dev_priv->gtt.base.mm,
        return 0;
  
  err_out:
 -      unmap_and_free_pt(ppgtt->scratch_pt, ppgtt->base.dev);
 +      gen6_free_scratch(vm);
        return ret;
  }
  
@@@ -1543,7 -1464,7 +1543,7 @@@ static void gen6_scratch_va_range(struc
        uint32_t pde, temp;
  
        gen6_for_each_pde(unused, &ppgtt->pd, start, length, temp, pde)
 -              ppgtt->pd.page_table[pde] = ppgtt->scratch_pt;
 +              ppgtt->pd.page_table[pde] = ppgtt->base.scratch_pt;
  }
  
  static int gen6_ppgtt_init(struct i915_hw_ppgtt *ppgtt)
        ppgtt->base.total = I915_PDES * GEN6_PTES * PAGE_SIZE;
        ppgtt->debug_dump = gen6_dump_ppgtt;
  
 -      ppgtt->pd.pd_offset =
 +      ppgtt->pd.base.ggtt_offset =
                ppgtt->node.start / PAGE_SIZE * sizeof(gen6_pte_t);
  
        ppgtt->pd_addr = (gen6_pte_t __iomem *)dev_priv->gtt.gsm +
 -              ppgtt->pd.pd_offset / sizeof(gen6_pte_t);
 +              ppgtt->pd.base.ggtt_offset / sizeof(gen6_pte_t);
  
        gen6_scratch_va_range(ppgtt, 0, ppgtt->base.total);
  
                         ppgtt->node.start / PAGE_SIZE);
  
        DRM_DEBUG("Adding PPGTT at offset %x\n",
 -                ppgtt->pd.pd_offset << 10);
 +                ppgtt->pd.base.ggtt_offset << 10);
  
        return 0;
  }
  
  static int __hw_ppgtt_init(struct drm_device *dev, struct i915_hw_ppgtt *ppgtt)
  {
 -      struct drm_i915_private *dev_priv = dev->dev_private;
 -
        ppgtt->base.dev = dev;
 -      ppgtt->base.scratch = dev_priv->gtt.base.scratch;
  
        if (INTEL_INFO(dev)->gen < 8)
                return gen6_ppgtt_init(ppgtt);
        else
                return gen8_ppgtt_init(ppgtt);
  }
 +
  int i915_ppgtt_init(struct drm_device *dev, struct i915_hw_ppgtt *ppgtt)
  {
        struct drm_i915_private *dev_priv = dev->dev_private;
  
  int i915_ppgtt_init_hw(struct drm_device *dev)
  {
 -      struct drm_i915_private *dev_priv = dev->dev_private;
 -      struct intel_engine_cs *ring;
 -      struct i915_hw_ppgtt *ppgtt = dev_priv->mm.aliasing_ppgtt;
 -      int i, ret = 0;
 -
        /* In the case of execlists, PPGTT is enabled by the context descriptor
         * and the PDPs are contained within the context itself.  We don't
         * need to do anything here. */
        else
                MISSING_CASE(INTEL_INFO(dev)->gen);
  
 -      if (ppgtt) {
 -              for_each_ring(ring, dev_priv, i) {
 -                      ret = ppgtt->switch_mm(ppgtt, ring);
 -                      if (ret != 0)
 -                              return ret;
 -              }
 -      }
 +      return 0;
 +}
  
 -      return ret;
 +int i915_ppgtt_init_ring(struct drm_i915_gem_request *req)
 +{
 +      struct drm_i915_private *dev_priv = req->ring->dev->dev_private;
 +      struct i915_hw_ppgtt *ppgtt = dev_priv->mm.aliasing_ppgtt;
 +
 +      if (i915.enable_execlists)
 +              return 0;
 +
 +      if (!ppgtt)
 +              return 0;
 +
 +      return ppgtt->switch_mm(ppgtt, req);
  }
 +
  struct i915_hw_ppgtt *
  i915_ppgtt_create(struct drm_device *dev, struct drm_i915_file_private *fpriv)
  {
@@@ -1922,7 -1843,7 +1922,7 @@@ static void gen8_ggtt_clear_range(struc
                 first_entry, num_entries, max_entries))
                num_entries = max_entries;
  
 -      scratch_pte = gen8_pte_encode(vm->scratch.addr,
 +      scratch_pte = gen8_pte_encode(px_dma(vm->scratch_page),
                                      I915_CACHE_LLC,
                                      use_scratch);
        for (i = 0; i < num_entries; i++)
@@@ -1948,8 -1869,7 +1948,8 @@@ static void gen6_ggtt_clear_range(struc
                 first_entry, num_entries, max_entries))
                num_entries = max_entries;
  
 -      scratch_pte = vm->pte_encode(vm->scratch.addr, I915_CACHE_LLC, use_scratch, 0);
 +      scratch_pte = vm->pte_encode(px_dma(vm->scratch_page),
 +                                   I915_CACHE_LLC, use_scratch, 0);
  
        for (i = 0; i < num_entries; i++)
                iowrite32(scratch_pte, &gtt_base[i]);
@@@ -2003,6 -1923,17 +2003,17 @@@ static int ggtt_bind_vma(struct i915_vm
                vma->vm->insert_entries(vma->vm, pages,
                                        vma->node.start,
                                        cache_level, pte_flags);
+               /* Note the inconsistency here is due to absence of the
+                * aliasing ppgtt on gen4 and earlier. Though we always
+                * request PIN_USER for execbuffer (translated to LOCAL_BIND),
+                * without the appgtt, we cannot honour that request and so
+                * must substitute it with a global binding. Since we do this
+                * behind the upper layers back, we need to explicitly set
+                * the bound flag ourselves.
+                */
+               vma->bound |= GLOBAL_BIND;
        }
  
        if (dev_priv->mm.aliasing_ppgtt && flags & LOCAL_BIND) {
@@@ -2174,7 -2105,7 +2185,7 @@@ static int i915_gem_setup_global_gtt(st
  void i915_gem_init_global_gtt(struct drm_device *dev)
  {
        struct drm_i915_private *dev_priv = dev->dev_private;
 -      unsigned long gtt_size, mappable_size;
 +      u64 gtt_size, mappable_size;
  
        gtt_size = dev_priv->gtt.base.total;
        mappable_size = dev_priv->gtt.mappable_end;
@@@ -2204,6 -2135,42 +2215,6 @@@ void i915_global_gtt_cleanup(struct drm
        vm->cleanup(vm);
  }
  
 -static int setup_scratch_page(struct drm_device *dev)
 -{
 -      struct drm_i915_private *dev_priv = dev->dev_private;
 -      struct page *page;
 -      dma_addr_t dma_addr;
 -
 -      page = alloc_page(GFP_KERNEL | GFP_DMA32 | __GFP_ZERO);
 -      if (page == NULL)
 -              return -ENOMEM;
 -      set_pages_uc(page, 1);
 -
 -#ifdef CONFIG_INTEL_IOMMU
 -      dma_addr = pci_map_page(dev->pdev, page, 0, PAGE_SIZE,
 -                              PCI_DMA_BIDIRECTIONAL);
 -      if (pci_dma_mapping_error(dev->pdev, dma_addr))
 -              return -EINVAL;
 -#else
 -      dma_addr = page_to_phys(page);
 -#endif
 -      dev_priv->gtt.base.scratch.page = page;
 -      dev_priv->gtt.base.scratch.addr = dma_addr;
 -
 -      return 0;
 -}
 -
 -static void teardown_scratch_page(struct drm_device *dev)
 -{
 -      struct drm_i915_private *dev_priv = dev->dev_private;
 -      struct page *page = dev_priv->gtt.base.scratch.page;
 -
 -      set_pages_wb(page, 1);
 -      pci_unmap_page(dev->pdev, dev_priv->gtt.base.scratch.addr,
 -                     PAGE_SIZE, PCI_DMA_BIDIRECTIONAL);
 -      __free_page(page);
 -}
 -
  static unsigned int gen6_get_total_gtt_size(u16 snb_gmch_ctl)
  {
        snb_gmch_ctl >>= SNB_GMCH_GGMS_SHIFT;
@@@ -2286,8 -2253,8 +2297,8 @@@ static int ggtt_probe_common(struct drm
                             size_t gtt_size)
  {
        struct drm_i915_private *dev_priv = dev->dev_private;
 +      struct i915_page_scratch *scratch_page;
        phys_addr_t gtt_phys_addr;
 -      int ret;
  
        /* For Modern GENs the PTEs and register space are split in the BAR */
        gtt_phys_addr = pci_resource_start(dev->pdev, 0) +
                return -ENOMEM;
        }
  
 -      ret = setup_scratch_page(dev);
 -      if (ret) {
 +      scratch_page = alloc_scratch_page(dev);
 +      if (IS_ERR(scratch_page)) {
                DRM_ERROR("Scratch setup failed\n");
                /* iounmap will also get called at remove, but meh */
                iounmap(dev_priv->gtt.gsm);
 +              return PTR_ERR(scratch_page);
        }
  
 -      return ret;
 +      dev_priv->gtt.base.scratch_page = scratch_page;
 +
 +      return 0;
  }
  
  /* The GGTT and PPGTT need a private PPAT setup in order to handle cacheability
@@@ -2396,13 -2360,13 +2407,13 @@@ static void chv_setup_private_ppat(stru
  }
  
  static int gen8_gmch_probe(struct drm_device *dev,
 -                         size_t *gtt_total,
 +                         u64 *gtt_total,
                           size_t *stolen,
                           phys_addr_t *mappable_base,
 -                         unsigned long *mappable_end)
 +                         u64 *mappable_end)
  {
        struct drm_i915_private *dev_priv = dev->dev_private;
 -      unsigned int gtt_size;
 +      u64 gtt_size;
        u16 snb_gmch_ctl;
        int ret;
  
  }
  
  static int gen6_gmch_probe(struct drm_device *dev,
 -                         size_t *gtt_total,
 +                         u64 *gtt_total,
                           size_t *stolen,
                           phys_addr_t *mappable_base,
 -                         unsigned long *mappable_end)
 +                         u64 *mappable_end)
  {
        struct drm_i915_private *dev_priv = dev->dev_private;
        unsigned int gtt_size;
         * a coarse sanity check.
         */
        if ((*mappable_end < (64<<20) || (*mappable_end > (512<<20)))) {
 -              DRM_ERROR("Unknown GMADR size (%lx)\n",
 +              DRM_ERROR("Unknown GMADR size (%llx)\n",
                          dev_priv->gtt.mappable_end);
                return -ENXIO;
        }
@@@ -2491,14 -2455,14 +2502,14 @@@ static void gen6_gmch_remove(struct i91
        struct i915_gtt *gtt = container_of(vm, struct i915_gtt, base);
  
        iounmap(gtt->gsm);
 -      teardown_scratch_page(vm->dev);
 +      free_scratch_page(vm->dev, vm->scratch_page);
  }
  
  static int i915_gmch_probe(struct drm_device *dev,
 -                         size_t *gtt_total,
 +                         u64 *gtt_total,
                           size_t *stolen,
                           phys_addr_t *mappable_base,
 -                         unsigned long *mappable_end)
 +                         u64 *mappable_end)
  {
        struct drm_i915_private *dev_priv = dev->dev_private;
        int ret;
@@@ -2555,17 -2519,17 +2566,17 @@@ int i915_gem_gtt_init(struct drm_devic
                dev_priv->gtt.base.cleanup = gen6_gmch_remove;
        }
  
 +      gtt->base.dev = dev;
 +
        ret = gtt->gtt_probe(dev, &gtt->base.total, &gtt->stolen_size,
                             &gtt->mappable_base, &gtt->mappable_end);
        if (ret)
                return ret;
  
 -      gtt->base.dev = dev;
 -
        /* GMADR is the PCI mmio aperture into the global GTT. */
 -      DRM_INFO("Memory usable by graphics device = %zdM\n",
 +      DRM_INFO("Memory usable by graphics device = %lluM\n",
                 gtt->base.total >> 20);
 -      DRM_DEBUG_DRIVER("GMADR size = %ldM\n", gtt->mappable_end >> 20);
 +      DRM_DEBUG_DRIVER("GMADR size = %lldM\n", gtt->mappable_end >> 20);
        DRM_DEBUG_DRIVER("GTT stolen size = %zdM\n", gtt->stolen_size >> 20);
  #ifdef CONFIG_INTEL_IOMMU
        if (intel_iommu_gfx_mapped)
@@@ -2742,17 -2706,30 +2753,17 @@@ static struct sg_table 
  intel_rotate_fb_obj_pages(struct i915_ggtt_view *ggtt_view,
                          struct drm_i915_gem_object *obj)
  {
 -      struct drm_device *dev = obj->base.dev;
        struct intel_rotation_info *rot_info = &ggtt_view->rotation_info;
 -      unsigned long size, pages, rot_pages;
 +      unsigned int size_pages = rot_info->size >> PAGE_SHIFT;
        struct sg_page_iter sg_iter;
        unsigned long i;
        dma_addr_t *page_addr_list;
        struct sg_table *st;
 -      unsigned int tile_pitch, tile_height;
 -      unsigned int width_pages, height_pages;
        int ret = -ENOMEM;
  
 -      pages = obj->base.size / PAGE_SIZE;
 -
 -      /* Calculate tiling geometry. */
 -      tile_height = intel_tile_height(dev, rot_info->pixel_format,
 -                                      rot_info->fb_modifier);
 -      tile_pitch = PAGE_SIZE / tile_height;
 -      width_pages = DIV_ROUND_UP(rot_info->pitch, tile_pitch);
 -      height_pages = DIV_ROUND_UP(rot_info->height, tile_height);
 -      rot_pages = width_pages * height_pages;
 -      size = rot_pages * PAGE_SIZE;
 -
        /* Allocate a temporary list of source pages for random access. */
 -      page_addr_list = drm_malloc_ab(pages, sizeof(dma_addr_t));
 +      page_addr_list = drm_malloc_ab(obj->base.size / PAGE_SIZE,
 +                                     sizeof(dma_addr_t));
        if (!page_addr_list)
                return ERR_PTR(ret);
  
        if (!st)
                goto err_st_alloc;
  
 -      ret = sg_alloc_table(st, rot_pages, GFP_KERNEL);
 +      ret = sg_alloc_table(st, size_pages, GFP_KERNEL);
        if (ret)
                goto err_sg_alloc;
  
        }
  
        /* Rotate the pages. */
 -      rotate_pages(page_addr_list, width_pages, height_pages, st);
 +      rotate_pages(page_addr_list,
 +                   rot_info->width_pages, rot_info->height_pages,
 +                   st);
  
        DRM_DEBUG_KMS(
 -                    "Created rotated page mapping for object size %lu (pitch=%u, height=%u, pixel_format=0x%x, %ux%u tiles, %lu pages).\n",
 -                    size, rot_info->pitch, rot_info->height,
 -                    rot_info->pixel_format, width_pages, height_pages,
 -                    rot_pages);
 +                    "Created rotated page mapping for object size %zu (pitch=%u, height=%u, pixel_format=0x%x, %ux%u tiles, %u pages).\n",
 +                    obj->base.size, rot_info->pitch, rot_info->height,
 +                    rot_info->pixel_format, rot_info->width_pages,
 +                    rot_info->height_pages, size_pages);
  
        drm_free_large(page_addr_list);
  
@@@ -2793,10 -2768,10 +2804,10 @@@ err_st_alloc
        drm_free_large(page_addr_list);
  
        DRM_DEBUG_KMS(
 -                    "Failed to create rotated mapping for object size %lu! (%d) (pitch=%u, height=%u, pixel_format=0x%x, %ux%u tiles, %lu pages)\n",
 -                    size, ret, rot_info->pitch, rot_info->height,
 -                    rot_info->pixel_format, width_pages, height_pages,
 -                    rot_pages);
 +                    "Failed to create rotated mapping for object size %zu! (%d) (pitch=%u, height=%u, pixel_format=0x%x, %ux%u tiles, %u pages)\n",
 +                    obj->base.size, ret, rot_info->pitch, rot_info->height,
 +                    rot_info->pixel_format, rot_info->width_pages,
 +                    rot_info->height_pages, size_pages);
        return ERR_PTR(ret);
  }
  
@@@ -2914,12 -2889,9 +2925,12 @@@ int i915_vma_bind(struct i915_vma *vma
                                    vma->node.size,
                                    VM_TO_TRACE_NAME(vma->vm));
  
 +              /* XXX: i915_vma_pin() will fix this +- hack */
 +              vma->pin_count++;
                ret = vma->vm->allocate_va_range(vma->vm,
                                                 vma->node.start,
                                                 vma->node.size);
 +              vma->pin_count--;
                if (ret)
                        return ret;
        }
@@@ -2944,10 -2916,9 +2955,10 @@@ size_
  i915_ggtt_view_size(struct drm_i915_gem_object *obj,
                    const struct i915_ggtt_view *view)
  {
 -      if (view->type == I915_GGTT_VIEW_NORMAL ||
 -          view->type == I915_GGTT_VIEW_ROTATED) {
 +      if (view->type == I915_GGTT_VIEW_NORMAL) {
                return obj->base.size;
 +      } else if (view->type == I915_GGTT_VIEW_ROTATED) {
 +              return view->rotation_info.size;
        } else if (view->type == I915_GGTT_VIEW_PARTIAL) {
                return view->params.partial.size << PAGE_SHIFT;
        } else {
index ac3eb566c9d259fa2d6b7db077a9c4faca9fc223,d19c9db5e18c9d57057ad78ffdbdfa1a65b861b4..8a6717cc265c6c0a062d8cae9d4dc966356fa028
  #include <drm/i915_drm.h>
  #include "i915_drv.h"
  
 -/** @file i915_gem_tiling.c
 - *
 - * Support for managing tiling state of buffer objects.
 - *
 - * The idea behind tiling is to increase cache hit rates by rearranging
 - * pixel data so that a group of pixel accesses are in the same cacheline.
 - * Performance improvement from doing this on the back/depth buffer are on
 - * the order of 30%.
 - *
 - * Intel architectures make this somewhat more complicated, though, by
 - * adjustments made to addressing of data when the memory is in interleaved
 - * mode (matched pairs of DIMMS) to improve memory bandwidth.
 - * For interleaved memory, the CPU sends every sequential 64 bytes
 - * to an alternate memory channel so it can get the bandwidth from both.
 - *
 - * The GPU also rearranges its accesses for increased bandwidth to interleaved
 - * memory, and it matches what the CPU does for non-tiled.  However, when tiled
 - * it does it a little differently, since one walks addresses not just in the
 - * X direction but also Y.  So, along with alternating channels when bit
 - * 6 of the address flips, it also alternates when other bits flip --  Bits 9
 - * (every 512 bytes, an X tile scanline) and 10 (every two X tile scanlines)
 - * are common to both the 915 and 965-class hardware.
 - *
 - * The CPU also sometimes XORs in higher bits as well, to improve
 - * bandwidth doing strided access like we do so frequently in graphics.  This
 - * is called "Channel XOR Randomization" in the MCH documentation.  The result
 - * is that the CPU is XORing in either bit 11 or bit 17 to bit 6 of its address
 - * decode.
 +/**
 + * DOC: buffer object tiling
   *
 - * All of this bit 6 XORing has an effect on our memory management,
 - * as we need to make sure that the 3d driver can correctly address object
 - * contents.
 + * i915_gem_set_tiling() and i915_gem_get_tiling() is the userspace interface to
 + * declare fence register requirements.
   *
 - * If we don't have interleaved memory, all tiling is safe and no swizzling is
 - * required.
 + * In principle GEM doesn't care at all about the internal data layout of an
 + * object, and hence it also doesn't care about tiling or swizzling. There's two
 + * exceptions:
   *
 - * When bit 17 is XORed in, we simply refuse to tile at all.  Bit
 - * 17 is not just a page offset, so as we page an objet out and back in,
 - * individual pages in it will have different bit 17 addresses, resulting in
 - * each 64 bytes being swapped with its neighbor!
 + * - For X and Y tiling the hardware provides detilers for CPU access, so called
 + *   fences. Since there's only a limited amount of them the kernel must manage
 + *   these, and therefore userspace must tell the kernel the object tiling if it
 + *   wants to use fences for detiling.
 + * - On gen3 and gen4 platforms have a swizzling pattern for tiled objects which
 + *   depends upon the physical page frame number. When swapping such objects the
 + *   page frame number might change and the kernel must be able to fix this up
 + *   and hence now the tiling. Note that on a subset of platforms with
 + *   asymmetric memory channel population the swizzling pattern changes in an
 + *   unknown way, and for those the kernel simply forbids swapping completely.
   *
 - * Otherwise, if interleaved, we have to tell the 3d driver what the address
 - * swizzling it needs to do is, since it's writing with the CPU to the pages
 - * (bit 6 and potentially bit 11 XORed in), and the GPU is reading from the
 - * pages (bit 6, 9, and 10 XORed in), resulting in a cumulative bit swizzling
 - * required by the CPU of XORing in bit 6, 9, 10, and potentially 11, in order
 - * to match what the GPU expects.
 - */
 -
 -/**
 - * Detects bit 6 swizzling of address lookup between IGD access and CPU
 - * access through main memory.
 + * Since neither of this applies for new tiling layouts on modern platforms like
 + * W, Ys and Yf tiling GEM only allows object tiling to be set to X or Y tiled.
 + * Anything else can be handled in userspace entirely without the kernel's
 + * invovlement.
   */
 -void
 -i915_gem_detect_bit_6_swizzle(struct drm_device *dev)
 -{
 -      struct drm_i915_private *dev_priv = dev->dev_private;
 -      uint32_t swizzle_x = I915_BIT_6_SWIZZLE_UNKNOWN;
 -      uint32_t swizzle_y = I915_BIT_6_SWIZZLE_UNKNOWN;
 -
 -      if (INTEL_INFO(dev)->gen >= 8 || IS_VALLEYVIEW(dev)) {
 -              /*
 -               * On BDW+, swizzling is not used. We leave the CPU memory
 -               * controller in charge of optimizing memory accesses without
 -               * the extra address manipulation GPU side.
 -               *
 -               * VLV and CHV don't have GPU swizzling.
 -               */
 -              swizzle_x = I915_BIT_6_SWIZZLE_NONE;
 -              swizzle_y = I915_BIT_6_SWIZZLE_NONE;
 -      } else if (INTEL_INFO(dev)->gen >= 6) {
 -              if (dev_priv->preserve_bios_swizzle) {
 -                      if (I915_READ(DISP_ARB_CTL) &
 -                          DISP_TILE_SURFACE_SWIZZLING) {
 -                              swizzle_x = I915_BIT_6_SWIZZLE_9_10;
 -                              swizzle_y = I915_BIT_6_SWIZZLE_9;
 -                      } else {
 -                              swizzle_x = I915_BIT_6_SWIZZLE_NONE;
 -                              swizzle_y = I915_BIT_6_SWIZZLE_NONE;
 -                      }
 -              } else {
 -                      uint32_t dimm_c0, dimm_c1;
 -                      dimm_c0 = I915_READ(MAD_DIMM_C0);
 -                      dimm_c1 = I915_READ(MAD_DIMM_C1);
 -                      dimm_c0 &= MAD_DIMM_A_SIZE_MASK | MAD_DIMM_B_SIZE_MASK;
 -                      dimm_c1 &= MAD_DIMM_A_SIZE_MASK | MAD_DIMM_B_SIZE_MASK;
 -                      /* Enable swizzling when the channels are populated
 -                       * with identically sized dimms. We don't need to check
 -                       * the 3rd channel because no cpu with gpu attached
 -                       * ships in that configuration. Also, swizzling only
 -                       * makes sense for 2 channels anyway. */
 -                      if (dimm_c0 == dimm_c1) {
 -                              swizzle_x = I915_BIT_6_SWIZZLE_9_10;
 -                              swizzle_y = I915_BIT_6_SWIZZLE_9;
 -                      } else {
 -                              swizzle_x = I915_BIT_6_SWIZZLE_NONE;
 -                              swizzle_y = I915_BIT_6_SWIZZLE_NONE;
 -                      }
 -              }
 -      } else if (IS_GEN5(dev)) {
 -              /* On Ironlake whatever DRAM config, GPU always do
 -               * same swizzling setup.
 -               */
 -              swizzle_x = I915_BIT_6_SWIZZLE_9_10;
 -              swizzle_y = I915_BIT_6_SWIZZLE_9;
 -      } else if (IS_GEN2(dev)) {
 -              /* As far as we know, the 865 doesn't have these bit 6
 -               * swizzling issues.
 -               */
 -              swizzle_x = I915_BIT_6_SWIZZLE_NONE;
 -              swizzle_y = I915_BIT_6_SWIZZLE_NONE;
 -      } else if (IS_MOBILE(dev) || (IS_GEN3(dev) && !IS_G33(dev))) {
 -              uint32_t dcc;
 -
 -              /* On 9xx chipsets, channel interleave by the CPU is
 -               * determined by DCC.  For single-channel, neither the CPU
 -               * nor the GPU do swizzling.  For dual channel interleaved,
 -               * the GPU's interleave is bit 9 and 10 for X tiled, and bit
 -               * 9 for Y tiled.  The CPU's interleave is independent, and
 -               * can be based on either bit 11 (haven't seen this yet) or
 -               * bit 17 (common).
 -               */
 -              dcc = I915_READ(DCC);
 -              switch (dcc & DCC_ADDRESSING_MODE_MASK) {
 -              case DCC_ADDRESSING_MODE_SINGLE_CHANNEL:
 -              case DCC_ADDRESSING_MODE_DUAL_CHANNEL_ASYMMETRIC:
 -                      swizzle_x = I915_BIT_6_SWIZZLE_NONE;
 -                      swizzle_y = I915_BIT_6_SWIZZLE_NONE;
 -                      break;
 -              case DCC_ADDRESSING_MODE_DUAL_CHANNEL_INTERLEAVED:
 -                      if (dcc & DCC_CHANNEL_XOR_DISABLE) {
 -                              /* This is the base swizzling by the GPU for
 -                               * tiled buffers.
 -                               */
 -                              swizzle_x = I915_BIT_6_SWIZZLE_9_10;
 -                              swizzle_y = I915_BIT_6_SWIZZLE_9;
 -                      } else if ((dcc & DCC_CHANNEL_XOR_BIT_17) == 0) {
 -                              /* Bit 11 swizzling by the CPU in addition. */
 -                              swizzle_x = I915_BIT_6_SWIZZLE_9_10_11;
 -                              swizzle_y = I915_BIT_6_SWIZZLE_9_11;
 -                      } else {
 -                              /* Bit 17 swizzling by the CPU in addition. */
 -                              swizzle_x = I915_BIT_6_SWIZZLE_9_10_17;
 -                              swizzle_y = I915_BIT_6_SWIZZLE_9_17;
 -                      }
 -                      break;
 -              }
 -
 -              /* check for L-shaped memory aka modified enhanced addressing */
 -              if (IS_GEN4(dev)) {
 -                      uint32_t ddc2 = I915_READ(DCC2);
 -
 -                      if (!(ddc2 & DCC2_MODIFIED_ENHANCED_DISABLE))
 -                              dev_priv->quirks |= QUIRK_PIN_SWIZZLED_PAGES;
 -              }
 -
 -              if (dcc == 0xffffffff) {
 -                      DRM_ERROR("Couldn't read from MCHBAR.  "
 -                                "Disabling tiling.\n");
 -                      swizzle_x = I915_BIT_6_SWIZZLE_UNKNOWN;
 -                      swizzle_y = I915_BIT_6_SWIZZLE_UNKNOWN;
 -              }
 -      } else {
 -              /* The 965, G33, and newer, have a very flexible memory
 -               * configuration.  It will enable dual-channel mode
 -               * (interleaving) on as much memory as it can, and the GPU
 -               * will additionally sometimes enable different bit 6
 -               * swizzling for tiled objects from the CPU.
 -               *
 -               * Here's what I found on the G965:
 -               *    slot fill         memory size  swizzling
 -               * 0A   0B   1A   1B    1-ch   2-ch
 -               * 512  0    0    0     512    0     O
 -               * 512  0    512  0     16     1008  X
 -               * 512  0    0    512   16     1008  X
 -               * 0    512  0    512   16     1008  X
 -               * 1024 1024 1024 0     2048   1024  O
 -               *
 -               * We could probably detect this based on either the DRB
 -               * matching, which was the case for the swizzling required in
 -               * the table above, or from the 1-ch value being less than
 -               * the minimum size of a rank.
 -               */
 -              if (I915_READ16(C0DRB3) != I915_READ16(C1DRB3)) {
 -                      swizzle_x = I915_BIT_6_SWIZZLE_NONE;
 -                      swizzle_y = I915_BIT_6_SWIZZLE_NONE;
 -              } else {
 -                      swizzle_x = I915_BIT_6_SWIZZLE_9_10;
 -                      swizzle_y = I915_BIT_6_SWIZZLE_9;
 -              }
 -      }
 -
 -      dev_priv->mm.bit_6_swizzle_x = swizzle_x;
 -      dev_priv->mm.bit_6_swizzle_y = swizzle_y;
 -}
  
  /* Check pitch constriants for all chips & tiling formats */
  static bool
@@@ -144,18 -313,8 +144,18 @@@ i915_gem_object_fence_ok(struct drm_i91
  }
  
  /**
 + * i915_gem_set_tiling - IOCTL handler to set tiling mode
 + * @dev: DRM device
 + * @data: data pointer for the ioctl
 + * @file: DRM file for the ioctl call
 + *
   * Sets the tiling mode of an object, returning the required swizzling of
   * bit 6 of addresses in the object.
 + *
 + * Called by the user via ioctl.
 + *
 + * Returns:
 + * Zero on success, negative errno on failure.
   */
  int
  i915_gem_set_tiling(struct drm_device *dev, void *data,
@@@ -273,17 -432,7 +273,17 @@@ err
  }
  
  /**
 + * i915_gem_get_tiling - IOCTL handler to get tiling mode
 + * @dev: DRM device
 + * @data: data pointer for the ioctl
 + * @file: DRM file for the ioctl call
 + *
   * Returns the current tiling mode and required bit 6 swizzling for the object.
 + *
 + * Called by the user via ioctl.
 + *
 + * Returns:
 + * Zero on success, negative errno on failure.
   */
  int
  i915_gem_get_tiling(struct drm_device *dev, void *data,
        }
  
        /* Hide bit 17 from the user -- see comment in i915_gem_set_tiling */
-       args->phys_swizzle_mode = args->swizzle_mode;
+       if (dev_priv->quirks & QUIRK_PIN_SWIZZLED_PAGES)
+               args->phys_swizzle_mode = I915_BIT_6_SWIZZLE_UNKNOWN;
+       else
+               args->phys_swizzle_mode = args->swizzle_mode;
        if (args->swizzle_mode == I915_BIT_6_SWIZZLE_9_17)
                args->swizzle_mode = I915_BIT_6_SWIZZLE_9;
        if (args->swizzle_mode == I915_BIT_6_SWIZZLE_9_10_17)
  
        return 0;
  }
 -
 -/**
 - * Swap every 64 bytes of this page around, to account for it having a new
 - * bit 17 of its physical address and therefore being interpreted differently
 - * by the GPU.
 - */
 -static void
 -i915_gem_swizzle_page(struct page *page)
 -{
 -      char temp[64];
 -      char *vaddr;
 -      int i;
 -
 -      vaddr = kmap(page);
 -
 -      for (i = 0; i < PAGE_SIZE; i += 128) {
 -              memcpy(temp, &vaddr[i], 64);
 -              memcpy(&vaddr[i], &vaddr[i + 64], 64);
 -              memcpy(&vaddr[i + 64], temp, 64);
 -      }
 -
 -      kunmap(page);
 -}
 -
 -void
 -i915_gem_object_do_bit_17_swizzle(struct drm_i915_gem_object *obj)
 -{
 -      struct sg_page_iter sg_iter;
 -      int i;
 -
 -      if (obj->bit_17 == NULL)
 -              return;
 -
 -      i = 0;
 -      for_each_sg_page(obj->pages->sgl, &sg_iter, obj->pages->nents, 0) {
 -              struct page *page = sg_page_iter_page(&sg_iter);
 -              char new_bit_17 = page_to_phys(page) >> 17;
 -              if ((new_bit_17 & 0x1) !=
 -                  (test_bit(i, obj->bit_17) != 0)) {
 -                      i915_gem_swizzle_page(page);
 -                      set_page_dirty(page);
 -              }
 -              i++;
 -      }
 -}
 -
 -void
 -i915_gem_object_save_bit_17_swizzle(struct drm_i915_gem_object *obj)
 -{
 -      struct sg_page_iter sg_iter;
 -      int page_count = obj->base.size >> PAGE_SHIFT;
 -      int i;
 -
 -      if (obj->bit_17 == NULL) {
 -              obj->bit_17 = kcalloc(BITS_TO_LONGS(page_count),
 -                                    sizeof(long), GFP_KERNEL);
 -              if (obj->bit_17 == NULL) {
 -                      DRM_ERROR("Failed to allocate memory for bit 17 "
 -                                "record\n");
 -                      return;
 -              }
 -      }
 -
 -      i = 0;
 -      for_each_sg_page(obj->pages->sgl, &sg_iter, obj->pages->nents, 0) {
 -              if (page_to_phys(sg_page_iter_page(&sg_iter)) & (1 << 17))
 -                      __set_bit(i, obj->bit_17);
 -              else
 -                      __clear_bit(i, obj->bit_17);
 -              i++;
 -      }
 -}
index 630d997c05a032b903d064a441e72eafc0aaf501,3dcd59e694db9e6f32c8e49ea04cbf21bbdc0ad8..990acc20771a6027ad2144edf864011e668604e6
@@@ -122,6 -122,42 +122,6 @@@ fill_detail_timing_data(struct drm_disp
        drm_mode_set_name(panel_fixed_mode);
  }
  
 -static bool
 -lvds_dvo_timing_equal_size(const struct lvds_dvo_timing *a,
 -                         const struct lvds_dvo_timing *b)
 -{
 -      if (a->hactive_hi != b->hactive_hi ||
 -          a->hactive_lo != b->hactive_lo)
 -              return false;
 -
 -      if (a->hsync_off_hi != b->hsync_off_hi ||
 -          a->hsync_off_lo != b->hsync_off_lo)
 -              return false;
 -
 -      if (a->hsync_pulse_width != b->hsync_pulse_width)
 -              return false;
 -
 -      if (a->hblank_hi != b->hblank_hi ||
 -          a->hblank_lo != b->hblank_lo)
 -              return false;
 -
 -      if (a->vactive_hi != b->vactive_hi ||
 -          a->vactive_lo != b->vactive_lo)
 -              return false;
 -
 -      if (a->vsync_off != b->vsync_off)
 -              return false;
 -
 -      if (a->vsync_pulse_width != b->vsync_pulse_width)
 -              return false;
 -
 -      if (a->vblank_hi != b->vblank_hi ||
 -          a->vblank_lo != b->vblank_lo)
 -              return false;
 -
 -      return true;
 -}
 -
  static const struct lvds_dvo_timing *
  get_lvds_dvo_timing(const struct bdb_lvds_lfp_data *lvds_lfp_data,
                    const struct bdb_lvds_lfp_data_ptrs *lvds_lfp_data_ptrs,
@@@ -177,7 -213,7 +177,7 @@@ parse_lfp_panel_data(struct drm_i915_pr
        const struct lvds_dvo_timing *panel_dvo_timing;
        const struct lvds_fp_timing *fp_timing;
        struct drm_display_mode *panel_fixed_mode;
 -      int i, downclock, drrs_mode;
 +      int drrs_mode;
  
        lvds_options = find_section(bdb, BDB_LVDS_OPTIONS);
        if (!lvds_options)
        DRM_DEBUG_KMS("Found panel mode in BIOS VBT tables:\n");
        drm_mode_debug_printmodeline(panel_fixed_mode);
  
 -      /*
 -       * Iterate over the LVDS panel timing info to find the lowest clock
 -       * for the native resolution.
 -       */
 -      downclock = panel_dvo_timing->clock;
 -      for (i = 0; i < 16; i++) {
 -              const struct lvds_dvo_timing *dvo_timing;
 -
 -              dvo_timing = get_lvds_dvo_timing(lvds_lfp_data,
 -                                               lvds_lfp_data_ptrs,
 -                                               i);
 -              if (lvds_dvo_timing_equal_size(dvo_timing, panel_dvo_timing) &&
 -                  dvo_timing->clock < downclock)
 -                      downclock = dvo_timing->clock;
 -      }
 -
 -      if (downclock < panel_dvo_timing->clock && i915.lvds_downclock) {
 -              dev_priv->lvds_downclock_avail = 1;
 -              dev_priv->lvds_downclock = downclock * 10;
 -              DRM_DEBUG_KMS("LVDS downclock is found in VBT. "
 -                            "Normal Clock %dKHz, downclock %dKHz\n",
 -                            panel_fixed_mode->clock, 10*downclock);
 -      }
 -
        fp_timing = get_lvds_fp_timing(bdb, lvds_lfp_data,
                                       lvds_lfp_data_ptrs,
                                       lvds_options->panel_type);
@@@ -968,28 -1028,13 +968,28 @@@ static void parse_ddi_port(struct drm_i
        }
  
        if (is_dp) {
 -              if (aux_channel == 0x40 && port != PORT_A)
 +              if (port == PORT_E) {
 +                      info->alternate_aux_channel = aux_channel;
 +                      /* if DDIE share aux channel with other port, then
 +                       * DP couldn't exist on the shared port. Otherwise
 +                       * they share the same aux channel and system
 +                       * couldn't communicate with them seperately. */
 +                      if (aux_channel == DP_AUX_A)
 +                              dev_priv->vbt.ddi_port_info[PORT_A].supports_dp = 0;
 +                      else if (aux_channel == DP_AUX_B)
 +                              dev_priv->vbt.ddi_port_info[PORT_B].supports_dp = 0;
 +                      else if (aux_channel == DP_AUX_C)
 +                              dev_priv->vbt.ddi_port_info[PORT_C].supports_dp = 0;
 +                      else if (aux_channel == DP_AUX_D)
 +                              dev_priv->vbt.ddi_port_info[PORT_D].supports_dp = 0;
 +              }
 +              else if (aux_channel == DP_AUX_A && port != PORT_A)
                        DRM_DEBUG_KMS("Unexpected AUX channel for port A\n");
 -              if (aux_channel == 0x10 && port != PORT_B)
 +              else if (aux_channel == DP_AUX_B && port != PORT_B)
                        DRM_DEBUG_KMS("Unexpected AUX channel for port B\n");
 -              if (aux_channel == 0x20 && port != PORT_C)
 +              else if (aux_channel == DP_AUX_C && port != PORT_C)
                        DRM_DEBUG_KMS("Unexpected AUX channel for port C\n");
 -              if (aux_channel == 0x30 && port != PORT_D)
 +              else if (aux_channel == DP_AUX_D && port != PORT_D)
                        DRM_DEBUG_KMS("Unexpected AUX channel for port D\n");
        }
  
@@@ -1030,15 -1075,34 +1030,34 @@@ parse_device_mapping(struct drm_i915_pr
        const union child_device_config *p_child;
        union child_device_config *child_dev_ptr;
        int i, child_device_num, count;
-       u16     block_size;
+       u8 expected_size;
+       u16 block_size;
  
        p_defs = find_section(bdb, BDB_GENERAL_DEFINITIONS);
        if (!p_defs) {
                DRM_DEBUG_KMS("No general definition block is found, no devices defined.\n");
                return;
        }
-       if (p_defs->child_dev_size < sizeof(*p_child)) {
-               DRM_ERROR("General definiton block child device size is too small.\n");
+       if (bdb->version < 195) {
+               expected_size = 33;
+       } else if (bdb->version == 195) {
+               expected_size = 37;
+       } else if (bdb->version <= 197) {
+               expected_size = 38;
+       } else {
+               expected_size = 38;
+               DRM_DEBUG_DRIVER("Expected child_device_config size for BDB version %u not known; assuming %u\n",
+                                expected_size, bdb->version);
+       }
+       if (expected_size > sizeof(*p_child)) {
+               DRM_ERROR("child_device_config cannot fit in p_child\n");
+               return;
+       }
+       if (p_defs->child_dev_size != expected_size) {
+               DRM_ERROR("Size mismatch; child_device_config size=%u (expected %u); bdb->version: %u\n",
+                         p_defs->child_dev_size, expected_size, bdb->version);
                return;
        }
        /* get the block size of general definitions */
  
                child_dev_ptr = dev_priv->vbt.child_dev + count;
                count++;
-               memcpy(child_dev_ptr, p_child, sizeof(*p_child));
+               memcpy(child_dev_ptr, p_child, p_defs->child_dev_size);
        }
        return;
  }
index 91208e1f2f623f189fea468118b3fefc4f3f0c2c,87476ff181ddbef0967d948c37119cfcbd758315..7f6d5fd7c2cf9cf91e2a6d87defbe559cbc19ea1
@@@ -86,6 -86,9 +86,6 @@@ static void i9xx_crtc_clock_get(struct 
  static void ironlake_pch_clock_get(struct intel_crtc *crtc,
                                   struct intel_crtc_state *pipe_config);
  
 -static int intel_set_mode(struct drm_crtc *crtc,
 -                        struct drm_atomic_state *state,
 -                        bool force_restore);
  static int intel_framebuffer_init(struct drm_device *dev,
                                  struct intel_framebuffer *ifb,
                                  struct drm_mode_fb_cmd2 *mode_cmd,
@@@ -102,13 -105,22 +102,13 @@@ static void vlv_prepare_pll(struct inte
                            const struct intel_crtc_state *pipe_config);
  static void chv_prepare_pll(struct intel_crtc *crtc,
                            const struct intel_crtc_state *pipe_config);
 -static void intel_begin_crtc_commit(struct drm_crtc *crtc);
 -static void intel_finish_crtc_commit(struct drm_crtc *crtc);
 +static void intel_begin_crtc_commit(struct drm_crtc *, struct drm_crtc_state *);
 +static void intel_finish_crtc_commit(struct drm_crtc *, struct drm_crtc_state *);
  static void skl_init_scalers(struct drm_device *dev, struct intel_crtc *intel_crtc,
        struct intel_crtc_state *crtc_state);
  static int i9xx_get_refclk(const struct intel_crtc_state *crtc_state,
                           int num_connectors);
 -static void intel_crtc_enable_planes(struct drm_crtc *crtc);
 -static void intel_crtc_disable_planes(struct drm_crtc *crtc);
 -
 -static struct intel_encoder *intel_find_encoder(struct intel_connector *connector, int pipe)
 -{
 -      if (!connector->mst_port)
 -              return connector->encoder;
 -      else
 -              return &connector->mst_port->mst_encoders[pipe]->base;
 -}
 +static void intel_modeset_setup_hw_state(struct drm_device *dev);
  
  typedef struct {
        int     min, max;
@@@ -401,7 -413,7 +401,7 @@@ static const intel_limit_t intel_limits
  static const intel_limit_t intel_limits_bxt = {
        /* FIXME: find real dot limits */
        .dot = { .min = 0, .max = INT_MAX },
 -      .vco = { .min = 4800000, .max = 6480000 },
 +      .vco = { .min = 4800000, .max = 6700000 },
        .n = { .min = 1, .max = 1 },
        .m1 = { .min = 2, .max = 2 },
        /* FIXME: find real m2 limits */
        .p2 = { .p2_slow = 1, .p2_fast = 20 },
  };
  
 -static void vlv_clock(int refclk, intel_clock_t *clock)
 +static bool
 +needs_modeset(struct drm_crtc_state *state)
  {
 -      clock->m = clock->m1 * clock->m2;
 -      clock->p = clock->p1 * clock->p2;
 -      if (WARN_ON(clock->n == 0 || clock->p == 0))
 -              return;
 -      clock->vco = DIV_ROUND_CLOSEST(refclk * clock->m, clock->n);
 -      clock->dot = DIV_ROUND_CLOSEST(clock->vco, clock->p);
 +      return drm_atomic_crtc_needs_modeset(state);
  }
  
  /**
@@@ -545,25 -561,15 +545,25 @@@ intel_limit(struct intel_crtc_state *cr
        return limit;
  }
  
 +/*
 + * Platform specific helpers to calculate the port PLL loopback- (clock.m),
 + * and post-divider (clock.p) values, pre- (clock.vco) and post-divided fast
 + * (clock.dot) clock rates. This fast dot clock is fed to the port's IO logic.
 + * The helpers' return value is the rate of the clock that is fed to the
 + * display engine's pipe which can be the above fast dot clock rate or a
 + * divided-down version of it.
 + */
  /* m1 is reserved as 0 in Pineview, n is a ring counter */
 -static void pineview_clock(int refclk, intel_clock_t *clock)
 +static int pnv_calc_dpll_params(int refclk, intel_clock_t *clock)
  {
        clock->m = clock->m2 + 2;
        clock->p = clock->p1 * clock->p2;
        if (WARN_ON(clock->n == 0 || clock->p == 0))
 -              return;
 +              return 0;
        clock->vco = DIV_ROUND_CLOSEST(refclk * clock->m, clock->n);
        clock->dot = DIV_ROUND_CLOSEST(clock->vco, clock->p);
 +
 +      return clock->dot;
  }
  
  static uint32_t i9xx_dpll_compute_m(struct dpll *dpll)
        return 5 * (dpll->m1 + 2) + (dpll->m2 + 2);
  }
  
 -static void i9xx_clock(int refclk, intel_clock_t *clock)
 +static int i9xx_calc_dpll_params(int refclk, intel_clock_t *clock)
  {
        clock->m = i9xx_dpll_compute_m(clock);
        clock->p = clock->p1 * clock->p2;
        if (WARN_ON(clock->n + 2 == 0 || clock->p == 0))
 -              return;
 +              return 0;
        clock->vco = DIV_ROUND_CLOSEST(refclk * clock->m, clock->n + 2);
        clock->dot = DIV_ROUND_CLOSEST(clock->vco, clock->p);
 +
 +      return clock->dot;
  }
  
 -static void chv_clock(int refclk, intel_clock_t *clock)
 +static int vlv_calc_dpll_params(int refclk, intel_clock_t *clock)
  {
        clock->m = clock->m1 * clock->m2;
        clock->p = clock->p1 * clock->p2;
        if (WARN_ON(clock->n == 0 || clock->p == 0))
 -              return;
 +              return 0;
 +      clock->vco = DIV_ROUND_CLOSEST(refclk * clock->m, clock->n);
 +      clock->dot = DIV_ROUND_CLOSEST(clock->vco, clock->p);
 +
 +      return clock->dot / 5;
 +}
 +
 +int chv_calc_dpll_params(int refclk, intel_clock_t *clock)
 +{
 +      clock->m = clock->m1 * clock->m2;
 +      clock->p = clock->p1 * clock->p2;
 +      if (WARN_ON(clock->n == 0 || clock->p == 0))
 +              return 0;
        clock->vco = DIV_ROUND_CLOSEST_ULL((uint64_t)refclk * clock->m,
                        clock->n << 22);
        clock->dot = DIV_ROUND_CLOSEST(clock->vco, clock->p);
 +
 +      return clock->dot / 5;
  }
  
  #define INTELPllInvalid(s)   do { /* DRM_DEBUG(s); */ return false; } while (0)
@@@ -649,12 -639,16 +649,12 @@@ static bool intel_PLL_is_valid(struct d
        return true;
  }
  
 -static bool
 -i9xx_find_best_dpll(const intel_limit_t *limit,
 -                  struct intel_crtc_state *crtc_state,
 -                  int target, int refclk, intel_clock_t *match_clock,
 -                  intel_clock_t *best_clock)
 +static int
 +i9xx_select_p2_div(const intel_limit_t *limit,
 +                 const struct intel_crtc_state *crtc_state,
 +                 int target)
  {
 -      struct intel_crtc *crtc = to_intel_crtc(crtc_state->base.crtc);
 -      struct drm_device *dev = crtc->base.dev;
 -      intel_clock_t clock;
 -      int err = target;
 +      struct drm_device *dev = crtc_state->base.crtc->dev;
  
        if (intel_pipe_will_have_type(crtc_state, INTEL_OUTPUT_LVDS)) {
                /*
                 * single/dual channel state, if we even can.
                 */
                if (intel_is_dual_link_lvds(dev))
 -                      clock.p2 = limit->p2.p2_fast;
 +                      return limit->p2.p2_fast;
                else
 -                      clock.p2 = limit->p2.p2_slow;
 +                      return limit->p2.p2_slow;
        } else {
                if (target < limit->p2.dot_limit)
 -                      clock.p2 = limit->p2.p2_slow;
 +                      return limit->p2.p2_slow;
                else
 -                      clock.p2 = limit->p2.p2_fast;
 +                      return limit->p2.p2_fast;
        }
 +}
 +
 +static bool
 +i9xx_find_best_dpll(const intel_limit_t *limit,
 +                  struct intel_crtc_state *crtc_state,
 +                  int target, int refclk, intel_clock_t *match_clock,
 +                  intel_clock_t *best_clock)
 +{
 +      struct drm_device *dev = crtc_state->base.crtc->dev;
 +      intel_clock_t clock;
 +      int err = target;
  
        memset(best_clock, 0, sizeof(*best_clock));
  
 +      clock.p2 = i9xx_select_p2_div(limit, crtc_state, target);
 +
        for (clock.m1 = limit->m1.min; clock.m1 <= limit->m1.max;
             clock.m1++) {
                for (clock.m2 = limit->m2.min;
                                        clock.p1 <= limit->p1.max; clock.p1++) {
                                        int this_err;
  
 -                                      i9xx_clock(refclk, &clock);
 +                                      i9xx_calc_dpll_params(refclk, &clock);
                                        if (!intel_PLL_is_valid(dev, limit,
                                                                &clock))
                                                continue;
@@@ -727,14 -708,30 +727,14 @@@ pnv_find_best_dpll(const intel_limit_t 
                   int target, int refclk, intel_clock_t *match_clock,
                   intel_clock_t *best_clock)
  {
 -      struct intel_crtc *crtc = to_intel_crtc(crtc_state->base.crtc);
 -      struct drm_device *dev = crtc->base.dev;
 +      struct drm_device *dev = crtc_state->base.crtc->dev;
        intel_clock_t clock;
        int err = target;
  
 -      if (intel_pipe_will_have_type(crtc_state, INTEL_OUTPUT_LVDS)) {
 -              /*
 -               * For LVDS just rely on its current settings for dual-channel.
 -               * We haven't figured out how to reliably set up different
 -               * single/dual channel state, if we even can.
 -               */
 -              if (intel_is_dual_link_lvds(dev))
 -                      clock.p2 = limit->p2.p2_fast;
 -              else
 -                      clock.p2 = limit->p2.p2_slow;
 -      } else {
 -              if (target < limit->p2.dot_limit)
 -                      clock.p2 = limit->p2.p2_slow;
 -              else
 -                      clock.p2 = limit->p2.p2_fast;
 -      }
 -
        memset(best_clock, 0, sizeof(*best_clock));
  
 +      clock.p2 = i9xx_select_p2_div(limit, crtc_state, target);
 +
        for (clock.m1 = limit->m1.min; clock.m1 <= limit->m1.max;
             clock.m1++) {
                for (clock.m2 = limit->m2.min;
                                        clock.p1 <= limit->p1.max; clock.p1++) {
                                        int this_err;
  
 -                                      pineview_clock(refclk, &clock);
 +                                      pnv_calc_dpll_params(refclk, &clock);
                                        if (!intel_PLL_is_valid(dev, limit,
                                                                &clock))
                                                continue;
@@@ -772,17 -769,28 +772,17 @@@ g4x_find_best_dpll(const intel_limit_t 
                   int target, int refclk, intel_clock_t *match_clock,
                   intel_clock_t *best_clock)
  {
 -      struct intel_crtc *crtc = to_intel_crtc(crtc_state->base.crtc);
 -      struct drm_device *dev = crtc->base.dev;
 +      struct drm_device *dev = crtc_state->base.crtc->dev;
        intel_clock_t clock;
        int max_n;
 -      bool found;
 +      bool found = false;
        /* approximately equals target * 0.00585 */
        int err_most = (target >> 8) + (target >> 9);
 -      found = false;
 -
 -      if (intel_pipe_will_have_type(crtc_state, INTEL_OUTPUT_LVDS)) {
 -              if (intel_is_dual_link_lvds(dev))
 -                      clock.p2 = limit->p2.p2_fast;
 -              else
 -                      clock.p2 = limit->p2.p2_slow;
 -      } else {
 -              if (target < limit->p2.dot_limit)
 -                      clock.p2 = limit->p2.p2_slow;
 -              else
 -                      clock.p2 = limit->p2.p2_fast;
 -      }
  
        memset(best_clock, 0, sizeof(*best_clock));
 +
 +      clock.p2 = i9xx_select_p2_div(limit, crtc_state, target);
 +
        max_n = limit->n.max;
        /* based on hardware requirement, prefer smaller n to precision */
        for (clock.n = limit->n.min; clock.n <= max_n; clock.n++) {
                                     clock.p1 >= limit->p1.min; clock.p1--) {
                                        int this_err;
  
 -                                      i9xx_clock(refclk, &clock);
 +                                      i9xx_calc_dpll_params(refclk, &clock);
                                        if (!intel_PLL_is_valid(dev, limit,
                                                                &clock))
                                                continue;
@@@ -885,7 -893,7 +885,7 @@@ vlv_find_best_dpll(const intel_limit_t 
                                        clock.m2 = DIV_ROUND_CLOSEST(target * clock.p * clock.n,
                                                                     refclk * clock.m1);
  
 -                                      vlv_clock(refclk, &clock);
 +                                      vlv_calc_dpll_params(refclk, &clock);
  
                                        if (!intel_PLL_is_valid(dev, limit,
                                                                &clock))
@@@ -948,7 -956,7 +948,7 @@@ chv_find_best_dpll(const intel_limit_t 
  
                        clock.m2 = m2;
  
 -                      chv_clock(refclk, &clock);
 +                      chv_calc_dpll_params(refclk, &clock);
  
                        if (!intel_PLL_is_valid(dev, limit, &clock))
                                continue;
@@@ -1018,7 -1026,7 +1018,7 @@@ static bool pipe_dsl_stopped(struct drm
                line_mask = DSL_LINEMASK_GEN3;
  
        line1 = I915_READ(reg) & line_mask;
 -      mdelay(5);
 +      msleep(5);
        line2 = I915_READ(reg) & line_mask;
  
        return line1 == line2;
@@@ -1686,7 -1694,7 +1686,7 @@@ static int intel_num_dvo_pipes(struct d
        int count = 0;
  
        for_each_intel_crtc(dev, crtc)
 -              count += crtc->active &&
 +              count += crtc->base.state->active &&
                        intel_pipe_has_type(crtc, INTEL_OUTPUT_DVO);
  
        return count;
@@@ -1767,7 -1775,7 +1767,7 @@@ static void i9xx_disable_pll(struct int
        /* Disable DVO 2x clock on both PLLs if necessary */
        if (IS_I830(dev) &&
            intel_pipe_has_type(crtc, INTEL_OUTPUT_DVO) &&
 -          intel_num_dvo_pipes(dev) == 1) {
 +          !intel_num_dvo_pipes(dev)) {
                I915_WRITE(DPLL(PIPE_B),
                           I915_READ(DPLL(PIPE_B)) & ~DPLL_DVO_2X_MODE);
                I915_WRITE(DPLL(PIPE_A),
        /* Make sure the pipe isn't still relying on us */
        assert_pipe_disabled(dev_priv, pipe);
  
 -      I915_WRITE(DPLL(pipe), 0);
 +      I915_WRITE(DPLL(pipe), DPLL_VGA_MODE_DIS);
        POSTING_READ(DPLL(pipe));
  }
  
  static void vlv_disable_pll(struct drm_i915_private *dev_priv, enum pipe pipe)
  {
 -      u32 val = 0;
 +      u32 val;
  
        /* Make sure the pipe isn't still relying on us */
        assert_pipe_disabled(dev_priv, pipe);
         * Leave integrated clock source and reference clock enabled for pipe B.
         * The latter is needed for VGA hotplug / manual detection.
         */
 +      val = DPLL_VGA_MODE_DIS;
        if (pipe == PIPE_B)
 -              val = DPLL_INTEGRATED_CRI_CLK_VLV | DPLL_REFA_CLK_ENABLE_VLV;
 +              val = DPLL_INTEGRATED_CRI_CLK_VLV | DPLL_REF_CLK_ENABLE_VLV;
        I915_WRITE(DPLL(pipe), val);
        POSTING_READ(DPLL(pipe));
  
@@@ -1814,8 -1821,7 +1814,8 @@@ static void chv_disable_pll(struct drm_
        assert_pipe_disabled(dev_priv, pipe);
  
        /* Set PLL en = 0 */
 -      val = DPLL_SSC_REF_CLOCK_CHV | DPLL_REFA_CLK_ENABLE_VLV;
 +      val = DPLL_SSC_REF_CLK_CHV |
 +              DPLL_REF_CLK_ENABLE_VLV | DPLL_VGA_MODE_DIS;
        if (pipe != PIPE_A)
                val |= DPLL_INTEGRATED_CRI_CLK_VLV;
        I915_WRITE(DPLL(pipe), val);
@@@ -1936,13 -1942,11 +1936,13 @@@ static void intel_disable_shared_dpll(s
        struct intel_shared_dpll *pll = intel_crtc_to_shared_dpll(crtc);
  
        /* PCH only available on ILK+ */
 -      BUG_ON(INTEL_INFO(dev)->gen < 5);
 -      if (WARN_ON(pll == NULL))
 -             return;
 +      if (INTEL_INFO(dev)->gen < 5)
 +              return;
  
 -      if (WARN_ON(pll->config.crtc_mask == 0))
 +      if (pll == NULL)
 +              return;
 +
 +      if (WARN_ON(!(pll->config.crtc_mask & (1 << drm_crtc_index(&crtc->base)))))
                return;
  
        DRM_DEBUG_KMS("disable %s (active %d, on? %d) for crtc %d\n",
@@@ -2000,15 -2004,11 +2000,15 @@@ static void ironlake_enable_pch_transco
  
        if (HAS_PCH_IBX(dev_priv->dev)) {
                /*
 -               * make the BPC in transcoder be consistent with
 -               * that in pipeconf reg.
 +               * Make the BPC in transcoder be consistent with
 +               * that in pipeconf reg. For HDMI we must use 8bpc
 +               * here for both 8bpc and 12bpc.
                 */
                val &= ~PIPECONF_BPC_MASK;
 -              val |= pipeconf_val & PIPECONF_BPC_MASK;
 +              if (intel_pipe_has_type(intel_crtc, INTEL_OUTPUT_HDMI))
 +                      val |= PIPECONF_8BPC;
 +              else
 +                      val |= pipeconf_val & PIPECONF_BPC_MASK;
        }
  
        val &= ~TRANS_INTERLACE_MASK;
@@@ -2122,8 -2122,6 +2122,8 @@@ static void intel_enable_pipe(struct in
        int reg;
        u32 val;
  
 +      DRM_DEBUG_KMS("enabling pipe %c\n", pipe_name(pipe));
 +
        assert_planes_disabled(dev_priv, pipe);
        assert_cursor_disabled(dev_priv, pipe);
        assert_sprites_disabled(dev_priv, pipe);
@@@ -2183,8 -2181,6 +2183,8 @@@ static void intel_disable_pipe(struct i
        int reg;
        u32 val;
  
 +      DRM_DEBUG_KMS("disabling pipe %c\n", pipe_name(pipe));
 +
        /*
         * Make sure planes won't keep trying to pump pixels to us,
         * or we might hang the display.
                intel_wait_for_pipe_off(crtc);
  }
  
 -/**
 - * intel_enable_primary_hw_plane - enable the primary plane on a given pipe
 - * @plane:  plane to be enabled
 - * @crtc: crtc for the plane
 - *
 - * Enable @plane on @crtc, making sure that the pipe is running first.
 - */
 -static void intel_enable_primary_hw_plane(struct drm_plane *plane,
 -                                        struct drm_crtc *crtc)
 -{
 -      struct drm_device *dev = plane->dev;
 -      struct drm_i915_private *dev_priv = dev->dev_private;
 -      struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
 -
 -      /* If the pipe isn't enabled, we can't pump pixels and may hang */
 -      assert_pipe_enabled(dev_priv, intel_crtc->pipe);
 -      to_intel_plane_state(plane->state)->visible = true;
 -
 -      dev_priv->display.update_primary_plane(crtc, plane->fb,
 -                                             crtc->x, crtc->y);
 -}
 -
  static bool need_vtd_wa(struct drm_device *dev)
  {
  #ifdef CONFIG_INTEL_IOMMU
@@@ -2284,7 -2302,6 +2284,7 @@@ intel_fill_fb_ggtt_view(struct i915_ggt
                        const struct drm_plane_state *plane_state)
  {
        struct intel_rotation_info *info = &view->rotation_info;
 +      unsigned int tile_height, tile_pitch;
  
        *view = i915_ggtt_view_normal;
  
        info->pitch = fb->pitches[0];
        info->fb_modifier = fb->modifier[0];
  
 +      tile_height = intel_tile_height(fb->dev, fb->pixel_format,
 +                                      fb->modifier[0]);
 +      tile_pitch = PAGE_SIZE / tile_height;
 +      info->width_pages = DIV_ROUND_UP(fb->pitches[0], tile_pitch);
 +      info->height_pages = DIV_ROUND_UP(fb->height, tile_height);
 +      info->size = info->width_pages * info->height_pages * PAGE_SIZE;
 +
        return 0;
  }
  
 +static unsigned int intel_linear_alignment(struct drm_i915_private *dev_priv)
 +{
 +      if (INTEL_INFO(dev_priv)->gen >= 9)
 +              return 256 * 1024;
 +      else if (IS_BROADWATER(dev_priv) || IS_CRESTLINE(dev_priv) ||
 +               IS_VALLEYVIEW(dev_priv))
 +              return 128 * 1024;
 +      else if (INTEL_INFO(dev_priv)->gen >= 4)
 +              return 4 * 1024;
 +      else
 +              return 0;
 +}
 +
  int
  intel_pin_and_fence_fb_obj(struct drm_plane *plane,
                           struct drm_framebuffer *fb,
                           const struct drm_plane_state *plane_state,
 -                         struct intel_engine_cs *pipelined)
 +                         struct intel_engine_cs *pipelined,
 +                         struct drm_i915_gem_request **pipelined_request)
  {
        struct drm_device *dev = fb->dev;
        struct drm_i915_private *dev_priv = dev->dev_private;
  
        switch (fb->modifier[0]) {
        case DRM_FORMAT_MOD_NONE:
 -              if (INTEL_INFO(dev)->gen >= 9)
 -                      alignment = 256 * 1024;
 -              else if (IS_BROADWATER(dev) || IS_CRESTLINE(dev))
 -                      alignment = 128 * 1024;
 -              else if (INTEL_INFO(dev)->gen >= 4)
 -                      alignment = 4 * 1024;
 -              else
 -                      alignment = 64 * 1024;
 +              alignment = intel_linear_alignment(dev_priv);
                break;
        case I915_FORMAT_MOD_X_TILED:
                if (INTEL_INFO(dev)->gen >= 9)
  
        dev_priv->mm.interruptible = false;
        ret = i915_gem_object_pin_to_display_plane(obj, alignment, pipelined,
 -                                                 &view);
 +                                                 pipelined_request, &view);
        if (ret)
                goto err_interruptible;
  
         * a fence as the cost is not that onerous.
         */
        ret = i915_gem_object_get_fence(obj);
 -      if (ret)
 +      if (ret == -EDEADLK) {
 +              /*
 +               * -EDEADLK means there are no free fences
 +               * no pending flips.
 +               *
 +               * This is propagated to atomic, but it uses
 +               * -EDEADLK to force a locking recovery, so
 +               * change the returned error to -EBUSY.
 +               */
 +              ret = -EBUSY;
 +              goto err_unpin;
 +      } else if (ret)
                goto err_unpin;
  
        i915_gem_object_pin_fence(obj);
@@@ -2443,8 -2435,7 +2443,8 @@@ static void intel_unpin_fb_obj(struct d
  
  /* Computes the linear offset to the base tile and adjusts x, y. bytes per pixel
   * is assumed to be a power-of-two. */
 -unsigned long intel_gen4_compute_page_offset(int *x, int *y,
 +unsigned long intel_gen4_compute_page_offset(struct drm_i915_private *dev_priv,
 +                                           int *x, int *y,
                                             unsigned int tiling_mode,
                                             unsigned int cpp,
                                             unsigned int pitch)
  
                return tile_rows * pitch * 8 + tiles * 4096;
        } else {
 +              unsigned int alignment = intel_linear_alignment(dev_priv) - 1;
                unsigned int offset;
  
                offset = *y * pitch + *x * cpp;
 -              *y = 0;
 -              *x = (offset & 4095) / cpp;
 -              return offset & -4096;
 +              *y = (offset & alignment) / pitch;
 +              *x = ((offset & alignment) - *y * pitch) / cpp;
 +              return offset & ~alignment;
        }
  }
  
@@@ -2593,7 -2583,6 +2593,7 @@@ intel_find_initial_plane_obj(struct int
        struct intel_crtc *i;
        struct drm_i915_gem_object *obj;
        struct drm_plane *primary = intel_crtc->base.primary;
 +      struct drm_plane_state *plane_state = primary->state;
        struct drm_framebuffer *fb;
  
        if (!plane_config->fb)
        return;
  
  valid_fb:
 +      plane_state->src_x = plane_state->src_y = 0;
 +      plane_state->src_w = fb->width << 16;
 +      plane_state->src_h = fb->height << 16;
 +
 +      plane_state->crtc_x = plane_state->src_y = 0;
 +      plane_state->crtc_w = fb->width;
 +      plane_state->crtc_h = fb->height;
 +
        obj = intel_fb_obj(fb);
        if (obj->tiling_mode != I915_TILING_NONE)
                dev_priv->preserve_bios_swizzle = true;
  
 -      primary->fb = fb;
 -      primary->state->crtc = &intel_crtc->base;
 -      primary->crtc = &intel_crtc->base;
 -      update_state_fb(primary);
 -      obj->frontbuffer_bits |= INTEL_FRONTBUFFER_PRIMARY(intel_crtc->pipe);
 +      drm_framebuffer_reference(fb);
 +      primary->fb = primary->state->fb = fb;
 +      primary->crtc = primary->state->crtc = &intel_crtc->base;
 +      intel_crtc->base.state->plane_mask |= (1 << drm_plane_index(primary));
 +      obj->frontbuffer_bits |= to_intel_plane(primary)->frontbuffer_bit;
  }
  
  static void i9xx_update_primary_plane(struct drm_crtc *crtc,
  
        if (INTEL_INFO(dev)->gen >= 4) {
                intel_crtc->dspaddr_offset =
 -                      intel_gen4_compute_page_offset(&x, &y, obj->tiling_mode,
 +                      intel_gen4_compute_page_offset(dev_priv,
 +                                                     &x, &y, obj->tiling_mode,
                                                       pixel_size,
                                                       fb->pitches[0]);
                linear_offset -= intel_crtc->dspaddr_offset;
@@@ -2846,8 -2826,7 +2846,8 @@@ static void ironlake_update_primary_pla
  
        linear_offset = y * fb->pitches[0] + x * pixel_size;
        intel_crtc->dspaddr_offset =
 -              intel_gen4_compute_page_offset(&x, &y, obj->tiling_mode,
 +              intel_gen4_compute_page_offset(dev_priv,
 +                                             &x, &y, obj->tiling_mode,
                                               pixel_size,
                                               fb->pitches[0]);
        linear_offset -= intel_crtc->dspaddr_offset;
@@@ -2925,32 -2904,32 +2925,32 @@@ unsigned long intel_plane_obj_offset(st
        return i915_gem_obj_ggtt_offset_view(obj, view);
  }
  
 +static void skl_detach_scaler(struct intel_crtc *intel_crtc, int id)
 +{
 +      struct drm_device *dev = intel_crtc->base.dev;
 +      struct drm_i915_private *dev_priv = dev->dev_private;
 +
 +      I915_WRITE(SKL_PS_CTRL(intel_crtc->pipe, id), 0);
 +      I915_WRITE(SKL_PS_WIN_POS(intel_crtc->pipe, id), 0);
 +      I915_WRITE(SKL_PS_WIN_SZ(intel_crtc->pipe, id), 0);
 +      DRM_DEBUG_KMS("CRTC:%d Disabled scaler id %u.%u\n",
 +              intel_crtc->base.base.id, intel_crtc->pipe, id);
 +}
 +
  /*
   * This function detaches (aka. unbinds) unused scalers in hardware
   */
 -void skl_detach_scalers(struct intel_crtc *intel_crtc)
 +static void skl_detach_scalers(struct intel_crtc *intel_crtc)
  {
 -      struct drm_device *dev;
 -      struct drm_i915_private *dev_priv;
        struct intel_crtc_scaler_state *scaler_state;
        int i;
  
 -      if (!intel_crtc || !intel_crtc->config)
 -              return;
 -
 -      dev = intel_crtc->base.dev;
 -      dev_priv = dev->dev_private;
        scaler_state = &intel_crtc->config->scaler_state;
  
        /* loop through and disable scalers that aren't in use */
        for (i = 0; i < intel_crtc->num_scalers; i++) {
 -              if (!scaler_state->scalers[i].in_use) {
 -                      I915_WRITE(SKL_PS_CTRL(intel_crtc->pipe, i), 0);
 -                      I915_WRITE(SKL_PS_WIN_POS(intel_crtc->pipe, i), 0);
 -                      I915_WRITE(SKL_PS_WIN_SZ(intel_crtc->pipe, i), 0);
 -                      DRM_DEBUG_KMS("CRTC:%d Disabled scaler id %u.%u\n",
 -                              intel_crtc->base.base.id, intel_crtc->pipe, i);
 -              }
 +              if (!scaler_state->scalers[i].in_use)
 +                      skl_detach_scaler(intel_crtc, i);
        }
  }
  
@@@ -3153,8 -3132,8 +3153,8 @@@ intel_pipe_set_base_atomic(struct drm_c
        struct drm_device *dev = crtc->dev;
        struct drm_i915_private *dev_priv = dev->dev_private;
  
 -      if (dev_priv->display.disable_fbc)
 -              dev_priv->display.disable_fbc(dev);
 +      if (dev_priv->fbc.disable_fbc)
 +              dev_priv->fbc.disable_fbc(dev_priv);
  
        dev_priv->display.update_primary_plane(crtc, fb, x, y);
  
@@@ -3197,8 -3176,24 +3197,8 @@@ static void intel_update_primary_planes
        }
  }
  
 -void intel_crtc_reset(struct intel_crtc *crtc)
 -{
 -      struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
 -
 -      if (!crtc->active)
 -              return;
 -
 -      intel_crtc_disable_planes(&crtc->base);
 -      dev_priv->display.crtc_disable(&crtc->base);
 -      dev_priv->display.crtc_enable(&crtc->base);
 -      intel_crtc_enable_planes(&crtc->base);
 -}
 -
  void intel_prepare_reset(struct drm_device *dev)
  {
 -      struct drm_i915_private *dev_priv = to_i915(dev);
 -      struct intel_crtc *crtc;
 -
        /* no reset support for gen2 */
        if (IS_GEN2(dev))
                return;
                return;
  
        drm_modeset_lock_all(dev);
 -
        /*
         * Disabling the crtcs gracefully seems nicer. Also the
         * g33 docs say we should at least disable all the planes.
         */
 -      for_each_intel_crtc(dev, crtc) {
 -              if (!crtc->active)
 -                      continue;
 -
 -              intel_crtc_disable_planes(&crtc->base);
 -              dev_priv->display.crtc_disable(&crtc->base);
 -      }
 +      intel_display_suspend(dev);
  }
  
  void intel_finish_reset(struct drm_device *dev)
                dev_priv->display.hpd_irq_setup(dev);
        spin_unlock_irq(&dev_priv->irq_lock);
  
 -      intel_modeset_setup_hw_state(dev, true);
 +      intel_display_resume(dev);
  
        intel_hpd_init(dev_priv);
  
@@@ -4198,16 -4200,34 +4198,16 @@@ static void lpt_pch_enable(struct drm_c
        lpt_enable_pch_transcoder(dev_priv, cpu_transcoder);
  }
  
 -void intel_put_shared_dpll(struct intel_crtc *crtc)
 -{
 -      struct intel_shared_dpll *pll = intel_crtc_to_shared_dpll(crtc);
 -
 -      if (pll == NULL)
 -              return;
 -
 -      if (!(pll->config.crtc_mask & (1 << crtc->pipe))) {
 -              WARN(1, "bad %s crtc mask\n", pll->name);
 -              return;
 -      }
 -
 -      pll->config.crtc_mask &= ~(1 << crtc->pipe);
 -      if (pll->config.crtc_mask == 0) {
 -              WARN_ON(pll->on);
 -              WARN_ON(pll->active);
 -      }
 -
 -      crtc->config->shared_dpll = DPLL_ID_PRIVATE;
 -}
 -
  struct intel_shared_dpll *intel_get_shared_dpll(struct intel_crtc *crtc,
                                                struct intel_crtc_state *crtc_state)
  {
        struct drm_i915_private *dev_priv = crtc->base.dev->dev_private;
        struct intel_shared_dpll *pll;
 +      struct intel_shared_dpll_config *shared_dpll;
        enum intel_dpll_id i;
  
 +      shared_dpll = intel_atomic_get_shared_dpll_state(crtc_state->base.state);
 +
        if (HAS_PCH_IBX(dev_priv->dev)) {
                /* Ironlake PCH has a fixed PLL->PCH pipe mapping. */
                i = (enum intel_dpll_id) crtc->pipe;
                DRM_DEBUG_KMS("CRTC:%d using pre-allocated %s\n",
                              crtc->base.base.id, pll->name);
  
 -              WARN_ON(pll->new_config->crtc_mask);
 +              WARN_ON(shared_dpll[i].crtc_mask);
  
                goto found;
        }
                pll = &dev_priv->shared_dplls[i];
                DRM_DEBUG_KMS("CRTC:%d using pre-allocated %s\n",
                        crtc->base.base.id, pll->name);
 -              WARN_ON(pll->new_config->crtc_mask);
 +              WARN_ON(shared_dpll[i].crtc_mask);
  
                goto found;
        }
                pll = &dev_priv->shared_dplls[i];
  
                /* Only want to check enabled timings first */
 -              if (pll->new_config->crtc_mask == 0)
 +              if (shared_dpll[i].crtc_mask == 0)
                        continue;
  
                if (memcmp(&crtc_state->dpll_hw_state,
 -                         &pll->new_config->hw_state,
 -                         sizeof(pll->new_config->hw_state)) == 0) {
 +                         &shared_dpll[i].hw_state,
 +                         sizeof(crtc_state->dpll_hw_state)) == 0) {
                        DRM_DEBUG_KMS("CRTC:%d sharing existing %s (crtc mask 0x%08x, ative %d)\n",
                                      crtc->base.base.id, pll->name,
 -                                    pll->new_config->crtc_mask,
 +                                    shared_dpll[i].crtc_mask,
                                      pll->active);
                        goto found;
                }
        /* Ok no matching timings, maybe there's a free one? */
        for (i = 0; i < dev_priv->num_shared_dpll; i++) {
                pll = &dev_priv->shared_dplls[i];
 -              if (pll->new_config->crtc_mask == 0) {
 +              if (shared_dpll[i].crtc_mask == 0) {
                        DRM_DEBUG_KMS("CRTC:%d allocated %s\n",
                                      crtc->base.base.id, pll->name);
                        goto found;
        return NULL;
  
  found:
 -      if (pll->new_config->crtc_mask == 0)
 -              pll->new_config->hw_state = crtc_state->dpll_hw_state;
 +      if (shared_dpll[i].crtc_mask == 0)
 +              shared_dpll[i].hw_state =
 +                      crtc_state->dpll_hw_state;
  
        crtc_state->shared_dpll = i;
        DRM_DEBUG_DRIVER("using %s for pipe %c\n", pll->name,
                         pipe_name(crtc->pipe));
  
 -      pll->new_config->crtc_mask |= 1 << crtc->pipe;
 +      shared_dpll[i].crtc_mask |= 1 << crtc->pipe;
  
        return pll;
  }
  
 -/**
 - * intel_shared_dpll_start_config - start a new PLL staged config
 - * @dev_priv: DRM device
 - * @clear_pipes: mask of pipes that will have their PLLs freed
 - *
 - * Starts a new PLL staged config, copying the current config but
 - * releasing the references of pipes specified in clear_pipes.
 - */
 -static int intel_shared_dpll_start_config(struct drm_i915_private *dev_priv,
 -                                        unsigned clear_pipes)
 -{
 -      struct intel_shared_dpll *pll;
 -      enum intel_dpll_id i;
 -
 -      for (i = 0; i < dev_priv->num_shared_dpll; i++) {
 -              pll = &dev_priv->shared_dplls[i];
 -
 -              pll->new_config = kmemdup(&pll->config, sizeof pll->config,
 -                                        GFP_KERNEL);
 -              if (!pll->new_config)
 -                      goto cleanup;
 -
 -              pll->new_config->crtc_mask &= ~clear_pipes;
 -      }
 -
 -      return 0;
 -
 -cleanup:
 -      while (--i >= 0) {
 -              pll = &dev_priv->shared_dplls[i];
 -              kfree(pll->new_config);
 -              pll->new_config = NULL;
 -      }
 -
 -      return -ENOMEM;
 -}
 -
 -static void intel_shared_dpll_commit(struct drm_i915_private *dev_priv)
 +static void intel_shared_dpll_commit(struct drm_atomic_state *state)
  {
 +      struct drm_i915_private *dev_priv = to_i915(state->dev);
 +      struct intel_shared_dpll_config *shared_dpll;
        struct intel_shared_dpll *pll;
        enum intel_dpll_id i;
  
 -      for (i = 0; i < dev_priv->num_shared_dpll; i++) {
 -              pll = &dev_priv->shared_dplls[i];
 -
 -              WARN_ON(pll->new_config == &pll->config);
 -
 -              pll->config = *pll->new_config;
 -              kfree(pll->new_config);
 -              pll->new_config = NULL;
 -      }
 -}
 -
 -static void intel_shared_dpll_abort_config(struct drm_i915_private *dev_priv)
 -{
 -      struct intel_shared_dpll *pll;
 -      enum intel_dpll_id i;
 +      if (!to_intel_atomic_state(state)->dpll_set)
 +              return;
  
 +      shared_dpll = to_intel_atomic_state(state)->shared_dpll;
        for (i = 0; i < dev_priv->num_shared_dpll; i++) {
                pll = &dev_priv->shared_dplls[i];
 -
 -              WARN_ON(pll->new_config == &pll->config);
 -
 -              kfree(pll->new_config);
 -              pll->new_config = NULL;
 +              pll->config = shared_dpll[i];
        }
  }
  
@@@ -4316,16 -4386,62 +4316,16 @@@ static void cpt_verify_modeset(struct d
        }
  }
  
 -/**
 - * skl_update_scaler_users - Stages update to crtc's scaler state
 - * @intel_crtc: crtc
 - * @crtc_state: crtc_state
 - * @plane: plane (NULL indicates crtc is requesting update)
 - * @plane_state: plane's state
 - * @force_detach: request unconditional detachment of scaler
 - *
 - * This function updates scaler state for requested plane or crtc.
 - * To request scaler usage update for a plane, caller shall pass plane pointer.
 - * To request scaler usage update for crtc, caller shall pass plane pointer
 - * as NULL.
 - *
 - * Return
 - *     0 - scaler_usage updated successfully
 - *    error - requested scaling cannot be supported or other error condition
 - */
 -int
 -skl_update_scaler_users(
 -      struct intel_crtc *intel_crtc, struct intel_crtc_state *crtc_state,
 -      struct intel_plane *intel_plane, struct intel_plane_state *plane_state,
 -      int force_detach)
 +static int
 +skl_update_scaler(struct intel_crtc_state *crtc_state, bool force_detach,
 +                unsigned scaler_user, int *scaler_id, unsigned int rotation,
 +                int src_w, int src_h, int dst_w, int dst_h)
  {
 +      struct intel_crtc_scaler_state *scaler_state =
 +              &crtc_state->scaler_state;
 +      struct intel_crtc *intel_crtc =
 +              to_intel_crtc(crtc_state->base.crtc);
        int need_scaling;
 -      int idx;
 -      int src_w, src_h, dst_w, dst_h;
 -      int *scaler_id;
 -      struct drm_framebuffer *fb;
 -      struct intel_crtc_scaler_state *scaler_state;
 -      unsigned int rotation;
 -
 -      if (!intel_crtc || !crtc_state)
 -              return 0;
 -
 -      scaler_state = &crtc_state->scaler_state;
 -
 -      idx = intel_plane ? drm_plane_index(&intel_plane->base) : SKL_CRTC_INDEX;
 -      fb = intel_plane ? plane_state->base.fb : NULL;
 -
 -      if (intel_plane) {
 -              src_w = drm_rect_width(&plane_state->src) >> 16;
 -              src_h = drm_rect_height(&plane_state->src) >> 16;
 -              dst_w = drm_rect_width(&plane_state->dst);
 -              dst_h = drm_rect_height(&plane_state->dst);
 -              scaler_id = &plane_state->scaler_id;
 -              rotation = plane_state->base.rotation;
 -      } else {
 -              struct drm_display_mode *adjusted_mode =
 -                      &crtc_state->base.adjusted_mode;
 -              src_w = crtc_state->pipe_src_w;
 -              src_h = crtc_state->pipe_src_h;
 -              dst_w = adjusted_mode->hdisplay;
 -              dst_h = adjusted_mode->vdisplay;
 -              scaler_id = &scaler_state->scaler_id;
 -              rotation = DRM_ROTATE_0;
 -      }
  
        need_scaling = intel_rotation_90_or_270(rotation) ?
                (src_h != dst_w || src_w != dst_h):
         * update to free the scaler is done in plane/panel-fit programming.
         * For this purpose crtc/plane_state->scaler_id isn't reset here.
         */
 -      if (force_detach || !need_scaling || (intel_plane &&
 -              (!fb || !plane_state->visible))) {
 +      if (force_detach || !need_scaling) {
                if (*scaler_id >= 0) {
 -                      scaler_state->scaler_users &= ~(1 << idx);
 +                      scaler_state->scaler_users &= ~(1 << scaler_user);
                        scaler_state->scalers[*scaler_id].in_use = 0;
  
 -                      DRM_DEBUG_KMS("Staged freeing scaler id %d.%d from %s:%d "
 -                              "crtc_state = %p scaler_users = 0x%x\n",
 -                              intel_crtc->pipe, *scaler_id, intel_plane ? "PLANE" : "CRTC",
 -                              intel_plane ? intel_plane->base.base.id :
 -                              intel_crtc->base.base.id, crtc_state,
 +                      DRM_DEBUG_KMS("scaler_user index %u.%u: "
 +                              "Staged freeing scaler id %d scaler_users = 0x%x\n",
 +                              intel_crtc->pipe, scaler_user, *scaler_id,
                                scaler_state->scaler_users);
                        *scaler_id = -1;
                }
  
                src_w > SKL_MAX_SRC_W || src_h > SKL_MAX_SRC_H ||
                dst_w > SKL_MAX_DST_W || dst_h > SKL_MAX_DST_H) {
 -              DRM_DEBUG_KMS("%s:%d scaler_user index %u.%u: src %ux%u dst %ux%u "
 +              DRM_DEBUG_KMS("scaler_user index %u.%u: src %ux%u dst %ux%u "
                        "size is out of scaler range\n",
 -                      intel_plane ? "PLANE" : "CRTC",
 -                      intel_plane ? intel_plane->base.base.id : intel_crtc->base.base.id,
 -                      intel_crtc->pipe, idx, src_w, src_h, dst_w, dst_h);
 -              return -EINVAL;
 -      }
 -
 -      /* check colorkey */
 -      if (WARN_ON(intel_plane &&
 -              intel_plane->ckey.flags != I915_SET_COLORKEY_NONE)) {
 -              DRM_DEBUG_KMS("PLANE:%d scaling %ux%u->%ux%u not allowed with colorkey",
 -                      intel_plane->base.base.id, src_w, src_h, dst_w, dst_h);
 +                      intel_crtc->pipe, scaler_user, src_w, src_h, dst_w, dst_h);
                return -EINVAL;
        }
  
 -      /* Check src format */
 -      if (intel_plane) {
 -              switch (fb->pixel_format) {
 -              case DRM_FORMAT_RGB565:
 -              case DRM_FORMAT_XBGR8888:
 -              case DRM_FORMAT_XRGB8888:
 -              case DRM_FORMAT_ABGR8888:
 -              case DRM_FORMAT_ARGB8888:
 -              case DRM_FORMAT_XRGB2101010:
 -              case DRM_FORMAT_XBGR2101010:
 -              case DRM_FORMAT_YUYV:
 -              case DRM_FORMAT_YVYU:
 -              case DRM_FORMAT_UYVY:
 -              case DRM_FORMAT_VYUY:
 -                      break;
 -              default:
 -                      DRM_DEBUG_KMS("PLANE:%d FB:%d unsupported scaling format 0x%x\n",
 -                              intel_plane->base.base.id, fb->base.id, fb->pixel_format);
 -                      return -EINVAL;
 -              }
 -      }
 -
        /* mark this plane as a scaler user in crtc_state */
 -      scaler_state->scaler_users |= (1 << idx);
 -      DRM_DEBUG_KMS("%s:%d staged scaling request for %ux%u->%ux%u "
 -              "crtc_state = %p scaler_users = 0x%x\n",
 -              intel_plane ? "PLANE" : "CRTC",
 -              intel_plane ? intel_plane->base.base.id : intel_crtc->base.base.id,
 -              src_w, src_h, dst_w, dst_h, crtc_state, scaler_state->scaler_users);
 +      scaler_state->scaler_users |= (1 << scaler_user);
 +      DRM_DEBUG_KMS("scaler_user index %u.%u: "
 +              "staged scaling request for %ux%u->%ux%u scaler_users = 0x%x\n",
 +              intel_crtc->pipe, scaler_user, src_w, src_h, dst_w, dst_h,
 +              scaler_state->scaler_users);
 +
        return 0;
  }
  
 -static void skylake_pfit_update(struct intel_crtc *crtc, int enable)
 +/**
 + * skl_update_scaler_crtc - Stages update to scaler state for a given crtc.
 + *
 + * @state: crtc's scaler state
 + *
 + * Return
 + *     0 - scaler_usage updated successfully
 + *    error - requested scaling cannot be supported or other error condition
 + */
 +int skl_update_scaler_crtc(struct intel_crtc_state *state)
  {
 -      struct drm_device *dev = crtc->base.dev;
 -      struct drm_i915_private *dev_priv = dev->dev_private;
 -      int pipe = crtc->pipe;
 -      struct intel_crtc_scaler_state *scaler_state =
 -              &crtc->config->scaler_state;
 +      struct intel_crtc *intel_crtc = to_intel_crtc(state->base.crtc);
 +      struct drm_display_mode *adjusted_mode =
 +              &state->base.adjusted_mode;
  
 -      DRM_DEBUG_KMS("for crtc_state = %p\n", crtc->config);
 +      DRM_DEBUG_KMS("Updating scaler for [CRTC:%i] scaler_user index %u.%u\n",
 +                    intel_crtc->base.base.id, intel_crtc->pipe, SKL_CRTC_INDEX);
  
 -      /* To update pfit, first update scaler state */
 -      skl_update_scaler_users(crtc, crtc->config, NULL, NULL, !enable);
 -      intel_atomic_setup_scalers(crtc->base.dev, crtc, crtc->config);
 -      skl_detach_scalers(crtc);
 -      if (!enable)
 -              return;
 +      return skl_update_scaler(state, !state->base.active, SKL_CRTC_INDEX,
 +              &state->scaler_state.scaler_id, DRM_ROTATE_0,
 +              state->pipe_src_w, state->pipe_src_h,
 +              adjusted_mode->hdisplay, adjusted_mode->vdisplay);
 +}
 +
 +/**
 + * skl_update_scaler_plane - Stages update to scaler state for a given plane.
 + *
 + * @state: crtc's scaler state
 + * @plane_state: atomic plane state to update
 + *
 + * Return
 + *     0 - scaler_usage updated successfully
 + *    error - requested scaling cannot be supported or other error condition
 + */
 +static int skl_update_scaler_plane(struct intel_crtc_state *crtc_state,
 +                                 struct intel_plane_state *plane_state)
 +{
 +
 +      struct intel_crtc *intel_crtc = to_intel_crtc(crtc_state->base.crtc);
 +      struct intel_plane *intel_plane =
 +              to_intel_plane(plane_state->base.plane);
 +      struct drm_framebuffer *fb = plane_state->base.fb;
 +      int ret;
 +
 +      bool force_detach = !fb || !plane_state->visible;
 +
 +      DRM_DEBUG_KMS("Updating scaler for [PLANE:%d] scaler_user index %u.%u\n",
 +                    intel_plane->base.base.id, intel_crtc->pipe,
 +                    drm_plane_index(&intel_plane->base));
 +
 +      ret = skl_update_scaler(crtc_state, force_detach,
 +                              drm_plane_index(&intel_plane->base),
 +                              &plane_state->scaler_id,
 +                              plane_state->base.rotation,
 +                              drm_rect_width(&plane_state->src) >> 16,
 +                              drm_rect_height(&plane_state->src) >> 16,
 +                              drm_rect_width(&plane_state->dst),
 +                              drm_rect_height(&plane_state->dst));
 +
 +      if (ret || plane_state->scaler_id < 0)
 +              return ret;
 +
 +      /* check colorkey */
 +      if (plane_state->ckey.flags != I915_SET_COLORKEY_NONE) {
 +              DRM_DEBUG_KMS("[PLANE:%d] scaling with color key not allowed",
 +                            intel_plane->base.base.id);
 +              return -EINVAL;
 +      }
 +
 +      /* Check src format */
 +      switch (fb->pixel_format) {
 +      case DRM_FORMAT_RGB565:
 +      case DRM_FORMAT_XBGR8888:
 +      case DRM_FORMAT_XRGB8888:
 +      case DRM_FORMAT_ABGR8888:
 +      case DRM_FORMAT_ARGB8888:
 +      case DRM_FORMAT_XRGB2101010:
 +      case DRM_FORMAT_XBGR2101010:
 +      case DRM_FORMAT_YUYV:
 +      case DRM_FORMAT_YVYU:
 +      case DRM_FORMAT_UYVY:
 +      case DRM_FORMAT_VYUY:
 +              break;
 +      default:
 +              DRM_DEBUG_KMS("[PLANE:%d] FB:%d unsupported scaling format 0x%x\n",
 +                      intel_plane->base.base.id, fb->base.id, fb->pixel_format);
 +              return -EINVAL;
 +      }
 +
 +      return 0;
 +}
 +
 +static void skylake_scaler_disable(struct intel_crtc *crtc)
 +{
 +      int i;
 +
 +      for (i = 0; i < crtc->num_scalers; i++)
 +              skl_detach_scaler(crtc, i);
 +}
 +
 +static void skylake_pfit_enable(struct intel_crtc *crtc)
 +{
 +      struct drm_device *dev = crtc->base.dev;
 +      struct drm_i915_private *dev_priv = dev->dev_private;
 +      int pipe = crtc->pipe;
 +      struct intel_crtc_scaler_state *scaler_state =
 +              &crtc->config->scaler_state;
 +
 +      DRM_DEBUG_KMS("for crtc_state = %p\n", crtc->config);
  
        if (crtc->config->pch_pfit.enabled) {
                int id;
@@@ -4526,6 -4584,20 +4526,6 @@@ static void ironlake_pfit_enable(struc
        }
  }
  
 -static void intel_enable_sprite_planes(struct drm_crtc *crtc)
 -{
 -      struct drm_device *dev = crtc->dev;
 -      enum pipe pipe = to_intel_crtc(crtc)->pipe;
 -      struct drm_plane *plane;
 -      struct intel_plane *intel_plane;
 -
 -      drm_for_each_legacy_plane(plane, &dev->mode_config.plane_list) {
 -              intel_plane = to_intel_plane(plane);
 -              if (intel_plane->pipe == pipe)
 -                      intel_plane_restore(&intel_plane->base);
 -      }
 -}
 -
  void hsw_enable_ips(struct intel_crtc *crtc)
  {
        struct drm_device *dev = crtc->base.dev;
@@@ -4596,7 -4668,7 +4596,7 @@@ static void intel_crtc_load_lut(struct 
        bool reenable_ips = false;
  
        /* The clocks have to be on to load the palette. */
 -      if (!crtc->state->enable || !intel_crtc->active)
 +      if (!crtc->state->active)
                return;
  
        if (HAS_GMCH_DISPLAY(dev_priv->dev)) {
@@@ -4683,6 -4755,10 +4683,6 @@@ intel_post_enable_primary(struct drm_cr
         */
        hsw_enable_ips(intel_crtc);
  
 -      mutex_lock(&dev->struct_mutex);
 -      intel_fbc_update(dev);
 -      mutex_unlock(&dev->struct_mutex);
 -
        /*
         * Gen2 reports pipe underruns whenever all planes are disabled.
         * So don't enable underrun reporting before at least some planes
@@@ -4734,11 -4810,13 +4734,11 @@@ intel_pre_disable_primary(struct drm_cr
         * event which is after the vblank start event, so we need to have a
         * wait-for-vblank between disabling the plane and the pipe.
         */
 -      if (HAS_GMCH_DISPLAY(dev))
 +      if (HAS_GMCH_DISPLAY(dev)) {
                intel_set_memory_cxsr(dev_priv, false);
 -
 -      mutex_lock(&dev->struct_mutex);
 -      if (dev_priv->fbc.crtc == intel_crtc)
 -              intel_fbc_disable(dev);
 -      mutex_unlock(&dev->struct_mutex);
 +              dev_priv->wm.vlv.cxsr = false;
 +              intel_wait_for_vblank(dev, pipe);
 +      }
  
        /*
         * FIXME IPS should be fine as long as one plane is
        hsw_disable_ips(intel_crtc);
  }
  
 -static void intel_crtc_enable_planes(struct drm_crtc *crtc)
 +static void intel_post_plane_update(struct intel_crtc *crtc)
  {
 -      struct drm_device *dev = crtc->dev;
 -      struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
 -      int pipe = intel_crtc->pipe;
 +      struct intel_crtc_atomic_commit *atomic = &crtc->atomic;
 +      struct drm_device *dev = crtc->base.dev;
 +      struct drm_i915_private *dev_priv = dev->dev_private;
 +      struct drm_plane *plane;
  
 -      intel_enable_primary_hw_plane(crtc->primary, crtc);
 -      intel_enable_sprite_planes(crtc);
 -      intel_crtc_update_cursor(crtc, true);
 +      if (atomic->wait_vblank)
 +              intel_wait_for_vblank(dev, crtc->pipe);
  
 -      intel_post_enable_primary(crtc);
 +      intel_frontbuffer_flip(dev, atomic->fb_bits);
  
 -      /*
 -       * FIXME: Once we grow proper nuclear flip support out of this we need
 -       * to compute the mask of flip planes precisely. For the time being
 -       * consider this a flip to a NULL plane.
 -       */
 -      intel_frontbuffer_flip(dev, INTEL_FRONTBUFFER_ALL_MASK(pipe));
 +      if (atomic->disable_cxsr)
 +              crtc->wm.cxsr_allowed = true;
 +
 +      if (crtc->atomic.update_wm_post)
 +              intel_update_watermarks(&crtc->base);
 +
 +      if (atomic->update_fbc)
 +              intel_fbc_update(dev_priv);
 +
 +      if (atomic->post_enable_primary)
 +              intel_post_enable_primary(&crtc->base);
 +
 +      drm_for_each_plane_mask(plane, dev, atomic->update_sprite_watermarks)
 +              intel_update_sprite_watermarks(plane, &crtc->base,
 +                                             0, 0, 0, false, false);
 +
 +      memset(atomic, 0, sizeof(*atomic));
  }
  
 -static void intel_crtc_disable_planes(struct drm_crtc *crtc)
 +static void intel_pre_plane_update(struct intel_crtc *crtc)
  {
 -      struct drm_device *dev = crtc->dev;
 -      struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
 -      struct intel_plane *intel_plane;
 -      int pipe = intel_crtc->pipe;
 +      struct drm_device *dev = crtc->base.dev;
 +      struct drm_i915_private *dev_priv = dev->dev_private;
 +      struct intel_crtc_atomic_commit *atomic = &crtc->atomic;
 +      struct drm_plane *p;
  
 -      if (!intel_crtc->active)
 -              return;
 +      /* Track fb's for any planes being disabled */
 +      drm_for_each_plane_mask(p, dev, atomic->disabled_planes) {
 +              struct intel_plane *plane = to_intel_plane(p);
  
 -      intel_crtc_wait_for_pending_flips(crtc);
 +              mutex_lock(&dev->struct_mutex);
 +              i915_gem_track_fb(intel_fb_obj(plane->base.fb), NULL,
 +                                plane->frontbuffer_bit);
 +              mutex_unlock(&dev->struct_mutex);
 +      }
  
 -      intel_pre_disable_primary(crtc);
 +      if (atomic->wait_for_flips)
 +              intel_crtc_wait_for_pending_flips(&crtc->base);
  
 -      intel_crtc_dpms_overlay_disable(intel_crtc);
 -      for_each_intel_plane(dev, intel_plane) {
 -              if (intel_plane->pipe == pipe) {
 -                      struct drm_crtc *from = intel_plane->base.crtc;
 +      if (atomic->disable_fbc)
 +              intel_fbc_disable_crtc(crtc);
  
 -                      intel_plane->disable_plane(&intel_plane->base,
 -                                                 from ?: crtc, true);
 -              }
 +      if (crtc->atomic.disable_ips)
 +              hsw_disable_ips(crtc);
 +
 +      if (atomic->pre_disable_primary)
 +              intel_pre_disable_primary(&crtc->base);
 +
 +      if (atomic->disable_cxsr) {
 +              crtc->wm.cxsr_allowed = false;
 +              intel_set_memory_cxsr(dev_priv, false);
        }
 +}
 +
 +static void intel_crtc_disable_planes(struct drm_crtc *crtc, unsigned plane_mask)
 +{
 +      struct drm_device *dev = crtc->dev;
 +      struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
 +      struct drm_plane *p;
 +      int pipe = intel_crtc->pipe;
 +
 +      intel_crtc_dpms_overlay_disable(intel_crtc);
 +
 +      drm_for_each_plane_mask(p, dev, plane_mask)
 +              to_intel_plane(p)->disable_plane(p, crtc);
  
        /*
         * FIXME: Once we grow proper nuclear flip support out of this we need
@@@ -4843,7 -4887,9 +4843,7 @@@ static void ironlake_crtc_enable(struc
        struct intel_encoder *encoder;
        int pipe = intel_crtc->pipe;
  
 -      WARN_ON(!crtc->state->enable);
 -
 -      if (intel_crtc->active)
 +      if (WARN_ON(intel_crtc->active))
                return;
  
        if (intel_crtc->config->has_pch_encoder)
@@@ -4910,17 -4956,46 +4910,17 @@@ static bool hsw_crtc_supports_ips(struc
        return HAS_IPS(crtc->base.dev) && crtc->pipe == PIPE_A;
  }
  
 -/*
 - * This implements the workaround described in the "notes" section of the mode
 - * set sequence documentation. When going from no pipes or single pipe to
 - * multiple pipes, and planes are enabled after the pipe, we need to wait at
 - * least 2 vblanks on the first pipe before enabling planes on the second pipe.
 - */
 -static void haswell_mode_set_planes_workaround(struct intel_crtc *crtc)
 -{
 -      struct drm_device *dev = crtc->base.dev;
 -      struct intel_crtc *crtc_it, *other_active_crtc = NULL;
 -
 -      /* We want to get the other_active_crtc only if there's only 1 other
 -       * active crtc. */
 -      for_each_intel_crtc(dev, crtc_it) {
 -              if (!crtc_it->active || crtc_it == crtc)
 -                      continue;
 -
 -              if (other_active_crtc)
 -                      return;
 -
 -              other_active_crtc = crtc_it;
 -      }
 -      if (!other_active_crtc)
 -              return;
 -
 -      intel_wait_for_vblank(dev, other_active_crtc->pipe);
 -      intel_wait_for_vblank(dev, other_active_crtc->pipe);
 -}
 -
  static void haswell_crtc_enable(struct drm_crtc *crtc)
  {
        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 intel_encoder *encoder;
 -      int pipe = intel_crtc->pipe;
 +      int pipe = intel_crtc->pipe, hsw_workaround_pipe;
 +      struct intel_crtc_state *pipe_config =
 +              to_intel_crtc_state(crtc->state);
  
 -      WARN_ON(!crtc->state->enable);
 -
 -      if (intel_crtc->active)
 +      if (WARN_ON(intel_crtc->active))
                return;
  
        if (intel_crtc_to_shared_dpll(intel_crtc))
        intel_ddi_enable_pipe_clock(intel_crtc);
  
        if (INTEL_INFO(dev)->gen == 9)
 -              skylake_pfit_update(intel_crtc, 1);
 +              skylake_pfit_enable(intel_crtc);
        else if (INTEL_INFO(dev)->gen < 9)
                ironlake_pfit_enable(intel_crtc);
        else
  
        /* If we change the relative order between pipe/planes enabling, we need
         * to change the workaround. */
 -      haswell_mode_set_planes_workaround(intel_crtc);
 +      hsw_workaround_pipe = pipe_config->hsw_workaround_pipe;
 +      if (IS_HASWELL(dev) && hsw_workaround_pipe != INVALID_PIPE) {
 +              intel_wait_for_vblank(dev, hsw_workaround_pipe);
 +              intel_wait_for_vblank(dev, hsw_workaround_pipe);
 +      }
  }
  
  static void ironlake_pfit_disable(struct intel_crtc *crtc)
@@@ -5026,6 -5097,9 +5026,6 @@@ static void ironlake_crtc_disable(struc
        int pipe = intel_crtc->pipe;
        u32 reg, temp;
  
 -      if (!intel_crtc->active)
 -              return;
 -
        for_each_encoder_on_crtc(dev, crtc, encoder)
                encoder->disable(encoder);
  
                        I915_WRITE(PCH_DPLL_SEL, temp);
                }
  
 -              /* disable PCH DPLL */
 -              intel_disable_shared_dpll(intel_crtc);
 -
                ironlake_fdi_pll_disable(intel_crtc);
        }
  
        intel_crtc->active = false;
        intel_update_watermarks(crtc);
 -
 -      mutex_lock(&dev->struct_mutex);
 -      intel_fbc_update(dev);
 -      mutex_unlock(&dev->struct_mutex);
  }
  
  static void haswell_crtc_disable(struct drm_crtc *crtc)
        struct intel_encoder *encoder;
        enum transcoder cpu_transcoder = intel_crtc->config->cpu_transcoder;
  
 -      if (!intel_crtc->active)
 -              return;
 -
        for_each_encoder_on_crtc(dev, crtc, encoder) {
                intel_opregion_notify_encoder(encoder, false);
                encoder->disable(encoder);
        intel_ddi_disable_transcoder_func(dev_priv, cpu_transcoder);
  
        if (INTEL_INFO(dev)->gen == 9)
 -              skylake_pfit_update(intel_crtc, 0);
 +              skylake_scaler_disable(intel_crtc);
        else if (INTEL_INFO(dev)->gen < 9)
                ironlake_pfit_disable(intel_crtc);
        else
  
        intel_crtc->active = false;
        intel_update_watermarks(crtc);
 -
 -      mutex_lock(&dev->struct_mutex);
 -      intel_fbc_update(dev);
 -      mutex_unlock(&dev->struct_mutex);
 -
 -      if (intel_crtc_to_shared_dpll(intel_crtc))
 -              intel_disable_shared_dpll(intel_crtc);
 -}
 -
 -static void ironlake_crtc_off(struct drm_crtc *crtc)
 -{
 -      struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
 -      intel_put_shared_dpll(intel_crtc);
  }
  
 -
  static void i9xx_pfit_enable(struct intel_crtc *crtc)
  {
        struct drm_device *dev = crtc->base.dev;
@@@ -5147,7 -5245,6 +5147,7 @@@ static enum intel_display_power_domain 
  {
        switch (port) {
        case PORT_A:
 +      case PORT_E:
                return POWER_DOMAIN_PORT_DDI_A_4_LANES;
        case PORT_B:
                return POWER_DOMAIN_PORT_DDI_B_4_LANES;
@@@ -5201,9 -5298,6 +5201,9 @@@ static unsigned long get_crtc_power_dom
        unsigned long mask;
        enum transcoder transcoder;
  
 +      if (!crtc->state->active)
 +              return 0;
 +
        transcoder = intel_pipe_to_cpu_transcoder(dev->dev_private, pipe);
  
        mask = BIT(POWER_DOMAIN_PIPE(pipe));
        return mask;
  }
  
 +static unsigned long modeset_get_crtc_power_domains(struct drm_crtc *crtc)
 +{
 +      struct drm_i915_private *dev_priv = crtc->dev->dev_private;
 +      struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
 +      enum intel_display_power_domain domain;
 +      unsigned long domains, new_domains, old_domains;
 +
 +      old_domains = intel_crtc->enabled_power_domains;
 +      intel_crtc->enabled_power_domains = new_domains = get_crtc_power_domains(crtc);
 +
 +      domains = new_domains & ~old_domains;
 +
 +      for_each_power_domain(domain, domains)
 +              intel_display_power_get(dev_priv, domain);
 +
 +      return old_domains & ~new_domains;
 +}
 +
 +static void modeset_put_power_domains(struct drm_i915_private *dev_priv,
 +                                    unsigned long domains)
 +{
 +      enum intel_display_power_domain domain;
 +
 +      for_each_power_domain(domain, domains)
 +              intel_display_power_put(dev_priv, domain);
 +}
 +
  static void modeset_update_crtc_power_domains(struct drm_atomic_state *state)
  {
        struct drm_device *dev = state->dev;
        struct drm_i915_private *dev_priv = dev->dev_private;
 -      unsigned long pipe_domains[I915_MAX_PIPES] = { 0, };
 -      struct intel_crtc *crtc;
 +      unsigned long put_domains[I915_MAX_PIPES] = {};
 +      struct drm_crtc_state *crtc_state;
 +      struct drm_crtc *crtc;
 +      int i;
  
 -      /*
 -       * First get all needed power domains, then put all unneeded, to avoid
 -       * any unnecessary toggling of the power wells.
 -       */
 -      for_each_intel_crtc(dev, crtc) {
 -              enum intel_display_power_domain domain;
 +      for_each_crtc_in_state(state, crtc, crtc_state, i) {
 +              if (needs_modeset(crtc->state))
 +                      put_domains[to_intel_crtc(crtc)->pipe] =
 +                              modeset_get_crtc_power_domains(crtc);
 +      }
  
 -              if (!crtc->base.state->enable)
 -                      continue;
 +      if (dev_priv->display.modeset_commit_cdclk) {
 +              unsigned int cdclk = to_intel_atomic_state(state)->cdclk;
 +
 +              if (cdclk != dev_priv->cdclk_freq &&
 +                  !WARN_ON(!state->allow_modeset))
 +                      dev_priv->display.modeset_commit_cdclk(state);
 +      }
 +
 +      for (i = 0; i < I915_MAX_PIPES; i++)
 +              if (put_domains[i])
 +                      modeset_put_power_domains(dev_priv, put_domains[i]);
 +}
 +
 +static void intel_update_max_cdclk(struct drm_device *dev)
 +{
 +      struct drm_i915_private *dev_priv = dev->dev_private;
  
 -              pipe_domains[crtc->pipe] = get_crtc_power_domains(&crtc->base);
 +      if (IS_SKYLAKE(dev)) {
 +              u32 limit = I915_READ(SKL_DFSM) & SKL_DFSM_CDCLK_LIMIT_MASK;
  
 -              for_each_power_domain(domain, pipe_domains[crtc->pipe])
 -                      intel_display_power_get(dev_priv, domain);
 +              if (limit == SKL_DFSM_CDCLK_LIMIT_675)
 +                      dev_priv->max_cdclk_freq = 675000;
 +              else if (limit == SKL_DFSM_CDCLK_LIMIT_540)
 +                      dev_priv->max_cdclk_freq = 540000;
 +              else if (limit == SKL_DFSM_CDCLK_LIMIT_450)
 +                      dev_priv->max_cdclk_freq = 450000;
 +              else
 +                      dev_priv->max_cdclk_freq = 337500;
 +      } else if (IS_BROADWELL(dev))  {
 +              /*
 +               * FIXME with extra cooling we can allow
 +               * 540 MHz for ULX and 675 Mhz for ULT.
 +               * How can we know if extra cooling is
 +               * available? PCI ID, VTB, something else?
 +               */
 +              if (I915_READ(FUSE_STRAP) & HSW_CDCLK_LIMIT)
 +                      dev_priv->max_cdclk_freq = 450000;
 +              else if (IS_BDW_ULX(dev))
 +                      dev_priv->max_cdclk_freq = 450000;
 +              else if (IS_BDW_ULT(dev))
 +                      dev_priv->max_cdclk_freq = 540000;
 +              else
 +                      dev_priv->max_cdclk_freq = 675000;
 +      } else if (IS_CHERRYVIEW(dev)) {
 +              dev_priv->max_cdclk_freq = 320000;
 +      } else if (IS_VALLEYVIEW(dev)) {
 +              dev_priv->max_cdclk_freq = 400000;
 +      } else {
 +              /* otherwise assume cdclk is fixed */
 +              dev_priv->max_cdclk_freq = dev_priv->cdclk_freq;
        }
  
 -      if (dev_priv->display.modeset_global_resources)
 -              dev_priv->display.modeset_global_resources(state);
 +      DRM_DEBUG_DRIVER("Max CD clock rate: %d kHz\n",
 +                       dev_priv->max_cdclk_freq);
 +}
  
 -      for_each_intel_crtc(dev, crtc) {
 -              enum intel_display_power_domain domain;
 +static void intel_update_cdclk(struct drm_device *dev)
 +{
 +      struct drm_i915_private *dev_priv = dev->dev_private;
  
 -              for_each_power_domain(domain, crtc->enabled_power_domains)
 -                      intel_display_power_put(dev_priv, domain);
 +      dev_priv->cdclk_freq = dev_priv->display.get_display_clock_speed(dev);
 +      DRM_DEBUG_DRIVER("Current CD clock rate: %d kHz\n",
 +                       dev_priv->cdclk_freq);
  
 -              crtc->enabled_power_domains = pipe_domains[crtc->pipe];
 +      /*
 +       * Program the gmbus_freq based on the cdclk frequency.
 +       * BSpec erroneously claims we should aim for 4MHz, but
 +       * in fact 1MHz is the correct frequency.
 +       */
 +      if (IS_VALLEYVIEW(dev)) {
 +              /*
 +               * Program the gmbus_freq based on the cdclk frequency.
 +               * BSpec erroneously claims we should aim for 4MHz, but
 +               * in fact 1MHz is the correct frequency.
 +               */
 +              I915_WRITE(GMBUSFREQ_VLV, DIV_ROUND_UP(dev_priv->cdclk_freq, 1000));
        }
  
 -      intel_display_set_init_power(dev_priv, false);
 +      if (dev_priv->max_cdclk_freq == 0)
 +              intel_update_max_cdclk(dev);
  }
  
 -void broxton_set_cdclk(struct drm_device *dev, int frequency)
 +static void broxton_set_cdclk(struct drm_device *dev, int frequency)
  {
        struct drm_i915_private *dev_priv = dev->dev_private;
        uint32_t divider;
                return;
        }
  
 -      dev_priv->cdclk_freq = frequency;
 +      intel_update_cdclk(dev);
  }
  
  void broxton_init_cdclk(struct drm_device *dev)
@@@ -5633,7 -5641,6 +5633,7 @@@ static bool skl_cdclk_wait_for_pcu_read
  
  static void skl_set_cdclk(struct drm_i915_private *dev_priv, unsigned int freq)
  {
 +      struct drm_device *dev = dev_priv->dev;
        u32 freq_select, pcu_ack;
  
        DRM_DEBUG_DRIVER("Changing CDCLK to %dKHz\n", freq);
        mutex_lock(&dev_priv->rps.hw_lock);
        sandybridge_pcode_write(dev_priv, SKL_PCODE_CDCLK_CONTROL, pcu_ack);
        mutex_unlock(&dev_priv->rps.hw_lock);
 +
 +      intel_update_cdclk(dev);
  }
  
  void skl_uninit_cdclk(struct drm_i915_private *dev_priv)
@@@ -5746,6 -5751,22 +5746,6 @@@ static int valleyview_get_vco(struct dr
        return vco_freq[hpll_freq] * 1000;
  }
  
 -static void vlv_update_cdclk(struct drm_device *dev)
 -{
 -      struct drm_i915_private *dev_priv = dev->dev_private;
 -
 -      dev_priv->cdclk_freq = dev_priv->display.get_display_clock_speed(dev);
 -      DRM_DEBUG_DRIVER("Current CD clock rate: %d kHz\n",
 -                       dev_priv->cdclk_freq);
 -
 -      /*
 -       * Program the gmbus_freq based on the cdclk frequency.
 -       * BSpec erroneously claims we should aim for 4MHz, but
 -       * in fact 1MHz is the correct frequency.
 -       */
 -      I915_WRITE(GMBUSFREQ_VLV, DIV_ROUND_UP(dev_priv->cdclk_freq, 1000));
 -}
 -
  /* Adjust CDclk dividers to allow high res or save power if possible */
  static void valleyview_set_cdclk(struct drm_device *dev, int cdclk)
  {
  
        mutex_unlock(&dev_priv->sb_lock);
  
 -      vlv_update_cdclk(dev);
 +      intel_update_cdclk(dev);
  }
  
  static void cherryview_set_cdclk(struct drm_device *dev, int cdclk)
        }
        mutex_unlock(&dev_priv->rps.hw_lock);
  
 -      vlv_update_cdclk(dev);
 +      intel_update_cdclk(dev);
  }
  
  static int valleyview_calc_cdclk(struct drm_i915_private *dev_priv,
@@@ -5913,7 -5934,11 +5913,7 @@@ static int intel_mode_max_pixclk(struc
        int max_pixclk = 0;
  
        for_each_intel_crtc(dev, intel_crtc) {
 -              if (state)
 -                      crtc_state =
 -                              intel_atomic_get_crtc_state(state, intel_crtc);
 -              else
 -                      crtc_state = intel_crtc->config;
 +              crtc_state = intel_atomic_get_crtc_state(state, intel_crtc);
                if (IS_ERR(crtc_state))
                        return PTR_ERR(crtc_state);
  
        return max_pixclk;
  }
  
 -static int valleyview_modeset_global_pipes(struct drm_atomic_state *state)
 +static int valleyview_modeset_calc_cdclk(struct drm_atomic_state *state)
  {
 -      struct drm_i915_private *dev_priv = to_i915(state->dev);
 -      struct drm_crtc *crtc;
 -      struct drm_crtc_state *crtc_state;
 -      int max_pixclk = intel_mode_max_pixclk(state->dev, state);
 -      int cdclk, i;
 +      struct drm_device *dev = state->dev;
 +      struct drm_i915_private *dev_priv = dev->dev_private;
 +      int max_pixclk = intel_mode_max_pixclk(dev, state);
  
        if (max_pixclk < 0)
                return max_pixclk;
  
 -      if (IS_VALLEYVIEW(dev_priv))
 -              cdclk = valleyview_calc_cdclk(dev_priv, max_pixclk);
 -      else
 -              cdclk = broxton_calc_cdclk(dev_priv, max_pixclk);
 +      to_intel_atomic_state(state)->cdclk =
 +              valleyview_calc_cdclk(dev_priv, max_pixclk);
  
 -      if (cdclk == dev_priv->cdclk_freq)
 -              return 0;
 +      return 0;
 +}
  
 -      /* add all active pipes to the state */
 -      for_each_crtc(state->dev, crtc) {
 -              if (!crtc->state->enable)
 -                      continue;
 +static int broxton_modeset_calc_cdclk(struct drm_atomic_state *state)
 +{
 +      struct drm_device *dev = state->dev;
 +      struct drm_i915_private *dev_priv = dev->dev_private;
 +      int max_pixclk = intel_mode_max_pixclk(dev, state);
  
 -              crtc_state = drm_atomic_get_crtc_state(state, crtc);
 -              if (IS_ERR(crtc_state))
 -                      return PTR_ERR(crtc_state);
 -      }
 +      if (max_pixclk < 0)
 +              return max_pixclk;
  
 -      /* disable/enable all currently active pipes while we change cdclk */
 -      for_each_crtc_in_state(state, crtc, crtc_state, i)
 -              if (crtc_state->enable)
 -                      crtc_state->mode_changed = true;
 +      to_intel_atomic_state(state)->cdclk =
 +              broxton_calc_cdclk(dev_priv, max_pixclk);
  
        return 0;
  }
@@@ -5969,7 -6001,7 +5969,7 @@@ static void vlv_program_pfi_credits(str
        if (DIV_ROUND_CLOSEST(dev_priv->cdclk_freq, 1000) >= dev_priv->rps.cz_freq) {
                /* CHV suggested value is 31 or 63 */
                if (IS_CHERRYVIEW(dev_priv))
 -                      credits = PFI_CREDIT_31;
 +                      credits = PFI_CREDIT_63;
                else
                        credits = PFI_CREDIT(15);
        } else {
        WARN_ON(I915_READ(GCI_CONTROL) & PFI_CREDIT_RESEND);
  }
  
 -static void valleyview_modeset_global_resources(struct drm_atomic_state *old_state)
 +static void valleyview_modeset_commit_cdclk(struct drm_atomic_state *old_state)
  {
        struct drm_device *dev = old_state->dev;
 +      unsigned int req_cdclk = to_intel_atomic_state(old_state)->cdclk;
        struct drm_i915_private *dev_priv = dev->dev_private;
 -      int max_pixclk = intel_mode_max_pixclk(dev, NULL);
 -      int req_cdclk;
 -
 -      /* The path in intel_mode_max_pixclk() with a NULL atomic state should
 -       * never fail. */
 -      if (WARN_ON(max_pixclk < 0))
 -              return;
 -
 -      req_cdclk = valleyview_calc_cdclk(dev_priv, max_pixclk);
  
 -      if (req_cdclk != dev_priv->cdclk_freq) {
 -              /*
 -               * FIXME: We can end up here with all power domains off, yet
 -               * with a CDCLK frequency other than the minimum. To account
 -               * for this take the PIPE-A power domain, which covers the HW
 -               * blocks needed for the following programming. This can be
 -               * removed once it's guaranteed that we get here either with
 -               * the minimum CDCLK set, or the required power domains
 -               * enabled.
 -               */
 -              intel_display_power_get(dev_priv, POWER_DOMAIN_PIPE_A);
 +      /*
 +       * FIXME: We can end up here with all power domains off, yet
 +       * with a CDCLK frequency other than the minimum. To account
 +       * for this take the PIPE-A power domain, which covers the HW
 +       * blocks needed for the following programming. This can be
 +       * removed once it's guaranteed that we get here either with
 +       * the minimum CDCLK set, or the required power domains
 +       * enabled.
 +       */
 +      intel_display_power_get(dev_priv, POWER_DOMAIN_PIPE_A);
  
 -              if (IS_CHERRYVIEW(dev))
 -                      cherryview_set_cdclk(dev, req_cdclk);
 -              else
 -                      valleyview_set_cdclk(dev, req_cdclk);
 +      if (IS_CHERRYVIEW(dev))
 +              cherryview_set_cdclk(dev, req_cdclk);
 +      else
 +              valleyview_set_cdclk(dev, req_cdclk);
  
 -              vlv_program_pfi_credits(dev_priv);
 +      vlv_program_pfi_credits(dev_priv);
  
 -              intel_display_power_put(dev_priv, POWER_DOMAIN_PIPE_A);
 -      }
 +      intel_display_power_put(dev_priv, POWER_DOMAIN_PIPE_A);
  }
  
  static void valleyview_crtc_enable(struct drm_crtc *crtc)
        int pipe = intel_crtc->pipe;
        bool is_dsi;
  
 -      WARN_ON(!crtc->state->enable);
 -
 -      if (intel_crtc->active)
 +      if (WARN_ON(intel_crtc->active))
                return;
  
        is_dsi = intel_pipe_has_type(intel_crtc, INTEL_OUTPUT_DSI);
  
        intel_crtc_load_lut(crtc);
  
 -      intel_update_watermarks(crtc);
        intel_enable_pipe(intel_crtc);
  
        assert_vblank_disabled(crtc);
@@@ -6104,7 -6149,9 +6104,7 @@@ static void i9xx_crtc_enable(struct drm
        struct intel_encoder *encoder;
        int pipe = intel_crtc->pipe;
  
 -      WARN_ON(!crtc->state->enable);
 -
 -      if (intel_crtc->active)
 +      if (WARN_ON(intel_crtc->active))
                return;
  
        i9xx_set_pll_dividers(intel_crtc);
@@@ -6164,6 -6211,9 +6164,6 @@@ static void i9xx_crtc_disable(struct dr
        struct intel_encoder *encoder;
        int pipe = intel_crtc->pipe;
  
 -      if (!intel_crtc->active)
 -              return;
 -
        /*
         * On gen2 planes are double buffered but the pipe isn't, so we must
         * wait for planes to fully turn off before disabling the pipe.
  
        intel_crtc->active = false;
        intel_update_watermarks(crtc);
 -
 -      mutex_lock(&dev->struct_mutex);
 -      intel_fbc_update(dev);
 -      mutex_unlock(&dev->struct_mutex);
 -}
 -
 -static void i9xx_crtc_off(struct drm_crtc *crtc)
 -{
  }
  
 -/* Master function to enable/disable CRTC and corresponding power wells */
 -void intel_crtc_control(struct drm_crtc *crtc, bool enable)
 +static void intel_crtc_disable_noatomic(struct drm_crtc *crtc)
  {
 -      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_private *dev_priv = to_i915(crtc->dev);
        enum intel_display_power_domain domain;
        unsigned long domains;
  
 -      if (enable) {
 -              if (!intel_crtc->active) {
 -                      domains = get_crtc_power_domains(crtc);
 -                      for_each_power_domain(domain, domains)
 -                              intel_display_power_get(dev_priv, domain);
 -                      intel_crtc->enabled_power_domains = domains;
 -
 -                      dev_priv->display.crtc_enable(crtc);
 -                      intel_crtc_enable_planes(crtc);
 -              }
 -      } else {
 -              if (intel_crtc->active) {
 -                      intel_crtc_disable_planes(crtc);
 -                      dev_priv->display.crtc_disable(crtc);
 +      if (!intel_crtc->active)
 +              return;
  
 -                      domains = intel_crtc->enabled_power_domains;
 -                      for_each_power_domain(domain, domains)
 -                              intel_display_power_put(dev_priv, domain);
 -                      intel_crtc->enabled_power_domains = 0;
 -              }
 +      if (to_intel_plane_state(crtc->primary->state)->visible) {
 +              intel_crtc_wait_for_pending_flips(crtc);
 +              intel_pre_disable_primary(crtc);
        }
 +
 +      intel_crtc_disable_planes(crtc, crtc->state->plane_mask);
 +      dev_priv->display.crtc_disable(crtc);
 +      intel_disable_shared_dpll(intel_crtc);
 +
 +      domains = intel_crtc->enabled_power_domains;
 +      for_each_power_domain(domain, domains)
 +              intel_display_power_put(dev_priv, domain);
 +      intel_crtc->enabled_power_domains = 0;
  }
  
 -/**
 - * Sets the power management mode of the pipe and plane.
 +/*
 + * turn all crtc's off, but do not adjust state
 + * This has to be paired with a call to intel_modeset_setup_hw_state.
   */
 -void intel_crtc_update_dpms(struct drm_crtc *crtc)
 +int intel_display_suspend(struct drm_device *dev)
  {
 -      struct drm_device *dev = crtc->dev;
 -      struct intel_encoder *intel_encoder;
 -      bool enable = false;
 -
 -      for_each_encoder_on_crtc(dev, crtc, intel_encoder)
 -              enable |= intel_encoder->connectors_active;
 +      struct drm_mode_config *config = &dev->mode_config;
 +      struct drm_modeset_acquire_ctx *ctx = config->acquire_ctx;
 +      struct drm_atomic_state *state;
 +      struct drm_crtc *crtc;
 +      unsigned crtc_mask = 0;
 +      int ret = 0;
  
 -      intel_crtc_control(crtc, enable);
 +      if (WARN_ON(!ctx))
 +              return 0;
  
 -      crtc->state->active = enable;
 -}
 +      lockdep_assert_held(&ctx->ww_ctx);
 +      state = drm_atomic_state_alloc(dev);
 +      if (WARN_ON(!state))
 +              return -ENOMEM;
  
 -static void intel_crtc_disable(struct drm_crtc *crtc)
 -{
 -      struct drm_device *dev = crtc->dev;
 -      struct drm_connector *connector;
 -      struct drm_i915_private *dev_priv = dev->dev_private;
 +      state->acquire_ctx = ctx;
 +      state->allow_modeset = true;
  
 -      intel_crtc_disable_planes(crtc);
 -      dev_priv->display.crtc_disable(crtc);
 -      dev_priv->display.off(crtc);
 +      for_each_crtc(dev, crtc) {
 +              struct drm_crtc_state *crtc_state =
 +                      drm_atomic_get_crtc_state(state, crtc);
  
 -      drm_plane_helper_disable(crtc->primary);
 +              ret = PTR_ERR_OR_ZERO(crtc_state);
 +              if (ret)
 +                      goto free;
  
 -      /* Update computed state. */
 -      list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
 -              if (!connector->encoder || !connector->encoder->crtc)
 +              if (!crtc_state->active)
                        continue;
  
 -              if (connector->encoder->crtc != crtc)
 -                      continue;
 +              crtc_state->active = false;
 +              crtc_mask |= 1 << drm_crtc_index(crtc);
 +      }
 +
 +      if (crtc_mask) {
 +              ret = drm_atomic_commit(state);
  
 -              connector->dpms = DRM_MODE_DPMS_OFF;
 -              to_intel_encoder(connector->encoder)->connectors_active = false;
 +              if (!ret) {
 +                      for_each_crtc(dev, crtc)
 +                              if (crtc_mask & (1 << drm_crtc_index(crtc)))
 +                                      crtc->state->active = true;
 +
 +                      return ret;
 +              }
        }
 +
 +free:
 +      if (ret)
 +              DRM_ERROR("Suspending crtc's failed with %i\n", ret);
 +      drm_atomic_state_free(state);
 +      return ret;
  }
  
  void intel_encoder_destroy(struct drm_encoder *encoder)
        kfree(intel_encoder);
  }
  
 -/* Simple dpms helper for encoders with just one connector, no cloning and only
 - * one kind of off state. It clamps all !ON modes to fully OFF and changes the
 - * state of the entire output pipe. */
 -static void intel_encoder_dpms(struct intel_encoder *encoder, int mode)
 -{
 -      if (mode == DRM_MODE_DPMS_ON) {
 -              encoder->connectors_active = true;
 -
 -              intel_crtc_update_dpms(encoder->base.crtc);
 -      } else {
 -              encoder->connectors_active = false;
 -
 -              intel_crtc_update_dpms(encoder->base.crtc);
 -      }
 -}
 -
  /* Cross check the actual hw state with our own modeset state tracking (and it's
   * internal consistency). */
  static void intel_connector_check_state(struct intel_connector *connector)
  {
 +      struct drm_crtc *crtc = connector->base.state->crtc;
 +
 +      DRM_DEBUG_KMS("[CONNECTOR:%d:%s]\n",
 +                    connector->base.base.id,
 +                    connector->base.name);
 +
        if (connector->get_hw_state(connector)) {
 -              struct intel_encoder *encoder = connector->encoder;
 -              struct drm_crtc *crtc;
 -              bool encoder_enabled;
 -              enum pipe pipe;
 +              struct drm_encoder *encoder = &connector->encoder->base;
 +              struct drm_connector_state *conn_state = connector->base.state;
  
 -              DRM_DEBUG_KMS("[CONNECTOR:%d:%s]\n",
 -                            connector->base.base.id,
 -                            connector->base.name);
 +              I915_STATE_WARN(!crtc,
 +                       "connector enabled without attached crtc\n");
  
 -              /* there is no real hw state for MST connectors */
 -              if (connector->mst_port)
 +              if (!crtc)
                        return;
  
 -              I915_STATE_WARN(connector->base.dpms == DRM_MODE_DPMS_OFF,
 -                   "wrong connector dpms state\n");
 -              I915_STATE_WARN(connector->base.encoder != &encoder->base,
 -                   "active connector not linked to encoder\n");
 +              I915_STATE_WARN(!crtc->state->active,
 +                    "connector is active, but attached crtc isn't\n");
  
 -              if (encoder) {
 -                      I915_STATE_WARN(!encoder->connectors_active,
 -                           "encoder->connectors_active not set\n");
 -
 -                      encoder_enabled = encoder->get_hw_state(encoder, &pipe);
 -                      I915_STATE_WARN(!encoder_enabled, "encoder not enabled\n");
 -                      if (I915_STATE_WARN_ON(!encoder->base.crtc))
 -                              return;
 +              if (!encoder)
 +                      return;
  
 -                      crtc = encoder->base.crtc;
 +              I915_STATE_WARN(conn_state->best_encoder != encoder,
 +                      "atomic encoder doesn't match attached encoder\n");
  
 -                      I915_STATE_WARN(!crtc->state->enable,
 -                                      "crtc not enabled\n");
 -                      I915_STATE_WARN(!to_intel_crtc(crtc)->active, "crtc not active\n");
 -                      I915_STATE_WARN(pipe != to_intel_crtc(crtc)->pipe,
 -                           "encoder active on the wrong pipe\n");
 -              }
 +              I915_STATE_WARN(conn_state->crtc != encoder->crtc,
 +                      "attached encoder crtc differs from connector crtc\n");
 +      } else {
 +              I915_STATE_WARN(crtc && crtc->state->active,
 +                      "attached crtc is active, but connector isn't\n");
 +              I915_STATE_WARN(!crtc && connector->base.state->best_encoder,
 +                      "best encoder set without crtc!\n");
        }
  }
  
@@@ -6360,6 -6429,26 +6360,6 @@@ struct intel_connector *intel_connector
        return connector;
  }
  
 -/* Even simpler default implementation, if there's really no special case to
 - * consider. */
 -void intel_connector_dpms(struct drm_connector *connector, int mode)
 -{
 -      /* All the simple cases only support two dpms states. */
 -      if (mode != DRM_MODE_DPMS_ON)
 -              mode = DRM_MODE_DPMS_OFF;
 -
 -      if (mode == connector->dpms)
 -              return;
 -
 -      connector->dpms = mode;
 -
 -      /* Only need to change hw state when actually enabled */
 -      if (connector->encoder)
 -              intel_encoder_dpms(to_intel_encoder(connector->encoder), mode);
 -
 -      intel_modeset_check_state(connector->dev);
 -}
 -
  /* Simple connector->get_hw_state implementation for encoders that support only
   * one connector and no cloning and hence the encoder state determines the state
   * of the connector. */
@@@ -6497,36 -6586,12 +6497,36 @@@ retry
        return ret;
  }
  
 +static bool pipe_config_supports_ips(struct drm_i915_private *dev_priv,
 +                                   struct intel_crtc_state *pipe_config)
 +{
 +      if (pipe_config->pipe_bpp > 24)
 +              return false;
 +
 +      /* HSW can handle pixel rate up to cdclk? */
 +      if (IS_HASWELL(dev_priv->dev))
 +              return true;
 +
 +      /*
 +       * We compare against max which means we must take
 +       * the increased cdclk requirement into account when
 +       * calculating the new cdclk.
 +       *
 +       * Should measure whether using a lower cdclk w/o IPS
 +       */
 +      return ilk_pipe_pixel_rate(pipe_config) <=
 +              dev_priv->max_cdclk_freq * 95 / 100;
 +}
 +
  static void hsw_compute_ips_config(struct intel_crtc *crtc,
                                   struct intel_crtc_state *pipe_config)
  {
 +      struct drm_device *dev = crtc->base.dev;
 +      struct drm_i915_private *dev_priv = dev->dev_private;
 +
        pipe_config->ips_enabled = i915.enable_ips &&
 -                                 hsw_crtc_supports_ips(crtc) &&
 -                                 pipe_config->pipe_bpp <= 24;
 +              hsw_crtc_supports_ips(crtc) &&
 +              pipe_config_supports_ips(dev_priv, pipe_config);
  }
  
  static int intel_crtc_compute_config(struct intel_crtc *crtc,
        struct drm_device *dev = crtc->base.dev;
        struct drm_i915_private *dev_priv = dev->dev_private;
        struct drm_display_mode *adjusted_mode = &pipe_config->base.adjusted_mode;
 -      int ret;
  
        /* FIXME should check pixel clock limits on all platforms */
        if (INTEL_INFO(dev)->gen < 4) {
 -              int clock_limit =
 -                      dev_priv->display.get_display_clock_speed(dev);
 +              int clock_limit = dev_priv->max_cdclk_freq;
  
                /*
                 * Enable pixel doubling when the dot clock
        if (pipe_config->has_pch_encoder)
                return ironlake_fdi_compute_config(crtc, pipe_config);
  
 -      /* FIXME: remove below call once atomic mode set is place and all crtc
 -       * related checks called from atomic_crtc_check function */
 -      ret = 0;
 -      DRM_DEBUG_KMS("intel_crtc = %p drm_state (pipe_config->base.state) = %p\n",
 -              crtc, pipe_config->base.state);
 -      ret = intel_atomic_setup_scalers(dev, crtc, pipe_config);
 -
 -      return ret;
 +      return 0;
  }
  
  static int skylake_get_display_clock_speed(struct drm_device *dev)
        uint32_t cdctl = I915_READ(CDCLK_CTL);
        uint32_t linkrate;
  
 -      if (!(lcpll1 & LCPLL_PLL_ENABLE)) {
 -              WARN(1, "LCPLL1 not enabled\n");
 +      if (!(lcpll1 & LCPLL_PLL_ENABLE))
                return 24000; /* 24MHz is the cd freq with NSSC ref */
 -      }
  
        if ((cdctl & CDCLK_FREQ_SEL_MASK) == CDCLK_FREQ_540)
                return 540000;
        return 24000;
  }
  
 +static int broxton_get_display_clock_speed(struct drm_device *dev)
 +{
 +      struct drm_i915_private *dev_priv = to_i915(dev);
 +      uint32_t cdctl = I915_READ(CDCLK_CTL);
 +      uint32_t pll_ratio = I915_READ(BXT_DE_PLL_CTL) & BXT_DE_PLL_RATIO_MASK;
 +      uint32_t pll_enab = I915_READ(BXT_DE_PLL_ENABLE);
 +      int cdclk;
 +
 +      if (!(pll_enab & BXT_DE_PLL_PLL_ENABLE))
 +              return 19200;
 +
 +      cdclk = 19200 * pll_ratio / 2;
 +
 +      switch (cdctl & BXT_CDCLK_CD2X_DIV_SEL_MASK) {
 +      case BXT_CDCLK_CD2X_DIV_SEL_1:
 +              return cdclk;  /* 576MHz or 624MHz */
 +      case BXT_CDCLK_CD2X_DIV_SEL_1_5:
 +              return cdclk * 2 / 3; /* 384MHz */
 +      case BXT_CDCLK_CD2X_DIV_SEL_2:
 +              return cdclk / 2; /* 288MHz */
 +      case BXT_CDCLK_CD2X_DIV_SEL_4:
 +              return cdclk / 4; /* 144MHz */
 +      }
 +
 +      /* error case, do as if DE PLL isn't enabled */
 +      return 19200;
 +}
 +
  static int broadwell_get_display_clock_speed(struct drm_device *dev)
  {
        struct drm_i915_private *dev_priv = dev->dev_private;
@@@ -6786,37 -6834,20 +6786,37 @@@ static int i865_get_display_clock_speed
        return 266667;
  }
  
 -static int i855_get_display_clock_speed(struct drm_device *dev)
 +static int i85x_get_display_clock_speed(struct drm_device *dev)
  {
        u16 hpllcc = 0;
 +
 +      /*
 +       * 852GM/852GMV only supports 133 MHz and the HPLLCC
 +       * encoding is different :(
 +       * FIXME is this the right way to detect 852GM/852GMV?
 +       */
 +      if (dev->pdev->revision == 0x1)
 +              return 133333;
 +
 +      pci_bus_read_config_word(dev->pdev->bus,
 +                               PCI_DEVFN(0, 3), HPLLCC, &hpllcc);
 +
        /* Assume that the hardware is in the high speed state.  This
         * should be the default.
         */
        switch (hpllcc & GC_CLOCK_CONTROL_MASK) {
        case GC_CLOCK_133_200:
 +      case GC_CLOCK_133_200_2:
        case GC_CLOCK_100_200:
                return 200000;
        case GC_CLOCK_166_250:
                return 250000;
        case GC_CLOCK_100_133:
                return 133333;
 +      case GC_CLOCK_133_266:
 +      case GC_CLOCK_133_266_2:
 +      case GC_CLOCK_166_266:
 +              return 266667;
        }
  
        /* Shouldn't happen */
@@@ -6828,175 -6859,6 +6828,175 @@@ static int i830_get_display_clock_speed
        return 133333;
  }
  
 +static unsigned int intel_hpll_vco(struct drm_device *dev)
 +{
 +      struct drm_i915_private *dev_priv = dev->dev_private;
 +      static const unsigned int blb_vco[8] = {
 +              [0] = 3200000,
 +              [1] = 4000000,
 +              [2] = 5333333,
 +              [3] = 4800000,
 +              [4] = 6400000,
 +      };
 +      static const unsigned int pnv_vco[8] = {
 +              [0] = 3200000,
 +              [1] = 4000000,
 +              [2] = 5333333,
 +              [3] = 4800000,
 +              [4] = 2666667,
 +      };
 +      static const unsigned int cl_vco[8] = {
 +              [0] = 3200000,
 +              [1] = 4000000,
 +              [2] = 5333333,
 +              [3] = 6400000,
 +              [4] = 3333333,
 +              [5] = 3566667,
 +              [6] = 4266667,
 +      };
 +      static const unsigned int elk_vco[8] = {
 +              [0] = 3200000,
 +              [1] = 4000000,
 +              [2] = 5333333,
 +              [3] = 4800000,
 +      };
 +      static const unsigned int ctg_vco[8] = {
 +              [0] = 3200000,
 +              [1] = 4000000,
 +              [2] = 5333333,
 +              [3] = 6400000,
 +              [4] = 2666667,
 +              [5] = 4266667,
 +      };
 +      const unsigned int *vco_table;
 +      unsigned int vco;
 +      uint8_t tmp = 0;
 +
 +      /* FIXME other chipsets? */
 +      if (IS_GM45(dev))
 +              vco_table = ctg_vco;
 +      else if (IS_G4X(dev))
 +              vco_table = elk_vco;
 +      else if (IS_CRESTLINE(dev))
 +              vco_table = cl_vco;
 +      else if (IS_PINEVIEW(dev))
 +              vco_table = pnv_vco;
 +      else if (IS_G33(dev))
 +              vco_table = blb_vco;
 +      else
 +              return 0;
 +
 +      tmp = I915_READ(IS_MOBILE(dev) ? HPLLVCO_MOBILE : HPLLVCO);
 +
 +      vco = vco_table[tmp & 0x7];
 +      if (vco == 0)
 +              DRM_ERROR("Bad HPLL VCO (HPLLVCO=0x%02x)\n", tmp);
 +      else
 +              DRM_DEBUG_KMS("HPLL VCO %u kHz\n", vco);
 +
 +      return vco;
 +}
 +
 +static int gm45_get_display_clock_speed(struct drm_device *dev)
 +{
 +      unsigned int cdclk_sel, vco = intel_hpll_vco(dev);
 +      uint16_t tmp = 0;
 +
 +      pci_read_config_word(dev->pdev, GCFGC, &tmp);
 +
 +      cdclk_sel = (tmp >> 12) & 0x1;
 +
 +      switch (vco) {
 +      case 2666667:
 +      case 4000000:
 +      case 5333333:
 +              return cdclk_sel ? 333333 : 222222;
 +      case 3200000:
 +              return cdclk_sel ? 320000 : 228571;
 +      default:
 +              DRM_ERROR("Unable to determine CDCLK. HPLL VCO=%u, CFGC=0x%04x\n", vco, tmp);
 +              return 222222;
 +      }
 +}
 +
 +static int i965gm_get_display_clock_speed(struct drm_device *dev)
 +{
 +      static const uint8_t div_3200[] = { 16, 10,  8 };
 +      static const uint8_t div_4000[] = { 20, 12, 10 };
 +      static const uint8_t div_5333[] = { 24, 16, 14 };
 +      const uint8_t *div_table;
 +      unsigned int cdclk_sel, vco = intel_hpll_vco(dev);
 +      uint16_t tmp = 0;
 +
 +      pci_read_config_word(dev->pdev, GCFGC, &tmp);
 +
 +      cdclk_sel = ((tmp >> 8) & 0x1f) - 1;
 +
 +      if (cdclk_sel >= ARRAY_SIZE(div_3200))
 +              goto fail;
 +
 +      switch (vco) {
 +      case 3200000:
 +              div_table = div_3200;
 +              break;
 +      case 4000000:
 +              div_table = div_4000;
 +              break;
 +      case 5333333:
 +              div_table = div_5333;
 +              break;
 +      default:
 +              goto fail;
 +      }
 +
 +      return DIV_ROUND_CLOSEST(vco, div_table[cdclk_sel]);
 +
 +fail:
 +      DRM_ERROR("Unable to determine CDCLK. HPLL VCO=%u kHz, CFGC=0x%04x\n", vco, tmp);
 +      return 200000;
 +}
 +
 +static int g33_get_display_clock_speed(struct drm_device *dev)
 +{
 +      static const uint8_t div_3200[] = { 12, 10,  8,  7, 5, 16 };
 +      static const uint8_t div_4000[] = { 14, 12, 10,  8, 6, 20 };
 +      static const uint8_t div_4800[] = { 20, 14, 12, 10, 8, 24 };
 +      static const uint8_t div_5333[] = { 20, 16, 12, 12, 8, 28 };
 +      const uint8_t *div_table;
 +      unsigned int cdclk_sel, vco = intel_hpll_vco(dev);
 +      uint16_t tmp = 0;
 +
 +      pci_read_config_word(dev->pdev, GCFGC, &tmp);
 +
 +      cdclk_sel = (tmp >> 4) & 0x7;
 +
 +      if (cdclk_sel >= ARRAY_SIZE(div_3200))
 +              goto fail;
 +
 +      switch (vco) {
 +      case 3200000:
 +              div_table = div_3200;
 +              break;
 +      case 4000000:
 +              div_table = div_4000;
 +              break;
 +      case 4800000:
 +              div_table = div_4800;
 +              break;
 +      case 5333333:
 +              div_table = div_5333;
 +              break;
 +      default:
 +              goto fail;
 +      }
 +
 +      return DIV_ROUND_CLOSEST(vco, div_table[cdclk_sel]);
 +
 +fail:
 +      DRM_ERROR("Unable to determine CDCLK. HPLL VCO=%u kHz, CFGC=0x%08x\n", vco, tmp);
 +      return 190476;
 +}
 +
  static void
  intel_reduce_m_n_ratio(uint32_t *num, uint32_t *den)
  {
@@@ -7202,8 -7064,8 +7202,8 @@@ void intel_dp_set_m_n(struct intel_crt
                intel_cpu_transcoder_set_m_n(crtc, dp_m_n, dp_m2_n2);
  }
  
 -static void vlv_update_pll(struct intel_crtc *crtc,
 -                         struct intel_crtc_state *pipe_config)
 +static void vlv_compute_dpll(struct intel_crtc *crtc,
 +                           struct intel_crtc_state *pipe_config)
  {
        u32 dpll, dpll_md;
  
         * clock for pipe B, since VGA hotplug / manual detection depends
         * on it.
         */
 -      dpll = DPLL_EXT_BUFFER_ENABLE_VLV | DPLL_REFA_CLK_ENABLE_VLV |
 -              DPLL_VGA_MODE_DIS | DPLL_INTEGRATED_CLOCK_VLV;
 +      dpll = DPLL_EXT_BUFFER_ENABLE_VLV | DPLL_REF_CLK_ENABLE_VLV |
 +              DPLL_VGA_MODE_DIS | DPLL_INTEGRATED_REF_CLK_VLV;
        /* We should never disable this, set it here for state tracking */
        if (crtc->pipe == PIPE_B)
                dpll |= DPLL_INTEGRATED_CRI_CLK_VLV;
@@@ -7316,11 -7178,11 +7316,11 @@@ static void vlv_prepare_pll(struct inte
        mutex_unlock(&dev_priv->sb_lock);
  }
  
 -static void chv_update_pll(struct intel_crtc *crtc,
 -                         struct intel_crtc_state *pipe_config)
 +static void chv_compute_dpll(struct intel_crtc *crtc,
 +                           struct intel_crtc_state *pipe_config)
  {
 -      pipe_config->dpll_hw_state.dpll = DPLL_SSC_REF_CLOCK_CHV |
 -              DPLL_REFA_CLK_ENABLE_VLV | DPLL_VGA_MODE_DIS |
 +      pipe_config->dpll_hw_state.dpll = DPLL_SSC_REF_CLK_CHV |
 +              DPLL_REF_CLK_ENABLE_VLV | DPLL_VGA_MODE_DIS |
                DPLL_VCO_ENABLE;
        if (crtc->pipe != PIPE_A)
                pipe_config->dpll_hw_state.dpll |= DPLL_INTEGRATED_CRI_CLK_VLV;
@@@ -7456,11 -7318,11 +7456,11 @@@ void vlv_force_pll_on(struct drm_devic
        };
  
        if (IS_CHERRYVIEW(dev)) {
 -              chv_update_pll(crtc, &pipe_config);
 +              chv_compute_dpll(crtc, &pipe_config);
                chv_prepare_pll(crtc, &pipe_config);
                chv_enable_pll(crtc, &pipe_config);
        } else {
 -              vlv_update_pll(crtc, &pipe_config);
 +              vlv_compute_dpll(crtc, &pipe_config);
                vlv_prepare_pll(crtc, &pipe_config);
                vlv_enable_pll(crtc, &pipe_config);
        }
@@@ -7482,10 -7344,10 +7482,10 @@@ void vlv_force_pll_off(struct drm_devic
                vlv_disable_pll(to_i915(dev), pipe);
  }
  
 -static void i9xx_update_pll(struct intel_crtc *crtc,
 -                          struct intel_crtc_state *crtc_state,
 -                          intel_clock_t *reduced_clock,
 -                          int num_connectors)
 +static void i9xx_compute_dpll(struct intel_crtc *crtc,
 +                            struct intel_crtc_state *crtc_state,
 +                            intel_clock_t *reduced_clock,
 +                            int num_connectors)
  {
        struct drm_device *dev = crtc->base.dev;
        struct drm_i915_private *dev_priv = dev->dev_private;
        }
  }
  
 -static void i8xx_update_pll(struct intel_crtc *crtc,
 -                          struct intel_crtc_state *crtc_state,
 -                          intel_clock_t *reduced_clock,
 -                          int num_connectors)
 +static void i8xx_compute_dpll(struct intel_crtc *crtc,
 +                            struct intel_crtc_state *crtc_state,
 +                            intel_clock_t *reduced_clock,
 +                            int num_connectors)
  {
        struct drm_device *dev = crtc->base.dev;
        struct drm_i915_private *dev_priv = dev->dev_private;
@@@ -7722,14 -7584,9 +7722,14 @@@ void intel_mode_from_pipe_config(struc
        mode->vsync_end = pipe_config->base.adjusted_mode.crtc_vsync_end;
  
        mode->flags = pipe_config->base.adjusted_mode.flags;
 +      mode->type = DRM_MODE_TYPE_DRIVER;
  
        mode->clock = pipe_config->base.adjusted_mode.crtc_clock;
        mode->flags |= pipe_config->base.adjusted_mode.flags;
 +
 +      mode->hsync = drm_mode_hsync(mode);
 +      mode->vrefresh = drm_mode_vrefresh(mode);
 +      drm_mode_set_name(mode);
  }
  
  static void i9xx_set_pipeconf(struct intel_crtc *intel_crtc)
@@@ -7801,9 -7658,9 +7801,9 @@@ static int i9xx_crtc_compute_clock(stru
        struct drm_device *dev = crtc->base.dev;
        struct drm_i915_private *dev_priv = dev->dev_private;
        int refclk, num_connectors = 0;
 -      intel_clock_t clock, reduced_clock;
 -      bool ok, has_reduced_clock = false;
 -      bool is_lvds = false, is_dsi = false;
 +      intel_clock_t clock;
 +      bool ok;
 +      bool is_dsi = false;
        struct intel_encoder *encoder;
        const intel_limit_t *limit;
        struct drm_atomic_state *state = crtc_state->base.state;
                encoder = to_intel_encoder(connector_state->best_encoder);
  
                switch (encoder->type) {
 -              case INTEL_OUTPUT_LVDS:
 -                      is_lvds = true;
 -                      break;
                case INTEL_OUTPUT_DSI:
                        is_dsi = true;
                        break;
                        return -EINVAL;
                }
  
 -              if (is_lvds && dev_priv->lvds_downclock_avail) {
 -                      /*
 -                       * Ensure we match the reduced clock's P to the target
 -                       * clock.  If the clocks don't match, we can't switch
 -                       * the display clock by using the FP0/FP1. In such case
 -                       * we will disable the LVDS downclock feature.
 -                       */
 -                      has_reduced_clock =
 -                              dev_priv->display.find_dpll(limit, crtc_state,
 -                                                          dev_priv->lvds_downclock,
 -                                                          refclk, &clock,
 -                                                          &reduced_clock);
 -              }
                /* Compat-code for transition, will disappear. */
                crtc_state->dpll.n = clock.n;
                crtc_state->dpll.m1 = clock.m1;
        }
  
        if (IS_GEN2(dev)) {
 -              i8xx_update_pll(crtc, crtc_state,
 -                              has_reduced_clock ? &reduced_clock : NULL,
 -                              num_connectors);
 +              i8xx_compute_dpll(crtc, crtc_state, NULL,
 +                                num_connectors);
        } else if (IS_CHERRYVIEW(dev)) {
 -              chv_update_pll(crtc, crtc_state);
 +              chv_compute_dpll(crtc, crtc_state);
        } else if (IS_VALLEYVIEW(dev)) {
 -              vlv_update_pll(crtc, crtc_state);
 +              vlv_compute_dpll(crtc, crtc_state);
        } else {
 -              i9xx_update_pll(crtc, crtc_state,
 -                              has_reduced_clock ? &reduced_clock : NULL,
 -                              num_connectors);
 +              i9xx_compute_dpll(crtc, crtc_state, NULL,
 +                                num_connectors);
        }
  
        return 0;
@@@ -7929,7 -7804,10 +7929,7 @@@ static void vlv_crtc_clock_get(struct i
        clock.p1 = (mdiv >> DPIO_P1_SHIFT) & 7;
        clock.p2 = (mdiv >> DPIO_P2_SHIFT) & 0x1f;
  
 -      vlv_clock(refclk, &clock);
 -
 -      /* clock.dot is the fast clock */
 -      pipe_config->port_clock = clock.dot / 5;
 +      pipe_config->port_clock = vlv_calc_dpll_params(refclk, &clock);
  }
  
  static void
@@@ -8028,7 -7906,10 +8028,7 @@@ static void chv_crtc_clock_get(struct i
        clock.p1 = (cmn_dw13 >> DPIO_CHV_P1_DIV_SHIFT) & 0x7;
        clock.p2 = (cmn_dw13 >> DPIO_CHV_P2_DIV_SHIFT) & 0x1f;
  
 -      chv_clock(refclk, &clock);
 -
 -      /* clock.dot is the fast clock */
 -      pipe_config->port_clock = clock.dot / 5;
 +      pipe_config->port_clock = chv_calc_dpll_params(refclk, &clock);
  }
  
  static bool i9xx_get_pipe_config(struct intel_crtc *crtc,
@@@ -8677,7 -8558,9 +8677,7 @@@ static bool ironlake_compute_clocks(str
        struct drm_i915_private *dev_priv = dev->dev_private;
        int refclk;
        const intel_limit_t *limit;
 -      bool ret, is_lvds = false;
 -
 -      is_lvds = intel_pipe_will_have_type(crtc_state, INTEL_OUTPUT_LVDS);
 +      bool ret;
  
        refclk = ironlake_get_refclk(crtc_state);
  
        if (!ret)
                return false;
  
 -      if (is_lvds && dev_priv->lvds_downclock_avail) {
 -              /*
 -               * Ensure we match the reduced clock's P to the target clock.
 -               * If the clocks don't match, we can't switch the display clock
 -               * by using the FP0/FP1. In such case we will disable the LVDS
 -               * downclock feature.
 -              */
 -              *has_reduced_clock =
 -                      dev_priv->display.find_dpll(limit, crtc_state,
 -                                                  dev_priv->lvds_downclock,
 -                                                  refclk, clock,
 -                                                  reduced_clock);
 -      }
 -
        return true;
  }
  
@@@ -9400,7 -9297,6 +9400,7 @@@ static void hsw_restore_lcpll(struct dr
        }
  
        intel_uncore_forcewake_put(dev_priv, FORCEWAKE_ALL);
 +      intel_update_cdclk(dev_priv->dev);
  }
  
  /*
@@@ -9462,189 -9358,50 +9462,189 @@@ void hsw_disable_pc8(struct drm_i915_pr
        intel_prepare_ddi(dev);
  }
  
 -static void broxton_modeset_global_resources(struct drm_atomic_state *old_state)
 +static void broxton_modeset_commit_cdclk(struct drm_atomic_state *old_state)
  {
        struct drm_device *dev = old_state->dev;
 -      struct drm_i915_private *dev_priv = dev->dev_private;
 -      int max_pixclk = intel_mode_max_pixclk(dev, NULL);
 -      int req_cdclk;
 -
 -      /* see the comment in valleyview_modeset_global_resources */
 -      if (WARN_ON(max_pixclk < 0))
 -              return;
 -
 -      req_cdclk = broxton_calc_cdclk(dev_priv, max_pixclk);
 +      unsigned int req_cdclk = to_intel_atomic_state(old_state)->cdclk;
  
 -      if (req_cdclk != dev_priv->cdclk_freq)
 -              broxton_set_cdclk(dev, req_cdclk);
 +      broxton_set_cdclk(dev, req_cdclk);
  }
  
 -static int haswell_crtc_compute_clock(struct intel_crtc *crtc,
 -                                    struct intel_crtc_state *crtc_state)
 +/* compute the max rate for new configuration */
 +static int ilk_max_pixel_rate(struct drm_atomic_state *state)
  {
 -      if (!intel_ddi_pll_select(crtc, crtc_state))
 -              return -EINVAL;
 +      struct intel_crtc *intel_crtc;
 +      struct intel_crtc_state *crtc_state;
 +      int max_pixel_rate = 0;
  
 -      crtc->lowfreq_avail = false;
 +      for_each_intel_crtc(state->dev, intel_crtc) {
 +              int pixel_rate;
  
 -      return 0;
 +              crtc_state = intel_atomic_get_crtc_state(state, intel_crtc);
 +              if (IS_ERR(crtc_state))
 +                      return PTR_ERR(crtc_state);
 +
 +              if (!crtc_state->base.enable)
 +                      continue;
 +
 +              pixel_rate = ilk_pipe_pixel_rate(crtc_state);
 +
 +              /* pixel rate mustn't exceed 95% of cdclk with IPS on BDW */
 +              if (IS_BROADWELL(state->dev) && crtc_state->ips_enabled)
 +                      pixel_rate = DIV_ROUND_UP(pixel_rate * 100, 95);
 +
 +              max_pixel_rate = max(max_pixel_rate, pixel_rate);
 +      }
 +
 +      return max_pixel_rate;
  }
  
 -static void bxt_get_ddi_pll(struct drm_i915_private *dev_priv,
 -                              enum port port,
 -                              struct intel_crtc_state *pipe_config)
 +static void broadwell_set_cdclk(struct drm_device *dev, int cdclk)
  {
 -      switch (port) {
 -      case PORT_A:
 -              pipe_config->ddi_pll_sel = SKL_DPLL0;
 -              pipe_config->shared_dpll = DPLL_ID_SKL_DPLL1;
 -              break;
 -      case PORT_B:
 -              pipe_config->ddi_pll_sel = SKL_DPLL1;
 -              pipe_config->shared_dpll = DPLL_ID_SKL_DPLL2;
 -              break;
 -      case PORT_C:
 -              pipe_config->ddi_pll_sel = SKL_DPLL2;
 -              pipe_config->shared_dpll = DPLL_ID_SKL_DPLL3;
 +      struct drm_i915_private *dev_priv = dev->dev_private;
 +      uint32_t val, data;
 +      int ret;
 +
 +      if (WARN((I915_READ(LCPLL_CTL) &
 +                (LCPLL_PLL_DISABLE | LCPLL_PLL_LOCK |
 +                 LCPLL_CD_CLOCK_DISABLE | LCPLL_ROOT_CD_CLOCK_DISABLE |
 +                 LCPLL_CD2X_CLOCK_DISABLE | LCPLL_POWER_DOWN_ALLOW |
 +                 LCPLL_CD_SOURCE_FCLK)) != LCPLL_PLL_LOCK,
 +               "trying to change cdclk frequency with cdclk not enabled\n"))
 +              return;
 +
 +      mutex_lock(&dev_priv->rps.hw_lock);
 +      ret = sandybridge_pcode_write(dev_priv,
 +                                    BDW_PCODE_DISPLAY_FREQ_CHANGE_REQ, 0x0);
 +      mutex_unlock(&dev_priv->rps.hw_lock);
 +      if (ret) {
 +              DRM_ERROR("failed to inform pcode about cdclk change\n");
 +              return;
 +      }
 +
 +      val = I915_READ(LCPLL_CTL);
 +      val |= LCPLL_CD_SOURCE_FCLK;
 +      I915_WRITE(LCPLL_CTL, val);
 +
 +      if (wait_for_atomic_us(I915_READ(LCPLL_CTL) &
 +                             LCPLL_CD_SOURCE_FCLK_DONE, 1))
 +              DRM_ERROR("Switching to FCLK failed\n");
 +
 +      val = I915_READ(LCPLL_CTL);
 +      val &= ~LCPLL_CLK_FREQ_MASK;
 +
 +      switch (cdclk) {
 +      case 450000:
 +              val |= LCPLL_CLK_FREQ_450;
 +              data = 0;
 +              break;
 +      case 540000:
 +              val |= LCPLL_CLK_FREQ_54O_BDW;
 +              data = 1;
 +              break;
 +      case 337500:
 +              val |= LCPLL_CLK_FREQ_337_5_BDW;
 +              data = 2;
 +              break;
 +      case 675000:
 +              val |= LCPLL_CLK_FREQ_675_BDW;
 +              data = 3;
 +              break;
 +      default:
 +              WARN(1, "invalid cdclk frequency\n");
 +              return;
 +      }
 +
 +      I915_WRITE(LCPLL_CTL, val);
 +
 +      val = I915_READ(LCPLL_CTL);
 +      val &= ~LCPLL_CD_SOURCE_FCLK;
 +      I915_WRITE(LCPLL_CTL, val);
 +
 +      if (wait_for_atomic_us((I915_READ(LCPLL_CTL) &
 +                              LCPLL_CD_SOURCE_FCLK_DONE) == 0, 1))
 +              DRM_ERROR("Switching back to LCPLL failed\n");
 +
 +      mutex_lock(&dev_priv->rps.hw_lock);
 +      sandybridge_pcode_write(dev_priv, HSW_PCODE_DE_WRITE_FREQ_REQ, data);
 +      mutex_unlock(&dev_priv->rps.hw_lock);
 +
 +      intel_update_cdclk(dev);
 +
 +      WARN(cdclk != dev_priv->cdclk_freq,
 +           "cdclk requested %d kHz but got %d kHz\n",
 +           cdclk, dev_priv->cdclk_freq);
 +}
 +
 +static int broadwell_modeset_calc_cdclk(struct drm_atomic_state *state)
 +{
 +      struct drm_i915_private *dev_priv = to_i915(state->dev);
 +      int max_pixclk = ilk_max_pixel_rate(state);
 +      int cdclk;
 +
 +      /*
 +       * FIXME should also account for plane ratio
 +       * once 64bpp pixel formats are supported.
 +       */
 +      if (max_pixclk > 540000)
 +              cdclk = 675000;
 +      else if (max_pixclk > 450000)
 +              cdclk = 540000;
 +      else if (max_pixclk > 337500)
 +              cdclk = 450000;
 +      else
 +              cdclk = 337500;
 +
 +      /*
 +       * FIXME move the cdclk caclulation to
 +       * compute_config() so we can fail gracegully.
 +       */
 +      if (cdclk > dev_priv->max_cdclk_freq) {
 +              DRM_ERROR("requested cdclk (%d kHz) exceeds max (%d kHz)\n",
 +                        cdclk, dev_priv->max_cdclk_freq);
 +              cdclk = dev_priv->max_cdclk_freq;
 +      }
 +
 +      to_intel_atomic_state(state)->cdclk = cdclk;
 +
 +      return 0;
 +}
 +
 +static void broadwell_modeset_commit_cdclk(struct drm_atomic_state *old_state)
 +{
 +      struct drm_device *dev = old_state->dev;
 +      unsigned int req_cdclk = to_intel_atomic_state(old_state)->cdclk;
 +
 +      broadwell_set_cdclk(dev, req_cdclk);
 +}
 +
 +static int haswell_crtc_compute_clock(struct intel_crtc *crtc,
 +                                    struct intel_crtc_state *crtc_state)
 +{
 +      if (!intel_ddi_pll_select(crtc, crtc_state))
 +              return -EINVAL;
 +
 +      crtc->lowfreq_avail = false;
 +
 +      return 0;
 +}
 +
 +static void bxt_get_ddi_pll(struct drm_i915_private *dev_priv,
 +                              enum port port,
 +                              struct intel_crtc_state *pipe_config)
 +{
 +      switch (port) {
 +      case PORT_A:
 +              pipe_config->ddi_pll_sel = SKL_DPLL0;
 +              pipe_config->shared_dpll = DPLL_ID_SKL_DPLL1;
 +              break;
 +      case PORT_B:
 +              pipe_config->ddi_pll_sel = SKL_DPLL1;
 +              pipe_config->shared_dpll = DPLL_ID_SKL_DPLL2;
 +              break;
 +      case PORT_C:
 +              pipe_config->ddi_pll_sel = SKL_DPLL2;
 +              pipe_config->shared_dpll = DPLL_ID_SKL_DPLL3;
                break;
        default:
                DRM_ERROR("Incorrect port type\n");
@@@ -10221,7 -9978,7 +10221,7 @@@ bool intel_get_load_detect_pipe(struct 
  retry:
        ret = drm_modeset_lock(&config->connection_mutex, ctx);
        if (ret)
 -              goto fail_unlock;
 +              goto fail;
  
        /*
         * Algorithm gets a little messy:
  
                ret = drm_modeset_lock(&crtc->mutex, ctx);
                if (ret)
 -                      goto fail_unlock;
 +                      goto fail;
                ret = drm_modeset_lock(&crtc->primary->mutex, ctx);
                if (ret)
 -                      goto fail_unlock;
 +                      goto fail;
  
                old->dpms_mode = connector->dpms;
                old->load_detect_temp = false;
                        continue;
                if (possible_crtc->state->enable)
                        continue;
 -              /* This can occur when applying the pipe A quirk on resume. */
 -              if (to_intel_crtc(possible_crtc)->new_enabled)
 -                      continue;
  
                crtc = possible_crtc;
                break;
         */
        if (!crtc) {
                DRM_DEBUG_KMS("no pipe available for load-detect\n");
 -              goto fail_unlock;
 +              goto fail;
        }
  
        ret = drm_modeset_lock(&crtc->mutex, ctx);
        if (ret)
 -              goto fail_unlock;
 +              goto fail;
        ret = drm_modeset_lock(&crtc->primary->mutex, ctx);
        if (ret)
 -              goto fail_unlock;
 -      intel_encoder->new_crtc = to_intel_crtc(crtc);
 -      to_intel_connector(connector)->new_encoder = intel_encoder;
 +              goto fail;
  
        intel_crtc = to_intel_crtc(crtc);
 -      intel_crtc->new_enabled = true;
        old->dpms_mode = connector->dpms;
        old->load_detect_temp = true;
        old->release_fb = NULL;
  
        drm_mode_copy(&crtc_state->base.mode, mode);
  
 -      if (intel_set_mode(crtc, state, true)) {
 +      if (drm_atomic_commit(state)) {
                DRM_DEBUG_KMS("failed to set mode on load-detect pipe\n");
                if (old->release_fb)
                        old->release_fb->funcs->destroy(old->release_fb);
        intel_wait_for_vblank(dev, intel_crtc->pipe);
        return true;
  
 - fail:
 -      intel_crtc->new_enabled = crtc->state->enable;
 -fail_unlock:
 +fail:
        drm_atomic_state_free(state);
        state = NULL;
  
@@@ -10395,6 -10160,10 +10395,6 @@@ void intel_release_load_detect_pipe(str
                if (IS_ERR(crtc_state))
                        goto fail;
  
 -              to_intel_connector(connector)->new_encoder = NULL;
 -              intel_encoder->new_crtc = NULL;
 -              intel_crtc->new_enabled = false;
 -
                connector_state->best_encoder = NULL;
                connector_state->crtc = NULL;
  
                if (ret)
                        goto fail;
  
 -              ret = intel_set_mode(crtc, state, true);
 +              ret = drm_atomic_commit(state);
                if (ret)
                        goto fail;
  
@@@ -10453,7 -10222,6 +10453,7 @@@ static void i9xx_crtc_clock_get(struct 
        u32 dpll = pipe_config->dpll_hw_state.dpll;
        u32 fp;
        intel_clock_t clock;
 +      int port_clock;
        int refclk = i9xx_pll_refclk(dev, pipe_config);
  
        if ((dpll & DISPLAY_RATE_SELECT_FPA1) == 0)
                }
  
                if (IS_PINEVIEW(dev))
 -                      pineview_clock(refclk, &clock);
 +                      port_clock = pnv_calc_dpll_params(refclk, &clock);
                else
 -                      i9xx_clock(refclk, &clock);
 +                      port_clock = i9xx_calc_dpll_params(refclk, &clock);
        } else {
                u32 lvds = IS_I830(dev) ? 0 : I915_READ(LVDS);
                bool is_lvds = (pipe == 1) && (lvds & LVDS_PORT_EN);
                                clock.p2 = 2;
                }
  
 -              i9xx_clock(refclk, &clock);
 +              port_clock = i9xx_calc_dpll_params(refclk, &clock);
        }
  
        /*
         * port_clock to compute adjusted_mode.crtc_clock in the
         * encoder's get_config() function.
         */
 -      pipe_config->port_clock = clock.dot;
 +      pipe_config->port_clock = port_clock;
  }
  
  int intel_dotclock_calculate(int link_freq,
@@@ -10619,6 -10387,42 +10619,6 @@@ struct drm_display_mode *intel_crtc_mod
        return mode;
  }
  
 -static void intel_decrease_pllclock(struct drm_crtc *crtc)
 -{
 -      struct drm_device *dev = crtc->dev;
 -      struct drm_i915_private *dev_priv = dev->dev_private;
 -      struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
 -
 -      if (!HAS_GMCH_DISPLAY(dev))
 -              return;
 -
 -      if (!dev_priv->lvds_downclock_avail)
 -              return;
 -
 -      /*
 -       * Since this is called by a timer, we should never get here in
 -       * the manual case.
 -       */
 -      if (!HAS_PIPE_CXSR(dev) && intel_crtc->lowfreq_avail) {
 -              int pipe = intel_crtc->pipe;
 -              int dpll_reg = DPLL(pipe);
 -              int dpll;
 -
 -              DRM_DEBUG_DRIVER("downclocking LVDS\n");
 -
 -              assert_panel_unlocked(dev_priv, pipe);
 -
 -              dpll = I915_READ(dpll_reg);
 -              dpll |= DISPLAY_RATE_SELECT_FPA1;
 -              I915_WRITE(dpll_reg, dpll);
 -              intel_wait_for_vblank(dev, pipe);
 -              dpll = I915_READ(dpll_reg);
 -              if (!(dpll & DISPLAY_RATE_SELECT_FPA1))
 -                      DRM_DEBUG_DRIVER("failed to downclock LVDS!\n");
 -      }
 -
 -}
 -
  void intel_mark_busy(struct drm_device *dev)
  {
        struct drm_i915_private *dev_priv = dev->dev_private;
  void intel_mark_idle(struct drm_device *dev)
  {
        struct drm_i915_private *dev_priv = dev->dev_private;
 -      struct drm_crtc *crtc;
  
        if (!dev_priv->mm.busy)
                return;
  
        dev_priv->mm.busy = false;
  
 -      for_each_crtc(dev, crtc) {
 -              if (!crtc->primary->fb)
 -                      continue;
 -
 -              intel_decrease_pllclock(crtc);
 -      }
 -
        if (INTEL_INFO(dev)->gen >= 6)
                gen6_rps_idle(dev->dev_private);
  
@@@ -10673,23 -10485,24 +10673,23 @@@ static void intel_unpin_work_fn(struct 
  {
        struct intel_unpin_work *work =
                container_of(__work, struct intel_unpin_work, work);
 -      struct drm_device *dev = work->crtc->dev;
 -      enum pipe pipe = to_intel_crtc(work->crtc)->pipe;
 +      struct intel_crtc *crtc = to_intel_crtc(work->crtc);
 +      struct drm_device *dev = crtc->base.dev;
 +      struct drm_plane *primary = crtc->base.primary;
  
        mutex_lock(&dev->struct_mutex);
 -      intel_unpin_fb_obj(work->old_fb, work->crtc->primary->state);
 +      intel_unpin_fb_obj(work->old_fb, primary->state);
        drm_gem_object_unreference(&work->pending_flip_obj->base);
  
 -      intel_fbc_update(dev);
 -
        if (work->flip_queued_req)
                i915_gem_request_assign(&work->flip_queued_req, NULL);
        mutex_unlock(&dev->struct_mutex);
  
 -      intel_frontbuffer_flip_complete(dev, INTEL_FRONTBUFFER_PRIMARY(pipe));
 +      intel_frontbuffer_flip_complete(dev, to_intel_plane(primary)->frontbuffer_bit);
        drm_framebuffer_unreference(work->old_fb);
  
 -      BUG_ON(atomic_read(&to_intel_crtc(work->crtc)->unpin_work_count) == 0);
 -      atomic_dec(&to_intel_crtc(work->crtc)->unpin_work_count);
 +      BUG_ON(atomic_read(&crtc->unpin_work_count) == 0);
 +      atomic_dec(&crtc->unpin_work_count);
  
        kfree(work);
  }
@@@ -10822,15 -10635,14 +10822,15 @@@ static int intel_gen2_queue_flip(struc
                                 struct drm_crtc *crtc,
                                 struct drm_framebuffer *fb,
                                 struct drm_i915_gem_object *obj,
 -                               struct intel_engine_cs *ring,
 +                               struct drm_i915_gem_request *req,
                                 uint32_t flags)
  {
 +      struct intel_engine_cs *ring = req->ring;
        struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
        u32 flip_mask;
        int ret;
  
 -      ret = intel_ring_begin(ring, 6);
 +      ret = intel_ring_begin(req, 6);
        if (ret)
                return ret;
  
        intel_ring_emit(ring, 0); /* aux display base address, unused */
  
        intel_mark_page_flip_active(intel_crtc);
 -      __intel_ring_advance(ring);
        return 0;
  }
  
@@@ -10857,15 -10670,14 +10857,15 @@@ static int intel_gen3_queue_flip(struc
                                 struct drm_crtc *crtc,
                                 struct drm_framebuffer *fb,
                                 struct drm_i915_gem_object *obj,
 -                               struct intel_engine_cs *ring,
 +                               struct drm_i915_gem_request *req,
                                 uint32_t flags)
  {
 +      struct intel_engine_cs *ring = req->ring;
        struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
        u32 flip_mask;
        int ret;
  
 -      ret = intel_ring_begin(ring, 6);
 +      ret = intel_ring_begin(req, 6);
        if (ret)
                return ret;
  
        intel_ring_emit(ring, MI_NOOP);
  
        intel_mark_page_flip_active(intel_crtc);
 -      __intel_ring_advance(ring);
        return 0;
  }
  
@@@ -10889,16 -10702,15 +10889,16 @@@ static int intel_gen4_queue_flip(struc
                                 struct drm_crtc *crtc,
                                 struct drm_framebuffer *fb,
                                 struct drm_i915_gem_object *obj,
 -                               struct intel_engine_cs *ring,
 +                               struct drm_i915_gem_request *req,
                                 uint32_t flags)
  {
 +      struct intel_engine_cs *ring = req->ring;
        struct drm_i915_private *dev_priv = dev->dev_private;
        struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
        uint32_t pf, pipesrc;
        int ret;
  
 -      ret = intel_ring_begin(ring, 4);
 +      ret = intel_ring_begin(req, 4);
        if (ret)
                return ret;
  
        intel_ring_emit(ring, pf | pipesrc);
  
        intel_mark_page_flip_active(intel_crtc);
 -      __intel_ring_advance(ring);
        return 0;
  }
  
@@@ -10928,16 -10741,15 +10928,16 @@@ static int intel_gen6_queue_flip(struc
                                 struct drm_crtc *crtc,
                                 struct drm_framebuffer *fb,
                                 struct drm_i915_gem_object *obj,
 -                               struct intel_engine_cs *ring,
 +                               struct drm_i915_gem_request *req,
                                 uint32_t flags)
  {
 +      struct intel_engine_cs *ring = req->ring;
        struct drm_i915_private *dev_priv = dev->dev_private;
        struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
        uint32_t pf, pipesrc;
        int ret;
  
 -      ret = intel_ring_begin(ring, 4);
 +      ret = intel_ring_begin(req, 4);
        if (ret)
                return ret;
  
        intel_ring_emit(ring, pf | pipesrc);
  
        intel_mark_page_flip_active(intel_crtc);
 -      __intel_ring_advance(ring);
        return 0;
  }
  
@@@ -10964,10 -10777,9 +10964,10 @@@ static int intel_gen7_queue_flip(struc
                                 struct drm_crtc *crtc,
                                 struct drm_framebuffer *fb,
                                 struct drm_i915_gem_object *obj,
 -                               struct intel_engine_cs *ring,
 +                               struct drm_i915_gem_request *req,
                                 uint32_t flags)
  {
 +      struct intel_engine_cs *ring = req->ring;
        struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
        uint32_t plane_bit = 0;
        int len, ret;
         * then do the cacheline alignment, and finally emit the
         * MI_DISPLAY_FLIP.
         */
 -      ret = intel_ring_cacheline_align(ring);
 +      ret = intel_ring_cacheline_align(req);
        if (ret)
                return ret;
  
 -      ret = intel_ring_begin(ring, len);
 +      ret = intel_ring_begin(req, len);
        if (ret)
                return ret;
  
        intel_ring_emit(ring, (MI_NOOP));
  
        intel_mark_page_flip_active(intel_crtc);
 -      __intel_ring_advance(ring);
        return 0;
  }
  
@@@ -11160,11 -10973,12 +11160,11 @@@ static void ilk_do_mmio_flip(struct int
  static void intel_do_mmio_flip(struct intel_crtc *intel_crtc)
  {
        struct drm_device *dev = intel_crtc->base.dev;
 -      bool atomic_update;
        u32 start_vbl_count;
  
        intel_mark_page_flip_active(intel_crtc);
  
 -      atomic_update = intel_pipe_update_start(intel_crtc, &start_vbl_count);
 +      intel_pipe_update_start(intel_crtc, &start_vbl_count);
  
        if (INTEL_INFO(dev)->gen >= 9)
                skl_do_mmio_flip(intel_crtc);
                /* use_mmio_flip() retricts MMIO flips to ilk+ */
                ilk_do_mmio_flip(intel_crtc);
  
 -      if (atomic_update)
 -              intel_pipe_update_end(intel_crtc, start_vbl_count);
 +      intel_pipe_update_end(intel_crtc, start_vbl_count);
  }
  
  static void intel_mmio_flip_work_func(struct work_struct *work)
@@@ -11219,7 -11034,7 +11219,7 @@@ static int intel_default_queue_flip(str
                                    struct drm_crtc *crtc,
                                    struct drm_framebuffer *fb,
                                    struct drm_i915_gem_object *obj,
 -                                  struct intel_engine_cs *ring,
 +                                  struct drm_i915_gem_request *req,
                                    uint32_t flags)
  {
        return -ENODEV;
@@@ -11305,7 -11120,6 +11305,7 @@@ static int intel_crtc_page_flip(struct 
        struct intel_unpin_work *work;
        struct intel_engine_cs *ring;
        bool mmio_flip;
 +      struct drm_i915_gem_request *request = NULL;
        int ret;
  
        /*
         */
        ret = intel_pin_and_fence_fb_obj(crtc->primary, fb,
                                         crtc->primary->state,
 -                                       mmio_flip ? i915_gem_request_get_ring(obj->last_write_req) : ring);
 +                                       mmio_flip ? i915_gem_request_get_ring(obj->last_write_req) : ring, &request);
        if (ret)
                goto cleanup_pending;
  
                i915_gem_request_assign(&work->flip_queued_req,
                                        obj->last_write_req);
        } else {
 -              if (obj->last_write_req) {
 -                      ret = i915_gem_check_olr(obj->last_write_req);
 +              if (!request) {
 +                      ret = i915_gem_request_alloc(ring, ring->default_context, &request);
                        if (ret)
                                goto cleanup_unpin;
                }
  
 -              ret = dev_priv->display.queue_flip(dev, crtc, fb, obj, ring,
 +              ret = dev_priv->display.queue_flip(dev, crtc, fb, obj, request,
                                                   page_flip_flags);
                if (ret)
                        goto cleanup_unpin;
  
 -              i915_gem_request_assign(&work->flip_queued_req,
 -                                      intel_ring_get_request(ring));
 +              i915_gem_request_assign(&work->flip_queued_req, request);
        }
  
 +      if (request)
 +              i915_add_request_no_flush(request);
 +
        work->flip_queued_vblank = drm_crtc_vblank_count(crtc);
        work->enable_stall_check = true;
  
        i915_gem_track_fb(intel_fb_obj(work->old_fb), obj,
 -                        INTEL_FRONTBUFFER_PRIMARY(pipe));
 -
 -      intel_fbc_disable(dev);
 -      intel_frontbuffer_flip_prepare(dev, INTEL_FRONTBUFFER_PRIMARY(pipe));
 +                        to_intel_plane(primary)->frontbuffer_bit);
        mutex_unlock(&dev->struct_mutex);
  
 +      intel_fbc_disable_crtc(intel_crtc);
 +      intel_frontbuffer_flip_prepare(dev,
 +                                     to_intel_plane(primary)->frontbuffer_bit);
 +
        trace_i915_flip_request(intel_crtc->plane, obj);
  
        return 0;
  cleanup_unpin:
        intel_unpin_fb_obj(fb, crtc->primary->state);
  cleanup_pending:
 +      if (request)
 +              i915_gem_request_cancel(request);
        atomic_dec(&intel_crtc->unpin_work_count);
        mutex_unlock(&dev->struct_mutex);
  cleanup:
@@@ -11483,35 -11292,8 +11483,35 @@@ free_work
        kfree(work);
  
        if (ret == -EIO) {
 +              struct drm_atomic_state *state;
 +              struct drm_plane_state *plane_state;
 +
  out_hang:
 -              ret = intel_plane_restore(primary);
 +              state = drm_atomic_state_alloc(dev);
 +              if (!state)
 +                      return -ENOMEM;
 +              state->acquire_ctx = drm_modeset_legacy_acquire_ctx(crtc);
 +
 +retry:
 +              plane_state = drm_atomic_get_plane_state(state, primary);
 +              ret = PTR_ERR_OR_ZERO(plane_state);
 +              if (!ret) {
 +                      drm_atomic_set_fb_for_plane(plane_state, fb);
 +
 +                      ret = drm_atomic_set_crtc_for_plane(plane_state, crtc);
 +                      if (!ret)
 +                              ret = drm_atomic_commit(state);
 +              }
 +
 +              if (ret == -EDEADLK) {
 +                      drm_modeset_backoff(state->acquire_ctx);
 +                      drm_atomic_state_clear(state);
 +                      goto retry;
 +              }
 +
 +              if (ret)
 +                      drm_atomic_state_free(state);
 +
                if (ret == 0 && event) {
                        spin_lock_irq(&dev->event_lock);
                        drm_send_vblank_event(dev, pipe, event);
        return ret;
  }
  
 -static const struct drm_crtc_helper_funcs intel_helper_funcs = {
 -      .mode_set_base_atomic = intel_pipe_set_base_atomic,
 -      .load_lut = intel_crtc_load_lut,
 -      .atomic_begin = intel_begin_crtc_commit,
 -      .atomic_flush = intel_finish_crtc_commit,
 -};
  
  /**
 - * intel_modeset_update_staged_output_state
 + * intel_wm_need_update - Check whether watermarks need updating
 + * @plane: drm plane
 + * @state: new plane state
 + *
 + * Check current plane state versus the new one to determine whether
 + * watermarks need to be recalculated.
   *
 - * Updates the staged output configuration state, e.g. after we've read out the
 - * current hw state.
 + * Returns true or false.
   */
 -static void intel_modeset_update_staged_output_state(struct drm_device *dev)
 +static bool intel_wm_need_update(struct drm_plane *plane,
 +                               struct drm_plane_state *state)
  {
 -      struct intel_crtc *crtc;
 -      struct intel_encoder *encoder;
 -      struct intel_connector *connector;
 -
 -      for_each_intel_connector(dev, connector) {
 -              connector->new_encoder =
 -                      to_intel_encoder(connector->base.encoder);
 -      }
 +      /* Update watermarks on tiling changes. */
 +      if (!plane->state->fb || !state->fb ||
 +          plane->state->fb->modifier[0] != state->fb->modifier[0] ||
 +          plane->state->rotation != state->rotation)
 +              return true;
  
 -      for_each_intel_encoder(dev, encoder) {
 -              encoder->new_crtc =
 -                      to_intel_crtc(encoder->base.crtc);
 -      }
 +      if (plane->state->crtc_w != state->crtc_w)
 +              return true;
  
 -      for_each_intel_crtc(dev, crtc) {
 -              crtc->new_enabled = crtc->base.state->enable;
 -      }
 +      return false;
  }
  
 -/* Transitional helper to copy current connector/encoder state to
 - * connector->state. This is needed so that code that is partially
 - * converted to atomic does the right thing.
 - */
 -static void intel_modeset_update_connector_atomic_state(struct drm_device *dev)
 +int intel_plane_atomic_calc_changes(struct drm_crtc_state *crtc_state,
 +                                  struct drm_plane_state *plane_state)
  {
 -      struct intel_connector *connector;
 +      struct drm_crtc *crtc = crtc_state->crtc;
 +      struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
 +      struct drm_plane *plane = plane_state->plane;
 +      struct drm_device *dev = crtc->dev;
 +      struct drm_i915_private *dev_priv = dev->dev_private;
 +      struct intel_plane_state *old_plane_state =
 +              to_intel_plane_state(plane->state);
 +      int idx = intel_crtc->base.base.id, ret;
 +      int i = drm_plane_index(plane);
 +      bool mode_changed = needs_modeset(crtc_state);
 +      bool was_crtc_enabled = crtc->state->active;
 +      bool is_crtc_enabled = crtc_state->active;
 +
 +      bool turn_off, turn_on, visible, was_visible;
 +      struct drm_framebuffer *fb = plane_state->fb;
 +
 +      if (crtc_state && INTEL_INFO(dev)->gen >= 9 &&
 +          plane->type != DRM_PLANE_TYPE_CURSOR) {
 +              ret = skl_update_scaler_plane(
 +                      to_intel_crtc_state(crtc_state),
 +                      to_intel_plane_state(plane_state));
 +              if (ret)
 +                      return ret;
 +      }
  
 -      for_each_intel_connector(dev, connector) {
 -              if (connector->base.encoder) {
 -                      connector->base.state->best_encoder =
 -                              connector->base.encoder;
 -                      connector->base.state->crtc =
 -                              connector->base.encoder->crtc;
 -              } else {
 -                      connector->base.state->best_encoder = NULL;
 -                      connector->base.state->crtc = NULL;
 +      /*
 +       * Disabling a plane is always okay; we just need to update
 +       * fb tracking in a special way since cleanup_fb() won't
 +       * get called by the plane helpers.
 +       */
 +      if (old_plane_state->base.fb && !fb)
 +              intel_crtc->atomic.disabled_planes |= 1 << i;
 +
 +      was_visible = old_plane_state->visible;
 +      visible = to_intel_plane_state(plane_state)->visible;
 +
 +      if (!was_crtc_enabled && WARN_ON(was_visible))
 +              was_visible = false;
 +
 +      if (!is_crtc_enabled && WARN_ON(visible))
 +              visible = false;
 +
 +      if (!was_visible && !visible)
 +              return 0;
 +
 +      turn_off = was_visible && (!visible || mode_changed);
 +      turn_on = visible && (!was_visible || mode_changed);
 +
 +      DRM_DEBUG_ATOMIC("[CRTC:%i] has [PLANE:%i] with fb %i\n", idx,
 +                       plane->base.id, fb ? fb->base.id : -1);
 +
 +      DRM_DEBUG_ATOMIC("[PLANE:%i] visible %i -> %i, off %i, on %i, ms %i\n",
 +                       plane->base.id, was_visible, visible,
 +                       turn_off, turn_on, mode_changed);
 +
 +      if (turn_on) {
 +              intel_crtc->atomic.update_wm_pre = true;
 +              /* must disable cxsr around plane enable/disable */
 +              if (plane->type != DRM_PLANE_TYPE_CURSOR) {
 +                      intel_crtc->atomic.disable_cxsr = true;
 +                      /* to potentially re-enable cxsr */
 +                      intel_crtc->atomic.wait_vblank = true;
 +                      intel_crtc->atomic.update_wm_post = true;
 +              }
 +      } else if (turn_off) {
 +              intel_crtc->atomic.update_wm_post = true;
 +              /* must disable cxsr around plane enable/disable */
 +              if (plane->type != DRM_PLANE_TYPE_CURSOR) {
 +                      if (is_crtc_enabled)
 +                              intel_crtc->atomic.wait_vblank = true;
 +                      intel_crtc->atomic.disable_cxsr = true;
                }
 +      } else if (intel_wm_need_update(plane, plane_state)) {
 +              intel_crtc->atomic.update_wm_pre = true;
        }
 -}
  
 -/* Fixup legacy state after an atomic state swap.
 - */
 -static void intel_modeset_fixup_state(struct drm_atomic_state *state)
 -{
 -      struct intel_crtc *crtc;
 -      struct intel_encoder *encoder;
 -      struct intel_connector *connector;
 +      if (visible)
 +              intel_crtc->atomic.fb_bits |=
 +                      to_intel_plane(plane)->frontbuffer_bit;
  
 -      for_each_intel_connector(state->dev, connector) {
 -              connector->base.encoder = connector->base.state->best_encoder;
 -              if (connector->base.encoder)
 -                      connector->base.encoder->crtc =
 -                              connector->base.state->crtc;
 -      }
 +      switch (plane->type) {
 +      case DRM_PLANE_TYPE_PRIMARY:
 +              intel_crtc->atomic.wait_for_flips = true;
 +              intel_crtc->atomic.pre_disable_primary = turn_off;
 +              intel_crtc->atomic.post_enable_primary = turn_on;
  
 -      /* Update crtc of disabled encoders */
 -      for_each_intel_encoder(state->dev, encoder) {
 -              int num_connectors = 0;
 +              if (turn_off) {
 +                      /*
 +                       * FIXME: Actually if we will still have any other
 +                       * plane enabled on the pipe we could let IPS enabled
 +                       * still, but for now lets consider that when we make
 +                       * primary invisible by setting DSPCNTR to 0 on
 +                       * update_primary_plane function IPS needs to be
 +                       * disable.
 +                       */
 +                      intel_crtc->atomic.disable_ips = true;
  
 -              for_each_intel_connector(state->dev, connector)
 -                      if (connector->base.encoder == &encoder->base)
 -                              num_connectors++;
 +                      intel_crtc->atomic.disable_fbc = true;
 +              }
  
 -              if (num_connectors == 0)
 -                      encoder->base.crtc = NULL;
 -      }
 +              /*
 +               * 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 (visible &&
 +                  INTEL_INFO(dev)->gen <= 4 && !IS_G4X(dev) &&
 +                  dev_priv->fbc.crtc == intel_crtc &&
 +                  plane_state->rotation != BIT(DRM_ROTATE_0))
 +                      intel_crtc->atomic.disable_fbc = true;
 +
 +              /*
 +               * BDW signals flip done immediately if the plane
 +               * is disabled, even if the plane enable is already
 +               * armed to occur at the next vblank :(
 +               */
 +              if (turn_on && IS_BROADWELL(dev))
 +                      intel_crtc->atomic.wait_vblank = true;
  
 -      for_each_intel_crtc(state->dev, crtc) {
 -              crtc->base.enabled = crtc->base.state->enable;
 -              crtc->config = to_intel_crtc_state(crtc->base.state);
 +              intel_crtc->atomic.update_fbc |= visible || mode_changed;
 +              break;
 +      case DRM_PLANE_TYPE_CURSOR:
 +              break;
 +      case DRM_PLANE_TYPE_OVERLAY:
 +              if (turn_off && !mode_changed) {
 +                      intel_crtc->atomic.wait_vblank = true;
 +                      intel_crtc->atomic.update_sprite_watermarks |=
 +                              1 << i;
 +              }
        }
 +      return 0;
  }
  
 -static void
 -connected_sink_compute_bpp(struct intel_connector *connector,
 -                         struct intel_crtc_state *pipe_config)
 +static bool encoders_cloneable(const struct intel_encoder *a,
 +                             const struct intel_encoder *b)
  {
 -      int bpp = pipe_config->pipe_bpp;
 +      /* masks could be asymmetric, so check both ways */
 +      return a == b || (a->cloneable & (1 << b->type) &&
 +                        b->cloneable & (1 << a->type));
 +}
 +
 +static bool check_single_encoder_cloning(struct drm_atomic_state *state,
 +                                       struct intel_crtc *crtc,
 +                                       struct intel_encoder *encoder)
 +{
 +      struct intel_encoder *source_encoder;
 +      struct drm_connector *connector;
 +      struct drm_connector_state *connector_state;
 +      int i;
 +
 +      for_each_connector_in_state(state, connector, connector_state, i) {
 +              if (connector_state->crtc != &crtc->base)
 +                      continue;
 +
 +              source_encoder =
 +                      to_intel_encoder(connector_state->best_encoder);
 +              if (!encoders_cloneable(encoder, source_encoder))
 +                      return false;
 +      }
 +
 +      return true;
 +}
 +
 +static bool check_encoder_cloning(struct drm_atomic_state *state,
 +                                struct intel_crtc *crtc)
 +{
 +      struct intel_encoder *encoder;
 +      struct drm_connector *connector;
 +      struct drm_connector_state *connector_state;
 +      int i;
 +
 +      for_each_connector_in_state(state, connector, connector_state, i) {
 +              if (connector_state->crtc != &crtc->base)
 +                      continue;
 +
 +              encoder = to_intel_encoder(connector_state->best_encoder);
 +              if (!check_single_encoder_cloning(state, crtc, encoder))
 +                      return false;
 +      }
 +
 +      return true;
 +}
 +
 +static int intel_crtc_atomic_check(struct drm_crtc *crtc,
 +                                 struct drm_crtc_state *crtc_state)
 +{
 +      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 intel_crtc_state *pipe_config =
 +              to_intel_crtc_state(crtc_state);
 +      struct drm_atomic_state *state = crtc_state->state;
 +      int ret;
 +      bool mode_changed = needs_modeset(crtc_state);
 +
 +      if (mode_changed && !check_encoder_cloning(state, intel_crtc)) {
 +              DRM_DEBUG_KMS("rejecting invalid cloning configuration\n");
 +              return -EINVAL;
 +      }
 +
 +      if (mode_changed && !crtc_state->active)
 +              intel_crtc->atomic.update_wm_post = true;
 +
 +      if (mode_changed && crtc_state->enable &&
 +          dev_priv->display.crtc_compute_clock &&
 +          !WARN_ON(pipe_config->shared_dpll != DPLL_ID_PRIVATE)) {
 +              ret = dev_priv->display.crtc_compute_clock(intel_crtc,
 +                                                         pipe_config);
 +              if (ret)
 +                      return ret;
 +      }
 +
 +      ret = 0;
 +      if (INTEL_INFO(dev)->gen >= 9) {
 +              if (mode_changed)
 +                      ret = skl_update_scaler_crtc(pipe_config);
 +
 +              if (!ret)
 +                      ret = intel_atomic_setup_scalers(dev, intel_crtc,
 +                                                       pipe_config);
 +      }
 +
 +      return ret;
 +}
 +
 +static const struct drm_crtc_helper_funcs intel_helper_funcs = {
 +      .mode_set_base_atomic = intel_pipe_set_base_atomic,
 +      .load_lut = intel_crtc_load_lut,
 +      .atomic_begin = intel_begin_crtc_commit,
 +      .atomic_flush = intel_finish_crtc_commit,
 +      .atomic_check = intel_crtc_atomic_check,
 +};
 +
 +static void intel_modeset_update_connector_atomic_state(struct drm_device *dev)
 +{
 +      struct intel_connector *connector;
 +
 +      for_each_intel_connector(dev, connector) {
 +              if (connector->base.encoder) {
 +                      connector->base.state->best_encoder =
 +                              connector->base.encoder;
 +                      connector->base.state->crtc =
 +                              connector->base.encoder->crtc;
 +              } else {
 +                      connector->base.state->best_encoder = NULL;
 +                      connector->base.state->crtc = NULL;
 +              }
 +      }
 +}
 +
 +static void
 +connected_sink_compute_bpp(struct intel_connector *connector,
 +                         struct intel_crtc_state *pipe_config)
 +{
 +      int bpp = pipe_config->pipe_bpp;
  
        DRM_DEBUG_KMS("[CONNECTOR:%d:%s] checking for sink bpp constrains\n",
                connector->base.base.id,
@@@ -11941,20 -11526,17 +11941,20 @@@ static void intel_dump_pipe_config(stru
        DRM_DEBUG_KMS("double wide: %i\n", pipe_config->double_wide);
  
        if (IS_BROXTON(dev)) {
 -              DRM_DEBUG_KMS("ddi_pll_sel: %u; dpll_hw_state: ebb0: 0x%x, "
 +              DRM_DEBUG_KMS("ddi_pll_sel: %u; dpll_hw_state: ebb0: 0x%x, ebb4: 0x%x,"
                              "pll0: 0x%x, pll1: 0x%x, pll2: 0x%x, pll3: 0x%x, "
 -                            "pll6: 0x%x, pll8: 0x%x, pcsdw12: 0x%x\n",
 +                            "pll6: 0x%x, pll8: 0x%x, pll9: 0x%x, pll10: 0x%x, pcsdw12: 0x%x\n",
                              pipe_config->ddi_pll_sel,
                              pipe_config->dpll_hw_state.ebb0,
 +                            pipe_config->dpll_hw_state.ebb4,
                              pipe_config->dpll_hw_state.pll0,
                              pipe_config->dpll_hw_state.pll1,
                              pipe_config->dpll_hw_state.pll2,
                              pipe_config->dpll_hw_state.pll3,
                              pipe_config->dpll_hw_state.pll6,
                              pipe_config->dpll_hw_state.pll8,
 +                            pipe_config->dpll_hw_state.pll9,
 +                            pipe_config->dpll_hw_state.pll10,
                              pipe_config->dpll_hw_state.pcsdw12);
        } else if (IS_SKYLAKE(dev)) {
                DRM_DEBUG_KMS("ddi_pll_sel: %u; dpll_hw_state: "
        }
  }
  
 -static bool encoders_cloneable(const struct intel_encoder *a,
 -                             const struct intel_encoder *b)
 -{
 -      /* masks could be asymmetric, so check both ways */
 -      return a == b || (a->cloneable & (1 << b->type) &&
 -                        b->cloneable & (1 << a->type));
 -}
 -
 -static bool check_single_encoder_cloning(struct drm_atomic_state *state,
 -                                       struct intel_crtc *crtc,
 -                                       struct intel_encoder *encoder)
 -{
 -      struct intel_encoder *source_encoder;
 -      struct drm_connector *connector;
 -      struct drm_connector_state *connector_state;
 -      int i;
 -
 -      for_each_connector_in_state(state, connector, connector_state, i) {
 -              if (connector_state->crtc != &crtc->base)
 -                      continue;
 -
 -              source_encoder =
 -                      to_intel_encoder(connector_state->best_encoder);
 -              if (!encoders_cloneable(encoder, source_encoder))
 -                      return false;
 -      }
 -
 -      return true;
 -}
 -
 -static bool check_encoder_cloning(struct drm_atomic_state *state,
 -                                struct intel_crtc *crtc)
 -{
 -      struct intel_encoder *encoder;
 -      struct drm_connector *connector;
 -      struct drm_connector_state *connector_state;
 -      int i;
 -
 -      for_each_connector_in_state(state, connector, connector_state, i) {
 -              if (connector_state->crtc != &crtc->base)
 -                      continue;
 -
 -              encoder = to_intel_encoder(connector_state->best_encoder);
 -              if (!check_single_encoder_cloning(state, crtc, encoder))
 -                      return false;
 -      }
 -
 -      return true;
 -}
 -
  static bool check_digital_port_conflicts(struct drm_atomic_state *state)
  {
        struct drm_device *dev = state->dev;
@@@ -12064,7 -11696,6 +12064,7 @@@ clear_intel_crtc_state(struct intel_crt
        struct intel_dpll_hw_state dpll_hw_state;
        enum intel_dpll_id shared_dpll;
        uint32_t ddi_pll_sel;
 +      bool force_thru;
  
        /* FIXME: before the switch to atomic started, a new pipe_config was
         * kzalloc'd. Code that depends on any field being zero should be
        shared_dpll = crtc_state->shared_dpll;
        dpll_hw_state = crtc_state->dpll_hw_state;
        ddi_pll_sel = crtc_state->ddi_pll_sel;
 +      force_thru = crtc_state->pch_pfit.force_thru;
  
        memset(crtc_state, 0, sizeof *crtc_state);
  
        crtc_state->shared_dpll = shared_dpll;
        crtc_state->dpll_hw_state = dpll_hw_state;
        crtc_state->ddi_pll_sel = ddi_pll_sel;
 +      crtc_state->pch_pfit.force_thru = force_thru;
  }
  
  static int
  intel_modeset_pipe_config(struct drm_crtc *crtc,
 -                        struct drm_atomic_state *state,
                          struct intel_crtc_state *pipe_config)
  {
 +      struct drm_atomic_state *state = pipe_config->base.state;
        struct intel_encoder *encoder;
        struct drm_connector *connector;
        struct drm_connector_state *connector_state;
        int i;
        bool retry = true;
  
 -      if (!check_encoder_cloning(state, to_intel_crtc(crtc))) {
 -              DRM_DEBUG_KMS("rejecting invalid cloning configuration\n");
 -              return -EINVAL;
 -      }
 -
 -      if (!check_digital_port_conflicts(state)) {
 -              DRM_DEBUG_KMS("rejecting conflicting digital port configuration\n");
 -              return -EINVAL;
 -      }
 -
        clear_intel_crtc_state(pipe_config);
  
        pipe_config->cpu_transcoder =
@@@ -12187,31 -11826,96 +12187,33 @@@ encoder_retry
                goto encoder_retry;
        }
  
-       pipe_config->dither = pipe_config->pipe_bpp != base_bpp;
+       /* Dithering seems to not pass-through bits correctly when it should, so
+        * only enable it on 6bpc panels. */
+       pipe_config->dither = pipe_config->pipe_bpp == 6*3;
        DRM_DEBUG_KMS("plane bpp: %i, pipe bpp: %i, dithering: %i\n",
                      base_bpp, pipe_config->pipe_bpp, pipe_config->dither);
  
 -      return 0;
  fail:
        return ret;
  }
  
 -static bool intel_crtc_in_use(struct drm_crtc *crtc)
 -{
 -      struct drm_encoder *encoder;
 -      struct drm_device *dev = crtc->dev;
 -
 -      list_for_each_entry(encoder, &dev->mode_config.encoder_list, head)
 -              if (encoder->crtc == crtc)
 -                      return true;
 -
 -      return false;
 -}
 -
 -static bool
 -needs_modeset(struct drm_crtc_state *state)
 -{
 -      return state->mode_changed || state->active_changed;
 -}
 -
  static void
 -intel_modeset_update_state(struct drm_atomic_state *state)
 +intel_modeset_update_crtc_state(struct drm_atomic_state *state)
  {
 -      struct drm_device *dev = state->dev;
 -      struct drm_i915_private *dev_priv = dev->dev_private;
 -      struct intel_encoder *intel_encoder;
        struct drm_crtc *crtc;
        struct drm_crtc_state *crtc_state;
 -      struct drm_connector *connector;
        int i;
  
 -      intel_shared_dpll_commit(dev_priv);
 -
 -      for_each_intel_encoder(dev, intel_encoder) {
 -              if (!intel_encoder->base.crtc)
 -                      continue;
 -
 -              for_each_crtc_in_state(state, crtc, crtc_state, i) {
 -                      if (crtc != intel_encoder->base.crtc)
 -                              continue;
 -
 -                      if (crtc_state->enable && needs_modeset(crtc_state))
 -                              intel_encoder->connectors_active = false;
 -
 -                      break;
 -              }
 -      }
 -
 -      drm_atomic_helper_swap_state(state->dev, state);
 -      intel_modeset_fixup_state(state);
 -
        /* Double check state. */
 -      for_each_crtc(dev, crtc) {
 -              WARN_ON(crtc->state->enable != intel_crtc_in_use(crtc));
 -      }
 -
 -      list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
 -              if (!connector->encoder || !connector->encoder->crtc)
 -                      continue;
 -
 -              for_each_crtc_in_state(state, crtc, crtc_state, i) {
 -                      if (crtc != connector->encoder->crtc)
 -                              continue;
 -
 -                      if (crtc->state->enable && needs_modeset(crtc->state)) {
 -                              struct drm_property *dpms_property =
 -                                      dev->mode_config.dpms_property;
 -
 -                              connector->dpms = DRM_MODE_DPMS_ON;
 -                              drm_object_property_set_value(&connector->base,
 -                                                               dpms_property,
 -                                                               DRM_MODE_DPMS_ON);
 -
 -                              intel_encoder = to_intel_encoder(connector->encoder);
 -                              intel_encoder->connectors_active = true;
 -                      }
 +      for_each_crtc_in_state(state, crtc, crtc_state, i) {
 +              to_intel_crtc(crtc)->config = to_intel_crtc_state(crtc->state);
  
 -                      break;
 -              }
 +              /* Update hwmode for vblank functions */
 +              if (crtc->state->active)
 +                      crtc->hwmode = crtc->state->adjusted_mode;
 +              else
 +                      crtc->hwmode.crtc_clock = 0;
        }
 -
  }
  
  static bool intel_fuzzy_clock_check(int clock1, int clock2)
                            base.head) \
                if (mask & (1 <<(intel_crtc)->pipe))
  
 +
 +static bool
 +intel_compare_m_n(unsigned int m, unsigned int n,
 +                unsigned int m2, unsigned int n2,
 +                bool exact)
 +{
 +      if (m == m2 && n == n2)
 +              return true;
 +
 +      if (exact || !m || !n || !m2 || !n2)
 +              return false;
 +
 +      BUILD_BUG_ON(DATA_LINK_M_N_MASK > INT_MAX);
 +
 +      if (m > m2) {
 +              while (m > m2) {
 +                      m2 <<= 1;
 +                      n2 <<= 1;
 +              }
 +      } else if (m < m2) {
 +              while (m < m2) {
 +                      m <<= 1;
 +                      n <<= 1;
 +              }
 +      }
 +
 +      return m == m2 && n == n2;
 +}
 +
 +static bool
 +intel_compare_link_m_n(const struct intel_link_m_n *m_n,
 +                     struct intel_link_m_n *m2_n2,
 +                     bool adjust)
 +{
 +      if (m_n->tu == m2_n2->tu &&
 +          intel_compare_m_n(m_n->gmch_m, m_n->gmch_n,
 +                            m2_n2->gmch_m, m2_n2->gmch_n, !adjust) &&
 +          intel_compare_m_n(m_n->link_m, m_n->link_n,
 +                            m2_n2->link_m, m2_n2->link_n, !adjust)) {
 +              if (adjust)
 +                      *m2_n2 = *m_n;
 +
 +              return true;
 +      }
 +
 +      return false;
 +}
 +
  static bool
  intel_pipe_config_compare(struct drm_device *dev,
                          struct intel_crtc_state *current_config,
 -                        struct intel_crtc_state *pipe_config)
 +                        struct intel_crtc_state *pipe_config,
 +                        bool adjust)
  {
 +      bool ret = true;
 +
 +#define INTEL_ERR_OR_DBG_KMS(fmt, ...) \
 +      do { \
 +              if (!adjust) \
 +                      DRM_ERROR(fmt, ##__VA_ARGS__); \
 +              else \
 +                      DRM_DEBUG_KMS(fmt, ##__VA_ARGS__); \
 +      } while (0)
 +
  #define PIPE_CONF_CHECK_X(name)       \
        if (current_config->name != pipe_config->name) { \
 -              DRM_ERROR("mismatch in " #name " " \
 +              INTEL_ERR_OR_DBG_KMS("mismatch in " #name " " \
                          "(expected 0x%08x, found 0x%08x)\n", \
                          current_config->name, \
                          pipe_config->name); \
 -              return false; \
 +              ret = false; \
        }
  
  #define PIPE_CONF_CHECK_I(name)       \
        if (current_config->name != pipe_config->name) { \
 -              DRM_ERROR("mismatch in " #name " " \
 +              INTEL_ERR_OR_DBG_KMS("mismatch in " #name " " \
                          "(expected %i, found %i)\n", \
                          current_config->name, \
                          pipe_config->name); \
 -              return false; \
 +              ret = false; \
 +      }
 +
 +#define PIPE_CONF_CHECK_M_N(name) \
 +      if (!intel_compare_link_m_n(&current_config->name, \
 +                                  &pipe_config->name,\
 +                                  adjust)) { \
 +              INTEL_ERR_OR_DBG_KMS("mismatch in " #name " " \
 +                        "(expected tu %i gmch %i/%i link %i/%i, " \
 +                        "found tu %i, gmch %i/%i link %i/%i)\n", \
 +                        current_config->name.tu, \
 +                        current_config->name.gmch_m, \
 +                        current_config->name.gmch_n, \
 +                        current_config->name.link_m, \
 +                        current_config->name.link_n, \
 +                        pipe_config->name.tu, \
 +                        pipe_config->name.gmch_m, \
 +                        pipe_config->name.gmch_n, \
 +                        pipe_config->name.link_m, \
 +                        pipe_config->name.link_n); \
 +              ret = false; \
 +      }
 +
 +#define PIPE_CONF_CHECK_M_N_ALT(name, alt_name) \
 +      if (!intel_compare_link_m_n(&current_config->name, \
 +                                  &pipe_config->name, adjust) && \
 +          !intel_compare_link_m_n(&current_config->alt_name, \
 +                                  &pipe_config->name, adjust)) { \
 +              INTEL_ERR_OR_DBG_KMS("mismatch in " #name " " \
 +                        "(expected tu %i gmch %i/%i link %i/%i, " \
 +                        "or tu %i gmch %i/%i link %i/%i, " \
 +                        "found tu %i, gmch %i/%i link %i/%i)\n", \
 +                        current_config->name.tu, \
 +                        current_config->name.gmch_m, \
 +                        current_config->name.gmch_n, \
 +                        current_config->name.link_m, \
 +                        current_config->name.link_n, \
 +                        current_config->alt_name.tu, \
 +                        current_config->alt_name.gmch_m, \
 +                        current_config->alt_name.gmch_n, \
 +                        current_config->alt_name.link_m, \
 +                        current_config->alt_name.link_n, \
 +                        pipe_config->name.tu, \
 +                        pipe_config->name.gmch_m, \
 +                        pipe_config->name.gmch_n, \
 +                        pipe_config->name.link_m, \
 +                        pipe_config->name.link_n); \
 +              ret = false; \
        }
  
  /* This is required for BDW+ where there is only one set of registers for
  #define PIPE_CONF_CHECK_I_ALT(name, alt_name) \
        if ((current_config->name != pipe_config->name) && \
                (current_config->alt_name != pipe_config->name)) { \
 -                      DRM_ERROR("mismatch in " #name " " \
 +                      INTEL_ERR_OR_DBG_KMS("mismatch in " #name " " \
                                  "(expected %i or %i, found %i)\n", \
                                  current_config->name, \
                                  current_config->alt_name, \
                                  pipe_config->name); \
 -                      return false; \
 +                      ret = false; \
        }
  
  #define PIPE_CONF_CHECK_FLAGS(name, mask)     \
        if ((current_config->name ^ pipe_config->name) & (mask)) { \
 -              DRM_ERROR("mismatch in " #name "(" #mask ") "      \
 +              INTEL_ERR_OR_DBG_KMS("mismatch in " #name "(" #mask ") " \
                          "(expected %i, found %i)\n", \
                          current_config->name & (mask), \
                          pipe_config->name & (mask)); \
 -              return false; \
 +              ret = false; \
        }
  
  #define PIPE_CONF_CHECK_CLOCK_FUZZY(name) \
        if (!intel_fuzzy_clock_check(current_config->name, pipe_config->name)) { \
 -              DRM_ERROR("mismatch in " #name " " \
 +              INTEL_ERR_OR_DBG_KMS("mismatch in " #name " " \
                          "(expected %i, found %i)\n", \
                          current_config->name, \
                          pipe_config->name); \
 -              return false; \
 +              ret = false; \
        }
  
  #define PIPE_CONF_QUIRK(quirk)        \
  
        PIPE_CONF_CHECK_I(has_pch_encoder);
        PIPE_CONF_CHECK_I(fdi_lanes);
 -      PIPE_CONF_CHECK_I(fdi_m_n.gmch_m);
 -      PIPE_CONF_CHECK_I(fdi_m_n.gmch_n);
 -      PIPE_CONF_CHECK_I(fdi_m_n.link_m);
 -      PIPE_CONF_CHECK_I(fdi_m_n.link_n);
 -      PIPE_CONF_CHECK_I(fdi_m_n.tu);
 +      PIPE_CONF_CHECK_M_N(fdi_m_n);
  
        PIPE_CONF_CHECK_I(has_dp_encoder);
  
        if (INTEL_INFO(dev)->gen < 8) {
 -              PIPE_CONF_CHECK_I(dp_m_n.gmch_m);
 -              PIPE_CONF_CHECK_I(dp_m_n.gmch_n);
 -              PIPE_CONF_CHECK_I(dp_m_n.link_m);
 -              PIPE_CONF_CHECK_I(dp_m_n.link_n);
 -              PIPE_CONF_CHECK_I(dp_m_n.tu);
 -
 -              if (current_config->has_drrs) {
 -                      PIPE_CONF_CHECK_I(dp_m2_n2.gmch_m);
 -                      PIPE_CONF_CHECK_I(dp_m2_n2.gmch_n);
 -                      PIPE_CONF_CHECK_I(dp_m2_n2.link_m);
 -                      PIPE_CONF_CHECK_I(dp_m2_n2.link_n);
 -                      PIPE_CONF_CHECK_I(dp_m2_n2.tu);
 -              }
 -      } else {
 -              PIPE_CONF_CHECK_I_ALT(dp_m_n.gmch_m, dp_m2_n2.gmch_m);
 -              PIPE_CONF_CHECK_I_ALT(dp_m_n.gmch_n, dp_m2_n2.gmch_n);
 -              PIPE_CONF_CHECK_I_ALT(dp_m_n.link_m, dp_m2_n2.link_m);
 -              PIPE_CONF_CHECK_I_ALT(dp_m_n.link_n, dp_m2_n2.link_n);
 -              PIPE_CONF_CHECK_I_ALT(dp_m_n.tu, dp_m2_n2.tu);
 -      }
 +              PIPE_CONF_CHECK_M_N(dp_m_n);
 +
 +              PIPE_CONF_CHECK_I(has_drrs);
 +              if (current_config->has_drrs)
 +                      PIPE_CONF_CHECK_M_N(dp_m2_n2);
 +      } else
 +              PIPE_CONF_CHECK_M_N_ALT(dp_m_n, dp_m2_n2);
  
        PIPE_CONF_CHECK_I(base.adjusted_mode.crtc_hdisplay);
        PIPE_CONF_CHECK_I(base.adjusted_mode.crtc_htotal);
        PIPE_CONF_CHECK_I(pipe_src_w);
        PIPE_CONF_CHECK_I(pipe_src_h);
  
 -      /*
 -       * FIXME: BIOS likes to set up a cloned config with lvds+external
 -       * screen. Since we don't yet re-compute the pipe config when moving
 -       * just the lvds port away to another pipe the sw tracking won't match.
 -       *
 -       * Proper atomic modesets with recomputed global state will fix this.
 -       * Until then just don't check gmch state for inherited modes.
 -       */
 -      if (!PIPE_CONF_QUIRK(PIPE_CONFIG_QUIRK_INHERITED_MODE)) {
 -              PIPE_CONF_CHECK_I(gmch_pfit.control);
 -              /* pfit ratios are autocomputed by the hw on gen4+ */
 -              if (INTEL_INFO(dev)->gen < 4)
 -                      PIPE_CONF_CHECK_I(gmch_pfit.pgm_ratios);
 -              PIPE_CONF_CHECK_I(gmch_pfit.lvds_border_bits);
 -      }
 +      PIPE_CONF_CHECK_I(gmch_pfit.control);
 +      /* pfit ratios are autocomputed by the hw on gen4+ */
 +      if (INTEL_INFO(dev)->gen < 4)
 +              PIPE_CONF_CHECK_I(gmch_pfit.pgm_ratios);
 +      PIPE_CONF_CHECK_I(gmch_pfit.lvds_border_bits);
  
        PIPE_CONF_CHECK_I(pch_pfit.enabled);
        if (current_config->pch_pfit.enabled) {
  #undef PIPE_CONF_CHECK_FLAGS
  #undef PIPE_CONF_CHECK_CLOCK_FUZZY
  #undef PIPE_CONF_QUIRK
 +#undef INTEL_ERR_OR_DBG_KMS
  
 -      return true;
 +      return ret;
  }
  
  static void check_wm_state(struct drm_device *dev)
  }
  
  static void
 -check_connector_state(struct drm_device *dev)
 +check_connector_state(struct drm_device *dev,
 +                    struct drm_atomic_state *old_state)
  {
 -      struct intel_connector *connector;
 +      struct drm_connector_state *old_conn_state;
 +      struct drm_connector *connector;
 +      int i;
 +
 +      for_each_connector_in_state(old_state, connector, old_conn_state, i) {
 +              struct drm_encoder *encoder = connector->encoder;
 +              struct drm_connector_state *state = connector->state;
  
 -      for_each_intel_connector(dev, connector) {
                /* This also checks the encoder/connector hw state with the
                 * ->get_hw_state callbacks. */
 -              intel_connector_check_state(connector);
 +              intel_connector_check_state(to_intel_connector(connector));
  
 -              I915_STATE_WARN(&connector->new_encoder->base != connector->base.encoder,
 -                   "connector's staged encoder doesn't match current encoder\n");
 +              I915_STATE_WARN(state->best_encoder != encoder,
 +                   "connector's atomic encoder doesn't match legacy encoder\n");
        }
  }
  
@@@ -12589,106 -12207,124 +12591,106 @@@ check_encoder_state(struct drm_device *
  
        for_each_intel_encoder(dev, encoder) {
                bool enabled = false;
 -              bool active = false;
 -              enum pipe pipe, tracked_pipe;
 +              enum pipe pipe;
  
                DRM_DEBUG_KMS("[ENCODER:%d:%s]\n",
                              encoder->base.base.id,
                              encoder->base.name);
  
 -              I915_STATE_WARN(&encoder->new_crtc->base != encoder->base.crtc,
 -                   "encoder's stage crtc doesn't match current crtc\n");
 -              I915_STATE_WARN(encoder->connectors_active && !encoder->base.crtc,
 -                   "encoder's active_connectors set, but no crtc\n");
 -
                for_each_intel_connector(dev, connector) {
 -                      if (connector->base.encoder != &encoder->base)
 +                      if (connector->base.state->best_encoder != &encoder->base)
                                continue;
                        enabled = true;
 -                      if (connector->base.dpms != DRM_MODE_DPMS_OFF)
 -                              active = true;
 +
 +                      I915_STATE_WARN(connector->base.state->crtc !=
 +                                      encoder->base.crtc,
 +                           "connector's crtc doesn't match encoder crtc\n");
                }
 -              /*
 -               * for MST connectors if we unplug the connector is gone
 -               * away but the encoder is still connected to a crtc
 -               * until a modeset happens in response to the hotplug.
 -               */
 -              if (!enabled && encoder->base.encoder_type == DRM_MODE_ENCODER_DPMST)
 -                      continue;
  
                I915_STATE_WARN(!!encoder->base.crtc != enabled,
                     "encoder's enabled state mismatch "
                     "(expected %i, found %i)\n",
                     !!encoder->base.crtc, enabled);
 -              I915_STATE_WARN(active && !encoder->base.crtc,
 -                   "active encoder with no crtc\n");
 -
 -              I915_STATE_WARN(encoder->connectors_active != active,
 -                   "encoder's computed active state doesn't match tracked active state "
 -                   "(expected %i, found %i)\n", active, encoder->connectors_active);
 -
 -              active = encoder->get_hw_state(encoder, &pipe);
 -              I915_STATE_WARN(active != encoder->connectors_active,
 -                   "encoder's hw state doesn't match sw tracking "
 -                   "(expected %i, found %i)\n",
 -                   encoder->connectors_active, active);
  
 -              if (!encoder->base.crtc)
 -                      continue;
 -
 -              tracked_pipe = to_intel_crtc(encoder->base.crtc)->pipe;
 -              I915_STATE_WARN(active && pipe != tracked_pipe,
 -                   "active encoder's pipe doesn't match"
 -                   "(expected %i, found %i)\n",
 -                   tracked_pipe, pipe);
 +              if (!encoder->base.crtc) {
 +                      bool active;
  
 +                      active = encoder->get_hw_state(encoder, &pipe);
 +                      I915_STATE_WARN(active,
 +                           "encoder detached but still enabled on pipe %c.\n",
 +                           pipe_name(pipe));
 +              }
        }
  }
  
  static void
 -check_crtc_state(struct drm_device *dev)
 +check_crtc_state(struct drm_device *dev, struct drm_atomic_state *old_state)
  {
        struct drm_i915_private *dev_priv = dev->dev_private;
 -      struct intel_crtc *crtc;
        struct intel_encoder *encoder;
 -      struct intel_crtc_state pipe_config;
 +      struct drm_crtc_state *old_crtc_state;
 +      struct drm_crtc *crtc;
 +      int i;
  
 -      for_each_intel_crtc(dev, crtc) {
 -              bool enabled = false;
 -              bool active = false;
 +      for_each_crtc_in_state(old_state, crtc, old_crtc_state, i) {
 +              struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
 +              struct intel_crtc_state *pipe_config, *sw_config;
 +              bool active;
 +
 +              if (!needs_modeset(crtc->state))
 +                      continue;
  
 -              memset(&pipe_config, 0, sizeof(pipe_config));
 +              __drm_atomic_helper_crtc_destroy_state(crtc, old_crtc_state);
 +              pipe_config = to_intel_crtc_state(old_crtc_state);
 +              memset(pipe_config, 0, sizeof(*pipe_config));
 +              pipe_config->base.crtc = crtc;
 +              pipe_config->base.state = old_state;
  
                DRM_DEBUG_KMS("[CRTC:%d]\n",
 -                            crtc->base.base.id);
 -
 -              I915_STATE_WARN(crtc->active && !crtc->base.state->enable,
 -                   "active crtc, but not enabled in sw tracking\n");
 +                            crtc->base.id);
  
 -              for_each_intel_encoder(dev, encoder) {
 -                      if (encoder->base.crtc != &crtc->base)
 -                              continue;
 -                      enabled = true;
 -                      if (encoder->connectors_active)
 -                              active = true;
 -              }
 +              active = dev_priv->display.get_pipe_config(intel_crtc,
 +                                                         pipe_config);
  
 -              I915_STATE_WARN(active != crtc->active,
 -                   "crtc's computed active state doesn't match tracked active state "
 -                   "(expected %i, found %i)\n", active, crtc->active);
 -              I915_STATE_WARN(enabled != crtc->base.state->enable,
 -                   "crtc's computed enabled state doesn't match tracked enabled state "
 -                   "(expected %i, found %i)\n", enabled,
 -                              crtc->base.state->enable);
 +              /* hw state is inconsistent with the pipe quirk */
 +              if ((intel_crtc->pipe == PIPE_A && dev_priv->quirks & QUIRK_PIPEA_FORCE) ||
 +                  (intel_crtc->pipe == PIPE_B && dev_priv->quirks & QUIRK_PIPEB_FORCE))
 +                      active = crtc->state->active;
  
 -              active = dev_priv->display.get_pipe_config(crtc,
 -                                                         &pipe_config);
 +              I915_STATE_WARN(crtc->state->active != active,
 +                   "crtc active state doesn't match with hw state "
 +                   "(expected %i, found %i)\n", crtc->state->active, active);
  
 -              /* 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;
 +              I915_STATE_WARN(intel_crtc->active != crtc->state->active,
 +                   "transitional active state does not match atomic hw state "
 +                   "(expected %i, found %i)\n", crtc->state->active, intel_crtc->active);
  
 -              for_each_intel_encoder(dev, encoder) {
 +              for_each_encoder_on_crtc(dev, crtc, encoder) {
                        enum pipe pipe;
 -                      if (encoder->base.crtc != &crtc->base)
 -                              continue;
 -                      if (encoder->get_hw_state(encoder, &pipe))
 -                              encoder->get_config(encoder, &pipe_config);
 +
 +                      active = encoder->get_hw_state(encoder, &pipe);
 +                      I915_STATE_WARN(active != crtc->state->active,
 +                              "[ENCODER:%i] active %i with crtc active %i\n",
 +                              encoder->base.base.id, active, crtc->state->active);
 +
 +                      I915_STATE_WARN(active && intel_crtc->pipe != pipe,
 +                                      "Encoder connected to wrong pipe %c\n",
 +                                      pipe_name(pipe));
 +
 +                      if (active)
 +                              encoder->get_config(encoder, pipe_config);
                }
  
 -              I915_STATE_WARN(crtc->active != active,
 -                   "crtc active state doesn't match with hw state "
 -                   "(expected %i, found %i)\n", crtc->active, active);
 +              if (!crtc->state->active)
 +                      continue;
  
 -              if (active &&
 -                  !intel_pipe_config_compare(dev, crtc->config, &pipe_config)) {
 +              sw_config = to_intel_crtc_state(crtc->state);
 +              if (!intel_pipe_config_compare(dev, sw_config,
 +                                             pipe_config, false)) {
                        I915_STATE_WARN(1, "pipe state doesn't match!\n");
 -                      intel_dump_pipe_config(crtc, &pipe_config,
 +                      intel_dump_pipe_config(intel_crtc, pipe_config,
                                               "[hw state]");
 -                      intel_dump_pipe_config(crtc, crtc->config,
 +                      intel_dump_pipe_config(intel_crtc, sw_config,
                                               "[sw state]");
                }
        }
@@@ -12743,14 -12379,13 +12745,14 @@@ check_shared_dpll_state(struct drm_devi
        }
  }
  
 -void
 -intel_modeset_check_state(struct drm_device *dev)
 +static void
 +intel_modeset_check_state(struct drm_device *dev,
 +                        struct drm_atomic_state *old_state)
  {
        check_wm_state(dev);
 -      check_connector_state(dev);
 +      check_connector_state(dev, old_state);
        check_encoder_state(dev);
 -      check_crtc_state(dev);
 +      check_crtc_state(dev, old_state);
        check_shared_dpll_state(dev);
  }
  
@@@ -12804,390 -12439,519 +12806,390 @@@ static void update_scanline_offset(stru
                crtc->scanline_offset = 1;
  }
  
 -static struct intel_crtc_state *
 -intel_modeset_compute_config(struct drm_crtc *crtc,
 -                           struct drm_atomic_state *state)
 -{
 -      struct intel_crtc_state *pipe_config;
 -      int ret = 0;
 -
 -      ret = drm_atomic_add_affected_connectors(state, crtc);
 -      if (ret)
 -              return ERR_PTR(ret);
 -
 -      ret = drm_atomic_helper_check_modeset(state->dev, state);
 -      if (ret)
 -              return ERR_PTR(ret);
 -
 -      /*
 -       * Note this needs changes when we start tracking multiple modes
 -       * and crtcs.  At that point we'll need to compute the whole config
 -       * (i.e. one pipe_config for each crtc) rather than just the one
 -       * for this crtc.
 -       */
 -      pipe_config = intel_atomic_get_crtc_state(state, to_intel_crtc(crtc));
 -      if (IS_ERR(pipe_config))
 -              return pipe_config;
 -
 -      if (!pipe_config->base.enable)
 -              return pipe_config;
 -
 -      ret = intel_modeset_pipe_config(crtc, state, pipe_config);
 -      if (ret)
 -              return ERR_PTR(ret);
 -
 -      /* Check things that can only be changed through modeset */
 -      if (pipe_config->has_audio !=
 -          to_intel_crtc(crtc)->config->has_audio)
 -              pipe_config->base.mode_changed = true;
 -
 -      /*
 -       * Note we have an issue here with infoframes: current code
 -       * only updates them on the full mode set path per hw
 -       * requirements.  So here we should be checking for any
 -       * required changes and forcing a mode set.
 -       */
 -
 -      intel_dump_pipe_config(to_intel_crtc(crtc), pipe_config,"[modeset]");
 -
 -      ret = drm_atomic_helper_check_planes(state->dev, state);
 -      if (ret)
 -              return ERR_PTR(ret);
 -
 -      return pipe_config;
 -}
 -
 -static int __intel_set_mode_setup_plls(struct drm_atomic_state *state)
 +static void intel_modeset_clear_plls(struct drm_atomic_state *state)
  {
        struct drm_device *dev = state->dev;
        struct drm_i915_private *dev_priv = to_i915(dev);
 -      unsigned clear_pipes = 0;
 +      struct intel_shared_dpll_config *shared_dpll = NULL;
        struct intel_crtc *intel_crtc;
        struct intel_crtc_state *intel_crtc_state;
        struct drm_crtc *crtc;
        struct drm_crtc_state *crtc_state;
 -      int ret = 0;
        int i;
  
        if (!dev_priv->display.crtc_compute_clock)
 -              return 0;
 -
 -      for_each_crtc_in_state(state, crtc, crtc_state, i) {
 -              intel_crtc = to_intel_crtc(crtc);
 -              intel_crtc_state = to_intel_crtc_state(crtc_state);
 -
 -              if (needs_modeset(crtc_state)) {
 -                      clear_pipes |= 1 << intel_crtc->pipe;
 -                      intel_crtc_state->shared_dpll = DPLL_ID_PRIVATE;
 -              }
 -      }
 -
 -      ret = intel_shared_dpll_start_config(dev_priv, clear_pipes);
 -      if (ret)
 -              goto done;
 +              return;
  
        for_each_crtc_in_state(state, crtc, crtc_state, i) {
 -              if (!needs_modeset(crtc_state) || !crtc_state->enable)
 -                      continue;
 +              int dpll;
  
                intel_crtc = to_intel_crtc(crtc);
                intel_crtc_state = to_intel_crtc_state(crtc_state);
 +              dpll = intel_crtc_state->shared_dpll;
  
 -              ret = dev_priv->display.crtc_compute_clock(intel_crtc,
 -                                                         intel_crtc_state);
 -              if (ret) {
 -                      intel_shared_dpll_abort_config(dev_priv);
 -                      goto done;
 -              }
 -      }
 +              if (!needs_modeset(crtc_state) || dpll == DPLL_ID_PRIVATE)
 +                      continue;
  
 -done:
 -      return ret;
 -}
 +              intel_crtc_state->shared_dpll = DPLL_ID_PRIVATE;
  
 -/* Code that should eventually be part of atomic_check() */
 -static int __intel_set_mode_checks(struct drm_atomic_state *state)
 -{
 -      struct drm_device *dev = state->dev;
 -      int ret;
 +              if (!shared_dpll)
 +                      shared_dpll = intel_atomic_get_shared_dpll_state(state);
  
 -      /*
 -       * See if the config requires any additional preparation, e.g.
 -       * to adjust global state with pipes off.  We need to do this
 -       * here so we can get the modeset_pipe updated config for the new
 -       * mode set on this crtc.  For other crtcs we need to use the
 -       * adjusted_mode bits in the crtc directly.
 -       */
 -      if (IS_VALLEYVIEW(dev) || IS_BROXTON(dev)) {
 -              ret = valleyview_modeset_global_pipes(state);
 -              if (ret)
 -                      return ret;
 +              shared_dpll[dpll].crtc_mask &= ~(1 << intel_crtc->pipe);
        }
 -
 -      ret = __intel_set_mode_setup_plls(state);
 -      if (ret)
 -              return ret;
 -
 -      return 0;
  }
  
 -static int __intel_set_mode(struct drm_crtc *modeset_crtc,
 -                          struct intel_crtc_state *pipe_config)
 +/*
 + * This implements the workaround described in the "notes" section of the mode
 + * set sequence documentation. When going from no pipes or single pipe to
 + * multiple pipes, and planes are enabled after the pipe, we need to wait at
 + * least 2 vblanks on the first pipe before enabling planes on the second pipe.
 + */
 +static int haswell_mode_set_planes_workaround(struct drm_atomic_state *state)
  {
 -      struct drm_device *dev = modeset_crtc->dev;
 -      struct drm_i915_private *dev_priv = dev->dev_private;
 -      struct drm_atomic_state *state = pipe_config->base.state;
 -      struct drm_crtc *crtc;
        struct drm_crtc_state *crtc_state;
 -      int ret = 0;
 +      struct intel_crtc *intel_crtc;
 +      struct drm_crtc *crtc;
 +      struct intel_crtc_state *first_crtc_state = NULL;
 +      struct intel_crtc_state *other_crtc_state = NULL;
 +      enum pipe first_pipe = INVALID_PIPE, enabled_pipe = INVALID_PIPE;
        int i;
  
 -      ret = __intel_set_mode_checks(state);
 -      if (ret < 0)
 -              return ret;
 -
 -      ret = drm_atomic_helper_prepare_planes(dev, state);
 -      if (ret)
 -              return ret;
 -
 +      /* look at all crtc's that are going to be enabled in during modeset */
        for_each_crtc_in_state(state, crtc, crtc_state, i) {
 -              if (!needs_modeset(crtc_state))
 +              intel_crtc = to_intel_crtc(crtc);
 +
 +              if (!crtc_state->active || !needs_modeset(crtc_state))
                        continue;
  
 -              if (!crtc_state->enable) {
 -                      if (crtc->state->enable)
 -                              intel_crtc_disable(crtc);
 -              } else if (crtc->state->enable) {
 -                      intel_crtc_disable_planes(crtc);
 -                      dev_priv->display.crtc_disable(crtc);
 +              if (first_crtc_state) {
 +                      other_crtc_state = to_intel_crtc_state(crtc_state);
 +                      break;
 +              } else {
 +                      first_crtc_state = to_intel_crtc_state(crtc_state);
 +                      first_pipe = intel_crtc->pipe;
                }
        }
  
 -      /* crtc->mode is already used by the ->mode_set callbacks, hence we need
 -       * to set it here already despite that we pass it down the callchain.
 -       *
 -       * Note we'll need to fix this up when we start tracking multiple
 -       * pipes; here we assume a single modeset_pipe and only track the
 -       * single crtc and mode.
 -       */
 -      if (pipe_config->base.enable && needs_modeset(&pipe_config->base)) {
 -              modeset_crtc->mode = pipe_config->base.mode;
 -
 -              /*
 -               * Calculate and store various constants which
 -               * are later needed by vblank and swap-completion
 -               * timestamping. They are derived from true hwmode.
 -               */
 -              drm_calc_timestamping_constants(modeset_crtc,
 -                                              &pipe_config->base.adjusted_mode);
 -      }
 +      /* No workaround needed? */
 +      if (!first_crtc_state)
 +              return 0;
  
 -      /* Only after disabling all output pipelines that will be changed can we
 -       * update the the output configuration. */
 -      intel_modeset_update_state(state);
 +      /* w/a possibly needed, check how many crtc's are already enabled. */
 +      for_each_intel_crtc(state->dev, intel_crtc) {
 +              struct intel_crtc_state *pipe_config;
  
 -      /* The state has been swaped above, so state actually contains the
 -       * old state now. */
 +              pipe_config = intel_atomic_get_crtc_state(state, intel_crtc);
 +              if (IS_ERR(pipe_config))
 +                      return PTR_ERR(pipe_config);
  
 -      modeset_update_crtc_power_domains(state);
 +              pipe_config->hsw_workaround_pipe = INVALID_PIPE;
  
 -      /* Now enable the clocks, plane, pipe, and connectors that we set up. */
 -      for_each_crtc_in_state(state, crtc, crtc_state, i) {
 -              if (!needs_modeset(crtc->state) || !crtc->state->enable) {
 -                      drm_atomic_helper_commit_planes_on_crtc(crtc_state);
 +              if (!pipe_config->base.active ||
 +                  needs_modeset(&pipe_config->base))
                        continue;
 -              }
  
 -              update_scanline_offset(to_intel_crtc(crtc));
 +              /* 2 or more enabled crtcs means no need for w/a */
 +              if (enabled_pipe != INVALID_PIPE)
 +                      return 0;
  
 -              dev_priv->display.crtc_enable(crtc);
 -              drm_atomic_helper_commit_planes_on_crtc(crtc_state);
 +              enabled_pipe = intel_crtc->pipe;
        }
  
 -      /* FIXME: add subpixel order */
 -
 -      drm_atomic_helper_cleanup_planes(dev, state);
 -
 -      drm_atomic_state_free(state);
 +      if (enabled_pipe != INVALID_PIPE)
 +              first_crtc_state->hsw_workaround_pipe = enabled_pipe;
 +      else if (other_crtc_state)
 +              other_crtc_state->hsw_workaround_pipe = first_pipe;
  
        return 0;
  }
  
 -static int intel_set_mode_with_config(struct drm_crtc *crtc,
 -                                    struct intel_crtc_state *pipe_config,
 -                                    bool force_restore)
 +static int intel_modeset_all_pipes(struct drm_atomic_state *state)
  {
 -      int ret;
 +      struct drm_crtc *crtc;
 +      struct drm_crtc_state *crtc_state;
 +      int ret = 0;
  
 -      ret = __intel_set_mode(crtc, pipe_config);
 +      /* add all active pipes to the state */
 +      for_each_crtc(state->dev, crtc) {
 +              crtc_state = drm_atomic_get_crtc_state(state, crtc);
 +              if (IS_ERR(crtc_state))
 +                      return PTR_ERR(crtc_state);
  
 -      if (ret == 0 && force_restore) {
 -              intel_modeset_update_staged_output_state(crtc->dev);
 -              intel_modeset_check_state(crtc->dev);
 -      }
 +              if (!crtc_state->active || needs_modeset(crtc_state))
 +                      continue;
  
 -      return ret;
 -}
 +              crtc_state->mode_changed = true;
  
 -static int intel_set_mode(struct drm_crtc *crtc,
 -                        struct drm_atomic_state *state,
 -                        bool force_restore)
 -{
 -      struct intel_crtc_state *pipe_config;
 -      int ret = 0;
 +              ret = drm_atomic_add_affected_connectors(state, crtc);
 +              if (ret)
 +                      break;
  
 -      pipe_config = intel_modeset_compute_config(crtc, state);
 -      if (IS_ERR(pipe_config)) {
 -              ret = PTR_ERR(pipe_config);
 -              goto out;
 +              ret = drm_atomic_add_affected_planes(state, crtc);
 +              if (ret)
 +                      break;
        }
  
 -      ret = intel_set_mode_with_config(crtc, pipe_config, force_restore);
 -      if (ret)
 -              goto out;
 -
 -out:
        return ret;
  }
  
 -void intel_crtc_restore_mode(struct drm_crtc *crtc)
 +
 +static int intel_modeset_checks(struct drm_atomic_state *state)
  {
 -      struct drm_device *dev = crtc->dev;
 -      struct drm_atomic_state *state;
 -      struct intel_encoder *encoder;
 -      struct intel_connector *connector;
 -      struct drm_connector_state *connector_state;
 -      struct intel_crtc_state *crtc_state;
 +      struct drm_device *dev = state->dev;
 +      struct drm_i915_private *dev_priv = dev->dev_private;
        int ret;
  
 -      state = drm_atomic_state_alloc(dev);
 -      if (!state) {
 -              DRM_DEBUG_KMS("[CRTC:%d] mode restore failed, out of memory",
 -                            crtc->base.id);
 -              return;
 -      }
 -
 -      state->acquire_ctx = dev->mode_config.acquire_ctx;
 -
 -      /* The force restore path in the HW readout code relies on the staged
 -       * config still keeping the user requested config while the actual
 -       * state has been overwritten by the configuration read from HW. We
 -       * need to copy the staged config to the atomic state, otherwise the
 -       * mode set will just reapply the state the HW is already in. */
 -      for_each_intel_encoder(dev, encoder) {
 -              if (&encoder->new_crtc->base != crtc)
 -                      continue;
 -
 -              for_each_intel_connector(dev, connector) {
 -                      if (connector->new_encoder != encoder)
 -                              continue;
 -
 -                      connector_state = drm_atomic_get_connector_state(state, &connector->base);
 -                      if (IS_ERR(connector_state)) {
 -                              DRM_DEBUG_KMS("Failed to add [CONNECTOR:%d:%s] to state: %ld\n",
 -                                            connector->base.base.id,
 -                                            connector->base.name,
 -                                            PTR_ERR(connector_state));
 -                              continue;
 -                      }
 -
 -                      connector_state->crtc = crtc;
 -                      connector_state->best_encoder = &encoder->base;
 -              }
 -      }
 -
 -      crtc_state = intel_atomic_get_crtc_state(state, to_intel_crtc(crtc));
 -      if (IS_ERR(crtc_state)) {
 -              DRM_DEBUG_KMS("Failed to add [CRTC:%d] to state: %ld\n",
 -                            crtc->base.id, PTR_ERR(crtc_state));
 -              drm_atomic_state_free(state);
 -              return;
 +      if (!check_digital_port_conflicts(state)) {
 +              DRM_DEBUG_KMS("rejecting conflicting digital port configuration\n");
 +              return -EINVAL;
        }
  
 -      crtc_state->base.active = crtc_state->base.enable =
 -              to_intel_crtc(crtc)->new_enabled;
 -
 -      drm_mode_copy(&crtc_state->base.mode, &crtc->mode);
 +      /*
 +       * See if the config requires any additional preparation, e.g.
 +       * to adjust global state with pipes off.  We need to do this
 +       * here so we can get the modeset_pipe updated config for the new
 +       * mode set on this crtc.  For other crtcs we need to use the
 +       * adjusted_mode bits in the crtc directly.
 +       */
 +      if (dev_priv->display.modeset_calc_cdclk) {
 +              unsigned int cdclk;
  
 -      intel_modeset_setup_plane_state(state, crtc, &crtc->mode,
 -                                      crtc->primary->fb, crtc->x, crtc->y);
 +              ret = dev_priv->display.modeset_calc_cdclk(state);
  
 -      ret = intel_set_mode(crtc, state, false);
 -      if (ret)
 -              drm_atomic_state_free(state);
 -}
 +              cdclk = to_intel_atomic_state(state)->cdclk;
 +              if (!ret && cdclk != dev_priv->cdclk_freq)
 +                      ret = intel_modeset_all_pipes(state);
  
 -#undef for_each_intel_crtc_masked
 +              if (ret < 0)
 +                      return ret;
 +      } else
 +              to_intel_atomic_state(state)->cdclk = dev_priv->cdclk_freq;
  
 -static bool intel_connector_in_mode_set(struct intel_connector *connector,
 -                                      struct drm_mode_set *set)
 -{
 -      int ro;
 +      intel_modeset_clear_plls(state);
  
 -      for (ro = 0; ro < set->num_connectors; ro++)
 -              if (set->connectors[ro] == &connector->base)
 -                      return true;
 +      if (IS_HASWELL(dev))
 +              return haswell_mode_set_planes_workaround(state);
  
 -      return false;
 +      return 0;
  }
  
 -static int
 -intel_modeset_stage_output_state(struct drm_device *dev,
 -                               struct drm_mode_set *set,
 -                               struct drm_atomic_state *state)
 +/**
 + * intel_atomic_check - validate state object
 + * @dev: drm device
 + * @state: state to validate
 + */
 +static int intel_atomic_check(struct drm_device *dev,
 +                            struct drm_atomic_state *state)
  {
 -      struct intel_connector *connector;
 -      struct drm_connector *drm_connector;
 -      struct drm_connector_state *connector_state;
        struct drm_crtc *crtc;
        struct drm_crtc_state *crtc_state;
 -      int i, ret;
 -
 -      /* The upper layers ensure that we either disable a crtc or have a list
 -       * of connectors. For paranoia, double-check this. */
 -      WARN_ON(!set->fb && (set->num_connectors != 0));
 -      WARN_ON(set->fb && (set->num_connectors == 0));
 +      int ret, i;
 +      bool any_ms = false;
  
 -      for_each_intel_connector(dev, connector) {
 -              bool in_mode_set = intel_connector_in_mode_set(connector, set);
 +      ret = drm_atomic_helper_check_modeset(dev, state);
 +      if (ret)
 +              return ret;
  
 -              if (!in_mode_set && connector->base.state->crtc != set->crtc)
 -                      continue;
 +      for_each_crtc_in_state(state, crtc, crtc_state, i) {
 +              struct intel_crtc_state *pipe_config =
 +                      to_intel_crtc_state(crtc_state);
  
 -              connector_state =
 -                      drm_atomic_get_connector_state(state, &connector->base);
 -              if (IS_ERR(connector_state))
 -                      return PTR_ERR(connector_state);
 +              /* Catch I915_MODE_FLAG_INHERITED */
 +              if (crtc_state->mode.private_flags != crtc->state->mode.private_flags)
 +                      crtc_state->mode_changed = true;
  
 -              if (in_mode_set) {
 -                      int pipe = to_intel_crtc(set->crtc)->pipe;
 -                      connector_state->best_encoder =
 -                              &intel_find_encoder(connector, pipe)->base;
 +              if (!crtc_state->enable) {
 +                      if (needs_modeset(crtc_state))
 +                              any_ms = true;
 +                      continue;
                }
  
 -              if (connector->base.state->crtc != set->crtc)
 +              if (!needs_modeset(crtc_state))
                        continue;
  
 -              /* If we disable the crtc, disable all its connectors. Also, if
 -               * the connector is on the changing crtc but not on the new
 -               * connector list, disable it. */
 -              if (!set->fb || !in_mode_set) {
 -                      connector_state->best_encoder = NULL;
 -
 -                      DRM_DEBUG_KMS("[CONNECTOR:%d:%s] to [NOCRTC]\n",
 -                              connector->base.base.id,
 -                              connector->base.name);
 -              }
 -      }
 -      /* connector->new_encoder is now updated for all connectors. */
 +              /* FIXME: For only active_changed we shouldn't need to do any
 +               * state recomputation at all. */
  
 -      for_each_connector_in_state(state, drm_connector, connector_state, i) {
 -              connector = to_intel_connector(drm_connector);
 +              ret = drm_atomic_add_affected_connectors(state, crtc);
 +              if (ret)
 +                      return ret;
  
 -              if (!connector_state->best_encoder) {
 -                      ret = drm_atomic_set_crtc_for_connector(connector_state,
 -                                                              NULL);
 -                      if (ret)
 -                              return ret;
 +              ret = intel_modeset_pipe_config(crtc, pipe_config);
 +              if (ret)
 +                      return ret;
  
 -                      continue;
 +              if (i915.fastboot &&
 +                  intel_pipe_config_compare(state->dev,
 +                                      to_intel_crtc_state(crtc->state),
 +                                      pipe_config, true)) {
 +                      crtc_state->mode_changed = false;
                }
  
 -              if (intel_connector_in_mode_set(connector, set)) {
 -                      struct drm_crtc *crtc = connector->base.state->crtc;
 -
 -                      /* If this connector was in a previous crtc, add it
 -                       * to the state. We might need to disable it. */
 -                      if (crtc) {
 -                              crtc_state =
 -                                      drm_atomic_get_crtc_state(state, crtc);
 -                              if (IS_ERR(crtc_state))
 -                                      return PTR_ERR(crtc_state);
 -                      }
 +              if (needs_modeset(crtc_state)) {
 +                      any_ms = true;
  
 -                      ret = drm_atomic_set_crtc_for_connector(connector_state,
 -                                                              set->crtc);
 +                      ret = drm_atomic_add_affected_planes(state, crtc);
                        if (ret)
                                return ret;
                }
  
 -              /* Make sure the new CRTC will work with the encoder */
 -              if (!drm_encoder_crtc_ok(connector_state->best_encoder,
 -                                       connector_state->crtc)) {
 -                      return -EINVAL;
 -              }
 -
 -              DRM_DEBUG_KMS("[CONNECTOR:%d:%s] to [CRTC:%d]\n",
 -                      connector->base.base.id,
 -                      connector->base.name,
 -                      connector_state->crtc->base.id);
 -
 -              if (connector_state->best_encoder != &connector->encoder->base)
 -                      connector->encoder =
 -                              to_intel_encoder(connector_state->best_encoder);
 +              intel_dump_pipe_config(to_intel_crtc(crtc), pipe_config,
 +                                     needs_modeset(crtc_state) ?
 +                                     "[modeset]" : "[fastset]");
        }
  
 -      for_each_crtc_in_state(state, crtc, crtc_state, i) {
 -              bool has_connectors;
 +      if (any_ms) {
 +              ret = intel_modeset_checks(state);
  
 -              ret = drm_atomic_add_affected_connectors(state, crtc);
                if (ret)
                        return ret;
 +      } else
 +              to_intel_atomic_state(state)->cdclk =
 +                      to_i915(state->dev)->cdclk_freq;
 +
 +      return drm_atomic_helper_check_planes(state->dev, state);
 +}
 +
 +/**
 + * intel_atomic_commit - commit validated state object
 + * @dev: DRM device
 + * @state: the top-level driver state object
 + * @async: asynchronous commit
 + *
 + * This function commits a top-level state object that has been validated
 + * with drm_atomic_helper_check().
 + *
 + * FIXME:  Atomic modeset support for i915 is not yet complete.  At the moment
 + * we can only handle plane-related operations and do not yet support
 + * asynchronous commit.
 + *
 + * RETURNS
 + * Zero for success or -errno.
 + */
 +static int intel_atomic_commit(struct drm_device *dev,
 +                             struct drm_atomic_state *state,
 +                             bool async)
 +{
 +      struct drm_i915_private *dev_priv = dev->dev_private;
 +      struct drm_crtc *crtc;
 +      struct drm_crtc_state *crtc_state;
 +      int ret = 0;
 +      int i;
 +      bool any_ms = false;
  
 -              has_connectors = !!drm_atomic_connectors_for_crtc(state, crtc);
 -              if (has_connectors != crtc_state->enable)
 -                      crtc_state->enable =
 -                      crtc_state->active = has_connectors;
 +      if (async) {
 +              DRM_DEBUG_KMS("i915 does not yet support async commit\n");
 +              return -EINVAL;
        }
  
 -      ret = intel_modeset_setup_plane_state(state, set->crtc, set->mode,
 -                                            set->fb, set->x, set->y);
 +      ret = drm_atomic_helper_prepare_planes(dev, state);
        if (ret)
                return ret;
  
 -      crtc_state = drm_atomic_get_crtc_state(state, set->crtc);
 -      if (IS_ERR(crtc_state))
 -              return PTR_ERR(crtc_state);
 +      drm_atomic_helper_swap_state(dev, state);
  
 -      if (set->mode)
 -              drm_mode_copy(&crtc_state->mode, set->mode);
 +      for_each_crtc_in_state(state, crtc, crtc_state, i) {
 +              struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
  
 -      if (set->num_connectors)
 -              crtc_state->active = true;
 +              if (!needs_modeset(crtc->state))
 +                      continue;
  
 -      return 0;
 -}
 +              any_ms = true;
 +              intel_pre_plane_update(intel_crtc);
  
 -static int intel_crtc_set_config(struct drm_mode_set *set)
 -{
 -      struct drm_device *dev;
 -      struct drm_atomic_state *state = NULL;
 -      struct intel_crtc_state *pipe_config;
 -      int ret;
 +              if (crtc_state->active) {
 +                      intel_crtc_disable_planes(crtc, crtc_state->plane_mask);
 +                      dev_priv->display.crtc_disable(crtc);
 +                      intel_crtc->active = false;
 +                      intel_disable_shared_dpll(intel_crtc);
 +              }
 +      }
  
 -      BUG_ON(!set);
 -      BUG_ON(!set->crtc);
 -      BUG_ON(!set->crtc->helper_private);
 +      /* Only after disabling all output pipelines that will be changed can we
 +       * update the the output configuration. */
 +      intel_modeset_update_crtc_state(state);
  
 -      /* Enforce sane interface api - has been abused by the fb helper. */
 -      BUG_ON(!set->mode && set->fb);
 -      BUG_ON(set->fb && set->num_connectors == 0);
 +      if (any_ms) {
 +              intel_shared_dpll_commit(state);
  
 -      if (set->fb) {
 -              DRM_DEBUG_KMS("[CRTC:%d] [FB:%d] #connectors=%d (x y) (%i %i)\n",
 -                              set->crtc->base.id, set->fb->base.id,
 -                              (int)set->num_connectors, set->x, set->y);
 -      } else {
 -              DRM_DEBUG_KMS("[CRTC:%d] [NOFB]\n", set->crtc->base.id);
 +              drm_atomic_helper_update_legacy_modeset_state(state->dev, state);
 +              modeset_update_crtc_power_domains(state);
 +      }
 +
 +      /* Now enable the clocks, plane, pipe, and connectors that we set up. */
 +      for_each_crtc_in_state(state, crtc, crtc_state, i) {
 +              struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
 +              bool modeset = needs_modeset(crtc->state);
 +
 +              if (modeset && crtc->state->active) {
 +                      update_scanline_offset(to_intel_crtc(crtc));
 +                      dev_priv->display.crtc_enable(crtc);
 +              }
 +
 +              if (!modeset)
 +                      intel_pre_plane_update(intel_crtc);
 +
 +              drm_atomic_helper_commit_planes_on_crtc(crtc_state);
 +              intel_post_plane_update(intel_crtc);
        }
  
 -      dev = set->crtc->dev;
 +      /* FIXME: add subpixel order */
  
 -      state = drm_atomic_state_alloc(dev);
 -      if (!state)
 -              return -ENOMEM;
 +      drm_atomic_helper_wait_for_vblanks(dev, state);
 +      drm_atomic_helper_cleanup_planes(dev, state);
  
 -      state->acquire_ctx = dev->mode_config.acquire_ctx;
 +      if (any_ms)
 +              intel_modeset_check_state(dev, state);
  
 -      ret = intel_modeset_stage_output_state(dev, set, state);
 -      if (ret)
 -              goto out;
 +      drm_atomic_state_free(state);
 +
 +      return 0;
 +}
 +
 +void intel_crtc_restore_mode(struct drm_crtc *crtc)
 +{
 +      struct drm_device *dev = crtc->dev;
 +      struct drm_atomic_state *state;
 +      struct drm_crtc_state *crtc_state;
 +      int ret;
  
 -      pipe_config = intel_modeset_compute_config(set->crtc, state);
 -      if (IS_ERR(pipe_config)) {
 -              ret = PTR_ERR(pipe_config);
 -              goto out;
 +      state = drm_atomic_state_alloc(dev);
 +      if (!state) {
 +              DRM_DEBUG_KMS("[CRTC:%d] crtc restore failed, out of memory",
 +                            crtc->base.id);
 +              return;
        }
  
 -      intel_update_pipe_size(to_intel_crtc(set->crtc));
 +      state->acquire_ctx = drm_modeset_legacy_acquire_ctx(crtc);
  
 -      ret = intel_set_mode_with_config(set->crtc, pipe_config, true);
 +retry:
 +      crtc_state = drm_atomic_get_crtc_state(state, crtc);
 +      ret = PTR_ERR_OR_ZERO(crtc_state);
 +      if (!ret) {
 +              if (!crtc_state->active)
 +                      goto out;
  
 -      if (ret) {
 -              DRM_DEBUG_KMS("failed to set mode on [CRTC:%d], err = %d\n",
 -                            set->crtc->base.id, ret);
 +              crtc_state->mode_changed = true;
 +              ret = drm_atomic_commit(state);
 +      }
 +
 +      if (ret == -EDEADLK) {
 +              drm_atomic_state_clear(state);
 +              drm_modeset_backoff(state->acquire_ctx);
 +              goto retry;
        }
  
 -out:
        if (ret)
 +out:
                drm_atomic_state_free(state);
 -      return ret;
  }
  
 +#undef for_each_intel_crtc_masked
 +
  static const struct drm_crtc_funcs intel_crtc_funcs = {
        .gamma_set = intel_crtc_gamma_set,
 -      .set_config = intel_crtc_set_config,
 +      .set_config = drm_atomic_helper_set_config,
        .destroy = intel_crtc_destroy,
        .page_flip = intel_crtc_page_flip,
        .atomic_duplicate_state = intel_crtc_duplicate_state,
@@@ -13284,16 -13048,36 +13286,16 @@@ static void intel_shared_dpll_init(stru
  {
        struct drm_i915_private *dev_priv = dev->dev_private;
  
 +      intel_update_cdclk(dev);
 +
        if (HAS_DDI(dev))
                intel_ddi_pll_init(dev);
        else if (HAS_PCH_IBX(dev) || HAS_PCH_CPT(dev))
 -              ibx_pch_dpll_init(dev);
 -      else
 -              dev_priv->num_shared_dpll = 0;
 -
 -      BUG_ON(dev_priv->num_shared_dpll > I915_NUM_PLLS);
 -}
 -
 -/**
 - * intel_wm_need_update - Check whether watermarks need updating
 - * @plane: drm plane
 - * @state: new plane state
 - *
 - * Check current plane state versus the new one to determine whether
 - * watermarks need to be recalculated.
 - *
 - * Returns true or false.
 - */
 -bool intel_wm_need_update(struct drm_plane *plane,
 -                        struct drm_plane_state *state)
 -{
 -      /* Update watermarks on tiling changes. */
 -      if (!plane->state->fb || !state->fb ||
 -          plane->state->fb->modifier[0] != state->fb->modifier[0] ||
 -          plane->state->rotation != state->rotation)
 -              return true;
 +              ibx_pch_dpll_init(dev);
 +      else
 +              dev_priv->num_shared_dpll = 0;
  
 -      return false;
 +      BUG_ON(dev_priv->num_shared_dpll > I915_NUM_PLLS);
  }
  
  /**
@@@ -13315,13 -13099,27 +13317,13 @@@ intel_prepare_plane_fb(struct drm_plan
  {
        struct drm_device *dev = plane->dev;
        struct intel_plane *intel_plane = to_intel_plane(plane);
 -      enum pipe pipe = intel_plane->pipe;
        struct drm_i915_gem_object *obj = intel_fb_obj(fb);
        struct drm_i915_gem_object *old_obj = intel_fb_obj(plane->fb);
 -      unsigned frontbuffer_bits = 0;
        int ret = 0;
  
        if (!obj)
                return 0;
  
 -      switch (plane->type) {
 -      case DRM_PLANE_TYPE_PRIMARY:
 -              frontbuffer_bits = INTEL_FRONTBUFFER_PRIMARY(pipe);
 -              break;
 -      case DRM_PLANE_TYPE_CURSOR:
 -              frontbuffer_bits = INTEL_FRONTBUFFER_CURSOR(pipe);
 -              break;
 -      case DRM_PLANE_TYPE_OVERLAY:
 -              frontbuffer_bits = INTEL_FRONTBUFFER_SPRITE(pipe);
 -              break;
 -      }
 -
        mutex_lock(&dev->struct_mutex);
  
        if (plane->type == DRM_PLANE_TYPE_CURSOR &&
                if (ret)
                        DRM_DEBUG_KMS("failed to attach phys object\n");
        } else {
 -              ret = intel_pin_and_fence_fb_obj(plane, fb, new_state, NULL);
 +              ret = intel_pin_and_fence_fb_obj(plane, fb, new_state, NULL, NULL);
        }
  
        if (ret == 0)
 -              i915_gem_track_fb(old_obj, obj, frontbuffer_bits);
 +              i915_gem_track_fb(old_obj, obj, intel_plane->frontbuffer_bit);
  
        mutex_unlock(&dev->struct_mutex);
  
@@@ -13382,7 -13180,7 +13384,7 @@@ skl_max_scale(struct intel_crtc *intel_
        dev = intel_crtc->base.dev;
        dev_priv = dev->dev_private;
        crtc_clock = crtc_state->base.adjusted_mode.crtc_clock;
 -      cdclk = dev_priv->display.get_display_clock_speed(dev);
 +      cdclk = to_intel_atomic_state(crtc_state->base.state)->cdclk;
  
        if (!crtc_clock || !cdclk)
                return DRM_PLANE_HELPER_NO_SCALING;
  
  static int
  intel_check_primary_plane(struct drm_plane *plane,
 +                        struct intel_crtc_state *crtc_state,
                          struct intel_plane_state *state)
  {
 -      struct drm_device *dev = plane->dev;
 -      struct drm_i915_private *dev_priv = dev->dev_private;
        struct drm_crtc *crtc = state->base.crtc;
 -      struct intel_crtc *intel_crtc;
 -      struct intel_crtc_state *crtc_state;
        struct drm_framebuffer *fb = state->base.fb;
 -      struct drm_rect *dest = &state->dst;
 -      struct drm_rect *src = &state->src;
 -      const struct drm_rect *clip = &state->clip;
 -      bool can_position = false;
 -      int max_scale = DRM_PLANE_HELPER_NO_SCALING;
        int min_scale = DRM_PLANE_HELPER_NO_SCALING;
 -      int ret;
 -
 -      crtc = crtc ? crtc : plane->crtc;
 -      intel_crtc = to_intel_crtc(crtc);
 -      crtc_state = state->base.state ?
 -              intel_atomic_get_crtc_state(state->base.state, intel_crtc) : NULL;
 +      int max_scale = DRM_PLANE_HELPER_NO_SCALING;
 +      bool can_position = false;
  
 -      if (INTEL_INFO(dev)->gen >= 9) {
 -              /* use scaler when colorkey is not required */
 -              if (to_intel_plane(plane)->ckey.flags == I915_SET_COLORKEY_NONE) {
 -                      min_scale = 1;
 -                      max_scale = skl_max_scale(intel_crtc, crtc_state);
 -              }
 +      /* use scaler when colorkey is not required */
 +      if (INTEL_INFO(plane->dev)->gen >= 9 &&
 +          state->ckey.flags == I915_SET_COLORKEY_NONE) {
 +              min_scale = 1;
 +              max_scale = skl_max_scale(to_intel_crtc(crtc), crtc_state);
                can_position = true;
        }
  
 -      ret = drm_plane_helper_check_update(plane, crtc, fb,
 -                                          src, dest, clip,
 -                                          min_scale,
 -                                          max_scale,
 -                                          can_position, true,
 -                                          &state->visible);
 -      if (ret)
 -              return ret;
 -
 -      if (crtc_state ? crtc_state->base.active : intel_crtc->active) {
 -              struct intel_plane_state *old_state =
 -                      to_intel_plane_state(plane->state);
 -
 -              intel_crtc->atomic.wait_for_flips = true;
 -
 -              /*
 -               * 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 (state->visible &&
 -                  INTEL_INFO(dev)->gen <= 4 && !IS_G4X(dev) &&
 -                  dev_priv->fbc.crtc == intel_crtc &&
 -                  state->base.rotation != BIT(DRM_ROTATE_0)) {
 -                      intel_crtc->atomic.disable_fbc = true;
 -              }
 -
 -              if (state->visible && !old_state->visible) {
 -                      /*
 -                       * BDW signals flip done immediately if the plane
 -                       * is disabled, even if the plane enable is already
 -                       * armed to occur at the next vblank :(
 -                       */
 -                      if (IS_BROADWELL(dev))
 -                              intel_crtc->atomic.wait_vblank = true;
 -
 -                      if (crtc_state)
 -                              intel_crtc->atomic.post_enable_primary = true;
 -              }
 -
 -              /*
 -               * FIXME: Actually if we will still have any other plane enabled
 -               * on the pipe we could let IPS enabled still, but for
 -               * now lets consider that when we make primary invisible
 -               * by setting DSPCNTR to 0 on update_primary_plane function
 -               * IPS needs to be disable.
 -               */
 -              if (!state->visible || !fb)
 -                      intel_crtc->atomic.disable_ips = true;
 -
 -              if (!state->visible && old_state->visible &&
 -                  crtc_state && !needs_modeset(&crtc_state->base))
 -                      intel_crtc->atomic.pre_disable_primary = true;
 -
 -              intel_crtc->atomic.fb_bits |=
 -                      INTEL_FRONTBUFFER_PRIMARY(intel_crtc->pipe);
 -
 -              intel_crtc->atomic.update_fbc = true;
 -
 -              if (intel_wm_need_update(plane, &state->base))
 -                      intel_crtc->atomic.update_wm = true;
 -      }
 -
 -      if (INTEL_INFO(dev)->gen >= 9) {
 -              ret = skl_update_scaler_users(intel_crtc, crtc_state,
 -                      to_intel_plane(plane), state, 0);
 -              if (ret)
 -                      return ret;
 -      }
 -
 -      return 0;
 +      return drm_plane_helper_check_update(plane, crtc, fb, &state->src,
 +                                           &state->dst, &state->clip,
 +                                           min_scale, max_scale,
 +                                           can_position, true,
 +                                           &state->visible);
  }
  
  static void
@@@ -13442,19 -13324,20 +13444,19 @@@ intel_commit_primary_plane(struct drm_p
        crtc->x = src->x1 >> 16;
        crtc->y = src->y1 >> 16;
  
 -      if (intel_crtc->active) {
 -              if (state->visible)
 -                      /* FIXME: kill this fastboot hack */
 -                      intel_update_pipe_size(intel_crtc);
 +      if (!crtc->state->active)
 +              return;
  
 -              dev_priv->display.update_primary_plane(crtc, plane->fb,
 -                                                     crtc->x, crtc->y);
 -      }
 +      if (state->visible)
 +              /* FIXME: kill this fastboot hack */
 +              intel_update_pipe_size(intel_crtc);
 +
 +      dev_priv->display.update_primary_plane(crtc, fb, crtc->x, crtc->y);
  }
  
  static void
  intel_disable_primary_plane(struct drm_plane *plane,
 -                          struct drm_crtc *crtc,
 -                          bool force)
 +                          struct drm_crtc *crtc)
  {
        struct drm_device *dev = plane->dev;
        struct drm_i915_private *dev_priv = dev->dev_private;
        dev_priv->display.update_primary_plane(crtc, NULL, 0, 0);
  }
  
 -static void intel_begin_crtc_commit(struct drm_crtc *crtc)
 +static void intel_begin_crtc_commit(struct drm_crtc *crtc,
 +                                  struct drm_crtc_state *old_crtc_state)
  {
        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 intel_plane *intel_plane;
 -      struct drm_plane *p;
 -      unsigned fb_bits = 0;
 -
 -      /* Track fb's for any planes being disabled */
 -      list_for_each_entry(p, &dev->mode_config.plane_list, head) {
 -              intel_plane = to_intel_plane(p);
 -
 -              if (intel_crtc->atomic.disabled_planes &
 -                  (1 << drm_plane_index(p))) {
 -                      switch (p->type) {
 -                      case DRM_PLANE_TYPE_PRIMARY:
 -                              fb_bits = INTEL_FRONTBUFFER_PRIMARY(intel_plane->pipe);
 -                              break;
 -                      case DRM_PLANE_TYPE_CURSOR:
 -                              fb_bits = INTEL_FRONTBUFFER_CURSOR(intel_plane->pipe);
 -                              break;
 -                      case DRM_PLANE_TYPE_OVERLAY:
 -                              fb_bits = INTEL_FRONTBUFFER_SPRITE(intel_plane->pipe);
 -                              break;
 -                      }
 -
 -                      mutex_lock(&dev->struct_mutex);
 -                      i915_gem_track_fb(intel_fb_obj(p->fb), NULL, fb_bits);
 -                      mutex_unlock(&dev->struct_mutex);
 -              }
 -      }
 -
 -      if (intel_crtc->atomic.wait_for_flips)
 -              intel_crtc_wait_for_pending_flips(crtc);
 -
 -      if (intel_crtc->atomic.disable_fbc)
 -              intel_fbc_disable(dev);
 -
 -      if (intel_crtc->atomic.disable_ips)
 -              hsw_disable_ips(intel_crtc);
  
 -      if (intel_crtc->atomic.pre_disable_primary)
 -              intel_pre_disable_primary(crtc);
 -
 -      if (intel_crtc->atomic.update_wm)
 +      if (intel_crtc->atomic.update_wm_pre)
                intel_update_watermarks(crtc);
  
 -      intel_runtime_pm_get(dev_priv);
 -
        /* Perform vblank evasion around commit operation */
 -      if (intel_crtc->active)
 -              intel_crtc->atomic.evade =
 -                      intel_pipe_update_start(intel_crtc,
 -                                              &intel_crtc->atomic.start_vbl_count);
 +      if (crtc->state->active)
 +              intel_pipe_update_start(intel_crtc, &intel_crtc->start_vbl_count);
 +
 +      if (!needs_modeset(crtc->state) && INTEL_INFO(dev)->gen >= 9)
 +              skl_detach_scalers(intel_crtc);
  }
  
 -static void intel_finish_crtc_commit(struct drm_crtc *crtc)
 +static void intel_finish_crtc_commit(struct drm_crtc *crtc,
 +                                   struct drm_crtc_state *old_crtc_state)
  {
 -      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_plane *p;
 -
 -      if (intel_crtc->atomic.evade)
 -              intel_pipe_update_end(intel_crtc,
 -                                    intel_crtc->atomic.start_vbl_count);
 -
 -      intel_runtime_pm_put(dev_priv);
 -
 -      if (intel_crtc->atomic.wait_vblank)
 -              intel_wait_for_vblank(dev, intel_crtc->pipe);
  
 -      intel_frontbuffer_flip(dev, intel_crtc->atomic.fb_bits);
 -
 -      if (intel_crtc->atomic.update_fbc) {
 -              mutex_lock(&dev->struct_mutex);
 -              intel_fbc_update(dev);
 -              mutex_unlock(&dev->struct_mutex);
 -      }
 -
 -      if (intel_crtc->atomic.post_enable_primary)
 -              intel_post_enable_primary(crtc);
 -
 -      drm_for_each_legacy_plane(p, &dev->mode_config.plane_list)
 -              if (intel_crtc->atomic.update_sprite_watermarks & drm_plane_index(p))
 -                      intel_update_sprite_watermarks(p, crtc, 0, 0, 0,
 -                                                     false, false);
 -
 -      memset(&intel_crtc->atomic, 0, sizeof(intel_crtc->atomic));
 +      if (crtc->state->active)
 +              intel_pipe_update_end(intel_crtc, intel_crtc->start_vbl_count);
  }
  
  /**
@@@ -13541,10 -13490,10 +13543,10 @@@ static struct drm_plane *intel_primary_
        }
        primary->pipe = pipe;
        primary->plane = pipe;
 +      primary->frontbuffer_bit = INTEL_FRONTBUFFER_PRIMARY(pipe);
        primary->check_plane = intel_check_primary_plane;
        primary->commit_plane = intel_commit_primary_plane;
        primary->disable_plane = intel_disable_primary_plane;
 -      primary->ckey.flags = I915_SET_COLORKEY_NONE;
        if (HAS_FBC(dev) && INTEL_INFO(dev)->gen < 4)
                primary->plane = !pipe;
  
@@@ -13592,29 -13541,37 +13594,29 @@@ void intel_create_rotation_property(str
  
  static int
  intel_check_cursor_plane(struct drm_plane *plane,
 +                       struct intel_crtc_state *crtc_state,
                         struct intel_plane_state *state)
  {
 -      struct drm_crtc *crtc = state->base.crtc;
 -      struct drm_device *dev = plane->dev;
 +      struct drm_crtc *crtc = crtc_state->base.crtc;
        struct drm_framebuffer *fb = state->base.fb;
 -      struct drm_rect *dest = &state->dst;
 -      struct drm_rect *src = &state->src;
 -      const struct drm_rect *clip = &state->clip;
        struct drm_i915_gem_object *obj = intel_fb_obj(fb);
 -      struct intel_crtc *intel_crtc;
        unsigned stride;
        int ret;
  
 -      crtc = crtc ? crtc : plane->crtc;
 -      intel_crtc = to_intel_crtc(crtc);
 -
 -      ret = drm_plane_helper_check_update(plane, crtc, fb,
 -                                          src, dest, clip,
 +      ret = drm_plane_helper_check_update(plane, crtc, fb, &state->src,
 +                                          &state->dst, &state->clip,
                                            DRM_PLANE_HELPER_NO_SCALING,
                                            DRM_PLANE_HELPER_NO_SCALING,
                                            true, true, &state->visible);
        if (ret)
                return ret;
  
 -
        /* if we want to turn off the cursor ignore width and height */
        if (!obj)
 -              goto finish;
 +              return 0;
  
        /* Check for which cursor types we support */
 -      if (!cursor_size_ok(dev, state->base.crtc_w, state->base.crtc_h)) {
 +      if (!cursor_size_ok(plane->dev, state->base.crtc_w, state->base.crtc_h)) {
                DRM_DEBUG("Cursor dimension %dx%d not supported\n",
                          state->base.crtc_w, state->base.crtc_h);
                return -EINVAL;
  
        if (fb->modifier[0] != DRM_FORMAT_MOD_NONE) {
                DRM_DEBUG_KMS("cursor cannot be tiled\n");
 -              ret = -EINVAL;
 -      }
 -
 -finish:
 -      if (intel_crtc->active) {
 -              if (plane->state->crtc_w != state->base.crtc_w)
 -                      intel_crtc->atomic.update_wm = true;
 -
 -              intel_crtc->atomic.fb_bits |=
 -                      INTEL_FRONTBUFFER_CURSOR(intel_crtc->pipe);
 +              return -EINVAL;
        }
  
 -      return ret;
 +      return 0;
  }
  
  static void
  intel_disable_cursor_plane(struct drm_plane *plane,
 -                         struct drm_crtc *crtc,
 -                         bool force)
 +                         struct drm_crtc *crtc)
  {
 -      struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
 -
 -      if (!force) {
 -              plane->fb = NULL;
 -              intel_crtc->cursor_bo = NULL;
 -              intel_crtc->cursor_addr = 0;
 -      }
 -
        intel_crtc_update_cursor(crtc, false);
  }
  
@@@ -13670,9 -13645,9 +13672,9 @@@ intel_commit_cursor_plane(struct drm_pl
  
        intel_crtc->cursor_addr = addr;
        intel_crtc->cursor_bo = obj;
 -update:
  
 -      if (intel_crtc->active)
 +update:
 +      if (crtc->state->active)
                intel_crtc_update_cursor(crtc, state->visible);
  }
  
@@@ -13697,7 -13672,6 +13699,7 @@@ static struct drm_plane *intel_cursor_p
        cursor->max_downscale = 1;
        cursor->pipe = pipe;
        cursor->plane = pipe;
 +      cursor->frontbuffer_bit = INTEL_FRONTBUFFER_CURSOR(pipe);
        cursor->check_plane = intel_check_cursor_plane;
        cursor->commit_plane = intel_commit_cursor_plane;
        cursor->disable_plane = intel_disable_cursor_plane;
@@@ -13738,6 -13712,8 +13740,6 @@@ static void skl_init_scalers(struct drm
        for (i = 0; i < intel_crtc->num_scalers; i++) {
                intel_scaler = &scaler_state->scalers[i];
                intel_scaler->in_use = 0;
 -              intel_scaler->id = i;
 -
                intel_scaler->mode = PS_SCALER_MODE_DYN;
        }
  
@@@ -13809,8 -13785,6 +13811,8 @@@ static void intel_crtc_init(struct drm_
        intel_crtc->cursor_cntl = ~0;
        intel_crtc->cursor_size = ~0;
  
 +      intel_crtc->wm.cxsr_allowed = true;
 +
        BUG_ON(pipe >= ARRAY_SIZE(dev_priv->plane_to_crtc_mapping) ||
               dev_priv->plane_to_crtc_mapping[intel_crtc->plane] != NULL);
        dev_priv->plane_to_crtc_mapping[intel_crtc->plane] = &intel_crtc->base;
@@@ -13945,7 -13919,8 +13947,7 @@@ static void intel_setup_outputs(struct 
                 */
                found = I915_READ(DDI_BUF_CTL_A) & DDI_INIT_DISPLAY_DETECTED;
                /* WaIgnoreDDIAStrap: skl */
 -              if (found ||
 -                  (IS_SKYLAKE(dev) && INTEL_REVID(dev) < SKL_REVID_D0))
 +              if (found || IS_SKYLAKE(dev))
                        intel_ddi_init(dev, PORT_A);
  
                /* DDI B, C and D detection is indicated by the SFUSE_STRAP
                }
  
                intel_dsi_init(dev);
 -      } else if (SUPPORTS_DIGITAL_OUTPUTS(dev)) {
 +      } else if (!IS_GEN2(dev) && !IS_PINEVIEW(dev)) {
                bool found = false;
  
                if (I915_READ(GEN3_SDVOB) & SDVO_DETECTED) {
                        DRM_DEBUG_KMS("probing SDVOB\n");
                        found = intel_sdvo_init(dev, GEN3_SDVOB, true);
 -                      if (!found && SUPPORTS_INTEGRATED_HDMI(dev)) {
 +                      if (!found && IS_G4X(dev)) {
                                DRM_DEBUG_KMS("probing HDMI on SDVOB\n");
                                intel_hdmi_init(dev, GEN4_HDMIB, PORT_B);
                        }
  
 -                      if (!found && SUPPORTS_INTEGRATED_DP(dev))
 +                      if (!found && IS_G4X(dev))
                                intel_dp_init(dev, DP_B, PORT_B);
                }
  
  
                if (!found && (I915_READ(GEN3_SDVOC) & SDVO_DETECTED)) {
  
 -                      if (SUPPORTS_INTEGRATED_HDMI(dev)) {
 +                      if (IS_G4X(dev)) {
                                DRM_DEBUG_KMS("probing HDMI on SDVOC\n");
                                intel_hdmi_init(dev, GEN4_HDMIC, PORT_C);
                        }
 -                      if (SUPPORTS_INTEGRATED_DP(dev))
 +                      if (IS_G4X(dev))
                                intel_dp_init(dev, DP_C, PORT_C);
                }
  
 -              if (SUPPORTS_INTEGRATED_DP(dev) &&
 +              if (IS_G4X(dev) &&
                    (I915_READ(DP_D) & DP_DETECTED))
                        intel_dp_init(dev, DP_D, PORT_D);
        } else if (IS_GEN2(dev))
@@@ -14098,27 -14073,9 +14100,27 @@@ static int intel_user_framebuffer_creat
        return drm_gem_handle_create(file, &obj->base, handle);
  }
  
 +static int intel_user_framebuffer_dirty(struct drm_framebuffer *fb,
 +                                      struct drm_file *file,
 +                                      unsigned flags, unsigned color,
 +                                      struct drm_clip_rect *clips,
 +                                      unsigned num_clips)
 +{
 +      struct drm_device *dev = fb->dev;
 +      struct intel_framebuffer *intel_fb = to_intel_framebuffer(fb);
 +      struct drm_i915_gem_object *obj = intel_fb->obj;
 +
 +      mutex_lock(&dev->struct_mutex);
 +      intel_fb_obj_flush(obj, false, ORIGIN_DIRTYFB);
 +      mutex_unlock(&dev->struct_mutex);
 +
 +      return 0;
 +}
 +
  static const struct drm_framebuffer_funcs intel_fb_funcs = {
        .destroy = intel_user_framebuffer_destroy,
        .create_handle = intel_user_framebuffer_create_handle,
 +      .dirty = intel_user_framebuffer_dirty,
  };
  
  static
@@@ -14324,8 -14281,6 +14326,8 @@@ static const struct drm_mode_config_fun
        .output_poll_changed = intel_fbdev_output_poll_changed,
        .atomic_check = intel_atomic_check,
        .atomic_commit = intel_atomic_commit,
 +      .atomic_state_alloc = intel_atomic_state_alloc,
 +      .atomic_state_clear = intel_atomic_state_clear,
  };
  
  /* Set up chip specific display functions */
@@@ -14352,6 -14307,7 +14354,6 @@@ static void intel_init_display(struct d
                        haswell_crtc_compute_clock;
                dev_priv->display.crtc_enable = haswell_crtc_enable;
                dev_priv->display.crtc_disable = haswell_crtc_disable;
 -              dev_priv->display.off = ironlake_crtc_off;
                dev_priv->display.update_primary_plane =
                        skylake_update_primary_plane;
        } else if (HAS_DDI(dev)) {
                        haswell_crtc_compute_clock;
                dev_priv->display.crtc_enable = haswell_crtc_enable;
                dev_priv->display.crtc_disable = haswell_crtc_disable;
 -              dev_priv->display.off = ironlake_crtc_off;
                dev_priv->display.update_primary_plane =
                        ironlake_update_primary_plane;
        } else if (HAS_PCH_SPLIT(dev)) {
                        ironlake_crtc_compute_clock;
                dev_priv->display.crtc_enable = ironlake_crtc_enable;
                dev_priv->display.crtc_disable = ironlake_crtc_disable;
 -              dev_priv->display.off = ironlake_crtc_off;
                dev_priv->display.update_primary_plane =
                        ironlake_update_primary_plane;
        } else if (IS_VALLEYVIEW(dev)) {
                dev_priv->display.crtc_compute_clock = i9xx_crtc_compute_clock;
                dev_priv->display.crtc_enable = valleyview_crtc_enable;
                dev_priv->display.crtc_disable = i9xx_crtc_disable;
 -              dev_priv->display.off = i9xx_crtc_off;
                dev_priv->display.update_primary_plane =
                        i9xx_update_primary_plane;
        } else {
                dev_priv->display.crtc_compute_clock = i9xx_crtc_compute_clock;
                dev_priv->display.crtc_enable = i9xx_crtc_enable;
                dev_priv->display.crtc_disable = i9xx_crtc_disable;
 -              dev_priv->display.off = i9xx_crtc_off;
                dev_priv->display.update_primary_plane =
                        i9xx_update_primary_plane;
        }
        if (IS_SKYLAKE(dev))
                dev_priv->display.get_display_clock_speed =
                        skylake_get_display_clock_speed;
 +      else if (IS_BROXTON(dev))
 +              dev_priv->display.get_display_clock_speed =
 +                      broxton_get_display_clock_speed;
        else if (IS_BROADWELL(dev))
                dev_priv->display.get_display_clock_speed =
                        broadwell_get_display_clock_speed;
                dev_priv->display.get_display_clock_speed =
                        ilk_get_display_clock_speed;
        else if (IS_I945G(dev) || IS_BROADWATER(dev) ||
 -               IS_GEN6(dev) || IS_IVYBRIDGE(dev) || (IS_G33(dev) && !IS_PINEVIEW_M(dev)))
 +               IS_GEN6(dev) || IS_IVYBRIDGE(dev))
                dev_priv->display.get_display_clock_speed =
                        i945_get_display_clock_speed;
 +      else if (IS_GM45(dev))
 +              dev_priv->display.get_display_clock_speed =
 +                      gm45_get_display_clock_speed;
 +      else if (IS_CRESTLINE(dev))
 +              dev_priv->display.get_display_clock_speed =
 +                      i965gm_get_display_clock_speed;
 +      else if (IS_PINEVIEW(dev))
 +              dev_priv->display.get_display_clock_speed =
 +                      pnv_get_display_clock_speed;
 +      else if (IS_G33(dev) || IS_G4X(dev))
 +              dev_priv->display.get_display_clock_speed =
 +                      g33_get_display_clock_speed;
        else if (IS_I915G(dev))
                dev_priv->display.get_display_clock_speed =
                        i915_get_display_clock_speed;
                        i865_get_display_clock_speed;
        else if (IS_I85X(dev))
                dev_priv->display.get_display_clock_speed =
 -                      i855_get_display_clock_speed;
 -      else /* 852, 830 */
 +                      i85x_get_display_clock_speed;
 +      else { /* 830 */
 +              WARN(!IS_I830(dev), "Unknown platform. Assuming 133 MHz CDCLK\n");
                dev_priv->display.get_display_clock_speed =
                        i830_get_display_clock_speed;
 +      }
  
        if (IS_GEN5(dev)) {
                dev_priv->display.fdi_link_train = ironlake_fdi_link_train;
                dev_priv->display.fdi_link_train = ivb_manual_fdi_link_train;
        } else if (IS_HASWELL(dev) || IS_BROADWELL(dev)) {
                dev_priv->display.fdi_link_train = hsw_fdi_link_train;
 +              if (IS_BROADWELL(dev)) {
 +                      dev_priv->display.modeset_commit_cdclk =
 +                              broadwell_modeset_commit_cdclk;
 +                      dev_priv->display.modeset_calc_cdclk =
 +                              broadwell_modeset_calc_cdclk;
 +              }
        } else if (IS_VALLEYVIEW(dev)) {
 -              dev_priv->display.modeset_global_resources =
 -                      valleyview_modeset_global_resources;
 +              dev_priv->display.modeset_commit_cdclk =
 +                      valleyview_modeset_commit_cdclk;
 +              dev_priv->display.modeset_calc_cdclk =
 +                      valleyview_modeset_calc_cdclk;
        } else if (IS_BROXTON(dev)) {
 -              dev_priv->display.modeset_global_resources =
 -                      broxton_modeset_global_resources;
 +              dev_priv->display.modeset_commit_cdclk =
 +                      broxton_modeset_commit_cdclk;
 +              dev_priv->display.modeset_calc_cdclk =
 +                      broxton_modeset_calc_cdclk;
        }
  
        switch (INTEL_INFO(dev)->gen) {
@@@ -14696,9 -14629,13 +14698,9 @@@ static void i915_disable_vga(struct drm
  
  void intel_modeset_init_hw(struct drm_device *dev)
  {
 +      intel_update_cdclk(dev);
        intel_prepare_ddi(dev);
 -
 -      if (IS_VALLEYVIEW(dev))
 -              vlv_update_cdclk(dev);
 -
        intel_init_clock_gating(dev);
 -
        intel_enable_gt_powersave(dev);
  }
  
@@@ -14778,15 -14715,13 +14780,15 @@@ void intel_modeset_init(struct drm_devi
        intel_setup_outputs(dev);
  
        /* Just in case the BIOS is doing something questionable. */
 -      intel_fbc_disable(dev);
 +      intel_fbc_disable(dev_priv);
  
        drm_modeset_lock_all(dev);
 -      intel_modeset_setup_hw_state(dev, false);
 +      intel_modeset_setup_hw_state(dev);
        drm_modeset_unlock_all(dev);
  
        for_each_intel_crtc(dev, crtc) {
 +              struct intel_initial_plane_config plane_config = {};
 +
                if (!crtc->active)
                        continue;
  
                 * can even allow for smooth boot transitions if the BIOS
                 * fb is large enough for the active pipe configuration.
                 */
 -              if (dev_priv->display.get_initial_plane_config) {
 -                      dev_priv->display.get_initial_plane_config(crtc,
 -                                                         &crtc->plane_config);
 -                      /*
 -                       * If the fb is shared between multiple heads, we'll
 -                       * just get the first one.
 -                       */
 -                      intel_find_initial_plane_obj(crtc, &crtc->plane_config);
 -              }
 +              dev_priv->display.get_initial_plane_config(crtc,
 +                                                         &plane_config);
 +
 +              /*
 +               * If the fb is shared between multiple heads, we'll
 +               * just get the first one.
 +               */
 +              intel_find_initial_plane_obj(crtc, &plane_config);
        }
  }
  
@@@ -14856,9 -14792,7 +14858,9 @@@ static void intel_sanitize_crtc(struct 
  {
        struct drm_device *dev = crtc->base.dev;
        struct drm_i915_private *dev_priv = dev->dev_private;
 +      struct intel_encoder *encoder;
        u32 reg;
 +      bool enable;
  
        /* Clear any frame start delays used for debugging left by the BIOS */
        reg = PIPECONF(crtc->config->cpu_transcoder);
        /* restore vblank interrupts to correct state */
        drm_crtc_vblank_reset(&crtc->base);
        if (crtc->active) {
 +              drm_calc_timestamping_constants(&crtc->base, &crtc->base.hwmode);
                update_scanline_offset(crtc);
                drm_crtc_vblank_on(&crtc->base);
        }
         * disable the crtc (and hence change the state) if it is wrong. Note
         * that gen4+ has a fixed plane -> pipe mapping.  */
        if (INTEL_INFO(dev)->gen < 4 && !intel_check_plane_mapping(crtc)) {
 -              struct intel_connector *connector;
                bool plane;
  
                DRM_DEBUG_KMS("[CRTC:%d] wrong plane connection detected!\n",
                plane = crtc->plane;
                to_intel_plane_state(crtc->base.primary->state)->visible = true;
                crtc->plane = !plane;
 -              intel_crtc_disable_planes(&crtc->base);
 -              dev_priv->display.crtc_disable(&crtc->base);
 +              intel_crtc_disable_noatomic(&crtc->base);
                crtc->plane = plane;
 -
 -              /* ... and break all links. */
 -              for_each_intel_connector(dev, connector) {
 -                      if (connector->encoder->base.crtc != &crtc->base)
 -                              continue;
 -
 -                      connector->base.dpms = DRM_MODE_DPMS_OFF;
 -                      connector->base.encoder = NULL;
 -              }
 -              /* multiple connectors may have the same encoder:
 -               *  handle them and break crtc link separately */
 -              for_each_intel_connector(dev, connector)
 -                      if (connector->encoder->base.crtc == &crtc->base) {
 -                              connector->encoder->base.crtc = NULL;
 -                              connector->encoder->connectors_active = false;
 -                      }
 -
 -              WARN_ON(crtc->active);
 -              crtc->base.state->enable = false;
 -              crtc->base.state->active = false;
 -              crtc->base.enabled = false;
        }
  
        if (dev_priv->quirks & QUIRK_PIPEA_FORCE &&
  
        /* Adjust the state of the output pipe according to whether we
         * have active connectors/encoders. */
 -      intel_crtc_update_dpms(&crtc->base);
 +      enable = false;
 +      for_each_encoder_on_crtc(dev, &crtc->base, encoder) {
 +              enable = true;
 +              break;
 +      }
  
 -      if (crtc->active != crtc->base.state->enable) {
 -              struct intel_encoder *encoder;
 +      if (!enable)
 +              intel_crtc_disable_noatomic(&crtc->base);
 +
 +      if (crtc->active != crtc->base.state->active) {
  
                /* This can happen either due to bugs in the get_hw_state
 -               * functions or because the pipe is force-enabled due to the
 +               * functions or because of calls to intel_crtc_disable_noatomic,
 +               * or because the pipe is force-enabled due to the
                 * pipe A quirk. */
                DRM_DEBUG_KMS("[CRTC:%d] hw state adjusted, was %s, now %s\n",
                              crtc->base.base.id,
                              crtc->base.state->enable ? "enabled" : "disabled",
                              crtc->active ? "enabled" : "disabled");
  
 -              crtc->base.state->enable = crtc->active;
 +              WARN_ON(drm_atomic_set_mode_for_crtc(crtc->base.state, NULL) < 0);
                crtc->base.state->active = crtc->active;
                crtc->base.enabled = crtc->active;
  
                 *  actually up, hence no need to break them. */
                WARN_ON(crtc->active);
  
 -              for_each_encoder_on_crtc(dev, &crtc->base, encoder) {
 -                      WARN_ON(encoder->connectors_active);
 +              for_each_encoder_on_crtc(dev, &crtc->base, encoder)
                        encoder->base.crtc = NULL;
 -              }
        }
  
        if (crtc->active || HAS_GMCH_DISPLAY(dev)) {
@@@ -14960,7 -14911,6 +14962,7 @@@ static void intel_sanitize_encoder(stru
  {
        struct intel_connector *connector;
        struct drm_device *dev = encoder->base.dev;
 +      bool active = false;
  
        /* We need to check both for a crtc link (meaning that the
         * encoder is active and trying to read from a pipe) and the
        bool has_active_crtc = encoder->base.crtc &&
                to_intel_crtc(encoder->base.crtc)->active;
  
 -      if (encoder->connectors_active && !has_active_crtc) {
 +      for_each_intel_connector(dev, connector) {
 +              if (connector->base.encoder != &encoder->base)
 +                      continue;
 +
 +              active = true;
 +              break;
 +      }
 +
 +      if (active && !has_active_crtc) {
                DRM_DEBUG_KMS("[ENCODER:%d:%s] has active connectors but no active pipe!\n",
                              encoder->base.base.id,
                              encoder->base.name);
                                encoder->post_disable(encoder);
                }
                encoder->base.crtc = NULL;
 -              encoder->connectors_active = false;
  
                /* Inconsistent output/port/pipe state happens presumably due to
                 * a bug in one of the get_hw_state functions. Or someplace else
@@@ -15041,31 -14984,10 +15043,31 @@@ static bool primary_get_hw_state(struc
  {
        struct drm_i915_private *dev_priv = crtc->base.dev->dev_private;
  
 -      if (!crtc->active)
 -              return false;
 +      return !!(I915_READ(DSPCNTR(crtc->plane)) & DISPLAY_PLANE_ENABLE);
 +}
  
 -      return I915_READ(DSPCNTR(crtc->plane)) & DISPLAY_PLANE_ENABLE;
 +static void readout_plane_state(struct intel_crtc *crtc,
 +                              struct intel_crtc_state *crtc_state)
 +{
 +      struct intel_plane *p;
 +      struct intel_plane_state *plane_state;
 +      bool active = crtc_state->base.active;
 +
 +      for_each_intel_plane(crtc->base.dev, p) {
 +              if (crtc->pipe != p->pipe)
 +                      continue;
 +
 +              plane_state = to_intel_plane_state(p->base.state);
 +
 +              if (p->base.type == DRM_PLANE_TYPE_PRIMARY)
 +                      plane_state->visible = primary_get_hw_state(crtc);
 +              else {
 +                      if (active)
 +                              p->disable_plane(&p->base, &crtc->base);
 +
 +                      plane_state->visible = false;
 +              }
 +      }
  }
  
  static void intel_modeset_readout_hw_state(struct drm_device *dev)
        int i;
  
        for_each_intel_crtc(dev, crtc) {
 -              struct drm_plane *primary = crtc->base.primary;
 -              struct intel_plane_state *plane_state;
 -
 +              __drm_atomic_helper_crtc_destroy_state(&crtc->base, crtc->base.state);
                memset(crtc->config, 0, sizeof(*crtc->config));
                crtc->config->base.crtc = &crtc->base;
  
 -              crtc->config->quirks |= PIPE_CONFIG_QUIRK_INHERITED_MODE;
 -
                crtc->active = dev_priv->display.get_pipe_config(crtc,
                                                                 crtc->config);
  
 -              crtc->base.state->enable = crtc->active;
                crtc->base.state->active = crtc->active;
                crtc->base.enabled = crtc->active;
  
 -              plane_state = to_intel_plane_state(primary->state);
 -              plane_state->visible = primary_get_hw_state(crtc);
 +              memset(&crtc->base.mode, 0, sizeof(crtc->base.mode));
 +              if (crtc->base.state->active) {
 +                      intel_mode_from_pipe_config(&crtc->base.mode, crtc->config);
 +                      intel_mode_from_pipe_config(&crtc->base.state->adjusted_mode, crtc->config);
 +                      WARN_ON(drm_atomic_set_mode_for_crtc(crtc->base.state, &crtc->base.mode));
 +
 +                      /*
 +                       * The initial mode needs to be set in order to keep
 +                       * the atomic core happy. It wants a valid mode if the
 +                       * crtc's enabled, so we do the above call.
 +                       *
 +                       * At this point some state updated by the connectors
 +                       * in their ->detect() callback has not run yet, so
 +                       * no recalculation can be done yet.
 +                       *
 +                       * Even if we could do a recalculation and modeset
 +                       * right now it would cause a double modeset if
 +                       * fbdev or userspace chooses a different initial mode.
 +                       *
 +                       * If that happens, someone indicated they wanted a
 +                       * mode change, which means it's safe to do a full
 +                       * recalculation.
 +                       */
 +                      crtc->base.state->mode.private_flags = I915_MODE_FLAG_INHERITED;
 +              }
 +
 +              crtc->base.hwmode = crtc->config->base.adjusted_mode;
 +              readout_plane_state(crtc, to_intel_crtc_state(crtc->base.state));
  
                DRM_DEBUG_KMS("[CRTC:%d] hw state readout: %s\n",
                              crtc->base.base.id,
                        encoder->base.crtc = NULL;
                }
  
 -              encoder->connectors_active = false;
                DRM_DEBUG_KMS("[ENCODER:%d:%s] hw state readout: %s, pipe %c\n",
                              encoder->base.base.id,
                              encoder->base.name,
        for_each_intel_connector(dev, connector) {
                if (connector->get_hw_state(connector)) {
                        connector->base.dpms = DRM_MODE_DPMS_ON;
 -                      connector->encoder->connectors_active = true;
                        connector->base.encoder = &connector->encoder->base;
                } else {
                        connector->base.dpms = DRM_MODE_DPMS_OFF;
        }
  }
  
 -/* Scan out the current hw modeset state, sanitizes it and maps it into the drm
 - * and i915 state tracking structures. */
 -void intel_modeset_setup_hw_state(struct drm_device *dev,
 -                                bool force_restore)
 +/* Scan out the current hw modeset state,
 + * and sanitizes it to the current state
 + */
 +static void
 +intel_modeset_setup_hw_state(struct drm_device *dev)
  {
        struct drm_i915_private *dev_priv = dev->dev_private;
        enum pipe pipe;
  
        intel_modeset_readout_hw_state(dev);
  
 -      /*
 -       * Now that we have the config, copy it to each CRTC struct
 -       * Note that this could go away if we move to using crtc_config
 -       * checking everywhere.
 -       */
 -      for_each_intel_crtc(dev, crtc) {
 -              if (crtc->active && i915.fastboot) {
 -                      intel_mode_from_pipe_config(&crtc->base.mode,
 -                                                  crtc->config);
 -                      DRM_DEBUG_KMS("[CRTC:%d] found active mode: ",
 -                                    crtc->base.base.id);
 -                      drm_mode_debug_printmodeline(&crtc->base.mode);
 -              }
 -      }
 -
        /* HW state is read out, now we need to sanitize this mess. */
        for_each_intel_encoder(dev, encoder) {
                intel_sanitize_encoder(encoder);
                pll->on = false;
        }
  
 -      if (IS_GEN9(dev))
 +      if (IS_VALLEYVIEW(dev))
 +              vlv_wm_get_hw_state(dev);
 +      else if (IS_GEN9(dev))
                skl_wm_get_hw_state(dev);
        else if (HAS_PCH_SPLIT(dev))
                ilk_wm_get_hw_state(dev);
  
 -      if (force_restore) {
 -              i915_redisable_vga(dev);
 +      for_each_intel_crtc(dev, crtc) {
 +              unsigned long put_domains;
  
 -              /*
 -               * We need to use raw interfaces for restoring state to avoid
 -               * checking (bogus) intermediate states.
 -               */
 -              for_each_pipe(dev_priv, pipe) {
 -                      struct drm_crtc *crtc =
 -                              dev_priv->pipe_to_crtc_mapping[pipe];
 +              put_domains = modeset_get_crtc_power_domains(&crtc->base);
 +              if (WARN_ON(put_domains))
 +                      modeset_put_power_domains(dev_priv, put_domains);
 +      }
 +      intel_display_set_init_power(dev_priv, false);
 +}
  
 -                      intel_crtc_restore_mode(crtc);
 -              }
 -      } else {
 -              intel_modeset_update_staged_output_state(dev);
 +void intel_display_resume(struct drm_device *dev)
 +{
 +      struct drm_atomic_state *state = drm_atomic_state_alloc(dev);
 +      struct intel_connector *conn;
 +      struct intel_plane *plane;
 +      struct drm_crtc *crtc;
 +      int ret;
 +
 +      if (!state)
 +              return;
 +
 +      state->acquire_ctx = dev->mode_config.acquire_ctx;
 +
 +      /* preserve complete old state, including dpll */
 +      intel_atomic_get_shared_dpll_state(state);
 +
 +      for_each_crtc(dev, crtc) {
 +              struct drm_crtc_state *crtc_state =
 +                      drm_atomic_get_crtc_state(state, crtc);
 +
 +              ret = PTR_ERR_OR_ZERO(crtc_state);
 +              if (ret)
 +                      goto err;
 +
 +              /* force a restore */
 +              crtc_state->mode_changed = true;
        }
  
 -      intel_modeset_check_state(dev);
 +      for_each_intel_plane(dev, plane) {
 +              ret = PTR_ERR_OR_ZERO(drm_atomic_get_plane_state(state, &plane->base));
 +              if (ret)
 +                      goto err;
 +      }
 +
 +      for_each_intel_connector(dev, conn) {
 +              ret = PTR_ERR_OR_ZERO(drm_atomic_get_connector_state(state, &conn->base));
 +              if (ret)
 +                      goto err;
 +      }
 +
 +      intel_modeset_setup_hw_state(dev);
 +
 +      i915_redisable_vga(dev);
 +      ret = drm_atomic_commit(state);
 +      if (!ret)
 +              return;
 +
 +err:
 +      DRM_ERROR("Restoring old state failed with %i\n", ret);
 +      drm_atomic_state_free(state);
  }
  
  void intel_modeset_gem_init(struct drm_device *dev)
                ret = intel_pin_and_fence_fb_obj(c->primary,
                                                 c->primary->fb,
                                                 c->primary->state,
 -                                               NULL);
 +                                               NULL, NULL);
                mutex_unlock(&dev->struct_mutex);
                if (ret) {
                        DRM_ERROR("failed to pin boot fb on pipe %d\n",
                                  to_intel_crtc(c)->pipe);
                        drm_framebuffer_unreference(c->primary->fb);
                        c->primary->fb = NULL;
 +                      c->primary->crtc = c->primary->state->crtc = NULL;
                        update_state_fb(c->primary);
 +                      c->state->plane_mask &= ~(1 << drm_plane_index(c->primary));
                }
        }
  
@@@ -15370,9 -15241,13 +15372,9 @@@ void intel_modeset_cleanup(struct drm_d
         */
        drm_kms_helper_poll_fini(dev);
  
 -      mutex_lock(&dev->struct_mutex);
 -
        intel_unregister_dsm_handler();
  
 -      intel_fbc_disable(dev);
 -
 -      mutex_unlock(&dev->struct_mutex);
 +      intel_fbc_disable(dev_priv);
  
        /* flush any delayed tasks or pending work */
        flush_scheduled_work();
index aa5ac231955a55fd597843e5d984eda8ff9026e7,600afdbef8c9a434f51d527c5d85e202c36bae2b..f4fe1183bae694fd8446611b400d2128bc7128a1
@@@ -328,7 -328,7 +328,7 @@@ intel_dp_mst_connector_destroy(struct d
  }
  
  static const struct drm_connector_funcs intel_dp_mst_connector_funcs = {
 -      .dpms = intel_connector_dpms,
 +      .dpms = drm_atomic_helper_connector_dpms,
        .detect = intel_dp_mst_detect,
        .fill_modes = drm_helper_probe_single_connector_modes,
        .set_property = intel_dp_mst_set_property,
@@@ -357,6 -357,16 +357,16 @@@ intel_dp_mst_mode_valid(struct drm_conn
        return MODE_OK;
  }
  
+ static struct drm_encoder *intel_mst_atomic_best_encoder(struct drm_connector *connector,
+                                                        struct drm_connector_state *state)
+ {
+       struct intel_connector *intel_connector = to_intel_connector(connector);
+       struct intel_dp *intel_dp = intel_connector->mst_port;
+       struct intel_crtc *crtc = to_intel_crtc(state->crtc);
+       return &intel_dp->mst_encoders[crtc->pipe]->base.base;
+ }
  static struct drm_encoder *intel_mst_best_encoder(struct drm_connector *connector)
  {
        struct intel_connector *intel_connector = to_intel_connector(connector);
  static const struct drm_connector_helper_funcs intel_dp_mst_connector_helper_funcs = {
        .get_modes = intel_dp_mst_get_modes,
        .mode_valid = intel_dp_mst_mode_valid,
+       .atomic_best_encoder = intel_mst_atomic_best_encoder,
        .best_encoder = intel_mst_best_encoder,
  };
  
@@@ -441,9 -452,10 +452,9 @@@ static struct drm_connector *intel_dp_a
        drm_object_attach_property(&connector->base, dev->mode_config.tile_property, 0);
  
        drm_mode_connector_set_path_property(connector, pathprop);
 -      drm_reinit_primary_mode_group(dev);
 -      mutex_lock(&dev->mode_config.mutex);
 +      drm_modeset_lock_all(dev);
        intel_connector_add_to_fbdev(intel_connector);
 -      mutex_unlock(&dev->mode_config.mutex);
 +      drm_modeset_unlock_all(dev);
        drm_connector_register(&intel_connector->base);
        return connector;
  }
@@@ -453,28 -465,19 +464,28 @@@ static void intel_dp_destroy_mst_connec
  {
        struct intel_connector *intel_connector = to_intel_connector(connector);
        struct drm_device *dev = connector->dev;
 +
        /* need to nuke the connector */
 -      mutex_lock(&dev->mode_config.mutex);
 -      intel_connector_dpms(connector, DRM_MODE_DPMS_OFF);
 -      mutex_unlock(&dev->mode_config.mutex);
 +      drm_modeset_lock_all(dev);
 +      if (connector->state->crtc) {
 +              struct drm_mode_set set;
 +              int ret;
 +
 +              memset(&set, 0, sizeof(set));
 +              set.crtc = connector->state->crtc,
 +
 +              ret = drm_atomic_helper_set_config(&set);
 +
 +              WARN(ret, "Disabling mst crtc failed with %i\n", ret);
 +      }
 +      drm_modeset_unlock_all(dev);
  
        intel_connector->unregister(intel_connector);
  
 -      mutex_lock(&dev->mode_config.mutex);
 +      drm_modeset_lock_all(dev);
        intel_connector_remove_from_fbdev(intel_connector);
        drm_connector_cleanup(connector);
 -      mutex_unlock(&dev->mode_config.mutex);
 -
 -      drm_reinit_primary_mode_group(dev);
 +      drm_modeset_unlock_all(dev);
  
        kfree(intel_connector);
        DRM_DEBUG_KMS("\n");
index 45285a9178fe10e1fd1f4db25547a7a51b52853e,260389acfb7752d01ce0ebd59597f06a671b2ea1..9d3c2e420d2b68611d52e9c6395d35721da19447
@@@ -1274,10 -1274,12 +1274,12 @@@ int i915_reg_read_ioctl(struct drm_devi
        struct drm_i915_private *dev_priv = dev->dev_private;
        struct drm_i915_reg_read *reg = data;
        struct register_whitelist const *entry = whitelist;
+       unsigned size;
+       u64 offset;
        int i, ret = 0;
  
        for (i = 0; i < ARRAY_SIZE(whitelist); i++, entry++) {
-               if (entry->offset == reg->offset &&
+               if (entry->offset == (reg->offset & -entry->size) &&
                    (1 << INTEL_INFO(dev)->gen & entry->gen_bitmask))
                        break;
        }
        if (i == ARRAY_SIZE(whitelist))
                return -EINVAL;
  
+       /* We use the low bits to encode extra flags as the register should
+        * be naturally aligned (and those that are not so aligned merely
+        * limit the available flags for that register).
+        */
+       offset = entry->offset;
+       size = entry->size;
+       size |= reg->offset ^ offset;
        intel_runtime_pm_get(dev_priv);
  
-       switch (entry->size) {
+       switch (size) {
+       case 8 | 1:
+               reg->val = I915_READ64_2x32(offset, offset+4);
+               break;
        case 8:
-               reg->val = I915_READ64(reg->offset);
+               reg->val = I915_READ64(offset);
                break;
        case 4:
-               reg->val = I915_READ(reg->offset);
+               reg->val = I915_READ(offset);
                break;
        case 2:
-               reg->val = I915_READ16(reg->offset);
+               reg->val = I915_READ16(offset);
                break;
        case 1:
-               reg->val = I915_READ8(reg->offset);
+               reg->val = I915_READ8(offset);
                break;
        default:
-               MISSING_CASE(entry->size);
                ret = -EINVAL;
                goto out;
        }
@@@ -1455,80 -1467,20 +1467,80 @@@ static int gen6_do_reset(struct drm_dev
        return ret;
  }
  
 -int intel_gpu_reset(struct drm_device *dev)
 +static int wait_for_register(struct drm_i915_private *dev_priv,
 +                           const u32 reg,
 +                           const u32 mask,
 +                           const u32 value,
 +                           const unsigned long timeout_ms)
 +{
 +      return wait_for((I915_READ(reg) & mask) == value, timeout_ms);
 +}
 +
 +static int gen8_do_reset(struct drm_device *dev)
  {
 -      if (INTEL_INFO(dev)->gen >= 6)
 -              return gen6_do_reset(dev);
 +      struct drm_i915_private *dev_priv = dev->dev_private;
 +      struct intel_engine_cs *engine;
 +      int i;
 +
 +      for_each_ring(engine, dev_priv, i) {
 +              I915_WRITE(RING_RESET_CTL(engine->mmio_base),
 +                         _MASKED_BIT_ENABLE(RESET_CTL_REQUEST_RESET));
 +
 +              if (wait_for_register(dev_priv,
 +                                    RING_RESET_CTL(engine->mmio_base),
 +                                    RESET_CTL_READY_TO_RESET,
 +                                    RESET_CTL_READY_TO_RESET,
 +                                    700)) {
 +                      DRM_ERROR("%s: reset request timeout\n", engine->name);
 +                      goto not_ready;
 +              }
 +      }
 +
 +      return gen6_do_reset(dev);
 +
 +not_ready:
 +      for_each_ring(engine, dev_priv, i)
 +              I915_WRITE(RING_RESET_CTL(engine->mmio_base),
 +                         _MASKED_BIT_DISABLE(RESET_CTL_REQUEST_RESET));
 +
 +      return -EIO;
 +}
 +
 +static int (*intel_get_gpu_reset(struct drm_device *dev))(struct drm_device *)
 +{
 +      if (!i915.reset)
 +              return NULL;
 +
 +      if (INTEL_INFO(dev)->gen >= 8)
 +              return gen8_do_reset;
 +      else if (INTEL_INFO(dev)->gen >= 6)
 +              return gen6_do_reset;
        else if (IS_GEN5(dev))
 -              return ironlake_do_reset(dev);
 +              return ironlake_do_reset;
        else if (IS_G4X(dev))
 -              return g4x_do_reset(dev);
 +              return g4x_do_reset;
        else if (IS_G33(dev))
 -              return g33_do_reset(dev);
 +              return g33_do_reset;
        else if (INTEL_INFO(dev)->gen >= 3)
 -              return i915_do_reset(dev);
 +              return i915_do_reset;
        else
 +              return NULL;
 +}
 +
 +int intel_gpu_reset(struct drm_device *dev)
 +{
 +      int (*reset)(struct drm_device *);
 +
 +      reset = intel_get_gpu_reset(dev);
 +      if (reset == NULL)
                return -ENODEV;
 +
 +      return reset(dev);
 +}
 +
 +bool intel_has_gpu_reset(struct drm_device *dev)
 +{
 +      return intel_get_gpu_reset(dev) != NULL;
  }
  
  void intel_uncore_check_errors(struct drm_device *dev)
index 36b40c9252b5df3f7aac5608957f78e9c887aa4f,477cbb12809b029c2de6d62bdd0bcb3ba415001c..109b8262dc85942ac54720c57682402c161d435e
@@@ -128,6 -128,7 +128,7 @@@ nouveau_cli_destroy(struct nouveau_cli 
        nvkm_vm_ref(NULL, &nvxx_client(&cli->base)->vm, NULL);
        nvif_client_fini(&cli->base);
        usif_client_fini(cli);
+       kfree(cli);
  }
  
  static void
@@@ -865,8 -866,10 +866,10 @@@ nouveau_drm_preclose(struct drm_device 
  
        pm_runtime_get_sync(dev->dev);
  
+       mutex_lock(&cli->mutex);
        if (cli->abi16)
                nouveau_abi16_fini(cli->abi16);
+       mutex_unlock(&cli->mutex);
  
        mutex_lock(&drm->client.mutex);
        list_del(&cli->head);
@@@ -943,8 -946,7 +946,8 @@@ static struct drm_drive
  driver_stub = {
        .driver_features =
                DRIVER_USE_AGP |
 -              DRIVER_GEM | DRIVER_MODESET | DRIVER_PRIME | DRIVER_RENDER,
 +              DRIVER_GEM | DRIVER_MODESET | DRIVER_PRIME | DRIVER_RENDER |
 +              DRIVER_KMS_LEGACY_CONTEXT,
  
        .load = nouveau_drm_load,
        .unload = nouveau_drm_unload,
diff --combined include/drm/drmP.h
index 4717449d6aa90be0fa24f7f8e9cecc03e2489439,5aa519711e0b6fcb1212a517e50be5afac8ed7d7..5908848d86b38a331bd9c11556de5d05da77aaf2
@@@ -137,18 -137,17 +137,18 @@@ void drm_err(const char *format, ...)
  /*@{*/
  
  /* driver capabilities and requirements mask */
 -#define DRIVER_USE_AGP     0x1
 -#define DRIVER_PCI_DMA     0x8
 -#define DRIVER_SG          0x10
 -#define DRIVER_HAVE_DMA    0x20
 -#define DRIVER_HAVE_IRQ    0x40
 -#define DRIVER_IRQ_SHARED  0x80
 -#define DRIVER_GEM         0x1000
 -#define DRIVER_MODESET     0x2000
 -#define DRIVER_PRIME       0x4000
 -#define DRIVER_RENDER      0x8000
 -#define DRIVER_ATOMIC      0x10000
 +#define DRIVER_USE_AGP                        0x1
 +#define DRIVER_PCI_DMA                        0x8
 +#define DRIVER_SG                     0x10
 +#define DRIVER_HAVE_DMA                       0x20
 +#define DRIVER_HAVE_IRQ                       0x40
 +#define DRIVER_IRQ_SHARED             0x80
 +#define DRIVER_GEM                    0x1000
 +#define DRIVER_MODESET                        0x2000
 +#define DRIVER_PRIME                  0x4000
 +#define DRIVER_RENDER                 0x8000
 +#define DRIVER_ATOMIC                 0x10000
 +#define DRIVER_KMS_LEGACY_CONTEXT     0x20000
  
  /***********************************************************************/
  /** \name Macros to make printk easier */
@@@ -676,6 -675,7 +676,6 @@@ struct drm_minor 
  
        /* currently active master for this node. Protected by master_mutex */
        struct drm_master *master;
 -      struct drm_mode_group mode_group;
  };
  
  
@@@ -691,7 -691,7 +691,7 @@@ struct drm_vblank_crtc 
        struct timer_list disable_timer;                /* delayed disable timer */
  
        /* vblank counter, protected by dev->vblank_time_lock for writes */
-       unsigned long count;
+       u32 count;
        /* vblank timestamps, protected by dev->vblank_time_lock for writes */
        struct timeval time[DRM_VBLANKTIME_RBSIZE];
  
index 800e0d1cf32c2a397932a7597384350fd08a2f94,918aa68b5199d54501a2a9d68404e44388e9e04e..2a747a91fdede982354438e1c48fc1a332d06885
@@@ -108,10 -108,8 +108,10 @@@ struct drm_crtc_helper_funcs 
        /* atomic helpers */
        int (*atomic_check)(struct drm_crtc *crtc,
                            struct drm_crtc_state *state);
 -      void (*atomic_begin)(struct drm_crtc *crtc);
 -      void (*atomic_flush)(struct drm_crtc *crtc);
 +      void (*atomic_begin)(struct drm_crtc *crtc,
 +                           struct drm_crtc_state *old_crtc_state);
 +      void (*atomic_flush)(struct drm_crtc *crtc,
 +                           struct drm_crtc_state *old_crtc_state);
  };
  
  /**
@@@ -170,6 -168,7 +170,7 @@@ struct drm_encoder_helper_funcs 
   * @get_modes: get mode list for this connector
   * @mode_valid: is this mode valid on the given connector? (optional)
   * @best_encoder: return the preferred encoder for this connector
+  * @atomic_best_encoder: atomic version of @best_encoder
   *
   * The helper operations are called by the mid-layer CRTC helper.
   */
@@@ -178,6 -177,8 +179,8 @@@ struct drm_connector_helper_funcs 
        enum drm_mode_status (*mode_valid)(struct drm_connector *connector,
                                           struct drm_display_mode *mode);
        struct drm_encoder *(*best_encoder)(struct drm_connector *connector);
+       struct drm_encoder *(*atomic_best_encoder)(struct drm_connector *connector,
+                                                  struct drm_connector_state *connector_state);
  };
  
  extern void drm_helper_disable_unused_functions(struct drm_device *dev);
@@@ -189,7 -190,7 +192,7 @@@ extern bool drm_crtc_helper_set_mode(st
  extern bool drm_helper_crtc_in_use(struct drm_crtc *crtc);
  extern bool drm_helper_encoder_in_use(struct drm_encoder *encoder);
  
 -extern void drm_helper_connector_dpms(struct drm_connector *connector, int mode);
 +extern int drm_helper_connector_dpms(struct drm_connector *connector, int mode);
  
  extern void drm_helper_move_panel_connectors_to_head(struct drm_device *);
  
index 192027b4f0314a14e41b589b45fd4e80d8089ab9,db809b722985d3a1a03480cc1e3d36a656af2d2d..dbd16a2d37db6defcadf264d5f5a5b474d819be2
@@@ -354,15 -354,9 +354,15 @@@ typedef struct drm_i915_irq_wait 
  #define I915_PARAM_REVISION              32
  #define I915_PARAM_SUBSLICE_TOTAL      33
  #define I915_PARAM_EU_TOTAL            34
 +#define I915_PARAM_HAS_GPU_RESET       35
 +#define I915_PARAM_HAS_RESOURCE_STREAMER 36
  
  typedef struct drm_i915_getparam {
 -      int param;
 +      s32 param;
 +      /*
 +       * WARNING: Using pointers instead of fixed-size u64 means we need to write
 +       * compat32 code. Don't repeat this mistake.
 +       */
        int __user *value;
  } drm_i915_getparam_t;
  
@@@ -770,12 -764,7 +770,12 @@@ struct drm_i915_gem_execbuffer2 
  #define I915_EXEC_BSD_RING1           (1<<13)
  #define I915_EXEC_BSD_RING2           (2<<13)
  
 -#define __I915_EXEC_UNKNOWN_FLAGS -(1<<15)
 +/** Tell the kernel that the batchbuffer is processed by
 + *  the resource streamer.
 + */
 +#define I915_EXEC_RESOURCE_STREAMER     (1<<15)
 +
 +#define __I915_EXEC_UNKNOWN_FLAGS -(I915_EXEC_RESOURCE_STREAMER<<1)
  
  #define I915_EXEC_CONTEXT_ID_MASK     (0xffffffff)
  #define i915_execbuffer2_set_context_id(eb2, context) \
@@@ -1081,6 -1070,14 +1081,14 @@@ struct drm_i915_reg_read 
        __u64 offset;
        __u64 val; /* Return value */
  };
+ /* Known registers:
+  *
+  * Render engine timestamp - 0x2358 + 64bit - gen7+
+  * - Note this register returns an invalid value if using the default
+  *   single instruction 8byte read, in order to workaround that use
+  *   offset (0x2538 | 1) instead.
+  *
+  */
  
  struct drm_i915_reset_stats {
        __u32 ctx_id;
@@@ -1117,7 -1114,6 +1125,7 @@@ struct drm_i915_gem_context_param 
        __u32 size;
        __u64 param;
  #define I915_CONTEXT_PARAM_BAN_PERIOD 0x1
 +#define I915_CONTEXT_PARAM_NO_ZEROMAP 0x2
        __u64 value;
  };