#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.