]> Git Repo - linux.git/commitdiff
Merge tag 'v3.10-rc2' into drm-intel-next-queued
authorDaniel Vetter <[email protected]>
Tue, 21 May 2013 07:52:16 +0000 (09:52 +0200)
committerDaniel Vetter <[email protected]>
Tue, 21 May 2013 07:52:16 +0000 (09:52 +0200)
Backmerge Linux 3.10-rc2 since the various (rather trivial) conflicts
grew a bit out of hand. intel_dp.c has the only real functional
conflict since the logic changed while dev_priv->edp.bpp was moved
around.

Also squash in a whitespace fixup from Ben Widawsky for
i915_gem_gtt.c, git seems to do something pretty strange in there
(which I don't fully understand tbh).

Conflicts:
drivers/gpu/drm/i915/i915_reg.h
drivers/gpu/drm/i915/intel_dp.c

Signed-off-by: Daniel Vetter <[email protected]>
14 files changed:
1  2 
drivers/gpu/drm/Makefile
drivers/gpu/drm/i915/i915_gem.c
drivers/gpu/drm/i915/i915_gem_gtt.c
drivers/gpu/drm/i915/i915_reg.h
drivers/gpu/drm/i915/intel_crt.c
drivers/gpu/drm/i915/intel_ddi.c
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_dvo.c
drivers/gpu/drm/i915/intel_hdmi.c
drivers/gpu/drm/i915/intel_opregion.c
drivers/gpu/drm/i915/intel_pm.c
drivers/gpu/drm/i915/intel_sdvo.c

diff --combined drivers/gpu/drm/Makefile
index 8f94018852a684383f45a9094779875ce358b0f4,1c9f24396002b31eaa03207b69e0e484646a0549..1ecbe5b7312de6798cd8e76cea4c8e16ae05f140
@@@ -12,8 -12,7 +12,8 @@@ drm-y       :=        drm_auth.o drm_buffer.o 
                drm_platform.o drm_sysfs.o drm_hashtab.o drm_mm.o \
                drm_crtc.o drm_modes.o drm_edid.o \
                drm_info.o drm_debugfs.o drm_encoder_slave.o \
 -              drm_trace_points.o drm_global.o drm_prime.o
 +              drm_trace_points.o drm_global.o drm_prime.o \
 +              drm_rect.o
  
  drm-$(CONFIG_COMPAT) += drm_ioc32.o
  drm-$(CONFIG_DRM_GEM_CMA_HELPER) += drm_gem_cma_helper.o
@@@ -50,7 -49,7 +50,7 @@@ obj-$(CONFIG_DRM_GMA500) += gma500
  obj-$(CONFIG_DRM_UDL) += udl/
  obj-$(CONFIG_DRM_AST) += ast/
  obj-$(CONFIG_DRM_SHMOBILE) +=shmobile/
- obj-$(CONFIG_DRM_TEGRA) += tegra/
  obj-$(CONFIG_DRM_OMAP)        += omapdrm/
  obj-$(CONFIG_DRM_TILCDC)      += tilcdc/
+ obj-$(CONFIG_DRM_QXL) += qxl/
  obj-y                 += i2c/
index 8a81d1a21050a4eef708979b500f751b78b020ae,6165535d15f07af8969a74f075994d31bfbae47e..a1a282ce2466b883fb7744da4c51dc2484cf7c69
@@@ -1045,6 -1045,8 +1045,8 @@@ static int __wait_seqno(struct intel_ri
        if (timeout) {
                struct timespec sleep_time = timespec_sub(now, before);
                *timeout = timespec_sub(*timeout, sleep_time);
+               if (!timespec_valid(timeout)) /* i.e. negative time remains */
+                       set_normalized_timespec(timeout, 0, 0);
        }
  
        switch (end) {
        case -ERESTARTSYS: /* Signal */
                return (int)end;
        case 0: /* Timeout */
-               if (timeout)
-                       set_normalized_timespec(timeout, 0, 0);
                return -ETIME;
        default: /* Completed */
                WARN_ON(end < 0); /* We're not aware of other errors */
@@@ -2042,11 -2042,6 +2042,11 @@@ i915_add_request(struct intel_ring_buff
        request->seqno = intel_ring_get_seqno(ring);
        request->ring = ring;
        request->tail = request_ring_position;
 +      request->ctx = ring->last_context;
 +
 +      if (request->ctx)
 +              i915_gem_context_reference(request->ctx);
 +
        request->emitted_jiffies = jiffies;
        was_empty = list_empty(&ring->request_list);
        list_add_tail(&request->list, &ring->request_list);
@@@ -2099,17 -2094,6 +2099,17 @@@ i915_gem_request_remove_from_client(str
        spin_unlock(&file_priv->mm.lock);
  }
  
 +static void i915_gem_free_request(struct drm_i915_gem_request *request)
 +{
 +      list_del(&request->list);
 +      i915_gem_request_remove_from_client(request);
 +
 +      if (request->ctx)
 +              i915_gem_context_unreference(request->ctx);
 +
 +      kfree(request);
 +}
 +
  static void i915_gem_reset_ring_lists(struct drm_i915_private *dev_priv,
                                      struct intel_ring_buffer *ring)
  {
                                           struct drm_i915_gem_request,
                                           list);
  
 -              list_del(&request->list);
 -              i915_gem_request_remove_from_client(request);
 -              kfree(request);
 +              i915_gem_free_request(request);
        }
  
        while (!list_empty(&ring->active_list)) {
@@@ -2212,7 -2198,9 +2212,7 @@@ i915_gem_retire_requests_ring(struct in
                 */
                ring->last_retired_head = request->tail;
  
 -              list_del(&request->list);
 -              i915_gem_request_remove_from_client(request);
 -              kfree(request);
 +              i915_gem_free_request(request);
        }
  
        /* Move any buffers on the active list that are no longer referenced
@@@ -2389,10 -2377,8 +2389,8 @@@ i915_gem_wait_ioctl(struct drm_device *
        mutex_unlock(&dev->struct_mutex);
  
        ret = __wait_seqno(ring, seqno, reset_counter, true, timeout);
-       if (timeout) {
-               WARN_ON(!timespec_valid(timeout));
+       if (timeout)
                args->timeout_ns = timespec_to_ns(timeout);
-       }
        return ret;
  
  out:
index 85b3d5d4deecc57e4f2023078dd53c77d816ff0a,bdb0d7717bc77937dce3c4de563f1e7066c7bb2e..ddad13fa31567aa7332a241262b5bb6b9e725ea8
@@@ -28,6 -28,8 +28,6 @@@
  #include "i915_trace.h"
  #include "intel_drv.h"
  
 -typedef uint32_t gen6_gtt_pte_t;
 -
  /* PPGTT stuff */
  #define GEN6_GTT_ADDR_ENCODE(addr)    ((addr) | (((addr) >> 28) & 0xff0))
  
  #define GEN6_PTE_CACHE_LLC_MLC                (3 << 1)
  #define GEN6_PTE_ADDR_ENCODE(addr)    GEN6_GTT_ADDR_ENCODE(addr)
  
 -static inline gen6_gtt_pte_t gen6_pte_encode(struct drm_device *dev,
 -                                           dma_addr_t addr,
 -                                           enum i915_cache_level level)
 +static gen6_gtt_pte_t gen6_pte_encode(struct drm_device *dev,
 +                                    dma_addr_t addr,
 +                                    enum i915_cache_level level)
  {
        gen6_gtt_pte_t pte = GEN6_PTE_VALID;
        pte |= GEN6_PTE_ADDR_ENCODE(addr);
  
        switch (level) {
        case I915_CACHE_LLC_MLC:
 -              /* Haswell doesn't set L3 this way */
 -              if (IS_HASWELL(dev))
 -                      pte |= GEN6_PTE_CACHE_LLC;
 -              else
 -                      pte |= GEN6_PTE_CACHE_LLC_MLC;
 +              pte |= GEN6_PTE_CACHE_LLC_MLC;
                break;
        case I915_CACHE_LLC:
                pte |= GEN6_PTE_CACHE_LLC;
                break;
        case I915_CACHE_NONE:
 -              if (IS_HASWELL(dev))
 -                      pte |= HSW_PTE_UNCACHED;
 -              else
 -                      pte |= GEN6_PTE_UNCACHED;
 +              pte |= GEN6_PTE_UNCACHED;
                break;
        default:
                BUG();
        return pte;
  }
  
 -static int gen6_ppgtt_enable(struct drm_device *dev)
 +#define BYT_PTE_WRITEABLE             (1 << 1)
 +#define BYT_PTE_SNOOPED_BY_CPU_CACHES (1 << 2)
 +
 +static gen6_gtt_pte_t byt_pte_encode(struct drm_device *dev,
 +                                   dma_addr_t addr,
 +                                   enum i915_cache_level level)
  {
 -      drm_i915_private_t *dev_priv = dev->dev_private;
 -      uint32_t pd_offset;
 -      struct intel_ring_buffer *ring;
 -      struct i915_hw_ppgtt *ppgtt = dev_priv->mm.aliasing_ppgtt;
 +      gen6_gtt_pte_t pte = GEN6_PTE_VALID;
 +      pte |= GEN6_PTE_ADDR_ENCODE(addr);
 +
 +      /* Mark the page as writeable.  Other platforms don't have a
 +       * setting for read-only/writable, so this matches that behavior.
 +       */
 +      pte |= BYT_PTE_WRITEABLE;
 +
 +      if (level != I915_CACHE_NONE)
 +              pte |= BYT_PTE_SNOOPED_BY_CPU_CACHES;
 +
 +      return pte;
 +}
 +
 +static gen6_gtt_pte_t hsw_pte_encode(struct drm_device *dev,
 +                                   dma_addr_t addr,
 +                                   enum i915_cache_level level)
 +{
 +      gen6_gtt_pte_t pte = GEN6_PTE_VALID;
 +      pte |= GEN6_PTE_ADDR_ENCODE(addr);
 +
 +      if (level != I915_CACHE_NONE)
 +              pte |= GEN6_PTE_CACHE_LLC;
 +
 +      return pte;
 +}
 +
 +static void gen6_write_pdes(struct i915_hw_ppgtt *ppgtt)
 +{
 +      struct drm_i915_private *dev_priv = ppgtt->dev->dev_private;
        gen6_gtt_pte_t __iomem *pd_addr;
        uint32_t pd_entry;
        int i;
  
 +      WARN_ON(ppgtt->pd_offset & 0x3f);
        pd_addr = (gen6_gtt_pte_t __iomem*)dev_priv->gtt.gsm +
                ppgtt->pd_offset / sizeof(gen6_gtt_pte_t);
        for (i = 0; i < ppgtt->num_pd_entries; i++) {
                writel(pd_entry, pd_addr + i);
        }
        readl(pd_addr);
 +}
 +
 +static int gen6_ppgtt_enable(struct drm_device *dev)
 +{
 +      drm_i915_private_t *dev_priv = dev->dev_private;
 +      uint32_t pd_offset;
 +      struct intel_ring_buffer *ring;
 +      struct i915_hw_ppgtt *ppgtt = dev_priv->mm.aliasing_ppgtt;
 +      int i;
 +
 +      BUG_ON(ppgtt->pd_offset & 0x3f);
 +
 +      gen6_write_pdes(ppgtt);
  
        pd_offset = ppgtt->pd_offset;
        pd_offset /= 64; /* in cachelines, */
@@@ -190,9 -154,9 +190,9 @@@ static void gen6_ppgtt_clear_range(stru
        unsigned first_pte = first_entry % I915_PPGTT_PT_ENTRIES;
        unsigned last_pte, i;
  
 -      scratch_pte = gen6_pte_encode(ppgtt->dev,
 -                                    ppgtt->scratch_page_dma_addr,
 -                                    I915_CACHE_LLC);
 +      scratch_pte = ppgtt->pte_encode(ppgtt->dev,
 +                                      ppgtt->scratch_page_dma_addr,
 +                                      I915_CACHE_LLC);
  
        while (num_entries) {
                last_pte = first_pte + num_entries;
@@@ -227,8 -191,8 +227,8 @@@ static void gen6_ppgtt_insert_entries(s
                dma_addr_t page_addr;
  
                page_addr = sg_page_iter_dma_address(&sg_iter);
 -              pt_vaddr[act_pte] = gen6_pte_encode(ppgtt->dev, page_addr,
 -                                                  cache_level);
 +              pt_vaddr[act_pte] = ppgtt->pte_encode(ppgtt->dev, page_addr,
 +                                                    cache_level);
                if (++act_pte == I915_PPGTT_PT_ENTRIES) {
                        kunmap_atomic(pt_vaddr);
                        act_pt++;
@@@ -269,16 -233,8 +269,15 @@@ static int gen6_ppgtt_init(struct i915_
        /* ppgtt PDEs reside in the global gtt pagetable, which has 512*1024
         * entries. For aliasing ppgtt support we just steal them at the end for
         * now. */
-       first_pd_entry_in_global_pt =
-               gtt_total_entries(dev_priv->gtt) - I915_PPGTT_PD_ENTRIES;
 -       first_pd_entry_in_global_pt = gtt_total_entries(dev_priv->gtt);
++      first_pd_entry_in_global_pt = gtt_total_entries(dev_priv->gtt);
  
 +      if (IS_HASWELL(dev)) {
 +              ppgtt->pte_encode = hsw_pte_encode;
 +      } else if (IS_VALLEYVIEW(dev)) {
 +              ppgtt->pte_encode = byt_pte_encode;
 +      } else {
 +              ppgtt->pte_encode = gen6_pte_encode;
 +      }
        ppgtt->num_pd_entries = I915_PPGTT_PD_ENTRIES;
        ppgtt->enable = gen6_ppgtt_enable;
        ppgtt->clear_range = gen6_ppgtt_clear_range;
@@@ -481,8 -437,7 +480,8 @@@ static void gen6_ggtt_insert_entries(st
  
        for_each_sg_page(st->sgl, &sg_iter, st->nents, 0) {
                addr = sg_page_iter_dma_address(&sg_iter);
 -              iowrite32(gen6_pte_encode(dev, addr, level), &gtt_entries[i]);
 +              iowrite32(dev_priv->gtt.pte_encode(dev, addr, level),
 +                        &gtt_entries[i]);
                i++;
        }
  
         */
        if (i != 0)
                WARN_ON(readl(&gtt_entries[i-1])
 -                      != gen6_pte_encode(dev, addr, level));
 +                      != dev_priv->gtt.pte_encode(dev, addr, level));
  
        /* This next bit makes the above posting read even more important. We
         * want to flush the TLBs only after we're certain all the PTE updates
@@@ -519,9 -474,8 +518,9 @@@ static void gen6_ggtt_clear_range(struc
                 first_entry, num_entries, max_entries))
                num_entries = max_entries;
  
 -      scratch_pte = gen6_pte_encode(dev, dev_priv->gtt.scratch_page_dma,
 -                                    I915_CACHE_LLC);
 +      scratch_pte = dev_priv->gtt.pte_encode(dev,
 +                                             dev_priv->gtt.scratch_page_dma,
 +                                             I915_CACHE_LLC);
        for (i = 0; i < num_entries; i++)
                iowrite32(scratch_pte, &gtt_base[i]);
        readl(gtt_base);
@@@ -755,15 -709,6 +754,6 @@@ static inline size_t gen6_get_stolen_si
        return snb_gmch_ctl << 25; /* 32 MB units */
  }
  
- static inline size_t gen7_get_stolen_size(u16 snb_gmch_ctl)
- {
-       static const int stolen_decoder[] = {
-               0, 0, 0, 0, 0, 32, 48, 64, 128, 256, 96, 160, 224, 352};
-       snb_gmch_ctl >>= IVB_GMCH_GMS_SHIFT;
-       snb_gmch_ctl &= IVB_GMCH_GMS_MASK;
-       return stolen_decoder[snb_gmch_ctl] << 20;
- }
  static int gen6_gmch_probe(struct drm_device *dev,
                           size_t *gtt_total,
                           size_t *stolen,
        pci_read_config_word(dev->pdev, SNB_GMCH_CTRL, &snb_gmch_ctl);
        gtt_size = gen6_get_total_gtt_size(snb_gmch_ctl);
  
-       if (IS_GEN7(dev) && !IS_VALLEYVIEW(dev))
-               *stolen = gen7_get_stolen_size(snb_gmch_ctl);
-       else
-               *stolen = gen6_get_stolen_size(snb_gmch_ctl);
+       *stolen = gen6_get_stolen_size(snb_gmch_ctl);
        *gtt_total = (gtt_size / sizeof(gen6_gtt_pte_t)) << PAGE_SHIFT;
  
        /* For Modern GENs the PTEs and register space are split in the BAR */
@@@ -868,13 -809,6 +854,13 @@@ int i915_gem_gtt_init(struct drm_devic
        } else {
                dev_priv->gtt.gtt_probe = gen6_gmch_probe;
                dev_priv->gtt.gtt_remove = gen6_gmch_remove;
 +              if (IS_HASWELL(dev)) {
 +                      dev_priv->gtt.pte_encode = hsw_pte_encode;
 +              } else if (IS_VALLEYVIEW(dev)) {
 +                      dev_priv->gtt.pte_encode = byt_pte_encode;
 +              } else {
 +                      dev_priv->gtt.pte_encode = gen6_pte_encode;
 +              }
        }
  
        ret = dev_priv->gtt.gtt_probe(dev, &dev_priv->gtt.total,
index 7af7ae66b3385ece1d108e5b099776e0df5df095,2d6b62e42daf324478ea64bc49e6e722330c3e2b..e4cf382f0b75397408eeab87bc892c6829c7249d
@@@ -46,8 -46,6 +46,6 @@@
  #define    SNB_GMCH_GGMS_MASK 0x3
  #define    SNB_GMCH_GMS_SHIFT   3 /* Graphics Mode Select */
  #define    SNB_GMCH_GMS_MASK    0x1f
- #define    IVB_GMCH_GMS_SHIFT   4
- #define    IVB_GMCH_GMS_MASK    0xf
  
  
  /* PCI config space */
   *  0x8100: fast clock controls
   *
   * DPIO is VLV only.
 + *
 + * Note: digital port B is DDI0, digital pot C is DDI1
   */
  #define DPIO_PKT                      (VLV_DISPLAY_BASE + 0x2100)
  #define  DPIO_RID                     (0<<24)
  #define  DPIO_SFR_BYPASS              (1<<1)
  #define  DPIO_RESET                   (1<<0)
  
 +#define _DPIO_TX3_SWING_CTL4_A                0x690
 +#define _DPIO_TX3_SWING_CTL4_B                0x2a90
 +#define DPIO_TX3_SWING_CTL4(pipe) _PIPE(pipe, _DPIO_TX_SWING_CTL4_A, \
 +                                      _DPIO_TX3_SWING_CTL4_B)
 +
 +/*
 + * Per pipe/PLL DPIO regs
 + */
  #define _DPIO_DIV_A                   0x800c
  #define   DPIO_POST_DIV_SHIFT         (28) /* 3 bits */
 +#define   DPIO_POST_DIV_DAC           0
 +#define   DPIO_POST_DIV_HDMIDP                1 /* DAC 225-400M rate */
 +#define   DPIO_POST_DIV_LVDS1         2
 +#define   DPIO_POST_DIV_LVDS2         3
  #define   DPIO_K_SHIFT                        (24) /* 4 bits */
  #define   DPIO_P1_SHIFT                       (21) /* 3 bits */
  #define   DPIO_P2_SHIFT                       (16) /* 5 bits */
  #define _DPIO_CORE_CLK_B              0x803c
  #define DPIO_CORE_CLK(pipe) _PIPE(pipe, _DPIO_CORE_CLK_A, _DPIO_CORE_CLK_B)
  
 +#define _DPIO_IREF_CTL_A              0x8040
 +#define _DPIO_IREF_CTL_B              0x8060
 +#define DPIO_IREF_CTL(pipe) _PIPE(pipe, _DPIO_IREF_CTL_A, _DPIO_IREF_CTL_B)
 +
 +#define DPIO_IREF_BCAST                       0xc044
 +#define _DPIO_IREF_A                  0x8044
 +#define _DPIO_IREF_B                  0x8064
 +#define DPIO_IREF(pipe) _PIPE(pipe, _DPIO_IREF_A, _DPIO_IREF_B)
 +
 +#define _DPIO_PLL_CML_A                       0x804c
 +#define _DPIO_PLL_CML_B                       0x806c
 +#define DPIO_PLL_CML(pipe) _PIPE(pipe, _DPIO_PLL_CML_A, _DPIO_PLL_CML_B)
 +
  #define _DPIO_LFP_COEFF_A             0x8048
  #define _DPIO_LFP_COEFF_B             0x8068
  #define DPIO_LFP_COEFF(pipe) _PIPE(pipe, _DPIO_LFP_COEFF_A, _DPIO_LFP_COEFF_B)
  
 +#define DPIO_CALIBRATION              0x80ac
 +
  #define DPIO_FASTCLK_DISABLE          0x8100
  
 -#define DPIO_DATA_CHANNEL1            0x8220
 -#define DPIO_DATA_CHANNEL2            0x8420
 +/*
 + * Per DDI channel DPIO regs
 + */
 +
 +#define _DPIO_PCS_TX_0                        0x8200
 +#define _DPIO_PCS_TX_1                        0x8400
 +#define   DPIO_PCS_TX_LANE2_RESET     (1<<16)
 +#define   DPIO_PCS_TX_LANE1_RESET     (1<<7)
 +#define DPIO_PCS_TX(port) _PORT(port, _DPIO_PCS_TX_0, _DPIO_PCS_TX_1)
 +
 +#define _DPIO_PCS_CLK_0                       0x8204
 +#define _DPIO_PCS_CLK_1                       0x8404
 +#define   DPIO_PCS_CLK_CRI_RXEB_EIOS_EN       (1<<22)
 +#define   DPIO_PCS_CLK_CRI_RXDIGFILTSG_EN (1<<21)
 +#define   DPIO_PCS_CLK_DATAWIDTH_SHIFT        (6)
 +#define   DPIO_PCS_CLK_SOFT_RESET     (1<<5)
 +#define DPIO_PCS_CLK(port) _PORT(port, _DPIO_PCS_CLK_0, _DPIO_PCS_CLK_1)
 +
 +#define _DPIO_PCS_CTL_OVR1_A          0x8224
 +#define _DPIO_PCS_CTL_OVR1_B          0x8424
 +#define DPIO_PCS_CTL_OVER1(port) _PORT(port, _DPIO_PCS_CTL_OVR1_A, \
 +                                     _DPIO_PCS_CTL_OVR1_B)
 +
 +#define _DPIO_PCS_STAGGER0_A          0x822c
 +#define _DPIO_PCS_STAGGER0_B          0x842c
 +#define DPIO_PCS_STAGGER0(port) _PORT(port, _DPIO_PCS_STAGGER0_A, \
 +                                    _DPIO_PCS_STAGGER0_B)
 +
 +#define _DPIO_PCS_STAGGER1_A          0x8230
 +#define _DPIO_PCS_STAGGER1_B          0x8430
 +#define DPIO_PCS_STAGGER1(port) _PORT(port, _DPIO_PCS_STAGGER1_A, \
 +                                    _DPIO_PCS_STAGGER1_B)
 +
 +#define _DPIO_PCS_CLOCKBUF0_A         0x8238
 +#define _DPIO_PCS_CLOCKBUF0_B         0x8438
 +#define DPIO_PCS_CLOCKBUF0(port) _PORT(port, _DPIO_PCS_CLOCKBUF0_A, \
 +                                     _DPIO_PCS_CLOCKBUF0_B)
 +
 +#define _DPIO_PCS_CLOCKBUF8_A         0x825c
 +#define _DPIO_PCS_CLOCKBUF8_B         0x845c
 +#define DPIO_PCS_CLOCKBUF8(port) _PORT(port, _DPIO_PCS_CLOCKBUF8_A, \
 +                                     _DPIO_PCS_CLOCKBUF8_B)
 +
 +#define _DPIO_TX_SWING_CTL2_A         0x8288
 +#define _DPIO_TX_SWING_CTL2_B         0x8488
 +#define DPIO_TX_SWING_CTL2(port) _PORT(port, _DPIO_TX_SWING_CTL2_A, \
 +                                     _DPIO_TX_SWING_CTL2_B)
 +
 +#define _DPIO_TX_SWING_CTL3_A         0x828c
 +#define _DPIO_TX_SWING_CTL3_B         0x848c
 +#define DPIO_TX_SWING_CTL3(port) _PORT(port, _DPIO_TX_SWING_CTL3_A, \
 +                                     _DPIO_TX_SWING_CTL3_B)
 +
 +#define _DPIO_TX_SWING_CTL4_A         0x8290
 +#define _DPIO_TX_SWING_CTL4_B         0x8490
 +#define DPIO_TX_SWING_CTL4(port) _PORT(port, _DPIO_TX_SWING_CTL4_A, \
 +                                     _DPIO_TX_SWING_CTL4_B)
 +
 +#define _DPIO_TX_OCALINIT_0           0x8294
 +#define _DPIO_TX_OCALINIT_1           0x8494
 +#define   DPIO_TX_OCALINIT_EN         (1<<31)
 +#define DPIO_TX_OCALINIT(port) _PORT(port, _DPIO_TX_OCALINIT_0, \
 +                                   _DPIO_TX_OCALINIT_1)
 +
 +#define _DPIO_TX_CTL_0                        0x82ac
 +#define _DPIO_TX_CTL_1                        0x84ac
 +#define DPIO_TX_CTL(port) _PORT(port, _DPIO_TX_CTL_0, _DPIO_TX_CTL_1)
 +
 +#define _DPIO_TX_LANE_0                       0x82b8
 +#define _DPIO_TX_LANE_1                       0x84b8
 +#define DPIO_TX_LANE(port) _PORT(port, _DPIO_TX_LANE_0, _DPIO_TX_LANE_1)
 +
 +#define _DPIO_DATA_CHANNEL1           0x8220
 +#define _DPIO_DATA_CHANNEL2           0x8420
 +#define DPIO_DATA_CHANNEL(port) _PORT(port, _DPIO_DATA_CHANNEL1, _DPIO_DATA_CHANNEL2)
 +
 +#define _DPIO_PORT0_PCS0              0x0220
 +#define _DPIO_PORT0_PCS1              0x0420
 +#define _DPIO_PORT1_PCS2              0x2620
 +#define _DPIO_PORT1_PCS3              0x2820
 +#define DPIO_DATA_LANE_A(port) _PORT(port, _DPIO_PORT0_PCS0, _DPIO_PORT1_PCS2)
 +#define DPIO_DATA_LANE_B(port) _PORT(port, _DPIO_PORT0_PCS1, _DPIO_PORT1_PCS3)
 +#define DPIO_DATA_CHANNEL1              0x8220
 +#define DPIO_DATA_CHANNEL2              0x8420
  
  /*
   * Fence registers
  
  #define ERROR_GEN6    0x040a0
  #define GEN7_ERR_INT  0x44040
 -#define   ERR_INT_MMIO_UNCLAIMED (1<<13)
 +#define   ERR_INT_POISON              (1<<31)
 +#define   ERR_INT_MMIO_UNCLAIMED      (1<<13)
 +#define   ERR_INT_FIFO_UNDERRUN_C     (1<<6)
 +#define   ERR_INT_FIFO_UNDERRUN_B     (1<<3)
 +#define   ERR_INT_FIFO_UNDERRUN_A     (1<<0)
  
  #define FPGA_DBG              0x42300
  #define   FPGA_DBG_RM_NOCLAIM (1<<31)
  #define VLV_IIR               (VLV_DISPLAY_BASE + 0x20a4)
  #define VLV_IMR               (VLV_DISPLAY_BASE + 0x20a8)
  #define VLV_ISR               (VLV_DISPLAY_BASE + 0x20ac)
 +#define VLV_PCBR      (VLV_DISPLAY_BASE + 0x2120)
  #define   I915_PIPE_CONTROL_NOTIFY_INTERRUPT          (1<<18)
  #define   I915_DISPLAY_PORT_INTERRUPT                 (1<<17)
  #define   I915_RENDER_COMMAND_PARSER_ERROR_INTERRUPT  (1<<15)
  #define   DPFC_CTL_EN         (1<<31)
  #define   DPFC_CTL_PLANEA     (0<<30)
  #define   DPFC_CTL_PLANEB     (1<<30)
 +#define   IVB_DPFC_CTL_PLANE_SHIFT    (29)
  #define   DPFC_CTL_FENCE_EN   (1<<29)
 +#define   IVB_DPFC_CTL_FENCE_EN       (1<<28)
  #define   DPFC_CTL_PERSISTENT_MODE    (1<<25)
  #define   DPFC_SR_EN          (1<<10)
  #define   DPFC_CTL_LIMIT_1X   (0<<6)
  #define ILK_DPFC_CHICKEN      0x43224
  #define ILK_FBC_RT_BASE               0x2128
  #define   ILK_FBC_RT_VALID    (1<<0)
 +#define   SNB_FBC_FRONT_BUFFER        (1<<1)
  
  #define ILK_DISPLAY_CHICKEN1  0x42000
  #define   ILK_FBCQ_DIS                (1<<22)
  #define   SNB_CPU_FENCE_ENABLE        (1<<29)
  #define DPFC_CPU_FENCE_OFFSET 0x100104
  
 +/* Framebuffer compression for Ivybridge */
 +#define IVB_FBC_RT_BASE                       0x7020
 +
 +
 +#define _HSW_PIPE_SLICE_CHICKEN_1_A   0x420B0
 +#define _HSW_PIPE_SLICE_CHICKEN_1_B   0x420B4
 +#define   HSW_BYPASS_FBC_QUEUE                (1<<22)
 +#define HSW_PIPE_SLICE_CHICKEN_1(pipe) _PIPE(pipe, + \
 +                                           _HSW_PIPE_SLICE_CHICKEN_1_A, + \
 +                                           _HSW_PIPE_SLICE_CHICKEN_1_B)
 +
 +#define HSW_CLKGATE_DISABLE_PART_1    0x46500
 +#define   HSW_DPFC_GATING_DISABLE     (1<<23)
  
  /*
   * GPIO regs
  #define   DPLL_FPA01_P1_POST_DIV_MASK 0x00ff0000 /* i915 */
  #define   DPLL_FPA01_P1_POST_DIV_MASK_PINEVIEW        0x00ff8000 /* Pineview */
  #define   DPLL_LOCK_VLV                       (1<<15)
 +#define   DPLL_INTEGRATED_CRI_CLK_VLV (1<<14)
  #define   DPLL_INTEGRATED_CLOCK_VLV   (1<<13)
 +#define   DPLL_PORTC_READY_MASK               (0xf << 4)
 +#define   DPLL_PORTB_READY_MASK               (0xf)
  
  #define   DPLL_FPA01_P1_POST_DIV_MASK_I830    0x001f0000
  /*
  #define   BLM_PIPE_A                  (0 << 29)
  #define   BLM_PIPE_B                  (1 << 29)
  #define   BLM_PIPE_C                  (2 << 29) /* ivb + */
 +#define   BLM_TRANSCODER_A            BLM_PIPE_A /* hsw */
 +#define   BLM_TRANSCODER_B            BLM_PIPE_B
 +#define   BLM_TRANSCODER_C            BLM_PIPE_C
 +#define   BLM_TRANSCODER_EDP          (3 << 29)
  #define   BLM_PIPE(pipe)              ((pipe) << 29)
  #define   BLM_POLARITY_I965           (1 << 28) /* gen4 only */
  #define   BLM_PHASE_IN_INTERUPT_STATUS        (1 << 26)
  #define   DP_PRE_EMPHASIS_SHIFT               22
  
  /* How many wires to use. I guess 3 was too hard */
 -#define   DP_PORT_WIDTH_1             (0 << 19)
 -#define   DP_PORT_WIDTH_2             (1 << 19)
 -#define   DP_PORT_WIDTH_4             (3 << 19)
 +#define   DP_PORT_WIDTH(width)                (((width) - 1) << 19)
  #define   DP_PORT_WIDTH_MASK          (7 << 19)
  
  /* Mystic DPCD version 1.1 special mode */
   * which is after the LUTs, so we want the bytes for our color format.
   * For our current usage, this is always 3, one byte for R, G and B.
   */
 -#define _PIPEA_GMCH_DATA_M                    0x70050
 -#define _PIPEB_GMCH_DATA_M                    0x71050
 +#define _PIPEA_DATA_M_G4X     0x70050
 +#define _PIPEB_DATA_M_G4X     0x71050
  
  /* Transfer unit size for display port - 1, default is 0x3f (for TU size 64) */
- #define   PIPE_GMCH_DATA_M_TU_SIZE_MASK               (0x3f << 25)
- #define   PIPE_GMCH_DATA_M_TU_SIZE_SHIFT      25
+ #define  TU_SIZE(x)             (((x)-1) << 25) /* default size 64 */
 +#define  TU_SIZE_SHIFT                25
+ #define  TU_SIZE_MASK           (0x3f << 25)
  
- #define   PIPE_GMCH_DATA_M_MASK                       (0xffffff)
+ #define  DATA_LINK_M_N_MASK   (0xffffff)
+ #define  DATA_LINK_N_MAX      (0x800000)
  
 -#define _PIPEA_GMCH_DATA_N                    0x70054
 -#define _PIPEB_GMCH_DATA_N                    0x71054
 +#define _PIPEA_DATA_N_G4X     0x70054
 +#define _PIPEB_DATA_N_G4X     0x71054
 +#define   PIPE_GMCH_DATA_N_MASK                       (0xffffff)
  
  /*
   * Computing Link M and N values for the Display Port link
   * Attributes and VB-ID.
   */
  
 -#define _PIPEA_DP_LINK_M                              0x70060
 -#define _PIPEB_DP_LINK_M                              0x71060
 +#define _PIPEA_LINK_M_G4X     0x70060
 +#define _PIPEB_LINK_M_G4X     0x71060
 +#define   PIPEA_DP_LINK_M_MASK                        (0xffffff)
  
 -#define _PIPEA_DP_LINK_N                              0x70064
 -#define _PIPEB_DP_LINK_N                              0x71064
 +#define _PIPEA_LINK_N_G4X     0x70064
 +#define _PIPEB_LINK_N_G4X     0x71064
 +#define   PIPEA_DP_LINK_N_MASK                        (0xffffff)
  
 -#define PIPE_GMCH_DATA_M(pipe) _PIPE(pipe, _PIPEA_GMCH_DATA_M, _PIPEB_GMCH_DATA_M)
 -#define PIPE_GMCH_DATA_N(pipe) _PIPE(pipe, _PIPEA_GMCH_DATA_N, _PIPEB_GMCH_DATA_N)
 -#define PIPE_DP_LINK_M(pipe) _PIPE(pipe, _PIPEA_DP_LINK_M, _PIPEB_DP_LINK_M)
 -#define PIPE_DP_LINK_N(pipe) _PIPE(pipe, _PIPEA_DP_LINK_N, _PIPEB_DP_LINK_N)
 +#define PIPE_DATA_M_G4X(pipe) _PIPE(pipe, _PIPEA_DATA_M_G4X, _PIPEB_DATA_M_G4X)
 +#define PIPE_DATA_N_G4X(pipe) _PIPE(pipe, _PIPEA_DATA_N_G4X, _PIPEB_DATA_N_G4X)
 +#define PIPE_LINK_M_G4X(pipe) _PIPE(pipe, _PIPEA_LINK_M_G4X, _PIPEB_LINK_M_G4X)
 +#define PIPE_LINK_N_G4X(pipe) _PIPE(pipe, _PIPEA_LINK_N_G4X, _PIPEB_LINK_N_G4X)
  
  /* Display & cursor control */
  
  #define   PIPECONF_INTERLACED_ILK             (3 << 21)
  #define   PIPECONF_INTERLACED_DBL_ILK         (4 << 21) /* ilk/snb only */
  #define   PIPECONF_PFIT_PF_INTERLACED_DBL_ILK (5 << 21) /* ilk/snb only */
 +#define   PIPECONF_INTERLACE_MODE_MASK                (7 << 21)
  #define   PIPECONF_CXSR_DOWNCLOCK     (1<<16)
  #define   PIPECONF_COLOR_RANGE_SELECT (1 << 13)
  #define   PIPECONF_BPC_MASK   (0x7 << 5)
  
  
  #define _PIPEA_DATA_M1           (dev_priv->info->display_mmio_offset + 0x60030)
- #define  TU_SIZE(x)             (((x)-1) << 25) /* default size 64 */
- #define  TU_SIZE_MASK           0x7e000000
  #define  PIPE_DATA_M1_OFFSET    0
  #define _PIPEA_DATA_N1           (dev_priv->info->display_mmio_offset + 0x60034)
  #define  PIPE_DATA_N1_OFFSET    0
  #define DE_PIPEA_FIFO_UNDERRUN  (1 << 0)
  
  /* More Ivybridge lolz */
 -#define DE_ERR_DEBUG_IVB              (1<<30)
 +#define DE_ERR_INT_IVB                        (1<<30)
  #define DE_GSE_IVB                    (1<<29)
  #define DE_PCH_EVENT_IVB              (1<<28)
  #define DE_DP_A_HOTPLUG_IVB           (1<<27)
                                 SDE_PORTC_HOTPLUG_CPT |        \
                                 SDE_PORTB_HOTPLUG_CPT)
  #define SDE_GMBUS_CPT         (1 << 17)
 +#define SDE_ERROR_CPT         (1 << 16)
  #define SDE_AUDIO_CP_REQ_C_CPT        (1 << 10)
  #define SDE_AUDIO_CP_CHG_C_CPT        (1 << 9)
  #define SDE_FDI_RXC_CPT               (1 << 8)
  #define SDEIIR  0xc4008
  #define SDEIER  0xc400c
  
 +#define SERR_INT                      0xc4040
 +#define  SERR_INT_POISON              (1<<31)
 +#define  SERR_INT_TRANS_C_FIFO_UNDERRUN       (1<<6)
 +#define  SERR_INT_TRANS_B_FIFO_UNDERRUN       (1<<3)
 +#define  SERR_INT_TRANS_A_FIFO_UNDERRUN       (1<<0)
 +
  /* digital port hotplug */
  #define PCH_PORT_HOTPLUG        0xc4030               /* SHOTPLUG_CTL */
  #define PORTD_HOTPLUG_ENABLE            (1 << 20)
  
  /* transcoder */
  
 -#define _TRANS_HTOTAL_A          0xe0000
 -#define  TRANS_HTOTAL_SHIFT     16
 -#define  TRANS_HACTIVE_SHIFT    0
 -#define _TRANS_HBLANK_A          0xe0004
 -#define  TRANS_HBLANK_END_SHIFT 16
 -#define  TRANS_HBLANK_START_SHIFT 0
 -#define _TRANS_HSYNC_A           0xe0008
 -#define  TRANS_HSYNC_END_SHIFT  16
 -#define  TRANS_HSYNC_START_SHIFT 0
 -#define _TRANS_VTOTAL_A          0xe000c
 -#define  TRANS_VTOTAL_SHIFT     16
 -#define  TRANS_VACTIVE_SHIFT    0
 -#define _TRANS_VBLANK_A          0xe0010
 -#define  TRANS_VBLANK_END_SHIFT 16
 -#define  TRANS_VBLANK_START_SHIFT 0
 -#define _TRANS_VSYNC_A           0xe0014
 -#define  TRANS_VSYNC_END_SHIFT  16
 -#define  TRANS_VSYNC_START_SHIFT 0
 -#define _TRANS_VSYNCSHIFT_A   0xe0028
 -
 -#define _TRANSA_DATA_M1          0xe0030
 -#define _TRANSA_DATA_N1          0xe0034
 -#define _TRANSA_DATA_M2          0xe0038
 -#define _TRANSA_DATA_N2          0xe003c
 -#define _TRANSA_DP_LINK_M1       0xe0040
 -#define _TRANSA_DP_LINK_N1       0xe0044
 -#define _TRANSA_DP_LINK_M2       0xe0048
 -#define _TRANSA_DP_LINK_N2       0xe004c
 +#define _PCH_TRANS_HTOTAL_A           0xe0000
 +#define  TRANS_HTOTAL_SHIFT           16
 +#define  TRANS_HACTIVE_SHIFT          0
 +#define _PCH_TRANS_HBLANK_A           0xe0004
 +#define  TRANS_HBLANK_END_SHIFT               16
 +#define  TRANS_HBLANK_START_SHIFT     0
 +#define _PCH_TRANS_HSYNC_A            0xe0008
 +#define  TRANS_HSYNC_END_SHIFT                16
 +#define  TRANS_HSYNC_START_SHIFT      0
 +#define _PCH_TRANS_VTOTAL_A           0xe000c
 +#define  TRANS_VTOTAL_SHIFT           16
 +#define  TRANS_VACTIVE_SHIFT          0
 +#define _PCH_TRANS_VBLANK_A           0xe0010
 +#define  TRANS_VBLANK_END_SHIFT               16
 +#define  TRANS_VBLANK_START_SHIFT     0
 +#define _PCH_TRANS_VSYNC_A            0xe0014
 +#define  TRANS_VSYNC_END_SHIFT                16
 +#define  TRANS_VSYNC_START_SHIFT      0
 +#define _PCH_TRANS_VSYNCSHIFT_A               0xe0028
 +
 +#define _PCH_TRANSA_DATA_M1   0xe0030
 +#define _PCH_TRANSA_DATA_N1   0xe0034
 +#define _PCH_TRANSA_DATA_M2   0xe0038
 +#define _PCH_TRANSA_DATA_N2   0xe003c
 +#define _PCH_TRANSA_LINK_M1   0xe0040
 +#define _PCH_TRANSA_LINK_N1   0xe0044
 +#define _PCH_TRANSA_LINK_M2   0xe0048
 +#define _PCH_TRANSA_LINK_N2   0xe004c
  
  /* Per-transcoder DIP controls */
  
  #define HSW_TVIDEO_DIP_VSC_DATA(trans) \
         _TRANSCODER(trans, HSW_VIDEO_DIP_VSC_DATA_A, HSW_VIDEO_DIP_VSC_DATA_B)
  
 -#define _TRANS_HTOTAL_B          0xe1000
 -#define _TRANS_HBLANK_B          0xe1004
 -#define _TRANS_HSYNC_B           0xe1008
 -#define _TRANS_VTOTAL_B          0xe100c
 -#define _TRANS_VBLANK_B          0xe1010
 -#define _TRANS_VSYNC_B           0xe1014
 -#define _TRANS_VSYNCSHIFT_B    0xe1028
 -
 -#define TRANS_HTOTAL(pipe) _PIPE(pipe, _TRANS_HTOTAL_A, _TRANS_HTOTAL_B)
 -#define TRANS_HBLANK(pipe) _PIPE(pipe, _TRANS_HBLANK_A, _TRANS_HBLANK_B)
 -#define TRANS_HSYNC(pipe) _PIPE(pipe, _TRANS_HSYNC_A, _TRANS_HSYNC_B)
 -#define TRANS_VTOTAL(pipe) _PIPE(pipe, _TRANS_VTOTAL_A, _TRANS_VTOTAL_B)
 -#define TRANS_VBLANK(pipe) _PIPE(pipe, _TRANS_VBLANK_A, _TRANS_VBLANK_B)
 -#define TRANS_VSYNC(pipe) _PIPE(pipe, _TRANS_VSYNC_A, _TRANS_VSYNC_B)
 -#define TRANS_VSYNCSHIFT(pipe) _PIPE(pipe, _TRANS_VSYNCSHIFT_A, \
 -                                   _TRANS_VSYNCSHIFT_B)
 -
 -#define _TRANSB_DATA_M1          0xe1030
 -#define _TRANSB_DATA_N1          0xe1034
 -#define _TRANSB_DATA_M2          0xe1038
 -#define _TRANSB_DATA_N2          0xe103c
 -#define _TRANSB_DP_LINK_M1       0xe1040
 -#define _TRANSB_DP_LINK_N1       0xe1044
 -#define _TRANSB_DP_LINK_M2       0xe1048
 -#define _TRANSB_DP_LINK_N2       0xe104c
 -
 -#define TRANSDATA_M1(pipe) _PIPE(pipe, _TRANSA_DATA_M1, _TRANSB_DATA_M1)
 -#define TRANSDATA_N1(pipe) _PIPE(pipe, _TRANSA_DATA_N1, _TRANSB_DATA_N1)
 -#define TRANSDATA_M2(pipe) _PIPE(pipe, _TRANSA_DATA_M2, _TRANSB_DATA_M2)
 -#define TRANSDATA_N2(pipe) _PIPE(pipe, _TRANSA_DATA_N2, _TRANSB_DATA_N2)
 -#define TRANSDPLINK_M1(pipe) _PIPE(pipe, _TRANSA_DP_LINK_M1, _TRANSB_DP_LINK_M1)
 -#define TRANSDPLINK_N1(pipe) _PIPE(pipe, _TRANSA_DP_LINK_N1, _TRANSB_DP_LINK_N1)
 -#define TRANSDPLINK_M2(pipe) _PIPE(pipe, _TRANSA_DP_LINK_M2, _TRANSB_DP_LINK_M2)
 -#define TRANSDPLINK_N2(pipe) _PIPE(pipe, _TRANSA_DP_LINK_N2, _TRANSB_DP_LINK_N2)
 -
 -#define _TRANSACONF              0xf0008
 -#define _TRANSBCONF              0xf1008
 -#define TRANSCONF(plane) _PIPE(plane, _TRANSACONF, _TRANSBCONF)
 +#define _PCH_TRANS_HTOTAL_B          0xe1000
 +#define _PCH_TRANS_HBLANK_B          0xe1004
 +#define _PCH_TRANS_HSYNC_B           0xe1008
 +#define _PCH_TRANS_VTOTAL_B          0xe100c
 +#define _PCH_TRANS_VBLANK_B          0xe1010
 +#define _PCH_TRANS_VSYNC_B           0xe1014
 +#define _PCH_TRANS_VSYNCSHIFT_B        0xe1028
 +
 +#define PCH_TRANS_HTOTAL(pipe) _PIPE(pipe, _PCH_TRANS_HTOTAL_A, _PCH_TRANS_HTOTAL_B)
 +#define PCH_TRANS_HBLANK(pipe) _PIPE(pipe, _PCH_TRANS_HBLANK_A, _PCH_TRANS_HBLANK_B)
 +#define PCH_TRANS_HSYNC(pipe) _PIPE(pipe, _PCH_TRANS_HSYNC_A, _PCH_TRANS_HSYNC_B)
 +#define PCH_TRANS_VTOTAL(pipe) _PIPE(pipe, _PCH_TRANS_VTOTAL_A, _PCH_TRANS_VTOTAL_B)
 +#define PCH_TRANS_VBLANK(pipe) _PIPE(pipe, _PCH_TRANS_VBLANK_A, _PCH_TRANS_VBLANK_B)
 +#define PCH_TRANS_VSYNC(pipe) _PIPE(pipe, _PCH_TRANS_VSYNC_A, _PCH_TRANS_VSYNC_B)
 +#define PCH_TRANS_VSYNCSHIFT(pipe) _PIPE(pipe, _PCH_TRANS_VSYNCSHIFT_A, \
 +                                       _PCH_TRANS_VSYNCSHIFT_B)
 +
 +#define _PCH_TRANSB_DATA_M1   0xe1030
 +#define _PCH_TRANSB_DATA_N1   0xe1034
 +#define _PCH_TRANSB_DATA_M2   0xe1038
 +#define _PCH_TRANSB_DATA_N2   0xe103c
 +#define _PCH_TRANSB_LINK_M1   0xe1040
 +#define _PCH_TRANSB_LINK_N1   0xe1044
 +#define _PCH_TRANSB_LINK_M2   0xe1048
 +#define _PCH_TRANSB_LINK_N2   0xe104c
 +
 +#define PCH_TRANS_DATA_M1(pipe) _PIPE(pipe, _PCH_TRANSA_DATA_M1, _PCH_TRANSB_DATA_M1)
 +#define PCH_TRANS_DATA_N1(pipe) _PIPE(pipe, _PCH_TRANSA_DATA_N1, _PCH_TRANSB_DATA_N1)
 +#define PCH_TRANS_DATA_M2(pipe) _PIPE(pipe, _PCH_TRANSA_DATA_M2, _PCH_TRANSB_DATA_M2)
 +#define PCH_TRANS_DATA_N2(pipe) _PIPE(pipe, _PCH_TRANSA_DATA_N2, _PCH_TRANSB_DATA_N2)
 +#define PCH_TRANS_LINK_M1(pipe) _PIPE(pipe, _PCH_TRANSA_LINK_M1, _PCH_TRANSB_LINK_M1)
 +#define PCH_TRANS_LINK_N1(pipe) _PIPE(pipe, _PCH_TRANSA_LINK_N1, _PCH_TRANSB_LINK_N1)
 +#define PCH_TRANS_LINK_M2(pipe) _PIPE(pipe, _PCH_TRANSA_LINK_M2, _PCH_TRANSB_LINK_M2)
 +#define PCH_TRANS_LINK_N2(pipe) _PIPE(pipe, _PCH_TRANSA_LINK_N2, _PCH_TRANSB_LINK_N2)
 +
 +#define _PCH_TRANSACONF              0xf0008
 +#define _PCH_TRANSBCONF              0xf1008
 +#define PCH_TRANSCONF(pipe) _PIPE(pipe, _PCH_TRANSACONF, _PCH_TRANSBCONF)
 +#define LPT_TRANSCONF         _PCH_TRANSACONF /* lpt has only one transcoder */
  #define  TRANS_DISABLE          (0<<31)
  #define  TRANS_ENABLE           (1<<31)
  #define  TRANS_STATE_MASK       (1<<30)
  #define  FDI_LINK_TRAIN_600MV_3_5DB_SNB_B     (0x39<<22)
  #define  FDI_LINK_TRAIN_800MV_0DB_SNB_B               (0x38<<22)
  #define  FDI_LINK_TRAIN_VOL_EMP_MASK          (0x3f<<22)
 -#define  FDI_DP_PORT_WIDTH_X1           (0<<19)
 -#define  FDI_DP_PORT_WIDTH_X2           (1<<19)
 -#define  FDI_DP_PORT_WIDTH_X3           (2<<19)
 -#define  FDI_DP_PORT_WIDTH_X4           (3<<19)
 +#define  FDI_DP_PORT_WIDTH_SHIFT              19
 +#define  FDI_DP_PORT_WIDTH_MASK                       (7 << FDI_DP_PORT_WIDTH_SHIFT)
 +#define  FDI_DP_PORT_WIDTH(width)           (((width) - 1) << FDI_DP_PORT_WIDTH_SHIFT)
  #define  FDI_TX_ENHANCE_FRAME_ENABLE    (1<<18)
  /* Ironlake: hardwired to 1 */
  #define  FDI_TX_PLL_ENABLE              (1<<14)
  /* train, dp width same as FDI_TX */
  #define  FDI_FS_ERRC_ENABLE           (1<<27)
  #define  FDI_FE_ERRC_ENABLE           (1<<26)
 -#define  FDI_DP_PORT_WIDTH_X8           (7<<19)
  #define  FDI_RX_POLARITY_REVERSED_LPT (1<<16)
  #define  FDI_8BPC                       (0<<16)
  #define  FDI_10BPC                      (1<<16)
  #define  FDI_LINK_TRAIN_PATTERN_IDLE_CPT      (2<<8)
  #define  FDI_LINK_TRAIN_NORMAL_CPT            (3<<8)
  #define  FDI_LINK_TRAIN_PATTERN_MASK_CPT      (3<<8)
 -/* LPT */
 -#define  FDI_PORT_WIDTH_2X_LPT                        (1<<19)
 -#define  FDI_PORT_WIDTH_1X_LPT                        (0<<19)
  
  #define _FDI_RXA_MISC                 0xf0010
  #define _FDI_RXB_MISC                 0xf1010
  #define   GEN6_RC_CTL_RC6_ENABLE              (1<<18)
  #define   GEN6_RC_CTL_RC1e_ENABLE             (1<<20)
  #define   GEN6_RC_CTL_RC7_ENABLE              (1<<22)
 +#define   GEN7_RC_CTL_TO_MODE                 (1<<28)
  #define   GEN6_RC_CTL_EI_MODE(x)              ((x)<<27)
  #define   GEN6_RC_CTL_HW_ENABLE                       (1<<31)
  #define GEN6_RP_DOWN_TIMEOUT                  0xA010
  #define   IOSF_BAR_SHIFT                      1
  #define   IOSF_SB_BUSY                                (1<<0)
  #define   IOSF_PORT_PUNIT                     0x4
 +#define   IOSF_PORT_NC                                0x11
  #define VLV_IOSF_DATA                         0x182104
  #define VLV_IOSF_ADDR                         0x182108
  
  #define PUNIT_OPCODE_REG_READ                 6
  #define PUNIT_OPCODE_REG_WRITE                        7
  
 +#define PUNIT_REG_GPU_LFM                     0xd3
 +#define PUNIT_REG_GPU_FREQ_REQ                        0xd4
 +#define PUNIT_REG_GPU_FREQ_STS                        0xd8
 +#define PUNIT_REG_MEDIA_TURBO_FREQ_REQ                0xdc
 +
 +#define PUNIT_FUSE_BUS2                               0xf6 /* bits 47:40 */
 +#define PUNIT_FUSE_BUS1                               0xf5 /* bits 55:48 */
 +
 +#define IOSF_NC_FB_GFX_FREQ_FUSE              0x1c
 +#define   FB_GFX_MAX_FREQ_FUSE_SHIFT          3
 +#define   FB_GFX_MAX_FREQ_FUSE_MASK           0x000007f8
 +#define   FB_GFX_FGUARANTEED_FREQ_FUSE_SHIFT  11
 +#define   FB_GFX_FGUARANTEED_FREQ_FUSE_MASK   0x0007f800
 +#define IOSF_NC_FB_GFX_FMAX_FUSE_HI           0x34
 +#define   FB_FMAX_VMIN_FREQ_HI_MASK           0x00000007
 +#define IOSF_NC_FB_GFX_FMAX_FUSE_LO           0x30
 +#define   FB_FMAX_VMIN_FREQ_LO_SHIFT          27
 +#define   FB_FMAX_VMIN_FREQ_LO_MASK           0xf8000000
 +
  #define GEN6_GT_CORE_STATUS           0x138060
  #define   GEN6_CORE_CPD_STATE_MASK    (7<<4)
  #define   GEN6_RCn_MASK                       7
  #define  TRANS_DDI_EDP_INPUT_B_ONOFF  (5<<12)
  #define  TRANS_DDI_EDP_INPUT_C_ONOFF  (6<<12)
  #define  TRANS_DDI_BFI_ENABLE         (1<<4)
 -#define  TRANS_DDI_PORT_WIDTH_X1      (0<<1)
 -#define  TRANS_DDI_PORT_WIDTH_X2      (1<<1)
 -#define  TRANS_DDI_PORT_WIDTH_X4      (3<<1)
  
  /* DisplayPort Transport Control */
  #define DP_TP_CTL_A                   0x64040
  #define  DDI_BUF_PORT_REVERSAL                        (1<<16)
  #define  DDI_BUF_IS_IDLE                      (1<<7)
  #define  DDI_A_4_LANES                                (1<<4)
 -#define  DDI_PORT_WIDTH_X1                    (0<<1)
 -#define  DDI_PORT_WIDTH_X2                    (1<<1)
 -#define  DDI_PORT_WIDTH_X4                    (3<<1)
 +#define  DDI_PORT_WIDTH(width)                        (((width) - 1) << 1)
  #define  DDI_INIT_DISPLAY_DETECTED            (1<<0)
  
  /* DDI Buffer Translations */
  #define _PIPE_A_CSC_COEFF_RV_GV       0x49020
  #define _PIPE_A_CSC_COEFF_BV  0x49024
  #define _PIPE_A_CSC_MODE      0x49028
 +#define   CSC_BLACK_SCREEN_OFFSET     (1 << 2)
 +#define   CSC_POSITION_BEFORE_GAMMA   (1 << 1)
 +#define   CSC_MODE_YUV_TO_RGB         (1 << 0)
  #define _PIPE_A_CSC_PREOFF_HI 0x49030
  #define _PIPE_A_CSC_PREOFF_ME 0x49034
  #define _PIPE_A_CSC_PREOFF_LO 0x49038
  #define _PIPE_B_CSC_POSTOFF_ME        0x49144
  #define _PIPE_B_CSC_POSTOFF_LO        0x49148
  
 -#define CSC_BLACK_SCREEN_OFFSET (1 << 2)
 -#define CSC_POSITION_BEFORE_GAMMA (1 << 1)
 -#define CSC_MODE_YUV_TO_RGB (1 << 0)
 -
  #define PIPE_CSC_COEFF_RY_GY(pipe) _PIPE(pipe, _PIPE_A_CSC_COEFF_RY_GY, _PIPE_B_CSC_COEFF_RY_GY)
  #define PIPE_CSC_COEFF_BY(pipe) _PIPE(pipe, _PIPE_A_CSC_COEFF_BY, _PIPE_B_CSC_COEFF_BY)
  #define PIPE_CSC_COEFF_RU_GU(pipe) _PIPE(pipe, _PIPE_A_CSC_COEFF_RU_GU, _PIPE_B_CSC_COEFF_RU_GU)
index cc414f1a0b92c4379f556fc5c23bff703b457110,58b4a53715cdc76073d05e05435a62b0c269cc65..66a0c6f0bb818400d216a4e32136ada0b219b19c
@@@ -45,6 -45,9 +45,9 @@@
  
  struct intel_crt {
        struct intel_encoder base;
+       /* DPMS state is stored in the connector, which we need in the
+        * encoder's enable/disable callbacks */
+       struct intel_connector *connector;
        bool force_hotplug_required;
        u32 adpa_reg;
  };
@@@ -81,29 -84,6 +84,6 @@@ static bool intel_crt_get_hw_state(stru
        return true;
  }
  
- static void intel_disable_crt(struct intel_encoder *encoder)
- {
-       struct drm_i915_private *dev_priv = encoder->base.dev->dev_private;
-       struct intel_crt *crt = intel_encoder_to_crt(encoder);
-       u32 temp;
-       temp = I915_READ(crt->adpa_reg);
-       temp |= ADPA_HSYNC_CNTL_DISABLE | ADPA_VSYNC_CNTL_DISABLE;
-       temp &= ~ADPA_DAC_ENABLE;
-       I915_WRITE(crt->adpa_reg, temp);
- }
- static void intel_enable_crt(struct intel_encoder *encoder)
- {
-       struct drm_i915_private *dev_priv = encoder->base.dev->dev_private;
-       struct intel_crt *crt = intel_encoder_to_crt(encoder);
-       u32 temp;
-       temp = I915_READ(crt->adpa_reg);
-       temp |= ADPA_DAC_ENABLE;
-       I915_WRITE(crt->adpa_reg, temp);
- }
  /* Note: The caller is required to filter out dpms modes not supported by the
   * platform. */
  static void intel_crt_set_dpms(struct intel_encoder *encoder, int mode)
        I915_WRITE(crt->adpa_reg, temp);
  }
  
+ static void intel_disable_crt(struct intel_encoder *encoder)
+ {
+       intel_crt_set_dpms(encoder, DRM_MODE_DPMS_OFF);
+ }
+ static void intel_enable_crt(struct intel_encoder *encoder)
+ {
+       struct intel_crt *crt = intel_encoder_to_crt(encoder);
+       intel_crt_set_dpms(encoder, crt->connector->base.dpms);
+ }
  static void intel_crt_dpms(struct drm_connector *connector, int mode)
  {
        struct drm_device *dev = connector->dev;
@@@ -214,10 -207,6 +207,10 @@@ static bool intel_crt_compute_config(st
        if (HAS_PCH_SPLIT(dev))
                pipe_config->has_pch_encoder = true;
  
 +      /* LPT FDI RX only supports 8bpc. */
 +      if (HAS_PCH_LPT(dev))
 +              pipe_config->pipe_bpp = 24;
 +
        return true;
  }
  
@@@ -442,7 -431,7 +435,7 @@@ static bool intel_crt_detect_ddc(struc
  
        BUG_ON(crt->base.type != INTEL_OUTPUT_ANALOG);
  
 -      i2c = intel_gmbus_get_adapter(dev_priv, dev_priv->crt_ddc_pin);
 +      i2c = intel_gmbus_get_adapter(dev_priv, dev_priv->vbt.crt_ddc_pin);
        edid = intel_crt_get_edid(connector, i2c);
  
        if (edid) {
@@@ -648,7 -637,7 +641,7 @@@ static int intel_crt_get_modes(struct d
        int ret;
        struct i2c_adapter *i2c;
  
 -      i2c = intel_gmbus_get_adapter(dev_priv, dev_priv->crt_ddc_pin);
 +      i2c = intel_gmbus_get_adapter(dev_priv, dev_priv->vbt.crt_ddc_pin);
        ret = intel_crt_ddc_get_modes(connector, i2c);
        if (ret || !IS_G4X(dev))
                return ret;
@@@ -753,6 -742,7 +746,7 @@@ void intel_crt_init(struct drm_device *
        }
  
        connector = &intel_connector->base;
+       crt->connector = intel_connector;
        drm_connector_init(dev, &intel_connector->base,
                           &intel_crt_connector_funcs, DRM_MODE_CONNECTOR_VGA);
  
index cddcf4af7a5a8deb1f77157f005d5891f3646934,fb961bb81903c95550289845a846bd0308c448d7..062de679f38f3ebd9143c61ac3c6fca24bfbd785
@@@ -174,8 -174,6 +174,8 @@@ void hsw_fdi_link_train(struct drm_crt
         * mode set "sequence for CRT port" document:
         * - TP1 to TP2 time with the default value
         * - FDI delay to 90h
 +       *
 +       * WaFDIAutoLinkSetTimingOverrride:hsw
         */
        I915_WRITE(_FDI_RXA_MISC, FDI_RX_PWRDN_LANE1_VAL(2) |
                                  FDI_RX_PWRDN_LANE0_VAL(2) |
  
        /* Enable the PCH Receiver FDI PLL */
        rx_ctl_val = dev_priv->fdi_rx_config | FDI_RX_ENHANCE_FRAME_ENABLE |
 -                   FDI_RX_PLL_ENABLE | ((intel_crtc->fdi_lanes - 1) << 19);
 +                   FDI_RX_PLL_ENABLE |
 +                   FDI_DP_PORT_WIDTH(intel_crtc->config.fdi_lanes);
        I915_WRITE(_FDI_RXA_CTL, rx_ctl_val);
        POSTING_READ(_FDI_RXA_CTL);
        udelay(220);
                 * port reversal bit */
                I915_WRITE(DDI_BUF_CTL(PORT_E),
                           DDI_BUF_CTL_ENABLE |
 -                         ((intel_crtc->fdi_lanes - 1) << 1) |
 +                         ((intel_crtc->config.fdi_lanes - 1) << 1) |
                           hsw_ddi_buf_ctl_values[i / 2]);
                POSTING_READ(DDI_BUF_CTL(PORT_E));
  
        DRM_ERROR("FDI link training failed!\n");
  }
  
 -/* WRPLL clock dividers */
 -struct wrpll_tmds_clock {
 -      u32 clock;
 -      u16 p;          /* Post divider */
 -      u16 n2;         /* Feedback divider */
 -      u16 r2;         /* Reference divider */
 -};
 -
 -/* Table of matching values for WRPLL clocks programming for each frequency.
 - * The code assumes this table is sorted. */
 -static const struct wrpll_tmds_clock wrpll_tmds_clock_table[] = {
 -      {19750, 38,     25,     18},
 -      {20000, 48,     32,     18},
 -      {21000, 36,     21,     15},
 -      {21912, 42,     29,     17},
 -      {22000, 36,     22,     15},
 -      {23000, 36,     23,     15},
 -      {23500, 40,     40,     23},
 -      {23750, 26,     16,     14},
 -      {24000, 36,     24,     15},
 -      {25000, 36,     25,     15},
 -      {25175, 26,     40,     33},
 -      {25200, 30,     21,     15},
 -      {26000, 36,     26,     15},
 -      {27000, 30,     21,     14},
 -      {27027, 18,     100,    111},
 -      {27500, 30,     29,     19},
 -      {28000, 34,     30,     17},
 -      {28320, 26,     30,     22},
 -      {28322, 32,     42,     25},
 -      {28750, 24,     23,     18},
 -      {29000, 30,     29,     18},
 -      {29750, 32,     30,     17},
 -      {30000, 30,     25,     15},
 -      {30750, 30,     41,     24},
 -      {31000, 30,     31,     18},
 -      {31500, 30,     28,     16},
 -      {32000, 30,     32,     18},
 -      {32500, 28,     32,     19},
 -      {33000, 24,     22,     15},
 -      {34000, 28,     30,     17},
 -      {35000, 26,     32,     19},
 -      {35500, 24,     30,     19},
 -      {36000, 26,     26,     15},
 -      {36750, 26,     46,     26},
 -      {37000, 24,     23,     14},
 -      {37762, 22,     40,     26},
 -      {37800, 20,     21,     15},
 -      {38000, 24,     27,     16},
 -      {38250, 24,     34,     20},
 -      {39000, 24,     26,     15},
 -      {40000, 24,     32,     18},
 -      {40500, 20,     21,     14},
 -      {40541, 22,     147,    89},
 -      {40750, 18,     19,     14},
 -      {41000, 16,     17,     14},
 -      {41500, 22,     44,     26},
 -      {41540, 22,     44,     26},
 -      {42000, 18,     21,     15},
 -      {42500, 22,     45,     26},
 -      {43000, 20,     43,     27},
 -      {43163, 20,     24,     15},
 -      {44000, 18,     22,     15},
 -      {44900, 20,     108,    65},
 -      {45000, 20,     25,     15},
 -      {45250, 20,     52,     31},
 -      {46000, 18,     23,     15},
 -      {46750, 20,     45,     26},
 -      {47000, 20,     40,     23},
 -      {48000, 18,     24,     15},
 -      {49000, 18,     49,     30},
 -      {49500, 16,     22,     15},
 -      {50000, 18,     25,     15},
 -      {50500, 18,     32,     19},
 -      {51000, 18,     34,     20},
 -      {52000, 18,     26,     15},
 -      {52406, 14,     34,     25},
 -      {53000, 16,     22,     14},
 -      {54000, 16,     24,     15},
 -      {54054, 16,     173,    108},
 -      {54500, 14,     24,     17},
 -      {55000, 12,     22,     18},
 -      {56000, 14,     45,     31},
 -      {56250, 16,     25,     15},
 -      {56750, 14,     25,     17},
 -      {57000, 16,     27,     16},
 -      {58000, 16,     43,     25},
 -      {58250, 16,     38,     22},
 -      {58750, 16,     40,     23},
 -      {59000, 14,     26,     17},
 -      {59341, 14,     40,     26},
 -      {59400, 16,     44,     25},
 -      {60000, 16,     32,     18},
 -      {60500, 12,     39,     29},
 -      {61000, 14,     49,     31},
 -      {62000, 14,     37,     23},
 -      {62250, 14,     42,     26},
 -      {63000, 12,     21,     15},
 -      {63500, 14,     28,     17},
 -      {64000, 12,     27,     19},
 -      {65000, 14,     32,     19},
 -      {65250, 12,     29,     20},
 -      {65500, 12,     32,     22},
 -      {66000, 12,     22,     15},
 -      {66667, 14,     38,     22},
 -      {66750, 10,     21,     17},
 -      {67000, 14,     33,     19},
 -      {67750, 14,     58,     33},
 -      {68000, 14,     30,     17},
 -      {68179, 14,     46,     26},
 -      {68250, 14,     46,     26},
 -      {69000, 12,     23,     15},
 -      {70000, 12,     28,     18},
 -      {71000, 12,     30,     19},
 -      {72000, 12,     24,     15},
 -      {73000, 10,     23,     17},
 -      {74000, 12,     23,     14},
 -      {74176, 8,      100,    91},
 -      {74250, 10,     22,     16},
 -      {74481, 12,     43,     26},
 -      {74500, 10,     29,     21},
 -      {75000, 12,     25,     15},
 -      {75250, 10,     39,     28},
 -      {76000, 12,     27,     16},
 -      {77000, 12,     53,     31},
 -      {78000, 12,     26,     15},
 -      {78750, 12,     28,     16},
 -      {79000, 10,     38,     26},
 -      {79500, 10,     28,     19},
 -      {80000, 12,     32,     18},
 -      {81000, 10,     21,     14},
 -      {81081, 6,      100,    111},
 -      {81624, 8,      29,     24},
 -      {82000, 8,      17,     14},
 -      {83000, 10,     40,     26},
 -      {83950, 10,     28,     18},
 -      {84000, 10,     28,     18},
 -      {84750, 6,      16,     17},
 -      {85000, 6,      17,     18},
 -      {85250, 10,     30,     19},
 -      {85750, 10,     27,     17},
 -      {86000, 10,     43,     27},
 -      {87000, 10,     29,     18},
 -      {88000, 10,     44,     27},
 -      {88500, 10,     41,     25},
 -      {89000, 10,     28,     17},
 -      {89012, 6,      90,     91},
 -      {89100, 10,     33,     20},
 -      {90000, 10,     25,     15},
 -      {91000, 10,     32,     19},
 -      {92000, 10,     46,     27},
 -      {93000, 10,     31,     18},
 -      {94000, 10,     40,     23},
 -      {94500, 10,     28,     16},
 -      {95000, 10,     44,     25},
 -      {95654, 10,     39,     22},
 -      {95750, 10,     39,     22},
 -      {96000, 10,     32,     18},
 -      {97000, 8,      23,     16},
 -      {97750, 8,      42,     29},
 -      {98000, 8,      45,     31},
 -      {99000, 8,      22,     15},
 -      {99750, 8,      34,     23},
 -      {100000,        6,      20,     18},
 -      {100500,        6,      19,     17},
 -      {101000,        6,      37,     33},
 -      {101250,        8,      21,     14},
 -      {102000,        6,      17,     15},
 -      {102250,        6,      25,     22},
 -      {103000,        8,      29,     19},
 -      {104000,        8,      37,     24},
 -      {105000,        8,      28,     18},
 -      {106000,        8,      22,     14},
 -      {107000,        8,      46,     29},
 -      {107214,        8,      27,     17},
 -      {108000,        8,      24,     15},
 -      {108108,        8,      173,    108},
 -      {109000,        6,      23,     19},
 -      {110000,        6,      22,     18},
 -      {110013,        6,      22,     18},
 -      {110250,        8,      49,     30},
 -      {110500,        8,      36,     22},
 -      {111000,        8,      23,     14},
 -      {111264,        8,      150,    91},
 -      {111375,        8,      33,     20},
 -      {112000,        8,      63,     38},
 -      {112500,        8,      25,     15},
 -      {113100,        8,      57,     34},
 -      {113309,        8,      42,     25},
 -      {114000,        8,      27,     16},
 -      {115000,        6,      23,     18},
 -      {116000,        8,      43,     25},
 -      {117000,        8,      26,     15},
 -      {117500,        8,      40,     23},
 -      {118000,        6,      38,     29},
 -      {119000,        8,      30,     17},
 -      {119500,        8,      46,     26},
 -      {119651,        8,      39,     22},
 -      {120000,        8,      32,     18},
 -      {121000,        6,      39,     29},
 -      {121250,        6,      31,     23},
 -      {121750,        6,      23,     17},
 -      {122000,        6,      42,     31},
 -      {122614,        6,      30,     22},
 -      {123000,        6,      41,     30},
 -      {123379,        6,      37,     27},
 -      {124000,        6,      51,     37},
 -      {125000,        6,      25,     18},
 -      {125250,        4,      13,     14},
 -      {125750,        4,      27,     29},
 -      {126000,        6,      21,     15},
 -      {127000,        6,      24,     17},
 -      {127250,        6,      41,     29},
 -      {128000,        6,      27,     19},
 -      {129000,        6,      43,     30},
 -      {129859,        4,      25,     26},
 -      {130000,        6,      26,     18},
 -      {130250,        6,      42,     29},
 -      {131000,        6,      32,     22},
 -      {131500,        6,      38,     26},
 -      {131850,        6,      41,     28},
 -      {132000,        6,      22,     15},
 -      {132750,        6,      28,     19},
 -      {133000,        6,      34,     23},
 -      {133330,        6,      37,     25},
 -      {134000,        6,      61,     41},
 -      {135000,        6,      21,     14},
 -      {135250,        6,      167,    111},
 -      {136000,        6,      62,     41},
 -      {137000,        6,      35,     23},
 -      {138000,        6,      23,     15},
 -      {138500,        6,      40,     26},
 -      {138750,        6,      37,     24},
 -      {139000,        6,      34,     22},
 -      {139050,        6,      34,     22},
 -      {139054,        6,      34,     22},
 -      {140000,        6,      28,     18},
 -      {141000,        6,      36,     23},
 -      {141500,        6,      22,     14},
 -      {142000,        6,      30,     19},
 -      {143000,        6,      27,     17},
 -      {143472,        4,      17,     16},
 -      {144000,        6,      24,     15},
 -      {145000,        6,      29,     18},
 -      {146000,        6,      47,     29},
 -      {146250,        6,      26,     16},
 -      {147000,        6,      49,     30},
 -      {147891,        6,      23,     14},
 -      {148000,        6,      23,     14},
 -      {148250,        6,      28,     17},
 -      {148352,        4,      100,    91},
 -      {148500,        6,      33,     20},
 -      {149000,        6,      48,     29},
 -      {150000,        6,      25,     15},
 -      {151000,        4,      19,     17},
 -      {152000,        6,      27,     16},
 -      {152280,        6,      44,     26},
 -      {153000,        6,      34,     20},
 -      {154000,        6,      53,     31},
 -      {155000,        6,      31,     18},
 -      {155250,        6,      50,     29},
 -      {155750,        6,      45,     26},
 -      {156000,        6,      26,     15},
 -      {157000,        6,      61,     35},
 -      {157500,        6,      28,     16},
 -      {158000,        6,      65,     37},
 -      {158250,        6,      44,     25},
 -      {159000,        6,      53,     30},
 -      {159500,        6,      39,     22},
 -      {160000,        6,      32,     18},
 -      {161000,        4,      31,     26},
 -      {162000,        4,      18,     15},
 -      {162162,        4,      131,    109},
 -      {162500,        4,      53,     44},
 -      {163000,        4,      29,     24},
 -      {164000,        4,      17,     14},
 -      {165000,        4,      22,     18},
 -      {166000,        4,      32,     26},
 -      {167000,        4,      26,     21},
 -      {168000,        4,      46,     37},
 -      {169000,        4,      104,    83},
 -      {169128,        4,      64,     51},
 -      {169500,        4,      39,     31},
 -      {170000,        4,      34,     27},
 -      {171000,        4,      19,     15},
 -      {172000,        4,      51,     40},
 -      {172750,        4,      32,     25},
 -      {172800,        4,      32,     25},
 -      {173000,        4,      41,     32},
 -      {174000,        4,      49,     38},
 -      {174787,        4,      22,     17},
 -      {175000,        4,      35,     27},
 -      {176000,        4,      30,     23},
 -      {177000,        4,      38,     29},
 -      {178000,        4,      29,     22},
 -      {178500,        4,      37,     28},
 -      {179000,        4,      53,     40},
 -      {179500,        4,      73,     55},
 -      {180000,        4,      20,     15},
 -      {181000,        4,      55,     41},
 -      {182000,        4,      31,     23},
 -      {183000,        4,      42,     31},
 -      {184000,        4,      30,     22},
 -      {184750,        4,      26,     19},
 -      {185000,        4,      37,     27},
 -      {186000,        4,      51,     37},
 -      {187000,        4,      36,     26},
 -      {188000,        4,      32,     23},
 -      {189000,        4,      21,     15},
 -      {190000,        4,      38,     27},
 -      {190960,        4,      41,     29},
 -      {191000,        4,      41,     29},
 -      {192000,        4,      27,     19},
 -      {192250,        4,      37,     26},
 -      {193000,        4,      20,     14},
 -      {193250,        4,      53,     37},
 -      {194000,        4,      23,     16},
 -      {194208,        4,      23,     16},
 -      {195000,        4,      26,     18},
 -      {196000,        4,      45,     31},
 -      {197000,        4,      35,     24},
 -      {197750,        4,      41,     28},
 -      {198000,        4,      22,     15},
 -      {198500,        4,      25,     17},
 -      {199000,        4,      28,     19},
 -      {200000,        4,      37,     25},
 -      {201000,        4,      61,     41},
 -      {202000,        4,      112,    75},
 -      {202500,        4,      21,     14},
 -      {203000,        4,      146,    97},
 -      {204000,        4,      62,     41},
 -      {204750,        4,      44,     29},
 -      {205000,        4,      38,     25},
 -      {206000,        4,      29,     19},
 -      {207000,        4,      23,     15},
 -      {207500,        4,      40,     26},
 -      {208000,        4,      37,     24},
 -      {208900,        4,      48,     31},
 -      {209000,        4,      48,     31},
 -      {209250,        4,      31,     20},
 -      {210000,        4,      28,     18},
 -      {211000,        4,      25,     16},
 -      {212000,        4,      22,     14},
 -      {213000,        4,      30,     19},
 -      {213750,        4,      38,     24},
 -      {214000,        4,      46,     29},
 -      {214750,        4,      35,     22},
 -      {215000,        4,      43,     27},
 -      {216000,        4,      24,     15},
 -      {217000,        4,      37,     23},
 -      {218000,        4,      42,     26},
 -      {218250,        4,      42,     26},
 -      {218750,        4,      34,     21},
 -      {219000,        4,      47,     29},
 -      {220000,        4,      44,     27},
 -      {220640,        4,      49,     30},
 -      {220750,        4,      36,     22},
 -      {221000,        4,      36,     22},
 -      {222000,        4,      23,     14},
 -      {222525,        4,      28,     17},
 -      {222750,        4,      33,     20},
 -      {227000,        4,      37,     22},
 -      {230250,        4,      29,     17},
 -      {233500,        4,      38,     22},
 -      {235000,        4,      40,     23},
 -      {238000,        4,      30,     17},
 -      {241500,        2,      17,     19},
 -      {245250,        2,      20,     22},
 -      {247750,        2,      22,     24},
 -      {253250,        2,      15,     16},
 -      {256250,        2,      18,     19},
 -      {262500,        2,      31,     32},
 -      {267250,        2,      66,     67},
 -      {268500,        2,      94,     95},
 -      {270000,        2,      14,     14},
 -      {272500,        2,      77,     76},
 -      {273750,        2,      57,     56},
 -      {280750,        2,      24,     23},
 -      {281250,        2,      23,     22},
 -      {286000,        2,      17,     16},
 -      {291750,        2,      26,     24},
 -      {296703,        2,      56,     51},
 -      {297000,        2,      22,     20},
 -      {298000,        2,      21,     19},
 -};
 -
  static void intel_ddi_mode_set(struct drm_encoder *encoder,
                               struct drm_display_mode *mode,
                               struct drm_display_mode *adjusted_mode)
        int pipe = intel_crtc->pipe;
        int type = intel_encoder->type;
  
 -      DRM_DEBUG_KMS("Preparing DDI mode for Haswell on port %c, pipe %c\n",
 +      DRM_DEBUG_KMS("Preparing DDI mode on port %c, pipe %c\n",
                      port_name(port), pipe_name(pipe));
  
        intel_crtc->eld_vld = false;
  
                intel_dp->DP = intel_dig_port->port_reversal |
                               DDI_BUF_CTL_ENABLE | DDI_BUF_EMP_400MV_0DB_HSW;
 -              switch (intel_dp->lane_count) {
 -              case 1:
 -                      intel_dp->DP |= DDI_PORT_WIDTH_X1;
 -                      break;
 -              case 2:
 -                      intel_dp->DP |= DDI_PORT_WIDTH_X2;
 -                      break;
 -              case 4:
 -                      intel_dp->DP |= DDI_PORT_WIDTH_X4;
 -                      break;
 -              default:
 -                      intel_dp->DP |= DDI_PORT_WIDTH_X4;
 -                      WARN(1, "Unexpected DP lane count %d\n",
 -                           intel_dp->lane_count);
 -                      break;
 -              }
 +              intel_dp->DP |= DDI_PORT_WIDTH(intel_dp->lane_count);
  
                if (intel_dp->has_audio) {
                        DRM_DEBUG_DRIVER("DP audio on pipe %c on DDI\n",
@@@ -350,8 -748,8 +350,8 @@@ intel_ddi_get_crtc_encoder(struct drm_c
        }
  
        if (num_encoders != 1)
 -              WARN(1, "%d encoders on crtc for pipe %d\n", num_encoders,
 -                   intel_crtc->pipe);
 +              WARN(1, "%d encoders on crtc for pipe %c\n", num_encoders,
 +                   pipe_name(intel_crtc->pipe));
  
        BUG_ON(ret == NULL);
        return ret;
@@@ -404,224 -802,27 +404,224 @@@ void intel_ddi_put_crtc_pll(struct drm_
        intel_crtc->ddi_pll_sel = PORT_CLK_SEL_NONE;
  }
  
 -static void intel_ddi_calculate_wrpll(int clock, int *p, int *n2, int *r2)
 +#define LC_FREQ 2700
 +#define LC_FREQ_2K (LC_FREQ * 2000)
 +
 +#define P_MIN 2
 +#define P_MAX 64
 +#define P_INC 2
 +
 +/* Constraints for PLL good behavior */
 +#define REF_MIN 48
 +#define REF_MAX 400
 +#define VCO_MIN 2400
 +#define VCO_MAX 4800
 +
 +#define ABS_DIFF(a, b) ((a > b) ? (a - b) : (b - a))
 +
 +struct wrpll_rnp {
 +      unsigned p, n2, r2;
 +};
 +
 +static unsigned wrpll_get_budget_for_freq(int clock)
 +{
 +      unsigned budget;
 +
 +      switch (clock) {
 +      case 25175000:
 +      case 25200000:
 +      case 27000000:
 +      case 27027000:
 +      case 37762500:
 +      case 37800000:
 +      case 40500000:
 +      case 40541000:
 +      case 54000000:
 +      case 54054000:
 +      case 59341000:
 +      case 59400000:
 +      case 72000000:
 +      case 74176000:
 +      case 74250000:
 +      case 81000000:
 +      case 81081000:
 +      case 89012000:
 +      case 89100000:
 +      case 108000000:
 +      case 108108000:
 +      case 111264000:
 +      case 111375000:
 +      case 148352000:
 +      case 148500000:
 +      case 162000000:
 +      case 162162000:
 +      case 222525000:
 +      case 222750000:
 +      case 296703000:
 +      case 297000000:
 +              budget = 0;
 +              break;
 +      case 233500000:
 +      case 245250000:
 +      case 247750000:
 +      case 253250000:
 +      case 298000000:
 +              budget = 1500;
 +              break;
 +      case 169128000:
 +      case 169500000:
 +      case 179500000:
 +      case 202000000:
 +              budget = 2000;
 +              break;
 +      case 256250000:
 +      case 262500000:
 +      case 270000000:
 +      case 272500000:
 +      case 273750000:
 +      case 280750000:
 +      case 281250000:
 +      case 286000000:
 +      case 291750000:
 +              budget = 4000;
 +              break;
 +      case 267250000:
 +      case 268500000:
 +              budget = 5000;
 +              break;
 +      default:
 +              budget = 1000;
 +              break;
 +      }
 +
 +      return budget;
 +}
 +
 +static void wrpll_update_rnp(uint64_t freq2k, unsigned budget,
 +                           unsigned r2, unsigned n2, unsigned p,
 +                           struct wrpll_rnp *best)
  {
 -      u32 i;
 +      uint64_t a, b, c, d, diff, diff_best;
  
 -      for (i = 0; i < ARRAY_SIZE(wrpll_tmds_clock_table); i++)
 -              if (clock <= wrpll_tmds_clock_table[i].clock)
 -                      break;
 +      /* No best (r,n,p) yet */
 +      if (best->p == 0) {
 +              best->p = p;
 +              best->n2 = n2;
 +              best->r2 = r2;
 +              return;
 +      }
 +
 +      /*
 +       * Output clock is (LC_FREQ_2K / 2000) * N / (P * R), which compares to
 +       * freq2k.
 +       *
 +       * delta = 1e6 *
 +       *         abs(freq2k - (LC_FREQ_2K * n2/(p * r2))) /
 +       *         freq2k;
 +       *
 +       * and we would like delta <= budget.
 +       *
 +       * If the discrepancy is above the PPM-based budget, always prefer to
 +       * improve upon the previous solution.  However, if you're within the
 +       * budget, try to maximize Ref * VCO, that is N / (P * R^2).
 +       */
 +      a = freq2k * budget * p * r2;
 +      b = freq2k * budget * best->p * best->r2;
 +      diff = ABS_DIFF((freq2k * p * r2), (LC_FREQ_2K * n2));
 +      diff_best = ABS_DIFF((freq2k * best->p * best->r2),
 +                           (LC_FREQ_2K * best->n2));
 +      c = 1000000 * diff;
 +      d = 1000000 * diff_best;
 +
 +      if (a < c && b < d) {
 +              /* If both are above the budget, pick the closer */
 +              if (best->p * best->r2 * diff < p * r2 * diff_best) {
 +                      best->p = p;
 +                      best->n2 = n2;
 +                      best->r2 = r2;
 +              }
 +      } else if (a >= c && b < d) {
 +              /* If A is below the threshold but B is above it?  Update. */
 +              best->p = p;
 +              best->n2 = n2;
 +              best->r2 = r2;
 +      } else if (a >= c && b >= d) {
 +              /* Both are below the limit, so pick the higher n2/(r2*r2) */
 +              if (n2 * best->r2 * best->r2 > best->n2 * r2 * r2) {
 +                      best->p = p;
 +                      best->n2 = n2;
 +                      best->r2 = r2;
 +              }
 +      }
 +      /* Otherwise a < c && b >= d, do nothing */
 +}
 +
 +static void
 +intel_ddi_calculate_wrpll(int clock /* in Hz */,
 +                        unsigned *r2_out, unsigned *n2_out, unsigned *p_out)
 +{
 +      uint64_t freq2k;
 +      unsigned p, n2, r2;
 +      struct wrpll_rnp best = { 0, 0, 0 };
 +      unsigned budget;
 +
 +      freq2k = clock / 100;
 +
 +      budget = wrpll_get_budget_for_freq(clock);
 +
 +      /* Special case handling for 540 pixel clock: bypass WR PLL entirely
 +       * and directly pass the LC PLL to it. */
 +      if (freq2k == 5400000) {
 +              *n2_out = 2;
 +              *p_out = 1;
 +              *r2_out = 2;
 +              return;
 +      }
  
 -      if (i == ARRAY_SIZE(wrpll_tmds_clock_table))
 -              i--;
 +      /*
 +       * Ref = LC_FREQ / R, where Ref is the actual reference input seen by
 +       * the WR PLL.
 +       *
 +       * We want R so that REF_MIN <= Ref <= REF_MAX.
 +       * Injecting R2 = 2 * R gives:
 +       *   REF_MAX * r2 > LC_FREQ * 2 and
 +       *   REF_MIN * r2 < LC_FREQ * 2
 +       *
 +       * Which means the desired boundaries for r2 are:
 +       *  LC_FREQ * 2 / REF_MAX < r2 < LC_FREQ * 2 / REF_MIN
 +       *
 +       */
 +      for (r2 = LC_FREQ * 2 / REF_MAX + 1;
 +           r2 <= LC_FREQ * 2 / REF_MIN;
 +           r2++) {
 +
 +              /*
 +               * VCO = N * Ref, that is: VCO = N * LC_FREQ / R
 +               *
 +               * Once again we want VCO_MIN <= VCO <= VCO_MAX.
 +               * Injecting R2 = 2 * R and N2 = 2 * N, we get:
 +               *   VCO_MAX * r2 > n2 * LC_FREQ and
 +               *   VCO_MIN * r2 < n2 * LC_FREQ)
 +               *
 +               * Which means the desired boundaries for n2 are:
 +               * VCO_MIN * r2 / LC_FREQ < n2 < VCO_MAX * r2 / LC_FREQ
 +               */
 +              for (n2 = VCO_MIN * r2 / LC_FREQ + 1;
 +                   n2 <= VCO_MAX * r2 / LC_FREQ;
 +                   n2++) {
  
 -      *p = wrpll_tmds_clock_table[i].p;
 -      *n2 = wrpll_tmds_clock_table[i].n2;
 -      *r2 = wrpll_tmds_clock_table[i].r2;
 +                      for (p = P_MIN; p <= P_MAX; p += P_INC)
 +                              wrpll_update_rnp(freq2k, budget,
 +                                               r2, n2, p, &best);
 +              }
 +      }
  
 -      if (wrpll_tmds_clock_table[i].clock != clock)
 -              DRM_INFO("WRPLL: using settings for %dKHz on %dKHz mode\n",
 -                       wrpll_tmds_clock_table[i].clock, clock);
 +      *n2_out = best.n2;
 +      *p_out = best.p;
 +      *r2_out = best.r2;
  
 -      DRM_DEBUG_KMS("WRPLL: %dKHz refresh rate with p=%d, n2=%d r2=%d\n",
 -                    clock, *p, *n2, *r2);
 +      DRM_DEBUG_KMS("WRPLL: %dHz refresh rate with p=%d, n2=%d r2=%d\n",
 +                    clock, *p_out, *n2_out, *r2_out);
  }
  
  bool intel_ddi_pll_mode_set(struct drm_crtc *crtc, int clock)
                return true;
  
        } else if (type == INTEL_OUTPUT_HDMI) {
 -              int p, n2, r2;
 +              unsigned p, n2, r2;
  
                if (plls->wrpll1_refcount == 0) {
                        DRM_DEBUG_KMS("Using WRPLL 1 on pipe %c\n",
                WARN(I915_READ(reg) & WRPLL_PLL_ENABLE,
                     "WRPLL already enabled\n");
  
 -              intel_ddi_calculate_wrpll(clock, &p, &n2, &r2);
 +              intel_ddi_calculate_wrpll(clock * 1000, &r2, &n2, &p);
  
                val = WRPLL_PLL_ENABLE | WRPLL_PLL_SELECT_LCPLL_2700 |
                      WRPLL_DIVIDER_REFERENCE(r2) | WRPLL_DIVIDER_FEEDBACK(n2) |
@@@ -794,7 -995,7 +794,7 @@@ void intel_ddi_enable_transcoder_func(s
                        /* Can only use the always-on power well for eDP when
                         * not using the panel fitter, and when not using motion
                          * blur mitigation (which we don't support). */
 -                      if (dev_priv->pch_pf_size)
 +                      if (intel_crtc->config.pch_pfit.size)
                                temp |= TRANS_DDI_EDP_INPUT_A_ONOFF;
                        else
                                temp |= TRANS_DDI_EDP_INPUT_A_ON;
  
        } else if (type == INTEL_OUTPUT_ANALOG) {
                temp |= TRANS_DDI_MODE_SELECT_FDI;
 -              temp |= (intel_crtc->fdi_lanes - 1) << 1;
 +              temp |= (intel_crtc->config.fdi_lanes - 1) << 1;
  
        } else if (type == INTEL_OUTPUT_DISPLAYPORT ||
                   type == INTEL_OUTPUT_EDP) {
  
                temp |= TRANS_DDI_MODE_SELECT_DP_SST;
  
 -              switch (intel_dp->lane_count) {
 -              case 1:
 -                      temp |= TRANS_DDI_PORT_WIDTH_X1;
 -                      break;
 -              case 2:
 -                      temp |= TRANS_DDI_PORT_WIDTH_X2;
 -                      break;
 -              case 4:
 -                      temp |= TRANS_DDI_PORT_WIDTH_X4;
 -                      break;
 -              default:
 -                      temp |= TRANS_DDI_PORT_WIDTH_X4;
 -                      WARN(1, "Unsupported lane count %d\n",
 -                           intel_dp->lane_count);
 -              }
 -
 +              temp |= DDI_PORT_WIDTH(intel_dp->lane_count);
        } else {
 -              WARN(1, "Invalid encoder type %d for pipe %d\n",
 -                   intel_encoder->type, pipe);
 +              WARN(1, "Invalid encoder type %d for pipe %c\n",
 +                   intel_encoder->type, pipe_name(pipe));
        }
  
        I915_WRITE(TRANS_DDI_FUNC_CTL(cpu_transcoder), temp);
@@@ -932,7 -1148,7 +932,7 @@@ bool intel_ddi_get_hw_state(struct inte
                }
        }
  
 -      DRM_DEBUG_KMS("No pipe for ddi port %i found\n", port);
 +      DRM_DEBUG_KMS("No pipe for ddi port %c found\n", port_name(port));
  
        return false;
  }
@@@ -1049,6 -1265,8 +1049,8 @@@ static void intel_ddi_pre_enable(struc
                intel_dp_sink_dpms(intel_dp, DRM_MODE_DPMS_ON);
                intel_dp_start_link_train(intel_dp);
                intel_dp_complete_link_train(intel_dp);
+               if (port != PORT_A)
+                       intel_dp_stop_link_train(intel_dp);
        }
  }
  
@@@ -1110,10 -1328,13 +1112,13 @@@ static void intel_enable_ddi(struct int
        } else if (type == INTEL_OUTPUT_EDP) {
                struct intel_dp *intel_dp = enc_to_intel_dp(encoder);
  
+               if (port == PORT_A)
+                       intel_dp_stop_link_train(intel_dp);
                ironlake_edp_backlight_on(intel_dp);
        }
  
 -      if (intel_crtc->eld_vld) {
 +      if (intel_crtc->eld_vld && type != INTEL_OUTPUT_EDP) {
                tmp = I915_READ(HSW_AUD_PIN_ELD_CP_VLD);
                tmp |= ((AUDIO_OUTPUT_ENABLE_A | AUDIO_ELD_VALID_A) << (pipe * 4));
                I915_WRITE(HSW_AUD_PIN_ELD_CP_VLD, tmp);
@@@ -1131,12 -1352,9 +1136,12 @@@ static void intel_disable_ddi(struct in
        struct drm_i915_private *dev_priv = dev->dev_private;
        uint32_t tmp;
  
 -      tmp = I915_READ(HSW_AUD_PIN_ELD_CP_VLD);
 -      tmp &= ~((AUDIO_OUTPUT_ENABLE_A | AUDIO_ELD_VALID_A) << (pipe * 4));
 -      I915_WRITE(HSW_AUD_PIN_ELD_CP_VLD, tmp);
 +      if (intel_crtc->eld_vld && type != INTEL_OUTPUT_EDP) {
 +              tmp = I915_READ(HSW_AUD_PIN_ELD_CP_VLD);
 +              tmp &= ~((AUDIO_OUTPUT_ENABLE_A | AUDIO_ELD_VALID_A) <<
 +                       (pipe * 4));
 +              I915_WRITE(HSW_AUD_PIN_ELD_CP_VLD, tmp);
 +      }
  
        if (type == INTEL_OUTPUT_EDP) {
                struct intel_dp *intel_dp = enc_to_intel_dp(encoder);
@@@ -1300,6 -1518,16 +1305,6 @@@ void intel_ddi_init(struct drm_device *
                return;
        }
  
 -      if (port != PORT_A) {
 -              hdmi_connector = kzalloc(sizeof(struct intel_connector),
 -                                       GFP_KERNEL);
 -              if (!hdmi_connector) {
 -                      kfree(dp_connector);
 -                      kfree(intel_dig_port);
 -                      return;
 -              }
 -      }
 -
        intel_encoder = &intel_dig_port->base;
        encoder = &intel_encoder->base;
  
        intel_dig_port->port = port;
        intel_dig_port->port_reversal = I915_READ(DDI_BUF_CTL(port)) &
                                        DDI_BUF_PORT_REVERSAL;
 -      if (hdmi_connector)
 -              intel_dig_port->hdmi.hdmi_reg = DDI_BUF_CTL(port);
        intel_dig_port->dp.output_reg = DDI_BUF_CTL(port);
  
        intel_encoder->type = INTEL_OUTPUT_UNKNOWN;
        intel_encoder->cloneable = false;
        intel_encoder->hot_plug = intel_ddi_hot_plug;
  
 -      if (hdmi_connector)
 -              intel_hdmi_init_connector(intel_dig_port, hdmi_connector);
        intel_dp_init_connector(intel_dig_port, dp_connector);
 +
 +      if (intel_encoder->type != INTEL_OUTPUT_EDP) {
 +              hdmi_connector = kzalloc(sizeof(struct intel_connector),
 +                                       GFP_KERNEL);
 +              if (!hdmi_connector) {
 +                      return;
 +              }
 +
 +              intel_dig_port->hdmi.hdmi_reg = DDI_BUF_CTL(port);
 +              intel_hdmi_init_connector(intel_dig_port, hdmi_connector);
 +      }
  }
index 7358e4e9761e372a52ff44a094257594cfedf909,efe8299197555c1ae5def2bc95bf930a4e041a8b..2d90594016d9b7444a71035bb7520ba290c96cb6
@@@ -45,6 -45,18 +45,6 @@@ bool intel_pipe_has_type(struct drm_crt
  static void intel_increase_pllclock(struct drm_crtc *crtc);
  static void intel_crtc_update_cursor(struct drm_crtc *crtc, bool on);
  
 -typedef struct {
 -      /* given values */
 -      int n;
 -      int m1, m2;
 -      int p1, p2;
 -      /* derived values */
 -      int     dot;
 -      int     vco;
 -      int     m;
 -      int     p;
 -} intel_clock_t;
 -
  typedef struct {
        int     min, max;
  } intel_range_t;
@@@ -101,6 -113,15 +101,6 @@@ intel_g4x_find_best_PLL(const intel_lim
                        int target, int refclk, intel_clock_t *match_clock,
                        intel_clock_t *best_clock);
  
 -static bool
 -intel_find_pll_g4x_dp(const intel_limit_t *, struct drm_crtc *crtc,
 -                    int target, int refclk, intel_clock_t *match_clock,
 -                    intel_clock_t *best_clock);
 -static bool
 -intel_find_pll_ironlake_dp(const intel_limit_t *, struct drm_crtc *crtc,
 -                         int target, int refclk, intel_clock_t *match_clock,
 -                         intel_clock_t *best_clock);
 -
  static bool
  intel_vlv_find_best_pll(const intel_limit_t *limit, struct drm_crtc *crtc,
                        int target, int refclk, intel_clock_t *match_clock,
@@@ -233,6 -254,20 +233,6 @@@ static const intel_limit_t intel_limits
        .find_pll = intel_g4x_find_best_PLL,
  };
  
 -static const intel_limit_t intel_limits_g4x_display_port = {
 -      .dot = { .min = 161670, .max = 227000 },
 -      .vco = { .min = 1750000, .max = 3500000},
 -      .n = { .min = 1, .max = 2 },
 -      .m = { .min = 97, .max = 108 },
 -      .m1 = { .min = 0x10, .max = 0x12 },
 -      .m2 = { .min = 0x05, .max = 0x06 },
 -      .p = { .min = 10, .max = 20 },
 -      .p1 = { .min = 1, .max = 2},
 -      .p2 = { .dot_limit = 0,
 -              .p2_slow = 10, .p2_fast = 10 },
 -      .find_pll = intel_find_pll_g4x_dp,
 -};
 -
  static const intel_limit_t intel_limits_pineview_sdvo = {
        .dot = { .min = 20000, .max = 400000},
        .vco = { .min = 1700000, .max = 3500000 },
@@@ -339,6 -374,20 +339,6 @@@ static const intel_limit_t intel_limits
        .find_pll = intel_g4x_find_best_PLL,
  };
  
 -static const intel_limit_t intel_limits_ironlake_display_port = {
 -      .dot = { .min = 25000, .max = 350000 },
 -      .vco = { .min = 1760000, .max = 3510000},
 -      .n = { .min = 1, .max = 2 },
 -      .m = { .min = 81, .max = 90 },
 -      .m1 = { .min = 12, .max = 22 },
 -      .m2 = { .min = 5, .max = 9 },
 -      .p = { .min = 10, .max = 20 },
 -      .p1 = { .min = 1, .max = 2},
 -      .p2 = { .dot_limit = 0,
 -              .p2_slow = 10, .p2_fast = 10 },
 -      .find_pll = intel_find_pll_ironlake_dp,
 -};
 -
  static const intel_limit_t intel_limits_vlv_dac = {
        .dot = { .min = 25000, .max = 270000 },
        .vco = { .min = 4000000, .max = 6000000 },
        .m1 = { .min = 2, .max = 3 },
        .m2 = { .min = 11, .max = 156 },
        .p = { .min = 10, .max = 30 },
 -      .p1 = { .min = 2, .max = 3 },
 +      .p1 = { .min = 1, .max = 3 },
        .p2 = { .dot_limit = 270000,
                .p2_slow = 2, .p2_fast = 20 },
        .find_pll = intel_vlv_find_best_pll,
  };
  
  static const intel_limit_t intel_limits_vlv_hdmi = {
 -      .dot = { .min = 20000, .max = 165000 },
 -      .vco = { .min = 4000000, .max = 5994000},
 +      .dot = { .min = 25000, .max = 270000 },
 +      .vco = { .min = 4000000, .max = 6000000 },
        .n = { .min = 1, .max = 7 },
        .m = { .min = 60, .max = 300 }, /* guess */
        .m1 = { .min = 2, .max = 3 },
@@@ -375,7 -424,7 +375,7 @@@ static const intel_limit_t intel_limits
        .m1 = { .min = 2, .max = 3 },
        .m2 = { .min = 11, .max = 156 },
        .p = { .min = 10, .max = 30 },
 -      .p1 = { .min = 2, .max = 3 },
 +      .p1 = { .min = 1, .max = 3 },
        .p2 = { .dot_limit = 270000,
                .p2_slow = 2, .p2_fast = 20 },
        .find_pll = intel_vlv_find_best_pll,
@@@ -401,7 -450,8 +401,7 @@@ u32 intel_dpio_read(struct drm_i915_pri
        return I915_READ(DPIO_DATA);
  }
  
 -static void intel_dpio_write(struct drm_i915_private *dev_priv, int reg,
 -                           u32 val)
 +void intel_dpio_write(struct drm_i915_private *dev_priv, int reg, u32 val)
  {
        WARN_ON(!mutex_is_locked(&dev_priv->dpio_lock));
  
                DRM_ERROR("DPIO write wait timed out\n");
  }
  
 -static void vlv_init_dpio(struct drm_device *dev)
 -{
 -      struct drm_i915_private *dev_priv = dev->dev_private;
 -
 -      /* Reset the DPIO config */
 -      I915_WRITE(DPIO_CTL, 0);
 -      POSTING_READ(DPIO_CTL);
 -      I915_WRITE(DPIO_CTL, 1);
 -      POSTING_READ(DPIO_CTL);
 -}
 -
  static const intel_limit_t *intel_ironlake_limit(struct drm_crtc *crtc,
                                                int refclk)
  {
                        else
                                limit = &intel_limits_ironlake_single_lvds;
                }
 -      } else if (intel_pipe_has_type(crtc, INTEL_OUTPUT_DISPLAYPORT) ||
 -                 intel_pipe_has_type(crtc, INTEL_OUTPUT_EDP))
 -              limit = &intel_limits_ironlake_display_port;
 -      else
 +      } else
                limit = &intel_limits_ironlake_dac;
  
        return limit;
@@@ -457,6 -521,8 +457,6 @@@ static const intel_limit_t *intel_g4x_l
                limit = &intel_limits_g4x_hdmi;
        } else if (intel_pipe_has_type(crtc, INTEL_OUTPUT_SDVO)) {
                limit = &intel_limits_g4x_sdvo;
 -      } else if (intel_pipe_has_type(crtc, INTEL_OUTPUT_DISPLAYPORT)) {
 -              limit = &intel_limits_g4x_display_port;
        } else /* The option is for other outputs */
                limit = &intel_limits_i9xx_sdvo;
  
@@@ -507,18 -573,13 +507,18 @@@ static void pineview_clock(int refclk, 
        clock->dot = clock->vco / clock->p;
  }
  
 +static uint32_t i9xx_dpll_compute_m(struct dpll *dpll)
 +{
 +      return 5 * (dpll->m1 + 2) + (dpll->m2 + 2);
 +}
 +
  static void intel_clock(struct drm_device *dev, int refclk, intel_clock_t *clock)
  {
        if (IS_PINEVIEW(dev)) {
                pineview_clock(refclk, clock);
                return;
        }
 -      clock->m = 5 * (clock->m1 + 2) + (clock->m2 + 2);
 +      clock->m = i9xx_dpll_compute_m(clock);
        clock->p = clock->p1 * clock->p2;
        clock->vco = refclk * clock->m / (clock->n + 2);
        clock->dot = clock->vco / clock->p;
@@@ -651,6 -712,12 +651,6 @@@ intel_g4x_find_best_PLL(const intel_lim
        found = false;
  
        if (intel_pipe_has_type(crtc, INTEL_OUTPUT_LVDS)) {
 -              int lvds_reg;
 -
 -              if (HAS_PCH_SPLIT(dev))
 -                      lvds_reg = PCH_LVDS;
 -              else
 -                      lvds_reg = LVDS;
                if (intel_is_dual_link_lvds(dev))
                        clock.p2 = limit->p2.p2_fast;
                else
                                        if (!intel_PLL_is_valid(dev, limit,
                                                                &clock))
                                                continue;
 -                                      if (match_clock &&
 -                                          clock.p != match_clock->p)
 -                                              continue;
  
                                        this_err = abs(clock.dot - target);
                                        if (this_err < err_most) {
        return found;
  }
  
 -static bool
 -intel_find_pll_ironlake_dp(const intel_limit_t *limit, struct drm_crtc *crtc,
 -                         int target, int refclk, intel_clock_t *match_clock,
 -                         intel_clock_t *best_clock)
 -{
 -      struct drm_device *dev = crtc->dev;
 -      intel_clock_t clock;
 -
 -      if (target < 200000) {
 -              clock.n = 1;
 -              clock.p1 = 2;
 -              clock.p2 = 10;
 -              clock.m1 = 12;
 -              clock.m2 = 9;
 -      } else {
 -              clock.n = 2;
 -              clock.p1 = 1;
 -              clock.p2 = 10;
 -              clock.m1 = 14;
 -              clock.m2 = 8;
 -      }
 -      intel_clock(dev, refclk, &clock);
 -      memcpy(best_clock, &clock, sizeof(intel_clock_t));
 -      return true;
 -}
 -
 -/* DisplayPort has only two frequencies, 162MHz and 270MHz */
 -static bool
 -intel_find_pll_g4x_dp(const intel_limit_t *limit, struct drm_crtc *crtc,
 -                    int target, int refclk, intel_clock_t *match_clock,
 -                    intel_clock_t *best_clock)
 -{
 -      intel_clock_t clock;
 -      if (target < 200000) {
 -              clock.p1 = 2;
 -              clock.p2 = 10;
 -              clock.n = 2;
 -              clock.m1 = 23;
 -              clock.m2 = 8;
 -      } else {
 -              clock.p1 = 1;
 -              clock.p2 = 10;
 -              clock.n = 1;
 -              clock.m1 = 14;
 -              clock.m2 = 2;
 -      }
 -      clock.m = 5 * (clock.m1 + 2) + (clock.m2 + 2);
 -      clock.p = (clock.p1 * clock.p2);
 -      clock.dot = 96000 * clock.m / (clock.n + 2) / clock.p;
 -      clock.vco = 0;
 -      memcpy(best_clock, &clock, sizeof(intel_clock_t));
 -      return true;
 -}
  static bool
  intel_vlv_find_best_pll(const intel_limit_t *limit, struct drm_crtc *crtc,
                        int target, int refclk, intel_clock_t *match_clock,
@@@ -974,14 -1097,14 +974,14 @@@ static void assert_pch_pll(struct drm_i
                pch_dpll = I915_READ(PCH_DPLL_SEL);
                cur_state = pll->pll_reg == _PCH_DPLL_B;
                if (!WARN(((pch_dpll >> (4 * crtc->pipe)) & 1) != cur_state,
 -                        "PLL[%d] not attached to this transcoder %d: %08x\n",
 -                        cur_state, crtc->pipe, pch_dpll)) {
 +                        "PLL[%d] not attached to this transcoder %c: %08x\n",
 +                        cur_state, pipe_name(crtc->pipe), pch_dpll)) {
                        cur_state = !!(val >> (4*crtc->pipe + 3));
                        WARN(cur_state != state,
 -                           "PLL[%d] not %s on this transcoder %d: %08x\n",
 +                           "PLL[%d] not %s on this transcoder %c: %08x\n",
                             pll->pll_reg == _PCH_DPLL_B,
                             state_string(state),
 -                           crtc->pipe,
 +                           pipe_name(crtc->pipe),
                             val);
                }
        }
@@@ -1104,8 -1227,8 +1104,8 @@@ void assert_pipe(struct drm_i915_privat
        if (pipe == PIPE_A && dev_priv->quirks & QUIRK_PIPEA_FORCE)
                state = true;
  
 -      if (!intel_using_power_well(dev_priv->dev) &&
 -          cpu_transcoder != TRANSCODER_EDP) {
 +      if (!intel_display_power_enabled(dev_priv->dev,
 +                              POWER_DOMAIN_TRANSCODER(cpu_transcoder))) {
                cur_state = false;
        } else {
                reg = PIPECONF(cpu_transcoder);
@@@ -1179,8 -1302,8 +1179,8 @@@ static void assert_sprites_disabled(str
                reg = SPCNTR(pipe, i);
                val = I915_READ(reg);
                WARN((val & SP_ENABLE),
 -                   "sprite %d assertion failure, should be off on pipe %c but is still active\n",
 -                   pipe * 2 + i, pipe_name(pipe));
 +                   "sprite %c assertion failure, should be off on pipe %c but is still active\n",
 +                   sprite_name(pipe, i), pipe_name(pipe));
        }
  }
  
@@@ -1200,14 -1323,14 +1200,14 @@@ static void assert_pch_refclk_enabled(s
        WARN(!enabled, "PCH refclk assertion failure, should be active but is disabled\n");
  }
  
 -static void assert_transcoder_disabled(struct drm_i915_private *dev_priv,
 -                                     enum pipe pipe)
 +static void assert_pch_transcoder_disabled(struct drm_i915_private *dev_priv,
 +                                         enum pipe pipe)
  {
        int reg;
        u32 val;
        bool enabled;
  
 -      reg = TRANSCONF(pipe);
 +      reg = PCH_TRANSCONF(pipe);
        val = I915_READ(reg);
        enabled = !!(val & TRANS_ENABLE);
        WARN(enabled,
@@@ -1351,8 -1474,6 +1351,8 @@@ static void intel_enable_pll(struct drm
        int reg;
        u32 val;
  
 +      assert_pipe_disabled(dev_priv, pipe);
 +
        /* No really, not for ILK+ */
        BUG_ON(!IS_VALLEYVIEW(dev_priv->dev) && dev_priv->info->gen >= 5);
  
@@@ -1465,20 -1586,6 +1465,20 @@@ intel_sbi_read(struct drm_i915_private 
        return I915_READ(SBI_DATA);
  }
  
 +void vlv_wait_port_ready(struct drm_i915_private *dev_priv, int port)
 +{
 +      u32 port_mask;
 +
 +      if (!port)
 +              port_mask = DPLL_PORTB_READY_MASK;
 +      else
 +              port_mask = DPLL_PORTC_READY_MASK;
 +
 +      if (wait_for((I915_READ(DPLL(0)) & port_mask) == 0, 1000))
 +              WARN(1, "timed out waiting for port %c ready: 0x%08x\n",
 +                   'B' + port, I915_READ(DPLL(0)));
 +}
 +
  /**
   * ironlake_enable_pch_pll - enable PCH PLL
   * @dev_priv: i915 private structure
@@@ -1559,7 -1666,7 +1559,7 @@@ static void intel_disable_pch_pll(struc
        DRM_DEBUG_KMS("disabling PCH PLL %x\n", pll->pll_reg);
  
        /* Make sure transcoder isn't still depending on us */
 -      assert_transcoder_disabled(dev_priv, intel_crtc->pipe);
 +      assert_pch_transcoder_disabled(dev_priv, intel_crtc->pipe);
  
        reg = pll->pll_reg;
        val = I915_READ(reg);
@@@ -1599,7 -1706,7 +1599,7 @@@ static void ironlake_enable_pch_transco
                I915_WRITE(reg, val);
        }
  
 -      reg = TRANSCONF(pipe);
 +      reg = PCH_TRANSCONF(pipe);
        val = I915_READ(reg);
        pipeconf_val = I915_READ(PIPECONF(pipe));
  
  
        I915_WRITE(reg, val | TRANS_ENABLE);
        if (wait_for(I915_READ(reg) & TRANS_STATE_ENABLE, 100))
 -              DRM_ERROR("failed to enable transcoder %d\n", pipe);
 +              DRM_ERROR("failed to enable transcoder %c\n", pipe_name(pipe));
  }
  
  static void lpt_enable_pch_transcoder(struct drm_i915_private *dev_priv,
        else
                val |= TRANS_PROGRESSIVE;
  
 -      I915_WRITE(TRANSCONF(TRANSCODER_A), val);
 -      if (wait_for(I915_READ(_TRANSACONF) & TRANS_STATE_ENABLE, 100))
 +      I915_WRITE(LPT_TRANSCONF, val);
 +      if (wait_for(I915_READ(LPT_TRANSCONF) & TRANS_STATE_ENABLE, 100))
                DRM_ERROR("Failed to enable PCH transcoder\n");
  }
  
@@@ -1671,13 -1778,13 +1671,13 @@@ static void ironlake_disable_pch_transc
        /* Ports must be off as well */
        assert_pch_ports_disabled(dev_priv, pipe);
  
 -      reg = TRANSCONF(pipe);
 +      reg = PCH_TRANSCONF(pipe);
        val = I915_READ(reg);
        val &= ~TRANS_ENABLE;
        I915_WRITE(reg, val);
        /* wait for PCH transcoder off, transcoder state */
        if (wait_for((I915_READ(reg) & TRANS_STATE_ENABLE) == 0, 50))
 -              DRM_ERROR("failed to disable transcoder %d\n", pipe);
 +              DRM_ERROR("failed to disable transcoder %c\n", pipe_name(pipe));
  
        if (!HAS_PCH_IBX(dev)) {
                /* Workaround: Clear the timing override chicken bit again. */
@@@ -1692,11 -1799,11 +1692,11 @@@ static void lpt_disable_pch_transcoder(
  {
        u32 val;
  
 -      val = I915_READ(_TRANSACONF);
 +      val = I915_READ(LPT_TRANSCONF);
        val &= ~TRANS_ENABLE;
 -      I915_WRITE(_TRANSACONF, val);
 +      I915_WRITE(LPT_TRANSCONF, val);
        /* wait for PCH transcoder off, transcoder state */
 -      if (wait_for((I915_READ(_TRANSACONF) & TRANS_STATE_ENABLE) == 0, 50))
 +      if (wait_for((I915_READ(LPT_TRANSCONF) & TRANS_STATE_ENABLE) == 0, 50))
                DRM_ERROR("Failed to disable PCH transcoder\n");
  
        /* Workaround: clear timing override bit. */
@@@ -1728,9 -1835,6 +1728,9 @@@ static void intel_enable_pipe(struct dr
        int reg;
        u32 val;
  
 +      assert_planes_disabled(dev_priv, pipe);
 +      assert_sprites_disabled(dev_priv, pipe);
 +
        if (HAS_PCH_LPT(dev_priv->dev))
                pch_transcoder = TRANSCODER_A;
        else
@@@ -1992,7 -2096,7 +1992,7 @@@ static int i9xx_update_plane(struct drm
        case 1:
                break;
        default:
 -              DRM_ERROR("Can't update plane %d in SAREA\n", plane);
 +              DRM_ERROR("Can't update plane %c in SAREA\n", plane_name(plane));
                return -EINVAL;
        }
  
@@@ -2089,7 -2193,7 +2089,7 @@@ static int ironlake_update_plane(struc
        case 2:
                break;
        default:
 -              DRM_ERROR("Can't update plane %d in SAREA\n", plane);
 +              DRM_ERROR("Can't update plane %c in SAREA\n", plane_name(plane));
                return -EINVAL;
        }
  
@@@ -2280,9 -2384,9 +2280,9 @@@ intel_pipe_set_base(struct drm_crtc *cr
        }
  
        if (intel_crtc->plane > INTEL_INFO(dev)->num_pipes) {
 -              DRM_ERROR("no plane for crtc: plane %d, num_pipes %d\n",
 -                              intel_crtc->plane,
 -                              INTEL_INFO(dev)->num_pipes);
 +              DRM_ERROR("no plane for crtc: plane %c, num_pipes %d\n",
 +                        plane_name(intel_crtc->plane),
 +                        INTEL_INFO(dev)->num_pipes);
                return -EINVAL;
        }
  
@@@ -2363,11 -2467,6 +2363,11 @@@ static void intel_fdi_normal_train(stru
                           FDI_FE_ERRC_ENABLE);
  }
  
 +static bool pipe_has_enabled_pch(struct intel_crtc *intel_crtc)
 +{
 +      return intel_crtc->base.enabled && intel_crtc->config.has_pch_encoder;
 +}
 +
  static void ivb_modeset_global_resources(struct drm_device *dev)
  {
        struct drm_i915_private *dev_priv = dev->dev_private;
                to_intel_crtc(dev_priv->pipe_to_crtc_mapping[PIPE_C]);
        uint32_t temp;
  
 -      /* When everything is off disable fdi C so that we could enable fdi B
 -       * with all lanes. XXX: This misses the case where a pipe is not using
 -       * any pch resources and so doesn't need any fdi lanes. */
 -      if (!pipe_B_crtc->base.enabled && !pipe_C_crtc->base.enabled) {
 +      /*
 +       * When everything is off disable fdi C so that we could enable fdi B
 +       * with all lanes. Note that we don't care about enabled pipes without
 +       * an enabled pch encoder.
 +       */
 +      if (!pipe_has_enabled_pch(pipe_B_crtc) &&
 +          !pipe_has_enabled_pch(pipe_C_crtc)) {
                WARN_ON(I915_READ(FDI_RX_CTL(PIPE_B)) & FDI_RX_ENABLE);
                WARN_ON(I915_READ(FDI_RX_CTL(PIPE_C)) & FDI_RX_ENABLE);
  
@@@ -2421,8 -2517,8 +2421,8 @@@ static void ironlake_fdi_link_train(str
        /* enable CPU FDI TX and PCH FDI RX */
        reg = FDI_TX_CTL(pipe);
        temp = I915_READ(reg);
 -      temp &= ~(7 << 19);
 -      temp |= (intel_crtc->fdi_lanes - 1) << 19;
 +      temp &= ~FDI_DP_PORT_WIDTH_MASK;
 +      temp |= FDI_DP_PORT_WIDTH(intel_crtc->config.fdi_lanes);
        temp &= ~FDI_LINK_TRAIN_NONE;
        temp |= FDI_LINK_TRAIN_PATTERN_1;
        I915_WRITE(reg, temp | FDI_TX_ENABLE);
@@@ -2519,8 -2615,8 +2519,8 @@@ static void gen6_fdi_link_train(struct 
        /* enable CPU FDI TX and PCH FDI RX */
        reg = FDI_TX_CTL(pipe);
        temp = I915_READ(reg);
 -      temp &= ~(7 << 19);
 -      temp |= (intel_crtc->fdi_lanes - 1) << 19;
 +      temp &= ~FDI_DP_PORT_WIDTH_MASK;
 +      temp |= FDI_DP_PORT_WIDTH(intel_crtc->config.fdi_lanes);
        temp &= ~FDI_LINK_TRAIN_NONE;
        temp |= FDI_LINK_TRAIN_PATTERN_1;
        temp &= ~FDI_LINK_TRAIN_VOL_EMP_MASK;
@@@ -2654,8 -2750,8 +2654,8 @@@ static void ivb_manual_fdi_link_train(s
        /* enable CPU FDI TX and PCH FDI RX */
        reg = FDI_TX_CTL(pipe);
        temp = I915_READ(reg);
 -      temp &= ~(7 << 19);
 -      temp |= (intel_crtc->fdi_lanes - 1) << 19;
 +      temp &= ~FDI_DP_PORT_WIDTH_MASK;
 +      temp |= FDI_DP_PORT_WIDTH(intel_crtc->config.fdi_lanes);
        temp &= ~(FDI_LINK_TRAIN_AUTO | FDI_LINK_TRAIN_NONE_IVB);
        temp |= FDI_LINK_TRAIN_PATTERN_1_IVB;
        temp &= ~FDI_LINK_TRAIN_VOL_EMP_MASK;
@@@ -2756,8 -2852,8 +2756,8 @@@ static void ironlake_fdi_pll_enable(str
        /* enable PCH FDI RX PLL, wait warmup plus DMI latency */
        reg = FDI_RX_CTL(pipe);
        temp = I915_READ(reg);
 -      temp &= ~((0x7 << 19) | (0x7 << 16));
 -      temp |= (intel_crtc->fdi_lanes - 1) << 19;
 +      temp &= ~(FDI_DP_PORT_WIDTH_MASK | (0x7 << 16));
 +      temp |= FDI_DP_PORT_WIDTH(intel_crtc->config.fdi_lanes);
        temp |= (I915_READ(PIPECONF(pipe)) & PIPECONF_BPC_MASK) << 11;
        I915_WRITE(reg, temp | FDI_RX_PLL_ENABLE);
  
@@@ -2989,30 -3085,6 +2989,30 @@@ static void lpt_program_iclkip(struct d
        mutex_unlock(&dev_priv->dpio_lock);
  }
  
 +static void ironlake_pch_transcoder_set_timings(struct intel_crtc *crtc,
 +                                              enum pipe pch_transcoder)
 +{
 +      struct drm_device *dev = crtc->base.dev;
 +      struct drm_i915_private *dev_priv = dev->dev_private;
 +      enum transcoder cpu_transcoder = crtc->config.cpu_transcoder;
 +
 +      I915_WRITE(PCH_TRANS_HTOTAL(pch_transcoder),
 +                 I915_READ(HTOTAL(cpu_transcoder)));
 +      I915_WRITE(PCH_TRANS_HBLANK(pch_transcoder),
 +                 I915_READ(HBLANK(cpu_transcoder)));
 +      I915_WRITE(PCH_TRANS_HSYNC(pch_transcoder),
 +                 I915_READ(HSYNC(cpu_transcoder)));
 +
 +      I915_WRITE(PCH_TRANS_VTOTAL(pch_transcoder),
 +                 I915_READ(VTOTAL(cpu_transcoder)));
 +      I915_WRITE(PCH_TRANS_VBLANK(pch_transcoder),
 +                 I915_READ(VBLANK(cpu_transcoder)));
 +      I915_WRITE(PCH_TRANS_VSYNC(pch_transcoder),
 +                 I915_READ(VSYNC(cpu_transcoder)));
 +      I915_WRITE(PCH_TRANS_VSYNCSHIFT(pch_transcoder),
 +                 I915_READ(VSYNCSHIFT(cpu_transcoder)));
 +}
 +
  /*
   * Enable PCH resources required for PCH ports:
   *   - PCH PLLs
@@@ -3029,7 -3101,7 +3029,7 @@@ static void ironlake_pch_enable(struct 
        int pipe = intel_crtc->pipe;
        u32 reg, temp;
  
 -      assert_transcoder_disabled(dev_priv, pipe);
 +      assert_pch_transcoder_disabled(dev_priv, pipe);
  
        /* Write the TU size bits before fdi link training, so that error
         * detection works. */
  
        /* set transcoder timing, panel must allow it */
        assert_panel_unlocked(dev_priv, pipe);
 -      I915_WRITE(TRANS_HTOTAL(pipe), I915_READ(HTOTAL(pipe)));
 -      I915_WRITE(TRANS_HBLANK(pipe), I915_READ(HBLANK(pipe)));
 -      I915_WRITE(TRANS_HSYNC(pipe),  I915_READ(HSYNC(pipe)));
 -
 -      I915_WRITE(TRANS_VTOTAL(pipe), I915_READ(VTOTAL(pipe)));
 -      I915_WRITE(TRANS_VBLANK(pipe), I915_READ(VBLANK(pipe)));
 -      I915_WRITE(TRANS_VSYNC(pipe),  I915_READ(VSYNC(pipe)));
 -      I915_WRITE(TRANS_VSYNCSHIFT(pipe),  I915_READ(VSYNCSHIFT(pipe)));
 +      ironlake_pch_transcoder_set_timings(intel_crtc, pipe);
  
        intel_fdi_normal_train(crtc);
  
@@@ -3126,12 -3205,19 +3126,12 @@@ static void lpt_pch_enable(struct drm_c
        struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
        enum transcoder cpu_transcoder = intel_crtc->config.cpu_transcoder;
  
 -      assert_transcoder_disabled(dev_priv, TRANSCODER_A);
 +      assert_pch_transcoder_disabled(dev_priv, TRANSCODER_A);
  
        lpt_program_iclkip(crtc);
  
        /* Set transcoder timing. */
 -      I915_WRITE(_TRANS_HTOTAL_A, I915_READ(HTOTAL(cpu_transcoder)));
 -      I915_WRITE(_TRANS_HBLANK_A, I915_READ(HBLANK(cpu_transcoder)));
 -      I915_WRITE(_TRANS_HSYNC_A,  I915_READ(HSYNC(cpu_transcoder)));
 -
 -      I915_WRITE(_TRANS_VTOTAL_A, I915_READ(VTOTAL(cpu_transcoder)));
 -      I915_WRITE(_TRANS_VBLANK_A, I915_READ(VBLANK(cpu_transcoder)));
 -      I915_WRITE(_TRANS_VSYNC_A,  I915_READ(VSYNC(cpu_transcoder)));
 -      I915_WRITE(_TRANS_VSYNCSHIFT_A, I915_READ(VSYNCSHIFT(cpu_transcoder)));
 +      ironlake_pch_transcoder_set_timings(intel_crtc, PIPE_A);
  
        lpt_enable_pch_transcoder(dev_priv, cpu_transcoder);
  }
@@@ -3208,7 -3294,7 +3208,7 @@@ static struct intel_pch_pll *intel_get_
  found:
        intel_crtc->pch_pll = pll;
        pll->refcount++;
 -      DRM_DEBUG_DRIVER("using pll %d for pipe %d\n", i, intel_crtc->pipe);
 +      DRM_DEBUG_DRIVER("using pll %d for pipe %c\n", i, pipe_name(intel_crtc->pipe));
  prepare: /* separate function? */
        DRM_DEBUG_DRIVER("switching PLL %x off\n", pll->pll_reg);
  
        return pll;
  }
  
 -void intel_cpt_verify_modeset(struct drm_device *dev, int pipe)
 +static void cpt_verify_modeset(struct drm_device *dev, int pipe)
  {
        struct drm_i915_private *dev_priv = dev->dev_private;
        int dslreg = PIPEDSL(pipe);
        udelay(500);
        if (wait_for(I915_READ(dslreg) != temp, 5)) {
                if (wait_for(I915_READ(dslreg) != temp, 5))
 -                      DRM_ERROR("mode set failed: pipe %d stuck\n", pipe);
 +                      DRM_ERROR("mode set failed: pipe %c stuck\n", pipe_name(pipe));
 +      }
 +}
 +
 +static void ironlake_pfit_enable(struct intel_crtc *crtc)
 +{
 +      struct drm_device *dev = crtc->base.dev;
 +      struct drm_i915_private *dev_priv = dev->dev_private;
 +      int pipe = crtc->pipe;
 +
 +      if (crtc->config.pch_pfit.size) {
 +              /* Force use of hard-coded filter coefficients
 +               * as some pre-programmed values are broken,
 +               * e.g. x201.
 +               */
 +              if (IS_IVYBRIDGE(dev) || IS_HASWELL(dev))
 +                      I915_WRITE(PF_CTL(pipe), PF_ENABLE | PF_FILTER_MED_3x3 |
 +                                               PF_PIPE_SEL_IVB(pipe));
 +              else
 +                      I915_WRITE(PF_CTL(pipe), PF_ENABLE | PF_FILTER_MED_3x3);
 +              I915_WRITE(PF_WIN_POS(pipe), crtc->config.pch_pfit.pos);
 +              I915_WRITE(PF_WIN_SZ(pipe), crtc->config.pch_pfit.size);
        }
  }
  
@@@ -3274,10 -3339,6 +3274,10 @@@ static void ironlake_crtc_enable(struc
                return;
  
        intel_crtc->active = true;
 +
 +      intel_set_cpu_fifo_underrun_reporting(dev, pipe, true);
 +      intel_set_pch_fifo_underrun_reporting(dev, pipe, true);
 +
        intel_update_watermarks(dev);
  
        if (intel_pipe_has_type(crtc, INTEL_OUTPUT_LVDS)) {
                        encoder->pre_enable(encoder);
  
        /* Enable panel fitting for LVDS */
 -      if (dev_priv->pch_pf_size &&
 -          (intel_pipe_has_type(crtc, INTEL_OUTPUT_LVDS) ||
 -           intel_pipe_has_type(crtc, INTEL_OUTPUT_EDP))) {
 -              /* Force use of hard-coded filter coefficients
 -               * as some pre-programmed values are broken,
 -               * e.g. x201.
 -               */
 -              if (IS_IVYBRIDGE(dev))
 -                      I915_WRITE(PF_CTL(pipe), PF_ENABLE | PF_FILTER_MED_3x3 |
 -                                               PF_PIPE_SEL_IVB(pipe));
 -              else
 -                      I915_WRITE(PF_CTL(pipe), PF_ENABLE | PF_FILTER_MED_3x3);
 -              I915_WRITE(PF_WIN_POS(pipe), dev_priv->pch_pf_pos);
 -              I915_WRITE(PF_WIN_SZ(pipe), dev_priv->pch_pf_size);
 -      }
 +      ironlake_pfit_enable(intel_crtc);
  
        /*
         * On ILK+ LUT must be loaded before the pipe is running but with
                encoder->enable(encoder);
  
        if (HAS_PCH_CPT(dev))
 -              intel_cpt_verify_modeset(dev, intel_crtc->pipe);
 +              cpt_verify_modeset(dev, intel_crtc->pipe);
  
        /*
         * There seems to be a race in PCH platform hw (at least on some
@@@ -3355,11 -3430,6 +3355,11 @@@ static void haswell_crtc_enable(struct 
                return;
  
        intel_crtc->active = true;
 +
 +      intel_set_cpu_fifo_underrun_reporting(dev, pipe, true);
 +      if (intel_crtc->config.has_pch_encoder)
 +              intel_set_pch_fifo_underrun_reporting(dev, TRANSCODER_A, true);
 +
        intel_update_watermarks(dev);
  
        if (intel_crtc->config.has_pch_encoder)
        intel_ddi_enable_pipe_clock(intel_crtc);
  
        /* Enable panel fitting for eDP */
 -      if (dev_priv->pch_pf_size &&
 -          intel_pipe_has_type(crtc, INTEL_OUTPUT_EDP)) {
 -              /* Force use of hard-coded filter coefficients
 -               * as some pre-programmed values are broken,
 -               * e.g. x201.
 -               */
 -              I915_WRITE(PF_CTL(pipe), PF_ENABLE | PF_FILTER_MED_3x3 |
 -                                       PF_PIPE_SEL_IVB(pipe));
 -              I915_WRITE(PF_WIN_POS(pipe), dev_priv->pch_pf_pos);
 -              I915_WRITE(PF_WIN_SZ(pipe), dev_priv->pch_pf_size);
 -      }
 +      ironlake_pfit_enable(intel_crtc);
  
        /*
         * On ILK+ LUT must be loaded before the pipe is running but with
        intel_wait_for_vblank(dev, intel_crtc->pipe);
  }
  
 +static void ironlake_pfit_disable(struct intel_crtc *crtc)
 +{
 +      struct drm_device *dev = crtc->base.dev;
 +      struct drm_i915_private *dev_priv = dev->dev_private;
 +      int pipe = crtc->pipe;
 +
 +      /* To avoid upsetting the power well on haswell only disable the pfit if
 +       * it's in use. The hw state code will make sure we get this right. */
 +      if (crtc->config.pch_pfit.size) {
 +              I915_WRITE(PF_CTL(pipe), 0);
 +              I915_WRITE(PF_WIN_POS(pipe), 0);
 +              I915_WRITE(PF_WIN_SZ(pipe), 0);
 +      }
 +}
 +
  static void ironlake_crtc_disable(struct drm_crtc *crtc)
  {
        struct drm_device *dev = crtc->dev;
        if (dev_priv->cfb_plane == plane)
                intel_disable_fbc(dev);
  
 +      intel_set_pch_fifo_underrun_reporting(dev, pipe, false);
        intel_disable_pipe(dev_priv, pipe);
  
 -      /* Disable PF */
 -      I915_WRITE(PF_CTL(pipe), 0);
 -      I915_WRITE(PF_WIN_SZ(pipe), 0);
 +      ironlake_pfit_disable(intel_crtc);
  
        for_each_encoder_on_crtc(dev, crtc, encoder)
                if (encoder->post_disable)
        ironlake_fdi_disable(crtc);
  
        ironlake_disable_pch_transcoder(dev_priv, pipe);
 +      intel_set_pch_fifo_underrun_reporting(dev, pipe, true);
  
        if (HAS_PCH_CPT(dev)) {
                /* disable TRANS_DP_CTL */
@@@ -3525,19 -3590,22 +3525,19 @@@ static void haswell_crtc_disable(struc
        drm_vblank_off(dev, pipe);
        intel_crtc_update_cursor(crtc, false);
  
 -      intel_disable_plane(dev_priv, plane, pipe);
 -
 +      /* FBC must be disabled before disabling the plane on HSW. */
        if (dev_priv->cfb_plane == plane)
                intel_disable_fbc(dev);
  
 +      intel_disable_plane(dev_priv, plane, pipe);
 +
 +      if (intel_crtc->config.has_pch_encoder)
 +              intel_set_pch_fifo_underrun_reporting(dev, TRANSCODER_A, false);
        intel_disable_pipe(dev_priv, pipe);
  
        intel_ddi_disable_transcoder_func(dev_priv, cpu_transcoder);
  
 -      /* XXX: Once we have proper panel fitter state tracking implemented with
 -       * hardware state read/check support we should switch to only disable
 -       * the panel fitter when we know it's used. */
 -      if (intel_using_power_well(dev)) {
 -              I915_WRITE(PF_CTL(pipe), 0);
 -              I915_WRITE(PF_WIN_SZ(pipe), 0);
 -      }
 +      ironlake_pfit_disable(intel_crtc);
  
        intel_ddi_disable_pipe_clock(intel_crtc);
  
  
        if (intel_crtc->config.has_pch_encoder) {
                lpt_disable_pch_transcoder(dev_priv);
 +              intel_set_pch_fifo_underrun_reporting(dev, TRANSCODER_A, true);
                intel_ddi_fdi_disable(crtc);
        }
  
@@@ -3618,85 -3685,6 +3618,85 @@@ g4x_fixup_plane(struct drm_i915_privat
        }
  }
  
 +static void i9xx_pfit_enable(struct intel_crtc *crtc)
 +{
 +      struct drm_device *dev = crtc->base.dev;
 +      struct drm_i915_private *dev_priv = dev->dev_private;
 +      struct intel_crtc_config *pipe_config = &crtc->config;
 +
 +      if (!crtc->config.gmch_pfit.control)
 +              return;
 +
 +      WARN_ON(I915_READ(PFIT_CONTROL) & PFIT_ENABLE);
 +      assert_pipe_disabled(dev_priv, crtc->pipe);
 +
 +      /*
 +       * Enable automatic panel scaling so that non-native modes
 +       * fill the screen.  The panel fitter should only be
 +       * adjusted whilst the pipe is disabled, according to
 +       * register description and PRM.
 +       */
 +      DRM_DEBUG_KMS("applying panel-fitter: %x, %x\n",
 +                    pipe_config->gmch_pfit.control,
 +                    pipe_config->gmch_pfit.pgm_ratios);
 +
 +      I915_WRITE(PFIT_PGM_RATIOS, pipe_config->gmch_pfit.pgm_ratios);
 +      I915_WRITE(PFIT_CONTROL, pipe_config->gmch_pfit.control);
 +
 +      /* Border color in case we don't scale up to the full screen. Black by
 +       * default, change to something else for debugging. */
 +      I915_WRITE(BCLRPAT(crtc->pipe), 0);
 +}
 +
 +static void valleyview_crtc_enable(struct drm_crtc *crtc)
 +{
 +      struct drm_device *dev = crtc->dev;
 +      struct drm_i915_private *dev_priv = dev->dev_private;
 +      struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
 +      struct intel_encoder *encoder;
 +      int pipe = intel_crtc->pipe;
 +      int plane = intel_crtc->plane;
 +
 +      WARN_ON(!crtc->enabled);
 +
 +      if (intel_crtc->active)
 +              return;
 +
 +      intel_crtc->active = true;
 +      intel_update_watermarks(dev);
 +
 +      mutex_lock(&dev_priv->dpio_lock);
 +
 +      for_each_encoder_on_crtc(dev, crtc, encoder)
 +              if (encoder->pre_pll_enable)
 +                      encoder->pre_pll_enable(encoder);
 +
 +      intel_enable_pll(dev_priv, pipe);
 +
 +      for_each_encoder_on_crtc(dev, crtc, encoder)
 +              if (encoder->pre_enable)
 +                      encoder->pre_enable(encoder);
 +
 +      /* VLV wants encoder enabling _before_ the pipe is up. */
 +      for_each_encoder_on_crtc(dev, crtc, encoder)
 +              encoder->enable(encoder);
 +
 +      /* Enable panel fitting for eDP */
 +      i9xx_pfit_enable(intel_crtc);
 +
 +      intel_enable_pipe(dev_priv, pipe, false);
 +      intel_enable_plane(dev_priv, plane, pipe);
 +
 +      intel_crtc_load_lut(crtc);
 +      intel_update_fbc(dev);
 +
 +      /* Give the overlay scaler a chance to enable if it's on this pipe */
 +      intel_crtc_dpms_overlay(intel_crtc, true);
 +      intel_crtc_update_cursor(crtc, true);
 +
 +      mutex_unlock(&dev_priv->dpio_lock);
 +}
 +
  static void i9xx_crtc_enable(struct drm_crtc *crtc)
  {
        struct drm_device *dev = crtc->dev;
                if (encoder->pre_enable)
                        encoder->pre_enable(encoder);
  
 +      /* Enable panel fitting for LVDS */
 +      i9xx_pfit_enable(intel_crtc);
 +
        intel_enable_pipe(dev_priv, pipe, false);
        intel_enable_plane(dev_priv, plane, pipe);
        if (IS_G4X(dev))
@@@ -3743,15 -3728,20 +3743,15 @@@ static void i9xx_pfit_disable(struct in
  {
        struct drm_device *dev = crtc->base.dev;
        struct drm_i915_private *dev_priv = dev->dev_private;
 -      enum pipe pipe;
 -      uint32_t pctl = I915_READ(PFIT_CONTROL);
  
 -      assert_pipe_disabled(dev_priv, crtc->pipe);
 +      if (!crtc->config.gmch_pfit.control)
 +              return;
  
 -      if (INTEL_INFO(dev)->gen >= 4)
 -              pipe = (pctl & PFIT_PIPE_MASK) >> PFIT_PIPE_SHIFT;
 -      else
 -              pipe = PIPE_B;
 +      assert_pipe_disabled(dev_priv, crtc->pipe);
  
 -      if (pipe == crtc->pipe) {
 -              DRM_DEBUG_DRIVER("disabling pfit, current: 0x%08x\n", pctl);
 -              I915_WRITE(PFIT_CONTROL, 0);
 -      }
 +      DRM_DEBUG_DRIVER("disabling pfit, current: 0x%08x\n",
 +                       I915_READ(PFIT_CONTROL));
 +      I915_WRITE(PFIT_CONTROL, 0);
  }
  
  static void i9xx_crtc_disable(struct drm_crtc *crtc)
  
        i9xx_pfit_disable(intel_crtc);
  
 +      for_each_encoder_on_crtc(dev, crtc, encoder)
 +              if (encoder->post_disable)
 +                      encoder->post_disable(encoder);
 +
        intel_disable_pll(dev_priv, pipe);
  
        intel_crtc->active = false;
@@@ -3859,8 -3845,8 +3859,8 @@@ static void intel_crtc_disable(struct d
        /* crtc should still be enabled when we disable it. */
        WARN_ON(!crtc->enabled);
  
 -      intel_crtc->eld_vld = false;
        dev_priv->display.crtc_disable(crtc);
 +      intel_crtc->eld_vld = false;
        intel_crtc_update_sarea(crtc, false);
        dev_priv->display.off(crtc);
  
@@@ -3991,118 -3977,8 +3991,118 @@@ bool intel_connector_get_hw_state(struc
        return encoder->get_hw_state(encoder, &pipe);
  }
  
 -static bool intel_crtc_compute_config(struct drm_crtc *crtc,
 -                                    struct intel_crtc_config *pipe_config)
 +static bool ironlake_check_fdi_lanes(struct drm_device *dev, enum pipe pipe,
 +                                   struct intel_crtc_config *pipe_config)
 +{
 +      struct drm_i915_private *dev_priv = dev->dev_private;
 +      struct intel_crtc *pipe_B_crtc =
 +              to_intel_crtc(dev_priv->pipe_to_crtc_mapping[PIPE_B]);
 +
 +      DRM_DEBUG_KMS("checking fdi config on pipe %c, lanes %i\n",
 +                    pipe_name(pipe), pipe_config->fdi_lanes);
 +      if (pipe_config->fdi_lanes > 4) {
 +              DRM_DEBUG_KMS("invalid fdi lane config on pipe %c: %i lanes\n",
 +                            pipe_name(pipe), pipe_config->fdi_lanes);
 +              return false;
 +      }
 +
 +      if (IS_HASWELL(dev)) {
 +              if (pipe_config->fdi_lanes > 2) {
 +                      DRM_DEBUG_KMS("only 2 lanes on haswell, required: %i lanes\n",
 +                                    pipe_config->fdi_lanes);
 +                      return false;
 +              } else {
 +                      return true;
 +              }
 +      }
 +
 +      if (INTEL_INFO(dev)->num_pipes == 2)
 +              return true;
 +
 +      /* Ivybridge 3 pipe is really complicated */
 +      switch (pipe) {
 +      case PIPE_A:
 +              return true;
 +      case PIPE_B:
 +              if (dev_priv->pipe_to_crtc_mapping[PIPE_C]->enabled &&
 +                  pipe_config->fdi_lanes > 2) {
 +                      DRM_DEBUG_KMS("invalid shared fdi lane config on pipe %c: %i lanes\n",
 +                                    pipe_name(pipe), pipe_config->fdi_lanes);
 +                      return false;
 +              }
 +              return true;
 +      case PIPE_C:
 +              if (!pipe_has_enabled_pch(pipe_B_crtc) ||
 +                  pipe_B_crtc->config.fdi_lanes <= 2) {
 +                      if (pipe_config->fdi_lanes > 2) {
 +                              DRM_DEBUG_KMS("invalid shared fdi lane config on pipe %c: %i lanes\n",
 +                                            pipe_name(pipe), pipe_config->fdi_lanes);
 +                              return false;
 +                      }
 +              } else {
 +                      DRM_DEBUG_KMS("fdi link B uses too many lanes to enable link C\n");
 +                      return false;
 +              }
 +              return true;
 +      default:
 +              BUG();
 +      }
 +}
 +
 +#define RETRY 1
 +static int ironlake_fdi_compute_config(struct intel_crtc *intel_crtc,
 +                                     struct intel_crtc_config *pipe_config)
 +{
 +      struct drm_device *dev = intel_crtc->base.dev;
 +      struct drm_display_mode *adjusted_mode = &pipe_config->adjusted_mode;
 +      int target_clock, lane, link_bw;
 +      bool setup_ok, needs_recompute = false;
 +
 +retry:
 +      /* FDI is a binary signal running at ~2.7GHz, encoding
 +       * each output octet as 10 bits. The actual frequency
 +       * is stored as a divider into a 100MHz clock, and the
 +       * mode pixel clock is stored in units of 1KHz.
 +       * Hence the bw of each lane in terms of the mode signal
 +       * is:
 +       */
 +      link_bw = intel_fdi_link_freq(dev) * MHz(100)/KHz(1)/10;
 +
 +      if (pipe_config->pixel_target_clock)
 +              target_clock = pipe_config->pixel_target_clock;
 +      else
 +              target_clock = adjusted_mode->clock;
 +
 +      lane = ironlake_get_lanes_required(target_clock, link_bw,
 +                                         pipe_config->pipe_bpp);
 +
 +      pipe_config->fdi_lanes = lane;
 +
 +      if (pipe_config->pixel_multiplier > 1)
 +              link_bw *= pipe_config->pixel_multiplier;
 +      intel_link_compute_m_n(pipe_config->pipe_bpp, lane, target_clock,
 +                             link_bw, &pipe_config->fdi_m_n);
 +
 +      setup_ok = ironlake_check_fdi_lanes(intel_crtc->base.dev,
 +                                          intel_crtc->pipe, pipe_config);
 +      if (!setup_ok && pipe_config->pipe_bpp > 6*3) {
 +              pipe_config->pipe_bpp -= 2*3;
 +              DRM_DEBUG_KMS("fdi link bw constraint, reducing pipe bpp to %i\n",
 +                            pipe_config->pipe_bpp);
 +              needs_recompute = true;
 +              pipe_config->bw_constrained = true;
 +
 +              goto retry;
 +      }
 +
 +      if (needs_recompute)
 +              return RETRY;
 +
 +      return setup_ok ? 0 : -EINVAL;
 +}
 +
 +static int intel_crtc_compute_config(struct drm_crtc *crtc,
 +                                   struct intel_crtc_config *pipe_config)
  {
        struct drm_device *dev = crtc->dev;
        struct drm_display_mode *adjusted_mode = &pipe_config->adjusted_mode;
                /* FDI link clock is fixed at 2.7G */
                if (pipe_config->requested_mode.clock * 3
                    > IRONLAKE_FDI_FREQ * 4)
 -                      return false;
 +                      return -EINVAL;
        }
  
        /* All interlaced capable intel hw wants timings in frames. Note though
        if (!pipe_config->timings_set)
                drm_mode_set_crtcinfo(adjusted_mode, 0);
  
 -      /* WaPruneModeWithIncorrectHsyncOffset: Cantiga+ cannot handle modes
 -       * with a hsync front porch of 0.
 +      /* Cantiga+ cannot handle modes with a hsync front porch of 0.
 +       * WaPruneModeWithIncorrectHsyncOffset:ctg,elk,ilk,snb,ivb,vlv,hsw.
         */
        if ((INTEL_INFO(dev)->gen > 4 || IS_G4X(dev)) &&
                adjusted_mode->hsync_start == adjusted_mode->hdisplay)
 -              return false;
 +              return -EINVAL;
  
        if ((IS_G4X(dev) || IS_VALLEYVIEW(dev)) && pipe_config->pipe_bpp > 10*3) {
                pipe_config->pipe_bpp = 10*3; /* 12bpc is gen5+ */
                pipe_config->pipe_bpp = 8*3;
        }
  
 -      return true;
 +      if (pipe_config->has_pch_encoder)
 +              return ironlake_fdi_compute_config(to_intel_crtc(crtc), pipe_config);
 +
 +      return 0;
  }
  
  static int valleyview_get_display_clock_speed(struct drm_device *dev)
@@@ -4211,33 -4084,43 +4211,43 @@@ static int i830_get_display_clock_speed
  }
  
  static void
- intel_reduce_ratio(uint32_t *num, uint32_t *den)
+ intel_reduce_m_n_ratio(uint32_t *num, uint32_t *den)
  {
-       while (*num > 0xffffff || *den > 0xffffff) {
+       while (*num > DATA_LINK_M_N_MASK ||
+              *den > DATA_LINK_M_N_MASK) {
                *num >>= 1;
                *den >>= 1;
        }
  }
  
+ static void compute_m_n(unsigned int m, unsigned int n,
+                       uint32_t *ret_m, uint32_t *ret_n)
+ {
+       *ret_n = min_t(unsigned int, roundup_pow_of_two(n), DATA_LINK_N_MAX);
+       *ret_m = div_u64((uint64_t) m * *ret_n, n);
+       intel_reduce_m_n_ratio(ret_m, ret_n);
+ }
  void
  intel_link_compute_m_n(int bits_per_pixel, int nlanes,
                       int pixel_clock, int link_clock,
                       struct intel_link_m_n *m_n)
  {
        m_n->tu = 64;
-       m_n->gmch_m = bits_per_pixel * pixel_clock;
-       m_n->gmch_n = link_clock * nlanes * 8;
-       intel_reduce_ratio(&m_n->gmch_m, &m_n->gmch_n);
-       m_n->link_m = pixel_clock;
-       m_n->link_n = link_clock;
-       intel_reduce_ratio(&m_n->link_m, &m_n->link_n);
+       compute_m_n(bits_per_pixel * pixel_clock,
+                   link_clock * nlanes * 8,
+                   &m_n->gmch_m, &m_n->gmch_n);
+       compute_m_n(pixel_clock, link_clock,
+                   &m_n->link_m, &m_n->link_n);
  }
  
  static inline bool intel_panel_use_ssc(struct drm_i915_private *dev_priv)
  {
        if (i915_panel_use_ssc >= 0)
                return i915_panel_use_ssc != 0;
 -      return dev_priv->lvds_use_ssc
 +      return dev_priv->vbt.lvds_use_ssc
                && !(dev_priv->quirks & QUIRK_LVDS_SSC_DISABLE);
  }
  
@@@ -4273,7 -4156,7 +4283,7 @@@ static int i9xx_get_refclk(struct drm_c
                refclk = vlv_get_refclk(crtc);
        } else if (intel_pipe_has_type(crtc, INTEL_OUTPUT_LVDS) &&
            intel_panel_use_ssc(dev_priv) && num_connectors < 2) {
 -              refclk = dev_priv->lvds_ssc_freq * 1000;
 +              refclk = dev_priv->vbt.lvds_ssc_freq * 1000;
                DRM_DEBUG_KMS("using SSC reference clock of %d MHz\n",
                              refclk / 1000);
        } else if (!IS_GEN2(dev)) {
        return refclk;
  }
  
 -static void i9xx_adjust_sdvo_tv_clock(struct intel_crtc *crtc)
 +static uint32_t pnv_dpll_compute_fp(struct dpll *dpll)
  {
 -      unsigned dotclock = crtc->config.adjusted_mode.clock;
 -      struct dpll *clock = &crtc->config.dpll;
 -
 -      /* SDVO TV has fixed PLL values depend on its clock range,
 -         this mirrors vbios setting. */
 -      if (dotclock >= 100000 && dotclock < 140500) {
 -              clock->p1 = 2;
 -              clock->p2 = 10;
 -              clock->n = 3;
 -              clock->m1 = 16;
 -              clock->m2 = 8;
 -      } else if (dotclock >= 140500 && dotclock <= 200000) {
 -              clock->p1 = 1;
 -              clock->p2 = 10;
 -              clock->n = 6;
 -              clock->m1 = 12;
 -              clock->m2 = 8;
 -      }
 +      return (1 << dpll->n) << 16 | dpll->m1 << 8 | dpll->m2;
 +}
  
 -      crtc->config.clock_set = true;
 +static uint32_t i9xx_dpll_compute_fp(struct dpll *dpll)
 +{
 +      return dpll->n << 16 | dpll->m1 << 8 | dpll->m2;
  }
  
  static void i9xx_update_pll_dividers(struct intel_crtc *crtc,
        struct drm_i915_private *dev_priv = dev->dev_private;
        int pipe = crtc->pipe;
        u32 fp, fp2 = 0;
 -      struct dpll *clock = &crtc->config.dpll;
  
        if (IS_PINEVIEW(dev)) {
 -              fp = (1 << clock->n) << 16 | clock->m1 << 8 | clock->m2;
 +              fp = pnv_dpll_compute_fp(&crtc->config.dpll);
                if (reduced_clock)
 -                      fp2 = (1 << reduced_clock->n) << 16 |
 -                              reduced_clock->m1 << 8 | reduced_clock->m2;
 +                      fp2 = pnv_dpll_compute_fp(reduced_clock);
        } else {
 -              fp = clock->n << 16 | clock->m1 << 8 | clock->m2;
 +              fp = i9xx_dpll_compute_fp(&crtc->config.dpll);
                if (reduced_clock)
 -                      fp2 = reduced_clock->n << 16 | reduced_clock->m1 << 8 |
 -                              reduced_clock->m2;
 +                      fp2 = i9xx_dpll_compute_fp(reduced_clock);
        }
  
        I915_WRITE(FP0(pipe), fp);
        }
  }
  
 +static void vlv_pllb_recal_opamp(struct drm_i915_private *dev_priv)
 +{
 +      u32 reg_val;
 +
 +      /*
 +       * PLLB opamp always calibrates to max value of 0x3f, force enable it
 +       * and set it to a reasonable value instead.
 +       */
 +      reg_val = intel_dpio_read(dev_priv, DPIO_IREF(1));
 +      reg_val &= 0xffffff00;
 +      reg_val |= 0x00000030;
 +      intel_dpio_write(dev_priv, DPIO_IREF(1), reg_val);
 +
 +      reg_val = intel_dpio_read(dev_priv, DPIO_CALIBRATION);
 +      reg_val &= 0x8cffffff;
 +      reg_val = 0x8c000000;
 +      intel_dpio_write(dev_priv, DPIO_CALIBRATION, reg_val);
 +
 +      reg_val = intel_dpio_read(dev_priv, DPIO_IREF(1));
 +      reg_val &= 0xffffff00;
 +      intel_dpio_write(dev_priv, DPIO_IREF(1), reg_val);
 +
 +      reg_val = intel_dpio_read(dev_priv, DPIO_CALIBRATION);
 +      reg_val &= 0x00ffffff;
 +      reg_val |= 0xb0000000;
 +      intel_dpio_write(dev_priv, DPIO_CALIBRATION, reg_val);
 +}
 +
 +static void intel_pch_transcoder_set_m_n(struct intel_crtc *crtc,
 +                                       struct intel_link_m_n *m_n)
 +{
 +      struct drm_device *dev = crtc->base.dev;
 +      struct drm_i915_private *dev_priv = dev->dev_private;
 +      int pipe = crtc->pipe;
 +
 +      I915_WRITE(PCH_TRANS_DATA_M1(pipe), TU_SIZE(m_n->tu) | m_n->gmch_m);
 +      I915_WRITE(PCH_TRANS_DATA_N1(pipe), m_n->gmch_n);
 +      I915_WRITE(PCH_TRANS_LINK_M1(pipe), m_n->link_m);
 +      I915_WRITE(PCH_TRANS_LINK_N1(pipe), m_n->link_n);
 +}
 +
 +static void intel_cpu_transcoder_set_m_n(struct intel_crtc *crtc,
 +                                       struct intel_link_m_n *m_n)
 +{
 +      struct drm_device *dev = crtc->base.dev;
 +      struct drm_i915_private *dev_priv = dev->dev_private;
 +      int pipe = crtc->pipe;
 +      enum transcoder transcoder = crtc->config.cpu_transcoder;
 +
 +      if (INTEL_INFO(dev)->gen >= 5) {
 +              I915_WRITE(PIPE_DATA_M1(transcoder), TU_SIZE(m_n->tu) | m_n->gmch_m);
 +              I915_WRITE(PIPE_DATA_N1(transcoder), m_n->gmch_n);
 +              I915_WRITE(PIPE_LINK_M1(transcoder), m_n->link_m);
 +              I915_WRITE(PIPE_LINK_N1(transcoder), m_n->link_n);
 +      } else {
 +              I915_WRITE(PIPE_DATA_M_G4X(pipe), TU_SIZE(m_n->tu) | m_n->gmch_m);
 +              I915_WRITE(PIPE_DATA_N_G4X(pipe), m_n->gmch_n);
 +              I915_WRITE(PIPE_LINK_M_G4X(pipe), m_n->link_m);
 +              I915_WRITE(PIPE_LINK_N_G4X(pipe), m_n->link_n);
 +      }
 +}
 +
  static void intel_dp_set_m_n(struct intel_crtc *crtc)
  {
        if (crtc->config.has_pch_encoder)
@@@ -4399,18 -4237,24 +4409,18 @@@ static void vlv_update_pll(struct intel
  {
        struct drm_device *dev = crtc->base.dev;
        struct drm_i915_private *dev_priv = dev->dev_private;
 +      struct drm_display_mode *adjusted_mode =
 +              &crtc->config.adjusted_mode;
 +      struct intel_encoder *encoder;
        int pipe = crtc->pipe;
 -      u32 dpll, mdiv, pdiv;
 +      u32 dpll, mdiv;
        u32 bestn, bestm1, bestm2, bestp1, bestp2;
 -      bool is_sdvo;
 -      u32 temp;
 +      bool is_hdmi;
 +      u32 coreclk, reg_val, dpll_md;
  
        mutex_lock(&dev_priv->dpio_lock);
  
 -      is_sdvo = intel_pipe_has_type(&crtc->base, INTEL_OUTPUT_SDVO) ||
 -              intel_pipe_has_type(&crtc->base, INTEL_OUTPUT_HDMI);
 -
 -      dpll = DPLL_VGA_MODE_DIS;
 -      dpll |= DPLL_EXT_BUFFER_ENABLE_VLV;
 -      dpll |= DPLL_REFA_CLK_ENABLE_VLV;
 -      dpll |= DPLL_INTEGRATED_CLOCK_VLV;
 -
 -      I915_WRITE(DPLL(pipe), dpll);
 -      POSTING_READ(DPLL(pipe));
 +      is_hdmi = intel_pipe_has_type(&crtc->base, INTEL_OUTPUT_HDMI);
  
        bestn = crtc->config.dpll.n;
        bestm1 = crtc->config.dpll.m1;
        bestp1 = crtc->config.dpll.p1;
        bestp2 = crtc->config.dpll.p2;
  
 -      /*
 -       * In Valleyview PLL and program lane counter registers are exposed
 -       * through DPIO interface
 -       */
 +      /* See eDP HDMI DPIO driver vbios notes doc */
 +
 +      /* PLL B needs special handling */
 +      if (pipe)
 +              vlv_pllb_recal_opamp(dev_priv);
 +
 +      /* Set up Tx target for periodic Rcomp update */
 +      intel_dpio_write(dev_priv, DPIO_IREF_BCAST, 0x0100000f);
 +
 +      /* Disable target IRef on PLL */
 +      reg_val = intel_dpio_read(dev_priv, DPIO_IREF_CTL(pipe));
 +      reg_val &= 0x00ffffff;
 +      intel_dpio_write(dev_priv, DPIO_IREF_CTL(pipe), reg_val);
 +
 +      /* Disable fast lock */
 +      intel_dpio_write(dev_priv, DPIO_FASTCLK_DISABLE, 0x610);
 +
 +      /* Set idtafcrecal before PLL is enabled */
        mdiv = ((bestm1 << DPIO_M1DIV_SHIFT) | (bestm2 & DPIO_M2DIV_MASK));
        mdiv |= ((bestp1 << DPIO_P1_SHIFT) | (bestp2 << DPIO_P2_SHIFT));
        mdiv |= ((bestn << DPIO_N_SHIFT));
 -      mdiv |= (1 << DPIO_POST_DIV_SHIFT);
        mdiv |= (1 << DPIO_K_SHIFT);
 +
 +      /*
 +       * Post divider depends on pixel clock rate, DAC vs digital (and LVDS,
 +       * but we don't support that).
 +       * Note: don't use the DAC post divider as it seems unstable.
 +       */
 +      mdiv |= (DPIO_POST_DIV_HDMIDP << DPIO_POST_DIV_SHIFT);
 +      intel_dpio_write(dev_priv, DPIO_DIV(pipe), mdiv);
 +
        mdiv |= DPIO_ENABLE_CALIBRATION;
        intel_dpio_write(dev_priv, DPIO_DIV(pipe), mdiv);
  
 -      intel_dpio_write(dev_priv, DPIO_CORE_CLK(pipe), 0x01000000);
 +      /* Set HBR and RBR LPF coefficients */
 +      if (adjusted_mode->clock == 162000 ||
 +          intel_pipe_has_type(&crtc->base, INTEL_OUTPUT_HDMI))
 +              intel_dpio_write(dev_priv, DPIO_LFP_COEFF(pipe),
 +                               0x005f0021);
 +      else
 +              intel_dpio_write(dev_priv, DPIO_LFP_COEFF(pipe),
 +                               0x00d0000f);
 +
 +      if (intel_pipe_has_type(&crtc->base, INTEL_OUTPUT_EDP) ||
 +          intel_pipe_has_type(&crtc->base, INTEL_OUTPUT_DISPLAYPORT)) {
 +              /* Use SSC source */
 +              if (!pipe)
 +                      intel_dpio_write(dev_priv, DPIO_REFSFR(pipe),
 +                                       0x0df40000);
 +              else
 +                      intel_dpio_write(dev_priv, DPIO_REFSFR(pipe),
 +                                       0x0df70000);
 +      } else { /* HDMI or VGA */
 +              /* Use bend source */
 +              if (!pipe)
 +                      intel_dpio_write(dev_priv, DPIO_REFSFR(pipe),
 +                                       0x0df70000);
 +              else
 +                      intel_dpio_write(dev_priv, DPIO_REFSFR(pipe),
 +                                       0x0df40000);
 +      }
 +
 +      coreclk = intel_dpio_read(dev_priv, DPIO_CORE_CLK(pipe));
 +      coreclk = (coreclk & 0x0000ff00) | 0x01c00000;
 +      if (intel_pipe_has_type(&crtc->base, INTEL_OUTPUT_DISPLAYPORT) ||
 +          intel_pipe_has_type(&crtc->base, INTEL_OUTPUT_EDP))
 +              coreclk |= 0x01000000;
 +      intel_dpio_write(dev_priv, DPIO_CORE_CLK(pipe), coreclk);
 +
 +      intel_dpio_write(dev_priv, DPIO_PLL_CML(pipe), 0x87871000);
  
 -      pdiv = (1 << DPIO_REFSEL_OVERRIDE) | (5 << DPIO_PLL_MODESEL_SHIFT) |
 -              (3 << DPIO_BIAS_CURRENT_CTL_SHIFT) | (1<<20) |
 -              (7 << DPIO_PLL_REFCLK_SEL_SHIFT) | (8 << DPIO_DRIVER_CTL_SHIFT) |
 -              (5 << DPIO_CLK_BIAS_CTL_SHIFT);
 -      intel_dpio_write(dev_priv, DPIO_REFSFR(pipe), pdiv);
 +      for_each_encoder_on_crtc(dev, &crtc->base, encoder)
 +              if (encoder->pre_pll_enable)
 +                      encoder->pre_pll_enable(encoder);
  
 -      intel_dpio_write(dev_priv, DPIO_LFP_COEFF(pipe), 0x005f003b);
 +      /* Enable DPIO clock input */
 +      dpll = DPLL_EXT_BUFFER_ENABLE_VLV | DPLL_REFA_CLK_ENABLE_VLV |
 +              DPLL_VGA_MODE_DIS | DPLL_INTEGRATED_CLOCK_VLV;
 +      if (pipe)
 +              dpll |= DPLL_INTEGRATED_CRI_CLK_VLV;
  
        dpll |= DPLL_VCO_ENABLE;
        I915_WRITE(DPLL(pipe), dpll);
        POSTING_READ(DPLL(pipe));
 +      udelay(150);
 +
        if (wait_for(((I915_READ(DPLL(pipe)) & DPLL_LOCK_VLV) == DPLL_LOCK_VLV), 1))
                DRM_ERROR("DPLL %d failed to lock\n", pipe);
  
 -      intel_dpio_write(dev_priv, DPIO_FASTCLK_DISABLE, 0x620);
 -
 -      if (crtc->config.has_dp_encoder)
 -              intel_dp_set_m_n(crtc);
 -
 -      I915_WRITE(DPLL(pipe), dpll);
 -
 -      /* Wait for the clocks to stabilize. */
 -      POSTING_READ(DPLL(pipe));
 -      udelay(150);
 -
 -      temp = 0;
 -      if (is_sdvo) {
 -              temp = 0;
 -              if (crtc->config.pixel_multiplier > 1) {
 -                      temp = (crtc->config.pixel_multiplier - 1)
 -                              << DPLL_MD_UDI_MULTIPLIER_SHIFT;
 -              }
 +      dpll_md = 0;
 +      if (crtc->config.pixel_multiplier > 1) {
 +              dpll_md = (crtc->config.pixel_multiplier - 1)
 +                      << DPLL_MD_UDI_MULTIPLIER_SHIFT;
        }
 -      I915_WRITE(DPLL_MD(pipe), temp);
 +      I915_WRITE(DPLL_MD(pipe), dpll_md);
        POSTING_READ(DPLL_MD(pipe));
  
 -      /* Now program lane control registers */
 -      if(intel_pipe_has_type(&crtc->base, INTEL_OUTPUT_DISPLAYPORT)
 -         || intel_pipe_has_type(&crtc->base, INTEL_OUTPUT_HDMI)) {
 -              temp = 0x1000C4;
 -              if(pipe == 1)
 -                      temp |= (1 << 21);
 -              intel_dpio_write(dev_priv, DPIO_DATA_CHANNEL1, temp);
 -      }
 -
 -      if(intel_pipe_has_type(&crtc->base, INTEL_OUTPUT_EDP)) {
 -              temp = 0x1000C4;
 -              if(pipe == 1)
 -                      temp |= (1 << 21);
 -              intel_dpio_write(dev_priv, DPIO_DATA_CHANNEL2, temp);
 -      }
 +      if (crtc->config.has_dp_encoder)
 +              intel_dp_set_m_n(crtc);
  
        mutex_unlock(&dev_priv->dpio_lock);
  }
@@@ -4545,15 -4355,14 +4555,15 @@@ static void i9xx_update_pll(struct inte
        else
                dpll |= DPLLB_MODE_DAC_SERIAL;
  
 -      if (is_sdvo) {
 -              if ((crtc->config.pixel_multiplier > 1) &&
 -                  (IS_I945G(dev) || IS_I945GM(dev) || IS_G33(dev))) {
 -                      dpll |= (crtc->config.pixel_multiplier - 1)
 -                              << SDVO_MULTIPLIER_SHIFT_HIRES;
 -              }
 -              dpll |= DPLL_DVO_HIGH_SPEED;
 +      if ((crtc->config.pixel_multiplier > 1) &&
 +          (IS_I945G(dev) || IS_I945GM(dev) || IS_G33(dev))) {
 +              dpll |= (crtc->config.pixel_multiplier - 1)
 +                      << SDVO_MULTIPLIER_SHIFT_HIRES;
        }
 +
 +      if (is_sdvo)
 +              dpll |= DPLL_DVO_HIGH_SPEED;
 +
        if (intel_pipe_has_type(&crtc->base, INTEL_OUTPUT_DISPLAYPORT))
                dpll |= DPLL_DVO_HIGH_SPEED;
  
        if (INTEL_INFO(dev)->gen >= 4)
                dpll |= (6 << PLL_LOAD_PULSE_PHASE_SHIFT);
  
 -      if (is_sdvo && intel_pipe_has_type(&crtc->base, INTEL_OUTPUT_TVOUT))
 +      if (crtc->config.sdvo_tv_clock)
                dpll |= PLL_REF_INPUT_TVCLKINBC;
 -      else if (intel_pipe_has_type(&crtc->base, INTEL_OUTPUT_TVOUT))
 -              /* XXX: just matching BIOS for now */
 -              /*      dpll |= PLL_REF_INPUT_TVCLKINBC; */
 -              dpll |= 3;
        else if (intel_pipe_has_type(&crtc->base, INTEL_OUTPUT_LVDS) &&
                 intel_panel_use_ssc(dev_priv) && num_connectors < 2)
                dpll |= PLLB_REF_INPUT_SPREADSPECTRUMIN;
        udelay(150);
  
        if (INTEL_INFO(dev)->gen >= 4) {
 -              u32 temp = 0;
 -              if (is_sdvo) {
 -                      temp = 0;
 -                      if (crtc->config.pixel_multiplier > 1) {
 -                              temp = (crtc->config.pixel_multiplier - 1)
 -                                      << DPLL_MD_UDI_MULTIPLIER_SHIFT;
 -                      }
 +              u32 dpll_md = 0;
 +              if (crtc->config.pixel_multiplier > 1) {
 +                      dpll_md = (crtc->config.pixel_multiplier - 1)
 +                              << DPLL_MD_UDI_MULTIPLIER_SHIFT;
                }
 -              I915_WRITE(DPLL_MD(pipe), temp);
 +              I915_WRITE(DPLL_MD(pipe), dpll_md);
        } else {
                /* The pixel multiplier can only be updated once the
                 * DPLL is enabled and the clocks are stable.
@@@ -4689,17 -4505,12 +4699,17 @@@ static void intel_set_pipe_timings(stru
        struct drm_i915_private *dev_priv = dev->dev_private;
        enum pipe pipe = intel_crtc->pipe;
        enum transcoder cpu_transcoder = intel_crtc->config.cpu_transcoder;
 -      uint32_t vsyncshift;
 +      uint32_t vsyncshift, crtc_vtotal, crtc_vblank_end;
 +
 +      /* We need to be careful not to changed the adjusted mode, for otherwise
 +       * the hw state checker will get angry at the mismatch. */
 +      crtc_vtotal = adjusted_mode->crtc_vtotal;
 +      crtc_vblank_end = adjusted_mode->crtc_vblank_end;
  
        if (!IS_GEN2(dev) && adjusted_mode->flags & DRM_MODE_FLAG_INTERLACE) {
                /* the chip adds 2 halflines automatically */
 -              adjusted_mode->crtc_vtotal -= 1;
 -              adjusted_mode->crtc_vblank_end -= 1;
 +              crtc_vtotal -= 1;
 +              crtc_vblank_end -= 1;
                vsyncshift = adjusted_mode->crtc_hsync_start
                             - adjusted_mode->crtc_htotal / 2;
        } else {
  
        I915_WRITE(VTOTAL(cpu_transcoder),
                   (adjusted_mode->crtc_vdisplay - 1) |
 -                 ((adjusted_mode->crtc_vtotal - 1) << 16));
 +                 ((crtc_vtotal - 1) << 16));
        I915_WRITE(VBLANK(cpu_transcoder),
                   (adjusted_mode->crtc_vblank_start - 1) |
 -                 ((adjusted_mode->crtc_vblank_end - 1) << 16));
 +                 ((crtc_vblank_end - 1) << 16));
        I915_WRITE(VSYNC(cpu_transcoder),
                   (adjusted_mode->crtc_vsync_start - 1) |
                   ((adjusted_mode->crtc_vsync_end - 1) << 16));
                   ((mode->hdisplay - 1) << 16) | (mode->vdisplay - 1));
  }
  
 +static void intel_get_pipe_timings(struct intel_crtc *crtc,
 +                                 struct intel_crtc_config *pipe_config)
 +{
 +      struct drm_device *dev = crtc->base.dev;
 +      struct drm_i915_private *dev_priv = dev->dev_private;
 +      enum transcoder cpu_transcoder = pipe_config->cpu_transcoder;
 +      uint32_t tmp;
 +
 +      tmp = I915_READ(HTOTAL(cpu_transcoder));
 +      pipe_config->adjusted_mode.crtc_hdisplay = (tmp & 0xffff) + 1;
 +      pipe_config->adjusted_mode.crtc_htotal = ((tmp >> 16) & 0xffff) + 1;
 +      tmp = I915_READ(HBLANK(cpu_transcoder));
 +      pipe_config->adjusted_mode.crtc_hblank_start = (tmp & 0xffff) + 1;
 +      pipe_config->adjusted_mode.crtc_hblank_end = ((tmp >> 16) & 0xffff) + 1;
 +      tmp = I915_READ(HSYNC(cpu_transcoder));
 +      pipe_config->adjusted_mode.crtc_hsync_start = (tmp & 0xffff) + 1;
 +      pipe_config->adjusted_mode.crtc_hsync_end = ((tmp >> 16) & 0xffff) + 1;
 +
 +      tmp = I915_READ(VTOTAL(cpu_transcoder));
 +      pipe_config->adjusted_mode.crtc_vdisplay = (tmp & 0xffff) + 1;
 +      pipe_config->adjusted_mode.crtc_vtotal = ((tmp >> 16) & 0xffff) + 1;
 +      tmp = I915_READ(VBLANK(cpu_transcoder));
 +      pipe_config->adjusted_mode.crtc_vblank_start = (tmp & 0xffff) + 1;
 +      pipe_config->adjusted_mode.crtc_vblank_end = ((tmp >> 16) & 0xffff) + 1;
 +      tmp = I915_READ(VSYNC(cpu_transcoder));
 +      pipe_config->adjusted_mode.crtc_vsync_start = (tmp & 0xffff) + 1;
 +      pipe_config->adjusted_mode.crtc_vsync_end = ((tmp >> 16) & 0xffff) + 1;
 +
 +      if (I915_READ(PIPECONF(cpu_transcoder)) & PIPECONF_INTERLACE_MASK) {
 +              pipe_config->adjusted_mode.flags |= DRM_MODE_FLAG_INTERLACE;
 +              pipe_config->adjusted_mode.crtc_vtotal += 1;
 +              pipe_config->adjusted_mode.crtc_vblank_end += 1;
 +      }
 +
 +      tmp = I915_READ(PIPESRC(crtc->pipe));
 +      pipe_config->requested_mode.vdisplay = (tmp & 0xffff) + 1;
 +      pipe_config->requested_mode.hdisplay = ((tmp >> 16) & 0xffff) + 1;
 +}
 +
  static void i9xx_set_pipeconf(struct intel_crtc *intel_crtc)
  {
        struct drm_device *dev = intel_crtc->base.dev;
                        pipeconf &= ~PIPECONF_DOUBLE_WIDE;
        }
  
 -      /* default to 8bpc */
 -      pipeconf &= ~(PIPECONF_BPC_MASK | PIPECONF_DITHER_EN);
 -      if (intel_crtc->config.has_dp_encoder) {
 -              if (intel_crtc->config.dither) {
 -                      pipeconf |= PIPECONF_6BPC |
 -                                  PIPECONF_DITHER_EN |
 +      /* only g4x and later have fancy bpc/dither controls */
 +      if (IS_G4X(dev) || IS_VALLEYVIEW(dev)) {
 +              pipeconf &= ~(PIPECONF_BPC_MASK |
 +                            PIPECONF_DITHER_EN | PIPECONF_DITHER_TYPE_MASK);
 +
 +              /* Bspec claims that we can't use dithering for 30bpp pipes. */
 +              if (intel_crtc->config.dither && intel_crtc->config.pipe_bpp != 30)
 +                      pipeconf |= PIPECONF_DITHER_EN |
                                    PIPECONF_DITHER_TYPE_SP;
 -              }
 -      }
  
 -      if (IS_VALLEYVIEW(dev) && intel_pipe_has_type(&intel_crtc->base,
 -                                                    INTEL_OUTPUT_EDP)) {
 -              if (intel_crtc->config.dither) {
 -                      pipeconf |= PIPECONF_6BPC |
 -                                      PIPECONF_ENABLE |
 -                                      I965_PIPECONF_ACTIVE;
 +              switch (intel_crtc->config.pipe_bpp) {
 +              case 18:
 +                      pipeconf |= PIPECONF_6BPC;
 +                      break;
 +              case 24:
 +                      pipeconf |= PIPECONF_8BPC;
 +                      break;
 +              case 30:
 +                      pipeconf |= PIPECONF_10BPC;
 +                      break;
 +              default:
 +                      /* Case prevented by intel_choose_pipe_bpp_dither. */
 +                      BUG();
                }
        }
  
@@@ -4874,8 -4639,8 +4884,8 @@@ static int i9xx_crtc_mode_set(struct dr
        int refclk, num_connectors = 0;
        intel_clock_t clock, reduced_clock;
        u32 dspcntr;
 -      bool ok, has_reduced_clock = false, is_sdvo = false;
 -      bool is_lvds = false, is_tv = false;
 +      bool ok, has_reduced_clock = false;
 +      bool is_lvds = false;
        struct intel_encoder *encoder;
        const intel_limit_t *limit;
        int ret;
                case INTEL_OUTPUT_LVDS:
                        is_lvds = true;
                        break;
 -              case INTEL_OUTPUT_SDVO:
 -              case INTEL_OUTPUT_HDMI:
 -                      is_sdvo = true;
 -                      if (encoder->needs_tv_clock)
 -                              is_tv = true;
 -                      break;
 -              case INTEL_OUTPUT_TVOUT:
 -                      is_tv = true;
 -                      break;
                }
  
                num_connectors++;
                intel_crtc->config.dpll.p2 = clock.p2;
        }
  
 -      if (is_sdvo && is_tv)
 -              i9xx_adjust_sdvo_tv_clock(intel_crtc);
 -
        if (IS_GEN2(dev))
                i8xx_update_pll(intel_crtc, adjusted_mode,
                                has_reduced_clock ? &reduced_clock : NULL,
        else
                i9xx_update_pll(intel_crtc,
                                has_reduced_clock ? &reduced_clock : NULL,
 -                              num_connectors);
 +                                num_connectors);
  
        /* Set up the display plane register */
        dspcntr = DISPPLANE_GAMMA_ENABLE;
                        dspcntr |= DISPPLANE_SEL_PIPE_B;
        }
  
 -      DRM_DEBUG_KMS("Mode for pipe %c:\n", pipe == 0 ? 'A' : 'B');
 +      DRM_DEBUG_KMS("Mode for pipe %c:\n", pipe_name(pipe));
        drm_mode_debug_printmodeline(mode);
  
        intel_set_pipe_timings(intel_crtc, mode, adjusted_mode);
  
        i9xx_set_pipeconf(intel_crtc);
  
 -      intel_enable_pipe(dev_priv, pipe, false);
 -
 -      intel_wait_for_vblank(dev, pipe);
 -
        I915_WRITE(DSPCNTR(plane), dspcntr);
        POSTING_READ(DSPCNTR(plane));
  
        return ret;
  }
  
 +static void i9xx_get_pfit_config(struct intel_crtc *crtc,
 +                               struct intel_crtc_config *pipe_config)
 +{
 +      struct drm_device *dev = crtc->base.dev;
 +      struct drm_i915_private *dev_priv = dev->dev_private;
 +      uint32_t tmp;
 +
 +      tmp = I915_READ(PFIT_CONTROL);
 +
 +      if (INTEL_INFO(dev)->gen < 4) {
 +              if (crtc->pipe != PIPE_B)
 +                      return;
 +
 +              /* gen2/3 store dither state in pfit control, needs to match */
 +              pipe_config->gmch_pfit.control = tmp & PANEL_8TO6_DITHER_ENABLE;
 +      } else {
 +              if ((tmp & PFIT_PIPE_MASK) != (crtc->pipe << PFIT_PIPE_SHIFT))
 +                      return;
 +      }
 +
 +      if (!(tmp & PFIT_ENABLE))
 +              return;
 +
 +      pipe_config->gmch_pfit.control = I915_READ(PFIT_CONTROL);
 +      pipe_config->gmch_pfit.pgm_ratios = I915_READ(PFIT_PGM_RATIOS);
 +      if (INTEL_INFO(dev)->gen < 5)
 +              pipe_config->gmch_pfit.lvds_border_bits =
 +                      I915_READ(LVDS) & LVDS_BORDER_ENABLE;
 +}
 +
  static bool i9xx_get_pipe_config(struct intel_crtc *crtc,
                                 struct intel_crtc_config *pipe_config)
  {
        if (!(tmp & PIPECONF_ENABLE))
                return false;
  
 +      intel_get_pipe_timings(crtc, pipe_config);
 +
 +      i9xx_get_pfit_config(crtc, pipe_config);
 +
        return true;
  }
  
@@@ -5032,6 -4779,7 +5042,6 @@@ static void ironlake_init_pch_refclk(st
        u32 val, final;
        bool has_lvds = false;
        bool has_cpu_edp = false;
 -      bool has_pch_edp = false;
        bool has_panel = false;
        bool has_ck505 = false;
        bool can_ssc = false;
                        break;
                case INTEL_OUTPUT_EDP:
                        has_panel = true;
 -                      if (intel_encoder_is_pch_edp(&encoder->base))
 -                              has_pch_edp = true;
 -                      else
 +                      if (enc_to_dig_port(&encoder->base)->port == PORT_A)
                                has_cpu_edp = true;
                        break;
                }
        }
  
        if (HAS_PCH_IBX(dev)) {
 -              has_ck505 = dev_priv->display_clock_mode;
 +              has_ck505 = dev_priv->vbt.display_clock_mode;
                can_ssc = has_ck505;
        } else {
                has_ck505 = false;
                can_ssc = true;
        }
  
 -      DRM_DEBUG_KMS("has_panel %d has_lvds %d has_pch_edp %d has_cpu_edp %d has_ck505 %d\n",
 -                    has_panel, has_lvds, has_pch_edp, has_cpu_edp,
 -                    has_ck505);
 +      DRM_DEBUG_KMS("has_panel %d has_lvds %d has_ck505 %d\n",
 +                    has_panel, has_lvds, has_ck505);
  
        /* Ironlake: try to setup display ref clock before DPLL
         * enabling. This is only under driver's control after
@@@ -5351,6 -5102,7 +5361,6 @@@ static int ironlake_get_refclk(struct d
        struct drm_device *dev = crtc->dev;
        struct drm_i915_private *dev_priv = dev->dev_private;
        struct intel_encoder *encoder;
 -      struct intel_encoder *edp_encoder = NULL;
        int num_connectors = 0;
        bool is_lvds = false;
  
                case INTEL_OUTPUT_LVDS:
                        is_lvds = true;
                        break;
 -              case INTEL_OUTPUT_EDP:
 -                      edp_encoder = encoder;
 -                      break;
                }
                num_connectors++;
        }
  
        if (is_lvds && intel_panel_use_ssc(dev_priv) && num_connectors < 2) {
                DRM_DEBUG_KMS("using SSC reference clock of %d MHz\n",
 -                            dev_priv->lvds_ssc_freq);
 -              return dev_priv->lvds_ssc_freq * 1000;
 +                            dev_priv->vbt.lvds_ssc_freq);
 +              return dev_priv->vbt.lvds_ssc_freq * 1000;
        }
  
        return 120000;
  }
  
 -static void ironlake_set_pipeconf(struct drm_crtc *crtc,
 -                                struct drm_display_mode *adjusted_mode,
 -                                bool dither)
 +static void ironlake_set_pipeconf(struct drm_crtc *crtc)
  {
        struct drm_i915_private *dev_priv = crtc->dev->dev_private;
        struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
        }
  
        val &= ~(PIPECONF_DITHER_EN | PIPECONF_DITHER_TYPE_MASK);
 -      if (dither)
 +      if (intel_crtc->config.dither)
                val |= (PIPECONF_DITHER_EN | PIPECONF_DITHER_TYPE_SP);
  
        val &= ~PIPECONF_INTERLACE_MASK;
 -      if (adjusted_mode->flags & DRM_MODE_FLAG_INTERLACE)
 +      if (intel_crtc->config.adjusted_mode.flags & DRM_MODE_FLAG_INTERLACE)
                val |= PIPECONF_INTERLACED_ILK;
        else
                val |= PIPECONF_PROGRESSIVE;
@@@ -5483,7 -5240,9 +5493,7 @@@ static void intel_set_pipe_csc(struct d
        }
  }
  
 -static void haswell_set_pipeconf(struct drm_crtc *crtc,
 -                               struct drm_display_mode *adjusted_mode,
 -                               bool dither)
 +static void haswell_set_pipeconf(struct drm_crtc *crtc)
  {
        struct drm_i915_private *dev_priv = crtc->dev->dev_private;
        struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
        val = I915_READ(PIPECONF(cpu_transcoder));
  
        val &= ~(PIPECONF_DITHER_EN | PIPECONF_DITHER_TYPE_MASK);
 -      if (dither)
 +      if (intel_crtc->config.dither)
                val |= (PIPECONF_DITHER_EN | PIPECONF_DITHER_TYPE_SP);
  
        val &= ~PIPECONF_INTERLACE_MASK_HSW;
 -      if (adjusted_mode->flags & DRM_MODE_FLAG_INTERLACE)
 +      if (intel_crtc->config.adjusted_mode.flags & DRM_MODE_FLAG_INTERLACE)
                val |= PIPECONF_INTERLACED_ILK;
        else
                val |= PIPECONF_PROGRESSIVE;
@@@ -5517,13 -5276,22 +5527,13 @@@ static bool ironlake_compute_clocks(str
        struct intel_encoder *intel_encoder;
        int refclk;
        const intel_limit_t *limit;
 -      bool ret, is_sdvo = false, is_tv = false, is_lvds = false;
 +      bool ret, is_lvds = false;
  
        for_each_encoder_on_crtc(dev, crtc, intel_encoder) {
                switch (intel_encoder->type) {
                case INTEL_OUTPUT_LVDS:
                        is_lvds = true;
                        break;
 -              case INTEL_OUTPUT_SDVO:
 -              case INTEL_OUTPUT_HDMI:
 -                      is_sdvo = true;
 -                      if (intel_encoder->needs_tv_clock)
 -                              is_tv = true;
 -                      break;
 -              case INTEL_OUTPUT_TVOUT:
 -                      is_tv = true;
 -                      break;
                }
        }
  
                                                     reduced_clock);
        }
  
 -      if (is_sdvo && is_tv)
 -              i9xx_adjust_sdvo_tv_clock(to_intel_crtc(crtc));
 -
        return true;
  }
  
@@@ -5575,25 -5346,65 +5585,25 @@@ static void cpt_enable_fdi_bc_bifurcati
        POSTING_READ(SOUTH_CHICKEN1);
  }
  
 -static bool ironlake_check_fdi_lanes(struct intel_crtc *intel_crtc)
 +static void ivybridge_update_fdi_bc_bifurcation(struct intel_crtc *intel_crtc)
  {
        struct drm_device *dev = intel_crtc->base.dev;
        struct drm_i915_private *dev_priv = dev->dev_private;
 -      struct intel_crtc *pipe_B_crtc =
 -              to_intel_crtc(dev_priv->pipe_to_crtc_mapping[PIPE_B]);
 -
 -      DRM_DEBUG_KMS("checking fdi config on pipe %i, lanes %i\n",
 -                    intel_crtc->pipe, intel_crtc->fdi_lanes);
 -      if (intel_crtc->fdi_lanes > 4) {
 -              DRM_DEBUG_KMS("invalid fdi lane config on pipe %i: %i lanes\n",
 -                            intel_crtc->pipe, intel_crtc->fdi_lanes);
 -              /* Clamp lanes to avoid programming the hw with bogus values. */
 -              intel_crtc->fdi_lanes = 4;
 -
 -              return false;
 -      }
 -
 -      if (INTEL_INFO(dev)->num_pipes == 2)
 -              return true;
  
        switch (intel_crtc->pipe) {
        case PIPE_A:
 -              return true;
 +              break;
        case PIPE_B:
 -              if (dev_priv->pipe_to_crtc_mapping[PIPE_C]->enabled &&
 -                  intel_crtc->fdi_lanes > 2) {
 -                      DRM_DEBUG_KMS("invalid shared fdi lane config on pipe %i: %i lanes\n",
 -                                    intel_crtc->pipe, intel_crtc->fdi_lanes);
 -                      /* Clamp lanes to avoid programming the hw with bogus values. */
 -                      intel_crtc->fdi_lanes = 2;
 -
 -                      return false;
 -              }
 -
 -              if (intel_crtc->fdi_lanes > 2)
 +              if (intel_crtc->config.fdi_lanes > 2)
                        WARN_ON(I915_READ(SOUTH_CHICKEN1) & FDI_BC_BIFURCATION_SELECT);
                else
                        cpt_enable_fdi_bc_bifurcation(dev);
  
 -              return true;
 +              break;
        case PIPE_C:
 -              if (!pipe_B_crtc->base.enabled || pipe_B_crtc->fdi_lanes <= 2) {
 -                      if (intel_crtc->fdi_lanes > 2) {
 -                              DRM_DEBUG_KMS("invalid shared fdi lane config on pipe %i: %i lanes\n",
 -                                            intel_crtc->pipe, intel_crtc->fdi_lanes);
 -                              /* Clamp lanes to avoid programming the hw with bogus values. */
 -                              intel_crtc->fdi_lanes = 2;
 -
 -                              return false;
 -                      }
 -              } else {
 -                      DRM_DEBUG_KMS("fdi link B uses too many lanes to enable link C\n");
 -                      return false;
 -              }
 -
                cpt_enable_fdi_bc_bifurcation(dev);
  
 -              return true;
 +              break;
        default:
                BUG();
        }
@@@ -5610,13 -5421,78 +5620,13 @@@ int ironlake_get_lanes_required(int tar
        return bps / (link_bw * 8) + 1;
  }
  
 -void intel_pch_transcoder_set_m_n(struct intel_crtc *crtc,
 -                                struct intel_link_m_n *m_n)
 -{
 -      struct drm_device *dev = crtc->base.dev;
 -      struct drm_i915_private *dev_priv = dev->dev_private;
 -      int pipe = crtc->pipe;
 -
 -      I915_WRITE(TRANSDATA_M1(pipe), TU_SIZE(m_n->tu) | m_n->gmch_m);
 -      I915_WRITE(TRANSDATA_N1(pipe), m_n->gmch_n);
 -      I915_WRITE(TRANSDPLINK_M1(pipe), m_n->link_m);
 -      I915_WRITE(TRANSDPLINK_N1(pipe), m_n->link_n);
 -}
 -
 -void intel_cpu_transcoder_set_m_n(struct intel_crtc *crtc,
 -                                struct intel_link_m_n *m_n)
 -{
 -      struct drm_device *dev = crtc->base.dev;
 -      struct drm_i915_private *dev_priv = dev->dev_private;
 -      int pipe = crtc->pipe;
 -      enum transcoder transcoder = crtc->config.cpu_transcoder;
 -
 -      if (INTEL_INFO(dev)->gen >= 5) {
 -              I915_WRITE(PIPE_DATA_M1(transcoder), TU_SIZE(m_n->tu) | m_n->gmch_m);
 -              I915_WRITE(PIPE_DATA_N1(transcoder), m_n->gmch_n);
 -              I915_WRITE(PIPE_LINK_M1(transcoder), m_n->link_m);
 -              I915_WRITE(PIPE_LINK_N1(transcoder), m_n->link_n);
 -      } else {
 -              I915_WRITE(PIPE_GMCH_DATA_M(pipe), TU_SIZE(m_n->tu) | m_n->gmch_m);
 -              I915_WRITE(PIPE_GMCH_DATA_N(pipe), m_n->gmch_n);
 -              I915_WRITE(PIPE_DP_LINK_M(pipe), m_n->link_m);
 -              I915_WRITE(PIPE_DP_LINK_N(pipe), m_n->link_n);
 -      }
 -}
 -
 -static void ironlake_fdi_set_m_n(struct drm_crtc *crtc)
 +static bool ironlake_needs_fb_cb_tune(struct dpll *dpll, int factor)
  {
 -      struct drm_device *dev = crtc->dev;
 -      struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
 -      struct drm_display_mode *adjusted_mode =
 -              &intel_crtc->config.adjusted_mode;
 -      struct intel_link_m_n m_n = {0};
 -      int target_clock, lane, link_bw;
 -
 -      /* FDI is a binary signal running at ~2.7GHz, encoding
 -       * each output octet as 10 bits. The actual frequency
 -       * is stored as a divider into a 100MHz clock, and the
 -       * mode pixel clock is stored in units of 1KHz.
 -       * Hence the bw of each lane in terms of the mode signal
 -       * is:
 -       */
 -      link_bw = intel_fdi_link_freq(dev) * MHz(100)/KHz(1)/10;
 -
 -      if (intel_crtc->config.pixel_target_clock)
 -              target_clock = intel_crtc->config.pixel_target_clock;
 -      else
 -              target_clock = adjusted_mode->clock;
 -
 -      lane = ironlake_get_lanes_required(target_clock, link_bw,
 -                                         intel_crtc->config.pipe_bpp);
 -
 -      intel_crtc->fdi_lanes = lane;
 -
 -      if (intel_crtc->config.pixel_multiplier > 1)
 -              link_bw *= intel_crtc->config.pixel_multiplier;
 -      intel_link_compute_m_n(intel_crtc->config.pipe_bpp, lane, target_clock,
 -                             link_bw, &m_n);
 -
 -      intel_cpu_transcoder_set_m_n(intel_crtc, &m_n);
 +      return i9xx_dpll_compute_m(dpll) < factor * dpll->n;
  }
  
  static uint32_t ironlake_compute_dpll(struct intel_crtc *intel_crtc,
 -                                    intel_clock_t *clock, u32 *fp,
 +                                    u32 *fp,
                                      intel_clock_t *reduced_clock, u32 *fp2)
  {
        struct drm_crtc *crtc = &intel_crtc->base;
        struct intel_encoder *intel_encoder;
        uint32_t dpll;
        int factor, num_connectors = 0;
 -      bool is_lvds = false, is_sdvo = false, is_tv = false;
 +      bool is_lvds = false, is_sdvo = false;
  
        for_each_encoder_on_crtc(dev, crtc, intel_encoder) {
                switch (intel_encoder->type) {
                case INTEL_OUTPUT_SDVO:
                case INTEL_OUTPUT_HDMI:
                        is_sdvo = true;
 -                      if (intel_encoder->needs_tv_clock)
 -                              is_tv = true;
 -                      break;
 -              case INTEL_OUTPUT_TVOUT:
 -                      is_tv = true;
                        break;
                }
  
        factor = 21;
        if (is_lvds) {
                if ((intel_panel_use_ssc(dev_priv) &&
 -                   dev_priv->lvds_ssc_freq == 100) ||
 +                   dev_priv->vbt.lvds_ssc_freq == 100) ||
                    (HAS_PCH_IBX(dev) && intel_is_dual_link_lvds(dev)))
                        factor = 25;
 -      } else if (is_sdvo && is_tv)
 +      } else if (intel_crtc->config.sdvo_tv_clock)
                factor = 20;
  
 -      if (clock->m < factor * clock->n)
 +      if (ironlake_needs_fb_cb_tune(&intel_crtc->config.dpll, factor))
                *fp |= FP_CB_TUNE;
  
        if (fp2 && (reduced_clock->m < factor * reduced_clock->n))
                dpll |= DPLLB_MODE_LVDS;
        else
                dpll |= DPLLB_MODE_DAC_SERIAL;
 -      if (is_sdvo) {
 -              if (intel_crtc->config.pixel_multiplier > 1) {
 -                      dpll |= (intel_crtc->config.pixel_multiplier - 1)
 -                              << PLL_REF_SDVO_HDMI_MULTIPLIER_SHIFT;
 -              }
 -              dpll |= DPLL_DVO_HIGH_SPEED;
 +
 +      if (intel_crtc->config.pixel_multiplier > 1) {
 +              dpll |= (intel_crtc->config.pixel_multiplier - 1)
 +                      << PLL_REF_SDVO_HDMI_MULTIPLIER_SHIFT;
        }
 -      if (intel_crtc->config.has_dp_encoder &&
 -          intel_crtc->config.has_pch_encoder)
 +
 +      if (is_sdvo)
 +              dpll |= DPLL_DVO_HIGH_SPEED;
 +      if (intel_crtc->config.has_dp_encoder)
                dpll |= DPLL_DVO_HIGH_SPEED;
  
        /* compute bitmask from p1 value */
 -      dpll |= (1 << (clock->p1 - 1)) << DPLL_FPA01_P1_POST_DIV_SHIFT;
 +      dpll |= (1 << (intel_crtc->config.dpll.p1 - 1)) << DPLL_FPA01_P1_POST_DIV_SHIFT;
        /* also FPA1 */
 -      dpll |= (1 << (clock->p1 - 1)) << DPLL_FPA1_P1_POST_DIV_SHIFT;
 +      dpll |= (1 << (intel_crtc->config.dpll.p1 - 1)) << DPLL_FPA1_P1_POST_DIV_SHIFT;
  
 -      switch (clock->p2) {
 +      switch (intel_crtc->config.dpll.p2) {
        case 5:
                dpll |= DPLL_DAC_SERIAL_P2_CLOCK_DIV_5;
                break;
                break;
        }
  
 -      if (is_sdvo && is_tv)
 -              dpll |= PLL_REF_INPUT_TVCLKINBC;
 -      else if (is_tv)
 -              /* XXX: just matching BIOS for now */
 -              /*      dpll |= PLL_REF_INPUT_TVCLKINBC; */
 -              dpll |= 3;
 -      else if (is_lvds && intel_panel_use_ssc(dev_priv) && num_connectors < 2)
 +      if (is_lvds && intel_panel_use_ssc(dev_priv) && num_connectors < 2)
                dpll |= PLLB_REF_INPUT_SPREADSPECTRUMIN;
        else
                dpll |= PLL_REF_INPUT_DREFCLK;
@@@ -5716,11 -5603,12 +5726,11 @@@ static int ironlake_crtc_mode_set(struc
        int plane = intel_crtc->plane;
        int num_connectors = 0;
        intel_clock_t clock, reduced_clock;
 -      u32 dpll, fp = 0, fp2 = 0;
 +      u32 dpll = 0, fp = 0, fp2 = 0;
        bool ok, has_reduced_clock = false;
        bool is_lvds = false;
        struct intel_encoder *encoder;
        int ret;
 -      bool dither, fdi_config_ok;
  
        for_each_encoder_on_crtc(dev, crtc, encoder) {
                switch (encoder->type) {
        /* Ensure that the cursor is valid for the new mode before changing... */
        intel_crtc_update_cursor(crtc, true);
  
 -      /* determine panel color depth */
 -      dither = intel_crtc->config.dither;
 -      if (is_lvds && dev_priv->lvds_dither)
 -              dither = true;
 -
 -      fp = clock.n << 16 | clock.m1 << 8 | clock.m2;
 -      if (has_reduced_clock)
 -              fp2 = reduced_clock.n << 16 | reduced_clock.m1 << 8 |
 -                      reduced_clock.m2;
 -
 -      dpll = ironlake_compute_dpll(intel_crtc, &clock, &fp, &reduced_clock,
 -                                   has_reduced_clock ? &fp2 : NULL);
 -
 -      DRM_DEBUG_KMS("Mode for pipe %d:\n", pipe);
 +      DRM_DEBUG_KMS("Mode for pipe %c:\n", pipe_name(pipe));
        drm_mode_debug_printmodeline(mode);
  
        /* CPU eDP is the only output that doesn't need a PCH PLL of its own. */
        if (intel_crtc->config.has_pch_encoder) {
                struct intel_pch_pll *pll;
  
 +              fp = i9xx_dpll_compute_fp(&intel_crtc->config.dpll);
 +              if (has_reduced_clock)
 +                      fp2 = i9xx_dpll_compute_fp(&reduced_clock);
 +
 +              dpll = ironlake_compute_dpll(intel_crtc,
 +                                           &fp, &reduced_clock,
 +                                           has_reduced_clock ? &fp2 : NULL);
 +
                pll = intel_get_pch_pll(intel_crtc, dpll, fp);
                if (pll == NULL) {
 -                      DRM_DEBUG_DRIVER("failed to find PLL for pipe %d\n",
 -                                       pipe);
 +                      DRM_DEBUG_DRIVER("failed to find PLL for pipe %c\n",
 +                                       pipe_name(pipe));
                        return -EINVAL;
                }
        } else
  
        intel_set_pipe_timings(intel_crtc, mode, adjusted_mode);
  
 -      /* Note, this also computes intel_crtc->fdi_lanes which is used below in
 -       * ironlake_check_fdi_lanes. */
 -      intel_crtc->fdi_lanes = 0;
 -      if (intel_crtc->config.has_pch_encoder)
 -              ironlake_fdi_set_m_n(crtc);
 -
 -      fdi_config_ok = ironlake_check_fdi_lanes(intel_crtc);
 +      if (intel_crtc->config.has_pch_encoder) {
 +              intel_cpu_transcoder_set_m_n(intel_crtc,
 +                                           &intel_crtc->config.fdi_m_n);
 +      }
  
 -      ironlake_set_pipeconf(crtc, adjusted_mode, dither);
 +      if (IS_IVYBRIDGE(dev))
 +              ivybridge_update_fdi_bc_bifurcation(intel_crtc);
  
 -      intel_wait_for_vblank(dev, pipe);
 +      ironlake_set_pipeconf(crtc);
  
        /* Set up the display plane register */
        I915_WRITE(DSPCNTR(plane), DISPPLANE_GAMMA_ENABLE);
  
        intel_update_linetime_watermarks(dev, pipe, adjusted_mode);
  
 -      return fdi_config_ok ? ret : -EINVAL;
 +      return ret;
 +}
 +
 +static void ironlake_get_fdi_m_n_config(struct intel_crtc *crtc,
 +                                      struct intel_crtc_config *pipe_config)
 +{
 +      struct drm_device *dev = crtc->base.dev;
 +      struct drm_i915_private *dev_priv = dev->dev_private;
 +      enum transcoder transcoder = pipe_config->cpu_transcoder;
 +
 +      pipe_config->fdi_m_n.link_m = I915_READ(PIPE_LINK_M1(transcoder));
 +      pipe_config->fdi_m_n.link_n = I915_READ(PIPE_LINK_N1(transcoder));
 +      pipe_config->fdi_m_n.gmch_m = I915_READ(PIPE_DATA_M1(transcoder))
 +                                      & ~TU_SIZE_MASK;
 +      pipe_config->fdi_m_n.gmch_n = I915_READ(PIPE_DATA_N1(transcoder));
 +      pipe_config->fdi_m_n.tu = ((I915_READ(PIPE_DATA_M1(transcoder))
 +                                 & TU_SIZE_MASK) >> TU_SIZE_SHIFT) + 1;
 +}
 +
 +static void ironlake_get_pfit_config(struct intel_crtc *crtc,
 +                                   struct intel_crtc_config *pipe_config)
 +{
 +      struct drm_device *dev = crtc->base.dev;
 +      struct drm_i915_private *dev_priv = dev->dev_private;
 +      uint32_t tmp;
 +
 +      tmp = I915_READ(PF_CTL(crtc->pipe));
 +
 +      if (tmp & PF_ENABLE) {
 +              pipe_config->pch_pfit.pos = I915_READ(PF_WIN_POS(crtc->pipe));
 +              pipe_config->pch_pfit.size = I915_READ(PF_WIN_SZ(crtc->pipe));
 +      }
  }
  
  static bool ironlake_get_pipe_config(struct intel_crtc *crtc,
        if (!(tmp & PIPECONF_ENABLE))
                return false;
  
 -      if (I915_READ(TRANSCONF(crtc->pipe)) & TRANS_ENABLE)
 +      if (I915_READ(PCH_TRANSCONF(crtc->pipe)) & TRANS_ENABLE) {
                pipe_config->has_pch_encoder = true;
  
 +              tmp = I915_READ(FDI_RX_CTL(crtc->pipe));
 +              pipe_config->fdi_lanes = ((FDI_DP_PORT_WIDTH_MASK & tmp) >>
 +                                        FDI_DP_PORT_WIDTH_SHIFT) + 1;
 +
 +              ironlake_get_fdi_m_n_config(crtc, pipe_config);
 +      }
 +
 +      intel_get_pipe_timings(crtc, pipe_config);
 +
 +      ironlake_get_pfit_config(crtc, pipe_config);
 +
        return true;
  }
  
  static void haswell_modeset_global_resources(struct drm_device *dev)
  {
 -      struct drm_i915_private *dev_priv = dev->dev_private;
        bool enable = false;
        struct intel_crtc *crtc;
        struct intel_encoder *encoder;
                /* XXX: Should check for edp transcoder here, but thanks to init
                 * sequence that's not yet available. Just in case desktop eDP
                 * on PORT D is possible on haswell, too. */
 +              /* Even the eDP panel fitter is outside the always-on well. */
 +              if (crtc->config.pch_pfit.size && crtc->base.enabled)
 +                      enable = true;
        }
  
        list_for_each_entry(encoder, &dev->mode_config.encoder_list,
                        enable = true;
        }
  
 -      /* Even the eDP panel fitter is outside the always-on well. */
 -      if (dev_priv->pch_pf_size)
 -              enable = true;
 -
        intel_set_power_well(dev, enable);
  }
  
@@@ -5938,11 -5793,12 +5948,11 @@@ static int haswell_crtc_mode_set(struc
        bool is_cpu_edp = false;
        struct intel_encoder *encoder;
        int ret;
 -      bool dither;
  
        for_each_encoder_on_crtc(dev, crtc, encoder) {
                switch (encoder->type) {
                case INTEL_OUTPUT_EDP:
 -                      if (!intel_encoder_is_pch_edp(&encoder->base))
 +                      if (enc_to_dig_port(&encoder->base)->port == PORT_A)
                                is_cpu_edp = true;
                        break;
                }
        /* Ensure that the cursor is valid for the new mode before changing... */
        intel_crtc_update_cursor(crtc, true);
  
 -      /* determine panel color depth */
 -      dither = intel_crtc->config.dither;
 -
 -      DRM_DEBUG_KMS("Mode for pipe %d:\n", pipe);
 +      DRM_DEBUG_KMS("Mode for pipe %c:\n", pipe_name(pipe));
        drm_mode_debug_printmodeline(mode);
  
        if (intel_crtc->config.has_dp_encoder)
  
        intel_set_pipe_timings(intel_crtc, mode, adjusted_mode);
  
 -      if (intel_crtc->config.has_pch_encoder)
 -              ironlake_fdi_set_m_n(crtc);
 +      if (intel_crtc->config.has_pch_encoder) {
 +              intel_cpu_transcoder_set_m_n(intel_crtc,
 +                                           &intel_crtc->config.fdi_m_n);
 +      }
  
 -      haswell_set_pipeconf(crtc, adjusted_mode, dither);
 +      haswell_set_pipeconf(crtc);
  
        intel_set_pipe_csc(crtc);
  
@@@ -6010,40 -5867,22 +6020,40 @@@ static bool haswell_get_pipe_config(str
  {
        struct drm_device *dev = crtc->base.dev;
        struct drm_i915_private *dev_priv = dev->dev_private;
 +      enum transcoder cpu_transcoder = crtc->config.cpu_transcoder;
 +      enum intel_display_power_domain pfit_domain;
        uint32_t tmp;
  
 -      tmp = I915_READ(PIPECONF(crtc->config.cpu_transcoder));
 +      if (!intel_display_power_enabled(dev,
 +                      POWER_DOMAIN_TRANSCODER(cpu_transcoder)))
 +              return false;
 +
 +      tmp = I915_READ(PIPECONF(cpu_transcoder));
        if (!(tmp & PIPECONF_ENABLE))
                return false;
  
        /*
 -       * aswell has only FDI/PCH transcoder A. It is which is connected to
 +       * Haswell has only FDI/PCH transcoder A. It is which is connected to
         * DDI E. So just check whether this pipe is wired to DDI E and whether
         * the PCH transcoder is on.
         */
 -      tmp = I915_READ(TRANS_DDI_FUNC_CTL(crtc->pipe));
 +      tmp = I915_READ(TRANS_DDI_FUNC_CTL(cpu_transcoder));
        if ((tmp & TRANS_DDI_PORT_MASK) == TRANS_DDI_SELECT_PORT(PORT_E) &&
 -          I915_READ(TRANSCONF(PIPE_A)) & TRANS_ENABLE)
 +          I915_READ(LPT_TRANSCONF) & TRANS_ENABLE) {
                pipe_config->has_pch_encoder = true;
  
 +              tmp = I915_READ(FDI_RX_CTL(PIPE_A));
 +              pipe_config->fdi_lanes = ((FDI_DP_PORT_WIDTH_MASK & tmp) >>
 +                                        FDI_DP_PORT_WIDTH_SHIFT) + 1;
 +
 +              ironlake_get_fdi_m_n_config(crtc, pipe_config);
 +      }
 +
 +      intel_get_pipe_timings(crtc, pipe_config);
 +
 +      pfit_domain = POWER_DOMAIN_PIPE_PANEL_FITTER(crtc->pipe);
 +      if (intel_display_power_enabled(dev, pfit_domain))
 +              ironlake_get_pfit_config(crtc, pipe_config);
  
        return true;
  }
@@@ -6281,7 -6120,7 +6291,7 @@@ static void ironlake_write_eld(struct d
                eldv |= IBX_ELD_VALIDB << 4;
                eldv |= IBX_ELD_VALIDB << 8;
        } else {
 -              DRM_DEBUG_DRIVER("ELD on port %c\n", 'A' + i);
 +              DRM_DEBUG_DRIVER("ELD on port %c\n", port_name(i));
                eldv = IBX_ELD_VALIDB << ((i - 1) * 4);
        }
  
@@@ -7752,13 -7591,6 +7762,13 @@@ pipe_config_set_bpp(struct drm_crtc *cr
                                      bpp, connector->display_info.bpc*3);
                        pipe_config->pipe_bpp = connector->display_info.bpc*3;
                }
 +
 +              /* Clamp bpp to 8 on screens without EDID 1.4 */
 +              if (connector->display_info.bpc == 0 && bpp > 24) {
 +                      DRM_DEBUG_KMS("clamping display bpp (was %d) to default limit of 24\n",
 +                                    bpp);
 +                      pipe_config->pipe_bpp = 24;
 +              }
        }
  
        return bpp;
@@@ -7773,8 -7605,7 +7783,8 @@@ intel_modeset_pipe_config(struct drm_cr
        struct drm_encoder_helper_funcs *encoder_funcs;
        struct intel_encoder *encoder;
        struct intel_crtc_config *pipe_config;
 -      int plane_bpp;
 +      int plane_bpp, ret = -EINVAL;
 +      bool retry = true;
  
        pipe_config = kzalloc(sizeof(*pipe_config), GFP_KERNEL);
        if (!pipe_config)
        if (plane_bpp < 0)
                goto fail;
  
 +encoder_retry:
        /* Pass our mode to the connectors and the CRTC to give them a chance to
         * adjust it according to limitations or connector properties, and also
         * a chance to reject the mode entirely.
                }
        }
  
 -      if (!(intel_crtc_compute_config(crtc, pipe_config))) {
 +      ret = intel_crtc_compute_config(crtc, pipe_config);
 +      if (ret < 0) {
                DRM_DEBUG_KMS("CRTC fixup failed\n");
                goto fail;
        }
 +
 +      if (ret == RETRY) {
 +              if (WARN(!retry, "loop in pipe configuration computation\n")) {
 +                      ret = -EINVAL;
 +                      goto fail;
 +              }
 +
 +              DRM_DEBUG_KMS("CRTC bw constrained, retrying\n");
 +              retry = false;
 +              goto encoder_retry;
 +      }
 +
        DRM_DEBUG_KMS("[CRTC:%d]\n", crtc->base.id);
  
        pipe_config->dither = pipe_config->pipe_bpp != plane_bpp;
        return pipe_config;
  fail:
        kfree(pipe_config);
 -      return ERR_PTR(-EINVAL);
 +      return ERR_PTR(ret);
  }
  
  /* Computes which crtcs are affected and sets the relevant bits in the mask. For
@@@ -7938,9 -7755,6 +7948,9 @@@ intel_modeset_affected_pipes(struct drm
         */
        *modeset_pipes &= 1 << intel_crtc->pipe;
        *prepare_pipes &= 1 << intel_crtc->pipe;
 +
 +      DRM_DEBUG_KMS("set mode pipe masks: modeset: %x, prepare: %x, disable: %x\n",
 +                    *modeset_pipes, *prepare_pipes, *disable_pipes);
  }
  
  static bool intel_crtc_in_use(struct drm_crtc *crtc)
@@@ -8007,69 -7821,19 +8017,69 @@@ intel_modeset_update_state(struct drm_d
        list_for_each_entry((intel_crtc), \
                            &(dev)->mode_config.crtc_list, \
                            base.head) \
 -              if (mask & (1 <<(intel_crtc)->pipe)) \
 +              if (mask & (1 <<(intel_crtc)->pipe))
  
  static bool
 -intel_pipe_config_compare(struct intel_crtc_config *current_config,
 +intel_pipe_config_compare(struct drm_device *dev,
 +                        struct intel_crtc_config *current_config,
                          struct intel_crtc_config *pipe_config)
  {
 -      if (current_config->has_pch_encoder != pipe_config->has_pch_encoder) {
 -              DRM_ERROR("mismatch in has_pch_encoder "
 -                        "(expected %i, found %i)\n",
 -                        current_config->has_pch_encoder,
 -                        pipe_config->has_pch_encoder);
 -              return false;
 -      }
 +#define PIPE_CONF_CHECK_I(name)       \
 +      if (current_config->name != pipe_config->name) { \
 +              DRM_ERROR("mismatch in " #name " " \
 +                        "(expected %i, found %i)\n", \
 +                        current_config->name, \
 +                        pipe_config->name); \
 +              return false; \
 +      }
 +
 +#define PIPE_CONF_CHECK_FLAGS(name, mask)     \
 +      if ((current_config->name ^ pipe_config->name) & (mask)) { \
 +              DRM_ERROR("mismatch in " #name " " \
 +                        "(expected %i, found %i)\n", \
 +                        current_config->name & (mask), \
 +                        pipe_config->name & (mask)); \
 +              return false; \
 +      }
 +
 +      PIPE_CONF_CHECK_I(has_pch_encoder);
 +      PIPE_CONF_CHECK_I(fdi_lanes);
 +      PIPE_CONF_CHECK_I(fdi_m_n.gmch_m);
 +      PIPE_CONF_CHECK_I(fdi_m_n.gmch_n);
 +      PIPE_CONF_CHECK_I(fdi_m_n.link_m);
 +      PIPE_CONF_CHECK_I(fdi_m_n.link_n);
 +      PIPE_CONF_CHECK_I(fdi_m_n.tu);
 +
 +      PIPE_CONF_CHECK_I(adjusted_mode.crtc_hdisplay);
 +      PIPE_CONF_CHECK_I(adjusted_mode.crtc_htotal);
 +      PIPE_CONF_CHECK_I(adjusted_mode.crtc_hblank_start);
 +      PIPE_CONF_CHECK_I(adjusted_mode.crtc_hblank_end);
 +      PIPE_CONF_CHECK_I(adjusted_mode.crtc_hsync_start);
 +      PIPE_CONF_CHECK_I(adjusted_mode.crtc_hsync_end);
 +
 +      PIPE_CONF_CHECK_I(adjusted_mode.crtc_vdisplay);
 +      PIPE_CONF_CHECK_I(adjusted_mode.crtc_vtotal);
 +      PIPE_CONF_CHECK_I(adjusted_mode.crtc_vblank_start);
 +      PIPE_CONF_CHECK_I(adjusted_mode.crtc_vblank_end);
 +      PIPE_CONF_CHECK_I(adjusted_mode.crtc_vsync_start);
 +      PIPE_CONF_CHECK_I(adjusted_mode.crtc_vsync_end);
 +
 +      PIPE_CONF_CHECK_FLAGS(adjusted_mode.flags,
 +                            DRM_MODE_FLAG_INTERLACE);
 +
 +      PIPE_CONF_CHECK_I(requested_mode.hdisplay);
 +      PIPE_CONF_CHECK_I(requested_mode.vdisplay);
 +
 +      PIPE_CONF_CHECK_I(gmch_pfit.control);
 +      /* pfit ratios are autocomputed by the hw on gen4+ */
 +      if (INTEL_INFO(dev)->gen < 4)
 +              PIPE_CONF_CHECK_I(gmch_pfit.pgm_ratios);
 +      PIPE_CONF_CHECK_I(gmch_pfit.lvds_border_bits);
 +      PIPE_CONF_CHECK_I(pch_pfit.pos);
 +      PIPE_CONF_CHECK_I(pch_pfit.size);
 +
 +#undef PIPE_CONF_CHECK_I
 +#undef PIPE_CONF_CHECK_FLAGS
  
        return true;
  }
@@@ -8171,7 -7935,6 +8181,7 @@@ intel_modeset_check_state(struct drm_de
                     "(expected %i, found %i)\n", enabled, crtc->base.enabled);
  
                memset(&pipe_config, 0, sizeof(pipe_config));
 +              pipe_config.cpu_transcoder = crtc->config.cpu_transcoder;
                active = dev_priv->display.get_pipe_config(crtc,
                                                           &pipe_config);
                WARN(crtc->active != active,
                     "(expected %i, found %i)\n", crtc->active, active);
  
                WARN(active &&
 -                   !intel_pipe_config_compare(&crtc->config, &pipe_config),
 +                   !intel_pipe_config_compare(dev, &crtc->config, &pipe_config),
                     "pipe state doesn't match!\n");
        }
  }
@@@ -8222,6 -7985,9 +8232,6 @@@ static int __intel_set_mode(struct drm_
                }
        }
  
 -      DRM_DEBUG_KMS("set mode pipe masks: modeset: %x, prepare: %x, disable: %x\n",
 -                    modeset_pipes, prepare_pipes, disable_pipes);
 -
        for_each_intel_crtc_masked(dev, disable_pipes, intel_crtc)
                intel_crtc_disable(&intel_crtc->base);
  
@@@ -8812,8 -8578,10 +8822,8 @@@ static void intel_setup_outputs(struct 
                                intel_hdmi_init(dev, GEN4_HDMIB, PORT_B);
                        }
  
 -                      if (!found && SUPPORTS_INTEGRATED_DP(dev)) {
 -                              DRM_DEBUG_KMS("probing DP_B\n");
 +                      if (!found && SUPPORTS_INTEGRATED_DP(dev))
                                intel_dp_init(dev, DP_B, PORT_B);
 -                      }
                }
  
                /* Before G4X SDVOC doesn't have its own detect register */
                                DRM_DEBUG_KMS("probing HDMI on SDVOC\n");
                                intel_hdmi_init(dev, GEN4_HDMIC, PORT_C);
                        }
 -                      if (SUPPORTS_INTEGRATED_DP(dev)) {
 -                              DRM_DEBUG_KMS("probing DP_C\n");
 +                      if (SUPPORTS_INTEGRATED_DP(dev))
                                intel_dp_init(dev, DP_C, PORT_C);
 -                      }
                }
  
                if (SUPPORTS_INTEGRATED_DP(dev) &&
 -                  (I915_READ(DP_D) & DP_DETECTED)) {
 -                      DRM_DEBUG_KMS("probing DP_D\n");
 +                  (I915_READ(DP_D) & DP_DETECTED))
                        intel_dp_init(dev, DP_D, PORT_D);
 -              }
        } else if (IS_GEN2(dev))
                intel_dvo_init(dev);
  
@@@ -9004,13 -8776,6 +9014,13 @@@ static void intel_init_display(struct d
                dev_priv->display.crtc_disable = ironlake_crtc_disable;
                dev_priv->display.off = ironlake_crtc_off;
                dev_priv->display.update_plane = ironlake_update_plane;
 +      } else if (IS_VALLEYVIEW(dev)) {
 +              dev_priv->display.get_pipe_config = i9xx_get_pipe_config;
 +              dev_priv->display.crtc_mode_set = i9xx_crtc_mode_set;
 +              dev_priv->display.crtc_enable = valleyview_crtc_enable;
 +              dev_priv->display.crtc_disable = i9xx_crtc_disable;
 +              dev_priv->display.off = i9xx_crtc_off;
 +              dev_priv->display.update_plane = i9xx_update_plane;
        } else {
                dev_priv->display.get_pipe_config = i9xx_get_pipe_config;
                dev_priv->display.crtc_mode_set = i9xx_crtc_mode_set;
@@@ -9252,11 -9017,6 +9262,11 @@@ void intel_modeset_init_hw(struct drm_d
        mutex_unlock(&dev->struct_mutex);
  }
  
 +void intel_modeset_suspend_hw(struct drm_device *dev)
 +{
 +      intel_suspend_hw(dev);
 +}
 +
  void intel_modeset_init(struct drm_device *dev)
  {
        struct drm_i915_private *dev_priv = dev->dev_private;
                for (j = 0; j < dev_priv->num_plane; j++) {
                        ret = intel_plane_init(dev, i, j);
                        if (ret)
 -                              DRM_DEBUG_KMS("pipe %d plane %d init failed: %d\n",
 -                                            i, j, ret);
 +                              DRM_DEBUG_KMS("pipe %c sprite %c init failed: %d\n",
 +                                            pipe_name(i), sprite_name(i, j), ret);
                }
        }
  
@@@ -9660,23 -9420,12 +9670,23 @@@ void intel_modeset_cleanup(struct drm_d
        struct drm_crtc *crtc;
        struct intel_crtc *intel_crtc;
  
 +      /*
 +       * Interrupts and polling as the first thing to avoid creating havoc.
 +       * Too much stuff here (turning of rps, connectors, ...) would
 +       * experience fancy races otherwise.
 +       */
 +      drm_irq_uninstall(dev);
 +      cancel_work_sync(&dev_priv->hotplug_work);
 +      /*
 +       * Due to the hpd irq storm handling the hotplug work can re-arm the
 +       * poll handlers. Hence disable polling after hpd handling is shut down.
 +       */
        drm_kms_helper_poll_fini(dev);
 +
        mutex_lock(&dev->struct_mutex);
  
        intel_unregister_dsm_handler();
  
 -
        list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
                /* Skip inactive CRTCs */
                if (!crtc->fb)
  
        ironlake_teardown_rc6(dev);
  
 -      if (IS_VALLEYVIEW(dev))
 -              vlv_init_dpio(dev);
 -
        mutex_unlock(&dev->struct_mutex);
  
 -      /* Disable the irq before mode object teardown, for the irq might
 -       * enqueue unpin/hotplug work. */
 -      drm_irq_uninstall(dev);
 -      cancel_work_sync(&dev_priv->hotplug_work);
 -      cancel_work_sync(&dev_priv->rps.work);
 -
        /* flush any delayed tasks or pending work */
        flush_scheduled_work();
  
@@@ -9742,9 -9500,6 +9752,9 @@@ int intel_modeset_vga_set_state(struct 
  #include <linux/seq_file.h>
  
  struct intel_display_error_state {
 +
 +      u32 power_well_driver;
 +
        struct intel_cursor_error_state {
                u32 control;
                u32 position;
        } cursor[I915_MAX_PIPES];
  
        struct intel_pipe_error_state {
 +              enum transcoder cpu_transcoder;
                u32 conf;
                u32 source;
  
@@@ -9788,12 -9542,8 +9798,12 @@@ intel_display_capture_error_state(struc
        if (error == NULL)
                return NULL;
  
 +      if (HAS_POWER_WELL(dev))
 +              error->power_well_driver = I915_READ(HSW_PWR_WELL_DRIVER);
 +
        for_each_pipe(i) {
                cpu_transcoder = intel_pipe_to_cpu_transcoder(dev_priv, i);
 +              error->pipe[i].cpu_transcoder = cpu_transcoder;
  
                if (INTEL_INFO(dev)->gen <= 6 || IS_VALLEYVIEW(dev)) {
                        error->cursor[i].control = I915_READ(CURCNTR(i));
                error->pipe[i].vsync = I915_READ(VSYNC(cpu_transcoder));
        }
  
 +      /* In the code above we read the registers without checking if the power
 +       * well was on, so here we have to clear the FPGA_DBG_RM_NOCLAIM bit to
 +       * prevent the next I915_WRITE from detecting it and printing an error
 +       * message. */
 +      if (HAS_POWER_WELL(dev))
 +              I915_WRITE_NOTRACE(FPGA_DBG, FPGA_DBG_RM_NOCLAIM);
 +
        return error;
  }
  
@@@ -9846,13 -9589,8 +9856,13 @@@ intel_display_print_error_state(struct 
        int i;
  
        seq_printf(m, "Num Pipes: %d\n", INTEL_INFO(dev)->num_pipes);
 +      if (HAS_POWER_WELL(dev))
 +              seq_printf(m, "PWR_WELL_CTL2: %08x\n",
 +                         error->power_well_driver);
        for_each_pipe(i) {
                seq_printf(m, "Pipe [%d]:\n", i);
 +              seq_printf(m, "  CPU transcoder: %c\n",
 +                         transcoder_name(error->pipe[i].cpu_transcoder));
                seq_printf(m, "  CONF: %08x\n", error->pipe[i].conf);
                seq_printf(m, "  SRC: %08x\n", error->pipe[i].source);
                seq_printf(m, "  HTOTAL: %08x\n", error->pipe[i].htotal);
index 2bb4009b7a6024c67d6653ac9a7f5ce9cc8c50b9,3d704b706a8d42d974e70f4fa3e095fbcbcdb910..6ba9f09fe21af9ce41eddf8074517631f055a0aa
@@@ -52,11 -52,17 +52,11 @@@ static bool is_edp(struct intel_dp *int
        return intel_dig_port->base.type == INTEL_OUTPUT_EDP;
  }
  
 -/**
 - * is_pch_edp - is the port on the PCH and attached to an eDP panel?
 - * @intel_dp: DP struct
 - *
 - * Returns true if the given DP struct corresponds to a PCH DP port attached
 - * to an eDP panel, false otherwise.  Helpful for determining whether we
 - * may need FDI resources for a given DP output or not.
 - */
 -static bool is_pch_edp(struct intel_dp *intel_dp)
 +static struct drm_device *intel_dp_to_dev(struct intel_dp *intel_dp)
  {
 -      return intel_dp->is_pch_edp;
 +      struct intel_digital_port *intel_dig_port = dp_to_dig_port(intel_dp);
 +
 +      return intel_dig_port->base.base.dev;
  }
  
  /**
   */
  static bool is_cpu_edp(struct intel_dp *intel_dp)
  {
 -      return is_edp(intel_dp) && !is_pch_edp(intel_dp);
 -}
 -
 -static struct drm_device *intel_dp_to_dev(struct intel_dp *intel_dp)
 -{
 +      struct drm_device *dev = intel_dp_to_dev(intel_dp);
        struct intel_digital_port *intel_dig_port = dp_to_dig_port(intel_dp);
 +      enum port port = intel_dig_port->port;
  
 -      return intel_dig_port->base.base.dev;
 +      return is_edp(intel_dp) &&
 +              (port == PORT_A || (port == PORT_C && IS_VALLEYVIEW(dev)));
  }
  
  static struct intel_dp *intel_attached_dp(struct drm_connector *connector)
        return enc_to_intel_dp(&intel_attached_encoder(connector)->base);
  }
  
 -/**
 - * intel_encoder_is_pch_edp - is the given encoder a PCH attached eDP?
 - * @encoder: DRM encoder
 - *
 - * Return true if @encoder corresponds to a PCH attached eDP panel.  Needed
 - * by intel_display.c.
 - */
 -bool intel_encoder_is_pch_edp(struct drm_encoder *encoder)
 -{
 -      struct intel_dp *intel_dp;
 -
 -      if (!encoder)
 -              return false;
 -
 -      intel_dp = enc_to_intel_dp(encoder);
 -
 -      return is_pch_edp(intel_dp);
 -}
 -
  static void intel_dp_link_down(struct intel_dp *intel_dp);
  
  static int
@@@ -633,49 -660,6 +633,49 @@@ intel_dp_i2c_init(struct intel_dp *inte
        return ret;
  }
  
 +static void
 +intel_dp_set_clock(struct intel_encoder *encoder,
 +                 struct intel_crtc_config *pipe_config, int link_bw)
 +{
 +      struct drm_device *dev = encoder->base.dev;
 +
 +      if (IS_G4X(dev)) {
 +              if (link_bw == DP_LINK_BW_1_62) {
 +                      pipe_config->dpll.p1 = 2;
 +                      pipe_config->dpll.p2 = 10;
 +                      pipe_config->dpll.n = 2;
 +                      pipe_config->dpll.m1 = 23;
 +                      pipe_config->dpll.m2 = 8;
 +              } else {
 +                      pipe_config->dpll.p1 = 1;
 +                      pipe_config->dpll.p2 = 10;
 +                      pipe_config->dpll.n = 1;
 +                      pipe_config->dpll.m1 = 14;
 +                      pipe_config->dpll.m2 = 2;
 +              }
 +              pipe_config->clock_set = true;
 +      } else if (IS_HASWELL(dev)) {
 +              /* Haswell has special-purpose DP DDI clocks. */
 +      } else if (HAS_PCH_SPLIT(dev)) {
 +              if (link_bw == DP_LINK_BW_1_62) {
 +                      pipe_config->dpll.n = 1;
 +                      pipe_config->dpll.p1 = 2;
 +                      pipe_config->dpll.p2 = 10;
 +                      pipe_config->dpll.m1 = 12;
 +                      pipe_config->dpll.m2 = 9;
 +              } else {
 +                      pipe_config->dpll.n = 2;
 +                      pipe_config->dpll.p1 = 1;
 +                      pipe_config->dpll.p2 = 10;
 +                      pipe_config->dpll.m1 = 14;
 +                      pipe_config->dpll.m2 = 8;
 +              }
 +              pipe_config->clock_set = true;
 +      } else if (IS_VALLEYVIEW(dev)) {
 +              /* FIXME: Need to figure out optimized DP clocks for vlv. */
 +      }
 +}
 +
  bool
  intel_dp_compute_config(struct intel_encoder *encoder,
                        struct intel_crtc_config *pipe_config)
        struct drm_device *dev = encoder->base.dev;
        struct drm_i915_private *dev_priv = dev->dev_private;
        struct drm_display_mode *adjusted_mode = &pipe_config->adjusted_mode;
 -      struct drm_display_mode *mode = &pipe_config->requested_mode;
        struct intel_dp *intel_dp = enc_to_intel_dp(&encoder->base);
 +      struct intel_crtc *intel_crtc = encoder->new_crtc;
        struct intel_connector *intel_connector = intel_dp->attached_connector;
        int lane_count, clock;
        int max_lane_count = drm_dp_max_lane_count(intel_dp->dpcd);
        if (is_edp(intel_dp) && intel_connector->panel.fixed_mode) {
                intel_fixed_panel_mode(intel_connector->panel.fixed_mode,
                                       adjusted_mode);
 -              intel_pch_panel_fitting(dev,
 -                                      intel_connector->panel.fitting_mode,
 -                                      mode, adjusted_mode);
 +              if (!HAS_PCH_SPLIT(dev))
 +                      intel_gmch_panel_fitting(intel_crtc, pipe_config,
 +                                               intel_connector->panel.fitting_mode);
 +              else
 +                      intel_pch_panel_fitting(intel_crtc, pipe_config,
 +                                              intel_connector->panel.fitting_mode);
        }
        /* We need to take the panel's fixed mode into account. */
        target_clock = adjusted_mode->clock;
  
        /* Walk through all bpp values. Luckily they're all nicely spaced with 2
         * bpc in between. */
-       bpp = pipe_config->pipe_bpp;
-       /*
-        * eDP panels are really fickle, try to enfore the bpp the firmware
-        * recomments. This means we'll up-dither 16bpp framebuffers on
-        * high-depth panels.
-        */
-       if (is_edp(intel_dp) && dev_priv->vbt.edp_bpp) {
-               DRM_DEBUG_KMS("forcing bpp for eDP panel to BIOS-provided %i\n",
-                             dev_priv->vbt.edp_bpp);
-               bpp = dev_priv->vbt.edp_bpp;
-       }
+       bpp = min_t(int, 8*3, pipe_config->pipe_bpp);
 -      if (is_edp(intel_dp) && dev_priv->edp.bpp)
 -              bpp = min_t(int, bpp, dev_priv->edp.bpp);
++      if (is_edp(intel_dp) && dev_priv->vbt.edp_bpp)
++              bpp = min_t(int, bpp, dev_priv->vbt.edp_bpp);
  
        for (; bpp >= 6*3; bpp -= 2*3) {
                mode_rate = intel_dp_link_required(target_clock, bpp);
@@@ -770,6 -742,7 +761,7 @@@ found
        intel_dp->link_bw = bws[clock];
        intel_dp->lane_count = lane_count;
        adjusted_mode->clock = drm_dp_bw_code_to_link_rate(intel_dp->link_bw);
+       pipe_config->pipe_bpp = bpp;
        pipe_config->pixel_target_clock = target_clock;
  
        DRM_DEBUG_KMS("DP link bw %02x lane count %d clock %d bpp %d\n",
                               target_clock, adjusted_mode->clock,
                               &pipe_config->dp_m_n);
  
-       pipe_config->pipe_bpp = bpp;
 +      intel_dp_set_clock(encoder, pipe_config, intel_dp->link_bw);
 +
        return true;
  }
  
@@@ -864,8 -833,18 +854,8 @@@ intel_dp_mode_set(struct drm_encoder *e
  
        /* Handle DP bits in common between all three register formats */
        intel_dp->DP |= DP_VOLTAGE_0_4 | DP_PRE_EMPHASIS_0;
 +      intel_dp->DP |= DP_PORT_WIDTH(intel_dp->lane_count);
  
 -      switch (intel_dp->lane_count) {
 -      case 1:
 -              intel_dp->DP |= DP_PORT_WIDTH_1;
 -              break;
 -      case 2:
 -              intel_dp->DP |= DP_PORT_WIDTH_2;
 -              break;
 -      case 4:
 -              intel_dp->DP |= DP_PORT_WIDTH_4;
 -              break;
 -      }
        if (intel_dp->has_audio) {
                DRM_DEBUG_DRIVER("Enabling DP audio on pipe %c\n",
                                 pipe_name(intel_crtc->pipe));
@@@ -1400,78 -1379,17 +1390,79 @@@ static void intel_enable_dp(struct inte
        ironlake_edp_panel_on(intel_dp);
        ironlake_edp_panel_vdd_off(intel_dp, true);
        intel_dp_complete_link_train(intel_dp);
+       intel_dp_stop_link_train(intel_dp);
        ironlake_edp_backlight_on(intel_dp);
 +
 +      if (IS_VALLEYVIEW(dev)) {
 +              struct intel_digital_port *dport =
 +                      enc_to_dig_port(&encoder->base);
 +              int channel = vlv_dport_to_channel(dport);
 +
 +              vlv_wait_port_ready(dev_priv, channel);
 +      }
  }
  
  static void intel_pre_enable_dp(struct intel_encoder *encoder)
  {
        struct intel_dp *intel_dp = enc_to_intel_dp(&encoder->base);
        struct drm_device *dev = encoder->base.dev;
 +      struct drm_i915_private *dev_priv = dev->dev_private;
  
        if (is_cpu_edp(intel_dp) && !IS_VALLEYVIEW(dev))
                ironlake_edp_pll_on(intel_dp);
 +
 +      if (IS_VALLEYVIEW(dev)) {
 +              struct intel_digital_port *dport = enc_to_dig_port(&encoder->base);
 +              struct intel_crtc *intel_crtc =
 +                      to_intel_crtc(encoder->base.crtc);
 +              int port = vlv_dport_to_channel(dport);
 +              int pipe = intel_crtc->pipe;
 +              u32 val;
 +
 +              WARN_ON(!mutex_is_locked(&dev_priv->dpio_lock));
 +
 +              val = intel_dpio_read(dev_priv, DPIO_DATA_LANE_A(port));
 +              val = 0;
 +              if (pipe)
 +                      val |= (1<<21);
 +              else
 +                      val &= ~(1<<21);
 +              val |= 0x001000c4;
 +              intel_dpio_write(dev_priv, DPIO_DATA_CHANNEL(port), val);
 +
 +              intel_dpio_write(dev_priv, DPIO_PCS_CLOCKBUF0(port),
 +                               0x00760018);
 +              intel_dpio_write(dev_priv, DPIO_PCS_CLOCKBUF8(port),
 +                               0x00400888);
 +      }
 +}
 +
 +static void intel_dp_pre_pll_enable(struct intel_encoder *encoder)
 +{
 +      struct intel_digital_port *dport = enc_to_dig_port(&encoder->base);
 +      struct drm_device *dev = encoder->base.dev;
 +      struct drm_i915_private *dev_priv = dev->dev_private;
 +      int port = vlv_dport_to_channel(dport);
 +
 +      if (!IS_VALLEYVIEW(dev))
 +              return;
 +
 +      WARN_ON(!mutex_is_locked(&dev_priv->dpio_lock));
 +
 +      /* Program Tx lane resets to default */
 +      intel_dpio_write(dev_priv, DPIO_PCS_TX(port),
 +                       DPIO_PCS_TX_LANE2_RESET |
 +                       DPIO_PCS_TX_LANE1_RESET);
 +      intel_dpio_write(dev_priv, DPIO_PCS_CLK(port),
 +                       DPIO_PCS_CLK_CRI_RXEB_EIOS_EN |
 +                       DPIO_PCS_CLK_CRI_RXDIGFILTSG_EN |
 +                       (1<<DPIO_PCS_CLK_DATAWIDTH_SHIFT) |
 +                               DPIO_PCS_CLK_SOFT_RESET);
 +
 +      /* Fix up inter-pair skew failure */
 +      intel_dpio_write(dev_priv, DPIO_PCS_STAGGER1(port), 0x00750f00);
 +      intel_dpio_write(dev_priv, DPIO_TX_CTL(port), 0x00001500);
 +      intel_dpio_write(dev_priv, DPIO_TX_LANE(port), 0x40400000);
  }
  
  /*
@@@ -1534,9 -1452,7 +1525,9 @@@ intel_dp_voltage_max(struct intel_dp *i
  {
        struct drm_device *dev = intel_dp_to_dev(intel_dp);
  
 -      if (IS_GEN7(dev) && is_cpu_edp(intel_dp))
 +      if (IS_VALLEYVIEW(dev))
 +              return DP_TRAIN_VOLTAGE_SWING_1200;
 +      else if (IS_GEN7(dev) && is_cpu_edp(intel_dp))
                return DP_TRAIN_VOLTAGE_SWING_800;
        else if (HAS_PCH_CPT(dev) && !is_cpu_edp(intel_dp))
                return DP_TRAIN_VOLTAGE_SWING_1200;
@@@ -1561,19 -1477,7 +1552,19 @@@ intel_dp_pre_emphasis_max(struct intel_
                default:
                        return DP_TRAIN_PRE_EMPHASIS_0;
                }
 -      } else if (IS_GEN7(dev) && is_cpu_edp(intel_dp) && !IS_VALLEYVIEW(dev)) {
 +      } else if (IS_VALLEYVIEW(dev)) {
 +              switch (voltage_swing & DP_TRAIN_VOLTAGE_SWING_MASK) {
 +              case DP_TRAIN_VOLTAGE_SWING_400:
 +                      return DP_TRAIN_PRE_EMPHASIS_9_5;
 +              case DP_TRAIN_VOLTAGE_SWING_600:
 +                      return DP_TRAIN_PRE_EMPHASIS_6;
 +              case DP_TRAIN_VOLTAGE_SWING_800:
 +                      return DP_TRAIN_PRE_EMPHASIS_3_5;
 +              case DP_TRAIN_VOLTAGE_SWING_1200:
 +              default:
 +                      return DP_TRAIN_PRE_EMPHASIS_0;
 +              }
 +      } else if (IS_GEN7(dev) && is_cpu_edp(intel_dp)) {
                switch (voltage_swing & DP_TRAIN_VOLTAGE_SWING_MASK) {
                case DP_TRAIN_VOLTAGE_SWING_400:
                        return DP_TRAIN_PRE_EMPHASIS_6;
        }
  }
  
 +static uint32_t intel_vlv_signal_levels(struct intel_dp *intel_dp)
 +{
 +      struct drm_device *dev = intel_dp_to_dev(intel_dp);
 +      struct drm_i915_private *dev_priv = dev->dev_private;
 +      struct intel_digital_port *dport = dp_to_dig_port(intel_dp);
 +      unsigned long demph_reg_value, preemph_reg_value,
 +              uniqtranscale_reg_value;
 +      uint8_t train_set = intel_dp->train_set[0];
 +      int port = vlv_dport_to_channel(dport);
 +
 +      WARN_ON(!mutex_is_locked(&dev_priv->dpio_lock));
 +
 +      switch (train_set & DP_TRAIN_PRE_EMPHASIS_MASK) {
 +      case DP_TRAIN_PRE_EMPHASIS_0:
 +              preemph_reg_value = 0x0004000;
 +              switch (train_set & DP_TRAIN_VOLTAGE_SWING_MASK) {
 +              case DP_TRAIN_VOLTAGE_SWING_400:
 +                      demph_reg_value = 0x2B405555;
 +                      uniqtranscale_reg_value = 0x552AB83A;
 +                      break;
 +              case DP_TRAIN_VOLTAGE_SWING_600:
 +                      demph_reg_value = 0x2B404040;
 +                      uniqtranscale_reg_value = 0x5548B83A;
 +                      break;
 +              case DP_TRAIN_VOLTAGE_SWING_800:
 +                      demph_reg_value = 0x2B245555;
 +                      uniqtranscale_reg_value = 0x5560B83A;
 +                      break;
 +              case DP_TRAIN_VOLTAGE_SWING_1200:
 +                      demph_reg_value = 0x2B405555;
 +                      uniqtranscale_reg_value = 0x5598DA3A;
 +                      break;
 +              default:
 +                      return 0;
 +              }
 +              break;
 +      case DP_TRAIN_PRE_EMPHASIS_3_5:
 +              preemph_reg_value = 0x0002000;
 +              switch (train_set & DP_TRAIN_VOLTAGE_SWING_MASK) {
 +              case DP_TRAIN_VOLTAGE_SWING_400:
 +                      demph_reg_value = 0x2B404040;
 +                      uniqtranscale_reg_value = 0x5552B83A;
 +                      break;
 +              case DP_TRAIN_VOLTAGE_SWING_600:
 +                      demph_reg_value = 0x2B404848;
 +                      uniqtranscale_reg_value = 0x5580B83A;
 +                      break;
 +              case DP_TRAIN_VOLTAGE_SWING_800:
 +                      demph_reg_value = 0x2B404040;
 +                      uniqtranscale_reg_value = 0x55ADDA3A;
 +                      break;
 +              default:
 +                      return 0;
 +              }
 +              break;
 +      case DP_TRAIN_PRE_EMPHASIS_6:
 +              preemph_reg_value = 0x0000000;
 +              switch (train_set & DP_TRAIN_VOLTAGE_SWING_MASK) {
 +              case DP_TRAIN_VOLTAGE_SWING_400:
 +                      demph_reg_value = 0x2B305555;
 +                      uniqtranscale_reg_value = 0x5570B83A;
 +                      break;
 +              case DP_TRAIN_VOLTAGE_SWING_600:
 +                      demph_reg_value = 0x2B2B4040;
 +                      uniqtranscale_reg_value = 0x55ADDA3A;
 +                      break;
 +              default:
 +                      return 0;
 +              }
 +              break;
 +      case DP_TRAIN_PRE_EMPHASIS_9_5:
 +              preemph_reg_value = 0x0006000;
 +              switch (train_set & DP_TRAIN_VOLTAGE_SWING_MASK) {
 +              case DP_TRAIN_VOLTAGE_SWING_400:
 +                      demph_reg_value = 0x1B405555;
 +                      uniqtranscale_reg_value = 0x55ADDA3A;
 +                      break;
 +              default:
 +                      return 0;
 +              }
 +              break;
 +      default:
 +              return 0;
 +      }
 +
 +      intel_dpio_write(dev_priv, DPIO_TX_OCALINIT(port), 0x00000000);
 +      intel_dpio_write(dev_priv, DPIO_TX_SWING_CTL4(port), demph_reg_value);
 +      intel_dpio_write(dev_priv, DPIO_TX_SWING_CTL2(port),
 +                       uniqtranscale_reg_value);
 +      intel_dpio_write(dev_priv, DPIO_TX_SWING_CTL3(port), 0x0C782040);
 +      intel_dpio_write(dev_priv, DPIO_PCS_STAGGER0(port), 0x00030000);
 +      intel_dpio_write(dev_priv, DPIO_PCS_CTL_OVER1(port), preemph_reg_value);
 +      intel_dpio_write(dev_priv, DPIO_TX_OCALINIT(port), 0x80000000);
 +
 +      return 0;
 +}
 +
  static void
  intel_get_adjust_train(struct intel_dp *intel_dp, uint8_t link_status[DP_LINK_STATUS_SIZE])
  {
@@@ -1869,10 -1676,7 +1860,10 @@@ intel_dp_set_signal_levels(struct intel
        if (HAS_DDI(dev)) {
                signal_levels = intel_hsw_signal_levels(train_set);
                mask = DDI_BUF_EMP_MASK;
 -      } else if (IS_GEN7(dev) && is_cpu_edp(intel_dp) && !IS_VALLEYVIEW(dev)) {
 +      } else if (IS_VALLEYVIEW(dev)) {
 +              signal_levels = intel_vlv_signal_levels(intel_dp);
 +              mask = 0;
 +      } else if (IS_GEN7(dev) && is_cpu_edp(intel_dp)) {
                signal_levels = intel_gen7_edp_signal_levels(train_set);
                mask = EDP_LINK_TRAIN_VOL_EMP_MASK_IVB;
        } else if (IS_GEN6(dev) && is_cpu_edp(intel_dp)) {
@@@ -1898,10 -1702,9 +1889,9 @@@ intel_dp_set_link_train(struct intel_d
        struct drm_i915_private *dev_priv = dev->dev_private;
        enum port port = intel_dig_port->port;
        int ret;
-       uint32_t temp;
  
        if (HAS_DDI(dev)) {
-               temp = I915_READ(DP_TP_CTL(port));
+               uint32_t temp = I915_READ(DP_TP_CTL(port));
  
                if (dp_train_pat & DP_LINK_SCRAMBLING_DISABLE)
                        temp |= DP_TP_CTL_SCRAMBLE_DISABLE;
                temp &= ~DP_TP_CTL_LINK_TRAIN_MASK;
                switch (dp_train_pat & DP_TRAINING_PATTERN_MASK) {
                case DP_TRAINING_PATTERN_DISABLE:
-                       if (port != PORT_A) {
-                               temp |= DP_TP_CTL_LINK_TRAIN_IDLE;
-                               I915_WRITE(DP_TP_CTL(port), temp);
-                               if (wait_for((I915_READ(DP_TP_STATUS(port)) &
-                                             DP_TP_STATUS_IDLE_DONE), 1))
-                                       DRM_ERROR("Timed out waiting for DP idle patterns\n");
-                               temp &= ~DP_TP_CTL_LINK_TRAIN_MASK;
-                       }
                        temp |= DP_TP_CTL_LINK_TRAIN_NORMAL;
  
                        break;
        return true;
  }
  
+ static void intel_dp_set_idle_link_train(struct intel_dp *intel_dp)
+ {
+       struct intel_digital_port *intel_dig_port = dp_to_dig_port(intel_dp);
+       struct drm_device *dev = intel_dig_port->base.base.dev;
+       struct drm_i915_private *dev_priv = dev->dev_private;
+       enum port port = intel_dig_port->port;
+       uint32_t val;
+       if (!HAS_DDI(dev))
+               return;
+       val = I915_READ(DP_TP_CTL(port));
+       val &= ~DP_TP_CTL_LINK_TRAIN_MASK;
+       val |= DP_TP_CTL_LINK_TRAIN_IDLE;
+       I915_WRITE(DP_TP_CTL(port), val);
+       /*
+        * On PORT_A we can have only eDP in SST mode. There the only reason
+        * we need to set idle transmission mode is to work around a HW issue
+        * where we enable the pipe while not in idle link-training mode.
+        * In this case there is requirement to wait for a minimum number of
+        * idle patterns to be sent.
+        */
+       if (port == PORT_A)
+               return;
+       if (wait_for((I915_READ(DP_TP_STATUS(port)) & DP_TP_STATUS_IDLE_DONE),
+                    1))
+               DRM_ERROR("Timed out waiting for DP idle patterns\n");
+ }
  /* Enable corresponding port and start training pattern 1 */
  void
  intel_dp_start_link_train(struct intel_dp *intel_dp)
@@@ -2140,10 -1962,19 +2149,19 @@@ intel_dp_complete_link_train(struct int
                ++tries;
        }
  
+       intel_dp_set_idle_link_train(intel_dp);
+       intel_dp->DP = DP;
        if (channel_eq)
-               DRM_DEBUG_KMS("Channel EQ done. DP Training successfull\n");
+               DRM_DEBUG_KMS("Channel EQ done. DP Training successful\n");
  
-       intel_dp_set_link_train(intel_dp, DP, DP_TRAINING_PATTERN_DISABLE);
+ }
+ void intel_dp_stop_link_train(struct intel_dp *intel_dp)
+ {
+       intel_dp_set_link_train(intel_dp, intel_dp->DP,
+                               DP_TRAINING_PATTERN_DISABLE);
  }
  
  static void
@@@ -2351,6 -2182,7 +2369,7 @@@ intel_dp_check_link_status(struct intel
                              drm_get_encoder_name(&intel_encoder->base));
                intel_dp_start_link_train(intel_dp);
                intel_dp_complete_link_train(intel_dp);
+               intel_dp_stop_link_train(intel_dp);
        }
  }
  
@@@ -2615,6 -2447,9 +2634,9 @@@ intel_dp_set_property(struct drm_connec
        }
  
        if (property == dev_priv->broadcast_rgb_property) {
+               bool old_auto = intel_dp->color_range_auto;
+               uint32_t old_range = intel_dp->color_range;
                switch (val) {
                case INTEL_BROADCAST_RGB_AUTO:
                        intel_dp->color_range_auto = true;
                default:
                        return -EINVAL;
                }
+               if (old_auto == intel_dp->color_range_auto &&
+                   old_range == intel_dp->color_range)
+                       return 0;
                goto done;
        }
  
@@@ -2679,12 -2519,15 +2706,15 @@@ void intel_dp_encoder_destroy(struct dr
  {
        struct intel_digital_port *intel_dig_port = enc_to_dig_port(encoder);
        struct intel_dp *intel_dp = &intel_dig_port->dp;
+       struct drm_device *dev = intel_dp_to_dev(intel_dp);
  
        i2c_del_adapter(&intel_dp->adapter);
        drm_encoder_cleanup(encoder);
        if (is_edp(intel_dp)) {
                cancel_delayed_work_sync(&intel_dp->panel_vdd_work);
+               mutex_lock(&dev->mode_config.mutex);
                ironlake_panel_vdd_off_sync(intel_dp);
+               mutex_unlock(&dev->mode_config.mutex);
        }
        kfree(intel_dig_port);
  }
@@@ -2745,11 -2588,11 +2775,11 @@@ bool intel_dpd_is_edp(struct drm_devic
        struct child_device_config *p_child;
        int i;
  
 -      if (!dev_priv->child_dev_num)
 +      if (!dev_priv->vbt.child_dev_num)
                return false;
  
 -      for (i = 0; i < dev_priv->child_dev_num; i++) {
 -              p_child = dev_priv->child_dev + i;
 +      for (i = 0; i < dev_priv->vbt.child_dev_num; i++) {
 +              p_child = dev_priv->vbt.child_dev + i;
  
                if (p_child->dvo_port == PORT_IDPD &&
                    p_child->device_type == DEVICE_TYPE_eDP)
@@@ -2827,7 -2670,7 +2857,7 @@@ intel_dp_init_panel_power_sequencer(str
        DRM_DEBUG_KMS("cur t1_t3 %d t8 %d t9 %d t10 %d t11_t12 %d\n",
                      cur.t1_t3, cur.t8, cur.t9, cur.t10, cur.t11_t12);
  
 -      vbt = dev_priv->edp.pps;
 +      vbt = dev_priv->vbt.edp_pps;
  
        /* Upper limits from eDP 1.3 spec. Note that we use the clunky units of
         * our hw here, which are all in 100usec. */
@@@ -2949,39 -2792,28 +2979,39 @@@ intel_dp_init_connector(struct intel_di
        intel_dp->DP = I915_READ(intel_dp->output_reg);
        intel_dp->attached_connector = intel_connector;
  
 -      if (HAS_PCH_SPLIT(dev) && port == PORT_D)
 -              if (intel_dpd_is_edp(dev))
 -                      intel_dp->is_pch_edp = true;
 -
 +      type = DRM_MODE_CONNECTOR_DisplayPort;
        /*
         * FIXME : We need to initialize built-in panels before external panels.
         * For X0, DP_C is fixed as eDP. Revisit this as part of VLV eDP cleanup
         */
 -      if (IS_VALLEYVIEW(dev) && port == PORT_C) {
 -              type = DRM_MODE_CONNECTOR_eDP;
 -              intel_encoder->type = INTEL_OUTPUT_EDP;
 -      } else if (port == PORT_A || is_pch_edp(intel_dp)) {
 +      switch (port) {
 +      case PORT_A:
                type = DRM_MODE_CONNECTOR_eDP;
 -              intel_encoder->type = INTEL_OUTPUT_EDP;
 -      } else {
 -              /* The intel_encoder->type value may be INTEL_OUTPUT_UNKNOWN for
 -               * DDI or INTEL_OUTPUT_DISPLAYPORT for the older gens, so don't
 -               * rewrite it.
 -               */
 -              type = DRM_MODE_CONNECTOR_DisplayPort;
 +              break;
 +      case PORT_C:
 +              if (IS_VALLEYVIEW(dev))
 +                      type = DRM_MODE_CONNECTOR_eDP;
 +              break;
 +      case PORT_D:
 +              if (HAS_PCH_SPLIT(dev) && intel_dpd_is_edp(dev))
 +                      type = DRM_MODE_CONNECTOR_eDP;
 +              break;
 +      default:        /* silence GCC warning */
 +              break;
        }
  
 +      /*
 +       * For eDP we always set the encoder type to INTEL_OUTPUT_EDP, but
 +       * for DP the encoder type can be set by the caller to
 +       * INTEL_OUTPUT_UNKNOWN for DDI, so don't rewrite it.
 +       */
 +      if (type == DRM_MODE_CONNECTOR_eDP)
 +              intel_encoder->type = INTEL_OUTPUT_EDP;
 +
 +      DRM_DEBUG_KMS("Adding %s connector on port %c\n",
 +                      type == DRM_MODE_CONNECTOR_eDP ? "eDP" : "DP",
 +                      port_name(port));
 +
        drm_connector_init(dev, connector, &intel_dp_connector_funcs, type);
        drm_connector_helper_add(connector, &intel_dp_connector_helper_funcs);
  
                }
  
                /* fallback to VBT if available for eDP */
 -              if (!fixed_mode && dev_priv->lfp_lvds_vbt_mode) {
 -                      fixed_mode = drm_mode_duplicate(dev, dev_priv->lfp_lvds_vbt_mode);
 +              if (!fixed_mode && dev_priv->vbt.lfp_lvds_vbt_mode) {
 +                      fixed_mode = drm_mode_duplicate(dev, dev_priv->vbt.lfp_lvds_vbt_mode);
                        if (fixed_mode)
                                fixed_mode->type |= DRM_MODE_TYPE_PREFERRED;
                }
@@@ -3154,8 -2986,6 +3184,8 @@@ intel_dp_init(struct drm_device *dev, i
        intel_encoder->disable = intel_disable_dp;
        intel_encoder->post_disable = intel_post_disable_dp;
        intel_encoder->get_hw_state = intel_dp_get_hw_state;
 +      if (IS_VALLEYVIEW(dev))
 +              intel_encoder->pre_pll_enable = intel_dp_pre_pll_enable;
  
        intel_dig_port->port = port;
        intel_dig_port->dp.output_reg = output_reg;
index 0f3554592719a17b6a6dc434824afddc9d1317f9,624a9e6b8d718ebe64a3aa41019137b673b3b296..9b0af7e27c82a40a41b9d26a94eab454834edfde
@@@ -120,6 -120,7 +120,6 @@@ struct intel_encoder 
        struct intel_crtc *new_crtc;
  
        int type;
 -      bool needs_tv_clock;
        /*
         * Intel hw has only one MUX where encoders could be clone, hence a
         * simple flag is enough to compute the possible_clones mask.
@@@ -176,18 -177,6 +176,18 @@@ struct intel_connector 
        u8 polled;
  };
  
 +typedef struct dpll {
 +      /* given values */
 +      int n;
 +      int m1, m2;
 +      int p1, p2;
 +      /* derived values */
 +      int     dot;
 +      int     vco;
 +      int     m;
 +      int     p;
 +} intel_clock_t;
 +
  struct intel_crtc_config {
        struct drm_display_mode requested_mode;
        struct drm_display_mode adjusted_mode;
        /* DP has a bunch of special case unfortunately, so mark the pipe
         * accordingly. */
        bool has_dp_encoder;
 +
 +      /*
 +       * Enable dithering, used when the selected pipe bpp doesn't match the
 +       * plane bpp.
 +       */
        bool dither;
  
        /* Controls for the clock computation, to override various stages. */
        bool clock_set;
  
 +      /* SDVO TV has a bunch of special case. To make multifunction encoders
 +       * work correctly, we need to track this at runtime.*/
 +      bool sdvo_tv_clock;
 +
 +      /*
 +       * crtc bandwidth limit, don't increase pipe bpp or clock if not really
 +       * required. This is set in the 2nd loop of calling encoder's
 +       * ->compute_config if the first pick doesn't work out.
 +       */
 +      bool bw_constrained;
 +
        /* Settings for the intel dpll used on pretty much everything but
         * haswell. */
 -      struct dpll {
 -              unsigned n;
 -              unsigned m1, m2;
 -              unsigned p1, p2;
 -      } dpll;
 +      struct dpll dpll;
  
        int pipe_bpp;
        struct intel_link_m_n dp_m_n;
        int pixel_target_clock;
        /* Used by SDVO (and if we ever fix it, HDMI). */
        unsigned pixel_multiplier;
 +
 +      /* Panel fitter controls for gen2-gen4 + VLV */
 +      struct {
 +              u32 control;
 +              u32 pgm_ratios;
 +              u32 lvds_border_bits;
 +      } gmch_pfit;
 +
 +      /* Panel fitter placement and size for Ironlake+ */
 +      struct {
 +              u32 pos;
 +              u32 size;
 +      } pch_pfit;
 +
 +      /* FDI configuration, only valid if has_pch_encoder is set. */
 +      int fdi_lanes;
 +      struct intel_link_m_n fdi_m_n;
  };
  
  struct intel_crtc {
        bool lowfreq_avail;
        struct intel_overlay *overlay;
        struct intel_unpin_work *unpin_work;
 -      int fdi_lanes;
  
        atomic_t unpin_work_count;
  
  
        /* reset counter value when the last flip was submitted */
        unsigned int reset_counter;
 +
 +      /* Access to these should be protected by dev_priv->irq_lock. */
 +      bool cpu_fifo_underrun_disabled;
 +      bool pch_fifo_underrun_disabled;
  };
  
  struct intel_plane {
@@@ -454,6 -411,7 +454,6 @@@ struct intel_dp 
        uint8_t downstream_ports[DP_MAX_DOWNSTREAM_PORTS];
        struct i2c_adapter adapter;
        struct i2c_algo_dp_aux_data algo;
 -      bool is_pch_edp;
        uint8_t train_set[4];
        int panel_power_up_delay;
        int panel_power_down_delay;
@@@ -473,19 -431,6 +473,19 @@@ struct intel_digital_port 
        struct intel_hdmi hdmi;
  };
  
 +static inline int
 +vlv_dport_to_channel(struct intel_digital_port *dport)
 +{
 +      switch (dport->port) {
 +      case PORT_B:
 +              return 0;
 +      case PORT_C:
 +              return 1;
 +      default:
 +              BUG();
 +      }
 +}
 +
  static inline struct drm_crtc *
  intel_get_crtc_for_pipe(struct drm_device *dev, int pipe)
  {
@@@ -529,7 -474,6 +529,7 @@@ int intel_ddc_get_modes(struct drm_conn
  extern void intel_attach_force_audio_property(struct drm_connector *connector);
  extern void intel_attach_broadcast_rgb_property(struct drm_connector *connector);
  
 +extern bool intel_pipe_has_type(struct drm_crtc *crtc, int type);
  extern void intel_crt_init(struct drm_device *dev);
  extern void intel_hdmi_init(struct drm_device *dev,
                            int hdmi_reg, enum port port);
@@@ -555,6 -499,7 +555,7 @@@ extern void intel_dp_init_connector(str
  extern void intel_dp_init_link_config(struct intel_dp *intel_dp);
  extern void intel_dp_start_link_train(struct intel_dp *intel_dp);
  extern void intel_dp_complete_link_train(struct intel_dp *intel_dp);
+ extern void intel_dp_stop_link_train(struct intel_dp *intel_dp);
  extern void intel_dp_sink_dpms(struct intel_dp *intel_dp, int mode);
  extern void intel_dp_encoder_destroy(struct drm_encoder *encoder);
  extern void intel_dp_check_link_status(struct intel_dp *intel_dp);
@@@ -567,6 -512,7 +568,6 @@@ extern void ironlake_edp_panel_on(struc
  extern void ironlake_edp_panel_off(struct intel_dp *intel_dp);
  extern void ironlake_edp_panel_vdd_on(struct intel_dp *intel_dp);
  extern void ironlake_edp_panel_vdd_off(struct intel_dp *intel_dp, bool sync);
 -extern bool intel_encoder_is_pch_edp(struct drm_encoder *encoder);
  extern int intel_plane_init(struct drm_device *dev, enum pipe pipe, int plane);
  extern void intel_flush_display_plane(struct drm_i915_private *dev_priv,
                                      enum plane plane);
@@@ -578,14 -524,12 +579,14 @@@ extern void intel_panel_fini(struct int
  
  extern void intel_fixed_panel_mode(struct drm_display_mode *fixed_mode,
                                   struct drm_display_mode *adjusted_mode);
 -extern void intel_pch_panel_fitting(struct drm_device *dev,
 -                                  int fitting_mode,
 -                                  const struct drm_display_mode *mode,
 -                                  struct drm_display_mode *adjusted_mode);
 -extern u32 intel_panel_get_max_backlight(struct drm_device *dev);
 -extern void intel_panel_set_backlight(struct drm_device *dev, u32 level);
 +extern void intel_pch_panel_fitting(struct intel_crtc *crtc,
 +                                  struct intel_crtc_config *pipe_config,
 +                                  int fitting_mode);
 +extern void intel_gmch_panel_fitting(struct intel_crtc *crtc,
 +                                   struct intel_crtc_config *pipe_config,
 +                                   int fitting_mode);
 +extern void intel_panel_set_backlight(struct drm_device *dev,
 +                                    u32 level, u32 max);
  extern int intel_panel_setup_backlight(struct drm_connector *connector);
  extern void intel_panel_enable_backlight(struct drm_device *dev,
                                         enum pipe pipe);
@@@ -621,17 -565,19 +622,17 @@@ static inline struct intel_encoder *int
        return to_intel_connector(connector)->encoder;
  }
  
 -static inline struct intel_dp *enc_to_intel_dp(struct drm_encoder *encoder)
 -{
 -      struct intel_digital_port *intel_dig_port =
 -              container_of(encoder, struct intel_digital_port, base.base);
 -      return &intel_dig_port->dp;
 -}
 -
  static inline struct intel_digital_port *
  enc_to_dig_port(struct drm_encoder *encoder)
  {
        return container_of(encoder, struct intel_digital_port, base.base);
  }
  
 +static inline struct intel_dp *enc_to_intel_dp(struct drm_encoder *encoder)
 +{
 +      return &enc_to_dig_port(encoder)->dp;
 +}
 +
  static inline struct intel_digital_port *
  dp_to_dig_port(struct intel_dp *intel_dp)
  {
@@@ -661,7 -607,6 +662,7 @@@ intel_pipe_to_cpu_transcoder(struct drm
  extern void intel_wait_for_vblank(struct drm_device *dev, int pipe);
  extern void intel_wait_for_pipe_off(struct drm_device *dev, int pipe);
  extern int ironlake_get_lanes_required(int target_clock, int link_bw, int bpp);
 +extern void vlv_wait_port_ready(struct drm_i915_private *dev_priv, int port);
  
  struct intel_load_detect_pipe {
        struct drm_framebuffer *release_fb;
@@@ -715,9 -660,13 +716,9 @@@ extern void assert_pipe(struct drm_i915
  #define assert_pipe_disabled(d, p) assert_pipe(d, p, false)
  
  extern void intel_init_clock_gating(struct drm_device *dev);
 +extern void intel_suspend_hw(struct drm_device *dev);
  extern void intel_write_eld(struct drm_encoder *encoder,
                            struct drm_display_mode *mode);
 -extern void intel_cpt_verify_modeset(struct drm_device *dev, int pipe);
 -extern void intel_cpu_transcoder_set_m_n(struct intel_crtc *crtc,
 -                                       struct intel_link_m_n *m_n);
 -extern void intel_pch_transcoder_set_m_n(struct intel_crtc *crtc,
 -                                       struct intel_link_m_n *m_n);
  extern void intel_prepare_ddi(struct drm_device *dev);
  extern void hsw_fdi_link_train(struct drm_crtc *crtc);
  extern void intel_ddi_init(struct drm_device *dev, enum port port);
@@@ -741,8 -690,6 +742,8 @@@ extern int intel_sprite_get_colorkey(st
                                     struct drm_file *file_priv);
  
  extern u32 intel_dpio_read(struct drm_i915_private *dev_priv, int reg);
 +extern void intel_dpio_write(struct drm_i915_private *dev_priv, int reg,
 +                           u32 val);
  
  /* Power-related functions, located in intel_pm.c */
  extern void intel_init_pm(struct drm_device *dev);
@@@ -754,8 -701,7 +755,8 @@@ extern void intel_update_fbc(struct drm
  extern void intel_gpu_ips_init(struct drm_i915_private *dev_priv);
  extern void intel_gpu_ips_teardown(void);
  
 -extern bool intel_using_power_well(struct drm_device *dev);
 +extern bool intel_display_power_enabled(struct drm_device *dev,
 +                                      enum intel_display_power_domain domain);
  extern void intel_init_power_well(struct drm_device *dev);
  extern void intel_set_power_well(struct drm_device *dev, bool enable);
  extern void intel_enable_gt_powersave(struct drm_device *dev);
@@@ -782,11 -728,5 +783,11 @@@ intel_ddi_connector_get_hw_state(struc
  extern void intel_ddi_fdi_disable(struct drm_crtc *crtc);
  
  extern void intel_display_handle_reset(struct drm_device *dev);
 +extern bool intel_set_cpu_fifo_underrun_reporting(struct drm_device *dev,
 +                                                enum pipe pipe,
 +                                                bool enable);
 +extern bool intel_set_pch_fifo_underrun_reporting(struct drm_device *dev,
 +                                               enum transcoder pch_transcoder,
 +                                               bool enable);
  
  #endif /* __INTEL_DRV_H__ */
index ee328ce8e9fe8c49b4c5e7b5dd101b713aa6e72c,cc70b16d5d42b38bd97fb0eda2db12209ccf13c2..2c0be924e9a9553f380eb20bb85eea9e4816b653
@@@ -53,13 -53,6 +53,13 @@@ static const struct intel_dvo_device in
                .slave_addr = CH7xxx_ADDR,
                .dev_ops = &ch7xxx_ops,
        },
 +      {
 +              .type = INTEL_DVO_CHIP_TMDS,
 +              .name = "ch7xxx",
 +              .dvo_reg = DVOC,
 +              .slave_addr = 0x75, /* For some ch7010 */
 +              .dev_ops = &ch7xxx_ops,
 +      },
        {
                .type = INTEL_DVO_CHIP_LVDS,
                .name = "ivch",
@@@ -455,6 -448,7 +455,7 @@@ void intel_dvo_init(struct drm_device *
                const struct intel_dvo_device *dvo = &intel_dvo_devices[i];
                struct i2c_adapter *i2c;
                int gpio;
+               bool dvoinit;
  
                /* Allow the I2C driver info to specify the GPIO to be used in
                 * special cases, but otherwise default to what's defined
                i2c = intel_gmbus_get_adapter(dev_priv, gpio);
  
                intel_dvo->dev = *dvo;
-               if (!dvo->dev_ops->init(&intel_dvo->dev, i2c))
+               /* GMBUS NAK handling seems to be unstable, hence let the
+                * transmitter detection run in bit banging mode for now.
+                */
+               intel_gmbus_force_bit(i2c, true);
+               dvoinit = dvo->dev_ops->init(&intel_dvo->dev, i2c);
+               intel_gmbus_force_bit(i2c, false);
+               if (!dvoinit)
                        continue;
  
                intel_encoder->type = INTEL_OUTPUT_DVO;
index 93de5ff77912aaf9f46bdca2a5c3dc766addec39,a9057930f2b2186d43a3a71417e59408804172b3..2b727f0d201fd8e7e0f82e5efa5e77553fcff630
@@@ -697,14 -697,6 +697,14 @@@ static void intel_enable_hdmi(struct in
                I915_WRITE(intel_hdmi->hdmi_reg, temp);
                POSTING_READ(intel_hdmi->hdmi_reg);
        }
 +
 +      if (IS_VALLEYVIEW(dev)) {
 +              struct intel_digital_port *dport =
 +                      enc_to_dig_port(&encoder->base);
 +              int channel = vlv_dport_to_channel(dport);
 +
 +              vlv_wait_port_ready(dev_priv, channel);
 +      }
  }
  
  static void intel_disable_hdmi(struct intel_encoder *encoder)
@@@ -783,8 -775,6 +783,8 @@@ bool intel_hdmi_compute_config(struct i
        struct intel_hdmi *intel_hdmi = enc_to_intel_hdmi(&encoder->base);
        struct drm_device *dev = encoder->base.dev;
        struct drm_display_mode *adjusted_mode = &pipe_config->adjusted_mode;
 +      int clock_12bpc = pipe_config->requested_mode.clock * 3 / 2;
 +      int desired_bpp;
  
        if (intel_hdmi->color_range_auto) {
                /* See CEA-861-E - 5.1 Default Encoding Parameters */
        /*
         * HDMI is either 12 or 8, so if the display lets 10bpc sneak
         * through, clamp it down. Note that g4x/vlv don't support 12bpc hdmi
 -       * outputs.
 +       * outputs. We also need to check that the higher clock still fits
 +       * within limits.
         */
 -      if (pipe_config->pipe_bpp > 8*3 && HAS_PCH_SPLIT(dev)) {
 -              DRM_DEBUG_KMS("forcing bpc to 12 for HDMI\n");
 -              pipe_config->pipe_bpp = 12*3;
 +      if (pipe_config->pipe_bpp > 8*3 && clock_12bpc <= 225000
 +          && HAS_PCH_SPLIT(dev)) {
 +              DRM_DEBUG_KMS("picking bpc to 12 for HDMI output\n");
 +              desired_bpp = 12*3;
 +
 +              /* Need to adjust the port link by 1.5x for 12bpc. */
 +              adjusted_mode->clock = clock_12bpc;
 +              pipe_config->pixel_target_clock =
 +                      pipe_config->requested_mode.clock;
        } else {
 -              DRM_DEBUG_KMS("forcing bpc to 8 for HDMI\n");
 -              pipe_config->pipe_bpp = 8*3;
 +              DRM_DEBUG_KMS("picking bpc to 8 for HDMI output\n");
 +              desired_bpp = 8*3;
 +      }
 +
 +      if (!pipe_config->bw_constrained) {
 +              DRM_DEBUG_KMS("forcing pipe bpc to %i for HDMI\n", desired_bpp);
 +              pipe_config->pipe_bpp = desired_bpp;
 +      }
 +
 +      if (adjusted_mode->clock > 225000) {
 +              DRM_DEBUG_KMS("too high HDMI clock, rejecting mode\n");
 +              return false;
        }
  
        return true;
@@@ -947,6 -920,9 +947,9 @@@ intel_hdmi_set_property(struct drm_conn
        }
  
        if (property == dev_priv->broadcast_rgb_property) {
+               bool old_auto = intel_hdmi->color_range_auto;
+               uint32_t old_range = intel_hdmi->color_range;
                switch (val) {
                case INTEL_BROADCAST_RGB_AUTO:
                        intel_hdmi->color_range_auto = true;
                default:
                        return -EINVAL;
                }
+               if (old_auto == intel_hdmi->color_range_auto &&
+                   old_range == intel_hdmi->color_range)
+                       return 0;
                goto done;
        }
  
@@@ -974,101 -955,6 +982,101 @@@ done
        return 0;
  }
  
 +static void intel_hdmi_pre_enable(struct intel_encoder *encoder)
 +{
 +      struct intel_digital_port *dport = enc_to_dig_port(&encoder->base);
 +      struct drm_device *dev = encoder->base.dev;
 +      struct drm_i915_private *dev_priv = dev->dev_private;
 +      struct intel_crtc *intel_crtc =
 +              to_intel_crtc(encoder->base.crtc);
 +      int port = vlv_dport_to_channel(dport);
 +      int pipe = intel_crtc->pipe;
 +      u32 val;
 +
 +      if (!IS_VALLEYVIEW(dev))
 +              return;
 +
 +      WARN_ON(!mutex_is_locked(&dev_priv->dpio_lock));
 +
 +      /* Enable clock channels for this port */
 +      val = intel_dpio_read(dev_priv, DPIO_DATA_LANE_A(port));
 +      val = 0;
 +      if (pipe)
 +              val |= (1<<21);
 +      else
 +              val &= ~(1<<21);
 +      val |= 0x001000c4;
 +      intel_dpio_write(dev_priv, DPIO_DATA_CHANNEL(port), val);
 +
 +      /* HDMI 1.0V-2dB */
 +      intel_dpio_write(dev_priv, DPIO_TX_OCALINIT(port), 0);
 +      intel_dpio_write(dev_priv, DPIO_TX_SWING_CTL4(port),
 +                       0x2b245f5f);
 +      intel_dpio_write(dev_priv, DPIO_TX_SWING_CTL2(port),
 +                       0x5578b83a);
 +      intel_dpio_write(dev_priv, DPIO_TX_SWING_CTL3(port),
 +                       0x0c782040);
 +      intel_dpio_write(dev_priv, DPIO_TX3_SWING_CTL4(port),
 +                       0x2b247878);
 +      intel_dpio_write(dev_priv, DPIO_PCS_STAGGER0(port), 0x00030000);
 +      intel_dpio_write(dev_priv, DPIO_PCS_CTL_OVER1(port),
 +                       0x00002000);
 +      intel_dpio_write(dev_priv, DPIO_TX_OCALINIT(port),
 +                       DPIO_TX_OCALINIT_EN);
 +
 +      /* Program lane clock */
 +      intel_dpio_write(dev_priv, DPIO_PCS_CLOCKBUF0(port),
 +                       0x00760018);
 +      intel_dpio_write(dev_priv, DPIO_PCS_CLOCKBUF8(port),
 +                       0x00400888);
 +}
 +
 +static void intel_hdmi_pre_pll_enable(struct intel_encoder *encoder)
 +{
 +      struct intel_digital_port *dport = enc_to_dig_port(&encoder->base);
 +      struct drm_device *dev = encoder->base.dev;
 +      struct drm_i915_private *dev_priv = dev->dev_private;
 +      int port = vlv_dport_to_channel(dport);
 +
 +      if (!IS_VALLEYVIEW(dev))
 +              return;
 +
 +      WARN_ON(!mutex_is_locked(&dev_priv->dpio_lock));
 +
 +      /* Program Tx lane resets to default */
 +      intel_dpio_write(dev_priv, DPIO_PCS_TX(port),
 +                       DPIO_PCS_TX_LANE2_RESET |
 +                       DPIO_PCS_TX_LANE1_RESET);
 +      intel_dpio_write(dev_priv, DPIO_PCS_CLK(port),
 +                       DPIO_PCS_CLK_CRI_RXEB_EIOS_EN |
 +                       DPIO_PCS_CLK_CRI_RXDIGFILTSG_EN |
 +                       (1<<DPIO_PCS_CLK_DATAWIDTH_SHIFT) |
 +                       DPIO_PCS_CLK_SOFT_RESET);
 +
 +      /* Fix up inter-pair skew failure */
 +      intel_dpio_write(dev_priv, DPIO_PCS_STAGGER1(port), 0x00750f00);
 +      intel_dpio_write(dev_priv, DPIO_TX_CTL(port), 0x00001500);
 +      intel_dpio_write(dev_priv, DPIO_TX_LANE(port), 0x40400000);
 +
 +      intel_dpio_write(dev_priv, DPIO_PCS_CTL_OVER1(port),
 +                       0x00002000);
 +      intel_dpio_write(dev_priv, DPIO_TX_OCALINIT(port),
 +                       DPIO_TX_OCALINIT_EN);
 +}
 +
 +static void intel_hdmi_post_disable(struct intel_encoder *encoder)
 +{
 +      struct intel_digital_port *dport = enc_to_dig_port(&encoder->base);
 +      struct drm_i915_private *dev_priv = encoder->base.dev->dev_private;
 +      int port = vlv_dport_to_channel(dport);
 +
 +      /* Reset lanes to avoid HDMI flicker (VLV w/a) */
 +      mutex_lock(&dev_priv->dpio_lock);
 +      intel_dpio_write(dev_priv, DPIO_PCS_TX(port), 0x00000000);
 +      intel_dpio_write(dev_priv, DPIO_PCS_CLK(port), 0x00e00060);
 +      mutex_unlock(&dev_priv->dpio_lock);
 +}
 +
  static void intel_hdmi_destroy(struct drm_connector *connector)
  {
        drm_sysfs_connector_remove(connector);
@@@ -1208,11 -1094,6 +1216,11 @@@ void intel_hdmi_init(struct drm_device 
        intel_encoder->enable = intel_enable_hdmi;
        intel_encoder->disable = intel_disable_hdmi;
        intel_encoder->get_hw_state = intel_hdmi_get_hw_state;
 +      if (IS_VALLEYVIEW(dev)) {
 +              intel_encoder->pre_enable = intel_hdmi_pre_enable;
 +              intel_encoder->pre_pll_enable = intel_hdmi_pre_pll_enable;
 +              intel_encoder->post_disable = intel_hdmi_post_disable;
 +      }
  
        intel_encoder->type = INTEL_OUTPUT_HDMI;
        intel_encoder->crtc_mask = (1 << 0) | (1 << 1) | (1 << 2);
index 62b64e4877b8b9a5b5764d987936c37559d40739,a8117e614009d072b7486176dff44bdd99b93538..5c2d6939600e553998ed41fbfa3ed9001fe07002
@@@ -110,10 -110,6 +110,10 @@@ struct opregion_asle 
        u8 rsvd[102];
  } __attribute__((packed));
  
 +/* Driver readiness indicator */
 +#define ASLE_ARDY_READY               (1 << 0)
 +#define ASLE_ARDY_NOT_READY   (0 << 0)
 +
  /* ASLE irq request bits */
  #define ASLE_SET_ALS_ILLUM     (1 << 0)
  #define ASLE_SET_BACKLIGHT     (1 << 1)
  #define ASLE_PFIT_FAILED      (1<<14)
  #define ASLE_PWM_FREQ_FAILED  (1<<16)
  
 +/* Technology enabled indicator */
 +#define ASLE_TCHE_ALS_EN      (1 << 0)
 +#define ASLE_TCHE_BLC_EN      (1 << 1)
 +#define ASLE_TCHE_PFIT_EN     (1 << 2)
 +#define ASLE_TCHE_PFMB_EN     (1 << 3)
 +
  /* ASLE backlight brightness to set */
  #define ASLE_BCLP_VALID                (1<<31)
  #define ASLE_BCLP_MSK          (~(1<<31))
@@@ -162,6 -152,7 +162,6 @@@ static u32 asle_set_backlight(struct dr
  {
        struct drm_i915_private *dev_priv = dev->dev_private;
        struct opregion_asle __iomem *asle = dev_priv->opregion.asle;
 -      u32 max;
  
        DRM_DEBUG_DRIVER("bclp = 0x%08x\n", bclp);
  
        if (bclp > 255)
                return ASLE_BACKLIGHT_FAILED;
  
 -      max = intel_panel_get_max_backlight(dev);
 -      intel_panel_set_backlight(dev, bclp * max / 255);
 +      intel_panel_set_backlight(dev, bclp, 255);
        iowrite32((bclp*0x64)/0xff | ASLE_CBLV_VALID, &asle->cblv);
  
        return 0;
@@@ -182,22 -174,29 +182,22 @@@ static u32 asle_set_als_illum(struct dr
  {
        /* alsi is the current ALS reading in lux. 0 indicates below sensor
           range, 0xffff indicates above sensor range. 1-0xfffe are valid */
 -      return 0;
 +      DRM_DEBUG_DRIVER("Illum is not supported\n");
 +      return ASLE_ALS_ILLUM_FAILED;
  }
  
  static u32 asle_set_pwm_freq(struct drm_device *dev, u32 pfmb)
  {
 -      struct drm_i915_private *dev_priv = dev->dev_private;
 -      if (pfmb & ASLE_PFMB_PWM_VALID) {
 -              u32 blc_pwm_ctl = I915_READ(BLC_PWM_CTL);
 -              u32 pwm = pfmb & ASLE_PFMB_PWM_MASK;
 -              blc_pwm_ctl &= BACKLIGHT_DUTY_CYCLE_MASK;
 -              pwm = pwm >> 9;
 -              /* FIXME - what do we do with the PWM? */
 -      }
 -      return 0;
 +      DRM_DEBUG_DRIVER("PWM freq is not supported\n");
 +      return ASLE_PWM_FREQ_FAILED;
  }
  
  static u32 asle_set_pfit(struct drm_device *dev, u32 pfit)
  {
        /* Panel fitting is currently controlled by the X code, so this is a
           noop until modesetting support works fully */
 -      if (!(pfit & ASLE_PFIT_VALID))
 -              return ASLE_PFIT_FAILED;
 -      return 0;
 +      DRM_DEBUG_DRIVER("Pfit is not supported\n");
 +      return ASLE_PFIT_FAILED;
  }
  
  void intel_opregion_asle_intr(struct drm_device *dev)
        iowrite32(asle_stat, &asle->aslc);
  }
  
 -void intel_opregion_gse_intr(struct drm_device *dev)
 -{
 -      struct drm_i915_private *dev_priv = dev->dev_private;
 -      struct opregion_asle __iomem *asle = dev_priv->opregion.asle;
 -      u32 asle_stat = 0;
 -      u32 asle_req;
 -
 -      if (!asle)
 -              return;
 -
 -      asle_req = ioread32(&asle->aslc) & ASLE_REQ_MSK;
 -
 -      if (!asle_req) {
 -              DRM_DEBUG_DRIVER("non asle set request??\n");
 -              return;
 -      }
 -
 -      if (asle_req & ASLE_SET_ALS_ILLUM) {
 -              DRM_DEBUG_DRIVER("Illum is not supported\n");
 -              asle_stat |= ASLE_ALS_ILLUM_FAILED;
 -      }
 -
 -      if (asle_req & ASLE_SET_BACKLIGHT)
 -              asle_stat |= asle_set_backlight(dev, ioread32(&asle->bclp));
 -
 -      if (asle_req & ASLE_SET_PFIT) {
 -              DRM_DEBUG_DRIVER("Pfit is not supported\n");
 -              asle_stat |= ASLE_PFIT_FAILED;
 -      }
 -
 -      if (asle_req & ASLE_SET_PWM_FREQ) {
 -              DRM_DEBUG_DRIVER("PWM freq is not supported\n");
 -              asle_stat |= ASLE_PWM_FREQ_FAILED;
 -      }
 -
 -      iowrite32(asle_stat, &asle->aslc);
 -}
 -#define ASLE_ALS_EN    (1<<0)
 -#define ASLE_BLC_EN    (1<<1)
 -#define ASLE_PFIT_EN   (1<<2)
 -#define ASLE_PFMB_EN   (1<<3)
 -
 -void intel_opregion_enable_asle(struct drm_device *dev)
 -{
 -      struct drm_i915_private *dev_priv = dev->dev_private;
 -      struct opregion_asle __iomem *asle = dev_priv->opregion.asle;
 -
 -      if (asle) {
 -              if (IS_MOBILE(dev))
 -                      intel_enable_asle(dev);
 -
 -              iowrite32(ASLE_ALS_EN | ASLE_BLC_EN | ASLE_PFIT_EN |
 -                        ASLE_PFMB_EN,
 -                        &asle->tche);
 -              iowrite32(1, &asle->ardy);
 -      }
 -}
 -
  #define ACPI_EV_DISPLAY_SWITCH (1<<0)
  #define ACPI_EV_LID            (1<<1)
  #define ACPI_EV_DOCK           (1<<2)
@@@ -293,11 -350,11 +293,11 @@@ static void intel_didl_outputs(struct d
        if (!handle || acpi_bus_get_device(handle, &acpi_dev))
                return;
  
-       if (acpi_is_video_device(acpi_dev))
+       if (acpi_is_video_device(handle))
                acpi_video_bus = acpi_dev;
        else {
                list_for_each_entry(acpi_cdev, &acpi_dev->children, node) {
-                       if (acpi_is_video_device(acpi_cdev)) {
+                       if (acpi_is_video_device(acpi_cdev->handle)) {
                                acpi_video_bus = acpi_cdev;
                                break;
                        }
@@@ -415,10 -472,8 +415,10 @@@ void intel_opregion_init(struct drm_dev
                register_acpi_notifier(&intel_opregion_notifier);
        }
  
 -      if (opregion->asle)
 -              intel_opregion_enable_asle(dev);
 +      if (opregion->asle) {
 +              iowrite32(ASLE_TCHE_BLC_EN, &opregion->asle->tche);
 +              iowrite32(ASLE_ARDY_READY, &opregion->asle->ardy);
 +      }
  }
  
  void intel_opregion_fini(struct drm_device *dev)
        if (!opregion->header)
                return;
  
 +      if (opregion->asle)
 +              iowrite32(ASLE_ARDY_NOT_READY, &opregion->asle->ardy);
 +
        if (opregion->acpi) {
                iowrite32(0, &opregion->acpi->drdy);
  
@@@ -494,8 -546,6 +494,8 @@@ int intel_opregion_setup(struct drm_dev
        if (mboxes & MBOX_ASLE) {
                DRM_DEBUG_DRIVER("ASLE supported\n");
                opregion->asle = base + OPREGION_ASLE_OFFSET;
 +
 +              iowrite32(ASLE_ARDY_NOT_READY, &opregion->asle->ardy);
        }
  
        return 0;
index 1a765723d37ecca5403efed1b0736df616d10d32,aa01128ff192cc6c5860c881a9aa8a71cb756fd7..e2255ed9789458dac8b63781192a1cc48ed7411e
@@@ -113,8 -113,8 +113,8 @@@ static void i8xx_enable_fbc(struct drm_
        fbc_ctl |= obj->fence_reg;
        I915_WRITE(FBC_CONTROL, fbc_ctl);
  
 -      DRM_DEBUG_KMS("enabled FBC, pitch %d, yoff %d, plane %d, ",
 -                    cfb_pitch, crtc->y, intel_crtc->plane);
 +      DRM_DEBUG_KMS("enabled FBC, pitch %d, yoff %d, plane %c, ",
 +                    cfb_pitch, crtc->y, plane_name(intel_crtc->plane));
  }
  
  static bool i8xx_fbc_enabled(struct drm_device *dev)
@@@ -148,7 -148,7 +148,7 @@@ static void g4x_enable_fbc(struct drm_c
        /* enable it... */
        I915_WRITE(DPFC_CONTROL, I915_READ(DPFC_CONTROL) | DPFC_CTL_EN);
  
 -      DRM_DEBUG_KMS("enabled fbc on plane %d\n", intel_crtc->plane);
 +      DRM_DEBUG_KMS("enabled fbc on plane %c\n", plane_name(intel_crtc->plane));
  }
  
  static void g4x_disable_fbc(struct drm_device *dev)
@@@ -228,7 -228,7 +228,7 @@@ static void ironlake_enable_fbc(struct 
                sandybridge_blit_fbc_update(dev);
        }
  
 -      DRM_DEBUG_KMS("enabled fbc on plane %d\n", intel_crtc->plane);
 +      DRM_DEBUG_KMS("enabled fbc on plane %c\n", plane_name(intel_crtc->plane));
  }
  
  static void ironlake_disable_fbc(struct drm_device *dev)
                dpfc_ctl &= ~DPFC_CTL_EN;
                I915_WRITE(ILK_DPFC_CONTROL, dpfc_ctl);
  
 +              if (IS_IVYBRIDGE(dev))
 +                      /* WaFbcDisableDpfcClockGating:ivb */
 +                      I915_WRITE(ILK_DSPCLK_GATE_D,
 +                                 I915_READ(ILK_DSPCLK_GATE_D) &
 +                                 ~ILK_DPFCUNIT_CLOCK_GATE_DISABLE);
 +
 +              if (IS_HASWELL(dev))
 +                      /* WaFbcDisableDpfcClockGating:hsw */
 +                      I915_WRITE(HSW_CLKGATE_DISABLE_PART_1,
 +                                 I915_READ(HSW_CLKGATE_DISABLE_PART_1) &
 +                                 ~HSW_DPFC_GATING_DISABLE);
 +
                DRM_DEBUG_KMS("disabled FBC\n");
        }
  }
@@@ -265,47 -253,6 +265,47 @@@ static bool ironlake_fbc_enabled(struc
        return I915_READ(ILK_DPFC_CONTROL) & DPFC_CTL_EN;
  }
  
 +static void gen7_enable_fbc(struct drm_crtc *crtc, unsigned long interval)
 +{
 +      struct drm_device *dev = crtc->dev;
 +      struct drm_i915_private *dev_priv = dev->dev_private;
 +      struct drm_framebuffer *fb = crtc->fb;
 +      struct intel_framebuffer *intel_fb = to_intel_framebuffer(fb);
 +      struct drm_i915_gem_object *obj = intel_fb->obj;
 +      struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
 +
 +      I915_WRITE(IVB_FBC_RT_BASE, obj->gtt_offset | ILK_FBC_RT_VALID);
 +
 +      I915_WRITE(ILK_DPFC_CONTROL, DPFC_CTL_EN | DPFC_CTL_LIMIT_1X |
 +                 IVB_DPFC_CTL_FENCE_EN |
 +                 intel_crtc->plane << IVB_DPFC_CTL_PLANE_SHIFT);
 +
 +      if (IS_IVYBRIDGE(dev)) {
 +              /* WaFbcAsynchFlipDisableFbcQueue:ivb */
 +              I915_WRITE(ILK_DISPLAY_CHICKEN1, ILK_FBCQ_DIS);
 +              /* WaFbcDisableDpfcClockGating:ivb */
 +              I915_WRITE(ILK_DSPCLK_GATE_D,
 +                         I915_READ(ILK_DSPCLK_GATE_D) |
 +                         ILK_DPFCUNIT_CLOCK_GATE_DISABLE);
 +      } else {
 +              /* WaFbcAsynchFlipDisableFbcQueue:hsw */
 +              I915_WRITE(HSW_PIPE_SLICE_CHICKEN_1(intel_crtc->pipe),
 +                         HSW_BYPASS_FBC_QUEUE);
 +              /* WaFbcDisableDpfcClockGating:hsw */
 +              I915_WRITE(HSW_CLKGATE_DISABLE_PART_1,
 +                         I915_READ(HSW_CLKGATE_DISABLE_PART_1) |
 +                         HSW_DPFC_GATING_DISABLE);
 +      }
 +
 +      I915_WRITE(SNB_DPFC_CTL_SA,
 +                 SNB_CPU_FENCE_ENABLE | obj->fence_reg);
 +      I915_WRITE(DPFC_CPU_FENCE_OFFSET, crtc->y);
 +
 +      sandybridge_blit_fbc_update(dev);
 +
 +      DRM_DEBUG_KMS("enabled fbc on plane %d\n", intel_crtc->plane);
 +}
 +
  bool intel_fbc_enabled(struct drm_device *dev)
  {
        struct drm_i915_private *dev_priv = dev->dev_private;
@@@ -492,7 -439,7 +492,7 @@@ void intel_update_fbc(struct drm_devic
        if (enable_fbc < 0) {
                DRM_DEBUG_KMS("fbc set to per-chip default\n");
                enable_fbc = 1;
 -              if (INTEL_INFO(dev)->gen <= 6)
 +              if (INTEL_INFO(dev)->gen <= 7 && !IS_HASWELL(dev))
                        enable_fbc = 0;
        }
        if (!enable_fbc) {
                dev_priv->no_fbc_reason = FBC_MODE_TOO_LARGE;
                goto out_disable;
        }
 -      if ((IS_I915GM(dev) || IS_I945GM(dev)) && intel_crtc->plane != 0) {
 +      if ((IS_I915GM(dev) || IS_I945GM(dev) || IS_HASWELL(dev)) &&
 +          intel_crtc->plane != 0) {
                DRM_DEBUG_KMS("plane not 0, disabling compression\n");
                dev_priv->no_fbc_reason = FBC_BAD_PLANE;
                goto out_disable;
                goto out_disable;
  
        if (i915_gem_stolen_setup_compression(dev, intel_fb->obj->base.size)) {
 -              DRM_INFO("not enough stolen space for compressed buffer (need %zd bytes), disabling\n", intel_fb->obj->base.size);
 -              DRM_INFO("hint: you may be able to increase stolen memory size in the BIOS to avoid this\n");
                DRM_DEBUG_KMS("framebuffer too large, disabling compression\n");
                dev_priv->no_fbc_reason = FBC_STOLEN_TOO_SMALL;
                goto out_disable;
@@@ -1353,17 -1301,17 +1353,17 @@@ static void valleyview_update_wm(struc
  
        vlv_update_drain_latency(dev);
  
-       if (g4x_compute_wm0(dev, 0,
+       if (g4x_compute_wm0(dev, PIPE_A,
                            &valleyview_wm_info, latency_ns,
                            &valleyview_cursor_wm_info, latency_ns,
                            &planea_wm, &cursora_wm))
-               enabled |= 1;
+               enabled |= 1 << PIPE_A;
  
-       if (g4x_compute_wm0(dev, 1,
+       if (g4x_compute_wm0(dev, PIPE_B,
                            &valleyview_wm_info, latency_ns,
                            &valleyview_cursor_wm_info, latency_ns,
                            &planeb_wm, &cursorb_wm))
-               enabled |= 2;
+               enabled |= 1 << PIPE_B;
  
        if (single_plane_enabled(enabled) &&
            g4x_compute_srwm(dev, ffs(enabled) - 1,
@@@ -1409,17 -1357,17 +1409,17 @@@ static void g4x_update_wm(struct drm_de
        int plane_sr, cursor_sr;
        unsigned int enabled = 0;
  
-       if (g4x_compute_wm0(dev, 0,
+       if (g4x_compute_wm0(dev, PIPE_A,
                            &g4x_wm_info, latency_ns,
                            &g4x_cursor_wm_info, latency_ns,
                            &planea_wm, &cursora_wm))
-               enabled |= 1;
+               enabled |= 1 << PIPE_A;
  
-       if (g4x_compute_wm0(dev, 1,
+       if (g4x_compute_wm0(dev, PIPE_B,
                            &g4x_wm_info, latency_ns,
                            &g4x_cursor_wm_info, latency_ns,
                            &planeb_wm, &cursorb_wm))
-               enabled |= 2;
+               enabled |= 1 << PIPE_B;
  
        if (single_plane_enabled(enabled) &&
            g4x_compute_srwm(dev, ffs(enabled) - 1,
@@@ -1685,10 -1633,6 +1685,10 @@@ static bool ironlake_check_srwm(struct 
                I915_WRITE(DISP_ARB_CTL,
                           I915_READ(DISP_ARB_CTL) | DISP_FBC_WM_DIS);
                return false;
 +      } else if (INTEL_INFO(dev)->gen >= 6) {
 +              /* enable FBC WM (except on ILK, where it must remain off) */
 +              I915_WRITE(DISP_ARB_CTL,
 +                         I915_READ(DISP_ARB_CTL) & ~DISP_FBC_WM_DIS);
        }
  
        if (display_wm > display->max_wm) {
@@@ -1772,7 -1716,7 +1772,7 @@@ static void ironlake_update_wm(struct d
        unsigned int enabled;
  
        enabled = 0;
-       if (g4x_compute_wm0(dev, 0,
+       if (g4x_compute_wm0(dev, PIPE_A,
                            &ironlake_display_wm_info,
                            ILK_LP0_PLANE_LATENCY,
                            &ironlake_cursor_wm_info,
                DRM_DEBUG_KMS("FIFO watermarks For pipe A -"
                              " plane %d, " "cursor: %d\n",
                              plane_wm, cursor_wm);
-               enabled |= 1;
+               enabled |= 1 << PIPE_A;
        }
  
-       if (g4x_compute_wm0(dev, 1,
+       if (g4x_compute_wm0(dev, PIPE_B,
                            &ironlake_display_wm_info,
                            ILK_LP0_PLANE_LATENCY,
                            &ironlake_cursor_wm_info,
                DRM_DEBUG_KMS("FIFO watermarks For pipe B -"
                              " plane %d, cursor: %d\n",
                              plane_wm, cursor_wm);
-               enabled |= 2;
+               enabled |= 1 << PIPE_B;
        }
  
        /*
@@@ -1857,7 -1801,7 +1857,7 @@@ static void sandybridge_update_wm(struc
        unsigned int enabled;
  
        enabled = 0;
-       if (g4x_compute_wm0(dev, 0,
+       if (g4x_compute_wm0(dev, PIPE_A,
                            &sandybridge_display_wm_info, latency,
                            &sandybridge_cursor_wm_info, latency,
                            &plane_wm, &cursor_wm)) {
                DRM_DEBUG_KMS("FIFO watermarks For pipe A -"
                              " plane %d, " "cursor: %d\n",
                              plane_wm, cursor_wm);
-               enabled |= 1;
+               enabled |= 1 << PIPE_A;
        }
  
-       if (g4x_compute_wm0(dev, 1,
+       if (g4x_compute_wm0(dev, PIPE_B,
                            &sandybridge_display_wm_info, latency,
                            &sandybridge_cursor_wm_info, latency,
                            &plane_wm, &cursor_wm)) {
                DRM_DEBUG_KMS("FIFO watermarks For pipe B -"
                              " plane %d, cursor: %d\n",
                              plane_wm, cursor_wm);
-               enabled |= 2;
+               enabled |= 1 << PIPE_B;
        }
  
        /*
@@@ -1960,7 -1904,7 +1960,7 @@@ static void ivybridge_update_wm(struct 
        unsigned int enabled;
  
        enabled = 0;
-       if (g4x_compute_wm0(dev, 0,
+       if (g4x_compute_wm0(dev, PIPE_A,
                            &sandybridge_display_wm_info, latency,
                            &sandybridge_cursor_wm_info, latency,
                            &plane_wm, &cursor_wm)) {
                DRM_DEBUG_KMS("FIFO watermarks For pipe A -"
                              " plane %d, " "cursor: %d\n",
                              plane_wm, cursor_wm);
-               enabled |= 1;
+               enabled |= 1 << PIPE_A;
        }
  
-       if (g4x_compute_wm0(dev, 1,
+       if (g4x_compute_wm0(dev, PIPE_B,
                            &sandybridge_display_wm_info, latency,
                            &sandybridge_cursor_wm_info, latency,
                            &plane_wm, &cursor_wm)) {
                DRM_DEBUG_KMS("FIFO watermarks For pipe B -"
                              " plane %d, cursor: %d\n",
                              plane_wm, cursor_wm);
-               enabled |= 2;
+               enabled |= 1 << PIPE_B;
        }
  
-       if (g4x_compute_wm0(dev, 2,
+       if (g4x_compute_wm0(dev, PIPE_C,
                            &sandybridge_display_wm_info, latency,
                            &sandybridge_cursor_wm_info, latency,
                            &plane_wm, &cursor_wm)) {
                DRM_DEBUG_KMS("FIFO watermarks For pipe C -"
                              " plane %d, cursor: %d\n",
                              plane_wm, cursor_wm);
-               enabled |= 3;
+               enabled |= 1 << PIPE_C;
        }
  
        /*
@@@ -2202,15 -2146,15 +2202,15 @@@ static void sandybridge_update_sprite_w
                                            &sandybridge_display_wm_info,
                                            latency, &sprite_wm);
        if (!ret) {
 -              DRM_DEBUG_KMS("failed to compute sprite wm for pipe %d\n",
 -                            pipe);
 +              DRM_DEBUG_KMS("failed to compute sprite wm for pipe %c\n",
 +                            pipe_name(pipe));
                return;
        }
  
        val = I915_READ(reg);
        val &= ~WM0_PIPE_SPRITE_MASK;
        I915_WRITE(reg, val | (sprite_wm << WM0_PIPE_SPRITE_SHIFT));
 -      DRM_DEBUG_KMS("sprite watermarks For pipe %d - %d\n", pipe, sprite_wm);
 +      DRM_DEBUG_KMS("sprite watermarks For pipe %c - %d\n", pipe_name(pipe), sprite_wm);
  
  
        ret = sandybridge_compute_sprite_srwm(dev, pipe, sprite_width,
                                              SNB_READ_WM1_LATENCY() * 500,
                                              &sprite_wm);
        if (!ret) {
 -              DRM_DEBUG_KMS("failed to compute sprite lp1 wm on pipe %d\n",
 -                            pipe);
 +              DRM_DEBUG_KMS("failed to compute sprite lp1 wm on pipe %c\n",
 +                            pipe_name(pipe));
                return;
        }
        I915_WRITE(WM1S_LP_ILK, sprite_wm);
                                              SNB_READ_WM2_LATENCY() * 500,
                                              &sprite_wm);
        if (!ret) {
 -              DRM_DEBUG_KMS("failed to compute sprite lp2 wm on pipe %d\n",
 -                            pipe);
 +              DRM_DEBUG_KMS("failed to compute sprite lp2 wm on pipe %c\n",
 +                            pipe_name(pipe));
                return;
        }
        I915_WRITE(WM2S_LP_IVB, sprite_wm);
                                              SNB_READ_WM3_LATENCY() * 500,
                                              &sprite_wm);
        if (!ret) {
 -              DRM_DEBUG_KMS("failed to compute sprite lp3 wm on pipe %d\n",
 -                            pipe);
 +              DRM_DEBUG_KMS("failed to compute sprite lp3 wm on pipe %c\n",
 +                            pipe_name(pipe));
                return;
        }
        I915_WRITE(WM3S_LP_IVB, sprite_wm);
@@@ -2537,52 -2481,6 +2537,52 @@@ void gen6_set_rps(struct drm_device *de
        trace_intel_gpu_freq_change(val * 50);
  }
  
 +void valleyview_set_rps(struct drm_device *dev, u8 val)
 +{
 +      struct drm_i915_private *dev_priv = dev->dev_private;
 +      unsigned long timeout = jiffies + msecs_to_jiffies(10);
 +      u32 limits = gen6_rps_limits(dev_priv, &val);
 +      u32 pval;
 +
 +      WARN_ON(!mutex_is_locked(&dev_priv->rps.hw_lock));
 +      WARN_ON(val > dev_priv->rps.max_delay);
 +      WARN_ON(val < dev_priv->rps.min_delay);
 +
 +      DRM_DEBUG_DRIVER("gpu freq request from %d to %d\n",
 +                       vlv_gpu_freq(dev_priv->mem_freq,
 +                                    dev_priv->rps.cur_delay),
 +                       vlv_gpu_freq(dev_priv->mem_freq, val));
 +
 +      if (val == dev_priv->rps.cur_delay)
 +              return;
 +
 +      valleyview_punit_write(dev_priv, PUNIT_REG_GPU_FREQ_REQ, val);
 +
 +      do {
 +              valleyview_punit_read(dev_priv, PUNIT_REG_GPU_FREQ_STS, &pval);
 +              if (time_after(jiffies, timeout)) {
 +                      DRM_DEBUG_DRIVER("timed out waiting for Punit\n");
 +                      break;
 +              }
 +              udelay(10);
 +      } while (pval & 1);
 +
 +      valleyview_punit_read(dev_priv, PUNIT_REG_GPU_FREQ_STS, &pval);
 +      if ((pval >> 8) != val)
 +              DRM_DEBUG_DRIVER("punit overrode freq: %d requested, but got %d\n",
 +                        val, pval >> 8);
 +
 +      /* Make sure we continue to get interrupts
 +       * until we hit the minimum or maximum frequencies.
 +       */
 +      I915_WRITE(GEN6_RP_INTERRUPT_LIMITS, limits);
 +
 +      dev_priv->rps.cur_delay = pval >> 8;
 +
 +      trace_intel_gpu_freq_change(vlv_gpu_freq(dev_priv->mem_freq, val));
 +}
 +
 +
  static void gen6_disable_rps(struct drm_device *dev)
  {
        struct drm_i915_private *dev_priv = dev->dev_private;
        I915_WRITE(GEN6_PMIIR, I915_READ(GEN6_PMIIR));
  }
  
 +static void valleyview_disable_rps(struct drm_device *dev)
 +{
 +      struct drm_i915_private *dev_priv = dev->dev_private;
 +
 +      I915_WRITE(GEN6_RC_CONTROL, 0);
 +      I915_WRITE(GEN6_PMINTRMSK, 0xffffffff);
 +      I915_WRITE(GEN6_PMIER, 0);
 +      /* Complete PM interrupt masking here doesn't race with the rps work
 +       * item again unmasking PM interrupts because that is using a different
 +       * register (PMIMR) to mask PM interrupts. The only risk is in leaving
 +       * stale bits in PMIIR and PMIMR which gen6_enable_rps will clean up. */
 +
 +      spin_lock_irq(&dev_priv->rps.lock);
 +      dev_priv->rps.pm_iir = 0;
 +      spin_unlock_irq(&dev_priv->rps.lock);
 +
 +      I915_WRITE(GEN6_PMIIR, I915_READ(GEN6_PMIIR));
 +
 +      if (dev_priv->vlv_pctx) {
 +              drm_gem_object_unreference(&dev_priv->vlv_pctx->base);
 +              dev_priv->vlv_pctx = NULL;
 +      }
 +}
 +
  int intel_enable_rc6(const struct drm_device *dev)
  {
        /* Respect the kernel parameter if it is set */
@@@ -2765,7 -2639,7 +2765,7 @@@ static void gen6_enable_rps(struct drm_
                   (IS_HASWELL(dev) ? GEN7_RP_DOWN_IDLE_AVG : GEN6_RP_DOWN_IDLE_CONT));
  
        ret = sandybridge_pcode_write(dev_priv, GEN6_PCODE_WRITE_MIN_FREQ_TABLE, 0);
-       if (!ret && (IS_GEN6(dev) || IS_IVYBRIDGE(dev))) {
+       if (!ret) {
                pcu_mbox = 0;
                ret = sandybridge_pcode_read(dev_priv, GEN6_READ_OC_PARAMS, &pcu_mbox);
                if (!ret && (pcu_mbox & (1<<31))) { /* OC supported */
@@@ -2868,202 -2742,6 +2868,202 @@@ static void gen6_update_ring_freq(struc
        }
  }
  
 +int valleyview_rps_max_freq(struct drm_i915_private *dev_priv)
 +{
 +      u32 val, rp0;
 +
 +      valleyview_nc_read(dev_priv, IOSF_NC_FB_GFX_FREQ_FUSE, &val);
 +
 +      rp0 = (val & FB_GFX_MAX_FREQ_FUSE_MASK) >> FB_GFX_MAX_FREQ_FUSE_SHIFT;
 +      /* Clamp to max */
 +      rp0 = min_t(u32, rp0, 0xea);
 +
 +      return rp0;
 +}
 +
 +static int valleyview_rps_rpe_freq(struct drm_i915_private *dev_priv)
 +{
 +      u32 val, rpe;
 +
 +      valleyview_nc_read(dev_priv, IOSF_NC_FB_GFX_FMAX_FUSE_LO, &val);
 +      rpe = (val & FB_FMAX_VMIN_FREQ_LO_MASK) >> FB_FMAX_VMIN_FREQ_LO_SHIFT;
 +      valleyview_nc_read(dev_priv, IOSF_NC_FB_GFX_FMAX_FUSE_HI, &val);
 +      rpe |= (val & FB_FMAX_VMIN_FREQ_HI_MASK) << 5;
 +
 +      return rpe;
 +}
 +
 +int valleyview_rps_min_freq(struct drm_i915_private *dev_priv)
 +{
 +      u32 val;
 +
 +      valleyview_punit_read(dev_priv, PUNIT_REG_GPU_LFM, &val);
 +
 +      return val & 0xff;
 +}
 +
 +static void vlv_rps_timer_work(struct work_struct *work)
 +{
 +      drm_i915_private_t *dev_priv = container_of(work, drm_i915_private_t,
 +                                                  rps.vlv_work.work);
 +
 +      /*
 +       * Timer fired, we must be idle.  Drop to min voltage state.
 +       * Note: we use RPe here since it should match the
 +       * Vmin we were shooting for.  That should give us better
 +       * perf when we come back out of RC6 than if we used the
 +       * min freq available.
 +       */
 +      mutex_lock(&dev_priv->rps.hw_lock);
 +      valleyview_set_rps(dev_priv->dev, dev_priv->rps.rpe_delay);
 +      mutex_unlock(&dev_priv->rps.hw_lock);
 +}
 +
 +static void valleyview_setup_pctx(struct drm_device *dev)
 +{
 +      struct drm_i915_private *dev_priv = dev->dev_private;
 +      struct drm_i915_gem_object *pctx;
 +      unsigned long pctx_paddr;
 +      u32 pcbr;
 +      int pctx_size = 24*1024;
 +
 +      pcbr = I915_READ(VLV_PCBR);
 +      if (pcbr) {
 +              /* BIOS set it up already, grab the pre-alloc'd space */
 +              int pcbr_offset;
 +
 +              pcbr_offset = (pcbr & (~4095)) - dev_priv->mm.stolen_base;
 +              pctx = i915_gem_object_create_stolen_for_preallocated(dev_priv->dev,
 +                                                                    pcbr_offset,
 +                                                                    -1,
 +                                                                    pctx_size);
 +              goto out;
 +      }
 +
 +      /*
 +       * From the Gunit register HAS:
 +       * The Gfx driver is expected to program this register and ensure
 +       * proper allocation within Gfx stolen memory.  For example, this
 +       * register should be programmed such than the PCBR range does not
 +       * overlap with other ranges, such as the frame buffer, protected
 +       * memory, or any other relevant ranges.
 +       */
 +      pctx = i915_gem_object_create_stolen(dev, pctx_size);
 +      if (!pctx) {
 +              DRM_DEBUG("not enough stolen space for PCTX, disabling\n");
 +              return;
 +      }
 +
 +      pctx_paddr = dev_priv->mm.stolen_base + pctx->stolen->start;
 +      I915_WRITE(VLV_PCBR, pctx_paddr);
 +
 +out:
 +      dev_priv->vlv_pctx = pctx;
 +}
 +
 +static void valleyview_enable_rps(struct drm_device *dev)
 +{
 +      struct drm_i915_private *dev_priv = dev->dev_private;
 +      struct intel_ring_buffer *ring;
 +      u32 gtfifodbg, val, rpe;
 +      int i;
 +
 +      WARN_ON(!mutex_is_locked(&dev_priv->rps.hw_lock));
 +
 +      if ((gtfifodbg = I915_READ(GTFIFODBG))) {
 +              DRM_ERROR("GT fifo had a previous error %x\n", gtfifodbg);
 +              I915_WRITE(GTFIFODBG, gtfifodbg);
 +      }
 +
 +      valleyview_setup_pctx(dev);
 +
 +      gen6_gt_force_wake_get(dev_priv);
 +
 +      I915_WRITE(GEN6_RP_UP_THRESHOLD, 59400);
 +      I915_WRITE(GEN6_RP_DOWN_THRESHOLD, 245000);
 +      I915_WRITE(GEN6_RP_UP_EI, 66000);
 +      I915_WRITE(GEN6_RP_DOWN_EI, 350000);
 +
 +      I915_WRITE(GEN6_RP_IDLE_HYSTERSIS, 10);
 +
 +      I915_WRITE(GEN6_RP_CONTROL,
 +                 GEN6_RP_MEDIA_TURBO |
 +                 GEN6_RP_MEDIA_HW_NORMAL_MODE |
 +                 GEN6_RP_MEDIA_IS_GFX |
 +                 GEN6_RP_ENABLE |
 +                 GEN6_RP_UP_BUSY_AVG |
 +                 GEN6_RP_DOWN_IDLE_CONT);
 +
 +      I915_WRITE(GEN6_RC6_WAKE_RATE_LIMIT, 0x00280000);
 +      I915_WRITE(GEN6_RC_EVALUATION_INTERVAL, 125000);
 +      I915_WRITE(GEN6_RC_IDLE_HYSTERSIS, 25);
 +
 +      for_each_ring(ring, dev_priv, i)
 +              I915_WRITE(RING_MAX_IDLE(ring->mmio_base), 10);
 +
 +      I915_WRITE(GEN6_RC6_THRESHOLD, 0xc350);
 +
 +      /* allows RC6 residency counter to work */
 +      I915_WRITE(0x138104, _MASKED_BIT_ENABLE(0x3));
 +      I915_WRITE(GEN6_RC_CONTROL,
 +                 GEN7_RC_CTL_TO_MODE);
 +
 +      valleyview_punit_read(dev_priv, PUNIT_REG_GPU_FREQ_STS, &val);
 +      switch ((val >> 6) & 3) {
 +      case 0:
 +      case 1:
 +              dev_priv->mem_freq = 800;
 +              break;
 +      case 2:
 +              dev_priv->mem_freq = 1066;
 +              break;
 +      case 3:
 +              dev_priv->mem_freq = 1333;
 +              break;
 +      }
 +      DRM_DEBUG_DRIVER("DDR speed: %d MHz", dev_priv->mem_freq);
 +
 +      DRM_DEBUG_DRIVER("GPLL enabled? %s\n", val & 0x10 ? "yes" : "no");
 +      DRM_DEBUG_DRIVER("GPU status: 0x%08x\n", val);
 +
 +      DRM_DEBUG_DRIVER("current GPU freq: %d\n",
 +                       vlv_gpu_freq(dev_priv->mem_freq, (val >> 8) & 0xff));
 +      dev_priv->rps.cur_delay = (val >> 8) & 0xff;
 +
 +      dev_priv->rps.max_delay = valleyview_rps_max_freq(dev_priv);
 +      dev_priv->rps.hw_max = dev_priv->rps.max_delay;
 +      DRM_DEBUG_DRIVER("max GPU freq: %d\n", vlv_gpu_freq(dev_priv->mem_freq,
 +                                                   dev_priv->rps.max_delay));
 +
 +      rpe = valleyview_rps_rpe_freq(dev_priv);
 +      DRM_DEBUG_DRIVER("RPe GPU freq: %d\n",
 +                       vlv_gpu_freq(dev_priv->mem_freq, rpe));
 +      dev_priv->rps.rpe_delay = rpe;
 +
 +      val = valleyview_rps_min_freq(dev_priv);
 +      DRM_DEBUG_DRIVER("min GPU freq: %d\n", vlv_gpu_freq(dev_priv->mem_freq,
 +                                                          val));
 +      dev_priv->rps.min_delay = val;
 +
 +      DRM_DEBUG_DRIVER("setting GPU freq to %d\n",
 +                       vlv_gpu_freq(dev_priv->mem_freq, rpe));
 +
 +      INIT_DELAYED_WORK(&dev_priv->rps.vlv_work, vlv_rps_timer_work);
 +
 +      valleyview_set_rps(dev_priv->dev, rpe);
 +
 +      /* requires MSI enabled */
 +      I915_WRITE(GEN6_PMIER, GEN6_PM_DEFERRED_EVENTS);
 +      spin_lock_irq(&dev_priv->rps.lock);
 +      WARN_ON(dev_priv->rps.pm_iir != 0);
 +      I915_WRITE(GEN6_PMIMR, 0);
 +      spin_unlock_irq(&dev_priv->rps.lock);
 +      /* enable all PM interrupts */
 +      I915_WRITE(GEN6_PMINTRMSK, 0);
 +
 +      gen6_gt_force_wake_put(dev_priv);
 +}
 +
  void ironlake_teardown_rc6(struct drm_device *dev)
  {
        struct drm_i915_private *dev_priv = dev->dev_private;
@@@ -3787,22 -3465,13 +3787,22 @@@ void intel_disable_gt_powersave(struct 
  {
        struct drm_i915_private *dev_priv = dev->dev_private;
  
 +      /* Interrupts should be disabled already to avoid re-arming. */
 +      WARN_ON(dev->irq_enabled);
 +
        if (IS_IRONLAKE_M(dev)) {
                ironlake_disable_drps(dev);
                ironlake_disable_rc6(dev);
 -      } else if (INTEL_INFO(dev)->gen >= 6 && !IS_VALLEYVIEW(dev)) {
 +      } else if (INTEL_INFO(dev)->gen >= 6) {
                cancel_delayed_work_sync(&dev_priv->rps.delayed_resume_work);
 +              cancel_work_sync(&dev_priv->rps.work);
 +              if (IS_VALLEYVIEW(dev))
 +                      cancel_delayed_work_sync(&dev_priv->rps.vlv_work);
                mutex_lock(&dev_priv->rps.hw_lock);
 -              gen6_disable_rps(dev);
 +              if (IS_VALLEYVIEW(dev))
 +                      valleyview_disable_rps(dev);
 +              else
 +                      gen6_disable_rps(dev);
                mutex_unlock(&dev_priv->rps.hw_lock);
        }
  }
@@@ -3815,13 -3484,8 +3815,13 @@@ static void intel_gen6_powersave_work(s
        struct drm_device *dev = dev_priv->dev;
  
        mutex_lock(&dev_priv->rps.hw_lock);
 -      gen6_enable_rps(dev);
 -      gen6_update_ring_freq(dev);
 +
 +      if (IS_VALLEYVIEW(dev)) {
 +              valleyview_enable_rps(dev);
 +      } else {
 +              gen6_enable_rps(dev);
 +              gen6_update_ring_freq(dev);
 +      }
        mutex_unlock(&dev_priv->rps.hw_lock);
  }
  
@@@ -3833,7 -3497,7 +3833,7 @@@ void intel_enable_gt_powersave(struct d
                ironlake_enable_drps(dev);
                ironlake_enable_rc6(dev);
                intel_init_emon(dev);
 -      } else if ((IS_GEN6(dev) || IS_GEN7(dev)) && !IS_VALLEYVIEW(dev)) {
 +      } else if (IS_GEN6(dev) || IS_GEN7(dev)) {
                /*
                 * PCU communication is slow and this doesn't need to be
                 * done at any specific time, so do this out of our fast path
@@@ -3915,7 -3579,7 +3915,7 @@@ static void ironlake_init_clock_gating(
                   _3D_CHICKEN2_WM_READ_PIPELINED << 16 |
                   _3D_CHICKEN2_WM_READ_PIPELINED);
  
 -      /* WaDisableRenderCachePipelinedFlush */
 +      /* WaDisableRenderCachePipelinedFlush:ilk */
        I915_WRITE(CACHE_MODE_0,
                   _MASKED_BIT_ENABLE(CM0_PIPELINED_RENDER_FLUSH_DISABLE));
  
@@@ -3943,7 -3607,7 +3943,7 @@@ static void cpt_init_clock_gating(struc
                val = I915_READ(TRANS_CHICKEN2(pipe));
                val |= TRANS_CHICKEN2_TIMING_OVERRIDE;
                val &= ~TRANS_CHICKEN2_FDI_POLARITY_REVERSED;
 -              if (dev_priv->fdi_rx_polarity_inverted)
 +              if (dev_priv->vbt.fdi_rx_polarity_inverted)
                        val |= TRANS_CHICKEN2_FDI_POLARITY_REVERSED;
                val &= ~TRANS_CHICKEN2_FRAME_START_DELAY_MASK;
                val &= ~TRANS_CHICKEN2_DISABLE_DEEP_COLOR_COUNTER;
@@@ -3982,11 -3646,11 +3982,11 @@@ static void gen6_init_clock_gating(stru
                   I915_READ(ILK_DISPLAY_CHICKEN2) |
                   ILK_ELPIN_409_SELECT);
  
 -      /* WaDisableHiZPlanesWhenMSAAEnabled */
 +      /* WaDisableHiZPlanesWhenMSAAEnabled:snb */
        I915_WRITE(_3D_CHICKEN,
                   _MASKED_BIT_ENABLE(_3D_CHICKEN_HIZ_PLANE_DISABLE_MSAA_4X_SNB));
  
 -      /* WaSetupGtModeTdRowDispatch */
 +      /* WaSetupGtModeTdRowDispatch:snb */
        if (IS_SNB_GT1(dev))
                I915_WRITE(GEN6_GT_MODE,
                           _MASKED_BIT_ENABLE(GEN6_TD_FOUR_ROW_DISPATCH_DISABLE));
         * According to the spec, bit 11 (RCCUNIT) must also be set,
         * but we didn't debug actual testcases to find it out.
         *
 -       * Also apply WaDisableVDSUnitClockGating and
 -       * WaDisableRCPBUnitClockGating.
 +       * Also apply WaDisableVDSUnitClockGating:snb and
 +       * WaDisableRCPBUnitClockGating:snb.
         */
        I915_WRITE(GEN6_UCGCTL2,
                   GEN7_VDSUNIT_CLOCK_GATE_DISABLE |
                   ILK_DPARBUNIT_CLOCK_GATE_ENABLE  |
                   ILK_DPFDUNIT_CLOCK_GATE_ENABLE);
  
 -      /* WaMbcDriverBootEnable */
 +      /* WaMbcDriverBootEnable:snb */
        I915_WRITE(GEN6_MBCTL, I915_READ(GEN6_MBCTL) |
                   GEN6_MBCTL_ENABLE_BOOT_FETCH);
  
@@@ -4075,6 -3739,7 +4075,6 @@@ static void gen7_setup_fixed_func_sched
        reg |= GEN7_FF_VS_SCHED_HW;
        reg |= GEN7_FF_DS_SCHED_HW;
  
 -      /* WaVSRefCountFullforceMissDisable */
        if (IS_HASWELL(dev_priv->dev))
                reg &= ~GEN7_FF_VS_REF_CNT_FFME;
  
@@@ -4093,23 -3758,6 +4093,23 @@@ static void lpt_init_clock_gating(struc
                I915_WRITE(SOUTH_DSPCLK_GATE_D,
                           I915_READ(SOUTH_DSPCLK_GATE_D) |
                           PCH_LP_PARTITION_LEVEL_DISABLE);
 +
 +      /* WADPOClockGatingDisable:hsw */
 +      I915_WRITE(_TRANSA_CHICKEN1,
 +                 I915_READ(_TRANSA_CHICKEN1) |
 +                 TRANS_CHICKEN1_DP0UNIT_GC_DISABLE);
 +}
 +
 +static void lpt_suspend_hw(struct drm_device *dev)
 +{
 +      struct drm_i915_private *dev_priv = dev->dev_private;
 +
 +      if (dev_priv->pch_id == INTEL_PCH_LPT_LP_DEVICE_ID_TYPE) {
 +              uint32_t val = I915_READ(SOUTH_DSPCLK_GATE_D);
 +
 +              val &= ~PCH_LP_PARTITION_LEVEL_DISABLE;
 +              I915_WRITE(SOUTH_DSPCLK_GATE_D, val);
 +      }
  }
  
  static void haswell_init_clock_gating(struct drm_device *dev)
        I915_WRITE(WM1_LP_ILK, 0);
  
        /* According to the spec, bit 13 (RCZUNIT) must be set on IVB.
 -       * This implements the WaDisableRCZUnitClockGating workaround.
 +       * This implements the WaDisableRCZUnitClockGating:hsw workaround.
         */
        I915_WRITE(GEN6_UCGCTL2, GEN6_RCZUNIT_CLOCK_GATE_DISABLE);
  
 -      /* Apply the WaDisableRHWOOptimizationForRenderHang workaround. */
 +      /* Apply the WaDisableRHWOOptimizationForRenderHang:hsw workaround. */
        I915_WRITE(GEN7_COMMON_SLICE_CHICKEN1,
                   GEN7_CSC1_RHWO_OPT_DISABLE_IN_RCC);
  
 -      /* WaApplyL3ControlAndL3ChickenMode requires those two on Ivy Bridge */
 +      /* WaApplyL3ControlAndL3ChickenMode:hsw */
        I915_WRITE(GEN7_L3CNTLREG1,
                        GEN7_WA_FOR_GEN7_L3_CONTROL);
        I915_WRITE(GEN7_L3_CHICKEN_MODE_REGISTER,
                        GEN7_WA_L3_CHICKEN_MODE);
  
 -      /* This is required by WaCatErrorRejectionIssue */
 +      /* This is required by WaCatErrorRejectionIssue:hsw */
        I915_WRITE(GEN7_SQ_CHICKEN_MBCUNIT_CONFIG,
                        I915_READ(GEN7_SQ_CHICKEN_MBCUNIT_CONFIG) |
                        GEN7_SQ_CHICKEN_MBCUNIT_SQINTMOB);
                intel_flush_display_plane(dev_priv, pipe);
        }
  
 +      /* WaVSRefCountFullforceMissDisable:hsw */
        gen7_setup_fixed_func_scheduler(dev_priv);
  
 -      /* WaDisable4x2SubspanOptimization */
 +      /* WaDisable4x2SubspanOptimization:hsw */
        I915_WRITE(CACHE_MODE_1,
                   _MASKED_BIT_ENABLE(PIXEL_SUBSPAN_COLLECT_OPT_DISABLE));
  
 -      /* WaMbcDriverBootEnable */
 +      /* WaMbcDriverBootEnable:hsw */
        I915_WRITE(GEN6_MBCTL, I915_READ(GEN6_MBCTL) |
                   GEN6_MBCTL_ENABLE_BOOT_FETCH);
  
 -      /* WaSwitchSolVfFArbitrationPriority */
 +      /* WaSwitchSolVfFArbitrationPriority:hsw */
        I915_WRITE(GAM_ECOCHK, I915_READ(GAM_ECOCHK) | HSW_ECOCHK_ARB_PRIO_SOL);
  
        /* XXX: This is a workaround for early silicon revisions and should be
@@@ -4186,16 -3833,16 +4186,16 @@@ static void ivybridge_init_clock_gating
  
        I915_WRITE(ILK_DSPCLK_GATE_D, ILK_VRHUNIT_CLOCK_GATE_DISABLE);
  
 -      /* WaDisableEarlyCull */
 +      /* WaDisableEarlyCull:ivb */
        I915_WRITE(_3D_CHICKEN3,
                   _MASKED_BIT_ENABLE(_3D_CHICKEN_SF_DISABLE_OBJEND_CULL));
  
 -      /* WaDisableBackToBackFlipFix */
 +      /* WaDisableBackToBackFlipFix:ivb */
        I915_WRITE(IVB_CHICKEN3,
                   CHICKEN3_DGMG_REQ_OUT_FIX_DISABLE |
                   CHICKEN3_DGMG_DONE_FIX_DISABLE);
  
 -      /* WaDisablePSDDualDispatchEnable */
 +      /* WaDisablePSDDualDispatchEnable:ivb */
        if (IS_IVB_GT1(dev))
                I915_WRITE(GEN7_HALF_SLICE_CHICKEN1,
                           _MASKED_BIT_ENABLE(GEN7_PSD_SINGLE_PORT_DISPATCH_ENABLE));
                I915_WRITE(GEN7_HALF_SLICE_CHICKEN1_GT2,
                           _MASKED_BIT_ENABLE(GEN7_PSD_SINGLE_PORT_DISPATCH_ENABLE));
  
 -      /* Apply the WaDisableRHWOOptimizationForRenderHang workaround. */
 +      /* Apply the WaDisableRHWOOptimizationForRenderHang:ivb workaround. */
        I915_WRITE(GEN7_COMMON_SLICE_CHICKEN1,
                   GEN7_CSC1_RHWO_OPT_DISABLE_IN_RCC);
  
 -      /* WaApplyL3ControlAndL3ChickenMode requires those two on Ivy Bridge */
 +      /* WaApplyL3ControlAndL3ChickenMode:ivb */
        I915_WRITE(GEN7_L3CNTLREG1,
                        GEN7_WA_FOR_GEN7_L3_CONTROL);
        I915_WRITE(GEN7_L3_CHICKEN_MODE_REGISTER,
                           _MASKED_BIT_ENABLE(DOP_CLOCK_GATING_DISABLE));
  
  
 -      /* WaForceL3Serialization */
 +      /* WaForceL3Serialization:ivb */
        I915_WRITE(GEN7_L3SQCREG4, I915_READ(GEN7_L3SQCREG4) &
                   ~L3SQ_URB_READ_CAM_MATCH_DISABLE);
  
         * but we didn't debug actual testcases to find it out.
         *
         * According to the spec, bit 13 (RCZUNIT) must be set on IVB.
 -       * This implements the WaDisableRCZUnitClockGating workaround.
 +       * This implements the WaDisableRCZUnitClockGating:ivb workaround.
         */
        I915_WRITE(GEN6_UCGCTL2,
                   GEN6_RCZUNIT_CLOCK_GATE_DISABLE |
                   GEN6_RCCUNIT_CLOCK_GATE_DISABLE);
  
 -      /* This is required by WaCatErrorRejectionIssue */
 +      /* This is required by WaCatErrorRejectionIssue:ivb */
        I915_WRITE(GEN7_SQ_CHICKEN_MBCUNIT_CONFIG,
                        I915_READ(GEN7_SQ_CHICKEN_MBCUNIT_CONFIG) |
                        GEN7_SQ_CHICKEN_MBCUNIT_SQINTMOB);
                intel_flush_display_plane(dev_priv, pipe);
        }
  
 -      /* WaMbcDriverBootEnable */
 +      /* WaMbcDriverBootEnable:ivb */
        I915_WRITE(GEN6_MBCTL, I915_READ(GEN6_MBCTL) |
                   GEN6_MBCTL_ENABLE_BOOT_FETCH);
  
 +      /* WaVSRefCountFullforceMissDisable:ivb */
        gen7_setup_fixed_func_scheduler(dev_priv);
  
 -      /* WaDisable4x2SubspanOptimization */
 +      /* WaDisable4x2SubspanOptimization:ivb */
        I915_WRITE(CACHE_MODE_1,
                   _MASKED_BIT_ENABLE(PIXEL_SUBSPAN_COLLECT_OPT_DISABLE));
  
@@@ -4286,46 -3932,46 +4286,46 @@@ static void valleyview_init_clock_gatin
  
        I915_WRITE(ILK_DSPCLK_GATE_D, ILK_VRHUNIT_CLOCK_GATE_DISABLE);
  
 -      /* WaDisableEarlyCull */
 +      /* WaDisableEarlyCull:vlv */
        I915_WRITE(_3D_CHICKEN3,
                   _MASKED_BIT_ENABLE(_3D_CHICKEN_SF_DISABLE_OBJEND_CULL));
  
 -      /* WaDisableBackToBackFlipFix */
 +      /* WaDisableBackToBackFlipFix:vlv */
        I915_WRITE(IVB_CHICKEN3,
                   CHICKEN3_DGMG_REQ_OUT_FIX_DISABLE |
                   CHICKEN3_DGMG_DONE_FIX_DISABLE);
  
 -      /* WaDisablePSDDualDispatchEnable */
 +      /* WaDisablePSDDualDispatchEnable:vlv */
        I915_WRITE(GEN7_HALF_SLICE_CHICKEN1,
                   _MASKED_BIT_ENABLE(GEN7_MAX_PS_THREAD_DEP |
                                      GEN7_PSD_SINGLE_PORT_DISPATCH_ENABLE));
  
 -      /* Apply the WaDisableRHWOOptimizationForRenderHang workaround. */
 +      /* Apply the WaDisableRHWOOptimizationForRenderHang:vlv workaround. */
        I915_WRITE(GEN7_COMMON_SLICE_CHICKEN1,
                   GEN7_CSC1_RHWO_OPT_DISABLE_IN_RCC);
  
 -      /* WaApplyL3ControlAndL3ChickenMode requires those two on Ivy Bridge */
 +      /* WaApplyL3ControlAndL3ChickenMode:vlv */
        I915_WRITE(GEN7_L3CNTLREG1, I915_READ(GEN7_L3CNTLREG1) | GEN7_L3AGDIS);
        I915_WRITE(GEN7_L3_CHICKEN_MODE_REGISTER, GEN7_WA_L3_CHICKEN_MODE);
  
 -      /* WaForceL3Serialization */
 +      /* WaForceL3Serialization:vlv */
        I915_WRITE(GEN7_L3SQCREG4, I915_READ(GEN7_L3SQCREG4) &
                   ~L3SQ_URB_READ_CAM_MATCH_DISABLE);
  
 -      /* WaDisableDopClockGating */
 +      /* WaDisableDopClockGating:vlv */
        I915_WRITE(GEN7_ROW_CHICKEN2,
                   _MASKED_BIT_ENABLE(DOP_CLOCK_GATING_DISABLE));
  
 -      /* WaForceL3Serialization */
 +      /* WaForceL3Serialization:vlv */
        I915_WRITE(GEN7_L3SQCREG4, I915_READ(GEN7_L3SQCREG4) &
                   ~L3SQ_URB_READ_CAM_MATCH_DISABLE);
  
 -      /* This is required by WaCatErrorRejectionIssue */
 +      /* This is required by WaCatErrorRejectionIssue:vlv */
        I915_WRITE(GEN7_SQ_CHICKEN_MBCUNIT_CONFIG,
                   I915_READ(GEN7_SQ_CHICKEN_MBCUNIT_CONFIG) |
                   GEN7_SQ_CHICKEN_MBCUNIT_SQINTMOB);
  
 -      /* WaMbcDriverBootEnable */
 +      /* WaMbcDriverBootEnable:vlv */
        I915_WRITE(GEN6_MBCTL, I915_READ(GEN6_MBCTL) |
                   GEN6_MBCTL_ENABLE_BOOT_FETCH);
  
         * but we didn't debug actual testcases to find it out.
         *
         * According to the spec, bit 13 (RCZUNIT) must be set on IVB.
 -       * This implements the WaDisableRCZUnitClockGating workaround.
 +       * This implements the WaDisableRCZUnitClockGating:vlv workaround.
         *
 -       * Also apply WaDisableVDSUnitClockGating and
 -       * WaDisableRCPBUnitClockGating.
 +       * Also apply WaDisableVDSUnitClockGating:vlv and
 +       * WaDisableRCPBUnitClockGating:vlv.
         */
        I915_WRITE(GEN6_UCGCTL2,
                   GEN7_VDSUNIT_CLOCK_GATE_DISABLE |
                   _MASKED_BIT_ENABLE(PIXEL_SUBSPAN_COLLECT_OPT_DISABLE));
  
        /*
 -       * WaDisableVLVClockGating_VBIIssue
 +       * WaDisableVLVClockGating_VBIIssue:vlv
         * Disable clock gating on th GCFG unit to prevent a delay
         * in the reporting of vblank events.
         */
@@@ -4464,42 -4110,20 +4464,42 @@@ void intel_init_clock_gating(struct drm
        dev_priv->display.init_clock_gating(dev);
  }
  
 +void intel_suspend_hw(struct drm_device *dev)
 +{
 +      if (HAS_PCH_LPT(dev))
 +              lpt_suspend_hw(dev);
 +}
 +
  /**
   * We should only use the power well if we explicitly asked the hardware to
   * enable it, so check if it's enabled and also check if we've requested it to
   * be enabled.
   */
 -bool intel_using_power_well(struct drm_device *dev)
 +bool intel_display_power_enabled(struct drm_device *dev,
 +                               enum intel_display_power_domain domain)
  {
        struct drm_i915_private *dev_priv = dev->dev_private;
  
 -      if (IS_HASWELL(dev))
 +      if (!HAS_POWER_WELL(dev))
 +              return true;
 +
 +      switch (domain) {
 +      case POWER_DOMAIN_PIPE_A:
 +      case POWER_DOMAIN_TRANSCODER_EDP:
 +              return true;
 +      case POWER_DOMAIN_PIPE_B:
 +      case POWER_DOMAIN_PIPE_C:
 +      case POWER_DOMAIN_PIPE_A_PANEL_FITTER:
 +      case POWER_DOMAIN_PIPE_B_PANEL_FITTER:
 +      case POWER_DOMAIN_PIPE_C_PANEL_FITTER:
 +      case POWER_DOMAIN_TRANSCODER_A:
 +      case POWER_DOMAIN_TRANSCODER_B:
 +      case POWER_DOMAIN_TRANSCODER_C:
                return I915_READ(HSW_PWR_WELL_DRIVER) ==
                       (HSW_PWR_WELL_ENABLE | HSW_PWR_WELL_STATE);
 -      else
 -              return true;
 +      default:
 +              BUG();
 +      }
  }
  
  void intel_set_power_well(struct drm_device *dev, bool enable)
@@@ -4566,12 -4190,7 +4566,12 @@@ void intel_init_pm(struct drm_device *d
        if (I915_HAS_FBC(dev)) {
                if (HAS_PCH_SPLIT(dev)) {
                        dev_priv->display.fbc_enabled = ironlake_fbc_enabled;
 -                      dev_priv->display.enable_fbc = ironlake_enable_fbc;
 +                      if (IS_IVYBRIDGE(dev) || IS_HASWELL(dev))
 +                              dev_priv->display.enable_fbc =
 +                                      gen7_enable_fbc;
 +                      else
 +                              dev_priv->display.enable_fbc =
 +                                      ironlake_enable_fbc;
                        dev_priv->display.disable_fbc = ironlake_disable_fbc;
                } else if (IS_GM45(dev)) {
                        dev_priv->display.fbc_enabled = g4x_fbc_enabled;
@@@ -4721,7 -4340,6 +4721,7 @@@ static void __gen6_gt_force_wake_get(st
                            FORCEWAKE_ACK_TIMEOUT_MS))
                DRM_ERROR("Timed out waiting for forcewake to ack request.\n");
  
 +      /* WaRsForcewakeWaitTC0:snb */
        __gen6_gt_wait_for_thread_c0(dev_priv);
  }
  
@@@ -4753,7 -4371,6 +4753,7 @@@ static void __gen6_gt_force_wake_mt_get
                            FORCEWAKE_ACK_TIMEOUT_MS))
                DRM_ERROR("Timed out waiting for forcewake to ack request.\n");
  
 +      /* WaRsForcewakeWaitTC0:ivb,hsw */
        __gen6_gt_wait_for_thread_c0(dev_priv);
  }
  
@@@ -4857,7 -4474,6 +4857,7 @@@ static void vlv_force_wake_get(struct d
                            FORCEWAKE_ACK_TIMEOUT_MS))
                DRM_ERROR("Timed out waiting for media to ack forcewake request.\n");
  
 +      /* WaRsForcewakeWaitTC0:vlv */
        __gen6_gt_wait_for_thread_c0(dev_priv);
  }
  
@@@ -4952,13 -4568,14 +4952,13 @@@ int sandybridge_pcode_write(struct drm_
        return 0;
  }
  
 -static int vlv_punit_rw(struct drm_i915_private *dev_priv, u8 opcode,
 +static int vlv_punit_rw(struct drm_i915_private *dev_priv, u32 port, u8 opcode,
                        u8 addr, u32 *val)
  {
 -      u32 cmd, devfn, port, be, bar;
 +      u32 cmd, devfn, be, bar;
  
        bar = 0;
        be = 0xf;
 -      port = IOSF_PORT_PUNIT;
        devfn = PCI_DEVFN(2, 0);
  
        cmd = (devfn << IOSF_DEVFN_SHIFT) | (opcode << IOSF_OPCODE_SHIFT) |
        I915_WRITE(VLV_IOSF_DOORBELL_REQ, cmd);
  
        if (wait_for((I915_READ(VLV_IOSF_DOORBELL_REQ) & IOSF_SB_BUSY) == 0,
 -                   500)) {
 +                   5)) {
                DRM_ERROR("timeout waiting for pcode %s (%d) to finish\n",
                          opcode == PUNIT_OPCODE_REG_READ ? "read" : "write",
                          addr);
  
  int valleyview_punit_read(struct drm_i915_private *dev_priv, u8 addr, u32 *val)
  {
 -      return vlv_punit_rw(dev_priv, PUNIT_OPCODE_REG_READ, addr, val);
 +      return vlv_punit_rw(dev_priv, IOSF_PORT_PUNIT, PUNIT_OPCODE_REG_READ,
 +                          addr, val);
  }
  
  int valleyview_punit_write(struct drm_i915_private *dev_priv, u8 addr, u32 val)
  {
 -      return vlv_punit_rw(dev_priv, PUNIT_OPCODE_REG_WRITE, addr, &val);
 +      return vlv_punit_rw(dev_priv, IOSF_PORT_PUNIT, PUNIT_OPCODE_REG_WRITE,
 +                          addr, &val);
 +}
 +
 +int valleyview_nc_read(struct drm_i915_private *dev_priv, u8 addr, u32 *val)
 +{
 +      return vlv_punit_rw(dev_priv, IOSF_PORT_NC, PUNIT_OPCODE_REG_READ,
 +                          addr, val);
 +}
 +
 +int vlv_gpu_freq(int ddr_freq, int val)
 +{
 +      int mult, base;
 +
 +      switch (ddr_freq) {
 +      case 800:
 +              mult = 20;
 +              base = 120;
 +              break;
 +      case 1066:
 +              mult = 22;
 +              base = 133;
 +              break;
 +      case 1333:
 +              mult = 21;
 +              base = 125;
 +              break;
 +      default:
 +              return -1;
 +      }
 +
 +      return ((val - 0xbd) * mult) + base;
  }
 +
 +int vlv_freq_opcode(int ddr_freq, int val)
 +{
 +      int mult, base;
 +
 +      switch (ddr_freq) {
 +      case 800:
 +              mult = 20;
 +              base = 120;
 +              break;
 +      case 1066:
 +              mult = 22;
 +              base = 133;
 +              break;
 +      case 1333:
 +              mult = 21;
 +              base = 125;
 +              break;
 +      default:
 +              return -1;
 +      }
 +
 +      val /= mult;
 +      val -= base / mult;
 +      val += 0xbd;
 +
 +      if (val > 0xea)
 +              val = 0xea;
 +
 +      return val;
 +}
 +
index 2f54dc3dc5df4793c0f1e3507c03ada3178d3db3,d15428404b9a22cd5cf20566777dd4785d5f9f90..78f0631b1c43ae33cf5259ea1672efdc0d5af484
@@@ -1041,32 -1041,6 +1041,32 @@@ intel_sdvo_get_preferred_input_mode(str
        return true;
  }
  
 +static void i9xx_adjust_sdvo_tv_clock(struct intel_crtc_config *pipe_config)
 +{
 +      unsigned dotclock = pipe_config->adjusted_mode.clock;
 +      struct dpll *clock = &pipe_config->dpll;
 +
 +      /* SDVO TV has fixed PLL values depend on its clock range,
 +         this mirrors vbios setting. */
 +      if (dotclock >= 100000 && dotclock < 140500) {
 +              clock->p1 = 2;
 +              clock->p2 = 10;
 +              clock->n = 3;
 +              clock->m1 = 16;
 +              clock->m2 = 8;
 +      } else if (dotclock >= 140500 && dotclock <= 200000) {
 +              clock->p1 = 1;
 +              clock->p2 = 10;
 +              clock->n = 6;
 +              clock->m1 = 12;
 +              clock->m2 = 8;
 +      } else {
 +              WARN(1, "SDVO TV clock out of range: %i\n", dotclock);
 +      }
 +
 +      pipe_config->clock_set = true;
 +}
 +
  static bool intel_sdvo_compute_config(struct intel_encoder *encoder,
                                      struct intel_crtc_config *pipe_config)
  {
                (void) intel_sdvo_get_preferred_input_mode(intel_sdvo,
                                                           mode,
                                                           adjusted_mode);
 +              pipe_config->sdvo_tv_clock = true;
        } else if (intel_sdvo->is_lvds) {
                if (!intel_sdvo_set_output_timings_from_mode(intel_sdvo,
                                                             intel_sdvo->sdvo_lvds_fixed_mode))
        if (intel_sdvo->color_range)
                pipe_config->limited_color_range = true;
  
 +      /* Clock computation needs to happen after pixel multiplier. */
 +      if (intel_sdvo->is_tv)
 +              i9xx_adjust_sdvo_tv_clock(pipe_config);
 +
        return true;
  }
  
@@@ -1526,7 -1495,7 +1526,7 @@@ intel_sdvo_get_analog_edid(struct drm_c
  
        return drm_get_edid(connector,
                            intel_gmbus_get_adapter(dev_priv,
 -                                                  dev_priv->crt_ddc_pin));
 +                                                  dev_priv->vbt.crt_ddc_pin));
  }
  
  static enum drm_connector_status
@@@ -1656,9 -1625,12 +1656,9 @@@ intel_sdvo_detect(struct drm_connector 
        if (ret == connector_status_connected) {
                intel_sdvo->is_tv = false;
                intel_sdvo->is_lvds = false;
 -              intel_sdvo->base.needs_tv_clock = false;
  
 -              if (response & SDVO_TV_MASK) {
 +              if (response & SDVO_TV_MASK)
                        intel_sdvo->is_tv = true;
 -                      intel_sdvo->base.needs_tv_clock = true;
 -              }
                if (response & SDVO_LVDS_MASK)
                        intel_sdvo->is_lvds = intel_sdvo->sdvo_lvds_fixed_mode != NULL;
        }
@@@ -1809,9 -1781,9 +1809,9 @@@ static void intel_sdvo_get_lvds_modes(s
                goto end;
  
        /* Fetch modes from VBT */
 -      if (dev_priv->sdvo_lvds_vbt_mode != NULL) {
 +      if (dev_priv->vbt.sdvo_lvds_vbt_mode != NULL) {
                newmode = drm_mode_duplicate(connector->dev,
 -                                           dev_priv->sdvo_lvds_vbt_mode);
 +                                           dev_priv->vbt.sdvo_lvds_vbt_mode);
                if (newmode != NULL) {
                        /* Guarantee the mode is preferred */
                        newmode->type = (DRM_MODE_TYPE_PREFERRED |
@@@ -1958,6 -1930,9 +1958,9 @@@ intel_sdvo_set_property(struct drm_conn
        }
  
        if (property == dev_priv->broadcast_rgb_property) {
+               bool old_auto = intel_sdvo->color_range_auto;
+               uint32_t old_range = intel_sdvo->color_range;
                switch (val) {
                case INTEL_BROADCAST_RGB_AUTO:
                        intel_sdvo->color_range_auto = true;
                default:
                        return -EINVAL;
                }
+               if (old_auto == intel_sdvo->color_range_auto &&
+                   old_range == intel_sdvo->color_range)
+                       return 0;
                goto done;
        }
  
@@@ -2347,6 -2327,7 +2355,6 @@@ intel_sdvo_tv_init(struct intel_sdvo *i
        intel_sdvo_connector->output_flag = type;
  
        intel_sdvo->is_tv = true;
 -      intel_sdvo->base.needs_tv_clock = true;
  
        intel_sdvo_connector_init(intel_sdvo_connector, intel_sdvo);
  
@@@ -2434,6 -2415,7 +2442,6 @@@ static boo
  intel_sdvo_output_setup(struct intel_sdvo *intel_sdvo, uint16_t flags)
  {
        intel_sdvo->is_tv = false;
 -      intel_sdvo->base.needs_tv_clock = false;
        intel_sdvo->is_lvds = false;
  
        /* SDVO requires XXX1 function may not exist unless it has XXX0 function.*/
This page took 0.324796 seconds and 4 git commands to generate.