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