Browse Source

drm/nouveau: allow cursor image and position to survive suspend

- This isn't triggered yet on a normal kernel, because it still does a VT
switch, but it seemed like a good idea to fix this now.

Tested-by: Maxim Levitsky <maximlevitsky@gmail.com>
Signed-off-by: Maarten Maathuis <madman2003@gmail.com>
Signed-off-by: Ben Skeggs <bskeggs@redhat.com>
Maarten Maathuis 15 years ago
parent
commit
b334f2b3b6

+ 2 - 0
drivers/gpu/drm/nouveau/nouveau_crtc.h

@@ -40,6 +40,8 @@ struct nouveau_crtc {
 	int sharpness;
 	int last_dpms;
 
+	int cursor_saved_x, cursor_saved_y;
+
 	struct {
 		int cpp;
 		bool blanked;

+ 29 - 0
drivers/gpu/drm/nouveau/nouveau_drv.c

@@ -175,6 +175,13 @@ nouveau_pci_suspend(struct pci_dev *pdev, pm_message_t pm_state)
 		nouveau_bo_unpin(nouveau_fb->nvbo);
 	}
 
+	list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
+		struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc);
+
+		nouveau_bo_unmap(nv_crtc->cursor.nvbo);
+		nouveau_bo_unpin(nv_crtc->cursor.nvbo);
+	}
+
 	NV_INFO(dev, "Evicting buffers...\n");
 	ttm_bo_evict_mm(&dev_priv->ttm.bdev, TTM_PL_VRAM);
 
@@ -314,12 +321,34 @@ nouveau_pci_resume(struct pci_dev *pdev)
 		nouveau_bo_pin(nouveau_fb->nvbo, TTM_PL_FLAG_VRAM);
 	}
 
+	list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
+		struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc);
+		int ret;
+
+		ret = nouveau_bo_pin(nv_crtc->cursor.nvbo, TTM_PL_FLAG_VRAM);
+		if (!ret)
+			ret = nouveau_bo_map(nv_crtc->cursor.nvbo);
+		if (ret)
+			NV_ERROR(dev, "Could not pin/map cursor.\n");
+	}
+
 	if (dev_priv->card_type < NV_50) {
 		nv04_display_restore(dev);
 		NVLockVgaCrtcs(dev, false);
 	} else
 		nv50_display_init(dev);
 
+	list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
+		struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc);
+
+		nv_crtc->cursor.set_offset(nv_crtc,
+					nv_crtc->cursor.nvbo->bo.offset -
+					dev_priv->vm_vram_base);
+
+		nv_crtc->cursor.set_pos(nv_crtc, nv_crtc->cursor_saved_x,
+			nv_crtc->cursor_saved_y);
+	}
+
 	/* Force CLUT to get re-loaded during modeset */
 	list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
 		struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc);

+ 1 - 0
drivers/gpu/drm/nouveau/nv04_cursor.c

@@ -20,6 +20,7 @@ nv04_cursor_hide(struct nouveau_crtc *nv_crtc, bool update)
 static void
 nv04_cursor_set_pos(struct nouveau_crtc *nv_crtc, int x, int y)
 {
+	nv_crtc->cursor_saved_x = x; nv_crtc->cursor_saved_y = y;
 	NVWriteRAMDAC(nv_crtc->base.dev, nv_crtc->index,
 		      NV_PRAMDAC_CU_START_POS,
 		      XLATE(y, 0, NV_PRAMDAC_CU_START_POS_Y) |

+ 1 - 0
drivers/gpu/drm/nouveau/nv50_cursor.c

@@ -107,6 +107,7 @@ nv50_cursor_set_pos(struct nouveau_crtc *nv_crtc, int x, int y)
 {
 	struct drm_device *dev = nv_crtc->base.dev;
 
+	nv_crtc->cursor_saved_x = x; nv_crtc->cursor_saved_y = y;
 	nv_wr32(dev, NV50_PDISPLAY_CURSOR_USER_POS(nv_crtc->index),
 		((y & 0xFFFF) << 16) | (x & 0xFFFF));
 	/* Needed to make the cursor move. */