Commit 4dc63933 authored by Maarten Lankhorst's avatar Maarten Lankhorst Committed by Ben Skeggs

drm/nouveau: dont switch vt on suspend

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: default avatarMaarten Lankhorst <maarten.lankhorst@ubuntu.com>
Signed-off-by: default avatarBen Skeggs <bskeggs@redhat.com>
parent 4d8bb03b
...@@ -570,6 +570,7 @@ nouveau_display_suspend(struct drm_device *dev, bool runtime) ...@@ -570,6 +570,7 @@ nouveau_display_suspend(struct drm_device *dev, bool runtime)
list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) { list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc); struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc);
if (nv_crtc->cursor.nvbo) { if (nv_crtc->cursor.nvbo) {
if (nv_crtc->cursor.set_offset)
nouveau_bo_unmap(nv_crtc->cursor.nvbo); nouveau_bo_unmap(nv_crtc->cursor.nvbo);
nouveau_bo_unpin(nv_crtc->cursor.nvbo); nouveau_bo_unpin(nv_crtc->cursor.nvbo);
} }
...@@ -604,7 +605,7 @@ nouveau_display_resume(struct drm_device *dev, bool runtime) ...@@ -604,7 +605,7 @@ nouveau_display_resume(struct drm_device *dev, bool runtime)
continue; continue;
ret = nouveau_bo_pin(nv_crtc->cursor.nvbo, TTM_PL_FLAG_VRAM, true); 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); ret = nouveau_bo_map(nv_crtc->cursor.nvbo);
if (ret) if (ret)
NV_ERROR(drm, "Could not pin/map cursor.\n"); NV_ERROR(drm, "Could not pin/map cursor.\n");
...@@ -637,6 +638,8 @@ nouveau_display_resume(struct drm_device *dev, bool runtime) ...@@ -637,6 +638,8 @@ nouveau_display_resume(struct drm_device *dev, bool runtime)
if (!nv_crtc->cursor.nvbo) if (!nv_crtc->cursor.nvbo)
continue; continue;
if (nv_crtc->cursor.set_offset)
nv_crtc->cursor.set_offset(nv_crtc, nv_crtc->cursor.nvbo->bo.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.set_pos(nv_crtc, nv_crtc->cursor_saved_x,
nv_crtc->cursor_saved_y); nv_crtc->cursor_saved_y);
......
...@@ -370,6 +370,7 @@ nouveau_fbcon_create(struct drm_fb_helper *helper, ...@@ -370,6 +370,7 @@ nouveau_fbcon_create(struct drm_fb_helper *helper,
ret = -ENOMEM; ret = -ENOMEM;
goto out_unlock; goto out_unlock;
} }
info->skip_vt_switch = 1;
ret = fb_alloc_cmap(&info->cmap, 256, 0); ret = fb_alloc_cmap(&info->cmap, 256, 0);
if (ret) { if (ret) {
...@@ -487,29 +488,16 @@ static const struct drm_fb_helper_funcs nouveau_fbcon_helper_funcs = { ...@@ -487,29 +488,16 @@ static const struct drm_fb_helper_funcs nouveau_fbcon_helper_funcs = {
.fb_probe = nouveau_fbcon_create, .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 void
nouveau_fbcon_set_suspend(struct drm_device *dev, int state) nouveau_fbcon_set_suspend(struct drm_device *dev, int state)
{ {
struct nouveau_drm *drm = nouveau_drm(dev); struct nouveau_drm *drm = nouveau_drm(dev);
if (drm->fbcon) { if (drm->fbcon) {
if (state == FBINFO_STATE_RUNNING) {
schedule_work(&drm->fbcon->work);
return;
}
flush_work(&drm->fbcon->work);
console_lock(); console_lock();
if (state == FBINFO_STATE_RUNNING)
nouveau_fbcon_accel_restore(dev);
fb_set_suspend(drm->fbcon->helper.fbdev, state); fb_set_suspend(drm->fbcon->helper.fbdev, state);
if (state != FBINFO_STATE_RUNNING)
nouveau_fbcon_accel_save_disable(dev); nouveau_fbcon_accel_save_disable(dev);
console_unlock(); console_unlock();
} }
...@@ -531,7 +519,6 @@ nouveau_fbcon_init(struct drm_device *dev) ...@@ -531,7 +519,6 @@ nouveau_fbcon_init(struct drm_device *dev)
if (!fbcon) if (!fbcon)
return -ENOMEM; return -ENOMEM;
INIT_WORK(&fbcon->work, nouveau_fbcon_set_suspend_work);
fbcon->dev = dev; fbcon->dev = dev;
drm->fbcon = fbcon; drm->fbcon = fbcon;
......
...@@ -36,7 +36,6 @@ struct nouveau_fbdev { ...@@ -36,7 +36,6 @@ struct nouveau_fbdev {
struct nouveau_framebuffer nouveau_fb; struct nouveau_framebuffer nouveau_fb;
struct list_head fbdev_list; struct list_head fbdev_list;
struct drm_device *dev; struct drm_device *dev;
struct work_struct work;
unsigned int saved_flags; unsigned int saved_flags;
struct nvif_object surf2d; struct nvif_object surf2d;
struct nvif_object clip; struct nvif_object clip;
......
...@@ -125,7 +125,6 @@ nv50_pioc_create(struct nvif_object *disp, const u32 *oclass, u8 head, ...@@ -125,7 +125,6 @@ nv50_pioc_create(struct nvif_object *disp, const u32 *oclass, u8 head,
struct nv50_curs { struct nv50_curs {
struct nv50_pioc base; struct nv50_pioc base;
struct nouveau_bo *image;
}; };
static int static int
...@@ -924,29 +923,29 @@ static void ...@@ -924,29 +923,29 @@ static void
nv50_crtc_cursor_show(struct nouveau_crtc *nv_crtc) nv50_crtc_cursor_show(struct nouveau_crtc *nv_crtc)
{ {
struct nv50_mast *mast = nv50_mast(nv_crtc->base.dev); 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); u32 *push = evo_wait(mast, 16);
if (push) { if (push) {
if (nv50_vers(mast) < G82_DISP_CORE_CHANNEL_DMA) { if (nv50_vers(mast) < G82_DISP_CORE_CHANNEL_DMA) {
evo_mthd(push, 0x0880 + (nv_crtc->index * 0x400), 2); evo_mthd(push, 0x0880 + (nv_crtc->index * 0x400), 2);
evo_data(push, 0x85000000); evo_data(push, 0x85000000);
evo_data(push, curs->image->bo.offset >> 8); evo_data(push, nv_crtc->cursor.nvbo->bo.offset >> 8);
} else } else
if (nv50_vers(mast) < GF110_DISP_CORE_CHANNEL_DMA) { if (nv50_vers(mast) < GF110_DISP_CORE_CHANNEL_DMA) {
evo_mthd(push, 0x0880 + (nv_crtc->index * 0x400), 2); evo_mthd(push, 0x0880 + (nv_crtc->index * 0x400), 2);
evo_data(push, 0x85000000); 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_mthd(push, 0x089c + (nv_crtc->index * 0x400), 1);
evo_data(push, mast->base.vram.handle); evo_data(push, mast->base.vram.handle);
} else { } else {
evo_mthd(push, 0x0480 + (nv_crtc->index * 0x300), 2); evo_mthd(push, 0x0480 + (nv_crtc->index * 0x300), 2);
evo_data(push, 0x85000000); 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_mthd(push, 0x048c + (nv_crtc->index * 0x300), 1);
evo_data(push, mast->base.vram.handle); evo_data(push, mast->base.vram.handle);
} }
evo_kick(push, mast); evo_kick(push, mast);
} }
nv_crtc->cursor.visible = true;
} }
static void static void
...@@ -972,15 +971,15 @@ nv50_crtc_cursor_hide(struct nouveau_crtc *nv_crtc) ...@@ -972,15 +971,15 @@ nv50_crtc_cursor_hide(struct nouveau_crtc *nv_crtc)
} }
evo_kick(push, mast); evo_kick(push, mast);
} }
nv_crtc->cursor.visible = false;
} }
static void static void
nv50_crtc_cursor_show_hide(struct nouveau_crtc *nv_crtc, bool show, bool update) 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_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); nv50_crtc_cursor_show(nv_crtc);
else else
nv50_crtc_cursor_hide(nv_crtc); nv50_crtc_cursor_hide(nv_crtc);
...@@ -1280,7 +1279,6 @@ nv50_crtc_cursor_set(struct drm_crtc *crtc, struct drm_file *file_priv, ...@@ -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) uint32_t handle, uint32_t width, uint32_t height)
{ {
struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc); struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc);
struct nv50_curs *curs = nv50_curs(crtc);
struct drm_device *dev = crtc->dev; struct drm_device *dev = crtc->dev;
struct drm_gem_object *gem = NULL; struct drm_gem_object *gem = NULL;
struct nouveau_bo *nvbo = NULL; struct nouveau_bo *nvbo = NULL;
...@@ -1299,9 +1297,9 @@ nv50_crtc_cursor_set(struct drm_crtc *crtc, struct drm_file *file_priv, ...@@ -1299,9 +1297,9 @@ nv50_crtc_cursor_set(struct drm_crtc *crtc, struct drm_file *file_priv,
} }
if (ret == 0) { if (ret == 0) {
if (curs->image) if (nv_crtc->cursor.nvbo)
nouveau_bo_unpin(curs->image); nouveau_bo_unpin(nv_crtc->cursor.nvbo);
nouveau_bo_ref(nvbo, &curs->image); nouveau_bo_ref(nvbo, &nv_crtc->cursor.nvbo);
} }
drm_gem_object_unreference_unlocked(gem); drm_gem_object_unreference_unlocked(gem);
...@@ -1312,10 +1310,14 @@ nv50_crtc_cursor_set(struct drm_crtc *crtc, struct drm_file *file_priv, ...@@ -1312,10 +1310,14 @@ nv50_crtc_cursor_set(struct drm_crtc *crtc, struct drm_file *file_priv,
static int static int
nv50_crtc_cursor_move(struct drm_crtc *crtc, int x, int y) 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_curs *curs = nv50_curs(crtc);
struct nv50_chan *chan = nv50_chan(curs); struct nv50_chan *chan = nv50_chan(curs);
nvif_wr32(&chan->user, 0x0084, (y << 16) | (x & 0xffff)); nvif_wr32(&chan->user, 0x0084, (y << 16) | (x & 0xffff));
nvif_wr32(&chan->user, 0x0080, 0x00000000); nvif_wr32(&chan->user, 0x0080, 0x00000000);
nv_crtc->cursor_saved_x = x;
nv_crtc->cursor_saved_y = y;
return 0; return 0;
} }
...@@ -1336,6 +1338,14 @@ nv50_crtc_gamma_set(struct drm_crtc *crtc, u16 *r, u16 *g, u16 *b, ...@@ -1336,6 +1338,14 @@ nv50_crtc_gamma_set(struct drm_crtc *crtc, u16 *r, u16 *g, u16 *b,
nv50_crtc_lut_load(crtc); 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 static void
nv50_crtc_destroy(struct drm_crtc *crtc) nv50_crtc_destroy(struct drm_crtc *crtc)
{ {
...@@ -1361,9 +1371,9 @@ nv50_crtc_destroy(struct drm_crtc *crtc) ...@@ -1361,9 +1371,9 @@ nv50_crtc_destroy(struct drm_crtc *crtc)
nouveau_bo_ref(NULL, &head->image); nouveau_bo_ref(NULL, &head->image);
/*XXX: ditto */ /*XXX: ditto */
if (head->curs.image) if (nv_crtc->cursor.nvbo)
nouveau_bo_unpin(head->curs.image); nouveau_bo_unpin(nv_crtc->cursor.nvbo);
nouveau_bo_ref(NULL, &head->curs.image); nouveau_bo_ref(NULL, &nv_crtc->cursor.nvbo);
nouveau_bo_unmap(nv_crtc->lut.nvbo); nouveau_bo_unmap(nv_crtc->lut.nvbo);
if (nv_crtc->lut.nvbo) if (nv_crtc->lut.nvbo)
...@@ -1413,6 +1423,7 @@ nv50_crtc_create(struct drm_device *dev, int index) ...@@ -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.set_color_vibrance = nv50_crtc_set_color_vibrance;
head->base.color_vibrance = 50; head->base.color_vibrance = 50;
head->base.vibrant_hue = 0; head->base.vibrant_hue = 0;
head->base.cursor.set_pos = nv50_crtc_cursor_restore;
for (i = 0; i < 256; i++) { for (i = 0; i < 256; i++) {
head->base.lut.r[i] = i << 8; head->base.lut.r[i] = i << 8;
head->base.lut.g[i] = i << 8; head->base.lut.g[i] = i << 8;
...@@ -1440,8 +1451,6 @@ nv50_crtc_create(struct drm_device *dev, int index) ...@@ -1440,8 +1451,6 @@ nv50_crtc_create(struct drm_device *dev, int index)
if (ret) if (ret)
goto out; goto out;
nv50_crtc_lut_load(crtc);
/* allocate cursor resources */ /* allocate cursor resources */
ret = nv50_curs_create(disp->disp, index, &head->curs); ret = nv50_curs_create(disp->disp, index, &head->curs);
if (ret) if (ret)
...@@ -2419,6 +2428,8 @@ nv50_display_init(struct drm_device *dev) ...@@ -2419,6 +2428,8 @@ nv50_display_init(struct drm_device *dev)
list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) { list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
struct nv50_sync *sync = nv50_sync(crtc); struct nv50_sync *sync = nv50_sync(crtc);
nv50_crtc_lut_load(crtc);
nouveau_bo_wr32(disp->sync, sync->addr / 4, sync->data); nouveau_bo_wr32(disp->sync, sync->addr / 4, sync->data);
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment