mirror of
https://github.com/torvalds/linux.git
synced 2024-11-14 08:02:07 +00:00
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: 3650b228f8
This commit is contained in:
commit
4fb87241e5
@ -80,9 +80,9 @@ struct catpt_spec {
|
||||
u32 host_ssp_offset[CATPT_SSP_COUNT];
|
||||
u32 dram_mask;
|
||||
u32 iram_mask;
|
||||
u32 d3srampgd_bit;
|
||||
u32 d3pgd_bit;
|
||||
void (*pll_shutdown)(struct catpt_dev *cdev, bool enable);
|
||||
int (*power_up)(struct catpt_dev *cdev);
|
||||
int (*power_down)(struct catpt_dev *cdev);
|
||||
};
|
||||
|
||||
struct catpt_dev {
|
||||
@ -126,10 +126,8 @@ int catpt_dma_memcpy_fromdsp(struct catpt_dev *cdev, struct dma_chan *chan,
|
||||
|
||||
void lpt_dsp_pll_shutdown(struct catpt_dev *cdev, bool enable);
|
||||
void wpt_dsp_pll_shutdown(struct catpt_dev *cdev, bool enable);
|
||||
int lpt_dsp_power_up(struct catpt_dev *cdev);
|
||||
int lpt_dsp_power_down(struct catpt_dev *cdev);
|
||||
int wpt_dsp_power_up(struct catpt_dev *cdev);
|
||||
int wpt_dsp_power_down(struct catpt_dev *cdev);
|
||||
int catpt_dsp_power_up(struct catpt_dev *cdev);
|
||||
int catpt_dsp_power_down(struct catpt_dev *cdev);
|
||||
int catpt_dsp_stall(struct catpt_dev *cdev, bool stall);
|
||||
void catpt_dsp_update_srampge(struct catpt_dev *cdev, struct resource *sram,
|
||||
unsigned long mask);
|
||||
|
@ -69,7 +69,7 @@ release_dma_chan:
|
||||
dma_release_channel(chan);
|
||||
if (ret)
|
||||
return ret;
|
||||
return cdev->spec->power_down(cdev);
|
||||
return catpt_dsp_power_down(cdev);
|
||||
}
|
||||
|
||||
static int __maybe_unused catpt_resume(struct device *dev)
|
||||
@ -77,7 +77,7 @@ static int __maybe_unused catpt_resume(struct device *dev)
|
||||
struct catpt_dev *cdev = dev_get_drvdata(dev);
|
||||
int ret, i;
|
||||
|
||||
ret = cdev->spec->power_up(cdev);
|
||||
ret = catpt_dsp_power_up(cdev);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
@ -162,7 +162,7 @@ static int catpt_probe_components(struct catpt_dev *cdev)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = cdev->spec->power_up(cdev);
|
||||
ret = catpt_dsp_power_up(cdev);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
@ -204,7 +204,7 @@ err_reg_board:
|
||||
err_boot_fw:
|
||||
catpt_dmac_remove(cdev);
|
||||
err_dmac_probe:
|
||||
cdev->spec->power_down(cdev);
|
||||
catpt_dsp_power_down(cdev);
|
||||
|
||||
return ret;
|
||||
}
|
||||
@ -293,7 +293,7 @@ static int catpt_acpi_remove(struct platform_device *pdev)
|
||||
|
||||
snd_soc_unregister_component(cdev->dev);
|
||||
catpt_dmac_remove(cdev);
|
||||
cdev->spec->power_down(cdev);
|
||||
catpt_dsp_power_down(cdev);
|
||||
|
||||
catpt_sram_free(&cdev->iram);
|
||||
catpt_sram_free(&cdev->dram);
|
||||
@ -311,9 +311,9 @@ static struct catpt_spec lpt_desc = {
|
||||
.host_ssp_offset = { 0x0E8000, 0x0E9000 },
|
||||
.dram_mask = LPT_VDRTCTL0_DSRAMPGE_MASK,
|
||||
.iram_mask = LPT_VDRTCTL0_ISRAMPGE_MASK,
|
||||
.d3srampgd_bit = LPT_VDRTCTL0_D3SRAMPGD,
|
||||
.d3pgd_bit = LPT_VDRTCTL0_D3PGD,
|
||||
.pll_shutdown = lpt_dsp_pll_shutdown,
|
||||
.power_up = lpt_dsp_power_up,
|
||||
.power_down = lpt_dsp_power_down,
|
||||
};
|
||||
|
||||
static struct catpt_spec wpt_desc = {
|
||||
@ -326,9 +326,9 @@ static struct catpt_spec wpt_desc = {
|
||||
.host_ssp_offset = { 0x0FC000, 0x0FD000 },
|
||||
.dram_mask = WPT_VDRTCTL0_DSRAMPGE_MASK,
|
||||
.iram_mask = WPT_VDRTCTL0_ISRAMPGE_MASK,
|
||||
.d3srampgd_bit = WPT_VDRTCTL0_D3SRAMPGD,
|
||||
.d3pgd_bit = WPT_VDRTCTL0_D3PGD,
|
||||
.pll_shutdown = wpt_dsp_pll_shutdown,
|
||||
.power_up = wpt_dsp_power_up,
|
||||
.power_down = wpt_dsp_power_down,
|
||||
};
|
||||
|
||||
static const struct acpi_device_id catpt_ids[] = {
|
||||
|
@ -344,53 +344,7 @@ static void catpt_dsp_set_regs_defaults(struct catpt_dev *cdev)
|
||||
}
|
||||
}
|
||||
|
||||
int lpt_dsp_power_down(struct catpt_dev *cdev)
|
||||
{
|
||||
catpt_dsp_reset(cdev, true);
|
||||
|
||||
/* set 24Mhz clock for both SSPs */
|
||||
catpt_updatel_shim(cdev, CS1, CATPT_CS_SBCS(0) | CATPT_CS_SBCS(1),
|
||||
CATPT_CS_SBCS(0) | CATPT_CS_SBCS(1));
|
||||
catpt_dsp_select_lpclock(cdev, true, false);
|
||||
|
||||
/* DRAM power gating all */
|
||||
catpt_dsp_set_srampge(cdev, &cdev->dram, cdev->spec->dram_mask,
|
||||
cdev->spec->dram_mask);
|
||||
catpt_dsp_set_srampge(cdev, &cdev->iram, cdev->spec->iram_mask,
|
||||
cdev->spec->iram_mask);
|
||||
|
||||
catpt_updatel_pci(cdev, PMCS, PCI_PM_CTRL_STATE_MASK, PCI_D3hot);
|
||||
/* give hw time to drop off */
|
||||
udelay(50);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int lpt_dsp_power_up(struct catpt_dev *cdev)
|
||||
{
|
||||
/* SRAM power gating none */
|
||||
catpt_dsp_set_srampge(cdev, &cdev->dram, cdev->spec->dram_mask, 0);
|
||||
catpt_dsp_set_srampge(cdev, &cdev->iram, cdev->spec->iram_mask, 0);
|
||||
|
||||
catpt_updatel_pci(cdev, PMCS, PCI_PM_CTRL_STATE_MASK, PCI_D0);
|
||||
/* give hw time to wake up */
|
||||
udelay(100);
|
||||
|
||||
catpt_dsp_select_lpclock(cdev, false, false);
|
||||
catpt_updatel_shim(cdev, CS1,
|
||||
CATPT_CS_SBCS(0) | CATPT_CS_SBCS(1),
|
||||
CATPT_CS_SBCS(0) | CATPT_CS_SBCS(1));
|
||||
/* stagger DSP reset after clock selection */
|
||||
udelay(50);
|
||||
|
||||
catpt_dsp_reset(cdev, false);
|
||||
/* generate int deassert msg to fix inversed int logic */
|
||||
catpt_updatel_shim(cdev, IMC, CATPT_IMC_IPCDB | CATPT_IMC_IPCCD, 0);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int wpt_dsp_power_down(struct catpt_dev *cdev)
|
||||
int catpt_dsp_power_down(struct catpt_dev *cdev)
|
||||
{
|
||||
u32 mask, val;
|
||||
|
||||
@ -420,8 +374,8 @@ int wpt_dsp_power_down(struct catpt_dev *cdev)
|
||||
cdev->spec->dram_mask);
|
||||
catpt_dsp_set_srampge(cdev, &cdev->iram, cdev->spec->iram_mask,
|
||||
cdev->spec->iram_mask);
|
||||
mask = WPT_VDRTCTL0_D3SRAMPGD | WPT_VDRTCTL0_D3PGD;
|
||||
catpt_updatel_pci(cdev, VDRTCTL0, mask, WPT_VDRTCTL0_D3PGD);
|
||||
mask = cdev->spec->d3srampgd_bit | cdev->spec->d3pgd_bit;
|
||||
catpt_updatel_pci(cdev, VDRTCTL0, mask, cdev->spec->d3pgd_bit);
|
||||
|
||||
catpt_updatel_pci(cdev, PMCS, PCI_PM_CTRL_STATE_MASK, PCI_D3hot);
|
||||
/* give hw time to drop off */
|
||||
@ -435,7 +389,7 @@ int wpt_dsp_power_down(struct catpt_dev *cdev)
|
||||
return 0;
|
||||
}
|
||||
|
||||
int wpt_dsp_power_up(struct catpt_dev *cdev)
|
||||
int catpt_dsp_power_up(struct catpt_dev *cdev)
|
||||
{
|
||||
u32 mask, val;
|
||||
|
||||
@ -450,7 +404,7 @@ int wpt_dsp_power_up(struct catpt_dev *cdev)
|
||||
catpt_updatel_pci(cdev, PMCS, PCI_PM_CTRL_STATE_MASK, PCI_D0);
|
||||
|
||||
/* SRAM power gating none */
|
||||
mask = WPT_VDRTCTL0_D3SRAMPGD | WPT_VDRTCTL0_D3PGD;
|
||||
mask = cdev->spec->d3srampgd_bit | cdev->spec->d3pgd_bit;
|
||||
catpt_updatel_pci(cdev, VDRTCTL0, mask, mask);
|
||||
catpt_dsp_set_srampge(cdev, &cdev->dram, cdev->spec->dram_mask, 0);
|
||||
catpt_dsp_set_srampge(cdev, &cdev->iram, cdev->spec->iram_mask, 0);
|
||||
|
@ -324,6 +324,54 @@ static void catpt_dai_shutdown(struct snd_pcm_substream *substream,
|
||||
snd_soc_dai_set_dma_data(dai, substream, NULL);
|
||||
}
|
||||
|
||||
static int catpt_set_dspvol(struct catpt_dev *cdev, u8 stream_id, long *ctlvol);
|
||||
|
||||
static int catpt_dai_apply_usettings(struct snd_soc_dai *dai,
|
||||
struct catpt_stream_runtime *stream)
|
||||
{
|
||||
struct catpt_dev *cdev = dev_get_drvdata(dai->dev);
|
||||
struct snd_soc_component *component = dai->component;
|
||||
struct snd_kcontrol *pos, *kctl = NULL;
|
||||
const char *name;
|
||||
int ret;
|
||||
u32 id = stream->info.stream_hw_id;
|
||||
|
||||
/* only selected streams have individual controls */
|
||||
switch (id) {
|
||||
case CATPT_PIN_ID_OFFLOAD1:
|
||||
name = "Media0 Playback Volume";
|
||||
break;
|
||||
case CATPT_PIN_ID_OFFLOAD2:
|
||||
name = "Media1 Playback Volume";
|
||||
break;
|
||||
case CATPT_PIN_ID_CAPTURE1:
|
||||
name = "Mic Capture Volume";
|
||||
break;
|
||||
case CATPT_PIN_ID_REFERENCE:
|
||||
name = "Loopback Mute";
|
||||
break;
|
||||
default:
|
||||
return 0;
|
||||
};
|
||||
|
||||
list_for_each_entry(pos, &component->card->snd_card->controls, list) {
|
||||
if (pos->private_data == component &&
|
||||
!strncmp(name, pos->id.name, sizeof(pos->id.name))) {
|
||||
kctl = pos;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!kctl)
|
||||
return -ENOENT;
|
||||
|
||||
if (stream->template->type != CATPT_STRM_TYPE_LOOPBACK)
|
||||
return catpt_set_dspvol(cdev, id, (long *)kctl->private_value);
|
||||
ret = catpt_ipc_mute_loopback(cdev, id, *(bool *)kctl->private_value);
|
||||
if (ret)
|
||||
return CATPT_IPC_ERROR(ret);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int catpt_dai_hw_params(struct snd_pcm_substream *substream,
|
||||
struct snd_pcm_hw_params *params,
|
||||
struct snd_soc_dai *dai)
|
||||
@ -370,6 +418,10 @@ static int catpt_dai_hw_params(struct snd_pcm_substream *substream,
|
||||
if (ret)
|
||||
return CATPT_IPC_ERROR(ret);
|
||||
|
||||
ret = catpt_dai_apply_usettings(dai, stream);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
stream->allocated = true;
|
||||
return 0;
|
||||
}
|
||||
@ -391,54 +443,6 @@ static int catpt_dai_hw_free(struct snd_pcm_substream *substream,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int catpt_set_dspvol(struct catpt_dev *cdev, u8 stream_id, long *ctlvol);
|
||||
|
||||
static int catpt_dai_apply_usettings(struct snd_soc_dai *dai,
|
||||
struct catpt_stream_runtime *stream)
|
||||
{
|
||||
struct catpt_dev *cdev = dev_get_drvdata(dai->dev);
|
||||
struct snd_soc_component *component = dai->component;
|
||||
struct snd_kcontrol *pos, *kctl = NULL;
|
||||
const char *name;
|
||||
int ret;
|
||||
u32 id = stream->info.stream_hw_id;
|
||||
|
||||
/* only selected streams have individual controls */
|
||||
switch (id) {
|
||||
case CATPT_PIN_ID_OFFLOAD1:
|
||||
name = "Media0 Playback Volume";
|
||||
break;
|
||||
case CATPT_PIN_ID_OFFLOAD2:
|
||||
name = "Media1 Playback Volume";
|
||||
break;
|
||||
case CATPT_PIN_ID_CAPTURE1:
|
||||
name = "Mic Capture Volume";
|
||||
break;
|
||||
case CATPT_PIN_ID_REFERENCE:
|
||||
name = "Loopback Mute";
|
||||
break;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
|
||||
list_for_each_entry(pos, &component->card->snd_card->controls, list) {
|
||||
if (pos->private_data == component &&
|
||||
!strncmp(name, pos->id.name, sizeof(pos->id.name))) {
|
||||
kctl = pos;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!kctl)
|
||||
return -ENOENT;
|
||||
|
||||
if (stream->template->type != CATPT_STRM_TYPE_LOOPBACK)
|
||||
return catpt_set_dspvol(cdev, id, (long *)kctl->private_value);
|
||||
ret = catpt_ipc_mute_loopback(cdev, id, *(bool *)kctl->private_value);
|
||||
if (ret)
|
||||
return CATPT_IPC_ERROR(ret);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int catpt_dai_prepare(struct snd_pcm_substream *substream,
|
||||
struct snd_soc_dai *dai)
|
||||
{
|
||||
@ -458,14 +462,6 @@ static int catpt_dai_prepare(struct snd_pcm_substream *substream,
|
||||
if (ret)
|
||||
return CATPT_IPC_ERROR(ret);
|
||||
|
||||
ret = catpt_dsp_update_lpclock(cdev);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = catpt_dai_apply_usettings(dai, stream);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
stream->prepared = true;
|
||||
return 0;
|
||||
}
|
||||
@ -500,6 +496,7 @@ static int catpt_dai_trigger(struct snd_pcm_substream *substream, int cmd,
|
||||
case SNDRV_PCM_TRIGGER_RESUME:
|
||||
case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
|
||||
resume_stream:
|
||||
catpt_dsp_update_lpclock(cdev);
|
||||
ret = catpt_ipc_resume_stream(cdev, stream->info.stream_hw_id);
|
||||
if (ret)
|
||||
return CATPT_IPC_ERROR(ret);
|
||||
@ -507,11 +504,11 @@ static int catpt_dai_trigger(struct snd_pcm_substream *substream, int cmd,
|
||||
|
||||
case SNDRV_PCM_TRIGGER_STOP:
|
||||
stream->prepared = false;
|
||||
catpt_dsp_update_lpclock(cdev);
|
||||
fallthrough;
|
||||
case SNDRV_PCM_TRIGGER_SUSPEND:
|
||||
case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
|
||||
ret = catpt_ipc_pause_stream(cdev, stream->info.stream_hw_id);
|
||||
catpt_dsp_update_lpclock(cdev);
|
||||
if (ret)
|
||||
return CATPT_IPC_ERROR(ret);
|
||||
break;
|
||||
@ -534,6 +531,8 @@ void catpt_stream_update_position(struct catpt_dev *cdev,
|
||||
|
||||
dsppos = bytes_to_frames(r, pos->stream_position);
|
||||
|
||||
if (!stream->prepared)
|
||||
goto exit;
|
||||
/* only offload is set_write_pos driven */
|
||||
if (stream->template->type != CATPT_STRM_TYPE_RENDER)
|
||||
goto exit;
|
||||
|
Loading…
Reference in New Issue
Block a user