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) { dev_err(dev->dev, "failed to modeset init host: %d\n", ret); goto fail; } if (!msm_dsi_manager_validate_current_config(msm_dsi->id)) goto fail; 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); dev_err(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); dev_err(dev->dev, "failed to create dsi connector: %d\n", ret); msm_dsi->connector = NULL; goto fail; } 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; }
int msm_dsi_modeset_init(struct msm_dsi *msm_dsi, struct drm_device *dev, struct drm_encoder *encoders[MSM_DSI_ENCODER_NUM]) { struct msm_drm_private *priv = dev->dev_private; struct drm_bridge *ext_bridge; int ret, i; if (WARN_ON(!encoders[MSM_DSI_VIDEO_ENCODER_ID] || !encoders[MSM_DSI_CMD_ENCODER_ID])) return -EINVAL; msm_dsi->dev = dev; ret = msm_dsi_host_modeset_init(msm_dsi->host, dev); if (ret) { dev_err(dev->dev, "failed to modeset init host: %d\n", ret); goto fail; } msm_dsi->bridge = msm_dsi_manager_bridge_init(msm_dsi->id); if (IS_ERR(msm_dsi->bridge)) { ret = PTR_ERR(msm_dsi->bridge); dev_err(dev->dev, "failed to create dsi bridge: %d\n", ret); msm_dsi->bridge = NULL; goto fail; } for (i = 0; i < MSM_DSI_ENCODER_NUM; i++) { encoders[i]->bridge = msm_dsi->bridge; msm_dsi->encoders[i] = encoders[i]; } /* * 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); dev_err(dev->dev, "failed to create dsi connector: %d\n", ret); msm_dsi->connector = NULL; goto fail; } priv->bridges[priv->num_bridges++] = msm_dsi->bridge; priv->connectors[priv->num_connectors++] = msm_dsi->connector; return 0; fail: if (msm_dsi) { /* 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; }