diff --git a/drivers/gpu/drm/nouveau/core/core/mm.c b/drivers/gpu/drm/nouveau/core/core/mm.c
index 4d6206448670154deaeed940e0eb44993024fea9..a6d3cd6490f7fa97f171dff724f73430364af89f 100644
--- a/drivers/gpu/drm/nouveau/core/core/mm.c
+++ b/drivers/gpu/drm/nouveau/core/core/mm.c
@@ -218,13 +218,16 @@ nouveau_mm_init(struct nouveau_mm *mm, u32 offset, u32 length, u32 block)
 	node = kzalloc(sizeof(*node), GFP_KERNEL);
 	if (!node)
 		return -ENOMEM;
-	node->offset = roundup(offset, mm->block_size);
-	node->length = rounddown(offset + length, mm->block_size) - node->offset;
+
+	if (length) {
+		node->offset  = roundup(offset, mm->block_size);
+		node->length  = rounddown(offset + length, mm->block_size);
+		node->length -= node->offset;
+	}
 
 	list_add_tail(&node->nl_entry, &mm->nodes);
 	list_add_tail(&node->fl_entry, &mm->free);
 	mm->heap_nodes++;
-	mm->heap_size += length;
 	return 0;
 }
 
diff --git a/drivers/gpu/drm/nouveau/core/include/core/mm.h b/drivers/gpu/drm/nouveau/core/include/core/mm.h
index 9ee9bf4028ca168800bc2c6fbcac96346aad9024..975137ba34a6faefb7d4121b8db2efd3464a28c6 100644
--- a/drivers/gpu/drm/nouveau/core/include/core/mm.h
+++ b/drivers/gpu/drm/nouveau/core/include/core/mm.h
@@ -19,7 +19,6 @@ struct nouveau_mm {
 
 	u32 block_size;
 	int heap_nodes;
-	u32 heap_size;
 };
 
 int  nouveau_mm_init(struct nouveau_mm *, u32 offset, u32 length, u32 block);
diff --git a/drivers/gpu/drm/nouveau/core/subdev/fb/nv50.c b/drivers/gpu/drm/nouveau/core/subdev/fb/nv50.c
index 27fb1af7a779b2a0add14ab0462cb060d6e4d8d7..5f570806143ad0fb35fcd67017acf07513b563e4 100644
--- a/drivers/gpu/drm/nouveau/core/subdev/fb/nv50.c
+++ b/drivers/gpu/drm/nouveau/core/subdev/fb/nv50.c
@@ -219,13 +219,11 @@ nv50_fb_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
 			     ((priv->base.ram.size & 0x000000ff) << 32);
 
 	tags = nv_rd32(priv, 0x100320);
