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