Merge drm-next into drm-intel-next-queued (this time for real)
authorJoonas Lahtinen <joonas.lahtinen@linux.intel.com>
Thu, 1 Mar 2018 09:14:24 +0000 (11:14 +0200)
committerJoonas Lahtinen <joonas.lahtinen@linux.intel.com>
Thu, 1 Mar 2018 09:14:24 +0000 (11:14 +0200)
To pull in the HDCP changes, especially wait_for changes to drm/i915
that Chris wants to build on top of.

Signed-off-by: Joonas Lahtinen <joonas.lahtinen@linux.intel.com>
1  2 
Documentation/gpu/todo.rst
drivers/gpu/drm/i915/Makefile
drivers/gpu/drm/i915/gvt/scheduler.c
drivers/gpu/drm/i915/gvt/scheduler.h
drivers/gpu/drm/i915/i915_drv.h
drivers/gpu/drm/i915/i915_perf.c
drivers/gpu/drm/i915/i915_reg.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_fbc.c

@@@ -212,6 -212,16 +212,16 @@@ probably use drm_fb_helper_fbdev_teardo
  
  Contact: Maintainer of the driver you plan to convert
  
+ idr_init_base()
+ ---------------
+ DRM core&drivers uses a lot of idr (integer lookup directories) for mapping
+ userspace IDs to internal objects, and in most places ID=0 means NULL and hence
+ is never used. Switching to idr_init_base() for these would make the idr more
+ efficient.
+ Contact: Daniel Vetter
  Core refactorings
  =================
  
@@@ -440,12 -450,5 +450,12 @@@ See drivers/gpu/drm/amd/display/TODO fo
  
  Contact: Harry Wentland, Alex Deucher
  
 +i915
 +----
 +
 +- Our early/late pm callbacks could be removed in favour of using
 +  device_link_add to model the dependency between i915 and snd_had. See
 +  https://dri.freedesktop.org/docs/drm/driver-api/device_link.html
 +
  Outside DRM
  ===========
@@@ -63,13 -63,13 +63,13 @@@ i915-y += i915_cmd_parser.o 
          i915_gem.o \
          i915_gem_object.o \
          i915_gem_render_state.o \
 -        i915_gem_request.o \
          i915_gem_shrinker.o \
          i915_gem_stolen.o \
          i915_gem_tiling.o \
          i915_gem_timeline.o \
          i915_gem_userptr.o \
          i915_gemfs.o \
 +        i915_request.o \
          i915_trace_points.o \
          i915_vma.o \
          intel_breadcrumbs.o \
@@@ -110,6 -110,7 +110,7 @@@ i915-y += intel_audio.o 
          intel_fbc.o \
          intel_fifo_underrun.o \
          intel_frontbuffer.o \
+         intel_hdcp.o \
          intel_hotplug.o \
          intel_modes.o \
          intel_overlay.o \
@@@ -126,7 -126,7 +126,7 @@@ static int populate_shadow_context(stru
        return 0;
  }
  
 -static inline bool is_gvt_request(struct drm_i915_gem_request *req)
 +static inline bool is_gvt_request(struct i915_request *req)
  {
        return i915_gem_context_force_single_submission(req->ctx);
  }
