1 // SPDX-License-Identifier: GPL-2.0 2 // 3 // Copyright (C) 2014-2016 Freescale Semiconductor, Inc. 4 // Copyright (C) 2019-2024 NXP 5 // 6 // Freescale ASRC Memory to Memory (M2M) driver 7 8 #include <linux/dma/imx-dma.h> 9 #include <linux/dma-buf.h> 10 #include <linux/dma-mapping.h> 11 #include <linux/pm_runtime.h> 12 #include <sound/asound.h> 13 #include <sound/dmaengine_pcm.h> 14 #include <sound/initval.h> 15 16 #include "fsl_asrc_common.h" 17 18 #define DIR_STR(dir) (dir) == IN ? "in" : "out" 19 20 #define ASRC_xPUT_DMA_CALLBACK(dir) \ 21 (((dir) == IN) ? asrc_input_dma_callback \ 22 : asrc_output_dma_callback) 23 24 /* Maximum output and capture buffer size */ 25 #define ASRC_M2M_BUFFER_SIZE (512 * 1024) 26 27 /* Maximum output and capture period size */ 28 #define ASRC_M2M_PERIOD_SIZE (48 * 1024) 29 30 /* dma complete callback */ 31 static void asrc_input_dma_callback(void *data) 32 { 33 struct fsl_asrc_pair *pair = (struct fsl_asrc_pair *)data; 34 35 complete(&pair->complete[IN]); 36 } 37 38 /* dma complete callback */ 39 static void asrc_output_dma_callback(void *data) 40 { 41 struct fsl_asrc_pair *pair = (struct fsl_asrc_pair *)data; 42 43 complete(&pair->complete[OUT]); 44 } 45 46 /** 47 *asrc_read_last_fifo: read all the remaining data from FIFO 48 *@pair: Structure pointer of fsl_asrc_pair 49 *@dma_vaddr: virtual address of capture buffer 50 *@length: payload length of capture buffer 51 */ 52 static void asrc_read_last_fifo(struct fsl_asrc_pair *pair, void *dma_vaddr, u32 *length) 53 { 54 struct fsl_asrc *asrc = pair->asrc; 55 enum asrc_pair_index index = pair->index; 56 u32 i, reg, size, t_size = 0, width; 57 u32 *reg32 = NULL; 58 u16 *reg16 = NULL; 59 u8 *reg24 = NULL; 60 61 width = snd_pcm_format_physical_width(pair->sample_format[OUT]); 62 if (width == 32) 63 reg32 = dma_vaddr + *length; 64 else if (width == 16) 65 reg16 = dma_vaddr + *length; 66 else 67 reg24 = dma_vaddr + *length; 68 retry: 69 size = asrc->get_output_fifo_size(pair); 70 if (size + *length > ASRC_M2M_BUFFER_SIZE) 71 goto end; 72 73 for (i = 0; i < size * pair->channels; i++) { 74 regmap_read(asrc->regmap, asrc->get_fifo_addr(OUT, index), ®); 75 if (reg32) { 76 *reg32++ = reg; 77 } else if (reg16) { 78 *reg16++ = (u16)reg; 79 } else { 80 *reg24++ = (u8)reg; 81 *reg24++ = (u8)(reg >> 8); 82 *reg24++ = (u8)(reg >> 16); 83 } 84 } 85 t_size += size; 86 87 /* In case there is data left in FIFO */ 88 if (size) 89 goto retry; 90 end: 91 /* Update payload length */ 92 if (reg32) 93 *length += t_size * pair->channels * 4; 94 else if (reg16) 95 *length += t_size * pair->channels * 2; 96 else 97 *length += t_size * pair->channels * 3; 98 } 99 100 /* config dma channel */ 101 static int asrc_dmaconfig(struct fsl_asrc_pair *pair, 102 struct dma_chan *chan, 103 u32 dma_addr, dma_addr_t buf_addr, u32 buf_len, 104 int dir, int width) 105 { 106 struct fsl_asrc *asrc = pair->asrc; 107 struct device *dev = &asrc->pdev->dev; 108 struct dma_slave_config slave_config; 109 enum dma_slave_buswidth buswidth; 110 unsigned int sg_len, max_period_size; 111 struct scatterlist *sg; 112 int ret, i; 113 114 switch (width) { 115 case 8: 116 buswidth = DMA_SLAVE_BUSWIDTH_1_BYTE; 117 break; 118 case 16: 119 buswidth = DMA_SLAVE_BUSWIDTH_2_BYTES; 120 break; 121 case 24: 122 buswidth = DMA_SLAVE_BUSWIDTH_3_BYTES; 123 break; 124 case 32: 125 buswidth = DMA_SLAVE_BUSWIDTH_4_BYTES; 126 break; 127 default: 128 dev_err(dev, "invalid word width\n"); 129 return -EINVAL; 130 } 131 132 memset(&slave_config, 0, sizeof(slave_config)); 133 if (dir == IN) { 134 slave_config.direction = DMA_MEM_TO_DEV; 135 slave_config.dst_addr = dma_addr; 136 slave_config.dst_addr_width = buswidth; 137 slave_config.dst_maxburst = asrc->m2m_get_maxburst(IN, pair); 138 } else { 139 slave_config.direction = DMA_DEV_TO_MEM; 140 slave_config.src_addr = dma_addr; 141 slave_config.src_addr_width = buswidth; 142 slave_config.src_maxburst = asrc->m2m_get_maxburst(OUT, pair); 143 } 144 145 ret = dmaengine_slave_config(chan, &slave_config); 146 if (ret) { 147 dev_err(dev, "failed to config dmaengine for %s task: %d\n", 148 DIR_STR(dir), ret); 149 return -EINVAL; 150 } 151 152 max_period_size = rounddown(ASRC_M2M_PERIOD_SIZE, width * pair->channels / 8); 153 /* scatter gather mode */ 154 sg_len = buf_len / max_period_size; 155 if (buf_len % max_period_size) 156 sg_len += 1; 157 158 sg = kmalloc_array(sg_len, sizeof(*sg), GFP_KERNEL); 159 if (!sg) 160 return -ENOMEM; 161 162 sg_init_table(sg, sg_len); 163 for (i = 0; i < (sg_len - 1); i++) { 164 sg_dma_address(&sg[i]) = buf_addr + i * max_period_size; 165 sg_dma_len(&sg[i]) = max_period_size; 166 } 167 sg_dma_address(&sg[i]) = buf_addr + i * max_period_size; 168 sg_dma_len(&sg[i]) = buf_len - i * max_period_size; 169 170 pair->desc[dir] = dmaengine_prep_slave_sg(chan, sg, sg_len, 171 slave_config.direction, 172 DMA_PREP_INTERRUPT); 173 kfree(sg); 174 if (!pair->desc[dir]) { 175 dev_err(dev, "failed to prepare dmaengine for %s task\n", DIR_STR(dir)); 176 return -EINVAL; 177 } 178 179 pair->desc[dir]->callback = ASRC_xPUT_DMA_CALLBACK(dir); 180 pair->desc[dir]->callback_param = pair; 181 182 return 0; 183 } 184 185 /* main function of converter */ 186 static void asrc_m2m_device_run(struct fsl_asrc_pair *pair, struct snd_compr_task_runtime *task) 187 { 188 struct fsl_asrc *asrc = pair->asrc; 189 struct device *dev = &asrc->pdev->dev; 190 enum asrc_pair_index index = pair->index; 191 struct snd_dma_buffer *src_buf, *dst_buf; 192 unsigned int in_buf_len; 193 unsigned int out_dma_len; 194 unsigned int width; 195 u32 fifo_addr; 196 int ret; 197 198 /* set ratio mod */ 199 if (asrc->m2m_set_ratio_mod) { 200 if (pair->ratio_mod_flag) { 201 asrc->m2m_set_ratio_mod(pair, pair->ratio_mod); 202 pair->ratio_mod_flag = false; 203 } 204 } 205 206 src_buf = &pair->dma_buffer[IN]; 207 dst_buf = &pair->dma_buffer[OUT]; 208 209 width = snd_pcm_format_physical_width(pair->sample_format[IN]); 210 fifo_addr = asrc->paddr + asrc->get_fifo_addr(IN, index); 211 212 in_buf_len = task->input_size; 213 214 if (in_buf_len < width * pair->channels / 8 || 215 in_buf_len > ASRC_M2M_BUFFER_SIZE || 216 in_buf_len % (width * pair->channels / 8)) { 217 dev_err(dev, "out buffer size is error: [%d]\n", in_buf_len); 218 goto end; 219 } 220 221 /* dma config for output dma channel */ 222 ret = asrc_dmaconfig(pair, 223 pair->dma_chan[IN], 224 fifo_addr, 225 src_buf->addr, 226 in_buf_len, IN, width); 227 if (ret) { 228 dev_err(dev, "out dma config error\n"); 229 goto end; 230 } 231 232 width = snd_pcm_format_physical_width(pair->sample_format[OUT]); 233 fifo_addr = asrc->paddr + asrc->get_fifo_addr(OUT, index); 234 out_dma_len = asrc->m2m_calc_out_len(pair, in_buf_len); 235 if (out_dma_len > 0 && out_dma_len <= ASRC_M2M_BUFFER_SIZE) { 236 /* dma config for capture dma channel */ 237 ret = asrc_dmaconfig(pair, 238 pair->dma_chan[OUT], 239 fifo_addr, 240 dst_buf->addr, 241 out_dma_len, OUT, width); 242 if (ret) { 243 dev_err(dev, "cap dma config error\n"); 244 goto end; 245 } 246 } else if (out_dma_len > ASRC_M2M_BUFFER_SIZE) { 247 dev_err(dev, "cap buffer size error\n"); 248 goto end; 249 } 250 251 reinit_completion(&pair->complete[IN]); 252 reinit_completion(&pair->complete[OUT]); 253 254 /* Submit DMA request */ 255 dmaengine_submit(pair->desc[IN]); 256 dma_async_issue_pending(pair->desc[IN]->chan); 257 if (out_dma_len > 0) { 258 dmaengine_submit(pair->desc[OUT]); 259 dma_async_issue_pending(pair->desc[OUT]->chan); 260 } 261 262 asrc->m2m_start(pair); 263 264 if (!wait_for_completion_interruptible_timeout(&pair->complete[IN], 10 * HZ)) { 265 dev_err(dev, "out DMA task timeout\n"); 266 goto end; 267 } 268 269 if (out_dma_len > 0) { 270 if (!wait_for_completion_interruptible_timeout(&pair->complete[OUT], 10 * HZ)) { 271 dev_err(dev, "cap DMA task timeout\n"); 272 goto end; 273 } 274 } 275 276 /* read the last words from FIFO */ 277 asrc_read_last_fifo(pair, dst_buf->area, &out_dma_len); 278 /* update payload length for capture */ 279 task->output_size = out_dma_len; 280 end: 281 return; 282 } 283 284 static int fsl_asrc_m2m_comp_open(struct snd_compr_stream *stream) 285 { 286 struct fsl_asrc *asrc = stream->private_data; 287 struct snd_compr_runtime *runtime = stream->runtime; 288 struct device *dev = &asrc->pdev->dev; 289 struct fsl_asrc_pair *pair; 290 int size, ret; 291 292 pair = kzalloc(sizeof(*pair) + asrc->pair_priv_size, GFP_KERNEL); 293 if (!pair) 294 return -ENOMEM; 295 296 pair->private = (void *)pair + sizeof(struct fsl_asrc_pair); 297 pair->asrc = asrc; 298 299 init_completion(&pair->complete[IN]); 300 init_completion(&pair->complete[OUT]); 301 302 runtime->private_data = pair; 303 304 size = ASRC_M2M_BUFFER_SIZE; 305 ret = snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, dev, size, &pair->dma_buffer[IN]); 306 if (ret) 307 goto error_alloc_in_buf; 308 309 ret = snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, dev, size, &pair->dma_buffer[OUT]); 310 if (ret) 311 goto error_alloc_out_buf; 312 313 ret = pm_runtime_get_sync(dev); 314 if (ret < 0) { 315 dev_err(dev, "Failed to power up asrc\n"); 316 goto err_pm_runtime; 317 } 318 319 return 0; 320 321 err_pm_runtime: 322 snd_dma_free_pages(&pair->dma_buffer[OUT]); 323 error_alloc_out_buf: 324 snd_dma_free_pages(&pair->dma_buffer[IN]); 325 error_alloc_in_buf: 326 kfree(pair); 327 return ret; 328 } 329 330 static int fsl_asrc_m2m_comp_release(struct snd_compr_stream *stream) 331 { 332 struct fsl_asrc *asrc = stream->private_data; 333 struct snd_compr_runtime *runtime = stream->runtime; 334 struct fsl_asrc_pair *pair = runtime->private_data; 335 struct device *dev = &asrc->pdev->dev; 336 337 pm_runtime_put_sync(dev); 338 339 snd_dma_free_pages(&pair->dma_buffer[IN]); 340 snd_dma_free_pages(&pair->dma_buffer[OUT]); 341 342 kfree(runtime->private_data); 343 344 return 0; 345 } 346 347 static int fsl_asrc_m2m_comp_set_params(struct snd_compr_stream *stream, 348 struct snd_compr_params *params) 349 { 350 struct fsl_asrc *asrc = stream->private_data; 351 struct snd_compr_runtime *runtime = stream->runtime; 352 struct fsl_asrc_pair *pair = runtime->private_data; 353 struct fsl_asrc_m2m_cap cap; 354 int ret, i; 355 356 ret = asrc->m2m_get_cap(&cap); 357 if (ret) 358 return -EINVAL; 359 360 if (pcm_format_to_bits((__force snd_pcm_format_t)params->codec.format) & cap.fmt_in) 361 pair->sample_format[IN] = (__force snd_pcm_format_t)params->codec.format; 362 else 363 return -EINVAL; 364 365 if (pcm_format_to_bits((__force snd_pcm_format_t)params->codec.pcm_format) & cap.fmt_out) 366 pair->sample_format[OUT] = (__force snd_pcm_format_t)params->codec.pcm_format; 367 else 368 return -EINVAL; 369 370 /* check input rate is in scope */ 371 for (i = 0; i < cap.rate_in_count; i++) 372 if (params->codec.sample_rate == cap.rate_in[i]) { 373 pair->rate[IN] = params->codec.sample_rate; 374 break; 375 } 376 if (i == cap.rate_in_count) 377 return -EINVAL; 378 379 /* check output rate is in scope */ 380 for (i = 0; i < cap.rate_out_count; i++) 381 if (params->codec.options.src_d.out_sample_rate == cap.rate_out[i]) { 382 pair->rate[OUT] = params->codec.options.src_d.out_sample_rate; 383 break; 384 } 385 if (i == cap.rate_out_count) 386 return -EINVAL; 387 388 if (params->codec.ch_in != params->codec.ch_out || 389 params->codec.ch_in < cap.chan_min || 390 params->codec.ch_in > cap.chan_max) 391 return -EINVAL; 392 393 pair->channels = params->codec.ch_in; 394 pair->buf_len[IN] = params->buffer.fragment_size; 395 pair->buf_len[OUT] = params->buffer.fragment_size; 396 397 return 0; 398 } 399 400 static int fsl_asrc_m2m_mmap(struct dma_buf *dmabuf, struct vm_area_struct *vma) 401 { 402 struct snd_dma_buffer *dmab = dmabuf->priv; 403 404 return snd_dma_buffer_mmap(dmab, vma); 405 } 406 407 static struct sg_table *fsl_asrc_m2m_map_dma_buf(struct dma_buf_attachment *attachment, 408 enum dma_data_direction direction) 409 { 410 struct snd_dma_buffer *dmab = attachment->dmabuf->priv; 411 struct sg_table *sgt; 412 413 sgt = kmalloc(sizeof(*sgt), GFP_KERNEL); 414 if (!sgt) 415 return NULL; 416 417 if (dma_get_sgtable(attachment->dev, sgt, dmab->area, dmab->addr, dmab->bytes) < 0) 418 goto free; 419 420 if (dma_map_sgtable(attachment->dev, sgt, direction, 0)) 421 goto free; 422 423 return sgt; 424 425 free: 426 sg_free_table(sgt); 427 kfree(sgt); 428 return NULL; 429 } 430 431 static void fsl_asrc_m2m_unmap_dma_buf(struct dma_buf_attachment *attachment, 432 struct sg_table *table, 433 enum dma_data_direction direction) 434 { 435 dma_unmap_sgtable(attachment->dev, table, direction, 0); 436 } 437 438 static void fsl_asrc_m2m_release(struct dma_buf *dmabuf) 439 { 440 /* buffer is released by fsl_asrc_m2m_comp_release() */ 441 } 442 443 static const struct dma_buf_ops fsl_asrc_m2m_dma_buf_ops = { 444 .mmap = fsl_asrc_m2m_mmap, 445 .map_dma_buf = fsl_asrc_m2m_map_dma_buf, 446 .unmap_dma_buf = fsl_asrc_m2m_unmap_dma_buf, 447 .release = fsl_asrc_m2m_release, 448 }; 449 450 static int fsl_asrc_m2m_comp_task_create(struct snd_compr_stream *stream, 451 struct snd_compr_task_runtime *task) 452 { 453 DEFINE_DMA_BUF_EXPORT_INFO(exp_info_in); 454 DEFINE_DMA_BUF_EXPORT_INFO(exp_info_out); 455 struct fsl_asrc *asrc = stream->private_data; 456 struct snd_compr_runtime *runtime = stream->runtime; 457 struct fsl_asrc_pair *pair = runtime->private_data; 458 struct device *dev = &asrc->pdev->dev; 459 int ret; 460 461 exp_info_in.ops = &fsl_asrc_m2m_dma_buf_ops; 462 exp_info_in.size = ASRC_M2M_BUFFER_SIZE; 463 exp_info_in.flags = O_RDWR; 464 exp_info_in.priv = &pair->dma_buffer[IN]; 465 task->input = dma_buf_export(&exp_info_in); 466 if (IS_ERR(task->input)) { 467 ret = PTR_ERR(task->input); 468 return ret; 469 } 470 471 exp_info_out.ops = &fsl_asrc_m2m_dma_buf_ops; 472 exp_info_out.size = ASRC_M2M_BUFFER_SIZE; 473 exp_info_out.flags = O_RDWR; 474 exp_info_out.priv = &pair->dma_buffer[OUT]; 475 task->output = dma_buf_export(&exp_info_out); 476 if (IS_ERR(task->output)) { 477 ret = PTR_ERR(task->output); 478 return ret; 479 } 480 481 /* Request asrc pair/context */ 482 ret = asrc->request_pair(pair->channels, pair); 483 if (ret) { 484 dev_err(dev, "failed to request pair: %d\n", ret); 485 goto err_request_pair; 486 } 487 488 ret = asrc->m2m_prepare(pair); 489 if (ret) { 490 dev_err(dev, "failed to start pair part one: %d\n", ret); 491 goto err_start_part_one; 492 } 493 494 /* Request dma channels */ 495 pair->dma_chan[IN] = asrc->get_dma_channel(pair, IN); 496 if (!pair->dma_chan[IN]) { 497 dev_err(dev, "[ctx%d] failed to get input DMA channel\n", pair->index); 498 ret = -EBUSY; 499 goto err_dma_channel_in; 500 } 501 502 pair->dma_chan[OUT] = asrc->get_dma_channel(pair, OUT); 503 if (!pair->dma_chan[OUT]) { 504 dev_err(dev, "[ctx%d] failed to get output DMA channel\n", pair->index); 505 ret = -EBUSY; 506 goto err_dma_channel_out; 507 } 508 509 return 0; 510 511 err_dma_channel_out: 512 dma_release_channel(pair->dma_chan[IN]); 513 err_dma_channel_in: 514 if (asrc->m2m_unprepare) 515 asrc->m2m_unprepare(pair); 516 err_start_part_one: 517 asrc->release_pair(pair); 518 err_request_pair: 519 return ret; 520 } 521 522 static int fsl_asrc_m2m_comp_task_start(struct snd_compr_stream *stream, 523 struct snd_compr_task_runtime *task) 524 { 525 struct snd_compr_runtime *runtime = stream->runtime; 526 struct fsl_asrc_pair *pair = runtime->private_data; 527 528 asrc_m2m_device_run(pair, task); 529 530 return 0; 531 } 532 533 static int fsl_asrc_m2m_comp_task_stop(struct snd_compr_stream *stream, 534 struct snd_compr_task_runtime *task) 535 { 536 return 0; 537 } 538 539 static int fsl_asrc_m2m_comp_task_free(struct snd_compr_stream *stream, 540 struct snd_compr_task_runtime *task) 541 { 542 struct fsl_asrc *asrc = stream->private_data; 543 struct snd_compr_runtime *runtime = stream->runtime; 544 struct fsl_asrc_pair *pair = runtime->private_data; 545 546 /* Stop & release pair/context */ 547 if (asrc->m2m_stop) 548 asrc->m2m_stop(pair); 549 550 if (asrc->m2m_unprepare) 551 asrc->m2m_unprepare(pair); 552 asrc->release_pair(pair); 553 554 /* Release dma channel */ 555 if (pair->dma_chan[IN]) 556 dma_release_channel(pair->dma_chan[IN]); 557 if (pair->dma_chan[OUT]) 558 dma_release_channel(pair->dma_chan[OUT]); 559 560 return 0; 561 } 562 563 static int fsl_asrc_m2m_get_caps(struct snd_compr_stream *cstream, 564 struct snd_compr_caps *caps) 565 { 566 caps->num_codecs = 1; 567 caps->min_fragment_size = 4096; 568 caps->max_fragment_size = 4096; 569 caps->min_fragments = 1; 570 caps->max_fragments = 1; 571 caps->codecs[0] = SND_AUDIOCODEC_PCM; 572 573 return 0; 574 } 575 576 static int fsl_asrc_m2m_fill_codec_caps(struct fsl_asrc *asrc, 577 struct snd_compr_codec_caps *codec) 578 { 579 struct fsl_asrc_m2m_cap cap; 580 snd_pcm_format_t k; 581 int j = 0; 582 int ret; 583 584 ret = asrc->m2m_get_cap(&cap); 585 if (ret) 586 return -EINVAL; 587 588 pcm_for_each_format(k) { 589 if (pcm_format_to_bits(k) & cap.fmt_in) { 590 codec->descriptor[j].max_ch = cap.chan_max; 591 memcpy(codec->descriptor[j].sample_rates, 592 cap.rate_in, 593 cap.rate_in_count * sizeof(__u32)); 594 codec->descriptor[j].num_sample_rates = cap.rate_in_count; 595 codec->descriptor[j].formats = (__force __u32)k; 596 codec->descriptor[j].pcm_formats = cap.fmt_out; 597 codec->descriptor[j].src.out_sample_rate_min = cap.rate_out[0]; 598 codec->descriptor[j].src.out_sample_rate_max = 599 cap.rate_out[cap.rate_out_count - 1]; 600 j++; 601 } 602 } 603 604 codec->codec = SND_AUDIOCODEC_PCM; 605 codec->num_descriptors = j; 606 return 0; 607 } 608 609 static int fsl_asrc_m2m_get_codec_caps(struct snd_compr_stream *stream, 610 struct snd_compr_codec_caps *codec) 611 { 612 struct fsl_asrc *asrc = stream->private_data; 613 614 return fsl_asrc_m2m_fill_codec_caps(asrc, codec); 615 } 616 617 static struct snd_compr_ops fsl_asrc_m2m_compr_ops = { 618 .open = fsl_asrc_m2m_comp_open, 619 .free = fsl_asrc_m2m_comp_release, 620 .set_params = fsl_asrc_m2m_comp_set_params, 621 .get_caps = fsl_asrc_m2m_get_caps, 622 .get_codec_caps = fsl_asrc_m2m_get_codec_caps, 623 .task_create = fsl_asrc_m2m_comp_task_create, 624 .task_start = fsl_asrc_m2m_comp_task_start, 625 .task_stop = fsl_asrc_m2m_comp_task_stop, 626 .task_free = fsl_asrc_m2m_comp_task_free, 627 }; 628 629 int fsl_asrc_m2m_suspend(struct fsl_asrc *asrc) 630 { 631 struct fsl_asrc_pair *pair; 632 int i; 633 634 for (i = 0; i < PAIR_CTX_NUM; i++) { 635 pair = asrc->pair[i]; 636 if (!pair) 637 continue; 638 if (!completion_done(&pair->complete[IN])) { 639 if (pair->dma_chan[IN]) 640 dmaengine_terminate_all(pair->dma_chan[IN]); 641 asrc_input_dma_callback((void *)pair); 642 } 643 if (!completion_done(&pair->complete[OUT])) { 644 if (pair->dma_chan[OUT]) 645 dmaengine_terminate_all(pair->dma_chan[OUT]); 646 asrc_output_dma_callback((void *)pair); 647 } 648 649 if (asrc->m2m_pair_suspend) 650 asrc->m2m_pair_suspend(pair); 651 } 652 653 return 0; 654 } 655 EXPORT_SYMBOL_GPL(fsl_asrc_m2m_suspend); 656 657 int fsl_asrc_m2m_resume(struct fsl_asrc *asrc) 658 { 659 struct fsl_asrc_pair *pair; 660 int i; 661 662 for (i = 0; i < PAIR_CTX_NUM; i++) { 663 pair = asrc->pair[i]; 664 if (!pair) 665 continue; 666 if (asrc->m2m_pair_resume) 667 asrc->m2m_pair_resume(pair); 668 } 669 670 return 0; 671 } 672 EXPORT_SYMBOL_GPL(fsl_asrc_m2m_resume); 673 674 int fsl_asrc_m2m_init(struct fsl_asrc *asrc) 675 { 676 struct device *dev = &asrc->pdev->dev; 677 struct snd_card *card; 678 struct snd_compr *compr; 679 int ret; 680 681 ret = snd_card_new(dev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1, 682 THIS_MODULE, 0, &card); 683 if (ret < 0) 684 return ret; 685 686 strscpy(card->driver, "fsl-asrc-m2m", sizeof(card->driver)); 687 strscpy(card->shortname, "ASRC-M2M", sizeof(card->shortname)); 688 strscpy(card->longname, "ASRC-M2M", sizeof(card->shortname)); 689 690 asrc->card = card; 691 692 compr = devm_kzalloc(dev, sizeof(*compr), GFP_KERNEL); 693 if (!compr) { 694 ret = -ENOMEM; 695 goto err; 696 } 697 698 compr->ops = &fsl_asrc_m2m_compr_ops; 699 compr->private_data = asrc; 700 701 ret = snd_compress_new(card, 0, SND_COMPRESS_ACCEL, "ASRC M2M", compr); 702 if (ret < 0) 703 goto err; 704 705 ret = snd_card_register(card); 706 if (ret < 0) 707 goto err; 708 709 return 0; 710 err: 711 snd_card_free(card); 712 return ret; 713 } 714 EXPORT_SYMBOL_GPL(fsl_asrc_m2m_init); 715 716 void fsl_asrc_m2m_exit(struct fsl_asrc *asrc) 717 { 718 struct snd_card *card = asrc->card; 719 720 snd_card_free(card); 721 } 722 EXPORT_SYMBOL_GPL(fsl_asrc_m2m_exit); 723 724 MODULE_IMPORT_NS("DMA_BUF"); 725 MODULE_AUTHOR("Shengjiu Wang <Shengjiu.Wang@nxp.com>"); 726 MODULE_DESCRIPTION("Freescale ASRC M2M driver"); 727 MODULE_LICENSE("GPL"); 728