2 * Copyright (C) 2006 Ben Skeggs.
6 * Permission is hereby granted, free of charge, to any person obtaining
7 * a copy of this software and associated documentation files (the
8 * "Software"), to deal in the Software without restriction, including
9 * without limitation the rights to use, copy, modify, merge, publish,
10 * distribute, sublicense, and/or sell copies of the Software, and to
11 * permit persons to whom the Software is furnished to do so, subject to
12 * the following conditions:
14 * The above copyright notice and this permission notice (including the
15 * next paragraph) shall be included in all copies or substantial
16 * portions of the Software.
18 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
19 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
20 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
21 * IN NO EVENT SHALL THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE
22 * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
23 * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
24 * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
30 * Ben Skeggs <darktama@iinet.net.au>
35 #include "nouveau_drm.h"
36 #include "nouveau_drv.h"
37 #include "nouveau_reg.h"
38 #include <linux/ratelimit.h>
40 /* needed for hotplug irq */
41 #include "nouveau_connector.h"
42 #include "nv50_display.h"
45 nouveau_irq_preinstall(struct drm_device
*dev
)
47 struct drm_nouveau_private
*dev_priv
= dev
->dev_private
;
50 nv_wr32(dev
, NV03_PMC_INTR_EN_0
, 0);
52 if (dev_priv
->card_type
== NV_50
) {
53 INIT_WORK(&dev_priv
->irq_work
, nv50_display_irq_handler_bh
);
54 INIT_LIST_HEAD(&dev_priv
->vbl_waiting
);
59 nouveau_irq_postinstall(struct drm_device
*dev
)
62 nv_wr32(dev
, NV03_PMC_INTR_EN_0
, NV_PMC_INTR_EN_0_MASTER_ENABLE
);
67 nouveau_irq_uninstall(struct drm_device
*dev
)
70 nv_wr32(dev
, NV03_PMC_INTR_EN_0
, 0);
74 nouveau_call_method(struct nouveau_channel
*chan
, int class, int mthd
, int data
)
76 struct drm_nouveau_private
*dev_priv
= chan
->dev
->dev_private
;
77 struct nouveau_pgraph_object_method
*grm
;
78 struct nouveau_pgraph_object_class
*grc
;
80 grc
= dev_priv
->engine
.graph
.grclass
;
87 if (grc
->id
!= class || !grc
->methods
)
93 return grm
->exec(chan
, class, mthd
, data
);
101 nouveau_fifo_swmthd(struct nouveau_channel
*chan
, uint32_t addr
, uint32_t data
)
103 struct drm_device
*dev
= chan
->dev
;
104 const int subc
= (addr
>> 13) & 0x7;
105 const int mthd
= addr
& 0x1ffc;
107 if (mthd
== 0x0000) {
108 struct nouveau_gpuobj_ref
*ref
= NULL
;
110 if (nouveau_gpuobj_ref_find(chan
, data
, &ref
))
113 if (ref
->gpuobj
->engine
!= NVOBJ_ENGINE_SW
)
116 chan
->sw_subchannel
[subc
] = ref
->gpuobj
->class;
117 nv_wr32(dev
, NV04_PFIFO_CACHE1_ENGINE
, nv_rd32(dev
,
118 NV04_PFIFO_CACHE1_ENGINE
) & ~(0xf << subc
* 4));
123 if (nv_rd32(dev
, NV04_PFIFO_CACHE1_ENGINE
) & (1 << (subc
*4)))
126 if (nouveau_call_method(chan
, chan
->sw_subchannel
[subc
], mthd
, data
))
133 nouveau_fifo_irq_handler(struct drm_device
*dev
)
135 struct drm_nouveau_private
*dev_priv
= dev
->dev_private
;
136 struct nouveau_engine
*engine
= &dev_priv
->engine
;
137 uint32_t status
, reassign
;
140 reassign
= nv_rd32(dev
, NV03_PFIFO_CACHES
) & 1;
141 while ((status
= nv_rd32(dev
, NV03_PFIFO_INTR_0
)) && (cnt
++ < 100)) {
142 struct nouveau_channel
*chan
= NULL
;
145 nv_wr32(dev
, NV03_PFIFO_CACHES
, 0);
147 chid
= engine
->fifo
.channel_id(dev
);
148 if (chid
>= 0 && chid
< engine
->fifo
.channels
)
149 chan
= dev_priv
->fifos
[chid
];
150 get
= nv_rd32(dev
, NV03_PFIFO_CACHE1_GET
);
152 if (status
& NV_PFIFO_INTR_CACHE_ERROR
) {
156 /* NV_PFIFO_CACHE1_GET actually goes to 0xffc before
157 * wrapping on my G80 chips, but CACHE1 isn't big
158 * enough for this much data.. Tests show that it
159 * wraps around to the start at GET=0x800.. No clue
162 ptr
= (get
& 0x7ff) >> 2;
164 if (dev_priv
->card_type
< NV_40
) {
166 NV04_PFIFO_CACHE1_METHOD(ptr
));
168 NV04_PFIFO_CACHE1_DATA(ptr
));
171 NV40_PFIFO_CACHE1_METHOD(ptr
));
173 NV40_PFIFO_CACHE1_DATA(ptr
));
176 if (!chan
|| !nouveau_fifo_swmthd(chan
, mthd
, data
)) {
177 NV_INFO(dev
, "PFIFO_CACHE_ERROR - Ch %d/%d "
178 "Mthd 0x%04x Data 0x%08x\n",
179 chid
, (mthd
>> 13) & 7, mthd
& 0x1ffc,
183 nv_wr32(dev
, NV04_PFIFO_CACHE1_DMA_PUSH
, 0);
184 nv_wr32(dev
, NV03_PFIFO_INTR_0
,
185 NV_PFIFO_INTR_CACHE_ERROR
);
187 nv_wr32(dev
, NV03_PFIFO_CACHE1_PUSH0
,
188 nv_rd32(dev
, NV03_PFIFO_CACHE1_PUSH0
) & ~1);
189 nv_wr32(dev
, NV03_PFIFO_CACHE1_GET
, get
+ 4);
190 nv_wr32(dev
, NV03_PFIFO_CACHE1_PUSH0
,
191 nv_rd32(dev
, NV03_PFIFO_CACHE1_PUSH0
) | 1);
192 nv_wr32(dev
, NV04_PFIFO_CACHE1_HASH
, 0);
194 nv_wr32(dev
, NV04_PFIFO_CACHE1_DMA_PUSH
,
195 nv_rd32(dev
, NV04_PFIFO_CACHE1_DMA_PUSH
) | 1);
196 nv_wr32(dev
, NV04_PFIFO_CACHE1_PULL0
, 1);
198 status
&= ~NV_PFIFO_INTR_CACHE_ERROR
;
201 if (status
& NV_PFIFO_INTR_DMA_PUSHER
) {
202 NV_INFO(dev
, "PFIFO_DMA_PUSHER - Ch %d\n", chid
);
204 status
&= ~NV_PFIFO_INTR_DMA_PUSHER
;
205 nv_wr32(dev
, NV03_PFIFO_INTR_0
,
206 NV_PFIFO_INTR_DMA_PUSHER
);
208 nv_wr32(dev
, NV04_PFIFO_CACHE1_DMA_STATE
, 0x00000000);
209 if (nv_rd32(dev
, NV04_PFIFO_CACHE1_DMA_PUT
) != get
)
210 nv_wr32(dev
, NV04_PFIFO_CACHE1_DMA_GET
,
214 if (status
& NV_PFIFO_INTR_SEMAPHORE
) {
217 status
&= ~NV_PFIFO_INTR_SEMAPHORE
;
218 nv_wr32(dev
, NV03_PFIFO_INTR_0
,
219 NV_PFIFO_INTR_SEMAPHORE
);
221 sem
= nv_rd32(dev
, NV10_PFIFO_CACHE1_SEMAPHORE
);
222 nv_wr32(dev
, NV10_PFIFO_CACHE1_SEMAPHORE
, sem
| 0x1);
224 nv_wr32(dev
, NV03_PFIFO_CACHE1_GET
, get
+ 4);
225 nv_wr32(dev
, NV04_PFIFO_CACHE1_PULL0
, 1);
229 NV_INFO(dev
, "PFIFO_INTR 0x%08x - Ch %d\n",
231 nv_wr32(dev
, NV03_PFIFO_INTR_0
, status
);
235 nv_wr32(dev
, NV03_PFIFO_CACHES
, reassign
);
239 NV_INFO(dev
, "PFIFO still angry after %d spins, halt\n", cnt
);
240 nv_wr32(dev
, 0x2140, 0);
241 nv_wr32(dev
, 0x140, 0);
244 nv_wr32(dev
, NV03_PMC_INTR_0
, NV_PMC_INTR_0_PFIFO_PENDING
);
247 struct nouveau_bitfield_names
{
252 static struct nouveau_bitfield_names nstatus_names
[] =
254 { NV04_PGRAPH_NSTATUS_STATE_IN_USE
, "STATE_IN_USE" },
255 { NV04_PGRAPH_NSTATUS_INVALID_STATE
, "INVALID_STATE" },
256 { NV04_PGRAPH_NSTATUS_BAD_ARGUMENT
, "BAD_ARGUMENT" },
257 { NV04_PGRAPH_NSTATUS_PROTECTION_FAULT
, "PROTECTION_FAULT" }
260 static struct nouveau_bitfield_names nstatus_names_nv10
[] =
262 { NV10_PGRAPH_NSTATUS_STATE_IN_USE
, "STATE_IN_USE" },
263 { NV10_PGRAPH_NSTATUS_INVALID_STATE
, "INVALID_STATE" },
264 { NV10_PGRAPH_NSTATUS_BAD_ARGUMENT
, "BAD_ARGUMENT" },
265 { NV10_PGRAPH_NSTATUS_PROTECTION_FAULT
, "PROTECTION_FAULT" }
268 static struct nouveau_bitfield_names nsource_names
[] =
270 { NV03_PGRAPH_NSOURCE_NOTIFICATION
, "NOTIFICATION" },
271 { NV03_PGRAPH_NSOURCE_DATA_ERROR
, "DATA_ERROR" },
272 { NV03_PGRAPH_NSOURCE_PROTECTION_ERROR
, "PROTECTION_ERROR" },
273 { NV03_PGRAPH_NSOURCE_RANGE_EXCEPTION
, "RANGE_EXCEPTION" },
274 { NV03_PGRAPH_NSOURCE_LIMIT_COLOR
, "LIMIT_COLOR" },
275 { NV03_PGRAPH_NSOURCE_LIMIT_ZETA
, "LIMIT_ZETA" },
276 { NV03_PGRAPH_NSOURCE_ILLEGAL_MTHD
, "ILLEGAL_MTHD" },
277 { NV03_PGRAPH_NSOURCE_DMA_R_PROTECTION
, "DMA_R_PROTECTION" },
278 { NV03_PGRAPH_NSOURCE_DMA_W_PROTECTION
, "DMA_W_PROTECTION" },
279 { NV03_PGRAPH_NSOURCE_FORMAT_EXCEPTION
, "FORMAT_EXCEPTION" },
280 { NV03_PGRAPH_NSOURCE_PATCH_EXCEPTION
, "PATCH_EXCEPTION" },
281 { NV03_PGRAPH_NSOURCE_STATE_INVALID
, "STATE_INVALID" },
282 { NV03_PGRAPH_NSOURCE_DOUBLE_NOTIFY
, "DOUBLE_NOTIFY" },
283 { NV03_PGRAPH_NSOURCE_NOTIFY_IN_USE
, "NOTIFY_IN_USE" },
284 { NV03_PGRAPH_NSOURCE_METHOD_CNT
, "METHOD_CNT" },
285 { NV03_PGRAPH_NSOURCE_BFR_NOTIFICATION
, "BFR_NOTIFICATION" },
286 { NV03_PGRAPH_NSOURCE_DMA_VTX_PROTECTION
, "DMA_VTX_PROTECTION" },
287 { NV03_PGRAPH_NSOURCE_DMA_WIDTH_A
, "DMA_WIDTH_A" },
288 { NV03_PGRAPH_NSOURCE_DMA_WIDTH_B
, "DMA_WIDTH_B" },
292 nouveau_print_bitfield_names_(uint32_t value
,
293 const struct nouveau_bitfield_names
*namelist
,
294 const int namelist_len
)
297 * Caller must have already printed the KERN_* log level for us.
298 * Also the caller is responsible for adding the newline.
301 for (i
= 0; i
< namelist_len
; ++i
) {
302 uint32_t mask
= namelist
[i
].mask
;
304 printk(" %s", namelist
[i
].name
);
309 printk(" (unknown bits 0x%08x)", value
);
311 #define nouveau_print_bitfield_names(val, namelist) \
312 nouveau_print_bitfield_names_((val), (namelist), ARRAY_SIZE(namelist))
316 nouveau_graph_chid_from_grctx(struct drm_device
*dev
)
318 struct drm_nouveau_private
*dev_priv
= dev
->dev_private
;
322 if (dev_priv
->card_type
< NV_40
)
323 return dev_priv
->engine
.fifo
.channels
;
325 if (dev_priv
->card_type
< NV_50
) {
326 inst
= (nv_rd32(dev
, 0x40032c) & 0xfffff) << 4;
328 for (i
= 0; i
< dev_priv
->engine
.fifo
.channels
; i
++) {
329 struct nouveau_channel
*chan
= dev_priv
->fifos
[i
];
331 if (!chan
|| !chan
->ramin_grctx
)
334 if (inst
== chan
->ramin_grctx
->instance
)
338 inst
= (nv_rd32(dev
, 0x40032c) & 0xfffff) << 12;
340 for (i
= 0; i
< dev_priv
->engine
.fifo
.channels
; i
++) {
341 struct nouveau_channel
*chan
= dev_priv
->fifos
[i
];
343 if (!chan
|| !chan
->ramin
)
346 if (inst
== chan
->ramin
->instance
)
356 nouveau_graph_trapped_channel(struct drm_device
*dev
, int *channel_ret
)
358 struct drm_nouveau_private
*dev_priv
= dev
->dev_private
;
359 struct nouveau_engine
*engine
= &dev_priv
->engine
;
362 if (dev_priv
->card_type
< NV_10
)
363 channel
= (nv_rd32(dev
, NV04_PGRAPH_TRAPPED_ADDR
) >> 24) & 0xf;
365 if (dev_priv
->card_type
< NV_40
)
366 channel
= (nv_rd32(dev
, NV04_PGRAPH_TRAPPED_ADDR
) >> 20) & 0x1f;
368 channel
= nouveau_graph_chid_from_grctx(dev
);
370 if (channel
>= engine
->fifo
.channels
|| !dev_priv
->fifos
[channel
]) {
371 NV_ERROR(dev
, "AIII, invalid/inactive channel id %d\n", channel
);
375 *channel_ret
= channel
;
379 struct nouveau_pgraph_trap
{
382 int subc
, mthd
, size
;
383 uint32_t data
, data2
;
384 uint32_t nsource
, nstatus
;
388 nouveau_graph_trap_info(struct drm_device
*dev
,
389 struct nouveau_pgraph_trap
*trap
)
391 struct drm_nouveau_private
*dev_priv
= dev
->dev_private
;
394 trap
->nsource
= trap
->nstatus
= 0;
395 if (dev_priv
->card_type
< NV_50
) {
396 trap
->nsource
= nv_rd32(dev
, NV03_PGRAPH_NSOURCE
);
397 trap
->nstatus
= nv_rd32(dev
, NV03_PGRAPH_NSTATUS
);
400 if (nouveau_graph_trapped_channel(dev
, &trap
->channel
))
402 address
= nv_rd32(dev
, NV04_PGRAPH_TRAPPED_ADDR
);
404 trap
->mthd
= address
& 0x1FFC;
405 trap
->data
= nv_rd32(dev
, NV04_PGRAPH_TRAPPED_DATA
);
406 if (dev_priv
->card_type
< NV_10
) {
407 trap
->subc
= (address
>> 13) & 0x7;
409 trap
->subc
= (address
>> 16) & 0x7;
410 trap
->data2
= nv_rd32(dev
, NV10_PGRAPH_TRAPPED_DATA_HIGH
);
413 if (dev_priv
->card_type
< NV_10
)
414 trap
->class = nv_rd32(dev
, 0x400180 + trap
->subc
*4) & 0xFF;
415 else if (dev_priv
->card_type
< NV_40
)
416 trap
->class = nv_rd32(dev
, 0x400160 + trap
->subc
*4) & 0xFFF;
417 else if (dev_priv
->card_type
< NV_50
)
418 trap
->class = nv_rd32(dev
, 0x400160 + trap
->subc
*4) & 0xFFFF;
420 trap
->class = nv_rd32(dev
, 0x400814);
424 nouveau_graph_dump_trap_info(struct drm_device
*dev
, const char *id
,
425 struct nouveau_pgraph_trap
*trap
)
427 struct drm_nouveau_private
*dev_priv
= dev
->dev_private
;
428 uint32_t nsource
= trap
->nsource
, nstatus
= trap
->nstatus
;
430 NV_INFO(dev
, "%s - nSource:", id
);
431 nouveau_print_bitfield_names(nsource
, nsource_names
);
432 printk(", nStatus:");
433 if (dev_priv
->card_type
< NV_10
)
434 nouveau_print_bitfield_names(nstatus
, nstatus_names
);
436 nouveau_print_bitfield_names(nstatus
, nstatus_names_nv10
);
439 NV_INFO(dev
, "%s - Ch %d/%d Class 0x%04x Mthd 0x%04x "
440 "Data 0x%08x:0x%08x\n",
441 id
, trap
->channel
, trap
->subc
,
442 trap
->class, trap
->mthd
,
443 trap
->data2
, trap
->data
);
447 nouveau_pgraph_intr_swmthd(struct drm_device
*dev
,
448 struct nouveau_pgraph_trap
*trap
)
450 struct drm_nouveau_private
*dev_priv
= dev
->dev_private
;
452 if (trap
->channel
< 0 ||
453 trap
->channel
>= dev_priv
->engine
.fifo
.channels
||
454 !dev_priv
->fifos
[trap
->channel
])
457 return nouveau_call_method(dev_priv
->fifos
[trap
->channel
],
458 trap
->class, trap
->mthd
, trap
->data
);
462 nouveau_pgraph_intr_notify(struct drm_device
*dev
, uint32_t nsource
)
464 struct nouveau_pgraph_trap trap
;
467 nouveau_graph_trap_info(dev
, &trap
);
469 if (nsource
& NV03_PGRAPH_NSOURCE_ILLEGAL_MTHD
) {
470 if (nouveau_pgraph_intr_swmthd(dev
, &trap
))
477 nouveau_graph_dump_trap_info(dev
, "PGRAPH_NOTIFY", &trap
);
480 static DEFINE_RATELIMIT_STATE(nouveau_ratelimit_state
, 3 * HZ
, 20);
482 static int nouveau_ratelimit(void)
484 return __ratelimit(&nouveau_ratelimit_state
);
489 nouveau_pgraph_intr_error(struct drm_device
*dev
, uint32_t nsource
)
491 struct nouveau_pgraph_trap trap
;
494 nouveau_graph_trap_info(dev
, &trap
);
495 trap
.nsource
= nsource
;
497 if (nsource
& NV03_PGRAPH_NSOURCE_ILLEGAL_MTHD
) {
498 if (nouveau_pgraph_intr_swmthd(dev
, &trap
))
500 } else if (nsource
& NV03_PGRAPH_NSOURCE_DMA_VTX_PROTECTION
) {
501 uint32_t v
= nv_rd32(dev
, 0x402000);
502 nv_wr32(dev
, 0x402000, v
);
504 /* dump the error anyway for now: it's useful for
505 Gallium development */
511 if (unhandled
&& nouveau_ratelimit())
512 nouveau_graph_dump_trap_info(dev
, "PGRAPH_ERROR", &trap
);
516 nouveau_pgraph_intr_context_switch(struct drm_device
*dev
)
518 struct drm_nouveau_private
*dev_priv
= dev
->dev_private
;
519 struct nouveau_engine
*engine
= &dev_priv
->engine
;
522 chid
= engine
->fifo
.channel_id(dev
);
523 NV_DEBUG(dev
, "PGRAPH context switch interrupt channel %x\n", chid
);
525 switch (dev_priv
->card_type
) {
527 nv04_graph_context_switch(dev
);
530 nv10_graph_context_switch(dev
);
533 NV_ERROR(dev
, "Context switch not implemented\n");
539 nouveau_pgraph_irq_handler(struct drm_device
*dev
)
543 while ((status
= nv_rd32(dev
, NV03_PGRAPH_INTR
))) {
544 uint32_t nsource
= nv_rd32(dev
, NV03_PGRAPH_NSOURCE
);
546 if (status
& NV_PGRAPH_INTR_NOTIFY
) {
547 nouveau_pgraph_intr_notify(dev
, nsource
);
549 status
&= ~NV_PGRAPH_INTR_NOTIFY
;
550 nv_wr32(dev
, NV03_PGRAPH_INTR
, NV_PGRAPH_INTR_NOTIFY
);
553 if (status
& NV_PGRAPH_INTR_ERROR
) {
554 nouveau_pgraph_intr_error(dev
, nsource
);
556 status
&= ~NV_PGRAPH_INTR_ERROR
;
557 nv_wr32(dev
, NV03_PGRAPH_INTR
, NV_PGRAPH_INTR_ERROR
);
560 if (status
& NV_PGRAPH_INTR_CONTEXT_SWITCH
) {
561 nouveau_pgraph_intr_context_switch(dev
);
563 status
&= ~NV_PGRAPH_INTR_CONTEXT_SWITCH
;
564 nv_wr32(dev
, NV03_PGRAPH_INTR
,
565 NV_PGRAPH_INTR_CONTEXT_SWITCH
);
569 NV_INFO(dev
, "Unhandled PGRAPH_INTR - 0x%08x\n", status
);
570 nv_wr32(dev
, NV03_PGRAPH_INTR
, status
);
573 if ((nv_rd32(dev
, NV04_PGRAPH_FIFO
) & (1 << 0)) == 0)
574 nv_wr32(dev
, NV04_PGRAPH_FIFO
, 1);
577 nv_wr32(dev
, NV03_PMC_INTR_0
, NV_PMC_INTR_0_PGRAPH_PENDING
);
581 nv50_pgraph_irq_handler(struct drm_device
*dev
)
585 while ((status
= nv_rd32(dev
, NV03_PGRAPH_INTR
))) {
586 uint32_t nsource
= nv_rd32(dev
, NV03_PGRAPH_NSOURCE
);
588 if (status
& 0x00000001) {
589 nouveau_pgraph_intr_notify(dev
, nsource
);
590 status
&= ~0x00000001;
591 nv_wr32(dev
, NV03_PGRAPH_INTR
, 0x00000001);
594 if (status
& 0x00000010) {
595 nouveau_pgraph_intr_error(dev
, nsource
|
596 NV03_PGRAPH_NSOURCE_ILLEGAL_MTHD
);
598 status
&= ~0x00000010;
599 nv_wr32(dev
, NV03_PGRAPH_INTR
, 0x00000010);
602 if (status
& 0x00001000) {
603 nv_wr32(dev
, 0x400500, 0x00000000);
604 nv_wr32(dev
, NV03_PGRAPH_INTR
,
605 NV_PGRAPH_INTR_CONTEXT_SWITCH
);
606 nv_wr32(dev
, NV40_PGRAPH_INTR_EN
, nv_rd32(dev
,
607 NV40_PGRAPH_INTR_EN
) &
608 ~NV_PGRAPH_INTR_CONTEXT_SWITCH
);
609 nv_wr32(dev
, 0x400500, 0x00010001);
611 nv50_graph_context_switch(dev
);
613 status
&= ~NV_PGRAPH_INTR_CONTEXT_SWITCH
;
616 if (status
& 0x00100000) {
617 nouveau_pgraph_intr_error(dev
, nsource
|
618 NV03_PGRAPH_NSOURCE_DATA_ERROR
);
620 status
&= ~0x00100000;
621 nv_wr32(dev
, NV03_PGRAPH_INTR
, 0x00100000);
624 if (status
& 0x00200000) {
627 nouveau_pgraph_intr_error(dev
, nsource
|
628 NV03_PGRAPH_NSOURCE_PROTECTION_ERROR
);
630 NV_ERROR(dev
, "magic set 1:\n");
631 for (r
= 0x408900; r
<= 0x408910; r
+= 4)
632 NV_ERROR(dev
, "\t0x%08x: 0x%08x\n", r
,
634 nv_wr32(dev
, 0x408900,
635 nv_rd32(dev
, 0x408904) | 0xc0000000);
636 for (r
= 0x408e08; r
<= 0x408e24; r
+= 4)
637 NV_ERROR(dev
, "\t0x%08x: 0x%08x\n", r
,
639 nv_wr32(dev
, 0x408e08,
640 nv_rd32(dev
, 0x408e08) | 0xc0000000);
642 NV_ERROR(dev
, "magic set 2:\n");
643 for (r
= 0x409900; r
<= 0x409910; r
+= 4)
644 NV_ERROR(dev
, "\t0x%08x: 0x%08x\n", r
,
646 nv_wr32(dev
, 0x409900,
647 nv_rd32(dev
, 0x409904) | 0xc0000000);
648 for (r
= 0x409e08; r
<= 0x409e24; r
+= 4)
649 NV_ERROR(dev
, "\t0x%08x: 0x%08x\n", r
,
651 nv_wr32(dev
, 0x409e08,
652 nv_rd32(dev
, 0x409e08) | 0xc0000000);
654 status
&= ~0x00200000;
655 nv_wr32(dev
, NV03_PGRAPH_NSOURCE
, nsource
);
656 nv_wr32(dev
, NV03_PGRAPH_INTR
, 0x00200000);
660 NV_INFO(dev
, "Unhandled PGRAPH_INTR - 0x%08x\n",
662 nv_wr32(dev
, NV03_PGRAPH_INTR
, status
);
666 const int isb
= (1 << 16) | (1 << 0);
668 if ((nv_rd32(dev
, 0x400500) & isb
) != isb
)
669 nv_wr32(dev
, 0x400500,
670 nv_rd32(dev
, 0x400500) | isb
);
674 nv_wr32(dev
, NV03_PMC_INTR_0
, NV_PMC_INTR_0_PGRAPH_PENDING
);
675 nv_wr32(dev
, 0x400824, nv_rd32(dev
, 0x400824) & ~(1 << 31));
679 nouveau_crtc_irq_handler(struct drm_device
*dev
, int crtc
)
682 nv_wr32(dev
, NV_CRTC0_INTSTAT
, NV_CRTC_INTR_VBLANK
);
685 nv_wr32(dev
, NV_CRTC1_INTSTAT
, NV_CRTC_INTR_VBLANK
);
689 nouveau_irq_handler(DRM_IRQ_ARGS
)
691 struct drm_device
*dev
= (struct drm_device
*)arg
;
692 struct drm_nouveau_private
*dev_priv
= dev
->dev_private
;
693 uint32_t status
, fbdev_flags
= 0;
695 status
= nv_rd32(dev
, NV03_PMC_INTR_0
);
699 if (dev_priv
->fbdev_info
) {
700 fbdev_flags
= dev_priv
->fbdev_info
->flags
;
701 dev_priv
->fbdev_info
->flags
|= FBINFO_HWACCEL_DISABLED
;
704 if (status
& NV_PMC_INTR_0_PFIFO_PENDING
) {
705 nouveau_fifo_irq_handler(dev
);
706 status
&= ~NV_PMC_INTR_0_PFIFO_PENDING
;
709 if (status
& NV_PMC_INTR_0_PGRAPH_PENDING
) {
710 if (dev_priv
->card_type
>= NV_50
)
711 nv50_pgraph_irq_handler(dev
);
713 nouveau_pgraph_irq_handler(dev
);
715 status
&= ~NV_PMC_INTR_0_PGRAPH_PENDING
;
718 if (status
& NV_PMC_INTR_0_CRTCn_PENDING
) {
719 nouveau_crtc_irq_handler(dev
, (status
>>24)&3);
720 status
&= ~NV_PMC_INTR_0_CRTCn_PENDING
;
723 if (status
& (NV_PMC_INTR_0_NV50_DISPLAY_PENDING
|
724 NV_PMC_INTR_0_NV50_I2C_PENDING
)) {
725 nv50_display_irq_handler(dev
);
726 status
&= ~(NV_PMC_INTR_0_NV50_DISPLAY_PENDING
|
727 NV_PMC_INTR_0_NV50_I2C_PENDING
);
731 NV_ERROR(dev
, "Unhandled PMC INTR status bits 0x%08x\n", status
);
733 if (dev_priv
->fbdev_info
)
734 dev_priv
->fbdev_info
->flags
= fbdev_flags
;