diff options
Diffstat (limited to 'drivers/gpu/drm/nouveau/core/subdev/gpio/base.c')
-rw-r--r-- | drivers/gpu/drm/nouveau/core/subdev/gpio/base.c | 42 |
1 files changed, 39 insertions, 3 deletions
diff --git a/drivers/gpu/drm/nouveau/core/subdev/gpio/base.c b/drivers/gpu/drm/nouveau/core/subdev/gpio/base.c index 20cb5f2..dbf9b5d0 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/gpio/base.c +++ b/drivers/gpu/drm/nouveau/core/subdev/gpio/base.c @@ -103,6 +103,37 @@ nouveau_gpio_get(struct nouveau_gpio *gpio, int idx, u8 tag, u8 line) return ret; } +static void +nouveau_gpio_intr_disable(struct nouveau_event *event, int type, int index) +{ + struct nouveau_gpio *gpio = nouveau_gpio(event->priv); + const struct nouveau_gpio_impl *impl = (void *)nv_object(gpio)->oclass; + impl->intr_mask(gpio, NVKM_GPIO_TOGGLED, 1 << index, 0); +} + +static void +nouveau_gpio_intr_enable(struct nouveau_event *event, int type, int index) +{ + struct nouveau_gpio *gpio = nouveau_gpio(event->priv); + const struct nouveau_gpio_impl *impl = (void *)nv_object(gpio)->oclass; + impl->intr_mask(gpio, NVKM_GPIO_TOGGLED, 1 << index, 1 << index); +} + +static void +nouveau_gpio_intr(struct nouveau_subdev *subdev) +{ + struct nouveau_gpio *gpio = nouveau_gpio(subdev); + const struct nouveau_gpio_impl *impl = (void *)nv_object(gpio)->oclass; + u32 hi, lo, i; + + impl->intr_stat(gpio, &hi, &lo); + + for (i = 0; (hi | lo) && i < impl->lines; i++) { + if ((hi | lo) & (1 << i)) + nouveau_event_trigger(gpio->events, 1, i); + } +} + void _nouveau_gpio_dtor(struct nouveau_object *object) { @@ -127,13 +158,18 @@ nouveau_gpio_create_(struct nouveau_object *parent, if (ret) return ret; + gpio->find = nouveau_gpio_find; + gpio->set = nouveau_gpio_set; + gpio->get = nouveau_gpio_get; + ret = nouveau_event_create(1, impl->lines, &gpio->events); if (ret) return ret; - gpio->find = nouveau_gpio_find; - gpio->set = nouveau_gpio_set; - gpio->get = nouveau_gpio_get; + gpio->events->priv = gpio; + gpio->events->enable = nouveau_gpio_intr_enable; + gpio->events->disable = nouveau_gpio_intr_disable; + nv_subdev(gpio)->intr = nouveau_gpio_intr; return 0; } |