1 // SPDX-License-Identifier: GPL-2.0 1 // SPDX-License-Identifier: GPL-2.0 2 // 2 // 3 // soc-link.c 3 // soc-link.c 4 // 4 // 5 // Copyright (C) 2019 Renesas Electronics Corp 5 // Copyright (C) 2019 Renesas Electronics Corp. 6 // Kuninori Morimoto <kuninori.morimoto.gx@ren 6 // Kuninori Morimoto <kuninori.morimoto.gx@renesas.com> 7 // 7 // 8 #include <sound/soc.h> 8 #include <sound/soc.h> 9 #include <sound/soc-link.h> 9 #include <sound/soc-link.h> 10 10 11 #define soc_link_ret(rtd, ret) _soc_link_ret(r 11 #define soc_link_ret(rtd, ret) _soc_link_ret(rtd, __func__, ret) 12 static inline int _soc_link_ret(struct snd_soc 12 static inline int _soc_link_ret(struct snd_soc_pcm_runtime *rtd, 13 const char *fu 13 const char *func, int ret) 14 { 14 { 15 /* Positive, Zero values are not error 15 /* Positive, Zero values are not errors */ 16 if (ret >= 0) 16 if (ret >= 0) 17 return ret; 17 return ret; 18 18 19 /* Negative values might be errors */ 19 /* Negative values might be errors */ 20 switch (ret) { 20 switch (ret) { 21 case -EPROBE_DEFER: 21 case -EPROBE_DEFER: 22 case -ENOTSUPP: 22 case -ENOTSUPP: 23 break; 23 break; 24 default: 24 default: 25 dev_err(rtd->dev, 25 dev_err(rtd->dev, 26 "ASoC: error at %s on 26 "ASoC: error at %s on %s: %d\n", 27 func, rtd->dai_link->n 27 func, rtd->dai_link->name, ret); 28 } 28 } 29 29 30 return ret; 30 return ret; 31 } 31 } 32 32 33 /* << 34 * We might want to check substream by using l << 35 * In such case, we can update these macros. << 36 */ << 37 #define soc_link_mark_push(rtd, substream, tgt << 38 #define soc_link_mark_pop(rtd, substream, tgt) << 39 #define soc_link_mark_match(rtd, substream, tg << 40 << 41 int snd_soc_link_init(struct snd_soc_pcm_runti 33 int snd_soc_link_init(struct snd_soc_pcm_runtime *rtd) 42 { 34 { 43 int ret = 0; 35 int ret = 0; 44 36 45 if (rtd->dai_link->init) 37 if (rtd->dai_link->init) 46 ret = rtd->dai_link->init(rtd) 38 ret = rtd->dai_link->init(rtd); 47 39 48 return soc_link_ret(rtd, ret); 40 return soc_link_ret(rtd, ret); 49 } 41 } 50 42 51 void snd_soc_link_exit(struct snd_soc_pcm_runt << 52 { << 53 if (rtd->dai_link->exit) << 54 rtd->dai_link->exit(rtd); << 55 } << 56 << 57 int snd_soc_link_be_hw_params_fixup(struct snd 43 int snd_soc_link_be_hw_params_fixup(struct snd_soc_pcm_runtime *rtd, 58 struct snd 44 struct snd_pcm_hw_params *params) 59 { 45 { 60 int ret = 0; 46 int ret = 0; 61 47 62 if (rtd->dai_link->be_hw_params_fixup) 48 if (rtd->dai_link->be_hw_params_fixup) 63 ret = rtd->dai_link->be_hw_par 49 ret = rtd->dai_link->be_hw_params_fixup(rtd, params); 64 50 65 return soc_link_ret(rtd, ret); 51 return soc_link_ret(rtd, ret); 66 } 52 } 67 53 68 int snd_soc_link_startup(struct snd_pcm_substr 54 int snd_soc_link_startup(struct snd_pcm_substream *substream) 69 { 55 { 70 struct snd_soc_pcm_runtime *rtd = snd_ !! 56 struct snd_soc_pcm_runtime *rtd = substream->private_data; 71 int ret = 0; 57 int ret = 0; 72 58 73 if (rtd->dai_link->ops && 59 if (rtd->dai_link->ops && 74 rtd->dai_link->ops->startup) 60 rtd->dai_link->ops->startup) 75 ret = rtd->dai_link->ops->star 61 ret = rtd->dai_link->ops->startup(substream); 76 62 77 /* mark substream if succeeded */ << 78 if (ret == 0) << 79 soc_link_mark_push(rtd, substr << 80 << 81 return soc_link_ret(rtd, ret); 63 return soc_link_ret(rtd, ret); 82 } 64 } 83 65 84 void snd_soc_link_shutdown(struct snd_pcm_subs !! 66 void snd_soc_link_shutdown(struct snd_pcm_substream *substream) 85 int rollback) << 86 { 67 { 87 struct snd_soc_pcm_runtime *rtd = snd_ !! 68 struct snd_soc_pcm_runtime *rtd = substream->private_data; 88 << 89 if (rollback && !soc_link_mark_match(r << 90 return; << 91 69 92 if (rtd->dai_link->ops && 70 if (rtd->dai_link->ops && 93 rtd->dai_link->ops->shutdown) 71 rtd->dai_link->ops->shutdown) 94 rtd->dai_link->ops->shutdown(s 72 rtd->dai_link->ops->shutdown(substream); 95 << 96 /* remove marked substream */ << 97 soc_link_mark_pop(rtd, substream, star << 98 } 73 } 99 74 100 int snd_soc_link_prepare(struct snd_pcm_substr 75 int snd_soc_link_prepare(struct snd_pcm_substream *substream) 101 { 76 { 102 struct snd_soc_pcm_runtime *rtd = snd_ !! 77 struct snd_soc_pcm_runtime *rtd = substream->private_data; 103 int ret = 0; 78 int ret = 0; 104 79 105 if (rtd->dai_link->ops && 80 if (rtd->dai_link->ops && 106 rtd->dai_link->ops->prepare) 81 rtd->dai_link->ops->prepare) 107 ret = rtd->dai_link->ops->prep 82 ret = rtd->dai_link->ops->prepare(substream); 108 83 109 return soc_link_ret(rtd, ret); 84 return soc_link_ret(rtd, ret); 110 } 85 } 111 86 112 int snd_soc_link_hw_params(struct snd_pcm_subs 87 int snd_soc_link_hw_params(struct snd_pcm_substream *substream, 113 struct snd_pcm_hw_p 88 struct snd_pcm_hw_params *params) 114 { 89 { 115 struct snd_soc_pcm_runtime *rtd = snd_ !! 90 struct snd_soc_pcm_runtime *rtd = substream->private_data; 116 int ret = 0; 91 int ret = 0; 117 92 118 if (rtd->dai_link->ops && 93 if (rtd->dai_link->ops && 119 rtd->dai_link->ops->hw_params) 94 rtd->dai_link->ops->hw_params) 120 ret = rtd->dai_link->ops->hw_p 95 ret = rtd->dai_link->ops->hw_params(substream, params); 121 96 122 /* mark substream if succeeded */ << 123 if (ret == 0) << 124 soc_link_mark_push(rtd, substr << 125 << 126 return soc_link_ret(rtd, ret); 97 return soc_link_ret(rtd, ret); 127 } 98 } 128 99 129 void snd_soc_link_hw_free(struct snd_pcm_subst !! 100 void snd_soc_link_hw_free(struct snd_pcm_substream *substream) 130 { 101 { 131 struct snd_soc_pcm_runtime *rtd = snd_ !! 102 struct snd_soc_pcm_runtime *rtd = substream->private_data; 132 << 133 if (rollback && !soc_link_mark_match(r << 134 return; << 135 103 136 if (rtd->dai_link->ops && 104 if (rtd->dai_link->ops && 137 rtd->dai_link->ops->hw_free) 105 rtd->dai_link->ops->hw_free) 138 rtd->dai_link->ops->hw_free(su 106 rtd->dai_link->ops->hw_free(substream); 139 << 140 /* remove marked substream */ << 141 soc_link_mark_pop(rtd, substream, hw_p << 142 } 107 } 143 108 144 static int soc_link_trigger(struct snd_pcm_sub !! 109 int snd_soc_link_trigger(struct snd_pcm_substream *substream, int cmd) 145 { 110 { 146 struct snd_soc_pcm_runtime *rtd = snd_ !! 111 struct snd_soc_pcm_runtime *rtd = substream->private_data; 147 int ret = 0; 112 int ret = 0; 148 113 149 if (rtd->dai_link->ops && 114 if (rtd->dai_link->ops && 150 rtd->dai_link->ops->trigger) 115 rtd->dai_link->ops->trigger) 151 ret = rtd->dai_link->ops->trig 116 ret = rtd->dai_link->ops->trigger(substream, cmd); 152 117 153 return soc_link_ret(rtd, ret); 118 return soc_link_ret(rtd, ret); 154 } 119 } 155 120 156 int snd_soc_link_trigger(struct snd_pcm_substr << 157 int rollback) << 158 { << 159 struct snd_soc_pcm_runtime *rtd = snd_ << 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(substre << 167 if (ret < 0) << 168 break; << 169 soc_link_mark_push(rtd, substr << 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 << 175 break; << 176 << 177 ret = soc_link_trigger(substre << 178 soc_link_mark_pop(rtd, substre << 179 } << 180 << 181 return ret; << 182 } << 183 << 184 int snd_soc_link_compr_startup(struct snd_comp 121 int snd_soc_link_compr_startup(struct snd_compr_stream *cstream) 185 { 122 { 186 struct snd_soc_pcm_runtime *rtd = cstr 123 struct snd_soc_pcm_runtime *rtd = cstream->private_data; 187 int ret = 0; 124 int ret = 0; 188 125 189 if (rtd->dai_link->compr_ops && 126 if (rtd->dai_link->compr_ops && 190 rtd->dai_link->compr_ops->startup) 127 rtd->dai_link->compr_ops->startup) 191 ret = rtd->dai_link->compr_ops 128 ret = rtd->dai_link->compr_ops->startup(cstream); 192 129 193 if (ret == 0) << 194 soc_link_mark_push(rtd, cstrea << 195 << 196 return soc_link_ret(rtd, ret); 130 return soc_link_ret(rtd, ret); 197 } 131 } 198 EXPORT_SYMBOL_GPL(snd_soc_link_compr_startup); 132 EXPORT_SYMBOL_GPL(snd_soc_link_compr_startup); 199 133 200 void snd_soc_link_compr_shutdown(struct snd_co !! 134 void snd_soc_link_compr_shutdown(struct snd_compr_stream *cstream) 201 int rollback) << 202 { 135 { 203 struct snd_soc_pcm_runtime *rtd = cstr 136 struct snd_soc_pcm_runtime *rtd = cstream->private_data; 204 137 205 if (rollback && !soc_link_mark_match(r << 206 return; << 207 << 208 if (rtd->dai_link->compr_ops && 138 if (rtd->dai_link->compr_ops && 209 rtd->dai_link->compr_ops->shutdown 139 rtd->dai_link->compr_ops->shutdown) 210 rtd->dai_link->compr_ops->shut 140 rtd->dai_link->compr_ops->shutdown(cstream); 211 << 212 soc_link_mark_pop(rtd, cstream, compr_ << 213 } 141 } 214 EXPORT_SYMBOL_GPL(snd_soc_link_compr_shutdown) 142 EXPORT_SYMBOL_GPL(snd_soc_link_compr_shutdown); 215 143 216 int snd_soc_link_compr_set_params(struct snd_c 144 int snd_soc_link_compr_set_params(struct snd_compr_stream *cstream) 217 { 145 { 218 struct snd_soc_pcm_runtime *rtd = cstr 146 struct snd_soc_pcm_runtime *rtd = cstream->private_data; 219 int ret = 0; 147 int ret = 0; 220 148 221 if (rtd->dai_link->compr_ops && 149 if (rtd->dai_link->compr_ops && 222 rtd->dai_link->compr_ops->set_para 150 rtd->dai_link->compr_ops->set_params) 223 ret = rtd->dai_link->compr_ops 151 ret = rtd->dai_link->compr_ops->set_params(cstream); 224 152 225 return soc_link_ret(rtd, ret); 153 return soc_link_ret(rtd, ret); 226 } 154 } 227 EXPORT_SYMBOL_GPL(snd_soc_link_compr_set_param 155 EXPORT_SYMBOL_GPL(snd_soc_link_compr_set_params); 228 156
Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.