summaryrefslogtreecommitdiff
path: root/drivers/gpu/drm/nouveau/dispnv04
diff options
context:
space:
mode:
authorBen Skeggs <bskeggs@redhat.com>2019-02-12 22:28:13 +1000
committerBen Skeggs <bskeggs@redhat.com>2019-02-20 08:59:59 +1000
commit0f9976dd97caac3de5308945eb5b5e1c7754b768 (patch)
tree1edf5ee3e50d4dde7fef2ebe85ef173dd0cea3e8 /drivers/gpu/drm/nouveau/dispnv04
parentf04a4186afb6799c44a486c12308d9469a2fa8f2 (diff)
drm/nouveau/kms/nv04-nv4x: move resume code to dispnv04 init hook
It has no relevance to the atomic path used by newer GPUs. Signed-off-by: Ben Skeggs <bskeggs@redhat.com>
Diffstat (limited to 'drivers/gpu/drm/nouveau/dispnv04')
-rw-r--r--drivers/gpu/drm/nouveau/dispnv04/disp.c70
1 files changed, 66 insertions, 4 deletions
diff --git a/drivers/gpu/drm/nouveau/dispnv04/disp.c b/drivers/gpu/drm/nouveau/dispnv04/disp.c
index 451e38a82fe7..5713bacaee80 100644
--- a/drivers/gpu/drm/nouveau/dispnv04/disp.c
+++ b/drivers/gpu/drm/nouveau/dispnv04/disp.c
@@ -73,11 +73,13 @@ nv04_display_fini(struct drm_device *dev, bool suspend)
}
static int
-nv04_display_init(struct drm_device *dev)
+nv04_display_init(struct drm_device *dev, bool resume, bool runtime)
{
struct nv04_display *disp = nv04_display(dev);
+ struct nouveau_drm *drm = nouveau_drm(dev);
struct nouveau_encoder *encoder;
- struct nouveau_crtc *crtc;
+ struct drm_crtc *crtc;
+ int ret;
/* meh.. modeset apparently doesn't setup all the regs and depends
* on pre-existing state, for now load the state of the card *before*
@@ -87,14 +89,74 @@ nv04_display_init(struct drm_device *dev)
* save/restore "pre-load" state, but more general so we can save
* on suspend too.
*/
- list_for_each_entry(crtc, &dev->mode_config.crtc_list, base.head)
- crtc->save(&crtc->base);
+ list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
+ struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc);
+ nv_crtc->save(&nv_crtc->base);
+ }
list_for_each_entry(encoder, &dev->mode_config.encoder_list, base.base.head)
encoder->enc_save(&encoder->base.base);
/* Enable flip completion events. */
nvif_notify_get(&disp->flip);
+
+ if (!resume)
+ return 0;
+
+ /* Re-pin FB/cursors. */
+ list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
+ struct nouveau_framebuffer *nouveau_fb;
+
+ nouveau_fb = nouveau_framebuffer(crtc->primary->fb);
+ if (!nouveau_fb || !nouveau_fb->nvbo)
+ continue;
+
+ ret = nouveau_bo_pin(nouveau_fb->nvbo, TTM_PL_FLAG_VRAM, true);
+ if (ret)
+ NV_ERROR(drm, "Could not pin framebuffer\n");
+ }
+
+ list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
+ struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc);
+ if (!nv_crtc->cursor.nvbo)
+ continue;
+
+ ret = nouveau_bo_pin(nv_crtc->cursor.nvbo, TTM_PL_FLAG_VRAM, true);
+ 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");
+ }
+
+ /* 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);
+
+ nv_crtc->lut.depth = 0;
+ }
+
+ /* This should ensure we don't hit a locking problem when someone
+ * wakes us up via a connector. We should never go into suspend
+ * while the display is on anyways.
+ */
+ if (runtime)
+ return 0;
+
+ /* Restore mode. */
+ drm_helper_resume_force_mode(dev);
+
+ list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
+ struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc);
+
+ if (!nv_crtc->cursor.nvbo)
+ continue;
+
+ 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);
+ }
+
return 0;
}