1254885Sdumbbell/* 2254885Sdumbbell * Copyright 2008 Advanced Micro Devices, Inc. 3254885Sdumbbell * Copyright 2008 Red Hat Inc. 4254885Sdumbbell * Copyright 2009 Jerome Glisse. 5254885Sdumbbell * 6254885Sdumbbell * Permission is hereby granted, free of charge, to any person obtaining a 7254885Sdumbbell * copy of this software and associated documentation files (the "Software"), 8254885Sdumbbell * to deal in the Software without restriction, including without limitation 9254885Sdumbbell * the rights to use, copy, modify, merge, publish, distribute, sublicense, 10254885Sdumbbell * and/or sell copies of the Software, and to permit persons to whom the 11254885Sdumbbell * Software is furnished to do so, subject to the following conditions: 12254885Sdumbbell * 13254885Sdumbbell * The above copyright notice and this permission notice shall be included in 14254885Sdumbbell * all copies or substantial portions of the Software. 15254885Sdumbbell * 16254885Sdumbbell * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17254885Sdumbbell * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18254885Sdumbbell * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 19254885Sdumbbell * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR 20254885Sdumbbell * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 21254885Sdumbbell * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 22254885Sdumbbell * OTHER DEALINGS IN THE SOFTWARE. 23254885Sdumbbell * 24254885Sdumbbell * Authors: Dave Airlie 25254885Sdumbbell * Alex Deucher 26254885Sdumbbell * Jerome Glisse 27254885Sdumbbell */ 28254885Sdumbbell 29254885Sdumbbell#include <sys/cdefs.h> 30254885Sdumbbell__FBSDID("$FreeBSD: releng/11.0/sys/dev/drm2/radeon/radeon_irq_kms.c 280183 2015-03-17 18:50:33Z dumbbell $"); 31254885Sdumbbell 32254885Sdumbbell#include <dev/drm2/drmP.h> 33254885Sdumbbell#include <dev/drm2/drm_crtc_helper.h> 34254885Sdumbbell#include <dev/drm2/radeon/radeon_drm.h> 35254885Sdumbbell#include "radeon_reg.h" 36254885Sdumbbell#include "radeon_irq_kms.h" 37254885Sdumbbell#include "radeon.h" 38254885Sdumbbell#include "atom.h" 39254885Sdumbbell 40254885Sdumbbell#define RADEON_WAIT_IDLE_TIMEOUT 200 41254885Sdumbbell 42254885Sdumbbell/** 43254885Sdumbbell * radeon_driver_irq_handler_kms - irq handler for KMS 44254885Sdumbbell * 45254885Sdumbbell * @DRM_IRQ_ARGS: args 46254885Sdumbbell * 47254885Sdumbbell * This is the irq handler for the radeon KMS driver (all asics). 48254885Sdumbbell * radeon_irq_process is a macro that points to the per-asic 49254885Sdumbbell * irq handler callback. 50254885Sdumbbell */ 51254885Sdumbbellirqreturn_t radeon_driver_irq_handler_kms(DRM_IRQ_ARGS) 52254885Sdumbbell{ 53254885Sdumbbell struct drm_device *dev = (struct drm_device *) arg; 54254885Sdumbbell struct radeon_device *rdev = dev->dev_private; 55254885Sdumbbell 56254885Sdumbbell return radeon_irq_process(rdev); 57254885Sdumbbell} 58254885Sdumbbell 59254885Sdumbbell/* 60254885Sdumbbell * Handle hotplug events outside the interrupt handler proper. 61254885Sdumbbell */ 62254885Sdumbbell/** 63254885Sdumbbell * radeon_hotplug_work_func - display hotplug work handler 64254885Sdumbbell * 65254885Sdumbbell * @work: work struct 66254885Sdumbbell * 67254885Sdumbbell * This is the hot plug event work handler (all asics). 68254885Sdumbbell * The work gets scheduled from the irq handler if there 69254885Sdumbbell * was a hot plug interrupt. It walks the connector table 70254885Sdumbbell * and calls the hotplug handler for each one, then sends 71254885Sdumbbell * a drm hotplug event to alert userspace. 72254885Sdumbbell */ 73254885Sdumbbellstatic void radeon_hotplug_work_func(void *arg, int pending) 74254885Sdumbbell{ 75254885Sdumbbell struct radeon_device *rdev = arg; 76254885Sdumbbell struct drm_device *dev = rdev->ddev; 77254885Sdumbbell struct drm_mode_config *mode_config = &dev->mode_config; 78254885Sdumbbell struct drm_connector *connector; 79254885Sdumbbell 80254885Sdumbbell if (mode_config->num_connector) { 81254885Sdumbbell list_for_each_entry(connector, &mode_config->connector_list, head) 82254885Sdumbbell radeon_connector_hotplug(connector); 83254885Sdumbbell } 84254885Sdumbbell /* Just fire off a uevent and let userspace tell us what to do */ 85254885Sdumbbell drm_helper_hpd_irq_event(dev); 86254885Sdumbbell} 87254885Sdumbbell 88254885Sdumbbell/** 89254885Sdumbbell * radeon_driver_irq_preinstall_kms - drm irq preinstall callback 90254885Sdumbbell * 91254885Sdumbbell * @dev: drm dev pointer 92254885Sdumbbell * 93254885Sdumbbell * Gets the hw ready to enable irqs (all asics). 94254885Sdumbbell * This function disables all interrupt sources on the GPU. 95254885Sdumbbell */ 96254885Sdumbbellvoid radeon_driver_irq_preinstall_kms(struct drm_device *dev) 97254885Sdumbbell{ 98254885Sdumbbell struct radeon_device *rdev = dev->dev_private; 99254885Sdumbbell unsigned long irqflags; 100254885Sdumbbell unsigned i; 101254885Sdumbbell 102254885Sdumbbell DRM_SPINLOCK_IRQSAVE(&rdev->irq.lock, irqflags); 103254885Sdumbbell /* Disable *all* interrupts */ 104254885Sdumbbell for (i = 0; i < RADEON_NUM_RINGS; i++) 105254885Sdumbbell atomic_set(&rdev->irq.ring_int[i], 0); 106254885Sdumbbell for (i = 0; i < RADEON_MAX_HPD_PINS; i++) 107254885Sdumbbell rdev->irq.hpd[i] = false; 108254885Sdumbbell for (i = 0; i < RADEON_MAX_CRTCS; i++) { 109254885Sdumbbell rdev->irq.crtc_vblank_int[i] = false; 110254885Sdumbbell atomic_set(&rdev->irq.pflip[i], 0); 111254885Sdumbbell rdev->irq.afmt[i] = false; 112254885Sdumbbell } 113254885Sdumbbell radeon_irq_set(rdev); 114254885Sdumbbell DRM_SPINUNLOCK_IRQRESTORE(&rdev->irq.lock, irqflags); 115254885Sdumbbell /* Clear bits */ 116254885Sdumbbell radeon_irq_process(rdev); 117254885Sdumbbell} 118254885Sdumbbell 119254885Sdumbbell/** 120254885Sdumbbell * radeon_driver_irq_postinstall_kms - drm irq preinstall callback 121254885Sdumbbell * 122254885Sdumbbell * @dev: drm dev pointer 123254885Sdumbbell * 124254885Sdumbbell * Handles stuff to be done after enabling irqs (all asics). 125254885Sdumbbell * Returns 0 on success. 126254885Sdumbbell */ 127254885Sdumbbellint radeon_driver_irq_postinstall_kms(struct drm_device *dev) 128254885Sdumbbell{ 129254885Sdumbbell dev->max_vblank_count = 0x001fffff; 130254885Sdumbbell return 0; 131254885Sdumbbell} 132254885Sdumbbell 133254885Sdumbbell/** 134254885Sdumbbell * radeon_driver_irq_uninstall_kms - drm irq uninstall callback 135254885Sdumbbell * 136254885Sdumbbell * @dev: drm dev pointer 137254885Sdumbbell * 138254885Sdumbbell * This function disables all interrupt sources on the GPU (all asics). 139254885Sdumbbell */ 140254885Sdumbbellvoid radeon_driver_irq_uninstall_kms(struct drm_device *dev) 141254885Sdumbbell{ 142254885Sdumbbell struct radeon_device *rdev = dev->dev_private; 143254885Sdumbbell unsigned long irqflags; 144254885Sdumbbell unsigned i; 145254885Sdumbbell 146254885Sdumbbell if (rdev == NULL) { 147254885Sdumbbell return; 148254885Sdumbbell } 149254885Sdumbbell DRM_SPINLOCK_IRQSAVE(&rdev->irq.lock, irqflags); 150254885Sdumbbell /* Disable *all* interrupts */ 151254885Sdumbbell for (i = 0; i < RADEON_NUM_RINGS; i++) 152254885Sdumbbell atomic_set(&rdev->irq.ring_int[i], 0); 153254885Sdumbbell for (i = 0; i < RADEON_MAX_HPD_PINS; i++) 154254885Sdumbbell rdev->irq.hpd[i] = false; 155254885Sdumbbell for (i = 0; i < RADEON_MAX_CRTCS; i++) { 156254885Sdumbbell rdev->irq.crtc_vblank_int[i] = false; 157254885Sdumbbell atomic_set(&rdev->irq.pflip[i], 0); 158254885Sdumbbell rdev->irq.afmt[i] = false; 159254885Sdumbbell } 160254885Sdumbbell radeon_irq_set(rdev); 161254885Sdumbbell DRM_SPINUNLOCK_IRQRESTORE(&rdev->irq.lock, irqflags); 162254885Sdumbbell} 163254885Sdumbbell 164254885Sdumbbell/** 165254885Sdumbbell * radeon_msi_ok - asic specific msi checks 166254885Sdumbbell * 167254885Sdumbbell * @rdev: radeon device pointer 168254885Sdumbbell * 169254885Sdumbbell * Handles asic specific MSI checks to determine if 170254885Sdumbbell * MSIs should be enabled on a particular chip (all asics). 171254885Sdumbbell * Returns true if MSIs should be enabled, false if MSIs 172254885Sdumbbell * should not be enabled. 173254885Sdumbbell */ 174280183Sdumbbellstatic bool radeon_msi_ok(struct radeon_device *rdev) 175254885Sdumbbell{ 176254885Sdumbbell /* RV370/RV380 was first asic with MSI support */ 177280183Sdumbbell if (rdev->family < CHIP_RV380) 178254885Sdumbbell return false; 179254885Sdumbbell 180254885Sdumbbell /* MSIs don't work on AGP */ 181280183Sdumbbell if (rdev->flags & RADEON_IS_AGP) 182254885Sdumbbell return false; 183254885Sdumbbell 184254885Sdumbbell /* force MSI on */ 185254885Sdumbbell if (radeon_msi == 1) 186254885Sdumbbell return true; 187254885Sdumbbell else if (radeon_msi == 0) 188254885Sdumbbell return false; 189254885Sdumbbell 190254885Sdumbbell /* Quirks */ 191254885Sdumbbell /* HP RS690 only seems to work with MSIs. */ 192280183Sdumbbell if ((rdev->ddev->pci_device == 0x791f) && 193280183Sdumbbell (rdev->ddev->pci_subvendor == 0x103c) && 194280183Sdumbbell (rdev->ddev->pci_subdevice == 0x30c2)) 195254885Sdumbbell return true; 196254885Sdumbbell 197254885Sdumbbell /* Dell RS690 only seems to work with MSIs. */ 198280183Sdumbbell if ((rdev->ddev->pci_device == 0x791f) && 199280183Sdumbbell (rdev->ddev->pci_subvendor == 0x1028) && 200280183Sdumbbell (rdev->ddev->pci_subdevice == 0x01fc)) 201254885Sdumbbell return true; 202254885Sdumbbell 203254885Sdumbbell /* Dell RS690 only seems to work with MSIs. */ 204280183Sdumbbell if ((rdev->ddev->pci_device == 0x791f) && 205280183Sdumbbell (rdev->ddev->pci_subvendor == 0x1028) && 206280183Sdumbbell (rdev->ddev->pci_subdevice == 0x01fd)) 207254885Sdumbbell return true; 208254885Sdumbbell 209254885Sdumbbell /* Gateway RS690 only seems to work with MSIs. */ 210280183Sdumbbell if ((rdev->ddev->pci_device == 0x791f) && 211280183Sdumbbell (rdev->ddev->pci_subvendor == 0x107b) && 212280183Sdumbbell (rdev->ddev->pci_subdevice == 0x0185)) 213254885Sdumbbell return true; 214254885Sdumbbell 215254885Sdumbbell /* try and enable MSIs by default on all RS690s */ 216280183Sdumbbell if (rdev->family == CHIP_RS690) 217254885Sdumbbell return true; 218254885Sdumbbell 219254885Sdumbbell /* RV515 seems to have MSI issues where it loses 220254885Sdumbbell * MSI rearms occasionally. This leads to lockups and freezes. 221254885Sdumbbell * disable it by default. 222254885Sdumbbell */ 223280183Sdumbbell if (rdev->family == CHIP_RV515) 224254885Sdumbbell return false; 225280183Sdumbbell if (rdev->flags & RADEON_IS_IGP) { 226254885Sdumbbell /* APUs work fine with MSIs */ 227280183Sdumbbell if (rdev->family >= CHIP_PALM) 228254885Sdumbbell return true; 229254885Sdumbbell /* lots of IGPs have problems with MSIs */ 230254885Sdumbbell return false; 231254885Sdumbbell } 232254885Sdumbbell 233254885Sdumbbell return true; 234254885Sdumbbell} 235254885Sdumbbell 236254885Sdumbbell/** 237254885Sdumbbell * radeon_irq_kms_init - init driver interrupt info 238254885Sdumbbell * 239254885Sdumbbell * @rdev: radeon device pointer 240254885Sdumbbell * 241254885Sdumbbell * Sets up the work irq handlers, vblank init, MSIs, etc. (all asics). 242254885Sdumbbell * Returns 0 for success, error for failure. 243254885Sdumbbell */ 244254885Sdumbbellint radeon_irq_kms_init(struct radeon_device *rdev) 245254885Sdumbbell{ 246254885Sdumbbell int r = 0; 247254885Sdumbbell 248254885Sdumbbell TASK_INIT(&rdev->hotplug_work, 0, radeon_hotplug_work_func, rdev); 249254885Sdumbbell TASK_INIT(&rdev->audio_work, 0, r600_audio_update_hdmi, rdev); 250254885Sdumbbell 251254885Sdumbbell DRM_SPININIT(&rdev->irq.lock, "drm__radeon_device__irq__lock"); 252254885Sdumbbell r = drm_vblank_init(rdev->ddev, rdev->num_crtc); 253254885Sdumbbell if (r) { 254254885Sdumbbell return r; 255254885Sdumbbell } 256254885Sdumbbell /* enable msi */ 257280183Sdumbbell rdev->msi_enabled = 0; 258254885Sdumbbell 259280183Sdumbbell if (radeon_msi_ok(rdev)) { 260280183Sdumbbell int ret = drm_pci_enable_msi(rdev->ddev); 261280183Sdumbbell if (!ret) { 262280183Sdumbbell rdev->msi_enabled = 1; 263280183Sdumbbell dev_info(rdev->dev, "radeon: using MSI.\n"); 264280183Sdumbbell } 265280183Sdumbbell } 266254885Sdumbbell rdev->irq.installed = true; 267254885Sdumbbell r = drm_irq_install(rdev->ddev); 268254885Sdumbbell if (r) { 269254885Sdumbbell rdev->irq.installed = false; 270254885Sdumbbell return r; 271254885Sdumbbell } 272254885Sdumbbell DRM_INFO("radeon: irq initialized.\n"); 273254885Sdumbbell return 0; 274254885Sdumbbell} 275254885Sdumbbell 276254885Sdumbbell/** 277254885Sdumbbell * radeon_irq_kms_fini - tear down driver interrrupt info 278254885Sdumbbell * 279254885Sdumbbell * @rdev: radeon device pointer 280254885Sdumbbell * 281254885Sdumbbell * Tears down the work irq handlers, vblank handlers, MSIs, etc. (all asics). 282254885Sdumbbell */ 283254885Sdumbbellvoid radeon_irq_kms_fini(struct radeon_device *rdev) 284254885Sdumbbell{ 285254885Sdumbbell drm_vblank_cleanup(rdev->ddev); 286254885Sdumbbell if (rdev->irq.installed) { 287254885Sdumbbell drm_irq_uninstall(rdev->ddev); 288254885Sdumbbell rdev->irq.installed = false; 289280183Sdumbbell if (rdev->msi_enabled) 290280183Sdumbbell drm_pci_disable_msi(rdev->ddev); 291254885Sdumbbell } 292254885Sdumbbell taskqueue_drain(rdev->tq, &rdev->hotplug_work); 293254885Sdumbbell} 294254885Sdumbbell 295254885Sdumbbell/** 296254885Sdumbbell * radeon_irq_kms_sw_irq_get - enable software interrupt 297254885Sdumbbell * 298254885Sdumbbell * @rdev: radeon device pointer 299254885Sdumbbell * @ring: ring whose interrupt you want to enable 300254885Sdumbbell * 301254885Sdumbbell * Enables the software interrupt for a specific ring (all asics). 302254885Sdumbbell * The software interrupt is generally used to signal a fence on 303254885Sdumbbell * a particular ring. 304254885Sdumbbell */ 305254885Sdumbbellvoid radeon_irq_kms_sw_irq_get(struct radeon_device *rdev, int ring) 306254885Sdumbbell{ 307254885Sdumbbell unsigned long irqflags; 308254885Sdumbbell 309254885Sdumbbell if (!rdev->ddev->irq_enabled) 310254885Sdumbbell return; 311254885Sdumbbell 312254885Sdumbbell if (atomic_inc_return(&rdev->irq.ring_int[ring]) == 1) { 313254885Sdumbbell DRM_SPINLOCK_IRQSAVE(&rdev->irq.lock, irqflags); 314254885Sdumbbell radeon_irq_set(rdev); 315254885Sdumbbell DRM_SPINUNLOCK_IRQRESTORE(&rdev->irq.lock, irqflags); 316254885Sdumbbell } 317254885Sdumbbell} 318254885Sdumbbell 319254885Sdumbbell/** 320254885Sdumbbell * radeon_irq_kms_sw_irq_put - disable software interrupt 321254885Sdumbbell * 322254885Sdumbbell * @rdev: radeon device pointer 323254885Sdumbbell * @ring: ring whose interrupt you want to disable 324254885Sdumbbell * 325254885Sdumbbell * Disables the software interrupt for a specific ring (all asics). 326254885Sdumbbell * The software interrupt is generally used to signal a fence on 327254885Sdumbbell * a particular ring. 328254885Sdumbbell */ 329254885Sdumbbellvoid radeon_irq_kms_sw_irq_put(struct radeon_device *rdev, int ring) 330254885Sdumbbell{ 331254885Sdumbbell unsigned long irqflags; 332254885Sdumbbell 333254885Sdumbbell if (!rdev->ddev->irq_enabled) 334254885Sdumbbell return; 335254885Sdumbbell 336254885Sdumbbell if (atomic_dec_and_test(&rdev->irq.ring_int[ring])) { 337254885Sdumbbell DRM_SPINLOCK_IRQSAVE(&rdev->irq.lock, irqflags); 338254885Sdumbbell radeon_irq_set(rdev); 339254885Sdumbbell DRM_SPINUNLOCK_IRQRESTORE(&rdev->irq.lock, irqflags); 340254885Sdumbbell } 341254885Sdumbbell} 342254885Sdumbbell 343254885Sdumbbell/** 344254885Sdumbbell * radeon_irq_kms_pflip_irq_get - enable pageflip interrupt 345254885Sdumbbell * 346254885Sdumbbell * @rdev: radeon device pointer 347254885Sdumbbell * @crtc: crtc whose interrupt you want to enable 348254885Sdumbbell * 349254885Sdumbbell * Enables the pageflip interrupt for a specific crtc (all asics). 350254885Sdumbbell * For pageflips we use the vblank interrupt source. 351254885Sdumbbell */ 352254885Sdumbbellvoid radeon_irq_kms_pflip_irq_get(struct radeon_device *rdev, int crtc) 353254885Sdumbbell{ 354254885Sdumbbell unsigned long irqflags; 355254885Sdumbbell 356254885Sdumbbell if (crtc < 0 || crtc >= rdev->num_crtc) 357254885Sdumbbell return; 358254885Sdumbbell 359254885Sdumbbell if (!rdev->ddev->irq_enabled) 360254885Sdumbbell return; 361254885Sdumbbell 362254885Sdumbbell if (atomic_inc_return(&rdev->irq.pflip[crtc]) == 1) { 363254885Sdumbbell DRM_SPINLOCK_IRQSAVE(&rdev->irq.lock, irqflags); 364254885Sdumbbell radeon_irq_set(rdev); 365254885Sdumbbell DRM_SPINUNLOCK_IRQRESTORE(&rdev->irq.lock, irqflags); 366254885Sdumbbell } 367254885Sdumbbell} 368254885Sdumbbell 369254885Sdumbbell/** 370254885Sdumbbell * radeon_irq_kms_pflip_irq_put - disable pageflip interrupt 371254885Sdumbbell * 372254885Sdumbbell * @rdev: radeon device pointer 373254885Sdumbbell * @crtc: crtc whose interrupt you want to disable 374254885Sdumbbell * 375254885Sdumbbell * Disables the pageflip interrupt for a specific crtc (all asics). 376254885Sdumbbell * For pageflips we use the vblank interrupt source. 377254885Sdumbbell */ 378254885Sdumbbellvoid radeon_irq_kms_pflip_irq_put(struct radeon_device *rdev, int crtc) 379254885Sdumbbell{ 380254885Sdumbbell unsigned long irqflags; 381254885Sdumbbell 382254885Sdumbbell if (crtc < 0 || crtc >= rdev->num_crtc) 383254885Sdumbbell return; 384254885Sdumbbell 385254885Sdumbbell if (!rdev->ddev->irq_enabled) 386254885Sdumbbell return; 387254885Sdumbbell 388254885Sdumbbell if (atomic_dec_and_test(&rdev->irq.pflip[crtc])) { 389254885Sdumbbell DRM_SPINLOCK_IRQSAVE(&rdev->irq.lock, irqflags); 390254885Sdumbbell radeon_irq_set(rdev); 391254885Sdumbbell DRM_SPINUNLOCK_IRQRESTORE(&rdev->irq.lock, irqflags); 392254885Sdumbbell } 393254885Sdumbbell} 394254885Sdumbbell 395254885Sdumbbell/** 396254885Sdumbbell * radeon_irq_kms_enable_afmt - enable audio format change interrupt 397254885Sdumbbell * 398254885Sdumbbell * @rdev: radeon device pointer 399254885Sdumbbell * @block: afmt block whose interrupt you want to enable 400254885Sdumbbell * 401254885Sdumbbell * Enables the afmt change interrupt for a specific afmt block (all asics). 402254885Sdumbbell */ 403254885Sdumbbellvoid radeon_irq_kms_enable_afmt(struct radeon_device *rdev, int block) 404254885Sdumbbell{ 405254885Sdumbbell unsigned long irqflags; 406254885Sdumbbell 407280183Sdumbbell if (!rdev->ddev->irq_enabled) 408280183Sdumbbell return; 409280183Sdumbbell 410254885Sdumbbell DRM_SPINLOCK_IRQSAVE(&rdev->irq.lock, irqflags); 411254885Sdumbbell rdev->irq.afmt[block] = true; 412254885Sdumbbell radeon_irq_set(rdev); 413254885Sdumbbell DRM_SPINUNLOCK_IRQRESTORE(&rdev->irq.lock, irqflags); 414254885Sdumbbell 415254885Sdumbbell} 416254885Sdumbbell 417254885Sdumbbell/** 418254885Sdumbbell * radeon_irq_kms_disable_afmt - disable audio format change interrupt 419254885Sdumbbell * 420254885Sdumbbell * @rdev: radeon device pointer 421254885Sdumbbell * @block: afmt block whose interrupt you want to disable 422254885Sdumbbell * 423254885Sdumbbell * Disables the afmt change interrupt for a specific afmt block (all asics). 424254885Sdumbbell */ 425254885Sdumbbellvoid radeon_irq_kms_disable_afmt(struct radeon_device *rdev, int block) 426254885Sdumbbell{ 427254885Sdumbbell unsigned long irqflags; 428254885Sdumbbell 429280183Sdumbbell if (!rdev->ddev->irq_enabled) 430280183Sdumbbell return; 431280183Sdumbbell 432254885Sdumbbell DRM_SPINLOCK_IRQSAVE(&rdev->irq.lock, irqflags); 433254885Sdumbbell rdev->irq.afmt[block] = false; 434254885Sdumbbell radeon_irq_set(rdev); 435254885Sdumbbell DRM_SPINUNLOCK_IRQRESTORE(&rdev->irq.lock, irqflags); 436254885Sdumbbell} 437254885Sdumbbell 438254885Sdumbbell/** 439254885Sdumbbell * radeon_irq_kms_enable_hpd - enable hotplug detect interrupt 440254885Sdumbbell * 441254885Sdumbbell * @rdev: radeon device pointer 442254885Sdumbbell * @hpd_mask: mask of hpd pins you want to enable. 443254885Sdumbbell * 444254885Sdumbbell * Enables the hotplug detect interrupt for a specific hpd pin (all asics). 445254885Sdumbbell */ 446254885Sdumbbellvoid radeon_irq_kms_enable_hpd(struct radeon_device *rdev, unsigned hpd_mask) 447254885Sdumbbell{ 448254885Sdumbbell unsigned long irqflags; 449254885Sdumbbell int i; 450254885Sdumbbell 451280183Sdumbbell if (!rdev->ddev->irq_enabled) 452280183Sdumbbell return; 453280183Sdumbbell 454254885Sdumbbell DRM_SPINLOCK_IRQSAVE(&rdev->irq.lock, irqflags); 455254885Sdumbbell for (i = 0; i < RADEON_MAX_HPD_PINS; ++i) 456254885Sdumbbell rdev->irq.hpd[i] |= !!(hpd_mask & (1 << i)); 457254885Sdumbbell radeon_irq_set(rdev); 458254885Sdumbbell DRM_SPINUNLOCK_IRQRESTORE(&rdev->irq.lock, irqflags); 459254885Sdumbbell} 460254885Sdumbbell 461254885Sdumbbell/** 462254885Sdumbbell * radeon_irq_kms_disable_hpd - disable hotplug detect interrupt 463254885Sdumbbell * 464254885Sdumbbell * @rdev: radeon device pointer 465254885Sdumbbell * @hpd_mask: mask of hpd pins you want to disable. 466254885Sdumbbell * 467254885Sdumbbell * Disables the hotplug detect interrupt for a specific hpd pin (all asics). 468254885Sdumbbell */ 469254885Sdumbbellvoid radeon_irq_kms_disable_hpd(struct radeon_device *rdev, unsigned hpd_mask) 470254885Sdumbbell{ 471254885Sdumbbell unsigned long irqflags; 472254885Sdumbbell int i; 473254885Sdumbbell 474280183Sdumbbell if (!rdev->ddev->irq_enabled) 475280183Sdumbbell return; 476280183Sdumbbell 477254885Sdumbbell DRM_SPINLOCK_IRQSAVE(&rdev->irq.lock, irqflags); 478254885Sdumbbell for (i = 0; i < RADEON_MAX_HPD_PINS; ++i) 479254885Sdumbbell rdev->irq.hpd[i] &= !(hpd_mask & (1 << i)); 480254885Sdumbbell radeon_irq_set(rdev); 481254885Sdumbbell DRM_SPINUNLOCK_IRQRESTORE(&rdev->irq.lock, irqflags); 482254885Sdumbbell} 483254885Sdumbbell 484