drm_client_event.c 5.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214
  1. // SPDX-License-Identifier: GPL-2.0 or MIT
  2. /*
  3. * Copyright 2018 Noralf Trønnes
  4. */
  5. #include <linux/export.h>
  6. #include <linux/list.h>
  7. #include <linux/mutex.h>
  8. #include <linux/seq_file.h>
  9. #include <drm/drm_client.h>
  10. #include <drm/drm_client_event.h>
  11. #include <drm/drm_debugfs.h>
  12. #include <drm/drm_device.h>
  13. #include <drm/drm_drv.h>
  14. #include <drm/drm_print.h>
  15. #include "drm_internal.h"
  16. /**
  17. * drm_client_dev_unregister - Unregister clients
  18. * @dev: DRM device
  19. *
  20. * This function releases all clients by calling each client's
  21. * &drm_client_funcs.unregister callback. The callback function
  22. * is responsibe for releaseing all resources including the client
  23. * itself.
  24. *
  25. * The helper drm_dev_unregister() calls this function. Drivers
  26. * that use it don't need to call this function themselves.
  27. */
  28. void drm_client_dev_unregister(struct drm_device *dev)
  29. {
  30. struct drm_client_dev *client, *tmp;
  31. if (!drm_core_check_feature(dev, DRIVER_MODESET))
  32. return;
  33. mutex_lock(&dev->clientlist_mutex);
  34. list_for_each_entry_safe(client, tmp, &dev->clientlist, list) {
  35. list_del(&client->list);
  36. /*
  37. * Unregistering consumes and frees the client.
  38. */
  39. if (client->funcs && client->funcs->unregister)
  40. client->funcs->unregister(client);
  41. else
  42. drm_client_release(client);
  43. }
  44. mutex_unlock(&dev->clientlist_mutex);
  45. }
  46. EXPORT_SYMBOL(drm_client_dev_unregister);
  47. static void drm_client_hotplug(struct drm_client_dev *client)
  48. {
  49. struct drm_device *dev = client->dev;
  50. int ret;
  51. if (!client->funcs || !client->funcs->hotplug)
  52. return;
  53. if (client->hotplug_failed)
  54. return;
  55. if (client->suspended) {
  56. client->hotplug_pending = true;
  57. return;
  58. }
  59. client->hotplug_pending = false;
  60. ret = client->funcs->hotplug(client);
  61. drm_dbg_kms(dev, "%s: ret=%d\n", client->name, ret);
  62. if (ret)
  63. client->hotplug_failed = true;
  64. }
  65. /**
  66. * drm_client_dev_hotplug - Send hotplug event to clients
  67. * @dev: DRM device
  68. *
  69. * This function calls the &drm_client_funcs.hotplug callback on the attached clients.
  70. *
  71. * drm_kms_helper_hotplug_event() calls this function, so drivers that use it
  72. * don't need to call this function themselves.
  73. */
  74. void drm_client_dev_hotplug(struct drm_device *dev)
  75. {
  76. struct drm_client_dev *client;
  77. if (!drm_core_check_feature(dev, DRIVER_MODESET))
  78. return;
  79. if (!dev->mode_config.num_connector) {
  80. drm_dbg_kms(dev, "No connectors found, will not send hotplug events!\n");
  81. return;
  82. }
  83. mutex_lock(&dev->clientlist_mutex);
  84. list_for_each_entry(client, &dev->clientlist, list)
  85. drm_client_hotplug(client);
  86. mutex_unlock(&dev->clientlist_mutex);
  87. }
  88. EXPORT_SYMBOL(drm_client_dev_hotplug);
  89. void drm_client_dev_restore(struct drm_device *dev, bool force)
  90. {
  91. struct drm_client_dev *client;
  92. int ret;
  93. if (!drm_core_check_feature(dev, DRIVER_MODESET))
  94. return;
  95. mutex_lock(&dev->clientlist_mutex);
  96. list_for_each_entry(client, &dev->clientlist, list) {
  97. if (!client->funcs || !client->funcs->restore)
  98. continue;
  99. ret = client->funcs->restore(client, force);
  100. drm_dbg_kms(dev, "%s: ret=%d\n", client->name, ret);
  101. if (!ret) /* The first one to return zero gets the privilege to restore */
  102. break;
  103. }
  104. mutex_unlock(&dev->clientlist_mutex);
  105. }
  106. static int drm_client_suspend(struct drm_client_dev *client)
  107. {
  108. struct drm_device *dev = client->dev;
  109. int ret = 0;
  110. if (drm_WARN_ON_ONCE(dev, client->suspended))
  111. return 0;
  112. if (client->funcs && client->funcs->suspend)
  113. ret = client->funcs->suspend(client);
  114. drm_dbg_kms(dev, "%s: ret=%d\n", client->name, ret);
  115. client->suspended = true;
  116. return ret;
  117. }
  118. void drm_client_dev_suspend(struct drm_device *dev)
  119. {
  120. struct drm_client_dev *client;
  121. mutex_lock(&dev->clientlist_mutex);
  122. list_for_each_entry(client, &dev->clientlist, list) {
  123. if (!client->suspended)
  124. drm_client_suspend(client);
  125. }
  126. mutex_unlock(&dev->clientlist_mutex);
  127. }
  128. EXPORT_SYMBOL(drm_client_dev_suspend);
  129. static int drm_client_resume(struct drm_client_dev *client)
  130. {
  131. struct drm_device *dev = client->dev;
  132. int ret = 0;
  133. if (drm_WARN_ON_ONCE(dev, !client->suspended))
  134. return 0;
  135. if (client->funcs && client->funcs->resume)
  136. ret = client->funcs->resume(client);
  137. drm_dbg_kms(dev, "%s: ret=%d\n", client->name, ret);
  138. client->suspended = false;
  139. if (client->hotplug_pending)
  140. drm_client_hotplug(client);
  141. return ret;
  142. }
  143. void drm_client_dev_resume(struct drm_device *dev)
  144. {
  145. struct drm_client_dev *client;
  146. mutex_lock(&dev->clientlist_mutex);
  147. list_for_each_entry(client, &dev->clientlist, list) {
  148. if (client->suspended)
  149. drm_client_resume(client);
  150. }
  151. mutex_unlock(&dev->clientlist_mutex);
  152. }
  153. EXPORT_SYMBOL(drm_client_dev_resume);
  154. #ifdef CONFIG_DEBUG_FS
  155. static int drm_client_debugfs_internal_clients(struct seq_file *m, void *data)
  156. {
  157. struct drm_debugfs_entry *entry = m->private;
  158. struct drm_device *dev = entry->dev;
  159. struct drm_printer p = drm_seq_file_printer(m);
  160. struct drm_client_dev *client;
  161. mutex_lock(&dev->clientlist_mutex);
  162. list_for_each_entry(client, &dev->clientlist, list)
  163. drm_printf(&p, "%s\n", client->name);
  164. mutex_unlock(&dev->clientlist_mutex);
  165. return 0;
  166. }
  167. static const struct drm_debugfs_info drm_client_debugfs_list[] = {
  168. { "internal_clients", drm_client_debugfs_internal_clients, 0 },
  169. };
  170. void drm_client_debugfs_init(struct drm_device *dev)
  171. {
  172. drm_debugfs_add_files(dev, drm_client_debugfs_list,
  173. ARRAY_SIZE(drm_client_debugfs_list));
  174. }
  175. #endif