linux/drivers/gpu/drm/xylon/xylon_irq.c
<<
>>
Prefs
   1/*
   2 * Xylon DRM driver IRQ functions
   3 *
   4 * Copyright (C) 2014 Xylon d.o.o.
   5 * Author: Davor Joja <davor.joja@logicbricks.com>
   6 *
   7 * This software is licensed under the terms of the GNU General Public
   8 * License version 2, as published by the Free Software Foundation, and
   9 * may be copied, distributed, and modified under those terms.
  10 *
  11 * This program is distributed in the hope that it will be useful,
  12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  14 * GNU General Public License for more details.
  15 */
  16
  17#include <drm/drmP.h>
  18
  19#include "xylon_drv.h"
  20#include "xylon_crtc.h"
  21#include "xylon_irq.h"
  22
  23irqreturn_t xylon_drm_irq_handler(int irq, void *arg)
  24{
  25        struct drm_device *dev = (struct drm_device *)arg;
  26        struct xylon_drm_device *xdev;
  27
  28        if (!dev)
  29                return IRQ_NONE;
  30
  31        xdev = dev->dev_private;
  32
  33        xylon_drm_crtc_int_handle(xdev->crtc);
  34
  35        return IRQ_HANDLED;
  36}
  37
  38void xylon_drm_irq_preinst(struct drm_device *dev)
  39{
  40        struct xylon_drm_device *xdev = dev->dev_private;
  41
  42        xylon_drm_crtc_int_hw_disable(xdev->crtc);
  43}
  44
  45int xylon_drm_irq_postinst(struct drm_device *dev)
  46{
  47        return 0;
  48}
  49
  50void xylon_drm_irq_uninst(struct drm_device *dev)
  51{
  52        struct xylon_drm_device *xdev = dev->dev_private;
  53
  54        xylon_drm_crtc_int_hw_disable(xdev->crtc);
  55}
  56
  57int xylon_drm_irq_install(struct drm_device *dev)
  58{
  59        struct xylon_drm_device *xdev = dev->dev_private;
  60        unsigned long irq_flags;
  61        int ret;
  62
  63        if (!drm_core_check_feature(dev, DRIVER_HAVE_IRQ))
  64                return -EINVAL;
  65
  66        mutex_lock(&dev->struct_mutex);
  67        if (dev->irq_enabled)
  68                return -EBUSY;
  69        mutex_unlock(&dev->struct_mutex);
  70
  71        if (dev->driver->irq_preinstall)
  72                dev->driver->irq_preinstall(dev);
  73
  74        if (drm_core_check_feature(dev, DRIVER_IRQ_SHARED))
  75                irq_flags = IRQF_SHARED;
  76        else
  77                irq_flags = 0;
  78
  79        ret = xylon_drm_crtc_int_request(xdev->crtc, irq_flags,
  80                                         xylon_drm_irq_handler, dev);
  81        if (ret < 0)
  82                return ret;
  83
  84        if (dev->driver->irq_postinstall)
  85                ret = dev->driver->irq_postinstall(dev);
  86
  87        if (ret < 0) {
  88                xylon_drm_crtc_int_free(xdev->crtc, dev);
  89                return ret;
  90        }
  91
  92        mutex_lock(&dev->struct_mutex);
  93        dev->irq_enabled = 1;
  94        mutex_unlock(&dev->struct_mutex);
  95
  96        return ret;
  97}
  98
  99int xylon_drm_irq_uninstall(struct drm_device *dev)
 100{
 101        struct xylon_drm_device *xdev = dev->dev_private;
 102        unsigned long irqflags;
 103        int i, irq_enabled;
 104
 105        if (!drm_core_check_feature(dev, DRIVER_HAVE_IRQ))
 106                return -EINVAL;
 107
 108        mutex_lock(&dev->struct_mutex);
 109        irq_enabled = dev->irq_enabled;
 110        dev->irq_enabled = 0;
 111        mutex_unlock(&dev->struct_mutex);
 112
 113        if (dev->num_crtcs) {
 114                spin_lock_irqsave(&dev->vbl_lock, irqflags);
 115                for (i = 0; i < dev->num_crtcs; i++) {
 116                        wake_up(&dev->vblank[i].queue);
 117                        dev->vblank[i].enabled = 0;
 118                        dev->vblank[i].last =
 119                                dev->driver->get_vblank_counter(dev, i);
 120                }
 121                spin_unlock_irqrestore(&dev->vbl_lock, irqflags);
 122        }
 123
 124        if (!irq_enabled)
 125                return -EINVAL;
 126
 127        if (dev->driver->irq_uninstall)
 128                dev->driver->irq_uninstall(dev);
 129
 130        xylon_drm_crtc_int_free(xdev->crtc, dev);
 131
 132        return 0;
 133}
 134