Subversion Repositories Kolibri OS

Rev

Rev 3764 | Rev 6104 | Go to most recent revision | Blame | Compare with Previous | Last modification | View Log | Download | RSS feed

  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. extern int irq_override;
  39.  
  40.  
  41. /**
  42.  * radeon_driver_irq_handler_kms - irq handler for KMS
  43.  *
  44.  * @int irq, void *arg: 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(int irq, void *arg)
  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.  * radeon_driver_irq_preinstall_kms - drm irq preinstall callback
  60.  *
  61.  * @dev: drm dev pointer
  62.  *
  63.  * Gets the hw ready to enable irqs (all asics).
  64.  * This function disables all interrupt sources on the GPU.
  65.  */
  66. void radeon_driver_irq_preinstall_kms(struct drm_device *dev)
  67. {
  68.         struct radeon_device *rdev = dev->dev_private;
  69.         unsigned long irqflags;
  70.     unsigned i;
  71.  
  72.         spin_lock_irqsave(&rdev->irq.lock, irqflags);
  73.     /* Disable *all* interrupts */
  74.         for (i = 0; i < RADEON_NUM_RINGS; i++)
  75.                 atomic_set(&rdev->irq.ring_int[i], 0);
  76.         rdev->irq.dpm_thermal = false;
  77.         for (i = 0; i < RADEON_MAX_HPD_PINS; i++)
  78.                 rdev->irq.hpd[i] = false;
  79.         for (i = 0; i < RADEON_MAX_CRTCS; i++) {
  80.         rdev->irq.crtc_vblank_int[i] = false;
  81.                 atomic_set(&rdev->irq.pflip[i], 0);
  82.                 rdev->irq.afmt[i] = false;
  83.     }
  84.     radeon_irq_set(rdev);
  85.         spin_unlock_irqrestore(&rdev->irq.lock, irqflags);
  86.     /* Clear bits */
  87.     radeon_irq_process(rdev);
  88. }
  89.  
  90. /**
  91.  * radeon_driver_irq_postinstall_kms - drm irq preinstall callback
  92.  *
  93.  * @dev: drm dev pointer
  94.  *
  95.  * Handles stuff to be done after enabling irqs (all asics).
  96.  * Returns 0 on success.
  97.  */
  98. int radeon_driver_irq_postinstall_kms(struct drm_device *dev)
  99. {
  100.         dev->max_vblank_count = 0x001fffff;
  101.         return 0;
  102. }
  103.  
  104. /**
  105.  * radeon_driver_irq_uninstall_kms - drm irq uninstall callback
  106.  *
  107.  * @dev: drm dev pointer
  108.  *
  109.  * This function disables all interrupt sources on the GPU (all asics).
  110.  */
  111. void radeon_driver_irq_uninstall_kms(struct drm_device *dev)
  112. {
  113.         struct radeon_device *rdev = dev->dev_private;
  114.         unsigned long irqflags;
  115.         unsigned i;
  116.  
  117.         if (rdev == NULL) {
  118.                 return;
  119.         }
  120.         spin_lock_irqsave(&rdev->irq.lock, irqflags);
  121.         /* Disable *all* interrupts */
  122.         for (i = 0; i < RADEON_NUM_RINGS; i++)
  123.                 atomic_set(&rdev->irq.ring_int[i], 0);
  124.         rdev->irq.dpm_thermal = false;
  125.         for (i = 0; i < RADEON_MAX_HPD_PINS; i++)
  126.                 rdev->irq.hpd[i] = false;
  127.         for (i = 0; i < RADEON_MAX_CRTCS; i++) {
  128.                 rdev->irq.crtc_vblank_int[i] = false;
  129.                 atomic_set(&rdev->irq.pflip[i], 0);
  130.                 rdev->irq.afmt[i] = false;
  131.         }
  132.         radeon_irq_set(rdev);
  133.         spin_unlock_irqrestore(&rdev->irq.lock, irqflags);
  134. }
  135.  
  136.  
  137.  
  138. /**
  139.  * radeon_irq_kms_init - init driver interrupt info
  140.  *
  141.  * @rdev: radeon device pointer
  142.  *
  143.  * Sets up the work irq handlers, vblank init, MSIs, etc. (all asics).
  144.  * Returns 0 for success, error for failure.
  145.  */
  146. int radeon_irq_kms_init(struct radeon_device *rdev)
  147. {
  148.         int r = 0;
  149.  
  150.         spin_lock_init(&rdev->irq.lock);
  151.         /* enable msi */
  152.         rdev->msi_enabled = 0;
  153.  
  154.     rdev->irq.installed = true;
  155.         r = drm_irq_install(rdev->ddev, rdev->ddev->pdev->irq);
  156.     if (r) {
  157.        rdev->irq.installed = false;
  158.        FAIL();
  159.        return r;
  160.    }
  161.  
  162.         DRM_INFO("radeon: irq initialized.\n");
  163.         return 0;
  164. }
  165.  
  166. /**
  167.  * radeon_irq_kms_fini - tear down driver interrupt info
  168.  *
  169.  * @rdev: radeon device pointer
  170.  *
  171.  * Tears down the work irq handlers, vblank handlers, MSIs, etc. (all asics).
  172.  */
  173. void radeon_irq_kms_fini(struct radeon_device *rdev)
  174. {
  175. //      drm_vblank_cleanup(rdev->ddev);
  176.         if (rdev->irq.installed) {
  177. //              drm_irq_uninstall(rdev->ddev);
  178.                 rdev->irq.installed = false;
  179. //       if (rdev->msi_enabled)
  180. //                      pci_disable_msi(rdev->pdev);
  181.         }
  182. }
  183.  
  184. /**
  185.  * radeon_irq_kms_sw_irq_get - enable software interrupt
  186.  *
  187.  * @rdev: radeon device pointer
  188.  * @ring: ring whose interrupt you want to enable
  189.  *
  190.  * Enables the software interrupt for a specific ring (all asics).
  191.  * The software interrupt is generally used to signal a fence on
  192.  * a particular ring.
  193.  */
  194. void radeon_irq_kms_sw_irq_get(struct radeon_device *rdev, int ring)
  195. {
  196.         unsigned long irqflags;
  197.  
  198.         if (!rdev->ddev->irq_enabled)
  199.                 return;
  200.  
  201.         if (atomic_inc_return(&rdev->irq.ring_int[ring]) == 1) {
  202.                 spin_lock_irqsave(&rdev->irq.lock, irqflags);
  203.                 radeon_irq_set(rdev);
  204.                 spin_unlock_irqrestore(&rdev->irq.lock, irqflags);
  205.         }
  206. }
  207.  
  208. /**
  209.  * radeon_irq_kms_sw_irq_put - disable software interrupt
  210.  *
  211.  * @rdev: radeon device pointer
  212.  * @ring: ring whose interrupt you want to disable
  213.  *
  214.  * Disables the software interrupt for a specific ring (all asics).
  215.  * The software interrupt is generally used to signal a fence on
  216.  * a particular ring.
  217.  */
  218. void radeon_irq_kms_sw_irq_put(struct radeon_device *rdev, int ring)
  219. {
  220.         unsigned long irqflags;
  221.  
  222.         if (!rdev->ddev->irq_enabled)
  223.                 return;
  224.  
  225.         if (atomic_dec_and_test(&rdev->irq.ring_int[ring])) {
  226.                 spin_lock_irqsave(&rdev->irq.lock, irqflags);
  227.                 radeon_irq_set(rdev);
  228.                 spin_unlock_irqrestore(&rdev->irq.lock, irqflags);
  229.         }
  230. }
  231.  
  232. /**
  233.  * radeon_irq_kms_enable_hpd - enable hotplug detect interrupt
  234.  *
  235.  * @rdev: radeon device pointer
  236.  * @hpd_mask: mask of hpd pins you want to enable.
  237.  *
  238.  * Enables the hotplug detect interrupt for a specific hpd pin (all asics).
  239.  */
  240. void radeon_irq_kms_enable_hpd(struct radeon_device *rdev, unsigned hpd_mask)
  241. {
  242.         unsigned long irqflags;
  243.         int i;
  244.  
  245.         if (!rdev->ddev->irq_enabled)
  246.                 return;
  247.  
  248.         spin_lock_irqsave(&rdev->irq.lock, irqflags);
  249.         for (i = 0; i < RADEON_MAX_HPD_PINS; ++i)
  250.                 rdev->irq.hpd[i] |= !!(hpd_mask & (1 << i));
  251.         radeon_irq_set(rdev);
  252.         spin_unlock_irqrestore(&rdev->irq.lock, irqflags);
  253. }
  254.  
  255. /**
  256.  * radeon_irq_kms_disable_hpd - disable hotplug detect interrupt
  257.  *
  258.  * @rdev: radeon device pointer
  259.  * @hpd_mask: mask of hpd pins you want to disable.
  260.  *
  261.  * Disables the hotplug detect interrupt for a specific hpd pin (all asics).
  262.  */
  263. void radeon_irq_kms_disable_hpd(struct radeon_device *rdev, unsigned hpd_mask)
  264. {
  265.         unsigned long irqflags;
  266.         int i;
  267.  
  268.         if (!rdev->ddev->irq_enabled)
  269.                 return;
  270.  
  271.         spin_lock_irqsave(&rdev->irq.lock, irqflags);
  272.         for (i = 0; i < RADEON_MAX_HPD_PINS; ++i)
  273.                 rdev->irq.hpd[i] &= !(hpd_mask & (1 << i));
  274.         radeon_irq_set(rdev);
  275.         spin_unlock_irqrestore(&rdev->irq.lock, irqflags);
  276. }
  277.  
  278.