diff mbox series

Revert "ASoC: Intel: haswell: Power transition refactor"

Message ID 20200901153041.14771-1-cezary.rojewski@intel.com
State New
Headers show
Series Revert "ASoC: Intel: haswell: Power transition refactor" | expand

Commit Message

Cezary Rojewski Sept. 1, 2020, 3:30 p.m. UTC
This reverts commit 8ec7d6043263ecf250b9b7c0dd8ade899487538a.

While addressing existing power-cycle limitations for
sound/soc/intel/haswell solution, change brings regression for standard
audio userspace flows e.g.: when using PulseAudio.

Occasional sound-card initialization fail is still better than
pernament audio distortions, so revert the change.

Fixes: 8ec7d6043263 ("ASoC: Intel: haswell: Power transition refactor")
Reported-by: Christian Bundy <christianbundy@fraction.io>
Signed-off-by: Cezary Rojewski <cezary.rojewski@intel.com>
---
 sound/soc/intel/haswell/sst-haswell-dsp.c | 185 ++++++++++------------
 1 file changed, 81 insertions(+), 104 deletions(-)

Comments

Pierre-Louis Bossart Sept. 1, 2020, 3:40 p.m. UTC | #1
On 9/1/20 10:30 AM, Cezary Rojewski wrote:
> This reverts commit 8ec7d6043263ecf250b9b7c0dd8ade899487538a.
> 
> While addressing existing power-cycle limitations for
> sound/soc/intel/haswell solution, change brings regression for standard
> audio userspace flows e.g.: when using PulseAudio.
> 
> Occasional sound-card initialization fail is still better than
> pernament audio distortions, so revert the change.
> 
> Fixes: 8ec7d6043263 ("ASoC: Intel: haswell: Power transition refactor")
> Reported-by: Christian Bundy <christianbundy@fraction.io>
> Signed-off-by: Cezary Rojewski <cezary.rojewski@intel.com>

Reviewed-by: Pierre-Louis Bossart <pierre-louis.bossart@linux.intel.com>

This should be applied to 5.8-stable and 5.9-rcX, it impacts the Google 
'Samus' Chromebook and Dell XPS 9343 (if used in I2S mode).

Thanks Cezary.
Mark Brown Sept. 1, 2020, 4:01 p.m. UTC | #2
On Tue, 1 Sep 2020 17:30:41 +0200, Cezary Rojewski wrote:
> This reverts commit 8ec7d6043263ecf250b9b7c0dd8ade899487538a.
> 
> While addressing existing power-cycle limitations for
> sound/soc/intel/haswell solution, change brings regression for standard
> audio userspace flows e.g.: when using PulseAudio.
> 
> Occasional sound-card initialization fail is still better than
> pernament audio distortions, so revert the change.

Applied to

   https://git.kernel.org/pub/scm/linux/kernel/git/broonie/sound.git for-next

Thanks!

[1/1] ASoC: Intel: haswell: Fix power transition refactor
      commit: 154549558a622b31702fcaa01ccd85e6e34073de

All being well this means that it will be integrated into the linux-next
tree (usually sometime in the next 24 hours) and sent to Linus during
the next merge window (or sooner if it is a bug fix), however if
problems are discovered then the patch may be dropped or reverted.

You may get further e-mails resulting from automated or manual testing
and review of the tree, please engage with people reporting problems and
send followup patches addressing any issues that are reported if needed.

If any updates are required or you are submitting further changes they
should be sent as incremental updates against current git, existing
patches will not be replaced.

Please add any relevant lists and maintainers to the CCs when replying
to this mail.

