drm/omap: Merge HPD enable operation with HPD callback registration
authorLaurent Pinchart <laurent.pinchart@ideasonboard.com>
Wed, 30 May 2018 18:46:44 +0000 (21:46 +0300)
committerTomi Valkeinen <tomi.valkeinen@ti.com>
Mon, 3 Sep 2018 13:13:29 +0000 (16:13 +0300)
The omap_dss_device .enable_hpd() and .disable_hpd() are used to enable
and disable hot-plug detection at omapdrm probe and remove time. This is
required to avoid reporting hot-plug detection events before the DRM
infrastructure is ready to accept them, as that could result in crashes
or other malfunction.

Hot-plug event reporting is conditioned by both HPD being enabled
through the .enable_hpd() operation and by the HPD callback being
registered though the .register_hpd_cb() operation. We thus don't need a
separate enable operation if we can guarantee that callbacks won't be
registered too early.

HPD callbacks are registered at connector initialization time, which is
too early to start reporting HPD events. There's however nothing
blocking a move of callback registration to a later time when the
omapdrm driver calls the HPD enable operations. Do so, and remove the
HPD enable operation completely from omap_dss_device drivers.

Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
Reviewed-by: Sebastian Reichel <sebastian.reichel@collabora.co.uk>
Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ti.com>
drivers/gpu/drm/omapdrm/displays/connector-dvi.c
drivers/gpu/drm/omapdrm/displays/connector-hdmi.c
drivers/gpu/drm/omapdrm/displays/encoder-tpd12s015.c
drivers/gpu/drm/omapdrm/dss/omapdss.h
drivers/gpu/drm/omapdrm/omap_connector.c
drivers/gpu/drm/omapdrm/omap_connector.h
drivers/gpu/drm/omapdrm/omap_drv.c

index a53d5967e5a96faa914c457a2146c52275c0d67e..6be260ff6458a6af76850930090c55f3e2568388 100644 (file)
@@ -234,30 +234,6 @@ static void dvic_unregister_hpd_cb(struct omap_dss_device *dssdev)
        mutex_unlock(&ddata->hpd_lock);
 }
 
