aboutsummaryrefslogtreecommitdiffstats
path: root/sound
diff options
context:
space:
mode:
authorJie Yang <yang.jie@intel.com>2015-02-05 09:56:48 -0500
committerMark Brown <broonie@kernel.org>2015-02-05 13:05:28 -0500
commitcd311dd123f5ae5c6da71bdfa9a379a694eb9917 (patch)
treeb0b86dcdd990d64371879399d1f282672454eb28 /sound
parentc41cda1dbe50816d839c32271007c7b832d4d14a (diff)
ASoC: Intel: add a status for runtime suspend/resume
For runtime suspend/resume, it is some different with suspend/resume, e.g. codec power supply won't be switch off, codec jack detection still working(to wake up system from Jack event), won't call call snd_soc_suspend/resume, etc. So here, we add a platform PM status, HSW_PM_STATE_RTD3, to make the status more clear, when in idle, it will enter this status, to transfer from HSW_PM_STATE_RTD3 to HSW_PM_STATE_D3, we will do those extra jobs, and vice versa for resuming. Signed-off-by: Jie Yang <yang.jie@intel.com> Signed-off-by: Mark Brown <broonie@kernel.org>
Diffstat (limited to 'sound')
-rw-r--r--sound/soc/intel/sst-haswell-pcm.c70
1 files changed, 36 insertions, 34 deletions
diff --git a/sound/soc/intel/sst-haswell-pcm.c b/sound/soc/intel/sst-haswell-pcm.c
index ad7f4a51e138..78fa01be57f2 100644
--- a/sound/soc/intel/sst-haswell-pcm.c
+++ b/sound/soc/intel/sst-haswell-pcm.c
@@ -119,8 +119,9 @@ struct hsw_pcm_data {
119}; 119};
120 120
121enum hsw_pm_state { 121enum hsw_pm_state {
122 HSW_PM_STATE_D3 = 0, 122 HSW_PM_STATE_D0 = 0,
123 HSW_PM_STATE_D0 = 1, 123 HSW_PM_STATE_RTD3 = 1,
124 HSW_PM_STATE_D3 = 2,
124}; 125};
125 126
126/* private data for the driver */ 127/* private data for the driver */
@@ -1035,12 +1036,12 @@ static int hsw_pcm_runtime_suspend(struct device *dev)
1035 struct hsw_priv_data *pdata = dev_get_drvdata(dev); 1036 struct hsw_priv_data *pdata = dev_get_drvdata(dev);
1036 struct sst_hsw *hsw = pdata->hsw; 1037 struct sst_hsw *hsw = pdata->hsw;
1037 1038
1038 if (pdata->pm_state == HSW_PM_STATE_D3) 1039 if (pdata->pm_state >= HSW_PM_STATE_RTD3)
1039 return 0; 1040 return 0;
1040 1041
1041 sst_hsw_dsp_runtime_suspend(hsw); 1042 sst_hsw_dsp_runtime_suspend(hsw);
1042 sst_hsw_dsp_runtime_sleep(hsw); 1043 sst_hsw_dsp_runtime_sleep(hsw);
1043 pdata->pm_state = HSW_PM_STATE_D3; 1044 pdata->pm_state = HSW_PM_STATE_RTD3;
1044 1045
1045 return 0; 1046 return 0;
1046} 1047}
@@ -1051,7 +1052,7 @@ static int hsw_pcm_runtime_resume(struct device *dev)
1051 struct sst_hsw *hsw = pdata->hsw; 1052 struct sst_hsw *hsw = pdata->hsw;
1052 int ret; 1053 int ret;
1053 1054
1054 if (pdata->pm_state == HSW_PM_STATE_D0) 1055 if (pdata->pm_state != HSW_PM_STATE_RTD3)
1055 return 0; 1056 return 0;
1056 1057
1057 ret = sst_hsw_dsp_load(hsw); 1058 ret = sst_hsw_dsp_load(hsw);
@@ -1091,7 +1092,7 @@ static void hsw_pcm_complete(struct device *dev)
1091 struct hsw_pcm_data *pcm_data; 1092 struct hsw_pcm_data *pcm_data;
1092 int i, err; 1093 int i, err;
1093 1094
1094 if (pdata->pm_state == HSW_PM_STATE_D0) 1095 if (pdata->pm_state != HSW_PM_STATE_D3)
1095 return; 1096 return;
1096 1097
1097 err = sst_hsw_dsp_load(hsw); 1098 err = sst_hsw_dsp_load(hsw);
@@ -1139,41 +1140,42 @@ static int hsw_pcm_prepare(struct device *dev)
1139 1140
1140 if (pdata->pm_state == HSW_PM_STATE_D3) 1141 if (pdata->pm_state == HSW_PM_STATE_D3)
1141 return 0; 1142 return 0;
1142 /* suspend all active streams */ 1143 else if (pdata->pm_state == HSW_PM_STATE_D0) {
1143 for (i = 0; i < ARRAY_SIZE(mod_map); i++) { 1144 /* suspend all active streams */
1144 pcm_data = &pdata->pcm[mod_map[i].dai_id][mod_map[i].stream]; 1145 for (i = 0; i < ARRAY_SIZE(mod_map); i++) {
1146 pcm_data = &pdata->pcm[mod_map[i].dai_id][mod_map[i].stream];
1147
1148 if (!pcm_data->substream)
1149 continue;
1150 dev_dbg(dev, "suspending pcm %d\n", i);
1151 snd_pcm_suspend_all(pcm_data->hsw_pcm);
1152
1153 /* We need to wait until the DSP FW stops the streams */
1154 msleep(2);
1155 }
1145 1156
1146 if (!pcm_data->substream) 1157 /* preserve persistent memory */
1147 continue; 1158 for (i = 0; i < ARRAY_SIZE(mod_map); i++) {
1148 dev_dbg(dev, "suspending pcm %d\n", i); 1159 pcm_data = &pdata->pcm[mod_map[i].dai_id][mod_map[i].stream];
1149 snd_pcm_suspend_all(pcm_data->hsw_pcm); 1160
1161 if (!pcm_data->substream)
1162 continue;
1150 1163
1151 /* We need to wait until the DSP FW stops the streams */ 1164 dev_dbg(dev, "saving context pcm %d\n", i);
1152 msleep(2); 1165 err = sst_module_runtime_save(pcm_data->runtime,
1166 &pcm_data->context);
1167 if (err < 0)
1168 dev_err(dev, "failed to save context for PCM %d\n", i);
1169 }
1170 /* enter D3 state and stall */
1171 sst_hsw_dsp_runtime_suspend(hsw);
1172 /* put the DSP to sleep */
1173 sst_hsw_dsp_runtime_sleep(hsw);
1153 } 1174 }
1154 1175
1155 snd_soc_suspend(pdata->soc_card->dev); 1176 snd_soc_suspend(pdata->soc_card->dev);
1156 snd_soc_poweroff(pdata->soc_card->dev); 1177 snd_soc_poweroff(pdata->soc_card->dev);
1157 1178
1158 /* enter D3 state and stall */
1159 sst_hsw_dsp_runtime_suspend(hsw);
1160
1161 /* preserve persistent memory */
1162 for (i = 0; i < ARRAY_SIZE(mod_map); i++) {
1163 pcm_data = &pdata->pcm[mod_map[i].dai_id][mod_map[i].stream];
1164
1165 if (!pcm_data->substream)
1166 continue;
1167
1168 dev_dbg(dev, "saving context pcm %d\n", i);
1169 err = sst_module_runtime_save(pcm_data->runtime,
1170 &pcm_data->context);
1171 if (err < 0)
1172 dev_err(dev, "failed to save context for PCM %d\n", i);
1173 }
1174
1175 /* put the DSP to sleep */
1176 sst_hsw_dsp_runtime_sleep(hsw);
1177 pdata->pm_state = HSW_PM_STATE_D3; 1179 pdata->pm_state = HSW_PM_STATE_D3;
1178 1180
1179 return 0; 1181 return 0;