1 // SPDX-License-Identifier: GPL-2.0
5 // Copyright (C) 2019 Renesas Electronics Corp.
6 // Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
9 #include <sound/soc-link.h>
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
)
15 /* Positive, Zero values are not errors */
19 /* Negative values might be errors */
26 "ASoC: error at %s on %s: %d\n",
27 func
, rtd
->dai_link
->name
, ret
);
34 * We might want to check substream by using list.
35 * In such case, we can update these macros.
37 #define soc_link_mark_push(rtd, substream, tgt) ((rtd)->mark_##tgt = substream)
38 #define soc_link_mark_pop(rtd, tgt) ((rtd)->mark_##tgt = NULL)
39 #define soc_link_mark_match(rtd, substream, tgt) ((rtd)->mark_##tgt == substream)
41 int snd_soc_link_init(struct snd_soc_pcm_runtime
*rtd
)
45 if (rtd
->dai_link
->init
)
46 ret
= rtd
->dai_link
->init(rtd
);
48 return soc_link_ret(rtd
, ret
);
51 void snd_soc_link_exit(struct snd_soc_pcm_runtime
*rtd
)
53 if (rtd
->dai_link
->exit
)
54 rtd
->dai_link
->exit(rtd
);
57 int snd_soc_link_be_hw_params_fixup(struct snd_soc_pcm_runtime
*rtd
,
58 struct snd_pcm_hw_params
*params
)
62 if (rtd
->dai_link
->be_hw_params_fixup
)
63 ret
= rtd
->dai_link
->be_hw_params_fixup(rtd
, params
);
65 return soc_link_ret(rtd
, ret
);
68 int snd_soc_link_startup(struct snd_pcm_substream
*substream
)
70 struct snd_soc_pcm_runtime
*rtd
= snd_soc_substream_to_rtd(substream
);
73 if (rtd
->dai_link
->ops
&&
74 rtd
->dai_link
->ops
->startup
)
75 ret
= rtd
->dai_link
->ops
->startup(substream
);
77 /* mark substream if succeeded */
79 soc_link_mark_push(rtd
, substream
, startup
);
81 return soc_link_ret(rtd
, ret
);
84 void snd_soc_link_shutdown(struct snd_pcm_substream
*substream
,
87 struct snd_soc_pcm_runtime
*rtd
= snd_soc_substream_to_rtd(substream
);
89 if (rollback
&& !soc_link_mark_match(rtd
, substream
, startup
))
92 if (rtd
->dai_link
->ops
&&
93 rtd
->dai_link
->ops
->shutdown
)
94 rtd
->dai_link
->ops
->shutdown(substream
);
96 /* remove marked substream */
97 soc_link_mark_pop(rtd
, startup
);
100 int snd_soc_link_prepare(struct snd_pcm_substream
*substream
)
102 struct snd_soc_pcm_runtime
*rtd
= snd_soc_substream_to_rtd(substream
);
105 if (rtd
->dai_link
->ops
&&
106 rtd
->dai_link
->ops
->prepare
)
107 ret
= rtd
->dai_link
->ops
->prepare(substream
);
109 return soc_link_ret(rtd
, ret
);
112 int snd_soc_link_hw_params(struct snd_pcm_substream
*substream
,
113 struct snd_pcm_hw_params
*params
)
115 struct snd_soc_pcm_runtime
*rtd
= snd_soc_substream_to_rtd(substream
);
118 if (rtd
->dai_link
->ops
&&
119 rtd
->dai_link
->ops
->hw_params
)
120 ret
= rtd
->dai_link
->ops
->hw_params(substream
, params
);
122 /* mark substream if succeeded */
124 soc_link_mark_push(rtd
, substream
, hw_params
);
126 return soc_link_ret(rtd
, ret
);
129 void snd_soc_link_hw_free(struct snd_pcm_substream
*substream
, int rollback
)
131 struct snd_soc_pcm_runtime
*rtd
= snd_soc_substream_to_rtd(substream
);
133 if (rollback
&& !soc_link_mark_match(rtd
, substream
, hw_params
))
136 if (rtd
->dai_link
->ops
&&
137 rtd
->dai_link
->ops
->hw_free
)
138 rtd
->dai_link
->ops
->hw_free(substream
);
140 /* remove marked substream */
141 soc_link_mark_pop(rtd
, hw_params
);
144 static int soc_link_trigger(struct snd_pcm_substream
*substream
, int cmd
)
146 struct snd_soc_pcm_runtime
*rtd
= snd_soc_substream_to_rtd(substream
);
149 if (rtd
->dai_link
->ops
&&
150 rtd
->dai_link
->ops
->trigger
)
151 ret
= rtd
->dai_link
->ops
->trigger(substream
, cmd
);
153 return soc_link_ret(rtd
, ret
);
156 int snd_soc_link_trigger(struct snd_pcm_substream
*substream
, int cmd
,
159 struct snd_soc_pcm_runtime
*rtd
= snd_soc_substream_to_rtd(substream
);
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
);
169 soc_link_mark_push(rtd
, substream
, trigger
);
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
))
177 ret
= soc_link_trigger(substream
, cmd
);
178 soc_link_mark_pop(rtd
, startup
);
184 int snd_soc_link_compr_startup(struct snd_compr_stream
*cstream
)
186 struct snd_soc_pcm_runtime
*rtd
= cstream
->private_data
;
189 if (rtd
->dai_link
->compr_ops
&&
190 rtd
->dai_link
->compr_ops
->startup
)
191 ret
= rtd
->dai_link
->compr_ops
->startup(cstream
);
194 soc_link_mark_push(rtd
, cstream
, compr_startup
);
196 return soc_link_ret(rtd
, ret
);
198 EXPORT_SYMBOL_GPL(snd_soc_link_compr_startup
);
200 void snd_soc_link_compr_shutdown(struct snd_compr_stream
*cstream
,
203 struct snd_soc_pcm_runtime
*rtd
= cstream
->private_data
;
205 if (rollback
&& !soc_link_mark_match(rtd
, cstream
, compr_startup
))
208 if (rtd
->dai_link
->compr_ops
&&
209 rtd
->dai_link
->compr_ops
->shutdown
)
210 rtd
->dai_link
->compr_ops
->shutdown(cstream
);
212 soc_link_mark_pop(rtd
, compr_startup
);
214 EXPORT_SYMBOL_GPL(snd_soc_link_compr_shutdown
);
216 int snd_soc_link_compr_set_params(struct snd_compr_stream
*cstream
)
218 struct snd_soc_pcm_runtime
*rtd
= cstream
->private_data
;
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
);
225 return soc_link_ret(rtd
, ret
);
227 EXPORT_SYMBOL_GPL(snd_soc_link_compr_set_params
);