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