Subversion Repositories Kolibri OS

Rev

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