1 // SPDX-License-Identifier: GPL-2.0-only
2 // Based on sof_sdw_rt5682.c
3 // This file incorporates work covered by the following copyright notice:
4 // Copyright (c) 2023 Intel Corporation
5 // Copyright (c) 2024 Advanced Micro Devices, Inc.
8 * soc_sdw_cs42l43 - Helpers to handle CS42L43 from generic machine driver
10 #include <linux/device.h>
11 #include <linux/errno.h>
12 #include <linux/input.h>
13 #include <sound/jack.h>
14 #include <linux/soundwire/sdw.h>
15 #include <linux/soundwire/sdw_type.h>
16 #include <sound/cs42l43.h>
17 #include <sound/control.h>
18 #include <sound/soc.h>
19 #include <sound/soc-acpi.h>
20 #include <sound/soc-dapm.h>
21 #include <sound/soc_sdw_utils.h>
23 static const struct snd_soc_dapm_route cs42l43_hs_map
[] = {
24 { "Headphone", NULL
, "cs42l43 AMP3_OUT" },
25 { "Headphone", NULL
, "cs42l43 AMP4_OUT" },
26 { "cs42l43 ADC1_IN1_P", NULL
, "Headset Mic" },
27 { "cs42l43 ADC1_IN1_N", NULL
, "Headset Mic" },
30 static const struct snd_soc_dapm_route cs42l43_spk_map
[] = {
31 { "Speaker", NULL
, "cs42l43 AMP1_OUT_P", },
32 { "Speaker", NULL
, "cs42l43 AMP1_OUT_N", },
33 { "Speaker", NULL
, "cs42l43 AMP2_OUT_P", },
34 { "Speaker", NULL
, "cs42l43 AMP2_OUT_N", },
37 static const struct snd_soc_dapm_route cs42l43_dmic_map
[] = {
38 { "cs42l43 PDM1_DIN", NULL
, "DMIC" },
39 { "cs42l43 PDM2_DIN", NULL
, "DMIC" },
42 static struct snd_soc_jack_pin soc_jack_pins
[] = {
45 .mask
= SND_JACK_HEADPHONE
,
49 .mask
= SND_JACK_MICROPHONE
,
53 int asoc_sdw_cs42l43_hs_rtd_init(struct snd_soc_pcm_runtime
*rtd
, struct snd_soc_dai
*dai
)
55 struct snd_soc_component
*component
= snd_soc_rtd_to_codec(rtd
, 0)->component
;
56 struct asoc_sdw_mc_private
*ctx
= snd_soc_card_get_drvdata(rtd
->card
);
57 struct snd_soc_jack
*jack
= &ctx
->sdw_headset
;
58 struct snd_soc_card
*card
= rtd
->card
;
61 card
->components
= devm_kasprintf(card
->dev
, GFP_KERNEL
, "%s hs:cs42l43",
63 if (!card
->components
)
66 ret
= snd_soc_dapm_add_routes(&card
->dapm
, cs42l43_hs_map
,
67 ARRAY_SIZE(cs42l43_hs_map
));
69 dev_err(card
->dev
, "cs42l43 hs map addition failed: %d\n", ret
);
73 ret
= snd_soc_card_jack_new_pins(card
, "Jack",
74 SND_JACK_MECHANICAL
| SND_JACK_AVOUT
|
75 SND_JACK_HEADSET
| SND_JACK_LINEOUT
|
76 SND_JACK_BTN_0
| SND_JACK_BTN_1
|
77 SND_JACK_BTN_2
| SND_JACK_BTN_3
,
79 ARRAY_SIZE(soc_jack_pins
));
81 dev_err(card
->dev
, "Failed to create jack: %d\n", ret
);
85 snd_jack_set_key(jack
->jack
, SND_JACK_BTN_0
, KEY_PLAYPAUSE
);
86 snd_jack_set_key(jack
->jack
, SND_JACK_BTN_1
, KEY_VOICECOMMAND
);
87 snd_jack_set_key(jack
->jack
, SND_JACK_BTN_2
, KEY_VOLUMEUP
);
88 snd_jack_set_key(jack
->jack
, SND_JACK_BTN_3
, KEY_VOLUMEDOWN
);
90 ret
= snd_soc_component_set_jack(component
, jack
, NULL
);
92 dev_err(card
->dev
, "Failed to register jack: %d\n", ret
);
96 ret
= snd_soc_component_set_sysclk(component
, CS42L43_SYSCLK
, CS42L43_SYSCLK_SDW
,
99 dev_err(card
->dev
, "Failed to set sysclk: %d\n", ret
);
103 EXPORT_SYMBOL_NS(asoc_sdw_cs42l43_hs_rtd_init
, "SND_SOC_SDW_UTILS");
105 int asoc_sdw_cs42l43_spk_rtd_init(struct snd_soc_pcm_runtime
*rtd
, struct snd_soc_dai
*dai
)
107 struct snd_soc_card
*card
= rtd
->card
;
108 struct asoc_sdw_mc_private
*ctx
= snd_soc_card_get_drvdata(card
);
111 if (!(ctx
->mc_quirk
& SOC_SDW_SIDECAR_AMPS
)) {
112 /* Will be set by the bridge code in this case */
113 card
->components
= devm_kasprintf(card
->dev
, GFP_KERNEL
,
114 "%s spk:cs42l43-spk",
116 if (!card
->components
)
120 ret
= snd_soc_dapm_add_routes(&card
->dapm
, cs42l43_spk_map
,
121 ARRAY_SIZE(cs42l43_spk_map
));
123 dev_err(card
->dev
, "cs42l43 speaker map addition failed: %d\n", ret
);
127 EXPORT_SYMBOL_NS(asoc_sdw_cs42l43_spk_rtd_init
, "SND_SOC_SDW_UTILS");
129 int asoc_sdw_cs42l43_spk_init(struct snd_soc_card
*card
,
130 struct snd_soc_dai_link
*dai_links
,
131 struct asoc_sdw_codec_info
*info
,
134 /* Do init on playback link only. */
140 return asoc_sdw_bridge_cs35l56_spk_init(card
, dai_links
, info
, playback
);
142 EXPORT_SYMBOL_NS(asoc_sdw_cs42l43_spk_init
, "SND_SOC_SDW_UTILS");
144 int asoc_sdw_cs42l43_dmic_rtd_init(struct snd_soc_pcm_runtime
*rtd
, struct snd_soc_dai
*dai
)
146 struct snd_soc_card
*card
= rtd
->card
;
149 card
->components
= devm_kasprintf(card
->dev
, GFP_KERNEL
, "%s mic:cs42l43-dmic",
151 if (!card
->components
)
154 ret
= snd_soc_dapm_add_routes(&card
->dapm
, cs42l43_dmic_map
,
155 ARRAY_SIZE(cs42l43_dmic_map
));
157 dev_err(card
->dev
, "cs42l43 dmic map addition failed: %d\n", ret
);
161 EXPORT_SYMBOL_NS(asoc_sdw_cs42l43_dmic_rtd_init
, "SND_SOC_SDW_UTILS");