[kernel/f14/master] nouveau: more fixes

Ben Skeggs bskeggs at fedoraproject.org
Fri Oct 1 05:53:00 UTC 2010


commit 2e4b75da82511e4f124bdb5af1641d77c3d49b82
Author: Ben Skeggs <bskeggs at redhat.com>
Date:   Fri Oct 1 15:52:28 2010 +1000

    nouveau: more fixes

 drm-nouveau-ibdma-race.patch |   29 --
 drm-nouveau-updates.patch    |  609 +++++++++++++++++++++++++++++++++---------
 kernel.spec                  |    8 +-
 3 files changed, 481 insertions(+), 165 deletions(-)
---
diff --git a/drm-nouveau-updates.patch b/drm-nouveau-updates.patch
index 1939d9b..ec86a44 100644
--- a/drm-nouveau-updates.patch
+++ b/drm-nouveau-updates.patch
@@ -1,4 +1,4 @@
-From 1a79b8673c5f061a87b5fe1579e3de5a50aadea5 Mon Sep 17 00:00:00 2001
+From b1bfbda896a9d9d8e8bd86dd08aac2b2f9928ce1 Mon Sep 17 00:00:00 2001
 From: Ben Skeggs <bskeggs at redhat.com>
 Date: Tue, 1 Jun 2010 15:32:24 +1000
 Subject: [PATCH] drm-nouveau-updates
@@ -1027,6 +1027,85 @@ drm/nouveau: correct INIT_DP_CONDITION subcondition 5
 Fixes DP output on a GTX 465 board I have.
 
 Signed-off-by: Ben Skeggs <bskeggs at redhat.com>
+
+drm/nouveau: add debugfs file to forcibly evict everything from vram
+
+Very useful for debugging buffer migration issues.
+
+Signed-off-by: Ben Skeggs <bskeggs at redhat.com>
+
+drm/nv50: assume smaller tiles for bo moves
+
+Somehow fixes some corruption seen in KDE..
+
+Signed-off-by: Ben Skeggs <bskeggs at redhat.com>
+
+drm/nouveau: fix panels using straps-based mode detection
+
+nouveau_bios_fp_mode() zeroes the mode struct before filling in relevant
+entries.  This nukes the mode id initialised by drm_mode_create(), and
+causes warnings from idr when we try to remove the mode.
+
+Signed-off-by: Ben Skeggs <bskeggs at redhat.com>
+
+drm/nv10: Don't oops if the card wants to switch to a channel with no grctx.
+
+Signed-off-by: Francisco Jerez <currojerez at riseup.net>
+
+drm/nouveau: enable enhanced framing only if DP display supports it
+
+Reported-by: Adam Jackson <ajax at redhat.com>
+Signed-off-by: Ben Skeggs <bskeggs at redhat.com>
+
+drm/nouveau: fix typo in c2aa91afea5f7e7ae4530fabd37414a79c03328c
+
+Signed-off-by: Ben Skeggs <bskeggs at redhat.com>
+
+drm/nouveau: fix required mode bandwidth calculation for DP
+
+This should fix eDP on certain laptops with 18-bit panels, we were rejecting
+the panel's native mode due to thinking there was insufficient bandwidth
+for it.
+
+Signed-off-by: Ben Skeggs <bskeggs at redhat.com>
+
+drm/nv30-nv40: Fix postdivider mask when writing engine/memory PLLs.
+
+Signed-off-by: Francisco Jerez <currojerez at riseup.net>
+
+drm/nv0x-nv4x: Leave the 0x40 bit untouched when changing CRE_LCD.
+
+It's an unrelated PLL filtering control bit, leave it alone when
+changing the CRTC-encoder binding.
+
+Signed-off-by: Francisco Jerez <currojerez at riseup.net>
+
+drm/nv50: prevent (IB_PUT == IB_GET) for occurring unless idle
+
+Should fix a DMA race condition I've never seen myself, but could be
+the culprit in some random hangs that have been reported.
+
+Signed-off-by: Ben Skeggs <bskeggs at redhat.com>
+
+drm/nouveau: Add a module option to force card POST.
+
+Signed-off-by: Ben Skeggs <bskeggs at redhat.com>
+
+drm/nouveau: Try to fetch an EDID from OF if DDC fails.
+
+More Apple brain damage, it fixes the modesetting failure on an eMac
+G4 (fdo bug 29810).
+
+Reported-by: Zoltan Varnagy <doi at freemail.hu>
+Signed-off-by: Francisco Jerez <currojerez at riseup.net>
+
+drm/nouveau: better handling of unmappable vram
+
+Signed-off-by: Ben Skeggs <bskeggs at redhat.com>
+
+drm/nouveau: fix chipset vs card_type thinko
+
+Signed-off-by: Ben Skeggs <bskeggs at redhat.com>
 ---
  drivers/gpu/drm/drm_crtc_helper.c           |   22 +-
  drivers/gpu/drm/i2c/ch7006_drv.c            |   22 +-
@@ -1034,24 +1113,25 @@ Signed-off-by: Ben Skeggs <bskeggs at redhat.com>
  drivers/gpu/drm/nouveau/Kconfig             |    1 +
  drivers/gpu/drm/nouveau/Makefile            |   12 +-
  drivers/gpu/drm/nouveau/nouveau_acpi.c      |   38 +-
- drivers/gpu/drm/nouveau/nouveau_bios.c      |  912 ++++++--
+ drivers/gpu/drm/nouveau/nouveau_bios.c      |  914 ++++++--
  drivers/gpu/drm/nouveau/nouveau_bios.h      |    6 +-
- drivers/gpu/drm/nouveau/nouveau_bo.c        |  228 ++-
+ drivers/gpu/drm/nouveau/nouveau_bo.c        |  251 ++-
  drivers/gpu/drm/nouveau/nouveau_calc.c      |   10 +-
  drivers/gpu/drm/nouveau/nouveau_channel.c   |   18 +-
- drivers/gpu/drm/nouveau/nouveau_connector.c |  417 ++--
- drivers/gpu/drm/nouveau/nouveau_connector.h |    7 +-
- drivers/gpu/drm/nouveau/nouveau_dma.c       |   21 +-
- drivers/gpu/drm/nouveau/nouveau_dp.c        |  131 +-
- drivers/gpu/drm/nouveau/nouveau_drv.c       |   45 +-
- drivers/gpu/drm/nouveau/nouveau_drv.h       |  309 ++--
- drivers/gpu/drm/nouveau/nouveau_encoder.h   |   16 +-
+ drivers/gpu/drm/nouveau/nouveau_connector.c |  473 ++--
+ drivers/gpu/drm/nouveau/nouveau_connector.h |   10 +-
+ drivers/gpu/drm/nouveau/nouveau_debugfs.c   |   16 +
+ drivers/gpu/drm/nouveau/nouveau_dma.c       |   23 +-
+ drivers/gpu/drm/nouveau/nouveau_dp.c        |  138 +-
+ drivers/gpu/drm/nouveau/nouveau_drv.c       |   49 +-
+ drivers/gpu/drm/nouveau/nouveau_drv.h       |  310 ++--
+ drivers/gpu/drm/nouveau/nouveau_encoder.h   |   17 +-
  drivers/gpu/drm/nouveau/nouveau_fbcon.c     |    4 +-
  drivers/gpu/drm/nouveau/nouveau_fence.c     |   35 +-
  drivers/gpu/drm/nouveau/nouveau_gem.c       |   15 +-
  drivers/gpu/drm/nouveau/nouveau_grctx.c     |  160 --
  drivers/gpu/drm/nouveau/nouveau_grctx.h     |    2 +-
- drivers/gpu/drm/nouveau/nouveau_hw.c        |   13 +-
+ drivers/gpu/drm/nouveau/nouveau_hw.c        |   15 +-
  drivers/gpu/drm/nouveau/nouveau_i2c.c       |   83 +-
  drivers/gpu/drm/nouveau/nouveau_i2c.h       |   11 +-
  drivers/gpu/drm/nouveau/nouveau_irq.c       |  129 +-
@@ -1064,20 +1144,20 @@ Signed-off-by: Ben Skeggs <bskeggs at redhat.com>
  drivers/gpu/drm/nouveau/nouveau_sgdma.c     |  118 +-
  drivers/gpu/drm/nouveau/nouveau_state.c     |  398 ++--
  drivers/gpu/drm/nouveau/nv04_crtc.c         |   11 +-
- drivers/gpu/drm/nouveau/nv04_dac.c          |   60 +-
- drivers/gpu/drm/nouveau/nv04_dfp.c          |  145 +-
+ drivers/gpu/drm/nouveau/nv04_dac.c          |   61 +-
+ drivers/gpu/drm/nouveau/nv04_dfp.c          |  147 +-
  drivers/gpu/drm/nouveau/nv04_display.c      |   90 +-
  drivers/gpu/drm/nouveau/nv04_fbcon.c        |    9 +-
  drivers/gpu/drm/nouveau/nv04_fifo.c         |   88 +-
  drivers/gpu/drm/nouveau/nv04_graph.c        |    5 +-
  drivers/gpu/drm/nouveau/nv04_instmem.c      |  167 +-
  drivers/gpu/drm/nouveau/nv04_mc.c           |    4 +
- drivers/gpu/drm/nouveau/nv04_tv.c           |  133 +-
+ drivers/gpu/drm/nouveau/nv04_tv.c           |  139 +-
  drivers/gpu/drm/nouveau/nv10_fifo.c         |   29 +-
  drivers/gpu/drm/nouveau/nv10_gpio.c         |   92 +
- drivers/gpu/drm/nouveau/nv10_graph.c        |  175 +-
+ drivers/gpu/drm/nouveau/nv10_graph.c        |  177 +-
  drivers/gpu/drm/nouveau/nv17_gpio.c         |   92 -
- drivers/gpu/drm/nouveau/nv17_tv.c           |  181 +-
+ drivers/gpu/drm/nouveau/nv17_tv.c           |  179 +-
  drivers/gpu/drm/nouveau/nv17_tv.h           |   15 +-
  drivers/gpu/drm/nouveau/nv17_tv_modes.c     |   48 +-
  drivers/gpu/drm/nouveau/nv20_graph.c        |  576 +++---
@@ -1103,8 +1183,8 @@ Signed-off-by: Ben Skeggs <bskeggs at redhat.com>
  drivers/gpu/drm/nouveau/nvc0_fifo.c         |   89 +
  drivers/gpu/drm/nouveau/nvc0_graph.c        |   74 +
  drivers/gpu/drm/nouveau/nvc0_instmem.c      |  229 ++
