diff options
| -rw-r--r-- | shared-core/nv10_graph.c | 333 | 
1 files 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;  } | 
