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