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