diff mbox

[3/4] drm/i915: Check live status before reading edid

Message ID 1440504093-19370-4-git-send-email-sonika.jindal@intel.com (mailing list archive)
State New, archived
Headers show

Commit Message

sonika.jindal@intel.com Aug. 25, 2015, 12:01 p.m. UTC
Adding this for SKL onwards.

v2: Adding checks for VLV/CHV as well. Reusing old ibx and g4x functions
to check digital port status. Adding a separate function to get bxt live
status (Daniel)
v3: Using intel_encoder->hpd_pin to check the live status (Siva)
Moving the live status read to intel_hdmi_probe and passing parameter
to read/not to read the edid. (me)

Signed-off-by: Sonika Jindal <sonika.jindal@intel.com>
---
 drivers/gpu/drm/i915/intel_dp.c   |    4 +--
 drivers/gpu/drm/i915/intel_drv.h  |    2 ++
 drivers/gpu/drm/i915/intel_hdmi.c |   62 ++++++++++++++++++++++++++++++++-----
 3 files changed, 58 insertions(+), 10 deletions(-)

Comments

Jani Nikula Aug. 25, 2015, 4:51 p.m. UTC | #1
On Tue, 25 Aug 2015, Sonika Jindal <sonika.jindal@intel.com> wrote:
> Adding this for SKL onwards.
>
> v2: Adding checks for VLV/CHV as well. Reusing old ibx and g4x functions
> to check digital port status. Adding a separate function to get bxt live
> status (Daniel)
> v3: Using intel_encoder->hpd_pin to check the live status (Siva)
> Moving the live status read to intel_hdmi_probe and passing parameter
> to read/not to read the edid. (me)

We may want to merge this cleanup first:
http://mid.gmane.org/cover.1440056461.git.jani.nikula@intel.com

BR,
Jani.



