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