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 if (ops && ops->auto_selectable_formats) 181 for (i = 0; i < until; i++) 182 fmt |= ops->auto_selectable_formats[i]; 183 184 return fmt; 185 } 186 187 /** 188 * snd_soc_dai_set_fmt - configure DAI hardware audio format. 189 * @dai: DAI 190 * @fmt: SND_SOC_DAIFMT_* format value. 191 * 192 * Configures the DAI hardware format and clocking. 193 */ 194 int snd_soc_dai_set_fmt(struct snd_soc_dai *dai, unsigned int fmt) 195 { 196 int ret = -ENOTSUPP; 197 198 if (dai->driver->ops && dai->driver->ops->set_fmt) 199 ret = dai->driver->ops->set_fmt(dai, fmt); 200 201 return soc_dai_ret(dai, ret); 202 } 203 EXPORT_SYMBOL_GPL(snd_soc_dai_set_fmt); 204 205 /** 206 * snd_soc_xlate_tdm_slot_mask - generate tx/rx slot mask. 207 * @slots: Number of slots in use. 208 * @tx_mask: bitmask representing active TX slots. 209 * @rx_mask: bitmask representing active RX slots. 210 * 211 * Generates the TDM tx and rx slot default masks for DAI. 212 */ 213 static int snd_soc_xlate_tdm_slot_mask(unsigned int slots, 214 unsigned int *tx_mask, 215 unsigned int *rx_mask) 216 { 217 if (*tx_mask || *rx_mask) 218 return 0; 219 220 if (!slots) 221 return -EINVAL; 222 223 *tx_mask = (1 << slots) - 1; 224 *rx_mask = (1 << slots) - 1; 225 226 return 0; 227 } 228 229 /** 230 * snd_soc_dai_set_tdm_slot() - Configures a DAI for TDM operation 231 * @dai: The DAI to configure 232 * @tx_mask: bitmask representing active TX slots. 233 * @rx_mask: bitmask representing active RX slots. 234 * @slots: Number of slots in use. 235 * @slot_width: Width in bits for each slot. 236 * 237 * This function configures the specified DAI for TDM operation. @slot contains 238 * the total number of slots of the TDM stream and @slot_with the width of each 239 * slot in bit clock cycles. @tx_mask and @rx_mask are bitmasks specifying the 240 * active slots of the TDM stream for the specified DAI, i.e. which slots the 241 * DAI should write to or read from. If a bit is set the corresponding slot is 242 * active, if a bit is cleared the corresponding slot is inactive. Bit 0 maps to 243 * the first slot, bit 1 to the second slot and so on. The first active slot 244 * maps to the first channel of the DAI, the second active slot to the second 245 * channel and so on. 246 * 247 * TDM mode can be disabled by passing 0 for @slots. In this case @tx_mask, 248 * @rx_mask and @slot_width will be ignored. 249 * 250 * Returns 0 on success, a negative error code otherwise. 251 */ 252 int snd_soc_dai_set_tdm_slot(struct snd_soc_dai *dai, 253 unsigned int tx_mask, unsigned int rx_mask, 254 int slots, int slot_width) 255 { 256 int ret = -ENOTSUPP; 257 int stream; 258 unsigned int *tdm_mask[] = { 259 &tx_mask, 260 &rx_mask, 261 }; 262 263 if (slots) { 264 if (dai->driver->ops && 265 dai->driver->ops->xlate_tdm_slot_mask) 266 ret = dai->driver->ops->xlate_tdm_slot_mask(slots, &tx_mask, &rx_mask); 267 else 268 ret = snd_soc_xlate_tdm_slot_mask(slots, &tx_mask, &rx_mask); 269 if (ret) 270 goto err; 271 } 272 273 for_each_pcm_streams(stream) 274 snd_soc_dai_tdm_mask_set(dai, stream, *tdm_mask[stream]); 275 276 if (dai->driver->ops && 277 dai->driver->ops->set_tdm_slot) 278 ret = dai->driver->ops->set_tdm_slot(dai, tx_mask, rx_mask, 279 slots, slot_width); 280 err: 281 return soc_dai_ret(dai, ret); 282 } 283 EXPORT_SYMBOL_GPL(snd_soc_dai_set_tdm_slot); 284 285 /** 286 * snd_soc_dai_set_channel_map - configure DAI audio channel map 287 * @dai: DAI 288 * @tx_num: how many TX channels 289 * @tx_slot: pointer to an array which imply the TX slot number channel 290 * 0~num-1 uses 291 * @rx_num: how many RX channels 292 * @rx_slot: pointer to an array which imply the RX slot number channel 293 * 0~num-1 uses 294 * 295 * configure the relationship between channel number and TDM slot number. 296 */ 297 int snd_soc_dai_set_channel_map(struct snd_soc_dai *dai, 298 unsigned int tx_num, const unsigned int *tx_slot, 299 unsigned int rx_num, const unsigned int *rx_slot) 300 { 301 int ret = -ENOTSUPP; 302 303 if (dai->driver->ops && 304 dai->driver->ops->set_channel_map) 305 ret = dai->driver->ops->set_channel_map(dai, tx_num, tx_slot, 306 rx_num, rx_slot); 307 return soc_dai_ret(dai, ret); 308 } 309 EXPORT_SYMBOL_GPL(snd_soc_dai_set_channel_map); 310 311 /** 312 * snd_soc_dai_get_channel_map - Get DAI audio channel map 313 * @dai: DAI 314 * @tx_num: how many TX channels 315 * @tx_slot: pointer to an array which imply the TX slot number channel 316 * 0~num-1 uses 317 * @rx_num: how many RX channels 318 * @rx_slot: pointer to an array which imply the RX slot number channel 319 * 0~num-1 uses 320 */ 321 int snd_soc_dai_get_channel_map(const struct snd_soc_dai *dai, 322 unsigned int *tx_num, unsigned int *tx_slot, 323 unsigned int *rx_num, unsigned int *rx_slot) 324 { 325 int ret = -ENOTSUPP; 326 327 if (dai->driver->ops && 328 dai->driver->ops->get_channel_map) 329 ret = dai->driver->ops->get_channel_map(dai, tx_num, tx_slot, 330 rx_num, rx_slot); 331 return soc_dai_ret(dai, ret); 332 } 333 EXPORT_SYMBOL_GPL(snd_soc_dai_get_channel_map); 334 335 /** 336 * snd_soc_dai_set_tristate - configure DAI system or master clock. 337 * @dai: DAI 338 * @tristate: tristate enable 339 * 340 * Tristates the DAI so that others can use it. 341 */ 342 int snd_soc_dai_set_tristate(struct snd_soc_dai *dai, int tristate) 343 { 344 int ret = -EINVAL; 345 346 if (dai->driver->ops && 347 dai->driver->ops->set_tristate) 348 ret = dai->driver->ops->set_tristate(dai, tristate); 349 350 return soc_dai_ret(dai, ret); 351 } 352 EXPORT_SYMBOL_GPL(snd_soc_dai_set_tristate); 353 354 int snd_soc_dai_prepare(struct snd_soc_dai *dai, 355 struct snd_pcm_substream *substream) 356 { 357 int ret = 0; 358 359 if (!snd_soc_dai_stream_valid(dai, substream->stream)) 360 return 0; 361 362 if (dai->driver->ops && 363 dai->driver->ops->prepare) 364 ret = dai->driver->ops->prepare(substream, dai); 365 366 return soc_dai_ret(dai, ret); 367 } 368 EXPORT_SYMBOL_GPL(snd_soc_dai_prepare); 369 370 int snd_soc_dai_mute_is_ctrled_at_trigger(struct snd_soc_dai *dai) 371 { 372 if (dai->driver->ops) 373 return dai->driver->ops->mute_unmute_on_trigger; 374 375 return 0; 376 } 377 378 /** 379 * snd_soc_dai_digital_mute - configure DAI system or master clock. 380 * @dai: DAI 381 * @mute: mute enable 382 * @direction: stream to mute 383 * 384 * Mutes the DAI DAC. 385 */ 386 int snd_soc_dai_digital_mute(struct snd_soc_dai *dai, int mute, 387 int direction) 388 { 389 int ret = -ENOTSUPP; 390 391 /* 392 * ignore if direction was CAPTURE 393 * and it had .no_capture_mute flag 394 */ 395 if (dai->driver->ops && 396 dai->driver->ops->mute_stream && 397 (direction == SNDRV_PCM_STREAM_PLAYBACK || 398 !dai->driver->ops->no_capture_mute)) 399 ret = dai->driver->ops->mute_stream(dai, mute, direction); 400 401 return soc_dai_ret(dai, ret); 402 } 403 EXPORT_SYMBOL_GPL(snd_soc_dai_digital_mute); 404 405 int snd_soc_dai_hw_params(struct snd_soc_dai *dai, 406 struct snd_pcm_substream *substream, 407 struct snd_pcm_hw_params *params) 408 { 409 int ret = 0; 410 411 if (dai->driver->ops && 412 dai->driver->ops->hw_params) 413 ret = dai->driver->ops->hw_params(substream, params, dai); 414 415 /* mark substream if succeeded */ 416 if (ret == 0) 417 soc_dai_mark_push(dai, substream, hw_params); 418 419 return soc_dai_ret(dai, ret); 420 } 421 422 void snd_soc_dai_hw_free(struct snd_soc_dai *dai, 423 struct snd_pcm_substream *substream, 424 int rollback) 425 { 426 if (rollback && !soc_dai_mark_match(dai, substream, hw_params)) 427 return; 428 429 if (dai->driver->ops && 430 dai->driver->ops->hw_free) 431 dai->driver->ops->hw_free(substream, dai); 432 433 /* remove marked substream */ 434 soc_dai_mark_pop(dai, hw_params); 435 } 436 437 int snd_soc_dai_startup(struct snd_soc_dai *dai, 438 struct snd_pcm_substream *substream) 439 { 440 int ret = 0; 441 442 if (!snd_soc_dai_stream_valid(dai, substream->stream)) 443 return 0; 444 445 if (dai->driver->ops && 446 dai->driver->ops->startup) 447 ret = dai->driver->ops->startup(substream, dai); 448 449 /* mark substream if succeeded */ 450 if (ret == 0) 451 soc_dai_mark_push(dai, substream, startup); 452 453 return soc_dai_ret(dai, ret); 454 } 455 456 void snd_soc_dai_shutdown(struct snd_soc_dai *dai, 457 struct snd_pcm_substream *substream, 458 int rollback) 459 { 460 if (!snd_soc_dai_stream_valid(dai, substream->stream)) 461 return; 462 463 if (rollback && !soc_dai_mark_match(dai, substream, startup)) 464 return; 465 466 if (dai->driver->ops && 467 dai->driver->ops->shutdown) 468 dai->driver->ops->shutdown(substream, dai); 469 470 /* remove marked substream */ 471 soc_dai_mark_pop(dai, startup); 472 } 473 474 int snd_soc_dai_compress_new(struct snd_soc_dai *dai, 475 struct snd_soc_pcm_runtime *rtd) 476 { 477 int ret = -ENOTSUPP; 478 if (dai->driver->ops && 479 dai->driver->ops->compress_new) 480 ret = dai->driver->ops->compress_new(rtd); 481 return soc_dai_ret(dai, ret); 482 } 483 484 /* 485 * snd_soc_dai_stream_valid() - check if a DAI supports the given stream 486 * 487 * Returns true if the DAI supports the indicated stream type. 488 */ 489 bool snd_soc_dai_stream_valid(const struct snd_soc_dai *dai, int dir) 490 { 491 const struct snd_soc_pcm_stream *stream = snd_soc_dai_get_pcm_stream(dai, dir); 492 493 /* If the codec specifies any channels at all, it supports the stream */ 494 return stream->channels_min; 495 } 496 497 void snd_soc_dai_action(struct snd_soc_dai *dai, 498 int stream, int action) 499 { 500 /* see snd_soc_dai_stream_active() */ 501 dai->stream[stream].active += action; 502 503 /* see snd_soc_component_active() */ 504 dai->component->active += action; 505 } 506 EXPORT_SYMBOL_GPL(snd_soc_dai_action); 507 508 int snd_soc_dai_active(const struct snd_soc_dai *dai) 509 { 510 int stream, active; 511 512 active = 0; 513 for_each_pcm_streams(stream) 514 active += dai->stream[stream].active; 515 516 return active; 517 } 518 EXPORT_SYMBOL_GPL(snd_soc_dai_active); 519 520 int snd_soc_pcm_dai_probe(struct snd_soc_pcm_runtime *rtd, int order) 521 { 522 struct snd_soc_dai *dai; 523 int i; 524 525 for_each_rtd_dais(rtd, i, dai) { 526 if (dai->probed) 527 continue; 528 529 if (dai->driver->ops) { 530 if (dai->driver->ops->probe_order != order) 531 continue; 532 533 if (dai->driver->ops->probe) { 534 int ret = dai->driver->ops->probe(dai); 535 536 if (ret < 0) 537 return soc_dai_ret(dai, ret); 538 } 539 } 540 dai->probed = 1; 541 } 542 543 return 0; 544 } 545 546 int snd_soc_pcm_dai_remove(struct snd_soc_pcm_runtime *rtd, int order) 547 { 548 struct snd_soc_dai *dai; 549 int i, r, ret = 0; 550 551 for_each_rtd_dais(rtd, i, dai) { 552 if (!dai->probed) 553 continue; 554 555 if (dai->driver->ops) { 556 if (dai->driver->ops->remove_order != order) 557 continue; 558 559 if (dai->driver->ops->remove) { 560 r = dai->driver->ops->remove(dai); 561 if (r < 0) 562 ret = r; /* use last error */ 563 } 564 } 565 dai->probed = 0; 566 } 567 568 return ret; 569 } 570 571 int snd_soc_pcm_dai_new(struct snd_soc_pcm_runtime *rtd) 572 { 573 struct snd_soc_dai *dai; 574 int i; 575 576 for_each_rtd_dais(rtd, i, dai) { 577 if (dai->driver->ops && 578 dai->driver->ops->pcm_new) { 579 int ret = dai->driver->ops->pcm_new(rtd, dai); 580 if (ret < 0) 581 return soc_dai_ret(dai, ret); 582 } 583 } 584 585 return 0; 586 } 587 588 int snd_soc_pcm_dai_prepare(struct snd_pcm_substream *substream) 589 { 590 struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream); 591 struct snd_soc_dai *dai; 592 int i, ret; 593 594 for_each_rtd_dais(rtd, i, dai) { 595 ret = snd_soc_dai_prepare(dai, substream); 596 if (ret < 0) 597 return ret; 598 } 599 600 return 0; 601 } 602 603 static int soc_dai_trigger(struct snd_soc_dai *dai, 604 struct snd_pcm_substream *substream, int cmd) 605 { 606 int ret = 0; 607 608 if (!snd_soc_dai_stream_valid(dai, substream->stream)) 609 return 0; 610 611 if (dai->driver->ops && 612 dai->driver->ops->trigger) 613 ret = dai->driver->ops->trigger(substream, cmd, dai); 614 615 return soc_dai_ret(dai, ret); 616 } 617 618 int snd_soc_pcm_dai_trigger(struct snd_pcm_substream *substream, 619 int cmd, int rollback) 620 { 621 struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream); 622 struct snd_soc_dai *dai; 623 int i, r, ret = 0; 624 625 switch (cmd) { 626 case SNDRV_PCM_TRIGGER_START: 627 case SNDRV_PCM_TRIGGER_RESUME: 628 case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: 629 for_each_rtd_dais(rtd, i, dai) { 630 ret = soc_dai_trigger(dai, substream, cmd); 631 if (ret < 0) 632 break; 633 634 if (snd_soc_dai_mute_is_ctrled_at_trigger(dai)) 635 snd_soc_dai_digital_mute(dai, 0, substream->stream); 636 637 soc_dai_mark_push(dai, substream, trigger); 638 } 639 break; 640 case SNDRV_PCM_TRIGGER_STOP: 641 case SNDRV_PCM_TRIGGER_SUSPEND: 642 case SNDRV_PCM_TRIGGER_PAUSE_PUSH: 643 for_each_rtd_dais(rtd, i, dai) { 644 if (rollback && !soc_dai_mark_match(dai, substream, trigger)) 645 continue; 646 647 if (snd_soc_dai_mute_is_ctrled_at_trigger(dai)) 648 snd_soc_dai_digital_mute(dai, 1, substream->stream); 649 650 r = soc_dai_trigger(dai, substream, cmd); 651 if (r < 0) 652 ret = r; /* use last ret */ 653 soc_dai_mark_pop(dai, trigger); 654 } 655 } 656 657 return ret; 658 } 659 660 void snd_soc_pcm_dai_delay(struct snd_pcm_substream *substream, 661 snd_pcm_sframes_t *cpu_delay, 662 snd_pcm_sframes_t *codec_delay) 663 { 664 struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream); 665 struct snd_soc_dai *dai; 666 int i; 667 668 /* 669 * We're looking for the delay through the full audio path so it needs to 670 * be the maximum of the DAIs doing transmit and the maximum of the DAIs 671 * doing receive (ie, all CPUs and all CODECs) rather than just the maximum 672 * of all DAIs. 673 */ 674 675 /* for CPU */ 676 for_each_rtd_cpu_dais(rtd, i, dai) 677 if (dai->driver->ops && 678 dai->driver->ops->delay) 679 *cpu_delay = max(*cpu_delay, dai->driver->ops->delay(substream, dai)); 680 681 /* for Codec */ 682 for_each_rtd_codec_dais(rtd, i, dai) 683 if (dai->driver->ops && 684 dai->driver->ops->delay) 685 *codec_delay = max(*codec_delay, dai->driver->ops->delay(substream, dai)); 686 } 687 688 int snd_soc_dai_compr_startup(struct snd_soc_dai *dai, 689 struct snd_compr_stream *cstream) 690 { 691 int ret = 0; 692 693 if (dai->driver->cops && 694 dai->driver->cops->startup) 695 ret = dai->driver->cops->startup(cstream, dai); 696 697 /* mark cstream if succeeded */ 698 if (ret == 0) 699 soc_dai_mark_push(dai, cstream, compr_startup); 700 701 return soc_dai_ret(dai, ret); 702 } 703 EXPORT_SYMBOL_GPL(snd_soc_dai_compr_startup); 704 705 void snd_soc_dai_compr_shutdown(struct snd_soc_dai *dai, 706 struct snd_compr_stream *cstream, 707 int rollback) 708 { 709 if (rollback && !soc_dai_mark_match(dai, cstream, compr_startup)) 710 return; 711 712 if (dai->driver->cops && 713 dai->driver->cops->shutdown) 714 dai->driver->cops->shutdown(cstream, dai); 715 716 /* remove marked cstream */ 717 soc_dai_mark_pop(dai, compr_startup); 718 } 719 EXPORT_SYMBOL_GPL(snd_soc_dai_compr_shutdown); 720 721 int snd_soc_dai_compr_trigger(struct snd_soc_dai *dai, 722 struct snd_compr_stream *cstream, int cmd) 723 { 724 int ret = 0; 725 726 if (dai->driver->cops && 727 dai->driver->cops->trigger) 728 ret = dai->driver->cops->trigger(cstream, cmd, dai); 729 730 return soc_dai_ret(dai, ret); 731 } 732 EXPORT_SYMBOL_GPL(snd_soc_dai_compr_trigger); 733 734 int snd_soc_dai_compr_set_params(struct snd_soc_dai *dai, 735 struct snd_compr_stream *cstream, 736 struct snd_compr_params *params) 737 { 738 int ret = 0; 739 740 if (dai->driver->cops && 741 dai->driver->cops->set_params) 742 ret = dai->driver->cops->set_params(cstream, params, dai); 743 744 return soc_dai_ret(dai, ret); 745 } 746 EXPORT_SYMBOL_GPL(snd_soc_dai_compr_set_params); 747 748 int snd_soc_dai_compr_get_params(struct snd_soc_dai *dai, 749 struct snd_compr_stream *cstream, 750 struct snd_codec *params) 751 { 752 int ret = 0; 753 754 if (dai->driver->cops && 755 dai->driver->cops->get_params) 756 ret = dai->driver->cops->get_params(cstream, params, dai); 757 758 return soc_dai_ret(dai, ret); 759 } 760 EXPORT_SYMBOL_GPL(snd_soc_dai_compr_get_params); 761 762 int snd_soc_dai_compr_ack(struct snd_soc_dai *dai, 763 struct snd_compr_stream *cstream, 764 size_t bytes) 765 { 766 int ret = 0; 767 768 if (dai->driver->cops && 769 dai->driver->cops->ack) 770 ret = dai->driver->cops->ack(cstream, bytes, dai); 771 772 return soc_dai_ret(dai, ret); 773 } 774 EXPORT_SYMBOL_GPL(snd_soc_dai_compr_ack); 775 776 int snd_soc_dai_compr_pointer(struct snd_soc_dai *dai, 777 struct snd_compr_stream *cstream, 778 struct snd_compr_tstamp64 *tstamp) 779 { 780 int ret = 0; 781 782 if (dai->driver->cops && 783 dai->driver->cops->pointer) 784 ret = dai->driver->cops->pointer(cstream, tstamp, dai); 785 786 return soc_dai_ret(dai, ret); 787 } 788 EXPORT_SYMBOL_GPL(snd_soc_dai_compr_pointer); 789 790 int snd_soc_dai_compr_set_metadata(struct snd_soc_dai *dai, 791 struct snd_compr_stream *cstream, 792 struct snd_compr_metadata *metadata) 793 { 794 int ret = 0; 795 796 if (dai->driver->cops && 797 dai->driver->cops->set_metadata) 798 ret = dai->driver->cops->set_metadata(cstream, metadata, dai); 799 800 return soc_dai_ret(dai, ret); 801 } 802 EXPORT_SYMBOL_GPL(snd_soc_dai_compr_set_metadata); 803 804 int snd_soc_dai_compr_get_metadata(struct snd_soc_dai *dai, 805 struct snd_compr_stream *cstream, 806 struct snd_compr_metadata *metadata) 807 { 808 int ret = 0; 809 810 if (dai->driver->cops && 811 dai->driver->cops->get_metadata) 812 ret = dai->driver->cops->get_metadata(cstream, metadata, dai); 813 814 return soc_dai_ret(dai, ret); 815 } 816 EXPORT_SYMBOL_GPL(snd_soc_dai_compr_get_metadata); 817