2 * Copyright (C) 2007 Ben Skeggs.
5 * Permission is hereby granted, free of charge, to any person obtaining
6 * a copy of this software and associated documentation files (the
7 * "Software"), to deal in the Software without restriction, including
8 * without limitation the rights to use, copy, modify, merge, publish,
9 * distribute, sublicense, and/or sell copies of the Software, and to
10 * permit persons to whom the Software is furnished to do so, subject to
11 * the following conditions:
13 * The above copyright notice and this permission notice (including the
14 * next paragraph) shall be included in all copies or substantial
15 * portions of the Software.
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
18 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
19 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
20 * IN NO EVENT SHALL THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE
21 * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
22 * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
23 * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
29 #include "nouveau_drv.h"
31 #include "nouveau_grctx.h"
33 #define IS_G80 ((dev_priv->chipset & 0xf0) == 0x50)
36 nv50_graph_init_reset(struct drm_device
*dev
)
38 uint32_t pmc_e
= NV_PMC_ENABLE_PGRAPH
| (1 << 21);
42 nv_wr32(dev
, NV03_PMC_ENABLE
, nv_rd32(dev
, NV03_PMC_ENABLE
) & ~pmc_e
);
43 nv_wr32(dev
, NV03_PMC_ENABLE
, nv_rd32(dev
, NV03_PMC_ENABLE
) | pmc_e
);
47 nv50_graph_init_intr(struct drm_device
*dev
)
51 nv_wr32(dev
, NV03_PGRAPH_INTR
, 0xffffffff);
52 nv_wr32(dev
, 0x400138, 0xffffffff);
53 nv_wr32(dev
, NV40_PGRAPH_INTR_EN
, 0xffffffff);
57 nv50_graph_init_regs__nv(struct drm_device
*dev
)
59 struct drm_nouveau_private
*dev_priv
= dev
->dev_private
;
60 uint32_t units
= nv_rd32(dev
, 0x1540);
65 nv_wr32(dev
, 0x400804, 0xc0000000);
66 nv_wr32(dev
, 0x406800, 0xc0000000);
67 nv_wr32(dev
, 0x400c04, 0xc0000000);
68 nv_wr32(dev
, 0x401800, 0xc0000000);
69 nv_wr32(dev
, 0x405018, 0xc0000000);
70 nv_wr32(dev
, 0x402000, 0xc0000000);
72 for (i
= 0; i
< 16; i
++) {
74 if (dev_priv
->chipset
< 0xa0) {
75 nv_wr32(dev
, 0x408900 + (i
<< 12), 0xc0000000);
76 nv_wr32(dev
, 0x408e08 + (i
<< 12), 0xc0000000);
77 nv_wr32(dev
, 0x408314 + (i
<< 12), 0xc0000000);
79 nv_wr32(dev
, 0x408600 + (i
<< 11), 0xc0000000);
80 nv_wr32(dev
, 0x408708 + (i
<< 11), 0xc0000000);
81 nv_wr32(dev
, 0x40831c + (i
<< 11), 0xc0000000);
86 nv_wr32(dev
, 0x400108, 0xffffffff);
88 nv_wr32(dev
, 0x400824, 0x00004000);
89 nv_wr32(dev
, 0x400500, 0x00010001);
93 nv50_graph_init_regs(struct drm_device
*dev
)
97 nv_wr32(dev
, NV04_PGRAPH_DEBUG_3
,
98 (1 << 2) /* HW_CONTEXT_SWITCH_ENABLED */);
99 nv_wr32(dev
, 0x402ca8, 0x800);
103 nv50_graph_init_ctxctl(struct drm_device
*dev
)
105 struct drm_nouveau_private
*dev_priv
= dev
->dev_private
;
110 nouveau_grctx_prog_load(dev
);
111 dev_priv
->engine
.graph
.grctx_size
= 0x70000;
113 if (!dev_priv
->engine
.graph
.ctxprog
) {
114 struct nouveau_grctx ctx
= {};
115 uint32_t *cp
= kmalloc(512 * 4, GFP_KERNEL
);
118 NV_ERROR(dev
, "Couldn't alloc ctxprog! Disabling acceleration.\n");
119 dev_priv
->engine
.graph
.accel_blocked
= true;
123 ctx
.mode
= NOUVEAU_GRCTX_PROG
;
125 ctx
.ctxprog_max
= 512;
126 if (!nv50_grctx_init(&ctx
)) {
127 dev_priv
->engine
.graph
.grctx_size
= ctx
.ctxvals_pos
* 4;
129 nv_wr32(dev
, NV40_PGRAPH_CTXCTL_UCODE_INDEX
, 0);
130 for (i
= 0; i
< ctx
.ctxprog_len
; i
++)
131 nv_wr32(dev
, NV40_PGRAPH_CTXCTL_UCODE_DATA
, cp
[i
]);
133 dev_priv
->engine
.graph
.accel_blocked
= true;
138 nv_wr32(dev
, 0x400320, 4);
139 nv_wr32(dev
, NV40_PGRAPH_CTXCTL_CUR
, 0);
140 nv_wr32(dev
, NV20_PGRAPH_CHANNEL_CTX_POINTER
, 0);
145 nv50_graph_init(struct drm_device
*dev
)
151 nv50_graph_init_reset(dev
);
152 nv50_graph_init_regs__nv(dev
);
153 nv50_graph_init_regs(dev
);
154 nv50_graph_init_intr(dev
);
156 ret
= nv50_graph_init_ctxctl(dev
);
164 nv50_graph_takedown(struct drm_device
*dev
)
167 nouveau_grctx_fini(dev
);
171 nv50_graph_fifo_access(struct drm_device
*dev
, bool enabled
)
173 const uint32_t mask
= 0x00010001;
176 nv_wr32(dev
, 0x400500, nv_rd32(dev
, 0x400500) | mask
);
178 nv_wr32(dev
, 0x400500, nv_rd32(dev
, 0x400500) & ~mask
);
181 struct nouveau_channel
*
182 nv50_graph_channel(struct drm_device
*dev
)
184 struct drm_nouveau_private
*dev_priv
= dev
->dev_private
;
188 /* Be sure we're not in the middle of a context switch or bad things
189 * will happen, such as unloading the wrong pgraph context.
191 if (!nv_wait(0x400300, 0x00000001, 0x00000000))
192 NV_ERROR(dev
, "Ctxprog is still running\n");
194 inst
= nv_rd32(dev
, NV50_PGRAPH_CTXCTL_CUR
);
195 if (!(inst
& NV50_PGRAPH_CTXCTL_CUR_LOADED
))
197 inst
= (inst
& NV50_PGRAPH_CTXCTL_CUR_INSTANCE
) << 12;
199 for (i
= 0; i
< dev_priv
->engine
.fifo
.channels
; i
++) {
200 struct nouveau_channel
*chan
= dev_priv
->fifos
[i
];
202 if (chan
&& chan
->ramin
&& chan
->ramin
->instance
== inst
)
210 nv50_graph_create_context(struct nouveau_channel
*chan
)
212 struct drm_device
*dev
= chan
->dev
;
213 struct drm_nouveau_private
*dev_priv
= dev
->dev_private
;
214 struct nouveau_gpuobj
*ramin
= chan
->ramin
->gpuobj
;
215 struct nouveau_gpuobj
*ctx
;
216 struct nouveau_pgraph_engine
*pgraph
= &dev_priv
->engine
.graph
;
219 NV_DEBUG(dev
, "ch%d\n", chan
->id
);
221 ret
= nouveau_gpuobj_new_ref(dev
, chan
, NULL
, 0, pgraph
->grctx_size
,
222 0x1000, NVOBJ_FLAG_ZERO_ALLOC
|
223 NVOBJ_FLAG_ZERO_FREE
, &chan
->ramin_grctx
);
226 ctx
= chan
->ramin_grctx
->gpuobj
;
228 hdr
= IS_G80
? 0x200 : 0x20;
229 dev_priv
->engine
.instmem
.prepare_access(dev
, true);
230 nv_wo32(dev
, ramin
, (hdr
+ 0x00)/4, 0x00190002);
231 nv_wo32(dev
, ramin
, (hdr
+ 0x04)/4, chan
->ramin_grctx
->instance
+
232 pgraph
->grctx_size
- 1);
233 nv_wo32(dev
, ramin
, (hdr
+ 0x08)/4, chan
->ramin_grctx
->instance
);
234 nv_wo32(dev
, ramin
, (hdr
+ 0x0c)/4, 0);
235 nv_wo32(dev
, ramin
, (hdr
+ 0x10)/4, 0);
236 nv_wo32(dev
, ramin
, (hdr
+ 0x14)/4, 0x00010000);
237 dev_priv
->engine
.instmem
.finish_access(dev
);
239 dev_priv
->engine
.instmem
.prepare_access(dev
, true);
240 if (!pgraph
->ctxprog
) {
241 struct nouveau_grctx ctx
= {};
243 ctx
.mode
= NOUVEAU_GRCTX_VALS
;
244 ctx
.data
= chan
->ramin_grctx
->gpuobj
;
245 nv50_grctx_init(&ctx
);
247 nouveau_grctx_vals_load(dev
, ctx
);
249 nv_wo32(dev
, ctx
, 0x00000/4, chan
->ramin
->instance
>> 12);
250 dev_priv
->engine
.instmem
.finish_access(dev
);
256 nv50_graph_destroy_context(struct nouveau_channel
*chan
)
258 struct drm_device
*dev
= chan
->dev
;
259 struct drm_nouveau_private
*dev_priv
= dev
->dev_private
;
260 int i
, hdr
= IS_G80
? 0x200 : 0x20;
262 NV_DEBUG(dev
, "ch%d\n", chan
->id
);
264 if (!chan
->ramin
|| !chan
->ramin
->gpuobj
)
267 dev_priv
->engine
.instmem
.prepare_access(dev
, true);
268 for (i
= hdr
; i
< hdr
+ 24; i
+= 4)
269 nv_wo32(dev
, chan
->ramin
->gpuobj
, i
/4, 0);
270 dev_priv
->engine
.instmem
.finish_access(dev
);
272 nouveau_gpuobj_ref_del(dev
, &chan
->ramin_grctx
);
276 nv50_graph_do_load_context(struct drm_device
*dev
, uint32_t inst
)
278 uint32_t fifo
= nv_rd32(dev
, 0x400500);
280 nv_wr32(dev
, 0x400500, fifo
& ~1);
281 nv_wr32(dev
, 0x400784, inst
);
282 nv_wr32(dev
, 0x400824, nv_rd32(dev
, 0x400824) | 0x40);
283 nv_wr32(dev
, 0x400320, nv_rd32(dev
, 0x400320) | 0x11);
284 nv_wr32(dev
, 0x400040, 0xffffffff);
285 (void)nv_rd32(dev
, 0x400040);
286 nv_wr32(dev
, 0x400040, 0x00000000);
287 nv_wr32(dev
, 0x400304, nv_rd32(dev
, 0x400304) | 1);
289 if (nouveau_wait_for_idle(dev
))
290 nv_wr32(dev
, 0x40032c, inst
| (1<<31));
291 nv_wr32(dev
, 0x400500, fifo
);
297 nv50_graph_load_context(struct nouveau_channel
*chan
)
299 uint32_t inst
= chan
->ramin
->instance
>> 12;
301 NV_DEBUG(chan
->dev
, "ch%d\n", chan
->id
);
302 return nv50_graph_do_load_context(chan
->dev
, inst
);
306 nv50_graph_unload_context(struct drm_device
*dev
)
310 inst
= nv_rd32(dev
, NV50_PGRAPH_CTXCTL_CUR
);
311 if (!(inst
& NV50_PGRAPH_CTXCTL_CUR_LOADED
))
313 inst
&= NV50_PGRAPH_CTXCTL_CUR_INSTANCE
;
315 nouveau_wait_for_idle(dev
);
316 nv_wr32(dev
, 0x400784, inst
);
317 nv_wr32(dev
, 0x400824, nv_rd32(dev
, 0x400824) | 0x20);
318 nv_wr32(dev
, 0x400304, nv_rd32(dev
, 0x400304) | 0x01);
319 nouveau_wait_for_idle(dev
);
321 nv_wr32(dev
, NV50_PGRAPH_CTXCTL_CUR
, inst
);
326 nv50_graph_context_switch(struct drm_device
*dev
)
330 nv50_graph_unload_context(dev
);
332 inst
= nv_rd32(dev
, NV50_PGRAPH_CTXCTL_NEXT
);
333 inst
&= NV50_PGRAPH_CTXCTL_NEXT_INSTANCE
;
334 nv50_graph_do_load_context(dev
, inst
);
336 nv_wr32(dev
, NV40_PGRAPH_INTR_EN
, nv_rd32(dev
,
337 NV40_PGRAPH_INTR_EN
) | NV_PGRAPH_INTR_CONTEXT_SWITCH
);
341 nv50_graph_nvsw_dma_vblsem(struct nouveau_channel
*chan
, int grclass
,
342 int mthd
, uint32_t data
)
344 struct nouveau_gpuobj_ref
*ref
= NULL
;
346 if (nouveau_gpuobj_ref_find(chan
, data
, &ref
))
349 if (nouveau_notifier_offset(ref
->gpuobj
, NULL
))
352 chan
->nvsw
.vblsem
= ref
->gpuobj
;
353 chan
->nvsw
.vblsem_offset
= ~0;
358 nv50_graph_nvsw_vblsem_offset(struct nouveau_channel
*chan
, int grclass
,
359 int mthd
, uint32_t data
)
361 if (nouveau_notifier_offset(chan
->nvsw
.vblsem
, &data
))
364 chan
->nvsw
.vblsem_offset
= data
>> 2;
369 nv50_graph_nvsw_vblsem_release_val(struct nouveau_channel
*chan
, int grclass
,
370 int mthd
, uint32_t data
)
372 chan
->nvsw
.vblsem_rval
= data
;
377 nv50_graph_nvsw_vblsem_release(struct nouveau_channel
*chan
, int grclass
,
378 int mthd
, uint32_t data
)
380 struct drm_device
*dev
= chan
->dev
;
381 struct drm_nouveau_private
*dev_priv
= dev
->dev_private
;
383 if (!chan
->nvsw
.vblsem
|| chan
->nvsw
.vblsem_offset
== ~0 || data
> 1)
386 if (!(nv_rd32(dev
, NV50_PDISPLAY_INTR_EN
) &
387 NV50_PDISPLAY_INTR_EN_VBLANK_CRTC_(data
))) {
388 nv_wr32(dev
, NV50_PDISPLAY_INTR_1
,
389 NV50_PDISPLAY_INTR_1_VBLANK_CRTC_(data
));
390 nv_wr32(dev
, NV50_PDISPLAY_INTR_EN
, nv_rd32(dev
,
391 NV50_PDISPLAY_INTR_EN
) |
392 NV50_PDISPLAY_INTR_EN_VBLANK_CRTC_(data
));
395 list_add(&chan
->nvsw
.vbl_wait
, &dev_priv
->vbl_waiting
);
399 static struct nouveau_pgraph_object_method nv50_graph_nvsw_methods
[] = {
400 { 0x018c, nv50_graph_nvsw_dma_vblsem
},
401 { 0x0400, nv50_graph_nvsw_vblsem_offset
},
402 { 0x0404, nv50_graph_nvsw_vblsem_release_val
},
403 { 0x0408, nv50_graph_nvsw_vblsem_release
},
407 struct nouveau_pgraph_object_class nv50_graph_grclass
[] = {
408 { 0x506e, true, nv50_graph_nvsw_methods
}, /* nvsw */
409 { 0x0030, false, NULL
}, /* null */
410 { 0x5039, false, NULL
}, /* m2mf */
411 { 0x502d, false, NULL
}, /* 2d */
412 { 0x50c0, false, NULL
}, /* compute */
413 { 0x85c0, false, NULL
}, /* compute (nva3, nva5, nva8) */
414 { 0x5097, false, NULL
}, /* tesla (nv50) */
415 { 0x8297, false, NULL
}, /* tesla (nv8x/nv9x) */
416 { 0x8397, false, NULL
}, /* tesla (nva0, nvaa, nvac) */
417 { 0x8597, false, NULL
}, /* tesla (nva3, nva5, nva8) */