From 61f0479757aa4371801b9d552e85dd6d6327d036 Mon Sep 17 00:00:00 2001 From: Abhinav Kumar Date: Fri, 31 May 2019 19:43:27 -0700 Subject: drm/msm/dsi: add protection against NULL dsi device When panel probe happens after DSI probe, the DSI probe is deferred as per current design. In the probe defer path dsi device is destroyed. This NULL dsi device could be deferenced by the panel probe in the mipi_dsi_attach path. Check for NULL dsi device before accessing it. Changes in v2: - Add more comments on how this NULL pointer situation will be hit Reported-by: Jeffrey Hugo Tested-by: Jeffrey Hugo Signed-off-by: Abhinav Kumar Signed-off-by: Rob Clark --- drivers/gpu/drm/msm/dsi/dsi_manager.c | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) (limited to 'drivers/gpu/drm/msm/dsi/dsi_manager.c') diff --git a/drivers/gpu/drm/msm/dsi/dsi_manager.c b/drivers/gpu/drm/msm/dsi/dsi_manager.c index 979a8e929341..72ac869a737a 100644 --- a/drivers/gpu/drm/msm/dsi/dsi_manager.c +++ b/drivers/gpu/drm/msm/dsi/dsi_manager.c @@ -762,7 +762,7 @@ bool msm_dsi_manager_cmd_xfer_trigger(int id, u32 dma_base, u32 len) void msm_dsi_manager_attach_dsi_device(int id, u32 device_flags) { struct msm_dsi *msm_dsi = dsi_mgr_get_dsi(id); - struct drm_device *dev = msm_dsi->dev; + struct drm_device *dev; struct msm_drm_private *priv; struct msm_kms *kms; struct drm_encoder *encoder; @@ -774,7 +774,17 @@ void msm_dsi_manager_attach_dsi_device(int id, u32 device_flags) * (generally the case when we're connected to a drm_panel of the type * mipi_dsi_device), this would be NULL. In such cases, try to set the * encoder mode in the DSI connector's detect() op. + * + * msm_dsi pointer is assigned to a valid dsi device only when + * msm_dsi_manager_register() succeeds. When panel hasnt probed yet + * dsi_mgr_setup_components() could potentially return -EDEFER and + * assign the msm_dsi->dev to NULL. When the panel now probes and calls + * mipi_dsi_attach(), this will call msm_dsi_manager_attach_dsi_device() + * which will result in a NULL pointer dereference */ + + dev = msm_dsi ? msm_dsi->dev : NULL; + if (!dev) return; -- cgit v1.2.3 From e3a91f893cabd684a6cd63599425118308defc06 Mon Sep 17 00:00:00 2001 From: Sean Paul Date: Mon, 17 Jun 2019 16:12:52 -0400 Subject: drm/msm/dsi: Split mode_flags out of msm_dsi_host_get_panel() We use the flags in more places than just get_panel, so split them out into a separate function. Reviewed-by: Rob Clark Signed-off-by: Sean Paul Link: https://patchwork.freedesktop.org/patch/msgid/20190617201301.133275-4-sean@poorly.run --- drivers/gpu/drm/msm/dsi/dsi.h | 4 ++-- drivers/gpu/drm/msm/dsi/dsi_host.c | 15 ++++++--------- drivers/gpu/drm/msm/dsi/dsi_manager.c | 7 ++++--- 3 files changed, 12 insertions(+), 14 deletions(-) (limited to 'drivers/gpu/drm/msm/dsi/dsi_manager.c') diff --git a/drivers/gpu/drm/msm/dsi/dsi.h b/drivers/gpu/drm/msm/dsi/dsi.h index 9c6b31c2d79f..8bdc48ca0b67 100644 --- a/drivers/gpu/drm/msm/dsi/dsi.h +++ b/drivers/gpu/drm/msm/dsi/dsi.h @@ -169,8 +169,8 @@ int msm_dsi_host_power_on(struct mipi_dsi_host *host, int msm_dsi_host_power_off(struct mipi_dsi_host *host); int msm_dsi_host_set_display_mode(struct mipi_dsi_host *host, const struct drm_display_mode *mode); -struct drm_panel *msm_dsi_host_get_panel(struct mipi_dsi_host *host, - unsigned long *panel_flags); +struct drm_panel *msm_dsi_host_get_panel(struct mipi_dsi_host *host); +unsigned long msm_dsi_host_get_mode_flags(struct mipi_dsi_host *host); struct drm_bridge *msm_dsi_host_get_bridge(struct mipi_dsi_host *host); int msm_dsi_host_register(struct mipi_dsi_host *host, bool check_defer); void msm_dsi_host_unregister(struct mipi_dsi_host *host); diff --git a/drivers/gpu/drm/msm/dsi/dsi_host.c b/drivers/gpu/drm/msm/dsi/dsi_host.c index dc16067128fc..2594ecfcdc14 100644 --- a/drivers/gpu/drm/msm/dsi/dsi_host.c +++ b/drivers/gpu/drm/msm/dsi/dsi_host.c @@ -2442,17 +2442,14 @@ int msm_dsi_host_set_display_mode(struct mipi_dsi_host *host, return 0; } -struct drm_panel *msm_dsi_host_get_panel(struct mipi_dsi_host *host, - unsigned long *panel_flags) +struct drm_panel *msm_dsi_host_get_panel(struct mipi_dsi_host *host) { - struct msm_dsi_host *msm_host = to_msm_dsi_host(host); - struct drm_panel *panel; - - panel = of_drm_find_panel(msm_host->device_node); - if (panel_flags) - *panel_flags = msm_host->mode_flags; + return of_drm_find_panel(to_msm_dsi_host(host)->device_node); +} - return panel; +unsigned long msm_dsi_host_get_mode_flags(struct mipi_dsi_host *host) +{ + return to_msm_dsi_host(host)->mode_flags; } struct drm_bridge *msm_dsi_host_get_bridge(struct mipi_dsi_host *host) diff --git a/drivers/gpu/drm/msm/dsi/dsi_manager.c b/drivers/gpu/drm/msm/dsi/dsi_manager.c index 72ac869a737a..47b349a4015a 100644 --- a/drivers/gpu/drm/msm/dsi/dsi_manager.c +++ b/drivers/gpu/drm/msm/dsi/dsi_manager.c @@ -244,8 +244,9 @@ static enum drm_connector_status dsi_mgr_connector_detect( DBG("id=%d", id); if (!msm_dsi->panel) { - msm_dsi->panel = msm_dsi_host_get_panel(msm_dsi->host, - &msm_dsi->device_flags); + msm_dsi->panel = msm_dsi_host_get_panel(msm_dsi->host); + msm_dsi->device_flags = msm_dsi_host_get_mode_flags( + msm_dsi->host); /* There is only 1 panel in the global panel list * for dual DSI mode. Therefore slave dsi should get @@ -255,7 +256,7 @@ static enum drm_connector_status dsi_mgr_connector_detect( if (!msm_dsi->panel && IS_DUAL_DSI() && !IS_MASTER_DSI_LINK(id) && other_dsi) msm_dsi->panel = msm_dsi_host_get_panel( - other_dsi->host, NULL); + other_dsi->host); if (msm_dsi->panel && kms->funcs->set_encoder_mode) { -- cgit v1.2.3 From 09951aaa7229b253b0e00979d6c6d17b20e16fe4 Mon Sep 17 00:00:00 2001 From: Sean Paul Date: Mon, 17 Jun 2019 16:12:53 -0400 Subject: drm/msm/dsi: Don't store dsi host mode_flags in msm_dsi It's a bit dangerous to store the flags in msm_dsi since there's no way to tell when they're populated. Fortunately the only place that uses them is the same place that fills them. So just use a local variable and delete the struct member. Reviewed-by: Rob Clark Signed-off-by: Sean Paul Link: https://patchwork.freedesktop.org/patch/msgid/20190617201301.133275-5-sean@poorly.run --- drivers/gpu/drm/msm/dsi/dsi.h | 1 - drivers/gpu/drm/msm/dsi/dsi_manager.c | 17 +++++++++-------- 2 files changed, 9 insertions(+), 9 deletions(-) (limited to 'drivers/gpu/drm/msm/dsi/dsi_manager.c') diff --git a/drivers/gpu/drm/msm/dsi/dsi.h b/drivers/gpu/drm/msm/dsi/dsi.h index 8bdc48ca0b67..e0bbe8128aef 100644 --- a/drivers/gpu/drm/msm/dsi/dsi.h +++ b/drivers/gpu/drm/msm/dsi/dsi.h @@ -79,7 +79,6 @@ struct msm_dsi { */ struct drm_panel *panel; struct drm_bridge *external_bridge; - unsigned long device_flags; struct device *phy_dev; bool phy_enabled; diff --git a/drivers/gpu/drm/msm/dsi/dsi_manager.c b/drivers/gpu/drm/msm/dsi/dsi_manager.c index 47b349a4015a..ffc095504594 100644 --- a/drivers/gpu/drm/msm/dsi/dsi_manager.c +++ b/drivers/gpu/drm/msm/dsi/dsi_manager.c @@ -233,6 +233,12 @@ static int dsi_mgr_bridge_get_id(struct drm_bridge *bridge) return dsi_bridge->id; } +static bool dsi_mgr_is_cmd_mode(struct msm_dsi *msm_dsi) +{ + unsigned long host_flags = msm_dsi_host_get_mode_flags(msm_dsi->host); + return !(host_flags & MIPI_DSI_MODE_VIDEO); +} + static enum drm_connector_status dsi_mgr_connector_detect( struct drm_connector *connector, bool force) { @@ -241,17 +247,15 @@ static enum drm_connector_status dsi_mgr_connector_detect( struct msm_dsi *other_dsi = dsi_mgr_get_other_dsi(id); struct msm_drm_private *priv = connector->dev->dev_private; struct msm_kms *kms = priv->kms; + bool cmd_mode; DBG("id=%d", id); if (!msm_dsi->panel) { msm_dsi->panel = msm_dsi_host_get_panel(msm_dsi->host); - msm_dsi->device_flags = msm_dsi_host_get_mode_flags( - msm_dsi->host); /* There is only 1 panel in the global panel list * for dual DSI mode. Therefore slave dsi should get - * the drm_panel instance from master dsi, and - * keep using the panel flags got from the current DSI link. + * the drm_panel instance from master dsi. */ if (!msm_dsi->panel && IS_DUAL_DSI() && !IS_MASTER_DSI_LINK(id) && other_dsi) @@ -259,9 +263,8 @@ static enum drm_connector_status dsi_mgr_connector_detect( other_dsi->host); + cmd_mode = dsi_mgr_is_cmd_mode(msm_dsi); if (msm_dsi->panel && kms->funcs->set_encoder_mode) { - bool cmd_mode = !(msm_dsi->device_flags & - MIPI_DSI_MODE_VIDEO); struct drm_encoder *encoder = msm_dsi_get_encoder(msm_dsi); @@ -277,8 +280,6 @@ static enum drm_connector_status dsi_mgr_connector_detect( */ if (msm_dsi->panel && IS_DUAL_DSI() && other_dsi && other_dsi->panel) { - bool cmd_mode = !(msm_dsi->device_flags & - MIPI_DSI_MODE_VIDEO); struct drm_encoder *encoder = msm_dsi_get_encoder( dsi_mgr_get_dsi(DSI_ENCODER_MASTER)); struct drm_encoder *slave_enc = msm_dsi_get_encoder( -- cgit v1.2.3 From 4f229b41386fbf290505411964c8ed25f48e1656 Mon Sep 17 00:00:00 2001 From: Sean Paul Date: Mon, 17 Jun 2019 16:12:54 -0400 Subject: drm/msm/dsi: Pull out panel init code into function Pull all of the panel init code out of detect() and put it in its own function. This will be useful in future patches where it's moved from detect(). Reviewed-by: Rob Clark Signed-off-by: Sean Paul Link: https://patchwork.freedesktop.org/patch/msgid/20190617201301.133275-6-sean@poorly.run --- drivers/gpu/drm/msm/dsi/dsi_manager.c | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) (limited to 'drivers/gpu/drm/msm/dsi/dsi_manager.c') diff --git a/drivers/gpu/drm/msm/dsi/dsi_manager.c b/drivers/gpu/drm/msm/dsi/dsi_manager.c index ffc095504594..4be0240c2d9d 100644 --- a/drivers/gpu/drm/msm/dsi/dsi_manager.c +++ b/drivers/gpu/drm/msm/dsi/dsi_manager.c @@ -239,17 +239,14 @@ static bool dsi_mgr_is_cmd_mode(struct msm_dsi *msm_dsi) return !(host_flags & MIPI_DSI_MODE_VIDEO); } -static enum drm_connector_status dsi_mgr_connector_detect( - struct drm_connector *connector, bool force) +static void msm_dsi_manager_panel_init(struct drm_connector *connector, u8 id) { - int id = dsi_mgr_connector_get_id(connector); struct msm_dsi *msm_dsi = dsi_mgr_get_dsi(id); struct msm_dsi *other_dsi = dsi_mgr_get_other_dsi(id); struct msm_drm_private *priv = connector->dev->dev_private; struct msm_kms *kms = priv->kms; bool cmd_mode; - DBG("id=%d", id); if (!msm_dsi->panel) { msm_dsi->panel = msm_dsi_host_get_panel(msm_dsi->host); @@ -292,6 +289,17 @@ static enum drm_connector_status dsi_mgr_connector_detect( pr_err("mdp does not support dual DSI\n"); } } +} + +static enum drm_connector_status dsi_mgr_connector_detect( + struct drm_connector *connector, bool force) +{ + int id = dsi_mgr_connector_get_id(connector); + struct msm_dsi *msm_dsi = dsi_mgr_get_dsi(id); + + DBG("id=%d", id); + if (!msm_dsi->panel) + msm_dsi_manager_panel_init(connector, id); return msm_dsi->panel ? connector_status_connected : connector_status_disconnected; -- cgit v1.2.3 From faccd71cec5516b1f79e8b40757563617c886171 Mon Sep 17 00:00:00 2001 From: Sean Paul Date: Mon, 17 Jun 2019 16:12:55 -0400 Subject: drm/msm/dsi: Simplify the logic in msm_dsi_manager_panel_init() This patch moves things around a bit to be a little more readable and pulls out the set_encoder_mode() call into its own function for later use. Reviewed-by: Rob Clark Signed-off-by: Sean Paul Link: https://patchwork.freedesktop.org/patch/msgid/20190617201301.133275-7-sean@poorly.run --- drivers/gpu/drm/msm/dsi/dsi_manager.c | 100 ++++++++++++++++++++-------------- 1 file changed, 59 insertions(+), 41 deletions(-) (limited to 'drivers/gpu/drm/msm/dsi/dsi_manager.c') diff --git a/drivers/gpu/drm/msm/dsi/dsi_manager.c b/drivers/gpu/drm/msm/dsi/dsi_manager.c index 4be0240c2d9d..787d97829912 100644 --- a/drivers/gpu/drm/msm/dsi/dsi_manager.c +++ b/drivers/gpu/drm/msm/dsi/dsi_manager.c @@ -239,56 +239,71 @@ static bool dsi_mgr_is_cmd_mode(struct msm_dsi *msm_dsi) return !(host_flags & MIPI_DSI_MODE_VIDEO); } -static void msm_dsi_manager_panel_init(struct drm_connector *connector, u8 id) +static void msm_dsi_manager_setup_encoder(int id) { struct msm_dsi *msm_dsi = dsi_mgr_get_dsi(id); - struct msm_dsi *other_dsi = dsi_mgr_get_other_dsi(id); - struct msm_drm_private *priv = connector->dev->dev_private; + struct msm_drm_private *priv = msm_dsi->dev->dev_private; struct msm_kms *kms = priv->kms; - bool cmd_mode; + struct drm_encoder *encoder = msm_dsi_get_encoder(msm_dsi); - if (!msm_dsi->panel) { - msm_dsi->panel = msm_dsi_host_get_panel(msm_dsi->host); + if (encoder && kms->funcs->set_encoder_mode) + kms->funcs->set_encoder_mode(kms, encoder, + dsi_mgr_is_cmd_mode(msm_dsi)); +} - /* There is only 1 panel in the global panel list - * for dual DSI mode. Therefore slave dsi should get - * the drm_panel instance from master dsi. - */ - if (!msm_dsi->panel && IS_DUAL_DSI() && - !IS_MASTER_DSI_LINK(id) && other_dsi) - msm_dsi->panel = msm_dsi_host_get_panel( - other_dsi->host); +static int msm_dsi_manager_panel_init(struct drm_connector *conn, u8 id) +{ + struct msm_drm_private *priv = conn->dev->dev_private; + struct msm_kms *kms = priv->kms; + struct msm_dsi *msm_dsi = dsi_mgr_get_dsi(id); + struct msm_dsi *other_dsi = dsi_mgr_get_other_dsi(id); + struct msm_dsi *master_dsi, *slave_dsi; + struct drm_panel *panel; + if (IS_DUAL_DSI() && !IS_MASTER_DSI_LINK(id)) { + master_dsi = other_dsi; + slave_dsi = msm_dsi; + } else { + master_dsi = msm_dsi; + slave_dsi = other_dsi; + } - cmd_mode = dsi_mgr_is_cmd_mode(msm_dsi); - if (msm_dsi->panel && kms->funcs->set_encoder_mode) { - struct drm_encoder *encoder = - msm_dsi_get_encoder(msm_dsi); + /* + * There is only 1 panel in the global panel list for dual DSI mode. + * Therefore slave dsi should get the drm_panel instance from master + * dsi. + */ + panel = msm_dsi_host_get_panel(master_dsi->host); + if (IS_ERR(panel)) { + DRM_ERROR("Could not find panel for %u (%ld)\n", msm_dsi->id, + PTR_ERR(panel)); + return PTR_ERR(panel); + } - kms->funcs->set_encoder_mode(kms, encoder, cmd_mode); - } + if (!panel) + return 0; - if (msm_dsi->panel && IS_DUAL_DSI()) - drm_object_attach_property(&connector->base, - connector->dev->mode_config.tile_property, 0); + msm_dsi_manager_setup_encoder(id); - /* Set split display info to kms once dual DSI panel is - * connected to both hosts. - */ - if (msm_dsi->panel && IS_DUAL_DSI() && - other_dsi && other_dsi->panel) { - struct drm_encoder *encoder = msm_dsi_get_encoder( - dsi_mgr_get_dsi(DSI_ENCODER_MASTER)); - struct drm_encoder *slave_enc = msm_dsi_get_encoder( - dsi_mgr_get_dsi(DSI_ENCODER_SLAVE)); - - if (kms->funcs->set_split_display) - kms->funcs->set_split_display(kms, encoder, - slave_enc, cmd_mode); - else - pr_err("mdp does not support dual DSI\n"); - } + if (!IS_DUAL_DSI()) + goto out; + + drm_object_attach_property(&conn->base, + conn->dev->mode_config.tile_property, 0); + + /* + * Set split display info to kms once dual DSI panel is connected to + * both hosts. + */ + if (other_dsi && other_dsi->panel && kms->funcs->set_split_display) { + kms->funcs->set_split_display(kms, master_dsi->encoder, + slave_dsi->encoder, + dsi_mgr_is_cmd_mode(msm_dsi)); } + +out: + msm_dsi->panel = panel; + return 0; } static enum drm_connector_status dsi_mgr_connector_detect( @@ -298,8 +313,11 @@ static enum drm_connector_status dsi_mgr_connector_detect( struct msm_dsi *msm_dsi = dsi_mgr_get_dsi(id); DBG("id=%d", id); - if (!msm_dsi->panel) - msm_dsi_manager_panel_init(connector, id); + if (!msm_dsi->panel) { + int ret = msm_dsi_manager_panel_init(connector, id); + if (ret) + return connector_status_disconnected; + } return msm_dsi->panel ? connector_status_connected : connector_status_disconnected; -- cgit v1.2.3 From 970524b07a9c1d0434266a0f32825631bc206848 Mon Sep 17 00:00:00 2001 From: Sean Paul Date: Mon, 17 Jun 2019 16:12:56 -0400 Subject: drm/msm/dsi: Use the new setup_encoder function in attach_dsi_device Now that we have a function to call set_encoder_mode() for us, use it. Reviewed-by: Rob Clark Signed-off-by: Sean Paul Link: https://patchwork.freedesktop.org/patch/msgid/20190617201301.133275-8-sean@poorly.run --- drivers/gpu/drm/msm/dsi/dsi.h | 2 +- drivers/gpu/drm/msm/dsi/dsi_host.c | 2 +- drivers/gpu/drm/msm/dsi/dsi_manager.c | 15 ++------------- 3 files changed, 4 insertions(+), 15 deletions(-) (limited to 'drivers/gpu/drm/msm/dsi/dsi_manager.c') diff --git a/drivers/gpu/drm/msm/dsi/dsi.h b/drivers/gpu/drm/msm/dsi/dsi.h index e0bbe8128aef..f8a611725f2e 100644 --- a/drivers/gpu/drm/msm/dsi/dsi.h +++ b/drivers/gpu/drm/msm/dsi/dsi.h @@ -96,7 +96,7 @@ struct drm_connector *msm_dsi_manager_connector_init(u8 id); struct drm_connector *msm_dsi_manager_ext_bridge_init(u8 id); int msm_dsi_manager_cmd_xfer(int id, const struct mipi_dsi_msg *msg); bool msm_dsi_manager_cmd_xfer_trigger(int id, u32 dma_base, u32 len); -void msm_dsi_manager_attach_dsi_device(int id, u32 device_flags); +void msm_dsi_manager_attach_dsi_device(int id); int msm_dsi_manager_register(struct msm_dsi *msm_dsi); void msm_dsi_manager_unregister(struct msm_dsi *msm_dsi); bool msm_dsi_manager_validate_current_config(u8 id); diff --git a/drivers/gpu/drm/msm/dsi/dsi_host.c b/drivers/gpu/drm/msm/dsi/dsi_host.c index 2594ecfcdc14..f6eb91cf97e6 100644 --- a/drivers/gpu/drm/msm/dsi/dsi_host.c +++ b/drivers/gpu/drm/msm/dsi/dsi_host.c @@ -1598,7 +1598,7 @@ static int dsi_host_attach(struct mipi_dsi_host *host, msm_host->format = dsi->format; msm_host->mode_flags = dsi->mode_flags; - msm_dsi_manager_attach_dsi_device(msm_host->id, dsi->mode_flags); + msm_dsi_manager_attach_dsi_device(msm_host->id); /* Some gpios defined in panel DT need to be controlled by host */ ret = dsi_host_init_panel_gpios(msm_host, &dsi->dev); diff --git a/drivers/gpu/drm/msm/dsi/dsi_manager.c b/drivers/gpu/drm/msm/dsi/dsi_manager.c index 787d97829912..a48a54005f50 100644 --- a/drivers/gpu/drm/msm/dsi/dsi_manager.c +++ b/drivers/gpu/drm/msm/dsi/dsi_manager.c @@ -787,14 +787,10 @@ bool msm_dsi_manager_cmd_xfer_trigger(int id, u32 dma_base, u32 len) return true; } -void msm_dsi_manager_attach_dsi_device(int id, u32 device_flags) +void msm_dsi_manager_attach_dsi_device(int id) { struct msm_dsi *msm_dsi = dsi_mgr_get_dsi(id); struct drm_device *dev; - struct msm_drm_private *priv; - struct msm_kms *kms; - struct drm_encoder *encoder; - bool cmd_mode; /* * drm_device pointer is assigned to msm_dsi only in the modeset_init @@ -816,14 +812,7 @@ void msm_dsi_manager_attach_dsi_device(int id, u32 device_flags) if (!dev) return; - priv = dev->dev_private; - kms = priv->kms; - encoder = msm_dsi_get_encoder(msm_dsi); - cmd_mode = !(device_flags & - MIPI_DSI_MODE_VIDEO); - - if (encoder && kms->funcs->set_encoder_mode) - kms->funcs->set_encoder_mode(kms, encoder, cmd_mode); + msm_dsi_manager_setup_encoder(id); } int msm_dsi_manager_register(struct msm_dsi *msm_dsi) -- cgit v1.2.3 From 6d5e78406991a144b7c44cd57b21e290fdb1d227 Mon Sep 17 00:00:00 2001 From: Sean Paul Date: Mon, 17 Jun 2019 16:12:57 -0400 Subject: drm/msm/dsi: Move dsi panel init into modeset init path Since deferred probe from the modeset init path now works, we can move the panel initialization from detect() into connector init. This avoids doing work in detect() and hopefully will result in a more deterministic boot sequence between devices with a dsi panel, and those with an external bridge. Reviewed-by: Rob Clark Signed-off-by: Sean Paul Link: https://patchwork.freedesktop.org/patch/msgid/20190617201301.133275-9-sean@poorly.run --- drivers/gpu/drm/msm/dsi/dsi_manager.c | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) (limited to 'drivers/gpu/drm/msm/dsi/dsi_manager.c') diff --git a/drivers/gpu/drm/msm/dsi/dsi_manager.c b/drivers/gpu/drm/msm/dsi/dsi_manager.c index a48a54005f50..630af00bbe9a 100644 --- a/drivers/gpu/drm/msm/dsi/dsi_manager.c +++ b/drivers/gpu/drm/msm/dsi/dsi_manager.c @@ -312,13 +312,6 @@ static enum drm_connector_status dsi_mgr_connector_detect( int id = dsi_mgr_connector_get_id(connector); struct msm_dsi *msm_dsi = dsi_mgr_get_dsi(id); - DBG("id=%d", id); - if (!msm_dsi->panel) { - int ret = msm_dsi_manager_panel_init(connector, id); - if (ret) - return connector_status_disconnected; - } - return msm_dsi->panel ? connector_status_connected : connector_status_disconnected; } @@ -631,7 +624,17 @@ struct drm_connector *msm_dsi_manager_connector_init(u8 id) drm_connector_attach_encoder(connector, msm_dsi->encoder); + ret = msm_dsi_manager_panel_init(connector, id); + if (ret) { + DRM_DEV_ERROR(msm_dsi->dev->dev, "init panel failed %d\n", ret); + goto fail; + } + return connector; + +fail: + connector->funcs->destroy(msm_dsi->connector); + return ERR_PTR(ret); } bool msm_dsi_manager_validate_current_config(u8 id) -- cgit v1.2.3 From 03436e3ec69c8e026224a5f172e5d0431f722305 Mon Sep 17 00:00:00 2001 From: Sean Paul Date: Mon, 17 Jun 2019 16:12:58 -0400 Subject: drm/msm/dsi: Move setup_encoder to modeset_init Now that the panel probe/setup is in the modeset path, we can call dsi_manager_setup_encoder() in a common place for both internal and external bridge setups. Reviewed-by: Rob Clark Signed-off-by: Sean Paul Link: https://patchwork.freedesktop.org/patch/msgid/20190617201301.133275-10-sean@poorly.run --- drivers/gpu/drm/msm/dsi/dsi.c | 2 ++ drivers/gpu/drm/msm/dsi/dsi.h | 2 +- drivers/gpu/drm/msm/dsi/dsi_host.c | 2 -- drivers/gpu/drm/msm/dsi/dsi_manager.c | 37 ++--------------------------------- 4 files changed, 5 insertions(+), 38 deletions(-) (limited to 'drivers/gpu/drm/msm/dsi/dsi_manager.c') diff --git a/drivers/gpu/drm/msm/dsi/dsi.c b/drivers/gpu/drm/msm/dsi/dsi.c index 7b2a1e6a8810..d45b0a40aaf3 100644 --- a/drivers/gpu/drm/msm/dsi/dsi.c +++ b/drivers/gpu/drm/msm/dsi/dsi.c @@ -250,6 +250,8 @@ int msm_dsi_modeset_init(struct msm_dsi *msm_dsi, struct drm_device *dev, goto fail; } + msm_dsi_manager_setup_encoder(msm_dsi->id); + priv->bridges[priv->num_bridges++] = msm_dsi->bridge; priv->connectors[priv->num_connectors++] = msm_dsi->connector; diff --git a/drivers/gpu/drm/msm/dsi/dsi.h b/drivers/gpu/drm/msm/dsi/dsi.h index f8a611725f2e..53bb124e8259 100644 --- a/drivers/gpu/drm/msm/dsi/dsi.h +++ b/drivers/gpu/drm/msm/dsi/dsi.h @@ -96,7 +96,7 @@ struct drm_connector *msm_dsi_manager_connector_init(u8 id); struct drm_connector *msm_dsi_manager_ext_bridge_init(u8 id); int msm_dsi_manager_cmd_xfer(int id, const struct mipi_dsi_msg *msg); bool msm_dsi_manager_cmd_xfer_trigger(int id, u32 dma_base, u32 len); -void msm_dsi_manager_attach_dsi_device(int id); +void msm_dsi_manager_setup_encoder(int id); int msm_dsi_manager_register(struct msm_dsi *msm_dsi); void msm_dsi_manager_unregister(struct msm_dsi *msm_dsi); bool msm_dsi_manager_validate_current_config(u8 id); diff --git a/drivers/gpu/drm/msm/dsi/dsi_host.c b/drivers/gpu/drm/msm/dsi/dsi_host.c index f6eb91cf97e6..1ae2f5522979 100644 --- a/drivers/gpu/drm/msm/dsi/dsi_host.c +++ b/drivers/gpu/drm/msm/dsi/dsi_host.c @@ -1598,8 +1598,6 @@ static int dsi_host_attach(struct mipi_dsi_host *host, msm_host->format = dsi->format; msm_host->mode_flags = dsi->mode_flags; - msm_dsi_manager_attach_dsi_device(msm_host->id); - /* Some gpios defined in panel DT need to be controlled by host */ ret = dsi_host_init_panel_gpios(msm_host, &dsi->dev); if (ret) diff --git a/drivers/gpu/drm/msm/dsi/dsi_manager.c b/drivers/gpu/drm/msm/dsi/dsi_manager.c index 630af00bbe9a..ff39ce6150ad 100644 --- a/drivers/gpu/drm/msm/dsi/dsi_manager.c +++ b/drivers/gpu/drm/msm/dsi/dsi_manager.c @@ -239,7 +239,7 @@ static bool dsi_mgr_is_cmd_mode(struct msm_dsi *msm_dsi) return !(host_flags & MIPI_DSI_MODE_VIDEO); } -static void msm_dsi_manager_setup_encoder(int id) +void msm_dsi_manager_setup_encoder(int id) { struct msm_dsi *msm_dsi = dsi_mgr_get_dsi(id); struct msm_drm_private *priv = msm_dsi->dev->dev_private; @@ -280,12 +280,7 @@ static int msm_dsi_manager_panel_init(struct drm_connector *conn, u8 id) return PTR_ERR(panel); } - if (!panel) - return 0; - - msm_dsi_manager_setup_encoder(id); - - if (!IS_DUAL_DSI()) + if (!panel || !IS_DUAL_DSI()) goto out; drm_object_attach_property(&conn->base, @@ -790,34 +785,6 @@ bool msm_dsi_manager_cmd_xfer_trigger(int id, u32 dma_base, u32 len) return true; } -void msm_dsi_manager_attach_dsi_device(int id) -{ - struct msm_dsi *msm_dsi = dsi_mgr_get_dsi(id); - struct drm_device *dev; - - /* - * drm_device pointer is assigned to msm_dsi only in the modeset_init - * path. If mipi_dsi_attach() happens in DSI driver's probe path - * (generally the case when we're connected to a drm_panel of the type - * mipi_dsi_device), this would be NULL. In such cases, try to set the - * encoder mode in the DSI connector's detect() op. - * - * msm_dsi pointer is assigned to a valid dsi device only when - * msm_dsi_manager_register() succeeds. When panel hasnt probed yet - * dsi_mgr_setup_components() could potentially return -EDEFER and - * assign the msm_dsi->dev to NULL. When the panel now probes and calls - * mipi_dsi_attach(), this will call msm_dsi_manager_attach_dsi_device() - * which will result in a NULL pointer dereference - */ - - dev = msm_dsi ? msm_dsi->dev : NULL; - - if (!dev) - return; - - msm_dsi_manager_setup_encoder(id); -} - int msm_dsi_manager_register(struct msm_dsi *msm_dsi) { struct msm_dsi_manager *msm_dsim = &msm_dsim_glb; -- cgit v1.2.3