OSDN Git Service

Eliminate support for fake buffers.
[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 void
41 nouveau_irq_preinstall(struct drm_device *dev)
42 {
43         struct drm_nouveau_private *dev_priv = dev->dev_private;
44
45         /* Master disable */
46         NV_WRITE(NV03_PMC_INTR_EN_0, 0);
47 }
48
49 void
50 nouveau_irq_postinstall(struct drm_device *dev)
51 {
52         struct drm_nouveau_private *dev_priv = dev->dev_private;
53
54         /* Master enable */
55         NV_WRITE(NV03_PMC_INTR_EN_0, NV_PMC_INTR_EN_0_MASTER_ENABLE);
56 }
57
58 void
59 nouveau_irq_uninstall(struct drm_device *dev)
60 {
61         struct drm_nouveau_private *dev_priv = dev->dev_private;
62
63         /* Master disable */
64         NV_WRITE(NV03_PMC_INTR_EN_0, 0);
65 }
66
67 static void
68 nouveau_fifo_irq_handler(struct drm_device *dev)
69 {
70         struct drm_nouveau_private *dev_priv = dev->dev_private;
71         uint32_t status;
72
73         while ((status = NV_READ(NV03_PFIFO_INTR_0))) {
74                 uint32_t chid, get;
75
76                 NV_WRITE(NV03_PFIFO_CACHES, 0);
77
78                 chid = NV_READ(NV03_PFIFO_CACHE1_PUSH1) &
79                                 (nouveau_fifo_number(dev) - 1);
80                 get  = NV_READ(NV03_PFIFO_CACHE1_GET);
81
82                 if (status & NV_PFIFO_INTR_CACHE_ERROR) {
83                         uint32_t mthd, data;
84                         int ptr;
85                         
86                         ptr = get >> 2;
87                         if (dev_priv->card_type < NV_40) {
88                                 mthd = NV_READ(NV04_PFIFO_CACHE1_METHOD(ptr));
89                                 data = NV_READ(NV04_PFIFO_CACHE1_DATA(ptr));
90                         } else {
91                                 mthd = NV_READ(NV40_PFIFO_CACHE1_METHOD(ptr));
92                                 data = NV_READ(NV40_PFIFO_CACHE1_DATA(ptr));
93                         }
94
95                         DRM_INFO("PFIFO_CACHE_ERROR - "
96                                  "Ch %d/%d Mthd 0x%04x Data 0x%08x\n",
97                                  chid, (mthd >> 13) & 7, mthd & 0x1ffc, data);
98
99                         NV_WRITE(NV03_PFIFO_CACHE1_GET, get + 4);
100                         NV_WRITE(NV04_PFIFO_CACHE1_PULL0, 1);
101
102                         status &= ~NV_PFIFO_INTR_CACHE_ERROR;
103                         NV_WRITE(NV03_PFIFO_INTR_0, NV_PFIFO_INTR_CACHE_ERROR);
104                 }
105
106                 if (status & NV_PFIFO_INTR_DMA_PUSHER) {
107                         DRM_INFO("PFIFO_DMA_PUSHER - Ch %d\n", chid);
108
109                         status &= ~NV_PFIFO_INTR_DMA_PUSHER;
110                         NV_WRITE(NV03_PFIFO_INTR_0, NV_PFIFO_INTR_DMA_PUSHER);
111
112                         NV_WRITE(NV04_PFIFO_CACHE1_DMA_STATE, 0x00000000);
113                         if (NV_READ(NV04_PFIFO_CACHE1_DMA_PUT) != get)
114                                 NV_WRITE(NV04_PFIFO_CACHE1_DMA_GET, get + 4);
115                 }
116
117                 if (status) {
118                         DRM_INFO("Unhandled PFIFO_INTR - 0x%8x\n", status);
119                         NV_WRITE(NV03_PFIFO_INTR_0, status);
120                 }
121
122                 NV_WRITE(NV03_PFIFO_CACHES, 1);
123         }
124
125         NV_WRITE(NV03_PMC_INTR_0, NV_PMC_INTR_0_PFIFO_PENDING);
126 }
127
128 struct nouveau_bitfield_names {
129         uint32_t mask;
130         const char * name;
131 };
132
133 static struct nouveau_bitfield_names nouveau_nstatus_names[] =
134 {
135         { NV04_PGRAPH_NSTATUS_STATE_IN_USE,       "STATE_IN_USE" },
136         { NV04_PGRAPH_NSTATUS_INVALID_STATE,      "INVALID_STATE" },
137         { NV04_PGRAPH_NSTATUS_BAD_ARGUMENT,       "BAD_ARGUMENT" },
138         { NV04_PGRAPH_NSTATUS_PROTECTION_FAULT,   "PROTECTION_FAULT" }
139 };
140
141 static struct nouveau_bitfield_names nouveau_nstatus_names_nv10[] =
142 {
143         { NV10_PGRAPH_NSTATUS_STATE_IN_USE,       "STATE_IN_USE" },
144         { NV10_PGRAPH_NSTATUS_INVALID_STATE,      "INVALID_STATE" },
145         { NV10_PGRAPH_NSTATUS_BAD_ARGUMENT,       "BAD_ARGUMENT" },
146         { NV10_PGRAPH_NSTATUS_PROTECTION_FAULT,   "PROTECTION_FAULT" }
147 };
148
149 static struct nouveau_bitfield_names nouveau_nsource_names[] =
150 {
151         { NV03_PGRAPH_NSOURCE_NOTIFICATION,       "NOTIFICATION" },
152         { NV03_PGRAPH_NSOURCE_DATA_ERROR,         "DATA_ERROR" },
153         { NV03_PGRAPH_NSOURCE_PROTECTION_ERROR,   "PROTECTION_ERROR" },
154         { NV03_PGRAPH_NSOURCE_RANGE_EXCEPTION,    "RANGE_EXCEPTION" },
155         { NV03_PGRAPH_NSOURCE_LIMIT_COLOR,        "LIMIT_COLOR" },
156         { NV03_PGRAPH_NSOURCE_LIMIT_ZETA,         "LIMIT_ZETA" },
157         { NV03_PGRAPH_NSOURCE_ILLEGAL_MTHD,       "ILLEGAL_MTHD" },
158         { NV03_PGRAPH_NSOURCE_DMA_R_PROTECTION,   "DMA_R_PROTECTION" },
159         { NV03_PGRAPH_NSOURCE_DMA_W_PROTECTION,   "DMA_W_PROTECTION" },
160         { NV03_PGRAPH_NSOURCE_FORMAT_EXCEPTION,   "FORMAT_EXCEPTION" },
161         { NV03_PGRAPH_NSOURCE_PATCH_EXCEPTION,    "PATCH_EXCEPTION" },
162         { NV03_PGRAPH_NSOURCE_STATE_INVALID,      "STATE_INVALID" },
163         { NV03_PGRAPH_NSOURCE_DOUBLE_NOTIFY,      "DOUBLE_NOTIFY" },
164         { NV03_PGRAPH_NSOURCE_NOTIFY_IN_USE,      "NOTIFY_IN_USE" },
165         { NV03_PGRAPH_NSOURCE_METHOD_CNT,         "METHOD_CNT" },
166         { NV03_PGRAPH_NSOURCE_BFR_NOTIFICATION,   "BFR_NOTIFICATION" },
167         { NV03_PGRAPH_NSOURCE_DMA_VTX_PROTECTION, "DMA_VTX_PROTECTION" },
168         { NV03_PGRAPH_NSOURCE_DMA_WIDTH_A,        "DMA_WIDTH_A" },
169         { NV03_PGRAPH_NSOURCE_DMA_WIDTH_B,        "DMA_WIDTH_B" },
170 };
171
172 static void
173 nouveau_print_bitfield_names(uint32_t value,
174                              const struct nouveau_bitfield_names *namelist,
175                              const int namelist_len)
176 {
177         int i;
178         for(i=0; i<namelist_len; ++i) {
179                 uint32_t mask = namelist[i].mask;
180                 if(value & mask) {
181                         printk(" %s", namelist[i].name);
182                         value &= ~mask;
183                 }
184         }
185         if(value)
186                 printk(" (unknown bits 0x%08x)", value);
187 }
188
189 static int
190 nouveau_graph_trapped_channel(struct drm_device *dev, int *channel_ret)
191 {
192         struct drm_nouveau_private *dev_priv = dev->dev_private;
193         int channel;
194
195         if (dev_priv->card_type < NV_10) {
196                 channel = (NV_READ(NV04_PGRAPH_TRAPPED_ADDR) >> 24) & 0xf;
197         } else if (dev_priv->card_type < NV_40) {
198                 channel = (NV_READ(NV04_PGRAPH_TRAPPED_ADDR) >> 20) & 0x1f;
199         } else
200         if (dev_priv->card_type < NV_50) {
201                 uint32_t cur_grctx = (NV_READ(0x40032C) & 0xfffff) << 4;
202
203                 /* 0x400704 *sometimes* contains a sensible channel ID, but
204                  * mostly not.. for now lookup which channel owns the active
205                  * PGRAPH context.  Probably a better way, but this'll do
206                  * for now.
207                  */
208                 for (channel = 0; channel < 32; channel++) {
209                         if (dev_priv->fifos[channel] == NULL)
210                                 continue;
211                         if (cur_grctx ==
212                             dev_priv->fifos[channel]->ramin_grctx->instance)
213                                 break;
214                 }
215                 if (channel == 32) {
216                         DRM_ERROR("AIII, unable to determine active channel "
217                                   "from PGRAPH context 0x%08x\n", cur_grctx);
218                         return -EINVAL;
219                 }
220         } else {
221                 uint32_t cur_grctx = (NV_READ(0x40032C) & 0xfffff) << 12;
222
223                 for (channel = 0; channel < 128; channel++) {
224                         if (dev_priv->fifos[channel] == NULL)
225                                 continue;
226                         if (cur_grctx ==
227                             dev_priv->fifos[channel]->ramin_grctx->instance)
228                                 break;
229                 }
230                 if (channel == 128) {
231                         DRM_ERROR("AIII, unable to determine active channel "
232                                   "from PGRAPH context 0x%08x\n", cur_grctx);
233                         return -EINVAL;
234                 }
235         }
236
237         if (channel > nouveau_fifo_number(dev) ||
238             dev_priv->fifos[channel] == NULL) {
239                 DRM_ERROR("AIII, invalid/inactive channel id %d\n", channel);
240                 return -EINVAL;
241         }
242
243         *channel_ret = channel;
244         return 0;
245 }
246
247 static void
248 nouveau_graph_dump_trap_info(struct drm_device *dev, const char *id)
249 {
250         struct drm_nouveau_private *dev_priv = dev->dev_private;
251         uint32_t address;
252         uint32_t channel, class;
253         uint32_t method, subc, data, data2;
254         uint32_t nsource, nstatus;
255
256         if (nouveau_graph_trapped_channel(dev, &channel))
257                 channel = -1;
258
259         data    = NV_READ(NV04_PGRAPH_TRAPPED_DATA);
260         address = NV_READ(NV04_PGRAPH_TRAPPED_ADDR);
261         method  = address & 0x1FFC;
262         if (dev_priv->card_type < NV_10) {
263                 subc = (address >> 13) & 0x7;
264                 data2= 0;
265         } else {
266                 subc = (address >> 16) & 0x7;
267                 data2= NV_READ(NV10_PGRAPH_TRAPPED_DATA_HIGH);
268         }
269         nsource = NV_READ(NV03_PGRAPH_NSOURCE);
270         nstatus = NV_READ(NV03_PGRAPH_NSTATUS);
271         if (dev_priv->card_type < NV_10) {
272                 class = NV_READ(0x400180 + subc*4) & 0xFF;
273         } else if (dev_priv->card_type < NV_40) {
274                 class = NV_READ(0x400160 + subc*4) & 0xFFF;
275         } else if (dev_priv->card_type < NV_50) {
276                 class = NV_READ(0x400160 + subc*4) & 0xFFFF;
277         } else {
278                 class = NV_READ(0x400814);
279         }
280
281         DRM_INFO("%s - nSource:", id);
282         nouveau_print_bitfield_names(nsource, nouveau_nsource_names,
283                                      ARRAY_SIZE(nouveau_nsource_names));
284         printk(", nStatus:");
285         if (dev_priv->card_type < NV_10)
286                 nouveau_print_bitfield_names(nstatus, nouveau_nstatus_names,
287                                      ARRAY_SIZE(nouveau_nstatus_names));
288         else
289                 nouveau_print_bitfield_names(nstatus, nouveau_nstatus_names_nv10,
290                                      ARRAY_SIZE(nouveau_nstatus_names_nv10));
291         printk("\n");
292
293         DRM_INFO("%s - Ch %d/%d Class 0x%04x Mthd 0x%04x Data 0x%08x:0x%08x\n",
294                  id, channel, subc, class, method, data2, data);
295 }
296
297 static inline void
298 nouveau_pgraph_intr_notify(struct drm_device *dev, uint32_t nsource)
299 {
300         struct drm_nouveau_private *dev_priv = dev->dev_private;
301         int handled = 0;
302
303         DRM_DEBUG("PGRAPH notify interrupt\n");
304         if (dev_priv->card_type == NV_04 &&
305             (nsource & NV03_PGRAPH_NSOURCE_ILLEGAL_MTHD)) {
306                 uint32_t class, mthd;
307
308                 /* NV4 (nvidia TNT 1) reports software methods with
309                  * PGRAPH NOTIFY ILLEGAL_MTHD
310                  */
311                 mthd = NV_READ(NV04_PGRAPH_TRAPPED_ADDR) & 0x1FFC;
312                 class = NV_READ(NV04_PGRAPH_CTX_SWITCH1) & 0xFFF;
313                 DRM_DEBUG("Got NV04 software method method %x for class %#x\n",
314                           mthd, class);
315
316                 if (nouveau_sw_method_execute(dev, class, mthd)) {
317                         DRM_ERROR("Unable to execute NV04 software method %x "
318                                   "for object class %x. Please report.\n",
319                                   mthd, class);
320                 } else {
321                         handled = 1;
322                 }
323         }
324
325         if (!handled)
326                 nouveau_graph_dump_trap_info(dev, "PGRAPH_NOTIFY");
327 }
328
329 static inline void
330 nouveau_pgraph_intr_error(struct drm_device *dev, uint32_t nsource)
331 {
332         nouveau_graph_dump_trap_info(dev, "PGRAPH_ERROR");
333 }
334
335 static inline void
336 nouveau_pgraph_intr_context_switch(struct drm_device *dev)
337 {
338         struct drm_nouveau_private *dev_priv = dev->dev_private;
339         uint32_t chid;
340         
341         chid = NV_READ(NV03_PFIFO_CACHE1_PUSH1) & (nouveau_fifo_number(dev)-1);
342         DRM_DEBUG("PGRAPH context switch interrupt channel %x\n", chid);
343
344         switch(dev_priv->card_type) {
345         case NV_04:
346         case NV_05:
347                 nouveau_nv04_context_switch(dev);
348                 break;
349         case NV_10:
350         case NV_11:
351         case NV_17:
352                 nouveau_nv10_context_switch(dev);
353                 break;
354         default:
355                 DRM_ERROR("Context switch not implemented\n");
356                 break;
357         }
358 }
359
360 static void
361 nouveau_pgraph_irq_handler(struct drm_device *dev)
362 {
363         struct drm_nouveau_private *dev_priv = dev->dev_private;
364         uint32_t status;
365
366         while ((status = NV_READ(NV03_PGRAPH_INTR))) {
367                 uint32_t nsource = NV_READ(NV03_PGRAPH_NSOURCE);
368
369                 if (status & NV_PGRAPH_INTR_NOTIFY) {
370                         nouveau_pgraph_intr_notify(dev, nsource);
371
372                         status &= ~NV_PGRAPH_INTR_NOTIFY;
373                         NV_WRITE(NV03_PGRAPH_INTR, NV_PGRAPH_INTR_NOTIFY);
374                 }
375
376                 if (status & NV_PGRAPH_INTR_ERROR) {
377                         nouveau_pgraph_intr_error(dev, nsource);
378
379                         status &= ~NV_PGRAPH_INTR_ERROR;
380                         NV_WRITE(NV03_PGRAPH_INTR, NV_PGRAPH_INTR_ERROR);
381                 }
382
383                 if (status & NV_PGRAPH_INTR_CONTEXT_SWITCH) {
384                         nouveau_pgraph_intr_context_switch(dev);
385
386                         status &= ~NV_PGRAPH_INTR_CONTEXT_SWITCH;
387                         NV_WRITE(NV03_PGRAPH_INTR,
388                                  NV_PGRAPH_INTR_CONTEXT_SWITCH);
389                 }
390
391                 if (status) {
392                         DRM_INFO("Unhandled PGRAPH_INTR - 0x%8x\n", status);
393                         NV_WRITE(NV03_PGRAPH_INTR, status);
394                 }
395
396                 if ((NV_READ(NV04_PGRAPH_FIFO) & (1 << 0)) == 0)
397                         NV_WRITE(NV04_PGRAPH_FIFO, 1);
398         }
399
400         NV_WRITE(NV03_PMC_INTR_0, NV_PMC_INTR_0_PGRAPH_PENDING);
401 }
402
403 static void
404 nouveau_crtc_irq_handler(struct drm_device *dev, int crtc)
405 {
406         struct drm_nouveau_private *dev_priv = dev->dev_private;
407
408         if (crtc&1) {
409                 NV_WRITE(NV_CRTC0_INTSTAT, NV_CRTC_INTR_VBLANK);
410         }
411
412         if (crtc&2) {
413                 NV_WRITE(NV_CRTC1_INTSTAT, NV_CRTC_INTR_VBLANK);
414         }
415 }
416
417 irqreturn_t
418 nouveau_irq_handler(DRM_IRQ_ARGS)
419 {
420         struct drm_device *dev = (struct drm_device*)arg;
421         struct drm_nouveau_private *dev_priv = dev->dev_private;
422         uint32_t status;
423
424         status = NV_READ(NV03_PMC_INTR_0);
425         if (!status)
426                 return IRQ_NONE;
427
428         if (status & NV_PMC_INTR_0_PFIFO_PENDING) {
429                 nouveau_fifo_irq_handler(dev);
430                 status &= ~NV_PMC_INTR_0_PFIFO_PENDING;
431         }
432
433         if (status & NV_PMC_INTR_0_PGRAPH_PENDING) {
434                 nouveau_pgraph_irq_handler(dev);
435                 status &= ~NV_PMC_INTR_0_PGRAPH_PENDING;
436         }
437
438         if (status & NV_PMC_INTR_0_CRTCn_PENDING) {
439                 nouveau_crtc_irq_handler(dev, (status>>24)&3);
440                 status &= ~NV_PMC_INTR_0_CRTCn_PENDING;
441         }
442
443         if (status)
444                 DRM_ERROR("Unhandled PMC INTR status bits 0x%08x\n", status);
445
446         return IRQ_HANDLED;
447 }
448