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 <dt-bindings/sound/qcom,q6asm.h> 6 #include <linux/init.h> 7 #include <linux/err.h> 8 #include <linux/module.h> 9 #include <linux/of.h> 10 #include <linux/platform_device.h> 11 #include <linux/slab.h> 12 #include <sound/soc.h> 13 #include <sound/soc-dapm.h> 14 #include <sound/pcm.h> 15 #include <linux/spinlock.h> 16 #include <sound/compress_driver.h> 17 #include <asm/div64.h> 18 #include <asm/dma.h> 19 #include <linux/dma-mapping.h> 20 #include <sound/pcm_params.h> 21 #include "q6asm.h" 22 #include "q6routing.h" 23 #include "q6dsp-errno.h" 24 25 #define DRV_NAME "q6asm-fe-dai" 26 27 #define PLAYBACK_MIN_NUM_PERIODS 2 28 #define PLAYBACK_MAX_NUM_PERIODS 8 29 #define PLAYBACK_MAX_PERIOD_SIZE 65536 30 #define PLAYBACK_MIN_PERIOD_SIZE 128 31 #define CAPTURE_MIN_NUM_PERIODS 2 32 #define CAPTURE_MAX_NUM_PERIODS 8 33 #define CAPTURE_MAX_PERIOD_SIZE 4096 34 #define CAPTURE_MIN_PERIOD_SIZE 320 35 #define SID_MASK_DEFAULT 0xF 36 37 /* Default values used if user space does not set */ 38 #define COMPR_PLAYBACK_MIN_FRAGMENT_SIZE (8 * 1024) 39 #define COMPR_PLAYBACK_MAX_FRAGMENT_SIZE (128 * 1024) 40 #define COMPR_PLAYBACK_MIN_NUM_FRAGMENTS (4) 41 #define COMPR_PLAYBACK_MAX_NUM_FRAGMENTS (16 * 4) 42 43 #define ALAC_CH_LAYOUT_MONO ((101 << 16) | 1) 44 #define ALAC_CH_LAYOUT_STEREO ((101 << 16) | 2) 45 46 enum stream_state { 47 Q6ASM_STREAM_IDLE = 0, 48 Q6ASM_STREAM_STOPPED, 49 Q6ASM_STREAM_RUNNING, 50 }; 51 52 struct q6asm_dai_rtd { 53 struct snd_pcm_substream *substream; 54 struct snd_compr_stream *cstream; 55 struct snd_codec codec; 56 struct snd_dma_buffer dma_buffer; 57 spinlock_t lock; 58 phys_addr_t phys; 59 unsigned int pcm_size; 60 unsigned int pcm_count; 61 unsigned int pcm_irq_pos; /* IRQ position */ 62 unsigned int periods; 63 uint64_t bytes_sent; 64 uint64_t bytes_received; 65 uint64_t copied_total; 66 uint16_t bits_per_sample; 67 uint16_t source; /* Encoding source bit mask */ 68 struct audio_client *audio_client; 69 uint32_t next_track_stream_id; 70 bool next_track; 71 uint32_t stream_id; 72 uint16_t session_id; 73 enum stream_state state; 74 uint32_t initial_samples_drop; 75 uint32_t trailing_samples_drop; 76 bool notify_on_drain; 77 }; 78 79 struct q6asm_dai_data { 80 struct snd_soc_dai_driver *dais; 81 int num_dais; 82 long long int sid; 83 }; 84 85 static const struct snd_pcm_hardware q6asm_dai_hardware_capture = { 86 .info = (SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_BATCH | 87 SNDRV_PCM_INFO_BLOCK_TRANSFER | 88 SNDRV_PCM_INFO_MMAP_VALID | 89 SNDRV_PCM_INFO_INTERLEAVED | 90 SNDRV_PCM_INFO_PAUSE | SNDRV_PCM_INFO_RESUME), 91 .formats = (SNDRV_PCM_FMTBIT_S16_LE | 92 SNDRV_PCM_FMTBIT_S24_LE), 93 .rates = SNDRV_PCM_RATE_8000_48000, 94 .rate_min = 8000, 95 .rate_max = 48000, 96 .channels_min = 1, 97 .channels_max = 4, 98 .buffer_bytes_max = CAPTURE_MAX_NUM_PERIODS * 99 CAPTURE_MAX_PERIOD_SIZE, 100 .period_bytes_min = CAPTURE_MIN_PERIOD_SIZE, 101 .period_bytes_max = CAPTURE_MAX_PERIOD_SIZE, 102 .periods_min = CAPTURE_MIN_NUM_PERIODS, 103 .periods_max = CAPTURE_MAX_NUM_PERIODS, 104 .fifo_size = 0, 105 }; 106 107 static const struct snd_pcm_hardware q6asm_dai_hardware_playback = { 108 .info = (SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_BATCH | 109 SNDRV_PCM_INFO_BLOCK_TRANSFER | 110 SNDRV_PCM_INFO_MMAP_VALID | 111 SNDRV_PCM_INFO_INTERLEAVED | 112 SNDRV_PCM_INFO_PAUSE | SNDRV_PCM_INFO_RESUME), 113 .formats = (SNDRV_PCM_FMTBIT_S16_LE | 114 SNDRV_PCM_FMTBIT_S24_LE), 115 .rates = SNDRV_PCM_RATE_8000_192000, 116 .rate_min = 8000, 117 .rate_max = 192000, 118 .channels_min = 1, 119 .channels_max = 8, 120 .buffer_bytes_max = (PLAYBACK_MAX_NUM_PERIODS * 121 PLAYBACK_MAX_PERIOD_SIZE), 122 .period_bytes_min = PLAYBACK_MIN_PERIOD_SIZE, 123 .period_bytes_max = PLAYBACK_MAX_PERIOD_SIZE, 124 .periods_min = PLAYBACK_MIN_NUM_PERIODS, 125 .periods_max = PLAYBACK_MAX_NUM_PERIODS, 126 .fifo_size = 0, 127 }; 128 129 #define Q6ASM_FEDAI_DRIVER(num) { \ 130 .playback = { \ 131 .stream_name = "MultiMedia"#num" Playback", \ 132 .rates = (SNDRV_PCM_RATE_8000_48000 | \ 133 SNDRV_PCM_RATE_12000 | \ 134 SNDRV_PCM_RATE_24000 | \ 135 SNDRV_PCM_RATE_88200 | \ 136 SNDRV_PCM_RATE_96000 | \ 137 SNDRV_PCM_RATE_176400 | \ 138 SNDRV_PCM_RATE_192000), \ 139 .formats = (SNDRV_PCM_FMTBIT_S16_LE | \ 140 SNDRV_PCM_FMTBIT_S24_LE), \ 141 .channels_min = 1, \ 142 .channels_max = 8, \ 143 .rate_min = 8000, \ 144 .rate_max = 192000, \ 145 }, \ 146 .capture = { \ 147 .stream_name = "MultiMedia"#num" Capture", \ 148 .rates = (SNDRV_PCM_RATE_8000_48000 | \ 149 SNDRV_PCM_RATE_12000 | \ 150 SNDRV_PCM_RATE_24000), \ 151 .formats = (SNDRV_PCM_FMTBIT_S16_LE | \ 152 SNDRV_PCM_FMTBIT_S24_LE), \ 153 .channels_min = 1, \ 154 .channels_max = 4, \ 155 .rate_min = 8000, \ 156 .rate_max = 48000, \ 157 }, \ 158 .name = "MultiMedia"#num, \ 159 .id = MSM_FRONTEND_DAI_MULTIMEDIA##num, \ 160 } 161 162 static const struct snd_compr_codec_caps q6asm_compr_caps = { 163 .num_descriptors = 1, 164 .descriptor[0].max_ch = 2, 165 .descriptor[0].sample_rates = { 8000, 11025, 12000, 16000, 22050, 166 24000, 32000, 44100, 48000, 88200, 167 96000, 176400, 192000 }, 168 .descriptor[0].num_sample_rates = 13, 169 .descriptor[0].bit_rate[0] = 320, 170 .descriptor[0].bit_rate[1] = 128, 171 .descriptor[0].num_bitrates = 2, 172 .descriptor[0].profiles = 0, 173 .descriptor[0].modes = SND_AUDIOCHANMODE_MP3_STEREO, 174 .descriptor[0].formats = 0, 175 }; 176 177 static void event_handler(uint32_t opcode, uint32_t token, 178 void *payload, void *priv) 179 { 180 struct q6asm_dai_rtd *prtd = priv; 181 struct snd_pcm_substream *substream = prtd->substream; 182 183 switch (opcode) { 184 case ASM_CLIENT_EVENT_CMD_RUN_DONE: 185 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) 186 q6asm_write_async(prtd->audio_client, prtd->stream_id, 187 prtd->pcm_count, 0, 0, 0); 188 break; 189 case ASM_CLIENT_EVENT_CMD_EOS_DONE: 190 prtd->state = Q6ASM_STREAM_STOPPED; 191 break; 192 case ASM_CLIENT_EVENT_DATA_WRITE_DONE: { 193 prtd->pcm_irq_pos += prtd->pcm_count; 194 snd_pcm_period_elapsed(substream); 195 if (prtd->state == Q6ASM_STREAM_RUNNING) 196 q6asm_write_async(prtd->audio_client, prtd->stream_id, 197 prtd->pcm_count, 0, 0, 0); 198 199 break; 200 } 201 case ASM_CLIENT_EVENT_DATA_READ_DONE: 202 prtd->pcm_irq_pos += prtd->pcm_count; 203 snd_pcm_period_elapsed(substream); 204 if (prtd->state == Q6ASM_STREAM_RUNNING) 205 q6asm_read(prtd->audio_client, prtd->stream_id); 206 207 break; 208 default: 209 break; 210 } 211 } 212 213 static int q6asm_dai_prepare(struct snd_soc_component *component, 214 struct snd_pcm_substream *substream) 215 { 216 struct snd_pcm_runtime *runtime = substream->runtime; 217 struct snd_soc_pcm_runtime *soc_prtd = snd_soc_substream_to_rtd(substream); 218 struct q6asm_dai_rtd *prtd = runtime->private_data; 219 struct q6asm_dai_data *pdata; 220 struct device *dev = component->dev; 221 int ret, i; 222 223 pdata = snd_soc_component_get_drvdata(component); 224 if (!pdata) 225 return -EINVAL; 226 227 if (!prtd || !prtd->audio_client) { 228 dev_err(dev, "%s: private data null or audio client freed\n", 229 __func__); 230 return -EINVAL; 231 } 232 233 prtd->pcm_count = snd_pcm_lib_period_bytes(substream); 234 prtd->pcm_irq_pos = 0; 235 /* rate and channels are sent to audio driver */ 236 if (prtd->state) { 237 /* clear the previous setup if any */ 238 q6asm_cmd(prtd->audio_client, prtd->stream_id, CMD_CLOSE); 239 q6asm_unmap_memory_regions(substream->stream, 240 prtd->audio_client); 241 q6routing_stream_close(soc_prtd->dai_link->id, 242 substream->stream); 243 } 244 245 ret = q6asm_map_memory_regions(substream->stream, prtd->audio_client, 246 prtd->phys, 247 (prtd->pcm_size / prtd->periods), 248 prtd->periods); 249 250 if (ret < 0) { 251 dev_err(dev, "Audio Start: Buffer Allocation failed rc = %d\n", 252 ret); 253 return -ENOMEM; 254 } 255 256 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { 257 ret = q6asm_open_write(prtd->audio_client, prtd->stream_id, 258 FORMAT_LINEAR_PCM, 259 0, prtd->bits_per_sample, false); 260 } else if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) { 261 ret = q6asm_open_read(prtd->audio_client, prtd->stream_id, 262 FORMAT_LINEAR_PCM, 263 prtd->bits_per_sample); 264 } 265 266 if (ret < 0) { 267 dev_err(dev, "%s: q6asm_open_write failed\n", __func__); 268 goto open_err; 269 } 270 271 prtd->session_id = q6asm_get_session_id(prtd->audio_client); 272 ret = q6routing_stream_open(soc_prtd->dai_link->id, LEGACY_PCM_MODE, 273 prtd->session_id, substream->stream); 274 if (ret) { 275 dev_err(dev, "%s: stream reg failed ret:%d\n", __func__, ret); 276 goto routing_err; 277 } 278 279 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { 280 ret = q6asm_media_format_block_multi_ch_pcm( 281 prtd->audio_client, prtd->stream_id, 282 runtime->rate, runtime->channels, NULL, 283 prtd->bits_per_sample); 284 } else if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) { 285 ret = q6asm_enc_cfg_blk_pcm_format_support(prtd->audio_client, 286 prtd->stream_id, 287 runtime->rate, 288 runtime->channels, 289 prtd->bits_per_sample); 290 291 /* Queue the buffers */ 292 for (i = 0; i < runtime->periods; i++) 293 q6asm_read(prtd->audio_client, prtd->stream_id); 294 295 } 296 if (ret < 0) 297 dev_info(dev, "%s: CMD Format block failed\n", __func__); 298 else 299 prtd->state = Q6ASM_STREAM_RUNNING; 300 301 return ret; 302 303 routing_err: 304 q6asm_cmd(prtd->audio_client, prtd->stream_id, CMD_CLOSE); 305 open_err: 306 q6asm_unmap_memory_regions(substream->stream, prtd->audio_client); 307 q6asm_audio_client_free(prtd->audio_client); 308 prtd->audio_client = NULL; 309 310 return ret; 311 } 312 313 static int q6asm_dai_trigger(struct snd_soc_component *component, 314 struct snd_pcm_substream *substream, int cmd) 315 { 316 int ret = 0; 317 struct snd_pcm_runtime *runtime = substream->runtime; 318 struct q6asm_dai_rtd *prtd = runtime->private_data; 319 320 switch (cmd) { 321 case SNDRV_PCM_TRIGGER_START: 322 case SNDRV_PCM_TRIGGER_RESUME: 323 case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: 324 ret = q6asm_run_nowait(prtd->audio_client, prtd->stream_id, 325 0, 0, 0); 326 break; 327 case SNDRV_PCM_TRIGGER_STOP: 328 prtd->state = Q6ASM_STREAM_STOPPED; 329 ret = q6asm_cmd_nowait(prtd->audio_client, prtd->stream_id, 330 CMD_EOS); 331 break; 332 case SNDRV_PCM_TRIGGER_SUSPEND: 333 case SNDRV_PCM_TRIGGER_PAUSE_PUSH: 334 ret = q6asm_cmd_nowait(prtd->audio_client, prtd->stream_id, 335 CMD_PAUSE); 336 break; 337 default: 338 ret = -EINVAL; 339 break; 340 } 341 342 return ret; 343 } 344 345 static int q6asm_dai_open(struct snd_soc_component *component, 346 struct snd_pcm_substream *substream) 347 { 348 struct snd_pcm_runtime *runtime = substream->runtime; 349 struct snd_soc_pcm_runtime *soc_prtd = snd_soc_substream_to_rtd(substream); 350 struct snd_soc_dai *cpu_dai = snd_soc_rtd_to_cpu(soc_prtd, 0); 351 struct q6asm_dai_rtd *prtd; 352 struct q6asm_dai_data *pdata; 353 struct device *dev = component->dev; 354 int ret = 0; 355 int stream_id; 356 357 stream_id = cpu_dai->driver->id; 358 359 pdata = snd_soc_component_get_drvdata(component); 360 if (!pdata) { 361 dev_err(dev, "Drv data not found ..\n"); 362 return -EINVAL; 363 } 364 365 prtd = kzalloc(sizeof(struct q6asm_dai_rtd), GFP_KERNEL); 366 if (prtd == NULL) 367 return -ENOMEM; 368 369 prtd->substream = substream; 370 prtd->audio_client = q6asm_audio_client_alloc(dev, 371 (q6asm_cb)event_handler, prtd, stream_id, 372 LEGACY_PCM_MODE); 373 if (IS_ERR(prtd->audio_client)) { 374 dev_info(dev, "%s: Could not allocate memory\n", __func__); 375 ret = PTR_ERR(prtd->audio_client); 376 kfree(prtd); 377 return ret; 378 } 379 380 /* DSP expects stream id from 1 */ 381 prtd->stream_id = 1; 382 383 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) 384 runtime->hw = q6asm_dai_hardware_playback; 385 else if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) 386 runtime->hw = q6asm_dai_hardware_capture; 387 388 /* Ensure that buffer size is a multiple of period size */ 389 ret = snd_pcm_hw_constraint_integer(runtime, 390 SNDRV_PCM_HW_PARAM_PERIODS); 391 if (ret < 0) 392 dev_info(dev, "snd_pcm_hw_constraint_integer failed\n"); 393 394 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { 395 ret = snd_pcm_hw_constraint_minmax(runtime, 396 SNDRV_PCM_HW_PARAM_BUFFER_BYTES, 397 PLAYBACK_MIN_NUM_PERIODS * PLAYBACK_MIN_PERIOD_SIZE, 398 PLAYBACK_MAX_NUM_PERIODS * PLAYBACK_MAX_PERIOD_SIZE); 399 if (ret < 0) { 400 dev_err(dev, "constraint for buffer bytes min max ret = %d\n", 401 ret); 402 } 403 } 404 405 ret = snd_pcm_hw_constraint_step(runtime, 0, 406 SNDRV_PCM_HW_PARAM_PERIOD_BYTES, 32); 407 if (ret < 0) { 408 dev_err(dev, "constraint for period bytes step ret = %d\n", 409 ret); 410 } 411 ret = snd_pcm_hw_constraint_step(runtime, 0, 412 SNDRV_PCM_HW_PARAM_BUFFER_BYTES, 32); 413 if (ret < 0) { 414 dev_err(dev, "constraint for buffer bytes step ret = %d\n", 415 ret); 416 } 417 418 runtime->private_data = prtd; 419 420 snd_soc_set_runtime_hwparams(substream, &q6asm_dai_hardware_playback); 421 422 runtime->dma_bytes = q6asm_dai_hardware_playback.buffer_bytes_max; 423 424 425 if (pdata->sid < 0) 426 prtd->phys = substream->dma_buffer.addr; 427 else 428 prtd->phys = substream->dma_buffer.addr | (pdata->sid << 32); 429 430 return 0; 431 } 432 433 static int q6asm_dai_close(struct snd_soc_component *component, 434 struct snd_pcm_substream *substream) 435 { 436 struct snd_pcm_runtime *runtime = substream->runtime; 437 struct snd_soc_pcm_runtime *soc_prtd = snd_soc_substream_to_rtd(substream); 438 struct q6asm_dai_rtd *prtd = runtime->private_data; 439 440 if (prtd->audio_client) { 441 if (prtd->state) 442 q6asm_cmd(prtd->audio_client, prtd->stream_id, 443 CMD_CLOSE); 444 445 q6asm_unmap_memory_regions(substream->stream, 446 prtd->audio_client); 447 q6asm_audio_client_free(prtd->audio_client); 448 prtd->audio_client = NULL; 449 } 450 q6routing_stream_close(soc_prtd->dai_link->id, 451 substream->stream); 452 kfree(prtd); 453 return 0; 454 } 455 456 static snd_pcm_uframes_t q6asm_dai_pointer(struct snd_soc_component *component, 457 struct snd_pcm_substream *substream) 458 { 459 460 struct snd_pcm_runtime *runtime = substream->runtime; 461 struct q6asm_dai_rtd *prtd = runtime->private_data; 462 463 if (prtd->pcm_irq_pos >= prtd->pcm_size) 464 prtd->pcm_irq_pos = 0; 465 466 return bytes_to_frames(runtime, (prtd->pcm_irq_pos)); 467 } 468 469 static int q6asm_dai_hw_params(struct snd_soc_component *component, 470 struct snd_pcm_substream *substream, 471 struct snd_pcm_hw_params *params) 472 { 473 struct snd_pcm_runtime *runtime = substream->runtime; 474 struct q6asm_dai_rtd *prtd = runtime->private_data; 475 476 prtd->pcm_size = params_buffer_bytes(params); 477 prtd->periods = params_periods(params); 478 479 switch (params_format(params)) { 480 case SNDRV_PCM_FORMAT_S16_LE: 481 prtd->bits_per_sample = 16; 482 break; 483 case SNDRV_PCM_FORMAT_S24_LE: 484 prtd->bits_per_sample = 24; 485 break; 486 } 487 488 return 0; 489 } 490 491 static void compress_event_handler(uint32_t opcode, uint32_t token, 492 void *payload, void *priv) 493 { 494 struct q6asm_dai_rtd *prtd = priv; 495 struct snd_compr_stream *substream = prtd->cstream; 496 unsigned long flags; 497 u32 wflags = 0; 498 uint64_t avail; 499 uint32_t bytes_written, bytes_to_write; 500 bool is_last_buffer = false; 501 502 switch (opcode) { 503 case ASM_CLIENT_EVENT_CMD_RUN_DONE: 504 spin_lock_irqsave(&prtd->lock, flags); 505 if (!prtd->bytes_sent) { 506 q6asm_stream_remove_initial_silence(prtd->audio_client, 507 prtd->stream_id, 508 prtd->initial_samples_drop); 509 510 q6asm_write_async(prtd->audio_client, prtd->stream_id, 511 prtd->pcm_count, 0, 0, 0); 512 prtd->bytes_sent += prtd->pcm_count; 513 } 514 515 spin_unlock_irqrestore(&prtd->lock, flags); 516 break; 517 518 case ASM_CLIENT_EVENT_CMD_EOS_DONE: 519 spin_lock_irqsave(&prtd->lock, flags); 520 if (prtd->notify_on_drain) { 521 if (substream->partial_drain) { 522 /* 523 * Close old stream and make it stale, switch 524 * the active stream now! 525 */ 526 q6asm_cmd_nowait(prtd->audio_client, 527 prtd->stream_id, 528 CMD_CLOSE); 529 /* 530 * vaild stream ids start from 1, So we are 531 * toggling this between 1 and 2. 532 */ 533 prtd->stream_id = (prtd->stream_id == 1 ? 2 : 1); 534 } 535 536 snd_compr_drain_notify(prtd->cstream); 537 prtd->notify_on_drain = false; 538 539 } else { 540 prtd->state = Q6ASM_STREAM_STOPPED; 541 } 542 spin_unlock_irqrestore(&prtd->lock, flags); 543 break; 544 545 case ASM_CLIENT_EVENT_DATA_WRITE_DONE: 546 spin_lock_irqsave(&prtd->lock, flags); 547 548 bytes_written = token >> ASM_WRITE_TOKEN_LEN_SHIFT; 549 prtd->copied_total += bytes_written; 550 snd_compr_fragment_elapsed(substream); 551 552 if (prtd->state != Q6ASM_STREAM_RUNNING) { 553 spin_unlock_irqrestore(&prtd->lock, flags); 554 break; 555 } 556 557 avail = prtd->bytes_received - prtd->bytes_sent; 558 if (avail > prtd->pcm_count) { 559 bytes_to_write = prtd->pcm_count; 560 } else { 561 if (substream->partial_drain || prtd->notify_on_drain) 562 is_last_buffer = true; 563 bytes_to_write = avail; 564 } 565 566 if (bytes_to_write) { 567 if (substream->partial_drain && is_last_buffer) { 568 wflags |= ASM_LAST_BUFFER_FLAG; 569 q6asm_stream_remove_trailing_silence(prtd->audio_client, 570 prtd->stream_id, 571 prtd->trailing_samples_drop); 572 } 573 574 q6asm_write_async(prtd->audio_client, prtd->stream_id, 575 bytes_to_write, 0, 0, wflags); 576 577 prtd->bytes_sent += bytes_to_write; 578 } 579 580 if (prtd->notify_on_drain && is_last_buffer) 581 q6asm_cmd_nowait(prtd->audio_client, 582 prtd->stream_id, CMD_EOS); 583 584 spin_unlock_irqrestore(&prtd->lock, flags); 585 break; 586 587 default: 588 break; 589 } 590 } 591 592 static int q6asm_dai_compr_open(struct snd_soc_component *component, 593 struct snd_compr_stream *stream) 594 { 595 struct snd_soc_pcm_runtime *rtd = stream->private_data; 596 struct snd_compr_runtime *runtime = stream->runtime; 597 struct snd_soc_dai *cpu_dai = snd_soc_rtd_to_cpu(rtd, 0); 598 struct q6asm_dai_data *pdata; 599 struct device *dev = component->dev; 600 struct q6asm_dai_rtd *prtd; 601 int stream_id, size, ret; 602 603 stream_id = cpu_dai->driver->id; 604 pdata = snd_soc_component_get_drvdata(component); 605 if (!pdata) { 606 dev_err(dev, "Drv data not found ..\n"); 607 return -EINVAL; 608 } 609 610 prtd = kzalloc(sizeof(*prtd), GFP_KERNEL); 611 if (!prtd) 612 return -ENOMEM; 613 614 /* DSP expects stream id from 1 */ 615 prtd->stream_id = 1; 616 617 prtd->cstream = stream; 618 prtd->audio_client = q6asm_audio_client_alloc(dev, 619 (q6asm_cb)compress_event_handler, 620 prtd, stream_id, LEGACY_PCM_MODE); 621 if (IS_ERR(prtd->audio_client)) { 622 dev_err(dev, "Could not allocate memory\n"); 623 ret = PTR_ERR(prtd->audio_client); 624 goto free_prtd; 625 } 626 627 size = COMPR_PLAYBACK_MAX_FRAGMENT_SIZE * 628 COMPR_PLAYBACK_MAX_NUM_FRAGMENTS; 629 ret = snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, dev, size, 630 &prtd->dma_buffer); 631 if (ret) { 632 dev_err(dev, "Cannot allocate buffer(s)\n"); 633 goto free_client; 634 } 635 636 if (pdata->sid < 0) 637 prtd->phys = prtd->dma_buffer.addr; 638 else 639 prtd->phys = prtd->dma_buffer.addr | (pdata->sid << 32); 640 641 snd_compr_set_runtime_buffer(stream, &prtd->dma_buffer); 642 spin_lock_init(&prtd->lock); 643 runtime->private_data = prtd; 644 645 return 0; 646 647 free_client: 648 q6asm_audio_client_free(prtd->audio_client); 649 free_prtd: 650 kfree(prtd); 651 652 return ret; 653 } 654 655 static int q6asm_dai_compr_free(struct snd_soc_component *component, 656 struct snd_compr_stream *stream) 657 { 658 struct snd_compr_runtime *runtime = stream->runtime; 659 struct q6asm_dai_rtd *prtd = runtime->private_data; 660 struct snd_soc_pcm_runtime *rtd = stream->private_data; 661 662 if (prtd->audio_client) { 663 if (prtd->state) { 664 q6asm_cmd(prtd->audio_client, prtd->stream_id, 665 CMD_CLOSE); 666 if (prtd->next_track_stream_id) { 667 q6asm_cmd(prtd->audio_client, 668 prtd->next_track_stream_id, 669 CMD_CLOSE); 670 } 671 } 672 673 snd_dma_free_pages(&prtd->dma_buffer); 674 q6asm_unmap_memory_regions(stream->direction, 675 prtd->audio_client); 676 q6asm_audio_client_free(prtd->audio_client); 677 prtd->audio_client = NULL; 678 } 679 q6routing_stream_close(rtd->dai_link->id, stream->direction); 680 kfree(prtd); 681 682 return 0; 683 } 684 685 static int __q6asm_dai_compr_set_codec_params(struct snd_soc_component *component, 686 struct snd_compr_stream *stream, 687 struct snd_codec *codec, 688 int stream_id) 689 { 690 struct snd_compr_runtime *runtime = stream->runtime; 691 struct q6asm_dai_rtd *prtd = runtime->private_data; 692 struct q6asm_flac_cfg flac_cfg; 693 struct q6asm_wma_cfg wma_cfg; 694 struct q6asm_alac_cfg alac_cfg; 695 struct q6asm_ape_cfg ape_cfg; 696 unsigned int wma_v9 = 0; 697 struct device *dev = component->dev; 698 int ret; 699 union snd_codec_options *codec_options; 700 struct snd_dec_flac *flac; 701 struct snd_dec_wma *wma; 702 struct snd_dec_alac *alac; 703 struct snd_dec_ape *ape; 704 705 codec_options = &(prtd->codec.options); 706 707 memcpy(&prtd->codec, codec, sizeof(*codec)); 708 709 switch (codec->id) { 710 case SND_AUDIOCODEC_FLAC: 711 712 memset(&flac_cfg, 0x0, sizeof(struct q6asm_flac_cfg)); 713 flac = &codec_options->flac_d; 714 715 flac_cfg.ch_cfg = codec->ch_in; 716 flac_cfg.sample_rate = codec->sample_rate; 717 flac_cfg.stream_info_present = 1; 718 flac_cfg.sample_size = flac->sample_size; 719 flac_cfg.min_blk_size = flac->min_blk_size; 720 flac_cfg.max_blk_size = flac->max_blk_size; 721 flac_cfg.max_frame_size = flac->max_frame_size; 722 flac_cfg.min_frame_size = flac->min_frame_size; 723 724 ret = q6asm_stream_media_format_block_flac(prtd->audio_client, 725 stream_id, 726 &flac_cfg); 727 if (ret < 0) { 728 dev_err(dev, "FLAC CMD Format block failed:%d\n", ret); 729 return -EIO; 730 } 731 break; 732 733 case SND_AUDIOCODEC_WMA: 734 wma = &codec_options->wma_d; 735 736 memset(&wma_cfg, 0x0, sizeof(struct q6asm_wma_cfg)); 737 738 wma_cfg.sample_rate = codec->sample_rate; 739 wma_cfg.num_channels = codec->ch_in; 740 wma_cfg.bytes_per_sec = codec->bit_rate / 8; 741 wma_cfg.block_align = codec->align; 742 wma_cfg.bits_per_sample = prtd->bits_per_sample; 743 wma_cfg.enc_options = wma->encoder_option; 744 wma_cfg.adv_enc_options = wma->adv_encoder_option; 745 wma_cfg.adv_enc_options2 = wma->adv_encoder_option2; 746 747 if (wma_cfg.num_channels == 1) 748 wma_cfg.channel_mask = 4; /* Mono Center */ 749 else if (wma_cfg.num_channels == 2) 750 wma_cfg.channel_mask = 3; /* Stereo FL/FR */ 751 else 752 return -EINVAL; 753 754 /* check the codec profile */ 755 switch (codec->profile) { 756 case SND_AUDIOPROFILE_WMA9: 757 wma_cfg.fmtag = 0x161; 758 wma_v9 = 1; 759 break; 760 761 case SND_AUDIOPROFILE_WMA10: 762 wma_cfg.fmtag = 0x166; 763 break; 764 765 case SND_AUDIOPROFILE_WMA9_PRO: 766 wma_cfg.fmtag = 0x162; 767 break; 768 769 case SND_AUDIOPROFILE_WMA9_LOSSLESS: 770 wma_cfg.fmtag = 0x163; 771 break; 772 773 case SND_AUDIOPROFILE_WMA10_LOSSLESS: 774 wma_cfg.fmtag = 0x167; 775 break; 776 777 default: 778 dev_err(dev, "Unknown WMA profile:%x\n", 779 codec->profile); 780 return -EIO; 781 } 782 783 if (wma_v9) 784 ret = q6asm_stream_media_format_block_wma_v9( 785 prtd->audio_client, stream_id, 786 &wma_cfg); 787 else 788 ret = q6asm_stream_media_format_block_wma_v10( 789 prtd->audio_client, stream_id, 790 &wma_cfg); 791 if (ret < 0) { 792 dev_err(dev, "WMA9 CMD failed:%d\n", ret); 793 return -EIO; 794 } 795 break; 796 797 case SND_AUDIOCODEC_ALAC: 798 memset(&alac_cfg, 0x0, sizeof(alac_cfg)); 799 alac = &codec_options->alac_d; 800 801 alac_cfg.sample_rate = codec->sample_rate; 802 alac_cfg.avg_bit_rate = codec->bit_rate; 803 alac_cfg.bit_depth = prtd->bits_per_sample; 804 alac_cfg.num_channels = codec->ch_in; 805 806 alac_cfg.frame_length = alac->frame_length; 807 alac_cfg.pb = alac->pb; 808 alac_cfg.mb = alac->mb; 809 alac_cfg.kb = alac->kb; 810 alac_cfg.max_run = alac->max_run; 811 alac_cfg.compatible_version = alac->compatible_version; 812 alac_cfg.max_frame_bytes = alac->max_frame_bytes; 813 814 switch (codec->ch_in) { 815 case 1: 816 alac_cfg.channel_layout_tag = ALAC_CH_LAYOUT_MONO; 817 break; 818 case 2: 819 alac_cfg.channel_layout_tag = ALAC_CH_LAYOUT_STEREO; 820 break; 821 } 822 ret = q6asm_stream_media_format_block_alac(prtd->audio_client, 823 stream_id, 824 &alac_cfg); 825 if (ret < 0) { 826 dev_err(dev, "ALAC CMD Format block failed:%d\n", ret); 827 return -EIO; 828 } 829 break; 830 831 case SND_AUDIOCODEC_APE: 832 memset(&ape_cfg, 0x0, sizeof(ape_cfg)); 833 ape = &codec_options->ape_d; 834 835 ape_cfg.sample_rate = codec->sample_rate; 836 ape_cfg.num_channels = codec->ch_in; 837 ape_cfg.bits_per_sample = prtd->bits_per_sample; 838 839 ape_cfg.compatible_version = ape->compatible_version; 840 ape_cfg.compression_level = ape->compression_level; 841 ape_cfg.format_flags = ape->format_flags; 842 ape_cfg.blocks_per_frame = ape->blocks_per_frame; 843 ape_cfg.final_frame_blocks = ape->final_frame_blocks; 844 ape_cfg.total_frames = ape->total_frames; 845 ape_cfg.seek_table_present = ape->seek_table_present; 846 847 ret = q6asm_stream_media_format_block_ape(prtd->audio_client, 848 stream_id, 849 &ape_cfg); 850 if (ret < 0) { 851 dev_err(dev, "APE CMD Format block failed:%d\n", ret); 852 return -EIO; 853 } 854 break; 855 856 default: 857 break; 858 } 859 860 return 0; 861 } 862 863 static int q6asm_dai_compr_set_params(struct snd_soc_component *component, 864 struct snd_compr_stream *stream, 865 struct snd_compr_params *params) 866 { 867 struct snd_compr_runtime *runtime = stream->runtime; 868 struct q6asm_dai_rtd *prtd = runtime->private_data; 869 struct snd_soc_pcm_runtime *rtd = stream->private_data; 870 int dir = stream->direction; 871 struct q6asm_dai_data *pdata; 872 struct device *dev = component->dev; 873 int ret; 874 875 pdata = snd_soc_component_get_drvdata(component); 876 if (!pdata) 877 return -EINVAL; 878 879 if (!prtd || !prtd->audio_client) { 880 dev_err(dev, "private data null or audio client freed\n"); 881 return -EINVAL; 882 } 883 884 prtd->periods = runtime->fragments; 885 prtd->pcm_count = runtime->fragment_size; 886 prtd->pcm_size = runtime->fragments * runtime->fragment_size; 887 prtd->bits_per_sample = 16; 888 889 if (dir == SND_COMPRESS_PLAYBACK) { 890 ret = q6asm_open_write(prtd->audio_client, prtd->stream_id, params->codec.id, 891 params->codec.profile, prtd->bits_per_sample, 892 true); 893 894 if (ret < 0) { 895 dev_err(dev, "q6asm_open_write failed\n"); 896 goto open_err; 897 } 898 } 899 900 prtd->session_id = q6asm_get_session_id(prtd->audio_client); 901 ret = q6routing_stream_open(rtd->dai_link->id, LEGACY_PCM_MODE, 902 prtd->session_id, dir); 903 if (ret) { 904 dev_err(dev, "Stream reg failed ret:%d\n", ret); 905 goto q6_err; 906 } 907 908 ret = __q6asm_dai_compr_set_codec_params(component, stream, 909 ¶ms->codec, 910 prtd->stream_id); 911 if (ret) { 912 dev_err(dev, "codec param setup failed ret:%d\n", ret); 913 goto q6_err; 914 } 915 916 ret = q6asm_map_memory_regions(dir, prtd->audio_client, prtd->phys, 917 (prtd->pcm_size / prtd->periods), 918 prtd->periods); 919 920 if (ret < 0) { 921 dev_err(dev, "Buffer Mapping failed ret:%d\n", ret); 922 ret = -ENOMEM; 923 goto q6_err; 924 } 925 926 prtd->state = Q6ASM_STREAM_RUNNING; 927 928 return 0; 929 930 q6_err: 931 q6asm_cmd(prtd->audio_client, prtd->stream_id, CMD_CLOSE); 932 933 open_err: 934 q6asm_audio_client_free(prtd->audio_client); 935 prtd->audio_client = NULL; 936 return ret; 937 } 938 939 static int q6asm_dai_compr_set_metadata(struct snd_soc_component *component, 940 struct snd_compr_stream *stream, 941 struct snd_compr_metadata *metadata) 942 { 943 struct snd_compr_runtime *runtime = stream->runtime; 944 struct q6asm_dai_rtd *prtd = runtime->private_data; 945 int ret = 0; 946 947 switch (metadata->key) { 948 case SNDRV_COMPRESS_ENCODER_PADDING: 949 prtd->trailing_samples_drop = metadata->value[0]; 950 break; 951 case SNDRV_COMPRESS_ENCODER_DELAY: 952 prtd->initial_samples_drop = metadata->value[0]; 953 if (prtd->next_track_stream_id) { 954 ret = q6asm_open_write(prtd->audio_client, 955 prtd->next_track_stream_id, 956 prtd->codec.id, 957 prtd->codec.profile, 958 prtd->bits_per_sample, 959 true); 960 if (ret < 0) { 961 dev_err(component->dev, "q6asm_open_write failed\n"); 962 return ret; 963 } 964 ret = __q6asm_dai_compr_set_codec_params(component, stream, 965 &prtd->codec, 966 prtd->next_track_stream_id); 967 if (ret < 0) { 968 dev_err(component->dev, "q6asm_open_write failed\n"); 969 return ret; 970 } 971 972 ret = q6asm_stream_remove_initial_silence(prtd->audio_client, 973 prtd->next_track_stream_id, 974 prtd->initial_samples_drop); 975 prtd->next_track_stream_id = 0; 976 977 } 978 979 break; 980 default: 981 ret = -EINVAL; 982 break; 983 } 984 985 return ret; 986 } 987 988 static int q6asm_dai_compr_trigger(struct snd_soc_component *component, 989 struct snd_compr_stream *stream, int cmd) 990 { 991 struct snd_compr_runtime *runtime = stream->runtime; 992 struct q6asm_dai_rtd *prtd = runtime->private_data; 993 int ret = 0; 994 995 switch (cmd) { 996 case SNDRV_PCM_TRIGGER_START: 997 case SNDRV_PCM_TRIGGER_RESUME: 998 case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: 999 ret = q6asm_run_nowait(prtd->audio_client, prtd->stream_id, 1000 0, 0, 0); 1001 break; 1002 case SNDRV_PCM_TRIGGER_STOP: 1003 prtd->state = Q6ASM_STREAM_STOPPED; 1004 ret = q6asm_cmd_nowait(prtd->audio_client, prtd->stream_id, 1005 CMD_EOS); 1006 break; 1007 case SNDRV_PCM_TRIGGER_SUSPEND: 1008 case SNDRV_PCM_TRIGGER_PAUSE_PUSH: 1009 ret = q6asm_cmd_nowait(prtd->audio_client, prtd->stream_id, 1010 CMD_PAUSE); 1011 break; 1012 case SND_COMPR_TRIGGER_NEXT_TRACK: 1013 prtd->next_track = true; 1014 prtd->next_track_stream_id = (prtd->stream_id == 1 ? 2 : 1); 1015 break; 1016 case SND_COMPR_TRIGGER_DRAIN: 1017 case SND_COMPR_TRIGGER_PARTIAL_DRAIN: 1018 prtd->notify_on_drain = true; 1019 break; 1020 default: 1021 ret = -EINVAL; 1022 break; 1023 } 1024 1025 return ret; 1026 } 1027 1028 static int q6asm_dai_compr_pointer(struct snd_soc_component *component, 1029 struct snd_compr_stream *stream, 1030 struct snd_compr_tstamp64 *tstamp) 1031 { 1032 struct snd_compr_runtime *runtime = stream->runtime; 1033 struct q6asm_dai_rtd *prtd = runtime->private_data; 1034 unsigned long flags; 1035 uint64_t temp_copied_total; 1036 1037 spin_lock_irqsave(&prtd->lock, flags); 1038 1039 tstamp->copied_total = prtd->copied_total; 1040 temp_copied_total = tstamp->copied_total; 1041 tstamp->byte_offset = do_div(temp_copied_total, prtd->pcm_size); 1042 1043 spin_unlock_irqrestore(&prtd->lock, flags); 1044 1045 return 0; 1046 } 1047 1048 static int q6asm_compr_copy(struct snd_soc_component *component, 1049 struct snd_compr_stream *stream, char __user *buf, 1050 size_t count) 1051 { 1052 struct snd_compr_runtime *runtime = stream->runtime; 1053 struct q6asm_dai_rtd *prtd = runtime->private_data; 1054 unsigned long flags; 1055 u32 wflags = 0; 1056 uint64_t avail, bytes_in_flight = 0; 1057 void *dstn; 1058 size_t copy; 1059 u32 app_pointer; 1060 uint64_t bytes_received; 1061 uint64_t temp_bytes_received; 1062 1063 bytes_received = prtd->bytes_received; 1064 temp_bytes_received = bytes_received; 1065 1066 /** 1067 * Make sure that next track data pointer is aligned at 32 bit boundary 1068 * This is a Mandatory requirement from DSP data buffers alignment 1069 */ 1070 if (prtd->next_track) { 1071 bytes_received = ALIGN(prtd->bytes_received, prtd->pcm_count); 1072 temp_bytes_received = bytes_received; 1073 } 1074 1075 app_pointer = do_div(temp_bytes_received, prtd->pcm_size); 1076 dstn = prtd->dma_buffer.area + app_pointer; 1077 1078 if (count < prtd->pcm_size - app_pointer) { 1079 if (copy_from_user(dstn, buf, count)) 1080 return -EFAULT; 1081 } else { 1082 copy = prtd->pcm_size - app_pointer; 1083 if (copy_from_user(dstn, buf, copy)) 1084 return -EFAULT; 1085 if (copy_from_user(prtd->dma_buffer.area, buf + copy, 1086 count - copy)) 1087 return -EFAULT; 1088 } 1089 1090 spin_lock_irqsave(&prtd->lock, flags); 1091 1092 bytes_in_flight = prtd->bytes_received - prtd->copied_total; 1093 1094 if (prtd->next_track) { 1095 prtd->next_track = false; 1096 prtd->copied_total = ALIGN(prtd->copied_total, prtd->pcm_count); 1097 prtd->bytes_sent = ALIGN(prtd->bytes_sent, prtd->pcm_count); 1098 } 1099 1100 prtd->bytes_received = bytes_received + count; 1101 1102 /* Kick off the data to dsp if its starving!! */ 1103 if (prtd->state == Q6ASM_STREAM_RUNNING && (bytes_in_flight == 0)) { 1104 uint32_t bytes_to_write = prtd->pcm_count; 1105 1106 avail = prtd->bytes_received - prtd->bytes_sent; 1107 1108 if (avail < prtd->pcm_count) 1109 bytes_to_write = avail; 1110 1111 q6asm_write_async(prtd->audio_client, prtd->stream_id, 1112 bytes_to_write, 0, 0, wflags); 1113 prtd->bytes_sent += bytes_to_write; 1114 } 1115 1116 spin_unlock_irqrestore(&prtd->lock, flags); 1117 1118 return count; 1119 } 1120 1121 static int q6asm_dai_compr_mmap(struct snd_soc_component *component, 1122 struct snd_compr_stream *stream, 1123 struct vm_area_struct *vma) 1124 { 1125 struct snd_compr_runtime *runtime = stream->runtime; 1126 struct q6asm_dai_rtd *prtd = runtime->private_data; 1127 struct device *dev = component->dev; 1128 1129 return dma_mmap_coherent(dev, vma, 1130 prtd->dma_buffer.area, prtd->dma_buffer.addr, 1131 prtd->dma_buffer.bytes); 1132 } 1133 1134 static int q6asm_dai_compr_get_caps(struct snd_soc_component *component, 1135 struct snd_compr_stream *stream, 1136 struct snd_compr_caps *caps) 1137 { 1138 caps->direction = SND_COMPRESS_PLAYBACK; 1139 caps->min_fragment_size = COMPR_PLAYBACK_MIN_FRAGMENT_SIZE; 1140 caps->max_fragment_size = COMPR_PLAYBACK_MAX_FRAGMENT_SIZE; 1141 caps->min_fragments = COMPR_PLAYBACK_MIN_NUM_FRAGMENTS; 1142 caps->max_fragments = COMPR_PLAYBACK_MAX_NUM_FRAGMENTS; 1143 caps->num_codecs = 5; 1144 caps->codecs[0] = SND_AUDIOCODEC_MP3; 1145 caps->codecs[1] = SND_AUDIOCODEC_FLAC; 1146 caps->codecs[2] = SND_AUDIOCODEC_WMA; 1147 caps->codecs[3] = SND_AUDIOCODEC_ALAC; 1148 caps->codecs[4] = SND_AUDIOCODEC_APE; 1149 1150 return 0; 1151 } 1152 1153 static int q6asm_dai_compr_get_codec_caps(struct snd_soc_component *component, 1154 struct snd_compr_stream *stream, 1155 struct snd_compr_codec_caps *codec) 1156 { 1157 switch (codec->codec) { 1158 case SND_AUDIOCODEC_MP3: 1159 *codec = q6asm_compr_caps; 1160 break; 1161 default: 1162 break; 1163 } 1164 1165 return 0; 1166 } 1167 1168 static const struct snd_compress_ops q6asm_dai_compress_ops = { 1169 .open = q6asm_dai_compr_open, 1170 .free = q6asm_dai_compr_free, 1171 .set_params = q6asm_dai_compr_set_params, 1172 .set_metadata = q6asm_dai_compr_set_metadata, 1173 .pointer = q6asm_dai_compr_pointer, 1174 .trigger = q6asm_dai_compr_trigger, 1175 .get_caps = q6asm_dai_compr_get_caps, 1176 .get_codec_caps = q6asm_dai_compr_get_codec_caps, 1177 .mmap = q6asm_dai_compr_mmap, 1178 .copy = q6asm_compr_copy, 1179 }; 1180 1181 static int q6asm_dai_pcm_new(struct snd_soc_component *component, 1182 struct snd_soc_pcm_runtime *rtd) 1183 { 1184 struct snd_pcm *pcm = rtd->pcm; 1185 size_t size = q6asm_dai_hardware_playback.buffer_bytes_max; 1186 1187 return snd_pcm_set_fixed_buffer_all(pcm, SNDRV_DMA_TYPE_DEV, 1188 component->dev, size); 1189 } 1190 1191 static const struct snd_soc_dapm_widget q6asm_dapm_widgets[] = { 1192 SND_SOC_DAPM_AIF_IN("MM_DL1", "MultiMedia1 Playback", 0, SND_SOC_NOPM, 0, 0), 1193 SND_SOC_DAPM_AIF_IN("MM_DL2", "MultiMedia2 Playback", 0, SND_SOC_NOPM, 0, 0), 1194 SND_SOC_DAPM_AIF_IN("MM_DL3", "MultiMedia3 Playback", 0, SND_SOC_NOPM, 0, 0), 1195 SND_SOC_DAPM_AIF_IN("MM_DL4", "MultiMedia4 Playback", 0, SND_SOC_NOPM, 0, 0), 1196 SND_SOC_DAPM_AIF_IN("MM_DL5", "MultiMedia5 Playback", 0, SND_SOC_NOPM, 0, 0), 1197 SND_SOC_DAPM_AIF_IN("MM_DL6", "MultiMedia6 Playback", 0, SND_SOC_NOPM, 0, 0), 1198 SND_SOC_DAPM_AIF_IN("MM_DL7", "MultiMedia7 Playback", 0, SND_SOC_NOPM, 0, 0), 1199 SND_SOC_DAPM_AIF_IN("MM_DL8", "MultiMedia8 Playback", 0, SND_SOC_NOPM, 0, 0), 1200 SND_SOC_DAPM_AIF_OUT("MM_UL1", "MultiMedia1 Capture", 0, SND_SOC_NOPM, 0, 0), 1201 SND_SOC_DAPM_AIF_OUT("MM_UL2", "MultiMedia2 Capture", 0, SND_SOC_NOPM, 0, 0), 1202 SND_SOC_DAPM_AIF_OUT("MM_UL3", "MultiMedia3 Capture", 0, SND_SOC_NOPM, 0, 0), 1203 SND_SOC_DAPM_AIF_OUT("MM_UL4", "MultiMedia4 Capture", 0, SND_SOC_NOPM, 0, 0), 1204 SND_SOC_DAPM_AIF_OUT("MM_UL5", "MultiMedia5 Capture", 0, SND_SOC_NOPM, 0, 0), 1205 SND_SOC_DAPM_AIF_OUT("MM_UL6", "MultiMedia6 Capture", 0, SND_SOC_NOPM, 0, 0), 1206 SND_SOC_DAPM_AIF_OUT("MM_UL7", "MultiMedia7 Capture", 0, SND_SOC_NOPM, 0, 0), 1207 SND_SOC_DAPM_AIF_OUT("MM_UL8", "MultiMedia8 Capture", 0, SND_SOC_NOPM, 0, 0), 1208 }; 1209 1210 static const struct snd_soc_component_driver q6asm_fe_dai_component = { 1211 .name = DRV_NAME, 1212 .open = q6asm_dai_open, 1213 .hw_params = q6asm_dai_hw_params, 1214 .close = q6asm_dai_close, 1215 .prepare = q6asm_dai_prepare, 1216 .trigger = q6asm_dai_trigger, 1217 .pointer = q6asm_dai_pointer, 1218 .pcm_construct = q6asm_dai_pcm_new, 1219 .compress_ops = &q6asm_dai_compress_ops, 1220 .dapm_widgets = q6asm_dapm_widgets, 1221 .num_dapm_widgets = ARRAY_SIZE(q6asm_dapm_widgets), 1222 .legacy_dai_naming = 1, 1223 }; 1224 1225 static struct snd_soc_dai_driver q6asm_fe_dais_template[] = { 1226 Q6ASM_FEDAI_DRIVER(1), 1227 Q6ASM_FEDAI_DRIVER(2), 1228 Q6ASM_FEDAI_DRIVER(3), 1229 Q6ASM_FEDAI_DRIVER(4), 1230 Q6ASM_FEDAI_DRIVER(5), 1231 Q6ASM_FEDAI_DRIVER(6), 1232 Q6ASM_FEDAI_DRIVER(7), 1233 Q6ASM_FEDAI_DRIVER(8), 1234 }; 1235 1236 static const struct snd_soc_dai_ops q6asm_dai_ops = { 1237 .compress_new = snd_soc_new_compress, 1238 }; 1239 1240 static int of_q6asm_parse_dai_data(struct device *dev, 1241 struct q6asm_dai_data *pdata) 1242 { 1243 struct snd_soc_dai_driver *dai_drv; 1244 struct snd_soc_pcm_stream empty_stream; 1245 struct device_node *node; 1246 int ret, id, dir, idx = 0; 1247 1248 1249 pdata->num_dais = of_get_child_count(dev->of_node); 1250 if (!pdata->num_dais) { 1251 dev_err(dev, "No dais found in DT\n"); 1252 return -EINVAL; 1253 } 1254 1255 pdata->dais = devm_kcalloc(dev, pdata->num_dais, sizeof(*dai_drv), 1256 GFP_KERNEL); 1257 if (!pdata->dais) 1258 return -ENOMEM; 1259 1260 memset(&empty_stream, 0, sizeof(empty_stream)); 1261 1262 for_each_child_of_node(dev->of_node, node) { 1263 ret = of_property_read_u32(node, "reg", &id); 1264 if (ret || id >= MAX_SESSIONS || id < 0) { 1265 dev_err(dev, "valid dai id not found:%d\n", ret); 1266 continue; 1267 } 1268 1269 dai_drv = &pdata->dais[idx++]; 1270 *dai_drv = q6asm_fe_dais_template[id]; 1271 1272 ret = of_property_read_u32(node, "direction", &dir); 1273 if (ret) 1274 continue; 1275 1276 if (dir == Q6ASM_DAI_RX) 1277 dai_drv->capture = empty_stream; 1278 else if (dir == Q6ASM_DAI_TX) 1279 dai_drv->playback = empty_stream; 1280 1281 if (of_property_read_bool(node, "is-compress-dai")) 1282 dai_drv->ops = &q6asm_dai_ops; 1283 } 1284 1285 return 0; 1286 } 1287 1288 static int q6asm_dai_probe(struct platform_device *pdev) 1289 { 1290 struct device *dev = &pdev->dev; 1291 struct device_node *node = dev->of_node; 1292 struct of_phandle_args args; 1293 struct q6asm_dai_data *pdata; 1294 int rc; 1295 1296 pdata = devm_kzalloc(dev, sizeof(*pdata), GFP_KERNEL); 1297 if (!pdata) 1298 return -ENOMEM; 1299 1300 rc = of_parse_phandle_with_fixed_args(node, "iommus", 1, 0, &args); 1301 if (rc < 0) 1302 pdata->sid = -1; 1303 else 1304 pdata->sid = args.args[0] & SID_MASK_DEFAULT; 1305 1306 dev_set_drvdata(dev, pdata); 1307 1308 rc = of_q6asm_parse_dai_data(dev, pdata); 1309 if (rc) 1310 return rc; 1311 1312 return devm_snd_soc_register_component(dev, &q6asm_fe_dai_component, 1313 pdata->dais, pdata->num_dais); 1314 } 1315 1316 #ifdef CONFIG_OF 1317 static const struct of_device_id q6asm_dai_device_id[] = { 1318 { .compatible = "qcom,q6asm-dais" }, 1319 {}, 1320 }; 1321 MODULE_DEVICE_TABLE(of, q6asm_dai_device_id); 1322 #endif 1323 1324 static struct platform_driver q6asm_dai_platform_driver = { 1325 .driver = { 1326 .name = "q6asm-dai", 1327 .of_match_table = of_match_ptr(q6asm_dai_device_id), 1328 }, 1329 .probe = q6asm_dai_probe, 1330 }; 1331 module_platform_driver(q6asm_dai_platform_driver); 1332 1333 MODULE_DESCRIPTION("Q6ASM dai driver"); 1334 MODULE_LICENSE("GPL v2"); 1335