linux/drivers/gpu/drm/via/via_irq.c
<<
>>
Prefs
   1/* via_irq.c
   2 *
   3 * Copyright 2004 BEAM Ltd.
   4 * Copyright 2002 Tungsten Graphics, Inc.
   5 * Copyright 2005 Thomas Hellstrom.
   6 * All Rights Reserved.
   7 *
   8 * Permission is hereby granted, free of charge, to any person obtaining a
   9 * copy of this software and associated documentation files (the "Software"),
  10 * to deal in the Software without restriction, including without limitation
  11 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
  12 * and/or sell copies of the Software, and to permit persons to whom the
  13 * Software is furnished to do so, subject to the following conditions:
  14 *
  15 * The above copyright notice and this permission notice (including the next
  16 * paragraph) shall be included in all copies or substantial portions of the
  17 * Software.
  18 *
  19 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  20 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  21 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
  22 * BEAM LTD, TUNGSTEN GRAPHICS  AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM,
  23 * DAMAGES OR
  24 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
  25 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
  26 * DEALINGS IN THE SOFTWARE.
  27 *
  28 * Authors:
  29 *    Terry Barnaby <terry1@beam.ltd.uk>
  30 *    Keith Whitwell <keith@tungstengraphics.com>
  31 *    Thomas Hellstrom <unichrome@shipmail.org>
  32 *
  33 * This code provides standard DRM access to the Via Unichrome / Pro Vertical blank
  34 * interrupt, as well as an infrastructure to handle other interrupts of the chip.
  35 * The refresh rate is also calculated for video playback sync purposes.
  36 */
  37
  38#include <drm/drmP.h>
  39#include <drm/via_drm.h>
  40#include "via_drv.h"
  41
  42#define VIA_REG_INTERRUPT       0x200
  43
  44/* VIA_REG_INTERRUPT */
  45#define VIA_IRQ_GLOBAL    (1 << 31)
  46#define VIA_IRQ_VBLANK_ENABLE   (1 << 19)
  47#define VIA_IRQ_VBLANK_PENDING  (1 << 3)
  48#define VIA_IRQ_HQV0_ENABLE     (1 << 11)
  49#define VIA_IRQ_HQV1_ENABLE     (1 << 25)
  50#define VIA_IRQ_HQV0_PENDING    (1 << 9)
  51#define VIA_IRQ_HQV1_PENDING    (1 << 10)
  52#define VIA_IRQ_DMA0_DD_ENABLE  (1 << 20)
  53#define VIA_IRQ_DMA0_TD_ENABLE  (1 << 21)
  54#define VIA_IRQ_DMA1_DD_ENABLE  (1 << 22)
  55#define VIA_IRQ_DMA1_TD_ENABLE  (1 << 23)
  56#define VIA_IRQ_DMA0_DD_PENDING (1 << 4)
  57#define VIA_IRQ_DMA0_TD_PENDING (1 << 5)
  58#define VIA_IRQ_DMA1_DD_PENDING (1 << 6)
  59#define VIA_IRQ_DMA1_TD_PENDING (1 << 7)
  60
  61
  62/*
  63 * Device-specific IRQs go here. This type might need to be extended with
  64 * the register if there are multiple IRQ control registers.
  65 * Currently we activate the HQV interrupts of  Unichrome Pro group A.
  66 */
  67
  68static maskarray_t via_pro_group_a_irqs[] = {
  69        {VIA_IRQ_HQV0_ENABLE, VIA_IRQ_HQV0_PENDING, 0x000003D0, 0x00008010,
  70         0x00000000 },
  71        {VIA_IRQ_HQV1_ENABLE, VIA_IRQ_HQV1_PENDING, 0x000013D0, 0x00008010,
  72         0x00000000 },
  73        {VIA_IRQ_DMA0_TD_ENABLE, VIA_IRQ_DMA0_TD_PENDING, VIA_PCI_DMA_CSR0,
  74         VIA_DMA_CSR_TA | VIA_DMA_CSR_TD, 0x00000008},
  75        {VIA_IRQ_DMA1_TD_ENABLE, VIA_IRQ_DMA1_TD_PENDING, VIA_PCI_DMA_CSR1,
  76         VIA_DMA_CSR_TA | VIA_DMA_CSR_TD, 0x00000008},
  77};
  78static int via_num_pro_group_a = ARRAY_SIZE(via_pro_group_a_irqs);
  79static int via_irqmap_pro_group_a[] = {0, 1, -1, 2, -1, 3};
  80
  81static maskarray_t via_unichrome_irqs[] = {
  82        {VIA_IRQ_DMA0_TD_ENABLE, VIA_IRQ_DMA0_TD_PENDING, VIA_PCI_DMA_CSR0,
  83         VIA_DMA_CSR_TA | VIA_DMA_CSR_TD, 0x00000008},
  84        {VIA_IRQ_DMA1_TD_ENABLE, VIA_IRQ_DMA1_TD_PENDING, VIA_PCI_DMA_CSR1,
  85         VIA_DMA_CSR_TA | VIA_DMA_CSR_TD, 0x00000008}
  86};
  87static int via_num_unichrome = ARRAY_SIZE(via_unichrome_irqs);
  88static int via_irqmap_unichrome[] = {-1, -1, -1, 0, -1, 1};
  89
  90
  91u32 via_get_vblank_counter(struct drm_device *dev, unsigned int pipe)
  92{
  93        drm_via_private_t *dev_priv = dev->dev_private;
  94
  95        if (pipe != 0)
  96                return 0;
  97
  98        return atomic_read(&dev_priv->vbl_received);
  99}
 100
 101irqreturn_t via_driver_irq_handler(int irq, void *arg)
 102{
 103        struct drm_device *dev = (struct drm_device *) arg;
 104        drm_via_private_t *dev_priv = (drm_via_private_t *) dev->dev_private;
 105        u32 status;
 106        int handled = 0;
 107        ktime_t cur_vblank;
 108        drm_via_irq_t *cur_irq = dev_priv->via_irqs;
 109        int i;
 110
 111        status = VIA_READ(VIA_REG_INTERRUPT);
 112        if (status & VIA_IRQ_VBLANK_PENDING) {
 113                atomic_inc(&dev_priv->vbl_received);
 114                if (!(atomic_read(&dev_priv->vbl_received) & 0x0F)) {
 115                        cur_vblank = ktime_get();
 116                        if (dev_priv->last_vblank_valid) {
 117                                dev_priv->nsec_per_vblank =
 118                                        ktime_sub(cur_vblank,
 119                                                dev_priv->last_vblank) >> 4;
 120                        }
 121                        dev_priv->last_vblank = cur_vblank;
 122                        dev_priv->last_vblank_valid = 1;
 123                }
 124                if (!(atomic_read(&dev_priv->vbl_received) & 0xFF)) {
 125                        DRM_DEBUG("nsec per vblank is: %llu\n",
 126                                  ktime_to_ns(dev_priv->nsec_per_vblank));
 127                }
 128                drm_handle_vblank(dev, 0);
 129                handled = 1;
 130        }
 131
 132        for (i = 0; i < dev_priv->num_irqs; ++i) {
 133                if (status & cur_irq->pending_mask) {
 134                        atomic_inc(&cur_irq->irq_received);
 135                        wake_up(&cur_irq->irq_queue);
 136                        handled = 1;
 137                        if (dev_priv->irq_map[drm_via_irq_dma0_td] == i)
 138                                via_dmablit_handler(dev, 0, 1);
 139                        else if (dev_priv->irq_map[drm_via_irq_dma1_td] == i)
 140                                via_dmablit_handler(dev, 1, 1);
 141                }
 142                cur_irq++;
 143        }
 144
 145        /* Acknowledge interrupts */
 146        VIA_WRITE(VIA_REG_INTERRUPT, status);
 147
 148
 149        if (handled)
 150                return IRQ_HANDLED;
 151        else
 152                return IRQ_NONE;
 153}
 154
 155static __inline__ void viadrv_acknowledge_irqs(drm_via_private_t *dev_priv)
 156{
 157        u32 status;
 158
 159        if (dev_priv) {
 160                /* Acknowledge interrupts */
 161                status = VIA_READ(VIA_REG_INTERRUPT);
 162                VIA_WRITE(VIA_REG_INTERRUPT, status |
 163                          dev_priv->irq_pending_mask);
 164        }
 165}
 166
 167int via_enable_vblank(struct drm_device *dev, unsigned int pipe)
 168{
 169        drm_via_private_t *dev_priv = dev->dev_private;
 170        u32 status;
 171
 172        if (pipe != 0) {
 173                DRM_ERROR("%s:  bad crtc %u\n", __func__, pipe);
 174                return -EINVAL;
 175        }
 176
 177        status = VIA_READ(VIA_REG_INTERRUPT);
 178        VIA_WRITE(VIA_REG_INTERRUPT, status | VIA_IRQ_VBLANK_ENABLE);
 179
 180        VIA_WRITE8(0x83d4, 0x11);
 181        VIA_WRITE8(0x83d5, VIA_READ8(0x83d5) | 0x30);
 182
 183        return 0;
 184}
 185
 186void via_disable_vblank(struct drm_device *dev, unsigned int pipe)
 187{
 188        drm_via_private_t *dev_priv = dev->dev_private;
 189        u32 status;
 190
 191        status = VIA_READ(VIA_REG_INTERRUPT);
 192        VIA_WRITE(VIA_REG_INTERRUPT, status & ~VIA_IRQ_VBLANK_ENABLE);
 193
 194        VIA_WRITE8(0x83d4, 0x11);
 195        VIA_WRITE8(0x83d5, VIA_READ8(0x83d5) & ~0x30);
 196
 197        if (pipe != 0)
 198                DRM_ERROR("%s:  bad crtc %u\n", __func__, pipe);
 199}
 200
 201static int
 202via_driver_irq_wait(struct drm_device *dev, unsigned int irq, int force_sequence,
 203                    unsigned int *sequence)
 204{
 205        drm_via_private_t *dev_priv = (drm_via_private_t *) dev->dev_private;
 206        unsigned int cur_irq_sequence;
 207        drm_via_irq_t *cur_irq;
 208        int ret = 0;
 209        maskarray_t *masks;
 210        int real_irq;
 211
 212        DRM_DEBUG("\n");
 213
 214        if (!dev_priv) {
 215                DRM_ERROR("called with no initialization\n");
 216                return -EINVAL;
 217        }
 218
 219        if (irq >= drm_via_irq_num) {
 220                DRM_ERROR("Trying to wait on unknown irq %d\n", irq);
 221                return -EINVAL;
 222        }
 223
 224        real_irq = dev_priv->irq_map[irq];
 225
 226        if (real_irq < 0) {
 227                DRM_ERROR("Video IRQ %d not available on this hardware.\n",
 228                          irq);
 229                return -EINVAL;
 230        }
 231
 232        masks = dev_priv->irq_masks;
 233        cur_irq = dev_priv->via_irqs + real_irq;
 234
 235        if (masks[real_irq][2] && !force_sequence) {
 236                DRM_WAIT_ON(ret, cur_irq->irq_queue, 3 * HZ,
 237                            ((VIA_READ(masks[irq][2]) & masks[irq][3]) ==
 238                             masks[irq][4]));
 239                cur_irq_sequence = atomic_read(&cur_irq->irq_received);
 240        } else {
 241                DRM_WAIT_ON(ret, cur_irq->irq_queue, 3 * HZ,
 242                            (((cur_irq_sequence =
 243                               atomic_read(&cur_irq->irq_received)) -
 244                              *sequence) <= (1 << 23)));
 245        }
 246        *sequence = cur_irq_sequence;
 247        return ret;
 248}
 249
 250
 251/*
 252 * drm_dma.h hooks
 253 */
 254
 255void via_driver_irq_preinstall(struct drm_device *dev)
 256{
 257        drm_via_private_t *dev_priv = (drm_via_private_t *) dev->dev_private;
 258        u32 status;
 259        drm_via_irq_t *cur_irq;
 260        int i;
 261
 262        DRM_DEBUG("dev_priv: %p\n", dev_priv);
 263        if (dev_priv) {
 264                cur_irq = dev_priv->via_irqs;
 265
 266                dev_priv->irq_enable_mask = VIA_IRQ_VBLANK_ENABLE;
 267                dev_priv->irq_pending_mask = VIA_IRQ_VBLANK_PENDING;
 268
 269                if (dev_priv->chipset == VIA_PRO_GROUP_A ||
 270                    dev_priv->chipset == VIA_DX9_0) {
 271                        dev_priv->irq_masks = via_pro_group_a_irqs;
 272                        dev_priv->num_irqs = via_num_pro_group_a;
 273                        dev_priv->irq_map = via_irqmap_pro_group_a;
 274                } else {
 275                        dev_priv->irq_masks = via_unichrome_irqs;
 276                        dev_priv->num_irqs = via_num_unichrome;
 277                        dev_priv->irq_map = via_irqmap_unichrome;
 278                }
 279
 280                for (i = 0; i < dev_priv->num_irqs; ++i) {
 281                        atomic_set(&cur_irq->irq_received, 0);
 282                        cur_irq->enable_mask = dev_priv->irq_masks[i][0];
 283                        cur_irq->pending_mask = dev_priv->irq_masks[i][1];
 284                        init_waitqueue_head(&cur_irq->irq_queue);
 285                        dev_priv->irq_enable_mask |= cur_irq->enable_mask;
 286                        dev_priv->irq_pending_mask |= cur_irq->pending_mask;
 287                        cur_irq++;
 288
 289                        DRM_DEBUG("Initializing IRQ %d\n", i);
 290                }
 291
 292                dev_priv->last_vblank_valid = 0;
 293
 294                /* Clear VSync interrupt regs */
 295                status = VIA_READ(VIA_REG_INTERRUPT);
 296                VIA_WRITE(VIA_REG_INTERRUPT, status &
 297                          ~(dev_priv->irq_enable_mask));
 298
 299                /* Clear bits if they're already high */
 300                viadrv_acknowledge_irqs(dev_priv);
 301        }
 302}
 303
 304int via_driver_irq_postinstall(struct drm_device *dev)
 305{
 306        drm_via_private_t *dev_priv = (drm_via_private_t *) dev->dev_private;
 307        u32 status;
 308
 309        DRM_DEBUG("via_driver_irq_postinstall\n");
 310        if (!dev_priv)
 311                return -EINVAL;
 312
 313        status = VIA_READ(VIA_REG_INTERRUPT);
 314        VIA_WRITE(VIA_REG_INTERRUPT, status | VIA_IRQ_GLOBAL
 315                  | dev_priv->irq_enable_mask);
 316
 317        /* Some magic, oh for some data sheets ! */
 318        VIA_WRITE8(0x83d4, 0x11);
 319        VIA_WRITE8(0x83d5, VIA_READ8(0x83d5) | 0x30);
 320
 321        return 0;
 322}
 323
 324void via_driver_irq_uninstall(struct drm_device *dev)
 325{
 326        drm_via_private_t *dev_priv = (drm_via_private_t *) dev->dev_private;
 327        u32 status;
 328
 329        DRM_DEBUG("\n");
 330        if (dev_priv) {
 331
 332                /* Some more magic, oh for some data sheets ! */
 333
 334                VIA_WRITE8(0x83d4, 0x11);
 335                VIA_WRITE8(0x83d5, VIA_READ8(0x83d5) & ~0x30);
 336
 337                status = VIA_READ(VIA_REG_INTERRUPT);
 338                VIA_WRITE(VIA_REG_INTERRUPT, status &
 339                          ~(VIA_IRQ_VBLANK_ENABLE | dev_priv->irq_enable_mask));
 340        }
 341}
 342
 343int via_wait_irq(struct drm_device *dev, void *data, struct drm_file *file_priv)
 344{
 345        drm_via_irqwait_t *irqwait = data;
 346        struct timespec64 now;
 347        int ret = 0;
 348        drm_via_private_t *dev_priv = (drm_via_private_t *) dev->dev_private;
 349        drm_via_irq_t *cur_irq = dev_priv->via_irqs;
 350        int force_sequence;
 351
 352        if (irqwait->request.irq >= dev_priv->num_irqs) {
 353                DRM_ERROR("Trying to wait on unknown irq %d\n",
 354                          irqwait->request.irq);
 355                return -EINVAL;
 356        }
 357
 358        cur_irq += irqwait->request.irq;
 359
 360        switch (irqwait->request.type & ~VIA_IRQ_FLAGS_MASK) {
 361        case VIA_IRQ_RELATIVE:
 362                irqwait->request.sequence +=
 363                        atomic_read(&cur_irq->irq_received);
 364                irqwait->request.type &= ~_DRM_VBLANK_RELATIVE;
 365        case VIA_IRQ_ABSOLUTE:
 366                break;
 367        default:
 368                return -EINVAL;
 369        }
 370
 371        if (irqwait->request.type & VIA_IRQ_SIGNAL) {
 372                DRM_ERROR("Signals on Via IRQs not implemented yet.\n");
 373                return -EINVAL;
 374        }
 375
 376        force_sequence = (irqwait->request.type & VIA_IRQ_FORCE_SEQUENCE);
 377
 378        ret = via_driver_irq_wait(dev, irqwait->request.irq, force_sequence,
 379                                  &irqwait->request.sequence);
 380        ktime_get_ts64(&now);
 381        irqwait->reply.tval_sec = now.tv_sec;
 382        irqwait->reply.tval_usec = now.tv_nsec / NSEC_PER_USEC;
 383
 384        return ret;
 385}
 386