ASoC: soc-dai: add snd_soc_dai_active()
[linux-2.6-block.git] / sound / soc / soc-dai.c
CommitLineData
06f6e1d4
KM
1// SPDX-License-Identifier: GPL-2.0
2//
3// soc-dai.c
4//
5// Copyright (C) 2019 Renesas Electronics Corp.
6// Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
7//
8
9#include <sound/soc.h>
10#include <sound/soc-dai.h>
11
aa7b8230
KM
12#define soc_dai_ret(dai, ret) _soc_dai_ret(dai, __func__, ret)
13static inline int _soc_dai_ret(struct snd_soc_dai *dai,
14 const char *func, int ret)
15{
16 switch (ret) {
17 case -EPROBE_DEFER:
18 case -ENOTSUPP:
19 case 0:
20 break;
21 default:
22 dev_err(dai->dev,
23 "ASoC: error at %s on %s: %d\n",
24 func, dai->name, ret);
25 }
26
27 return ret;
28}
29
06f6e1d4
KM
30/**
31 * snd_soc_dai_set_sysclk - configure DAI system or master clock.
32 * @dai: DAI
33 * @clk_id: DAI specific clock ID
34 * @freq: new clock frequency in Hz
35 * @dir: new clock direction - input/output.
36 *
37 * Configures the DAI master (MCLK) or system (SYSCLK) clocking.
38 */
39int snd_soc_dai_set_sysclk(struct snd_soc_dai *dai, int clk_id,
40 unsigned int freq, int dir)
41{
aa7b8230
KM
42 int ret;
43
479914ed
KM
44 if (dai->driver->ops &&
45 dai->driver->ops->set_sysclk)
aa7b8230
KM
46 ret = dai->driver->ops->set_sysclk(dai, clk_id, freq, dir);
47 else
48 ret = snd_soc_component_set_sysclk(dai->component, clk_id, 0,
49 freq, dir);
06f6e1d4 50
aa7b8230 51 return soc_dai_ret(dai, ret);
06f6e1d4
KM
52}
53EXPORT_SYMBOL_GPL(snd_soc_dai_set_sysclk);
54
55/**
56 * snd_soc_dai_set_clkdiv - configure DAI clock dividers.
57 * @dai: DAI
58 * @div_id: DAI specific clock divider ID
59 * @div: new clock divisor.
60 *
61 * Configures the clock dividers. This is used to derive the best DAI bit and
62 * frame clocks from the system or master clock. It's best to set the DAI bit
63 * and frame clocks as low as possible to save system power.
64 */
65int snd_soc_dai_set_clkdiv(struct snd_soc_dai *dai,
66 int div_id, int div)
67{
aa7b8230
KM
68 int ret = -EINVAL;
69
479914ed
KM
70 if (dai->driver->ops &&
71 dai->driver->ops->set_clkdiv)
aa7b8230
KM
72 ret = dai->driver->ops->set_clkdiv(dai, div_id, div);
73
74 return soc_dai_ret(dai, ret);
06f6e1d4
KM
75}
76EXPORT_SYMBOL_GPL(snd_soc_dai_set_clkdiv);
77
78/**
79 * snd_soc_dai_set_pll - configure DAI PLL.
80 * @dai: DAI
81 * @pll_id: DAI specific PLL ID
82 * @source: DAI specific source for the PLL
83 * @freq_in: PLL input clock frequency in Hz
84 * @freq_out: requested PLL output clock frequency in Hz
85 *
86 * Configures and enables PLL to generate output clock based on input clock.
87 */
88int snd_soc_dai_set_pll(struct snd_soc_dai *dai, int pll_id, int source,
89 unsigned int freq_in, unsigned int freq_out)
90{
aa7b8230
KM
91 int ret;
92
479914ed
KM
93 if (dai->driver->ops &&
94 dai->driver->ops->set_pll)
aa7b8230
KM
95 ret = dai->driver->ops->set_pll(dai, pll_id, source,
96 freq_in, freq_out);
97 else
98 ret = snd_soc_component_set_pll(dai->component, pll_id, source,
99 freq_in, freq_out);
06f6e1d4 100
aa7b8230 101 return soc_dai_ret(dai, ret);
06f6e1d4
KM
102}
103EXPORT_SYMBOL_GPL(snd_soc_dai_set_pll);
104
105/**
106 * snd_soc_dai_set_bclk_ratio - configure BCLK to sample rate ratio.
107 * @dai: DAI
108 * @ratio: Ratio of BCLK to Sample rate.
109 *
110 * Configures the DAI for a preset BCLK to sample rate ratio.
111 */
112int snd_soc_dai_set_bclk_ratio(struct snd_soc_dai *dai, unsigned int ratio)
113{
aa7b8230
KM
114 int ret = -EINVAL;
115
479914ed
KM
116 if (dai->driver->ops &&
117 dai->driver->ops->set_bclk_ratio)
aa7b8230
KM
118 ret = dai->driver->ops->set_bclk_ratio(dai, ratio);
119
120 return soc_dai_ret(dai, ret);
06f6e1d4
KM
121}
122EXPORT_SYMBOL_GPL(snd_soc_dai_set_bclk_ratio);
123
124/**
125 * snd_soc_dai_set_fmt - configure DAI hardware audio format.
126 * @dai: DAI
127 * @fmt: SND_SOC_DAIFMT_* format value.
128 *
129 * Configures the DAI hardware format and clocking.
130 */
131int snd_soc_dai_set_fmt(struct snd_soc_dai *dai, unsigned int fmt)
132{
aa7b8230
KM
133 int ret = -ENOTSUPP;
134
479914ed
KM
135 if (dai->driver->ops &&
136 dai->driver->ops->set_fmt)
aa7b8230
KM
137 ret = dai->driver->ops->set_fmt(dai, fmt);
138
139 return soc_dai_ret(dai, ret);
06f6e1d4
KM
140}
141EXPORT_SYMBOL_GPL(snd_soc_dai_set_fmt);
142
143/**
144 * snd_soc_xlate_tdm_slot - generate tx/rx slot mask.
145 * @slots: Number of slots in use.
146 * @tx_mask: bitmask representing active TX slots.
147 * @rx_mask: bitmask representing active RX slots.
148 *
149 * Generates the TDM tx and rx slot default masks for DAI.
150 */
151static int snd_soc_xlate_tdm_slot_mask(unsigned int slots,
152 unsigned int *tx_mask,
153 unsigned int *rx_mask)
154{
155 if (*tx_mask || *rx_mask)
156 return 0;
157
158 if (!slots)
159 return -EINVAL;
160
161 *tx_mask = (1 << slots) - 1;
162 *rx_mask = (1 << slots) - 1;
163
164 return 0;
165}
166
167/**
168 * snd_soc_dai_set_tdm_slot() - Configures a DAI for TDM operation
169 * @dai: The DAI to configure
170 * @tx_mask: bitmask representing active TX slots.
171 * @rx_mask: bitmask representing active RX slots.
172 * @slots: Number of slots in use.
173 * @slot_width: Width in bits for each slot.
174 *
175 * This function configures the specified DAI for TDM operation. @slot contains
176 * the total number of slots of the TDM stream and @slot_with the width of each
177 * slot in bit clock cycles. @tx_mask and @rx_mask are bitmasks specifying the
178 * active slots of the TDM stream for the specified DAI, i.e. which slots the
179 * DAI should write to or read from. If a bit is set the corresponding slot is
180 * active, if a bit is cleared the corresponding slot is inactive. Bit 0 maps to
181 * the first slot, bit 1 to the second slot and so on. The first active slot
182 * maps to the first channel of the DAI, the second active slot to the second
183 * channel and so on.
184 *
185 * TDM mode can be disabled by passing 0 for @slots. In this case @tx_mask,
186 * @rx_mask and @slot_width will be ignored.
187 *
188 * Returns 0 on success, a negative error code otherwise.
189 */
190int snd_soc_dai_set_tdm_slot(struct snd_soc_dai *dai,
191 unsigned int tx_mask, unsigned int rx_mask,
192 int slots, int slot_width)
193{
aa7b8230
KM
194 int ret = -ENOTSUPP;
195
479914ed
KM
196 if (dai->driver->ops &&
197 dai->driver->ops->xlate_tdm_slot_mask)
06f6e1d4
KM
198 dai->driver->ops->xlate_tdm_slot_mask(slots,
199 &tx_mask, &rx_mask);
200 else
201 snd_soc_xlate_tdm_slot_mask(slots, &tx_mask, &rx_mask);
202
203 dai->tx_mask = tx_mask;
204 dai->rx_mask = rx_mask;
205
479914ed
KM
206 if (dai->driver->ops &&
207 dai->driver->ops->set_tdm_slot)
aa7b8230 208 ret = dai->driver->ops->set_tdm_slot(dai, tx_mask, rx_mask,
06f6e1d4 209 slots, slot_width);
aa7b8230 210 return soc_dai_ret(dai, ret);
06f6e1d4
KM
211}
212EXPORT_SYMBOL_GPL(snd_soc_dai_set_tdm_slot);
213
214/**
215 * snd_soc_dai_set_channel_map - configure DAI audio channel map
216 * @dai: DAI
217 * @tx_num: how many TX channels
218 * @tx_slot: pointer to an array which imply the TX slot number channel
219 * 0~num-1 uses
220 * @rx_num: how many RX channels
221 * @rx_slot: pointer to an array which imply the RX slot number channel
222 * 0~num-1 uses
223 *
224 * configure the relationship between channel number and TDM slot number.
225 */
226int snd_soc_dai_set_channel_map(struct snd_soc_dai *dai,
227 unsigned int tx_num, unsigned int *tx_slot,
228 unsigned int rx_num, unsigned int *rx_slot)
229{
aa7b8230
KM
230 int ret = -ENOTSUPP;
231
479914ed
KM
232 if (dai->driver->ops &&
233 dai->driver->ops->set_channel_map)
aa7b8230
KM
234 ret = dai->driver->ops->set_channel_map(dai, tx_num, tx_slot,
235 rx_num, rx_slot);
236 return soc_dai_ret(dai, ret);
06f6e1d4
KM
237}
238EXPORT_SYMBOL_GPL(snd_soc_dai_set_channel_map);
239
240/**
241 * snd_soc_dai_get_channel_map - Get DAI audio channel map
242 * @dai: DAI
243 * @tx_num: how many TX channels
244 * @tx_slot: pointer to an array which imply the TX slot number channel
245 * 0~num-1 uses
246 * @rx_num: how many RX channels
247 * @rx_slot: pointer to an array which imply the RX slot number channel
248 * 0~num-1 uses
249 */
250int snd_soc_dai_get_channel_map(struct snd_soc_dai *dai,
251 unsigned int *tx_num, unsigned int *tx_slot,
252 unsigned int *rx_num, unsigned int *rx_slot)
253{
aa7b8230
KM
254 int ret = -ENOTSUPP;
255
479914ed
KM
256 if (dai->driver->ops &&
257 dai->driver->ops->get_channel_map)
aa7b8230
KM
258 ret = dai->driver->ops->get_channel_map(dai, tx_num, tx_slot,
259 rx_num, rx_slot);
260 return soc_dai_ret(dai, ret);
06f6e1d4
KM
261}
262EXPORT_SYMBOL_GPL(snd_soc_dai_get_channel_map);
263
264/**
265 * snd_soc_dai_set_tristate - configure DAI system or master clock.
266 * @dai: DAI
267 * @tristate: tristate enable
268 *
269 * Tristates the DAI so that others can use it.
270 */
271int snd_soc_dai_set_tristate(struct snd_soc_dai *dai, int tristate)
272{
aa7b8230
KM
273 int ret = -EINVAL;
274
479914ed
KM
275 if (dai->driver->ops &&
276 dai->driver->ops->set_tristate)
aa7b8230
KM
277 ret = dai->driver->ops->set_tristate(dai, tristate);
278
279 return soc_dai_ret(dai, ret);
06f6e1d4
KM
280}
281EXPORT_SYMBOL_GPL(snd_soc_dai_set_tristate);
282
283/**
284 * snd_soc_dai_digital_mute - configure DAI system or master clock.
285 * @dai: DAI
286 * @mute: mute enable
287 * @direction: stream to mute
288 *
289 * Mutes the DAI DAC.
290 */
291int snd_soc_dai_digital_mute(struct snd_soc_dai *dai, int mute,
292 int direction)
293{
aa7b8230
KM
294 int ret = -ENOTSUPP;
295
479914ed
KM
296 if (dai->driver->ops &&
297 dai->driver->ops->mute_stream)
aa7b8230 298 ret = dai->driver->ops->mute_stream(dai, mute, direction);
06f6e1d4 299 else if (direction == SNDRV_PCM_STREAM_PLAYBACK &&
479914ed 300 dai->driver->ops &&
06f6e1d4 301 dai->driver->ops->digital_mute)
aa7b8230
KM
302 ret = dai->driver->ops->digital_mute(dai, mute);
303
304 return soc_dai_ret(dai, ret);
06f6e1d4
KM
305}
306EXPORT_SYMBOL_GPL(snd_soc_dai_digital_mute);
aa6166c2
KM
307
308int snd_soc_dai_hw_params(struct snd_soc_dai *dai,
309 struct snd_pcm_substream *substream,
310 struct snd_pcm_hw_params *params)
311{
312 struct snd_soc_pcm_runtime *rtd = substream->private_data;
aa7b8230 313 int ret = 0;
aa6166c2
KM
314
315 /* perform any topology hw_params fixups before DAI */
316 if (rtd->dai_link->be_hw_params_fixup) {
317 ret = rtd->dai_link->be_hw_params_fixup(rtd, params);
aa7b8230
KM
318 if (ret < 0)
319 goto end;
aa6166c2
KM
320 }
321
479914ed
KM
322 if (dai->driver->ops &&
323 dai->driver->ops->hw_params)
aa6166c2 324 ret = dai->driver->ops->hw_params(substream, params, dai);
aa7b8230
KM
325end:
326 return soc_dai_ret(dai, ret);
aa6166c2 327}
846faaed
KM
328
329void snd_soc_dai_hw_free(struct snd_soc_dai *dai,
330 struct snd_pcm_substream *substream)
331{
479914ed
KM
332 if (dai->driver->ops &&
333 dai->driver->ops->hw_free)
846faaed
KM
334 dai->driver->ops->hw_free(substream, dai);
335}
5a52a045
KM
336
337int snd_soc_dai_startup(struct snd_soc_dai *dai,
338 struct snd_pcm_substream *substream)
339{
340 int ret = 0;
341
479914ed
KM
342 if (dai->driver->ops &&
343 dai->driver->ops->startup)
5a52a045
KM
344 ret = dai->driver->ops->startup(substream, dai);
345
aa7b8230 346 return soc_dai_ret(dai, ret);
5a52a045 347}
330fcb51
KM
348
349void snd_soc_dai_shutdown(struct snd_soc_dai *dai,
350 struct snd_pcm_substream *substream)
351{
479914ed
KM
352 if (dai->driver->ops &&
353 dai->driver->ops->shutdown)
330fcb51
KM
354 dai->driver->ops->shutdown(substream, dai);
355}
4beb8e10 356
1dea80d4
KM
357snd_pcm_sframes_t snd_soc_dai_delay(struct snd_soc_dai *dai,
358 struct snd_pcm_substream *substream)
359{
360 int delay = 0;
361
479914ed
KM
362 if (dai->driver->ops &&
363 dai->driver->ops->delay)
1dea80d4
KM
364 delay = dai->driver->ops->delay(substream, dai);
365
366 return delay;
367}
e0f22622 368
b423c420
KM
369int snd_soc_dai_compress_new(struct snd_soc_dai *dai,
370 struct snd_soc_pcm_runtime *rtd, int num)
371{
aa7b8230 372 int ret = -ENOTSUPP;
b423c420 373 if (dai->driver->compress_new)
aa7b8230
KM
374 ret = dai->driver->compress_new(rtd, num);
375 return soc_dai_ret(dai, ret);
b423c420 376}
467fece8
KM
377
378/*
379 * snd_soc_dai_stream_valid() - check if a DAI supports the given stream
380 *
381 * Returns true if the DAI supports the indicated stream type.
382 */
383bool snd_soc_dai_stream_valid(struct snd_soc_dai *dai, int dir)
384{
acf253c1 385 struct snd_soc_pcm_stream *stream = snd_soc_dai_get_pcm_stream(dai, dir);
467fece8
KM
386
387 /* If the codec specifies any channels at all, it supports the stream */
388 return stream->channels_min;
389}
0b73ba55 390
dc829106
KM
391void snd_soc_dai_action(struct snd_soc_dai *dai,
392 int stream, int action)
393{
394 dai->stream_active[stream] += action;
395 dai->active += action;
396 dai->component->active += action;
397}
398EXPORT_SYMBOL_GPL(snd_soc_dai_action);
399
efffd9b3
KM
400int snd_soc_dai_active(struct snd_soc_dai *dai)
401{
402 int stream, active;
403
404 active = 0;
405 for_each_pcm_streams(stream)
406 active += dai->stream_active[stream];
407
408 return active;
409}
410EXPORT_SYMBOL_GPL(snd_soc_dai_active);
411
51801aea
KM
412int snd_soc_pcm_dai_probe(struct snd_soc_pcm_runtime *rtd, int order)
413{
414 struct snd_soc_dai *dai;
415 int i;
416
417 for_each_rtd_dais(rtd, i, dai) {
418 if (dai->driver->probe_order != order)
419 continue;
420
421 if (dai->driver->probe) {
422 int ret = dai->driver->probe(dai);
423
424 if (ret < 0)
425 return soc_dai_ret(dai, ret);
426 }
427
428 dai->probed = 1;
429 }
430
431 return 0;
432}
433
7eaa313b
KM
434int snd_soc_pcm_dai_remove(struct snd_soc_pcm_runtime *rtd, int order)
435{
436 struct snd_soc_dai *dai;
437 int i, r, ret = 0;
438
439 for_each_rtd_dais(rtd, i, dai) {
440 if (dai->driver->remove_order != order)
441 continue;
442
443 if (dai->probed &&
444 dai->driver->remove) {
445 r = dai->driver->remove(dai);
446 if (r < 0)
447 ret = r; /* use last error */
448 }
449
450 dai->probed = 0;
451 }
452
453 return ret;
454}
455
0b73ba55
KM
456int snd_soc_pcm_dai_new(struct snd_soc_pcm_runtime *rtd)
457{
458 struct snd_soc_dai *dai;
459 int i, ret = 0;
460
461 for_each_rtd_dais(rtd, i, dai) {
462 if (dai->driver->pcm_new) {
463 ret = dai->driver->pcm_new(rtd, dai);
464 if (ret < 0)
465 return soc_dai_ret(dai, ret);
466 }
467 }
468
469 return 0;
470}
d108c7fd
KM
471
472int snd_soc_pcm_dai_prepare(struct snd_pcm_substream *substream)
473{
474 struct snd_soc_pcm_runtime *rtd = substream->private_data;
475 struct snd_soc_dai *dai;
476 int i, ret;
477
478 for_each_rtd_dais(rtd, i, dai) {
479 if (dai->driver->ops &&
480 dai->driver->ops->prepare) {
481 ret = dai->driver->ops->prepare(substream, dai);
482 if (ret < 0)
483 return soc_dai_ret(dai, ret);
484 }
485 }
486
487 return 0;
488}
42f2472d
KM
489
490int snd_soc_pcm_dai_trigger(struct snd_pcm_substream *substream,
491 int cmd)
492{
493 struct snd_soc_pcm_runtime *rtd = substream->private_data;
494 struct snd_soc_dai *dai;
495 int i, ret;
496
497 for_each_rtd_dais(rtd, i, dai) {
498 if (dai->driver->ops &&
499 dai->driver->ops->trigger) {
500 ret = dai->driver->ops->trigger(substream, cmd, dai);
501 if (ret < 0)
502 return soc_dai_ret(dai, ret);
503 }
504 }
505
506 return 0;
507}
30819358
KM
508
509int snd_soc_pcm_dai_bespoke_trigger(struct snd_pcm_substream *substream,
510 int cmd)
511{
512 struct snd_soc_pcm_runtime *rtd = substream->private_data;
513 struct snd_soc_dai *dai;
514 int i, ret;
515
516 for_each_rtd_dais(rtd, i, dai) {
517 if (dai->driver->ops &&
518 dai->driver->ops->bespoke_trigger) {
519 ret = dai->driver->ops->bespoke_trigger(substream,
520 cmd, dai);
521 if (ret < 0)
522 return soc_dai_ret(dai, ret);
523 }
524 }
525
526 return 0;
527}
b5ae4cce
KM
528
529int snd_soc_dai_compr_startup(struct snd_soc_dai *dai,
530 struct snd_compr_stream *cstream)
531{
532 int ret = 0;
533
534 if (dai->driver->cops &&
535 dai->driver->cops->startup)
536 ret = dai->driver->cops->startup(cstream, dai);
537
538 return soc_dai_ret(dai, ret);
539}
540EXPORT_SYMBOL_GPL(snd_soc_dai_compr_startup);
2b25f81d
KM
541
542void snd_soc_dai_compr_shutdown(struct snd_soc_dai *dai,
543 struct snd_compr_stream *cstream)
544{
545 if (dai->driver->cops &&
546 dai->driver->cops->shutdown)
547 dai->driver->cops->shutdown(cstream, dai);
548}
549EXPORT_SYMBOL_GPL(snd_soc_dai_compr_shutdown);
eb08411b
KM
550
551int snd_soc_dai_compr_trigger(struct snd_soc_dai *dai,
552 struct snd_compr_stream *cstream, int cmd)
553{
554 int ret = 0;
555
556 if (dai->driver->cops &&
557 dai->driver->cops->trigger)
558 ret = dai->driver->cops->trigger(cstream, cmd, dai);
559
560 return soc_dai_ret(dai, ret);
561}
562EXPORT_SYMBOL_GPL(snd_soc_dai_compr_trigger);
8dfedafb
KM
563
564int snd_soc_dai_compr_set_params(struct snd_soc_dai *dai,
565 struct snd_compr_stream *cstream,
566 struct snd_compr_params *params)
567{
568 int ret = 0;
569
570 if (dai->driver->cops &&
571 dai->driver->cops->set_params)
572 ret = dai->driver->cops->set_params(cstream, params, dai);
573
574 return soc_dai_ret(dai, ret);
575}
576EXPORT_SYMBOL_GPL(snd_soc_dai_compr_set_params);
adbef543
KM
577
578int snd_soc_dai_compr_get_params(struct snd_soc_dai *dai,
579 struct snd_compr_stream *cstream,
580 struct snd_codec *params)
581{
582 int ret = 0;
583
584 if (dai->driver->cops &&
585 dai->driver->cops->get_params)
586 ret = dai->driver->cops->get_params(cstream, params, dai);
587
588 return soc_dai_ret(dai, ret);
589}
590EXPORT_SYMBOL_GPL(snd_soc_dai_compr_get_params);
53294353
KM
591
592int snd_soc_dai_compr_ack(struct snd_soc_dai *dai,
593 struct snd_compr_stream *cstream,
594 size_t bytes)
595{
596 int ret = 0;
597
598 if (dai->driver->cops &&
599 dai->driver->cops->ack)
600 ret = dai->driver->cops->ack(cstream, bytes, dai);
601
602 return soc_dai_ret(dai, ret);
603}
604EXPORT_SYMBOL_GPL(snd_soc_dai_compr_ack);
ed38cc59
KM
605
606int snd_soc_dai_compr_pointer(struct snd_soc_dai *dai,
607 struct snd_compr_stream *cstream,
608 struct snd_compr_tstamp *tstamp)
609{
610 int ret = 0;
611
612 if (dai->driver->cops &&
613 dai->driver->cops->pointer)
614 ret = dai->driver->cops->pointer(cstream, tstamp, dai);
615
616 return soc_dai_ret(dai, ret);
617}
618EXPORT_SYMBOL_GPL(snd_soc_dai_compr_pointer);
88b3a7df
KM
619
620int snd_soc_dai_compr_set_metadata(struct snd_soc_dai *dai,
621 struct snd_compr_stream *cstream,
622 struct snd_compr_metadata *metadata)
623{
624 int ret = 0;
625
626 if (dai->driver->cops &&
627 dai->driver->cops->set_metadata)
628 ret = dai->driver->cops->set_metadata(cstream, metadata, dai);
629
630 return soc_dai_ret(dai, ret);
631}
632EXPORT_SYMBOL_GPL(snd_soc_dai_compr_set_metadata);
94d72819
KM
633
634int snd_soc_dai_compr_get_metadata(struct snd_soc_dai *dai,
635 struct snd_compr_stream *cstream,
636 struct snd_compr_metadata *metadata)
637{
638 int ret = 0;
639
640 if (dai->driver->cops &&
641 dai->driver->cops->get_metadata)
642 ret = dai->driver->cops->get_metadata(cstream, metadata, dai);
643
644 return soc_dai_ret(dai, ret);
645}
646EXPORT_SYMBOL_GPL(snd_soc_dai_compr_get_metadata);