diff --git a/drivers/gpu/drm/nouveau/nouveau_display.c b/drivers/gpu/drm/nouveau/nouveau_display.c
index f8042433752b..f972e9c1a23a 100644
--- a/drivers/gpu/drm/nouveau/nouveau_display.c
+++ b/drivers/gpu/drm/nouveau/nouveau_display.c
@@ -570,7 +570,8 @@ nouveau_display_suspend(struct drm_device *dev, bool runtime)
 	list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
 		struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc);
 		if (nv_crtc->cursor.nvbo) {
-			nouveau_bo_unmap(nv_crtc->cursor.nvbo);
+			if (nv_crtc->cursor.set_offset)
+				nouveau_bo_unmap(nv_crtc->cursor.nvbo);
 			nouveau_bo_unpin(nv_crtc->cursor.nvbo);
 		}
 	}
@@ -604,7 +605,7 @@ nouveau_display_resume(struct drm_device *dev, bool runtime)
 			continue;
 
 		ret = nouveau_bo_pin(nv_crtc->cursor.nvbo, TTM_PL_FLAG_VRAM, true);
-		if (!ret)
+		if (!ret && nv_crtc->cursor.set_offset)
 			ret = nouveau_bo_map(nv_crtc->cursor.nvbo);
 		if (ret)
 			NV_ERROR(drm, "Could not pin/map cursor.\n");
@@ -637,7 +638,9 @@ nouveau_display_resume(struct drm_device *dev, bool runtime)
 
 		if (!nv_crtc->cursor.nvbo)
 			continue;
-		nv_crtc->cursor.set_offset(nv_crtc, nv_crtc->cursor.nvbo->bo.offset);
+
+		if (nv_crtc->cursor.set_offset)
+			nv_crtc->cursor.set_offset(nv_crtc, nv_crtc->cursor.nvbo->bo.offset);
 		nv_crtc->cursor.set_pos(nv_crtc, nv_crtc->cursor_saved_x,
 						 nv_crtc->cursor_saved_y);
 	}
diff --git a/drivers/gpu/drm/nouveau/nouveau_fbcon.c b/drivers/gpu/drm/nouveau/nouveau_fbcon.c
index 3ed12a8cfc91..d6e6958bc5f8 100644
--- a/drivers/gpu/drm/nouveau/nouveau_fbcon.c
+++ b/drivers/gpu/drm/nouveau/nouveau_fbcon.c
@@ -370,6 +370,7 @@ nouveau_fbcon_create(struct drm_fb_helper *helper,
 		ret = -ENOMEM;
 		goto out_unlock;
 	}
