[<prev] [next>] [thread-next>] [day] [month] [year] [list]
Message-Id: <20250902062300.212021-1-mohammad.rafi.shaik@oss.qualcomm.com>
Date: Tue, 2 Sep 2025 11:53:00 +0530
From: Mohammad Rafi Shaik <mohammad.rafi.shaik@....qualcomm.com>
To: Srinivas Kandagatla <srini@...nel.org>,
Liam Girdwood <lgirdwood@...il.com>, Mark Brown <broonie@...nel.org>,
Jaroslav Kysela <perex@...ex.cz>, Takashi Iwai <tiwai@...e.com>
Cc: linux-sound@...r.kernel.org, linux-arm-msm@...r.kernel.org,
linux-kernel@...r.kernel.org, kernel@....qualcomm.com,
prasad.kumpatla@....qualcomm.com
Subject: [PATCH v2] ASoC: codecs: lpass-macro: Add support for channel map mixer control
Introduce the channel map mixer control support for LPASS macro
codec Digital Audio Interfaces (DAIs). The channel map mixer controls
are required by APPS to configure usecase-specific audio routing and
channel mapping.
Signed-off-by: Mohammad Rafi Shaik <mohammad.rafi.shaik@....qualcomm.com>
---
Changes in v2:
- Updated patch with improved commit description..
- Link to v1: https://lore.kernel.org/linux-sound/20240930053111.3986838-1-quic_mohs@quicinc.com/
---
sound/soc/codecs/lpass-macro-common.c | 55 +++++++++++++++++++++++++++
sound/soc/codecs/lpass-macro-common.h | 2 +
sound/soc/codecs/lpass-rx-macro.c | 12 ++++++
sound/soc/codecs/lpass-tx-macro.c | 9 +++++
sound/soc/codecs/lpass-va-macro.c | 9 +++++
sound/soc/codecs/lpass-wsa-macro.c | 12 ++++++
6 files changed, 99 insertions(+)
diff --git a/sound/soc/codecs/lpass-macro-common.c b/sound/soc/codecs/lpass-macro-common.c
index 6e3b8d0897dd..777af4885245 100644
--- a/sound/soc/codecs/lpass-macro-common.c
+++ b/sound/soc/codecs/lpass-macro-common.c
@@ -8,12 +8,67 @@
#include <linux/platform_device.h>
#include <linux/pm_domain.h>
#include <linux/pm_runtime.h>
+#include <sound/control.h>
+#include <sound/pcm.h>
+#include <sound/soc.h>
#include "lpass-macro-common.h"
static DEFINE_MUTEX(lpass_codec_mutex);
static enum lpass_codec_version lpass_codec_version;
+static int lpass_macro_chmap_ctl_get(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct snd_pcm_chmap *info = snd_kcontrol_chip(kcontrol);
+ struct snd_soc_dai *dai = info->private_data;
+ u32 *chmap_data = NULL;
+ u32 rx_ch_cnt = 0;
+ u32 tx_ch_cnt = 0;
+ u32 rx_ch, tx_ch;
+
+ chmap_data = kzalloc(sizeof(u32) * 2, GFP_KERNEL);
+ if (!chmap_data)
+ return -ENOMEM;
+
+ snd_soc_dai_get_channel_map(dai, &tx_ch_cnt, &tx_ch, &rx_ch_cnt, &rx_ch);
+ if (rx_ch_cnt) {
+ chmap_data[0] = rx_ch_cnt;
+ chmap_data[1] = rx_ch;
+ } else if (tx_ch_cnt) {
+ chmap_data[0] = tx_ch_cnt;
+ chmap_data[1] = tx_ch;
+ }
+ memcpy(ucontrol->value.bytes.data, chmap_data, sizeof(u32) * 2);
+
+ kfree(chmap_data);
+ return 0;
+}
+
+int lpass_macro_add_chmap_ctls(struct snd_soc_pcm_runtime *rtd,
+ struct snd_soc_dai *dai, int dir)
+{
+ struct snd_pcm_chmap *info;
+ int ret;
+
+ info = kzalloc(sizeof(*info), GFP_KERNEL);
+ if (!info)
+ return -ENOMEM;
+
+ ret = snd_pcm_add_chmap_ctls(rtd->pcm, dir, NULL,
+ 2 * sizeof(u32), 0, &info);
+ if (ret < 0) {
+ kfree(info);
+ return ret;
+ }
+
+ /* override handlers */
+ info->private_data = dai;
+ info->kctl->get = lpass_macro_chmap_ctl_get;
+ return 0;
+}
+EXPORT_SYMBOL_GPL(lpass_macro_add_chmap_ctls);
+
struct lpass_macro *lpass_macro_pds_init(struct device *dev)
{
struct lpass_macro *l_pds;
diff --git a/sound/soc/codecs/lpass-macro-common.h b/sound/soc/codecs/lpass-macro-common.h
index fb4b96cb2b23..23ed6836addf 100644
--- a/sound/soc/codecs/lpass-macro-common.h
+++ b/sound/soc/codecs/lpass-macro-common.h
@@ -40,6 +40,8 @@ struct lpass_macro *lpass_macro_pds_init(struct device *dev);
void lpass_macro_pds_exit(struct lpass_macro *pds);
void lpass_macro_set_codec_version(enum lpass_codec_version version);
enum lpass_codec_version lpass_macro_get_codec_version(void);
+int lpass_macro_add_chmap_ctls(struct snd_soc_pcm_runtime *rtd,
+ struct snd_soc_dai *dai, int dir);
static inline void lpass_macro_pds_exit_action(void *pds)
{
diff --git a/sound/soc/codecs/lpass-rx-macro.c b/sound/soc/codecs/lpass-rx-macro.c
index 238dbdb46c18..db08be2600ea 100644
--- a/sound/soc/codecs/lpass-rx-macro.c
+++ b/sound/soc/codecs/lpass-rx-macro.c
@@ -1953,10 +1953,22 @@ static int rx_macro_digital_mute(struct snd_soc_dai *dai, int mute, int stream)
return 0;
}
+static int rx_macro_pcm_new(struct snd_soc_pcm_runtime *rtd,
+ struct snd_soc_dai *dai)
+{
+ int dir = SNDRV_PCM_STREAM_PLAYBACK;
+
+ if (dai->id == RX_MACRO_AIF_ECHO)
+ dir = SNDRV_PCM_STREAM_CAPTURE;
+
+ return lpass_macro_add_chmap_ctls(rtd, dai, dir);
+}
+
static const struct snd_soc_dai_ops rx_macro_dai_ops = {
.hw_params = rx_macro_hw_params,
.get_channel_map = rx_macro_get_channel_map,
.mute_stream = rx_macro_digital_mute,
+ .pcm_new = rx_macro_pcm_new,
};
static struct snd_soc_dai_driver rx_macro_dai[] = {
diff --git a/sound/soc/codecs/lpass-tx-macro.c b/sound/soc/codecs/lpass-tx-macro.c
index 1da34cb3505f..934b814b7a01 100644
--- a/sound/soc/codecs/lpass-tx-macro.c
+++ b/sound/soc/codecs/lpass-tx-macro.c
@@ -1210,10 +1210,19 @@ static int tx_macro_digital_mute(struct snd_soc_dai *dai, int mute, int stream)
return 0;
}
+static int tx_macro_pcm_new(struct snd_soc_pcm_runtime *rtd,
+ struct snd_soc_dai *dai)
+{
+ int dir = SNDRV_PCM_STREAM_CAPTURE;
+
+ return lpass_macro_add_chmap_ctls(rtd, dai, dir);
+}
+
static const struct snd_soc_dai_ops tx_macro_dai_ops = {
.hw_params = tx_macro_hw_params,
.get_channel_map = tx_macro_get_channel_map,
.mute_stream = tx_macro_digital_mute,
+ .pcm_new = tx_macro_pcm_new,
};
static struct snd_soc_dai_driver tx_macro_dai[] = {
diff --git a/sound/soc/codecs/lpass-va-macro.c b/sound/soc/codecs/lpass-va-macro.c
index a49551f3fb29..69224c7805bf 100644
--- a/sound/soc/codecs/lpass-va-macro.c
+++ b/sound/soc/codecs/lpass-va-macro.c
@@ -938,10 +938,19 @@ static int va_macro_digital_mute(struct snd_soc_dai *dai, int mute, int stream)
return 0;
}
+static int va_macro_pcm_new(struct snd_soc_pcm_runtime *rtd,
+ struct snd_soc_dai *dai)
+{
+ int dir = SNDRV_PCM_STREAM_CAPTURE;
+
+ return lpass_macro_add_chmap_ctls(rtd, dai, dir);
+}
+
static const struct snd_soc_dai_ops va_macro_dai_ops = {
.hw_params = va_macro_hw_params,
.get_channel_map = va_macro_get_channel_map,
.mute_stream = va_macro_digital_mute,
+ .pcm_new = va_macro_pcm_new,
};
static struct snd_soc_dai_driver va_macro_dais[] = {
diff --git a/sound/soc/codecs/lpass-wsa-macro.c b/sound/soc/codecs/lpass-wsa-macro.c
index da6adb3de21d..62ed1173fd1c 100644
--- a/sound/soc/codecs/lpass-wsa-macro.c
+++ b/sound/soc/codecs/lpass-wsa-macro.c
@@ -1354,9 +1354,21 @@ static int wsa_macro_get_channel_map(const struct snd_soc_dai *dai,
return 0;
}
+static int wsa_macro_pcm_new(struct snd_soc_pcm_runtime *rtd,
+ struct snd_soc_dai *dai)
+{
+ int dir = SNDRV_PCM_STREAM_PLAYBACK;
+
+ if (dai->id == WSA_MACRO_AIF_VI || dai->id == WSA_MACRO_AIF_ECHO)
+ dir = SNDRV_PCM_STREAM_CAPTURE;
+
+ return lpass_macro_add_chmap_ctls(rtd, dai, dir);
+}
+
static const struct snd_soc_dai_ops wsa_macro_dai_ops = {
.hw_params = wsa_macro_hw_params,
.get_channel_map = wsa_macro_get_channel_map,
+ .pcm_new = wsa_macro_pcm_new,
};
static struct snd_soc_dai_driver wsa_macro_dai[] = {
--
2.34.1
Powered by blists - more mailing lists