1 /* 2 * Copyright 2008 Advanced Micro Devices, Inc. 3 * Copyright 2008 Red Hat Inc. 4 * Copyright 2009 Jerome Glisse. 5 * 6 * Permission is hereby granted, free of charge, to any person obtaining a 7 * copy of this software and associated documentation files (the "Software"), 8 * to deal in the Software without restriction, including without limitation 9 * the rights to use, copy, modify, merge, publish, distribute, sublicense, 10 * and/or sell copies of the Software, and to permit persons to whom the 11 * Software is furnished to do so, subject to the following conditions: 12 * 13 * The above copyright notice and this permission notice shall be included in 14 * all copies or substantial portions of the Software. 15 * 16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 19 * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR 20 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 21 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 22 * OTHER DEALINGS IN THE SOFTWARE. 23 * 24 * Authors: Dave Airlie 25 * Alex Deucher 26 * Jerome Glisse 27 * 28 * $FreeBSD: head/sys/dev/drm2/radeon/radeon_irq_kms.c 254885 2013-08-25 19:37:15Z dumbbell $ 29 */ 30 31 #include <drm/drmP.h> 32 #include <drm/drm_crtc_helper.h> 33 #include <uapi_drm/radeon_drm.h> 34 #include "radeon_reg.h" 35 #include "radeon_irq_kms.h" 36 #include "radeon.h" 37 #include "atom.h" 38 39 #define RADEON_WAIT_IDLE_TIMEOUT 200 40 41 /** 42 * radeon_driver_irq_handler_kms - irq handler for KMS 43 * 44 * @DRM_IRQ_ARGS: args 45 * 46 * This is the irq handler for the radeon KMS driver (all asics). 47 * radeon_irq_process is a macro that points to the per-asic 48 * irq handler callback. 49 */ 50 irqreturn_t radeon_driver_irq_handler_kms(DRM_IRQ_ARGS) 51 { 52 struct drm_device *dev = (struct drm_device *) arg; 53 struct radeon_device *rdev = dev->dev_private; 54 55 return radeon_irq_process(rdev); 56 } 57 58 /* 59 * Handle hotplug events outside the interrupt handler proper. 60 */ 61 /** 62 * radeon_hotplug_work_func - display hotplug work handler 63 * 64 * @work: work struct 65 * 66 * This is the hot plug event work handler (all asics). 67 * The work gets scheduled from the irq handler if there 68 * was a hot plug interrupt. It walks the connector table 69 * and calls the hotplug handler for each one, then sends 70 * a drm hotplug event to alert userspace. 71 */ 72 static void radeon_hotplug_work_func(void *arg, int pending) 73 { 74 struct radeon_device *rdev = arg; 75 struct drm_device *dev = rdev->ddev; 76 struct drm_mode_config *mode_config = &dev->mode_config; 77 struct drm_connector *connector; 78 79 if (mode_config->num_connector) { 80 list_for_each_entry(connector, &mode_config->connector_list, head) 81 radeon_connector_hotplug(connector); 82 } 83 /* Just fire off a uevent and let userspace tell us what to do */ 84 drm_helper_hpd_irq_event(dev); 85 } 86 87 /** 88 * radeon_driver_irq_preinstall_kms - drm irq preinstall callback 89 * 90 * @dev: drm dev pointer 91 * 92 * Gets the hw ready to enable irqs (all asics). 93 * This function disables all interrupt sources on the GPU. 94 */ 95 void radeon_driver_irq_preinstall_kms(struct drm_device *dev) 96 { 97 struct radeon_device *rdev = dev->dev_private; 98 unsigned i; 99 100 lockmgr(&rdev->irq.lock, LK_EXCLUSIVE); 101 /* Disable *all* interrupts */ 102 for (i = 0; i < RADEON_NUM_RINGS; i++) 103 atomic_set(&rdev->irq.ring_int[i], 0); 104 for (i = 0; i < RADEON_MAX_HPD_PINS; i++) 105 rdev->irq.hpd[i] = false; 106 for (i = 0; i < RADEON_MAX_CRTCS; i++) { 107 rdev->irq.crtc_vblank_int[i] = false; 108 atomic_set(&rdev->irq.pflip[i], 0); 109 rdev->irq.afmt[i] = false; 110 } 111 radeon_irq_set(rdev); 112 lockmgr(&rdev->irq.lock, LK_RELEASE); 113 /* Clear bits */ 114 radeon_irq_process(rdev); 115 } 116 117 /** 118 * radeon_driver_irq_postinstall_kms - drm irq preinstall callback 119 * 120 * @dev: drm dev pointer 121 * 122 * Handles stuff to be done after enabling irqs (all asics). 123 * Returns 0 on success. 124 */ 125 int radeon_driver_irq_postinstall_kms(struct drm_device *dev) 126 { 127 dev->max_vblank_count = 0x001fffff; 128 return 0; 129 } 130 131 /** 132 * radeon_driver_irq_uninstall_kms - drm irq uninstall callback 133 * 134 * @dev: drm dev pointer 135 * 136 * This function disables all interrupt sources on the GPU (all asics). 137 */ 138 void radeon_driver_irq_uninstall_kms(struct drm_device *dev) 139 { 140 struct radeon_device *rdev = dev->dev_private; 141 unsigned i; 142 143 if (rdev == NULL) { 144 return; 145 } 146 lockmgr(&rdev->irq.lock, LK_EXCLUSIVE); 147 /* Disable *all* interrupts */ 148 for (i = 0; i < RADEON_NUM_RINGS; i++) 149 atomic_set(&rdev->irq.ring_int[i], 0); 150 for (i = 0; i < RADEON_MAX_HPD_PINS; i++) 151 rdev->irq.hpd[i] = false; 152 for (i = 0; i < RADEON_MAX_CRTCS; i++) { 153 rdev->irq.crtc_vblank_int[i] = false; 154 atomic_set(&rdev->irq.pflip[i], 0); 155 rdev->irq.afmt[i] = false; 156 } 157 radeon_irq_set(rdev); 158 lockmgr(&rdev->irq.lock, LK_RELEASE); 159 } 160 161 /** 162 * radeon_msi_ok - asic specific msi checks 163 * 164 * @rdev: radeon device pointer 165 * 166 * Handles asic specific MSI checks to determine if 167 * MSIs should be enabled on a particular chip (all asics). 168 * Returns true if MSIs should be enabled, false if MSIs 169 * should not be enabled. 170 */ 171 int radeon_msi_ok(struct drm_device *dev, unsigned long flags) 172 { 173 int family; 174 175 family = flags & RADEON_FAMILY_MASK; 176 177 /* RV370/RV380 was first asic with MSI support */ 178 if (family < CHIP_RV380) 179 return false; 180 181 /* MSIs don't work on AGP */ 182 if (drm_device_is_agp(dev)) 183 return false; 184 185 /* force MSI on */ 186 if (radeon_msi == 1) 187 return true; 188 else if (radeon_msi == 0) 189 return false; 190 191 /* Quirks */ 192 /* HP RS690 only seems to work with MSIs. */ 193 if ((dev->pci_device == 0x791f) && 194 (dev->pci_subvendor == 0x103c) && 195 (dev->pci_subdevice == 0x30c2)) 196 return true; 197 198 /* Dell RS690 only seems to work with MSIs. */ 199 if ((dev->pci_device == 0x791f) && 200 (dev->pci_subvendor == 0x1028) && 201 (dev->pci_subdevice == 0x01fc)) 202 return true; 203 204 /* Dell RS690 only seems to work with MSIs. */ 205 if ((dev->pci_device == 0x791f) && 206 (dev->pci_subvendor == 0x1028) && 207 (dev->pci_subdevice == 0x01fd)) 208 return true; 209 210 /* Gateway RS690 only seems to work with MSIs. */ 211 if ((dev->pci_device == 0x791f) && 212 (dev->pci_subvendor == 0x107b) && 213 (dev->pci_subdevice == 0x0185)) 214 return true; 215 216 /* try and enable MSIs by default on all RS690s */ 217 if (family == CHIP_RS690) 218 return true; 219 220 /* RV515 seems to have MSI issues where it loses 221 * MSI rearms occasionally. This leads to lockups and freezes. 222 * disable it by default. 223 */ 224 if (family == CHIP_RV515) 225 return false; 226 if (flags & RADEON_IS_IGP) { 227 /* APUs work fine with MSIs */ 228 if (family >= CHIP_PALM) 229 return true; 230 /* lots of IGPs have problems with MSIs */ 231 return false; 232 } 233 234 return true; 235 } 236 237 /** 238 * radeon_irq_kms_init - init driver interrupt info 239 * 240 * @rdev: radeon device pointer 241 * 242 * Sets up the work irq handlers, vblank init, MSIs, etc. (all asics). 243 * Returns 0 for success, error for failure. 244 */ 245 int radeon_irq_kms_init(struct radeon_device *rdev) 246 { 247 int r = 0; 248 249 TASK_INIT(&rdev->hotplug_work, 0, radeon_hotplug_work_func, rdev); 250 TASK_INIT(&rdev->audio_work, 0, r600_audio_update_hdmi, rdev); 251 252 lockinit(&rdev->irq.lock, "drm__radeon_device__irq__lock", 0, LK_CANRECURSE); 253 r = drm_vblank_init(rdev->ddev, rdev->num_crtc); 254 if (r) { 255 return r; 256 } 257 /* enable msi */ 258 rdev->msi_enabled = rdev->ddev->msi_enabled; 259 260 rdev->irq.installed = true; 261 DRM_UNLOCK(rdev->ddev); 262 r = drm_irq_install(rdev->ddev); 263 DRM_LOCK(rdev->ddev); 264 if (r) { 265 rdev->irq.installed = false; 266 return r; 267 } 268 DRM_INFO("radeon: irq initialized.\n"); 269 return 0; 270 } 271 272 /** 273 * radeon_irq_kms_fini - tear down driver interrrupt info 274 * 275 * @rdev: radeon device pointer 276 * 277 * Tears down the work irq handlers, vblank handlers, MSIs, etc. (all asics). 278 */ 279 void radeon_irq_kms_fini(struct radeon_device *rdev) 280 { 281 drm_vblank_cleanup(rdev->ddev); 282 if (rdev->irq.installed) { 283 drm_irq_uninstall(rdev->ddev); 284 rdev->irq.installed = false; 285 } 286 taskqueue_drain(rdev->tq, &rdev->hotplug_work); 287 } 288 289 /** 290 * radeon_irq_kms_sw_irq_get - enable software interrupt 291 * 292 * @rdev: radeon device pointer 293 * @ring: ring whose interrupt you want to enable 294 * 295 * Enables the software interrupt for a specific ring (all asics). 296 * The software interrupt is generally used to signal a fence on 297 * a particular ring. 298 */ 299 void radeon_irq_kms_sw_irq_get(struct radeon_device *rdev, int ring) 300 { 301 if (!rdev->ddev->irq_enabled) 302 return; 303 304 if (atomic_inc_return(&rdev->irq.ring_int[ring]) == 1) { 305 lockmgr(&rdev->irq.lock, LK_EXCLUSIVE); 306 radeon_irq_set(rdev); 307 lockmgr(&rdev->irq.lock, LK_RELEASE); 308 } 309 } 310 311 /** 312 * radeon_irq_kms_sw_irq_put - disable software interrupt 313 * 314 * @rdev: radeon device pointer 315 * @ring: ring whose interrupt you want to disable 316 * 317 * Disables the software interrupt for a specific ring (all asics). 318 * The software interrupt is generally used to signal a fence on 319 * a particular ring. 320 */ 321 void radeon_irq_kms_sw_irq_put(struct radeon_device *rdev, int ring) 322 { 323 if (!rdev->ddev->irq_enabled) 324 return; 325 326 if (atomic_dec_and_test(&rdev->irq.ring_int[ring])) { 327 lockmgr(&rdev->irq.lock, LK_EXCLUSIVE); 328 radeon_irq_set(rdev); 329 lockmgr(&rdev->irq.lock, LK_RELEASE); 330 } 331 } 332 333 /** 334 * radeon_irq_kms_pflip_irq_get - enable pageflip interrupt 335 * 336 * @rdev: radeon device pointer 337 * @crtc: crtc whose interrupt you want to enable 338 * 339 * Enables the pageflip interrupt for a specific crtc (all asics). 340 * For pageflips we use the vblank interrupt source. 341 */ 342 void radeon_irq_kms_pflip_irq_get(struct radeon_device *rdev, int crtc) 343 { 344 if (crtc < 0 || crtc >= rdev->num_crtc) 345 return; 346 347 if (!rdev->ddev->irq_enabled) 348 return; 349 350 if (atomic_inc_return(&rdev->irq.pflip[crtc]) == 1) { 351 lockmgr(&rdev->irq.lock, LK_EXCLUSIVE); 352 radeon_irq_set(rdev); 353 lockmgr(&rdev->irq.lock, LK_RELEASE); 354 } 355 } 356 357 /** 358 * radeon_irq_kms_pflip_irq_put - disable pageflip interrupt 359 * 360 * @rdev: radeon device pointer 361 * @crtc: crtc whose interrupt you want to disable 362 * 363 * Disables the pageflip interrupt for a specific crtc (all asics). 364 * For pageflips we use the vblank interrupt source. 365 */ 366 void radeon_irq_kms_pflip_irq_put(struct radeon_device *rdev, int crtc) 367 { 368 if (crtc < 0 || crtc >= rdev->num_crtc) 369 return; 370 371 if (!rdev->ddev->irq_enabled) 372 return; 373 374 if (atomic_dec_and_test(&rdev->irq.pflip[crtc])) { 375 lockmgr(&rdev->irq.lock, LK_EXCLUSIVE); 376 radeon_irq_set(rdev); 377 lockmgr(&rdev->irq.lock, LK_RELEASE); 378 } 379 } 380 381 /** 382 * radeon_irq_kms_enable_afmt - enable audio format change interrupt 383 * 384 * @rdev: radeon device pointer 385 * @block: afmt block whose interrupt you want to enable 386 * 387 * Enables the afmt change interrupt for a specific afmt block (all asics). 388 */ 389 void radeon_irq_kms_enable_afmt(struct radeon_device *rdev, int block) 390 { 391 lockmgr(&rdev->irq.lock, LK_EXCLUSIVE); 392 rdev->irq.afmt[block] = true; 393 radeon_irq_set(rdev); 394 lockmgr(&rdev->irq.lock, LK_RELEASE); 395 396 } 397 398 /** 399 * radeon_irq_kms_disable_afmt - disable audio format change interrupt 400 * 401 * @rdev: radeon device pointer 402 * @block: afmt block whose interrupt you want to disable 403 * 404 * Disables the afmt change interrupt for a specific afmt block (all asics). 405 */ 406 void radeon_irq_kms_disable_afmt(struct radeon_device *rdev, int block) 407 { 408 lockmgr(&rdev->irq.lock, LK_EXCLUSIVE); 409 rdev->irq.afmt[block] = false; 410 radeon_irq_set(rdev); 411 lockmgr(&rdev->irq.lock, LK_RELEASE); 412 } 413 414 /** 415 * radeon_irq_kms_enable_hpd - enable hotplug detect interrupt 416 * 417 * @rdev: radeon device pointer 418 * @hpd_mask: mask of hpd pins you want to enable. 419 * 420 * Enables the hotplug detect interrupt for a specific hpd pin (all asics). 421 */ 422 void radeon_irq_kms_enable_hpd(struct radeon_device *rdev, unsigned hpd_mask) 423 { 424 int i; 425 426 lockmgr(&rdev->irq.lock, LK_EXCLUSIVE); 427 for (i = 0; i < RADEON_MAX_HPD_PINS; ++i) 428 rdev->irq.hpd[i] |= !!(hpd_mask & (1 << i)); 429 radeon_irq_set(rdev); 430 lockmgr(&rdev->irq.lock, LK_RELEASE); 431 } 432 433 /** 434 * radeon_irq_kms_disable_hpd - disable hotplug detect interrupt 435 * 436 * @rdev: radeon device pointer 437 * @hpd_mask: mask of hpd pins you want to disable. 438 * 439 * Disables the hotplug detect interrupt for a specific hpd pin (all asics). 440 */ 441 void radeon_irq_kms_disable_hpd(struct radeon_device *rdev, unsigned hpd_mask) 442 { 443 int i; 444 445 lockmgr(&rdev->irq.lock, LK_EXCLUSIVE); 446 for (i = 0; i < RADEON_MAX_HPD_PINS; ++i) 447 rdev->irq.hpd[i] &= !(hpd_mask & (1 << i)); 448 radeon_irq_set(rdev); 449 lockmgr(&rdev->irq.lock, LK_RELEASE); 450 } 451 452