cec-notifier.c 6.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256
  1. // SPDX-License-Identifier: GPL-2.0-only
  2. /*
  3. * cec-notifier.c - notify CEC drivers of physical address changes
  4. *
  5. * Copyright 2016 Russell King.
  6. * Copyright 2016-2017 Cisco Systems, Inc. and/or its affiliates. All rights reserved.
  7. */
  8. #include <linux/export.h>
  9. #include <linux/platform_device.h>
  10. #include <linux/string.h>
  11. #include <linux/slab.h>
  12. #include <linux/i2c.h>
  13. #include <linux/list.h>
  14. #include <linux/kref.h>
  15. #include <linux/of_platform.h>
  16. #include <media/cec.h>
  17. #include <media/cec-notifier.h>
  18. #include <drm/drm_edid.h>
  19. struct cec_notifier {
  20. struct mutex lock;
  21. struct list_head head;
  22. struct kref kref;
  23. struct device *hdmi_dev;
  24. struct cec_connector_info conn_info;
  25. const char *port_name;
  26. struct cec_adapter *cec_adap;
  27. u16 phys_addr;
  28. };
  29. static LIST_HEAD(cec_notifiers);
  30. static DEFINE_MUTEX(cec_notifiers_lock);
  31. /**
  32. * cec_notifier_get_conn - find or create a new cec_notifier for the given
  33. * device and connector tuple.
  34. * @hdmi_dev: device that sends the events.
  35. * @port_name: the connector name from which the event occurs
  36. *
  37. * If a notifier for device @dev already exists, then increase the refcount
  38. * and return that notifier.
  39. *
  40. * If it doesn't exist, then allocate a new notifier struct and return a
  41. * pointer to that new struct.
  42. *
  43. * Return NULL if the memory could not be allocated.
  44. */
  45. static struct cec_notifier *
  46. cec_notifier_get_conn(struct device *hdmi_dev, const char *port_name)
  47. {
  48. struct cec_notifier *n;
  49. mutex_lock(&cec_notifiers_lock);
  50. list_for_each_entry(n, &cec_notifiers, head) {
  51. if (n->hdmi_dev == hdmi_dev &&
  52. (!port_name ||
  53. (n->port_name && !strcmp(n->port_name, port_name)))) {
  54. kref_get(&n->kref);
  55. mutex_unlock(&cec_notifiers_lock);
  56. return n;
  57. }
  58. }
  59. n = kzalloc(sizeof(*n), GFP_KERNEL);
  60. if (!n)
  61. goto unlock;
  62. n->hdmi_dev = hdmi_dev;
  63. if (port_name) {
  64. n->port_name = kstrdup(port_name, GFP_KERNEL);
  65. if (!n->port_name) {
  66. kfree(n);
  67. n = NULL;
  68. goto unlock;
  69. }
  70. }
  71. n->phys_addr = CEC_PHYS_ADDR_INVALID;
  72. mutex_init(&n->lock);
  73. kref_init(&n->kref);
  74. list_add_tail(&n->head, &cec_notifiers);
  75. unlock:
  76. mutex_unlock(&cec_notifiers_lock);
  77. return n;
  78. }
  79. static void cec_notifier_release(struct kref *kref)
  80. {
  81. struct cec_notifier *n =
  82. container_of(kref, struct cec_notifier, kref);
  83. list_del(&n->head);
  84. kfree(n->port_name);
  85. kfree(n);
  86. }
  87. static void cec_notifier_put(struct cec_notifier *n)
  88. {
  89. mutex_lock(&cec_notifiers_lock);
  90. kref_put(&n->kref, cec_notifier_release);
  91. mutex_unlock(&cec_notifiers_lock);
  92. }
  93. struct cec_notifier *
  94. cec_notifier_conn_register(struct device *hdmi_dev, const char *port_name,
  95. const struct cec_connector_info *conn_info)
  96. {
  97. struct cec_notifier *n = cec_notifier_get_conn(hdmi_dev, port_name);
  98. if (!n)
  99. return n;
  100. mutex_lock(&n->lock);
  101. n->phys_addr = CEC_PHYS_ADDR_INVALID;
  102. if (conn_info)
  103. n->conn_info = *conn_info;
  104. else
  105. memset(&n->conn_info, 0, sizeof(n->conn_info));
  106. if (n->cec_adap) {
  107. if (!n->cec_adap->adap_controls_phys_addr)
  108. cec_phys_addr_invalidate(n->cec_adap);
  109. cec_s_conn_info(n->cec_adap, conn_info);
  110. }
  111. mutex_unlock(&n->lock);
  112. return n;
  113. }
  114. EXPORT_SYMBOL_GPL(cec_notifier_conn_register);
  115. void cec_notifier_conn_unregister(struct cec_notifier *n)
  116. {
  117. if (!n)
  118. return;
  119. mutex_lock(&n->lock);
  120. memset(&n->conn_info, 0, sizeof(n->conn_info));
  121. n->phys_addr = CEC_PHYS_ADDR_INVALID;
  122. if (n->cec_adap) {
  123. if (!n->cec_adap->adap_controls_phys_addr)
  124. cec_phys_addr_invalidate(n->cec_adap);
  125. cec_s_conn_info(n->cec_adap, NULL);
  126. }
  127. mutex_unlock(&n->lock);
  128. cec_notifier_put(n);
  129. }
  130. EXPORT_SYMBOL_GPL(cec_notifier_conn_unregister);
  131. struct cec_notifier *
  132. cec_notifier_cec_adap_register(struct device *hdmi_dev, const char *port_name,
  133. struct cec_adapter *adap)
  134. {
  135. struct cec_notifier *n;
  136. if (WARN_ON(!adap))
  137. return NULL;
  138. n = cec_notifier_get_conn(hdmi_dev, port_name);
  139. if (!n)
  140. return n;
  141. mutex_lock(&n->lock);
  142. n->cec_adap = adap;
  143. adap->conn_info = n->conn_info;
  144. adap->notifier = n;
  145. if (!adap->adap_controls_phys_addr)
  146. cec_s_phys_addr(adap, n->phys_addr, false);
  147. mutex_unlock(&n->lock);
  148. return n;
  149. }
  150. EXPORT_SYMBOL_GPL(cec_notifier_cec_adap_register);
  151. void cec_notifier_cec_adap_unregister(struct cec_notifier *n,
  152. struct cec_adapter *adap)
  153. {
  154. if (!n)
  155. return;
  156. mutex_lock(&n->lock);
  157. adap->notifier = NULL;
  158. n->cec_adap = NULL;
  159. mutex_unlock(&n->lock);
  160. cec_notifier_put(n);
  161. }
  162. EXPORT_SYMBOL_GPL(cec_notifier_cec_adap_unregister);
  163. void cec_notifier_set_phys_addr(struct cec_notifier *n, u16 pa)
  164. {
  165. if (n == NULL)
  166. return;
  167. mutex_lock(&n->lock);
  168. n->phys_addr = pa;
  169. if (n->cec_adap && !n->cec_adap->adap_controls_phys_addr)
  170. cec_s_phys_addr(n->cec_adap, n->phys_addr, false);
  171. mutex_unlock(&n->lock);
  172. }
  173. EXPORT_SYMBOL_GPL(cec_notifier_set_phys_addr);
  174. /*
  175. * Note: In the drm subsystem, prefer calling (if possible):
  176. *
  177. * cec_notifier_set_phys_addr(n, connector->display_info.source_physical_address);
  178. */
  179. void cec_notifier_set_phys_addr_from_edid(struct cec_notifier *n,
  180. const struct edid *edid)
  181. {
  182. u16 pa = CEC_PHYS_ADDR_INVALID;
  183. if (n == NULL)
  184. return;
  185. if (edid && edid->extensions)
  186. pa = cec_get_edid_phys_addr((const u8 *)edid,
  187. EDID_LENGTH * (edid->extensions + 1), NULL);
  188. cec_notifier_set_phys_addr(n, pa);
  189. }
  190. EXPORT_SYMBOL_GPL(cec_notifier_set_phys_addr_from_edid);
  191. struct device *cec_notifier_parse_hdmi_phandle(struct device *dev)
  192. {
  193. struct platform_device *hdmi_pdev;
  194. struct device *hdmi_dev = NULL;
  195. struct device_node *np;
  196. np = of_parse_phandle(dev->of_node, "hdmi-phandle", 0);
  197. if (!np) {
  198. dev_err(dev, "Failed to find HDMI node in device tree\n");
  199. return ERR_PTR(-ENODEV);
  200. }
  201. hdmi_pdev = of_find_device_by_node(np);
  202. if (hdmi_pdev)
  203. hdmi_dev = &hdmi_pdev->dev;
  204. #if IS_REACHABLE(CONFIG_I2C)
  205. if (!hdmi_dev) {
  206. struct i2c_client *hdmi_client = of_find_i2c_device_by_node(np);
  207. if (hdmi_client)
  208. hdmi_dev = &hdmi_client->dev;
  209. }
  210. #endif
  211. of_node_put(np);
  212. if (!hdmi_dev)
  213. return ERR_PTR(-EPROBE_DEFER);
  214. /*
  215. * Note that the device struct is only used as a key into the
  216. * cec_notifiers list, it is never actually accessed.
  217. * So we decrement the reference here so we don't leak
  218. * memory.
  219. */
  220. put_device(hdmi_dev);
  221. return hdmi_dev;
  222. }
  223. EXPORT_SYMBOL_GPL(cec_notifier_parse_hdmi_phandle);