[PATCH 2/6] drm/i915/hdmi: Read the HPD status before trying to read the EDID

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On Thu, 13 Dec 2012, Damien Lespiau <damien.lespiau at gmail.com> wrote:
> From: Damien Lespiau <damien.lespiau at intel.com>
>
> If you unplug the hdmi connector slowly enough, the hotplug interrupt
> fires but then the kernel code tries to read the EDID and succeeds
> (because the connector is still half connected, the HPD pin is shorter
> than the others, and DDC works). Since EDID succeeds it thinks the
> monitor is still connected.
>
> To prevent that, read the live HPD status in the hotplug handler before
> trying to read the EDID.
>
> v2: Rename the function to ibx_ (Chris Wilson)

The name's a bit funny in the intermediate step because the patch
doesn't really do anything for IBX before patch 5/6... :) I don't mind,
just an observation, and perhaps Daniel will fold the two together once
we get tested-by on ILK+IBX.

Reviewed-by: Jani Nikula <jani.nikula at intel.com>


>
> Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=55372
> Signed-off-by: Damien Lespiau <damien.lespiau at intel.com>
> ---
>  drivers/gpu/drm/i915/intel_display.c | 33 +++++++++++++++++++++++++++++++++
>  drivers/gpu/drm/i915/intel_drv.h     |  3 +++
>  drivers/gpu/drm/i915/intel_hdmi.c    |  9 +++++++--
>  3 files changed, 43 insertions(+), 2 deletions(-)
>
> diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
> index 115bf62..21fedf7 100644
> --- a/drivers/gpu/drm/i915/intel_display.c
> +++ b/drivers/gpu/drm/i915/intel_display.c
> @@ -994,6 +994,39 @@ void intel_wait_for_pipe_off(struct drm_device *dev, int pipe)
>  	}
>  }
>  
> +/*
> + * ibx_digital_port_connected - is the specified port connected?
> + * @dev_priv: i915 private structure
> + * @port: the port to test
> + *
> + * Returns true if @port is connected, false otherwise.
> + */
> +bool ibx_digital_port_connected(struct drm_i915_private *dev_priv,
> +				struct intel_digital_port *port)
> +{
> +	u32 bit;
> +
> +	/* XXX: IBX has different SDEISR bits */
> +	if (HAS_PCH_IBX(dev_priv->dev))
> +		return true;
> +
> +	switch(port->port) {
> +	case PORT_B:
> +		bit = SDE_PORTB_HOTPLUG_CPT;
> +		break;
> +	case PORT_C:
> +		bit = SDE_PORTC_HOTPLUG_CPT;
> +		break;
> +	case PORT_D:
> +		bit = SDE_PORTD_HOTPLUG_CPT;
> +		break;
> +	default:
> +		return true;
> +	}
> +
> +	return I915_READ(SDEISR) & bit;
> +}
> +
>  static const char *state_string(bool enabled)
>  {
>  	return enabled ? "on" : "off";
> diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
> index 22728f2..53d4c8f 100644
> --- a/drivers/gpu/drm/i915/intel_drv.h
> +++ b/drivers/gpu/drm/i915/intel_drv.h
> @@ -545,6 +545,9 @@ hdmi_to_dig_port(struct intel_hdmi *intel_hdmi)
>  	return container_of(intel_hdmi, struct intel_digital_port, hdmi);
>  }
>  
> +bool ibx_digital_port_connected(struct drm_i915_private *dev_priv,
> +				struct intel_digital_port *port);
> +
>  extern void intel_connector_attach_encoder(struct intel_connector *connector,
>  					   struct intel_encoder *encoder);
>  extern struct drm_encoder *intel_best_encoder(struct drm_connector *connector);
> diff --git a/drivers/gpu/drm/i915/intel_hdmi.c b/drivers/gpu/drm/i915/intel_hdmi.c
> index 53df0a8..9f834d3 100644
> --- a/drivers/gpu/drm/i915/intel_hdmi.c
> +++ b/drivers/gpu/drm/i915/intel_hdmi.c
> @@ -793,16 +793,21 @@ static bool g4x_hdmi_connected(struct intel_hdmi *intel_hdmi)
>  static enum drm_connector_status
>  intel_hdmi_detect(struct drm_connector *connector, bool force)
>  {
> +	struct drm_device *dev = connector->dev;
>  	struct intel_hdmi *intel_hdmi = intel_attached_hdmi(connector);
>  	struct intel_digital_port *intel_dig_port =
>  		hdmi_to_dig_port(intel_hdmi);
>  	struct intel_encoder *intel_encoder = &intel_dig_port->base;
> -	struct drm_i915_private *dev_priv = connector->dev->dev_private;
> +	struct drm_i915_private *dev_priv = dev->dev_private;
>  	struct edid *edid;
>  	enum drm_connector_status status = connector_status_disconnected;
>  
> -	if (IS_G4X(connector->dev) && !g4x_hdmi_connected(intel_hdmi))
> +
> +	if (IS_G4X(dev) && !g4x_hdmi_connected(intel_hdmi))
>  		return status;
> +	else if (HAS_PCH_SPLIT(dev) &&
> +		 !ibx_digital_port_connected(dev_priv, intel_dig_port))
> +		 return status;
>  
>  	intel_hdmi->has_hdmi_sink = false;
>  	intel_hdmi->has_audio = false;
> -- 
> 1.7.11.7
>
> _______________________________________________
> Intel-gfx mailing list
> Intel-gfx at lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/intel-gfx


[Index of Archives]     [Linux USB Devel]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]
  Powered by Linux