diff mbox

[v2,18/25] drm/msm/dsi: Don't get DSI index from DT

Message ID 1466691210-22779-19-git-send-email-architt@codeaurora.org (mailing list archive)
State New, archived
Headers show

Commit Message

Archit Taneja June 23, 2016, 2:13 p.m. UTC
The DSI host and PHY driver currently expects the DT bindings to provide
custom properties "qcom,dsi-host-index" and "qcom,dsi-phy-index" so that
the driver can identify which DSI instance it is.

The binding isn't acceptable, but the driver still needs to figure out
what its instance id. This is now done by storing the mmio starting
addresses for each DSI instance in every SoC version in the driver. The
driver then identifies the index number by trying to match the stored
address with comparing the resource start address we get from DT.

We don't have compatible strings for DSI PHY on each SoC, but only the
DSI PHY type. We only support one SoC version for each PHY type, so we
get away doing the same thing above for the PHY driver. We can revisit
this when we support two SoCs with the same DSI PHY.

Signed-off-by: Archit Taneja <architt@codeaurora.org>
---
v2:
 - New patch

 drivers/gpu/drm/msm/dsi/dsi_cfg.c               |  8 ++++++
 drivers/gpu/drm/msm/dsi/dsi_cfg.h               |  2 ++
 drivers/gpu/drm/msm/dsi/dsi_host.c              | 33 +++++++++++++++++++------
 drivers/gpu/drm/msm/dsi/phy/dsi_phy.c           | 32 +++++++++++++++++++++---
 drivers/gpu/drm/msm/dsi/phy/dsi_phy.h           |  2 ++
 drivers/gpu/drm/msm/dsi/phy/dsi_phy_20nm.c      |  4 ++-
 drivers/gpu/drm/msm/dsi/phy/dsi_phy_28nm.c      |  4 +++
 drivers/gpu/drm/msm/dsi/phy/dsi_phy_28nm_8960.c |  2 ++
 8 files changed, 75 insertions(+), 12 deletions(-)

Comments

Rob Herring June 23, 2016, 2:45 p.m. UTC | #1
On Thu, Jun 23, 2016 at 9:13 AM, Archit Taneja <architt@codeaurora.org> wrote:
> The DSI host and PHY driver currently expects the DT bindings to provide
> custom properties "qcom,dsi-host-index" and "qcom,dsi-phy-index" so that
> the driver can identify which DSI instance it is.
>
> The binding isn't acceptable, but the driver still needs to figure out
> what its instance id. This is now done by storing the mmio starting
> addresses for each DSI instance in every SoC version in the driver. The
> driver then identifies the index number by trying to match the stored
> address with comparing the resource start address we get from DT.

I looked a bit more at this. It seems at least one reason you need to
know which DSI instance is which is when ganging the instances
together and needing to define the clock master. You could define a
property for the clock master for example.

Rob
Archit Taneja June 24, 2016, 5 a.m. UTC | #2
On 06/23/2016 08:15 PM, Rob Herring wrote:
> On Thu, Jun 23, 2016 at 9:13 AM, Archit Taneja <architt@codeaurora.org> wrote:
>> The DSI host and PHY driver currently expects the DT bindings to provide
>> custom properties "qcom,dsi-host-index" and "qcom,dsi-phy-index" so that
>> the driver can identify which DSI instance it is.
>>
>> The binding isn't acceptable, but the driver still needs to figure out
>> what its instance id. This is now done by storing the mmio starting
>> addresses for each DSI instance in every SoC version in the driver. The
>> driver then identifies the index number by trying to match the stored
>> address with comparing the resource start address we get from DT.
>
> I looked a bit more at this. It seems at least one reason you need to
> know which DSI instance is which is when ganging the instances
> together and needing to define the clock master. You could define a
> property for the clock master for example.

The ganging of instances itself has two parts to it: 1) routing the
external clocks feeding to the DSI hosts. That can be managed by
assigned clocks without the need of having a clock-master property.
I've shared an example at the end showing how that can be done. 2)
Programming certain PHY register fields telling it which 'DSI index
number' it's getting its clocks from.

