output.c 6.7 KB

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