The ->detect() vfunc of connectors is usually responsible for setting the
encoder type on intel_digital_ports when a hotplug event happens.

However we sometimes want to force a modeset on a specific connector:
  - the user can ask the SETCRTC ioctl to use a connector that wasne
    marked as connected (because we never received a hotplug event for it).
    This can be also used in tests to do a modeset without the need of a
    plugged-in monitor.
  - the command line video= option can be used to force modesets, eg.:
    video=HDMI-A-1:1024x768e

So, before we try to do anything with the DDI encoder as part of a modeset,
we need to ensure that the personality of the encoder matches the selected
connector.

Signed-off-by: Damien Lespiau <damien.lesp...@intel.com>
---
 drivers/gpu/drm/i915/intel_ddi.c     | 50 ++++++++++++++++++++++++++++++++++++
 drivers/gpu/drm/i915/intel_display.c |  2 ++
 drivers/gpu/drm/i915/intel_drv.h     |  1 +
 3 files changed, 53 insertions(+)

diff --git a/drivers/gpu/drm/i915/intel_ddi.c b/drivers/gpu/drm/i915/intel_ddi.c
index c8382f5..fe04a09 100644
--- a/drivers/gpu/drm/i915/intel_ddi.c
+++ b/drivers/gpu/drm/i915/intel_ddi.c
@@ -701,6 +701,56 @@ intel_ddi_calculate_wrpll(int clock /* in Hz */,
                      clock, *p_out, *n2_out, *r2_out);
 }
 
+/*
+ * The ->detect() vfunc of connectors is usually responsible for setting the
+ * encoder type on intel_digital_ports when a hotplug event happens.
+ *
+ * However we sometimes want to force a modeset on a specific connector:
+ *   - the user can ask the SETCRTC ioctl to use a connector that isn't marked
+ *     as connected (because we never received a hotplug event for it).
+ *     This can be also used in tests to do a modeset without the need of a
+ *     plugged-in monitor.
+ *   - the command line video= option can be used to force modesets, eg.:
+ *     video=HDMI-A-1:1024x768e
+ *
+ * So, before we try to do anything with the DDI encoder as part of a modeset,
+ * we need to ensure that the personality of the encoder matches the selected
+ * connector.
+ */
+void
+intel_ddi_ensure_encoder_type(struct drm_crtc *crtc)
+{
+       struct drm_device *dev = crtc->dev;
+       struct intel_connector *connector;
+
+       if (!HAS_DDI(dev))
+               return;
+
+       list_for_each_entry(connector, &dev->mode_config.connector_list,
+                           base.head) {
+               int connector_type = connector->base.connector_type;
+
+               if (!connector->new_encoder)
+                       continue;
+
+               if (connector_type == DRM_MODE_CONNECTOR_HDMIA ||
+                   connector_type == DRM_MODE_CONNECTOR_HDMIB) {
+                       connector->new_encoder->type = INTEL_OUTPUT_HDMI;
+                       continue;
+               }
+
+               if (connector_type == DRM_MODE_CONNECTOR_eDP) {
+                       connector->new_encoder->type = INTEL_OUTPUT_EDP;
+                       continue;
+               }
+
+               if (connector_type == DRM_MODE_CONNECTOR_DisplayPort) {
+                       connector->new_encoder->type = INTEL_OUTPUT_DISPLAYPORT;
+                       continue;
+               }
+       }
+}
+
 bool intel_ddi_pll_mode_set(struct drm_crtc *crtc)
 {
        struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
diff --git a/drivers/gpu/drm/i915/intel_display.c 
b/drivers/gpu/drm/i915/intel_display.c
index 5dff7ca..dcd7a9c 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -9565,6 +9565,8 @@ static int __intel_set_mode(struct drm_crtc *crtc,
        *saved_hwmode = crtc->hwmode;
        *saved_mode = crtc->mode;
 
+       intel_ddi_ensure_encoder_type(crtc);
+
        /* Hack: Because we don't (yet) support global modeset on multiple
         * crtcs, we don't keep track of the new mode for more than one crtc.
         * Hence simply check whether any bit is set in modeset_pipes in all the
diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
index 2b5bcb6..ebf6ba4 100644
--- a/drivers/gpu/drm/i915/intel_drv.h
+++ b/drivers/gpu/drm/i915/intel_drv.h
@@ -612,6 +612,7 @@ void intel_ddi_disable_transcoder_func(struct 
drm_i915_private *dev_priv,
 void intel_ddi_enable_pipe_clock(struct intel_crtc *intel_crtc);
 void intel_ddi_disable_pipe_clock(struct intel_crtc *intel_crtc);
 void intel_ddi_setup_hw_pll_state(struct drm_device *dev);
+void intel_ddi_ensure_encoder_type(struct drm_crtc *crtc);
 bool intel_ddi_pll_mode_set(struct drm_crtc *crtc);
 void intel_ddi_put_crtc_pll(struct drm_crtc *crtc);
 void intel_ddi_set_pipe_settings(struct drm_crtc *crtc);
-- 
1.8.3.1

_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx

Reply via email to