diff mbox series

Issues bringing up WCD9385 codec on SC7280/QCM6490

Message ID CXCXIAY8RBVK.2Y9W66THN9QH2@fairphone.com
State New
Headers show
Series Issues bringing up WCD9385 codec on SC7280/QCM6490 | expand

Commit Message

Luca Weiss Dec. 1, 2023, 10:35 a.m. UTC
Hi all,

I'm trying to get audio working on qcm6490-fairphone-fp5 (the SoC is
sc7280.dtsi-based).
Unfortunately the current sc7280.dtsi only supports directly interfacing
with the hw blocks (lpass_aon/lpass_hm/lpass_audiocc) and not using
q6afecc, but I think I've done this "conversion" correctly, based on
other mainline SoCs and downstream dts.

So, to the problem: I've added the nodes for the WCD9385 codec found on
this device which is handling the microphones (and analog audio over
USB-C). But I can't get it to work. I believe the first problem I saw
was the error "soundwire device init timeout" where I saw that the wcd
tx & rx devices (on the soundwire bus) only appeared after the timeout
of 2 seconds expired and wcd938x driver probe failed. After bumping this
to something higher (20 seconds) this was resolved.

But now I'm having these errors in the initialization of the wcd
devices.

[   45.651156] qcom-soundwire 3230000.soundwire: swrm_wait_for_rd_fifo_avail err read underflow
[   45.651173] soundwire sdw-master-1: trf on Slave 1 failed:-5 read addr 41 count 1
[   45.651182] wcd9380-codec sdw:0:0217:010d:00:3: SDW_SCP_INTMASK1 write failed:-5
[   45.651186] wcd9380-codec sdw:0:0217:010d:00:3: Slave 1 initialization failed: -5

After some more debugging and changing some timeouts I'm noticing that
the swr devices appear immediately after pm_runtime puts the driver to
sleep, qcom_swrm_irq_handler is called and then we get this:

[   45.531863] qcom-soundwire 3230000.soundwire: SWR new slave attached

The same also happens for the other soundwire controller

[   47.581067] qcom-soundwire 3210000.soundwire: SWR new slave attached

And this is currently where I'm stuck and can't really think of why this
is happening.. I've double checked nearly all of the properties I've
added/modified incl. wcd reset GPIO, wcd *-supply, lpi pinctrl settings.
I believe the "read underflow" error here is because the whole driver
stack is already trying to suspend so then communication fails. The real
question for me is why the swr 'slaves' only appear exactly when
pm_runtime is suspending everything.