-static void dvic_enable_hpd(struct omap_dss_device *dssdev)
-{
-       struct panel_drv_data *ddata = to_panel_data(dssdev);
-
-       if (!ddata->hpd_gpio)
-               return;
-
-       mutex_lock(&ddata->hpd_lock);
-       ddata->hpd_enabled = true;
-       mutex_unlock(&ddata->hpd_lock);
-}
-
-static void dvic_disable_hpd(struct omap_dss_device *dssdev)
-{
-       struct panel_drv_data *ddata = to_panel_data(dssdev);
-
-       if (!ddata->hpd_gpio)
-               return;
-
-       mutex_lock(&ddata->hpd_lock);
-       ddata->hpd_enabled = false;
-       mutex_unlock(&ddata->hpd_lock);
-}
-
 static const struct omap_dss_device_ops dvic_ops = {
        .connect        = dvic_connect,
        .disconnect     = dvic_disconnect,
@@ -274,8 +250,6 @@ static const struct omap_dss_device_ops dvic_ops = {
 
        .register_hpd_cb        = dvic_register_hpd_cb,
        .unregister_hpd_cb      = dvic_unregister_hpd_cb,
-       .enable_hpd             = dvic_enable_hpd,
-       .disable_hpd            = dvic_disable_hpd,
 };
 
 static irqreturn_t dvic_hpd_isr(int irq, void *data)
index c58bf64d1a9b901dcea56caed64db6df7daaccd0..84cc68388940e539eda37471379b7790249713b2 100644 (file)
@@ -37,7 +37,6 @@ struct panel_drv_data {
        struct omap_dss_device dssdev;
        void (*hpd_cb)(void *cb_data, enum drm_connector_status status);
        void *hpd_cb_data;
-       bool hpd_enabled;
        struct mutex hpd_lock;
 
        struct device *dev;
@@ -170,30 +169,6 @@ static void hdmic_unregister_hpd_cb(struct omap_dss_device *dssdev)
        mutex_unlock(&ddata->hpd_lock);
 }
 
-static void hdmic_enable_hpd(struct omap_dss_device *dssdev)
-{
-       struct panel_drv_data *ddata = to_panel_data(dssdev);
-
-       if (!ddata->hpd_gpio)
-               return;
-
-       mutex_lock(&ddata->hpd_lock);
-       ddata->hpd_enabled = true;
-       mutex_unlock(&ddata->hpd_lock);
-}
-
-static void hdmic_disable_hpd(struct omap_dss_device *dssdev)
-{
-       struct panel_drv_data *ddata = to_panel_data(dssdev);
-
-       if (!ddata->hpd_gpio)
-               return;
-
-       mutex_lock(&ddata->hpd_lock);
-       ddata->hpd_enabled = false;
-       mutex_unlock(&ddata->hpd_lock);
-}
-
 static int hdmic_set_hdmi_mode(struct omap_dss_device *dssdev, bool hdmi_mode)
 {
        struct omap_dss_device *src = dssdev->src;
@@ -224,8 +199,6 @@ static const struct omap_dss_device_ops hdmic_ops = {
        .detect                 = hdmic_detect,
        .register_hpd_cb        = hdmic_register_hpd_cb,
        .unregister_hpd_cb      = hdmic_unregister_hpd_cb,
-       .enable_hpd             = hdmic_enable_hpd,
-       .disable_hpd            = hdmic_disable_hpd,
 
        .hdmi = {
                .set_hdmi_mode  = hdmic_set_hdmi_mode,
@@ -238,7 +211,7 @@ static irqreturn_t hdmic_hpd_isr(int irq, void *data)
        struct panel_drv_data *ddata = data;
 
        mutex_lock(&ddata->hpd_lock);
-       if (ddata->hpd_enabled && ddata->hpd_cb) {
+       if (ddata->hpd_cb) {
                enum drm_connector_status status;
 
                if (hdmic_detect(&ddata->dssdev))
index 508df4174c5e66a21b38700afabcf6ca724bb2bf..d6d08148a3e546f45c1769099eae54adfe59b6bf 100644 (file)
@@ -23,7 +23,6 @@ struct panel_drv_data {
        struct omap_dss_device dssdev;
        void (*hpd_cb)(void *cb_data, enum drm_connector_status status);
        void *hpd_cb_data;
-       bool hpd_enabled;
        struct mutex hpd_lock;
 
        struct gpio_desc *ct_cp_hpd_gpio;
@@ -163,24 +162,6 @@ static void tpd_unregister_hpd_cb(struct omap_dss_device *dssdev)
        mutex_unlock(&ddata->hpd_lock);
 }
 
-static void tpd_enable_hpd(struct omap_dss_device *dssdev)
-{
-       struct panel_drv_data *ddata = to_panel_data(dssdev);
-
-       mutex_lock(&ddata->hpd_lock);
-       ddata->hpd_enabled = true;
-       mutex_unlock(&ddata->hpd_lock);
-}
-
-static void tpd_disable_hpd(struct omap_dss_device *dssdev)
-{
-       struct panel_drv_data *ddata = to_panel_data(dssdev);
-
-       mutex_lock(&ddata->hpd_lock);
-       ddata->hpd_enabled = false;
-       mutex_unlock(&ddata->hpd_lock);
-}
-
 static int tpd_set_infoframe(struct omap_dss_device *dssdev,
                const struct hdmi_avi_infoframe *avi)
 {
@@ -208,8 +189,6 @@ static const struct omap_dss_device_ops tpd_ops = {
        .detect                 = tpd_detect,
        .register_hpd_cb        = tpd_register_hpd_cb,
        .unregister_hpd_cb      = tpd_unregister_hpd_cb,
-       .enable_hpd             = tpd_enable_hpd,
-       .disable_hpd            = tpd_disable_hpd,
 
        .hdmi = {
                .set_infoframe          = tpd_set_infoframe,
@@ -222,7 +201,7 @@ static irqreturn_t tpd_hpd_isr(int irq, void *data)
        struct panel_drv_data *ddata = data;
 
        mutex_lock(&ddata->hpd_lock);
-       if (ddata->hpd_enabled && ddata->hpd_cb) {
+       if (ddata->hpd_cb) {
                enum drm_connector_status status;
 
                if (tpd_detect(&ddata->dssdev))
index b05d47b3493737d3dbb8a845f9e35be786cc2646..ecefc1b193ca814d82c0e6adb7deb2397be24fe2 100644 (file)
@@ -377,8 +377,6 @@ struct omap_dss_device_ops {
                                          enum drm_connector_status status),
                                void *cb_data);
        void (*unregister_hpd_cb)(struct omap_dss_device *dssdev);
-       void (*enable_hpd)(struct omap_dss_device *dssdev);
-       void (*disable_hpd)(struct omap_dss_device *dssdev);
 
        int (*read_edid)(struct omap_dss_device *dssdev, u8 *buf, int len);
 
index cd33995b0b1ae7f6e445e36fef5f884f77fa3411..e77427d81eb97a64e46d8e44c2e41f1df358083f 100644 (file)
@@ -30,6 +30,7 @@
 struct omap_connector {
        struct drm_connector base;
        struct omap_dss_device *dssdev;
+       struct omap_dss_device *hpd;
        bool hdmi_mode;
 };
 
@@ -50,6 +51,25 @@ static void omap_connector_hpd_cb(void *cb_data,
                drm_kms_helper_hotplug_event(dev);
 }
 
+void omap_connector_enable_hpd(struct drm_connector *connector)
+{
+       struct omap_connector *omap_connector = to_omap_connector(connector);
+       struct omap_dss_device *hpd = omap_connector->hpd;
+
+       if (hpd)
+               hpd->ops->register_hpd_cb(hpd, omap_connector_hpd_cb,
+                                         omap_connector);
+}
+
+void omap_connector_disable_hpd(struct drm_connector *connector)
+{
+       struct omap_connector *omap_connector = to_omap_connector(connector);
+       struct omap_dss_device *hpd = omap_connector->hpd;
+
+       if (hpd)
+               hpd->ops->unregister_hpd_cb(hpd);
+}
+
 bool omap_connector_get_hdmi_mode(struct drm_connector *connector)
 {
        struct omap_connector *omap_connector = to_omap_connector(connector);
@@ -109,14 +129,15 @@ static enum drm_connector_status omap_connector_detect(
 static void omap_connector_destroy(struct drm_connector *connector)
 {
        struct omap_connector *omap_connector = to_omap_connector(connector);
-       struct omap_dss_device *dssdev;
 
        DBG("%s", omap_connector->dssdev->name);
 
-       if (connector->polled == DRM_CONNECTOR_POLL_HPD) {
-               dssdev = omap_connector_find_device(connector,
-                                                   OMAP_DSS_DEVICE_OP_HPD);
-               dssdev->ops->unregister_hpd_cb(dssdev);
+       if (omap_connector->hpd) {
+               struct omap_dss_device *hpd = omap_connector->hpd;
+
+               hpd->ops->unregister_hpd_cb(hpd);
+               omapdss_device_put(hpd);
+               omap_connector->hpd = NULL;
        }
 
        drm_connector_unregister(connector);
@@ -298,8 +319,7 @@ struct drm_connector *omap_connector_init(struct drm_device *dev,
         */
        dssdev = omap_connector_find_device(connector, OMAP_DSS_DEVICE_OP_HPD);
        if (dssdev) {
-               dssdev->ops->register_hpd_cb(dssdev, omap_connector_hpd_cb,
-                                            omap_connector);
+               omap_connector->hpd = omapdss_device_get(dssdev);
                connector->polled = DRM_CONNECTOR_POLL_HPD;
        } else {
                dssdev = omap_connector_find_device(connector,
index 98bbc779b30265304363166c66da784de0277ff1..465b3c9499d5809eaeb44a3466979f885fae5603 100644 (file)
@@ -33,5 +33,7 @@ struct drm_connector *omap_connector_init(struct drm_device *dev,
 struct drm_encoder *omap_connector_attached_encoder(
                struct drm_connector *connector);
 bool omap_connector_get_hdmi_mode(struct drm_connector *connector);
+void omap_connector_enable_hpd(struct drm_connector *connector);
+void omap_connector_disable_hpd(struct drm_connector *connector);
 
 #endif /* __OMAPDRM_CONNECTOR_H__ */
index 843222118fa717dcc0bef9bd95b3700046a3987f..0cca16c323d962c276853f4d434a527462cfc701 100644 (file)
@@ -375,12 +375,8 @@ static void omap_modeset_enable_external_hpd(struct drm_device *ddev)
        struct omap_drm_private *priv = ddev->dev_private;
        int i;
 
-       for (i = 0; i < priv->num_pipes; i++) {
-               struct omap_dss_device *display = priv->pipes[i].display;
-
-               if (display->ops->enable_hpd)
-                       display->ops->enable_hpd(display);
-       }
+       for (i = 0; i < priv->num_pipes; i++)
+               omap_connector_enable_hpd(priv->pipes[i].connector);
 }
 
 /*
@@ -391,12 +387,8 @@ static void omap_modeset_disable_external_hpd(struct drm_device *ddev)
        struct omap_drm_private *priv = ddev->dev_private;
        int i;
 
-       for (i = 0; i < priv->num_pipes; i++) {
-               struct omap_dss_device *display = priv->pipes[i].display;
-
-               if (display->ops->disable_hpd)
-                       display->ops->disable_hpd(display);
-       }
+       for (i = 0; i < priv->num_pipes; i++)
+               omap_connector_disable_hpd(priv->pipes[i].connector);
 }
 
 /*