1 // SPDX-License-Identifier: GPL-2.0 2 /* 3 * ALSA SoC using the QUICC Multichannel Controller (QMC) 4 * 5 * Copyright 2022 CS GROUP France 6 * 7 * Author: Herve Codina <herve.codina@bootlin.com> 8 */ 9 10 #include <linux/dma-mapping.h> 11 #include <linux/module.h> 12 #include <linux/of.h> 13 #include <linux/of_platform.h> 14 #include <linux/platform_device.h> 15 #include <linux/slab.h> 16 #include <soc/fsl/qe/qmc.h> 17 #include <sound/pcm_params.h> 18 #include <sound/soc.h> 19 20 struct qmc_dai { 21 char *name; 22 int id; 23 struct device *dev; 24 struct qmc_chan *qmc_chan; 25 unsigned int nb_tx_ts; 26 unsigned int nb_rx_ts; 27 }; 28 29 struct qmc_audio { 30 struct device *dev; 31 unsigned int num_dais; 32 struct qmc_dai *dais; 33 struct snd_soc_dai_driver *dai_drivers; 34 }; 35 36 struct qmc_dai_prtd { 37 struct qmc_dai *qmc_dai; 38 dma_addr_t dma_buffer_start; 39 dma_addr_t period_ptr_submitted; 40 dma_addr_t period_ptr_ended; 41 dma_addr_t dma_buffer_end; 42 size_t period_size; 43 struct snd_pcm_substream *substream; 44 }; 45 46 static int qmc_audio_pcm_construct(struct snd_soc_component *component, 47 struct snd_soc_pcm_runtime *rtd) 48 { 49 struct snd_card *card = rtd->card->snd_card; 50 int ret; 51 52 ret = dma_coerce_mask_and_coherent(card->dev, DMA_BIT_MASK(32)); 53 if (ret) 54 return ret; 55 56 snd_pcm_set_managed_buffer_all(rtd->pcm, SNDRV_DMA_TYPE_DEV, card->dev, 57 64*1024, 64*1024); 58 return 0; 59 } 60 61 static int qmc_audio_pcm_hw_params(struct snd_soc_component *component, 62 struct snd_pcm_substream *substream, 63 struct snd_pcm_hw_params *params) 64 { 65 struct snd_pcm_runtime *runtime = substream->runtime; 66 struct qmc_dai_prtd *prtd = substream->runtime->private_data; 67 68 prtd->dma_buffer_start = runtime->dma_addr; 69 prtd->dma_buffer_end = runtime->dma_addr + params_buffer_bytes(params); 70 prtd->period_size = params_period_bytes(params); 71 prtd->period_ptr_submitted = prtd->dma_buffer_start; 72 prtd->period_ptr_ended = prtd->dma_buffer_start; 73 prtd->substream = substream; 74 75 return 0; 76 } 77 78 static void qmc_audio_pcm_write_complete(void *context) 79 { 80 struct qmc_dai_prtd *prtd = context; 81 int ret; 82 83 prtd->period_ptr_ended += prtd->period_size; 84 if (prtd->period_ptr_ended >= prtd->dma_buffer_end) 85 prtd->period_ptr_ended = prtd->dma_buffer_start; 86 87 prtd->period_ptr_submitted += prtd->period_size; 88 if (prtd->period_ptr_submitted >= prtd->dma_buffer_end) 89 prtd->period_ptr_submitted = prtd->dma_buffer_start; 90 91 ret = qmc_chan_write_submit(prtd->qmc_dai->qmc_chan, 92 prtd->period_ptr_submitted, prtd->period_size, 93 qmc_audio_pcm_write_complete, prtd); 94 if (ret) { 95 dev_err(prtd->qmc_dai->dev, "write_submit failed %d\n", 96 ret); 97 } 98 99 snd_pcm_period_elapsed(prtd->substream); 100 } 101 102 static void qmc_audio_pcm_read_complete(void *context, size_t length) 103 { 104 struct qmc_dai_prtd *prtd = context; 105 int ret; 106 107 if (length != prtd->period_size) { 108 dev_err(prtd->qmc_dai->dev, "read complete length = %zu, exp %zu\n", 109 length, prtd->period_size); 110 } 111 112 prtd->period_ptr_ended += prtd->period_size; 113 if (prtd->period_ptr_ended >= prtd->dma_buffer_end) 114 prtd->period_ptr_ended = prtd->dma_buffer_start; 115 116 prtd->period_ptr_submitted += prtd->period_size; 117 if (prtd->period_ptr_submitted >= prtd->dma_buffer_end) 118 prtd->period_ptr_submitted = prtd->dma_buffer_start; 119 120 ret = qmc_chan_read_submit(prtd->qmc_dai->qmc_chan, 121 prtd->period_ptr_submitted, prtd->period_size, 122 qmc_audio_pcm_read_complete, prtd); 123 if (ret) { 124 dev_err(prtd->qmc_dai->dev, "read_submit failed %d\n", 125 ret); 126 } 127 128 snd_pcm_period_elapsed(prtd->substream); 129 } 130 131 static int qmc_audio_pcm_trigger(struct snd_soc_component *component, 132 struct snd_pcm_substream *substream, int cmd) 133 { 134 struct qmc_dai_prtd *prtd = substream->runtime->private_data; 135 int ret; 136 137 if (!prtd->qmc_dai) { 138 dev_err(component->dev, "qmc_dai is not set\n"); 139 return -EINVAL; 140 } 141 142 switch (cmd) { 143 case SNDRV_PCM_TRIGGER_START: 144 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { 145 /* Submit first chunk ... */ 146 ret = qmc_chan_write_submit(prtd->qmc_dai->qmc_chan, 147 prtd->period_ptr_submitted, prtd->period_size, 148 qmc_audio_pcm_write_complete, prtd); 149 if (ret) { 150 dev_err(component->dev, "write_submit failed %d\n", 151 ret); 152 return ret; 153 } 154 155 /* ... prepare next one ... */ 156 prtd->period_ptr_submitted += prtd->period_size; 157 if (prtd->period_ptr_submitted >= prtd->dma_buffer_end) 158 prtd->period_ptr_submitted = prtd->dma_buffer_start; 159 160 /* ... and send it */ 161 ret = qmc_chan_write_submit(prtd->qmc_dai->qmc_chan, 162 prtd->period_ptr_submitted, prtd->period_size, 163 qmc_audio_pcm_write_complete, prtd); 164 if (ret) { 165 dev_err(component->dev, "write_submit failed %d\n", 166 ret); 167 return ret; 168 } 169 } else { 170 /* Submit first chunk ... */ 171 ret = qmc_chan_read_submit(prtd->qmc_dai->qmc_chan, 172 prtd->period_ptr_submitted, prtd->period_size, 173 qmc_audio_pcm_read_complete, prtd); 174 if (ret) { 175 dev_err(component->dev, "read_submit failed %d\n", 176 ret); 177 return ret; 178 } 179 180 /* ... prepare next one ... */ 181 prtd->period_ptr_submitted += prtd->period_size; 182 if (prtd->period_ptr_submitted >= prtd->dma_buffer_end) 183 prtd->period_ptr_submitted = prtd->dma_buffer_start; 184 185 /* ... and send it */ 186 ret = qmc_chan_read_submit(prtd->qmc_dai->qmc_chan, 187 prtd->period_ptr_submitted, prtd->period_size, 188 qmc_audio_pcm_read_complete, prtd); 189 if (ret) { 190 dev_err(component->dev, "write_submit failed %d\n", 191 ret); 192 return ret; 193 } 194 } 195 break; 196 197 case SNDRV_PCM_TRIGGER_RESUME: 198 case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: 199 break; 200 201 case SNDRV_PCM_TRIGGER_STOP: 202 case SNDRV_PCM_TRIGGER_SUSPEND: 203 case SNDRV_PCM_TRIGGER_PAUSE_PUSH: 204 break; 205 206 default: 207 return -EINVAL; 208 } 209 210 return 0; 211 } 212 213 static snd_pcm_uframes_t qmc_audio_pcm_pointer(struct snd_soc_component *component, 214 struct snd_pcm_substream *substream) 215 { 216 struct qmc_dai_prtd *prtd = substream->runtime->private_data; 217 218 return bytes_to_frames(substream->runtime, 219 prtd->period_ptr_ended - prtd->dma_buffer_start); 220 } 221 222 static int qmc_audio_of_xlate_dai_name(struct snd_soc_component *component, 223 const struct of_phandle_args *args, 224 const char **dai_name) 225 { 226 struct qmc_audio *qmc_audio = dev_get_drvdata(component->dev); 227 struct snd_soc_dai_driver *dai_driver; 228 int id = args->args[0]; 229 int i; 230 231 for (i = 0; i < qmc_audio->num_dais; i++) { 232 dai_driver = qmc_audio->dai_drivers + i; 233 if (dai_driver->id == id) { 234 *dai_name = dai_driver->name; 235 return 0; 236 } 237 } 238 239 return -EINVAL; 240 } 241 242 static const struct snd_pcm_hardware qmc_audio_pcm_hardware = { 243 .info = SNDRV_PCM_INFO_MMAP | 244 SNDRV_PCM_INFO_MMAP_VALID | 245 SNDRV_PCM_INFO_INTERLEAVED | 246 SNDRV_PCM_INFO_PAUSE, 247 .period_bytes_min = 32, 248 .period_bytes_max = 64*1024, 249 .periods_min = 2, 250 .periods_max = 2*1024, 251 .buffer_bytes_max = 64*1024, 252 }; 253 254 static int qmc_audio_pcm_open(struct snd_soc_component *component, 255 struct snd_pcm_substream *substream) 256 { 257 struct snd_pcm_runtime *runtime = substream->runtime; 258 struct qmc_dai_prtd *prtd; 259 int ret; 260 261 snd_soc_set_runtime_hwparams(substream, &qmc_audio_pcm_hardware); 262 263 /* ensure that buffer size is a multiple of period size */ 264 ret = snd_pcm_hw_constraint_integer(runtime, SNDRV_PCM_HW_PARAM_PERIODS); 265 if (ret < 0) 266 return ret; 267 268 prtd = kzalloc(sizeof(*prtd), GFP_KERNEL); 269 if (prtd == NULL) 270 return -ENOMEM; 271 272 runtime->private_data = prtd; 273 274 return 0; 275 } 276 277 static int qmc_audio_pcm_close(struct snd_soc_component *component, 278 struct snd_pcm_substream *substream) 279 { 280 struct qmc_dai_prtd *prtd = substream->runtime->private_data; 281 282 kfree(prtd); 283 return 0; 284 } 285 286 static const struct snd_soc_component_driver qmc_audio_soc_platform = { 287 .open = qmc_audio_pcm_open, 288 .close = qmc_audio_pcm_close, 289 .hw_params = qmc_audio_pcm_hw_params, 290 .trigger = qmc_audio_pcm_trigger, 291 .pointer = qmc_audio_pcm_pointer, 292 .pcm_construct = qmc_audio_pcm_construct, 293 .of_xlate_dai_name = qmc_audio_of_xlate_dai_name, 294 }; 295 296 static unsigned int qmc_dai_get_index(struct snd_soc_dai *dai) 297 { 298 struct qmc_audio *qmc_audio = snd_soc_dai_get_drvdata(dai); 299 300 return dai->driver - qmc_audio->dai_drivers; 301 } 302 303 static struct qmc_dai *qmc_dai_get_data(struct snd_soc_dai *dai) 304 { 305 struct qmc_audio *qmc_audio = snd_soc_dai_get_drvdata(dai); 306 unsigned int index; 307 308 index = qmc_dai_get_index(dai); 309 if (index > qmc_audio->num_dais) 310 return NULL; 311 312 return qmc_audio->dais + index; 313 } 314 315 /* 316 * The constraints for format/channel is to match with the number of 8bit 317 * time-slots available. 318 */ 319 static int qmc_dai_hw_rule_channels_by_format(struct qmc_dai *qmc_dai, 320 struct snd_pcm_hw_params *params, 321 unsigned int nb_ts) 322 { 323 struct snd_interval *c = hw_param_interval(params, SNDRV_PCM_HW_PARAM_CHANNELS); 324 snd_pcm_format_t format = params_format(params); 325 struct snd_interval ch = {0}; 326 327 switch (snd_pcm_format_physical_width(format)) { 328 case 8: 329 ch.max = nb_ts; 330 break; 331 case 16: 332 ch.max = nb_ts/2; 333 break; 334 case 32: 335 ch.max = nb_ts/4; 336 break; 337 case 64: 338 ch.max = nb_ts/8; 339 break; 340 default: 341 dev_err(qmc_dai->dev, "format physical width %u not supported\n", 342 snd_pcm_format_physical_width(format)); 343 return -EINVAL; 344 } 345 346 ch.min = ch.max ? 1 : 0; 347 348 return snd_interval_refine(c, &ch); 349 } 350 351 static int qmc_dai_hw_rule_playback_channels_by_format(struct snd_pcm_hw_params *params, 352 struct snd_pcm_hw_rule *rule) 353 { 354 struct qmc_dai *qmc_dai = rule->private; 355 356 return qmc_dai_hw_rule_channels_by_format(qmc_dai, params, qmc_dai->nb_tx_ts); 357 } 358 359 static int qmc_dai_hw_rule_capture_channels_by_format( 360 struct snd_pcm_hw_params *params, 361 struct snd_pcm_hw_rule *rule) 362 { 363 struct qmc_dai *qmc_dai = rule->private; 364 365 return qmc_dai_hw_rule_channels_by_format(qmc_dai, params, qmc_dai->nb_rx_ts); 366 } 367 368 static int qmc_dai_hw_rule_format_by_channels(struct qmc_dai *qmc_dai, 369 struct snd_pcm_hw_params *params, 370 unsigned int nb_ts) 371 { 372 struct snd_mask *f_old = hw_param_mask(params, SNDRV_PCM_HW_PARAM_FORMAT); 373 unsigned int channels = params_channels(params); 374 unsigned int slot_width; 375 struct snd_mask f_new; 376 unsigned int i; 377 378 if (!channels || channels > nb_ts) { 379 dev_err(qmc_dai->dev, "channels %u not supported\n", 380 nb_ts); 381 return -EINVAL; 382 } 383 384 slot_width = (nb_ts / channels) * 8; 385 386 snd_mask_none(&f_new); 387 for (i = 0; i <= SNDRV_PCM_FORMAT_LAST; i++) { 388 if (snd_mask_test(f_old, i)) { 389 if (snd_pcm_format_physical_width(i) <= slot_width) 390 snd_mask_set(&f_new, i); 391 } 392 } 393 394 return snd_mask_refine(f_old, &f_new); 395 } 396 397 static int qmc_dai_hw_rule_playback_format_by_channels( 398 struct snd_pcm_hw_params *params, 399 struct snd_pcm_hw_rule *rule) 400 { 401 struct qmc_dai *qmc_dai = rule->private; 402 403 return qmc_dai_hw_rule_format_by_channels(qmc_dai, params, qmc_dai->nb_tx_ts); 404 } 405 406 static int qmc_dai_hw_rule_capture_format_by_channels( 407 struct snd_pcm_hw_params *params, 408 struct snd_pcm_hw_rule *rule) 409 { 410 struct qmc_dai *qmc_dai = rule->private; 411 412 return qmc_dai_hw_rule_format_by_channels(qmc_dai, params, qmc_dai->nb_rx_ts); 413 } 414 415 static int qmc_dai_startup(struct snd_pcm_substream *substream, 416 struct snd_soc_dai *dai) 417 { 418 struct qmc_dai_prtd *prtd = substream->runtime->private_data; 419 snd_pcm_hw_rule_func_t hw_rule_channels_by_format; 420 snd_pcm_hw_rule_func_t hw_rule_format_by_channels; 421 struct qmc_dai *qmc_dai; 422 unsigned int frame_bits; 423 int ret; 424 425 qmc_dai = qmc_dai_get_data(dai); 426 if (!qmc_dai) { 427 dev_err(dai->dev, "Invalid dai\n"); 428 return -EINVAL; 429 } 430 431 prtd->qmc_dai = qmc_dai; 432 433 if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) { 434 hw_rule_channels_by_format = qmc_dai_hw_rule_capture_channels_by_format; 435 hw_rule_format_by_channels = qmc_dai_hw_rule_capture_format_by_channels; 436 frame_bits = qmc_dai->nb_rx_ts * 8; 437 } else { 438 hw_rule_channels_by_format = qmc_dai_hw_rule_playback_channels_by_format; 439 hw_rule_format_by_channels = qmc_dai_hw_rule_playback_format_by_channels; 440 frame_bits = qmc_dai->nb_tx_ts * 8; 441 } 442 443 ret = snd_pcm_hw_rule_add(substream->runtime, 0, SNDRV_PCM_HW_PARAM_CHANNELS, 444 hw_rule_channels_by_format, qmc_dai, 445 SNDRV_PCM_HW_PARAM_FORMAT, -1); 446 if (ret) { 447 dev_err(dai->dev, "Failed to add channels rule (%d)\n", ret); 448 return ret; 449 } 450 451 ret = snd_pcm_hw_rule_add(substream->runtime, 0, SNDRV_PCM_HW_PARAM_FORMAT, 452 hw_rule_format_by_channels, qmc_dai, 453 SNDRV_PCM_HW_PARAM_CHANNELS, -1); 454 if (ret) { 455 dev_err(dai->dev, "Failed to add format rule (%d)\n", ret); 456 return ret; 457 } 458 459 ret = snd_pcm_hw_constraint_single(substream->runtime, 460 SNDRV_PCM_HW_PARAM_FRAME_BITS, 461 frame_bits); 462 if (ret < 0) { 463 dev_err(dai->dev, "Failed to add frame_bits constraint (%d)\n", ret); 464 return ret; 465 } 466 467 return 0; 468 } 469 470 static int qmc_dai_hw_params(struct snd_pcm_substream *substream, 471 struct snd_pcm_hw_params *params, 472 struct snd_soc_dai *dai) 473 { 474 struct qmc_chan_param chan_param = {0}; 475 struct qmc_dai *qmc_dai; 476 int ret; 477 478 qmc_dai = qmc_dai_get_data(dai); 479 if (!qmc_dai) { 480 dev_err(dai->dev, "Invalid dai\n"); 481 return -EINVAL; 482 } 483 484 if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) { 485 chan_param.mode = QMC_TRANSPARENT; 486 chan_param.transp.max_rx_buf_size = params_period_bytes(params); 487 ret = qmc_chan_set_param(qmc_dai->qmc_chan, &chan_param); 488 if (ret) { 489 dev_err(dai->dev, "set param failed %d\n", 490 ret); 491 return ret; 492 } 493 } 494 495 return 0; 496 } 497 498 static int qmc_dai_trigger(struct snd_pcm_substream *substream, int cmd, 499 struct snd_soc_dai *dai) 500 { 501 struct qmc_dai *qmc_dai; 502 int direction; 503 int ret; 504 505 qmc_dai = qmc_dai_get_data(dai); 506 if (!qmc_dai) { 507 dev_err(dai->dev, "Invalid dai\n"); 508 return -EINVAL; 509 } 510 511 direction = (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) ? 512 QMC_CHAN_WRITE : QMC_CHAN_READ; 513 514 switch (cmd) { 515 case SNDRV_PCM_TRIGGER_START: 516 case SNDRV_PCM_TRIGGER_RESUME: 517 case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: 518 ret = qmc_chan_start(qmc_dai->qmc_chan, direction); 519 if (ret) 520 return ret; 521 break; 522 523 case SNDRV_PCM_TRIGGER_STOP: 524 ret = qmc_chan_stop(qmc_dai->qmc_chan, direction); 525 if (ret) 526 return ret; 527 ret = qmc_chan_reset(qmc_dai->qmc_chan, direction); 528 if (ret) 529 return ret; 530 break; 531 532 case SNDRV_PCM_TRIGGER_SUSPEND: 533 case SNDRV_PCM_TRIGGER_PAUSE_PUSH: 534 ret = qmc_chan_stop(qmc_dai->qmc_chan, direction); 535 if (ret) 536 return ret; 537 break; 538 539 default: 540 return -EINVAL; 541 } 542 543 return 0; 544 } 545 546 static const struct snd_soc_dai_ops qmc_dai_ops = { 547 .startup = qmc_dai_startup, 548 .trigger = qmc_dai_trigger, 549 .hw_params = qmc_dai_hw_params, 550 }; 551 552 static u64 qmc_audio_formats(u8 nb_ts) 553 { 554 u64 formats; 555 unsigned int chan_width; 556 unsigned int format_width; 557 int i; 558 559 if (!nb_ts) 560 return 0; 561 562 formats = 0; 563 chan_width = nb_ts * 8; 564 for (i = 0; i <= SNDRV_PCM_FORMAT_LAST; i++) { 565 /* 566 * Support format other than little-endian (ie big-endian or 567 * without endianness such as 8bit formats) 568 */ 569 if (snd_pcm_format_little_endian(i) == 1) 570 continue; 571 572 /* Support physical width multiple of 8bit */ 573 format_width = snd_pcm_format_physical_width(i); 574 if (format_width == 0 || format_width % 8) 575 continue; 576 577 /* 578 * And support physical width that can fit N times in the 579 * channel 580 */ 581 if (format_width > chan_width || chan_width % format_width) 582 continue; 583 584 formats |= (1ULL << i); 585 } 586 return formats; 587 } 588 589 static int qmc_audio_dai_parse(struct qmc_audio *qmc_audio, struct device_node *np, 590 struct qmc_dai *qmc_dai, struct snd_soc_dai_driver *qmc_soc_dai_driver) 591 { 592 struct qmc_chan_info info; 593 u32 val; 594 int ret; 595 596 qmc_dai->dev = qmc_audio->dev; 597 598 ret = of_property_read_u32(np, "reg", &val); 599 if (ret) { 600 dev_err(qmc_audio->dev, "%pOF: failed to read reg\n", np); 601 return ret; 602 } 603 qmc_dai->id = val; 604 605 qmc_dai->name = devm_kasprintf(qmc_audio->dev, GFP_KERNEL, "%s.%d", 606 np->parent->name, qmc_dai->id); 607 608 qmc_dai->qmc_chan = devm_qmc_chan_get_byphandle(qmc_audio->dev, np, 609 "fsl,qmc-chan"); 610 if (IS_ERR(qmc_dai->qmc_chan)) { 611 ret = PTR_ERR(qmc_dai->qmc_chan); 612 return dev_err_probe(qmc_audio->dev, ret, 613 "dai %d get QMC channel failed\n", qmc_dai->id); 614 } 615 616 qmc_soc_dai_driver->id = qmc_dai->id; 617 qmc_soc_dai_driver->name = qmc_dai->name; 618 619 ret = qmc_chan_get_info(qmc_dai->qmc_chan, &info); 620 if (ret) { 621 dev_err(qmc_audio->dev, "dai %d get QMC channel info failed %d\n", 622 qmc_dai->id, ret); 623 return ret; 624 } 625 dev_info(qmc_audio->dev, "dai %d QMC channel mode %d, nb_tx_ts %u, nb_rx_ts %u\n", 626 qmc_dai->id, info.mode, info.nb_tx_ts, info.nb_rx_ts); 627 628 if (info.mode != QMC_TRANSPARENT) { 629 dev_err(qmc_audio->dev, "dai %d QMC chan mode %d is not QMC_TRANSPARENT\n", 630 qmc_dai->id, info.mode); 631 return -EINVAL; 632 } 633 qmc_dai->nb_tx_ts = info.nb_tx_ts; 634 qmc_dai->nb_rx_ts = info.nb_rx_ts; 635 636 qmc_soc_dai_driver->playback.channels_min = 0; 637 qmc_soc_dai_driver->playback.channels_max = 0; 638 if (qmc_dai->nb_tx_ts) { 639 qmc_soc_dai_driver->playback.channels_min = 1; 640 qmc_soc_dai_driver->playback.channels_max = qmc_dai->nb_tx_ts; 641 } 642 qmc_soc_dai_driver->playback.formats = qmc_audio_formats(qmc_dai->nb_tx_ts); 643 644 qmc_soc_dai_driver->capture.channels_min = 0; 645 qmc_soc_dai_driver->capture.channels_max = 0; 646 if (qmc_dai->nb_rx_ts) { 647 qmc_soc_dai_driver->capture.channels_min = 1; 648 qmc_soc_dai_driver->capture.channels_max = qmc_dai->nb_rx_ts; 649 } 650 qmc_soc_dai_driver->capture.formats = qmc_audio_formats(qmc_dai->nb_rx_ts); 651 652 qmc_soc_dai_driver->playback.rates = snd_pcm_rate_to_rate_bit(info.tx_fs_rate); 653 qmc_soc_dai_driver->playback.rate_min = info.tx_fs_rate; 654 qmc_soc_dai_driver->playback.rate_max = info.tx_fs_rate; 655 qmc_soc_dai_driver->capture.rates = snd_pcm_rate_to_rate_bit(info.rx_fs_rate); 656 qmc_soc_dai_driver->capture.rate_min = info.rx_fs_rate; 657 qmc_soc_dai_driver->capture.rate_max = info.rx_fs_rate; 658 659 qmc_soc_dai_driver->ops = &qmc_dai_ops; 660 661 return 0; 662 } 663 664 static int qmc_audio_probe(struct platform_device *pdev) 665 { 666 struct device_node *np = pdev->dev.of_node; 667 struct qmc_audio *qmc_audio; 668 struct device_node *child; 669 unsigned int i; 670 int ret; 671 672 qmc_audio = devm_kzalloc(&pdev->dev, sizeof(*qmc_audio), GFP_KERNEL); 673 if (!qmc_audio) 674 return -ENOMEM; 675 676 qmc_audio->dev = &pdev->dev; 677 678 qmc_audio->num_dais = of_get_available_child_count(np); 679 if (qmc_audio->num_dais) { 680 qmc_audio->dais = devm_kcalloc(&pdev->dev, qmc_audio->num_dais, 681 sizeof(*qmc_audio->dais), 682 GFP_KERNEL); 683 if (!qmc_audio->dais) 684 return -ENOMEM; 685 686 qmc_audio->dai_drivers = devm_kcalloc(&pdev->dev, qmc_audio->num_dais, 687 sizeof(*qmc_audio->dai_drivers), 688 GFP_KERNEL); 689 if (!qmc_audio->dai_drivers) 690 return -ENOMEM; 691 } 692 693 i = 0; 694 for_each_available_child_of_node(np, child) { 695 ret = qmc_audio_dai_parse(qmc_audio, child, 696 qmc_audio->dais + i, 697 qmc_audio->dai_drivers + i); 698 if (ret) { 699 of_node_put(child); 700 return ret; 701 } 702 i++; 703 } 704 705 706 platform_set_drvdata(pdev, qmc_audio); 707 708 ret = devm_snd_soc_register_component(qmc_audio->dev, 709 &qmc_audio_soc_platform, 710 qmc_audio->dai_drivers, 711 qmc_audio->num_dais); 712 if (ret) 713 return ret; 714 715 return 0; 716 } 717 718 static const struct of_device_id qmc_audio_id_table[] = { 719 { .compatible = "fsl,qmc-audio" }, 720 {} /* sentinel */ 721 }; 722 MODULE_DEVICE_TABLE(of, qmc_audio_id_table); 723 724 static struct platform_driver qmc_audio_driver = { 725 .driver = { 726 .name = "fsl-qmc-audio", 727 .of_match_table = of_match_ptr(qmc_audio_id_table), 728 }, 729 .probe = qmc_audio_probe, 730 }; 731 module_platform_driver(qmc_audio_driver); 732 733 MODULE_AUTHOR("Herve Codina <herve.codina@bootlin.com>"); 734 MODULE_DESCRIPTION("CPM/QE QMC audio driver"); 735 MODULE_LICENSE("GPL"); 736