The only thing I've not really checked yet is qcom,rx-port-mapping &
qcom,tx-port-mapping, there I've just tried the two different values
found on the various devices but I don't think this is causing these
issues. I will try to look further into this property at some point but
with msm-5.4 downstream it's quite tricky to find where these values are
represented (I got some hints from Krzysztof though where to look so
I'll try to do that soon)

I'm attaching my current diff to the email, just note that it's based on
one of my dev branches and is manually edited to remove some debug
prints etc so it will probably not apply anywhere. I can also push the
git tree somewhere in case that's helpful.

Regards
Luca
diff mbox series

Patch

diff --git a/arch/arm64/boot/dts/qcom/qcm6490-fairphone-fp5.dts b/arch/arm64/boot/dts/qcom/qcm6490-fairphone-fp5.dts
index 6e03715073ec..1c56f5c85571 100644
--- a/arch/arm64/boot/dts/qcom/qcm6490-fairphone-fp5.dts
+++ b/arch/arm64/boot/dts/qcom/qcm6490-fairphone-fp5.dts
@@ -337,6 +337,38 @@  fake-reg-mclk3 {
 		clocks = <&camcc CAM_CC_MCLK3_CLK>;
 		regulator-always-on;
 	};
+
+	wcd9385: audio-codec-1 {
+		compatible = "qcom,wcd9385-codec";
+
+		pinctrl-0 = <&wcd_default>;
+		pinctrl-names = "default";
+
+		reset-gpios = <&tlmm 83 GPIO_ACTIVE_LOW>;
+
+		qcom,rx-device = <&wcd_rx>;
+		qcom,tx-device = <&wcd_tx>;
+
+		vdd-rxtx-supply = <&vreg_l18b>;
+		vdd-io-supply = <&vreg_l18b>; // ???
+		vdd-buck-supply = <&vreg_l17b>;
+		vdd-mic-bias-supply = <&vreg_bob>;
+
+		qcom,micbias1-microvolt = <1800000>;
+		qcom,micbias2-microvolt = <1800000>;
+		qcom,micbias3-microvolt = <1800000>;
+		qcom,micbias4-microvolt = <1800000>;
+
+		// FIXME validate those
+		qcom,mbhc-buttons-vthreshold-microvolt = <75000 150000 237000 500000 500000
+							  500000 500000 500000>;
+		qcom,mbhc-headset-vthreshold-microvolt = <1700000>;
+		qcom,mbhc-headphone-vthreshold-microvolt = <50000>;
+		#sound-dai-cells = <1>;
+	};
 };
 
 &apps_rsc {
@@ -713,6 +794,43 @@  &ipa {
 	status = "okay";
 };
 
+&lpass_rx_macro {
+	status = "okay";
+};
+
+&lpass_tx_macro {
+	status = "okay";
+};
+
+&lpass_va_macro {
+	status = "okay";
+};
+
+&lpass_rx_swr_clk {
+	drive-strength = <2>;
+	slew-rate = <1>;
+	bias-disable;
+};
+
+&lpass_rx_swr_data {
+	drive-strength = <2>;
+	slew-rate = <1>;
+	bias-bus-hold;
+};
+
+&lpass_tx_swr_clk {
+	drive-strength = <2>;
+	slew-rate = <1>;
+	bias-disable;
+};
+
+&lpass_tx_swr_data {
+	drive-strength = <2>;
+	slew-rate = <1>;
+	bias-bus-hold;
+};
+
 &mdss {
 	status = "okay";
 };
@@ -1083,6 +1215,35 @@  cpu {
 		};
 	};
 
+	wcd-capture-dai-link {
+		link-name = "WCD Capture";
+
+		cpu {
+			sound-dai = <&q6afedai TX_CODEC_DMA_TX_3>;
+		};
+
+		codec {
+			sound-dai = <&wcd9385 1>, <&swr1 0>, <&lpass_tx_macro 0>;
+		};
+	};
+
 	displayport-rx-dai-link {
 		link-name = "DisplayPort Playback";
 
@@ -1130,6 +1291,27 @@  goodix-berlin@0 {
 	};
 };
 
