File 0001-drm-merged-fixes-5-sans-nv04_graph-change.patch of Package nouveau

From 44a0b8ce4d9c937c74eea5de50f242a970edab71 Mon Sep 17 00:00:00 2001
From: root <root@gdp.(none)>
Date: Tue, 6 May 2008 23:04:55 +0100
Subject: [PATCH] merged fixes 5, sans nv04_graph change

---
 shared-core/nouveau_drm.h  |    2 +
 shared-core/nouveau_fifo.c |  141 ++++++++++++++++++++++++++++++++++++++++++++
 shared-core/nouveau_mem.c  |    3 +-
 shared-core/nv20_graph.c   |    4 +
 4 files changed, 149 insertions(+), 1 deletions(-)

diff --git drm/shared-core/nouveau_drm.h drm/shared-core/nouveau_drm.h
index 4b5869a..487308b 100644
--- drm/shared-core/nouveau_drm.h
+++ drm/shared-core/nouveau_drm.h
@@ -167,6 +167,8 @@ struct drm_nouveau_sarea {
 	unsigned int nbox;
 };
 
+#define DRM_NOUVEAU_SUSPEND            0x10
+#define DRM_NOUVEAU_RESUME             0x11
 #define DRM_NOUVEAU_CARD_INIT          0x00
 #define DRM_NOUVEAU_GETPARAM           0x01
 #define DRM_NOUVEAU_SETPARAM           0x02
diff --git drm/shared-core/nouveau_fifo.c drm/shared-core/nouveau_fifo.c
index 5ec2bc3..e2fb038 100644
--- drm/shared-core/nouveau_fifo.c
+++ drm/shared-core/nouveau_fifo.c
@@ -27,6 +27,16 @@
 #include "nouveau_drv.h"
 #include "nouveau_drm.h"
 
+static struct {
+	u32 fifo_mode;
+	u32 graph_ctx_control;
+	u32 graph_state;
+	u32 *ramin_copy;
+	u32 *dchan_pushbuf;
+	bool resume_allowed;
+} susres = {
+	.resume_allowed = false
+};
 
 /* returns the size of fifo context */
 int nouveau_fifo_ctx_size(struct drm_device *dev)
@@ -578,11 +588,142 @@ static int nouveau_ioctl_fifo_free(struct drm_device *dev, void *data,
 	return 0;
 }
 
