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

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.comSigned-off-by: default avatarMark Brown <broonie@kernel.org>
parent e8f112d8
......@@ -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;
......
......@@ -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);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment