--- /dev/null
+From 9f15d0cf8e4481943f8b11b37d07a77b4b8c7831 Mon Sep 17 00:00:00 2001
+From: Adam Jackson <ajax@redhat.com>
+Date: Wed, 23 May 2012 16:26:54 -0400
+Subject: drm/edid/quirks: ViewSonic VA2026w
+
+From: Adam Jackson <ajax@redhat.com>
+
+commit bc42aabc6a01b92b0f961d65671564e0e1cd7592 upstream.
+
+Entirely new class of fail for this one. The detailed timings are for
+normal CVT but the monitor really wanted CVT-R.
+
+Bugzilla: http://bugzilla.redhat/com/516471
+Signed-off-by: Adam Jackson <ajax@redhat.com>
+Signed-off-by: Dave Airlie <airlied@redhat.com>
+Signed-off-by: Julien Cristau <jcristau@debian.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/gpu/drm/drm_edid.c | 22 ++++++++++++++++++----
+ 1 file changed, 18 insertions(+), 4 deletions(-)
+
+--- a/drivers/gpu/drm/drm_edid.c
++++ b/drivers/gpu/drm/drm_edid.c
+@@ -66,6 +66,8 @@
+ #define EDID_QUIRK_FIRST_DETAILED_PREFERRED (1 << 5)
+ /* use +hsync +vsync for detailed mode */
+ #define EDID_QUIRK_DETAILED_SYNC_PP (1 << 6)
++/* Force reduced-blanking timings for detailed modes */
++#define EDID_QUIRK_FORCE_REDUCED_BLANKING (1 << 7)
+
+ struct detailed_mode_closure {
+ struct drm_connector *connector;
+@@ -120,6 +122,9 @@ static struct edid_quirk {
+ /* Samsung SyncMaster 22[5-6]BW */
+ { "SAM", 596, EDID_QUIRK_PREFER_LARGE_60 },
+ { "SAM", 638, EDID_QUIRK_PREFER_LARGE_60 },
++
++ /* ViewSonic VA2026w */
++ { "VSC", 5020, EDID_QUIRK_FORCE_REDUCED_BLANKING },
+ };
+
+ /*** DDC fetch and block validation ***/
+@@ -852,12 +857,19 @@ static struct drm_display_mode *drm_mode
+ "Wrong Hsync/Vsync pulse width\n");
+ return NULL;
+ }
++
++ if (quirks & EDID_QUIRK_FORCE_REDUCED_BLANKING) {
++ mode = drm_cvt_mode(dev, hactive, vactive, 60, true, false, false);
++ if (!mode)
++ return NULL;
++
++ goto set_size;
++ }
++
+ mode = drm_mode_create(dev);
+ if (!mode)
+ return NULL;
+
+- mode->type = DRM_MODE_TYPE_DRIVER;
+-
+ if (quirks & EDID_QUIRK_135_CLOCK_TOO_HIGH)
+ timing->pixel_clock = cpu_to_le16(1088);
+
+@@ -881,8 +893,6 @@ static struct drm_display_mode *drm_mode
+
+ drm_mode_do_interlace_quirk(mode, pt);
+
+- drm_mode_set_name(mode);
+-
+ if (quirks & EDID_QUIRK_DETAILED_SYNC_PP) {
+ pt->misc |= DRM_EDID_PT_HSYNC_POSITIVE | DRM_EDID_PT_VSYNC_POSITIVE;
+ }
+@@ -892,6 +902,7 @@ static struct drm_display_mode *drm_mode
+ mode->flags |= (pt->misc & DRM_EDID_PT_VSYNC_POSITIVE) ?
+ DRM_MODE_FLAG_PVSYNC : DRM_MODE_FLAG_NVSYNC;
+
++set_size:
+ mode->width_mm = pt->width_mm_lo | (pt->width_height_mm_hi & 0xf0) << 4;
+ mode->height_mm = pt->height_mm_lo | (pt->width_height_mm_hi & 0xf) << 8;
+
+@@ -905,6 +916,9 @@ static struct drm_display_mode *drm_mode
+ mode->height_mm = edid->height_cm * 10;
+ }
+
++ mode->type = DRM_MODE_TYPE_DRIVER;
++ drm_mode_set_name(mode);
++
+ return mode;
+ }
+
--- /dev/null
+From 5b6fd09a2834879518f22ed3ac6917a48ef4f15e Mon Sep 17 00:00:00 2001
+From: Chris Wilson <chris@chris-wilson.co.uk>
+Date: Tue, 17 Apr 2012 19:35:53 +0100
+Subject: drm/i915: Unpin the flip target if we fail to queue the flip
+
+From: Chris Wilson <chris@chris-wilson.co.uk>
+
+commit 83d4092b0381e5dd6f312b2ec57121dcf0fcbade upstream.
+
+Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
+Cc: Jesse Barnes <jbarnes@virtuousgeek.org>
+Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
+Signed-off-by: Julien Cristau <jcristau@debian.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/gpu/drm/i915/intel_display.c | 50 ++++++++++++++++++++++++-----------
+ 1 file changed, 35 insertions(+), 15 deletions(-)
+
+--- a/drivers/gpu/drm/i915/intel_display.c
++++ b/drivers/gpu/drm/i915/intel_display.c
+@@ -7313,14 +7313,14 @@ static int intel_gen2_queue_flip(struct
+
+ ret = intel_pin_and_fence_fb_obj(dev, obj, LP_RING(dev_priv));
+ if (ret)
+- goto out;
++ goto err;
+
+ /* Offset into the new buffer for cases of shared fbs between CRTCs */
+ offset = crtc->y * fb->pitches[0] + crtc->x * fb->bits_per_pixel/8;
+
+ ret = BEGIN_LP_RING(6);
+ if (ret)
+- goto out;
++ goto err_unpin;
+
+ /* Can't queue multiple flips, so wait for the previous
+ * one to finish before executing the next.
+@@ -7337,7 +7337,11 @@ static int intel_gen2_queue_flip(struct
+ OUT_RING(obj->gtt_offset + offset);
+ OUT_RING(0); /* aux display base address, unused */
+ ADVANCE_LP_RING();
+-out:
++ return 0;
++
++err_unpin:
++ intel_unpin_fb_obj(obj);
++err:
+ return ret;
+ }
+
+@@ -7354,14 +7358,14 @@ static int intel_gen3_queue_flip(struct
+
+ ret = intel_pin_and_fence_fb_obj(dev, obj, LP_RING(dev_priv));
+ if (ret)
+- goto out;
++ goto err;
+
+ /* Offset into the new buffer for cases of shared fbs between CRTCs */
+ offset = crtc->y * fb->pitches[0] + crtc->x * fb->bits_per_pixel/8;
+
+ ret = BEGIN_LP_RING(6);
+ if (ret)
+- goto out;
++ goto err_unpin;
+
+ if (intel_crtc->plane)
+ flip_mask = MI_WAIT_FOR_PLANE_B_FLIP;
+@@ -7376,7 +7380,11 @@ static int intel_gen3_queue_flip(struct
+ OUT_RING(MI_NOOP);
+
+ ADVANCE_LP_RING();
+-out:
++ return 0;
++
++err_unpin:
++ intel_unpin_fb_obj(obj);
++err:
+ return ret;
+ }
+
+@@ -7392,11 +7400,11 @@ static int intel_gen4_queue_flip(struct
+
+ ret = intel_pin_and_fence_fb_obj(dev, obj, LP_RING(dev_priv));
+ if (ret)
+- goto out;
++ goto err;
+
+ ret = BEGIN_LP_RING(4);
+ if (ret)
+- goto out;
++ goto err_unpin;
+
+ /* i965+ uses the linear or tiled offsets from the
+ * Display Registers (which do not change across a page-flip)
+@@ -7415,7 +7423,11 @@ static int intel_gen4_queue_flip(struct
+ pipesrc = I915_READ(PIPESRC(intel_crtc->pipe)) & 0x0fff0fff;
+ OUT_RING(pf | pipesrc);
+ ADVANCE_LP_RING();
+-out:
++ return 0;
++
++err_unpin:
++ intel_unpin_fb_obj(obj);
++err:
+ return ret;
+ }
+
+@@ -7431,11 +7443,11 @@ static int intel_gen6_queue_flip(struct
+
+ ret = intel_pin_and_fence_fb_obj(dev, obj, LP_RING(dev_priv));
+ if (ret)
+- goto out;
++ goto err;
+
+ ret = BEGIN_LP_RING(4);
+ if (ret)
+- goto out;
++ goto err_unpin;
+
+ OUT_RING(MI_DISPLAY_FLIP |
+ MI_DISPLAY_FLIP_PLANE(intel_crtc->plane));
+@@ -7452,7 +7464,11 @@ static int intel_gen6_queue_flip(struct
+ pipesrc = I915_READ(PIPESRC(intel_crtc->pipe)) & 0x0fff0fff;
+ OUT_RING(pf | pipesrc);
+ ADVANCE_LP_RING();
+-out:
++ return 0;
++
++err_unpin:
++ intel_unpin_fb_obj(obj);
++err:
+ return ret;
+ }
+
+@@ -7474,18 +7490,22 @@ static int intel_gen7_queue_flip(struct
+
+ ret = intel_pin_and_fence_fb_obj(dev, obj, ring);
+ if (ret)
+- goto out;
++ goto err;
+
+ ret = intel_ring_begin(ring, 4);
+ if (ret)
+- goto out;
++ goto err_unpin;
+
+ intel_ring_emit(ring, MI_DISPLAY_FLIP_I915 | (intel_crtc->plane << 19));
+ intel_ring_emit(ring, (fb->pitches[0] | obj->tiling_mode));
+ intel_ring_emit(ring, (obj->gtt_offset));
+ intel_ring_emit(ring, (MI_NOOP));
+ intel_ring_advance(ring);
+-out:
++ return 0;
++
++err_unpin:
++ intel_unpin_fb_obj(obj);
++err:
+ return ret;
+ }
+
--- /dev/null
+From 40e9b8bb59c2b168523a91e5e319d6339047b499 Mon Sep 17 00:00:00 2001
+From: Daniel Vetter <daniel.vetter@ffwll.ch>
+Date: Wed, 23 May 2012 14:02:00 +0200
+Subject: drm/i915: fix up ivb plane 3 pageflips
+
+From: Daniel Vetter <daniel.vetter@ffwll.ch>
+
+commit cb05d8dedefa3066bf5d74ef88c6ca6cf4bd1c87 upstream.
+
+Or at least plug another gapping hole. Apparrently hw desingers only
+moved the bit field, but did not bother ot re-enumerate the planes
+when adding support for a 3rd pipe.
+
+Discovered by i-g-t/flip_test.
+
+This may or may not fix the reference bugzilla, because that one
+smells like we have still larger fish to fry.
+
+v2: Fixup the impossible case to catch programming errors, noticed by
+Chris Wilson.
+
+References: https://bugs.freedesktop.org/show_bug.cgi?id=50069
+Acked-by: Chris Wilson <chris@chris-wilson.co.uk>
+Tested-by: Eugeni Dodonov <eugeni.dodonov@intel.com>
+Eugeni Dodonov <eugeni.dodonov@intel.com>
+Signed-Off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
+Signed-off-by: Julien Cristau <jcristau@debian.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/gpu/drm/i915/i915_reg.h | 8 ++++++++
+ drivers/gpu/drm/i915/intel_display.c | 19 ++++++++++++++++++-
+ 2 files changed, 26 insertions(+), 1 deletion(-)
+
+--- a/drivers/gpu/drm/i915/i915_reg.h
++++ b/drivers/gpu/drm/i915/i915_reg.h
+@@ -197,6 +197,14 @@
+ #define MI_DISPLAY_FLIP MI_INSTR(0x14, 2)
+ #define MI_DISPLAY_FLIP_I915 MI_INSTR(0x14, 1)
+ #define MI_DISPLAY_FLIP_PLANE(n) ((n) << 20)
++/* IVB has funny definitions for which plane to flip. */
++#define MI_DISPLAY_FLIP_IVB_PLANE_A (0 << 19)
++#define MI_DISPLAY_FLIP_IVB_PLANE_B (1 << 19)
++#define MI_DISPLAY_FLIP_IVB_SPRITE_A (2 << 19)
++#define MI_DISPLAY_FLIP_IVB_SPRITE_B (3 << 19)
++#define MI_DISPLAY_FLIP_IVB_PLANE_C (4 << 19)
++#define MI_DISPLAY_FLIP_IVB_SPRITE_C (5 << 19)
++
+ #define MI_SET_CONTEXT MI_INSTR(0x18, 0)
+ #define MI_MM_SPACE_GTT (1<<8)
+ #define MI_MM_SPACE_PHYSICAL (0<<8)
+--- a/drivers/gpu/drm/i915/intel_display.c
++++ b/drivers/gpu/drm/i915/intel_display.c
+@@ -7486,17 +7486,34 @@ static int intel_gen7_queue_flip(struct
+ struct drm_i915_private *dev_priv = dev->dev_private;
+ struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
+ struct intel_ring_buffer *ring = &dev_priv->ring[BCS];
++ uint32_t plane_bit = 0;
+ int ret;
+
+ ret = intel_pin_and_fence_fb_obj(dev, obj, ring);
+ if (ret)
+ goto err;
+
++ switch(intel_crtc->plane) {
++ case PLANE_A:
++ plane_bit = MI_DISPLAY_FLIP_IVB_PLANE_A;
++ break;
++ case PLANE_B:
++ plane_bit = MI_DISPLAY_FLIP_IVB_PLANE_B;
++ break;
++ case PLANE_C:
++ plane_bit = MI_DISPLAY_FLIP_IVB_PLANE_C;
++ break;
++ default:
++ WARN_ONCE(1, "unknown plane in flip command\n");
++ ret = -ENODEV;
++ goto err;
++ }
++
+ ret = intel_ring_begin(ring, 4);
+ if (ret)
+ goto err_unpin;
+
+- intel_ring_emit(ring, MI_DISPLAY_FLIP_I915 | (intel_crtc->plane << 19));
++ intel_ring_emit(ring, MI_DISPLAY_FLIP_I915 | plane_bit);
+ intel_ring_emit(ring, (fb->pitches[0] | obj->tiling_mode));
+ intel_ring_emit(ring, (obj->gtt_offset));
+ intel_ring_emit(ring, (MI_NOOP));
--- /dev/null
+From 66063840d247bbcd838cca471594a5c1d1bab7c9 Mon Sep 17 00:00:00 2001
+From: Jesse Barnes <jbarnes@virtuousgeek.org>
+Date: Thu, 22 Mar 2012 14:38:43 -0700
+Subject: drm/i915: move NEEDS_FORCE_WAKE to i915_drv.c
+
+From: Jesse Barnes <jbarnes@virtuousgeek.org>
+
+commit b7d84096d3c45f4e397e913da4ce24ec9a32022e upstream.
+
+It's only used by the main read/write functions, so we can keep it with
+them.
+
+Signed-off-by: Jesse Barnes <jbarnes@virtuousgeek.org>
+Acked-by: Ben Widawsky <ben@bwidawsk.net>
+Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
+Signed-off-by: Julien Cristau <jcristau@debian.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/gpu/drm/i915/i915_drv.c | 6 ++++++
+ drivers/gpu/drm/i915/i915_drv.h | 6 ------
+ 2 files changed, 6 insertions(+), 6 deletions(-)
+
+--- a/drivers/gpu/drm/i915/i915_drv.c
++++ b/drivers/gpu/drm/i915/i915_drv.c
+@@ -993,6 +993,12 @@ MODULE_AUTHOR(DRIVER_AUTHOR);
+ MODULE_DESCRIPTION(DRIVER_DESC);
+ MODULE_LICENSE("GPL and additional rights");
+
++/* We give fast paths for the really cool registers */
++#define NEEDS_FORCE_WAKE(dev_priv, reg) \
++ (((dev_priv)->info->gen >= 6) && \
++ ((reg) < 0x40000) && \
++ ((reg) != FORCEWAKE))
++
+ #define __i915_read(x, y) \
+ u##x i915_read##x(struct drm_i915_private *dev_priv, u32 reg) { \
+ u##x val = 0; \
+--- a/drivers/gpu/drm/i915/i915_drv.h
++++ b/drivers/gpu/drm/i915/i915_drv.h
+@@ -1450,12 +1450,6 @@ void gen6_gt_force_wake_get(struct drm_i
+ void gen6_gt_force_wake_put(struct drm_i915_private *dev_priv);
+ int __gen6_gt_wait_for_fifo(struct drm_i915_private *dev_priv);
+
+-/* We give fast paths for the really cool registers */
+-#define NEEDS_FORCE_WAKE(dev_priv, reg) \
+- (((dev_priv)->info->gen >= 6) && \
+- ((reg) < 0x40000) && \
+- ((reg) != FORCEWAKE))
+-
+ #define __i915_read(x, y) \
+ u##x i915_read##x(struct drm_i915_private *dev_priv, u32 reg);
+
--- /dev/null
+From 65e197d81ee729a7c8f3536fb6a92797fdceb7d1 Mon Sep 17 00:00:00 2001
+From: Daniel Vetter <daniel.vetter@ffwll.ch>
+Date: Mon, 4 Jun 2012 11:18:15 +0200
+Subject: drm/i915: hold forcewake around ring hw init
+
+From: Daniel Vetter <daniel.vetter@ffwll.ch>
+
+commit b7884eb45ec98c0d34c7f49005ae9d4b4b4e38f6 upstream.
+
+Empirical evidence suggests that we need to: On at least one ivb
+machine when running the hangman i-g-t test, the rings don't properly
+initialize properly - the RING_START registers seems to be stuck at
+all zeros.
+
+Holding forcewake around this register init sequences makes chip reset
+reliable again. Note that this is not the first such issue:
+
+commit f01db988ef6f6c70a6cc36ee71e4a98a68901229
+Author: Sean Paul <seanpaul@chromium.org>
+Date: Fri Mar 16 12:43:22 2012 -0400
+
+ drm/i915: Add wait_for in init_ring_common
+
+added delay loops to make RING_START and RING_CTL initialization
+reliable on the blt ring at boot-up. So I guess it won't hurt if we do
+this unconditionally for all force_wake needing gpus.
+
+To avoid copy&pasting of the HAS_FORCE_WAKE check I've added a new
+intel_info bit for that.
+
+v2: Fixup missing commas in static struct and properly handling the
+error case in init_ring_common, both noticed by Jani Nikula.
+
+Reported-and-tested-by: Yang Guang <guang.a.yang@intel.com>
+Reviewed-by: Eugeni Dodonov <eugeni.dodonov@intel.com>
+Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=50522
+Signed-Off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
+[bwh: Backported to 3.2:
+ - drop changes to Haswell device information
+ - NEEDS_FORCE_WAKE didn't refer to Valley View anyway]
+Signed-off-by: Ben Hutchings <ben@decadent.org.uk>
+[jcristau: further context adjustments for 3.4]
+Signed-off-by: Julien Cristau <jcristau@debian.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/gpu/drm/i915/i915_drv.c | 6 +++++-
+ drivers/gpu/drm/i915/i915_drv.h | 3 +++
+ drivers/gpu/drm/i915/intel_ringbuffer.c | 16 +++++++++++++---
+ 3 files changed, 21 insertions(+), 4 deletions(-)
+
+--- a/drivers/gpu/drm/i915/i915_drv.c
++++ b/drivers/gpu/drm/i915/i915_drv.c
+@@ -224,6 +224,7 @@ static const struct intel_device_info in
+ .has_bsd_ring = 1,
+ .has_blt_ring = 1,
+ .has_llc = 1,
++ .has_force_wake = 1,
+ };
+
+ static const struct intel_device_info intel_sandybridge_m_info = {
+@@ -233,6 +234,7 @@ static const struct intel_device_info in
+ .has_bsd_ring = 1,
+ .has_blt_ring = 1,
+ .has_llc = 1,
++ .has_force_wake = 1,
+ };
+
+ static const struct intel_device_info intel_ivybridge_d_info = {
+@@ -241,6 +243,7 @@ static const struct intel_device_info in
+ .has_bsd_ring = 1,
+ .has_blt_ring = 1,
+ .has_llc = 1,
++ .has_force_wake = 1,
+ };
+
+ static const struct intel_device_info intel_ivybridge_m_info = {
+@@ -250,6 +253,7 @@ static const struct intel_device_info in
+ .has_bsd_ring = 1,
+ .has_blt_ring = 1,
+ .has_llc = 1,
++ .has_force_wake = 1,
+ };
+
+ static const struct pci_device_id pciidlist[] = { /* aka */
+@@ -995,7 +999,7 @@ MODULE_LICENSE("GPL and additional right
+
+ /* We give fast paths for the really cool registers */
+ #define NEEDS_FORCE_WAKE(dev_priv, reg) \
+- (((dev_priv)->info->gen >= 6) && \
++ ((HAS_FORCE_WAKE((dev_priv)->dev)) && \
+ ((reg) < 0x40000) && \
+ ((reg) != FORCEWAKE))
+
+--- a/drivers/gpu/drm/i915/i915_drv.h
++++ b/drivers/gpu/drm/i915/i915_drv.h
+@@ -255,6 +255,7 @@ struct intel_device_info {
+ u8 is_broadwater:1;
+ u8 is_crestline:1;
+ u8 is_ivybridge:1;
++ u8 has_force_wake:1;
+ u8 has_fbc:1;
+ u8 has_pipe_cxsr:1;
+ u8 has_hotplug:1;
+@@ -1051,6 +1052,8 @@ struct drm_i915_file_private {
+ #define HAS_PCH_CPT(dev) (INTEL_PCH_TYPE(dev) == PCH_CPT)
+ #define HAS_PCH_IBX(dev) (INTEL_PCH_TYPE(dev) == PCH_IBX)
+
++#define HAS_FORCE_WAKE(dev) (INTEL_INFO(dev)->has_force_wake)
++
+ #include "i915_trace.h"
+
+ /**
+--- a/drivers/gpu/drm/i915/intel_ringbuffer.c
++++ b/drivers/gpu/drm/i915/intel_ringbuffer.c
+@@ -249,10 +249,15 @@ u32 intel_ring_get_active_head(struct in
+
+ static int init_ring_common(struct intel_ring_buffer *ring)
+ {
+- drm_i915_private_t *dev_priv = ring->dev->dev_private;
++ struct drm_device *dev = ring->dev;
++ drm_i915_private_t *dev_priv = dev->dev_private;
+ struct drm_i915_gem_object *obj = ring->obj;
++ int ret = 0;
+ u32 head;
+
++ if (HAS_FORCE_WAKE(dev))
++ gen6_gt_force_wake_get(dev_priv);
++
+ /* Stop the ring if it's running. */
+ I915_WRITE_CTL(ring, 0);
+ I915_WRITE_HEAD(ring, 0);
+@@ -300,7 +305,8 @@ static int init_ring_common(struct intel
+ I915_READ_HEAD(ring),
+ I915_READ_TAIL(ring),
+ I915_READ_START(ring));
+- return -EIO;
++ ret = -EIO;
++ goto out;
+ }
+
+ if (!drm_core_check_feature(ring->dev, DRIVER_MODESET))
+@@ -312,7 +318,11 @@ static int init_ring_common(struct intel
+ ring->last_retired_head = -1;
+ }
+
+- return 0;
++out:
++ if (HAS_FORCE_WAKE(dev))
++ gen6_gt_force_wake_put(dev_priv);
++
++ return ret;
+ }
+
+ static int
--- /dev/null
+From 0fc6c852ea34ce5e5870c5c614d7fa2895073775 Mon Sep 17 00:00:00 2001
+From: Takashi Iwai <tiwai@suse.de>
+Date: Tue, 20 Mar 2012 13:07:05 +0100
+Subject: drm/i915: Check VBIOS value for determining LVDS dual channel mode, too
+
+From: Takashi Iwai <tiwai@suse.de>
+
+commit b03543857fd75876b96e10d4320b775e95041bb7 upstream.
+
+Currently i915 driver checks [PCH_]LVDS register bits to decide
+whether to set up the dual-link or the single-link mode. This relies
+implicitly on that BIOS initializes the register properly at boot.
+However, BIOS doesn't initialize it always. When the machine is
+booted with the closed lid, BIOS skips the LVDS reg initialization.
+This ends up in blank output on a machine with a dual-link LVDS when
+you open the lid after the boot.
+
+This patch adds a workaround for that problem by checking the initial
+LVDS register value in VBT.
+
+Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=37742
+Tested-By: Paulo Zanoni <paulo.r.zanoni@intel.com>
+Reviewed-by: Rodrigo Vivi <rodrigo.vivi@gmail.com>
+Reviewed-by: Adam Jackson <ajax@redhat.com>
+Signed-off-by: Takashi Iwai <tiwai@suse.de>
+Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
+Signed-off-by: Julien Cristau <jcristau@debian.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/gpu/drm/i915/i915_drv.h | 2 +
+ drivers/gpu/drm/i915/intel_bios.c | 36 +++++++++++++++++++++++++++++++++++
+ drivers/gpu/drm/i915/intel_display.c | 30 +++++++++++++++++++++++------
+ 3 files changed, 62 insertions(+), 6 deletions(-)
+
+--- a/drivers/gpu/drm/i915/i915_drv.h
++++ b/drivers/gpu/drm/i915/i915_drv.h
+@@ -406,6 +406,8 @@ typedef struct drm_i915_private {
+ unsigned int lvds_use_ssc:1;
+ unsigned int display_clock_mode:1;
+ int lvds_ssc_freq;
++ unsigned int bios_lvds_val; /* initial [PCH_]LVDS reg val in VBIOS */
++ unsigned int lvds_val; /* used for checking LVDS channel mode */
+ struct {
+ int rate;
+ int lanes;
+--- a/drivers/gpu/drm/i915/intel_bios.c
++++ b/drivers/gpu/drm/i915/intel_bios.c
+@@ -174,6 +174,28 @@ get_lvds_dvo_timing(const struct bdb_lvd
+ return (struct lvds_dvo_timing *)(entry + dvo_timing_offset);
+ }
+
++/* get lvds_fp_timing entry
++ * this function may return NULL if the corresponding entry is invalid
++ */
++static const struct lvds_fp_timing *
++get_lvds_fp_timing(const struct bdb_header *bdb,
++ const struct bdb_lvds_lfp_data *data,
++ const struct bdb_lvds_lfp_data_ptrs *ptrs,
++ int index)
++{
++ size_t data_ofs = (const u8 *)data - (const u8 *)bdb;
++ u16 data_size = ((const u16 *)data)[-1]; /* stored in header */
++ size_t ofs;
++
++ if (index >= ARRAY_SIZE(ptrs->ptr))
++ return NULL;
++ ofs = ptrs->ptr[index].fp_timing_offset;
++ if (ofs < data_ofs ||
++ ofs + sizeof(struct lvds_fp_timing) > data_ofs + data_size)
++ return NULL;
++ return (const struct lvds_fp_timing *)((const u8 *)bdb + ofs);
++}
++
+ /* Try to find integrated panel data */
+ static void
+ parse_lfp_panel_data(struct drm_i915_private *dev_priv,
+@@ -183,6 +205,7 @@ parse_lfp_panel_data(struct drm_i915_pri
+ const struct bdb_lvds_lfp_data *lvds_lfp_data;
+ const struct bdb_lvds_lfp_data_ptrs *lvds_lfp_data_ptrs;
+ const struct lvds_dvo_timing *panel_dvo_timing;
++ const struct lvds_fp_timing *fp_timing;
+ struct drm_display_mode *panel_fixed_mode;
+ int i, downclock;
+
+@@ -244,6 +267,19 @@ parse_lfp_panel_data(struct drm_i915_pri
+ "Normal Clock %dKHz, downclock %dKHz\n",
+ panel_fixed_mode->clock, 10*downclock);
+ }
++
++ fp_timing = get_lvds_fp_timing(bdb, lvds_lfp_data,
++ lvds_lfp_data_ptrs,
++ lvds_options->panel_type);
++ if (fp_timing) {
++ /* check the resolution, just to be sure */
++ if (fp_timing->x_res == panel_fixed_mode->hdisplay &&
++ fp_timing->y_res == panel_fixed_mode->vdisplay) {
++ dev_priv->bios_lvds_val = fp_timing->lvds_reg_val;
++ DRM_DEBUG_KMS("VBT initial LVDS value %x\n",
++ dev_priv->bios_lvds_val);
++ }
++ }
+ }
+
+ /* Try to find sdvo panel data */
+--- a/drivers/gpu/drm/i915/intel_display.c
++++ b/drivers/gpu/drm/i915/intel_display.c
+@@ -360,6 +360,27 @@ static const intel_limit_t intel_limits_
+ .find_pll = intel_find_pll_ironlake_dp,
+ };
+
++static bool is_dual_link_lvds(struct drm_i915_private *dev_priv,
++ unsigned int reg)
++{
++ unsigned int val;
++
++ if (dev_priv->lvds_val)
++ val = dev_priv->lvds_val;
++ else {
++ /* BIOS should set the proper LVDS register value at boot, but
++ * in reality, it doesn't set the value when the lid is closed;
++ * we need to check "the value to be set" in VBT when LVDS
++ * register is uninitialized.
++ */
++ val = I915_READ(reg);
++ if (!(val & ~LVDS_DETECTED))
++ val = dev_priv->bios_lvds_val;
++ dev_priv->lvds_val = val;
++ }
++ return (val & LVDS_CLKB_POWER_MASK) == LVDS_CLKB_POWER_UP;
++}
++
+ static const intel_limit_t *intel_ironlake_limit(struct drm_crtc *crtc,
+ int refclk)
+ {
+@@ -368,8 +389,7 @@ static const intel_limit_t *intel_ironla
+ const intel_limit_t *limit;
+
+ if (intel_pipe_has_type(crtc, INTEL_OUTPUT_LVDS)) {
+- if ((I915_READ(PCH_LVDS) & LVDS_CLKB_POWER_MASK) ==
+- LVDS_CLKB_POWER_UP) {
++ if (is_dual_link_lvds(dev_priv, PCH_LVDS)) {
+ /* LVDS dual channel */
+ if (refclk == 100000)
+ limit = &intel_limits_ironlake_dual_lvds_100m;
+@@ -397,8 +417,7 @@ static const intel_limit_t *intel_g4x_li
+ const intel_limit_t *limit;
+
+ if (intel_pipe_has_type(crtc, INTEL_OUTPUT_LVDS)) {
+- if ((I915_READ(LVDS) & LVDS_CLKB_POWER_MASK) ==
+- LVDS_CLKB_POWER_UP)
++ if (is_dual_link_lvds(dev_priv, LVDS))
+ /* LVDS with dual channel */
+ limit = &intel_limits_g4x_dual_channel_lvds;
+ else
+@@ -536,8 +555,7 @@ intel_find_best_PLL(const intel_limit_t
+ * reliably set up different single/dual channel state, if we
+ * even can.
+ */
+- if ((I915_READ(LVDS) & LVDS_CLKB_POWER_MASK) ==
+- LVDS_CLKB_POWER_UP)
++ if (is_dual_link_lvds(dev_priv, LVDS))
+ clock.p2 = limit->p2.p2_fast;
+ else
+ clock.p2 = limit->p2.p2_slow;
--- /dev/null
+From 9d4d3e3a82cceb7a2fadac9ca284b9fa6bee086d Mon Sep 17 00:00:00 2001
+From: Sean Paul <seanpaul@chromium.org>
+Date: Fri, 16 Mar 2012 12:43:22 -0400
+Subject: drm/i915: Add wait_for in init_ring_common
+
+From: Sean Paul <seanpaul@chromium.org>
+
+commit f01db988ef6f6c70a6cc36ee71e4a98a68901229 upstream.
+
+I have seen a number of "blt ring initialization failed" messages
+where the ctl or start registers are not the correct value. Upon further
+inspection, if the code just waited a little bit, it would read the
+correct value. Adding the wait_for to these reads should eliminate the
+issue.
+
+Signed-off-by: Sean Paul <seanpaul@chromium.org>
+Reviewed-by: Ben Widawsky <ben@bwidawsk.net>
+Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
+Signed-off-by: Julien Cristau <jcristau@debian.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/gpu/drm/i915/intel_ringbuffer.c | 6 +++---
+ 1 file changed, 3 insertions(+), 3 deletions(-)
+
+--- a/drivers/gpu/drm/i915/intel_ringbuffer.c
++++ b/drivers/gpu/drm/i915/intel_ringbuffer.c
+@@ -295,9 +295,9 @@ static int init_ring_common(struct intel
+ | RING_VALID);
+
+ /* If the head is still not zero, the ring is dead */
+- if ((I915_READ_CTL(ring) & RING_VALID) == 0 ||
+- I915_READ_START(ring) != obj->gtt_offset ||
+- (I915_READ_HEAD(ring) & HEAD_ADDR) != 0) {
++ if (wait_for((I915_READ_CTL(ring) & RING_VALID) != 0 &&
++ I915_READ_START(ring) == obj->gtt_offset &&
++ (I915_READ_HEAD(ring) & HEAD_ADDR) == 0, 50)) {
+ DRM_ERROR("%s initialization failed "
+ "ctl %08x head %08x tail %08x start %08x\n",
+ ring->name,
--- /dev/null
+From 6f04ea0e7402a7148f641d27a5d0702f2c475ec8 Mon Sep 17 00:00:00 2001
+From: Chris Wilson <chris@chris-wilson.co.uk>
+Date: Tue, 17 Apr 2012 10:05:38 +0100
+Subject: drm/i915: Wait for all pending operations to the fb before disabling the pipe
+
+From: Chris Wilson <chris@chris-wilson.co.uk>
+
+commit 0f91128d88bbb8b0a8e7bb93df2c40680871d45a upstream.
+
+During modeset we have to disable the pipe to reconfigure its timings
+and maybe its size. Userspace may have queued up command buffers that
+depend upon the pipe running in a certain configuration and so the
+commands may become confused across the modeset. At the moment, we use a
+less than satisfactory kick-scanline-waits should the GPU hang during
+the modeset. It should be more reliable to wait for the pending
+operations to complete first, even though we still have a window for
+userspace to submit a broken command buffer during the modeset.
+
+Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
+Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
+Signed-off-by: Julien Cristau <jcristau@debian.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/gpu/drm/i915/intel_display.c | 27 ++++-----------------------
+ 1 file changed, 4 insertions(+), 23 deletions(-)
+
+--- a/drivers/gpu/drm/i915/intel_display.c
++++ b/drivers/gpu/drm/i915/intel_display.c
+@@ -2897,16 +2897,14 @@ static void intel_clear_scanline_wait(st
+
+ static void intel_crtc_wait_for_pending_flips(struct drm_crtc *crtc)
+ {
+- struct drm_i915_gem_object *obj;
+- struct drm_i915_private *dev_priv;
++ struct drm_device *dev = crtc->dev;
+
+ if (crtc->fb == NULL)
+ return;
+
+- obj = to_intel_framebuffer(crtc->fb)->obj;
+- dev_priv = crtc->dev->dev_private;
+- wait_event(dev_priv->pending_flip_queue,
+- atomic_read(&obj->pending_flip) == 0);
++ mutex_lock(&dev->struct_mutex);
++ intel_finish_fb(crtc->fb);
++ mutex_unlock(&dev->struct_mutex);
+ }
+
+ static bool intel_crtc_driving_pch(struct drm_crtc *crtc)
+@@ -3372,23 +3370,6 @@ static void intel_crtc_disable(struct dr
+ struct drm_crtc_helper_funcs *crtc_funcs = crtc->helper_private;
+ struct drm_device *dev = crtc->dev;
+
+- /* Flush any pending WAITs before we disable the pipe. Note that
+- * we need to drop the struct_mutex in order to acquire it again
+- * during the lowlevel dpms routines around a couple of the
+- * operations. It does not look trivial nor desirable to move
+- * that locking higher. So instead we leave a window for the
+- * submission of further commands on the fb before we can actually
+- * disable it. This race with userspace exists anyway, and we can
+- * only rely on the pipe being disabled by userspace after it
+- * receives the hotplug notification and has flushed any pending
+- * batches.
+- */
+- if (crtc->fb) {
+- mutex_lock(&dev->struct_mutex);
+- intel_finish_fb(crtc->fb);
+- mutex_unlock(&dev->struct_mutex);
+- }
+-
+ crtc_funcs->dpms(crtc, DRM_MODE_DPMS_OFF);
+ assert_plane_disabled(dev->dev_private, to_intel_crtc(crtc)->plane);
+ assert_pipe_disabled(dev->dev_private, to_intel_crtc(crtc)->pipe);
--- /dev/null
+From 73885de682d7277f1ee16c22450b60a399b66361 Mon Sep 17 00:00:00 2001
+From: Daniel Vetter <daniel.vetter@ffwll.ch>
+Date: Fri, 13 Apr 2012 15:51:51 +0200
+Subject: drm/i915: don't pwrite tiled objects through the gtt
+
+From: Daniel Vetter <daniel.vetter@ffwll.ch>
+
+commit c07496fa61f4c5cb2addd1c57f6b22fcaeea2eeb upstream.
+
+... we will botch up the bit17 swizzling. Furthermore tiled pwrite is
+a (now) unused slowpath, so no one really cares.
+
+This fixes the last swizzling issues I have with i-g-t on my bit17
+swizzling i915G. No regression, it's been broken since the dawn of
+gem, but it's nice for regression tracking when really _all_ i-g-t
+tests work.
+
+Actually this is not true, Chris Wilson noticed while reviewing this
+patch that the commit
+
+commit d9e86c0ee60f323e890484628f351bf50fa9a15d
+Author: Chris Wilson <chris@chris-wilson.co.uk>
+Date: Wed Nov 10 16:40:20 2010 +0000
+
+ drm/i915: Pipelined fencing [infrastructure]
+
+contained a functional change that broke things.
+
+Reviewed-by: Chris Wilson <chris@chris-wilson.co.uk>
+Signed-Off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
+[jcristau: adjust context for 3.4]
+Signed-off-by: Julien Cristau <jcristau@debian.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/gpu/drm/i915/i915_gem.c | 1 +
+ 1 file changed, 1 insertion(+)
+
+--- a/drivers/gpu/drm/i915/i915_gem.c
++++ b/drivers/gpu/drm/i915/i915_gem.c
+@@ -928,6 +928,7 @@ i915_gem_pwrite_ioctl(struct drm_device
+ }
+
+ if (obj->gtt_space &&
++ obj->tiling_mode == I915_TILING_NONE &&
+ obj->base.write_domain != I915_GEM_DOMAIN_CPU) {
+ ret = i915_gem_object_pin(obj, 0, true);
+ if (ret)
--- /dev/null
+From c06328694bb2599a382531b18bb1c3931944a136 Mon Sep 17 00:00:00 2001
+From: Alex Deucher <alexander.deucher@amd.com>
+Date: Tue, 17 Jul 2012 14:02:43 -0400
+Subject: drm/radeon: fix up pll selection on DCE5/6
+
+From: Alex Deucher <alexander.deucher@amd.com>
+
+commit 26fe45a0a76f165425f332a5aaa298f149f9db22 upstream.
+
+Selecting ATOM_PPLL_INVALID should be equivalent as the
+DCPLL or PPLL0 are already programmed for the DISPCLK, but
+the preferred method is to always specify the PLL selected.
+SetPixelClock will check the parameters and skip the
+programming if the PLL is already set up.
+
+Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
+Reviewed-by: Christian König <christian.koenig@amd.com>
+Signed-off-by: Julien Cristau <jcristau@debian.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/gpu/drm/radeon/atombios_crtc.c | 6 +++++-
+ 1 file changed, 5 insertions(+), 1 deletion(-)
+
+--- a/drivers/gpu/drm/radeon/atombios_crtc.c
++++ b/drivers/gpu/drm/radeon/atombios_crtc.c
+@@ -1533,7 +1533,11 @@ static int radeon_atom_pick_pll(struct d
+ * crtc virtual pixel clock.
+ */
+ if (ENCODER_MODE_IS_DP(atombios_get_encoder_mode(test_encoder))) {
+- if (ASIC_IS_DCE5(rdev) || rdev->clock.dp_extclk)
++ if (ASIC_IS_DCE5(rdev))
++ return ATOM_DCPLL;
++ else if (ASIC_IS_DCE6(rdev))
++ return ATOM_PPLL0;
++ else if (rdev->clock.dp_extclk)
+ return ATOM_PPLL_INVALID;
+ }
+ }
--- /dev/null
+From 0e47f8bac057b1e74e87133858e1ce8343739cb1 Mon Sep 17 00:00:00 2001
+From: Paulo Zanoni <paulo.r.zanoni@intel.com>
+Date: Mon, 28 May 2012 16:43:00 -0300
+Subject: drm/i915: add some barriers when changing DIPs
+
+From: Paulo Zanoni <paulo.r.zanoni@intel.com>
+
+commit 9d9740f099f2eaf309c4c9cbc0d732507140db28 upstream.
+
+On IVB and older, we basically have two registers: the control and the
+data register. We write a few consecutitve times to the control
+register, and we need these writes to arrive exactly in the specified
+order.
+
+Also, when we're changing the data register, we need to guarantee that
+anything written to the control register already arrived (since
+changing the control register can change where the data register
+points to). Also, we need to make sure all the writes to the data
+register happen exactly in the specified order, and we also *can't*
+read the data register during this process, since reading and/or
+writing it will change the place it points to.
+
+So invoke the "better safe than sorry" rule and just be careful and
+put barriers everywhere :)
+
+On HSW we still have a control register that we write many times, but
+we have many data registers.
+
+Demanded-by: Chris Wilson <chris@chris-wilson.co.uk>
+Signed-off-by: Paulo Zanoni <paulo.r.zanoni@intel.com>
+Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
+[bwh: Backported to 3.2:
+ - There are only two write_infoframe functions to be modified
+ - The other VIDEO_DIP_CTL writes are in entirely different functions]
+Signed-off-by: Ben Hutchings <ben@decadent.org.uk>
+Signed-off-by: Julien Cristau <jcristau@debian.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/gpu/drm/i915/intel_hdmi.c | 11 ++++++++++-
+ 1 file changed, 10 insertions(+), 1 deletion(-)
+
+--- a/drivers/gpu/drm/i915/intel_hdmi.c
++++ b/drivers/gpu/drm/i915/intel_hdmi.c
+@@ -138,14 +138,17 @@ static void i9xx_write_infoframe(struct
+
+ I915_WRITE(VIDEO_DIP_CTL, VIDEO_DIP_ENABLE | val | port | flags);
+
++ mmiowb();
+ for (i = 0; i < len; i += 4) {
+ I915_WRITE(VIDEO_DIP_DATA, *data);
+ data++;
+ }
++ mmiowb();
+
+ flags |= intel_infoframe_flags(frame);
+
+ I915_WRITE(VIDEO_DIP_CTL, VIDEO_DIP_ENABLE | val | port | flags);
++ POSTING_READ(VIDEO_DIP_CTL);
+ }
+
+ static void ironlake_write_infoframe(struct drm_encoder *encoder,
+@@ -168,14 +171,17 @@ static void ironlake_write_infoframe(str
+
+ I915_WRITE(reg, VIDEO_DIP_ENABLE | val | flags);
+
++ mmiowb();
+ for (i = 0; i < len; i += 4) {
+ I915_WRITE(TVIDEO_DIP_DATA(intel_crtc->pipe), *data);
+ data++;
+ }
++ mmiowb();
+
+ flags |= intel_infoframe_flags(frame);
+
+ I915_WRITE(reg, VIDEO_DIP_ENABLE | val | flags);
++ POSTING_READ(reg);
+ }
+ static void intel_set_infoframe(struct drm_encoder *encoder,
+ struct dip_infoframe *frame)
+@@ -549,10 +555,13 @@ void intel_hdmi_init(struct drm_device *
+ if (!HAS_PCH_SPLIT(dev)) {
+ intel_hdmi->write_infoframe = i9xx_write_infoframe;
+ I915_WRITE(VIDEO_DIP_CTL, 0);
++ POSTING_READ(VIDEO_DIP_CTL);
+ } else {
+ intel_hdmi->write_infoframe = ironlake_write_infoframe;
+- for_each_pipe(i)
++ for_each_pipe(i) {
+ I915_WRITE(TVIDEO_DIP_CTL(i), 0);
++ POSTING_READ(TVIDEO_DIP_CTL(i));
++ }
+ }
+
+ drm_encoder_helper_add(&intel_encoder->base, &intel_hdmi_helper_funcs);
--- /dev/null
+From 6168bbff4b22341a1ca4a5bbd7a1bf22834ce741 Mon Sep 17 00:00:00 2001
+From: Chris Wilson <chris@chris-wilson.co.uk>
+Date: Fri, 11 May 2012 18:01:33 +0100
+Subject: drm/i915: SDVO hotplug have different interrupt status bits for i915/i965/g4x
+
+From: Chris Wilson <chris@chris-wilson.co.uk>
+
+commit 084b612ecf8e59973576b2f644e6949609c79375 upstream.
+
+Note that gen3 is the only platform where we've got the bit
+definitions right, hence the workaround of disabling sdvo hotplug
+support on i945g/gm is not due to misdiagnosis of broken hotplug irq
+handling ...
+
+Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
+[danvet: add some blurb about sdvo hotplug fail on i945g/gm I've
+wondered about while reviewing.]
+Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
+[bwh: Backported to 3.2:
+ - Adjust context
+ - Handle all three cases in i915_driver_irq_postinstall() as there
+ are not separate functions for gen3 and gen4+
+ - Carry on using IS_SDVOB() in intel_sdvo_init()]
+Signed-off-by: Ben Hutchings <ben@decadent.org.uk>
+Signed-off-by: Julien Cristau <jcristau@debian.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/gpu/drm/i915/i915_irq.c | 20 ++++++++++++++++----
+ drivers/gpu/drm/i915/i915_reg.h | 10 ++++++++--
+ drivers/gpu/drm/i915/intel_sdvo.c | 17 +++++++++++++----
+ 3 files changed, 37 insertions(+), 10 deletions(-)
+
+--- a/drivers/gpu/drm/i915/i915_irq.c
++++ b/drivers/gpu/drm/i915/i915_irq.c
+@@ -2051,10 +2051,22 @@ static int i915_driver_irq_postinstall(s
+ hotplug_en |= HDMIC_HOTPLUG_INT_EN;
+ if (dev_priv->hotplug_supported_mask & HDMID_HOTPLUG_INT_STATUS)
+ hotplug_en |= HDMID_HOTPLUG_INT_EN;
+- if (dev_priv->hotplug_supported_mask & SDVOC_HOTPLUG_INT_STATUS)
+- hotplug_en |= SDVOC_HOTPLUG_INT_EN;
+- if (dev_priv->hotplug_supported_mask & SDVOB_HOTPLUG_INT_STATUS)
+- hotplug_en |= SDVOB_HOTPLUG_INT_EN;
++ if (IS_G4X(dev)) {
++ if (dev_priv->hotplug_supported_mask & SDVOC_HOTPLUG_INT_STATUS_G4X)
++ hotplug_en |= SDVOC_HOTPLUG_INT_EN;
++ if (dev_priv->hotplug_supported_mask & SDVOB_HOTPLUG_INT_STATUS_G4X)
++ hotplug_en |= SDVOB_HOTPLUG_INT_EN;
++ } else if (IS_GEN4(dev)) {
++ if (dev_priv->hotplug_supported_mask & SDVOC_HOTPLUG_INT_STATUS_I965)
++ hotplug_en |= SDVOC_HOTPLUG_INT_EN;
++ if (dev_priv->hotplug_supported_mask & SDVOB_HOTPLUG_INT_STATUS_I965)
++ hotplug_en |= SDVOB_HOTPLUG_INT_EN;
++ } else {
++ if (dev_priv->hotplug_supported_mask & SDVOC_HOTPLUG_INT_STATUS_I915)
++ hotplug_en |= SDVOC_HOTPLUG_INT_EN;
++ if (dev_priv->hotplug_supported_mask & SDVOB_HOTPLUG_INT_STATUS_I915)
++ hotplug_en |= SDVOB_HOTPLUG_INT_EN;
++ }
+ if (dev_priv->hotplug_supported_mask & CRT_HOTPLUG_INT_STATUS) {
+ hotplug_en |= CRT_HOTPLUG_INT_EN;
+
+--- a/drivers/gpu/drm/i915/i915_reg.h
++++ b/drivers/gpu/drm/i915/i915_reg.h
+@@ -1491,14 +1491,20 @@
+ #define DPC_HOTPLUG_INT_STATUS (1 << 28)
+ #define HDMID_HOTPLUG_INT_STATUS (1 << 27)
+ #define DPD_HOTPLUG_INT_STATUS (1 << 27)
++/* CRT/TV common between gen3+ */
+ #define CRT_HOTPLUG_INT_STATUS (1 << 11)
+ #define TV_HOTPLUG_INT_STATUS (1 << 10)
+ #define CRT_HOTPLUG_MONITOR_MASK (3 << 8)
+ #define CRT_HOTPLUG_MONITOR_COLOR (3 << 8)
+ #define CRT_HOTPLUG_MONITOR_MONO (2 << 8)
+ #define CRT_HOTPLUG_MONITOR_NONE (0 << 8)
+-#define SDVOC_HOTPLUG_INT_STATUS (1 << 7)
+-#define SDVOB_HOTPLUG_INT_STATUS (1 << 6)
++/* SDVO is different across gen3/4 */
++#define SDVOC_HOTPLUG_INT_STATUS_G4X (1 << 3)
++#define SDVOB_HOTPLUG_INT_STATUS_G4X (1 << 2)
++#define SDVOC_HOTPLUG_INT_STATUS_I965 (3 << 4)
++#define SDVOB_HOTPLUG_INT_STATUS_I965 (3 << 2)
++#define SDVOC_HOTPLUG_INT_STATUS_I915 (1 << 7)
++#define SDVOB_HOTPLUG_INT_STATUS_I915 (1 << 6)
+
+ /* SDVO port control */
+ #define SDVOB 0x61140
+--- a/drivers/gpu/drm/i915/intel_sdvo.c
++++ b/drivers/gpu/drm/i915/intel_sdvo.c
+@@ -2528,6 +2528,7 @@ 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);
+@@ -2558,10 +2559,18 @@ bool intel_sdvo_init(struct drm_device *
+ }
+ }
+
+- if (IS_SDVOB(sdvo_reg))
+- dev_priv->hotplug_supported_mask |= SDVOB_HOTPLUG_INT_STATUS;
+- else
+- dev_priv->hotplug_supported_mask |= SDVOC_HOTPLUG_INT_STATUS;
++ hotplug_mask = 0;
++ if (IS_G4X(dev)) {
++ hotplug_mask = IS_SDVOB(sdvo_reg) ?
++ SDVOB_HOTPLUG_INT_STATUS_G4X : SDVOC_HOTPLUG_INT_STATUS_G4X;
++ } else if (IS_GEN4(dev)) {
++ hotplug_mask = IS_SDVOB(sdvo_reg) ?
++ SDVOB_HOTPLUG_INT_STATUS_I965 : SDVOC_HOTPLUG_INT_STATUS_I965;
++ } else {
++ hotplug_mask = IS_SDVOB(sdvo_reg) ?
++ SDVOB_HOTPLUG_INT_STATUS_I915 : SDVOC_HOTPLUG_INT_STATUS_I915;
++ }
++ dev_priv->hotplug_supported_mask |= hotplug_mask;
+
+ drm_encoder_helper_add(&intel_encoder->base, &intel_sdvo_helper_funcs);
+
--- /dev/null
+From ad0ab3ebac01cab8e92d26ba1e3867d193dacad8 Mon Sep 17 00:00:00 2001
+From: Alex Deucher <alexander.deucher@amd.com>
+Date: Mon, 6 Aug 2012 17:06:03 -0400
+Subject: drm/radeon: fix ordering in pll picking on dce4+
+
+From: Alex Deucher <alexander.deucher@amd.com>
+
+commit ecd67955fd4c8e66e4df312098989d5fa7da624c upstream.
+
+No functional change, but re-order the cases so they
+evaluate properly due to the way the DCE macros work.
+
+Noticed by kallisti5 on IRC.
+
+Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
+Signed-off-by: Julien Cristau <jcristau@debian.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/gpu/drm/radeon/atombios_crtc.c | 8 ++++----
+ 1 file changed, 4 insertions(+), 4 deletions(-)
+
+--- a/drivers/gpu/drm/radeon/atombios_crtc.c
++++ b/drivers/gpu/drm/radeon/atombios_crtc.c
+@@ -1533,12 +1533,12 @@ static int radeon_atom_pick_pll(struct d
+ * crtc virtual pixel clock.
+ */
+ if (ENCODER_MODE_IS_DP(atombios_get_encoder_mode(test_encoder))) {
+- if (ASIC_IS_DCE5(rdev))
+- return ATOM_DCPLL;
++ if (rdev->clock.dp_extclk)
++ return ATOM_PPLL_INVALID;
+ else if (ASIC_IS_DCE6(rdev))
+ return ATOM_PPLL0;
+- else if (rdev->clock.dp_extclk)
+- return ATOM_PPLL_INVALID;
++ else if (ASIC_IS_DCE5(rdev))
++ return ATOM_DCPLL;
+ }
+ }
+ }
--- /dev/null
+From 31d04b5fa45264da10750fc7f526d0e65f894a29 Mon Sep 17 00:00:00 2001
+From: Paul Menzel <paulepanter@users.sourceforge.net>
+Date: Wed, 8 Aug 2012 23:12:19 +0200
+Subject: drm: Add EDID_QUIRK_FORCE_REDUCED_BLANKING for ASUS VW222S
+
+From: Paul Menzel <paulepanter@users.sourceforge.net>
+
+commit 6f33814bd4d9cfe76033a31b1c0c76c960cd8e4b upstream.
+
+Connecting an ASUS VW222S [1] over VGA a garbled screen is shown with
+vertical stripes in the top half.
+
+In commit bc42aabc [2]
+
+ commit bc42aabc6a01b92b0f961d65671564e0e1cd7592
+ Author: Adam Jackson <ajax@redhat.com>
+ Date: Wed May 23 16:26:54 2012 -0400
+
+ drm/edid/quirks: ViewSonic VA2026w
+
+Adam Jackson added the quirk `EDID_QUIRK_FORCE_REDUCED_BLANKING` which
+is also needed for this ASUS monitor.
+
+All log files and output from `xrandr` is included in the referenced
+Bugzilla report #17629.
+
+Please note that this monitor only has a VGA (D-Sub) connector [1].
+
+[1] http://www.asus.com/Display/LCD_Monitors/VW222S/
+[2] http://git.kernel.org/?p=linux/kernel/git/torvalds/linux.git;a=commit;h=bc42aabc6a01b92b0f961d65671564e0e1cd7592
+
+Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=17629
+Signed-off-by: Paul Menzel <paulepanter@users.sourceforge.net>
+Cc: <dri-devel@lists.freedesktop.org>
+Cc: Adam Jackson <ajax@redhat.com>
+Cc: Ian Pilcher <arequipeno@gmail.com>
+Signed-off-by: Dave Airlie <airlied@redhat.com>
+Signed-off-by: Julien Cristau <jcristau@debian.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/gpu/drm/drm_edid.c | 3 +++
+ 1 file changed, 3 insertions(+)
+
+--- a/drivers/gpu/drm/drm_edid.c
++++ b/drivers/gpu/drm/drm_edid.c
+@@ -87,6 +87,9 @@ static struct edid_quirk {
+ int product_id;
+ u32 quirks;
+ } edid_quirk_list[] = {
++ /* ASUS VW222S */
++ { "ACI", 0x22a2, EDID_QUIRK_FORCE_REDUCED_BLANKING },
++
+ /* Acer AL1706 */
+ { "ACR", 44358, EDID_QUIRK_PREFER_LARGE_60 },
+ /* Acer F51 */
--- /dev/null
+From 134ca686c1803f09cf091c57edf1b3e5a2b1b0d6 Mon Sep 17 00:00:00 2001
+From: Jani Nikula <jani.nikula@intel.com>
+Date: Wed, 29 Aug 2012 14:08:42 +0300
+Subject: drm/i915: only enable sdvo hotplug irq if needed
+
+From: Jani Nikula <jani.nikula@intel.com>
+
+commit fcbc50da7753b210b4442ca9abc4efbd4e481f6e upstream.
+
+Avoid constant wakeups caused by noisy irq lines when we don't even care
+about the irq. This should be particularly useful for i945g/gm where the
+hotplug has been disabled:
+
+commit 768b107e4b3be0acf6f58e914afe4f337c00932b
+Author: Daniel Vetter <daniel.vetter@ffwll.ch>
+Date: Fri May 4 11:29:56 2012 +0200
+
+ drm/i915: disable sdvo hotplug on i945g/gm
+
+v2: While at it, remove the bogus hotplug_active read, and do not mask
+hotplug_active[0] before checking whether the irq is needed, per discussion
+with Daniel on IRC.
+
+Bugzilla: https://bugzilla.kernel.org/show_bug.cgi?id=38442
+Tested-by: Dominik Köppl <dominik@devwork.org>
+Signed-off-by: Jani Nikula <jani.nikula@intel.com>
+Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
+Signed-off-by: Julien Cristau <jcristau@debian.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/gpu/drm/i915/intel_sdvo.c | 15 ++++++---------
+ 1 file changed, 6 insertions(+), 9 deletions(-)
+
+--- a/drivers/gpu/drm/i915/intel_sdvo.c
++++ b/drivers/gpu/drm/i915/intel_sdvo.c
+@@ -2570,7 +2570,6 @@ bool intel_sdvo_init(struct drm_device *
+ hotplug_mask = IS_SDVOB(sdvo_reg) ?
+ SDVOB_HOTPLUG_INT_STATUS_I915 : SDVOC_HOTPLUG_INT_STATUS_I915;
+ }
+- dev_priv->hotplug_supported_mask |= hotplug_mask;
+
+ drm_encoder_helper_add(&intel_encoder->base, &intel_sdvo_helper_funcs);
+
+@@ -2578,14 +2577,6 @@ bool intel_sdvo_init(struct drm_device *
+ if (!intel_sdvo_get_capabilities(intel_sdvo, &intel_sdvo->caps))
+ goto err;
+
+- /* Set up hotplug command - note paranoia about contents of reply.
+- * We assume that the hardware is in a sane state, and only touch
+- * the bits we think we understand.
+- */
+- intel_sdvo_get_value(intel_sdvo, SDVO_CMD_GET_ACTIVE_HOT_PLUG,
+- &intel_sdvo->hotplug_active, 2);
+- intel_sdvo->hotplug_active[0] &= ~0x3;
+-
+ if (intel_sdvo_output_setup(intel_sdvo,
+ intel_sdvo->caps.output_flags) != true) {
+ DRM_DEBUG_KMS("SDVO output failed to setup on SDVO%c\n",
+@@ -2593,6 +2584,12 @@ bool intel_sdvo_init(struct drm_device *
+ goto err;
+ }
+
++ /* Only enable the hotplug irq if we need it, to work around noisy
++ * hotplug lines.
++ */
++ if (intel_sdvo->hotplug_active[0])
++ dev_priv->hotplug_supported_mask |= hotplug_mask;
++
+ intel_sdvo_select_ddc_bus(dev_priv, intel_sdvo, sdvo_reg);
+
+ /* Set the input timing to the screen. Assume always input 0. */
--- /dev/null
+From 72485a6009099d724f60ec39aee16befee977629 Mon Sep 17 00:00:00 2001
+From: Chris Wilson <chris@chris-wilson.co.uk>
+Date: Sat, 15 Sep 2012 09:41:57 +0100
+Subject: drm/i915: Reduce a pin-leak BUG into a WARN
+
+From: Chris Wilson <chris@chris-wilson.co.uk>
+
+commit 7e81a42e341a4f15d76624b7c02ffb21b085b56f upstream.
+
+Pin-leaks persist and we get the perennial bug reports of machine
+lockups to the BUG_ON(pin_count==MAX). If we instead loudly report that
+the object cannot be pinned at that time it should prevent the driver from
+locking up, and hopefully restore a semblance of working whilst still
+leaving us a OOPS to debug.
+
+Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
+Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
+[bwh: Backported to 3.2: adjust context]
+Signed-off-by: Ben Hutchings <ben@decadent.org.uk>
+Signed-off-by: Julien Cristau <jcristau@debian.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/gpu/drm/i915/i915_gem.c | 3 ++-
+ 1 file changed, 2 insertions(+), 1 deletion(-)
+
+--- a/drivers/gpu/drm/i915/i915_gem.c
++++ b/drivers/gpu/drm/i915/i915_gem.c
+@@ -3318,7 +3318,8 @@ i915_gem_object_pin(struct drm_i915_gem_
+ struct drm_i915_private *dev_priv = dev->dev_private;
+ int ret;
+
+- BUG_ON(obj->pin_count == DRM_I915_GEM_OBJECT_MAX_PIN_COUNT);
++ if (WARN_ON(obj->pin_count == DRM_I915_GEM_OBJECT_MAX_PIN_COUNT))
++ return -EBUSY;
+ WARN_ON(i915_verify_lists(dev));
+
+ if (obj->gtt_space != NULL) {
--- /dev/null
+From d316825ff7dd1720cb8617433c1a0eff18907f09 Mon Sep 17 00:00:00 2001
+From: Eugeni Dodonov <eugeni.dodonov@intel.com>
+Date: Mon, 18 Jun 2012 19:03:38 -0300
+Subject: drm/i915: prevent possible pin leak on error path
+
+From: Eugeni Dodonov <eugeni.dodonov@intel.com>
+
+commit ab3951eb74e7c33a2f5b7b64d72e82f1eea61571 upstream.
+
+We should not hit this under any sane conditions, but still, this does not
+looks right.
+
+CC: Chris Wilson <chris@chris-wilson.co.uk>
+CC: Daniel Vetter <daniel.vetter@ffwll.ch>
+Reported-by: Herton Ronaldo Krzesinski <herton.krzesinski@canonical.com>
+Reviewed-by: Chris Wlison <chris@chris-wilson.co.uk>
+Signed-off-by: Eugeni Dodonov <eugeni.dodonov@intel.com>
+Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
+Signed-off-by: Julien Cristau <jcristau@debian.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/gpu/drm/i915/intel_display.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/drivers/gpu/drm/i915/intel_display.c
++++ b/drivers/gpu/drm/i915/intel_display.c
+@@ -7505,7 +7505,7 @@ static int intel_gen7_queue_flip(struct
+ default:
+ WARN_ONCE(1, "unknown plane in flip command\n");
+ ret = -ENODEV;
+- goto err;
++ goto err_unpin;
+ }
+
+ ret = intel_ring_begin(ring, 4);
--- /dev/null
+From e574d421d77efd42519f36f71fb3f49001b57293 Mon Sep 17 00:00:00 2001
+From: Ben Widawsky <ben@bwidawsk.net>
+Date: Wed, 3 Oct 2012 19:34:24 -0700
+Subject: drm/i915: Fix GT_MODE default value
+
+From: Ben Widawsky <ben@bwidawsk.net>
+
+commit f8f2ac9a76b0f80a6763ca316116a7bab8486997 upstream.
+
+I can't even find how I figured this might be needed anymore. But sure
+enough, the value I'm reading back on platforms doesn't match what the
+docs recommends.
+
+It seemed to fix Chris' GT1 in limited testing as well.
+
+Tested-by: Chris Wilson <chris@chris-wilson.co.uk>
+Signed-off-by: Ben Widawsky <ben@bwidawsk.net>
+Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
+[bwh: Backported to 3.2: open-code _MASKED_BIT_{ENABLE,DISABLE}]
+Signed-off-by: Ben Hutchings <ben@decadent.org.uk>
+Signed-off-by: Julien Cristau <jcristau@debian.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/gpu/drm/i915/i915_reg.h | 3 +++
+ drivers/gpu/drm/i915/intel_display.c | 5 +++++
+ 2 files changed, 8 insertions(+)
+
+--- a/drivers/gpu/drm/i915/i915_reg.h
++++ b/drivers/gpu/drm/i915/i915_reg.h
+@@ -445,6 +445,9 @@
+ # define VS_TIMER_DISPATCH (1 << 6)
+ # define MI_FLUSH_ENABLE (1 << 12)
+
++#define GEN6_GT_MODE 0x20d0
++#define GEN6_GT_MODE_HI (1 << 9)
++
+ #define GFX_MODE 0x02520
+ #define GFX_MODE_GEN7 0x0229c
+ #define RING_MODE_GEN7(ring) ((ring)->mmio_base+0x29c)
+--- a/drivers/gpu/drm/i915/intel_display.c
++++ b/drivers/gpu/drm/i915/intel_display.c
+@@ -8620,6 +8620,11 @@ static void gen6_init_clock_gating(struc
+ DISPPLANE_TRICKLE_FEED_DISABLE);
+ intel_flush_display_plane(dev_priv, pipe);
+ }
++
++ /* The default value should be 0x200 according to docs, but the two
++ * platforms I checked have a 0 for this. (Maybe BIOS overrides?) */
++ I915_WRITE(GEN6_GT_MODE, 0xffff << 16);
++ I915_WRITE(GEN6_GT_MODE, GEN6_GT_MODE_HI << 16 | GEN6_GT_MODE_HI);
+ }
+
+ static void gen7_setup_fixed_func_scheduler(struct drm_i915_private *dev_priv)
--- /dev/null
+From a7af5ff4992e0755d3aa3f889c323cb23ed83612 Mon Sep 17 00:00:00 2001
+From: Daniel Vetter <daniel.vetter@ffwll.ch>
+Date: Tue, 2 Oct 2012 17:54:35 +0200
+Subject: drm/i915: call drm_handle_vblank before finish_page_flip
+
+From: Daniel Vetter <daniel.vetter@ffwll.ch>
+
+commit 74d44445afb9f50126eba052adeb89827cee88f3 upstream.
+
+... since finish_page_flip needs the vblank timestamp generated
+in drm_handle_vblank. Somehow all the gmch platforms get it right,
+but all the pch platform irq handlers get is wrong. Hooray for copy&
+pasting!
+
+Currently this gets papered over by a gross hack in finish_page_flip.
+A second patch will remove that.
+
+Note that without this, the new timestamp sanity checks in flip_test
+occasionally get tripped up, hence the cc: stable tag.
+
+Reviewed-by: mario.kleiner@tuebingen.mpg.de
+Tested-by: Imre Deak <imre.deak@intel.com>
+Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
+[bwh: Backported to 3.2: no loop over pipes in ivybridge_irq_handler(),
+ so make a similar change to that in ironlake_irq_handler()]
+Signed-off-by: Ben Hutchings <ben@decadent.org.uk>
+Signed-off-by: Julien Cristau <jcristau@debian.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/gpu/drm/i915/i915_irq.c | 24 ++++++++++++------------
+ 1 file changed, 12 insertions(+), 12 deletions(-)
+
+--- a/drivers/gpu/drm/i915/i915_irq.c
++++ b/drivers/gpu/drm/i915/i915_irq.c
+@@ -530,6 +530,12 @@ static irqreturn_t ivybridge_irq_handler
+ if (de_iir & DE_GSE_IVB)
+ intel_opregion_gse_intr(dev);
+
++ if (de_iir & DE_PIPEA_VBLANK_IVB)
++ drm_handle_vblank(dev, 0);
++
++ if (de_iir & DE_PIPEB_VBLANK_IVB)
++ drm_handle_vblank(dev, 1);
++
+ if (de_iir & DE_PLANEA_FLIP_DONE_IVB) {
+ intel_prepare_page_flip(dev, 0);
+ intel_finish_page_flip_plane(dev, 0);
+@@ -540,12 +546,6 @@ static irqreturn_t ivybridge_irq_handler
+ intel_finish_page_flip_plane(dev, 1);
+ }
+
+- if (de_iir & DE_PIPEA_VBLANK_IVB)
+- drm_handle_vblank(dev, 0);
+-
+- if (de_iir & DE_PIPEB_VBLANK_IVB)
+- drm_handle_vblank(dev, 1);
+-
+ /* check event from PCH */
+ if (de_iir & DE_PCH_EVENT_IVB) {
+ if (pch_iir & SDE_HOTPLUG_MASK_CPT)
+@@ -622,6 +622,12 @@ static irqreturn_t ironlake_irq_handler(
+ if (de_iir & DE_GSE)
+ intel_opregion_gse_intr(dev);
+
++ if (de_iir & DE_PIPEA_VBLANK)
++ drm_handle_vblank(dev, 0);
++
++ if (de_iir & DE_PIPEB_VBLANK)
++ drm_handle_vblank(dev, 1);
++
+ if (de_iir & DE_PLANEA_FLIP_DONE) {
+ intel_prepare_page_flip(dev, 0);
+ intel_finish_page_flip_plane(dev, 0);
+@@ -632,12 +638,6 @@ static irqreturn_t ironlake_irq_handler(
+ intel_finish_page_flip_plane(dev, 1);
+ }
+
+- if (de_iir & DE_PIPEA_VBLANK)
+- drm_handle_vblank(dev, 0);
+-
+- if (de_iir & DE_PIPEB_VBLANK)
+- drm_handle_vblank(dev, 1);
+-
+ /* check event from PCH */
+ if (de_iir & DE_PCH_EVENT) {
+ if (pch_iir & hotplug_mask)
--- /dev/null
+From 26db88c526637f289781830db777b0fd07b01bff Mon Sep 17 00:00:00 2001
+From: Chris Wilson <chris@chris-wilson.co.uk>
+Date: Thu, 27 Sep 2012 21:25:58 +0100
+Subject: drm/i915: Flush the pending flips on the CRTC before modification
+
+From: Chris Wilson <chris@chris-wilson.co.uk>
+
+commit 5bb61643f6a70d48de9cfe91ad0fee0d618b6816 upstream.
+
+This was meant to be the purpose of the
+intel_crtc_wait_for_pending_flips() function which is called whilst
+preparing the CRTC for a modeset or before disabling. However, as Ville
+Syrjala pointed out, we set the pending flip notification on the old
+framebuffer that is no longer attached to the CRTC by the time we come
+to flush the pending operations. Instead, we can simply wait on the
+pending unpin work to be finished on this CRTC, knowning that the
+hardware has therefore finished modifying the registers, before proceeding
+with our direct access.
+
+Fixes i-g-t/flip_test on non-pch platforms. pch platforms simply
+schedule the flip immediately when the pipe is disabled, leading
+to other funny issues.
+
+Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
+[danvet: Added i-g-t note and cc: stable]
+Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
+Signed-off-by: Julien Cristau <jcristau@debian.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/gpu/drm/i915/intel_display.c | 24 ++++++++++++++++++++++--
+ 1 file changed, 22 insertions(+), 2 deletions(-)
+
+--- a/drivers/gpu/drm/i915/intel_display.c
++++ b/drivers/gpu/drm/i915/intel_display.c
+@@ -2895,13 +2895,34 @@ static void intel_clear_scanline_wait(st
+ I915_WRITE_CTL(ring, tmp);
+ }
+
++static bool intel_crtc_has_pending_flip(struct drm_crtc *crtc)
++{
++ struct drm_device *dev = crtc->dev;
++ struct drm_i915_private *dev_priv = dev->dev_private;
++ unsigned long flags;
++ bool pending;
++
++ if (atomic_read(&dev_priv->mm.wedged))
++ return false;
++
++ spin_lock_irqsave(&dev->event_lock, flags);
++ pending = to_intel_crtc(crtc)->unpin_work != NULL;
++ spin_unlock_irqrestore(&dev->event_lock, flags);
++
++ return pending;
++}
++
+ static void intel_crtc_wait_for_pending_flips(struct drm_crtc *crtc)
+ {
+ struct drm_device *dev = crtc->dev;
++ struct drm_i915_private *dev_priv = dev->dev_private;
+
+ if (crtc->fb == NULL)
+ return;
+
++ wait_event(dev_priv->pending_flip_queue,
++ !intel_crtc_has_pending_flip(crtc));
++
+ mutex_lock(&dev->struct_mutex);
+ intel_finish_fb(crtc->fb);
+ mutex_unlock(&dev->struct_mutex);
+@@ -7258,9 +7279,8 @@ static void do_intel_finish_page_flip(st
+
+ atomic_clear_mask(1 << intel_crtc->plane,
+ &obj->pending_flip.counter);
+- if (atomic_read(&obj->pending_flip) == 0)
+- wake_up(&dev_priv->pending_flip_queue);
+
++ wake_up(&dev_priv->pending_flip_queue);
+ schedule_work(&work->work);
+
+ trace_i915_flip_complete(intel_crtc->plane, work->pending_flip_obj);
gfs2-test-bufdata-with-buffer-locked-and-gfs2_log_lock-held.patch
drm-i915-disable-cpt-phase-pointer-fdi-rx-workaround.patch
kvm-ppc-44x-fix-dcr-read-write.patch
+0001-drm-edid-quirks-ViewSonic-VA2026w.patch
+0002-drm-i915-Unpin-the-flip-target-if-we-fail-to-queue-t.patch
+0003-drm-i915-fix-up-ivb-plane-3-pageflips.patch
+0004-drm-i915-move-NEEDS_FORCE_WAKE-to-i915_drv.c.patch
+0005-drm-i915-hold-forcewake-around-ring-hw-init.patch
+0006-drm-i915-Check-VBIOS-value-for-determining-LVDS-dual.patch
+0007-drm-i915-Add-wait_for-in-init_ring_common.patch
+0008-drm-i915-Wait-for-all-pending-operations-to-the-fb-b.patch
+0009-drm-i915-don-t-pwrite-tiled-objects-through-the-gtt.patch
+0010-drm-radeon-fix-up-pll-selection-on-DCE5-6.patch
+0011-drm-i915-add-some-barriers-when-changing-DIPs.patch
+0012-drm-i915-SDVO-hotplug-have-different-interrupt-statu.patch
+0013-drm-radeon-fix-ordering-in-pll-picking-on-dce4.patch
+0014-drm-Add-EDID_QUIRK_FORCE_REDUCED_BLANKING-for-ASUS-V.patch
+0015-drm-i915-only-enable-sdvo-hotplug-irq-if-needed.patch
+0016-drm-i915-Reduce-a-pin-leak-BUG-into-a-WARN.patch
+0017-drm-i915-prevent-possible-pin-leak-on-error-path.patch
+0018-drm-i915-Fix-GT_MODE-default-value.patch
+0019-drm-i915-call-drm_handle_vblank-before-finish_page_f.patch
+0020-drm-i915-Flush-the-pending-flips-on-the-CRTC-before-.patch