panel_event_notifier.c 5.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184
  1. // SPDX-License-Identifier: GPL-2.0-only
  2. /*
  3. * Copyright (c) 2021, The Linux Foundation. All rights reserved.
  4. *
  5. */
  6. #include <linux/list.h>
  7. #include <linux/mutex.h>
  8. #include <linux/module.h>
  9. #include <linux/soc/qcom/panel_event_notifier.h>
  10. struct panel_event_notifier_entry {
  11. panel_event_notifier_handler handler;
  12. void *pvt_data;
  13. struct drm_panel *panel;
  14. enum panel_event_notifier_tag tag;
  15. };
  16. static DEFINE_MUTEX(panel_event_notifier_entries_lock);
  17. static struct panel_event_notifier_entry
  18. panel_event_notifier_entries[PANEL_EVENT_NOTIFIER_CLIENT_MAX];
  19. static bool panel_event_notifier_tag_valid(enum panel_event_notifier_tag tag)
  20. {
  21. return tag > PANEL_EVENT_NOTIFICATION_NONE &&
  22. tag < PANEL_EVENT_NOTIFICATION_MAX;
  23. }
  24. /**
  25. * panel_event_notifier_register: responsible for registering clients
  26. * interested in panel event notifications.
  27. * clients register with a client handle and tag
  28. * suggesting the notifications they are
  29. * interested in and a callback which is
  30. * triggered when the interested panel
  31. * notifications are received.
  32. *
  33. * @tag: The tag for which the caller would like to receive panel events for.
  34. *
  35. * @client_handle: handle to recongnize the client registering for
  36. * notifications.
  37. *
  38. * @panel: struct drm_panel for which the panel events are requested for.
  39. *
  40. * @handler: The handler that will be invoked when a panel event notification is
  41. * received pertaining to @tag. The handler will be invoked with a
  42. * pointer to private data registered by the client that is needed
  43. * for servicing the notification.
  44. *
  45. * @pvt_data: The data that should be passed to @handler when a notification
  46. * occurs
  47. *
  48. * On success, the function will return a cookie.
  49. *
  50. */
  51. void *panel_event_notifier_register(enum panel_event_notifier_tag tag,
  52. enum panel_event_notifier_client client_handle,
  53. struct drm_panel *panel,
  54. panel_event_notifier_handler handler, void *pvt_data)
  55. {
  56. struct panel_event_notifier_entry *entry;
  57. if (!panel_event_notifier_tag_valid(tag) || !handler) {
  58. pr_err("Invalid tag or handler found while registering\n");
  59. return ERR_PTR(-EINVAL);
  60. }
  61. if (client_handle < 0 ||
  62. client_handle >= PANEL_EVENT_NOTIFIER_CLIENT_MAX) {
  63. pr_err("Invalid client handle used for registering\n");
  64. return ERR_PTR(-EINVAL);
  65. }
  66. mutex_lock(&panel_event_notifier_entries_lock);
  67. entry = &panel_event_notifier_entries[client_handle];
  68. if (entry->handler) {
  69. mutex_unlock(&panel_event_notifier_entries_lock);
  70. return ERR_PTR(-EEXIST);
  71. }
  72. entry->panel = panel;
  73. entry->handler = handler;
  74. entry->pvt_data = pvt_data;
  75. entry->tag = tag;
  76. mutex_unlock(&panel_event_notifier_entries_lock);
  77. pr_debug("client %d registered successfully\n", client_handle);
  78. return entry;
  79. }
  80. EXPORT_SYMBOL(panel_event_notifier_register);
  81. /**
  82. * panel_event_notifier_unregister: responsible for unregistering clients.
  83. *
  84. * @cookie: cookie used for unregistering client.
  85. */
  86. void panel_event_notifier_unregister(void *cookie)
  87. {
  88. struct panel_event_notifier_entry *entry = cookie;
  89. if (!cookie)
  90. return;
  91. mutex_lock(&panel_event_notifier_entries_lock);
  92. entry->panel = NULL;
  93. entry->handler = NULL;
  94. entry->pvt_data = NULL;
  95. entry->tag = PANEL_EVENT_NOTIFICATION_NONE;
  96. mutex_unlock(&panel_event_notifier_entries_lock);
  97. }
  98. EXPORT_SYMBOL(panel_event_notifier_unregister);
  99. /**
  100. * panel_event_notifion_trigger: responsible for triggering notifications.
  101. * Contains tag which notifies the panel
  102. * notification is on premiary or secondary
  103. * display and a notifcation carrying necessary
  104. * data for clients to consume while servicing the
  105. * notification. A handler registered by the
  106. * client will be triggered to notify the event.
  107. *
  108. * @tag: tag suggesting the panel on which notification is triggered whether
  109. *I primary or secondary display panel.
  110. *
  111. * @notification: contains data required for client to address the notification.
  112. */
  113. void panel_event_notification_trigger(enum panel_event_notifier_tag tag,
  114. struct panel_event_notification *notification)
  115. {
  116. struct panel_event_notifier_entry *entry;
  117. panel_event_notifier_handler handler = NULL;
  118. void *pvt_data;
  119. int i;
  120. if (!panel_event_notifier_tag_valid(tag)) {
  121. pr_err("Invalid panel notifier tag\n");
  122. return;
  123. }
  124. for (i = 0; i < PANEL_EVENT_NOTIFIER_CLIENT_MAX; i++) {
  125. mutex_lock(&panel_event_notifier_entries_lock);
  126. entry = &panel_event_notifier_entries[i];
  127. if (notification->panel != entry->panel) {
  128. pr_debug("invalid panel found notification_panel:0x%x entry_panel:0x%x\n",
  129. notification->panel, entry->panel);
  130. mutex_unlock(&panel_event_notifier_entries_lock);
  131. continue;
  132. }
  133. /* skip client entries not subscribed to tag */
  134. if (entry->tag != tag) {
  135. pr_err("tag mismatch entry->tag:%d tag:%d\n", entry->tag, tag);
  136. mutex_unlock(&panel_event_notifier_entries_lock);
  137. continue;
  138. }
  139. handler = entry->handler;
  140. pvt_data = entry->pvt_data;
  141. mutex_unlock(&panel_event_notifier_entries_lock);
  142. pr_debug("triggering notification for tag:%d, type:%d\n",
  143. tag, notification->notif_type);
  144. if (handler)
  145. handler(tag, notification, pvt_data);
  146. }
  147. }
  148. EXPORT_SYMBOL(panel_event_notification_trigger);
  149. static int __init panel_event_notifier_init(void)
  150. {
  151. pr_debug("Panel event notifier initialized\n");
  152. return 0;
  153. }
  154. module_init(panel_event_notifier_init);
  155. static void __exit panel_event_notifier_exit(void)
  156. {
  157. pr_debug("Panel event notifier exited\n");
  158. }
  159. module_exit(panel_event_notifier_exit);
  160. MODULE_LICENSE("GPL v2");
  161. MODULE_DESCRIPTION("Qualcomm Technologies, Inc. Panel event notifier");