aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/sound/pcm_params.h7
-rw-r--r--include/sound/soc.h3
-rw-r--r--sound/soc/intel/broadwell.c32
-rw-r--r--sound/soc/intel/bytcr_dpcm_rt5640.c4
-rw-r--r--sound/soc/intel/cht_bsw_rt5645.c4
-rw-r--r--sound/soc/intel/cht_bsw_rt5672.c49
-rw-r--r--sound/soc/intel/haswell.c4
-rw-r--r--sound/soc/intel/sst-dsp-priv.h13
-rw-r--r--sound/soc/intel/sst-firmware.c1
-rw-r--r--sound/soc/intel/sst-haswell-dsp.c6
-rw-r--r--sound/soc/intel/sst-haswell-ipc.c451
-rw-r--r--sound/soc/intel/sst-haswell-ipc.h53
-rw-r--r--sound/soc/intel/sst-haswell-pcm.c139
-rw-r--r--sound/soc/intel/sst-mfld-platform-pcm.c60
-rw-r--r--sound/soc/intel/sst-mfld-platform.h1
-rw-r--r--sound/soc/intel/sst/sst.c128
-rw-r--r--sound/soc/intel/sst/sst.h12
-rw-r--r--sound/soc/intel/sst/sst_drv_interface.c65
-rw-r--r--sound/soc/intel/sst/sst_loader.c10
-rw-r--r--sound/soc/soc-pcm.c1
20 files changed, 980 insertions, 63 deletions
diff --git a/include/sound/pcm_params.h b/include/sound/pcm_params.h
index 3c45f3924ba7..c704357775fc 100644
--- a/include/sound/pcm_params.h
+++ b/include/sound/pcm_params.h
@@ -366,4 +366,11 @@ static inline int params_physical_width(const struct snd_pcm_hw_params *p)
366 return snd_pcm_format_physical_width(params_format(p)); 366 return snd_pcm_format_physical_width(params_format(p));
367} 367}
368 368
369static inline void
370params_set_format(struct snd_pcm_hw_params *p, snd_pcm_format_t fmt)
371{
372 snd_mask_set(hw_param_mask(p, SNDRV_PCM_HW_PARAM_FORMAT),
373 (__force int)fmt);
374}
375
369#endif /* __SOUND_PCM_PARAMS_H */ 376#endif /* __SOUND_PCM_PARAMS_H */
diff --git a/include/sound/soc.h b/include/sound/soc.h
index 0d1ade195628..76bc944dcb5c 100644
--- a/include/sound/soc.h
+++ b/include/sound/soc.h
@@ -954,6 +954,9 @@ struct snd_soc_dai_link {
954 unsigned int symmetric_channels:1; 954 unsigned int symmetric_channels:1;
955 unsigned int symmetric_samplebits:1; 955 unsigned int symmetric_samplebits:1;
956 956
957 /* Mark this pcm with non atomic ops */
958 bool nonatomic;
959
957 /* Do not create a PCM for this DAI link (Backend link) */ 960 /* Do not create a PCM for this DAI link (Backend link) */
958 unsigned int no_pcm:1; 961 unsigned int no_pcm:1;
959 962
diff --git a/sound/soc/intel/broadwell.c b/sound/soc/intel/broadwell.c
index 9cf7d01479ad..af5d73070f60 100644
--- a/sound/soc/intel/broadwell.c
+++ b/sound/soc/intel/broadwell.c
@@ -110,9 +110,7 @@ static int broadwell_ssp0_fixup(struct snd_soc_pcm_runtime *rtd,
110 channels->min = channels->max = 2; 110 channels->min = channels->max = 2;
111 111
112 /* set SSP0 to 16 bit */ 112 /* set SSP0 to 16 bit */
113 snd_mask_set(&params->masks[SNDRV_PCM_HW_PARAM_FORMAT - 113 params_set_format(params, SNDRV_PCM_FORMAT_S16_LE);
114 SNDRV_PCM_HW_PARAM_FIRST_MASK],
115 SNDRV_PCM_FORMAT_S16_LE);
116 return 0; 114 return 0;
117} 115}
118 116
@@ -227,6 +225,32 @@ static struct snd_soc_dai_link broadwell_rt286_dais[] = {
227 }, 225 },
228}; 226};
229 227
228static int broadwell_suspend(struct snd_soc_card *card){
229 struct snd_soc_codec *codec;
230
231 list_for_each_entry(codec, &card->codec_dev_list, card_list) {
232 if (!strcmp(codec->component.name, "i2c-INT343A:00")) {
233 dev_dbg(codec->dev, "disabling jack detect before going to suspend.\n");
234 rt286_mic_detect(codec, NULL);
235 break;
236 }
237 }
238 return 0;
239}
240
241static int broadwell_resume(struct snd_soc_card *card){
242 struct snd_soc_codec *codec;
243
244 list_for_each_entry(codec, &card->codec_dev_list, card_list) {
245 if (!strcmp(codec->component.name, "i2c-INT343A:00")) {
246 dev_dbg(codec->dev, "enabling jack detect for resume.\n");
247 rt286_mic_detect(codec, &broadwell_headset);
248 break;
249 }
250 }
251 return 0;
252}
253
230/* broadwell audio machine driver for WPT + RT286S */ 254/* broadwell audio machine driver for WPT + RT286S */
231static struct snd_soc_card broadwell_rt286 = { 255static struct snd_soc_card broadwell_rt286 = {
232 .name = "broadwell-rt286", 256 .name = "broadwell-rt286",
@@ -240,6 +264,8 @@ static struct snd_soc_card broadwell_rt286 = {
240 .dapm_routes = broadwell_rt286_map, 264 .dapm_routes = broadwell_rt286_map,
241 .num_dapm_routes = ARRAY_SIZE(broadwell_rt286_map), 265 .num_dapm_routes = ARRAY_SIZE(broadwell_rt286_map),
242 .fully_routed = true, 266 .fully_routed = true,
267 .suspend_pre = broadwell_suspend,
268 .resume_post = broadwell_resume,
243}; 269};
244 270
245static int broadwell_audio_probe(struct platform_device *pdev) 271static int broadwell_audio_probe(struct platform_device *pdev)
diff --git a/sound/soc/intel/bytcr_dpcm_rt5640.c b/sound/soc/intel/bytcr_dpcm_rt5640.c
index 59308629043e..3b262d01c1b3 100644
--- a/sound/soc/intel/bytcr_dpcm_rt5640.c
+++ b/sound/soc/intel/bytcr_dpcm_rt5640.c
@@ -113,9 +113,7 @@ static int byt_codec_fixup(struct snd_soc_pcm_runtime *rtd,
113 channels->min = channels->max = 2; 113 channels->min = channels->max = 2;
114 114
115 /* set SSP2 to 24-bit */ 115 /* set SSP2 to 24-bit */
116 snd_mask_set(&params->masks[SNDRV_PCM_HW_PARAM_FORMAT - 116 params_set_format(params, SNDRV_PCM_FORMAT_S24_LE);
117 SNDRV_PCM_HW_PARAM_FIRST_MASK],
118 SNDRV_PCM_FORMAT_S24_LE);
119 return 0; 117 return 0;
120} 118}
121 119
diff --git a/sound/soc/intel/cht_bsw_rt5645.c b/sound/soc/intel/cht_bsw_rt5645.c
index bd29617a9ab9..dd935255a020 100644
--- a/sound/soc/intel/cht_bsw_rt5645.c
+++ b/sound/soc/intel/cht_bsw_rt5645.c
@@ -203,9 +203,7 @@ static int cht_codec_fixup(struct snd_soc_pcm_runtime *rtd,
203 channels->min = channels->max = 2; 203 channels->min = channels->max = 2;
204 204
205 /* set SSP2 to 24-bit */ 205 /* set SSP2 to 24-bit */
206 snd_mask_set(&params->masks[SNDRV_PCM_HW_PARAM_FORMAT - 206 params_set_format(params, SNDRV_PCM_FORMAT_S24_LE);
207 SNDRV_PCM_HW_PARAM_FIRST_MASK],
208 SNDRV_PCM_FORMAT_S24_LE);
209 return 0; 207 return 0;
210} 208}
211 209
diff --git a/sound/soc/intel/cht_bsw_rt5672.c b/sound/soc/intel/cht_bsw_rt5672.c
index ff016621583a..279df4c43de1 100644
--- a/sound/soc/intel/cht_bsw_rt5672.c
+++ b/sound/soc/intel/cht_bsw_rt5672.c
@@ -50,6 +50,7 @@ static int platform_clock_control(struct snd_soc_dapm_widget *w,
50 struct snd_soc_dapm_context *dapm = w->dapm; 50 struct snd_soc_dapm_context *dapm = w->dapm;
51 struct snd_soc_card *card = dapm->card; 51 struct snd_soc_card *card = dapm->card;
52 struct snd_soc_dai *codec_dai; 52 struct snd_soc_dai *codec_dai;
53 int ret;
53 54
54 codec_dai = cht_get_codec_dai(card); 55 codec_dai = cht_get_codec_dai(card);
55 if (!codec_dai) { 56 if (!codec_dai) {
@@ -57,17 +58,31 @@ static int platform_clock_control(struct snd_soc_dapm_widget *w,
57 return -EIO; 58 return -EIO;
58 } 59 }
59 60
60 if (!SND_SOC_DAPM_EVENT_OFF(event)) 61 if (SND_SOC_DAPM_EVENT_ON(event)) {
61 return 0; 62 /* set codec PLL source to the 19.2MHz platform clock (MCLK) */
62 63 ret = snd_soc_dai_set_pll(codec_dai, 0, RT5670_PLL1_S_MCLK,
63 /* Set codec sysclk source to its internal clock because codec PLL will 64 CHT_PLAT_CLK_3_HZ, 48000 * 512);
64 * be off when idle and MCLK will also be off by ACPI when codec is 65 if (ret < 0) {
65 * runtime suspended. Codec needs clock for jack detection and button 66 dev_err(card->dev, "can't set codec pll: %d\n", ret);
66 * press. 67 return ret;
67 */ 68 }
68 snd_soc_dai_set_sysclk(codec_dai, RT5670_SCLK_S_RCCLK, 69
69 0, SND_SOC_CLOCK_IN); 70 /* set codec sysclk source to PLL */
70 71 ret = snd_soc_dai_set_sysclk(codec_dai, RT5670_SCLK_S_PLL1,
72 48000 * 512, SND_SOC_CLOCK_IN);
73 if (ret < 0) {
74 dev_err(card->dev, "can't set codec sysclk: %d\n", ret);
75 return ret;
76 }
77 } else {
78 /* Set codec sysclk source to its internal clock because codec
79 * PLL will be off when idle and MCLK will also be off by ACPI
80 * when codec is runtime suspended. Codec needs clock for jack
81 * detection and button press.
82 */
83 snd_soc_dai_set_sysclk(codec_dai, RT5670_SCLK_S_RCCLK,
84 48000 * 512, SND_SOC_CLOCK_IN);
85 }
71 return 0; 86 return 0;
72} 87}
73 88
@@ -77,7 +92,8 @@ static const struct snd_soc_dapm_widget cht_dapm_widgets[] = {
77 SND_SOC_DAPM_MIC("Int Mic", NULL), 92 SND_SOC_DAPM_MIC("Int Mic", NULL),
78 SND_SOC_DAPM_SPK("Ext Spk", NULL), 93 SND_SOC_DAPM_SPK("Ext Spk", NULL),
79 SND_SOC_DAPM_SUPPLY("Platform Clock", SND_SOC_NOPM, 0, 0, 94 SND_SOC_DAPM_SUPPLY("Platform Clock", SND_SOC_NOPM, 0, 0,
80 platform_clock_control, SND_SOC_DAPM_POST_PMD), 95 platform_clock_control, SND_SOC_DAPM_PRE_PMU |
96 SND_SOC_DAPM_POST_PMD),
81}; 97};
82 98
83static const struct snd_soc_dapm_route cht_audio_map[] = { 99static const struct snd_soc_dapm_route cht_audio_map[] = {
@@ -178,9 +194,7 @@ static int cht_codec_fixup(struct snd_soc_pcm_runtime *rtd,
178 channels->min = channels->max = 2; 194 channels->min = channels->max = 2;
179 195
180 /* set SSP2 to 24-bit */ 196 /* set SSP2 to 24-bit */
181 snd_mask_set(&params->masks[SNDRV_PCM_HW_PARAM_FORMAT - 197 params_set_format(params, SNDRV_PCM_FORMAT_S24_LE);
182 SNDRV_PCM_HW_PARAM_FIRST_MASK],
183 SNDRV_PCM_FORMAT_S24_LE);
184 return 0; 198 return 0;
185} 199}
186 200
@@ -217,7 +231,7 @@ static struct snd_soc_dai_link cht_dailink[] = {
217 .codec_dai_name = "snd-soc-dummy-dai", 231 .codec_dai_name = "snd-soc-dummy-dai",
218 .codec_name = "snd-soc-dummy", 232 .codec_name = "snd-soc-dummy",
219 .platform_name = "sst-mfld-platform", 233 .platform_name = "sst-mfld-platform",
220 .ignore_suspend = 1, 234 .nonatomic = true,
221 .dynamic = 1, 235 .dynamic = 1,
222 .dpcm_playback = 1, 236 .dpcm_playback = 1,
223 .dpcm_capture = 1, 237 .dpcm_capture = 1,
@@ -240,13 +254,13 @@ static struct snd_soc_dai_link cht_dailink[] = {
240 .cpu_dai_name = "ssp2-port", 254 .cpu_dai_name = "ssp2-port",
241 .platform_name = "sst-mfld-platform", 255 .platform_name = "sst-mfld-platform",
242 .no_pcm = 1, 256 .no_pcm = 1,
257 .nonatomic = true,
243 .codec_dai_name = "rt5670-aif1", 258 .codec_dai_name = "rt5670-aif1",
244 .codec_name = "i2c-10EC5670:00", 259 .codec_name = "i2c-10EC5670:00",
245 .dai_fmt = SND_SOC_DAIFMT_DSP_B | SND_SOC_DAIFMT_IB_NF 260 .dai_fmt = SND_SOC_DAIFMT_DSP_B | SND_SOC_DAIFMT_IB_NF
246 | SND_SOC_DAIFMT_CBS_CFS, 261 | SND_SOC_DAIFMT_CBS_CFS,
247 .init = cht_codec_init, 262 .init = cht_codec_init,
248 .be_hw_params_fixup = cht_codec_fixup, 263 .be_hw_params_fixup = cht_codec_fixup,
249 .ignore_suspend = 1,
250 .dpcm_playback = 1, 264 .dpcm_playback = 1,
251 .dpcm_capture = 1, 265 .dpcm_capture = 1,
252 .ops = &cht_be_ssp2_ops, 266 .ops = &cht_be_ssp2_ops,
@@ -285,7 +299,6 @@ static int snd_cht_mc_probe(struct platform_device *pdev)
285static struct platform_driver snd_cht_mc_driver = { 299static struct platform_driver snd_cht_mc_driver = {
286 .driver = { 300 .driver = {
287 .name = "cht-bsw-rt5672", 301 .name = "cht-bsw-rt5672",
288 .pm = &snd_soc_pm_ops,
289 }, 302 },
290 .probe = snd_cht_mc_probe, 303 .probe = snd_cht_mc_probe,
291}; 304};
diff --git a/sound/soc/intel/haswell.c b/sound/soc/intel/haswell.c
index 35edf51a52aa..00fddd3f5dfb 100644
--- a/sound/soc/intel/haswell.c
+++ b/sound/soc/intel/haswell.c
@@ -56,9 +56,7 @@ static int haswell_ssp0_fixup(struct snd_soc_pcm_runtime *rtd,
56 channels->min = channels->max = 2; 56 channels->min = channels->max = 2;
57 57
58 /* set SSP0 to 16 bit */ 58 /* set SSP0 to 16 bit */
59 snd_mask_set(&params->masks[SNDRV_PCM_HW_PARAM_FORMAT - 59 params_set_format(params, SNDRV_PCM_FORMAT_S16_LE);
60 SNDRV_PCM_HW_PARAM_FIRST_MASK],
61 SNDRV_PCM_FORMAT_S16_LE);
62 return 0; 60 return 0;
63} 61}
64 62
diff --git a/sound/soc/intel/sst-dsp-priv.h b/sound/soc/intel/sst-dsp-priv.h
index b9da030e312d..396d54510350 100644
--- a/sound/soc/intel/sst-dsp-priv.h
+++ b/sound/soc/intel/sst-dsp-priv.h
@@ -173,6 +173,16 @@ struct sst_module_runtime_context {
173}; 173};
174 174
175/* 175/*
176 * Audio DSP Module State
177 */
178enum sst_module_state {
179 SST_MODULE_STATE_UNLOADED = 0, /* default state */
180 SST_MODULE_STATE_LOADED,
181 SST_MODULE_STATE_INITIALIZED, /* and inactive */
182 SST_MODULE_STATE_ACTIVE,
183};
184
185/*
176 * Audio DSP Generic Module. 186 * Audio DSP Generic Module.
177 * 187 *
178 * Each Firmware file can consist of 1..N modules. A module can span multiple 188 * Each Firmware file can consist of 1..N modules. A module can span multiple
@@ -203,6 +213,9 @@ struct sst_module {
203 struct list_head list; /* DSP list of modules */ 213 struct list_head list; /* DSP list of modules */
204 struct list_head list_fw; /* FW list of modules */ 214 struct list_head list_fw; /* FW list of modules */
205 struct list_head runtime_list; /* list of runtime module objects*/ 215 struct list_head runtime_list; /* list of runtime module objects*/
216
217 /* state */
218 enum sst_module_state state;
206}; 219};
207 220
208/* 221/*
diff --git a/sound/soc/intel/sst-firmware.c b/sound/soc/intel/sst-firmware.c
index 5f71ef607a57..5e5800897da2 100644
--- a/sound/soc/intel/sst-firmware.c
+++ b/sound/soc/intel/sst-firmware.c
@@ -498,6 +498,7 @@ struct sst_module *sst_module_new(struct sst_fw *sst_fw,
498 sst_module->scratch_size = template->scratch_size; 498 sst_module->scratch_size = template->scratch_size;
499 sst_module->persistent_size = template->persistent_size; 499 sst_module->persistent_size = template->persistent_size;
500 sst_module->entry = template->entry; 500 sst_module->entry = template->entry;
501 sst_module->state = SST_MODULE_STATE_UNLOADED;
501 502
502 INIT_LIST_HEAD(&sst_module->block_list); 503 INIT_LIST_HEAD(&sst_module->block_list);
503 INIT_LIST_HEAD(&sst_module->runtime_list); 504 INIT_LIST_HEAD(&sst_module->runtime_list);
diff --git a/sound/soc/intel/sst-haswell-dsp.c b/sound/soc/intel/sst-haswell-dsp.c
index c42ffae5fe9f..b3e957d46933 100644
--- a/sound/soc/intel/sst-haswell-dsp.c
+++ b/sound/soc/intel/sst-haswell-dsp.c
@@ -100,6 +100,7 @@ static int hsw_parse_module(struct sst_dsp *dsp, struct sst_fw *fw,
100 && module->type != SST_HSW_MODULE_PCM 100 && module->type != SST_HSW_MODULE_PCM
101 && module->type != SST_HSW_MODULE_PCM_REFERENCE 101 && module->type != SST_HSW_MODULE_PCM_REFERENCE
102 && module->type != SST_HSW_MODULE_PCM_CAPTURE 102 && module->type != SST_HSW_MODULE_PCM_CAPTURE
103 && module->type != SST_HSW_MODULE_WAVES
103 && module->type != SST_HSW_MODULE_LPAL) 104 && module->type != SST_HSW_MODULE_LPAL)
104 return 0; 105 return 0;
105 106
@@ -139,6 +140,7 @@ static int hsw_parse_module(struct sst_dsp *dsp, struct sst_fw *fw,
139 mod->type = SST_MEM_IRAM; 140 mod->type = SST_MEM_IRAM;
140 break; 141 break;
141 case SST_HSW_DRAM: 142 case SST_HSW_DRAM:
143 case SST_HSW_REGS:
142 ram = dsp->addr.lpe; 144 ram = dsp->addr.lpe;
143 mod->offset = block->ram_offset; 145 mod->offset = block->ram_offset;
144 mod->type = SST_MEM_DRAM; 146 mod->type = SST_MEM_DRAM;
@@ -169,6 +171,7 @@ static int hsw_parse_module(struct sst_dsp *dsp, struct sst_fw *fw,
169 171
170 block = (void *)block + sizeof(*block) + block->size; 172 block = (void *)block + sizeof(*block) + block->size;
171 } 173 }
174 mod->state = SST_MODULE_STATE_LOADED;
172 175
173 return 0; 176 return 0;
174} 177}
@@ -207,9 +210,6 @@ static int hsw_parse_fw_image(struct sst_fw *sst_fw)
207 module = (void *)module + sizeof(*module) + module->mod_size; 210 module = (void *)module + sizeof(*module) + module->mod_size;
208 } 211 }
209 212
210 /* allocate scratch mem regions */
211 sst_block_alloc_scratch(dsp);
212
213 return 0; 213 return 0;
214} 214}
215 215
diff --git a/sound/soc/intel/sst-haswell-ipc.c b/sound/soc/intel/sst-haswell-ipc.c
index 394af5684c05..43fb5f339168 100644
--- a/sound/soc/intel/sst-haswell-ipc.c
+++ b/sound/soc/intel/sst-haswell-ipc.c
@@ -79,6 +79,15 @@
79#define IPC_LOG_ID_MASK (0xf << IPC_LOG_ID_SHIFT) 79#define IPC_LOG_ID_MASK (0xf << IPC_LOG_ID_SHIFT)
80#define IPC_LOG_ID(x) (x << IPC_LOG_ID_SHIFT) 80#define IPC_LOG_ID(x) (x << IPC_LOG_ID_SHIFT)
81 81
82/* Module Message */
83#define IPC_MODULE_OPERATION_SHIFT 20
84#define IPC_MODULE_OPERATION_MASK (0xf << IPC_MODULE_OPERATION_SHIFT)
85#define IPC_MODULE_OPERATION(x) (x << IPC_MODULE_OPERATION_SHIFT)
86
87#define IPC_MODULE_ID_SHIFT 16
88#define IPC_MODULE_ID_MASK (0xf << IPC_MODULE_ID_SHIFT)
89#define IPC_MODULE_ID(x) (x << IPC_MODULE_ID_SHIFT)
90
82/* IPC message timeout (msecs) */ 91/* IPC message timeout (msecs) */
83#define IPC_TIMEOUT_MSECS 300 92#define IPC_TIMEOUT_MSECS 300
84#define IPC_BOOT_MSECS 200 93#define IPC_BOOT_MSECS 200
@@ -115,6 +124,7 @@ enum ipc_glb_type {
115 IPC_GLB_ENTER_DX_STATE = 12, 124 IPC_GLB_ENTER_DX_STATE = 12,
116 IPC_GLB_GET_MIXER_STREAM_INFO = 13, /* Request mixer stream params */ 125 IPC_GLB_GET_MIXER_STREAM_INFO = 13, /* Request mixer stream params */
117 IPC_GLB_DEBUG_LOG_MESSAGE = 14, /* Message to or from the debug logger. */ 126 IPC_GLB_DEBUG_LOG_MESSAGE = 14, /* Message to or from the debug logger. */
127 IPC_GLB_MODULE_OPERATION = 15, /* Message to loadable fw module */
118 IPC_GLB_REQUEST_TRANSFER = 16, /* < Request Transfer for host */ 128 IPC_GLB_REQUEST_TRANSFER = 16, /* < Request Transfer for host */
119 IPC_GLB_MAX_IPC_MESSAGE_TYPE = 17, /* Maximum message number */ 129 IPC_GLB_MAX_IPC_MESSAGE_TYPE = 17, /* Maximum message number */
120}; 130};
@@ -133,6 +143,16 @@ enum ipc_glb_reply {
133 IPC_GLB_REPLY_SOURCE_NOT_STARTED = 10, /* Source was not started. */ 143 IPC_GLB_REPLY_SOURCE_NOT_STARTED = 10, /* Source was not started. */
134}; 144};
135 145
146enum ipc_module_operation {
147 IPC_MODULE_NOTIFICATION = 0,
148 IPC_MODULE_ENABLE = 1,
149 IPC_MODULE_DISABLE = 2,
150 IPC_MODULE_GET_PARAMETER = 3,
151 IPC_MODULE_SET_PARAMETER = 4,
152 IPC_MODULE_GET_INFO = 5,
153 IPC_MODULE_MAX_MESSAGE
154};
155
136/* Stream Message - Types */ 156/* Stream Message - Types */
137enum ipc_str_operation { 157enum ipc_str_operation {
138 IPC_STR_RESET = 0, 158 IPC_STR_RESET = 0,
@@ -317,6 +337,15 @@ struct sst_hsw {
317 337
318 /* FW log stream */ 338 /* FW log stream */
319 struct sst_hsw_log_stream log_stream; 339 struct sst_hsw_log_stream log_stream;
340
341 /* flags bit field to track module state when resume from RTD3,
342 * each bit represent state (enabled/disabled) of single module */
343 u32 enabled_modules_rtd3;
344
345 /* buffer to store parameter lines */
346 u32 param_idx_w; /* write index */
347 u32 param_idx_r; /* read index */
348 u8 param_buf[WAVES_PARAM_LINES][WAVES_PARAM_COUNT];
320}; 349};
321 350
322#define CREATE_TRACE_POINTS 351#define CREATE_TRACE_POINTS
@@ -352,6 +381,16 @@ static inline u32 msg_get_notify_reason(u32 msg)
352 return (msg & IPC_STG_TYPE_MASK) >> IPC_STG_TYPE_SHIFT; 381 return (msg & IPC_STG_TYPE_MASK) >> IPC_STG_TYPE_SHIFT;
353} 382}
354 383
384static inline u32 msg_get_module_operation(u32 msg)
385{
386 return (msg & IPC_MODULE_OPERATION_MASK) >> IPC_MODULE_OPERATION_SHIFT;
387}
388
389static inline u32 msg_get_module_id(u32 msg)
390{
391 return (msg & IPC_MODULE_ID_MASK) >> IPC_MODULE_ID_SHIFT;
392}
393
355u32 create_channel_map(enum sst_hsw_channel_config config) 394u32 create_channel_map(enum sst_hsw_channel_config config)
356{ 395{
357 switch (config) { 396 switch (config) {
@@ -795,6 +834,31 @@ static int hsw_process_reply(struct sst_hsw *hsw, u32 header)
795 return 1; 834 return 1;
796} 835}
797 836
837static int hsw_module_message(struct sst_hsw *hsw, u32 header)
838{
839 u32 operation, module_id;
840 int handled = 0;
841
842 operation = msg_get_module_operation(header);
843 module_id = msg_get_module_id(header);
844 dev_dbg(hsw->dev, "received module message header: 0x%8.8x\n",
845 header);
846 dev_dbg(hsw->dev, "operation: 0x%8.8x module_id: 0x%8.8x\n",
847 operation, module_id);
848
849 switch (operation) {
850 case IPC_MODULE_NOTIFICATION:
851 dev_dbg(hsw->dev, "module notification received");
852 handled = 1;
853 break;
854 default:
855 handled = hsw_process_reply(hsw, header);
856 break;
857 }
858
859 return handled;
860}
861
798static int hsw_stream_message(struct sst_hsw *hsw, u32 header) 862static int hsw_stream_message(struct sst_hsw *hsw, u32 header)
799{ 863{
800 u32 stream_msg, stream_id, stage_type; 864 u32 stream_msg, stream_id, stage_type;
@@ -890,6 +954,9 @@ static int hsw_process_notification(struct sst_hsw *hsw)
890 case IPC_GLB_DEBUG_LOG_MESSAGE: 954 case IPC_GLB_DEBUG_LOG_MESSAGE:
891 handled = hsw_log_message(hsw, header); 955 handled = hsw_log_message(hsw, header);
892 break; 956 break;
957 case IPC_GLB_MODULE_OPERATION:
958 handled = hsw_module_message(hsw, header);
959 break;
893 default: 960 default:
894 dev_err(hsw->dev, "error: unexpected type %d hdr 0x%8.8x\n", 961 dev_err(hsw->dev, "error: unexpected type %d hdr 0x%8.8x\n",
895 type, header); 962 type, header);
@@ -1732,6 +1799,7 @@ static void sst_hsw_drop_all(struct sst_hsw *hsw)
1732int sst_hsw_dsp_load(struct sst_hsw *hsw) 1799int sst_hsw_dsp_load(struct sst_hsw *hsw)
1733{ 1800{
1734 struct sst_dsp *dsp = hsw->dsp; 1801 struct sst_dsp *dsp = hsw->dsp;
1802 struct sst_fw *sst_fw, *t;
1735 int ret; 1803 int ret;
1736 1804
1737 dev_dbg(hsw->dev, "loading audio DSP...."); 1805 dev_dbg(hsw->dev, "loading audio DSP....");
@@ -1748,12 +1816,17 @@ int sst_hsw_dsp_load(struct sst_hsw *hsw)
1748 return ret; 1816 return ret;
1749 } 1817 }
1750 1818
1751 ret = sst_fw_reload(hsw->sst_fw); 1819 list_for_each_entry_safe_reverse(sst_fw, t, &dsp->fw_list, list) {
1752 if (ret < 0) { 1820 ret = sst_fw_reload(sst_fw);
1753 dev_err(hsw->dev, "error: SST FW reload failed\n"); 1821 if (ret < 0) {
1754 sst_dsp_dma_put_channel(dsp); 1822 dev_err(hsw->dev, "error: SST FW reload failed\n");
1755 return -ENOMEM; 1823 sst_dsp_dma_put_channel(dsp);
1824 return -ENOMEM;
1825 }
1756 } 1826 }
1827 ret = sst_block_alloc_scratch(hsw->dsp);
1828 if (ret < 0)
1829 return -EINVAL;
1757 1830
1758 sst_dsp_dma_put_channel(dsp); 1831 sst_dsp_dma_put_channel(dsp);
1759 return 0; 1832 return 0;
@@ -1809,12 +1882,17 @@ int sst_hsw_dsp_runtime_suspend(struct sst_hsw *hsw)
1809 1882
1810int sst_hsw_dsp_runtime_sleep(struct sst_hsw *hsw) 1883int sst_hsw_dsp_runtime_sleep(struct sst_hsw *hsw)
1811{ 1884{
1812 sst_fw_unload(hsw->sst_fw); 1885 struct sst_fw *sst_fw, *t;
1813 sst_block_free_scratch(hsw->dsp); 1886 struct sst_dsp *dsp = hsw->dsp;
1887
1888 list_for_each_entry_safe(sst_fw, t, &dsp->fw_list, list) {
1889 sst_fw_unload(sst_fw);
1890 }
1891 sst_block_free_scratch(dsp);
1814 1892
1815 hsw->boot_complete = false; 1893 hsw->boot_complete = false;
1816 1894
1817 sst_dsp_sleep(hsw->dsp); 1895 sst_dsp_sleep(dsp);
1818 1896
1819 return 0; 1897 return 0;
1820} 1898}
@@ -1833,6 +1911,8 @@ int sst_hsw_dsp_runtime_resume(struct sst_hsw *hsw)
1833 if (ret < 0) 1911 if (ret < 0)
1834 dev_err(dev, "error: audio DSP boot failure\n"); 1912 dev_err(dev, "error: audio DSP boot failure\n");
1835 1913
1914 sst_hsw_init_module_state(hsw);
1915
1836 ret = wait_event_timeout(hsw->boot_wait, hsw->boot_complete, 1916 ret = wait_event_timeout(hsw->boot_wait, hsw->boot_complete,
1837 msecs_to_jiffies(IPC_BOOT_MSECS)); 1917 msecs_to_jiffies(IPC_BOOT_MSECS));
1838 if (ret == 0) { 1918 if (ret == 0) {
@@ -1875,6 +1955,337 @@ struct sst_dsp *sst_hsw_get_dsp(struct sst_hsw *hsw)
1875 return hsw->dsp; 1955 return hsw->dsp;
1876} 1956}
1877 1957
1958void sst_hsw_init_module_state(struct sst_hsw *hsw)
1959{
1960 struct sst_module *module;
1961 enum sst_hsw_module_id id;
1962
1963 /* the base fw contains several modules */
1964 for (id = SST_HSW_MODULE_BASE_FW; id < SST_HSW_MAX_MODULE_ID; id++) {
1965 module = sst_module_get_from_id(hsw->dsp, id);
1966 if (module) {
1967 /* module waves is active only after being enabled */
1968 if (id == SST_HSW_MODULE_WAVES)
1969 module->state = SST_MODULE_STATE_INITIALIZED;
1970 else
1971 module->state = SST_MODULE_STATE_ACTIVE;
1972 }
1973 }
1974}
1975
1976bool sst_hsw_is_module_loaded(struct sst_hsw *hsw, u32 module_id)
1977{
1978 struct sst_module *module;
1979
1980 module = sst_module_get_from_id(hsw->dsp, module_id);
1981 if (module == NULL || module->state == SST_MODULE_STATE_UNLOADED)
1982 return false;
1983 else
1984 return true;
1985}
1986
1987bool sst_hsw_is_module_active(struct sst_hsw *hsw, u32 module_id)
1988{
1989 struct sst_module *module;
1990
1991 module = sst_module_get_from_id(hsw->dsp, module_id);
1992 if (module != NULL && module->state == SST_MODULE_STATE_ACTIVE)
1993 return true;
1994 else
1995 return false;
1996}
1997
1998void sst_hsw_set_module_enabled_rtd3(struct sst_hsw *hsw, u32 module_id)
1999{
2000 hsw->enabled_modules_rtd3 |= (1 << module_id);
2001}
2002
2003void sst_hsw_set_module_disabled_rtd3(struct sst_hsw *hsw, u32 module_id)
2004{
2005 hsw->enabled_modules_rtd3 &= ~(1 << module_id);
2006}
2007
2008bool sst_hsw_is_module_enabled_rtd3(struct sst_hsw *hsw, u32 module_id)
2009{
2010 return hsw->enabled_modules_rtd3 & (1 << module_id);
2011}
2012
2013void sst_hsw_reset_param_buf(struct sst_hsw *hsw)
2014{
2015 hsw->param_idx_w = 0;
2016 hsw->param_idx_r = 0;
2017 memset((void *)hsw->param_buf, 0, sizeof(hsw->param_buf));
2018}
2019
2020int sst_hsw_store_param_line(struct sst_hsw *hsw, u8 *buf)
2021{
2022 /* save line to the first available position of param buffer */
2023 if (hsw->param_idx_w > WAVES_PARAM_LINES - 1) {
2024 dev_warn(hsw->dev, "warning: param buffer overflow!\n");
2025 return -EPERM;
2026 }
2027 memcpy(hsw->param_buf[hsw->param_idx_w], buf, WAVES_PARAM_COUNT);
2028 hsw->param_idx_w++;
2029 return 0;
2030}
2031
2032int sst_hsw_load_param_line(struct sst_hsw *hsw, u8 *buf)
2033{
2034 u8 id = 0;
2035
2036 /* read the first matching line from param buffer */
2037 while (hsw->param_idx_r < WAVES_PARAM_LINES) {
2038 id = hsw->param_buf[hsw->param_idx_r][0];
2039 hsw->param_idx_r++;
2040 if (buf[0] == id) {
2041 memcpy(buf, hsw->param_buf[hsw->param_idx_r],
2042 WAVES_PARAM_COUNT);
2043 break;
2044 }
2045 }
2046 if (hsw->param_idx_r > WAVES_PARAM_LINES - 1) {
2047 dev_dbg(hsw->dev, "end of buffer, roll to the beginning\n");
2048 hsw->param_idx_r = 0;
2049 return 0;
2050 }
2051 return 0;
2052}
2053
2054int sst_hsw_launch_param_buf(struct sst_hsw *hsw)
2055{
2056 int ret, idx;
2057
2058 /* put all param lines to DSP through ipc */
2059 for (idx = 0; idx < hsw->param_idx_w; idx++) {
2060 ret = sst_hsw_module_set_param(hsw,
2061 SST_HSW_MODULE_WAVES, 0, hsw->param_buf[idx][0],
2062 WAVES_PARAM_COUNT, hsw->param_buf[idx]);
2063 if (ret < 0)
2064 return ret;
2065 }
2066 return 0;
2067}
2068
2069int sst_hsw_module_load(struct sst_hsw *hsw,
2070 u32 module_id, u32 instance_id, char *name)
2071{
2072 int ret = 0;
2073 const struct firmware *fw = NULL;
2074 struct sst_fw *hsw_sst_fw;
2075 struct sst_module *module;
2076 struct device *dev = hsw->dev;
2077 struct sst_dsp *dsp = hsw->dsp;
2078
2079 dev_dbg(dev, "sst_hsw_module_load id=%d, name='%s'", module_id, name);
2080
2081 module = sst_module_get_from_id(dsp, module_id);
2082 if (module == NULL) {
2083 /* loading for the first time */
2084 if (module_id == SST_HSW_MODULE_BASE_FW) {
2085 /* for base module: use fw requested in acpi probe */
2086 fw = dsp->pdata->fw;
2087 if (!fw) {
2088 dev_err(dev, "request Base fw failed\n");
2089 return -ENODEV;
2090 }
2091 } else {
2092 /* try and load any other optional modules if they are
2093 * available. Use dev_info instead of dev_err in case
2094 * request firmware failed */
2095 ret = request_firmware(&fw, name, dev);
2096 if (ret) {
2097 dev_info(dev, "fw image %s not available(%d)\n",
2098 name, ret);
2099 return ret;
2100 }
2101 }
2102 hsw_sst_fw = sst_fw_new(dsp, fw, hsw);
2103 if (hsw_sst_fw == NULL) {
2104 dev_err(dev, "error: failed to load firmware\n");
2105 ret = -ENOMEM;
2106 goto out;
2107 }
2108 module = sst_module_get_from_id(dsp, module_id);
2109 if (module == NULL) {
2110 dev_err(dev, "error: no module %d in firmware %s\n",
2111 module_id, name);
2112 }
2113 } else
2114 dev_info(dev, "module %d (%s) already loaded\n",
2115 module_id, name);
2116out:
2117 /* release fw, but base fw should be released by acpi driver */
2118 if (fw && module_id != SST_HSW_MODULE_BASE_FW)
2119 release_firmware(fw);
2120
2121 return ret;
2122}
2123
2124int sst_hsw_module_enable(struct sst_hsw *hsw,
2125 u32 module_id, u32 instance_id)
2126{
2127 int ret;
2128 u32 header = 0;
2129 struct sst_hsw_ipc_module_config config;
2130 struct sst_module *module;
2131 struct sst_module_runtime *runtime;
2132 struct device *dev = hsw->dev;
2133 struct sst_dsp *dsp = hsw->dsp;
2134
2135 if (!sst_hsw_is_module_loaded(hsw, module_id)) {
2136 dev_dbg(dev, "module %d not loaded\n", module_id);
2137 return 0;
2138 }
2139
2140 if (sst_hsw_is_module_active(hsw, module_id)) {
2141 dev_info(dev, "module %d already enabled\n", module_id);
2142 return 0;
2143 }
2144
2145 module = sst_module_get_from_id(dsp, module_id);
2146 if (module == NULL) {
2147 dev_err(dev, "module %d not valid\n", module_id);
2148 return -ENXIO;
2149 }
2150
2151 runtime = sst_module_runtime_get_from_id(module, module_id);
2152 if (runtime == NULL) {
2153 dev_err(dev, "runtime %d not valid", module_id);
2154 return -ENXIO;
2155 }
2156
2157 header = IPC_GLB_TYPE(IPC_GLB_MODULE_OPERATION) |
2158 IPC_MODULE_OPERATION(IPC_MODULE_ENABLE) |
2159 IPC_MODULE_ID(module_id);
2160 dev_dbg(dev, "module enable header: %x\n", header);
2161
2162 config.map.module_entries_count = 1;
2163 config.map.module_entries[0].module_id = module->id;
2164 config.map.module_entries[0].entry_point = module->entry;
2165
2166 config.persistent_mem.offset =
2167 sst_dsp_get_offset(dsp,
2168 runtime->persistent_offset, SST_MEM_DRAM);
2169 config.persistent_mem.size = module->persistent_size;
2170
2171 config.scratch_mem.offset =
2172 sst_dsp_get_offset(dsp,
2173 dsp->scratch_offset, SST_MEM_DRAM);
2174 config.scratch_mem.size = module->scratch_size;
2175 dev_dbg(dev, "mod %d enable p:%d @ %x, s:%d @ %x, ep: %x",
2176 config.map.module_entries[0].module_id,
2177 config.persistent_mem.size,
2178 config.persistent_mem.offset,
2179 config.scratch_mem.size, config.scratch_mem.offset,
2180 config.map.module_entries[0].entry_point);
2181
2182 ret = ipc_tx_message_wait(hsw, header,
2183 &config, sizeof(config), NULL, 0);
2184 if (ret < 0)
2185 dev_err(dev, "ipc: module enable failed - %d\n", ret);
2186 else
2187 module->state = SST_MODULE_STATE_ACTIVE;
2188
2189 return ret;
2190}
2191
2192int sst_hsw_module_disable(struct sst_hsw *hsw,
2193 u32 module_id, u32 instance_id)
2194{
2195 int ret;
2196 u32 header;
2197 struct sst_module *module;
2198 struct device *dev = hsw->dev;
2199 struct sst_dsp *dsp = hsw->dsp;
2200
2201 if (!sst_hsw_is_module_loaded(hsw, module_id)) {
2202 dev_dbg(dev, "module %d not loaded\n", module_id);
2203 return 0;
2204 }
2205
2206 if (!sst_hsw_is_module_active(hsw, module_id)) {
2207 dev_info(dev, "module %d already disabled\n", module_id);
2208 return 0;
2209 }
2210
2211 module = sst_module_get_from_id(dsp, module_id);
2212 if (module == NULL) {
2213 dev_err(dev, "module %d not valid\n", module_id);
2214 return -ENXIO;
2215 }
2216
2217 header = IPC_GLB_TYPE(IPC_GLB_MODULE_OPERATION) |
2218 IPC_MODULE_OPERATION(IPC_MODULE_DISABLE) |
2219 IPC_MODULE_ID(module_id);
2220
2221 ret = ipc_tx_message_wait(hsw, header, NULL, 0, NULL, 0);
2222 if (ret < 0)
2223 dev_err(dev, "module disable failed - %d\n", ret);
2224 else
2225 module->state = SST_MODULE_STATE_INITIALIZED;
2226
2227 return ret;
2228}
2229
2230int sst_hsw_module_set_param(struct sst_hsw *hsw,
2231 u32 module_id, u32 instance_id, u32 parameter_id,
2232 u32 param_size, char *param)
2233{
2234 int ret;
2235 unsigned char *data = NULL;
2236 u32 header = 0;
2237 u32 payload_size = 0, transfer_parameter_size = 0;
2238 dma_addr_t dma_addr = 0;
2239 struct sst_hsw_transfer_parameter *parameter;
2240 struct device *dev = hsw->dev;
2241
2242 header = IPC_GLB_TYPE(IPC_GLB_MODULE_OPERATION) |
2243 IPC_MODULE_OPERATION(IPC_MODULE_SET_PARAMETER) |
2244 IPC_MODULE_ID(module_id);
2245 dev_dbg(dev, "sst_hsw_module_set_param header=%x\n", header);
2246
2247 payload_size = param_size +
2248 sizeof(struct sst_hsw_transfer_parameter) -
2249 sizeof(struct sst_hsw_transfer_list);
2250 dev_dbg(dev, "parameter size : %d\n", param_size);
2251 dev_dbg(dev, "payload size : %d\n", payload_size);
2252
2253 if (payload_size <= SST_HSW_IPC_MAX_SHORT_PARAMETER_SIZE) {
2254 /* short parameter, mailbox can contain data */
2255 dev_dbg(dev, "transfer parameter size : %d\n",
2256 transfer_parameter_size);
2257
2258 transfer_parameter_size = ALIGN(payload_size, 4);
2259 dev_dbg(dev, "transfer parameter aligned size : %d\n",
2260 transfer_parameter_size);
2261
2262 parameter = kzalloc(transfer_parameter_size, GFP_KERNEL);
2263 if (parameter == NULL)
2264 return -ENOMEM;
2265
2266 memcpy(parameter->data, param, param_size);
2267 } else {
2268 dev_warn(dev, "transfer parameter size too large!");
2269 return 0;
2270 }
2271
2272 parameter->parameter_id = parameter_id;
2273 parameter->data_size = param_size;
2274
2275 ret = ipc_tx_message_wait(hsw, header,
2276 parameter, transfer_parameter_size , NULL, 0);
2277 if (ret < 0)
2278 dev_err(dev, "ipc: module set parameter failed - %d\n", ret);
2279
2280 kfree(parameter);
2281
2282 if (data)
2283 dma_free_coherent(hsw->dsp->dma_dev,
2284 param_size, (void *)data, dma_addr);
2285
2286 return ret;
2287}
2288
1878static struct sst_dsp_device hsw_dev = { 2289static struct sst_dsp_device hsw_dev = {
1879 .thread = hsw_irq_thread, 2290 .thread = hsw_irq_thread,
1880 .ops = &haswell_ops, 2291 .ops = &haswell_ops,
@@ -1936,12 +2347,21 @@ int sst_hsw_dsp_init(struct device *dev, struct sst_pdata *pdata)
1936 /* keep the DSP in reset state for base FW loading */ 2347 /* keep the DSP in reset state for base FW loading */
1937 sst_dsp_reset(hsw->dsp); 2348 sst_dsp_reset(hsw->dsp);
1938 2349
1939 hsw->sst_fw = sst_fw_new(hsw->dsp, pdata->fw, hsw); 2350 /* load base module and other modules in base firmware image */
1940 if (hsw->sst_fw == NULL) { 2351 ret = sst_hsw_module_load(hsw, SST_HSW_MODULE_BASE_FW, 0, "Base");
1941 ret = -ENODEV; 2352 if (ret < 0)
1942 dev_err(dev, "error: failed to load firmware\n");
1943 goto fw_err; 2353 goto fw_err;
1944 } 2354
2355 /* try to load module waves */
2356 sst_hsw_module_load(hsw, SST_HSW_MODULE_WAVES, 0, "intel/IntcPP01.bin");
2357
2358 /* allocate scratch mem regions */
2359 ret = sst_block_alloc_scratch(hsw->dsp);
2360 if (ret < 0)
2361 goto boot_err;
2362
2363 /* init param buffer */
2364 sst_hsw_reset_param_buf(hsw);
1945 2365
1946 /* wait for DSP boot completion */ 2366 /* wait for DSP boot completion */
1947 sst_dsp_boot(hsw->dsp); 2367 sst_dsp_boot(hsw->dsp);
@@ -1955,6 +2375,9 @@ int sst_hsw_dsp_init(struct device *dev, struct sst_pdata *pdata)
1955 goto boot_err; 2375 goto boot_err;
1956 } 2376 }
1957 2377
2378 /* init module state after boot */
2379 sst_hsw_init_module_state(hsw);
2380
1958 /* get the FW version */ 2381 /* get the FW version */
1959 sst_hsw_fw_get_version(hsw, &version); 2382 sst_hsw_fw_get_version(hsw, &version);
1960 2383
@@ -1970,7 +2393,7 @@ int sst_hsw_dsp_init(struct device *dev, struct sst_pdata *pdata)
1970 2393
1971boot_err: 2394boot_err:
1972 sst_dsp_reset(hsw->dsp); 2395 sst_dsp_reset(hsw->dsp);
1973 sst_fw_free(hsw->sst_fw); 2396 sst_fw_free_all(hsw->dsp);
1974fw_err: 2397fw_err:
1975 dma_free_coherent(hsw->dsp->dma_dev, SST_HSW_DX_CONTEXT_SIZE, 2398 dma_free_coherent(hsw->dsp->dma_dev, SST_HSW_DX_CONTEXT_SIZE,
1976 hsw->dx_context, hsw->dx_context_paddr); 2399 hsw->dx_context, hsw->dx_context_paddr);
diff --git a/sound/soc/intel/sst-haswell-ipc.h b/sound/soc/intel/sst-haswell-ipc.h
index 858096041cb1..06d71aefa1fe 100644
--- a/sound/soc/intel/sst-haswell-ipc.h
+++ b/sound/soc/intel/sst-haswell-ipc.h
@@ -37,6 +37,9 @@
37#define SST_HSW_IPC_MAX_PAYLOAD_SIZE 400 37#define SST_HSW_IPC_MAX_PAYLOAD_SIZE 400
38#define SST_HSW_MAX_INFO_SIZE 64 38#define SST_HSW_MAX_INFO_SIZE 64
39#define SST_HSW_BUILD_HASH_LENGTH 40 39#define SST_HSW_BUILD_HASH_LENGTH 40
40#define SST_HSW_IPC_MAX_SHORT_PARAMETER_SIZE 500
41#define WAVES_PARAM_COUNT 128
42#define WAVES_PARAM_LINES 160
40 43
41struct sst_hsw; 44struct sst_hsw;
42struct sst_hsw_stream; 45struct sst_hsw_stream;
@@ -187,6 +190,28 @@ enum sst_hsw_performance_action {
187 SST_HSW_PERF_STOP = 1, 190 SST_HSW_PERF_STOP = 1,
188}; 191};
189 192
193struct sst_hsw_transfer_info {
194 uint32_t destination; /* destination address */
195 uint32_t reverse:1; /* if 1 data flows from destination */
196 uint32_t size:31; /* transfer size in bytes.*/
197 uint16_t first_page_offset; /* offset to data in the first page. */
198 uint8_t packed_pages; /* page addresses. Each occupies 20 bits */
199} __attribute__((packed));
200
201struct sst_hsw_transfer_list {
202 uint32_t transfers_count;
203 struct sst_hsw_transfer_info transfers;
204} __attribute__((packed));
205
206struct sst_hsw_transfer_parameter {
207 uint32_t parameter_id;
208 uint32_t data_size;
209 union {
210 uint8_t data[1];
211 struct sst_hsw_transfer_list transfer_list;
212 };
213} __attribute__((packed));
214
190/* SST firmware module info */ 215/* SST firmware module info */
191struct sst_hsw_module_info { 216struct sst_hsw_module_info {
192 u8 name[SST_HSW_MAX_INFO_SIZE]; 217 u8 name[SST_HSW_MAX_INFO_SIZE];
@@ -215,6 +240,12 @@ struct sst_hsw_fx_enable {
215 struct sst_hsw_memory_info persistent_mem; 240 struct sst_hsw_memory_info persistent_mem;
216} __attribute__((packed)); 241} __attribute__((packed));
217 242
243struct sst_hsw_ipc_module_config {
244 struct sst_hsw_module_map map;
245 struct sst_hsw_memory_info persistent_mem;
246 struct sst_hsw_memory_info scratch_mem;
247} __attribute__((packed));
248
218struct sst_hsw_get_fx_param { 249struct sst_hsw_get_fx_param {
219 u32 parameter_id; 250 u32 parameter_id;
220 u32 param_size; 251 u32 param_size;
@@ -467,6 +498,28 @@ int sst_hsw_dsp_init(struct device *dev, struct sst_pdata *pdata);
467void sst_hsw_dsp_free(struct device *dev, struct sst_pdata *pdata); 498void sst_hsw_dsp_free(struct device *dev, struct sst_pdata *pdata);
468struct sst_dsp *sst_hsw_get_dsp(struct sst_hsw *hsw); 499struct sst_dsp *sst_hsw_get_dsp(struct sst_hsw *hsw);
469 500
501/* fw module function */
502void sst_hsw_init_module_state(struct sst_hsw *hsw);
503bool sst_hsw_is_module_loaded(struct sst_hsw *hsw, u32 module_id);
504bool sst_hsw_is_module_active(struct sst_hsw *hsw, u32 module_id);
505void sst_hsw_set_module_enabled_rtd3(struct sst_hsw *hsw, u32 module_id);
506void sst_hsw_set_module_disabled_rtd3(struct sst_hsw *hsw, u32 module_id);
507bool sst_hsw_is_module_enabled_rtd3(struct sst_hsw *hsw, u32 module_id);
508void sst_hsw_reset_param_buf(struct sst_hsw *hsw);
509int sst_hsw_store_param_line(struct sst_hsw *hsw, u8 *buf);
510int sst_hsw_load_param_line(struct sst_hsw *hsw, u8 *buf);
511int sst_hsw_launch_param_buf(struct sst_hsw *hsw);
512
513int sst_hsw_module_load(struct sst_hsw *hsw,
514 u32 module_id, u32 instance_id, char *name);
515int sst_hsw_module_enable(struct sst_hsw *hsw,
516 u32 module_id, u32 instance_id);
517int sst_hsw_module_disable(struct sst_hsw *hsw,
518 u32 module_id, u32 instance_id);
519int sst_hsw_module_set_param(struct sst_hsw *hsw,
520 u32 module_id, u32 instance_id, u32 parameter_id,
521 u32 param_size, char *param);
522
470/* runtime module management */ 523/* runtime module management */
471struct sst_module_runtime *sst_hsw_runtime_module_create(struct sst_hsw *hsw, 524struct sst_module_runtime *sst_hsw_runtime_module_create(struct sst_hsw *hsw,
472 int mod_id, int offset); 525 int mod_id, int offset);
diff --git a/sound/soc/intel/sst-haswell-pcm.c b/sound/soc/intel/sst-haswell-pcm.c
index 7e21e8f85885..b40ec746bc19 100644
--- a/sound/soc/intel/sst-haswell-pcm.c
+++ b/sound/soc/intel/sst-haswell-pcm.c
@@ -318,6 +318,97 @@ static int hsw_volume_get(struct snd_kcontrol *kcontrol,
318 return 0; 318 return 0;
319} 319}
320 320
321static int hsw_waves_switch_get(struct snd_kcontrol *kcontrol,
322 struct snd_ctl_elem_value *ucontrol)
323{
324 struct snd_soc_platform *platform = snd_soc_kcontrol_platform(kcontrol);
325 struct hsw_priv_data *pdata = snd_soc_platform_get_drvdata(platform);
326 struct sst_hsw *hsw = pdata->hsw;
327 enum sst_hsw_module_id id = SST_HSW_MODULE_WAVES;
328
329 ucontrol->value.integer.value[0] =
330 (sst_hsw_is_module_active(hsw, id) ||
331 sst_hsw_is_module_enabled_rtd3(hsw, id));
332 return 0;
333}
334
335static int hsw_waves_switch_put(struct snd_kcontrol *kcontrol,
336 struct snd_ctl_elem_value *ucontrol)
337{
338 struct snd_soc_platform *platform = snd_soc_kcontrol_platform(kcontrol);
339 struct hsw_priv_data *pdata = snd_soc_platform_get_drvdata(platform);
340 struct sst_hsw *hsw = pdata->hsw;
341 int ret = 0;
342 enum sst_hsw_module_id id = SST_HSW_MODULE_WAVES;
343 bool switch_on = (bool)ucontrol->value.integer.value[0];
344
345 /* if module is in RAM on the DSP, apply user settings to module through
346 * ipc. If module is not in RAM on the DSP, store user setting for
347 * track */
348 if (sst_hsw_is_module_loaded(hsw, id)) {
349 if (switch_on == sst_hsw_is_module_active(hsw, id))
350 return 0;
351
352 if (switch_on)
353 ret = sst_hsw_module_enable(hsw, id, 0);
354 else
355 ret = sst_hsw_module_disable(hsw, id, 0);
356 } else {
357 if (switch_on == sst_hsw_is_module_enabled_rtd3(hsw, id))
358 return 0;
359
360 if (switch_on)
361 sst_hsw_set_module_enabled_rtd3(hsw, id);
362 else
363 sst_hsw_set_module_disabled_rtd3(hsw, id);
364 }
365
366 return ret;
367}
368
369static int hsw_waves_param_get(struct snd_kcontrol *kcontrol,
370 struct snd_ctl_elem_value *ucontrol)
371{
372 struct snd_soc_platform *platform = snd_soc_kcontrol_platform(kcontrol);
373 struct hsw_priv_data *pdata = snd_soc_platform_get_drvdata(platform);
374 struct sst_hsw *hsw = pdata->hsw;
375
376 /* return a matching line from param buffer */
377 return sst_hsw_load_param_line(hsw, ucontrol->value.bytes.data);
378}
379
380static int hsw_waves_param_put(struct snd_kcontrol *kcontrol,
381 struct snd_ctl_elem_value *ucontrol)
382{
383 struct snd_soc_platform *platform = snd_soc_kcontrol_platform(kcontrol);
384 struct hsw_priv_data *pdata = snd_soc_platform_get_drvdata(platform);
385 struct sst_hsw *hsw = pdata->hsw;
386 int ret;
387 enum sst_hsw_module_id id = SST_HSW_MODULE_WAVES;
388 int param_id = ucontrol->value.bytes.data[0];
389 int param_size = WAVES_PARAM_COUNT;
390
391 /* clear param buffer and reset buffer index */
392 if (param_id == 0xFF) {
393 sst_hsw_reset_param_buf(hsw);
394 return 0;
395 }
396
397 /* store params into buffer */
398 ret = sst_hsw_store_param_line(hsw, ucontrol->value.bytes.data);
399 if (ret < 0)
400 return ret;
401
402 if (sst_hsw_is_module_loaded(hsw, id)) {
403 if (!sst_hsw_is_module_active(hsw, id))
404 return 0;
405
406 ret = sst_hsw_module_set_param(hsw, id, 0, param_id,
407 param_size, ucontrol->value.bytes.data);
408 }
409 return ret;
410}
411
321/* TLV used by both global and stream volumes */ 412/* TLV used by both global and stream volumes */
322static const DECLARE_TLV_DB_SCALE(hsw_vol_tlv, -9000, 300, 1); 413static const DECLARE_TLV_DB_SCALE(hsw_vol_tlv, -9000, 300, 1);
323 414
@@ -339,6 +430,12 @@ static const struct snd_kcontrol_new hsw_volume_controls[] = {
339 SOC_DOUBLE_EXT_TLV("Mic Capture Volume", 4, 0, 8, 430 SOC_DOUBLE_EXT_TLV("Mic Capture Volume", 4, 0, 8,
340 ARRAY_SIZE(volume_map) - 1, 0, 431 ARRAY_SIZE(volume_map) - 1, 0,
341 hsw_stream_volume_get, hsw_stream_volume_put, hsw_vol_tlv), 432 hsw_stream_volume_get, hsw_stream_volume_put, hsw_vol_tlv),
433 /* enable/disable module waves */
434 SOC_SINGLE_BOOL_EXT("Waves Switch", 0,
435 hsw_waves_switch_get, hsw_waves_switch_put),
436 /* set parameters to module waves */
437 SND_SOC_BYTES_EXT("Waves Set Param", WAVES_PARAM_COUNT,
438 hsw_waves_param_get, hsw_waves_param_put),
342}; 439};
343 440
344/* Create DMA buffer page table for DSP */ 441/* Create DMA buffer page table for DSP */
@@ -807,6 +904,17 @@ static int hsw_pcm_create_modules(struct hsw_priv_data *pdata)
807 pcm_data->runtime->persistent_offset; 904 pcm_data->runtime->persistent_offset;
808 } 905 }
809 906
907 /* create runtime blocks for module waves */
908 if (sst_hsw_is_module_loaded(hsw, SST_HSW_MODULE_WAVES)) {
909 pcm_data = &pdata->pcm[HSW_PCM_COUNT-1][0];
910 pcm_data->runtime = sst_hsw_runtime_module_create(hsw,
911 SST_HSW_MODULE_WAVES, pcm_data->persistent_offset);
912 if (pcm_data->runtime == NULL)
913 goto err;
914 pcm_data->persistent_offset =
915 pcm_data->runtime->persistent_offset;
916 }
917
810 return 0; 918 return 0;
811 919
812err: 920err:
@@ -820,12 +928,16 @@ err:
820 928
821static void hsw_pcm_free_modules(struct hsw_priv_data *pdata) 929static void hsw_pcm_free_modules(struct hsw_priv_data *pdata)
822{ 930{
931 struct sst_hsw *hsw = pdata->hsw;
823 struct hsw_pcm_data *pcm_data; 932 struct hsw_pcm_data *pcm_data;
824 int i; 933 int i;
825 934
826 for (i = 0; i < ARRAY_SIZE(mod_map); i++) { 935 for (i = 0; i < ARRAY_SIZE(mod_map); i++) {
827 pcm_data = &pdata->pcm[mod_map[i].dai_id][mod_map[i].stream]; 936 pcm_data = &pdata->pcm[mod_map[i].dai_id][mod_map[i].stream];
828 937 sst_hsw_runtime_module_free(pcm_data->runtime);
938 }
939 if (sst_hsw_is_module_loaded(hsw, SST_HSW_MODULE_WAVES)) {
940 pcm_data = &pdata->pcm[HSW_PCM_COUNT-1][0];
829 sst_hsw_runtime_module_free(pcm_data->runtime); 941 sst_hsw_runtime_module_free(pcm_data->runtime);
830 } 942 }
831} 943}
@@ -984,7 +1096,9 @@ static int hsw_pcm_probe(struct snd_soc_platform *platform)
984 } 1096 }
985 1097
986 /* allocate runtime modules */ 1098 /* allocate runtime modules */
987 hsw_pcm_create_modules(priv_data); 1099 ret = hsw_pcm_create_modules(priv_data);
1100 if (ret < 0)
1101 goto err;
988 1102
989 /* enable runtime PM with auto suspend */ 1103 /* enable runtime PM with auto suspend */
990 pm_runtime_set_autosuspend_delay(platform->dev, 1104 pm_runtime_set_autosuspend_delay(platform->dev,
@@ -1101,10 +1215,18 @@ static int hsw_pcm_runtime_suspend(struct device *dev)
1101{ 1215{
1102 struct hsw_priv_data *pdata = dev_get_drvdata(dev); 1216 struct hsw_priv_data *pdata = dev_get_drvdata(dev);
1103 struct sst_hsw *hsw = pdata->hsw; 1217 struct sst_hsw *hsw = pdata->hsw;
1218 int ret;
1104 1219
1105 if (pdata->pm_state >= HSW_PM_STATE_RTD3) 1220 if (pdata->pm_state >= HSW_PM_STATE_RTD3)
1106 return 0; 1221 return 0;
1107 1222
1223 /* fw modules will be unloaded on RTD3, set flag to track */
1224 if (sst_hsw_is_module_active(hsw, SST_HSW_MODULE_WAVES)) {
1225 ret = sst_hsw_module_disable(hsw, SST_HSW_MODULE_WAVES, 0);
1226 if (ret < 0)
1227 return ret;
1228 sst_hsw_set_module_enabled_rtd3(hsw, SST_HSW_MODULE_WAVES);
1229 }
1108 sst_hsw_dsp_runtime_suspend(hsw); 1230 sst_hsw_dsp_runtime_suspend(hsw);
1109 sst_hsw_dsp_runtime_sleep(hsw); 1231 sst_hsw_dsp_runtime_sleep(hsw);
1110 pdata->pm_state = HSW_PM_STATE_RTD3; 1232 pdata->pm_state = HSW_PM_STATE_RTD3;
@@ -1139,6 +1261,19 @@ static int hsw_pcm_runtime_resume(struct device *dev)
1139 else if (ret == 1) /* no action required */ 1261 else if (ret == 1) /* no action required */
1140 return 0; 1262 return 0;
1141 1263
1264 /* check flag when resume */
1265 if (sst_hsw_is_module_enabled_rtd3(hsw, SST_HSW_MODULE_WAVES)) {
1266 ret = sst_hsw_module_enable(hsw, SST_HSW_MODULE_WAVES, 0);
1267 if (ret < 0)
1268 return ret;
1269 /* put parameters from buffer to dsp */
1270 ret = sst_hsw_launch_param_buf(hsw);
1271 if (ret < 0)
1272 return ret;
1273 /* unset flag */
1274 sst_hsw_set_module_disabled_rtd3(hsw, SST_HSW_MODULE_WAVES);
1275 }
1276
1142 pdata->pm_state = HSW_PM_STATE_D0; 1277 pdata->pm_state = HSW_PM_STATE_D0;
1143 return ret; 1278 return ret;
1144} 1279}
diff --git a/sound/soc/intel/sst-mfld-platform-pcm.c b/sound/soc/intel/sst-mfld-platform-pcm.c
index 7523cbef8780..2fbaf2c75d17 100644
--- a/sound/soc/intel/sst-mfld-platform-pcm.c
+++ b/sound/soc/intel/sst-mfld-platform-pcm.c
@@ -594,11 +594,13 @@ static int sst_platform_pcm_trigger(struct snd_pcm_substream *substream,
594 ret_val = stream->ops->stream_drop(sst->dev, str_id); 594 ret_val = stream->ops->stream_drop(sst->dev, str_id);
595 break; 595 break;
596 case SNDRV_PCM_TRIGGER_PAUSE_PUSH: 596 case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
597 case SNDRV_PCM_TRIGGER_SUSPEND:
597 dev_dbg(rtd->dev, "sst: in pause\n"); 598 dev_dbg(rtd->dev, "sst: in pause\n");
598 status = SST_PLATFORM_PAUSED; 599 status = SST_PLATFORM_PAUSED;
599 ret_val = stream->ops->stream_pause(sst->dev, str_id); 600 ret_val = stream->ops->stream_pause(sst->dev, str_id);
600 break; 601 break;
601 case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: 602 case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
603 case SNDRV_PCM_TRIGGER_RESUME:
602 dev_dbg(rtd->dev, "sst: in pause release\n"); 604 dev_dbg(rtd->dev, "sst: in pause release\n");
603 status = SST_PLATFORM_RUNNING; 605 status = SST_PLATFORM_RUNNING;
604 ret_val = stream->ops->stream_pause_release(sst->dev, str_id); 606 ret_val = stream->ops->stream_pause_release(sst->dev, str_id);
@@ -665,6 +667,9 @@ static int sst_pcm_new(struct snd_soc_pcm_runtime *rtd)
665 667
666static int sst_soc_probe(struct snd_soc_platform *platform) 668static int sst_soc_probe(struct snd_soc_platform *platform)
667{ 669{
670 struct sst_data *drv = dev_get_drvdata(platform->dev);
671
672 drv->soc_card = platform->component.card;
668 return sst_dsp_init_v2_dpcm(platform); 673 return sst_dsp_init_v2_dpcm(platform);
669} 674}
670 675
@@ -727,9 +732,64 @@ static int sst_platform_remove(struct platform_device *pdev)
727 return 0; 732 return 0;
728} 733}
729 734
735#ifdef CONFIG_PM_SLEEP
736
737static int sst_soc_prepare(struct device *dev)
738{
739 struct sst_data *drv = dev_get_drvdata(dev);
740 int i;
741
742 /* suspend all pcms first */
743 snd_soc_suspend(drv->soc_card->dev);
744 snd_soc_poweroff(drv->soc_card->dev);
745
746 /* set the SSPs to idle */
747 for (i = 0; i < drv->soc_card->num_rtd; i++) {
748 struct snd_soc_dai *dai = drv->soc_card->rtd[i].cpu_dai;
749
750 if (dai->active) {
751 send_ssp_cmd(dai, dai->name, 0);
752 sst_handle_vb_timer(dai, false);
753 }
754 }
755
756 return 0;
757}
758
759static void sst_soc_complete(struct device *dev)
760{
761 struct sst_data *drv = dev_get_drvdata(dev);
762 int i;
763
764 /* restart SSPs */
765 for (i = 0; i < drv->soc_card->num_rtd; i++) {
766 struct snd_soc_dai *dai = drv->soc_card->rtd[i].cpu_dai;
767
768 if (dai->active) {
769 sst_handle_vb_timer(dai, true);
770 send_ssp_cmd(dai, dai->name, 1);
771 }
772 }
773 snd_soc_resume(drv->soc_card->dev);
774}
775
776#else
777
778#define sst_soc_prepare NULL
779#define sst_soc_complete NULL
780
781#endif
782
783
784static const struct dev_pm_ops sst_platform_pm = {
785 .prepare = sst_soc_prepare,
786 .complete = sst_soc_complete,
787};
788
730static struct platform_driver sst_platform_driver = { 789static struct platform_driver sst_platform_driver = {
731 .driver = { 790 .driver = {
732 .name = "sst-mfld-platform", 791 .name = "sst-mfld-platform",
792 .pm = &sst_platform_pm,
733 }, 793 },
734 .probe = sst_platform_probe, 794 .probe = sst_platform_probe,
735 .remove = sst_platform_remove, 795 .remove = sst_platform_remove,
diff --git a/sound/soc/intel/sst-mfld-platform.h b/sound/soc/intel/sst-mfld-platform.h
index 79c8d1246a8f..9094314be2b0 100644
--- a/sound/soc/intel/sst-mfld-platform.h
+++ b/sound/soc/intel/sst-mfld-platform.h
@@ -174,6 +174,7 @@ struct sst_data {
174 struct sst_platform_data *pdata; 174 struct sst_platform_data *pdata;
175 struct snd_sst_bytes_v2 *byte_stream; 175 struct snd_sst_bytes_v2 *byte_stream;
176 struct mutex lock; 176 struct mutex lock;
177 struct snd_soc_card *soc_card;
177}; 178};
178int sst_register_dsp(struct sst_device *sst); 179int sst_register_dsp(struct sst_device *sst);
179int sst_unregister_dsp(struct sst_device *sst); 180int sst_unregister_dsp(struct sst_device *sst);
diff --git a/sound/soc/intel/sst/sst.c b/sound/soc/intel/sst/sst.c
index 11c578651c1c..1a7eeec444b1 100644
--- a/sound/soc/intel/sst/sst.c
+++ b/sound/soc/intel/sst/sst.c
@@ -423,23 +423,135 @@ static int intel_sst_runtime_suspend(struct device *dev)
423 return ret; 423 return ret;
424} 424}
425 425
426static int intel_sst_runtime_resume(struct device *dev) 426static int intel_sst_suspend(struct device *dev)
427{ 427{
428 int ret = 0;
429 struct intel_sst_drv *ctx = dev_get_drvdata(dev); 428 struct intel_sst_drv *ctx = dev_get_drvdata(dev);
429 struct sst_fw_save *fw_save;
430 int i, ret = 0;
430 431
431 if (ctx->sst_state == SST_RESET) { 432 /* check first if we are already in SW reset */
432 ret = sst_load_fw(ctx); 433 if (ctx->sst_state == SST_RESET)
433 if (ret) { 434 return 0;
434 dev_err(dev, "FW download fail %d\n", ret); 435
435 sst_set_fw_state_locked(ctx, SST_RESET); 436 /*
437 * check if any stream is active and running
438 * they should already by suspend by soc_suspend
439 */
440 for (i = 1; i <= ctx->info.max_streams; i++) {
441 struct stream_info *stream = &ctx->streams[i];
442
443 if (stream->status == STREAM_RUNNING) {
444 dev_err(dev, "stream %d is running, cant susupend, abort\n", i);
445 return -EBUSY;
436 } 446 }
437 } 447 }
448 synchronize_irq(ctx->irq_num);
449 flush_workqueue(ctx->post_msg_wq);
450
451 /* Move the SST state to Reset */
452 sst_set_fw_state_locked(ctx, SST_RESET);
453
454 /* tell DSP we are suspending */
455 if (ctx->ops->save_dsp_context(ctx))
456 return -EBUSY;
457
458 /* save the memories */
459 fw_save = kzalloc(sizeof(*fw_save), GFP_KERNEL);
460 if (!fw_save)
461 return -ENOMEM;
462 fw_save->iram = kzalloc(ctx->iram_end - ctx->iram_base, GFP_KERNEL);
463 if (!fw_save->iram) {
464 ret = -ENOMEM;
465 goto iram;
466 }
467 fw_save->dram = kzalloc(ctx->dram_end - ctx->dram_base, GFP_KERNEL);
468 if (!fw_save->dram) {
469 ret = -ENOMEM;
470 goto dram;
471 }
472 fw_save->sram = kzalloc(SST_MAILBOX_SIZE, GFP_KERNEL);
473 if (!fw_save->sram) {
474 ret = -ENOMEM;
475 goto sram;
476 }
477
478 fw_save->ddr = kzalloc(ctx->ddr_end - ctx->ddr_base, GFP_KERNEL);
479 if (!fw_save->ddr) {
480 ret = -ENOMEM;
481 goto ddr;
482 }
483
484 memcpy32_fromio(fw_save->iram, ctx->iram, ctx->iram_end - ctx->iram_base);
485 memcpy32_fromio(fw_save->dram, ctx->dram, ctx->dram_end - ctx->dram_base);
486 memcpy32_fromio(fw_save->sram, ctx->mailbox, SST_MAILBOX_SIZE);
487 memcpy32_fromio(fw_save->ddr, ctx->ddr, ctx->ddr_end - ctx->ddr_base);
488
489 ctx->fw_save = fw_save;
490 ctx->ops->reset(ctx);
491 return 0;
492ddr:
493 kfree(fw_save->sram);
494sram:
495 kfree(fw_save->dram);
496dram:
497 kfree(fw_save->iram);
498iram:
499 kfree(fw_save);
500 return ret;
501}
502
503static int intel_sst_resume(struct device *dev)
504{
505 struct intel_sst_drv *ctx = dev_get_drvdata(dev);
506 struct sst_fw_save *fw_save = ctx->fw_save;
507 int ret = 0;
508 struct sst_block *block;
509
510 if (!fw_save)
511 return 0;
512
513 sst_set_fw_state_locked(ctx, SST_FW_LOADING);
514
515 /* we have to restore the memory saved */
516 ctx->ops->reset(ctx);
517
518 ctx->fw_save = NULL;
519
520 memcpy32_toio(ctx->iram, fw_save->iram, ctx->iram_end - ctx->iram_base);
521 memcpy32_toio(ctx->dram, fw_save->dram, ctx->dram_end - ctx->dram_base);
522 memcpy32_toio(ctx->mailbox, fw_save->sram, SST_MAILBOX_SIZE);
523 memcpy32_toio(ctx->ddr, fw_save->ddr, ctx->ddr_end - ctx->ddr_base);
524
525 kfree(fw_save->sram);
526 kfree(fw_save->dram);
527 kfree(fw_save->iram);
528 kfree(fw_save->ddr);
529 kfree(fw_save);
530
531 block = sst_create_block(ctx, 0, FW_DWNL_ID);
532 if (block == NULL)
533 return -ENOMEM;
534
535
536 /* start and wait for ack */
537 ctx->ops->start(ctx);
538 ret = sst_wait_timeout(ctx, block);
539 if (ret) {
540 dev_err(ctx->dev, "fw download failed %d\n", ret);
541 /* FW download failed due to timeout */
542 ret = -EBUSY;
543
544 } else {
545 sst_set_fw_state_locked(ctx, SST_FW_RUNNING);
546 }
547
548 sst_free_block(ctx, block);
438 return ret; 549 return ret;
439} 550}
440 551
441const struct dev_pm_ops intel_sst_pm = { 552const struct dev_pm_ops intel_sst_pm = {
553 .suspend = intel_sst_suspend,
554 .resume = intel_sst_resume,
442 .runtime_suspend = intel_sst_runtime_suspend, 555 .runtime_suspend = intel_sst_runtime_suspend,
443 .runtime_resume = intel_sst_runtime_resume,
444}; 556};
445EXPORT_SYMBOL_GPL(intel_sst_pm); 557EXPORT_SYMBOL_GPL(intel_sst_pm);
diff --git a/sound/soc/intel/sst/sst.h b/sound/soc/intel/sst/sst.h
index 562bc483d6b7..3f493862e98d 100644
--- a/sound/soc/intel/sst/sst.h
+++ b/sound/soc/intel/sst/sst.h
@@ -337,6 +337,13 @@ struct sst_shim_regs64 {
337 u64 csr2; 337 u64 csr2;
338}; 338};
339 339
340struct sst_fw_save {
341 void *iram;
342 void *dram;
343 void *sram;
344 void *ddr;
345};
346
340/** 347/**
341 * struct intel_sst_drv - driver ops 348 * struct intel_sst_drv - driver ops
342 * 349 *
@@ -428,6 +435,8 @@ struct intel_sst_drv {
428 * persistent till worker thread gets called 435 * persistent till worker thread gets called
429 */ 436 */
430 char firmware_name[FW_NAME_SIZE]; 437 char firmware_name[FW_NAME_SIZE];
438
439 struct sst_fw_save *fw_save;
431}; 440};
432 441
433/* misc definitions */ 442/* misc definitions */
@@ -544,4 +553,7 @@ int sst_alloc_drv_context(struct intel_sst_drv **ctx,
544int sst_context_init(struct intel_sst_drv *ctx); 553int sst_context_init(struct intel_sst_drv *ctx);
545void sst_context_cleanup(struct intel_sst_drv *ctx); 554void sst_context_cleanup(struct intel_sst_drv *ctx);
546void sst_configure_runtime_pm(struct intel_sst_drv *ctx); 555void sst_configure_runtime_pm(struct intel_sst_drv *ctx);
556void memcpy32_toio(void __iomem *dst, const void *src, int count);
557void memcpy32_fromio(void *dst, const void __iomem *src, int count);
558
547#endif 559#endif
diff --git a/sound/soc/intel/sst/sst_drv_interface.c b/sound/soc/intel/sst/sst_drv_interface.c
index 5f75ef3cdd22..f0e4b99b3aeb 100644
--- a/sound/soc/intel/sst/sst_drv_interface.c
+++ b/sound/soc/intel/sst/sst_drv_interface.c
@@ -138,12 +138,36 @@ int sst_get_stream(struct intel_sst_drv *ctx,
138static int sst_power_control(struct device *dev, bool state) 138static int sst_power_control(struct device *dev, bool state)
139{ 139{
140 struct intel_sst_drv *ctx = dev_get_drvdata(dev); 140 struct intel_sst_drv *ctx = dev_get_drvdata(dev);
141 141 int ret = 0;
142 dev_dbg(ctx->dev, "state:%d", state); 142 int usage_count = 0;
143 if (state == true) 143
144 return pm_runtime_get_sync(dev); 144#ifdef CONFIG_PM
145 else 145 usage_count = atomic_read(&dev->power.usage_count);
146#else
147 usage_count = 1;
148#endif
149
150 if (state == true) {
151 ret = pm_runtime_get_sync(dev);
152
153 dev_dbg(ctx->dev, "Enable: pm usage count: %d\n", usage_count);
154 if (ret < 0) {
155 dev_err(ctx->dev, "Runtime get failed with err: %d\n", ret);
156 return ret;
157 }
158 if ((ctx->sst_state == SST_RESET) && (usage_count == 1)) {
159 ret = sst_load_fw(ctx);
160 if (ret) {
161 dev_err(dev, "FW download fail %d\n", ret);
162 sst_set_fw_state_locked(ctx, SST_RESET);
163 ret = sst_pm_runtime_put(ctx);
164 }
165 }
166 } else {
167 dev_dbg(ctx->dev, "Disable: pm usage count: %d\n", usage_count);
146 return sst_pm_runtime_put(ctx); 168 return sst_pm_runtime_put(ctx);
169 }
170 return ret;
147} 171}
148 172
149/* 173/*
@@ -572,6 +596,35 @@ static int sst_stream_drop(struct device *dev, int str_id)
572 return sst_drop_stream(ctx, str_id); 596 return sst_drop_stream(ctx, str_id);
573} 597}
574 598
599static int sst_stream_pause(struct device *dev, int str_id)
600{
601 struct stream_info *str_info;
602 struct intel_sst_drv *ctx = dev_get_drvdata(dev);
603
604 if (ctx->sst_state != SST_FW_RUNNING)
605 return 0;
606
607 str_info = get_stream_info(ctx, str_id);
608 if (!str_info)
609 return -EINVAL;
610
611 return sst_pause_stream(ctx, str_id);
612}
613
614static int sst_stream_resume(struct device *dev, int str_id)
615{
616 struct stream_info *str_info;
617 struct intel_sst_drv *ctx = dev_get_drvdata(dev);
618
619 if (ctx->sst_state != SST_FW_RUNNING)
620 return 0;
621
622 str_info = get_stream_info(ctx, str_id);
623 if (!str_info)
624 return -EINVAL;
625 return sst_resume_stream(ctx, str_id);
626}
627
575static int sst_stream_init(struct device *dev, struct pcm_stream_info *str_info) 628static int sst_stream_init(struct device *dev, struct pcm_stream_info *str_info)
576{ 629{
577 int str_id = 0; 630 int str_id = 0;
@@ -633,6 +686,8 @@ static struct sst_ops pcm_ops = {
633 .stream_init = sst_stream_init, 686 .stream_init = sst_stream_init,
634 .stream_start = sst_stream_start, 687 .stream_start = sst_stream_start,
635 .stream_drop = sst_stream_drop, 688 .stream_drop = sst_stream_drop,
689 .stream_pause = sst_stream_pause,
690 .stream_pause_release = sst_stream_resume,
636 .stream_read_tstamp = sst_read_timestamp, 691 .stream_read_tstamp = sst_read_timestamp,
637 .send_byte_stream = sst_send_byte_stream, 692 .send_byte_stream = sst_send_byte_stream,
638 .close = sst_close_pcm_stream, 693 .close = sst_close_pcm_stream,
diff --git a/sound/soc/intel/sst/sst_loader.c b/sound/soc/intel/sst/sst_loader.c
index 7888cd707853..e88907ae8b15 100644
--- a/sound/soc/intel/sst/sst_loader.c
+++ b/sound/soc/intel/sst/sst_loader.c
@@ -39,7 +39,15 @@
39#include "sst.h" 39#include "sst.h"
40#include "../sst-dsp.h" 40#include "../sst-dsp.h"
41 41
42static inline void memcpy32_toio(void __iomem *dst, const void *src, int count) 42void memcpy32_toio(void __iomem *dst, const void *src, int count)
43{
44 /* __iowrite32_copy uses 32-bit count values so divide by 4 for
45 * right count in words
46 */
47 __iowrite32_copy(dst, src, count/4);
48}
49
50void memcpy32_fromio(void *dst, const void __iomem *src, int count)
43{ 51{
44 /* __iowrite32_copy uses 32-bit count values so divide by 4 for 52 /* __iowrite32_copy uses 32-bit count values so divide by 4 for
45 * right count in words 53 * right count in words
diff --git a/sound/soc/soc-pcm.c b/sound/soc/soc-pcm.c
index 6b0136e7cb88..6e3781e88f9a 100644
--- a/sound/soc/soc-pcm.c
+++ b/sound/soc/soc-pcm.c
@@ -2511,6 +2511,7 @@ int soc_new_pcm(struct snd_soc_pcm_runtime *rtd, int num)
2511 /* DAPM dai link stream work */ 2511 /* DAPM dai link stream work */
2512 INIT_DELAYED_WORK(&rtd->delayed_work, close_delayed_work); 2512 INIT_DELAYED_WORK(&rtd->delayed_work, close_delayed_work);
2513 2513
2514 pcm->nonatomic = rtd->dai_link->nonatomic;
2514 rtd->pcm = pcm; 2515 rtd->pcm = pcm;
2515 pcm->private_data = rtd; 2516 pcm->private_data = rtd;
2516 2517