drm/nv50: add function to control GPIO IRQ reporting
authorBen Skeggs <bskeggs@redhat.com>
Fri, 23 Jul 2010 01:31:08 +0000 (11:31 +1000)
committerBen Skeggs <bskeggs@redhat.com>
Mon, 26 Jul 2010 01:42:59 +0000 (11:42 +1000)
Signed-off-by: Ben Skeggs <bskeggs@redhat.com>
drivers/gpu/drm/nouveau/nouveau_drv.h
drivers/gpu/drm/nouveau/nv50_display.c
drivers/gpu/drm/nouveau/nv50_gpio.c
drivers/gpu/drm/nouveau/nv50_mc.c

index 9d53f3d..6b24186 100644 (file)
@@ -1140,6 +1140,7 @@ int nv17_gpio_set(struct drm_device *dev, enum dcb_gpio_tag tag, int state);
 /* nv50_gpio.c */
 int nv50_gpio_get(struct drm_device *dev, enum dcb_gpio_tag tag);
 int nv50_gpio_set(struct drm_device *dev, enum dcb_gpio_tag tag, int state);
+void nv50_gpio_irq_enable(struct drm_device *, enum dcb_gpio_tag, bool on);
 
 /* nv50_calc. */
 int nv50_calc_pll(struct drm_device *, struct pll_lims *, int clk,
index c19ed8c..fbd91c2 100644 (file)
@@ -184,7 +184,7 @@ nv50_display_init(struct drm_device *dev)
        struct nouveau_timer_engine *ptimer = &dev_priv->engine.timer;
        struct nouveau_channel *evo = dev_priv->evo;
        struct drm_connector *connector;
-       uint32_t val, ram_amount, hpd_en[2];
+       uint32_t val, ram_amount;
        uint64_t start;
        int ret, i;
 
@@ -365,26 +365,10 @@ nv50_display_init(struct drm_device *dev)
                                             NV50_PDISPLAY_INTR_EN_CLK_UNK40));
 
        /* enable hotplug interrupts */
-       hpd_en[0] = hpd_en[1] = 0;
        list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
                struct nouveau_connector *conn = nouveau_connector(connector);
-               struct dcb_gpio_entry *gpio;
-
-               if (conn->dcb->gpio_tag == 0xff)
-                       continue;
-
-               gpio = nouveau_bios_gpio_entry(dev, conn->dcb->gpio_tag);
-               if (!gpio)
-                       continue;
 
-               hpd_en[gpio->line >> 4] |= (0x00010001 << (gpio->line & 0xf));
-       }
-
-       nv_wr32(dev, 0xe054, 0xffffffff);
-       nv_wr32(dev, 0xe050, hpd_en[0]);
-       if (dev_priv->chipset >= 0x90) {
-               nv_wr32(dev, 0xe074, 0xffffffff);
-               nv_wr32(dev, 0xe070, hpd_en[1]);
+               nv50_gpio_irq_enable(dev, conn->dcb->gpio_tag, true);
        }
 
        return 0;
index bb47ad7..88715c5 100644 (file)
@@ -74,3 +74,22 @@ nv50_gpio_set(struct drm_device *dev, enum dcb_gpio_tag tag, int state)
        nv_wr32(dev, r, v);
        return 0;
 }
+
+void
+nv50_gpio_irq_enable(struct drm_device *dev, enum dcb_gpio_tag tag, bool on)
+{
+       struct dcb_gpio_entry *gpio;
+       u32 reg, mask;
+
+       gpio = nouveau_bios_gpio_entry(dev, tag);
+       if (!gpio) {
+               NV_ERROR(dev, "gpio tag 0x%02x not found\n", tag);
+               return;
+       }
+
+       reg  = gpio->line < 16 ? 0xe050 : 0xe070;
+       mask = 0x00010001 << (gpio->line & 0xf);
+
+       nv_wr32(dev, reg + 4, mask);
+       nv_mask(dev, reg + 0, mask, on ? mask : 0);
+}
index e0a9c3f..f680e8e 100644 (file)
 int
 nv50_mc_init(struct drm_device *dev)
 {
+       struct drm_nouveau_private *dev_priv = dev->dev_private;
+
        nv_wr32(dev, NV03_PMC_ENABLE, 0xFFFFFFFF);
+
+       /* disable, and ack any pending gpio interrupts
+        * XXX doesn't technically belong here, but it'll do for the moment
+        */
+       nv_wr32(dev, 0xe050, 0x00000000);
+       nv_wr32(dev, 0xe054, 0xffffffff);
+       if (dev_priv->chipset >= 0x90) {
+               nv_wr32(dev, 0xe070, 0x00000000);
+               nv_wr32(dev, 0xe074, 0xffffffff);
+       }
+
        return 0;
 }