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
,
215 NV_INFO(dev
, "PFIFO_INTR 0x%08x - Ch %d\n",
217 nv_wr32(dev
, NV03_PFIFO_INTR_0
, status
);
221 nv_wr32(dev
, NV03_PFIFO_CACHES
, reassign
);
225 NV_INFO(dev
, "PFIFO still angry after %d spins, halt\n", cnt
);
226 nv_wr32(dev
, 0x2140, 0);
227 nv_wr32(dev
, 0x140, 0);
230 nv_wr32(dev
, NV03_PMC_INTR_0
, NV_PMC_INTR_0_PFIFO_PENDING
);
233 struct nouveau_bitfield_names
{
238 static struct nouveau_bitfield_names nstatus_names
[] =
240 { NV04_PGRAPH_NSTATUS_STATE_IN_USE
, "STATE_IN_USE" },
241 { NV04_PGRAPH_NSTATUS_INVALID_STATE
, "INVALID_STATE" },
242 { NV04_PGRAPH_NSTATUS_BAD_ARGUMENT
, "BAD_ARGUMENT" },
243 { NV04_PGRAPH_NSTATUS_PROTECTION_FAULT
, "PROTECTION_FAULT" }
246 static struct nouveau_bitfield_names nstatus_names_nv10
[] =
248 { NV10_PGRAPH_NSTATUS_STATE_IN_USE
, "STATE_IN_USE" },
249 { NV10_PGRAPH_NSTATUS_INVALID_STATE
, "INVALID_STATE" },
250 { NV10_PGRAPH_NSTATUS_BAD_ARGUMENT
, "BAD_ARGUMENT" },
251 { NV10_PGRAPH_NSTATUS_PROTECTION_FAULT
, "PROTECTION_FAULT" }
254 static struct nouveau_bitfield_names nsource_names
[] =
256 { NV03_PGRAPH_NSOURCE_NOTIFICATION
, "NOTIFICATION" },
257 { NV03_PGRAPH_NSOURCE_DATA_ERROR
, "DATA_ERROR" },
258 { NV03_PGRAPH_NSOURCE_PROTECTION_ERROR
, "PROTECTION_ERROR" },
259 { NV03_PGRAPH_NSOURCE_RANGE_EXCEPTION
, "RANGE_EXCEPTION" },
260 { NV03_PGRAPH_NSOURCE_LIMIT_COLOR
, "LIMIT_COLOR" },
261 { NV03_PGRAPH_NSOURCE_LIMIT_ZETA
, "LIMIT_ZETA" },
262 { NV03_PGRAPH_NSOURCE_ILLEGAL_MTHD
, "ILLEGAL_MTHD" },
263 { NV03_PGRAPH_NSOURCE_DMA_R_PROTECTION
, "DMA_R_PROTECTION" },
264 { NV03_PGRAPH_NSOURCE_DMA_W_PROTECTION
, "DMA_W_PROTECTION" },
265 { NV03_PGRAPH_NSOURCE_FORMAT_EXCEPTION
, "FORMAT_EXCEPTION" },
266 { NV03_PGRAPH_NSOURCE_PATCH_EXCEPTION
, "PATCH_EXCEPTION" },
267 { NV03_PGRAPH_NSOURCE_STATE_INVALID
, "STATE_INVALID" },
268 { NV03_PGRAPH_NSOURCE_DOUBLE_NOTIFY
, "DOUBLE_NOTIFY" },
269 { NV03_PGRAPH_NSOURCE_NOTIFY_IN_USE
, "NOTIFY_IN_USE" },
270 { NV03_PGRAPH_NSOURCE_METHOD_CNT
, "METHOD_CNT" },
271 { NV03_PGRAPH_NSOURCE_BFR_NOTIFICATION
, "BFR_NOTIFICATION" },
272 { NV03_PGRAPH_NSOURCE_DMA_VTX_PROTECTION
, "DMA_VTX_PROTECTION" },
273 { NV03_PGRAPH_NSOURCE_DMA_WIDTH_A
, "DMA_WIDTH_A" },
274 { NV03_PGRAPH_NSOURCE_DMA_WIDTH_B
, "DMA_WIDTH_B" },
278 nouveau_print_bitfield_names_(uint32_t value
,
279 const struct nouveau_bitfield_names
*namelist
,
280 const int namelist_len
)
283 * Caller must have already printed the KERN_* log level for us.
284 * Also the caller is responsible for adding the newline.
287 for (i
= 0; i
< namelist_len
; ++i
) {
288 uint32_t mask
= namelist
[i
].mask
;
290 printk(" %s", namelist
[i
].name
);
295 printk(" (unknown bits 0x%08x)", value
);
297 #define nouveau_print_bitfield_names(val, namelist) \
298 nouveau_print_bitfield_names_((val), (namelist), ARRAY_SIZE(namelist))
302 nouveau_graph_chid_from_grctx(struct drm_device
*dev
)
304 struct drm_nouveau_private
*dev_priv
= dev
->dev_private
;
308 if (dev_priv
->card_type
< NV_40
)
309 return dev_priv
->engine
.fifo
.channels
;
311 if (dev_priv
->card_type
< NV_50
) {
312 inst
= (nv_rd32(dev
, 0x40032c) & 0xfffff) << 4;
314 for (i
= 0; i
< dev_priv
->engine
.fifo
.channels
; i
++) {
315 struct nouveau_channel
*chan
= dev_priv
->fifos
[i
];
317 if (!chan
|| !chan
->ramin_grctx
)
320 if (inst
== chan
->ramin_grctx
->instance
)
324 inst
= (nv_rd32(dev
, 0x40032c) & 0xfffff) << 12;
326 for (i
= 0; i
< dev_priv
->engine
.fifo
.channels
; i
++) {
327 struct nouveau_channel
*chan
= dev_priv
->fifos
[i
];
329 if (!chan
|| !chan
->ramin
)
332 if (inst
== chan
->ramin
->instance
)
342 nouveau_graph_trapped_channel(struct drm_device
*dev
, int *channel_ret
)
344 struct drm_nouveau_private
*dev_priv
= dev
->dev_private
;
345 struct nouveau_engine
*engine
= &dev_priv
->engine
;
348 if (dev_priv
->card_type
< NV_10
)
349 channel
= (nv_rd32(dev
, NV04_PGRAPH_TRAPPED_ADDR
) >> 24) & 0xf;
351 if (dev_priv
->card_type
< NV_40
)
352 channel
= (nv_rd32(dev
, NV04_PGRAPH_TRAPPED_ADDR
) >> 20) & 0x1f;
354 channel
= nouveau_graph_chid_from_grctx(dev
);
356 if (channel
>= engine
->fifo
.channels
|| !dev_priv
->fifos
[channel
]) {
357 NV_ERROR(dev
, "AIII, invalid/inactive channel id %d\n", channel
);
361 *channel_ret
= channel
;
365 struct nouveau_pgraph_trap
{
368 int subc
, mthd
, size
;
369 uint32_t data
, data2
;
370 uint32_t nsource
, nstatus
;
374 nouveau_graph_trap_info(struct drm_device
*dev
,
375 struct nouveau_pgraph_trap
*trap
)
377 struct drm_nouveau_private
*dev_priv
= dev
->dev_private
;
380 trap
->nsource
= trap
->nstatus
= 0;
381 if (dev_priv
->card_type
< NV_50
) {
382 trap
->nsource
= nv_rd32(dev
, NV03_PGRAPH_NSOURCE
);
383 trap
->nstatus
= nv_rd32(dev
, NV03_PGRAPH_NSTATUS
);
386 if (nouveau_graph_trapped_channel(dev
, &trap
->channel
))
388 address
= nv_rd32(dev
, NV04_PGRAPH_TRAPPED_ADDR
);
390 trap
->mthd
= address
& 0x1FFC;
391 trap
->data
= nv_rd32(dev
, NV04_PGRAPH_TRAPPED_DATA
);
392 if (dev_priv
->card_type
< NV_10
) {
393 trap
->subc
= (address
>> 13) & 0x7;
395 trap
->subc
= (address
>> 16) & 0x7;
396 trap
->data2
= nv_rd32(dev
, NV10_PGRAPH_TRAPPED_DATA_HIGH
);
399 if (dev_priv
->card_type
< NV_10
)
400 trap
->class = nv_rd32(dev
, 0x400180 + trap
->subc
*4) & 0xFF;
401 else if (dev_priv
->card_type
< NV_40
)
402 trap
->class = nv_rd32(dev
, 0x400160 + trap
->subc
*4) & 0xFFF;
403 else if (dev_priv
->card_type
< NV_50
)
404 trap
->class = nv_rd32(dev
, 0x400160 + trap
->subc
*4) & 0xFFFF;
406 trap
->class = nv_rd32(dev
, 0x400814);
410 nouveau_graph_dump_trap_info(struct drm_device
*dev
, const char *id
,
411 struct nouveau_pgraph_trap
*trap
)
413 struct drm_nouveau_private
*dev_priv
= dev
->dev_private
;
414 uint32_t nsource
= trap
->nsource
, nstatus
= trap
->nstatus
;
416 NV_INFO(dev
, "%s - nSource:", id
);
417 nouveau_print_bitfield_names(nsource
, nsource_names
);
418 printk(", nStatus:");
419 if (dev_priv
->card_type
< NV_10
)
420 nouveau_print_bitfield_names(nstatus
, nstatus_names
);
422 nouveau_print_bitfield_names(nstatus
, nstatus_names_nv10
);
425 NV_INFO(dev
, "%s - Ch %d/%d Class 0x%04x Mthd 0x%04x "
426 "Data 0x%08x:0x%08x\n",
427 id
, trap
->channel
, trap
->subc
,
428 trap
->class, trap
->mthd
,
429 trap
->data2
, trap
->data
);
433 nouveau_pgraph_intr_swmthd(struct drm_device
*dev
,
434 struct nouveau_pgraph_trap
*trap
)
436 struct drm_nouveau_private
*dev_priv
= dev
->dev_private
;
438 if (trap
->channel
< 0 ||
439 trap
->channel
>= dev_priv
->engine
.fifo
.channels
||
440 !dev_priv
->fifos
[trap
->channel
])
443 return nouveau_call_method(dev_priv
->fifos
[trap
->channel
],
444 trap
->class, trap
->mthd
, trap
->data
);
448 nouveau_pgraph_intr_notify(struct drm_device
*dev
, uint32_t nsource
)
450 struct nouveau_pgraph_trap trap
;
453 nouveau_graph_trap_info(dev
, &trap
);
455 if (nsource
& NV03_PGRAPH_NSOURCE_ILLEGAL_MTHD
) {
456 if (nouveau_pgraph_intr_swmthd(dev
, &trap
))
463 nouveau_graph_dump_trap_info(dev
, "PGRAPH_NOTIFY", &trap
);
466 static DEFINE_RATELIMIT_STATE(nouveau_ratelimit_state
, 3 * HZ
, 20);
468 static int nouveau_ratelimit(void)
470 return __ratelimit(&nouveau_ratelimit_state
);
475 nouveau_pgraph_intr_error(struct drm_device
*dev
, uint32_t nsource
)
477 struct nouveau_pgraph_trap trap
;
480 nouveau_graph_trap_info(dev
, &trap
);
481 trap
.nsource
= nsource
;
483 if (nsource
& NV03_PGRAPH_NSOURCE_ILLEGAL_MTHD
) {
484 if (nouveau_pgraph_intr_swmthd(dev
, &trap
))
486 } else if (nsource
& NV03_PGRAPH_NSOURCE_DMA_VTX_PROTECTION
) {
487 uint32_t v
= nv_rd32(dev
, 0x402000);
488 nv_wr32(dev
, 0x402000, v
);
490 /* dump the error anyway for now: it's useful for
491 Gallium development */
497 if (unhandled
&& nouveau_ratelimit())
498 nouveau_graph_dump_trap_info(dev
, "PGRAPH_ERROR", &trap
);
502 nouveau_pgraph_intr_context_switch(struct drm_device
*dev
)
504 struct drm_nouveau_private
*dev_priv
= dev
->dev_private
;
505 struct nouveau_engine
*engine
= &dev_priv
->engine
;
508 chid
= engine
->fifo
.channel_id(dev
);
509 NV_DEBUG(dev
, "PGRAPH context switch interrupt channel %x\n", chid
);
511 switch (dev_priv
->card_type
) {
513 nv04_graph_context_switch(dev
);
516 nv10_graph_context_switch(dev
);
519 NV_ERROR(dev
, "Context switch not implemented\n");
525 nouveau_pgraph_irq_handler(struct drm_device
*dev
)
529 while ((status
= nv_rd32(dev
, NV03_PGRAPH_INTR
))) {
530 uint32_t nsource
= nv_rd32(dev
, NV03_PGRAPH_NSOURCE
);
532 if (status
& NV_PGRAPH_INTR_NOTIFY
) {
533 nouveau_pgraph_intr_notify(dev
, nsource
);
535 status
&= ~NV_PGRAPH_INTR_NOTIFY
;
536 nv_wr32(dev
, NV03_PGRAPH_INTR
, NV_PGRAPH_INTR_NOTIFY
);
539 if (status
& NV_PGRAPH_INTR_ERROR
) {
540 nouveau_pgraph_intr_error(dev
, nsource
);
542 status
&= ~NV_PGRAPH_INTR_ERROR
;
543 nv_wr32(dev
, NV03_PGRAPH_INTR
, NV_PGRAPH_INTR_ERROR
);
546 if (status
& NV_PGRAPH_INTR_CONTEXT_SWITCH
) {
547 nouveau_pgraph_intr_context_switch(dev
);
549 status
&= ~NV_PGRAPH_INTR_CONTEXT_SWITCH
;
550 nv_wr32(dev
, NV03_PGRAPH_INTR
,
551 NV_PGRAPH_INTR_CONTEXT_SWITCH
);
555 NV_INFO(dev
, "Unhandled PGRAPH_INTR - 0x%08x\n", status
);
556 nv_wr32(dev
, NV03_PGRAPH_INTR
, status
);
559 if ((nv_rd32(dev
, NV04_PGRAPH_FIFO
) & (1 << 0)) == 0)
560 nv_wr32(dev
, NV04_PGRAPH_FIFO
, 1);
563 nv_wr32(dev
, NV03_PMC_INTR_0
, NV_PMC_INTR_0_PGRAPH_PENDING
);
567 nv50_pgraph_irq_handler(struct drm_device
*dev
)
569 uint32_t status
, nsource
;
571 status
= nv_rd32(dev
, NV03_PGRAPH_INTR
);
572 nsource
= nv_rd32(dev
, NV03_PGRAPH_NSOURCE
);
574 if (status
& 0x00000001) {
575 nouveau_pgraph_intr_notify(dev
, nsource
);
576 status
&= ~0x00000001;
577 nv_wr32(dev
, NV03_PGRAPH_INTR
, 0x00000001);
580 if (status
& 0x00000010) {
581 nouveau_pgraph_intr_error(dev
, nsource
|
582 NV03_PGRAPH_NSOURCE_ILLEGAL_MTHD
);
584 status
&= ~0x00000010;
585 nv_wr32(dev
, NV03_PGRAPH_INTR
, 0x00000010);
588 if (status
& 0x00001000) {
589 nv_wr32(dev
, 0x400500, 0x00000000);
590 nv_wr32(dev
, NV03_PGRAPH_INTR
, NV_PGRAPH_INTR_CONTEXT_SWITCH
);
591 nv_wr32(dev
, NV40_PGRAPH_INTR_EN
, nv_rd32(dev
,
592 NV40_PGRAPH_INTR_EN
) & ~NV_PGRAPH_INTR_CONTEXT_SWITCH
);
593 nv_wr32(dev
, 0x400500, 0x00010001);
595 nv50_graph_context_switch(dev
);
597 status
&= ~NV_PGRAPH_INTR_CONTEXT_SWITCH
;
600 if (status
& 0x00100000) {
601 nouveau_pgraph_intr_error(dev
, nsource
|
602 NV03_PGRAPH_NSOURCE_DATA_ERROR
);
604 status
&= ~0x00100000;
605 nv_wr32(dev
, NV03_PGRAPH_INTR
, 0x00100000);
608 if (status
& 0x00200000) {
611 nouveau_pgraph_intr_error(dev
, nsource
|
612 NV03_PGRAPH_NSOURCE_PROTECTION_ERROR
);
614 NV_ERROR(dev
, "magic set 1:\n");
615 for (r
= 0x408900; r
<= 0x408910; r
+= 4)
616 NV_ERROR(dev
, "\t0x%08x: 0x%08x\n", r
, nv_rd32(dev
, r
));
617 nv_wr32(dev
, 0x408900, nv_rd32(dev
, 0x408904) | 0xc0000000);
618 for (r
= 0x408e08; r
<= 0x408e24; r
+= 4)
619 NV_ERROR(dev
, "\t0x%08x: 0x%08x\n", r
, nv_rd32(dev
, r
));
620 nv_wr32(dev
, 0x408e08, nv_rd32(dev
, 0x408e08) | 0xc0000000);
622 NV_ERROR(dev
, "magic set 2:\n");
623 for (r
= 0x409900; r
<= 0x409910; r
+= 4)
624 NV_ERROR(dev
, "\t0x%08x: 0x%08x\n", r
, nv_rd32(dev
, r
));
625 nv_wr32(dev
, 0x409900, nv_rd32(dev
, 0x409904) | 0xc0000000);
626 for (r
= 0x409e08; r
<= 0x409e24; r
+= 4)
627 NV_ERROR(dev
, "\t0x%08x: 0x%08x\n", r
, nv_rd32(dev
, r
));
628 nv_wr32(dev
, 0x409e08, nv_rd32(dev
, 0x409e08) | 0xc0000000);
630 status
&= ~0x00200000;
631 nv_wr32(dev
, NV03_PGRAPH_NSOURCE
, nsource
);
632 nv_wr32(dev
, NV03_PGRAPH_INTR
, 0x00200000);
636 NV_INFO(dev
, "Unhandled PGRAPH_INTR - 0x%08x\n", status
);
637 nv_wr32(dev
, NV03_PGRAPH_INTR
, status
);
641 const int isb
= (1 << 16) | (1 << 0);
643 if ((nv_rd32(dev
, 0x400500) & isb
) != isb
)
644 nv_wr32(dev
, 0x400500, nv_rd32(dev
, 0x400500) | isb
);
645 nv_wr32(dev
, 0x400824, nv_rd32(dev
, 0x400824) & ~(1 << 31));
648 nv_wr32(dev
, NV03_PMC_INTR_0
, NV_PMC_INTR_0_PGRAPH_PENDING
);
652 nouveau_crtc_irq_handler(struct drm_device
*dev
, int crtc
)
655 nv_wr32(dev
, NV_CRTC0_INTSTAT
, NV_CRTC_INTR_VBLANK
);
658 nv_wr32(dev
, NV_CRTC1_INTSTAT
, NV_CRTC_INTR_VBLANK
);
662 nouveau_irq_handler(DRM_IRQ_ARGS
)
664 struct drm_device
*dev
= (struct drm_device
*)arg
;
665 struct drm_nouveau_private
*dev_priv
= dev
->dev_private
;
666 uint32_t status
, fbdev_flags
= 0;
668 status
= nv_rd32(dev
, NV03_PMC_INTR_0
);
672 if (dev_priv
->fbdev_info
) {
673 fbdev_flags
= dev_priv
->fbdev_info
->flags
;
674 dev_priv
->fbdev_info
->flags
|= FBINFO_HWACCEL_DISABLED
;
677 if (status
& NV_PMC_INTR_0_PFIFO_PENDING
) {
678 nouveau_fifo_irq_handler(dev
);
679 status
&= ~NV_PMC_INTR_0_PFIFO_PENDING
;
682 if (status
& NV_PMC_INTR_0_PGRAPH_PENDING
) {
683 if (dev_priv
->card_type
>= NV_50
)
684 nv50_pgraph_irq_handler(dev
);
686 nouveau_pgraph_irq_handler(dev
);
688 status
&= ~NV_PMC_INTR_0_PGRAPH_PENDING
;
691 if (status
& NV_PMC_INTR_0_CRTCn_PENDING
) {
692 nouveau_crtc_irq_handler(dev
, (status
>>24)&3);
693 status
&= ~NV_PMC_INTR_0_CRTCn_PENDING
;
696 if (status
& (NV_PMC_INTR_0_NV50_DISPLAY_PENDING
|
697 NV_PMC_INTR_0_NV50_I2C_PENDING
)) {
698 nv50_display_irq_handler(dev
);
699 status
&= ~(NV_PMC_INTR_0_NV50_DISPLAY_PENDING
|
700 NV_PMC_INTR_0_NV50_I2C_PENDING
);
704 NV_ERROR(dev
, "Unhandled PMC INTR status bits 0x%08x\n", status
);
706 if (dev_priv
->fbdev_info
)
707 dev_priv
->fbdev_info
->flags
= fbdev_flags
;