diff mbox

[17/21] drm/omap: Move HPD disconnection handling to omap_connector

Message ID 20180606093650.26034-18-laurent.pinchart@ideasonboard.com (mailing list archive)
State New, archived
Headers show

Commit Message

Laurent Pinchart June 6, 2018, 9:36 a.m. UTC
On HDMI outputs, CEC support requires notification of HPD signal
deassertion. The HPD signal can be handled by various omap_dss_device
instances in the pipeline, and all of them forward HPD events to the
OMAP4 internal HDMI encoder.

Knowledge of the DSS internals need to be removed from the
omap_dss_device instances in order to migrate to drm_bridge. To do so,
move HPD handling for CEC to the omap_connector.

Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
---
 drivers/gpu/drm/omapdrm/displays/connector-hdmi.c  |  7 +----
 .../gpu/drm/omapdrm/displays/encoder-tpd12s015.c   |  7 +----
 drivers/gpu/drm/omapdrm/omap_connector.c           | 33 ++++++++++++++++++----
 3 files changed, 29 insertions(+), 18 deletions(-)

Comments

Sebastian Reichel June 11, 2018, 10:33 p.m. UTC | #1
Hi,

On Wed, Jun 06, 2018 at 12:36:46PM +0300, Laurent Pinchart wrote:
> On HDMI outputs, CEC support requires notification of HPD signal
> deassertion. The HPD signal can be handled by various omap_dss_device
> instances in the pipeline, and all of them forward HPD events to the
> OMAP4 internal HDMI encoder.
> 
> Knowledge of the DSS internals need to be removed from the
> omap_dss_device instances in order to migrate to drm_bridge. To do so,
> move HPD handling for CEC to the omap_connector.
> 
> Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
> ---

Reviewed-by: Sebastian Reichel <sebastian.reichel@collabora.co.uk>

-- Sebastian