+static int nouveau_ioctl_suspend(struct drm_device *dev, void *data,
+				 struct drm_file *file_priv)
+{
+	struct drm_nouveau_private *dev_priv = dev->dev_private;
+	struct nouveau_engine *engine = &dev_priv->Engine;
+	int i;
+
+	if (!susres.resume_allowed) {
+		susres.ramin_copy = vmalloc(dev_priv->ramin->size);
+		susres.dchan_pushbuf = vmalloc(0x8000);
+		susres.resume_allowed = true;
+	}
+
+	NV_WRITE(NV04_PGRAPH_FIFO, 0);
+	/* disable the fifo caches */
+	NV_WRITE(NV03_PFIFO_CACHES, 0x00000000);
+	NV_WRITE(NV04_PFIFO_CACHE1_DMA_PUSH,
+		 NV_READ(NV04_PFIFO_CACHE1_DMA_PUSH) & ~1);
+	NV_WRITE(NV03_PFIFO_CACHE1_PUSH0, 0x00000000);
+	NV_WRITE(NV04_PFIFO_CACHE1_PULL0, 0x00000000);
+
+	susres.fifo_mode = NV_READ(NV04_PFIFO_MODE);
+
+	if (dev_priv->card_type >= NV_10) {
+		susres.graph_state = NV_READ(NV10_PGRAPH_STATE);
+		susres.graph_ctx_control = NV_READ(NV10_PGRAPH_CTX_CONTROL);
+	} else {
+		susres.graph_state = NV_READ(NV04_PGRAPH_STATE);
+		susres.graph_ctx_control = NV_READ(NV04_PGRAPH_CTX_CONTROL);
+	}
+
+	engine->fifo.save_context(dev_priv->fifos[engine->fifo.channel_id(dev)]);
+	engine->graph.save_context(dev_priv->fifos[engine->fifo.channel_id(dev)]);
+	nouveau_wait_for_idle(dev);
+
+	/* XXX copying all of RAMIN is probably overkill */
+	if (susres.ramin_copy)
+		for (i = 0; i < dev_priv->ramin->size / 4; i++)
+			susres.ramin_copy[i] = NV_RI32(i << 2);
+	else
+		DRM_ERROR("No suspend RAMIN\n");
+	/* XXX don't know if this is necessary; is there any chance of the drm
+	 * fifo being non-empty on suspend?
+	 */
+	if (susres.dchan_pushbuf)
+		for (i = 0; i < 0x2000; i++)
+			susres.dchan_pushbuf[i] = dev_priv->channel.pushbuf[i];
+	else
+		DRM_ERROR("No suspend DRM pushbuf\n");
+
+	/* reenable the fifo caches */
+	NV_WRITE(NV04_PFIFO_CACHE1_DMA_PUSH,
+		 NV_READ(NV04_PFIFO_CACHE1_DMA_PUSH) | 1);
+	NV_WRITE(NV03_PFIFO_CACHE1_PUSH0, 0x00000001);
+	NV_WRITE(NV04_PFIFO_CACHE1_PULL0, 0x00000001);
+	NV_WRITE(NV03_PFIFO_CACHES, 0x00000001);
+	NV_WRITE(NV04_PGRAPH_FIFO, 1);
+
+	return 0;
+}
+
+static int nouveau_ioctl_resume(struct drm_device *dev, void *data,
+				struct drm_file *file_priv)
+{
+	struct drm_nouveau_private *dev_priv = dev->dev_private;
+	struct nouveau_engine *engine = &dev_priv->Engine;
+	int i;
+
+	if (!susres.resume_allowed)
+		return 0;
+
+	DRM_DEBUG("Doing resume\n");
+
+	if (susres.dchan_pushbuf)
+		for (i = 0; i < 0x2000; i++)
+			dev_priv->channel.pushbuf[i] = susres.dchan_pushbuf[i];
+	if (susres.ramin_copy)
+		for (i = 0; i < dev_priv->ramin->size / 4; i++)
+			NV_WI32(i << 2, susres.ramin_copy[i]);
+
+	engine->mc.init(dev);
+	engine->timer.init(dev);
+	engine->fb.init(dev);
+	engine->graph.init(dev);
+	engine->fifo.init(dev);
+
+	NV_WRITE(NV04_PGRAPH_FIFO, 0);
+	/* disable the fifo caches */
+	NV_WRITE(NV03_PFIFO_CACHES, 0x00000000);
+	NV_WRITE(NV04_PFIFO_CACHE1_DMA_PUSH,
+		 NV_READ(NV04_PFIFO_CACHE1_DMA_PUSH) & ~1);
+	NV_WRITE(NV03_PFIFO_CACHE1_PUSH0, 0x00000000);
+	NV_WRITE(NV04_PFIFO_CACHE1_PULL0, 0x00000000);
+
+	/* PMC power cycling PFIFO in init clobbers some of the stuff stored in
+	 * RAMIN (such as NV04_PFIFO_CACHE1_DMA_INSTANCE). this is unhelpful
+	 */
+	if (susres.ramin_copy)
+		for (i = 0; i < dev_priv->ramin->size / 4; i++)
+			NV_WI32(i << 2, susres.ramin_copy[i]);
+
+	engine->fifo.load_context(dev_priv->fifos[0]);
+	NV_WRITE(NV04_PFIFO_MODE, susres.fifo_mode);
+
+	engine->graph.load_context(dev_priv->fifos[0]);
+	nouveau_wait_for_idle(dev);
+
+	if (dev_priv->card_type >= NV_10) {
+		NV_WRITE(NV10_PGRAPH_STATE, susres.graph_state);
+		NV_WRITE(NV10_PGRAPH_CTX_CONTROL, susres.graph_ctx_control);
+	} else {
+		NV_WRITE(NV04_PGRAPH_STATE, susres.graph_state);
+		NV_WRITE(NV04_PGRAPH_CTX_CONTROL, susres.graph_ctx_control);
+	}
+
+	/* reenable the fifo caches */
+	NV_WRITE(NV04_PFIFO_CACHE1_DMA_PUSH,
+		 NV_READ(NV04_PFIFO_CACHE1_DMA_PUSH) | 1);
+	NV_WRITE(NV03_PFIFO_CACHE1_PUSH0, 0x00000001);
+	NV_WRITE(NV04_PFIFO_CACHE1_PULL0, 0x00000001);
+	NV_WRITE(NV03_PFIFO_CACHES, 0x00000001);
+	NV_WRITE(NV04_PGRAPH_FIFO, 0x1);
+
+	if (dev->irq_enabled)
+		nouveau_irq_postinstall(dev);
+
+	return 0;
+}
+
 /***********************************
  * finally, the ioctl table
  ***********************************/
 
 struct drm_ioctl_desc nouveau_ioctls[] = {
+	DRM_IOCTL_DEF(DRM_NOUVEAU_SUSPEND, nouveau_ioctl_suspend, DRM_AUTH),
+	DRM_IOCTL_DEF(DRM_NOUVEAU_RESUME, nouveau_ioctl_resume, DRM_AUTH),
 	DRM_IOCTL_DEF(DRM_NOUVEAU_CARD_INIT, nouveau_ioctl_card_init, DRM_AUTH),
 	DRM_IOCTL_DEF(DRM_NOUVEAU_GETPARAM, nouveau_ioctl_getparam, DRM_AUTH),
 	DRM_IOCTL_DEF(DRM_NOUVEAU_SETPARAM, nouveau_ioctl_setparam, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
diff --git drm/shared-core/nouveau_mem.c drm/shared-core/nouveau_mem.c
index d79c1a5..4b35dcb 100644
--- drm/shared-core/nouveau_mem.c
+++ drm/shared-core/nouveau_mem.c
@@ -507,7 +507,8 @@ int nouveau_mem_init(struct drm_device *dev)
 		dev_priv->fb_nomap_heap=NULL;
 	}
 
-#if !defined(__powerpc__) && !defined(__ia64__)
+#if 0
+!defined(__powerpc__) && !defined(__ia64__)
 	/* Init AGP / NV50 PCIEGART */
 	if (drm_device_is_agp(dev) && dev->agp) {
 		if ((ret = nouveau_mem_init_agp(dev, 0)))
diff --git drm/shared-core/nv20_graph.c drm/shared-core/nv20_graph.c
index ad73ea9..e06536d 100644
--- drm/shared-core/nv20_graph.c
+++ drm/shared-core/nv20_graph.c
@@ -694,6 +694,7 @@ int nv20_graph_init(struct drm_device *dev) {
 	NV_WRITE(NV03_PMC_ENABLE, NV_READ(NV03_PMC_ENABLE) |
 			 NV_PMC_ENABLE_PGRAPH);
 
+	if (!dev_priv->ctx_table) {
 	/* Create Context Pointer Table */
 	dev_priv->ctx_table_size = 32 * 4;
 	if ((ret = nouveau_gpuobj_new_ref(dev, NULL, NULL, 0,
@@ -701,6 +702,7 @@ int nv20_graph_init(struct drm_device *dev) {
 					  NVOBJ_FLAG_ZERO_ALLOC,
 					  &dev_priv->ctx_table)))
 		return ret;
+	}
 
 	NV_WRITE(NV20_PGRAPH_CHANNEL_CTX_TABLE,
 		 dev_priv->ctx_table->instance >> 4);
@@ -812,6 +814,7 @@ int nv30_graph_init(struct drm_device *dev)
 	NV_WRITE(NV03_PMC_ENABLE, NV_READ(NV03_PMC_ENABLE) |
 			 NV_PMC_ENABLE_PGRAPH);
 
+	if (!dev_priv->ctx_table) {
 	/* Create Context Pointer Table */
 	dev_priv->ctx_table_size = 32 * 4;
 	if ((ret = nouveau_gpuobj_new_ref(dev, NULL, NULL, 0,
@@ -819,6 +822,7 @@ int nv30_graph_init(struct drm_device *dev)
 					  NVOBJ_FLAG_ZERO_ALLOC,
 					  &dev_priv->ctx_table)))
 		return ret;
+	}
 
 	NV_WRITE(NV20_PGRAPH_CHANNEL_CTX_TABLE,
 			dev_priv->ctx_table->instance >> 4);
-- 
1.5.4.4

openSUSE Build Service is sponsored by