For (2), just having a 'clock-master' property in one of the instances
property isn't sufficient to program the register field. We need to
know that DSI0 is 0, and DSI1 is 1. That's why we need to derive it in
the driver itself if we don't have a property for it in DT.

It would have been nicer if the register interface had let us say
"I am the master" or "other instance is the master", but I guess that
wouldn't have worked if a SoC had, say, 3 DSI instances.

I guess we can derive the instance number from the driver internally
as done in this patch, use assigned clocks to set up the routing of
the external clocks, and have a "qcom,dsi-clock-master" property
only needed for Dual DSI usecases.

Does this sound good?

Thanks,
Archit

In the example bindings below, DSI0 PLL outputs are used to drive both
the DSIs, i.e, DSI0 instance is the clock master:

dsi_phy0 {
	/* DSI0 PLL clock provider */
};

dsi_phy1 {
	/* DSI1 PLL clock provider */
};

dsi0 {
	...

	assigned-clocks =
			<&mmcc BYTE0_CLK_SRC>,
			<&mmcc PCLK0_CLK_SRC>;
	assigned-clock-parents =
				<&dsi_phy0 0>,
				<&dsi_phy0 1>;
	...

};

dsi1 {
	...
	assigned-clocks =
			<&mmcc BYTE1_CLK_SRC>,
			<&mmcc PCLK1_CLK_SRC>;
	assigned-clock-parents =
				<&dsi_phy0 0>,
				<&dsi_phy0 1>;
	...
};


>
> Rob
> --
> To unsubscribe from this list: send the line "unsubscribe linux-arm-msm" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html
>
diff mbox

Patch

diff --git a/drivers/gpu/drm/msm/dsi/dsi_cfg.c b/drivers/gpu/drm/msm/dsi/dsi_cfg.c
index 93c1ee0..63436d8 100644
--- a/drivers/gpu/drm/msm/dsi/dsi_cfg.c
+++ b/drivers/gpu/drm/msm/dsi/dsi_cfg.c
@@ -29,6 +29,8 @@  static const struct msm_dsi_config apq8064_dsi_cfg = {
 	},
 	.bus_clk_names = dsi_v2_bus_clk_names,
 	.num_bus_clks = ARRAY_SIZE(dsi_v2_bus_clk_names),
