From b2ee72f4400999b2cf783256547fe8c7bfa698f5 Mon Sep 17 00:00:00 2001 From: Matthieu Castet Date: Sun, 9 Sep 2007 12:13:00 +0200 Subject: nouveau : nv10 pipe ctx switch load/save. This fix some issues with more than one 3D fifo, but there still some "corruption" sometimes --- shared-core/nv10_graph.c | 333 ++++++++++++++++++++++++++++++----------------- 1 file changed, 215 insertions(+), 118 deletions(-) diff --git a/shared-core/nv10_graph.c b/shared-core/nv10_graph.c index e470ff06..f90ba05b 100644 --- a/shared-core/nv10_graph.c +++ b/shared-core/nv10_graph.c @@ -27,13 +27,68 @@ #include "nouveau_drm.h" #include "nouveau_drv.h" +#define NV10_FIFO_NUMBER 32 + +struct pipe_state { + uint32_t pipe_0x0000[0x040/4]; + uint32_t pipe_0x0040[0x010/4]; + uint32_t pipe_0x0200[0x0c0/4]; + uint32_t pipe_0x4400[0x080/4]; + uint32_t pipe_0x6400[0x3b0/4]; + uint32_t pipe_0x6800[0x2f0/4]; + uint32_t pipe_0x6c00[0x030/4]; + uint32_t pipe_0x7000[0x130/4]; + uint32_t pipe_0x7400[0x0c0/4]; + uint32_t pipe_0x7800[0x0c0/4]; +}; + +/* TODO dynamic allocation ??? */ +static struct pipe_state pipe_state[NV10_FIFO_NUMBER]; + +static void nv10_graph_save_pipe(struct nouveau_channel *chan) { + struct drm_device *dev = chan->dev; + struct drm_nouveau_private *dev_priv = dev->dev_private; + struct pipe_state *fifo_pipe_state = pipe_state + chan->id; + int i; +#define PIPE_SAVE(addr) \ + do { \ + NV_WRITE(NV10_PGRAPH_PIPE_ADDRESS, addr); \ + for (i=0; i < sizeof(fifo_pipe_state->pipe_##addr)/sizeof(fifo_pipe_state->pipe_##addr[0]); i++) \ + fifo_pipe_state->pipe_##addr[i] = NV_READ(NV10_PGRAPH_PIPE_DATA); \ + } while (0) + + PIPE_SAVE(0x4400); + PIPE_SAVE(0x0200); + PIPE_SAVE(0x6400); + PIPE_SAVE(0x6800); + PIPE_SAVE(0x6c00); + PIPE_SAVE(0x7000); + PIPE_SAVE(0x7400); + PIPE_SAVE(0x7800); + PIPE_SAVE(0x0040); + PIPE_SAVE(0x0000); + +#undef PIPE_SAVE +} -static void nv10_praph_pipe(struct drm_device *dev) { +static void nv10_graph_load_pipe(struct nouveau_channel *chan) { + struct drm_device *dev = chan->dev; struct drm_nouveau_private *dev_priv = dev->dev_private; + struct pipe_state *fifo_pipe_state = pipe_state + chan->id; int i; + uint32_t xfmode0, xfmode1; +#define PIPE_RESTORE(addr) \ + do { \ + NV_WRITE(NV10_PGRAPH_PIPE_ADDRESS, addr); \ + for (i=0; i < sizeof(fifo_pipe_state->pipe_##addr)/sizeof(fifo_pipe_state->pipe_##addr[0]); i++) \ + NV_WRITE(NV10_PGRAPH_PIPE_DATA, fifo_pipe_state->pipe_##addr[i]); \ + } while (0) + nouveau_wait_for_idle(dev); /* XXX check haiku comments */ + xfmode0 = NV_READ(NV10_PGRAPH_XFMODE0); + xfmode1 = NV_READ(NV10_PGRAPH_XFMODE1); NV_WRITE(NV10_PGRAPH_XFMODE0, 0x10000000); NV_WRITE(NV10_PGRAPH_XFMODE1, 0x00000000); NV_WRITE(NV10_PGRAPH_PIPE_ADDRESS, 0x000064c0); @@ -43,7 +98,6 @@ static void nv10_praph_pipe(struct drm_device *dev) { NV_WRITE(NV10_PGRAPH_PIPE_DATA, 0x00000000); NV_WRITE(NV10_PGRAPH_PIPE_ADDRESS, 0x00006ab0); - for (i = 0; i < 3; i++) NV_WRITE(NV10_PGRAPH_PIPE_DATA, 0x3f800000); @@ -54,131 +108,176 @@ static void nv10_praph_pipe(struct drm_device *dev) { NV_WRITE(NV10_PGRAPH_PIPE_ADDRESS, 0x00000040); NV_WRITE(NV10_PGRAPH_PIPE_DATA, 0x00000008); - NV_WRITE(NV10_PGRAPH_PIPE_ADDRESS, 0x00000200); - for (i = 0; i < 48; i++) - NV_WRITE(NV10_PGRAPH_PIPE_DATA, 0x00000000); + PIPE_RESTORE(0x0200); nouveau_wait_for_idle(dev); - NV_WRITE(NV10_PGRAPH_XFMODE0, 0x00000000); - NV_WRITE(NV10_PGRAPH_XFMODE1, 0x00000000); - NV_WRITE(NV10_PGRAPH_PIPE_ADDRESS, 0x00006400); - for (i = 0; i < 211; i++) - NV_WRITE(NV10_PGRAPH_PIPE_DATA, 0x00000000); + /* restore XFMODE */ + NV_WRITE(NV10_PGRAPH_XFMODE0, xfmode0); + NV_WRITE(NV10_PGRAPH_XFMODE1, xfmode1); + PIPE_RESTORE(0x6400); + PIPE_RESTORE(0x6800); + PIPE_RESTORE(0x6c00); + PIPE_RESTORE(0x7000); + PIPE_RESTORE(0x7400); + PIPE_RESTORE(0x7800); + PIPE_RESTORE(0x4400); + PIPE_RESTORE(0x0000); + PIPE_RESTORE(0x0040); + nouveau_wait_for_idle(dev); - NV_WRITE(NV10_PGRAPH_PIPE_DATA, 0x3f800000); - NV_WRITE(NV10_PGRAPH_PIPE_DATA, 0x40000000); - NV_WRITE(NV10_PGRAPH_PIPE_DATA, 0x40000000); - NV_WRITE(NV10_PGRAPH_PIPE_DATA, 0x40000000); - NV_WRITE(NV10_PGRAPH_PIPE_DATA, 0x40000000); - NV_WRITE(NV10_PGRAPH_PIPE_DATA, 0x00000000); - NV_WRITE(NV10_PGRAPH_PIPE_DATA, 0x00000000); - NV_WRITE(NV10_PGRAPH_PIPE_DATA, 0x3f800000); - NV_WRITE(NV10_PGRAPH_PIPE_DATA, 0x00000000); - NV_WRITE(NV10_PGRAPH_PIPE_DATA, 0x3f000000); - NV_WRITE(NV10_PGRAPH_PIPE_DATA, 0x3f000000); - NV_WRITE(NV10_PGRAPH_PIPE_DATA, 0x00000000); - NV_WRITE(NV10_PGRAPH_PIPE_DATA, 0x00000000); - NV_WRITE(NV10_PGRAPH_PIPE_DATA, 0x00000000); - NV_WRITE(NV10_PGRAPH_PIPE_DATA, 0x00000000); - NV_WRITE(NV10_PGRAPH_PIPE_DATA, 0x3f800000); - NV_WRITE(NV10_PGRAPH_PIPE_DATA, 0x00000000); - NV_WRITE(NV10_PGRAPH_PIPE_DATA, 0x00000000); - NV_WRITE(NV10_PGRAPH_PIPE_DATA, 0x00000000); - NV_WRITE(NV10_PGRAPH_PIPE_DATA, 0x00000000); - NV_WRITE(NV10_PGRAPH_PIPE_DATA, 0x00000000); - NV_WRITE(NV10_PGRAPH_PIPE_DATA, 0x3f800000); - NV_WRITE(NV10_PGRAPH_PIPE_DATA, 0x3f800000); - NV_WRITE(NV10_PGRAPH_PIPE_DATA, 0x3f800000); - NV_WRITE(NV10_PGRAPH_PIPE_DATA, 0x3f800000); - - NV_WRITE(NV10_PGRAPH_PIPE_ADDRESS, 0x00006800); +#undef PIPE_RESTORE +} + +static void nv10_graph_create_pipe(struct nouveau_channel *chan) { + struct pipe_state *fifo_pipe_state = pipe_state + chan->id; + uint32_t *fifo_pipe_state_addr; + int i; +#define PIPE_INIT(addr) \ + do { \ + fifo_pipe_state_addr = fifo_pipe_state->pipe_##addr; \ + } while (0) +#define PIPE_INIT_END(addr) \ + do { \ + if (fifo_pipe_state_addr != \ + sizeof(fifo_pipe_state->pipe_##addr)/sizeof(fifo_pipe_state->pipe_##addr[0]) + fifo_pipe_state->pipe_##addr) \ + DRM_ERROR("incomplete pipe init for 0x%x : %p/%p\n", addr, fifo_pipe_state_addr, \ + sizeof(fifo_pipe_state->pipe_##addr)/sizeof(fifo_pipe_state->pipe_##addr[0]) + fifo_pipe_state->pipe_##addr); \ + } while (0) +#define NV_WRITE_PIPE_INIT(value) *(fifo_pipe_state_addr++) = value + + PIPE_INIT(0x0200); + for (i = 0; i < 48; i++) + NV_WRITE_PIPE_INIT(0x00000000); + PIPE_INIT_END(0x0200); + + PIPE_INIT(0x6400); + for (i = 0; i < 211; i++) + NV_WRITE_PIPE_INIT(0x00000000); + NV_WRITE_PIPE_INIT(0x3f800000); + NV_WRITE_PIPE_INIT(0x40000000); + NV_WRITE_PIPE_INIT(0x40000000); + NV_WRITE_PIPE_INIT(0x40000000); + NV_WRITE_PIPE_INIT(0x40000000); + NV_WRITE_PIPE_INIT(0x00000000); + NV_WRITE_PIPE_INIT(0x00000000); + NV_WRITE_PIPE_INIT(0x3f800000); + NV_WRITE_PIPE_INIT(0x00000000); + NV_WRITE_PIPE_INIT(0x3f000000); + NV_WRITE_PIPE_INIT(0x3f000000); + NV_WRITE_PIPE_INIT(0x00000000); + NV_WRITE_PIPE_INIT(0x00000000); + NV_WRITE_PIPE_INIT(0x00000000); + NV_WRITE_PIPE_INIT(0x00000000); + NV_WRITE_PIPE_INIT(0x3f800000); + NV_WRITE_PIPE_INIT(0x00000000); + NV_WRITE_PIPE_INIT(0x00000000); + NV_WRITE_PIPE_INIT(0x00000000); + NV_WRITE_PIPE_INIT(0x00000000); + NV_WRITE_PIPE_INIT(0x00000000); + NV_WRITE_PIPE_INIT(0x3f800000); + NV_WRITE_PIPE_INIT(0x3f800000); + NV_WRITE_PIPE_INIT(0x3f800000); + NV_WRITE_PIPE_INIT(0x3f800000); + PIPE_INIT_END(0x6400); + + PIPE_INIT(0x6800); for (i = 0; i < 162; i++) - NV_WRITE(NV10_PGRAPH_PIPE_DATA, 0x00000000); - NV_WRITE(NV10_PGRAPH_PIPE_DATA, 0x3f800000); + NV_WRITE_PIPE_INIT(0x00000000); + NV_WRITE_PIPE_INIT(0x3f800000); for (i = 0; i < 25; i++) - NV_WRITE(NV10_PGRAPH_PIPE_DATA, 0x00000000); - - NV_WRITE(NV10_PGRAPH_PIPE_ADDRESS, 0x00006c00); - NV_WRITE(NV10_PGRAPH_PIPE_DATA, 0x00000000); - NV_WRITE(NV10_PGRAPH_PIPE_DATA, 0x00000000); - NV_WRITE(NV10_PGRAPH_PIPE_DATA, 0x00000000); - NV_WRITE(NV10_PGRAPH_PIPE_DATA, 0x00000000); - NV_WRITE(NV10_PGRAPH_PIPE_DATA, 0xbf800000); - NV_WRITE(NV10_PGRAPH_PIPE_DATA, 0x00000000); - NV_WRITE(NV10_PGRAPH_PIPE_DATA, 0x00000000); - NV_WRITE(NV10_PGRAPH_PIPE_DATA, 0x00000000); - NV_WRITE(NV10_PGRAPH_PIPE_DATA, 0x00000000); - NV_WRITE(NV10_PGRAPH_PIPE_DATA, 0x00000000); - NV_WRITE(NV10_PGRAPH_PIPE_DATA, 0x00000000); - NV_WRITE(NV10_PGRAPH_PIPE_DATA, 0x00000000); - NV_WRITE(NV10_PGRAPH_PIPE_ADDRESS, 0x00007000); - NV_WRITE(NV10_PGRAPH_PIPE_DATA, 0x00000000); - NV_WRITE(NV10_PGRAPH_PIPE_DATA, 0x00000000); - NV_WRITE(NV10_PGRAPH_PIPE_DATA, 0x00000000); - NV_WRITE(NV10_PGRAPH_PIPE_DATA, 0x00000000); - NV_WRITE(NV10_PGRAPH_PIPE_DATA, 0x00000000); - NV_WRITE(NV10_PGRAPH_PIPE_DATA, 0x00000000); - NV_WRITE(NV10_PGRAPH_PIPE_DATA, 0x00000000); - NV_WRITE(NV10_PGRAPH_PIPE_DATA, 0x00000000); - NV_WRITE(NV10_PGRAPH_PIPE_DATA, 0x00000000); - NV_WRITE(NV10_PGRAPH_PIPE_DATA, 0x00000000); - NV_WRITE(NV10_PGRAPH_PIPE_DATA, 0x00000000); - NV_WRITE(NV10_PGRAPH_PIPE_DATA, 0x00000000); - NV_WRITE(NV10_PGRAPH_PIPE_DATA, 0x7149f2ca); - NV_WRITE(NV10_PGRAPH_PIPE_DATA, 0x00000000); - NV_WRITE(NV10_PGRAPH_PIPE_DATA, 0x00000000); - NV_WRITE(NV10_PGRAPH_PIPE_DATA, 0x00000000); - NV_WRITE(NV10_PGRAPH_PIPE_DATA, 0x7149f2ca); - NV_WRITE(NV10_PGRAPH_PIPE_DATA, 0x00000000); - NV_WRITE(NV10_PGRAPH_PIPE_DATA, 0x00000000); - NV_WRITE(NV10_PGRAPH_PIPE_DATA, 0x00000000); - NV_WRITE(NV10_PGRAPH_PIPE_DATA, 0x7149f2ca); - NV_WRITE(NV10_PGRAPH_PIPE_DATA, 0x00000000); - NV_WRITE(NV10_PGRAPH_PIPE_DATA, 0x00000000); - NV_WRITE(NV10_PGRAPH_PIPE_DATA, 0x00000000); - NV_WRITE(NV10_PGRAPH_PIPE_DATA, 0x7149f2ca); - NV_WRITE(NV10_PGRAPH_PIPE_DATA, 0x00000000); - NV_WRITE(NV10_PGRAPH_PIPE_DATA, 0x00000000); - NV_WRITE(NV10_PGRAPH_PIPE_DATA, 0x00000000); - NV_WRITE(NV10_PGRAPH_PIPE_DATA, 0x7149f2ca); - NV_WRITE(NV10_PGRAPH_PIPE_DATA, 0x00000000); - NV_WRITE(NV10_PGRAPH_PIPE_DATA, 0x00000000); - NV_WRITE(NV10_PGRAPH_PIPE_DATA, 0x00000000); - NV_WRITE(NV10_PGRAPH_PIPE_DATA, 0x7149f2ca); - NV_WRITE(NV10_PGRAPH_PIPE_DATA, 0x00000000); - NV_WRITE(NV10_PGRAPH_PIPE_DATA, 0x00000000); - NV_WRITE(NV10_PGRAPH_PIPE_DATA, 0x00000000); - NV_WRITE(NV10_PGRAPH_PIPE_DATA, 0x7149f2ca); - NV_WRITE(NV10_PGRAPH_PIPE_DATA, 0x00000000); - NV_WRITE(NV10_PGRAPH_PIPE_DATA, 0x00000000); - NV_WRITE(NV10_PGRAPH_PIPE_DATA, 0x00000000); - NV_WRITE(NV10_PGRAPH_PIPE_DATA, 0x7149f2ca); + NV_WRITE_PIPE_INIT(0x00000000); + PIPE_INIT_END(0x6800); + + PIPE_INIT(0x6c00); + NV_WRITE_PIPE_INIT(0x00000000); + NV_WRITE_PIPE_INIT(0x00000000); + NV_WRITE_PIPE_INIT(0x00000000); + NV_WRITE_PIPE_INIT(0x00000000); + NV_WRITE_PIPE_INIT(0xbf800000); + NV_WRITE_PIPE_INIT(0x00000000); + NV_WRITE_PIPE_INIT(0x00000000); + NV_WRITE_PIPE_INIT(0x00000000); + NV_WRITE_PIPE_INIT(0x00000000); + NV_WRITE_PIPE_INIT(0x00000000); + NV_WRITE_PIPE_INIT(0x00000000); + NV_WRITE_PIPE_INIT(0x00000000); + PIPE_INIT_END(0x6c00); + + PIPE_INIT(0x7000); + NV_WRITE_PIPE_INIT(0x00000000); + NV_WRITE_PIPE_INIT(0x00000000); + NV_WRITE_PIPE_INIT(0x00000000); + NV_WRITE_PIPE_INIT(0x00000000); + NV_WRITE_PIPE_INIT(0x00000000); + NV_WRITE_PIPE_INIT(0x00000000); + NV_WRITE_PIPE_INIT(0x00000000); + NV_WRITE_PIPE_INIT(0x00000000); + NV_WRITE_PIPE_INIT(0x00000000); + NV_WRITE_PIPE_INIT(0x00000000); + NV_WRITE_PIPE_INIT(0x00000000); + NV_WRITE_PIPE_INIT(0x00000000); + NV_WRITE_PIPE_INIT(0x7149f2ca); + NV_WRITE_PIPE_INIT(0x00000000); + NV_WRITE_PIPE_INIT(0x00000000); + NV_WRITE_PIPE_INIT(0x00000000); + NV_WRITE_PIPE_INIT(0x7149f2ca); + NV_WRITE_PIPE_INIT(0x00000000); + NV_WRITE_PIPE_INIT(0x00000000); + NV_WRITE_PIPE_INIT(0x00000000); + NV_WRITE_PIPE_INIT(0x7149f2ca); + NV_WRITE_PIPE_INIT(0x00000000); + NV_WRITE_PIPE_INIT(0x00000000); + NV_WRITE_PIPE_INIT(0x00000000); + NV_WRITE_PIPE_INIT(0x7149f2ca); + NV_WRITE_PIPE_INIT(0x00000000); + NV_WRITE_PIPE_INIT(0x00000000); + NV_WRITE_PIPE_INIT(0x00000000); + NV_WRITE_PIPE_INIT(0x7149f2ca); + NV_WRITE_PIPE_INIT(0x00000000); + NV_WRITE_PIPE_INIT(0x00000000); + NV_WRITE_PIPE_INIT(0x00000000); + NV_WRITE_PIPE_INIT(0x7149f2ca); + NV_WRITE_PIPE_INIT(0x00000000); + NV_WRITE_PIPE_INIT(0x00000000); + NV_WRITE_PIPE_INIT(0x00000000); + NV_WRITE_PIPE_INIT(0x7149f2ca); + NV_WRITE_PIPE_INIT(0x00000000); + NV_WRITE_PIPE_INIT(0x00000000); + NV_WRITE_PIPE_INIT(0x00000000); + NV_WRITE_PIPE_INIT(0x7149f2ca); for (i = 0; i < 35; i++) - NV_WRITE(NV10_PGRAPH_PIPE_DATA, 0x00000000); - + NV_WRITE_PIPE_INIT(0x00000000); + PIPE_INIT_END(0x7000); - NV_WRITE(NV10_PGRAPH_PIPE_ADDRESS, 0x00007400); + PIPE_INIT(0x7400); for (i = 0; i < 48; i++) - NV_WRITE(NV10_PGRAPH_PIPE_DATA, 0x00000000); + NV_WRITE_PIPE_INIT(0x00000000); + PIPE_INIT_END(0x7400); - NV_WRITE(NV10_PGRAPH_PIPE_ADDRESS, 0x00007800); + PIPE_INIT(0x7800); for (i = 0; i < 48; i++) - NV_WRITE(NV10_PGRAPH_PIPE_DATA, 0x00000000); + NV_WRITE_PIPE_INIT(0x00000000); + PIPE_INIT_END(0x7800); - NV_WRITE(NV10_PGRAPH_PIPE_ADDRESS, 0x00004400); + PIPE_INIT(0x4400); for (i = 0; i < 32; i++) - NV_WRITE(NV10_PGRAPH_PIPE_DATA, 0x00000000); + NV_WRITE_PIPE_INIT(0x00000000); + PIPE_INIT_END(0x4400); - NV_WRITE(NV10_PGRAPH_PIPE_ADDRESS, 0x00000000); + PIPE_INIT(0x0000); for (i = 0; i < 16; i++) - NV_WRITE(NV10_PGRAPH_PIPE_DATA, 0x00000000); + NV_WRITE_PIPE_INIT(0x00000000); + PIPE_INIT_END(0x0000); - NV_WRITE(NV10_PGRAPH_PIPE_ADDRESS, 0x00000040); + PIPE_INIT(0x0040); for (i = 0; i < 4; i++) - NV_WRITE(NV10_PGRAPH_PIPE_DATA, 0x00000000); + NV_WRITE_PIPE_INIT(0x00000000); + PIPE_INIT_END(0x0040); - nouveau_wait_for_idle(dev); +#undef PIPE_INIT +#undef PIPE_INIT_END +#undef NV_WRITE_PIPE_INIT } static int nv10_graph_ctx_regs [] = { @@ -555,6 +654,8 @@ int nv10_graph_load_context(struct nouveau_channel *chan) } NV_WRITE(NV10_PGRAPH_CTX_USER, chan->id << 24); + nv10_graph_load_pipe(chan); + return 0; } @@ -571,6 +672,8 @@ int nv10_graph_save_context(struct nouveau_channel *chan) chan->pgraph_ctx[i] = NV_READ(nv17_graph_ctx_regs[j]); } + nv10_graph_save_pipe(chan); + return 0; } @@ -609,12 +712,13 @@ void nouveau_nv10_context_switch(struct drm_device *dev) DRM_DEBUG("WARNING: Invalid last channel, switch to %x\n", next->id); } else { - DRM_INFO("NV: PGRAPH context switch interrupt channel %x -> %x\n", + DRM_DEBUG("NV: PGRAPH context switch interrupt channel %x -> %x\n", last->id, next->id); } NV_WRITE(NV04_PGRAPH_FIFO,0x0); if (last) { + nouveau_wait_for_idle(dev); nv10_graph_save_context(last); } @@ -693,14 +797,7 @@ int nv10_graph_create_context(struct nouveau_channel *chan) { NV_WRITE_CTX(0x00400ed0, 0x00000080); } - /* for the first channel init the regs */ - if (dev_priv->fifo_alloc_count == 0) - nv10_graph_load_context(chan); - - - //XXX should be saved/restored for each fifo - //we supposed here we have X fifo and only one 3D fifo. - nv10_praph_pipe(dev); + nv10_graph_create_pipe(chan); return 0; } -- cgit v1.2.3