diff options
Diffstat (limited to 'shared-core')
-rw-r--r-- | shared-core/i915_dma.c | 1 | ||||
-rw-r--r-- | shared-core/nouveau_drv.h | 22 | ||||
-rw-r--r-- | shared-core/nouveau_fifo.c | 150 | ||||
-rw-r--r-- | shared-core/nouveau_irq.c | 34 | ||||
-rw-r--r-- | shared-core/nouveau_reg.h | 96 | ||||
-rw-r--r-- | shared-core/nouveau_state.c | 14 | ||||
-rw-r--r-- | shared-core/nv10_graph.c | 594 | ||||
-rw-r--r-- | shared-core/nv20_graph.c | 155 | ||||
-rw-r--r-- | shared-core/nv30_graph.c | 243 | ||||
-rw-r--r-- | shared-core/nv40_graph.c | 2 | ||||
-rw-r--r-- | shared-core/radeon_cp.c | 8 |
11 files changed, 1241 insertions, 78 deletions
diff --git a/shared-core/i915_dma.c b/shared-core/i915_dma.c index cd7d2b43..a2f1243a 100644 --- a/shared-core/i915_dma.c +++ b/shared-core/i915_dma.c @@ -64,6 +64,7 @@ int i915_wait_ring(drm_device_t * dev, int n, const char *caller) i = 0; last_head = ring->head; + DRM_UDELAY(1); } return DRM_ERR(EBUSY); diff --git a/shared-core/nouveau_drv.h b/shared-core/nouveau_drv.h index 6b09046c..4978c476 100644 --- a/shared-core/nouveau_drv.h +++ b/shared-core/nouveau_drv.h @@ -90,8 +90,8 @@ struct nouveau_fifo /* objects belonging to this fifo */ struct nouveau_object *objs; - /* XXX move this in PGRAPH struct */ - uint32_t pgraph_ctx_user; + /* XXX dynamic alloc ? */ + uint32_t nv10_pgraph_ctx [340]; }; struct nouveau_config { @@ -142,6 +142,10 @@ typedef struct drm_nouveau_private { struct mem_block *fb_nomap_heap; struct mem_block *ramin_heap; + /* context table pointed to be NV_PGRAPH_CHANNEL_CTX_TABLE (0x400780) */ + uint32_t ctx_table_size; + struct mem_block *ctx_table; + struct nouveau_config config; } drm_nouveau_private_t; @@ -198,6 +202,20 @@ extern void nouveau_irq_preinstall(drm_device_t*); extern void nouveau_irq_postinstall(drm_device_t*); extern void nouveau_irq_uninstall(drm_device_t*); +/* nv10_graph.c */ +extern void nouveau_nv10_context_switch(drm_device_t *dev); +extern int nv10_graph_init(drm_device_t *dev); +extern int nv10_graph_context_create(drm_device_t *dev, int channel); + +/* nv20_graph.c */ +extern void nouveau_nv20_context_switch(drm_device_t *dev); +extern int nv20_graph_init(drm_device_t *dev); +extern int nv20_graph_context_create(drm_device_t *dev, int channel); + +/* nv30_graph.c */ +extern int nv30_graph_init(drm_device_t *dev); +extern int nv30_graph_context_create(drm_device_t *dev, int channel); + /* nv40_graph.c */ extern int nv40_graph_init(drm_device_t *dev); extern int nv40_graph_context_create(drm_device_t *dev, int channel); diff --git a/shared-core/nouveau_fifo.c b/shared-core/nouveau_fifo.c index e5f825e6..1e2870f1 100644 --- a/shared-core/nouveau_fifo.c +++ b/shared-core/nouveau_fifo.c @@ -265,9 +265,9 @@ nouveau_fifo_cmdbuf_alloc(struct drm_device *dev, int channel) #define RAMFC_WR(offset, val) NV_WRITE(fifoctx + NV04_RAMFC_##offset, (val)) static void nouveau_nv04_context_init(drm_device_t *dev, - drm_nouveau_fifo_alloc_t *init) + drm_nouveau_fifo_alloc_t *init) { - drm_nouveau_private_t *dev_priv = dev->dev_private; + drm_nouveau_private_t *dev_priv = dev->dev_private; struct nouveau_object *cb_obj; uint32_t fifoctx, ctx_size = 32; int i; @@ -275,53 +275,106 @@ static void nouveau_nv04_context_init(drm_device_t *dev, cb_obj = dev_priv->fifos[init->channel].cmdbuf_obj; fifoctx=NV_RAMIN+dev_priv->ramfc_offset+init->channel*ctx_size; - // clear the fifo context - for(i=0;i<ctx_size/4;i++) - NV_WRITE(fifoctx+4*i,0x0); + + // clear the fifo context + for(i=0;i<ctx_size/4;i++) + NV_WRITE(fifoctx+4*i,0x0); - RAMFC_WR(DMA_PUT , init->put_base); + RAMFC_WR(DMA_PUT , init->put_base); RAMFC_WR(DMA_GET , init->put_base); RAMFC_WR(DMA_INSTANCE , nouveau_chip_instance_get(dev, cb_obj->instance)); #ifdef __BIG_ENDIAN - RAMFC_WR(DMA_FETCH, NV_PFIFO_CACH1_DMAF_TRIG_112_BYTES|NV_PFIFO_CACH1_DMAF_SIZE_128_BYTES|NV_PFIFO_CACH1_DMAF_MAX_REQS_4|NV_PFIFO_CACH1_BIG_ENDIAN); + RAMFC_WR(DMA_FETCH, NV_PFIFO_CACH1_DMAF_TRIG_112_BYTES | + NV_PFIFO_CACH1_DMAF_SIZE_128_BYTES | + NV_PFIFO_CACH1_DMAF_MAX_REQS_4 | + NV_PFIFO_CACH1_BIG_ENDIAN); #else - RAMFC_WR(DMA_FETCH, NV_PFIFO_CACH1_DMAF_TRIG_112_BYTES|NV_PFIFO_CACH1_DMAF_SIZE_128_BYTES|NV_PFIFO_CACH1_DMAF_MAX_REQS_4); + RAMFC_WR(DMA_FETCH, NV_PFIFO_CACH1_DMAF_TRIG_112_BYTES | + NV_PFIFO_CACH1_DMAF_SIZE_128_BYTES | + NV_PFIFO_CACH1_DMAF_MAX_REQS_4); #endif } #undef RAMFC_WR #define RAMFC_WR(offset, val) NV_WRITE(fifoctx + NV10_RAMFC_##offset, (val)) static void nouveau_nv10_context_init(drm_device_t *dev, - drm_nouveau_fifo_alloc_t *init) + drm_nouveau_fifo_alloc_t *init) { - drm_nouveau_private_t *dev_priv = dev->dev_private; + drm_nouveau_private_t *dev_priv = dev->dev_private; + struct nouveau_object *cb_obj; + uint32_t fifoctx; + int i; + cb_obj = dev_priv->fifos[init->channel].cmdbuf_obj; + fifoctx = NV_RAMIN + dev_priv->ramfc_offset + init->channel*64; + + for (i=0;i<64;i+=4) + NV_WRITE(fifoctx + i, 0); + + /* Fill entries that are seen filled in dumps of nvidia driver just + * after channel's is put into DMA mode + */ + + RAMFC_WR(DMA_PUT , init->put_base); + RAMFC_WR(DMA_GET , init->put_base); + RAMFC_WR(DMA_INSTANCE , nouveau_chip_instance_get(dev, + cb_obj->instance)); +#ifdef __BIG_ENDIAN + RAMFC_WR(DMA_FETCH, NV_PFIFO_CACH1_DMAF_TRIG_112_BYTES | + NV_PFIFO_CACH1_DMAF_SIZE_128_BYTES | + NV_PFIFO_CACH1_DMAF_MAX_REQS_4 | + NV_PFIFO_CACH1_BIG_ENDIAN); +#else + + RAMFC_WR(DMA_FETCH, NV_PFIFO_CACH1_DMAF_TRIG_112_BYTES | + NV_PFIFO_CACH1_DMAF_SIZE_128_BYTES | + NV_PFIFO_CACH1_DMAF_MAX_REQS_4); +#endif +} + +static void nouveau_nv30_context_init(drm_device_t *dev, + drm_nouveau_fifo_alloc_t *init) +{ + drm_nouveau_private_t *dev_priv = dev->dev_private; + struct nouveau_fifo *chan = &dev_priv->fifos[init->channel]; struct nouveau_object *cb_obj; - uint32_t fifoctx; + uint32_t fifoctx, grctx_inst, cb_inst, ctx_size = 64; int i; - cb_obj = dev_priv->fifos[init->channel].cmdbuf_obj; - fifoctx = NV_RAMIN + dev_priv->ramfc_offset + init->channel*64; - for (i=0;i<64;i+=4) - NV_WRITE(fifoctx + i, 0); - - /* Fill entries that are seen filled in dumps of nvidia driver just - * after channel's is put into DMA mode - */ - RAMFC_WR(DMA_PUT , init->put_base); - RAMFC_WR(DMA_GET , init->put_base); - RAMFC_WR(DMA_INSTANCE , nouveau_chip_instance_get(dev, - cb_obj->instance)); + cb_obj = dev_priv->fifos[init->channel].cmdbuf_obj; + cb_inst = nouveau_chip_instance_get(dev, chan->cmdbuf_obj->instance); + grctx_inst = nouveau_chip_instance_get(dev, chan->ramin_grctx); + fifoctx = NV_RAMIN + dev_priv->ramfc_offset + init->channel * ctx_size; + + for (i = 0; i < ctx_size; i += 4) + NV_WRITE(fifoctx + i, 0); + + RAMFC_WR(DMA_PUT, init->put_base); + RAMFC_WR(DMA_GET, init->put_base); + RAMFC_WR(REF_CNT, NV_READ(NV_PFIFO_CACH1_REF_CNT)); + RAMFC_WR(DMA_INSTANCE, cb_inst); + RAMFC_WR(DMA_STATE, NV_READ(NV_PFIFO_CACH1_DMAS)); + RAMFC_WR(DMA_FETCH, NV_PFIFO_CACH1_DMAF_TRIG_128_BYTES | + NV_PFIFO_CACH1_DMAF_SIZE_128_BYTES | + NV_PFIFO_CACH1_DMAF_MAX_REQS_8 | #ifdef __BIG_ENDIAN - RAMFC_WR(DMA_FETCH, NV_PFIFO_CACH1_DMAF_TRIG_112_BYTES | - NV_PFIFO_CACH1_DMAF_SIZE_128_BYTES | - NV_PFIFO_CACH1_DMAF_MAX_REQS_4 | - NV_PFIFO_CACH1_BIG_ENDIAN); + NV_PFIFO_CACH1_BIG_ENDIAN | #else - RAMFC_WR(DMA_FETCH, NV_PFIFO_CACH1_DMAF_TRIG_112_BYTES | - NV_PFIFO_CACH1_DMAF_SIZE_128_BYTES | - NV_PFIFO_CACH1_DMAF_MAX_REQS_4); + 0x00000000); #endif - RAMFC_WR(DMA_SUBROUTINE, 0); + + RAMFC_WR(ENGINE, NV_READ(NV_PFIFO_CACH1_ENG)); + RAMFC_WR(PULL1_ENGINE, NV_READ(NV_PFIFO_CACH1_PUL1)); + RAMFC_WR(ACQUIRE_VALUE, NV_READ(NV_PFIFO_CACH1_ACQUIRE_VALUE)); + RAMFC_WR(ACQUIRE_TIMESTAMP, NV_READ(NV_PFIFO_CACH1_ACQUIRE_TIMESTAMP)); + RAMFC_WR(ACQUIRE_TIMEOUT, NV_READ(NV_PFIFO_CACH1_ACQUIRE_TIMEOUT)); + RAMFC_WR(SEMAPHORE, NV_READ(NV_PFIFO_CACH1_SEMAPHORE)); + NV_WRITE(NV_PGRAPH_CHANNEL_CTX_SIZE, grctx_inst); /* Misnomer. Really a ptr to the grctx */ + + /* + * TODO: We need to put this somewhere... + */ + /* INSTANCE_WR(dev_priv->ctx_table, init->channel, grctx_inst); */ + RAMFC_WR(DMA_SUBROUTINE, init->put_base); } static void nouveau_nv10_context_save(drm_device_t *dev) @@ -485,7 +538,6 @@ static int nouveau_fifo_alloc(drm_device_t* dev,drm_nouveau_fifo_alloc_t* init, init->channel = i; init->put_base = 0; dev_priv->cur_fifo = init->channel; - dev_priv->fifos[i].pgraph_ctx_user = i << 24; nouveau_wait_for_idle(dev); @@ -498,8 +550,23 @@ static int nouveau_fifo_alloc(drm_device_t* dev,drm_nouveau_fifo_alloc_t* init, /* Construct inital RAMFC for new channel */ if (dev_priv->card_type < NV_10) { nouveau_nv04_context_init(dev, init); - } else if (dev_priv->card_type < NV_40) { + } else if (dev_priv->card_type < NV_20) { + nv10_graph_context_create(dev, init->channel); + nouveau_nv10_context_init(dev, init); + } else if (dev_priv->card_type < NV_30) { + ret = nv20_graph_context_create(dev, init->channel); + if (ret) { + nouveau_fifo_free(dev, init->channel); + return ret; + } nouveau_nv10_context_init(dev, init); + } else if (dev_priv->card_type < NV_40) { + ret = nv30_graph_context_create(dev, init->channel); + if (ret) { + nouveau_fifo_free(dev, init->channel); + return ret; + } + nouveau_nv30_context_init(dev, init); } else { ret = nv40_graph_context_create(dev, init->channel); if (ret) { @@ -521,7 +588,7 @@ static int nouveau_fifo_alloc(drm_device_t* dev,drm_nouveau_fifo_alloc_t* init, */ if (dev_priv->fifo_alloc_count == 0) { nouveau_fifo_context_restore(dev, init->channel); - if (dev_priv->card_type >= NV_40) { + if (dev_priv->card_type >= NV_30) { struct nouveau_fifo *chan; uint32_t inst; @@ -530,9 +597,11 @@ static int nouveau_fifo_alloc(drm_device_t* dev,drm_nouveau_fifo_alloc_t* init, chan->ramin_grctx); /* see comments in nv40_graph_context_restore() */ - NV_WRITE(0x400784, inst); - NV_WRITE(0x40032C, inst | 0x01000000); - NV_WRITE(NV40_PFIFO_GRCTX_INSTANCE, inst); + NV_WRITE(NV_PGRAPH_CHANNEL_CTX_SIZE, inst); + if (dev_priv->card_type >= NV_40) { + NV_WRITE(0x40032C, inst | 0x01000000); + NV_WRITE(NV40_PFIFO_GRCTX_INSTANCE, inst); + } } } @@ -590,6 +659,13 @@ void nouveau_fifo_free(drm_device_t* dev,int n) if (dev_priv->card_type >= NV_40) nouveau_instmem_free(dev, dev_priv->fifos[n].ramin_grctx); + else if (dev_priv->card_type >= NV_30) { + } + else if (dev_priv->card_type >= NV_20) { + /* clear ctx table */ + INSTANCE_WR(dev_priv->ctx_table, n, 0); + nouveau_instmem_free(dev, dev_priv->fifos[n].ramin_grctx); + } /* reenable the fifo caches */ NV_WRITE(NV_PFIFO_CACHES, 0x00000001); diff --git a/shared-core/nouveau_irq.c b/shared-core/nouveau_irq.c index 7a31fb0b..a92b8168 100644 --- a/shared-core/nouveau_irq.c +++ b/shared-core/nouveau_irq.c @@ -237,37 +237,6 @@ static void nouveau_nv04_context_switch(drm_device_t *dev) } -static void nouveau_nv10_context_switch(drm_device_t *dev) -{ - drm_nouveau_private_t *dev_priv = dev->dev_private; - int channel, channel_old; - - channel=NV_READ(NV_PFIFO_CACH1_PSH1)&(nouveau_fifo_number(dev)-1); - channel_old = (NV_READ(NV_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(NV_PGRAPH_FIFO,0x0); - NV_WRITE(NV_PFIFO_CACH1_PUL0, 0x00000000); - NV_WRITE(NV_PFIFO_CACH1_PUL1, 0x00000000); - NV_WRITE(NV_PFIFO_CACHES, 0x00000000); - - dev_priv->fifos[channel_old].pgraph_ctx_user = NV_READ(NV_PGRAPH_CTX_USER); - //XXX save PGRAPH context - NV_WRITE(NV_PGRAPH_CTX_CONTROL, 0x10000000); - NV_WRITE(NV_PGRAPH_CTX_USER, dev_priv->fifos[channel].pgraph_ctx_user); - //XXX restore PGRAPH context - printk("ctx_user %x %x\n", dev_priv->fifos[channel_old].pgraph_ctx_user, dev_priv->fifos[channel].pgraph_ctx_user); - - NV_WRITE(NV_PGRAPH_FFINTFC_ST2, NV_READ(NV_PGRAPH_FFINTFC_ST2)&0xCFFFFFFF); - NV_WRITE(NV_PGRAPH_CTX_CONTROL, 0x10010100); - - NV_WRITE(NV_PFIFO_CACH1_PUL0, 0x00000001); - NV_WRITE(NV_PFIFO_CACH1_PUL1, 0x00000001); - NV_WRITE(NV_PFIFO_CACHES, 0x00000001); - NV_WRITE(NV_PGRAPH_FIFO,0x1); -} - static void nouveau_pgraph_irq_handler(drm_device_t *dev) { uint32_t status; @@ -360,6 +329,9 @@ static void nouveau_pgraph_irq_handler(drm_device_t *dev) case NV_10: nouveau_nv10_context_switch(dev); break; + case NV_20: + nouveau_nv20_context_switch(dev); + break; default: DRM_INFO("NV: Context switch not implemented\n"); break; diff --git a/shared-core/nouveau_reg.h b/shared-core/nouveau_reg.h index 23fce39a..543be694 100644 --- a/shared-core/nouveau_reg.h +++ b/shared-core/nouveau_reg.h @@ -55,6 +55,7 @@ #define NV_PMC_INTEN 0x00000140 # define NV_PMC_INTEN_MASTER_ENABLE (1<< 0) +#define NV_PGRAPH_DEBUG_4 0x00400090 #define NV_PGRAPH_INTSTAT 0x00400100 #define NV04_PGRAPH_INTEN 0x00400140 #define NV40_PGRAPH_INTEN 0x0040013C @@ -68,8 +69,101 @@ # define NV_PGRAPH_NV40_UNK220_FB_INSTANCE #define NV_PGRAPH_CTX_USER 0x00400148 #define NV_PGRAPH_CTX_SWITCH1 0x0040014C +#define NV_PGRAPH_CTX_SWITCH2 0x00400150 +#define NV_PGRAPH_CTX_SWITCH3 0x00400154 +#define NV_PGRAPH_CTX_SWITCH4 0x00400158 +#define NV_PGRAPH_CTX_SWITCH5 0x0040015C +#define NV_PGRAPH_X_MISC 0x00400500 +#define NV_PGRAPH_Y_MISC 0x00400504 +#define NV_PGRAPH_VALID1 0x00400508 +#define NV_PGRAPH_SOURCE_COLOR 0x0040050C +#define NV_PGRAPH_MISC24_0 0x00400510 +#define NV_PGRAPH_XY_LOGIC_MISC0 0x00400514 +#define NV_PGRAPH_XY_LOGIC_MISC1 0x00400518 +#define NV_PGRAPH_XY_LOGIC_MISC2 0x0040051C +#define NV_PGRAPH_XY_LOGIC_MISC3 0x00400520 +#define NV_PGRAPH_CLIPX_0 0x00400524 +#define NV_PGRAPH_CLIPX_1 0x00400528 +#define NV_PGRAPH_CLIPY_0 0x0040052C +#define NV_PGRAPH_CLIPY_1 0x00400530 +#define NV_PGRAPH_ABS_ICLIP_XMAX 0x00400534 +#define NV_PGRAPH_ABS_ICLIP_YMAX 0x00400538 +#define NV_PGRAPH_ABS_UCLIP_XMIN 0x0040053C +#define NV_PGRAPH_ABS_UCLIP_YMIN 0x00400540 +#define NV_PGRAPH_ABS_UCLIP_XMAX 0x00400544 +#define NV_PGRAPH_ABS_UCLIP_YMAX 0x00400548 +#define NV_PGRAPH_ABS_UCLIPA_XMIN 0x00400560 +#define NV_PGRAPH_ABS_UCLIPA_YMIN 0x00400564 +#define NV_PGRAPH_ABS_UCLIPA_XMAX 0x00400568 +#define NV_PGRAPH_ABS_UCLIPA_YMAX 0x0040056C +#define NV_PGRAPH_MISC24_1 0x00400570 +#define NV_PGRAPH_MISC24_2 0x00400574 +#define NV_PGRAPH_VALID2 0x00400578 +#define NV_PGRAPH_PASSTHRU_0 0x0040057C +#define NV_PGRAPH_PASSTHRU_1 0x00400580 +#define NV_PGRAPH_PASSTHRU_2 0x00400584 +#define NV_PGRAPH_DIMX_TEXTURE 0x00400588 +#define NV_PGRAPH_WDIMX_TEXTURE 0x0040058C +#define NV_PGRAPH_MONO_COLOR0 0x00400600 +#define NV_PGRAPH_ROP3 0x00400604 +#define NV_PGRAPH_BETA_AND 0x00400608 +#define NV_PGRAPH_BETA_PREMULT 0x0040060C +#define NV_PGRAPH_BOFFSET0 0x00400640 +#define NV_PGRAPH_BOFFSET1 0x00400644 +#define NV_PGRAPH_BOFFSET2 0x00400648 +#define NV_PGRAPH_BOFFSET3 0x0040064C +#define NV_PGRAPH_BOFFSET4 0x00400650 +#define NV_PGRAPH_BOFFSET5 0x00400654 +#define NV_PGRAPH_BBASE0 0x00400658 +#define NV_PGRAPH_BBASE1 0x0040065C +#define NV_PGRAPH_BBASE2 0x00400660 +#define NV_PGRAPH_BBASE3 0x00400664 +#define NV_PGRAPH_BBASE4 0x00400668 +#define NV_PGRAPH_BBASE5 0x0040066C +#define NV_PGRAPH_BPITCH0 0x00400670 +#define NV_PGRAPH_BPITCH1 0x00400674 +#define NV_PGRAPH_BPITCH2 0x00400678 +#define NV_PGRAPH_BPITCH3 0x0040067C +#define NV_PGRAPH_BPITCH4 0x00400680 +#define NV_PGRAPH_BLIMIT0 0x00400684 +#define NV_PGRAPH_BLIMIT1 0x00400688 +#define NV_PGRAPH_BLIMIT2 0x0040068C +#define NV_PGRAPH_BLIMIT3 0x00400690 +#define NV_PGRAPH_BLIMIT4 0x00400694 +#define NV_PGRAPH_BLIMIT5 0x00400698 +#define NV_PGRAPH_BSWIZZLE2 0x0040069C +#define NV_PGRAPH_BSWIZZLE5 0x004006A0 +#define NV_PGRAPH_SURFACE 0x00400710 +#define NV_PGRAPH_STATE 0x00400714 +#define NV_PGRAPH_NOTIFY 0x00400718 + #define NV_PGRAPH_FIFO 0x00400720 + +#define NV_PGRAPH_BPIXEL 0x00400724 +#define NV_PGRAPH_RDI_INDEX 0x00400750 +#define NV_PGRAPH_RDI_DATA 0x00400754 #define NV_PGRAPH_FFINTFC_ST2 0x00400764 +#define NV_PGRAPH_DMA_PITCH 0x00400770 +#define NV_PGRAPH_DVD_COLORFMT 0x00400774 +#define NV_PGRAPH_SCALED_FORMAT 0x00400778 +#define NV_PGRAPH_CHANNEL_CTX_TABLE 0x00400780 +#define NV_PGRAPH_CHANNEL_CTX_SIZE 0x00400784 +#define NV_PGRAPH_CHANNEL_CTX_POINTER 0x00400788 +#define NV_PGRAPH_PATT_COLOR0 0x00400800 +#define NV_PGRAPH_PATT_COLOR1 0x00400804 +#define NV_PGRAPH_PATTERN_SHAPE 0x00400810 +#define NV_PGRAPH_CHROMA 0x00400814 +#define NV_PGRAPH_STORED_FMT 0x00400830 +#define NV_PGRAPH_XFMODE0 0x00400F40 +#define NV_PGRAPH_XFMODE1 0x00400F44 +#define NV_PGRAPH_GLOBALSTATE0 0x00400F48 +#define NV_PGRAPH_GLOBALSTATE1 0x00400F4C +#define NV_PGRAPH_PIPE_ADDRESS 0x00400F50 +#define NV_PGRAPH_PIPE_DATA 0x00400F54 +#define NV_PGRAPH_DMA_START_0 0x00401000 +#define NV_PGRAPH_DMA_START_1 0x00401004 +#define NV_PGRAPH_DMA_LENGTH 0x00401008 +#define NV_PGRAPH_DMA_MISC 0x0040100C /* It's a guess that this works on NV03. Confirmed on NV04, though */ #define NV_PFIFO_DELAY_0 0x00002040 @@ -198,7 +292,7 @@ #define NV04_RAMFC_DMA_PUT 0x00 #define NV04_RAMFC_DMA_GET 0x04 #define NV04_RAMFC_DMA_INSTANCE 0x08 -#define NV04_RAMFC_DMA_FETCH 0x16 +#define NV04_RAMFC_DMA_FETCH 0x10 #define NV10_RAMFC_DMA_PUT 0x00 #define NV10_RAMFC_DMA_GET 0x04 diff --git a/shared-core/nouveau_state.c b/shared-core/nouveau_state.c index 44f8c1aa..f324c5ff 100644 --- a/shared-core/nouveau_state.c +++ b/shared-core/nouveau_state.c @@ -66,8 +66,12 @@ int nouveau_firstopen(struct drm_device *dev) /* map larger RAMIN aperture on NV40 cards */ if (dev_priv->card_type >= NV_40) { - ret = drm_addmap(dev, drm_get_resource_start(dev, 2), - drm_get_resource_len(dev, 2), + int ramin_resource = 2; + if (drm_get_resource_len(dev, ramin_resource) == 0) + ramin_resource = 3; + + ret = drm_addmap(dev, drm_get_resource_start(dev, ramin_resource), + drm_get_resource_len(dev, ramin_resource), _DRM_REGISTERS, _DRM_READ_ONLY, &dev_priv->ramin); @@ -92,6 +96,12 @@ int nouveau_firstopen(struct drm_device *dev) /* FIXME: doesn't belong here, and have no idea what it's for.. */ if (dev_priv->card_type >= NV_40) nv40_graph_init(dev); + else if (dev_priv->card_type >= NV_30) { + } + else if (dev_priv->card_type >= NV_20) + nv20_graph_init(dev); + else if (dev_priv->card_type >= NV_10) + nv10_graph_init(dev); return 0; } diff --git a/shared-core/nv10_graph.c b/shared-core/nv10_graph.c new file mode 100644 index 00000000..ccbb34de --- /dev/null +++ b/shared-core/nv10_graph.c @@ -0,0 +1,594 @@ +/* + * Copyright 2007 Matthieu CASTET <castet.matthieu@free.fr> + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +#include "drmP.h" +#include "drm.h" +#include "nouveau_drm.h" +#include "nouveau_drv.h" + + +static void nv10_praph_pipe(drm_device_t *dev) { + drm_nouveau_private_t *dev_priv = dev->dev_private; + int i; + + nouveau_wait_for_idle(dev); + /* XXX check haiku comments */ + NV_WRITE(NV_PGRAPH_XFMODE0, 0x10000000); + NV_WRITE(NV_PGRAPH_XFMODE1, 0x00000000); + NV_WRITE(NV_PGRAPH_PIPE_ADDRESS, 0x000064c0); + for (i = 0; i < 4; i++) + NV_WRITE(NV_PGRAPH_PIPE_DATA, 0x3f800000); + for (i = 0; i < 4; i++) + NV_WRITE(NV_PGRAPH_PIPE_DATA, 0x00000000); + + NV_WRITE(NV_PGRAPH_PIPE_ADDRESS, 0x00006ab0); + + for (i = 0; i < 3; i++) + NV_WRITE(NV_PGRAPH_PIPE_DATA, 0x3f800000); + + NV_WRITE(NV_PGRAPH_PIPE_ADDRESS, 0x00006a80); + for (i = 0; i < 3; i++) + NV_WRITE(NV_PGRAPH_PIPE_DATA, 0x00000000); + + NV_WRITE(NV_PGRAPH_PIPE_ADDRESS, 0x00000040); + NV_WRITE(NV_PGRAPH_PIPE_DATA, 0x00000008); + + NV_WRITE(NV_PGRAPH_PIPE_ADDRESS, 0x00000200); + for (i = 0; i < 48; i++) + NV_WRITE(NV_PGRAPH_PIPE_DATA, 0x00000000); + + nouveau_wait_for_idle(dev); + + NV_WRITE(NV_PGRAPH_XFMODE0, 0x00000000); + NV_WRITE(NV_PGRAPH_XFMODE1, 0x00000000); + NV_WRITE(NV_PGRAPH_PIPE_ADDRESS, 0x00006400); + for (i = 0; i < 211; i++) + NV_WRITE(NV_PGRAPH_PIPE_DATA, 0x00000000); + + NV_WRITE(NV_PGRAPH_PIPE_DATA, 0x3f800000); + NV_WRITE(NV_PGRAPH_PIPE_DATA, 0x40000000); + NV_WRITE(NV_PGRAPH_PIPE_DATA, 0x40000000); + NV_WRITE(NV_PGRAPH_PIPE_DATA, 0x40000000); + NV_WRITE(NV_PGRAPH_PIPE_DATA, 0x40000000); + NV_WRITE(NV_PGRAPH_PIPE_DATA, 0x00000000); + NV_WRITE(NV_PGRAPH_PIPE_DATA, 0x00000000); + NV_WRITE(NV_PGRAPH_PIPE_DATA, 0x3f800000); + NV_WRITE(NV_PGRAPH_PIPE_DATA, 0x00000000); + NV_WRITE(NV_PGRAPH_PIPE_DATA, 0x3f000000); + NV_WRITE(NV_PGRAPH_PIPE_DATA, 0x3f000000); + NV_WRITE(NV_PGRAPH_PIPE_DATA, 0x00000000); + NV_WRITE(NV_PGRAPH_PIPE_DATA, 0x00000000); + NV_WRITE(NV_PGRAPH_PIPE_DATA, 0x00000000); + NV_WRITE(NV_PGRAPH_PIPE_DATA, 0x00000000); + NV_WRITE(NV_PGRAPH_PIPE_DATA, 0x3f800000); + NV_WRITE(NV_PGRAPH_PIPE_DATA, 0x00000000); + NV_WRITE(NV_PGRAPH_PIPE_DATA, 0x00000000); + NV_WRITE(NV_PGRAPH_PIPE_DATA, 0x00000000); + NV_WRITE(NV_PGRAPH_PIPE_DATA, 0x00000000); + NV_WRITE(NV_PGRAPH_PIPE_DATA, 0x00000000); + NV_WRITE(NV_PGRAPH_PIPE_DATA, 0x3f800000); + NV_WRITE(NV_PGRAPH_PIPE_DATA, 0x3f800000); + NV_WRITE(NV_PGRAPH_PIPE_DATA, 0x3f800000); + NV_WRITE(NV_PGRAPH_PIPE_DATA, 0x3f800000); + + NV_WRITE(NV_PGRAPH_PIPE_ADDRESS, 0x00006800); + for (i = 0; i < 162; i++) + NV_WRITE(NV_PGRAPH_PIPE_DATA, 0x00000000); + NV_WRITE(NV_PGRAPH_PIPE_DATA, 0x3f800000); + for (i = 0; i < 25; i++) + NV_WRITE(NV_PGRAPH_PIPE_DATA, 0x00000000); + + NV_WRITE(NV_PGRAPH_PIPE_ADDRESS, 0x00006c00); + NV_WRITE(NV_PGRAPH_PIPE_DATA, 0x00000000); + NV_WRITE(NV_PGRAPH_PIPE_DATA, 0x00000000); + NV_WRITE(NV_PGRAPH_PIPE_DATA, 0x00000000); + NV_WRITE(NV_PGRAPH_PIPE_DATA, 0x00000000); + NV_WRITE(NV_PGRAPH_PIPE_DATA, 0xbf800000); + NV_WRITE(NV_PGRAPH_PIPE_DATA, 0x00000000); + NV_WRITE(NV_PGRAPH_PIPE_DATA, 0x00000000); + NV_WRITE(NV_PGRAPH_PIPE_DATA, 0x00000000); + NV_WRITE(NV_PGRAPH_PIPE_DATA, 0x00000000); + NV_WRITE(NV_PGRAPH_PIPE_DATA, 0x00000000); + NV_WRITE(NV_PGRAPH_PIPE_DATA, 0x00000000); + NV_WRITE(NV_PGRAPH_PIPE_DATA, 0x00000000); + NV_WRITE(NV_PGRAPH_PIPE_ADDRESS, 0x00007000); + NV_WRITE(NV_PGRAPH_PIPE_DATA, 0x00000000); + NV_WRITE(NV_PGRAPH_PIPE_DATA, 0x00000000); + NV_WRITE(NV_PGRAPH_PIPE_DATA, 0x00000000); + NV_WRITE(NV_PGRAPH_PIPE_DATA, 0x00000000); + NV_WRITE(NV_PGRAPH_PIPE_DATA, 0x00000000); + NV_WRITE(NV_PGRAPH_PIPE_DATA, 0x00000000); + NV_WRITE(NV_PGRAPH_PIPE_DATA, 0x00000000); + NV_WRITE(NV_PGRAPH_PIPE_DATA, 0x00000000); + NV_WRITE(NV_PGRAPH_PIPE_DATA, 0x00000000); + NV_WRITE(NV_PGRAPH_PIPE_DATA, 0x00000000); + NV_WRITE(NV_PGRAPH_PIPE_DATA, 0x00000000); + NV_WRITE(NV_PGRAPH_PIPE_DATA, 0x00000000); + NV_WRITE(NV_PGRAPH_PIPE_DATA, 0x7149f2ca); + NV_WRITE(NV_PGRAPH_PIPE_DATA, 0x00000000); + NV_WRITE(NV_PGRAPH_PIPE_DATA, 0x00000000); + NV_WRITE(NV_PGRAPH_PIPE_DATA, 0x00000000); + NV_WRITE(NV_PGRAPH_PIPE_DATA, 0x7149f2ca); + NV_WRITE(NV_PGRAPH_PIPE_DATA, 0x00000000); + NV_WRITE(NV_PGRAPH_PIPE_DATA, 0x00000000); + NV_WRITE(NV_PGRAPH_PIPE_DATA, 0x00000000); + NV_WRITE(NV_PGRAPH_PIPE_DATA, 0x7149f2ca); + NV_WRITE(NV_PGRAPH_PIPE_DATA, 0x00000000); + NV_WRITE(NV_PGRAPH_PIPE_DATA, 0x00000000); + NV_WRITE(NV_PGRAPH_PIPE_DATA, 0x00000000); + NV_WRITE(NV_PGRAPH_PIPE_DATA, 0x7149f2ca); + NV_WRITE(NV_PGRAPH_PIPE_DATA, 0x00000000); + NV_WRITE(NV_PGRAPH_PIPE_DATA, 0x00000000); + NV_WRITE(NV_PGRAPH_PIPE_DATA, 0x00000000); + NV_WRITE(NV_PGRAPH_PIPE_DATA, 0x7149f2ca); + NV_WRITE(NV_PGRAPH_PIPE_DATA, 0x00000000); + NV_WRITE(NV_PGRAPH_PIPE_DATA, 0x00000000); + NV_WRITE(NV_PGRAPH_PIPE_DATA, 0x00000000); + NV_WRITE(NV_PGRAPH_PIPE_DATA, 0x7149f2ca); + NV_WRITE(NV_PGRAPH_PIPE_DATA, 0x00000000); + NV_WRITE(NV_PGRAPH_PIPE_DATA, 0x00000000); + NV_WRITE(NV_PGRAPH_PIPE_DATA, 0x00000000); + NV_WRITE(NV_PGRAPH_PIPE_DATA, 0x7149f2ca); + NV_WRITE(NV_PGRAPH_PIPE_DATA, 0x00000000); + NV_WRITE(NV_PGRAPH_PIPE_DATA, 0x00000000); + NV_WRITE(NV_PGRAPH_PIPE_DATA, 0x00000000); + NV_WRITE(NV_PGRAPH_PIPE_DATA, 0x7149f2ca); + for (i = 0; i < 35; i++) + NV_WRITE(NV_PGRAPH_PIPE_DATA, 0x00000000); + + + NV_WRITE(NV_PGRAPH_PIPE_ADDRESS, 0x00007400); + for (i = 0; i < 48; i++) + NV_WRITE(NV_PGRAPH_PIPE_DATA, 0x00000000); + + NV_WRITE(NV_PGRAPH_PIPE_ADDRESS, 0x00007800); + for (i = 0; i < 48; i++) + NV_WRITE(NV_PGRAPH_PIPE_DATA, 0x00000000); + + NV_WRITE(NV_PGRAPH_PIPE_ADDRESS, 0x00004400); + for (i = 0; i < 32; i++) + NV_WRITE(NV_PGRAPH_PIPE_DATA, 0x00000000); + + NV_WRITE(NV_PGRAPH_PIPE_ADDRESS, 0x00000000); + for (i = 0; i < 16; i++) + NV_WRITE(NV_PGRAPH_PIPE_DATA, 0x00000000); + + NV_WRITE(NV_PGRAPH_PIPE_ADDRESS, 0x00000040); + for (i = 0; i < 4; i++) + NV_WRITE(NV_PGRAPH_PIPE_DATA, 0x00000000); + + nouveau_wait_for_idle(dev); +} + +/* TODO replace address with name + use loops */ +static int nv10_graph_ctx_regs [] = { +NV_PGRAPH_XY_LOGIC_MISC0, +NV_PGRAPH_DEBUG_4, +0x004006b0, + +NV_PGRAPH_CTX_SWITCH1, +NV_PGRAPH_CTX_SWITCH2, +NV_PGRAPH_CTX_SWITCH3, +NV_PGRAPH_CTX_SWITCH4, +NV_PGRAPH_CTX_SWITCH5, +0x00400160, +0x00400180, +0x004001a0, +0x004001c0, +0x004001e0, +0x00400164, +0x00400184, +0x004001a4, +0x004001c4, +0x004001e4, +0x00400168, +0x00400188, +0x004001a8, +0x004001c8, +0x004001e8, +0x0040016c, +0x0040018c, +0x004001ac, +0x004001cc, +0x004001ec, +0x00400170, +0x00400190, +0x004001b0, +0x004001d0, +0x004001f0, +0x00400174, +0x00400194, +0x004001b4, +0x004001d4, +0x004001f4, +0x00400178, +0x00400198, +0x004001b8, +0x004001d8, +0x004001f8, +0x0040017c, +0x0040019c, +0x004001bc, +0x004001dc, +0x004001fc, +NV_PGRAPH_CTX_USER, +NV_PGRAPH_DMA_START_0, +NV_PGRAPH_DMA_START_1, +NV_PGRAPH_DMA_LENGTH, +NV_PGRAPH_DMA_MISC, +NV_PGRAPH_DMA_PITCH, +NV_PGRAPH_BOFFSET0, +NV_PGRAPH_BBASE0, +NV_PGRAPH_BLIMIT0, +NV_PGRAPH_BOFFSET1, +NV_PGRAPH_BBASE1, +NV_PGRAPH_BLIMIT1, +NV_PGRAPH_BOFFSET2, +NV_PGRAPH_BBASE2, +NV_PGRAPH_BLIMIT2, +NV_PGRAPH_BOFFSET3, +NV_PGRAPH_BBASE3, +NV_PGRAPH_BLIMIT3, +NV_PGRAPH_BOFFSET4, +NV_PGRAPH_BBASE4, +NV_PGRAPH_BLIMIT4, +NV_PGRAPH_BOFFSET5, +NV_PGRAPH_BBASE5, +NV_PGRAPH_BLIMIT5, +NV_PGRAPH_BPITCH0, +NV_PGRAPH_BPITCH1, +NV_PGRAPH_BPITCH2, +NV_PGRAPH_BPITCH3, +NV_PGRAPH_BPITCH4, +NV_PGRAPH_SURFACE, +NV_PGRAPH_STATE, +NV_PGRAPH_BSWIZZLE2, +NV_PGRAPH_BSWIZZLE5, +NV_PGRAPH_BPIXEL, +NV_PGRAPH_NOTIFY, +NV_PGRAPH_PATT_COLOR0, +NV_PGRAPH_PATT_COLOR1, +0x00400900, +0x00400904, +0x00400908, +0x0040090c, +0x00400910, +0x00400914, +0x00400918, +0x0040091c, +0x00400920, +0x00400924, +0x00400928, +0x0040092c, +0x00400930, +0x00400934, +0x00400938, +0x0040093c, +0x00400940, +0x00400944, +0x00400948, +0x0040094c, +0x00400950, +0x00400954, +0x00400958, +0x0040095c, +0x00400960, +0x00400964, +0x00400968, +0x0040096c, +0x00400970, +0x00400974, +0x00400978, +0x0040097c, +0x00400980, +0x00400984, +0x00400988, +0x0040098c, +0x00400990, +0x00400994, +0x00400998, +0x0040099c, +0x004009a0, +0x004009a4, +0x004009a8, +0x004009ac, +0x004009b0, +0x004009b4, +0x004009b8, +0x004009bc, +0x004009c0, +0x004009c4, +0x004009c8, +0x004009cc, +0x004009d0, +0x004009d4, +0x004009d8, +0x004009dc, +0x004009e0, +0x004009e4, +0x004009e8, +0x004009ec, +0x004009f0, +0x004009f4, +0x004009f8, +0x004009fc, +0x00400808, +0x0040080c, +NV_PGRAPH_PATTERN_SHAPE, +NV_PGRAPH_MONO_COLOR0, +NV_PGRAPH_ROP3, +NV_PGRAPH_CHROMA, +NV_PGRAPH_BETA_AND, +NV_PGRAPH_BETA_PREMULT, +0x00400e70, +0x00400e74, +0x00400e78, +0x00400e7c, +0x00400e80, +0x00400e84, +0x00400e88, +0x00400e8c, +0x00400ea0, +0x00400ea4, +0x00400ea8, +0x00400eac, +0x00400eb0, +0x00400eb4, +0x00400eb8, +0x00400ebc, +0x00400ec0, +0x00400ec4, +0x00400ec8, +0x00400ecc, +0x00400ed0, +0x00400ed4, +0x00400ed8, +0x00400edc, +0x00400ee0, +0x00400a00, +0x00400a04, +0x00400e90, +0x00400e94, +0x00400e98, +0x00400e9c, +0x00400f00, +0x00400f20, +0x00400f04, +0x00400f24, +0x00400f08, +0x00400f28, +0x00400f0c, +0x00400f2c, +0x00400f10, +0x00400f30, +0x00400f14, +0x00400f34, +0x00400f18, +0x00400f38, +0x00400f1c, +0x00400f3c, +NV_PGRAPH_XFMODE0, +NV_PGRAPH_XFMODE1, +NV_PGRAPH_GLOBALSTATE0, +NV_PGRAPH_GLOBALSTATE1, +NV_PGRAPH_STORED_FMT, +NV_PGRAPH_SOURCE_COLOR, +0x00400400, +0x00400480, +0x00400404, +0x00400484, +0x00400408, +0x00400488, +0x0040040c, +0x0040048c, +0x00400410, +0x00400490, +0x00400414, +0x00400494, +0x00400418, +0x00400498, +0x0040041c, +0x0040049c, +0x00400420, +0x004004a0, +0x00400424, +0x004004a4, +0x00400428, +0x004004a8, +0x0040042c, +0x004004ac, +0x00400430, +0x004004b0, +0x00400434, +0x004004b4, +0x00400438, +0x004004b8, +0x0040043c, +0x004004bc, +0x00400440, +0x004004c0, +0x00400444, +0x004004c4, +0x00400448, +0x004004c8, +0x0040044c, +0x004004cc, +0x00400450, +0x004004d0, +0x00400454, +0x004004d4, +0x00400458, +0x004004d8, +0x0040045c, +0x004004dc, +0x00400460, +0x004004e0, +0x00400464, +0x004004e4, +0x00400468, +0x004004e8, +0x0040046c, +0x004004ec, +0x00400470, +0x004004f0, +0x00400474, +0x004004f4, +0x00400478, +0x004004f8, +0x0040047c, +0x004004fc, +NV_PGRAPH_ABS_UCLIP_XMIN, +NV_PGRAPH_ABS_UCLIP_XMAX, +NV_PGRAPH_ABS_UCLIP_YMIN, +NV_PGRAPH_ABS_UCLIP_YMAX, +0x00400550, +0x00400558, +0x00400554, +0x0040055c, +NV_PGRAPH_ABS_UCLIPA_XMIN, +NV_PGRAPH_ABS_UCLIPA_XMAX, +NV_PGRAPH_ABS_UCLIPA_YMIN, +NV_PGRAPH_ABS_UCLIPA_YMAX, +NV_PGRAPH_ABS_ICLIP_XMAX, +NV_PGRAPH_ABS_ICLIP_YMAX, +NV_PGRAPH_XY_LOGIC_MISC1, +NV_PGRAPH_XY_LOGIC_MISC2, +NV_PGRAPH_XY_LOGIC_MISC3, +NV_PGRAPH_CLIPX_0, +NV_PGRAPH_CLIPX_1, +NV_PGRAPH_CLIPY_0, +NV_PGRAPH_CLIPY_1, +0x00400e40, +0x00400e44, +0x00400e48, +0x00400e4c, +0x00400e50, +0x00400e54, +0x00400e58, +0x00400e5c, +0x00400e60, +0x00400e64, +0x00400e68, +0x00400e6c, +0x00400e00, +0x00400e04, +0x00400e08, +0x00400e0c, +0x00400e10, +0x00400e14, +0x00400e18, +0x00400e1c, +0x00400e20, +0x00400e24, +0x00400e28, +0x00400e2c, +0x00400e30, +0x00400e34, +0x00400e38, +0x00400e3c, +NV_PGRAPH_PASSTHRU_0, +NV_PGRAPH_PASSTHRU_1, +NV_PGRAPH_PASSTHRU_2, +NV_PGRAPH_DIMX_TEXTURE, +NV_PGRAPH_WDIMX_TEXTURE, +NV_PGRAPH_DVD_COLORFMT, +NV_PGRAPH_SCALED_FORMAT, +NV_PGRAPH_MISC24_0, +NV_PGRAPH_MISC24_1, +NV_PGRAPH_MISC24_2, +NV_PGRAPH_X_MISC, +NV_PGRAPH_Y_MISC, +NV_PGRAPH_VALID1, +NV_PGRAPH_VALID2, +0 +}; + +void nouveau_nv10_context_switch(drm_device_t *dev) +{ + drm_nouveau_private_t *dev_priv = dev->dev_private; + int channel, channel_old, i; + + channel=NV_READ(NV_PFIFO_CACH1_PSH1)&(nouveau_fifo_number(dev)-1); + channel_old = (NV_READ(NV_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(NV_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 + + // save PGRAPH context + for (i = 0; nv10_graph_ctx_regs[i]; i++) + dev_priv->fifos[channel_old].nv10_pgraph_ctx[i] = NV_READ(nv10_graph_ctx_regs[i]); + + nouveau_wait_for_idle(dev); + + NV_WRITE(NV_PGRAPH_CTX_CONTROL, 0x10000000); + NV_WRITE(NV_PGRAPH_CTX_USER, (NV_READ(NV_PGRAPH_CTX_USER) & 0xffffff) | (0x1f << 24)); + + nouveau_wait_for_idle(dev); + // restore PGRAPH context + //XXX not working yet +#if 0 + for (i = 0; nv10_graph_ctx_regs[i]; i++) + NV_WRITE(nv10_graph_ctx_regs[i], dev_priv->fifos[channel].nv10_pgraph_ctx[i]); + nouveau_wait_for_idle(dev); +#endif + + NV_WRITE(NV_PGRAPH_CTX_CONTROL, 0x10010100); + NV_WRITE(NV_PGRAPH_CTX_USER, channel << 24); + NV_WRITE(NV_PGRAPH_FFINTFC_ST2, NV_READ(NV_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(NV_PGRAPH_FIFO,0x1); +} + +int nv10_graph_context_create(drm_device_t *dev, int channel) { + drm_nouveau_private_t *dev_priv = dev->dev_private; + DRM_DEBUG("nv10_graph_context_create %d\n", channel); + + memset(dev_priv->fifos[channel].nv10_pgraph_ctx, 0, sizeof(dev_priv->fifos[channel].nv10_pgraph_ctx)); + + //dev_priv->fifos[channel].pgraph_ctx_user = channel << 24; + dev_priv->fifos[channel].nv10_pgraph_ctx[0] = 0x0001ffff; + /* is it really needed ??? */ + dev_priv->fifos[channel].nv10_pgraph_ctx[1] = NV_READ(NV_PGRAPH_DEBUG_4); + dev_priv->fifos[channel].nv10_pgraph_ctx[2] = NV_READ(0x004006b0); + return 0; +} + + +int nv10_graph_init(drm_device_t *dev) { + //XXX should be call at each fifo init + nv10_praph_pipe(dev); + return 0; +} diff --git a/shared-core/nv20_graph.c b/shared-core/nv20_graph.c new file mode 100644 index 00000000..6e351a2d --- /dev/null +++ b/shared-core/nv20_graph.c @@ -0,0 +1,155 @@ +/* + * Copyright 2007 Matthieu CASTET <castet.matthieu@free.fr> + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +#include "drmP.h" +#include "drm.h" +#include "nouveau_drv.h" +#include "nouveau_drm.h" + +#define NV20_GRCTX_SIZE (3529*4) + +int nv20_graph_context_create(drm_device_t *dev, int channel) { + drm_nouveau_private_t *dev_priv = + (drm_nouveau_private_t *)dev->dev_private; + struct nouveau_fifo *chan = &dev_priv->fifos[channel]; + unsigned int ctx_size = NV20_GRCTX_SIZE; + int i; + + /* Alloc and clear RAMIN to store the context */ + chan->ramin_grctx = nouveau_instmem_alloc(dev, ctx_size, 4); + if (!chan->ramin_grctx) + return DRM_ERR(ENOMEM); + for (i=0; i<ctx_size; i+=4) + INSTANCE_WR(chan->ramin_grctx, i/4, 0x00000000); + + /* Initialise default context values */ + INSTANCE_WR(chan->ramin_grctx, 10, channel << 24); /* CTX_USER */ + + INSTANCE_WR(dev_priv->ctx_table, channel, nouveau_chip_instance_get(dev, chan->ramin_grctx)); + + return 0; +} + +static void nv20_graph_rdi(drm_device_t *dev) { + drm_nouveau_private_t *dev_priv = + (drm_nouveau_private_t *)dev->dev_private; + int i; + + NV_WRITE(NV_PGRAPH_RDI_INDEX, 0x2c80000); + for (i = 0; i < 32; i++) + NV_WRITE(NV_PGRAPH_RDI_DATA, 0); + + nouveau_wait_for_idle(dev); +} + +/* Save current context (from PGRAPH) into the channel's context + */ +static void nv20_graph_context_save_current(drm_device_t *dev, int channel) { + drm_nouveau_private_t *dev_priv = + (drm_nouveau_private_t *)dev->dev_private; + uint32_t instance; + + instance = INSTANCE_RD(dev_priv->ctx_table, channel); + if (!instance) { + return; + } + if (instance != nouveau_chip_instance_get(dev, dev_priv->fifos[channel].ramin_grctx)) + DRM_ERROR("nv20_graph_context_save_current : bad instance\n"); + + NV_WRITE(NV_PGRAPH_CHANNEL_CTX_SIZE, instance); + NV_WRITE(NV_PGRAPH_CHANNEL_CTX_POINTER, 2 /* save ctx */); +} + + +/* Restore the context for a specific channel into PGRAPH + */ +static void nv20_graph_context_restore(drm_device_t *dev, int channel) { + drm_nouveau_private_t *dev_priv = + (drm_nouveau_private_t *)dev->dev_private; + uint32_t instance; + + instance = INSTANCE_RD(dev_priv->ctx_table, channel); + if (!instance) { + return; + } + if (instance != nouveau_chip_instance_get(dev, dev_priv->fifos[channel].ramin_grctx)) + DRM_ERROR("nv20_graph_context_restore_current : bad instance\n"); + + NV_WRITE(NV_PGRAPH_CTX_USER, channel << 24); + NV_WRITE(NV_PGRAPH_CHANNEL_CTX_SIZE, instance); + NV_WRITE(NV_PGRAPH_CHANNEL_CTX_POINTER, 1 /* restore ctx */); +} + +void nouveau_nv20_context_switch(drm_device_t *dev) +{ + drm_nouveau_private_t *dev_priv = dev->dev_private; + int channel, channel_old; + + channel=NV_READ(NV_PFIFO_CACH1_PSH1)&(nouveau_fifo_number(dev)-1); + channel_old = (NV_READ(NV_PGRAPH_CTX_USER) >> 24) & (nouveau_fifo_number(dev)-1); + + DRM_DEBUG("NV: PGRAPH context switch interrupt channel %x -> %x\n",channel_old, channel); + + NV_WRITE(NV_PGRAPH_FIFO,0x0); + + nv20_graph_context_save_current(dev, channel_old); + + nouveau_wait_for_idle(dev); + + NV_WRITE(NV_PGRAPH_CTX_CONTROL, 0x10000000); + + nv20_graph_context_restore(dev, channel); + + nouveau_wait_for_idle(dev); + + if ((NV_READ(NV_PGRAPH_CTX_USER) >> 24) != channel) + DRM_ERROR("nouveau_nv20_context_switch : wrong channel restored %x %x!!!\n", channel, NV_READ(NV_PGRAPH_CTX_USER) >> 24); + + NV_WRITE(NV_PGRAPH_CTX_CONTROL, 0x10010100); + NV_WRITE(NV_PGRAPH_FFINTFC_ST2, NV_READ(NV_PGRAPH_FFINTFC_ST2)&0xCFFFFFFF); + + NV_WRITE(NV_PGRAPH_FIFO,0x1); +} + +int nv20_graph_init(drm_device_t *dev) { + drm_nouveau_private_t *dev_priv = + (drm_nouveau_private_t *)dev->dev_private; + int i; + + /* Create Context Pointer Table */ + dev_priv->ctx_table_size = 32 * 4; + dev_priv->ctx_table = nouveau_instmem_alloc(dev, dev_priv->ctx_table_size, 4); + if (!dev_priv->ctx_table) + return DRM_ERR(ENOMEM); + + for (i=0; i< dev_priv->ctx_table_size; i+=4) + INSTANCE_WR(dev_priv->ctx_table, i/4, 0x00000000); + + NV_WRITE(NV_PGRAPH_CHANNEL_CTX_TABLE, nouveau_chip_instance_get(dev, dev_priv->ctx_table)); + + //XXX need to be done and save/restore for each fifo ??? + nv20_graph_rdi(dev); + + return 0; +} diff --git a/shared-core/nv30_graph.c b/shared-core/nv30_graph.c new file mode 100644 index 00000000..dbc39490 --- /dev/null +++ b/shared-core/nv30_graph.c @@ -0,0 +1,243 @@ +/* + * Based on nv40_graph.c + * Someday this will all go away... + */ +#include "drmP.h" +#include "drm.h" +#include "nouveau_drv.h" +#include "nouveau_drm.h" + +/* + * TODO: In the dump start seems to be 7654b0 while end is 76ac28. + * This is obviously not the correct size. + */ +#define NV30_GRCTX_SIZE (22392) + +/*TODO: deciper what each offset in the context represents. The below + * contexts are taken from dumps just after the 3D object is + * created. + */ +static void nv30_graph_context_init(drm_device_t *dev, struct mem_block *ctx) +{ + drm_nouveau_private_t *dev_priv = dev->dev_private; + int i; + + INSTANCE_WR(ctx, 0x28/4, 0x10000000); + INSTANCE_WR(ctx, 0x40c/4, 0x00000101); + INSTANCE_WR(ctx, 0x420/4, 0x00000111); + INSTANCE_WR(ctx, 0x424/4, 0x00000060); + INSTANCE_WR(ctx, 0x440/4, 0x00000080); + INSTANCE_WR(ctx, 0x444/4, 0xffff0000); + INSTANCE_WR(ctx, 0x448/4, 0x00000001); + INSTANCE_WR(ctx, 0x45c/4, 0x44400000); + INSTANCE_WR(ctx, 0x448/4, 0xffff0000); + INSTANCE_WR(ctx, 0x4dc/4, 0xfff00000); + INSTANCE_WR(ctx, 0x4e0/4, 0xfff00000); + INSTANCE_WR(ctx, 0x4e8/4, 0x00011100); + + for (i = 0x504; i <= 0x540; i += 4) + INSTANCE_WR(ctx, i/4, 0x7ff00000); + + INSTANCE_WR(ctx, 0x54c/4, 0x4b7fffff); + INSTANCE_WR(ctx, 0x588/4, 0x00000080); + INSTANCE_WR(ctx, 0x58c/4, 0x30201000); + INSTANCE_WR(ctx, 0x590/4, 0x70605040); + INSTANCE_WR(ctx, 0x594/4, 0xb8a89888); + INSTANCE_WR(ctx, 0x598/4, 0xf8e8d8c8); + INSTANCE_WR(ctx, 0x5ac/4, 0xb0000000); + + for (i = 0x604; i <= 0x640; i += 4) + INSTANCE_WR(ctx, i/4, 0x00010588); + + for (i = 0x644; i <= 0x680; i += 4) + INSTANCE_WR(ctx, i/4, 0x00030303); + + for (i = 0x6c4; i <= 0x700; i += 4) + INSTANCE_WR(ctx, i/4, 0x0008aae4); + + for (i = 0x704; i <= 0x740; i += 4) + INSTANCE_WR(ctx, i/4, 0x1012000); + + for (i = 0x744; i <= 0x780; i += 4) + INSTANCE_WR(ctx, i/4, 0x0080008); + + INSTANCE_WR(ctx, 0x860/4, 0x00040000); + INSTANCE_WR(ctx, 0x864/4, 0x00010000); + INSTANCE_WR(ctx, 0x868/4, 0x00040000); + INSTANCE_WR(ctx, 0x86c/4, 0x00040000); + INSTANCE_WR(ctx, 0x870/4, 0x00040000); + INSTANCE_WR(ctx, 0x874/4, 0x00040000); + + for (i = 0x00; i <= 0x1170; i += 0x10) + { + INSTANCE_WR(ctx, (0x1f24 + i)/4, 0x000c001b); + INSTANCE_WR(ctx, (0x1f20 + i)/4, 0x0436086c); + INSTANCE_WR(ctx, (0x1f1c + i)/4, 0x10700ff9); + } + + INSTANCE_WR(ctx, 0x30bc/4, 0x0000ffff); + INSTANCE_WR(ctx, 0x30c0/4, 0x0000ffff); + INSTANCE_WR(ctx, 0x30c4/4, 0x0000ffff); + INSTANCE_WR(ctx, 0x30c8/4, 0x0000ffff); + + INSTANCE_WR(ctx, 0x380c/4, 0x3f800000); + INSTANCE_WR(ctx, 0x3450/4, 0x3f800000); + INSTANCE_WR(ctx, 0x3820/4, 0x3f800000); + INSTANCE_WR(ctx, 0x3854/4, 0x3f800000); + INSTANCE_WR(ctx, 0x3850/4, 0x3f000000); + INSTANCE_WR(ctx, 0x384c/4, 0x40000000); + INSTANCE_WR(ctx, 0x3868/4, 0xbf800000); + INSTANCE_WR(ctx, 0x3860/4, 0x3f800000); + INSTANCE_WR(ctx, 0x386c/4, 0x40000000); + INSTANCE_WR(ctx, 0x3870/4, 0xbf800000); + + for (i = 0x4e0; i <= 0x4e1c; i += 4) + INSTANCE_WR(ctx, i/4, 0x001c527d); + INSTANCE_WR(ctx, 0x4e40, 0x001c527c); + + INSTANCE_WR(ctx, 0x5680/4, 0x000a0000); + INSTANCE_WR(ctx, 0x87c/4, 0x10000000); + INSTANCE_WR(ctx, 0x28/4, 0x10000011); +} + + +int +nv30_graph_context_create(drm_device_t *dev, int channel) +{ + drm_nouveau_private_t *dev_priv = + (drm_nouveau_private_t *)dev->dev_private; + struct nouveau_fifo *chan = &dev_priv->fifos[channel]; + void (*ctx_init)(drm_device_t *, struct mem_block *); + unsigned int ctx_size; + int i, chipset; + + chipset = (NV_READ(NV_PMC_BOOT_0) & 0x0ff00000) >> 20; + switch (chipset) { + default: + ctx_size = NV30_GRCTX_SIZE; + ctx_init = nv30_graph_context_init; + break; + } + + /* Alloc and clear RAMIN to store the context */ + chan->ramin_grctx = nouveau_instmem_alloc(dev, ctx_size, 4); + if (!chan->ramin_grctx) + return DRM_ERR(ENOMEM); + for (i=0; i<ctx_size; i+=4) + INSTANCE_WR(chan->ramin_grctx, i/4, 0x00000000); + + /* Initialise default context values */ + ctx_init(dev, chan->ramin_grctx); + + return 0; +} +#if 0 +/* Save current context (from PGRAPH) into the channel's context + *XXX: fails sometimes, not sure why.. + */ +void +nv40_graph_context_save_current(drm_device_t *dev) +{ + drm_nouveau_private_t *dev_priv = + (drm_nouveau_private_t *)dev->dev_private; + uint32_t instance; + int i; + + NV_WRITE(NV_PGRAPH_FIFO, 0); + + instance = NV_READ(0x40032C) & 0xFFFFF; + if (!instance) { + NV_WRITE(NV_PGRAPH_FIFO, 1); + return; + } + + NV_WRITE(0x400784, instance); + NV_WRITE(0x400310, NV_READ(0x400310) | 0x20); + NV_WRITE(0x400304, 1); + /* just in case, we don't want to spin in-kernel forever */ + for (i=0; i<1000; i++) { + if (NV_READ(0x40030C) == 0) + break; + } + if (i==1000) { + DRM_ERROR("failed to save current grctx to ramin\n"); + DRM_ERROR("instance = 0x%08x\n", NV_READ(0x40032C)); + DRM_ERROR("0x40030C = 0x%08x\n", NV_READ(0x40030C)); + NV_WRITE(NV_PGRAPH_FIFO, 1); + return; + } + + NV_WRITE(NV_PGRAPH_FIFO, 1); +} + +/* Restore the context for a specific channel into PGRAPH + * XXX: fails sometimes.. not sure why + */ +void +nv40_graph_context_restore(drm_device_t *dev, int channel) +{ + drm_nouveau_private_t *dev_priv = + (drm_nouveau_private_t *)dev->dev_private; + struct nouveau_fifo *chan = &dev_priv->fifos[channel]; + uint32_t instance; + int i; + + instance = nouveau_chip_instance_get(dev, chan->ramin_grctx); + + NV_WRITE(NV_PGRAPH_FIFO, 0); + NV_WRITE(0x400784, instance); + NV_WRITE(0x400310, NV_READ(0x400310) | 0x40); + NV_WRITE(0x400304, 1); + /* just in case, we don't want to spin in-kernel forever */ + for (i=0; i<1000; i++) { + if (NV_READ(0x40030C) == 0) + break; + } + if (i==1000) { + DRM_ERROR("failed to restore grctx for ch%d to PGRAPH\n", + channel); + DRM_ERROR("instance = 0x%08x\n", instance); + DRM_ERROR("0x40030C = 0x%08x\n", NV_READ(0x40030C)); + NV_WRITE(NV_PGRAPH_FIFO, 1); + return; + } + + + /* 0x40032C, no idea of it's exact function. Could simply be a + * record of the currently active PGRAPH context. It's currently + * unknown as to what bit 24 does. The nv ddx has it set, so we will + * set it here too. + */ + NV_WRITE(0x40032C, instance | 0x01000000); + /* 0x32E0 records the instance address of the active FIFO's PGRAPH + * context. If at any time this doesn't match 0x40032C, you will + * recieve PGRAPH_INTR_CONTEXT_SWITCH + */ + NV_WRITE(NV40_PFIFO_GRCTX_INSTANCE, instance); + NV_WRITE(NV_PGRAPH_FIFO, 1); +} +#endif +int +nv30_graph_init(drm_device_t *dev) +{ + drm_nouveau_private_t *dev_priv = + (drm_nouveau_private_t *)dev->dev_private; + int i, chipset; + + chipset = (NV_READ(NV_PMC_BOOT_0) & 0x0ff00000) >> 20; + DRM_DEBUG("chipset (from PMC_BOOT_0): NV%02X\n", chipset); + + /* Create Context Pointer Table */ + dev_priv->ctx_table_size = 32 * 4; + dev_priv->ctx_table = nouveau_instmem_alloc(dev, dev_priv->ctx_table_size, 4); + if (!dev_priv->ctx_table) + return DRM_ERR(ENOMEM); + + for (i=0; i< dev_priv->ctx_table_size; i+=4) + INSTANCE_WR(dev_priv->ctx_table, i/4, 0x00000000); + + NV_WRITE(NV_PGRAPH_CHANNEL_CTX_TABLE, nouveau_chip_instance_get(dev, dev_priv->ctx_table)); + + return 0; +} + diff --git a/shared-core/nv40_graph.c b/shared-core/nv40_graph.c index 53f55bce..3e1b2f6f 100644 --- a/shared-core/nv40_graph.c +++ b/shared-core/nv40_graph.c @@ -10,7 +10,7 @@ */ #define NV40_GRCTX_SIZE (175*1024) #define NV43_GRCTX_SIZE (70*1024) -#define NV4A_GRCTX_SIZE (60*1024) +#define NV4A_GRCTX_SIZE (64*1024) #define NV4E_GRCTX_SIZE (25*1024) /*TODO: deciper what each offset in the context represents. The below diff --git a/shared-core/radeon_cp.c b/shared-core/radeon_cp.c index 4135f4d5..0fa6535d 100644 --- a/shared-core/radeon_cp.c +++ b/shared-core/radeon_cp.c @@ -1563,8 +1563,8 @@ static int radeon_do_init_cp(drm_device_t * dev, drm_radeon_init_t * init) if (dev_priv->flags & RADEON_IS_AGP) { base = dev->agp->base; /* Check if valid */ - if ((base + dev_priv->gart_size) > dev_priv->fb_location && - base < (dev_priv->fb_location + dev_priv->fb_size)) { + if ((base + dev_priv->gart_size - 1) >= dev_priv->fb_location && + base < (dev_priv->fb_location + dev_priv->fb_size - 1)) { DRM_INFO("Can't use AGP base @0x%08lx, won't fit\n", dev->agp->base); base = 0; @@ -1574,8 +1574,8 @@ static int radeon_do_init_cp(drm_device_t * dev, drm_radeon_init_t * init) /* If not or if AGP is at 0 (Macs), try to put it elsewhere */ if (base == 0) { base = dev_priv->fb_location + dev_priv->fb_size; - if (((base + dev_priv->gart_size) & 0xfffffffful) - < base) + if (base < dev_priv->fb_location || + ((base + dev_priv->gart_size) & 0xfffffffful) < base) base = dev_priv->fb_location - dev_priv->gart_size; } |