summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBen Skeggs <bskeggs@redhat.com>2011-11-22 13:49:22 +1000
committerBen Skeggs <bskeggs@redhat.com>2011-12-21 19:01:45 +1000
commit47e5d5cb83d4b41168f4afa1ca32843d4a126cc8 (patch)
tree4081ca722b80a39dffc0b64b4e23fc1abd6181a3
parenta0b25635515ef5049f93b032a1e37f18b16e0f6f (diff)
drm/nv40/disp: implement support for hotplug irq
Signed-off-by: Ben Skeggs <bskeggs@redhat.com>
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_state.c3
-rw-r--r--drivers/gpu/drm/nouveau/nv04_display.c8
-rw-r--r--drivers/gpu/drm/nouveau/nv10_gpio.c41
3 files changed, 52 insertions, 0 deletions
diff --git a/drivers/gpu/drm/nouveau/nouveau_state.c b/drivers/gpu/drm/nouveau/nouveau_state.c
index c4edba6a457d..57ccda47a70b 100644
--- a/drivers/gpu/drm/nouveau/nouveau_state.c
+++ b/drivers/gpu/drm/nouveau/nouveau_state.c
@@ -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;
diff --git a/drivers/gpu/drm/nouveau/nv04_display.c b/drivers/gpu/drm/nouveau/nv04_display.c
index 7047d37e8dab..15b748f0ea4b 100644
--- a/drivers/gpu/drm/nouveau/nv04_display.c
+++ b/drivers/gpu/drm/nouveau/nv04_display.c
@@ -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;
}
diff --git a/drivers/gpu/drm/nouveau/nv10_gpio.c b/drivers/gpu/drm/nouveau/nv10_gpio.c
index 419d6495649b..550ad3fcf0af 100644
--- a/drivers/gpu/drm/nouveau/nv10_gpio.c
+++ b/drivers/gpu/drm/nouveau/nv10_gpio.c
@@ -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);
+}