diff options
author | Takashi Iwai <tiwai@suse.de> | 2015-03-23 08:14:02 -0400 |
---|---|---|
committer | Takashi Iwai <tiwai@suse.de> | 2015-03-23 08:14:02 -0400 |
commit | 3372dbdd8ca11f51be8c6a30b2bc79eb04c4a902 (patch) | |
tree | d4499bf5a5665b4820ffaf96bce55bf6b895195e /sound/soc/intel | |
parent | bc465aa9d045feb0e13b4a8f32cc33c1943f62d6 (diff) | |
parent | 967b1307b69b8ada8b331e01046ad1ef83742e99 (diff) |
Merge branch 'for-next' into topic/hda-core
Diffstat (limited to 'sound/soc/intel')
-rw-r--r-- | sound/soc/intel/broadwell.c | 16 | ||||
-rw-r--r-- | sound/soc/intel/byt-max98090.c | 11 | ||||
-rw-r--r-- | sound/soc/intel/bytcr_dpcm_rt5640.c | 4 | ||||
-rw-r--r-- | sound/soc/intel/cht_bsw_rt5645.c | 16 | ||||
-rw-r--r-- | sound/soc/intel/cht_bsw_rt5672.c | 9 | ||||
-rw-r--r-- | sound/soc/intel/haswell.c | 4 | ||||
-rw-r--r-- | sound/soc/intel/mfld_machine.c | 24 | ||||
-rw-r--r-- | sound/soc/intel/sst-mfld-platform-pcm.c | 60 | ||||
-rw-r--r-- | sound/soc/intel/sst-mfld-platform.h | 1 | ||||
-rw-r--r-- | sound/soc/intel/sst/sst.c | 128 | ||||
-rw-r--r-- | sound/soc/intel/sst/sst.h | 12 | ||||
-rw-r--r-- | sound/soc/intel/sst/sst_drv_interface.c | 65 | ||||
-rw-r--r-- | sound/soc/intel/sst/sst_loader.c | 10 |
13 files changed, 291 insertions, 69 deletions
diff --git a/sound/soc/intel/broadwell.c b/sound/soc/intel/broadwell.c index 9cf7d01479ad..fc5542034b9b 100644 --- a/sound/soc/intel/broadwell.c +++ b/sound/soc/intel/broadwell.c | |||
@@ -80,15 +80,9 @@ static int broadwell_rt286_codec_init(struct snd_soc_pcm_runtime *rtd) | |||
80 | { | 80 | { |
81 | struct snd_soc_codec *codec = rtd->codec; | 81 | struct snd_soc_codec *codec = rtd->codec; |
82 | int ret = 0; | 82 | int ret = 0; |
83 | ret = snd_soc_jack_new(codec, "Headset", | 83 | ret = snd_soc_card_jack_new(rtd->card, "Headset", |
84 | SND_JACK_HEADSET | SND_JACK_BTN_0, &broadwell_headset); | 84 | SND_JACK_HEADSET | SND_JACK_BTN_0, &broadwell_headset, |
85 | 85 | broadwell_headset_pins, ARRAY_SIZE(broadwell_headset_pins)); | |
86 | if (ret) | ||
87 | return ret; | ||
88 | |||
89 | ret = snd_soc_jack_add_pins(&broadwell_headset, | ||
90 | ARRAY_SIZE(broadwell_headset_pins), | ||
91 | broadwell_headset_pins); | ||
92 | if (ret) | 86 | if (ret) |
93 | return ret; | 87 | return ret; |
94 | 88 | ||
@@ -110,9 +104,7 @@ static int broadwell_ssp0_fixup(struct snd_soc_pcm_runtime *rtd, | |||
110 | channels->min = channels->max = 2; | 104 | channels->min = channels->max = 2; |
111 | 105 | ||
112 | /* set SSP0 to 16 bit */ | 106 | /* set SSP0 to 16 bit */ |
113 | snd_mask_set(¶ms->masks[SNDRV_PCM_HW_PARAM_FORMAT - | 107 | 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; | 108 | return 0; |
117 | } | 109 | } |
118 | 110 | ||
diff --git a/sound/soc/intel/byt-max98090.c b/sound/soc/intel/byt-max98090.c index 9832afe7d22c..d8b1f038da1c 100644 --- a/sound/soc/intel/byt-max98090.c +++ b/sound/soc/intel/byt-max98090.c | |||
@@ -84,7 +84,6 @@ static struct snd_soc_jack_gpio hs_jack_gpios[] = { | |||
84 | static int byt_max98090_init(struct snd_soc_pcm_runtime *runtime) | 84 | static int byt_max98090_init(struct snd_soc_pcm_runtime *runtime) |
85 | { | 85 | { |
86 | int ret; | 86 | int ret; |
87 | struct snd_soc_codec *codec = runtime->codec; | ||
88 | struct snd_soc_card *card = runtime->card; | 87 | struct snd_soc_card *card = runtime->card; |
89 | struct byt_max98090_private *drv = snd_soc_card_get_drvdata(card); | 88 | struct byt_max98090_private *drv = snd_soc_card_get_drvdata(card); |
90 | struct snd_soc_jack *jack = &drv->jack; | 89 | struct snd_soc_jack *jack = &drv->jack; |
@@ -100,13 +99,9 @@ static int byt_max98090_init(struct snd_soc_pcm_runtime *runtime) | |||
100 | } | 99 | } |
101 | 100 | ||
102 | /* Enable jack detection */ | 101 | /* Enable jack detection */ |
103 | ret = snd_soc_jack_new(codec, "Headset", | 102 | ret = snd_soc_card_jack_new(runtime->card, "Headset", |
104 | SND_JACK_LINEOUT | SND_JACK_HEADSET, jack); | 103 | SND_JACK_LINEOUT | SND_JACK_HEADSET, jack, |
105 | if (ret) | 104 | hs_jack_pins, ARRAY_SIZE(hs_jack_pins)); |
106 | return ret; | ||
107 | |||
108 | ret = snd_soc_jack_add_pins(jack, ARRAY_SIZE(hs_jack_pins), | ||
109 | hs_jack_pins); | ||
110 | if (ret) | 105 | if (ret) |
111 | return ret; | 106 | return ret; |
112 | 107 | ||
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(¶ms->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..012227997ed9 100644 --- a/sound/soc/intel/cht_bsw_rt5645.c +++ b/sound/soc/intel/cht_bsw_rt5645.c | |||
@@ -169,17 +169,17 @@ static int cht_codec_init(struct snd_soc_pcm_runtime *runtime) | |||
169 | return ret; | 169 | return ret; |
170 | } | 170 | } |
171 | 171 | ||
172 | ret = snd_soc_jack_new(codec, "Headphone Jack", | 172 | ret = snd_soc_card_jack_new(runtime->card, "Headphone Jack", |
173 | SND_JACK_HEADPHONE, | 173 | SND_JACK_HEADPHONE, &ctx->hp_jack, |
174 | &ctx->hp_jack); | 174 | NULL, 0); |
175 | if (ret) { | 175 | if (ret) { |
176 | dev_err(runtime->dev, "HP jack creation failed %d\n", ret); | 176 | dev_err(runtime->dev, "HP jack creation failed %d\n", ret); |
177 | return ret; | 177 | return ret; |
178 | } | 178 | } |
179 | 179 | ||
180 | ret = snd_soc_jack_new(codec, "Mic Jack", | 180 | ret = snd_soc_card_jack_new(runtime->card, "Mic Jack", |
181 | SND_JACK_MICROPHONE, | 181 | SND_JACK_MICROPHONE, &ctx->mic_jack, |
182 | &ctx->mic_jack); | 182 | NULL, 0); |
183 | if (ret) { | 183 | if (ret) { |
184 | dev_err(runtime->dev, "Mic jack creation failed %d\n", ret); | 184 | dev_err(runtime->dev, "Mic jack creation failed %d\n", ret); |
185 | return ret; | 185 | return ret; |
@@ -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(¶ms->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..bc8dcacd5e6a 100644 --- a/sound/soc/intel/cht_bsw_rt5672.c +++ b/sound/soc/intel/cht_bsw_rt5672.c | |||
@@ -178,9 +178,7 @@ static int cht_codec_fixup(struct snd_soc_pcm_runtime *rtd, | |||
178 | channels->min = channels->max = 2; | 178 | channels->min = channels->max = 2; |
179 | 179 | ||
180 | /* set SSP2 to 24-bit */ | 180 | /* set SSP2 to 24-bit */ |
181 | snd_mask_set(¶ms->masks[SNDRV_PCM_HW_PARAM_FORMAT - | 181 | 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; | 182 | return 0; |
185 | } | 183 | } |
186 | 184 | ||
@@ -217,7 +215,7 @@ static struct snd_soc_dai_link cht_dailink[] = { | |||
217 | .codec_dai_name = "snd-soc-dummy-dai", | 215 | .codec_dai_name = "snd-soc-dummy-dai", |
218 | .codec_name = "snd-soc-dummy", | 216 | .codec_name = "snd-soc-dummy", |
219 | .platform_name = "sst-mfld-platform", | 217 | .platform_name = "sst-mfld-platform", |
220 | .ignore_suspend = 1, | 218 | .nonatomic = true, |
221 | .dynamic = 1, | 219 | .dynamic = 1, |
222 | .dpcm_playback = 1, | 220 | .dpcm_playback = 1, |
223 | .dpcm_capture = 1, | 221 | .dpcm_capture = 1, |
@@ -240,13 +238,13 @@ static struct snd_soc_dai_link cht_dailink[] = { | |||
240 | .cpu_dai_name = "ssp2-port", | 238 | .cpu_dai_name = "ssp2-port", |
241 | .platform_name = "sst-mfld-platform", | 239 | .platform_name = "sst-mfld-platform", |
242 | .no_pcm = 1, | 240 | .no_pcm = 1, |
241 | .nonatomic = true, | ||
243 | .codec_dai_name = "rt5670-aif1", | 242 | .codec_dai_name = "rt5670-aif1", |
244 | .codec_name = "i2c-10EC5670:00", | 243 | .codec_name = "i2c-10EC5670:00", |
245 | .dai_fmt = SND_SOC_DAIFMT_DSP_B | SND_SOC_DAIFMT_IB_NF | 244 | .dai_fmt = SND_SOC_DAIFMT_DSP_B | SND_SOC_DAIFMT_IB_NF |
246 | | SND_SOC_DAIFMT_CBS_CFS, | 245 | | SND_SOC_DAIFMT_CBS_CFS, |
247 | .init = cht_codec_init, | 246 | .init = cht_codec_init, |
248 | .be_hw_params_fixup = cht_codec_fixup, | 247 | .be_hw_params_fixup = cht_codec_fixup, |
249 | .ignore_suspend = 1, | ||
250 | .dpcm_playback = 1, | 248 | .dpcm_playback = 1, |
251 | .dpcm_capture = 1, | 249 | .dpcm_capture = 1, |
252 | .ops = &cht_be_ssp2_ops, | 250 | .ops = &cht_be_ssp2_ops, |
@@ -285,7 +283,6 @@ static int snd_cht_mc_probe(struct platform_device *pdev) | |||
285 | static struct platform_driver snd_cht_mc_driver = { | 283 | static struct platform_driver snd_cht_mc_driver = { |
286 | .driver = { | 284 | .driver = { |
287 | .name = "cht-bsw-rt5672", | 285 | .name = "cht-bsw-rt5672", |
288 | .pm = &snd_soc_pm_ops, | ||
289 | }, | 286 | }, |
290 | .probe = snd_cht_mc_probe, | 287 | .probe = snd_cht_mc_probe, |
291 | }; | 288 | }; |
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(¶ms->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/mfld_machine.c b/sound/soc/intel/mfld_machine.c index 90b7a57713a0..49c09a0add79 100644 --- a/sound/soc/intel/mfld_machine.c +++ b/sound/soc/intel/mfld_machine.c | |||
@@ -228,10 +228,13 @@ static void mfld_jack_check(unsigned int intr_status) | |||
228 | { | 228 | { |
229 | struct mfld_jack_data jack_data; | 229 | struct mfld_jack_data jack_data; |
230 | 230 | ||
231 | if (!mfld_codec) | ||
232 | return; | ||
233 | |||
231 | jack_data.mfld_jack = &mfld_jack; | 234 | jack_data.mfld_jack = &mfld_jack; |
232 | jack_data.intr_id = intr_status; | 235 | jack_data.intr_id = intr_status; |
233 | 236 | ||
234 | sn95031_jack_detection(&jack_data); | 237 | sn95031_jack_detection(mfld_codec, &jack_data); |
235 | /* TODO: add american headset detection post gpiolib support */ | 238 | /* TODO: add american headset detection post gpiolib support */ |
236 | } | 239 | } |
237 | 240 | ||
@@ -240,8 +243,6 @@ static int mfld_init(struct snd_soc_pcm_runtime *runtime) | |||
240 | struct snd_soc_dapm_context *dapm = &runtime->card->dapm; | 243 | struct snd_soc_dapm_context *dapm = &runtime->card->dapm; |
241 | int ret_val; | 244 | int ret_val; |
242 | 245 | ||
243 | mfld_codec = runtime->codec; | ||
244 | |||
245 | /* default is earpiece pin, userspace sets it explcitly */ | 246 | /* default is earpiece pin, userspace sets it explcitly */ |
246 | snd_soc_dapm_disable_pin(dapm, "Headphones"); | 247 | snd_soc_dapm_disable_pin(dapm, "Headphones"); |
247 | /* default is lineout NC, userspace sets it explcitly */ | 248 | /* default is lineout NC, userspace sets it explcitly */ |
@@ -254,20 +255,15 @@ static int mfld_init(struct snd_soc_pcm_runtime *runtime) | |||
254 | snd_soc_dapm_disable_pin(dapm, "LINEINR"); | 255 | snd_soc_dapm_disable_pin(dapm, "LINEINR"); |
255 | 256 | ||
256 | /* Headset and button jack detection */ | 257 | /* Headset and button jack detection */ |
257 | ret_val = snd_soc_jack_new(mfld_codec, "Intel(R) MID Audio Jack", | 258 | ret_val = snd_soc_card_jack_new(runtime->card, |
258 | SND_JACK_HEADSET | SND_JACK_BTN_0 | | 259 | "Intel(R) MID Audio Jack", SND_JACK_HEADSET | |
259 | SND_JACK_BTN_1, &mfld_jack); | 260 | SND_JACK_BTN_0 | SND_JACK_BTN_1, &mfld_jack, |
261 | mfld_jack_pins, ARRAY_SIZE(mfld_jack_pins)); | ||
260 | if (ret_val) { | 262 | if (ret_val) { |
261 | pr_err("jack creation failed\n"); | 263 | pr_err("jack creation failed\n"); |
262 | return ret_val; | 264 | return ret_val; |
263 | } | 265 | } |
264 | 266 | ||
265 | ret_val = snd_soc_jack_add_pins(&mfld_jack, | ||
266 | ARRAY_SIZE(mfld_jack_pins), mfld_jack_pins); | ||
267 | if (ret_val) { | ||
268 | pr_err("adding jack pins failed\n"); | ||
269 | return ret_val; | ||
270 | } | ||
271 | ret_val = snd_soc_jack_add_zones(&mfld_jack, | 267 | ret_val = snd_soc_jack_add_zones(&mfld_jack, |
272 | ARRAY_SIZE(mfld_zones), mfld_zones); | 268 | ARRAY_SIZE(mfld_zones), mfld_zones); |
273 | if (ret_val) { | 269 | if (ret_val) { |
@@ -275,6 +271,8 @@ static int mfld_init(struct snd_soc_pcm_runtime *runtime) | |||
275 | return ret_val; | 271 | return ret_val; |
276 | } | 272 | } |
277 | 273 | ||
274 | mfld_codec = runtime->codec; | ||
275 | |||
278 | /* we want to check if anything is inserted at boot, | 276 | /* we want to check if anything is inserted at boot, |
279 | * so send a fake event to codec and it will read adc | 277 | * so send a fake event to codec and it will read adc |
280 | * to find if anything is there or not */ | 278 | * to find if anything is there or not */ |
@@ -359,8 +357,6 @@ static irqreturn_t snd_mfld_jack_detection(int irq, void *data) | |||
359 | { | 357 | { |
360 | struct mfld_mc_private *mc_drv_ctx = (struct mfld_mc_private *) data; | 358 | struct mfld_mc_private *mc_drv_ctx = (struct mfld_mc_private *) data; |
361 | 359 | ||
362 | if (mfld_jack.codec == NULL) | ||
363 | return IRQ_HANDLED; | ||
364 | mfld_jack_check(mc_drv_ctx->interrupt_status); | 360 | mfld_jack_check(mc_drv_ctx->interrupt_status); |
365 | 361 | ||
366 | return IRQ_HANDLED; | 362 | return IRQ_HANDLED; |
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 | ||
666 | static int sst_soc_probe(struct snd_soc_platform *platform) | 668 | static 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 | |||
737 | static 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 | |||
759 | static 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 | |||
784 | static const struct dev_pm_ops sst_platform_pm = { | ||
785 | .prepare = sst_soc_prepare, | ||
786 | .complete = sst_soc_complete, | ||
787 | }; | ||
788 | |||
730 | static struct platform_driver sst_platform_driver = { | 789 | static 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 | }; |
178 | int sst_register_dsp(struct sst_device *sst); | 179 | int sst_register_dsp(struct sst_device *sst); |
179 | int sst_unregister_dsp(struct sst_device *sst); | 180 | int 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 | ||
426 | static int intel_sst_runtime_resume(struct device *dev) | 426 | static 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; | ||
492 | ddr: | ||
493 | kfree(fw_save->sram); | ||
494 | sram: | ||
495 | kfree(fw_save->dram); | ||
496 | dram: | ||
497 | kfree(fw_save->iram); | ||
498 | iram: | ||
499 | kfree(fw_save); | ||
500 | return ret; | ||
501 | } | ||
502 | |||
503 | static 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 | ||
441 | const struct dev_pm_ops intel_sst_pm = { | 552 | const 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 | }; |
445 | EXPORT_SYMBOL_GPL(intel_sst_pm); | 557 | EXPORT_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 | ||
340 | struct 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, | |||
544 | int sst_context_init(struct intel_sst_drv *ctx); | 553 | int sst_context_init(struct intel_sst_drv *ctx); |
545 | void sst_context_cleanup(struct intel_sst_drv *ctx); | 554 | void sst_context_cleanup(struct intel_sst_drv *ctx); |
546 | void sst_configure_runtime_pm(struct intel_sst_drv *ctx); | 555 | void sst_configure_runtime_pm(struct intel_sst_drv *ctx); |
556 | void memcpy32_toio(void __iomem *dst, const void *src, int count); | ||
557 | void 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, | |||
138 | static int sst_power_control(struct device *dev, bool state) | 138 | static 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 | ||
599 | static 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 | |||
614 | static 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 | |||
575 | static int sst_stream_init(struct device *dev, struct pcm_stream_info *str_info) | 628 | static 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 | ||
42 | static inline void memcpy32_toio(void __iomem *dst, const void *src, int count) | 42 | void 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 | |||
50 | void 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 |