[Intel-gfx] [PATCH] drm: i915: Improve behavior in case of broken HDMI EDID
Daniel Vetter
daniel at ffwll.ch
Wed Apr 20 11:34:38 UTC 2016
On Tue, Apr 19, 2016 at 02:31:13PM -0300, Ezequiel Garcia wrote:
> Currently, our implementation of drm_connector_funcs.detect is
> based on getting a valid EDID.
>
> This requirement makes the driver fail to detect connected
> connectors in case of EDID corruption, which in turn prevents
> from falling back to modes provided by builtin or user-provided
> EDIDs.
Imo, this should be fixed in the probe helpers. Something like the below
might make sense:
diff --git a/drivers/gpu/drm/drm_probe_helper.c b/drivers/gpu/drm/drm_probe_helper.c
index e714b5a7955f..d3b9dc7535da 100644
--- a/drivers/gpu/drm/drm_probe_helper.c
+++ b/drivers/gpu/drm/drm_probe_helper.c
@@ -214,7 +214,10 @@ int drm_helper_probe_single_connector_modes(struct drm_connector *connector,
else
connector->status = connector_status_disconnected;
if (connector->funcs->force)
- connector->funcs->force(connector);
+ connector->funcs->force(connector);
+ } else if (connector->override_edid){
+ connector->status = connector_status_connected;
+ connector->funcs->force(connector);
} else {
connector->status = connector->funcs->detect(connector, true);
}
It should do what you want it to do, still allow us to override force
state manually and also fix things up for every, not just i915-hdmi. Also,
much smaller patch.
Only downside is that we need acks from other driver maintainers, since
essentially it's a behaviour change. Thus far you had to both inject the
edid and override status if your sink was totally busted. Now just
injecting edid will be enough.
Cheers, Daniel
>
> Let's fix this by calling drm_probe_ddc in drm_connector_funcs.detect,
> and do the EDID full reading and parsing in
> drm_connector_helper_funcs.get_modes, when it's actually needed.
>
> This patch allows i915 to take advantage of the DRM_LOAD_EDID_FIRMWARE
> infrastructure.
>
> Without this patch, any device that fails to provide a valid
> EDID will be reported as disconnected (unless the state is forced)
> and thus the kernel won't allow to use such device with any mode,
> either builtin, user-provided, or the 1024x768 noedid fallback.
>
> Signed-off-by: Ezequiel Garcia <ezequiel at vanguardiasur.com.ar>
> ---
> This patch supersedes: "drm/i915/hdmi: Fix weak connector detection",
> https://patchwork.freedesktop.org/patch/79098/.
>
> drivers/gpu/drm/i915/intel_hdmi.c | 59 ++++++++++++++++++++++++---------------
> 1 file changed, 36 insertions(+), 23 deletions(-)
>
> diff --git a/drivers/gpu/drm/i915/intel_hdmi.c b/drivers/gpu/drm/i915/intel_hdmi.c
> index 616108c4bc3e..aa2f2271394a 100644
> --- a/drivers/gpu/drm/i915/intel_hdmi.c
> +++ b/drivers/gpu/drm/i915/intel_hdmi.c
> @@ -1392,36 +1392,17 @@ intel_hdmi_detect(struct drm_connector *connector, bool force)
> enum drm_connector_status status;
> struct intel_hdmi *intel_hdmi = intel_attached_hdmi(connector);
> struct drm_i915_private *dev_priv = to_i915(connector->dev);
> - bool live_status = false;
> - unsigned int try;
> -
> - DRM_DEBUG_KMS("[CONNECTOR:%d:%s]\n",
> - connector->base.id, connector->name);
> + struct i2c_adapter *adap;
>
> intel_display_power_get(dev_priv, POWER_DOMAIN_GMBUS);
>
> - for (try = 0; !live_status && try < 9; try++) {
> - if (try)
> - msleep(10);
> - live_status = intel_digital_port_connected(dev_priv,
> - hdmi_to_dig_port(intel_hdmi));
> - }
> -
> - if (!live_status)
> - DRM_DEBUG_KMS("Live status not up!");
> -
> - intel_hdmi_unset_edid(connector);
> -
> - if (intel_hdmi_set_edid(connector, live_status)) {
> - struct intel_hdmi *intel_hdmi = intel_attached_hdmi(connector);
> -
> - hdmi_to_dig_port(intel_hdmi)->base.type = INTEL_OUTPUT_HDMI;
> + adap = intel_gmbus_get_adapter(dev_priv, intel_hdmi->ddc_bus);
> + if (drm_probe_ddc(adap))
> status = connector_status_connected;
> - } else
> + else
> status = connector_status_disconnected;
>
> intel_display_power_put(dev_priv, POWER_DOMAIN_GMBUS);
> -
> return status;
> }
>
> @@ -1442,10 +1423,42 @@ intel_hdmi_force(struct drm_connector *connector)
> hdmi_to_dig_port(intel_hdmi)->base.type = INTEL_OUTPUT_HDMI;
> }
>
> +static void intel_hdmi_detect_edid(struct drm_connector *connector)
> +{
> + struct intel_hdmi *intel_hdmi = intel_attached_hdmi(connector);
> + struct drm_i915_private *dev_priv = to_i915(connector->dev);
> + bool live_status = false;
> + unsigned int try;
> +
> + DRM_DEBUG_KMS("[CONNECTOR:%d:%s]\n",
> + connector->base.id, connector->name);
> +
> + intel_display_power_get(dev_priv, POWER_DOMAIN_GMBUS);
> +
> + for (try = 0; !live_status && try < 9; try++) {
> + if (try)
> + msleep(10);
> + live_status = intel_digital_port_connected(dev_priv,
> + hdmi_to_dig_port(intel_hdmi));
> + }
> +
> + if (!live_status)
> + DRM_DEBUG_KMS("Live status not up!");
> +
> + intel_hdmi_unset_edid(connector);
> + if (intel_hdmi_set_edid(connector, live_status))
> + hdmi_to_dig_port(intel_hdmi)->base.type = INTEL_OUTPUT_HDMI;
> +
> + intel_display_power_put(dev_priv, POWER_DOMAIN_GMBUS);
> +}
> +
> static int intel_hdmi_get_modes(struct drm_connector *connector)
> {
> struct edid *edid;
>
> + if (!to_intel_connector(connector)->detect_edid)
> + intel_hdmi_detect_edid(connector);
> +
> edid = to_intel_connector(connector)->detect_edid;
> if (edid == NULL)
> return 0;
> --
> 2.7.0
>
> _______________________________________________
> Intel-gfx mailing list
> Intel-gfx at lists.freedesktop.org
> https://lists.freedesktop.org/mailman/listinfo/intel-gfx
--
Daniel Vetter
Software Engineer, Intel Corporation
http://blog.ffwll.ch
More information about the Intel-gfx
mailing list