0516-drm-vc4-Fix-handling-of-interlaced-video-modes.patch 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104
  1. From fa69b17facd1a2fd3e430b78f65b60b4a087b53d Mon Sep 17 00:00:00 2001
  2. From: Mario Kleiner <mario.kleiner.de@gmail.com>
  3. Date: Tue, 19 Jul 2016 20:58:58 +0200
  4. Subject: [PATCH] drm/vc4: Fix handling of interlaced video modes.
  5. We must not apply CRTC_INTERLACE_HALVE_V to interlaced modes during
  6. mode enumeration, as drm_helper_probe_single_connector_modes
  7. does, so wrap it and reset the effect of CRTC_INTERLACE_HALVE_V
  8. on affected interlaced modes.
  9. Also mode_fixup interlaced modes passed in from user space.
  10. This fixes the vblank timestamping constants and entries in
  11. the mode->crtc_xxx fields needed for precise vblank timestamping.
  12. Signed-off-by: Mario Kleiner <mario.kleiner.de@gmail.com>
  13. Signed-off-by: Eric Anholt <eric@anholt.net>
  14. ---
  15. drivers/gpu/drm/vc4/vc4_crtc.c | 18 ++++++++++++++++++
  16. drivers/gpu/drm/vc4/vc4_hdmi.c | 29 +++++++++++++++++++++++++++--
  17. 2 files changed, 45 insertions(+), 2 deletions(-)
  18. --- a/drivers/gpu/drm/vc4/vc4_crtc.c
  19. +++ b/drivers/gpu/drm/vc4/vc4_crtc.c
  20. @@ -538,6 +538,23 @@ static void vc4_crtc_enable(struct drm_c
  21. CRTC_READ(PV_V_CONTROL) | PV_VCONTROL_VIDEN);
  22. }
  23. +static bool vc4_crtc_mode_fixup(struct drm_crtc *crtc,
  24. + const struct drm_display_mode *mode,
  25. + struct drm_display_mode *adjusted_mode)
  26. +{
  27. + /*
  28. + * Interlaced video modes got CRTC_INTERLACE_HALVE_V applied when
  29. + * coming from user space. We don't want this, as it screws up
  30. + * vblank timestamping, so fix it up.
  31. + */
  32. + drm_mode_set_crtcinfo(adjusted_mode, 0);
  33. +
  34. + DRM_DEBUG_KMS("[CRTC:%d] adjusted_mode :\n", crtc->base.id);
  35. + drm_mode_debug_printmodeline(adjusted_mode);
  36. +
  37. + return true;
  38. +}
  39. +
  40. static int vc4_crtc_atomic_check(struct drm_crtc *crtc,
  41. struct drm_crtc_state *state)
  42. {
  43. @@ -848,6 +865,7 @@ static const struct drm_crtc_helper_func
  44. .mode_set_nofb = vc4_crtc_mode_set_nofb,
  45. .disable = vc4_crtc_disable,
  46. .enable = vc4_crtc_enable,
  47. + .mode_fixup = vc4_crtc_mode_fixup,
  48. .atomic_check = vc4_crtc_atomic_check,
  49. .atomic_flush = vc4_crtc_atomic_flush,
  50. };
  51. --- a/drivers/gpu/drm/vc4/vc4_hdmi.c
  52. +++ b/drivers/gpu/drm/vc4/vc4_hdmi.c
  53. @@ -219,10 +219,35 @@ vc4_hdmi_connector_best_encoder(struct d
  54. return hdmi_connector->encoder;
  55. }
  56. +/*
  57. + * drm_helper_probe_single_connector_modes() applies drm_mode_set_crtcinfo to
  58. + * all modes with flag CRTC_INTERLACE_HALVE_V. We don't want this, as it
  59. + * screws up vblank timestamping for interlaced modes, so fix it up.
  60. + */
  61. +static int vc4_hdmi_connector_probe_modes(struct drm_connector *connector,
  62. + uint32_t maxX, uint32_t maxY)
  63. +{
  64. + struct drm_display_mode *mode;
  65. + int count;
  66. +
  67. + count = drm_helper_probe_single_connector_modes(connector, maxX, maxY);
  68. + if (count == 0)
  69. + return 0;
  70. +
  71. + DRM_DEBUG_KMS("[CONNECTOR:%d:%s] probed adapted modes :\n",
  72. + connector->base.id, connector->name);
  73. + list_for_each_entry(mode, &connector->modes, head) {
  74. + drm_mode_set_crtcinfo(mode, 0);
  75. + drm_mode_debug_printmodeline(mode);
  76. + }
  77. +
  78. + return count;
  79. +}
  80. +
  81. static const struct drm_connector_funcs vc4_hdmi_connector_funcs = {
  82. .dpms = drm_atomic_helper_connector_dpms,
  83. .detect = vc4_hdmi_connector_detect,
  84. - .fill_modes = drm_helper_probe_single_connector_modes,
  85. + .fill_modes = vc4_hdmi_connector_probe_modes,
  86. .destroy = vc4_hdmi_connector_destroy,
  87. .reset = drm_atomic_helper_connector_reset,
  88. .atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state,
  89. @@ -258,7 +283,7 @@ static struct drm_connector *vc4_hdmi_co
  90. connector->polled = (DRM_CONNECTOR_POLL_CONNECT |
  91. DRM_CONNECTOR_POLL_DISCONNECT);
  92. - connector->interlace_allowed = 0;
  93. + connector->interlace_allowed = 1;
  94. connector->doublescan_allowed = 0;
  95. drm_mode_connector_attach_encoder(connector, encoder);