1145132Sanholt/* mach64_irq.c -- IRQ handling for ATI Mach64 -*- linux-c -*- 2145132Sanholt * Created: Tue Feb 25, 2003 by Leif Delgass, based on radeon_irq.c/r128_irq.c 3152909Sanholt */ 4152909Sanholt/*- 5145132Sanholt * Copyright (C) The Weather Channel, Inc. 2002. 6145132Sanholt * Copyright 2003 Leif Delgass 7145132Sanholt * All Rights Reserved. 8145132Sanholt * 9145132Sanholt * The Weather Channel (TM) funded Tungsten Graphics to develop the 10145132Sanholt * initial release of the Radeon 8500 driver under the XFree86 license. 11145132Sanholt * This notice must be preserved. 12145132Sanholt * 13145132Sanholt * Permission is hereby granted, free of charge, to any person obtaining a 14145132Sanholt * copy of this software and associated documentation files (the "Software"), 15145132Sanholt * to deal in the Software without restriction, including without limitation 16145132Sanholt * the rights to use, copy, modify, merge, publish, distribute, sublicense, 17145132Sanholt * and/or sell copies of the Software, and to permit persons to whom the 18145132Sanholt * Software is furnished to do so, subject to the following conditions: 19145132Sanholt * 20145132Sanholt * The above copyright notice and this permission notice (including the next 21145132Sanholt * paragraph) shall be included in all copies or substantial portions of the 22145132Sanholt * Software. 23145132Sanholt * 24145132Sanholt * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 25145132Sanholt * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 26145132Sanholt * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 27145132Sanholt * THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR 28145132Sanholt * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 29145132Sanholt * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 30145132Sanholt * DEALINGS IN THE SOFTWARE. 31145132Sanholt * 32145132Sanholt * Authors: 33145132Sanholt * Keith Whitwell <keith@tungstengraphics.com> 34145132Sanholt * Eric Anholt <anholt@FreeBSD.org> 35145132Sanholt * Leif Delgass <ldelgass@retinalburn.net> 36145132Sanholt */ 37145132Sanholt 38152909Sanholt#include <sys/cdefs.h> 39152909Sanholt__FBSDID("$FreeBSD$"); 40152909Sanholt 41145132Sanholt#include "dev/drm/drmP.h" 42145132Sanholt#include "dev/drm/drm.h" 43145132Sanholt#include "dev/drm/mach64_drm.h" 44145132Sanholt#include "dev/drm/mach64_drv.h" 45145132Sanholt 46145132Sanholtirqreturn_t mach64_driver_irq_handler(DRM_IRQ_ARGS) 47145132Sanholt{ 48182080Srnoland struct drm_device *dev = arg; 49182080Srnoland drm_mach64_private_t *dev_priv = dev->dev_private; 50145132Sanholt int status; 51145132Sanholt 52145132Sanholt status = MACH64_READ(MACH64_CRTC_INT_CNTL); 53145132Sanholt 54145132Sanholt /* VBLANK interrupt */ 55145132Sanholt if (status & MACH64_CRTC_VBLANK_INT) { 56145132Sanholt /* Mask off all interrupt ack bits before setting the ack bit, since 57145132Sanholt * there may be other handlers outside the DRM. 58145132Sanholt * 59145132Sanholt * NOTE: On mach64, you need to keep the enable bits set when doing 60145132Sanholt * the ack, despite what the docs say about not acking and enabling 61145132Sanholt * in a single write. 62145132Sanholt */ 63145132Sanholt MACH64_WRITE(MACH64_CRTC_INT_CNTL, 64145132Sanholt (status & ~MACH64_CRTC_INT_ACKS) 65145132Sanholt | MACH64_CRTC_VBLANK_INT); 66145132Sanholt 67182080Srnoland atomic_inc(&dev_priv->vbl_received); 68182080Srnoland drm_handle_vblank(dev, 0); 69145132Sanholt return IRQ_HANDLED; 70145132Sanholt } 71145132Sanholt return IRQ_NONE; 72145132Sanholt} 73145132Sanholt 74182080Srnolandu32 mach64_get_vblank_counter(struct drm_device * dev, int crtc) 75145132Sanholt{ 76182080Srnoland const drm_mach64_private_t *const dev_priv = dev->dev_private; 77145132Sanholt 78182080Srnoland if (crtc != 0) 79182080Srnoland return 0; 80145132Sanholt 81182080Srnoland return atomic_read(&dev_priv->vbl_received); 82182080Srnoland} 83145132Sanholt 84182080Srnolandint mach64_enable_vblank(struct drm_device * dev, int crtc) 85182080Srnoland{ 86182080Srnoland drm_mach64_private_t *dev_priv = dev->dev_private; 87182080Srnoland u32 status = MACH64_READ(MACH64_CRTC_INT_CNTL); 88182080Srnoland 89182080Srnoland if (crtc != 0) { 90182080Srnoland DRM_ERROR("tried to enable vblank on non-existent crtc %d\n", 91182080Srnoland crtc); 92182080Srnoland return -EINVAL; 93182080Srnoland } 94182080Srnoland 95182080Srnoland DRM_DEBUG("before enable vblank CRTC_INT_CTNL: 0x%08x\n", status); 96182080Srnoland 97182080Srnoland /* Turn on VBLANK interrupt */ 98182080Srnoland MACH64_WRITE(MACH64_CRTC_INT_CNTL, MACH64_READ(MACH64_CRTC_INT_CNTL) 99182080Srnoland | MACH64_CRTC_VBLANK_INT_EN); 100182080Srnoland 101182080Srnoland return 0; 102145132Sanholt} 103145132Sanholt 104182080Srnolandvoid mach64_disable_vblank(struct drm_device * dev, int crtc) 105145132Sanholt{ 106182080Srnoland if (crtc != 0) { 107182080Srnoland DRM_ERROR("tried to disable vblank on non-existent crtc %d\n", 108182080Srnoland crtc); 109182080Srnoland return; 110182080Srnoland } 111145132Sanholt 112182080Srnoland /* 113182080Srnoland * FIXME: implement proper interrupt disable by using the vblank 114182080Srnoland * counter register (if available). 115182080Srnoland */ 116182080Srnoland} 117182080Srnoland 118182080Srnolandstatic void mach64_disable_vblank_local(struct drm_device * dev, int crtc) 119182080Srnoland{ 120182080Srnoland drm_mach64_private_t *dev_priv = dev->dev_private; 121145132Sanholt u32 status = MACH64_READ(MACH64_CRTC_INT_CNTL); 122145132Sanholt 123182080Srnoland if (crtc != 0) { 124182080Srnoland DRM_ERROR("tried to disable vblank on non-existent crtc %d\n", 125182080Srnoland crtc); 126182080Srnoland return; 127182080Srnoland } 128145132Sanholt 129182080Srnoland DRM_DEBUG("before disable vblank CRTC_INT_CTNL: 0x%08x\n", status); 130182080Srnoland 131145132Sanholt /* Disable and clear VBLANK interrupt */ 132145132Sanholt MACH64_WRITE(MACH64_CRTC_INT_CNTL, (status & ~MACH64_CRTC_VBLANK_INT_EN) 133145132Sanholt | MACH64_CRTC_VBLANK_INT); 134145132Sanholt} 135145132Sanholt 136182080Srnolandvoid mach64_driver_irq_preinstall(struct drm_device * dev) 137145132Sanholt{ 138182080Srnoland drm_mach64_private_t *dev_priv = dev->dev_private; 139145132Sanholt 140182080Srnoland u32 status = MACH64_READ(MACH64_CRTC_INT_CNTL); 141145132Sanholt 142182080Srnoland DRM_DEBUG("before install CRTC_INT_CTNL: 0x%08x\n", status); 143145132Sanholt 144182080Srnoland mach64_disable_vblank_local(dev, 0); 145145132Sanholt} 146145132Sanholt 147182080Srnolandint mach64_driver_irq_postinstall(struct drm_device * dev) 148145132Sanholt{ 149189130Srnoland return 0; 150182080Srnoland} 151182080Srnoland 152182080Srnolandvoid mach64_driver_irq_uninstall(struct drm_device * dev) 153182080Srnoland{ 154182080Srnoland drm_mach64_private_t *dev_priv = dev->dev_private; 155145132Sanholt if (!dev_priv) 156145132Sanholt return; 157145132Sanholt 158182080Srnoland mach64_disable_vblank_local(dev, 0); 159145132Sanholt 160145132Sanholt DRM_DEBUG("after uninstall CRTC_INT_CTNL: 0x%08x\n", 161145132Sanholt MACH64_READ(MACH64_CRTC_INT_CNTL)); 162145132Sanholt} 163