>  drivers/gpu/drm/omapdrm/displays/connector-hdmi.c  |  7 +----
>  .../gpu/drm/omapdrm/displays/encoder-tpd12s015.c   |  7 +----
>  drivers/gpu/drm/omapdrm/omap_connector.c           | 33 ++++++++++++++++++----
>  3 files changed, 29 insertions(+), 18 deletions(-)
> 
> diff --git a/drivers/gpu/drm/omapdrm/displays/connector-hdmi.c b/drivers/gpu/drm/omapdrm/displays/connector-hdmi.c
> index 84cc68388940..6f2364afb14a 100644
> --- a/drivers/gpu/drm/omapdrm/displays/connector-hdmi.c
> +++ b/drivers/gpu/drm/omapdrm/displays/connector-hdmi.c
> @@ -137,13 +137,8 @@ static int hdmic_read_edid(struct omap_dss_device *dssdev,
>  static bool hdmic_detect(struct omap_dss_device *dssdev)
>  {
>  	struct panel_drv_data *ddata = to_panel_data(dssdev);
> -	struct omap_dss_device *src = dssdev->src;
> -	bool connected;
>  
> -	connected = gpiod_get_value_cansleep(ddata->hpd_gpio);
> -	if (!connected && src->ops->hdmi.lost_hotplug)
> -		src->ops->hdmi.lost_hotplug(src);
> -	return connected;
> +	return gpiod_get_value_cansleep(ddata->hpd_gpio);
>  }
>  
>  static void hdmic_register_hpd_cb(struct omap_dss_device *dssdev,
> diff --git a/drivers/gpu/drm/omapdrm/displays/encoder-tpd12s015.c b/drivers/gpu/drm/omapdrm/displays/encoder-tpd12s015.c
> index 1fa1d332dbc4..2772af84531a 100644
> --- a/drivers/gpu/drm/omapdrm/displays/encoder-tpd12s015.c
> +++ b/drivers/gpu/drm/omapdrm/displays/encoder-tpd12s015.c
> @@ -130,13 +130,8 @@ static int tpd_read_edid(struct omap_dss_device *dssdev,
>  static bool tpd_detect(struct omap_dss_device *dssdev)
>  {
>  	struct panel_drv_data *ddata = to_panel_data(dssdev);
> -	struct omap_dss_device *src = dssdev->src;
> -	bool connected;
>  
> -	connected = gpiod_get_value_cansleep(ddata->hpd_gpio);
> -	if (!connected && src->ops->hdmi.lost_hotplug)
> -		src->ops->hdmi.lost_hotplug(src);
> -	return connected;
> +	return gpiod_get_value_cansleep(ddata->hpd_gpio);
>  }
>  
>  static void tpd_register_hpd_cb(struct omap_dss_device *dssdev,
> diff --git a/drivers/gpu/drm/omapdrm/omap_connector.c b/drivers/gpu/drm/omapdrm/omap_connector.c
> index 56985c191740..1b3f85a02c85 100644
> --- a/drivers/gpu/drm/omapdrm/omap_connector.c
> +++ b/drivers/gpu/drm/omapdrm/omap_connector.c
> @@ -34,6 +34,22 @@ struct omap_connector {
>  	bool hdmi_mode;
>  };
>  
> +static void omap_connector_hpd_notify(struct drm_connector *connector,
> +				      struct omap_dss_device *src,
> +				      enum drm_connector_status status)
> +{
> +	if (status == connector_status_disconnected) {
> +		/*
> +		 * If the source is an HDMI encoder, notify it of disconnection.
> +		 * This is required to let the HDMI encoder reset any internal
> +		 * state related to connection status, such as the CEC address.
> +		 */
> +		if (src && src->type == OMAP_DISPLAY_TYPE_HDMI &&
> +		    src->ops->hdmi.lost_hotplug)
> +			src->ops->hdmi.lost_hotplug(src);
> +	}
> +}
> +
>  static void omap_connector_hpd_cb(void *cb_data,
>  				  enum drm_connector_status status)
>  {
> @@ -47,8 +63,12 @@ static void omap_connector_hpd_cb(void *cb_data,
>  	connector->status = status;
>  	mutex_unlock(&dev->mode_config.mutex);
>  
> -	if (old_status != status)
> -		drm_kms_helper_hotplug_event(dev);
> +	if (old_status == status)
> +		return;
> +
> +	omap_connector_hpd_notify(connector, omap_connector->hpd, status);
> +
> +	drm_kms_helper_hotplug_event(dev);
>  }
>  
>  void omap_connector_enable_hpd(struct drm_connector *connector)
> @@ -103,10 +123,11 @@ static enum drm_connector_status omap_connector_detect(
>  					    OMAP_DSS_DEVICE_OP_DETECT);
>  
>  	if (dssdev) {
> -		if (dssdev->ops->detect(dssdev))
> -			status = connector_status_connected;
> -		else
> -			status = connector_status_disconnected;
> +		status = dssdev->ops->detect(dssdev)
> +		       ? connector_status_connected
> +		       : connector_status_disconnected;
> +
> +		omap_connector_hpd_notify(connector, dssdev->src, status);
>  	} else {
>  		switch (omap_connector->dssdev->type) {
>  		case OMAP_DISPLAY_TYPE_DPI:
> -- 
> Regards,
> 
> Laurent Pinchart
> 
> _______________________________________________
> dri-devel mailing list
> dri-devel@lists.freedesktop.org
> https://lists.freedesktop.org/mailman/listinfo/dri-devel
diff mbox

Patch

diff --git a/drivers/gpu/drm/omapdrm/displays/connector-hdmi.c b/drivers/gpu/drm/omapdrm/displays/connector-hdmi.c
index 84cc68388940..6f2364afb14a 100644
--- a/drivers/gpu/drm/omapdrm/displays/connector-hdmi.c
+++ b/drivers/gpu/drm/omapdrm/displays/connector-hdmi.c
@@ -137,13 +137,8 @@  static int hdmic_read_edid(struct omap_dss_device *dssdev,
 static bool hdmic_detect(struct omap_dss_device *dssdev)
 {
 	struct panel_drv_data *ddata = to_panel_data(dssdev);
-	struct omap_dss_device *src = dssdev->src;
-	bool connected;
 
-	connected = gpiod_get_value_cansleep(ddata->hpd_gpio);
-	if (!connected && src->ops->hdmi.lost_hotplug)
-		src->ops->hdmi.lost_hotplug(src);
-	return connected;
+	return gpiod_get_value_cansleep(ddata->hpd_gpio);
 }
 
 static void hdmic_register_hpd_cb(struct omap_dss_device *dssdev,
diff --git a/drivers/gpu/drm/omapdrm/displays/encoder-tpd12s015.c b/drivers/gpu/drm/omapdrm/displays/encoder-tpd12s015.c
index 1fa1d332dbc4..2772af84531a 100644
--- a/drivers/gpu/drm/omapdrm/displays/encoder-tpd12s015.c
+++ b/drivers/gpu/drm/omapdrm/displays/encoder-tpd12s015.c
@@ -130,13 +130,8 @@  static int tpd_read_edid(struct omap_dss_device *dssdev,
 static bool tpd_detect(struct omap_dss_device *dssdev)
 {
 	struct panel_drv_data *ddata = to_panel_data(dssdev);
-	struct omap_dss_device *src = dssdev->src;
-	bool connected;
 
-	connected = gpiod_get_value_cansleep(ddata->hpd_gpio);
-	if (!connected && src->ops->hdmi.lost_hotplug)
-		src->ops->hdmi.lost_hotplug(src);
-	return connected;
+	return gpiod_get_value_cansleep(ddata->hpd_gpio);
 }
 
 static void tpd_register_hpd_cb(struct omap_dss_device *dssdev,
diff --git a/drivers/gpu/drm/omapdrm/omap_connector.c b/drivers/gpu/drm/omapdrm/omap_connector.c
index 56985c191740..1b3f85a02c85 100644
--- a/drivers/gpu/drm/omapdrm/omap_connector.c
+++ b/drivers/gpu/drm/omapdrm/omap_connector.c
@@ -34,6 +34,22 @@  struct omap_connector {
 	bool hdmi_mode;
 };
 
+static void omap_connector_hpd_notify(struct drm_connector *connector,
+				      struct omap_dss_device *src,
+				      enum drm_connector_status status)
+{
+	if (status == connector_status_disconnected) {
+		/*
+		 * If the source is an HDMI encoder, notify it of disconnection.
+		 * This is required to let the HDMI encoder reset any internal
+		 * state related to connection status, such as the CEC address.
+		 */
+		if (src && src->type == OMAP_DISPLAY_TYPE_HDMI &&
+		    src->ops->hdmi.lost_hotplug)
+			src->ops->hdmi.lost_hotplug(src);
+	}
+}
+
 static void omap_connector_hpd_cb(void *cb_data,
 				  enum drm_connector_status status)
 {
@@ -47,8 +63,12 @@  static void omap_connector_hpd_cb(void *cb_data,
 	connector->status = status;
 	mutex_unlock(&dev->mode_config.mutex);
 
-	if (old_status != status)
-		drm_kms_helper_hotplug_event(dev);
+	if (old_status == status)
+		return;
+
+	omap_connector_hpd_notify(connector, omap_connector->hpd, status);
+
+	drm_kms_helper_hotplug_event(dev);
 }
 
 void omap_connector_enable_hpd(struct drm_connector *connector)
@@ -103,10 +123,11 @@  static enum drm_connector_status omap_connector_detect(
 					    OMAP_DSS_DEVICE_OP_DETECT);
 
 	if (dssdev) {
-		if (dssdev->ops->detect(dssdev))
-			status = connector_status_connected;
-		else
-			status = connector_status_disconnected;
+		status = dssdev->ops->detect(dssdev)
+		       ? connector_status_connected
+		       : connector_status_disconnected;
+
+		omap_connector_hpd_notify(connector, dssdev->src, status);
 	} else {
 		switch (omap_connector->dssdev->type) {
 		case OMAP_DISPLAY_TYPE_DPI: