* [PATCH v3 1/6] ASoC: dt-bindings: es8316: Document jack detect inversion
2026-09-04 10:02 [PATCH v3 0/6] Add audio support for QCS6490 Rubik Pi 3 Hongyang Zhao
@ 2026-09-04 10:02 ` Hongyang Zhao
2026-09-04 10:02 ` [PATCH v3 2/6] ASoC: dt-bindings: qcom,sm8250: Add RubikPi 3 sound card Hongyang Zhao
` (4 subsequent siblings)
5 siblings, 0 replies; 9+ messages in thread
From: Hongyang Zhao @ 2026-09-04 10:02 UTC (permalink / raw)
To: Liam Girdwood, Mark Brown, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Daniel Drake, Katsuhiro Suzuki, Matteo Martelli,
Binbin Zhou, Srinivas Kandagatla, Jaroslav Kysela, Takashi Iwai,
Bjorn Andersson, Konrad Dybcio
Cc: Mohammad Rafi Shaik, Roger Shimizu, linux-sound, linux-kernel,
linux-arm-msm, devicetree, Hongyang Zhao, Krzysztof Kozlowski
The ES8316 driver supports the everest,jack-detect-inverted property to
account for boards which invert the codec jack-detect signal. However,
the property is not described by the binding, so a valid user of the
driver fails schema validation because the binding rejects unknown
properties.
Document the flag so boards can describe the jack-detect polarity used
by their wiring.
Acked-by: Krzysztof Kozlowski <krzysztof.kozlowski@oss.qualcomm.com>
Signed-off-by: Hongyang Zhao <hongyang.zhao@thundersoft.com>
---
Documentation/devicetree/bindings/sound/everest,es8316.yaml | 5 +++++
1 file changed, 5 insertions(+)
diff --git a/Documentation/devicetree/bindings/sound/everest,es8316.yaml b/Documentation/devicetree/bindings/sound/everest,es8316.yaml
index f4ff23120c5b..9060358a9080 100644
--- a/Documentation/devicetree/bindings/sound/everest,es8316.yaml
+++ b/Documentation/devicetree/bindings/sound/everest,es8316.yaml
@@ -84,6 +84,11 @@ properties:
"#sound-dai-cells":
const: 0
+ everest,jack-detect-inverted:
+ $ref: /schemas/types.yaml#/definitions/flag
+ description:
+ Defined to invert the jack detection.
+
required:
- compatible
- reg
--
2.43.0
^ permalink raw reply [flat|nested] 9+ messages in thread* [PATCH v3 2/6] ASoC: dt-bindings: qcom,sm8250: Add RubikPi 3 sound card
2026-09-04 10:02 [PATCH v3 0/6] Add audio support for QCS6490 Rubik Pi 3 Hongyang Zhao
2026-09-04 10:02 ` [PATCH v3 1/6] ASoC: dt-bindings: es8316: Document jack detect inversion Hongyang Zhao
@ 2026-09-04 10:02 ` Hongyang Zhao
2026-09-07 9:51 ` Krzysztof Kozlowski
2026-09-04 10:02 ` [PATCH v3 3/6] ASoC: qcom: common: Add generic headset jack helpers Hongyang Zhao
` (3 subsequent siblings)
5 siblings, 1 reply; 9+ messages in thread
From: Hongyang Zhao @ 2026-09-04 10:02 UTC (permalink / raw)
To: Liam Girdwood, Mark Brown, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Daniel Drake, Katsuhiro Suzuki, Matteo Martelli,
Binbin Zhou, Srinivas Kandagatla, Jaroslav Kysela, Takashi Iwai,
Bjorn Andersson, Konrad Dybcio
Cc: Mohammad Rafi Shaik, Roger Shimizu, linux-sound, linux-kernel,
linux-arm-msm, devicetree, Hongyang Zhao
The QCS6490-based Thundercomm RubikPi 3 routes primary MI2S to an
external ES8316 headset codec and quaternary MI2S to the LT9611 HDMI
bridge. This requires board-specific DAI clocking and jack setup in the
sc8280xp machine driver.
The existing QCM6490 and QCS6490 compatibles select machine data for
boards using different codec and audio routing arrangements, so they
cannot be used as compatible fallbacks for RubikPi 3.
Add a dedicated compatible to select the RubikPi 3 machine data.
Signed-off-by: Hongyang Zhao <hongyang.zhao@thundersoft.com>
---
Documentation/devicetree/bindings/sound/qcom,sm8250.yaml | 1 +
1 file changed, 1 insertion(+)
diff --git a/Documentation/devicetree/bindings/sound/qcom,sm8250.yaml b/Documentation/devicetree/bindings/sound/qcom,sm8250.yaml
index 1536fcd96d68..fc7bccdace0f 100644
--- a/Documentation/devicetree/bindings/sound/qcom,sm8250.yaml
+++ b/Documentation/devicetree/bindings/sound/qcom,sm8250.yaml
@@ -54,6 +54,7 @@ properties:
- qcom,sm8250-sndcard
- qcom,sm8450-sndcard
- qcom,x1e80100-sndcard
+ - thundercomm,qcs6490-rubikpi3-sndcard
audio-routing:
$ref: /schemas/types.yaml#/definitions/non-unique-string-array
--
2.43.0
^ permalink raw reply [flat|nested] 9+ messages in thread* Re: [PATCH v3 2/6] ASoC: dt-bindings: qcom,sm8250: Add RubikPi 3 sound card
2026-09-04 10:02 ` [PATCH v3 2/6] ASoC: dt-bindings: qcom,sm8250: Add RubikPi 3 sound card Hongyang Zhao
@ 2026-09-07 9:51 ` Krzysztof Kozlowski
0 siblings, 0 replies; 9+ messages in thread
From: Krzysztof Kozlowski @ 2026-09-07 9:51 UTC (permalink / raw)
To: Hongyang Zhao
Cc: Liam Girdwood, Mark Brown, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Daniel Drake, Katsuhiro Suzuki, Matteo Martelli,
Binbin Zhou, Srinivas Kandagatla, Jaroslav Kysela, Takashi Iwai,
Bjorn Andersson, Konrad Dybcio, Mohammad Rafi Shaik,
Roger Shimizu, linux-sound, linux-kernel, linux-arm-msm,
devicetree
On Fri, Sep 04, 2026 at 06:02:26PM +0800, Hongyang Zhao wrote:
> The QCS6490-based Thundercomm RubikPi 3 routes primary MI2S to an
> external ES8316 headset codec and quaternary MI2S to the LT9611 HDMI
> bridge. This requires board-specific DAI clocking and jack setup in the
> sc8280xp machine driver.
>
> The existing QCM6490 and QCS6490 compatibles select machine data for
> boards using different codec and audio routing arrangements, so they
> cannot be used as compatible fallbacks for RubikPi 3.
>
> Add a dedicated compatible to select the RubikPi 3 machine data.
>
> Signed-off-by: Hongyang Zhao <hongyang.zhao@thundersoft.com>
> ---
> Documentation/devicetree/bindings/sound/qcom,sm8250.yaml | 1 +
> 1 file changed, 1 insertion(+)
Acked-by: Krzysztof Kozlowski <krzysztof.kozlowski@oss.qualcomm.com>
Best regards,
Krzysztof
^ permalink raw reply [flat|nested] 9+ messages in thread
* [PATCH v3 3/6] ASoC: qcom: common: Add generic headset jack helpers
2026-09-04 10:02 [PATCH v3 0/6] Add audio support for QCS6490 Rubik Pi 3 Hongyang Zhao
2026-09-04 10:02 ` [PATCH v3 1/6] ASoC: dt-bindings: es8316: Document jack detect inversion Hongyang Zhao
2026-09-04 10:02 ` [PATCH v3 2/6] ASoC: dt-bindings: qcom,sm8250: Add RubikPi 3 sound card Hongyang Zhao
@ 2026-09-04 10:02 ` Hongyang Zhao
2026-09-04 10:02 ` [PATCH v3 4/6] ASoC: qcom: sc8280xp: Add per-DAI board configuration Hongyang Zhao
` (2 subsequent siblings)
5 siblings, 0 replies; 9+ messages in thread
From: Hongyang Zhao @ 2026-09-04 10:02 UTC (permalink / raw)
To: Liam Girdwood, Mark Brown, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Daniel Drake, Katsuhiro Suzuki, Matteo Martelli,
Binbin Zhou, Srinivas Kandagatla, Jaroslav Kysela, Takashi Iwai,
Bjorn Andersson, Konrad Dybcio
Cc: Mohammad Rafi Shaik, Roger Shimizu, linux-sound, linux-kernel,
linux-arm-msm, devicetree, Hongyang Zhao
qcom_snd_wcd_jack_setup() combines creation of the card-level headset
jack with the WCD-specific operation of attaching jack detection to
codecs on the TX codec DMA links. External codecs connected over MI2S
also provide component jack detection, but cannot use the WCD-specific
DAI filtering.
Factor the common jack allocation, DAPM pin registration and headset
button mappings into a private initializer. Reuse it from the existing
WCD path and add a generic setup helper which attaches the jack to every
codec component in a runtime.
Treat -ENOTSUPP as a no-op because snd_soc_component_set_jack() uses it
for components which do not provide a set_jack callback.
Add a matching cleanup helper so machine drivers can detach component
jack detection when the DAI link exits. The WCD setup behavior remains
unchanged.
Signed-off-by: Hongyang Zhao <hongyang.zhao@thundersoft.com>
---
sound/soc/qcom/common.c | 61 ++++++++++++++++++++++++++++++++++++++++++-------
sound/soc/qcom/common.h | 3 +++
2 files changed, 56 insertions(+), 8 deletions(-)
diff --git a/sound/soc/qcom/common.c b/sound/soc/qcom/common.c
index d9f256d51973..83b745f617a8 100644
--- a/sound/soc/qcom/common.c
+++ b/sound/soc/qcom/common.c
@@ -339,13 +339,11 @@ static struct snd_soc_jack_pin qcom_headset_jack_pins[] = {
},
};
-int qcom_snd_wcd_jack_setup(struct snd_soc_pcm_runtime *rtd,
- struct snd_soc_jack *jack, bool *jack_setup)
+static int qcom_snd_headset_jack_init(struct snd_soc_card *card,
+ struct snd_soc_jack *jack,
+ bool *jack_setup)
{
- struct snd_soc_dai *cpu_dai = snd_soc_rtd_to_cpu(rtd, 0);
- struct snd_soc_dai *codec_dai = snd_soc_rtd_to_codec(rtd, 0);
- struct snd_soc_card *card = rtd->card;
- int rval, i;
+ int rval;
if (!*jack_setup) {
rval = snd_soc_card_jack_new_pins(card, "Headset Jack",
@@ -369,6 +367,55 @@ int qcom_snd_wcd_jack_setup(struct snd_soc_pcm_runtime *rtd,
*jack_setup = true;
}
+ return 0;
+}
+
+int qcom_snd_headset_jack_setup(struct snd_soc_pcm_runtime *rtd,
+ struct snd_soc_jack *jack, bool *jack_setup)
+{
+ struct snd_soc_dai *codec_dai;
+ struct snd_soc_card *card = rtd->card;
+ int rval, i;
+
+ rval = qcom_snd_headset_jack_init(card, jack, jack_setup);
+ if (rval)
+ return rval;
+
+ for_each_rtd_codec_dais(rtd, i, codec_dai) {
+ rval = snd_soc_component_set_jack(codec_dai->component, jack, NULL);
+ if (rval != 0 && rval != -ENOTSUPP) {
+ dev_warn(card->dev, "Failed to set jack: %d\n", rval);
+ qcom_snd_headset_jack_cleanup(rtd);
+ return rval;
+ }
+ }
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(qcom_snd_headset_jack_setup);
+
+void qcom_snd_headset_jack_cleanup(struct snd_soc_pcm_runtime *rtd)
+{
+ struct snd_soc_dai *codec_dai;
+ int i;
+
+ for_each_rtd_codec_dais(rtd, i, codec_dai)
+ snd_soc_component_set_jack(codec_dai->component, NULL, NULL);
+}
+EXPORT_SYMBOL_GPL(qcom_snd_headset_jack_cleanup);
+
+int qcom_snd_wcd_jack_setup(struct snd_soc_pcm_runtime *rtd,
+ struct snd_soc_jack *jack, bool *jack_setup)
+{
+ struct snd_soc_dai *cpu_dai = snd_soc_rtd_to_cpu(rtd, 0);
+ struct snd_soc_dai *codec_dai = snd_soc_rtd_to_codec(rtd, 0);
+ struct snd_soc_card *card = rtd->card;
+ int rval, i;
+
+ rval = qcom_snd_headset_jack_init(card, jack, jack_setup);
+ if (rval)
+ return rval;
+
switch (cpu_dai->id) {
case LPI_MI2S_RX_0:
case TX_CODEC_DMA_TX_0:
@@ -388,8 +435,6 @@ int qcom_snd_wcd_jack_setup(struct snd_soc_pcm_runtime *rtd,
default:
break;
}
-
-
return 0;
}
EXPORT_SYMBOL_GPL(qcom_snd_wcd_jack_setup);
diff --git a/sound/soc/qcom/common.h b/sound/soc/qcom/common.h
index c1deac109f24..b6204a32bd64 100644
--- a/sound/soc/qcom/common.h
+++ b/sound/soc/qcom/common.h
@@ -24,6 +24,9 @@ int qcom_snd_apply_dai_tdm_slots_cfg(struct snd_soc_pcm_runtime *rtd,
const struct qcom_snd_tdm_slot_cfg *cpu_cfg,
const struct qcom_snd_tdm_slot_cfg *codec_cfg);
int qcom_snd_apply_dai_tdm_slots(struct snd_soc_pcm_runtime *rtd);
+int qcom_snd_headset_jack_setup(struct snd_soc_pcm_runtime *rtd,
+ struct snd_soc_jack *jack, bool *jack_setup);
+void qcom_snd_headset_jack_cleanup(struct snd_soc_pcm_runtime *rtd);
int qcom_snd_wcd_jack_setup(struct snd_soc_pcm_runtime *rtd,
struct snd_soc_jack *jack, bool *jack_setup);
int qcom_snd_dp_jack_setup(struct snd_soc_pcm_runtime *rtd,
--
2.43.0
^ permalink raw reply [flat|nested] 9+ messages in thread* [PATCH v3 4/6] ASoC: qcom: sc8280xp: Add per-DAI board configuration
2026-09-04 10:02 [PATCH v3 0/6] Add audio support for QCS6490 Rubik Pi 3 Hongyang Zhao
` (2 preceding siblings ...)
2026-09-04 10:02 ` [PATCH v3 3/6] ASoC: qcom: common: Add generic headset jack helpers Hongyang Zhao
@ 2026-09-04 10:02 ` Hongyang Zhao
2026-09-04 10:02 ` [PATCH v3 5/6] ASoC: qcom: sc8280xp: Add RubikPi 3 sound card support Hongyang Zhao
2026-09-04 10:02 ` [PATCH v3 6/6] arm64: dts: qcom: qcs6490-rubikpi3: Add audio support Hongyang Zhao
5 siblings, 0 replies; 9+ messages in thread
From: Hongyang Zhao @ 2026-09-04 10:02 UTC (permalink / raw)
To: Liam Girdwood, Mark Brown, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Daniel Drake, Katsuhiro Suzuki, Matteo Martelli,
Binbin Zhou, Srinivas Kandagatla, Jaroslav Kysela, Takashi Iwai,
Bjorn Andersson, Konrad Dybcio
Cc: Mohammad Rafi Shaik, Roger Shimizu, linux-sound, linux-kernel,
linux-arm-msm, devicetree, Hongyang Zhao
The board data currently applies codec sysclk, MI2S clock and jack setup
policy to every backend DAI on a sound card. This cannot describe a card
whose codecs have different clock requirements on different MI2S
interfaces.
Add an optional per-DAI configuration table indexed by CPU DAI ID. Each
entry can override the MCLK rate, CPU MCLK and BCLK programming, codec
sysclk setup and jack setup path. Keep the codec DAI format card-wide.
Cards without a matching per-DAI entry continue to use the existing
card-wide settings, keeping all current board data unchanged.
Signed-off-by: Hongyang Zhao <hongyang.zhao@thundersoft.com>
---
sound/soc/qcom/sc8280xp.c | 107 ++++++++++++++++++++++++++++++++++++++++++----
1 file changed, 98 insertions(+), 9 deletions(-)
diff --git a/sound/soc/qcom/sc8280xp.c b/sound/soc/qcom/sc8280xp.c
index 4d48e1012cd4..368a54c2cdf8 100644
--- a/sound/soc/qcom/sc8280xp.c
+++ b/sound/soc/qcom/sc8280xp.c
@@ -58,6 +58,25 @@ static const struct snd_soc_dapm_widget max98090_dapm_widgets[] = {
SND_SOC_DAPM_SPK("Speaker", NULL),
};
+enum sc8280xp_jack_setup {
+ SC8280XP_JACK_SETUP_NONE,
+ SC8280XP_JACK_SETUP_CODEC,
+ SC8280XP_JACK_SETUP_WCD,
+};
+
+struct sc8280xp_dai_data {
+ unsigned int id;
+ unsigned int mclk_rate;
+ bool codec_sysclk_set;
+ bool mi2s_mclk_enable;
+ bool mi2s_bclk_enable;
+ enum sc8280xp_jack_setup jack_setup;
+};
+
+#define SC8280XP_DAI_DATA(...) \
+ .dai_data = (const struct sc8280xp_dai_data[]) { __VA_ARGS__ }, \
+ .num_dai_data = ARRAY_SIZE(((const struct sc8280xp_dai_data[]) { __VA_ARGS__ }))
+
struct qcom_snd_soc_common {
const char *driver_name;
const struct snd_soc_dapm_widget *dapm_widgets;
@@ -71,6 +90,8 @@ struct qcom_snd_soc_common {
bool mi2s_mclk_enable;
bool mi2s_bclk_enable;
bool wcd_jack;
+ const struct sc8280xp_dai_data *dai_data;
+ size_t num_dai_data;
int (*snd_prepare)(struct snd_pcm_substream *substream);
};
@@ -83,6 +104,20 @@ struct sc8280xp_snd_data {
bool jack_setup;
};
+static const struct sc8280xp_dai_data *
+sc8280xp_get_dai_data(const struct qcom_snd_soc_common *common,
+ unsigned int id)
+{
+ size_t i;
+
+ for (i = 0; i < common->num_dai_data; i++) {
+ if (common->dai_data[i].id == id)
+ return &common->dai_data[i];
+ }
+
+ return NULL;
+}
+
static inline int sc8280xp_get_mclk_freq(struct snd_pcm_hw_params *params)
{
int rate = params_rate(params);
@@ -112,13 +147,22 @@ static int sc8280xp_tdm_hw_params(struct snd_pcm_substream *substream,
struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream);
struct sc8280xp_snd_data *data = snd_soc_card_get_drvdata(rtd->card);
struct snd_soc_dai *cpu_dai = snd_soc_rtd_to_cpu(rtd, 0);
+ const struct sc8280xp_dai_data *dai_data;
struct snd_soc_dai *codec_dai;
struct qcom_snd_tdm_slot_cfg cpu_cfg;
struct qcom_snd_tdm_slot_cfg codec_cfg;
+ bool codec_sysclk_set = data->priv->codec_sysclk_set;
+ bool mi2s_bclk_enable = data->priv->mi2s_bclk_enable;
int bclk_freq;
int ret;
int i;
+ dai_data = sc8280xp_get_dai_data(data->priv, cpu_dai->id);
+ if (dai_data) {
+ codec_sysclk_set = dai_data->codec_sysclk_set;
+ mi2s_bclk_enable = dai_data->mi2s_bclk_enable;
+ }
+
ret = qcom_snd_get_dai_tdm_slots(rtd, &cpu_cfg, &codec_cfg);
if (ret)
return ret == -ENOENT ? 0 : ret;
@@ -147,7 +191,7 @@ static int sc8280xp_tdm_hw_params(struct snd_pcm_substream *substream,
if (bclk_freq <= 0)
return -EINVAL;
- if (data->priv->mi2s_bclk_enable) {
+ if (mi2s_bclk_enable) {
ret = snd_soc_dai_set_sysclk(cpu_dai, LPAIF_MI2S_BCLK, bclk_freq,
SND_SOC_CLOCK_IN);
if (ret && ret != -ENOTSUPP) {
@@ -157,7 +201,7 @@ static int sc8280xp_tdm_hw_params(struct snd_pcm_substream *substream,
}
}
- if (data->priv->codec_sysclk_set) {
+ if (codec_sysclk_set) {
for_each_rtd_codec_dais(rtd, i, codec_dai) {
ret = snd_soc_dai_set_sysclk(codec_dai, 0, bclk_freq,
SND_SOC_CLOCK_IN);
@@ -176,10 +220,13 @@ static int sc8280xp_snd_init(struct snd_soc_pcm_runtime *rtd)
{
struct sc8280xp_snd_data *data = snd_soc_card_get_drvdata(rtd->card);
struct snd_soc_dai *cpu_dai = snd_soc_rtd_to_cpu(rtd, 0);
+ const struct sc8280xp_dai_data *dai_data;
struct snd_soc_card *card = rtd->card;
struct snd_soc_jack *dp_jack = NULL;
int dp_pcm_id = 0;
+ dai_data = sc8280xp_get_dai_data(data->priv, cpu_dai->id);
+
switch (cpu_dai->id) {
case WSA_CODEC_DMA_RX_0:
case WSA_CODEC_DMA_RX_1:
@@ -209,10 +256,24 @@ static int sc8280xp_snd_init(struct snd_soc_pcm_runtime *rtd)
if (dp_jack)
return qcom_snd_dp_jack_setup(rtd, dp_jack, dp_pcm_id);
- if (data->priv->wcd_jack)
- return qcom_snd_wcd_jack_setup(rtd, &data->jack, &data->jack_setup);
+ if (!dai_data) {
+ if (data->priv->wcd_jack)
+ return qcom_snd_wcd_jack_setup(rtd, &data->jack,
+ &data->jack_setup);
- return 0;
+ return 0;
+ }
+
+ switch (dai_data->jack_setup) {
+ case SC8280XP_JACK_SETUP_CODEC:
+ return qcom_snd_headset_jack_setup(rtd, &data->jack,
+ &data->jack_setup);
+ case SC8280XP_JACK_SETUP_WCD:
+ return qcom_snd_wcd_jack_setup(rtd, &data->jack,
+ &data->jack_setup);
+ default:
+ return 0;
+ }
}
static int sc8280xp_be_hw_params_fixup(struct snd_soc_pcm_runtime *rtd,
@@ -251,10 +312,24 @@ static int sc8280xp_snd_hw_params(struct snd_pcm_substream *substream,
struct snd_soc_dai *codec_dai = snd_soc_rtd_to_codec(rtd, 0);
struct snd_soc_dai *cpu_dai = snd_soc_rtd_to_cpu(rtd, 0);
struct sc8280xp_snd_data *data = snd_soc_card_get_drvdata(rtd->card);
- int mclk_freq = sc8280xp_get_mclk_freq(params);
+ const struct sc8280xp_dai_data *dai_data;
+ bool codec_sysclk_set = data->priv->codec_sysclk_set;
+ bool mi2s_mclk_enable = data->priv->mi2s_mclk_enable;
+ bool mi2s_bclk_enable = data->priv->mi2s_bclk_enable;
+ int mclk_freq;
int bclk_freq = sc8280xp_get_bclk_freq(params);
int ret;
+ dai_data = sc8280xp_get_dai_data(data->priv, cpu_dai->id);
+ mclk_freq = sc8280xp_get_mclk_freq(params);
+ if (dai_data) {
+ codec_sysclk_set = dai_data->codec_sysclk_set;
+ mi2s_mclk_enable = dai_data->mi2s_mclk_enable;
+ mi2s_bclk_enable = dai_data->mi2s_bclk_enable;
+ if (dai_data->mclk_rate)
+ mclk_freq = dai_data->mclk_rate;
+ }
+
switch (cpu_dai->id) {
case PRIMARY_MI2S_RX ... QUATERNARY_MI2S_TX:
case QUINARY_MI2S_RX ... QUINARY_MI2S_TX:
@@ -271,7 +346,7 @@ static int sc8280xp_snd_hw_params(struct snd_pcm_substream *substream,
return ret;
}
- if (data->priv->mi2s_mclk_enable) {
+ if (mi2s_mclk_enable) {
ret = snd_soc_dai_set_sysclk(cpu_dai,
LPAIF_MI2S_MCLK, mclk_freq,
SND_SOC_CLOCK_OUT);
@@ -279,7 +354,7 @@ static int sc8280xp_snd_hw_params(struct snd_pcm_substream *substream,
return ret;
}
- if (data->priv->mi2s_bclk_enable) {
+ if (mi2s_bclk_enable) {
ret = snd_soc_dai_set_sysclk(cpu_dai,
LPAIF_MI2S_BCLK, bclk_freq,
SND_SOC_CLOCK_OUT);
@@ -287,7 +362,7 @@ static int sc8280xp_snd_hw_params(struct snd_pcm_substream *substream,
return ret;
}
- if (data->priv->codec_sysclk_set) {
+ if (codec_sysclk_set) {
ret = snd_soc_dai_set_sysclk(codec_dai,
0, mclk_freq,
SND_SOC_CLOCK_IN);
@@ -368,6 +443,19 @@ static int sc8280xp_snd_hw_free(struct snd_pcm_substream *substream)
return qcom_snd_sdw_hw_free(substream, &data->stream_prepared[cpu_dai->id]);
}
+static void sc8280xp_snd_exit(struct snd_soc_pcm_runtime *rtd)
+{
+ struct sc8280xp_snd_data *data = snd_soc_card_get_drvdata(rtd->card);
+ struct snd_soc_dai *cpu_dai = snd_soc_rtd_to_cpu(rtd, 0);
+ const struct sc8280xp_dai_data *dai_data;
+
+ dai_data = sc8280xp_get_dai_data(data->priv, cpu_dai->id);
+ if (dai_data && dai_data->jack_setup == SC8280XP_JACK_SETUP_CODEC) {
+ qcom_snd_headset_jack_cleanup(rtd);
+ data->jack_setup = false;
+ }
+}
+
static const struct snd_soc_ops sc8280xp_be_ops = {
.startup = qcom_snd_sdw_startup,
.shutdown = qcom_snd_sdw_shutdown,
@@ -384,6 +472,7 @@ static void sc8280xp_add_be_ops(struct snd_soc_card *card)
for_each_card_prelinks(card, i, link) {
if (link->no_pcm == 1) {
link->init = sc8280xp_snd_init;
+ link->exit = sc8280xp_snd_exit;
link->be_hw_params_fixup = sc8280xp_be_hw_params_fixup;
link->ops = &sc8280xp_be_ops;
}
--
2.43.0
^ permalink raw reply [flat|nested] 9+ messages in thread* [PATCH v3 5/6] ASoC: qcom: sc8280xp: Add RubikPi 3 sound card support
2026-09-04 10:02 [PATCH v3 0/6] Add audio support for QCS6490 Rubik Pi 3 Hongyang Zhao
` (3 preceding siblings ...)
2026-09-04 10:02 ` [PATCH v3 4/6] ASoC: qcom: sc8280xp: Add per-DAI board configuration Hongyang Zhao
@ 2026-09-04 10:02 ` Hongyang Zhao
2026-09-04 10:02 ` [PATCH v3 6/6] arm64: dts: qcom: qcs6490-rubikpi3: Add audio support Hongyang Zhao
5 siblings, 0 replies; 9+ messages in thread
From: Hongyang Zhao @ 2026-09-04 10:02 UTC (permalink / raw)
To: Liam Girdwood, Mark Brown, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Daniel Drake, Katsuhiro Suzuki, Matteo Martelli,
Binbin Zhou, Srinivas Kandagatla, Jaroslav Kysela, Takashi Iwai,
Bjorn Andersson, Konrad Dybcio
Cc: Mohammad Rafi Shaik, Roger Shimizu, linux-sound, linux-kernel,
linux-arm-msm, devicetree, Hongyang Zhao
RubikPi 3 connects an ES8316 codec to primary MI2S for headset playback
and capture, and an LT9611 bridge to quaternary MI2S for HDMI audio.
Add per-DAI data for the primary playback and capture links. Configure
the codecs for I2S with normal clock polarity and as bit and frame clock
consumers. Program the primary MI2S BCLK, configure the ES8316 for its
fixed 19.2 MHz MCLK and enable component jack detection on the playback
link.
The HDMI link inherits the card-wide I2S format but does not request
codec sysclk programming because the LT9611 codec DAI does not implement
set_sysclk().
Select this configuration through the RubikPi 3 sound-card compatible.
Signed-off-by: Hongyang Zhao <hongyang.zhao@thundersoft.com>
---
sound/soc/qcom/sc8280xp.c | 23 +++++++++++++++++++++++
1 file changed, 23 insertions(+)
diff --git a/sound/soc/qcom/sc8280xp.c b/sound/soc/qcom/sc8280xp.c
index 368a54c2cdf8..73009f9bb8e4 100644
--- a/sound/soc/qcom/sc8280xp.c
+++ b/sound/soc/qcom/sc8280xp.c
@@ -577,6 +577,28 @@ static const struct qcom_snd_soc_common qcs6490_priv_data = {
.wcd_jack = true,
};
+static const struct qcom_snd_soc_common rubikpi3_priv_data = {
+ .driver_name = "qcs6490",
+ .dapm_widgets = sc8280xp_dapm_widgets,
+ .num_dapm_widgets = ARRAY_SIZE(sc8280xp_dapm_widgets),
+ .codec_dai_fmt = SND_SOC_DAIFMT_I2S |
+ SND_SOC_DAIFMT_NB_NF |
+ SND_SOC_DAIFMT_BC_FC,
+ SC8280XP_DAI_DATA({
+ .id = PRIMARY_MI2S_RX,
+ .mclk_rate = 19200000,
+ .codec_sysclk_set = true,
+ .mi2s_bclk_enable = true,
+ .jack_setup = SC8280XP_JACK_SETUP_CODEC,
+ }, {
+ .id = PRIMARY_MI2S_TX,
+ .mclk_rate = 19200000,
+ .codec_sysclk_set = true,
+ .mi2s_bclk_enable = true,
+ }
+ ),
+};
+
static const struct qcom_snd_soc_common qcs8275_priv_data = {
.driver_name = "qcs8300",
.dapm_widgets = max98090_dapm_widgets,
@@ -656,6 +678,7 @@ static const struct of_device_id snd_sc8280xp_dt_match[] = {
{ .compatible = "qcom,qcm6490-idp-sndcard", .data = &qcm6490_priv_data },
{ .compatible = "qcom,qcs615-sndcard", .data = &qcs615_priv_data },
{ .compatible = "qcom,qcs6490-rb3gen2-sndcard", .data = &qcs6490_priv_data },
+ { .compatible = "thundercomm,qcs6490-rubikpi3-sndcard", .data = &rubikpi3_priv_data },
{ .compatible = "qcom,qcs8275-sndcard", .data = &qcs8275_priv_data },
{ .compatible = "qcom,qcs9075-sndcard", .data = &qcs9100_priv_data },
{ .compatible = "qcom,qcs9100-sndcard", .data = &qcs9100_priv_data },
--
2.43.0
^ permalink raw reply [flat|nested] 9+ messages in thread* [PATCH v3 6/6] arm64: dts: qcom: qcs6490-rubikpi3: Add audio support
2026-09-04 10:02 [PATCH v3 0/6] Add audio support for QCS6490 Rubik Pi 3 Hongyang Zhao
` (4 preceding siblings ...)
2026-09-04 10:02 ` [PATCH v3 5/6] ASoC: qcom: sc8280xp: Add RubikPi 3 sound card support Hongyang Zhao
@ 2026-09-04 10:02 ` Hongyang Zhao
2026-09-07 12:27 ` Konrad Dybcio
5 siblings, 1 reply; 9+ messages in thread
From: Hongyang Zhao @ 2026-09-04 10:02 UTC (permalink / raw)
To: Liam Girdwood, Mark Brown, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Daniel Drake, Katsuhiro Suzuki, Matteo Martelli,
Binbin Zhou, Srinivas Kandagatla, Jaroslav Kysela, Takashi Iwai,
Bjorn Andersson, Konrad Dybcio
Cc: Mohammad Rafi Shaik, Roger Shimizu, linux-sound, linux-kernel,
linux-arm-msm, devicetree, Hongyang Zhao
RubikPi 3 uses the AudioReach firmware path for its external audio
interfaces. Primary MI2S connects to an ES8316 codec for headset playback
and capture, while quaternary MI2S feeds the LT9611 HDMI bridge.
Describe the ES8316 supplies, MCLK, jack detection and audio routing, and
add the primary and quaternary MI2S links. The 1.8 V and 3.3 V codec
supplies are both controlled by GPIO117.
Signed-off-by: Hongyang Zhao <hongyang.zhao@thundersoft.com>
---
.../boot/dts/qcom/qcs6490-thundercomm-rubikpi3.dts | 169 +++++++++++++++++++++
1 file changed, 169 insertions(+)
diff --git a/arch/arm64/boot/dts/qcom/qcs6490-thundercomm-rubikpi3.dts b/arch/arm64/boot/dts/qcom/qcs6490-thundercomm-rubikpi3.dts
index 0f21777c480b..10277bee86b3 100644
--- a/arch/arm64/boot/dts/qcom/qcs6490-thundercomm-rubikpi3.dts
+++ b/arch/arm64/boot/dts/qcom/qcs6490-thundercomm-rubikpi3.dts
@@ -19,6 +19,7 @@
#include "pm7325.dtsi"
#include "pm8350c.dtsi" /* PM7350C */
#include "pmk8350.dtsi" /* PMK7325 */
+#include "qcs6490-audioreach.dtsi"
/delete-node/ &adsp_mem;
/delete-node/ &cdsp_mem;
@@ -128,6 +129,33 @@ fan0: pwm-fan {
pinctrl-names = "default";
};
+ vreg_es8316_1v8: regulator-es8316-1v8 {
+ compatible = "regulator-fixed";
+
+ regulator-name = "vreg_es8316_1v8";
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+
+ gpio = <&tlmm 117 GPIO_ACTIVE_HIGH>;
+ enable-active-high;
+
+ pinctrl-0 = <&es8316_power_on>;
+ pinctrl-names = "default";
+
+ vin-supply = <&vreg_l18b_1p8>;
+ };
+
+ vreg_es8316_3v3: regulator-es8316-3v3 {
+ compatible = "regulator-fixed";
+
+ regulator-name = "vreg_es8316_3v3";
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
+
+ gpio = <&tlmm 117 GPIO_ACTIVE_HIGH>;
+ enable-active-high;
+ };
+
vreg_eth_1v8: regulator-eth-1v8 {
compatible = "regulator-fixed";
@@ -743,6 +771,30 @@ &gpu_zap_shader {
firmware-name = "qcom/qcs6490/a660_zap.mbn";
};
+&i2c0 {
+ status = "okay";
+
+ es8316: audio-codec@11 {
+ compatible = "everest,es8316";
+ reg = <0x11>;
+ #sound-dai-cells = <0>;
+
+ clocks = <&q6prmcc LPASS_CLK_ID_MCLK_1 LPASS_CLK_ATTRIBUTE_COUPLE_NO>;
+ clock-names = "mclk";
+
+ interrupts-extended = <&tlmm 63 IRQ_TYPE_LEVEL_HIGH>;
+ avdd-supply = <&vreg_es8316_3v3>;
+ cpvdd-supply = <&vreg_es8316_1v8>;
+ dvdd-supply = <&vreg_es8316_1v8>;
+ pvdd-supply = <&vreg_es8316_1v8>;
+
+ pinctrl-0 = <&es8316_jack_detect>;
+ pinctrl-names = "default";
+
+ everest,jack-detect-inverted;
+ };
+};
+
/* Pin 3, 5 in 40-pin connector */
&i2c1 {
status = "okay";
@@ -756,6 +808,7 @@ &i2c9 {
lt9611_codec: hdmi-bridge@39 {
compatible = "lontium,lt9611";
reg = <0x39>;
+ #sound-dai-cells = <1>;
interrupts-extended = <&tlmm 20 IRQ_TYPE_EDGE_FALLING>;
reset-gpios = <&tlmm 21 GPIO_ACTIVE_HIGH>;
@@ -994,6 +1047,23 @@ &pon_resin {
status = "okay";
};
+&q6apmbedai {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ dai@10 {
+ reg = <PRIMARY_MI2S_RX>;
+ clocks = <&q6prmcc LPASS_CLK_ID_PRI_MI2S_IBIT LPASS_CLK_ATTRIBUTE_COUPLE_NO>;
+ clock-names = "bclk";
+ };
+
+ dai@11 {
+ reg = <PRIMARY_MI2S_TX>;
+ clocks = <&q6prmcc LPASS_CLK_ID_PRI_MI2S_IBIT LPASS_CLK_ATTRIBUTE_COUPLE_NO>;
+ clock-names = "bclk";
+ };
+};
+
&qupv3_id_0 {
firmware-name = "qcom/qcm6490/qupv3fw.elf";
@@ -1030,6 +1100,69 @@ &sdhc_2 {
status = "okay";
};
+&sound {
+ compatible = "thundercomm,qcs6490-rubikpi3-sndcard";
+ model = "QCS6490-Thundercomm-RubikPi3";
+
+ pinctrl-0 = <&mi2s0_data0>, <&mi2s0_data1>, <&mi2s0_mclk>,
+ <&mi2s0_sclk>, <&mi2s0_ws>,
+ <&lpass_qua_mi2s_sclk>, <&lpass_qua_mi2s_ws>,
+ <&lpass_qua_mi2s_data>;
+ pinctrl-names = "default";
+
+ audio-routing = "Headphone Jack", "HPOL",
+ "Headphone Jack", "HPOR",
+ "MIC2", "Mic Jack";
+
+ mi2s-capture-dai-link {
+ link-name = "Primary MI2S Capture";
+
+ codec {
+ sound-dai = <&es8316>;
+ };
+
+ cpu {
+ sound-dai = <&q6apmbedai PRIMARY_MI2S_TX>;
+ };
+
+ platform {
+ sound-dai = <&q6apm>;
+ };
+ };
+
+ mi2s-playback-dai-link {
+ link-name = "Primary MI2S Playback";
+
+ codec {
+ sound-dai = <&es8316>;
+ };
+
+ cpu {
+ sound-dai = <&q6apmbedai PRIMARY_MI2S_RX>;
+ };
+
+ platform {
+ sound-dai = <&q6apm>;
+ };
+ };
+
+ quaternary-mi2s-playback-dai-link {
+ link-name = "HDMI Playback";
+
+ codec {
+ sound-dai = <<9611_codec 0>;
+ };
+
+ cpu {
+ sound-dai = <&q6apmbedai QUATERNARY_MI2S_RX>;
+ };
+
+ platform {
+ sound-dai = <&q6apm>;
+ };
+ };
+};
+
/* Pin 19, 21, 23, 24 in 40-pin connector */
&spi12 {
status = "okay";
@@ -1244,6 +1377,29 @@ &sdc2_data {
drive-strength = <10>;
};
+&lpass_tlmm {
+ lpass_qua_mi2s_sclk: qua-mi2s-sclk-state {
+ pins = "gpio0";
+ function = "qua_mi2s_sclk";
+ drive-strength = <8>;
+ bias-disable;
+ };
+
+ lpass_qua_mi2s_ws: qua-mi2s-ws-state {
+ pins = "gpio1";
+ function = "qua_mi2s_ws";
+ drive-strength = <8>;
+ bias-disable;
+ };
+
+ lpass_qua_mi2s_data: qua-mi2s-data-state {
+ pins = "gpio2", "gpio3", "gpio4";
+ function = "qua_mi2s_data";
+ drive-strength = <8>;
+ bias-disable;
+ };
+};
+
&tlmm {
pcie1_reset_n: pcie1-reset-n-state {
pins = "gpio2";
@@ -1389,6 +1545,12 @@ m2_vcc_pin: m2-vcc-state {
input-disable;
};
+ es8316_jack_detect: es8316-jack-detect-state {
+ pins = "gpio63";
+ function = "gpio";
+ bias-disable;
+ };
+
lt9611_vcc_pin: lt9611-vcc-pin-state {
pins = "gpio83";
function = "gpio";
@@ -1418,6 +1580,13 @@ pcie0_wake_n: pcie0-wake-n-state {
bias-pull-up;
};
+ es8316_power_on: es8316-power-on-state {
+ pins = "gpio117";
+ function = "gpio";
+ drive-strength = <2>;
+ bias-pull-down;
+ };
+
wifi_power_on: wifi-power-on-state {
pins = "gpio125";
function = "gpio";
--
2.43.0
^ permalink raw reply [flat|nested] 9+ messages in thread* Re: [PATCH v3 6/6] arm64: dts: qcom: qcs6490-rubikpi3: Add audio support
2026-09-04 10:02 ` [PATCH v3 6/6] arm64: dts: qcom: qcs6490-rubikpi3: Add audio support Hongyang Zhao
@ 2026-09-07 12:27 ` Konrad Dybcio
0 siblings, 0 replies; 9+ messages in thread
From: Konrad Dybcio @ 2026-09-07 12:27 UTC (permalink / raw)
To: Hongyang Zhao, Liam Girdwood, Mark Brown, Rob Herring,
Krzysztof Kozlowski, Conor Dooley, Daniel Drake,
Katsuhiro Suzuki, Matteo Martelli, Binbin Zhou,
Srinivas Kandagatla, Jaroslav Kysela, Takashi Iwai,
Bjorn Andersson, Konrad Dybcio
Cc: Mohammad Rafi Shaik, Roger Shimizu, linux-sound, linux-kernel,
linux-arm-msm, devicetree
On 9/4/26 12:02 PM, Hongyang Zhao wrote:
> RubikPi 3 uses the AudioReach firmware path for its external audio
> interfaces. Primary MI2S connects to an ES8316 codec for headset playback
> and capture, while quaternary MI2S feeds the LT9611 HDMI bridge.
[...]
> +&i2c0 {
> + status = "okay";
This should have an explicitly set `clock-frequency`
with that fixed:
Reviewed-by: Konrad Dybcio <konrad.dybcio@oss.qualcomm.com>
Konrad
^ permalink raw reply [flat|nested] 9+ messages in thread