- drivers/gpu/drm/nouveau/nvreg.h             |   22 -
- 76 files changed, 7472 insertions(+), 5278 deletions(-)
+ drivers/gpu/drm/nouveau/nvreg.h             |   23 +-
+ 77 files changed, 7584 insertions(+), 5293 deletions(-)
  delete mode 100644 drivers/gpu/drm/nouveau/nouveau_grctx.c
  create mode 100644 drivers/gpu/drm/nouveau/nouveau_ramht.c
  create mode 100644 drivers/gpu/drm/nouveau/nouveau_ramht.h
@@ -1352,7 +1432,7 @@ index d4bcca8..1191526 100644
 +	return 0;
 +}
 diff --git a/drivers/gpu/drm/nouveau/nouveau_bios.c b/drivers/gpu/drm/nouveau/nouveau_bios.c
-index e492919..47bc0ba 100644
+index e492919..72905c9 100644
 --- a/drivers/gpu/drm/nouveau/nouveau_bios.c
 +++ b/drivers/gpu/drm/nouveau/nouveau_bios.c
 @@ -28,6 +28,8 @@
@@ -2829,7 +2909,7 @@ index e492919..47bc0ba 100644
  	int ret;
  
  	if (!NVInitVBIOS(dev))
-@@ -6284,40 +6797,27 @@ nouveau_bios_init(struct drm_device *dev)
+@@ -6284,40 +6797,29 @@ nouveau_bios_init(struct drm_device *dev)
  	if (!bios->major_version)	/* we don't run version 0 bios */
  		return 0;
  
@@ -2853,9 +2933,11 @@ index e492919..47bc0ba 100644
 +			"running VBIOS init tables.\n");
  		bios->execute = true;
  	}
- 
--	bios_wr32(bios, NV_PEXTDEV_BOOT_0, saved_nv_pextdev_boot_0);
 -
+-	bios_wr32(bios, NV_PEXTDEV_BOOT_0, saved_nv_pextdev_boot_0);
++	if (nouveau_force_post)
++		bios->execute = true;
+ 
  	ret = nouveau_run_vbios_init(dev);
  	if (ret)
  		return ret;
@@ -2918,10 +3000,10 @@ index adf4ec2..c1de2f3 100644
  
  	struct {
 diff --git a/drivers/gpu/drm/nouveau/nouveau_bo.c b/drivers/gpu/drm/nouveau/nouveau_bo.c
-index 6f3c195..22a2038 100644
+index 51746d9..a4011f5 100644
 --- a/drivers/gpu/drm/nouveau/nouveau_bo.c
 +++ b/drivers/gpu/drm/nouveau/nouveau_bo.c
-@@ -43,17 +43,12 @@ nouveau_bo_del_ttm(struct ttm_buffer_object *bo)
+@@ -58,17 +58,12 @@ nouveau_bo_del_ttm(struct ttm_buffer_object *bo)
  	struct drm_device *dev = dev_priv->dev;
  	struct nouveau_bo *nvbo = nouveau_bo(bo);
  
@@ -2939,7 +3021,16 @@ index 6f3c195..22a2038 100644
  	kfree(nvbo);
  }
  
