]> git.karo-electronics.de Git - karo-tx-linux.git/commitdiff
Merge tag 'drm-intel-next-2013-06-18' of git://people.freedesktop.org/~danvet/drm...
authorDave Airlie <airlied@redhat.com>
Thu, 27 Jun 2013 23:50:34 +0000 (09:50 +1000)
committerDave Airlie <airlied@redhat.com>
Thu, 27 Jun 2013 23:50:34 +0000 (09:50 +1000)
Last 3.11 feature pull. I have a few odds bits and pieces and fixes in my
queue, I'll sort them out later on to see what's for 3.11-fixes and what's
for 3.12. But nothing to hold this here up imo.

Highlights:
- more hangcheck work from Mika and Chris to prepare for arb robustness
- trickle feed fixes from Ville
- first parts of the shared pch pll rework, with some basic hw state
  readout and cross-checking (this shuts up the confused pch pll refcount
  WARN that Linus just recently forwarded)
- Haswell audio power well support from Wang Xingchao (alsa bits acked by
  Takashi)
- some cleanups and asserts sprinkling around the plane/gamma enabling
  sequence from Ville
- more gtt refactoring from Ben
- clear up the adjusted->mode vs. pixel clock vs. port clock confusion
- 30bpp support, this time for real hopefully

* tag 'drm-intel-next-2013-06-18' of git://people.freedesktop.org/~danvet/drm-intel: (97 commits)
  drm/i915: remove a superflous semi-colon
  drm/i915: Kill useless "Enable panel fitter" comments
  drm/i915: Remove extra "ring" from error message
  drm/i915: simplify the reduced clock handling for pch plls
  drm/i915: stop killing pfit on i9xx
  drm/i915: explicitly set up PIPECONF (and gamma table) on haswell
  drm/i915: set up PIPECONF explicitly for i9xx/vlv platforms
  drm/i915: set up PIPECONF explicitly on ilk-ivb
  drm/i915: find guilty batch buffer on ring resets
  drm/i915: store ring hangcheck action
  drm/i915: add batch bo to i915_add_request()
  drm/i915: change i915_add_request to macro
  drm/i915: add i915_gem_context_get_hang_stats()
  drm/i915: add struct i915_ctx_hang_stats
  drm/i915: Try harder to disable trickle feed on VLV
  drm/i915: fix up pch pll enabling for pixel multipliers
  drm/i915: hw state readout and cross-checking for shared dplls
  drm/i915: WARN on lack of shared dpll
  drm/i915: split up intel_modeset_check_state
  drm/i915: extract readout_hw_state from setup_hw_state
  ...

Conflicts:
drivers/gpu/drm/i915/intel_display.c
drivers/gpu/drm/i915/intel_fb.c
drivers/gpu/drm/i915/intel_sdvo.c

1  2 
drivers/gpu/drm/i915/i915_dma.c
drivers/gpu/drm/i915/i915_drv.c
drivers/gpu/drm/i915/i915_drv.h
drivers/gpu/drm/i915/i915_gem.c
drivers/gpu/drm/i915/intel_display.c
drivers/gpu/drm/i915/intel_dp.c
drivers/gpu/drm/i915/intel_fb.c
drivers/gpu/drm/i915/intel_lvds.c
drivers/gpu/drm/i915/intel_sdvo.c

index c52d866dfdb0c0205ff291e701e049aacc42c3a1,8e628dc43a5fe901682b410e8d8dbb1e73bad006..adb319b53ecd4acb98e1ce35f599ea935ff83dce
@@@ -42,6 -42,7 +42,6 @@@
  #include <linux/vga_switcheroo.h>
  #include <linux/slab.h>
  #include <acpi/video.h>
 -#include <asm/pat.h>
  
  #define LP_RING(d) (&((struct drm_i915_private *)(d))->ring[RCS])
  
@@@ -1001,8 -1002,7 +1001,7 @@@ static int i915_getparam(struct drm_dev
                value = 1;
                break;
        default:
-               DRM_DEBUG_DRIVER("Unknown parameter %d\n",
-                                param->param);
+               DRM_DEBUG("Unknown parameter %d\n", param->param);
                return -EINVAL;
        }
  