-	if (tags) {
-		ret = nouveau_mm_init(&priv->base.tags, 0, tags, 1);
-		if (ret)
-			return ret;
+	ret = nouveau_mm_init(&priv->base.tags, 0, tags, 1);
+	if (ret)
+		return ret;
 
-		nv_debug(priv, "%d compression tags\n", tags);
-	}
+	nv_debug(priv, "%d compression tags\n", tags);
 
 	size = (priv->base.ram.size >> 12) - rsvd_head - rsvd_tail;
 	switch (device->chipset) {
diff --git a/drivers/gpu/drm/nouveau/core/subdev/i2c/base.c b/drivers/gpu/drm/nouveau/core/subdev/i2c/base.c
index 3d2c88310f982553380f19a7f89d5379a89a5d01..dbfc2abf0cfe1a98379a567fa8a7a90fcd409d5f 100644
--- a/drivers/gpu/drm/nouveau/core/subdev/i2c/base.c
+++ b/drivers/gpu/drm/nouveau/core/subdev/i2c/base.c
@@ -292,7 +292,7 @@ nouveau_i2c_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
 		case DCB_I2C_NVIO_BIT:
 			port->drive = info.drive & 0x0f;
 			if (device->card_type < NV_D0) {
-				if (info.drive >= ARRAY_SIZE(nv50_i2c_port))
+				if (port->drive >= ARRAY_SIZE(nv50_i2c_port))
 					break;
 				port->drive = nv50_i2c_port[port->drive];
 				port->sense = port->drive;
diff --git a/drivers/gpu/drm/nouveau/nouveau_display.c b/drivers/gpu/drm/nouveau/nouveau_display.c
index d2f8ffeed742c54ae5a3d85d2f806f41e66d3a9d..86124b131f4f31a2ca18e8c2416084ad6df1f585 100644
--- a/drivers/gpu/drm/nouveau/nouveau_display.c
+++ b/drivers/gpu/drm/nouveau/nouveau_display.c
@@ -290,6 +290,7 @@ nouveau_display_create(struct drm_device *dev)
 	struct nouveau_drm *drm = nouveau_drm(dev);
 	struct nouveau_disp *pdisp = nouveau_disp(drm->device);
 	struct nouveau_display *disp;
+	u32 pclass = dev->pdev->class >> 8;
 	int ret, gen;
 
 	disp = drm->display = kzalloc(sizeof(*disp), GFP_KERNEL);
@@ -360,23 +361,27 @@ nouveau_display_create(struct drm_device *dev)
 	drm_kms_helper_poll_init(dev);
 	drm_kms_helper_poll_disable(dev);
 
-	if (nv_device(drm->device)->card_type < NV_50)
-		ret = nv04_display_create(dev);
-	else
-	if (nv_device(drm->device)->card_type < NV_D0)
-		ret = nv50_display_create(dev);
-	else
-		ret = nvd0_display_create(dev);
-	if (ret)
-		goto disp_create_err;
-
-	if (dev->mode_config.num_crtc) {
-		ret = drm_vblank_init(dev, dev->mode_config.num_crtc);
+	if (nouveau_modeset == 1 ||
+	    (nouveau_modeset < 0 && pclass == PCI_CLASS_DISPLAY_VGA)) {
+		if (nv_device(drm->device)->card_type < NV_50)
+			ret = nv04_display_create(dev);
+		else
+		if (nv_device(drm->device)->card_type < NV_D0)
+			ret = nv50_display_create(dev);
+		else
+			ret = nvd0_display_create(dev);
 		if (ret)
-			goto vblank_err;
+			goto disp_create_err;
+
+		if (dev->mode_config.num_crtc) {
+			ret = drm_vblank_init(dev, dev->mode_config.num_crtc);
+			if (ret)
+				goto vblank_err;
+		}
+
+		nouveau_backlight_init(dev);
 	}
 
-	nouveau_backlight_init(dev);
 	return 0;
 
 vblank_err:
@@ -395,7 +400,8 @@ nouveau_display_destroy(struct drm_device *dev)
 	nouveau_backlight_exit(dev);
 	drm_vblank_cleanup(dev);
 
-	disp->dtor(dev);
+	if (disp->dtor)
+		disp->dtor(dev);
 
 	drm_kms_helper_poll_fini(dev);
 	drm_mode_config_cleanup(dev);
diff --git a/drivers/gpu/drm/nouveau/nouveau_drm.c b/drivers/gpu/drm/nouveau/nouveau_drm.c
index ccae8c26ae2b34ecc25e8312ee6d57c0d14f06e3..0910125cbbc3be3cfa757f0976f3afea8cac6a21 100644
--- a/drivers/gpu/drm/nouveau/nouveau_drm.c
+++ b/drivers/gpu/drm/nouveau/nouveau_drm.c
@@ -63,8 +63,9 @@ MODULE_PARM_DESC(noaccel, "disable kernel/abi16 acceleration");
 static int nouveau_noaccel = 0;
 module_param_named(noaccel, nouveau_noaccel, int, 0400);
 
-MODULE_PARM_DESC(modeset, "enable driver");
-static int nouveau_modeset = -1;
+MODULE_PARM_DESC(modeset, "enable driver (default: auto, "
+		          "0 = disabled, 1 = enabled, 2 = headless)");
+int nouveau_modeset = -1;
 module_param_named(modeset, nouveau_modeset, int, 0400);
 
 static struct drm_driver driver;
@@ -363,7 +364,8 @@ nouveau_drm_unload(struct drm_device *dev)
 
 	nouveau_pm_fini(dev);
 
-	nouveau_display_fini(dev);
+	if (dev->mode_config.num_crtc)
+		nouveau_display_fini(dev);
 	nouveau_display_destroy(dev);
 
 	nouveau_irq_fini(dev);
@@ -403,13 +405,15 @@ nouveau_drm_suspend(struct pci_dev *pdev, pm_message_t pm_state)
 	    pm_state.event == PM_EVENT_PRETHAW)
 		return 0;
 
-	NV_INFO(drm, "suspending fbcon...\n");
-	nouveau_fbcon_set_suspend(dev, 1);
+	if (dev->mode_config.num_crtc) {
+		NV_INFO(drm, "suspending fbcon...\n");
+		nouveau_fbcon_set_suspend(dev, 1);
 
-	NV_INFO(drm, "suspending display...\n");
-	ret = nouveau_display_suspend(dev);
-	if (ret)
-		return ret;
+		NV_INFO(drm, "suspending display...\n");
+		ret = nouveau_display_suspend(dev);
+		if (ret)
+			return ret;
+	}
 
 	NV_INFO(drm, "evicting buffers...\n");
 	ttm_bo_evict_mm(&drm->ttm.bdev, TTM_PL_VRAM);
@@ -445,8 +449,10 @@ nouveau_drm_suspend(struct pci_dev *pdev, pm_message_t pm_state)
 		nouveau_client_init(&cli->base);
 	}
 
-	NV_INFO(drm, "resuming display...\n");
-	nouveau_display_resume(dev);
+	if (dev->mode_config.num_crtc) {
+		NV_INFO(drm, "resuming display...\n");
+		nouveau_display_resume(dev);
+	}
 	return ret;
 }
 
