diff options
Diffstat (limited to 'drivers/gpu/drm/nouveau/nv50_gpio.c')
-rw-r--r-- | drivers/gpu/drm/nouveau/nv50_gpio.c | 37 |
1 files changed, 36 insertions, 1 deletions
diff --git a/drivers/gpu/drm/nouveau/nv50_gpio.c b/drivers/gpu/drm/nouveau/nv50_gpio.c index c61782b314e7..b2fab2bf3d61 100644 --- a/drivers/gpu/drm/nouveau/nv50_gpio.c +++ b/drivers/gpu/drm/nouveau/nv50_gpio.c @@ -31,7 +31,7 @@ nv50_gpio_location(struct dcb_gpio_entry *gpio, uint32_t *reg, uint32_t *shift) { const uint32_t nv50_gpio_reg[4] = { 0xe104, 0xe108, 0xe280, 0xe284 }; - if (gpio->line > 32) + if (gpio->line >= 32) return -EINVAL; *reg = nv50_gpio_reg[gpio->line >> 3]; @@ -74,3 +74,38 @@ 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); +} + +int +nv50_gpio_init(struct drm_device *dev) +{ + struct drm_nouveau_private *dev_priv = dev->dev_private; + + /* disable, and ack any pending gpio interrupts */ + 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; +} |