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 <asm/dma.h> 14 #include <linux/dma-mapping.h> 15 #include <linux/of_device.h> 16 #include <sound/pcm_params.h> 17 #include "q6asm.h" 18 #include "q6routing.h" 19 #include "q6dsp-errno.h" 20 21 #define DRV_NAME "q6asm-fe-dai" 22 23 #define PLAYBACK_MIN_NUM_PERIODS 2 24 #define PLAYBACK_MAX_NUM_PERIODS 8 25 #define PLAYBACK_MAX_PERIOD_SIZE 65536 26 #define PLAYBACK_MIN_PERIOD_SIZE 128 27 #define CAPTURE_MIN_NUM_PERIODS 2 28 #define CAPTURE_MAX_NUM_PERIODS 8 29 #define CAPTURE_MAX_PERIOD_SIZE 4096 30 #define CAPTURE_MIN_PERIOD_SIZE 320 31 #define SID_MASK_DEFAULT 0xF 32 33 enum stream_state { 34 Q6ASM_STREAM_IDLE = 0, 35 Q6ASM_STREAM_STOPPED, 36 Q6ASM_STREAM_RUNNING, 37 }; 38 39 struct q6asm_dai_rtd { 40 struct snd_pcm_substream *substream; 41 phys_addr_t phys; 42 unsigned int pcm_size; 43 unsigned int pcm_count; 44 unsigned int pcm_irq_pos; /* IRQ position */ 45 unsigned int periods; 46 uint16_t bits_per_sample; 47 uint16_t source; /* Encoding source bit mask */ 48 struct audio_client *audio_client; 49 uint16_t session_id; 50 enum stream_state state; 51 }; 52 53 struct q6asm_dai_data { 54 long long int sid; 55 }; 56 57 static struct snd_pcm_hardware q6asm_dai_hardware_capture = { 58 .info = (SNDRV_PCM_INFO_MMAP | 59 SNDRV_PCM_INFO_BLOCK_TRANSFER | 60 SNDRV_PCM_INFO_MMAP_VALID | 61 SNDRV_PCM_INFO_INTERLEAVED | 62 SNDRV_PCM_INFO_PAUSE | SNDRV_PCM_INFO_RESUME), 63 .formats = (SNDRV_PCM_FMTBIT_S16_LE | 64 SNDRV_PCM_FMTBIT_S24_LE), 65 .rates = SNDRV_PCM_RATE_8000_48000, 66 .rate_min = 8000, 67 .rate_max = 48000, 68 .channels_min = 1, 69 .channels_max = 4, 70 .buffer_bytes_max = CAPTURE_MAX_NUM_PERIODS * 71 CAPTURE_MAX_PERIOD_SIZE, 72 .period_bytes_min = CAPTURE_MIN_PERIOD_SIZE, 73 .period_bytes_max = CAPTURE_MAX_PERIOD_SIZE, 74 .periods_min = CAPTURE_MIN_NUM_PERIODS, 75 .periods_max = CAPTURE_MAX_NUM_PERIODS, 76 .fifo_size = 0, 77 }; 78 79 static struct snd_pcm_hardware q6asm_dai_hardware_playback = { 80 .info = (SNDRV_PCM_INFO_MMAP | 81 SNDRV_PCM_INFO_BLOCK_TRANSFER | 82 SNDRV_PCM_INFO_MMAP_VALID | 83 SNDRV_PCM_INFO_INTERLEAVED | 84 SNDRV_PCM_INFO_PAUSE | SNDRV_PCM_INFO_RESUME), 85 .formats = (SNDRV_PCM_FMTBIT_S16_LE | 86 SNDRV_PCM_FMTBIT_S24_LE), 87 .rates = SNDRV_PCM_RATE_8000_192000, 88 .rate_min = 8000, 89 .rate_max = 192000, 90 .channels_min = 1, 91 .channels_max = 8, 92 .buffer_bytes_max = (PLAYBACK_MAX_NUM_PERIODS * 93 PLAYBACK_MAX_PERIOD_SIZE), 94 .period_bytes_min = PLAYBACK_MIN_PERIOD_SIZE, 95 .period_bytes_max = PLAYBACK_MAX_PERIOD_SIZE, 96 .periods_min = PLAYBACK_MIN_NUM_PERIODS, 97 .periods_max = PLAYBACK_MAX_NUM_PERIODS, 98 .fifo_size = 0, 99 }; 100 101 #define Q6ASM_FEDAI_DRIVER(num) { \ 102 .playback = { \ 103 .stream_name = "MultiMedia"#num" Playback", \ 104 .rates = (SNDRV_PCM_RATE_8000_192000| \ 105 SNDRV_PCM_RATE_KNOT), \ 106 .formats = (SNDRV_PCM_FMTBIT_S16_LE | \ 107 SNDRV_PCM_FMTBIT_S24_LE), \ 108 .channels_min = 1, \ 109 .channels_max = 8, \ 110 .rate_min = 8000, \ 111 .rate_max = 192000, \ 112 }, \ 113 .capture = { \ 114 .stream_name = "MultiMedia"#num" Capture", \ 115 .rates = (SNDRV_PCM_RATE_8000_48000| \ 116 SNDRV_PCM_RATE_KNOT), \ 117 .formats = (SNDRV_PCM_FMTBIT_S16_LE | \ 118 SNDRV_PCM_FMTBIT_S24_LE), \ 119 .channels_min = 1, \ 120 .channels_max = 4, \ 121 .rate_min = 8000, \ 122 .rate_max = 48000, \ 123 }, \ 124 .name = "MultiMedia"#num, \ 125 .id = MSM_FRONTEND_DAI_MULTIMEDIA##num, \ 126 } 127 128 /* Conventional and unconventional sample rate supported */ 129 static unsigned int supported_sample_rates[] = { 130 8000, 11025, 12000, 16000, 22050, 24000, 32000, 44100, 48000, 131 88200, 96000, 176400, 192000 132 }; 133 134 static struct snd_pcm_hw_constraint_list constraints_sample_rates = { 135 .count = ARRAY_SIZE(supported_sample_rates), 136 .list = supported_sample_rates, 137 .mask = 0, 138 }; 139 140 static void event_handler(uint32_t opcode, uint32_t token, 141 uint32_t *payload, void *priv) 142 { 143 struct q6asm_dai_rtd *prtd = priv; 144 struct snd_pcm_substream *substream = prtd->substream; 145 146 switch (opcode) { 147 case ASM_CLIENT_EVENT_CMD_RUN_DONE: 148 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) 149 q6asm_write_async(prtd->audio_client, 150 prtd->pcm_count, 0, 0, NO_TIMESTAMP); 151 break; 152 case ASM_CLIENT_EVENT_CMD_EOS_DONE: 153 prtd->state = Q6ASM_STREAM_STOPPED; 154 break; 155 case ASM_CLIENT_EVENT_DATA_WRITE_DONE: { 156 prtd->pcm_irq_pos += prtd->pcm_count; 157 snd_pcm_period_elapsed(substream); 158 if (prtd->state == Q6ASM_STREAM_RUNNING) 159 q6asm_write_async(prtd->audio_client, 160 prtd->pcm_count, 0, 0, NO_TIMESTAMP); 161 162 break; 163 } 164 case ASM_CLIENT_EVENT_DATA_READ_DONE: 165 prtd->pcm_irq_pos += prtd->pcm_count; 166 snd_pcm_period_elapsed(substream); 167 if (prtd->state == Q6ASM_STREAM_RUNNING) 168 q6asm_read(prtd->audio_client); 169 170 break; 171 default: 172 break; 173 } 174 } 175 176 static int q6asm_dai_prepare(struct snd_pcm_substream *substream) 177 { 178 struct snd_pcm_runtime *runtime = substream->runtime; 179 struct snd_soc_pcm_runtime *soc_prtd = substream->private_data; 180 struct q6asm_dai_rtd *prtd = runtime->private_data; 181 struct snd_soc_component *c = snd_soc_rtdcom_lookup(soc_prtd, DRV_NAME); 182 struct q6asm_dai_data *pdata; 183 int ret, i; 184 185 pdata = snd_soc_component_get_drvdata(c); 186 if (!pdata) 187 return -EINVAL; 188 189 if (!prtd || !prtd->audio_client) { 190 pr_err("%s: private data null or audio client freed\n", 191 __func__); 192 return -EINVAL; 193 } 194 195 prtd->pcm_count = snd_pcm_lib_period_bytes(substream); 196 prtd->pcm_irq_pos = 0; 197 /* rate and channels are sent to audio driver */ 198 if (prtd->state) { 199 /* clear the previous setup if any */ 200 q6asm_cmd(prtd->audio_client, CMD_CLOSE); 201 q6asm_unmap_memory_regions(substream->stream, 202 prtd->audio_client); 203 q6routing_stream_close(soc_prtd->dai_link->id, 204 substream->stream); 205 } 206 207 ret = q6asm_map_memory_regions(substream->stream, prtd->audio_client, 208 prtd->phys, 209 (prtd->pcm_size / prtd->periods), 210 prtd->periods); 211 212 if (ret < 0) { 213 pr_err("Audio Start: Buffer Allocation failed rc = %d\n", 214 ret); 215 return -ENOMEM; 216 } 217 218 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { 219 ret = q6asm_open_write(prtd->audio_client, FORMAT_LINEAR_PCM, 220 prtd->bits_per_sample); 221 } else if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) { 222 ret = q6asm_open_read(prtd->audio_client, FORMAT_LINEAR_PCM, 223 prtd->bits_per_sample); 224 } 225 226 if (ret < 0) { 227 pr_err("%s: q6asm_open_write failed\n", __func__); 228 q6asm_audio_client_free(prtd->audio_client); 229 prtd->audio_client = NULL; 230 return -ENOMEM; 231 } 232 233 prtd->session_id = q6asm_get_session_id(prtd->audio_client); 234 ret = q6routing_stream_open(soc_prtd->dai_link->id, LEGACY_PCM_MODE, 235 prtd->session_id, substream->stream); 236 if (ret) { 237 pr_err("%s: stream reg failed ret:%d\n", __func__, ret); 238 return ret; 239 } 240 241 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { 242 ret = q6asm_media_format_block_multi_ch_pcm( 243 prtd->audio_client, runtime->rate, 244 runtime->channels, NULL, 245 prtd->bits_per_sample); 246 } else if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) { 247 ret = q6asm_enc_cfg_blk_pcm_format_support(prtd->audio_client, 248 runtime->rate, runtime->channels, 249 prtd->bits_per_sample); 250 251 /* Queue the buffers */ 252 for (i = 0; i < runtime->periods; i++) 253 q6asm_read(prtd->audio_client); 254 255 } 256 if (ret < 0) 257 pr_info("%s: CMD Format block failed\n", __func__); 258 259 prtd->state = Q6ASM_STREAM_RUNNING; 260 261 return 0; 262 } 263 264 static int q6asm_dai_trigger(struct snd_pcm_substream *substream, int cmd) 265 { 266 int ret = 0; 267 struct snd_pcm_runtime *runtime = substream->runtime; 268 struct q6asm_dai_rtd *prtd = runtime->private_data; 269 270 switch (cmd) { 271 case SNDRV_PCM_TRIGGER_START: 272 case SNDRV_PCM_TRIGGER_RESUME: 273 case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: 274 ret = q6asm_run_nowait(prtd->audio_client, 0, 0, 0); 275 break; 276 case SNDRV_PCM_TRIGGER_STOP: 277 prtd->state = Q6ASM_STREAM_STOPPED; 278 ret = q6asm_cmd_nowait(prtd->audio_client, CMD_EOS); 279 break; 280 case SNDRV_PCM_TRIGGER_SUSPEND: 281 case SNDRV_PCM_TRIGGER_PAUSE_PUSH: 282 ret = q6asm_cmd_nowait(prtd->audio_client, CMD_PAUSE); 283 break; 284 default: 285 ret = -EINVAL; 286 break; 287 } 288 289 return ret; 290 } 291 292 static int q6asm_dai_open(struct snd_pcm_substream *substream) 293 { 294 struct snd_pcm_runtime *runtime = substream->runtime; 295 struct snd_soc_pcm_runtime *soc_prtd = substream->private_data; 296 struct snd_soc_dai *cpu_dai = soc_prtd->cpu_dai; 297 struct snd_soc_component *c = snd_soc_rtdcom_lookup(soc_prtd, DRV_NAME); 298 struct q6asm_dai_rtd *prtd; 299 struct q6asm_dai_data *pdata; 300 struct device *dev = c->dev; 301 int ret = 0; 302 int stream_id; 303 304 stream_id = cpu_dai->driver->id; 305 306 pdata = snd_soc_component_get_drvdata(c); 307 if (!pdata) { 308 pr_err("Drv data not found ..\n"); 309 return -EINVAL; 310 } 311 312 prtd = kzalloc(sizeof(struct q6asm_dai_rtd), GFP_KERNEL); 313 if (prtd == NULL) 314 return -ENOMEM; 315 316 prtd->substream = substream; 317 prtd->audio_client = q6asm_audio_client_alloc(dev, 318 (q6asm_cb)event_handler, prtd, stream_id, 319 LEGACY_PCM_MODE); 320 if (IS_ERR(prtd->audio_client)) { 321 pr_info("%s: Could not allocate memory\n", __func__); 322 ret = PTR_ERR(prtd->audio_client); 323 kfree(prtd); 324 return ret; 325 } 326 327 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) 328 runtime->hw = q6asm_dai_hardware_playback; 329 else if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) 330 runtime->hw = q6asm_dai_hardware_capture; 331 332 ret = snd_pcm_hw_constraint_list(runtime, 0, 333 SNDRV_PCM_HW_PARAM_RATE, 334 &constraints_sample_rates); 335 if (ret < 0) 336 pr_info("snd_pcm_hw_constraint_list failed\n"); 337 /* Ensure that buffer size is a multiple of period size */ 338 ret = snd_pcm_hw_constraint_integer(runtime, 339 SNDRV_PCM_HW_PARAM_PERIODS); 340 if (ret < 0) 341 pr_info("snd_pcm_hw_constraint_integer failed\n"); 342 343 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { 344 ret = snd_pcm_hw_constraint_minmax(runtime, 345 SNDRV_PCM_HW_PARAM_BUFFER_BYTES, 346 PLAYBACK_MIN_NUM_PERIODS * PLAYBACK_MIN_PERIOD_SIZE, 347 PLAYBACK_MAX_NUM_PERIODS * PLAYBACK_MAX_PERIOD_SIZE); 348 if (ret < 0) { 349 pr_err("constraint for buffer bytes min max ret = %d\n", 350 ret); 351 } 352 } 353 354 ret = snd_pcm_hw_constraint_step(runtime, 0, 355 SNDRV_PCM_HW_PARAM_PERIOD_BYTES, 32); 356 if (ret < 0) { 357 pr_err("constraint for period bytes step ret = %d\n", 358 ret); 359 } 360 ret = snd_pcm_hw_constraint_step(runtime, 0, 361 SNDRV_PCM_HW_PARAM_BUFFER_BYTES, 32); 362 if (ret < 0) { 363 pr_err("constraint for buffer bytes step ret = %d\n", 364 ret); 365 } 366 367 runtime->private_data = prtd; 368 369 snd_soc_set_runtime_hwparams(substream, &q6asm_dai_hardware_playback); 370 371 runtime->dma_bytes = q6asm_dai_hardware_playback.buffer_bytes_max; 372 373 374 if (pdata->sid < 0) 375 prtd->phys = substream->dma_buffer.addr; 376 else 377 prtd->phys = substream->dma_buffer.addr | (pdata->sid << 32); 378 379 snd_pcm_set_runtime_buffer(substream, &substream->dma_buffer); 380 381 return 0; 382 } 383 384 static int q6asm_dai_close(struct snd_pcm_substream *substream) 385 { 386 struct snd_pcm_runtime *runtime = substream->runtime; 387 struct snd_soc_pcm_runtime *soc_prtd = substream->private_data; 388 struct q6asm_dai_rtd *prtd = runtime->private_data; 389 390 if (prtd->audio_client) { 391 if (prtd->state) 392 q6asm_cmd(prtd->audio_client, CMD_CLOSE); 393 394 q6asm_unmap_memory_regions(substream->stream, 395 prtd->audio_client); 396 q6asm_audio_client_free(prtd->audio_client); 397 prtd->audio_client = NULL; 398 } 399 q6routing_stream_close(soc_prtd->dai_link->id, 400 substream->stream); 401 kfree(prtd); 402 return 0; 403 } 404 405 static snd_pcm_uframes_t q6asm_dai_pointer(struct snd_pcm_substream *substream) 406 { 407 408 struct snd_pcm_runtime *runtime = substream->runtime; 409 struct q6asm_dai_rtd *prtd = runtime->private_data; 410 411 if (prtd->pcm_irq_pos >= prtd->pcm_size) 412 prtd->pcm_irq_pos = 0; 413 414 return bytes_to_frames(runtime, (prtd->pcm_irq_pos)); 415 } 416 417 static int q6asm_dai_mmap(struct snd_pcm_substream *substream, 418 struct vm_area_struct *vma) 419 { 420 421 struct snd_pcm_runtime *runtime = substream->runtime; 422 struct snd_soc_pcm_runtime *soc_prtd = substream->private_data; 423 struct snd_soc_component *c = snd_soc_rtdcom_lookup(soc_prtd, DRV_NAME); 424 struct device *dev = c->dev; 425 426 return dma_mmap_coherent(dev, vma, 427 runtime->dma_area, runtime->dma_addr, 428 runtime->dma_bytes); 429 } 430 431 static int q6asm_dai_hw_params(struct snd_pcm_substream *substream, 432 struct snd_pcm_hw_params *params) 433 { 434 struct snd_pcm_runtime *runtime = substream->runtime; 435 struct q6asm_dai_rtd *prtd = runtime->private_data; 436 437 prtd->pcm_size = params_buffer_bytes(params); 438 prtd->periods = params_periods(params); 439 440 switch (params_format(params)) { 441 case SNDRV_PCM_FORMAT_S16_LE: 442 prtd->bits_per_sample = 16; 443 break; 444 case SNDRV_PCM_FORMAT_S24_LE: 445 prtd->bits_per_sample = 24; 446 break; 447 } 448 449 return 0; 450 } 451 452 static struct snd_pcm_ops q6asm_dai_ops = { 453 .open = q6asm_dai_open, 454 .hw_params = q6asm_dai_hw_params, 455 .close = q6asm_dai_close, 456 .ioctl = snd_pcm_lib_ioctl, 457 .prepare = q6asm_dai_prepare, 458 .trigger = q6asm_dai_trigger, 459 .pointer = q6asm_dai_pointer, 460 .mmap = q6asm_dai_mmap, 461 }; 462 463 static int q6asm_dai_pcm_new(struct snd_soc_pcm_runtime *rtd) 464 { 465 struct snd_pcm_substream *psubstream, *csubstream; 466 struct snd_soc_component *c = snd_soc_rtdcom_lookup(rtd, DRV_NAME); 467 struct snd_pcm *pcm = rtd->pcm; 468 struct device *dev; 469 int size, ret; 470 471 dev = c->dev; 472 size = q6asm_dai_hardware_playback.buffer_bytes_max; 473 psubstream = pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream; 474 if (psubstream) { 475 ret = snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, dev, size, 476 &psubstream->dma_buffer); 477 if (ret) { 478 dev_err(dev, "Cannot allocate buffer(s)\n"); 479 return ret; 480 } 481 } 482 483 csubstream = pcm->streams[SNDRV_PCM_STREAM_CAPTURE].substream; 484 if (csubstream) { 485 ret = snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, dev, size, 486 &csubstream->dma_buffer); 487 if (ret) { 488 dev_err(dev, "Cannot allocate buffer(s)\n"); 489 if (psubstream) 490 snd_dma_free_pages(&psubstream->dma_buffer); 491 return ret; 492 } 493 } 494 495 return 0; 496 } 497 498 static void q6asm_dai_pcm_free(struct snd_pcm *pcm) 499 { 500 struct snd_pcm_substream *substream; 501 int i; 502 503 for (i = 0; i < ARRAY_SIZE(pcm->streams); i++) { 504 substream = pcm->streams[i].substream; 505 if (substream) { 506 snd_dma_free_pages(&substream->dma_buffer); 507 substream->dma_buffer.area = NULL; 508 substream->dma_buffer.addr = 0; 509 } 510 } 511 } 512 513 static const struct snd_soc_component_driver q6asm_fe_dai_component = { 514 .name = DRV_NAME, 515 .ops = &q6asm_dai_ops, 516 .pcm_new = q6asm_dai_pcm_new, 517 .pcm_free = q6asm_dai_pcm_free, 518 519 }; 520 521 static struct snd_soc_dai_driver q6asm_fe_dais[] = { 522 Q6ASM_FEDAI_DRIVER(1), 523 Q6ASM_FEDAI_DRIVER(2), 524 Q6ASM_FEDAI_DRIVER(3), 525 Q6ASM_FEDAI_DRIVER(4), 526 Q6ASM_FEDAI_DRIVER(5), 527 Q6ASM_FEDAI_DRIVER(6), 528 Q6ASM_FEDAI_DRIVER(7), 529 Q6ASM_FEDAI_DRIVER(8), 530 }; 531 532 static int q6asm_dai_probe(struct platform_device *pdev) 533 { 534 struct device *dev = &pdev->dev; 535 struct device_node *node = dev->of_node; 536 struct of_phandle_args args; 537 struct q6asm_dai_data *pdata; 538 int rc; 539 540 pdata = devm_kzalloc(dev, sizeof(*pdata), GFP_KERNEL); 541 if (!pdata) 542 return -ENOMEM; 543 544 rc = of_parse_phandle_with_fixed_args(node, "iommus", 1, 0, &args); 545 if (rc < 0) 546 pdata->sid = -1; 547 else 548 pdata->sid = args.args[0] & SID_MASK_DEFAULT; 549 550 dev_set_drvdata(dev, pdata); 551 552 return devm_snd_soc_register_component(dev, &q6asm_fe_dai_component, 553 q6asm_fe_dais, 554 ARRAY_SIZE(q6asm_fe_dais)); 555 } 556 557 static const struct of_device_id q6asm_dai_device_id[] = { 558 { .compatible = "qcom,q6asm-dais" }, 559 {}, 560 }; 561 MODULE_DEVICE_TABLE(of, q6asm_dai_device_id); 562 563 static struct platform_driver q6asm_dai_platform_driver = { 564 .driver = { 565 .name = "q6asm-dai", 566 .of_match_table = of_match_ptr(q6asm_dai_device_id), 567 }, 568 .probe = q6asm_dai_probe, 569 }; 570 module_platform_driver(q6asm_dai_platform_driver); 571 572 MODULE_DESCRIPTION("Q6ASM dai driver"); 573 MODULE_LICENSE("GPL v2"); 574