123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227 |
- // SPDX-License-Identifier: GPL-2.0
- //
- // soc-link.c
- //
- // Copyright (C) 2019 Renesas Electronics Corp.
- // Kuninori Morimoto <[email protected]>
- //
- #include <sound/soc.h>
- #include <sound/soc-link.h>
- #define soc_link_ret(rtd, ret) _soc_link_ret(rtd, __func__, ret)
- static inline int _soc_link_ret(struct snd_soc_pcm_runtime *rtd,
- const char *func, int ret)
- {
- /* Positive, Zero values are not errors */
- if (ret >= 0)
- return ret;
- /* Negative values might be errors */
- switch (ret) {
- case -EPROBE_DEFER:
- case -ENOTSUPP:
- break;
- default:
- dev_err(rtd->dev,
- "ASoC: error at %s on %s: %d\n",
- func, rtd->dai_link->name, ret);
- }
- return ret;
- }
- /*
- * We might want to check substream by using list.
- * In such case, we can update these macros.
- */
- #define soc_link_mark_push(rtd, substream, tgt) ((rtd)->mark_##tgt = substream)
- #define soc_link_mark_pop(rtd, substream, tgt) ((rtd)->mark_##tgt = NULL)
- #define soc_link_mark_match(rtd, substream, tgt) ((rtd)->mark_##tgt == substream)
- int snd_soc_link_init(struct snd_soc_pcm_runtime *rtd)
- {
- int ret = 0;
- if (rtd->dai_link->init)
- ret = rtd->dai_link->init(rtd);
- return soc_link_ret(rtd, ret);
- }
- void snd_soc_link_exit(struct snd_soc_pcm_runtime *rtd)
- {
- if (rtd->dai_link->exit)
- rtd->dai_link->exit(rtd);
- }
- int snd_soc_link_be_hw_params_fixup(struct snd_soc_pcm_runtime *rtd,
- struct snd_pcm_hw_params *params)
- {
- int ret = 0;
- if (rtd->dai_link->be_hw_params_fixup)
- ret = rtd->dai_link->be_hw_params_fixup(rtd, params);
- return soc_link_ret(rtd, ret);
- }
- int snd_soc_link_startup(struct snd_pcm_substream *substream)
- {
- struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream);
- int ret = 0;
- if (rtd->dai_link->ops &&
- rtd->dai_link->ops->startup)
- ret = rtd->dai_link->ops->startup(substream);
- /* mark substream if succeeded */
- if (ret == 0)
- soc_link_mark_push(rtd, substream, startup);
- return soc_link_ret(rtd, ret);
- }
- void snd_soc_link_shutdown(struct snd_pcm_substream *substream,
- int rollback)
- {
- struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream);
- if (rollback && !soc_link_mark_match(rtd, substream, startup))
- return;
- if (rtd->dai_link->ops &&
- rtd->dai_link->ops->shutdown)
- rtd->dai_link->ops->shutdown(substream);
- /* remove marked substream */
- soc_link_mark_pop(rtd, substream, startup);
- }
- int snd_soc_link_prepare(struct snd_pcm_substream *substream)
- {
- struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream);
- int ret = 0;
- if (rtd->dai_link->ops &&
- rtd->dai_link->ops->prepare)
- ret = rtd->dai_link->ops->prepare(substream);
- return soc_link_ret(rtd, ret);
- }
- int snd_soc_link_hw_params(struct snd_pcm_substream *substream,
- struct snd_pcm_hw_params *params)
- {
- struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream);
- int ret = 0;
- if (rtd->dai_link->ops &&
- rtd->dai_link->ops->hw_params)
- ret = rtd->dai_link->ops->hw_params(substream, params);
- /* mark substream if succeeded */
- if (ret == 0)
- soc_link_mark_push(rtd, substream, hw_params);
- return soc_link_ret(rtd, ret);
- }
- void snd_soc_link_hw_free(struct snd_pcm_substream *substream, int rollback)
- {
- struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream);
- if (rollback && !soc_link_mark_match(rtd, substream, hw_params))
- return;
- if (rtd->dai_link->ops &&
- rtd->dai_link->ops->hw_free)
- rtd->dai_link->ops->hw_free(substream);
- /* remove marked substream */
- soc_link_mark_pop(rtd, substream, hw_params);
- }
- static int soc_link_trigger(struct snd_pcm_substream *substream, int cmd)
- {
- struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream);
- int ret = 0;
- if (rtd->dai_link->ops &&
- rtd->dai_link->ops->trigger)
- ret = rtd->dai_link->ops->trigger(substream, cmd);
- return soc_link_ret(rtd, ret);
- }
- int snd_soc_link_trigger(struct snd_pcm_substream *substream, int cmd,
- int rollback)
- {
- struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream);
- int ret = 0;
- switch (cmd) {
- case SNDRV_PCM_TRIGGER_START:
- case SNDRV_PCM_TRIGGER_RESUME:
- case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
- ret = soc_link_trigger(substream, cmd);
- if (ret < 0)
- break;
- soc_link_mark_push(rtd, substream, trigger);
- break;
- case SNDRV_PCM_TRIGGER_STOP:
- case SNDRV_PCM_TRIGGER_SUSPEND:
- case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
- if (rollback && !soc_link_mark_match(rtd, substream, trigger))
- break;
- ret = soc_link_trigger(substream, cmd);
- soc_link_mark_pop(rtd, substream, startup);
- }
- return ret;
- }
- int snd_soc_link_compr_startup(struct snd_compr_stream *cstream)
- {
- struct snd_soc_pcm_runtime *rtd = cstream->private_data;
- int ret = 0;
- if (rtd->dai_link->compr_ops &&
- rtd->dai_link->compr_ops->startup)
- ret = rtd->dai_link->compr_ops->startup(cstream);
- if (ret == 0)
- soc_link_mark_push(rtd, cstream, compr_startup);
- return soc_link_ret(rtd, ret);
- }
- EXPORT_SYMBOL_GPL(snd_soc_link_compr_startup);
- void snd_soc_link_compr_shutdown(struct snd_compr_stream *cstream,
- int rollback)
- {
- struct snd_soc_pcm_runtime *rtd = cstream->private_data;
- if (rollback && !soc_link_mark_match(rtd, cstream, compr_startup))
- return;
- if (rtd->dai_link->compr_ops &&
- rtd->dai_link->compr_ops->shutdown)
- rtd->dai_link->compr_ops->shutdown(cstream);
- soc_link_mark_pop(rtd, cstream, compr_startup);
- }
- EXPORT_SYMBOL_GPL(snd_soc_link_compr_shutdown);
- int snd_soc_link_compr_set_params(struct snd_compr_stream *cstream)
- {
- struct snd_soc_pcm_runtime *rtd = cstream->private_data;
- int ret = 0;
- if (rtd->dai_link->compr_ops &&
- rtd->dai_link->compr_ops->set_params)
- ret = rtd->dai_link->compr_ops->set_params(cstream);
- return soc_link_ret(rtd, ret);
- }
- EXPORT_SYMBOL_GPL(snd_soc_link_compr_set_params);
|