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