Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

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

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
Loading
Loading
Loading
Loading
+6 −3
Original line number Original line Diff line number Diff line
@@ -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)
			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)


		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);
+5 −18
Original line number Original line Diff line number Diff line
@@ -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 = {
	.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)
	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;


+0 −1
Original line number Original line Diff line number Diff line
@@ -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;
+27 −16
Original line number Original line Diff line number Diff line
@@ -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
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)
		}
		}
		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,
		     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,
	}
	}


	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,
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,
	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)
	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)
	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)
	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)


	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);
	}
	}