1 // SPDX-License-Identifier: GPL-2.0-only
2 //
3 // Copyright(c) 2023 Intel Corporation
4
5 #include <linux/device.h>
6 #include <sound/soc-acpi.h>
7 #include <sound/soc-acpi-intel-ssp-common.h>
8
9 /*
10 * Codec probe function
11 */
12 #define CODEC_MAP_ENTRY(n, s, h, t) \
13 { \
14 .name = n, \
15 .tplg_suffix = s, \
16 .acpi_hid = h, \
17 .codec_type = t, \
18 }
19
20 struct codec_map {
21 const char *name;
22 const char *tplg_suffix;
23 const char *acpi_hid;
24 enum snd_soc_acpi_intel_codec codec_type;
25 };
26
27 static const struct codec_map codecs[] = {
28 /* Cirrus Logic */
29 CODEC_MAP_ENTRY("CS42L42", "cs42l42", CS42L42_ACPI_HID, CODEC_CS42L42),
30
31 /* Dialog */
32 CODEC_MAP_ENTRY("DA7219", "da7219", DA7219_ACPI_HID, CODEC_DA7219),
33
34 /* Everest */
35 CODEC_MAP_ENTRY("ES8316", "es8336", ES8316_ACPI_HID, CODEC_ES8316),
36 CODEC_MAP_ENTRY("ES8326", "es8336", ES8326_ACPI_HID, CODEC_ES8326),
37 CODEC_MAP_ENTRY("ES8336", "es8336", ES8336_ACPI_HID, CODEC_ES8336),
38
39 /* Nuvoton */
40 CODEC_MAP_ENTRY("NAU8825", "nau8825", NAU8825_ACPI_HID, CODEC_NAU8825),
41
42 /* Realtek */
43 CODEC_MAP_ENTRY("RT5650", "rt5650", RT5650_ACPI_HID, CODEC_RT5650),
44 CODEC_MAP_ENTRY("RT5682", "rt5682", RT5682_ACPI_HID, CODEC_RT5682),
45 CODEC_MAP_ENTRY("RT5682S", "rt5682", RT5682S_ACPI_HID, CODEC_RT5682S),
46 };
47
48 static const struct codec_map amps[] = {
49 /* Cirrus Logic */
50 CODEC_MAP_ENTRY("CS35L41", "cs35l41", CS35L41_ACPI_HID, CODEC_CS35L41),
51
52 /* Maxim */
53 CODEC_MAP_ENTRY("MAX98357A", "max98357a", MAX_98357A_ACPI_HID, CODEC_MAX98357A),
54 CODEC_MAP_ENTRY("MAX98360A", "max98360a", MAX_98360A_ACPI_HID, CODEC_MAX98360A),
55 CODEC_MAP_ENTRY("MAX98373", "max98373", MAX_98373_ACPI_HID, CODEC_MAX98373),
56 CODEC_MAP_ENTRY("MAX98390", "max98390", MAX_98390_ACPI_HID, CODEC_MAX98390),
57
58 /* Nuvoton */
59 CODEC_MAP_ENTRY("NAU8318", "nau8318", NAU8318_ACPI_HID, CODEC_NAU8318),
60
61 /* Realtek */
62 CODEC_MAP_ENTRY("RT1011", "rt1011", RT1011_ACPI_HID, CODEC_RT1011),
63 CODEC_MAP_ENTRY("RT1015", "rt1015", RT1015_ACPI_HID, CODEC_RT1015),
64 CODEC_MAP_ENTRY("RT1015P", "rt1015", RT1015P_ACPI_HID, CODEC_RT1015P),
65 CODEC_MAP_ENTRY("RT1019P", "rt1019", RT1019P_ACPI_HID, CODEC_RT1019P),
66 CODEC_MAP_ENTRY("RT1308", "rt1308", RT1308_ACPI_HID, CODEC_RT1308),
67
68 /*
69 * Monolithic components
70 *
71 * Only put components that can serve as both the amp and the codec below this line.
72 * This will ensure that if the part is used just as a codec and there is an amp as well
73 * then the amp will be selected properly.
74 */
75 CODEC_MAP_ENTRY("RT5650", "rt5650", RT5650_ACPI_HID, CODEC_RT5650),
76 };
77
78 enum snd_soc_acpi_intel_codec
snd_soc_acpi_intel_detect_codec_type(struct device * dev)79 snd_soc_acpi_intel_detect_codec_type(struct device *dev)
80 {
81 int i;
82
83 for (i = 0; i < ARRAY_SIZE(codecs); i++) {
84 if (!acpi_dev_present(codecs[i].acpi_hid, NULL, -1))
85 continue;
86
87 dev_dbg(dev, "codec %s found\n", codecs[i].name);
88 return codecs[i].codec_type;
89 }
90
91 return CODEC_NONE;
92 }
93 EXPORT_SYMBOL_NS(snd_soc_acpi_intel_detect_codec_type, SND_SOC_ACPI_INTEL_MATCH);
94
95 enum snd_soc_acpi_intel_codec
snd_soc_acpi_intel_detect_amp_type(struct device * dev)96 snd_soc_acpi_intel_detect_amp_type(struct device *dev)
97 {
98 int i;
99
100 for (i = 0; i < ARRAY_SIZE(amps); i++) {
101 if (!acpi_dev_present(amps[i].acpi_hid, NULL, -1))
102 continue;
103
104 dev_dbg(dev, "amp %s found\n", amps[i].name);
105 return amps[i].codec_type;
106 }
107
108 return CODEC_NONE;
109 }
110 EXPORT_SYMBOL_NS(snd_soc_acpi_intel_detect_amp_type, SND_SOC_ACPI_INTEL_MATCH);
111
112 const char *
snd_soc_acpi_intel_get_codec_name(enum snd_soc_acpi_intel_codec codec_type)113 snd_soc_acpi_intel_get_codec_name(enum snd_soc_acpi_intel_codec codec_type)
114 {
115 int i;
116
117 for (i = 0; i < ARRAY_SIZE(codecs); i++) {
118 if (codecs[i].codec_type != codec_type)
119 continue;
120
121 return codecs[i].name;
122 }
123 for (i = 0; i < ARRAY_SIZE(amps); i++) {
124 if (amps[i].codec_type != codec_type)
125 continue;
126
127 return amps[i].name;
128 }
129
130 return NULL;
131 }
132 EXPORT_SYMBOL_NS(snd_soc_acpi_intel_get_codec_name, SND_SOC_ACPI_INTEL_MATCH);
133
134 const char *
snd_soc_acpi_intel_get_codec_tplg_suffix(enum snd_soc_acpi_intel_codec codec_type)135 snd_soc_acpi_intel_get_codec_tplg_suffix(enum snd_soc_acpi_intel_codec codec_type)
136 {
137 int i;
138
139 for (i = 0; i < ARRAY_SIZE(codecs); i++) {
140 if (codecs[i].codec_type != codec_type)
141 continue;
142
143 return codecs[i].tplg_suffix;
144 }
145
146 return NULL;
147 }
148 EXPORT_SYMBOL_NS(snd_soc_acpi_intel_get_codec_tplg_suffix, SND_SOC_ACPI_INTEL_MATCH);
149
150 const char *
snd_soc_acpi_intel_get_amp_tplg_suffix(enum snd_soc_acpi_intel_codec codec_type)151 snd_soc_acpi_intel_get_amp_tplg_suffix(enum snd_soc_acpi_intel_codec codec_type)
152 {
153 int i;
154
155 for (i = 0; i < ARRAY_SIZE(amps); i++) {
156 if (amps[i].codec_type != codec_type)
157 continue;
158
159 return amps[i].tplg_suffix;
160 }
161
162 return NULL;
163 }
164 EXPORT_SYMBOL_NS(snd_soc_acpi_intel_get_amp_tplg_suffix, SND_SOC_ACPI_INTEL_MATCH);
165
166 MODULE_DESCRIPTION("ASoC Intel SOF Common Machine Driver Helpers");
167 MODULE_AUTHOR("Brent Lu <brent.lu@intel.com>");
168 MODULE_LICENSE("GPL");
169