Commit 6afb7721 authored by Maciej Purski's avatar Maciej Purski Committed by Inki Dae

drm/exynos: move connector creation to attach callback

The current implementation assumes that the only possible peripheral
device for DSIM is a panel. Using an output bridge child device
should also be possible.

If an output bridge is available, don't create a new connector.
Instead, call drm_bridge_attach() and set encoder's bridge to NULL
in order to avoid an out bridge from being visible by the framework, as
the DSI bus needs control on enabling its child output bridge.

Such sequence is required by Toshiba TC358764 bridge, which is a DSI
peripheral bridge device.

changed in v5:
- detach bridge in mipi_dsi detach callback
Signed-off-by: default avatarMaciej Purski <m.purski@samsung.com>
[ a.hajda@samsung.com: v5 ]
Signed-off-by: default avatarAndrzej Hajda <a.hajda@samsung.com>
Manually merged due to merge conflict.
Signed-off-by: default avatarInki Dae <inki.dae@samsung.com>
parent 2782622e
...@@ -255,6 +255,7 @@ struct exynos_dsi { ...@@ -255,6 +255,7 @@ struct exynos_dsi {
struct mipi_dsi_host dsi_host; struct mipi_dsi_host dsi_host;
struct drm_connector connector; struct drm_connector connector;
struct drm_panel *panel; struct drm_panel *panel;
struct drm_bridge *out_bridge;
struct device *dev; struct device *dev;
void __iomem *reg_base; void __iomem *reg_base;
...@@ -1499,7 +1500,30 @@ static int exynos_dsi_host_attach(struct mipi_dsi_host *host, ...@@ -1499,7 +1500,30 @@ static int exynos_dsi_host_attach(struct mipi_dsi_host *host,
struct mipi_dsi_device *device) struct mipi_dsi_device *device)
{ {
struct exynos_dsi *dsi = host_to_dsi(host); struct exynos_dsi *dsi = host_to_dsi(host);
struct drm_device *drm = dsi->connector.dev; struct drm_encoder *encoder = &dsi->encoder;
struct drm_device *drm = encoder->dev;
struct drm_bridge *out_bridge;
out_bridge = of_drm_find_bridge(device->dev.of_node);
if (out_bridge) {
drm_bridge_attach(encoder, out_bridge, NULL);
dsi->out_bridge = out_bridge;
encoder->bridge = NULL;
} else {
int ret = exynos_dsi_create_connector(encoder);
if (ret) {
DRM_ERROR("failed to create connector ret = %d\n", ret);
drm_encoder_cleanup(encoder);
return ret;
}
dsi->panel = of_drm_find_panel(device->dev.of_node);
if (dsi->panel) {
drm_panel_attach(dsi->panel, &dsi->connector);
dsi->connector.status = connector_status_connected;
}
}
/* /*
* This is a temporary solution and should be made by more generic way. * This is a temporary solution and should be made by more generic way.
...@@ -1518,14 +1542,6 @@ static int exynos_dsi_host_attach(struct mipi_dsi_host *host, ...@@ -1518,14 +1542,6 @@ static int exynos_dsi_host_attach(struct mipi_dsi_host *host,
dsi->lanes = device->lanes; dsi->lanes = device->lanes;
dsi->format = device->format; dsi->format = device->format;
dsi->mode_flags = device->mode_flags; dsi->mode_flags = device->mode_flags;
dsi->panel = of_drm_find_panel(device->dev.of_node);
if (IS_ERR(dsi->panel))
dsi->panel = NULL;
if (dsi->panel) {
drm_panel_attach(dsi->panel, &dsi->connector);
dsi->connector.status = connector_status_connected;
}
exynos_drm_crtc_get_by_type(drm, EXYNOS_DISPLAY_TYPE_LCD)->i80_mode = exynos_drm_crtc_get_by_type(drm, EXYNOS_DISPLAY_TYPE_LCD)->i80_mode =
!(dsi->mode_flags & MIPI_DSI_MODE_VIDEO); !(dsi->mode_flags & MIPI_DSI_MODE_VIDEO);
...@@ -1541,19 +1557,21 @@ static int exynos_dsi_host_detach(struct mipi_dsi_host *host, ...@@ -1541,19 +1557,21 @@ static int exynos_dsi_host_detach(struct mipi_dsi_host *host,
struct mipi_dsi_device *device) struct mipi_dsi_device *device)
{ {
struct exynos_dsi *dsi = host_to_dsi(host); struct exynos_dsi *dsi = host_to_dsi(host);
struct drm_device *drm = dsi->connector.dev; struct drm_device *drm = dsi->encoder.dev;
mutex_lock(&drm->mode_config.mutex);
if (dsi->panel) { if (dsi->panel) {
mutex_lock(&drm->mode_config.mutex);
exynos_dsi_disable(&dsi->encoder); exynos_dsi_disable(&dsi->encoder);
drm_panel_detach(dsi->panel); drm_panel_detach(dsi->panel);
dsi->panel = NULL; dsi->panel = NULL;
dsi->connector.status = connector_status_disconnected; dsi->connector.status = connector_status_disconnected;
mutex_unlock(&drm->mode_config.mutex);
} else {
if (dsi->out_bridge->funcs->detach)
dsi->out_bridge->funcs->detach(dsi->out_bridge);
dsi->out_bridge = NULL;
} }
mutex_unlock(&drm->mode_config.mutex);
if (drm->mode_config.poll_enabled) if (drm->mode_config.poll_enabled)
drm_kms_helper_hotplug_event(drm); drm_kms_helper_hotplug_event(drm);
...@@ -1657,13 +1675,6 @@ static int exynos_dsi_bind(struct device *dev, struct device *master, ...@@ -1657,13 +1675,6 @@ static int exynos_dsi_bind(struct device *dev, struct device *master,
if (ret < 0) if (ret < 0)
return ret; return ret;
ret = exynos_dsi_create_connector(encoder);
if (ret) {
DRM_ERROR("failed to create connector ret = %d\n", ret);
drm_encoder_cleanup(encoder);
return ret;
}
if (dsi->in_bridge_node) { if (dsi->in_bridge_node) {
in_bridge = of_drm_find_bridge(dsi->in_bridge_node); in_bridge = of_drm_find_bridge(dsi->in_bridge_node);
if (in_bridge) if (in_bridge)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment