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 #define IS_G80 ((dev_priv->chipset & 0xf0) == 0x50)
34 nv50_graph_init_reset(struct drm_device *dev)
36 struct drm_nouveau_private *dev_priv = dev->dev_private;
37 uint32_t pmc_e = NV_PMC_ENABLE_PGRAPH | (1 << 21);
41 NV_WRITE(NV03_PMC_ENABLE, NV_READ(NV03_PMC_ENABLE) & ~pmc_e);
42 NV_WRITE(NV03_PMC_ENABLE, NV_READ(NV03_PMC_ENABLE) | pmc_e);
46 nv50_graph_init_intr(struct drm_device *dev)
48 struct drm_nouveau_private *dev_priv = dev->dev_private;
51 NV_WRITE(NV03_PGRAPH_INTR, 0xffffffff);
52 NV_WRITE(0x400138, 0xffffffff);
53 NV_WRITE(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;
63 NV_WRITE(0x400804, 0xc0000000);
64 NV_WRITE(0x406800, 0xc0000000);
65 NV_WRITE(0x400c04, 0xc0000000);
66 NV_WRITE(0x401804, 0xc0000000);
67 NV_WRITE(0x405018, 0xc0000000);
68 NV_WRITE(0x402000, 0xc0000000);
70 NV_WRITE(0x400108, 0xffffffff);
72 NV_WRITE(0x400824, 0x00004000);
73 NV_WRITE(0x400500, 0x00010001);
77 nv50_graph_init_regs(struct drm_device *dev)
79 struct drm_nouveau_private *dev_priv = dev->dev_private;
83 NV_WRITE(NV04_PGRAPH_DEBUG_3, (1<<2) /* HW_CONTEXT_SWITCH_ENABLED */);
86 static uint32_t nv84_ctx_voodoo[] = {
87 0x0070008e, 0x0070009c, 0x00200020, 0x00600008, 0x0050004c, 0x00400e89,
88 0x00200000, 0x00600007, 0x00300000, 0x00c000ff, 0x00200000, 0x008000ff,
89 0x00700009, 0x0041634d, 0x00402944, 0x00402905, 0x0040290d, 0x00413e06,
90 0x00600005, 0x004015c5, 0x00600011, 0x0040270b, 0x004021c5, 0x00700000,
91 0x00700081, 0x00600004, 0x0050004a, 0x00216f40, 0x00600007, 0x00c02801,
92 0x0020002e, 0x00800001, 0x005000cb, 0x0090ffff, 0x0091ffff, 0x00200020,
93 0x00600008, 0x0050004c, 0x00600009, 0x00413e45, 0x0041594d, 0x0070009d,
94 0x00402dcf, 0x0070009f, 0x0050009f, 0x00402ac0, 0x00200200, 0x00600008,
95 0x00402a4f, 0x00402ac0, 0x004030cc, 0x00700081, 0x00200000, 0x00600006,
96 0x00700000, 0x00111bfc, 0x00700083, 0x00300000, 0x00216f40, 0x00600007,
97 0x00c00b01, 0x0020001e, 0x00800001, 0x005000cb, 0x00c000ff, 0x00700080,
98 0x00700083, 0x00200047, 0x00600006, 0x0011020a, 0x00200480, 0x00600007,
99 0x00300000, 0x00c000ff, 0x00c800ff, 0x00414907, 0x00202916, 0x008000ff,
100 0x0040508c, 0x005000cb, 0x00a0023f, 0x00200040, 0x00600006, 0x0070000f,
101 0x00170202, 0x0011020a, 0x00200032, 0x0010020d, 0x001c0242, 0x00120302,
102 0x00140402, 0x00180500, 0x00130509, 0x00150550, 0x00110605, 0x0020000f,
103 0x00100607, 0x00110700, 0x00110900, 0x00120902, 0x00110a00, 0x00160b02,
104 0x00120b28, 0x00140b2b, 0x00110c01, 0x00111400, 0x00111405, 0x00111407,
105 0x00111409, 0x0011140b, 0x002000cb, 0x00101500, 0x0040790f, 0x0040794b,
106 0x00214d40, 0x00600007, 0x0020043e, 0x008800ff, 0x0070008f, 0x0040798c,
107 0x005000cb, 0x00000000, 0x0020002b, 0x00101a05, 0x00131c00, 0x00121c04,
108 0x00141c20, 0x00111c25, 0x00131c40, 0x00121c44, 0x00141c60, 0x00111c65,
109 0x00131c80, 0x00121c84, 0x00141ca0, 0x00111ca5, 0x00131cc0, 0x00121cc4,
110 0x00141ce0, 0x00111ce5, 0x00131f00, 0x00191f40, 0x0040a1e0, 0x002001ed,
111 0x00600006, 0x00200044, 0x00102080, 0x001120c6, 0x001520c9, 0x001920d0,
112 0x00122100, 0x00122103, 0x00162200, 0x00122207, 0x00112280, 0x00112300,
113 0x00112302, 0x00122380, 0x0011238b, 0x00112394, 0x0011239c, 0x0040bee1,
114 0x00200254, 0x00600006, 0x00200044, 0x00102480, 0x0040af0f, 0x0040af4b,
115 0x00214d40, 0x00600007, 0x0020043e, 0x008800ff, 0x0070008f, 0x0040af8c,
116 0x005000cb, 0x00000000, 0x001124c6, 0x001524c9, 0x001924d0, 0x00122500,
117 0x00122503, 0x00162600, 0x00122607, 0x00112680, 0x00112700, 0x00112702,
118 0x00122780, 0x0011278b, 0x00112794, 0x0011279c, 0x0040d1e2, 0x002002bb,
119 0x00600006, 0x00200044, 0x00102880, 0x001128c6, 0x001528c9, 0x001928d0,
120 0x00122900, 0x00122903, 0x00162a00, 0x00122a07, 0x00112a80, 0x00112b00,
121 0x00112b02, 0x00122b80, 0x00112b8b, 0x00112b94, 0x00112b9c, 0x0040eee3,
122 0x00200322, 0x00600006, 0x00200044, 0x00102c80, 0x0040df0f, 0x0040df4b,
123 0x00214d40, 0x00600007, 0x0020043e, 0x008800ff, 0x0070008f, 0x0040df8c,
124 0x005000cb, 0x00000000, 0x00112cc6, 0x00152cc9, 0x00192cd0, 0x00122d00,
125 0x00122d03, 0x00162e00, 0x00122e07, 0x00112e80, 0x00112f00, 0x00112f02,
126 0x00122f80, 0x00112f8b, 0x00112f94, 0x00112f9c, 0x004101e4, 0x00200389,
127 0x00600006, 0x00200044, 0x00103080, 0x001130c6, 0x001530c9, 0x001930d0,
128 0x00123100, 0x00123103, 0x00163200, 0x00123207, 0x00113280, 0x00113300,
129 0x00113302, 0x00123380, 0x0011338b, 0x00113394, 0x0011339c, 0x00411ee5,
130 0x002003f0, 0x00600006, 0x00200044, 0x00103480, 0x00410f0f, 0x00410f4b,
131 0x00214d40, 0x00600007, 0x0020043e, 0x008800ff, 0x0070008f, 0x00410f8c,
132 0x005000cb, 0x00000000, 0x001134c6, 0x001534c9, 0x001934d0, 0x00123500,
133 0x00123503, 0x00163600, 0x00123607, 0x00113680, 0x00113700, 0x00113702,
134 0x00123780, 0x0011378b, 0x00113794, 0x0011379c, 0x00000000, 0x0041250f,
135 0x005000cb, 0x00214d40, 0x00600007, 0x0020043e, 0x008800ff, 0x005000cb,
136 0x00412887, 0x0060000a, 0x00000000, 0x00413700, 0x007000a0, 0x00700080,
137 0x00200480, 0x00600007, 0x00200004, 0x00c000ff, 0x008000ff, 0x005000cb,
138 0x00700000, 0x00200000, 0x00600006, 0x00111bfe, 0x0041594d, 0x00700000,
139 0x00200000, 0x00600006, 0x00111bfe, 0x00700080, 0x0070001d, 0x0040114d,
140 0x00700081, 0x00600004, 0x0050004a, 0x00414388, 0x0060000b, 0x00200000,
141 0x00600006, 0x00700000, 0x0041590b, 0x00111bfd, 0x0040424d, 0x00202916,
142 0x008000fd, 0x005000cb, 0x00c00002, 0x00200480, 0x00600007, 0x00200160,
143 0x00800002, 0x005000cb, 0x00c01802, 0x002027b6, 0x00800002, 0x005000cb,
144 0x00404e4d, 0x0060000b, 0x0041574d, 0x00700001, 0x005000cf, 0x00700003,
145 0x00415e06, 0x00415f05, 0x0060000d, 0x00700005, 0x0070000d, 0x00700006,
146 0x0070000b, 0x0070000e, 0x0070001c, 0x0060000c, ~0
149 static uint32_t nv86_ctx_voodoo[] = {
150 0x0070008e, 0x0070009c, 0x00200020, 0x00600008, 0x0050004c, 0x00400e89,
151 0x00200000, 0x00600007, 0x00300000, 0x00c000ff, 0x00200000, 0x008000ff,
152 0x00700009, 0x0040dd4d, 0x00402944, 0x00402905, 0x0040290d, 0x0040b906,
153 0x00600005, 0x004015c5, 0x00600011, 0x0040270b, 0x004021c5, 0x00700000,
154 0x00700081, 0x00600004, 0x0050004a, 0x00216d80, 0x00600007, 0x00c02801,
155 0x0020002e, 0x00800001, 0x005000cb, 0x0090ffff, 0x0091ffff, 0x00200020,
156 0x00600008, 0x0050004c, 0x00600009, 0x0040b945, 0x0040d44d, 0x0070009d,
157 0x00402dcf, 0x0070009f, 0x0050009f, 0x00402ac0, 0x00200200, 0x00600008,
158 0x00402a4f, 0x00402ac0, 0x004030cc, 0x00700081, 0x00200000, 0x00600006,
159 0x00700000, 0x00111bfc, 0x00700083, 0x00300000, 0x00216d80, 0x00600007,
160 0x00c00b01, 0x0020001e, 0x00800001, 0x005000cb, 0x00c000ff, 0x00700080,
161 0x00700083, 0x00200047, 0x00600006, 0x0011020a, 0x00200280, 0x00600007,
162 0x00300000, 0x00c000ff, 0x00c800ff, 0x0040c407, 0x00202916, 0x008000ff,
163 0x0040508c, 0x005000cb, 0x00a0023f, 0x00200040, 0x00600006, 0x0070000f,
164 0x00170202, 0x0011020a, 0x00200032, 0x0010020d, 0x001c0242, 0x00120302,
165 0x00140402, 0x00180500, 0x00130509, 0x00150550, 0x00110605, 0x0020000f,
166 0x00100607, 0x00110700, 0x00110900, 0x00120902, 0x00110a00, 0x00160b02,
167 0x00120b28, 0x00140b2b, 0x00110c01, 0x00111400, 0x00111405, 0x00111407,
168 0x00111409, 0x0011140b, 0x002000cb, 0x00101500, 0x0040790f, 0x0040794b,
169 0x00214b40, 0x00600007, 0x00200442, 0x008800ff, 0x0070008f, 0x0040798c,
170 0x005000cb, 0x00000000, 0x0020002b, 0x00101a05, 0x00131c00, 0x00121c04,
171 0x00141c20, 0x00111c25, 0x00131c40, 0x00121c44, 0x00141c60, 0x00111c65,
172 0x00131f00, 0x00191f40, 0x004099e0, 0x002001d9, 0x00600006, 0x00200044,
173 0x00102080, 0x001120c6, 0x001520c9, 0x001920d0, 0x00122100, 0x00122103,
174 0x00162200, 0x00122207, 0x00112280, 0x00112300, 0x00112302, 0x00122380,
175 0x0011238b, 0x00112394, 0x0011239c, 0x00000000, 0x0040a00f, 0x005000cb,
176 0x00214b40, 0x00600007, 0x00200442, 0x008800ff, 0x005000cb, 0x0040a387,
177 0x0060000a, 0x00000000, 0x0040b200, 0x007000a0, 0x00700080, 0x00200280,
178 0x00600007, 0x00200004, 0x00c000ff, 0x008000ff, 0x005000cb, 0x00700000,
179 0x00200000, 0x00600006, 0x00111bfe, 0x0040d44d, 0x00700000, 0x00200000,
180 0x00600006, 0x00111bfe, 0x00700080, 0x0070001d, 0x0040114d, 0x00700081,
181 0x00600004, 0x0050004a, 0x0040be88, 0x0060000b, 0x00200000, 0x00600006,
182 0x00700000, 0x0040d40b, 0x00111bfd, 0x0040424d, 0x00202916, 0x008000fd,
183 0x005000cb, 0x00c00002, 0x00200280, 0x00600007, 0x00200160, 0x00800002,
184 0x005000cb, 0x00c01802, 0x002027b6, 0x00800002, 0x005000cb, 0x00404e4d,
185 0x0060000b, 0x0040d24d, 0x00700001, 0x00700003, 0x0040d806, 0x0040d905,
186 0x0060000d, 0x00700005, 0x0070000d, 0x00700006, 0x0070000b, 0x0070000e,
187 0x0070001c, 0x0060000c, ~0
191 nv50_graph_init_ctxctl(struct drm_device *dev)
193 struct drm_nouveau_private *dev_priv = dev->dev_private;
194 uint32_t *voodoo = NULL;
198 switch (dev_priv->chipset) {
200 voodoo = nv84_ctx_voodoo;
203 voodoo = nv86_ctx_voodoo;
206 DRM_ERROR("no voodoo for chipset NV%02x\n", dev_priv->chipset);
210 NV_WRITE(NV40_PGRAPH_CTXCTL_UCODE_INDEX, 0);
211 while (*voodoo != ~0) {
212 NV_WRITE(NV40_PGRAPH_CTXCTL_UCODE_DATA, *voodoo);
216 NV_WRITE(0x400320, 4);
217 NV_WRITE(NV40_PGRAPH_CTXCTL_CUR, 0);
218 NV_WRITE(NV20_PGRAPH_CHANNEL_CTX_POINTER, 0);
224 nv50_graph_init(struct drm_device *dev)
230 nv50_graph_init_reset(dev);
231 nv50_graph_init_intr(dev);
232 nv50_graph_init_regs__nv(dev);
233 nv50_graph_init_regs(dev);
235 ret = nv50_graph_init_ctxctl(dev);
243 nv50_graph_takedown(struct drm_device *dev)
249 nv50_graph_create_context(struct nouveau_channel *chan)
251 struct drm_device *dev = chan->dev;
252 struct drm_nouveau_private *dev_priv = dev->dev_private;
253 struct nouveau_engine *engine = &dev_priv->Engine;
254 struct nouveau_gpuobj *ramin = chan->ramin->gpuobj;
255 int grctx_size = 0x60000, hdr;
258 DRM_DEBUG("ch%d\n", chan->id);
260 ret = nouveau_gpuobj_new_ref(dev, chan, NULL, 0, grctx_size, 0x1000,
261 NVOBJ_FLAG_ZERO_ALLOC |
262 NVOBJ_FLAG_ZERO_FREE, &chan->ramin_grctx);
266 hdr = IS_G80 ? 0x200 : 0x20;
267 INSTANCE_WR(ramin, (hdr + 0x00)/4, 0x00190002);
268 INSTANCE_WR(ramin, (hdr + 0x04)/4, chan->ramin_grctx->instance +
270 INSTANCE_WR(ramin, (hdr + 0x08)/4, chan->ramin_grctx->instance);
271 INSTANCE_WR(ramin, (hdr + 0x0c)/4, 0);
272 INSTANCE_WR(ramin, (hdr + 0x10)/4, 0);
273 INSTANCE_WR(ramin, (hdr + 0x14)/4, 0x00010000);
275 ret = engine->graph.load_context(chan);
277 DRM_ERROR("Error hacking up initial context: %d\n", ret);
281 INSTANCE_WR(chan->ramin_grctx->gpuobj, 0x00000/4,
282 chan->ramin->instance >> 12);
283 INSTANCE_WR(chan->ramin_grctx->gpuobj, 0x0011c/4, 0x00000002);
289 nv50_graph_destroy_context(struct nouveau_channel *chan)
291 struct drm_device *dev = chan->dev;
292 struct drm_nouveau_private *dev_priv = dev->dev_private;
295 DRM_DEBUG("ch%d\n", chan->id);
297 hdr = IS_G80 ? 0x200 : 0x20;
298 for (i=hdr; i<hdr+24; i+=4)
299 INSTANCE_WR(chan->ramin->gpuobj, i/4, 0);
301 nouveau_gpuobj_ref_del(dev, &chan->ramin_grctx);
305 nv50_graph_transfer_context(struct drm_device *dev, uint32_t inst, int save)
307 struct drm_nouveau_private *dev_priv = dev->dev_private;
308 uint32_t old_cp, tv = 20000;
311 DRM_DEBUG("inst=0x%08x, save=%d\n", inst, save);
313 old_cp = NV_READ(NV20_PGRAPH_CHANNEL_CTX_POINTER);
314 NV_WRITE(NV20_PGRAPH_CHANNEL_CTX_POINTER, inst);
315 NV_WRITE(0x400824, NV_READ(0x400824) |
316 (save ? NV40_PGRAPH_CTXCTL_0310_XFER_SAVE :
317 NV40_PGRAPH_CTXCTL_0310_XFER_LOAD));
318 NV_WRITE(NV40_PGRAPH_CTXCTL_0304, NV40_PGRAPH_CTXCTL_0304_XFER_CTX);
320 for (i = 0; i < tv; i++) {
321 if (NV_READ(NV40_PGRAPH_CTXCTL_030C) == 0)
324 NV_WRITE(NV20_PGRAPH_CHANNEL_CTX_POINTER, old_cp);
327 DRM_ERROR("failed: inst=0x%08x save=%d\n", inst, save);
328 DRM_ERROR("0x40030C = 0x%08x\n",
329 NV_READ(NV40_PGRAPH_CTXCTL_030C));
337 nv50_graph_load_context(struct nouveau_channel *chan)
339 struct drm_device *dev = chan->dev;
340 struct drm_nouveau_private *dev_priv = dev->dev_private;
341 uint32_t inst = chan->ramin->instance >> 12;
344 DRM_DEBUG("ch%d\n", chan->id);
347 if ((ret = nv50_graph_transfer_context(dev, inst, 0)))
351 NV_WRITE(NV20_PGRAPH_CHANNEL_CTX_POINTER, inst);
352 NV_WRITE(0x400320, 4);
353 NV_WRITE(NV40_PGRAPH_CTXCTL_CUR, inst | (1<<31));
359 nv50_graph_save_context(struct nouveau_channel *chan)
361 struct drm_device *dev = chan->dev;
362 uint32_t inst = chan->ramin->instance >> 12;
364 DRM_DEBUG("ch%d\n", chan->id);
366 return nv50_graph_transfer_context(dev, inst, 1);