omap_connector.c 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157
  1. // SPDX-License-Identifier: GPL-2.0-only
  2. /*
  3. * Copyright (C) 2011 Texas Instruments Incorporated - http://www.ti.com/
  4. * Author: Rob Clark <rob@ti.com>
  5. */
  6. #include <drm/drm_atomic_helper.h>
  7. #include <drm/drm_crtc.h>
  8. #include <drm/drm_probe_helper.h>
  9. #include "omap_drv.h"
  10. /*
  11. * connector funcs
  12. */
  13. #define to_omap_connector(x) container_of(x, struct omap_connector, base)
  14. struct omap_connector {
  15. struct drm_connector base;
  16. struct omap_dss_device *output;
  17. };
  18. static enum drm_connector_status omap_connector_detect(
  19. struct drm_connector *connector, bool force)
  20. {
  21. return connector_status_connected;
  22. }
  23. static void omap_connector_destroy(struct drm_connector *connector)
  24. {
  25. struct omap_connector *omap_connector = to_omap_connector(connector);
  26. DBG("%s", connector->name);
  27. drm_connector_unregister(connector);
  28. drm_connector_cleanup(connector);
  29. omapdss_device_put(omap_connector->output);
  30. kfree(omap_connector);
  31. }
  32. static int omap_connector_get_modes(struct drm_connector *connector)
  33. {
  34. struct omap_connector *omap_connector = to_omap_connector(connector);
  35. struct omap_dss_device *dssdev = NULL;
  36. struct omap_dss_device *d;
  37. DBG("%s", connector->name);
  38. /*
  39. * If the display pipeline reports modes (e.g. with a fixed resolution
  40. * panel or an analog TV output), query it.
  41. */
  42. for (d = omap_connector->output; d; d = d->next) {
  43. if (d->ops_flags & OMAP_DSS_DEVICE_OP_MODES)
  44. dssdev = d;
  45. }
  46. if (dssdev)
  47. return dssdev->ops->get_modes(dssdev, connector);
  48. /* We can't retrieve modes. The KMS core will add the default modes. */
  49. return 0;
  50. }
  51. enum drm_mode_status omap_connector_mode_fixup(struct omap_dss_device *dssdev,
  52. const struct drm_display_mode *mode,
  53. struct drm_display_mode *adjusted_mode)
  54. {
  55. int ret;
  56. drm_mode_copy(adjusted_mode, mode);
  57. for (; dssdev; dssdev = dssdev->next) {
  58. if (!dssdev->ops || !dssdev->ops->check_timings)
  59. continue;
  60. ret = dssdev->ops->check_timings(dssdev, adjusted_mode);
  61. if (ret)
  62. return MODE_BAD;
  63. }
  64. return MODE_OK;
  65. }
  66. static enum drm_mode_status omap_connector_mode_valid(struct drm_connector *connector,
  67. struct drm_display_mode *mode)
  68. {
  69. struct omap_connector *omap_connector = to_omap_connector(connector);
  70. struct drm_display_mode new_mode = {};
  71. enum drm_mode_status status;
  72. status = omap_connector_mode_fixup(omap_connector->output, mode,
  73. &new_mode);
  74. if (status != MODE_OK)
  75. goto done;
  76. /* Check if vrefresh is still valid. */
  77. if (drm_mode_vrefresh(mode) != drm_mode_vrefresh(&new_mode))
  78. status = MODE_NOCLOCK;
  79. done:
  80. DBG("connector: mode %s: " DRM_MODE_FMT,
  81. (status == MODE_OK) ? "valid" : "invalid",
  82. DRM_MODE_ARG(mode));
  83. return status;
  84. }
  85. static const struct drm_connector_funcs omap_connector_funcs = {
  86. .reset = drm_atomic_helper_connector_reset,
  87. .detect = omap_connector_detect,
  88. .fill_modes = drm_helper_probe_single_connector_modes,
  89. .destroy = omap_connector_destroy,
  90. .atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state,
  91. .atomic_destroy_state = drm_atomic_helper_connector_destroy_state,
  92. };
  93. static const struct drm_connector_helper_funcs omap_connector_helper_funcs = {
  94. .get_modes = omap_connector_get_modes,
  95. .mode_valid = omap_connector_mode_valid,
  96. };
  97. /* initialize connector */
  98. struct drm_connector *omap_connector_init(struct drm_device *dev,
  99. struct omap_dss_device *output,
  100. struct drm_encoder *encoder)
  101. {
  102. struct drm_connector *connector = NULL;
  103. struct omap_connector *omap_connector;
  104. DBG("%s", output->name);
  105. omap_connector = kzalloc(sizeof(*omap_connector), GFP_KERNEL);
  106. if (!omap_connector)
  107. goto fail;
  108. omap_connector->output = omapdss_device_get(output);
  109. connector = &omap_connector->base;
  110. connector->interlace_allowed = 1;
  111. connector->doublescan_allowed = 0;
  112. drm_connector_init(dev, connector, &omap_connector_funcs,
  113. DRM_MODE_CONNECTOR_DSI);
  114. drm_connector_helper_add(connector, &omap_connector_helper_funcs);
  115. return connector;
  116. fail:
  117. if (connector)
  118. omap_connector_destroy(connector);
  119. return NULL;
  120. }