diff --git a/arch/arm64/boot/dts/qcom/Makefile b/arch/arm64/boot/dts/qcom/Makefile index 88230c4e00ea9..7332a73dbac71 100644 --- a/arch/arm64/boot/dts/qcom/Makefile +++ b/arch/arm64/boot/dts/qcom/Makefile @@ -509,6 +509,7 @@ x1e80100-qcp-el2-dtbs := x1e80100-qcp.dtb x1-el2.dtbo dtb-$(CONFIG_ARCH_QCOM) += x1e80100-qcp.dtb x1e80100-qcp-el2.dtb x1p42100-asus-vivobook-s15-el2-dtbs := x1p42100-asus-vivobook-s15.dtb x1-el2.dtbo dtb-$(CONFIG_ARCH_QCOM) += x1p42100-asus-vivobook-s15.dtb x1p42100-asus-vivobook-s15-el2.dtb +dtb-$(CONFIG_ARCH_QCOM) += x1p42100-asus-vivobook-16-x1607qa.dtb x1p42100-asus-zenbook-a14-el2-dtbs := x1p42100-asus-zenbook-a14.dtb x1-el2.dtbo dtb-$(CONFIG_ARCH_QCOM) += x1p42100-asus-zenbook-a14.dtb x1p42100-asus-zenbook-a14-el2.dtb x1p42100-asus-zenbook-a14-lcd-el2-dtbs := x1p42100-asus-zenbook-a14-lcd.dtb x1-el2.dtbo diff --git a/arch/arm64/boot/dts/qcom/x1p42100-asus-vivobook-16-x1607qa.dts b/arch/arm64/boot/dts/qcom/x1p42100-asus-vivobook-16-x1607qa.dts new file mode 100644 index 0000000000000..fc572d779b311 --- /dev/null +++ b/arch/arm64/boot/dts/qcom/x1p42100-asus-vivobook-16-x1607qa.dts @@ -0,0 +1,239 @@ +// SPDX-License-Identifier: BSD-3-Clause +/* Hybrid device tree for ASUS Vivobook 16 X1607QA (X1P-42-100). + * Base: proven x1p42100-asus-vivobook-s15 (panel, USB, boot path). + * Transplanted from x126100-asus-vivobook-16: audio stack + * (WCD9385 codec, WSA8845 speakers, soundwire, sndcard) + firmware paths. + */ + +/dts-v1/; + +#include "purwa.dtsi" +#include "x1-asus-vivobook-s15.dtsi" + +/ { + model = "ASUS Vivobook 16 (X1607QA)"; + compatible = "asus,vivobook-16-x1607qa", "qcom,x1p42100"; + chassis-type = "laptop"; +}; + +/* Speaker VDD-IO rail, from vivobook-16 board regulators */ +&apps_rsc { + regulators-0 { + vreg_l12b_1p2: ldo12 { + regulator-name = "vreg_l12b_1p2"; + regulator-min-microvolt = <1200000>; + regulator-max-microvolt = <1200000>; + regulator-initial-mode = ; + regulator-always-on; + }; + }; +}; + +&tlmm { + wcd_default: wcd-reset-n-active-state { + pins = "gpio191"; + function = "gpio"; + drive-strength = <16>; + bias-disable; + output-low; + }; +}; + +&lpass_tlmm { + spkr_01_sd_n_active: spkr-01-sd-n-active-state { + pins = "gpio12"; + function = "gpio"; + drive-strength = <16>; + bias-disable; + output-low; + }; +}; + +&lpass_vamacro { + pinctrl-0 = <&dmic01_default>; + pinctrl-names = "default"; +}; + +/ { + wcd938x: audio-codec { + compatible = "qcom,wcd9385-codec"; + + pinctrl-0 = <&wcd_default>; + pinctrl-names = "default"; + + qcom,micbias1-microvolt = <1800000>; + qcom,micbias2-microvolt = <1800000>; + qcom,micbias3-microvolt = <1800000>; + qcom,micbias4-microvolt = <1800000>; + 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>; + qcom,rx-device = <&wcd_rx>; + qcom,tx-device = <&wcd_tx>; + + reset-gpios = <&tlmm 191 GPIO_ACTIVE_LOW>; + + vdd-buck-supply = <&vreg_l15b_1p8>; + vdd-rxtx-supply = <&vreg_l15b_1p8>; + vdd-io-supply = <&vreg_l15b_1p8>; + vdd-mic-bias-supply = <&vreg_bob1>; + + #sound-dai-cells = <1>; + }; + + sound { + compatible = "qcom,x1e80100-sndcard"; + model = "X1E80100-ASUS-Vivobook-16"; + audio-routing = "SpkrLeft IN", "WSA WSA_SPK1 OUT", + "SpkrRight IN", "WSA WSA_SPK2 OUT", + "IN1_HPHL", "HPHL_OUT", + "IN2_HPHR", "HPHR_OUT", + "AMIC2", "MIC BIAS2", + "VA DMIC0", "MIC BIAS1", + "VA DMIC1", "MIC BIAS1", + "VA DMIC0", "VA MIC BIAS1", + "VA DMIC1", "VA MIC BIAS1", + "TX SWR_INPUT1", "ADC2_OUTPUT"; + + wcd-playback-dai-link { + link-name = "WCD Playback"; + + cpu { + sound-dai = <&q6apmbedai RX_CODEC_DMA_RX_0>; + }; + + codec { + sound-dai = <&wcd938x 0>, <&swr1 0>, <&lpass_rxmacro 0>; + }; + + platform { + sound-dai = <&q6apm>; + }; + }; + + wcd-capture-dai-link { + link-name = "WCD Capture"; + + cpu { + sound-dai = <&q6apmbedai TX_CODEC_DMA_TX_3>; + }; + + codec { + sound-dai = <&wcd938x 1>, <&swr2 1>, <&lpass_txmacro 0>; + }; + + platform { + sound-dai = <&q6apm>; + }; + }; + + va-dai-link { + link-name = "VA Capture"; + + codec { + sound-dai = <&lpass_vamacro 0>; + }; + + cpu { + sound-dai = <&q6apmbedai VA_CODEC_DMA_TX_0>; + }; + + platform { + sound-dai = <&q6apm>; + }; + }; + + wsa-dai-link { + link-name = "WSA Playback"; + + codec { + sound-dai = <&left_spkr>, <&right_spkr>, + <&swr0 0>, <&lpass_wsamacro 0>; + }; + + cpu { + sound-dai = <&q6apmbedai WSA_CODEC_DMA_RX_0>; + }; + + platform { + sound-dai = <&q6apm>; + }; + }; + }; +}; + +&swr0 { + status = "okay"; + + pinctrl-0 = <&wsa_swr_active>, <&spkr_01_sd_n_active>; + pinctrl-names = "default"; + + /* WSA8845, Left Speaker */ + left_spkr: speaker@0,0 { + compatible = "sdw20217020400"; + reg = <0 0>; + reset-gpios = <&lpass_tlmm 12 GPIO_ACTIVE_LOW>; + #sound-dai-cells = <0>; + sound-name-prefix = "SpkrLeft"; + vdd-1p8-supply = <&vreg_l15b_1p8>; + vdd-io-supply = <&vreg_l12b_1p2>; + qcom,port-mapping = <1 2 3 7 10 13>; + }; + + /* WSA8845, Right Speaker */ + right_spkr: speaker@0,1 { + compatible = "sdw20217020400"; + reg = <0 1>; + reset-gpios = <&lpass_tlmm 12 GPIO_ACTIVE_LOW>; + #sound-dai-cells = <0>; + sound-name-prefix = "SpkrRight"; + vdd-1p8-supply = <&vreg_l15b_1p8>; + vdd-io-supply = <&vreg_l12b_1p2>; + qcom,port-mapping = <4 5 6 7 11 13>; + }; +}; + +&swr1 { + status = "okay"; + + /* WCD9385 RX */ + wcd_rx: codec@0,4 { + compatible = "sdw20217010d00"; + reg = <0 4>; + qcom,rx-port-mapping = <1 2 3 4 5>; + }; +}; + +&swr2 { + status = "okay"; + + /* WCD9385 TX */ + wcd_tx: codec@0,3 { + compatible = "sdw20217010d00"; + reg = <0 3>; + qcom,tx-port-mapping = <2 2 3 4>; + }; +}; + +&remoteproc_adsp { + firmware-name = "qcom/x1p42100/ASUSTeK/vivobook-16-x1607qa/qcadsp8380.mbn", + "qcom/x1p42100/ASUSTeK/vivobook-16-x1607qa/adsp_dtbs.elf"; + + status = "okay"; +}; + +&remoteproc_cdsp { + firmware-name = "qcom/x1p42100/ASUSTeK/vivobook-16-x1607qa/qccdsp8380.mbn", + "qcom/x1p42100/ASUSTeK/vivobook-16-x1607qa/cdsp_dtbs.elf"; + + status = "okay"; +}; + +&gpu { + status = "okay"; + + zap-shader { + firmware-name = "qcom/x1p42100/ASUSTeK/vivobook-16-x1607qa/qcdxkmsucpurwa.mbn"; + }; +}; diff --git a/drivers/soundwire/qcom.c b/drivers/soundwire/qcom.c index 6e0c5fb10efad..cb50cf239cdf4 100644 --- a/drivers/soundwire/qcom.c +++ b/drivers/soundwire/qcom.c @@ -21,6 +21,41 @@ #include #include #include "bus.h" +#include + +/* + * Bounded retry for deferred clock providers. Clock-provider registration + * does not trigger deferred-probe retries, so a consumer that loses the + * probe-order race stays deferred forever. Wait up to 30 s for providers + * that are registered milliseconds later. + */ +static struct clk *clk_get_retry(struct device *dev, const char *id) +{ + struct clk *c; + int i; + + for (i = 0; i < 60; i++) { + c = devm_clk_get(dev, id); + if (!IS_ERR(c) || PTR_ERR(c) != -EPROBE_DEFER) + return c; + msleep(500); + } + return c; +} + +static struct clk *clk_get_retry_optional(struct device *dev, const char *id) +{ + struct clk *c; + int i; + + for (i = 0; i < 60; i++) { + c = devm_clk_get_optional(dev, id); + if (!IS_ERR(c) || PTR_ERR(c) != -EPROBE_DEFER) + return c; + msleep(500); + } + return c; +} #define SWRM_COMP_SW_RESET 0x008 #define SWRM_COMP_STATUS 0x014 @@ -1669,7 +1704,7 @@ static int qcom_swrm_probe(struct platform_device *pdev) goto err_init; } - ctrl->hclk = devm_clk_get(dev, "iface"); + ctrl->hclk = clk_get_retry(dev, "iface"); if (IS_ERR(ctrl->hclk)) { ret = dev_err_probe(dev, PTR_ERR(ctrl->hclk), "unable to get iface clock\n"); goto err_init; diff --git a/sound/soc/codecs/lpass-rx-macro.c b/sound/soc/codecs/lpass-rx-macro.c index c41eb8de61609..5d893960dd885 100644 --- a/sound/soc/codecs/lpass-rx-macro.c +++ b/sound/soc/codecs/lpass-rx-macro.c @@ -18,6 +18,41 @@ #include #include "lpass-macro-common.h" +#include + +/* + * Bounded retry for deferred clock providers. Clock-provider registration + * does not trigger deferred-probe retries, so a consumer that loses the + * probe-order race stays deferred forever. Wait up to 30 s for providers + * that are registered milliseconds later. + */ +static struct clk *clk_get_retry(struct device *dev, const char *id) +{ + struct clk *c; + int i; + + for (i = 0; i < 60; i++) { + c = devm_clk_get(dev, id); + if (!IS_ERR(c) || PTR_ERR(c) != -EPROBE_DEFER) + return c; + msleep(500); + } + return c; +} + +static struct clk *clk_get_retry_optional(struct device *dev, const char *id) +{ + struct clk *c; + int i; + + for (i = 0; i < 60; i++) { + c = devm_clk_get_optional(dev, id); + if (!IS_ERR(c) || PTR_ERR(c) != -EPROBE_DEFER) + return c; + msleep(500); + } + return c; +} #define CDC_RX_TOP_TOP_CFG0 (0x0000) #define CDC_RX_TOP_SWR_CTRL (0x0008) @@ -3780,25 +3815,25 @@ static int rx_macro_probe(struct platform_device *pdev) if (!rx) return -ENOMEM; - rx->macro = devm_clk_get_optional(dev, "macro"); + rx->macro = clk_get_retry_optional(dev, "macro"); if (IS_ERR(rx->macro)) return dev_err_probe(dev, PTR_ERR(rx->macro), "unable to get macro clock\n"); - rx->dcodec = devm_clk_get_optional(dev, "dcodec"); + rx->dcodec = clk_get_retry_optional(dev, "dcodec"); if (IS_ERR(rx->dcodec)) return dev_err_probe(dev, PTR_ERR(rx->dcodec), "unable to get dcodec clock\n"); - rx->mclk = devm_clk_get(dev, "mclk"); + rx->mclk = clk_get_retry(dev, "mclk"); if (IS_ERR(rx->mclk)) return dev_err_probe(dev, PTR_ERR(rx->mclk), "unable to get mclk clock\n"); if (flags & LPASS_MACRO_FLAG_HAS_NPL_CLOCK) { - rx->npl = devm_clk_get(dev, "npl"); + rx->npl = clk_get_retry(dev, "npl"); if (IS_ERR(rx->npl)) return dev_err_probe(dev, PTR_ERR(rx->npl), "unable to get npl clock\n"); } - rx->fsgen = devm_clk_get(dev, "fsgen"); + rx->fsgen = clk_get_retry(dev, "fsgen"); if (IS_ERR(rx->fsgen)) return dev_err_probe(dev, PTR_ERR(rx->fsgen), "unable to get fsgen clock\n"); diff --git a/sound/soc/codecs/lpass-tx-macro.c b/sound/soc/codecs/lpass-tx-macro.c index 6deaaabe43afa..4b8635cc2b2f8 100644 --- a/sound/soc/codecs/lpass-tx-macro.c +++ b/sound/soc/codecs/lpass-tx-macro.c @@ -16,6 +16,41 @@ #include #include "lpass-macro-common.h" +#include + +/* + * Bounded retry for deferred clock providers. Clock-provider registration + * does not trigger deferred-probe retries, so a consumer that loses the + * probe-order race stays deferred forever. Wait up to 30 s for providers + * that are registered milliseconds later. + */ +static struct clk *clk_get_retry(struct device *dev, const char *id) +{ + struct clk *c; + int i; + + for (i = 0; i < 60; i++) { + c = devm_clk_get(dev, id); + if (!IS_ERR(c) || PTR_ERR(c) != -EPROBE_DEFER) + return c; + msleep(500); + } + return c; +} + +static struct clk *clk_get_retry_optional(struct device *dev, const char *id) +{ + struct clk *c; + int i; + + for (i = 0; i < 60; i++) { + c = devm_clk_get_optional(dev, id); + if (!IS_ERR(c) || PTR_ERR(c) != -EPROBE_DEFER) + return c; + msleep(500); + } + return c; +} #define CDC_TX_CLK_RST_CTRL_MCLK_CONTROL (0x0000) #define CDC_TX_MCLK_EN_MASK BIT(0) @@ -2258,25 +2293,25 @@ static int tx_macro_probe(struct platform_device *pdev) tx->data = device_get_match_data(dev); - tx->macro = devm_clk_get_optional(dev, "macro"); + tx->macro = clk_get_retry_optional(dev, "macro"); if (IS_ERR(tx->macro)) return dev_err_probe(dev, PTR_ERR(tx->macro), "unable to get macro clock\n"); - tx->dcodec = devm_clk_get_optional(dev, "dcodec"); + tx->dcodec = clk_get_retry_optional(dev, "dcodec"); if (IS_ERR(tx->dcodec)) return dev_err_probe(dev, PTR_ERR(tx->dcodec), "unable to get dcodec clock\n"); - tx->mclk = devm_clk_get(dev, "mclk"); + tx->mclk = clk_get_retry(dev, "mclk"); if (IS_ERR(tx->mclk)) return dev_err_probe(dev, PTR_ERR(tx->mclk), "unable to get mclk clock\n"); if (tx->data->flags & LPASS_MACRO_FLAG_HAS_NPL_CLOCK) { - tx->npl = devm_clk_get(dev, "npl"); + tx->npl = clk_get_retry(dev, "npl"); if (IS_ERR(tx->npl)) return dev_err_probe(dev, PTR_ERR(tx->npl), "unable to get npl clock\n"); } - tx->fsgen = devm_clk_get(dev, "fsgen"); + tx->fsgen = clk_get_retry(dev, "fsgen"); if (IS_ERR(tx->fsgen)) return dev_err_probe(dev, PTR_ERR(tx->fsgen), "unable to get fsgen clock\n"); diff --git a/sound/soc/codecs/lpass-va-macro.c b/sound/soc/codecs/lpass-va-macro.c index 03d6434a4a126..fda1bbada11df 100644 --- a/sound/soc/codecs/lpass-va-macro.c +++ b/sound/soc/codecs/lpass-va-macro.c @@ -19,6 +19,41 @@ #include #include "lpass-macro-common.h" +#include + +/* + * Bounded retry for deferred clock providers. Clock-provider registration + * does not trigger deferred-probe retries, so a consumer that loses the + * probe-order race stays deferred forever. Wait up to 30 s for providers + * that are registered milliseconds later. + */ +static struct clk *clk_get_retry(struct device *dev, const char *id) +{ + struct clk *c; + int i; + + for (i = 0; i < 60; i++) { + c = devm_clk_get(dev, id); + if (!IS_ERR(c) || PTR_ERR(c) != -EPROBE_DEFER) + return c; + msleep(500); + } + return c; +} + +static struct clk *clk_get_retry_optional(struct device *dev, const char *id) +{ + struct clk *c; + int i; + + for (i = 0; i < 60; i++) { + c = devm_clk_get_optional(dev, id); + if (!IS_ERR(c) || PTR_ERR(c) != -EPROBE_DEFER) + return c; + msleep(500); + } + return c; +} /* VA macro registers */ #define CDC_VA_CLK_RST_CTRL_MCLK_CONTROL (0x0000) @@ -1557,15 +1592,15 @@ static int va_macro_probe(struct platform_device *pdev) va->dev = dev; - va->macro = devm_clk_get_optional(dev, "macro"); + va->macro = clk_get_retry_optional(dev, "macro"); if (IS_ERR(va->macro)) return dev_err_probe(dev, PTR_ERR(va->macro), "unable to get macro clock\n"); - va->dcodec = devm_clk_get_optional(dev, "dcodec"); + va->dcodec = clk_get_retry_optional(dev, "dcodec"); if (IS_ERR(va->dcodec)) return dev_err_probe(dev, PTR_ERR(va->dcodec), "unable to get dcodec clock\n"); - va->mclk = devm_clk_get(dev, "mclk"); + va->mclk = clk_get_retry(dev, "mclk"); if (IS_ERR(va->mclk)) return dev_err_probe(dev, PTR_ERR(va->mclk), "unable to get mclk clock\n"); @@ -1610,7 +1645,7 @@ static int va_macro_probe(struct platform_device *pdev) goto err; if (va->has_npl_clk) { - va->npl = devm_clk_get(dev, "npl"); + va->npl = clk_get_retry(dev, "npl"); if (IS_ERR(va->npl)) { ret = PTR_ERR(va->npl); goto err; diff --git a/sound/soc/codecs/lpass-wsa-macro.c b/sound/soc/codecs/lpass-wsa-macro.c index 899c8bee4645f..437a0876a8bcb 100644 --- a/sound/soc/codecs/lpass-wsa-macro.c +++ b/sound/soc/codecs/lpass-wsa-macro.c @@ -19,6 +19,41 @@ #include "lpass-macro-common.h" #include "lpass-wsa-macro.h" +#include + +/* + * Bounded retry for deferred clock providers. Clock-provider registration + * does not trigger deferred-probe retries, so a consumer that loses the + * probe-order race stays deferred forever. Wait up to 30 s for providers + * that are registered milliseconds later. + */ +static struct clk *clk_get_retry(struct device *dev, const char *id) +{ + struct clk *c; + int i; + + for (i = 0; i < 60; i++) { + c = devm_clk_get(dev, id); + if (!IS_ERR(c) || PTR_ERR(c) != -EPROBE_DEFER) + return c; + msleep(500); + } + return c; +} + +static struct clk *clk_get_retry_optional(struct device *dev, const char *id) +{ + struct clk *c; + int i; + + for (i = 0; i < 60; i++) { + c = devm_clk_get_optional(dev, id); + if (!IS_ERR(c) || PTR_ERR(c) != -EPROBE_DEFER) + return c; + msleep(500); + } + return c; +} #define CDC_WSA_CLK_RST_CTRL_MCLK_CONTROL (0x0000) #define CDC_WSA_MCLK_EN_MASK BIT(0) @@ -2701,25 +2736,25 @@ static int wsa_macro_probe(struct platform_device *pdev) if (!wsa) return -ENOMEM; - wsa->macro = devm_clk_get_optional(dev, "macro"); + wsa->macro = clk_get_retry_optional(dev, "macro"); if (IS_ERR(wsa->macro)) return dev_err_probe(dev, PTR_ERR(wsa->macro), "unable to get macro clock\n"); - wsa->dcodec = devm_clk_get_optional(dev, "dcodec"); + wsa->dcodec = clk_get_retry_optional(dev, "dcodec"); if (IS_ERR(wsa->dcodec)) return dev_err_probe(dev, PTR_ERR(wsa->dcodec), "unable to get dcodec clock\n"); - wsa->mclk = devm_clk_get(dev, "mclk"); + wsa->mclk = clk_get_retry(dev, "mclk"); if (IS_ERR(wsa->mclk)) return dev_err_probe(dev, PTR_ERR(wsa->mclk), "unable to get mclk clock\n"); if (flags & LPASS_MACRO_FLAG_HAS_NPL_CLOCK) { - wsa->npl = devm_clk_get(dev, "npl"); + wsa->npl = clk_get_retry(dev, "npl"); if (IS_ERR(wsa->npl)) return dev_err_probe(dev, PTR_ERR(wsa->npl), "unable to get npl clock\n"); } - wsa->fsgen = devm_clk_get(dev, "fsgen"); + wsa->fsgen = clk_get_retry(dev, "fsgen"); if (IS_ERR(wsa->fsgen)) return dev_err_probe(dev, PTR_ERR(wsa->fsgen), "unable to get fsgen clock\n");