@@@ -148,7 -148,7 +148,7 @@@ static void save_ring_hw_state(struct i
  static int shadow_context_status_change(struct notifier_block *nb,
                unsigned long action, void *data)
  {
 -      struct drm_i915_gem_request *req = (struct drm_i915_gem_request *)data;
 +      struct i915_request *req = data;
        struct intel_gvt *gvt = container_of(nb, struct intel_gvt,
                                shadow_ctx_notifier_block[req->engine->id]);
        struct intel_gvt_workload_scheduler *scheduler = &gvt->scheduler;
@@@ -333,13 -333,13 +333,13 @@@ static int intel_gvt_generate_request(s
        int ring_id = workload->ring_id;
        struct drm_i915_private *dev_priv = workload->vgpu->gvt->dev_priv;
        struct intel_engine_cs *engine = dev_priv->engine[ring_id];
 -      struct drm_i915_gem_request *rq;
 +      struct i915_request *rq;
        struct intel_vgpu *vgpu = workload->vgpu;
        struct intel_vgpu_submission *s = &vgpu->submission;
        struct i915_gem_context *shadow_ctx = s->shadow_ctx;
        int ret;
  
 -      rq = i915_gem_request_alloc(dev_priv->engine[ring_id], shadow_ctx);
 +      rq = i915_request_alloc(dev_priv->engine[ring_id], shadow_ctx);
        if (IS_ERR(rq)) {
                gvt_vgpu_err("fail to allocate gem request\n");
                ret = PTR_ERR(rq);
  
        gvt_dbg_sched("ring id %d get i915 gem request %p\n", ring_id, rq);
  
 -      workload->req = i915_gem_request_get(rq);
 +      workload->req = i915_request_get(rq);
        ret = copy_workload_to_ring_buffer(workload);
        if (ret)
                goto err_unpin;
@@@ -582,7 -582,7 +582,7 @@@ out
        if (!IS_ERR_OR_NULL(workload->req)) {
                gvt_dbg_sched("ring id %d submit workload to i915 %p\n",
                                ring_id, workload->req);
 -              i915_add_request(workload->req);
 +              i915_request_add(workload->req);
                workload->dispatched = true;
        }
  
@@@ -769,7 -769,7 +769,7 @@@ static void complete_current_workload(s
                                workload->status = 0;
                }
  
 -              i915_gem_request_put(fetch_and_zero(&workload->req));
 +              i915_request_put(fetch_and_zero(&workload->req));
  
                if (!workload->status && !(vgpu->resetting_eng &
                                           ENGINE_MASK(ring_id))) {
@@@ -886,7 -886,7 +886,7 @@@ static int workload_thread(void *priv
  
                gvt_dbg_sched("ring id %d wait workload %p\n",
                                workload->ring_id, workload);
 -              i915_wait_request(workload->req, 0, MAX_SCHEDULE_TIMEOUT);
 +              i915_request_wait(workload->req, 0, MAX_SCHEDULE_TIMEOUT);
  
  complete:
                gvt_dbg_sched("will complete workload %p, status: %d\n",
@@@ -991,7 -991,7 +991,7 @@@ void intel_vgpu_clean_submission(struc
  {
        struct intel_vgpu_submission *s = &vgpu->submission;
  
-       intel_vgpu_select_submission_ops(vgpu, 0);
+       intel_vgpu_select_submission_ops(vgpu, ALL_ENGINES, 0);
        i915_gem_context_put(s->shadow_ctx);
        kmem_cache_destroy(s->workloads);
  }
@@@ -1079,6 -1079,7 +1079,7 @@@ out_shadow_ctx
   *
   */
  int intel_vgpu_select_submission_ops(struct intel_vgpu *vgpu,
+                                    unsigned long engine_mask,
                                     unsigned int interface)
  {
        struct intel_vgpu_submission *s = &vgpu->submission;
        if (WARN_ON(interface >= ARRAY_SIZE(ops)))
                return -EINVAL;
  
-       if (s->active) {
-               s->ops->clean(vgpu);
-               s->active = false;
-               gvt_dbg_core("vgpu%d: de-select ops [ %s ] \n",
-                               vgpu->id, s->ops->name);
-       }
+       if (WARN_ON(interface == 0 && engine_mask != ALL_ENGINES))
+               return -EINVAL;
+       if (s->active)
+               s->ops->clean(vgpu, engine_mask);
  
        if (interface == 0) {
                s->ops = NULL;
                s->virtual_submission_interface = 0;
-               gvt_dbg_core("vgpu%d: no submission ops\n", vgpu->id);
+               s->active = false;
+               gvt_dbg_core("vgpu%d: remove submission ops\n", vgpu->id);
                return 0;
        }
  
-       ret = ops[interface]->init(vgpu);
+       ret = ops[interface]->init(vgpu, engine_mask);
        if (ret)
                return ret;
  
@@@ -80,7 -80,7 +80,7 @@@ struct intel_shadow_wa_ctx 
  struct intel_vgpu_workload {
        struct intel_vgpu *vgpu;
        int ring_id;
 -      struct drm_i915_gem_request *req;
 +      struct i915_request *req;
        /* if this workload has been dispatched to i915? */
        bool dispatched;
        bool shadowed;
@@@ -141,6 -141,7 +141,7 @@@ void intel_vgpu_reset_submission(struc
  void intel_vgpu_clean_submission(struct intel_vgpu *vgpu);
  
  int intel_vgpu_select_submission_ops(struct intel_vgpu *vgpu,
+                                    unsigned long engine_mask,
                                     unsigned int interface);
  
  extern const struct intel_vgpu_submission_ops
@@@ -71,9 -71,9 +71,9 @@@
  #include "i915_gem_fence_reg.h"
  #include "i915_gem_object.h"
  #include "i915_gem_gtt.h"
 -#include "i915_gem_request.h"
  #include "i915_gem_timeline.h"
  
 +#include "i915_request.h"
  #include "i915_vma.h"
  
  #include "intel_gvt.h"
@@@ -1231,7 -1231,7 +1231,7 @@@ struct i915_gpu_error 
         *
         * #I915_WEDGED - If reset fails and we can no longer use the GPU,
         * we set the #I915_WEDGED bit. Prior to command submission, e.g.
 -       * i915_gem_request_alloc(), this bit is checked and the sequence
 +       * i915_request_alloc(), this bit is checked and the sequence
         * aborted (with -EIO reported to userspace) if set.
         */
        unsigned long flags;
@@@ -2788,10 -2788,9 +2788,10 @@@ intel_info(const struct drm_i915_privat
  /* Early gen2 have a totally busted CS tlb and require pinned batches. */
  #define HAS_BROKEN_CS_TLB(dev_priv)   (IS_I830(dev_priv) || IS_I845G(dev_priv))
  
 -/* WaRsDisableCoarsePowerGating:skl,bxt */
 +/* WaRsDisableCoarsePowerGating:skl,cnl */
  #define NEEDS_WaRsDisableCoarsePowerGating(dev_priv) \
 -      (IS_SKL_GT3(dev_priv) || IS_SKL_GT4(dev_priv))
 +      (IS_CANNONLAKE(dev_priv) || \
 +       IS_SKL_GT3(dev_priv) || IS_SKL_GT4(dev_priv))
  
  /*
   * dp aux and gmbus irq on gen4 seems to be able to generate legacy interrupts
@@@ -3330,7 -3329,7 +3330,7 @@@ i915_gem_obj_finish_shmem_access(struc
  
  int __must_check i915_mutex_lock_interruptible(struct drm_device *dev);
  void i915_vma_move_to_active(struct i915_vma *vma,
 -                           struct drm_i915_gem_request *req,
 +                           struct i915_request *rq,
                             unsigned int flags);
  int i915_gem_dumb_create(struct drm_file *file_priv,
                         struct drm_device *dev,
@@@ -3345,9 -3344,11 +3345,9 @@@ void i915_gem_track_fb(struct drm_i915_
  
  int __must_check i915_gem_set_global_seqno(struct drm_device *dev, u32 seqno);
  
 -struct drm_i915_gem_request *
 +struct i915_request *
  i915_gem_find_active_request(struct intel_engine_cs *engine);
  
 -void i915_gem_retire_requests(struct drm_i915_private *dev_priv);
 -
  static inline bool i915_reset_backoff(struct i915_gpu_error *error)
  {
        return unlikely(test_bit(I915_RESET_BACKOFF, &error->flags));
@@@ -3379,7 -3380,7 +3379,7 @@@ static inline u32 i915_reset_engine_cou
        return READ_ONCE(error->reset_engine_count[engine->id]);
  }
  
 -struct drm_i915_gem_request *
 +struct i915_request *
  i915_gem_reset_prepare_engine(struct intel_engine_cs *engine);
  int i915_gem_reset_prepare(struct drm_i915_private *dev_priv);
  void i915_gem_reset(struct drm_i915_private *dev_priv);
@@@ -3388,7 -3389,7 +3388,7 @@@ void i915_gem_reset_finish(struct drm_i
  void i915_gem_set_wedged(struct drm_i915_private *dev_priv);
  bool i915_gem_unset_wedged(struct drm_i915_private *dev_priv);
  void i915_gem_reset_engine(struct intel_engine_cs *engine,
 -                         struct drm_i915_gem_request *request);
 +                         struct i915_request *request);
  
  void i915_gem_init_mmio(struct drm_i915_private *i915);
  int __must_check i915_gem_init(struct drm_i915_private *dev_priv);
@@@ -3681,6 -3682,7 +3681,7 @@@ extern int intel_setup_gmbus(struct drm
  extern void intel_teardown_gmbus(struct drm_i915_private *dev_priv);
  extern bool intel_gmbus_is_valid_pin(struct drm_i915_private *dev_priv,
                                     unsigned int pin);
+ extern int intel_gmbus_output_aksv(struct i2c_adapter *adapter);
  
  extern struct i2c_adapter *
  intel_gmbus_get_adapter(struct drm_i915_private *dev_priv, unsigned int pin);
@@@ -4006,9 -4008,9 +4007,9 @@@ wait_remaining_ms_from_jiffies(unsigne
  }
  
  static inline bool
 -__i915_request_irq_complete(const struct drm_i915_gem_request *req)
 +__i915_request_irq_complete(const struct i915_request *rq)
  {
 -      struct intel_engine_cs *engine = req->engine;
 +      struct intel_engine_cs *engine = rq->engine;
        u32 seqno;
  
        /* Note that the engine may have wrapped around the seqno, and
         * this by kicking all the waiters before resetting the seqno
         * in hardware, and also signal the fence.
         */
 -      if (test_bit(DMA_FENCE_FLAG_SIGNALED_BIT, &req->fence.flags))
 +      if (test_bit(DMA_FENCE_FLAG_SIGNALED_BIT, &rq->fence.flags))
                return true;
  
        /* The request was dequeued before we were awoken. We check after
         * the request execution are sufficient to ensure that a check
         * after reading the value from hw matches this request.
         */
 -      seqno = i915_gem_request_global_seqno(req);
 +      seqno = i915_request_global_seqno(rq);
        if (!seqno)
                return false;
  
        /* Before we do the heavier coherent read of the seqno,
         * check the value (hopefully) in the CPU cacheline.
         */
 -      if (__i915_gem_request_completed(req, seqno))
 +      if (__i915_request_completed(rq, seqno))
                return true;
  
        /* Ensure our read of the seqno is coherent so that we
                        wake_up_process(b->irq_wait->tsk);
                spin_unlock_irq(&b->irq_lock);
  
 -              if (__i915_gem_request_completed(req, seqno))
 +              if (__i915_request_completed(rq, seqno))
                        return true;
        }
  
   * The two separate pointers let us decouple read()s from tail pointer aging.
   *
   * The tail pointers are checked and updated at a limited rate within a hrtimer
-  * callback (the same callback that is used for delivering POLLIN events)
+  * callback (the same callback that is used for delivering EPOLLIN events)
   *
   * Initially the tails are marked invalid with %INVALID_TAIL_PTR which
   * indicates that an updated tail pointer is needed.
@@@ -1630,10 -1630,10 +1630,10 @@@ static void gen8_update_reg_state_unloc
   * Same as gen8_update_reg_state_unlocked only through the batchbuffer. This
   * is only used by the kernel context.
   */
 -static int gen8_emit_oa_config(struct drm_i915_gem_request *req,
 +static int gen8_emit_oa_config(struct i915_request *rq,
                               const struct i915_oa_config *oa_config)
  {
 -      struct drm_i915_private *dev_priv = req->i915;
 +      struct drm_i915_private *dev_priv = rq->i915;
        /* The MMIO offsets for Flex EU registers aren't contiguous */
        u32 flex_mmio[] = {
                i915_mmio_reg_offset(EU_PERF_CNTL0),
        u32 *cs;
        int i;
  
 -      cs = intel_ring_begin(req, ARRAY_SIZE(flex_mmio) * 2 + 4);
 +      cs = intel_ring_begin(rq, ARRAY_SIZE(flex_mmio) * 2 + 4);
        if (IS_ERR(cs))
                return PTR_ERR(cs);
  
        }
  
        *cs++ = MI_NOOP;
 -      intel_ring_advance(req, cs);
 +      intel_ring_advance(rq, cs);
  
        return 0;
  }
@@@ -1695,38 -1695,38 +1695,38 @@@ static int gen8_switch_to_updated_kerne
  {
        struct intel_engine_cs *engine = dev_priv->engine[RCS];
        struct i915_gem_timeline *timeline;
 -      struct drm_i915_gem_request *req;
 +      struct i915_request *rq;
        int ret;
  
        lockdep_assert_held(&dev_priv->drm.struct_mutex);
  
 -      i915_gem_retire_requests(dev_priv);
 +      i915_retire_requests(dev_priv);
  
 -      req = i915_gem_request_alloc(engine, dev_priv->kernel_context);
 -      if (IS_ERR(req))
 -              return PTR_ERR(req);
 +      rq = i915_request_alloc(engine, dev_priv->kernel_context);
 +      if (IS_ERR(rq))
 +              return PTR_ERR(rq);
  
 -      ret = gen8_emit_oa_config(req, oa_config);
 +      ret = gen8_emit_oa_config(rq, oa_config);
        if (ret) {
 -              i915_add_request(req);
 +              i915_request_add(rq);
                return ret;
        }
  
        /* Queue this switch after all other activity */
        list_for_each_entry(timeline, &dev_priv->gt.timelines, link) {
 -              struct drm_i915_gem_request *prev;
 +              struct i915_request *prev;
                struct intel_timeline *tl;
  
                tl = &timeline->engine[engine->id];
                prev = i915_gem_active_raw(&tl->last_request,
                                           &dev_priv->drm.struct_mutex);
                if (prev)
 -                      i915_sw_fence_await_sw_fence_gfp(&req->submit,
 +                      i915_sw_fence_await_sw_fence_gfp(&rq->submit,
                                                         &prev->submit,
                                                         GFP_KERNEL);
        }
  
 -      i915_add_request(req);
 +      i915_request_add(rq);
  
        return 0;
  }
@@@ -2292,13 -2292,13 +2292,13 @@@ static ssize_t i915_perf_read(struct fi
                mutex_unlock(&dev_priv->perf.lock);
        }
  
-       /* We allow the poll checking to sometimes report false positive POLLIN
+       /* We allow the poll checking to sometimes report false positive EPOLLIN
         * events where we might actually report EAGAIN on read() if there's
         * not really any data available. In this situation though we don't
-        * want to enter a busy loop between poll() reporting a POLLIN event
+        * want to enter a busy loop between poll() reporting a EPOLLIN event
         * and read() returning -EAGAIN. Clearing the oa.pollin state here
         * effectively ensures we back off until the next hrtimer callback
-        * before reporting another POLLIN event.
+        * before reporting another EPOLLIN event.
         */
        if (ret >= 0 || ret == -EAGAIN) {
                /* Maybe make ->pollin per-stream state if we support multiple
@@@ -2342,12 -2342,12 +2342,12 @@@ static enum hrtimer_restart oa_poll_che
   *
   * Returns: any poll events that are ready without sleeping
   */
- static unsigned int i915_perf_poll_locked(struct drm_i915_private *dev_priv,
+ static __poll_t i915_perf_poll_locked(struct drm_i915_private *dev_priv,
                                          struct i915_perf_stream *stream,
                                          struct file *file,
                                          poll_table *wait)
  {
-       unsigned int events = 0;
+       __poll_t events = 0;
  
        stream->ops->poll_wait(stream, file, wait);
  
         * samples to read.
         */
        if (dev_priv->perf.oa.pollin)
-               events |= POLLIN;
+               events |= EPOLLIN;
  
        return events;
  }
   *
   * Returns: any poll events that are ready without sleeping
   */
- static unsigned int i915_perf_poll(struct file *file, poll_table *wait)
+ static __poll_t i915_perf_poll(struct file *file, poll_table *wait)
  {
        struct i915_perf_stream *stream = file->private_data;
        struct drm_i915_private *dev_priv = stream->dev_priv;
-       int ret;
+       __poll_t ret;
  
        mutex_lock(&dev_priv->perf.lock);
        ret = i915_perf_poll_locked(dev_priv, stream, file, wait);
@@@ -2807,13 -2807,6 +2807,13 @@@ enum i915_power_well_id 
  #define GEN9_RCS_FE_FSM2 _MMIO(0x22a4)
  
  /* Fuse readout registers for GT */
 +#define HSW_PAVP_FUSE1                        _MMIO(0x911C)
 +#define   HSW_F1_EU_DIS_SHIFT         16
 +#define   HSW_F1_EU_DIS_MASK          (0x3 << HSW_F1_EU_DIS_SHIFT)
 +#define   HSW_F1_EU_DIS_10EUS         0
 +#define   HSW_F1_EU_DIS_8EUS          1
 +#define   HSW_F1_EU_DIS_6EUS          2
 +
  #define CHV_FUSE_GT                   _MMIO(VLV_DISPLAY_BASE + 0x2168)
  #define   CHV_FGT_DISABLE_SS0         (1 << 10)
  #define   CHV_FGT_DISABLE_SS1         (1 << 11)
  # define GPIO_DATA_PULLUP_DISABLE     (1 << 13)
  
  #define GMBUS0                        _MMIO(dev_priv->gpio_mmio_base + 0x5100) /* clock/port select */
+ #define   GMBUS_AKSV_SELECT   (1<<11)
  #define   GMBUS_RATE_100KHZ   (0<<8)
  #define   GMBUS_RATE_50KHZ    (1<<8)
  #define   GMBUS_RATE_400KHZ   (2<<8) /* reserved on Pineview */
@@@ -5353,8 -5347,8 +5354,8 @@@ enum 
  #define _DPF_AUX_CH_DATA4     (dev_priv->info.display_mmio_offset + 0x64520)
  #define _DPF_AUX_CH_DATA5     (dev_priv->info.display_mmio_offset + 0x64524)
  
 -#define DP_AUX_CH_CTL(port)   _MMIO_PORT(port, _DPA_AUX_CH_CTL, _DPB_AUX_CH_CTL)
 -#define DP_AUX_CH_DATA(port, i)       _MMIO(_PORT(port, _DPA_AUX_CH_DATA1, _DPB_AUX_CH_DATA1) + (i) * 4) /* 5 registers */
 +#define DP_AUX_CH_CTL(aux_ch) _MMIO_PORT(aux_ch, _DPA_AUX_CH_CTL, _DPB_AUX_CH_CTL)
 +#define DP_AUX_CH_DATA(aux_ch, i)     _MMIO(_PORT(aux_ch, _DPA_AUX_CH_DATA1, _DPB_AUX_CH_DATA1) + (i) * 4) /* 5 registers */
  
  #define   DP_AUX_CH_CTL_SEND_BUSY         (1 << 31)
  #define   DP_AUX_CH_CTL_DONE              (1 << 30)
  #define _PCH_DPD_AUX_CH_DATA4 0xe4320
  #define _PCH_DPD_AUX_CH_DATA5 0xe4324
  
 -#define PCH_DP_AUX_CH_CTL(port)               _MMIO_PORT((port) - PORT_B, _PCH_DPB_AUX_CH_CTL, _PCH_DPC_AUX_CH_CTL)
 -#define PCH_DP_AUX_CH_DATA(port, i)   _MMIO(_PORT((port) - PORT_B, _PCH_DPB_AUX_CH_DATA1, _PCH_DPC_AUX_CH_DATA1) + (i) * 4) /* 5 registers */
 +#define PCH_DP_AUX_CH_CTL(aux_ch)             _MMIO_PORT((aux_ch) - AUX_CH_B, _PCH_DPB_AUX_CH_CTL, _PCH_DPC_AUX_CH_CTL)
 +#define PCH_DP_AUX_CH_DATA(aux_ch, i) _MMIO(_PORT((aux_ch) - AUX_CH_B, _PCH_DPB_AUX_CH_DATA1, _PCH_DPC_AUX_CH_DATA1) + (i) * 4) /* 5 registers */
  
  /* CPT */
  #define  PORT_TRANS_A_SEL_CPT 0
  #define     GEN9_MEM_LATENCY_LEVEL_1_5_SHIFT  8
  #define     GEN9_MEM_LATENCY_LEVEL_2_6_SHIFT  16
  #define     GEN9_MEM_LATENCY_LEVEL_3_7_SHIFT  24
+ #define   SKL_PCODE_LOAD_HDCP_KEYS            0x5
  #define   SKL_PCODE_CDCLK_CONTROL             0x7
  #define     SKL_CDCLK_PREPARE_FOR_CHANGE      0x3
  #define     SKL_CDCLK_READY_FOR_CHANGE                0x1
@@@ -8521,6 -8516,88 +8523,88 @@@ enum skl_power_gate 
  #define   CNL_AUX_ANAOVRD1_ENABLE     (1<<16)
  #define   CNL_AUX_ANAOVRD1_LDO_BYPASS (1<<23)
  
+ /* HDCP Key Registers */
+ #define HDCP_KEY_CONF                 _MMIO(0x66c00)
+ #define  HDCP_AKSV_SEND_TRIGGER               BIT(31)
+ #define  HDCP_CLEAR_KEYS_TRIGGER      BIT(30)
+ #define  HDCP_KEY_LOAD_TRIGGER                BIT(8)
+ #define HDCP_KEY_STATUS                       _MMIO(0x66c04)
+ #define  HDCP_FUSE_IN_PROGRESS                BIT(7)
+ #define  HDCP_FUSE_ERROR              BIT(6)
+ #define  HDCP_FUSE_DONE                       BIT(5)
+ #define  HDCP_KEY_LOAD_STATUS         BIT(1)
+ #define  HDCP_KEY_LOAD_DONE           BIT(0)
+ #define HDCP_AKSV_LO                  _MMIO(0x66c10)
+ #define HDCP_AKSV_HI                  _MMIO(0x66c14)
+ /* HDCP Repeater Registers */
+ #define HDCP_REP_CTL                  _MMIO(0x66d00)
+ #define  HDCP_DDIB_REP_PRESENT                BIT(30)
+ #define  HDCP_DDIA_REP_PRESENT                BIT(29)
+ #define  HDCP_DDIC_REP_PRESENT                BIT(28)
+ #define  HDCP_DDID_REP_PRESENT                BIT(27)
+ #define  HDCP_DDIF_REP_PRESENT                BIT(26)
+ #define  HDCP_DDIE_REP_PRESENT                BIT(25)
+ #define  HDCP_DDIB_SHA1_M0            (1 << 20)
+ #define  HDCP_DDIA_SHA1_M0            (2 << 20)
+ #define  HDCP_DDIC_SHA1_M0            (3 << 20)
+ #define  HDCP_DDID_SHA1_M0            (4 << 20)
+ #define  HDCP_DDIF_SHA1_M0            (5 << 20)
+ #define  HDCP_DDIE_SHA1_M0            (6 << 20) /* Bspec says 5? */
+ #define  HDCP_SHA1_BUSY                       BIT(16)
+ #define  HDCP_SHA1_READY              BIT(17)
+ #define  HDCP_SHA1_COMPLETE           BIT(18)
+ #define  HDCP_SHA1_V_MATCH            BIT(19)
+ #define  HDCP_SHA1_TEXT_32            (1 << 1)
+ #define  HDCP_SHA1_COMPLETE_HASH      (2 << 1)
+ #define  HDCP_SHA1_TEXT_24            (4 << 1)
+ #define  HDCP_SHA1_TEXT_16            (5 << 1)
+ #define  HDCP_SHA1_TEXT_8             (6 << 1)
+ #define  HDCP_SHA1_TEXT_0             (7 << 1)
+ #define HDCP_SHA_V_PRIME_H0           _MMIO(0x66d04)
+ #define HDCP_SHA_V_PRIME_H1           _MMIO(0x66d08)
+ #define HDCP_SHA_V_PRIME_H2           _MMIO(0x66d0C)
+ #define HDCP_SHA_V_PRIME_H3           _MMIO(0x66d10)
+ #define HDCP_SHA_V_PRIME_H4           _MMIO(0x66d14)
+ #define HDCP_SHA_V_PRIME(h)           _MMIO((0x66d04 + h * 4))
+ #define HDCP_SHA_TEXT                 _MMIO(0x66d18)
+ /* HDCP Auth Registers */
+ #define _PORTA_HDCP_AUTHENC           0x66800
+ #define _PORTB_HDCP_AUTHENC           0x66500
+ #define _PORTC_HDCP_AUTHENC           0x66600
+ #define _PORTD_HDCP_AUTHENC           0x66700
+ #define _PORTE_HDCP_AUTHENC           0x66A00
+ #define _PORTF_HDCP_AUTHENC           0x66900
+ #define _PORT_HDCP_AUTHENC(port, x)   _MMIO(_PICK(port, \
+                                         _PORTA_HDCP_AUTHENC, \
+                                         _PORTB_HDCP_AUTHENC, \
+                                         _PORTC_HDCP_AUTHENC, \
+                                         _PORTD_HDCP_AUTHENC, \
+                                         _PORTE_HDCP_AUTHENC, \
+                                         _PORTF_HDCP_AUTHENC) + x)
+ #define PORT_HDCP_CONF(port)          _PORT_HDCP_AUTHENC(port, 0x0)
+ #define  HDCP_CONF_CAPTURE_AN         BIT(0)
+ #define  HDCP_CONF_AUTH_AND_ENC               (BIT(1) | BIT(0))
+ #define PORT_HDCP_ANINIT(port)                _PORT_HDCP_AUTHENC(port, 0x4)
+ #define PORT_HDCP_ANLO(port)          _PORT_HDCP_AUTHENC(port, 0x8)
+ #define PORT_HDCP_ANHI(port)          _PORT_HDCP_AUTHENC(port, 0xC)
+ #define PORT_HDCP_BKSVLO(port)                _PORT_HDCP_AUTHENC(port, 0x10)
+ #define PORT_HDCP_BKSVHI(port)                _PORT_HDCP_AUTHENC(port, 0x14)
+ #define PORT_HDCP_RPRIME(port)                _PORT_HDCP_AUTHENC(port, 0x18)
+ #define PORT_HDCP_STATUS(port)                _PORT_HDCP_AUTHENC(port, 0x1C)
+ #define  HDCP_STATUS_STREAM_A_ENC     BIT(31)
+ #define  HDCP_STATUS_STREAM_B_ENC     BIT(30)
+ #define  HDCP_STATUS_STREAM_C_ENC     BIT(29)
+ #define  HDCP_STATUS_STREAM_D_ENC     BIT(28)
+ #define  HDCP_STATUS_AUTH             BIT(21)
+ #define  HDCP_STATUS_ENC              BIT(20)
+ #define  HDCP_STATUS_RI_MATCH         BIT(19)
+ #define  HDCP_STATUS_R0_READY         BIT(18)
+ #define  HDCP_STATUS_AN_READY         BIT(17)
+ #define  HDCP_STATUS_CIPHER           BIT(16)
+ #define  HDCP_STATUS_FRAME_CNT(x)     ((x >> 8) & 0xff)
  /* Per-pipe DDI Function Control */
  #define _TRANS_DDI_FUNC_CTL_A         0x60400
  #define _TRANS_DDI_FUNC_CTL_B         0x61400
  #define  TRANS_DDI_EDP_INPUT_A_ONOFF  (4<<12)
  #define  TRANS_DDI_EDP_INPUT_B_ONOFF  (5<<12)
  #define  TRANS_DDI_EDP_INPUT_C_ONOFF  (6<<12)
+ #define  TRANS_DDI_HDCP_SIGNALLING    (1<<9)
  #define  TRANS_DDI_DP_VC_PAYLOAD_ALLOC        (1<<8)
  #define  TRANS_DDI_HDMI_SCRAMBLER_CTS_ENABLE (1<<7)
  #define  TRANS_DDI_HDMI_SCRAMBLER_RESET_FREQ (1<<6)
@@@ -2067,18 -2067,9 +2067,18 @@@ static unsigned int intel_surf_alignmen
        }
  }
  
 +static bool intel_plane_uses_fence(const struct intel_plane_state *plane_state)
 +{
 +      struct intel_plane *plane = to_intel_plane(plane_state->base.plane);
 +      struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
 +
 +      return INTEL_GEN(dev_priv) < 4 || plane->has_fbc;
 +}
 +
  struct i915_vma *
  intel_pin_and_fence_fb_obj(struct drm_framebuffer *fb,
                           unsigned int rotation,
 +                         bool uses_fence,
                           unsigned long *out_flags)
  {
        struct drm_device *dev = fb->dev;
        if (IS_ERR(vma))
                goto err;
  
 -      if (i915_vma_is_map_and_fenceable(vma)) {
 +      if (uses_fence && i915_vma_is_map_and_fenceable(vma)) {
 +              int ret;
 +
                /* Install a fence for tiled scan-out. Pre-i965 always needs a
                 * fence, whereas 965+ only requires a fence if using
                 * framebuffer compression.  For simplicity, we always, when
                 * something and try to run the system in a "less than optimal"
                 * mode that matches the user configuration.
                 */
 -              if (i915_vma_pin_fence(vma) == 0 && vma->fence)
 +              ret = i915_vma_pin_fence(vma);
 +              if (ret != 0 && INTEL_GEN(dev_priv) < 4) {
 +                      vma = ERR_PTR(ret);
 +                      goto err;
 +              }
 +
 +              if (ret == 0 && vma->fence)
                        *out_flags |= PLANE_HAS_FENCE;
        }
  
@@@ -2845,7 -2828,6 +2845,7 @@@ valid_fb
        intel_state->vma =
                intel_pin_and_fence_fb_obj(fb,
                                           primary->state->rotation,
 +                                         intel_plane_uses_fence(intel_state),
                                           &intel_state->flags);
        mutex_unlock(&dev->struct_mutex);
        if (IS_ERR(intel_state->vma)) {
@@@ -6459,9 -6441,18 +6459,18 @@@ static int intel_crtc_compute_config(st
         * - LVDS dual channel mode
         * - Double wide pipe
         */
-       if ((intel_crtc_has_type(pipe_config, INTEL_OUTPUT_LVDS) &&
-            intel_is_dual_link_lvds(dev)) || pipe_config->double_wide)
-               pipe_config->pipe_src_w &= ~1;
+       if (pipe_config->pipe_src_w & 1) {
+               if (pipe_config->double_wide) {
+                       DRM_DEBUG_KMS("Odd pipe source width not supported with double wide pipe\n");
+                       return -EINVAL;
+               }
+               if (intel_crtc_has_type(pipe_config, INTEL_OUTPUT_LVDS) &&
+                   intel_is_dual_link_lvds(dev)) {
+                       DRM_DEBUG_KMS("Odd pipe source width not supported with dual link LVDS\n");
+                       return -EINVAL;
+               }
+       }
  
        /* Cantiga+ cannot handle modes with a hsync front porch of 0.
         * WaPruneModeWithIncorrectHsyncOffset:ctg,elk,ilk,snb,ivb,vlv,hsw.
@@@ -9398,13 -9389,18 +9407,18 @@@ static int intel_check_cursor(struct in
                              struct intel_plane_state *plane_state)
  {
        const struct drm_framebuffer *fb = plane_state->base.fb;
+       struct drm_rect clip = {};
        int src_x, src_y;
        u32 offset;
        int ret;
  
+       if (crtc_state->base.enable)
+               drm_mode_get_hv_timing(&crtc_state->base.mode,
+                                      &clip.x2, &clip.y2);
        ret = drm_atomic_helper_check_plane_state(&plane_state->base,
                                                  &crtc_state->base,
-                                                 &plane_state->clip,
+                                                 &clip,
                                                  DRM_PLANE_HELPER_NO_SCALING,
                                                  DRM_PLANE_HELPER_NO_SCALING,
                                                  true, true);
@@@ -12602,23 -12598,23 +12616,23 @@@ struct wait_rps_boost 
        struct wait_queue_entry wait;
  
        struct drm_crtc *crtc;
 -      struct drm_i915_gem_request *request;
 +      struct i915_request *request;
  };
  
  static int do_rps_boost(struct wait_queue_entry *_wait,
                        unsigned mode, int sync, void *key)
  {
        struct wait_rps_boost *wait = container_of(_wait, typeof(*wait), wait);
 -      struct drm_i915_gem_request *rq = wait->request;
 +      struct i915_request *rq = wait->request;
  
        /*
         * If we missed the vblank, but the request is already running it
         * is reasonable to assume that it will complete before the next
         * vblank without our intervention, so leave RPS alone.
         */
 -      if (!i915_gem_request_started(rq))
 +      if (!i915_request_started(rq))
                gen6_rps_boost(rq, NULL);
 -      i915_gem_request_put(rq);
 +      i915_request_put(rq);
  
        drm_crtc_vblank_put(wait->crtc);
  
@@@ -12656,42 -12652,6 +12670,42 @@@ static void add_rps_boost_after_vblank(
        add_wait_queue(drm_crtc_vblank_waitqueue(crtc), &wait->wait);
  }
  
 +static int intel_plane_pin_fb(struct intel_plane_state *plane_state)
 +{
 +      struct intel_plane *plane = to_intel_plane(plane_state->base.plane);
 +      struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
 +      struct drm_framebuffer *fb = plane_state->base.fb;
 +      struct i915_vma *vma;
 +
 +      if (plane->id == PLANE_CURSOR &&
 +          INTEL_INFO(dev_priv)->cursor_needs_physical) {
 +              struct drm_i915_gem_object *obj = intel_fb_obj(fb);
 +              const int align = intel_cursor_alignment(dev_priv);
 +
 +              return i915_gem_object_attach_phys(obj, align);
 +      }
 +
 +      vma = intel_pin_and_fence_fb_obj(fb,
 +                                       plane_state->base.rotation,
 +                                       intel_plane_uses_fence(plane_state),
 +                                       &plane_state->flags);
 +      if (IS_ERR(vma))
 +              return PTR_ERR(vma);
 +
 +      plane_state->vma = vma;
 +
 +      return 0;
 +}
 +
 +static void intel_plane_unpin_fb(struct intel_plane_state *old_plane_state)
 +{
 +      struct i915_vma *vma;
 +
 +      vma = fetch_and_zero(&old_plane_state->vma);
 +      if (vma)
 +              intel_unpin_fb_vma(vma, old_plane_state->flags);
 +}
 +
  /**
   * intel_prepare_plane_fb - Prepare fb for usage on plane
   * @plane: drm plane to prepare for
@@@ -12766,7 -12726,22 +12780,7 @@@ intel_prepare_plane_fb(struct drm_plan
                return ret;
        }
  
 -      if (plane->type == DRM_PLANE_TYPE_CURSOR &&
 -          INTEL_INFO(dev_priv)->cursor_needs_physical) {
 -              const int align = intel_cursor_alignment(dev_priv);
 -
 -              ret = i915_gem_object_attach_phys(obj, align);
 -      } else {
 -              struct i915_vma *vma;
 -
 -              vma = intel_pin_and_fence_fb_obj(fb,
 -                                               new_state->rotation,
 -                                               &to_intel_plane_state(new_state)->flags);
 -              if (!IS_ERR(vma))
 -                      to_intel_plane_state(new_state)->vma = vma;
 -              else
 -                      ret =  PTR_ERR(vma);
 -      }
 +      ret = intel_plane_pin_fb(to_intel_plane_state(new_state));
  
        i915_gem_object_wait_priority(obj, 0, I915_PRIORITY_DISPLAY);
  
  intel_cleanup_plane_fb(struct drm_plane *plane,
                       struct drm_plane_state *old_state)
  {
 -      struct i915_vma *vma;
 +      struct drm_i915_private *dev_priv = to_i915(plane->dev);
  
        /* Should only be called after a successful intel_prepare_plane_fb()! */
 -      vma = fetch_and_zero(&to_intel_plane_state(old_state)->vma);
 -      if (vma) {
 -              mutex_lock(&plane->dev->struct_mutex);
 -              intel_unpin_fb_vma(vma, to_intel_plane_state(old_state)->flags);
 -              mutex_unlock(&plane->dev->struct_mutex);
 -      }
 +      mutex_lock(&dev_priv->drm.struct_mutex);
 +      intel_plane_unpin_fb(to_intel_plane_state(old_state));
 +      mutex_unlock(&dev_priv->drm.struct_mutex);
  }
  
  int
@@@ -12861,6 -12839,7 +12875,7 @@@ intel_check_primary_plane(struct intel_
        int min_scale = DRM_PLANE_HELPER_NO_SCALING;
        int max_scale = DRM_PLANE_HELPER_NO_SCALING;
        bool can_position = false;
+       struct drm_rect clip = {};
        int ret;
  
        if (INTEL_GEN(dev_priv) >= 9) {
                can_position = true;
        }
  
+       if (crtc_state->base.enable)
+               drm_mode_get_hv_timing(&crtc_state->base.mode,
+                                      &clip.x2, &clip.y2);
        ret = drm_atomic_helper_check_plane_state(&state->base,
                                                  &crtc_state->base,
-                                                 &state->clip,
+                                                 &clip,
                                                  min_scale, max_scale,
                                                  can_position, true);
        if (ret)
@@@ -13101,6 -13084,7 +13120,6 @@@ intel_legacy_cursor_update(struct drm_p
        struct intel_plane *intel_plane = to_intel_plane(plane);
        struct drm_framebuffer *old_fb;
        struct drm_crtc_state *crtc_state = crtc->state;
 -      struct i915_vma *old_vma, *vma;
  
        /*
         * When crtc is inactive or there is a modeset pending,
        if (ret)
                goto out_free;
  
 -      if (INTEL_INFO(dev_priv)->cursor_needs_physical) {
 -              int align = intel_cursor_alignment(dev_priv);
 -
 -              ret = i915_gem_object_attach_phys(intel_fb_obj(fb), align);
 -              if (ret) {
 -                      DRM_DEBUG_KMS("failed to attach phys object\n");
 -                      goto out_unlock;
 -              }
 -      } else {
 -              vma = intel_pin_and_fence_fb_obj(fb,
 -                                               new_plane_state->rotation,
 -                                               &to_intel_plane_state(new_plane_state)->flags);
 -              if (IS_ERR(vma)) {
 -                      DRM_DEBUG_KMS("failed to pin object\n");
 -
 -                      ret = PTR_ERR(vma);
 -                      goto out_unlock;
 -              }
 -
 -              to_intel_plane_state(new_plane_state)->vma = vma;
 -      }
 +      ret = intel_plane_pin_fb(to_intel_plane_state(new_plane_state));
 +      if (ret)
 +              goto out_unlock;
  
        old_fb = old_plane_state->fb;
  
                intel_plane->disable_plane(intel_plane, to_intel_crtc(crtc));
        }
  
 -      old_vma = fetch_and_zero(&to_intel_plane_state(old_plane_state)->vma);
 -      if (old_vma)
 -              intel_unpin_fb_vma(old_vma,
 -                                 to_intel_plane_state(old_plane_state)->flags);
 +      intel_plane_unpin_fb(to_intel_plane_state(old_plane_state));
  
  out_unlock:
        mutex_unlock(&dev_priv->drm.struct_mutex);
@@@ -13209,32 -13214,6 +13228,32 @@@ static const struct drm_plane_funcs int
        .format_mod_supported = intel_cursor_plane_format_mod_supported,
  };
  
 +static bool i9xx_plane_has_fbc(struct drm_i915_private *dev_priv,
 +                             enum i9xx_plane_id i9xx_plane)
 +{
 +      if (!HAS_FBC(dev_priv))
 +              return false;
 +
 +      if (IS_BROADWELL(dev_priv) || IS_HASWELL(dev_priv))
 +              return i9xx_plane == PLANE_A; /* tied to pipe A */
 +      else if (IS_IVYBRIDGE(dev_priv))
 +              return i9xx_plane == PLANE_A || i9xx_plane == PLANE_B ||
 +                      i9xx_plane == PLANE_C;
 +      else if (INTEL_GEN(dev_priv) >= 4)
 +              return i9xx_plane == PLANE_A || i9xx_plane == PLANE_B;
 +      else
 +              return i9xx_plane == PLANE_A;
 +}
 +
 +static bool skl_plane_has_fbc(struct drm_i915_private *dev_priv,
 +                            enum pipe pipe, enum plane_id plane_id)
 +{
 +      if (!HAS_FBC(dev_priv))
 +              return false;
 +
 +      return pipe == PIPE_A && plane_id == PLANE_PRIMARY;
 +}
 +
  static struct intel_plane *
  intel_primary_plane_create(struct drm_i915_private *dev_priv, enum pipe pipe)
  {
                primary->i9xx_plane = (enum i9xx_plane_id) pipe;
        primary->id = PLANE_PRIMARY;
        primary->frontbuffer_bit = INTEL_FRONTBUFFER(pipe, primary->id);
 +
 +      if (INTEL_GEN(dev_priv) >= 9)
 +              primary->has_fbc = skl_plane_has_fbc(dev_priv,
 +                                                   primary->pipe,
 +                                                   primary->id);
 +      else
 +              primary->has_fbc = i9xx_plane_has_fbc(dev_priv,
 +                                                    primary->i9xx_plane);
 +
 +      if (primary->has_fbc) {
 +              struct intel_fbc *fbc = &dev_priv->fbc;
 +
 +              fbc->possible_framebuffer_bits |= primary->frontbuffer_bit;
 +      }
 +
        primary->check_plane = intel_check_primary_plane;
  
        if (INTEL_GEN(dev_priv) >= 9) {
@@@ -14196,10 -14160,37 +14215,37 @@@ static void intel_atomic_state_free(str
        kfree(state);
  }
  
+ static enum drm_mode_status
+ intel_mode_valid(struct drm_device *dev,
+                const struct drm_display_mode *mode)
+ {
+       if (mode->vscan > 1)
+               return MODE_NO_VSCAN;
+       if (mode->flags & DRM_MODE_FLAG_DBLSCAN)
+               return MODE_NO_DBLESCAN;
+       if (mode->flags & DRM_MODE_FLAG_HSKEW)
+               return MODE_H_ILLEGAL;
+       if (mode->flags & (DRM_MODE_FLAG_CSYNC |
+                          DRM_MODE_FLAG_NCSYNC |
+                          DRM_MODE_FLAG_PCSYNC))
+               return MODE_HSYNC;
+       if (mode->flags & (DRM_MODE_FLAG_BCAST |
+                          DRM_MODE_FLAG_PIXMUX |
+                          DRM_MODE_FLAG_CLKDIV2))
+               return MODE_BAD;
+       return MODE_OK;
+ }
  static const struct drm_mode_config_funcs intel_mode_funcs = {
        .fb_create = intel_user_framebuffer_create,
        .get_format_info = intel_get_format_info,
        .output_poll_changed = intel_fbdev_output_poll_changed,
+       .mode_valid = intel_mode_valid,
        .atomic_check = intel_atomic_check,
        .atomic_commit = intel_atomic_commit,
        .atomic_state_alloc = intel_atomic_state_alloc,
@@@ -15350,6 -15341,10 +15396,10 @@@ static void intel_hpd_poll_fini(struct 
        for_each_intel_connector_iter(connector, &conn_iter) {
                if (connector->modeset_retry_work.func)
                        cancel_work_sync(&connector->modeset_retry_work);
+               if (connector->hdcp_shim) {
+                       cancel_delayed_work_sync(&connector->hdcp_check_work);
+                       cancel_work_sync(&connector->hdcp_prop_work);
+               }
        }
        drm_connector_list_iter_end(&conn_iter);
  }
@@@ -36,7 -36,9 +36,9 @@@
  #include <drm/drm_atomic_helper.h>
  #include <drm/drm_crtc.h>
  #include <drm/drm_crtc_helper.h>
+ #include <drm/drm_dp_helper.h>
  #include <drm/drm_edid.h>
+ #include <drm/drm_hdcp.h>
  #include "intel_drv.h"
  #include <drm/i915_drm.h>
  #include "i915_drv.h"
@@@ -94,6 -96,15 +96,6 @@@ static const struct dp_link_dpll chv_dp
                { .p1 = 2, .p2 = 1, .n = 1, .m1 = 2, .m2 = 0x6c00000 } }
  };
  
 -static const int bxt_rates[] = { 162000, 216000, 243000, 270000,
 -                                324000, 432000, 540000 };
 -static const int skl_rates[] = { 162000, 216000, 270000,
 -                                324000, 432000, 540000 };
 -static const int cnl_rates[] = { 162000, 216000, 270000,
 -                               324000, 432000, 540000,
 -                               648000, 810000 };
 -static const int default_rates[] = { 162000, 270000, 540000 };
 -
  /**
   * intel_dp_is_edp - is the given port attached to an eDP panel (either CPU or PCH)
   * @intel_dp: DP struct
@@@ -133,17 -144,14 +135,17 @@@ static void intel_dp_unset_edid(struct 
  /* update sink rates from dpcd */
  static void intel_dp_set_sink_rates(struct intel_dp *intel_dp)
  {
 +      static const int dp_rates[] = {
 +              162000, 270000, 540000, 810000
 +      };
        int i, max_rate;
  
        max_rate = drm_dp_bw_code_to_link_rate(intel_dp->dpcd[DP_MAX_LINK_RATE]);
  
 -      for (i = 0; i < ARRAY_SIZE(default_rates); i++) {
 -              if (default_rates[i] > max_rate)
 +      for (i = 0; i < ARRAY_SIZE(dp_rates); i++) {
 +              if (dp_rates[i] > max_rate)
                        break;
 -              intel_dp->sink_rates[i] = default_rates[i];
 +              intel_dp->sink_rates[i] = dp_rates[i];
        }
  
        intel_dp->num_sink_rates = i;
@@@ -260,22 -268,6 +262,22 @@@ static int cnl_max_source_rate(struct i
  static void
  intel_dp_set_source_rates(struct intel_dp *intel_dp)
  {
 +      /* The values must be in increasing order */
 +      static const int cnl_rates[] = {
 +              162000, 216000, 270000, 324000, 432000, 540000, 648000, 810000
 +      };
 +      static const int bxt_rates[] = {
 +              162000, 216000, 243000, 270000, 324000, 432000, 540000
 +      };
 +      static const int skl_rates[] = {
 +              162000, 216000, 270000, 324000, 432000, 540000
 +      };
 +      static const int hsw_rates[] = {
 +              162000, 270000, 540000
 +      };
 +      static const int g4x_rates[] = {
 +              162000, 270000
 +      };
        struct intel_digital_port *dig_port = dp_to_dig_port(intel_dp);
        struct drm_i915_private *dev_priv = to_i915(dig_port->base.base.dev);
        const struct ddi_vbt_port_info *info =
        /* This should only be done once */
        WARN_ON(intel_dp->source_rates || intel_dp->num_source_rates);
  
 -      if (IS_GEN9_LP(dev_priv)) {
 -              source_rates = bxt_rates;
 -              size = ARRAY_SIZE(bxt_rates);
 -      } else if (IS_CANNONLAKE(dev_priv)) {
 +      if (IS_CANNONLAKE(dev_priv)) {
                source_rates = cnl_rates;
                size = ARRAY_SIZE(cnl_rates);
                max_rate = cnl_max_source_rate(intel_dp);
 +      } else if (IS_GEN9_LP(dev_priv)) {
 +              source_rates = bxt_rates;
 +              size = ARRAY_SIZE(bxt_rates);
        } else if (IS_GEN9_BC(dev_priv)) {
                source_rates = skl_rates;
                size = ARRAY_SIZE(skl_rates);
        } else if ((IS_HASWELL(dev_priv) && !IS_HSW_ULX(dev_priv)) ||
                   IS_BROADWELL(dev_priv)) {
 -              source_rates = default_rates;
 -              size = ARRAY_SIZE(default_rates);
 +              source_rates = hsw_rates;
 +              size = ARRAY_SIZE(hsw_rates);
        } else {
 -              source_rates = default_rates;
 -              size = ARRAY_SIZE(default_rates) - 1;
 +              source_rates = g4x_rates;
 +              size = ARRAY_SIZE(g4x_rates);
        }
  
        if (max_rate && vbt_max_rate)
@@@ -364,7 -356,7 +366,7 @@@ static void intel_dp_set_common_rates(s
  
        /* Paranoia, there should always be something in common. */
        if (WARN_ON(intel_dp->num_common_rates == 0)) {
 -              intel_dp->common_rates[0] = default_rates[0];
 +              intel_dp->common_rates[0] = 162000;
                intel_dp->num_common_rates = 1;
        }
  }
@@@ -664,15 -656,19 +666,15 @@@ static in
  bxt_power_sequencer_idx(struct intel_dp *intel_dp)
  {
        struct drm_i915_private *dev_priv = to_i915(intel_dp_to_dev(intel_dp));
 +      int backlight_controller = dev_priv->vbt.backlight.controller;
  
        lockdep_assert_held(&dev_priv->pps_mutex);
  
        /* We should never land here with regular DP ports */
        WARN_ON(!intel_dp_is_edp(intel_dp));
  
 -      /*
 -       * TODO: BXT has 2 PPS instances. The correct port->PPS instance
 -       * mapping needs to be retrieved from VBT, for now just hard-code to
 -       * use instance #0 always.
 -       */
        if (!intel_dp->pps_reset)
 -              return 0;
 +              return backlight_controller;
  
        intel_dp->pps_reset = false;
  
         */
        intel_dp_init_panel_power_sequencer_registers(intel_dp, false);
  
 -      return 0;
 +      return backlight_controller;
  }
  
  typedef bool (*vlv_pipe_check)(struct drm_i915_private *dev_priv,
@@@ -940,7 -936,7 +942,7 @@@ static uint32_
  intel_dp_aux_wait_done(struct intel_dp *intel_dp, bool has_aux_irq)
  {
        struct drm_i915_private *dev_priv = to_i915(intel_dp_to_dev(intel_dp));
 -      i915_reg_t ch_ctl = intel_dp->aux_ch_ctl_reg;
 +      i915_reg_t ch_ctl = intel_dp->aux_ch_ctl_reg(intel_dp);
        uint32_t status;
        bool done;
  
  
  static uint32_t g4x_get_aux_clock_divider(struct intel_dp *intel_dp, int index)
  {
 -      struct intel_digital_port *intel_dig_port = dp_to_dig_port(intel_dp);
 -      struct drm_i915_private *dev_priv = to_i915(intel_dig_port->base.base.dev);
 +      struct drm_i915_private *dev_priv = to_i915(intel_dp_to_dev(intel_dp));
  
        if (index)
                return 0;
  
  static uint32_t ilk_get_aux_clock_divider(struct intel_dp *intel_dp, int index)
  {
 -      struct intel_digital_port *intel_dig_port = dp_to_dig_port(intel_dp);
 -      struct drm_i915_private *dev_priv = to_i915(intel_dig_port->base.base.dev);
 +      struct drm_i915_private *dev_priv = to_i915(intel_dp_to_dev(intel_dp));
  
        if (index)
                return 0;
         * like to run at 2MHz.  So, take the cdclk or PCH rawclk value and
         * divide by 2000 and use that
         */
 -      if (intel_dig_port->base.port == PORT_A)
 +      if (intel_dp->aux_ch == AUX_CH_A)
                return DIV_ROUND_CLOSEST(dev_priv->cdclk.hw.cdclk, 2000);
        else
                return DIV_ROUND_CLOSEST(dev_priv->rawclk_freq, 2000);
  
  static uint32_t hsw_get_aux_clock_divider(struct intel_dp *intel_dp, int index)
  {
 -      struct intel_digital_port *intel_dig_port = dp_to_dig_port(intel_dp);
 -      struct drm_i915_private *dev_priv = to_i915(intel_dig_port->base.base.dev);
 +      struct drm_i915_private *dev_priv = to_i915(intel_dp_to_dev(intel_dp));
  
 -      if (intel_dig_port->base.port != PORT_A && HAS_PCH_LPT_H(dev_priv)) {
 +      if (intel_dp->aux_ch != AUX_CH_A && HAS_PCH_LPT_H(dev_priv)) {
                /* Workaround for non-ULT HSW */
                switch (index) {
                case 0: return 63;
@@@ -1063,15 -1062,34 +1065,34 @@@ static uint32_t skl_get_aux_send_ctl(st
               DP_AUX_CH_CTL_SYNC_PULSE_SKL(32);
  }
  
+ static uint32_t intel_dp_get_aux_send_ctl(struct intel_dp *intel_dp,
+                                         bool has_aux_irq,
+                                         int send_bytes,
+                                         uint32_t aux_clock_divider,
+                                         bool aksv_write)
+ {
+       uint32_t val = 0;
+       if (aksv_write) {
+               send_bytes += 5;
+               val |= DP_AUX_CH_CTL_AUX_AKSV_SELECT;
+       }
+       return val | intel_dp->get_aux_send_ctl(intel_dp,
+                                               has_aux_irq,
+                                               send_bytes,
+                                               aux_clock_divider);
+ }
  static int
  intel_dp_aux_ch(struct intel_dp *intel_dp,
                const uint8_t *send, int send_bytes,
-               uint8_t *recv, int recv_size)
+               uint8_t *recv, int recv_size, bool aksv_write)
  {
        struct intel_digital_port *intel_dig_port = dp_to_dig_port(intel_dp);
        struct drm_i915_private *dev_priv =
                        to_i915(intel_dig_port->base.base.dev);
 -      i915_reg_t ch_ctl = intel_dp->aux_ch_ctl_reg;
 +      i915_reg_t ch_ctl, ch_data[5];
        uint32_t aux_clock_divider;
        int i, ret, recv_bytes;
        uint32_t status;
        bool has_aux_irq = HAS_AUX_IRQ(dev_priv);
        bool vdd;
  
 +      ch_ctl = intel_dp->aux_ch_ctl_reg(intel_dp);
 +      for (i = 0; i < ARRAY_SIZE(ch_data); i++)
 +              ch_data[i] = intel_dp->aux_ch_data_reg(intel_dp, i);
 +
        pps_lock(intel_dp);
  
        /*
        }
  
        while ((aux_clock_divider = intel_dp->get_aux_clock_divider(intel_dp, clock++))) {
-               u32 send_ctl = intel_dp->get_aux_send_ctl(intel_dp,
-                                                         has_aux_irq,
-                                                         send_bytes,
-                                                         aux_clock_divider);
+               u32 send_ctl = intel_dp_get_aux_send_ctl(intel_dp,
+                                                        has_aux_irq,
+                                                        send_bytes,
+                                                        aux_clock_divider,
+                                                        aksv_write);
  
                /* Must try at least 3 times according to DP spec */
                for (try = 0; try < 5; try++) {
                        /* Load the send data into the aux channel data registers */
                        for (i = 0; i < send_bytes; i += 4)
 -                              I915_WRITE(intel_dp->aux_ch_data_reg[i >> 2],
 +                              I915_WRITE(ch_data[i >> 2],
                                           intel_dp_pack_aux(send + i,
                                                             send_bytes - i));
  
                                   DP_AUX_CH_CTL_TIME_OUT_ERROR |
                                   DP_AUX_CH_CTL_RECEIVE_ERROR);
  
 -                      if (status & DP_AUX_CH_CTL_TIME_OUT_ERROR)
 -                              continue;
 -
                        /* DP CTS 1.2 Core Rev 1.1, 4.2.1.1 & 4.2.1.2
                         *   400us delay required for errors and timeouts
                         *   Timeout errors from the HW already meet this
                         *   requirement so skip to next iteration
                         */
 +                      if (status & DP_AUX_CH_CTL_TIME_OUT_ERROR)
 +                              continue;
 +
                        if (status & DP_AUX_CH_CTL_RECEIVE_ERROR) {
                                usleep_range(400, 500);
                                continue;
@@@ -1208,6 -1223,14 +1230,6 @@@ done
        if (recv_bytes == 0 || recv_bytes > 20) {
                DRM_DEBUG_KMS("Forbidden recv_bytes = %d on aux transaction\n",
                              recv_bytes);
 -              /*
 -               * FIXME: This patch was created on top of a series that
 -               * organize the retries at drm level. There EBUSY should
 -               * also take care for 1ms wait before retrying.
 -               * That aux retries re-org is still needed and after that is
 -               * merged we remove this sleep from here.
 -               */
 -              usleep_range(1000, 1500);
                ret = -EBUSY;
                goto out;
        }
                recv_bytes = recv_size;
  
        for (i = 0; i < recv_bytes; i += 4)
 -              intel_dp_unpack_aux(I915_READ(intel_dp->aux_ch_data_reg[i >> 2]),
 +              intel_dp_unpack_aux(I915_READ(ch_data[i >> 2]),
                                    recv + i, recv_bytes - i);
  
        ret = recv_bytes;
@@@ -1262,7 -1285,8 +1284,8 @@@ intel_dp_aux_transfer(struct drm_dp_au
                if (msg->buffer)
                        memcpy(txbuf + HEADER_SIZE, msg->buffer, msg->size);
  
-               ret = intel_dp_aux_ch(intel_dp, txbuf, txsize, rxbuf, rxsize);
+               ret = intel_dp_aux_ch(intel_dp, txbuf, txsize, rxbuf, rxsize,
+                                     false);
                if (ret > 0) {
                        msg->reply = rxbuf[0] >> 4;
  
                if (WARN_ON(rxsize > 20))
                        return -E2BIG;
  
-               ret = intel_dp_aux_ch(intel_dp, txbuf, txsize, rxbuf, rxsize);
+               ret = intel_dp_aux_ch(intel_dp, txbuf, txsize, rxbuf, rxsize,
+                                     false);
                if (ret > 0) {
                        msg->reply = rxbuf[0] >> 4;
                        /*
        return ret;
  }
  
 -static enum port intel_aux_port(struct drm_i915_private *dev_priv,
 -                              enum port port)
 +static enum aux_ch intel_aux_ch(struct intel_dp *intel_dp)
  {
 +      struct intel_encoder *encoder = &dp_to_dig_port(intel_dp)->base;
 +      struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
 +      enum port port = encoder->port;
        const struct ddi_vbt_port_info *info =
                &dev_priv->vbt.ddi_port_info[port];
 -      enum port aux_port;
 +      enum aux_ch aux_ch;
  
        if (!info->alternate_aux_channel) {
 +              aux_ch = (enum aux_ch) port;
 +
                DRM_DEBUG_KMS("using AUX %c for port %c (platform default)\n",
 -                            port_name(port), port_name(port));
 -              return port;
 +                            aux_ch_name(aux_ch), port_name(port));
 +              return aux_ch;
        }
  
        switch (info->alternate_aux_channel) {
        case DP_AUX_A:
 -              aux_port = PORT_A;
 +              aux_ch = AUX_CH_A;
                break;
        case DP_AUX_B:
 -              aux_port = PORT_B;
 +              aux_ch = AUX_CH_B;
                break;
        case DP_AUX_C:
 -              aux_port = PORT_C;
 +              aux_ch = AUX_CH_C;
                break;
        case DP_AUX_D:
 -              aux_port = PORT_D;
 +              aux_ch = AUX_CH_D;
                break;
        case DP_AUX_F:
 -              aux_port = PORT_F;
 +              aux_ch = AUX_CH_F;
                break;
        default:
                MISSING_CASE(info->alternate_aux_channel);
 -              aux_port = PORT_A;
 +              aux_ch = AUX_CH_A;
                break;
        }
  
        DRM_DEBUG_KMS("using AUX %c for port %c (VBT)\n",
 -                    port_name(aux_port), port_name(port));
 +                    aux_ch_name(aux_ch), port_name(port));
  
 -      return aux_port;
 +      return aux_ch;
  }
  
 -static i915_reg_t g4x_aux_ctl_reg(struct drm_i915_private *dev_priv,
 -                                enum port port)
 +static enum intel_display_power_domain
 +intel_aux_power_domain(struct intel_dp *intel_dp)
  {
 -      switch (port) {
 -      case PORT_B:
 -      case PORT_C:
 -      case PORT_D:
 -              return DP_AUX_CH_CTL(port);
 +      switch (intel_dp->aux_ch) {
 +      case AUX_CH_A:
 +              return POWER_DOMAIN_AUX_A;
 +      case AUX_CH_B:
 +              return POWER_DOMAIN_AUX_B;
 +      case AUX_CH_C:
 +              return POWER_DOMAIN_AUX_C;
 +      case AUX_CH_D:
 +              return POWER_DOMAIN_AUX_D;
 +      case AUX_CH_F:
 +              return POWER_DOMAIN_AUX_F;
        default:
 -              MISSING_CASE(port);
 -              return DP_AUX_CH_CTL(PORT_B);
 +              MISSING_CASE(intel_dp->aux_ch);
 +              return POWER_DOMAIN_AUX_A;
        }
  }
  
 -static i915_reg_t g4x_aux_data_reg(struct drm_i915_private *dev_priv,
 -                                 enum port port, int index)
 +static i915_reg_t g4x_aux_ctl_reg(struct intel_dp *intel_dp)
  {
 -      switch (port) {
 -      case PORT_B:
 -      case PORT_C:
 -      case PORT_D:
 -              return DP_AUX_CH_DATA(port, index);
 +      struct drm_i915_private *dev_priv = to_i915(intel_dp_to_dev(intel_dp));
 +      enum aux_ch aux_ch = intel_dp->aux_ch;
 +
 +      switch (aux_ch) {
 +      case AUX_CH_B:
 +      case AUX_CH_C:
 +      case AUX_CH_D:
 +              return DP_AUX_CH_CTL(aux_ch);
        default:
 -              MISSING_CASE(port);
 -              return DP_AUX_CH_DATA(PORT_B, index);
 +              MISSING_CASE(aux_ch);
 +              return DP_AUX_CH_CTL(AUX_CH_B);
        }
  }
  
 -static i915_reg_t ilk_aux_ctl_reg(struct drm_i915_private *dev_priv,
 -                                enum port port)
 +static i915_reg_t g4x_aux_data_reg(struct intel_dp *intel_dp, int index)
  {
 -      switch (port) {
 -      case PORT_A:
 -              return DP_AUX_CH_CTL(port);
 -      case PORT_B:
 -      case PORT_C:
 -      case PORT_D:
 -              return PCH_DP_AUX_CH_CTL(port);
 +      struct drm_i915_private *dev_priv = to_i915(intel_dp_to_dev(intel_dp));
 +      enum aux_ch aux_ch = intel_dp->aux_ch;
 +
 +      switch (aux_ch) {
 +      case AUX_CH_B:
 +      case AUX_CH_C:
 +      case AUX_CH_D:
 +              return DP_AUX_CH_DATA(aux_ch, index);
        default:
 -              MISSING_CASE(port);
 -              return DP_AUX_CH_CTL(PORT_A);
 +              MISSING_CASE(aux_ch);
 +              return DP_AUX_CH_DATA(AUX_CH_B, index);
        }
  }
  
 -static i915_reg_t ilk_aux_data_reg(struct drm_i915_private *dev_priv,
 -                                 enum port port, int index)
 +static i915_reg_t ilk_aux_ctl_reg(struct intel_dp *intel_dp)
  {
 -      switch (port) {
 -      case PORT_A:
 -              return DP_AUX_CH_DATA(port, index);
 -      case PORT_B:
 -      case PORT_C:
 -      case PORT_D:
 -              return PCH_DP_AUX_CH_DATA(port, index);
 +      struct drm_i915_private *dev_priv = to_i915(intel_dp_to_dev(intel_dp));
 +      enum aux_ch aux_ch = intel_dp->aux_ch;
 +
 +      switch (aux_ch) {
 +      case AUX_CH_A:
 +              return DP_AUX_CH_CTL(aux_ch);
 +      case AUX_CH_B:
 +      case AUX_CH_C:
 +      case AUX_CH_D:
 +              return PCH_DP_AUX_CH_CTL(aux_ch);
        default:
 -              MISSING_CASE(port);
 -              return DP_AUX_CH_DATA(PORT_A, index);
 +              MISSING_CASE(aux_ch);
 +              return DP_AUX_CH_CTL(AUX_CH_A);
        }
  }
  
 -static i915_reg_t skl_aux_ctl_reg(struct drm_i915_private *dev_priv,
 -                                enum port port)
 +static i915_reg_t ilk_aux_data_reg(struct intel_dp *intel_dp, int index)
  {
 -      switch (port) {
 -      case PORT_A:
 -      case PORT_B:
 -      case PORT_C:
 -      case PORT_D:
 -      case PORT_F:
 -              return DP_AUX_CH_CTL(port);
 +      struct drm_i915_private *dev_priv = to_i915(intel_dp_to_dev(intel_dp));
 +      enum aux_ch aux_ch = intel_dp->aux_ch;
 +
 +      switch (aux_ch) {
 +      case AUX_CH_A:
 +              return DP_AUX_CH_DATA(aux_ch, index);
 +      case AUX_CH_B:
 +      case AUX_CH_C:
 +      case AUX_CH_D:
 +              return PCH_DP_AUX_CH_DATA(aux_ch, index);
        default:
 -              MISSING_CASE(port);
 -              return DP_AUX_CH_CTL(PORT_A);
 +              MISSING_CASE(aux_ch);
 +              return DP_AUX_CH_DATA(AUX_CH_A, index);
        }
  }
  
 -static i915_reg_t skl_aux_data_reg(struct drm_i915_private *dev_priv,
 -                                 enum port port, int index)
 +static i915_reg_t skl_aux_ctl_reg(struct intel_dp *intel_dp)
  {
 -      switch (port) {
 -      case PORT_A:
 -      case PORT_B:
 -      case PORT_C:
 -      case PORT_D:
 -      case PORT_F:
 -              return DP_AUX_CH_DATA(port, index);
 +      struct drm_i915_private *dev_priv = to_i915(intel_dp_to_dev(intel_dp));
 +      enum aux_ch aux_ch = intel_dp->aux_ch;
 +
 +      switch (aux_ch) {
 +      case AUX_CH_A:
 +      case AUX_CH_B:
 +      case AUX_CH_C:
 +      case AUX_CH_D:
 +      case AUX_CH_F:
 +              return DP_AUX_CH_CTL(aux_ch);
        default:
 -              MISSING_CASE(port);
 -              return DP_AUX_CH_DATA(PORT_A, index);
 +              MISSING_CASE(aux_ch);
 +              return DP_AUX_CH_CTL(AUX_CH_A);
        }
  }
  
 -static i915_reg_t intel_aux_ctl_reg(struct drm_i915_private *dev_priv,
 -                                  enum port port)
 -{
 -      if (INTEL_GEN(dev_priv) >= 9)
 -              return skl_aux_ctl_reg(dev_priv, port);
 -      else if (HAS_PCH_SPLIT(dev_priv))
 -              return ilk_aux_ctl_reg(dev_priv, port);
 -      else
 -              return g4x_aux_ctl_reg(dev_priv, port);
 -}
 -
 -static i915_reg_t intel_aux_data_reg(struct drm_i915_private *dev_priv,
 -                                   enum port port, int index)
 -{
 -      if (INTEL_GEN(dev_priv) >= 9)
 -              return skl_aux_data_reg(dev_priv, port, index);
 -      else if (HAS_PCH_SPLIT(dev_priv))
 -              return ilk_aux_data_reg(dev_priv, port, index);
 -      else
 -              return g4x_aux_data_reg(dev_priv, port, index);
 -}
 -
 -static void intel_aux_reg_init(struct intel_dp *intel_dp)
 +static i915_reg_t skl_aux_data_reg(struct intel_dp *intel_dp, int index)
  {
        struct drm_i915_private *dev_priv = to_i915(intel_dp_to_dev(intel_dp));
 -      enum port port = intel_aux_port(dev_priv,
 -                                      dp_to_dig_port(intel_dp)->base.port);
 -      int i;
 -
 -      intel_dp->aux_ch_ctl_reg = intel_aux_ctl_reg(dev_priv, port);
 -      for (i = 0; i < ARRAY_SIZE(intel_dp->aux_ch_data_reg); i++)
 -              intel_dp->aux_ch_data_reg[i] = intel_aux_data_reg(dev_priv, port, i);
 +      enum aux_ch aux_ch = intel_dp->aux_ch;
 +
 +      switch (aux_ch) {
 +      case AUX_CH_A:
 +      case AUX_CH_B:
 +      case AUX_CH_C:
 +      case AUX_CH_D:
 +      case AUX_CH_F:
 +              return DP_AUX_CH_DATA(aux_ch, index);
 +      default:
 +              MISSING_CASE(aux_ch);
 +              return DP_AUX_CH_DATA(AUX_CH_A, index);
 +      }
  }
  
  static void
@@@ -1484,42 -1507,14 +1508,42 @@@ intel_dp_aux_fini(struct intel_dp *inte
  static void
  intel_dp_aux_init(struct intel_dp *intel_dp)
  {
 -      struct intel_digital_port *intel_dig_port = dp_to_dig_port(intel_dp);
 -      enum port port = intel_dig_port->base.port;
 +      struct drm_i915_private *dev_priv = to_i915(intel_dp_to_dev(intel_dp));
 +      struct intel_encoder *encoder = &dp_to_dig_port(intel_dp)->base;
 +
 +      intel_dp->aux_ch = intel_aux_ch(intel_dp);
 +      intel_dp->aux_power_domain = intel_aux_power_domain(intel_dp);
 +
 +      if (INTEL_GEN(dev_priv) >= 9) {
 +              intel_dp->aux_ch_ctl_reg = skl_aux_ctl_reg;
 +              intel_dp->aux_ch_data_reg = skl_aux_data_reg;
 +      } else if (HAS_PCH_SPLIT(dev_priv)) {
 +              intel_dp->aux_ch_ctl_reg = ilk_aux_ctl_reg;
 +              intel_dp->aux_ch_data_reg = ilk_aux_data_reg;
 +      } else {
 +              intel_dp->aux_ch_ctl_reg = g4x_aux_ctl_reg;
 +              intel_dp->aux_ch_data_reg = g4x_aux_data_reg;
 +      }
 +
 +      if (INTEL_GEN(dev_priv) >= 9)
 +              intel_dp->get_aux_clock_divider = skl_get_aux_clock_divider;
 +      else if (IS_BROADWELL(dev_priv) || IS_HASWELL(dev_priv))
 +              intel_dp->get_aux_clock_divider = hsw_get_aux_clock_divider;
 +      else if (HAS_PCH_SPLIT(dev_priv))
 +              intel_dp->get_aux_clock_divider = ilk_get_aux_clock_divider;
 +      else
 +              intel_dp->get_aux_clock_divider = g4x_get_aux_clock_divider;
 +
 +      if (INTEL_GEN(dev_priv) >= 9)
 +              intel_dp->get_aux_send_ctl = skl_get_aux_send_ctl;
 +      else
 +              intel_dp->get_aux_send_ctl = g4x_get_aux_send_ctl;
  
 -      intel_aux_reg_init(intel_dp);
        drm_dp_aux_init(&intel_dp->aux);
  
        /* Failure to allocate our preferred name is not critical */
 -      intel_dp->aux.name = kasprintf(GFP_KERNEL, "DPDDC-%c", port_name(port));
 +      intel_dp->aux.name = kasprintf(GFP_KERNEL, "DPDDC-%c",
 +                                     port_name(encoder->port));
        intel_dp->aux.transfer = intel_dp_aux_transfer;
  }
  
@@@ -3177,6 -3172,35 +3201,6 @@@ intel_dp_get_link_status(struct intel_d
                                DP_LINK_STATUS_SIZE) == DP_LINK_STATUS_SIZE;
  }
  
 -static bool intel_dp_get_y_cord_status(struct intel_dp *intel_dp)
 -{
 -      uint8_t psr_caps = 0;
 -
 -      if (drm_dp_dpcd_readb(&intel_dp->aux, DP_PSR_CAPS, &psr_caps) != 1)
 -              return false;
 -      return psr_caps & DP_PSR2_SU_Y_COORDINATE_REQUIRED;
 -}
 -
 -static bool intel_dp_get_colorimetry_status(struct intel_dp *intel_dp)
 -{
 -      uint8_t dprx = 0;
 -
 -      if (drm_dp_dpcd_readb(&intel_dp->aux, DP_DPRX_FEATURE_ENUMERATION_LIST,
 -                            &dprx) != 1)
 -              return false;
 -      return dprx & DP_VSC_SDP_EXT_FOR_COLORIMETRY_SUPPORTED;
 -}
 -
 -static bool intel_dp_get_alpm_status(struct intel_dp *intel_dp)
 -{
 -      uint8_t alpm_caps = 0;
 -
 -      if (drm_dp_dpcd_readb(&intel_dp->aux, DP_RECEIVER_ALPM_CAP,
 -                            &alpm_caps) != 1)
 -              return false;
 -      return alpm_caps & DP_ALPM_CAP;
 -}
 -
  /* These are source-specific values. */
  uint8_t
  intel_dp_voltage_max(struct intel_dp *intel_dp)
@@@ -3727,7 -3751,40 +3751,7 @@@ intel_edp_init_dpcd(struct intel_dp *in
                dev_priv->no_aux_handshake = intel_dp->dpcd[DP_MAX_DOWNSPREAD] &
                        DP_NO_AUX_HANDSHAKE_LINK_TRAINING;
  
 -      /* Check if the panel supports PSR */
 -      drm_dp_dpcd_read(&intel_dp->aux, DP_PSR_SUPPORT,
 -                       intel_dp->psr_dpcd,
 -                       sizeof(intel_dp->psr_dpcd));
 -      if (intel_dp->psr_dpcd[0] & DP_PSR_IS_SUPPORTED) {
 -              dev_priv->psr.sink_support = true;
 -              DRM_DEBUG_KMS("Detected EDP PSR Panel.\n");
 -      }
 -
 -      if (INTEL_GEN(dev_priv) >= 9 &&
 -          (intel_dp->psr_dpcd[0] & DP_PSR2_IS_SUPPORTED)) {
 -              uint8_t frame_sync_cap;
 -
 -              dev_priv->psr.sink_support = true;
 -              if (drm_dp_dpcd_readb(&intel_dp->aux,
 -                                    DP_SINK_DEVICE_AUX_FRAME_SYNC_CAP,
 -                                    &frame_sync_cap) != 1)
 -                      frame_sync_cap = 0;
 -              dev_priv->psr.aux_frame_sync = frame_sync_cap ? true : false;
 -              /* PSR2 needs frame sync as well */
 -              dev_priv->psr.psr2_support = dev_priv->psr.aux_frame_sync;
 -              DRM_DEBUG_KMS("PSR2 %s on sink",
 -                            dev_priv->psr.psr2_support ? "supported" : "not supported");
 -
 -              if (dev_priv->psr.psr2_support) {
 -                      dev_priv->psr.y_cord_support =
 -                              intel_dp_get_y_cord_status(intel_dp);
 -                      dev_priv->psr.colorimetry_support =
 -                              intel_dp_get_colorimetry_status(intel_dp);
 -                      dev_priv->psr.alpm =
 -                              intel_dp_get_alpm_status(intel_dp);
 -              }
 -
 -      }
 +      intel_psr_init_dpcd(intel_dp);
  
        /*
         * Read the eDP display control registers.
@@@ -4992,6 -5049,236 +5016,236 @@@ void intel_dp_encoder_suspend(struct in
        pps_unlock(intel_dp);
  }
  
+ static
+ int intel_dp_hdcp_write_an_aksv(struct intel_digital_port *intel_dig_port,
+                               u8 *an)
+ {
+       struct intel_dp *intel_dp = enc_to_intel_dp(&intel_dig_port->base.base);
+       uint8_t txbuf[4], rxbuf[2], reply = 0;
+       ssize_t dpcd_ret;
+       int ret;
+       /* Output An first, that's easy */
+       dpcd_ret = drm_dp_dpcd_write(&intel_dig_port->dp.aux, DP_AUX_HDCP_AN,
+                                    an, DRM_HDCP_AN_LEN);
+       if (dpcd_ret != DRM_HDCP_AN_LEN) {
+               DRM_ERROR("Failed to write An over DP/AUX (%zd)\n", dpcd_ret);
+               return dpcd_ret >= 0 ? -EIO : dpcd_ret;
+       }
+       /*
+        * Since Aksv is Oh-So-Secret, we can't access it in software. So in
+        * order to get it on the wire, we need to create the AUX header as if
+        * we were writing the data, and then tickle the hardware to output the
+        * data once the header is sent out.
+        */
+       txbuf[0] = (DP_AUX_NATIVE_WRITE << 4) |
+                  ((DP_AUX_HDCP_AKSV >> 16) & 0xf);
+       txbuf[1] = (DP_AUX_HDCP_AKSV >> 8) & 0xff;
+       txbuf[2] = DP_AUX_HDCP_AKSV & 0xff;
+       txbuf[3] = DRM_HDCP_KSV_LEN - 1;
+       ret = intel_dp_aux_ch(intel_dp, txbuf, sizeof(txbuf), rxbuf,
+                             sizeof(rxbuf), true);
+       if (ret < 0) {
+               DRM_ERROR("Write Aksv over DP/AUX failed (%d)\n", ret);
+               return ret;
+       } else if (ret == 0) {
+               DRM_ERROR("Aksv write over DP/AUX was empty\n");
+               return -EIO;
+       }
+       reply = (rxbuf[0] >> 4) & DP_AUX_NATIVE_REPLY_MASK;
+       return reply == DP_AUX_NATIVE_REPLY_ACK ? 0 : -EIO;
+ }
+ static int intel_dp_hdcp_read_bksv(struct intel_digital_port *intel_dig_port,
+                                  u8 *bksv)
+ {
+       ssize_t ret;
+       ret = drm_dp_dpcd_read(&intel_dig_port->dp.aux, DP_AUX_HDCP_BKSV, bksv,
+                              DRM_HDCP_KSV_LEN);
+       if (ret != DRM_HDCP_KSV_LEN) {
+               DRM_ERROR("Read Bksv from DP/AUX failed (%zd)\n", ret);
+               return ret >= 0 ? -EIO : ret;
+       }
+       return 0;
+ }
+ static int intel_dp_hdcp_read_bstatus(struct intel_digital_port *intel_dig_port,
+                                     u8 *bstatus)
+ {
+       ssize_t ret;
+       /*
+        * For some reason the HDMI and DP HDCP specs call this register
+        * definition by different names. In the HDMI spec, it's called BSTATUS,
+        * but in DP it's called BINFO.
+        */
+       ret = drm_dp_dpcd_read(&intel_dig_port->dp.aux, DP_AUX_HDCP_BINFO,
+                              bstatus, DRM_HDCP_BSTATUS_LEN);
+       if (ret != DRM_HDCP_BSTATUS_LEN) {
+               DRM_ERROR("Read bstatus from DP/AUX failed (%zd)\n", ret);
+               return ret >= 0 ? -EIO : ret;
+       }
+       return 0;
+ }
+ static
+ int intel_dp_hdcp_read_bcaps(struct intel_digital_port *intel_dig_port,
+                            u8 *bcaps)
+ {
+       ssize_t ret;
+       ret = drm_dp_dpcd_read(&intel_dig_port->dp.aux, DP_AUX_HDCP_BCAPS,
+                              bcaps, 1);
+       if (ret != 1) {
+               DRM_ERROR("Read bcaps from DP/AUX failed (%zd)\n", ret);
+               return ret >= 0 ? -EIO : ret;
+       }
+       return 0;
+ }
+ static
+ int intel_dp_hdcp_repeater_present(struct intel_digital_port *intel_dig_port,
+                                  bool *repeater_present)
+ {
+       ssize_t ret;
+       u8 bcaps;
+       ret = intel_dp_hdcp_read_bcaps(intel_dig_port, &bcaps);
+       if (ret)
+               return ret;
+       *repeater_present = bcaps & DP_BCAPS_REPEATER_PRESENT;
+       return 0;
+ }
+ static
+ int intel_dp_hdcp_read_ri_prime(struct intel_digital_port *intel_dig_port,
+                               u8 *ri_prime)
+ {
+       ssize_t ret;
+       ret = drm_dp_dpcd_read(&intel_dig_port->dp.aux, DP_AUX_HDCP_RI_PRIME,
+                              ri_prime, DRM_HDCP_RI_LEN);
+       if (ret != DRM_HDCP_RI_LEN) {
+               DRM_ERROR("Read Ri' from DP/AUX failed (%zd)\n", ret);
+               return ret >= 0 ? -EIO : ret;
+       }
+       return 0;
+ }
+ static
+ int intel_dp_hdcp_read_ksv_ready(struct intel_digital_port *intel_dig_port,
+                                bool *ksv_ready)
+ {
+       ssize_t ret;
+       u8 bstatus;
+       ret = drm_dp_dpcd_read(&intel_dig_port->dp.aux, DP_AUX_HDCP_BSTATUS,
+                              &bstatus, 1);
+       if (ret != 1) {
+               DRM_ERROR("Read bstatus from DP/AUX failed (%zd)\n", ret);
+               return ret >= 0 ? -EIO : ret;
+       }
+       *ksv_ready = bstatus & DP_BSTATUS_READY;
+       return 0;
+ }
+ static
+ int intel_dp_hdcp_read_ksv_fifo(struct intel_digital_port *intel_dig_port,
+                               int num_downstream, u8 *ksv_fifo)
+ {
+       ssize_t ret;
+       int i;
+       /* KSV list is read via 15 byte window (3 entries @ 5 bytes each) */
+       for (i = 0; i < num_downstream; i += 3) {
+               size_t len = min(num_downstream - i, 3) * DRM_HDCP_KSV_LEN;
+               ret = drm_dp_dpcd_read(&intel_dig_port->dp.aux,
+                                      DP_AUX_HDCP_KSV_FIFO,
+                                      ksv_fifo + i * DRM_HDCP_KSV_LEN,
+                                      len);
+               if (ret != len) {
+                       DRM_ERROR("Read ksv[%d] from DP/AUX failed (%zd)\n", i,
+                                 ret);
+                       return ret >= 0 ? -EIO : ret;
+               }
+       }
+       return 0;
+ }
+ static
+ int intel_dp_hdcp_read_v_prime_part(struct intel_digital_port *intel_dig_port,
+                                   int i, u32 *part)
+ {
+       ssize_t ret;
+       if (i >= DRM_HDCP_V_PRIME_NUM_PARTS)
+               return -EINVAL;
+       ret = drm_dp_dpcd_read(&intel_dig_port->dp.aux,
+                              DP_AUX_HDCP_V_PRIME(i), part,
+                              DRM_HDCP_V_PRIME_PART_LEN);
+       if (ret != DRM_HDCP_V_PRIME_PART_LEN) {
+               DRM_ERROR("Read v'[%d] from DP/AUX failed (%zd)\n", i, ret);
+               return ret >= 0 ? -EIO : ret;
+       }
+       return 0;
+ }
+ static
+ int intel_dp_hdcp_toggle_signalling(struct intel_digital_port *intel_dig_port,
+                                   bool enable)
+ {
+       /* Not used for single stream DisplayPort setups */
+       return 0;
+ }
+ static
+ bool intel_dp_hdcp_check_link(struct intel_digital_port *intel_dig_port)
+ {
+       ssize_t ret;
+       u8 bstatus;
+       ret = drm_dp_dpcd_read(&intel_dig_port->dp.aux, DP_AUX_HDCP_BSTATUS,
+                              &bstatus, 1);
+       if (ret != 1) {
+               DRM_ERROR("Read bstatus from DP/AUX failed (%zd)\n", ret);
+               return false;
+       }
+       return !(bstatus & (DP_BSTATUS_LINK_FAILURE | DP_BSTATUS_REAUTH_REQ));
+ }
+ static
+ int intel_dp_hdcp_capable(struct intel_digital_port *intel_dig_port,
+                         bool *hdcp_capable)
+ {
+       ssize_t ret;
+       u8 bcaps;
+       ret = intel_dp_hdcp_read_bcaps(intel_dig_port, &bcaps);
+       if (ret)
+               return ret;
+       *hdcp_capable = bcaps & DP_BCAPS_HDCP_CAPABLE;
+       return 0;
+ }
+ static const struct intel_hdcp_shim intel_dp_hdcp_shim = {
+       .write_an_aksv = intel_dp_hdcp_write_an_aksv,
+       .read_bksv = intel_dp_hdcp_read_bksv,
+       .read_bstatus = intel_dp_hdcp_read_bstatus,
+       .repeater_present = intel_dp_hdcp_repeater_present,
+       .read_ri_prime = intel_dp_hdcp_read_ri_prime,
+       .read_ksv_ready = intel_dp_hdcp_read_ksv_ready,
+       .read_ksv_fifo = intel_dp_hdcp_read_ksv_fifo,
+       .read_v_prime_part = intel_dp_hdcp_read_v_prime_part,
+       .toggle_signalling = intel_dp_hdcp_toggle_signalling,
+       .check_link = intel_dp_hdcp_check_link,
+       .hdcp_capable = intel_dp_hdcp_capable,
+ };
  static void intel_edp_panel_vdd_sanitize(struct intel_dp *intel_dp)
  {
        struct drm_i915_private *dev_priv = to_i915(intel_dp_to_dev(intel_dp));
@@@ -5157,6 -5444,9 +5411,9 @@@ err
                drm_modeset_acquire_fini(&ctx);
                WARN(iret, "Acquiring modeset locks failed with %i\n", iret);
  
+               /* Short pulse can signify loss of hdcp authentication */
+               intel_hdcp_check_link(intel_dp->attached_connector);
                if (!handled) {
                        intel_dp->detect_done = false;
                        goto put_power;
@@@ -5976,6 -6266,42 +6233,6 @@@ out_vdd_off
        return false;
  }
  
 -/* Set up the hotplug pin and aux power domain. */
 -static void
 -intel_dp_init_connector_port_info(struct intel_digital_port *intel_dig_port)
 -{
 -      struct intel_encoder *encoder = &intel_dig_port->base;
 -      struct intel_dp *intel_dp = &intel_dig_port->dp;
 -      struct intel_encoder *intel_encoder = &intel_dig_port->base;
 -      struct drm_i915_private *dev_priv = to_i915(intel_encoder->base.dev);
 -
 -      encoder->hpd_pin = intel_hpd_pin_default(dev_priv, encoder->port);
 -
 -      switch (encoder->port) {
 -      case PORT_A:
 -              intel_dp->aux_power_domain = POWER_DOMAIN_AUX_A;
 -              break;
 -      case PORT_B:
 -              intel_dp->aux_power_domain = POWER_DOMAIN_AUX_B;
 -              break;
 -      case PORT_C:
 -              intel_dp->aux_power_domain = POWER_DOMAIN_AUX_C;
 -              break;
 -      case PORT_D:
 -              intel_dp->aux_power_domain = POWER_DOMAIN_AUX_D;
 -              break;
 -      case PORT_E:
 -              /* FIXME: Check VBT for actual wiring of PORT E */
 -              intel_dp->aux_power_domain = POWER_DOMAIN_AUX_D;
 -              break;
 -      case PORT_F:
 -              intel_dp->aux_power_domain = POWER_DOMAIN_AUX_F;
 -              break;
 -      default:
 -              MISSING_CASE(encoder->port);
 -      }
 -}
 -
  static void intel_dp_modeset_retry_work_fn(struct work_struct *work)
  {
        struct intel_connector *intel_connector;
@@@ -6027,6 -6353,20 +6284,6 @@@ intel_dp_init_connector(struct intel_di
        intel_dp->active_pipe = INVALID_PIPE;
  
        /* intel_dp vfuncs */
 -      if (INTEL_GEN(dev_priv) >= 9)
 -              intel_dp->get_aux_clock_divider = skl_get_aux_clock_divider;
 -      else if (IS_HASWELL(dev_priv) || IS_BROADWELL(dev_priv))
 -              intel_dp->get_aux_clock_divider = hsw_get_aux_clock_divider;
 -      else if (HAS_PCH_SPLIT(dev_priv))
 -              intel_dp->get_aux_clock_divider = ilk_get_aux_clock_divider;
 -      else
 -              intel_dp->get_aux_clock_divider = g4x_get_aux_clock_divider;
 -
 -      if (INTEL_GEN(dev_priv) >= 9)
 -              intel_dp->get_aux_send_ctl = skl_get_aux_send_ctl;
 -      else
 -              intel_dp->get_aux_send_ctl = g4x_get_aux_send_ctl;
 -
        if (HAS_DDI(dev_priv))
                intel_dp->prepare_link_retrain = intel_ddi_prepare_link_retrain;
  
                connector->interlace_allowed = true;
        connector->doublescan_allowed = 0;
  
 -      intel_dp_init_connector_port_info(intel_dig_port);
 +      intel_encoder->hpd_pin = intel_hpd_pin_default(dev_priv, port);
  
        intel_dp_aux_init(intel_dp);
  
        }
  
        intel_dp_add_properties(intel_dp, connector);
+       if (is_hdcp_supported(dev_priv, port) && !intel_dp_is_edp(intel_dp)) {
+               int ret = intel_hdcp_init(intel_connector, &intel_dp_hdcp_shim);
+               if (ret)
+                       DRM_DEBUG_KMS("HDCP init failed, skipping.\n");
+       }
  
        /* For G4X desktop chip, PEG_BAND_GAP_DATA 3:0 must first be written
         * 0xd.  Failure to do so will result in spurious interrupts being
  #include <drm/drm_atomic.h>
  
  /**
-  * _wait_for - magic (register) wait macro
+  * __wait_for - magic wait macro
   *
-  * Does the right thing for modeset paths when run under kdgb or similar atomic
-  * contexts. Note that it's important that we check the condition again after
-  * having timed out, since the timeout could be due to preemption or similar and
-  * we've never had a chance to check the condition before the timeout.
+  * Macro to help avoid open coding check/wait/timeout patterns. Note that it's
+  * important that we check the condition again after having timed out, since the
+  * timeout could be due to preemption or similar and we've never had a chance to
+  * check the condition before the timeout.
   */
- #define _wait_for(COND, US, Wmin, Wmax) ({ \
+ #define __wait_for(OP, COND, US, Wmin, Wmax) ({ \
        unsigned long timeout__ = jiffies + usecs_to_jiffies(US) + 1;   \
        long wait__ = (Wmin); /* recommended min for usleep is 10 us */ \
        int ret__;                                                      \
        might_sleep();                                                  \
        for (;;) {                                                      \
                bool expired__ = time_after(jiffies, timeout__);        \
+               OP;                                                     \
                if (COND) {                                             \
                        ret__ = 0;                                      \
                        break;                                          \
@@@ -70,7 -71,9 +71,9 @@@
        ret__;                                                          \
  })
  
- #define wait_for(COND, MS)    _wait_for((COND), (MS) * 1000, 10, 1000)
+ #define _wait_for(COND, US, Wmin, Wmax)       __wait_for(, (COND), (US), (Wmin), \
+                                                  (Wmax))
+ #define wait_for(COND, MS)            _wait_for((COND), (MS) * 1000, 10, 1000)
  
  /* If CONFIG_PREEMPT_COUNT is disabled, in_atomic() always reports false. */
  #if defined(CONFIG_DRM_I915_DEBUG) && defined(CONFIG_PREEMPT_COUNT)
@@@ -299,6 -302,80 +302,80 @@@ struct intel_panel 
        } backlight;
  };
  
+ /*
+  * This structure serves as a translation layer between the generic HDCP code
+  * and the bus-specific code. What that means is that HDCP over HDMI differs
+  * from HDCP over DP, so to account for these differences, we need to
+  * communicate with the receiver through this shim.
+  *
+  * For completeness, the 2 buses differ in the following ways:
+  *    - DP AUX vs. DDC
+  *            HDCP registers on the receiver are set via DP AUX for DP, and
+  *            they are set via DDC for HDMI.
+  *    - Receiver register offsets
+  *            The offsets of the registers are different for DP vs. HDMI
+  *    - Receiver register masks/offsets
+  *            For instance, the ready bit for the KSV fifo is in a different
+  *            place on DP vs HDMI
+  *    - Receiver register names
+  *            Seriously. In the DP spec, the 16-bit register containing
+  *            downstream information is called BINFO, on HDMI it's called
+  *            BSTATUS. To confuse matters further, DP has a BSTATUS register
+  *            with a completely different definition.
+  *    - KSV FIFO
+  *            On HDMI, the ksv fifo is read all at once, whereas on DP it must
+  *            be read 3 keys at a time
+  *    - Aksv output
+  *            Since Aksv is hidden in hardware, there's different procedures
+  *            to send it over DP AUX vs DDC
+  */
+ struct intel_hdcp_shim {
+       /* Outputs the transmitter's An and Aksv values to the receiver. */
+       int (*write_an_aksv)(struct intel_digital_port *intel_dig_port, u8 *an);
+       /* Reads the receiver's key selection vector */
+       int (*read_bksv)(struct intel_digital_port *intel_dig_port, u8 *bksv);
+       /*
+        * Reads BINFO from DP receivers and BSTATUS from HDMI receivers. The
+        * definitions are the same in the respective specs, but the names are
+        * different. Call it BSTATUS since that's the name the HDMI spec
+        * uses and it was there first.
+        */
+       int (*read_bstatus)(struct intel_digital_port *intel_dig_port,
+                           u8 *bstatus);
+       /* Determines whether a repeater is present downstream */
+       int (*repeater_present)(struct intel_digital_port *intel_dig_port,
+                               bool *repeater_present);
+       /* Reads the receiver's Ri' value */
+       int (*read_ri_prime)(struct intel_digital_port *intel_dig_port, u8 *ri);
+       /* Determines if the receiver's KSV FIFO is ready for consumption */
+       int (*read_ksv_ready)(struct intel_digital_port *intel_dig_port,
+                             bool *ksv_ready);
+       /* Reads the ksv fifo for num_downstream devices */
+       int (*read_ksv_fifo)(struct intel_digital_port *intel_dig_port,
+                            int num_downstream, u8 *ksv_fifo);
+       /* Reads a 32-bit part of V' from the receiver */
+       int (*read_v_prime_part)(struct intel_digital_port *intel_dig_port,
+                                int i, u32 *part);
+       /* Enables HDCP signalling on the port */
+       int (*toggle_signalling)(struct intel_digital_port *intel_dig_port,
+                                bool enable);
+       /* Ensures the link is still protected */
+       bool (*check_link)(struct intel_digital_port *intel_dig_port);
+       /* Detects panel's hdcp capability. This is optional for HDMI. */
+       int (*hdcp_capable)(struct intel_digital_port *intel_dig_port,
+                           bool *hdcp_capable);
+ };
  struct intel_connector {
        struct drm_connector base;
        /*
  
        /* Work struct to schedule a uevent on link train failure */
        struct work_struct modeset_retry_work;
+       const struct intel_hdcp_shim *hdcp_shim;
+       struct mutex hdcp_mutex;
+       uint64_t hdcp_value; /* protected by hdcp_mutex */
+       struct delayed_work hdcp_check_work;
+       struct work_struct hdcp_prop_work;
  };
  
  struct intel_digital_connector_state {
@@@ -407,7 -490,6 +490,6 @@@ struct intel_atomic_state 
  
  struct intel_plane_state {
        struct drm_plane_state base;
-       struct drm_rect clip;
        struct i915_vma *vma;
        unsigned long flags;
  #define PLANE_HAS_FENCE BIT(0)
@@@ -853,7 -935,6 +935,7 @@@ struct intel_plane 
        enum plane_id id;
        enum pipe pipe;
        bool can_scale;
 +      bool has_fbc;
        int max_downscale;
        uint32_t frontbuffer_bit;
  
@@@ -960,6 -1041,8 +1042,6 @@@ struct intel_dp_compliance 
  
  struct intel_dp {
        i915_reg_t output_reg;
 -      i915_reg_t aux_ch_ctl_reg;
 -      i915_reg_t aux_ch_data_reg[5];
        uint32_t DP;
        int link_rate;
        uint8_t lane_count;
        bool detect_done;
        bool channel_eq_status;
        bool reset_link_params;
 +      enum aux_ch aux_ch;
        uint8_t dpcd[DP_RECEIVER_CAP_SIZE];
        uint8_t psr_dpcd[EDP_PSR_RECEIVER_CAP_SIZE];
        uint8_t downstream_ports[DP_MAX_DOWNSTREAM_PORTS];
                                     int send_bytes,
                                     uint32_t aux_clock_divider);
  
 +      i915_reg_t (*aux_ch_ctl_reg)(struct intel_dp *dp);
 +      i915_reg_t (*aux_ch_data_reg)(struct intel_dp *dp, int index);
 +
        /* This is called before a link training is starterd */
        void (*prepare_link_retrain)(struct intel_dp *intel_dp);
  
@@@ -1304,6 -1383,8 +1386,8 @@@ void intel_ddi_compute_min_voltage_leve
  u32 bxt_signal_levels(struct intel_dp *intel_dp);
  uint32_t ddi_signal_levels(struct intel_dp *intel_dp);
  u8 intel_ddi_dp_voltage_max(struct intel_encoder *encoder);
+ int intel_ddi_toggle_hdcp_signalling(struct intel_encoder *intel_encoder,
+                                    bool enable);
  
  unsigned int intel_fb_align_height(const struct drm_framebuffer *fb,
                                   int plane, unsigned int height);
@@@ -1427,7 -1508,6 +1511,7 @@@ void intel_release_load_detect_pipe(str
  struct i915_vma *
  intel_pin_and_fence_fb_obj(struct drm_framebuffer *fb,
                           unsigned int rotation,
 +                         bool uses_fence,
                           unsigned long *out_flags);
  void intel_unpin_fb_vma(struct i915_vma *vma, unsigned long flags);
  struct drm_framebuffer *
@@@ -1769,10 -1849,19 +1853,20 @@@ static inline void intel_backlight_devi
  }
  #endif /* CONFIG_BACKLIGHT_CLASS_DEVICE */
  
+ /* intel_hdcp.c */
+ void intel_hdcp_atomic_check(struct drm_connector *connector,
+                            struct drm_connector_state *old_state,
+                            struct drm_connector_state *new_state);
+ int intel_hdcp_init(struct intel_connector *connector,
+                   const struct intel_hdcp_shim *hdcp_shim);
+ int intel_hdcp_enable(struct intel_connector *connector);
+ int intel_hdcp_disable(struct intel_connector *connector);
+ int intel_hdcp_check_link(struct intel_connector *connector);
+ bool is_hdcp_supported(struct drm_i915_private *dev_priv, enum port port);
  
  /* intel_psr.c */
  #define CAN_PSR(dev_priv) (HAS_PSR(dev_priv) && dev_priv->psr.sink_support)
 +void intel_psr_init_dpcd(struct intel_dp *intel_dp);
  void intel_psr_enable(struct intel_dp *intel_dp,
                      const struct intel_crtc_state *crtc_state);
  void intel_psr_disable(struct intel_dp *intel_dp,
@@@ -1899,7 -1988,8 +1993,7 @@@ void intel_suspend_gt_powersave(struct 
  void gen6_rps_busy(struct drm_i915_private *dev_priv);
  void gen6_rps_reset_ei(struct drm_i915_private *dev_priv);
  void gen6_rps_idle(struct drm_i915_private *dev_priv);
 -void gen6_rps_boost(struct drm_i915_gem_request *rq,
 -                  struct intel_rps_client *rps);
 +void gen6_rps_boost(struct i915_request *rq, struct intel_rps_client *rps);
  void g4x_wm_get_hw_state(struct drm_device *dev);
  void vlv_wm_get_hw_state(struct drm_device *dev);
  void ilk_wm_get_hw_state(struct drm_device *dev);
@@@ -46,6 -46,16 +46,6 @@@ static inline bool fbc_supported(struc
        return HAS_FBC(dev_priv);
  }
  
 -static inline bool fbc_on_pipe_a_only(struct drm_i915_private *dev_priv)
 -{
 -      return IS_HASWELL(dev_priv) || INTEL_GEN(dev_priv) >= 8;
 -}
 -
 -static inline bool fbc_on_plane_a_only(struct drm_i915_private *dev_priv)
 -{
 -      return INTEL_GEN(dev_priv) < 4;
 -}
 -
  static inline bool no_fbc_on_multiple_pipes(struct drm_i915_private *dev_priv)
  {
        return INTEL_GEN(dev_priv) <= 3;
@@@ -793,8 -803,7 +793,7 @@@ static bool intel_fbc_can_activate(stru
                return false;
        }
  
-       if ((cache->crtc.mode_flags & DRM_MODE_FLAG_INTERLACE) ||
-           (cache->crtc.mode_flags & DRM_MODE_FLAG_DBLSCAN)) {
+       if (cache->crtc.mode_flags & DRM_MODE_FLAG_INTERLACE) {
                fbc->no_fbc_reason = "incompatible mode";
                return false;
        }
         * Note that is possible for a tiled surface to be unmappable (and
         * so have no fence associated with it) due to aperture constaints
         * at the time of pinning.
 +       *
 +       * FIXME with 90/270 degree rotation we should use the fence on
 +       * the normal GTT view (the rotated view doesn't even have a
 +       * fence). Would need changes to the FBC fence Y offset as well.
 +       * For now this will effecively disable FBC with 90/270 degree
 +       * rotation.
         */
        if (!(cache->flags & PLANE_HAS_FENCE)) {
                fbc->no_fbc_reason = "framebuffer not tiled or fenced";
@@@ -1091,10 -1094,13 +1090,10 @@@ void intel_fbc_choose_crtc(struct drm_i
                struct intel_crtc_state *crtc_state;
                struct intel_crtc *crtc = to_intel_crtc(plane_state->base.crtc);
  
 -              if (!plane_state->base.visible)
 -                      continue;
 -
 -              if (fbc_on_pipe_a_only(dev_priv) && crtc->pipe != PIPE_A)
 +              if (!plane->has_fbc)
                        continue;
  
 -              if (fbc_on_plane_a_only(dev_priv) && plane->i9xx_plane != PLANE_A)
 +              if (!plane_state->base.visible)
                        continue;
  
                crtc_state = intel_atomic_get_new_crtc_state(state, crtc);
@@@ -1351,6 -1357,7 +1350,6 @@@ static bool need_fbc_vtd_wa(struct drm_
  void intel_fbc_init(struct drm_i915_private *dev_priv)
  {
        struct intel_fbc *fbc = &dev_priv->fbc;
 -      enum pipe pipe;
  
        INIT_WORK(&fbc->work.work, intel_fbc_work_fn);
        INIT_WORK(&fbc->underrun_work, intel_fbc_underrun_work_fn);
                return;
        }
  
 -      for_each_pipe(dev_priv, pipe) {
 -              fbc->possible_framebuffer_bits |=
 -                      INTEL_FRONTBUFFER(pipe, PLANE_PRIMARY);
 -
 -              if (fbc_on_pipe_a_only(dev_priv))
 -                      break;
 -      }
 -
        /* This value was pulled out of someone's hat */
        if (INTEL_GEN(dev_priv) <= 4 && !IS_GM45(dev_priv))
                I915_WRITE(FBC_CONTROL, 500 << FBC_CTL_INTERVAL_SHIFT);