rpms/kernel/F-13 drm-nouveau-acpi-edid-fallback.patch, 1.3, 1.4 drm-nouveau-drm-fixed-header.patch, 1.1, 1.2 drm-nouveau-updates.patch, 1.11, 1.12 kernel.spec, 1.2078, 1.2079

Ben Skeggs bskeggs at fedoraproject.org
Fri Jul 2 05:47:02 UTC 2010


Author: bskeggs

Update of /cvs/pkgs/rpms/kernel/F-13
In directory cvs01.phx2.fedoraproject.org:/tmp/cvs-serv27472

Modified Files:
	drm-nouveau-acpi-edid-fallback.patch 
	drm-nouveau-drm-fixed-header.patch drm-nouveau-updates.patch 
	kernel.spec 
Log Message:
* Fri Jul 02 2010 Ben Skeggs <bskeggs at redhat.com> 2.6.33.6-142.rc1
- nouveau: fix connector ordering issues (rhbz#602492)



drm-nouveau-acpi-edid-fallback.patch:
 nouveau_acpi.c      |   81 +++++++++++++++++++++++++++++++++++++++++++++++-----
 nouveau_connector.c |    8 +++++
 nouveau_drv.h       |   20 +++++++++---
 nouveau_state.c     |    6 ---
 4 files changed, 98 insertions(+), 17 deletions(-)

Index: drm-nouveau-acpi-edid-fallback.patch
===================================================================
RCS file: /cvs/pkgs/rpms/kernel/F-13/drm-nouveau-acpi-edid-fallback.patch,v
retrieving revision 1.3
retrieving revision 1.4
diff -u -p -r1.3 -r1.4
--- drm-nouveau-acpi-edid-fallback.patch	15 Apr 2010 22:53:44 -0000	1.3
+++ drm-nouveau-acpi-edid-fallback.patch	2 Jul 2010 05:47:01 -0000	1.4
@@ -1,14 +1,14 @@
-From 84efb21352ab48f43ec824eb53378356c2ce9c63 Mon Sep 17 00:00:00 2001
+From 782468d6a9fb865677c166ceffc2271e1f709cc5 Mon Sep 17 00:00:00 2001
 From: Ben Skeggs <bskeggs at redhat.com>
 Date: Fri, 16 Apr 2010 08:12:34 +1000
-Subject: [PATCH 2/2] drm-nouveau-acpi-edid-fallback
+Subject: [PATCH 2/3] drm-nouveau-acpi-edid-fallback
 
 ---
  drivers/gpu/drm/nouveau/nouveau_acpi.c      |   81 ++++++++++++++++++++++++--
- drivers/gpu/drm/nouveau/nouveau_connector.c |    5 ++
+ drivers/gpu/drm/nouveau/nouveau_connector.c |    8 +++
  drivers/gpu/drm/nouveau/nouveau_drv.h       |   20 +++++--
  drivers/gpu/drm/nouveau/nouveau_state.c     |    5 +-
- 4 files changed, 95 insertions(+), 16 deletions(-)
+ 4 files changed, 98 insertions(+), 16 deletions(-)
 
 diff --git a/drivers/gpu/drm/nouveau/nouveau_acpi.c b/drivers/gpu/drm/nouveau/nouveau_acpi.c
 index 48227e7..ac7fd04 100644
@@ -149,23 +149,26 @@ index 48227e7..ac7fd04 100644
 +	return 0;
 +}
 diff --git a/drivers/gpu/drm/nouveau/nouveau_connector.c b/drivers/gpu/drm/nouveau/nouveau_connector.c
-index 8fc0145..6ddb67c 100644
+index fb51958..5832b60 100644
 --- a/drivers/gpu/drm/nouveau/nouveau_connector.c
 +++ b/drivers/gpu/drm/nouveau/nouveau_connector.c
-@@ -716,6 +716,11 @@ nouveau_connector_create_lvds(struct drm_device *dev,
+@@ -356,6 +356,14 @@ nouveau_connector_detect_lvds(struct drm_connector *connector)
  		}
  	}
  
 +	/* Let's try ACPI */
-+	if (!nv_connector->edid && !nv_connector->native_mode &&
-+	    !dev_priv->vbios.fp_no_ddc)
++	if (status != connector_status_connected &&
++	    !dev_priv->vbios.fp_no_ddc) {
 +		nouveau_acpi_get_edid(dev, connector, &nv_connector->edid);
++		if (nv_connector->edid)
++			status = connector_status_connected;
++	}
 +
- 	if (!nv_connector->edid)
- 		goto out;
- 
+ out:
+ #ifdef CONFIG_ACPI
+ 	if (status == connector_status_connected &&
 diff --git a/drivers/gpu/drm/nouveau/nouveau_drv.h b/drivers/gpu/drm/nouveau/nouveau_drv.h
-index 9e12c93..41b9b70 100644
+index c31159a..675d7ac 100644
 --- a/drivers/gpu/drm/nouveau/nouveau_drv.h
 +++ b/drivers/gpu/drm/nouveau/nouveau_drv.h
 @@ -39,6 +39,8 @@
@@ -216,7 +219,7 @@ index 9e12c93..41b9b70 100644
  #endif
  
 diff --git a/drivers/gpu/drm/nouveau/nouveau_state.c b/drivers/gpu/drm/nouveau/nouveau_state.c
-index a11cd7f..9f52b05 100644
+index 7c1d252..7ca9465 100644
 --- a/drivers/gpu/drm/nouveau/nouveau_state.c
 +++ b/drivers/gpu/drm/nouveau/nouveau_state.c
 @@ -627,10 +627,7 @@ int nouveau_load(struct drm_device *dev, unsigned long flags)
@@ -232,5 +235,5 @@ index a11cd7f..9f52b05 100644
  	dev_priv->wq = create_workqueue("nouveau");
  	if (!dev_priv->wq)
 -- 
-1.7.0.1
+1.7.1
 

drm-nouveau-drm-fixed-header.patch:
 drm_fixed.h |   68 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-
 1 file changed, 67 insertions(+), 1 deletion(-)

Index: drm-nouveau-drm-fixed-header.patch
===================================================================
RCS file: /cvs/pkgs/rpms/kernel/F-13/drm-nouveau-drm-fixed-header.patch,v
retrieving revision 1.1
retrieving revision 1.2
diff -u -p -r1.1 -r1.2
--- drm-nouveau-drm-fixed-header.patch	29 Apr 2010 01:06:40 -0000	1.1
+++ drm-nouveau-drm-fixed-header.patch	2 Jul 2010 05:47:01 -0000	1.2
@@ -1,7 +1,7 @@
-From 98b5715348686cb2d9d695c5010d3831d99b934b Mon Sep 17 00:00:00 2001
+From 841045c942be3fd2bf928a7de3e730a00665347e Mon Sep 17 00:00:00 2001
 From: Ben Skeggs <bskeggs at redhat.com>
 Date: Wed, 28 Apr 2010 15:19:10 +1000
-Subject: [PATCH] drm-nouveau-drm-fixed-header
+Subject: [PATCH 3/3] drm-nouveau-drm-fixed-header
 
 ---
  drivers/gpu/drm/nouveau/drm_fixed.h |   67 +++++++++++++++++++++++++++++++++++
@@ -82,5 +82,5 @@ index 0000000..4a08a66
 +}
 +#endif
 -- 
-1.7.0.1
+1.7.1
 

drm-nouveau-updates.patch:
 Makefile            |    7 
 nouveau_bios.c      | 1057 ++++++++++++++---------
 nouveau_bios.h      |  133 +-
 nouveau_bo.c        |   68 -
 nouveau_calc.c      |    4 
 nouveau_channel.c   |   17 
 nouveau_connector.c |  383 ++++----
 nouveau_connector.h |    3 
 nouveau_debugfs.c   |   18 
 nouveau_dma.c       |    5 
 nouveau_dp.c        |    8 
 nouveau_drv.c       |   14 
 nouveau_drv.h       |   70 -
 nouveau_encoder.h   |    7 
 nouveau_fence.c     |   31 
 nouveau_gem.c       |   55 -
 nouveau_hw.c        |    6 
 nouveau_i2c.c       |   23 
 nouveau_irq.c       |  615 ++++++++++++-
 nouveau_mem.c       |  129 +-
 nouveau_reg.h       |    1 
 nouveau_sgdma.c     |   18 
 nouveau_state.c     |   39 
 nv04_crtc.c         |    6 
 nv04_dac.c          |   15 
 nv04_dfp.c          |   12 
 nv04_display.c      |   64 -
 nv04_fbcon.c        |    6 
 nv04_fifo.c         |    5 
 nv04_graph.c        |    3 
 nv04_tv.c           |   10 
 nv17_tv.c           |   12 
 nv40_fifo.c         |    7 
 nv40_graph.c        |   21 
 nv50_calc.c         |   87 +
 nv50_crtc.c         |   46 -
 nv50_dac.c          |   13 
 nv50_display.c      |  122 +-
 nv50_display.h      |    1 
 nv50_fb.c           |   38 
 nv50_fbcon.c        |   17 
 nv50_fifo.c         |    5 
 nv50_gpio.c         |   76 +
 nv50_graph.c        |  103 +-
 nv50_grctx.c        | 2383 ++++++++++++++++++++++++++++++++++++++++++++++++++++
 nv50_instmem.c      |   18 
 nv50_sor.c          |   43 
 47 files changed, 4702 insertions(+), 1122 deletions(-)