+	.io_start = { 0x4700000, 0x5800000 },
+	.num_dsi = 2,
 };
 
 static const char * const dsi_6g_bus_clk_names[] = {
@@ -48,6 +50,8 @@  static const struct msm_dsi_config msm8974_apq8084_dsi_cfg = {
 	},
 	.bus_clk_names = dsi_6g_bus_clk_names,
 	.num_bus_clks = ARRAY_SIZE(dsi_6g_bus_clk_names),
+	.io_start = { 0xfd922800, 0xfd922b00 },
+	.num_dsi = 2,
 };
 
 static const char * const dsi_8916_bus_clk_names[] = {
@@ -66,6 +70,8 @@  static const struct msm_dsi_config msm8916_dsi_cfg = {
 	},
 	.bus_clk_names = dsi_8916_bus_clk_names,
 	.num_bus_clks = ARRAY_SIZE(dsi_8916_bus_clk_names),
+	.io_start = { 0x1a98000 },
+	.num_dsi = 1,
 };
 
 static const struct msm_dsi_config msm8994_dsi_cfg = {
@@ -84,6 +90,8 @@  static const struct msm_dsi_config msm8994_dsi_cfg = {
 	},
 	.bus_clk_names = dsi_6g_bus_clk_names,
 	.num_bus_clks = ARRAY_SIZE(dsi_6g_bus_clk_names),
+	.io_start = { 0xfd998000, 0xfd9a0000 },
+	.num_dsi = 2,
 };
 
 static const struct msm_dsi_cfg_handler dsi_cfg_handlers[] = {
diff --git a/drivers/gpu/drm/msm/dsi/dsi_cfg.h b/drivers/gpu/drm/msm/dsi/dsi_cfg.h
index a68c836..eeacc323 100644
--- a/drivers/gpu/drm/msm/dsi/dsi_cfg.h
+++ b/drivers/gpu/drm/msm/dsi/dsi_cfg.h
@@ -34,6 +34,8 @@  struct msm_dsi_config {
 	struct dsi_reg_config reg_cfg;
 	const char * const *bus_clk_names;
 	const int num_bus_clks;
+	const resource_size_t io_start[DSI_MAX];
+	const int num_dsi;
 };
 
 struct msm_dsi_cfg_handler {
diff --git a/drivers/gpu/drm/msm/dsi/dsi_host.c b/drivers/gpu/drm/msm/dsi/dsi_host.c
index e6a8cd1..80d8594 100644
--- a/drivers/gpu/drm/msm/dsi/dsi_host.c
+++ b/drivers/gpu/drm/msm/dsi/dsi_host.c
@@ -1605,13 +1605,6 @@  static int dsi_host_parse_dt(struct msm_dsi_host *msm_host)
 	struct device_node *endpoint, *device_node;
 	int ret;
 
-	ret = of_property_read_u32(np, "qcom,dsi-host-index", &msm_host->id);
-	if (ret) {
-		dev_err(dev, "%s: host index not specified, ret=%d\n",
-			__func__, ret);
-		return ret;
-	}
-
 	/*
 	 * Get the endpoint of the output port of the DSI host. In our case,
 	 * this is mapped to port number with reg = 1. Don't return an error if
@@ -1659,6 +1652,25 @@  err:
 	return ret;
 }
 
+static int dsi_host_get_id(struct msm_dsi_host *msm_host)
+{
+	struct platform_device *pdev = msm_host->pdev;
+	const struct msm_dsi_config *cfg = msm_host->cfg_hnd->cfg;
+	struct resource *res;
+	int i;
+
+	res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "dsi_ctrl");
+	if (!res)
+		return -EINVAL;
+
+	for (i = 0; i < cfg->num_dsi; i++) {
+		if (cfg->io_start[i] == res->start)
+			return i;
+	}
+
+	return -EINVAL;
+}
+
 int msm_dsi_host_init(struct msm_dsi *msm_dsi)
 {
 	struct msm_dsi_host *msm_host = NULL;
@@ -1695,6 +1707,13 @@  int msm_dsi_host_init(struct msm_dsi *msm_dsi)
 		goto fail;
 	}
 
+	msm_host->id = dsi_host_get_id(msm_host);
+	if (msm_host->id < 0) {
+		ret = msm_host->id;
+		pr_err("%s: unable to identify DSI host index\n", __func__);
+		goto fail;
+	}
+
 	/* fixup base address by io offset */
 	msm_host->ctrl_base += msm_host->cfg_hnd->cfg->io_offset;
 
diff --git a/drivers/gpu/drm/msm/dsi/phy/dsi_phy.c b/drivers/gpu/drm/msm/dsi/phy/dsi_phy.c
index e2f42d8..f39386e 100644
--- a/drivers/gpu/drm/msm/dsi/phy/dsi_phy.c
+++ b/drivers/gpu/drm/msm/dsi/phy/dsi_phy.c
@@ -271,6 +271,30 @@  static const struct of_device_id dsi_phy_dt_match[] = {
 	{}
 };
 
+/*
+ * Currently, we only support one SoC for each PHY type. When we have multiple
+ * SoCs for the same PHY, we can try to make the index searching a bit more
+ * clever.
+ */
+static int dsi_phy_get_id(struct msm_dsi_phy *phy)
+{
+	struct platform_device *pdev = phy->pdev;
+	const struct msm_dsi_phy_cfg *cfg = phy->cfg;
+	struct resource *res;
+	int i;
+
+	res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "dsi_phy");
+	if (!res)
+		return -EINVAL;
+
+	for (i = 0; i < cfg->num_dsi_phy; i++) {
+		if (cfg->io_start[i] == res->start)
+			return i;
+	}
+
+	return -EINVAL;
+}
+
 static int dsi_phy_driver_probe(struct platform_device *pdev)
 {
 	struct msm_dsi_phy *phy;
@@ -289,10 +313,10 @@  static int dsi_phy_driver_probe(struct platform_device *pdev)
 	phy->cfg = match->data;
 	phy->pdev = pdev;
 
-	ret = of_property_read_u32(dev->of_node,
-				"qcom,dsi-phy-index", &phy->id);
-	if (ret) {
-		dev_err(dev, "%s: PHY index not specified, %d\n",
+	phy->id = dsi_phy_get_id(phy);
+	if (phy->id < 0) {
+		ret = phy->id;
+		dev_err(dev, "%s: couldn't identify PHY index, %d\n",
 			__func__, ret);
 		goto fail;
 	}
diff --git a/drivers/gpu/drm/msm/dsi/phy/dsi_phy.h b/drivers/gpu/drm/msm/dsi/phy/dsi_phy.h
index 0d54ed0..f24a854 100644
--- a/drivers/gpu/drm/msm/dsi/phy/dsi_phy.h
+++ b/drivers/gpu/drm/msm/dsi/phy/dsi_phy.h
@@ -38,6 +38,8 @@  struct msm_dsi_phy_cfg {
 	 * Fill default H/W values in illegal cells, eg. cell {0, 1}.
 	 */
 	bool src_pll_truthtable[DSI_MAX][DSI_MAX];
+	const resource_size_t io_start[DSI_MAX];
+	const int num_dsi_phy;
 };
 
 extern const struct msm_dsi_phy_cfg dsi_phy_28nm_hpm_cfgs;
diff --git a/drivers/gpu/drm/msm/dsi/phy/dsi_phy_20nm.c b/drivers/gpu/drm/msm/dsi/phy/dsi_phy_20nm.c
index f4bc11a..c757e20 100644
--- a/drivers/gpu/drm/msm/dsi/phy/dsi_phy_20nm.c
+++ b/drivers/gpu/drm/msm/dsi/phy/dsi_phy_20nm.c
@@ -145,6 +145,8 @@  const struct msm_dsi_phy_cfg dsi_phy_20nm_cfgs = {
 	.ops = {
 		.enable = dsi_20nm_phy_enable,
 		.disable = dsi_20nm_phy_disable,
-	}
+	},
+	.io_start = { 0xfd998300, 0xfd9a0300 },
+	.num_dsi_phy = 2,
 };
 
diff --git a/drivers/gpu/drm/msm/dsi/phy/dsi_phy_28nm.c b/drivers/gpu/drm/msm/dsi/phy/dsi_phy_28nm.c
index 96d1852..63d7fba 100644
--- a/drivers/gpu/drm/msm/dsi/phy/dsi_phy_28nm.c
+++ b/drivers/gpu/drm/msm/dsi/phy/dsi_phy_28nm.c
@@ -145,6 +145,8 @@  const struct msm_dsi_phy_cfg dsi_phy_28nm_hpm_cfgs = {
 		.enable = dsi_28nm_phy_enable,
 		.disable = dsi_28nm_phy_disable,
 	},
+	.io_start = { 0xfd922b00, 0xfd923100 },
+	.num_dsi_phy = 2,
 };
 
 const struct msm_dsi_phy_cfg dsi_phy_28nm_lp_cfgs = {
@@ -160,5 +162,7 @@  const struct msm_dsi_phy_cfg dsi_phy_28nm_lp_cfgs = {
 		.enable = dsi_28nm_phy_enable,
 		.disable = dsi_28nm_phy_disable,
 	},
+	.io_start = { 0x1a98500 },
+	.num_dsi_phy = 1,
 };
 
diff --git a/drivers/gpu/drm/msm/dsi/phy/dsi_phy_28nm_8960.c b/drivers/gpu/drm/msm/dsi/phy/dsi_phy_28nm_8960.c
index 213355a..7bdb9de 100644
--- a/drivers/gpu/drm/msm/dsi/phy/dsi_phy_28nm_8960.c
+++ b/drivers/gpu/drm/msm/dsi/phy/dsi_phy_28nm_8960.c
@@ -192,4 +192,6 @@  const struct msm_dsi_phy_cfg dsi_phy_28nm_8960_cfgs = {
 		.enable = dsi_28nm_phy_enable,
 		.disable = dsi_28nm_phy_disable,
 	},
+	.io_start = { 0x4700300, 0x5800300 },
+	.num_dsi_phy = 2,
 };