0001
0002
0003
0004
0005
0006
0007
0008
0009 #include <sound/soc.h>
0010 #include <sound/soc-dai.h>
0011 #include <sound/soc-link.h>
0012
0013 #define soc_dai_ret(dai, ret) _soc_dai_ret(dai, __func__, ret)
0014 static inline int _soc_dai_ret(struct snd_soc_dai *dai,
0015 const char *func, int ret)
0016 {
0017
0018 if (ret >= 0)
0019 return ret;
0020
0021
0022 switch (ret) {
0023 case -EPROBE_DEFER:
0024 case -ENOTSUPP:
0025 break;
0026 default:
0027 dev_err(dai->dev,
0028 "ASoC: error at %s on %s: %d\n",
0029 func, dai->name, ret);
0030 }
0031
0032 return ret;
0033 }
0034
0035
0036
0037
0038
0039 #define soc_dai_mark_push(dai, substream, tgt) ((dai)->mark_##tgt = substream)
0040 #define soc_dai_mark_pop(dai, substream, tgt) ((dai)->mark_##tgt = NULL)
0041 #define soc_dai_mark_match(dai, substream, tgt) ((dai)->mark_##tgt == substream)
0042
0043
0044
0045
0046
0047
0048
0049
0050
0051
0052 int snd_soc_dai_set_sysclk(struct snd_soc_dai *dai, int clk_id,
0053 unsigned int freq, int dir)
0054 {
0055 int ret;
0056
0057 if (dai->driver->ops &&
0058 dai->driver->ops->set_sysclk)
0059 ret = dai->driver->ops->set_sysclk(dai, clk_id, freq, dir);
0060 else
0061 ret = snd_soc_component_set_sysclk(dai->component, clk_id, 0,
0062 freq, dir);
0063
0064 return soc_dai_ret(dai, ret);
0065 }
0066 EXPORT_SYMBOL_GPL(snd_soc_dai_set_sysclk);
0067
0068
0069
0070
0071
0072
0073
0074
0075
0076
0077
0078 int snd_soc_dai_set_clkdiv(struct snd_soc_dai *dai,
0079 int div_id, int div)
0080 {
0081 int ret = -EINVAL;
0082
0083 if (dai->driver->ops &&
0084 dai->driver->ops->set_clkdiv)
0085 ret = dai->driver->ops->set_clkdiv(dai, div_id, div);
0086
0087 return soc_dai_ret(dai, ret);
0088 }
0089 EXPORT_SYMBOL_GPL(snd_soc_dai_set_clkdiv);
0090
0091
0092
0093
0094
0095
0096
0097
0098
0099
0100
0101 int snd_soc_dai_set_pll(struct snd_soc_dai *dai, int pll_id, int source,
0102 unsigned int freq_in, unsigned int freq_out)
0103 {
0104 int ret;
0105
0106 if (dai->driver->ops &&
0107 dai->driver->ops->set_pll)
0108 ret = dai->driver->ops->set_pll(dai, pll_id, source,
0109 freq_in, freq_out);
0110 else
0111 ret = snd_soc_component_set_pll(dai->component, pll_id, source,
0112 freq_in, freq_out);
0113
0114 return soc_dai_ret(dai, ret);
0115 }
0116 EXPORT_SYMBOL_GPL(snd_soc_dai_set_pll);
0117
0118
0119
0120
0121
0122
0123
0124
0125 int snd_soc_dai_set_bclk_ratio(struct snd_soc_dai *dai, unsigned int ratio)
0126 {
0127 int ret = -EINVAL;
0128
0129 if (dai->driver->ops &&
0130 dai->driver->ops->set_bclk_ratio)
0131 ret = dai->driver->ops->set_bclk_ratio(dai, ratio);
0132
0133 return soc_dai_ret(dai, ret);
0134 }
0135 EXPORT_SYMBOL_GPL(snd_soc_dai_set_bclk_ratio);
0136
0137 int snd_soc_dai_get_fmt_max_priority(struct snd_soc_pcm_runtime *rtd)
0138 {
0139 struct snd_soc_dai *dai;
0140 int i, max = 0;
0141
0142
0143
0144
0145 for_each_rtd_dais(rtd, i, dai) {
0146 if (dai->driver->ops &&
0147 dai->driver->ops->num_auto_selectable_formats)
0148 max = max(max, dai->driver->ops->num_auto_selectable_formats);
0149 else
0150 return 0;
0151 }
0152
0153 return max;
0154 }
0155
0156
0157
0158
0159
0160
0161
0162
0163
0164
0165
0166
0167
0168
0169 u64 snd_soc_dai_get_fmt(struct snd_soc_dai *dai, int priority)
0170 {
0171 const struct snd_soc_dai_ops *ops = dai->driver->ops;
0172 u64 fmt = 0;
0173 int i, max = 0, until = priority;
0174
0175
0176
0177
0178
0179
0180
0181
0182
0183
0184
0185
0186
0187
0188 if (ops)
0189 max = ops->num_auto_selectable_formats;
0190
0191 if (max < until)
0192 until = max;
0193
0194 for (i = 0; i < until; i++)
0195 fmt |= ops->auto_selectable_formats[i];
0196
0197 return fmt;
0198 }
0199
0200
0201
0202
0203
0204
0205
0206
0207 int snd_soc_dai_set_fmt(struct snd_soc_dai *dai, unsigned int fmt)
0208 {
0209 int ret = -ENOTSUPP;
0210
0211 if (dai->driver->ops && dai->driver->ops->set_fmt)
0212 ret = dai->driver->ops->set_fmt(dai, fmt);
0213
0214 return soc_dai_ret(dai, ret);
0215 }
0216 EXPORT_SYMBOL_GPL(snd_soc_dai_set_fmt);
0217
0218
0219
0220
0221
0222
0223
0224
0225
0226 static int snd_soc_xlate_tdm_slot_mask(unsigned int slots,
0227 unsigned int *tx_mask,
0228 unsigned int *rx_mask)
0229 {
0230 if (*tx_mask || *rx_mask)
0231 return 0;
0232
0233 if (!slots)
0234 return -EINVAL;
0235
0236 *tx_mask = (1 << slots) - 1;
0237 *rx_mask = (1 << slots) - 1;
0238
0239 return 0;
0240 }
0241
0242
0243
0244
0245
0246
0247
0248
0249
0250
0251
0252
0253
0254
0255
0256
0257
0258
0259
0260
0261
0262
0263
0264
0265 int snd_soc_dai_set_tdm_slot(struct snd_soc_dai *dai,
0266 unsigned int tx_mask, unsigned int rx_mask,
0267 int slots, int slot_width)
0268 {
0269 int ret = -ENOTSUPP;
0270
0271 if (dai->driver->ops &&
0272 dai->driver->ops->xlate_tdm_slot_mask)
0273 dai->driver->ops->xlate_tdm_slot_mask(slots,
0274 &tx_mask, &rx_mask);
0275 else
0276 snd_soc_xlate_tdm_slot_mask(slots, &tx_mask, &rx_mask);
0277
0278 dai->tx_mask = tx_mask;
0279 dai->rx_mask = rx_mask;
0280
0281 if (dai->driver->ops &&
0282 dai->driver->ops->set_tdm_slot)
0283 ret = dai->driver->ops->set_tdm_slot(dai, tx_mask, rx_mask,
0284 slots, slot_width);
0285 return soc_dai_ret(dai, ret);
0286 }
0287 EXPORT_SYMBOL_GPL(snd_soc_dai_set_tdm_slot);
0288
0289
0290
0291
0292
0293
0294
0295
0296
0297
0298
0299
0300
0301 int snd_soc_dai_set_channel_map(struct snd_soc_dai *dai,
0302 unsigned int tx_num, unsigned int *tx_slot,
0303 unsigned int rx_num, unsigned int *rx_slot)
0304 {
0305 int ret = -ENOTSUPP;
0306
0307 if (dai->driver->ops &&
0308 dai->driver->ops->set_channel_map)
0309 ret = dai->driver->ops->set_channel_map(dai, tx_num, tx_slot,
0310 rx_num, rx_slot);
0311 return soc_dai_ret(dai, ret);
0312 }
0313 EXPORT_SYMBOL_GPL(snd_soc_dai_set_channel_map);
0314
0315
0316
0317
0318
0319
0320
0321
0322
0323
0324
0325 int snd_soc_dai_get_channel_map(struct snd_soc_dai *dai,
0326 unsigned int *tx_num, unsigned int *tx_slot,
0327 unsigned int *rx_num, unsigned int *rx_slot)
0328 {
0329 int ret = -ENOTSUPP;
0330
0331 if (dai->driver->ops &&
0332 dai->driver->ops->get_channel_map)
0333 ret = dai->driver->ops->get_channel_map(dai, tx_num, tx_slot,
0334 rx_num, rx_slot);
0335 return soc_dai_ret(dai, ret);
0336 }
0337 EXPORT_SYMBOL_GPL(snd_soc_dai_get_channel_map);
0338
0339
0340
0341
0342
0343
0344
0345
0346 int snd_soc_dai_set_tristate(struct snd_soc_dai *dai, int tristate)
0347 {
0348 int ret = -EINVAL;
0349
0350 if (dai->driver->ops &&
0351 dai->driver->ops->set_tristate)
0352 ret = dai->driver->ops->set_tristate(dai, tristate);
0353
0354 return soc_dai_ret(dai, ret);
0355 }
0356 EXPORT_SYMBOL_GPL(snd_soc_dai_set_tristate);
0357
0358
0359
0360
0361
0362
0363
0364
0365
0366 int snd_soc_dai_digital_mute(struct snd_soc_dai *dai, int mute,
0367 int direction)
0368 {
0369 int ret = -ENOTSUPP;
0370
0371
0372
0373
0374
0375 if (dai->driver->ops &&
0376 dai->driver->ops->mute_stream &&
0377 (direction == SNDRV_PCM_STREAM_PLAYBACK ||
0378 !dai->driver->ops->no_capture_mute))
0379 ret = dai->driver->ops->mute_stream(dai, mute, direction);
0380
0381 return soc_dai_ret(dai, ret);
0382 }
0383 EXPORT_SYMBOL_GPL(snd_soc_dai_digital_mute);
0384
0385 int snd_soc_dai_hw_params(struct snd_soc_dai *dai,
0386 struct snd_pcm_substream *substream,
0387 struct snd_pcm_hw_params *params)
0388 {
0389 struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream);
0390 int ret = 0;
0391
0392 if (dai->driver->ops &&
0393 dai->driver->ops->hw_params) {
0394
0395 ret = snd_soc_link_be_hw_params_fixup(rtd, params);
0396 if (ret < 0)
0397 goto end;
0398
0399 ret = dai->driver->ops->hw_params(substream, params, dai);
0400 }
0401
0402
0403 if (ret == 0)
0404 soc_dai_mark_push(dai, substream, hw_params);
0405 end:
0406 return soc_dai_ret(dai, ret);
0407 }
0408
0409 void snd_soc_dai_hw_free(struct snd_soc_dai *dai,
0410 struct snd_pcm_substream *substream,
0411 int rollback)
0412 {
0413 if (rollback && !soc_dai_mark_match(dai, substream, hw_params))
0414 return;
0415
0416 if (dai->driver->ops &&
0417 dai->driver->ops->hw_free)
0418 dai->driver->ops->hw_free(substream, dai);
0419
0420
0421 soc_dai_mark_pop(dai, substream, hw_params);
0422 }
0423
0424 int snd_soc_dai_startup(struct snd_soc_dai *dai,
0425 struct snd_pcm_substream *substream)
0426 {
0427 int ret = 0;
0428
0429 if (dai->driver->ops &&
0430 dai->driver->ops->startup)
0431 ret = dai->driver->ops->startup(substream, dai);
0432
0433
0434 if (ret == 0)
0435 soc_dai_mark_push(dai, substream, startup);
0436
0437 return soc_dai_ret(dai, ret);
0438 }
0439
0440 void snd_soc_dai_shutdown(struct snd_soc_dai *dai,
0441 struct snd_pcm_substream *substream,
0442 int rollback)
0443 {
0444 if (rollback && !soc_dai_mark_match(dai, substream, startup))
0445 return;
0446
0447 if (dai->driver->ops &&
0448 dai->driver->ops->shutdown)
0449 dai->driver->ops->shutdown(substream, dai);
0450
0451
0452 soc_dai_mark_pop(dai, substream, startup);
0453 }
0454
0455 int snd_soc_dai_compress_new(struct snd_soc_dai *dai,
0456 struct snd_soc_pcm_runtime *rtd, int num)
0457 {
0458 int ret = -ENOTSUPP;
0459 if (dai->driver->compress_new)
0460 ret = dai->driver->compress_new(rtd, num);
0461 return soc_dai_ret(dai, ret);
0462 }
0463
0464
0465
0466
0467
0468
0469 bool snd_soc_dai_stream_valid(struct snd_soc_dai *dai, int dir)
0470 {
0471 struct snd_soc_pcm_stream *stream = snd_soc_dai_get_pcm_stream(dai, dir);
0472
0473
0474 return stream->channels_min;
0475 }
0476
0477
0478
0479
0480 void snd_soc_dai_link_set_capabilities(struct snd_soc_dai_link *dai_link)
0481 {
0482 bool supported[SNDRV_PCM_STREAM_LAST + 1];
0483 int direction;
0484
0485 for_each_pcm_streams(direction) {
0486 struct snd_soc_dai_link_component *cpu;
0487 struct snd_soc_dai_link_component *codec;
0488 struct snd_soc_dai *dai;
0489 bool supported_cpu = false;
0490 bool supported_codec = false;
0491 int i;
0492
0493 for_each_link_cpus(dai_link, i, cpu) {
0494 dai = snd_soc_find_dai_with_mutex(cpu);
0495 if (dai && snd_soc_dai_stream_valid(dai, direction)) {
0496 supported_cpu = true;
0497 break;
0498 }
0499 }
0500 for_each_link_codecs(dai_link, i, codec) {
0501 dai = snd_soc_find_dai_with_mutex(codec);
0502 if (dai && snd_soc_dai_stream_valid(dai, direction)) {
0503 supported_codec = true;
0504 break;
0505 }
0506 }
0507 supported[direction] = supported_cpu && supported_codec;
0508 }
0509
0510 dai_link->dpcm_playback = supported[SNDRV_PCM_STREAM_PLAYBACK];
0511 dai_link->dpcm_capture = supported[SNDRV_PCM_STREAM_CAPTURE];
0512 }
0513 EXPORT_SYMBOL_GPL(snd_soc_dai_link_set_capabilities);
0514
0515 void snd_soc_dai_action(struct snd_soc_dai *dai,
0516 int stream, int action)
0517 {
0518
0519 dai->stream_active[stream] += action;
0520
0521
0522 dai->component->active += action;
0523 }
0524 EXPORT_SYMBOL_GPL(snd_soc_dai_action);
0525
0526 int snd_soc_dai_active(struct snd_soc_dai *dai)
0527 {
0528 int stream, active;
0529
0530 active = 0;
0531 for_each_pcm_streams(stream)
0532 active += dai->stream_active[stream];
0533
0534 return active;
0535 }
0536 EXPORT_SYMBOL_GPL(snd_soc_dai_active);
0537
0538 int snd_soc_pcm_dai_probe(struct snd_soc_pcm_runtime *rtd, int order)
0539 {
0540 struct snd_soc_dai *dai;
0541 int i;
0542
0543 for_each_rtd_dais(rtd, i, dai) {
0544 if (dai->driver->probe_order != order)
0545 continue;
0546
0547 if (dai->driver->probe) {
0548 int ret = dai->driver->probe(dai);
0549
0550 if (ret < 0)
0551 return soc_dai_ret(dai, ret);
0552 }
0553
0554 dai->probed = 1;
0555 }
0556
0557 return 0;
0558 }
0559
0560 int snd_soc_pcm_dai_remove(struct snd_soc_pcm_runtime *rtd, int order)
0561 {
0562 struct snd_soc_dai *dai;
0563 int i, r, ret = 0;
0564
0565 for_each_rtd_dais(rtd, i, dai) {
0566 if (dai->driver->remove_order != order)
0567 continue;
0568
0569 if (dai->probed &&
0570 dai->driver->remove) {
0571 r = dai->driver->remove(dai);
0572 if (r < 0)
0573 ret = r;
0574 }
0575
0576 dai->probed = 0;
0577 }
0578
0579 return ret;
0580 }
0581
0582 int snd_soc_pcm_dai_new(struct snd_soc_pcm_runtime *rtd)
0583 {
0584 struct snd_soc_dai *dai;
0585 int i;
0586
0587 for_each_rtd_dais(rtd, i, dai) {
0588 if (dai->driver->pcm_new) {
0589 int ret = dai->driver->pcm_new(rtd, dai);
0590 if (ret < 0)
0591 return soc_dai_ret(dai, ret);
0592 }
0593 }
0594
0595 return 0;
0596 }
0597
0598 int snd_soc_pcm_dai_prepare(struct snd_pcm_substream *substream)
0599 {
0600 struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream);
0601 struct snd_soc_dai *dai;
0602 int i, ret;
0603
0604 for_each_rtd_dais(rtd, i, dai) {
0605 if (dai->driver->ops &&
0606 dai->driver->ops->prepare) {
0607 ret = dai->driver->ops->prepare(substream, dai);
0608 if (ret < 0)
0609 return soc_dai_ret(dai, ret);
0610 }
0611 }
0612
0613 return 0;
0614 }
0615
0616 static int soc_dai_trigger(struct snd_soc_dai *dai,
0617 struct snd_pcm_substream *substream, int cmd)
0618 {
0619 int ret = 0;
0620
0621 if (dai->driver->ops &&
0622 dai->driver->ops->trigger)
0623 ret = dai->driver->ops->trigger(substream, cmd, dai);
0624
0625 return soc_dai_ret(dai, ret);
0626 }
0627
0628 int snd_soc_pcm_dai_trigger(struct snd_pcm_substream *substream,
0629 int cmd, int rollback)
0630 {
0631 struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream);
0632 struct snd_soc_dai *dai;
0633 int i, r, ret = 0;
0634
0635 switch (cmd) {
0636 case SNDRV_PCM_TRIGGER_START:
0637 case SNDRV_PCM_TRIGGER_RESUME:
0638 case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
0639 for_each_rtd_dais(rtd, i, dai) {
0640 ret = soc_dai_trigger(dai, substream, cmd);
0641 if (ret < 0)
0642 break;
0643 soc_dai_mark_push(dai, substream, trigger);
0644 }
0645 break;
0646 case SNDRV_PCM_TRIGGER_STOP:
0647 case SNDRV_PCM_TRIGGER_SUSPEND:
0648 case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
0649 for_each_rtd_dais(rtd, i, dai) {
0650 if (rollback && !soc_dai_mark_match(dai, substream, trigger))
0651 continue;
0652
0653 r = soc_dai_trigger(dai, substream, cmd);
0654 if (r < 0)
0655 ret = r;
0656 soc_dai_mark_pop(dai, substream, trigger);
0657 }
0658 }
0659
0660 return ret;
0661 }
0662
0663 int snd_soc_pcm_dai_bespoke_trigger(struct snd_pcm_substream *substream,
0664 int cmd)
0665 {
0666 struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream);
0667 struct snd_soc_dai *dai;
0668 int i, ret;
0669
0670 for_each_rtd_dais(rtd, i, dai) {
0671 if (dai->driver->ops &&
0672 dai->driver->ops->bespoke_trigger) {
0673 ret = dai->driver->ops->bespoke_trigger(substream,
0674 cmd, dai);
0675 if (ret < 0)
0676 return soc_dai_ret(dai, ret);
0677 }
0678 }
0679
0680 return 0;
0681 }
0682
0683 void snd_soc_pcm_dai_delay(struct snd_pcm_substream *substream,
0684 snd_pcm_sframes_t *cpu_delay,
0685 snd_pcm_sframes_t *codec_delay)
0686 {
0687 struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream);
0688 struct snd_soc_dai *dai;
0689 int i;
0690
0691
0692
0693
0694
0695
0696
0697
0698
0699 for_each_rtd_cpu_dais(rtd, i, dai)
0700 if (dai->driver->ops &&
0701 dai->driver->ops->delay)
0702 *cpu_delay = max(*cpu_delay, dai->driver->ops->delay(substream, dai));
0703
0704
0705 for_each_rtd_codec_dais(rtd, i, dai)
0706 if (dai->driver->ops &&
0707 dai->driver->ops->delay)
0708 *codec_delay = max(*codec_delay, dai->driver->ops->delay(substream, dai));
0709 }
0710
0711 int snd_soc_dai_compr_startup(struct snd_soc_dai *dai,
0712 struct snd_compr_stream *cstream)
0713 {
0714 int ret = 0;
0715
0716 if (dai->driver->cops &&
0717 dai->driver->cops->startup)
0718 ret = dai->driver->cops->startup(cstream, dai);
0719
0720
0721 if (ret == 0)
0722 soc_dai_mark_push(dai, cstream, compr_startup);
0723
0724 return soc_dai_ret(dai, ret);
0725 }
0726 EXPORT_SYMBOL_GPL(snd_soc_dai_compr_startup);
0727
0728 void snd_soc_dai_compr_shutdown(struct snd_soc_dai *dai,
0729 struct snd_compr_stream *cstream,
0730 int rollback)
0731 {
0732 if (rollback && !soc_dai_mark_match(dai, cstream, compr_startup))
0733 return;
0734
0735 if (dai->driver->cops &&
0736 dai->driver->cops->shutdown)
0737 dai->driver->cops->shutdown(cstream, dai);
0738
0739
0740 soc_dai_mark_pop(dai, cstream, compr_startup);
0741 }
0742 EXPORT_SYMBOL_GPL(snd_soc_dai_compr_shutdown);
0743
0744 int snd_soc_dai_compr_trigger(struct snd_soc_dai *dai,
0745 struct snd_compr_stream *cstream, int cmd)
0746 {
0747 int ret = 0;
0748
0749 if (dai->driver->cops &&
0750 dai->driver->cops->trigger)
0751 ret = dai->driver->cops->trigger(cstream, cmd, dai);
0752
0753 return soc_dai_ret(dai, ret);
0754 }
0755 EXPORT_SYMBOL_GPL(snd_soc_dai_compr_trigger);
0756
0757 int snd_soc_dai_compr_set_params(struct snd_soc_dai *dai,
0758 struct snd_compr_stream *cstream,
0759 struct snd_compr_params *params)
0760 {
0761 int ret = 0;
0762
0763 if (dai->driver->cops &&
0764 dai->driver->cops->set_params)
0765 ret = dai->driver->cops->set_params(cstream, params, dai);
0766
0767 return soc_dai_ret(dai, ret);
0768 }
0769 EXPORT_SYMBOL_GPL(snd_soc_dai_compr_set_params);
0770
0771 int snd_soc_dai_compr_get_params(struct snd_soc_dai *dai,
0772 struct snd_compr_stream *cstream,
0773 struct snd_codec *params)
0774 {
0775 int ret = 0;
0776
0777 if (dai->driver->cops &&
0778 dai->driver->cops->get_params)
0779 ret = dai->driver->cops->get_params(cstream, params, dai);
0780
0781 return soc_dai_ret(dai, ret);
0782 }
0783 EXPORT_SYMBOL_GPL(snd_soc_dai_compr_get_params);
0784
0785 int snd_soc_dai_compr_ack(struct snd_soc_dai *dai,
0786 struct snd_compr_stream *cstream,
0787 size_t bytes)
0788 {
0789 int ret = 0;
0790
0791 if (dai->driver->cops &&
0792 dai->driver->cops->ack)
0793 ret = dai->driver->cops->ack(cstream, bytes, dai);
0794
0795 return soc_dai_ret(dai, ret);
0796 }
0797 EXPORT_SYMBOL_GPL(snd_soc_dai_compr_ack);
0798
0799 int snd_soc_dai_compr_pointer(struct snd_soc_dai *dai,
0800 struct snd_compr_stream *cstream,
0801 struct snd_compr_tstamp *tstamp)
0802 {
0803 int ret = 0;
0804
0805 if (dai->driver->cops &&
0806 dai->driver->cops->pointer)
0807 ret = dai->driver->cops->pointer(cstream, tstamp, dai);
0808
0809 return soc_dai_ret(dai, ret);
0810 }
0811 EXPORT_SYMBOL_GPL(snd_soc_dai_compr_pointer);
0812
0813 int snd_soc_dai_compr_set_metadata(struct snd_soc_dai *dai,
0814 struct snd_compr_stream *cstream,
0815 struct snd_compr_metadata *metadata)
0816 {
0817 int ret = 0;
0818
0819 if (dai->driver->cops &&
0820 dai->driver->cops->set_metadata)
0821 ret = dai->driver->cops->set_metadata(cstream, metadata, dai);
0822
0823 return soc_dai_ret(dai, ret);
0824 }
0825 EXPORT_SYMBOL_GPL(snd_soc_dai_compr_set_metadata);
0826
0827 int snd_soc_dai_compr_get_metadata(struct snd_soc_dai *dai,
0828 struct snd_compr_stream *cstream,
0829 struct snd_compr_metadata *metadata)
0830 {
0831 int ret = 0;
0832
0833 if (dai->driver->cops &&
0834 dai->driver->cops->get_metadata)
0835 ret = dai->driver->cops->get_metadata(cstream, metadata, dai);
0836
0837 return soc_dai_ret(dai, ret);
0838 }
0839 EXPORT_SYMBOL_GPL(snd_soc_dai_compr_get_metadata);