Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

Merge series "ASoC: Intel: catpt: Offload fixes and code optimization" from Cezary Rojewski <cezary.rojewski@intel.com>:

First two of the series address bugs connected mainly to offload streams:
- scenarios with very low buffer sizes: RESET_STREAM IPC timeouts
- fix lp clock selection when switching between PAUSE <-> RESUME states:
glitches on first offload when no additional stream is opened
simultaneously

Follow ups are: code reduction and optimization oriented patches.
This has been foretold in:

[PATCH v10 00/14] ASoC: Intel: Catpt - Lynx and Wildcat point
https://www.spinics.net/lists/alsa-devel/msg116440.html
Note: LPT power up/down sequences might get aligned with WPT once
enough testing is done as capabilities are shared for both DSPs.

First, optimize applying of user settings - prevent redundand calls from
happening - and then as mentioned above, streamline power on/off sequence
for LPT and WPT.

Cezary Rojewski (5):
ASoC: Intel: catpt: Skip position update for unprepared streams
ASoC: Intel: catpt: Correct clock selection for dai trigger
ASoC: Intel: catpt: Optimize applying user settings
ASoC: Intel: catpt: Streamline power routines across LPT and WPT
ASoC: Intel: catpt: Cleanup after power routines streamlining

sound/soc/intel/catpt/core.h | 10 ++-
sound/soc/intel/catpt/device.c | 18 +++---
sound/soc/intel/catpt/dsp.c | 56 ++--------------
sound/soc/intel/catpt/pcm.c | 113 ++++++++++++++++-----------------
4 files changed, 74 insertions(+), 123 deletions(-)

--
2.17.1

base-commit: 3650b228f83adda7e5ee532e2b90429c03f7b9ec

