omap_encoder.c 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144
  1. // SPDX-License-Identifier: GPL-2.0-only
  2. /*
  3. * Copyright (C) 2011 Texas Instruments Incorporated - https://www.ti.com/
  4. * Author: Rob Clark <rob@ti.com>
  5. */
  6. #include <linux/list.h>
  7. #include <drm/drm_bridge.h>
  8. #include <drm/drm_crtc.h>
  9. #include <drm/drm_modeset_helper_vtables.h>
  10. #include <drm/drm_edid.h>
  11. #include "omap_drv.h"
  12. /*
  13. * encoder funcs
  14. */
  15. #define to_omap_encoder(x) container_of(x, struct omap_encoder, base)
  16. /* The encoder and connector both map to same dssdev.. the encoder
  17. * handles the 'active' parts, ie. anything the modifies the state
  18. * of the hw, and the connector handles the 'read-only' parts, like
  19. * detecting connection and reading edid.
  20. */
  21. struct omap_encoder {
  22. struct drm_encoder base;
  23. struct omap_dss_device *output;
  24. };
  25. static void omap_encoder_destroy(struct drm_encoder *encoder)
  26. {
  27. struct omap_encoder *omap_encoder = to_omap_encoder(encoder);
  28. drm_encoder_cleanup(encoder);
  29. kfree(omap_encoder);
  30. }
  31. static const struct drm_encoder_funcs omap_encoder_funcs = {
  32. .destroy = omap_encoder_destroy,
  33. };
  34. static void omap_encoder_update_videomode_flags(struct videomode *vm,
  35. u32 bus_flags)
  36. {
  37. if (!(vm->flags & (DISPLAY_FLAGS_DE_LOW |
  38. DISPLAY_FLAGS_DE_HIGH))) {
  39. if (bus_flags & DRM_BUS_FLAG_DE_LOW)
  40. vm->flags |= DISPLAY_FLAGS_DE_LOW;
  41. else if (bus_flags & DRM_BUS_FLAG_DE_HIGH)
  42. vm->flags |= DISPLAY_FLAGS_DE_HIGH;
  43. }
  44. if (!(vm->flags & (DISPLAY_FLAGS_PIXDATA_POSEDGE |
  45. DISPLAY_FLAGS_PIXDATA_NEGEDGE))) {
  46. if (bus_flags & DRM_BUS_FLAG_PIXDATA_DRIVE_POSEDGE)
  47. vm->flags |= DISPLAY_FLAGS_PIXDATA_POSEDGE;
  48. else if (bus_flags & DRM_BUS_FLAG_PIXDATA_DRIVE_NEGEDGE)
  49. vm->flags |= DISPLAY_FLAGS_PIXDATA_NEGEDGE;
  50. }
  51. if (!(vm->flags & (DISPLAY_FLAGS_SYNC_POSEDGE |
  52. DISPLAY_FLAGS_SYNC_NEGEDGE))) {
  53. if (bus_flags & DRM_BUS_FLAG_SYNC_DRIVE_POSEDGE)
  54. vm->flags |= DISPLAY_FLAGS_SYNC_POSEDGE;
  55. else if (bus_flags & DRM_BUS_FLAG_SYNC_DRIVE_NEGEDGE)
  56. vm->flags |= DISPLAY_FLAGS_SYNC_NEGEDGE;
  57. }
  58. }
  59. static void omap_encoder_mode_set(struct drm_encoder *encoder,
  60. struct drm_display_mode *mode,
  61. struct drm_display_mode *adjusted_mode)
  62. {
  63. struct omap_encoder *omap_encoder = to_omap_encoder(encoder);
  64. struct omap_dss_device *output = omap_encoder->output;
  65. struct drm_device *dev = encoder->dev;
  66. struct drm_connector *connector;
  67. struct videomode vm = { 0 };
  68. u32 bus_flags;
  69. list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
  70. if (connector->encoder == encoder)
  71. break;
  72. }
  73. drm_display_mode_to_videomode(adjusted_mode, &vm);
  74. /*
  75. * HACK: This fixes the vm flags.
  76. * struct drm_display_mode does not contain the VSYNC/HSYNC/DE flags and
  77. * they get lost when converting back and forth between struct
  78. * drm_display_mode and struct videomode. The hack below goes and
  79. * fetches the missing flags.
  80. *
  81. * A better solution is to use DRM's bus-flags through the whole driver.
  82. */
  83. drm_for_each_bridge_in_chain_from(output->bridge, bridge) {
  84. if (!bridge->timings)
  85. continue;
  86. bus_flags = bridge->timings->input_bus_flags;
  87. omap_encoder_update_videomode_flags(&vm, bus_flags);
  88. }
  89. bus_flags = connector->display_info.bus_flags;
  90. omap_encoder_update_videomode_flags(&vm, bus_flags);
  91. /* Set timings for all devices in the display pipeline. */
  92. dss_mgr_set_timings(output, &vm);
  93. }
  94. static const struct drm_encoder_helper_funcs omap_encoder_helper_funcs = {
  95. .mode_set = omap_encoder_mode_set,
  96. };
  97. /* initialize encoder */
  98. struct drm_encoder *omap_encoder_init(struct drm_device *dev,
  99. struct omap_dss_device *output)
  100. {
  101. struct drm_encoder *encoder = NULL;
  102. struct omap_encoder *omap_encoder;
  103. omap_encoder = kzalloc_obj(*omap_encoder);
  104. if (!omap_encoder)
  105. goto fail;
  106. omap_encoder->output = output;
  107. encoder = &omap_encoder->base;
  108. drm_encoder_init(dev, encoder, &omap_encoder_funcs,
  109. DRM_MODE_ENCODER_TMDS, NULL);
  110. drm_encoder_helper_add(encoder, &omap_encoder_helper_funcs);
  111. return encoder;
  112. fail:
  113. if (encoder)
  114. omap_encoder_destroy(encoder);
  115. return NULL;
  116. }