@@@ -1401,6 -1401,29 +1400,6 @@@ void i915_master_destroy(struct drm_dev
        master->driver_priv = NULL;
  }
  
 -static void
 -i915_mtrr_setup(struct drm_i915_private *dev_priv, unsigned long base,
 -              unsigned long size)
 -{
 -      dev_priv->mm.gtt_mtrr = -1;
 -
 -#if defined(CONFIG_X86_PAT)
 -      if (cpu_has_pat)
 -              return;
 -#endif
 -
 -      /* Set up a WC MTRR for non-PAT systems.  This is more common than
 -       * one would think, because the kernel disables PAT on first
 -       * generation Core chips because WC PAT gets overridden by a UC
 -       * MTRR if present.  Even if a UC MTRR isn't present.
 -       */
 -      dev_priv->mm.gtt_mtrr = mtrr_add(base, size, MTRR_TYPE_WRCOMB, 1);
 -      if (dev_priv->mm.gtt_mtrr < 0) {
 -              DRM_INFO("MTRR allocation failed.  Graphics "
 -                       "performance may suffer.\n");
 -      }
 -}
 -
  static void i915_kick_out_firmware_fb(struct drm_i915_private *dev_priv)
  {
        struct apertures_struct *ap;
@@@ -1559,8 -1582,8 +1558,8 @@@ int i915_driver_load(struct drm_device 
                goto out_rmmap;
        }
  
 -      i915_mtrr_setup(dev_priv, dev_priv->gtt.mappable_base,
 -                      aperture_size);
 +      dev_priv->mm.gtt_mtrr = arch_phys_wc_add(dev_priv->gtt.mappable_base,
 +                                               aperture_size);
  
        /* The i915 workqueue is primarily used for batched retirement of
         * requests (and thus managing bo) once the task has been completed
        /* Start out suspended */
        dev_priv->mm.suspended = 1;
  
+       if (HAS_POWER_WELL(dev))
+               i915_init_power_well(dev);
        if (drm_core_check_feature(dev, DRIVER_MODESET)) {
                ret = i915_load_modeset_init(dev);
                if (ret < 0) {
@@@ -1665,7 -1691,12 +1667,7 @@@ out_gem_unload
        intel_teardown_mchbar(dev);
        destroy_workqueue(dev_priv->wq);
  out_mtrrfree:
 -      if (dev_priv->mm.gtt_mtrr >= 0) {
 -              mtrr_del(dev_priv->mm.gtt_mtrr,
 -                       dev_priv->gtt.mappable_base,
 -                       aperture_size);
 -              dev_priv->mm.gtt_mtrr = -1;
 -      }
 +      arch_phys_wc_del(dev_priv->mm.gtt_mtrr);
        io_mapping_free(dev_priv->gtt.mappable);
        dev_priv->gtt.gtt_remove(dev);
  out_rmmap:
@@@ -1684,6 -1715,9 +1686,9 @@@ int i915_driver_unload(struct drm_devic
  
        intel_gpu_ips_teardown();
  
+       if (HAS_POWER_WELL(dev))
+               i915_remove_power_well(dev);
        i915_teardown_sysfs(dev);
  
        if (dev_priv->mm.inactive_shrinker.shrink)
        cancel_delayed_work_sync(&dev_priv->mm.retire_work);
  
        io_mapping_free(dev_priv->gtt.mappable);
 -      if (dev_priv->mm.gtt_mtrr >= 0) {
 -              mtrr_del(dev_priv->mm.gtt_mtrr,
 -                       dev_priv->gtt.mappable_base,
 -                       dev_priv->gtt.mappable_end);
 -              dev_priv->mm.gtt_mtrr = -1;
 -      }
 +      arch_phys_wc_del(dev_priv->mm.gtt_mtrr);
  
        acpi_video_unregister();
  
@@@ -1775,7 -1814,7 +1780,7 @@@ int i915_driver_open(struct drm_device 
        struct drm_i915_file_private *file_priv;
  
        DRM_DEBUG_DRIVER("\n");
-       file_priv = kmalloc(sizeof(*file_priv), GFP_KERNEL);
+       file_priv = kzalloc(sizeof(*file_priv), GFP_KERNEL);
        if (!file_priv)
                return -ENOMEM;
  
index 59ff7456bd70f4dec18f3eb587f0b31498750cd5,c3e4f2915e5bce3a488da6fb6fbfac17f41b76ff..deaa32e8113bfa51cd9d49082b0cffa7166927ca
@@@ -376,64 -376,40 +376,64 @@@ static const struct pci_device_id pciid
        INTEL_VGA_DEVICE(0x016a, &intel_ivybridge_d_info), /* GT2 server */
        INTEL_VGA_DEVICE(0x0402, &intel_haswell_d_info), /* GT1 desktop */
        INTEL_VGA_DEVICE(0x0412, &intel_haswell_d_info), /* GT2 desktop */
 -      INTEL_VGA_DEVICE(0x0422, &intel_haswell_d_info), /* GT2 desktop */
 +      INTEL_VGA_DEVICE(0x0422, &intel_haswell_d_info), /* GT3 desktop */
        INTEL_VGA_DEVICE(0x040a, &intel_haswell_d_info), /* GT1 server */
        INTEL_VGA_DEVICE(0x041a, &intel_haswell_d_info), /* GT2 server */
 -      INTEL_VGA_DEVICE(0x042a, &intel_haswell_d_info), /* GT2 server */
 +      INTEL_VGA_DEVICE(0x042a, &intel_haswell_d_info), /* GT3 server */
        INTEL_VGA_DEVICE(0x0406, &intel_haswell_m_info), /* GT1 mobile */
        INTEL_VGA_DEVICE(0x0416, &intel_haswell_m_info), /* GT2 mobile */
        INTEL_VGA_DEVICE(0x0426, &intel_haswell_m_info), /* GT2 mobile */
 +      INTEL_VGA_DEVICE(0x040B, &intel_haswell_d_info), /* GT1 reserved */
 +      INTEL_VGA_DEVICE(0x041B, &intel_haswell_d_info), /* GT2 reserved */
 +      INTEL_VGA_DEVICE(0x042B, &intel_haswell_d_info), /* GT3 reserved */
 +      INTEL_VGA_DEVICE(0x040E, &intel_haswell_d_info), /* GT1 reserved */
 +      INTEL_VGA_DEVICE(0x041E, &intel_haswell_d_info), /* GT2 reserved */
 +      INTEL_VGA_DEVICE(0x042E, &intel_haswell_d_info), /* GT3 reserved */
        INTEL_VGA_DEVICE(0x0C02, &intel_haswell_d_info), /* SDV GT1 desktop */
        INTEL_VGA_DEVICE(0x0C12, &intel_haswell_d_info), /* SDV GT2 desktop */
 -      INTEL_VGA_DEVICE(0x0C22, &intel_haswell_d_info), /* SDV GT2 desktop */
 +      INTEL_VGA_DEVICE(0x0C22, &intel_haswell_d_info), /* SDV GT3 desktop */
        INTEL_VGA_DEVICE(0x0C0A, &intel_haswell_d_info), /* SDV GT1 server */
        INTEL_VGA_DEVICE(0x0C1A, &intel_haswell_d_info), /* SDV GT2 server */
 -      INTEL_VGA_DEVICE(0x0C2A, &intel_haswell_d_info), /* SDV GT2 server */
 +      INTEL_VGA_DEVICE(0x0C2A, &intel_haswell_d_info), /* SDV GT3 server */
        INTEL_VGA_DEVICE(0x0C06, &intel_haswell_m_info), /* SDV GT1 mobile */
        INTEL_VGA_DEVICE(0x0C16, &intel_haswell_m_info), /* SDV GT2 mobile */
 -      INTEL_VGA_DEVICE(0x0C26, &intel_haswell_m_info), /* SDV GT2 mobile */
 +      INTEL_VGA_DEVICE(0x0C26, &intel_haswell_m_info), /* SDV GT3 mobile */
 +      INTEL_VGA_DEVICE(0x0C0B, &intel_haswell_d_info), /* SDV GT1 reserved */
 +      INTEL_VGA_DEVICE(0x0C1B, &intel_haswell_d_info), /* SDV GT2 reserved */
 +      INTEL_VGA_DEVICE(0x0C2B, &intel_haswell_d_info), /* SDV GT3 reserved */
 +      INTEL_VGA_DEVICE(0x0C0E, &intel_haswell_d_info), /* SDV GT1 reserved */
 +      INTEL_VGA_DEVICE(0x0C1E, &intel_haswell_d_info), /* SDV GT2 reserved */
 +      INTEL_VGA_DEVICE(0x0C2E, &intel_haswell_d_info), /* SDV GT3 reserved */
        INTEL_VGA_DEVICE(0x0A02, &intel_haswell_d_info), /* ULT GT1 desktop */
        INTEL_VGA_DEVICE(0x0A12, &intel_haswell_d_info), /* ULT GT2 desktop */
 -      INTEL_VGA_DEVICE(0x0A22, &intel_haswell_d_info), /* ULT GT2 desktop */
 +      INTEL_VGA_DEVICE(0x0A22, &intel_haswell_d_info), /* ULT GT3 desktop */
        INTEL_VGA_DEVICE(0x0A0A, &intel_haswell_d_info), /* ULT GT1 server */
        INTEL_VGA_DEVICE(0x0A1A, &intel_haswell_d_info), /* ULT GT2 server */
 -      INTEL_VGA_DEVICE(0x0A2A, &intel_haswell_d_info), /* ULT GT2 server */
 +      INTEL_VGA_DEVICE(0x0A2A, &intel_haswell_d_info), /* ULT GT3 server */
        INTEL_VGA_DEVICE(0x0A06, &intel_haswell_m_info), /* ULT GT1 mobile */
        INTEL_VGA_DEVICE(0x0A16, &intel_haswell_m_info), /* ULT GT2 mobile */
 -      INTEL_VGA_DEVICE(0x0A26, &intel_haswell_m_info), /* ULT GT2 mobile */
 +      INTEL_VGA_DEVICE(0x0A26, &intel_haswell_m_info), /* ULT GT3 mobile */
 +      INTEL_VGA_DEVICE(0x0A0B, &intel_haswell_d_info), /* ULT GT1 reserved */
 +      INTEL_VGA_DEVICE(0x0A1B, &intel_haswell_d_info), /* ULT GT2 reserved */
 +      INTEL_VGA_DEVICE(0x0A2B, &intel_haswell_d_info), /* ULT GT3 reserved */
 +      INTEL_VGA_DEVICE(0x0A0E, &intel_haswell_m_info), /* ULT GT1 reserved */
 +      INTEL_VGA_DEVICE(0x0A1E, &intel_haswell_m_info), /* ULT GT2 reserved */
 +      INTEL_VGA_DEVICE(0x0A2E, &intel_haswell_m_info), /* ULT GT3 reserved */
        INTEL_VGA_DEVICE(0x0D02, &intel_haswell_d_info), /* CRW GT1 desktop */
        INTEL_VGA_DEVICE(0x0D12, &intel_haswell_d_info), /* CRW GT2 desktop */
 -      INTEL_VGA_DEVICE(0x0D22, &intel_haswell_d_info), /* CRW GT2 desktop */
 +      INTEL_VGA_DEVICE(0x0D22, &intel_haswell_d_info), /* CRW GT3 desktop */
        INTEL_VGA_DEVICE(0x0D0A, &intel_haswell_d_info), /* CRW GT1 server */
        INTEL_VGA_DEVICE(0x0D1A, &intel_haswell_d_info), /* CRW GT2 server */
 -      INTEL_VGA_DEVICE(0x0D2A, &intel_haswell_d_info), /* CRW GT2 server */
 +      INTEL_VGA_DEVICE(0x0D2A, &intel_haswell_d_info), /* CRW GT3 server */
        INTEL_VGA_DEVICE(0x0D06, &intel_haswell_m_info), /* CRW GT1 mobile */
        INTEL_VGA_DEVICE(0x0D16, &intel_haswell_m_info), /* CRW GT2 mobile */
 -      INTEL_VGA_DEVICE(0x0D26, &intel_haswell_m_info), /* CRW GT2 mobile */
 +      INTEL_VGA_DEVICE(0x0D26, &intel_haswell_m_info), /* CRW GT3 mobile */
 +      INTEL_VGA_DEVICE(0x0D0B, &intel_haswell_d_info), /* CRW GT1 reserved */
 +      INTEL_VGA_DEVICE(0x0D1B, &intel_haswell_d_info), /* CRW GT2 reserved */
 +      INTEL_VGA_DEVICE(0x0D2B, &intel_haswell_d_info), /* CRW GT3 reserved */
 +      INTEL_VGA_DEVICE(0x0D0E, &intel_haswell_d_info), /* CRW GT1 reserved */
 +      INTEL_VGA_DEVICE(0x0D1E, &intel_haswell_d_info), /* CRW GT2 reserved */
 +      INTEL_VGA_DEVICE(0x0D2E, &intel_haswell_d_info), /* CRW GT3 reserved */
        INTEL_VGA_DEVICE(0x0f30, &intel_valleyview_m_info),
        INTEL_VGA_DEVICE(0x0f31, &intel_valleyview_m_info),
        INTEL_VGA_DEVICE(0x0f32, &intel_valleyview_m_info),
@@@ -457,7 -433,6 +457,6 @@@ void intel_detect_pch(struct drm_devic
         */
        if (INTEL_INFO(dev)->num_pipes == 0) {
                dev_priv->pch_type = PCH_NOP;
-               dev_priv->num_pch_pll = 0;
                return;
        }
  
  
                        if (id == INTEL_PCH_IBX_DEVICE_ID_TYPE) {
                                dev_priv->pch_type = PCH_IBX;
-                               dev_priv->num_pch_pll = 2;
                                DRM_DEBUG_KMS("Found Ibex Peak PCH\n");
                                WARN_ON(!IS_GEN5(dev));
                        } else if (id == INTEL_PCH_CPT_DEVICE_ID_TYPE) {
                                dev_priv->pch_type = PCH_CPT;
-                               dev_priv->num_pch_pll = 2;
                                DRM_DEBUG_KMS("Found CougarPoint PCH\n");
                                WARN_ON(!(IS_GEN6(dev) || IS_IVYBRIDGE(dev)));
                        } else if (id == INTEL_PCH_PPT_DEVICE_ID_TYPE) {
                                /* PantherPoint is CPT compatible */
                                dev_priv->pch_type = PCH_CPT;
-                               dev_priv->num_pch_pll = 2;
                                DRM_DEBUG_KMS("Found PatherPoint PCH\n");
                                WARN_ON(!(IS_GEN6(dev) || IS_IVYBRIDGE(dev)));
                        } else if (id == INTEL_PCH_LPT_DEVICE_ID_TYPE) {
                                dev_priv->pch_type = PCH_LPT;
-                               dev_priv->num_pch_pll = 0;
                                DRM_DEBUG_KMS("Found LynxPoint PCH\n");
                                WARN_ON(!IS_HASWELL(dev));
                                WARN_ON(IS_ULT(dev));
                        } else if (id == INTEL_PCH_LPT_LP_DEVICE_ID_TYPE) {
                                dev_priv->pch_type = PCH_LPT;
-                               dev_priv->num_pch_pll = 0;
                                DRM_DEBUG_KMS("Found LynxPoint LP PCH\n");
                                WARN_ON(!IS_HASWELL(dev));
                                WARN_ON(!IS_ULT(dev));
                        }
-                       BUG_ON(dev_priv->num_pch_pll > I915_NUM_PLLS);
                }
                pci_dev_put(pch);
        }
@@@ -570,7 -539,7 +563,7 @@@ static int i915_drm_freeze(struct drm_d
        intel_opregion_fini(dev);
  
        console_lock();
-       intel_fbdev_set_suspend(dev, 1);
+       intel_fbdev_set_suspend(dev, FBINFO_STATE_SUSPENDED);
        console_unlock();
  
        return 0;
@@@ -614,7 -583,7 +607,7 @@@ void intel_console_resume(struct work_s
        struct drm_device *dev = dev_priv->dev;
  
        console_lock();
-       intel_fbdev_set_suspend(dev, 0);
+       intel_fbdev_set_suspend(dev, FBINFO_STATE_RUNNING);
        console_unlock();
  }
  
@@@ -683,7 -652,7 +676,7 @@@ static int __i915_drm_thaw(struct drm_d
         * path of resume if possible.
         */
        if (console_trylock()) {
-               intel_fbdev_set_suspend(dev, 0);
+               intel_fbdev_set_suspend(dev, FBINFO_STATE_RUNNING);
                console_unlock();
        } else {
                schedule_work(&dev_priv->console_resume_work);
index 359a2003086b2449f294db51dd2add657e34564d,4b5ee47b49955a8c7b08d0bedd936f837cce2667..9e1bf6dcbb2af8ece697e4d23861c7f5a3f62b1b
@@@ -132,15 -132,38 +132,38 @@@ enum hpd_pin 
        list_for_each_entry((intel_encoder), &(dev)->mode_config.encoder_list, base.head) \
                if ((intel_encoder)->base.crtc == (__crtc))
  
- struct intel_pch_pll {
+ struct drm_i915_private;
+ enum intel_dpll_id {
+       DPLL_ID_PRIVATE = -1, /* non-shared dpll in use */
+       /* real shared dpll ids must be >= 0 */
+       DPLL_ID_PCH_PLL_A,
+       DPLL_ID_PCH_PLL_B,
+ };
+ #define I915_NUM_PLLS 2
+ struct intel_dpll_hw_state {
+       uint32_t dpll;
+       uint32_t fp0;
+       uint32_t fp1;
+ };
+ struct intel_shared_dpll {
        int refcount; /* count of number of CRTCs sharing this PLL */
        int active; /* count of number of active CRTCs (i.e. DPMS on) */
        bool on; /* is the PLL actually active? Disabled during modeset */
-       int pll_reg;
-       int fp0_reg;
-       int fp1_reg;
+       const char *name;
+       /* should match the index in the dev_priv->shared_dplls array */
+       enum intel_dpll_id id;
+       struct intel_dpll_hw_state hw_state;
+       void (*enable)(struct drm_i915_private *dev_priv,
+                      struct intel_shared_dpll *pll);
+       void (*disable)(struct drm_i915_private *dev_priv,
+                       struct intel_shared_dpll *pll);
+       bool (*get_hw_state)(struct drm_i915_private *dev_priv,
+                            struct intel_shared_dpll *pll,
+                            struct intel_dpll_hw_state *hw_state);
  };
- #define I915_NUM_PLLS 2
  
  /* Used by dp and fdi links */
  struct intel_link_m_n {
@@@ -195,7 -218,6 +218,6 @@@ struct opregion_header
  struct opregion_acpi;
  struct opregion_swsci;
  struct opregion_asle;
- struct drm_i915_private;
  
  struct intel_opregion {
        struct opregion_header __iomem *header;
@@@ -306,6 -328,8 +328,8 @@@ struct drm_i915_error_state 
  
  struct intel_crtc_config;
  struct intel_crtc;
+ struct intel_limit;
+ struct dpll;
  
  struct drm_i915_display_funcs {
        bool (*fbc_enabled)(struct drm_device *dev);
        void (*disable_fbc)(struct drm_device *dev);
        int (*get_display_clock_speed)(struct drm_device *dev);
        int (*get_fifo_size)(struct drm_device *dev, int plane);
+       /**
+        * find_dpll() - Find the best values for the PLL
+        * @limit: limits for the PLL
+        * @crtc: current CRTC
+        * @target: target frequency in kHz
+        * @refclk: reference clock frequency in kHz
+        * @match_clock: if provided, @best_clock P divider must
+        *               match the P divider from @match_clock
+        *               used for LVDS downclocking
+        * @best_clock: best PLL values found
+        *
+        * Returns true on success, false on failure.
+        */
+       bool (*find_dpll)(const struct intel_limit *limit,
+                         struct drm_crtc *crtc,
+                         int target, int refclk,
+                         struct dpll *match_clock,
+                         struct dpll *best_clock);
        void (*update_wm)(struct drm_device *dev);
        void (*update_sprite_wm)(struct drm_device *dev, int pipe,
                                 uint32_t sprite_width, int pixel_size,
@@@ -466,6 -508,13 +508,13 @@@ struct i915_hw_ppgtt 
        void (*cleanup)(struct i915_hw_ppgtt *ppgtt);
  };
  
+ struct i915_ctx_hang_stats {
+       /* This context had batch pending when hang was declared */
+       unsigned batch_pending;
+       /* This context had batch active when hang was declared */
+       unsigned batch_active;
+ };
  
  /* This must match up with the value previously used for execbuf2.rsvd1. */
  #define DEFAULT_CONTEXT_ID 0
@@@ -476,6 -525,7 +525,7 @@@ struct i915_hw_context 
        struct drm_i915_file_private *file_priv;
        struct intel_ring_buffer *ring;
        struct drm_i915_gem_object *obj;
+       struct i915_ctx_hang_stats hang_stats;
  };
  
  enum no_fbc_reason {
@@@ -720,6 -770,15 +770,15 @@@ struct intel_ilk_power_mgmt 
        struct drm_i915_gem_object *renderctx;
  };
  
+ /* Power well structure for haswell */
+ struct i915_power_well {
+       struct drm_device *device;
+       spinlock_t lock;
+       /* power well enable/disable usage count */
+       int count;
+       int i915_request;
+ };
  struct i915_dri1_state {
        unsigned allow_batchbuffer : 1;
        u32 __iomem *gfx_hws_cpu_addr;
@@@ -842,7 -901,6 +901,6 @@@ struct i915_gpu_error 
  #define DRM_I915_HANGCHECK_PERIOD 1500 /* in ms */
  #define DRM_I915_HANGCHECK_JIFFIES msecs_to_jiffies(DRM_I915_HANGCHECK_PERIOD)
        struct timer_list hangcheck_timer;
-       int hangcheck_count;
  
        /* For reset and error_state handling. */
        spinlock_t lock;
@@@ -998,7 -1056,6 +1056,6 @@@ typedef struct drm_i915_private 
        u32 hpd_event_bits;
        struct timer_list hotplug_reenable_timer;
  
-       int num_pch_pll;
        int num_plane;
  
        unsigned long cfb_size;
        struct drm_crtc *pipe_to_crtc_mapping[3];
        wait_queue_head_t pending_flip_queue;
  
-       struct intel_pch_pll pch_plls[I915_NUM_PLLS];
+       int num_shared_dpll;
+       struct intel_shared_dpll shared_dplls[I915_NUM_PLLS];
        struct intel_ddi_plls ddi_plls;
  
        /* Reclocking support */
         * mchdev_lock in intel_pm.c */
        struct intel_ilk_power_mgmt ips;
  
+       /* Haswell power well */
+       struct i915_power_well power_well;
        enum no_fbc_reason no_fbc_reason;
  
        struct drm_mm_node *compressed_fb;
@@@ -1154,7 -1215,7 +1215,7 @@@ struct drm_i915_gem_object 
        struct drm_mm_node *gtt_space;
        /** Stolen memory for this object, instead of being backed by shmem. */
        struct drm_mm_node *stolen;
-       struct list_head gtt_list;
+       struct list_head global_list;
  
        /** This object's place on the active/inactive lists */
        struct list_head ring_list;
@@@ -1301,12 -1362,18 +1362,18 @@@ struct drm_i915_gem_request 
        /** GEM sequence number associated with this request. */
        uint32_t seqno;
  
-       /** Postion in the ringbuffer of the end of the request */
+       /** Position in the ringbuffer of the start of the request */
+       u32 head;
+       /** Position in the ringbuffer of the end of the request */
        u32 tail;
  
        /** Context related to this request */
        struct i915_hw_context *ctx;
  
+       /** Batch buffer related to this request if any */
+       struct drm_i915_gem_object *batch_obj;
        /** Time at which this request was emitted, in jiffies. */
        unsigned long emitted_jiffies;
  
@@@ -1324,6 -1391,8 +1391,8 @@@ struct drm_i915_file_private 
                struct list_head request_list;
        } mm;
        struct idr context_idr;
+       struct i915_ctx_hang_stats hang_stats;
  };
  
  #define INTEL_INFO(dev)       (((struct drm_i915_private *) (dev)->dev_private)->info)
@@@ -1660,6 -1729,7 +1729,7 @@@ i915_gem_object_unpin_fence(struct drm_
  {
        if (obj->fence_reg != I915_FENCE_REG_NONE) {
                struct drm_i915_private *dev_priv = obj->base.dev->dev_private;
+               WARN_ON(dev_priv->fence_regs[obj->fence_reg].pin_count <= 0);
                dev_priv->fence_regs[obj->fence_reg].pin_count--;
        }
  }
@@@ -1692,9 -1762,12 +1762,12 @@@ void i915_gem_init_swizzling(struct drm
  void i915_gem_cleanup_ringbuffer(struct drm_device *dev);
  int __must_check i915_gpu_idle(struct drm_device *dev);
  int __must_check i915_gem_idle(struct drm_device *dev);
- int i915_add_request(struct intel_ring_buffer *ring,
-                    struct drm_file *file,
-                    u32 *seqno);
+ int __i915_add_request(struct intel_ring_buffer *ring,
+                      struct drm_file *file,
+                      struct drm_i915_gem_object *batch_obj,
+                      u32 *seqno);
+ #define i915_add_request(ring, seqno) \
+       __i915_add_request(ring, NULL, NULL, seqno)
  int __must_check i915_wait_seqno(struct intel_ring_buffer *ring,
                                 uint32_t seqno);
  int i915_gem_fault(struct vm_area_struct *vma, struct vm_fault *vmf);
@@@ -1748,6 -1821,10 +1821,10 @@@ static inline void i915_gem_context_unr
        kref_put(&ctx->ref, i915_gem_context_free);
  }
  
+ struct i915_ctx_hang_stats * __must_check
+ i915_gem_context_get_hang_stats(struct intel_ring_buffer *ring,
+                               struct drm_file *file,
+                               u32 id);
  int i915_gem_context_create_ioctl(struct drm_device *dev, void *data,
                                  struct drm_file *file);
  int i915_gem_context_destroy_ioctl(struct drm_device *dev, void *data,
@@@ -2003,19 -2080,4 +2080,19 @@@ static inline void __user *to_user_ptr(
        return (void __user *)(uintptr_t)address;
  }
  
 +static inline unsigned long msecs_to_jiffies_timeout(const unsigned int m)
 +{
 +      unsigned long j = msecs_to_jiffies(m);
 +
 +      return min_t(unsigned long, MAX_JIFFY_OFFSET, j + 1);
 +}
 +
 +static inline unsigned long
 +timespec_to_jiffies_timeout(const struct timespec *value)
 +{
 +      unsigned long j = timespec_to_jiffies(value);
 +
 +      return min_t(unsigned long, MAX_JIFFY_OFFSET, j + 1);
 +}
 +
  #endif
index e5b6a92e710263767a2cdc82f23cf8204e19dcc4,9b20fbbfd338bc75f992055d2f1b0e5a59048191..a6178baccb56c60cbbae893e526f28037992cad3
@@@ -91,11 -91,14 +91,11 @@@ i915_gem_wait_for_error(struct i915_gpu
  {
        int ret;
  
 -#define EXIT_COND (!i915_reset_in_progress(error))
 +#define EXIT_COND (!i915_reset_in_progress(error) || \
 +                 i915_terminally_wedged(error))
        if (EXIT_COND)
                return 0;
  
 -      /* GPU is already declared terminally dead, give up. */
 -      if (i915_terminally_wedged(error))
 -              return -EIO;
 -
        /*
         * Only wait 10 seconds for the gpu reset to complete to avoid hanging
         * userspace. If it takes that long something really bad is going on and
@@@ -176,7 -179,7 +176,7 @@@ i915_gem_get_aperture_ioctl(struct drm_
  
        pinned = 0;
        mutex_lock(&dev->struct_mutex);
-       list_for_each_entry(obj, &dev_priv->mm.bound_list, gtt_list)
+       list_for_each_entry(obj, &dev_priv->mm.bound_list, global_list)
                if (obj->pin_count)
                        pinned += obj->gtt_space->size;
        mutex_unlock(&dev->struct_mutex);
@@@ -956,7 -959,7 +956,7 @@@ i915_gem_check_olr(struct intel_ring_bu
  
        ret = 0;
        if (seqno == ring->outstanding_lazy_request)
-               ret = i915_add_request(ring, NULL, NULL);
+               ret = i915_add_request(ring, NULL);
  
        return ret;
  }
@@@ -1000,7 -1003,7 +1000,7 @@@ static int __wait_seqno(struct intel_ri
                wait_forever = false;
        }
  
 -      timeout_jiffies = timespec_to_jiffies(&wait_time);
 +      timeout_jiffies = timespec_to_jiffies_timeout(&wait_time);
  
        if (WARN_ON(!ring->irq_get(ring)))
                return -ENODEV;
@@@ -1676,7 -1679,7 +1676,7 @@@ i915_gem_object_put_pages(struct drm_i9
        /* ->put_pages might need to allocate memory for the bit17 swizzle
         * array, hence protect them from being reaped by removing them from gtt
         * lists early. */
-       list_del(&obj->gtt_list);
+       list_del(&obj->global_list);
  
        ops->put_pages(obj);
        obj->pages = NULL;
@@@ -1696,7 -1699,7 +1696,7 @@@ __i915_gem_shrink(struct drm_i915_priva
  
        list_for_each_entry_safe(obj, next,
                                 &dev_priv->mm.unbound_list,
-                                gtt_list) {
+                                global_list) {
                if ((i915_gem_object_is_purgeable(obj) || !purgeable_only) &&
                    i915_gem_object_put_pages(obj) == 0) {
                        count += obj->base.size >> PAGE_SHIFT;
@@@ -1733,7 -1736,8 +1733,8 @@@ i915_gem_shrink_all(struct drm_i915_pri
  
        i915_gem_evict_everything(dev_priv->dev);
  
-       list_for_each_entry_safe(obj, next, &dev_priv->mm.unbound_list, gtt_list)
+       list_for_each_entry_safe(obj, next, &dev_priv->mm.unbound_list,
+                                global_list)
                i915_gem_object_put_pages(obj);
  }
  
@@@ -1858,7 -1862,7 +1859,7 @@@ i915_gem_object_get_pages(struct drm_i9
        if (ret)
                return ret;
  
-       list_add_tail(&obj->gtt_list, &dev_priv->mm.unbound_list);
+       list_add_tail(&obj->global_list, &dev_priv->mm.unbound_list);
        return 0;
  }
  
@@@ -1996,17 -2000,18 +1997,18 @@@ i915_gem_get_seqno(struct drm_device *d
        return 0;
  }
  
- int
i915_add_request(struct intel_ring_buffer *ring,
-                struct drm_file *file,
-                u32 *out_seqno)
+ int __i915_add_request(struct intel_ring_buffer *ring,
                     struct drm_file *file,
+                      struct drm_i915_gem_object *obj,
+                      u32 *out_seqno)
  {
        drm_i915_private_t *dev_priv = ring->dev->dev_private;
        struct drm_i915_gem_request *request;
-       u32 request_ring_position;
+       u32 request_ring_position, request_start;
        int was_empty;
        int ret;
  
+       request_start = intel_ring_get_tail(ring);
        /*
         * Emit any outstanding flushes - execbuf can fail to emit the flush
         * after having emitted the batchbuffer command. Hence we need to fix
  
        request->seqno = intel_ring_get_seqno(ring);
        request->ring = ring;
+       request->head = request_start;
        request->tail = request_ring_position;
        request->ctx = ring->last_context;
+       request->batch_obj = obj;
+       /* Whilst this request exists, batch_obj will be on the
+        * active_list, and so will hold the active reference. Only when this
+        * request is retired will the the batch_obj be moved onto the
+        * inactive_list and lose its active reference. Hence we do not need
+        * to explicitly hold another reference here.
+        */
  
        if (request->ctx)
                i915_gem_context_reference(request->ctx);
@@@ -2096,6 -2110,94 +2107,94 @@@ i915_gem_request_remove_from_client(str
        spin_unlock(&file_priv->mm.lock);
  }
  
+ static bool i915_head_inside_object(u32 acthd, struct drm_i915_gem_object *obj)
+ {
+       if (acthd >= obj->gtt_offset &&
+           acthd < obj->gtt_offset + obj->base.size)
+               return true;
+       return false;
+ }
+ static bool i915_head_inside_request(const u32 acthd_unmasked,
+                                    const u32 request_start,
+                                    const u32 request_end)
+ {
+       const u32 acthd = acthd_unmasked & HEAD_ADDR;
+       if (request_start < request_end) {
+               if (acthd >= request_start && acthd < request_end)
+                       return true;
+       } else if (request_start > request_end) {
+               if (acthd >= request_start || acthd < request_end)
+                       return true;
+       }
+       return false;
+ }
+ static bool i915_request_guilty(struct drm_i915_gem_request *request,
+                               const u32 acthd, bool *inside)
+ {
+       /* There is a possibility that unmasked head address
+        * pointing inside the ring, matches the batch_obj address range.
+        * However this is extremely unlikely.
+        */
+       if (request->batch_obj) {
+               if (i915_head_inside_object(acthd, request->batch_obj)) {
+                       *inside = true;
+                       return true;
+               }
+       }
+       if (i915_head_inside_request(acthd, request->head, request->tail)) {
+               *inside = false;
+               return true;
+       }
+       return false;
+ }
+ static void i915_set_reset_status(struct intel_ring_buffer *ring,
+                                 struct drm_i915_gem_request *request,
+                                 u32 acthd)
+ {
+       struct i915_ctx_hang_stats *hs = NULL;
+       bool inside, guilty;
+       /* Innocent until proven guilty */
+       guilty = false;
+       if (ring->hangcheck.action != wait &&
+           i915_request_guilty(request, acthd, &inside)) {
+               DRM_ERROR("%s hung %s bo (0x%x ctx %d) at 0x%x\n",
+                         ring->name,
+                         inside ? "inside" : "flushing",
+                         request->batch_obj ?
+                         request->batch_obj->gtt_offset : 0,
+                         request->ctx ? request->ctx->id : 0,
+                         acthd);
+               guilty = true;
+       }
+       /* If contexts are disabled or this is the default context, use
+        * file_priv->reset_state
+        */
+       if (request->ctx && request->ctx->id != DEFAULT_CONTEXT_ID)
+               hs = &request->ctx->hang_stats;
+       else if (request->file_priv)
+               hs = &request->file_priv->hang_stats;
+       if (hs) {
+               if (guilty)
+                       hs->batch_active++;
+               else
+                       hs->batch_pending++;
+       }
+ }
  static void i915_gem_free_request(struct drm_i915_gem_request *request)
  {
        list_del(&request->list);
  static void i915_gem_reset_ring_lists(struct drm_i915_private *dev_priv,
                                      struct intel_ring_buffer *ring)
  {
+       u32 completed_seqno;
+       u32 acthd;
+       acthd = intel_ring_get_active_head(ring);
+       completed_seqno = ring->get_seqno(ring, false);
        while (!list_empty(&ring->request_list)) {
                struct drm_i915_gem_request *request;
  
                                           struct drm_i915_gem_request,
                                           list);
  
+               if (request->seqno > completed_seqno)
+                       i915_set_reset_status(ring, request, acthd);
                i915_gem_free_request(request);
        }
  
@@@ -2276,7 -2387,7 +2384,7 @@@ i915_gem_retire_work_handler(struct wor
        idle = true;
        for_each_ring(ring, dev_priv, i) {
                if (ring->gpu_caches_dirty)
-                       i915_add_request(ring, NULL, NULL);
+                       i915_add_request(ring, NULL);
  
                idle &= list_empty(&ring->request_list);
        }
@@@ -2508,9 -2619,10 +2616,10 @@@ i915_gem_object_unbind(struct drm_i915_
                obj->has_aliasing_ppgtt_mapping = 0;
        }
        i915_gem_gtt_finish_object(obj);
+       i915_gem_object_unpin_pages(obj);
  
        list_del(&obj->mm_list);
-       list_move_tail(&obj->gtt_list, &dev_priv->mm.unbound_list);
+       list_move_tail(&obj->global_list, &dev_priv->mm.unbound_list);
        /* Avoid an unnecessary call to unbind on rebind. */
        obj->map_and_fenceable = true;
  
@@@ -2918,7 -3030,7 +3027,7 @@@ static void i915_gem_verify_gtt(struct 
        struct drm_i915_gem_object *obj;
        int err = 0;
  
-       list_for_each_entry(obj, &dev_priv->mm.gtt_list, gtt_list) {
+       list_for_each_entry(obj, &dev_priv->mm.gtt_list, global_list) {
                if (obj->gtt_space == NULL) {
                        printk(KERN_ERR "object found on GTT list with no space reserved\n");
                        err++;
@@@ -3042,7 -3154,7 +3151,7 @@@ search_free
                return ret;
        }
  
-       list_move_tail(&obj->gtt_list, &dev_priv->mm.bound_list);
+       list_move_tail(&obj->global_list, &dev_priv->mm.bound_list);
        list_add_tail(&obj->mm_list, &dev_priv->mm.inactive_list);
  
        obj->gtt_space = node;
  
        obj->map_and_fenceable = mappable && fenceable;
  
-       i915_gem_object_unpin_pages(obj);
        trace_i915_gem_object_bind(obj, map_and_fenceable);
        i915_gem_verify_gtt(dev);
        return 0;
@@@ -3757,7 -3868,7 +3865,7 @@@ void i915_gem_object_init(struct drm_i9
                          const struct drm_i915_gem_object_ops *ops)
  {
        INIT_LIST_HEAD(&obj->mm_list);
-       INIT_LIST_HEAD(&obj->gtt_list);
+       INIT_LIST_HEAD(&obj->global_list);
        INIT_LIST_HEAD(&obj->ring_list);
        INIT_LIST_HEAD(&obj->exec_list);
  
@@@ -3857,7 -3968,13 +3965,13 @@@ void i915_gem_free_object(struct drm_ge
                dev_priv->mm.interruptible = was_interruptible;
        }
  
-       obj->pages_pin_count = 0;
+       /* Stolen objects don't hold a ref, but do hold pin count. Fix that up
+        * before progressing. */
+       if (obj->stolen)
+               i915_gem_object_unpin_pages(obj);
+       if (WARN_ON(obj->pages_pin_count))
+               obj->pages_pin_count = 0;
        i915_gem_object_put_pages(obj);
        i915_gem_object_free_mmap_offset(obj);
        i915_gem_object_release_stolen(obj);
@@@ -4498,10 -4615,10 +4612,10 @@@ i915_gem_inactive_shrink(struct shrinke
        }
  
        cnt = 0;
-       list_for_each_entry(obj, &dev_priv->mm.unbound_list, gtt_list)
+       list_for_each_entry(obj, &dev_priv->mm.unbound_list, global_list)
                if (obj->pages_pin_count == 0)
                        cnt += obj->base.size >> PAGE_SHIFT;
-       list_for_each_entry(obj, &dev_priv->mm.inactive_list, gtt_list)
+       list_for_each_entry(obj, &dev_priv->mm.inactive_list, global_list)
                if (obj->pin_count == 0 && obj->pages_pin_count == 0)
                        cnt += obj->base.size >> PAGE_SHIFT;
  
index 6eb99e13c37d03b86325e5e5a24fb70f0c2c1503,218bc938936e8fb3b6a77e7c3a822df0fed44185..b08d1f9ce0de77a9360b7263ff64bb09875548c0
@@@ -59,24 -59,6 +59,6 @@@ typedef struct intel_limit intel_limit_
  struct intel_limit {
        intel_range_t   dot, vco, n, m, m1, m2, p, p1;
        intel_p2_t          p2;
-       /**
-        * find_pll() - Find the best values for the PLL
-        * @limit: limits for the PLL
-        * @crtc: current CRTC
-        * @target: target frequency in kHz
-        * @refclk: reference clock frequency in kHz
-        * @match_clock: if provided, @best_clock P divider must
-        *               match the P divider from @match_clock
-        *               used for LVDS downclocking
-        * @best_clock: best PLL values found
-        *
-        * Returns true on success, false on failure.
-        */
-       bool (*find_pll)(const intel_limit_t *limit,
-                        struct drm_crtc *crtc,
-                        int target, int refclk,
-                        intel_clock_t *match_clock,
-                        intel_clock_t *best_clock);
  };
  
  /* FDI */
@@@ -92,20 -74,6 +74,6 @@@ intel_pch_rawclk(struct drm_device *dev
        return I915_READ(PCH_RAWCLK_FREQ) & RAWCLK_FREQ_MASK;
  }
  
- static bool
- intel_find_best_PLL(const intel_limit_t *limit, struct drm_crtc *crtc,
-                   int target, int refclk, intel_clock_t *match_clock,
-                   intel_clock_t *best_clock);
- static bool
- intel_g4x_find_best_PLL(const intel_limit_t *limit, 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,
-                       intel_clock_t *best_clock);
  static inline u32 /* units of 100MHz */
  intel_fdi_link_freq(struct drm_device *dev)
  {
@@@ -127,7 -95,6 +95,6 @@@ static const intel_limit_t intel_limits
        .p1 = { .min = 2, .max = 33 },
        .p2 = { .dot_limit = 165000,
                .p2_slow = 4, .p2_fast = 2 },
-       .find_pll = intel_find_best_PLL,
  };
  
  static const intel_limit_t intel_limits_i8xx_lvds = {
        .p1 = { .min = 1, .max = 6 },
        .p2 = { .dot_limit = 165000,
                .p2_slow = 14, .p2_fast = 7 },
-       .find_pll = intel_find_best_PLL,
  };
  
  static const intel_limit_t intel_limits_i9xx_sdvo = {
        .p1 = { .min = 1, .max = 8 },
        .p2 = { .dot_limit = 200000,
                .p2_slow = 10, .p2_fast = 5 },
-       .find_pll = intel_find_best_PLL,
  };
  
  static const intel_limit_t intel_limits_i9xx_lvds = {
        .p1 = { .min = 1, .max = 8 },
        .p2 = { .dot_limit = 112000,
                .p2_slow = 14, .p2_fast = 7 },
-       .find_pll = intel_find_best_PLL,
  };
  
  
@@@ -186,7 -150,6 +150,6 @@@ static const intel_limit_t intel_limits
                .p2_slow = 10,
                .p2_fast = 10
        },
-       .find_pll = intel_g4x_find_best_PLL,
  };
  
  static const intel_limit_t intel_limits_g4x_hdmi = {
        .p1 = { .min = 1, .max = 8},
        .p2 = { .dot_limit = 165000,
                .p2_slow = 10, .p2_fast = 5 },
-       .find_pll = intel_g4x_find_best_PLL,
  };
  
  static const intel_limit_t intel_limits_g4x_single_channel_lvds = {
        .p2 = { .dot_limit = 0,
                .p2_slow = 14, .p2_fast = 14
        },
-       .find_pll = intel_g4x_find_best_PLL,
  };
  
  static const intel_limit_t intel_limits_g4x_dual_channel_lvds = {
        .p2 = { .dot_limit = 0,
                .p2_slow = 7, .p2_fast = 7
        },
-       .find_pll = intel_g4x_find_best_PLL,
  };
  
  static const intel_limit_t intel_limits_pineview_sdvo = {
        .p1 = { .min = 1, .max = 8 },
        .p2 = { .dot_limit = 200000,
                .p2_slow = 10, .p2_fast = 5 },
-       .find_pll = intel_find_best_PLL,
  };
  
  static const intel_limit_t intel_limits_pineview_lvds = {
        .p1 = { .min = 1, .max = 8 },
        .p2 = { .dot_limit = 112000,
                .p2_slow = 14, .p2_fast = 14 },
-       .find_pll = intel_find_best_PLL,
  };
  
  /* Ironlake / Sandybridge
@@@ -279,7 -237,6 +237,6 @@@ static const intel_limit_t intel_limits
        .p1 = { .min = 1, .max = 8 },
        .p2 = { .dot_limit = 225000,
                .p2_slow = 10, .p2_fast = 5 },
-       .find_pll = intel_g4x_find_best_PLL,
  };
  
  static const intel_limit_t intel_limits_ironlake_single_lvds = {
        .p1 = { .min = 2, .max = 8 },
        .p2 = { .dot_limit = 225000,
                .p2_slow = 14, .p2_fast = 14 },
-       .find_pll = intel_g4x_find_best_PLL,
  };
  
  static const intel_limit_t intel_limits_ironlake_dual_lvds = {
        .p1 = { .min = 2, .max = 8 },
        .p2 = { .dot_limit = 225000,
                .p2_slow = 7, .p2_fast = 7 },
-       .find_pll = intel_g4x_find_best_PLL,
  };
  
  /* LVDS 100mhz refclk limits. */
@@@ -322,7 -277,6 +277,6 @@@ static const intel_limit_t intel_limits
        .p1 = { .min = 2, .max = 8 },
        .p2 = { .dot_limit = 225000,
                .p2_slow = 14, .p2_fast = 14 },
-       .find_pll = intel_g4x_find_best_PLL,
  };
  
  static const intel_limit_t intel_limits_ironlake_dual_lvds_100m = {
        .p1 = { .min = 2, .max = 6 },
        .p2 = { .dot_limit = 225000,
                .p2_slow = 7, .p2_fast = 7 },
-       .find_pll = intel_g4x_find_best_PLL,
  };
  
  static const intel_limit_t intel_limits_vlv_dac = {
        .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 = {
        .p1 = { .min = 2, .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_dp = {
        .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_ironlake_limit(struct drm_crtc *crtc,
@@@ -475,12 -425,8 +425,8 @@@ static uint32_t i9xx_dpll_compute_m(str
        return 5 * (dpll->m1 + 2) + (dpll->m2 + 2);
  }
  
- static void intel_clock(struct drm_device *dev, int refclk, intel_clock_t *clock)
+ static void i9xx_clock(int refclk, intel_clock_t *clock)
  {
-       if (IS_PINEVIEW(dev)) {
-               pineview_clock(refclk, clock);
-               return;
-       }
        clock->m = i9xx_dpll_compute_m(clock);
        clock->p = clock->p1 * clock->p2;
        clock->vco = refclk * clock->m / (clock->n + 2);
@@@ -538,10 -484,9 +484,9 @@@ static bool intel_PLL_is_valid(struct d
  }
  
  static bool
- intel_find_best_PLL(const intel_limit_t *limit, struct drm_crtc *crtc,
+ i9xx_find_best_dpll(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;
             clock.m1++) {
                for (clock.m2 = limit->m2.min;
                     clock.m2 <= limit->m2.max; clock.m2++) {
-                       /* m1 is always 0 in Pineview */
-                       if (clock.m2 >= clock.m1 && !IS_PINEVIEW(dev))
+                       if (clock.m2 >= clock.m1)
                                break;
                        for (clock.n = limit->n.min;
                             clock.n <= limit->n.max; clock.n++) {
                                        clock.p1 <= limit->p1.max; clock.p1++) {
                                        int this_err;
  
-                                       intel_clock(dev, refclk, &clock);
+                                       i9xx_clock(refclk, &clock);
+                                       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) {
+                                               *best_clock = clock;
+                                               err = this_err;
+                                       }
+                               }
+                       }
+               }
+       }
+       return (err != target);
+ }
+ static bool
+ pnv_find_best_dpll(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;
+       int err = target;
+       if (intel_pipe_has_type(crtc, INTEL_OUTPUT_LVDS)) {
+               /*
+                * For LVDS just rely on its current settings for dual-channel.
+                * We haven't figured out how to reliably set up different
+                * single/dual channel state, if we even can.
+                */
+               if (intel_is_dual_link_lvds(dev))
+                       clock.p2 = limit->p2.p2_fast;
+               else
+                       clock.p2 = limit->p2.p2_slow;
+       } else {
+               if (target < limit->p2.dot_limit)
+                       clock.p2 = limit->p2.p2_slow;
+               else
+                       clock.p2 = limit->p2.p2_fast;
+       }
+       memset(best_clock, 0, sizeof(*best_clock));
+       for (clock.m1 = limit->m1.min; clock.m1 <= limit->m1.max;
+            clock.m1++) {
+               for (clock.m2 = limit->m2.min;
+                    clock.m2 <= limit->m2.max; clock.m2++) {
+                       for (clock.n = limit->n.min;
+                            clock.n <= limit->n.max; clock.n++) {
+                               for (clock.p1 = limit->p1.min;
+                                       clock.p1 <= limit->p1.max; clock.p1++) {
+                                       int this_err;
+                                       pineview_clock(refclk, &clock);
                                        if (!intel_PLL_is_valid(dev, limit,
                                                                &clock))
                                                continue;
  }
  
  static bool
intel_g4x_find_best_PLL(const intel_limit_t *limit, struct drm_crtc *crtc,
-                       int target, int refclk, intel_clock_t *match_clock,
-                       intel_clock_t *best_clock)
g4x_find_best_dpll(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;
                                     clock.p1 >= limit->p1.min; clock.p1--) {
                                        int this_err;
  
-                                       intel_clock(dev, refclk, &clock);
+                                       i9xx_clock(refclk, &clock);
                                        if (!intel_PLL_is_valid(dev, limit,
                                                                &clock))
                                                continue;
  }
  
  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,
-                       intel_clock_t *best_clock)
vlv_find_best_dpll(const intel_limit_t *limit, struct drm_crtc *crtc,
+                  int target, int refclk, intel_clock_t *match_clock,
+                  intel_clock_t *best_clock)
  {
        u32 p1, p2, m1, m2, vco, bestn, bestm1, bestm2, bestp1, bestp2;
        u32 m, n, fastclk;
@@@ -906,14 -909,24 +909,24 @@@ static void assert_pll(struct drm_i915_
  #define assert_pll_enabled(d, p) assert_pll(d, p, true)
  #define assert_pll_disabled(d, p) assert_pll(d, p, false)
  
+ static struct intel_shared_dpll *
+ intel_crtc_to_shared_dpll(struct intel_crtc *crtc)
+ {
+       struct drm_i915_private *dev_priv = crtc->base.dev->dev_private;
+       if (crtc->config.shared_dpll < 0)
+               return NULL;
+       return &dev_priv->shared_dplls[crtc->config.shared_dpll];
+ }
  /* For ILK+ */
- static void assert_pch_pll(struct drm_i915_private *dev_priv,
-                          struct intel_pch_pll *pll,
-                          struct intel_crtc *crtc,
-                          bool state)
+ static void assert_shared_dpll(struct drm_i915_private *dev_priv,
+                              struct intel_shared_dpll *pll,
+                              bool state)
  {
-       u32 val;
        bool cur_state;
+       struct intel_dpll_hw_state hw_state;
  
        if (HAS_PCH_LPT(dev_priv->dev)) {
                DRM_DEBUG_DRIVER("LPT detected: skipping PCH PLL test\n");
        }
  
        if (WARN (!pll,
-                 "asserting PCH PLL %s with no PLL\n", state_string(state)))
+                 "asserting DPLL %s with no DPLL\n", state_string(state)))
                return;
  
-       val = I915_READ(pll->pll_reg);
-       cur_state = !!(val & DPLL_VCO_ENABLE);
+       cur_state = pll->get_hw_state(dev_priv, pll, &hw_state);
        WARN(cur_state != state,
-            "PCH PLL state for reg %x assertion failure (expected %s, current %s), val=%08x\n",
-            pll->pll_reg, state_string(state), state_string(cur_state), val);
-       /* Make sure the selected PLL is correctly attached to the transcoder */
-       if (crtc && HAS_PCH_CPT(dev_priv->dev)) {
-               u32 pch_dpll;
-               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 %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 %c: %08x\n",
-                            pll->pll_reg == _PCH_DPLL_B,
-                            state_string(state),
-                            pipe_name(crtc->pipe),
-                            val);
-               }
-       }
+            "%s assertion failure (expected %s, current %s)\n",
+            pll->name, state_string(state), state_string(cur_state));
  }
- #define assert_pch_pll_enabled(d, p, c) assert_pch_pll(d, p, c, true)
- #define assert_pch_pll_disabled(d, p, c) assert_pch_pll(d, p, c, false)
+ #define assert_shared_dpll_enabled(d, p) assert_shared_dpll(d, p, true)
+ #define assert_shared_dpll_disabled(d, p) assert_shared_dpll(d, p, false)
  
  static void assert_fdi_tx(struct drm_i915_private *dev_priv,
                          enum pipe pipe, bool state)
@@@ -1102,12 -1095,13 +1095,13 @@@ static void assert_plane(struct drm_i91
  static void assert_planes_disabled(struct drm_i915_private *dev_priv,
                                   enum pipe pipe)
  {
+       struct drm_device *dev = dev_priv->dev;
        int reg, i;
        u32 val;
        int cur_pipe;
  
-       /* Planes are fixed to pipes on ILK+ */
-       if (HAS_PCH_SPLIT(dev_priv->dev) || IS_VALLEYVIEW(dev_priv->dev)) {
+       /* Primary planes are fixed to pipes on gen4+ */
+       if (INTEL_INFO(dev)->gen >= 4) {
                reg = DSPCNTR(pipe);
                val = I915_READ(reg);
                WARN((val & DISPLAY_PLANE_ENABLE),
        }
  
        /* Need to check both planes against the pipe */
-       for (i = 0; i < 2; i++) {
+       for (i = 0; i < INTEL_INFO(dev)->num_pipes; i++) {
                reg = DSPCNTR(i);
                val = I915_READ(reg);
                cur_pipe = (val & DISPPLANE_SEL_PIPE_MASK) >>
  static void assert_sprites_disabled(struct drm_i915_private *dev_priv,
                                    enum pipe pipe)
  {
+       struct drm_device *dev = dev_priv->dev;
        int reg, i;
        u32 val;
  
-       if (!IS_VALLEYVIEW(dev_priv->dev))
-               return;
-       /* Need to check both planes against the pipe */
-       for (i = 0; i < dev_priv->num_plane; i++) {
-               reg = SPCNTR(pipe, i);
+       if (IS_VALLEYVIEW(dev)) {
+               for (i = 0; i < dev_priv->num_plane; i++) {
+                       reg = SPCNTR(pipe, i);
+                       val = I915_READ(reg);
+                       WARN((val & SP_ENABLE),
+                            "sprite %c assertion failure, should be off on pipe %c but is still active\n",
+                            sprite_name(pipe, i), pipe_name(pipe));
+               }
+       } else if (INTEL_INFO(dev)->gen >= 7) {
+               reg = SPRCTL(pipe);
                val = I915_READ(reg);
-               WARN((val & SP_ENABLE),
+               WARN((val & SPRITE_ENABLE),
                     "sprite %c assertion failure, should be off on pipe %c but is still active\n",
-                    sprite_name(pipe, i), pipe_name(pipe));
+                    plane_name(pipe), pipe_name(pipe));
+       } else if (INTEL_INFO(dev)->gen >= 5) {
+               reg = DVSCNTR(pipe);
+               val = I915_READ(reg);
+               WARN((val & DVS_ENABLE),
+                    "sprite %c assertion failure, should be off on pipe %c but is still active\n",
+                    plane_name(pipe), pipe_name(pipe));
        }
  }
  
@@@ -1382,94 -1387,71 +1387,71 @@@ void vlv_wait_port_ready(struct drm_i91
  }
  
  /**
-  * ironlake_enable_pch_pll - enable PCH PLL
+  * ironlake_enable_shared_dpll - enable PCH PLL
   * @dev_priv: i915 private structure
   * @pipe: pipe PLL to enable
   *
   * The PCH PLL needs to be enabled before the PCH transcoder, since it
   * drives the transcoder clock.
   */
- static void ironlake_enable_pch_pll(struct intel_crtc *intel_crtc)
+ static void ironlake_enable_shared_dpll(struct intel_crtc *crtc)
  {
-       struct drm_i915_private *dev_priv = intel_crtc->base.dev->dev_private;
-       struct intel_pch_pll *pll;
-       int reg;
-       u32 val;
+       struct drm_i915_private *dev_priv = crtc->base.dev->dev_private;
+       struct intel_shared_dpll *pll = intel_crtc_to_shared_dpll(crtc);
  
        /* PCH PLLs only available on ILK, SNB and IVB */
        BUG_ON(dev_priv->info->gen < 5);
-       pll = intel_crtc->pch_pll;
-       if (pll == NULL)
+       if (WARN_ON(pll == NULL))
                return;
  
        if (WARN_ON(pll->refcount == 0))
                return;
  
-       DRM_DEBUG_KMS("enable PCH PLL %x (active %d, on? %d)for crtc %d\n",
-                     pll->pll_reg, pll->active, pll->on,
-                     intel_crtc->base.base.id);
-       /* PCH refclock must be enabled first */
-       assert_pch_refclk_enabled(dev_priv);
+       DRM_DEBUG_KMS("enable %s (active %d, on? %d)for crtc %d\n",
+                     pll->name, pll->active, pll->on,
+                     crtc->base.base.id);
  
-       if (pll->active++ && pll->on) {
-               assert_pch_pll_enabled(dev_priv, pll, NULL);
+       if (pll->active++) {
+               WARN_ON(!pll->on);
+               assert_shared_dpll_enabled(dev_priv, pll);
                return;
        }
+       WARN_ON(pll->on);
  
-       DRM_DEBUG_KMS("enabling PCH PLL %x\n", pll->pll_reg);
-       reg = pll->pll_reg;
-       val = I915_READ(reg);
-       val |= DPLL_VCO_ENABLE;
-       I915_WRITE(reg, val);
-       POSTING_READ(reg);
-       udelay(200);
+       DRM_DEBUG_KMS("enabling %s\n", pll->name);
+       pll->enable(dev_priv, pll);
        pll->on = true;
  }
  
- static void intel_disable_pch_pll(struct intel_crtc *intel_crtc)
+ static void intel_disable_shared_dpll(struct intel_crtc *crtc)
  {
-       struct drm_i915_private *dev_priv = intel_crtc->base.dev->dev_private;
-       struct intel_pch_pll *pll = intel_crtc->pch_pll;
-       int reg;
-       u32 val;
+       struct drm_i915_private *dev_priv = crtc->base.dev->dev_private;
+       struct intel_shared_dpll *pll = intel_crtc_to_shared_dpll(crtc);
  
        /* PCH only available on ILK+ */
        BUG_ON(dev_priv->info->gen < 5);
-       if (pll == NULL)
+       if (WARN_ON(pll == NULL))
               return;
  
        if (WARN_ON(pll->refcount == 0))
                return;
  
-       DRM_DEBUG_KMS("disable PCH PLL %x (active %d, on? %d) for crtc %d\n",
-                     pll->pll_reg, pll->active, pll->on,
-                     intel_crtc->base.base.id);
+       DRM_DEBUG_KMS("disable %s (active %d, on? %d) for crtc %d\n",
+                     pll->name, pll->active, pll->on,
+                     crtc->base.base.id);
  
        if (WARN_ON(pll->active == 0)) {
-               assert_pch_pll_disabled(dev_priv, pll, NULL);
+               assert_shared_dpll_disabled(dev_priv, pll);
                return;
        }
  
-       if (--pll->active) {
-               assert_pch_pll_enabled(dev_priv, pll, NULL);
+       assert_shared_dpll_enabled(dev_priv, pll);
+       WARN_ON(!pll->on);
+       if (--pll->active)
                return;
-       }
-       DRM_DEBUG_KMS("disabling PCH PLL %x\n", pll->pll_reg);
-       /* Make sure transcoder isn't still depending on us */
-       assert_pch_transcoder_disabled(dev_priv, intel_crtc->pipe);
-       reg = pll->pll_reg;
-       val = I915_READ(reg);
-       val &= ~DPLL_VCO_ENABLE;
-       I915_WRITE(reg, val);
-       POSTING_READ(reg);
-       udelay(200);
  
+       DRM_DEBUG_KMS("disabling %s\n", pll->name);
+       pll->disable(dev_priv, pll);
        pll->on = false;
  }
  
@@@ -1478,15 -1460,15 +1460,15 @@@ static void ironlake_enable_pch_transco
  {
        struct drm_device *dev = dev_priv->dev;
        struct drm_crtc *crtc = dev_priv->pipe_to_crtc_mapping[pipe];
+       struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
        uint32_t reg, val, pipeconf_val;
  
        /* PCH only available on ILK+ */
        BUG_ON(dev_priv->info->gen < 5);
  
        /* Make sure PCH DPLL is enabled */
-       assert_pch_pll_enabled(dev_priv,
-                              to_intel_crtc(crtc)->pch_pll,
-                              to_intel_crtc(crtc));
+       assert_shared_dpll_enabled(dev_priv,
+                                  intel_crtc_to_shared_dpll(intel_crtc));
  
        /* FDI must be feeding us bits for PCH ports */
        assert_fdi_tx_enabled(dev_priv, pipe);
@@@ -1943,6 -1925,9 +1925,9 @@@ static int i9xx_update_plane(struct drm
                        dspcntr &= ~DISPPLANE_TILED;
        }
  
+       if (IS_G4X(dev))
+               dspcntr |= DISPPLANE_TRICKLE_FEED_DISABLE;
        I915_WRITE(reg, dspcntr);
  
        linear_offset = y * fb->pitches[0] + x * (fb->bits_per_pixel / 8);
@@@ -2212,7 -2197,8 +2197,8 @@@ intel_pipe_set_base(struct drm_crtc *cr
        crtc->y = y;
  
        if (old_fb) {
-               intel_wait_for_vblank(dev, intel_crtc->pipe);
+               if (intel_crtc->active && old_fb != fb)
+                       intel_wait_for_vblank(dev, intel_crtc->pipe);
                intel_unpin_fb_obj(to_intel_framebuffer(old_fb)->obj);
        }
  
@@@ -2945,31 -2931,18 +2931,18 @@@ static void ironlake_pch_enable(struct 
         * transcoder, and we actually should do this to not upset any PCH
         * transcoder that already use the clock when we share it.
         *
-        * Note that enable_pch_pll tries to do the right thing, but get_pch_pll
-        * unconditionally resets the pll - we need that to have the right LVDS
-        * enable sequence. */
-       ironlake_enable_pch_pll(intel_crtc);
+        * Note that enable_shared_dpll tries to do the right thing, but
+        * get_shared_dpll unconditionally resets the pll - we need that to have
+        * the right LVDS enable sequence. */
+       ironlake_enable_shared_dpll(intel_crtc);
  
        if (HAS_PCH_CPT(dev)) {
                u32 sel;
  
                temp = I915_READ(PCH_DPLL_SEL);
-               switch (pipe) {
-               default:
-               case 0:
-                       temp |= TRANSA_DPLL_ENABLE;
-                       sel = TRANSA_DPLLB_SEL;
-                       break;
-               case 1:
-                       temp |= TRANSB_DPLL_ENABLE;
-                       sel = TRANSB_DPLLB_SEL;
-                       break;
-               case 2:
-                       temp |= TRANSC_DPLL_ENABLE;
-                       sel = TRANSC_DPLLB_SEL;
-                       break;
-               }
-               if (intel_crtc->pch_pll->pll_reg == _PCH_DPLL_B)
+               temp |= TRANS_DPLL_ENABLE(pipe);
+               sel = TRANS_DPLLB_SEL(pipe);
+               if (intel_crtc->config.shared_dpll == DPLL_ID_PCH_PLL_B)
                        temp |= sel;
                else
                        temp &= ~sel;
@@@ -3038,69 -3011,72 +3011,72 @@@ static void lpt_pch_enable(struct drm_c
        lpt_enable_pch_transcoder(dev_priv, cpu_transcoder);
  }
  
- static void intel_put_pch_pll(struct intel_crtc *intel_crtc)
+ static void intel_put_shared_dpll(struct intel_crtc *crtc)
  {
-       struct intel_pch_pll *pll = intel_crtc->pch_pll;
+       struct intel_shared_dpll *pll = intel_crtc_to_shared_dpll(crtc);
  
        if (pll == NULL)
                return;
  
        if (pll->refcount == 0) {
-               WARN(1, "bad PCH PLL refcount\n");
+               WARN(1, "bad %s refcount\n", pll->name);
                return;
        }
  
-       --pll->refcount;
-       intel_crtc->pch_pll = NULL;
+       if (--pll->refcount == 0) {
+               WARN_ON(pll->on);
+               WARN_ON(pll->active);
+       }
+       crtc->config.shared_dpll = DPLL_ID_PRIVATE;
  }
  
- static struct intel_pch_pll *intel_get_pch_pll(struct intel_crtc *intel_crtc, u32 dpll, u32 fp)
+ static struct intel_shared_dpll *intel_get_shared_dpll(struct intel_crtc *crtc, u32 dpll, u32 fp)
  {
-       struct drm_i915_private *dev_priv = intel_crtc->base.dev->dev_private;
-       struct intel_pch_pll *pll;
-       int i;
+       struct drm_i915_private *dev_priv = crtc->base.dev->dev_private;
+       struct intel_shared_dpll *pll = intel_crtc_to_shared_dpll(crtc);
+       enum intel_dpll_id i;
  
-       pll = intel_crtc->pch_pll;
        if (pll) {
-               DRM_DEBUG_KMS("CRTC:%d reusing existing PCH PLL %x\n",
-                             intel_crtc->base.base.id, pll->pll_reg);
-               goto prepare;
+               DRM_DEBUG_KMS("CRTC:%d dropping existing %s\n",
+                             crtc->base.base.id, pll->name);
+               intel_put_shared_dpll(crtc);
        }
  
        if (HAS_PCH_IBX(dev_priv->dev)) {
                /* Ironlake PCH has a fixed PLL->PCH pipe mapping. */
-               i = intel_crtc->pipe;
-               pll = &dev_priv->pch_plls[i];
+               i = crtc->pipe;
+               pll = &dev_priv->shared_dplls[i];
  
-               DRM_DEBUG_KMS("CRTC:%d using pre-allocated PCH PLL %x\n",
-                             intel_crtc->base.base.id, pll->pll_reg);
+               DRM_DEBUG_KMS("CRTC:%d using pre-allocated %s\n",
+                             crtc->base.base.id, pll->name);
  
                goto found;
        }
  
-       for (i = 0; i < dev_priv->num_pch_pll; i++) {
-               pll = &dev_priv->pch_plls[i];
+       for (i = 0; i < dev_priv->num_shared_dpll; i++) {
+               pll = &dev_priv->shared_dplls[i];
  
                /* Only want to check enabled timings first */
                if (pll->refcount == 0)
                        continue;
  
-               if (dpll == (I915_READ(pll->pll_reg) & 0x7fffffff) &&
-                   fp == I915_READ(pll->fp0_reg)) {
-                       DRM_DEBUG_KMS("CRTC:%d sharing existing PCH PLL %x (refcount %d, ative %d)\n",
-                                     intel_crtc->base.base.id,
-                                     pll->pll_reg, pll->refcount, pll->active);
+               if (dpll == (I915_READ(PCH_DPLL(pll->id)) & 0x7fffffff) &&
+                   fp == I915_READ(PCH_FP0(pll->id))) {
+                       DRM_DEBUG_KMS("CRTC:%d sharing existing %s (refcount %d, ative %d)\n",
+                                     crtc->base.base.id,
+                                     pll->name, pll->refcount, pll->active);
  
                        goto found;
                }
        }
  
        /* Ok no matching timings, maybe there's a free one? */
-       for (i = 0; i < dev_priv->num_pch_pll; i++) {
-               pll = &dev_priv->pch_plls[i];
+       for (i = 0; i < dev_priv->num_shared_dpll; i++) {
+               pll = &dev_priv->shared_dplls[i];
                if (pll->refcount == 0) {
-                       DRM_DEBUG_KMS("CRTC:%d allocated PCH PLL %x\n",
-                                     intel_crtc->base.base.id, pll->pll_reg);
+                       DRM_DEBUG_KMS("CRTC:%d allocated %s\n",
+                                     crtc->base.base.id, pll->name);
                        goto found;
                }
        }
        return NULL;
  
  found:
-       intel_crtc->pch_pll = pll;
-       pll->refcount++;
-       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);
+       crtc->config.shared_dpll = i;
+       DRM_DEBUG_DRIVER("using %s for pipe %c\n", pll->name,
+                        pipe_name(crtc->pipe));
  
-       /* Wait for the clocks to stabilize before rewriting the regs */
-       I915_WRITE(pll->pll_reg, dpll & ~DPLL_VCO_ENABLE);
-       POSTING_READ(pll->pll_reg);
-       udelay(150);
+       if (pll->active == 0) {
+               memcpy(&pll->hw_state, &crtc->config.dpll_hw_state,
+                      sizeof(pll->hw_state));
+               DRM_DEBUG_DRIVER("setting up %s\n", pll->name);
+               WARN_ON(pll->on);
+               assert_shared_dpll_disabled(dev_priv, pll);
+               /* Wait for the clocks to stabilize before rewriting the regs */
+               I915_WRITE(PCH_DPLL(pll->id), dpll & ~DPLL_VCO_ENABLE);
+               POSTING_READ(PCH_DPLL(pll->id));
+               udelay(150);
+               I915_WRITE(PCH_FP0(pll->id), fp);
+               I915_WRITE(PCH_DPLL(pll->id), dpll & ~DPLL_VCO_ENABLE);
+       }
+       pll->refcount++;
  
-       I915_WRITE(pll->fp0_reg, fp);
-       I915_WRITE(pll->pll_reg, dpll & ~DPLL_VCO_ENABLE);
-       pll->on = false;
        return pll;
  }
  
@@@ -3160,6 -3144,28 +3144,28 @@@ static void ironlake_pfit_enable(struc
        }
  }
  
+ static void intel_enable_planes(struct drm_crtc *crtc)
+ {
+       struct drm_device *dev = crtc->dev;
+       enum pipe pipe = to_intel_crtc(crtc)->pipe;
+       struct intel_plane *intel_plane;
+       list_for_each_entry(intel_plane, &dev->mode_config.plane_list, base.head)
+               if (intel_plane->pipe == pipe)
+                       intel_plane_restore(&intel_plane->base);
+ }
+ static void intel_disable_planes(struct drm_crtc *crtc)
+ {
+       struct drm_device *dev = crtc->dev;
+       enum pipe pipe = to_intel_crtc(crtc)->pipe;
+       struct intel_plane *intel_plane;
+       list_for_each_entry(intel_plane, &dev->mode_config.plane_list, base.head)
+               if (intel_plane->pipe == pipe)
+                       intel_plane_disable(&intel_plane->base);
+ }
  static void ironlake_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 */
        ironlake_pfit_enable(intel_crtc);
  
        /*
        intel_enable_pipe(dev_priv, pipe,
                          intel_crtc->config.has_pch_encoder);
        intel_enable_plane(dev_priv, plane, pipe);
+       intel_enable_planes(crtc);
+       intel_crtc_update_cursor(crtc, true);
  
        if (intel_crtc->config.has_pch_encoder)
                ironlake_pch_enable(crtc);
        intel_update_fbc(dev);
        mutex_unlock(&dev->struct_mutex);
  
-       intel_crtc_update_cursor(crtc, true);
        for_each_encoder_on_crtc(dev, crtc, encoder)
                encoder->enable(encoder);
  
@@@ -3309,7 -3314,6 +3314,6 @@@ static void haswell_crtc_enable(struct 
  
        intel_ddi_enable_pipe_clock(intel_crtc);
  
-       /* Enable panel fitting for eDP */
        ironlake_pfit_enable(intel_crtc);
  
        /*
        intel_enable_pipe(dev_priv, pipe,
                          intel_crtc->config.has_pch_encoder);
        intel_enable_plane(dev_priv, plane, pipe);
+       intel_enable_planes(crtc);
+       intel_crtc_update_cursor(crtc, true);
  
        hsw_enable_ips(intel_crtc);
  
        intel_update_fbc(dev);
        mutex_unlock(&dev->struct_mutex);
  
-       intel_crtc_update_cursor(crtc, true);
        for_each_encoder_on_crtc(dev, crtc, encoder)
                encoder->enable(encoder);
  
@@@ -3384,14 -3388,17 +3388,17 @@@ static void ironlake_crtc_disable(struc
  
        intel_crtc_wait_for_pending_flips(crtc);
        drm_vblank_off(dev, pipe);
-       intel_crtc_update_cursor(crtc, false);
-       intel_disable_plane(dev_priv, plane, pipe);
  
        if (dev_priv->cfb_plane == plane)
                intel_disable_fbc(dev);
  
-       intel_set_pch_fifo_underrun_reporting(dev, pipe, false);
+       intel_crtc_update_cursor(crtc, false);
+       intel_disable_planes(crtc);
+       intel_disable_plane(dev_priv, plane, pipe);
+       if (intel_crtc->config.has_pch_encoder)
+               intel_set_pch_fifo_underrun_reporting(dev, pipe, false);
        intel_disable_pipe(dev_priv, pipe);
  
        ironlake_pfit_disable(intel_crtc);
                if (encoder->post_disable)
                        encoder->post_disable(encoder);
  
-       ironlake_fdi_disable(crtc);
-       ironlake_disable_pch_transcoder(dev_priv, pipe);
-       intel_set_pch_fifo_underrun_reporting(dev, pipe, true);
+       if (intel_crtc->config.has_pch_encoder) {
+               ironlake_fdi_disable(crtc);
  
-       if (HAS_PCH_CPT(dev)) {
-               /* disable TRANS_DP_CTL */
-               reg = TRANS_DP_CTL(pipe);
-               temp = I915_READ(reg);
-               temp &= ~(TRANS_DP_OUTPUT_ENABLE | TRANS_DP_PORT_SEL_MASK);
-               temp |= TRANS_DP_PORT_SEL_NONE;
-               I915_WRITE(reg, temp);
+               ironlake_disable_pch_transcoder(dev_priv, pipe);
+               intel_set_pch_fifo_underrun_reporting(dev, pipe, true);
  
-               /* disable DPLL_SEL */
-               temp = I915_READ(PCH_DPLL_SEL);
-               switch (pipe) {
-               case 0:
-                       temp &= ~(TRANSA_DPLL_ENABLE | TRANSA_DPLLB_SEL);
-                       break;
-               case 1:
-                       temp &= ~(TRANSB_DPLL_ENABLE | TRANSB_DPLLB_SEL);
-                       break;
-               case 2:
-                       /* C shares PLL A or B */
-                       temp &= ~(TRANSC_DPLL_ENABLE | TRANSC_DPLLB_SEL);
-                       break;
-               default:
-                       BUG(); /* wtf */
+               if (HAS_PCH_CPT(dev)) {
+                       /* disable TRANS_DP_CTL */
+                       reg = TRANS_DP_CTL(pipe);
+                       temp = I915_READ(reg);
+                       temp &= ~(TRANS_DP_OUTPUT_ENABLE |
+                                 TRANS_DP_PORT_SEL_MASK);
+                       temp |= TRANS_DP_PORT_SEL_NONE;
+                       I915_WRITE(reg, temp);
+                       /* disable DPLL_SEL */
+                       temp = I915_READ(PCH_DPLL_SEL);
+                       temp &= ~(TRANS_DPLL_ENABLE(pipe) | TRANS_DPLLB_SEL(pipe));
+                       I915_WRITE(PCH_DPLL_SEL, temp);
                }
-               I915_WRITE(PCH_DPLL_SEL, temp);
-       }
  
-       /* disable PCH DPLL */
-       intel_disable_pch_pll(intel_crtc);
+               /* disable PCH DPLL */
+               intel_disable_shared_dpll(intel_crtc);
  
-       ironlake_fdi_pll_disable(intel_crtc);
+               ironlake_fdi_pll_disable(intel_crtc);
+       }
  
        intel_crtc->active = false;
        intel_update_watermarks(dev);
@@@ -3463,7 -3460,6 +3460,6 @@@ static void haswell_crtc_disable(struc
  
        intel_crtc_wait_for_pending_flips(crtc);
        drm_vblank_off(dev, pipe);
-       intel_crtc_update_cursor(crtc, false);
  
        /* FBC must be disabled before disabling the plane on HSW. */
        if (dev_priv->cfb_plane == plane)
  
        hsw_disable_ips(intel_crtc);
  
+       intel_crtc_update_cursor(crtc, false);
+       intel_disable_planes(crtc);
        intel_disable_plane(dev_priv, plane, pipe);
  
        if (intel_crtc->config.has_pch_encoder)
  static void ironlake_crtc_off(struct drm_crtc *crtc)
  {
        struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
-       intel_put_pch_pll(intel_crtc);
+       intel_put_shared_dpll(intel_crtc);
  }
  
  static void haswell_crtc_off(struct drm_crtc *crtc)
@@@ -3611,19 -3609,17 +3609,17 @@@ static void valleyview_crtc_enable(stru
        for_each_encoder_on_crtc(dev, crtc, encoder)
                encoder->enable(encoder);
  
-       /* Enable panel fitting for eDP */
        i9xx_pfit_enable(intel_crtc);
  
+       intel_crtc_load_lut(crtc);
        intel_enable_pipe(dev_priv, pipe, false);
        intel_enable_plane(dev_priv, plane, pipe);
+       intel_enable_planes(crtc);
+       intel_crtc_update_cursor(crtc, true);
  
-       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);
  }
  
@@@ -3650,20 -3646,22 +3646,22 @@@ static void i9xx_crtc_enable(struct drm
                if (encoder->pre_enable)
                        encoder->pre_enable(encoder);
  
-       /* Enable panel fitting for LVDS */
        i9xx_pfit_enable(intel_crtc);
  
+       intel_crtc_load_lut(crtc);
        intel_enable_pipe(dev_priv, pipe, false);
        intel_enable_plane(dev_priv, plane, pipe);
+       intel_enable_planes(crtc);
+       /* The fixup needs to happen before cursor is enabled */
        if (IS_G4X(dev))
                g4x_fixup_plane(dev_priv, pipe);
-       intel_crtc_load_lut(crtc);
-       intel_update_fbc(dev);
+       intel_crtc_update_cursor(crtc, true);
  
        /* 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);
+       intel_update_fbc(dev);
  
        for_each_encoder_on_crtc(dev, crtc, encoder)
                encoder->enable(encoder);
@@@ -3702,13 -3700,15 +3700,15 @@@ static void i9xx_crtc_disable(struct dr
        /* Give the overlay scaler a chance to disable if it's on this pipe */
        intel_crtc_wait_for_pending_flips(crtc);
        drm_vblank_off(dev, pipe);
-       intel_crtc_dpms_overlay(intel_crtc, false);
-       intel_crtc_update_cursor(crtc, false);
  
        if (dev_priv->cfb_plane == plane)
                intel_disable_fbc(dev);
  
+       intel_crtc_dpms_overlay(intel_crtc, false);
+       intel_crtc_update_cursor(crtc, false);
+       intel_disable_planes(crtc);
        intel_disable_plane(dev_priv, plane, pipe);
        intel_disable_pipe(dev_priv, pipe);
  
        i9xx_pfit_disable(intel_crtc);
@@@ -3985,7 -3985,7 +3985,7 @@@ static int ironlake_fdi_compute_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;
+       int lane, link_bw, fdi_dotclock;
        bool setup_ok, needs_recompute = false;
  
  retry:
         */
        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;
+       fdi_dotclock = adjusted_mode->clock;
+       fdi_dotclock /= pipe_config->pixel_multiplier;
  
-       lane = ironlake_get_lanes_required(target_clock, link_bw,
+       lane = ironlake_get_lanes_required(fdi_dotclock, 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,
+       intel_link_compute_m_n(pipe_config->pipe_bpp, lane, fdi_dotclock,
                               link_bw, &pipe_config->fdi_m_n);
  
        setup_ok = ironlake_check_fdi_lanes(intel_crtc->base.dev,
@@@ -4039,12 -4035,11 +4035,11 @@@ static void hsw_compute_ips_config(stru
                                   pipe_config->pipe_bpp == 24;
  }
  
- static int intel_crtc_compute_config(struct drm_crtc *crtc,
+ static int intel_crtc_compute_config(struct intel_crtc *crtc,
                                     struct intel_crtc_config *pipe_config)
  {
-       struct drm_device *dev = crtc->dev;
+       struct drm_device *dev = crtc->base.dev;
        struct drm_display_mode *adjusted_mode = &pipe_config->adjusted_mode;
-       struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
  
        if (HAS_PCH_SPLIT(dev)) {
                /* FDI link clock is fixed at 2.7G */
        }
  
        if (IS_HASWELL(dev))
-               hsw_compute_ips_config(intel_crtc, pipe_config);
+               hsw_compute_ips_config(crtc, pipe_config);
+       /* XXX: PCH clock sharing is done in ->mode_set, so make sure the old
+        * clock survives for now. */
+       if (HAS_PCH_IBX(dev) || HAS_PCH_CPT(dev))
+               pipe_config->shared_dpll = crtc->config.shared_dpll;
  
        if (pipe_config->has_pch_encoder)
-               return ironlake_fdi_compute_config(intel_crtc, pipe_config);
+               return ironlake_fdi_compute_config(crtc, pipe_config);
  
        return 0;
  }
@@@ -4239,7 -4239,7 +4239,7 @@@ static int i9xx_get_refclk(struct drm_c
  
  static uint32_t pnv_dpll_compute_fp(struct dpll *dpll)
  {
-       return (1 << dpll->n) << 16 | dpll->m1 << 8 | dpll->m2;
+       return (1 << dpll->n) << 16 | dpll->m2;
  }
  
  static uint32_t i9xx_dpll_compute_fp(struct dpll *dpll)
@@@ -4351,8 -4351,6 +4351,6 @@@ 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;
        vlv_dpio_write(dev_priv, DPIO_DIV(pipe), mdiv);
  
        /* Set HBR and RBR LPF coefficients */
-       if (adjusted_mode->clock == 162000 ||
+       if (crtc->config.port_clock == 162000 ||
            intel_pipe_has_type(&crtc->base, INTEL_OUTPUT_HDMI))
                vlv_dpio_write(dev_priv, DPIO_LFP_COEFF(pipe),
                                 0x005f0021);
        if (wait_for(((I915_READ(DPLL(pipe)) & DPLL_LOCK_VLV) == DPLL_LOCK_VLV), 1))
                DRM_ERROR("DPLL %d failed to lock\n", pipe);
  
-       dpll_md = 0;
-       if (crtc->config.pixel_multiplier > 1) {
-               dpll_md = (crtc->config.pixel_multiplier - 1)
-                       << DPLL_MD_UDI_MULTIPLIER_SHIFT;
-       }
+       dpll_md = (crtc->config.pixel_multiplier - 1)
+               << DPLL_MD_UDI_MULTIPLIER_SHIFT;
        I915_WRITE(DPLL_MD(pipe), dpll_md);
        POSTING_READ(DPLL_MD(pipe));
  
@@@ -4497,8 -4492,7 +4492,7 @@@ static void i9xx_update_pll(struct inte
        else
                dpll |= DPLLB_MODE_DAC_SERIAL;
  
-       if ((crtc->config.pixel_multiplier > 1) &&
-           (IS_I945G(dev) || IS_I945GM(dev) || IS_G33(dev))) {
+       if (IS_I945G(dev) || IS_I945GM(dev) || IS_G33(dev)) {
                dpll |= (crtc->config.pixel_multiplier - 1)
                        << SDVO_MULTIPLIER_SHIFT_HIRES;
        }
        udelay(150);
  
        if (INTEL_INFO(dev)->gen >= 4) {
-               u32 dpll_md = 0;
-               if (crtc->config.pixel_multiplier > 1) {
-                       dpll_md = (crtc->config.pixel_multiplier - 1)
-                               << DPLL_MD_UDI_MULTIPLIER_SHIFT;
-               }
+               u32 dpll_md = (crtc->config.pixel_multiplier - 1)
+                       << DPLL_MD_UDI_MULTIPLIER_SHIFT;
                I915_WRITE(DPLL_MD(pipe), dpll_md);
        } else {
                /* The pixel multiplier can only be updated once the
  }
  
  static void i8xx_update_pll(struct intel_crtc *crtc,
-                           struct drm_display_mode *adjusted_mode,
                            intel_clock_t *reduced_clock,
                            int num_connectors)
  {
        I915_WRITE(DPLL(pipe), dpll);
  }
  
- static void intel_set_pipe_timings(struct intel_crtc *intel_crtc,
-                                  struct drm_display_mode *mode,
-                                  struct drm_display_mode *adjusted_mode)
+ static void intel_set_pipe_timings(struct intel_crtc *intel_crtc)
  {
        struct drm_device *dev = intel_crtc->base.dev;
        struct drm_i915_private *dev_priv = dev->dev_private;
        enum pipe pipe = intel_crtc->pipe;
        enum transcoder cpu_transcoder = intel_crtc->config.cpu_transcoder;
+       struct drm_display_mode *adjusted_mode =
+               &intel_crtc->config.adjusted_mode;
+       struct drm_display_mode *mode = &intel_crtc->config.requested_mode;
        uint32_t vsyncshift, crtc_vtotal, crtc_vblank_end;
  
        /* We need to be careful not to changed the adjusted mode, for otherwise
@@@ -4741,7 -4732,7 +4732,7 @@@ static void i9xx_set_pipeconf(struct in
        struct drm_i915_private *dev_priv = dev->dev_private;
        uint32_t pipeconf;
  
-       pipeconf = I915_READ(PIPECONF(intel_crtc->pipe));
+       pipeconf = 0;
  
        if (intel_crtc->pipe == 0 && INTEL_INFO(dev)->gen < 4) {
                /* Enable pixel doubling when the dot clock is > 90% of the (display)
                if (intel_crtc->config.requested_mode.clock >
                    dev_priv->display.get_display_clock_speed(dev) * 9 / 10)
                        pipeconf |= PIPECONF_DOUBLE_WIDE;
-               else
-                       pipeconf &= ~PIPECONF_DOUBLE_WIDE;
        }
  
        /* 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 |= PIPECONF_CXSR_DOWNCLOCK;
                } else {
                        DRM_DEBUG_KMS("disabling CxSR downclocking\n");
-                       pipeconf &= ~PIPECONF_CXSR_DOWNCLOCK;
                }
        }
  
-       pipeconf &= ~PIPECONF_INTERLACE_MASK;
        if (!IS_GEN2(dev) &&
            intel_crtc->config.adjusted_mode.flags & DRM_MODE_FLAG_INTERLACE)
                pipeconf |= PIPECONF_INTERLACE_W_FIELD_INDICATION;
        else
                pipeconf |= PIPECONF_PROGRESSIVE;
  
-       if (IS_VALLEYVIEW(dev)) {
-               if (intel_crtc->config.limited_color_range)
-                       pipeconf |= PIPECONF_COLOR_RANGE_SELECT;
-               else
-                       pipeconf &= ~PIPECONF_COLOR_RANGE_SELECT;
-       }
+       if (IS_VALLEYVIEW(dev) && intel_crtc->config.limited_color_range)
+               pipeconf |= PIPECONF_COLOR_RANGE_SELECT;
  
        I915_WRITE(PIPECONF(intel_crtc->pipe), pipeconf);
        POSTING_READ(PIPECONF(intel_crtc->pipe));
@@@ -4818,8 -4798,6 +4798,6 @@@ static int i9xx_crtc_mode_set(struct dr
        struct drm_device *dev = crtc->dev;
        struct drm_i915_private *dev_priv = dev->dev_private;
        struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
-       struct drm_display_mode *adjusted_mode =
-               &intel_crtc->config.adjusted_mode;
        struct drm_display_mode *mode = &intel_crtc->config.requested_mode;
        int pipe = intel_crtc->pipe;
        int plane = intel_crtc->plane;
         * reflck * (5 * (m1 + 2) + (m2 + 2)) / (n + 2) / p1 / p2.
         */
        limit = intel_limit(crtc, refclk);
-       ok = limit->find_pll(limit, crtc, adjusted_mode->clock, refclk, NULL,
-                            &clock);
-       if (!ok) {
+       ok = dev_priv->display.find_dpll(limit, crtc,
+                                        intel_crtc->config.port_clock,
+                                        refclk, NULL, &clock);
+       if (!ok && !intel_crtc->config.clock_set) {
                DRM_ERROR("Couldn't find PLL settings for mode!\n");
                return -EINVAL;
        }
                 * by using the FP0/FP1. In such case we will disable the LVDS
                 * downclock feature.
                */
-               has_reduced_clock = limit->find_pll(limit, crtc,
+               has_reduced_clock =
+                       dev_priv->display.find_dpll(limit, crtc,
                                                    dev_priv->lvds_downclock,
-                                                   refclk,
-                                                   &clock,
+                                                   refclk, &clock,
                                                    &reduced_clock);
        }
        /* Compat-code for transition, will disappear. */
        }
  
        if (IS_GEN2(dev))
-               i8xx_update_pll(intel_crtc, adjusted_mode,
+               i8xx_update_pll(intel_crtc,
                                has_reduced_clock ? &reduced_clock : NULL,
                                num_connectors);
        else if (IS_VALLEYVIEW(dev))
                        dspcntr |= DISPPLANE_SEL_PIPE_B;
        }
  
-       intel_set_pipe_timings(intel_crtc, mode, adjusted_mode);
+       intel_set_pipe_timings(intel_crtc);
  
        /* pipesrc and dspsize control the size that is scaled from,
         * which should always be the user's requested size.
@@@ -4963,6 -4942,7 +4942,7 @@@ static bool i9xx_get_pipe_config(struc
        uint32_t tmp;
  
        pipe_config->cpu_transcoder = crtc->pipe;
+       pipe_config->shared_dpll = DPLL_ID_PRIVATE;
  
        tmp = I915_READ(PIPECONF(crtc->pipe));
        if (!(tmp & PIPECONF_ENABLE))
  
        i9xx_get_pfit_config(crtc, pipe_config);
  
+       if (INTEL_INFO(dev)->gen >= 4) {
+               tmp = I915_READ(DPLL_MD(crtc->pipe));
+               pipe_config->pixel_multiplier =
+                       ((tmp & DPLL_MD_UDI_MULTIPLIER_MASK)
+                        >> DPLL_MD_UDI_MULTIPLIER_SHIFT) + 1;
+       } else if (IS_I945G(dev) || IS_I945GM(dev) || IS_G33(dev)) {
+               tmp = I915_READ(DPLL(crtc->pipe));
+               pipe_config->pixel_multiplier =
+                       ((tmp & SDVO_MULTIPLIER_MASK)
+                        >> SDVO_MULTIPLIER_SHIFT_HIRES) + 1;
+       } else {
+               /* Note that on i915G/GM the pixel multiplier is in the sdvo
+                * port and will be fixed up in the encoder->get_config
+                * function. */
+               pipe_config->pixel_multiplier = 1;
+       }
        return true;
  }
  
@@@ -5330,9 -5327,8 +5327,8 @@@ static void ironlake_set_pipeconf(struc
        int pipe = intel_crtc->pipe;
        uint32_t val;
  
-       val = I915_READ(PIPECONF(pipe));
+       val = 0;
  
-       val &= ~PIPECONF_BPC_MASK;
        switch (intel_crtc->config.pipe_bpp) {
        case 18:
                val |= PIPECONF_6BPC;
                BUG();
        }
  
-       val &= ~(PIPECONF_DITHER_EN | PIPECONF_DITHER_TYPE_MASK);
        if (intel_crtc->config.dither)
                val |= (PIPECONF_DITHER_EN | PIPECONF_DITHER_TYPE_SP);
  
-       val &= ~PIPECONF_INTERLACE_MASK;
        if (intel_crtc->config.adjusted_mode.flags & DRM_MODE_FLAG_INTERLACE)
                val |= PIPECONF_INTERLACED_ILK;
        else
  
        if (intel_crtc->config.limited_color_range)
                val |= PIPECONF_COLOR_RANGE_SELECT;
-       else
-               val &= ~PIPECONF_COLOR_RANGE_SELECT;
  
        I915_WRITE(PIPECONF(pipe), val);
        POSTING_READ(PIPECONF(pipe));
@@@ -5441,13 -5433,11 +5433,11 @@@ static void haswell_set_pipeconf(struc
        enum transcoder cpu_transcoder = intel_crtc->config.cpu_transcoder;
        uint32_t val;
  
-       val = I915_READ(PIPECONF(cpu_transcoder));
+       val = 0;
  
-       val &= ~(PIPECONF_DITHER_EN | PIPECONF_DITHER_TYPE_MASK);
        if (intel_crtc->config.dither)
                val |= (PIPECONF_DITHER_EN | PIPECONF_DITHER_TYPE_SP);
  
-       val &= ~PIPECONF_INTERLACE_MASK_HSW;
        if (intel_crtc->config.adjusted_mode.flags & DRM_MODE_FLAG_INTERLACE)
                val |= PIPECONF_INTERLACED_ILK;
        else
  
        I915_WRITE(PIPECONF(cpu_transcoder), val);
        POSTING_READ(PIPECONF(cpu_transcoder));
+       I915_WRITE(GAMMA_MODE(intel_crtc->pipe), GAMMA_MODE_MODE_8BIT);
+       POSTING_READ(GAMMA_MODE(intel_crtc->pipe));
  }
  
  static bool ironlake_compute_clocks(struct drm_crtc *crtc,
-                                   struct drm_display_mode *adjusted_mode,
                                    intel_clock_t *clock,
                                    bool *has_reduced_clock,
                                    intel_clock_t *reduced_clock)
         * reflck * (5 * (m1 + 2) + (m2 + 2)) / (n + 2) / p1 / p2.
         */
        limit = intel_limit(crtc, refclk);
-       ret = limit->find_pll(limit, crtc, adjusted_mode->clock, refclk, NULL,
-                             clock);
+       ret = dev_priv->display.find_dpll(limit, crtc,
+                                         to_intel_crtc(crtc)->config.port_clock,
+                                         refclk, NULL, clock);
        if (!ret)
                return false;
  
                 * by using the FP0/FP1. In such case we will disable the LVDS
                 * downclock feature.
                */
-               *has_reduced_clock = limit->find_pll(limit, crtc,
-                                                    dev_priv->lvds_downclock,
-                                                    refclk,
-                                                    clock,
-                                                    reduced_clock);
+               *has_reduced_clock =
+                       dev_priv->display.find_dpll(limit, crtc,
+                                                   dev_priv->lvds_downclock,
+                                                   refclk, clock,
+                                                   reduced_clock);
        }
  
        return true;
@@@ -5615,10 -5608,8 +5608,8 @@@ static uint32_t ironlake_compute_dpll(s
        else
                dpll |= DPLLB_MODE_DAC_SERIAL;
  
-       if (intel_crtc->config.pixel_multiplier > 1) {
-               dpll |= (intel_crtc->config.pixel_multiplier - 1)
-                       << PLL_REF_SDVO_HDMI_MULTIPLIER_SHIFT;
-       }
+       dpll |= (intel_crtc->config.pixel_multiplier - 1)
+               << PLL_REF_SDVO_HDMI_MULTIPLIER_SHIFT;
  
        if (is_sdvo)
                dpll |= DPLL_DVO_HIGH_SPEED;
        else
                dpll |= PLL_REF_INPUT_DREFCLK;
  
-       return dpll;
+       return dpll | DPLL_VCO_ENABLE;
  }
  
  static int ironlake_crtc_mode_set(struct drm_crtc *crtc,
        struct drm_device *dev = crtc->dev;
        struct drm_i915_private *dev_priv = dev->dev_private;
        struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
-       struct drm_display_mode *adjusted_mode =
-               &intel_crtc->config.adjusted_mode;
-       struct drm_display_mode *mode = &intel_crtc->config.requested_mode;
        int pipe = intel_crtc->pipe;
        int plane = intel_crtc->plane;
        int num_connectors = 0;
        bool ok, has_reduced_clock = false;
        bool is_lvds = false;
        struct intel_encoder *encoder;
+       struct intel_shared_dpll *pll;
        int ret;
  
        for_each_encoder_on_crtc(dev, crtc, encoder) {
        WARN(!(HAS_PCH_IBX(dev) || HAS_PCH_CPT(dev)),
             "Unexpected PCH type %d\n", INTEL_PCH_TYPE(dev));
  
-       ok = ironlake_compute_clocks(crtc, adjusted_mode, &clock,
+       ok = ironlake_compute_clocks(crtc, &clock,
                                     &has_reduced_clock, &reduced_clock);
-       if (!ok) {
+       if (!ok && !intel_crtc->config.clock_set) {
                DRM_ERROR("Couldn't find PLL settings for mode!\n");
                return -EINVAL;
        }
  
        /* 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);
                                             &fp, &reduced_clock,
                                             has_reduced_clock ? &fp2 : NULL);
  
-               pll = intel_get_pch_pll(intel_crtc, dpll, fp);
+               intel_crtc->config.dpll_hw_state.dpll = dpll;
+               intel_crtc->config.dpll_hw_state.fp0 = fp;
+               if (has_reduced_clock)
+                       intel_crtc->config.dpll_hw_state.fp1 = fp2;
+               else
+                       intel_crtc->config.dpll_hw_state.fp1 = fp;
+               pll = intel_get_shared_dpll(intel_crtc, dpll, fp);
                if (pll == NULL) {
                        DRM_DEBUG_DRIVER("failed to find PLL for pipe %c\n",
                                         pipe_name(pipe));
                        return -EINVAL;
                }
        } else
-               intel_put_pch_pll(intel_crtc);
+               intel_put_shared_dpll(intel_crtc);
  
        if (intel_crtc->config.has_dp_encoder)
                intel_dp_set_m_n(intel_crtc);
                if (encoder->pre_pll_enable)
                        encoder->pre_pll_enable(encoder);
  
-       if (intel_crtc->pch_pll) {
-               I915_WRITE(intel_crtc->pch_pll->pll_reg, dpll);
+       if (is_lvds && has_reduced_clock && i915_powersave)
+               intel_crtc->lowfreq_avail = true;
+       else
+               intel_crtc->lowfreq_avail = false;
+       if (intel_crtc->config.has_pch_encoder) {
+               pll = intel_crtc_to_shared_dpll(intel_crtc);
+               I915_WRITE(PCH_DPLL(pll->id), dpll);
  
                /* Wait for the clocks to stabilize. */
-               POSTING_READ(intel_crtc->pch_pll->pll_reg);
+               POSTING_READ(PCH_DPLL(pll->id));
                udelay(150);
  
                /* The pixel multiplier can only be updated once the
                 *
                 * So write it again.
                 */
-               I915_WRITE(intel_crtc->pch_pll->pll_reg, dpll);
-       }
+               I915_WRITE(PCH_DPLL(pll->id), dpll);
  
-       intel_crtc->lowfreq_avail = false;
-       if (intel_crtc->pch_pll) {
-               if (is_lvds && has_reduced_clock && i915_powersave) {
-                       I915_WRITE(intel_crtc->pch_pll->fp1_reg, fp2);
-                       intel_crtc->lowfreq_avail = true;
-               } else {
-                       I915_WRITE(intel_crtc->pch_pll->fp1_reg, fp);
-               }
+               if (has_reduced_clock)
+                       I915_WRITE(PCH_FP1(pll->id), fp2);
+               else
+                       I915_WRITE(PCH_FP1(pll->id), fp);
        }
  
-       intel_set_pipe_timings(intel_crtc, mode, adjusted_mode);
+       intel_set_pipe_timings(intel_crtc);
  
        if (intel_crtc->config.has_pch_encoder) {
                intel_cpu_transcoder_set_m_n(intel_crtc,
@@@ -5808,6 -5804,14 +5804,14 @@@ static void ironlake_get_pfit_config(st
        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));
+               /* We currently do not free assignements of panel fitters on
+                * ivb/hsw (since we don't use the higher upscaling modes which
+                * differentiates them) so just WARN about this case for now. */
+               if (IS_GEN7(dev)) {
+                       WARN_ON((tmp & PF_PIPE_SEL_MASK_IVB) !=
+                               PF_PIPE_SEL_IVB(crtc->pipe));
+               }
        }
  }
  
@@@ -5819,12 -5823,15 +5823,15 @@@ static bool ironlake_get_pipe_config(st
        uint32_t tmp;
  
        pipe_config->cpu_transcoder = crtc->pipe;
+       pipe_config->shared_dpll = DPLL_ID_PRIVATE;
  
        tmp = I915_READ(PIPECONF(crtc->pipe));
        if (!(tmp & PIPECONF_ENABLE))
                return false;
  
        if (I915_READ(PCH_TRANSCONF(crtc->pipe)) & TRANS_ENABLE) {
+               struct intel_shared_dpll *pll;
                pipe_config->has_pch_encoder = true;
  
                tmp = I915_READ(FDI_RX_CTL(crtc->pipe));
                                          FDI_DP_PORT_WIDTH_SHIFT) + 1;
  
                ironlake_get_fdi_m_n_config(crtc, pipe_config);
+               /* XXX: Can't properly read out the pch dpll pixel multiplier
+                * since we don't have state tracking for pch clocks yet. */
+               pipe_config->pixel_multiplier = 1;
+               if (HAS_PCH_IBX(dev_priv->dev)) {
+                       pipe_config->shared_dpll = crtc->pipe;
+               } else {
+                       tmp = I915_READ(PCH_DPLL_SEL);
+                       if (tmp & TRANS_DPLLB_SEL(crtc->pipe))
+                               pipe_config->shared_dpll = DPLL_ID_PCH_PLL_B;
+                       else
+                               pipe_config->shared_dpll = DPLL_ID_PCH_PLL_A;
+               }
+               pll = &dev_priv->shared_dplls[pipe_config->shared_dpll];
+               WARN_ON(!pll->get_hw_state(dev_priv, pll,
+                                          &pipe_config->dpll_hw_state));
+       } else {
+               pipe_config->pixel_multiplier = 1;
        }
  
        intel_get_pipe_timings(crtc, pipe_config);
@@@ -5865,31 -5893,10 +5893,10 @@@ static int haswell_crtc_mode_set(struc
        struct drm_device *dev = crtc->dev;
        struct drm_i915_private *dev_priv = dev->dev_private;
        struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
-       struct drm_display_mode *adjusted_mode =
-               &intel_crtc->config.adjusted_mode;
-       struct drm_display_mode *mode = &intel_crtc->config.requested_mode;
-       int pipe = intel_crtc->pipe;
        int plane = intel_crtc->plane;
-       int num_connectors = 0;
-       bool is_cpu_edp = false;
-       struct intel_encoder *encoder;
        int ret;
  
-       for_each_encoder_on_crtc(dev, crtc, encoder) {
-               switch (encoder->type) {
-               case INTEL_OUTPUT_EDP:
-                       if (enc_to_dig_port(&encoder->base)->port == PORT_A)
-                               is_cpu_edp = true;
-                       break;
-               }
-               num_connectors++;
-       }
-       WARN(num_connectors != 1, "%d connectors attached to pipe %c\n",
-            num_connectors, pipe_name(pipe));
-       if (!intel_ddi_pll_mode_set(crtc, adjusted_mode->clock))
+       if (!intel_ddi_pll_mode_set(crtc))
                return -EINVAL;
  
        /* Ensure that the cursor is valid for the new mode before changing... */
  
        intel_crtc->lowfreq_avail = false;
  
-       intel_set_pipe_timings(intel_crtc, mode, adjusted_mode);
+       intel_set_pipe_timings(intel_crtc);
  
        if (intel_crtc->config.has_pch_encoder) {
                intel_cpu_transcoder_set_m_n(intel_crtc,
@@@ -5931,6 -5938,8 +5938,8 @@@ static bool haswell_get_pipe_config(str
        uint32_t tmp;
  
        pipe_config->cpu_transcoder = crtc->pipe;
+       pipe_config->shared_dpll = DPLL_ID_PRIVATE;
        tmp = I915_READ(TRANS_DDI_FUNC_CTL(TRANSCODER_EDP));
        if (tmp & TRANS_DDI_FUNC_ENABLE) {
                enum pipe trans_edp_pipe;
        pipe_config->ips_enabled = hsw_crtc_supports_ips(crtc) &&
                                   (I915_READ(IPS_CTL) & IPS_ENABLE);
  
+       pipe_config->pixel_multiplier = 1;
        return true;
  }
  
@@@ -6300,6 -6311,9 +6311,9 @@@ void intel_crtc_load_lut(struct drm_crt
        if (!crtc->enabled || !intel_crtc->active)
                return;
  
+       if (!HAS_PCH_SPLIT(dev_priv->dev))
+               assert_pll_enabled(dev_priv, pipe);
        /* use legacy palette for Ironlake */
        if (HAS_PCH_SPLIT(dev))
                palreg = LGC_PALETTE(pipe);
@@@ -6909,8 -6923,10 +6923,10 @@@ static int intel_crtc_clock_get(struct 
                        return 0;
                }
  
-               /* XXX: Handle the 100Mhz refclk */
-               intel_clock(dev, 96000, &clock);
+               if (IS_PINEVIEW(dev))
+                       pineview_clock(96000, &clock);
+               else
+                       i9xx_clock(96000, &clock);
        } else {
                bool is_lvds = (pipe == 1) && (I915_READ(LVDS) & LVDS_PORT_EN);
  
                        if ((dpll & PLL_REF_INPUT_MASK) ==
                            PLLB_REF_INPUT_SPREADSPECTRUMIN) {
                                /* XXX: might not be 66MHz */
-                               intel_clock(dev, 66000, &clock);
+                               i9xx_clock(66000, &clock);
                        } else
-                               intel_clock(dev, 48000, &clock);
+                               i9xx_clock(48000, &clock);
                } else {
                        if (dpll & PLL_P1_DIVIDE_BY_TWO)
                                clock.p1 = 2;
                        else
                                clock.p2 = 2;
  
-                       intel_clock(dev, 48000, &clock);
+                       i9xx_clock(48000, &clock);
                }
        }
  
@@@ -7068,7 -7084,8 +7084,8 @@@ void intel_mark_idle(struct drm_device 
        }
  }
  
- void intel_mark_fb_busy(struct drm_i915_gem_object *obj)
+ void intel_mark_fb_busy(struct drm_i915_gem_object *obj,
+                       struct intel_ring_buffer *ring)
  {
        struct drm_device *dev = obj->base.dev;
        struct drm_crtc *crtc;
                if (!crtc->fb)
                        continue;
  
-               if (to_intel_framebuffer(crtc->fb)->obj == obj)
-                       intel_increase_pllclock(crtc);
+               if (to_intel_framebuffer(crtc->fb)->obj != obj)
+                       continue;
+               intel_increase_pllclock(crtc);
+               if (ring && intel_fbc_enabled(dev))
+                       ring->fbc_dirty = true;
        }
  }
  
@@@ -7531,7 -7552,7 +7552,7 @@@ static int intel_crtc_page_flip(struct 
                goto cleanup_pending;
  
        intel_disable_fbc(dev);
-       intel_mark_fb_busy(obj);
+       intel_mark_fb_busy(obj, NULL);
        mutex_unlock(&dev->struct_mutex);
  
        trace_i915_flip_request(intel_crtc->plane, obj);
@@@ -7562,28 -7583,6 +7583,6 @@@ static struct drm_crtc_helper_funcs int
        .load_lut = intel_crtc_load_lut,
  };
  
- bool intel_encoder_check_is_cloned(struct intel_encoder *encoder)
- {
-       struct intel_encoder *other_encoder;
-       struct drm_crtc *crtc = &encoder->new_crtc->base;
-       if (WARN_ON(!crtc))
-               return false;
-       list_for_each_entry(other_encoder,
-                           &crtc->dev->mode_config.encoder_list,
-                           base.head) {
-               if (&other_encoder->new_crtc->base != crtc ||
-                   encoder == other_encoder)
-                       continue;
-               else
-                       return true;
-       }
-       return false;
- }
  static bool intel_encoder_crtc_ok(struct drm_encoder *encoder,
                                  struct drm_crtc *crtc)
  {
@@@ -7651,13 -7650,39 +7650,39 @@@ static void intel_modeset_commit_output
        }
  }
  
+ static void
+ connected_sink_compute_bpp(struct intel_connector * connector,
+                          struct intel_crtc_config *pipe_config)
+ {
+       int bpp = pipe_config->pipe_bpp;
+       DRM_DEBUG_KMS("[CONNECTOR:%d:%s] checking for sink bpp constrains\n",
+               connector->base.base.id,
+               drm_get_connector_name(&connector->base));
+       /* Don't use an invalid EDID bpc value */
+       if (connector->base.display_info.bpc &&
+           connector->base.display_info.bpc * 3 < bpp) {
+               DRM_DEBUG_KMS("clamping display bpp (was %d) to EDID reported max of %d\n",
+                             bpp, connector->base.display_info.bpc*3);
+               pipe_config->pipe_bpp = connector->base.display_info.bpc*3;
+       }
+       /* Clamp bpp to 8 on screens without EDID 1.4 */
+       if (connector->base.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;
+       }
+ }
  static int
pipe_config_set_bpp(struct drm_crtc *crtc,
-                   struct drm_framebuffer *fb,
-                   struct intel_crtc_config *pipe_config)
compute_baseline_pipe_bpp(struct intel_crtc *crtc,
+                         struct drm_framebuffer *fb,
+                         struct intel_crtc_config *pipe_config)
  {
-       struct drm_device *dev = crtc->dev;
-       struct drm_connector *connector;
+       struct drm_device *dev = crtc->base.dev;
+       struct intel_connector *connector;
        int bpp;
  
        switch (fb->pixel_format) {
  
        /* Clamp display bpp to EDID value */
        list_for_each_entry(connector, &dev->mode_config.connector_list,
-                           head) {
-               if (connector->encoder && connector->encoder->crtc != crtc)
+                           base.head) {
+               if (!connector->new_encoder ||
+                   connector->new_encoder->new_crtc != crtc)
                        continue;
  
-               /* Don't use an invalid EDID bpc value */
-               if (connector->display_info.bpc &&
-                   connector->display_info.bpc * 3 < bpp) {
-                       DRM_DEBUG_KMS("clamping display bpp (was %d) to EDID reported max of %d\n",
-                                     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;
-               }
+               connected_sink_compute_bpp(connector, pipe_config);
        }
  
        return bpp;
@@@ -7753,6 -7766,25 +7766,25 @@@ static void intel_dump_pipe_config(stru
        DRM_DEBUG_KMS("ips: %i\n", pipe_config->ips_enabled);
  }
  
+ static bool check_encoder_cloning(struct drm_crtc *crtc)
+ {
+       int num_encoders = 0;
+       bool uncloneable_encoders = false;
+       struct intel_encoder *encoder;
+       list_for_each_entry(encoder, &crtc->dev->mode_config.encoder_list,
+                           base.head) {
+               if (&encoder->new_crtc->base != crtc)
+                       continue;
+               num_encoders++;
+               if (!encoder->cloneable)
+                       uncloneable_encoders = true;
+       }
+       return !(num_encoders > 1 && uncloneable_encoders);
+ }
  static struct intel_crtc_config *
  intel_modeset_pipe_config(struct drm_crtc *crtc,
                          struct drm_framebuffer *fb,
        int plane_bpp, ret = -EINVAL;
        bool retry = true;
  
+       if (!check_encoder_cloning(crtc)) {
+               DRM_DEBUG_KMS("rejecting invalid cloning configuration\n");
+               return ERR_PTR(-EINVAL);
+       }
        pipe_config = kzalloc(sizeof(*pipe_config), GFP_KERNEL);
        if (!pipe_config)
                return ERR_PTR(-ENOMEM);
        drm_mode_copy(&pipe_config->adjusted_mode, mode);
        drm_mode_copy(&pipe_config->requested_mode, mode);
        pipe_config->cpu_transcoder = to_intel_crtc(crtc)->pipe;
-       plane_bpp = pipe_config_set_bpp(crtc, fb, pipe_config);
+       pipe_config->shared_dpll = DPLL_ID_PRIVATE;
+       /* Compute a starting value for pipe_config->pipe_bpp taking the source
+        * plane pixel format and any sink constraints into account. Returns the
+        * source plane bpp so that dithering can be selected on mismatches
+        * after encoders and crtc also have had their say. */
+       plane_bpp = compute_baseline_pipe_bpp(to_intel_crtc(crtc),
+                                             fb, pipe_config);
        if (plane_bpp < 0)
                goto fail;
  
  encoder_retry:
+       /* Ensure the port clock defaults are reset when retrying. */
+       pipe_config->port_clock = 0;
+       pipe_config->pixel_multiplier = 1;
        /* 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.
                }
        }
  
-       ret = intel_crtc_compute_config(crtc, pipe_config);
+       /* Set default port clock if not overwritten by the encoder. Needs to be
+        * done afterwards in case the encoder adjusts the mode. */
+       if (!pipe_config->port_clock)
+               pipe_config->port_clock = pipe_config->adjusted_mode.clock;
+       ret = intel_crtc_compute_config(to_intel_crtc(crtc), pipe_config);
        if (ret < 0) {
                DRM_DEBUG_KMS("CRTC fixup failed\n");
                goto fail;
@@@ -8002,6 -8054,15 +8054,15 @@@ intel_pipe_config_compare(struct drm_de
                          struct intel_crtc_config *current_config,
                          struct intel_crtc_config *pipe_config)
  {
+ #define PIPE_CONF_CHECK_X(name)       \
+       if (current_config->name != pipe_config->name) { \
+               DRM_ERROR("mismatch in " #name " " \
+                         "(expected 0x%08x, found 0x%08x)\n", \
+                         current_config->name, \
+                         pipe_config->name); \
+               return false; \
+       }
  #define PIPE_CONF_CHECK_I(name)       \
        if (current_config->name != pipe_config->name) { \
                DRM_ERROR("mismatch in " #name " " \
                return false; \
        }
  
+ #define PIPE_CONF_QUIRK(quirk)        \
+       ((current_config->quirks | pipe_config->quirks) & (quirk))
        PIPE_CONF_CHECK_I(cpu_transcoder);
  
        PIPE_CONF_CHECK_I(has_pch_encoder);
        PIPE_CONF_CHECK_I(adjusted_mode.crtc_vsync_start);
        PIPE_CONF_CHECK_I(adjusted_mode.crtc_vsync_end);
  
+       if (!HAS_PCH_SPLIT(dev))
+               PIPE_CONF_CHECK_I(pixel_multiplier);
        PIPE_CONF_CHECK_FLAGS(adjusted_mode.flags,
                              DRM_MODE_FLAG_INTERLACE);
  
-       PIPE_CONF_CHECK_FLAGS(adjusted_mode.flags,
-                             DRM_MODE_FLAG_PHSYNC);
-       PIPE_CONF_CHECK_FLAGS(adjusted_mode.flags,
-                             DRM_MODE_FLAG_NHSYNC);
-       PIPE_CONF_CHECK_FLAGS(adjusted_mode.flags,
-                             DRM_MODE_FLAG_PVSYNC);
-       PIPE_CONF_CHECK_FLAGS(adjusted_mode.flags,
-                             DRM_MODE_FLAG_NVSYNC);
+       if (!PIPE_CONF_QUIRK(PIPE_CONFIG_QUIRK_MODE_SYNC_FLAGS)) {
+               PIPE_CONF_CHECK_FLAGS(adjusted_mode.flags,
+                                     DRM_MODE_FLAG_PHSYNC);
+               PIPE_CONF_CHECK_FLAGS(adjusted_mode.flags,
+                                     DRM_MODE_FLAG_NHSYNC);
+               PIPE_CONF_CHECK_FLAGS(adjusted_mode.flags,
+                                     DRM_MODE_FLAG_PVSYNC);
+               PIPE_CONF_CHECK_FLAGS(adjusted_mode.flags,
+                                     DRM_MODE_FLAG_NVSYNC);
+       }
  
        PIPE_CONF_CHECK_I(requested_mode.hdisplay);
        PIPE_CONF_CHECK_I(requested_mode.vdisplay);
  
        PIPE_CONF_CHECK_I(ips_enabled);
  
+       PIPE_CONF_CHECK_I(shared_dpll);
+       PIPE_CONF_CHECK_X(dpll_hw_state.dpll);
+       PIPE_CONF_CHECK_X(dpll_hw_state.fp0);
+       PIPE_CONF_CHECK_X(dpll_hw_state.fp1);
+ #undef PIPE_CONF_CHECK_X
  #undef PIPE_CONF_CHECK_I
  #undef PIPE_CONF_CHECK_FLAGS
+ #undef PIPE_CONF_QUIRK
  
        return true;
  }
  
- void
intel_modeset_check_state(struct drm_device *dev)
static void
check_connector_state(struct drm_device *dev)
  {
-       drm_i915_private_t *dev_priv = dev->dev_private;
-       struct intel_crtc *crtc;
-       struct intel_encoder *encoder;
        struct intel_connector *connector;
-       struct intel_crtc_config pipe_config;
  
        list_for_each_entry(connector, &dev->mode_config.connector_list,
                            base.head) {
                WARN(&connector->new_encoder->base != connector->base.encoder,
                     "connector's staged encoder doesn't match current encoder\n");
        }
+ }
+ static void
+ check_encoder_state(struct drm_device *dev)
+ {
+       struct intel_encoder *encoder;
+       struct intel_connector *connector;
  
        list_for_each_entry(encoder, &dev->mode_config.encoder_list,
                            base.head) {
                     tracked_pipe, pipe);
  
        }
+ }
+ static void
+ check_crtc_state(struct drm_device *dev)
+ {
+       drm_i915_private_t *dev_priv = dev->dev_private;
+       struct intel_crtc *crtc;
+       struct intel_encoder *encoder;
+       struct intel_crtc_config pipe_config;
  
        list_for_each_entry(crtc, &dev->mode_config.crtc_list,
                            base.head) {
                        enabled = true;
                        if (encoder->connectors_active)
                                active = true;
-                       if (encoder->get_config)
-                               encoder->get_config(encoder, &pipe_config);
                }
                WARN(active != crtc->active,
                     "crtc's computed active state doesn't match tracked active state "
                     "(expected %i, found %i)\n", active, crtc->active);
  
                active = dev_priv->display.get_pipe_config(crtc,
                                                           &pipe_config);
 +
 +              /* hw state is inconsistent with the pipe A quirk */
 +              if (crtc->pipe == PIPE_A && dev_priv->quirks & QUIRK_PIPEA_FORCE)
 +                      active = crtc->active;
 +
+               list_for_each_entry(encoder, &dev->mode_config.encoder_list,
+                                   base.head) {
+                       if (encoder->base.crtc != &crtc->base)
+                               continue;
+                       if (encoder->get_config)
+                               encoder->get_config(encoder, &pipe_config);
+               }
                WARN(crtc->active != active,
                     "crtc active state doesn't match with hw state "
                     "(expected %i, found %i)\n", crtc->active, active);
        }
  }
  
+ static void
+ check_shared_dpll_state(struct drm_device *dev)
+ {
+       drm_i915_private_t *dev_priv = dev->dev_private;
+       struct intel_crtc *crtc;
+       struct intel_dpll_hw_state dpll_hw_state;
+       int i;
+       for (i = 0; i < dev_priv->num_shared_dpll; i++) {
+               struct intel_shared_dpll *pll = &dev_priv->shared_dplls[i];
+               int enabled_crtcs = 0, active_crtcs = 0;
+               bool active;
+               memset(&dpll_hw_state, 0, sizeof(dpll_hw_state));
+               DRM_DEBUG_KMS("%s\n", pll->name);
+               active = pll->get_hw_state(dev_priv, pll, &dpll_hw_state);
+               WARN(pll->active > pll->refcount,
+                    "more active pll users than references: %i vs %i\n",
+                    pll->active, pll->refcount);
+               WARN(pll->active && !pll->on,
+                    "pll in active use but not on in sw tracking\n");
+               WARN(pll->on != active,
+                    "pll on state mismatch (expected %i, found %i)\n",
+                    pll->on, active);
+               list_for_each_entry(crtc, &dev->mode_config.crtc_list,
+                                   base.head) {
+                       if (crtc->base.enabled && intel_crtc_to_shared_dpll(crtc) == pll)
+                               enabled_crtcs++;
+                       if (crtc->active && intel_crtc_to_shared_dpll(crtc) == pll)
+                               active_crtcs++;
+               }
+               WARN(pll->active != active_crtcs,
+                    "pll active crtcs mismatch (expected %i, found %i)\n",
+                    pll->active, active_crtcs);
+               WARN(pll->refcount != enabled_crtcs,
+                    "pll enabled crtcs mismatch (expected %i, found %i)\n",
+                    pll->refcount, enabled_crtcs);
+               WARN(pll->on && memcmp(&pll->hw_state, &dpll_hw_state,
+                                      sizeof(dpll_hw_state)),
+                    "pll hw state mismatch\n");
+       }
+ }
+ void
+ intel_modeset_check_state(struct drm_device *dev)
+ {
+       check_connector_state(dev);
+       check_encoder_state(dev);
+       check_crtc_state(dev);
+       check_shared_dpll_state(dev);
+ }
  static int __intel_set_mode(struct drm_crtc *crtc,
                            struct drm_display_mode *mode,
                            int x, int y, struct drm_framebuffer *fb)
@@@ -8387,21 -8534,6 +8539,21 @@@ static void intel_set_config_restore_st
        }
  }
  
 +static bool
 +is_crtc_connector_off(struct drm_crtc *crtc, struct drm_connector *connectors,
 +                    int num_connectors)
 +{
 +      int i;
 +
 +      for (i = 0; i < num_connectors; i++)
 +              if (connectors[i].encoder &&
 +                  connectors[i].encoder->crtc == crtc &&
 +                  connectors[i].dpms != DRM_MODE_DPMS_ON)
 +                      return true;
 +
 +      return false;
 +}
 +
  static void
  intel_set_config_compute_mode_changes(struct drm_mode_set *set,
                                      struct intel_set_config *config)
  
        /* We should be able to check here if the fb has the same properties
         * and then just flip_or_move it */
 -      if (set->crtc->fb != set->fb) {
 +      if (set->connectors != NULL &&
 +          is_crtc_connector_off(set->crtc, *set->connectors,
 +                                set->num_connectors)) {
 +                      config->mode_changed = true;
 +      } else if (set->crtc->fb != set->fb) {
                /* If we have no fb then treat it as a full mode set */
                if (set->crtc->fb == NULL) {
                        DRM_DEBUG_KMS("crtc has no fb, full mode set\n");
                } else if (set->fb->pixel_format !=
                           set->crtc->fb->pixel_format) {
                        config->mode_changed = true;
 -              } else
 +              } else {
                        config->fb_changed = true;
 +              }
        }
  
        if (set->fb && (set->x != set->crtc->x || set->y != set->crtc->y))
@@@ -8593,6 -8720,11 +8745,6 @@@ static int intel_crtc_set_config(struc
        if (config->mode_changed) {
                ret = intel_set_mode(set->crtc, set->mode,
                                     set->x, set->y, set->fb);
 -              if (ret) {
 -                      DRM_ERROR("failed to set mode on [CRTC:%d], err = %d\n",
 -                                set->crtc->base.id, ret);
 -                      goto fail;
 -              }
        } else if (config->fb_changed) {
                intel_crtc_wait_for_pending_flips(set->crtc);
  
                                          set->x, set->y, set->fb);
        }
  
 -      intel_set_config_free(config);
 -
 -      return 0;
 -
 +      if (ret) {
 +              DRM_ERROR("failed to set mode on [CRTC:%d], err = %d\n",
 +                        set->crtc->base.id, ret);
  fail:
 -      intel_set_config_restore_state(dev, config);
 +              intel_set_config_restore_state(dev, config);
  
 -      /* Try to restore the config */
 -      if (config->mode_changed &&
 -          intel_set_mode(save_set.crtc, save_set.mode,
 -                         save_set.x, save_set.y, save_set.fb))
 -              DRM_ERROR("failed to restore config after modeset failure\n");
 +              /* Try to restore the config */
 +              if (config->mode_changed &&
 +                  intel_set_mode(save_set.crtc, save_set.mode,
 +                                 save_set.x, save_set.y, save_set.fb))
 +                      DRM_ERROR("failed to restore config after modeset failure\n");
 +      }
  
  out_config:
        intel_set_config_free(config);
@@@ -8633,23 -8765,93 +8785,93 @@@ static void intel_cpu_pll_init(struct d
                intel_ddi_pll_init(dev);
  }
  
- static void intel_pch_pll_init(struct drm_device *dev)
+ static bool ibx_pch_dpll_get_hw_state(struct drm_i915_private *dev_priv,
+                                     struct intel_shared_dpll *pll,
+                                     struct intel_dpll_hw_state *hw_state)
  {
-       drm_i915_private_t *dev_priv = dev->dev_private;
-       int i;
+       uint32_t val;
  
-       if (dev_priv->num_pch_pll == 0) {
-               DRM_DEBUG_KMS("No PCH PLLs on this hardware, skipping initialisation\n");
-               return;
+       val = I915_READ(PCH_DPLL(pll->id));
+       hw_state->dpll = val;
+       hw_state->fp0 = I915_READ(PCH_FP0(pll->id));
+       hw_state->fp1 = I915_READ(PCH_FP1(pll->id));
+       return val & DPLL_VCO_ENABLE;
+ }
+ static void ibx_pch_dpll_enable(struct drm_i915_private *dev_priv,
+                               struct intel_shared_dpll *pll)
+ {
+       uint32_t reg, val;
+       /* PCH refclock must be enabled first */
+       assert_pch_refclk_enabled(dev_priv);
+       reg = PCH_DPLL(pll->id);
+       val = I915_READ(reg);
+       val |= DPLL_VCO_ENABLE;
+       I915_WRITE(reg, val);
+       POSTING_READ(reg);
+       udelay(200);
+ }
+ static void ibx_pch_dpll_disable(struct drm_i915_private *dev_priv,
+                                struct intel_shared_dpll *pll)
+ {
+       struct drm_device *dev = dev_priv->dev;
+       struct intel_crtc *crtc;
+       uint32_t reg, val;
+       /* Make sure no transcoder isn't still depending on us. */
+       list_for_each_entry(crtc, &dev->mode_config.crtc_list, base.head) {
+               if (intel_crtc_to_shared_dpll(crtc) == pll)
+                       assert_pch_transcoder_disabled(dev_priv, crtc->pipe);
        }
  
-       for (i = 0; i < dev_priv->num_pch_pll; i++) {
-               dev_priv->pch_plls[i].pll_reg = _PCH_DPLL(i);
-               dev_priv->pch_plls[i].fp0_reg = _PCH_FP0(i);
-               dev_priv->pch_plls[i].fp1_reg = _PCH_FP1(i);
+       reg = PCH_DPLL(pll->id);
+       val = I915_READ(reg);
+       val &= ~DPLL_VCO_ENABLE;
+       I915_WRITE(reg, val);
+       POSTING_READ(reg);
+       udelay(200);
+ }
+ static char *ibx_pch_dpll_names[] = {
+       "PCH DPLL A",
+       "PCH DPLL B",
+ };
+ static void ibx_pch_dpll_init(struct drm_device *dev)
+ {
+       struct drm_i915_private *dev_priv = dev->dev_private;
+       int i;
+       dev_priv->num_shared_dpll = 2;
+       for (i = 0; i < dev_priv->num_shared_dpll; i++) {
+               dev_priv->shared_dplls[i].id = i;
+               dev_priv->shared_dplls[i].name = ibx_pch_dpll_names[i];
+               dev_priv->shared_dplls[i].enable = ibx_pch_dpll_enable;
+               dev_priv->shared_dplls[i].disable = ibx_pch_dpll_disable;
+               dev_priv->shared_dplls[i].get_hw_state =
+                       ibx_pch_dpll_get_hw_state;
        }
  }
  
+ static void intel_shared_dpll_init(struct drm_device *dev)
+ {
+       struct drm_i915_private *dev_priv = dev->dev_private;
+       if (HAS_PCH_IBX(dev) || HAS_PCH_CPT(dev))
+               ibx_pch_dpll_init(dev);
+       else
+               dev_priv->num_shared_dpll = 0;
+       BUG_ON(dev_priv->num_shared_dpll > I915_NUM_PLLS);
+       DRM_DEBUG_KMS("%i shared PLLs initialized\n",
+                     dev_priv->num_shared_dpll);
+ }
  static void intel_crtc_init(struct drm_device *dev, int pipe)
  {
        drm_i915_private_t *dev_priv = dev->dev_private;
@@@ -8754,13 -8956,8 +8976,8 @@@ static void intel_setup_outputs(struct 
        struct drm_i915_private *dev_priv = dev->dev_private;
        struct intel_encoder *encoder;
        bool dpd_is_edp = false;
-       bool has_lvds;
  
-       has_lvds = intel_lvds_init(dev);
-       if (!has_lvds && !HAS_PCH_SPLIT(dev)) {
-               /* disable the panel fitter on everything but LVDS */
-               I915_WRITE(PFIT_CONTROL, 0);
-       }
+       intel_lvds_init(dev);
  
        if (!IS_ULT(dev))
                intel_crt_init(dev);
@@@ -8941,8 -9138,7 +9158,8 @@@ int intel_framebuffer_init(struct drm_d
        case DRM_FORMAT_XRGB1555:
        case DRM_FORMAT_ARGB1555:
                if (INTEL_INFO(dev)->gen > 3) {
 -                      DRM_DEBUG("invalid format: 0x%08x\n", mode_cmd->pixel_format);
 +                      DRM_DEBUG("unsupported pixel format: %s\n",
 +                                drm_get_format_name(mode_cmd->pixel_format));
                        return -EINVAL;
                }
                break;
        case DRM_FORMAT_XBGR2101010:
        case DRM_FORMAT_ABGR2101010:
                if (INTEL_INFO(dev)->gen < 4) {
 -                      DRM_DEBUG("invalid format: 0x%08x\n", mode_cmd->pixel_format);
 +                      DRM_DEBUG("unsupported pixel format: %s\n",
 +                                drm_get_format_name(mode_cmd->pixel_format));
                        return -EINVAL;
                }
                break;
        case DRM_FORMAT_YVYU:
        case DRM_FORMAT_VYUY:
                if (INTEL_INFO(dev)->gen < 5) {
 -                      DRM_DEBUG("invalid format: 0x%08x\n", mode_cmd->pixel_format);
 +                      DRM_DEBUG("unsupported pixel format: %s\n",
 +                                drm_get_format_name(mode_cmd->pixel_format));
                        return -EINVAL;
                }
                break;
        default:
 -              DRM_DEBUG("unsupported pixel format 0x%08x\n", mode_cmd->pixel_format);
 +              DRM_DEBUG("unsupported pixel format: %s\n",
 +                        drm_get_format_name(mode_cmd->pixel_format));
                return -EINVAL;
        }
  
@@@ -9015,6 -9208,15 +9232,15 @@@ static void intel_init_display(struct d
  {
        struct drm_i915_private *dev_priv = dev->dev_private;
  
+       if (HAS_PCH_SPLIT(dev) || IS_G4X(dev))
+               dev_priv->display.find_dpll = g4x_find_best_dpll;
+       else if (IS_VALLEYVIEW(dev))
+               dev_priv->display.find_dpll = vlv_find_best_dpll;
+       else if (IS_PINEVIEW(dev))
+               dev_priv->display.find_dpll = pnv_find_best_dpll;
+       else
+               dev_priv->display.find_dpll = i9xx_find_best_dpll;
        if (HAS_DDI(dev)) {
                dev_priv->display.get_pipe_config = haswell_get_pipe_config;
                dev_priv->display.crtc_mode_set = haswell_crtc_mode_set;
@@@ -9333,7 -9535,7 +9559,7 @@@ void intel_modeset_init(struct drm_devi
        }
  
        intel_cpu_pll_init(dev);
-       intel_pch_pll_init(dev);
+       intel_shared_dpll_init(dev);
  
        /* Just disable it once at startup */
        i915_disable_vga(dev);
@@@ -9534,17 -9736,14 +9760,14 @@@ void i915_redisable_vga(struct drm_devi
        }
  }
  
- /* Scan out the current hw modeset state, sanitizes it and maps it into the drm
-  * and i915 state tracking structures. */
- void intel_modeset_setup_hw_state(struct drm_device *dev,
-                                 bool force_restore)
+ static void intel_modeset_readout_hw_state(struct drm_device *dev)
  {
        struct drm_i915_private *dev_priv = dev->dev_private;
        enum pipe pipe;
-       struct drm_plane *plane;
        struct intel_crtc *crtc;
        struct intel_encoder *encoder;
        struct intel_connector *connector;
+       int i;
  
        list_for_each_entry(crtc, &dev->mode_config.crtc_list,
                            base.head) {
                              crtc->active ? "enabled" : "disabled");
        }
  
+       /* FIXME: Smash this into the new shared dpll infrastructure. */
        if (HAS_DDI(dev))
                intel_ddi_setup_hw_pll_state(dev);
  
+       for (i = 0; i < dev_priv->num_shared_dpll; i++) {
+               struct intel_shared_dpll *pll = &dev_priv->shared_dplls[i];
+               pll->on = pll->get_hw_state(dev_priv, pll, &pll->hw_state);
+               pll->active = 0;
+               list_for_each_entry(crtc, &dev->mode_config.crtc_list,
+                                   base.head) {
+                       if (crtc->active && intel_crtc_to_shared_dpll(crtc) == pll)
+                               pll->active++;
+               }
+               pll->refcount = pll->active;
+               DRM_DEBUG_KMS("%s hw state readout: refcount %i\n",
+                             pll->name, pll->refcount);
+       }
        list_for_each_entry(encoder, &dev->mode_config.encoder_list,
                            base.head) {
                pipe = 0;
                              drm_get_connector_name(&connector->base),
                              connector->base.encoder ? "enabled" : "disabled");
        }
+ }
+ /* Scan out the current hw modeset state, sanitizes it and maps it into the drm
+  * and i915 state tracking structures. */
+ void intel_modeset_setup_hw_state(struct drm_device *dev,
+                                 bool force_restore)
+ {
+       struct drm_i915_private *dev_priv = dev->dev_private;
+       enum pipe pipe;
+       struct drm_plane *plane;
+       struct intel_crtc *crtc;
+       struct intel_encoder *encoder;
+       intel_modeset_readout_hw_state(dev);
  
        /* HW state is read out, now we need to sanitize this mess. */
        list_for_each_entry(encoder, &dev->mode_config.encoder_list,
index 91a31b3b98295107096b6e3c94431ec05478d0c2,6d560755cf53ecd02c1a87e0cc522b8529174506..98686005dcf64f98edb9bd1b27537764180ef833
@@@ -260,7 -260,7 +260,7 @@@ intel_dp_aux_wait_done(struct intel_dp 
  #define C (((status = I915_READ_NOTRACE(ch_ctl)) & DP_AUX_CH_CTL_SEND_BUSY) == 0)
        if (has_aux_irq)
                done = wait_event_timeout(dev_priv->gmbus_wait_queue, C,
 -                                        msecs_to_jiffies(10));
 +                                        msecs_to_jiffies_timeout(10));
        else
                done = wait_for_atomic(C, 10) == 0;
        if (!done)
@@@ -677,7 -677,7 +677,7 @@@ intel_dp_compute_config(struct intel_en
        int max_clock = intel_dp_max_link_bw(intel_dp) == DP_LINK_BW_2_7 ? 1 : 0;
        int bpp, mode_rate;
        static int bws[2] = { DP_LINK_BW_1_62, DP_LINK_BW_2_7 };
-       int target_clock, link_avail, link_clock;
+       int link_avail, link_clock;
  
        if (HAS_PCH_SPLIT(dev) && !HAS_DDI(dev) && port != PORT_A)
                pipe_config->has_pch_encoder = true;
                        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;
  
        if (adjusted_mode->flags & DRM_MODE_FLAG_DBLCLK)
                return false;
  
        /* Walk through all bpp values. Luckily they're all nicely spaced with 2
         * bpc in between. */
-       bpp = min_t(int, 8*3, pipe_config->pipe_bpp);
+       bpp = pipe_config->pipe_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);
+               mode_rate = intel_dp_link_required(adjusted_mode->clock, bpp);
  
                for (clock = 0; clock <= max_clock; clock++) {
                        for (lane_count = 1; lane_count <= max_lane_count; lane_count <<= 1) {
@@@ -746,18 -744,17 +744,17 @@@ 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;
+       pipe_config->port_clock = drm_dp_bw_code_to_link_rate(intel_dp->link_bw);
  
        DRM_DEBUG_KMS("DP link bw %02x lane count %d clock %d bpp %d\n",
                      intel_dp->link_bw, intel_dp->lane_count,
-                     adjusted_mode->clock, bpp);
+                     pipe_config->port_clock, bpp);
        DRM_DEBUG_KMS("DP link bw required %i available %i\n",
                      mode_rate, link_avail);
  
        intel_link_compute_m_n(bpp, lane_count,
-                              target_clock, adjusted_mode->clock,
+                              adjusted_mode->clock, pipe_config->port_clock,
                               &pipe_config->dp_m_n);
  
        intel_dp_set_clock(encoder, pipe_config, intel_dp->link_bw);
@@@ -780,24 -777,28 +777,28 @@@ void intel_dp_init_link_config(struct i
        }
  }
  
- static void ironlake_set_pll_edp(struct drm_crtc *crtc, int clock)
+ static void ironlake_set_pll_cpu_edp(struct intel_dp *intel_dp)
  {
-       struct drm_device *dev = crtc->dev;
+       struct intel_digital_port *dig_port = dp_to_dig_port(intel_dp);
+       struct intel_crtc *crtc = to_intel_crtc(dig_port->base.base.crtc);
+       struct drm_device *dev = crtc->base.dev;
        struct drm_i915_private *dev_priv = dev->dev_private;
        u32 dpa_ctl;
  
-       DRM_DEBUG_KMS("eDP PLL enable for clock %d\n", clock);
+       DRM_DEBUG_KMS("eDP PLL enable for clock %d\n", crtc->config.port_clock);
        dpa_ctl = I915_READ(DP_A);
        dpa_ctl &= ~DP_PLL_FREQ_MASK;
  
-       if (clock < 200000) {
+       if (crtc->config.port_clock == 162000) {
                /* For a long time we've carried around a ILK-DevA w/a for the
                 * 160MHz clock. If we're really unlucky, it's still required.
                 */
                DRM_DEBUG_KMS("160MHz cpu eDP clock, might need ilk devA w/a\n");
                dpa_ctl |= DP_PLL_FREQ_160MHZ;
+               intel_dp->DP |= DP_PLL_FREQ_160MHZ;
        } else {
                dpa_ctl |= DP_PLL_FREQ_270MHZ;
+               intel_dp->DP |= DP_PLL_FREQ_270MHZ;
        }
  
        I915_WRITE(DP_A, dpa_ctl);
@@@ -814,8 -815,7 +815,7 @@@ intel_dp_mode_set(struct drm_encoder *e
        struct drm_i915_private *dev_priv = dev->dev_private;
        struct intel_dp *intel_dp = enc_to_intel_dp(encoder);
        enum port port = dp_to_dig_port(intel_dp)->port;
-       struct drm_crtc *crtc = encoder->crtc;
-       struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
+       struct intel_crtc *crtc = to_intel_crtc(encoder->crtc);
  
        /*
         * There are four kinds of DP registers:
  
        if (intel_dp->has_audio) {
                DRM_DEBUG_DRIVER("Enabling DP audio on pipe %c\n",
-                                pipe_name(intel_crtc->pipe));
+                                pipe_name(crtc->pipe));
                intel_dp->DP |= DP_AUDIO_OUTPUT_ENABLE;
                intel_write_eld(encoder, adjusted_mode);
        }
                if (intel_dp->link_configuration[1] & DP_LANE_COUNT_ENHANCED_FRAME_EN)
                        intel_dp->DP |= DP_ENHANCED_FRAMING;
  
-               intel_dp->DP |= intel_crtc->pipe << 29;
-               /* don't miss out required setting for eDP */
-               if (adjusted_mode->clock < 200000)
-                       intel_dp->DP |= DP_PLL_FREQ_160MHZ;
-               else
-                       intel_dp->DP |= DP_PLL_FREQ_270MHZ;
+               intel_dp->DP |= crtc->pipe << 29;
        } else if (!HAS_PCH_CPT(dev) || port == PORT_A) {
                if (!HAS_PCH_SPLIT(dev) && !IS_VALLEYVIEW(dev))
                        intel_dp->DP |= intel_dp->color_range;
                if (intel_dp->link_configuration[1] & DP_LANE_COUNT_ENHANCED_FRAME_EN)
                        intel_dp->DP |= DP_ENHANCED_FRAMING;
  
-               if (intel_crtc->pipe == 1)
+               if (crtc->pipe == 1)
                        intel_dp->DP |= DP_PIPEB_SELECT;
-               if (port == PORT_A && !IS_VALLEYVIEW(dev)) {
-                       /* don't miss out required setting for eDP */
-                       if (adjusted_mode->clock < 200000)
-                               intel_dp->DP |= DP_PLL_FREQ_160MHZ;
-                       else
-                               intel_dp->DP |= DP_PLL_FREQ_270MHZ;
-               }
        } else {
                intel_dp->DP |= DP_LINK_TRAIN_OFF_CPT;
        }
  
        if (port == PORT_A && !IS_VALLEYVIEW(dev))
-               ironlake_set_pll_edp(crtc, adjusted_mode->clock);
+               ironlake_set_pll_cpu_edp(intel_dp);
  }
  
  #define IDLE_ON_MASK          (PP_ON | 0        | PP_SEQUENCE_MASK | 0                     | PP_SEQUENCE_STATE_MASK)
index 3b03c3c6cc5d410197082c6fbd2d897c952032f6,244060ad354bcb12b18eb018a11b1de23111cfc4..dff669e2387f4e5aa8fd84433935e4603ec43992
@@@ -60,8 -60,9 +60,9 @@@ static struct fb_ops intelfb_ops = 
  static int intelfb_create(struct drm_fb_helper *helper,
                          struct drm_fb_helper_surface_size *sizes)
  {
-       struct intel_fbdev *ifbdev = (struct intel_fbdev *)helper;
-       struct drm_device *dev = ifbdev->helper.dev;
+       struct intel_fbdev *ifbdev =
+               container_of(helper, struct intel_fbdev, helper);
+       struct drm_device *dev = helper->dev;
        struct drm_i915_private *dev_priv = dev->dev_private;
        struct fb_info *info;
        struct drm_framebuffer *fb;
                goto out_unpin;
        }
  
-       info->par = ifbdev;
+       info->par = helper;
  
        ret = intel_framebuffer_init(dev, &ifbdev->ifb, &mode_cmd, obj);
        if (ret)
@@@ -217,7 -218,7 +218,7 @@@ static void intel_fbdev_destroy(struct 
  int intel_fbdev_init(struct drm_device *dev)
  {
        struct intel_fbdev *ifbdev;
-       drm_i915_private_t *dev_priv = dev->dev_private;
+       struct drm_i915_private *dev_priv = dev->dev_private;
        int ret;
  
        ifbdev = kzalloc(sizeof(struct intel_fbdev), GFP_KERNEL);
  
  void intel_fbdev_initial_config(struct drm_device *dev)
  {
-       drm_i915_private_t *dev_priv = dev->dev_private;
+       struct drm_i915_private *dev_priv = dev->dev_private;
  
        /* Due to peculiar init order wrt to hpd handling this is separate. */
        drm_fb_helper_initial_config(&dev_priv->fbdev->helper, 32);
  
  void intel_fbdev_fini(struct drm_device *dev)
  {
-       drm_i915_private_t *dev_priv = dev->dev_private;
+       struct drm_i915_private *dev_priv = dev->dev_private;
        if (!dev_priv->fbdev)
                return;
  
  
  void intel_fbdev_set_suspend(struct drm_device *dev, int state)
  {
-       drm_i915_private_t *dev_priv = dev->dev_private;
+       struct drm_i915_private *dev_priv = dev->dev_private;
        struct intel_fbdev *ifbdev = dev_priv->fbdev;
        struct fb_info *info;
  
         * been restored from swap. If the object is stolen however, it will be
         * full of whatever garbage was left in there.
         */
-       if (!state && ifbdev->ifb.obj->stolen)
+       if (state == FBINFO_STATE_RUNNING && ifbdev->ifb.obj->stolen)
                memset_io(info->screen_base, 0, info->screen_size);
  
        fb_set_suspend(info, state);
@@@ -284,14 -285,16 +285,14 @@@ MODULE_LICENSE("GPL and additional righ
  
  void intel_fb_output_poll_changed(struct drm_device *dev)
  {
-       drm_i915_private_t *dev_priv = dev->dev_private;
+       struct drm_i915_private *dev_priv = dev->dev_private;
        drm_fb_helper_hotplug_event(&dev_priv->fbdev->helper);
  }
  
  void intel_fb_restore_mode(struct drm_device *dev)
  {
        int ret;
-       drm_i915_private_t *dev_priv = dev->dev_private;
+       struct drm_i915_private *dev_priv = dev->dev_private;
 -      struct drm_mode_config *config = &dev->mode_config;
 -      struct drm_plane *plane;
  
        if (INTEL_INFO(dev)->num_pipes == 0)
                return;
        if (ret)
                DRM_DEBUG("failed to restore crtc mode\n");
  
 -      /* Be sure to shut off any planes that may be active */
 -      list_for_each_entry(plane, &config->plane_list, head)
 -              if (plane->enabled)
 -                      plane->funcs->disable_plane(plane);
 -
        drm_modeset_unlock_all(dev);
  }
index 0ef8b4dc835f856f56412164c42e7c3647cc1390,eeff28ec2ff42468e2d2a076e35f863edefc22f6..2abb2d3c727b8044fc3eef6a6929769d8d4a0cd7
@@@ -264,9 -264,6 +264,6 @@@ static bool intel_lvds_compute_config(s
                return false;
        }
  
-       if (intel_encoder_check_is_cloned(&lvds_encoder->base))
-               return false;
        if ((I915_READ(lvds_encoder->reg) & LVDS_A3_POWER_MASK) ==
            LVDS_A3_POWER_UP)
                lvds_bpp = 8*3;
@@@ -639,10 -636,10 +636,10 @@@ static const struct dmi_system_id intel
        },
        {
                .callback = intel_no_lvds_dmi_callback,
 -              .ident = "Hewlett-Packard HP t5740e Thin Client",
 +              .ident = "Hewlett-Packard HP t5740",
                .matches = {
                        DMI_MATCH(DMI_BOARD_VENDOR, "Hewlett-Packard"),
 -                      DMI_MATCH(DMI_PRODUCT_NAME, "HP t5740e Thin Client"),
 +                      DMI_MATCH(DMI_PRODUCT_NAME, " t5740"),
                },
        },
        {
@@@ -880,7 -877,7 +877,7 @@@ static bool intel_lvds_supported(struc
   * Create the connector, register the LVDS DDC bus, and try to figure out what
   * modes we can display on the LVDS panel (if present).
   */
bool intel_lvds_init(struct drm_device *dev)
void intel_lvds_init(struct drm_device *dev)
  {
        struct drm_i915_private *dev_priv = dev->dev_private;
        struct intel_lvds_encoder *lvds_encoder;
        u8 pin;
  
        if (!intel_lvds_supported(dev))
-               return false;
+               return;
  
        /* Skip init on machines we know falsely report LVDS */
        if (dmi_check_system(intel_no_lvds))
-               return false;
+               return;
  
        pin = GMBUS_PORT_PANEL;
        if (!lvds_is_present_in_vbt(dev, &pin)) {
                DRM_DEBUG_KMS("LVDS is not present in VBT\n");
-               return false;
+               return;
        }
  
        if (HAS_PCH_SPLIT(dev)) {
                if ((I915_READ(PCH_LVDS) & LVDS_DETECTED) == 0)
-                       return false;
+                       return;
                if (dev_priv->vbt.edp_support) {
                        DRM_DEBUG_KMS("disable LVDS for eDP support\n");
-                       return false;
+                       return;
                }
        }
  
        lvds_encoder = kzalloc(sizeof(struct intel_lvds_encoder), GFP_KERNEL);
        if (!lvds_encoder)
-               return false;
+               return;
  
        lvds_connector = kzalloc(sizeof(struct intel_lvds_connector), GFP_KERNEL);
        if (!lvds_connector) {
                kfree(lvds_encoder);
-               return false;
+               return;
        }
  
        lvds_encoder->attached_connector = lvds_connector;
@@@ -1097,7 -1094,7 +1094,7 @@@ out
        intel_panel_init(&intel_connector->panel, fixed_mode);
        intel_panel_setup_backlight(connector);
  
-       return true;
+       return;
  
  failed:
        DRM_DEBUG_KMS("No LVDS modes found, disabling.\n");
                drm_mode_destroy(dev, fixed_mode);
        kfree(lvds_encoder);
        kfree(lvds_connector);
-       return false;
+       return;
  }
index c5584193770522b2d9e0ec9bc4daceea46f3a954,b8e1623be30d57a70570536f4f7aa2d1a771c712..2628d56224499307cffa4e409a646122a9578db0
@@@ -80,7 -80,7 +80,7 @@@ struct intel_sdvo 
  
        /*
         * Capabilities of the SDVO device returned by
-        * i830_sdvo_get_capabilities()
+        * intel_sdvo_get_capabilities()
         */
        struct intel_sdvo_caps caps;
  
@@@ -1219,6 -1219,7 +1219,7 @@@ static void intel_sdvo_mode_set(struct 
  
        switch (intel_crtc->config.pixel_multiplier) {
        default:
+               WARN(1, "unknown pixel mutlipler specified\n");
        case 1: rate = SDVO_CLOCK_RATE_MULT_1X; break;
        case 2: rate = SDVO_CLOCK_RATE_MULT_2X; break;
        case 4: rate = SDVO_CLOCK_RATE_MULT_4X; break;
@@@ -1276,7 -1277,7 +1277,7 @@@ static bool intel_sdvo_connector_get_hw
        struct intel_sdvo_connector *intel_sdvo_connector =
                to_intel_sdvo_connector(&connector->base);
        struct intel_sdvo *intel_sdvo = intel_attached_sdvo(&connector->base);
-       u16 active_outputs;
+       u16 active_outputs = 0;
  
        intel_sdvo_get_active_outputs(intel_sdvo, &active_outputs);
  
@@@ -1292,7 -1293,7 +1293,7 @@@ static bool intel_sdvo_get_hw_state(str
        struct drm_device *dev = encoder->base.dev;
        struct drm_i915_private *dev_priv = dev->dev_private;
        struct intel_sdvo *intel_sdvo = to_intel_sdvo(&encoder->base);
-       u16 active_outputs;
+       u16 active_outputs = 0;
        u32 tmp;
  
        tmp = I915_READ(intel_sdvo->sdvo_reg);
  static void intel_sdvo_get_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 intel_sdvo *intel_sdvo = to_intel_sdvo(&encoder->base);
        struct intel_sdvo_dtd dtd;
-       u32 flags = 0;
+       int encoder_pixel_multiplier = 0;
+       u32 flags = 0, sdvox;
+       u8 val;
        bool ret;
  
        ret = intel_sdvo_get_input_timing(intel_sdvo, &dtd);
        if (!ret) {
+               /* Some sdvo encoders are not spec compliant and don't
+                * implement the mandatory get_timings function. */
                DRM_DEBUG_DRIVER("failed to retrieve SDVO DTD\n");
-               return;
+               pipe_config->quirks |= PIPE_CONFIG_QUIRK_MODE_SYNC_FLAGS;
+       } else {
+               if (dtd.part2.dtd_flags & DTD_FLAG_HSYNC_POSITIVE)
+                       flags |= DRM_MODE_FLAG_PHSYNC;
+               else
+                       flags |= DRM_MODE_FLAG_NHSYNC;
+               if (dtd.part2.dtd_flags & DTD_FLAG_VSYNC_POSITIVE)
+                       flags |= DRM_MODE_FLAG_PVSYNC;
+               else
+                       flags |= DRM_MODE_FLAG_NVSYNC;
        }
  
-       if (dtd.part2.dtd_flags & DTD_FLAG_HSYNC_POSITIVE)
-               flags |= DRM_MODE_FLAG_PHSYNC;
-       else
-               flags |= DRM_MODE_FLAG_NHSYNC;
+       pipe_config->adjusted_mode.flags |= flags;
  
-       if (dtd.part2.dtd_flags & DTD_FLAG_VSYNC_POSITIVE)
-               flags |= DRM_MODE_FLAG_PVSYNC;
-       else
-               flags |= DRM_MODE_FLAG_NVSYNC;
+       /*
+        * pixel multiplier readout is tricky: Only on i915g/gm it is stored in
+        * the sdvo port register, on all other platforms it is part of the dpll
+        * state. Since the general pipe state readout happens before the
+        * encoder->get_config we so already have a valid pixel multplier on all
+        * other platfroms.
+        */
+       if (IS_I915G(dev) || IS_I915GM(dev)) {
+               sdvox = I915_READ(intel_sdvo->sdvo_reg);
+               pipe_config->pixel_multiplier =
+                       ((sdvox & SDVO_PORT_MULTIPLY_MASK)
+                        >> SDVO_PORT_MULTIPLY_SHIFT) + 1;
+       }
  
-       pipe_config->adjusted_mode.flags |= flags;
+       /* Cross check the port pixel multiplier with the sdvo encoder state. */
+       intel_sdvo_get_value(intel_sdvo, SDVO_CMD_GET_CLOCK_RATE_MULT, &val, 1);
+       switch (val) {
+       case SDVO_CLOCK_RATE_MULT_1X:
+               encoder_pixel_multiplier = 1;
+               break;
+       case SDVO_CLOCK_RATE_MULT_2X:
+               encoder_pixel_multiplier = 2;
+               break;
+       case SDVO_CLOCK_RATE_MULT_4X:
+               encoder_pixel_multiplier = 4;
+               break;
+       }
+       if(HAS_PCH_SPLIT(dev))
+               return; /* no pixel multiplier readout support yet */
+       WARN(encoder_pixel_multiplier != pipe_config->pixel_multiplier,
+            "SDVO pixel multiplier mismatch, port: %i, encoder: %i\n",
+            pipe_config->pixel_multiplier, encoder_pixel_multiplier);
  }
  
  static void intel_disable_sdvo(struct intel_encoder *encoder)
@@@ -1844,9 -1886,15 +1886,9 @@@ static void intel_sdvo_get_lvds_modes(s
        struct drm_display_mode *newmode;
  
        /*
 -       * Attempt to get the mode list from DDC.
 -       * Assume that the preferred modes are
 -       * arranged in priority order.
 +       * Fetch modes from VBT. For SDVO prefer the VBT mode since some
 +       * SDVO->LVDS transcoders can't cope with the EDID mode.
         */
 -      intel_ddc_get_modes(connector, intel_sdvo->i2c);
 -      if (list_empty(&connector->probed_modes) == false)
 -              goto end;
 -
 -      /* Fetch modes from VBT */
        if (dev_priv->vbt.sdvo_lvds_vbt_mode != NULL) {
                newmode = drm_mode_duplicate(connector->dev,
                                             dev_priv->vbt.sdvo_lvds_vbt_mode);
                }
        }
  
 -end:
 +      /*
 +       * Attempt to get the mode list from DDC.
 +       * Assume that the preferred modes are
 +       * arranged in priority order.
 +       */
 +      intel_ddc_get_modes(connector, &intel_sdvo->ddc);
 +
        list_for_each_entry(newmode, &connector->probed_modes, head) {
                if (newmode->type & DRM_MODE_TYPE_PREFERRED) {
                        intel_sdvo->sdvo_lvds_fixed_mode =
@@@ -2819,7 -2861,6 +2861,6 @@@ bool intel_sdvo_init(struct drm_device 
        struct drm_i915_private *dev_priv = dev->dev_private;
        struct intel_encoder *intel_encoder;
        struct intel_sdvo *intel_sdvo;
-       u32 hotplug_mask;
        int i;
        intel_sdvo = kzalloc(sizeof(struct intel_sdvo), GFP_KERNEL);
        if (!intel_sdvo)
                }
        }
  
-       hotplug_mask = 0;
-       if (IS_G4X(dev)) {
-               hotplug_mask = intel_sdvo->is_sdvob ?
-                       SDVOB_HOTPLUG_INT_STATUS_G4X : SDVOC_HOTPLUG_INT_STATUS_G4X;
-       } else if (IS_GEN4(dev)) {
-               hotplug_mask = intel_sdvo->is_sdvob ?
-                       SDVOB_HOTPLUG_INT_STATUS_I965 : SDVOC_HOTPLUG_INT_STATUS_I965;
-       } else {
-               hotplug_mask = intel_sdvo->is_sdvob ?
-                       SDVOB_HOTPLUG_INT_STATUS_I915 : SDVOC_HOTPLUG_INT_STATUS_I915;
-       }
 -      /* Only enable the hotplug irq if we need it, to work around noisy
 -       * hotplug lines.
 -       */
 -      if (intel_sdvo->hotplug_active)
 -              intel_encoder->hpd_pin = HPD_SDVO_B ? HPD_SDVO_B : HPD_SDVO_C;
--
        intel_encoder->compute_config = intel_sdvo_compute_config;
        intel_encoder->disable = intel_disable_sdvo;
        intel_encoder->mode_set = intel_sdvo_mode_set;
                goto err_output;
        }
  
 +      /* Only enable the hotplug irq if we need it, to work around noisy
 +       * hotplug lines.
 +       */
 +      if (intel_sdvo->hotplug_active) {
 +              intel_encoder->hpd_pin =
 +                      intel_sdvo->is_sdvob ?  HPD_SDVO_B : HPD_SDVO_C;
 +      }
 +
        /*
         * Cloning SDVO with anything is often impossible, since the SDVO
         * encoder can request a special input timing mode. And even if that's