Subversion Repositories Kolibri OS

Rev

Rev 3120 | 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. #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.  * @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.  * 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.         for (i = 0; i < RADEON_MAX_HPD_PINS; i++)
  77.                 rdev->irq.hpd[i] = false;
  78.         for (i = 0; i < RADEON_MAX_CRTCS; i++) {
  79.         rdev->irq.crtc_vblank_int[i] = false;
  80.                 atomic_set(&rdev->irq.pflip[i], 0);
  81.                 rdev->irq.afmt[i] = false;
  82.     }
  83.     radeon_irq_set(rdev);
  84.         spin_unlock_irqrestore(&rdev->irq.lock, irqflags);
  85.     /* Clear bits */
  86.     radeon_irq_process(rdev);
  87. }
  88.  
  89. /**
  90.  * radeon_driver_irq_postinstall_kms - drm irq preinstall callback
  91.  *
  92.  * @dev: drm dev pointer
  93.  *
  94.  * Handles stuff to be done after enabling irqs (all asics).
  95.  * Returns 0 on success.
  96.  */
  97. int radeon_driver_irq_postinstall_kms(struct drm_device *dev)
  98. {
  99.         dev->max_vblank_count = 0x001fffff;
  100.         return 0;
  101. }
  102.  
  103. /**
  104.  * radeon_driver_irq_uninstall_kms - drm irq uninstall callback
  105.  *
  106.  * @dev: drm dev pointer
  107.  *
  108.  * This function disables all interrupt sources on the GPU (all asics).
  109.  */
  110. void radeon_driver_irq_uninstall_kms(struct drm_device *dev)
  111. {
  112.         struct radeon_device *rdev = dev->dev_private;
  113.         unsigned long irqflags;
  114.         unsigned i;
  115.  
  116.         if (rdev == NULL) {
  117.                 return;
  118.         }
  119.         spin_lock_irqsave(&rdev->irq.lock, irqflags);
  120.         /* Disable *all* interrupts */
  121.         for (i = 0; i < RADEON_NUM_RINGS; i++)
  122.                 atomic_set(&rdev->irq.ring_int[i], 0);
  123.         for (i = 0; i < RADEON_MAX_HPD_PINS; i++)
  124.                 rdev->irq.hpd[i] = false;
  125.         for (i = 0; i < RADEON_MAX_CRTCS; i++) {
  126.                 rdev->irq.crtc_vblank_int[i] = false;
  127.                 atomic_set(&rdev->irq.pflip[i], 0);
  128.                 rdev->irq.afmt[i] = false;
  129.         }
  130.         radeon_irq_set(rdev);
  131.         spin_unlock_irqrestore(&rdev->irq.lock, irqflags);
  132. }
  133.  
  134.  
  135.  
  136. /**
  137.  * radeon_irq_kms_init - init driver interrupt info
  138.  *
  139.  * @rdev: radeon device pointer
  140.  *
  141.  * Sets up the work irq handlers, vblank init, MSIs, etc. (all asics).
  142.  * Returns 0 for success, error for failure.
  143.  */
  144. int radeon_irq_kms_init(struct radeon_device *rdev)
  145. {
  146.     int irq_line;
  147.         int r = 0;
  148.  
  149.     ENTER();
  150.  
  151.  
  152.         spin_lock_init(&rdev->irq.lock);
  153.         /* enable msi */
  154.         rdev->msi_enabled = 0;
  155.  
  156.     rdev->irq.installed = true;
  157.         r = drm_irq_install(rdev->ddev);
  158.     if (r) {
  159.        rdev->irq.installed = false;
  160.        FAIL();
  161.        return r;
  162.    }
  163.         DRM_INFO("radeon: irq initialized.\n");
  164.         return 0;
  165. }
  166.  
  167. /**
  168.  * radeon_irq_kms_fini - tear down driver interrupt info
  169.  *
  170.  * @rdev: radeon device pointer
  171.  *
  172.  * Tears down the work irq handlers, vblank handlers, MSIs, etc. (all asics).
  173.  */
  174. void radeon_irq_kms_fini(struct radeon_device *rdev)
  175. {
  176. //      drm_vblank_cleanup(rdev->ddev);
  177.         if (rdev->irq.installed) {
  178. //              drm_irq_uninstall(rdev->ddev);
  179.                 rdev->irq.installed = false;
  180. //       if (rdev->msi_enabled)
  181. //                      pci_disable_msi(rdev->pdev);
  182.         }
  183. //      flush_work(&rdev->hotplug_work);
  184. }
  185.  
  186. /**
  187.  * radeon_irq_kms_sw_irq_get - enable software interrupt
  188.  *
  189.  * @rdev: radeon device pointer
  190.  * @ring: ring whose interrupt you want to enable
  191.  *
  192.  * Enables the software interrupt for a specific ring (all asics).
  193.  * The software interrupt is generally used to signal a fence on
  194.  * a particular ring.
  195.  */
  196. void radeon_irq_kms_sw_irq_get(struct radeon_device *rdev, int ring)
  197. {
  198.         unsigned long irqflags;
  199.  
  200.         if (!rdev->ddev->irq_enabled)
  201.                 return;
  202.  
  203.         if (atomic_inc_return(&rdev->irq.ring_int[ring]) == 1) {
  204.                 spin_lock_irqsave(&rdev->irq.lock, irqflags);
  205.                 radeon_irq_set(rdev);
  206.                 spin_unlock_irqrestore(&rdev->irq.lock, irqflags);
  207.         }
  208. }
  209.  
  210. /**
  211.  * radeon_irq_kms_sw_irq_put - disable software interrupt
  212.  *
  213.  * @rdev: radeon device pointer
  214.  * @ring: ring whose interrupt you want to disable
  215.  *
  216.  * Disables the software interrupt for a specific ring (all asics).
  217.  * The software interrupt is generally used to signal a fence on
  218.  * a particular ring.
  219.  */
  220. void radeon_irq_kms_sw_irq_put(struct radeon_device *rdev, int ring)
  221. {
  222.         unsigned long irqflags;
  223.  
  224.         if (!rdev->ddev->irq_enabled)
  225.                 return;
  226.  
  227.         if (atomic_dec_and_test(&rdev->irq.ring_int[ring])) {
  228.                 spin_lock_irqsave(&rdev->irq.lock, irqflags);
  229.                 radeon_irq_set(rdev);
  230.                 spin_unlock_irqrestore(&rdev->irq.lock, irqflags);
  231.         }
  232. }
  233.  
  234. /**
  235.  * radeon_irq_kms_enable_hpd - enable hotplug detect interrupt
  236.  *
  237.  * @rdev: radeon device pointer
  238.  * @hpd_mask: mask of hpd pins you want to enable.
  239.  *
  240.  * Enables the hotplug detect interrupt for a specific hpd pin (all asics).
  241.  */
  242. void radeon_irq_kms_enable_hpd(struct radeon_device *rdev, unsigned hpd_mask)
  243. {
  244.         unsigned long irqflags;
  245.         int i;
  246.  
  247.         spin_lock_irqsave(&rdev->irq.lock, irqflags);
  248.         for (i = 0; i < RADEON_MAX_HPD_PINS; ++i)
  249.                 rdev->irq.hpd[i] |= !!(hpd_mask & (1 << i));
  250.         radeon_irq_set(rdev);
  251.         spin_unlock_irqrestore(&rdev->irq.lock, irqflags);
  252. }
  253.  
  254. /**
  255.  * radeon_irq_kms_disable_hpd - disable hotplug detect interrupt
  256.  *
  257.  * @rdev: radeon device pointer
  258.  * @hpd_mask: mask of hpd pins you want to disable.
  259.  *
  260.  * Disables the hotplug detect interrupt for a specific hpd pin (all asics).
  261.  */
  262. void radeon_irq_kms_disable_hpd(struct radeon_device *rdev, unsigned hpd_mask)
  263. {
  264.         unsigned long irqflags;
  265.         int i;
  266.  
  267.         spin_lock_irqsave(&rdev->irq.lock, irqflags);
  268.         for (i = 0; i < RADEON_MAX_HPD_PINS; ++i)
  269.                 rdev->irq.hpd[i] &= !(hpd_mask & (1 << i));
  270.         radeon_irq_set(rdev);
  271.         spin_unlock_irqrestore(&rdev->irq.lock, irqflags);
  272. }
  273.  
  274.  
  275. static struct drm_driver drm_driver = {
  276.     .irq_preinstall = radeon_driver_irq_preinstall_kms,
  277.     .irq_postinstall = radeon_driver_irq_postinstall_kms,
  278.     .irq_handler = radeon_driver_irq_handler_kms
  279. };
  280.  
  281. static struct drm_driver *driver = &drm_driver;
  282.  
  283. int drm_irq_install(struct drm_device *dev)
  284. {
  285.     unsigned long sh_flags = 0;
  286.     int irq_line;
  287.     int ret = 0;
  288.  
  289.     char *irqname;
  290.  
  291.     mutex_lock(&dev->struct_mutex);
  292.  
  293.     /* Driver must have been initialized */
  294.     if (!dev->dev_private) {
  295.             mutex_unlock(&dev->struct_mutex);
  296.             return -EINVAL;
  297.     }
  298.  
  299.     if (dev->irq_enabled) {
  300.             mutex_unlock(&dev->struct_mutex);
  301.             return -EBUSY;
  302.     }
  303.     dev->irq_enabled = 1;
  304.     mutex_unlock(&dev->struct_mutex);
  305.  
  306.     irq_line   = drm_dev_to_irq(dev);
  307.  
  308.     DRM_DEBUG("irq=%d\n", drm_dev_to_irq(dev));
  309.  
  310.     /* Before installing handler */
  311.     if (driver->irq_preinstall)
  312.             driver->irq_preinstall(dev);
  313.  
  314.     ret = AttachIntHandler(irq_line, driver->irq_handler, (u32)dev);
  315.  
  316.     /* After installing handler */
  317.     if (driver->irq_postinstall)
  318.             ret = driver->irq_postinstall(dev);
  319.  
  320.     if (ret < 0) {
  321.             DRM_ERROR(__FUNCTION__);
  322.     }
  323.  
  324.     u16_t cmd = PciRead16(dev->pdev->busnr, dev->pdev->devfn, 4);
  325.     cmd&= ~(1<<10);
  326.     PciWrite16(dev->pdev->busnr, dev->pdev->devfn, 4, cmd);
  327.  
  328.     return ret;
  329. }
  330.