Skip to content

Commit 996b07e

Browse files
ranj063broonie
authored andcommitted
ASoC: SOF: Intel: Split the set_power_op for IPC3 and IPC4
Suspending to S0iX with IPC3 requires the PM_GATE IPC to be sent again to stop the DMA trace. But with IPC4, this is not needed as the trace is stopped with the LARGE_CONFIG_SET IPC. Also, sending the MOD_D0IX IPC to set the D0I3 state again when the DSP is in D0I3 already results in an imbalance in PM runtime states in the firmware. So split the set_power_state ops for IPC3 and IPC4 to avoid sending the MOD_D0IX IPC when the DSP is already in D0I3 with IPC4. Signed-off-by: Ranjani Sridharan <ranjani.sridharan@linux.intel.com> Reviewed-by: Rander Wang <rander.wang@intel.com> Reviewed-by: Bard Liao <yung-chuan.liao@linux.intel.com> Reviewed-by: Péter Ujfalusi <peter.ujfalusi@linux.intel.com> Reviewed-by: Pierre-Louis Bossart <pierre-louis.bossart@linux.intel.com> Signed-off-by: Peter Ujfalusi <peter.ujfalusi@linux.intel.com> Link: https://lore.kernel.org/r/20230420104714.29573-1-peter.ujfalusi@linux.intel.com Signed-off-by: Mark Brown <broonie@kernel.org>
1 parent 09cda70 commit 996b07e

8 files changed

Lines changed: 60 additions & 25 deletions

File tree

sound/soc/sof/intel/apl.c

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,8 @@ int sof_apl_ops_init(struct snd_sof_dev *sdev)
4848

4949
/* debug */
5050
sof_apl_ops.ipc_dump = hda_ipc_dump;
51+
52+
sof_apl_ops.set_power_state = hda_dsp_set_power_state_ipc3;
5153
}
5254

5355
if (sdev->pdata->ipc_type == SOF_INTEL_IPC4) {
@@ -73,6 +75,8 @@ int sof_apl_ops_init(struct snd_sof_dev *sdev)
7375

7476
/* debug */
7577
sof_apl_ops.ipc_dump = hda_ipc4_dump;
78+
79+
sof_apl_ops.set_power_state = hda_dsp_set_power_state_ipc4;
7680
}
7781

7882
/* set DAI driver ops */

sound/soc/sof/intel/cnl.c

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -395,6 +395,8 @@ int sof_cnl_ops_init(struct snd_sof_dev *sdev)
395395

396396
/* debug */
397397
sof_cnl_ops.ipc_dump = cnl_ipc_dump;
398+
399+
sof_cnl_ops.set_power_state = hda_dsp_set_power_state_ipc3;
398400
}
399401

400402
if (sdev->pdata->ipc_type == SOF_INTEL_IPC4) {
@@ -420,6 +422,8 @@ int sof_cnl_ops_init(struct snd_sof_dev *sdev)
420422

421423
/* debug */
422424
sof_cnl_ops.ipc_dump = cnl_ipc4_dump;
425+
426+
sof_cnl_ops.set_power_state = hda_dsp_set_power_state_ipc4;
423427
}
424428

425429
/* set DAI driver ops */

