OSDN Git Service

Merge branch 'master' of ssh+git://git.freedesktop.org/git/mesa/drm into xgi-0-0-2
[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
39 void nouveau_irq_preinstall(struct drm_device *dev)
40 {
41         struct drm_nouveau_private *dev_priv = dev->dev_private;
42
43         DRM_DEBUG("IRQ: preinst\n");
44
45         if (!dev_priv) {
46                 DRM_ERROR("AIII, no dev_priv\n");
47                 return;
48         }
49         if (!dev_priv->mmio) {
50                 DRM_ERROR("AIII, no dev_priv->mmio\n");
51                 return;
52         }
53
54         /* Disable/Clear PFIFO interrupts */
55         NV_WRITE(NV03_PFIFO_INTR_EN_0, 0);
56         NV_WRITE(NV03_PFIFO_INTR_0, 0xFFFFFFFF);
57         /* Disable/Clear PGRAPH interrupts */
58         if (dev_priv->card_type<NV_40)
59                 NV_WRITE(NV03_PGRAPH_INTR_EN, 0);
60         else
61                 NV_WRITE(NV40_PGRAPH_INTR_EN, 0);
62         NV_WRITE(NV03_PGRAPH_INTR, 0xFFFFFFFF);
63 #if 0
64         /* Disable/Clear CRTC0/1 interrupts */
65         NV_WRITE(NV_CRTC0_INTEN, 0);
66         NV_WRITE(NV_CRTC0_INTSTAT, NV_CRTC_INTR_VBLANK);
67         NV_WRITE(NV_CRTC1_INTEN, 0);
68         NV_WRITE(NV_CRTC1_INTSTAT, NV_CRTC_INTR_VBLANK);
69 #endif
70         /* Master disable */
71         NV_WRITE(NV03_PMC_INTR_EN_0, 0);
72 }
73
74 void nouveau_irq_postinstall(struct drm_device *dev)
75 {
76         struct drm_nouveau_private *dev_priv = dev->dev_private;
77
78         if (!dev_priv) {
79                 DRM_ERROR("AIII, no dev_priv\n");
80                 return;
81         }
82         if (!dev_priv->mmio) {
83                 DRM_ERROR("AIII, no dev_priv->mmio\n");
84                 return;
85         }
86
87         DRM_DEBUG("IRQ: postinst\n");
88
89         /* Enable PFIFO error reporting */
90         NV_WRITE(NV03_PFIFO_INTR_EN_0, 0xFFFFFFFF);
91         NV_WRITE(NV03_PFIFO_INTR_0, 0xFFFFFFFF);
92
93         /* Enable PGRAPH interrupts */
94         if (dev_priv->card_type<NV_40)
95                 NV_WRITE(NV03_PGRAPH_INTR_EN, 0xFFFFFFFF);
96         else
97                 NV_WRITE(NV40_PGRAPH_INTR_EN, 0xFFFFFFFF);
98         NV_WRITE(NV03_PGRAPH_INTR, 0xFFFFFFFF);
99
100 #if 0
101         /* Enable CRTC0/1 interrupts */
102         NV_WRITE(NV_CRTC0_INTEN, NV_CRTC_INTR_VBLANK);
103         NV_WRITE(NV_CRTC1_INTEN, NV_CRTC_INTR_VBLANK);
104 #endif
105
106         /* Master enable */
107         NV_WRITE(NV03_PMC_INTR_EN_0, NV_PMC_INTR_EN_0_MASTER_ENABLE);
108 }
109
110 void nouveau_irq_uninstall(struct drm_device *dev)
111 {
112         struct drm_nouveau_private *dev_priv = dev->dev_private;
113
114         if (!dev_priv) {
115                 DRM_ERROR("AIII, no dev_priv\n");
116                 return;
117         }
118         if (!dev_priv->mmio) {
119                 DRM_ERROR("AIII, no dev_priv->mmio\n");
120                 return;
121         }
122
123         DRM_DEBUG("IRQ: uninst\n");
124
125         /* Disable PFIFO interrupts */
126         NV_WRITE(NV03_PFIFO_INTR_EN_0, 0);
127         /* Disable PGRAPH interrupts */
128         if (dev_priv->card_type<NV_40)
129                 NV_WRITE(NV03_PGRAPH_INTR_EN, 0);
130         else
131                 NV_WRITE(NV40_PGRAPH_INTR_EN, 0);
132 #if 0
133         /* Disable CRTC0/1 interrupts */
134         NV_WRITE(NV_CRTC0_INTEN, 0);
135         NV_WRITE(NV_CRTC1_INTEN, 0);
136 #endif
137         /* Master disable */
138         NV_WRITE(NV03_PMC_INTR_EN_0, 0);
139 }
140
141 static void nouveau_fifo_irq_handler(struct drm_device *dev)
142 {
143         uint32_t status, chmode, chstat, channel;
144         struct drm_nouveau_private *dev_priv = dev->dev_private;
145
146         status = NV_READ(NV03_PFIFO_INTR_0);
147         if (!status)
148                 return;
149         chmode = NV_READ(NV04_PFIFO_MODE);
150         chstat = NV_READ(NV04_PFIFO_DMA);
151         channel=NV_READ(NV03_PFIFO_CACHE1_PUSH1)&(nouveau_fifo_number(dev)-1);
152
153         DRM_DEBUG("NV: PFIFO interrupt! Channel=%d, INTSTAT=0x%08x/MODE=0x%08x/PEND=0x%08x\n", channel, status, chmode, chstat);
154
155         if (status & NV_PFIFO_INTR_CACHE_ERROR) {
156                 uint32_t c1get, c1method, c1data;
157
158                 DRM_ERROR("NV: PFIFO error interrupt\n");
159
160                 c1get = NV_READ(NV03_PFIFO_CACHE1_GET) >> 2;
161                 if (dev_priv->card_type < NV_40) {
162                         /* Untested, so it may not work.. */
163                         c1method = NV_READ(NV04_PFIFO_CACHE1_METHOD(c1get));
164                         c1data   = NV_READ(NV04_PFIFO_CACHE1_DATA(c1get));
165                 } else {
166                         c1method = NV_READ(NV40_PFIFO_CACHE1_METHOD(c1get));
167                         c1data   = NV_READ(NV40_PFIFO_CACHE1_DATA(c1get));
168                 }
169
170                 DRM_ERROR("NV: Channel %d/%d - Method 0x%04x, Data 0x%08x\n",
171                                 channel, (c1method >> 13) & 7,
172                                 c1method & 0x1ffc, c1data
173                          );
174
175                 status &= ~NV_PFIFO_INTR_CACHE_ERROR;
176                 NV_WRITE(NV03_PFIFO_INTR_0, NV_PFIFO_INTR_CACHE_ERROR);
177         }
178
179         if (status & NV_PFIFO_INTR_DMA_PUSHER) {
180                 DRM_INFO("NV: PFIFO DMA pusher interrupt\n");
181
182                 status &= ~NV_PFIFO_INTR_DMA_PUSHER;
183                 NV_WRITE(NV03_PFIFO_INTR_0, NV_PFIFO_INTR_DMA_PUSHER);
184
185                 NV_WRITE(NV04_PFIFO_CACHE1_DMA_STATE, 0x00000000);
186                 if (NV_READ(NV04_PFIFO_CACHE1_DMA_PUT)!=NV_READ(NV04_PFIFO_CACHE1_DMA_GET))
187                 {
188                         uint32_t getval=NV_READ(NV04_PFIFO_CACHE1_DMA_GET)+4;
189                         NV_WRITE(NV04_PFIFO_CACHE1_DMA_GET,getval);
190                 }
191         }
192
193         if (status) {
194                 DRM_INFO("NV: unknown PFIFO interrupt. status=0x%08x\n", status);
195
196                 NV_WRITE(NV03_PFIFO_INTR_0, status);
197         }
198
199         NV_WRITE(NV03_PMC_INTR_0, NV_PMC_INTR_0_PFIFO_PENDING);
200 }
201
202 #if 0
203 static void nouveau_nv04_context_switch(struct drm_device *dev)
204 {
205         struct drm_nouveau_private *dev_priv = dev->dev_private;
206         uint32_t channel,i;
207         uint32_t max=0;
208         NV_WRITE(NV04_PGRAPH_FIFO,0x0);
209         channel=NV_READ(NV03_PFIFO_CACHE1_PUSH1)&(nouveau_fifo_number(dev)-1);
210         //DRM_INFO("raw PFIFO_CACH1_PHS1 reg is %x\n",NV_READ(NV03_PFIFO_CACHE1_PUSH1));
211         //DRM_INFO("currently on channel %d\n",channel);
212         for (i=0;i<nouveau_fifo_number(dev);i++)
213                 if ((dev_priv->fifos[i].used)&&(i!=channel)) {
214                         uint32_t put,get,pending;
215                         //put=NV_READ(dev_priv->ramfc_offset+i*32);
216                         //get=NV_READ(dev_priv->ramfc_offset+4+i*32);
217                         put=NV_READ(NV03_FIFO_REGS_DMAPUT(i));
218                         get=NV_READ(NV03_FIFO_REGS_DMAGET(i));
219                         pending=NV_READ(NV04_PFIFO_DMA);
220                         //DRM_INFO("Channel %d (put/get %x/%x)\n",i,put,get);
221                         /* mark all pending channels as such */
222                         if ((put!=get)&!(pending&(1<<i)))
223                         {
224                                 pending|=(1<<i);
225                                 NV_WRITE(NV04_PFIFO_DMA,pending);
226                         }
227                         max++;
228                 }
229         nouveau_wait_for_idle(dev);
230
231 #if 1
232         /* 2-channel commute */
233         //              NV_WRITE(NV03_PFIFO_CACHE1_PUSH1,channel|0x100);
234         if (channel==0)
235                 channel=1;
236         else
237                 channel=0;
238         //              dev_priv->cur_fifo=channel;
239         NV_WRITE(NV04_PFIFO_NEXT_CHANNEL,channel|0x100);
240 #endif
241         //NV_WRITE(NV03_PFIFO_CACHE1_PUSH1,max|0x100);
242         //NV_WRITE(0x2050,max|0x100);
243
244         NV_WRITE(NV04_PGRAPH_FIFO,0x1);
245         
246 }
247 #endif
248
249
250 struct nouveau_bitfield_names
251 {
252         uint32_t mask;
253         const char * name;
254 };
255
256 static struct nouveau_bitfield_names nouveau_nstatus_names[] =
257 {
258         { NV03_PGRAPH_NSTATUS_STATE_IN_USE,       "STATE_IN_USE" },
259         { NV03_PGRAPH_NSTATUS_INVALID_STATE,      "INVALID_STATE" },
260         { NV03_PGRAPH_NSTATUS_BAD_ARGUMENT,       "BAD_ARGUMENT" },
261         { NV03_PGRAPH_NSTATUS_PROTECTION_FAULT,   "PROTECTION_FAULT" }
262 };
263
264 static struct nouveau_bitfield_names nouveau_nsource_names[] =
265 {
266         { NV03_PGRAPH_NSOURCE_NOTIFICATION,       "NOTIFICATION" },
267         { NV03_PGRAPH_NSOURCE_DATA_ERROR,         "DATA_ERROR" },
268         { NV03_PGRAPH_NSOURCE_PROTECTION_ERROR,   "PROTECTION_ERROR" },
269         { NV03_PGRAPH_NSOURCE_RANGE_EXCEPTION,    "RANGE_EXCEPTION" },
270         { NV03_PGRAPH_NSOURCE_LIMIT_COLOR,        "LIMIT_COLOR" },
271         { NV03_PGRAPH_NSOURCE_LIMIT_ZETA,         "LIMIT_ZETA" },
272         { NV03_PGRAPH_NSOURCE_ILLEGAL_MTHD,       "ILLEGAL_MTHD" },
273         { NV03_PGRAPH_NSOURCE_DMA_R_PROTECTION,   "DMA_R_PROTECTION" },
274         { NV03_PGRAPH_NSOURCE_DMA_W_PROTECTION,   "DMA_W_PROTECTION" },
275         { NV03_PGRAPH_NSOURCE_FORMAT_EXCEPTION,   "FORMAT_EXCEPTION" },
276         { NV03_PGRAPH_NSOURCE_PATCH_EXCEPTION,    "PATCH_EXCEPTION" },
277         { NV03_PGRAPH_NSOURCE_STATE_INVALID,      "STATE_INVALID" },
278         { NV03_PGRAPH_NSOURCE_DOUBLE_NOTIFY,      "DOUBLE_NOTIFY" },
279         { NV03_PGRAPH_NSOURCE_NOTIFY_IN_USE,      "NOTIFY_IN_USE" },
280         { NV03_PGRAPH_NSOURCE_METHOD_CNT,         "METHOD_CNT" },
281         { NV03_PGRAPH_NSOURCE_BFR_NOTIFICATION,   "BFR_NOTIFICATION" },
282         { NV03_PGRAPH_NSOURCE_DMA_VTX_PROTECTION, "DMA_VTX_PROTECTION" },
283         { NV03_PGRAPH_NSOURCE_DMA_WIDTH_A,        "DMA_WIDTH_A" },
284         { NV03_PGRAPH_NSOURCE_DMA_WIDTH_B,        "DMA_WIDTH_B" },
285 };
286
287 static void
288 nouveau_print_bitfield_names(uint32_t value,
289                              const struct nouveau_bitfield_names *namelist,
290                              const int namelist_len)
291 {
292         int i;
293         for(i=0; i<namelist_len; ++i) {
294                 uint32_t mask = namelist[i].mask;
295                 if(value & mask) {
296                         printk(" %s", namelist[i].name);
297                         value &= ~mask;
298                 }
299         }
300         if(value)
301                 printk(" (unknown bits 0x%08x)", value);
302 }
303
304 static void
305 nouveau_graph_dump_trap_info(struct drm_device *dev)
306 {
307         struct drm_nouveau_private *dev_priv = dev->dev_private;
308         uint32_t address;
309         uint32_t channel, class;
310         uint32_t method, subc, data;
311         uint32_t nsource, nstatus;
312
313         address = NV_READ(0x400704);
314         channel = (address >> 20) & 0x1F;
315         subc    = (address >> 16) & 0x7;
316         method  = address & 0x1FFC;
317         data    = NV_READ(0x400708);
318         nsource = NV_READ(NV03_PGRAPH_NSOURCE);
319         nstatus = NV_READ(NV03_PGRAPH_NSTATUS);
320         if (dev_priv->card_type < NV_50) {
321                 class = NV_READ(0x400160 + subc*4) & 0xFFFF;
322         } else {
323                 class = NV_READ(0x400814);
324         }
325
326         DRM_ERROR("nSource:");
327         nouveau_print_bitfield_names(nsource, nouveau_nsource_names,
328                                      ARRAY_SIZE(nouveau_nsource_names));
329         printk(", nStatus:");
330         nouveau_print_bitfield_names(nstatus, nouveau_nstatus_names,
331                                      ARRAY_SIZE(nouveau_nstatus_names));
332         printk("\n");
333
334         DRM_ERROR("NV: Channel %d/%d (class 0x%04x) - "
335                         "Method 0x%04x, Data 0x%08x\n",
336                         channel, subc, class, method, data
337                  );
338 }
339
340 static void nouveau_pgraph_irq_handler(struct drm_device *dev)
341 {
342         uint32_t status;
343         struct drm_nouveau_private *dev_priv = dev->dev_private;
344
345         status = NV_READ(NV03_PGRAPH_INTR);
346         if (!status)
347                 return;
348
349         if (status & NV_PGRAPH_INTR_NOTIFY) {
350                 uint32_t nsource, nstatus, instance, notify;
351                 DRM_DEBUG("NV: PGRAPH notify interrupt\n");
352
353                 nstatus = NV_READ(NV03_PGRAPH_NSTATUS);
354                 nsource = NV_READ(NV03_PGRAPH_NSOURCE);
355                 DRM_DEBUG("nsource:0x%08x\tnstatus:0x%08x\n", nsource, nstatus);
356
357                 /* if this wasn't NOTIFICATION_PENDING, dump extra trap info */
358                 if (nsource & ~(1<<0)) {
359                         nouveau_graph_dump_trap_info(dev);
360                 } else {
361                         instance = NV_READ(0x00400158);
362                         notify   = NV_READ(0x00400150) >> 16;
363                         DRM_DEBUG("instance:0x%08x\tnotify:0x%08x\n",
364                                   instance, notify);
365                 }
366
367                 status &= ~NV_PGRAPH_INTR_NOTIFY;
368                 NV_WRITE(NV03_PGRAPH_INTR, NV_PGRAPH_INTR_NOTIFY);
369         }
370
371         if (status & NV_PGRAPH_INTR_BUFFER_NOTIFY) {
372                 uint32_t nsource, nstatus, instance, notify;
373                 DRM_DEBUG("NV: PGRAPH buffer notify interrupt\n");
374
375                 nstatus = NV_READ(NV03_PGRAPH_NSTATUS);
376                 nsource = NV_READ(NV03_PGRAPH_NSOURCE);
377                 DRM_DEBUG("nsource:0x%08x\tnstatus:0x%08x\n", nsource, nstatus);
378
379                 instance = NV_READ(0x00400158);
380                 notify   = NV_READ(0x00400150) >> 16;
381                 DRM_DEBUG("instance:0x%08x\tnotify:0x%08x\n", instance, notify);
382
383                 status &= ~NV_PGRAPH_INTR_BUFFER_NOTIFY;
384                 NV_WRITE(NV03_PGRAPH_INTR, NV_PGRAPH_INTR_BUFFER_NOTIFY);
385         }
386
387         if (status & NV_PGRAPH_INTR_MISSING_HW) {
388                 DRM_ERROR("NV: PGRAPH missing hw interrupt\n");
389
390                 status &= ~NV_PGRAPH_INTR_MISSING_HW;
391                 NV_WRITE(NV03_PGRAPH_INTR, NV_PGRAPH_INTR_MISSING_HW);
392         }
393
394         if (status & NV_PGRAPH_INTR_ERROR) {
395                 uint32_t nsource, nstatus, instance;
396
397                 DRM_ERROR("NV: PGRAPH error interrupt\n");
398
399                 nstatus = NV_READ(NV03_PGRAPH_NSTATUS);
400                 nsource = NV_READ(NV03_PGRAPH_NSOURCE);
401                 DRM_ERROR("nsource:0x%08x\tnstatus:0x%08x\n", nsource, nstatus);
402
403                 instance = NV_READ(0x00400158);
404                 DRM_ERROR("instance:0x%08x\n", instance);
405
406                 nouveau_graph_dump_trap_info(dev);
407
408                 status &= ~NV_PGRAPH_INTR_ERROR;
409                 NV_WRITE(NV03_PGRAPH_INTR, NV_PGRAPH_INTR_ERROR);
410         }
411
412         if (status & NV_PGRAPH_INTR_CONTEXT_SWITCH) {
413                 uint32_t channel=NV_READ(NV03_PFIFO_CACHE1_PUSH1)&(nouveau_fifo_number(dev)-1);
414                 DRM_INFO("NV: PGRAPH context switch interrupt channel %x\n",channel);
415                 switch(dev_priv->card_type)
416                 {
417                         case NV_04:
418                         case NV_05:
419                                 nouveau_nv04_context_switch(dev);
420                                 break;
421                         case NV_10:
422                         case NV_11:
423                         case NV_17:
424                                 nouveau_nv10_context_switch(dev);
425                                 break;
426                         case NV_20:
427                         case NV_30:
428                                 nouveau_nv20_context_switch(dev);
429                                 break;
430                         default:
431                                 DRM_INFO("NV: Context switch not implemented\n");
432                                 break;
433                 }
434
435                 status &= ~NV_PGRAPH_INTR_CONTEXT_SWITCH;
436                 NV_WRITE(NV03_PGRAPH_INTR, NV_PGRAPH_INTR_CONTEXT_SWITCH);
437         }
438
439         if (status) {
440                 DRM_INFO("NV: Unknown PGRAPH interrupt! STAT=0x%08x\n", status);
441                 NV_WRITE(NV03_PGRAPH_INTR, status);
442         }
443
444         NV_WRITE(NV03_PMC_INTR_0, NV_PMC_INTR_0_PGRAPH_PENDING);
445 }
446
447 static void nouveau_crtc_irq_handler(struct drm_device *dev, int crtc)
448 {
449         struct drm_nouveau_private *dev_priv = dev->dev_private;
450         if (crtc&1) {
451                 NV_WRITE(NV_CRTC0_INTSTAT, NV_CRTC_INTR_VBLANK);
452         }
453
454         if (crtc&2) {
455                 NV_WRITE(NV_CRTC1_INTSTAT, NV_CRTC_INTR_VBLANK);
456         }
457 }
458
459 irqreturn_t nouveau_irq_handler(DRM_IRQ_ARGS)
460 {
461         struct drm_device *dev = (struct drm_device*)arg;
462         struct drm_nouveau_private *dev_priv = dev->dev_private;
463         uint32_t status;
464
465         status = NV_READ(NV03_PMC_INTR_0);
466         if (!status)
467                 return IRQ_NONE;
468
469         DRM_DEBUG("PMC INTSTAT: 0x%08x\n", status);
470
471         if (status & NV_PMC_INTR_0_PFIFO_PENDING) {
472                 nouveau_fifo_irq_handler(dev);
473                 status &= ~NV_PMC_INTR_0_PFIFO_PENDING;
474         }
475         if (status & NV_PMC_INTR_0_PGRAPH_PENDING) {
476                 nouveau_pgraph_irq_handler(dev);
477                 status &= ~NV_PMC_INTR_0_PGRAPH_PENDING;
478         }
479         if (status & NV_PMC_INTR_0_CRTCn_PENDING) {
480                 nouveau_crtc_irq_handler(dev, (status>>24)&3);
481                 status &= ~NV_PMC_INTR_0_CRTCn_PENDING;
482         }
483
484         if (status)
485                 DRM_ERROR("Unhandled PMC INTR status bits 0x%08x\n", status);
486
487         return IRQ_HANDLED;
488 }
489