#include <linux/component.h>
 #include <linux/of_irq.h>
 #include <linux/delay.h>
+#include <drm/dp/drm_dp_aux_bus.h>
 
 #include "msm_drv.h"
 #include "msm_kms.h"
        dp->dp_display.drm_dev = drm;
        priv->dp[dp->id] = &dp->dp_display;
 
-       rc = dp->parser->parse(dp->parser, dp->dp_display.connector_type);
+       rc = dp->parser->parse(dp->parser);
        if (rc) {
                DRM_ERROR("device tree parsing failed\n");
                goto end;
        }
 
-       dp->dp_display.next_bridge = dp->parser->next_bridge;
 
        dp->drm_dev = drm;
        dp->aux->drm_dev = drm;
        dp->name = "drm_dp";
        dp->dp_display.connector_type = desc->connector_type;
        dp->wide_bus_en = desc->wide_bus_en;
+       dp->dp_display.is_edp =
+               (dp->dp_display.connector_type == DRM_MODE_CONNECTOR_eDP);
 
        rc = dp_init_sub_modules(dp);
        if (rc) {
 
        dp = container_of(dp_display, struct dp_display_private, dp_display);
 
-       dp_add_event(dp, EV_HPD_INIT_SETUP, 0, 100);
+       if (!dp_display->is_edp)
+               dp_add_event(dp, EV_HPD_INIT_SETUP, 0, 100);
 }
 
 bool msm_dp_wide_bus_available(const struct msm_dp *dp_display)
        }
 }
 
+static int dp_display_get_next_bridge(struct msm_dp *dp)
+{
+       int rc;
+       struct dp_display_private *dp_priv;
+       struct device_node *aux_bus;
+       struct device *dev;
+
+       dp_priv = container_of(dp, struct dp_display_private, dp_display);
+       dev = &dp_priv->pdev->dev;
+       aux_bus = of_get_child_by_name(dev->of_node, "aux-bus");
+
+       if (aux_bus && dp->is_edp) {
+               dp_display_host_init(dp_priv);
+               dp_catalog_ctrl_hpd_config(dp_priv->catalog);
+               dp_display_host_phy_init(dp_priv);
+               enable_irq(dp_priv->irq);
+
+               /*
+                * The code below assumes that the panel will finish probing
+                * by the time devm_of_dp_aux_populate_ep_devices() returns.
+                * This isn't a great assumption since it will fail if the
+                * panel driver is probed asynchronously but is the best we
+                * can do without a bigger driver reorganization.
+                */
+               rc = devm_of_dp_aux_populate_ep_devices(dp_priv->aux);
+               of_node_put(aux_bus);
+               if (rc)
+                       goto error;
+       } else if (dp->is_edp) {
+               DRM_ERROR("eDP aux_bus not found\n");
+               return -ENODEV;
+       }
+
+       /*
+        * External bridges are mandatory for eDP interfaces: one has to
+        * provide at least an eDP panel (which gets wrapped into panel-bridge).
+        *
+        * For DisplayPort interfaces external bridges are optional, so
+        * silently ignore an error if one is not present (-ENODEV).
+        */
+       rc = dp_parser_find_next_bridge(dp_priv->parser);
+       if (!dp->is_edp && rc == -ENODEV)
+               return 0;
+
+       if (!rc) {
+               dp->next_bridge = dp_priv->parser->next_bridge;
+               return 0;
+       }
+
+error:
+       if (dp->is_edp) {
+               disable_irq(dp_priv->irq);
+               dp_display_host_phy_exit(dp_priv);
+               dp_display_host_deinit(dp_priv);
+       }
+       return rc;
+}
+
 int msm_dp_modeset_init(struct msm_dp *dp_display, struct drm_device *dev,
                        struct drm_encoder *encoder)
 {
 
        dp_display->encoder = encoder;
 
+       ret = dp_display_get_next_bridge(dp_display);
+       if (ret)
+               return ret;
+
        dp_display->bridge = dp_bridge_init(dp_display, dev, encoder);
        if (IS_ERR(dp_display->bridge)) {
                ret = PTR_ERR(dp_display->bridge);
 
        bridge->funcs = &dp_bridge_ops;
        bridge->type = dp_display->connector_type;
 
-       bridge->ops =
-               DRM_BRIDGE_OP_DETECT |
-               DRM_BRIDGE_OP_HPD |
-               DRM_BRIDGE_OP_MODES;
+       /*
+        * Many ops only make sense for DP. Why?
+        * - Detect/HPD are used by DRM to know if a display is _physically_
+        *   there, not whether the display is powered on / finished initting.
+        *   On eDP we assume the display is always there because you can't
+        *   know until power is applied. If we don't implement the ops DRM will
+        *   assume our display is always there.
+        * - Currently eDP mode reading is driven by the panel driver. This
+        *   allows the panel driver to properly power itself on to read the
+        *   modes.
+        */
+       if (!dp_display->is_edp) {
+               bridge->ops =
+                       DRM_BRIDGE_OP_DETECT |
+                       DRM_BRIDGE_OP_HPD |
+                       DRM_BRIDGE_OP_MODES;
+       }
 
        drm_bridge_add(bridge);
 
 
        return 0;
 }
 
-static int dp_parser_find_next_bridge(struct dp_parser *parser)
+int dp_parser_find_next_bridge(struct dp_parser *parser)
 {
        struct device *dev = &parser->pdev->dev;
        struct drm_bridge *bridge;
        return 0;
 }
 
-static int dp_parser_parse(struct dp_parser *parser, int connector_type)
+static int dp_parser_parse(struct dp_parser *parser)
 {
        int rc = 0;
 
        if (rc)
                return rc;
 
-       /*
-        * External bridges are mandatory for eDP interfaces: one has to
-        * provide at least an eDP panel (which gets wrapped into panel-bridge).
-        *
-        * For DisplayPort interfaces external bridges are optional, so
-        * silently ignore an error if one is not present (-ENODEV).
-        */
-       rc = dp_parser_find_next_bridge(parser);
-       if (rc == -ENODEV) {
-               if (connector_type == DRM_MODE_CONNECTOR_eDP) {
-                       DRM_ERROR("eDP: next bridge is not present\n");
-                       return rc;
-               }
-       } else if (rc) {
-               if (rc != -EPROBE_DEFER)
-                       DRM_ERROR("DP: error parsing next bridge: %d\n", rc);
-               return rc;
-       }
-
        /* Map the corresponding regulator information according to
         * version. Currently, since we only have one supported platform,
         * mapping the regulator directly.