Index: drm-nouveau-updates.patch
===================================================================
RCS file: /cvs/pkgs/rpms/kernel/F-13/drm-nouveau-updates.patch,v
retrieving revision 1.11
retrieving revision 1.12
diff -u -p -r1.11 -r1.12
--- drm-nouveau-updates.patch	25 Jun 2010 06:32:37 -0000	1.11
+++ drm-nouveau-updates.patch	2 Jul 2010 05:47:01 -0000	1.12
@@ -1,7 +1,7 @@
-From 4d67e7955f066668f8174583a3ce47844b8e67a8 Mon Sep 17 00:00:00 2001
+From 1fe467ac55c8503078f679b1f503e4895d6c5895 Mon Sep 17 00:00:00 2001
 From: Marcin Slusarz <marcin.slusarz at gmail.com>
 Date: Wed, 17 Feb 2010 19:04:00 +0100
-Subject: [PATCH] drm-nouveau-updates
+Subject: [PATCH 1/3] drm-nouveau-updates
 MIME-Version: 1.0
 Content-Type: text/plain; charset=UTF-8
 Content-Transfer-Encoding: 8bit
@@ -580,21 +580,66 @@ Signed-off-by: Ben Skeggs <bskeggs at redha
 drm/nouveau: reduce usage of fence spinlock to when absolutely necessary
 
 Signed-off-by: Ben Skeggs <bskeggs at redhat.com>
