diff options
Diffstat (limited to 'sound/soc/sof/intel/hda-dsp.c')
| -rw-r--r-- | sound/soc/sof/intel/hda-dsp.c | 101 | 
1 files changed, 66 insertions, 35 deletions
diff --git a/sound/soc/sof/intel/hda-dsp.c b/sound/soc/sof/intel/hda-dsp.c index a6f2822401e0..44f39a520bb3 100644 --- a/sound/soc/sof/intel/hda-dsp.c +++ b/sound/soc/sof/intel/hda-dsp.c @@ -18,6 +18,7 @@  #include <linux/module.h>  #include <sound/hdaudio_ext.h>  #include <sound/hda_register.h> +#include <sound/hda-mlink.h>  #include <trace/events/sof_intel.h>  #include "../sof-audio.h"  #include "../ops.h" @@ -321,6 +322,9 @@ void hda_dsp_ipc_int_enable(struct snd_sof_dev *sdev)  	struct sof_intel_hda_dev *hda = sdev->pdata->hw_pdata;  	const struct sof_intel_dsp_desc *chip = hda->desc; +	if (sdev->dspless_mode_selected) +		return; +  	/* enable IPC DONE and BUSY interrupts */  	snd_sof_dsp_update_bits(sdev, HDA_DSP_BAR, chip->ipc_ctl,  			HDA_DSP_REG_HIPCCTL_DONE | HDA_DSP_REG_HIPCCTL_BUSY, @@ -336,6 +340,9 @@ void hda_dsp_ipc_int_disable(struct snd_sof_dev *sdev)  	struct sof_intel_hda_dev *hda = sdev->pdata->hw_pdata;  	const struct sof_intel_dsp_desc *chip = hda->desc; +	if (sdev->dspless_mode_selected) +		return; +  	/* disable IPC interrupt */  	snd_sof_dsp_update_bits(sdev, HDA_DSP_BAR, HDA_DSP_REG_ADSPIC,  				HDA_DSP_ADSPIC_IPC, 0); @@ -567,31 +574,11 @@ static void hda_dsp_state_log(struct snd_sof_dev *sdev)   * is called again either because of a new IPC sent to the DSP or   * during system suspend/resume.   */ -int hda_dsp_set_power_state(struct snd_sof_dev *sdev, -			    const struct sof_dsp_power_state *target_state) +static int hda_dsp_set_power_state(struct snd_sof_dev *sdev, +				   const struct sof_dsp_power_state *target_state)  {  	int ret = 0; -	/* -	 * When the DSP is already in D0I3 and the target state is D0I3, -	 * it could be the case that the DSP is in D0I3 during S0 -	 * and the system is suspending to S0Ix. Therefore, -	 * hda_dsp_set_D0_state() must be called to disable trace DMA -	 * by sending the PM_GATE IPC to the FW. -	 */ -	if (target_state->substate == SOF_HDA_DSP_PM_D0I3 && -	    sdev->system_suspend_target == SOF_SUSPEND_S0IX) -		goto set_state; - -	/* -	 * For all other cases, return without doing anything if -	 * the DSP is already in the target state. -	 */ -	if (target_state->state == sdev->dsp_power_state.state && -	    target_state->substate == sdev->dsp_power_state.substate) -		return 0; - -set_state:  	switch (target_state->state) {  	case SOF_DSP_PM_D0:  		ret = hda_dsp_set_D0_state(sdev, target_state); @@ -623,6 +610,42 @@ set_state:  	return ret;  } +int hda_dsp_set_power_state_ipc3(struct snd_sof_dev *sdev, +				 const struct sof_dsp_power_state *target_state) +{ +	/* +	 * When the DSP is already in D0I3 and the target state is D0I3, +	 * it could be the case that the DSP is in D0I3 during S0 +	 * and the system is suspending to S0Ix. Therefore, +	 * hda_dsp_set_D0_state() must be called to disable trace DMA +	 * by sending the PM_GATE IPC to the FW. +	 */ +	if (target_state->substate == SOF_HDA_DSP_PM_D0I3 && +	    sdev->system_suspend_target == SOF_SUSPEND_S0IX) +		return hda_dsp_set_power_state(sdev, target_state); + +	/* +	 * For all other cases, return without doing anything if +	 * the DSP is already in the target state. +	 */ +	if (target_state->state == sdev->dsp_power_state.state && +	    target_state->substate == sdev->dsp_power_state.substate) +		return 0; + +	return hda_dsp_set_power_state(sdev, target_state); +} + +int hda_dsp_set_power_state_ipc4(struct snd_sof_dev *sdev, +				 const struct sof_dsp_power_state *target_state) +{ +	/* Return without doing anything if the DSP is already in the target state */ +	if (target_state->state == sdev->dsp_power_state.state && +	    target_state->substate == sdev->dsp_power_state.substate) +		return 0; + +	return hda_dsp_set_power_state(sdev, target_state); +} +  /*   * Audio DSP states may transform as below:-   * @@ -681,6 +704,9 @@ static int hda_suspend(struct snd_sof_dev *sdev, bool runtime_suspend)  	/* power down all hda links */  	hda_bus_ml_suspend(bus); +	if (sdev->dspless_mode_selected) +		goto skip_dsp; +  	ret = chip->power_down_dsp(sdev);  	if (ret < 0) {  		dev_err(sdev->dev, "failed to power down DSP during suspend\n"); @@ -694,6 +720,7 @@ static int hda_suspend(struct snd_sof_dev *sdev, bool runtime_suspend)  	/* disable ppcap interrupt */  	hda_dsp_ctrl_ppcap_enable(sdev, false);  	hda_dsp_ctrl_ppcap_int_enable(sdev, false); +skip_dsp:  	/* disable hda bus irq and streams */  	hda_dsp_ctrl_stop_chip(sdev); @@ -744,9 +771,11 @@ static int hda_resume(struct snd_sof_dev *sdev, bool runtime_resume)  			hda_codec_jack_check(sdev);  	} -	/* enable ppcap interrupt */ -	hda_dsp_ctrl_ppcap_enable(sdev, true); -	hda_dsp_ctrl_ppcap_int_enable(sdev, true); +	if (!sdev->dspless_mode_selected) { +		/* enable ppcap interrupt */ +		hda_dsp_ctrl_ppcap_enable(sdev, true); +		hda_dsp_ctrl_ppcap_int_enable(sdev, true); +	}  cleanup:  	/* display codec can powered off after controller init */ @@ -788,7 +817,7 @@ int hda_dsp_resume(struct snd_sof_dev *sdev)  		}  		/* restore L1SEN bit */ -		if (hda->l1_support_changed) +		if (hda->l1_disabled)  			snd_sof_dsp_update_bits(sdev, HDA_DSP_HDA_BAR,  						HDA_VS_INTEL_EM2,  						HDA_VS_INTEL_EM2_L1SEN, 0); @@ -843,8 +872,10 @@ int hda_dsp_runtime_suspend(struct snd_sof_dev *sdev)  	};  	int ret; -	/* cancel any attempt for DSP D0I3 */ -	cancel_delayed_work_sync(&hda->d0i3_work); +	if (!sdev->dspless_mode_selected) { +		/* cancel any attempt for DSP D0I3 */ +		cancel_delayed_work_sync(&hda->d0i3_work); +	}  	/* stop hda controller and power dsp off */  	ret = hda_suspend(sdev, true); @@ -866,8 +897,10 @@ int hda_dsp_suspend(struct snd_sof_dev *sdev, u32 target_state)  	};  	int ret; -	/* cancel any attempt for DSP D0I3 */ -	cancel_delayed_work_sync(&hda->d0i3_work); +	if (!sdev->dspless_mode_selected) { +		/* cancel any attempt for DSP D0I3 */ +		cancel_delayed_work_sync(&hda->d0i3_work); +	}  	if (target_state == SOF_DSP_PM_D0) {  		/* Set DSP power state */ @@ -880,11 +913,9 @@ int hda_dsp_suspend(struct snd_sof_dev *sdev, u32 target_state)  		}  		/* enable L1SEN to make sure the system can enter S0Ix */ -		hda->l1_support_changed = -			snd_sof_dsp_update_bits(sdev, HDA_DSP_HDA_BAR, -						HDA_VS_INTEL_EM2, -						HDA_VS_INTEL_EM2_L1SEN, -						HDA_VS_INTEL_EM2_L1SEN); +		if (hda->l1_disabled) +			snd_sof_dsp_update_bits(sdev, HDA_DSP_HDA_BAR, HDA_VS_INTEL_EM2, +						HDA_VS_INTEL_EM2_L1SEN, HDA_VS_INTEL_EM2_L1SEN);  		/* stop the CORB/RIRB DMA if it is On */  		hda_codec_suspend_cmd_io(sdev);  |