summaryrefslogtreecommitdiff
path: root/sound/soc/sdw_utils
diff options
context:
space:
mode:
Diffstat (limited to 'sound/soc/sdw_utils')
-rw-r--r--sound/soc/sdw_utils/soc_sdw_cs_amp.c46
-rw-r--r--sound/soc/sdw_utils/soc_sdw_utils.c13
2 files changed, 56 insertions, 3 deletions
diff --git a/sound/soc/sdw_utils/soc_sdw_cs_amp.c b/sound/soc/sdw_utils/soc_sdw_cs_amp.c
index a0bb626c5cb8..4b6181cf2971 100644
--- a/sound/soc/sdw_utils/soc_sdw_cs_amp.c
+++ b/sound/soc/sdw_utils/soc_sdw_cs_amp.c
@@ -15,6 +15,7 @@
#include <sound/soc_sdw_utils.h>
#define CODEC_NAME_SIZE 8
+#define CS_AMP_CHANNELS_PER_AMP 4
int asoc_sdw_cs_spk_rtd_init(struct snd_soc_pcm_runtime *rtd, struct snd_soc_dai *dai)
{
@@ -48,6 +49,51 @@ int asoc_sdw_cs_spk_rtd_init(struct snd_soc_pcm_runtime *rtd, struct snd_soc_dai
}
EXPORT_SYMBOL_NS(asoc_sdw_cs_spk_rtd_init, "SND_SOC_SDW_UTILS");
+int asoc_sdw_cs_spk_feedback_rtd_init(struct snd_soc_pcm_runtime *rtd, struct snd_soc_dai *dai)
+{
+ const struct snd_soc_dai_link *dai_link = rtd->dai_link;
+ const struct snd_soc_dai_link_ch_map *ch_map;
+ const struct snd_soc_dai_link_component *codec_dlc;
+ struct snd_soc_dai *codec_dai;
+ u8 ch_slot[8] = {};
+ unsigned int amps_per_bus, ch_per_amp, mask;
+ int i, ret;
+
+ WARN_ON(dai_link->num_cpus > ARRAY_SIZE(ch_slot));
+
+ /*
+ * CS35L56 has 4 TX channels. When the capture is aggregated the
+ * same bus slots will be allocated to all the amps on a bus. Only
+ * one amp on that bus can be transmitting in each slot so divide
+ * the available 4 slots between all the amps on a bus.
+ */
+ amps_per_bus = dai_link->num_codecs / dai_link->num_cpus;
+ if ((amps_per_bus == 0) || (amps_per_bus > CS_AMP_CHANNELS_PER_AMP)) {
+ dev_err(rtd->card->dev, "Illegal num_codecs:%u / num_cpus:%u\n",
+ dai_link->num_codecs, dai_link->num_cpus);
+ return -EINVAL;
+ }
+
+ ch_per_amp = CS_AMP_CHANNELS_PER_AMP / amps_per_bus;
+
+ for_each_rtd_ch_maps(rtd, i, ch_map) {
+ codec_dlc = snd_soc_link_to_codec(rtd->dai_link, i);
+ codec_dai = snd_soc_find_dai(codec_dlc);
+ mask = GENMASK(ch_per_amp - 1, 0) << ch_slot[ch_map->cpu];
+
+ ret = snd_soc_dai_set_tdm_slot(codec_dai, 0, mask, 4, 32);
+ if (ret < 0) {
+ dev_err(rtd->card->dev, "Failed to set TDM slot:%d\n", ret);
+ return ret;
+ }
+
+ ch_slot[ch_map->cpu] += ch_per_amp;
+ }
+
+ return 0;
+}
+EXPORT_SYMBOL_NS(asoc_sdw_cs_spk_feedback_rtd_init, "SND_SOC_SDW_UTILS");
+
int asoc_sdw_cs_amp_init(struct snd_soc_card *card,
struct snd_soc_dai_link *dai_links,
struct asoc_sdw_codec_info *info,
diff --git a/sound/soc/sdw_utils/soc_sdw_utils.c b/sound/soc/sdw_utils/soc_sdw_utils.c
index 937fa3ce59df..6ee7d30b8ece 100644
--- a/sound/soc/sdw_utils/soc_sdw_utils.c
+++ b/sound/soc/sdw_utils/soc_sdw_utils.c
@@ -488,10 +488,10 @@ struct asoc_sdw_codec_info codec_info_list[] = {
.part_id = 0x3556,
.dais = {
{
- .direction = {true, true},
+ .direction = {true, false},
.dai_name = "cs35l56-sdw1",
.dai_type = SOC_SDW_DAI_TYPE_AMP,
- .dailink = {SOC_SDW_AMP_OUT_DAI_ID, SOC_SDW_AMP_IN_DAI_ID},
+ .dailink = {SOC_SDW_AMP_OUT_DAI_ID, SOC_SDW_UNUSED_DAI_ID},
.init = asoc_sdw_cs_amp_init,
.rtd_init = asoc_sdw_cs_spk_rtd_init,
.controls = generic_spk_controls,
@@ -499,8 +499,15 @@ struct asoc_sdw_codec_info codec_info_list[] = {
.widgets = generic_spk_widgets,
.num_widgets = ARRAY_SIZE(generic_spk_widgets),
},
+ {
+ .direction = {false, true},
+ .dai_name = "cs35l56-sdw1c",
+ .dai_type = SOC_SDW_DAI_TYPE_AMP,
+ .dailink = {SOC_SDW_UNUSED_DAI_ID, SOC_SDW_AMP_IN_DAI_ID},
+ .rtd_init = asoc_sdw_cs_spk_feedback_rtd_init,
+ },
},
- .dai_num = 1,
+ .dai_num = 2,
},
{
.part_id = 0x4242,