+74 -123
+4 -6
sound/soc/intel/catpt/core.h
··· 80 80 u32 host_ssp_offset[CATPT_SSP_COUNT]; 81 81 u32 dram_mask; 82 82 u32 iram_mask; 83 + u32 d3srampgd_bit; 84 + u32 d3pgd_bit; 83 85 void (*pll_shutdown)(struct catpt_dev *cdev, bool enable); 84 - int (*power_up)(struct catpt_dev *cdev); 85 - int (*power_down)(struct catpt_dev *cdev); 86 86 }; 87 87 88 88 struct catpt_dev { ··· 126 126 127 127 void lpt_dsp_pll_shutdown(struct catpt_dev *cdev, bool enable); 128 128 void wpt_dsp_pll_shutdown(struct catpt_dev *cdev, bool enable); 129 - int lpt_dsp_power_up(struct catpt_dev *cdev); 130 - int lpt_dsp_power_down(struct catpt_dev *cdev); 131 - int wpt_dsp_power_up(struct catpt_dev *cdev); 132 - int wpt_dsp_power_down(struct catpt_dev *cdev); 129 + int catpt_dsp_power_up(struct catpt_dev *cdev); 130 + int catpt_dsp_power_down(struct catpt_dev *cdev); 133 131 int catpt_dsp_stall(struct catpt_dev *cdev, bool stall); 134 132 void catpt_dsp_update_srampge(struct catpt_dev *cdev, struct resource *sram, 135 133 unsigned long mask);
+9 -9
sound/soc/intel/catpt/device.c
··· 69 69 dma_release_channel(chan); 70 70 if (ret) 71 71 return ret; 72 - return cdev->spec->power_down(cdev); 72 + return catpt_dsp_power_down(cdev); 73 73 } 74 74 75 75 static int __maybe_unused catpt_resume(struct device *dev) ··· 77 77 struct catpt_dev *cdev = dev_get_drvdata(dev); 78 78 int ret, i; 79 79 80 - ret = cdev->spec->power_up(cdev); 80 + ret = catpt_dsp_power_up(cdev); 81 81 if (ret) 82 82 return ret; 83 83 ··· 162 162 { 163 163 int ret; 164 164 165 - ret = cdev->spec->power_up(cdev); 165 + ret = catpt_dsp_power_up(cdev); 166 166 if (ret) 167 167 return ret; 168 168 ··· 204 204 err_boot_fw: 205 205 catpt_dmac_remove(cdev); 206 206 err_dmac_probe: 207 - cdev->spec->power_down(cdev); 207 + catpt_dsp_power_down(cdev); 208 208 209 209 return ret; 210 210 } ··· 293 293 294 294 snd_soc_unregister_component(cdev->dev); 295 295 catpt_dmac_remove(cdev); 296 - cdev->spec->power_down(cdev); 296 + catpt_dsp_power_down(cdev); 297 297 298 298 catpt_sram_free(&cdev->iram); 299 299 catpt_sram_free(&cdev->dram); ··· 311 311 .host_ssp_offset = { 0x0E8000, 0x0E9000 }, 312 312 .dram_mask = LPT_VDRTCTL0_DSRAMPGE_MASK, 313 313 .iram_mask = LPT_VDRTCTL0_ISRAMPGE_MASK, 314 + .d3srampgd_bit = LPT_VDRTCTL0_D3SRAMPGD, 315 + .d3pgd_bit = LPT_VDRTCTL0_D3PGD, 314 316 .pll_shutdown = lpt_dsp_pll_shutdown, 315 - .power_up = lpt_dsp_power_up, 316 - .power_down = lpt_dsp_power_down, 317 317 }; 318 318 319 319 static struct catpt_spec wpt_desc = { ··· 326 326 .host_ssp_offset = { 0x0FC000, 0x0FD000 }, 327 327 .dram_mask = WPT_VDRTCTL0_DSRAMPGE_MASK, 328 328 .iram_mask = WPT_VDRTCTL0_ISRAMPGE_MASK, 329 + .d3srampgd_bit = WPT_VDRTCTL0_D3SRAMPGD, 330 + .d3pgd_bit = WPT_VDRTCTL0_D3PGD, 329 331 .pll_shutdown = wpt_dsp_pll_shutdown, 330 - .power_up = wpt_dsp_power_up, 331 - .power_down = wpt_dsp_power_down, 332 332 }; 333 333 334 334 static const struct acpi_device_id catpt_ids[] = {
+5 -51
sound/soc/intel/catpt/dsp.c
··· 344 344 } 345 345 } 346 346 347 - int lpt_dsp_power_down(struct catpt_dev *cdev) 348 - { 349 - catpt_dsp_reset(cdev, true); 350 - 351 - /* set 24Mhz clock for both SSPs */ 352 - catpt_updatel_shim(cdev, CS1, CATPT_CS_SBCS(0) | CATPT_CS_SBCS(1), 353 - CATPT_CS_SBCS(0) | CATPT_CS_SBCS(1)); 354 - catpt_dsp_select_lpclock(cdev, true, false); 355 - 356 - /* DRAM power gating all */ 357 - catpt_dsp_set_srampge(cdev, &cdev->dram, cdev->spec->dram_mask, 358 - cdev->spec->dram_mask); 359 - catpt_dsp_set_srampge(cdev, &cdev->iram, cdev->spec->iram_mask, 360 - cdev->spec->iram_mask); 361 - 362 - catpt_updatel_pci(cdev, PMCS, PCI_PM_CTRL_STATE_MASK, PCI_D3hot); 363 - /* give hw time to drop off */ 364 - udelay(50); 365 - 366 - return 0; 367 - } 368 - 369 - int lpt_dsp_power_up(struct catpt_dev *cdev) 370 - { 371 - /* SRAM power gating none */ 372 - catpt_dsp_set_srampge(cdev, &cdev->dram, cdev->spec->dram_mask, 0); 373 - catpt_dsp_set_srampge(cdev, &cdev->iram, cdev->spec->iram_mask, 0); 374 - 375 - catpt_updatel_pci(cdev, PMCS, PCI_PM_CTRL_STATE_MASK, PCI_D0); 376 - /* give hw time to wake up */ 377 - udelay(100); 378 - 379 - catpt_dsp_select_lpclock(cdev, false, false); 380 - catpt_updatel_shim(cdev, CS1, 381 - CATPT_CS_SBCS(0) | CATPT_CS_SBCS(1), 382 - CATPT_CS_SBCS(0) | CATPT_CS_SBCS(1)); 383 - /* stagger DSP reset after clock selection */ 384 - udelay(50); 385 - 386 - catpt_dsp_reset(cdev, false); 387 - /* generate int deassert msg to fix inversed int logic */ 388 - catpt_updatel_shim(cdev, IMC, CATPT_IMC_IPCDB | CATPT_IMC_IPCCD, 0); 389 - 390 - return 0; 391 - } 392 - 393 - int wpt_dsp_power_down(struct catpt_dev *cdev) 347 + int catpt_dsp_power_down(struct catpt_dev *cdev) 394 348 { 395 349 u32 mask, val; 396 350 ··· 374 420 cdev->spec->dram_mask); 375 421 catpt_dsp_set_srampge(cdev, &cdev->iram, cdev->spec->iram_mask, 376 422 cdev->spec->iram_mask); 377 - mask = WPT_VDRTCTL0_D3SRAMPGD | WPT_VDRTCTL0_D3PGD; 378 - catpt_updatel_pci(cdev, VDRTCTL0, mask, WPT_VDRTCTL0_D3PGD); 423 + mask = cdev->spec->d3srampgd_bit | cdev->spec->d3pgd_bit; 424 + catpt_updatel_pci(cdev, VDRTCTL0, mask, cdev->spec->d3pgd_bit); 379 425 380 426 catpt_updatel_pci(cdev, PMCS, PCI_PM_CTRL_STATE_MASK, PCI_D3hot); 381 427 /* give hw time to drop off */ ··· 389 435 return 0; 390 436 } 391 437 392 - int wpt_dsp_power_up(struct catpt_dev *cdev) 438 + int catpt_dsp_power_up(struct catpt_dev *cdev) 393 439 { 394 440 u32 mask, val; 395 441 ··· 404 450 catpt_updatel_pci(cdev, PMCS, PCI_PM_CTRL_STATE_MASK, PCI_D0); 405 451 406 452 /* SRAM power gating none */ 407 - mask = WPT_VDRTCTL0_D3SRAMPGD | WPT_VDRTCTL0_D3PGD; 453 + mask = cdev->spec->d3srampgd_bit | cdev->spec->d3pgd_bit; 408 454 catpt_updatel_pci(cdev, VDRTCTL0, mask, mask); 409 455 catpt_dsp_set_srampge(cdev, &cdev->dram, cdev->spec->dram_mask, 0); 410 456 catpt_dsp_set_srampge(cdev, &cdev->iram, cdev->spec->iram_mask, 0);
+56 -57
sound/soc/intel/catpt/pcm.c
··· 324 324 snd_soc_dai_set_dma_data(dai, substream, NULL); 325 325 } 326 326 327 + static int catpt_set_dspvol(struct catpt_dev *cdev, u8 stream_id, long *ctlvol); 328 + 329 + static int catpt_dai_apply_usettings(struct snd_soc_dai *dai, 330 + struct catpt_stream_runtime *stream) 331 + { 332 + struct catpt_dev *cdev = dev_get_drvdata(dai->dev); 333 + struct snd_soc_component *component = dai->component; 334 + struct snd_kcontrol *pos, *kctl = NULL; 335 + const char *name; 336 + int ret; 337 + u32 id = stream->info.stream_hw_id; 338 + 339 + /* only selected streams have individual controls */ 340 + switch (id) { 341 + case CATPT_PIN_ID_OFFLOAD1: 342 + name = "Media0 Playback Volume"; 343 + break; 344 + case CATPT_PIN_ID_OFFLOAD2: 345 + name = "Media1 Playback Volume"; 346 + break; 347 + case CATPT_PIN_ID_CAPTURE1: 348 + name = "Mic Capture Volume"; 349 + break; 350 + case CATPT_PIN_ID_REFERENCE: 351 + name = "Loopback Mute"; 352 + break; 353 + default: 354 + return 0; 355 + }; 356 + 357 + list_for_each_entry(pos, &component->card->snd_card->controls, list) { 358 + if (pos->private_data == component && 359 + !strncmp(name, pos->id.name, sizeof(pos->id.name))) { 360 + kctl = pos; 361 + break; 362 + } 363 + } 364 + if (!kctl) 365 + return -ENOENT; 366 + 367 + if (stream->template->type != CATPT_STRM_TYPE_LOOPBACK) 368 + return catpt_set_dspvol(cdev, id, (long *)kctl->private_value); 369 + ret = catpt_ipc_mute_loopback(cdev, id, *(bool *)kctl->private_value); 370 + if (ret) 371 + return CATPT_IPC_ERROR(ret); 372 + return 0; 373 + } 374 + 327 375 static int catpt_dai_hw_params(struct snd_pcm_substream *substream, 328 376 struct snd_pcm_hw_params *params, 329 377 struct snd_soc_dai *dai) ··· 418 370 if (ret) 419 371 return CATPT_IPC_ERROR(ret); 420 372 373 + ret = catpt_dai_apply_usettings(dai, stream); 374 + if (ret) 375 + return ret; 376 + 421 377 stream->allocated = true; 422 378 return 0; 423 379 } ··· 443 391 return 0; 444 392 } 445 393 446 - static int catpt_set_dspvol(struct catpt_dev *cdev, u8 stream_id, long *ctlvol); 447 - 448 - static int catpt_dai_apply_usettings(struct snd_soc_dai *dai, 449 - struct catpt_stream_runtime *stream) 450 - { 451 - struct catpt_dev *cdev = dev_get_drvdata(dai->dev); 452 - struct snd_soc_component *component = dai->component; 453 - struct snd_kcontrol *pos, *kctl = NULL; 454 - const char *name; 455 - int ret; 456 - u32 id = stream->info.stream_hw_id; 457 - 458 - /* only selected streams have individual controls */ 459 - switch (id) { 460 - case CATPT_PIN_ID_OFFLOAD1: 461 - name = "Media0 Playback Volume"; 462 - break; 463 - case CATPT_PIN_ID_OFFLOAD2: 464 - name = "Media1 Playback Volume"; 465 - break; 466 - case CATPT_PIN_ID_CAPTURE1: 467 - name = "Mic Capture Volume"; 468 - break; 469 - case CATPT_PIN_ID_REFERENCE: 470 - name = "Loopback Mute"; 471 - break; 472 - default: 473 - return 0; 474 - } 475 - 476 - list_for_each_entry(pos, &component->card->snd_card->controls, list) { 477 - if (pos->private_data == component && 478 - !strncmp(name, pos->id.name, sizeof(pos->id.name))) { 479 - kctl = pos; 480 - break; 481 - } 482 - } 483 - if (!kctl) 484 - return -ENOENT; 485 - 486 - if (stream->template->type != CATPT_STRM_TYPE_LOOPBACK) 487 - return catpt_set_dspvol(cdev, id, (long *)kctl->private_value); 488 - ret = catpt_ipc_mute_loopback(cdev, id, *(bool *)kctl->private_value); 489 - if (ret) 490 - return CATPT_IPC_ERROR(ret); 491 - return 0; 492 - } 493 - 494 394 static int catpt_dai_prepare(struct snd_pcm_substream *substream, 495 395 struct snd_soc_dai *dai) 496 396 { ··· 461 457 ret = catpt_ipc_pause_stream(cdev, stream->info.stream_hw_id); 462 458 if (ret) 463 459 return CATPT_IPC_ERROR(ret); 464 - 465 - ret = catpt_dsp_update_lpclock(cdev); 466 - if (ret) 467 - return ret; 468 - 469 - ret = catpt_dai_apply_usettings(dai, stream); 470 - if (ret) 471 - return ret; 472 460 473 461 stream->prepared = true; 474 462 return 0; ··· 496 500 case SNDRV_PCM_TRIGGER_RESUME: 497 501 case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: 498 502 resume_stream: 503 + catpt_dsp_update_lpclock(cdev); 499 504 ret = catpt_ipc_resume_stream(cdev, stream->info.stream_hw_id); 500 505 if (ret) 501 506 return CATPT_IPC_ERROR(ret); ··· 504 507 505 508 case SNDRV_PCM_TRIGGER_STOP: 506 509 stream->prepared = false; 507 - catpt_dsp_update_lpclock(cdev); 508 510 fallthrough; 509 511 case SNDRV_PCM_TRIGGER_SUSPEND: 510 512 case SNDRV_PCM_TRIGGER_PAUSE_PUSH: 511 513 ret = catpt_ipc_pause_stream(cdev, stream->info.stream_hw_id); 514 + catpt_dsp_update_lpclock(cdev); 512 515 if (ret) 513 516 return CATPT_IPC_ERROR(ret); 514 517 break; ··· 531 534 532 535 dsppos = bytes_to_frames(r, pos->stream_position); 533 536 537 + if (!stream->prepared) 538 + goto exit; 534 539 /* only offload is set_write_pos driven */ 535 540 if (stream->template->type != CATPT_STRM_TYPE_RENDER) 536 541 goto exit;