Thanks,
Mark
Liam Girdwood Sept. 2, 2020, 1:11 p.m. UTC | #3
On Tue, 2020-09-01 at 17:30 +0200, Cezary Rojewski wrote:
> This reverts commit 8ec7d6043263ecf250b9b7c0dd8ade899487538a.
> 
> 
> 
> While addressing existing power-cycle limitations for
> 
> sound/soc/intel/haswell solution, change brings regression for standard
> 
> audio userspace flows e.g.: when using PulseAudio.
> 
> 
> 
> Occasional sound-card initialization fail is still better than
> 
> pernament audio distortions, so revert the change.
> 
> 
> 
> Fixes: 8ec7d6043263 ("ASoC: Intel: haswell: Power transition refactor")
> 
> Reported-by: Christian Bundy <christianbundy@fraction.io>
> 
> Signed-off-by: Cezary Rojewski <cezary.rojewski@intel.com>

Acked-by: Liam Girdwood <liam.r.girdwood@linux.intel.com>
diff mbox series

Patch

diff --git a/sound/soc/intel/haswell/sst-haswell-dsp.c b/sound/soc/intel/haswell/sst-haswell-dsp.c
index de80e19454c1..88c3f63bded9 100644
--- a/sound/soc/intel/haswell/sst-haswell-dsp.c
+++ b/sound/soc/intel/haswell/sst-haswell-dsp.c
@@ -243,92 +243,45 @@  static irqreturn_t hsw_irq(int irq, void *context)
 	return ret;
 }
 
