Commit | Line | Data |
---|---|---|
02e75636 KM |
1 | // SPDX-License-Identifier: GPL-2.0 |
2 | // | |
3 | // soc-link.c | |
4 | // | |
5 | // Copyright (C) 2019 Renesas Electronics Corp. | |
6 | // Kuninori Morimoto <kuninori.morimoto.gx@renesas.com> | |
7 | // | |
8 | #include <sound/soc.h> | |
9 | #include <sound/soc-link.h> | |
10 | ||
11 | #define soc_link_ret(rtd, ret) _soc_link_ret(rtd, __func__, ret) | |
12 | static inline int _soc_link_ret(struct snd_soc_pcm_runtime *rtd, | |
13 | const char *func, int ret) | |
14 | { | |
28ff437a PLB |
15 | /* Positive, Zero values are not errors */ |
16 | if (ret >= 0) | |
17 | return ret; | |
18 | ||
19 | /* Negative values might be errors */ | |
02e75636 KM |
20 | switch (ret) { |
21 | case -EPROBE_DEFER: | |
22 | case -ENOTSUPP: | |
02e75636 KM |
23 | break; |
24 | default: | |
25 | dev_err(rtd->dev, | |
26 | "ASoC: error at %s on %s: %d\n", | |
27 | func, rtd->dai_link->name, ret); | |
28 | } | |
29 | ||
30 | return ret; | |
31 | } | |
32 | ||
6064ed73 KM |
33 | /* |
34 | * We might want to check substream by using list. | |
35 | * In such case, we can update these macros. | |
36 | */ | |
37 | #define soc_link_mark_push(rtd, substream, tgt) ((rtd)->mark_##tgt = substream) | |
38 | #define soc_link_mark_pop(rtd, substream, tgt) ((rtd)->mark_##tgt = NULL) | |
39 | #define soc_link_mark_match(rtd, substream, tgt) ((rtd)->mark_##tgt == substream) | |
40 | ||
02e75636 KM |
41 | int snd_soc_link_init(struct snd_soc_pcm_runtime *rtd) |
42 | { | |
43 | int ret = 0; | |
44 | ||
45 | if (rtd->dai_link->init) | |
46 | ret = rtd->dai_link->init(rtd); | |
47 | ||
48 | return soc_link_ret(rtd, ret); | |
49 | } | |
a5e6c109 | 50 | |
21a00fb3 PLB |
51 | void snd_soc_link_exit(struct snd_soc_pcm_runtime *rtd) |
52 | { | |
53 | if (rtd->dai_link->exit) | |
54 | rtd->dai_link->exit(rtd); | |
55 | } | |
56 | ||
0cbbf8a0 KM |
57 | int snd_soc_link_be_hw_params_fixup(struct snd_soc_pcm_runtime *rtd, |
58 | struct snd_pcm_hw_params *params) | |
59 | { | |
60 | int ret = 0; | |
61 | ||
62 | if (rtd->dai_link->be_hw_params_fixup) | |
63 | ret = rtd->dai_link->be_hw_params_fixup(rtd, params); | |
64 | ||
65 | return soc_link_ret(rtd, ret); | |
66 | } | |
67 | ||
7cf3c5b4 | 68 | int snd_soc_link_startup(struct snd_pcm_substream *substream) |
a5e6c109 | 69 | { |
9099904b | 70 | struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream); |
a5e6c109 KM |
71 | int ret = 0; |
72 | ||
73 | if (rtd->dai_link->ops && | |
74 | rtd->dai_link->ops->startup) | |
75 | ret = rtd->dai_link->ops->startup(substream); | |
76 | ||
6064ed73 KM |
77 | /* mark substream if succeeded */ |
78 | if (ret == 0) | |
79 | soc_link_mark_push(rtd, substream, startup); | |
80 | ||
a5e6c109 KM |
81 | return soc_link_ret(rtd, ret); |
82 | } | |
83 | ||
6064ed73 KM |
84 | void snd_soc_link_shutdown(struct snd_pcm_substream *substream, |
85 | int rollback) | |
a5e6c109 | 86 | { |
9099904b | 87 | struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream); |
7cf3c5b4 | 88 | |
6064ed73 KM |
89 | if (rollback && !soc_link_mark_match(rtd, substream, startup)) |
90 | return; | |
91 | ||
a5e6c109 KM |
92 | if (rtd->dai_link->ops && |
93 | rtd->dai_link->ops->shutdown) | |
94 | rtd->dai_link->ops->shutdown(substream); | |
6064ed73 KM |
95 | |
96 | /* remove marked substream */ | |
97 | soc_link_mark_pop(rtd, substream, startup); | |
a5e6c109 KM |
98 | } |
99 | ||
7cf3c5b4 | 100 | int snd_soc_link_prepare(struct snd_pcm_substream *substream) |
a5e6c109 | 101 | { |
9099904b | 102 | struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream); |
a5e6c109 KM |
103 | int ret = 0; |
104 | ||
105 | if (rtd->dai_link->ops && | |
106 | rtd->dai_link->ops->prepare) | |
107 | ret = rtd->dai_link->ops->prepare(substream); | |
108 | ||
109 | return soc_link_ret(rtd, ret); | |
110 | } | |
111 | ||
7cf3c5b4 | 112 | int snd_soc_link_hw_params(struct snd_pcm_substream *substream, |
a5e6c109 KM |
113 | struct snd_pcm_hw_params *params) |
114 | { | |
9099904b | 115 | struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream); |
a5e6c109 KM |
116 | int ret = 0; |
117 | ||
118 | if (rtd->dai_link->ops && | |
119 | rtd->dai_link->ops->hw_params) | |
120 | ret = rtd->dai_link->ops->hw_params(substream, params); | |
121 | ||
918ad772 KM |
122 | /* mark substream if succeeded */ |
123 | if (ret == 0) | |
124 | soc_link_mark_push(rtd, substream, hw_params); | |
125 | ||
a5e6c109 KM |
126 | return soc_link_ret(rtd, ret); |
127 | } | |
128 | ||
918ad772 | 129 | void snd_soc_link_hw_free(struct snd_pcm_substream *substream, int rollback) |
a5e6c109 | 130 | { |
9099904b | 131 | struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream); |
7cf3c5b4 | 132 | |
918ad772 KM |
133 | if (rollback && !soc_link_mark_match(rtd, substream, hw_params)) |
134 | return; | |
135 | ||
a5e6c109 KM |
136 | if (rtd->dai_link->ops && |
137 | rtd->dai_link->ops->hw_free) | |
138 | rtd->dai_link->ops->hw_free(substream); | |
918ad772 KM |
139 | |
140 | /* remove marked substream */ | |
141 | soc_link_mark_pop(rtd, substream, hw_params); | |
a5e6c109 KM |
142 | } |
143 | ||
6374f493 | 144 | static int soc_link_trigger(struct snd_pcm_substream *substream, int cmd) |
a5e6c109 | 145 | { |
9099904b | 146 | struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream); |
a5e6c109 KM |
147 | int ret = 0; |
148 | ||
149 | if (rtd->dai_link->ops && | |
150 | rtd->dai_link->ops->trigger) | |
151 | ret = rtd->dai_link->ops->trigger(substream, cmd); | |
152 | ||
153 | return soc_link_ret(rtd, ret); | |
154 | } | |
9ab711cb | 155 | |
6374f493 KM |
156 | int snd_soc_link_trigger(struct snd_pcm_substream *substream, int cmd, |
157 | int rollback) | |
158 | { | |
9099904b | 159 | struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream); |
6374f493 KM |
160 | int ret = 0; |
161 | ||
162 | switch (cmd) { | |
163 | case SNDRV_PCM_TRIGGER_START: | |
164 | case SNDRV_PCM_TRIGGER_RESUME: | |
165 | case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: | |
166 | ret = soc_link_trigger(substream, cmd); | |
167 | if (ret < 0) | |
168 | break; | |
169 | soc_link_mark_push(rtd, substream, trigger); | |
170 | break; | |
171 | case SNDRV_PCM_TRIGGER_STOP: | |
172 | case SNDRV_PCM_TRIGGER_SUSPEND: | |
173 | case SNDRV_PCM_TRIGGER_PAUSE_PUSH: | |
174 | if (rollback && !soc_link_mark_match(rtd, substream, trigger)) | |
175 | break; | |
176 | ||
177 | ret = soc_link_trigger(substream, cmd); | |
178 | soc_link_mark_pop(rtd, substream, startup); | |
179 | } | |
180 | ||
181 | return ret; | |
182 | } | |
183 | ||
9ab711cb KM |
184 | int snd_soc_link_compr_startup(struct snd_compr_stream *cstream) |
185 | { | |
186 | struct snd_soc_pcm_runtime *rtd = cstream->private_data; | |
187 | int ret = 0; | |
188 | ||
189 | if (rtd->dai_link->compr_ops && | |
190 | rtd->dai_link->compr_ops->startup) | |
191 | ret = rtd->dai_link->compr_ops->startup(cstream); | |
192 | ||
cd7c7d10 KM |
193 | if (ret == 0) |
194 | soc_link_mark_push(rtd, cstream, compr_startup); | |
195 | ||
9ab711cb KM |
196 | return soc_link_ret(rtd, ret); |
197 | } | |
198 | EXPORT_SYMBOL_GPL(snd_soc_link_compr_startup); | |
0e532c99 | 199 | |
cd7c7d10 KM |
200 | void snd_soc_link_compr_shutdown(struct snd_compr_stream *cstream, |
201 | int rollback) | |
0e532c99 KM |
202 | { |
203 | struct snd_soc_pcm_runtime *rtd = cstream->private_data; | |
204 | ||
cd7c7d10 KM |
205 | if (rollback && !soc_link_mark_match(rtd, cstream, compr_startup)) |
206 | return; | |
207 | ||
0e532c99 KM |
208 | if (rtd->dai_link->compr_ops && |
209 | rtd->dai_link->compr_ops->shutdown) | |
210 | rtd->dai_link->compr_ops->shutdown(cstream); | |
cd7c7d10 KM |
211 | |
212 | soc_link_mark_pop(rtd, cstream, compr_startup); | |
0e532c99 KM |
213 | } |
214 | EXPORT_SYMBOL_GPL(snd_soc_link_compr_shutdown); | |
eab810f3 KM |
215 | |
216 | int snd_soc_link_compr_set_params(struct snd_compr_stream *cstream) | |
217 | { | |
218 | struct snd_soc_pcm_runtime *rtd = cstream->private_data; | |
219 | int ret = 0; | |
220 | ||
221 | if (rtd->dai_link->compr_ops && | |
222 | rtd->dai_link->compr_ops->set_params) | |
223 | ret = rtd->dai_link->compr_ops->set_params(cstream); | |
224 | ||
225 | return soc_link_ret(rtd, ret); | |
226 | } | |
227 | EXPORT_SYMBOL_GPL(snd_soc_link_compr_set_params); |