Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 90910a65 authored by Heiko Stuebner's avatar Heiko Stuebner Committed by Andrzej Hajda
Browse files

drm/bridge/synopsys: dsi: add ability to have glue-specific attach and detach



With the regular means of adding the dsi-component in probe it creates
a race condition with the panel probing, as the panel device only gets
created after the dsi-bus got created.

When the panel-driver is build as a module it currently fails hard as the
panel cannot be probed directly:

dw_mipi_dsi_bind()
  __dw_mipi_dsi_probe()
    creates dsi bus
    creates panel device
    triggers panel module load
    panel not probed (module not loaded or panel probe slow)
  drm_bridge_attach
    fails with -EINVAL due to empty panel_bridge

Additionally the panel probing can run concurrently with dsi bringup
making it possible that the panel can already be found but dsi-attach
hasn't finished running.

To solve that cleanly we may want to only create the component after
the panel has finished probing, by calling component_add from the
host-attach dsi callback.

As that is specific to glue drivers, add a new struct for host_ops
so that glue drivers can tell the bridge to call specific functions
after the common host-attach and before the common host-detach run.

Suggested-by: default avatarAndrzej Hajda <a.hajda@samsung.com>
Reviewed-by: default avatarAndrzej Hajda <a.hajda@samsung.com>
Signed-off-by: default avatarHeiko Stuebner <heiko@sntech.de>
Signed-off-by: default avatarAndrzej Hajda <a.hajda@samsung.com>
Link: https://patchwork.freedesktop.org/patch/msgid/20181001123845.11818-4-heiko@sntech.de
parent f2b0e264
Loading
Loading
Loading
Loading
+15 −0
Original line number Original line Diff line number Diff line
@@ -270,6 +270,7 @@ static int dw_mipi_dsi_host_attach(struct mipi_dsi_host *host,
				   struct mipi_dsi_device *device)
				   struct mipi_dsi_device *device)
{
{
	struct dw_mipi_dsi *dsi = host_to_dsi(host);
	struct dw_mipi_dsi *dsi = host_to_dsi(host);
	const struct dw_mipi_dsi_plat_data *pdata = dsi->plat_data;
	struct drm_bridge *bridge;
	struct drm_bridge *bridge;
	struct drm_panel *panel;
	struct drm_panel *panel;
	int ret;
	int ret;
@@ -300,6 +301,12 @@ static int dw_mipi_dsi_host_attach(struct mipi_dsi_host *host,


	drm_bridge_add(&dsi->bridge);
	drm_bridge_add(&dsi->bridge);


	if (pdata->host_ops && pdata->host_ops->attach) {
		ret = pdata->host_ops->attach(pdata->priv_data, device);
		if (ret < 0)
			return ret;
	}

	return 0;
	return 0;
}
}


@@ -307,6 +314,14 @@ static int dw_mipi_dsi_host_detach(struct mipi_dsi_host *host,
				   struct mipi_dsi_device *device)
				   struct mipi_dsi_device *device)
{
{
	struct dw_mipi_dsi *dsi = host_to_dsi(host);
	struct dw_mipi_dsi *dsi = host_to_dsi(host);
	const struct dw_mipi_dsi_plat_data *pdata = dsi->plat_data;
	int ret;

	if (pdata->host_ops && pdata->host_ops->detach) {
		ret = pdata->host_ops->detach(pdata->priv_data, device);
		if (ret < 0)
			return ret;
	}


	drm_of_panel_bridge_remove(host->dev->of_node, 1, 0);
	drm_of_panel_bridge_remove(host->dev->of_node, 1, 0);


+8 −0
Original line number Original line Diff line number Diff line
@@ -19,6 +19,13 @@ struct dw_mipi_dsi_phy_ops {
			     unsigned int *lane_mbps);
			     unsigned int *lane_mbps);
};
};


struct dw_mipi_dsi_host_ops {
	int (*attach)(void *priv_data,
		      struct mipi_dsi_device *dsi);
	int (*detach)(void *priv_data,
		      struct mipi_dsi_device *dsi);
};

struct dw_mipi_dsi_plat_data {
struct dw_mipi_dsi_plat_data {
	void __iomem *base;
	void __iomem *base;
	unsigned int max_data_lanes;
	unsigned int max_data_lanes;
@@ -27,6 +34,7 @@ struct dw_mipi_dsi_plat_data {
					   const struct drm_display_mode *mode);
					   const struct drm_display_mode *mode);


	const struct dw_mipi_dsi_phy_ops *phy_ops;
	const struct dw_mipi_dsi_phy_ops *phy_ops;
	const struct dw_mipi_dsi_host_ops *host_ops;


	void *priv_data;
	void *priv_data;
};
};