OSDN Git Service

drm/bo: fix stupid lock imbalance
[android-x86/external-libdrm.git] / shared-core / nouveau_irq.c
1 /*
2  * Copyright (C) 2006 Ben Skeggs.
3  *
4  * All Rights Reserved.
5  *
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:
13  *
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.
17  *
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.
25  *
26  */
27
28 /*
29  * Authors:
30  *   Ben Skeggs <darktama@iinet.net.au>
31  */
32
33 #include "drmP.h"
34 #include "drm.h"
35 #include "nouveau_drm.h"
36 #include "nouveau_drv.h"
37 #include "nouveau_reg.h"
38 #include "nouveau_swmthd.h"
39
40 /* needed for interrupt based vpll changes */
41 #include "nv50_display.h"
42 #include "nv50_crtc.h"
43 #include "nv50_output.h"
44 /* needed for hotplug irq */
45 #include "nv50_kms_wrapper.h"
46
47 void
48 nouveau_irq_preinstall(struct drm_device *dev)
49 {
50         struct drm_nouveau_private *dev_priv = dev->dev_private;
51
52         /* Master disable */
53         NV_WRITE(NV03_PMC_INTR_EN_0, 0);
54 }
55
56 int
57 nouveau_irq_postinstall(struct drm_device *dev)
58 {
59         struct drm_nouveau_private *dev_priv = dev->dev_private;
60
61         /* Master enable */
62         NV_WRITE(NV03_PMC_INTR_EN_0, NV_PMC_INTR_EN_0_MASTER_ENABLE);
63
64         return 0;
65 }
66
67 void
68 nouveau_irq_uninstall(struct drm_device *dev)
69 {
70         struct drm_nouveau_private *dev_priv = dev->dev_private;
71
72         /* Master disable */
73         NV_WRITE(NV03_PMC_INTR_EN_0, 0);
74 }
75
76 static void
77 nouveau_fifo_irq_handler(struct drm_device *dev)
78 {
79         struct drm_nouveau_private *dev_priv = dev->dev_private;
80         struct nouveau_engine *engine = &dev_priv->Engine;
81         uint32_t status, reassign;
82
83         reassign = NV_READ(NV03_PFIFO_CACHES) & 1;
84         while ((status = NV_READ(NV03_PFIFO_INTR_0))) {
85                 uint32_t chid, get;
86
87                 NV_WRITE(NV03_PFIFO_CACHES, 0);
88
89                 chid = engine->fifo.channel_id(dev);
90                 get  = NV_READ(NV03_PFIFO_CACHE1_GET);
91
92                 if (status & NV_PFIFO_INTR_CACHE_ERROR) {
93                         uint32_t mthd, data;
94                         int ptr;
95
96                         ptr = get >> 2;
97                         if (dev_priv->card_type < NV_40) {
98                                 mthd = NV_READ(NV04_PFIFO_CACHE1_METHOD(ptr));
99                                 data = NV_READ(NV04_PFIFO_CACHE1_DATA(ptr));
100                         } else {
101                                 mthd = NV_READ(NV40_PFIFO_CACHE1_METHOD(ptr));
102                                 data = NV_READ(NV40_PFIFO_CACHE1_DATA(ptr));
103                         }
104
105                         DRM_INFO("PFIFO_CACHE_ERROR - "
106                                  "Ch %d/%d Mthd 0x%04x Data 0x%08x\n",
107                                  chid, (mthd >> 13) & 7, mthd & 0x1ffc, data);
108
109                         NV_WRITE(NV03_PFIFO_CACHE1_GET, get + 4);
110                         NV_WRITE(NV04_PFIFO_CACHE1_PULL0, 1);
111
112                         status &= ~NV_PFIFO_INTR_CACHE_ERROR;
113                         NV_WRITE(NV03_PFIFO_INTR_0, NV_PFIFO_INTR_CACHE_ERROR);
114                 }
115
116                 if (status & NV_PFIFO_INTR_DMA_PUSHER) {
117                         DRM_INFO("PFIFO_DMA_PUSHER - Ch %d\n", chid);
118
119                         status &= ~NV_PFIFO_INTR_DMA_PUSHER;
120                         NV_WRITE(NV03_PFIFO_INTR_0, NV_PFIFO_INTR_DMA_PUSHER);
121
122                         NV_WRITE(NV04_PFIFO_CACHE1_DMA_STATE, 0x00000000);
123                         if (NV_READ(NV04_PFIFO_CACHE1_DMA_PUT) != get)
124                                 NV_WRITE(NV04_PFIFO_CACHE1_DMA_GET, get + 4);
125                 }
126
127                 if (status) {
128                         DRM_INFO("Unhandled PFIFO_INTR - 0x%08x\n", status);
129                         NV_WRITE(NV03_PFIFO_INTR_0, status);
130                         NV_WRITE(NV03_PMC_INTR_EN_0, 0);
131                 }
132
133                 NV_WRITE(NV03_PFIFO_CACHES, reassign);
134         }
135
136         NV_WRITE(NV03_PMC_INTR_0, NV_PMC_INTR_0_PFIFO_PENDING);
137 }
138
139 struct nouveau_bitfield_names {
140         uint32_t mask;
141         const char * name;
142 };
143
144 static struct nouveau_bitfield_names nouveau_nstatus_names[] =
145 {
146         { NV04_PGRAPH_NSTATUS_STATE_IN_USE,       "STATE_IN_USE" },
147         { NV04_PGRAPH_NSTATUS_INVALID_STATE,      "INVALID_STATE" },
148         { NV04_PGRAPH_NSTATUS_BAD_ARGUMENT,       "BAD_ARGUMENT" },
149         { NV04_PGRAPH_NSTATUS_PROTECTION_FAULT,   "PROTECTION_FAULT" }
150 };
151
152 static struct nouveau_bitfield_names nouveau_nstatus_names_nv10[] =
153 {
154         { NV10_PGRAPH_NSTATUS_STATE_IN_USE,       "STATE_IN_USE" },
155         { NV10_PGRAPH_NSTATUS_INVALID_STATE,      "INVALID_STATE" },
156         { NV10_PGRAPH_NSTATUS_BAD_ARGUMENT,       "BAD_ARGUMENT" },
157         { NV10_PGRAPH_NSTATUS_PROTECTION_FAULT,   "PROTECTION_FAULT" }
158 };
159
160 static struct nouveau_bitfield_names nouveau_nsource_names[] =
161 {
162         { NV03_PGRAPH_NSOURCE_NOTIFICATION,       "NOTIFICATION" },
163         { NV03_PGRAPH_NSOURCE_DATA_ERROR,         "DATA_ERROR" },
164         { NV03_PGRAPH_NSOURCE_PROTECTION_ERROR,   "PROTECTION_ERROR" },
165         { NV03_PGRAPH_NSOURCE_RANGE_EXCEPTION,    "RANGE_EXCEPTION" },
166         { NV03_PGRAPH_NSOURCE_LIMIT_COLOR,        "LIMIT_COLOR" },
167         { NV03_PGRAPH_NSOURCE_LIMIT_ZETA,         "LIMIT_ZETA" },
168         { NV03_PGRAPH_NSOURCE_ILLEGAL_MTHD,       "ILLEGAL_MTHD" },
169         { NV03_PGRAPH_NSOURCE_DMA_R_PROTECTION,   "DMA_R_PROTECTION" },
170         { NV03_PGRAPH_NSOURCE_DMA_W_PROTECTION,   "DMA_W_PROTECTION" },
171         { NV03_PGRAPH_NSOURCE_FORMAT_EXCEPTION,   "FORMAT_EXCEPTION" },
172         { NV03_PGRAPH_NSOURCE_PATCH_EXCEPTION,    "PATCH_EXCEPTION" },
173         { NV03_PGRAPH_NSOURCE_STATE_INVALID,      "STATE_INVALID" },
174         { NV03_PGRAPH_NSOURCE_DOUBLE_NOTIFY,      "DOUBLE_NOTIFY" },
175         { NV03_PGRAPH_NSOURCE_NOTIFY_IN_USE,      "NOTIFY_IN_USE" },
176         { NV03_PGRAPH_NSOURCE_METHOD_CNT,         "METHOD_CNT" },
177         { NV03_PGRAPH_NSOURCE_BFR_NOTIFICATION,   "BFR_NOTIFICATION" },
178         { NV03_PGRAPH_NSOURCE_DMA_VTX_PROTECTION, "DMA_VTX_PROTECTION" },
179         { NV03_PGRAPH_NSOURCE_DMA_WIDTH_A,        "DMA_WIDTH_A" },
180         { NV03_PGRAPH_NSOURCE_DMA_WIDTH_B,        "DMA_WIDTH_B" },
181 };
182
183 static void
184 nouveau_print_bitfield_names(uint32_t value,
185                              const struct nouveau_bitfield_names *namelist,
186                              const int namelist_len)
187 {
188         int i;
189         for(i=0; i<namelist_len; ++i) {
190                 uint32_t mask = namelist[i].mask;
191                 if(value & mask) {
192                         printk(" %s", namelist[i].name);
193                         value &= ~mask;
194                 }
195         }
196         if(value)
197                 printk(" (unknown bits 0x%08x)", value);
198 }
199
200 static int
201 nouveau_graph_chid_from_grctx(struct drm_device *dev)
202 {
203         struct drm_nouveau_private *dev_priv = dev->dev_private;
204         uint32_t inst;
205         int i;
206
207         if (dev_priv->card_type < NV_40)
208                 return dev_priv->Engine.fifo.channels;
209         else
210         if (dev_priv->card_type < NV_50)
211                 inst = (NV_READ(0x40032c) & 0xfffff) << 4;
212         else
213                 inst = NV_READ(0x40032c) & 0xfffff;
214
215         for (i = 0; i < dev_priv->Engine.fifo.channels; i++) {
216                 struct nouveau_channel *chan = dev_priv->fifos[i];
217
218                 if (!chan || !chan->ramin_grctx)
219                         continue;
220
221                 if (dev_priv->card_type < NV_50) {
222                         if (inst == chan->ramin_grctx->instance)
223                                 break;
224                 } else {
225                         if (inst == INSTANCE_RD(chan->ramin_grctx->gpuobj, 0))
226                                 break;
227                 }
228         }
229
230         return i;
231 }
232
233 static int
234 nouveau_graph_trapped_channel(struct drm_device *dev, int *channel_ret)
235 {
236         struct drm_nouveau_private *dev_priv = dev->dev_private;
237         struct nouveau_engine *engine = &dev_priv->Engine;
238         int channel;
239
240         if (dev_priv->card_type < NV_10)
241                 channel = (NV_READ(NV04_PGRAPH_TRAPPED_ADDR) >> 24) & 0xf;
242         else
243         if (dev_priv->card_type < NV_40)
244                 channel = (NV_READ(NV04_PGRAPH_TRAPPED_ADDR) >> 20) & 0x1f;
245         else
246                 channel = nouveau_graph_chid_from_grctx(dev);
247
248         if (channel >= engine->fifo.channels || !dev_priv->fifos[channel]) {
249                 DRM_ERROR("AIII, invalid/inactive channel id %d\n", channel);
250                 return -EINVAL;
251         }
252
253         *channel_ret = channel;
254         return 0;
255 }
256
257 struct nouveau_pgraph_trap {
258         int channel;
259         int class;
260         int subc, mthd, size;
261         uint32_t data, data2;
262         uint32_t nsource, nstatus;
263 };
264
265 static void
266 nouveau_graph_trap_info(struct drm_device *dev,
267                         struct nouveau_pgraph_trap *trap)
268 {
269         struct drm_nouveau_private *dev_priv = dev->dev_private;
270         uint32_t address;
271
272         trap->nsource = trap->nstatus = 0;
273         if (dev_priv->card_type < NV_50) {
274                 trap->nsource = NV_READ(NV03_PGRAPH_NSOURCE);
275                 trap->nstatus = NV_READ(NV03_PGRAPH_NSTATUS);
276         }
277
278         if (nouveau_graph_trapped_channel(dev, &trap->channel))
279                 trap->channel = -1;
280         address = NV_READ(NV04_PGRAPH_TRAPPED_ADDR);
281
282         trap->mthd = address & 0x1FFC;
283         trap->data = NV_READ(NV04_PGRAPH_TRAPPED_DATA);
284         if (dev_priv->card_type < NV_10) {
285                 trap->subc  = (address >> 13) & 0x7;
286         } else {
287                 trap->subc  = (address >> 16) & 0x7;
288                 trap->data2 = NV_READ(NV10_PGRAPH_TRAPPED_DATA_HIGH);
289         }
290
291         if (dev_priv->card_type < NV_10) {
292                 trap->class = NV_READ(0x400180 + trap->subc*4) & 0xFF;
293         } else if (dev_priv->card_type < NV_40) {
294                 trap->class = NV_READ(0x400160 + trap->subc*4) & 0xFFF;
295         } else if (dev_priv->card_type < NV_50) {
296                 trap->class = NV_READ(0x400160 + trap->subc*4) & 0xFFFF;
297         } else {
298                 trap->class = NV_READ(0x400814);
299         }
300 }
301
302 static void
303 nouveau_graph_dump_trap_info(struct drm_device *dev, const char *id,
304                              struct nouveau_pgraph_trap *trap)
305 {
306         struct drm_nouveau_private *dev_priv = dev->dev_private;
307         uint32_t nsource = trap->nsource, nstatus = trap->nstatus;
308
309         DRM_INFO("%s - nSource:", id);
310         nouveau_print_bitfield_names(nsource, nouveau_nsource_names,
311                                      ARRAY_SIZE(nouveau_nsource_names));
312         printk(", nStatus:");
313         if (dev_priv->card_type < NV_10)
314                 nouveau_print_bitfield_names(nstatus, nouveau_nstatus_names,
315                                      ARRAY_SIZE(nouveau_nstatus_names));
316         else
317                 nouveau_print_bitfield_names(nstatus, nouveau_nstatus_names_nv10,
318                                      ARRAY_SIZE(nouveau_nstatus_names_nv10));
319         printk("\n");
320
321         DRM_INFO("%s - Ch %d/%d Class 0x%04x Mthd 0x%04x Data 0x%08x:0x%08x\n",
322                  id, trap->channel, trap->subc, trap->class, trap->mthd,
323                  trap->data2, trap->data);
324 }
325
326 static inline void
327 nouveau_pgraph_intr_notify(struct drm_device *dev, uint32_t nsource)
328 {
329         struct nouveau_pgraph_trap trap;
330         int unhandled = 0;
331
332         nouveau_graph_trap_info(dev, &trap);
333
334         if (nsource & NV03_PGRAPH_NSOURCE_ILLEGAL_MTHD) {
335                 /* NV4 (nvidia TNT 1) reports software methods with
336                  * PGRAPH NOTIFY ILLEGAL_MTHD
337                  */
338                 DRM_DEBUG("Got NV04 software method method %x for class %#x\n",
339                           trap.mthd, trap.class);
340
341                 if (nouveau_sw_method_execute(dev, trap.class, trap.mthd)) {
342                         DRM_ERROR("Unable to execute NV04 software method %x "
343                                   "for object class %x. Please report.\n",
344                                   trap.mthd, trap.class);
345                         unhandled = 1;
346                 }
347         } else {
348                 unhandled = 1;
349         }
350
351         if (unhandled)
352                 nouveau_graph_dump_trap_info(dev, "PGRAPH_NOTIFY", &trap);
353 }
354
355 static inline void
356 nouveau_pgraph_intr_error(struct drm_device *dev, uint32_t nsource)
357 {
358         struct nouveau_pgraph_trap trap;
359         int unhandled = 0;
360
361         nouveau_graph_trap_info(dev, &trap);
362         trap.nsource = nsource;
363
364         if (nsource & NV03_PGRAPH_NSOURCE_ILLEGAL_MTHD) {
365                 if (trap.channel >= 0 && trap.mthd == 0x0150) {
366                         nouveau_fence_handler(dev, trap.channel);
367                 } else
368                 if (nouveau_sw_method_execute(dev, trap.class, trap.mthd)) {
369                         unhandled = 1;
370                 }
371         } else {
372                 unhandled = 1;
373         }
374
375         if (unhandled)
376                 nouveau_graph_dump_trap_info(dev, "PGRAPH_ERROR", &trap);
377 }
378
379 static inline void
380 nouveau_pgraph_intr_context_switch(struct drm_device *dev)
381 {
382         struct drm_nouveau_private *dev_priv = dev->dev_private;
383         struct nouveau_engine *engine = &dev_priv->Engine;
384         uint32_t chid;
385
386         chid = engine->fifo.channel_id(dev);
387         DRM_DEBUG("PGRAPH context switch interrupt channel %x\n", chid);
388
389         switch(dev_priv->card_type) {
390         case NV_04:
391         case NV_05:
392                 nouveau_nv04_context_switch(dev);
393                 break;
394         case NV_10:
395         case NV_11:
396         case NV_17:
397                 nouveau_nv10_context_switch(dev);
398                 break;
399         default:
400                 DRM_ERROR("Context switch not implemented\n");
401                 break;
402         }
403 }
404
405 static void
406 nouveau_pgraph_irq_handler(struct drm_device *dev)
407 {
408         struct drm_nouveau_private *dev_priv = dev->dev_private;
409         uint32_t status;
410
411         while ((status = NV_READ(NV03_PGRAPH_INTR))) {
412                 uint32_t nsource = NV_READ(NV03_PGRAPH_NSOURCE);
413
414                 if (status & NV_PGRAPH_INTR_NOTIFY) {
415                         nouveau_pgraph_intr_notify(dev, nsource);
416
417                         status &= ~NV_PGRAPH_INTR_NOTIFY;
418                         NV_WRITE(NV03_PGRAPH_INTR, NV_PGRAPH_INTR_NOTIFY);
419                 }
420
421                 if (status & NV_PGRAPH_INTR_ERROR) {
422                         nouveau_pgraph_intr_error(dev, nsource);
423
424                         status &= ~NV_PGRAPH_INTR_ERROR;
425                         NV_WRITE(NV03_PGRAPH_INTR, NV_PGRAPH_INTR_ERROR);
426                 }
427
428                 if (status & NV_PGRAPH_INTR_CONTEXT_SWITCH) {
429                         nouveau_pgraph_intr_context_switch(dev);
430
431                         status &= ~NV_PGRAPH_INTR_CONTEXT_SWITCH;
432                         NV_WRITE(NV03_PGRAPH_INTR,
433                                  NV_PGRAPH_INTR_CONTEXT_SWITCH);
434                 }
435
436                 if (status) {
437                         DRM_INFO("Unhandled PGRAPH_INTR - 0x%08x\n", status);
438                         NV_WRITE(NV03_PGRAPH_INTR, status);
439                 }
440
441                 if ((NV_READ(NV04_PGRAPH_FIFO) & (1 << 0)) == 0)
442                         NV_WRITE(NV04_PGRAPH_FIFO, 1);
443         }
444
445         NV_WRITE(NV03_PMC_INTR_0, NV_PMC_INTR_0_PGRAPH_PENDING);
446 }
447
448 static void
449 nv50_pgraph_irq_handler(struct drm_device *dev)
450 {
451         struct drm_nouveau_private *dev_priv = dev->dev_private;
452         uint32_t status;
453
454         status = NV_READ(NV03_PGRAPH_INTR);
455
456         if (status & 0x00000020) {
457                 nouveau_pgraph_intr_error(dev,
458                                           NV03_PGRAPH_NSOURCE_ILLEGAL_MTHD);
459
460                 status &= ~0x00000020;
461                 NV_WRITE(NV03_PGRAPH_INTR, 0x00000020);
462         }
463
464         if (status & 0x00100000) {
465                 nouveau_pgraph_intr_error(dev,
466                                           NV03_PGRAPH_NSOURCE_DATA_ERROR);
467
468                 status &= ~0x00100000;
469                 NV_WRITE(NV03_PGRAPH_INTR, 0x00100000);
470         }
471
472         if (status & 0x00200000) {
473                 nouveau_pgraph_intr_error(dev,
474                                           NV03_PGRAPH_NSOURCE_PROTECTION_ERROR);
475
476                 status &= ~0x00200000;
477                 NV_WRITE(NV03_PGRAPH_INTR, 0x00200000);
478         }
479
480         if (status) {
481                 DRM_INFO("Unhandled PGRAPH_INTR - 0x%08x\n", status);
482                 NV_WRITE(NV03_PGRAPH_INTR, status);
483         }
484
485         {
486                 const int isb = (1 << 16) | (1 << 0);
487
488                 if ((NV_READ(0x400500) & isb) != isb)
489                         NV_WRITE(0x400500, NV_READ(0x400500) | isb);
490         }
491
492         NV_WRITE(NV03_PMC_INTR_0, NV_PMC_INTR_0_PGRAPH_PENDING);
493 }
494
495 static void
496 nouveau_crtc_irq_handler(struct drm_device *dev, int crtc)
497 {
498         struct drm_nouveau_private *dev_priv = dev->dev_private;
499
500         if (crtc&1) {
501                 NV_WRITE(NV_CRTC0_INTSTAT, NV_CRTC_INTR_VBLANK);
502         }
503
504         if (crtc&2) {
505                 NV_WRITE(NV_CRTC1_INTSTAT, NV_CRTC_INTR_VBLANK);
506         }
507 }
508
509 static void
510 nouveau_nv50_display_irq_handler(struct drm_device *dev)
511 {
512         struct drm_nouveau_private *dev_priv = dev->dev_private;
513         uint32_t val = NV_READ(NV50_PDISPLAY_SUPERVISOR);
514
515         DRM_INFO("NV50_PDISPLAY_SUPERVISOR - 0x%08X\n", val);
516
517         /* vblank interrupts */
518         if (val & NV50_PDISPLAY_SUPERVISOR_CRTCn) {
519                 NV_WRITE(NV50_PDISPLAY_SUPERVISOR, val & NV50_PDISPLAY_SUPERVISOR_CRTCn);
520                 val &= ~NV50_PDISPLAY_SUPERVISOR_CRTCn;
521         }
522
523         /* clock setting amongst other things. */
524         if (val & NV50_PDISPLAY_SUPERVISOR_CLK_MASK) {
525                 uint32_t state = (val & NV50_PDISPLAY_SUPERVISOR_CLK_MASK) >> NV50_PDISPLAY_SUPERVISOR_CLK_MASK__SHIFT;
526
527                 NV50_DEBUG("state %d\n", state);
528
529                 /* Set pll */
530                 if (state == 2) {
531                         struct nv50_display *display = nv50_get_display(dev);
532                         struct nv50_output *output = NULL;
533                         struct nv50_crtc *crtc = NULL;
534                         int crtc_index;
535
536                         uint32_t unk30 = NV_READ(NV50_PDISPLAY_UNK30_CTRL);
537
538                         for (crtc_index = 0; crtc_index < 2; crtc_index++) {
539                                 bool clock_change = false;
540                                 bool clock_ack = false;
541
542                                 if (crtc_index == 0 && (unk30 & NV50_PDISPLAY_UNK30_CTRL_UPDATE_VCLK0))
543                                         clock_change = true;
544
545                                 if (crtc_index == 1 && (unk30 & NV50_PDISPLAY_UNK30_CTRL_UPDATE_VCLK1))
546                                         clock_change = true;
547
548                                 if (clock_change)
549                                         clock_ack = true;
550
551                                 if (display->last_crtc == crtc_index)
552                                         clock_ack = true;
553
554                                 list_for_each_entry(crtc, &display->crtcs, item) {
555                                         if (crtc->index == crtc_index)
556                                                 break;
557                                 }
558
559                                 if (clock_change)
560                                         crtc->set_clock(crtc);
561
562                                 NV50_DEBUG("index %d clock_change %d clock_ack %d\n", crtc_index, clock_change, clock_ack);
563
564                                 if (!clock_ack)
565                                         continue;
566
567                                 crtc->set_clock_mode(crtc);
568
569                                 list_for_each_entry(output, &display->outputs, item) {
570                                         if (!output->crtc)
571                                                 continue;
572
573                                         if (output->crtc == crtc)
574                                                 output->set_clock_mode(output);
575                                 }
576                         }
577                 }
578
579                 NV_WRITE(NV50_PDISPLAY_UNK30_CTRL, NV50_PDISPLAY_UNK30_CTRL_PENDING);
580                 NV_WRITE(NV50_PDISPLAY_SUPERVISOR, val & NV50_PDISPLAY_SUPERVISOR_CLK_MASK);
581
582                 val &= ~NV50_PDISPLAY_SUPERVISOR_CLK_MASK;
583         }
584
585         if (val)
586                 DRM_ERROR("unsupported NV50_DISPLAY_INTR - 0x%08X\n", val);
587
588         NV_WRITE(NV50_PDISPLAY_SUPERVISOR, val);
589 }
590
591 static void
592 nouveau_nv50_i2c_irq_handler(struct drm_device *dev)
593 {
594         struct drm_nouveau_private *dev_priv = dev->dev_private;
595
596         DRM_INFO("NV50_PCONNECTOR_HOTPLUG_CTRL - 0x%08X\n", NV_READ(NV50_PCONNECTOR_HOTPLUG_CTRL));
597
598         /* This seems to be the way to acknowledge an interrupt. */
599         NV_WRITE(NV50_PCONNECTOR_HOTPLUG_CTRL, 0x7FFF7FFF);
600
601         /* Do a "dumb" detect all */
602         nv50_kms_connector_detect_all(dev);
603 }
604
605 irqreturn_t
606 nouveau_irq_handler(DRM_IRQ_ARGS)
607 {
608         struct drm_device *dev = (struct drm_device*)arg;
609         struct drm_nouveau_private *dev_priv = dev->dev_private;
610         uint32_t status;
611
612         status = NV_READ(NV03_PMC_INTR_0);
613         if (!status)
614                 return IRQ_NONE;
615
616         if (status & NV_PMC_INTR_0_PFIFO_PENDING) {
617                 nouveau_fifo_irq_handler(dev);
618                 status &= ~NV_PMC_INTR_0_PFIFO_PENDING;
619         }
620
621         if (status & NV_PMC_INTR_0_PGRAPH_PENDING) {
622                 if (dev_priv->card_type >= NV_50)
623                         nv50_pgraph_irq_handler(dev);
624                 else
625                         nouveau_pgraph_irq_handler(dev);
626
627                 status &= ~NV_PMC_INTR_0_PGRAPH_PENDING;
628         }
629
630         if (status & NV_PMC_INTR_0_CRTCn_PENDING) {
631                 nouveau_crtc_irq_handler(dev, (status>>24)&3);
632                 status &= ~NV_PMC_INTR_0_CRTCn_PENDING;
633         }
634
635         if (status & NV_PMC_INTR_0_NV50_DISPLAY_PENDING) {
636                 nouveau_nv50_display_irq_handler(dev);
637                 status &= ~NV_PMC_INTR_0_NV50_DISPLAY_PENDING;
638         }
639
640         if (status & NV_PMC_INTR_0_NV50_I2C_PENDING) {
641                 nouveau_nv50_i2c_irq_handler(dev);
642                 status &= ~NV_PMC_INTR_0_NV50_I2C_PENDING;
643         }
644
645         if (status)
646                 DRM_ERROR("Unhandled PMC INTR status bits 0x%08x\n", status);
647
648         return IRQ_HANDLED;
649 }