drm/nouveau: dont switch vt on suspend
authorMaarten Lankhorst <maarten.lankhorst@canonical.com>
Tue, 13 Jan 2015 08:18:49 +0000 (09:18 +0100)
committerBen Skeggs <bskeggs@redhat.com>
Thu, 22 Jan 2015 02:15:08 +0000 (12:15 +1000)
Restore the nv50 cursor bo on resume, and load the lut in
nv50_display_display_init so it gets set on resume too.

Tested on a fermi and a curie.

Signed-off-by: Maarten Lankhorst <maarten.lankhorst@ubuntu.com>
Signed-off-by: Ben Skeggs <bskeggs@redhat.com>
drivers/gpu/drm/nouveau/nouveau_display.c
drivers/gpu/drm/nouveau/nouveau_fbcon.c
drivers/gpu/drm/nouveau/nouveau_fbcon.h
drivers/gpu/drm/nouveau/nv50_display.c

index f8042433752b440d72fd9306009f55e972c68385..f972e9c1a23adf088602cc77425de8346f4be945 100644 (file)
@@ -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);
        }
index 3ed12a8cfc914520fc097ac98e5e16e63ed0d532..d6e6958bc5f88fad7024c3d1aad1e9632ea39ae6 100644 (file)
@@ -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;
 
index 6208e70e4a1cfdd16a949db884a605466d0ced38..1e2e9e27a03bbdfdbf215d14d22378f9607c4f76 100644 (file)
@@ -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;
index fcbbf3884781d79338970fdd52150fa083372688..113e8cdb0b2b240c77e88b27562578bdcb94dfc6 100644 (file)
@@ -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
@@ -924,29 +923,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
@@ -972,15 +971,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);
@@ -1280,7 +1279,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;
@@ -1299,9 +1297,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);
 
@@ -1312,10 +1310,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;
 }
 
@@ -1336,6 +1338,14 @@ nv50_crtc_gamma_set(struct drm_crtc *crtc, u16 *r, u16 *g, u16 *b,
        nv50_crtc_lut_load(crtc);
 }
 
+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)
 {
@@ -1361,9 +1371,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)
@@ -1413,6 +1423,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;
@@ -1440,8 +1451,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)
@@ -2419,6 +2428,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);
        }