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 "nouveau_swmthd.h"
41 nouveau_irq_preinstall(struct drm_device *dev)
43 struct drm_nouveau_private *dev_priv = dev->dev_private;
46 NV_WRITE(NV03_PMC_INTR_EN_0, 0);
50 nouveau_irq_postinstall(struct drm_device *dev)
52 struct drm_nouveau_private *dev_priv = dev->dev_private;
55 NV_WRITE(NV03_PMC_INTR_EN_0, NV_PMC_INTR_EN_0_MASTER_ENABLE);
61 nouveau_irq_uninstall(struct drm_device *dev)
63 struct drm_nouveau_private *dev_priv = dev->dev_private;
66 NV_WRITE(NV03_PMC_INTR_EN_0, 0);
70 nouveau_fifo_irq_handler(struct drm_device *dev)
72 struct drm_nouveau_private *dev_priv = dev->dev_private;
73 struct nouveau_engine *engine = &dev_priv->Engine;
74 uint32_t status, reassign;
76 reassign = NV_READ(NV03_PFIFO_CACHES) & 1;
77 while ((status = NV_READ(NV03_PFIFO_INTR_0))) {
80 NV_WRITE(NV03_PFIFO_CACHES, 0);
82 chid = engine->fifo.channel_id(dev);
83 get = NV_READ(NV03_PFIFO_CACHE1_GET);
85 if (status & NV_PFIFO_INTR_CACHE_ERROR) {
90 if (dev_priv->card_type < NV_40) {
91 mthd = NV_READ(NV04_PFIFO_CACHE1_METHOD(ptr));
92 data = NV_READ(NV04_PFIFO_CACHE1_DATA(ptr));
94 mthd = NV_READ(NV40_PFIFO_CACHE1_METHOD(ptr));
95 data = NV_READ(NV40_PFIFO_CACHE1_DATA(ptr));
98 DRM_INFO("PFIFO_CACHE_ERROR - "
99 "Ch %d/%d Mthd 0x%04x Data 0x%08x\n",
100 chid, (mthd >> 13) & 7, mthd & 0x1ffc, data);
102 NV_WRITE(NV03_PFIFO_CACHE1_GET, get + 4);
103 NV_WRITE(NV04_PFIFO_CACHE1_PULL0, 1);
105 status &= ~NV_PFIFO_INTR_CACHE_ERROR;
106 NV_WRITE(NV03_PFIFO_INTR_0, NV_PFIFO_INTR_CACHE_ERROR);
109 if (status & NV_PFIFO_INTR_DMA_PUSHER) {
110 DRM_INFO("PFIFO_DMA_PUSHER - Ch %d\n", chid);
112 status &= ~NV_PFIFO_INTR_DMA_PUSHER;
113 NV_WRITE(NV03_PFIFO_INTR_0, NV_PFIFO_INTR_DMA_PUSHER);
115 NV_WRITE(NV04_PFIFO_CACHE1_DMA_STATE, 0x00000000);
116 if (NV_READ(NV04_PFIFO_CACHE1_DMA_PUT) != get)
117 NV_WRITE(NV04_PFIFO_CACHE1_DMA_GET, get + 4);
121 DRM_INFO("Unhandled PFIFO_INTR - 0x%08x\n", status);
122 NV_WRITE(NV03_PFIFO_INTR_0, status);
123 NV_WRITE(NV03_PMC_INTR_EN_0, 0);
126 NV_WRITE(NV03_PFIFO_CACHES, reassign);
129 NV_WRITE(NV03_PMC_INTR_0, NV_PMC_INTR_0_PFIFO_PENDING);
132 struct nouveau_bitfield_names {
137 static struct nouveau_bitfield_names nouveau_nstatus_names[] =
139 { NV04_PGRAPH_NSTATUS_STATE_IN_USE, "STATE_IN_USE" },
140 { NV04_PGRAPH_NSTATUS_INVALID_STATE, "INVALID_STATE" },
141 { NV04_PGRAPH_NSTATUS_BAD_ARGUMENT, "BAD_ARGUMENT" },
142 { NV04_PGRAPH_NSTATUS_PROTECTION_FAULT, "PROTECTION_FAULT" }
145 static struct nouveau_bitfield_names nouveau_nstatus_names_nv10[] =
147 { NV10_PGRAPH_NSTATUS_STATE_IN_USE, "STATE_IN_USE" },
148 { NV10_PGRAPH_NSTATUS_INVALID_STATE, "INVALID_STATE" },
149 { NV10_PGRAPH_NSTATUS_BAD_ARGUMENT, "BAD_ARGUMENT" },
150 { NV10_PGRAPH_NSTATUS_PROTECTION_FAULT, "PROTECTION_FAULT" }
153 static struct nouveau_bitfield_names nouveau_nsource_names[] =
155 { NV03_PGRAPH_NSOURCE_NOTIFICATION, "NOTIFICATION" },
156 { NV03_PGRAPH_NSOURCE_DATA_ERROR, "DATA_ERROR" },
157 { NV03_PGRAPH_NSOURCE_PROTECTION_ERROR, "PROTECTION_ERROR" },
158 { NV03_PGRAPH_NSOURCE_RANGE_EXCEPTION, "RANGE_EXCEPTION" },
159 { NV03_PGRAPH_NSOURCE_LIMIT_COLOR, "LIMIT_COLOR" },
160 { NV03_PGRAPH_NSOURCE_LIMIT_ZETA, "LIMIT_ZETA" },
161 { NV03_PGRAPH_NSOURCE_ILLEGAL_MTHD, "ILLEGAL_MTHD" },
162 { NV03_PGRAPH_NSOURCE_DMA_R_PROTECTION, "DMA_R_PROTECTION" },
163 { NV03_PGRAPH_NSOURCE_DMA_W_PROTECTION, "DMA_W_PROTECTION" },
164 { NV03_PGRAPH_NSOURCE_FORMAT_EXCEPTION, "FORMAT_EXCEPTION" },
165 { NV03_PGRAPH_NSOURCE_PATCH_EXCEPTION, "PATCH_EXCEPTION" },
166 { NV03_PGRAPH_NSOURCE_STATE_INVALID, "STATE_INVALID" },
167 { NV03_PGRAPH_NSOURCE_DOUBLE_NOTIFY, "DOUBLE_NOTIFY" },
168 { NV03_PGRAPH_NSOURCE_NOTIFY_IN_USE, "NOTIFY_IN_USE" },
169 { NV03_PGRAPH_NSOURCE_METHOD_CNT, "METHOD_CNT" },
170 { NV03_PGRAPH_NSOURCE_BFR_NOTIFICATION, "BFR_NOTIFICATION" },
171 { NV03_PGRAPH_NSOURCE_DMA_VTX_PROTECTION, "DMA_VTX_PROTECTION" },
172 { NV03_PGRAPH_NSOURCE_DMA_WIDTH_A, "DMA_WIDTH_A" },
173 { NV03_PGRAPH_NSOURCE_DMA_WIDTH_B, "DMA_WIDTH_B" },
177 nouveau_print_bitfield_names(uint32_t value,
178 const struct nouveau_bitfield_names *namelist,
179 const int namelist_len)
182 for(i=0; i<namelist_len; ++i) {
183 uint32_t mask = namelist[i].mask;
185 printk(" %s", namelist[i].name);
190 printk(" (unknown bits 0x%08x)", value);
194 nouveau_graph_chid_from_grctx(struct drm_device *dev)
196 struct drm_nouveau_private *dev_priv = dev->dev_private;
200 if (dev_priv->card_type < NV_40)
201 return dev_priv->Engine.fifo.channels;
203 if (dev_priv->card_type < NV_50)
204 inst = (NV_READ(0x40032c) & 0xfffff) << 4;
206 inst = NV_READ(0x40032c) & 0xfffff;
208 for (i = 0; i < dev_priv->Engine.fifo.channels; i++) {
209 struct nouveau_channel *chan = dev_priv->fifos[i];
211 if (!chan || !chan->ramin_grctx)
214 if (dev_priv->card_type < NV_50) {
215 if (inst == chan->ramin_grctx->instance)
218 if (inst == INSTANCE_RD(chan->ramin_grctx->gpuobj, 0))
227 nouveau_graph_trapped_channel(struct drm_device *dev, int *channel_ret)
229 struct drm_nouveau_private *dev_priv = dev->dev_private;
230 struct nouveau_engine *engine = &dev_priv->Engine;
233 if (dev_priv->card_type < NV_10)
234 channel = (NV_READ(NV04_PGRAPH_TRAPPED_ADDR) >> 24) & 0xf;
236 if (dev_priv->card_type < NV_40)
237 channel = (NV_READ(NV04_PGRAPH_TRAPPED_ADDR) >> 20) & 0x1f;
239 channel = nouveau_graph_chid_from_grctx(dev);
241 if (channel >= engine->fifo.channels || !dev_priv->fifos[channel]) {
242 DRM_ERROR("AIII, invalid/inactive channel id %d\n", channel);
246 *channel_ret = channel;
250 struct nouveau_pgraph_trap {
253 int subc, mthd, size;
254 uint32_t data, data2;
255 uint32_t nsource, nstatus;
259 nouveau_graph_trap_info(struct drm_device *dev,
260 struct nouveau_pgraph_trap *trap)
262 struct drm_nouveau_private *dev_priv = dev->dev_private;
265 trap->nsource = trap->nstatus = 0;
266 if (dev_priv->card_type < NV_50) {
267 trap->nsource = NV_READ(NV03_PGRAPH_NSOURCE);
268 trap->nstatus = NV_READ(NV03_PGRAPH_NSTATUS);
271 if (nouveau_graph_trapped_channel(dev, &trap->channel))
273 address = NV_READ(NV04_PGRAPH_TRAPPED_ADDR);
275 trap->mthd = address & 0x1FFC;
276 trap->data = NV_READ(NV04_PGRAPH_TRAPPED_DATA);
277 if (dev_priv->card_type < NV_10) {
278 trap->subc = (address >> 13) & 0x7;
280 trap->subc = (address >> 16) & 0x7;
281 trap->data2 = NV_READ(NV10_PGRAPH_TRAPPED_DATA_HIGH);
284 if (dev_priv->card_type < NV_10) {
285 trap->class = NV_READ(0x400180 + trap->subc*4) & 0xFF;
286 } else if (dev_priv->card_type < NV_40) {
287 trap->class = NV_READ(0x400160 + trap->subc*4) & 0xFFF;
288 } else if (dev_priv->card_type < NV_50) {
289 trap->class = NV_READ(0x400160 + trap->subc*4) & 0xFFFF;
291 trap->class = NV_READ(0x400814);
296 nouveau_graph_dump_trap_info(struct drm_device *dev, const char *id,
297 struct nouveau_pgraph_trap *trap)
299 struct drm_nouveau_private *dev_priv = dev->dev_private;
300 uint32_t nsource = trap->nsource, nstatus = trap->nstatus;
302 DRM_INFO("%s - nSource:", id);
303 nouveau_print_bitfield_names(nsource, nouveau_nsource_names,
304 ARRAY_SIZE(nouveau_nsource_names));
305 printk(", nStatus:");
306 if (dev_priv->card_type < NV_10)
307 nouveau_print_bitfield_names(nstatus, nouveau_nstatus_names,
308 ARRAY_SIZE(nouveau_nstatus_names));
310 nouveau_print_bitfield_names(nstatus, nouveau_nstatus_names_nv10,
311 ARRAY_SIZE(nouveau_nstatus_names_nv10));
314 DRM_INFO("%s - Ch %d/%d Class 0x%04x Mthd 0x%04x Data 0x%08x:0x%08x\n",
315 id, trap->channel, trap->subc, trap->class, trap->mthd,
316 trap->data2, trap->data);
320 nouveau_pgraph_intr_notify(struct drm_device *dev, uint32_t nsource)
322 struct nouveau_pgraph_trap trap;
325 nouveau_graph_trap_info(dev, &trap);
327 if (nsource & NV03_PGRAPH_NSOURCE_ILLEGAL_MTHD) {
328 /* NV4 (nvidia TNT 1) reports software methods with
329 * PGRAPH NOTIFY ILLEGAL_MTHD
331 DRM_DEBUG("Got NV04 software method method %x for class %#x\n",
332 trap.mthd, trap.class);
334 if (nouveau_sw_method_execute(dev, trap.class, trap.mthd)) {
335 DRM_ERROR("Unable to execute NV04 software method %x "
336 "for object class %x. Please report.\n",
337 trap.mthd, trap.class);
345 nouveau_graph_dump_trap_info(dev, "PGRAPH_NOTIFY", &trap);
349 nouveau_pgraph_intr_error(struct drm_device *dev, uint32_t nsource)
351 struct nouveau_pgraph_trap trap;
354 nouveau_graph_trap_info(dev, &trap);
355 trap.nsource = nsource;
357 if (nsource & NV03_PGRAPH_NSOURCE_ILLEGAL_MTHD) {
358 if (trap.channel >= 0 && trap.mthd == 0x0150) {
359 nouveau_fence_handler(dev, trap.channel);
361 if (nouveau_sw_method_execute(dev, trap.class, trap.mthd)) {
369 nouveau_graph_dump_trap_info(dev, "PGRAPH_ERROR", &trap);
373 nouveau_pgraph_intr_context_switch(struct drm_device *dev)
375 struct drm_nouveau_private *dev_priv = dev->dev_private;
376 struct nouveau_engine *engine = &dev_priv->Engine;
379 chid = engine->fifo.channel_id(dev);
380 DRM_DEBUG("PGRAPH context switch interrupt channel %x\n", chid);
382 switch(dev_priv->card_type) {
385 nouveau_nv04_context_switch(dev);
390 nouveau_nv10_context_switch(dev);
393 DRM_ERROR("Context switch not implemented\n");
399 nouveau_pgraph_irq_handler(struct drm_device *dev)
401 struct drm_nouveau_private *dev_priv = dev->dev_private;
404 while ((status = NV_READ(NV03_PGRAPH_INTR))) {
405 uint32_t nsource = NV_READ(NV03_PGRAPH_NSOURCE);
407 if (status & NV_PGRAPH_INTR_NOTIFY) {
408 nouveau_pgraph_intr_notify(dev, nsource);
410 status &= ~NV_PGRAPH_INTR_NOTIFY;
411 NV_WRITE(NV03_PGRAPH_INTR, NV_PGRAPH_INTR_NOTIFY);
414 if (status & NV_PGRAPH_INTR_ERROR) {
415 nouveau_pgraph_intr_error(dev, nsource);
417 status &= ~NV_PGRAPH_INTR_ERROR;
418 NV_WRITE(NV03_PGRAPH_INTR, NV_PGRAPH_INTR_ERROR);
421 if (status & NV_PGRAPH_INTR_CONTEXT_SWITCH) {
422 nouveau_pgraph_intr_context_switch(dev);
424 status &= ~NV_PGRAPH_INTR_CONTEXT_SWITCH;
425 NV_WRITE(NV03_PGRAPH_INTR,
426 NV_PGRAPH_INTR_CONTEXT_SWITCH);
430 DRM_INFO("Unhandled PGRAPH_INTR - 0x%08x\n", status);
431 NV_WRITE(NV03_PGRAPH_INTR, status);
434 if ((NV_READ(NV04_PGRAPH_FIFO) & (1 << 0)) == 0)
435 NV_WRITE(NV04_PGRAPH_FIFO, 1);
438 NV_WRITE(NV03_PMC_INTR_0, NV_PMC_INTR_0_PGRAPH_PENDING);
442 nv50_pgraph_irq_handler(struct drm_device *dev)
444 struct drm_nouveau_private *dev_priv = dev->dev_private;
447 status = NV_READ(NV03_PGRAPH_INTR);
449 if (status & 0x00000020) {
450 nouveau_pgraph_intr_error(dev,
451 NV03_PGRAPH_NSOURCE_ILLEGAL_MTHD);
453 status &= ~0x00000020;
454 NV_WRITE(NV03_PGRAPH_INTR, 0x00000020);
457 if (status & 0x00100000) {
458 nouveau_pgraph_intr_error(dev,
459 NV03_PGRAPH_NSOURCE_DATA_ERROR);
461 status &= ~0x00100000;
462 NV_WRITE(NV03_PGRAPH_INTR, 0x00100000);
465 if (status & 0x00200000) {
466 nouveau_pgraph_intr_error(dev,
467 NV03_PGRAPH_NSOURCE_PROTECTION_ERROR);
469 status &= ~0x00200000;
470 NV_WRITE(NV03_PGRAPH_INTR, 0x00200000);
474 DRM_INFO("Unhandled PGRAPH_INTR - 0x%08x\n", status);
475 NV_WRITE(NV03_PGRAPH_INTR, status);
478 if ((NV_READ(0x400500) & (1 << 16)) == 0)
479 NV_WRITE(0x400500, NV_READ(0x400500) | (1 << 16));
481 NV_WRITE(NV03_PMC_INTR_0, NV_PMC_INTR_0_PGRAPH_PENDING);
485 nouveau_crtc_irq_handler(struct drm_device *dev, int crtc)
487 struct drm_nouveau_private *dev_priv = dev->dev_private;
490 NV_WRITE(NV_CRTC0_INTSTAT, NV_CRTC_INTR_VBLANK);
494 NV_WRITE(NV_CRTC1_INTSTAT, NV_CRTC_INTR_VBLANK);
499 nouveau_nv50_display_irq_handler(struct drm_device *dev)
501 struct drm_nouveau_private *dev_priv = dev->dev_private;
502 uint32_t val = NV_READ(NV50_DISPLAY_SUPERVISOR);
504 DRM_INFO("NV50_DISPLAY_INTR - 0x%08X\n", val);
506 NV_WRITE(NV50_DISPLAY_SUPERVISOR, val);
510 nouveau_nv50_i2c_irq_handler(struct drm_device *dev)
512 struct drm_nouveau_private *dev_priv = dev->dev_private;
514 DRM_INFO("NV50_I2C_INTR - 0x%08X\n", NV_READ(NV50_I2C_CONTROLLER));
516 /* This seems to be the way to acknowledge an interrupt. */
517 NV_WRITE(NV50_I2C_CONTROLLER, 0x7FFF7FFF);
521 nouveau_irq_handler(DRM_IRQ_ARGS)
523 struct drm_device *dev = (struct drm_device*)arg;
524 struct drm_nouveau_private *dev_priv = dev->dev_private;
527 status = NV_READ(NV03_PMC_INTR_0);
531 if (status & NV_PMC_INTR_0_PFIFO_PENDING) {
532 nouveau_fifo_irq_handler(dev);
533 status &= ~NV_PMC_INTR_0_PFIFO_PENDING;
536 if (status & NV_PMC_INTR_0_PGRAPH_PENDING) {
537 if (dev_priv->card_type >= NV_50)
538 nv50_pgraph_irq_handler(dev);
540 nouveau_pgraph_irq_handler(dev);
542 status &= ~NV_PMC_INTR_0_PGRAPH_PENDING;
545 if (status & NV_PMC_INTR_0_CRTCn_PENDING) {
546 nouveau_crtc_irq_handler(dev, (status>>24)&3);
547 status &= ~NV_PMC_INTR_0_CRTCn_PENDING;
550 if (status & NV_PMC_INTR_0_NV50_DISPLAY_PENDING) {
551 nouveau_nv50_display_irq_handler(dev);
552 status &= ~NV_PMC_INTR_0_NV50_DISPLAY_PENDING;
555 if (status & NV_PMC_INTR_0_NV50_I2C_PENDING) {
556 nouveau_nv50_i2c_irq_handler(dev);
557 status &= ~NV_PMC_INTR_0_NV50_I2C_PENDING;
561 DRM_ERROR("Unhandled PMC INTR status bits 0x%08x\n", status);