+&swr0 {
+	status = "okay";
+
+	wcd_rx: codec@0,4 {
+		compatible = "sdw20217010d00";
+		reg = <0 4>;
+		qcom,rx-port-mapping = <1 2 3 4 5>; // TODO no clue if correct
+	};
+};
+
+&swr1 {
+	status = "okay";
+
+	wcd_tx: codec@0,3 {
+		compatible = "sdw20217010d00";
+		reg = <0 3>;
+		qcom,tx-port-mapping = <1 2 3 4>; // TODO no clue if correct
+		//qcom,tx-port-mapping = <1 1 2 3>; // TODO no clue if correct
+	};
+};
+
 &tlmm {
 	/*
 	 * 32-33: SMB1394 (SPMI)
@@ -1252,6 +1434,27 @@  usb_redrive_1v8_en_default: usb-redrive-1v8-en-default-state {
 		bias-disable;
 		output-high;
 	};
+
+	wcd_default: wcd-reset-n-active-state {
+		pins = "gpio83";
+		function = "gpio";
+		drive-strength = <16>;
+		bias-disable;
+		output-low;
+	};
 };
 
 &uart5 {
diff --git a/arch/arm64/boot/dts/qcom/sc7280.dtsi b/arch/arm64/boot/dts/qcom/sc7280.dtsi
index 651def7796b0..e34bcf95874c 100644
--- a/arch/arm64/boot/dts/qcom/sc7280.dtsi
+++ b/arch/arm64/boot/dts/qcom/sc7280.dtsi
@@ -26,6 +26,7 @@ 
 #include <dt-bindings/soc/qcom,apr.h>
 #include <dt-bindings/soc/qcom,rpmh-rsc.h>
 #include <dt-bindings/sound/qcom,lpass.h>
+#include <dt-bindings/sound/qcom,q6dsp-lpass-ports.h>
 #include <dt-bindings/thermal/thermal.h>
 
 / {
@@ -2390,14 +2391,16 @@  lpass_rx_macro: codec@3200000 {
 			pinctrl-names = "default";
 			pinctrl-0 = <&lpass_rx_swr_clk>, <&lpass_rx_swr_data>;
 
-			clocks = <&lpass_aon LPASS_AON_CC_TX_MCLK_CLK>,
-				 <&lpass_aon LPASS_AON_CC_TX_MCLK_2X_CLK>,
+			clocks = <&q6afecc LPASS_CLK_ID_RX_CORE_MCLK LPASS_CLK_ATTRIBUTE_COUPLE_NO>,
+				 <&q6afecc LPASS_CLK_ID_RX_CORE_NPL_MCLK LPASS_CLK_ATTRIBUTE_COUPLE_NO>,
+				 <&q6afecc LPASS_HW_MACRO_VOTE LPASS_CLK_ATTRIBUTE_COUPLE_NO>,
+				 <&q6afecc LPASS_HW_DCODEC_VOTE LPASS_CLK_ATTRIBUTE_COUPLE_NO>,
 				 <&lpass_va_macro>;
-			clock-names = "mclk", "npl", "fsgen";
+			clock-names = "mclk", "npl", "macro", "dcodec", "fsgen";
 
-			power-domains = <&lpass_hm LPASS_CORE_CC_LPASS_CORE_HM_GDSC>,
-					<&lpass_aon LPASS_AON_CC_LPASS_AUDIO_HM_GDSC>;
-			power-domain-names = "macro", "dcodec";
+			assigned-clocks = <&q6afecc LPASS_CLK_ID_RX_CORE_MCLK LPASS_CLK_ATTRIBUTE_COUPLE_NO>,
+					  <&q6afecc LPASS_CLK_ID_RX_CORE_NPL_MCLK LPASS_CLK_ATTRIBUTE_COUPLE_NO>;
+			assigned-clock-rates = <22579200>, <22579200>;
 
 			#clock-cells = <0>;
 			#sound-dai-cells = <1>;
@@ -2416,9 +2419,6 @@  swr0: soundwire@3210000 {
 			qcom,din-ports = <0>;
 			qcom,dout-ports = <5>;
 
-			resets = <&lpass_audiocc LPASS_AUDIO_SWR_RX_CGCR>;
-			reset-names = "swr_audio_cgcr";
-
 			qcom,ports-word-length =	/bits/ 8 <0x01 0x07 0x04 0xff 0xff>;
 			qcom,ports-sinterval-low =	/bits/ 8 <0x03 0x3f 0x1f 0x03 0x03>;
 			qcom,ports-offset1 =		/bits/ 8 <0x00 0x00 0x0b 0x01 0x01>;
@@ -2443,14 +2443,18 @@  lpass_tx_macro: codec@3220000 {
 			pinctrl-names = "default";
 			pinctrl-0 = <&lpass_tx_swr_clk>, <&lpass_tx_swr_data>;
 
-			clocks = <&lpass_aon LPASS_AON_CC_TX_MCLK_CLK>,
-				 <&lpass_aon LPASS_AON_CC_TX_MCLK_2X_CLK>,
+			clocks = <&q6afecc LPASS_CLK_ID_TX_CORE_MCLK LPASS_CLK_ATTRIBUTE_COUPLE_NO>,
+				 <&q6afecc LPASS_CLK_ID_TX_CORE_NPL_MCLK LPASS_CLK_ATTRIBUTE_COUPLE_NO>,
+				 <&q6afecc LPASS_HW_MACRO_VOTE LPASS_CLK_ATTRIBUTE_COUPLE_NO>,
+				 <&q6afecc LPASS_HW_DCODEC_VOTE LPASS_CLK_ATTRIBUTE_COUPLE_NO>,
 				 <&lpass_va_macro>;
-			clock-names = "mclk", "npl", "fsgen";
+			clock-names = "mclk", "npl", "macro", "dcodec", "fsgen";
 
-			power-domains = <&lpass_hm LPASS_CORE_CC_LPASS_CORE_HM_GDSC>,
-					<&lpass_aon LPASS_AON_CC_LPASS_AUDIO_HM_GDSC>;
-			power-domain-names = "macro", "dcodec";
+			assigned-clocks = <&q6afecc LPASS_CLK_ID_TX_CORE_MCLK LPASS_CLK_ATTRIBUTE_COUPLE_NO>,
+					  <&q6afecc LPASS_CLK_ID_TX_CORE_NPL_MCLK LPASS_CLK_ATTRIBUTE_COUPLE_NO>;
+			assigned-clock-rates = <19200000>, <19200000>;
+
+			clock-output-names = "mclk";
 
 			#clock-cells = <0>;
 			#sound-dai-cells = <1>;
@@ -2470,9 +2474,6 @@  swr1: soundwire@3230000 {
 			qcom,din-ports = <3>;
 			qcom,dout-ports = <0>;
 
-			resets = <&lpass_audiocc LPASS_AUDIO_SWR_TX_CGCR>;
-			reset-names = "swr_audio_cgcr";
-
 			qcom,ports-sinterval-low =	/bits/ 8 <0x01 0x03 0x03>;
 			qcom,ports-offset1 =		/bits/ 8 <0x01 0x00 0x02>;
 			qcom,ports-offset2 =		/bits/ 8 <0x00 0x00 0x00>;
@@ -2501,21 +2502,23 @@  lpass_audiocc: clock-controller@3300000 {
 			#clock-cells = <1>;
 			#power-domain-cells = <1>;
 			#reset-cells = <1>;
+
+			status = "reserved"; /* Owned by ADSP firmware */
 		};
 
 		lpass_va_macro: codec@3370000 {
 			compatible = "qcom,sc7280-lpass-va-macro";
 			reg = <0 0x03370000 0 0x1000>;
 
-			pinctrl-names = "default";
-			pinctrl-0 = <&lpass_dmic01_clk>, <&lpass_dmic01_data>;
+			clocks = <&q6afecc LPASS_CLK_ID_VA_CORE_MCLK LPASS_CLK_ATTRIBUTE_COUPLE_NO>,
+				 <&q6afecc LPASS_HW_MACRO_VOTE LPASS_CLK_ATTRIBUTE_COUPLE_NO>,
+				 <&q6afecc LPASS_HW_DCODEC_VOTE LPASS_CLK_ATTRIBUTE_COUPLE_NO>,
+				 <&q6afecc LPASS_CLK_ID_VA_CORE_2X_MCLK LPASS_CLK_ATTRIBUTE_COUPLE_NO>;
+			clock-names = "mclk", "macro", "dcodec", "npl";
 
-			clocks = <&lpass_aon LPASS_AON_CC_TX_MCLK_CLK>;
-			clock-names = "mclk";
-
-			power-domains = <&lpass_hm LPASS_CORE_CC_LPASS_CORE_HM_GDSC>,
-					<&lpass_aon LPASS_AON_CC_LPASS_AUDIO_HM_GDSC>;
-			power-domain-names = "macro", "dcodec";
+			assigned-clocks = <&q6afecc LPASS_CLK_ID_VA_CORE_MCLK LPASS_CLK_ATTRIBUTE_COUPLE_NO>,
+					  <&q6afecc LPASS_CLK_ID_VA_CORE_2X_MCLK LPASS_CLK_ATTRIBUTE_COUPLE_NO>;
+			assigned-clock-rates = <19200000>, <19200000>;
 
 			#clock-cells = <0>;
 			#sound-dai-cells = <1>;
@@ -2632,6 +2635,10 @@  lpass_tlmm: pinctrl@33c0000 {
 			#gpio-cells = <2>;
 			gpio-ranges = <&lpass_tlmm 0 0 15>;
 
+			clocks = <&q6afecc LPASS_HW_MACRO_VOTE LPASS_CLK_ATTRIBUTE_COUPLE_NO>,
+				 <&q6afecc LPASS_HW_DCODEC_VOTE LPASS_CLK_ATTRIBUTE_COUPLE_NO>;
+			clock-names = "core", "audio";
+
 			lpass_dmic01_clk: dmic01-clk-state {
 				pins = "gpio6";
 				function = "dmic1_clk";
diff --git a/sound/soc/codecs/lpass-tx-macro.c b/sound/soc/codecs/lpass-tx-macro.c
index 82f9873ffada..0d861c056462 100644
--- a/sound/soc/codecs/lpass-tx-macro.c
+++ b/sound/soc/codecs/lpass-tx-macro.c
@@ -1998,18 +1998,18 @@  static int tx_macro_probe(struct platform_device *pdev)
 	}
 
 	/* Update defaults for lpass sc7280 */
-	if (of_device_is_compatible(np, "qcom,sc7280-lpass-tx-macro")) {
-		for (reg = 0; reg < ARRAY_SIZE(tx_defaults); reg++) {
-			switch (tx_defaults[reg].reg) {
-			case CDC_TX_TOP_CSR_SWR_AMIC0_CTL:
-			case CDC_TX_TOP_CSR_SWR_AMIC1_CTL:
-				tx_defaults[reg].def = 0x0E;
-				break;
-			default:
-				break;
-			}
-		}
-	}
+	//if (of_device_is_compatible(np, "qcom,sc7280-lpass-tx-macro")) {
+	//	for (reg = 0; reg < ARRAY_SIZE(tx_defaults); reg++) {
+	//		switch (tx_defaults[reg].reg) {
+	//		case CDC_TX_TOP_CSR_SWR_AMIC0_CTL:
+	//		case CDC_TX_TOP_CSR_SWR_AMIC1_CTL:
+	//			tx_defaults[reg].def = 0x0E;
+	//			break;
+	//		default:
+	//			break;
+	//		}
+	//	}
+	//}
 
 	tx->regmap = devm_regmap_init_mmio(dev, base, &tx_regmap_config);
 	if (IS_ERR(tx->regmap)) {
@@ -2162,7 +2162,7 @@  static const struct dev_pm_ops tx_macro_pm_ops = {
 static const struct of_device_id tx_macro_dt_match[] = {
 	{
 		.compatible = "qcom,sc7280-lpass-tx-macro",
-		.data = (void *)(LPASS_MACRO_FLAG_HAS_NPL_CLOCK | LPASS_MACRO_FLAG_RESET_SWR),
+		.data = (void *)LPASS_MACRO_FLAG_HAS_NPL_CLOCK,
 	}, {
 		.compatible = "qcom,sm6115-lpass-tx-macro",
 		.data = (void *)LPASS_MACRO_FLAG_HAS_NPL_CLOCK,
diff --git a/sound/soc/codecs/wcd938x-sdw.c b/sound/soc/codecs/wcd938x-sdw.c
index a1f04010da95..24cb95a6affd 100644
--- a/sound/soc/codecs/wcd938x-sdw.c
+++ b/sound/soc/codecs/wcd938x-sdw.c
@@ -1272,11 +1272,12 @@  static int wcd9380_probe(struct sdw_slave *pdev,
 		regcache_cache_only(wcd->regmap, true);
 	}
 
-	pm_runtime_set_autosuspend_delay(dev, 3000);
+	pm_runtime_set_autosuspend_delay(dev, 10000);
 	pm_runtime_use_autosuspend(dev);
 	pm_runtime_mark_last_busy(dev);
 	pm_runtime_set_active(dev);
 	pm_runtime_enable(dev);
 
 	ret = component_add(dev, &wcd938x_sdw_component_ops);
 	if (ret)
diff --git a/sound/soc/codecs/wcd938x.c b/sound/soc/codecs/wcd938x.c
index faf8d3f9b3c5..104b7ab160fc 100644
--- a/sound/soc/codecs/wcd938x.c
+++ b/sound/soc/codecs/wcd938x.c
@@ -3096,12 +3096,14 @@  static int wcd938x_soc_codec_probe(struct snd_soc_component *component)
 	unsigned long time_left;
 	int ret, i;
 
 	time_left = wait_for_completion_timeout(&tx_sdw_dev->initialization_complete,
-						msecs_to_jiffies(2000));
+						msecs_to_jiffies(20000));
 	if (!time_left) {
 		dev_err(dev, "soundwire device init timeout\n");
 		return -ETIMEDOUT;
 	}
 
 	snd_soc_component_init_regmap(component, wcd938x->regmap);