-@@ -166,9 +161,6 @@ nouveau_bo_new(struct drm_device *dev, struct nouveau_channel *chan,
+@@ -167,8 +162,6 @@ nouveau_bo_new(struct drm_device *dev, struct nouveau_channel *chan,
+ 	nouveau_bo_fixup_align(dev, tile_mode, tile_flags, &align, &size);
+ 	align >>= PAGE_SHIFT;
+ 
+-	nvbo->placement.fpfn = 0;
+-	nvbo->placement.lpfn = mappable ? dev_priv->fb_mappable_pages : 0;
+ 	nouveau_bo_placement_set(nvbo, flags, 0);
+ 
+ 	nvbo->channel = chan;
+@@ -181,9 +174,6 @@ nouveau_bo_new(struct drm_device *dev, struct nouveau_channel *chan,
  	}
  	nvbo->channel = NULL;
  
@@ -2949,7 +3040,7 @@ index 6f3c195..22a2038 100644
  	*pnvbo = nvbo;
  	return 0;
  }
-@@ -296,7 +288,8 @@ nouveau_bo_map(struct nouveau_bo *nvbo)
+@@ -311,7 +301,8 @@ nouveau_bo_map(struct nouveau_bo *nvbo)
  void
  nouveau_bo_unmap(struct nouveau_bo *nvbo)
  {
@@ -2959,7 +3050,7 @@ index 6f3c195..22a2038 100644
  }
  
  u16
-@@ -395,7 +388,10 @@ nouveau_bo_init_mem_type(struct ttm_bo_device *bdev, uint32_t type,
+@@ -410,7 +401,10 @@ nouveau_bo_init_mem_type(struct ttm_bo_device *bdev, uint32_t type,
  		man->available_caching = TTM_PL_FLAG_UNCACHED |
  					 TTM_PL_FLAG_WC;
  		man->default_caching = TTM_PL_FLAG_WC;
@@ -2971,7 +3062,7 @@ index 6f3c195..22a2038 100644
  		break;
  	case TTM_PL_TT:
  		switch (dev_priv->gart_info.type) {
-@@ -461,18 +457,20 @@ nouveau_bo_move_accel_cleanup(struct nouveau_channel *chan,
+@@ -476,18 +470,20 @@ nouveau_bo_move_accel_cleanup(struct nouveau_channel *chan,
  		return ret;
  
  	ret = ttm_bo_move_accel_cleanup(&nvbo->bo, fence, NULL,
@@ -2998,7 +3089,7 @@ index 6f3c195..22a2038 100644
  		if (mem->mem_type == TTM_PL_TT)
  			return NvDmaGART;
  		return NvDmaVRAM;
-@@ -484,86 +482,181 @@ nouveau_bo_mem_ctxdma(struct nouveau_bo *nvbo, struct nouveau_channel *chan,
+@@ -499,86 +495,181 @@ nouveau_bo_mem_ctxdma(struct nouveau_bo *nvbo, struct nouveau_channel *chan,
  }
  
  static int
@@ -3060,8 +3151,8 @@ index 6f3c195..22a2038 100644
 +	while (length) {
 +		u32 amount, stride, height;
 +
-+		amount  = min(length, (u64)(16 * 1024 * 1024));
-+		stride  = 64 * 4;
++		amount  = min(length, (u64)(4 * 1024 * 1024));
++		stride  = 16 * 4;
 +		height  = amount / stride;
 +
 +		if (new_mem->mem_type == TTM_PL_VRAM && nvbo->tile_flags) {
@@ -3071,7 +3162,7 @@ index 6f3c195..22a2038 100644
 +
 +			BEGIN_RING(chan, NvSubM2MF, 0x0200, 7);
 +			OUT_RING  (chan, 0);
-+			OUT_RING  (chan, 0x20);
++			OUT_RING  (chan, 0);
 +			OUT_RING  (chan, stride);
 +			OUT_RING  (chan, height);
 +			OUT_RING  (chan, 1);
@@ -3092,7 +3183,7 @@ index 6f3c195..22a2038 100644
 +
 +			BEGIN_RING(chan, NvSubM2MF, 0x021c, 7);
 +			OUT_RING  (chan, 0);
-+			OUT_RING  (chan, 0x20);
++			OUT_RING  (chan, 0);
 +			OUT_RING  (chan, stride);
 +			OUT_RING  (chan, height);
 +			OUT_RING  (chan, 1);
@@ -3225,7 +3316,7 @@ index 6f3c195..22a2038 100644
  	return nouveau_bo_move_accel_cleanup(chan, nvbo, evict, no_wait_reserve, no_wait_gpu, new_mem);
  }
  
-@@ -710,13 +803,6 @@ nouveau_bo_move(struct ttm_buffer_object *bo, bool evict, bool intr,
+@@ -725,13 +816,6 @@ nouveau_bo_move(struct ttm_buffer_object *bo, bool evict, bool intr,
  	if (ret)
  		return ret;
  
@@ -3239,7 +3330,7 @@ index 6f3c195..22a2038 100644
  	/* Fake bo copy. */
  	if (old_mem->mem_type == TTM_PL_SYSTEM && !bo->ttm) {
  		BUG_ON(bo->mem.mm_node != NULL);
-@@ -725,6 +811,12 @@ nouveau_bo_move(struct ttm_buffer_object *bo, bool evict, bool intr,
+@@ -740,6 +824,12 @@ nouveau_bo_move(struct ttm_buffer_object *bo, bool evict, bool intr,
  		goto out;
  	}
  
@@ -3252,6 +3343,34 @@ index 6f3c195..22a2038 100644
  	/* Hardware assisted copy. */
  	if (new_mem->mem_type == TTM_PL_SYSTEM)
  		ret = nouveau_bo_move_flipd(bo, evict, intr, no_wait_reserve, no_wait_gpu, new_mem);
+@@ -815,7 +905,26 @@ nouveau_ttm_io_mem_free(struct ttm_bo_device *bdev, struct ttm_mem_reg *mem)
+ static int
+ nouveau_ttm_fault_reserve_notify(struct ttm_buffer_object *bo)
+ {
+-	return 0;
++	struct drm_nouveau_private *dev_priv = nouveau_bdev(bo->bdev);
++	struct nouveau_bo *nvbo = nouveau_bo(bo);
++
++	/* as long as the bo isn't in vram, and isn't tiled, we've got
++	 * nothing to do here.
++	 */
++	if (bo->mem.mem_type != TTM_PL_VRAM) {
++		if (dev_priv->card_type < NV_50 || !nvbo->tile_flags)
++			return 0;
++	}
++
++	/* make sure bo is in mappable vram */
++	if (bo->mem.mm_node->start + bo->mem.num_pages < dev_priv->fb_mappable_pages)
++		return 0;
++
++
++	nvbo->placement.fpfn = 0;
++	nvbo->placement.lpfn = dev_priv->fb_mappable_pages;
++	nouveau_bo_placement_set(nvbo, TTM_PL_VRAM, 0);
++	return ttm_bo_validate(bo, &nvbo->placement, false, true, false);
+ }
+ 
+ struct ttm_bo_driver nouveau_bo_driver = {
 diff --git a/drivers/gpu/drm/nouveau/nouveau_calc.c b/drivers/gpu/drm/nouveau/nouveau_calc.c
 index 88f9bc0..23d9896 100644
 --- a/drivers/gpu/drm/nouveau/nouveau_calc.c
@@ -3360,7 +3479,7 @@ index 1fc57ef..53c2a6f 100644
  
  	nouveau_channel_free(chan);
 diff --git a/drivers/gpu/drm/nouveau/nouveau_connector.c b/drivers/gpu/drm/nouveau/nouveau_connector.c
-index 149ed22..a1473ff 100644
+index 149ed22..46584c3 100644
 --- a/drivers/gpu/drm/nouveau/nouveau_connector.c
 +++ b/drivers/gpu/drm/nouveau/nouveau_connector.c
 @@ -37,12 +37,6 @@
@@ -3376,7 +3495,30 @@ index 149ed22..a1473ff 100644
  static struct nouveau_encoder *
  find_encoder_by_type(struct drm_connector *connector, int type)
  {
-@@ -102,60 +96,12 @@ nouveau_connector_destroy(struct drm_connector *drm_connector)
+@@ -82,6 +76,22 @@ nouveau_encoder_connector_get(struct nouveau_encoder *encoder)
+ 	return NULL;
+ }
+ 
++/*TODO: This could use improvement, and learn to handle the fixed
++ *      BIOS tables etc.  It's fine currently, for its only user.
++ */
++int
++nouveau_connector_bpp(struct drm_connector *connector)
++{
++	struct nouveau_connector *nv_connector = nouveau_connector(connector);
++
++	if (nv_connector->edid && nv_connector->edid->revision >= 4) {
++		u8 bpc = ((nv_connector->edid->input & 0x70) >> 3) + 4;
++		if (bpc > 4)
++			return bpc;
++	}
++
++	return 18;
++}
+ 
+ static void
+ nouveau_connector_destroy(struct drm_connector *drm_connector)
+@@ -102,60 +112,12 @@ nouveau_connector_destroy(struct drm_connector *drm_connector)
  	kfree(drm_connector);
  }
  
@@ -3438,7 +3580,7 @@ index 149ed22..a1473ff 100644
  
  	for (i = 0; i < DRM_CONNECTOR_MAX_ENCODER; i++) {
  		struct nouveau_i2c_chan *i2c = NULL;
-@@ -174,14 +120,8 @@ nouveau_connector_ddc_detect(struct drm_connector *connector,
+@@ -174,14 +136,8 @@ nouveau_connector_ddc_detect(struct drm_connector *connector,
  
  		if (nv_encoder->dcb->i2c_index < 0xf)
  			i2c = nouveau_i2c_find(dev, nv_encoder->dcb->i2c_index);
@@ -3454,7 +3596,44 @@ index 149ed22..a1473ff 100644
  			*pnv_encoder = nv_encoder;
  			return i2c;
  		}
-@@ -234,21 +174,7 @@ nouveau_connector_detect(struct drm_connector *connector)
+@@ -190,6 +146,36 @@ nouveau_connector_ddc_detect(struct drm_connector *connector,
+ 	return NULL;
+ }
+ 
++static struct nouveau_encoder *
++nouveau_connector_of_detect(struct drm_connector *connector)
++{
++#ifdef __powerpc__
++	struct drm_device *dev = connector->dev;
++	struct nouveau_connector *nv_connector = nouveau_connector(connector);
++	struct nouveau_encoder *nv_encoder;
++	struct device_node *cn, *dn = pci_device_to_OF_node(dev->pdev);
++
++	if (!dn ||
++	    !((nv_encoder = find_encoder_by_type(connector, OUTPUT_TMDS)) ||
++	      (nv_encoder = find_encoder_by_type(connector, OUTPUT_ANALOG))))
++		return NULL;
++
++	for_each_child_of_node(dn, cn) {
++		const char *name = of_get_property(cn, "name", NULL);
++		const void *edid = of_get_property(cn, "EDID", NULL);
++		int idx = name ? name[strlen(name) - 1] - 'A' : 0;
++
++		if (nv_encoder->dcb->i2c_index == idx && edid) {
++			nv_connector->edid =
++				kmemdup(edid, EDID_LENGTH, GFP_KERNEL);
++			of_node_put(cn);
++			return nv_encoder;
++		}
++	}
++#endif
++	return NULL;
++}
++
+ static void
+ nouveau_connector_set_encoder(struct drm_connector *connector,
+ 			      struct nouveau_encoder *nv_encoder)
+@@ -234,21 +220,7 @@ nouveau_connector_detect(struct drm_connector *connector)
  	struct nouveau_connector *nv_connector = nouveau_connector(connector);
  	struct nouveau_encoder *nv_encoder = NULL;
  	struct nouveau_i2c_chan *i2c;
@@ -3477,7 +3656,7 @@ index 149ed22..a1473ff 100644
  
  	/* Cleanup the previous EDID block. */
  	if (nv_connector->edid) {
-@@ -259,9 +185,7 @@ nouveau_connector_detect(struct drm_connector *connector)
+@@ -259,9 +231,7 @@ nouveau_connector_detect(struct drm_connector *connector)
  
  	i2c = nouveau_connector_ddc_detect(connector, &nv_encoder);
  	if (i2c) {
@@ -3487,7 +3666,20 @@ index 149ed22..a1473ff 100644
  		drm_mode_connector_update_edid_property(connector,
  							nv_connector->edid);
  		if (!nv_connector->edid) {
-@@ -321,6 +245,85 @@ detect_analog:
+@@ -301,6 +271,12 @@ nouveau_connector_detect(struct drm_connector *connector)
+ 		return connector_status_connected;
+ 	}
+ 
++	nv_encoder = nouveau_connector_of_detect(connector);
++	if (nv_encoder) {
++		nouveau_connector_set_encoder(connector, nv_encoder);
++		return connector_status_connected;
++	}
++
+ detect_analog:
+ 	nv_encoder = find_encoder_by_type(connector, OUTPUT_ANALOG);
+ 	if (!nv_encoder && !nouveau_tv_disable)
+@@ -321,6 +297,85 @@ detect_analog:
  	return connector_status_disconnected;
  }
  
@@ -3573,7 +3765,7 @@ index 149ed22..a1473ff 100644
  static void
  nouveau_connector_force(struct drm_connector *connector)
  {
-@@ -353,6 +356,7 @@ nouveau_connector_set_property(struct drm_connector *connector,
+@@ -353,6 +408,7 @@ nouveau_connector_set_property(struct drm_connector *connector,
  {
  	struct nouveau_connector *nv_connector = nouveau_connector(connector);
  	struct nouveau_encoder *nv_encoder = nv_connector->detected_encoder;
@@ -3581,7 +3773,7 @@ index 149ed22..a1473ff 100644
  	struct drm_device *dev = connector->dev;
  	int ret;
  
-@@ -425,8 +429,8 @@ nouveau_connector_set_property(struct drm_connector *connector,
+@@ -425,8 +481,8 @@ nouveau_connector_set_property(struct drm_connector *connector,
  	}
  
  	if (nv_encoder && nv_encoder->dcb->type == OUTPUT_TV)
@@ -3592,7 +3784,7 @@ index 149ed22..a1473ff 100644
  
  	return -EINVAL;
  }
-@@ -441,7 +445,8 @@ nouveau_connector_native_mode(struct drm_connector *connector)
+@@ -441,7 +497,8 @@ nouveau_connector_native_mode(struct drm_connector *connector)
  	int high_w = 0, high_h = 0, high_v = 0;
  
  	list_for_each_entry(mode, &nv_connector->base.probed_modes, head) {
@@ -3602,7 +3794,7 @@ index 149ed22..a1473ff 100644
  			continue;
  
  		/* Use preferred mode if there is one.. */
-@@ -534,21 +539,28 @@ static int
+@@ -534,21 +591,30 @@ static int
  nouveau_connector_get_modes(struct drm_connector *connector)
  {
  	struct drm_device *dev = connector->dev;
@@ -3629,13 +3821,15 @@ index 149ed22..a1473ff 100644
 +	if (nv_encoder->dcb->type == OUTPUT_LVDS &&
 +	    (nv_encoder->dcb->lvdsconf.use_straps_for_mode ||
 +	     dev_priv->vbios.fp_no_ddc) && nouveau_bios_fp_mode(dev, NULL)) {
-+		nv_connector->native_mode = drm_mode_create(dev);
-+		nouveau_bios_fp_mode(dev, nv_connector->native_mode);
++		struct drm_display_mode mode;
++
++		nouveau_bios_fp_mode(dev, &mode);
++		nv_connector->native_mode = drm_mode_duplicate(dev, &mode);
 +	}
  
  	/* Find the native mode if this is a digital panel, if we didn't
  	 * find any modes through DDC previously add the native mode to
-@@ -566,10 +578,10 @@ nouveau_connector_get_modes(struct drm_connector *connector)
+@@ -566,10 +632,10 @@ nouveau_connector_get_modes(struct drm_connector *connector)
  	}
  
  	if (nv_encoder->dcb->type == OUTPUT_TV)
@@ -3649,7 +3843,7 @@ index 149ed22..a1473ff 100644
  		ret += nouveau_connector_scaler_modes_add(connector);
  
  	return ret;
-@@ -582,6 +594,7 @@ nouveau_connector_mode_valid(struct drm_connector *connector,
+@@ -582,6 +648,7 @@ nouveau_connector_mode_valid(struct drm_connector *connector,
  	struct drm_nouveau_private *dev_priv = connector->dev->dev_private;
  	struct nouveau_connector *nv_connector = nouveau_connector(connector);
  	struct nouveau_encoder *nv_encoder = nv_connector->detected_encoder;
@@ -3657,7 +3851,7 @@ index 149ed22..a1473ff 100644
  	unsigned min_clock = 25000, max_clock = min_clock;
  	unsigned clock = mode->clock;
  
-@@ -608,8 +621,7 @@ nouveau_connector_mode_valid(struct drm_connector *connector,
+@@ -608,15 +675,14 @@ nouveau_connector_mode_valid(struct drm_connector *connector,
  			max_clock = 350000;
  		break;
  	case OUTPUT_TV:
@@ -3667,7 +3861,15 @@ index 149ed22..a1473ff 100644
  	case OUTPUT_DP:
  		if (nv_encoder->dp.link_bw == DP_LINK_BW_2_7)
  			max_clock = nv_encoder->dp.link_nr * 270000;
-@@ -643,6 +655,44 @@ nouveau_connector_best_encoder(struct drm_connector *connector)
+ 		else
+ 			max_clock = nv_encoder->dp.link_nr * 162000;
+ 
+-		clock *= 3;
++		clock = clock * nouveau_connector_bpp(connector) / 8;
+ 		break;
+ 	default:
+ 		BUG_ON(1);
+@@ -643,6 +709,44 @@ nouveau_connector_best_encoder(struct drm_connector *connector)
  	return NULL;
  }
  
@@ -3712,7 +3914,7 @@ index 149ed22..a1473ff 100644
  static const struct drm_connector_helper_funcs
  nouveau_connector_helper_funcs = {
  	.get_modes = nouveau_connector_get_modes,
-@@ -662,148 +712,74 @@ nouveau_connector_funcs = {
+@@ -662,148 +766,74 @@ nouveau_connector_funcs = {
  	.force = nouveau_connector_force
  };
  
@@ -3887,7 +4089,7 @@ index 149ed22..a1473ff 100644
  	nv_connector->dcb = dcb;
  	connector = &nv_connector->base;
  
-@@ -811,27 +787,21 @@ nouveau_connector_create(struct drm_device *dev,
+@@ -811,27 +841,21 @@ nouveau_connector_create(struct drm_device *dev,
  	connector->interlace_allowed = false;
  	connector->doublescan_allowed = false;
  
@@ -3926,7 +4128,7 @@ index 149ed22..a1473ff 100644
  	}
  
  	/* Init DVI-I specific properties */
-@@ -841,12 +811,8 @@ nouveau_connector_create(struct drm_device *dev,
+@@ -841,12 +865,8 @@ nouveau_connector_create(struct drm_device *dev,
  		drm_connector_attach_property(connector, dev->mode_config.dvi_i_select_subconnector_property, 0);
  	}
  
@@ -3939,7 +4141,7 @@ index 149ed22..a1473ff 100644
  		if (dev_priv->card_type >= NV_50) {
  			drm_connector_attach_property(connector,
  					dev->mode_config.scaling_mode_property,
-@@ -858,17 +824,6 @@ nouveau_connector_create(struct drm_device *dev,
+@@ -858,17 +878,6 @@ nouveau_connector_create(struct drm_device *dev,
  	case DCB_CONNECTOR_TV_3:
  		nv_connector->scaling_mode = DRM_MODE_SCALE_NONE;
  		break;
@@ -3957,7 +4159,7 @@ index 149ed22..a1473ff 100644
  	default:
  		nv_connector->scaling_mode = DRM_MODE_SCALE_FULLSCREEN;
  
-@@ -882,15 +837,15 @@ nouveau_connector_create(struct drm_device *dev,
+@@ -882,15 +891,15 @@ nouveau_connector_create(struct drm_device *dev,
  		break;
  	}
  
@@ -3982,10 +4184,10 @@ index 149ed22..a1473ff 100644
 -	return 0;
  }
 diff --git a/drivers/gpu/drm/nouveau/nouveau_connector.h b/drivers/gpu/drm/nouveau/nouveau_connector.h
-index 4ef38ab..0d2e668 100644
+index 4ef38ab..c21ed6b 100644
 --- a/drivers/gpu/drm/nouveau/nouveau_connector.h
 +++ b/drivers/gpu/drm/nouveau/nouveau_connector.h
-@@ -49,7 +49,10 @@ static inline struct nouveau_connector *nouveau_connector(
+@@ -49,7 +49,13 @@ static inline struct nouveau_connector *nouveau_connector(
  	return container_of(con, struct nouveau_connector, base);
  }
  
@@ -3996,10 +4198,41 @@ index 4ef38ab..0d2e668 100644
 +
 +void
 +nouveau_connector_set_polling(struct drm_connector *);
++
++int
++nouveau_connector_bpp(struct drm_connector *);
  
  #endif /* __NOUVEAU_CONNECTOR_H__ */
+diff --git a/drivers/gpu/drm/nouveau/nouveau_debugfs.c b/drivers/gpu/drm/nouveau/nouveau_debugfs.c
+index 7933de4..8e15923 100644
+--- a/drivers/gpu/drm/nouveau/nouveau_debugfs.c
++++ b/drivers/gpu/drm/nouveau/nouveau_debugfs.c
+@@ -157,7 +157,23 @@ nouveau_debugfs_vbios_image(struct seq_file *m, void *data)
+ 	return 0;
+ }
+ 
++static int
++nouveau_debugfs_evict_vram(struct seq_file *m, void *data)
++{
++	struct drm_info_node *node = (struct drm_info_node *) m->private;
++	struct drm_nouveau_private *dev_priv = node->minor->dev->dev_private;
++	int ret;
++
++	ret = ttm_bo_evict_mm(&dev_priv->ttm.bdev, TTM_PL_VRAM);
++	if (ret)
++		seq_printf(m, "failed: %d", ret);
++	else
++		seq_printf(m, "succeeded\n");
++	return 0;
++}
++
+ static struct drm_info_list nouveau_debugfs_list[] = {
++	{ "evict_vram", nouveau_debugfs_evict_vram, 0, NULL },
+ 	{ "chipset", nouveau_debugfs_chipset_info, 0, NULL },
+ 	{ "memory", nouveau_debugfs_memory_info, 0, NULL },
+ 	{ "vbios.rom", nouveau_debugfs_vbios_image, 0, NULL },
 diff --git a/drivers/gpu/drm/nouveau/nouveau_dma.c b/drivers/gpu/drm/nouveau/nouveau_dma.c
-index 65c441a..9d27acd 100644
+index 65c441a..eb24e2b 100644
 --- a/drivers/gpu/drm/nouveau/nouveau_dma.c
 +++ b/drivers/gpu/drm/nouveau/nouveau_dma.c
 @@ -28,6 +28,7 @@
@@ -4058,8 +4291,17 @@ index 65c441a..9d27acd 100644
  	/* Insert NOPS for NOUVEAU_DMA_SKIPS */
  	ret = RING_SPACE(chan, NOUVEAU_DMA_SKIPS);
  	if (ret)
+@@ -219,7 +214,7 @@ nv50_dma_push_wait(struct nouveau_channel *chan, int count)
+ 
+ 		chan->dma.ib_free = get - chan->dma.ib_put;
+ 		if (chan->dma.ib_free <= 0)
+-			chan->dma.ib_free += chan->dma.ib_max + 1;
++			chan->dma.ib_free += chan->dma.ib_max;
+ 	}
+ 
+ 	return 0;
 diff --git a/drivers/gpu/drm/nouveau/nouveau_dp.c b/drivers/gpu/drm/nouveau/nouveau_dp.c
-index deeb21c..89ca1f6 100644
+index deeb21c..4562f30 100644
 --- a/drivers/gpu/drm/nouveau/nouveau_dp.c
 +++ b/drivers/gpu/drm/nouveau/nouveau_dp.c
 @@ -23,8 +23,10 @@
@@ -4115,7 +4357,17 @@ index deeb21c..89ca1f6 100644
  train:
  	cr_done = eq_done = false;
  
-@@ -403,6 +431,15 @@ stop:
+@@ -289,7 +317,8 @@ train:
+ 		return false;
+ 
+ 	config[0] = nv_encoder->dp.link_nr;
+-	if (nv_encoder->dp.dpcd_version >= 0x11)
++	if (nv_encoder->dp.dpcd_version >= 0x11 &&
++	    nv_encoder->dp.enhanced_frame)
+ 		config[0] |= DP_LANE_COUNT_ENHANCED_FRAME_EN;
+ 
+ 	ret = nouveau_dp_lane_count_set(encoder, config[0]);
+@@ -403,6 +432,15 @@ stop:
  		}
  	}
  
@@ -4131,7 +4383,21 @@ index deeb21c..89ca1f6 100644
  	return eq_done;
  }
  
-@@ -487,7 +524,8 @@ nouveau_dp_auxch(struct nouveau_i2c_chan *auxch, int cmd, int addr,
+@@ -431,10 +469,12 @@ nouveau_dp_detect(struct drm_encoder *encoder)
+ 	    !nv_encoder->dcb->dpconf.link_bw)
+ 		nv_encoder->dp.link_bw = DP_LINK_BW_1_62;
+ 
+-	nv_encoder->dp.link_nr = dpcd[2] & 0xf;
++	nv_encoder->dp.link_nr = dpcd[2] & DP_MAX_LANE_COUNT_MASK;
+ 	if (nv_encoder->dp.link_nr > nv_encoder->dcb->dpconf.link_nr)
+ 		nv_encoder->dp.link_nr = nv_encoder->dcb->dpconf.link_nr;
+ 
++	nv_encoder->dp.enhanced_frame = (dpcd[2] & DP_ENHANCED_FRAME_CAP);
++
+ 	return true;
+ }
+ 
+@@ -487,7 +527,8 @@ nouveau_dp_auxch(struct nouveau_i2c_chan *auxch, int cmd, int addr,
  		nv_wr32(dev, NV50_AUXCH_CTRL(index), ctrl | 0x80000000);
  		nv_wr32(dev, NV50_AUXCH_CTRL(index), ctrl);
  		nv_wr32(dev, NV50_AUXCH_CTRL(index), ctrl | 0x00010000);
@@ -4141,7 +4407,7 @@ index deeb21c..89ca1f6 100644
  			NV_ERROR(dev, "expected bit 16 == 0, got 0x%08x\n",
  				 nv_rd32(dev, NV50_AUXCH_CTRL(index)));
  			ret = -EBUSY;
-@@ -535,47 +573,64 @@ out:
+@@ -535,47 +576,64 @@ out:
  	return ret ? ret : (stat & NV50_AUXCH_STAT_REPLY);
  }
  
@@ -4242,7 +4508,7 @@ index deeb21c..89ca1f6 100644
 +	.functionality = nouveau_dp_i2c_func
 +};
 diff --git a/drivers/gpu/drm/nouveau/nouveau_drv.c b/drivers/gpu/drm/nouveau/nouveau_drv.c
-index 2737704..946748a 100644
+index 2737704..ee2442f 100644
 --- a/drivers/gpu/drm/nouveau/nouveau_drv.c
 +++ b/drivers/gpu/drm/nouveau/nouveau_drv.c
 @@ -35,13 +35,9 @@
@@ -4271,7 +4537,18 @@ index 2737704..946748a 100644
  module_param_named(vram_notify, nouveau_vram_notify, int, 0400);
  
  MODULE_PARM_DESC(duallink, "Allow dual-link TMDS (>=GeForce 8)");
-@@ -155,9 +151,6 @@ nouveau_pci_suspend(struct pci_dev *pdev, pm_message_t pm_state)
+@@ -83,6 +79,10 @@ MODULE_PARM_DESC(nofbaccel, "Disable fbcon acceleration");
+ int nouveau_nofbaccel = 0;
+ module_param_named(nofbaccel, nouveau_nofbaccel, int, 0400);
+ 
++MODULE_PARM_DESC(force_post, "Force POST");
++int nouveau_force_post = 0;
++module_param_named(force_post, nouveau_force_post, int, 0400);
++
+ MODULE_PARM_DESC(override_conntype, "Ignore DCB connector type");
+ int nouveau_override_conntype = 0;
+ module_param_named(override_conntype, nouveau_override_conntype, int, 0400);
+@@ -155,9 +155,6 @@ nouveau_pci_suspend(struct pci_dev *pdev, pm_message_t pm_state)
  	struct drm_crtc *crtc;
  	int ret, i;
  
@@ -4281,7 +4558,7 @@ index 2737704..946748a 100644
  	if (pm_state.event == PM_EVENT_PRETHAW)
  		return 0;
  
-@@ -257,9 +250,6 @@ nouveau_pci_resume(struct pci_dev *pdev)
+@@ -257,9 +254,6 @@ nouveau_pci_resume(struct pci_dev *pdev)
  	struct drm_crtc *crtc;
  	int ret, i;
  
@@ -4291,7 +4568,7 @@ index 2737704..946748a 100644
  	nouveau_fbcon_save_disable_accel(dev);
  
  	NV_INFO(dev, "We're back, enabling device...\n");
-@@ -269,6 +259,13 @@ nouveau_pci_resume(struct pci_dev *pdev)
+@@ -269,6 +263,13 @@ nouveau_pci_resume(struct pci_dev *pdev)
  		return -1;
  	pci_set_master(dev->pdev);
  
@@ -4305,7 +4582,7 @@ index 2737704..946748a 100644
  	NV_INFO(dev, "POSTing device...\n");
  	ret = nouveau_run_vbios_init(dev);
  	if (ret)
-@@ -323,7 +320,6 @@ nouveau_pci_resume(struct pci_dev *pdev)
+@@ -323,7 +324,6 @@ nouveau_pci_resume(struct pci_dev *pdev)
  
  	list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
  		struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc);
@@ -4313,7 +4590,7 @@ index 2737704..946748a 100644
  
  		ret = nouveau_bo_pin(nv_crtc->cursor.nvbo, TTM_PL_FLAG_VRAM);
  		if (!ret)
-@@ -332,11 +328,7 @@ nouveau_pci_resume(struct pci_dev *pdev)
+@@ -332,11 +332,7 @@ nouveau_pci_resume(struct pci_dev *pdev)
  			NV_ERROR(dev, "Could not pin/map cursor.\n");
  	}
  
@@ -4326,7 +4603,7 @@ index 2737704..946748a 100644
  
  	list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
  		struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc);
-@@ -371,7 +363,8 @@ nouveau_pci_resume(struct pci_dev *pdev)
+@@ -371,7 +367,8 @@ nouveau_pci_resume(struct pci_dev *pdev)
  static struct drm_driver driver = {
  	.driver_features =
  		DRIVER_USE_AGP | DRIVER_PCI_DMA | DRIVER_SG |
@@ -4336,7 +4613,7 @@ index 2737704..946748a 100644
  	.load = nouveau_load,
  	.firstopen = nouveau_firstopen,
  	.lastclose = nouveau_lastclose,
-@@ -438,16 +431,18 @@ static int __init nouveau_init(void)
+@@ -438,16 +435,18 @@ static int __init nouveau_init(void)
  			nouveau_modeset = 1;
  	}
  
@@ -4360,7 +4637,7 @@ index 2737704..946748a 100644
  	nouveau_unregister_dsm_handler();
  }
 diff --git a/drivers/gpu/drm/nouveau/nouveau_drv.h b/drivers/gpu/drm/nouveau/nouveau_drv.h
-index c697191..228c8cd 100644
+index 8be2f59..be53e92 100644
 --- a/drivers/gpu/drm/nouveau/nouveau_drv.h
 +++ b/drivers/gpu/drm/nouveau/nouveau_drv.h
 @@ -123,14 +123,6 @@ nvbo_kmap_obj_iovirtual(struct nouveau_bo *nvbo)
@@ -4701,7 +4978,7 @@ index c697191..228c8cd 100644
  extern int nouveau_duallink;
  extern int nouveau_uscript_lvds;
  extern int nouveau_uscript_tmds;
-@@ -682,7 +666,6 @@ extern int nouveau_tv_disable;
+@@ -682,10 +666,10 @@ extern int nouveau_tv_disable;
  extern char *nouveau_tv_norm;
  extern int nouveau_reg_debug;
  extern char *nouveau_vbios;
@@ -4709,7 +4986,11 @@ index c697191..228c8cd 100644
  extern int nouveau_ignorelid;
  extern int nouveau_nofbaccel;
  extern int nouveau_noaccel;
-@@ -707,17 +690,12 @@ extern bool nouveau_wait_for_idle(struct drm_device *);
++extern int nouveau_force_post;
+ extern int nouveau_override_conntype;
+ 
+ extern int nouveau_pci_suspend(struct pci_dev *pdev, pm_message_t pm_state);
+@@ -707,17 +691,12 @@ extern bool nouveau_wait_for_idle(struct drm_device *);
  extern int  nouveau_card_init(struct drm_device *);
  
  /* nouveau_mem.c */
@@ -4732,7 +5013,7 @@ index c697191..228c8cd 100644
  extern void nouveau_mem_close(struct drm_device *);
  extern struct nouveau_tile_reg *nv10_mem_set_tiling(struct drm_device *dev,
  						    uint32_t addr,
-@@ -759,7 +737,6 @@ extern void nouveau_channel_free(struct nouveau_channel *);
+@@ -759,7 +738,6 @@ extern void nouveau_channel_free(struct nouveau_channel *);
  extern int  nouveau_gpuobj_early_init(struct drm_device *);
  extern int  nouveau_gpuobj_init(struct drm_device *);
  extern void nouveau_gpuobj_takedown(struct drm_device *);
@@ -4740,7 +5021,7 @@ index c697191..228c8cd 100644
  extern int  nouveau_gpuobj_suspend(struct drm_device *dev);
  extern void nouveau_gpuobj_suspend_cleanup(struct drm_device *dev);
  extern void nouveau_gpuobj_resume(struct drm_device *dev);
-@@ -769,24 +746,11 @@ extern void nouveau_gpuobj_channel_takedown(struct nouveau_channel *);
+@@ -769,24 +747,11 @@ extern void nouveau_gpuobj_channel_takedown(struct nouveau_channel *);
  extern int nouveau_gpuobj_new(struct drm_device *, struct nouveau_channel *,
  			      uint32_t size, int align, uint32_t flags,
  			      struct nouveau_gpuobj **);
@@ -4770,7 +5051,7 @@ index c697191..228c8cd 100644
  extern int nouveau_gpuobj_dma_new(struct nouveau_channel *, int class,
  				  uint64_t offset, uint64_t size, int access,
  				  int target, struct nouveau_gpuobj **);
-@@ -857,11 +821,13 @@ void nouveau_register_dsm_handler(void);
+@@ -857,11 +822,13 @@ void nouveau_register_dsm_handler(void);
  void nouveau_unregister_dsm_handler(void);
  int nouveau_acpi_get_bios_chunk(uint8_t *bios, int offset, int len);
  bool nouveau_acpi_rom_supported(struct pci_dev *pdev);
@@ -4784,7 +5065,7 @@ index c697191..228c8cd 100644
  #endif
  
  /* nouveau_backlight.c */
-@@ -924,22 +890,29 @@ extern void nv10_fb_takedown(struct drm_device *);
+@@ -924,22 +891,29 @@ extern void nv10_fb_takedown(struct drm_device *);
  extern void nv10_fb_set_region_tiling(struct drm_device *, int, uint32_t,
  				      uint32_t, uint32_t);
  
@@ -4816,7 +5097,7 @@ index c697191..228c8cd 100644
  extern bool nv04_fifo_cache_pull(struct drm_device *, bool);
  extern int  nv04_fifo_channel_id(struct drm_device *);
  extern int  nv04_fifo_create_context(struct nouveau_channel *);
-@@ -971,6 +944,19 @@ extern void nv50_fifo_destroy_context(struct nouveau_channel *);
+@@ -971,6 +945,19 @@ extern void nv50_fifo_destroy_context(struct nouveau_channel *);
  extern int  nv50_fifo_load_context(struct nouveau_channel *);
  extern int  nv50_fifo_unload_context(struct drm_device *);
  
@@ -4836,7 +5117,7 @@ index c697191..228c8cd 100644
  /* nv04_graph.c */
  extern struct nouveau_pgraph_object_class nv04_graph_grclass[];
  extern int  nv04_graph_init(struct drm_device *);
-@@ -1035,11 +1021,15 @@ extern int  nv50_graph_unload_context(struct drm_device *);
+@@ -1035,11 +1022,15 @@ extern int  nv50_graph_unload_context(struct drm_device *);
  extern void nv50_graph_context_switch(struct drm_device *);
  extern int  nv50_grctx_init(struct nouveau_grctx *);
  
@@ -4857,7 +5138,7 @@ index c697191..228c8cd 100644
  
  /* nv04_instmem.c */
  extern int  nv04_instmem_init(struct drm_device *);
-@@ -1051,8 +1041,7 @@ extern int  nv04_instmem_populate(struct drm_device *, struct nouveau_gpuobj *,
+@@ -1051,8 +1042,7 @@ extern int  nv04_instmem_populate(struct drm_device *, struct nouveau_gpuobj *,
  extern void nv04_instmem_clear(struct drm_device *, struct nouveau_gpuobj *);
  extern int  nv04_instmem_bind(struct drm_device *, struct nouveau_gpuobj *);
  extern int  nv04_instmem_unbind(struct drm_device *, struct nouveau_gpuobj *);
@@ -4867,7 +5148,7 @@ index c697191..228c8cd 100644
  
  /* nv50_instmem.c */
  extern int  nv50_instmem_init(struct drm_device *);
-@@ -1064,8 +1053,21 @@ extern int  nv50_instmem_populate(struct drm_device *, struct nouveau_gpuobj *,
+@@ -1064,8 +1054,21 @@ extern int  nv50_instmem_populate(struct drm_device *, struct nouveau_gpuobj *,
  extern void nv50_instmem_clear(struct drm_device *, struct nouveau_gpuobj *);
  extern int  nv50_instmem_bind(struct drm_device *, struct nouveau_gpuobj *);
  extern int  nv50_instmem_unbind(struct drm_device *, struct nouveau_gpuobj *);
@@ -4891,7 +5172,7 @@ index c697191..228c8cd 100644
  
  /* nv04_mc.c */
  extern int  nv04_mc_init(struct drm_device *);
-@@ -1088,13 +1090,14 @@ extern long nouveau_compat_ioctl(struct file *file, unsigned int cmd,
+@@ -1088,13 +1091,14 @@ extern long nouveau_compat_ioctl(struct file *file, unsigned int cmd,
  				 unsigned long arg);
  
  /* nv04_dac.c */
@@ -4908,7 +5189,7 @@ index c697191..228c8cd 100644
  extern int nv04_dfp_get_bound_head(struct drm_device *dev, struct dcb_entry *dcbent);
  extern void nv04_dfp_bind_head(struct drm_device *dev, struct dcb_entry *dcbent,
  			       int head, bool dl);
-@@ -1103,15 +1106,17 @@ extern void nv04_dfp_update_fp_control(struct drm_encoder *encoder, int mode);
+@@ -1103,15 +1107,17 @@ extern void nv04_dfp_update_fp_control(struct drm_encoder *encoder, int mode);
  
  /* nv04_tv.c */
  extern int nv04_tv_identify(struct drm_device *dev, int i2c_index);
@@ -4929,7 +5210,7 @@ index c697191..228c8cd 100644
  
  /* nv04_crtc.c */
  extern int nv04_crtc_create(struct drm_device *, int index);
-@@ -1147,7 +1152,6 @@ extern int nouveau_fence_wait(void *obj, void *arg, bool lazy, bool intr);
+@@ -1148,7 +1154,6 @@ extern int nouveau_fence_wait(void *obj, void *arg, bool lazy, bool intr);
  extern int nouveau_fence_flush(void *obj, void *arg);
  extern void nouveau_fence_unref(void **obj);
  extern void *nouveau_fence_ref(void *obj);
@@ -4937,7 +5218,7 @@ index c697191..228c8cd 100644
  
  /* nouveau_gem.c */
  extern int nouveau_gem_new(struct drm_device *, struct nouveau_channel *,
-@@ -1167,13 +1171,15 @@ extern int nouveau_gem_ioctl_cpu_fini(struct drm_device *, void *,
+@@ -1168,13 +1173,15 @@ extern int nouveau_gem_ioctl_cpu_fini(struct drm_device *, void *,
  extern int nouveau_gem_ioctl_info(struct drm_device *, void *,
  				  struct drm_file *);
  
@@ -4956,7 +5237,7 @@ index c697191..228c8cd 100644
  
  /* nv50_calc. */
  int nv50_calc_pll(struct drm_device *, struct pll_lims *, int clk,
-@@ -1220,6 +1226,13 @@ static inline void nv_wr32(struct drm_device *dev, unsigned reg, u32 val)
+@@ -1221,6 +1228,13 @@ static inline void nv_wr32(struct drm_device *dev, unsigned reg, u32 val)
  	iowrite32_native(val, dev_priv->mmio + reg);
  }
  
@@ -4970,7 +5251,7 @@ index c697191..228c8cd 100644
  static inline u8 nv_rd08(struct drm_device *dev, unsigned reg)
  {
  	struct drm_nouveau_private *dev_priv = dev->dev_private;
-@@ -1232,7 +1245,7 @@ static inline void nv_wr08(struct drm_device *dev, unsigned reg, u8 val)
+@@ -1233,7 +1247,7 @@ static inline void nv_wr08(struct drm_device *dev, unsigned reg, u8 val)
  	iowrite8(val, dev_priv->mmio + reg);
  }
  
@@ -4979,7 +5260,7 @@ index c697191..228c8cd 100644
  	nouveau_wait_until(dev, 2000000000ULL, (reg), (mask), (val))
  
  /* PRAMIN access */
-@@ -1249,17 +1262,8 @@ static inline void nv_wi32(struct drm_device *dev, unsigned offset, u32 val)
+@@ -1250,17 +1264,8 @@ static inline void nv_wi32(struct drm_device *dev, unsigned offset, u32 val)
  }
  
  /* object access */
@@ -4999,7 +5280,7 @@ index c697191..228c8cd 100644
  
  /*
   * Logging
-@@ -1346,6 +1350,15 @@ nv_two_reg_pll(struct drm_device *dev)
+@@ -1347,6 +1352,15 @@ nv_two_reg_pll(struct drm_device *dev)
  	return false;
  }
  
@@ -5016,7 +5297,7 @@ index c697191..228c8cd 100644
  #define NV_SW_DMA_SEMAPHORE                                          0x00000060
  #define NV_SW_SEMAPHORE_OFFSET                                       0x00000064
 diff --git a/drivers/gpu/drm/nouveau/nouveau_encoder.h b/drivers/gpu/drm/nouveau/nouveau_encoder.h
-index e1df820..7c82d68 100644
+index e1df820..ae69b61 100644
 --- a/drivers/gpu/drm/nouveau/nouveau_encoder.h
 +++ b/drivers/gpu/drm/nouveau/nouveau_encoder.h
 @@ -38,13 +38,15 @@ struct nouveau_encoder {
@@ -5037,7 +5318,15 @@ index e1df820..7c82d68 100644
  	union {
  		struct {
  			int mc_unknown;
-@@ -69,10 +71,16 @@ static inline struct drm_encoder *to_drm_encoder(struct nouveau_encoder *enc)
+@@ -53,6 +55,7 @@ struct nouveau_encoder {
+ 			int dpcd_version;
+ 			int link_nr;
+ 			int link_bw;
++			bool enhanced_frame;
+ 		} dp;
+ 	};
+ };
+@@ -69,10 +72,16 @@ static inline struct drm_encoder *to_drm_encoder(struct nouveau_encoder *enc)
  	return &enc->base.base;
  }
  
@@ -5198,7 +5487,7 @@ index faddf53..6b208ff 100644
  }
  
 diff --git a/drivers/gpu/drm/nouveau/nouveau_gem.c b/drivers/gpu/drm/nouveau/nouveau_gem.c
-index 69c76cf..62ac673 100644
+index 6937d53..613f878 100644
 --- a/drivers/gpu/drm/nouveau/nouveau_gem.c
 +++ b/drivers/gpu/drm/nouveau/nouveau_gem.c
 @@ -137,8 +137,6 @@ nouveau_gem_ioctl_new(struct drm_device *dev, void *data,
@@ -5210,7 +5499,7 @@ index 69c76cf..62ac673 100644
  	if (unlikely(dev_priv->ttm.bdev.dev_mapping == NULL))
  		dev_priv->ttm.bdev.dev_mapping = dev_priv->dev->dev_mapping;
  
-@@ -577,10 +575,9 @@ nouveau_gem_ioctl_pushbuf(struct drm_device *dev, void *data,
+@@ -578,10 +576,9 @@ nouveau_gem_ioctl_pushbuf(struct drm_device *dev, void *data,
  	struct drm_nouveau_gem_pushbuf_bo *bo;
  	struct nouveau_channel *chan;
  	struct validate_op op;
@@ -5222,7 +5511,7 @@ index 69c76cf..62ac673 100644
  	NOUVEAU_GET_USER_CHANNEL_WITH_RETURN(req->channel, file_priv, chan);
  
  	req->vram_available = dev_priv->fb_aper_free;
-@@ -650,7 +647,7 @@ nouveau_gem_ioctl_pushbuf(struct drm_device *dev, void *data,
+@@ -666,7 +663,7 @@ nouveau_gem_ioctl_pushbuf(struct drm_device *dev, void *data,
  				      push[i].length);
  		}
  	} else
@@ -5231,7 +5520,7 @@ index 69c76cf..62ac673 100644
  		ret = RING_SPACE(chan, req->nr_push * 2);
  		if (ret) {
  			NV_ERROR(dev, "cal_space: %d\n", ret);
-@@ -725,7 +722,7 @@ out_next:
+@@ -741,7 +738,7 @@ out_next:
  		req->suffix0 = 0x00000000;
  		req->suffix1 = 0x00000000;
  	} else
@@ -5240,7 +5529,7 @@ index 69c76cf..62ac673 100644
  		req->suffix0 = 0x00020000;
  		req->suffix1 = 0x00000000;
  	} else {
-@@ -760,8 +757,6 @@ nouveau_gem_ioctl_cpu_prep(struct drm_device *dev, void *data,
+@@ -776,8 +773,6 @@ nouveau_gem_ioctl_cpu_prep(struct drm_device *dev, void *data,
  	bool no_wait = !!(req->flags & NOUVEAU_GEM_CPU_PREP_NOWAIT);
  	int ret = -EINVAL;
  
@@ -5249,7 +5538,7 @@ index 69c76cf..62ac673 100644
  	gem = drm_gem_object_lookup(dev, file_priv, req->handle);
  	if (!gem)
  		return ret;
-@@ -800,8 +795,6 @@ nouveau_gem_ioctl_cpu_fini(struct drm_device *dev, void *data,
+@@ -816,8 +811,6 @@ nouveau_gem_ioctl_cpu_fini(struct drm_device *dev, void *data,
  	struct nouveau_bo *nvbo;
  	int ret = -EINVAL;
  
@@ -5258,7 +5547,7 @@ index 69c76cf..62ac673 100644
  	gem = drm_gem_object_lookup(dev, file_priv, req->handle);
  	if (!gem)
  		return ret;
-@@ -827,8 +820,6 @@ nouveau_gem_ioctl_info(struct drm_device *dev, void *data,
+@@ -843,8 +836,6 @@ nouveau_gem_ioctl_info(struct drm_device *dev, void *data,
  	struct drm_gem_object *gem;
  	int ret;
  
@@ -5447,9 +5736,18 @@ index 5d39c4c..4a8ad13 100644
  #endif
  
 diff --git a/drivers/gpu/drm/nouveau/nouveau_hw.c b/drivers/gpu/drm/nouveau/nouveau_hw.c
-index 7855b35..f8ec49b 100644
+index 7855b35..cb13134 100644
 --- a/drivers/gpu/drm/nouveau/nouveau_hw.c
 +++ b/drivers/gpu/drm/nouveau/nouveau_hw.c
+@@ -305,7 +305,7 @@ setPLL_double_lowregs(struct drm_device *dev, uint32_t NMNMreg,
+ 	bool mpll = Preg == 0x4020;
+ 	uint32_t oldPval = nvReadMC(dev, Preg);
+ 	uint32_t NMNM = pv->NM2 << 16 | pv->NM1;
+-	uint32_t Pval = (oldPval & (mpll ? ~(0x11 << 16) : ~(1 << 16))) |
++	uint32_t Pval = (oldPval & (mpll ? ~(0x77 << 16) : ~(7 << 16))) |
+ 			0xc << 28 | pv->log2P << 16;
+ 	uint32_t saved4600 = 0;
+ 	/* some cards have different maskc040s */
 @@ -865,8 +865,13 @@ nv_save_state_ext(struct drm_device *dev, int head,
  	rd_cio_state(dev, head, regp, NV_CIO_CRE_FF_INDEX);
  	rd_cio_state(dev, head, regp, NV_CIO_CRE_FFLWM__INDEX);
@@ -9522,7 +9820,7 @@ index eba687f..291a4cb 100644
  		crtc_wr_cio_state(crtc, regp, NV_CIO_CRE_47);
  	}
 diff --git a/drivers/gpu/drm/nouveau/nv04_dac.c b/drivers/gpu/drm/nouveau/nv04_dac.c
-index 1cb19e3..9cc560c 100644
+index 1cb19e3..ba6423f 100644
 --- a/drivers/gpu/drm/nouveau/nv04_dac.c
 +++ b/drivers/gpu/drm/nouveau/nv04_dac.c
 @@ -220,6 +220,7 @@ uint32_t nv17_dac_sample_load(struct drm_encoder *encoder)
@@ -9609,7 +9907,14 @@ index 1cb19e3..9cc560c 100644
  	return true;
  }
  
-@@ -344,15 +352,9 @@ static void nv04_dac_prepare(struct drm_encoder *encoder)
+@@ -337,22 +345,13 @@ static void nv04_dac_prepare(struct drm_encoder *encoder)
+ {
+ 	struct drm_encoder_helper_funcs *helper = encoder->helper_private;
+ 	struct drm_device *dev = encoder->dev;
+-	struct drm_nouveau_private *dev_priv = dev->dev_private;
+ 	int head = nouveau_crtc(encoder->crtc)->index;
+-	struct nv04_crtc_reg *crtcstate = dev_priv->mode_reg.crtc_reg;
+ 
  	helper->dpms(encoder, DRM_MODE_DPMS_OFF);
  
  	nv04_dfp_disable(dev, head);
@@ -9619,14 +9924,13 @@ index 1cb19e3..9cc560c 100644
 -	 */
 -	if (!(crtcstate[head].CRTC[NV_CIO_CRE_LCD__INDEX] & 0x44))
 -		crtcstate[head].CRTC[NV_CIO_CRE_LCD__INDEX] = 0;
-+	crtcstate[head].CRTC[NV_CIO_CRE_LCD__INDEX] = 0;
  }
  
 -
  static void nv04_dac_mode_set(struct drm_encoder *encoder,
  			      struct drm_display_mode *mode,
  			      struct drm_display_mode *adjusted_mode)
-@@ -428,6 +430,17 @@ void nv04_dac_update_dacclk(struct drm_encoder *encoder, bool enable)
+@@ -428,6 +427,17 @@ void nv04_dac_update_dacclk(struct drm_encoder *encoder, bool enable)
  	}
  }
  
@@ -9644,7 +9948,7 @@ index 1cb19e3..9cc560c 100644
  static void nv04_dac_dpms(struct drm_encoder *encoder, int mode)
  {
  	struct drm_device *dev = encoder->dev;
-@@ -501,11 +514,13 @@ static const struct drm_encoder_funcs nv04_dac_funcs = {
+@@ -501,11 +511,13 @@ static const struct drm_encoder_funcs nv04_dac_funcs = {
  	.destroy = nv04_dac_destroy,
  };
  
@@ -9660,7 +9964,7 @@ index 1cb19e3..9cc560c 100644
  
  	nv_encoder = kzalloc(sizeof(*nv_encoder), GFP_KERNEL);
  	if (!nv_encoder)
-@@ -527,5 +542,6 @@ int nv04_dac_create(struct drm_device *dev, struct dcb_entry *entry)
+@@ -527,5 +539,6 @@ int nv04_dac_create(struct drm_device *dev, struct dcb_entry *entry)
  	encoder->possible_crtcs = entry->heads;
  	encoder->possible_clones = 0;
  
@@ -9668,7 +9972,7 @@ index 1cb19e3..9cc560c 100644
  	return 0;
  }
 diff --git a/drivers/gpu/drm/nouveau/nv04_dfp.c b/drivers/gpu/drm/nouveau/nv04_dfp.c
-index 41634d4..e331b4f 100644
+index 41634d4..762d9f2 100644
 --- a/drivers/gpu/drm/nouveau/nv04_dfp.c
 +++ b/drivers/gpu/drm/nouveau/nv04_dfp.c
 @@ -34,6 +34,8 @@
@@ -9680,7 +9984,16 @@ index 41634d4..e331b4f 100644
  #define FP_TG_CONTROL_ON  (NV_PRAMDAC_FP_TG_CONTROL_DISPEN_POS |	\
  			   NV_PRAMDAC_FP_TG_CONTROL_HSYNC_POS |		\
  			   NV_PRAMDAC_FP_TG_CONTROL_VSYNC_POS)
-@@ -144,6 +146,36 @@ void nv04_dfp_update_fp_control(struct drm_encoder *encoder, int mode)
+@@ -102,6 +104,8 @@ void nv04_dfp_disable(struct drm_device *dev, int head)
+ 	}
+ 	/* don't inadvertently turn it on when state written later */
+ 	crtcstate[head].fp_control = FP_TG_CONTROL_OFF;
++	crtcstate[head].CRTC[NV_CIO_CRE_LCD__INDEX] &=
++		~NV_CIO_CRE_LCD_ROUTE_MASK;
+ }
+ 
+ void nv04_dfp_update_fp_control(struct drm_encoder *encoder, int mode)
+@@ -144,6 +148,36 @@ void nv04_dfp_update_fp_control(struct drm_encoder *encoder, int mode)
  	}
  }
  
@@ -9717,7 +10030,7 @@ index 41634d4..e331b4f 100644
  static bool nv04_dfp_mode_fixup(struct drm_encoder *encoder,
  				struct drm_display_mode *mode,
  				struct drm_display_mode *adjusted_mode)
-@@ -221,26 +253,21 @@ static void nv04_dfp_prepare(struct drm_encoder *encoder)
+@@ -221,26 +255,21 @@ static void nv04_dfp_prepare(struct drm_encoder *encoder)
  
  	nv04_dfp_prepare_sel_clk(dev, nv_encoder, head);
  
@@ -9741,7 +10054,7 @@ index 41634d4..e331b4f 100644
 -						       NV_CIO_CRE_LCD__INDEX,
 -						       *cr_lcd_oth);
 -				}
-+	*cr_lcd = 0x3;
++	*cr_lcd = (*cr_lcd & ~NV_CIO_CRE_LCD_ROUTE_MASK) | 0x3;
 +
 +	if (nv_two_heads(dev)) {
 +		if (nv_encoder->dcb->location == DCB_LOC_ON_CHIP)
@@ -9759,7 +10072,7 @@ index 41634d4..e331b4f 100644
  			}
  		}
  	}
-@@ -412,10 +439,7 @@ static void nv04_dfp_commit(struct drm_encoder *encoder)
+@@ -412,10 +441,7 @@ static void nv04_dfp_commit(struct drm_encoder *encoder)
  	struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder);
  	struct dcb_entry *dcbe = nv_encoder->dcb;
  	int head = nouveau_crtc(encoder->crtc)->index;
@@ -9771,7 +10084,7 @@ index 41634d4..e331b4f 100644
  
  	if (dcbe->type == OUTPUT_TMDS)
  		run_tmds_table(dev, dcbe, head, nv_encoder->mode.clock);
-@@ -433,6 +457,12 @@ static void nv04_dfp_commit(struct drm_encoder *encoder)
+@@ -433,6 +459,12 @@ static void nv04_dfp_commit(struct drm_encoder *encoder)
  	else
  		NVWriteRAMDAC(dev, 0, NV_PRAMDAC_TEST_CONTROL + nv04_dac_output_offset(encoder), 0x00100000);
  
@@ -9784,7 +10097,7 @@ index 41634d4..e331b4f 100644
  	helper->dpms(encoder, DRM_MODE_DPMS_ON);
  
  	NV_INFO(dev, "Output %s is running on CRTC %d using output %c\n",
-@@ -440,6 +470,27 @@ static void nv04_dfp_commit(struct drm_encoder *encoder)
+@@ -440,6 +472,27 @@ static void nv04_dfp_commit(struct drm_encoder *encoder)
  		nv_crtc->index, '@' + ffs(nv_encoder->dcb->or));
  }
  
@@ -9812,7 +10125,7 @@ index 41634d4..e331b4f 100644
  static inline bool is_powersaving_dpms(int mode)
  {
  	return (mode != DRM_MODE_DPMS_ON);
-@@ -487,6 +538,7 @@ static void nv04_lvds_dpms(struct drm_encoder *encoder, int mode)
+@@ -487,6 +540,7 @@ static void nv04_lvds_dpms(struct drm_encoder *encoder, int mode)
  					 LVDS_PANEL_OFF, 0);
  	}
  
@@ -9820,7 +10133,7 @@ index 41634d4..e331b4f 100644
  	nv04_dfp_update_fp_control(encoder, mode);
  
  	if (mode == DRM_MODE_DPMS_ON)
-@@ -510,6 +562,7 @@ static void nv04_tmds_dpms(struct drm_encoder *encoder, int mode)
+@@ -510,6 +564,7 @@ static void nv04_tmds_dpms(struct drm_encoder *encoder, int mode)
  	NV_INFO(dev, "Setting dpms mode %d on tmds encoder (output %d)\n",
  		     mode, nv_encoder->dcb->index);
  
@@ -9828,7 +10141,7 @@ index 41634d4..e331b4f 100644
  	nv04_dfp_update_fp_control(encoder, mode);
  }
  
-@@ -554,10 +607,42 @@ static void nv04_dfp_destroy(struct drm_encoder *encoder)
+@@ -554,10 +609,42 @@ static void nv04_dfp_destroy(struct drm_encoder *encoder)
  
  	NV_DEBUG_KMS(encoder->dev, "\n");
  
@@ -9871,7 +10184,7 @@ index 41634d4..e331b4f 100644
  static const struct drm_encoder_helper_funcs nv04_lvds_helper_funcs = {
  	.dpms = nv04_lvds_dpms,
  	.save = nv04_dfp_save,
-@@ -584,11 +669,12 @@ static const struct drm_encoder_funcs nv04_dfp_funcs = {
+@@ -584,11 +671,12 @@ static const struct drm_encoder_funcs nv04_dfp_funcs = {
  	.destroy = nv04_dfp_destroy,
  };
  
@@ -9886,7 +10199,7 @@ index 41634d4..e331b4f 100644
  	int type;
  
  	switch (entry->type) {
-@@ -613,11 +699,16 @@ int nv04_dfp_create(struct drm_device *dev, struct dcb_entry *entry)
+@@ -613,11 +701,16 @@ int nv04_dfp_create(struct drm_device *dev, struct dcb_entry *entry)
  	nv_encoder->dcb = entry;
  	nv_encoder->or = ffs(entry->or) - 1;
  
@@ -10592,7 +10905,7 @@ index 617ed1e..2af43a1 100644
  }
  
 diff --git a/drivers/gpu/drm/nouveau/nv04_tv.c b/drivers/gpu/drm/nouveau/nv04_tv.c
-index c4e3404..0b5d012 100644
+index c4e3404..9915a3b 100644
 --- a/drivers/gpu/drm/nouveau/nv04_tv.c
 +++ b/drivers/gpu/drm/nouveau/nv04_tv.c
 @@ -34,69 +34,26 @@
@@ -10682,7 +10995,22 @@ index c4e3404..0b5d012 100644
  }
  
  static void nv04_tv_bind(struct drm_device *dev, int head, bool bind)
-@@ -195,7 +152,7 @@ static void nv04_tv_mode_set(struct drm_encoder *encoder,
+@@ -142,12 +99,10 @@ static void nv04_tv_bind(struct drm_device *dev, int head, bool bind)
+ 
+ 	state->tv_setup = 0;
+ 
+-	if (bind) {
+-		state->CRTC[NV_CIO_CRE_LCD__INDEX] = 0;
++	if (bind)
+ 		state->CRTC[NV_CIO_CRE_49] |= 0x10;
+-	} else {
++	else
+ 		state->CRTC[NV_CIO_CRE_49] &= ~0x10;
+-	}
+ 
+ 	NVWriteVgaCrtc(dev, head, NV_CIO_CRE_LCD__INDEX,
+ 		       state->CRTC[NV_CIO_CRE_LCD__INDEX]);
+@@ -195,7 +150,7 @@ static void nv04_tv_mode_set(struct drm_encoder *encoder,
  	regp->tv_vskew = 1;
  	regp->tv_vsync_delay = 1;
  
@@ -10691,7 +11019,7 @@ index c4e3404..0b5d012 100644
  }
  
  static void nv04_tv_commit(struct drm_encoder *encoder)
-@@ -214,30 +171,31 @@ static void nv04_tv_commit(struct drm_encoder *encoder)
+@@ -214,30 +169,31 @@ static void nv04_tv_commit(struct drm_encoder *encoder)
  
  static void nv04_tv_destroy(struct drm_encoder *encoder)
  {
@@ -10737,7 +11065,7 @@ index c4e3404..0b5d012 100644
  	if (type < 0)
  		return type;
  
-@@ -246,40 +204,31 @@ int nv04_tv_create(struct drm_device *dev, struct dcb_entry *entry)
+@@ -246,40 +202,31 @@ int nv04_tv_create(struct drm_device *dev, struct dcb_entry *entry)
  	if (!nv_encoder)
  		return -ENOMEM;
  
@@ -10789,7 +11117,7 @@ index c4e3404..0b5d012 100644
  
  	*hfuncs = (struct drm_encoder_helper_funcs) {
  		.dpms = nv04_tv_dpms,
-@@ -292,14 +241,16 @@ int nv04_tv_create(struct drm_device *dev, struct dcb_entry *entry)
+@@ -292,14 +239,16 @@ int nv04_tv_create(struct drm_device *dev, struct dcb_entry *entry)
  		.detect = sfuncs->detect,
  	};
  
@@ -11017,7 +11345,7 @@ index 0000000..007fc29
 +	return 0;
 +}
 diff --git a/drivers/gpu/drm/nouveau/nv10_graph.c b/drivers/gpu/drm/nouveau/nv10_graph.c
-index fcf2cdd..b2f6a57 100644
+index fcf2cdd..8e68c97 100644
 --- a/drivers/gpu/drm/nouveau/nv10_graph.c
 +++ b/drivers/gpu/drm/nouveau/nv10_graph.c
 @@ -43,51 +43,51 @@ struct pipe_state {
@@ -11205,6 +11533,15 @@ index fcf2cdd..b2f6a57 100644
  
  	nv_wr32(dev, NV10_PGRAPH_CTX_CONTROL, 0x10010100);
  	tmp = nv_rd32(dev, NV10_PGRAPH_CTX_USER);
+@@ -729,7 +803,7 @@ nv10_graph_context_switch(struct drm_device *dev)
+ 	/* Load context for next channel */
+ 	chid = (nv_rd32(dev, NV04_PGRAPH_TRAPPED_ADDR) >> 20) & 0x1f;
+ 	chan = dev_priv->fifos[chid];
+-	if (chan)
++	if (chan && chan->pgraph_ctx)
+ 		nv10_graph_load_context(chan);
+ 
+ 	pgraph->fifo_access(dev, true);
 @@ -856,11 +930,12 @@ int nv10_graph_init(struct drm_device *dev)
  	for (i = 0; i < NV10_PFB_TILE__SIZE; i++)
  		nv10_graph_set_region_tiling(dev, i, 0, 0, 0);
@@ -11322,7 +11659,7 @@ index 2e58c33..0000000
 -	return 0;
 -}
 diff --git a/drivers/gpu/drm/nouveau/nv17_tv.c b/drivers/gpu/drm/nouveau/nv17_tv.c
-index 74c8803..a3b8861 100644
+index 74c8803..28119fd 100644
 --- a/drivers/gpu/drm/nouveau/nv17_tv.c
 +++ b/drivers/gpu/drm/nouveau/nv17_tv.c
 @@ -37,6 +37,7 @@ static uint32_t nv42_tv_sample_load(struct drm_encoder *encoder)
@@ -11598,7 +11935,7 @@ index 74c8803..a3b8861 100644
  
  	nv04_dac_update_dacclk(encoder, mode == DRM_MODE_DPMS_ON);
  }
-@@ -373,15 +423,10 @@ static void nv17_tv_prepare(struct drm_encoder *encoder)
+@@ -373,15 +423,8 @@ static void nv17_tv_prepare(struct drm_encoder *encoder)
  
  	}
  
@@ -11612,13 +11949,11 @@ index 74c8803..a3b8861 100644
 -			*cr_lcd = 0;
 -	}
 +	if (tv_norm->kind == CTV_ENC_MODE)
-+		*cr_lcd = 0x1 | (head ? 0x0 : 0x8);
-+	else
-+		*cr_lcd = 0;
++		*cr_lcd |= 0x1 | (head ? 0x0 : 0x8);
  
  	/* Set the DACCLK register */
  	dacclk = (NVReadRAMDAC(dev, 0, dacclk_off) & ~0x30) | 0x1;
-@@ -744,8 +789,10 @@ static struct drm_encoder_funcs nv17_tv_funcs = {
+@@ -744,8 +787,10 @@ static struct drm_encoder_funcs nv17_tv_funcs = {
  	.destroy = nv17_tv_destroy,
  };
  
@@ -11630,7 +11965,7 @@ index 74c8803..a3b8861 100644
  	struct drm_encoder *encoder;
  	struct nv17_tv_encoder *tv_enc = NULL;
  
-@@ -774,5 +821,7 @@ int nv17_tv_create(struct drm_device *dev, struct dcb_entry *entry)
+@@ -774,5 +819,7 @@ int nv17_tv_create(struct drm_device *dev, struct dcb_entry *entry)
  	encoder->possible_crtcs = entry->heads;
  	encoder->possible_clones = 0;
  
@@ -20040,7 +20375,7 @@ index 0000000..152d8e8
 +{
 +}
 diff --git a/drivers/gpu/drm/nouveau/nvreg.h b/drivers/gpu/drm/nouveau/nvreg.h
-index 5998c35..ad64673 100644
+index 5998c35..881f8a5 100644
 --- a/drivers/gpu/drm/nouveau/nvreg.h
 +++ b/drivers/gpu/drm/nouveau/nvreg.h
 @@ -147,28 +147,6 @@
@@ -20072,6 +20407,14 @@ index 5998c35..ad64673 100644
  #define NV_PCRTC_INTR_0					0x00600100
  #	define NV_PCRTC_INTR_0_VBLANK				(1 << 0)
  #define NV_PCRTC_INTR_EN_0				0x00600140
+@@ -285,6 +263,7 @@
+ #		define NV_CIO_CRE_HCUR_ADDR1_ADR	7:2
+ #	define NV_CIO_CRE_LCD__INDEX		0x33
+ #		define NV_CIO_CRE_LCD_LCD_SELECT	0:0
++#		define NV_CIO_CRE_LCD_ROUTE_MASK	0x3b
+ #	define NV_CIO_CRE_DDC0_STATUS__INDEX	0x36
+ #	define NV_CIO_CRE_DDC0_WR__INDEX	0x37
+ #	define NV_CIO_CRE_ILACE__INDEX		0x39	/* interlace */
 -- 
-1.7.2.2
+1.7.3
 
diff --git a/kernel.spec b/kernel.spec
index c95299d..643bc22 100644
--- a/kernel.spec
+++ b/kernel.spec
@@ -48,7 +48,7 @@ Summary: The Linux kernel
 # reset this by hand to 1 (or to 0 and then use rpmdev-bumpspec).
 # scripts/rebase.sh should be made to do that for you, actually.
 #
-%global baserelease 36
+%global baserelease 37
 %global fedora_build %{baserelease}
 
 # base_sublevel is the kernel version we're starting with and patching
@@ -666,7 +666,6 @@ Patch1807: drm-i2c-ch7006-fix.patch
 Patch1810: drm-nouveau-updates.patch
 Patch1811: drm-nouveau-race-fix.patch
 Patch1812: drm-nouveau-nva3-noaccel.patch
-Patch1813: drm-nouveau-ibdma-race.patch
 Patch1819: drm-intel-big-hammer.patch
 # intel drm is all merged upstream
 Patch1824: drm-intel-next.patch
@@ -1303,7 +1302,6 @@ ApplyPatch drm-i2c-ch7006-fix.patch
 ApplyPatch drm-nouveau-updates.patch
 ApplyPatch drm-nouveau-race-fix.patch
 ApplyPatch drm-nouveau-nva3-noaccel.patch
-ApplyPatch drm-nouveau-ibdma-race.patch
 
 ApplyPatch drm-intel-big-hammer.patch
 ApplyOptionalPatch drm-intel-next.patch
@@ -1975,6 +1973,10 @@ fi
 # and build.
 
 %changelog
+* Fri Oct 01 2010 Ben Skeggs <bskeggs at redhat.com> 2.6.35.6-37
+- nouveau: DP fixes, nv50+ corruption fix, display fixes
+- drm-nouveau-ibdma-race.patch: removed, in updates now
+
 * Thu Sep 30 2010 Dave Jones <davej at redhat.com>
 - silence another rcu_reference warning
 


More information about the scm-commits mailing list