summaryrefslogtreecommitdiff
path: root/sound/soc/intel/catpt
diff options
context:
space:
mode:
authorMark Brown <broonie@kernel.org>2020-11-16 23:28:03 +0000
committerMark Brown <broonie@kernel.org>2020-11-16 23:28:03 +0000
commit4fb87241e5192caf9226fd4ca96ce2fd861503c1 (patch)
tree21e6cc146f372f5d60edc49c36b2ece7a61c7f7d /sound/soc/intel/catpt
parent47f667afe716113ace014691bfdc134ce9045d18 (diff)
parent3d32489838bbf3119bb1ea59cdbed0077d7dbf3c (diff)
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
Diffstat (limited to 'sound/soc/intel/catpt')
-rw-r--r--sound/soc/intel/catpt/core.h10
-rw-r--r--sound/soc/intel/catpt/device.c18
-rw-r--r--sound/soc/intel/catpt/dsp.c56
-rw-r--r--sound/soc/intel/catpt/pcm.c113
4 files changed, 74 insertions, 123 deletions
diff --git a/sound/soc/intel/catpt/core.h b/sound/soc/intel/catpt/core.h
index 88dc3fb6306f..0f53a0d43254 100644
--- a/sound/soc/intel/catpt/core.h
+++ b/sound/soc/intel/catpt/core.h
@@ -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);
diff --git a/sound/soc/intel/catpt/device.c b/sound/soc/intel/catpt/device.c
index a70179959795..b1d380868d8c 100644
--- a/sound/soc/intel/catpt/device.c
+++ b/sound/soc/intel/catpt/device.c
@@ -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[] = {
diff --git a/sound/soc/intel/catpt/dsp.c b/sound/soc/intel/catpt/dsp.c
index 9e807b941732..9c5fd18f2600 100644
--- a/sound/soc/intel/catpt/dsp.c
+++ b/sound/soc/intel/catpt/dsp.c
@@ -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);
diff --git a/sound/soc/intel/catpt/pcm.c b/sound/soc/intel/catpt/pcm.c
index 1775540ac92b..e5d54bb1c42a 100644
--- a/sound/soc/intel/catpt/pcm.c
+++ b/sound/soc/intel/catpt/pcm.c
@@ -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;