@@ -486,8 +492,10 @@ nouveau_drm_resume(struct pci_dev *pdev)
 	nouveau_irq_postinstall(dev);
 	nouveau_pm_resume(dev);
 
-	NV_INFO(drm, "resuming display...\n");
-	nouveau_display_resume(dev);
+	if (dev->mode_config.num_crtc) {
+		NV_INFO(drm, "resuming display...\n");
+		nouveau_display_resume(dev);
+	}
 	return 0;
 }
 
@@ -662,9 +670,7 @@ nouveau_drm_init(void)
 #ifdef CONFIG_VGA_CONSOLE
 		if (vgacon_text_force())
 			nouveau_modeset = 0;
-		else
 #endif
-			nouveau_modeset = 1;
 	}
 
 	if (!nouveau_modeset)
diff --git a/drivers/gpu/drm/nouveau/nouveau_drm.h b/drivers/gpu/drm/nouveau/nouveau_drm.h
index 819471217546b23cb867e3e583ed856d5d810ea2..a10169927086dfea6c826dac0378ae1d2c82ffb3 100644
--- a/drivers/gpu/drm/nouveau/nouveau_drm.h
+++ b/drivers/gpu/drm/nouveau/nouveau_drm.h
@@ -141,4 +141,6 @@ int nouveau_drm_resume(struct pci_dev *);
 		nv_info((cli), fmt, ##args);                                   \
 } while (0)
 
+extern int nouveau_modeset;
+
 #endif
diff --git a/drivers/gpu/drm/nouveau/nouveau_irq.c b/drivers/gpu/drm/nouveau/nouveau_irq.c
index 9ca8afdb5549777c7a2b25e64de9b63f700260bc..1d8cb506a28ae5159ebe4c9df362f3f0d92d7758 100644
--- a/drivers/gpu/drm/nouveau/nouveau_irq.c
+++ b/drivers/gpu/drm/nouveau/nouveau_irq.c
@@ -61,13 +61,15 @@ nouveau_irq_handler(DRM_IRQ_ARGS)
 
 	nv_subdev(pmc)->intr(nv_subdev(pmc));
 
