diff options
author | Mark Brown <broonie@linaro.org> | 2014-08-15 07:51:28 -0400 |
---|---|---|
committer | Mark Brown <broonie@linaro.org> | 2014-08-15 07:51:28 -0400 |
commit | 543c675482bcf1e7b9f85bb1589314f38f60c520 (patch) | |
tree | 904f425393ac99539827d3164d2b0f78ac1607c5 /sound/soc/intel | |
parent | 2fa4a285ddfd39cfa711da3f5e898ec2ce80ef87 (diff) | |
parent | ae34a78c430c37c06404f032fb04e51315204281 (diff) |
Merge tag 'asoc-v3.17' into asoc-linus
ASoC: Updates for v3.17
This has been a pretty exciting release in terms of the framework, we've
finally got support for multiple CODECs attached to a single DAI link
which has been something there's been interest in as long as I've been
working on ASoC. A big thanks to Benoit and Misael for their work on
this.
Otherwise it's been a fairly standard release for development, including
more componentisation work from Lars-Peter and a good selection of both
CODEC and CPU drivers.
- Support for multiple CODECs attached to a single DAI, enabling
systems with for example multiple DAC/speaker drivers on a single
link, contributed by Benoit Cousson based on work from Misael Lopez
Cruz.
- Support for byte controls larger than 256 bytes based on the use of
TLVs contributed by Omair Mohammed Abdullah.
- More componentisation work from Lars-Peter Clausen.
- The remainder of the conversions of CODEC drivers to params_width()
- Drivers for Cirrus Logic CS4265, Freescale i.MX ASRC blocks, Realtek
RT286 and RT5670, Rockchip RK3xxx I2S controllers and Texas Instruments
TAS2552.
- Lots of updates and fixes, especially to the DaVinci, Intel,
Freescale, Realtek, and rcar drivers.
# gpg: Signature made Mon 04 Aug 2014 17:13:21 BST using RSA key ID 7EA229BD
# gpg: Good signature from "Mark Brown <broonie@sirena.org.uk>"
# gpg: aka "Mark Brown <broonie@debian.org>"
# gpg: aka "Mark Brown <broonie@kernel.org>"
# gpg: aka "Mark Brown <broonie@tardis.ed.ac.uk>"
# gpg: aka "Mark Brown <broonie@linaro.org>"
# gpg: aka "Mark Brown <Mark.Brown@linaro.org>"
Diffstat (limited to 'sound/soc/intel')
-rw-r--r-- | sound/soc/intel/Kconfig | 12 | ||||
-rw-r--r-- | sound/soc/intel/Makefile | 2 | ||||
-rw-r--r-- | sound/soc/intel/broadwell.c | 251 | ||||
-rw-r--r-- | sound/soc/intel/byt-max98090.c | 8 | ||||
-rw-r--r-- | sound/soc/intel/byt-rt5640.c | 1 | ||||
-rw-r--r-- | sound/soc/intel/sst-atom-controls.h | 30 | ||||
-rw-r--r-- | sound/soc/intel/sst-baytrail-ipc.c | 30 | ||||
-rw-r--r-- | sound/soc/intel/sst-dsp.c | 10 | ||||
-rw-r--r-- | sound/soc/intel/sst-dsp.h | 39 | ||||
-rw-r--r-- | sound/soc/intel/sst-haswell-dsp.c | 57 | ||||
-rw-r--r-- | sound/soc/intel/sst-haswell-ipc.c | 40 | ||||
-rw-r--r-- | sound/soc/intel/sst-mfld-dsp.h | 429 | ||||
-rw-r--r-- | sound/soc/intel/sst-mfld-platform-compress.c | 11 | ||||
-rw-r--r-- | sound/soc/intel/sst-mfld-platform-pcm.c | 319 | ||||
-rw-r--r-- | sound/soc/intel/sst-mfld-platform.h | 29 |
15 files changed, 1118 insertions, 150 deletions
diff --git a/sound/soc/intel/Kconfig b/sound/soc/intel/Kconfig index c30fedb3e149..f5b4a9c79cdf 100644 --- a/sound/soc/intel/Kconfig +++ b/sound/soc/intel/Kconfig | |||
@@ -58,3 +58,15 @@ config SND_SOC_INTEL_BYT_MAX98090_MACH | |||
58 | help | 58 | help |
59 | This adds audio driver for Intel Baytrail platform based boards | 59 | This adds audio driver for Intel Baytrail platform based boards |
60 | with the MAX98090 audio codec. | 60 | with the MAX98090 audio codec. |
61 | |||
62 | config SND_SOC_INTEL_BROADWELL_MACH | ||
63 | tristate "ASoC Audio DSP support for Intel Broadwell Wildcatpoint" | ||
64 | depends on SND_SOC_INTEL_SST && X86_INTEL_LPSS && DW_DMAC | ||
65 | select SND_SOC_INTEL_HASWELL | ||
66 | select SND_COMPRESS_OFFLOAD | ||
67 | select SND_SOC_RT286 | ||
68 | help | ||
69 | This adds support for the Wilcatpoint Audio DSP on Intel(R) Broadwell | ||
70 | Ultrabook platforms. | ||
71 | Say Y if you have such a device | ||
72 | If unsure select "N". | ||
diff --git a/sound/soc/intel/Makefile b/sound/soc/intel/Makefile index 4bfca79a42ba..7acbfc43a0c6 100644 --- a/sound/soc/intel/Makefile +++ b/sound/soc/intel/Makefile | |||
@@ -24,7 +24,9 @@ obj-$(CONFIG_SND_SOC_INTEL_BAYTRAIL) += snd-soc-sst-baytrail-pcm.o | |||
24 | snd-soc-sst-haswell-objs := haswell.o | 24 | snd-soc-sst-haswell-objs := haswell.o |
25 | snd-soc-sst-byt-rt5640-mach-objs := byt-rt5640.o | 25 | snd-soc-sst-byt-rt5640-mach-objs := byt-rt5640.o |
26 | snd-soc-sst-byt-max98090-mach-objs := byt-max98090.o | 26 | snd-soc-sst-byt-max98090-mach-objs := byt-max98090.o |
27 | snd-soc-sst-broadwell-objs := broadwell.o | ||
27 | 28 | ||
28 | obj-$(CONFIG_SND_SOC_INTEL_HASWELL_MACH) += snd-soc-sst-haswell.o | 29 | obj-$(CONFIG_SND_SOC_INTEL_HASWELL_MACH) += snd-soc-sst-haswell.o |
29 | obj-$(CONFIG_SND_SOC_INTEL_BYT_RT5640_MACH) += snd-soc-sst-byt-rt5640-mach.o | 30 | obj-$(CONFIG_SND_SOC_INTEL_BYT_RT5640_MACH) += snd-soc-sst-byt-rt5640-mach.o |
30 | obj-$(CONFIG_SND_SOC_INTEL_BYT_MAX98090_MACH) += snd-soc-sst-byt-max98090-mach.o | 31 | obj-$(CONFIG_SND_SOC_INTEL_BYT_MAX98090_MACH) += snd-soc-sst-byt-max98090-mach.o |
32 | obj-$(CONFIG_SND_SOC_INTEL_BROADWELL_MACH) += snd-soc-sst-broadwell.o | ||
diff --git a/sound/soc/intel/broadwell.c b/sound/soc/intel/broadwell.c new file mode 100644 index 000000000000..0e550f14028f --- /dev/null +++ b/sound/soc/intel/broadwell.c | |||
@@ -0,0 +1,251 @@ | |||
1 | /* | ||
2 | * Intel Broadwell Wildcatpoint SST Audio | ||
3 | * | ||
4 | * Copyright (C) 2013, Intel Corporation. All rights reserved. | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or | ||
7 | * modify it under the terms of the GNU General Public License version | ||
8 | * 2 as published by the Free Software Foundation. | ||
9 | * | ||
10 | * This program is distributed in the hope that it will be useful, | ||
11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
13 | * GNU General Public License for more details. | ||
14 | * | ||
15 | */ | ||
16 | |||
17 | #include <linux/module.h> | ||
18 | #include <linux/platform_device.h> | ||
19 | #include <sound/core.h> | ||
20 | #include <sound/pcm.h> | ||
21 | #include <sound/soc.h> | ||
22 | #include <sound/pcm_params.h> | ||
23 | |||
24 | #include "sst-dsp.h" | ||
25 | #include "sst-haswell-ipc.h" | ||
26 | |||
27 | #include "../codecs/rt286.h" | ||
28 | |||
29 | static const struct snd_soc_dapm_widget broadwell_widgets[] = { | ||
30 | SND_SOC_DAPM_HP("Headphones", NULL), | ||
31 | SND_SOC_DAPM_SPK("Speaker", NULL), | ||
32 | SND_SOC_DAPM_MIC("Mic Jack", NULL), | ||
33 | SND_SOC_DAPM_MIC("DMIC1", NULL), | ||
34 | SND_SOC_DAPM_MIC("DMIC2", NULL), | ||
35 | SND_SOC_DAPM_LINE("Line Jack", NULL), | ||
36 | }; | ||
37 | |||
38 | static const struct snd_soc_dapm_route broadwell_rt286_map[] = { | ||
39 | |||
40 | /* speaker */ | ||
41 | {"Speaker", NULL, "SPOR"}, | ||
42 | {"Speaker", NULL, "SPOL"}, | ||
43 | |||
44 | /* HP jack connectors - unknown if we have jack deteck */ | ||
45 | {"Headphones", NULL, "HPO Pin"}, | ||
46 | |||
47 | /* other jacks */ | ||
48 | {"MIC1", NULL, "Mic Jack"}, | ||
49 | {"LINE1", NULL, "Line Jack"}, | ||
50 | |||
51 | /* digital mics */ | ||
52 | {"DMIC1 Pin", NULL, "DMIC1"}, | ||
53 | {"DMIC2 Pin", NULL, "DMIC2"}, | ||
54 | |||
55 | /* CODEC BE connections */ | ||
56 | {"SSP0 CODEC IN", NULL, "AIF1 Capture"}, | ||
57 | {"AIF1 Playback", NULL, "SSP0 CODEC OUT"}, | ||
58 | }; | ||
59 | |||
60 | static int broadwell_ssp0_fixup(struct snd_soc_pcm_runtime *rtd, | ||
61 | struct snd_pcm_hw_params *params) | ||
62 | { | ||
63 | struct snd_interval *rate = hw_param_interval(params, | ||
64 | SNDRV_PCM_HW_PARAM_RATE); | ||
65 | struct snd_interval *channels = hw_param_interval(params, | ||
66 | SNDRV_PCM_HW_PARAM_CHANNELS); | ||
67 | |||
68 | /* The ADSP will covert the FE rate to 48k, stereo */ | ||
69 | rate->min = rate->max = 48000; | ||
70 | channels->min = channels->max = 2; | ||
71 | |||
72 | /* set SSP0 to 16 bit */ | ||
73 | snd_mask_set(¶ms->masks[SNDRV_PCM_HW_PARAM_FORMAT - | ||
74 | SNDRV_PCM_HW_PARAM_FIRST_MASK], | ||
75 | SNDRV_PCM_FORMAT_S16_LE); | ||
76 | return 0; | ||
77 | } | ||
78 | |||
79 | static int broadwell_rt286_hw_params(struct snd_pcm_substream *substream, | ||
80 | struct snd_pcm_hw_params *params) | ||
81 | { | ||
82 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | ||
83 | struct snd_soc_dai *codec_dai = rtd->codec_dai; | ||
84 | int ret; | ||
85 | |||
86 | ret = snd_soc_dai_set_sysclk(codec_dai, RT286_SCLK_S_PLL, 24000000, | ||
87 | SND_SOC_CLOCK_IN); | ||
88 | |||
89 | if (ret < 0) { | ||
90 | dev_err(rtd->dev, "can't set codec sysclk configuration\n"); | ||
91 | return ret; | ||
92 | } | ||
93 | |||
94 | return ret; | ||
95 | } | ||
96 | |||
97 | static struct snd_soc_ops broadwell_rt286_ops = { | ||
98 | .hw_params = broadwell_rt286_hw_params, | ||
99 | }; | ||
100 | |||
101 | static int broadwell_rtd_init(struct snd_soc_pcm_runtime *rtd) | ||
102 | { | ||
103 | struct snd_soc_codec *codec = rtd->codec; | ||
104 | struct snd_soc_dapm_context *dapm = &codec->dapm; | ||
105 | struct sst_pdata *pdata = dev_get_platdata(rtd->platform->dev); | ||
106 | struct sst_hsw *broadwell = pdata->dsp; | ||
107 | int ret; | ||
108 | |||
109 | /* Set ADSP SSP port settings */ | ||
110 | ret = sst_hsw_device_set_config(broadwell, SST_HSW_DEVICE_SSP_0, | ||
111 | SST_HSW_DEVICE_MCLK_FREQ_24_MHZ, | ||
112 | SST_HSW_DEVICE_CLOCK_MASTER, 9); | ||
113 | if (ret < 0) { | ||
114 | dev_err(rtd->dev, "error: failed to set device config\n"); | ||
115 | return ret; | ||
116 | } | ||
117 | |||
118 | /* always connected - check HP for jack detect */ | ||
119 | snd_soc_dapm_enable_pin(dapm, "Headphones"); | ||
120 | snd_soc_dapm_enable_pin(dapm, "Speaker"); | ||
121 | snd_soc_dapm_enable_pin(dapm, "Mic Jack"); | ||
122 | snd_soc_dapm_enable_pin(dapm, "Line Jack"); | ||
123 | snd_soc_dapm_enable_pin(dapm, "DMIC1"); | ||
124 | snd_soc_dapm_enable_pin(dapm, "DMIC2"); | ||
125 | |||
126 | return 0; | ||
127 | } | ||
128 | |||
129 | /* broadwell digital audio interface glue - connects codec <--> CPU */ | ||
130 | static struct snd_soc_dai_link broadwell_rt286_dais[] = { | ||
131 | /* Front End DAI links */ | ||
132 | { | ||
133 | .name = "System PCM", | ||
134 | .stream_name = "System Playback", | ||
135 | .cpu_dai_name = "System Pin", | ||
136 | .platform_name = "haswell-pcm-audio", | ||
137 | .dynamic = 1, | ||
138 | .codec_name = "snd-soc-dummy", | ||
139 | .codec_dai_name = "snd-soc-dummy-dai", | ||
140 | .init = broadwell_rtd_init, | ||
141 | .trigger = {SND_SOC_DPCM_TRIGGER_POST, SND_SOC_DPCM_TRIGGER_POST}, | ||
142 | .dpcm_playback = 1, | ||
143 | }, | ||
144 | { | ||
145 | .name = "Offload0", | ||
146 | .stream_name = "Offload0 Playback", | ||
147 | .cpu_dai_name = "Offload0 Pin", | ||
148 | .platform_name = "haswell-pcm-audio", | ||
149 | .dynamic = 1, | ||
150 | .codec_name = "snd-soc-dummy", | ||
151 | .codec_dai_name = "snd-soc-dummy-dai", | ||
152 | .trigger = {SND_SOC_DPCM_TRIGGER_POST, SND_SOC_DPCM_TRIGGER_POST}, | ||
153 | .dpcm_playback = 1, | ||
154 | }, | ||
155 | { | ||
156 | .name = "Offload1", | ||
157 | .stream_name = "Offload1 Playback", | ||
158 | .cpu_dai_name = "Offload1 Pin", | ||
159 | .platform_name = "haswell-pcm-audio", | ||
160 | .dynamic = 1, | ||
161 | .codec_name = "snd-soc-dummy", | ||
162 | .codec_dai_name = "snd-soc-dummy-dai", | ||
163 | .trigger = {SND_SOC_DPCM_TRIGGER_POST, SND_SOC_DPCM_TRIGGER_POST}, | ||
164 | .dpcm_playback = 1, | ||
165 | }, | ||
166 | { | ||
167 | .name = "Loopback PCM", | ||
168 | .stream_name = "Loopback", | ||
169 | .cpu_dai_name = "Loopback Pin", | ||
170 | .platform_name = "haswell-pcm-audio", | ||
171 | .dynamic = 0, | ||
172 | .codec_name = "snd-soc-dummy", | ||
173 | .codec_dai_name = "snd-soc-dummy-dai", | ||
174 | .trigger = {SND_SOC_DPCM_TRIGGER_POST, SND_SOC_DPCM_TRIGGER_POST}, | ||
175 | .dpcm_capture = 1, | ||
176 | }, | ||
177 | { | ||
178 | .name = "Capture PCM", | ||
179 | .stream_name = "Capture", | ||
180 | .cpu_dai_name = "Capture Pin", | ||
181 | .platform_name = "haswell-pcm-audio", | ||
182 | .dynamic = 1, | ||
183 | .codec_name = "snd-soc-dummy", | ||
184 | .codec_dai_name = "snd-soc-dummy-dai", | ||
185 | .trigger = {SND_SOC_DPCM_TRIGGER_POST, SND_SOC_DPCM_TRIGGER_POST}, | ||
186 | .dpcm_capture = 1, | ||
187 | }, | ||
188 | |||
189 | /* Back End DAI links */ | ||
190 | { | ||
191 | /* SSP0 - Codec */ | ||
192 | .name = "Codec", | ||
193 | .be_id = 0, | ||
194 | .cpu_dai_name = "snd-soc-dummy-dai", | ||
195 | .platform_name = "snd-soc-dummy", | ||
196 | .no_pcm = 1, | ||
197 | .codec_name = "i2c-INT343A:00", | ||
198 | .codec_dai_name = "rt286-aif1", | ||
199 | .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | | ||
200 | SND_SOC_DAIFMT_CBS_CFS, | ||
201 | .ignore_suspend = 1, | ||
202 | .ignore_pmdown_time = 1, | ||
203 | .be_hw_params_fixup = broadwell_ssp0_fixup, | ||
204 | .ops = &broadwell_rt286_ops, | ||
205 | .dpcm_playback = 1, | ||
206 | .dpcm_capture = 1, | ||
207 | }, | ||
208 | }; | ||
209 | |||
210 | /* broadwell audio machine driver for WPT + RT286S */ | ||
211 | static struct snd_soc_card broadwell_rt286 = { | ||
212 | .name = "broadwell-rt286", | ||
213 | .owner = THIS_MODULE, | ||
214 | .dai_link = broadwell_rt286_dais, | ||
215 | .num_links = ARRAY_SIZE(broadwell_rt286_dais), | ||
216 | .dapm_widgets = broadwell_widgets, | ||
217 | .num_dapm_widgets = ARRAY_SIZE(broadwell_widgets), | ||
218 | .dapm_routes = broadwell_rt286_map, | ||
219 | .num_dapm_routes = ARRAY_SIZE(broadwell_rt286_map), | ||
220 | .fully_routed = true, | ||
221 | }; | ||
222 | |||
223 | static int broadwell_audio_probe(struct platform_device *pdev) | ||
224 | { | ||
225 | broadwell_rt286.dev = &pdev->dev; | ||
226 | |||
227 | return snd_soc_register_card(&broadwell_rt286); | ||
228 | } | ||
229 | |||
230 | static int broadwell_audio_remove(struct platform_device *pdev) | ||
231 | { | ||
232 | snd_soc_unregister_card(&broadwell_rt286); | ||
233 | return 0; | ||
234 | } | ||
235 | |||
236 | static struct platform_driver broadwell_audio = { | ||
237 | .probe = broadwell_audio_probe, | ||
238 | .remove = broadwell_audio_remove, | ||
239 | .driver = { | ||
240 | .name = "broadwell-audio", | ||
241 | .owner = THIS_MODULE, | ||
242 | }, | ||
243 | }; | ||
244 | |||
245 | module_platform_driver(broadwell_audio) | ||
246 | |||
247 | /* Module information */ | ||
248 | MODULE_AUTHOR("Liam Girdwood, Xingchao Wang"); | ||
249 | MODULE_DESCRIPTION("Intel SST Audio for WPT/Broadwell"); | ||
250 | MODULE_LICENSE("GPL v2"); | ||
251 | MODULE_ALIAS("platform:broadwell-audio"); | ||
diff --git a/sound/soc/intel/byt-max98090.c b/sound/soc/intel/byt-max98090.c index 5cfb41ec3fab..b8b8af571ef1 100644 --- a/sound/soc/intel/byt-max98090.c +++ b/sound/soc/intel/byt-max98090.c | |||
@@ -63,14 +63,6 @@ static struct snd_soc_jack_pin hs_jack_pins[] = { | |||
63 | .pin = "Headset Mic", | 63 | .pin = "Headset Mic", |
64 | .mask = SND_JACK_MICROPHONE, | 64 | .mask = SND_JACK_MICROPHONE, |
65 | }, | 65 | }, |
66 | { | ||
67 | .pin = "Ext Spk", | ||
68 | .mask = SND_JACK_LINEOUT, | ||
69 | }, | ||
70 | { | ||
71 | .pin = "Int Mic", | ||
72 | .mask = SND_JACK_LINEIN, | ||
73 | }, | ||
74 | }; | 66 | }; |
75 | 67 | ||
76 | static struct snd_soc_jack_gpio hs_jack_gpios[] = { | 68 | static struct snd_soc_jack_gpio hs_jack_gpios[] = { |
diff --git a/sound/soc/intel/byt-rt5640.c b/sound/soc/intel/byt-rt5640.c index 53d160d39972..234a58de3c53 100644 --- a/sound/soc/intel/byt-rt5640.c +++ b/sound/soc/intel/byt-rt5640.c | |||
@@ -34,6 +34,7 @@ static const struct snd_soc_dapm_widget byt_rt5640_widgets[] = { | |||
34 | }; | 34 | }; |
35 | 35 | ||
36 | static const struct snd_soc_dapm_route byt_rt5640_audio_map[] = { | 36 | static const struct snd_soc_dapm_route byt_rt5640_audio_map[] = { |
37 | {"Headset Mic", NULL, "MICBIAS1"}, | ||
37 | {"IN2P", NULL, "Headset Mic"}, | 38 | {"IN2P", NULL, "Headset Mic"}, |
38 | {"IN2N", NULL, "Headset Mic"}, | 39 | {"IN2N", NULL, "Headset Mic"}, |
39 | {"DMIC1", NULL, "Internal Mic"}, | 40 | {"DMIC1", NULL, "Internal Mic"}, |
diff --git a/sound/soc/intel/sst-atom-controls.h b/sound/soc/intel/sst-atom-controls.h new file mode 100644 index 000000000000..14063ab8c7c5 --- /dev/null +++ b/sound/soc/intel/sst-atom-controls.h | |||
@@ -0,0 +1,30 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2013-14 Intel Corp | ||
3 | * Author: Ramesh Babu <ramesh.babu.koul@intel.com> | ||
4 | * Omair M Abdullah <omair.m.abdullah@intel.com> | ||
5 | * Samreen Nilofer <samreen.nilofer@intel.com> | ||
6 | * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or modify | ||
9 | * it under the terms of the GNU General Public License as published by | ||
10 | * the Free Software Foundation; version 2 of the License. | ||
11 | * | ||
12 | * This program is distributed in the hope that it will be useful, but | ||
13 | * WITHOUT ANY WARRANTY; without even the implied warranty of | ||
14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
15 | * General Public License for more details. | ||
16 | * | ||
17 | * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | ||
18 | * | ||
19 | */ | ||
20 | |||
21 | #ifndef __SST_CONTROLS_V2_H__ | ||
22 | #define __SST_CONTROLS_V2_H__ | ||
23 | |||
24 | enum { | ||
25 | MERR_DPCM_AUDIO = 0, | ||
26 | MERR_DPCM_COMPR, | ||
27 | }; | ||
28 | |||
29 | |||
30 | #endif | ||
diff --git a/sound/soc/intel/sst-baytrail-ipc.c b/sound/soc/intel/sst-baytrail-ipc.c index d207b22ea330..67673a2c0f41 100644 --- a/sound/soc/intel/sst-baytrail-ipc.c +++ b/sound/soc/intel/sst-baytrail-ipc.c | |||
@@ -122,6 +122,26 @@ struct sst_byt_tstamp { | |||
122 | u32 channel_peak[8]; | 122 | u32 channel_peak[8]; |
123 | } __packed; | 123 | } __packed; |
124 | 124 | ||
125 | struct sst_byt_fw_version { | ||
126 | u8 build; | ||
127 | u8 minor; | ||
128 | u8 major; | ||
129 | u8 type; | ||
130 | } __packed; | ||
131 | |||
132 | struct sst_byt_fw_build_info { | ||
133 | u8 date[16]; | ||
134 | u8 time[16]; | ||
135 | } __packed; | ||
136 | |||
137 | struct sst_byt_fw_init { | ||
138 | struct sst_byt_fw_version fw_version; | ||
139 | struct sst_byt_fw_build_info build_info; | ||
140 | u16 result; | ||
141 | u8 module_id; | ||
142 | u8 debug_info; | ||
143 | } __packed; | ||
144 | |||
125 | /* driver internal IPC message structure */ | 145 | /* driver internal IPC message structure */ |
126 | struct ipc_message { | 146 | struct ipc_message { |
127 | struct list_head list; | 147 | struct list_head list; |
@@ -868,6 +888,7 @@ int sst_byt_dsp_init(struct device *dev, struct sst_pdata *pdata) | |||
868 | { | 888 | { |
869 | struct sst_byt *byt; | 889 | struct sst_byt *byt; |
870 | struct sst_fw *byt_sst_fw; | 890 | struct sst_fw *byt_sst_fw; |
891 | struct sst_byt_fw_init init; | ||
871 | int err; | 892 | int err; |
872 | 893 | ||
873 | dev_dbg(dev, "initialising Byt DSP IPC\n"); | 894 | dev_dbg(dev, "initialising Byt DSP IPC\n"); |
@@ -929,6 +950,15 @@ int sst_byt_dsp_init(struct device *dev, struct sst_pdata *pdata) | |||
929 | goto boot_err; | 950 | goto boot_err; |
930 | } | 951 | } |
931 | 952 | ||
953 | /* show firmware information */ | ||
954 | sst_dsp_inbox_read(byt->dsp, &init, sizeof(init)); | ||
955 | dev_info(byt->dev, "FW version: %02x.%02x.%02x.%02x\n", | ||
956 | init.fw_version.major, init.fw_version.minor, | ||
957 | init.fw_version.build, init.fw_version.type); | ||
958 | dev_info(byt->dev, "Build type: %x\n", init.fw_version.type); | ||
959 | dev_info(byt->dev, "Build date: %s %s\n", | ||
960 | init.build_info.date, init.build_info.time); | ||
961 | |||
932 | pdata->dsp = byt; | 962 | pdata->dsp = byt; |
933 | byt->fw = byt_sst_fw; | 963 | byt->fw = byt_sst_fw; |
934 | 964 | ||
diff --git a/sound/soc/intel/sst-dsp.c b/sound/soc/intel/sst-dsp.c index 0b715b20a2d7..cd23060a0d86 100644 --- a/sound/soc/intel/sst-dsp.c +++ b/sound/soc/intel/sst-dsp.c | |||
@@ -224,19 +224,23 @@ EXPORT_SYMBOL_GPL(sst_dsp_shim_update_bits64); | |||
224 | 224 | ||
225 | void sst_dsp_dump(struct sst_dsp *sst) | 225 | void sst_dsp_dump(struct sst_dsp *sst) |
226 | { | 226 | { |
227 | sst->ops->dump(sst); | 227 | if (sst->ops->dump) |
228 | sst->ops->dump(sst); | ||
228 | } | 229 | } |
229 | EXPORT_SYMBOL_GPL(sst_dsp_dump); | 230 | EXPORT_SYMBOL_GPL(sst_dsp_dump); |
230 | 231 | ||
231 | void sst_dsp_reset(struct sst_dsp *sst) | 232 | void sst_dsp_reset(struct sst_dsp *sst) |
232 | { | 233 | { |
233 | sst->ops->reset(sst); | 234 | if (sst->ops->reset) |
235 | sst->ops->reset(sst); | ||
234 | } | 236 | } |
235 | EXPORT_SYMBOL_GPL(sst_dsp_reset); | 237 | EXPORT_SYMBOL_GPL(sst_dsp_reset); |
236 | 238 | ||
237 | int sst_dsp_boot(struct sst_dsp *sst) | 239 | int sst_dsp_boot(struct sst_dsp *sst) |
238 | { | 240 | { |
239 | sst->ops->boot(sst); | 241 | if (sst->ops->boot) |
242 | sst->ops->boot(sst); | ||
243 | |||
240 | return 0; | 244 | return 0; |
241 | } | 245 | } |
242 | EXPORT_SYMBOL_GPL(sst_dsp_boot); | 246 | EXPORT_SYMBOL_GPL(sst_dsp_boot); |
diff --git a/sound/soc/intel/sst-dsp.h b/sound/soc/intel/sst-dsp.h index e44423be66c4..3165dfa97408 100644 --- a/sound/soc/intel/sst-dsp.h +++ b/sound/soc/intel/sst-dsp.h | |||
@@ -52,7 +52,11 @@ | |||
52 | #define SST_CLKCTL 0x78 | 52 | #define SST_CLKCTL 0x78 |
53 | #define SST_CSR2 0x80 | 53 | #define SST_CSR2 0x80 |
54 | #define SST_LTRC 0xE0 | 54 | #define SST_LTRC 0xE0 |
55 | #define SST_HDMC 0xE8 | 55 | #define SST_HMDC 0xE8 |
56 | |||
57 | #define SST_SHIM_BEGIN SST_CSR | ||
58 | #define SST_SHIM_END SST_HDMC | ||
59 | |||
56 | #define SST_DBGO 0xF0 | 60 | #define SST_DBGO 0xF0 |
57 | 61 | ||
58 | #define SST_SHIM_SIZE 0x100 | 62 | #define SST_SHIM_SIZE 0x100 |
@@ -73,6 +77,8 @@ | |||
73 | #define SST_CSR_S0IOCS (0x1 << 21) | 77 | #define SST_CSR_S0IOCS (0x1 << 21) |
74 | #define SST_CSR_S1IOCS (0x1 << 23) | 78 | #define SST_CSR_S1IOCS (0x1 << 23) |
75 | #define SST_CSR_LPCS (0x1 << 31) | 79 | #define SST_CSR_LPCS (0x1 << 31) |
80 | #define SST_CSR_24MHZ_LPCS (SST_CSR_SBCS0 | SST_CSR_SBCS1 | SST_CSR_LPCS) | ||
81 | #define SST_CSR_24MHZ_NO_LPCS (SST_CSR_SBCS0 | SST_CSR_SBCS1) | ||
76 | #define SST_BYT_CSR_RST (0x1 << 0) | 82 | #define SST_BYT_CSR_RST (0x1 << 0) |
77 | #define SST_BYT_CSR_VECTOR_SEL (0x1 << 1) | 83 | #define SST_BYT_CSR_VECTOR_SEL (0x1 << 1) |
78 | #define SST_BYT_CSR_STALL (0x1 << 2) | 84 | #define SST_BYT_CSR_STALL (0x1 << 2) |
@@ -92,6 +98,14 @@ | |||
92 | #define SST_IMRX_DONE (0x1 << 0) | 98 | #define SST_IMRX_DONE (0x1 << 0) |
93 | #define SST_BYT_IMRX_REQUEST (0x1 << 1) | 99 | #define SST_BYT_IMRX_REQUEST (0x1 << 1) |
94 | 100 | ||
101 | /* IMRD / IMD */ | ||
102 | #define SST_IMRD_DONE (0x1 << 0) | ||
103 | #define SST_IMRD_BUSY (0x1 << 1) | ||
104 | #define SST_IMRD_SSP0 (0x1 << 16) | ||
105 | #define SST_IMRD_DMAC0 (0x1 << 21) | ||
106 | #define SST_IMRD_DMAC1 (0x1 << 22) | ||
107 | #define SST_IMRD_DMAC (SST_IMRD_DMAC0 | SST_IMRD_DMAC1) | ||
108 | |||
95 | /* IPCX / IPCC */ | 109 | /* IPCX / IPCC */ |
96 | #define SST_IPCX_DONE (0x1 << 30) | 110 | #define SST_IPCX_DONE (0x1 << 30) |
97 | #define SST_IPCX_BUSY (0x1 << 31) | 111 | #define SST_IPCX_BUSY (0x1 << 31) |
@@ -118,9 +132,21 @@ | |||
118 | /* LTRC */ | 132 | /* LTRC */ |
119 | #define SST_LTRC_VAL(x) (x << 0) | 133 | #define SST_LTRC_VAL(x) (x << 0) |
120 | 134 | ||
121 | /* HDMC */ | 135 | /* HMDC */ |
122 | #define SST_HDMC_HDDA0(x) (x << 0) | 136 | #define SST_HMDC_HDDA0(x) (x << 0) |
123 | #define SST_HDMC_HDDA1(x) (x << 7) | 137 | #define SST_HMDC_HDDA1(x) (x << 7) |
138 | #define SST_HMDC_HDDA_E0_CH0 1 | ||
139 | #define SST_HMDC_HDDA_E0_CH1 2 | ||
140 | #define SST_HMDC_HDDA_E0_CH2 4 | ||
141 | #define SST_HMDC_HDDA_E0_CH3 8 | ||
142 | #define SST_HMDC_HDDA_E1_CH0 SST_HMDC_HDDA1(SST_HMDC_HDDA_E0_CH0) | ||
143 | #define SST_HMDC_HDDA_E1_CH1 SST_HMDC_HDDA1(SST_HMDC_HDDA_E0_CH1) | ||
144 | #define SST_HMDC_HDDA_E1_CH2 SST_HMDC_HDDA1(SST_HMDC_HDDA_E0_CH2) | ||
145 | #define SST_HMDC_HDDA_E1_CH3 SST_HMDC_HDDA1(SST_HMDC_HDDA_E0_CH3) | ||
146 | #define SST_HMDC_HDDA_E0_ALLCH (SST_HMDC_HDDA_E0_CH0 | SST_HMDC_HDDA_E0_CH1 | \ | ||
147 | SST_HMDC_HDDA_E0_CH2 | SST_HMDC_HDDA_E0_CH3) | ||
148 | #define SST_HMDC_HDDA_E1_ALLCH (SST_HMDC_HDDA_E1_CH0 | SST_HMDC_HDDA_E1_CH1 | \ | ||
149 | SST_HMDC_HDDA_E1_CH2 | SST_HMDC_HDDA_E1_CH3) | ||
124 | 150 | ||
125 | 151 | ||
126 | /* SST Vendor Defined Registers and bits */ | 152 | /* SST Vendor Defined Registers and bits */ |
@@ -130,11 +156,16 @@ | |||
130 | #define SST_VDRTCTL3 0xaC | 156 | #define SST_VDRTCTL3 0xaC |
131 | 157 | ||
132 | /* VDRTCTL0 */ | 158 | /* VDRTCTL0 */ |
159 | #define SST_VDRTCL0_APLLSE_MASK 1 | ||
133 | #define SST_VDRTCL0_DSRAMPGE_SHIFT 16 | 160 | #define SST_VDRTCL0_DSRAMPGE_SHIFT 16 |
134 | #define SST_VDRTCL0_DSRAMPGE_MASK (0xffff << SST_VDRTCL0_DSRAMPGE_SHIFT) | 161 | #define SST_VDRTCL0_DSRAMPGE_MASK (0xffff << SST_VDRTCL0_DSRAMPGE_SHIFT) |
135 | #define SST_VDRTCL0_ISRAMPGE_SHIFT 6 | 162 | #define SST_VDRTCL0_ISRAMPGE_SHIFT 6 |
136 | #define SST_VDRTCL0_ISRAMPGE_MASK (0x3ff << SST_VDRTCL0_ISRAMPGE_SHIFT) | 163 | #define SST_VDRTCL0_ISRAMPGE_MASK (0x3ff << SST_VDRTCL0_ISRAMPGE_SHIFT) |
137 | 164 | ||
165 | /* PMCS */ | ||
166 | #define SST_PMCS 0x84 | ||
167 | #define SST_PMCS_PS_MASK 0x3 | ||
168 | |||
138 | struct sst_dsp; | 169 | struct sst_dsp; |
139 | 170 | ||
140 | /* | 171 | /* |
diff --git a/sound/soc/intel/sst-haswell-dsp.c b/sound/soc/intel/sst-haswell-dsp.c index a33b931181dc..4b6c163c10ff 100644 --- a/sound/soc/intel/sst-haswell-dsp.c +++ b/sound/soc/intel/sst-haswell-dsp.c | |||
@@ -28,9 +28,6 @@ | |||
28 | #include <linux/firmware.h> | 28 | #include <linux/firmware.h> |
29 | #include <linux/pm_runtime.h> | 29 | #include <linux/pm_runtime.h> |
30 | 30 | ||
31 | #include <linux/acpi.h> | ||
32 | #include <acpi/acpi_bus.h> | ||
33 | |||
34 | #include "sst-dsp.h" | 31 | #include "sst-dsp.h" |
35 | #include "sst-dsp-priv.h" | 32 | #include "sst-dsp-priv.h" |
36 | #include "sst-haswell-ipc.h" | 33 | #include "sst-haswell-ipc.h" |
@@ -272,9 +269,9 @@ static void hsw_boot(struct sst_dsp *sst) | |||
272 | SST_CSR2_SDFD_SSP1); | 269 | SST_CSR2_SDFD_SSP1); |
273 | 270 | ||
274 | /* enable DMA engine 0,1 all channels to access host memory */ | 271 | /* enable DMA engine 0,1 all channels to access host memory */ |
275 | sst_dsp_shim_update_bits_unlocked(sst, SST_HDMC, | 272 | sst_dsp_shim_update_bits_unlocked(sst, SST_HMDC, |
276 | SST_HDMC_HDDA1(0xff) | SST_HDMC_HDDA0(0xff), | 273 | SST_HMDC_HDDA1(0xff) | SST_HMDC_HDDA0(0xff), |
277 | SST_HDMC_HDDA1(0xff) | SST_HDMC_HDDA0(0xff)); | 274 | SST_HMDC_HDDA1(0xff) | SST_HMDC_HDDA0(0xff)); |
278 | 275 | ||
279 | /* disable all clock gating */ | 276 | /* disable all clock gating */ |
280 | writel(0x0, sst->addr.pci_cfg + SST_VDRTCTL2); | 277 | writel(0x0, sst->addr.pci_cfg + SST_VDRTCTL2); |
@@ -313,9 +310,7 @@ static const struct sst_adsp_memregion lp_region[] = { | |||
313 | 310 | ||
314 | /* wild cat point ADSP mem regions */ | 311 | /* wild cat point ADSP mem regions */ |
315 | static const struct sst_adsp_memregion wpt_region[] = { | 312 | static const struct sst_adsp_memregion wpt_region[] = { |
316 | {0x00000, 0x40000, 8, SST_MEM_DRAM}, /* D-SRAM0 - 8 * 32kB */ | 313 | {0x00000, 0xA0000, 20, SST_MEM_DRAM}, /* D-SRAM0,D-SRAM1,D-SRAM2 - 20 * 32kB */ |
317 | {0x40000, 0x80000, 8, SST_MEM_DRAM}, /* D-SRAM1 - 8 * 32kB */ | ||
318 | {0x80000, 0xA0000, 4, SST_MEM_DRAM}, /* D-SRAM2 - 4 * 32kB */ | ||
319 | {0xA0000, 0xF0000, 10, SST_MEM_IRAM}, /* I-SRAM - 10 * 32kB */ | 314 | {0xA0000, 0xF0000, 10, SST_MEM_IRAM}, /* I-SRAM - 10 * 32kB */ |
320 | }; | 315 | }; |
321 | 316 | ||
@@ -339,21 +334,40 @@ static int hsw_acpi_resource_map(struct sst_dsp *sst, struct sst_pdata *pdata) | |||
339 | return 0; | 334 | return 0; |
340 | } | 335 | } |
341 | 336 | ||
337 | struct sst_sram_shift { | ||
338 | u32 dev_id; /* SST Device IDs */ | ||
339 | u32 iram_shift; | ||
340 | u32 dram_shift; | ||
341 | }; | ||
342 | |||
343 | static const struct sst_sram_shift sram_shift[] = { | ||
344 | {SST_DEV_ID_LYNX_POINT, 6, 16}, /* lp */ | ||
345 | {SST_DEV_ID_WILDCAT_POINT, 2, 12}, /* wpt */ | ||
346 | }; | ||
342 | static u32 hsw_block_get_bit(struct sst_mem_block *block) | 347 | static u32 hsw_block_get_bit(struct sst_mem_block *block) |
343 | { | 348 | { |
344 | u32 bit = 0, shift = 0; | 349 | u32 bit = 0, shift = 0, index; |
350 | struct sst_dsp *sst = block->dsp; | ||
345 | 351 | ||
346 | switch (block->type) { | 352 | for (index = 0; index < ARRAY_SIZE(sram_shift); index++) { |
347 | case SST_MEM_DRAM: | 353 | if (sram_shift[index].dev_id == sst->id) |
348 | shift = 16; | 354 | break; |
349 | break; | ||
350 | case SST_MEM_IRAM: | ||
351 | shift = 6; | ||
352 | break; | ||
353 | default: | ||
354 | return 0; | ||
355 | } | 355 | } |
356 | 356 | ||
357 | if (index < ARRAY_SIZE(sram_shift)) { | ||
358 | switch (block->type) { | ||
359 | case SST_MEM_DRAM: | ||
360 | shift = sram_shift[index].dram_shift; | ||
361 | break; | ||
362 | case SST_MEM_IRAM: | ||
363 | shift = sram_shift[index].iram_shift; | ||
364 | break; | ||
365 | default: | ||
366 | shift = 0; | ||
367 | } | ||
368 | } else | ||
369 | shift = 0; | ||
370 | |||
357 | bit = 1 << (block->index + shift); | 371 | bit = 1 << (block->index + shift); |
358 | 372 | ||
359 | return bit; | 373 | return bit; |
@@ -501,8 +515,9 @@ static int hsw_init(struct sst_dsp *sst, struct sst_pdata *pdata) | |||
501 | } | 515 | } |
502 | } | 516 | } |
503 | 517 | ||
504 | /* set default power gating mask */ | 518 | /* set default power gating control, enable power gating control for all blocks. that is, |
505 | writel(0x0, sst->addr.pci_cfg + SST_VDRTCTL0); | 519 | can't be accessed, please enable each block before accessing. */ |
520 | writel(0xffffffff, sst->addr.pci_cfg + SST_VDRTCTL0); | ||
506 | 521 | ||
507 | return 0; | 522 | return 0; |
508 | } | 523 | } |
diff --git a/sound/soc/intel/sst-haswell-ipc.c b/sound/soc/intel/sst-haswell-ipc.c index 434236343ddf..b6291516dbbf 100644 --- a/sound/soc/intel/sst-haswell-ipc.c +++ b/sound/soc/intel/sst-haswell-ipc.c | |||
@@ -183,7 +183,7 @@ struct sst_hsw_ipc_fw_ready { | |||
183 | u32 inbox_size; | 183 | u32 inbox_size; |
184 | u32 outbox_size; | 184 | u32 outbox_size; |
185 | u32 fw_info_size; | 185 | u32 fw_info_size; |
186 | u8 fw_info[1]; | 186 | u8 fw_info[IPC_MAX_MAILBOX_BYTES - 5 * sizeof(u32)]; |
187 | } __attribute__((packed)); | 187 | } __attribute__((packed)); |
188 | 188 | ||
189 | struct ipc_message { | 189 | struct ipc_message { |
@@ -457,9 +457,10 @@ static void ipc_tx_msgs(struct kthread_work *work) | |||
457 | return; | 457 | return; |
458 | } | 458 | } |
459 | 459 | ||
460 | /* if the DSP is busy we will TX messages after IRQ */ | 460 | /* if the DSP is busy, we will TX messages after IRQ. |
461 | * also postpone if we are in the middle of procesing completion irq*/ | ||
461 | ipcx = sst_dsp_shim_read_unlocked(hsw->dsp, SST_IPCX); | 462 | ipcx = sst_dsp_shim_read_unlocked(hsw->dsp, SST_IPCX); |
462 | if (ipcx & SST_IPCX_BUSY) { | 463 | if (ipcx & (SST_IPCX_BUSY | SST_IPCX_DONE)) { |
463 | spin_unlock_irqrestore(&hsw->dsp->spinlock, flags); | 464 | spin_unlock_irqrestore(&hsw->dsp->spinlock, flags); |
464 | return; | 465 | return; |
465 | } | 466 | } |
@@ -502,6 +503,7 @@ static int tx_wait_done(struct sst_hsw *hsw, struct ipc_message *msg, | |||
502 | ipc_shim_dbg(hsw, "message timeout"); | 503 | ipc_shim_dbg(hsw, "message timeout"); |
503 | 504 | ||
504 | trace_ipc_error("error message timeout for", msg->header); | 505 | trace_ipc_error("error message timeout for", msg->header); |
506 | list_del(&msg->list); | ||
505 | ret = -ETIMEDOUT; | 507 | ret = -ETIMEDOUT; |
506 | } else { | 508 | } else { |
507 | 509 | ||
@@ -569,6 +571,9 @@ static void hsw_fw_ready(struct sst_hsw *hsw, u32 header) | |||
569 | { | 571 | { |
570 | struct sst_hsw_ipc_fw_ready fw_ready; | 572 | struct sst_hsw_ipc_fw_ready fw_ready; |
571 | u32 offset; | 573 | u32 offset; |
574 | u8 fw_info[IPC_MAX_MAILBOX_BYTES - 5 * sizeof(u32)]; | ||
575 | char *tmp[5], *pinfo; | ||
576 | int i = 0; | ||
572 | 577 | ||
573 | offset = (header & 0x1FFFFFFF) << 3; | 578 | offset = (header & 0x1FFFFFFF) << 3; |
574 | 579 | ||
@@ -589,6 +594,19 @@ static void hsw_fw_ready(struct sst_hsw *hsw, u32 header) | |||
589 | fw_ready.inbox_offset, fw_ready.inbox_size); | 594 | fw_ready.inbox_offset, fw_ready.inbox_size); |
590 | dev_dbg(hsw->dev, " mailbox downstream 0x%x - size 0x%x\n", | 595 | dev_dbg(hsw->dev, " mailbox downstream 0x%x - size 0x%x\n", |
591 | fw_ready.outbox_offset, fw_ready.outbox_size); | 596 | fw_ready.outbox_offset, fw_ready.outbox_size); |
597 | if (fw_ready.fw_info_size < sizeof(fw_ready.fw_info)) { | ||
598 | fw_ready.fw_info[fw_ready.fw_info_size] = 0; | ||
599 | dev_dbg(hsw->dev, " Firmware info: %s \n", fw_ready.fw_info); | ||
600 | |||
601 | /* log the FW version info got from the mailbox here. */ | ||
602 | memcpy(fw_info, fw_ready.fw_info, fw_ready.fw_info_size); | ||
603 | pinfo = &fw_info[0]; | ||
604 | for (i = 0; i < sizeof(tmp) / sizeof(char *); i++) | ||
605 | tmp[i] = strsep(&pinfo, " "); | ||
606 | dev_info(hsw->dev, "FW loaded, mailbox readback FW info: type %s, - " | ||
607 | "version: %s.%s, build %s, source commit id: %s\n", | ||
608 | tmp[0], tmp[1], tmp[2], tmp[3], tmp[4]); | ||
609 | } | ||
592 | } | 610 | } |
593 | 611 | ||
594 | static void hsw_notification_work(struct work_struct *work) | 612 | static void hsw_notification_work(struct work_struct *work) |
@@ -671,7 +689,9 @@ static void hsw_stream_update(struct sst_hsw *hsw, struct ipc_message *msg) | |||
671 | switch (stream_msg) { | 689 | switch (stream_msg) { |
672 | case IPC_STR_STAGE_MESSAGE: | 690 | case IPC_STR_STAGE_MESSAGE: |
673 | case IPC_STR_NOTIFICATION: | 691 | case IPC_STR_NOTIFICATION: |
692 | break; | ||
674 | case IPC_STR_RESET: | 693 | case IPC_STR_RESET: |
694 | trace_ipc_notification("stream reset", stream->reply.stream_hw_id); | ||
675 | break; | 695 | break; |
676 | case IPC_STR_PAUSE: | 696 | case IPC_STR_PAUSE: |
677 | stream->running = false; | 697 | stream->running = false; |
@@ -762,7 +782,8 @@ static int hsw_process_reply(struct sst_hsw *hsw, u32 header) | |||
762 | } | 782 | } |
763 | 783 | ||
764 | /* update any stream states */ | 784 | /* update any stream states */ |
765 | hsw_stream_update(hsw, msg); | 785 | if (msg_get_global_type(header) == IPC_GLB_STREAM_MESSAGE) |
786 | hsw_stream_update(hsw, msg); | ||
766 | 787 | ||
767 | /* wake up and return the error if we have waiters on this message ? */ | 788 | /* wake up and return the error if we have waiters on this message ? */ |
768 | list_del(&msg->list); | 789 | list_del(&msg->list); |
@@ -1628,7 +1649,7 @@ int sst_hsw_dx_set_state(struct sst_hsw *hsw, | |||
1628 | enum sst_hsw_dx_state state, struct sst_hsw_ipc_dx_reply *dx) | 1649 | enum sst_hsw_dx_state state, struct sst_hsw_ipc_dx_reply *dx) |
1629 | { | 1650 | { |
1630 | u32 header, state_; | 1651 | u32 header, state_; |
1631 | int ret; | 1652 | int ret, item; |
1632 | 1653 | ||
1633 | header = IPC_GLB_TYPE(IPC_GLB_ENTER_DX_STATE); | 1654 | header = IPC_GLB_TYPE(IPC_GLB_ENTER_DX_STATE); |
1634 | state_ = state; | 1655 | state_ = state; |
@@ -1642,6 +1663,13 @@ int sst_hsw_dx_set_state(struct sst_hsw *hsw, | |||
1642 | return ret; | 1663 | return ret; |
1643 | } | 1664 | } |
1644 | 1665 | ||
1666 | for (item = 0; item < dx->entries_no; item++) { | ||
1667 | dev_dbg(hsw->dev, | ||
1668 | "Item[%d] offset[%x] - size[%x] - source[%x]\n", | ||
1669 | item, dx->mem_info[item].offset, | ||
1670 | dx->mem_info[item].size, | ||
1671 | dx->mem_info[item].source); | ||
1672 | } | ||
1645 | dev_dbg(hsw->dev, "ipc: got %d entry numbers for state %d\n", | 1673 | dev_dbg(hsw->dev, "ipc: got %d entry numbers for state %d\n", |
1646 | dx->entries_no, state); | 1674 | dx->entries_no, state); |
1647 | 1675 | ||
@@ -1775,8 +1803,6 @@ int sst_hsw_dsp_init(struct device *dev, struct sst_pdata *pdata) | |||
1775 | 1803 | ||
1776 | /* get the FW version */ | 1804 | /* get the FW version */ |
1777 | sst_hsw_fw_get_version(hsw, &version); | 1805 | sst_hsw_fw_get_version(hsw, &version); |
1778 | dev_info(hsw->dev, "FW loaded: type %d - version: %d.%d build %d\n", | ||
1779 | version.type, version.major, version.minor, version.build); | ||
1780 | 1806 | ||
1781 | /* get the globalmixer */ | 1807 | /* get the globalmixer */ |
1782 | ret = sst_hsw_mixer_get_info(hsw); | 1808 | ret = sst_hsw_mixer_get_info(hsw); |
diff --git a/sound/soc/intel/sst-mfld-dsp.h b/sound/soc/intel/sst-mfld-dsp.h index 8d482d76475a..4257263157cd 100644 --- a/sound/soc/intel/sst-mfld-dsp.h +++ b/sound/soc/intel/sst-mfld-dsp.h | |||
@@ -3,7 +3,7 @@ | |||
3 | /* | 3 | /* |
4 | * sst_mfld_dsp.h - Intel SST Driver for audio engine | 4 | * sst_mfld_dsp.h - Intel SST Driver for audio engine |
5 | * | 5 | * |
6 | * Copyright (C) 2008-12 Intel Corporation | 6 | * Copyright (C) 2008-14 Intel Corporation |
7 | * Authors: Vinod Koul <vinod.koul@linux.intel.com> | 7 | * Authors: Vinod Koul <vinod.koul@linux.intel.com> |
8 | * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | 8 | * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
9 | * | 9 | * |
@@ -19,6 +19,142 @@ | |||
19 | * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | 19 | * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
20 | */ | 20 | */ |
21 | 21 | ||
22 | #define SST_MAX_BIN_BYTES 1024 | ||
23 | |||
24 | #define MAX_DBG_RW_BYTES 80 | ||
25 | #define MAX_NUM_SCATTER_BUFFERS 8 | ||
26 | #define MAX_LOOP_BACK_DWORDS 8 | ||
27 | /* IPC base address and mailbox, timestamp offsets */ | ||
28 | #define SST_MAILBOX_SIZE 0x0400 | ||
29 | #define SST_MAILBOX_SEND 0x0000 | ||
30 | #define SST_TIME_STAMP 0x1800 | ||
31 | #define SST_TIME_STAMP_MRFLD 0x800 | ||
32 | #define SST_RESERVED_OFFSET 0x1A00 | ||
33 | #define SST_SCU_LPE_MAILBOX 0x1000 | ||
34 | #define SST_LPE_SCU_MAILBOX 0x1400 | ||
35 | #define SST_SCU_LPE_LOG_BUF (SST_SCU_LPE_MAILBOX+16) | ||
36 | #define PROCESS_MSG 0x80 | ||
37 | |||
38 | /* Message ID's for IPC messages */ | ||
39 | /* Bits B7: SST or IA/SC ; B6-B4: Msg Category; B3-B0: Msg Type */ | ||
40 | |||
41 | /* I2L Firmware/Codec Download msgs */ | ||
42 | #define IPC_IA_PREP_LIB_DNLD 0x01 | ||
43 | #define IPC_IA_LIB_DNLD_CMPLT 0x02 | ||
44 | #define IPC_IA_GET_FW_VERSION 0x04 | ||
45 | #define IPC_IA_GET_FW_BUILD_INF 0x05 | ||
46 | #define IPC_IA_GET_FW_INFO 0x06 | ||
47 | #define IPC_IA_GET_FW_CTXT 0x07 | ||
48 | #define IPC_IA_SET_FW_CTXT 0x08 | ||
49 | #define IPC_IA_PREPARE_SHUTDOWN 0x31 | ||
50 | /* I2L Codec Config/control msgs */ | ||
51 | #define IPC_PREP_D3 0x10 | ||
52 | #define IPC_IA_SET_CODEC_PARAMS 0x10 | ||
53 | #define IPC_IA_GET_CODEC_PARAMS 0x11 | ||
54 | #define IPC_IA_SET_PPP_PARAMS 0x12 | ||
55 | #define IPC_IA_GET_PPP_PARAMS 0x13 | ||
56 | #define IPC_SST_PERIOD_ELAPSED_MRFLD 0xA | ||
57 | #define IPC_IA_ALG_PARAMS 0x1A | ||
58 | #define IPC_IA_TUNING_PARAMS 0x1B | ||
59 | #define IPC_IA_SET_RUNTIME_PARAMS 0x1C | ||
60 | #define IPC_IA_SET_PARAMS 0x1 | ||
61 | #define IPC_IA_GET_PARAMS 0x2 | ||
62 | |||
63 | #define IPC_EFFECTS_CREATE 0xE | ||
64 | #define IPC_EFFECTS_DESTROY 0xF | ||
65 | |||
66 | /* I2L Stream config/control msgs */ | ||
67 | #define IPC_IA_ALLOC_STREAM_MRFLD 0x2 | ||
68 | #define IPC_IA_ALLOC_STREAM 0x20 /* Allocate a stream ID */ | ||
69 | #define IPC_IA_FREE_STREAM_MRFLD 0x03 | ||
70 | #define IPC_IA_FREE_STREAM 0x21 /* Free the stream ID */ | ||
71 | #define IPC_IA_SET_STREAM_PARAMS 0x22 | ||
72 | #define IPC_IA_SET_STREAM_PARAMS_MRFLD 0x12 | ||
73 | #define IPC_IA_GET_STREAM_PARAMS 0x23 | ||
74 | #define IPC_IA_PAUSE_STREAM 0x24 | ||
75 | #define IPC_IA_PAUSE_STREAM_MRFLD 0x4 | ||
76 | #define IPC_IA_RESUME_STREAM 0x25 | ||
77 | #define IPC_IA_RESUME_STREAM_MRFLD 0x5 | ||
78 | #define IPC_IA_DROP_STREAM 0x26 | ||
79 | #define IPC_IA_DROP_STREAM_MRFLD 0x07 | ||
80 | #define IPC_IA_DRAIN_STREAM 0x27 /* Short msg with str_id */ | ||
81 | #define IPC_IA_DRAIN_STREAM_MRFLD 0x8 | ||
82 | #define IPC_IA_CONTROL_ROUTING 0x29 | ||
83 | #define IPC_IA_VTSV_UPDATE_MODULES 0x20 | ||
84 | #define IPC_IA_VTSV_DETECTED 0x21 | ||
85 | |||
86 | #define IPC_IA_START_STREAM_MRFLD 0X06 | ||
87 | #define IPC_IA_START_STREAM 0x30 /* Short msg with str_id */ | ||
88 | |||
89 | #define IPC_IA_SET_GAIN_MRFLD 0x21 | ||
90 | /* Debug msgs */ | ||
91 | #define IPC_IA_DBG_MEM_READ 0x40 | ||
92 | #define IPC_IA_DBG_MEM_WRITE 0x41 | ||
93 | #define IPC_IA_DBG_LOOP_BACK 0x42 | ||
94 | #define IPC_IA_DBG_LOG_ENABLE 0x45 | ||
95 | #define IPC_IA_DBG_SET_PROBE_PARAMS 0x47 | ||
96 | |||
97 | /* L2I Firmware/Codec Download msgs */ | ||
98 | #define IPC_IA_FW_INIT_CMPLT 0x81 | ||
99 | #define IPC_IA_FW_INIT_CMPLT_MRFLD 0x01 | ||
100 | #define IPC_IA_FW_ASYNC_ERR_MRFLD 0x11 | ||
101 | |||
102 | /* L2I Codec Config/control msgs */ | ||
103 | #define IPC_SST_FRAGMENT_ELPASED 0x90 /* Request IA more data */ | ||
104 | |||
105 | #define IPC_SST_BUF_UNDER_RUN 0x92 /* PB Under run and stopped */ | ||
106 | #define IPC_SST_BUF_OVER_RUN 0x93 /* CAP Under run and stopped */ | ||
107 | #define IPC_SST_DRAIN_END 0x94 /* PB Drain complete and stopped */ | ||
108 | #define IPC_SST_CHNGE_SSP_PARAMS 0x95 /* PB SSP parameters changed */ | ||
109 | #define IPC_SST_STREAM_PROCESS_FATAL_ERR 0x96/* error in processing a stream */ | ||
110 | #define IPC_SST_PERIOD_ELAPSED 0x97 /* period elapsed */ | ||
111 | |||
112 | #define IPC_SST_ERROR_EVENT 0x99 /* Buffer over run occurred */ | ||
113 | /* L2S messages */ | ||
114 | #define IPC_SC_DDR_LINK_UP 0xC0 | ||
115 | #define IPC_SC_DDR_LINK_DOWN 0xC1 | ||
116 | #define IPC_SC_SET_LPECLK_REQ 0xC2 | ||
117 | #define IPC_SC_SSP_BIT_BANG 0xC3 | ||
118 | |||
119 | /* L2I Error reporting msgs */ | ||
120 | #define IPC_IA_MEM_ALLOC_FAIL 0xE0 | ||
121 | #define IPC_IA_PROC_ERR 0xE1 /* error in processing a | ||
122 | stream can be used by playback and | ||
123 | capture modules */ | ||
124 | |||
125 | /* L2I Debug msgs */ | ||
126 | #define IPC_IA_PRINT_STRING 0xF0 | ||
127 | |||
128 | /* Buffer under-run */ | ||
129 | #define IPC_IA_BUF_UNDER_RUN_MRFLD 0x0B | ||
130 | |||
131 | /* Mrfld specific defines: | ||
132 | * For asynchronous messages(INIT_CMPLT, PERIOD_ELAPSED, ASYNC_ERROR) | ||
133 | * received from FW, the format is: | ||
134 | * - IPC High: pvt_id is set to zero. Always short message. | ||
135 | * - msg_id is in lower 16-bits of IPC low payload. | ||
136 | * - pipe_id is in higher 16-bits of IPC low payload for period_elapsed. | ||
137 | * - error id is in higher 16-bits of IPC low payload for async errors. | ||
138 | */ | ||
139 | #define SST_ASYNC_DRV_ID 0 | ||
140 | |||
141 | /* Command Response or Acknowledge message to any IPC message will have | ||
142 | * same message ID and stream ID information which is sent. | ||
143 | * There is no specific Ack message ID. The data field is used as response | ||
144 | * meaning. | ||
145 | */ | ||
146 | enum ackData { | ||
147 | IPC_ACK_SUCCESS = 0, | ||
148 | IPC_ACK_FAILURE, | ||
149 | }; | ||
150 | |||
151 | enum ipc_ia_msg_id { | ||
152 | IPC_CMD = 1, /*!< Task Control message ID */ | ||
153 | IPC_SET_PARAMS = 2,/*!< Task Set param message ID */ | ||
154 | IPC_GET_PARAMS = 3, /*!< Task Get param message ID */ | ||
155 | IPC_INVALID = 0xFF, /*!<Task Get param message ID */ | ||
156 | }; | ||
157 | |||
22 | enum sst_codec_types { | 158 | enum sst_codec_types { |
23 | /* AUDIO/MUSIC CODEC Type Definitions */ | 159 | /* AUDIO/MUSIC CODEC Type Definitions */ |
24 | SST_CODEC_TYPE_UNKNOWN = 0, | 160 | SST_CODEC_TYPE_UNKNOWN = 0, |
@@ -35,14 +171,157 @@ enum stream_type { | |||
35 | SST_STREAM_TYPE_MUSIC = 1, | 171 | SST_STREAM_TYPE_MUSIC = 1, |
36 | }; | 172 | }; |
37 | 173 | ||
174 | enum sst_error_codes { | ||
175 | /* Error code,response to msgId: Description */ | ||
176 | /* Common error codes */ | ||
177 | SST_SUCCESS = 0, /* Success */ | ||
178 | SST_ERR_INVALID_STREAM_ID = 1, | ||
179 | SST_ERR_INVALID_MSG_ID = 2, | ||
180 | SST_ERR_INVALID_STREAM_OP = 3, | ||
181 | SST_ERR_INVALID_PARAMS = 4, | ||
182 | SST_ERR_INVALID_CODEC = 5, | ||
183 | SST_ERR_INVALID_MEDIA_TYPE = 6, | ||
184 | SST_ERR_STREAM_ERR = 7, | ||
185 | |||
186 | SST_ERR_STREAM_IN_USE = 15, | ||
187 | }; | ||
188 | |||
189 | struct ipc_dsp_hdr { | ||
190 | u16 mod_index_id:8; /*!< DSP Command ID specific to tasks */ | ||
191 | u16 pipe_id:8; /*!< instance of the module in the pipeline */ | ||
192 | u16 mod_id; /*!< Pipe_id */ | ||
193 | u16 cmd_id; /*!< Module ID = lpe_algo_types_t */ | ||
194 | u16 length; /*!< Length of the payload only */ | ||
195 | } __packed; | ||
196 | |||
197 | union ipc_header_high { | ||
198 | struct { | ||
199 | u32 msg_id:8; /* Message ID - Max 256 Message Types */ | ||
200 | u32 task_id:4; /* Task ID associated with this comand */ | ||
201 | u32 drv_id:4; /* Identifier for the driver to track*/ | ||
202 | u32 rsvd1:8; /* Reserved */ | ||
203 | u32 result:4; /* Reserved */ | ||
204 | u32 res_rqd:1; /* Response rqd */ | ||
205 | u32 large:1; /* Large Message if large = 1 */ | ||
206 | u32 done:1; /* bit 30 - Done bit */ | ||
207 | u32 busy:1; /* bit 31 - busy bit*/ | ||
208 | } part; | ||
209 | u32 full; | ||
210 | } __packed; | ||
211 | /* IPC header */ | ||
212 | union ipc_header_mrfld { | ||
213 | struct { | ||
214 | u32 header_low_payload; | ||
215 | union ipc_header_high header_high; | ||
216 | } p; | ||
217 | u64 full; | ||
218 | } __packed; | ||
219 | /* CAUTION NOTE: All IPC message body must be multiple of 32 bits.*/ | ||
220 | |||
221 | /* IPC Header */ | ||
222 | union ipc_header { | ||
223 | struct { | ||
224 | u32 msg_id:8; /* Message ID - Max 256 Message Types */ | ||
225 | u32 str_id:5; | ||
226 | u32 large:1; /* Large Message if large = 1 */ | ||
227 | u32 reserved:2; /* Reserved for future use */ | ||
228 | u32 data:14; /* Ack/Info for msg, size of msg in Mailbox */ | ||
229 | u32 done:1; /* bit 30 */ | ||
230 | u32 busy:1; /* bit 31 */ | ||
231 | } part; | ||
232 | u32 full; | ||
233 | } __packed; | ||
234 | |||
235 | /* Firmware build info */ | ||
236 | struct sst_fw_build_info { | ||
237 | unsigned char date[16]; /* Firmware build date */ | ||
238 | unsigned char time[16]; /* Firmware build time */ | ||
239 | } __packed; | ||
240 | |||
241 | /* Firmware Version info */ | ||
242 | struct snd_sst_fw_version { | ||
243 | u8 build; /* build number*/ | ||
244 | u8 minor; /* minor number*/ | ||
245 | u8 major; /* major number*/ | ||
246 | u8 type; /* build type */ | ||
247 | }; | ||
248 | |||
249 | struct ipc_header_fw_init { | ||
250 | struct snd_sst_fw_version fw_version;/* Firmware version details */ | ||
251 | struct sst_fw_build_info build_info; | ||
252 | u16 result; /* Fw init result */ | ||
253 | u8 module_id; /* Module ID in case of error */ | ||
254 | u8 debug_info; /* Debug info from Module ID in case of fail */ | ||
255 | } __packed; | ||
256 | |||
257 | struct snd_sst_tstamp { | ||
258 | u64 ring_buffer_counter; /* PB/CP: Bytes copied from/to DDR. */ | ||
259 | u64 hardware_counter; /* PB/CP: Bytes DMAed to/from SSP. */ | ||
260 | u64 frames_decoded; | ||
261 | u64 bytes_decoded; | ||
262 | u64 bytes_copied; | ||
263 | u32 sampling_frequency; | ||
264 | u32 channel_peak[8]; | ||
265 | } __packed; | ||
266 | |||
267 | /* Stream type params struture for Alloc stream */ | ||
268 | struct snd_sst_str_type { | ||
269 | u8 codec_type; /* Codec type */ | ||
270 | u8 str_type; /* 1 = voice 2 = music */ | ||
271 | u8 operation; /* Playback or Capture */ | ||
272 | u8 protected_str; /* 0=Non DRM, 1=DRM */ | ||
273 | u8 time_slots; | ||
274 | u8 reserved; /* Reserved */ | ||
275 | u16 result; /* Result used for acknowledgment */ | ||
276 | } __packed; | ||
277 | |||
278 | /* Library info structure */ | ||
279 | struct module_info { | ||
280 | u32 lib_version; | ||
281 | u32 lib_type;/*TBD- KLOCKWORK u8 lib_type;*/ | ||
282 | u32 media_type; | ||
283 | u8 lib_name[12]; | ||
284 | u32 lib_caps; | ||
285 | unsigned char b_date[16]; /* Lib build date */ | ||
286 | unsigned char b_time[16]; /* Lib build time */ | ||
287 | } __packed; | ||
288 | |||
289 | /* Library slot info */ | ||
290 | struct lib_slot_info { | ||
291 | u8 slot_num; /* 1 or 2 */ | ||
292 | u8 reserved1; | ||
293 | u16 reserved2; | ||
294 | u32 iram_size; /* slot size in IRAM */ | ||
295 | u32 dram_size; /* slot size in DRAM */ | ||
296 | u32 iram_offset; /* starting offset of slot in IRAM */ | ||
297 | u32 dram_offset; /* starting offset of slot in DRAM */ | ||
298 | } __packed; | ||
299 | |||
300 | struct snd_ppp_mixer_params { | ||
301 | __u32 type; /*Type of the parameter */ | ||
302 | __u32 size; | ||
303 | __u32 input_stream_bitmap; /*Input stream Bit Map*/ | ||
304 | } __packed; | ||
305 | |||
306 | struct snd_sst_lib_download { | ||
307 | struct module_info lib_info; /* library info type, capabilities etc */ | ||
308 | struct lib_slot_info slot_info; /* slot info to be downloaded */ | ||
309 | u32 mod_entry_pt; | ||
310 | }; | ||
311 | |||
312 | struct snd_sst_lib_download_info { | ||
313 | struct snd_sst_lib_download dload_lib; | ||
314 | u16 result; /* Result used for acknowledgment */ | ||
315 | u8 pvt_id; /* Private ID */ | ||
316 | u8 reserved; /* for alignment */ | ||
317 | }; | ||
38 | struct snd_pcm_params { | 318 | struct snd_pcm_params { |
39 | u8 num_chan; /* 1=Mono, 2=Stereo */ | 319 | u8 num_chan; /* 1=Mono, 2=Stereo */ |
40 | u8 pcm_wd_sz; /* 16/24 - bit*/ | 320 | u8 pcm_wd_sz; /* 16/24 - bit*/ |
41 | u32 reserved; /* Bitrate in bits per second */ | 321 | u8 use_offload_path; /* 0-PCM using period elpased & ALSA interfaces |
42 | u32 sfreq; /* Sampling rate in Hz */ | 322 | 1-PCM stream via compressed interface */ |
43 | u8 use_offload_path; | ||
44 | u8 reserved2; | 323 | u8 reserved2; |
45 | u16 reserved3; | 324 | u32 sfreq; /* Sampling rate in Hz */ |
46 | u8 channel_map[8]; | 325 | u8 channel_map[8]; |
47 | } __packed; | 326 | } __packed; |
48 | 327 | ||
@@ -76,6 +355,7 @@ struct snd_aac_params { | |||
76 | struct snd_wma_params { | 355 | struct snd_wma_params { |
77 | u8 num_chan; /* 1=Mono, 2=Stereo */ | 356 | u8 num_chan; /* 1=Mono, 2=Stereo */ |
78 | u8 pcm_wd_sz; /* 16/24 - bit*/ | 357 | u8 pcm_wd_sz; /* 16/24 - bit*/ |
358 | u16 reserved1; | ||
79 | u32 brate; /* Use the hard coded value. */ | 359 | u32 brate; /* Use the hard coded value. */ |
80 | u32 sfreq; /* Sampling freq eg. 8000, 441000, 48000 */ | 360 | u32 sfreq; /* Sampling freq eg. 8000, 441000, 48000 */ |
81 | u32 channel_mask; /* Channel Mask */ | 361 | u32 channel_mask; /* Channel Mask */ |
@@ -101,26 +381,153 @@ struct sst_address_info { | |||
101 | }; | 381 | }; |
102 | 382 | ||
103 | struct snd_sst_alloc_params_ext { | 383 | struct snd_sst_alloc_params_ext { |
104 | struct sst_address_info ring_buf_info[8]; | 384 | __u16 sg_count; |
105 | u8 sg_count; | 385 | __u16 reserved; |
106 | u8 reserved; | 386 | __u32 frag_size; /*Number of samples after which period elapsed |
107 | u16 reserved2; | ||
108 | u32 frag_size; /*Number of samples after which period elapsed | ||
109 | message is sent valid only if path = 0*/ | 387 | message is sent valid only if path = 0*/ |
110 | } __packed; | 388 | struct sst_address_info ring_buf_info[8]; |
389 | }; | ||
111 | 390 | ||
112 | struct snd_sst_stream_params { | 391 | struct snd_sst_stream_params { |
113 | union snd_sst_codec_params uc; | 392 | union snd_sst_codec_params uc; |
114 | } __packed; | 393 | } __packed; |
115 | 394 | ||
116 | struct snd_sst_params { | 395 | struct snd_sst_params { |
396 | u32 result; | ||
117 | u32 stream_id; | 397 | u32 stream_id; |
118 | u8 codec; | 398 | u8 codec; |
119 | u8 ops; | 399 | u8 ops; |
120 | u8 stream_type; | 400 | u8 stream_type; |
121 | u8 device_type; | 401 | u8 device_type; |
402 | u8 task; | ||
122 | struct snd_sst_stream_params sparams; | 403 | struct snd_sst_stream_params sparams; |
123 | struct snd_sst_alloc_params_ext aparams; | 404 | struct snd_sst_alloc_params_ext aparams; |
124 | }; | 405 | }; |
125 | 406 | ||
407 | struct snd_sst_alloc_mrfld { | ||
408 | u16 codec_type; | ||
409 | u8 operation; | ||
410 | u8 sg_count; | ||
411 | struct sst_address_info ring_buf_info[8]; | ||
412 | u32 frag_size; | ||
413 | u32 ts; | ||
414 | struct snd_sst_stream_params codec_params; | ||
415 | } __packed; | ||
416 | |||
417 | /* Alloc stream params structure */ | ||
418 | struct snd_sst_alloc_params { | ||
419 | struct snd_sst_str_type str_type; | ||
420 | struct snd_sst_stream_params stream_params; | ||
421 | struct snd_sst_alloc_params_ext alloc_params; | ||
422 | } __packed; | ||
423 | |||
424 | /* Alloc stream response message */ | ||
425 | struct snd_sst_alloc_response { | ||
426 | struct snd_sst_str_type str_type; /* Stream type for allocation */ | ||
427 | struct snd_sst_lib_download lib_dnld; /* Valid only for codec dnld */ | ||
428 | }; | ||
429 | |||
430 | /* Drop response */ | ||
431 | struct snd_sst_drop_response { | ||
432 | u32 result; | ||
433 | u32 bytes; | ||
434 | }; | ||
435 | |||
436 | struct snd_sst_async_msg { | ||
437 | u32 msg_id; /* Async msg id */ | ||
438 | u32 payload[0]; | ||
439 | }; | ||
440 | |||
441 | struct snd_sst_async_err_msg { | ||
442 | u32 fw_resp; /* Firmware Result */ | ||
443 | u32 lib_resp; /*Library result */ | ||
444 | } __packed; | ||
445 | |||
446 | struct snd_sst_vol { | ||
447 | u32 stream_id; | ||
448 | s32 volume; | ||
449 | u32 ramp_duration; | ||
450 | u32 ramp_type; /* Ramp type, default=0 */ | ||
451 | }; | ||
452 | |||
453 | /* Gain library parameters for mrfld | ||
454 | * based on DSP command spec v0.82 | ||
455 | */ | ||
456 | struct snd_sst_gain_v2 { | ||
457 | u16 gain_cell_num; /* num of gain cells to modify*/ | ||
458 | u8 cell_nbr_idx; /* instance index*/ | ||
459 | u8 cell_path_idx; /* pipe-id */ | ||
460 | u16 module_id; /*module id */ | ||
461 | u16 left_cell_gain; /* left gain value in dB*/ | ||
462 | u16 right_cell_gain; /* right gain value in dB*/ | ||
463 | u16 gain_time_const; /* gain time constant*/ | ||
464 | } __packed; | ||
465 | |||
466 | struct snd_sst_mute { | ||
467 | u32 stream_id; | ||
468 | u32 mute; | ||
469 | }; | ||
470 | |||
471 | struct snd_sst_runtime_params { | ||
472 | u8 type; | ||
473 | u8 str_id; | ||
474 | u8 size; | ||
475 | u8 rsvd; | ||
476 | void *addr; | ||
477 | } __packed; | ||
478 | |||
479 | enum stream_param_type { | ||
480 | SST_SET_TIME_SLOT = 0, | ||
481 | SST_SET_CHANNEL_INFO = 1, | ||
482 | OTHERS = 2, /*reserved for future params*/ | ||
483 | }; | ||
484 | |||
485 | /* CSV Voice call routing structure */ | ||
486 | struct snd_sst_control_routing { | ||
487 | u8 control; /* 0=start, 1=Stop */ | ||
488 | u8 reserved[3]; /* Reserved- for 32 bit alignment */ | ||
489 | }; | ||
490 | |||
491 | struct ipc_post { | ||
492 | struct list_head node; | ||
493 | union ipc_header header; /* driver specific */ | ||
494 | bool is_large; | ||
495 | bool is_process_reply; | ||
496 | union ipc_header_mrfld mrfld_header; | ||
497 | char *mailbox_data; | ||
498 | }; | ||
499 | |||
500 | struct snd_sst_ctxt_params { | ||
501 | u32 address; /* Physical Address in DDR where the context is stored */ | ||
502 | u32 size; /* size of the context */ | ||
503 | }; | ||
504 | |||
505 | struct snd_sst_lpe_log_params { | ||
506 | u8 dbg_type; | ||
507 | u8 module_id; | ||
508 | u8 log_level; | ||
509 | u8 reserved; | ||
510 | } __packed; | ||
511 | |||
512 | enum snd_sst_bytes_type { | ||
513 | SND_SST_BYTES_SET = 0x1, | ||
514 | SND_SST_BYTES_GET = 0x2, | ||
515 | }; | ||
516 | |||
517 | struct snd_sst_bytes_v2 { | ||
518 | u8 type; | ||
519 | u8 ipc_msg; | ||
520 | u8 block; | ||
521 | u8 task_id; | ||
522 | u8 pipe_id; | ||
523 | u8 rsvd; | ||
524 | u16 len; | ||
525 | char bytes[0]; | ||
526 | }; | ||
527 | |||
528 | #define MAX_VTSV_FILES 2 | ||
529 | struct snd_sst_vtsv_info { | ||
530 | struct sst_address_info vfiles[MAX_VTSV_FILES]; | ||
531 | } __packed; | ||
532 | |||
126 | #endif /* __SST_MFLD_DSP_H__ */ | 533 | #endif /* __SST_MFLD_DSP_H__ */ |
diff --git a/sound/soc/intel/sst-mfld-platform-compress.c b/sound/soc/intel/sst-mfld-platform-compress.c index 02abd19fce1d..29c059ca19e8 100644 --- a/sound/soc/intel/sst-mfld-platform-compress.c +++ b/sound/soc/intel/sst-mfld-platform-compress.c | |||
@@ -100,14 +100,19 @@ static int sst_platform_compr_set_params(struct snd_compr_stream *cstream, | |||
100 | int retval; | 100 | int retval; |
101 | struct snd_sst_params str_params; | 101 | struct snd_sst_params str_params; |
102 | struct sst_compress_cb cb; | 102 | struct sst_compress_cb cb; |
103 | struct snd_soc_pcm_runtime *rtd = cstream->private_data; | ||
104 | struct snd_soc_platform *platform = rtd->platform; | ||
105 | struct sst_data *ctx = snd_soc_platform_get_drvdata(platform); | ||
103 | 106 | ||
104 | stream = cstream->runtime->private_data; | 107 | stream = cstream->runtime->private_data; |
105 | /* construct fw structure for this*/ | 108 | /* construct fw structure for this*/ |
106 | memset(&str_params, 0, sizeof(str_params)); | 109 | memset(&str_params, 0, sizeof(str_params)); |
107 | 110 | ||
108 | str_params.ops = STREAM_OPS_PLAYBACK; | 111 | /* fill the device type and stream id to pass to SST driver */ |
109 | str_params.stream_type = SST_STREAM_TYPE_MUSIC; | 112 | retval = sst_fill_stream_params(cstream, ctx, &str_params, true); |
110 | str_params.device_type = SND_SST_DEVICE_COMPRESS; | 113 | pr_debug("compr_set_params: fill stream params ret_val = 0x%x\n", retval); |
114 | if (retval < 0) | ||
115 | return retval; | ||
111 | 116 | ||
112 | switch (params->codec.id) { | 117 | switch (params->codec.id) { |
113 | case SND_AUDIOCODEC_MP3: { | 118 | case SND_AUDIOCODEC_MP3: { |
diff --git a/sound/soc/intel/sst-mfld-platform-pcm.c b/sound/soc/intel/sst-mfld-platform-pcm.c index 7c790f51d259..706212a6a68c 100644 --- a/sound/soc/intel/sst-mfld-platform-pcm.c +++ b/sound/soc/intel/sst-mfld-platform-pcm.c | |||
@@ -1,7 +1,7 @@ | |||
1 | /* | 1 | /* |
2 | * sst_mfld_platform.c - Intel MID Platform driver | 2 | * sst_mfld_platform.c - Intel MID Platform driver |
3 | * | 3 | * |
4 | * Copyright (C) 2010-2013 Intel Corp | 4 | * Copyright (C) 2010-2014 Intel Corp |
5 | * Author: Vinod Koul <vinod.koul@intel.com> | 5 | * Author: Vinod Koul <vinod.koul@intel.com> |
6 | * Author: Harsha Priya <priya.harsha@intel.com> | 6 | * Author: Harsha Priya <priya.harsha@intel.com> |
7 | * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | 7 | * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
@@ -27,7 +27,9 @@ | |||
27 | #include <sound/pcm_params.h> | 27 | #include <sound/pcm_params.h> |
28 | #include <sound/soc.h> | 28 | #include <sound/soc.h> |
29 | #include <sound/compress_driver.h> | 29 | #include <sound/compress_driver.h> |
30 | #include <asm/platform_sst_audio.h> | ||
30 | #include "sst-mfld-platform.h" | 31 | #include "sst-mfld-platform.h" |
32 | #include "sst-atom-controls.h" | ||
31 | 33 | ||
32 | struct sst_device *sst; | 34 | struct sst_device *sst; |
33 | static DEFINE_MUTEX(sst_lock); | 35 | static DEFINE_MUTEX(sst_lock); |
@@ -92,6 +94,13 @@ static struct snd_pcm_hardware sst_platform_pcm_hw = { | |||
92 | .fifo_size = SST_FIFO_SIZE, | 94 | .fifo_size = SST_FIFO_SIZE, |
93 | }; | 95 | }; |
94 | 96 | ||
97 | static struct sst_dev_stream_map dpcm_strm_map[] = { | ||
98 | {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}, /* Reserved, not in use */ | ||
99 | {MERR_DPCM_AUDIO, 0, SNDRV_PCM_STREAM_PLAYBACK, PIPE_MEDIA1_IN, SST_TASK_ID_MEDIA, 0}, | ||
100 | {MERR_DPCM_COMPR, 0, SNDRV_PCM_STREAM_PLAYBACK, PIPE_MEDIA0_IN, SST_TASK_ID_MEDIA, 0}, | ||
101 | {MERR_DPCM_AUDIO, 0, SNDRV_PCM_STREAM_CAPTURE, PIPE_PCM1_OUT, SST_TASK_ID_MEDIA, 0}, | ||
102 | }; | ||
103 | |||
95 | /* MFLD - MSIC */ | 104 | /* MFLD - MSIC */ |
96 | static struct snd_soc_dai_driver sst_platform_dai[] = { | 105 | static struct snd_soc_dai_driver sst_platform_dai[] = { |
97 | { | 106 | { |
@@ -143,58 +152,142 @@ static inline int sst_get_stream_status(struct sst_runtime_stream *stream) | |||
143 | return state; | 152 | return state; |
144 | } | 153 | } |
145 | 154 | ||
155 | static void sst_fill_alloc_params(struct snd_pcm_substream *substream, | ||
156 | struct snd_sst_alloc_params_ext *alloc_param) | ||
157 | { | ||
158 | unsigned int channels; | ||
159 | snd_pcm_uframes_t period_size; | ||
160 | ssize_t periodbytes; | ||
161 | ssize_t buffer_bytes = snd_pcm_lib_buffer_bytes(substream); | ||
162 | u32 buffer_addr = virt_to_phys(substream->dma_buffer.area); | ||
163 | |||
164 | channels = substream->runtime->channels; | ||
165 | period_size = substream->runtime->period_size; | ||
166 | periodbytes = samples_to_bytes(substream->runtime, period_size); | ||
167 | alloc_param->ring_buf_info[0].addr = buffer_addr; | ||
168 | alloc_param->ring_buf_info[0].size = buffer_bytes; | ||
169 | alloc_param->sg_count = 1; | ||
170 | alloc_param->reserved = 0; | ||
171 | alloc_param->frag_size = periodbytes * channels; | ||
172 | |||
173 | } | ||
146 | static void sst_fill_pcm_params(struct snd_pcm_substream *substream, | 174 | static void sst_fill_pcm_params(struct snd_pcm_substream *substream, |
147 | struct sst_pcm_params *param) | 175 | struct snd_sst_stream_params *param) |
148 | { | 176 | { |
177 | param->uc.pcm_params.num_chan = (u8) substream->runtime->channels; | ||
178 | param->uc.pcm_params.pcm_wd_sz = substream->runtime->sample_bits; | ||
179 | param->uc.pcm_params.sfreq = substream->runtime->rate; | ||
180 | |||
181 | /* PCM stream via ALSA interface */ | ||
182 | param->uc.pcm_params.use_offload_path = 0; | ||
183 | param->uc.pcm_params.reserved2 = 0; | ||
184 | memset(param->uc.pcm_params.channel_map, 0, sizeof(u8)); | ||
149 | 185 | ||
150 | param->num_chan = (u8) substream->runtime->channels; | ||
151 | param->pcm_wd_sz = substream->runtime->sample_bits; | ||
152 | param->reserved = 0; | ||
153 | param->sfreq = substream->runtime->rate; | ||
154 | param->ring_buffer_size = snd_pcm_lib_buffer_bytes(substream); | ||
155 | param->period_count = substream->runtime->period_size; | ||
156 | param->ring_buffer_addr = virt_to_phys(substream->dma_buffer.area); | ||
157 | pr_debug("period_cnt = %d\n", param->period_count); | ||
158 | pr_debug("sfreq= %d, wd_sz = %d\n", param->sfreq, param->pcm_wd_sz); | ||
159 | } | 186 | } |
160 | 187 | ||
161 | static int sst_platform_alloc_stream(struct snd_pcm_substream *substream) | 188 | static int sst_get_stream_mapping(int dev, int sdev, int dir, |
189 | struct sst_dev_stream_map *map, int size) | ||
190 | { | ||
191 | int i; | ||
192 | |||
193 | if (map == NULL) | ||
194 | return -EINVAL; | ||
195 | |||
196 | |||
197 | /* index 0 is not used in stream map */ | ||
198 | for (i = 1; i < size; i++) { | ||
199 | if ((map[i].dev_num == dev) && (map[i].direction == dir)) | ||
200 | return i; | ||
201 | } | ||
202 | return 0; | ||
203 | } | ||
204 | |||
205 | int sst_fill_stream_params(void *substream, | ||
206 | const struct sst_data *ctx, struct snd_sst_params *str_params, bool is_compress) | ||
207 | { | ||
208 | int map_size; | ||
209 | int index; | ||
210 | struct sst_dev_stream_map *map; | ||
211 | struct snd_pcm_substream *pstream = NULL; | ||
212 | struct snd_compr_stream *cstream = NULL; | ||
213 | |||
214 | map = ctx->pdata->pdev_strm_map; | ||
215 | map_size = ctx->pdata->strm_map_size; | ||
216 | |||
217 | if (is_compress == true) | ||
218 | cstream = (struct snd_compr_stream *)substream; | ||
219 | else | ||
220 | pstream = (struct snd_pcm_substream *)substream; | ||
221 | |||
222 | str_params->stream_type = SST_STREAM_TYPE_MUSIC; | ||
223 | |||
224 | /* For pcm streams */ | ||
225 | if (pstream) { | ||
226 | index = sst_get_stream_mapping(pstream->pcm->device, | ||
227 | pstream->number, pstream->stream, | ||
228 | map, map_size); | ||
229 | if (index <= 0) | ||
230 | return -EINVAL; | ||
231 | |||
232 | str_params->stream_id = index; | ||
233 | str_params->device_type = map[index].device_id; | ||
234 | str_params->task = map[index].task_id; | ||
235 | |||
236 | str_params->ops = (u8)pstream->stream; | ||
237 | } | ||
238 | |||
239 | if (cstream) { | ||
240 | index = sst_get_stream_mapping(cstream->device->device, | ||
241 | 0, cstream->direction, | ||
242 | map, map_size); | ||
243 | if (index <= 0) | ||
244 | return -EINVAL; | ||
245 | str_params->stream_id = index; | ||
246 | str_params->device_type = map[index].device_id; | ||
247 | str_params->task = map[index].task_id; | ||
248 | |||
249 | str_params->ops = (u8)cstream->direction; | ||
250 | } | ||
251 | return 0; | ||
252 | } | ||
253 | |||
254 | static int sst_platform_alloc_stream(struct snd_pcm_substream *substream, | ||
255 | struct snd_soc_platform *platform) | ||
162 | { | 256 | { |
163 | struct sst_runtime_stream *stream = | 257 | struct sst_runtime_stream *stream = |
164 | substream->runtime->private_data; | 258 | substream->runtime->private_data; |
165 | struct sst_pcm_params param = {0}; | 259 | struct snd_sst_stream_params param = {{{0,},},}; |
166 | struct sst_stream_params str_params = {0}; | 260 | struct snd_sst_params str_params = {0}; |
167 | int ret_val; | 261 | struct snd_sst_alloc_params_ext alloc_params = {0}; |
262 | int ret_val = 0; | ||
263 | struct sst_data *ctx = snd_soc_platform_get_drvdata(platform); | ||
168 | 264 | ||
169 | /* set codec params and inform SST driver the same */ | 265 | /* set codec params and inform SST driver the same */ |
170 | sst_fill_pcm_params(substream, ¶m); | 266 | sst_fill_pcm_params(substream, ¶m); |
267 | sst_fill_alloc_params(substream, &alloc_params); | ||
171 | substream->runtime->dma_area = substream->dma_buffer.area; | 268 | substream->runtime->dma_area = substream->dma_buffer.area; |
172 | str_params.sparams = param; | 269 | str_params.sparams = param; |
173 | str_params.codec = param.codec; | 270 | str_params.aparams = alloc_params; |
174 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { | 271 | str_params.codec = SST_CODEC_TYPE_PCM; |
175 | str_params.ops = STREAM_OPS_PLAYBACK; | 272 | |
176 | str_params.device_type = substream->pcm->device + 1; | 273 | /* fill the device type and stream id to pass to SST driver */ |
177 | pr_debug("Playbck stream,Device %d\n", | 274 | ret_val = sst_fill_stream_params(substream, ctx, &str_params, false); |
178 | substream->pcm->device); | ||
179 | } else { | ||
180 | str_params.ops = STREAM_OPS_CAPTURE; | ||
181 | str_params.device_type = SND_SST_DEVICE_CAPTURE; | ||
182 | pr_debug("Capture stream,Device %d\n", | ||
183 | substream->pcm->device); | ||
184 | } | ||
185 | ret_val = stream->ops->open(&str_params); | ||
186 | pr_debug("SST_SND_PLAY/CAPTURE ret_val = %x\n", ret_val); | ||
187 | if (ret_val < 0) | 275 | if (ret_val < 0) |
188 | return ret_val; | 276 | return ret_val; |
189 | 277 | ||
190 | stream->stream_info.str_id = ret_val; | 278 | stream->stream_info.str_id = str_params.stream_id; |
191 | pr_debug("str id : %d\n", stream->stream_info.str_id); | 279 | |
280 | ret_val = stream->ops->open(&str_params); | ||
281 | if (ret_val <= 0) | ||
282 | return ret_val; | ||
283 | |||
284 | |||
192 | return ret_val; | 285 | return ret_val; |
193 | } | 286 | } |
194 | 287 | ||
195 | static void sst_period_elapsed(void *mad_substream) | 288 | static void sst_period_elapsed(void *arg) |
196 | { | 289 | { |
197 | struct snd_pcm_substream *substream = mad_substream; | 290 | struct snd_pcm_substream *substream = arg; |
198 | struct sst_runtime_stream *stream; | 291 | struct sst_runtime_stream *stream; |
199 | int status; | 292 | int status; |
200 | 293 | ||
@@ -218,7 +311,7 @@ static int sst_platform_init_stream(struct snd_pcm_substream *substream) | |||
218 | pr_debug("setting buffer ptr param\n"); | 311 | pr_debug("setting buffer ptr param\n"); |
219 | sst_set_stream_status(stream, SST_PLATFORM_INIT); | 312 | sst_set_stream_status(stream, SST_PLATFORM_INIT); |
220 | stream->stream_info.period_elapsed = sst_period_elapsed; | 313 | stream->stream_info.period_elapsed = sst_period_elapsed; |
221 | stream->stream_info.mad_substream = substream; | 314 | stream->stream_info.arg = substream; |
222 | stream->stream_info.buffer_ptr = 0; | 315 | stream->stream_info.buffer_ptr = 0; |
223 | stream->stream_info.sfreq = substream->runtime->rate; | 316 | stream->stream_info.sfreq = substream->runtime->rate; |
224 | ret_val = stream->ops->device_control( | 317 | ret_val = stream->ops->device_control( |
@@ -230,19 +323,12 @@ static int sst_platform_init_stream(struct snd_pcm_substream *substream) | |||
230 | } | 323 | } |
231 | /* end -- helper functions */ | 324 | /* end -- helper functions */ |
232 | 325 | ||
233 | static int sst_platform_open(struct snd_pcm_substream *substream) | 326 | static int sst_media_open(struct snd_pcm_substream *substream, |
327 | struct snd_soc_dai *dai) | ||
234 | { | 328 | { |
329 | int ret_val = 0; | ||
235 | struct snd_pcm_runtime *runtime = substream->runtime; | 330 | struct snd_pcm_runtime *runtime = substream->runtime; |
236 | struct sst_runtime_stream *stream; | 331 | struct sst_runtime_stream *stream; |
237 | int ret_val; | ||
238 | |||
239 | pr_debug("sst_platform_open called\n"); | ||
240 | |||
241 | snd_soc_set_runtime_hwparams(substream, &sst_platform_pcm_hw); | ||
242 | ret_val = snd_pcm_hw_constraint_integer(runtime, | ||
243 | SNDRV_PCM_HW_PARAM_PERIODS); | ||
244 | if (ret_val < 0) | ||
245 | return ret_val; | ||
246 | 332 | ||
247 | stream = kzalloc(sizeof(*stream), GFP_KERNEL); | 333 | stream = kzalloc(sizeof(*stream), GFP_KERNEL); |
248 | if (!stream) | 334 | if (!stream) |
@@ -251,50 +337,69 @@ static int sst_platform_open(struct snd_pcm_substream *substream) | |||
251 | 337 | ||
252 | /* get the sst ops */ | 338 | /* get the sst ops */ |
253 | mutex_lock(&sst_lock); | 339 | mutex_lock(&sst_lock); |
254 | if (!sst) { | 340 | if (!sst || |
341 | !try_module_get(sst->dev->driver->owner)) { | ||
255 | pr_err("no device available to run\n"); | 342 | pr_err("no device available to run\n"); |
256 | mutex_unlock(&sst_lock); | 343 | ret_val = -ENODEV; |
257 | kfree(stream); | 344 | goto out_ops; |
258 | return -ENODEV; | ||
259 | } | ||
260 | if (!try_module_get(sst->dev->driver->owner)) { | ||
261 | mutex_unlock(&sst_lock); | ||
262 | kfree(stream); | ||
263 | return -ENODEV; | ||
264 | } | 345 | } |
265 | stream->ops = sst->ops; | 346 | stream->ops = sst->ops; |
266 | mutex_unlock(&sst_lock); | 347 | mutex_unlock(&sst_lock); |
267 | 348 | ||
268 | stream->stream_info.str_id = 0; | 349 | stream->stream_info.str_id = 0; |
269 | sst_set_stream_status(stream, SST_PLATFORM_INIT); | 350 | |
270 | stream->stream_info.mad_substream = substream; | 351 | stream->stream_info.arg = substream; |
271 | /* allocate memory for SST API set */ | 352 | /* allocate memory for SST API set */ |
272 | runtime->private_data = stream; | 353 | runtime->private_data = stream; |
273 | 354 | ||
274 | return 0; | 355 | /* Make sure, that the period size is always even */ |
356 | snd_pcm_hw_constraint_step(substream->runtime, 0, | ||
357 | SNDRV_PCM_HW_PARAM_PERIODS, 2); | ||
358 | |||
359 | return snd_pcm_hw_constraint_integer(runtime, | ||
360 | SNDRV_PCM_HW_PARAM_PERIODS); | ||
361 | out_ops: | ||
362 | kfree(stream); | ||
363 | mutex_unlock(&sst_lock); | ||
364 | return ret_val; | ||
275 | } | 365 | } |
276 | 366 | ||
277 | static int sst_platform_close(struct snd_pcm_substream *substream) | 367 | static void sst_media_close(struct snd_pcm_substream *substream, |
368 | struct snd_soc_dai *dai) | ||
278 | { | 369 | { |
279 | struct sst_runtime_stream *stream; | 370 | struct sst_runtime_stream *stream; |
280 | int ret_val = 0, str_id; | 371 | int ret_val = 0, str_id; |
281 | 372 | ||
282 | pr_debug("sst_platform_close called\n"); | ||
283 | stream = substream->runtime->private_data; | 373 | stream = substream->runtime->private_data; |
284 | str_id = stream->stream_info.str_id; | 374 | str_id = stream->stream_info.str_id; |
285 | if (str_id) | 375 | if (str_id) |
286 | ret_val = stream->ops->close(str_id); | 376 | ret_val = stream->ops->close(str_id); |
287 | module_put(sst->dev->driver->owner); | 377 | module_put(sst->dev->driver->owner); |
288 | kfree(stream); | 378 | kfree(stream); |
289 | return ret_val; | ||
290 | } | 379 | } |
291 | 380 | ||
292 | static int sst_platform_pcm_prepare(struct snd_pcm_substream *substream) | 381 | static inline unsigned int get_current_pipe_id(struct snd_soc_platform *platform, |
382 | struct snd_pcm_substream *substream) | ||
383 | { | ||
384 | struct sst_data *sst = snd_soc_platform_get_drvdata(platform); | ||
385 | struct sst_dev_stream_map *map = sst->pdata->pdev_strm_map; | ||
386 | struct sst_runtime_stream *stream = | ||
387 | substream->runtime->private_data; | ||
388 | u32 str_id = stream->stream_info.str_id; | ||
389 | unsigned int pipe_id; | ||
390 | pipe_id = map[str_id].device_id; | ||
391 | |||
392 | pr_debug("%s: got pipe_id = %#x for str_id = %d\n", | ||
393 | __func__, pipe_id, str_id); | ||
394 | return pipe_id; | ||
395 | } | ||
396 | |||
397 | static int sst_media_prepare(struct snd_pcm_substream *substream, | ||
398 | struct snd_soc_dai *dai) | ||
293 | { | 399 | { |
294 | struct sst_runtime_stream *stream; | 400 | struct sst_runtime_stream *stream; |
295 | int ret_val = 0, str_id; | 401 | int ret_val = 0, str_id; |
296 | 402 | ||
297 | pr_debug("sst_platform_pcm_prepare called\n"); | ||
298 | stream = substream->runtime->private_data; | 403 | stream = substream->runtime->private_data; |
299 | str_id = stream->stream_info.str_id; | 404 | str_id = stream->stream_info.str_id; |
300 | if (stream->stream_info.str_id) { | 405 | if (stream->stream_info.str_id) { |
@@ -303,8 +408,8 @@ static int sst_platform_pcm_prepare(struct snd_pcm_substream *substream) | |||
303 | return ret_val; | 408 | return ret_val; |
304 | } | 409 | } |
305 | 410 | ||
306 | ret_val = sst_platform_alloc_stream(substream); | 411 | ret_val = sst_platform_alloc_stream(substream, dai->platform); |
307 | if (ret_val < 0) | 412 | if (ret_val <= 0) |
308 | return ret_val; | 413 | return ret_val; |
309 | snprintf(substream->pcm->id, sizeof(substream->pcm->id), | 414 | snprintf(substream->pcm->id, sizeof(substream->pcm->id), |
310 | "%d", stream->stream_info.str_id); | 415 | "%d", stream->stream_info.str_id); |
@@ -316,6 +421,41 @@ static int sst_platform_pcm_prepare(struct snd_pcm_substream *substream) | |||
316 | return ret_val; | 421 | return ret_val; |
317 | } | 422 | } |
318 | 423 | ||
424 | static int sst_media_hw_params(struct snd_pcm_substream *substream, | ||
425 | struct snd_pcm_hw_params *params, | ||
426 | struct snd_soc_dai *dai) | ||
427 | { | ||
428 | snd_pcm_lib_malloc_pages(substream, params_buffer_bytes(params)); | ||
429 | memset(substream->runtime->dma_area, 0, params_buffer_bytes(params)); | ||
430 | return 0; | ||
431 | } | ||
432 | |||
433 | static int sst_media_hw_free(struct snd_pcm_substream *substream, | ||
434 | struct snd_soc_dai *dai) | ||
435 | { | ||
436 | return snd_pcm_lib_free_pages(substream); | ||
437 | } | ||
438 | |||
439 | static struct snd_soc_dai_ops sst_media_dai_ops = { | ||
440 | .startup = sst_media_open, | ||
441 | .shutdown = sst_media_close, | ||
442 | .prepare = sst_media_prepare, | ||
443 | .hw_params = sst_media_hw_params, | ||
444 | .hw_free = sst_media_hw_free, | ||
445 | }; | ||
446 | |||
447 | static int sst_platform_open(struct snd_pcm_substream *substream) | ||
448 | { | ||
449 | struct snd_pcm_runtime *runtime; | ||
450 | |||
451 | if (substream->pcm->internal) | ||
452 | return 0; | ||
453 | |||
454 | runtime = substream->runtime; | ||
455 | runtime->hw = sst_platform_pcm_hw; | ||
456 | return 0; | ||
457 | } | ||
458 | |||
319 | static int sst_platform_pcm_trigger(struct snd_pcm_substream *substream, | 459 | static int sst_platform_pcm_trigger(struct snd_pcm_substream *substream, |
320 | int cmd) | 460 | int cmd) |
321 | { | 461 | { |
@@ -331,7 +471,7 @@ static int sst_platform_pcm_trigger(struct snd_pcm_substream *substream, | |||
331 | pr_debug("sst: Trigger Start\n"); | 471 | pr_debug("sst: Trigger Start\n"); |
332 | str_cmd = SST_SND_START; | 472 | str_cmd = SST_SND_START; |
333 | status = SST_PLATFORM_RUNNING; | 473 | status = SST_PLATFORM_RUNNING; |
334 | stream->stream_info.mad_substream = substream; | 474 | stream->stream_info.arg = substream; |
335 | break; | 475 | break; |
336 | case SNDRV_PCM_TRIGGER_STOP: | 476 | case SNDRV_PCM_TRIGGER_STOP: |
337 | pr_debug("sst: in stop\n"); | 477 | pr_debug("sst: in stop\n"); |
@@ -377,32 +517,15 @@ static snd_pcm_uframes_t sst_platform_pcm_pointer | |||
377 | pr_err("sst: error code = %d\n", ret_val); | 517 | pr_err("sst: error code = %d\n", ret_val); |
378 | return ret_val; | 518 | return ret_val; |
379 | } | 519 | } |
380 | return stream->stream_info.buffer_ptr; | 520 | substream->runtime->delay = str_info->pcm_delay; |
381 | } | 521 | return str_info->buffer_ptr; |
382 | |||
383 | static int sst_platform_pcm_hw_params(struct snd_pcm_substream *substream, | ||
384 | struct snd_pcm_hw_params *params) | ||
385 | { | ||
386 | snd_pcm_lib_malloc_pages(substream, params_buffer_bytes(params)); | ||
387 | memset(substream->runtime->dma_area, 0, params_buffer_bytes(params)); | ||
388 | |||
389 | return 0; | ||
390 | } | ||
391 | |||
392 | static int sst_platform_pcm_hw_free(struct snd_pcm_substream *substream) | ||
393 | { | ||
394 | return snd_pcm_lib_free_pages(substream); | ||
395 | } | 522 | } |
396 | 523 | ||
397 | static struct snd_pcm_ops sst_platform_ops = { | 524 | static struct snd_pcm_ops sst_platform_ops = { |
398 | .open = sst_platform_open, | 525 | .open = sst_platform_open, |
399 | .close = sst_platform_close, | ||
400 | .ioctl = snd_pcm_lib_ioctl, | 526 | .ioctl = snd_pcm_lib_ioctl, |
401 | .prepare = sst_platform_pcm_prepare, | ||
402 | .trigger = sst_platform_pcm_trigger, | 527 | .trigger = sst_platform_pcm_trigger, |
403 | .pointer = sst_platform_pcm_pointer, | 528 | .pointer = sst_platform_pcm_pointer, |
404 | .hw_params = sst_platform_pcm_hw_params, | ||
405 | .hw_free = sst_platform_pcm_hw_free, | ||
406 | }; | 529 | }; |
407 | 530 | ||
408 | static void sst_pcm_free(struct snd_pcm *pcm) | 531 | static void sst_pcm_free(struct snd_pcm *pcm) |
@@ -413,15 +536,15 @@ static void sst_pcm_free(struct snd_pcm *pcm) | |||
413 | 536 | ||
414 | static int sst_pcm_new(struct snd_soc_pcm_runtime *rtd) | 537 | static int sst_pcm_new(struct snd_soc_pcm_runtime *rtd) |
415 | { | 538 | { |
539 | struct snd_soc_dai *dai = rtd->cpu_dai; | ||
416 | struct snd_pcm *pcm = rtd->pcm; | 540 | struct snd_pcm *pcm = rtd->pcm; |
417 | int retval = 0; | 541 | int retval = 0; |
418 | 542 | ||
419 | pr_debug("sst_pcm_new called\n"); | 543 | if (dai->driver->playback.channels_min || |
420 | if (pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream || | 544 | dai->driver->capture.channels_min) { |
421 | pcm->streams[SNDRV_PCM_STREAM_CAPTURE].substream) { | ||
422 | retval = snd_pcm_lib_preallocate_pages_for_all(pcm, | 545 | retval = snd_pcm_lib_preallocate_pages_for_all(pcm, |
423 | SNDRV_DMA_TYPE_CONTINUOUS, | 546 | SNDRV_DMA_TYPE_CONTINUOUS, |
424 | snd_dma_continuous_data(GFP_KERNEL), | 547 | snd_dma_continuous_data(GFP_DMA), |
425 | SST_MIN_BUFFER, SST_MAX_BUFFER); | 548 | SST_MIN_BUFFER, SST_MAX_BUFFER); |
426 | if (retval) { | 549 | if (retval) { |
427 | pr_err("dma buffer allocationf fail\n"); | 550 | pr_err("dma buffer allocationf fail\n"); |
@@ -445,10 +568,28 @@ static const struct snd_soc_component_driver sst_component = { | |||
445 | 568 | ||
446 | static int sst_platform_probe(struct platform_device *pdev) | 569 | static int sst_platform_probe(struct platform_device *pdev) |
447 | { | 570 | { |
571 | struct sst_data *drv; | ||
448 | int ret; | 572 | int ret; |
573 | struct sst_platform_data *pdata; | ||
574 | |||
575 | drv = devm_kzalloc(&pdev->dev, sizeof(*drv), GFP_KERNEL); | ||
576 | if (drv == NULL) { | ||
577 | pr_err("kzalloc failed\n"); | ||
578 | return -ENOMEM; | ||
579 | } | ||
580 | |||
581 | pdata = devm_kzalloc(&pdev->dev, sizeof(*pdata), GFP_KERNEL); | ||
582 | if (pdata == NULL) { | ||
583 | pr_err("kzalloc failed for pdata\n"); | ||
584 | return -ENOMEM; | ||
585 | } | ||
586 | |||
587 | pdata->pdev_strm_map = dpcm_strm_map; | ||
588 | pdata->strm_map_size = ARRAY_SIZE(dpcm_strm_map); | ||
589 | drv->pdata = pdata; | ||
590 | mutex_init(&drv->lock); | ||
591 | dev_set_drvdata(&pdev->dev, drv); | ||
449 | 592 | ||
450 | pr_debug("sst_platform_probe called\n"); | ||
451 | sst = NULL; | ||
452 | ret = snd_soc_register_platform(&pdev->dev, &sst_soc_platform_drv); | 593 | ret = snd_soc_register_platform(&pdev->dev, &sst_soc_platform_drv); |
453 | if (ret) { | 594 | if (ret) { |
454 | pr_err("registering soc platform failed\n"); | 595 | pr_err("registering soc platform failed\n"); |
diff --git a/sound/soc/intel/sst-mfld-platform.h b/sound/soc/intel/sst-mfld-platform.h index 6c5e7dc49e3c..6c6a42c08e24 100644 --- a/sound/soc/intel/sst-mfld-platform.h +++ b/sound/soc/intel/sst-mfld-platform.h | |||
@@ -39,9 +39,10 @@ extern struct sst_device *sst; | |||
39 | 39 | ||
40 | struct pcm_stream_info { | 40 | struct pcm_stream_info { |
41 | int str_id; | 41 | int str_id; |
42 | void *mad_substream; | 42 | void *arg; |
43 | void (*period_elapsed) (void *mad_substream); | 43 | void (*period_elapsed) (void *arg); |
44 | unsigned long long buffer_ptr; | 44 | unsigned long long buffer_ptr; |
45 | unsigned long long pcm_delay; | ||
45 | int sfreq; | 46 | int sfreq; |
46 | }; | 47 | }; |
47 | 48 | ||
@@ -62,7 +63,9 @@ enum sst_controls { | |||
62 | SST_SND_BUFFER_POINTER = 0x05, | 63 | SST_SND_BUFFER_POINTER = 0x05, |
63 | SST_SND_STREAM_INIT = 0x06, | 64 | SST_SND_STREAM_INIT = 0x06, |
64 | SST_SND_START = 0x07, | 65 | SST_SND_START = 0x07, |
65 | SST_MAX_CONTROLS = 0x07, | 66 | SST_SET_BYTE_STREAM = 0x100A, |
67 | SST_GET_BYTE_STREAM = 0x100B, | ||
68 | SST_MAX_CONTROLS = SST_GET_BYTE_STREAM, | ||
66 | }; | 69 | }; |
67 | 70 | ||
68 | enum sst_stream_ops { | 71 | enum sst_stream_ops { |
@@ -124,8 +127,9 @@ struct compress_sst_ops { | |||
124 | }; | 127 | }; |
125 | 128 | ||
126 | struct sst_ops { | 129 | struct sst_ops { |
127 | int (*open) (struct sst_stream_params *str_param); | 130 | int (*open) (struct snd_sst_params *str_param); |
128 | int (*device_control) (int cmd, void *arg); | 131 | int (*device_control) (int cmd, void *arg); |
132 | int (*set_generic_params)(enum sst_controls cmd, void *arg); | ||
129 | int (*close) (unsigned int str_id); | 133 | int (*close) (unsigned int str_id); |
130 | }; | 134 | }; |
131 | 135 | ||
@@ -143,10 +147,27 @@ struct sst_device { | |||
143 | char *name; | 147 | char *name; |
144 | struct device *dev; | 148 | struct device *dev; |
145 | struct sst_ops *ops; | 149 | struct sst_ops *ops; |
150 | struct platform_device *pdev; | ||
146 | struct compress_sst_ops *compr_ops; | 151 | struct compress_sst_ops *compr_ops; |
147 | }; | 152 | }; |
148 | 153 | ||
154 | struct sst_data; | ||
149 | void sst_set_stream_status(struct sst_runtime_stream *stream, int state); | 155 | void sst_set_stream_status(struct sst_runtime_stream *stream, int state); |
156 | int sst_fill_stream_params(void *substream, const struct sst_data *ctx, | ||
157 | struct snd_sst_params *str_params, bool is_compress); | ||
158 | |||
159 | struct sst_algo_int_control_v2 { | ||
160 | struct soc_mixer_control mc; | ||
161 | u16 module_id; /* module identifieer */ | ||
162 | u16 pipe_id; /* location info: pipe_id + instance_id */ | ||
163 | u16 instance_id; | ||
164 | unsigned int value; /* Value received is stored here */ | ||
165 | }; | ||
166 | struct sst_data { | ||
167 | struct platform_device *pdev; | ||
168 | struct sst_platform_data *pdata; | ||
169 | struct mutex lock; | ||
170 | }; | ||
150 | int sst_register_dsp(struct sst_device *sst); | 171 | int sst_register_dsp(struct sst_device *sst); |
151 | int sst_unregister_dsp(struct sst_device *sst); | 172 | int sst_unregister_dsp(struct sst_device *sst); |
152 | #endif | 173 | #endif |