Merge tag 'drm-intel-next-2015-01-17' of git://anongit.freedesktop.org/drm-intel...
authorDave Airlie <airlied@redhat.com>
Mon, 26 Jan 2015 23:01:09 +0000 (09:01 +1000)
committerDave Airlie <airlied@redhat.com>
Mon, 26 Jan 2015 23:01:09 +0000 (09:01 +1000)
- refactor i915/snd-hda interaction to use the component framework (Imre)
- psr cleanups and small fixes (Rodrigo)
- a few perf w/a from Ken Graunke
- switch to atomic plane helpers (Matt Roper)
- wc mmap support (Chris Wilson & Akash Goel)
- smaller things all over

* tag 'drm-intel-next-2015-01-17' of git://anongit.freedesktop.org/drm-intel: (40 commits)
  drm/i915: Update DRIVER_DATE to 20150117
  i915: reuse %ph to dump small buffers
  drm/i915: Ensure the HiZ RAW Stall Optimization is on for Cherryview.
  drm/i915: Enable the HiZ RAW Stall Optimization on Broadwell.
  drm/i915: PSR link standby at debugfs
  drm/i915: group link_standby setup and let this info visible everywhere.
  drm/i915: Add missing vbt check.
  drm/i915: PSR HSW/BDW: Fix inverted logic at sink main_link_active bit.
  drm/i915: PSR VLV/CHV: Remove condition checks that only applies to Haswell.
  drm/i915: VLV/CHV PSR needs to exit PSR on every flush.
  drm/i915: Fix kerneldoc for i915 atomic plane code
  drm/i915: Don't pretend SDVO hotplug works on 915
  drm/i915: Don't register HDMI connectors for eDP ports on VLV/CHV
  drm/i915: Remove I915_HAS_HOTPLUG() check from i915_hpd_irq_setup()
  drm/i915: Make hpd arrays big enough to avoid out of bounds access
  Revert "drm/i915/chv: Use timeout mode for RC6 on chv"
  drm/i915: Improve HiZ throughput on Cherryview.
  drm/i915: Reset CSB read pointer in ring init
  drm/i915: Drop unused position fields (v2)
  drm/i915: Move to atomic plane helpers (v9)
  ...

33 files changed:
Documentation/DocBook/drm.tmpl
drivers/gpu/drm/i915/Makefile
drivers/gpu/drm/i915/i915_debugfs.c
drivers/gpu/drm/i915/i915_dma.c
drivers/gpu/drm/i915/i915_drv.c
drivers/gpu/drm/i915/i915_drv.h
drivers/gpu/drm/i915/i915_gem.c
drivers/gpu/drm/i915/i915_gem_context.c
drivers/gpu/drm/i915/i915_gem_evict.c
drivers/gpu/drm/i915/i915_gem_execbuffer.c
drivers/gpu/drm/i915/i915_irq.c
drivers/gpu/drm/i915/i915_reg.h
drivers/gpu/drm/i915/intel_atomic_plane.c [new file with mode: 0644]
drivers/gpu/drm/i915/intel_audio.c
drivers/gpu/drm/i915/intel_bios.c
drivers/gpu/drm/i915/intel_bios.h
drivers/gpu/drm/i915/intel_display.c
drivers/gpu/drm/i915/intel_dp.c
drivers/gpu/drm/i915/intel_drv.h
drivers/gpu/drm/i915/intel_lrc.c
drivers/gpu/drm/i915/intel_pm.c
drivers/gpu/drm/i915/intel_psr.c
drivers/gpu/drm/i915/intel_ringbuffer.c
drivers/gpu/drm/i915/intel_runtime_pm.c
drivers/gpu/drm/i915/intel_sdvo.c
drivers/gpu/drm/i915/intel_sprite.c
include/drm/i915_component.h [new file with mode: 0644]
include/drm/i915_powerwell.h [deleted file]
include/uapi/drm/i915_drm.h
sound/pci/hda/hda_i915.c
sound/pci/hda/hda_i915.h [deleted file]
sound/pci/hda/hda_intel.c
sound/pci/hda/hda_intel.h [new file with mode: 0644]

index 3b2571e8481928175e11eed36e77368ac10e21f8..77d045557daf48d6fa332f80e021bd00a74f9eb5 100644 (file)
@@ -4017,6 +4017,11 @@ int num_ioctls;</synopsis>
          framebuffer compression and panel self refresh.
         </para>
       </sect2>
+      <sect2>
+        <title>Atomic Plane Helpers</title>
+!Pdrivers/gpu/drm/i915/intel_atomic_plane.c atomic plane helpers
+!Idrivers/gpu/drm/i915/intel_atomic_plane.c
+      </sect2>
       <sect2>
         <title>Output Probing</title>
         <para>
@@ -4159,6 +4164,17 @@ int num_ioctls;</synopsis>
 !Pdrivers/gpu/drm/i915/i915_gem_gtt.c Global GTT views
 !Idrivers/gpu/drm/i915/i915_gem_gtt.c
       </sect2>
+      <sect2>
+        <title>Buffer Object Eviction</title>
+       <para>
+         This section documents the interface function for evicting buffer
+         objects to make space available in the virtual gpu address spaces.
+         Note that this is mostly orthogonal to shrinking buffer objects
+         caches, which has the goal to make main memory (shared with the gpu
+         through the unified memory architecture) available.
+       </para>
+!Idrivers/gpu/drm/i915/i915_gem_evict.c
+      </sect2>
     </sect1>
 
     <sect1>
index 1849ffae61aec7e99bad921750e41b6bb5fc0cd7..16e3dc350274b51a426dc61a8c18251ccb18a392 100644 (file)
@@ -66,6 +66,7 @@ i915-y += dvo_ch7017.o \
          dvo_ns2501.o \
          dvo_sil164.o \
          dvo_tfp410.o \
+         intel_atomic_plane.o \
          intel_crt.o \
          intel_ddi.o \
          intel_dp.o \
index e515aad478585b7b72d5a080aa708688853252e9..0d11cbe9f80c5d1b0496be1c80f811f1a3df6a88 100644 (file)
@@ -2248,6 +2248,9 @@ static int i915_edp_psr_status(struct seq_file *m, void *data)
                }
        seq_puts(m, "\n");
 
