Unverified Commit 62f8f766 authored by Keyon Jie's avatar Keyon Jie Committed by Mark Brown
Browse files

ASoC: SOF: Intel: hda-dsp: Add helper for setting DSP D0ix substate



Adding helper to implement setting dsp to d0i3 or d0i0 status, this will
be needed for driver D0ix support.

Signed-off-by: default avatarKeyon Jie <yang.jie@linux.intel.com>
Signed-off-by: default avatarPierre-Louis Bossart <pierre-louis.bossart@linux.intel.com>
Link: https://lore.kernel.org/r/20191025224122.7718-5-pierre-louis.bossart@linux.intel.com


Signed-off-by: default avatarMark Brown <broonie@kernel.org>
parent e8f112d8
Loading
Loading
Loading
Loading
+46 −0
Original line number Diff line number Diff line
@@ -306,6 +306,52 @@ void hda_dsp_ipc_int_disable(struct snd_sof_dev *sdev)
			HDA_DSP_REG_HIPCCTL_BUSY | HDA_DSP_REG_HIPCCTL_DONE, 0);
}

static int hda_dsp_wait_d0i3c_done(struct snd_sof_dev *sdev, int retry)
{
	struct hdac_bus *bus = sof_to_bus(sdev);

	while (snd_hdac_chip_readb(bus, VS_D0I3C) & SOF_HDA_VS_D0I3C_CIP) {
		if (!retry--)
			return -ETIMEDOUT;
		usleep_range(10, 15);
	}

	return 0;
}

int hda_dsp_set_power_state(struct snd_sof_dev *sdev,
			    enum sof_d0_substate d0_substate)
{
	struct hdac_bus *bus = sof_to_bus(sdev);
	int retry = 50;
	int ret;
	u8 value;

	/* Write to D0I3C after Command-In-Progress bit is cleared */
	ret = hda_dsp_wait_d0i3c_done(sdev, retry);
	if (ret < 0) {
		dev_err(bus->dev, "CIP timeout before update D0I3C!\n");
		return ret;
	}

	/* Update D0I3C register */
	value = d0_substate == SOF_DSP_D0I3 ? SOF_HDA_VS_D0I3C_I3 : 0;
	snd_hdac_chip_updateb(bus, VS_D0I3C, SOF_HDA_VS_D0I3C_I3, value);

	/* Wait for cmd in progress to be cleared before exiting the function */
	retry = 50;
	ret = hda_dsp_wait_d0i3c_done(sdev, retry);
	if (ret < 0) {
		dev_err(bus->dev, "CIP timeout after D0I3C updated!\n");
		return ret;
	}

	dev_vdbg(bus->dev, "D0I3C updated, register = 0x%x\n",
		 snd_hdac_chip_readb(bus, VS_D0I3C));

	return 0;
}

static int hda_suspend(struct snd_sof_dev *sdev, bool runtime_suspend)
{
	struct sof_intel_hda_dev *hda = sdev->pdata->hw_pdata;
+10 −0
Original line number Diff line number Diff line
@@ -64,6 +64,13 @@
#define SOF_HDA_PPCTL_PIE		BIT(31)
#define SOF_HDA_PPCTL_GPROCEN		BIT(30)

/*Vendor Specific Registers*/
#define SOF_HDA_VS_D0I3C		0x104A

/* D0I3C Register fields */
#define SOF_HDA_VS_D0I3C_CIP		BIT(0) /* Command-In-Progress */
#define SOF_HDA_VS_D0I3C_I3		BIT(2) /* D0i3 enable bit */

/* DPIB entry size: 8 Bytes = 2 DWords */
#define SOF_HDA_DPIB_ENTRY_SIZE	0x8

@@ -455,6 +462,9 @@ int hda_dsp_core_reset_power_down(struct snd_sof_dev *sdev,
void hda_dsp_ipc_int_enable(struct snd_sof_dev *sdev);
void hda_dsp_ipc_int_disable(struct snd_sof_dev *sdev);

int hda_dsp_set_power_state(struct snd_sof_dev *sdev,
			    enum sof_d0_substate d0_substate);

int hda_dsp_suspend(struct snd_sof_dev *sdev);
int hda_dsp_resume(struct snd_sof_dev *sdev);
int hda_dsp_runtime_suspend(struct snd_sof_dev *sdev);