The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/dev/drm/radeon_irq.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

    1 /* radeon_irq.c -- IRQ handling for radeon -*- linux-c -*- */
    2 /*-
    3  * Copyright (C) The Weather Channel, Inc.  2002.  All Rights Reserved.
    4  *
    5  * The Weather Channel (TM) funded Tungsten Graphics to develop the
    6  * initial release of the Radeon 8500 driver under the XFree86 license.
    7  * This notice must be preserved.
    8  *
    9  * Permission is hereby granted, free of charge, to any person obtaining a
   10  * copy of this software and associated documentation files (the "Software"),
   11  * to deal in the Software without restriction, including without limitation
   12  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
   13  * and/or sell copies of the Software, and to permit persons to whom the
   14  * Software is furnished to do so, subject to the following conditions:
   15  *
   16  * The above copyright notice and this permission notice (including the next
   17  * paragraph) shall be included in all copies or substantial portions of the
   18  * Software.
   19  *
   20  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
   21  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
   22  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
   23  * PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, 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  *    Keith Whitwell <keith@tungstengraphics.com>
   30  *    Michel D�zer <michel@daenzer.net>
   31  */
   32 
   33 #include <sys/cdefs.h>
   34 __FBSDID("$FreeBSD: releng/9.0/sys/dev/drm/radeon_irq.c 197603 2009-09-28 22:37:07Z rnoland $");
   35 
   36 #include "dev/drm/drmP.h"
   37 #include "dev/drm/drm.h"
   38 #include "dev/drm/radeon_drm.h"
   39 #include "dev/drm/radeon_drv.h"
   40 
   41 void radeon_irq_set_state(struct drm_device *dev, u32 mask, int state)
   42 {
   43         drm_radeon_private_t *dev_priv = dev->dev_private;
   44 
   45         if (state)
   46                 dev_priv->irq_enable_reg |= mask;
   47         else
   48                 dev_priv->irq_enable_reg &= ~mask;
   49 
   50         if (dev->irq_enabled)
   51                 RADEON_WRITE(RADEON_GEN_INT_CNTL, dev_priv->irq_enable_reg);
   52 }
   53 
   54 static void r500_vbl_irq_set_state(struct drm_device *dev, u32 mask, int state)
   55 {
   56         drm_radeon_private_t *dev_priv = dev->dev_private;
   57 
   58         if (state)
   59                 dev_priv->r500_disp_irq_reg |= mask;
   60         else
   61                 dev_priv->r500_disp_irq_reg &= ~mask;
   62 
   63         if (dev->irq_enabled)
   64                 RADEON_WRITE(R500_DxMODE_INT_MASK, dev_priv->r500_disp_irq_reg);
   65 }
   66 
   67 int radeon_enable_vblank(struct drm_device *dev, int crtc)
   68 {
   69         drm_radeon_private_t *dev_priv = dev->dev_private;
   70 
   71         if ((dev_priv->flags & RADEON_FAMILY_MASK) >= CHIP_RS600) {     
   72                 switch (crtc) {
   73                 case 0:
   74                         r500_vbl_irq_set_state(dev, R500_D1MODE_INT_MASK, 1);
   75                         break;
   76                 case 1:
   77                         r500_vbl_irq_set_state(dev, R500_D2MODE_INT_MASK, 1);
   78                         break;
   79                 default:
   80                         DRM_ERROR("tried to enable vblank on non-existent crtc %d\n",
   81                                   crtc);
   82                         return EINVAL;
   83                 }
   84         } else {
   85                 switch (crtc) {
   86                 case 0:
   87                         radeon_irq_set_state(dev, RADEON_CRTC_VBLANK_MASK, 1);
   88                         break;
   89                 case 1:
   90                         radeon_irq_set_state(dev, RADEON_CRTC2_VBLANK_MASK, 1);
   91                         break;
   92                 default:
   93                         DRM_ERROR("tried to enable vblank on non-existent crtc %d\n",
   94                                   crtc);
   95                         return EINVAL;
   96                 }
   97         }
   98 
   99         return 0;
  100 }
  101 
  102 void radeon_disable_vblank(struct drm_device *dev, int crtc)
  103 {
  104         drm_radeon_private_t *dev_priv = dev->dev_private;
  105 
  106         if ((dev_priv->flags & RADEON_FAMILY_MASK) >= CHIP_RS600) {     
  107                 switch (crtc) {
  108                 case 0:
  109                         r500_vbl_irq_set_state(dev, R500_D1MODE_INT_MASK, 0);
  110                         break;
  111                 case 1:
  112                         r500_vbl_irq_set_state(dev, R500_D2MODE_INT_MASK, 0);
  113                         break;
  114                 default:
  115                         DRM_ERROR("tried to enable vblank on non-existent crtc %d\n",
  116                                   crtc);
  117                         break;
  118                 }
  119         } else {
  120                 switch (crtc) {
  121                 case 0:
  122                         radeon_irq_set_state(dev, RADEON_CRTC_VBLANK_MASK, 0);
  123                         break;
  124                 case 1:
  125                         radeon_irq_set_state(dev, RADEON_CRTC2_VBLANK_MASK, 0);
  126                         break;
  127                 default:
  128                         DRM_ERROR("tried to enable vblank on non-existent crtc %d\n",
  129                                   crtc);
  130                         break;
  131                 }
  132         }
  133 }
  134 
  135 static __inline__ u32 radeon_acknowledge_irqs(drm_radeon_private_t * dev_priv, u32 *r500_disp_int)
  136 {
  137         u32 irqs = RADEON_READ(RADEON_GEN_INT_STATUS);
  138         u32 irq_mask = RADEON_SW_INT_TEST;
  139 
  140         *r500_disp_int = 0;
  141         if ((dev_priv->flags & RADEON_FAMILY_MASK) >= CHIP_RS600) {
  142                 /* vbl interrupts in a different place */
  143 
  144                 if (irqs & R500_DISPLAY_INT_STATUS) {
  145                         /* if a display interrupt */
  146                         u32 disp_irq;
  147 
  148                         disp_irq = RADEON_READ(R500_DISP_INTERRUPT_STATUS);
  149 
  150                         *r500_disp_int = disp_irq;
  151                         if (disp_irq & R500_D1_VBLANK_INTERRUPT) {
  152                                 RADEON_WRITE(R500_D1MODE_VBLANK_STATUS, R500_VBLANK_ACK);
  153                         }
  154                         if (disp_irq & R500_D2_VBLANK_INTERRUPT) {
  155                                 RADEON_WRITE(R500_D2MODE_VBLANK_STATUS, R500_VBLANK_ACK);
  156                         }
  157                 }
  158                 irq_mask |= R500_DISPLAY_INT_STATUS;
  159         } else
  160                 irq_mask |= RADEON_CRTC_VBLANK_STAT | RADEON_CRTC2_VBLANK_STAT;
  161 
  162         irqs &= irq_mask;
  163 
  164         if (irqs)
  165                 RADEON_WRITE(RADEON_GEN_INT_STATUS, irqs);
  166         
  167         return irqs;
  168 }
  169 
  170 /* Interrupts - Used for device synchronization and flushing in the
  171  * following circumstances:
  172  *
  173  * - Exclusive FB access with hw idle:
  174  *    - Wait for GUI Idle (?) interrupt, then do normal flush.
  175  *
  176  * - Frame throttling, NV_fence:
  177  *    - Drop marker irq's into command stream ahead of time.
  178  *    - Wait on irq's with lock *not held*
  179  *    - Check each for termination condition
  180  *
  181  * - Internally in cp_getbuffer, etc:
  182  *    - as above, but wait with lock held???
  183  *
  184  * NOTE: These functions are misleadingly named -- the irq's aren't
  185  * tied to dma at all, this is just a hangover from dri prehistory.
  186  */
  187 
  188 irqreturn_t radeon_driver_irq_handler(DRM_IRQ_ARGS)
  189 {
  190         struct drm_device *dev = (struct drm_device *) arg;
  191         drm_radeon_private_t *dev_priv =
  192             (drm_radeon_private_t *) dev->dev_private;
  193         u32 stat;
  194         u32 r500_disp_int;
  195         u32 tmp;
  196 
  197         if ((dev_priv->flags & RADEON_FAMILY_MASK) >= CHIP_R600)
  198                 return IRQ_NONE;
  199 
  200         /* Only consider the bits we're interested in - others could be used
  201          * outside the DRM
  202          */
  203         stat = radeon_acknowledge_irqs(dev_priv, &r500_disp_int);
  204         if (!stat)
  205                 return IRQ_NONE;
  206 
  207         stat &= dev_priv->irq_enable_reg;
  208 
  209         /* SW interrupt */
  210         if (stat & RADEON_SW_INT_TEST)
  211                 DRM_WAKEUP(&dev_priv->swi_queue);
  212 
  213         /* VBLANK interrupt */
  214         if ((dev_priv->flags & RADEON_FAMILY_MASK) >= CHIP_RS600) {
  215                 if (r500_disp_int & R500_D1_VBLANK_INTERRUPT)
  216                         drm_handle_vblank(dev, 0);
  217                 if (r500_disp_int & R500_D2_VBLANK_INTERRUPT)
  218                         drm_handle_vblank(dev, 1);
  219         } else {
  220                 if (stat & RADEON_CRTC_VBLANK_STAT)
  221                         drm_handle_vblank(dev, 0);
  222                 if (stat & RADEON_CRTC2_VBLANK_STAT)
  223                         drm_handle_vblank(dev, 1);
  224         }
  225         if (dev->msi_enabled) {
  226                 switch(dev_priv->flags & RADEON_FAMILY_MASK) {
  227                         case CHIP_RS400:
  228                         case CHIP_RS480:
  229                                 tmp = RADEON_READ(RADEON_AIC_CNTL) &
  230                                     ~RS400_MSI_REARM;
  231                                 RADEON_WRITE(RADEON_AIC_CNTL, tmp);
  232                                 RADEON_WRITE(RADEON_AIC_CNTL,
  233                                     tmp | RS400_MSI_REARM);
  234                                 break;
  235                         case CHIP_RS600:
  236                         case CHIP_RS690:
  237                         case CHIP_RS740:
  238                                 tmp = RADEON_READ(RADEON_BUS_CNTL) &
  239                                     ~RS600_MSI_REARM;
  240                                 RADEON_WRITE(RADEON_BUS_CNTL, tmp);
  241                                 RADEON_WRITE(RADEON_BUS_CNTL, tmp |
  242                                     RS600_MSI_REARM);
  243                                 break;
  244                          default:
  245                                 tmp = RADEON_READ(RADEON_MSI_REARM_EN) &
  246                                     ~RV370_MSI_REARM_EN;
  247                                 RADEON_WRITE(RADEON_MSI_REARM_EN, tmp);
  248                                 RADEON_WRITE(RADEON_MSI_REARM_EN,
  249                                     tmp | RV370_MSI_REARM_EN);
  250                                 break;
  251                 }
  252         }
  253         return IRQ_HANDLED;
  254 }
  255 
  256 static int radeon_emit_irq(struct drm_device * dev)
  257 {
  258         drm_radeon_private_t *dev_priv = dev->dev_private;
  259         unsigned int ret;
  260         RING_LOCALS;
  261 
  262         atomic_inc(&dev_priv->swi_emitted);
  263         ret = atomic_read(&dev_priv->swi_emitted);
  264 
  265         BEGIN_RING(4);
  266         OUT_RING_REG(RADEON_LAST_SWI_REG, ret);
  267         OUT_RING_REG(RADEON_GEN_INT_STATUS, RADEON_SW_INT_FIRE);
  268         ADVANCE_RING();
  269         COMMIT_RING();
  270 
  271         return ret;
  272 }
  273 
  274 static int radeon_wait_irq(struct drm_device * dev, int swi_nr)
  275 {
  276         drm_radeon_private_t *dev_priv =
  277             (drm_radeon_private_t *) dev->dev_private;
  278         int ret = 0;
  279 
  280         if (RADEON_READ(RADEON_LAST_SWI_REG) >= swi_nr)
  281                 return 0;
  282 
  283         dev_priv->stats.boxes |= RADEON_BOX_WAIT_IDLE;
  284 
  285         DRM_WAIT_ON(ret, dev_priv->swi_queue, 3 * DRM_HZ,
  286                     RADEON_READ(RADEON_LAST_SWI_REG) >= swi_nr);
  287 
  288         if (ret == -ERESTART)
  289                 DRM_DEBUG("restarting syscall");
  290 
  291         return ret;
  292 }
  293 
  294 u32 radeon_get_vblank_counter(struct drm_device *dev, int crtc)
  295 {
  296         drm_radeon_private_t *dev_priv = dev->dev_private;
  297 
  298         if (!dev_priv) {
  299                 DRM_ERROR("called with no initialization\n");
  300                 return -EINVAL;
  301         }
  302 
  303         if (crtc < 0 || crtc > 1) {
  304                 DRM_ERROR("Invalid crtc %d\n", crtc);
  305                 return -EINVAL;
  306         }
  307 
  308         if ((dev_priv->flags & RADEON_FAMILY_MASK) >= CHIP_RS600) {
  309                 if (crtc == 0)
  310                         return RADEON_READ(R500_D1CRTC_FRAME_COUNT);
  311                 else
  312                         return RADEON_READ(R500_D2CRTC_FRAME_COUNT);
  313         } else {
  314                 if (crtc == 0)
  315                         return RADEON_READ(RADEON_CRTC_CRNT_FRAME);
  316                 else
  317                         return RADEON_READ(RADEON_CRTC2_CRNT_FRAME);
  318         }
  319 }
  320 
  321 /* Needs the lock as it touches the ring.
  322  */
  323 int radeon_irq_emit(struct drm_device *dev, void *data, struct drm_file *file_priv)
  324 {
  325         drm_radeon_private_t *dev_priv = dev->dev_private;
  326         drm_radeon_irq_emit_t *emit = data;
  327         int result;
  328 
  329         if ((dev_priv->flags & RADEON_FAMILY_MASK) >= CHIP_R600)
  330                 return -EINVAL;
  331 
  332         LOCK_TEST_WITH_RETURN(dev, file_priv);
  333 
  334         if (!dev_priv) {
  335                 DRM_ERROR("called with no initialization\n");
  336                 return -EINVAL;
  337         }
  338 
  339         result = radeon_emit_irq(dev);
  340 
  341         if (DRM_COPY_TO_USER(emit->irq_seq, &result, sizeof(int))) {
  342                 DRM_ERROR("copy_to_user\n");
  343                 return -EFAULT;
  344         }
  345 
  346         return 0;
  347 }
  348 
  349 /* Doesn't need the hardware lock.
  350  */
  351 int radeon_irq_wait(struct drm_device *dev, void *data, struct drm_file *file_priv)
  352 {
  353         drm_radeon_private_t *dev_priv = dev->dev_private;
  354         drm_radeon_irq_wait_t *irqwait = data;
  355 
  356         if (!dev_priv) {
  357                 DRM_ERROR("called with no initialization\n");
  358                 return -EINVAL;
  359         }
  360 
  361         return radeon_wait_irq(dev, irqwait->irq_seq);
  362 }
  363 
  364 /* drm_dma.h hooks
  365 */
  366 void radeon_driver_irq_preinstall(struct drm_device * dev)
  367 {
  368         drm_radeon_private_t *dev_priv =
  369             (drm_radeon_private_t *) dev->dev_private;
  370         u32 dummy;
  371 
  372         if ((dev_priv->flags & RADEON_FAMILY_MASK) >= CHIP_R600)
  373                 return;
  374 
  375         /* Disable *all* interrupts */
  376         if ((dev_priv->flags & RADEON_FAMILY_MASK) >= CHIP_RS600)
  377                 RADEON_WRITE(R500_DxMODE_INT_MASK, 0);
  378         RADEON_WRITE(RADEON_GEN_INT_CNTL, 0);
  379 
  380         /* Clear bits if they're already high */
  381         radeon_acknowledge_irqs(dev_priv, &dummy);
  382 }
  383 
  384 int radeon_driver_irq_postinstall(struct drm_device * dev)
  385 {
  386         drm_radeon_private_t *dev_priv =
  387             (drm_radeon_private_t *) dev->dev_private;
  388 
  389         atomic_set(&dev_priv->swi_emitted, 0);
  390         DRM_INIT_WAITQUEUE(&dev_priv->swi_queue);
  391 
  392         if ((dev_priv->flags & RADEON_FAMILY_MASK) >= CHIP_R600)
  393                 return 0;
  394 
  395         radeon_irq_set_state(dev, RADEON_SW_INT_ENABLE, 1);
  396 
  397         return 0;
  398 }
  399 
  400 void radeon_driver_irq_uninstall(struct drm_device * dev)
  401 {
  402         drm_radeon_private_t *dev_priv =
  403             (drm_radeon_private_t *) dev->dev_private;
  404         if (!dev_priv)
  405                 return;
  406 
  407         dev_priv->irq_enabled = 0;
  408 
  409         if ((dev_priv->flags & RADEON_FAMILY_MASK) >= CHIP_R600)
  410                 return;
  411 
  412         if ((dev_priv->flags & RADEON_FAMILY_MASK) >= CHIP_RS600)
  413                 RADEON_WRITE(R500_DxMODE_INT_MASK, 0);
  414         /* Disable *all* interrupts */
  415         RADEON_WRITE(RADEON_GEN_INT_CNTL, 0);
  416 }
  417 
  418 
  419 int radeon_vblank_crtc_get(struct drm_device *dev)
  420 {
  421         drm_radeon_private_t *dev_priv = (drm_radeon_private_t *) dev->dev_private;
  422 
  423         return dev_priv->vblank_crtc;
  424 }
  425 
  426 int radeon_vblank_crtc_set(struct drm_device *dev, int64_t value)
  427 {
  428         drm_radeon_private_t *dev_priv = (drm_radeon_private_t *) dev->dev_private;
  429         if (value & ~(DRM_RADEON_VBLANK_CRTC1 | DRM_RADEON_VBLANK_CRTC2)) {
  430                 DRM_ERROR("called with invalid crtc 0x%x\n", (unsigned int)value);
  431                 return -EINVAL;
  432         }
  433         dev_priv->vblank_crtc = (unsigned int)value;
  434         return 0;
  435 }

Cache object: ef4c141c9669067d65e7ea236f851a9c


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.