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"
30 #include "nouveau_ramht.h"
31 #include "nouveau_grctx.h"
34 nv50_graph_init_reset(struct drm_device
*dev
)
36 uint32_t pmc_e
= NV_PMC_ENABLE_PGRAPH
| (1 << 21);
40 nv_wr32(dev
, NV03_PMC_ENABLE
, nv_rd32(dev
, NV03_PMC_ENABLE
) & ~pmc_e
);
41 nv_wr32(dev
, NV03_PMC_ENABLE
, nv_rd32(dev
, NV03_PMC_ENABLE
) | pmc_e
);
45 nv50_graph_init_intr(struct drm_device
*dev
)
49 nv_wr32(dev
, NV03_PGRAPH_INTR
, 0xffffffff);
50 nv_wr32(dev
, 0x400138, 0xffffffff);
51 nv_wr32(dev
, NV40_PGRAPH_INTR_EN
, 0xffffffff);
55 nv50_graph_init_regs__nv(struct drm_device
*dev
)
57 struct drm_nouveau_private
*dev_priv
= dev
->dev_private
;
58 uint32_t units
= nv_rd32(dev
, 0x1540);
63 nv_wr32(dev
, 0x400804, 0xc0000000);
64 nv_wr32(dev
, 0x406800, 0xc0000000);
65 nv_wr32(dev
, 0x400c04, 0xc0000000);
66 nv_wr32(dev
, 0x401800, 0xc0000000);
67 nv_wr32(dev
, 0x405018, 0xc0000000);
68 nv_wr32(dev
, 0x402000, 0xc0000000);
70 for (i
= 0; i
< 16; i
++) {
72 if (dev_priv
->chipset
< 0xa0) {
73 nv_wr32(dev
, 0x408900 + (i
<< 12), 0xc0000000);
74 nv_wr32(dev
, 0x408e08 + (i
<< 12), 0xc0000000);
75 nv_wr32(dev
, 0x408314 + (i
<< 12), 0xc0000000);
77 nv_wr32(dev
, 0x408600 + (i
<< 11), 0xc0000000);
78 nv_wr32(dev
, 0x408708 + (i
<< 11), 0xc0000000);
79 nv_wr32(dev
, 0x40831c + (i
<< 11), 0xc0000000);
84 nv_wr32(dev
, 0x400108, 0xffffffff);
86 nv_wr32(dev
, 0x400824, 0x00004000);
87 nv_wr32(dev
, 0x400500, 0x00010001);
91 nv50_graph_init_regs(struct drm_device
*dev
)
95 nv_wr32(dev
, NV04_PGRAPH_DEBUG_3
,
96 (1 << 2) /* HW_CONTEXT_SWITCH_ENABLED */);
97 nv_wr32(dev
, 0x402ca8, 0x800);
101 nv50_graph_init_ctxctl(struct drm_device
*dev
)
103 struct drm_nouveau_private
*dev_priv
= dev
->dev_private
;
104 struct nouveau_grctx ctx
= {};
110 cp
= kmalloc(512 * 4, GFP_KERNEL
);
112 NV_ERROR(dev
, "failed to allocate ctxprog\n");
113 dev_priv
->engine
.graph
.accel_blocked
= true;
118 ctx
.mode
= NOUVEAU_GRCTX_PROG
;
120 ctx
.ctxprog_max
= 512;
121 if (!nv50_grctx_init(&ctx
)) {
122 dev_priv
->engine
.graph
.grctx_size
= ctx
.ctxvals_pos
* 4;
124 nv_wr32(dev
, NV40_PGRAPH_CTXCTL_UCODE_INDEX
, 0);
125 for (i
= 0; i
< ctx
.ctxprog_len
; i
++)
126 nv_wr32(dev
, NV40_PGRAPH_CTXCTL_UCODE_DATA
, cp
[i
]);
128 dev_priv
->engine
.graph
.accel_blocked
= true;
132 nv_wr32(dev
, 0x400320, 4);
133 nv_wr32(dev
, NV40_PGRAPH_CTXCTL_CUR
, 0);
134 nv_wr32(dev
, NV20_PGRAPH_CHANNEL_CTX_POINTER
, 0);
139 nv50_graph_init(struct drm_device
*dev
)
145 nv50_graph_init_reset(dev
);
146 nv50_graph_init_regs__nv(dev
);
147 nv50_graph_init_regs(dev
);
148 nv50_graph_init_intr(dev
);
150 ret
= nv50_graph_init_ctxctl(dev
);
158 nv50_graph_takedown(struct drm_device
*dev
)
164 nv50_graph_fifo_access(struct drm_device
*dev
, bool enabled
)
166 const uint32_t mask
= 0x00010001;
169 nv_wr32(dev
, 0x400500, nv_rd32(dev
, 0x400500) | mask
);
171 nv_wr32(dev
, 0x400500, nv_rd32(dev
, 0x400500) & ~mask
);
174 struct nouveau_channel
*
175 nv50_graph_channel(struct drm_device
*dev
)
177 struct drm_nouveau_private
*dev_priv
= dev
->dev_private
;
181 /* Be sure we're not in the middle of a context switch or bad things
182 * will happen, such as unloading the wrong pgraph context.
184 if (!nv_wait(dev
, 0x400300, 0x00000001, 0x00000000))
185 NV_ERROR(dev
, "Ctxprog is still running\n");
187 inst
= nv_rd32(dev
, NV50_PGRAPH_CTXCTL_CUR
);
188 if (!(inst
& NV50_PGRAPH_CTXCTL_CUR_LOADED
))
190 inst
= (inst
& NV50_PGRAPH_CTXCTL_CUR_INSTANCE
) << 12;
192 for (i
= 0; i
< dev_priv
->engine
.fifo
.channels
; i
++) {
193 struct nouveau_channel
*chan
= dev_priv
->fifos
[i
];
195 if (chan
&& chan
->ramin
&& chan
->ramin
->vinst
== inst
)
203 nv50_graph_create_context(struct nouveau_channel
*chan
)
205 struct drm_device
*dev
= chan
->dev
;
206 struct drm_nouveau_private
*dev_priv
= dev
->dev_private
;
207 struct nouveau_gpuobj
*ramin
= chan
->ramin
;
208 struct nouveau_pgraph_engine
*pgraph
= &dev_priv
->engine
.graph
;
209 struct nouveau_grctx ctx
= {};
212 NV_DEBUG(dev
, "ch%d\n", chan
->id
);
214 ret
= nouveau_gpuobj_new(dev
, chan
, pgraph
->grctx_size
, 0x1000,
215 NVOBJ_FLAG_ZERO_ALLOC
|
216 NVOBJ_FLAG_ZERO_FREE
, &chan
->ramin_grctx
);
220 hdr
= (dev_priv
->chipset
== 0x50) ? 0x200 : 0x20;
221 nv_wo32(ramin
, hdr
+ 0x00, 0x00190002);
222 nv_wo32(ramin
, hdr
+ 0x04, chan
->ramin_grctx
->vinst
+
223 pgraph
->grctx_size
- 1);
224 nv_wo32(ramin
, hdr
+ 0x08, chan
->ramin_grctx
->vinst
);
225 nv_wo32(ramin
, hdr
+ 0x0c, 0);
226 nv_wo32(ramin
, hdr
+ 0x10, 0);
227 nv_wo32(ramin
, hdr
+ 0x14, 0x00010000);
230 ctx
.mode
= NOUVEAU_GRCTX_VALS
;
231 ctx
.data
= chan
->ramin_grctx
;
232 nv50_grctx_init(&ctx
);
234 nv_wo32(chan
->ramin_grctx
, 0x00000, chan
->ramin
->vinst
>> 12);
236 dev_priv
->engine
.instmem
.flush(dev
);
241 nv50_graph_destroy_context(struct nouveau_channel
*chan
)
243 struct drm_device
*dev
= chan
->dev
;
244 struct drm_nouveau_private
*dev_priv
= dev
->dev_private
;
245 int i
, hdr
= (dev_priv
->chipset
== 0x50) ? 0x200 : 0x20;
247 NV_DEBUG(dev
, "ch%d\n", chan
->id
);
252 for (i
= hdr
; i
< hdr
+ 24; i
+= 4)
253 nv_wo32(chan
->ramin
, i
, 0);
254 dev_priv
->engine
.instmem
.flush(dev
);
256 nouveau_gpuobj_ref(NULL
, &chan
->ramin_grctx
);
260 nv50_graph_do_load_context(struct drm_device
*dev
, uint32_t inst
)
262 uint32_t fifo
= nv_rd32(dev
, 0x400500);
264 nv_wr32(dev
, 0x400500, fifo
& ~1);
265 nv_wr32(dev
, 0x400784, inst
);
266 nv_wr32(dev
, 0x400824, nv_rd32(dev
, 0x400824) | 0x40);
267 nv_wr32(dev
, 0x400320, nv_rd32(dev
, 0x400320) | 0x11);
268 nv_wr32(dev
, 0x400040, 0xffffffff);
269 (void)nv_rd32(dev
, 0x400040);
270 nv_wr32(dev
, 0x400040, 0x00000000);
271 nv_wr32(dev
, 0x400304, nv_rd32(dev
, 0x400304) | 1);
273 if (nouveau_wait_for_idle(dev
))
274 nv_wr32(dev
, 0x40032c, inst
| (1<<31));
275 nv_wr32(dev
, 0x400500, fifo
);
281 nv50_graph_load_context(struct nouveau_channel
*chan
)
283 uint32_t inst
= chan
->ramin
->vinst
>> 12;
285 NV_DEBUG(chan
->dev
, "ch%d\n", chan
->id
);
286 return nv50_graph_do_load_context(chan
->dev
, inst
);
290 nv50_graph_unload_context(struct drm_device
*dev
)
294 inst
= nv_rd32(dev
, NV50_PGRAPH_CTXCTL_CUR
);
295 if (!(inst
& NV50_PGRAPH_CTXCTL_CUR_LOADED
))
297 inst
&= NV50_PGRAPH_CTXCTL_CUR_INSTANCE
;
299 nouveau_wait_for_idle(dev
);
300 nv_wr32(dev
, 0x400784, inst
);
301 nv_wr32(dev
, 0x400824, nv_rd32(dev
, 0x400824) | 0x20);
302 nv_wr32(dev
, 0x400304, nv_rd32(dev
, 0x400304) | 0x01);
303 nouveau_wait_for_idle(dev
);
305 nv_wr32(dev
, NV50_PGRAPH_CTXCTL_CUR
, inst
);
310 nv50_graph_context_switch(struct drm_device
*dev
)
314 nv50_graph_unload_context(dev
);
316 inst
= nv_rd32(dev
, NV50_PGRAPH_CTXCTL_NEXT
);
317 inst
&= NV50_PGRAPH_CTXCTL_NEXT_INSTANCE
;
318 nv50_graph_do_load_context(dev
, inst
);
320 nv_wr32(dev
, NV40_PGRAPH_INTR_EN
, nv_rd32(dev
,
321 NV40_PGRAPH_INTR_EN
) | NV_PGRAPH_INTR_CONTEXT_SWITCH
);
325 nv50_graph_nvsw_dma_vblsem(struct nouveau_channel
*chan
, int grclass
,
326 int mthd
, uint32_t data
)
328 struct nouveau_gpuobj
*gpuobj
;
330 gpuobj
= nouveau_ramht_find(chan
, data
);
334 if (nouveau_notifier_offset(gpuobj
, NULL
))
337 chan
->nvsw
.vblsem
= gpuobj
;
338 chan
->nvsw
.vblsem_offset
= ~0;
343 nv50_graph_nvsw_vblsem_offset(struct nouveau_channel
*chan
, int grclass
,
344 int mthd
, uint32_t data
)
346 if (nouveau_notifier_offset(chan
->nvsw
.vblsem
, &data
))
349 chan
->nvsw
.vblsem_offset
= data
>> 2;
354 nv50_graph_nvsw_vblsem_release_val(struct nouveau_channel
*chan
, int grclass
,
355 int mthd
, uint32_t data
)
357 chan
->nvsw
.vblsem_rval
= data
;
362 nv50_graph_nvsw_vblsem_release(struct nouveau_channel
*chan
, int grclass
,
363 int mthd
, uint32_t data
)
365 struct drm_device
*dev
= chan
->dev
;
366 struct drm_nouveau_private
*dev_priv
= dev
->dev_private
;
368 if (!chan
->nvsw
.vblsem
|| chan
->nvsw
.vblsem_offset
== ~0 || data
> 1)
371 if (!(nv_rd32(dev
, NV50_PDISPLAY_INTR_EN
) &
372 NV50_PDISPLAY_INTR_EN_VBLANK_CRTC_(data
))) {
373 nv_wr32(dev
, NV50_PDISPLAY_INTR_1
,
374 NV50_PDISPLAY_INTR_1_VBLANK_CRTC_(data
));
375 nv_wr32(dev
, NV50_PDISPLAY_INTR_EN
, nv_rd32(dev
,
376 NV50_PDISPLAY_INTR_EN
) |
377 NV50_PDISPLAY_INTR_EN_VBLANK_CRTC_(data
));
380 list_add(&chan
->nvsw
.vbl_wait
, &dev_priv
->vbl_waiting
);
384 static struct nouveau_pgraph_object_method nv50_graph_nvsw_methods
[] = {
385 { 0x018c, nv50_graph_nvsw_dma_vblsem
},
386 { 0x0400, nv50_graph_nvsw_vblsem_offset
},
387 { 0x0404, nv50_graph_nvsw_vblsem_release_val
},
388 { 0x0408, nv50_graph_nvsw_vblsem_release
},
392 struct nouveau_pgraph_object_class nv50_graph_grclass
[] = {
393 { 0x506e, true, nv50_graph_nvsw_methods
}, /* nvsw */
394 { 0x0030, false, NULL
}, /* null */
395 { 0x5039, false, NULL
}, /* m2mf */
396 { 0x502d, false, NULL
}, /* 2d */
397 { 0x50c0, false, NULL
}, /* compute */
398 { 0x85c0, false, NULL
}, /* compute (nva3, nva5, nva8) */
399 { 0x5097, false, NULL
}, /* tesla (nv50) */
400 { 0x8297, false, NULL
}, /* tesla (nv8x/nv9x) */
401 { 0x8397, false, NULL
}, /* tesla (nva0, nvaa, nvac) */
402 { 0x8597, false, NULL
}, /* tesla (nva3, nva5, nva8) */