summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMark Brown <broonie@kernel.org>2026-02-25 14:58:04 +0300
committerMark Brown <broonie@kernel.org>2026-02-25 14:58:04 +0300
commit61af3f6ed058a455c4868d6b5baa4ddcbf6a2fe9 (patch)
tree2147328c628123a5f8434c5436c36618c15b6eb9
parent70bbd833986ae6691b3609a0052a733ff2421565 (diff)
parentada32396f90951e12465224c04742607ca56a982 (diff)
downloadlinux-61af3f6ed058a455c4868d6b5baa4ddcbf6a2fe9.tar.xz
ASoC: SDCA: Initial support for Cirrus Logic CS47L47
Merge series from Richard Fitzgerald <rf@opensource.cirrus.com>: The CS47L47 is a SDCA smart codec with UAJ (headset, jack detect) and DMIC. This series adds the initial support for the Cirrus Logic CS47L47 codec.
-rw-r--r--include/sound/soc_sdw_utils.h2
-rw-r--r--sound/soc/sdca/sdca_class.c1
-rw-r--r--sound/soc/sdw_utils/Makefile1
-rw-r--r--sound/soc/sdw_utils/soc_sdw_cs47l47.c80
-rw-r--r--sound/soc/sdw_utils/soc_sdw_utils.c36
5 files changed, 120 insertions, 0 deletions
diff --git a/include/sound/soc_sdw_utils.h b/include/sound/soc_sdw_utils.h
index 227347c8f0b3..98531e500cbb 100644
--- a/include/sound/soc_sdw_utils.h
+++ b/include/sound/soc_sdw_utils.h
@@ -259,6 +259,8 @@ int asoc_sdw_cs42l43_spk_rtd_init(struct snd_soc_pcm_runtime *rtd, struct snd_so
int asoc_sdw_cs42l43_dmic_rtd_init(struct snd_soc_pcm_runtime *rtd, struct snd_soc_dai *dai);
int asoc_sdw_cs42l45_hs_rtd_init(struct snd_soc_pcm_runtime *rtd, struct snd_soc_dai *dai);
int asoc_sdw_cs42l45_dmic_rtd_init(struct snd_soc_pcm_runtime *rtd, struct snd_soc_dai *dai);
+int asoc_sdw_cs47l47_hs_rtd_init(struct snd_soc_pcm_runtime *rtd, struct snd_soc_dai *dai);
+int asoc_sdw_cs47l47_dmic_rtd_init(struct snd_soc_pcm_runtime *rtd, struct snd_soc_dai *dai);
int asoc_sdw_cs_spk_rtd_init(struct snd_soc_pcm_runtime *rtd, struct snd_soc_dai *dai);
int asoc_sdw_maxim_spk_rtd_init(struct snd_soc_pcm_runtime *rtd, struct snd_soc_dai *dai);
/* TI */
diff --git a/sound/soc/sdca/sdca_class.c b/sound/soc/sdca/sdca_class.c
index 918b638acb57..55c33ff63ca2 100644
--- a/sound/soc/sdca/sdca_class.c
+++ b/sound/soc/sdca/sdca_class.c
@@ -317,6 +317,7 @@ static const struct dev_pm_ops class_pm_ops = {
static const struct sdw_device_id class_sdw_id[] = {
SDW_SLAVE_ENTRY(0x01FA, 0x4245, 0),
+ SDW_SLAVE_ENTRY(0x01FA, 0x4747, 0),
{}
};
MODULE_DEVICE_TABLE(sdw, class_sdw_id);
diff --git a/sound/soc/sdw_utils/Makefile b/sound/soc/sdw_utils/Makefile
index e8bd5ffb1a6a..a8d091fd374b 100644
--- a/sound/soc/sdw_utils/Makefile
+++ b/sound/soc/sdw_utils/Makefile
@@ -6,6 +6,7 @@ snd-soc-sdw-utils-y := soc_sdw_utils.o soc_sdw_dmic.o soc_sdw_rt_dmic.o \
soc_sdw_bridge_cs35l56.o \
soc_sdw_cs42l42.o soc_sdw_cs42l43.o \
soc_sdw_cs42l45.o \
+ soc_sdw_cs47l47.o \
soc_sdw_cs_amp.o \
soc_sdw_maxim.o \
soc_sdw_ti_amp.o
diff --git a/sound/soc/sdw_utils/soc_sdw_cs47l47.c b/sound/soc/sdw_utils/soc_sdw_cs47l47.c
new file mode 100644
index 000000000000..259ecf1e0a71
--- /dev/null
+++ b/sound/soc/sdw_utils/soc_sdw_cs47l47.c
@@ -0,0 +1,80 @@
+// SPDX-License-Identifier: GPL-2.0-only
+// Based on sof_sdw_cs42l45.c
+// This file incorporates work covered by the following copyright notice:
+// Copyright (c) 2023 Intel Corporation
+// Copyright (c) 2024 Advanced Micro Devices, Inc.
+
+/*
+ * soc_sdw_cs47l47 - Helpers to handle CS47L47 from generic machine driver
+ */
+#include <linux/device.h>
+#include <linux/errno.h>
+#include <sound/jack.h>
+#include <sound/soc.h>
+#include <sound/soc-card.h>
+#include <sound/soc-component.h>
+#include <sound/soc-dai.h>
+#include <sound/soc_sdw_utils.h>
+
+static struct snd_soc_jack_pin soc_jack_pins[] = {
+ {
+ .pin = "cs47l47 OT 43 Headphone",
+ .mask = SND_JACK_HEADPHONE,
+ },
+ {
+ .pin = "cs47l47 OT 45 Headset",
+ .mask = SND_JACK_HEADPHONE,
+ },
+ {
+ .pin = "cs47l47 IT 31 Microphone",
+ .mask = SND_JACK_MICROPHONE,
+ },
+ {
+ .pin = "cs47l47 IT 33 Headset",
+ .mask = SND_JACK_MICROPHONE,
+ },
+};
+
+int asoc_sdw_cs47l47_hs_rtd_init(struct snd_soc_pcm_runtime *rtd, struct snd_soc_dai *dai)
+{
+ struct snd_soc_card *card = rtd->card;
+ struct snd_soc_component *component = snd_soc_rtd_to_codec(rtd, 0)->component;
+ struct asoc_sdw_mc_private *ctx = snd_soc_card_get_drvdata(card);
+ struct snd_soc_jack *jack = &ctx->sdw_headset;
+ int ret;
+
+ card->components = devm_kasprintf(card->dev, GFP_KERNEL, "%s hs:cs47l47",
+ card->components);
+ if (!card->components)
+ return -ENOMEM;
+
+ ret = snd_soc_card_jack_new_pins(card, "Jack", SND_JACK_MECHANICAL |
+ SND_JACK_HEADSET | SND_JACK_LINEOUT, jack,
+ soc_jack_pins, ARRAY_SIZE(soc_jack_pins));
+ if (ret) {
+ dev_err(card->dev, "Failed to create jack: %d\n", ret);
+ return ret;
+ }
+
+ ret = snd_soc_component_set_jack(component, jack, NULL);
+ if (ret) {
+ dev_err(card->dev, "Failed to register jack: %d\n", ret);
+ return ret;
+ }
+
+ return 0;
+}
+EXPORT_SYMBOL_NS(asoc_sdw_cs47l47_hs_rtd_init, "SND_SOC_SDW_UTILS");
+
+int asoc_sdw_cs47l47_dmic_rtd_init(struct snd_soc_pcm_runtime *rtd, struct snd_soc_dai *dai)
+{
+ struct snd_soc_card *card = rtd->card;
+
+ card->components = devm_kasprintf(card->dev, GFP_KERNEL, "%s mic:cs47l47-dmic",
+ card->components);
+ if (!card->components)
+ return -ENOMEM;
+
+ return 0;
+}
+EXPORT_SYMBOL_NS(asoc_sdw_cs47l47_dmic_rtd_init, "SND_SOC_SDW_UTILS");
diff --git a/sound/soc/sdw_utils/soc_sdw_utils.c b/sound/soc/sdw_utils/soc_sdw_utils.c
index 0e67d9f34cba..eeeb91dded9d 100644
--- a/sound/soc/sdw_utils/soc_sdw_utils.c
+++ b/sound/soc/sdw_utils/soc_sdw_utils.c
@@ -760,6 +760,42 @@ struct asoc_sdw_codec_info codec_info_list[] = {
.aux_num = 1,
},
{
+ .part_id = 0x4747,
+ .name_prefix = "cs47l47",
+ .dais = {
+ {
+ .direction = {true, false},
+ .codec_name = "snd_soc_sdca.UAJ.1",
+ .dai_name = "IT 41",
+ .dai_type = SOC_SDW_DAI_TYPE_JACK,
+ .dailink = {SOC_SDW_JACK_OUT_DAI_ID, SOC_SDW_UNUSED_DAI_ID},
+ .rtd_init = asoc_sdw_cs47l47_hs_rtd_init,
+ },
+ {
+ .direction = {false, true},
+ .codec_name = "snd_soc_sdca.SmartMic.0",
+ .dai_name = "OT 113",
+ .dai_type = SOC_SDW_DAI_TYPE_MIC,
+ .dailink = {SOC_SDW_UNUSED_DAI_ID, SOC_SDW_DMIC_DAI_ID},
+ .rtd_init = asoc_sdw_cs47l47_dmic_rtd_init,
+ },
+ {
+ .direction = {false, true},
+ .codec_name = "snd_soc_sdca.UAJ.1",
+ .dai_name = "OT 36",
+ .dai_type = SOC_SDW_DAI_TYPE_JACK,
+ .dailink = {SOC_SDW_UNUSED_DAI_ID, SOC_SDW_JACK_IN_DAI_ID},
+ },
+ },
+ .dai_num = 3,
+ .auxs = {
+ {
+ .codec_name = "snd_soc_sdca.HID.2",
+ },
+ },
+ .aux_num = 1,
+ },
+ {
.part_id = 0xaaaa, /* generic codec mockup */
.name_prefix = "sdw_mockup_mmulti-function",
.version_id = 0,