>
> Signed-off-by: Sonika Jindal <sonika.jindal@intel.com>
> ---
>  drivers/gpu/drm/i915/intel_dp.c   |    4 +--
>  drivers/gpu/drm/i915/intel_drv.h  |    2 ++
>  drivers/gpu/drm/i915/intel_hdmi.c |   62 ++++++++++++++++++++++++++++++++-----
>  3 files changed, 58 insertions(+), 10 deletions(-)
>
> diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c
> index b905c19..8f2eba2 100644
> --- a/drivers/gpu/drm/i915/intel_dp.c
> +++ b/drivers/gpu/drm/i915/intel_dp.c
> @@ -4477,8 +4477,8 @@ ironlake_dp_detect(struct intel_dp *intel_dp)
>  	return intel_dp_detect_dpcd(intel_dp);
>  }
>  
> -static int g4x_digital_port_connected(struct drm_device *dev,
> -				       struct intel_digital_port *intel_dig_port)
> +int g4x_digital_port_connected(struct drm_device *dev,
> +			       struct intel_digital_port *intel_dig_port)
>  {
>  	struct drm_i915_private *dev_priv = dev->dev_private;
>  	uint32_t bit;
> diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
> index 232b814..b07e141 100644
> --- a/drivers/gpu/drm/i915/intel_drv.h
> +++ b/drivers/gpu/drm/i915/intel_drv.h
> @@ -1192,6 +1192,8 @@ void intel_edp_drrs_disable(struct intel_dp *intel_dp);
>  void intel_edp_drrs_invalidate(struct drm_device *dev,
>  		unsigned frontbuffer_bits);
>  void intel_edp_drrs_flush(struct drm_device *dev, unsigned frontbuffer_bits);
> +int g4x_digital_port_connected(struct drm_device *dev,
> +			       struct intel_digital_port *intel_dig_port);
>  
>  /* intel_dp_mst.c */
>  int intel_dp_mst_encoder_init(struct intel_digital_port *intel_dig_port, int conn_id);
> diff --git a/drivers/gpu/drm/i915/intel_hdmi.c b/drivers/gpu/drm/i915/intel_hdmi.c
> index 68886c0..59518b4 100644
> --- a/drivers/gpu/drm/i915/intel_hdmi.c
> +++ b/drivers/gpu/drm/i915/intel_hdmi.c
> @@ -1328,23 +1328,63 @@ intel_hdmi_unset_edid(struct drm_connector *connector)
>  	to_intel_connector(connector)->detect_edid = NULL;
>  }
>  
> +static bool bxt_port_connected(struct drm_i915_private *dev_priv,
> +			       struct intel_digital_port *intel_dig_port)
> +{
> +	struct intel_encoder *intel_encoder = &intel_dig_port->base;
> +	enum port port;
> +	u32 temp = I915_READ(GEN8_DE_PORT_ISR);
> +
> +	intel_hpd_pin_to_port(intel_encoder->hpd_pin, &port);
> +	switch (port) {
> +	case PORT_A:
> +		return temp & BXT_DE_PORT_HP_DDIA;
> +
> +	case PORT_B:
> +		return temp & BXT_DE_PORT_HP_DDIB;
> +
> +	case PORT_C:
> +		return temp & BXT_DE_PORT_HP_DDIC;
> +
> +	default:
> +		return false;
> +
> +	}
> +}
> +
> +static bool intel_hdmi_live_status(struct intel_digital_port *intel_dig_port)
> +{
> +	struct drm_device *dev = intel_dig_port->base.base.dev;
> +	struct drm_i915_private *dev_priv = to_i915(dev);
> +
> +	if (IS_VALLEYVIEW(dev))
> +		return g4x_digital_port_connected(dev, intel_dig_port);
> +	else if (IS_SKYLAKE(dev) || IS_BROADWELL(dev))
> +		return ibx_digital_port_connected(dev_priv, intel_dig_port);
> +	else if (IS_BROXTON(dev))
> +		return bxt_port_connected(dev_priv, intel_dig_port);
> +
> +	return true;
> +}
> +
>  static bool
> -intel_hdmi_set_edid(struct drm_connector *connector)
> +intel_hdmi_set_edid(struct drm_connector *connector, bool force)
>  {
>  	struct drm_i915_private *dev_priv = to_i915(connector->dev);
>  	struct intel_hdmi *intel_hdmi = intel_attached_hdmi(connector);
>  	struct intel_encoder *intel_encoder =
>  		&hdmi_to_dig_port(intel_hdmi)->base;
>  	enum intel_display_power_domain power_domain;
> -	struct edid *edid;
> +	struct edid *edid = NULL;
>  	bool connected = false;
>  
>  	power_domain = intel_display_port_power_domain(intel_encoder);
>  	intel_display_power_get(dev_priv, power_domain);
>  
> -	edid = drm_get_edid(connector,
> -			    intel_gmbus_get_adapter(dev_priv,
> -						    intel_hdmi->ddc_bus));
> +	if (force)
> +		edid = drm_get_edid(connector,
> +				intel_gmbus_get_adapter(dev_priv,
> +					intel_hdmi->ddc_bus));
>  
>  	intel_display_power_put(dev_priv, power_domain);
>  
> @@ -1374,6 +1414,8 @@ void intel_hdmi_probe(struct intel_encoder *intel_encoder)
>  			enc_to_intel_hdmi(&intel_encoder->base);
>  	struct intel_connector *intel_connector =
>  				intel_hdmi->attached_connector;
> +	bool live_status = false;
> +
>  	/*
>  	 * Sometimes DDI ports are enumerated as DP as well as HDMI and
>  	 * detection is left for runtime. Since DP's detection method already
> @@ -1381,13 +1423,15 @@ void intel_hdmi_probe(struct intel_encoder *intel_encoder)
>  	 */
>  	if (intel_connector->base.connector_type != DRM_MODE_CONNECTOR_HDMIA)
>  		return;
> +
> +	live_status = intel_hdmi_live_status(hdmi_to_dig_port(intel_hdmi));
>  	/*
>  	 * We are here, means there is a hotplug or a force
>  	 * detection. Clear the cached EDID and probe the
>  	 * DDC bus to check the current status of HDMI.
>  	 */
>  	intel_hdmi_unset_edid(&intel_connector->base);
> -	if (intel_hdmi_set_edid(&intel_connector->base))
> +	if (intel_hdmi_set_edid(&intel_connector->base, live_status))
>  		DRM_DEBUG_DRIVER("DDC probe: got EDID\n");
>  	else
>  		DRM_DEBUG_DRIVER("DDC probe: no EDID\n");
> @@ -1442,7 +1486,7 @@ intel_hdmi_force(struct drm_connector *connector)
>  	if (connector->status != connector_status_connected)
>  		return;
>  
> -	intel_hdmi_set_edid(connector);
> +	intel_hdmi_set_edid(connector, true);
>  	hdmi_to_dig_port(intel_hdmi)->base.type = INTEL_OUTPUT_HDMI;
>  }
>  
> @@ -1996,6 +2040,7 @@ void intel_hdmi_init_connector(struct intel_digital_port *intel_dig_port,
>  	struct drm_device *dev = intel_encoder->base.dev;
>  	struct drm_i915_private *dev_priv = dev->dev_private;
>  	enum port port = intel_dig_port->port;
> +	bool live_status = false;
>  
>  	drm_connector_init(dev, connector, &intel_hdmi_connector_funcs,
>  			   DRM_MODE_CONNECTOR_HDMIA);
> @@ -2079,7 +2124,8 @@ void intel_hdmi_init_connector(struct intel_digital_port *intel_dig_port,
>  	intel_hdmi->attached_connector = intel_connector;
>  
>  	/* Set edid during init */
> -	intel_hdmi_set_edid(connector);
> +	live_status = intel_hdmi_live_status(intel_dig_port);
> +	intel_hdmi_set_edid(connector, live_status);
>  
>  	/* For G4X desktop chip, PEG_BAND_GAP_DATA 3:0 must first be written
>  	 * 0xd.  Failure to do so will result in spurious interrupts being
> -- 
> 1.7.10.4
>
> _______________________________________________
> Intel-gfx mailing list
> Intel-gfx@lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/intel-gfx
Hindman, Gavin Aug. 26, 2015, 4:36 a.m. UTC | #2
Jani - do you believe that this series will need to be reworked following merge of your cleanup series?   We've got some outstanding CHV hot-plug issues that Sonika's series should fix, so we need to get it in, but should definitely take the path towards longer-term quality.

Gavin Hindman
Senior Program Manager
SSG/OTC – Open Source Technology Center


-----Original Message-----
From: Intel-gfx [mailto:intel-gfx-bounces@lists.freedesktop.org] On Behalf Of Jani Nikula

Sent: Tuesday, August 25, 2015 9:52 AM
To: Jindal, Sonika; intel-gfx@lists.freedesktop.org
Subject: Re: [Intel-gfx] [PATCH 3/4] drm/i915: Check live status before reading edid

On Tue, 25 Aug 2015, Sonika Jindal <sonika.jindal@intel.com> wrote:
> Adding this for SKL onwards.

>

> v2: Adding checks for VLV/CHV as well. Reusing old ibx and g4x 

> functions to check digital port status. Adding a separate function to 

> get bxt live status (Daniel)

> v3: Using intel_encoder->hpd_pin to check the live status (Siva) 

> Moving the live status read to intel_hdmi_probe and passing parameter 

> to read/not to read the edid. (me)


We may want to merge this cleanup first:
http://mid.gmane.org/cover.1440056461.git.jani.nikula@intel.com

BR,
Jani.



>

> Signed-off-by: Sonika Jindal <sonika.jindal@intel.com>

> ---

>  drivers/gpu/drm/i915/intel_dp.c   |    4 +--

>  drivers/gpu/drm/i915/intel_drv.h  |    2 ++

>  drivers/gpu/drm/i915/intel_hdmi.c |   62 ++++++++++++++++++++++++++++++++-----

>  3 files changed, 58 insertions(+), 10 deletions(-)

>

> diff --git a/drivers/gpu/drm/i915/intel_dp.c 

> b/drivers/gpu/drm/i915/intel_dp.c index b905c19..8f2eba2 100644

> --- a/drivers/gpu/drm/i915/intel_dp.c

> +++ b/drivers/gpu/drm/i915/intel_dp.c

> @@ -4477,8 +4477,8 @@ ironlake_dp_detect(struct intel_dp *intel_dp)

>  	return intel_dp_detect_dpcd(intel_dp);  }

>  

> -static int g4x_digital_port_connected(struct drm_device *dev,

> -				       struct intel_digital_port *intel_dig_port)

> +int g4x_digital_port_connected(struct drm_device *dev,

> +			       struct intel_digital_port *intel_dig_port)

>  {

>  	struct drm_i915_private *dev_priv = dev->dev_private;

>  	uint32_t bit;

> diff --git a/drivers/gpu/drm/i915/intel_drv.h 

> b/drivers/gpu/drm/i915/intel_drv.h

> index 232b814..b07e141 100644

> --- a/drivers/gpu/drm/i915/intel_drv.h

> +++ b/drivers/gpu/drm/i915/intel_drv.h

> @@ -1192,6 +1192,8 @@ void intel_edp_drrs_disable(struct intel_dp 

> *intel_dp);  void intel_edp_drrs_invalidate(struct drm_device *dev,

>  		unsigned frontbuffer_bits);

>  void intel_edp_drrs_flush(struct drm_device *dev, unsigned 

> frontbuffer_bits);

> +int g4x_digital_port_connected(struct drm_device *dev,

> +			       struct intel_digital_port *intel_dig_port);

>  

>  /* intel_dp_mst.c */

>  int intel_dp_mst_encoder_init(struct intel_digital_port 

> *intel_dig_port, int conn_id); diff --git 

> a/drivers/gpu/drm/i915/intel_hdmi.c 

> b/drivers/gpu/drm/i915/intel_hdmi.c

> index 68886c0..59518b4 100644

> --- a/drivers/gpu/drm/i915/intel_hdmi.c

> +++ b/drivers/gpu/drm/i915/intel_hdmi.c

> @@ -1328,23 +1328,63 @@ intel_hdmi_unset_edid(struct drm_connector *connector)

>  	to_intel_connector(connector)->detect_edid = NULL;  }

>  

> +static bool bxt_port_connected(struct drm_i915_private *dev_priv,

> +			       struct intel_digital_port *intel_dig_port) {

> +	struct intel_encoder *intel_encoder = &intel_dig_port->base;

> +	enum port port;

> +	u32 temp = I915_READ(GEN8_DE_PORT_ISR);

> +

> +	intel_hpd_pin_to_port(intel_encoder->hpd_pin, &port);

> +	switch (port) {

> +	case PORT_A:

> +		return temp & BXT_DE_PORT_HP_DDIA;

> +

> +	case PORT_B:

> +		return temp & BXT_DE_PORT_HP_DDIB;

> +

> +	case PORT_C:

> +		return temp & BXT_DE_PORT_HP_DDIC;

> +

> +	default:

> +		return false;

> +

> +	}

> +}

> +

> +static bool intel_hdmi_live_status(struct intel_digital_port 

> +*intel_dig_port) {

> +	struct drm_device *dev = intel_dig_port->base.base.dev;

> +	struct drm_i915_private *dev_priv = to_i915(dev);

> +

> +	if (IS_VALLEYVIEW(dev))

> +		return g4x_digital_port_connected(dev, intel_dig_port);

> +	else if (IS_SKYLAKE(dev) || IS_BROADWELL(dev))

> +		return ibx_digital_port_connected(dev_priv, intel_dig_port);

> +	else if (IS_BROXTON(dev))

> +		return bxt_port_connected(dev_priv, intel_dig_port);

> +

> +	return true;

> +}

> +

>  static bool

> -intel_hdmi_set_edid(struct drm_connector *connector)

> +intel_hdmi_set_edid(struct drm_connector *connector, bool force)

>  {

>  	struct drm_i915_private *dev_priv = to_i915(connector->dev);

>  	struct intel_hdmi *intel_hdmi = intel_attached_hdmi(connector);

>  	struct intel_encoder *intel_encoder =

>  		&hdmi_to_dig_port(intel_hdmi)->base;

>  	enum intel_display_power_domain power_domain;

> -	struct edid *edid;

> +	struct edid *edid = NULL;

>  	bool connected = false;

>  

>  	power_domain = intel_display_port_power_domain(intel_encoder);

>  	intel_display_power_get(dev_priv, power_domain);

>  

> -	edid = drm_get_edid(connector,

> -			    intel_gmbus_get_adapter(dev_priv,

> -						    intel_hdmi->ddc_bus));

> +	if (force)

> +		edid = drm_get_edid(connector,

> +				intel_gmbus_get_adapter(dev_priv,

> +					intel_hdmi->ddc_bus));

>  

>  	intel_display_power_put(dev_priv, power_domain);

>  

> @@ -1374,6 +1414,8 @@ void intel_hdmi_probe(struct intel_encoder *intel_encoder)

>  			enc_to_intel_hdmi(&intel_encoder->base);

>  	struct intel_connector *intel_connector =

>  				intel_hdmi->attached_connector;

> +	bool live_status = false;

> +

>  	/*

>  	 * Sometimes DDI ports are enumerated as DP as well as HDMI and

>  	 * detection is left for runtime. Since DP's detection method 

> already @@ -1381,13 +1423,15 @@ void intel_hdmi_probe(struct intel_encoder *intel_encoder)

>  	 */

>  	if (intel_connector->base.connector_type != DRM_MODE_CONNECTOR_HDMIA)

>  		return;

> +

> +	live_status = intel_hdmi_live_status(hdmi_to_dig_port(intel_hdmi));

>  	/*

>  	 * We are here, means there is a hotplug or a force

>  	 * detection. Clear the cached EDID and probe the

>  	 * DDC bus to check the current status of HDMI.

>  	 */

>  	intel_hdmi_unset_edid(&intel_connector->base);

> -	if (intel_hdmi_set_edid(&intel_connector->base))

> +	if (intel_hdmi_set_edid(&intel_connector->base, live_status))

>  		DRM_DEBUG_DRIVER("DDC probe: got EDID\n");

>  	else

>  		DRM_DEBUG_DRIVER("DDC probe: no EDID\n"); @@ -1442,7 +1486,7 @@ 

> intel_hdmi_force(struct drm_connector *connector)

>  	if (connector->status != connector_status_connected)

>  		return;

>  

> -	intel_hdmi_set_edid(connector);

> +	intel_hdmi_set_edid(connector, true);

>  	hdmi_to_dig_port(intel_hdmi)->base.type = INTEL_OUTPUT_HDMI;  }

>  

> @@ -1996,6 +2040,7 @@ void intel_hdmi_init_connector(struct intel_digital_port *intel_dig_port,

>  	struct drm_device *dev = intel_encoder->base.dev;

>  	struct drm_i915_private *dev_priv = dev->dev_private;

>  	enum port port = intel_dig_port->port;

> +	bool live_status = false;

>  

>  	drm_connector_init(dev, connector, &intel_hdmi_connector_funcs,

>  			   DRM_MODE_CONNECTOR_HDMIA);

> @@ -2079,7 +2124,8 @@ void intel_hdmi_init_connector(struct intel_digital_port *intel_dig_port,

>  	intel_hdmi->attached_connector = intel_connector;

>  

>  	/* Set edid during init */

> -	intel_hdmi_set_edid(connector);

> +	live_status = intel_hdmi_live_status(intel_dig_port);

> +	intel_hdmi_set_edid(connector, live_status);

>  

>  	/* For G4X desktop chip, PEG_BAND_GAP_DATA 3:0 must first be written

>  	 * 0xd.  Failure to do so will result in spurious interrupts being

> --

> 1.7.10.4

>

> _______________________________________________

> Intel-gfx mailing list

> Intel-gfx@lists.freedesktop.org

> http://lists.freedesktop.org/mailman/listinfo/intel-gfx


--
Jani Nikula, Intel Open Source Technology Center _______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx
Jani Nikula Aug. 26, 2015, 6:36 a.m. UTC | #3
The cleanup series has already been reviewed, this one hasn't. The
cleanup series should actually make patch 3/4 simpler to
review. Otherwise there really isn't conflict.

BR,
Jani.


On Wed, 26 Aug 2015, "Hindman, Gavin" <gavin.hindman@intel.com> wrote:
> Jani - do you believe that this series will need to be reworked following merge of your cleanup series?   We've got some outstanding CHV hot-plug issues that Sonika's series should fix, so we need to get it in, but should definitely take the path towards longer-term quality.
>
> Gavin Hindman
> Senior Program Manager
> SSG/OTC – Open Source Technology Center
>
>
> -----Original Message-----
> From: Intel-gfx [mailto:intel-gfx-bounces@lists.freedesktop.org] On Behalf Of Jani Nikula
> Sent: Tuesday, August 25, 2015 9:52 AM
> To: Jindal, Sonika; intel-gfx@lists.freedesktop.org
> Subject: Re: [Intel-gfx] [PATCH 3/4] drm/i915: Check live status before reading edid
>
> On Tue, 25 Aug 2015, Sonika Jindal <sonika.jindal@intel.com> wrote:
>> Adding this for SKL onwards.
>>
>> v2: Adding checks for VLV/CHV as well. Reusing old ibx and g4x 
>> functions to check digital port status. Adding a separate function to 
>> get bxt live status (Daniel)
>> v3: Using intel_encoder->hpd_pin to check the live status (Siva) 
>> Moving the live status read to intel_hdmi_probe and passing parameter 
>> to read/not to read the edid. (me)
>
> We may want to merge this cleanup first:
> http://mid.gmane.org/cover.1440056461.git.jani.nikula@intel.com
>
> BR,
> Jani.
>
>
>
>>
>> Signed-off-by: Sonika Jindal <sonika.jindal@intel.com>
>> ---
>>  drivers/gpu/drm/i915/intel_dp.c   |    4 +--
>>  drivers/gpu/drm/i915/intel_drv.h  |    2 ++
>>  drivers/gpu/drm/i915/intel_hdmi.c |   62 ++++++++++++++++++++++++++++++++-----
>>  3 files changed, 58 insertions(+), 10 deletions(-)
>>
>> diff --git a/drivers/gpu/drm/i915/intel_dp.c 
>> b/drivers/gpu/drm/i915/intel_dp.c index b905c19..8f2eba2 100644
>> --- a/drivers/gpu/drm/i915/intel_dp.c
>> +++ b/drivers/gpu/drm/i915/intel_dp.c
>> @@ -4477,8 +4477,8 @@ ironlake_dp_detect(struct intel_dp *intel_dp)
>>  	return intel_dp_detect_dpcd(intel_dp);  }
>>  
>> -static int g4x_digital_port_connected(struct drm_device *dev,
>> -				       struct intel_digital_port *intel_dig_port)
>> +int g4x_digital_port_connected(struct drm_device *dev,
>> +			       struct intel_digital_port *intel_dig_port)
>>  {
>>  	struct drm_i915_private *dev_priv = dev->dev_private;
>>  	uint32_t bit;
>> diff --git a/drivers/gpu/drm/i915/intel_drv.h 
>> b/drivers/gpu/drm/i915/intel_drv.h
>> index 232b814..b07e141 100644
>> --- a/drivers/gpu/drm/i915/intel_drv.h
>> +++ b/drivers/gpu/drm/i915/intel_drv.h
>> @@ -1192,6 +1192,8 @@ void intel_edp_drrs_disable(struct intel_dp 
>> *intel_dp);  void intel_edp_drrs_invalidate(struct drm_device *dev,
>>  		unsigned frontbuffer_bits);
>>  void intel_edp_drrs_flush(struct drm_device *dev, unsigned 
>> frontbuffer_bits);
>> +int g4x_digital_port_connected(struct drm_device *dev,
>> +			       struct intel_digital_port *intel_dig_port);
>>  
>>  /* intel_dp_mst.c */
>>  int intel_dp_mst_encoder_init(struct intel_digital_port 
>> *intel_dig_port, int conn_id); diff --git 
>> a/drivers/gpu/drm/i915/intel_hdmi.c 
>> b/drivers/gpu/drm/i915/intel_hdmi.c
>> index 68886c0..59518b4 100644
>> --- a/drivers/gpu/drm/i915/intel_hdmi.c
>> +++ b/drivers/gpu/drm/i915/intel_hdmi.c
>> @@ -1328,23 +1328,63 @@ intel_hdmi_unset_edid(struct drm_connector *connector)
>>  	to_intel_connector(connector)->detect_edid = NULL;  }
>>  
>> +static bool bxt_port_connected(struct drm_i915_private *dev_priv,
>> +			       struct intel_digital_port *intel_dig_port) {
>> +	struct intel_encoder *intel_encoder = &intel_dig_port->base;
>> +	enum port port;
>> +	u32 temp = I915_READ(GEN8_DE_PORT_ISR);
>> +
>> +	intel_hpd_pin_to_port(intel_encoder->hpd_pin, &port);
>> +	switch (port) {
>> +	case PORT_A:
>> +		return temp & BXT_DE_PORT_HP_DDIA;
>> +
>> +	case PORT_B:
>> +		return temp & BXT_DE_PORT_HP_DDIB;
>> +
>> +	case PORT_C:
>> +		return temp & BXT_DE_PORT_HP_DDIC;
>> +
>> +	default:
>> +		return false;
>> +
>> +	}
>> +}
>> +
>> +static bool intel_hdmi_live_status(struct intel_digital_port 
>> +*intel_dig_port) {
>> +	struct drm_device *dev = intel_dig_port->base.base.dev;
>> +	struct drm_i915_private *dev_priv = to_i915(dev);
>> +
>> +	if (IS_VALLEYVIEW(dev))
>> +		return g4x_digital_port_connected(dev, intel_dig_port);
>> +	else if (IS_SKYLAKE(dev) || IS_BROADWELL(dev))
>> +		return ibx_digital_port_connected(dev_priv, intel_dig_port);
>> +	else if (IS_BROXTON(dev))
>> +		return bxt_port_connected(dev_priv, intel_dig_port);
>> +
>> +	return true;
>> +}
>> +
>>  static bool
>> -intel_hdmi_set_edid(struct drm_connector *connector)
>> +intel_hdmi_set_edid(struct drm_connector *connector, bool force)
>>  {
>>  	struct drm_i915_private *dev_priv = to_i915(connector->dev);
>>  	struct intel_hdmi *intel_hdmi = intel_attached_hdmi(connector);
>>  	struct intel_encoder *intel_encoder =
>>  		&hdmi_to_dig_port(intel_hdmi)->base;
>>  	enum intel_display_power_domain power_domain;
>> -	struct edid *edid;
>> +	struct edid *edid = NULL;
>>  	bool connected = false;
>>  
>>  	power_domain = intel_display_port_power_domain(intel_encoder);
>>  	intel_display_power_get(dev_priv, power_domain);
>>  
>> -	edid = drm_get_edid(connector,
>> -			    intel_gmbus_get_adapter(dev_priv,
>> -						    intel_hdmi->ddc_bus));
>> +	if (force)
>> +		edid = drm_get_edid(connector,
>> +				intel_gmbus_get_adapter(dev_priv,
>> +					intel_hdmi->ddc_bus));
>>  
>>  	intel_display_power_put(dev_priv, power_domain);
>>  
>> @@ -1374,6 +1414,8 @@ void intel_hdmi_probe(struct intel_encoder *intel_encoder)
>>  			enc_to_intel_hdmi(&intel_encoder->base);
>>  	struct intel_connector *intel_connector =
>>  				intel_hdmi->attached_connector;
>> +	bool live_status = false;
>> +
>>  	/*
>>  	 * Sometimes DDI ports are enumerated as DP as well as HDMI and
>>  	 * detection is left for runtime. Since DP's detection method 
>> already @@ -1381,13 +1423,15 @@ void intel_hdmi_probe(struct intel_encoder *intel_encoder)
>>  	 */
>>  	if (intel_connector->base.connector_type != DRM_MODE_CONNECTOR_HDMIA)
>>  		return;
>> +
>> +	live_status = intel_hdmi_live_status(hdmi_to_dig_port(intel_hdmi));
>>  	/*
>>  	 * We are here, means there is a hotplug or a force
>>  	 * detection. Clear the cached EDID and probe the
>>  	 * DDC bus to check the current status of HDMI.
>>  	 */
>>  	intel_hdmi_unset_edid(&intel_connector->base);
>> -	if (intel_hdmi_set_edid(&intel_connector->base))
>> +	if (intel_hdmi_set_edid(&intel_connector->base, live_status))
>>  		DRM_DEBUG_DRIVER("DDC probe: got EDID\n");
>>  	else
>>  		DRM_DEBUG_DRIVER("DDC probe: no EDID\n"); @@ -1442,7 +1486,7 @@ 
>> intel_hdmi_force(struct drm_connector *connector)
>>  	if (connector->status != connector_status_connected)
>>  		return;
>>  
>> -	intel_hdmi_set_edid(connector);
>> +	intel_hdmi_set_edid(connector, true);
>>  	hdmi_to_dig_port(intel_hdmi)->base.type = INTEL_OUTPUT_HDMI;  }
>>  
>> @@ -1996,6 +2040,7 @@ void intel_hdmi_init_connector(struct intel_digital_port *intel_dig_port,
>>  	struct drm_device *dev = intel_encoder->base.dev;
>>  	struct drm_i915_private *dev_priv = dev->dev_private;
>>  	enum port port = intel_dig_port->port;
>> +	bool live_status = false;
>>  
>>  	drm_connector_init(dev, connector, &intel_hdmi_connector_funcs,
>>  			   DRM_MODE_CONNECTOR_HDMIA);
>> @@ -2079,7 +2124,8 @@ void intel_hdmi_init_connector(struct intel_digital_port *intel_dig_port,
>>  	intel_hdmi->attached_connector = intel_connector;
>>  
>>  	/* Set edid during init */
>> -	intel_hdmi_set_edid(connector);
>> +	live_status = intel_hdmi_live_status(intel_dig_port);
>> +	intel_hdmi_set_edid(connector, live_status);
>>  
>>  	/* For G4X desktop chip, PEG_BAND_GAP_DATA 3:0 must first be written
>>  	 * 0xd.  Failure to do so will result in spurious interrupts being
>> --
>> 1.7.10.4
>>
>> _______________________________________________
>> Intel-gfx mailing list
>> Intel-gfx@lists.freedesktop.org
>> http://lists.freedesktop.org/mailman/listinfo/intel-gfx
>
> --
> Jani Nikula, Intel Open Source Technology Center _______________________________________________
> Intel-gfx mailing list
> Intel-gfx@lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/intel-gfx
diff mbox

Patch

diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c
index b905c19..8f2eba2 100644
--- a/drivers/gpu/drm/i915/intel_dp.c
+++ b/drivers/gpu/drm/i915/intel_dp.c
@@ -4477,8 +4477,8 @@  ironlake_dp_detect(struct intel_dp *intel_dp)
 	return intel_dp_detect_dpcd(intel_dp);
 }
 
-static int g4x_digital_port_connected(struct drm_device *dev,
-				       struct intel_digital_port *intel_dig_port)
+int g4x_digital_port_connected(struct drm_device *dev,
+			       struct intel_digital_port *intel_dig_port)
 {
 	struct drm_i915_private *dev_priv = dev->dev_private;
 	uint32_t bit;
diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
index 232b814..b07e141 100644
--- a/drivers/gpu/drm/i915/intel_drv.h
+++ b/drivers/gpu/drm/i915/intel_drv.h
@@ -1192,6 +1192,8 @@  void intel_edp_drrs_disable(struct intel_dp *intel_dp);
 void intel_edp_drrs_invalidate(struct drm_device *dev,
 		unsigned frontbuffer_bits);
 void intel_edp_drrs_flush(struct drm_device *dev, unsigned frontbuffer_bits);
+int g4x_digital_port_connected(struct drm_device *dev,
+			       struct intel_digital_port *intel_dig_port);
 
 /* intel_dp_mst.c */
 int intel_dp_mst_encoder_init(struct intel_digital_port *intel_dig_port, int conn_id);
diff --git a/drivers/gpu/drm/i915/intel_hdmi.c b/drivers/gpu/drm/i915/intel_hdmi.c
index 68886c0..59518b4 100644
--- a/drivers/gpu/drm/i915/intel_hdmi.c
+++ b/drivers/gpu/drm/i915/intel_hdmi.c
@@ -1328,23 +1328,63 @@  intel_hdmi_unset_edid(struct drm_connector *connector)
 	to_intel_connector(connector)->detect_edid = NULL;
 }
 
+static bool bxt_port_connected(struct drm_i915_private *dev_priv,
+			       struct intel_digital_port *intel_dig_port)
+{
+	struct intel_encoder *intel_encoder = &intel_dig_port->base;
+	enum port port;
+	u32 temp = I915_READ(GEN8_DE_PORT_ISR);
+
+	intel_hpd_pin_to_port(intel_encoder->hpd_pin, &port);
+	switch (port) {
+	case PORT_A:
+		return temp & BXT_DE_PORT_HP_DDIA;
+
+	case PORT_B:
+		return temp & BXT_DE_PORT_HP_DDIB;
+
+	case PORT_C:
+		return temp & BXT_DE_PORT_HP_DDIC;
+
+	default:
+		return false;
+
+	}
+}
+
+static bool intel_hdmi_live_status(struct intel_digital_port *intel_dig_port)
+{
+	struct drm_device *dev = intel_dig_port->base.base.dev;
+	struct drm_i915_private *dev_priv = to_i915(dev);
+
+	if (IS_VALLEYVIEW(dev))
+		return g4x_digital_port_connected(dev, intel_dig_port);
+	else if (IS_SKYLAKE(dev) || IS_BROADWELL(dev))
+		return ibx_digital_port_connected(dev_priv, intel_dig_port);
+	else if (IS_BROXTON(dev))
+		return bxt_port_connected(dev_priv, intel_dig_port);
+
+	return true;
+}
+
 static bool
-intel_hdmi_set_edid(struct drm_connector *connector)
+intel_hdmi_set_edid(struct drm_connector *connector, bool force)
 {
 	struct drm_i915_private *dev_priv = to_i915(connector->dev);
 	struct intel_hdmi *intel_hdmi = intel_attached_hdmi(connector);
 	struct intel_encoder *intel_encoder =
 		&hdmi_to_dig_port(intel_hdmi)->base;
 	enum intel_display_power_domain power_domain;
-	struct edid *edid;
+	struct edid *edid = NULL;
 	bool connected = false;
 
 	power_domain = intel_display_port_power_domain(intel_encoder);
 	intel_display_power_get(dev_priv, power_domain);
 
-	edid = drm_get_edid(connector,
-			    intel_gmbus_get_adapter(dev_priv,
-						    intel_hdmi->ddc_bus));
+	if (force)
+		edid = drm_get_edid(connector,
+				intel_gmbus_get_adapter(dev_priv,
+					intel_hdmi->ddc_bus));
 
 	intel_display_power_put(dev_priv, power_domain);
 
@@ -1374,6 +1414,8 @@  void intel_hdmi_probe(struct intel_encoder *intel_encoder)
 			enc_to_intel_hdmi(&intel_encoder->base);
 	struct intel_connector *intel_connector =
 				intel_hdmi->attached_connector;
+	bool live_status = false;
+
 	/*
 	 * Sometimes DDI ports are enumerated as DP as well as HDMI and
 	 * detection is left for runtime. Since DP's detection method already
@@ -1381,13 +1423,15 @@  void intel_hdmi_probe(struct intel_encoder *intel_encoder)
 	 */
 	if (intel_connector->base.connector_type != DRM_MODE_CONNECTOR_HDMIA)
 		return;
+
+	live_status = intel_hdmi_live_status(hdmi_to_dig_port(intel_hdmi));
 	/*
 	 * We are here, means there is a hotplug or a force
 	 * detection. Clear the cached EDID and probe the
 	 * DDC bus to check the current status of HDMI.
 	 */
 	intel_hdmi_unset_edid(&intel_connector->base);
-	if (intel_hdmi_set_edid(&intel_connector->base))
+	if (intel_hdmi_set_edid(&intel_connector->base, live_status))
 		DRM_DEBUG_DRIVER("DDC probe: got EDID\n");
 	else
 		DRM_DEBUG_DRIVER("DDC probe: no EDID\n");
@@ -1442,7 +1486,7 @@  intel_hdmi_force(struct drm_connector *connector)
 	if (connector->status != connector_status_connected)
 		return;
 
-	intel_hdmi_set_edid(connector);
+	intel_hdmi_set_edid(connector, true);
 	hdmi_to_dig_port(intel_hdmi)->base.type = INTEL_OUTPUT_HDMI;
 }
 
@@ -1996,6 +2040,7 @@  void intel_hdmi_init_connector(struct intel_digital_port *intel_dig_port,
 	struct drm_device *dev = intel_encoder->base.dev;
 	struct drm_i915_private *dev_priv = dev->dev_private;
 	enum port port = intel_dig_port->port;
+	bool live_status = false;
 
 	drm_connector_init(dev, connector, &intel_hdmi_connector_funcs,
 			   DRM_MODE_CONNECTOR_HDMIA);
@@ -2079,7 +2124,8 @@  void intel_hdmi_init_connector(struct intel_digital_port *intel_dig_port,
 	intel_hdmi->attached_connector = intel_connector;
 
 	/* Set edid during init */
-	intel_hdmi_set_edid(connector);
+	live_status = intel_hdmi_live_status(intel_dig_port);
+	intel_hdmi_set_edid(connector, live_status);
 
 	/* For G4X desktop chip, PEG_BAND_GAP_DATA 3:0 must first be written
 	 * 0xd.  Failure to do so will result in spurious interrupts being