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