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