output.c 6.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265
  1. // SPDX-License-Identifier: GPL-2.0-only
  2. /*
  3. * Copyright (C) 2012 Avionic Design GmbH
  4. * Copyright (C) 2012 NVIDIA CORPORATION. All rights reserved.
  5. */
  6. #include <drm/drm_atomic_helper.h>
  7. #include <drm/drm_of.h>
  8. #include <drm/drm_panel.h>
  9. #include <drm/drm_simple_kms_helper.h>
  10. #include "drm.h"
  11. #include "dc.h"
  12. #include <media/cec-notifier.h>
  13. int tegra_output_connector_get_modes(struct drm_connector *connector)
  14. {
  15. struct tegra_output *output = connector_to_output(connector);
  16. struct edid *edid = NULL;
  17. int err = 0;
  18. /*
  19. * If the panel provides one or more modes, use them exclusively and
  20. * ignore any other means of obtaining a mode.
  21. */
  22. if (output->panel) {
  23. err = drm_panel_get_modes(output->panel, connector);
  24. if (err > 0)
  25. return err;
  26. }
  27. if (output->edid)
  28. edid = kmemdup(output->edid, sizeof(*edid), GFP_KERNEL);
  29. else if (output->ddc)
  30. edid = drm_get_edid(connector, output->ddc);
  31. cec_notifier_set_phys_addr_from_edid(output->cec, edid);
  32. drm_connector_update_edid_property(connector, edid);
  33. if (edid) {
  34. err = drm_add_edid_modes(connector, edid);
  35. kfree(edid);
  36. }
  37. return err;
  38. }
  39. enum drm_connector_status
  40. tegra_output_connector_detect(struct drm_connector *connector, bool force)
  41. {
  42. struct tegra_output *output = connector_to_output(connector);
  43. enum drm_connector_status status = connector_status_unknown;
  44. if (output->hpd_gpio) {
  45. if (gpiod_get_value(output->hpd_gpio) == 0)
  46. status = connector_status_disconnected;
  47. else
  48. status = connector_status_connected;
  49. } else {
  50. if (!output->panel)
  51. status = connector_status_disconnected;
  52. else
  53. status = connector_status_connected;
  54. }
  55. if (status != connector_status_connected)
  56. cec_notifier_phys_addr_invalidate(output->cec);
  57. return status;
  58. }
  59. void tegra_output_connector_destroy(struct drm_connector *connector)
  60. {
  61. struct tegra_output *output = connector_to_output(connector);
  62. if (output->cec)
  63. cec_notifier_conn_unregister(output->cec);
  64. drm_connector_unregister(connector);
  65. drm_connector_cleanup(connector);
  66. }
  67. static irqreturn_t hpd_irq(int irq, void *data)
  68. {
  69. struct tegra_output *output = data;
  70. if (output->connector.dev)
  71. drm_helper_hpd_irq_event(output->connector.dev);
  72. return IRQ_HANDLED;
  73. }
  74. int tegra_output_probe(struct tegra_output *output)
  75. {
  76. struct device_node *ddc, *panel;
  77. unsigned long flags;
  78. int err, size;
  79. if (!output->of_node)
  80. output->of_node = output->dev->of_node;
  81. err = drm_of_find_panel_or_bridge(output->of_node, -1, -1,
  82. &output->panel, &output->bridge);
  83. if (err && err != -ENODEV)
  84. return err;
  85. panel = of_parse_phandle(output->of_node, "nvidia,panel", 0);
  86. if (panel) {
  87. /*
  88. * Don't mix nvidia,panel phandle with the graph in a
  89. * device-tree.
  90. */
  91. WARN_ON(output->panel || output->bridge);
  92. output->panel = of_drm_find_panel(panel);
  93. of_node_put(panel);
  94. if (IS_ERR(output->panel))
  95. return PTR_ERR(output->panel);
  96. }
  97. output->edid = of_get_property(output->of_node, "nvidia,edid", &size);
  98. ddc = of_parse_phandle(output->of_node, "nvidia,ddc-i2c-bus", 0);
  99. if (ddc) {
  100. output->ddc = of_get_i2c_adapter_by_node(ddc);
  101. of_node_put(ddc);
  102. if (!output->ddc) {
  103. err = -EPROBE_DEFER;
  104. return err;
  105. }
  106. }
  107. output->hpd_gpio = devm_gpiod_get_from_of_node(output->dev,
  108. output->of_node,
  109. "nvidia,hpd-gpio", 0,
  110. GPIOD_IN,
  111. "HDMI hotplug detect");
  112. if (IS_ERR(output->hpd_gpio)) {
  113. if (PTR_ERR(output->hpd_gpio) != -ENOENT)
  114. return PTR_ERR(output->hpd_gpio);
  115. output->hpd_gpio = NULL;
  116. }
  117. if (output->hpd_gpio) {
  118. err = gpiod_to_irq(output->hpd_gpio);
  119. if (err < 0) {
  120. dev_err(output->dev, "gpiod_to_irq(): %d\n", err);
  121. return err;
  122. }
  123. output->hpd_irq = err;
  124. flags = IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING |
  125. IRQF_ONESHOT;
  126. err = request_threaded_irq(output->hpd_irq, NULL, hpd_irq,
  127. flags, "hpd", output);
  128. if (err < 0) {
  129. dev_err(output->dev, "failed to request IRQ#%u: %d\n",
  130. output->hpd_irq, err);
  131. return err;
  132. }
  133. output->connector.polled = DRM_CONNECTOR_POLL_HPD;
  134. /*
  135. * Disable the interrupt until the connector has been
  136. * initialized to avoid a race in the hotplug interrupt
  137. * handler.
  138. */
  139. disable_irq(output->hpd_irq);
  140. }
  141. return 0;
  142. }
  143. void tegra_output_remove(struct tegra_output *output)
  144. {
  145. if (output->hpd_gpio)
  146. free_irq(output->hpd_irq, output);
  147. if (output->ddc)
  148. i2c_put_adapter(output->ddc);
  149. }
  150. int tegra_output_init(struct drm_device *drm, struct tegra_output *output)
  151. {
  152. int connector_type;
  153. /*
  154. * The connector is now registered and ready to receive hotplug events
  155. * so the hotplug interrupt can be enabled.
  156. */
  157. if (output->hpd_gpio)
  158. enable_irq(output->hpd_irq);
  159. connector_type = output->connector.connector_type;
  160. /*
  161. * Create a CEC notifier for HDMI connector.
  162. */
  163. if (connector_type == DRM_MODE_CONNECTOR_HDMIA ||
  164. connector_type == DRM_MODE_CONNECTOR_HDMIB) {
  165. struct cec_connector_info conn_info;
  166. cec_fill_conn_info_from_drm(&conn_info, &output->connector);
  167. output->cec = cec_notifier_conn_register(output->dev, NULL,
  168. &conn_info);
  169. if (!output->cec)
  170. return -ENOMEM;
  171. }
  172. return 0;
  173. }
  174. void tegra_output_exit(struct tegra_output *output)
  175. {
  176. /*
  177. * The connector is going away, so the interrupt must be disabled to
  178. * prevent the hotplug interrupt handler from potentially crashing.
  179. */
  180. if (output->hpd_gpio)
  181. disable_irq(output->hpd_irq);
  182. }
  183. void tegra_output_find_possible_crtcs(struct tegra_output *output,
  184. struct drm_device *drm)
  185. {
  186. struct device *dev = output->dev;
  187. struct drm_crtc *crtc;
  188. unsigned int mask = 0;
  189. drm_for_each_crtc(crtc, drm) {
  190. struct tegra_dc *dc = to_tegra_dc(crtc);
  191. if (tegra_dc_has_output(dc, dev))
  192. mask |= drm_crtc_mask(crtc);
  193. }
  194. if (mask == 0) {
  195. dev_warn(dev, "missing output definition for heads in DT\n");
  196. mask = 0x3;
  197. }
  198. output->encoder.possible_crtcs = mask;
  199. }
  200. int tegra_output_suspend(struct tegra_output *output)
  201. {
  202. if (output->hpd_irq)
  203. disable_irq(output->hpd_irq);
  204. return 0;
  205. }
  206. int tegra_output_resume(struct tegra_output *output)
  207. {
  208. if (output->hpd_irq)
  209. enable_irq(output->hpd_irq);
  210. return 0;
  211. }