1*4882a593Smuzhiyun // SPDX-License-Identifier: GPL-2.0
2*4882a593Smuzhiyun //
3*4882a593Smuzhiyun // soc-link.c
4*4882a593Smuzhiyun //
5*4882a593Smuzhiyun // Copyright (C) 2019 Renesas Electronics Corp.
6*4882a593Smuzhiyun // Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
7*4882a593Smuzhiyun //
8*4882a593Smuzhiyun #include <sound/soc.h>
9*4882a593Smuzhiyun #include <sound/soc-link.h>
10*4882a593Smuzhiyun
11*4882a593Smuzhiyun #define soc_link_ret(rtd, ret) _soc_link_ret(rtd, __func__, ret)
_soc_link_ret(struct snd_soc_pcm_runtime * rtd,const char * func,int ret)12*4882a593Smuzhiyun static inline int _soc_link_ret(struct snd_soc_pcm_runtime *rtd,
13*4882a593Smuzhiyun const char *func, int ret)
14*4882a593Smuzhiyun {
15*4882a593Smuzhiyun /* Positive, Zero values are not errors */
16*4882a593Smuzhiyun if (ret >= 0)
17*4882a593Smuzhiyun return ret;
18*4882a593Smuzhiyun
19*4882a593Smuzhiyun /* Negative values might be errors */
20*4882a593Smuzhiyun switch (ret) {
21*4882a593Smuzhiyun case -EPROBE_DEFER:
22*4882a593Smuzhiyun case -ENOTSUPP:
23*4882a593Smuzhiyun break;
24*4882a593Smuzhiyun default:
25*4882a593Smuzhiyun dev_err(rtd->dev,
26*4882a593Smuzhiyun "ASoC: error at %s on %s: %d\n",
27*4882a593Smuzhiyun func, rtd->dai_link->name, ret);
28*4882a593Smuzhiyun }
29*4882a593Smuzhiyun
30*4882a593Smuzhiyun return ret;
31*4882a593Smuzhiyun }
32*4882a593Smuzhiyun
33*4882a593Smuzhiyun /*
34*4882a593Smuzhiyun * We might want to check substream by using list.
35*4882a593Smuzhiyun * In such case, we can update these macros.
36*4882a593Smuzhiyun */
37*4882a593Smuzhiyun #define soc_link_mark_push(rtd, substream, tgt) ((rtd)->mark_##tgt = substream)
38*4882a593Smuzhiyun #define soc_link_mark_pop(rtd, substream, tgt) ((rtd)->mark_##tgt = NULL)
39*4882a593Smuzhiyun #define soc_link_mark_match(rtd, substream, tgt) ((rtd)->mark_##tgt == substream)
40*4882a593Smuzhiyun
snd_soc_link_init(struct snd_soc_pcm_runtime * rtd)41*4882a593Smuzhiyun int snd_soc_link_init(struct snd_soc_pcm_runtime *rtd)
42*4882a593Smuzhiyun {
43*4882a593Smuzhiyun int ret = 0;
44*4882a593Smuzhiyun
45*4882a593Smuzhiyun if (rtd->dai_link->init)
46*4882a593Smuzhiyun ret = rtd->dai_link->init(rtd);
47*4882a593Smuzhiyun
48*4882a593Smuzhiyun return soc_link_ret(rtd, ret);
49*4882a593Smuzhiyun }
50*4882a593Smuzhiyun
snd_soc_link_exit(struct snd_soc_pcm_runtime * rtd)51*4882a593Smuzhiyun void snd_soc_link_exit(struct snd_soc_pcm_runtime *rtd)
52*4882a593Smuzhiyun {
53*4882a593Smuzhiyun if (rtd->dai_link->exit)
54*4882a593Smuzhiyun rtd->dai_link->exit(rtd);
55*4882a593Smuzhiyun }
56*4882a593Smuzhiyun
snd_soc_link_be_hw_params_fixup(struct snd_soc_pcm_runtime * rtd,struct snd_pcm_hw_params * params)57*4882a593Smuzhiyun int snd_soc_link_be_hw_params_fixup(struct snd_soc_pcm_runtime *rtd,
58*4882a593Smuzhiyun struct snd_pcm_hw_params *params)
59*4882a593Smuzhiyun {
60*4882a593Smuzhiyun int ret = 0;
61*4882a593Smuzhiyun
62*4882a593Smuzhiyun if (rtd->dai_link->be_hw_params_fixup)
63*4882a593Smuzhiyun ret = rtd->dai_link->be_hw_params_fixup(rtd, params);
64*4882a593Smuzhiyun
65*4882a593Smuzhiyun return soc_link_ret(rtd, ret);
66*4882a593Smuzhiyun }
67*4882a593Smuzhiyun
snd_soc_link_startup(struct snd_pcm_substream * substream)68*4882a593Smuzhiyun int snd_soc_link_startup(struct snd_pcm_substream *substream)
69*4882a593Smuzhiyun {
70*4882a593Smuzhiyun struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream);
71*4882a593Smuzhiyun int ret = 0;
72*4882a593Smuzhiyun
73*4882a593Smuzhiyun if (rtd->dai_link->ops &&
74*4882a593Smuzhiyun rtd->dai_link->ops->startup)
75*4882a593Smuzhiyun ret = rtd->dai_link->ops->startup(substream);
76*4882a593Smuzhiyun
77*4882a593Smuzhiyun /* mark substream if succeeded */
78*4882a593Smuzhiyun if (ret == 0)
79*4882a593Smuzhiyun soc_link_mark_push(rtd, substream, startup);
80*4882a593Smuzhiyun
81*4882a593Smuzhiyun return soc_link_ret(rtd, ret);
82*4882a593Smuzhiyun }
83*4882a593Smuzhiyun
snd_soc_link_shutdown(struct snd_pcm_substream * substream,int rollback)84*4882a593Smuzhiyun void snd_soc_link_shutdown(struct snd_pcm_substream *substream,
85*4882a593Smuzhiyun int rollback)
86*4882a593Smuzhiyun {
87*4882a593Smuzhiyun struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream);
88*4882a593Smuzhiyun
89*4882a593Smuzhiyun if (rollback && !soc_link_mark_match(rtd, substream, startup))
90*4882a593Smuzhiyun return;
91*4882a593Smuzhiyun
92*4882a593Smuzhiyun if (rtd->dai_link->ops &&
93*4882a593Smuzhiyun rtd->dai_link->ops->shutdown)
94*4882a593Smuzhiyun rtd->dai_link->ops->shutdown(substream);
95*4882a593Smuzhiyun
96*4882a593Smuzhiyun /* remove marked substream */
97*4882a593Smuzhiyun soc_link_mark_pop(rtd, substream, startup);
98*4882a593Smuzhiyun }
99*4882a593Smuzhiyun
snd_soc_link_prepare(struct snd_pcm_substream * substream)100*4882a593Smuzhiyun int snd_soc_link_prepare(struct snd_pcm_substream *substream)
101*4882a593Smuzhiyun {
102*4882a593Smuzhiyun struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream);
103*4882a593Smuzhiyun int ret = 0;
104*4882a593Smuzhiyun
105*4882a593Smuzhiyun if (rtd->dai_link->ops &&
106*4882a593Smuzhiyun rtd->dai_link->ops->prepare)
107*4882a593Smuzhiyun ret = rtd->dai_link->ops->prepare(substream);
108*4882a593Smuzhiyun
109*4882a593Smuzhiyun return soc_link_ret(rtd, ret);
110*4882a593Smuzhiyun }
111*4882a593Smuzhiyun
snd_soc_link_hw_params(struct snd_pcm_substream * substream,struct snd_pcm_hw_params * params)112*4882a593Smuzhiyun int snd_soc_link_hw_params(struct snd_pcm_substream *substream,
113*4882a593Smuzhiyun struct snd_pcm_hw_params *params)
114*4882a593Smuzhiyun {
115*4882a593Smuzhiyun struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream);
116*4882a593Smuzhiyun int ret = 0;
117*4882a593Smuzhiyun
118*4882a593Smuzhiyun if (rtd->dai_link->ops &&
119*4882a593Smuzhiyun rtd->dai_link->ops->hw_params)
120*4882a593Smuzhiyun ret = rtd->dai_link->ops->hw_params(substream, params);
121*4882a593Smuzhiyun
122*4882a593Smuzhiyun return soc_link_ret(rtd, ret);
123*4882a593Smuzhiyun }
124*4882a593Smuzhiyun
snd_soc_link_hw_free(struct snd_pcm_substream * substream)125*4882a593Smuzhiyun void snd_soc_link_hw_free(struct snd_pcm_substream *substream)
126*4882a593Smuzhiyun {
127*4882a593Smuzhiyun struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream);
128*4882a593Smuzhiyun
129*4882a593Smuzhiyun if (rtd->dai_link->ops &&
130*4882a593Smuzhiyun rtd->dai_link->ops->hw_free)
131*4882a593Smuzhiyun rtd->dai_link->ops->hw_free(substream);
132*4882a593Smuzhiyun }
133*4882a593Smuzhiyun
snd_soc_link_trigger(struct snd_pcm_substream * substream,int cmd)134*4882a593Smuzhiyun int snd_soc_link_trigger(struct snd_pcm_substream *substream, int cmd)
135*4882a593Smuzhiyun {
136*4882a593Smuzhiyun struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream);
137*4882a593Smuzhiyun int ret = 0;
138*4882a593Smuzhiyun
139*4882a593Smuzhiyun if (rtd->dai_link->ops &&
140*4882a593Smuzhiyun rtd->dai_link->ops->trigger)
141*4882a593Smuzhiyun ret = rtd->dai_link->ops->trigger(substream, cmd);
142*4882a593Smuzhiyun
143*4882a593Smuzhiyun return soc_link_ret(rtd, ret);
144*4882a593Smuzhiyun }
145*4882a593Smuzhiyun
snd_soc_link_compr_startup(struct snd_compr_stream * cstream)146*4882a593Smuzhiyun int snd_soc_link_compr_startup(struct snd_compr_stream *cstream)
147*4882a593Smuzhiyun {
148*4882a593Smuzhiyun struct snd_soc_pcm_runtime *rtd = cstream->private_data;
149*4882a593Smuzhiyun int ret = 0;
150*4882a593Smuzhiyun
151*4882a593Smuzhiyun if (rtd->dai_link->compr_ops &&
152*4882a593Smuzhiyun rtd->dai_link->compr_ops->startup)
153*4882a593Smuzhiyun ret = rtd->dai_link->compr_ops->startup(cstream);
154*4882a593Smuzhiyun
155*4882a593Smuzhiyun return soc_link_ret(rtd, ret);
156*4882a593Smuzhiyun }
157*4882a593Smuzhiyun EXPORT_SYMBOL_GPL(snd_soc_link_compr_startup);
158*4882a593Smuzhiyun
snd_soc_link_compr_shutdown(struct snd_compr_stream * cstream)159*4882a593Smuzhiyun void snd_soc_link_compr_shutdown(struct snd_compr_stream *cstream)
160*4882a593Smuzhiyun {
161*4882a593Smuzhiyun struct snd_soc_pcm_runtime *rtd = cstream->private_data;
162*4882a593Smuzhiyun
163*4882a593Smuzhiyun if (rtd->dai_link->compr_ops &&
164*4882a593Smuzhiyun rtd->dai_link->compr_ops->shutdown)
165*4882a593Smuzhiyun rtd->dai_link->compr_ops->shutdown(cstream);
166*4882a593Smuzhiyun }
167*4882a593Smuzhiyun EXPORT_SYMBOL_GPL(snd_soc_link_compr_shutdown);
168*4882a593Smuzhiyun
snd_soc_link_compr_set_params(struct snd_compr_stream * cstream)169*4882a593Smuzhiyun int snd_soc_link_compr_set_params(struct snd_compr_stream *cstream)
170*4882a593Smuzhiyun {
171*4882a593Smuzhiyun struct snd_soc_pcm_runtime *rtd = cstream->private_data;
172*4882a593Smuzhiyun int ret = 0;
173*4882a593Smuzhiyun
174*4882a593Smuzhiyun if (rtd->dai_link->compr_ops &&
175*4882a593Smuzhiyun rtd->dai_link->compr_ops->set_params)
176*4882a593Smuzhiyun ret = rtd->dai_link->compr_ops->set_params(cstream);
177*4882a593Smuzhiyun
178*4882a593Smuzhiyun return soc_link_ret(rtd, ret);
179*4882a593Smuzhiyun }
180*4882a593Smuzhiyun EXPORT_SYMBOL_GPL(snd_soc_link_compr_set_params);
181