ASoC: SOF: Intel: hda-dsp: harden D0i3 programming sequence
authorRander Wang <rander.wang@intel.com>
Tue, 7 Mar 2023 09:54:52 +0000 (11:54 +0200)
committerMark Brown <broonie@kernel.org>
Tue, 7 Mar 2023 13:58:01 +0000 (13:58 +0000)
Add delay between set and wait command according to hardware programming
sequence. Also add debug log to detect error.

Signed-off-by: Rander Wang <rander.wang@intel.com>
Reviewed-by: Péter Ujfalusi <peter.ujfalusi@linux.intel.com>
Reviewed-by: Pierre-Louis Bossart <pierre-louis.bossart@linux.intel.com>
Reviewed-by: Péter Ujfalusi <peter.ujfalusi@linux.intel.com>
Reviewed-by: Ranjani Sridharan <ranjani.sridharan@linux.intel.com>
Signed-off-by: Peter Ujfalusi <peter.ujfalusi@linux.intel.com>
Link: https://lore.kernel.org/r/20230307095453.3719-1-peter.ujfalusi@linux.intel.com
Signed-off-by: Mark Brown <broonie@kernel.org>
sound/soc/sof/intel/hda-dsp.c

index 68eb06f13a1fd2539bab66cf9c255d860e059caf..a6f2822401e03da1d3553f50fa4370955219f6e2 100644 (file)
@@ -392,6 +392,12 @@ static int hda_dsp_update_d0i3c_register(struct snd_sof_dev *sdev, u8 value)
        snd_sof_dsp_update8(sdev, HDA_DSP_HDA_BAR, chip->d0i3_offset,
                            SOF_HDA_VS_D0I3C_I3, value);
 
+       /*
+        * The value written to the D0I3C::I3 bit may not be taken into account immediately.
+        * A delay is recommended before checking if D0I3C::CIP is cleared
+        */
+       usleep_range(30, 40);
+
        /* Wait for cmd in progress to be cleared before exiting the function */
        ret = hda_dsp_wait_d0i3c_done(sdev);
        if (ret < 0) {
@@ -400,6 +406,12 @@ static int hda_dsp_update_d0i3c_register(struct snd_sof_dev *sdev, u8 value)
        }
 
        reg = snd_sof_dsp_read8(sdev, HDA_DSP_HDA_BAR, chip->d0i3_offset);
+       /* Confirm d0i3 state changed with paranoia check */
+       if ((reg ^ value) & SOF_HDA_VS_D0I3C_I3) {
+               dev_err(sdev->dev, "failed to update D0I3C!\n");
+               return -EIO;
+       }
+
        trace_sof_intel_D0I3C_updated(sdev, reg);
 
        return 0;