5 #include "nouveau_drmif.h"
6 #include "nouveau_dma.h"
7 #include "nouveau_local.h"
9 #define READ_GET(ch) ((*(ch)->get - (ch)->dma.base) >> 2)
10 #define WRITE_PUT(ch, val) do { \
11 *(ch)->put = (((val) << 2) + (ch)->dma.base); \
15 nouveau_dma_channel_init(struct nouveau_channel *userchan)
17 struct nouveau_channel_priv *chan = nouveau_channel(userchan);
20 chan->dma.base = chan->drm.put_base;
21 chan->dma.cur = chan->dma.put = RING_SKIPS;
22 chan->dma.max = (chan->drm.cmdbuf_size >> 2) - 2;
23 chan->dma.free = chan->dma.max - chan->dma.cur;
25 for (i = 0; i < RING_SKIPS; i++)
26 chan->pushbuf[i] = 0x00000000;
29 #define CHECK_TIMEOUT() do { \
30 if ((NOUVEAU_TIME_MSEC() - t_start) > NOUVEAU_DMA_TIMEOUT) \
35 nouveau_dma_wait(struct nouveau_channel *userchan, int size)
37 struct nouveau_channel_priv *chan = nouveau_channel(userchan);
38 uint32_t get, t_start;
40 FIRE_RING_CH(userchan);
42 t_start = NOUVEAU_TIME_MSEC();
43 while (chan->dma.free < size) {
46 if (chan->dma.put >= get) {
47 chan->dma.free = chan->dma.max - chan->dma.cur;
49 if (chan->dma.free < size) {
50 #ifdef NOUVEAU_DMA_DEBUG
51 chan->dma.push_free = 1;
54 0x20000000 | chan->dma.base);
55 if (get <= RING_SKIPS) {
56 /*corner case - will be idle*/
57 if (chan->dma.put <= RING_SKIPS)
58 WRITE_PUT(chan, RING_SKIPS + 1);
63 } while (get <= RING_SKIPS);
66 WRITE_PUT(chan, RING_SKIPS);
67 chan->dma.cur = chan->dma.put = RING_SKIPS;
68 chan->dma.free = get - (RING_SKIPS + 1);
71 chan->dma.free = get - chan->dma.cur - 1;
80 #ifdef NOUVEAU_DMA_SUBCHAN_LRU
82 nouveau_dma_subc_bind(struct nouveau_grobj *grobj)
84 struct nouveau_channel_priv *chan = nouveau_channel(grobj->channel);
87 for (i = 0; i < 8; i++) {
88 if (chan->subchannel[i].grobj &&
89 chan->subchannel[i].grobj->bound ==
90 NOUVEAU_GROBJ_EXPLICIT_BIND)
92 if (chan->subchannel[i].seq < chan->subchannel[subc].seq)
97 if (chan->subchannel[subc].grobj)
98 chan->subchannel[subc].grobj->bound = 0;
99 chan->subchannel[subc].grobj = grobj;
101 grobj->bound = NOUVEAU_GROBJ_BOUND;
103 nouveau_dma_begin(grobj->channel, grobj, 0, 1);
104 nouveau_dma_out (grobj->channel, grobj->handle);
109 nouveau_dma_kickoff(struct nouveau_channel *userchan)
111 struct nouveau_channel_priv *chan = nouveau_channel(userchan);
115 if (chan->dma.cur == chan->dma.put)
118 if (chan->num_relocs) {
119 nouveau_bo_validate(userchan);
121 for (i = 0; i < chan->num_relocs; i++) {
122 struct nouveau_bo_reloc *r = &chan->relocs[i];
125 if (r->flags & NOUVEAU_BO_LOW) {
126 push = r->bo->base.offset + r->data;
128 if (r->flags & NOUVEAU_BO_HIGH) {
129 push = (r->bo->base.offset + r->data) >> 32;
134 if (r->flags & NOUVEAU_BO_OR) {
135 if (r->flags & NOUVEAU_BO_VRAM)
144 chan->num_relocs = 0;
147 #ifdef NOUVEAU_DMA_DEBUG
148 if (chan->dma.push_free) {
149 NOUVEAU_ERR("Packet incomplete: %d left\n", chan->dma.push_free);
154 put_offset = (chan->dma.cur << 2) + chan->dma.base;
155 #ifdef NOUVEAU_DMA_TRACE
156 NOUVEAU_MSG("FIRE_RING %d/0x%08x\n", chan->drm.channel, put_offset);
158 chan->dma.put = chan->dma.cur;
160 *chan->put = put_offset;