Subversion Repositories Kolibri OS

Rev

Rev 5271 | 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. #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.         /* enable msi */
  160.         rdev->msi_enabled = 0;
  161.  
  162.     rdev->irq.installed = true;
  163.         r = drm_irq_install(rdev->ddev, rdev->ddev->pdev->irq);
  164.     if (r) {
  165.        rdev->irq.installed = false;
  166.        FAIL();
  167.        return r;
  168.    }
  169.  
  170.         DRM_INFO("radeon: irq initialized.\n");
  171.         return 0;
  172. }
  173.  
  174. /**
  175.  * radeon_irq_kms_fini - tear down driver interrupt info
  176.  *
  177.  * @rdev: radeon device pointer
  178.  *
  179.  * Tears down the work irq handlers, vblank handlers, MSIs, etc. (all asics).
  180.  */
  181. void radeon_irq_kms_fini(struct radeon_device *rdev)
  182. {
  183.         drm_vblank_cleanup(rdev->ddev);
  184.         if (rdev->irq.installed) {
  185. //              drm_irq_uninstall(rdev->ddev);
  186.                 rdev->irq.installed = false;
  187. //       if (rdev->msi_enabled)
  188. //                      pci_disable_msi(rdev->pdev);
  189.         }
  190. }
  191.  
  192. /**
  193.  * radeon_irq_kms_sw_irq_get - enable software interrupt
  194.  *
  195.  * @rdev: radeon device pointer
  196.  * @ring: ring whose interrupt you want to enable
  197.  *
  198.  * Enables the software interrupt for a specific ring (all asics).
  199.  * The software interrupt is generally used to signal a fence on
  200.  * a particular ring.
  201.  */
  202. void radeon_irq_kms_sw_irq_get(struct radeon_device *rdev, int ring)
  203. {
  204.         unsigned long irqflags;
  205.  
  206.         if (!rdev->ddev->irq_enabled)
  207.                 return;
  208.  
  209.         if (atomic_inc_return(&rdev->irq.ring_int[ring]) == 1) {
  210.                 spin_lock_irqsave(&rdev->irq.lock, irqflags);
  211.                 radeon_irq_set(rdev);
  212.                 spin_unlock_irqrestore(&rdev->irq.lock, irqflags);
  213.         }
  214. }
  215.  
  216. /**
  217.  * radeon_irq_kms_sw_irq_get_delayed - enable software interrupt
  218.  *
  219.  * @rdev: radeon device pointer
  220.  * @ring: ring whose interrupt you want to enable
  221.  *
  222.  * Enables the software interrupt for a specific ring (all asics).
  223.  * The software interrupt is generally used to signal a fence on
  224.  * a particular ring.
  225.  */
  226. bool radeon_irq_kms_sw_irq_get_delayed(struct radeon_device *rdev, int ring)
  227. {
  228.         return atomic_inc_return(&rdev->irq.ring_int[ring]) == 1;
  229. }
  230.  
  231. /**
  232.  * radeon_irq_kms_sw_irq_put - disable software interrupt
  233.  *
  234.  * @rdev: radeon device pointer
  235.  * @ring: ring whose interrupt you want to disable
  236.  *
  237.  * Disables the software interrupt for a specific ring (all asics).
  238.  * The software interrupt is generally used to signal a fence on
  239.  * a particular ring.
  240.  */
  241. void radeon_irq_kms_sw_irq_put(struct radeon_device *rdev, int ring)
  242. {
  243.         unsigned long irqflags;
  244.  
  245.         if (!rdev->ddev->irq_enabled)
  246.                 return;
  247.  
  248.         if (atomic_dec_and_test(&rdev->irq.ring_int[ring])) {
  249.                 spin_lock_irqsave(&rdev->irq.lock, irqflags);
  250.                 radeon_irq_set(rdev);
  251.                 spin_unlock_irqrestore(&rdev->irq.lock, irqflags);
  252.         }
  253. }
  254.  
  255. /**
  256.  * radeon_irq_kms_enable_hpd - enable hotplug detect interrupt
  257.  *
  258.  * @rdev: radeon device pointer
  259.  * @hpd_mask: mask of hpd pins you want to enable.
  260.  *
  261.  * Enables the hotplug detect interrupt for a specific hpd pin (all asics).
  262.  */
  263. void radeon_irq_kms_enable_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. /**
  279.  * radeon_irq_kms_disable_hpd - disable hotplug detect interrupt
  280.  *
  281.  * @rdev: radeon device pointer
  282.  * @hpd_mask: mask of hpd pins you want to disable.
  283.  *
  284.  * Disables the hotplug detect interrupt for a specific hpd pin (all asics).
  285.  */
  286. void radeon_irq_kms_disable_hpd(struct radeon_device *rdev, unsigned hpd_mask)
  287. {
  288.         unsigned long irqflags;
  289.         int i;
  290.  
  291.         if (!rdev->ddev->irq_enabled)
  292.                 return;
  293.  
  294.         spin_lock_irqsave(&rdev->irq.lock, irqflags);
  295.         for (i = 0; i < RADEON_MAX_HPD_PINS; ++i)
  296.                 rdev->irq.hpd[i] &= !(hpd_mask & (1 << i));
  297.         radeon_irq_set(rdev);
  298.         spin_unlock_irqrestore(&rdev->irq.lock, irqflags);
  299. }
  300.  
  301.