2 * Copyright (C) 2010 Christoph Bumiller.
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.
28 #include "nouveau_drv.h"
29 #include "nouveau_reg.h"
30 #include "pscnv_fifo.h"
31 #include "pscnv_chan.h"
33 struct nvc0_fifo_engine
{
34 struct pscnv_fifo_engine base
;
35 struct pscnv_bo
*playlist
[2];
37 struct pscnv_bo
*ctrl_bo
;
38 struct drm_local_map
*fifo_ctl
;
41 #define nvc0_fifo(x) container_of(x, struct nvc0_fifo_engine, base)
43 static void nvc0_fifo_takedown(struct drm_device
*dev
);
44 static void nvc0_fifo_irq_handler(struct drm_device
*dev
, int irq
);
45 static int nvc0_fifo_chan_init_ib (struct pscnv_chan
*ch
, uint32_t pb_handle
, uint32_t flags
, uint32_t slimask
, uint64_t ib_start
, uint32_t ib_order
);
46 static void nvc0_fifo_chan_kill(struct pscnv_chan
*ch
);
48 int nvc0_fifo_init(struct drm_device
*dev
)
50 struct drm_nouveau_private
*dev_priv
= dev
->dev_private
;
51 struct nvc0_fifo_engine
*res
= kzalloc(sizeof *res
, GFP_KERNEL
);
56 NV_ERROR(dev
, "PFIFO: Couldn't allocate engine!\n");
60 res
->base
.takedown
= nvc0_fifo_takedown
;
61 res
->base
.chan_kill
= nvc0_fifo_chan_kill
;
62 res
->base
.chan_init_ib
= nvc0_fifo_chan_init_ib
;
64 res
->ctrl_bo
= pscnv_mem_alloc(dev
, 128 * 0x1000,
65 PSCNV_GEM_CONTIG
, 0, 0xf1f03e95);
68 NV_ERROR(dev
, "PFIFO: Couldn't allocate control area!\n");
73 res
->playlist
[0] = pscnv_mem_alloc(dev
, 0x1000, PSCNV_GEM_CONTIG
, 0, 0x91a71157);
74 res
->playlist
[1] = pscnv_mem_alloc(dev
, 0x1000, PSCNV_GEM_CONTIG
, 0, 0x91a71157);
75 if (!res
->playlist
[0] || !res
->playlist
[1]) {
76 NV_ERROR(dev
, "PFIFO: Couldn't allocate playlists!\n");
78 pscnv_mem_free(res
->playlist
[0]);
80 pscnv_mem_free(res
->playlist
[1]);
81 pscnv_mem_free(res
->ctrl_bo
);
85 dev_priv
->vm
->map_kernel(res
->playlist
[0]);
86 dev_priv
->vm
->map_kernel(res
->playlist
[1]);
87 res
->cur_playlist
= 0;
89 dev_priv
->vm
->map_user(res
->ctrl_bo
);
91 if (!res
->ctrl_bo
->map1
) {
92 NV_ERROR(dev
, "PFIFO: Couldn't map control area!\n");
93 pscnv_mem_free(res
->playlist
[0]);
94 pscnv_mem_free(res
->playlist
[1]);
95 pscnv_mem_free(res
->ctrl_bo
);
99 ret
= drm_addmap(dev
, drm_get_resource_start(dev
, 1) +
100 res
->ctrl_bo
->map1
->start
, 128 << 12,
101 _DRM_REGISTERS
, _DRM_KERNEL
| _DRM_DRIVER
, &res
->fifo_ctl
);
103 NV_ERROR(dev
, "PFIFO: Couldn't ioremap control area!\n");
104 pscnv_mem_free(res
->playlist
[0]);
105 pscnv_mem_free(res
->playlist
[1]);
106 pscnv_mem_free(res
->ctrl_bo
);
111 /* reset PFIFO, enable all available PSUBFIFO areas */
112 nv_mask(dev
, 0x000200, 0x00000100, 0x00000000);
113 nv_mask(dev
, 0x000200, 0x00000100, 0x00000100);
114 nv_wr32(dev
, 0x000204, 0xffffffff);
115 nv_wr32(dev
, 0x002204, 0xffffffff);
117 subfifo_count
= hweight32(nv_rd32(dev
, 0x002204));
119 /* assign engines to subfifos */
120 if (subfifo_count
>= 3) {
121 nv_wr32(dev
, 0x002208, ~(1 << 0)); /* PGRAPH */
122 nv_wr32(dev
, 0x00220c, ~(1 << 1)); /* PVP */
123 nv_wr32(dev
, 0x002210, ~(1 << 1)); /* PPP */
124 nv_wr32(dev
, 0x002214, ~(1 << 1)); /* PBSP */
125 nv_wr32(dev
, 0x002218, ~(1 << 2)); /* PCE0 (PCOPY0) */
126 nv_wr32(dev
, 0x00221c, ~(1 << 1)); /* PCE1 (PCOPY1) */
130 for (i
= 0; i
< subfifo_count
; i
++) {
131 nv_mask(dev
, 0x04013c + (i
* 0x2000), 0x10000100, 0x00000000);
132 nv_wr32(dev
, 0x040108 + (i
* 0x2000), 0xffffffff); /* INTR */
133 nv_wr32(dev
, 0x04010c + (i
* 0x2000), 0xfffffeff); /* INTR_EN */
137 nv_wr32(dev
, 0x204, 0);
138 nv_wr32(dev
, 0x204, 7); /* PMC.SUBFIFO_ENABLE */
139 nv_wr32(dev
, 0x2204, 7); /* PFIFO.SUBFIFO_ENABLE */
143 nv_mask(dev
, 0x002200, 0x00000001, 0x00000001);
145 /* PFIFO.POLL_AREA */
146 nv_wr32(dev
, 0x2254, (1 << 28) | (res
->ctrl_bo
->map1
->start
>> 12));
148 dev_priv
->fifo
= &res
->base
;
150 nouveau_irq_register(dev
, 8, nvc0_fifo_irq_handler
);
152 nv_wr32(dev
, 0x002a00, 0xffffffff); /* clears PFIFO.INTR bit 30 */
153 nv_wr32(dev
, 0x002100, 0xffffffff);
154 nv_wr32(dev
, 0x2140, 0xbfffffff); /* PFIFO_INTR_EN */
159 static void nvc0_fifo_takedown(struct drm_device
*dev
)
161 struct drm_nouveau_private
*dev_priv
= dev
->dev_private
;
162 struct nvc0_fifo_engine
*fifo
= nvc0_fifo(dev_priv
->fifo
);
163 nv_wr32(dev
, 0x2140, 0);
164 nouveau_irq_unregister(dev
, 8);
166 pscnv_mem_free(fifo
->playlist
[0]);
167 pscnv_mem_free(fifo
->playlist
[1]);
168 drm_rmmap(dev
, fifo
->fifo_ctl
);
169 pscnv_mem_free(fifo
->ctrl_bo
);
174 static void nvc0_fifo_playlist_update(struct drm_device
*dev
)
176 struct drm_nouveau_private
*dev_priv
= dev
->dev_private
;
177 struct nvc0_fifo_engine
*fifo
= nvc0_fifo(dev_priv
->fifo
);
180 fifo
->cur_playlist
^= 1;
181 vo
= fifo
->playlist
[fifo
->cur_playlist
];
182 for (i
= 0, pos
= 0; i
< 128; i
++) {
183 if (nv_rd32(dev
, 0x3004 + i
* 8) & 1) {
185 nv_wv32(vo
, pos
+ 4, 0x4);
189 dev_priv
->vm
->bar_flush(dev
);
191 nv_wr32(dev
, 0x2270, vo
->start
>> 12);
192 nv_wr32(dev
, 0x2274, 0x1f00000 | pos
/ 8);
194 if (!nv_wait(dev
, 0x227c, (1 << 20), 0))
195 NV_WARN(dev
, "WARNING: PFIFO 227c = 0x%08x\n",
196 nv_rd32(dev
, 0x227c));
199 static void nvc0_fifo_chan_kill(struct pscnv_chan
*ch
)
201 struct drm_device
*dev
= ch
->dev
;
202 struct drm_nouveau_private
*dev_priv
= dev
->dev_private
;
210 spin_lock_irqsave(&dev_priv
->context_switch_lock
, flags
);
211 status
= nv_rd32(dev
, 0x3004 + ch
->cid
* 8);
212 nv_wr32(dev
, 0x3004 + ch
->cid
* 8, status
& ~1);
213 nv_wr32(dev
, 0x2634, ch
->cid
);
214 if (!nv_wait(dev
, 0x2634, ~0, ch
->cid
))
215 NV_WARN(dev
, "WARNING: 2634 = 0x%08x\n", nv_rd32(dev
, 0x2634));
217 nvc0_fifo_playlist_update(dev
);
219 if (nv_rd32(dev
, 0x3004 + ch
->cid
* 8) & 0x1110) {
220 NV_WARN(dev
, "WARNING: PFIFO kickoff fail :(\n");
222 spin_unlock_irqrestore(&dev_priv
->context_switch_lock
, flags
);
225 #define nvchan_wr32(chan, ofst, val) \
226 DRM_WRITE32(fifo->fifo_ctl, ((chan)->cid * 0x1000 + ofst), val)
228 static int nvc0_fifo_chan_init_ib (struct pscnv_chan
*ch
, uint32_t pb_handle
, uint32_t flags
, uint32_t slimask
, uint64_t ib_start
, uint32_t ib_order
) {
229 struct drm_device
*dev
= ch
->dev
;
230 struct drm_nouveau_private
*dev_priv
= dev
->dev_private
;
231 struct nvc0_fifo_engine
*fifo
= nvc0_fifo(dev_priv
->fifo
);
232 unsigned long irqflags
;
235 uint64_t fifo_regs
= fifo
->ctrl_bo
->start
+ (ch
->cid
<< 12);
240 spin_lock_irqsave(&dev_priv
->context_switch_lock
, irqflags
);
242 for (i
= 0x40; i
<= 0x50; i
+= 4)
243 nvchan_wr32(ch
, i
, 0);
244 for (i
= 0x58; i
<= 0x60; i
+= 4)
245 nvchan_wr32(ch
, i
, 0);
246 nvchan_wr32(ch
, 0x88, 0);
247 nvchan_wr32(ch
, 0x8c, 0);
249 for (i
= 0; i
< 0x100; i
+= 4)
250 nv_wv32(ch
->bo
, i
, 0);
252 dev_priv
->vm
->bar_flush(dev
);
254 nv_wv32(ch
->bo
, 0x08, fifo_regs
);
255 nv_wv32(ch
->bo
, 0x0c, fifo_regs
>> 32);
257 nv_wv32(ch
->bo
, 0x48, ib_start
); /* IB */
258 nv_wv32(ch
->bo
, 0x4c,
259 (ib_start
>> 32) | (ib_order
<< 16));
260 nv_wv32(ch
->bo
, 0x10, 0xface);
261 nv_wv32(ch
->bo
, 0x54, 0x2);
262 nv_wv32(ch
->bo
, 0x9c, 0x100);
263 nv_wv32(ch
->bo
, 0x84, 0x20400000);
264 nv_wv32(ch
->bo
, 0x94, 0x30000000 ^ slimask
);
265 nv_wv32(ch
->bo
, 0xa4, 0x1f1f1f1f);
266 nv_wv32(ch
->bo
, 0xa8, 0x1f1f1f1f);
267 nv_wv32(ch
->bo
, 0xac, 0x1f);
268 nv_wv32(ch
->bo
, 0x30, 0xfffff902);
269 /* nv_wv32(chan->vo, 0xb8, 0xf8000000); */ /* previously omitted */
270 nv_wv32(ch
->bo
, 0xf8, 0x10003080);
271 nv_wv32(ch
->bo
, 0xfc, 0x10000010);
272 dev_priv
->vm
->bar_flush(dev
);
274 nv_wr32(dev
, 0x3000 + ch
->cid
* 8, 0xc0000000 | ch
->bo
->start
>> 12);
275 nv_wr32(dev
, 0x3004 + ch
->cid
* 8, 0x1f0001);
277 nvc0_fifo_playlist_update(dev
);
279 spin_unlock_irqrestore(&dev_priv
->context_switch_lock
, irqflags
);
281 dev_priv
->engines
[PSCNV_ENGINE_GRAPH
]->
282 chan_alloc(dev_priv
->engines
[PSCNV_ENGINE_GRAPH
], ch
);
283 if (dev_priv
->engines
[PSCNV_ENGINE_COPY0
])
284 dev_priv
->engines
[PSCNV_ENGINE_COPY0
]->
285 chan_alloc(dev_priv
->engines
[PSCNV_ENGINE_COPY0
], ch
);
286 if (dev_priv
->engines
[PSCNV_ENGINE_COPY1
])
287 dev_priv
->engines
[PSCNV_ENGINE_COPY1
]->
288 chan_alloc(dev_priv
->engines
[PSCNV_ENGINE_COPY1
], ch
);
293 static const char *pgf_unit_str(int unit
)
296 case 0: return "PGRAPH";
297 case 3: return "PEEPHOLE";
298 case 4: return "FB BAR";
299 case 5: return "RAMIN BAR";
300 case 7: return "PUSHBUF";
304 return "(unknown unit)";
307 static const char *pgf_cause_str(uint32_t flags
)
309 switch (flags
& 0xf) {
310 case 0x0: return "PDE not present";
311 case 0x1: return "PT too short";
312 case 0x2: return "PTE not present";
313 case 0x3: return "LIMIT exceeded";
314 case 0x5: return "NOUSER";
315 case 0x6: return "PTE set read-only";
319 return "unknown cause";
322 static void nvc0_pfifo_page_fault(struct drm_device
*dev
, int unit
)
325 uint32_t chan
, flags
;
327 chan
= nv_rd32(dev
, 0x2800 + unit
* 0x10) << 12;
328 virt
= nv_rd32(dev
, 0x2808 + unit
* 0x10);
329 virt
= (virt
<< 32) | nv_rd32(dev
, 0x2804 + unit
* 0x10);
330 flags
= nv_rd32(dev
, 0x280c + unit
* 0x10);
332 NV_INFO(dev
, "%s PAGE FAULT at 0x%010llx (%c, %s)\n",
333 pgf_unit_str(unit
), virt
,
334 (flags
& 0x80) ? 'w' : 'r', pgf_cause_str(flags
));
337 static void nvc0_pfifo_subfifo_fault(struct drm_device
*dev
, int unit
)
339 int cid
= nv_rd32(dev
, 0x40120 + unit
* 0x2000) & 0x7f;
340 int status
= nv_rd32(dev
, 0x40108 + unit
* 0x2000);
341 uint32_t addr
= nv_rd32(dev
, 0x400c0 + unit
* 0x2000);
342 uint32_t data
= nv_rd32(dev
, 0x400c4 + unit
* 0x2000);
343 int sub
= addr
>> 16 & 7;
344 int mthd
= addr
& 0x3ffc;
345 int mode
= addr
>> 21 & 7;
347 if (status
& 0x200000) {
348 NV_INFO(dev
, "PSUBFIFO %d ILLEGAL_MTHD: ch %d sub %d mthd %04x%s [mode %d] data %08x\n", unit
, cid
, sub
, mthd
, ((addr
& 1)?" NI":""), mode
, data
);
349 nv_wr32(dev
, 0x400c0 + unit
* 0x2000, 0x80600008);
350 nv_wr32(dev
, 0x40108 + unit
* 0x2000, 0x200000);
353 if (status
& 0x800000) {
354 NV_INFO(dev
, "PSUBFIFO %d EMPTY_SUBCHANNEL: ch %d sub %d mthd %04x%s [mode %d] data %08x\n", unit
, cid
, sub
, mthd
, ((addr
& 1)?" NI":""), mode
, data
);
355 nv_wr32(dev
, 0x400c0 + unit
* 0x2000, 0x80600008);
356 nv_wr32(dev
, 0x40108 + unit
* 0x2000, 0x800000);
360 NV_INFO(dev
, "unknown PSUBFIFO INTR: 0x%08x\n", status
);
361 nv_wr32(dev
, 0x4010c + unit
* 0x2000, nv_rd32(dev
, 0x4010c + unit
* 0x2000) & ~status
);
365 static void nvc0_fifo_irq_handler(struct drm_device
*dev
, int irq
)
369 status
= nv_rd32(dev
, 0x2100) & nv_rd32(dev
, 0x2140);
372 NV_INFO(dev
, "PFIFO INTR 1!\n");
373 nv_wr32(dev
, 0x2100, 1);
377 if (status
& 0x10000000) {
378 uint32_t bits
= nv_rd32(dev
, 0x259c);
379 uint32_t units
= bits
;
382 int i
= ffs(units
) - 1;
384 nvc0_pfifo_page_fault(dev
, i
);
386 nv_wr32(dev
, 0x259c, bits
); /* ack */
387 status
&= ~0x10000000;
390 if (status
& 0x20000000) {
391 uint32_t bits
= nv_rd32(dev
, 0x25a0);
392 uint32_t units
= bits
;
394 int i
= ffs(units
) - 1;
396 nvc0_pfifo_subfifo_fault(dev
, i
);
398 nv_wr32(dev
, 0x25a0, bits
); /* ack */
399 status
&= ~0x20000000;
402 if (status
& 0x00000100) {
404 uint32_t data
= nv_rd32(dev
, 0x400c4);
406 ibpk
[0] = nv_rd32(dev
, 0x40110);
407 ibpk
[1] = nv_rd32(dev
, 0x40114);
409 NV_INFO(dev
, "PFIFO FUCKUP: DATA = 0x%08x\n"
410 "IB PACKET = 0x%08x 0x%08x\n", data
, ibpk
[0], ibpk
[1]);
415 NV_INFO(dev
, "unknown PFIFO INTR: 0x%08x\n", status
);
416 /* disable interrupts */
417 nv_wr32(dev
, 0x2140, nv_rd32(dev
, 0x2140) & ~status
);
421 uint64_t nvc0_fifo_ctrl_offs(struct drm_device
*dev
, int cid
)
423 struct drm_nouveau_private
*dev_priv
= dev
->dev_private
;
424 struct nvc0_fifo_engine
*fifo
= nvc0_fifo(dev_priv
->fifo
);
425 return fifo
->ctrl_bo
->map1
->start
+ cid
* 0x1000;
429 static volatile uint32_t *nvc0_fifo_ctrl_ptr(struct drm_device
*dev
, struct pscnv_chan
*chan
)
431 struct drm_nouveau_private
*dev_priv
= dev
->dev_private
;
432 struct nvc0_fifo_engine
*fifo
= nvc0_fifo(dev_priv
->fifo
);
433 return &fifo
->fifo_ctl
[chan
->cid
* 0x1000 / 4];