-#define CSR_DEFAULT_VALUE 0x8480040E
-#define ISC_DEFAULT_VALUE 0x0
-#define ISD_DEFAULT_VALUE 0x0
-#define IMC_DEFAULT_VALUE 0x7FFF0003
-#define IMD_DEFAULT_VALUE 0x7FFF0003
-#define IPCC_DEFAULT_VALUE 0x0
-#define IPCD_DEFAULT_VALUE 0x0
-#define CLKCTL_DEFAULT_VALUE 0x7FF
-#define CSR2_DEFAULT_VALUE 0x0
-#define LTR_CTRL_DEFAULT_VALUE 0x0
-#define HMD_CTRL_DEFAULT_VALUE 0x0
-
-static void hsw_set_shim_defaults(struct sst_dsp *sst)
-{
-	sst_dsp_shim_write_unlocked(sst, SST_CSR, CSR_DEFAULT_VALUE);
-	sst_dsp_shim_write_unlocked(sst, SST_ISRX, ISC_DEFAULT_VALUE);
-	sst_dsp_shim_write_unlocked(sst, SST_ISRD, ISD_DEFAULT_VALUE);
-	sst_dsp_shim_write_unlocked(sst, SST_IMRX, IMC_DEFAULT_VALUE);
-	sst_dsp_shim_write_unlocked(sst, SST_IMRD, IMD_DEFAULT_VALUE);
-	sst_dsp_shim_write_unlocked(sst, SST_IPCX, IPCC_DEFAULT_VALUE);
-	sst_dsp_shim_write_unlocked(sst, SST_IPCD, IPCD_DEFAULT_VALUE);
-	sst_dsp_shim_write_unlocked(sst, SST_CLKCTL, CLKCTL_DEFAULT_VALUE);
-	sst_dsp_shim_write_unlocked(sst, SST_CSR2, CSR2_DEFAULT_VALUE);
-	sst_dsp_shim_write_unlocked(sst, SST_LTRC, LTR_CTRL_DEFAULT_VALUE);
-	sst_dsp_shim_write_unlocked(sst, SST_HMDC, HMD_CTRL_DEFAULT_VALUE);
-}
-
-/* all clock-gating minus DCLCGE and DTCGE */
-#define SST_VDRTCL2_CG_OTHER	0xB7D
-
 static void hsw_set_dsp_D3(struct sst_dsp *sst)
 {
+	u32 val;
 	u32 reg;
 
-	/* disable clock core gating */
+	/* Disable core clock gating (VDRTCTL2.DCLCGE = 0) */
 	reg = readl(sst->addr.pci_cfg + SST_VDRTCTL2);
-	reg &= ~(SST_VDRTCL2_DCLCGE);
+	reg &= ~(SST_VDRTCL2_DCLCGE | SST_VDRTCL2_DTCGE);
 	writel(reg, sst->addr.pci_cfg + SST_VDRTCTL2);
 
-	/* stall, reset and set 24MHz XOSC */
-	sst_dsp_shim_update_bits_unlocked(sst, SST_CSR,
-			SST_CSR_24MHZ_LPCS | SST_CSR_STALL | SST_CSR_RST,
-			SST_CSR_24MHZ_LPCS | SST_CSR_STALL | SST_CSR_RST);
-
-	/* DRAM power gating all */
-	reg = readl(sst->addr.pci_cfg + SST_VDRTCTL0);
-	reg |= SST_VDRTCL0_ISRAMPGE_MASK |
-		SST_VDRTCL0_DSRAMPGE_MASK;
-	reg &= ~(SST_VDRTCL0_D3SRAMPGD);
-	reg |= SST_VDRTCL0_D3PGD;
-	writel(reg, sst->addr.pci_cfg + SST_VDRTCTL0);
-	udelay(50);
+	/* enable power gating and switch off DRAM & IRAM blocks */
+	val = readl(sst->addr.pci_cfg + SST_VDRTCTL0);
+	val |= SST_VDRTCL0_DSRAMPGE_MASK |
+		SST_VDRTCL0_ISRAMPGE_MASK;
+	val &= ~(SST_VDRTCL0_D3PGD | SST_VDRTCL0_D3SRAMPGD);
+	writel(val, sst->addr.pci_cfg + SST_VDRTCTL0);
 
-	/* PLL shutdown enable */
-	reg = readl(sst->addr.pci_cfg + SST_VDRTCTL2);
-	reg |= SST_VDRTCL2_APLLSE_MASK;
-	writel(reg, sst->addr.pci_cfg + SST_VDRTCTL2);
+	/* switch off audio PLL */
+	val = readl(sst->addr.pci_cfg + SST_VDRTCTL2);
+	val |= SST_VDRTCL2_APLLSE_MASK;
+	writel(val, sst->addr.pci_cfg + SST_VDRTCTL2);
 
-	/* disable MCLK */
+	/* disable MCLK(clkctl.smos = 0) */
 	sst_dsp_shim_update_bits_unlocked(sst, SST_CLKCTL,
-			SST_CLKCTL_MASK, 0);
-
-	/* switch clock gating */
-	reg = readl(sst->addr.pci_cfg + SST_VDRTCTL2);
-	reg |= SST_VDRTCL2_CG_OTHER;
-	reg &= ~(SST_VDRTCL2_DTCGE);
-	writel(reg, sst->addr.pci_cfg + SST_VDRTCTL2);
-	/* enable DTCGE separatelly */
-	reg = readl(sst->addr.pci_cfg + SST_VDRTCTL2);
-	reg |= SST_VDRTCL2_DTCGE;
-	writel(reg, sst->addr.pci_cfg + SST_VDRTCTL2);
+		SST_CLKCTL_MASK, 0);
 
-	/* set shim defaults */
-	hsw_set_shim_defaults(sst);
-
-	/* set D3 */
-	reg = readl(sst->addr.pci_cfg + SST_PMCS);
-	reg |= SST_PMCS_PS_MASK;
-	writel(reg, sst->addr.pci_cfg + SST_PMCS);
+	/* Set D3 state, delay 50 us */
+	val = readl(sst->addr.pci_cfg + SST_PMCS);
+	val |= SST_PMCS_PS_MASK;
+	writel(val, sst->addr.pci_cfg + SST_PMCS);
 	udelay(50);
 
-	/* enable clock core gating */
+	/* Enable core clock gating (VDRTCTL2.DCLCGE = 1), delay 50 us */
 	reg = readl(sst->addr.pci_cfg + SST_VDRTCTL2);
-	reg |= SST_VDRTCL2_DCLCGE;
+	reg |= SST_VDRTCL2_DCLCGE | SST_VDRTCL2_DTCGE;
 	writel(reg, sst->addr.pci_cfg + SST_VDRTCTL2);
