diff mbox series

[04/26] ASoC: SOF: Intel: hda-dsp: Add helper for setting DSP D0ix substate

Message ID 20191025224122.7718-5-pierre-louis.bossart@linux.intel.com (mailing list archive)
State Accepted
Commit 62f8f76604623980d41cf73691ca45288871efd9
Headers show
Series ASoC: SOF: enable S0ix support for Intel platforms | expand

Commit Message

Pierre-Louis Bossart Oct. 25, 2019, 10:41 p.m. UTC
From: Keyon Jie <yang.jie@linux.intel.com>

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

Signed-off-by: Keyon Jie <yang.jie@linux.intel.com>
Signed-off-by: Pierre-Louis Bossart <pierre-louis.bossart@linux.intel.com>
---
 sound/soc/sof/intel/hda-dsp.c | 46 +++++++++++++++++++++++++++++++++++
 sound/soc/sof/intel/hda.h     | 10 ++++++++
 2 files changed, 56 insertions(+)

Comments

Cezary Rojewski Oct. 29, 2019, 10:07 a.m. UTC | #1
On 2019-10-26 00:41, Pierre-Louis Bossart wrote:
> From: Keyon Jie <yang.jie@linux.intel.com>
> 
> Adding helper to implement setting dsp to d0i3 or d0i0 status, this will
> be needed for driver D0ix support.
> 
> Signed-off-by: Keyon Jie <yang.jie@linux.intel.com>
> Signed-off-by: Pierre-Louis Bossart <pierre-louis.bossart@linux.intel.com>

> +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;

Some indentation or parenthesis would make this cleaner.

> +	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;
> +}
> +

I believe hda_dsp_wait_d0i3c_done function could have had its argument 
list simplified. "retry" is passed externally and it is always set to 
50. One could put the "retry" right inside _done function. This or allow 
the caller to modify the sleep period. Another option is to replace 
"retry" with "timeout period" (total timeout, that is) entirely.

In regard to maintenance, both ret checks (resulting in dev_errs) assume 
-ETIMEOUT outcome on _done failure. If said function gets updated in the 
future, these implicit checks might cause problems.

>   static int hda_suspend(struct snd_sof_dev *sdev, bool runtime_suspend)
>   {
>   	struct sof_intel_hda_dev *hda = sdev->pdata->hw_pdata;
> diff --git a/sound/soc/sof/intel/hda.h b/sound/soc/sof/intel/hda.h
> index ea02bf40cb25..0e7c366b8f71 100644
> --- a/sound/soc/sof/intel/hda.h
> +++ b/sound/soc/sof/intel/hda.h
> @@ -64,6 +64,13 @@
>   #define SOF_HDA_PPCTL_PIE		BIT(31)
>   #define SOF_HDA_PPCTL_GPROCEN		BIT(30)
>   
> +/*Vendor Specific Registers*/

Missing spaces.

> +#define SOF_HDA_VS_D0I3C		0x104A
Sridharan, Ranjani Oct. 29, 2019, 4:37 p.m. UTC | #2
On Tue, Oct 29, 2019 at 3:10 AM Cezary Rojewski <cezary.rojewski@intel.com>
wrote:

> On 2019-10-26 00:41, Pierre-Louis Bossart wrote:
> > From: Keyon Jie <yang.jie@linux.intel.com>
> >
> > Adding helper to implement setting dsp to d0i3 or d0i0 status, this will
> > be needed for driver D0ix support.
> >
> > Signed-off-by: Keyon Jie <yang.jie@linux.intel.com>
> > Signed-off-by: Pierre-Louis Bossart <
> pierre-louis.bossart@linux.intel.com>
>
> > +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;
>
> Some indentation or parenthesis would make this cleaner.
>
> > +     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;
> > +}
> > +
>
> I believe hda_dsp_wait_d0i3c_done function could have had its argument
> list simplified. "retry" is passed externally and it is always set to
> 50. One could put the "retry" right inside _done function. This or allow
> the caller to modify the sleep period. Another option is to replace
> "retry" with "timeout period" (total timeout, that is) entirely.
>
Cezary,

This has been fixed later in the series to use
the HDA_DSP_REG_POLL_RETRY_COUNT but I agree that this can further be
simplified to just use the macro inside the hda_dsp_wait_d0i3c_done()
instead of passing the argument.


>
> In regard to maintenance, both ret checks (resulting in dev_errs) assume
> -ETIMEOUT outcome on _done failure. If said function gets updated in the
> future, these implicit checks might cause problems.
>
Possibly, but at the moment -ETIMEOUT looks like the correct error to be
reported.

Thanks,
Ranjani

>
> >   static int hda_suspend(struct snd_sof_dev *sdev, bool runtime_suspend)
> >   {
> >       struct sof_intel_hda_dev *hda = sdev->pdata->hw_pdata;
> > diff --git a/sound/soc/sof/intel/hda.h b/sound/soc/sof/intel/hda.h
> > index ea02bf40cb25..0e7c366b8f71 100644
> > --- a/sound/soc/sof/intel/hda.h
> > +++ b/sound/soc/sof/intel/hda.h
> > @@ -64,6 +64,13 @@
> >   #define SOF_HDA_PPCTL_PIE           BIT(31)
> >   #define SOF_HDA_PPCTL_GPROCEN               BIT(30)
> >
> > +/*Vendor Specific Registers*/
>
> Missing spaces.
>
> > +#define SOF_HDA_VS_D0I3C             0x104A
> _______________________________________________
> Alsa-devel mailing list
> Alsa-devel@alsa-project.org
> https://mailman.alsa-project.org/mailman/listinfo/alsa-devel
>
diff mbox series

Patch

diff --git a/sound/soc/sof/intel/hda-dsp.c b/sound/soc/sof/intel/hda-dsp.c
index 3ea401646e0c..fa2f1f66c72c 100644
--- a/sound/soc/sof/intel/hda-dsp.c
+++ b/sound/soc/sof/intel/hda-dsp.c
@@ -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;
diff --git a/sound/soc/sof/intel/hda.h b/sound/soc/sof/intel/hda.h
index ea02bf40cb25..0e7c366b8f71 100644
--- a/sound/soc/sof/intel/hda.h
+++ b/sound/soc/sof/intel/hda.h
@@ -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);