+
+drm/nouveau: move LVDS detection back to connector detect() time
+
+Signed-off-by: Ben Skeggs <bskeggs at redhat.com>
+
+drm/nouveau: Put the dithering check back in nouveau_connector_create.
+
+a7b9f9e5adef dropped it by accident.
+
+Signed-off-by: Francisco Jerez <currojerez at riseup.net>
+Tested-by: Thibaut Girka <thib at sitedethib.com>
+
+drm/nouveau: set encoder for lvds
+
+fixes oops in nouveau_connector_get_modes with nv_encoder is NULL
+
+Signed-off-by: Albert Damen <albrt at gmx.net>
+Signed-off-by: Francisco Jerez <currojerez at riseup.net>
+
+drm/nouveau: tidy connector/encoder creation a little
+
+Create connectors before encoders to avoid having to do another loop across
+encoder list whenever we create a new connector.  This allows us to pass
+the connector to the encoder creation functions, and avoid using a
+create_resources() callback since we can now call it directly.
+
+This can also potentially modify the connector ordering on nv50.  On cards
+where the DCB connector and encoder tables are in the same order, things
+will be unchanged.  However, there's some cards where the ordering between
+the tables differ, and in one case, leads us to naming the connectors
+"wrongly".
+
+Signed-off-by: Ben Skeggs <bskeggs at redhat.com>
+
+drm/nv50: fix regression caused by ed15e77b6ee7c4fa6f50c18b3325e7f96ed3aade
+
+It became possible for us to have connectors present without any encoders
+attached (TV out, we don't support TVDAC yet), which caused the DDX to
+segfault.
+
+Signed-off-by: Ben Skeggs <bskeggs at redhat.com>
+
+drm/nv04: fix regression caused by ed15e77b6ee7c4fa6f50c18b3325e7f96ed3aade
+
+Signed-off-by: Ben Skeggs <bskeggs at redhat.com>
 ---
  drivers/gpu/drm/nouveau/Makefile            |    7 +-
  drivers/gpu/drm/nouveau/nouveau_bios.c      | 1057 ++++++++-----
- drivers/gpu/drm/nouveau/nouveau_bios.h      |  132 +-
+ drivers/gpu/drm/nouveau/nouveau_bios.h      |  133 +-
  drivers/gpu/drm/nouveau/nouveau_bo.c        |   68 +-
  drivers/gpu/drm/nouveau/nouveau_calc.c      |    4 +-
  drivers/gpu/drm/nouveau/nouveau_channel.c   |   17 +-
- drivers/gpu/drm/nouveau/nouveau_connector.c |  197 ++-
+ drivers/gpu/drm/nouveau/nouveau_connector.c |  383 +++---
  drivers/gpu/drm/nouveau/nouveau_connector.h |    3 +-
  drivers/gpu/drm/nouveau/nouveau_debugfs.c   |   18 +-
  drivers/gpu/drm/nouveau/nouveau_dma.c       |    5 +
  drivers/gpu/drm/nouveau/nouveau_dp.c        |    8 +-
  drivers/gpu/drm/nouveau/nouveau_drv.c       |   14 +-
- drivers/gpu/drm/nouveau/nouveau_drv.h       |   62 +-
- drivers/gpu/drm/nouveau/nouveau_encoder.h   |    3 +
+ drivers/gpu/drm/nouveau/nouveau_drv.h       |   70 +-
+ drivers/gpu/drm/nouveau/nouveau_encoder.h   |    7 +-
  drivers/gpu/drm/nouveau/nouveau_fence.c     |   31 +-
  drivers/gpu/drm/nouveau/nouveau_gem.c       |   55 +-
  drivers/gpu/drm/nouveau/nouveau_hw.c        |    6 +-
@@ -605,20 +650,20 @@ Signed-off-by: Ben Skeggs <bskeggs at redha
  drivers/gpu/drm/nouveau/nouveau_sgdma.c     |   18 +
  drivers/gpu/drm/nouveau/nouveau_state.c     |   39 +-
  drivers/gpu/drm/nouveau/nv04_crtc.c         |    6 +-
- drivers/gpu/drm/nouveau/nv04_dac.c          |    8 +-
- drivers/gpu/drm/nouveau/nv04_dfp.c          |    4 +-
- drivers/gpu/drm/nouveau/nv04_display.c      |   49 +-
+ drivers/gpu/drm/nouveau/nv04_dac.c          |   15 +-
+ drivers/gpu/drm/nouveau/nv04_dfp.c          |   12 +-
+ drivers/gpu/drm/nouveau/nv04_display.c      |   64 +-
  drivers/gpu/drm/nouveau/nv04_fbcon.c        |    6 +-
  drivers/gpu/drm/nouveau/nv04_fifo.c         |    5 +
  drivers/gpu/drm/nouveau/nv04_graph.c        |    3 +-
- drivers/gpu/drm/nouveau/nv04_tv.c           |    2 +-
- drivers/gpu/drm/nouveau/nv17_tv.c           |    6 +-
+ drivers/gpu/drm/nouveau/nv04_tv.c           |   10 +-
+ drivers/gpu/drm/nouveau/nv17_tv.c           |   12 +-
  drivers/gpu/drm/nouveau/nv40_fifo.c         |    7 +-
  drivers/gpu/drm/nouveau/nv40_graph.c        |   21 +
- drivers/gpu/drm/nouveau/nv50_calc.c         |   88 +
+ drivers/gpu/drm/nouveau/nv50_calc.c         |   87 +
  drivers/gpu/drm/nouveau/nv50_crtc.c         |   46 +-
- drivers/gpu/drm/nouveau/nv50_dac.c          |    4 +-
- drivers/gpu/drm/nouveau/nv50_display.c      |  111 +-
+ drivers/gpu/drm/nouveau/nv50_dac.c          |   13 +-
+ drivers/gpu/drm/nouveau/nv50_display.c      |  122 +-
  drivers/gpu/drm/nouveau/nv50_display.h      |    1 +
  drivers/gpu/drm/nouveau/nv50_fb.c           |   38 +
  drivers/gpu/drm/nouveau/nv50_fbcon.c        |   17 +-
@@ -627,8 +672,8 @@ Signed-off-by: Ben Skeggs <bskeggs at redha
  drivers/gpu/drm/nouveau/nv50_graph.c        |  103 +-
  drivers/gpu/drm/nouveau/nv50_grctx.c        | 2383 +++++++++++++++++++++++++++
  drivers/gpu/drm/nouveau/nv50_instmem.c      |   18 +-
- drivers/gpu/drm/nouveau/nv50_sor.c          |   25 +-
- 47 files changed, 4567 insertions(+), 977 deletions(-)
+ drivers/gpu/drm/nouveau/nv50_sor.c          |   42 +-
+ 47 files changed, 4702 insertions(+), 1121 deletions(-)
  create mode 100644 drivers/gpu/drm/nouveau/nv50_calc.c
  create mode 100644 drivers/gpu/drm/nouveau/nv50_fb.c
  create mode 100644 drivers/gpu/drm/nouveau/nv50_gpio.c
@@ -2664,10 +2709,10 @@ index 0e9cd1d..1803cc4 100644
  	/* feature_byte on BMP is poor, but init always sets CR4B */
  	was_locked = NVLockVgaCrtcs(dev, false);
 diff --git a/drivers/gpu/drm/nouveau/nouveau_bios.h b/drivers/gpu/drm/nouveau/nouveau_bios.h
-index fd94bd6..adf4ec2 100644
+index fd94bd6..bd33a54 100644
 --- a/drivers/gpu/drm/nouveau/nouveau_bios.h
 +++ b/drivers/gpu/drm/nouveau/nouveau_bios.h
-@@ -34,9 +34,72 @@
+@@ -34,9 +34,73 @@
  
  #define DCB_LOC_ON_CHIP 0
  
@@ -2718,6 +2763,7 @@ index fd94bd6..adf4ec2 100644
 +	enum dcb_connector_type type;
 +	uint8_t index2;
 +	uint8_t gpio_tag;
++	void *drm;
 +};
 +
 +struct dcb_connector_table {
@@ -2741,7 +2787,7 @@ index fd94bd6..adf4ec2 100644
  	uint8_t i2c_index;
  	uint8_t heads;
  	uint8_t connector;
-@@ -71,69 +134,22 @@ struct dcb_entry {
+@@ -71,69 +135,22 @@ struct dcb_entry {
  	bool i2c_upper_default;
  };
  
@@ -2815,7 +2861,7 @@ index fd94bd6..adf4ec2 100644
  enum nouveau_or {
  	OUTPUT_A = (1 << 0),
  	OUTPUT_B = (1 << 1),
-@@ -190,8 +206,8 @@ struct pll_lims {
+@@ -190,8 +207,8 @@ struct pll_lims {
  	int refclk;
  };
  
@@ -2826,7 +2872,7 @@ index fd94bd6..adf4ec2 100644
  
  	uint8_t chip_version;
  
-@@ -199,11 +215,6 @@ struct nouveau_bios_info {
+@@ -199,11 +216,6 @@ struct nouveau_bios_info {
  	uint32_t tvdactestval;
  	uint8_t digital_min_front_porch;
  	bool fp_no_ddc;
@@ -2838,7 +2884,7 @@ index fd94bd6..adf4ec2 100644
  
  	struct mutex lock;
  
-@@ -234,7 +245,7 @@ struct nvbios {
+@@ -234,7 +246,7 @@ struct nvbios {
  	uint16_t some_script_ptr; /* BIT I + 14 */
  	uint16_t init96_tbl_ptr; /* BIT I + 16 */
  
@@ -2847,7 +2893,7 @@ index fd94bd6..adf4ec2 100644
  
  	struct {
  		int crtchead;
-@@ -260,7 +271,6 @@ struct nvbios {
+@@ -260,7 +272,6 @@ struct nvbios {
  		bool reset_after_pclk_change;
  		bool dual_link;
  		bool link_c_increment;
@@ -3086,7 +3132,7 @@ index adac0f8..f9b2acf 100644
  }
  
 diff --git a/drivers/gpu/drm/nouveau/nouveau_connector.c b/drivers/gpu/drm/nouveau/nouveau_connector.c
-index d2f6335..1b9bd4f 100644
+index a378bc3..fb51958 100644
 --- a/drivers/gpu/drm/nouveau/nouveau_connector.c
 +++ b/drivers/gpu/drm/nouveau/nouveau_connector.c
 @@ -218,7 +218,7 @@ nouveau_connector_set_encoder(struct drm_connector *connector,
@@ -3098,16 +3144,27 @@ index d2f6335..1b9bd4f 100644
  		drm_connector_property_set_value(connector,
  			dev->mode_config.dvi_i_subconnector_property,
  			nv_encoder->dcb->type == OUTPUT_TMDS ?
-@@ -236,7 +236,7 @@ nouveau_connector_detect(struct drm_connector *connector)
+@@ -236,19 +236,6 @@ nouveau_connector_detect(struct drm_connector *connector)
  	struct nouveau_i2c_chan *i2c;
  	int type, flags;
  
 -	if (connector->connector_type == DRM_MODE_CONNECTOR_LVDS)
-+	if (nv_connector->dcb->type == DCB_CONNECTOR_LVDS)
- 		nv_encoder = find_encoder_by_type(connector, OUTPUT_LVDS);
- 	if (nv_encoder && nv_connector->native_mode) {
- #ifdef CONFIG_ACPI
-@@ -279,7 +279,7 @@ nouveau_connector_detect(struct drm_connector *connector)
+-		nv_encoder = find_encoder_by_type(connector, OUTPUT_LVDS);
+-	if (nv_encoder && nv_connector->native_mode) {
+-		unsigned status = connector_status_connected;
+-
+-#ifdef CONFIG_ACPI
+-		if (!nouveau_ignorelid && !acpi_lid_open())
+-			status = connector_status_unknown;
+-#endif
+-		nouveau_connector_set_encoder(connector, nv_encoder);
+-		return status;
+-	}
+-
+ 	/* Cleanup the previous EDID block. */
+ 	if (nv_connector->edid) {
+ 		drm_mode_connector_update_edid_property(connector, NULL);
+@@ -281,7 +268,7 @@ nouveau_connector_detect(struct drm_connector *connector)
  		 * same i2c channel so the value returned from ddc_detect
  		 * isn't necessarily correct.
  		 */
@@ -3116,7 +3173,7 @@ index d2f6335..1b9bd4f 100644
  			if (nv_connector->edid->input & DRM_EDID_INPUT_DIGITAL)
  				type = OUTPUT_TMDS;
  			else
-@@ -300,7 +300,7 @@ nouveau_connector_detect(struct drm_connector *connector)
+@@ -302,7 +289,7 @@ nouveau_connector_detect(struct drm_connector *connector)
  
  detect_analog:
  	nv_encoder = find_encoder_by_type(connector, OUTPUT_ANALOG);
@@ -3125,7 +3182,71 @@ index d2f6335..1b9bd4f 100644
  		nv_encoder = find_encoder_by_type(connector, OUTPUT_TV);
  	if (nv_encoder) {
  		struct drm_encoder *encoder = to_drm_encoder(nv_encoder);
-@@ -321,11 +321,11 @@ detect_analog:
+@@ -320,14 +307,75 @@ detect_analog:
+ 	return connector_status_disconnected;
+ }
+ 
++static enum drm_connector_status
++nouveau_connector_detect_lvds(struct drm_connector *connector)
++{
++	struct drm_device *dev = connector->dev;
++	struct drm_nouveau_private *dev_priv = dev->dev_private;
++	struct nouveau_connector *nv_connector = nouveau_connector(connector);
++	struct nouveau_encoder *nv_encoder = NULL;
++	enum drm_connector_status status = connector_status_disconnected;
++
++	/* Cleanup the previous EDID block. */
++	if (nv_connector->edid) {
++		drm_mode_connector_update_edid_property(connector, NULL);
++		kfree(nv_connector->edid);
++		nv_connector->edid = NULL;
++	}
++
++	nv_encoder = find_encoder_by_type(connector, OUTPUT_LVDS);
++	if (!nv_encoder)
++		return connector_status_disconnected;
++
++	if (!dev_priv->vbios.fp_no_ddc) {
++		status = nouveau_connector_detect(connector);
++		if (status == connector_status_connected)
++			goto out;
++	}
++
++	/* If no EDID found above, and the VBIOS indicates a hardcoded
++	 * modeline is avalilable for the panel, set it as the panel's
++	 * native mode and exit.
++	 */
++	if (nouveau_bios_fp_mode(dev, NULL) && (dev_priv->vbios.fp_no_ddc ||
++	    nv_encoder->dcb->lvdsconf.use_straps_for_mode)) {
++		status = connector_status_connected;
++		goto out;
++	}
++
++	/* Still nothing, some VBIOS images have a hardcoded EDID block
++	 * stored for the panel stored in them.
++	 */
++	if (!dev_priv->vbios.fp_no_ddc) {
++		struct edid *edid =
++			(struct edid *)nouveau_bios_embedded_edid(dev);
++		if (edid) {
++			nv_connector->edid = kmalloc(EDID_LENGTH, GFP_KERNEL);
++			*(nv_connector->edid) = *edid;
++			status = connector_status_connected;
++		}
++	}
++
++out:
++#ifdef CONFIG_ACPI
++	if (status == connector_status_connected &&
++	    !nouveau_ignorelid && !acpi_lid_open())
++		status = connector_status_unknown;
++#endif
++
++	drm_mode_connector_update_edid_property(connector, nv_connector->edid);
++	nouveau_connector_set_encoder(connector, nv_encoder);
++	return status;
++}
++
  static void
  nouveau_connector_force(struct drm_connector *connector)
  {
@@ -3139,7 +3260,7 @@ index d2f6335..1b9bd4f 100644
  		if (connector->force == DRM_FORCE_ON_DIGITAL)
  			type = OUTPUT_TMDS;
  		else
-@@ -335,7 +335,7 @@ nouveau_connector_force(struct drm_connector *connector)
+@@ -337,7 +385,7 @@ nouveau_connector_force(struct drm_connector *connector)
  
  	nv_encoder = find_encoder_by_type(connector, type);
  	if (!nv_encoder) {
@@ -3148,7 +3269,7 @@ index d2f6335..1b9bd4f 100644
  			 drm_get_connector_name(connector));
  		connector->status = connector_status_disconnected;
  		return;
-@@ -369,7 +369,7 @@ nouveau_connector_set_property(struct drm_connector *connector,
+@@ -371,7 +419,7 @@ nouveau_connector_set_property(struct drm_connector *connector,
  		}
  
  		/* LVDS always needs gpu scaling */
@@ -3157,7 +3278,7 @@ index d2f6335..1b9bd4f 100644
  		    value == DRM_MODE_SCALE_NONE)
  			return -EINVAL;
  
-@@ -429,24 +429,27 @@ nouveau_connector_set_property(struct drm_connector *connector,
+@@ -431,24 +479,27 @@ nouveau_connector_set_property(struct drm_connector *connector,
  }
  
  static struct drm_display_mode *
@@ -3194,16 +3315,40 @@ index d2f6335..1b9bd4f 100644
  		if (mode->hdisplay < high_w)
  			continue;
  
-@@ -535,7 +538,7 @@ nouveau_connector_get_modes(struct drm_connector *connector)
- 	/* If we're not LVDS, destroy the previous native mode, the attached
- 	 * monitor could have changed.
+@@ -530,21 +581,28 @@ static int
+ nouveau_connector_get_modes(struct drm_connector *connector)
+ {
+ 	struct drm_device *dev = connector->dev;
++	struct drm_nouveau_private *dev_priv = dev->dev_private;
+ 	struct nouveau_connector *nv_connector = nouveau_connector(connector);
+ 	struct nouveau_encoder *nv_encoder = nv_connector->detected_encoder;
++	struct drm_display_mode mode;
+ 	int ret = 0;
+ 
+-	/* If we're not LVDS, destroy the previous native mode, the attached
+-	 * monitor could have changed.
++	/* destroy the native mode, the attached monitor could have changed.
  	 */
 -	if (connector->connector_type != DRM_MODE_CONNECTOR_LVDS &&
-+	if (nv_connector->dcb->type != DCB_CONNECTOR_LVDS &&
- 	    nv_connector->native_mode) {
+-	    nv_connector->native_mode) {
++	if (nv_connector->native_mode) {
  		drm_mode_destroy(dev, nv_connector->native_mode);
  		nv_connector->native_mode = NULL;
-@@ -550,7 +553,7 @@ nouveau_connector_get_modes(struct drm_connector *connector)
+ 	}
+ 
+ 	if (nv_connector->edid)
+ 		ret = drm_add_edid_modes(connector, nv_connector->edid);
++	else
++	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, &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
+@@ -552,7 +610,7 @@ nouveau_connector_get_modes(struct drm_connector *connector)
  	 */
  	if (!nv_connector->native_mode)
  		nv_connector->native_mode =
@@ -3212,7 +3357,7 @@ index d2f6335..1b9bd4f 100644
  	if (ret == 0 && nv_connector->native_mode) {
  		struct drm_display_mode *mode;
  
-@@ -563,7 +566,7 @@ nouveau_connector_get_modes(struct drm_connector *connector)
+@@ -565,7 +623,7 @@ nouveau_connector_get_modes(struct drm_connector *connector)
  		ret = get_slave_funcs(nv_encoder)->
  			get_modes(to_drm_encoder(nv_encoder), connector);
  
@@ -3221,7 +3366,7 @@ index d2f6335..1b9bd4f 100644
  		ret += nouveau_connector_scaler_modes_add(connector);
  
  	return ret;
-@@ -581,9 +584,9 @@ nouveau_connector_mode_valid(struct drm_connector *connector,
+@@ -583,9 +641,9 @@ nouveau_connector_mode_valid(struct drm_connector *connector,
  
  	switch (nv_encoder->dcb->type) {
  	case OUTPUT_LVDS:
@@ -3234,7 +3379,7 @@ index d2f6335..1b9bd4f 100644
  			return MODE_PANEL;
  
  		min_clock = 0;
-@@ -591,8 +594,7 @@ nouveau_connector_mode_valid(struct drm_connector *connector,
+@@ -593,8 +651,7 @@ nouveau_connector_mode_valid(struct drm_connector *connector,
  		break;
  	case OUTPUT_TMDS:
  		if ((dev_priv->card_type >= NV_50 && !nouveau_duallink) ||
@@ -3244,7 +3389,7 @@ index d2f6335..1b9bd4f 100644
  			max_clock = 165000;
  		else
  			max_clock = 330000;
-@@ -613,6 +615,9 @@ nouveau_connector_mode_valid(struct drm_connector *connector,
+@@ -615,6 +672,9 @@ nouveau_connector_mode_valid(struct drm_connector *connector,
  
  		clock *= 3;
  		break;
@@ -3254,56 +3399,118 @@ index d2f6335..1b9bd4f 100644
  	}
  
  	if (clock < min_clock)
-@@ -680,7 +685,7 @@ nouveau_connector_create_lvds(struct drm_device *dev,
- 	/* Firstly try getting EDID over DDC, if allowed and I2C channel
- 	 * is available.
- 	 */
--	if (!dev_priv->VBIOS.pub.fp_no_ddc && nv_encoder->dcb->i2c_index < 0xf)
-+	if (!dev_priv->vbios.fp_no_ddc && nv_encoder->dcb->i2c_index < 0xf)
- 		i2c = nouveau_i2c_find(dev, nv_encoder->dcb->i2c_index);
+@@ -656,193 +716,138 @@ nouveau_connector_funcs = {
+ 	.force = nouveau_connector_force
+ };
  
- 	if (i2c) {
-@@ -695,7 +700,7 @@ nouveau_connector_create_lvds(struct drm_device *dev,
- 	 */
- 	if (!nv_connector->edid && nouveau_bios_fp_mode(dev, &native) &&
- 	     (nv_encoder->dcb->lvdsconf.use_straps_for_mode ||
+-static int
+-nouveau_connector_create_lvds(struct drm_device *dev,
+-			      struct drm_connector *connector)
+-{
+-	struct nouveau_connector *nv_connector = nouveau_connector(connector);
+-	struct drm_nouveau_private *dev_priv = dev->dev_private;
+-	struct nouveau_i2c_chan *i2c = NULL;
+-	struct nouveau_encoder *nv_encoder;
+-	struct drm_display_mode native, *mode, *temp;
+-	bool dummy, if_is_24bit = false;
+-	int ret, flags;
+-
+-	nv_encoder = find_encoder_by_type(connector, OUTPUT_LVDS);
+-	if (!nv_encoder)
+-		return -ENODEV;
+-
+-	ret = nouveau_bios_parse_lvds_table(dev, 0, &dummy, &if_is_24bit);
+-	if (ret) {
+-		NV_ERROR(dev, "Error parsing LVDS table, disabling LVDS\n");
+-		return ret;
+-	}
+-	nv_connector->use_dithering = !if_is_24bit;
+-
+-	/* Firstly try getting EDID over DDC, if allowed and I2C channel
+-	 * is available.
+-	 */
+-	if (!dev_priv->VBIOS.pub.fp_no_ddc && nv_encoder->dcb->i2c_index < 0xf)
+-		i2c = nouveau_i2c_find(dev, nv_encoder->dcb->i2c_index);
+-
+-	if (i2c) {
+-		nouveau_connector_ddc_prepare(connector, &flags);
+-		nv_connector->edid = drm_get_edid(connector, &i2c->adapter);
+-		nouveau_connector_ddc_finish(connector, flags);
+-	}
+-
+-	/* If no EDID found above, and the VBIOS indicates a hardcoded
+-	 * modeline is avalilable for the panel, set it as the panel's
+-	 * native mode and exit.
+-	 */
+-	if (!nv_connector->edid && nouveau_bios_fp_mode(dev, &native) &&
+-	     (nv_encoder->dcb->lvdsconf.use_straps_for_mode ||
 -	      dev_priv->VBIOS.pub.fp_no_ddc)) {
-+	      dev_priv->vbios.fp_no_ddc)) {
- 		nv_connector->native_mode = drm_mode_duplicate(dev, &native);
- 		goto out;
- 	}
-@@ -704,7 +709,7 @@ nouveau_connector_create_lvds(struct drm_device *dev,
- 	 * stored for the panel stored in them.
- 	 */
- 	if (!nv_connector->edid && !nv_connector->native_mode &&
+-		nv_connector->native_mode = drm_mode_duplicate(dev, &native);
+-		goto out;
+-	}
+-
+-	/* Still nothing, some VBIOS images have a hardcoded EDID block
+-	 * stored for the panel stored in them.
+-	 */
+-	if (!nv_connector->edid && !nv_connector->native_mode &&
 -	    !dev_priv->VBIOS.pub.fp_no_ddc) {
-+	    !dev_priv->vbios.fp_no_ddc) {
- 		struct edid *edid =
- 			(struct edid *)nouveau_bios_embedded_edid(dev);
- 		if (edid) {
-@@ -723,7 +728,7 @@ nouveau_connector_create_lvds(struct drm_device *dev,
- 	if (ret == 0)
- 		goto out;
- 	nv_connector->detected_encoder = nv_encoder;
+-		struct edid *edid =
+-			(struct edid *)nouveau_bios_embedded_edid(dev);
+-		if (edid) {
+-			nv_connector->edid = kmalloc(EDID_LENGTH, GFP_KERNEL);
+-			*(nv_connector->edid) = *edid;
+-		}
+-	}
+-
+-	if (!nv_connector->edid)
+-		goto out;
+-
+-	/* We didn't find/use a panel mode from the VBIOS, so parse the EDID
+-	 * block and look for the preferred mode there.
+-	 */
+-	ret = drm_add_edid_modes(connector, nv_connector->edid);
+-	if (ret == 0)
+-		goto out;
+-	nv_connector->detected_encoder = nv_encoder;
 -	nv_connector->native_mode = nouveau_connector_native_mode(nv_connector);
-+	nv_connector->native_mode = nouveau_connector_native_mode(connector);
- 	list_for_each_entry_safe(mode, temp, &connector->probed_modes, head)
- 		drm_mode_remove(connector, mode);
- 
-@@ -739,46 +744,66 @@ out:
- }
+-	list_for_each_entry_safe(mode, temp, &connector->probed_modes, head)
+-		drm_mode_remove(connector, mode);
+-
+-out:
+-	if (!nv_connector->native_mode) {
+-		NV_ERROR(dev, "LVDS present in DCB table, but couldn't "
+-			      "determine its native mode.  Disabling.\n");
+-		return -ENODEV;
+-	}
+-
+-	drm_mode_connector_update_edid_property(connector, nv_connector->edid);
+-	return 0;
+-}
++static const struct drm_connector_funcs
++nouveau_connector_funcs_lvds = {
++	.dpms = drm_helper_connector_dpms,
++	.save = NULL,
++	.restore = NULL,
++	.detect = nouveau_connector_detect_lvds,
++	.destroy = nouveau_connector_destroy,
++	.fill_modes = drm_helper_probe_single_connector_modes,
++	.set_property = nouveau_connector_set_property,
++	.force = nouveau_connector_force
++};
  
- int
+-int
 -nouveau_connector_create(struct drm_device *dev, int index, int type)
-+nouveau_connector_create(struct drm_device *dev,
-+			 struct dcb_connector_table_entry *dcb)
++struct drm_connector *
++nouveau_connector_create(struct drm_device *dev, int index)
  {
++	const struct drm_connector_funcs *funcs = &nouveau_connector_funcs;
  	struct drm_nouveau_private *dev_priv = dev->dev_private;
  	struct nouveau_connector *nv_connector = NULL;
++	struct dcb_connector_table_entry *dcb = NULL;
  	struct drm_connector *connector;
- 	struct drm_encoder *encoder;
+-	struct drm_encoder *encoder;
 -	int ret;
-+	int ret, type;
++	int type, ret = 0;
  
  	NV_DEBUG_KMS(dev, "\n");
  
@@ -3312,14 +3519,18 @@ index d2f6335..1b9bd4f 100644
 -		return -ENOMEM;
 -	nv_connector->dcb = nouveau_bios_connector_entry(dev, index);
 -	connector = &nv_connector->base;
--
++	if (index >= dev_priv->vbios.dcb.connector.entries)
++		return ERR_PTR(-EINVAL);
+ 
 -	switch (type) {
 -	case DRM_MODE_CONNECTOR_VGA:
+-		NV_INFO(dev, "Detected a VGA connector\n");
++	dcb = &dev_priv->vbios.dcb.connector.entry[index];
++	if (dcb->drm)
++		return dcb->drm;
++
 +	switch (dcb->type) {
-+	case DCB_CONNECTOR_NONE:
-+		return 0;
 +	case DCB_CONNECTOR_VGA:
- 		NV_INFO(dev, "Detected a VGA connector\n");
 +		type = DRM_MODE_CONNECTOR_VGA;
  		break;
 -	case DRM_MODE_CONNECTOR_DVID:
@@ -3327,78 +3538,69 @@ index d2f6335..1b9bd4f 100644
 +	case DCB_CONNECTOR_TV_0:
 +	case DCB_CONNECTOR_TV_1:
 +	case DCB_CONNECTOR_TV_3:
-+		NV_INFO(dev, "Detected a TV connector\n");
 +		type = DRM_MODE_CONNECTOR_TV;
  		break;
 -	case DRM_MODE_CONNECTOR_DVII:
+-		NV_INFO(dev, "Detected a DVI-I connector\n");
 +	case DCB_CONNECTOR_DVI_I:
- 		NV_INFO(dev, "Detected a DVI-I connector\n");
 +		type = DRM_MODE_CONNECTOR_DVII;
  		break;
 -	case DRM_MODE_CONNECTOR_LVDS:
 -		NV_INFO(dev, "Detected a LVDS connector\n");
 +	case DCB_CONNECTOR_DVI_D:
-+		NV_INFO(dev, "Detected a DVI-D connector\n");
 +		type = DRM_MODE_CONNECTOR_DVID;
  		break;
 -	case DRM_MODE_CONNECTOR_TV:
 -		NV_INFO(dev, "Detected a TV connector\n");
 +	case DCB_CONNECTOR_HDMI_0:
 +	case DCB_CONNECTOR_HDMI_1:
-+		NV_INFO(dev, "Detected a HDMI connector\n");
 +		type = DRM_MODE_CONNECTOR_HDMIA;
  		break;
 -	case DRM_MODE_CONNECTOR_DisplayPort:
+-		NV_INFO(dev, "Detected a DisplayPort connector\n");
 +	case DCB_CONNECTOR_LVDS:
-+		NV_INFO(dev, "Detected a LVDS connector\n");
 +		type = DRM_MODE_CONNECTOR_LVDS;
-+		break;
-+	case DCB_CONNECTOR_DP:
- 		NV_INFO(dev, "Detected a DisplayPort connector\n");
-+		type = DRM_MODE_CONNECTOR_DisplayPort;
++		funcs = &nouveau_connector_funcs_lvds;
  		break;
 -	default:
 -		NV_ERROR(dev, "Unknown connector, this is not good.\n");
++	case DCB_CONNECTOR_DP:
++		type = DRM_MODE_CONNECTOR_DisplayPort;
++		break;
 +	case DCB_CONNECTOR_eDP:
-+		NV_INFO(dev, "Detected an eDP connector\n");
 +		type = DRM_MODE_CONNECTOR_eDP;
  		break;
 +	default:
 +		NV_ERROR(dev, "unknown connector type: 0x%02x!!\n", dcb->type);
-+		return -EINVAL;
++		return ERR_PTR(-EINVAL);
  	}
  
 +	nv_connector = kzalloc(sizeof(*nv_connector), GFP_KERNEL);
 +	if (!nv_connector)
-+		return -ENOMEM;
++		return ERR_PTR(-ENOMEM);
 +	nv_connector->dcb = dcb;
 +	connector = &nv_connector->base;
 +
  	/* defaults, will get overridden in detect() */
  	connector->interlace_allowed = false;
  	connector->doublescan_allowed = false;
-@@ -786,55 +811,65 @@ nouveau_connector_create(struct drm_device *dev, int index, int type)
- 	drm_connector_init(dev, connector, &nouveau_connector_funcs, type);
+ 
+-	drm_connector_init(dev, connector, &nouveau_connector_funcs, type);
++	drm_connector_init(dev, connector, funcs, type);
  	drm_connector_helper_add(connector, &nouveau_connector_helper_funcs);
  
-+	/* attach encoders */
-+	list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) {
-+		struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder);
-+
-+		if (nv_encoder->dcb->connector != dcb->index)
-+			continue;
++	/* Check if we need dithering enabled */
++	if (dcb->type == DCB_CONNECTOR_LVDS) {
++		bool dummy, is_24bit = false;
 +
-+		if (get_slave_funcs(nv_encoder))
-+			get_slave_funcs(nv_encoder)->create_resources(encoder, connector);
++		ret = nouveau_bios_parse_lvds_table(dev, 0, &dummy, &is_24bit);
++		if (ret) {
++			NV_ERROR(dev, "Error parsing LVDS table, disabling "
++				 "LVDS\n");
++			goto fail;
++		}
 +
-+		drm_mode_connector_attach_encoder(connector, encoder);
-+	}
-+
-+	if (!connector->encoder_ids[0]) {
-+		NV_WARN(dev, "  no encoders, ignoring\n");
-+		drm_connector_cleanup(connector);
-+		kfree(connector);
-+		return 0;
++		nv_connector->use_dithering = !is_24bit;
 +	}
 +
  	/* Init DVI-I specific properties */
@@ -3410,9 +3612,8 @@ index d2f6335..1b9bd4f 100644
  	}
  
 -	if (type != DRM_MODE_CONNECTOR_LVDS)
-+	if (dcb->type != DCB_CONNECTOR_LVDS)
- 		nv_connector->use_dithering = false;
- 
+-		nv_connector->use_dithering = false;
+-
 -	if (type == DRM_MODE_CONNECTOR_DVID ||
 -	    type == DRM_MODE_CONNECTOR_DVII ||
 -	    type == DRM_MODE_CONNECTOR_LVDS ||
@@ -3469,14 +3670,25 @@ index d2f6335..1b9bd4f 100644
  	}
  
  	drm_sysfs_connector_add(connector);
++	dcb->drm = connector;
++	return dcb->drm;
  
 -	if (connector->connector_type == DRM_MODE_CONNECTOR_LVDS) {
-+	if (dcb->type == DCB_CONNECTOR_LVDS) {
- 		ret = nouveau_connector_create_lvds(dev, connector);
- 		if (ret) {
- 			connector->funcs->destroy(connector);
+-		ret = nouveau_connector_create_lvds(dev, connector);
+-		if (ret) {
+-			connector->funcs->destroy(connector);
+-			return ret;
+-		}
+-	}
++fail:
++	drm_connector_cleanup(connector);
++	kfree(connector);
++	return ERR_PTR(ret);
+ 
+-	return 0;
+ }
 diff --git a/drivers/gpu/drm/nouveau/nouveau_connector.h b/drivers/gpu/drm/nouveau/nouveau_connector.h
-index 728b809..4ef38ab 100644
+index 728b809..1ce3d91 100644
 --- a/drivers/gpu/drm/nouveau/nouveau_connector.h
 +++ b/drivers/gpu/drm/nouveau/nouveau_connector.h
 @@ -49,6 +49,7 @@ static inline struct nouveau_connector *nouveau_connector(
@@ -3484,8 +3696,8 @@ index 728b809..4ef38ab 100644
  }
  
 -int nouveau_connector_create(struct drm_device *dev, int i2c_index, int type);
-+int nouveau_connector_create(struct drm_device *,
-+			     struct dcb_connector_table_entry *);
++struct drm_connector *
++nouveau_connector_create(struct drm_device *, int index);
  
  #endif /* __NOUVEAU_CONNECTOR_H__ */
 diff --git a/drivers/gpu/drm/nouveau/nouveau_debugfs.c b/drivers/gpu/drm/nouveau/nouveau_debugfs.c
@@ -3608,7 +3820,7 @@ index da3b93b..60a709c 100644
  		struct nouveau_framebuffer *nouveau_fb;
  
 diff --git a/drivers/gpu/drm/nouveau/nouveau_drv.h b/drivers/gpu/drm/nouveau/nouveau_drv.h
-index 5be0cca..aeae21d 100644
+index 5be0cca..c31159a 100644
 --- a/drivers/gpu/drm/nouveau/nouveau_drv.h
 +++ b/drivers/gpu/drm/nouveau/nouveau_drv.h
 @@ -76,6 +76,7 @@ struct nouveau_bo {
@@ -3770,6 +3982,35 @@ index 5be0cca..aeae21d 100644
  
  /* nouveau_grctx.c */
  extern int  nouveau_grctx_prog_load(struct drm_device *);
+@@ -1081,13 +1083,13 @@ extern long nouveau_compat_ioctl(struct file *file, unsigned int cmd,
+ 				 unsigned long arg);
+ 
+ /* nv04_dac.c */
+-extern int nv04_dac_create(struct drm_device *dev, struct dcb_entry *entry);
++extern int nv04_dac_create(struct drm_connector *, struct dcb_entry *);
+ extern uint32_t nv17_dac_sample_load(struct drm_encoder *encoder);
+ extern int nv04_dac_output_offset(struct drm_encoder *encoder);
+ extern void nv04_dac_update_dacclk(struct drm_encoder *encoder, bool enable);
+ 
+ /* nv04_dfp.c */
+-extern int nv04_dfp_create(struct drm_device *dev, struct dcb_entry *entry);
++extern int nv04_dfp_create(struct drm_connector *, struct dcb_entry *);
+ 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);
+@@ -1096,10 +1098,10 @@ 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);
+-extern int nv04_tv_create(struct drm_device *dev, struct dcb_entry *entry);
++extern int nv04_tv_create(struct drm_connector *, struct dcb_entry *);
+ 
+ /* nv17_tv.c */
+-extern int nv17_tv_create(struct drm_device *dev, struct dcb_entry *entry);
++extern int nv17_tv_create(struct drm_connector *, struct dcb_entry *);
+ 
+ /* nv04_display.c */
+ extern int nv04_display_create(struct drm_device *);
 @@ -1119,7 +1121,8 @@ extern int nouveau_bo_pin(struct nouveau_bo *, uint32_t flags);
  extern int nouveau_bo_unpin(struct nouveau_bo *);
  extern int nouveau_bo_map(struct nouveau_bo *);
@@ -3806,7 +4047,7 @@ index 5be0cca..aeae21d 100644
  #ifdef __BIG_ENDIAN
  #define ioread16_native ioread16be
 diff --git a/drivers/gpu/drm/nouveau/nouveau_encoder.h b/drivers/gpu/drm/nouveau/nouveau_encoder.h
-index bc4a240..e1df820 100644
+index bc4a240..e4442e2 100644
 --- a/drivers/gpu/drm/nouveau/nouveau_encoder.h
 +++ b/drivers/gpu/drm/nouveau/nouveau_encoder.h
 @@ -47,6 +47,9 @@ struct nouveau_encoder {
@@ -3819,6 +4060,17 @@ index bc4a240..e1df820 100644
  			int dpcd_version;
  			int link_nr;
  			int link_bw;
+@@ -68,8 +71,8 @@ static inline struct drm_encoder *to_drm_encoder(struct nouveau_encoder *enc)
+ 
+ struct nouveau_connector *
+ nouveau_encoder_connector_get(struct nouveau_encoder *encoder);
+-int nv50_sor_create(struct drm_device *dev, struct dcb_entry *entry);
+-int nv50_dac_create(struct drm_device *dev, struct dcb_entry *entry);
++int nv50_sor_create(struct drm_connector *, struct dcb_entry *);
++int nv50_dac_create(struct drm_connector *, struct dcb_entry *);
+ 
+ struct bit_displayport_encoder_table {
+ 	uint32_t match;
 diff --git a/drivers/gpu/drm/nouveau/nouveau_fence.c b/drivers/gpu/drm/nouveau/nouveau_fence.c
 index faddf53..813d853 100644
 --- a/drivers/gpu/drm/nouveau/nouveau_fence.c
@@ -5128,7 +5380,7 @@ index d2f143e..9986aba 100644
  	int horizBlankStart	= (mode->crtc_hdisplay >> 3)		- 1;
  	int horizBlankEnd	= (mode->crtc_htotal >> 3)		- 1;
 diff --git a/drivers/gpu/drm/nouveau/nv04_dac.c b/drivers/gpu/drm/nouveau/nv04_dac.c
-index 1d73b15..1cb19e3 100644
+index 1d73b15..8066c56 100644
 --- a/drivers/gpu/drm/nouveau/nv04_dac.c
 +++ b/drivers/gpu/drm/nouveau/nv04_dac.c
 @@ -230,13 +230,13 @@ uint32_t nv17_dac_sample_load(struct drm_encoder *encoder)
@@ -5149,8 +5401,31 @@ index 1d73b15..1cb19e3 100644
  	}
  
  	saved_rtest_ctrl = NVReadRAMDAC(dev, 0, NV_PRAMDAC_TEST_CONTROL + regoffset);
+@@ -501,11 +501,13 @@ static const struct drm_encoder_funcs nv04_dac_funcs = {
+ 	.destroy = nv04_dac_destroy,
+ };
+ 
+-int nv04_dac_create(struct drm_device *dev, struct dcb_entry *entry)
++int
++nv04_dac_create(struct drm_connector *connector, struct dcb_entry *entry)
+ {
+ 	const struct drm_encoder_helper_funcs *helper;
+-	struct drm_encoder *encoder;
+ 	struct nouveau_encoder *nv_encoder = NULL;
++	struct drm_device *dev = connector->dev;
++	struct drm_encoder *encoder;
+ 
+ 	nv_encoder = kzalloc(sizeof(*nv_encoder), GFP_KERNEL);
+ 	if (!nv_encoder)
+@@ -527,5 +529,6 @@ int nv04_dac_create(struct drm_device *dev, struct dcb_entry *entry)
+ 	encoder->possible_crtcs = entry->heads;
+ 	encoder->possible_clones = 0;
+ 
++	drm_mode_connector_attach_encoder(connector, encoder);
+ 	return 0;
+ }
 diff --git a/drivers/gpu/drm/nouveau/nv04_dfp.c b/drivers/gpu/drm/nouveau/nv04_dfp.c
-index 483f875..41634d4 100644
+index 483f875..3559d89 100644
 --- a/drivers/gpu/drm/nouveau/nv04_dfp.c
 +++ b/drivers/gpu/drm/nouveau/nv04_dfp.c
 @@ -269,10 +269,10 @@ static void nv04_dfp_mode_set(struct drm_encoder *encoder,
@@ -5166,23 +5441,81 @@ index 483f875..41634d4 100644
  	regp->fp_horiz_regs[FP_SYNC_START] = output_mode->hsync_start - 1;
  	regp->fp_horiz_regs[FP_SYNC_END] = output_mode->hsync_end - 1;
  	regp->fp_horiz_regs[FP_VALID_START] = output_mode->hskew;
+@@ -584,11 +584,12 @@ static const struct drm_encoder_funcs nv04_dfp_funcs = {
+ 	.destroy = nv04_dfp_destroy,
+ };
+ 
+-int nv04_dfp_create(struct drm_device *dev, struct dcb_entry *entry)
++int
++nv04_dfp_create(struct drm_connector *connector, struct dcb_entry *entry)
+ {
+ 	const struct drm_encoder_helper_funcs *helper;
+-	struct drm_encoder *encoder;
+ 	struct nouveau_encoder *nv_encoder = NULL;
++	struct drm_encoder *encoder;
+ 	int type;
+ 
+ 	switch (entry->type) {
+@@ -613,11 +614,12 @@ int nv04_dfp_create(struct drm_device *dev, struct dcb_entry *entry)
+ 	nv_encoder->dcb = entry;
+ 	nv_encoder->or = ffs(entry->or) - 1;
+ 
+-	drm_encoder_init(dev, encoder, &nv04_dfp_funcs, type);
++	drm_encoder_init(connector->dev, encoder, &nv04_dfp_funcs, type);
+ 	drm_encoder_helper_add(encoder, helper);
+ 
+ 	encoder->possible_crtcs = entry->heads;
+ 	encoder->possible_clones = 0;
+ 
++	drm_mode_connector_attach_encoder(connector, encoder);
+ 	return 0;
+ }
 diff --git a/drivers/gpu/drm/nouveau/nv04_display.c b/drivers/gpu/drm/nouveau/nv04_display.c
-index ef77215..c7898b4 100644
+index ef77215..b35b7ed 100644
 --- a/drivers/gpu/drm/nouveau/nv04_display.c
 +++ b/drivers/gpu/drm/nouveau/nv04_display.c
-@@ -93,10 +93,9 @@ int
+@@ -93,10 +93,10 @@ int
  nv04_display_create(struct drm_device *dev)
  {
  	struct drm_nouveau_private *dev_priv = dev->dev_private;
 -	struct parsed_dcb *dcb = dev_priv->vbios->dcb;
 +	struct dcb_table *dcb = &dev_priv->vbios.dcb;
++	struct drm_connector *connector, *ct;
  	struct drm_encoder *encoder;
  	struct drm_crtc *crtc;
 -	uint16_t connector[16] = { 0 };
  	int i, ret;
  
  	NV_DEBUG_KMS(dev, "\n");
-@@ -154,52 +153,10 @@ nv04_display_create(struct drm_device *dev)
+@@ -133,19 +133,23 @@ nv04_display_create(struct drm_device *dev)
+ 	for (i = 0; i < dcb->entries; i++) {
+ 		struct dcb_entry *dcbent = &dcb->entry[i];
+ 
++		connector = nouveau_connector_create(dev, dcbent->connector);
++		if (IS_ERR(connector))
++			continue;
++
+ 		switch (dcbent->type) {
+ 		case OUTPUT_ANALOG:
+-			ret = nv04_dac_create(dev, dcbent);
++			ret = nv04_dac_create(connector, dcbent);
+ 			break;
+ 		case OUTPUT_LVDS:
+ 		case OUTPUT_TMDS:
+-			ret = nv04_dfp_create(dev, dcbent);
++			ret = nv04_dfp_create(connector, dcbent);
+ 			break;
+ 		case OUTPUT_TV:
+ 			if (dcbent->location == DCB_LOC_ON_CHIP)
+-				ret = nv17_tv_create(dev, dcbent);
++				ret = nv17_tv_create(connector, dcbent);
+ 			else
+-				ret = nv04_tv_create(dev, dcbent);
++				ret = nv04_tv_create(connector, dcbent);
+ 			break;
+ 		default:
+ 			NV_WARN(dev, "DCB type %d not known\n", dcbent->type);
+@@ -154,51 +158,15 @@ nv04_display_create(struct drm_device *dev)
  
  		if (ret)
  			continue;
@@ -5228,15 +5561,18 @@ index ef77215..c7898b4 100644
 -		default:
 -			type = DRM_MODE_CONNECTOR_Unknown;
 -			continue;
--		}
++	list_for_each_entry_safe(connector, ct,
++				 &dev->mode_config.connector_list, head) {
++		if (!connector->encoder_ids[0]) {
++			NV_WARN(dev, "%s has no encoders, removing\n",
++				drm_get_connector_name(connector));
++			connector->funcs->destroy(connector);
+ 		}
 -
 -		nouveau_connector_create(dev, dcbent->connector, type);
--	}
-+	for (i = 0; i < dcb->connector.entries; i++)
-+		nouveau_connector_create(dev, &dcb->connector.entry[i]);
+ 	}
  
  	/* Save previous state */
- 	NVLockVgaCrtcs(dev, false);
 diff --git a/drivers/gpu/drm/nouveau/nv04_fbcon.c b/drivers/gpu/drm/nouveau/nv04_fbcon.c
 index fd01caa..813b25c 100644
 --- a/drivers/gpu/drm/nouveau/nv04_fbcon.c
@@ -5307,10 +5643,24 @@ index e260986..f0cbbc0 100644
  }
  
 diff --git a/drivers/gpu/drm/nouveau/nv04_tv.c b/drivers/gpu/drm/nouveau/nv04_tv.c
-index 9c63099..c4e3404 100644
+index 9c63099..84b5954 100644
 --- a/drivers/gpu/drm/nouveau/nv04_tv.c
 +++ b/drivers/gpu/drm/nouveau/nv04_tv.c
-@@ -262,7 +262,7 @@ int nv04_tv_create(struct drm_device *dev, struct dcb_entry *entry)
+@@ -223,10 +223,12 @@ static void nv04_tv_destroy(struct drm_encoder *encoder)
+ 	kfree(nv_encoder);
+ }
+ 
+-int nv04_tv_create(struct drm_device *dev, struct dcb_entry *entry)
++int
++nv04_tv_create(struct drm_connector *connector, struct dcb_entry *entry)
+ {
+ 	struct nouveau_encoder *nv_encoder;
+ 	struct drm_encoder *encoder;
++	struct drm_device *dev = connector->dev;
+ 	struct drm_nouveau_private *dev_priv = dev->dev_private;
+ 	struct i2c_adapter *adap;
+ 	struct drm_encoder_funcs *funcs = NULL;
+@@ -262,11 +264,11 @@ int nv04_tv_create(struct drm_device *dev, struct dcb_entry *entry)
  	nv_encoder->or = ffs(entry->or) - 1;
  
  	/* Run the slave-specific initialization */
@@ -5319,8 +5669,23 @@ index 9c63099..c4e3404 100644
  
  	was_locked = NVLockVgaCrtcs(dev, false);
  
+-	ret = drm_i2c_encoder_init(encoder->dev, to_encoder_slave(encoder), adap,
++	ret = drm_i2c_encoder_init(dev, to_encoder_slave(encoder), adap,
+ 				   &nv04_tv_encoder_info[type].board_info);
+ 
+ 	NVLockVgaCrtcs(dev, was_locked);
+@@ -294,7 +296,9 @@ int nv04_tv_create(struct drm_device *dev, struct dcb_entry *entry)
+ 
+ 	/* Set the slave encoder configuration */
+ 	sfuncs->set_config(encoder, nv04_tv_encoder_info[type].params);
++	sfuncs->create_resources(encoder, connector);
+ 
++	drm_mode_connector_attach_encoder(connector, encoder);
+ 	return 0;
+ 
+ fail:
 diff --git a/drivers/gpu/drm/nouveau/nv17_tv.c b/drivers/gpu/drm/nouveau/nv17_tv.c
-index 21ac6e4..74c8803 100644
+index 21ac6e4..44437ff 100644
 --- a/drivers/gpu/drm/nouveau/nv17_tv.c
 +++ b/drivers/gpu/drm/nouveau/nv17_tv.c
 @@ -45,8 +45,8 @@ static uint32_t nv42_tv_sample_load(struct drm_encoder *encoder)
@@ -5343,6 +5708,26 @@ index 21ac6e4..74c8803 100644
  			}
  		}
  
+@@ -744,8 +744,10 @@ static struct drm_encoder_funcs nv17_tv_funcs = {
+ 	.destroy = nv17_tv_destroy,
+ };
+ 
+-int nv17_tv_create(struct drm_device *dev, struct dcb_entry *entry)
++int
++nv17_tv_create(struct drm_connector *connector, struct dcb_entry *entry)
+ {
++	struct drm_device *dev = connector->dev;
+ 	struct drm_encoder *encoder;
+ 	struct nv17_tv_encoder *tv_enc = NULL;
+ 
+@@ -774,5 +776,7 @@ int nv17_tv_create(struct drm_device *dev, struct dcb_entry *entry)
+ 	encoder->possible_crtcs = entry->heads;
+ 	encoder->possible_clones = 0;
+ 
++	nv17_tv_create_resources(encoder, connector);
++	drm_mode_connector_attach_encoder(connector, encoder);
+ 	return 0;
+ }
 diff --git a/drivers/gpu/drm/nouveau/nv40_fifo.c b/drivers/gpu/drm/nouveau/nv40_fifo.c
 index b4f19cc..500ccfd 100644
 --- a/drivers/gpu/drm/nouveau/nv40_fifo.c
@@ -5416,10 +5801,10 @@ index 53e8afe..0616c96 100644
  		nv40_graph_set_region_tiling(dev, i, 0, 0, 0);
 diff --git a/drivers/gpu/drm/nouveau/nv50_calc.c b/drivers/gpu/drm/nouveau/nv50_calc.c
 new file mode 100644
-index 0000000..90f3f6b
+index 0000000..2cdc2bf
 --- /dev/null
 +++ b/drivers/gpu/drm/nouveau/nv50_calc.c
-@@ -0,0 +1,88 @@
+@@ -0,0 +1,87 @@
 +/*
 + * Copyright 2010 Red Hat Inc.
 + *
@@ -5507,7 +5892,6 @@ index 0000000..90f3f6b
 +
 +	return clk;
 +}
-+
 diff --git a/drivers/gpu/drm/nouveau/nv50_crtc.c b/drivers/gpu/drm/nouveau/nv50_crtc.c
 index d1a651e..03d0e41 100644
 --- a/drivers/gpu/drm/nouveau/nv50_crtc.c
@@ -5573,7 +5957,7 @@ index d1a651e..03d0e41 100644
  
  	return 0;
 diff --git a/drivers/gpu/drm/nouveau/nv50_dac.c b/drivers/gpu/drm/nouveau/nv50_dac.c
-index f08f042..1fd9537 100644
+index f08f042..e114f81 100644
 --- a/drivers/gpu/drm/nouveau/nv50_dac.c
 +++ b/drivers/gpu/drm/nouveau/nv50_dac.c
 @@ -79,8 +79,8 @@ nv50_dac_detect(struct drm_encoder *encoder, struct drm_connector *connector)
@@ -5587,8 +5971,40 @@ index f08f042..1fd9537 100644
  		NV_DEBUG_KMS(dev, "Using bios provided load_pattern of %d\n",
  			  load_pattern);
  	} else {
+@@ -275,14 +275,11 @@ static const struct drm_encoder_funcs nv50_dac_encoder_funcs = {
+ };
+ 
+ int
+-nv50_dac_create(struct drm_device *dev, struct dcb_entry *entry)
++nv50_dac_create(struct drm_connector *connector, struct dcb_entry *entry)
+ {
+ 	struct nouveau_encoder *nv_encoder;
+ 	struct drm_encoder *encoder;
+ 
+-	NV_DEBUG_KMS(dev, "\n");
+-	NV_INFO(dev, "Detected a DAC output\n");
+-
+ 	nv_encoder = kzalloc(sizeof(*nv_encoder), GFP_KERNEL);
+ 	if (!nv_encoder)
+ 		return -ENOMEM;
+@@ -293,12 +290,14 @@ nv50_dac_create(struct drm_device *dev, struct dcb_entry *entry)
+ 
+ 	nv_encoder->disconnect = nv50_dac_disconnect;
+ 
+-	drm_encoder_init(dev, encoder, &nv50_dac_encoder_funcs,
++	drm_encoder_init(connector->dev, encoder, &nv50_dac_encoder_funcs,
+ 			 DRM_MODE_ENCODER_DAC);
+ 	drm_encoder_helper_add(encoder, &nv50_dac_helper_funcs);
+ 
+ 	encoder->possible_crtcs = entry->heads;
+ 	encoder->possible_clones = 0;
++
++	drm_mode_connector_attach_encoder(connector, encoder);
+ 	return 0;
+ }
+ 
 diff --git a/drivers/gpu/drm/nouveau/nv50_display.c b/drivers/gpu/drm/nouveau/nv50_display.c
-index 90f0bf5..2c2ec5f 100644
+index 90f0bf5..a0d7467 100644
 --- a/drivers/gpu/drm/nouveau/nv50_display.c
 +++ b/drivers/gpu/drm/nouveau/nv50_display.c
 @@ -143,7 +143,7 @@ nv50_evo_channel_new(struct drm_device *dev, struct nouveau_channel **pchan)
@@ -5620,17 +6036,37 @@ index 90f0bf5..2c2ec5f 100644
  			continue;
  
  		gpio = nouveau_bios_gpio_entry(dev, conn->dcb->gpio_tag);
-@@ -465,8 +463,7 @@ static int nv50_display_disable(struct drm_device *dev)
+@@ -465,8 +463,8 @@ static int nv50_display_disable(struct drm_device *dev)
  int nv50_display_create(struct drm_device *dev)
  {
  	struct drm_nouveau_private *dev_priv = dev->dev_private;
 -	struct parsed_dcb *dcb = dev_priv->vbios->dcb;
 -	uint32_t connector[16] = {};
 +	struct dcb_table *dcb = &dev_priv->vbios.dcb;
++	struct drm_connector *connector, *ct;
  	int ret, i;
  
  	NV_DEBUG_KMS(dev, "\n");
-@@ -522,49 +519,20 @@ int nv50_display_create(struct drm_device *dev)
+@@ -509,62 +507,39 @@ int nv50_display_create(struct drm_device *dev)
+ 			continue;
+ 		}
+ 
++		connector = nouveau_connector_create(dev, entry->connector);
++		if (IS_ERR(connector))
++			continue;
++
+ 		switch (entry->type) {
+ 		case OUTPUT_TMDS:
+ 		case OUTPUT_LVDS:
+ 		case OUTPUT_DP:
+-			nv50_sor_create(dev, entry);
++			nv50_sor_create(connector, entry);
+ 			break;
+ 		case OUTPUT_ANALOG:
+-			nv50_dac_create(dev, entry);
++			nv50_dac_create(connector, entry);
+ 			break;
+ 		default:
  			NV_WARN(dev, "DCB encoder %d unknown\n", entry->type);
  			continue;
  		}
@@ -5650,10 +6086,7 @@ index 90f0bf5..2c2ec5f 100644
 -
 -		encoders = connector[entry->connector];
 -		if (!(encoders & (1 << entry->type)))
-+	for (i = 0 ; i < dcb->connector.entries; i++) {
-+		if (i != 0 && dcb->connector.entry[i].index2 ==
-+			      dcb->connector.entry[i - 1].index2)
- 			continue;
+-			continue;
 -		connector[entry->connector] = 0;
 -
 -		if (encoders & (1 << OUTPUT_DP)) {
@@ -5669,13 +6102,18 @@ index 90f0bf5..2c2ec5f 100644
 -			type = DRM_MODE_CONNECTOR_LVDS;
 -		} else {
 -			type = DRM_MODE_CONNECTOR_Unknown;
--		}
++	list_for_each_entry_safe(connector, ct,
++				 &dev->mode_config.connector_list, head) {
++		if (!connector->encoder_ids[0]) {
++			NV_WARN(dev, "%s has no encoders, removing\n",
++				drm_get_connector_name(connector));
++			connector->funcs->destroy(connector);
+ 		}
 -
 -		if (type == DRM_MODE_CONNECTOR_Unknown)
 -			continue;
 -
 -		nouveau_connector_create(dev, entry->connector, type);
-+		nouveau_connector_create(dev, &dcb->connector.entry[i]);
  	}
  
  	ret = nv50_display_init(dev);
@@ -5687,7 +6125,7 @@ index 90f0bf5..2c2ec5f 100644
  
  	return 0;
  }
-@@ -667,8 +635,8 @@ nv50_display_irq_head(struct drm_device *dev, int *phead,
+@@ -667,8 +642,8 @@ nv50_display_irq_head(struct drm_device *dev, int *phead,
  		return -1;
  	}
  
@@ -5698,7 +6136,7 @@ index 90f0bf5..2c2ec5f 100644
  
  		if (dcbent->type != type)
  			continue;
-@@ -692,7 +660,7 @@ nv50_display_script_select(struct drm_device *dev, struct dcb_entry *dcbent,
+@@ -692,7 +667,7 @@ nv50_display_script_select(struct drm_device *dev, struct dcb_entry *dcbent,
  	struct drm_nouveau_private *dev_priv = dev->dev_private;
  	struct nouveau_connector *nv_connector = NULL;
  	struct drm_encoder *encoder;
@@ -5707,7 +6145,7 @@ index 90f0bf5..2c2ec5f 100644
  	uint32_t mc, script = 0, or;
  
  	list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) {
-@@ -710,7 +678,7 @@ nv50_display_script_select(struct drm_device *dev, struct dcb_entry *dcbent,
+@@ -710,7 +685,7 @@ nv50_display_script_select(struct drm_device *dev, struct dcb_entry *dcbent,
  	switch (dcbent->type) {
  	case OUTPUT_LVDS:
  		script = (mc >> 8) & 0xf;
@@ -5716,7 +6154,7 @@ index 90f0bf5..2c2ec5f 100644
  			if (bios->fp.dual_link)
  				script |= 0x0100;
  			if (bios->fp.if_is_24bit)
-@@ -815,6 +783,37 @@ ack:
+@@ -815,6 +790,37 @@ ack:
  }
  
  static void
@@ -5754,7 +6192,7 @@ index 90f0bf5..2c2ec5f 100644
  nv50_display_unk20_handler(struct drm_device *dev)
  {
  	struct dcb_entry *dcbent;
-@@ -837,6 +836,8 @@ nv50_display_unk20_handler(struct drm_device *dev)
+@@ -837,6 +843,8 @@ nv50_display_unk20_handler(struct drm_device *dev)
  
  	nouveau_bios_run_display_table(dev, dcbent, script, pclk);
  
@@ -5763,7 +6201,7 @@ index 90f0bf5..2c2ec5f 100644
  	tmp = nv_rd32(dev, NV50_PDISPLAY_CRTC_CLK_CTRL2(head));
  	tmp &= ~0x000000f;
  	nv_wr32(dev, NV50_PDISPLAY_CRTC_CLK_CTRL2(head), tmp);
-@@ -919,10 +920,12 @@ nv50_display_error_handler(struct drm_device *dev)
+@@ -919,10 +927,12 @@ nv50_display_error_handler(struct drm_device *dev)
  	nv_wr32(dev, NV50_PDISPLAY_TRAPPED_ADDR, 0x90000000);
  }
  
@@ -5779,7 +6217,7 @@ index 90f0bf5..2c2ec5f 100644
  	struct drm_connector *connector;
  	const uint32_t gpio_reg[4] = { 0xe104, 0xe108, 0xe280, 0xe284 };
  	uint32_t unplug_mask, plug_mask, change_mask;
-@@ -975,6 +978,8 @@ nv50_display_irq_hotplug(struct drm_device *dev)
+@@ -975,6 +985,8 @@ nv50_display_irq_hotplug(struct drm_device *dev)
  	nv_wr32(dev, 0xe054, nv_rd32(dev, 0xe054));
  	if (dev_priv->chipset >= 0x90)
  		nv_wr32(dev, 0xe074, nv_rd32(dev, 0xe074));
@@ -5788,7 +6226,7 @@ index 90f0bf5..2c2ec5f 100644
  }
  
  void
-@@ -983,8 +988,10 @@ nv50_display_irq_handler(struct drm_device *dev)
+@@ -983,8 +995,10 @@ nv50_display_irq_handler(struct drm_device *dev)
  	struct drm_nouveau_private *dev_priv = dev->dev_private;
  	uint32_t delayed = 0;
  
@@ -8653,7 +9091,7 @@ index f0dc4e3..5f21df3 100644
  		return -EINVAL;
  
 diff --git a/drivers/gpu/drm/nouveau/nv50_sor.c b/drivers/gpu/drm/nouveau/nv50_sor.c
-index c2fff54..812778d 100644
+index c2fff54..4832bba 100644
 --- a/drivers/gpu/drm/nouveau/nv50_sor.c
 +++ b/drivers/gpu/drm/nouveau/nv50_sor.c
 @@ -211,7 +211,7 @@ nv50_sor_mode_set(struct drm_encoder *encoder, struct drm_display_mode *mode,
@@ -8665,7 +9103,43 @@ index c2fff54..812778d 100644
  		if (nv_encoder->dcb->sorconf.link & 1)
  			mode_ctl |= 0x00000800;
  		else
-@@ -319,5 +319,28 @@ nv50_sor_create(struct drm_device *dev, struct dcb_entry *entry)
+@@ -272,32 +272,22 @@ static const struct drm_encoder_funcs nv50_sor_encoder_funcs = {
+ };
+ 
+ int
+-nv50_sor_create(struct drm_device *dev, struct dcb_entry *entry)
++nv50_sor_create(struct drm_connector *connector, struct dcb_entry *entry)
+ {
+ 	struct nouveau_encoder *nv_encoder = NULL;
++	struct drm_device *dev = connector->dev;
+ 	struct drm_encoder *encoder;
+-	bool dum;
+ 	int type;
+ 
+ 	NV_DEBUG_KMS(dev, "\n");
+ 
+ 	switch (entry->type) {
+ 	case OUTPUT_TMDS:
+-		NV_INFO(dev, "Detected a TMDS output\n");
++	case OUTPUT_DP:
+ 		type = DRM_MODE_ENCODER_TMDS;
+ 		break;
+ 	case OUTPUT_LVDS:
+-		NV_INFO(dev, "Detected a LVDS output\n");
+ 		type = DRM_MODE_ENCODER_LVDS;
+-
+-		if (nouveau_bios_parse_lvds_table(dev, 0, &dum, &dum)) {
+-			NV_ERROR(dev, "Failed parsing LVDS table\n");
+-			return -EINVAL;
+-		}
+-		break;
+-	case OUTPUT_DP:
+-		NV_INFO(dev, "Detected a DP output\n");
+-		type = DRM_MODE_ENCODER_TMDS;
+ 		break;
+ 	default:
+ 		return -EINVAL;
+@@ -319,5 +309,29 @@ nv50_sor_create(struct drm_device *dev, struct dcb_entry *entry)
  	encoder->possible_crtcs = entry->heads;
  	encoder->possible_clones = 0;
  
@@ -8692,8 +9166,9 @@ index c2fff54..812778d 100644
 +			nv_encoder->dp.mc_unknown = 5;
 +	}
 +
++	drm_mode_connector_attach_encoder(connector, encoder);
  	return 0;
  }
 -- 
-1.7.0.1
+1.7.1
 


Index: kernel.spec
===================================================================
RCS file: /cvs/pkgs/rpms/kernel/F-13/kernel.spec,v
retrieving revision 1.2078
retrieving revision 1.2079
diff -u -p -r1.2078 -r1.2079
--- kernel.spec	2 Jul 2010 00:57:47 -0000	1.2078
+++ kernel.spec	2 Jul 2010 05:47:01 -0000	1.2079
@@ -2214,6 +2214,9 @@ fi
 # and build.
 
 %changelog
+* Fri Jul 02 2010 Ben Skeggs <bskeggs at redhat.com> 2.6.33.6-142.rc1
+- nouveau: fix connector ordering issues (rhbz#602492)
+
 * Fri Jul 02 2010 Chuck Ebbert <cebbert at redhat.com> 2.6.33.6-141.rc1
 - Linux 2.6.33.6-rc1
 - Drop patches merged upstream:



More information about the scm-commits mailing list