diff options
Diffstat (limited to 'drivers/gpu/drm/msm/dsi/dsi.c')
| -rw-r--r-- | drivers/gpu/drm/msm/dsi/dsi.c | 108 |
1 files changed, 42 insertions, 66 deletions
diff --git a/drivers/gpu/drm/msm/dsi/dsi.c b/drivers/gpu/drm/msm/dsi/dsi.c index 052548883d27..d8bb40ef820e 100644 --- a/drivers/gpu/drm/msm/dsi/dsi.c +++ b/drivers/gpu/drm/msm/dsi/dsi.c @@ -5,19 +5,21 @@ #include "dsi.h" -struct drm_encoder *msm_dsi_get_encoder(struct msm_dsi *msm_dsi) +bool msm_dsi_is_cmd_mode(struct msm_dsi *msm_dsi) { - if (!msm_dsi || !msm_dsi_device_connected(msm_dsi)) - return NULL; + unsigned long host_flags = msm_dsi_host_get_mode_flags(msm_dsi->host); - return msm_dsi->encoder; + return !(host_flags & MIPI_DSI_MODE_VIDEO); } -bool msm_dsi_is_cmd_mode(struct msm_dsi *msm_dsi) +struct drm_dsc_config *msm_dsi_get_dsc_config(struct msm_dsi *msm_dsi) { - unsigned long host_flags = msm_dsi_host_get_mode_flags(msm_dsi->host); + return msm_dsi_host_get_dsc_config(msm_dsi->host); +} - return !(host_flags & MIPI_DSI_MODE_VIDEO); +bool msm_dsi_wide_bus_enabled(struct msm_dsi *msm_dsi) +{ + return msm_dsi_host_is_wide_bus_enabled(msm_dsi->host); } static int dsi_get_phy(struct msm_dsi *msm_dsi) @@ -40,7 +42,12 @@ static int dsi_get_phy(struct msm_dsi *msm_dsi) of_node_put(phy_node); - if (!phy_pdev || !msm_dsi->phy) { + if (!phy_pdev) { + DRM_DEV_ERROR(&pdev->dev, "%s: phy driver is not ready\n", __func__); + return -EPROBE_DEFER; + } + if (!msm_dsi->phy) { + put_device(&phy_pdev->dev); DRM_DEV_ERROR(&pdev->dev, "%s: phy driver is not ready\n", __func__); return -EPROBE_DEFER; } @@ -113,7 +120,23 @@ static int dsi_bind(struct device *dev, struct device *master, void *data) struct msm_drm_private *priv = dev_get_drvdata(master); struct msm_dsi *msm_dsi = dev_get_drvdata(dev); - priv->dsi[msm_dsi->id] = msm_dsi; + /* + * Next bridge doesn't exist for the secondary DSI host in a bonded + * pair. + */ + if (!msm_dsi_is_bonded_dsi(msm_dsi) || + msm_dsi_is_master_dsi(msm_dsi)) { + struct drm_bridge *ext_bridge; + + ext_bridge = devm_drm_of_get_bridge(&msm_dsi->pdev->dev, + msm_dsi->pdev->dev.of_node, 1, 0); + if (IS_ERR(ext_bridge)) + return PTR_ERR(ext_bridge); + + msm_dsi->next_bridge = ext_bridge; + } + + priv->kms->dsi[msm_dsi->id] = msm_dsi; return 0; } @@ -124,7 +147,8 @@ static void dsi_unbind(struct device *dev, struct device *master, struct msm_drm_private *priv = dev_get_drvdata(master); struct msm_dsi *msm_dsi = dev_get_drvdata(dev); - priv->dsi[msm_dsi->id] = NULL; + msm_dsi_tx_buf_free(msm_dsi->host); + priv->kms->dsi[msm_dsi->id] = NULL; } static const struct component_ops dsi_ops = { @@ -159,18 +183,19 @@ static int dsi_dev_probe(struct platform_device *pdev) return 0; } -static int dsi_dev_remove(struct platform_device *pdev) +static void dsi_dev_remove(struct platform_device *pdev) { struct msm_dsi *msm_dsi = platform_get_drvdata(pdev); DBG(""); dsi_destroy(msm_dsi); - - return 0; } static const struct of_device_id dt_match[] = { { .compatible = "qcom,mdss-dsi-ctrl" }, + + /* Deprecated, don't use */ + { .compatible = "qcom,dsi-ctrl-6g-qcm2290" }, {} }; @@ -207,20 +232,14 @@ void __exit msm_dsi_unregister(void) int msm_dsi_modeset_init(struct msm_dsi *msm_dsi, struct drm_device *dev, struct drm_encoder *encoder) { - struct msm_drm_private *priv; - struct drm_bridge *ext_bridge; int ret; - if (WARN_ON(!encoder) || WARN_ON(!msm_dsi) || WARN_ON(!dev)) - return -EINVAL; - - priv = dev->dev_private; msm_dsi->dev = dev; ret = msm_dsi_host_modeset_init(msm_dsi->host, dev); if (ret) { DRM_DEV_ERROR(dev->dev, "failed to modeset init host: %d\n", ret); - goto fail; + return ret; } if (msm_dsi_is_bonded_dsi(msm_dsi) && @@ -232,57 +251,14 @@ int msm_dsi_modeset_init(struct msm_dsi *msm_dsi, struct drm_device *dev, return 0; } - msm_dsi->encoder = encoder; - - msm_dsi->bridge = msm_dsi_manager_bridge_init(msm_dsi->id); - if (IS_ERR(msm_dsi->bridge)) { - ret = PTR_ERR(msm_dsi->bridge); - DRM_DEV_ERROR(dev->dev, "failed to create dsi bridge: %d\n", ret); - msm_dsi->bridge = NULL; - goto fail; - } - - /* - * check if the dsi encoder output is connected to a panel or an - * external bridge. We create a connector only if we're connected to a - * drm_panel device. When we're connected to an external bridge, we - * assume that the drm_bridge driver will create the connector itself. - */ - ext_bridge = msm_dsi_host_get_bridge(msm_dsi->host); - - if (ext_bridge) - msm_dsi->connector = - msm_dsi_manager_ext_bridge_init(msm_dsi->id); - else - msm_dsi->connector = - msm_dsi_manager_connector_init(msm_dsi->id); - - if (IS_ERR(msm_dsi->connector)) { - ret = PTR_ERR(msm_dsi->connector); + ret = msm_dsi_manager_connector_init(msm_dsi, encoder); + if (ret) { DRM_DEV_ERROR(dev->dev, "failed to create dsi connector: %d\n", ret); - msm_dsi->connector = NULL; - goto fail; + return ret; } - priv->bridges[priv->num_bridges++] = msm_dsi->bridge; - priv->connectors[priv->num_connectors++] = msm_dsi->connector; - return 0; -fail: - /* bridge/connector are normally destroyed by drm: */ - if (msm_dsi->bridge) { - msm_dsi_manager_bridge_destroy(msm_dsi->bridge); - msm_dsi->bridge = NULL; - } - - /* don't destroy connector if we didn't make it */ - if (msm_dsi->connector && !msm_dsi->external_bridge) - msm_dsi->connector->funcs->destroy(msm_dsi->connector); - - msm_dsi->connector = NULL; - - return ret; } void msm_dsi_snapshot(struct msm_disp_state *disp_state, struct msm_dsi *msm_dsi) |
