radeon_irq_kms.c 8.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340
  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 "drmP.h"
  29. #include "drm_crtc_helper.h"
  30. #include "radeon_drm.h"
  31. #include "radeon_reg.h"
  32. #include "radeon.h"
  33. #include "atom.h"
  34. #define RADEON_WAIT_IDLE_TIMEOUT 200
  35. irqreturn_t radeon_driver_irq_handler_kms(DRM_IRQ_ARGS)
  36. {
  37. struct drm_device *dev = (struct drm_device *) arg;
  38. struct radeon_device *rdev = dev->dev_private;
  39. return radeon_irq_process(rdev);
  40. }
  41. /*
  42. * Handle hotplug events outside the interrupt handler proper.
  43. */
  44. static void radeon_hotplug_work_func(struct work_struct *work)
  45. {
  46. struct radeon_device *rdev = container_of(work, struct radeon_device,
  47. hotplug_work);
  48. struct drm_device *dev = rdev->ddev;
  49. struct drm_mode_config *mode_config = &dev->mode_config;
  50. struct drm_connector *connector;
  51. if (mode_config->num_connector) {
  52. list_for_each_entry(connector, &mode_config->connector_list, head)
  53. radeon_connector_hotplug(connector);
  54. }
  55. /* Just fire off a uevent and let userspace tell us what to do */
  56. drm_helper_hpd_irq_event(dev);
  57. }
  58. void radeon_driver_irq_preinstall_kms(struct drm_device *dev)
  59. {
  60. struct radeon_device *rdev = dev->dev_private;
  61. unsigned long irqflags;
  62. unsigned i;
  63. spin_lock_irqsave(&rdev->irq.lock, irqflags);
  64. /* Disable *all* interrupts */
  65. for (i = 0; i < RADEON_NUM_RINGS; i++)
  66. atomic_set(&rdev->irq.ring_int[i], 0);
  67. rdev->irq.gui_idle = false;
  68. for (i = 0; i < RADEON_MAX_HPD_PINS; i++)
  69. rdev->irq.hpd[i] = false;
  70. for (i = 0; i < RADEON_MAX_CRTCS; i++) {
  71. rdev->irq.crtc_vblank_int[i] = false;
  72. atomic_set(&rdev->irq.pflip[i], 0);
  73. rdev->irq.afmt[i] = false;
  74. }
  75. radeon_irq_set(rdev);
  76. spin_unlock_irqrestore(&rdev->irq.lock, irqflags);
  77. /* Clear bits */
  78. radeon_irq_process(rdev);
  79. }
  80. int radeon_driver_irq_postinstall_kms(struct drm_device *dev)
  81. {
  82. dev->max_vblank_count = 0x001fffff;
  83. return 0;
  84. }
  85. void radeon_driver_irq_uninstall_kms(struct drm_device *dev)
  86. {
  87. struct radeon_device *rdev = dev->dev_private;
  88. unsigned long irqflags;
  89. unsigned i;
  90. if (rdev == NULL) {
  91. return;
  92. }
  93. spin_lock_irqsave(&rdev->irq.lock, irqflags);
  94. /* Disable *all* interrupts */
  95. for (i = 0; i < RADEON_NUM_RINGS; i++)
  96. atomic_set(&rdev->irq.ring_int[i], 0);
  97. rdev->irq.gui_idle = false;
  98. for (i = 0; i < RADEON_MAX_HPD_PINS; i++)
  99. rdev->irq.hpd[i] = false;
  100. for (i = 0; i < RADEON_MAX_CRTCS; i++) {
  101. rdev->irq.crtc_vblank_int[i] = false;
  102. atomic_set(&rdev->irq.pflip[i], 0);
  103. rdev->irq.afmt[i] = false;
  104. }
  105. radeon_irq_set(rdev);
  106. spin_unlock_irqrestore(&rdev->irq.lock, irqflags);
  107. }
  108. static bool radeon_msi_ok(struct radeon_device *rdev)
  109. {
  110. /* RV370/RV380 was first asic with MSI support */
  111. if (rdev->family < CHIP_RV380)
  112. return false;
  113. /* MSIs don't work on AGP */
  114. if (rdev->flags & RADEON_IS_AGP)
  115. return false;
  116. /* force MSI on */
  117. if (radeon_msi == 1)
  118. return true;
  119. else if (radeon_msi == 0)
  120. return false;
  121. /* Quirks */
  122. /* HP RS690 only seems to work with MSIs. */
  123. if ((rdev->pdev->device == 0x791f) &&
  124. (rdev->pdev->subsystem_vendor == 0x103c) &&
  125. (rdev->pdev->subsystem_device == 0x30c2))
  126. return true;
  127. /* Dell RS690 only seems to work with MSIs. */
  128. if ((rdev->pdev->device == 0x791f) &&
  129. (rdev->pdev->subsystem_vendor == 0x1028) &&
  130. (rdev->pdev->subsystem_device == 0x01fc))
  131. return true;
  132. /* Dell RS690 only seems to work with MSIs. */
  133. if ((rdev->pdev->device == 0x791f) &&
  134. (rdev->pdev->subsystem_vendor == 0x1028) &&
  135. (rdev->pdev->subsystem_device == 0x01fd))
  136. return true;
  137. /* RV515 seems to have MSI issues where it loses
  138. * MSI rearms occasionally. This leads to lockups and freezes.
  139. * disable it by default.
  140. */
  141. if (rdev->family == CHIP_RV515)
  142. return false;
  143. if (rdev->flags & RADEON_IS_IGP) {
  144. /* APUs work fine with MSIs */
  145. if (rdev->family >= CHIP_PALM)
  146. return true;
  147. /* lots of IGPs have problems with MSIs */
  148. return false;
  149. }
  150. return true;
  151. }
  152. int radeon_irq_kms_init(struct radeon_device *rdev)
  153. {
  154. int r = 0;
  155. INIT_WORK(&rdev->hotplug_work, radeon_hotplug_work_func);
  156. INIT_WORK(&rdev->audio_work, r600_audio_update_hdmi);
  157. spin_lock_init(&rdev->irq.lock);
  158. r = drm_vblank_init(rdev->ddev, rdev->num_crtc);
  159. if (r) {
  160. return r;
  161. }
  162. /* enable msi */
  163. rdev->msi_enabled = 0;
  164. if (radeon_msi_ok(rdev)) {
  165. int ret = pci_enable_msi(rdev->pdev);
  166. if (!ret) {
  167. rdev->msi_enabled = 1;
  168. dev_info(rdev->dev, "radeon: using MSI.\n");
  169. }
  170. }
  171. rdev->irq.installed = true;
  172. r = drm_irq_install(rdev->ddev);
  173. if (r) {
  174. rdev->irq.installed = false;
  175. return r;
  176. }
  177. DRM_INFO("radeon: irq initialized.\n");
  178. return 0;
  179. }
  180. void radeon_irq_kms_fini(struct radeon_device *rdev)
  181. {
  182. drm_vblank_cleanup(rdev->ddev);
  183. if (rdev->irq.installed) {
  184. drm_irq_uninstall(rdev->ddev);
  185. rdev->irq.installed = false;
  186. if (rdev->msi_enabled)
  187. pci_disable_msi(rdev->pdev);
  188. }
  189. flush_work_sync(&rdev->hotplug_work);
  190. }
  191. void radeon_irq_kms_sw_irq_get(struct radeon_device *rdev, int ring)
  192. {
  193. unsigned long irqflags;
  194. if (!rdev->ddev->irq_enabled)
  195. return;
  196. if (atomic_inc_return(&rdev->irq.ring_int[ring]) == 1) {
  197. spin_lock_irqsave(&rdev->irq.lock, irqflags);
  198. radeon_irq_set(rdev);
  199. spin_unlock_irqrestore(&rdev->irq.lock, irqflags);
  200. }
  201. }
  202. void radeon_irq_kms_sw_irq_put(struct radeon_device *rdev, int ring)
  203. {
  204. unsigned long irqflags;
  205. if (!rdev->ddev->irq_enabled)
  206. return;
  207. if (atomic_dec_and_test(&rdev->irq.ring_int[ring])) {
  208. spin_lock_irqsave(&rdev->irq.lock, irqflags);
  209. radeon_irq_set(rdev);
  210. spin_unlock_irqrestore(&rdev->irq.lock, irqflags);
  211. }
  212. }
  213. void radeon_irq_kms_pflip_irq_get(struct radeon_device *rdev, int crtc)
  214. {
  215. unsigned long irqflags;
  216. if (crtc < 0 || crtc >= rdev->num_crtc)
  217. return;
  218. if (!rdev->ddev->irq_enabled)
  219. return;
  220. if (atomic_inc_return(&rdev->irq.pflip[crtc]) == 1) {
  221. spin_lock_irqsave(&rdev->irq.lock, irqflags);
  222. radeon_irq_set(rdev);
  223. spin_unlock_irqrestore(&rdev->irq.lock, irqflags);
  224. }
  225. }
  226. void radeon_irq_kms_pflip_irq_put(struct radeon_device *rdev, int crtc)
  227. {
  228. unsigned long irqflags;
  229. if (crtc < 0 || crtc >= rdev->num_crtc)
  230. return;
  231. if (!rdev->ddev->irq_enabled)
  232. return;
  233. if (atomic_dec_and_test(&rdev->irq.pflip[crtc])) {
  234. spin_lock_irqsave(&rdev->irq.lock, irqflags);
  235. radeon_irq_set(rdev);
  236. spin_unlock_irqrestore(&rdev->irq.lock, irqflags);
  237. }
  238. }
  239. void radeon_irq_kms_enable_afmt(struct radeon_device *rdev, int block)
  240. {
  241. unsigned long irqflags;
  242. spin_lock_irqsave(&rdev->irq.lock, irqflags);
  243. rdev->irq.afmt[block] = true;
  244. radeon_irq_set(rdev);
  245. spin_unlock_irqrestore(&rdev->irq.lock, irqflags);
  246. }
  247. void radeon_irq_kms_disable_afmt(struct radeon_device *rdev, int block)
  248. {
  249. unsigned long irqflags;
  250. spin_lock_irqsave(&rdev->irq.lock, irqflags);
  251. rdev->irq.afmt[block] = false;
  252. radeon_irq_set(rdev);
  253. spin_unlock_irqrestore(&rdev->irq.lock, irqflags);
  254. }
  255. void radeon_irq_kms_enable_hpd(struct radeon_device *rdev, unsigned hpd_mask)
  256. {
  257. unsigned long irqflags;
  258. int i;
  259. spin_lock_irqsave(&rdev->irq.lock, irqflags);
  260. for (i = 0; i < RADEON_MAX_HPD_PINS; ++i)
  261. rdev->irq.hpd[i] |= !!(hpd_mask & (1 << i));
  262. radeon_irq_set(rdev);
  263. spin_unlock_irqrestore(&rdev->irq.lock, irqflags);
  264. }
  265. void radeon_irq_kms_disable_hpd(struct radeon_device *rdev, unsigned hpd_mask)
  266. {
  267. unsigned long irqflags;
  268. int i;
  269. spin_lock_irqsave(&rdev->irq.lock, irqflags);
  270. for (i = 0; i < RADEON_MAX_HPD_PINS; ++i)
  271. rdev->irq.hpd[i] &= !(hpd_mask & (1 << i));
  272. radeon_irq_set(rdev);
  273. spin_unlock_irqrestore(&rdev->irq.lock, irqflags);
  274. }
  275. int radeon_irq_kms_wait_gui_idle(struct radeon_device *rdev)
  276. {
  277. unsigned long irqflags;
  278. int r;
  279. spin_lock_irqsave(&rdev->irq.lock, irqflags);
  280. rdev->irq.gui_idle = true;
  281. radeon_irq_set(rdev);
  282. spin_unlock_irqrestore(&rdev->irq.lock, irqflags);
  283. r = wait_event_timeout(rdev->irq.idle_queue, radeon_gui_idle(rdev),
  284. msecs_to_jiffies(RADEON_WAIT_IDLE_TIMEOUT));
  285. spin_lock_irqsave(&rdev->irq.lock, irqflags);
  286. rdev->irq.gui_idle = false;
  287. radeon_irq_set(rdev);
  288. spin_unlock_irqrestore(&rdev->irq.lock, irqflags);
  289. return r;
  290. }