linux/drivers/gpu/drm/radeon/radeon_irq_kms.c
<<
>>
Prefs
   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#include <drm/drmP.h>
  29#include <drm/drm_crtc_helper.h>
  30#include <drm/radeon_drm.h>
  31#include "radeon_reg.h"
  32#include "radeon.h"
  33#include "atom.h"
  34
  35#define RADEON_WAIT_IDLE_TIMEOUT 200
  36
  37/**
  38 * radeon_driver_irq_handler_kms - irq handler for KMS
  39 *
  40 * @DRM_IRQ_ARGS: args
  41 *
  42 * This is the irq handler for the radeon KMS driver (all asics).
  43 * radeon_irq_process is a macro that points to the per-asic
  44 * irq handler callback.
  45 */
  46irqreturn_t radeon_driver_irq_handler_kms(DRM_IRQ_ARGS)
  47{
  48        struct drm_device *dev = (struct drm_device *) arg;
  49        struct radeon_device *rdev = dev->dev_private;
  50
  51        return radeon_irq_process(rdev);
  52}
  53
  54/*
  55 * Handle hotplug events outside the interrupt handler proper.
  56 */
  57/**
  58 * radeon_hotplug_work_func - display hotplug work handler
  59 *
  60 * @work: work struct
  61 *
  62 * This is the hot plug event work handler (all asics).
  63 * The work gets scheduled from the irq handler if there
  64 * was a hot plug interrupt.  It walks the connector table
  65 * and calls the hotplug handler for each one, then sends
  66 * a drm hotplug event to alert userspace.
  67 */
  68static void radeon_hotplug_work_func(struct work_struct *work)
  69{
  70        struct radeon_device *rdev = container_of(work, struct radeon_device,
  71                                                  hotplug_work);
  72        struct drm_device *dev = rdev->ddev;
  73        struct drm_mode_config *mode_config = &dev->mode_config;
  74        struct drm_connector *connector;
  75
  76        if (mode_config->num_connector) {
  77                list_for_each_entry(connector, &mode_config->connector_list, head)
  78                        radeon_connector_hotplug(connector);
  79        }
  80        /* Just fire off a uevent and let userspace tell us what to do */
  81        drm_helper_hpd_irq_event(dev);
  82}
  83
  84/**
  85 * radeon_irq_reset_work_func - execute gpu reset
  86 *
  87 * @work: work struct
  88 *
  89 * Execute scheduled gpu reset (cayman+).
  90 * This function is called when the irq handler
  91 * thinks we need a gpu reset.
  92 */
  93static void radeon_irq_reset_work_func(struct work_struct *work)
  94{
  95        struct radeon_device *rdev = container_of(work, struct radeon_device,
  96                                                  reset_work);
  97
  98        radeon_gpu_reset(rdev);
  99}
 100
 101/**
 102 * radeon_driver_irq_preinstall_kms - drm irq preinstall callback
 103 *
 104 * @dev: drm dev pointer
 105 *
 106 * Gets the hw ready to enable irqs (all asics).
 107 * This function disables all interrupt sources on the GPU.
 108 */
 109void radeon_driver_irq_preinstall_kms(struct drm_device *dev)
 110{
 111        struct radeon_device *rdev = dev->dev_private;
 112        unsigned long irqflags;
 113        unsigned i;
 114
 115        spin_lock_irqsave(&rdev->irq.lock, irqflags);
 116        /* Disable *all* interrupts */
 117        for (i = 0; i < RADEON_NUM_RINGS; i++)
 118                atomic_set(&rdev->irq.ring_int[i], 0);
 119        rdev->irq.dpm_thermal = false;
 120        for (i = 0; i < RADEON_MAX_HPD_PINS; i++)
 121                rdev->irq.hpd[i] = false;
 122        for (i = 0; i < RADEON_MAX_CRTCS; i++) {
 123                rdev->irq.crtc_vblank_int[i] = false;
 124                atomic_set(&rdev->irq.pflip[i], 0);
 125                rdev->irq.afmt[i] = false;
 126        }
 127        radeon_irq_set(rdev);
 128        spin_unlock_irqrestore(&rdev->irq.lock, irqflags);
 129        /* Clear bits */
 130        radeon_irq_process(rdev);
 131}
 132
 133/**
 134 * radeon_driver_irq_postinstall_kms - drm irq preinstall callback
 135 *
 136 * @dev: drm dev pointer
 137 *
 138 * Handles stuff to be done after enabling irqs (all asics).
 139 * Returns 0 on success.
 140 */
 141int radeon_driver_irq_postinstall_kms(struct drm_device *dev)
 142{
 143        dev->max_vblank_count = 0x001fffff;
 144        return 0;
 145}
 146
 147/**
 148 * radeon_driver_irq_uninstall_kms - drm irq uninstall callback
 149 *
 150 * @dev: drm dev pointer
 151 *
 152 * This function disables all interrupt sources on the GPU (all asics).
 153 */
 154void radeon_driver_irq_uninstall_kms(struct drm_device *dev)
 155{
 156        struct radeon_device *rdev = dev->dev_private;
 157        unsigned long irqflags;
 158        unsigned i;
 159
 160        if (rdev == NULL) {
 161                return;
 162        }
 163        spin_lock_irqsave(&rdev->irq.lock, irqflags);
 164        /* Disable *all* interrupts */
 165        for (i = 0; i < RADEON_NUM_RINGS; i++)
 166                atomic_set(&rdev->irq.ring_int[i], 0);
 167        rdev->irq.dpm_thermal = false;
 168        for (i = 0; i < RADEON_MAX_HPD_PINS; i++)
 169                rdev->irq.hpd[i] = false;
 170        for (i = 0; i < RADEON_MAX_CRTCS; i++) {
 171                rdev->irq.crtc_vblank_int[i] = false;
 172                atomic_set(&rdev->irq.pflip[i], 0);
 173                rdev->irq.afmt[i] = false;
 174        }
 175        radeon_irq_set(rdev);
 176        spin_unlock_irqrestore(&rdev->irq.lock, irqflags);
 177}
 178
 179/**
 180 * radeon_msi_ok - asic specific msi checks
 181 *
 182 * @rdev: radeon device pointer
 183 *
 184 * Handles asic specific MSI checks to determine if
 185 * MSIs should be enabled on a particular chip (all asics).
 186 * Returns true if MSIs should be enabled, false if MSIs
 187 * should not be enabled.
 188 */
 189static bool radeon_msi_ok(struct radeon_device *rdev)
 190{
 191        /* RV370/RV380 was first asic with MSI support */
 192        if (rdev->family < CHIP_RV380)
 193                return false;
 194
 195        /* MSIs don't work on AGP */
 196        if (rdev->flags & RADEON_IS_AGP)
 197                return false;
 198
 199        /* force MSI on */
 200        if (radeon_msi == 1)
 201                return true;
 202        else if (radeon_msi == 0)
 203                return false;
 204
 205        /* Quirks */
 206        /* HP RS690 only seems to work with MSIs. */
 207        if ((rdev->pdev->device == 0x791f) &&
 208            (rdev->pdev->subsystem_vendor == 0x103c) &&
 209            (rdev->pdev->subsystem_device == 0x30c2))
 210                return true;
 211
 212        /* Dell RS690 only seems to work with MSIs. */
 213        if ((rdev->pdev->device == 0x791f) &&
 214            (rdev->pdev->subsystem_vendor == 0x1028) &&
 215            (rdev->pdev->subsystem_device == 0x01fc))
 216                return true;
 217
 218        /* Dell RS690 only seems to work with MSIs. */
 219        if ((rdev->pdev->device == 0x791f) &&
 220            (rdev->pdev->subsystem_vendor == 0x1028) &&
 221            (rdev->pdev->subsystem_device == 0x01fd))
 222                return true;
 223
 224        /* Gateway RS690 only seems to work with MSIs. */
 225        if ((rdev->pdev->device == 0x791f) &&
 226            (rdev->pdev->subsystem_vendor == 0x107b) &&
 227            (rdev->pdev->subsystem_device == 0x0185))
 228                return true;
 229
 230        /* try and enable MSIs by default on all RS690s */
 231        if (rdev->family == CHIP_RS690)
 232                return true;
 233
 234        /* RV515 seems to have MSI issues where it loses
 235         * MSI rearms occasionally. This leads to lockups and freezes.
 236         * disable it by default.
 237         */
 238        if (rdev->family == CHIP_RV515)
 239                return false;
 240        if (rdev->flags & RADEON_IS_IGP) {
 241                /* APUs work fine with MSIs */
 242                if (rdev->family >= CHIP_PALM)
 243                        return true;
 244                /* lots of IGPs have problems with MSIs */
 245                return false;
 246        }
 247
 248        return true;
 249}
 250
 251/**
 252 * radeon_irq_kms_init - init driver interrupt info
 253 *
 254 * @rdev: radeon device pointer
 255 *
 256 * Sets up the work irq handlers, vblank init, MSIs, etc. (all asics).
 257 * Returns 0 for success, error for failure.
 258 */
 259int radeon_irq_kms_init(struct radeon_device *rdev)
 260{
 261        int r = 0;
 262
 263        spin_lock_init(&rdev->irq.lock);
 264        r = drm_vblank_init(rdev->ddev, rdev->num_crtc);
 265        if (r) {
 266                return r;
 267        }
 268        /* enable msi */
 269        rdev->msi_enabled = 0;
 270
 271        if (radeon_msi_ok(rdev)) {
 272                int ret = pci_enable_msi(rdev->pdev);
 273                if (!ret) {
 274                        rdev->msi_enabled = 1;
 275                        dev_info(rdev->dev, "radeon: using MSI.\n");
 276                }
 277        }
 278
 279        INIT_WORK(&rdev->hotplug_work, radeon_hotplug_work_func);
 280        INIT_WORK(&rdev->audio_work, r600_audio_update_hdmi);
 281        INIT_WORK(&rdev->reset_work, radeon_irq_reset_work_func);
 282
 283        rdev->irq.installed = true;
 284        r = drm_irq_install(rdev->ddev);
 285        if (r) {
 286                rdev->irq.installed = false;
 287                flush_work(&rdev->hotplug_work);
 288                return r;
 289        }
 290
 291        DRM_INFO("radeon: irq initialized.\n");
 292        return 0;
 293}
 294
 295/**
 296 * radeon_irq_kms_fini - tear down driver interrupt info
 297 *
 298 * @rdev: radeon device pointer
 299 *
 300 * Tears down the work irq handlers, vblank handlers, MSIs, etc. (all asics).
 301 */
 302void radeon_irq_kms_fini(struct radeon_device *rdev)
 303{
 304        drm_vblank_cleanup(rdev->ddev);
 305        if (rdev->irq.installed) {
 306                drm_irq_uninstall(rdev->ddev);
 307                rdev->irq.installed = false;
 308                if (rdev->msi_enabled)
 309                        pci_disable_msi(rdev->pdev);
 310                flush_work(&rdev->hotplug_work);
 311        }
 312}
 313
 314/**
 315 * radeon_irq_kms_sw_irq_get - enable software interrupt
 316 *
 317 * @rdev: radeon device pointer
 318 * @ring: ring whose interrupt you want to enable
 319 *
 320 * Enables the software interrupt for a specific ring (all asics).
 321 * The software interrupt is generally used to signal a fence on
 322 * a particular ring.
 323 */
 324void radeon_irq_kms_sw_irq_get(struct radeon_device *rdev, int ring)
 325{
 326        unsigned long irqflags;
 327
 328        if (!rdev->ddev->irq_enabled)
 329                return;
 330
 331        if (atomic_inc_return(&rdev->irq.ring_int[ring]) == 1) {
 332                spin_lock_irqsave(&rdev->irq.lock, irqflags);
 333                radeon_irq_set(rdev);
 334                spin_unlock_irqrestore(&rdev->irq.lock, irqflags);
 335        }
 336}
 337
 338/**
 339 * radeon_irq_kms_sw_irq_put - disable software interrupt
 340 *
 341 * @rdev: radeon device pointer
 342 * @ring: ring whose interrupt you want to disable
 343 *
 344 * Disables the software interrupt for a specific ring (all asics).
 345 * The software interrupt is generally used to signal a fence on
 346 * a particular ring.
 347 */
 348void radeon_irq_kms_sw_irq_put(struct radeon_device *rdev, int ring)
 349{
 350        unsigned long irqflags;
 351
 352        if (!rdev->ddev->irq_enabled)
 353                return;
 354
 355        if (atomic_dec_and_test(&rdev->irq.ring_int[ring])) {
 356                spin_lock_irqsave(&rdev->irq.lock, irqflags);
 357                radeon_irq_set(rdev);
 358                spin_unlock_irqrestore(&rdev->irq.lock, irqflags);
 359        }
 360}
 361
 362/**
 363 * radeon_irq_kms_pflip_irq_get - enable pageflip interrupt
 364 *
 365 * @rdev: radeon device pointer
 366 * @crtc: crtc whose interrupt you want to enable
 367 *
 368 * Enables the pageflip interrupt for a specific crtc (all asics).
 369 * For pageflips we use the vblank interrupt source.
 370 */
 371void radeon_irq_kms_pflip_irq_get(struct radeon_device *rdev, int crtc)
 372{
 373        unsigned long irqflags;
 374
 375        if (crtc < 0 || crtc >= rdev->num_crtc)
 376                return;
 377
 378        if (!rdev->ddev->irq_enabled)
 379                return;
 380
 381        if (atomic_inc_return(&rdev->irq.pflip[crtc]) == 1) {
 382                spin_lock_irqsave(&rdev->irq.lock, irqflags);
 383                radeon_irq_set(rdev);
 384                spin_unlock_irqrestore(&rdev->irq.lock, irqflags);
 385        }
 386}
 387
 388/**
 389 * radeon_irq_kms_pflip_irq_put - disable pageflip interrupt
 390 *
 391 * @rdev: radeon device pointer
 392 * @crtc: crtc whose interrupt you want to disable
 393 *
 394 * Disables the pageflip interrupt for a specific crtc (all asics).
 395 * For pageflips we use the vblank interrupt source.
 396 */
 397void radeon_irq_kms_pflip_irq_put(struct radeon_device *rdev, int crtc)
 398{
 399        unsigned long irqflags;
 400
 401        if (crtc < 0 || crtc >= rdev->num_crtc)
 402                return;
 403
 404        if (!rdev->ddev->irq_enabled)
 405                return;
 406
 407        if (atomic_dec_and_test(&rdev->irq.pflip[crtc])) {
 408                spin_lock_irqsave(&rdev->irq.lock, irqflags);
 409                radeon_irq_set(rdev);
 410                spin_unlock_irqrestore(&rdev->irq.lock, irqflags);
 411        }
 412}
 413
 414/**
 415 * radeon_irq_kms_enable_afmt - enable audio format change interrupt
 416 *
 417 * @rdev: radeon device pointer
 418 * @block: afmt block whose interrupt you want to enable
 419 *
 420 * Enables the afmt change interrupt for a specific afmt block (all asics).
 421 */
 422void radeon_irq_kms_enable_afmt(struct radeon_device *rdev, int block)
 423{
 424        unsigned long irqflags;
 425
 426        if (!rdev->ddev->irq_enabled)
 427                return;
 428
 429        spin_lock_irqsave(&rdev->irq.lock, irqflags);
 430        rdev->irq.afmt[block] = true;
 431        radeon_irq_set(rdev);
 432        spin_unlock_irqrestore(&rdev->irq.lock, irqflags);
 433
 434}
 435
 436/**
 437 * radeon_irq_kms_disable_afmt - disable audio format change interrupt
 438 *
 439 * @rdev: radeon device pointer
 440 * @block: afmt block whose interrupt you want to disable
 441 *
 442 * Disables the afmt change interrupt for a specific afmt block (all asics).
 443 */
 444void radeon_irq_kms_disable_afmt(struct radeon_device *rdev, int block)
 445{
 446        unsigned long irqflags;
 447
 448        if (!rdev->ddev->irq_enabled)
 449                return;
 450
 451        spin_lock_irqsave(&rdev->irq.lock, irqflags);
 452        rdev->irq.afmt[block] = false;
 453        radeon_irq_set(rdev);
 454        spin_unlock_irqrestore(&rdev->irq.lock, irqflags);
 455}
 456
 457/**
 458 * radeon_irq_kms_enable_hpd - enable hotplug detect interrupt
 459 *
 460 * @rdev: radeon device pointer
 461 * @hpd_mask: mask of hpd pins you want to enable.
 462 *
 463 * Enables the hotplug detect interrupt for a specific hpd pin (all asics).
 464 */
 465void radeon_irq_kms_enable_hpd(struct radeon_device *rdev, unsigned hpd_mask)
 466{
 467        unsigned long irqflags;
 468        int i;
 469
 470        if (!rdev->ddev->irq_enabled)
 471                return;
 472
 473        spin_lock_irqsave(&rdev->irq.lock, irqflags);
 474        for (i = 0; i < RADEON_MAX_HPD_PINS; ++i)
 475                rdev->irq.hpd[i] |= !!(hpd_mask & (1 << i));
 476        radeon_irq_set(rdev);
 477        spin_unlock_irqrestore(&rdev->irq.lock, irqflags);
 478}
 479
 480/**
 481 * radeon_irq_kms_disable_hpd - disable hotplug detect interrupt
 482 *
 483 * @rdev: radeon device pointer
 484 * @hpd_mask: mask of hpd pins you want to disable.
 485 *
 486 * Disables the hotplug detect interrupt for a specific hpd pin (all asics).
 487 */
 488void radeon_irq_kms_disable_hpd(struct radeon_device *rdev, unsigned hpd_mask)
 489{
 490        unsigned long irqflags;
 491        int i;
 492
 493        if (!rdev->ddev->irq_enabled)
 494                return;
 495
 496        spin_lock_irqsave(&rdev->irq.lock, irqflags);
 497        for (i = 0; i < RADEON_MAX_HPD_PINS; ++i)
 498                rdev->irq.hpd[i] &= !(hpd_mask & (1 << i));
 499        radeon_irq_set(rdev);
 500        spin_unlock_irqrestore(&rdev->irq.lock, irqflags);
 501}
 502
 503