1 // SPDX-License-Identifier: GPL-2.0-only 2 // 3 // Copyright(c) 2020 Intel Corporation 4 // 5 // Author: Cezary Rojewski <cezary.rojewski@intel.com> 6 // 7 8 #include <linux/cleanup.h> 9 #include <linux/pm_runtime.h> 10 #include <sound/soc.h> 11 #include <sound/pcm_params.h> 12 #include <uapi/sound/tlv.h> 13 #include "core.h" 14 #include "messages.h" 15 16 struct catpt_stream_template { 17 enum catpt_path_id path_id; 18 enum catpt_stream_type type; 19 u32 persistent_size; 20 u8 num_entries; 21 struct catpt_module_entry entries[]; 22 }; 23 24 static struct catpt_stream_template system_pb = { 25 .path_id = CATPT_PATH_SSP0_OUT, 26 .type = CATPT_STRM_TYPE_SYSTEM, 27 .num_entries = 1, 28 .entries = {{ CATPT_MODID_PCM_SYSTEM, 0 }}, 29 }; 30 31 static struct catpt_stream_template system_cp = { 32 .path_id = CATPT_PATH_SSP0_IN, 33 .type = CATPT_STRM_TYPE_CAPTURE, 34 .num_entries = 1, 35 .entries = {{ CATPT_MODID_PCM_CAPTURE, 0 }}, 36 }; 37 38 static struct catpt_stream_template offload_pb = { 39 .path_id = CATPT_PATH_SSP0_OUT, 40 .type = CATPT_STRM_TYPE_RENDER, 41 .num_entries = 1, 42 .entries = {{ CATPT_MODID_PCM, 0 }}, 43 }; 44 45 static struct catpt_stream_template loopback_cp = { 46 .path_id = CATPT_PATH_SSP0_OUT, 47 .type = CATPT_STRM_TYPE_LOOPBACK, 48 .num_entries = 1, 49 .entries = {{ CATPT_MODID_PCM_REFERENCE, 0 }}, 50 }; 51 52 static struct catpt_stream_template bluetooth_pb = { 53 .path_id = CATPT_PATH_SSP1_OUT, 54 .type = CATPT_STRM_TYPE_BLUETOOTH_RENDER, 55 .num_entries = 1, 56 .entries = {{ CATPT_MODID_BLUETOOTH_RENDER, 0 }}, 57 }; 58 59 static struct catpt_stream_template bluetooth_cp = { 60 .path_id = CATPT_PATH_SSP1_IN, 61 .type = CATPT_STRM_TYPE_BLUETOOTH_CAPTURE, 62 .num_entries = 1, 63 .entries = {{ CATPT_MODID_BLUETOOTH_CAPTURE, 0 }}, 64 }; 65 66 static struct catpt_stream_template *catpt_topology[] = { 67 [CATPT_STRM_TYPE_RENDER] = &offload_pb, 68 [CATPT_STRM_TYPE_SYSTEM] = &system_pb, 69 [CATPT_STRM_TYPE_CAPTURE] = &system_cp, 70 [CATPT_STRM_TYPE_LOOPBACK] = &loopback_cp, 71 [CATPT_STRM_TYPE_BLUETOOTH_RENDER] = &bluetooth_pb, 72 [CATPT_STRM_TYPE_BLUETOOTH_CAPTURE] = &bluetooth_cp, 73 }; 74 75 static struct catpt_stream_template * 76 catpt_get_stream_template(struct snd_pcm_substream *substream) 77 { 78 struct snd_soc_pcm_runtime *rtm = snd_soc_substream_to_rtd(substream); 79 struct snd_soc_dai *cpu_dai = snd_soc_rtd_to_cpu(rtm, 0); 80 enum catpt_stream_type type; 81 82 type = cpu_dai->driver->id; 83 84 /* account for capture in bidirectional dais */ 85 switch (type) { 86 case CATPT_STRM_TYPE_SYSTEM: 87 if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) 88 type = CATPT_STRM_TYPE_CAPTURE; 89 break; 90 case CATPT_STRM_TYPE_BLUETOOTH_RENDER: 91 if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) 92 type = CATPT_STRM_TYPE_BLUETOOTH_CAPTURE; 93 break; 94 default: 95 break; 96 } 97 98 return catpt_topology[type]; 99 } 100 101 /* Caller responsible for holding ->stream_mutex. */ 102 struct catpt_stream_runtime * 103 catpt_stream_find(struct catpt_dev *cdev, u8 stream_hw_id) 104 { 105 struct catpt_stream_runtime *pos, *result = NULL; 106 107 list_for_each_entry(pos, &cdev->stream_list, node) { 108 if (pos->info.stream_hw_id == stream_hw_id) { 109 result = pos; 110 break; 111 } 112 } 113 114 return result; 115 } 116 117 /* Caller responsible for holding ->stream_mutex. */ 118 static u8 catpt_stream_hw_id(struct catpt_dev *cdev, enum catpt_pin_id pin_id) 119 { 120 struct catpt_stream_runtime *stream; 121 122 switch (pin_id) { 123 default: 124 stream = catpt_stream_find(cdev, pin_id); 125 if (stream) 126 return stream->info.stream_hw_id; 127 break; 128 case CATPT_PIN_ID_MIXER: 129 if (!list_empty(&cdev->stream_list)) 130 return cdev->mixer.mixer_hw_id; 131 break; 132 } 133 134 return CATPT_PIN_ID_INVALID; 135 } 136 137 /* Caller responsible for holding ->stream_mutex. */ 138 static u32 *catpt_stream_volume_regs(struct catpt_dev *cdev, enum catpt_pin_id pin_id) 139 { 140 struct catpt_stream_runtime *stream; 141 142 switch (pin_id) { 143 case CATPT_PIN_ID_MIXER: 144 if (!list_empty(&cdev->stream_list)) 145 return &cdev->mixer.volume_regaddr[0]; 146 break; 147 default: 148 stream = catpt_stream_find(cdev, pin_id); 149 if (stream) 150 return &stream->info.volume_regaddr[0]; 151 break; 152 } 153 154 return NULL; 155 } 156 157 static void catpt_stream_read_position(struct catpt_dev *cdev, 158 struct catpt_stream_runtime *stream, u32 *pos) 159 { 160 memcpy_fromio(pos, cdev->lpe_ba + stream->info.read_pos_regaddr, sizeof(*pos)); 161 } 162 163 static void catpt_arrange_page_table(struct snd_pcm_substream *substream, 164 struct snd_dma_buffer *pgtbl) 165 { 166 struct snd_pcm_runtime *rtm = substream->runtime; 167 struct snd_dma_buffer *databuf = snd_pcm_get_dma_buf(substream); 168 int i, pages; 169 170 pages = snd_sgbuf_aligned_pages(rtm->dma_bytes); 171 172 for (i = 0; i < pages; i++) { 173 u32 pfn, offset; 174 u32 *page_table; 175 176 pfn = PFN_DOWN(snd_sgbuf_get_addr(databuf, i * PAGE_SIZE)); 177 /* incrementing by 2 on even and 3 on odd */ 178 offset = ((i << 2) + i) >> 1; 179 page_table = (u32 *)(pgtbl->area + offset); 180 181 if (i & 1) 182 *page_table |= (pfn << 4); 183 else 184 *page_table |= pfn; 185 } 186 } 187 188 static u32 catpt_get_channel_map(enum catpt_channel_config config) 189 { 190 switch (config) { 191 case CATPT_CHANNEL_CONFIG_MONO: 192 return GENMASK(31, 4) | CATPT_CHANNEL_CENTER; 193 194 case CATPT_CHANNEL_CONFIG_STEREO: 195 return GENMASK(31, 8) | CATPT_CHANNEL_LEFT 196 | (CATPT_CHANNEL_RIGHT << 4); 197 198 case CATPT_CHANNEL_CONFIG_2_POINT_1: 199 return GENMASK(31, 12) | CATPT_CHANNEL_LEFT 200 | (CATPT_CHANNEL_RIGHT << 4) 201 | (CATPT_CHANNEL_LFE << 8); 202 203 case CATPT_CHANNEL_CONFIG_3_POINT_0: 204 return GENMASK(31, 12) | CATPT_CHANNEL_LEFT 205 | (CATPT_CHANNEL_CENTER << 4) 206 | (CATPT_CHANNEL_RIGHT << 8); 207 208 case CATPT_CHANNEL_CONFIG_3_POINT_1: 209 return GENMASK(31, 16) | CATPT_CHANNEL_LEFT 210 | (CATPT_CHANNEL_CENTER << 4) 211 | (CATPT_CHANNEL_RIGHT << 8) 212 | (CATPT_CHANNEL_LFE << 12); 213 214 case CATPT_CHANNEL_CONFIG_QUATRO: 215 return GENMASK(31, 16) | CATPT_CHANNEL_LEFT 216 | (CATPT_CHANNEL_RIGHT << 4) 217 | (CATPT_CHANNEL_LEFT_SURROUND << 8) 218 | (CATPT_CHANNEL_RIGHT_SURROUND << 12); 219 220 case CATPT_CHANNEL_CONFIG_4_POINT_0: 221 return GENMASK(31, 16) | CATPT_CHANNEL_LEFT 222 | (CATPT_CHANNEL_CENTER << 4) 223 | (CATPT_CHANNEL_RIGHT << 8) 224 | (CATPT_CHANNEL_CENTER_SURROUND << 12); 225 226 case CATPT_CHANNEL_CONFIG_5_POINT_0: 227 return GENMASK(31, 20) | CATPT_CHANNEL_LEFT 228 | (CATPT_CHANNEL_CENTER << 4) 229 | (CATPT_CHANNEL_RIGHT << 8) 230 | (CATPT_CHANNEL_LEFT_SURROUND << 12) 231 | (CATPT_CHANNEL_RIGHT_SURROUND << 16); 232 233 case CATPT_CHANNEL_CONFIG_5_POINT_1: 234 return GENMASK(31, 24) | CATPT_CHANNEL_CENTER 235 | (CATPT_CHANNEL_LEFT << 4) 236 | (CATPT_CHANNEL_RIGHT << 8) 237 | (CATPT_CHANNEL_LEFT_SURROUND << 12) 238 | (CATPT_CHANNEL_RIGHT_SURROUND << 16) 239 | (CATPT_CHANNEL_LFE << 20); 240 241 case CATPT_CHANNEL_CONFIG_DUAL_MONO: 242 return GENMASK(31, 8) | CATPT_CHANNEL_LEFT 243 | (CATPT_CHANNEL_LEFT << 4); 244 245 default: 246 return U32_MAX; 247 } 248 } 249 250 static enum catpt_channel_config catpt_get_channel_config(u32 num_channels) 251 { 252 switch (num_channels) { 253 case 6: 254 return CATPT_CHANNEL_CONFIG_5_POINT_1; 255 case 5: 256 return CATPT_CHANNEL_CONFIG_5_POINT_0; 257 case 4: 258 return CATPT_CHANNEL_CONFIG_QUATRO; 259 case 3: 260 return CATPT_CHANNEL_CONFIG_2_POINT_1; 261 case 1: 262 return CATPT_CHANNEL_CONFIG_MONO; 263 case 2: 264 default: 265 return CATPT_CHANNEL_CONFIG_STEREO; 266 } 267 } 268 269 static int catpt_dai_startup(struct snd_pcm_substream *substream, 270 struct snd_soc_dai *dai) 271 { 272 struct catpt_stream_template *template; 273 struct catpt_stream_runtime *stream; 274 struct catpt_dev *cdev = dev_get_drvdata(dai->dev); 275 struct resource *res; 276 int ret; 277 278 template = catpt_get_stream_template(substream); 279 280 stream = kzalloc_obj(*stream); 281 if (!stream) 282 return -ENOMEM; 283 284 ret = snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, cdev->dev, PAGE_SIZE, 285 &stream->pgtbl); 286 if (ret) 287 goto err_pgtbl; 288 289 res = catpt_request_region(&cdev->dram, template->persistent_size); 290 if (!res) { 291 ret = -EBUSY; 292 goto err_request; 293 } 294 295 catpt_dsp_update_srampge(cdev, &cdev->dram, cdev->spec->dram_mask); 296 297 stream->template = template; 298 stream->persistent = res; 299 stream->substream = substream; 300 INIT_LIST_HEAD(&stream->node); 301 snd_soc_dai_set_dma_data(dai, substream, stream); 302 303 return 0; 304 305 err_request: 306 snd_dma_free_pages(&stream->pgtbl); 307 err_pgtbl: 308 kfree(stream); 309 return ret; 310 } 311 312 static void catpt_dai_shutdown(struct snd_pcm_substream *substream, 313 struct snd_soc_dai *dai) 314 { 315 struct catpt_stream_runtime *stream; 316 struct catpt_dev *cdev = dev_get_drvdata(dai->dev); 317 318 stream = snd_soc_dai_get_dma_data(dai, substream); 319 320 release_resource(stream->persistent); 321 kfree(stream->persistent); 322 catpt_dsp_update_srampge(cdev, &cdev->dram, cdev->spec->dram_mask); 323 324 snd_dma_free_pages(&stream->pgtbl); 325 kfree(stream); 326 snd_soc_dai_set_dma_data(dai, substream, NULL); 327 } 328 329 static int catpt_set_dspvol(struct catpt_dev *cdev, u8 stream_id, long *ctlvol); 330 331 struct catpt_control_data { 332 enum catpt_pin_id pin_id; 333 long volumes[CATPT_CHANNELS_MAX]; 334 }; 335 336 static int catpt_apply_volume(struct catpt_dev *cdev, struct snd_soc_card *card, const char *name) 337 { 338 struct snd_kcontrol *kctl = snd_ctl_find_id_mixer(card->snd_card, name); 339 struct catpt_control_data *data; 340 341 if (!kctl) 342 return -ENOENT; 343 data = (struct catpt_control_data *)kctl->private_value; 344 345 return catpt_set_dspvol(cdev, data->pin_id, data->volumes); 346 } 347 348 static int catpt_apply_mute(struct catpt_dev *cdev, struct snd_soc_card *card) 349 { 350 struct snd_kcontrol *kctl = snd_ctl_find_id_mixer(card->snd_card, "Loopback Mute"); 351 bool mute; 352 int ret; 353 354 if (!kctl) 355 return -ENOENT; 356 mute = *(bool *)kctl->private_value; 357 358 ret = catpt_ipc_mute_loopback(cdev, CATPT_PIN_ID_REFERENCE, mute); 359 return CATPT_IPC_RET(ret); 360 } 361 362 static int catpt_apply_controls(struct catpt_dev *cdev, struct snd_soc_card *card, 363 struct catpt_stream_runtime *stream) 364 { 365 int ret; 366 367 /* Update the master volume when the first stream is opened. */ 368 if (list_empty(&cdev->stream_list)) { 369 ret = catpt_apply_volume(cdev, card, "Master Playback Volume"); 370 if (ret) 371 return ret; 372 } 373 374 /* Only selected streams have individual controls. */ 375 switch (stream->info.stream_hw_id) { 376 case CATPT_PIN_ID_OFFLOAD1: 377 return catpt_apply_volume(cdev, card, "Media0 Playback Volume"); 378 case CATPT_PIN_ID_OFFLOAD2: 379 return catpt_apply_volume(cdev, card, "Media1 Playback Volume"); 380 case CATPT_PIN_ID_CAPTURE1: 381 return catpt_apply_volume(cdev, card, "Mic Capture Volume"); 382 case CATPT_PIN_ID_REFERENCE: 383 return catpt_apply_mute(cdev, card); 384 default: 385 return 0; 386 } 387 } 388 389 static int catpt_dai_hw_params(struct snd_pcm_substream *substream, 390 struct snd_pcm_hw_params *params, 391 struct snd_soc_dai *dai) 392 { 393 struct snd_pcm_runtime *rtm = substream->runtime; 394 struct snd_dma_buffer *dmab; 395 struct catpt_stream_runtime *stream; 396 struct catpt_audio_format afmt; 397 struct catpt_ring_info rinfo; 398 struct catpt_dev *cdev = dev_get_drvdata(dai->dev); 399 int ret; 400 401 stream = snd_soc_dai_get_dma_data(dai, substream); 402 if (stream->allocated) 403 return 0; 404 405 memset(&afmt, 0, sizeof(afmt)); 406 afmt.sample_rate = params_rate(params); 407 afmt.bit_depth = params_physical_width(params); 408 afmt.valid_bit_depth = params_width(params); 409 afmt.num_channels = params_channels(params); 410 afmt.channel_config = catpt_get_channel_config(afmt.num_channels); 411 afmt.channel_map = catpt_get_channel_map(afmt.channel_config); 412 afmt.interleaving = CATPT_INTERLEAVING_PER_CHANNEL; 413 414 dmab = snd_pcm_get_dma_buf(substream); 415 catpt_arrange_page_table(substream, &stream->pgtbl); 416 417 memset(&rinfo, 0, sizeof(rinfo)); 418 rinfo.page_table_addr = stream->pgtbl.addr; 419 rinfo.num_pages = DIV_ROUND_UP(rtm->dma_bytes, PAGE_SIZE); 420 rinfo.size = rtm->dma_bytes; 421 rinfo.offset = 0; 422 rinfo.ring_first_page_pfn = PFN_DOWN(snd_sgbuf_get_addr(dmab, 0)); 423 424 ret = catpt_ipc_alloc_stream(cdev, stream->template->path_id, 425 stream->template->type, 426 &afmt, &rinfo, 427 stream->template->num_entries, 428 stream->template->entries, 429 stream->persistent, 430 cdev->scratch, 431 &stream->info); 432 if (ret) 433 return CATPT_IPC_RET(ret); 434 435 guard(mutex)(&cdev->stream_mutex); 436 437 ret = catpt_apply_controls(cdev, dai->component->card, stream); 438 if (ret) { 439 catpt_ipc_free_stream(cdev, stream->info.stream_hw_id); 440 return ret; 441 } 442 443 list_add_tail(&stream->node, &cdev->stream_list); 444 stream->allocated = true; 445 return 0; 446 } 447 448 static int catpt_dai_hw_free(struct snd_pcm_substream *substream, 449 struct snd_soc_dai *dai) 450 { 451 struct catpt_stream_runtime *stream; 452 struct catpt_dev *cdev = dev_get_drvdata(dai->dev); 453 454 stream = snd_soc_dai_get_dma_data(dai, substream); 455 if (!stream->allocated) 456 return 0; 457 458 mutex_lock(&cdev->stream_mutex); 459 list_del(&stream->node); 460 mutex_unlock(&cdev->stream_mutex); 461 462 catpt_ipc_reset_stream(cdev, stream->info.stream_hw_id); 463 catpt_ipc_free_stream(cdev, stream->info.stream_hw_id); 464 465 stream->allocated = false; 466 return 0; 467 } 468 469 static int catpt_dai_prepare(struct snd_pcm_substream *substream, 470 struct snd_soc_dai *dai) 471 { 472 struct catpt_stream_runtime *stream; 473 struct catpt_dev *cdev = dev_get_drvdata(dai->dev); 474 int ret; 475 476 stream = snd_soc_dai_get_dma_data(dai, substream); 477 if (stream->prepared) 478 return 0; 479 480 ret = catpt_ipc_reset_stream(cdev, stream->info.stream_hw_id); 481 if (ret) 482 return CATPT_IPC_RET(ret); 483 484 ret = catpt_ipc_pause_stream(cdev, stream->info.stream_hw_id); 485 if (ret) 486 return CATPT_IPC_RET(ret); 487 488 stream->prepared = true; 489 return 0; 490 } 491 492 static int catpt_dai_trigger(struct snd_pcm_substream *substream, int cmd, 493 struct snd_soc_dai *dai) 494 { 495 struct snd_pcm_runtime *runtime = substream->runtime; 496 struct catpt_stream_runtime *stream; 497 struct catpt_dev *cdev = dev_get_drvdata(dai->dev); 498 snd_pcm_uframes_t pos; 499 int ret; 500 501 stream = snd_soc_dai_get_dma_data(dai, substream); 502 503 switch (cmd) { 504 case SNDRV_PCM_TRIGGER_START: 505 /* only offload is set_write_pos driven */ 506 if (stream->template->type != CATPT_STRM_TYPE_RENDER) 507 goto resume_stream; 508 509 pos = frames_to_bytes(runtime, runtime->start_threshold); 510 /* 511 * Dsp operates on buffer halves, thus max 2x set_write_pos 512 * (entire buffer filled) prior to stream start. 513 */ 514 ret = catpt_ipc_set_write_pos(cdev, stream->info.stream_hw_id, 515 pos, false, false); 516 if (ret) 517 return CATPT_IPC_RET(ret); 518 fallthrough; 519 case SNDRV_PCM_TRIGGER_RESUME: 520 case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: 521 resume_stream: 522 catpt_dsp_update_lpclock(cdev); 523 ret = catpt_ipc_resume_stream(cdev, stream->info.stream_hw_id); 524 if (ret) 525 return CATPT_IPC_RET(ret); 526 break; 527 528 case SNDRV_PCM_TRIGGER_STOP: 529 stream->prepared = false; 530 fallthrough; 531 case SNDRV_PCM_TRIGGER_SUSPEND: 532 case SNDRV_PCM_TRIGGER_PAUSE_PUSH: 533 ret = catpt_ipc_pause_stream(cdev, stream->info.stream_hw_id); 534 catpt_dsp_update_lpclock(cdev); 535 if (ret) 536 return CATPT_IPC_RET(ret); 537 break; 538 539 default: 540 break; 541 } 542 543 return 0; 544 } 545 546 void catpt_stream_update_position(struct catpt_dev *cdev, 547 struct catpt_stream_runtime *stream, 548 struct catpt_notify_position *pos) 549 { 550 struct snd_pcm_substream *substream = stream->substream; 551 struct snd_pcm_runtime *r = substream->runtime; 552 snd_pcm_uframes_t dsppos, newpos; 553 int ret; 554 555 dsppos = bytes_to_frames(r, pos->stream_position); 556 557 if (!stream->prepared) 558 goto exit; 559 /* only offload is set_write_pos driven */ 560 if (stream->template->type != CATPT_STRM_TYPE_RENDER) 561 goto exit; 562 563 if (dsppos >= r->buffer_size / 2) 564 newpos = r->buffer_size / 2; 565 else 566 newpos = 0; 567 /* 568 * Dsp operates on buffer halves, thus on every notify position 569 * (buffer half consumed) update wp to allow stream progression. 570 */ 571 ret = catpt_ipc_set_write_pos(cdev, stream->info.stream_hw_id, 572 frames_to_bytes(r, newpos), 573 false, false); 574 if (ret) { 575 dev_err(cdev->dev, "update position for stream %d failed: %d\n", 576 stream->info.stream_hw_id, ret); 577 return; 578 } 579 exit: 580 snd_pcm_period_elapsed(substream); 581 } 582 583 /* 200 ms for 2 32-bit channels at 48kHz (native format) */ 584 #define CATPT_BUFFER_MAX_SIZE 76800 585 #define CATPT_PCM_PERIODS_MAX 4 586 #define CATPT_PCM_PERIODS_MIN 2 587 588 static const struct snd_pcm_hardware catpt_pcm_hardware = { 589 .info = SNDRV_PCM_INFO_MMAP | 590 SNDRV_PCM_INFO_MMAP_VALID | 591 SNDRV_PCM_INFO_INTERLEAVED | 592 SNDRV_PCM_INFO_PAUSE | 593 SNDRV_PCM_INFO_RESUME | 594 SNDRV_PCM_INFO_NO_PERIOD_WAKEUP, 595 .formats = SNDRV_PCM_FMTBIT_S16_LE | 596 SNDRV_PCM_FMTBIT_S32_LE, 597 .subformats = SNDRV_PCM_SUBFMTBIT_MSBITS_24 | 598 SNDRV_PCM_SUBFMTBIT_MSBITS_MAX, 599 .period_bytes_min = PAGE_SIZE, 600 .period_bytes_max = CATPT_BUFFER_MAX_SIZE / CATPT_PCM_PERIODS_MIN, 601 .periods_min = CATPT_PCM_PERIODS_MIN, 602 .periods_max = CATPT_PCM_PERIODS_MAX, 603 .buffer_bytes_max = CATPT_BUFFER_MAX_SIZE, 604 }; 605 606 static int catpt_component_pcm_new(struct snd_soc_component *component, 607 struct snd_soc_pcm_runtime *rtm) 608 { 609 struct catpt_dev *cdev = dev_get_drvdata(component->dev); 610 611 snd_pcm_set_managed_buffer_all(rtm->pcm, SNDRV_DMA_TYPE_DEV_SG, 612 cdev->dev, 613 catpt_pcm_hardware.buffer_bytes_max, 614 catpt_pcm_hardware.buffer_bytes_max); 615 616 return 0; 617 } 618 619 static int catpt_component_open(struct snd_soc_component *component, 620 struct snd_pcm_substream *substream) 621 { 622 struct snd_soc_pcm_runtime *rtm = snd_soc_substream_to_rtd(substream); 623 624 if (!rtm->dai_link->no_pcm) 625 snd_soc_set_runtime_hwparams(substream, &catpt_pcm_hardware); 626 return 0; 627 } 628 629 static snd_pcm_uframes_t 630 catpt_component_pointer(struct snd_soc_component *component, 631 struct snd_pcm_substream *substream) 632 { 633 struct snd_soc_pcm_runtime *rtm = snd_soc_substream_to_rtd(substream); 634 struct snd_soc_dai *cpu_dai = snd_soc_rtd_to_cpu(rtm, 0); 635 struct catpt_stream_runtime *stream; 636 struct catpt_dev *cdev = dev_get_drvdata(component->dev); 637 u32 pos; 638 639 if (rtm->dai_link->no_pcm) 640 return 0; 641 642 stream = snd_soc_dai_get_dma_data(cpu_dai, substream); 643 catpt_stream_read_position(cdev, stream, &pos); 644 645 return bytes_to_frames(substream->runtime, pos); 646 } 647 648 static const struct snd_soc_dai_ops catpt_fe_dai_ops = { 649 .startup = catpt_dai_startup, 650 .shutdown = catpt_dai_shutdown, 651 .hw_params = catpt_dai_hw_params, 652 .hw_free = catpt_dai_hw_free, 653 .prepare = catpt_dai_prepare, 654 .trigger = catpt_dai_trigger, 655 }; 656 657 static int catpt_dai_pcm_new(struct snd_soc_pcm_runtime *rtm, 658 struct snd_soc_dai *dai) 659 { 660 struct snd_soc_dai *codec_dai = snd_soc_rtd_to_codec(rtm, 0); 661 struct catpt_ssp_device_format devfmt; 662 struct catpt_dev *cdev = dev_get_drvdata(dai->dev); 663 int ret; 664 665 devfmt.iface = dai->driver->id; 666 devfmt.channels = codec_dai->driver->capture.channels_max; 667 668 switch (devfmt.iface) { 669 case CATPT_SSP_IFACE_0: 670 devfmt.mclk = CATPT_MCLK_FREQ_24_MHZ; 671 672 switch (devfmt.channels) { 673 case 4: 674 devfmt.mode = CATPT_SSP_MODE_TDM_PROVIDER; 675 devfmt.clock_divider = 4; 676 break; 677 case 2: 678 default: 679 devfmt.mode = CATPT_SSP_MODE_I2S_PROVIDER; 680 devfmt.clock_divider = 9; 681 break; 682 } 683 break; 684 685 case CATPT_SSP_IFACE_1: 686 devfmt.mclk = CATPT_MCLK_OFF; 687 devfmt.mode = CATPT_SSP_MODE_I2S_CONSUMER; 688 devfmt.clock_divider = 0; 689 break; 690 } 691 692 /* see if this is a new configuration */ 693 if (!memcmp(&cdev->devfmt[devfmt.iface], &devfmt, sizeof(devfmt))) 694 return 0; 695 696 ret = pm_runtime_resume_and_get(cdev->dev); 697 if (ret) 698 return ret; 699 700 ret = catpt_ipc_set_device_format(cdev, &devfmt); 701 702 pm_runtime_put_autosuspend(cdev->dev); 703 704 if (ret) 705 return CATPT_IPC_RET(ret); 706 707 /* store device format set for given SSP */ 708 memcpy(&cdev->devfmt[devfmt.iface], &devfmt, sizeof(devfmt)); 709 return 0; 710 } 711 712 static const struct snd_soc_dai_ops catpt_dai_ops = { 713 .pcm_new = catpt_dai_pcm_new, 714 }; 715 716 static struct snd_soc_dai_driver dai_drivers[] = { 717 /* FE DAIs */ 718 { 719 .name = "System Pin", 720 .id = CATPT_STRM_TYPE_SYSTEM, 721 .ops = &catpt_fe_dai_ops, 722 .playback = { 723 .stream_name = "System Playback", 724 .channels_min = 2, 725 .channels_max = 2, 726 .rates = SNDRV_PCM_RATE_48000, 727 .formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S32_LE, 728 .subformats = SNDRV_PCM_SUBFMTBIT_MSBITS_24 | 729 SNDRV_PCM_SUBFMTBIT_MSBITS_MAX, 730 }, 731 .capture = { 732 .stream_name = "Analog Capture", 733 .channels_min = 2, 734 .channels_max = 4, 735 .rates = SNDRV_PCM_RATE_48000, 736 .formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S32_LE, 737 .subformats = SNDRV_PCM_SUBFMTBIT_MSBITS_24 | 738 SNDRV_PCM_SUBFMTBIT_MSBITS_MAX, 739 }, 740 }, 741 { 742 .name = "Offload0 Pin", 743 .id = CATPT_STRM_TYPE_RENDER, 744 .ops = &catpt_fe_dai_ops, 745 .playback = { 746 .stream_name = "Offload0 Playback", 747 .channels_min = 2, 748 .channels_max = 2, 749 .rates = SNDRV_PCM_RATE_8000_192000, 750 .formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S32_LE, 751 .subformats = SNDRV_PCM_SUBFMTBIT_MSBITS_24 | 752 SNDRV_PCM_SUBFMTBIT_MSBITS_MAX, 753 }, 754 }, 755 { 756 .name = "Offload1 Pin", 757 .id = CATPT_STRM_TYPE_RENDER, 758 .ops = &catpt_fe_dai_ops, 759 .playback = { 760 .stream_name = "Offload1 Playback", 761 .channels_min = 2, 762 .channels_max = 2, 763 .rates = SNDRV_PCM_RATE_8000_192000, 764 .formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S32_LE, 765 .subformats = SNDRV_PCM_SUBFMTBIT_MSBITS_24 | 766 SNDRV_PCM_SUBFMTBIT_MSBITS_MAX, 767 }, 768 }, 769 { 770 .name = "Loopback Pin", 771 .id = CATPT_STRM_TYPE_LOOPBACK, 772 .ops = &catpt_fe_dai_ops, 773 .capture = { 774 .stream_name = "Loopback Capture", 775 .channels_min = 2, 776 .channels_max = 2, 777 .rates = SNDRV_PCM_RATE_48000, 778 .formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S32_LE, 779 .subformats = SNDRV_PCM_SUBFMTBIT_MSBITS_24 | 780 SNDRV_PCM_SUBFMTBIT_MSBITS_MAX, 781 }, 782 }, 783 { 784 .name = "Bluetooth Pin", 785 .id = CATPT_STRM_TYPE_BLUETOOTH_RENDER, 786 .ops = &catpt_fe_dai_ops, 787 .playback = { 788 .stream_name = "Bluetooth Playback", 789 .channels_min = 1, 790 .channels_max = 1, 791 .rates = SNDRV_PCM_RATE_8000, 792 .formats = SNDRV_PCM_FMTBIT_S16_LE, 793 }, 794 .capture = { 795 .stream_name = "Bluetooth Capture", 796 .channels_min = 1, 797 .channels_max = 1, 798 .rates = SNDRV_PCM_RATE_8000, 799 .formats = SNDRV_PCM_FMTBIT_S16_LE, 800 }, 801 }, 802 /* BE DAIs */ 803 { 804 .name = "ssp0-port", 805 .id = CATPT_SSP_IFACE_0, 806 .playback = { 807 .channels_min = 1, 808 .channels_max = 8, 809 }, 810 .capture = { 811 .channels_min = 1, 812 .channels_max = 8, 813 }, 814 .ops = &catpt_dai_ops, 815 }, 816 { 817 .name = "ssp1-port", 818 .id = CATPT_SSP_IFACE_1, 819 .playback = { 820 .channels_min = 1, 821 .channels_max = 8, 822 }, 823 .capture = { 824 .channels_min = 1, 825 .channels_max = 8, 826 }, 827 .ops = &catpt_dai_ops, 828 }, 829 }; 830 831 #define DSP_VOLUME_MAX S32_MAX /* 0db */ 832 #define DSP_VOLUME_STEP_MAX 30 833 834 static u32 ctlvol_to_dspvol(u32 value) 835 { 836 if (value > DSP_VOLUME_STEP_MAX) 837 value = 0; 838 return DSP_VOLUME_MAX >> (DSP_VOLUME_STEP_MAX - value); 839 } 840 841 static u32 dspvol_to_ctlvol(u32 volume) 842 { 843 if (volume > DSP_VOLUME_MAX) 844 return DSP_VOLUME_STEP_MAX; 845 return volume ? __fls(volume) : 0; 846 } 847 848 static int catpt_set_dspvol(struct catpt_dev *cdev, u8 stream_id, long *ctlvol) 849 { 850 u32 dspvol; 851 int ret, i; 852 853 for (i = 1; i < CATPT_CHANNELS_MAX; i++) 854 if (ctlvol[i] != ctlvol[0]) 855 break; 856 857 if (i == CATPT_CHANNELS_MAX) { 858 dspvol = ctlvol_to_dspvol(ctlvol[0]); 859 860 ret = catpt_ipc_set_volume(cdev, stream_id, 861 CATPT_ALL_CHANNELS_MASK, dspvol, 862 0, CATPT_AUDIO_CURVE_NONE); 863 } else { 864 for (i = 0; i < CATPT_CHANNELS_MAX; i++) { 865 dspvol = ctlvol_to_dspvol(ctlvol[i]); 866 867 ret = catpt_ipc_set_volume(cdev, stream_id, 868 i, dspvol, 869 0, CATPT_AUDIO_CURVE_NONE); 870 if (ret) 871 break; 872 } 873 } 874 875 return CATPT_IPC_RET(ret); 876 } 877 878 static int catpt_volume_info(struct snd_kcontrol *kcontrol, 879 struct snd_ctl_elem_info *uinfo) 880 { 881 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; 882 uinfo->count = CATPT_CHANNELS_MAX; 883 uinfo->value.integer.min = 0; 884 uinfo->value.integer.max = DSP_VOLUME_STEP_MAX; 885 return 0; 886 } 887 888 static int catpt_volume_get(struct snd_kcontrol *kctl, struct snd_ctl_elem_value *uctl) 889 { 890 struct snd_soc_component *component = snd_kcontrol_chip(kctl); 891 struct catpt_dev *cdev = dev_get_drvdata(component->dev); 892 struct catpt_control_data *data; 893 u32 dspvol, *regs; 894 long *uvolumes; 895 int i; 896 897 data = (struct catpt_control_data *)kctl->private_value; 898 uvolumes = &uctl->value.integer.value[0]; 899 900 guard(mutex)(&cdev->stream_mutex); 901 902 regs = catpt_stream_volume_regs(cdev, data->pin_id); 903 if (regs) { 904 for (i = 0; i < CATPT_CHANNELS_MAX; i++) { 905 dspvol = readl(cdev->lpe_ba + regs[i]); 906 data->volumes[i] = dspvol_to_ctlvol(dspvol); 907 } 908 } 909 910 memcpy(uvolumes, data->volumes, sizeof(data->volumes)); 911 return 0; 912 } 913 914 static int catpt_volume_put(struct snd_kcontrol *kctl, struct snd_ctl_elem_value *uctl) 915 { 916 struct snd_soc_component *component = snd_kcontrol_chip(kctl); 917 struct catpt_dev *cdev = dev_get_drvdata(component->dev); 918 struct catpt_control_data *data; 919 u8 stream_hw_id; 920 long *uvolumes; 921 int ret; 922 923 data = (struct catpt_control_data *)kctl->private_value; 924 uvolumes = &uctl->value.integer.value[0]; 925 926 if (!memcmp(data->volumes, uvolumes, sizeof(data->volumes))) 927 return 0; 928 929 guard(mutex)(&cdev->stream_mutex); 930 931 stream_hw_id = catpt_stream_hw_id(cdev, data->pin_id); 932 if (stream_hw_id != CATPT_PIN_ID_INVALID) { 933 ret = catpt_set_dspvol(cdev, stream_hw_id, uvolumes); 934 if (ret) 935 return ret; 936 } 937 938 memcpy(data->volumes, uvolumes, sizeof(data->volumes)); 939 return 1; 940 } 941 942 static int catpt_loopback_mute_get(struct snd_kcontrol *kctl, struct snd_ctl_elem_value *uctl) 943 { 944 uctl->value.integer.value[0] = *(bool *)kctl->private_value; 945 return 0; 946 } 947 948 static int catpt_loopback_mute_put(struct snd_kcontrol *kctl, struct snd_ctl_elem_value *uctl) 949 { 950 struct snd_soc_component *component = snd_kcontrol_chip(kctl); 951 struct catpt_dev *cdev = dev_get_drvdata(component->dev); 952 bool *kmute, cmute; 953 u8 stream_hw_id; 954 int ret; 955 956 kmute = (bool *)kctl->private_value; 957 cmute = (bool)uctl->value.integer.value[0]; 958 959 if (*kmute == cmute) 960 return 0; 961 962 guard(mutex)(&cdev->stream_mutex); 963 964 stream_hw_id = catpt_stream_hw_id(cdev, CATPT_PIN_ID_REFERENCE); 965 if (stream_hw_id != CATPT_PIN_ID_INVALID) { 966 ret = catpt_ipc_mute_loopback(cdev, stream_hw_id, cmute); 967 if (ret) 968 return CATPT_IPC_RET(ret); 969 } 970 971 *kmute = cmute; 972 return 1; 973 } 974 975 static int catpt_waves_switch_get(struct snd_kcontrol *kcontrol, 976 struct snd_ctl_elem_value *ucontrol) 977 { 978 return 0; 979 } 980 981 static int catpt_waves_switch_put(struct snd_kcontrol *kcontrol, 982 struct snd_ctl_elem_value *ucontrol) 983 { 984 return 0; 985 } 986 987 static int catpt_waves_param_get(struct snd_kcontrol *kcontrol, 988 unsigned int __user *bytes, 989 unsigned int size) 990 { 991 return 0; 992 } 993 994 static int catpt_waves_param_put(struct snd_kcontrol *kcontrol, 995 const unsigned int __user *bytes, 996 unsigned int size) 997 { 998 return 0; 999 } 1000 1001 static const SNDRV_CTL_TLVD_DECLARE_DB_SCALE(catpt_volume_tlv, -9000, 300, 1); 1002 1003 #define CATPT_VOLUME_CTL(kname, pname) { \ 1004 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \ 1005 .name = kname, \ 1006 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE | \ 1007 SNDRV_CTL_ELEM_ACCESS_TLV_READ, \ 1008 .info = catpt_volume_info, \ 1009 .get = catpt_volume_get, \ 1010 .put = catpt_volume_put, \ 1011 .tlv.p = catpt_volume_tlv, \ 1012 .private_value = (unsigned long) \ 1013 &(struct catpt_control_data) { CATPT_PIN_ID_##pname } \ 1014 } 1015 1016 static const struct snd_kcontrol_new component_kcontrols[] = { 1017 /* Master volume (mixer stream) */ 1018 CATPT_VOLUME_CTL("Master Playback Volume", MIXER), 1019 /* Individual volume controls for offload and capture */ 1020 CATPT_VOLUME_CTL("Media0 Playback Volume", OFFLOAD1), 1021 CATPT_VOLUME_CTL("Media1 Playback Volume", OFFLOAD2), 1022 CATPT_VOLUME_CTL("Mic Capture Volume", CAPTURE1), 1023 SOC_SINGLE_BOOL_EXT("Loopback Mute", (unsigned long)&(bool[1]) {0}, 1024 catpt_loopback_mute_get, catpt_loopback_mute_put), 1025 /* Enable or disable WAVES module */ 1026 SOC_SINGLE_BOOL_EXT("Waves Switch", 0, 1027 catpt_waves_switch_get, catpt_waves_switch_put), 1028 /* WAVES module parameter control */ 1029 SND_SOC_BYTES_TLV("Waves Set Param", 128, 1030 catpt_waves_param_get, catpt_waves_param_put), 1031 }; 1032 1033 static const struct snd_soc_dapm_widget component_widgets[] = { 1034 SND_SOC_DAPM_AIF_IN("SSP0 CODEC IN", NULL, 0, SND_SOC_NOPM, 0, 0), 1035 SND_SOC_DAPM_AIF_OUT("SSP0 CODEC OUT", NULL, 0, SND_SOC_NOPM, 0, 0), 1036 SND_SOC_DAPM_AIF_IN("SSP1 BT IN", NULL, 0, SND_SOC_NOPM, 0, 0), 1037 SND_SOC_DAPM_AIF_OUT("SSP1 BT OUT", NULL, 0, SND_SOC_NOPM, 0, 0), 1038 1039 SND_SOC_DAPM_MIXER("Playback VMixer", SND_SOC_NOPM, 0, 0, NULL, 0), 1040 }; 1041 1042 static const struct snd_soc_dapm_route component_routes[] = { 1043 {"Playback VMixer", NULL, "System Playback"}, 1044 {"Playback VMixer", NULL, "Offload0 Playback"}, 1045 {"Playback VMixer", NULL, "Offload1 Playback"}, 1046 1047 {"SSP0 CODEC OUT", NULL, "Playback VMixer"}, 1048 1049 {"Analog Capture", NULL, "SSP0 CODEC IN"}, 1050 {"Loopback Capture", NULL, "SSP0 CODEC IN"}, 1051 1052 {"SSP1 BT OUT", NULL, "Bluetooth Playback"}, 1053 {"Bluetooth Capture", NULL, "SSP1 BT IN"}, 1054 }; 1055 1056 static const struct snd_soc_component_driver catpt_comp_driver = { 1057 .name = "catpt-platform", 1058 1059 .pcm_new = catpt_component_pcm_new, 1060 .open = catpt_component_open, 1061 .pointer = catpt_component_pointer, 1062 1063 .controls = component_kcontrols, 1064 .num_controls = ARRAY_SIZE(component_kcontrols), 1065 .dapm_widgets = component_widgets, 1066 .num_dapm_widgets = ARRAY_SIZE(component_widgets), 1067 .dapm_routes = component_routes, 1068 .num_dapm_routes = ARRAY_SIZE(component_routes), 1069 }; 1070 1071 int catpt_arm_stream_templates(struct catpt_dev *cdev) 1072 { 1073 struct resource *res; 1074 u32 scratch_size = 0; 1075 int i, j; 1076 1077 for (i = 0; i < ARRAY_SIZE(catpt_topology); i++) { 1078 struct catpt_stream_template *template; 1079 struct catpt_module_entry *entry; 1080 struct catpt_module_type *type; 1081 1082 template = catpt_topology[i]; 1083 template->persistent_size = 0; 1084 1085 for (j = 0; j < template->num_entries; j++) { 1086 entry = &template->entries[j]; 1087 type = &cdev->modules[entry->module_id]; 1088 1089 if (!type->loaded) 1090 return -ENOENT; 1091 1092 entry->entry_point = type->entry_point; 1093 template->persistent_size += type->persistent_size; 1094 if (type->scratch_size > scratch_size) 1095 scratch_size = type->scratch_size; 1096 } 1097 } 1098 1099 if (scratch_size) { 1100 /* allocate single scratch area for all modules */ 1101 res = catpt_request_region(&cdev->dram, scratch_size); 1102 if (!res) 1103 return -EBUSY; 1104 cdev->scratch = res; 1105 } 1106 1107 return 0; 1108 } 1109 1110 int catpt_register_plat_component(struct catpt_dev *cdev) 1111 { 1112 struct snd_soc_component *component; 1113 int ret; 1114 1115 component = devm_kzalloc(cdev->dev, sizeof(*component), GFP_KERNEL); 1116 if (!component) 1117 return -ENOMEM; 1118 1119 ret = snd_soc_component_initialize(component, &catpt_comp_driver, 1120 cdev->dev); 1121 if (ret) 1122 return ret; 1123 1124 component->name = catpt_comp_driver.name; 1125 return snd_soc_add_component(component, dai_drivers, 1126 ARRAY_SIZE(dai_drivers)); 1127 } 1128