sound/soc/sof/intel/hda-common-ops.c

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -89,7 +89,6 @@ struct snd_sof_dsp_ops sof_hda_common_ops = {
8989
.runtime_resume = hda_dsp_runtime_resume,
9090
.runtime_idle = hda_dsp_runtime_idle,
9191
.set_hw_params_upon_resume = hda_dsp_set_hw_params_upon_resume,
92-
.set_power_state = hda_dsp_set_power_state,
9392

9493
/* ALSA HW info flags */
9594
.hw_info = SNDRV_PCM_INFO_MMAP |

sound/soc/sof/intel/hda-dsp.c

Lines changed: 38 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -574,31 +574,11 @@ static void hda_dsp_state_log(struct snd_sof_dev *sdev)
574574
* is called again either because of a new IPC sent to the DSP or
575575
* during system suspend/resume.
576576
*/
577-
int hda_dsp_set_power_state(struct snd_sof_dev *sdev,
578-
const struct sof_dsp_power_state *target_state)
577+
static int hda_dsp_set_power_state(struct snd_sof_dev *sdev,
578+
const struct sof_dsp_power_state *target_state)
579579
{
580580
int ret = 0;
581581

582-
/*
583-
* When the DSP is already in D0I3 and the target state is D0I3,
584-
* it could be the case that the DSP is in D0I3 during S0
585-
* and the system is suspending to S0Ix. Therefore,
586-
* hda_dsp_set_D0_state() must be called to disable trace DMA
587-
* by sending the PM_GATE IPC to the FW.
588-
*/
589-
if (target_state->substate == SOF_HDA_DSP_PM_D0I3 &&
590-
sdev->system_suspend_target == SOF_SUSPEND_S0IX)
591-
goto set_state;
592-
593-
/*
594-
* For all other cases, return without doing anything if
595-
* the DSP is already in the target state.
596-
*/
597-
if (target_state->state == sdev->dsp_power_state.state &&
598-
target_state->substate == sdev->dsp_power_state.substate)
599-
return 0;
600-
601-
set_state:
602582
switch (target_state->state) {
603583
case SOF_DSP_PM_D0:
604584
ret = hda_dsp_set_D0_state(sdev, target_state);
@@ -630,6 +610,42 @@ int hda_dsp_set_power_state(struct snd_sof_dev *sdev,
630610
return ret;
631611
}
632612

613+
int hda_dsp_set_power_state_ipc3(struct snd_sof_dev *sdev,
614+
const struct sof_dsp_power_state *target_state)
615+
{
616+
/*
617+
* When the DSP is already in D0I3 and the target state is D0I3,
618+
* it could be the case that the DSP is in D0I3 during S0
619+
* and the system is suspending to S0Ix. Therefore,
620+
* hda_dsp_set_D0_state() must be called to disable trace DMA
621+
* by sending the PM_GATE IPC to the FW.
622+
*/
623+
if (target_state->substate == SOF_HDA_DSP_PM_D0I3 &&
624+
sdev->system_suspend_target == SOF_SUSPEND_S0IX)
625+
return hda_dsp_set_power_state(sdev, target_state);
626+
627+
/*
628+
* For all other cases, return without doing anything if
629+
* the DSP is already in the target state.
630+
*/
631+
if (target_state->state == sdev->dsp_power_state.state &&
632+
target_state->substate == sdev->dsp_power_state.substate)
633+
return 0;
634+
635+
return hda_dsp_set_power_state(sdev, target_state);
636+
}
637+
638+
int hda_dsp_set_power_state_ipc4(struct snd_sof_dev *sdev,
639+
const struct sof_dsp_power_state *target_state)
640+
{
641+
/* Return without doing anything if the DSP is already in the target state */
642+
if (target_state->state == sdev->dsp_power_state.state &&
643+
target_state->substate == sdev->dsp_power_state.substate)
644+
return 0;
645+
646+
return hda_dsp_set_power_state(sdev, target_state);
647+
}
648+
633649
/*
634650
* Audio DSP states may transform as below:-
635651
*

sound/soc/sof/intel/hda.h

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -584,8 +584,10 @@ void hda_dsp_ipc_int_enable(struct snd_sof_dev *sdev);
584584
void hda_dsp_ipc_int_disable(struct snd_sof_dev *sdev);
585585
bool hda_dsp_core_is_enabled(struct snd_sof_dev *sdev, unsigned int core_mask);
586586

587-
int hda_dsp_set_power_state(struct snd_sof_dev *sdev,
588-
const struct sof_dsp_power_state *target_state);
587+
int hda_dsp_set_power_state_ipc3(struct snd_sof_dev *sdev,
588+
const struct sof_dsp_power_state *target_state);
589+
int hda_dsp_set_power_state_ipc4(struct snd_sof_dev *sdev,
590+
const struct sof_dsp_power_state *target_state);
589591

590592
int hda_dsp_suspend(struct snd_sof_dev *sdev, u32 target_state);
591593
int hda_dsp_resume(struct snd_sof_dev *sdev);

sound/soc/sof/intel/icl.c

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -116,6 +116,8 @@ int sof_icl_ops_init(struct snd_sof_dev *sdev)
116116

117117
/* debug */
118118
sof_icl_ops.ipc_dump = cnl_ipc_dump;
119+
120+
sof_icl_ops.set_power_state = hda_dsp_set_power_state_ipc3;
119121
}
120122

121123
if (sdev->pdata->ipc_type == SOF_INTEL_IPC4) {
@@ -141,6 +143,8 @@ int sof_icl_ops_init(struct snd_sof_dev *sdev)
141143

142144
/* debug */
143145
sof_icl_ops.ipc_dump = cnl_ipc4_dump;
146+
147+
sof_icl_ops.set_power_state = hda_dsp_set_power_state_ipc4;
144148
}
145149

146150
/* debug */

sound/soc/sof/intel/mtl.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -668,6 +668,8 @@ int sof_mtl_ops_init(struct snd_sof_dev *sdev)
668668
/* set DAI ops */
669669
hda_set_dai_drv_ops(sdev, &sof_mtl_ops);
670670

671+
sof_mtl_ops.set_power_state = hda_dsp_set_power_state_ipc4;
672+
671673
return 0;
672674
};
673675
EXPORT_SYMBOL_NS(sof_mtl_ops_init, SND_SOC_SOF_INTEL_HDA_COMMON);

sound/soc/sof/intel/tgl.c

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,8 @@ int sof_tgl_ops_init(struct snd_sof_dev *sdev)
7171

7272
/* debug */
7373
sof_tgl_ops.ipc_dump = cnl_ipc_dump;
74+
75+
sof_tgl_ops.set_power_state = hda_dsp_set_power_state_ipc3;
7476
}
7577

7678
if (sdev->pdata->ipc_type == SOF_INTEL_IPC4) {
@@ -96,6 +98,8 @@ int sof_tgl_ops_init(struct snd_sof_dev *sdev)
9698

9799
/* debug */
98100
sof_tgl_ops.ipc_dump = cnl_ipc4_dump;
101+
102+
sof_tgl_ops.set_power_state = hda_dsp_set_power_state_ipc4;
99103
}
100104

101105
/* set DAI driver ops */

0 commit comments

Comments
 (0)