summaryrefslogtreecommitdiff
path: root/shared-core/nv10_graph.c
diff options
context:
space:
mode:
Diffstat (limited to 'shared-core/nv10_graph.c')
-rw-r--r--shared-core/nv10_graph.c196
1 files changed, 136 insertions, 60 deletions
diff --git a/shared-core/nv10_graph.c b/shared-core/nv10_graph.c
index 4cc44e21..e470ff06 100644
--- a/shared-core/nv10_graph.c
+++ b/shared-core/nv10_graph.c
@@ -28,8 +28,8 @@
#include "nouveau_drv.h"
-static void nv10_praph_pipe(drm_device_t *dev) {
- drm_nouveau_private_t *dev_priv = dev->dev_private;
+static void nv10_praph_pipe(struct drm_device *dev) {
+ struct drm_nouveau_private *dev_priv = dev->dev_private;
int i;
nouveau_wait_for_idle(dev);
@@ -181,11 +181,7 @@ static void nv10_praph_pipe(drm_device_t *dev) {
nouveau_wait_for_idle(dev);
}
-/* TODO replace address with name
- use loops */
static int nv10_graph_ctx_regs [] = {
-NV03_PGRAPH_XY_LOGIC_MISC0,
-
NV10_PGRAPH_CTX_SWITCH1,
NV10_PGRAPH_CTX_SWITCH2,
NV10_PGRAPH_CTX_SWITCH3,
@@ -455,6 +451,7 @@ NV03_PGRAPH_ABS_UCLIPA_YMIN,
NV03_PGRAPH_ABS_UCLIPA_YMAX,
NV03_PGRAPH_ABS_ICLIP_XMAX,
NV03_PGRAPH_ABS_ICLIP_YMAX,
+NV03_PGRAPH_XY_LOGIC_MISC0,
NV03_PGRAPH_XY_LOGIC_MISC1,
NV03_PGRAPH_XY_LOGIC_MISC2,
NV03_PGRAPH_XY_LOGIC_MISC3,
@@ -527,9 +524,9 @@ NV10_PGRAPH_DEBUG_4,
0x00400a04,
};
-static int nv10_graph_ctx_regs_find_offset(drm_device_t *dev, int reg)
+static int nv10_graph_ctx_regs_find_offset(struct drm_device *dev, int reg)
{
- drm_nouveau_private_t *dev_priv = dev->dev_private;
+ struct drm_nouveau_private *dev_priv = dev->dev_private;
int i, j;
for (i = 0; i < sizeof(nv10_graph_ctx_regs)/sizeof(nv10_graph_ctx_regs[0]); i++) {
if (nv10_graph_ctx_regs[i] == reg)
@@ -544,82 +541,115 @@ static int nv10_graph_ctx_regs_find_offset(drm_device_t *dev, int reg)
return -1;
}
-static void restore_ctx_regs(drm_device_t *dev, int channel)
+int nv10_graph_load_context(struct nouveau_channel *chan)
{
- drm_nouveau_private_t *dev_priv = dev->dev_private;
- struct nouveau_fifo *fifo = &dev_priv->fifos[channel];
+ struct drm_device *dev = chan->dev;
+ struct drm_nouveau_private *dev_priv = dev->dev_private;
int i, j;
+
for (i = 0; i < sizeof(nv10_graph_ctx_regs)/sizeof(nv10_graph_ctx_regs[0]); i++)
- NV_WRITE(nv10_graph_ctx_regs[i], fifo->pgraph_ctx[i]);
+ NV_WRITE(nv10_graph_ctx_regs[i], chan->pgraph_ctx[i]);
if (dev_priv->chipset>=0x17) {
for (j = 0; j < sizeof(nv17_graph_ctx_regs)/sizeof(nv17_graph_ctx_regs[0]); i++,j++)
- NV_WRITE(nv17_graph_ctx_regs[j], fifo->pgraph_ctx[i]);
+ NV_WRITE(nv17_graph_ctx_regs[j], chan->pgraph_ctx[i]);
}
- nouveau_wait_for_idle(dev);
+ NV_WRITE(NV10_PGRAPH_CTX_USER, chan->id << 24);
+
+ return 0;
}
-void nouveau_nv10_context_switch(drm_device_t *dev)
+int nv10_graph_save_context(struct nouveau_channel *chan)
{
- drm_nouveau_private_t *dev_priv = dev->dev_private;
- int channel, channel_old, i, j;
-
- channel=NV_READ(NV03_PFIFO_CACHE1_PUSH1)&(nouveau_fifo_number(dev)-1);
- channel_old = (NV_READ(NV10_PGRAPH_CTX_USER) >> 24) & (nouveau_fifo_number(dev)-1);
-
- DRM_INFO("NV: PGRAPH context switch interrupt channel %x -> %x\n",channel_old, channel);
-
- NV_WRITE(NV04_PGRAPH_FIFO,0x0);
-#if 0
- NV_WRITE(NV_PFIFO_CACH1_PUL0, 0x00000000);
- NV_WRITE(NV_PFIFO_CACH1_PUL1, 0x00000000);
- NV_WRITE(NV_PFIFO_CACHES, 0x00000000);
-#endif
+ struct drm_device *dev = chan->dev;
+ struct drm_nouveau_private *dev_priv = dev->dev_private;
+ int i, j;
- // save PGRAPH context
for (i = 0; i < sizeof(nv10_graph_ctx_regs)/sizeof(nv10_graph_ctx_regs[0]); i++)
- dev_priv->fifos[channel_old].pgraph_ctx[i] = NV_READ(nv10_graph_ctx_regs[i]);
+ chan->pgraph_ctx[i] = NV_READ(nv10_graph_ctx_regs[i]);
if (dev_priv->chipset>=0x17) {
for (j = 0; j < sizeof(nv17_graph_ctx_regs)/sizeof(nv17_graph_ctx_regs[0]); i++,j++)
- dev_priv->fifos[channel_old].pgraph_ctx[i] = NV_READ(nv17_graph_ctx_regs[j]);
+ chan->pgraph_ctx[i] = NV_READ(nv17_graph_ctx_regs[j]);
}
-
+
+ return 0;
+}
+
+void nouveau_nv10_context_switch(struct drm_device *dev)
+{
+ struct drm_nouveau_private *dev_priv;
+ struct nouveau_channel *next, *last;
+ int chid;
+
+ if (!dev) {
+ DRM_DEBUG("Invalid drm_device\n");
+ return;
+ }
+ dev_priv = dev->dev_private;
+ if (!dev_priv) {
+ DRM_DEBUG("Invalid drm_nouveau_private\n");
+ return;
+ }
+ if (!dev_priv->fifos) {
+ DRM_DEBUG("Invalid drm_nouveau_private->fifos\n");
+ return;
+ }
+
+ chid = (NV_READ(NV04_PGRAPH_TRAPPED_ADDR) >> 20)&(nouveau_fifo_number(dev)-1);
+ next = dev_priv->fifos[chid];
+
+ if (!next) {
+ DRM_DEBUG("Invalid next channel\n");
+ return;
+ }
+
+ chid = (NV_READ(NV10_PGRAPH_CTX_USER) >> 24) & (nouveau_fifo_number(dev)-1);
+ last = dev_priv->fifos[chid];
+
+ if (!last) {
+ DRM_DEBUG("WARNING: Invalid last channel, switch to %x\n",
+ next->id);
+ } else {
+ DRM_INFO("NV: PGRAPH context switch interrupt channel %x -> %x\n",
+ last->id, next->id);
+ }
+
+ NV_WRITE(NV04_PGRAPH_FIFO,0x0);
+ if (last) {
+ nv10_graph_save_context(last);
+ }
+
nouveau_wait_for_idle(dev);
NV_WRITE(NV10_PGRAPH_CTX_CONTROL, 0x10000000);
NV_WRITE(NV10_PGRAPH_CTX_USER, (NV_READ(NV10_PGRAPH_CTX_USER) & 0xffffff) | (0x1f << 24));
nouveau_wait_for_idle(dev);
- // restore PGRAPH context
-#if 1
- restore_ctx_regs(dev, channel);
-#endif
-
+
+ nv10_graph_load_context(next);
+
NV_WRITE(NV10_PGRAPH_CTX_CONTROL, 0x10010100);
- NV_WRITE(NV10_PGRAPH_CTX_USER, channel << 24);
+ //NV_WRITE(NV10_PGRAPH_CTX_USER, next->id << 24);
NV_WRITE(NV10_PGRAPH_FFINTFC_ST2, NV_READ(NV10_PGRAPH_FFINTFC_ST2)&0xCFFFFFFF);
-
-#if 0
- NV_WRITE(NV_PFIFO_CACH1_PUL0, 0x00000001);
- NV_WRITE(NV_PFIFO_CACH1_PUL1, 0x00000001);
- NV_WRITE(NV_PFIFO_CACHES, 0x00000001);
-#endif
NV_WRITE(NV04_PGRAPH_FIFO,0x1);
}
#define NV_WRITE_CTX(reg, val) do { \
int offset = nv10_graph_ctx_regs_find_offset(dev, reg); \
if (offset > 0) \
- fifo->pgraph_ctx[offset] = val; \
+ chan->pgraph_ctx[offset] = val; \
} while (0)
-int nv10_graph_context_create(drm_device_t *dev, int channel) {
- drm_nouveau_private_t *dev_priv = dev->dev_private;
- struct nouveau_fifo *fifo = &dev_priv->fifos[channel];
- uint32_t tmp, vramsz;
- DRM_DEBUG("nv10_graph_context_create %d\n", channel);
+int nv10_graph_create_context(struct nouveau_channel *chan) {
+ struct drm_device *dev = chan->dev;
+ struct drm_nouveau_private *dev_priv = dev->dev_private;
- memset(fifo->pgraph_ctx, 0, sizeof(fifo->pgraph_ctx));
+ DRM_DEBUG("nv10_graph_context_create %d\n", chan->id);
+ memset(chan->pgraph_ctx, 0, sizeof(chan->pgraph_ctx));
+
+ /* mmio trace suggest that should be done in ddx with methods/objects */
+#if 0
+ uint32_t tmp, vramsz;
/* per channel init from ddx */
tmp = NV_READ(NV10_PGRAPH_SURFACE) & 0x0007ff00;
/*XXX the original ddx code, does this in 2 steps :
@@ -640,17 +670,32 @@ int nv10_graph_context_create(drm_device_t *dev, int channel) {
NV_WRITE_CTX(NV04_PGRAPH_PATTERN_SHAPE, 0x00000000);
NV_WRITE_CTX(NV04_PGRAPH_BETA_AND , 0xFFFFFFFF);
+ NV_WRITE_CTX(NV03_PGRAPH_ABS_UCLIP_XMIN, 0);
+ NV_WRITE_CTX(NV03_PGRAPH_ABS_UCLIP_YMIN, 0);
+ NV_WRITE_CTX(NV03_PGRAPH_ABS_UCLIP_XMAX, 0x7fff);
+ NV_WRITE_CTX(NV03_PGRAPH_ABS_UCLIP_YMAX, 0x7fff);
+#endif
+ NV_WRITE_CTX(0x00400e88, 0x08000000);
+ NV_WRITE_CTX(0x00400e9c, 0x4b7fffff);
NV_WRITE_CTX(NV03_PGRAPH_XY_LOGIC_MISC0, 0x0001ffff);
- /* is it really needed ??? */
+ NV_WRITE_CTX(0x00400e10, 0x00001000);
+ NV_WRITE_CTX(0x00400e14, 0x00001000);
+ NV_WRITE_CTX(0x00400e30, 0x00080008);
+ NV_WRITE_CTX(0x00400e34, 0x00080008);
if (dev_priv->chipset>=0x17) {
+ /* is it really needed ??? */
NV_WRITE_CTX(NV10_PGRAPH_DEBUG_4, NV_READ(NV10_PGRAPH_DEBUG_4));
NV_WRITE_CTX(0x004006b0, NV_READ(0x004006b0));
+ NV_WRITE_CTX(0x00400eac, 0x0fff0000);
+ NV_WRITE_CTX(0x00400eb0, 0x0fff0000);
+ NV_WRITE_CTX(0x00400ec0, 0x00000080);
+ NV_WRITE_CTX(0x00400ed0, 0x00000080);
}
/* for the first channel init the regs */
if (dev_priv->fifo_alloc_count == 0)
- restore_ctx_regs(dev, channel);
+ nv10_graph_load_context(chan);
//XXX should be saved/restored for each fifo
@@ -659,9 +704,29 @@ int nv10_graph_context_create(drm_device_t *dev, int channel) {
return 0;
}
+void nv10_graph_destroy_context(struct nouveau_channel *chan)
+{
+ struct drm_device *dev = chan->dev;
+ struct drm_nouveau_private *dev_priv = dev->dev_private;
+ int chid;
+ chid = (NV_READ(NV10_PGRAPH_CTX_USER) >> 24) & (nouveau_fifo_number(dev)-1);
-int nv10_graph_init(drm_device_t *dev) {
- drm_nouveau_private_t *dev_priv = dev->dev_private;
+ /* does this avoid a potential context switch while we are written graph
+ * reg, or we should mask graph interrupt ???
+ */
+ NV_WRITE(NV04_PGRAPH_FIFO,0x0);
+ if (chid == chan->id) {
+ DRM_INFO("cleanning a channel with graph in current context\n");
+ nouveau_wait_for_idle(dev);
+ DRM_INFO("reseting current graph context\n");
+ nv10_graph_create_context(chan);
+ nv10_graph_load_context(chan);
+ }
+ NV_WRITE(NV04_PGRAPH_FIFO,0x1);
+}
+
+int nv10_graph_init(struct drm_device *dev) {
+ struct drm_nouveau_private *dev_priv = dev->dev_private;
int i;
NV_WRITE(NV03_PMC_ENABLE, NV_READ(NV03_PMC_ENABLE) &
@@ -669,16 +734,23 @@ int nv10_graph_init(drm_device_t *dev) {
NV_WRITE(NV03_PMC_ENABLE, NV_READ(NV03_PMC_ENABLE) |
NV_PMC_ENABLE_PGRAPH);
- NV_WRITE(NV03_PGRAPH_INTR_EN, 0x00000000);
NV_WRITE(NV03_PGRAPH_INTR , 0xFFFFFFFF);
+ NV_WRITE(NV03_PGRAPH_INTR_EN, 0xFFFFFFFF);
NV_WRITE(NV04_PGRAPH_DEBUG_0, 0xFFFFFFFF);
NV_WRITE(NV04_PGRAPH_DEBUG_0, 0x00000000);
NV_WRITE(NV04_PGRAPH_DEBUG_1, 0x00118700);
- NV_WRITE(NV04_PGRAPH_DEBUG_2, 0x24E00810);
- NV_WRITE(NV04_PGRAPH_DEBUG_3, 0x55DE0030 |
+ //NV_WRITE(NV04_PGRAPH_DEBUG_2, 0x24E00810); /* 0x25f92ad9 */
+ NV_WRITE(NV04_PGRAPH_DEBUG_2, 0x25f92ad9);
+ NV_WRITE(NV04_PGRAPH_DEBUG_3, 0x55DE0830 |
(1<<29) |
(1<<31));
+ if (dev_priv->chipset>=0x17) {
+ NV_WRITE(NV10_PGRAPH_DEBUG_4, 0x1f000000);
+ NV_WRITE(0x004006b0, 0x40000020);
+ }
+ else
+ NV_WRITE(NV10_PGRAPH_DEBUG_4, 0x00000000);
/* copy tile info from PFB */
for (i=0; i<NV10_PFB_TILE__SIZE; i++) {
@@ -688,6 +760,10 @@ int nv10_graph_init(drm_device_t *dev) {
NV_WRITE(NV10_PGRAPH_TSTATUS(i), NV_READ(NV10_PFB_TSTATUS(i)));
}
+ NV_WRITE(NV10_PGRAPH_CTX_SWITCH1, 0x00000000);
+ NV_WRITE(NV10_PGRAPH_CTX_SWITCH2, 0x00000000);
+ NV_WRITE(NV10_PGRAPH_CTX_SWITCH3, 0x00000000);
+ NV_WRITE(NV10_PGRAPH_CTX_SWITCH4, 0x00000000);
NV_WRITE(NV10_PGRAPH_CTX_CONTROL, 0x10010100);
NV_WRITE(NV10_PGRAPH_STATE , 0xFFFFFFFF);
NV_WRITE(NV04_PGRAPH_FIFO , 0x00000001);
@@ -695,7 +771,7 @@ int nv10_graph_init(drm_device_t *dev) {
return 0;
}
-void nv10_graph_takedown(drm_device_t *dev)
+void nv10_graph_takedown(struct drm_device *dev)
{
}