162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-only
262306a36Sopenharmony_ci/*
362306a36Sopenharmony_ci * Copyright (c) 2015, The Linux Foundation. All rights reserved.
462306a36Sopenharmony_ci */
562306a36Sopenharmony_ci
662306a36Sopenharmony_ci#include "drm/drm_bridge_connector.h"
762306a36Sopenharmony_ci
862306a36Sopenharmony_ci#include "msm_kms.h"
962306a36Sopenharmony_ci#include "dsi.h"
1062306a36Sopenharmony_ci
1162306a36Sopenharmony_ci#define DSI_CLOCK_MASTER	DSI_0
1262306a36Sopenharmony_ci#define DSI_CLOCK_SLAVE		DSI_1
1362306a36Sopenharmony_ci
1462306a36Sopenharmony_ci#define DSI_LEFT		DSI_0
1562306a36Sopenharmony_ci#define DSI_RIGHT		DSI_1
1662306a36Sopenharmony_ci
1762306a36Sopenharmony_ci/* According to the current drm framework sequence, take the encoder of
1862306a36Sopenharmony_ci * DSI_1 as master encoder
1962306a36Sopenharmony_ci */
2062306a36Sopenharmony_ci#define DSI_ENCODER_MASTER	DSI_1
2162306a36Sopenharmony_ci#define DSI_ENCODER_SLAVE	DSI_0
2262306a36Sopenharmony_ci
2362306a36Sopenharmony_cistruct msm_dsi_manager {
2462306a36Sopenharmony_ci	struct msm_dsi *dsi[DSI_MAX];
2562306a36Sopenharmony_ci
2662306a36Sopenharmony_ci	bool is_bonded_dsi;
2762306a36Sopenharmony_ci	bool is_sync_needed;
2862306a36Sopenharmony_ci	int master_dsi_link_id;
2962306a36Sopenharmony_ci};
3062306a36Sopenharmony_ci
3162306a36Sopenharmony_cistatic struct msm_dsi_manager msm_dsim_glb;
3262306a36Sopenharmony_ci
3362306a36Sopenharmony_ci#define IS_BONDED_DSI()		(msm_dsim_glb.is_bonded_dsi)
3462306a36Sopenharmony_ci#define IS_SYNC_NEEDED()	(msm_dsim_glb.is_sync_needed)
3562306a36Sopenharmony_ci#define IS_MASTER_DSI_LINK(id)	(msm_dsim_glb.master_dsi_link_id == id)
3662306a36Sopenharmony_ci
3762306a36Sopenharmony_cistatic inline struct msm_dsi *dsi_mgr_get_dsi(int id)
3862306a36Sopenharmony_ci{
3962306a36Sopenharmony_ci	return msm_dsim_glb.dsi[id];
4062306a36Sopenharmony_ci}
4162306a36Sopenharmony_ci
4262306a36Sopenharmony_cistatic inline struct msm_dsi *dsi_mgr_get_other_dsi(int id)
4362306a36Sopenharmony_ci{
4462306a36Sopenharmony_ci	return msm_dsim_glb.dsi[(id + 1) % DSI_MAX];
4562306a36Sopenharmony_ci}
4662306a36Sopenharmony_ci
4762306a36Sopenharmony_cistatic int dsi_mgr_parse_of(struct device_node *np, int id)
4862306a36Sopenharmony_ci{
4962306a36Sopenharmony_ci	struct msm_dsi_manager *msm_dsim = &msm_dsim_glb;
5062306a36Sopenharmony_ci
5162306a36Sopenharmony_ci	/* We assume 2 dsi nodes have the same information of bonded dsi and
5262306a36Sopenharmony_ci	 * sync-mode, and only one node specifies master in case of bonded mode.
5362306a36Sopenharmony_ci	 */
5462306a36Sopenharmony_ci	if (!msm_dsim->is_bonded_dsi)
5562306a36Sopenharmony_ci		msm_dsim->is_bonded_dsi = of_property_read_bool(np, "qcom,dual-dsi-mode");
5662306a36Sopenharmony_ci
5762306a36Sopenharmony_ci	if (msm_dsim->is_bonded_dsi) {
5862306a36Sopenharmony_ci		if (of_property_read_bool(np, "qcom,master-dsi"))
5962306a36Sopenharmony_ci			msm_dsim->master_dsi_link_id = id;
6062306a36Sopenharmony_ci		if (!msm_dsim->is_sync_needed)
6162306a36Sopenharmony_ci			msm_dsim->is_sync_needed = of_property_read_bool(
6262306a36Sopenharmony_ci					np, "qcom,sync-dual-dsi");
6362306a36Sopenharmony_ci	}
6462306a36Sopenharmony_ci
6562306a36Sopenharmony_ci	return 0;
6662306a36Sopenharmony_ci}
6762306a36Sopenharmony_ci
6862306a36Sopenharmony_cistatic int dsi_mgr_setup_components(int id)
6962306a36Sopenharmony_ci{
7062306a36Sopenharmony_ci	struct msm_dsi *msm_dsi = dsi_mgr_get_dsi(id);
7162306a36Sopenharmony_ci	struct msm_dsi *other_dsi = dsi_mgr_get_other_dsi(id);
7262306a36Sopenharmony_ci	struct msm_dsi *clk_master_dsi = dsi_mgr_get_dsi(DSI_CLOCK_MASTER);
7362306a36Sopenharmony_ci	struct msm_dsi *clk_slave_dsi = dsi_mgr_get_dsi(DSI_CLOCK_SLAVE);
7462306a36Sopenharmony_ci	int ret;
7562306a36Sopenharmony_ci
7662306a36Sopenharmony_ci	if (!IS_BONDED_DSI()) {
7762306a36Sopenharmony_ci		ret = msm_dsi_host_register(msm_dsi->host);
7862306a36Sopenharmony_ci		if (ret)
7962306a36Sopenharmony_ci			return ret;
8062306a36Sopenharmony_ci
8162306a36Sopenharmony_ci		msm_dsi_phy_set_usecase(msm_dsi->phy, MSM_DSI_PHY_STANDALONE);
8262306a36Sopenharmony_ci		msm_dsi_host_set_phy_mode(msm_dsi->host, msm_dsi->phy);
8362306a36Sopenharmony_ci	} else if (other_dsi) {
8462306a36Sopenharmony_ci		struct msm_dsi *master_link_dsi = IS_MASTER_DSI_LINK(id) ?
8562306a36Sopenharmony_ci							msm_dsi : other_dsi;
8662306a36Sopenharmony_ci		struct msm_dsi *slave_link_dsi = IS_MASTER_DSI_LINK(id) ?
8762306a36Sopenharmony_ci							other_dsi : msm_dsi;
8862306a36Sopenharmony_ci		/* Register slave host first, so that slave DSI device
8962306a36Sopenharmony_ci		 * has a chance to probe, and do not block the master
9062306a36Sopenharmony_ci		 * DSI device's probe.
9162306a36Sopenharmony_ci		 * Also, do not check defer for the slave host,
9262306a36Sopenharmony_ci		 * because only master DSI device adds the panel to global
9362306a36Sopenharmony_ci		 * panel list. The panel's device is the master DSI device.
9462306a36Sopenharmony_ci		 */
9562306a36Sopenharmony_ci		ret = msm_dsi_host_register(slave_link_dsi->host);
9662306a36Sopenharmony_ci		if (ret)
9762306a36Sopenharmony_ci			return ret;
9862306a36Sopenharmony_ci		ret = msm_dsi_host_register(master_link_dsi->host);
9962306a36Sopenharmony_ci		if (ret)
10062306a36Sopenharmony_ci			return ret;
10162306a36Sopenharmony_ci
10262306a36Sopenharmony_ci		/* PLL0 is to drive both 2 DSI link clocks in bonded DSI mode. */
10362306a36Sopenharmony_ci		msm_dsi_phy_set_usecase(clk_master_dsi->phy,
10462306a36Sopenharmony_ci					MSM_DSI_PHY_MASTER);
10562306a36Sopenharmony_ci		msm_dsi_phy_set_usecase(clk_slave_dsi->phy,
10662306a36Sopenharmony_ci					MSM_DSI_PHY_SLAVE);
10762306a36Sopenharmony_ci		msm_dsi_host_set_phy_mode(msm_dsi->host, msm_dsi->phy);
10862306a36Sopenharmony_ci		msm_dsi_host_set_phy_mode(other_dsi->host, other_dsi->phy);
10962306a36Sopenharmony_ci	}
11062306a36Sopenharmony_ci
11162306a36Sopenharmony_ci	return 0;
11262306a36Sopenharmony_ci}
11362306a36Sopenharmony_ci
11462306a36Sopenharmony_cistatic int enable_phy(struct msm_dsi *msm_dsi,
11562306a36Sopenharmony_ci		      struct msm_dsi_phy_shared_timings *shared_timings)
11662306a36Sopenharmony_ci{
11762306a36Sopenharmony_ci	struct msm_dsi_phy_clk_request clk_req;
11862306a36Sopenharmony_ci	bool is_bonded_dsi = IS_BONDED_DSI();
11962306a36Sopenharmony_ci
12062306a36Sopenharmony_ci	msm_dsi_host_get_phy_clk_req(msm_dsi->host, &clk_req, is_bonded_dsi);
12162306a36Sopenharmony_ci
12262306a36Sopenharmony_ci	return msm_dsi_phy_enable(msm_dsi->phy, &clk_req, shared_timings);
12362306a36Sopenharmony_ci}
12462306a36Sopenharmony_ci
12562306a36Sopenharmony_cistatic int
12662306a36Sopenharmony_cidsi_mgr_phy_enable(int id,
12762306a36Sopenharmony_ci		   struct msm_dsi_phy_shared_timings shared_timings[DSI_MAX])
12862306a36Sopenharmony_ci{
12962306a36Sopenharmony_ci	struct msm_dsi *msm_dsi = dsi_mgr_get_dsi(id);
13062306a36Sopenharmony_ci	struct msm_dsi *mdsi = dsi_mgr_get_dsi(DSI_CLOCK_MASTER);
13162306a36Sopenharmony_ci	struct msm_dsi *sdsi = dsi_mgr_get_dsi(DSI_CLOCK_SLAVE);
13262306a36Sopenharmony_ci	int ret;
13362306a36Sopenharmony_ci
13462306a36Sopenharmony_ci	/* In case of bonded DSI, some registers in PHY1 have been programmed
13562306a36Sopenharmony_ci	 * during PLL0 clock's set_rate. The PHY1 reset called by host1 here
13662306a36Sopenharmony_ci	 * will silently reset those PHY1 registers. Therefore we need to reset
13762306a36Sopenharmony_ci	 * and enable both PHYs before any PLL clock operation.
13862306a36Sopenharmony_ci	 */
13962306a36Sopenharmony_ci	if (IS_BONDED_DSI() && mdsi && sdsi) {
14062306a36Sopenharmony_ci		if (!mdsi->phy_enabled && !sdsi->phy_enabled) {
14162306a36Sopenharmony_ci			msm_dsi_host_reset_phy(mdsi->host);
14262306a36Sopenharmony_ci			msm_dsi_host_reset_phy(sdsi->host);
14362306a36Sopenharmony_ci
14462306a36Sopenharmony_ci			ret = enable_phy(mdsi,
14562306a36Sopenharmony_ci					 &shared_timings[DSI_CLOCK_MASTER]);
14662306a36Sopenharmony_ci			if (ret)
14762306a36Sopenharmony_ci				return ret;
14862306a36Sopenharmony_ci			ret = enable_phy(sdsi,
14962306a36Sopenharmony_ci					 &shared_timings[DSI_CLOCK_SLAVE]);
15062306a36Sopenharmony_ci			if (ret) {
15162306a36Sopenharmony_ci				msm_dsi_phy_disable(mdsi->phy);
15262306a36Sopenharmony_ci				return ret;
15362306a36Sopenharmony_ci			}
15462306a36Sopenharmony_ci		}
15562306a36Sopenharmony_ci	} else {
15662306a36Sopenharmony_ci		msm_dsi_host_reset_phy(msm_dsi->host);
15762306a36Sopenharmony_ci		ret = enable_phy(msm_dsi, &shared_timings[id]);
15862306a36Sopenharmony_ci		if (ret)
15962306a36Sopenharmony_ci			return ret;
16062306a36Sopenharmony_ci	}
16162306a36Sopenharmony_ci
16262306a36Sopenharmony_ci	msm_dsi->phy_enabled = true;
16362306a36Sopenharmony_ci
16462306a36Sopenharmony_ci	return 0;
16562306a36Sopenharmony_ci}
16662306a36Sopenharmony_ci
16762306a36Sopenharmony_cistatic void dsi_mgr_phy_disable(int id)
16862306a36Sopenharmony_ci{
16962306a36Sopenharmony_ci	struct msm_dsi *msm_dsi = dsi_mgr_get_dsi(id);
17062306a36Sopenharmony_ci	struct msm_dsi *mdsi = dsi_mgr_get_dsi(DSI_CLOCK_MASTER);
17162306a36Sopenharmony_ci	struct msm_dsi *sdsi = dsi_mgr_get_dsi(DSI_CLOCK_SLAVE);
17262306a36Sopenharmony_ci
17362306a36Sopenharmony_ci	/* disable DSI phy
17462306a36Sopenharmony_ci	 * In bonded dsi configuration, the phy should be disabled for the
17562306a36Sopenharmony_ci	 * first controller only when the second controller is disabled.
17662306a36Sopenharmony_ci	 */
17762306a36Sopenharmony_ci	msm_dsi->phy_enabled = false;
17862306a36Sopenharmony_ci	if (IS_BONDED_DSI() && mdsi && sdsi) {
17962306a36Sopenharmony_ci		if (!mdsi->phy_enabled && !sdsi->phy_enabled) {
18062306a36Sopenharmony_ci			msm_dsi_phy_disable(sdsi->phy);
18162306a36Sopenharmony_ci			msm_dsi_phy_disable(mdsi->phy);
18262306a36Sopenharmony_ci		}
18362306a36Sopenharmony_ci	} else {
18462306a36Sopenharmony_ci		msm_dsi_phy_disable(msm_dsi->phy);
18562306a36Sopenharmony_ci	}
18662306a36Sopenharmony_ci}
18762306a36Sopenharmony_ci
18862306a36Sopenharmony_cistruct dsi_bridge {
18962306a36Sopenharmony_ci	struct drm_bridge base;
19062306a36Sopenharmony_ci	int id;
19162306a36Sopenharmony_ci};
19262306a36Sopenharmony_ci
19362306a36Sopenharmony_ci#define to_dsi_bridge(x) container_of(x, struct dsi_bridge, base)
19462306a36Sopenharmony_ci
19562306a36Sopenharmony_cistatic int dsi_mgr_bridge_get_id(struct drm_bridge *bridge)
19662306a36Sopenharmony_ci{
19762306a36Sopenharmony_ci	struct dsi_bridge *dsi_bridge = to_dsi_bridge(bridge);
19862306a36Sopenharmony_ci	return dsi_bridge->id;
19962306a36Sopenharmony_ci}
20062306a36Sopenharmony_ci
20162306a36Sopenharmony_cistatic void msm_dsi_manager_set_split_display(u8 id)
20262306a36Sopenharmony_ci{
20362306a36Sopenharmony_ci	struct msm_dsi *msm_dsi = dsi_mgr_get_dsi(id);
20462306a36Sopenharmony_ci	struct msm_dsi *other_dsi = dsi_mgr_get_other_dsi(id);
20562306a36Sopenharmony_ci	struct msm_drm_private *priv = msm_dsi->dev->dev_private;
20662306a36Sopenharmony_ci	struct msm_kms *kms = priv->kms;
20762306a36Sopenharmony_ci	struct msm_dsi *master_dsi, *slave_dsi;
20862306a36Sopenharmony_ci
20962306a36Sopenharmony_ci	if (IS_BONDED_DSI() && !IS_MASTER_DSI_LINK(id)) {
21062306a36Sopenharmony_ci		master_dsi = other_dsi;
21162306a36Sopenharmony_ci		slave_dsi = msm_dsi;
21262306a36Sopenharmony_ci	} else {
21362306a36Sopenharmony_ci		master_dsi = msm_dsi;
21462306a36Sopenharmony_ci		slave_dsi = other_dsi;
21562306a36Sopenharmony_ci	}
21662306a36Sopenharmony_ci
21762306a36Sopenharmony_ci	if (!msm_dsi->external_bridge || !IS_BONDED_DSI())
21862306a36Sopenharmony_ci		return;
21962306a36Sopenharmony_ci
22062306a36Sopenharmony_ci	/*
22162306a36Sopenharmony_ci	 * Set split display info to kms once bonded DSI panel is connected to
22262306a36Sopenharmony_ci	 * both hosts.
22362306a36Sopenharmony_ci	 */
22462306a36Sopenharmony_ci	if (other_dsi && other_dsi->external_bridge && kms->funcs->set_split_display) {
22562306a36Sopenharmony_ci		kms->funcs->set_split_display(kms, master_dsi->encoder,
22662306a36Sopenharmony_ci					      slave_dsi->encoder,
22762306a36Sopenharmony_ci					      msm_dsi_is_cmd_mode(msm_dsi));
22862306a36Sopenharmony_ci	}
22962306a36Sopenharmony_ci}
23062306a36Sopenharmony_ci
23162306a36Sopenharmony_cistatic int dsi_mgr_bridge_power_on(struct drm_bridge *bridge)
23262306a36Sopenharmony_ci{
23362306a36Sopenharmony_ci	int id = dsi_mgr_bridge_get_id(bridge);
23462306a36Sopenharmony_ci	struct msm_dsi *msm_dsi = dsi_mgr_get_dsi(id);
23562306a36Sopenharmony_ci	struct msm_dsi *msm_dsi1 = dsi_mgr_get_dsi(DSI_1);
23662306a36Sopenharmony_ci	struct mipi_dsi_host *host = msm_dsi->host;
23762306a36Sopenharmony_ci	struct msm_dsi_phy_shared_timings phy_shared_timings[DSI_MAX];
23862306a36Sopenharmony_ci	bool is_bonded_dsi = IS_BONDED_DSI();
23962306a36Sopenharmony_ci	int ret;
24062306a36Sopenharmony_ci
24162306a36Sopenharmony_ci	DBG("id=%d", id);
24262306a36Sopenharmony_ci
24362306a36Sopenharmony_ci	ret = dsi_mgr_phy_enable(id, phy_shared_timings);
24462306a36Sopenharmony_ci	if (ret)
24562306a36Sopenharmony_ci		goto phy_en_fail;
24662306a36Sopenharmony_ci
24762306a36Sopenharmony_ci	ret = msm_dsi_host_power_on(host, &phy_shared_timings[id], is_bonded_dsi, msm_dsi->phy);
24862306a36Sopenharmony_ci	if (ret) {
24962306a36Sopenharmony_ci		pr_err("%s: power on host %d failed, %d\n", __func__, id, ret);
25062306a36Sopenharmony_ci		goto host_on_fail;
25162306a36Sopenharmony_ci	}
25262306a36Sopenharmony_ci
25362306a36Sopenharmony_ci	if (is_bonded_dsi && msm_dsi1) {
25462306a36Sopenharmony_ci		ret = msm_dsi_host_power_on(msm_dsi1->host,
25562306a36Sopenharmony_ci				&phy_shared_timings[DSI_1], is_bonded_dsi, msm_dsi1->phy);
25662306a36Sopenharmony_ci		if (ret) {
25762306a36Sopenharmony_ci			pr_err("%s: power on host1 failed, %d\n",
25862306a36Sopenharmony_ci							__func__, ret);
25962306a36Sopenharmony_ci			goto host1_on_fail;
26062306a36Sopenharmony_ci		}
26162306a36Sopenharmony_ci	}
26262306a36Sopenharmony_ci
26362306a36Sopenharmony_ci	/*
26462306a36Sopenharmony_ci	 * Enable before preparing the panel, disable after unpreparing, so
26562306a36Sopenharmony_ci	 * that the panel can communicate over the DSI link.
26662306a36Sopenharmony_ci	 */
26762306a36Sopenharmony_ci	msm_dsi_host_enable_irq(host);
26862306a36Sopenharmony_ci	if (is_bonded_dsi && msm_dsi1)
26962306a36Sopenharmony_ci		msm_dsi_host_enable_irq(msm_dsi1->host);
27062306a36Sopenharmony_ci
27162306a36Sopenharmony_ci	return 0;
27262306a36Sopenharmony_ci
27362306a36Sopenharmony_cihost1_on_fail:
27462306a36Sopenharmony_ci	msm_dsi_host_power_off(host);
27562306a36Sopenharmony_cihost_on_fail:
27662306a36Sopenharmony_ci	dsi_mgr_phy_disable(id);
27762306a36Sopenharmony_ciphy_en_fail:
27862306a36Sopenharmony_ci	return ret;
27962306a36Sopenharmony_ci}
28062306a36Sopenharmony_ci
28162306a36Sopenharmony_cistatic void dsi_mgr_bridge_power_off(struct drm_bridge *bridge)
28262306a36Sopenharmony_ci{
28362306a36Sopenharmony_ci	int id = dsi_mgr_bridge_get_id(bridge);
28462306a36Sopenharmony_ci	struct msm_dsi *msm_dsi = dsi_mgr_get_dsi(id);
28562306a36Sopenharmony_ci	struct msm_dsi *msm_dsi1 = dsi_mgr_get_dsi(DSI_1);
28662306a36Sopenharmony_ci	struct mipi_dsi_host *host = msm_dsi->host;
28762306a36Sopenharmony_ci	bool is_bonded_dsi = IS_BONDED_DSI();
28862306a36Sopenharmony_ci
28962306a36Sopenharmony_ci	msm_dsi_host_disable_irq(host);
29062306a36Sopenharmony_ci	if (is_bonded_dsi && msm_dsi1) {
29162306a36Sopenharmony_ci		msm_dsi_host_disable_irq(msm_dsi1->host);
29262306a36Sopenharmony_ci		msm_dsi_host_power_off(msm_dsi1->host);
29362306a36Sopenharmony_ci	}
29462306a36Sopenharmony_ci	msm_dsi_host_power_off(host);
29562306a36Sopenharmony_ci	dsi_mgr_phy_disable(id);
29662306a36Sopenharmony_ci}
29762306a36Sopenharmony_ci
29862306a36Sopenharmony_cistatic void dsi_mgr_bridge_pre_enable(struct drm_bridge *bridge)
29962306a36Sopenharmony_ci{
30062306a36Sopenharmony_ci	int id = dsi_mgr_bridge_get_id(bridge);
30162306a36Sopenharmony_ci	struct msm_dsi *msm_dsi = dsi_mgr_get_dsi(id);
30262306a36Sopenharmony_ci	struct msm_dsi *msm_dsi1 = dsi_mgr_get_dsi(DSI_1);
30362306a36Sopenharmony_ci	struct mipi_dsi_host *host = msm_dsi->host;
30462306a36Sopenharmony_ci	bool is_bonded_dsi = IS_BONDED_DSI();
30562306a36Sopenharmony_ci	int ret;
30662306a36Sopenharmony_ci
30762306a36Sopenharmony_ci	DBG("id=%d", id);
30862306a36Sopenharmony_ci	if (!msm_dsi_device_connected(msm_dsi))
30962306a36Sopenharmony_ci		return;
31062306a36Sopenharmony_ci
31162306a36Sopenharmony_ci	/* Do nothing with the host if it is slave-DSI in case of bonded DSI */
31262306a36Sopenharmony_ci	if (is_bonded_dsi && !IS_MASTER_DSI_LINK(id))
31362306a36Sopenharmony_ci		return;
31462306a36Sopenharmony_ci
31562306a36Sopenharmony_ci	ret = dsi_mgr_bridge_power_on(bridge);
31662306a36Sopenharmony_ci	if (ret) {
31762306a36Sopenharmony_ci		dev_err(&msm_dsi->pdev->dev, "Power on failed: %d\n", ret);
31862306a36Sopenharmony_ci		return;
31962306a36Sopenharmony_ci	}
32062306a36Sopenharmony_ci
32162306a36Sopenharmony_ci	ret = msm_dsi_host_enable(host);
32262306a36Sopenharmony_ci	if (ret) {
32362306a36Sopenharmony_ci		pr_err("%s: enable host %d failed, %d\n", __func__, id, ret);
32462306a36Sopenharmony_ci		goto host_en_fail;
32562306a36Sopenharmony_ci	}
32662306a36Sopenharmony_ci
32762306a36Sopenharmony_ci	if (is_bonded_dsi && msm_dsi1) {
32862306a36Sopenharmony_ci		ret = msm_dsi_host_enable(msm_dsi1->host);
32962306a36Sopenharmony_ci		if (ret) {
33062306a36Sopenharmony_ci			pr_err("%s: enable host1 failed, %d\n", __func__, ret);
33162306a36Sopenharmony_ci			goto host1_en_fail;
33262306a36Sopenharmony_ci		}
33362306a36Sopenharmony_ci	}
33462306a36Sopenharmony_ci
33562306a36Sopenharmony_ci	return;
33662306a36Sopenharmony_ci
33762306a36Sopenharmony_cihost1_en_fail:
33862306a36Sopenharmony_ci	msm_dsi_host_disable(host);
33962306a36Sopenharmony_cihost_en_fail:
34062306a36Sopenharmony_ci	dsi_mgr_bridge_power_off(bridge);
34162306a36Sopenharmony_ci}
34262306a36Sopenharmony_ci
34362306a36Sopenharmony_civoid msm_dsi_manager_tpg_enable(void)
34462306a36Sopenharmony_ci{
34562306a36Sopenharmony_ci	struct msm_dsi *m_dsi = dsi_mgr_get_dsi(DSI_0);
34662306a36Sopenharmony_ci	struct msm_dsi *s_dsi = dsi_mgr_get_dsi(DSI_1);
34762306a36Sopenharmony_ci
34862306a36Sopenharmony_ci	/* if dual dsi, trigger tpg on master first then slave */
34962306a36Sopenharmony_ci	if (m_dsi) {
35062306a36Sopenharmony_ci		msm_dsi_host_test_pattern_en(m_dsi->host);
35162306a36Sopenharmony_ci		if (IS_BONDED_DSI() && s_dsi)
35262306a36Sopenharmony_ci			msm_dsi_host_test_pattern_en(s_dsi->host);
35362306a36Sopenharmony_ci	}
35462306a36Sopenharmony_ci}
35562306a36Sopenharmony_ci
35662306a36Sopenharmony_cistatic void dsi_mgr_bridge_post_disable(struct drm_bridge *bridge)
35762306a36Sopenharmony_ci{
35862306a36Sopenharmony_ci	int id = dsi_mgr_bridge_get_id(bridge);
35962306a36Sopenharmony_ci	struct msm_dsi *msm_dsi = dsi_mgr_get_dsi(id);
36062306a36Sopenharmony_ci	struct msm_dsi *msm_dsi1 = dsi_mgr_get_dsi(DSI_1);
36162306a36Sopenharmony_ci	struct mipi_dsi_host *host = msm_dsi->host;
36262306a36Sopenharmony_ci	bool is_bonded_dsi = IS_BONDED_DSI();
36362306a36Sopenharmony_ci	int ret;
36462306a36Sopenharmony_ci
36562306a36Sopenharmony_ci	DBG("id=%d", id);
36662306a36Sopenharmony_ci
36762306a36Sopenharmony_ci	if (!msm_dsi_device_connected(msm_dsi))
36862306a36Sopenharmony_ci		return;
36962306a36Sopenharmony_ci
37062306a36Sopenharmony_ci	/*
37162306a36Sopenharmony_ci	 * Do nothing with the host if it is slave-DSI in case of bonded DSI.
37262306a36Sopenharmony_ci	 * It is safe to call dsi_mgr_phy_disable() here because a single PHY
37362306a36Sopenharmony_ci	 * won't be diabled until both PHYs request disable.
37462306a36Sopenharmony_ci	 */
37562306a36Sopenharmony_ci	if (is_bonded_dsi && !IS_MASTER_DSI_LINK(id))
37662306a36Sopenharmony_ci		goto disable_phy;
37762306a36Sopenharmony_ci
37862306a36Sopenharmony_ci	ret = msm_dsi_host_disable(host);
37962306a36Sopenharmony_ci	if (ret)
38062306a36Sopenharmony_ci		pr_err("%s: host %d disable failed, %d\n", __func__, id, ret);
38162306a36Sopenharmony_ci
38262306a36Sopenharmony_ci	if (is_bonded_dsi && msm_dsi1) {
38362306a36Sopenharmony_ci		ret = msm_dsi_host_disable(msm_dsi1->host);
38462306a36Sopenharmony_ci		if (ret)
38562306a36Sopenharmony_ci			pr_err("%s: host1 disable failed, %d\n", __func__, ret);
38662306a36Sopenharmony_ci	}
38762306a36Sopenharmony_ci
38862306a36Sopenharmony_ci	msm_dsi_host_disable_irq(host);
38962306a36Sopenharmony_ci	if (is_bonded_dsi && msm_dsi1)
39062306a36Sopenharmony_ci		msm_dsi_host_disable_irq(msm_dsi1->host);
39162306a36Sopenharmony_ci
39262306a36Sopenharmony_ci	/* Save PHY status if it is a clock source */
39362306a36Sopenharmony_ci	msm_dsi_phy_pll_save_state(msm_dsi->phy);
39462306a36Sopenharmony_ci
39562306a36Sopenharmony_ci	ret = msm_dsi_host_power_off(host);
39662306a36Sopenharmony_ci	if (ret)
39762306a36Sopenharmony_ci		pr_err("%s: host %d power off failed,%d\n", __func__, id, ret);
39862306a36Sopenharmony_ci
39962306a36Sopenharmony_ci	if (is_bonded_dsi && msm_dsi1) {
40062306a36Sopenharmony_ci		ret = msm_dsi_host_power_off(msm_dsi1->host);
40162306a36Sopenharmony_ci		if (ret)
40262306a36Sopenharmony_ci			pr_err("%s: host1 power off failed, %d\n",
40362306a36Sopenharmony_ci								__func__, ret);
40462306a36Sopenharmony_ci	}
40562306a36Sopenharmony_ci
40662306a36Sopenharmony_cidisable_phy:
40762306a36Sopenharmony_ci	dsi_mgr_phy_disable(id);
40862306a36Sopenharmony_ci}
40962306a36Sopenharmony_ci
41062306a36Sopenharmony_cistatic void dsi_mgr_bridge_mode_set(struct drm_bridge *bridge,
41162306a36Sopenharmony_ci		const struct drm_display_mode *mode,
41262306a36Sopenharmony_ci		const struct drm_display_mode *adjusted_mode)
41362306a36Sopenharmony_ci{
41462306a36Sopenharmony_ci	int id = dsi_mgr_bridge_get_id(bridge);
41562306a36Sopenharmony_ci	struct msm_dsi *msm_dsi = dsi_mgr_get_dsi(id);
41662306a36Sopenharmony_ci	struct msm_dsi *other_dsi = dsi_mgr_get_other_dsi(id);
41762306a36Sopenharmony_ci	struct mipi_dsi_host *host = msm_dsi->host;
41862306a36Sopenharmony_ci	bool is_bonded_dsi = IS_BONDED_DSI();
41962306a36Sopenharmony_ci
42062306a36Sopenharmony_ci	DBG("set mode: " DRM_MODE_FMT, DRM_MODE_ARG(mode));
42162306a36Sopenharmony_ci
42262306a36Sopenharmony_ci	if (is_bonded_dsi && !IS_MASTER_DSI_LINK(id))
42362306a36Sopenharmony_ci		return;
42462306a36Sopenharmony_ci
42562306a36Sopenharmony_ci	msm_dsi_host_set_display_mode(host, adjusted_mode);
42662306a36Sopenharmony_ci	if (is_bonded_dsi && other_dsi)
42762306a36Sopenharmony_ci		msm_dsi_host_set_display_mode(other_dsi->host, adjusted_mode);
42862306a36Sopenharmony_ci}
42962306a36Sopenharmony_ci
43062306a36Sopenharmony_cistatic enum drm_mode_status dsi_mgr_bridge_mode_valid(struct drm_bridge *bridge,
43162306a36Sopenharmony_ci						      const struct drm_display_info *info,
43262306a36Sopenharmony_ci						      const struct drm_display_mode *mode)
43362306a36Sopenharmony_ci{
43462306a36Sopenharmony_ci	int id = dsi_mgr_bridge_get_id(bridge);
43562306a36Sopenharmony_ci	struct msm_dsi *msm_dsi = dsi_mgr_get_dsi(id);
43662306a36Sopenharmony_ci	struct mipi_dsi_host *host = msm_dsi->host;
43762306a36Sopenharmony_ci	struct platform_device *pdev = msm_dsi->pdev;
43862306a36Sopenharmony_ci	struct dev_pm_opp *opp;
43962306a36Sopenharmony_ci	unsigned long byte_clk_rate;
44062306a36Sopenharmony_ci
44162306a36Sopenharmony_ci	byte_clk_rate = dsi_byte_clk_get_rate(host, IS_BONDED_DSI(), mode);
44262306a36Sopenharmony_ci
44362306a36Sopenharmony_ci	opp = dev_pm_opp_find_freq_ceil(&pdev->dev, &byte_clk_rate);
44462306a36Sopenharmony_ci	if (!IS_ERR(opp)) {
44562306a36Sopenharmony_ci		dev_pm_opp_put(opp);
44662306a36Sopenharmony_ci	} else if (PTR_ERR(opp) == -ERANGE) {
44762306a36Sopenharmony_ci		/*
44862306a36Sopenharmony_ci		 * An empty table is created by devm_pm_opp_set_clkname() even
44962306a36Sopenharmony_ci		 * if there is none. Thus find_freq_ceil will still return
45062306a36Sopenharmony_ci		 * -ERANGE in such case.
45162306a36Sopenharmony_ci		 */
45262306a36Sopenharmony_ci		if (dev_pm_opp_get_opp_count(&pdev->dev) != 0)
45362306a36Sopenharmony_ci			return MODE_CLOCK_RANGE;
45462306a36Sopenharmony_ci	} else {
45562306a36Sopenharmony_ci			return MODE_ERROR;
45662306a36Sopenharmony_ci	}
45762306a36Sopenharmony_ci
45862306a36Sopenharmony_ci	return msm_dsi_host_check_dsc(host, mode);
45962306a36Sopenharmony_ci}
46062306a36Sopenharmony_ci
46162306a36Sopenharmony_cistatic const struct drm_bridge_funcs dsi_mgr_bridge_funcs = {
46262306a36Sopenharmony_ci	.pre_enable = dsi_mgr_bridge_pre_enable,
46362306a36Sopenharmony_ci	.post_disable = dsi_mgr_bridge_post_disable,
46462306a36Sopenharmony_ci	.mode_set = dsi_mgr_bridge_mode_set,
46562306a36Sopenharmony_ci	.mode_valid = dsi_mgr_bridge_mode_valid,
46662306a36Sopenharmony_ci};
46762306a36Sopenharmony_ci
46862306a36Sopenharmony_ci/* initialize bridge */
46962306a36Sopenharmony_cistruct drm_bridge *msm_dsi_manager_bridge_init(u8 id)
47062306a36Sopenharmony_ci{
47162306a36Sopenharmony_ci	struct msm_dsi *msm_dsi = dsi_mgr_get_dsi(id);
47262306a36Sopenharmony_ci	struct drm_bridge *bridge = NULL;
47362306a36Sopenharmony_ci	struct dsi_bridge *dsi_bridge;
47462306a36Sopenharmony_ci	struct drm_encoder *encoder;
47562306a36Sopenharmony_ci	int ret;
47662306a36Sopenharmony_ci
47762306a36Sopenharmony_ci	dsi_bridge = devm_kzalloc(msm_dsi->dev->dev,
47862306a36Sopenharmony_ci				sizeof(*dsi_bridge), GFP_KERNEL);
47962306a36Sopenharmony_ci	if (!dsi_bridge) {
48062306a36Sopenharmony_ci		ret = -ENOMEM;
48162306a36Sopenharmony_ci		goto fail;
48262306a36Sopenharmony_ci	}
48362306a36Sopenharmony_ci
48462306a36Sopenharmony_ci	dsi_bridge->id = id;
48562306a36Sopenharmony_ci
48662306a36Sopenharmony_ci	encoder = msm_dsi->encoder;
48762306a36Sopenharmony_ci
48862306a36Sopenharmony_ci	bridge = &dsi_bridge->base;
48962306a36Sopenharmony_ci	bridge->funcs = &dsi_mgr_bridge_funcs;
49062306a36Sopenharmony_ci
49162306a36Sopenharmony_ci	drm_bridge_add(bridge);
49262306a36Sopenharmony_ci
49362306a36Sopenharmony_ci	ret = drm_bridge_attach(encoder, bridge, NULL, 0);
49462306a36Sopenharmony_ci	if (ret)
49562306a36Sopenharmony_ci		goto fail;
49662306a36Sopenharmony_ci
49762306a36Sopenharmony_ci	return bridge;
49862306a36Sopenharmony_ci
49962306a36Sopenharmony_cifail:
50062306a36Sopenharmony_ci	if (bridge)
50162306a36Sopenharmony_ci		msm_dsi_manager_bridge_destroy(bridge);
50262306a36Sopenharmony_ci
50362306a36Sopenharmony_ci	return ERR_PTR(ret);
50462306a36Sopenharmony_ci}
50562306a36Sopenharmony_ci
50662306a36Sopenharmony_ciint msm_dsi_manager_ext_bridge_init(u8 id)
50762306a36Sopenharmony_ci{
50862306a36Sopenharmony_ci	struct msm_dsi *msm_dsi = dsi_mgr_get_dsi(id);
50962306a36Sopenharmony_ci	struct drm_device *dev = msm_dsi->dev;
51062306a36Sopenharmony_ci	struct drm_encoder *encoder;
51162306a36Sopenharmony_ci	struct drm_bridge *int_bridge, *ext_bridge;
51262306a36Sopenharmony_ci	int ret;
51362306a36Sopenharmony_ci
51462306a36Sopenharmony_ci	int_bridge = msm_dsi->bridge;
51562306a36Sopenharmony_ci	ext_bridge = devm_drm_of_get_bridge(&msm_dsi->pdev->dev,
51662306a36Sopenharmony_ci					    msm_dsi->pdev->dev.of_node, 1, 0);
51762306a36Sopenharmony_ci	if (IS_ERR(ext_bridge))
51862306a36Sopenharmony_ci		return PTR_ERR(ext_bridge);
51962306a36Sopenharmony_ci
52062306a36Sopenharmony_ci	msm_dsi->external_bridge = ext_bridge;
52162306a36Sopenharmony_ci
52262306a36Sopenharmony_ci	encoder = msm_dsi->encoder;
52362306a36Sopenharmony_ci
52462306a36Sopenharmony_ci	/*
52562306a36Sopenharmony_ci	 * Try first to create the bridge without it creating its own
52662306a36Sopenharmony_ci	 * connector.. currently some bridges support this, and others
52762306a36Sopenharmony_ci	 * do not (and some support both modes)
52862306a36Sopenharmony_ci	 */
52962306a36Sopenharmony_ci	ret = drm_bridge_attach(encoder, ext_bridge, int_bridge,
53062306a36Sopenharmony_ci			DRM_BRIDGE_ATTACH_NO_CONNECTOR);
53162306a36Sopenharmony_ci	if (ret == -EINVAL) {
53262306a36Sopenharmony_ci		/*
53362306a36Sopenharmony_ci		 * link the internal dsi bridge to the external bridge,
53462306a36Sopenharmony_ci		 * connector is created by the next bridge.
53562306a36Sopenharmony_ci		 */
53662306a36Sopenharmony_ci		ret = drm_bridge_attach(encoder, ext_bridge, int_bridge, 0);
53762306a36Sopenharmony_ci		if (ret < 0)
53862306a36Sopenharmony_ci			return ret;
53962306a36Sopenharmony_ci	} else {
54062306a36Sopenharmony_ci		struct drm_connector *connector;
54162306a36Sopenharmony_ci
54262306a36Sopenharmony_ci		/* We are in charge of the connector, create one now. */
54362306a36Sopenharmony_ci		connector = drm_bridge_connector_init(dev, encoder);
54462306a36Sopenharmony_ci		if (IS_ERR(connector)) {
54562306a36Sopenharmony_ci			DRM_ERROR("Unable to create bridge connector\n");
54662306a36Sopenharmony_ci			return PTR_ERR(connector);
54762306a36Sopenharmony_ci		}
54862306a36Sopenharmony_ci
54962306a36Sopenharmony_ci		ret = drm_connector_attach_encoder(connector, encoder);
55062306a36Sopenharmony_ci		if (ret < 0)
55162306a36Sopenharmony_ci			return ret;
55262306a36Sopenharmony_ci	}
55362306a36Sopenharmony_ci
55462306a36Sopenharmony_ci	/* The pipeline is ready, ping encoders if necessary */
55562306a36Sopenharmony_ci	msm_dsi_manager_set_split_display(id);
55662306a36Sopenharmony_ci
55762306a36Sopenharmony_ci	return 0;
55862306a36Sopenharmony_ci}
55962306a36Sopenharmony_ci
56062306a36Sopenharmony_civoid msm_dsi_manager_bridge_destroy(struct drm_bridge *bridge)
56162306a36Sopenharmony_ci{
56262306a36Sopenharmony_ci	drm_bridge_remove(bridge);
56362306a36Sopenharmony_ci}
56462306a36Sopenharmony_ci
56562306a36Sopenharmony_ciint msm_dsi_manager_cmd_xfer(int id, const struct mipi_dsi_msg *msg)
56662306a36Sopenharmony_ci{
56762306a36Sopenharmony_ci	struct msm_dsi *msm_dsi = dsi_mgr_get_dsi(id);
56862306a36Sopenharmony_ci	struct msm_dsi *msm_dsi0 = dsi_mgr_get_dsi(DSI_0);
56962306a36Sopenharmony_ci	struct mipi_dsi_host *host = msm_dsi->host;
57062306a36Sopenharmony_ci	bool is_read = (msg->rx_buf && msg->rx_len);
57162306a36Sopenharmony_ci	bool need_sync = (IS_SYNC_NEEDED() && !is_read);
57262306a36Sopenharmony_ci	int ret;
57362306a36Sopenharmony_ci
57462306a36Sopenharmony_ci	if (!msg->tx_buf || !msg->tx_len)
57562306a36Sopenharmony_ci		return 0;
57662306a36Sopenharmony_ci
57762306a36Sopenharmony_ci	/* In bonded master case, panel requires the same commands sent to
57862306a36Sopenharmony_ci	 * both DSI links. Host issues the command trigger to both links
57962306a36Sopenharmony_ci	 * when DSI_1 calls the cmd transfer function, no matter it happens
58062306a36Sopenharmony_ci	 * before or after DSI_0 cmd transfer.
58162306a36Sopenharmony_ci	 */
58262306a36Sopenharmony_ci	if (need_sync && (id == DSI_0))
58362306a36Sopenharmony_ci		return is_read ? msg->rx_len : msg->tx_len;
58462306a36Sopenharmony_ci
58562306a36Sopenharmony_ci	if (need_sync && msm_dsi0) {
58662306a36Sopenharmony_ci		ret = msm_dsi_host_xfer_prepare(msm_dsi0->host, msg);
58762306a36Sopenharmony_ci		if (ret) {
58862306a36Sopenharmony_ci			pr_err("%s: failed to prepare non-trigger host, %d\n",
58962306a36Sopenharmony_ci				__func__, ret);
59062306a36Sopenharmony_ci			return ret;
59162306a36Sopenharmony_ci		}
59262306a36Sopenharmony_ci	}
59362306a36Sopenharmony_ci	ret = msm_dsi_host_xfer_prepare(host, msg);
59462306a36Sopenharmony_ci	if (ret) {
59562306a36Sopenharmony_ci		pr_err("%s: failed to prepare host, %d\n", __func__, ret);
59662306a36Sopenharmony_ci		goto restore_host0;
59762306a36Sopenharmony_ci	}
59862306a36Sopenharmony_ci
59962306a36Sopenharmony_ci	ret = is_read ? msm_dsi_host_cmd_rx(host, msg) :
60062306a36Sopenharmony_ci			msm_dsi_host_cmd_tx(host, msg);
60162306a36Sopenharmony_ci
60262306a36Sopenharmony_ci	msm_dsi_host_xfer_restore(host, msg);
60362306a36Sopenharmony_ci
60462306a36Sopenharmony_cirestore_host0:
60562306a36Sopenharmony_ci	if (need_sync && msm_dsi0)
60662306a36Sopenharmony_ci		msm_dsi_host_xfer_restore(msm_dsi0->host, msg);
60762306a36Sopenharmony_ci
60862306a36Sopenharmony_ci	return ret;
60962306a36Sopenharmony_ci}
61062306a36Sopenharmony_ci
61162306a36Sopenharmony_cibool msm_dsi_manager_cmd_xfer_trigger(int id, u32 dma_base, u32 len)
61262306a36Sopenharmony_ci{
61362306a36Sopenharmony_ci	struct msm_dsi *msm_dsi = dsi_mgr_get_dsi(id);
61462306a36Sopenharmony_ci	struct msm_dsi *msm_dsi0 = dsi_mgr_get_dsi(DSI_0);
61562306a36Sopenharmony_ci	struct mipi_dsi_host *host = msm_dsi->host;
61662306a36Sopenharmony_ci
61762306a36Sopenharmony_ci	if (IS_SYNC_NEEDED() && (id == DSI_0))
61862306a36Sopenharmony_ci		return false;
61962306a36Sopenharmony_ci
62062306a36Sopenharmony_ci	if (IS_SYNC_NEEDED() && msm_dsi0)
62162306a36Sopenharmony_ci		msm_dsi_host_cmd_xfer_commit(msm_dsi0->host, dma_base, len);
62262306a36Sopenharmony_ci
62362306a36Sopenharmony_ci	msm_dsi_host_cmd_xfer_commit(host, dma_base, len);
62462306a36Sopenharmony_ci
62562306a36Sopenharmony_ci	return true;
62662306a36Sopenharmony_ci}
62762306a36Sopenharmony_ci
62862306a36Sopenharmony_ciint msm_dsi_manager_register(struct msm_dsi *msm_dsi)
62962306a36Sopenharmony_ci{
63062306a36Sopenharmony_ci	struct msm_dsi_manager *msm_dsim = &msm_dsim_glb;
63162306a36Sopenharmony_ci	int id = msm_dsi->id;
63262306a36Sopenharmony_ci	int ret;
63362306a36Sopenharmony_ci
63462306a36Sopenharmony_ci	if (id >= DSI_MAX) {
63562306a36Sopenharmony_ci		pr_err("%s: invalid id %d\n", __func__, id);
63662306a36Sopenharmony_ci		return -EINVAL;
63762306a36Sopenharmony_ci	}
63862306a36Sopenharmony_ci
63962306a36Sopenharmony_ci	if (msm_dsim->dsi[id]) {
64062306a36Sopenharmony_ci		pr_err("%s: dsi%d already registered\n", __func__, id);
64162306a36Sopenharmony_ci		return -EBUSY;
64262306a36Sopenharmony_ci	}
64362306a36Sopenharmony_ci
64462306a36Sopenharmony_ci	msm_dsim->dsi[id] = msm_dsi;
64562306a36Sopenharmony_ci
64662306a36Sopenharmony_ci	ret = dsi_mgr_parse_of(msm_dsi->pdev->dev.of_node, id);
64762306a36Sopenharmony_ci	if (ret) {
64862306a36Sopenharmony_ci		pr_err("%s: failed to parse OF DSI info\n", __func__);
64962306a36Sopenharmony_ci		goto fail;
65062306a36Sopenharmony_ci	}
65162306a36Sopenharmony_ci
65262306a36Sopenharmony_ci	ret = dsi_mgr_setup_components(id);
65362306a36Sopenharmony_ci	if (ret) {
65462306a36Sopenharmony_ci		pr_err("%s: failed to register mipi dsi host for DSI %d: %d\n",
65562306a36Sopenharmony_ci			__func__, id, ret);
65662306a36Sopenharmony_ci		goto fail;
65762306a36Sopenharmony_ci	}
65862306a36Sopenharmony_ci
65962306a36Sopenharmony_ci	return 0;
66062306a36Sopenharmony_ci
66162306a36Sopenharmony_cifail:
66262306a36Sopenharmony_ci	msm_dsim->dsi[id] = NULL;
66362306a36Sopenharmony_ci	return ret;
66462306a36Sopenharmony_ci}
66562306a36Sopenharmony_ci
66662306a36Sopenharmony_civoid msm_dsi_manager_unregister(struct msm_dsi *msm_dsi)
66762306a36Sopenharmony_ci{
66862306a36Sopenharmony_ci	struct msm_dsi_manager *msm_dsim = &msm_dsim_glb;
66962306a36Sopenharmony_ci
67062306a36Sopenharmony_ci	if (msm_dsi->host)
67162306a36Sopenharmony_ci		msm_dsi_host_unregister(msm_dsi->host);
67262306a36Sopenharmony_ci
67362306a36Sopenharmony_ci	if (msm_dsi->id >= 0)
67462306a36Sopenharmony_ci		msm_dsim->dsi[msm_dsi->id] = NULL;
67562306a36Sopenharmony_ci}
67662306a36Sopenharmony_ci
67762306a36Sopenharmony_cibool msm_dsi_is_bonded_dsi(struct msm_dsi *msm_dsi)
67862306a36Sopenharmony_ci{
67962306a36Sopenharmony_ci	return IS_BONDED_DSI();
68062306a36Sopenharmony_ci}
68162306a36Sopenharmony_ci
68262306a36Sopenharmony_cibool msm_dsi_is_master_dsi(struct msm_dsi *msm_dsi)
68362306a36Sopenharmony_ci{
68462306a36Sopenharmony_ci	return IS_MASTER_DSI_LINK(msm_dsi->id);
68562306a36Sopenharmony_ci}
686