1 // SPDX-License-Identifier: GPL-2.0 2 // Copyright (c) 2011-2017, The Linux Foundation. All rights reserved. 3 // Copyright (c) 2018, Linaro Limited 4 5 #include <linux/init.h> 6 #include <linux/err.h> 7 #include <linux/module.h> 8 #include <linux/platform_device.h> 9 #include <linux/slab.h> 10 #include <sound/soc.h> 11 #include <sound/soc-dapm.h> 12 #include <sound/pcm.h> 13 #include <linux/spinlock.h> 14 #include <sound/compress_driver.h> 15 #include <asm/dma.h> 16 #include <linux/dma-mapping.h> 17 #include <linux/of_device.h> 18 #include <sound/pcm_params.h> 19 #include "q6asm.h" 20 #include "q6routing.h" 21 #include "q6dsp-errno.h" 22 23 #define DRV_NAME "q6asm-fe-dai" 24 25 #define PLAYBACK_MIN_NUM_PERIODS 2 26 #define PLAYBACK_MAX_NUM_PERIODS 8 27 #define PLAYBACK_MAX_PERIOD_SIZE 65536 28 #define PLAYBACK_MIN_PERIOD_SIZE 128 29 #define CAPTURE_MIN_NUM_PERIODS 2 30 #define CAPTURE_MAX_NUM_PERIODS 8 31 #define CAPTURE_MAX_PERIOD_SIZE 4096 32 #define CAPTURE_MIN_PERIOD_SIZE 320 33 #define SID_MASK_DEFAULT 0xF 34 35 /* Default values used if user space does not set */ 36 #define COMPR_PLAYBACK_MIN_FRAGMENT_SIZE (8 * 1024) 37 #define COMPR_PLAYBACK_MAX_FRAGMENT_SIZE (128 * 1024) 38 #define COMPR_PLAYBACK_MIN_NUM_FRAGMENTS (4) 39 #define COMPR_PLAYBACK_MAX_NUM_FRAGMENTS (16 * 4) 40 #define Q6ASM_DAI_TX_RX 0 41 #define Q6ASM_DAI_TX 1 42 #define Q6ASM_DAI_RX 2 43 44 enum stream_state { 45 Q6ASM_STREAM_IDLE = 0, 46 Q6ASM_STREAM_STOPPED, 47 Q6ASM_STREAM_RUNNING, 48 }; 49 50 struct q6asm_dai_rtd { 51 struct snd_pcm_substream *substream; 52 struct snd_compr_stream *cstream; 53 struct snd_compr_params codec_param; 54 struct snd_dma_buffer dma_buffer; 55 spinlock_t lock; 56 phys_addr_t phys; 57 unsigned int pcm_size; 58 unsigned int pcm_count; 59 unsigned int pcm_irq_pos; /* IRQ position */ 60 unsigned int periods; 61 unsigned int bytes_sent; 62 unsigned int bytes_received; 63 unsigned int copied_total; 64 uint16_t bits_per_sample; 65 uint16_t source; /* Encoding source bit mask */ 66 struct audio_client *audio_client; 67 uint16_t session_id; 68 enum stream_state state; 69 }; 70 71 struct q6asm_dai_data { 72 long long int sid; 73 }; 74 75 static struct snd_pcm_hardware q6asm_dai_hardware_capture = { 76 .info = (SNDRV_PCM_INFO_MMAP | 77 SNDRV_PCM_INFO_BLOCK_TRANSFER | 78 SNDRV_PCM_INFO_MMAP_VALID | 79 SNDRV_PCM_INFO_INTERLEAVED | 80 SNDRV_PCM_INFO_PAUSE | SNDRV_PCM_INFO_RESUME), 81 .formats = (SNDRV_PCM_FMTBIT_S16_LE | 82 SNDRV_PCM_FMTBIT_S24_LE), 83 .rates = SNDRV_PCM_RATE_8000_48000, 84 .rate_min = 8000, 85 .rate_max = 48000, 86 .channels_min = 1, 87 .channels_max = 4, 88 .buffer_bytes_max = CAPTURE_MAX_NUM_PERIODS * 89 CAPTURE_MAX_PERIOD_SIZE, 90 .period_bytes_min = CAPTURE_MIN_PERIOD_SIZE, 91 .period_bytes_max = CAPTURE_MAX_PERIOD_SIZE, 92 .periods_min = CAPTURE_MIN_NUM_PERIODS, 93 .periods_max = CAPTURE_MAX_NUM_PERIODS, 94 .fifo_size = 0, 95 }; 96 97 static struct snd_pcm_hardware q6asm_dai_hardware_playback = { 98 .info = (SNDRV_PCM_INFO_MMAP | 99 SNDRV_PCM_INFO_BLOCK_TRANSFER | 100 SNDRV_PCM_INFO_MMAP_VALID | 101 SNDRV_PCM_INFO_INTERLEAVED | 102 SNDRV_PCM_INFO_PAUSE | SNDRV_PCM_INFO_RESUME), 103 .formats = (SNDRV_PCM_FMTBIT_S16_LE | 104 SNDRV_PCM_FMTBIT_S24_LE), 105 .rates = SNDRV_PCM_RATE_8000_192000, 106 .rate_min = 8000, 107 .rate_max = 192000, 108 .channels_min = 1, 109 .channels_max = 8, 110 .buffer_bytes_max = (PLAYBACK_MAX_NUM_PERIODS * 111 PLAYBACK_MAX_PERIOD_SIZE), 112 .period_bytes_min = PLAYBACK_MIN_PERIOD_SIZE, 113 .period_bytes_max = PLAYBACK_MAX_PERIOD_SIZE, 114 .periods_min = PLAYBACK_MIN_NUM_PERIODS, 115 .periods_max = PLAYBACK_MAX_NUM_PERIODS, 116 .fifo_size = 0, 117 }; 118 119 #define Q6ASM_FEDAI_DRIVER(num) { \ 120 .playback = { \ 121 .stream_name = "MultiMedia"#num" Playback", \ 122 .rates = (SNDRV_PCM_RATE_8000_192000| \ 123 SNDRV_PCM_RATE_KNOT), \ 124 .formats = (SNDRV_PCM_FMTBIT_S16_LE | \ 125 SNDRV_PCM_FMTBIT_S24_LE), \ 126 .channels_min = 1, \ 127 .channels_max = 8, \ 128 .rate_min = 8000, \ 129 .rate_max = 192000, \ 130 }, \ 131 .capture = { \ 132 .stream_name = "MultiMedia"#num" Capture", \ 133 .rates = (SNDRV_PCM_RATE_8000_48000| \ 134 SNDRV_PCM_RATE_KNOT), \ 135 .formats = (SNDRV_PCM_FMTBIT_S16_LE | \ 136 SNDRV_PCM_FMTBIT_S24_LE), \ 137 .channels_min = 1, \ 138 .channels_max = 4, \ 139 .rate_min = 8000, \ 140 .rate_max = 48000, \ 141 }, \ 142 .name = "MultiMedia"#num, \ 143 .id = MSM_FRONTEND_DAI_MULTIMEDIA##num, \ 144 } 145 146 /* Conventional and unconventional sample rate supported */ 147 static unsigned int supported_sample_rates[] = { 148 8000, 11025, 12000, 16000, 22050, 24000, 32000, 44100, 48000, 149 88200, 96000, 176400, 192000 150 }; 151 152 static struct snd_pcm_hw_constraint_list constraints_sample_rates = { 153 .count = ARRAY_SIZE(supported_sample_rates), 154 .list = supported_sample_rates, 155 .mask = 0, 156 }; 157 158 static const struct snd_compr_codec_caps q6asm_compr_caps = { 159 .num_descriptors = 1, 160 .descriptor[0].max_ch = 2, 161 .descriptor[0].sample_rates = { 8000, 11025, 12000, 16000, 22050, 162 24000, 32000, 44100, 48000, 88200, 163 96000, 176400, 192000 }, 164 .descriptor[0].num_sample_rates = 13, 165 .descriptor[0].bit_rate[0] = 320, 166 .descriptor[0].bit_rate[1] = 128, 167 .descriptor[0].num_bitrates = 2, 168 .descriptor[0].profiles = 0, 169 .descriptor[0].modes = SND_AUDIOCHANMODE_MP3_STEREO, 170 .descriptor[0].formats = 0, 171 }; 172 173 static void event_handler(uint32_t opcode, uint32_t token, 174 uint32_t *payload, void *priv) 175 { 176 struct q6asm_dai_rtd *prtd = priv; 177 struct snd_pcm_substream *substream = prtd->substream; 178 179 switch (opcode) { 180 case ASM_CLIENT_EVENT_CMD_RUN_DONE: 181 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) 182 q6asm_write_async(prtd->audio_client, 183 prtd->pcm_count, 0, 0, NO_TIMESTAMP); 184 break; 185 case ASM_CLIENT_EVENT_CMD_EOS_DONE: 186 prtd->state = Q6ASM_STREAM_STOPPED; 187 break; 188 case ASM_CLIENT_EVENT_DATA_WRITE_DONE: { 189 prtd->pcm_irq_pos += prtd->pcm_count; 190 snd_pcm_period_elapsed(substream); 191 if (prtd->state == Q6ASM_STREAM_RUNNING) 192 q6asm_write_async(prtd->audio_client, 193 prtd->pcm_count, 0, 0, NO_TIMESTAMP); 194 195 break; 196 } 197 case ASM_CLIENT_EVENT_DATA_READ_DONE: 198 prtd->pcm_irq_pos += prtd->pcm_count; 199 snd_pcm_period_elapsed(substream); 200 if (prtd->state == Q6ASM_STREAM_RUNNING) 201 q6asm_read(prtd->audio_client); 202 203 break; 204 default: 205 break; 206 } 207 } 208 209 static int q6asm_dai_prepare(struct snd_pcm_substream *substream) 210 { 211 struct snd_pcm_runtime *runtime = substream->runtime; 212 struct snd_soc_pcm_runtime *soc_prtd = substream->private_data; 213 struct q6asm_dai_rtd *prtd = runtime->private_data; 214 struct snd_soc_component *c = snd_soc_rtdcom_lookup(soc_prtd, DRV_NAME); 215 struct q6asm_dai_data *pdata; 216 int ret, i; 217 218 pdata = snd_soc_component_get_drvdata(c); 219 if (!pdata) 220 return -EINVAL; 221 222 if (!prtd || !prtd->audio_client) { 223 pr_err("%s: private data null or audio client freed\n", 224 __func__); 225 return -EINVAL; 226 } 227 228 prtd->pcm_count = snd_pcm_lib_period_bytes(substream); 229 prtd->pcm_irq_pos = 0; 230 /* rate and channels are sent to audio driver */ 231 if (prtd->state) { 232 /* clear the previous setup if any */ 233 q6asm_cmd(prtd->audio_client, CMD_CLOSE); 234 q6asm_unmap_memory_regions(substream->stream, 235 prtd->audio_client); 236 q6routing_stream_close(soc_prtd->dai_link->id, 237 substream->stream); 238 } 239 240 ret = q6asm_map_memory_regions(substream->stream, prtd->audio_client, 241 prtd->phys, 242 (prtd->pcm_size / prtd->periods), 243 prtd->periods); 244 245 if (ret < 0) { 246 pr_err("Audio Start: Buffer Allocation failed rc = %d\n", 247 ret); 248 return -ENOMEM; 249 } 250 251 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { 252 ret = q6asm_open_write(prtd->audio_client, FORMAT_LINEAR_PCM, 253 prtd->bits_per_sample); 254 } else if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) { 255 ret = q6asm_open_read(prtd->audio_client, FORMAT_LINEAR_PCM, 256 prtd->bits_per_sample); 257 } 258 259 if (ret < 0) { 260 pr_err("%s: q6asm_open_write failed\n", __func__); 261 q6asm_audio_client_free(prtd->audio_client); 262 prtd->audio_client = NULL; 263 return -ENOMEM; 264 } 265 266 prtd->session_id = q6asm_get_session_id(prtd->audio_client); 267 ret = q6routing_stream_open(soc_prtd->dai_link->id, LEGACY_PCM_MODE, 268 prtd->session_id, substream->stream); 269 if (ret) { 270 pr_err("%s: stream reg failed ret:%d\n", __func__, ret); 271 return ret; 272 } 273 274 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { 275 ret = q6asm_media_format_block_multi_ch_pcm( 276 prtd->audio_client, runtime->rate, 277 runtime->channels, NULL, 278 prtd->bits_per_sample); 279 } else if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) { 280 ret = q6asm_enc_cfg_blk_pcm_format_support(prtd->audio_client, 281 runtime->rate, runtime->channels, 282 prtd->bits_per_sample); 283 284 /* Queue the buffers */ 285 for (i = 0; i < runtime->periods; i++) 286 q6asm_read(prtd->audio_client); 287 288 } 289 if (ret < 0) 290 pr_info("%s: CMD Format block failed\n", __func__); 291 292 prtd->state = Q6ASM_STREAM_RUNNING; 293 294 return 0; 295 } 296 297 static int q6asm_dai_trigger(struct snd_pcm_substream *substream, int cmd) 298 { 299 int ret = 0; 300 struct snd_pcm_runtime *runtime = substream->runtime; 301 struct q6asm_dai_rtd *prtd = runtime->private_data; 302 303 switch (cmd) { 304 case SNDRV_PCM_TRIGGER_START: 305 case SNDRV_PCM_TRIGGER_RESUME: 306 case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: 307 ret = q6asm_run_nowait(prtd->audio_client, 0, 0, 0); 308 break; 309 case SNDRV_PCM_TRIGGER_STOP: 310 prtd->state = Q6ASM_STREAM_STOPPED; 311 ret = q6asm_cmd_nowait(prtd->audio_client, CMD_EOS); 312 break; 313 case SNDRV_PCM_TRIGGER_SUSPEND: 314 case SNDRV_PCM_TRIGGER_PAUSE_PUSH: 315 ret = q6asm_cmd_nowait(prtd->audio_client, CMD_PAUSE); 316 break; 317 default: 318 ret = -EINVAL; 319 break; 320 } 321 322 return ret; 323 } 324 325 static int q6asm_dai_open(struct snd_pcm_substream *substream) 326 { 327 struct snd_pcm_runtime *runtime = substream->runtime; 328 struct snd_soc_pcm_runtime *soc_prtd = substream->private_data; 329 struct snd_soc_dai *cpu_dai = soc_prtd->cpu_dai; 330 struct snd_soc_component *c = snd_soc_rtdcom_lookup(soc_prtd, DRV_NAME); 331 struct q6asm_dai_rtd *prtd; 332 struct q6asm_dai_data *pdata; 333 struct device *dev = c->dev; 334 int ret = 0; 335 int stream_id; 336 337 stream_id = cpu_dai->driver->id; 338 339 pdata = snd_soc_component_get_drvdata(c); 340 if (!pdata) { 341 pr_err("Drv data not found ..\n"); 342 return -EINVAL; 343 } 344 345 prtd = kzalloc(sizeof(struct q6asm_dai_rtd), GFP_KERNEL); 346 if (prtd == NULL) 347 return -ENOMEM; 348 349 prtd->substream = substream; 350 prtd->audio_client = q6asm_audio_client_alloc(dev, 351 (q6asm_cb)event_handler, prtd, stream_id, 352 LEGACY_PCM_MODE); 353 if (IS_ERR(prtd->audio_client)) { 354 pr_info("%s: Could not allocate memory\n", __func__); 355 ret = PTR_ERR(prtd->audio_client); 356 kfree(prtd); 357 return ret; 358 } 359 360 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) 361 runtime->hw = q6asm_dai_hardware_playback; 362 else if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) 363 runtime->hw = q6asm_dai_hardware_capture; 364 365 ret = snd_pcm_hw_constraint_list(runtime, 0, 366 SNDRV_PCM_HW_PARAM_RATE, 367 &constraints_sample_rates); 368 if (ret < 0) 369 pr_info("snd_pcm_hw_constraint_list failed\n"); 370 /* Ensure that buffer size is a multiple of period size */ 371 ret = snd_pcm_hw_constraint_integer(runtime, 372 SNDRV_PCM_HW_PARAM_PERIODS); 373 if (ret < 0) 374 pr_info("snd_pcm_hw_constraint_integer failed\n"); 375 376 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { 377 ret = snd_pcm_hw_constraint_minmax(runtime, 378 SNDRV_PCM_HW_PARAM_BUFFER_BYTES, 379 PLAYBACK_MIN_NUM_PERIODS * PLAYBACK_MIN_PERIOD_SIZE, 380 PLAYBACK_MAX_NUM_PERIODS * PLAYBACK_MAX_PERIOD_SIZE); 381 if (ret < 0) { 382 pr_err("constraint for buffer bytes min max ret = %d\n", 383 ret); 384 } 385 } 386 387 ret = snd_pcm_hw_constraint_step(runtime, 0, 388 SNDRV_PCM_HW_PARAM_PERIOD_BYTES, 32); 389 if (ret < 0) { 390 pr_err("constraint for period bytes step ret = %d\n", 391 ret); 392 } 393 ret = snd_pcm_hw_constraint_step(runtime, 0, 394 SNDRV_PCM_HW_PARAM_BUFFER_BYTES, 32); 395 if (ret < 0) { 396 pr_err("constraint for buffer bytes step ret = %d\n", 397 ret); 398 } 399 400 runtime->private_data = prtd; 401 402 snd_soc_set_runtime_hwparams(substream, &q6asm_dai_hardware_playback); 403 404 runtime->dma_bytes = q6asm_dai_hardware_playback.buffer_bytes_max; 405 406 407 if (pdata->sid < 0) 408 prtd->phys = substream->dma_buffer.addr; 409 else 410 prtd->phys = substream->dma_buffer.addr | (pdata->sid << 32); 411 412 snd_pcm_set_runtime_buffer(substream, &substream->dma_buffer); 413 414 return 0; 415 } 416 417 static int q6asm_dai_close(struct snd_pcm_substream *substream) 418 { 419 struct snd_pcm_runtime *runtime = substream->runtime; 420 struct snd_soc_pcm_runtime *soc_prtd = substream->private_data; 421 struct q6asm_dai_rtd *prtd = runtime->private_data; 422 423 if (prtd->audio_client) { 424 if (prtd->state) 425 q6asm_cmd(prtd->audio_client, CMD_CLOSE); 426 427 q6asm_unmap_memory_regions(substream->stream, 428 prtd->audio_client); 429 q6asm_audio_client_free(prtd->audio_client); 430 prtd->audio_client = NULL; 431 } 432 q6routing_stream_close(soc_prtd->dai_link->id, 433 substream->stream); 434 kfree(prtd); 435 return 0; 436 } 437 438 static snd_pcm_uframes_t q6asm_dai_pointer(struct snd_pcm_substream *substream) 439 { 440 441 struct snd_pcm_runtime *runtime = substream->runtime; 442 struct q6asm_dai_rtd *prtd = runtime->private_data; 443 444 if (prtd->pcm_irq_pos >= prtd->pcm_size) 445 prtd->pcm_irq_pos = 0; 446 447 return bytes_to_frames(runtime, (prtd->pcm_irq_pos)); 448 } 449 450 static int q6asm_dai_mmap(struct snd_pcm_substream *substream, 451 struct vm_area_struct *vma) 452 { 453 454 struct snd_pcm_runtime *runtime = substream->runtime; 455 struct snd_soc_pcm_runtime *soc_prtd = substream->private_data; 456 struct snd_soc_component *c = snd_soc_rtdcom_lookup(soc_prtd, DRV_NAME); 457 struct device *dev = c->dev; 458 459 return dma_mmap_coherent(dev, vma, 460 runtime->dma_area, runtime->dma_addr, 461 runtime->dma_bytes); 462 } 463 464 static int q6asm_dai_hw_params(struct snd_pcm_substream *substream, 465 struct snd_pcm_hw_params *params) 466 { 467 struct snd_pcm_runtime *runtime = substream->runtime; 468 struct q6asm_dai_rtd *prtd = runtime->private_data; 469 470 prtd->pcm_size = params_buffer_bytes(params); 471 prtd->periods = params_periods(params); 472 473 switch (params_format(params)) { 474 case SNDRV_PCM_FORMAT_S16_LE: 475 prtd->bits_per_sample = 16; 476 break; 477 case SNDRV_PCM_FORMAT_S24_LE: 478 prtd->bits_per_sample = 24; 479 break; 480 } 481 482 return 0; 483 } 484 485 static struct snd_pcm_ops q6asm_dai_ops = { 486 .open = q6asm_dai_open, 487 .hw_params = q6asm_dai_hw_params, 488 .close = q6asm_dai_close, 489 .ioctl = snd_pcm_lib_ioctl, 490 .prepare = q6asm_dai_prepare, 491 .trigger = q6asm_dai_trigger, 492 .pointer = q6asm_dai_pointer, 493 .mmap = q6asm_dai_mmap, 494 }; 495 496 static void compress_event_handler(uint32_t opcode, uint32_t token, 497 uint32_t *payload, void *priv) 498 { 499 struct q6asm_dai_rtd *prtd = priv; 500 struct snd_compr_stream *substream = prtd->cstream; 501 unsigned long flags; 502 uint64_t avail; 503 504 switch (opcode) { 505 case ASM_CLIENT_EVENT_CMD_RUN_DONE: 506 spin_lock_irqsave(&prtd->lock, flags); 507 if (!prtd->bytes_sent) { 508 q6asm_write_async(prtd->audio_client, prtd->pcm_count, 509 0, 0, NO_TIMESTAMP); 510 prtd->bytes_sent += prtd->pcm_count; 511 } 512 513 spin_unlock_irqrestore(&prtd->lock, flags); 514 break; 515 516 case ASM_CLIENT_EVENT_CMD_EOS_DONE: 517 prtd->state = Q6ASM_STREAM_STOPPED; 518 break; 519 520 case ASM_CLIENT_EVENT_DATA_WRITE_DONE: 521 spin_lock_irqsave(&prtd->lock, flags); 522 523 prtd->copied_total += prtd->pcm_count; 524 snd_compr_fragment_elapsed(substream); 525 526 if (prtd->state != Q6ASM_STREAM_RUNNING) { 527 spin_unlock_irqrestore(&prtd->lock, flags); 528 break; 529 } 530 531 avail = prtd->bytes_received - prtd->bytes_sent; 532 533 if (avail >= prtd->pcm_count) { 534 q6asm_write_async(prtd->audio_client, 535 prtd->pcm_count, 0, 0, NO_TIMESTAMP); 536 prtd->bytes_sent += prtd->pcm_count; 537 } 538 539 spin_unlock_irqrestore(&prtd->lock, flags); 540 break; 541 542 default: 543 break; 544 } 545 } 546 547 static int q6asm_dai_compr_open(struct snd_compr_stream *stream) 548 { 549 struct snd_soc_pcm_runtime *rtd = stream->private_data; 550 struct snd_soc_component *c = snd_soc_rtdcom_lookup(rtd, DRV_NAME); 551 struct snd_compr_runtime *runtime = stream->runtime; 552 struct snd_soc_dai *cpu_dai = rtd->cpu_dai; 553 struct q6asm_dai_data *pdata; 554 struct device *dev = c->dev; 555 struct q6asm_dai_rtd *prtd; 556 int stream_id, size, ret; 557 558 stream_id = cpu_dai->driver->id; 559 pdata = snd_soc_component_get_drvdata(c); 560 if (!pdata) { 561 dev_err(dev, "Drv data not found ..\n"); 562 return -EINVAL; 563 } 564 565 prtd = kzalloc(sizeof(*prtd), GFP_KERNEL); 566 if (!prtd) 567 return -ENOMEM; 568 569 prtd->cstream = stream; 570 prtd->audio_client = q6asm_audio_client_alloc(dev, 571 (q6asm_cb)compress_event_handler, 572 prtd, stream_id, LEGACY_PCM_MODE); 573 if (IS_ERR(prtd->audio_client)) { 574 dev_err(dev, "Could not allocate memory\n"); 575 ret = PTR_ERR(prtd->audio_client); 576 goto free_prtd; 577 } 578 579 size = COMPR_PLAYBACK_MAX_FRAGMENT_SIZE * 580 COMPR_PLAYBACK_MAX_NUM_FRAGMENTS; 581 ret = snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, dev, size, 582 &prtd->dma_buffer); 583 if (ret) { 584 dev_err(dev, "Cannot allocate buffer(s)\n"); 585 goto free_client; 586 } 587 588 if (pdata->sid < 0) 589 prtd->phys = prtd->dma_buffer.addr; 590 else 591 prtd->phys = prtd->dma_buffer.addr | (pdata->sid << 32); 592 593 snd_compr_set_runtime_buffer(stream, &prtd->dma_buffer); 594 spin_lock_init(&prtd->lock); 595 runtime->private_data = prtd; 596 597 return 0; 598 599 free_client: 600 q6asm_audio_client_free(prtd->audio_client); 601 free_prtd: 602 kfree(prtd); 603 604 return ret; 605 } 606 607 static int q6asm_dai_compr_free(struct snd_compr_stream *stream) 608 { 609 struct snd_compr_runtime *runtime = stream->runtime; 610 struct q6asm_dai_rtd *prtd = runtime->private_data; 611 struct snd_soc_pcm_runtime *rtd = stream->private_data; 612 613 if (prtd->audio_client) { 614 if (prtd->state) 615 q6asm_cmd(prtd->audio_client, CMD_CLOSE); 616 617 snd_dma_free_pages(&prtd->dma_buffer); 618 q6asm_unmap_memory_regions(stream->direction, 619 prtd->audio_client); 620 q6asm_audio_client_free(prtd->audio_client); 621 prtd->audio_client = NULL; 622 } 623 q6routing_stream_close(rtd->dai_link->id, stream->direction); 624 kfree(prtd); 625 626 return 0; 627 } 628 629 static int q6asm_dai_compr_set_params(struct snd_compr_stream *stream, 630 struct snd_compr_params *params) 631 { 632 struct snd_compr_runtime *runtime = stream->runtime; 633 struct q6asm_dai_rtd *prtd = runtime->private_data; 634 struct snd_soc_pcm_runtime *rtd = stream->private_data; 635 struct snd_soc_component *c = snd_soc_rtdcom_lookup(rtd, DRV_NAME); 636 int dir = stream->direction; 637 struct q6asm_dai_data *pdata; 638 struct device *dev = c->dev; 639 int ret; 640 641 memcpy(&prtd->codec_param, params, sizeof(*params)); 642 643 pdata = snd_soc_component_get_drvdata(c); 644 if (!pdata) 645 return -EINVAL; 646 647 if (!prtd || !prtd->audio_client) { 648 dev_err(dev, "private data null or audio client freed\n"); 649 return -EINVAL; 650 } 651 652 prtd->periods = runtime->fragments; 653 prtd->pcm_count = runtime->fragment_size; 654 prtd->pcm_size = runtime->fragments * runtime->fragment_size; 655 prtd->bits_per_sample = 16; 656 if (dir == SND_COMPRESS_PLAYBACK) { 657 ret = q6asm_open_write(prtd->audio_client, params->codec.id, 658 prtd->bits_per_sample); 659 660 if (ret < 0) { 661 dev_err(dev, "q6asm_open_write failed\n"); 662 q6asm_audio_client_free(prtd->audio_client); 663 prtd->audio_client = NULL; 664 return ret; 665 } 666 } 667 668 prtd->session_id = q6asm_get_session_id(prtd->audio_client); 669 ret = q6routing_stream_open(rtd->dai_link->id, LEGACY_PCM_MODE, 670 prtd->session_id, dir); 671 if (ret) { 672 dev_err(dev, "Stream reg failed ret:%d\n", ret); 673 return ret; 674 } 675 676 ret = q6asm_map_memory_regions(dir, prtd->audio_client, prtd->phys, 677 (prtd->pcm_size / prtd->periods), 678 prtd->periods); 679 680 if (ret < 0) { 681 dev_err(dev, "Buffer Mapping failed ret:%d\n", ret); 682 return -ENOMEM; 683 } 684 685 prtd->state = Q6ASM_STREAM_RUNNING; 686 687 return 0; 688 } 689 690 static int q6asm_dai_compr_trigger(struct snd_compr_stream *stream, int cmd) 691 { 692 struct snd_compr_runtime *runtime = stream->runtime; 693 struct q6asm_dai_rtd *prtd = runtime->private_data; 694 int ret = 0; 695 696 switch (cmd) { 697 case SNDRV_PCM_TRIGGER_START: 698 case SNDRV_PCM_TRIGGER_RESUME: 699 case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: 700 ret = q6asm_run_nowait(prtd->audio_client, 0, 0, 0); 701 break; 702 case SNDRV_PCM_TRIGGER_STOP: 703 prtd->state = Q6ASM_STREAM_STOPPED; 704 ret = q6asm_cmd_nowait(prtd->audio_client, CMD_EOS); 705 break; 706 case SNDRV_PCM_TRIGGER_SUSPEND: 707 case SNDRV_PCM_TRIGGER_PAUSE_PUSH: 708 ret = q6asm_cmd_nowait(prtd->audio_client, CMD_PAUSE); 709 break; 710 default: 711 ret = -EINVAL; 712 break; 713 } 714 715 return ret; 716 } 717 718 static int q6asm_dai_compr_pointer(struct snd_compr_stream *stream, 719 struct snd_compr_tstamp *tstamp) 720 { 721 struct snd_compr_runtime *runtime = stream->runtime; 722 struct q6asm_dai_rtd *prtd = runtime->private_data; 723 unsigned long flags; 724 725 spin_lock_irqsave(&prtd->lock, flags); 726 727 tstamp->copied_total = prtd->copied_total; 728 tstamp->byte_offset = prtd->copied_total % prtd->pcm_size; 729 730 spin_unlock_irqrestore(&prtd->lock, flags); 731 732 return 0; 733 } 734 735 static int q6asm_dai_compr_ack(struct snd_compr_stream *stream, 736 size_t count) 737 { 738 struct snd_compr_runtime *runtime = stream->runtime; 739 struct q6asm_dai_rtd *prtd = runtime->private_data; 740 unsigned long flags; 741 742 spin_lock_irqsave(&prtd->lock, flags); 743 prtd->bytes_received += count; 744 spin_unlock_irqrestore(&prtd->lock, flags); 745 746 return count; 747 } 748 749 static int q6asm_dai_compr_mmap(struct snd_compr_stream *stream, 750 struct vm_area_struct *vma) 751 { 752 struct snd_compr_runtime *runtime = stream->runtime; 753 struct q6asm_dai_rtd *prtd = runtime->private_data; 754 struct snd_soc_pcm_runtime *rtd = stream->private_data; 755 struct snd_soc_component *c = snd_soc_rtdcom_lookup(rtd, DRV_NAME); 756 struct device *dev = c->dev; 757 758 return dma_mmap_coherent(dev, vma, 759 prtd->dma_buffer.area, prtd->dma_buffer.addr, 760 prtd->dma_buffer.bytes); 761 } 762 763 static int q6asm_dai_compr_get_caps(struct snd_compr_stream *stream, 764 struct snd_compr_caps *caps) 765 { 766 caps->direction = SND_COMPRESS_PLAYBACK; 767 caps->min_fragment_size = COMPR_PLAYBACK_MIN_FRAGMENT_SIZE; 768 caps->max_fragment_size = COMPR_PLAYBACK_MAX_FRAGMENT_SIZE; 769 caps->min_fragments = COMPR_PLAYBACK_MIN_NUM_FRAGMENTS; 770 caps->max_fragments = COMPR_PLAYBACK_MAX_NUM_FRAGMENTS; 771 caps->num_codecs = 1; 772 caps->codecs[0] = SND_AUDIOCODEC_MP3; 773 774 return 0; 775 } 776 777 static int q6asm_dai_compr_get_codec_caps(struct snd_compr_stream *stream, 778 struct snd_compr_codec_caps *codec) 779 { 780 switch (codec->codec) { 781 case SND_AUDIOCODEC_MP3: 782 *codec = q6asm_compr_caps; 783 break; 784 default: 785 break; 786 } 787 788 return 0; 789 } 790 791 static struct snd_compr_ops q6asm_dai_compr_ops = { 792 .open = q6asm_dai_compr_open, 793 .free = q6asm_dai_compr_free, 794 .set_params = q6asm_dai_compr_set_params, 795 .pointer = q6asm_dai_compr_pointer, 796 .trigger = q6asm_dai_compr_trigger, 797 .get_caps = q6asm_dai_compr_get_caps, 798 .get_codec_caps = q6asm_dai_compr_get_codec_caps, 799 .mmap = q6asm_dai_compr_mmap, 800 .ack = q6asm_dai_compr_ack, 801 }; 802 803 static int q6asm_dai_pcm_new(struct snd_soc_pcm_runtime *rtd) 804 { 805 struct snd_pcm_substream *psubstream, *csubstream; 806 struct snd_soc_component *c = snd_soc_rtdcom_lookup(rtd, DRV_NAME); 807 struct snd_pcm *pcm = rtd->pcm; 808 struct device *dev; 809 int size, ret; 810 811 dev = c->dev; 812 size = q6asm_dai_hardware_playback.buffer_bytes_max; 813 psubstream = pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream; 814 if (psubstream) { 815 ret = snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, dev, size, 816 &psubstream->dma_buffer); 817 if (ret) { 818 dev_err(dev, "Cannot allocate buffer(s)\n"); 819 return ret; 820 } 821 } 822 823 csubstream = pcm->streams[SNDRV_PCM_STREAM_CAPTURE].substream; 824 if (csubstream) { 825 ret = snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, dev, size, 826 &csubstream->dma_buffer); 827 if (ret) { 828 dev_err(dev, "Cannot allocate buffer(s)\n"); 829 if (psubstream) 830 snd_dma_free_pages(&psubstream->dma_buffer); 831 return ret; 832 } 833 } 834 835 return 0; 836 } 837 838 static void q6asm_dai_pcm_free(struct snd_pcm *pcm) 839 { 840 struct snd_pcm_substream *substream; 841 int i; 842 843 for (i = 0; i < ARRAY_SIZE(pcm->streams); i++) { 844 substream = pcm->streams[i].substream; 845 if (substream) { 846 snd_dma_free_pages(&substream->dma_buffer); 847 substream->dma_buffer.area = NULL; 848 substream->dma_buffer.addr = 0; 849 } 850 } 851 } 852 853 static const struct snd_soc_component_driver q6asm_fe_dai_component = { 854 .name = DRV_NAME, 855 .ops = &q6asm_dai_ops, 856 .pcm_new = q6asm_dai_pcm_new, 857 .pcm_free = q6asm_dai_pcm_free, 858 .compr_ops = &q6asm_dai_compr_ops, 859 }; 860 861 static struct snd_soc_dai_driver q6asm_fe_dais[] = { 862 Q6ASM_FEDAI_DRIVER(1), 863 Q6ASM_FEDAI_DRIVER(2), 864 Q6ASM_FEDAI_DRIVER(3), 865 Q6ASM_FEDAI_DRIVER(4), 866 Q6ASM_FEDAI_DRIVER(5), 867 Q6ASM_FEDAI_DRIVER(6), 868 Q6ASM_FEDAI_DRIVER(7), 869 Q6ASM_FEDAI_DRIVER(8), 870 }; 871 872 static int of_q6asm_parse_dai_data(struct device *dev, 873 struct q6asm_dai_data *pdata) 874 { 875 static struct snd_soc_dai_driver *dai_drv; 876 struct snd_soc_pcm_stream empty_stream; 877 struct device_node *node; 878 int ret, id, dir; 879 880 memset(&empty_stream, 0, sizeof(empty_stream)); 881 882 for_each_child_of_node(dev->of_node, node) { 883 ret = of_property_read_u32(node, "reg", &id); 884 if (ret || id >= MAX_SESSIONS || id < 0) { 885 dev_err(dev, "valid dai id not found:%d\n", ret); 886 continue; 887 } 888 889 dai_drv = &q6asm_fe_dais[id]; 890 891 ret = of_property_read_u32(node, "direction", &dir); 892 if (ret) 893 continue; 894 895 if (dir == Q6ASM_DAI_RX) 896 dai_drv->capture = empty_stream; 897 else if (dir == Q6ASM_DAI_TX) 898 dai_drv->playback = empty_stream; 899 900 if (of_property_read_bool(node, "is-compress-dai")) 901 dai_drv->compress_new = snd_soc_new_compress; 902 } 903 904 return 0; 905 } 906 907 static int q6asm_dai_probe(struct platform_device *pdev) 908 { 909 struct device *dev = &pdev->dev; 910 struct device_node *node = dev->of_node; 911 struct of_phandle_args args; 912 struct q6asm_dai_data *pdata; 913 int rc; 914 915 pdata = devm_kzalloc(dev, sizeof(*pdata), GFP_KERNEL); 916 if (!pdata) 917 return -ENOMEM; 918 919 rc = of_parse_phandle_with_fixed_args(node, "iommus", 1, 0, &args); 920 if (rc < 0) 921 pdata->sid = -1; 922 else 923 pdata->sid = args.args[0] & SID_MASK_DEFAULT; 924 925 dev_set_drvdata(dev, pdata); 926 927 of_q6asm_parse_dai_data(dev, pdata); 928 929 return devm_snd_soc_register_component(dev, &q6asm_fe_dai_component, 930 q6asm_fe_dais, 931 ARRAY_SIZE(q6asm_fe_dais)); 932 } 933 934 static const struct of_device_id q6asm_dai_device_id[] = { 935 { .compatible = "qcom,q6asm-dais" }, 936 {}, 937 }; 938 MODULE_DEVICE_TABLE(of, q6asm_dai_device_id); 939 940 static struct platform_driver q6asm_dai_platform_driver = { 941 .driver = { 942 .name = "q6asm-dai", 943 .of_match_table = of_match_ptr(q6asm_dai_device_id), 944 }, 945 .probe = q6asm_dai_probe, 946 }; 947 module_platform_driver(q6asm_dai_platform_driver); 948 949 MODULE_DESCRIPTION("Q6ASM dai driver"); 950 MODULE_LICENSE("GPL v2"); 951