-	if (device->card_type >= NV_D0) {
-		if (nv_rd32(device, 0x000100) & 0x04000000)
-			nvd0_display_intr(dev);
-	} else
-	if (device->card_type >= NV_50) {
-		if (nv_rd32(device, 0x000100) & 0x04000000)
-			nv50_display_intr(dev);
+	if (dev->mode_config.num_crtc) {
+		if (device->card_type >= NV_D0) {
+			if (nv_rd32(device, 0x000100) & 0x04000000)
+				nvd0_display_intr(dev);
+		} else
+		if (device->card_type >= NV_50) {
+			if (nv_rd32(device, 0x000100) & 0x04000000)
+				nv50_display_intr(dev);
+		}
 	}
 
 	return IRQ_HANDLED;
diff --git a/drivers/gpu/drm/nouveau/nv04_dac.c b/drivers/gpu/drm/nouveau/nv04_dac.c
index 347a3bd78d0486f1fed24f11d8183f9382d822dd..64f7020fb605dcaff92163aa161d174ad0d77a23 100644
--- a/drivers/gpu/drm/nouveau/nv04_dac.c
+++ b/drivers/gpu/drm/nouveau/nv04_dac.c
@@ -220,7 +220,7 @@ static enum drm_connector_status nv04_dac_detect(struct drm_encoder *encoder,
 	NVWriteVgaCrtc(dev, 0, NV_CIO_CR_MODE_INDEX, saved_cr_mode);
 
 	if (blue == 0x18) {
-		NV_INFO(drm, "Load detected on head A\n");
+		NV_DEBUG(drm, "Load detected on head A\n");
 		return connector_status_connected;
 	}
 
@@ -338,8 +338,8 @@ nv17_dac_detect(struct drm_encoder *encoder, struct drm_connector *connector)
 
 	if (nv17_dac_sample_load(encoder) &
 	    NV_PRAMDAC_TEST_CONTROL_SENSEB_ALLHI) {
-		NV_INFO(drm, "Load detected on output %c\n",
-			'@' + ffs(dcb->or));
+		NV_DEBUG(drm, "Load detected on output %c\n",
+			 '@' + ffs(dcb->or));
 		return connector_status_connected;
 	} else {
 		return connector_status_disconnected;
@@ -413,9 +413,9 @@ static void nv04_dac_commit(struct drm_encoder *encoder)
 
 	helper->dpms(encoder, DRM_MODE_DPMS_ON);
 
-	NV_INFO(drm, "Output %s is running on CRTC %d using output %c\n",
-		drm_get_connector_name(&nouveau_encoder_connector_get(nv_encoder)->base),
-		nv_crtc->index, '@' + ffs(nv_encoder->dcb->or));
+	NV_DEBUG(drm, "Output %s is running on CRTC %d using output %c\n",
+		 drm_get_connector_name(&nouveau_encoder_connector_get(nv_encoder)->base),
+		 nv_crtc->index, '@' + ffs(nv_encoder->dcb->or));
 }
 
 void nv04_dac_update_dacclk(struct drm_encoder *encoder, bool enable)
@@ -461,8 +461,8 @@ static void nv04_dac_dpms(struct drm_encoder *encoder, int mode)
 		return;
 	nv_encoder->last_dpms = mode;
 
-	NV_INFO(drm, "Setting dpms mode %d on vga encoder (output %d)\n",
-		     mode, nv_encoder->dcb->index);
+	NV_DEBUG(drm, "Setting dpms mode %d on vga encoder (output %d)\n",
+		 mode, nv_encoder->dcb->index);
 
 	nv04_dac_update_dacclk(encoder, mode == DRM_MODE_DPMS_ON);
 }
diff --git a/drivers/gpu/drm/nouveau/nv04_dfp.c b/drivers/gpu/drm/nouveau/nv04_dfp.c
index da55d7642c8cdd325ccca35bd8a1d1b1c1bda8f5..184cdf806761c0bc0cefb52af00a8799ae8e6393 100644
--- a/drivers/gpu/drm/nouveau/nv04_dfp.c
+++ b/drivers/gpu/drm/nouveau/nv04_dfp.c
@@ -476,9 +476,9 @@ static void nv04_dfp_commit(struct drm_encoder *encoder)
 
 	helper->dpms(encoder, DRM_MODE_DPMS_ON);
 
-	NV_INFO(drm, "Output %s is running on CRTC %d using output %c\n",
-		drm_get_connector_name(&nouveau_encoder_connector_get(nv_encoder)->base),
-		nv_crtc->index, '@' + ffs(nv_encoder->dcb->or));
+	NV_DEBUG(drm, "Output %s is running on CRTC %d using output %c\n",
+		 drm_get_connector_name(&nouveau_encoder_connector_get(nv_encoder)->base),
+		 nv_crtc->index, '@' + ffs(nv_encoder->dcb->or));
 }
 
 static void nv04_dfp_update_backlight(struct drm_encoder *encoder, int mode)
