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 "nv50_grctx.h"
32 #define IS_G80 ((dev_priv->chipset & 0xf0) == 0x50)
35 nv50_graph_init_reset(struct drm_device
*dev
)
37 struct drm_nouveau_private
*dev_priv
= dev
->dev_private
;
38 uint32_t pmc_e
= NV_PMC_ENABLE_PGRAPH
| (1 << 21);
42 NV_WRITE(NV03_PMC_ENABLE
, NV_READ(NV03_PMC_ENABLE
) & ~pmc_e
);
43 NV_WRITE(NV03_PMC_ENABLE
, NV_READ(NV03_PMC_ENABLE
) | pmc_e
);
47 nv50_graph_init_intr(struct drm_device
*dev
)
49 struct drm_nouveau_private
*dev_priv
= dev
->dev_private
;
52 NV_WRITE(NV03_PGRAPH_INTR
, 0xffffffff);
53 NV_WRITE(0x400138, 0xffffffff);
54 NV_WRITE(NV40_PGRAPH_INTR_EN
, 0xffffffff);
58 nv50_graph_init_regs__nv(struct drm_device
*dev
)
60 struct drm_nouveau_private
*dev_priv
= dev
->dev_private
;
64 NV_WRITE(0x400804, 0xc0000000);
65 NV_WRITE(0x406800, 0xc0000000);
66 NV_WRITE(0x400c04, 0xc0000000);
67 NV_WRITE(0x401804, 0xc0000000);
68 NV_WRITE(0x405018, 0xc0000000);
69 NV_WRITE(0x402000, 0xc0000000);
71 NV_WRITE(0x400108, 0xffffffff);
73 NV_WRITE(0x400824, 0x00004000);
74 NV_WRITE(0x400500, 0x00010001);
78 nv50_graph_init_regs(struct drm_device
*dev
)
80 struct drm_nouveau_private
*dev_priv
= dev
->dev_private
;
84 NV_WRITE(NV04_PGRAPH_DEBUG_3
, (1<<2) /* HW_CONTEXT_SWITCH_ENABLED */);
88 nv50_graph_init_ctxctl(struct drm_device
*dev
)
90 struct drm_nouveau_private
*dev_priv
= dev
->dev_private
;
91 uint32_t *voodoo
= NULL
;
95 switch (dev_priv
->chipset
) {
97 voodoo
= nv50_ctxprog
;
100 voodoo
= nv84_ctxprog
;
103 voodoo
= nv86_ctxprog
;
106 voodoo
= nv92_ctxprog
;
110 voodoo
= nv94_ctxprog
;
113 voodoo
= nv98_ctxprog
;
116 voodoo
= nva0_ctxprog
;
119 voodoo
= nvaa_ctxprog
;
122 DRM_ERROR("no ctxprog for chipset NV%02x\n", dev_priv
->chipset
);
126 NV_WRITE(NV40_PGRAPH_CTXCTL_UCODE_INDEX
, 0);
127 while (*voodoo
!= ~0) {
128 NV_WRITE(NV40_PGRAPH_CTXCTL_UCODE_DATA
, *voodoo
);
132 NV_WRITE(0x400320, 4);
133 NV_WRITE(NV40_PGRAPH_CTXCTL_CUR
, 0);
134 NV_WRITE(NV20_PGRAPH_CHANNEL_CTX_POINTER
, 0);
140 nv50_graph_init(struct drm_device
*dev
)
146 nv50_graph_init_reset(dev
);
147 nv50_graph_init_intr(dev
);
148 nv50_graph_init_regs__nv(dev
);
149 nv50_graph_init_regs(dev
);
151 ret
= nv50_graph_init_ctxctl(dev
);
159 nv50_graph_takedown(struct drm_device
*dev
)
165 nv50_graph_create_context(struct nouveau_channel
*chan
)
167 struct drm_device
*dev
= chan
->dev
;
168 struct drm_nouveau_private
*dev_priv
= dev
->dev_private
;
169 struct nouveau_gpuobj
*ramin
= chan
->ramin
->gpuobj
;
170 struct nouveau_gpuobj
*ctx
;
171 struct nouveau_engine
*engine
= &dev_priv
->Engine
;
172 uint32_t *ctxvals
= NULL
;
173 int grctx_size
= 0x70000, hdr
;
176 DRM_DEBUG("ch%d\n", chan
->id
);
178 ret
= nouveau_gpuobj_new_ref(dev
, chan
, NULL
, 0, grctx_size
, 0x1000,
179 NVOBJ_FLAG_ZERO_ALLOC
|
180 NVOBJ_FLAG_ZERO_FREE
, &chan
->ramin_grctx
);
183 ctx
= chan
->ramin_grctx
->gpuobj
;
185 hdr
= IS_G80
? 0x200 : 0x20;
186 INSTANCE_WR(ramin
, (hdr
+ 0x00)/4, 0x00190002);
187 INSTANCE_WR(ramin
, (hdr
+ 0x04)/4, chan
->ramin_grctx
->instance
+
189 INSTANCE_WR(ramin
, (hdr
+ 0x08)/4, chan
->ramin_grctx
->instance
);
190 INSTANCE_WR(ramin
, (hdr
+ 0x0c)/4, 0);
191 INSTANCE_WR(ramin
, (hdr
+ 0x10)/4, 0);
192 INSTANCE_WR(ramin
, (hdr
+ 0x14)/4, 0x00010000);
194 switch (dev_priv
->chipset
) {
196 ctxvals
= nv50_ctxvals
;
199 ctxvals
= nv84_ctxvals
;
202 ctxvals
= nv86_ctxvals
;
205 ctxvals
= nv92_ctxvals
;
208 ctxvals
= nv94_ctxvals
;
211 ctxvals
= nv96_ctxvals
;
214 ctxvals
= nv98_ctxvals
;
217 ctxvals
= nva0_ctxvals
;
220 ctxvals
= nvaa_ctxvals
;
230 int cnt
= *ctxvals
++;
233 INSTANCE_WR(ctx
, pos
++, *ctxvals
);
237 /* This is complete crack, it accidently used to make at
238 * least some G8x cards work partially somehow, though there's
239 * no good reason why - and it stopped working as the rest
240 * of the code got off the drugs..
242 ret
= engine
->graph
.load_context(chan
);
244 DRM_ERROR("Error hacking up context: %d\n", ret
);
249 INSTANCE_WR(ctx
, 0x00000/4, chan
->ramin
->instance
>> 12);
250 if ((dev_priv
->chipset
& 0xf0) == 0xa0)
251 INSTANCE_WR(ctx
, 0x00004/4, 0x00000002);
253 INSTANCE_WR(ctx
, 0x0011c/4, 0x00000002);
259 nv50_graph_destroy_context(struct nouveau_channel
*chan
)
261 struct drm_device
*dev
= chan
->dev
;
262 struct drm_nouveau_private
*dev_priv
= dev
->dev_private
;
265 DRM_DEBUG("ch%d\n", chan
->id
);
267 hdr
= IS_G80
? 0x200 : 0x20;
268 for (i
=hdr
; i
<hdr
+24; i
+=4)
269 INSTANCE_WR(chan
->ramin
->gpuobj
, i
/4, 0);
271 nouveau_gpuobj_ref_del(dev
, &chan
->ramin_grctx
);
275 nv50_graph_transfer_context(struct drm_device
*dev
, uint32_t inst
, int save
)
277 struct drm_nouveau_private
*dev_priv
= dev
->dev_private
;
278 uint32_t old_cp
, tv
= 20000;
281 DRM_DEBUG("inst=0x%08x, save=%d\n", inst
, save
);
283 old_cp
= NV_READ(NV20_PGRAPH_CHANNEL_CTX_POINTER
);
284 NV_WRITE(NV20_PGRAPH_CHANNEL_CTX_POINTER
, inst
);
285 NV_WRITE(0x400824, NV_READ(0x400824) |
286 (save
? NV40_PGRAPH_CTXCTL_0310_XFER_SAVE
:
287 NV40_PGRAPH_CTXCTL_0310_XFER_LOAD
));
288 NV_WRITE(NV40_PGRAPH_CTXCTL_0304
, NV40_PGRAPH_CTXCTL_0304_XFER_CTX
);
290 for (i
= 0; i
< tv
; i
++) {
291 if (NV_READ(NV40_PGRAPH_CTXCTL_030C
) == 0)
294 NV_WRITE(NV20_PGRAPH_CHANNEL_CTX_POINTER
, old_cp
);
297 DRM_ERROR("failed: inst=0x%08x save=%d\n", inst
, save
);
298 DRM_ERROR("0x40030C = 0x%08x\n",
299 NV_READ(NV40_PGRAPH_CTXCTL_030C
));
307 nv50_graph_load_context(struct nouveau_channel
*chan
)
309 struct drm_device
*dev
= chan
->dev
;
310 struct drm_nouveau_private
*dev_priv
= dev
->dev_private
;
311 uint32_t inst
= chan
->ramin
->instance
>> 12;
314 DRM_DEBUG("ch%d\n", chan
->id
);
317 if ((ret
= nv50_graph_transfer_context(dev
, inst
, 0)))
321 NV_WRITE(NV20_PGRAPH_CHANNEL_CTX_POINTER
, inst
);
322 NV_WRITE(0x400320, 4);
323 NV_WRITE(NV40_PGRAPH_CTXCTL_CUR
, inst
| (1<<31));
329 nv50_graph_save_context(struct nouveau_channel
*chan
)
331 struct drm_device
*dev
= chan
->dev
;
332 uint32_t inst
= chan
->ramin
->instance
>> 12;
334 DRM_DEBUG("ch%d\n", chan
->id
);
336 return nv50_graph_transfer_context(dev
, inst
, 1);