drm/nv40/disp: implement support for hotplug irq
authorBen Skeggs <bskeggs@redhat.com>
Tue, 22 Nov 2011 03:49:22 +0000 (13:49 +1000)
committerBen Skeggs <bskeggs@redhat.com>
Wed, 21 Dec 2011 09:01:45 +0000 (19:01 +1000)
Signed-off-by: Ben Skeggs <bskeggs@redhat.com>
drivers/gpu/drm/nouveau/nouveau_state.c
drivers/gpu/drm/nouveau/nv04_display.c
drivers/gpu/drm/nouveau/nv10_gpio.c

index c4edba6..57ccda4 100644 (file)
@@ -273,8 +273,11 @@ static int nouveau_init_engine_ptrs(struct drm_device *dev)
                engine->display.destroy         = nv04_display_destroy;
                engine->display.init            = nv04_display_init;
                engine->display.fini            = nv04_display_fini;
+               engine->gpio.init               = nv10_gpio_init;
+               engine->gpio.fini               = nv10_gpio_fini;
                engine->gpio.drive              = nv10_gpio_drive;
                engine->gpio.sense              = nv10_gpio_sense;
+               engine->gpio.irq_enable         = nv10_gpio_irq_enable;
                engine->pm.clocks_get           = nv40_pm_clocks_get;
                engine->pm.clocks_pre           = nv40_pm_clocks_pre;
                engine->pm.clocks_set           = nv40_pm_clocks_set;
index 7047d37..15b748f 100644 (file)
@@ -31,6 +31,7 @@
 #include "nouveau_hw.h"
 #include "nouveau_encoder.h"
 #include "nouveau_connector.h"
+#include "nouveau_gpio.h"
 
 static void nv04_vblank_crtc0_isr(struct drm_device *);
 static void nv04_vblank_crtc1_isr(struct drm_device *);
@@ -220,6 +221,7 @@ nv04_display_destroy(struct drm_device *dev)
 int
 nv04_display_init(struct drm_device *dev)
 {
+       struct drm_connector *connector;
        struct drm_encoder *encoder;
        struct drm_crtc *crtc;
 
@@ -240,6 +242,12 @@ nv04_display_init(struct drm_device *dev)
        list_for_each_entry(crtc, &dev->mode_config.crtc_list, head)
                crtc->funcs->restore(crtc);
 
+       /* enable hotplug interrupts */
+       list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
+               struct nouveau_connector *conn = nouveau_connector(connector);
+               nouveau_gpio_irq(dev, 0, conn->hpd, 0xff, true);
+       }
+
        return 0;
 }
 
index 419d649..550ad3f 100644 (file)
@@ -27,6 +27,7 @@
 #include "drmP.h"
 #include "nouveau_drv.h"
 #include "nouveau_hw.h"
+#include "nouveau_gpio.h"
 
 int
 nv10_gpio_sense(struct drm_device *dev, int line)
@@ -80,3 +81,43 @@ nv10_gpio_drive(struct drm_device *dev, int line, int dir, int out)
        NVWriteCRTC(dev, 0, reg, mask | (data << line));
        return 0;
 }
+
+void
+nv10_gpio_irq_enable(struct drm_device *dev, int line, bool on)
+{
+       u32 mask = 0x00010001 << line;
+
+       nv_wr32(dev, 0x001104, mask);
+       nv_mask(dev, 0x001144, mask, on ? mask : 0);
+}
+
+static void
+nv10_gpio_isr(struct drm_device *dev)
+{
+       u32 intr = nv_rd32(dev, 0x1104);
+       u32 hi = (intr & 0x0000ffff) >> 0;
+       u32 lo = (intr & 0xffff0000) >> 16;
+
+       nouveau_gpio_isr(dev, 0, hi | lo);
+
+       nv_wr32(dev, 0x001104, intr);
+}
+
+int
+nv10_gpio_init(struct drm_device *dev)
+{
+       nv_wr32(dev, 0x001140, 0x00000000);
+       nv_wr32(dev, 0x001100, 0xffffffff);
+       nv_wr32(dev, 0x001144, 0x00000000);
+       nv_wr32(dev, 0x001104, 0xffffffff);
+       nouveau_irq_register(dev, 28, nv10_gpio_isr); /* PBUS */
+       return 0;
+}
+
+void
+nv10_gpio_fini(struct drm_device *dev)
+{
+       nv_wr32(dev, 0x001140, 0x00000000);
+       nv_wr32(dev, 0x001144, 0x00000000);
+       nouveau_irq_unregister(dev, 28);
+}