18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0 28c2ecf20Sopenharmony_ci// 38c2ecf20Sopenharmony_ci// soc-link.c 48c2ecf20Sopenharmony_ci// 58c2ecf20Sopenharmony_ci// Copyright (C) 2019 Renesas Electronics Corp. 68c2ecf20Sopenharmony_ci// Kuninori Morimoto <kuninori.morimoto.gx@renesas.com> 78c2ecf20Sopenharmony_ci// 88c2ecf20Sopenharmony_ci#include <sound/soc.h> 98c2ecf20Sopenharmony_ci#include <sound/soc-link.h> 108c2ecf20Sopenharmony_ci 118c2ecf20Sopenharmony_ci#define soc_link_ret(rtd, ret) _soc_link_ret(rtd, __func__, ret) 128c2ecf20Sopenharmony_cistatic inline int _soc_link_ret(struct snd_soc_pcm_runtime *rtd, 138c2ecf20Sopenharmony_ci const char *func, int ret) 148c2ecf20Sopenharmony_ci{ 158c2ecf20Sopenharmony_ci /* Positive, Zero values are not errors */ 168c2ecf20Sopenharmony_ci if (ret >= 0) 178c2ecf20Sopenharmony_ci return ret; 188c2ecf20Sopenharmony_ci 198c2ecf20Sopenharmony_ci /* Negative values might be errors */ 208c2ecf20Sopenharmony_ci switch (ret) { 218c2ecf20Sopenharmony_ci case -EPROBE_DEFER: 228c2ecf20Sopenharmony_ci case -ENOTSUPP: 238c2ecf20Sopenharmony_ci break; 248c2ecf20Sopenharmony_ci default: 258c2ecf20Sopenharmony_ci dev_err(rtd->dev, 268c2ecf20Sopenharmony_ci "ASoC: error at %s on %s: %d\n", 278c2ecf20Sopenharmony_ci func, rtd->dai_link->name, ret); 288c2ecf20Sopenharmony_ci } 298c2ecf20Sopenharmony_ci 308c2ecf20Sopenharmony_ci return ret; 318c2ecf20Sopenharmony_ci} 328c2ecf20Sopenharmony_ci 338c2ecf20Sopenharmony_ci/* 348c2ecf20Sopenharmony_ci * We might want to check substream by using list. 358c2ecf20Sopenharmony_ci * In such case, we can update these macros. 368c2ecf20Sopenharmony_ci */ 378c2ecf20Sopenharmony_ci#define soc_link_mark_push(rtd, substream, tgt) ((rtd)->mark_##tgt = substream) 388c2ecf20Sopenharmony_ci#define soc_link_mark_pop(rtd, substream, tgt) ((rtd)->mark_##tgt = NULL) 398c2ecf20Sopenharmony_ci#define soc_link_mark_match(rtd, substream, tgt) ((rtd)->mark_##tgt == substream) 408c2ecf20Sopenharmony_ci 418c2ecf20Sopenharmony_ciint snd_soc_link_init(struct snd_soc_pcm_runtime *rtd) 428c2ecf20Sopenharmony_ci{ 438c2ecf20Sopenharmony_ci int ret = 0; 448c2ecf20Sopenharmony_ci 458c2ecf20Sopenharmony_ci if (rtd->dai_link->init) 468c2ecf20Sopenharmony_ci ret = rtd->dai_link->init(rtd); 478c2ecf20Sopenharmony_ci 488c2ecf20Sopenharmony_ci return soc_link_ret(rtd, ret); 498c2ecf20Sopenharmony_ci} 508c2ecf20Sopenharmony_ci 518c2ecf20Sopenharmony_civoid snd_soc_link_exit(struct snd_soc_pcm_runtime *rtd) 528c2ecf20Sopenharmony_ci{ 538c2ecf20Sopenharmony_ci if (rtd->dai_link->exit) 548c2ecf20Sopenharmony_ci rtd->dai_link->exit(rtd); 558c2ecf20Sopenharmony_ci} 568c2ecf20Sopenharmony_ci 578c2ecf20Sopenharmony_ciint snd_soc_link_be_hw_params_fixup(struct snd_soc_pcm_runtime *rtd, 588c2ecf20Sopenharmony_ci struct snd_pcm_hw_params *params) 598c2ecf20Sopenharmony_ci{ 608c2ecf20Sopenharmony_ci int ret = 0; 618c2ecf20Sopenharmony_ci 628c2ecf20Sopenharmony_ci if (rtd->dai_link->be_hw_params_fixup) 638c2ecf20Sopenharmony_ci ret = rtd->dai_link->be_hw_params_fixup(rtd, params); 648c2ecf20Sopenharmony_ci 658c2ecf20Sopenharmony_ci return soc_link_ret(rtd, ret); 668c2ecf20Sopenharmony_ci} 678c2ecf20Sopenharmony_ci 688c2ecf20Sopenharmony_ciint snd_soc_link_startup(struct snd_pcm_substream *substream) 698c2ecf20Sopenharmony_ci{ 708c2ecf20Sopenharmony_ci struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); 718c2ecf20Sopenharmony_ci int ret = 0; 728c2ecf20Sopenharmony_ci 738c2ecf20Sopenharmony_ci if (rtd->dai_link->ops && 748c2ecf20Sopenharmony_ci rtd->dai_link->ops->startup) 758c2ecf20Sopenharmony_ci ret = rtd->dai_link->ops->startup(substream); 768c2ecf20Sopenharmony_ci 778c2ecf20Sopenharmony_ci /* mark substream if succeeded */ 788c2ecf20Sopenharmony_ci if (ret == 0) 798c2ecf20Sopenharmony_ci soc_link_mark_push(rtd, substream, startup); 808c2ecf20Sopenharmony_ci 818c2ecf20Sopenharmony_ci return soc_link_ret(rtd, ret); 828c2ecf20Sopenharmony_ci} 838c2ecf20Sopenharmony_ci 848c2ecf20Sopenharmony_civoid snd_soc_link_shutdown(struct snd_pcm_substream *substream, 858c2ecf20Sopenharmony_ci int rollback) 868c2ecf20Sopenharmony_ci{ 878c2ecf20Sopenharmony_ci struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); 888c2ecf20Sopenharmony_ci 898c2ecf20Sopenharmony_ci if (rollback && !soc_link_mark_match(rtd, substream, startup)) 908c2ecf20Sopenharmony_ci return; 918c2ecf20Sopenharmony_ci 928c2ecf20Sopenharmony_ci if (rtd->dai_link->ops && 938c2ecf20Sopenharmony_ci rtd->dai_link->ops->shutdown) 948c2ecf20Sopenharmony_ci rtd->dai_link->ops->shutdown(substream); 958c2ecf20Sopenharmony_ci 968c2ecf20Sopenharmony_ci /* remove marked substream */ 978c2ecf20Sopenharmony_ci soc_link_mark_pop(rtd, substream, startup); 988c2ecf20Sopenharmony_ci} 998c2ecf20Sopenharmony_ci 1008c2ecf20Sopenharmony_ciint snd_soc_link_prepare(struct snd_pcm_substream *substream) 1018c2ecf20Sopenharmony_ci{ 1028c2ecf20Sopenharmony_ci struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); 1038c2ecf20Sopenharmony_ci int ret = 0; 1048c2ecf20Sopenharmony_ci 1058c2ecf20Sopenharmony_ci if (rtd->dai_link->ops && 1068c2ecf20Sopenharmony_ci rtd->dai_link->ops->prepare) 1078c2ecf20Sopenharmony_ci ret = rtd->dai_link->ops->prepare(substream); 1088c2ecf20Sopenharmony_ci 1098c2ecf20Sopenharmony_ci return soc_link_ret(rtd, ret); 1108c2ecf20Sopenharmony_ci} 1118c2ecf20Sopenharmony_ci 1128c2ecf20Sopenharmony_ciint snd_soc_link_hw_params(struct snd_pcm_substream *substream, 1138c2ecf20Sopenharmony_ci struct snd_pcm_hw_params *params) 1148c2ecf20Sopenharmony_ci{ 1158c2ecf20Sopenharmony_ci struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); 1168c2ecf20Sopenharmony_ci int ret = 0; 1178c2ecf20Sopenharmony_ci 1188c2ecf20Sopenharmony_ci if (rtd->dai_link->ops && 1198c2ecf20Sopenharmony_ci rtd->dai_link->ops->hw_params) 1208c2ecf20Sopenharmony_ci ret = rtd->dai_link->ops->hw_params(substream, params); 1218c2ecf20Sopenharmony_ci 1228c2ecf20Sopenharmony_ci return soc_link_ret(rtd, ret); 1238c2ecf20Sopenharmony_ci} 1248c2ecf20Sopenharmony_ci 1258c2ecf20Sopenharmony_civoid snd_soc_link_hw_free(struct snd_pcm_substream *substream) 1268c2ecf20Sopenharmony_ci{ 1278c2ecf20Sopenharmony_ci struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); 1288c2ecf20Sopenharmony_ci 1298c2ecf20Sopenharmony_ci if (rtd->dai_link->ops && 1308c2ecf20Sopenharmony_ci rtd->dai_link->ops->hw_free) 1318c2ecf20Sopenharmony_ci rtd->dai_link->ops->hw_free(substream); 1328c2ecf20Sopenharmony_ci} 1338c2ecf20Sopenharmony_ci 1348c2ecf20Sopenharmony_ciint snd_soc_link_trigger(struct snd_pcm_substream *substream, int cmd) 1358c2ecf20Sopenharmony_ci{ 1368c2ecf20Sopenharmony_ci struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); 1378c2ecf20Sopenharmony_ci int ret = 0; 1388c2ecf20Sopenharmony_ci 1398c2ecf20Sopenharmony_ci if (rtd->dai_link->ops && 1408c2ecf20Sopenharmony_ci rtd->dai_link->ops->trigger) 1418c2ecf20Sopenharmony_ci ret = rtd->dai_link->ops->trigger(substream, cmd); 1428c2ecf20Sopenharmony_ci 1438c2ecf20Sopenharmony_ci return soc_link_ret(rtd, ret); 1448c2ecf20Sopenharmony_ci} 1458c2ecf20Sopenharmony_ci 1468c2ecf20Sopenharmony_ciint snd_soc_link_compr_startup(struct snd_compr_stream *cstream) 1478c2ecf20Sopenharmony_ci{ 1488c2ecf20Sopenharmony_ci struct snd_soc_pcm_runtime *rtd = cstream->private_data; 1498c2ecf20Sopenharmony_ci int ret = 0; 1508c2ecf20Sopenharmony_ci 1518c2ecf20Sopenharmony_ci if (rtd->dai_link->compr_ops && 1528c2ecf20Sopenharmony_ci rtd->dai_link->compr_ops->startup) 1538c2ecf20Sopenharmony_ci ret = rtd->dai_link->compr_ops->startup(cstream); 1548c2ecf20Sopenharmony_ci 1558c2ecf20Sopenharmony_ci return soc_link_ret(rtd, ret); 1568c2ecf20Sopenharmony_ci} 1578c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(snd_soc_link_compr_startup); 1588c2ecf20Sopenharmony_ci 1598c2ecf20Sopenharmony_civoid snd_soc_link_compr_shutdown(struct snd_compr_stream *cstream) 1608c2ecf20Sopenharmony_ci{ 1618c2ecf20Sopenharmony_ci struct snd_soc_pcm_runtime *rtd = cstream->private_data; 1628c2ecf20Sopenharmony_ci 1638c2ecf20Sopenharmony_ci if (rtd->dai_link->compr_ops && 1648c2ecf20Sopenharmony_ci rtd->dai_link->compr_ops->shutdown) 1658c2ecf20Sopenharmony_ci rtd->dai_link->compr_ops->shutdown(cstream); 1668c2ecf20Sopenharmony_ci} 1678c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(snd_soc_link_compr_shutdown); 1688c2ecf20Sopenharmony_ci 1698c2ecf20Sopenharmony_ciint snd_soc_link_compr_set_params(struct snd_compr_stream *cstream) 1708c2ecf20Sopenharmony_ci{ 1718c2ecf20Sopenharmony_ci struct snd_soc_pcm_runtime *rtd = cstream->private_data; 1728c2ecf20Sopenharmony_ci int ret = 0; 1738c2ecf20Sopenharmony_ci 1748c2ecf20Sopenharmony_ci if (rtd->dai_link->compr_ops && 1758c2ecf20Sopenharmony_ci rtd->dai_link->compr_ops->set_params) 1768c2ecf20Sopenharmony_ci ret = rtd->dai_link->compr_ops->set_params(cstream); 1778c2ecf20Sopenharmony_ci 1788c2ecf20Sopenharmony_ci return soc_link_ret(rtd, ret); 1798c2ecf20Sopenharmony_ci} 1808c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(snd_soc_link_compr_set_params); 181