msm: adsp-loader: Add support for adsp state in adsp loader

MDM9625 does not use PIL. ADSP is loaded by SBL
at boot. ADSP state should be set to loaded for
MDM9625. APR requires that ADSP is in loaded
state before registering.

Change-Id: Iaaf979c30389e395079120a5c3cbbef2a9c3e8a8
Signed-off-by: Venkat Sudhir <vsudhir@codeaurora.org>
diff --git a/Documentation/devicetree/bindings/sound/qcom-audio-dev.txt b/Documentation/devicetree/bindings/sound/qcom-audio-dev.txt
index 1e647a7..213da90 100644
--- a/Documentation/devicetree/bindings/sound/qcom-audio-dev.txt
+++ b/Documentation/devicetree/bindings/sound/qcom-audio-dev.txt
@@ -474,3 +474,22 @@
 			"MIC BIAS4 External", "Digital Mic6";
 			qcom,taiko-mclk-clk-freq = <12288000>;
 };
+
+* msm-adsp-loader
+
+Required properties:
+ - compatible : "msm-adsp-loader"
+ - qcom,adsp-state:
+	It is possible that some MSM use PIL to load the ADSP image. While
+	other MSM may use SBL to load the ADSP image at boot. Audio APR needs
+	state of ADSP to register and enable APR to be used for sending commands
+	to ADSP. so adsp-state represents the state of ADSP to ADSP loader. Value
+	of 0 indicates ADSP loader needs to use PIL and value of 2 means ADSP
+	image is already loaded by SBL.
+
+Example:
+
+qcom,msm-adsp-loader {
+	compatible = "qcom,adsp-loader";
+	qcom,adsp-state = <2>;
+};
diff --git a/arch/arm/boot/dts/msm8974.dtsi b/arch/arm/boot/dts/msm8974.dtsi
index 93ba2bf..aaf8da4 100644
--- a/arch/arm/boot/dts/msm8974.dtsi
+++ b/arch/arm/boot/dts/msm8974.dtsi
@@ -757,6 +757,7 @@
 
 	qcom,msm-adsp-loader {
 		compatible = "qcom,adsp-loader";
+		qcom,adsp-state = <0>;
 	};
 
 	qcom,msm-pcm {
diff --git a/arch/arm/boot/dts/msm9625.dtsi b/arch/arm/boot/dts/msm9625.dtsi
index b79f370..ab0e647 100644
--- a/arch/arm/boot/dts/msm9625.dtsi
+++ b/arch/arm/boot/dts/msm9625.dtsi
@@ -393,6 +393,7 @@
 
 	qcom,msm-adsp-loader {
 		compatible = "qcom,adsp-loader";
+		qcom,adsp-state = <2>;
 	};
 
 	qcom,msm-pcm {
diff --git a/arch/arm/mach-msm/qdsp6v2/adsp-loader.c b/arch/arm/mach-msm/qdsp6v2/adsp-loader.c
index c28e403..02dbece 100644
--- a/arch/arm/mach-msm/qdsp6v2/adsp-loader.c
+++ b/arch/arm/mach-msm/qdsp6v2/adsp-loader.c
@@ -19,6 +19,7 @@
 #include <linux/platform_device.h>
 #include <mach/subsystem_restart.h>
 #include <mach/qdsp6v2/apr.h>
+#include <linux/of_device.h>
 
 #define Q6_PIL_GET_DELAY_MS 100
 
@@ -30,25 +31,41 @@
 {
 	struct adsp_loader_private *priv;
 	int rc = 0;
+	const char *adsp_dt = "qcom,adsp-state";
+	u32 adsp_state;
 
-	priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL);
-	if (!priv)
-		return -ENOMEM;
-
-	platform_set_drvdata(pdev, priv);
-
-	priv->pil_h = subsystem_get("adsp");
-	if (IS_ERR(priv->pil_h)) {
-		pr_err("%s: pil get adsp failed, error:%d\n", __func__, rc);
-		devm_kfree(&pdev->dev, priv);
-		goto fail;
+	rc = of_property_read_u32(pdev->dev.of_node, adsp_dt, &adsp_state);
+	if (rc) {
+		dev_err(&pdev->dev,
+			"%s: ADSP state = %x\n", __func__, adsp_state);
+		return rc;
 	}
 
-	/* Query the DSP to check if resources are available */
-	msleep(Q6_PIL_GET_DELAY_MS);
+	if (adsp_state == APR_SUBSYS_DOWN) {
+		priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL);
+		if (!priv)
+			return -ENOMEM;
 
-	/* Set the state of the ADSP in APR driver */
-	apr_set_q6_state(APR_SUBSYS_LOADED);
+		platform_set_drvdata(pdev, priv);
+
+		priv->pil_h = subsystem_get("adsp");
+		if (IS_ERR(priv->pil_h)) {
+			pr_err("%s: pil get adsp failed, error:%d\n",
+				__func__, rc);
+			devm_kfree(&pdev->dev, priv);
+			goto fail;
+		}
+
+		/* Query the DSP to check if resources are available */
+		msleep(Q6_PIL_GET_DELAY_MS);
+
+		/* Set the state of the ADSP in APR driver */
+		apr_set_q6_state(APR_SUBSYS_LOADED);
+	} else if (adsp_state == APR_SUBSYS_LOADED) {
+		dev_dbg(&pdev->dev,
+			"%s:MDM9x25 ADSP state = %x\n", __func__, adsp_state);
+		apr_set_q6_state(APR_SUBSYS_LOADED);
+	}
 
 	/* Query for MMPM API */
 
@@ -62,7 +79,8 @@
 	struct adsp_loader_private *priv;
 
 	priv = platform_get_drvdata(pdev);
-	subsystem_put(priv->pil_h);
+	if (priv != NULL)
+		subsystem_put(priv->pil_h);
 	pr_info("%s: Q6/ADSP image is unloaded\n", __func__);
 
 	return 0;