output.c 6.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272
  1. /*
  2. * Copyright (C) 2012 Avionic Design GmbH
  3. * Copyright (C) 2012 NVIDIA CORPORATION. All rights reserved.
  4. *
  5. * This program is free software; you can redistribute it and/or modify
  6. * it under the terms of the GNU General Public License version 2 as
  7. * published by the Free Software Foundation.
  8. */
  9. #include <linux/module.h>
  10. #include <linux/of_gpio.h>
  11. #include <linux/of_i2c.h>
  12. #include "drm.h"
  13. static int tegra_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. if (output->edid)
  19. edid = kmemdup(output->edid, sizeof(*edid), GFP_KERNEL);
  20. else if (output->ddc)
  21. edid = drm_get_edid(connector, output->ddc);
  22. drm_mode_connector_update_edid_property(connector, edid);
  23. if (edid) {
  24. err = drm_add_edid_modes(connector, edid);
  25. kfree(edid);
  26. }
  27. return err;
  28. }
  29. static int tegra_connector_mode_valid(struct drm_connector *connector,
  30. struct drm_display_mode *mode)
  31. {
  32. struct tegra_output *output = connector_to_output(connector);
  33. enum drm_mode_status status = MODE_OK;
  34. int err;
  35. err = tegra_output_check_mode(output, mode, &status);
  36. if (err < 0)
  37. return MODE_ERROR;
  38. return status;
  39. }
  40. static struct drm_encoder *
  41. tegra_connector_best_encoder(struct drm_connector *connector)
  42. {
  43. struct tegra_output *output = connector_to_output(connector);
  44. return &output->encoder;
  45. }
  46. static const struct drm_connector_helper_funcs connector_helper_funcs = {
  47. .get_modes = tegra_connector_get_modes,
  48. .mode_valid = tegra_connector_mode_valid,
  49. .best_encoder = tegra_connector_best_encoder,
  50. };
  51. static enum drm_connector_status
  52. tegra_connector_detect(struct drm_connector *connector, bool force)
  53. {
  54. struct tegra_output *output = connector_to_output(connector);
  55. enum drm_connector_status status = connector_status_unknown;
  56. if (gpio_is_valid(output->hpd_gpio)) {
  57. if (gpio_get_value(output->hpd_gpio) == 0)
  58. status = connector_status_disconnected;
  59. else
  60. status = connector_status_connected;
  61. } else {
  62. if (connector->connector_type == DRM_MODE_CONNECTOR_LVDS)
  63. status = connector_status_connected;
  64. }
  65. return status;
  66. }
  67. static void tegra_connector_destroy(struct drm_connector *connector)
  68. {
  69. drm_sysfs_connector_remove(connector);
  70. drm_connector_cleanup(connector);
  71. }
  72. static const struct drm_connector_funcs connector_funcs = {
  73. .dpms = drm_helper_connector_dpms,
  74. .detect = tegra_connector_detect,
  75. .fill_modes = drm_helper_probe_single_connector_modes,
  76. .destroy = tegra_connector_destroy,
  77. };
  78. static void tegra_encoder_destroy(struct drm_encoder *encoder)
  79. {
  80. drm_encoder_cleanup(encoder);
  81. }
  82. static const struct drm_encoder_funcs encoder_funcs = {
  83. .destroy = tegra_encoder_destroy,
  84. };
  85. static void tegra_encoder_dpms(struct drm_encoder *encoder, int mode)
  86. {
  87. }
  88. static bool tegra_encoder_mode_fixup(struct drm_encoder *encoder,
  89. const struct drm_display_mode *mode,
  90. struct drm_display_mode *adjusted)
  91. {
  92. return true;
  93. }
  94. static void tegra_encoder_prepare(struct drm_encoder *encoder)
  95. {
  96. }
  97. static void tegra_encoder_commit(struct drm_encoder *encoder)
  98. {
  99. }
  100. static void tegra_encoder_mode_set(struct drm_encoder *encoder,
  101. struct drm_display_mode *mode,
  102. struct drm_display_mode *adjusted)
  103. {
  104. struct tegra_output *output = encoder_to_output(encoder);
  105. int err;
  106. err = tegra_output_enable(output);
  107. if (err < 0)
  108. dev_err(encoder->dev->dev, "tegra_output_enable(): %d\n", err);
  109. }
  110. static const struct drm_encoder_helper_funcs encoder_helper_funcs = {
  111. .dpms = tegra_encoder_dpms,
  112. .mode_fixup = tegra_encoder_mode_fixup,
  113. .prepare = tegra_encoder_prepare,
  114. .commit = tegra_encoder_commit,
  115. .mode_set = tegra_encoder_mode_set,
  116. };
  117. static irqreturn_t hpd_irq(int irq, void *data)
  118. {
  119. struct tegra_output *output = data;
  120. drm_helper_hpd_irq_event(output->connector.dev);
  121. return IRQ_HANDLED;
  122. }
  123. int tegra_output_parse_dt(struct tegra_output *output)
  124. {
  125. enum of_gpio_flags flags;
  126. struct device_node *ddc;
  127. size_t size;
  128. int err;
  129. if (!output->of_node)
  130. output->of_node = output->dev->of_node;
  131. output->edid = of_get_property(output->of_node, "nvidia,edid", &size);
  132. ddc = of_parse_phandle(output->of_node, "nvidia,ddc-i2c-bus", 0);
  133. if (ddc) {
  134. output->ddc = of_find_i2c_adapter_by_node(ddc);
  135. if (!output->ddc) {
  136. err = -EPROBE_DEFER;
  137. of_node_put(ddc);
  138. return err;
  139. }
  140. of_node_put(ddc);
  141. }
  142. if (!output->edid && !output->ddc)
  143. return -ENODEV;
  144. output->hpd_gpio = of_get_named_gpio_flags(output->of_node,
  145. "nvidia,hpd-gpio", 0,
  146. &flags);
  147. return 0;
  148. }
  149. int tegra_output_init(struct drm_device *drm, struct tegra_output *output)
  150. {
  151. int connector, encoder, err;
  152. if (gpio_is_valid(output->hpd_gpio)) {
  153. unsigned long flags;
  154. err = gpio_request_one(output->hpd_gpio, GPIOF_DIR_IN,
  155. "HDMI hotplug detect");
  156. if (err < 0) {
  157. dev_err(output->dev, "gpio_request_one(): %d\n", err);
  158. return err;
  159. }
  160. err = gpio_to_irq(output->hpd_gpio);
  161. if (err < 0) {
  162. dev_err(output->dev, "gpio_to_irq(): %d\n", err);
  163. goto free_hpd;
  164. }
  165. output->hpd_irq = err;
  166. flags = IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING |
  167. IRQF_ONESHOT;
  168. err = request_threaded_irq(output->hpd_irq, NULL, hpd_irq,
  169. flags, "hpd", output);
  170. if (err < 0) {
  171. dev_err(output->dev, "failed to request IRQ#%u: %d\n",
  172. output->hpd_irq, err);
  173. goto free_hpd;
  174. }
  175. output->connector.polled = DRM_CONNECTOR_POLL_HPD;
  176. }
  177. switch (output->type) {
  178. case TEGRA_OUTPUT_RGB:
  179. connector = DRM_MODE_CONNECTOR_LVDS;
  180. encoder = DRM_MODE_ENCODER_LVDS;
  181. break;
  182. case TEGRA_OUTPUT_HDMI:
  183. connector = DRM_MODE_CONNECTOR_HDMIA;
  184. encoder = DRM_MODE_ENCODER_TMDS;
  185. break;
  186. default:
  187. connector = DRM_MODE_CONNECTOR_Unknown;
  188. encoder = DRM_MODE_ENCODER_NONE;
  189. break;
  190. }
  191. drm_connector_init(drm, &output->connector, &connector_funcs,
  192. connector);
  193. drm_connector_helper_add(&output->connector, &connector_helper_funcs);
  194. drm_encoder_init(drm, &output->encoder, &encoder_funcs, encoder);
  195. drm_encoder_helper_add(&output->encoder, &encoder_helper_funcs);
  196. drm_mode_connector_attach_encoder(&output->connector, &output->encoder);
  197. drm_sysfs_connector_add(&output->connector);
  198. output->encoder.possible_crtcs = 0x3;
  199. return 0;
  200. free_hpd:
  201. gpio_free(output->hpd_gpio);
  202. return err;
  203. }
  204. int tegra_output_exit(struct tegra_output *output)
  205. {
  206. if (gpio_is_valid(output->hpd_gpio)) {
  207. free_irq(output->hpd_irq, output);
  208. gpio_free(output->hpd_gpio);
  209. }
  210. if (output->ddc)
  211. put_device(&output->ddc->dev);
  212. return 0;
  213. }