Re: [PATCH v1 2/2] ASoC: qcom: sc8280xp: add Shikra EVK machine variants
From: Ajay Kumar Nandam
Date: Thu Jul 09 2026 - 04:40:30 EST
On 6/12/2026 4:46 AM, Dmitry Baryshkov wrote:
On Thu, Jun 11, 2026 at 04:59:46PM +0530, Ajay Kumar Nandam wrote:
Add machine-driver support for Qualcomm Shikra EVK variants by matching
dedicated compatible strings and applying board-specific audio behavior.
Shikra platforms are available as CQM, CQS, and IQS variants with
different audio components and processing architectures:
- CQM/CQS use an I2S-based path with WSA885x amplifiers and
PM4125 + Rouleur codec components.
- CQM runs in DSP-bypass mode, where the complete audio pipeline runs
on CPU only and no DSP is involved.
- CQS uses modem-DSP based audio processing.
- IQS uses a third-party MAX98091 codec with modem-DSP support.
Introduce variant-specific handling so codec controls, DAPM widgets, and
clock programming match the board design and avoid invalid clock setup on
variants where it is not applicable.
To me it looks like several independent changes being squashed into one
commit.
ACK, we will make seperate logical patches in the next version.
Co-developed-by: Mohammad Rafi Shaik <mohammad.rafi.shaik@xxxxxxxxxxxxxxxx>
Signed-off-by: Mohammad Rafi Shaik <mohammad.rafi.shaik@xxxxxxxxxxxxxxxx>
Signed-off-by: Ajay Kumar Nandam <ajay.nandam@xxxxxxxxxxxxxxxx>
---
sound/soc/qcom/common.c | 2 ++
sound/soc/qcom/sc8280xp.c | 58 +++++++++++++++++++++++++++++++++++++--
sound/soc/qcom/sdw.c | 3 ++
3 files changed, 61 insertions(+), 2 deletions(-)
diff --git a/sound/soc/qcom/common.c b/sound/soc/qcom/common.c
index f42c98ded..32d6c09b2 100644
--- a/sound/soc/qcom/common.c
+++ b/sound/soc/qcom/common.c
@@ -3,6 +3,7 @@
// Copyright (c) 2018, The Linux Foundation. All rights reserved.
#include <dt-bindings/sound/qcom,q6afe.h>
+#include <dt-bindings/sound/qcom,qaif.h>
#include <linux/module.h>
#include <sound/jack.h>
#include <linux/input-event-codes.h>
@@ -430,6 +431,7 @@ int qcom_snd_wcd_jack_setup(struct snd_soc_pcm_runtime *rtd,
}
switch (cpu_dai->id) {
+ case QAIF_CDC_DMA_RX0:
case TX_CODEC_DMA_TX_0:
case TX_CODEC_DMA_TX_1:
case TX_CODEC_DMA_TX_2:
diff --git a/sound/soc/qcom/sc8280xp.c b/sound/soc/qcom/sc8280xp.c
index e5d23e244..4c985f81c 100644
--- a/sound/soc/qcom/sc8280xp.c
+++ b/sound/soc/qcom/sc8280xp.c
@@ -37,6 +37,25 @@ static struct snd_soc_dapm_widget sc8280xp_dapm_widgets[] = {
SND_SOC_DAPM_SPK("DP7 Jack", NULL),
};
+static struct snd_soc_dapm_widget shikra_cqm_dapm_widgets[] = {
+ SND_SOC_DAPM_HP("Headphone Jack", NULL),
+ SND_SOC_DAPM_MIC("Mic Jack", NULL),
+};
No speakers?
We are using the WSA885x external I²S speaker amplifier, separate machine-level SND_SOC_DAPM_SPK() widget is not required here.
+
+static const struct snd_soc_dapm_widget shikra_iqs_dapm_widgets[] = {
+ SND_SOC_DAPM_HP("Headphone", NULL),
+ SND_SOC_DAPM_MIC("Headset Mic", NULL),
+ SND_SOC_DAPM_MIC("Int Mic", NULL),
+ SND_SOC_DAPM_SPK("Speaker", NULL),
+};
+
+static const struct snd_kcontrol_new shikra_iqs_controls[] = {
+ SOC_DAPM_PIN_SWITCH("Headset Mic"),
+ SOC_DAPM_PIN_SWITCH("Headphone"),
+ SOC_DAPM_PIN_SWITCH("Int Mic"),
+ SOC_DAPM_PIN_SWITCH("Speaker"),
+};
No controls for CQM/CQS variants? Why? Or rather why do we need
kcontrols for IQS?
CQM/CQS use Qualcomm WSA885x and Rouleur codecs, whose audio paths are already described by the codec DAPM topology, so additional machine-driver pin-switch controls are not required.
IQS uses the external MAX98090 codec, and therefore the machine driver exposes the board-level endpoints through DAPM widgets and corresponding kcontrols.
+
struct snd_soc_common {
const char *driver_name;
const struct snd_soc_dapm_widget *dapm_widgets;
@@ -49,6 +68,7 @@ struct snd_soc_common {
bool codec_sysclk_set;
bool mi2s_mclk_enable;
bool mi2s_bclk_enable;
+ bool dsp_bypass;
};
struct sc8280xp_snd_data {
@@ -219,6 +239,10 @@ static int sc8280xp_snd_hw_params(struct snd_pcm_substream *substream,
int mclk_freq = sc8280xp_get_mclk_freq(params);
int bclk_freq = sc8280xp_get_bclk_freq(params);
+ /* Skip DSP configuration when operating in CPU-only (bypass) mode */
+ if (data->snd_soc_common_priv->dsp_bypass)
+ return 0;
+
How are e.g. MI2S signals configured / routed?
In bypass mode, the MI2S links are configured and routed by the QAIF platform driver rather than through the DSP path.
The check here only skips the DSP-specific configuration performed by
sc8280xp_snd_hw_params(). The MI2S interface setup required for CPU-only operation remains handled by the corresponding QAIF/platform driver, so skipping this machine-driver DSP configuration does not affect MI2S signal routing.
Regards,
Ajay Kumar Nandam
switch (cpu_dai->id) {
case PRIMARY_MI2S_RX ... QUATERNARY_MI2S_TX:
case QUINARY_MI2S_RX ... QUINARY_MI2S_TX:
@@ -239,7 +263,7 @@ static int sc8280xp_snd_hw_params(struct snd_pcm_substream *substream,
SND_SOC_CLOCK_IN);
if (data->snd_soc_common_priv->codec_sysclk_set)
- snd_soc_dai_set_sysclk(cpu_dai,
+ snd_soc_dai_set_sysclk(codec_dai,
0, mclk_freq,
SND_SOC_CLOCK_IN);
break;
@@ -284,7 +308,7 @@ static void sc8280xp_add_be_ops(struct snd_soc_card *card)
int i;
for_each_card_prelinks(card, i, link) {
- if (link->no_pcm == 1) {
+ if (link->no_pcm == 1 || link->num_codecs > 0) {
link->init = sc8280xp_snd_init;
link->be_hw_params_fixup = sc8280xp_be_hw_params_fixup;
link->ops = &sc8280xp_be_ops;
@@ -375,6 +399,33 @@ static struct snd_soc_common sc8280xp_priv_data = {
.num_dapm_widgets = ARRAY_SIZE(sc8280xp_dapm_widgets),
};
+static const struct snd_soc_common shikra_cqm_priv_data = {
+ .driver_name = "shikra",
+ .dapm_widgets = shikra_cqm_dapm_widgets,
+ .num_dapm_widgets = ARRAY_SIZE(shikra_cqm_dapm_widgets),
+ .dsp_bypass = true,
+};
+
+static const struct snd_soc_common shikra_cqs_priv_data = {
+ .driver_name = "shikra",
+ .dapm_widgets = shikra_cqm_dapm_widgets,
+ .num_dapm_widgets = ARRAY_SIZE(shikra_cqm_dapm_widgets),
+ .mi2s_bclk_enable = true,
+ .codec_sysclk_set = true,
+};
+
+static const struct snd_soc_common shikra_iqs_priv_data = {
+ .driver_name = "shikra",
+ .dapm_widgets = shikra_iqs_dapm_widgets,
+ .num_dapm_widgets = ARRAY_SIZE(shikra_iqs_dapm_widgets),
+ .controls = shikra_iqs_controls,
+ .num_controls = ARRAY_SIZE(shikra_iqs_controls),
+ .codec_dai_fmt = SND_SOC_DAIFMT_CBP_CFP |
+ SND_SOC_DAIFMT_NB_NF |
+ SND_SOC_DAIFMT_I2S,
+ .codec_sysclk_set = true,
+ .mi2s_bclk_enable = true,
+};
+
static struct snd_soc_common sm8450_priv_data = {
.driver_name = "sm8450",
.dapm_widgets = sc8280xp_dapm_widgets,
@@ -408,6 +459,9 @@ static const struct of_device_id snd_sc8280xp_dt_match[] = {
{.compatible = "qcom,qcs9075-sndcard", .data = &qcs9100_priv_data},
{.compatible = "qcom,qcs9100-sndcard", .data = &qcs9100_priv_data},
{.compatible = "qcom,sc8280xp-sndcard", .data = &sc8280xp_priv_data},
+ {.compatible = "qcom,shikra-cqm-sndcard", .data = &shikra_cqm_priv_data},
+ {.compatible = "qcom,shikra-cqs-sndcard", .data = &shikra_cqs_priv_data},
+ {.compatible = "qcom,shikra-iqs-sndcard", .data = &shikra_iqs_priv_data},
{.compatible = "qcom,sm8450-sndcard", .data = &sm8450_priv_data},
{.compatible = "qcom,sm8550-sndcard", .data = &sm8550_priv_data},
{.compatible = "qcom,sm8650-sndcard", .data = &sm8650_priv_data},
diff --git a/sound/soc/qcom/sdw.c b/sound/soc/qcom/sdw.c
index 6576b47a4..0be743cec 100644
--- a/sound/soc/qcom/sdw.c
+++ b/sound/soc/qcom/sdw.c
@@ -4,6 +4,7 @@
#include <dt-bindings/sound/qcom,lpass.h>
#include <dt-bindings/sound/qcom,q6afe.h>
+#include <dt-bindings/sound/qcom,qaif.h>
#include <linux/module.h>
#include <sound/soc.h>
#include "sdw.h"
@@ -41,6 +42,8 @@ static bool qcom_snd_is_sdw_dai(int id)
switch (id) {
case LPASS_CDC_DMA_TX3:
case LPASS_CDC_DMA_RX0:
+ case QAIF_CDC_DMA_VA_TX0:
+ case QAIF_CDC_DMA_RX0:
return true;
default:
break;
--
2.34.1