]> git.karo-electronics.de Git - mv-sheeva.git/blobdiff - drivers/gpu/drm/nouveau/nv50_display.c
drm/nv50: improve evo error handler when more than just channel 0 active
[mv-sheeva.git] / drivers / gpu / drm / nouveau / nv50_display.c
index db100a8f231e05dfa06fddd5ee74f0a032023ef2..99871e304d106c46b954388207e41e05cd9ed60b 100644 (file)
@@ -149,13 +149,13 @@ nv50_display_init(struct drm_device *dev)
        }
 
        nv_wr32(dev, NV50_PDISPLAY_PIO_CTRL, 0x00000000);
-       nv_wr32(dev, 0x610028, 0x00000000);
        nv_mask(dev, NV50_PDISPLAY_INTR_0, 0x00000000, 0x00000000);
+       nv_wr32(dev, NV50_PDISPLAY_INTR_EN_0, 0x00000000);
        nv_mask(dev, NV50_PDISPLAY_INTR_1, 0x00000000, 0x00000000);
-       nv_wr32(dev, NV50_PDISPLAY_INTR_EN,
-                    NV50_PDISPLAY_INTR_EN_CLK_UNK10 |
-                    NV50_PDISPLAY_INTR_EN_CLK_UNK20 |
-                    NV50_PDISPLAY_INTR_EN_CLK_UNK40);
+       nv_wr32(dev, NV50_PDISPLAY_INTR_EN_1,
+                    NV50_PDISPLAY_INTR_EN_1_CLK_UNK10 |
+                    NV50_PDISPLAY_INTR_EN_1_CLK_UNK20 |
+                    NV50_PDISPLAY_INTR_EN_1_CLK_UNK40);
 
        /* enable hotplug interrupts */
        list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
@@ -248,7 +248,7 @@ static int nv50_display_disable(struct drm_device *dev)
        }
 
        /* disable interrupts. */
-       nv_wr32(dev, NV50_PDISPLAY_INTR_EN, 0x00000000);
+       nv_wr32(dev, NV50_PDISPLAY_INTR_EN_1, 0x00000000);
 
        /* disable hotplug interrupts */
        nv_wr32(dev, 0xe054, 0xffffffff);
@@ -451,8 +451,7 @@ nv50_display_vblank_handler(struct drm_device *dev, uint32_t intr)
        if (intr & NV50_PDISPLAY_INTR_1_VBLANK_CRTC_1)
                nv50_display_vblank_crtc_handler(dev, 1);
 
-       nv_wr32(dev, NV50_PDISPLAY_INTR_EN, nv_rd32(dev,
-                    NV50_PDISPLAY_INTR_EN) & ~intr);
+       nv_mask(dev, NV50_PDISPLAY_INTR_EN_1, intr, 0x00000000);
        nv_wr32(dev, NV50_PDISPLAY_INTR_1, intr);
 }
 
@@ -779,16 +778,23 @@ nv50_display_irq_handler_bh(struct work_struct *work)
 static void
 nv50_display_error_handler(struct drm_device *dev)
 {
-       uint32_t addr, data;
+       u32 channels = (nv_rd32(dev, NV50_PDISPLAY_INTR_0) & 0x001f0000) >> 16;
+       u32 addr, data;
+       int chid;
 
-       nv_wr32(dev, NV50_PDISPLAY_INTR_0, 0x00010000);
-       addr = nv_rd32(dev, NV50_PDISPLAY_TRAPPED_ADDR);
-       data = nv_rd32(dev, NV50_PDISPLAY_TRAPPED_DATA);
+       for (chid = 0; chid < 5; chid++) {
+               if (!(channels & (1 << chid)))
+                       continue;
 
-       NV_ERROR(dev, "EvoCh %d Mthd 0x%04x Data 0x%08x (0x%04x 0x%02x)\n",
-                0, addr & 0xffc, data, addr >> 16, (addr >> 12) & 0xf);
+               nv_wr32(dev, NV50_PDISPLAY_INTR_0, 0x00010000 << chid);
+               addr = nv_rd32(dev, NV50_PDISPLAY_TRAPPED_ADDR(chid));
+               data = nv_rd32(dev, NV50_PDISPLAY_TRAPPED_DATA(chid));
+               NV_ERROR(dev, "EvoCh %d Mthd 0x%04x Data 0x%08x "
+                             "(0x%04x 0x%02x)\n", chid,
+                        addr & 0xffc, data, addr >> 16, (addr >> 12) & 0xf);
 
-       nv_wr32(dev, NV50_PDISPLAY_TRAPPED_ADDR, 0x90000000);
+               nv_wr32(dev, NV50_PDISPLAY_TRAPPED_ADDR(chid), 0x90000000);
+       }
 }
 
 void
@@ -891,9 +897,9 @@ nv50_display_irq_handler(struct drm_device *dev)
                if (!intr0 && !(intr1 & ~delayed))
                        break;
 
-               if (intr0 & 0x00010000) {
+               if (intr0 & 0x001f0000) {
                        nv50_display_error_handler(dev);
-                       intr0 &= ~0x00010000;
+                       intr0 &= ~0x001f0000;
                }
 
                if (intr1 & NV50_PDISPLAY_INTR_1_VBLANK_CRTC) {