+
 	udelay(50);
+
 }
 
 static void hsw_reset(struct sst_dsp *sst)
@@ -346,62 +299,75 @@  static void hsw_reset(struct sst_dsp *sst)
 		SST_CSR_RST | SST_CSR_STALL, SST_CSR_STALL);
 }
 
-/* recommended CSR state for power-up */
-#define SST_CSR_D0_MASK (0x18A09C0C | SST_CSR_DCS_MASK)
-
 static int hsw_set_dsp_D0(struct sst_dsp *sst)
 {
-	u32 reg;
+	int tries = 10;
+	u32 reg, fw_dump_bit;
 
-	/* disable clock core gating */
+	/* Disable core clock gating (VDRTCTL2.DCLCGE = 0) */
 	reg = readl(sst->addr.pci_cfg + SST_VDRTCTL2);
-	reg &= ~(SST_VDRTCL2_DCLCGE);
+	reg &= ~(SST_VDRTCL2_DCLCGE | SST_VDRTCL2_DTCGE);
 	writel(reg, sst->addr.pci_cfg + SST_VDRTCTL2);
 
-	/* switch clock gating */
-	reg = readl(sst->addr.pci_cfg + SST_VDRTCTL2);
-	reg |= SST_VDRTCL2_CG_OTHER;
-	reg &= ~(SST_VDRTCL2_DTCGE);
-	writel(reg, sst->addr.pci_cfg + SST_VDRTCTL2);
+	/* Disable D3PG (VDRTCTL0.D3PGD = 1) */
+	reg = readl(sst->addr.pci_cfg + SST_VDRTCTL0);
+	reg |= SST_VDRTCL0_D3PGD;
+	writel(reg, sst->addr.pci_cfg + SST_VDRTCTL0);
 
-	/* set D0 */
+	/* Set D0 state */
 	reg = readl(sst->addr.pci_cfg + SST_PMCS);
-	reg &= ~(SST_PMCS_PS_MASK);
+	reg &= ~SST_PMCS_PS_MASK;
 	writel(reg, sst->addr.pci_cfg + SST_PMCS);
 
-	/* DRAM power gating none */
-	reg = readl(sst->addr.pci_cfg + SST_VDRTCTL0);
-	reg &= ~(SST_VDRTCL0_ISRAMPGE_MASK |
-		SST_VDRTCL0_DSRAMPGE_MASK);
-	reg |= SST_VDRTCL0_D3SRAMPGD;
-	reg |= SST_VDRTCL0_D3PGD;
-	writel(reg, sst->addr.pci_cfg + SST_VDRTCTL0);
-	mdelay(10);
+	/* check that ADSP shim is enabled */
+	while (tries--) {
+		reg = readl(sst->addr.pci_cfg + SST_PMCS) & SST_PMCS_PS_MASK;
+		if (reg == 0)
+			goto finish;
+
+		msleep(1);
+	}
+
+	return -ENODEV;
 
-	/* set shim defaults */
-	hsw_set_shim_defaults(sst);
+finish:
+	/* select SSP1 19.2MHz base clock, SSP clock 0, turn off Low Power Clock */
+	sst_dsp_shim_update_bits_unlocked(sst, SST_CSR,
+		SST_CSR_S1IOCS | SST_CSR_SBCS1 | SST_CSR_LPCS, 0x0);
+
+	/* stall DSP core, set clk to 192/96Mhz */
+	sst_dsp_shim_update_bits_unlocked(sst,
+		SST_CSR, SST_CSR_STALL | SST_CSR_DCS_MASK,
+		SST_CSR_STALL | SST_CSR_DCS(4));
 
-	/* restore MCLK */
+	/* Set 24MHz MCLK, prevent local clock gating, enable SSP0 clock */
 	sst_dsp_shim_update_bits_unlocked(sst, SST_CLKCTL,
-			SST_CLKCTL_MASK, SST_CLKCTL_MASK);
+		SST_CLKCTL_MASK | SST_CLKCTL_DCPLCG | SST_CLKCTL_SCOE0,
+		SST_CLKCTL_MASK | SST_CLKCTL_DCPLCG | SST_CLKCTL_SCOE0);
 
