]>
Commit | Line | Data |
---|---|---|
1793936b KM |
1 | // SPDX-License-Identifier: GPL-2.0 |
2 | // | |
3 | // soc-card.c | |
4 | // | |
5 | // Copyright (C) 2019 Renesas Electronics Corp. | |
6 | // Kuninori Morimoto <[email protected]> | |
7 | // | |
8 | #include <sound/soc.h> | |
3359e9b6 | 9 | #include <sound/jack.h> |
1793936b KM |
10 | |
11 | #define soc_card_ret(dai, ret) _soc_card_ret(dai, __func__, ret) | |
12 | static inline int _soc_card_ret(struct snd_soc_card *card, | |
13 | const char *func, int ret) | |
14 | { | |
15 | switch (ret) { | |
16 | case -EPROBE_DEFER: | |
17 | case -ENOTSUPP: | |
18 | case 0: | |
19 | break; | |
20 | default: | |
21 | dev_err(card->dev, | |
22 | "ASoC: error at %s on %s: %d\n", | |
23 | func, card->name, ret); | |
24 | } | |
25 | ||
26 | return ret; | |
27 | } | |
209c6cdf KM |
28 | |
29 | struct snd_kcontrol *snd_soc_card_get_kcontrol(struct snd_soc_card *soc_card, | |
30 | const char *name) | |
31 | { | |
32 | struct snd_card *card = soc_card->snd_card; | |
33 | struct snd_kcontrol *kctl; | |
34 | ||
35 | if (unlikely(!name)) | |
36 | return NULL; | |
37 | ||
38 | list_for_each_entry(kctl, &card->controls, list) | |
39 | if (!strncmp(kctl->id.name, name, sizeof(kctl->id.name))) | |
40 | return kctl; | |
41 | return NULL; | |
42 | } | |
43 | EXPORT_SYMBOL_GPL(snd_soc_card_get_kcontrol); | |
3359e9b6 KM |
44 | |
45 | /** | |
46 | * snd_soc_card_jack_new - Create a new jack | |
47 | * @card: ASoC card | |
48 | * @id: an identifying string for this jack | |
49 | * @type: a bitmask of enum snd_jack_type values that can be detected by | |
50 | * this jack | |
51 | * @jack: structure to use for the jack | |
52 | * @pins: Array of jack pins to be added to the jack or NULL | |
53 | * @num_pins: Number of elements in the @pins array | |
54 | * | |
55 | * Creates a new jack object. | |
56 | * | |
57 | * Returns zero if successful, or a negative error code on failure. | |
58 | * On success jack will be initialised. | |
59 | */ | |
60 | int snd_soc_card_jack_new(struct snd_soc_card *card, const char *id, int type, | |
61 | struct snd_soc_jack *jack, | |
62 | struct snd_soc_jack_pin *pins, unsigned int num_pins) | |
63 | { | |
64 | int ret; | |
65 | ||
66 | mutex_init(&jack->mutex); | |
67 | jack->card = card; | |
68 | INIT_LIST_HEAD(&jack->pins); | |
69 | INIT_LIST_HEAD(&jack->jack_zones); | |
70 | BLOCKING_INIT_NOTIFIER_HEAD(&jack->notifier); | |
71 | ||
72 | ret = snd_jack_new(card->snd_card, id, type, &jack->jack, false, false); | |
73 | if (ret) | |
74 | goto end; | |
75 | ||
76 | if (num_pins) | |
77 | ret = snd_soc_jack_add_pins(jack, num_pins, pins); | |
78 | end: | |
79 | return soc_card_ret(card, ret); | |
80 | } | |
81 | EXPORT_SYMBOL_GPL(snd_soc_card_jack_new); | |
130dc08c KM |
82 | |
83 | int snd_soc_card_suspend_pre(struct snd_soc_card *card) | |
84 | { | |
85 | int ret = 0; | |
86 | ||
87 | if (card->suspend_pre) | |
88 | ret = card->suspend_pre(card); | |
89 | ||
90 | return soc_card_ret(card, ret); | |
91 | } | |
d17b60b2 KM |
92 | |
93 | int snd_soc_card_suspend_post(struct snd_soc_card *card) | |
94 | { | |
95 | int ret = 0; | |
96 | ||
97 | if (card->suspend_post) | |
98 | ret = card->suspend_post(card); | |
99 | ||
100 | return soc_card_ret(card, ret); | |
101 | } | |
934c752c KM |
102 | |
103 | int snd_soc_card_resume_pre(struct snd_soc_card *card) | |
104 | { | |
105 | int ret = 0; | |
106 | ||
107 | if (card->resume_pre) | |
108 | ret = card->resume_pre(card); | |
109 | ||
110 | return soc_card_ret(card, ret); | |
111 | } | |
739443d1 KM |
112 | |
113 | int snd_soc_card_resume_post(struct snd_soc_card *card) | |
114 | { | |
115 | int ret = 0; | |
116 | ||
117 | if (card->resume_post) | |
118 | ret = card->resume_post(card); | |
119 | ||
120 | return soc_card_ret(card, ret); | |
121 | } | |
73de4b02 KM |
122 | |
123 | int snd_soc_card_probe(struct snd_soc_card *card) | |
124 | { | |
125 | if (card->probe) { | |
126 | int ret = card->probe(card); | |
127 | ||
128 | if (ret < 0) | |
129 | return soc_card_ret(card, ret); | |
130 | ||
131 | /* | |
132 | * It has "card->probe" and "card->late_probe" callbacks. | |
133 | * So, set "probed" flag here, because it needs to care | |
134 | * about "late_probe". | |
135 | * | |
136 | * see | |
137 | * snd_soc_bind_card() | |
138 | * snd_soc_card_late_probe() | |
139 | */ | |
140 | card->probed = 1; | |
141 | } | |
142 | ||
143 | return 0; | |
144 | } | |
5c0eac03 KM |
145 | |
146 | int snd_soc_card_late_probe(struct snd_soc_card *card) | |
147 | { | |
148 | if (card->late_probe) { | |
149 | int ret = card->late_probe(card); | |
150 | ||
151 | if (ret < 0) | |
152 | return soc_card_ret(card, ret); | |
153 | } | |
154 | ||
155 | /* | |
156 | * It has "card->probe" and "card->late_probe" callbacks, | |
157 | * and "late_probe" callback is called after "probe". | |
158 | * This means, we can set "card->probed" flag afer "late_probe" | |
159 | * for all cases. | |
160 | * | |
161 | * see | |
162 | * snd_soc_bind_card() | |
163 | * snd_soc_card_probe() | |
164 | */ | |
165 | card->probed = 1; | |
166 | ||
167 | return 0; | |
168 | } | |
b0275d95 KM |
169 | |
170 | int snd_soc_card_remove(struct snd_soc_card *card) | |
171 | { | |
172 | int ret = 0; | |
173 | ||
174 | if (card->probed && | |
175 | card->remove) | |
176 | ret = card->remove(card); | |
177 | ||
178 | card->probed = 0; | |
179 | ||
180 | return soc_card_ret(card, ret); | |
181 | } | |
39caefda KM |
182 | |
183 | int snd_soc_card_set_bias_level(struct snd_soc_card *card, | |
184 | struct snd_soc_dapm_context *dapm, | |
185 | enum snd_soc_bias_level level) | |
186 | { | |
187 | int ret = 0; | |
188 | ||
189 | if (card && card->set_bias_level) | |
190 | ret = card->set_bias_level(card, dapm, level); | |
191 | ||
192 | return soc_card_ret(card, ret); | |
193 | } | |
d41278ea KM |
194 | |
195 | int snd_soc_card_set_bias_level_post(struct snd_soc_card *card, | |
196 | struct snd_soc_dapm_context *dapm, | |
197 | enum snd_soc_bias_level level) | |
198 | { | |
199 | int ret = 0; | |
200 | ||
201 | if (card && card->set_bias_level_post) | |
202 | ret = card->set_bias_level_post(card, dapm, level); | |
203 | ||
204 | return soc_card_ret(card, ret); | |
205 | } | |
cbc7a6b5 KM |
206 | |
207 | int snd_soc_card_add_dai_link(struct snd_soc_card *card, | |
208 | struct snd_soc_dai_link *dai_link) | |
209 | { | |
210 | int ret = 0; | |
211 | ||
212 | if (card->add_dai_link) | |
213 | ret = card->add_dai_link(card, dai_link); | |
214 | ||
215 | return soc_card_ret(card, ret); | |
216 | } | |
217 | EXPORT_SYMBOL_GPL(snd_soc_card_add_dai_link); | |
fcbbcc32 KM |
218 | |
219 | void snd_soc_card_remove_dai_link(struct snd_soc_card *card, | |
220 | struct snd_soc_dai_link *dai_link) | |
221 | { | |
222 | if (card->remove_dai_link) | |
223 | card->remove_dai_link(card, dai_link); | |
224 | } | |
225 | EXPORT_SYMBOL_GPL(snd_soc_card_remove_dai_link); |