+       seq_printf(m, "Link standby: %s\n",
+                  yesno((bool)dev_priv->psr.link_standby));
+
        /* CHV PSR has no kind of performance counter */
        if (HAS_PSR(dev) && HAS_DDI(dev)) {
                psrperf = I915_READ(EDP_PSR_PERF_CNT(dev)) &
index 52730ed863855f4484dd57c3c0f7f90a520bdb70..2447de36de44d889b94c5c29a9b5d774d49950e9 100644 (file)
@@ -143,6 +143,9 @@ static int i915_getparam(struct drm_device *dev, void *data,
        case I915_PARAM_HAS_COHERENT_PHYS_GTT:
                value = 1;
                break;
+       case I915_PARAM_MMAP_VERSION:
+               value = 1;
+               break;
        default:
                DRM_DEBUG("Unknown parameter %d\n", param->param);
                return -EINVAL;
@@ -830,6 +833,8 @@ int i915_driver_load(struct drm_device *dev, unsigned long flags)
 
        intel_runtime_pm_enable(dev_priv);
 
+       i915_audio_component_init(dev_priv);
+
        return 0;
 
 out_power_well:
@@ -870,6 +875,8 @@ int i915_driver_unload(struct drm_device *dev)
        struct drm_i915_private *dev_priv = dev->dev_private;
        int ret;
 
+       i915_audio_component_cleanup(dev_priv);
+
        ret = i915_gem_suspend(dev);
        if (ret) {
                DRM_ERROR("failed to idle hardware: %d\n", ret);
@@ -1063,6 +1070,8 @@ const struct drm_ioctl_desc i915_ioctls[] = {
        DRM_IOCTL_DEF_DRV(I915_REG_READ, i915_reg_read_ioctl, DRM_UNLOCKED|DRM_RENDER_ALLOW),
        DRM_IOCTL_DEF_DRV(I915_GET_RESET_STATS, i915_get_reset_stats_ioctl, DRM_UNLOCKED|DRM_RENDER_ALLOW),
        DRM_IOCTL_DEF_DRV(I915_GEM_USERPTR, i915_gem_userptr_ioctl, DRM_UNLOCKED|DRM_RENDER_ALLOW),
+       DRM_IOCTL_DEF_DRV(I915_GEM_CONTEXT_GETPARAM, i915_gem_context_getparam_ioctl, DRM_UNLOCKED|DRM_RENDER_ALLOW),
+       DRM_IOCTL_DEF_DRV(I915_GEM_CONTEXT_SETPARAM, i915_gem_context_setparam_ioctl, DRM_UNLOCKED|DRM_RENDER_ALLOW),
 };
 
 int i915_max_ioctl = ARRAY_SIZE(i915_ioctls);
index 0763fa0791e32b1324614801b4cc16adb8306ee7..308774f420790d39cd1691cc4235fec36fd8c138 100644 (file)
@@ -942,8 +942,7 @@ static int i915_pm_suspend(struct device *dev)
 
 static int i915_pm_suspend_late(struct device *dev)
 {
-       struct pci_dev *pdev = to_pci_dev(dev);
-       struct drm_device *drm_dev = pci_get_drvdata(pdev);
+       struct drm_device *drm_dev = dev_to_i915(dev)->dev;
 
        /*
         * We have a suspedn ordering issue with the snd-hda driver also
@@ -962,8 +961,7 @@ static int i915_pm_suspend_late(struct device *dev)
 
 static int i915_pm_resume_early(struct device *dev)
 {
-       struct pci_dev *pdev = to_pci_dev(dev);
-       struct drm_device *drm_dev = pci_get_drvdata(pdev);
+       struct drm_device *drm_dev = dev_to_i915(dev)->dev;
 
        if (drm_dev->switch_power_state == DRM_SWITCH_POWER_OFF)
                return 0;
@@ -973,8 +971,7 @@ static int i915_pm_resume_early(struct device *dev)
 
 static int i915_pm_resume(struct device *dev)
 {
-       struct pci_dev *pdev = to_pci_dev(dev);
-       struct drm_device *drm_dev = pci_get_drvdata(pdev);
+       struct drm_device *drm_dev = dev_to_i915(dev)->dev;
 
        if (drm_dev->switch_power_state == DRM_SWITCH_POWER_OFF)
                return 0;
index 54f2a275dba628c9f6555b7e3213b89e82fe03ad..ede48628bf8587bcd041edfb63041a0c650bc26b 100644 (file)
@@ -55,7 +55,7 @@
 
 #define DRIVER_NAME            "i915"
 #define DRIVER_DESC            "Intel Graphics"
-#define DRIVER_DATE            "20141219"
+#define DRIVER_DATE            "20150117"
 
 #undef WARN_ON
 /* Many gcc seem to no see through this and fall over :( */
@@ -83,7 +83,7 @@
        int __ret_warn_on = !!(condition);                              \
        if (unlikely(__ret_warn_on)) {                                  \
                if (i915.verbose_state_checks)                          \
-                       __WARN_printf(format);                          \
+                       WARN(1, format);                                \
                else                                                    \
                        DRM_ERROR(format);                              \
        }                                                               \
@@ -94,7 +94,7 @@
        int __ret_warn_on = !!(condition);                              \
        if (unlikely(__ret_warn_on)) {                                  \
                if (i915.verbose_state_checks)                          \
-                       __WARN_printf("WARN_ON(" #condition ")\n");     \
+                       WARN(1, "WARN_ON(" #condition ")\n");           \
                else                                                    \
                        DRM_ERROR("WARN_ON(" #condition ")\n");         \
        }                                                               \
@@ -678,6 +678,11 @@ struct i915_ctx_hang_stats {
        /* Time when this context was last blamed for a GPU reset */
        unsigned long guilty_ts;
 
+       /* If the contexts causes a second GPU hang within this time,
+        * it is permanently banned from submitting any more work.
+        */
+       unsigned long ban_period_seconds;
+
        /* This context is banned to submit more work */
        bool banned;
 };
@@ -784,6 +789,7 @@ struct i915_psr {
        bool active;
        struct delayed_work work;
        unsigned busy_frontbuffer_bits;
+       bool link_standby;
 };
 
 enum intel_pch {
@@ -1409,7 +1415,6 @@ struct intel_vbt_data {
                bool present;
                bool active_low_pwm;
                u8 min_brightness;      /* min_brightness/255 of max */
-               u8 controller;          /* brightness controller number */
        } backlight;
 
        /* MIPI DSI */
@@ -1768,6 +1773,9 @@ struct drm_i915_private {
        struct drm_property *broadcast_rgb_property;
        struct drm_property *force_audio_property;
 
+       /* hda/i915 audio component */
+       bool audio_component_registered;
+
        uint32_t hw_context_size;
        struct list_head context_list;
 
@@ -1853,6 +1861,11 @@ static inline struct drm_i915_private *to_i915(const struct drm_device *dev)
        return dev->dev_private;
 }
 
+static inline struct drm_i915_private *dev_to_i915(struct device *dev)
+{
+       return to_i915(dev_get_drvdata(dev));
+}
+
 /* Iterate over initialised rings */
 #define for_each_ring(ring__, dev_priv__, i__) \
        for ((i__) = 0; (i__) < I915_NUM_RINGS; (i__)++) \
@@ -2892,6 +2905,10 @@ int i915_gem_context_create_ioctl(struct drm_device *dev, void *data,
                                  struct drm_file *file);
 int i915_gem_context_destroy_ioctl(struct drm_device *dev, void *data,
                                   struct drm_file *file);
+int i915_gem_context_getparam_ioctl(struct drm_device *dev, void *data,
+                                   struct drm_file *file_priv);
+int i915_gem_context_setparam_ioctl(struct drm_device *dev, void *data,
+                                   struct drm_file *file_priv);
 
 /* i915_gem_evict.c */
 int __must_check i915_gem_evict_something(struct drm_device *dev,
index 4e4d969d3b283ee67411289cb52d3fe0d1285487..6c403654e33a121c0d6c3028e1e3e467fef84b04 100644 (file)
@@ -153,12 +153,6 @@ int i915_mutex_lock_interruptible(struct drm_device *dev)
        return 0;
 }
 
-static inline bool
-i915_gem_object_is_inactive(struct drm_i915_gem_object *obj)
-{
-       return i915_gem_obj_bound_any(obj) && !obj->active;
-}
-
 int
 i915_gem_get_aperture_ioctl(struct drm_device *dev, void *data,
                            struct drm_file *file)
@@ -1487,18 +1481,10 @@ i915_gem_set_domain_ioctl(struct drm_device *dev, void *data,
        if (ret)
                goto unref;
 
-       if (read_domains & I915_GEM_DOMAIN_GTT) {
+       if (read_domains & I915_GEM_DOMAIN_GTT)
                ret = i915_gem_object_set_to_gtt_domain(obj, write_domain != 0);
-
-               /* Silently promote "you're not bound, there was nothing to do"
-                * to success, since the client was just asking us to
-                * make sure everything was done.
-                */
-               if (ret == -EINVAL)
-                       ret = 0;
-       } else {
+       else
                ret = i915_gem_object_set_to_cpu_domain(obj, write_domain != 0);
-       }
 
 unref:
        drm_gem_object_unreference(&obj->base);
@@ -1563,6 +1549,12 @@ i915_gem_mmap_ioctl(struct drm_device *dev, void *data,
        struct drm_gem_object *obj;
        unsigned long addr;
 
+       if (args->flags & ~(I915_MMAP_WC))
+               return -EINVAL;
+
+       if (args->flags & I915_MMAP_WC && !cpu_has_pat)
+               return -ENODEV;
+
        obj = drm_gem_object_lookup(dev, file, args->handle);
        if (obj == NULL)
                return -ENOENT;
@@ -1578,6 +1570,19 @@ i915_gem_mmap_ioctl(struct drm_device *dev, void *data,
        addr = vm_mmap(obj->filp, 0, args->size,
                       PROT_READ | PROT_WRITE, MAP_SHARED,
                       args->offset);
+       if (args->flags & I915_MMAP_WC) {
+               struct mm_struct *mm = current->mm;
+               struct vm_area_struct *vma;
+
+               down_write(&mm->mmap_sem);
+               vma = find_vma(mm, addr);
+               if (vma)
+                       vma->vm_page_prot =
+                               pgprot_writecombine(vm_get_page_prot(vma->vm_flags));
+               else
+                       addr = -ENOMEM;
+               up_write(&mm->mmap_sem);
+       }
        drm_gem_object_unreference_unlocked(obj);
        if (IS_ERR((void *)addr))
                return addr;
@@ -2529,7 +2534,8 @@ static bool i915_context_is_banned(struct drm_i915_private *dev_priv,
        if (ctx->hang_stats.banned)
                return true;
 
-       if (elapsed <= DRM_I915_CTX_BAN_PERIOD) {
+       if (ctx->hang_stats.ban_period_seconds &&
+           elapsed <= ctx->hang_stats.ban_period_seconds) {
                if (!i915_gem_context_is_default(ctx)) {
                        DRM_DEBUG("context hanging too fast, banning!\n");
                        return true;
@@ -3698,15 +3704,10 @@ i915_gem_object_flush_cpu_write_domain(struct drm_i915_gem_object *obj,
 int
 i915_gem_object_set_to_gtt_domain(struct drm_i915_gem_object *obj, bool write)
 {
-       struct drm_i915_private *dev_priv = obj->base.dev->dev_private;
-       struct i915_vma *vma = i915_gem_obj_to_ggtt(obj);
        uint32_t old_write_domain, old_read_domains;
+       struct i915_vma *vma;
        int ret;
 
-       /* Not valid to be called on unbound objects. */
-       if (vma == NULL)
-               return -EINVAL;
-
        if (obj->base.write_domain == I915_GEM_DOMAIN_GTT)
                return 0;
 
@@ -3715,6 +3716,19 @@ i915_gem_object_set_to_gtt_domain(struct drm_i915_gem_object *obj, bool write)
                return ret;
 
        i915_gem_object_retire(obj);
+
+       /* Flush and acquire obj->pages so that we are coherent through
+        * direct access in memory with previous cached writes through
+        * shmemfs and that our cache domain tracking remains valid.
+        * For example, if the obj->filp was moved to swap without us
+        * being notified and releasing the pages, we would mistakenly
+        * continue to assume that the obj remained out of the CPU cached
+        * domain.
+        */
+       ret = i915_gem_object_get_pages(obj);
+       if (ret)
+               return ret;
+
        i915_gem_object_flush_cpu_write_domain(obj, false);
 
        /* Serialise direct access to this object with the barriers for
@@ -3746,9 +3760,10 @@ i915_gem_object_set_to_gtt_domain(struct drm_i915_gem_object *obj, bool write)
                                            old_write_domain);
 
        /* And bump the LRU for this access */
-       if (i915_gem_object_is_inactive(obj))
+       vma = i915_gem_obj_to_ggtt(obj);
+       if (vma && drm_mm_node_allocated(&vma->node) && !obj->active)
                list_move_tail(&vma->mm_list,
-                              &dev_priv->gtt.base.inactive_list);
+                              &to_i915(obj->base.dev)->gtt.base.inactive_list);
 
        return 0;
 }
index 9b23fb1f5bf655fb533e2154cf8bbf67f52a7dfe..8603bf48d3eeba142913e494131396641c8cc73b 100644 (file)
@@ -222,6 +222,8 @@ __create_hw_context(struct drm_device *dev,
         * is no remap info, it will be a NOP. */
        ctx->remap_slice = (1 << NUM_L3_SLICES(dev)) - 1;
 
+       ctx->hang_stats.ban_period_seconds = DRM_I915_CTX_BAN_PERIOD;
+
        return ctx;
 
 err_out:
@@ -792,3 +794,72 @@ int i915_gem_context_destroy_ioctl(struct drm_device *dev, void *data,
        DRM_DEBUG_DRIVER("HW context %d destroyed\n", args->ctx_id);
        return 0;
 }
+
+int i915_gem_context_getparam_ioctl(struct drm_device *dev, void *data,
+                                   struct drm_file *file)
+{
+       struct drm_i915_file_private *file_priv = file->driver_priv;
+       struct drm_i915_gem_context_param *args = data;
+       struct intel_context *ctx;
+       int ret;
+
+       ret = i915_mutex_lock_interruptible(dev);
+       if (ret)
+               return ret;
+
+       ctx = i915_gem_context_get(file_priv, args->ctx_id);
+       if (IS_ERR(ctx)) {
+               mutex_unlock(&dev->struct_mutex);
+               return PTR_ERR(ctx);
+       }
+
+       args->size = 0;
+       switch (args->param) {
+       case I915_CONTEXT_PARAM_BAN_PERIOD:
+               args->value = ctx->hang_stats.ban_period_seconds;
+               break;
+       default:
+               ret = -EINVAL;
+               break;
+       }
+       mutex_unlock(&dev->struct_mutex);
+
+       return ret;
+}
+
+int i915_gem_context_setparam_ioctl(struct drm_device *dev, void *data,
+                                   struct drm_file *file)
+{
+       struct drm_i915_file_private *file_priv = file->driver_priv;
+       struct drm_i915_gem_context_param *args = data;
+       struct intel_context *ctx;
+       int ret;
+
+       ret = i915_mutex_lock_interruptible(dev);
+       if (ret)
+               return ret;
+
+       ctx = i915_gem_context_get(file_priv, args->ctx_id);
+       if (IS_ERR(ctx)) {
+               mutex_unlock(&dev->struct_mutex);
+               return PTR_ERR(ctx);
+       }
+
+       switch (args->param) {
+       case I915_CONTEXT_PARAM_BAN_PERIOD:
+               if (args->size)
+                       ret = -EINVAL;
+               else if (args->value < ctx->hang_stats.ban_period_seconds &&
+                        !capable(CAP_SYS_ADMIN))
+                       ret = -EPERM;
+               else
+                       ctx->hang_stats.ban_period_seconds = args->value;
+               break;
+       default:
+               ret = -EINVAL;
+               break;
+       }
+       mutex_unlock(&dev->struct_mutex);
+
+       return ret;
+}
index 886ff2ee7a282e0762855e244e40cd8a7493b1fe..e3a49d94da3a794fe3524fb79eadefa423b266b8 100644 (file)
@@ -50,11 +50,12 @@ mark_free(struct i915_vma *vma, struct list_head *unwind)
  * i915_gem_evict_something - Evict vmas to make room for binding a new one
  * @dev: drm_device
  * @vm: address space to evict from
- * @size: size of the desired free space
+ * @min_size: size of the desired free space
  * @alignment: alignment constraint of the desired free space
  * @cache_level: cache_level for the desired space
- * @mappable: whether the free space must be mappable
- * @nonblocking: whether evicting active objects is allowed or not
+ * @start: start (inclusive) of the range from which to evict objects
+ * @end: end (exclusive) of the range from which to evict objects
+ * @flags: additional flags to control the eviction algorithm
  *
  * This function will try to evict vmas until a free space satisfying the
  * requirements is found. Callers must check first whether any such hole exists
@@ -196,7 +197,6 @@ found:
 
 /**
  * i915_gem_evict_vm - Evict all idle vmas from a vm
- *
  * @vm: Address space to cleanse
  * @do_idle: Boolean directing whether to idle first.
  *
@@ -214,6 +214,7 @@ int i915_gem_evict_vm(struct i915_address_space *vm, bool do_idle)
        struct i915_vma *vma, *next;
        int ret;
 
+       WARN_ON(!mutex_is_locked(&vm->dev->struct_mutex));
        trace_i915_gem_evict_vm(vm);
 
        if (do_idle) {
@@ -222,6 +223,8 @@ int i915_gem_evict_vm(struct i915_address_space *vm, bool do_idle)
                        return ret;
 
                i915_gem_retire_requests(vm->dev);
+
+               WARN_ON(!list_empty(&vm->active_list));
        }
 
        list_for_each_entry_safe(vma, next, &vm->inactive_list, mm_list)
index 1d6e0929ab831981e843c888e32bd55fd556cabd..e3ef17783765e5ae366194f8cef8d7d5a7ba0137 100644 (file)
@@ -1081,6 +1081,7 @@ i915_gem_execbuffer_parse(struct intel_engine_cs *ring,
 {
        struct drm_i915_private *dev_priv = to_i915(batch_obj->base.dev);
        struct drm_i915_gem_object *shadow_batch_obj;
+       bool need_reloc = false;
        int ret;
 
        shadow_batch_obj = i915_gem_batch_pool_get(&dev_priv->mm.batch_pool,
@@ -1106,6 +1107,7 @@ i915_gem_execbuffer_parse(struct intel_engine_cs *ring,
                vma->exec_entry = shadow_exec_entry;
                vma->exec_entry->flags = __EXEC_OBJECT_PURGEABLE;
                drm_gem_object_reference(&shadow_batch_obj->base);
+               i915_gem_execbuffer_reserve_vma(vma, ring, &need_reloc);
                list_add_tail(&vma->exec_list, &eb->vmas);
 
                shadow_batch_obj->base.pending_read_domains =
index 818ab4e9dabc0201a68be2471a6f541826d7a23b..8fe5a87705f7c607fd4e75df39124a42d4f3cb55 100644 (file)
@@ -45,7 +45,7 @@
  * and related files, but that will be described in separate chapters.
  */
 
-static const u32 hpd_ibx[] = {
+static const u32 hpd_ibx[HPD_NUM_PINS] = {
        [HPD_CRT] = SDE_CRT_HOTPLUG,
        [HPD_SDVO_B] = SDE_SDVOB_HOTPLUG,
        [HPD_PORT_B] = SDE_PORTB_HOTPLUG,
@@ -53,7 +53,7 @@ static const u32 hpd_ibx[] = {
        [HPD_PORT_D] = SDE_PORTD_HOTPLUG
 };
 
-static const u32 hpd_cpt[] = {
+static const u32 hpd_cpt[HPD_NUM_PINS] = {
        [HPD_CRT] = SDE_CRT_HOTPLUG_CPT,
        [HPD_SDVO_B] = SDE_SDVOB_HOTPLUG_CPT,
        [HPD_PORT_B] = SDE_PORTB_HOTPLUG_CPT,
@@ -61,7 +61,7 @@ static const u32 hpd_cpt[] = {
        [HPD_PORT_D] = SDE_PORTD_HOTPLUG_CPT
 };
 
-static const u32 hpd_mask_i915[] = {
+static const u32 hpd_mask_i915[HPD_NUM_PINS] = {
        [HPD_CRT] = CRT_HOTPLUG_INT_EN,
        [HPD_SDVO_B] = SDVOB_HOTPLUG_INT_EN,
        [HPD_SDVO_C] = SDVOC_HOTPLUG_INT_EN,
@@ -70,7 +70,7 @@ static const u32 hpd_mask_i915[] = {
        [HPD_PORT_D] = PORTD_HOTPLUG_INT_EN
 };
 
-static const u32 hpd_status_g4x[] = {
+static const u32 hpd_status_g4x[HPD_NUM_PINS] = {
        [HPD_CRT] = CRT_HOTPLUG_INT_STATUS,
        [HPD_SDVO_B] = SDVOB_HOTPLUG_INT_STATUS_G4X,
        [HPD_SDVO_C] = SDVOC_HOTPLUG_INT_STATUS_G4X,
@@ -79,7 +79,7 @@ static const u32 hpd_status_g4x[] = {
        [HPD_PORT_D] = PORTD_HOTPLUG_INT_STATUS
 };
 
-static const u32 hpd_status_i915[] = { /* i915 and valleyview are the same */
+static const u32 hpd_status_i915[HPD_NUM_PINS] = { /* i915 and valleyview are the same */
        [HPD_CRT] = CRT_HOTPLUG_INT_STATUS,
        [HPD_SDVO_B] = SDVOB_HOTPLUG_INT_STATUS_I915,
        [HPD_SDVO_C] = SDVOC_HOTPLUG_INT_STATUS_I915,
@@ -1522,7 +1522,7 @@ static inline enum port get_port_from_pin(enum hpd_pin pin)
 static inline void intel_hpd_irq_handler(struct drm_device *dev,
                                         u32 hotplug_trigger,
                                         u32 dig_hotplug_reg,
-                                        const u32 *hpd)
+                                        const u32 hpd[HPD_NUM_PINS])
 {
        struct drm_i915_private *dev_priv = dev->dev_private;
        int i;
@@ -4145,26 +4145,24 @@ static void i915_hpd_irq_setup(struct drm_device *dev)
 
        assert_spin_locked(&dev_priv->irq_lock);
 
-       if (I915_HAS_HOTPLUG(dev)) {
-               hotplug_en = I915_READ(PORT_HOTPLUG_EN);
-               hotplug_en &= ~HOTPLUG_INT_EN_MASK;
-               /* Note HDMI and DP share hotplug bits */
-               /* enable bits are the same for all generations */
-               for_each_intel_encoder(dev, intel_encoder)
-                       if (dev_priv->hpd_stats[intel_encoder->hpd_pin].hpd_mark == HPD_ENABLED)
-                               hotplug_en |= hpd_mask_i915[intel_encoder->hpd_pin];
-               /* Programming the CRT detection parameters tends
-                  to generate a spurious hotplug event about three
-                  seconds later.  So just do it once.
-               */
-               if (IS_G4X(dev))
-                       hotplug_en |= CRT_HOTPLUG_ACTIVATION_PERIOD_64;
-               hotplug_en &= ~CRT_HOTPLUG_VOLTAGE_COMPARE_MASK;
-               hotplug_en |= CRT_HOTPLUG_VOLTAGE_COMPARE_50;
-
-               /* Ignore TV since it's buggy */
-               I915_WRITE(PORT_HOTPLUG_EN, hotplug_en);
-       }
+       hotplug_en = I915_READ(PORT_HOTPLUG_EN);
+       hotplug_en &= ~HOTPLUG_INT_EN_MASK;
+       /* Note HDMI and DP share hotplug bits */
+       /* enable bits are the same for all generations */
+       for_each_intel_encoder(dev, intel_encoder)
+               if (dev_priv->hpd_stats[intel_encoder->hpd_pin].hpd_mark == HPD_ENABLED)
+                       hotplug_en |= hpd_mask_i915[intel_encoder->hpd_pin];
+       /* Programming the CRT detection parameters tends
+          to generate a spurious hotplug event about three
+          seconds later.  So just do it once.
+       */
+       if (IS_G4X(dev))
+               hotplug_en |= CRT_HOTPLUG_ACTIVATION_PERIOD_64;
+       hotplug_en &= ~CRT_HOTPLUG_VOLTAGE_COMPARE_MASK;
+       hotplug_en |= CRT_HOTPLUG_VOLTAGE_COMPARE_50;
+
+       /* Ignore TV since it's buggy */
+       I915_WRITE(PORT_HOTPLUG_EN, hotplug_en);
 }
 
 static irqreturn_t i965_irq_handler(int irq, void *arg)
@@ -4428,14 +4426,14 @@ void intel_irq_init(struct drm_i915_private *dev_priv)
                        dev->driver->irq_postinstall = i915_irq_postinstall;
                        dev->driver->irq_uninstall = i915_irq_uninstall;
                        dev->driver->irq_handler = i915_irq_handler;
-                       dev_priv->display.hpd_irq_setup = i915_hpd_irq_setup;
                } else {
                        dev->driver->irq_preinstall = i965_irq_preinstall;
                        dev->driver->irq_postinstall = i965_irq_postinstall;
                        dev->driver->irq_uninstall = i965_irq_uninstall;
                        dev->driver->irq_handler = i965_irq_handler;
-                       dev_priv->display.hpd_irq_setup = i915_hpd_irq_setup;
                }
+               if (I915_HAS_HOTPLUG(dev_priv))
+                       dev_priv->display.hpd_irq_setup = i915_hpd_irq_setup;
                dev->driver->enable_vblank = i915_enable_vblank;
                dev->driver->disable_vblank = i915_disable_vblank;
        }
index 40ca873a05ad91657acb963ebbbb01df36e87009..a39bb0385bcbcfa5b086a3fd6c43c5a26c3f1870 100644 (file)
@@ -5202,6 +5202,9 @@ enum punit_power_well {
 #define COMMON_SLICE_CHICKEN2                  0x7014
 # define GEN8_CSC2_SBE_VUE_CACHE_CONSERVATIVE  (1<<0)
 
+#define HIZ_CHICKEN                            0x7018
+# define CHV_HZ_8X8_MODE_IN_1X                 (1<<15)
+
 #define GEN7_L3SQCREG1                         0xB010
 #define  VLV_B0_WA_L3SQCREG1_VALUE             0x00D30000
 
@@ -6167,6 +6170,7 @@ enum punit_power_well {
 #define  HSW_ROW_CHICKEN3_L3_GLOBAL_ATOMICS_DISABLE    (1 << 6)
 
 #define HALF_SLICE_CHICKEN3            0xe184
+#define   HSW_SAMPLE_C_PERFORMANCE     (1<<9)
 #define   GEN8_CENTROID_PIXEL_OPT_DIS  (1<<8)
 #define   GEN8_SAMPLER_POWER_BYPASS_DIS        (1<<1)
 
diff --git a/drivers/gpu/drm/i915/intel_atomic_plane.c b/drivers/gpu/drm/i915/intel_atomic_plane.c
new file mode 100644 (file)
index 0000000..5488efe
--- /dev/null
@@ -0,0 +1,152 @@
+/*
+ * Copyright Â© 2014 Intel Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ */
+
+/**
+ * DOC: atomic plane helpers
+ *
+ * The functions here are used by the atomic plane helper functions to
+ * implement legacy plane updates (i.e., drm_plane->update_plane() and
+ * drm_plane->disable_plane()).  This allows plane updates to use the
+ * atomic state infrastructure and perform plane updates as separate
+ * prepare/check/commit/cleanup steps.
+ */
+
+#include <drm/drmP.h>
+#include <drm/drm_atomic_helper.h>
+#include <drm/drm_plane_helper.h>
+#include "intel_drv.h"
+
+/**
+ * intel_plane_duplicate_state - duplicate plane state
+ * @plane: drm plane
+ *
+ * Allocates and returns a copy of the plane state (both common and
+ * Intel-specific) for the specified plane.
+ *
+ * Returns: The newly allocated plane state, or NULL or failure.
+ */
+struct drm_plane_state *
+intel_plane_duplicate_state(struct drm_plane *plane)
+{
+       struct intel_plane_state *state;
+
+       if (plane->state)
+               state = kmemdup(plane->state, sizeof(*state), GFP_KERNEL);
+       else
+               state = kzalloc(sizeof(*state), GFP_KERNEL);
+
+       if (!state)
+               return NULL;
+
+       if (state->base.fb)
+               drm_framebuffer_reference(state->base.fb);
+
+       return &state->base;
+}
+
+/**
+ * intel_plane_destroy_state - destroy plane state
+ * @plane: drm plane
+ * @state: state object to destroy
+ *
+ * Destroys the plane state (both common and Intel-specific) for the
+ * specified plane.
+ */
+void
+intel_plane_destroy_state(struct drm_plane *plane,
+                         struct drm_plane_state *state)
+{
+       drm_atomic_helper_plane_destroy_state(plane, state);
+}
+
+static int intel_plane_atomic_check(struct drm_plane *plane,
+                                   struct drm_plane_state *state)
+{
+       struct drm_crtc *crtc = state->crtc;
+       struct intel_crtc *intel_crtc;
+       struct intel_plane *intel_plane = to_intel_plane(plane);
+       struct intel_plane_state *intel_state = to_intel_plane_state(state);
+
+       crtc = crtc ? crtc : plane->crtc;
+       intel_crtc = to_intel_crtc(crtc);
+
+       /*
+        * The original src/dest coordinates are stored in state->base, but
+        * we want to keep another copy internal to our driver that we can
+        * clip/modify ourselves.
+        */
+       intel_state->src.x1 = state->src_x;
+       intel_state->src.y1 = state->src_y;
+       intel_state->src.x2 = state->src_x + state->src_w;
+       intel_state->src.y2 = state->src_y + state->src_h;
+       intel_state->dst.x1 = state->crtc_x;
+       intel_state->dst.y1 = state->crtc_y;
+       intel_state->dst.x2 = state->crtc_x + state->crtc_w;
+       intel_state->dst.y2 = state->crtc_y + state->crtc_h;
+
+       /* Clip all planes to CRTC size, or 0x0 if CRTC is disabled */
+       intel_state->clip.x1 = 0;
+       intel_state->clip.y1 = 0;
+       intel_state->clip.x2 =
+               intel_crtc->active ? intel_crtc->config.pipe_src_w : 0;
+       intel_state->clip.y2 =
+               intel_crtc->active ? intel_crtc->config.pipe_src_h : 0;
+
+       /*
+        * 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 (state->fb == NULL && plane->state->fb != NULL) {
+               /*
+                * 'prepare' is never called when plane is being disabled, so
+                * we need to handle frontbuffer tracking as a special case
+                */
+               intel_crtc->atomic.disabled_planes |=
+                       (1 << drm_plane_index(plane));
+       }
+
+       return intel_plane->check_plane(plane, intel_state);
+}
+
+static void intel_plane_atomic_update(struct drm_plane *plane,
+                                     struct drm_plane_state *old_state)
+{
+       struct intel_plane *intel_plane = to_intel_plane(plane);
+       struct intel_plane_state *intel_state =
+               to_intel_plane_state(plane->state);
+
+       /* Don't disable an already disabled plane */
+       if (!plane->state->fb && !old_state->fb)
+               return;
+
+       intel_plane->commit_plane(plane, intel_state);
+}
+
+const struct drm_plane_helper_funcs intel_plane_helper_funcs = {
+       .prepare_fb = intel_prepare_plane_fb,
+       .cleanup_fb = intel_cleanup_plane_fb,
+       .atomic_check = intel_plane_atomic_check,
+       .atomic_update = intel_plane_atomic_update,
+};
+
index 2c7ed5cb29c0f4aae70ee6599d1d0e59cb857fb5..ee41b882e71aa4126fc9c37fb56228a686b7ec08 100644 (file)
@@ -22,6 +22,9 @@
  */
 
 #include <linux/kernel.h>
+#include <linux/component.h>
+#include <drm/i915_component.h>
+#include "intel_drv.h"
 
 #include <drm/drmP.h>
 #include <drm/drm_edid.h>
@@ -461,3 +464,110 @@ void intel_init_audio(struct drm_device *dev)
                dev_priv->display.audio_codec_disable = ilk_audio_codec_disable;
        }
 }
+
+static void i915_audio_component_get_power(struct device *dev)
+{
+       intel_display_power_get(dev_to_i915(dev), POWER_DOMAIN_AUDIO);
+}
+
+static void i915_audio_component_put_power(struct device *dev)
+{
+       intel_display_power_put(dev_to_i915(dev), POWER_DOMAIN_AUDIO);
+}
+
+/* Get CDCLK in kHz  */
+static int i915_audio_component_get_cdclk_freq(struct device *dev)
+{
+       struct drm_i915_private *dev_priv = dev_to_i915(dev);
+       int ret;
+
+       if (WARN_ON_ONCE(!HAS_DDI(dev_priv)))
+               return -ENODEV;
+
+       intel_display_power_get(dev_priv, POWER_DOMAIN_AUDIO);
+       ret = intel_ddi_get_cdclk_freq(dev_priv);
+       intel_display_power_put(dev_priv, POWER_DOMAIN_AUDIO);
+
+       return ret;
+}
+
+static const struct i915_audio_component_ops i915_audio_component_ops = {
+       .owner          = THIS_MODULE,
+       .get_power      = i915_audio_component_get_power,
+       .put_power      = i915_audio_component_put_power,
+       .get_cdclk_freq = i915_audio_component_get_cdclk_freq,
+};
+
+static int i915_audio_component_bind(struct device *i915_dev,
+                                    struct device *hda_dev, void *data)
+{
+       struct i915_audio_component *acomp = data;
+
+       if (WARN_ON(acomp->ops || acomp->dev))
+               return -EEXIST;
+
+       acomp->ops = &i915_audio_component_ops;
+       acomp->dev = i915_dev;
+
+       return 0;
+}
+
+static void i915_audio_component_unbind(struct device *i915_dev,
+                                       struct device *hda_dev, void *data)
+{
+       struct i915_audio_component *acomp = data;
+
+       acomp->ops = NULL;
+       acomp->dev = NULL;
+}
+
+static const struct component_ops i915_audio_component_bind_ops = {
+       .bind   = i915_audio_component_bind,
+       .unbind = i915_audio_component_unbind,
+};
+
+/**
+ * i915_audio_component_init - initialize and register the audio component
+ * @dev_priv: i915 device instance
+ *
+ * This will register with the component framework a child component which
+ * will bind dynamically to the snd_hda_intel driver's corresponding master
+ * component when the latter is registered. During binding the child
+ * initializes an instance of struct i915_audio_component which it receives
+ * from the master. The master can then start to use the interface defined by
+ * this struct. Each side can break the binding at any point by deregistering
+ * its own component after which each side's component unbind callback is
+ * called.
+ *
+ * We ignore any error during registration and continue with reduced
+ * functionality (i.e. without HDMI audio).
+ */
+void i915_audio_component_init(struct drm_i915_private *dev_priv)
+{
+       int ret;
+
+       ret = component_add(dev_priv->dev->dev, &i915_audio_component_bind_ops);
+       if (ret < 0) {
+               DRM_ERROR("failed to add audio component (%d)\n", ret);
+               /* continue with reduced functionality */
+               return;
+       }
+
+       dev_priv->audio_component_registered = true;
+}
+
+/**
+ * i915_audio_component_cleanup - deregister the audio component
+ * @dev_priv: i915 device instance
+ *
+ * Deregisters the audio component, breaking any existing binding to the
+ * corresponding snd_hda_intel driver's master component.
+ */
+void i915_audio_component_cleanup(struct drm_i915_private *dev_priv)
+{
+       if (!dev_priv->audio_component_registered)
+               return;
+
+       component_del(dev_priv->dev->dev, &i915_audio_component_bind_ops);
+       dev_priv->audio_component_registered = false;
+}
index 65b1fbc5eb57a788ee19833a7582b40de18fab13..3f178258d9f9ce679044d2775b66359297d68623 100644 (file)
@@ -314,7 +314,6 @@ parse_lfp_backlight(struct drm_i915_private *dev_priv, struct bdb_header *bdb)
 {
        const struct bdb_lfp_backlight_data *backlight_data;
        const struct bdb_lfp_backlight_data_entry *entry;
-       const struct bdb_lfp_backlight_control_data *bl_ctrl_data;
 
        backlight_data = find_section(bdb, BDB_LVDS_BACKLIGHT);
        if (!backlight_data)
@@ -327,7 +326,6 @@ parse_lfp_backlight(struct drm_i915_private *dev_priv, struct bdb_header *bdb)
        }
 
        entry = &backlight_data->data[panel_type];
-       bl_ctrl_data = &backlight_data->blc_ctl[panel_type];
 
        dev_priv->vbt.backlight.present = entry->type == BDB_BACKLIGHT_TYPE_PWM;
        if (!dev_priv->vbt.backlight.present) {
@@ -339,30 +337,12 @@ parse_lfp_backlight(struct drm_i915_private *dev_priv, struct bdb_header *bdb)
        dev_priv->vbt.backlight.pwm_freq_hz = entry->pwm_freq_hz;
        dev_priv->vbt.backlight.active_low_pwm = entry->active_low_pwm;
        dev_priv->vbt.backlight.min_brightness = entry->min_brightness;
-
-       dev_priv->vbt.backlight.controller = 0;
-       if (bdb->version >= 191) {
-               dev_priv->vbt.backlight.present =
-                               bl_ctrl_data->pin == BLC_CONTROL_PIN_DDI;
-               if (!dev_priv->vbt.backlight.present) {
-                       DRM_DEBUG_KMS("BL control pin is not DDI (pin %u)\n",
-                                       bl_ctrl_data->pin);
-                       return;
-               }
-               if (bl_ctrl_data->controller == 1)
-                       dev_priv->vbt.backlight.controller =
-                               bl_ctrl_data->controller;
-       }
-
        DRM_DEBUG_KMS("VBT backlight PWM modulation frequency %u Hz, "
                      "active %s, min brightness %u, level %u\n",
                      dev_priv->vbt.backlight.pwm_freq_hz,
                      dev_priv->vbt.backlight.active_low_pwm ? "low" : "high",
                      dev_priv->vbt.backlight.min_brightness,
                      backlight_data->level[panel_type]);
-
-       DRM_DEBUG_KMS("VBT BL controller %u\n",
-               dev_priv->vbt.backlight.controller);
 }
 
 /* Try to find sdvo panel data */
index 9a7202e5caf45aedc30165224d1487e66b4e5975..a6a8710f665f5c8b37c28fd3b62ad7d0593a00b4 100644 (file)
@@ -402,21 +402,10 @@ struct bdb_lfp_backlight_data_entry {
        u8 obsolete3;
 } __packed;
 
-#define BLC_CONTROL_PIN_PMIC           0
-#define BLC_CONTROL_PIN_LPSS_PWM       1
-#define BLC_CONTROL_PIN_DDI            2
-#define BLC_CONTROL_PIN_CABC           3
-
-struct bdb_lfp_backlight_control_data {
-       u8 controller:4;
-       u8 pin:4;
-} __packed;
-
 struct bdb_lfp_backlight_data {
        u8 entry_size;
        struct bdb_lfp_backlight_data_entry data[16];
        u8 level[16];
-       struct bdb_lfp_backlight_control_data blc_ctl[16];
 } __packed;
 
 struct aimdb_header {
index dc266e772340f4c397d7b39a1522cc5fa171869b..91d8ada8fe6d2965f5d0875ddb94e6666b19e6a3 100644 (file)
@@ -98,6 +98,8 @@ static void vlv_prepare_pll(struct intel_crtc *crtc,
                            const struct intel_crtc_config *pipe_config);
 static void chv_prepare_pll(struct intel_crtc *crtc,
                            const struct intel_crtc_config *pipe_config);
+static void intel_begin_crtc_commit(struct drm_crtc *crtc);
+static void intel_finish_crtc_commit(struct drm_crtc *crtc);
 
 static struct intel_encoder *intel_find_encoder(struct intel_connector *connector, int pipe)
 {
@@ -2165,7 +2167,8 @@ static void intel_disable_primary_hw_plane(struct drm_plane *plane,
        struct drm_i915_private *dev_priv = dev->dev_private;
        struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
 
-       assert_pipe_enabled(dev_priv, intel_crtc->pipe);
+       if (WARN_ON(!intel_crtc->active))
+               return;
 
        if (!intel_crtc->primary_enabled)
                return;
@@ -4036,7 +4039,7 @@ static void ironlake_pfit_enable(struct intel_crtc *crtc)
        }
 }
 
-static void intel_enable_planes(struct drm_crtc *crtc)
+static void intel_enable_sprite_planes(struct drm_crtc *crtc)
 {
        struct drm_device *dev = crtc->dev;
        enum pipe pipe = to_intel_crtc(crtc)->pipe;
@@ -4050,7 +4053,7 @@ static void intel_enable_planes(struct drm_crtc *crtc)
        }
 }
 
-static void intel_disable_planes(struct drm_crtc *crtc)
+static void intel_disable_sprite_planes(struct drm_crtc *crtc)
 {
        struct drm_device *dev = crtc->dev;
        enum pipe pipe = to_intel_crtc(crtc)->pipe;
@@ -4194,7 +4197,7 @@ static void intel_crtc_enable_planes(struct drm_crtc *crtc)
        int pipe = intel_crtc->pipe;
 
        intel_enable_primary_hw_plane(crtc->primary, crtc);
-       intel_enable_planes(crtc);
+       intel_enable_sprite_planes(crtc);
        intel_crtc_update_cursor(crtc, true);
        intel_crtc_dpms_overlay(intel_crtc, true);
 
@@ -4229,7 +4232,7 @@ static void intel_crtc_disable_planes(struct drm_crtc *crtc)
 
        intel_crtc_dpms_overlay(intel_crtc, false);
        intel_crtc_update_cursor(crtc, false);
-       intel_disable_planes(crtc);
+       intel_disable_sprite_planes(crtc);
        intel_disable_primary_hw_plane(crtc->primary, crtc);
 
        /*
@@ -4301,15 +4304,15 @@ static void ironlake_crtc_enable(struct drm_crtc *crtc)
        if (intel_crtc->config.has_pch_encoder)
                ironlake_pch_enable(crtc);
 
+       assert_vblank_disabled(crtc);
+       drm_crtc_vblank_on(crtc);
+
        for_each_encoder_on_crtc(dev, crtc, encoder)
                encoder->enable(encoder);
 
        if (HAS_PCH_CPT(dev))
                cpt_verify_modeset(dev, intel_crtc->pipe);
 
-       assert_vblank_disabled(crtc);
-       drm_crtc_vblank_on(crtc);
-
        intel_crtc_enable_planes(crtc);
 }
 
@@ -4421,14 +4424,14 @@ static void haswell_crtc_enable(struct drm_crtc *crtc)
        if (intel_crtc->config.dp_encoder_is_mst)
                intel_ddi_set_vc_payload_alloc(crtc, true);
 
+       assert_vblank_disabled(crtc);
+       drm_crtc_vblank_on(crtc);
+
        for_each_encoder_on_crtc(dev, crtc, encoder) {
                encoder->enable(encoder);
                intel_opregion_notify_encoder(encoder, true);
        }
 
-       assert_vblank_disabled(crtc);
-       drm_crtc_vblank_on(crtc);
-
        /* If we change the relative order between pipe/planes enabling, we need
         * to change the workaround. */
        haswell_mode_set_planes_workaround(intel_crtc);
@@ -4479,12 +4482,12 @@ static void ironlake_crtc_disable(struct drm_crtc *crtc)
 
        intel_crtc_disable_planes(crtc);
 
-       drm_crtc_vblank_off(crtc);
-       assert_vblank_disabled(crtc);
-
        for_each_encoder_on_crtc(dev, crtc, encoder)
                encoder->disable(encoder);
 
+       drm_crtc_vblank_off(crtc);
+       assert_vblank_disabled(crtc);
+
        if (intel_crtc->config.has_pch_encoder)
                intel_set_pch_fifo_underrun_reporting(dev_priv, pipe, false);
 
@@ -4543,14 +4546,14 @@ static void haswell_crtc_disable(struct drm_crtc *crtc)
 
        intel_crtc_disable_planes(crtc);
 
-       drm_crtc_vblank_off(crtc);
-       assert_vblank_disabled(crtc);
-
        for_each_encoder_on_crtc(dev, crtc, encoder) {
                intel_opregion_notify_encoder(encoder, false);
                encoder->disable(encoder);
        }
 
+       drm_crtc_vblank_off(crtc);
+       assert_vblank_disabled(crtc);
+
        if (intel_crtc->config.has_pch_encoder)
                intel_set_pch_fifo_underrun_reporting(dev_priv, TRANSCODER_A,
                                                      false);
@@ -5018,12 +5021,12 @@ static void valleyview_crtc_enable(struct drm_crtc *crtc)
        intel_update_watermarks(crtc);
        intel_enable_pipe(intel_crtc);
 
-       for_each_encoder_on_crtc(dev, crtc, encoder)
-               encoder->enable(encoder);
-
        assert_vblank_disabled(crtc);
        drm_crtc_vblank_on(crtc);
 
+       for_each_encoder_on_crtc(dev, crtc, encoder)
+               encoder->enable(encoder);
+
        intel_crtc_enable_planes(crtc);
 
        /* Underruns don't raise interrupts, so check manually. */
@@ -5079,12 +5082,12 @@ static void i9xx_crtc_enable(struct drm_crtc *crtc)
        intel_update_watermarks(crtc);
        intel_enable_pipe(intel_crtc);
 
-       for_each_encoder_on_crtc(dev, crtc, encoder)
-               encoder->enable(encoder);
-
        assert_vblank_disabled(crtc);
        drm_crtc_vblank_on(crtc);
 
+       for_each_encoder_on_crtc(dev, crtc, encoder)
+               encoder->enable(encoder);
+
        intel_crtc_enable_planes(crtc);
 
        /*
@@ -5156,12 +5159,12 @@ static void i9xx_crtc_disable(struct drm_crtc *crtc)
         */
        intel_wait_for_vblank(dev, pipe);
 
-       drm_crtc_vblank_off(crtc);
-       assert_vblank_disabled(crtc);
-
        for_each_encoder_on_crtc(dev, crtc, encoder)
                encoder->disable(encoder);
 
+       drm_crtc_vblank_off(crtc);
+       assert_vblank_disabled(crtc);
+
        intel_disable_pipe(intel_crtc);
 
        i9xx_pfit_disable(intel_crtc);
@@ -9613,7 +9616,6 @@ static int intel_crtc_page_flip(struct drm_crtc *crtc,
        struct drm_i915_gem_object *obj = intel_fb_obj(fb);
        struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
        struct drm_plane *primary = crtc->primary;
-       struct intel_plane *intel_plane = to_intel_plane(primary);
        enum pipe pipe = intel_crtc->pipe;
        struct intel_unpin_work *work;
        struct intel_engine_cs *ring;
@@ -9772,15 +9774,7 @@ free_work:
 
        if (ret == -EIO) {
 out_hang:
-               ret = primary->funcs->update_plane(primary, crtc, fb,
-                                                  intel_plane->crtc_x,
-                                                  intel_plane->crtc_y,
-                                                  intel_plane->crtc_h,
-                                                  intel_plane->crtc_w,
-                                                  intel_plane->src_x,
-                                                  intel_plane->src_y,
-                                                  intel_plane->src_h,
-                                                  intel_plane->src_w);
+               ret = intel_plane_restore(primary);
                if (ret == 0 && event) {
                        spin_lock_irq(&dev->event_lock);
                        drm_send_vblank_event(dev, pipe, event);
@@ -9793,6 +9787,8 @@ out_hang:
 static 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,
 };
 
 /**
@@ -11673,7 +11669,7 @@ intel_prepare_plane_fb(struct drm_plane *plane,
        unsigned frontbuffer_bits = 0;
        int ret = 0;
 
-       if (WARN_ON(fb == plane->fb || !obj))
+       if (!obj)
                return 0;
 
        switch (plane->type) {
@@ -11737,13 +11733,20 @@ static int
 intel_check_primary_plane(struct drm_plane *plane,
                          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_plane *intel_plane = to_intel_plane(plane);
        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;
        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,
                                            DRM_PLANE_HELPER_NO_SCALING,
@@ -11752,10 +11755,40 @@ intel_check_primary_plane(struct drm_plane *plane,
        if (ret)
                return ret;
 
-       intel_crtc_wait_for_pending_flips(crtc);
-       if (intel_crtc_has_pending_flip(crtc)) {
-               DRM_ERROR("pipe is still busy with an old pageflip\n");
-               return -EBUSY;
+       if (intel_crtc->active) {
+               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 (intel_crtc->primary_enabled &&
+                   INTEL_INFO(dev)->gen <= 4 && !IS_G4X(dev) &&
+                   dev_priv->fbc.plane == intel_crtc->plane &&
+                   intel_plane->rotation != BIT(DRM_ROTATE_0)) {
+                       intel_crtc->atomic.disable_fbc = true;
+               }
+
+               if (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->primary_enabled)
+                               intel_crtc->atomic.wait_vblank = true;
+               }
+
+               intel_crtc->atomic.fb_bits |=
+                       INTEL_FRONTBUFFER_PRIMARY(intel_crtc->pipe);
+
+               intel_crtc->atomic.update_fbc = true;
        }
 
        return 0;
@@ -11769,58 +11802,22 @@ intel_commit_primary_plane(struct drm_plane *plane,
        struct drm_framebuffer *fb = state->base.fb;
        struct drm_device *dev = plane->dev;
        struct drm_i915_private *dev_priv = dev->dev_private;
-       struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
+       struct intel_crtc *intel_crtc;
        struct drm_i915_gem_object *obj = intel_fb_obj(fb);
        struct intel_plane *intel_plane = to_intel_plane(plane);
        struct drm_rect *src = &state->src;
-       enum pipe pipe = intel_plane->pipe;
 
-       if (!fb) {
-               /*
-                * 'prepare' is never called when plane is being disabled, so
-                * we need to handle frontbuffer tracking here
-                */
-               mutex_lock(&dev->struct_mutex);
-               i915_gem_track_fb(intel_fb_obj(plane->fb), NULL,
-                                 INTEL_FRONTBUFFER_PRIMARY(pipe));
-               mutex_unlock(&dev->struct_mutex);
-       }
+       crtc = crtc ? crtc : plane->crtc;
+       intel_crtc = to_intel_crtc(crtc);
 
        plane->fb = fb;
        crtc->x = src->x1 >> 16;
        crtc->y = src->y1 >> 16;
 
-       intel_plane->crtc_x = state->orig_dst.x1;
-       intel_plane->crtc_y = state->orig_dst.y1;
-       intel_plane->crtc_w = drm_rect_width(&state->orig_dst);
-       intel_plane->crtc_h = drm_rect_height(&state->orig_dst);
-       intel_plane->src_x = state->orig_src.x1;
-       intel_plane->src_y = state->orig_src.y1;
-       intel_plane->src_w = drm_rect_width(&state->orig_src);
-       intel_plane->src_h = drm_rect_height(&state->orig_src);
        intel_plane->obj = obj;
 
        if (intel_crtc->active) {
-               /*
-                * FBC does not work on some platforms for rotated
-                * planes, so disable it when rotation is not 0 and
-                * update it when rotation is set back to 0.
-                *
-                * FIXME: This is redundant with the fbc update done in
-                * the primary plane enable function except that that
-                * one is done too late. We eventually need to unify
-                * this.
-                */
-               if (intel_crtc->primary_enabled &&
-                   INTEL_INFO(dev)->gen <= 4 && !IS_G4X(dev) &&
-                   dev_priv->fbc.plane == intel_crtc->plane &&
-                   intel_plane->rotation != BIT(DRM_ROTATE_0)) {
-                       intel_fbc_disable(dev);
-               }
-
                if (state->visible) {
-                       bool was_enabled = intel_crtc->primary_enabled;
-
                        /* FIXME: kill this fastboot hack */
                        intel_update_pipe_size(intel_crtc);
 
@@ -11828,14 +11825,6 @@ intel_commit_primary_plane(struct drm_plane *plane,
 
                        dev_priv->display.update_primary_plane(crtc, plane->fb,
                                        crtc->x, crtc->y);
-
-                       /*
-                        * 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) && !was_enabled)
-                               intel_wait_for_vblank(dev, intel_crtc->pipe);
                } else {
                        /*
                         * If clipping results in a non-visible primary plane,
@@ -11846,110 +11835,121 @@ intel_commit_primary_plane(struct drm_plane *plane,
                         */
                        intel_disable_primary_hw_plane(plane, crtc);
                }
-
-               intel_frontbuffer_flip(dev, INTEL_FRONTBUFFER_PRIMARY(pipe));
-
-               mutex_lock(&dev->struct_mutex);
-               intel_fbc_update(dev);
-               mutex_unlock(&dev->struct_mutex);
        }
 }
 
-int
-intel_update_plane(struct drm_plane *plane, struct drm_crtc *crtc,
-                  struct drm_framebuffer *fb, int crtc_x, int crtc_y,
-                  unsigned int crtc_w, unsigned int crtc_h,
-                  uint32_t src_x, uint32_t src_y,
-                  uint32_t src_w, uint32_t src_h)
+static void intel_begin_crtc_commit(struct drm_crtc *crtc)
 {
-       struct drm_device *dev = plane->dev;
+       struct drm_device *dev = crtc->dev;
        struct drm_i915_private *dev_priv = dev->dev_private;
-       struct drm_framebuffer *old_fb = plane->fb;
-       struct intel_plane_state state;
-       struct intel_plane *intel_plane = to_intel_plane(plane);
        struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
-       int ret;
+       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;
+                       }
 
-       state.base.crtc = crtc ? crtc : plane->crtc;
-       state.base.fb = fb;
+                       mutex_lock(&dev->struct_mutex);
+                       i915_gem_track_fb(intel_fb_obj(p->fb), NULL, fb_bits);
+                       mutex_unlock(&dev->struct_mutex);
+               }
+       }
 
-       /* sample coordinates in 16.16 fixed point */
-       state.src.x1 = src_x;
-       state.src.x2 = src_x + src_w;
-       state.src.y1 = src_y;
-       state.src.y2 = src_y + src_h;
+       if (intel_crtc->atomic.wait_for_flips)
+               intel_crtc_wait_for_pending_flips(crtc);
 
-       /* integer pixels */
-       state.dst.x1 = crtc_x;
-       state.dst.x2 = crtc_x + crtc_w;
-       state.dst.y1 = crtc_y;
-       state.dst.y2 = crtc_y + crtc_h;
+       if (intel_crtc->atomic.disable_fbc)
+               intel_fbc_disable(dev);
 
-       state.clip.x1 = 0;
-       state.clip.y1 = 0;
-       state.clip.x2 = intel_crtc->active ? intel_crtc->config.pipe_src_w : 0;
-       state.clip.y2 = intel_crtc->active ? intel_crtc->config.pipe_src_h : 0;
+       if (intel_crtc->atomic.pre_disable_primary)
+               intel_pre_disable_primary(crtc);
 
-       state.orig_src = state.src;
-       state.orig_dst = state.dst;
+       if (intel_crtc->atomic.update_wm)
+               intel_update_watermarks(crtc);
 
-       ret = intel_plane->check_plane(plane, &state);
-       if (ret)
-               return ret;
+       intel_runtime_pm_get(dev_priv);
 
-       if (fb != old_fb && fb) {
-               ret = intel_prepare_plane_fb(plane, fb);
-               if (ret)
-                       return ret;
-       }
+       /* 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);
+}
+
+static void intel_finish_crtc_commit(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_plane *p;
+
+       if (intel_crtc->atomic.evade)
+               intel_pipe_update_end(intel_crtc,
+                                     intel_crtc->atomic.start_vbl_count);
 
-       intel_runtime_pm_get(dev_priv);
-       intel_plane->commit_plane(plane, &state);
        intel_runtime_pm_put(dev_priv);
 
-       if (fb != old_fb && old_fb) {
-               if (intel_crtc->active)
-                       intel_wait_for_vblank(dev, intel_crtc->pipe);
-               intel_cleanup_plane_fb(plane, old_fb);
+       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);
        }
 
-       plane->fb = fb;
+       if (intel_crtc->atomic.post_enable_primary)
+               intel_post_enable_primary(crtc);
 
-       return 0;
+       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));
 }
 
 /**
- * intel_disable_plane - disable a plane
- * @plane: plane to disable
+ * intel_plane_destroy - destroy a plane
+ * @plane: plane to destroy
  *
- * General disable handler for all plane types.
+ * Common destruction function for all types of planes (primary, cursor,
+ * sprite).
  */
-int
-intel_disable_plane(struct drm_plane *plane)
-{
-       if (!plane->fb)
-               return 0;
-
-       if (WARN_ON(!plane->crtc))
-               return -EINVAL;
-
-       return plane->funcs->update_plane(plane, plane->crtc, NULL,
-                                         0, 0, 0, 0, 0, 0, 0, 0);
-}
-
-/* Common destruction function for both primary and cursor planes */
-static void intel_plane_destroy(struct drm_plane *plane)
+void intel_plane_destroy(struct drm_plane *plane)
 {
        struct intel_plane *intel_plane = to_intel_plane(plane);
+       intel_plane_destroy_state(plane, plane->state);
        drm_plane_cleanup(plane);
        kfree(intel_plane);
 }
 
 static const struct drm_plane_funcs intel_primary_plane_funcs = {
-       .update_plane = intel_update_plane,
-       .disable_plane = intel_disable_plane,
+       .update_plane = drm_plane_helper_update,
+       .disable_plane = drm_plane_helper_disable,
        .destroy = intel_plane_destroy,
-       .set_property = intel_plane_set_property
+       .set_property = intel_plane_set_property,
+       .atomic_duplicate_state = intel_plane_duplicate_state,
+       .atomic_destroy_state = intel_plane_destroy_state,
+
 };
 
 static struct drm_plane *intel_primary_plane_create(struct drm_device *dev,
@@ -11963,6 +11963,12 @@ static struct drm_plane *intel_primary_plane_create(struct drm_device *dev,
        if (primary == NULL)
                return NULL;
 
+       primary->base.state = intel_plane_duplicate_state(&primary->base);
+       if (primary->base.state == NULL) {
+               kfree(primary);
+               return NULL;
+       }
+
        primary->can_scale = false;
        primary->max_downscale = 1;
        primary->pipe = pipe;
@@ -11998,6 +12004,8 @@ static struct drm_plane *intel_primary_plane_create(struct drm_device *dev,
                                primary->rotation);
        }
 
+       drm_plane_helper_add(&primary->base, &intel_plane_helper_funcs);
+
        return &primary->base;
 }
 
@@ -12006,16 +12014,19 @@ intel_check_cursor_plane(struct drm_plane *plane,
                         struct intel_plane_state *state)
 {
        struct drm_crtc *crtc = state->base.crtc;
-       struct drm_device *dev = crtc->dev;
+       struct drm_device *dev = plane->dev;
        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);
-       int crtc_w, crtc_h;
+       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,
                                            DRM_PLANE_HELPER_NO_SCALING,
@@ -12027,18 +12038,17 @@ intel_check_cursor_plane(struct drm_plane *plane,
 
        /* if we want to turn off the cursor ignore width and height */
        if (!obj)
-               return 0;
+               goto finish;
 
        /* Check for which cursor types we support */
-       crtc_w = drm_rect_width(&state->orig_dst);
-       crtc_h = drm_rect_height(&state->orig_dst);
-       if (!cursor_size_ok(dev, crtc_w, crtc_h)) {
-               DRM_DEBUG("Cursor dimension not supported\n");
+       if (!cursor_size_ok(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;
        }
 
-       stride = roundup_pow_of_two(crtc_w) * 4;
-       if (obj->base.size < stride * crtc_h) {
+       stride = roundup_pow_of_two(state->base.crtc_w) * 4;
+       if (obj->base.size < stride * state->base.crtc_h) {
                DRM_DEBUG_KMS("buffer is too small\n");
                return -ENOMEM;
        }
@@ -12054,6 +12064,15 @@ intel_check_cursor_plane(struct drm_plane *plane,
        }
        mutex_unlock(&dev->struct_mutex);
 
+finish:
+       if (intel_crtc->active) {
+               if (intel_crtc->cursor_width != state->base.crtc_w)
+                       intel_crtc->atomic.update_wm = true;
+
+               intel_crtc->atomic.fb_bits |=
+                       INTEL_FRONTBUFFER_CURSOR(intel_crtc->pipe);
+       }
+
        return ret;
 }
 
@@ -12062,43 +12081,24 @@ intel_commit_cursor_plane(struct drm_plane *plane,
                          struct intel_plane_state *state)
 {
        struct drm_crtc *crtc = state->base.crtc;
-       struct drm_device *dev = crtc->dev;
-       struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
+       struct drm_device *dev = plane->dev;
+       struct intel_crtc *intel_crtc;
        struct intel_plane *intel_plane = to_intel_plane(plane);
        struct drm_i915_gem_object *obj = intel_fb_obj(state->base.fb);
-       struct drm_i915_gem_object *old_obj = intel_fb_obj(plane->fb);
-       enum pipe pipe = intel_crtc->pipe;
-       unsigned old_width;
        uint32_t addr;
 
+       crtc = crtc ? crtc : plane->crtc;
+       intel_crtc = to_intel_crtc(crtc);
+
        plane->fb = state->base.fb;
-       crtc->cursor_x = state->orig_dst.x1;
-       crtc->cursor_y = state->orig_dst.y1;
-
-       intel_plane->crtc_x = state->orig_dst.x1;
-       intel_plane->crtc_y = state->orig_dst.y1;
-       intel_plane->crtc_w = drm_rect_width(&state->orig_dst);
-       intel_plane->crtc_h = drm_rect_height(&state->orig_dst);
-       intel_plane->src_x = state->orig_src.x1;
-       intel_plane->src_y = state->orig_src.y1;
-       intel_plane->src_w = drm_rect_width(&state->orig_src);
-       intel_plane->src_h = drm_rect_height(&state->orig_src);
+       crtc->cursor_x = state->base.crtc_x;
+       crtc->cursor_y = state->base.crtc_y;
+
        intel_plane->obj = obj;
 
        if (intel_crtc->cursor_bo == obj)
                goto update;
 
-       /*
-        * 'prepare' is only called when fb != NULL; we still need to update
-        * frontbuffer tracking for the 'disable' case here.
-        */
-       if (!obj) {
-               mutex_lock(&dev->struct_mutex);
-               i915_gem_track_fb(old_obj, NULL,
-                                 INTEL_FRONTBUFFER_CURSOR(pipe));
-               mutex_unlock(&dev->struct_mutex);
-       }
-
        if (!obj)
                addr = 0;
        else if (!INTEL_INFO(dev)->cursor_needs_physical)
@@ -12109,25 +12109,20 @@ intel_commit_cursor_plane(struct drm_plane *plane,
        intel_crtc->cursor_addr = addr;
        intel_crtc->cursor_bo = obj;
 update:
-       old_width = intel_crtc->cursor_width;
+       intel_crtc->cursor_width = state->base.crtc_w;
+       intel_crtc->cursor_height = state->base.crtc_h;
 
-       intel_crtc->cursor_width = drm_rect_width(&state->orig_dst);
-       intel_crtc->cursor_height = drm_rect_height(&state->orig_dst);
-
-       if (intel_crtc->active) {
-               if (old_width != intel_crtc->cursor_width)
-                       intel_update_watermarks(crtc);
+       if (intel_crtc->active)
                intel_crtc_update_cursor(crtc, state->visible);
-
-               intel_frontbuffer_flip(dev, INTEL_FRONTBUFFER_CURSOR(pipe));
-       }
 }
 
 static const struct drm_plane_funcs intel_cursor_plane_funcs = {
-       .update_plane = intel_update_plane,
-       .disable_plane = intel_disable_plane,
+       .update_plane = drm_plane_helper_update,
+       .disable_plane = drm_plane_helper_disable,
        .destroy = intel_plane_destroy,
        .set_property = intel_plane_set_property,
+       .atomic_duplicate_state = intel_plane_duplicate_state,
+       .atomic_destroy_state = intel_plane_destroy_state,
 };
 
 static struct drm_plane *intel_cursor_plane_create(struct drm_device *dev,
@@ -12139,6 +12134,12 @@ static struct drm_plane *intel_cursor_plane_create(struct drm_device *dev,
        if (cursor == NULL)
                return NULL;
 
+       cursor->base.state = intel_plane_duplicate_state(&cursor->base);
+       if (cursor->base.state == NULL) {
+               kfree(cursor);
+               return NULL;
+       }
+
        cursor->can_scale = false;
        cursor->max_downscale = 1;
        cursor->pipe = pipe;
@@ -12165,6 +12166,8 @@ static struct drm_plane *intel_cursor_plane_create(struct drm_device *dev,
                                cursor->rotation);
        }
 
+       drm_plane_helper_add(&cursor->base, &intel_plane_helper_funcs);
+
        return &cursor->base;
 }
 
@@ -12390,14 +12393,16 @@ static void intel_setup_outputs(struct drm_device *dev)
                 * eDP ports. Consult the VBT as well as DP_DETECTED to
                 * detect eDP ports.
                 */
-               if (I915_READ(VLV_DISPLAY_BASE + GEN4_HDMIB) & SDVO_DETECTED)
+               if (I915_READ(VLV_DISPLAY_BASE + GEN4_HDMIB) & SDVO_DETECTED &&
+                   !intel_dp_is_edp(dev, PORT_B))
                        intel_hdmi_init(dev, VLV_DISPLAY_BASE + GEN4_HDMIB,
                                        PORT_B);
                if (I915_READ(VLV_DISPLAY_BASE + DP_B) & DP_DETECTED ||
                    intel_dp_is_edp(dev, PORT_B))
                        intel_dp_init(dev, VLV_DISPLAY_BASE + DP_B, PORT_B);
 
-               if (I915_READ(VLV_DISPLAY_BASE + GEN4_HDMIC) & SDVO_DETECTED)
+               if (I915_READ(VLV_DISPLAY_BASE + GEN4_HDMIC) & SDVO_DETECTED &&
+                   !intel_dp_is_edp(dev, PORT_C))
                        intel_hdmi_init(dev, VLV_DISPLAY_BASE + GEN4_HDMIC,
                                        PORT_C);
                if (I915_READ(VLV_DISPLAY_BASE + DP_C) & DP_DETECTED ||
index 88d81a8b0d3580c089bcd645e26f2da55a43abb0..df7b558f322285582012e8584fc2a7ed5358a9f7 100644 (file)
@@ -3773,7 +3773,7 @@ go_again:
                                intel_dp_stop_link_train(intel_dp);
                        }
 
-                       DRM_DEBUG_KMS("got esi %02x %02x %02x\n", esi[0], esi[1], esi[2]);
+                       DRM_DEBUG_KMS("got esi %3ph\n", esi);
                        ret = drm_dp_mst_hpd_irq(&intel_dp->mst_mgr, esi, &handled);
 
                        if (handled) {
@@ -3789,7 +3789,7 @@ go_again:
 
                                bret = intel_dp_get_sink_irq_esi(intel_dp, esi);
                                if (bret == true) {
-                                       DRM_DEBUG_KMS("got esi2 %02x %02x %02x\n", esi[0], esi[1], esi[2]);
+                                       DRM_DEBUG_KMS("got esi2 %3ph\n", esi);
                                        goto go_again;
                                }
                        } else
index bb871f3cfe2e0de18107fc4d55257b1e02326521..30e968f8c55ee51d6d083dc31383ce9ba01238b4 100644 (file)
@@ -248,9 +248,13 @@ struct intel_plane_state {
        struct drm_rect src;
        struct drm_rect dst;
        struct drm_rect clip;
-       struct drm_rect orig_src;
-       struct drm_rect orig_dst;
        bool visible;
+
+       /*
+        * used only for sprite planes to determine when to implicitly
+        * enable/disable the primary plane
+        */
+       bool hides_primary;
 };
 
 struct intel_plane_config {
@@ -415,6 +419,32 @@ struct skl_pipe_wm {
        uint32_t linetime;
 };
 
+/*
+ * Tracking of operations that need to be performed at the beginning/end of an
+ * atomic commit, outside the atomic section where interrupts are disabled.
+ * These are generally operations that grab mutexes or might otherwise sleep
+ * and thus can't be run with interrupts disabled.
+ */
+struct intel_crtc_atomic_commit {
+       /* vblank evasion */
+       bool evade;
+       unsigned start_vbl_count;
+
+       /* Sleepable operations to perform before commit */
+       bool wait_for_flips;
+       bool disable_fbc;
+       bool pre_disable_primary;
+       bool update_wm;
+       unsigned disabled_planes;
+
+       /* Sleepable operations to perform after commit */
+       unsigned fb_bits;
+       bool wait_vblank;
+       bool update_fbc;
+       bool post_enable_primary;
+       unsigned update_sprite_watermarks;
+};
+
 struct intel_crtc {
        struct drm_crtc base;
        enum pipe pipe;
@@ -468,6 +498,8 @@ struct intel_crtc {
 
        int scanline_offset;
        struct intel_mmio_flip mmio_flip;
+
+       struct intel_crtc_atomic_commit atomic;
 };
 
 struct intel_plane_wm_parameters {
@@ -485,10 +517,6 @@ struct intel_plane {
        struct drm_i915_gem_object *obj;
        bool can_scale;
        int max_downscale;
-       int crtc_x, crtc_y;
-       unsigned int crtc_w, crtc_h;
-       uint32_t src_x, src_y;
-       uint32_t src_w, src_h;
        unsigned int rotation;
 
        /* Since we need to change the watermarks before/after
@@ -542,6 +570,7 @@ struct cxsr_latency {
 #define to_intel_encoder(x) container_of(x, struct intel_encoder, base)
 #define to_intel_framebuffer(x) container_of(x, struct intel_framebuffer, base)
 #define to_intel_plane(x) container_of(x, struct intel_plane, base)
+#define to_intel_plane_state(x) container_of(x, struct intel_plane_state, base)
 #define intel_fb_obj(x) (x ? to_intel_framebuffer(x)->obj : NULL)
 
 struct intel_hdmi {
@@ -874,6 +903,8 @@ void intel_fb_obj_flush(struct drm_i915_gem_object *obj, bool retire);
 void intel_init_audio(struct drm_device *dev);
 void intel_audio_codec_enable(struct intel_encoder *encoder);
 void intel_audio_codec_disable(struct intel_encoder *encoder);
+void i915_audio_component_init(struct drm_i915_private *dev_priv);
+void i915_audio_component_cleanup(struct drm_i915_private *dev_priv);
 
 /* intel_display.c */
 bool intel_has_pending_fb_unpin(struct drm_device *dev);
@@ -1021,6 +1052,7 @@ int intel_update_plane(struct drm_plane *plane, struct drm_crtc *crtc,
                       uint32_t src_x, uint32_t src_y,
                       uint32_t src_w, uint32_t src_h);
 int intel_disable_plane(struct drm_plane *plane);
+void intel_plane_destroy(struct drm_plane *plane);
 
 /* intel_dp_mst.c */
 int intel_dp_mst_encoder_init(struct intel_digital_port *intel_dig_port, int conn_id);
@@ -1214,8 +1246,16 @@ int intel_sprite_get_colorkey(struct drm_device *dev, void *data,
 bool intel_pipe_update_start(struct intel_crtc *crtc,
                             uint32_t *start_vbl_count);
 void intel_pipe_update_end(struct intel_crtc *crtc, u32 start_vbl_count);
+void intel_post_enable_primary(struct drm_crtc *crtc);
+void intel_pre_disable_primary(struct drm_crtc *crtc);
 
 /* intel_tv.c */
 void intel_tv_init(struct drm_device *dev);
 
+/* intel_atomic.c */
+struct drm_plane_state *intel_plane_duplicate_state(struct drm_plane *plane);
+void intel_plane_destroy_state(struct drm_plane *plane,
+                              struct drm_plane_state *state);
+extern const struct drm_plane_helper_funcs intel_plane_helper_funcs;
+
 #endif /* __INTEL_DRV_H__ */
index 7670a0f0f62043b70dd530541ba79e67f88cde3b..e405b61cdac559cc8fd482291d0b765402b685e5 100644 (file)
@@ -1137,6 +1137,7 @@ static int gen8_init_common_ring(struct intel_engine_cs *ring)
                   _MASKED_BIT_DISABLE(GFX_REPLAY_MODE) |
                   _MASKED_BIT_ENABLE(GFX_RUN_LIST_ENABLE));
        POSTING_READ(RING_MODE_GEN7(ring));
+       ring->next_context_status_buffer = 0;
        DRM_DEBUG_DRIVER("Execlists enabled for %s\n", ring->name);
 
        memset(&ring->hangcheck, 0, sizeof(ring->hangcheck));
@@ -1394,7 +1395,6 @@ static int logical_ring_init(struct drm_device *dev, struct intel_engine_cs *rin
        INIT_LIST_HEAD(&ring->execlist_queue);
        INIT_LIST_HEAD(&ring->execlist_retired_req_list);
        spin_lock_init(&ring->execlist_lock);
-       ring->next_context_status_buffer = 0;
 
        ret = i915_cmd_parser_init_ring(ring);
        if (ret)
index 7d99a9c4e49b0ecd40d37808fdcbee3ec7763087..03fc7f2ee9d130d21a4fba47d79e5ce8bb62d65a 100644 (file)
@@ -4681,8 +4681,7 @@ static void cherryview_enable_rps(struct drm_device *dev)
                I915_WRITE(RING_MAX_IDLE(ring->mmio_base), 10);
        I915_WRITE(GEN6_RC_SLEEP, 0);
 
-       /* TO threshold set to 1750 us ( 0x557 * 1.28 us) */
-       I915_WRITE(GEN6_RC6_THRESHOLD, 0x557);
+       I915_WRITE(GEN6_RC6_THRESHOLD, 50000); /* 50/125ms per EI */
 
        /* allows RC6 residency counter to work */
        I915_WRITE(VLV_COUNTER_CONTROL,
@@ -4696,7 +4695,7 @@ static void cherryview_enable_rps(struct drm_device *dev)
        /* 3: Enable RC6 */
        if ((intel_enable_rc6(dev) & INTEL_RC6_ENABLE) &&
                                                (pcbr >> VLV_PCBR_ADDR_SHIFT))
-               rc6_mode = GEN7_RC_CTL_TO_MODE;
+               rc6_mode = GEN6_RC_CTL_EI_MODE(1);
 
        I915_WRITE(GEN6_RC_CONTROL, rc6_mode);
 
@@ -5974,6 +5973,10 @@ static void haswell_init_clock_gating(struct drm_device *dev)
        I915_WRITE(GEN7_GT_MODE,
                   _MASKED_FIELD(GEN6_WIZ_HASHING_MASK, GEN6_WIZ_HASHING_16x4));
 
+       /* WaSampleCChickenBitEnable:hsw */
+       I915_WRITE(HALF_SLICE_CHICKEN3,
+                  _MASKED_BIT_ENABLE(HSW_SAMPLE_C_PERFORMANCE));
+
        /* WaSwitchSolVfFArbitrationPriority:hsw */
        I915_WRITE(GAM_ECOCHK, I915_READ(GAM_ECOCHK) | HSW_ECOCHK_ARB_PRIO_SOL);
 
index dd0e6e0447d4933064fa7f16acd48dc49ccac30e..5ae193ec464a59d69510b6bf12f2f7af487ba6ed 100644 (file)
@@ -143,7 +143,6 @@ static void hsw_psr_enable_sink(struct intel_dp *intel_dp)
        struct drm_i915_private *dev_priv = dev->dev_private;
        uint32_t aux_clock_divider;
        int precharge = 0x3;
-       bool only_standby = dev_priv->vbt.psr.full_link;
        static const uint8_t aux_msg[] = {
                [0] = DP_AUX_NATIVE_WRITE << 4,
                [1] = DP_SET_POWER >> 8,
@@ -157,16 +156,13 @@ static void hsw_psr_enable_sink(struct intel_dp *intel_dp)
 
        aux_clock_divider = intel_dp->get_aux_clock_divider(intel_dp, 0);
 
-       if (IS_BROADWELL(dev) && dig_port->port != PORT_A)
-               only_standby = true;
-
        /* Enable PSR in sink */
-       if (intel_dp->psr_dpcd[1] & DP_PSR_NO_TRAIN_ON_EXIT || only_standby)
+       if (dev_priv->psr.link_standby)
                drm_dp_dpcd_writeb(&intel_dp->aux, DP_PSR_EN_CFG,
-                                  DP_PSR_ENABLE & ~DP_PSR_MAIN_LINK_ACTIVE);
+                                  DP_PSR_ENABLE DP_PSR_MAIN_LINK_ACTIVE);
        else
                drm_dp_dpcd_writeb(&intel_dp->aux, DP_PSR_EN_CFG,
-                                  DP_PSR_ENABLE DP_PSR_MAIN_LINK_ACTIVE);
+                                  DP_PSR_ENABLE & ~DP_PSR_MAIN_LINK_ACTIVE);
 
        /* Setup AUX registers */
        for (i = 0; i < sizeof(aux_msg); i += 4)
@@ -226,12 +222,8 @@ static void hsw_psr_enable_source(struct intel_dp *intel_dp)
                               dev_priv->vbt.psr.idle_frames + 1 : 2;
        uint32_t val = 0x0;
        const uint32_t link_entry_time = EDP_PSR_MIN_LINK_ENTRY_TIME_8_LINES;
-       bool only_standby = false;
 
-       if (IS_BROADWELL(dev) && dig_port->port != PORT_A)
-               only_standby = true;
-
-       if (intel_dp->psr_dpcd[1] & DP_PSR_NO_TRAIN_ON_EXIT || only_standby) {
+       if (dev_priv->psr.link_standby) {
                val |= EDP_PSR_LINK_STANDBY;
                val |= EDP_PSR_TP2_TP3_TIME_0us;
                val |= EDP_PSR_TP1_TIME_0us;
@@ -270,22 +262,19 @@ static bool intel_psr_match_conditions(struct intel_dp *intel_dp)
                return false;
        }
 
-       /* Below limitations aren't valid for Broadwell */
-       if (IS_BROADWELL(dev))
-               goto out;
-
-       if (I915_READ(HSW_STEREO_3D_CTL(intel_crtc->config.cpu_transcoder)) &
-           S3D_ENABLE) {
+       if (IS_HASWELL(dev) &&
+           I915_READ(HSW_STEREO_3D_CTL(intel_crtc->config.cpu_transcoder)) &
+                     S3D_ENABLE) {
                DRM_DEBUG_KMS("PSR condition failed: Stereo 3D is Enabled\n");
                return false;
        }
 
-       if (intel_crtc->config.adjusted_mode.flags & DRM_MODE_FLAG_INTERLACE) {
+       if (IS_HASWELL(dev) &&
+           intel_crtc->config.adjusted_mode.flags & DRM_MODE_FLAG_INTERLACE) {
                DRM_DEBUG_KMS("PSR condition failed: Interlaced is Enabled\n");
                return false;
        }
 
- out:
        dev_priv->psr.source_ok = true;
        return true;
 }
@@ -344,6 +333,13 @@ void intel_psr_enable(struct intel_dp *intel_dp)
        if (!intel_psr_match_conditions(intel_dp))
                goto unlock;
 
+       /* First we check VBT, but we must respect sink and source
+        * known restrictions */
+       dev_priv->psr.link_standby = dev_priv->vbt.psr.full_link;
+       if ((intel_dp->psr_dpcd[1] & DP_PSR_NO_TRAIN_ON_EXIT) ||
+           (IS_BROADWELL(dev) && intel_dig_port->port != PORT_A))
+               dev_priv->psr.link_standby = true;
+
        dev_priv->psr.busy_frontbuffer_bits = 0;
 
        if (HAS_DDI(dev)) {
@@ -620,13 +616,11 @@ void intel_psr_flush(struct drm_device *dev,
 
        /*
         * On Valleyview and Cherryview we don't use hardware tracking so
-        * sprite plane updates or cursor moves don't result in a PSR
+        * any plane updates or cursor moves don't result in a PSR
         * invalidating. Which means we need to manually fake this in
         * software for all flushes, not just when we've seen a preceding
         * invalidation through frontbuffer rendering. */
-       if (!HAS_DDI(dev) &&
-           ((frontbuffer_bits & INTEL_FRONTBUFFER_SPRITE(pipe)) ||
-            (frontbuffer_bits & INTEL_FRONTBUFFER_CURSOR(pipe))))
+       if (!HAS_DDI(dev))
                intel_psr_exit(dev);
 
        if (!dev_priv->psr.active && !dev_priv->psr.busy_frontbuffer_bits)
index 12a36f0ca53d61e589d708d37e3791bfd4d8625e..23020d67329b042a3cac7a30efd4092087a2e06a 100644 (file)
@@ -796,6 +796,16 @@ static int bdw_init_workarounds(struct intel_engine_cs *ring)
                          HDC_DONOT_FETCH_MEM_WHEN_MASKED |
                          (IS_BDW_GT3(dev) ? HDC_FENCE_DEST_SLM_DISABLE : 0));
 
+       /* From the Haswell PRM, Command Reference: Registers, CACHE_MODE_0:
+        * "The Hierarchical Z RAW Stall Optimization allows non-overlapping
+        *  polygons in the same 8x4 pixel/sample area to be processed without
+        *  stalling waiting for the earlier ones to write to Hierarchical Z
+        *  buffer."
+        *
+        * This optimization is off by default for Broadwell; turn it on.
+        */
+       WA_CLR_BIT_MASKED(CACHE_MODE_0_GEN7, HIZ_RAW_STALL_OPT_DISABLE);
+
        /* Wa4x4STCOptimizationDisable:bdw */
        WA_SET_BIT_MASKED(CACHE_MODE_1,
                          GEN8_4x4_STC_OPTIMIZATION_DISABLE);
@@ -836,6 +846,14 @@ static int chv_init_workarounds(struct intel_engine_cs *ring)
                          HDC_FORCE_NON_COHERENT |
                          HDC_DONOT_FETCH_MEM_WHEN_MASKED);
 
+       /* According to the CACHE_MODE_0 default value documentation, some
+        * CHV platforms disable this optimization by default.  Turn it on.
+        */
+       WA_CLR_BIT_MASKED(CACHE_MODE_0_GEN7, HIZ_RAW_STALL_OPT_DISABLE);
+
+       /* Improve HiZ throughput on CHV. */
+       WA_SET_BIT_MASKED(HIZ_CHICKEN, CHV_HZ_8X8_MODE_IN_1X);
+
        return 0;
 }
 
index 39e1b071765db89136a2db1cba32f77d54104698..8bf7bb4a12bcf5637e2b2bf1f6ca733c25d3a7ed 100644 (file)
@@ -31,7 +31,6 @@
 
 #include "i915_drv.h"
 #include "intel_drv.h"
-#include <drm/i915_powerwell.h>
 
 /**
  * DOC: runtime pm
@@ -50,8 +49,6 @@
  * present for a given platform.
  */
 
-static struct i915_power_domains *hsw_pwr;
-
 #define for_each_power_well(i, power_well, domain_mask, power_domains) \
        for (i = 0;                                                     \
             i < (power_domains)->power_well_count &&                   \
@@ -1071,10 +1068,8 @@ int intel_power_domains_init(struct drm_i915_private *dev_priv)
         */
        if (IS_HASWELL(dev_priv->dev)) {
                set_power_wells(power_domains, hsw_power_wells);
-               hsw_pwr = power_domains;
        } else if (IS_BROADWELL(dev_priv->dev)) {
                set_power_wells(power_domains, bdw_power_wells);
-               hsw_pwr = power_domains;
        } else if (IS_CHERRYVIEW(dev_priv->dev)) {
                set_power_wells(power_domains, chv_power_wells);
        } else if (IS_VALLEYVIEW(dev_priv->dev)) {
@@ -1118,8 +1113,6 @@ void intel_power_domains_fini(struct drm_i915_private *dev_priv)
         * the power well is not enabled, so just enable it in case
         * we're going to unload/reload. */
        intel_display_set_init_power(dev_priv, true);
-
-       hsw_pwr = NULL;
 }
 
 static void intel_power_domains_resume(struct drm_i915_private *dev_priv)
@@ -1328,52 +1321,3 @@ void intel_runtime_pm_enable(struct drm_i915_private *dev_priv)
        pm_runtime_put_autosuspend(device);
 }
 
-/* Display audio driver power well request */
-int i915_request_power_well(void)
-{
-       struct drm_i915_private *dev_priv;
-
-       if (!hsw_pwr)
-               return -ENODEV;
-
-       dev_priv = container_of(hsw_pwr, struct drm_i915_private,
-                               power_domains);
-       intel_display_power_get(dev_priv, POWER_DOMAIN_AUDIO);
-       return 0;
-}
-EXPORT_SYMBOL_GPL(i915_request_power_well);
-
-/* Display audio driver power well release */
-int i915_release_power_well(void)
-{
-       struct drm_i915_private *dev_priv;
-
-       if (!hsw_pwr)
-               return -ENODEV;
-
-       dev_priv = container_of(hsw_pwr, struct drm_i915_private,
-                               power_domains);
-       intel_display_power_put(dev_priv, POWER_DOMAIN_AUDIO);
-       return 0;
-}
-EXPORT_SYMBOL_GPL(i915_release_power_well);
-
-/*
- * Private interface for the audio driver to get CDCLK in kHz.
- *
- * Caller must request power well using i915_request_power_well() prior to
- * making the call.
- */
-int i915_get_cdclk_freq(void)
-{
-       struct drm_i915_private *dev_priv;
-
-       if (!hsw_pwr)
-               return -ENODEV;
-
-       dev_priv = container_of(hsw_pwr, struct drm_i915_private,
-                               power_domains);
-
-       return intel_ddi_get_cdclk_freq(dev_priv);
-}
-EXPORT_SYMBOL_GPL(i915_get_cdclk_freq);
index 6d7a277458b5cf0f24a3e97f2b60463f75585d2e..4e3d362931e9e412c8af3117da94609961a3d602 100644 (file)
@@ -1617,6 +1617,9 @@ static uint16_t intel_sdvo_get_hotplug_support(struct intel_sdvo *intel_sdvo)
        struct drm_device *dev = intel_sdvo->base.base.dev;
        uint16_t hotplug;
 
+       if (!I915_HAS_HOTPLUG(dev))
+               return 0;
+
        /* HW Erratum: SDVO Hotplug is broken on all i945G chips, there's noise
         * on the line. */
        if (IS_I945G(dev) || IS_I945GM(dev))
index c18e57d36c2cbd4a3a7a25348e9b0c3e94f650c7..dca3f70ef1ba02aebd587f7e8163f108a1daedb7 100644 (file)
@@ -33,6 +33,7 @@
 #include <drm/drm_crtc.h>
 #include <drm/drm_fourcc.h>
 #include <drm/drm_rect.h>
+#include <drm/drm_plane_helper.h>
 #include "intel_drv.h"
 #include <drm/i915_drm.h>
 #include "i915_drv.h"
@@ -412,8 +413,6 @@ vlv_update_plane(struct drm_plane *dplane, struct drm_crtc *crtc,
        u32 sprctl;
        unsigned long sprsurf_offset, linear_offset;
        int pixel_size = drm_format_plane_cpp(fb->pixel_format, 0);
-       u32 start_vbl_count;
-       bool atomic_update;
 
        sprctl = I915_READ(SPCNTR(pipe, plane));
 
@@ -502,8 +501,6 @@ vlv_update_plane(struct drm_plane *dplane, struct drm_crtc *crtc,
                linear_offset += src_h * fb->pitches[0] + src_w * pixel_size;
        }
 
-       atomic_update = intel_pipe_update_start(intel_crtc, &start_vbl_count);
-
        intel_update_primary_plane(intel_crtc);
 
        if (IS_CHERRYVIEW(dev) && pipe == PIPE_B)
@@ -525,9 +522,6 @@ vlv_update_plane(struct drm_plane *dplane, struct drm_crtc *crtc,
                   sprsurf_offset);
 
        intel_flush_primary_plane(dev_priv, intel_crtc->plane);
-
-       if (atomic_update)
-               intel_pipe_update_end(intel_crtc, start_vbl_count);
 }
 
 static void
@@ -539,10 +533,6 @@ vlv_disable_plane(struct drm_plane *dplane, struct drm_crtc *crtc)
        struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
        int pipe = intel_plane->pipe;
        int plane = intel_plane->plane;
-       u32 start_vbl_count;
-       bool atomic_update;
-
-       atomic_update = intel_pipe_update_start(intel_crtc, &start_vbl_count);
 
        intel_update_primary_plane(intel_crtc);
 
@@ -553,9 +543,6 @@ vlv_disable_plane(struct drm_plane *dplane, struct drm_crtc *crtc)
 
        intel_flush_primary_plane(dev_priv, intel_crtc->plane);
 
-       if (atomic_update)
-               intel_pipe_update_end(intel_crtc, start_vbl_count);
-
        intel_update_sprite_watermarks(dplane, crtc, 0, 0, 0, false, false);
 }
 
@@ -626,8 +613,6 @@ ivb_update_plane(struct drm_plane *plane, struct drm_crtc *crtc,
        u32 sprctl, sprscale = 0;
        unsigned long sprsurf_offset, linear_offset;
        int pixel_size = drm_format_plane_cpp(fb->pixel_format, 0);
-       u32 start_vbl_count;
-       bool atomic_update;
 
        sprctl = I915_READ(SPRCTL(pipe));
 
@@ -711,8 +696,6 @@ ivb_update_plane(struct drm_plane *plane, struct drm_crtc *crtc,
                }
        }
 
-       atomic_update = intel_pipe_update_start(intel_crtc, &start_vbl_count);
-
        intel_update_primary_plane(intel_crtc);
 
        I915_WRITE(SPRSTRIDE(pipe), fb->pitches[0]);
@@ -735,9 +718,6 @@ ivb_update_plane(struct drm_plane *plane, struct drm_crtc *crtc,
                   i915_gem_obj_ggtt_offset(obj) + sprsurf_offset);
 
        intel_flush_primary_plane(dev_priv, intel_crtc->plane);
-
-       if (atomic_update)
-               intel_pipe_update_end(intel_crtc, start_vbl_count);
 }
 
 static void
@@ -748,10 +728,6 @@ ivb_disable_plane(struct drm_plane *plane, struct drm_crtc *crtc)
        struct intel_plane *intel_plane = to_intel_plane(plane);
        struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
        int pipe = intel_plane->pipe;
-       u32 start_vbl_count;
-       bool atomic_update;
-
-       atomic_update = intel_pipe_update_start(intel_crtc, &start_vbl_count);
 
        intel_update_primary_plane(intel_crtc);
 
@@ -764,16 +740,12 @@ ivb_disable_plane(struct drm_plane *plane, struct drm_crtc *crtc)
 
        intel_flush_primary_plane(dev_priv, intel_crtc->plane);
 
-       if (atomic_update)
-               intel_pipe_update_end(intel_crtc, start_vbl_count);
-
        /*
         * Avoid underruns when disabling the sprite.
         * FIXME remove once watermark updates are done properly.
         */
-       intel_wait_for_vblank(dev, pipe);
-
-       intel_update_sprite_watermarks(plane, crtc, 0, 0, 0, false, false);
+       intel_crtc->atomic.wait_vblank = true;
+       intel_crtc->atomic.update_sprite_watermarks |= (1 << drm_plane_index(plane));
 }
 
 static int
@@ -846,8 +818,6 @@ ilk_update_plane(struct drm_plane *plane, struct drm_crtc *crtc,
        unsigned long dvssurf_offset, linear_offset;
        u32 dvscntr, dvsscale;
        int pixel_size = drm_format_plane_cpp(fb->pixel_format, 0);
-       u32 start_vbl_count;
-       bool atomic_update;
 
        dvscntr = I915_READ(DVSCNTR(pipe));
 
@@ -922,8 +892,6 @@ ilk_update_plane(struct drm_plane *plane, struct drm_crtc *crtc,
                linear_offset += src_h * fb->pitches[0] + src_w * pixel_size;
        }
 
-       atomic_update = intel_pipe_update_start(intel_crtc, &start_vbl_count);
-
        intel_update_primary_plane(intel_crtc);
 
        I915_WRITE(DVSSTRIDE(pipe), fb->pitches[0]);
@@ -941,9 +909,6 @@ ilk_update_plane(struct drm_plane *plane, struct drm_crtc *crtc,
                   i915_gem_obj_ggtt_offset(obj) + dvssurf_offset);
 
        intel_flush_primary_plane(dev_priv, intel_crtc->plane);
-
-       if (atomic_update)
-               intel_pipe_update_end(intel_crtc, start_vbl_count);
 }
 
 static void
@@ -954,10 +919,6 @@ ilk_disable_plane(struct drm_plane *plane, struct drm_crtc *crtc)
        struct intel_plane *intel_plane = to_intel_plane(plane);
        struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
        int pipe = intel_plane->pipe;
-       u32 start_vbl_count;
-       bool atomic_update;
-
-       atomic_update = intel_pipe_update_start(intel_crtc, &start_vbl_count);
 
        intel_update_primary_plane(intel_crtc);
 
@@ -969,19 +930,25 @@ ilk_disable_plane(struct drm_plane *plane, struct drm_crtc *crtc)
 
        intel_flush_primary_plane(dev_priv, intel_crtc->plane);
 
-       if (atomic_update)
-               intel_pipe_update_end(intel_crtc, start_vbl_count);
-
        /*
         * Avoid underruns when disabling the sprite.
         * FIXME remove once watermark updates are done properly.
         */
-       intel_wait_for_vblank(dev, pipe);
-
-       intel_update_sprite_watermarks(plane, crtc, 0, 0, 0, false, false);
+       intel_crtc->atomic.wait_vblank = true;
+       intel_crtc->atomic.update_sprite_watermarks |= (1 << drm_plane_index(plane));
 }
 
-static void
+/**
+ * intel_post_enable_primary - Perform operations after enabling primary plane
+ * @crtc: the CRTC whose primary plane was just enabled
+ *
+ * Performs potentially sleeping operations that must be done after the primary
+ * plane is enabled, such as updating FBC and IPS.  Note that this may be
+ * called due to an explicit primary plane update, or due to an implicit
+ * re-enable that is caused when a sprite plane is updated to no longer
+ * completely hide the primary plane.
+ */
+void
 intel_post_enable_primary(struct drm_crtc *crtc)
 {
        struct drm_device *dev = crtc->dev;
@@ -1008,7 +975,17 @@ intel_post_enable_primary(struct drm_crtc *crtc)
        mutex_unlock(&dev->struct_mutex);
 }
 
-static void
+/**
+ * intel_pre_disable_primary - Perform operations before disabling primary plane
+ * @crtc: the CRTC whose primary plane is to be disabled
+ *
+ * Performs potentially sleeping operations that must be done before the
+ * primary plane is enabled, such as updating FBC and IPS.  Note that this may
+ * be called due to an explicit primary plane update, or due to an implicit
+ * disable that is caused when a sprite plane completely hides the primary
+ * plane.
+ */
+void
 intel_pre_disable_primary(struct drm_crtc *crtc)
 {
        struct drm_device *dev = crtc->dev;
@@ -1105,15 +1082,16 @@ intel_check_sprite_plane(struct drm_plane *plane,
        uint32_t src_x, src_y, src_w, src_h;
        struct drm_rect *src = &state->src;
        struct drm_rect *dst = &state->dst;
-       struct drm_rect *orig_src = &state->orig_src;
        const struct drm_rect *clip = &state->clip;
        int hscale, vscale;
        int max_scale, min_scale;
        int pixel_size;
 
+       intel_crtc = intel_crtc ? intel_crtc : to_intel_crtc(plane->crtc);
+
        if (!fb) {
                state->visible = false;
-               return 0;
+               goto finish;
        }
 
        /* Don't modify another pipe's plane */
@@ -1191,10 +1169,10 @@ intel_check_sprite_plane(struct drm_plane *plane,
                                    intel_plane->rotation);
 
                /* sanity check to make sure the src viewport wasn't enlarged */
-               WARN_ON(src->x1 < (int) orig_src->x1 ||
-                       src->y1 < (int) orig_src->y1 ||
-                       src->x2 > (int) orig_src->x2 ||
-                       src->y2 > (int) orig_src->y2);
+               WARN_ON(src->x1 < (int) state->base.src_x ||
+                       src->y1 < (int) state->base.src_y ||
+                       src->x2 > (int) state->base.src_x + state->base.src_w ||
+                       src->y2 > (int) state->base.src_y + state->base.src_h);
 
                /*
                 * Hardware doesn't handle subpixel coordinates.
@@ -1260,6 +1238,29 @@ intel_check_sprite_plane(struct drm_plane *plane,
        dst->y1 = crtc_y;
        dst->y2 = crtc_y + crtc_h;
 
+finish:
+       /*
+        * If the sprite is completely covering the primary plane,
+        * we can disable the primary and save power.
+        */
+       state->hides_primary = fb != NULL && drm_rect_equals(dst, clip) &&
+               !colorkey_enabled(intel_plane);
+       WARN_ON(state->hides_primary && !state->visible && intel_crtc->active);
+
+       if (intel_crtc->active) {
+               if (intel_crtc->primary_enabled == state->hides_primary)
+                       intel_crtc->atomic.wait_for_flips = true;
+
+               if (intel_crtc->primary_enabled && state->hides_primary)
+                       intel_crtc->atomic.pre_disable_primary = true;
+
+               intel_crtc->atomic.fb_bits |=
+                       INTEL_FRONTBUFFER_SPRITE(intel_crtc->pipe);
+
+               if (!intel_crtc->primary_enabled && !state->hides_primary)
+                       intel_crtc->atomic.post_enable_primary = true;
+       }
+
        return 0;
 }
 
@@ -1267,58 +1268,23 @@ static void
 intel_commit_sprite_plane(struct drm_plane *plane,
                          struct intel_plane_state *state)
 {
-       struct drm_device *dev = plane->dev;
        struct drm_crtc *crtc = state->base.crtc;
-       struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
+       struct intel_crtc *intel_crtc;
        struct intel_plane *intel_plane = to_intel_plane(plane);
-       enum pipe pipe = intel_crtc->pipe;
        struct drm_framebuffer *fb = state->base.fb;
        struct drm_i915_gem_object *obj = intel_fb_obj(fb);
        int crtc_x, crtc_y;
        unsigned int crtc_w, crtc_h;
        uint32_t src_x, src_y, src_w, src_h;
-       struct drm_rect *dst = &state->dst;
-       const struct drm_rect *clip = &state->clip;
-       bool primary_enabled;
 
-       /*
-        * 'prepare' is never called when plane is being disabled, so we need
-        * to handle frontbuffer tracking here
-        */
-       if (!fb) {
-               mutex_lock(&dev->struct_mutex);
-               i915_gem_track_fb(intel_fb_obj(plane->fb), NULL,
-                                 INTEL_FRONTBUFFER_SPRITE(pipe));
-               mutex_unlock(&dev->struct_mutex);
-       }
+       crtc = crtc ? crtc : plane->crtc;
+       intel_crtc = to_intel_crtc(crtc);
 
-       /*
-        * If the sprite is completely covering the primary plane,
-        * we can disable the primary and save power.
-        */
-       primary_enabled = !drm_rect_equals(dst, clip) || colorkey_enabled(intel_plane);
-       WARN_ON(!primary_enabled && !state->visible && intel_crtc->active);
-
-       intel_plane->crtc_x = state->orig_dst.x1;
-       intel_plane->crtc_y = state->orig_dst.y1;
-       intel_plane->crtc_w = drm_rect_width(&state->orig_dst);
-       intel_plane->crtc_h = drm_rect_height(&state->orig_dst);
-       intel_plane->src_x = state->orig_src.x1;
-       intel_plane->src_y = state->orig_src.y1;
-       intel_plane->src_w = drm_rect_width(&state->orig_src);
-       intel_plane->src_h = drm_rect_height(&state->orig_src);
+       plane->fb = state->base.fb;
        intel_plane->obj = obj;
 
        if (intel_crtc->active) {
-               bool primary_was_enabled = intel_crtc->primary_enabled;
-
-               intel_crtc->primary_enabled = primary_enabled;
-
-               if (primary_was_enabled != primary_enabled)
-                       intel_crtc_wait_for_pending_flips(crtc);
-
-               if (primary_was_enabled && !primary_enabled)
-                       intel_pre_disable_primary(crtc);
+               intel_crtc->primary_enabled = !state->hides_primary;
 
                if (state->visible) {
                        crtc_x = state->dst.x1;
@@ -1335,23 +1301,9 @@ intel_commit_sprite_plane(struct drm_plane *plane,
                } else {
                        intel_plane->disable_plane(plane, crtc);
                }
-
-
-               intel_frontbuffer_flip(dev, INTEL_FRONTBUFFER_SPRITE(pipe));
-
-               if (!primary_was_enabled && primary_enabled)
-                       intel_post_enable_primary(crtc);
        }
 }
 
-static void intel_destroy_plane(struct drm_plane *plane)
-{
-       struct intel_plane *intel_plane = to_intel_plane(plane);
-       intel_disable_plane(plane);
-       drm_plane_cleanup(plane);
-       kfree(intel_plane);
-}
-
 int intel_sprite_set_colorkey(struct drm_device *dev, void *data,
                              struct drm_file *file_priv)
 {
@@ -1439,23 +1391,23 @@ int intel_plane_set_property(struct drm_plane *plane,
 
 int intel_plane_restore(struct drm_plane *plane)
 {
-       struct intel_plane *intel_plane = to_intel_plane(plane);
-
        if (!plane->crtc || !plane->fb)
                return 0;
 
        return plane->funcs->update_plane(plane, plane->crtc, plane->fb,
-                                 intel_plane->crtc_x, intel_plane->crtc_y,
-                                 intel_plane->crtc_w, intel_plane->crtc_h,
-                                 intel_plane->src_x, intel_plane->src_y,
-                                 intel_plane->src_w, intel_plane->src_h);
+                                 plane->state->crtc_x, plane->state->crtc_y,
+                                 plane->state->crtc_w, plane->state->crtc_h,
+                                 plane->state->src_x, plane->state->src_y,
+                                 plane->state->src_w, plane->state->src_h);
 }
 
-static const struct drm_plane_funcs intel_plane_funcs = {
-       .update_plane = intel_update_plane,
-       .disable_plane = intel_disable_plane,
-       .destroy = intel_destroy_plane,
+static const struct drm_plane_funcs intel_sprite_plane_funcs = {
+       .update_plane = drm_plane_helper_update,
+       .disable_plane = drm_plane_helper_disable,
+       .destroy = intel_plane_destroy,
        .set_property = intel_plane_set_property,
+       .atomic_duplicate_state = intel_plane_duplicate_state,
+       .atomic_destroy_state = intel_plane_destroy_state,
 };
 
 static uint32_t ilk_plane_formats[] = {
@@ -1517,6 +1469,13 @@ intel_plane_init(struct drm_device *dev, enum pipe pipe, int plane)
        if (!intel_plane)
                return -ENOMEM;
 
+       intel_plane->base.state =
+               intel_plane_duplicate_state(&intel_plane->base);
+       if (intel_plane->base.state == NULL) {
+               kfree(intel_plane);
+               return -ENOMEM;
+       }
+
        switch (INTEL_INFO(dev)->gen) {
        case 5:
        case 6:
@@ -1591,7 +1550,7 @@ intel_plane_init(struct drm_device *dev, enum pipe pipe, int plane)
        intel_plane->commit_plane = intel_commit_sprite_plane;
        possible_crtcs = (1 << pipe);
        ret = drm_universal_plane_init(dev, &intel_plane->base, possible_crtcs,
-                                      &intel_plane_funcs,
+                                      &intel_sprite_plane_funcs,
                                       plane_formats, num_plane_formats,
                                       DRM_PLANE_TYPE_OVERLAY);
        if (ret) {
@@ -1610,6 +1569,8 @@ intel_plane_init(struct drm_device *dev, enum pipe pipe, int plane)
                                           dev->mode_config.rotation_property,
                                           intel_plane->rotation);
 
+       drm_plane_helper_add(&intel_plane->base, &intel_plane_helper_funcs);
+
  out:
        return ret;
 }
diff --git a/include/drm/i915_component.h b/include/drm/i915_component.h
new file mode 100644 (file)
index 0000000..3e2f22e
--- /dev/null
@@ -0,0 +1,38 @@
+/*
+ * Copyright Â© 2014 Intel Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ */
+
+#ifndef _I915_COMPONENT_H_
+#define _I915_COMPONENT_H_
+
+struct i915_audio_component {
+       struct device *dev;
+
+       const struct i915_audio_component_ops {
+               struct module *owner;
+               void (*get_power)(struct device *);
+               void (*put_power)(struct device *);
+               int (*get_cdclk_freq)(struct device *);
+       } *ops;
+};
+
+#endif /* _I915_COMPONENT_H_ */
diff --git a/include/drm/i915_powerwell.h b/include/drm/i915_powerwell.h
deleted file mode 100644 (file)
index baa6f11..0000000
+++ /dev/null
@@ -1,37 +0,0 @@
-/**************************************************************************
- *
- * Copyright 2013 Intel Inc.
- * All Rights Reserved.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the
- * "Software"), to deal in the Software without restriction, including
- * without limitation the rights to use, copy, modify, merge, publish,
- * distribute, sub license, and/or sell copies of the Software, and to
- * permit persons to whom the Software is furnished to do so, subject to
- * the following conditions:
- *
- * The above copyright notice and this permission notice (including the
- * next paragraph) shall be included in all copies or substantial portions
- * of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
- * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM,
- * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
- * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
- * USE OR OTHER DEALINGS IN THE SOFTWARE.
- *
- *
- **************************************************************************/
-
-#ifndef _I915_POWERWELL_H_
-#define _I915_POWERWELL_H_
-
-/* For use by hda_i915 driver */
-extern int i915_request_power_well(void);
-extern int i915_release_power_well(void);
-extern int i915_get_cdclk_freq(void);
-
-#endif                         /* _I915_POWERWELL_H_ */
index 250262265ee31c3099b00850a29c6729889dcee9..2e559f6e699e84e50d5f325cc714659a30254f27 100644 (file)
@@ -224,6 +224,8 @@ typedef struct _drm_i915_sarea {
 #define DRM_I915_REG_READ              0x31
 #define DRM_I915_GET_RESET_STATS       0x32
 #define DRM_I915_GEM_USERPTR           0x33
+#define DRM_I915_GEM_CONTEXT_GETPARAM  0x34
+#define DRM_I915_GEM_CONTEXT_SETPARAM  0x35
 
 #define DRM_IOCTL_I915_INIT            DRM_IOW( DRM_COMMAND_BASE + DRM_I915_INIT, drm_i915_init_t)
 #define DRM_IOCTL_I915_FLUSH           DRM_IO ( DRM_COMMAND_BASE + DRM_I915_FLUSH)
@@ -275,6 +277,8 @@ typedef struct _drm_i915_sarea {
 #define DRM_IOCTL_I915_REG_READ                        DRM_IOWR (DRM_COMMAND_BASE + DRM_I915_REG_READ, struct drm_i915_reg_read)
 #define DRM_IOCTL_I915_GET_RESET_STATS         DRM_IOWR (DRM_COMMAND_BASE + DRM_I915_GET_RESET_STATS, struct drm_i915_reset_stats)
 #define DRM_IOCTL_I915_GEM_USERPTR                     DRM_IOWR (DRM_COMMAND_BASE + DRM_I915_GEM_USERPTR, struct drm_i915_gem_userptr)
+#define DRM_IOCTL_I915_GEM_CONTEXT_GETPARAM    DRM_IOWR (DRM_COMMAND_BASE + DRM_I915_GEM_CONTEXT_GETPARAM, struct drm_i915_gem_context_param)
+#define DRM_IOCTL_I915_GEM_CONTEXT_SETPARAM    DRM_IOWR (DRM_COMMAND_BASE + DRM_I915_GEM_CONTEXT_SETPARAM, struct drm_i915_gem_context_param)
 
 /* Allow drivers to submit batchbuffers directly to hardware, relying
  * on the security mechanisms provided by hardware.
@@ -341,6 +345,7 @@ typedef struct drm_i915_irq_wait {
 #define I915_PARAM_HAS_WT               27
 #define I915_PARAM_CMD_PARSER_VERSION   28
 #define I915_PARAM_HAS_COHERENT_PHYS_GTT 29
+#define I915_PARAM_MMAP_VERSION          30
 
 typedef struct drm_i915_getparam {
        int param;
@@ -488,6 +493,14 @@ struct drm_i915_gem_mmap {
         * This is a fixed-size type for 32/64 compatibility.
         */
        __u64 addr_ptr;
+
+       /**
+        * Flags for extended behaviour.
+        *
+        * Added in version 2.
+        */
+       __u64 flags;
+#define I915_MMAP_WC 0x1
 };
 
 struct drm_i915_gem_mmap_gtt {
@@ -1073,4 +1086,12 @@ struct drm_i915_gem_userptr {
        __u32 handle;
 };
 
+struct drm_i915_gem_context_param {
+       __u32 ctx_id;
+       __u32 size;
+       __u64 param;
+#define I915_CONTEXT_PARAM_BAN_PERIOD 0x1
+       __u64 value;
+};
+
 #endif /* _UAPI_I915_DRM_H_ */
index d4d0375ac181adcedccfcf4ebcaa9ce85b997f3a..714894527e06a50c9dc3903928b610b8a7035423 100644 (file)
 
 #include <linux/init.h>
 #include <linux/module.h>
+#include <linux/pci.h>
+#include <linux/component.h>
+#include <drm/i915_component.h>
 #include <sound/core.h>
-#include <drm/i915_powerwell.h>
 #include "hda_priv.h"
-#include "hda_i915.h"
+#include "hda_intel.h"
 
 /* Intel HSW/BDW display HDA controller Extended Mode registers.
  * EM4 (M value) and EM5 (N Value) are used to convert CDClk (Core Display
 #define AZX_REG_EM4                    0x100c
 #define AZX_REG_EM5                    0x1010
 
-static int (*get_power)(void);
-static int (*put_power)(void);
-static int (*get_cdclk)(void);
-
-int hda_display_power(bool enable)
+int hda_display_power(struct hda_intel *hda, bool enable)
 {
-       if (!get_power || !put_power)
+       struct i915_audio_component *acomp = &hda->audio_component;
+
+       if (!acomp->ops)
                return -ENODEV;
 
-       pr_debug("HDA display power %s \n",
-                       enable ? "Enable" : "Disable");
+       dev_dbg(&hda->chip.pci->dev, "display power %s\n",
+               enable ? "enable" : "disable");
        if (enable)
-               return get_power();
+               acomp->ops->get_power(acomp->dev);
        else
-               return put_power();
+               acomp->ops->put_power(acomp->dev);
+
+       return 0;
 }
 
-void haswell_set_bclk(struct azx *chip)
+void haswell_set_bclk(struct hda_intel *hda)
 {
        int cdclk_freq;
        unsigned int bclk_m, bclk_n;
+       struct i915_audio_component *acomp = &hda->audio_component;
 
-       if (!get_cdclk)
+       if (!acomp->ops)
                return;
 
-       cdclk_freq = get_cdclk();
+       cdclk_freq = acomp->ops->get_cdclk_freq(acomp->dev);
        switch (cdclk_freq) {
        case 337500:
                bclk_m = 16;
@@ -80,51 +83,108 @@ void haswell_set_bclk(struct azx *chip)
                break;
        }
 
-       azx_writew(chip, EM4, bclk_m);
-       azx_writew(chip, EM5, bclk_n);
+       azx_writew(&hda->chip, EM4, bclk_m);
+       azx_writew(&hda->chip, EM5, bclk_n);
 }
 
-
-int hda_i915_init(void)
+static int hda_component_master_bind(struct device *dev)
 {
-       int err = 0;
-
-       get_power = symbol_request(i915_request_power_well);
-       if (!get_power) {
-               pr_warn("hda-i915: get_power symbol get fail\n");
-               return -ENODEV;
+       struct snd_card *card = dev_get_drvdata(dev);
+       struct azx *chip = card->private_data;
+       struct hda_intel *hda = container_of(chip, struct hda_intel, chip);
+       struct i915_audio_component *acomp = &hda->audio_component;
+       int ret;
+
+       ret = component_bind_all(dev, acomp);
+       if (ret < 0)
+               return ret;
+
+       if (WARN_ON(!(acomp->dev && acomp->ops && acomp->ops->get_power &&
+                     acomp->ops->put_power && acomp->ops->get_cdclk_freq))) {
+               ret = -EINVAL;
+               goto out_unbind;
        }
 
-       put_power = symbol_request(i915_release_power_well);
-       if (!put_power) {
-               symbol_put(i915_request_power_well);
-               get_power = NULL;
-               return -ENODEV;
+       /*
+        * Atm, we don't support dynamic unbinding initiated by the child
+        * component, so pin its containing module until we unbind.
+        */
+       if (!try_module_get(acomp->ops->owner)) {
+               ret = -ENODEV;
+               goto out_unbind;
        }
 
-       get_cdclk = symbol_request(i915_get_cdclk_freq);
-       if (!get_cdclk) /* may have abnormal BCLK and audio playback rate */
-               pr_warn("hda-i915: get_cdclk symbol get fail\n");
+       return 0;
 
-       pr_debug("HDA driver get symbol successfully from i915 module\n");
+out_unbind:
+       component_unbind_all(dev, acomp);
 
-       return err;
+       return ret;
 }
 
-int hda_i915_exit(void)
+static void hda_component_master_unbind(struct device *dev)
 {
-       if (get_power) {
-               symbol_put(i915_request_power_well);
-               get_power = NULL;
-       }
-       if (put_power) {
-               symbol_put(i915_release_power_well);
-               put_power = NULL;
-       }
-       if (get_cdclk) {
-               symbol_put(i915_get_cdclk_freq);
-               get_cdclk = NULL;
+       struct snd_card *card = dev_get_drvdata(dev);
+       struct azx *chip = card->private_data;
+       struct hda_intel *hda = container_of(chip, struct hda_intel, chip);
+       struct i915_audio_component *acomp = &hda->audio_component;
+
+       module_put(acomp->ops->owner);
+       component_unbind_all(dev, acomp);
+       WARN_ON(acomp->ops || acomp->dev);
+}
+
+static const struct component_master_ops hda_component_master_ops = {
+       .bind = hda_component_master_bind,
+       .unbind = hda_component_master_unbind,
+};
+
+static int hda_component_master_match(struct device *dev, void *data)
+{
+       /* i915 is the only supported component */
+       return !strcmp(dev->driver->name, "i915");
+}
+
+int hda_i915_init(struct hda_intel *hda)
+{
+       struct component_match *match = NULL;
+       struct device *dev = &hda->chip.pci->dev;
+       struct i915_audio_component *acomp = &hda->audio_component;
+       int ret;
+
+       component_match_add(dev, &match, hda_component_master_match, hda);
+       ret = component_master_add_with_match(dev, &hda_component_master_ops,
+                                             match);
+       if (ret < 0)
+               goto out_err;
+
+       /*
+        * Atm, we don't support deferring the component binding, so make sure
+        * i915 is loaded and that the binding successfully completes.
+        */
+       request_module("i915");
+
+       if (!acomp->ops) {
+               ret = -ENODEV;
+               goto out_master_del;
        }
 
+       dev_dbg(dev, "bound to i915 component master\n");
+
+       return 0;
+out_master_del:
+       component_master_del(dev, &hda_component_master_ops);
+out_err:
+       dev_err(dev, "failed to add i915 component master (%d)\n", ret);
+
+       return ret;
+}
+
+int hda_i915_exit(struct hda_intel *hda)
+{
+       struct device *dev = &hda->chip.pci->dev;
+
+       component_master_del(dev, &hda_component_master_ops);
+
        return 0;
 }
diff --git a/sound/pci/hda/hda_i915.h b/sound/pci/hda/hda_i915.h
deleted file mode 100644 (file)
index e6072c6..0000000
+++ /dev/null
@@ -1,37 +0,0 @@
-/*
- *  This program is free software; you can redistribute it and/or modify it
- *  under the terms of the GNU General Public License as published by the Free
- *  Software Foundation; either version 2 of the License, or (at your option)
- *  any later version.
- *
- *  This program is distributed in the hope that it will be useful, but WITHOUT
- *  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- *  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
- *  more details.
- *
- *  You should have received a copy of the GNU General Public License along with
- *  this program; if not, write to the Free Software Foundation, Inc., 59
- *  Temple Place - Suite 330, Boston, MA  02111-1307, USA.
- */
-#ifndef __SOUND_HDA_I915_H
-#define __SOUND_HDA_I915_H
-
-#ifdef CONFIG_SND_HDA_I915
-int hda_display_power(bool enable);
-void haswell_set_bclk(struct azx *chip);
-int hda_i915_init(void);
-int hda_i915_exit(void);
-#else
-static inline int hda_display_power(bool enable) { return 0; }
-static inline void haswell_set_bclk(struct azx *chip) { return; }
-static inline int hda_i915_init(void)
-{
-       return -ENODEV;
-}
-static inline int hda_i915_exit(void)
-{
-       return 0;
-}
-#endif
-
-#endif
index d426a0bd6a5f7e86adf482c83ad86e3203a8a3ad..95a53999399073ced0218518494eb0ce2402fbb4 100644 (file)
@@ -63,7 +63,7 @@
 #include "hda_codec.h"
 #include "hda_controller.h"
 #include "hda_priv.h"
-#include "hda_i915.h"
+#include "hda_intel.h"
 
 /* position fix mode */
 enum {
@@ -354,31 +354,6 @@ static char *driver_short_names[] = {
        [AZX_DRIVER_GENERIC] = "HD-Audio Generic",
 };
 
-struct hda_intel {
-       struct azx chip;
-
-       /* for pending irqs */
-       struct work_struct irq_pending_work;
-
-       /* sync probing */
-       struct completion probe_wait;
-       struct work_struct probe_work;
-
-       /* card list (for power_save trigger) */
-       struct list_head list;
-
-       /* extra flags */
-       unsigned int irq_pending_warned:1;
-
-       /* VGA-switcheroo setup */
-       unsigned int use_vga_switcheroo:1;
-       unsigned int vga_switcheroo_registered:1;
-       unsigned int init_failed:1; /* delayed init failed */
-
-       /* secondary power domain for hdmi audio under vga device */
-       struct dev_pm_domain hdmi_pm_domain;
-};
-
 #ifdef CONFIG_X86
 static void __mark_pages_wc(struct azx *chip, struct snd_dma_buffer *dmab, bool on)
 {
@@ -828,7 +803,7 @@ static int azx_suspend(struct device *dev)
        pci_save_state(pci);
        pci_set_power_state(pci, PCI_D3hot);
        if (chip->driver_caps & AZX_DCAPS_I915_POWERWELL)
-               hda_display_power(false);
+               hda_display_power(hda, false);
        return 0;
 }
 
@@ -848,8 +823,8 @@ static int azx_resume(struct device *dev)
                return 0;
 
        if (chip->driver_caps & AZX_DCAPS_I915_POWERWELL) {
-               hda_display_power(true);
-               haswell_set_bclk(chip);
+               hda_display_power(hda, true);
+               haswell_set_bclk(hda);
        }
        pci_set_power_state(pci, PCI_D0);
        pci_restore_state(pci);
@@ -901,7 +876,7 @@ static int azx_runtime_suspend(struct device *dev)
        azx_enter_link_reset(chip);
        azx_clear_irq_pending(chip);
        if (chip->driver_caps & AZX_DCAPS_I915_POWERWELL)
-               hda_display_power(false);
+               hda_display_power(hda, false);
 
        return 0;
 }
@@ -927,8 +902,8 @@ static int azx_runtime_resume(struct device *dev)
                return 0;
 
        if (chip->driver_caps & AZX_DCAPS_I915_POWERWELL) {
-               hda_display_power(true);
-               haswell_set_bclk(chip);
+               hda_display_power(hda, true);
+               haswell_set_bclk(hda);
        }
 
        /* Read STATESTS before controller reset */
@@ -1150,8 +1125,8 @@ static int azx_free(struct azx *chip)
        release_firmware(chip->fw);
 #endif
        if (chip->driver_caps & AZX_DCAPS_I915_POWERWELL) {
-               hda_display_power(false);
-               hda_i915_exit();
+               hda_display_power(hda, false);
+               hda_i915_exit(hda);
        }
        kfree(hda);
 
@@ -1629,8 +1604,12 @@ static int azx_first_init(struct azx *chip)
        /* initialize chip */
        azx_init_pci(chip);
 
-       if (chip->driver_caps & AZX_DCAPS_I915_POWERWELL)
-               haswell_set_bclk(chip);
+       if (chip->driver_caps & AZX_DCAPS_I915_POWERWELL) {
+               struct hda_intel *hda;
+
+               hda = container_of(chip, struct hda_intel, chip);
+               haswell_set_bclk(hda);
+       }
 
        azx_init_chip(chip, (probe_only[dev] & 2) == 0);
 
@@ -1910,13 +1889,10 @@ static int azx_probe_continue(struct azx *chip)
        /* Request power well for Haswell HDA controller and codec */
        if (chip->driver_caps & AZX_DCAPS_I915_POWERWELL) {
 #ifdef CONFIG_SND_HDA_I915
-               err = hda_i915_init();
-               if (err < 0) {
-                       dev_err(chip->card->dev,
-                               "Error request power-well from i915\n");
+               err = hda_i915_init(hda);
+               if (err < 0)
                        goto out_free;
-               }
-               err = hda_display_power(true);
+               err = hda_display_power(hda, true);
                if (err < 0) {
                        dev_err(chip->card->dev,
                                "Cannot turn on display power on i915\n");
diff --git a/sound/pci/hda/hda_intel.h b/sound/pci/hda/hda_intel.h
new file mode 100644 (file)
index 0000000..3486118
--- /dev/null
@@ -0,0 +1,71 @@
+/*
+ *  This program is free software; you can redistribute it and/or modify it
+ *  under the terms of the GNU General Public License as published by the Free
+ *  Software Foundation; either version 2 of the License, or (at your option)
+ *  any later version.
+ *
+ *  This program is distributed in the hope that it will be useful, but WITHOUT
+ *  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ *  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ *  more details.
+ *
+ *  You should have received a copy of the GNU General Public License along with
+ *  this program; if not, write to the Free Software Foundation, Inc., 59
+ *  Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+ */
+#ifndef __SOUND_HDA_INTEL_H
+#define __SOUND_HDA_INTEL_H
+
+#include <drm/i915_component.h>
+#include "hda_priv.h"
+
+struct hda_intel {
+       struct azx chip;
+
+       /* for pending irqs */
+       struct work_struct irq_pending_work;
+
+       /* sync probing */
+       struct completion probe_wait;
+       struct work_struct probe_work;
+
+       /* card list (for power_save trigger) */
+       struct list_head list;
+
+       /* extra flags */
+       unsigned int irq_pending_warned:1;
+
+       /* VGA-switcheroo setup */
+       unsigned int use_vga_switcheroo:1;
+       unsigned int vga_switcheroo_registered:1;
+       unsigned int init_failed:1; /* delayed init failed */
+
+       /* secondary power domain for hdmi audio under vga device */
+       struct dev_pm_domain hdmi_pm_domain;
+
+       /* i915 component interface */
+       struct i915_audio_component audio_component;
+};
+
+#ifdef CONFIG_SND_HDA_I915
+int hda_display_power(struct hda_intel *hda, bool enable);
+void haswell_set_bclk(struct hda_intel *hda);
+int hda_i915_init(struct hda_intel *hda);
+int hda_i915_exit(struct hda_intel *hda);
+#else
+static inline int hda_display_power(struct hda_intel *hda, bool enable)
+{
+       return 0;
+}
+static inline void haswell_set_bclk(struct hda_intel *hda) { return; }
+static inline int hda_i915_init(struct hda_intel *hda)
+{
+       return -ENODEV;
+}
+static inline int hda_i915_exit(struct hda_intel *hda)
+{
+       return 0;
+}
+#endif
+
+#endif