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