+	info->skip_vt_switch = 1;
 
 	ret = fb_alloc_cmap(&info->cmap, 256, 0);
 	if (ret) {
@@ -487,30 +488,17 @@ static const struct drm_fb_helper_funcs nouveau_fbcon_helper_funcs = {
 	.fb_probe = nouveau_fbcon_create,
 };
 
-static void
-nouveau_fbcon_set_suspend_work(struct work_struct *work)
-{
-	struct nouveau_fbdev *fbcon = container_of(work, typeof(*fbcon), work);
-	console_lock();
-	nouveau_fbcon_accel_restore(fbcon->dev);
-	nouveau_fbcon_zfill(fbcon->dev, fbcon);
-	fb_set_suspend(fbcon->helper.fbdev, FBINFO_STATE_RUNNING);
-	console_unlock();
-}
-
 void
 nouveau_fbcon_set_suspend(struct drm_device *dev, int state)
 {
 	struct nouveau_drm *drm = nouveau_drm(dev);
 	if (drm->fbcon) {
-		if (state == FBINFO_STATE_RUNNING) {
-			schedule_work(&drm->fbcon->work);
-			return;
-		}
-		flush_work(&drm->fbcon->work);
 		console_lock();
+		if (state == FBINFO_STATE_RUNNING)
+			nouveau_fbcon_accel_restore(dev);
 		fb_set_suspend(drm->fbcon->helper.fbdev, state);
-		nouveau_fbcon_accel_save_disable(dev);
+		if (state != FBINFO_STATE_RUNNING)
+			nouveau_fbcon_accel_save_disable(dev);
 		console_unlock();
 	}
 }
@@ -531,7 +519,6 @@ nouveau_fbcon_init(struct drm_device *dev)
 	if (!fbcon)
 		return -ENOMEM;
 
-	INIT_WORK(&fbcon->work, nouveau_fbcon_set_suspend_work);
 	fbcon->dev = dev;
 	drm->fbcon = fbcon;
 
diff --git a/drivers/gpu/drm/nouveau/nouveau_fbcon.h b/drivers/gpu/drm/nouveau/nouveau_fbcon.h
index 6208e70e4a1c..1e2e9e27a03b 100644
--- a/drivers/gpu/drm/nouveau/nouveau_fbcon.h
+++ b/drivers/gpu/drm/nouveau/nouveau_fbcon.h
@@ -36,7 +36,6 @@ struct nouveau_fbdev {
 	struct nouveau_framebuffer nouveau_fb;
 	struct list_head fbdev_list;
 	struct drm_device *dev;
-	struct work_struct work;
 	unsigned int saved_flags;
 	struct nvif_object surf2d;
 	struct nvif_object clip;
diff --git a/drivers/gpu/drm/nouveau/nv50_display.c b/drivers/gpu/drm/nouveau/nv50_display.c
index 490b90866baf..038b0fe06db8 100644
--- a/drivers/gpu/drm/nouveau/nv50_display.c
+++ b/drivers/gpu/drm/nouveau/nv50_display.c
@@ -125,7 +125,6 @@ nv50_pioc_create(struct nvif_object *disp, const u32 *oclass, u8 head,
 
 struct nv50_curs {
 	struct nv50_pioc base;
-	struct nouveau_bo *image;
 };
 
 static int
@@ -917,29 +916,29 @@ static void
 nv50_crtc_cursor_show(struct nouveau_crtc *nv_crtc)
 {
 	struct nv50_mast *mast = nv50_mast(nv_crtc->base.dev);
-	struct nv50_curs *curs = nv50_curs(&nv_crtc->base);
 	u32 *push = evo_wait(mast, 16);
 	if (push) {
 		if (nv50_vers(mast) < G82_DISP_CORE_CHANNEL_DMA) {
 			evo_mthd(push, 0x0880 + (nv_crtc->index * 0x400), 2);
 			evo_data(push, 0x85000000);
-			evo_data(push, curs->image->bo.offset >> 8);
+			evo_data(push, nv_crtc->cursor.nvbo->bo.offset >> 8);
 		} else
 		if (nv50_vers(mast) < GF110_DISP_CORE_CHANNEL_DMA) {
 			evo_mthd(push, 0x0880 + (nv_crtc->index * 0x400), 2);
 			evo_data(push, 0x85000000);
-			evo_data(push, curs->image->bo.offset >> 8);
+			evo_data(push, nv_crtc->cursor.nvbo->bo.offset >> 8);
 			evo_mthd(push, 0x089c + (nv_crtc->index * 0x400), 1);
 			evo_data(push, mast->base.vram.handle);
 		} else {
 			evo_mthd(push, 0x0480 + (nv_crtc->index * 0x300), 2);
 			evo_data(push, 0x85000000);
-			evo_data(push, curs->image->bo.offset >> 8);
+			evo_data(push, nv_crtc->cursor.nvbo->bo.offset >> 8);
 			evo_mthd(push, 0x048c + (nv_crtc->index * 0x300), 1);
 			evo_data(push, mast->base.vram.handle);
 		}
 		evo_kick(push, mast);
 	}
+	nv_crtc->cursor.visible = true;
 }
 
 static void
@@ -965,15 +964,15 @@ nv50_crtc_cursor_hide(struct nouveau_crtc *nv_crtc)
 		}
 		evo_kick(push, mast);
 	}
+	nv_crtc->cursor.visible = false;
 }
 
 static void
 nv50_crtc_cursor_show_hide(struct nouveau_crtc *nv_crtc, bool show, bool update)
 {
 	struct nv50_mast *mast = nv50_mast(nv_crtc->base.dev);
-	struct nv50_curs *curs = nv50_curs(&nv_crtc->base);
 
-	if (show && curs->image)
+	if (show && nv_crtc->cursor.nvbo)
 		nv50_crtc_cursor_show(nv_crtc);
 	else
 		nv50_crtc_cursor_hide(nv_crtc);
@@ -1273,7 +1272,6 @@ nv50_crtc_cursor_set(struct drm_crtc *crtc, struct drm_file *file_priv,
 		     uint32_t handle, uint32_t width, uint32_t height)
 {
 	struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc);
-	struct nv50_curs *curs = nv50_curs(crtc);
 	struct drm_device *dev = crtc->dev;
 	struct drm_gem_object *gem = NULL;
 	struct nouveau_bo *nvbo = NULL;
@@ -1292,9 +1290,9 @@ nv50_crtc_cursor_set(struct drm_crtc *crtc, struct drm_file *file_priv,
 	}
 
 	if (ret == 0) {
-		if (curs->image)
-			nouveau_bo_unpin(curs->image);
-		nouveau_bo_ref(nvbo, &curs->image);
+		if (nv_crtc->cursor.nvbo)
+			nouveau_bo_unpin(nv_crtc->cursor.nvbo);
+		nouveau_bo_ref(nvbo, &nv_crtc->cursor.nvbo);
 	}
 	drm_gem_object_unreference_unlocked(gem);
 
@@ -1305,10 +1303,14 @@ nv50_crtc_cursor_set(struct drm_crtc *crtc, struct drm_file *file_priv,
 static int
 nv50_crtc_cursor_move(struct drm_crtc *crtc, int x, int y)
 {
+	struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc);
 	struct nv50_curs *curs = nv50_curs(crtc);
 	struct nv50_chan *chan = nv50_chan(curs);
 	nvif_wr32(&chan->user, 0x0084, (y << 16) | (x & 0xffff));
 	nvif_wr32(&chan->user, 0x0080, 0x00000000);
+
+	nv_crtc->cursor_saved_x = x;
+	nv_crtc->cursor_saved_y = y;
 	return 0;
 }
 
@@ -1330,6 +1332,14 @@ nv50_crtc_gamma_set(struct drm_crtc *crtc, u16 *r, u16 *g, u16 *b,
 }
 
 static void
+nv50_crtc_cursor_restore(struct nouveau_crtc *nv_crtc, int x, int y)
+{
+	nv50_crtc_cursor_move(&nv_crtc->base, x, y);
+
+	nv50_crtc_cursor_show_hide(nv_crtc, true, true);
+}
+
+static void
 nv50_crtc_destroy(struct drm_crtc *crtc)
 {
 	struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc);
@@ -1354,9 +1364,9 @@ nv50_crtc_destroy(struct drm_crtc *crtc)
 	nouveau_bo_ref(NULL, &head->image);
 
 	/*XXX: ditto */
-	if (head->curs.image)
-		nouveau_bo_unpin(head->curs.image);
-	nouveau_bo_ref(NULL, &head->curs.image);
+	if (nv_crtc->cursor.nvbo)
+		nouveau_bo_unpin(nv_crtc->cursor.nvbo);
+	nouveau_bo_ref(NULL, &nv_crtc->cursor.nvbo);
 
 	nouveau_bo_unmap(nv_crtc->lut.nvbo);
 	if (nv_crtc->lut.nvbo)
@@ -1406,6 +1416,7 @@ nv50_crtc_create(struct drm_device *dev, int index)
 	head->base.set_color_vibrance = nv50_crtc_set_color_vibrance;
 	head->base.color_vibrance = 50;
 	head->base.vibrant_hue = 0;
+	head->base.cursor.set_pos = nv50_crtc_cursor_restore;
 	for (i = 0; i < 256; i++) {
 		head->base.lut.r[i] = i << 8;
 		head->base.lut.g[i] = i << 8;
@@ -1433,8 +1444,6 @@ nv50_crtc_create(struct drm_device *dev, int index)
 	if (ret)
 		goto out;
 
-	nv50_crtc_lut_load(crtc);
-
 	/* allocate cursor resources */
 	ret = nv50_curs_create(disp->disp, index, &head->curs);
 	if (ret)
@@ -2427,6 +2436,8 @@ nv50_display_init(struct drm_device *dev)
 
 	list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
 		struct nv50_sync *sync = nv50_sync(crtc);
+
+		nv50_crtc_lut_load(crtc);
 		nouveau_bo_wr32(disp->sync, sync->addr / 4, sync->data);
 	}
 
