diff --git a/msm/dp/dp_display.c b/msm/dp/dp_display.c index 4e51e045d0..009e1c9ecb 100644 --- a/msm/dp/dp_display.c +++ b/msm/dp/dp_display.c @@ -163,6 +163,7 @@ struct dp_display_private { struct platform_device *pdev; struct device_node *aux_switch_node; + bool aux_switch_ready; struct dp_aux_bridge *aux_bridge; struct dentry *root; struct completion notification_comp; @@ -1324,6 +1325,55 @@ static int dp_display_process_hpd_low(struct dp_display_private *dp) return rc; } +static int dp_display_fsa4480_callback(struct notifier_block *self, + unsigned long event, void *data) +{ + return 0; +} + +static int dp_display_init_aux_switch(struct dp_display_private *dp) +{ + int rc = 0; + struct notifier_block nb; + const u32 max_retries = 50; + u32 retry; + + if (dp->aux_switch_ready) + return rc; + + SDE_EVT32_EXTERNAL(SDE_EVTLOG_FUNC_ENTRY); + + nb.notifier_call = dp_display_fsa4480_callback; + nb.priority = 0; + + /* + * Iteratively wait for reg notifier which confirms that fsa driver is probed. + * Bootup DP with cable connected usecase can hit this scenario. + */ + for (retry = 0; retry < max_retries; retry++) { + rc = fsa4480_reg_notifier(&nb, dp->aux_switch_node); + if (rc == 0) { + DP_DEBUG("registered notifier successfully\n"); + dp->aux_switch_ready = true; + break; + } else { + DP_DEBUG("failed to register notifier retry=%d rc=%d\n", retry, rc); + msleep(100); + } + } + + if (retry == max_retries) { + DP_WARN("Failed to register fsa notifier\n"); + dp->aux_switch_ready = false; + return rc; + } + + fsa4480_unreg_notifier(&nb, dp->aux_switch_node); + + SDE_EVT32_EXTERNAL(SDE_EVTLOG_FUNC_EXIT, rc); + return rc; +} + static int dp_display_usbpd_configure_cb(struct device *dev) { int rc = 0; @@ -1341,7 +1391,11 @@ static int dp_display_usbpd_configure_cb(struct device *dev) } if (!dp->debug->sim_mode && !dp->parser->no_aux_switch - && !dp->parser->gpio_aux_switch) { + && !dp->parser->gpio_aux_switch && dp->aux_switch_node) { + rc = dp_display_init_aux_switch(dp); + if (rc) + return rc; + rc = dp->aux->aux_switch(dp->aux, true, dp->hpd->orientation); if (rc) return rc; @@ -1896,6 +1950,7 @@ static int dp_init_sub_modules(struct dp_display_private *dp) int rc = 0; u32 dp_core_revision = 0; bool hdcp_disabled; + const char *phandle = "qcom,dp-aux-switch"; struct device *dev = &dp->pdev->dev; struct dp_hpd_cb *cb = &dp->hpd_cb; struct dp_ctrl_in ctrl_in = { @@ -1940,6 +1995,10 @@ static int dp_init_sub_modules(struct dp_display_private *dp) dp_core_revision = dp_catalog_get_dp_core_version(dp->catalog); + dp->aux_switch_node = of_parse_phandle(dp->pdev->dev.of_node, phandle, 0); + if (!dp->aux_switch_node) + DP_DEBUG("cannot parse %s handle\n", phandle); + dp->aux = dp_aux_get(dev, &dp->catalog->aux, dp->parser, dp->aux_switch_node, dp->aux_bridge); if (IS_ERR(dp->aux)) { @@ -3047,48 +3106,6 @@ static int dp_display_create_workqueue(struct dp_display_private *dp) return 0; } -static int dp_display_fsa4480_callback(struct notifier_block *self, - unsigned long event, void *data) -{ - return 0; -} - -static int dp_display_init_aux_switch(struct dp_display_private *dp) -{ - int rc = 0; - const char *phandle = "qcom,dp-aux-switch"; - struct notifier_block nb; - - if (!dp->pdev->dev.of_node) { - DP_ERR("cannot find dev.of_node\n"); - rc = -ENODEV; - goto end; - } - - SDE_EVT32_EXTERNAL(SDE_EVTLOG_FUNC_ENTRY); - dp->aux_switch_node = of_parse_phandle(dp->pdev->dev.of_node, - phandle, 0); - if (!dp->aux_switch_node) { - DP_WARN("cannot parse %s handle\n", phandle); - rc = -ENODEV; - goto end; - } - - nb.notifier_call = dp_display_fsa4480_callback; - nb.priority = 0; - - rc = fsa4480_reg_notifier(&nb, dp->aux_switch_node); - if (rc) { - DP_ERR("failed to register notifier (%d)\n", rc); - goto end; - } - - fsa4480_unreg_notifier(&nb, dp->aux_switch_node); -end: - SDE_EVT32_EXTERNAL(SDE_EVTLOG_FUNC_EXIT, rc); - return rc; -} - static int dp_display_bridge_internal_hpd(void *dev, bool hpd, bool hpd_irq) { struct dp_display_private *dp = dev; @@ -3502,12 +3519,6 @@ static int dp_display_probe(struct platform_device *pdev) memset(&dp->mst, 0, sizeof(dp->mst)); - rc = dp_display_init_aux_switch(dp); - if (rc) { - rc = -EPROBE_DEFER; - goto error; - } - rc = dp_display_init_aux_bridge(dp); if (rc) goto error;