aboutsummaryrefslogtreecommitdiffstats
path: root/sound/soc/intel
diff options
context:
space:
mode:
authorMark Brown <broonie@linaro.org>2014-08-15 07:51:28 -0400
committerMark Brown <broonie@linaro.org>2014-08-15 07:51:28 -0400
commit543c675482bcf1e7b9f85bb1589314f38f60c520 (patch)
tree904f425393ac99539827d3164d2b0f78ac1607c5 /sound/soc/intel
parent2fa4a285ddfd39cfa711da3f5e898ec2ce80ef87 (diff)
parentae34a78c430c37c06404f032fb04e51315204281 (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/Kconfig12
-rw-r--r--sound/soc/intel/Makefile2
-rw-r--r--sound/soc/intel/broadwell.c251
-rw-r--r--sound/soc/intel/byt-max98090.c8
-rw-r--r--sound/soc/intel/byt-rt5640.c1
-rw-r--r--sound/soc/intel/sst-atom-controls.h30
-rw-r--r--sound/soc/intel/sst-baytrail-ipc.c30
-rw-r--r--sound/soc/intel/sst-dsp.c10
-rw-r--r--sound/soc/intel/sst-dsp.h39
-rw-r--r--sound/soc/intel/sst-haswell-dsp.c57
-rw-r--r--sound/soc/intel/sst-haswell-ipc.c40
-rw-r--r--sound/soc/intel/sst-mfld-dsp.h429
-rw-r--r--sound/soc/intel/sst-mfld-platform-compress.c11
-rw-r--r--sound/soc/intel/sst-mfld-platform-pcm.c319
-rw-r--r--sound/soc/intel/sst-mfld-platform.h29
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
62config 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
24snd-soc-sst-haswell-objs := haswell.o 24snd-soc-sst-haswell-objs := haswell.o
25snd-soc-sst-byt-rt5640-mach-objs := byt-rt5640.o 25snd-soc-sst-byt-rt5640-mach-objs := byt-rt5640.o
26snd-soc-sst-byt-max98090-mach-objs := byt-max98090.o 26snd-soc-sst-byt-max98090-mach-objs := byt-max98090.o
27snd-soc-sst-broadwell-objs := broadwell.o
27 28
28obj-$(CONFIG_SND_SOC_INTEL_HASWELL_MACH) += snd-soc-sst-haswell.o 29obj-$(CONFIG_SND_SOC_INTEL_HASWELL_MACH) += snd-soc-sst-haswell.o
29obj-$(CONFIG_SND_SOC_INTEL_BYT_RT5640_MACH) += snd-soc-sst-byt-rt5640-mach.o 30obj-$(CONFIG_SND_SOC_INTEL_BYT_RT5640_MACH) += snd-soc-sst-byt-rt5640-mach.o
30obj-$(CONFIG_SND_SOC_INTEL_BYT_MAX98090_MACH) += snd-soc-sst-byt-max98090-mach.o 31obj-$(CONFIG_SND_SOC_INTEL_BYT_MAX98090_MACH) += snd-soc-sst-byt-max98090-mach.o
32obj-$(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
29static 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
38static 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
60static 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(&params->masks[SNDRV_PCM_HW_PARAM_FORMAT -
74 SNDRV_PCM_HW_PARAM_FIRST_MASK],
75 SNDRV_PCM_FORMAT_S16_LE);
76 return 0;
77}
78
79static 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
97static struct snd_soc_ops broadwell_rt286_ops = {
98 .hw_params = broadwell_rt286_hw_params,
99};
100
101static 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 */
130static 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 */
211static 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
223static 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
230static int broadwell_audio_remove(struct platform_device *pdev)
231{
232 snd_soc_unregister_card(&broadwell_rt286);
233 return 0;
234}
235
236static 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
245module_platform_driver(broadwell_audio)
246
247/* Module information */
248MODULE_AUTHOR("Liam Girdwood, Xingchao Wang");
249MODULE_DESCRIPTION("Intel SST Audio for WPT/Broadwell");
250MODULE_LICENSE("GPL v2");
251MODULE_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
76static struct snd_soc_jack_gpio hs_jack_gpios[] = { 68static 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
36static const struct snd_soc_dapm_route byt_rt5640_audio_map[] = { 36static 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
24enum {
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
125struct sst_byt_fw_version {
126 u8 build;
127 u8 minor;
128 u8 major;
129 u8 type;
130} __packed;
131
132struct sst_byt_fw_build_info {
133 u8 date[16];
134 u8 time[16];
135} __packed;
136
137struct 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 */
126struct ipc_message { 146struct 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
225void sst_dsp_dump(struct sst_dsp *sst) 225void 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}
229EXPORT_SYMBOL_GPL(sst_dsp_dump); 230EXPORT_SYMBOL_GPL(sst_dsp_dump);
230 231
231void sst_dsp_reset(struct sst_dsp *sst) 232void 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}
235EXPORT_SYMBOL_GPL(sst_dsp_reset); 237EXPORT_SYMBOL_GPL(sst_dsp_reset);
236 238
237int sst_dsp_boot(struct sst_dsp *sst) 239int 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}
242EXPORT_SYMBOL_GPL(sst_dsp_boot); 246EXPORT_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
138struct sst_dsp; 169struct 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 */
315static const struct sst_adsp_memregion wpt_region[] = { 312static 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
337struct sst_sram_shift {
338 u32 dev_id; /* SST Device IDs */
339 u32 iram_shift;
340 u32 dram_shift;
341};
342
343static 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};
342static u32 hsw_block_get_bit(struct sst_mem_block *block) 347static 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
189struct ipc_message { 189struct 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
594static void hsw_notification_work(struct work_struct *work) 612static 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 */
146enum ackData {
147 IPC_ACK_SUCCESS = 0,
148 IPC_ACK_FAILURE,
149};
150
151enum 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
22enum sst_codec_types { 158enum 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
174enum 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
189struct 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
197union 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 */
212union 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 */
222union 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 */
236struct 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 */
242struct 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
249struct 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
257struct 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 */
268struct 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 */
279struct 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 */
290struct 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
300struct 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
306struct 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
312struct 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};
38struct snd_pcm_params { 318struct 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 {
76struct snd_wma_params { 355struct 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
103struct snd_sst_alloc_params_ext { 383struct 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
112struct snd_sst_stream_params { 391struct snd_sst_stream_params {
113 union snd_sst_codec_params uc; 392 union snd_sst_codec_params uc;
114} __packed; 393} __packed;
115 394
116struct snd_sst_params { 395struct 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
407struct 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 */
418struct 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 */
425struct 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 */
431struct snd_sst_drop_response {
432 u32 result;
433 u32 bytes;
434};
435
436struct snd_sst_async_msg {
437 u32 msg_id; /* Async msg id */
438 u32 payload[0];
439};
440
441struct snd_sst_async_err_msg {
442 u32 fw_resp; /* Firmware Result */
443 u32 lib_resp; /*Library result */
444} __packed;
445
446struct 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 */
456struct 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
466struct snd_sst_mute {
467 u32 stream_id;
468 u32 mute;
469};
470
471struct snd_sst_runtime_params {
472 u8 type;
473 u8 str_id;
474 u8 size;
475 u8 rsvd;
476 void *addr;
477} __packed;
478
479enum 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 */
486struct snd_sst_control_routing {
487 u8 control; /* 0=start, 1=Stop */
488 u8 reserved[3]; /* Reserved- for 32 bit alignment */
489};
490
491struct 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
500struct 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
505struct snd_sst_lpe_log_params {
506 u8 dbg_type;
507 u8 module_id;
508 u8 log_level;
509 u8 reserved;
510} __packed;
511
512enum snd_sst_bytes_type {
513 SND_SST_BYTES_SET = 0x1,
514 SND_SST_BYTES_GET = 0x2,
515};
516
517struct 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
529struct 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
32struct sst_device *sst; 34struct sst_device *sst;
33static DEFINE_MUTEX(sst_lock); 35static 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
97static 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 */
96static struct snd_soc_dai_driver sst_platform_dai[] = { 105static 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
155static 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}
146static void sst_fill_pcm_params(struct snd_pcm_substream *substream, 174static 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
161static int sst_platform_alloc_stream(struct snd_pcm_substream *substream) 188static 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
205int 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
254static 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, &param); 266 sst_fill_pcm_params(substream, &param);
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
195static void sst_period_elapsed(void *mad_substream) 288static 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
233static int sst_platform_open(struct snd_pcm_substream *substream) 326static 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);
361out_ops:
362 kfree(stream);
363 mutex_unlock(&sst_lock);
364 return ret_val;
275} 365}
276 366
277static int sst_platform_close(struct snd_pcm_substream *substream) 367static 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
292static int sst_platform_pcm_prepare(struct snd_pcm_substream *substream) 381static 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
397static 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
424static 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
433static 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
439static 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
447static 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
319static int sst_platform_pcm_trigger(struct snd_pcm_substream *substream, 459static 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
383static 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
392static int sst_platform_pcm_hw_free(struct snd_pcm_substream *substream)
393{
394 return snd_pcm_lib_free_pages(substream);
395} 522}
396 523
397static struct snd_pcm_ops sst_platform_ops = { 524static 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
408static void sst_pcm_free(struct snd_pcm *pcm) 531static void sst_pcm_free(struct snd_pcm *pcm)
@@ -413,15 +536,15 @@ static void sst_pcm_free(struct snd_pcm *pcm)
413 536
414static int sst_pcm_new(struct snd_soc_pcm_runtime *rtd) 537static 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
446static int sst_platform_probe(struct platform_device *pdev) 569static 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
40struct pcm_stream_info { 40struct 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
68enum sst_stream_ops { 71enum sst_stream_ops {
@@ -124,8 +127,9 @@ struct compress_sst_ops {
124}; 127};
125 128
126struct sst_ops { 129struct 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
154struct sst_data;
149void sst_set_stream_status(struct sst_runtime_stream *stream, int state); 155void sst_set_stream_status(struct sst_runtime_stream *stream, int state);
156int sst_fill_stream_params(void *substream, const struct sst_data *ctx,
157 struct snd_sst_params *str_params, bool is_compress);
158
159struct 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};
166struct sst_data {
167 struct platform_device *pdev;
168 struct sst_platform_data *pdata;
169 struct mutex lock;
170};
150int sst_register_dsp(struct sst_device *sst); 171int sst_register_dsp(struct sst_device *sst);
151int sst_unregister_dsp(struct sst_device *sst); 172int sst_unregister_dsp(struct sst_device *sst);
152#endif 173#endif