radeon_irq_kms.c revision 282199
190075Sobrien/* 290075Sobrien * Copyright 2008 Advanced Micro Devices, Inc. 396263Sobrien * Copyright 2008 Red Hat Inc. 490075Sobrien * Copyright 2009 Jerome Glisse. 590075Sobrien * 690075Sobrien * Permission is hereby granted, free of charge, to any person obtaining a 790075Sobrien * copy of this software and associated documentation files (the "Software"), 890075Sobrien * to deal in the Software without restriction, including without limitation 990075Sobrien * the rights to use, copy, modify, merge, publish, distribute, sublicense, 1090075Sobrien * and/or sell copies of the Software, and to permit persons to whom the 1190075Sobrien * Software is furnished to do so, subject to the following conditions: 1290075Sobrien * 1390075Sobrien * The above copyright notice and this permission notice shall be included in 1490075Sobrien * all copies or substantial portions of the Software. 1590075Sobrien * 1690075Sobrien * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 1790075Sobrien * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 1890075Sobrien * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 1990075Sobrien * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR 2090075Sobrien * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 2190075Sobrien * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 2290075Sobrien * OTHER DEALINGS IN THE SOFTWARE. 2390075Sobrien * 2490075Sobrien * Authors: Dave Airlie 2590075Sobrien * Alex Deucher 2690075Sobrien * Jerome Glisse 2790075Sobrien */ 2890075Sobrien 2990075Sobrien#include <sys/cdefs.h> 3090075Sobrien__FBSDID("$FreeBSD: stable/10/sys/dev/drm2/radeon/radeon_irq_kms.c 282199 2015-04-28 19:35:05Z dumbbell $"); 3190075Sobrien 3290075Sobrien#include <dev/drm2/drmP.h> 3390075Sobrien#include <dev/drm2/drm_crtc_helper.h> 3490075Sobrien#include <dev/drm2/radeon/radeon_drm.h> 3590075Sobrien#include "radeon_reg.h" 3690075Sobrien#include "radeon_irq_kms.h" 3790075Sobrien#include "radeon.h" 3890075Sobrien#include "atom.h" 3990075Sobrien 4090075Sobrien#define RADEON_WAIT_IDLE_TIMEOUT 200 4190075Sobrien 4290075Sobrien/** 4390075Sobrien * radeon_driver_irq_handler_kms - irq handler for KMS 4490075Sobrien * 4590075Sobrien * @DRM_IRQ_ARGS: args 4690075Sobrien * 4790075Sobrien * This is the irq handler for the radeon KMS driver (all asics). 4890075Sobrien * radeon_irq_process is a macro that points to the per-asic 4990075Sobrien * irq handler callback. 5090075Sobrien */ 5190075Sobrienirqreturn_t radeon_driver_irq_handler_kms(DRM_IRQ_ARGS) 5290075Sobrien{ 5390075Sobrien struct drm_device *dev = (struct drm_device *) arg; 5490075Sobrien struct radeon_device *rdev = dev->dev_private; 5590075Sobrien 5690075Sobrien return radeon_irq_process(rdev); 5790075Sobrien} 5890075Sobrien 5990075Sobrien/* 6090075Sobrien * Handle hotplug events outside the interrupt handler proper. 6190075Sobrien */ 6290075Sobrien/** 6390075Sobrien * radeon_hotplug_work_func - display hotplug work handler 6490075Sobrien * 6590075Sobrien * @work: work struct 6690075Sobrien * 6790075Sobrien * This is the hot plug event work handler (all asics). 6890075Sobrien * The work gets scheduled from the irq handler if there 6990075Sobrien * was a hot plug interrupt. It walks the connector table 7090075Sobrien * and calls the hotplug handler for each one, then sends 7190075Sobrien * a drm hotplug event to alert userspace. 7290075Sobrien */ 7390075Sobrienstatic void radeon_hotplug_work_func(void *arg, int pending) 7490075Sobrien{ 7590075Sobrien struct radeon_device *rdev = arg; 7690075Sobrien struct drm_device *dev = rdev->ddev; 7790075Sobrien struct drm_mode_config *mode_config = &dev->mode_config; 7890075Sobrien struct drm_connector *connector; 7990075Sobrien 8090075Sobrien if (mode_config->num_connector) { 8190075Sobrien list_for_each_entry(connector, &mode_config->connector_list, head) 8290075Sobrien radeon_connector_hotplug(connector); 8390075Sobrien } 8490075Sobrien /* Just fire off a uevent and let userspace tell us what to do */ 8590075Sobrien drm_helper_hpd_irq_event(dev); 8690075Sobrien} 8790075Sobrien 8890075Sobrien/** 8990075Sobrien * radeon_driver_irq_preinstall_kms - drm irq preinstall callback 9090075Sobrien * 9190075Sobrien * @dev: drm dev pointer 9290075Sobrien * 9390075Sobrien * Gets the hw ready to enable irqs (all asics). 9490075Sobrien * This function disables all interrupt sources on the GPU. 9590075Sobrien */ 9690075Sobrienvoid radeon_driver_irq_preinstall_kms(struct drm_device *dev) 9790075Sobrien{ 9890075Sobrien struct radeon_device *rdev = dev->dev_private; 9990075Sobrien unsigned long irqflags; 10090075Sobrien unsigned i; 10190075Sobrien 10290075Sobrien DRM_SPINLOCK_IRQSAVE(&rdev->irq.lock, irqflags); 10390075Sobrien /* Disable *all* interrupts */ 10496263Sobrien for (i = 0; i < RADEON_NUM_RINGS; i++) 10590075Sobrien atomic_set(&rdev->irq.ring_int[i], 0); 10690075Sobrien for (i = 0; i < RADEON_MAX_HPD_PINS; i++) 10790075Sobrien rdev->irq.hpd[i] = false; 10890075Sobrien for (i = 0; i < RADEON_MAX_CRTCS; i++) { 10990075Sobrien rdev->irq.crtc_vblank_int[i] = false; 11090075Sobrien atomic_set(&rdev->irq.pflip[i], 0); 11190075Sobrien rdev->irq.afmt[i] = false; 11290075Sobrien } 11390075Sobrien radeon_irq_set(rdev); 11490075Sobrien DRM_SPINUNLOCK_IRQRESTORE(&rdev->irq.lock, irqflags); 11590075Sobrien /* Clear bits */ 11690075Sobrien radeon_irq_process(rdev); 11790075Sobrien} 11890075Sobrien 11990075Sobrien/** 12090075Sobrien * radeon_driver_irq_postinstall_kms - drm irq preinstall callback 12190075Sobrien * 12290075Sobrien * @dev: drm dev pointer 12390075Sobrien * 12490075Sobrien * Handles stuff to be done after enabling irqs (all asics). 12590075Sobrien * Returns 0 on success. 12690075Sobrien */ 12790075Sobrienint radeon_driver_irq_postinstall_kms(struct drm_device *dev) 12890075Sobrien{ 12990075Sobrien dev->max_vblank_count = 0x001fffff; 13090075Sobrien return 0; 13190075Sobrien} 13290075Sobrien 13390075Sobrien/** 13490075Sobrien * radeon_driver_irq_uninstall_kms - drm irq uninstall callback 13590075Sobrien * 13690075Sobrien * @dev: drm dev pointer 13790075Sobrien * 13890075Sobrien * This function disables all interrupt sources on the GPU (all asics). 13990075Sobrien */ 14090075Sobrienvoid radeon_driver_irq_uninstall_kms(struct drm_device *dev) 14190075Sobrien{ 14290075Sobrien struct radeon_device *rdev = dev->dev_private; 14390075Sobrien unsigned long irqflags; 14490075Sobrien unsigned i; 14590075Sobrien 14690075Sobrien if (rdev == NULL) { 14790075Sobrien return; 14890075Sobrien } 14990075Sobrien DRM_SPINLOCK_IRQSAVE(&rdev->irq.lock, irqflags); 15090075Sobrien /* Disable *all* interrupts */ 15190075Sobrien for (i = 0; i < RADEON_NUM_RINGS; i++) 15290075Sobrien atomic_set(&rdev->irq.ring_int[i], 0); 15390075Sobrien for (i = 0; i < RADEON_MAX_HPD_PINS; i++) 15490075Sobrien rdev->irq.hpd[i] = false; 15590075Sobrien for (i = 0; i < RADEON_MAX_CRTCS; i++) { 15690075Sobrien rdev->irq.crtc_vblank_int[i] = false; 15790075Sobrien atomic_set(&rdev->irq.pflip[i], 0); 15890075Sobrien rdev->irq.afmt[i] = false; 15990075Sobrien } 16090075Sobrien radeon_irq_set(rdev); 16190075Sobrien DRM_SPINUNLOCK_IRQRESTORE(&rdev->irq.lock, irqflags); 16290075Sobrien} 16390075Sobrien 16490075Sobrien/** 16590075Sobrien * radeon_msi_ok - asic specific msi checks 16690075Sobrien * 16790075Sobrien * @rdev: radeon device pointer 16890075Sobrien * 16990075Sobrien * Handles asic specific MSI checks to determine if 17090075Sobrien * MSIs should be enabled on a particular chip (all asics). 17190075Sobrien * Returns true if MSIs should be enabled, false if MSIs 17290075Sobrien * should not be enabled. 17390075Sobrien */ 17490075Sobrienstatic bool radeon_msi_ok(struct radeon_device *rdev) 17590075Sobrien{ 17690075Sobrien /* RV370/RV380 was first asic with MSI support */ 17790075Sobrien if (rdev->family < CHIP_RV380) 17890075Sobrien return false; 17990075Sobrien 18090075Sobrien /* MSIs don't work on AGP */ 18190075Sobrien if (rdev->flags & RADEON_IS_AGP) 18290075Sobrien return false; 18390075Sobrien 18490075Sobrien /* force MSI on */ 18590075Sobrien if (radeon_msi == 1) 18690075Sobrien return true; 18790075Sobrien else if (radeon_msi == 0) 18890075Sobrien return false; 18990075Sobrien 19090075Sobrien /* Quirks */ 19190075Sobrien /* HP RS690 only seems to work with MSIs. */ 19290075Sobrien if ((rdev->ddev->pci_device == 0x791f) && 19390075Sobrien (rdev->ddev->pci_subvendor == 0x103c) && 19490075Sobrien (rdev->ddev->pci_subdevice == 0x30c2)) 19590075Sobrien return true; 19690075Sobrien 19790075Sobrien /* Dell RS690 only seems to work with MSIs. */ 19890075Sobrien if ((rdev->ddev->pci_device == 0x791f) && 19990075Sobrien (rdev->ddev->pci_subvendor == 0x1028) && 20090075Sobrien (rdev->ddev->pci_subdevice == 0x01fc)) 20190075Sobrien return true; 20290075Sobrien 20390075Sobrien /* Dell RS690 only seems to work with MSIs. */ 20490075Sobrien if ((rdev->ddev->pci_device == 0x791f) && 20590075Sobrien (rdev->ddev->pci_subvendor == 0x1028) && 20690075Sobrien (rdev->ddev->pci_subdevice == 0x01fd)) 20790075Sobrien return true; 20890075Sobrien 20990075Sobrien /* Gateway RS690 only seems to work with MSIs. */ 21090075Sobrien if ((rdev->ddev->pci_device == 0x791f) && 21190075Sobrien (rdev->ddev->pci_subvendor == 0x107b) && 21290075Sobrien (rdev->ddev->pci_subdevice == 0x0185)) 21390075Sobrien return true; 21490075Sobrien 21590075Sobrien /* try and enable MSIs by default on all RS690s */ 21690075Sobrien if (rdev->family == CHIP_RS690) 21790075Sobrien return true; 21890075Sobrien 21990075Sobrien /* RV515 seems to have MSI issues where it loses 22090075Sobrien * MSI rearms occasionally. This leads to lockups and freezes. 22190075Sobrien * disable it by default. 22290075Sobrien */ 22390075Sobrien if (rdev->family == CHIP_RV515) 22490075Sobrien return false; 22590075Sobrien if (rdev->flags & RADEON_IS_IGP) { 22690075Sobrien /* APUs work fine with MSIs */ 22790075Sobrien if (rdev->family >= CHIP_PALM) 22890075Sobrien return true; 22990075Sobrien /* lots of IGPs have problems with MSIs */ 23090075Sobrien return false; 23190075Sobrien } 23290075Sobrien 23390075Sobrien return true; 23490075Sobrien} 23590075Sobrien 23690075Sobrien/** 23790075Sobrien * radeon_irq_kms_init - init driver interrupt info 23890075Sobrien * 23990075Sobrien * @rdev: radeon device pointer 24090075Sobrien * 24190075Sobrien * Sets up the work irq handlers, vblank init, MSIs, etc. (all asics). 24290075Sobrien * Returns 0 for success, error for failure. 24390075Sobrien */ 24490075Sobrienint radeon_irq_kms_init(struct radeon_device *rdev) 24590075Sobrien{ 24690075Sobrien int r = 0; 24790075Sobrien 24890075Sobrien TASK_INIT(&rdev->hotplug_work, 0, radeon_hotplug_work_func, rdev); 24990075Sobrien TASK_INIT(&rdev->audio_work, 0, r600_audio_update_hdmi, rdev); 25090075Sobrien 25190075Sobrien DRM_SPININIT(&rdev->irq.lock, "drm__radeon_device__irq__lock"); 25290075Sobrien r = drm_vblank_init(rdev->ddev, rdev->num_crtc); 25390075Sobrien if (r) { 25490075Sobrien return r; 25590075Sobrien } 25690075Sobrien /* enable msi */ 25790075Sobrien rdev->msi_enabled = 0; 25890075Sobrien 25990075Sobrien if (radeon_msi_ok(rdev)) { 26090075Sobrien int ret = drm_pci_enable_msi(rdev->ddev); 26190075Sobrien if (!ret) { 26290075Sobrien rdev->msi_enabled = 1; 26390075Sobrien dev_info(rdev->dev, "radeon: using MSI.\n"); 26490075Sobrien } 26590075Sobrien } 26690075Sobrien rdev->irq.installed = true; 26790075Sobrien r = drm_irq_install(rdev->ddev); 26890075Sobrien if (r) { 26990075Sobrien rdev->irq.installed = false; 27090075Sobrien return r; 27190075Sobrien } 27290075Sobrien DRM_INFO("radeon: irq initialized.\n"); 27390075Sobrien return 0; 27490075Sobrien} 27590075Sobrien 27690075Sobrien/** 27790075Sobrien * radeon_irq_kms_fini - tear down driver interrrupt info 27890075Sobrien * 27990075Sobrien * @rdev: radeon device pointer 28090075Sobrien * 28190075Sobrien * Tears down the work irq handlers, vblank handlers, MSIs, etc. (all asics). 28290075Sobrien */ 28390075Sobrienvoid radeon_irq_kms_fini(struct radeon_device *rdev) 28490075Sobrien{ 28590075Sobrien drm_vblank_cleanup(rdev->ddev); 28690075Sobrien if (rdev->irq.installed) { 28790075Sobrien drm_irq_uninstall(rdev->ddev); 28890075Sobrien rdev->irq.installed = false; 28990075Sobrien if (rdev->msi_enabled) 29090075Sobrien drm_pci_disable_msi(rdev->ddev); 29190075Sobrien } 29290075Sobrien taskqueue_drain(rdev->tq, &rdev->hotplug_work); 29390075Sobrien} 29490075Sobrien 29590075Sobrien/** 29690075Sobrien * radeon_irq_kms_sw_irq_get - enable software interrupt 29790075Sobrien * 29890075Sobrien * @rdev: radeon device pointer 29990075Sobrien * @ring: ring whose interrupt you want to enable 30090075Sobrien * 30190075Sobrien * Enables the software interrupt for a specific ring (all asics). 30290075Sobrien * The software interrupt is generally used to signal a fence on 30390075Sobrien * a particular ring. 30490075Sobrien */ 30590075Sobrienvoid radeon_irq_kms_sw_irq_get(struct radeon_device *rdev, int ring) 30690075Sobrien{ 30790075Sobrien unsigned long irqflags; 30890075Sobrien 30990075Sobrien if (!rdev->ddev->irq_enabled) 31090075Sobrien return; 31190075Sobrien 31290075Sobrien if (atomic_inc_return(&rdev->irq.ring_int[ring]) == 1) { 31390075Sobrien DRM_SPINLOCK_IRQSAVE(&rdev->irq.lock, irqflags); 31490075Sobrien radeon_irq_set(rdev); 31590075Sobrien DRM_SPINUNLOCK_IRQRESTORE(&rdev->irq.lock, irqflags); 31690075Sobrien } 31790075Sobrien} 31890075Sobrien 31990075Sobrien/** 32090075Sobrien * radeon_irq_kms_sw_irq_put - disable software interrupt 32190075Sobrien * 32290075Sobrien * @rdev: radeon device pointer 32390075Sobrien * @ring: ring whose interrupt you want to disable 32490075Sobrien * 32596263Sobrien * Disables the software interrupt for a specific ring (all asics). 32690075Sobrien * The software interrupt is generally used to signal a fence on 32790075Sobrien * a particular ring. 32890075Sobrien */ 32990075Sobrienvoid radeon_irq_kms_sw_irq_put(struct radeon_device *rdev, int ring) 33090075Sobrien{ 33190075Sobrien unsigned long irqflags; 33290075Sobrien 33390075Sobrien if (!rdev->ddev->irq_enabled) 33490075Sobrien return; 33590075Sobrien 33690075Sobrien if (atomic_dec_and_test(&rdev->irq.ring_int[ring])) { 33790075Sobrien DRM_SPINLOCK_IRQSAVE(&rdev->irq.lock, irqflags); 33890075Sobrien radeon_irq_set(rdev); 33990075Sobrien DRM_SPINUNLOCK_IRQRESTORE(&rdev->irq.lock, irqflags); 34096263Sobrien } 34190075Sobrien} 34290075Sobrien 34390075Sobrien/** 34490075Sobrien * radeon_irq_kms_pflip_irq_get - enable pageflip interrupt 34590075Sobrien * 34690075Sobrien * @rdev: radeon device pointer 34790075Sobrien * @crtc: crtc whose interrupt you want to enable 34890075Sobrien * 34990075Sobrien * Enables the pageflip interrupt for a specific crtc (all asics). 35090075Sobrien * For pageflips we use the vblank interrupt source. 35190075Sobrien */ 35290075Sobrienvoid radeon_irq_kms_pflip_irq_get(struct radeon_device *rdev, int crtc) 35390075Sobrien{ 35490075Sobrien unsigned long irqflags; 35590075Sobrien 35690075Sobrien if (crtc < 0 || crtc >= rdev->num_crtc) 35790075Sobrien return; 35890075Sobrien 35990075Sobrien if (!rdev->ddev->irq_enabled) 36090075Sobrien return; 36190075Sobrien 36290075Sobrien if (atomic_inc_return(&rdev->irq.pflip[crtc]) == 1) { 36390075Sobrien DRM_SPINLOCK_IRQSAVE(&rdev->irq.lock, irqflags); 36490075Sobrien radeon_irq_set(rdev); 36590075Sobrien DRM_SPINUNLOCK_IRQRESTORE(&rdev->irq.lock, irqflags); 36690075Sobrien } 36790075Sobrien} 36890075Sobrien 36990075Sobrien/** 37090075Sobrien * radeon_irq_kms_pflip_irq_put - disable pageflip interrupt 37190075Sobrien * 37290075Sobrien * @rdev: radeon device pointer 37390075Sobrien * @crtc: crtc whose interrupt you want to disable 37496263Sobrien * 37596263Sobrien * Disables the pageflip interrupt for a specific crtc (all asics). 37696263Sobrien * For pageflips we use the vblank interrupt source. 37796263Sobrien */ 37896263Sobrienvoid radeon_irq_kms_pflip_irq_put(struct radeon_device *rdev, int crtc) 37996263Sobrien{ 38096263Sobrien unsigned long irqflags; 38196263Sobrien 38296263Sobrien if (crtc < 0 || crtc >= rdev->num_crtc) 38390075Sobrien return; 38490075Sobrien 38590075Sobrien if (!rdev->ddev->irq_enabled) 38690075Sobrien return; 38790075Sobrien 38890075Sobrien if (atomic_dec_and_test(&rdev->irq.pflip[crtc])) { 38990075Sobrien DRM_SPINLOCK_IRQSAVE(&rdev->irq.lock, irqflags); 39090075Sobrien radeon_irq_set(rdev); 39190075Sobrien DRM_SPINUNLOCK_IRQRESTORE(&rdev->irq.lock, irqflags); 39290075Sobrien } 39390075Sobrien} 39490075Sobrien 39590075Sobrien/** 39690075Sobrien * radeon_irq_kms_enable_afmt - enable audio format change interrupt 39790075Sobrien * 39890075Sobrien * @rdev: radeon device pointer 39990075Sobrien * @block: afmt block whose interrupt you want to enable 40090075Sobrien * 40190075Sobrien * Enables the afmt change interrupt for a specific afmt block (all asics). 40290075Sobrien */ 40390075Sobrienvoid radeon_irq_kms_enable_afmt(struct radeon_device *rdev, int block) 40490075Sobrien{ 40590075Sobrien unsigned long irqflags; 40690075Sobrien 40790075Sobrien if (!rdev->ddev->irq_enabled) 40890075Sobrien return; 40990075Sobrien 41090075Sobrien DRM_SPINLOCK_IRQSAVE(&rdev->irq.lock, irqflags); 41190075Sobrien rdev->irq.afmt[block] = true; 41290075Sobrien radeon_irq_set(rdev); 41390075Sobrien DRM_SPINUNLOCK_IRQRESTORE(&rdev->irq.lock, irqflags); 41490075Sobrien 41590075Sobrien} 41690075Sobrien 41790075Sobrien/** 41890075Sobrien * radeon_irq_kms_disable_afmt - disable audio format change interrupt 41990075Sobrien * 42090075Sobrien * @rdev: radeon device pointer 42190075Sobrien * @block: afmt block whose interrupt you want to disable 42290075Sobrien * 42390075Sobrien * Disables the afmt change interrupt for a specific afmt block (all asics). 42490075Sobrien */ 42590075Sobrienvoid radeon_irq_kms_disable_afmt(struct radeon_device *rdev, int block) 42690075Sobrien{ 42790075Sobrien unsigned long irqflags; 42890075Sobrien 42990075Sobrien if (!rdev->ddev->irq_enabled) 43090075Sobrien return; 43190075Sobrien 43290075Sobrien DRM_SPINLOCK_IRQSAVE(&rdev->irq.lock, irqflags); 43390075Sobrien rdev->irq.afmt[block] = false; 43490075Sobrien radeon_irq_set(rdev); 43590075Sobrien DRM_SPINUNLOCK_IRQRESTORE(&rdev->irq.lock, irqflags); 43690075Sobrien} 43790075Sobrien 43890075Sobrien/** 43990075Sobrien * radeon_irq_kms_enable_hpd - enable hotplug detect interrupt 44090075Sobrien * 44190075Sobrien * @rdev: radeon device pointer 44290075Sobrien * @hpd_mask: mask of hpd pins you want to enable. 44390075Sobrien * 44490075Sobrien * Enables the hotplug detect interrupt for a specific hpd pin (all asics). 44590075Sobrien */ 44690075Sobrienvoid radeon_irq_kms_enable_hpd(struct radeon_device *rdev, unsigned hpd_mask) 44790075Sobrien{ 44890075Sobrien unsigned long irqflags; 44990075Sobrien int i; 45090075Sobrien 45190075Sobrien if (!rdev->ddev->irq_enabled) 45290075Sobrien return; 45390075Sobrien 45490075Sobrien DRM_SPINLOCK_IRQSAVE(&rdev->irq.lock, irqflags); 45590075Sobrien for (i = 0; i < RADEON_MAX_HPD_PINS; ++i) 45690075Sobrien rdev->irq.hpd[i] |= !!(hpd_mask & (1 << i)); 45790075Sobrien radeon_irq_set(rdev); 45890075Sobrien DRM_SPINUNLOCK_IRQRESTORE(&rdev->irq.lock, irqflags); 45990075Sobrien} 46090075Sobrien 46190075Sobrien/** 46290075Sobrien * radeon_irq_kms_disable_hpd - disable hotplug detect interrupt 46390075Sobrien * 46490075Sobrien * @rdev: radeon device pointer 46590075Sobrien * @hpd_mask: mask of hpd pins you want to disable. 46690075Sobrien * 46790075Sobrien * Disables the hotplug detect interrupt for a specific hpd pin (all asics). 46890075Sobrien */ 46990075Sobrienvoid radeon_irq_kms_disable_hpd(struct radeon_device *rdev, unsigned hpd_mask) 47090075Sobrien{ 47190075Sobrien unsigned long irqflags; 47290075Sobrien int i; 47390075Sobrien 47490075Sobrien if (!rdev->ddev->irq_enabled) 47590075Sobrien return; 47690075Sobrien 47790075Sobrien DRM_SPINLOCK_IRQSAVE(&rdev->irq.lock, irqflags); 47890075Sobrien for (i = 0; i < RADEON_MAX_HPD_PINS; ++i) 47990075Sobrien rdev->irq.hpd[i] &= !(hpd_mask & (1 << i)); 48090075Sobrien radeon_irq_set(rdev); 48190075Sobrien DRM_SPINUNLOCK_IRQRESTORE(&rdev->irq.lock, irqflags); 48290075Sobrien} 48390075Sobrien 48490075Sobrien