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
20struct 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
27static 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
48static 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
69enum snd_soc_acpi_intel_codec
70snd_soc_acpi_intel_detect_codec_type(struct device *dev)
71{
72	int i;
73
74	for (i = 0; i < ARRAY_SIZE(codecs); i++) {
75		if (!acpi_dev_present(codecs[i].acpi_hid, NULL, -1))
76			continue;
77
78		dev_dbg(dev, "codec %s found\n", codecs[i].name);
79		return codecs[i].codec_type;
80	}
81
82	return CODEC_NONE;
83}
84EXPORT_SYMBOL_NS(snd_soc_acpi_intel_detect_codec_type, SND_SOC_ACPI_INTEL_MATCH);
85
86enum snd_soc_acpi_intel_codec
87snd_soc_acpi_intel_detect_amp_type(struct device *dev)
88{
89	int i;
90
91	for (i = 0; i < ARRAY_SIZE(amps); i++) {
92		if (!acpi_dev_present(amps[i].acpi_hid, NULL, -1))
93			continue;
94
95		dev_dbg(dev, "amp %s found\n", amps[i].name);
96		return amps[i].codec_type;
97	}
98
99	return CODEC_NONE;
100}
101EXPORT_SYMBOL_NS(snd_soc_acpi_intel_detect_amp_type, SND_SOC_ACPI_INTEL_MATCH);
102
103const char *
104snd_soc_acpi_intel_get_codec_name(enum snd_soc_acpi_intel_codec codec_type)
105{
106	int i;
107
108	for (i = 0; i < ARRAY_SIZE(codecs); i++) {
109		if (codecs[i].codec_type != codec_type)
110			continue;
111
112		return codecs[i].name;
113	}
114	for (i = 0; i < ARRAY_SIZE(amps); i++) {
115		if (amps[i].codec_type != codec_type)
116			continue;
117
118		return amps[i].name;
119	}
120
121	return NULL;
122}
123EXPORT_SYMBOL_NS(snd_soc_acpi_intel_get_codec_name, SND_SOC_ACPI_INTEL_MATCH);
124
125const char *
126snd_soc_acpi_intel_get_codec_tplg_suffix(enum snd_soc_acpi_intel_codec codec_type)
127{
128	int i;
129
130	for (i = 0; i < ARRAY_SIZE(codecs); i++) {
131		if (codecs[i].codec_type != codec_type)
132			continue;
133
134		return codecs[i].tplg_suffix;
135	}
136
137	return NULL;
138}
139EXPORT_SYMBOL_NS(snd_soc_acpi_intel_get_codec_tplg_suffix, SND_SOC_ACPI_INTEL_MATCH);
140
141const char *
142snd_soc_acpi_intel_get_amp_tplg_suffix(enum snd_soc_acpi_intel_codec codec_type)
143{
144	int i;
145
146	for (i = 0; i < ARRAY_SIZE(amps); i++) {
147		if (amps[i].codec_type != codec_type)
148			continue;
149
150		return amps[i].tplg_suffix;
151	}
152
153	return NULL;
154}
155EXPORT_SYMBOL_NS(snd_soc_acpi_intel_get_amp_tplg_suffix, SND_SOC_ACPI_INTEL_MATCH);
156
157MODULE_DESCRIPTION("ASoC Intel SOF Common Machine Driver Helpers");
158MODULE_AUTHOR("Brent Lu <brent.lu@intel.com>");
159MODULE_LICENSE("GPL");
160