-	/* PLL shutdown disable */
+	/* Stall and reset core, set CSR */
+	hsw_reset(sst);
+
+	/* Enable core clock gating (VDRTCTL2.DCLCGE = 1), delay 50 us */
 	reg = readl(sst->addr.pci_cfg + SST_VDRTCTL2);
-	reg &= ~(SST_VDRTCL2_APLLSE_MASK);
+	reg |= SST_VDRTCL2_DCLCGE | SST_VDRTCL2_DTCGE;
 	writel(reg, sst->addr.pci_cfg + SST_VDRTCTL2);
 
-	sst_dsp_shim_update_bits_unlocked(sst, SST_CSR,
-			SST_CSR_D0_MASK, SST_CSR_SBCS0 | SST_CSR_SBCS1 |
-			SST_CSR_STALL | SST_CSR_DCS(4));
 	udelay(50);
 
-	/* enable clock core gating */
+	/* switch on audio PLL */
 	reg = readl(sst->addr.pci_cfg + SST_VDRTCTL2);
-	reg |= SST_VDRTCL2_DCLCGE;
+	reg &= ~SST_VDRTCL2_APLLSE_MASK;
 	writel(reg, sst->addr.pci_cfg + SST_VDRTCTL2);
 
-	/* clear reset */
-	sst_dsp_shim_update_bits_unlocked(sst, SST_CSR, SST_CSR_RST, 0);
+	/* set default power gating control, enable power gating control for all blocks. that is,
+	can't be accessed, please enable each block before accessing. */
+	reg = readl(sst->addr.pci_cfg + SST_VDRTCTL0);
+	reg |= SST_VDRTCL0_DSRAMPGE_MASK | SST_VDRTCL0_ISRAMPGE_MASK;
+	/* for D0, always enable the block(DSRAM[0]) used for FW dump */
+	fw_dump_bit = 1 << SST_VDRTCL0_DSRAMPGE_SHIFT;
+	writel(reg & ~fw_dump_bit, sst->addr.pci_cfg + SST_VDRTCTL0);
+
 
 	/* disable DMA finish function for SSP0 & SSP1 */
 	sst_dsp_shim_update_bits_unlocked(sst, SST_CSR2, SST_CSR2_SDFD_SSP1,
@@ -418,6 +384,12 @@  static int hsw_set_dsp_D0(struct sst_dsp *sst)
 	sst_dsp_shim_update_bits(sst, SST_IMRD, (SST_IMRD_DONE | SST_IMRD_BUSY |
 				SST_IMRD_SSP0 | SST_IMRD_DMAC), 0x0);
 
+	/* clear IPC registers */
+	sst_dsp_shim_write(sst, SST_IPCX, 0x0);
+	sst_dsp_shim_write(sst, SST_IPCD, 0x0);
+	sst_dsp_shim_write(sst, 0x80, 0x6);
+	sst_dsp_shim_write(sst, 0xe0, 0x300a);
+
 	return 0;
 }
 
@@ -443,6 +415,11 @@  static void hsw_sleep(struct sst_dsp *sst)
 {
 	dev_dbg(sst->dev, "HSW_PM dsp runtime suspend\n");
 
+	/* put DSP into reset and stall */
+	sst_dsp_shim_update_bits(sst, SST_CSR,
+		SST_CSR_24MHZ_LPCS | SST_CSR_RST | SST_CSR_STALL,
+		SST_CSR_RST | SST_CSR_STALL | SST_CSR_24MHZ_LPCS);
+
 	hsw_set_dsp_D3(sst);
 	dev_dbg(sst->dev, "HSW_PM dsp runtime suspend exit\n");
 }