@@ -520,8 +520,8 @@ static void nv04_lvds_dpms(struct drm_encoder *encoder, int mode)
 		return;
 	nv_encoder->last_dpms = mode;
 
-	NV_INFO(drm, "Setting dpms mode %d on lvds encoder (output %d)\n",
-		     mode, nv_encoder->dcb->index);
+	NV_DEBUG(drm, "Setting dpms mode %d on lvds encoder (output %d)\n",
+		 mode, nv_encoder->dcb->index);
 
 	if (was_powersaving && is_powersaving_dpms(mode))
 		return;
@@ -565,8 +565,8 @@ static void nv04_tmds_dpms(struct drm_encoder *encoder, int mode)
 		return;
 	nv_encoder->last_dpms = mode;
 
-	NV_INFO(drm, "Setting dpms mode %d on tmds encoder (output %d)\n",
-		     mode, nv_encoder->dcb->index);
+	NV_DEBUG(drm, "Setting dpms mode %d on tmds encoder (output %d)\n",
+		 mode, nv_encoder->dcb->index);
 
 	nv04_dfp_update_backlight(encoder, mode);
 	nv04_dfp_update_fp_control(encoder, mode);
diff --git a/drivers/gpu/drm/nouveau/nv04_tv.c b/drivers/gpu/drm/nouveau/nv04_tv.c
index 099fbeda6e2e18f85b7dedbc961582516729b50a..62e826a139b3bd4b08d00a0ca46e0efc59c62d63 100644
--- a/drivers/gpu/drm/nouveau/nv04_tv.c
+++ b/drivers/gpu/drm/nouveau/nv04_tv.c
@@ -75,8 +75,8 @@ static void nv04_tv_dpms(struct drm_encoder *encoder, int mode)
 	struct nv04_mode_state *state = &nv04_display(dev)->mode_reg;
 	uint8_t crtc1A;
 
-	NV_INFO(drm, "Setting dpms mode %d on TV encoder (output %d)\n",
-		mode, nv_encoder->dcb->index);
+	NV_DEBUG(drm, "Setting dpms mode %d on TV encoder (output %d)\n",
+		 mode, nv_encoder->dcb->index);
 
 	state->pllsel &= ~(PLLSEL_TV_CRTC1_MASK | PLLSEL_TV_CRTC2_MASK);
 
@@ -167,9 +167,8 @@ static void nv04_tv_commit(struct drm_encoder *encoder)
 
 	helper->dpms(encoder, DRM_MODE_DPMS_ON);
 
-	NV_INFO(drm, "Output %s is running on CRTC %d using output %c\n",
-		      drm_get_connector_name(&nouveau_encoder_connector_get(nv_encoder)->base), nv_crtc->index,
-		      '@' + ffs(nv_encoder->dcb->or));
+	NV_DEBUG(drm, "Output %s is running on CRTC %d using output %c\n",
+		 drm_get_connector_name(&nouveau_encoder_connector_get(nv_encoder)->base), nv_crtc->index, '@' + ffs(nv_encoder->dcb->or));
 }
 
 static void nv04_tv_destroy(struct drm_encoder *encoder)