omap_encoder.c 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146
  1. // SPDX-License-Identifier: GPL-2.0-only
  2. /*
  3. * Copyright (C) 2011 Texas Instruments Incorporated - https://www.ti.com/
  4. * Author: Rob Clark <[email protected]>
  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 drm_bridge *bridge;
  68. struct videomode vm = { 0 };
  69. u32 bus_flags;
  70. list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
  71. if (connector->encoder == encoder)
  72. break;
  73. }
  74. drm_display_mode_to_videomode(adjusted_mode, &vm);
  75. /*
  76. * HACK: This fixes the vm flags.
  77. * struct drm_display_mode does not contain the VSYNC/HSYNC/DE flags and
  78. * they get lost when converting back and forth between struct
  79. * drm_display_mode and struct videomode. The hack below goes and
  80. * fetches the missing flags.
  81. *
  82. * A better solution is to use DRM's bus-flags through the whole driver.
  83. */
  84. for (bridge = output->bridge; bridge;
  85. bridge = drm_bridge_get_next_bridge(bridge)) {
  86. if (!bridge->timings)
  87. continue;
  88. bus_flags = bridge->timings->input_bus_flags;
  89. omap_encoder_update_videomode_flags(&vm, bus_flags);
  90. }
  91. bus_flags = connector->display_info.bus_flags;
  92. omap_encoder_update_videomode_flags(&vm, bus_flags);
  93. /* Set timings for all devices in the display pipeline. */
  94. dss_mgr_set_timings(output, &vm);
  95. }
  96. static const struct drm_encoder_helper_funcs omap_encoder_helper_funcs = {
  97. .mode_set = omap_encoder_mode_set,
  98. };
  99. /* initialize encoder */
  100. struct drm_encoder *omap_encoder_init(struct drm_device *dev,
  101. struct omap_dss_device *output)
  102. {
  103. struct drm_encoder *encoder = NULL;
  104. struct omap_encoder *omap_encoder;
  105. omap_encoder = kzalloc(sizeof(*omap_encoder), GFP_KERNEL);
  106. if (!omap_encoder)
  107. goto fail;
  108. omap_encoder->output = output;
  109. encoder = &omap_encoder->base;
  110. drm_encoder_init(dev, encoder, &omap_encoder_funcs,
  111. DRM_MODE_ENCODER_TMDS, NULL);
  112. drm_encoder_helper_add(encoder, &omap_encoder_helper_funcs);
  113. return encoder;
  114. fail:
  115. if (encoder)
  116. omap_encoder_destroy(encoder);
  117. return NULL;
  118. }