aboutsummaryrefslogtreecommitdiffstats
path: root/sound/soc/intel/common
diff options
context:
space:
mode:
authorMark Brown <broonie@kernel.org>2015-04-12 14:48:33 -0400
committerMark Brown <broonie@kernel.org>2015-04-12 14:48:33 -0400
commitaab0bb17ef2440ef5f68dcde5f1a6b32dcdfa9fb (patch)
tree6e14e997a1424e189d47ec04f4b1e1b8e6d85491 /sound/soc/intel/common
parent77b62fa5d23988155132cf7fee44f2c209e3dc4c (diff)
parenta5e5e12bd4ed5cd1123ace4300b5c07230fbf21e (diff)
Merge remote-tracking branch 'asoc/topic/intel' into asoc-next
Diffstat (limited to 'sound/soc/intel/common')
-rw-r--r--sound/soc/intel/common/Makefile7
-rw-r--r--sound/soc/intel/common/sst-acpi.c286
-rw-r--r--sound/soc/intel/common/sst-dsp-priv.h373
-rw-r--r--sound/soc/intel/common/sst-dsp.c420
-rw-r--r--sound/soc/intel/common/sst-dsp.h285
-rw-r--r--sound/soc/intel/common/sst-firmware.c1205
-rw-r--r--sound/soc/intel/common/sst-ipc.c294
-rw-r--r--sound/soc/intel/common/sst-ipc.h91
8 files changed, 2961 insertions, 0 deletions
diff --git a/sound/soc/intel/common/Makefile b/sound/soc/intel/common/Makefile
new file mode 100644
index 000000000000..f24154ca4e98
--- /dev/null
+++ b/sound/soc/intel/common/Makefile
@@ -0,0 +1,7 @@
1snd-soc-sst-dsp-objs := sst-dsp.o sst-firmware.o
2snd-soc-sst-acpi-objs := sst-acpi.o
3snd-soc-sst-ipc-objs := sst-ipc.o
4
5obj-$(CONFIG_SND_SOC_INTEL_SST) += snd-soc-sst-dsp.o snd-soc-sst-ipc.o
6obj-$(CONFIG_SND_SOC_INTEL_SST_ACPI) += snd-soc-sst-acpi.o
7
diff --git a/sound/soc/intel/common/sst-acpi.c b/sound/soc/intel/common/sst-acpi.c
new file mode 100644
index 000000000000..42f293f9c6e2
--- /dev/null
+++ b/sound/soc/intel/common/sst-acpi.c
@@ -0,0 +1,286 @@
1/*
2 * Intel SST loader on ACPI systems
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/acpi.h>
18#include <linux/device.h>
19#include <linux/firmware.h>
20#include <linux/module.h>
21#include <linux/platform_device.h>
22
23#include "sst-dsp.h"
24
25#define SST_LPT_DSP_DMA_ADDR_OFFSET 0x0F0000
26#define SST_WPT_DSP_DMA_ADDR_OFFSET 0x0FE000
27#define SST_LPT_DSP_DMA_SIZE (1024 - 1)
28
29/* Descriptor for SST ASoC machine driver */
30struct sst_acpi_mach {
31 /* ACPI ID for the matching machine driver. Audio codec for instance */
32 const u8 id[ACPI_ID_LEN];
33 /* machine driver name */
34 const char *drv_name;
35 /* firmware file name */
36 const char *fw_filename;
37};
38
39/* Descriptor for setting up SST platform data */
40struct sst_acpi_desc {
41 const char *drv_name;
42 struct sst_acpi_mach *machines;
43 /* Platform resource indexes. Must set to -1 if not used */
44 int resindex_lpe_base;
45 int resindex_pcicfg_base;
46 int resindex_fw_base;
47 int irqindex_host_ipc;
48 int resindex_dma_base;
49 /* Unique number identifying the SST core on platform */
50 int sst_id;
51 /* DMA only valid when resindex_dma_base != -1*/
52 int dma_engine;
53 int dma_size;
54};
55
56struct sst_acpi_priv {
57 struct platform_device *pdev_mach;
58 struct platform_device *pdev_pcm;
59 struct sst_pdata sst_pdata;
60 struct sst_acpi_desc *desc;
61 struct sst_acpi_mach *mach;
62};
63
64static void sst_acpi_fw_cb(const struct firmware *fw, void *context)
65{
66 struct platform_device *pdev = context;
67 struct device *dev = &pdev->dev;
68 struct sst_acpi_priv *sst_acpi = platform_get_drvdata(pdev);
69 struct sst_pdata *sst_pdata = &sst_acpi->sst_pdata;
70 struct sst_acpi_desc *desc = sst_acpi->desc;
71 struct sst_acpi_mach *mach = sst_acpi->mach;
72
73 sst_pdata->fw = fw;
74 if (!fw) {
75 dev_err(dev, "Cannot load firmware %s\n", mach->fw_filename);
76 return;
77 }
78
79 /* register PCM and DAI driver */
80 sst_acpi->pdev_pcm =
81 platform_device_register_data(dev, desc->drv_name, -1,
82 sst_pdata, sizeof(*sst_pdata));
83 if (IS_ERR(sst_acpi->pdev_pcm)) {
84 dev_err(dev, "Cannot register device %s. Error %d\n",
85 desc->drv_name, (int)PTR_ERR(sst_acpi->pdev_pcm));
86 }
87
88 return;
89}
90
91static acpi_status sst_acpi_mach_match(acpi_handle handle, u32 level,
92 void *context, void **ret)
93{
94 *(bool *)context = true;
95 return AE_OK;
96}
97
98static struct sst_acpi_mach *sst_acpi_find_machine(
99 struct sst_acpi_mach *machines)
100{
101 struct sst_acpi_mach *mach;
102 bool found = false;
103
104 for (mach = machines; mach->id[0]; mach++)
105 if (ACPI_SUCCESS(acpi_get_devices(mach->id,
106 sst_acpi_mach_match,
107 &found, NULL)) && found)
108 return mach;
109
110 return NULL;
111}
112
113static int sst_acpi_probe(struct platform_device *pdev)
114{
115 const struct acpi_device_id *id;
116 struct device *dev = &pdev->dev;
117 struct sst_acpi_priv *sst_acpi;
118 struct sst_pdata *sst_pdata;
119 struct sst_acpi_mach *mach;
120 struct sst_acpi_desc *desc;
121 struct resource *mmio;
122 int ret = 0;
123
124 sst_acpi = devm_kzalloc(dev, sizeof(*sst_acpi), GFP_KERNEL);
125 if (sst_acpi == NULL)
126 return -ENOMEM;
127
128 id = acpi_match_device(dev->driver->acpi_match_table, dev);
129 if (!id)
130 return -ENODEV;
131
132 desc = (struct sst_acpi_desc *)id->driver_data;
133 mach = sst_acpi_find_machine(desc->machines);
134 if (mach == NULL) {
135 dev_err(dev, "No matching ASoC machine driver found\n");
136 return -ENODEV;
137 }
138
139 sst_pdata = &sst_acpi->sst_pdata;
140 sst_pdata->id = desc->sst_id;
141 sst_pdata->dma_dev = dev;
142 sst_acpi->desc = desc;
143 sst_acpi->mach = mach;
144
145 sst_pdata->resindex_dma_base = desc->resindex_dma_base;
146 if (desc->resindex_dma_base >= 0) {
147 sst_pdata->dma_engine = desc->dma_engine;
148 sst_pdata->dma_base = desc->resindex_dma_base;
149 sst_pdata->dma_size = desc->dma_size;
150 }
151
152 if (desc->irqindex_host_ipc >= 0)
153 sst_pdata->irq = platform_get_irq(pdev, desc->irqindex_host_ipc);
154
155 if (desc->resindex_lpe_base >= 0) {
156 mmio = platform_get_resource(pdev, IORESOURCE_MEM,
157 desc->resindex_lpe_base);
158 if (mmio) {
159 sst_pdata->lpe_base = mmio->start;
160 sst_pdata->lpe_size = resource_size(mmio);
161 }
162 }
163
164 if (desc->resindex_pcicfg_base >= 0) {
165 mmio = platform_get_resource(pdev, IORESOURCE_MEM,
166 desc->resindex_pcicfg_base);
167 if (mmio) {
168 sst_pdata->pcicfg_base = mmio->start;
169 sst_pdata->pcicfg_size = resource_size(mmio);
170 }
171 }
172
173 if (desc->resindex_fw_base >= 0) {
174 mmio = platform_get_resource(pdev, IORESOURCE_MEM,
175 desc->resindex_fw_base);
176 if (mmio) {
177 sst_pdata->fw_base = mmio->start;
178 sst_pdata->fw_size = resource_size(mmio);
179 }
180 }
181
182 platform_set_drvdata(pdev, sst_acpi);
183
184 /* register machine driver */
185 sst_acpi->pdev_mach =
186 platform_device_register_data(dev, mach->drv_name, -1,
187 sst_pdata, sizeof(*sst_pdata));
188 if (IS_ERR(sst_acpi->pdev_mach))
189 return PTR_ERR(sst_acpi->pdev_mach);
190
191 /* continue SST probing after firmware is loaded */
192 ret = request_firmware_nowait(THIS_MODULE, true, mach->fw_filename,
193 dev, GFP_KERNEL, pdev, sst_acpi_fw_cb);
194 if (ret)
195 platform_device_unregister(sst_acpi->pdev_mach);
196
197 return ret;
198}
199
200static int sst_acpi_remove(struct platform_device *pdev)
201{
202 struct sst_acpi_priv *sst_acpi = platform_get_drvdata(pdev);
203 struct sst_pdata *sst_pdata = &sst_acpi->sst_pdata;
204
205 platform_device_unregister(sst_acpi->pdev_mach);
206 if (!IS_ERR_OR_NULL(sst_acpi->pdev_pcm))
207 platform_device_unregister(sst_acpi->pdev_pcm);
208 release_firmware(sst_pdata->fw);
209
210 return 0;
211}
212
213static struct sst_acpi_mach haswell_machines[] = {
214 { "INT33CA", "haswell-audio", "intel/IntcSST1.bin" },
215 {}
216};
217
218static struct sst_acpi_desc sst_acpi_haswell_desc = {
219 .drv_name = "haswell-pcm-audio",
220 .machines = haswell_machines,
221 .resindex_lpe_base = 0,
222 .resindex_pcicfg_base = 1,
223 .resindex_fw_base = -1,
224 .irqindex_host_ipc = 0,
225 .sst_id = SST_DEV_ID_LYNX_POINT,
226 .dma_engine = SST_DMA_TYPE_DW,
227 .resindex_dma_base = SST_LPT_DSP_DMA_ADDR_OFFSET,
228 .dma_size = SST_LPT_DSP_DMA_SIZE,
229};
230
231static struct sst_acpi_mach broadwell_machines[] = {
232 { "INT343A", "broadwell-audio", "intel/IntcSST2.bin" },
233 {}
234};
235
236static struct sst_acpi_desc sst_acpi_broadwell_desc = {
237 .drv_name = "haswell-pcm-audio",
238 .machines = broadwell_machines,
239 .resindex_lpe_base = 0,
240 .resindex_pcicfg_base = 1,
241 .resindex_fw_base = -1,
242 .irqindex_host_ipc = 0,
243 .sst_id = SST_DEV_ID_WILDCAT_POINT,
244 .dma_engine = SST_DMA_TYPE_DW,
245 .resindex_dma_base = SST_WPT_DSP_DMA_ADDR_OFFSET,
246 .dma_size = SST_LPT_DSP_DMA_SIZE,
247};
248
249static struct sst_acpi_mach baytrail_machines[] = {
250 { "10EC5640", "byt-rt5640", "intel/fw_sst_0f28.bin-48kHz_i2s_master" },
251 { "193C9890", "byt-max98090", "intel/fw_sst_0f28.bin-48kHz_i2s_master" },
252 {}
253};
254
255static struct sst_acpi_desc sst_acpi_baytrail_desc = {
256 .drv_name = "baytrail-pcm-audio",
257 .machines = baytrail_machines,
258 .resindex_lpe_base = 0,
259 .resindex_pcicfg_base = 1,
260 .resindex_fw_base = 2,
261 .irqindex_host_ipc = 5,
262 .sst_id = SST_DEV_ID_BYT,
263 .resindex_dma_base = -1,
264};
265
266static struct acpi_device_id sst_acpi_match[] = {
267 { "INT33C8", (unsigned long)&sst_acpi_haswell_desc },
268 { "INT3438", (unsigned long)&sst_acpi_broadwell_desc },
269 { "80860F28", (unsigned long)&sst_acpi_baytrail_desc },
270 { }
271};
272MODULE_DEVICE_TABLE(acpi, sst_acpi_match);
273
274static struct platform_driver sst_acpi_driver = {
275 .probe = sst_acpi_probe,
276 .remove = sst_acpi_remove,
277 .driver = {
278 .name = "sst-acpi",
279 .acpi_match_table = ACPI_PTR(sst_acpi_match),
280 },
281};
282module_platform_driver(sst_acpi_driver);
283
284MODULE_AUTHOR("Jarkko Nikula <jarkko.nikula@linux.intel.com>");
285MODULE_DESCRIPTION("Intel SST loader on ACPI systems");
286MODULE_LICENSE("GPL v2");
diff --git a/sound/soc/intel/common/sst-dsp-priv.h b/sound/soc/intel/common/sst-dsp-priv.h
new file mode 100644
index 000000000000..396d54510350
--- /dev/null
+++ b/sound/soc/intel/common/sst-dsp-priv.h
@@ -0,0 +1,373 @@
1/*
2 * Intel Smart Sound Technology
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#ifndef __SOUND_SOC_SST_DSP_PRIV_H
18#define __SOUND_SOC_SST_DSP_PRIV_H
19
20#include <linux/kernel.h>
21#include <linux/types.h>
22#include <linux/interrupt.h>
23#include <linux/firmware.h>
24
25struct sst_mem_block;
26struct sst_module;
27struct sst_fw;
28
29/* do we need to remove or keep */
30#define DSP_DRAM_ADDR_OFFSET 0x400000
31
32/*
33 * DSP Operations exported by platform Audio DSP driver.
34 */
35struct sst_ops {
36 /* DSP core boot / reset */
37 void (*boot)(struct sst_dsp *);
38 void (*reset)(struct sst_dsp *);
39 int (*wake)(struct sst_dsp *);
40 void (*sleep)(struct sst_dsp *);
41 void (*stall)(struct sst_dsp *);
42
43 /* Shim IO */
44 void (*write)(void __iomem *addr, u32 offset, u32 value);
45 u32 (*read)(void __iomem *addr, u32 offset);
46 void (*write64)(void __iomem *addr, u32 offset, u64 value);
47 u64 (*read64)(void __iomem *addr, u32 offset);
48
49 /* DSP I/DRAM IO */
50 void (*ram_read)(struct sst_dsp *sst, void *dest, void __iomem *src,
51 size_t bytes);
52 void (*ram_write)(struct sst_dsp *sst, void __iomem *dest, void *src,
53 size_t bytes);
54
55 void (*dump)(struct sst_dsp *);
56
57 /* IRQ handlers */
58 irqreturn_t (*irq_handler)(int irq, void *context);
59
60 /* SST init and free */
61 int (*init)(struct sst_dsp *sst, struct sst_pdata *pdata);
62 void (*free)(struct sst_dsp *sst);
63
64 /* FW module parser/loader */
65 int (*parse_fw)(struct sst_fw *sst_fw);
66};
67
68/*
69 * Audio DSP memory offsets and addresses.
70 */
71struct sst_addr {
72 u32 lpe_base;
73 u32 shim_offset;
74 u32 iram_offset;
75 u32 dram_offset;
76 u32 dsp_iram_offset;
77 u32 dsp_dram_offset;
78 void __iomem *lpe;
79 void __iomem *shim;
80 void __iomem *pci_cfg;
81 void __iomem *fw_ext;
82};
83
84/*
85 * Audio DSP Mailbox configuration.
86 */
87struct sst_mailbox {
88 void __iomem *in_base;
89 void __iomem *out_base;
90 size_t in_size;
91 size_t out_size;
92};
93
94/*
95 * Audio DSP memory block types.
96 */
97enum sst_mem_type {
98 SST_MEM_IRAM = 0,
99 SST_MEM_DRAM = 1,
100 SST_MEM_ANY = 2,
101 SST_MEM_CACHE= 3,
102};
103
104/*
105 * Audio DSP Generic Firmware File.
106 *
107 * SST Firmware files can consist of 1..N modules. This generic structure is
108 * used to manage each firmware file and it's modules regardless of SST firmware
109 * type. A SST driver may load multiple FW files.
110 */
111struct sst_fw {
112 struct sst_dsp *dsp;
113
114 /* base addresses of FW file data */
115 dma_addr_t dmable_fw_paddr; /* physical address of fw data */
116 void *dma_buf; /* virtual address of fw data */
117 u32 size; /* size of fw data */
118
119 /* lists */
120 struct list_head list; /* DSP list of FW */
121 struct list_head module_list; /* FW list of modules */
122
123 void *private; /* core doesn't touch this */
124};
125
126/*
127 * Audio DSP Generic Module Template.
128 *
129 * Used to define and register a new FW module. This data is extracted from
130 * FW module header information.
131 */
132struct sst_module_template {
133 u32 id;
134 u32 entry; /* entry point */
135 u32 scratch_size;
136 u32 persistent_size;
137};
138
139/*
140 * Block Allocator - Used to allocate blocks of DSP memory.
141 */
142struct sst_block_allocator {
143 u32 id;
144 u32 offset;
145 int size;
146 enum sst_mem_type type;
147};
148
149/*
150 * Runtime Module Instance - A module object can be instanciated multiple
151 * times within the DSP FW.
152 */
153struct sst_module_runtime {
154 struct sst_dsp *dsp;
155 int id;
156 struct sst_module *module; /* parent module we belong too */
157
158 u32 persistent_offset; /* private memory offset */
159 void *private;
160
161 struct list_head list;
162 struct list_head block_list; /* list of blocks used */
163};
164
165/*
166 * Runtime Module Context - The runtime context must be manually stored by the
167 * driver prior to enter S3 and restored after leaving S3. This should really be
168 * part of the memory context saved by the enter D3 message IPC ???
169 */
170struct sst_module_runtime_context {
171 dma_addr_t dma_buffer;
172 u32 *buffer;
173};
174
175/*
176 * Audio DSP Module State
177 */
178enum sst_module_state {
179 SST_MODULE_STATE_UNLOADED = 0, /* default state */
180 SST_MODULE_STATE_LOADED,
181 SST_MODULE_STATE_INITIALIZED, /* and inactive */
182 SST_MODULE_STATE_ACTIVE,
183};
184
185/*
186 * Audio DSP Generic Module.
187 *
188 * Each Firmware file can consist of 1..N modules. A module can span multiple
189 * ADSP memory blocks. The simplest FW will be a file with 1 module. A module
190 * can be instanciated multiple times in the DSP.
191 */
192struct sst_module {
193 struct sst_dsp *dsp;
194 struct sst_fw *sst_fw; /* parent FW we belong too */
195
196 /* module configuration */
197 u32 id;
198 u32 entry; /* module entry point */
199 s32 offset; /* module offset in firmware file */
200 u32 size; /* module size */
201 u32 scratch_size; /* global scratch memory required */
202 u32 persistent_size; /* private memory required */
203 enum sst_mem_type type; /* destination memory type */
204 u32 data_offset; /* offset in ADSP memory space */
205 void *data; /* module data */
206
207 /* runtime */
208 u32 usage_count; /* can be unloaded if count == 0 */
209 void *private; /* core doesn't touch this */
210
211 /* lists */
212 struct list_head block_list; /* Module list of blocks in use */
213 struct list_head list; /* DSP list of modules */
214 struct list_head list_fw; /* FW list of modules */
215 struct list_head runtime_list; /* list of runtime module objects*/
216
217 /* state */
218 enum sst_module_state state;
219};
220
221/*
222 * SST Memory Block operations.
223 */
224struct sst_block_ops {
225 int (*enable)(struct sst_mem_block *block);
226 int (*disable)(struct sst_mem_block *block);
227};
228
229/*
230 * SST Generic Memory Block.
231 *
232 * SST ADP memory has multiple IRAM and DRAM blocks. Some ADSP blocks can be
233 * power gated.
234 */
235struct sst_mem_block {
236 struct sst_dsp *dsp;
237 struct sst_module *module; /* module that uses this block */
238
239 /* block config */
240 u32 offset; /* offset from base */
241 u32 size; /* block size */
242 u32 index; /* block index 0..N */
243 enum sst_mem_type type; /* block memory type IRAM/DRAM */
244 struct sst_block_ops *ops; /* block operations, if any */
245
246 /* block status */
247 u32 bytes_used; /* bytes in use by modules */
248 void *private; /* generic core does not touch this */
249 int users; /* number of modules using this block */
250
251 /* block lists */
252 struct list_head module_list; /* Module list of blocks */
253 struct list_head list; /* Map list of free/used blocks */
254};
255
256/*
257 * Generic SST Shim Interface.
258 */
259struct sst_dsp {
260
261 /* runtime */
262 struct sst_dsp_device *sst_dev;
263 spinlock_t spinlock; /* IPC locking */
264 struct mutex mutex; /* DSP FW lock */
265 struct device *dev;
266 struct device *dma_dev;
267 void *thread_context;
268 int irq;
269 u32 id;
270
271 /* list of free and used ADSP memory blocks */
272 struct list_head used_block_list;
273 struct list_head free_block_list;
274
275 /* operations */
276 struct sst_ops *ops;
277
278 /* debug FS */
279 struct dentry *debugfs_root;
280
281 /* base addresses */
282 struct sst_addr addr;
283
284 /* mailbox */
285 struct sst_mailbox mailbox;
286
287 /* SST FW files loaded and their modules */
288 struct list_head module_list;
289 struct list_head fw_list;
290
291 /* scratch buffer */
292 struct list_head scratch_block_list;
293 u32 scratch_offset;
294 u32 scratch_size;
295
296 /* platform data */
297 struct sst_pdata *pdata;
298
299 /* DMA FW loading */
300 struct sst_dma *dma;
301 bool fw_use_dma;
302};
303
304/* Size optimised DRAM/IRAM memcpy */
305static inline void sst_dsp_write(struct sst_dsp *sst, void *src,
306 u32 dest_offset, size_t bytes)
307{
308 sst->ops->ram_write(sst, sst->addr.lpe + dest_offset, src, bytes);
309}
310
311static inline void sst_dsp_read(struct sst_dsp *sst, void *dest,
312 u32 src_offset, size_t bytes)
313{
314 sst->ops->ram_read(sst, dest, sst->addr.lpe + src_offset, bytes);
315}
316
317static inline void *sst_dsp_get_thread_context(struct sst_dsp *sst)
318{
319 return sst->thread_context;
320}
321
322/* Create/Free FW files - can contain multiple modules */
323struct sst_fw *sst_fw_new(struct sst_dsp *dsp,
324 const struct firmware *fw, void *private);
325void sst_fw_free(struct sst_fw *sst_fw);
326void sst_fw_free_all(struct sst_dsp *dsp);
327int sst_fw_reload(struct sst_fw *sst_fw);
328void sst_fw_unload(struct sst_fw *sst_fw);
329
330/* Create/Free firmware modules */
331struct sst_module *sst_module_new(struct sst_fw *sst_fw,
332 struct sst_module_template *template, void *private);
333void sst_module_free(struct sst_module *module);
334struct sst_module *sst_module_get_from_id(struct sst_dsp *dsp, u32 id);
335int sst_module_alloc_blocks(struct sst_module *module);
336int sst_module_free_blocks(struct sst_module *module);
337
338/* Create/Free firmware module runtime instances */
339struct sst_module_runtime *sst_module_runtime_new(struct sst_module *module,
340 int id, void *private);
341void sst_module_runtime_free(struct sst_module_runtime *runtime);
342struct sst_module_runtime *sst_module_runtime_get_from_id(
343 struct sst_module *module, u32 id);
344int sst_module_runtime_alloc_blocks(struct sst_module_runtime *runtime,
345 int offset);
346int sst_module_runtime_free_blocks(struct sst_module_runtime *runtime);
347int sst_module_runtime_save(struct sst_module_runtime *runtime,
348 struct sst_module_runtime_context *context);
349int sst_module_runtime_restore(struct sst_module_runtime *runtime,
350 struct sst_module_runtime_context *context);
351
352/* generic block allocation */
353int sst_alloc_blocks(struct sst_dsp *dsp, struct sst_block_allocator *ba,
354 struct list_head *block_list);
355int sst_free_blocks(struct sst_dsp *dsp, struct list_head *block_list);
356
357/* scratch allocation */
358int sst_block_alloc_scratch(struct sst_dsp *dsp);
359void sst_block_free_scratch(struct sst_dsp *dsp);
360
361/* Register the DSPs memory blocks - would be nice to read from ACPI */
362struct sst_mem_block *sst_mem_block_register(struct sst_dsp *dsp, u32 offset,
363 u32 size, enum sst_mem_type type, struct sst_block_ops *ops, u32 index,
364 void *private);
365void sst_mem_block_unregister_all(struct sst_dsp *dsp);
366
367/* Create/Free DMA resources */
368int sst_dma_new(struct sst_dsp *sst);
369void sst_dma_free(struct sst_dma *dma);
370
371u32 sst_dsp_get_offset(struct sst_dsp *dsp, u32 offset,
372 enum sst_mem_type type);
373#endif
diff --git a/sound/soc/intel/common/sst-dsp.c b/sound/soc/intel/common/sst-dsp.c
new file mode 100644
index 000000000000..64e94212d2d2
--- /dev/null
+++ b/sound/soc/intel/common/sst-dsp.c
@@ -0,0 +1,420 @@
1/*
2 * Intel Smart Sound Technology (SST) DSP Core Driver
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/slab.h>
18#include <linux/export.h>
19#include <linux/interrupt.h>
20#include <linux/module.h>
21#include <linux/platform_device.h>
22#include <linux/io.h>
23
24#include "sst-dsp.h"
25#include "sst-dsp-priv.h"
26
27#define CREATE_TRACE_POINTS
28#include <trace/events/intel-sst.h>
29
30/* Internal generic low-level SST IO functions - can be overidden */
31void sst_shim32_write(void __iomem *addr, u32 offset, u32 value)
32{
33 writel(value, addr + offset);
34}
35EXPORT_SYMBOL_GPL(sst_shim32_write);
36
37u32 sst_shim32_read(void __iomem *addr, u32 offset)
38{
39 return readl(addr + offset);
40}
41EXPORT_SYMBOL_GPL(sst_shim32_read);
42
43void sst_shim32_write64(void __iomem *addr, u32 offset, u64 value)
44{
45 memcpy_toio(addr + offset, &value, sizeof(value));
46}
47EXPORT_SYMBOL_GPL(sst_shim32_write64);
48
49u64 sst_shim32_read64(void __iomem *addr, u32 offset)
50{
51 u64 val;
52
53 memcpy_fromio(&val, addr + offset, sizeof(val));
54 return val;
55}
56EXPORT_SYMBOL_GPL(sst_shim32_read64);
57
58static inline void _sst_memcpy_toio_32(volatile u32 __iomem *dest,
59 u32 *src, size_t bytes)
60{
61 int i, words = bytes >> 2;
62
63 for (i = 0; i < words; i++)
64 writel(src[i], dest + i);
65}
66
67static inline void _sst_memcpy_fromio_32(u32 *dest,
68 const volatile __iomem u32 *src, size_t bytes)
69{
70 int i, words = bytes >> 2;
71
72 for (i = 0; i < words; i++)
73 dest[i] = readl(src + i);
74}
75
76void sst_memcpy_toio_32(struct sst_dsp *sst,
77 void __iomem *dest, void *src, size_t bytes)
78{
79 _sst_memcpy_toio_32(dest, src, bytes);
80}
81EXPORT_SYMBOL_GPL(sst_memcpy_toio_32);
82
83void sst_memcpy_fromio_32(struct sst_dsp *sst, void *dest,
84 void __iomem *src, size_t bytes)
85{
86 _sst_memcpy_fromio_32(dest, src, bytes);
87}
88EXPORT_SYMBOL_GPL(sst_memcpy_fromio_32);
89
90/* Public API */
91void sst_dsp_shim_write(struct sst_dsp *sst, u32 offset, u32 value)
92{
93 unsigned long flags;
94
95 spin_lock_irqsave(&sst->spinlock, flags);
96 sst->ops->write(sst->addr.shim, offset, value);
97 spin_unlock_irqrestore(&sst->spinlock, flags);
98}
99EXPORT_SYMBOL_GPL(sst_dsp_shim_write);
100
101u32 sst_dsp_shim_read(struct sst_dsp *sst, u32 offset)
102{
103 unsigned long flags;
104 u32 val;
105
106 spin_lock_irqsave(&sst->spinlock, flags);
107 val = sst->ops->read(sst->addr.shim, offset);
108 spin_unlock_irqrestore(&sst->spinlock, flags);
109
110 return val;
111}
112EXPORT_SYMBOL_GPL(sst_dsp_shim_read);
113
114void sst_dsp_shim_write64(struct sst_dsp *sst, u32 offset, u64 value)
115{
116 unsigned long flags;
117
118 spin_lock_irqsave(&sst->spinlock, flags);
119 sst->ops->write64(sst->addr.shim, offset, value);
120 spin_unlock_irqrestore(&sst->spinlock, flags);
121}
122EXPORT_SYMBOL_GPL(sst_dsp_shim_write64);
123
124u64 sst_dsp_shim_read64(struct sst_dsp *sst, u32 offset)
125{
126 unsigned long flags;
127 u64 val;
128
129 spin_lock_irqsave(&sst->spinlock, flags);
130 val = sst->ops->read64(sst->addr.shim, offset);
131 spin_unlock_irqrestore(&sst->spinlock, flags);
132
133 return val;
134}
135EXPORT_SYMBOL_GPL(sst_dsp_shim_read64);
136
137void sst_dsp_shim_write_unlocked(struct sst_dsp *sst, u32 offset, u32 value)
138{
139 sst->ops->write(sst->addr.shim, offset, value);
140}
141EXPORT_SYMBOL_GPL(sst_dsp_shim_write_unlocked);
142
143u32 sst_dsp_shim_read_unlocked(struct sst_dsp *sst, u32 offset)
144{
145 return sst->ops->read(sst->addr.shim, offset);
146}
147EXPORT_SYMBOL_GPL(sst_dsp_shim_read_unlocked);
148
149void sst_dsp_shim_write64_unlocked(struct sst_dsp *sst, u32 offset, u64 value)
150{
151 sst->ops->write64(sst->addr.shim, offset, value);
152}
153EXPORT_SYMBOL_GPL(sst_dsp_shim_write64_unlocked);
154
155u64 sst_dsp_shim_read64_unlocked(struct sst_dsp *sst, u32 offset)
156{
157 return sst->ops->read64(sst->addr.shim, offset);
158}
159EXPORT_SYMBOL_GPL(sst_dsp_shim_read64_unlocked);
160
161int sst_dsp_shim_update_bits_unlocked(struct sst_dsp *sst, u32 offset,
162 u32 mask, u32 value)
163{
164 bool change;
165 unsigned int old, new;
166 u32 ret;
167
168 ret = sst_dsp_shim_read_unlocked(sst, offset);
169
170 old = ret;
171 new = (old & (~mask)) | (value & mask);
172
173 change = (old != new);
174 if (change)
175 sst_dsp_shim_write_unlocked(sst, offset, new);
176
177 return change;
178}
179EXPORT_SYMBOL_GPL(sst_dsp_shim_update_bits_unlocked);
180
181int sst_dsp_shim_update_bits64_unlocked(struct sst_dsp *sst, u32 offset,
182 u64 mask, u64 value)
183{
184 bool change;
185 u64 old, new;
186
187 old = sst_dsp_shim_read64_unlocked(sst, offset);
188
189 new = (old & (~mask)) | (value & mask);
190
191 change = (old != new);
192 if (change)
193 sst_dsp_shim_write64_unlocked(sst, offset, new);
194
195 return change;
196}
197EXPORT_SYMBOL_GPL(sst_dsp_shim_update_bits64_unlocked);
198
199int sst_dsp_shim_update_bits(struct sst_dsp *sst, u32 offset,
200 u32 mask, u32 value)
201{
202 unsigned long flags;
203 bool change;
204
205 spin_lock_irqsave(&sst->spinlock, flags);
206 change = sst_dsp_shim_update_bits_unlocked(sst, offset, mask, value);
207 spin_unlock_irqrestore(&sst->spinlock, flags);
208 return change;
209}
210EXPORT_SYMBOL_GPL(sst_dsp_shim_update_bits);
211
212int sst_dsp_shim_update_bits64(struct sst_dsp *sst, u32 offset,
213 u64 mask, u64 value)
214{
215 unsigned long flags;
216 bool change;
217
218 spin_lock_irqsave(&sst->spinlock, flags);
219 change = sst_dsp_shim_update_bits64_unlocked(sst, offset, mask, value);
220 spin_unlock_irqrestore(&sst->spinlock, flags);
221 return change;
222}
223EXPORT_SYMBOL_GPL(sst_dsp_shim_update_bits64);
224
225void sst_dsp_dump(struct sst_dsp *sst)
226{
227 if (sst->ops->dump)
228 sst->ops->dump(sst);
229}
230EXPORT_SYMBOL_GPL(sst_dsp_dump);
231
232void sst_dsp_reset(struct sst_dsp *sst)
233{
234 if (sst->ops->reset)
235 sst->ops->reset(sst);
236}
237EXPORT_SYMBOL_GPL(sst_dsp_reset);
238
239int sst_dsp_boot(struct sst_dsp *sst)
240{
241 if (sst->ops->boot)
242 sst->ops->boot(sst);
243
244 return 0;
245}
246EXPORT_SYMBOL_GPL(sst_dsp_boot);
247
248int sst_dsp_wake(struct sst_dsp *sst)
249{
250 if (sst->ops->wake)
251 return sst->ops->wake(sst);
252
253 return 0;
254}
255EXPORT_SYMBOL_GPL(sst_dsp_wake);
256
257void sst_dsp_sleep(struct sst_dsp *sst)
258{
259 if (sst->ops->sleep)
260 sst->ops->sleep(sst);
261}
262EXPORT_SYMBOL_GPL(sst_dsp_sleep);
263
264void sst_dsp_stall(struct sst_dsp *sst)
265{
266 if (sst->ops->stall)
267 sst->ops->stall(sst);
268}
269EXPORT_SYMBOL_GPL(sst_dsp_stall);
270
271void sst_dsp_ipc_msg_tx(struct sst_dsp *dsp, u32 msg)
272{
273 sst_dsp_shim_write_unlocked(dsp, SST_IPCX, msg | SST_IPCX_BUSY);
274 trace_sst_ipc_msg_tx(msg);
275}
276EXPORT_SYMBOL_GPL(sst_dsp_ipc_msg_tx);
277
278u32 sst_dsp_ipc_msg_rx(struct sst_dsp *dsp)
279{
280 u32 msg;
281
282 msg = sst_dsp_shim_read_unlocked(dsp, SST_IPCX);
283 trace_sst_ipc_msg_rx(msg);
284
285 return msg;
286}
287EXPORT_SYMBOL_GPL(sst_dsp_ipc_msg_rx);
288
289int sst_dsp_mailbox_init(struct sst_dsp *sst, u32 inbox_offset, size_t inbox_size,
290 u32 outbox_offset, size_t outbox_size)
291{
292 sst->mailbox.in_base = sst->addr.lpe + inbox_offset;
293 sst->mailbox.out_base = sst->addr.lpe + outbox_offset;
294 sst->mailbox.in_size = inbox_size;
295 sst->mailbox.out_size = outbox_size;
296 return 0;
297}
298EXPORT_SYMBOL_GPL(sst_dsp_mailbox_init);
299
300void sst_dsp_outbox_write(struct sst_dsp *sst, void *message, size_t bytes)
301{
302 u32 i;
303
304 trace_sst_ipc_outbox_write(bytes);
305
306 memcpy_toio(sst->mailbox.out_base, message, bytes);
307
308 for (i = 0; i < bytes; i += 4)
309 trace_sst_ipc_outbox_wdata(i, *(u32 *)(message + i));
310}
311EXPORT_SYMBOL_GPL(sst_dsp_outbox_write);
312
313void sst_dsp_outbox_read(struct sst_dsp *sst, void *message, size_t bytes)
314{
315 u32 i;
316
317 trace_sst_ipc_outbox_read(bytes);
318
319 memcpy_fromio(message, sst->mailbox.out_base, bytes);
320
321 for (i = 0; i < bytes; i += 4)
322 trace_sst_ipc_outbox_rdata(i, *(u32 *)(message + i));
323}
324EXPORT_SYMBOL_GPL(sst_dsp_outbox_read);
325
326void sst_dsp_inbox_write(struct sst_dsp *sst, void *message, size_t bytes)
327{
328 u32 i;
329
330 trace_sst_ipc_inbox_write(bytes);
331
332 memcpy_toio(sst->mailbox.in_base, message, bytes);
333
334 for (i = 0; i < bytes; i += 4)
335 trace_sst_ipc_inbox_wdata(i, *(u32 *)(message + i));
336}
337EXPORT_SYMBOL_GPL(sst_dsp_inbox_write);
338
339void sst_dsp_inbox_read(struct sst_dsp *sst, void *message, size_t bytes)
340{
341 u32 i;
342
343 trace_sst_ipc_inbox_read(bytes);
344
345 memcpy_fromio(message, sst->mailbox.in_base, bytes);
346
347 for (i = 0; i < bytes; i += 4)
348 trace_sst_ipc_inbox_rdata(i, *(u32 *)(message + i));
349}
350EXPORT_SYMBOL_GPL(sst_dsp_inbox_read);
351
352struct sst_dsp *sst_dsp_new(struct device *dev,
353 struct sst_dsp_device *sst_dev, struct sst_pdata *pdata)
354{
355 struct sst_dsp *sst;
356 int err;
357
358 dev_dbg(dev, "initialising audio DSP id 0x%x\n", pdata->id);
359
360 sst = devm_kzalloc(dev, sizeof(*sst), GFP_KERNEL);
361 if (sst == NULL)
362 return NULL;
363
364 spin_lock_init(&sst->spinlock);
365 mutex_init(&sst->mutex);
366 sst->dev = dev;
367 sst->dma_dev = pdata->dma_dev;
368 sst->thread_context = sst_dev->thread_context;
369 sst->sst_dev = sst_dev;
370 sst->id = pdata->id;
371 sst->irq = pdata->irq;
372 sst->ops = sst_dev->ops;
373 sst->pdata = pdata;
374 INIT_LIST_HEAD(&sst->used_block_list);
375 INIT_LIST_HEAD(&sst->free_block_list);
376 INIT_LIST_HEAD(&sst->module_list);
377 INIT_LIST_HEAD(&sst->fw_list);
378 INIT_LIST_HEAD(&sst->scratch_block_list);
379
380 /* Initialise SST Audio DSP */
381 if (sst->ops->init) {
382 err = sst->ops->init(sst, pdata);
383 if (err < 0)
384 return NULL;
385 }
386
387 /* Register the ISR */
388 err = request_threaded_irq(sst->irq, sst->ops->irq_handler,
389 sst_dev->thread, IRQF_SHARED, "AudioDSP", sst);
390 if (err)
391 goto irq_err;
392
393 err = sst_dma_new(sst);
394 if (err)
395 dev_warn(dev, "sst_dma_new failed %d\n", err);
396
397 return sst;
398
399irq_err:
400 if (sst->ops->free)
401 sst->ops->free(sst);
402
403 return NULL;
404}
405EXPORT_SYMBOL_GPL(sst_dsp_new);
406
407void sst_dsp_free(struct sst_dsp *sst)
408{
409 free_irq(sst->irq, sst);
410 if (sst->ops->free)
411 sst->ops->free(sst);
412
413 sst_dma_free(sst->dma);
414}
415EXPORT_SYMBOL_GPL(sst_dsp_free);
416
417/* Module information */
418MODULE_AUTHOR("Liam Girdwood");
419MODULE_DESCRIPTION("Intel SST Core");
420MODULE_LICENSE("GPL v2");
diff --git a/sound/soc/intel/common/sst-dsp.h b/sound/soc/intel/common/sst-dsp.h
new file mode 100644
index 000000000000..96aeb2556ad4
--- /dev/null
+++ b/sound/soc/intel/common/sst-dsp.h
@@ -0,0 +1,285 @@
1/*
2 * Intel Smart Sound Technology (SST) Core
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#ifndef __SOUND_SOC_SST_DSP_H
18#define __SOUND_SOC_SST_DSP_H
19
20#include <linux/kernel.h>
21#include <linux/types.h>
22#include <linux/interrupt.h>
23
24/* SST Device IDs */
25#define SST_DEV_ID_LYNX_POINT 0x33C8
26#define SST_DEV_ID_WILDCAT_POINT 0x3438
27#define SST_DEV_ID_BYT 0x0F28
28
29/* Supported SST DMA Devices */
30#define SST_DMA_TYPE_DW 1
31
32/* autosuspend delay 5s*/
33#define SST_RUNTIME_SUSPEND_DELAY (5 * 1000)
34
35/* SST Shim register map
36 * The register naming can differ between products. Some products also
37 * contain extra functionality.
38 */
39#define SST_CSR 0x00
40#define SST_PISR 0x08
41#define SST_PIMR 0x10
42#define SST_ISRX 0x18
43#define SST_ISRD 0x20
44#define SST_IMRX 0x28
45#define SST_IMRD 0x30
46#define SST_IPCX 0x38 /* IPC IA -> SST */
47#define SST_IPCD 0x40 /* IPC SST -> IA */
48#define SST_ISRSC 0x48
49#define SST_ISRLPESC 0x50
50#define SST_IMRSC 0x58
51#define SST_IMRLPESC 0x60
52#define SST_IPCSC 0x68
53#define SST_IPCLPESC 0x70
54#define SST_CLKCTL 0x78
55#define SST_CSR2 0x80
56#define SST_LTRC 0xE0
57#define SST_HMDC 0xE8
58
59#define SST_SHIM_BEGIN SST_CSR
60#define SST_SHIM_END SST_HDMC
61
62#define SST_DBGO 0xF0
63
64#define SST_SHIM_SIZE 0x100
65#define SST_PWMCTRL 0x1000
66
67/* SST Shim Register bits
68 * The register bit naming can differ between products. Some products also
69 * contain extra functionality.
70 */
71
72/* CSR / CS */
73#define SST_CSR_RST (0x1 << 1)
74#define SST_CSR_SBCS0 (0x1 << 2)
75#define SST_CSR_SBCS1 (0x1 << 3)
76#define SST_CSR_DCS(x) (x << 4)
77#define SST_CSR_DCS_MASK (0x7 << 4)
78#define SST_CSR_STALL (0x1 << 10)
79#define SST_CSR_S0IOCS (0x1 << 21)
80#define SST_CSR_S1IOCS (0x1 << 23)
81#define SST_CSR_LPCS (0x1 << 31)
82#define SST_CSR_24MHZ_LPCS (SST_CSR_SBCS0 | SST_CSR_SBCS1 | SST_CSR_LPCS)
83#define SST_CSR_24MHZ_NO_LPCS (SST_CSR_SBCS0 | SST_CSR_SBCS1)
84#define SST_BYT_CSR_RST (0x1 << 0)
85#define SST_BYT_CSR_VECTOR_SEL (0x1 << 1)
86#define SST_BYT_CSR_STALL (0x1 << 2)
87#define SST_BYT_CSR_PWAITMODE (0x1 << 3)
88
89/* ISRX / ISC */
90#define SST_ISRX_BUSY (0x1 << 1)
91#define SST_ISRX_DONE (0x1 << 0)
92#define SST_BYT_ISRX_REQUEST (0x1 << 1)
93
94/* ISRD / ISD */
95#define SST_ISRD_BUSY (0x1 << 1)
96#define SST_ISRD_DONE (0x1 << 0)
97
98/* IMRX / IMC */
99#define SST_IMRX_BUSY (0x1 << 1)
100#define SST_IMRX_DONE (0x1 << 0)
101#define SST_BYT_IMRX_REQUEST (0x1 << 1)
102
103/* IMRD / IMD */
104#define SST_IMRD_DONE (0x1 << 0)
105#define SST_IMRD_BUSY (0x1 << 1)
106#define SST_IMRD_SSP0 (0x1 << 16)
107#define SST_IMRD_DMAC0 (0x1 << 21)
108#define SST_IMRD_DMAC1 (0x1 << 22)
109#define SST_IMRD_DMAC (SST_IMRD_DMAC0 | SST_IMRD_DMAC1)
110
111/* IPCX / IPCC */
112#define SST_IPCX_DONE (0x1 << 30)
113#define SST_IPCX_BUSY (0x1 << 31)
114#define SST_BYT_IPCX_DONE ((u64)0x1 << 62)
115#define SST_BYT_IPCX_BUSY ((u64)0x1 << 63)
116
117/* IPCD */
118#define SST_IPCD_DONE (0x1 << 30)
119#define SST_IPCD_BUSY (0x1 << 31)
120#define SST_BYT_IPCD_DONE ((u64)0x1 << 62)
121#define SST_BYT_IPCD_BUSY ((u64)0x1 << 63)
122
123/* CLKCTL */
124#define SST_CLKCTL_SMOS(x) (x << 24)
125#define SST_CLKCTL_MASK (3 << 24)
126#define SST_CLKCTL_DCPLCG (1 << 18)
127#define SST_CLKCTL_SCOE1 (1 << 17)
128#define SST_CLKCTL_SCOE0 (1 << 16)
129
130/* CSR2 / CS2 */
131#define SST_CSR2_SDFD_SSP0 (1 << 1)
132#define SST_CSR2_SDFD_SSP1 (1 << 2)
133
134/* LTRC */
135#define SST_LTRC_VAL(x) (x << 0)
136
137/* HMDC */
138#define SST_HMDC_HDDA0(x) (x << 0)
139#define SST_HMDC_HDDA1(x) (x << 7)
140#define SST_HMDC_HDDA_E0_CH0 1
141#define SST_HMDC_HDDA_E0_CH1 2
142#define SST_HMDC_HDDA_E0_CH2 4
143#define SST_HMDC_HDDA_E0_CH3 8
144#define SST_HMDC_HDDA_E1_CH0 SST_HMDC_HDDA1(SST_HMDC_HDDA_E0_CH0)
145#define SST_HMDC_HDDA_E1_CH1 SST_HMDC_HDDA1(SST_HMDC_HDDA_E0_CH1)
146#define SST_HMDC_HDDA_E1_CH2 SST_HMDC_HDDA1(SST_HMDC_HDDA_E0_CH2)
147#define SST_HMDC_HDDA_E1_CH3 SST_HMDC_HDDA1(SST_HMDC_HDDA_E0_CH3)
148#define SST_HMDC_HDDA_E0_ALLCH (SST_HMDC_HDDA_E0_CH0 | SST_HMDC_HDDA_E0_CH1 | \
149 SST_HMDC_HDDA_E0_CH2 | SST_HMDC_HDDA_E0_CH3)
150#define SST_HMDC_HDDA_E1_ALLCH (SST_HMDC_HDDA_E1_CH0 | SST_HMDC_HDDA_E1_CH1 | \
151 SST_HMDC_HDDA_E1_CH2 | SST_HMDC_HDDA_E1_CH3)
152
153
154/* SST Vendor Defined Registers and bits */
155#define SST_VDRTCTL0 0xa0
156#define SST_VDRTCTL1 0xa4
157#define SST_VDRTCTL2 0xa8
158#define SST_VDRTCTL3 0xaC
159
160/* VDRTCTL0 */
161#define SST_VDRTCL0_D3PGD (1 << 0)
162#define SST_VDRTCL0_D3SRAMPGD (1 << 1)
163#define SST_VDRTCL0_DSRAMPGE_SHIFT 12
164#define SST_VDRTCL0_DSRAMPGE_MASK (0xfffff << SST_VDRTCL0_DSRAMPGE_SHIFT)
165#define SST_VDRTCL0_ISRAMPGE_SHIFT 2
166#define SST_VDRTCL0_ISRAMPGE_MASK (0x3ff << SST_VDRTCL0_ISRAMPGE_SHIFT)
167
168/* VDRTCTL2 */
169#define SST_VDRTCL2_DCLCGE (1 << 1)
170#define SST_VDRTCL2_DTCGE (1 << 10)
171#define SST_VDRTCL2_APLLSE_MASK (1 << 31)
172
173/* PMCS */
174#define SST_PMCS 0x84
175#define SST_PMCS_PS_MASK 0x3
176
177struct sst_dsp;
178
179/*
180 * SST Device.
181 *
182 * This structure is populated by the SST core driver.
183 */
184struct sst_dsp_device {
185 /* Mandatory fields */
186 struct sst_ops *ops;
187 irqreturn_t (*thread)(int irq, void *context);
188 void *thread_context;
189};
190
191/*
192 * SST Platform Data.
193 */
194struct sst_pdata {
195 /* ACPI data */
196 u32 lpe_base;
197 u32 lpe_size;
198 u32 pcicfg_base;
199 u32 pcicfg_size;
200 u32 fw_base;
201 u32 fw_size;
202 int irq;
203
204 /* Firmware */
205 const struct firmware *fw;
206
207 /* DMA */
208 int resindex_dma_base; /* other fields invalid if equals to -1 */
209 u32 dma_base;
210 u32 dma_size;
211 int dma_engine;
212 struct device *dma_dev;
213
214 /* DSP */
215 u32 id;
216 void *dsp;
217};
218
219/* Initialization */
220struct sst_dsp *sst_dsp_new(struct device *dev,
221 struct sst_dsp_device *sst_dev, struct sst_pdata *pdata);
222void sst_dsp_free(struct sst_dsp *sst);
223
224/* SHIM Read / Write */
225void sst_dsp_shim_write(struct sst_dsp *sst, u32 offset, u32 value);
226u32 sst_dsp_shim_read(struct sst_dsp *sst, u32 offset);
227int sst_dsp_shim_update_bits(struct sst_dsp *sst, u32 offset,
228 u32 mask, u32 value);
229void sst_dsp_shim_write64(struct sst_dsp *sst, u32 offset, u64 value);
230u64 sst_dsp_shim_read64(struct sst_dsp *sst, u32 offset);
231int sst_dsp_shim_update_bits64(struct sst_dsp *sst, u32 offset,
232 u64 mask, u64 value);
233
234/* SHIM Read / Write Unlocked for callers already holding sst lock */
235void sst_dsp_shim_write_unlocked(struct sst_dsp *sst, u32 offset, u32 value);
236u32 sst_dsp_shim_read_unlocked(struct sst_dsp *sst, u32 offset);
237int sst_dsp_shim_update_bits_unlocked(struct sst_dsp *sst, u32 offset,
238 u32 mask, u32 value);
239void sst_dsp_shim_write64_unlocked(struct sst_dsp *sst, u32 offset, u64 value);
240u64 sst_dsp_shim_read64_unlocked(struct sst_dsp *sst, u32 offset);
241int sst_dsp_shim_update_bits64_unlocked(struct sst_dsp *sst, u32 offset,
242 u64 mask, u64 value);
243
244/* Internal generic low-level SST IO functions - can be overidden */
245void sst_shim32_write(void __iomem *addr, u32 offset, u32 value);
246u32 sst_shim32_read(void __iomem *addr, u32 offset);
247void sst_shim32_write64(void __iomem *addr, u32 offset, u64 value);
248u64 sst_shim32_read64(void __iomem *addr, u32 offset);
249void sst_memcpy_toio_32(struct sst_dsp *sst,
250 void __iomem *dest, void *src, size_t bytes);
251void sst_memcpy_fromio_32(struct sst_dsp *sst,
252 void *dest, void __iomem *src, size_t bytes);
253
254/* DSP reset & boot */
255void sst_dsp_reset(struct sst_dsp *sst);
256int sst_dsp_boot(struct sst_dsp *sst);
257int sst_dsp_wake(struct sst_dsp *sst);
258void sst_dsp_sleep(struct sst_dsp *sst);
259void sst_dsp_stall(struct sst_dsp *sst);
260
261/* DMA */
262int sst_dsp_dma_get_channel(struct sst_dsp *dsp, int chan_id);
263void sst_dsp_dma_put_channel(struct sst_dsp *dsp);
264int sst_dsp_dma_copyfrom(struct sst_dsp *sst, dma_addr_t dest_addr,
265 dma_addr_t src_addr, size_t size);
266int sst_dsp_dma_copyto(struct sst_dsp *sst, dma_addr_t dest_addr,
267 dma_addr_t src_addr, size_t size);
268
269/* Msg IO */
270void sst_dsp_ipc_msg_tx(struct sst_dsp *dsp, u32 msg);
271u32 sst_dsp_ipc_msg_rx(struct sst_dsp *dsp);
272
273/* Mailbox management */
274int sst_dsp_mailbox_init(struct sst_dsp *dsp, u32 inbox_offset,
275 size_t inbox_size, u32 outbox_offset, size_t outbox_size);
276void sst_dsp_inbox_write(struct sst_dsp *dsp, void *message, size_t bytes);
277void sst_dsp_inbox_read(struct sst_dsp *dsp, void *message, size_t bytes);
278void sst_dsp_outbox_write(struct sst_dsp *dsp, void *message, size_t bytes);
279void sst_dsp_outbox_read(struct sst_dsp *dsp, void *message, size_t bytes);
280void sst_dsp_mailbox_dump(struct sst_dsp *dsp, size_t bytes);
281
282/* Debug */
283void sst_dsp_dump(struct sst_dsp *sst);
284
285#endif
diff --git a/sound/soc/intel/common/sst-firmware.c b/sound/soc/intel/common/sst-firmware.c
new file mode 100644
index 000000000000..ebcca6dc48d1
--- /dev/null
+++ b/sound/soc/intel/common/sst-firmware.c
@@ -0,0 +1,1205 @@
1/*
2 * Intel SST Firmware Loader
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/kernel.h>
18#include <linux/slab.h>
19#include <linux/sched.h>
20#include <linux/firmware.h>
21#include <linux/export.h>
22#include <linux/platform_device.h>
23#include <linux/dma-mapping.h>
24#include <linux/dmaengine.h>
25#include <linux/pci.h>
26#include <linux/acpi.h>
27
28/* supported DMA engine drivers */
29#include <linux/platform_data/dma-dw.h>
30#include <linux/dma/dw.h>
31
32#include <asm/page.h>
33#include <asm/pgtable.h>
34
35#include "sst-dsp.h"
36#include "sst-dsp-priv.h"
37
38#define SST_DMA_RESOURCES 2
39#define SST_DSP_DMA_MAX_BURST 0x3
40#define SST_HSW_BLOCK_ANY 0xffffffff
41
42#define SST_HSW_MASK_DMA_ADDR_DSP 0xfff00000
43
44struct sst_dma {
45 struct sst_dsp *sst;
46
47 struct dw_dma_chip *chip;
48
49 struct dma_async_tx_descriptor *desc;
50 struct dma_chan *ch;
51};
52
53static inline void sst_memcpy32(volatile void __iomem *dest, void *src, u32 bytes)
54{
55 /* __iowrite32_copy use 32bit size values so divide by 4 */
56 __iowrite32_copy((void *)dest, src, bytes/4);
57}
58
59static void sst_dma_transfer_complete(void *arg)
60{
61 struct sst_dsp *sst = (struct sst_dsp *)arg;
62
63 dev_dbg(sst->dev, "DMA: callback\n");
64}
65
66static int sst_dsp_dma_copy(struct sst_dsp *sst, dma_addr_t dest_addr,
67 dma_addr_t src_addr, size_t size)
68{
69 struct dma_async_tx_descriptor *desc;
70 struct sst_dma *dma = sst->dma;
71
72 if (dma->ch == NULL) {
73 dev_err(sst->dev, "error: no DMA channel\n");
74 return -ENODEV;
75 }
76
77 dev_dbg(sst->dev, "DMA: src: 0x%lx dest 0x%lx size %zu\n",
78 (unsigned long)src_addr, (unsigned long)dest_addr, size);
79
80 desc = dma->ch->device->device_prep_dma_memcpy(dma->ch, dest_addr,
81 src_addr, size, DMA_CTRL_ACK);
82 if (!desc){
83 dev_err(sst->dev, "error: dma prep memcpy failed\n");
84 return -EINVAL;
85 }
86
87 desc->callback = sst_dma_transfer_complete;
88 desc->callback_param = sst;
89
90 desc->tx_submit(desc);
91 dma_wait_for_async_tx(desc);
92
93 return 0;
94}
95
96/* copy to DSP */
97int sst_dsp_dma_copyto(struct sst_dsp *sst, dma_addr_t dest_addr,
98 dma_addr_t src_addr, size_t size)
99{
100 return sst_dsp_dma_copy(sst, dest_addr | SST_HSW_MASK_DMA_ADDR_DSP,
101 src_addr, size);
102}
103EXPORT_SYMBOL_GPL(sst_dsp_dma_copyto);
104
105/* copy from DSP */
106int sst_dsp_dma_copyfrom(struct sst_dsp *sst, dma_addr_t dest_addr,
107 dma_addr_t src_addr, size_t size)
108{
109 return sst_dsp_dma_copy(sst, dest_addr,
110 src_addr | SST_HSW_MASK_DMA_ADDR_DSP, size);
111}
112EXPORT_SYMBOL_GPL(sst_dsp_dma_copyfrom);
113
114/* remove module from memory - callers hold locks */
115static void block_list_remove(struct sst_dsp *dsp,
116 struct list_head *block_list)
117{
118 struct sst_mem_block *block, *tmp;
119 int err;
120
121 /* disable each block */
122 list_for_each_entry(block, block_list, module_list) {
123
124 if (block->ops && block->ops->disable) {
125 err = block->ops->disable(block);
126 if (err < 0)
127 dev_err(dsp->dev,
128 "error: cant disable block %d:%d\n",
129 block->type, block->index);
130 }
131 }
132
133 /* mark each block as free */
134 list_for_each_entry_safe(block, tmp, block_list, module_list) {
135 list_del(&block->module_list);
136 list_move(&block->list, &dsp->free_block_list);
137 dev_dbg(dsp->dev, "block freed %d:%d at offset 0x%x\n",
138 block->type, block->index, block->offset);
139 }
140}
141
142/* prepare the memory block to receive data from host - callers hold locks */
143static int block_list_prepare(struct sst_dsp *dsp,
144 struct list_head *block_list)
145{
146 struct sst_mem_block *block;
147 int ret = 0;
148
149 /* enable each block so that's it'e ready for data */
150 list_for_each_entry(block, block_list, module_list) {
151
152 if (block->ops && block->ops->enable && !block->users) {
153 ret = block->ops->enable(block);
154 if (ret < 0) {
155 dev_err(dsp->dev,
156 "error: cant disable block %d:%d\n",
157 block->type, block->index);
158 goto err;
159 }
160 }
161 }
162 return ret;
163
164err:
165 list_for_each_entry(block, block_list, module_list) {
166 if (block->ops && block->ops->disable)
167 block->ops->disable(block);
168 }
169 return ret;
170}
171
172static struct dw_dma_platform_data dw_pdata = {
173 .is_private = 1,
174 .chan_allocation_order = CHAN_ALLOCATION_ASCENDING,
175 .chan_priority = CHAN_PRIORITY_ASCENDING,
176};
177
178static struct dw_dma_chip *dw_probe(struct device *dev, struct resource *mem,
179 int irq)
180{
181 struct dw_dma_chip *chip;
182 int err;
183
184 chip = devm_kzalloc(dev, sizeof(*chip), GFP_KERNEL);
185 if (!chip)
186 return ERR_PTR(-ENOMEM);
187
188 chip->irq = irq;
189 chip->regs = devm_ioremap_resource(dev, mem);
190 if (IS_ERR(chip->regs))
191 return ERR_CAST(chip->regs);
192
193 err = dma_coerce_mask_and_coherent(dev, DMA_BIT_MASK(31));
194 if (err)
195 return ERR_PTR(err);
196
197 chip->dev = dev;
198 err = dw_dma_probe(chip, &dw_pdata);
199 if (err)
200 return ERR_PTR(err);
201
202 return chip;
203}
204
205static void dw_remove(struct dw_dma_chip *chip)
206{
207 dw_dma_remove(chip);
208}
209
210static bool dma_chan_filter(struct dma_chan *chan, void *param)
211{
212 struct sst_dsp *dsp = (struct sst_dsp *)param;
213
214 return chan->device->dev == dsp->dma_dev;
215}
216
217int sst_dsp_dma_get_channel(struct sst_dsp *dsp, int chan_id)
218{
219 struct sst_dma *dma = dsp->dma;
220 struct dma_slave_config slave;
221 dma_cap_mask_t mask;
222 int ret;
223
224 dma_cap_zero(mask);
225 dma_cap_set(DMA_SLAVE, mask);
226 dma_cap_set(DMA_MEMCPY, mask);
227
228 dma->ch = dma_request_channel(mask, dma_chan_filter, dsp);
229 if (dma->ch == NULL) {
230 dev_err(dsp->dev, "error: DMA request channel failed\n");
231 return -EIO;
232 }
233
234 memset(&slave, 0, sizeof(slave));
235 slave.direction = DMA_MEM_TO_DEV;
236 slave.src_addr_width =
237 slave.dst_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES;
238 slave.src_maxburst = slave.dst_maxburst = SST_DSP_DMA_MAX_BURST;
239
240 ret = dmaengine_slave_config(dma->ch, &slave);
241 if (ret) {
242 dev_err(dsp->dev, "error: unable to set DMA slave config %d\n",
243 ret);
244 dma_release_channel(dma->ch);
245 dma->ch = NULL;
246 }
247
248 return ret;
249}
250EXPORT_SYMBOL_GPL(sst_dsp_dma_get_channel);
251
252void sst_dsp_dma_put_channel(struct sst_dsp *dsp)
253{
254 struct sst_dma *dma = dsp->dma;
255
256 if (!dma->ch)
257 return;
258
259 dma_release_channel(dma->ch);
260 dma->ch = NULL;
261}
262EXPORT_SYMBOL_GPL(sst_dsp_dma_put_channel);
263
264int sst_dma_new(struct sst_dsp *sst)
265{
266 struct sst_pdata *sst_pdata = sst->pdata;
267 struct sst_dma *dma;
268 struct resource mem;
269 const char *dma_dev_name;
270 int ret = 0;
271
272 if (sst->pdata->resindex_dma_base == -1)
273 /* DMA is not used, return and squelsh error messages */
274 return 0;
275
276 /* configure the correct platform data for whatever DMA engine
277 * is attached to the ADSP IP. */
278 switch (sst->pdata->dma_engine) {
279 case SST_DMA_TYPE_DW:
280 dma_dev_name = "dw_dmac";
281 break;
282 default:
283 dev_err(sst->dev, "error: invalid DMA engine %d\n",
284 sst->pdata->dma_engine);
285 return -EINVAL;
286 }
287
288 dma = devm_kzalloc(sst->dev, sizeof(struct sst_dma), GFP_KERNEL);
289 if (!dma)
290 return -ENOMEM;
291
292 dma->sst = sst;
293
294 memset(&mem, 0, sizeof(mem));
295
296 mem.start = sst->addr.lpe_base + sst_pdata->dma_base;
297 mem.end = sst->addr.lpe_base + sst_pdata->dma_base + sst_pdata->dma_size - 1;
298 mem.flags = IORESOURCE_MEM;
299
300 /* now register DMA engine device */
301 dma->chip = dw_probe(sst->dma_dev, &mem, sst_pdata->irq);
302 if (IS_ERR(dma->chip)) {
303 dev_err(sst->dev, "error: DMA device register failed\n");
304 ret = PTR_ERR(dma->chip);
305 goto err_dma_dev;
306 }
307
308 sst->dma = dma;
309 sst->fw_use_dma = true;
310 return 0;
311
312err_dma_dev:
313 devm_kfree(sst->dev, dma);
314 return ret;
315}
316EXPORT_SYMBOL(sst_dma_new);
317
318void sst_dma_free(struct sst_dma *dma)
319{
320
321 if (dma == NULL)
322 return;
323
324 if (dma->ch)
325 dma_release_channel(dma->ch);
326
327 if (dma->chip)
328 dw_remove(dma->chip);
329
330}
331EXPORT_SYMBOL(sst_dma_free);
332
333/* create new generic firmware object */
334struct sst_fw *sst_fw_new(struct sst_dsp *dsp,
335 const struct firmware *fw, void *private)
336{
337 struct sst_fw *sst_fw;
338 int err;
339
340 if (!dsp->ops->parse_fw)
341 return NULL;
342
343 sst_fw = kzalloc(sizeof(*sst_fw), GFP_KERNEL);
344 if (sst_fw == NULL)
345 return NULL;
346
347 sst_fw->dsp = dsp;
348 sst_fw->private = private;
349 sst_fw->size = fw->size;
350
351 /* allocate DMA buffer to store FW data */
352 sst_fw->dma_buf = dma_alloc_coherent(dsp->dma_dev, sst_fw->size,
353 &sst_fw->dmable_fw_paddr, GFP_DMA | GFP_KERNEL);
354 if (!sst_fw->dma_buf) {
355 dev_err(dsp->dev, "error: DMA alloc failed\n");
356 kfree(sst_fw);
357 return NULL;
358 }
359
360 /* copy FW data to DMA-able memory */
361 memcpy((void *)sst_fw->dma_buf, (void *)fw->data, fw->size);
362
363 if (dsp->fw_use_dma) {
364 err = sst_dsp_dma_get_channel(dsp, 0);
365 if (err < 0)
366 goto chan_err;
367 }
368
369 /* call core specific FW paser to load FW data into DSP */
370 err = dsp->ops->parse_fw(sst_fw);
371 if (err < 0) {
372 dev_err(dsp->dev, "error: parse fw failed %d\n", err);
373 goto parse_err;
374 }
375
376 if (dsp->fw_use_dma)
377 sst_dsp_dma_put_channel(dsp);
378
379 mutex_lock(&dsp->mutex);
380 list_add(&sst_fw->list, &dsp->fw_list);
381 mutex_unlock(&dsp->mutex);
382
383 return sst_fw;
384
385parse_err:
386 if (dsp->fw_use_dma)
387 sst_dsp_dma_put_channel(dsp);
388chan_err:
389 dma_free_coherent(dsp->dma_dev, sst_fw->size,
390 sst_fw->dma_buf,
391 sst_fw->dmable_fw_paddr);
392 sst_fw->dma_buf = NULL;
393 kfree(sst_fw);
394 return NULL;
395}
396EXPORT_SYMBOL_GPL(sst_fw_new);
397
398int sst_fw_reload(struct sst_fw *sst_fw)
399{
400 struct sst_dsp *dsp = sst_fw->dsp;
401 int ret;
402
403 dev_dbg(dsp->dev, "reloading firmware\n");
404
405 /* call core specific FW paser to load FW data into DSP */
406 ret = dsp->ops->parse_fw(sst_fw);
407 if (ret < 0)
408 dev_err(dsp->dev, "error: parse fw failed %d\n", ret);
409
410 return ret;
411}
412EXPORT_SYMBOL_GPL(sst_fw_reload);
413
414void sst_fw_unload(struct sst_fw *sst_fw)
415{
416 struct sst_dsp *dsp = sst_fw->dsp;
417 struct sst_module *module, *mtmp;
418 struct sst_module_runtime *runtime, *rtmp;
419
420 dev_dbg(dsp->dev, "unloading firmware\n");
421
422 mutex_lock(&dsp->mutex);
423
424 /* check module by module */
425 list_for_each_entry_safe(module, mtmp, &dsp->module_list, list) {
426 if (module->sst_fw == sst_fw) {
427
428 /* remove runtime modules */
429 list_for_each_entry_safe(runtime, rtmp, &module->runtime_list, list) {
430
431 block_list_remove(dsp, &runtime->block_list);
432 list_del(&runtime->list);
433 kfree(runtime);
434 }
435
436 /* now remove the module */
437 block_list_remove(dsp, &module->block_list);
438 list_del(&module->list);
439 kfree(module);
440 }
441 }
442
443 /* remove all scratch blocks */
444 block_list_remove(dsp, &dsp->scratch_block_list);
445
446 mutex_unlock(&dsp->mutex);
447}
448EXPORT_SYMBOL_GPL(sst_fw_unload);
449
450/* free single firmware object */
451void sst_fw_free(struct sst_fw *sst_fw)
452{
453 struct sst_dsp *dsp = sst_fw->dsp;
454
455 mutex_lock(&dsp->mutex);
456 list_del(&sst_fw->list);
457 mutex_unlock(&dsp->mutex);
458
459 if (sst_fw->dma_buf)
460 dma_free_coherent(dsp->dma_dev, sst_fw->size, sst_fw->dma_buf,
461 sst_fw->dmable_fw_paddr);
462 kfree(sst_fw);
463}
464EXPORT_SYMBOL_GPL(sst_fw_free);
465
466/* free all firmware objects */
467void sst_fw_free_all(struct sst_dsp *dsp)
468{
469 struct sst_fw *sst_fw, *t;
470
471 mutex_lock(&dsp->mutex);
472 list_for_each_entry_safe(sst_fw, t, &dsp->fw_list, list) {
473
474 list_del(&sst_fw->list);
475 dma_free_coherent(dsp->dev, sst_fw->size, sst_fw->dma_buf,
476 sst_fw->dmable_fw_paddr);
477 kfree(sst_fw);
478 }
479 mutex_unlock(&dsp->mutex);
480}
481EXPORT_SYMBOL_GPL(sst_fw_free_all);
482
483/* create a new SST generic module from FW template */
484struct sst_module *sst_module_new(struct sst_fw *sst_fw,
485 struct sst_module_template *template, void *private)
486{
487 struct sst_dsp *dsp = sst_fw->dsp;
488 struct sst_module *sst_module;
489
490 sst_module = kzalloc(sizeof(*sst_module), GFP_KERNEL);
491 if (sst_module == NULL)
492 return NULL;
493
494 sst_module->id = template->id;
495 sst_module->dsp = dsp;
496 sst_module->sst_fw = sst_fw;
497 sst_module->scratch_size = template->scratch_size;
498 sst_module->persistent_size = template->persistent_size;
499 sst_module->entry = template->entry;
500 sst_module->state = SST_MODULE_STATE_UNLOADED;
501
502 INIT_LIST_HEAD(&sst_module->block_list);
503 INIT_LIST_HEAD(&sst_module->runtime_list);
504
505 mutex_lock(&dsp->mutex);
506 list_add(&sst_module->list, &dsp->module_list);
507 mutex_unlock(&dsp->mutex);
508
509 return sst_module;
510}
511EXPORT_SYMBOL_GPL(sst_module_new);
512
513/* free firmware module and remove from available list */
514void sst_module_free(struct sst_module *sst_module)
515{
516 struct sst_dsp *dsp = sst_module->dsp;
517
518 mutex_lock(&dsp->mutex);
519 list_del(&sst_module->list);
520 mutex_unlock(&dsp->mutex);
521
522 kfree(sst_module);
523}
524EXPORT_SYMBOL_GPL(sst_module_free);
525
526struct sst_module_runtime *sst_module_runtime_new(struct sst_module *module,
527 int id, void *private)
528{
529 struct sst_dsp *dsp = module->dsp;
530 struct sst_module_runtime *runtime;
531
532 runtime = kzalloc(sizeof(*runtime), GFP_KERNEL);
533 if (runtime == NULL)
534 return NULL;
535
536 runtime->id = id;
537 runtime->dsp = dsp;
538 runtime->module = module;
539 INIT_LIST_HEAD(&runtime->block_list);
540
541 mutex_lock(&dsp->mutex);
542 list_add(&runtime->list, &module->runtime_list);
543 mutex_unlock(&dsp->mutex);
544
545 return runtime;
546}
547EXPORT_SYMBOL_GPL(sst_module_runtime_new);
548
549void sst_module_runtime_free(struct sst_module_runtime *runtime)
550{
551 struct sst_dsp *dsp = runtime->dsp;
552
553 mutex_lock(&dsp->mutex);
554 list_del(&runtime->list);
555 mutex_unlock(&dsp->mutex);
556
557 kfree(runtime);
558}
559EXPORT_SYMBOL_GPL(sst_module_runtime_free);
560
561static struct sst_mem_block *find_block(struct sst_dsp *dsp,
562 struct sst_block_allocator *ba)
563{
564 struct sst_mem_block *block;
565
566 list_for_each_entry(block, &dsp->free_block_list, list) {
567 if (block->type == ba->type && block->offset == ba->offset)
568 return block;
569 }
570
571 return NULL;
572}
573
574/* Block allocator must be on block boundary */
575static int block_alloc_contiguous(struct sst_dsp *dsp,
576 struct sst_block_allocator *ba, struct list_head *block_list)
577{
578 struct list_head tmp = LIST_HEAD_INIT(tmp);
579 struct sst_mem_block *block;
580 u32 block_start = SST_HSW_BLOCK_ANY;
581 int size = ba->size, offset = ba->offset;
582
583 while (ba->size > 0) {
584
585 block = find_block(dsp, ba);
586 if (!block) {
587 list_splice(&tmp, &dsp->free_block_list);
588
589 ba->size = size;
590 ba->offset = offset;
591 return -ENOMEM;
592 }
593
594 list_move_tail(&block->list, &tmp);
595 ba->offset += block->size;
596 ba->size -= block->size;
597 }
598 ba->size = size;
599 ba->offset = offset;
600
601 list_for_each_entry(block, &tmp, list) {
602
603 if (block->offset < block_start)
604 block_start = block->offset;
605
606 list_add(&block->module_list, block_list);
607
608 dev_dbg(dsp->dev, "block allocated %d:%d at offset 0x%x\n",
609 block->type, block->index, block->offset);
610 }
611
612 list_splice(&tmp, &dsp->used_block_list);
613 return 0;
614}
615
616/* allocate first free DSP blocks for data - callers hold locks */
617static int block_alloc(struct sst_dsp *dsp, struct sst_block_allocator *ba,
618 struct list_head *block_list)
619{
620 struct sst_mem_block *block, *tmp;
621 int ret = 0;
622
623 if (ba->size == 0)
624 return 0;
625
626 /* find first free whole blocks that can hold module */
627 list_for_each_entry_safe(block, tmp, &dsp->free_block_list, list) {
628
629 /* ignore blocks with wrong type */
630 if (block->type != ba->type)
631 continue;
632
633 if (ba->size > block->size)
634 continue;
635
636 ba->offset = block->offset;
637 block->bytes_used = ba->size % block->size;
638 list_add(&block->module_list, block_list);
639 list_move(&block->list, &dsp->used_block_list);
640 dev_dbg(dsp->dev, "block allocated %d:%d at offset 0x%x\n",
641 block->type, block->index, block->offset);
642 return 0;
643 }
644
645 /* then find free multiple blocks that can hold module */
646 list_for_each_entry_safe(block, tmp, &dsp->free_block_list, list) {
647
648 /* ignore blocks with wrong type */
649 if (block->type != ba->type)
650 continue;
651
652 /* do we span > 1 blocks */
653 if (ba->size > block->size) {
654
655 /* align ba to block boundary */
656 ba->offset = block->offset;
657
658 ret = block_alloc_contiguous(dsp, ba, block_list);
659 if (ret == 0)
660 return ret;
661
662 }
663 }
664
665 /* not enough free block space */
666 return -ENOMEM;
667}
668
669int sst_alloc_blocks(struct sst_dsp *dsp, struct sst_block_allocator *ba,
670 struct list_head *block_list)
671{
672 int ret;
673
674 dev_dbg(dsp->dev, "block request 0x%x bytes at offset 0x%x type %d\n",
675 ba->size, ba->offset, ba->type);
676
677 mutex_lock(&dsp->mutex);
678
679 ret = block_alloc(dsp, ba, block_list);
680 if (ret < 0) {
681 dev_err(dsp->dev, "error: can't alloc blocks %d\n", ret);
682 goto out;
683 }
684
685 /* prepare DSP blocks for module usage */
686 ret = block_list_prepare(dsp, block_list);
687 if (ret < 0)
688 dev_err(dsp->dev, "error: prepare failed\n");
689
690out:
691 mutex_unlock(&dsp->mutex);
692 return ret;
693}
694EXPORT_SYMBOL_GPL(sst_alloc_blocks);
695
696int sst_free_blocks(struct sst_dsp *dsp, struct list_head *block_list)
697{
698 mutex_lock(&dsp->mutex);
699 block_list_remove(dsp, block_list);
700 mutex_unlock(&dsp->mutex);
701 return 0;
702}
703EXPORT_SYMBOL_GPL(sst_free_blocks);
704
705/* allocate memory blocks for static module addresses - callers hold locks */
706static int block_alloc_fixed(struct sst_dsp *dsp, struct sst_block_allocator *ba,
707 struct list_head *block_list)
708{
709 struct sst_mem_block *block, *tmp;
710 struct sst_block_allocator ba_tmp = *ba;
711 u32 end = ba->offset + ba->size, block_end;
712 int err;
713
714 /* only IRAM/DRAM blocks are managed */
715 if (ba->type != SST_MEM_IRAM && ba->type != SST_MEM_DRAM)
716 return 0;
717
718 /* are blocks already attached to this module */
719 list_for_each_entry_safe(block, tmp, block_list, module_list) {
720
721 /* ignore blocks with wrong type */
722 if (block->type != ba->type)
723 continue;
724
725 block_end = block->offset + block->size;
726
727 /* find block that holds section */
728 if (ba->offset >= block->offset && end <= block_end)
729 return 0;
730
731 /* does block span more than 1 section */
732 if (ba->offset >= block->offset && ba->offset < block_end) {
733
734 /* align ba to block boundary */
735 ba_tmp.size -= block_end - ba->offset;
736 ba_tmp.offset = block_end;
737 err = block_alloc_contiguous(dsp, &ba_tmp, block_list);
738 if (err < 0)
739 return -ENOMEM;
740
741 /* module already owns blocks */
742 return 0;
743 }
744 }
745
746 /* find first free blocks that can hold section in free list */
747 list_for_each_entry_safe(block, tmp, &dsp->free_block_list, list) {
748 block_end = block->offset + block->size;
749
750 /* ignore blocks with wrong type */
751 if (block->type != ba->type)
752 continue;
753
754 /* find block that holds section */
755 if (ba->offset >= block->offset && end <= block_end) {
756
757 /* add block */
758 list_move(&block->list, &dsp->used_block_list);
759 list_add(&block->module_list, block_list);
760 dev_dbg(dsp->dev, "block allocated %d:%d at offset 0x%x\n",
761 block->type, block->index, block->offset);
762 return 0;
763 }
764
765 /* does block span more than 1 section */
766 if (ba->offset >= block->offset && ba->offset < block_end) {
767
768 /* add block */
769 list_move(&block->list, &dsp->used_block_list);
770 list_add(&block->module_list, block_list);
771 /* align ba to block boundary */
772 ba_tmp.size -= block_end - ba->offset;
773 ba_tmp.offset = block_end;
774
775 err = block_alloc_contiguous(dsp, &ba_tmp, block_list);
776 if (err < 0)
777 return -ENOMEM;
778
779 return 0;
780 }
781 }
782
783 return -ENOMEM;
784}
785
786/* Load fixed module data into DSP memory blocks */
787int sst_module_alloc_blocks(struct sst_module *module)
788{
789 struct sst_dsp *dsp = module->dsp;
790 struct sst_fw *sst_fw = module->sst_fw;
791 struct sst_block_allocator ba;
792 int ret;
793
794 memset(&ba, 0, sizeof(ba));
795 ba.size = module->size;
796 ba.type = module->type;
797 ba.offset = module->offset;
798
799 dev_dbg(dsp->dev, "block request 0x%x bytes at offset 0x%x type %d\n",
800 ba.size, ba.offset, ba.type);
801
802 mutex_lock(&dsp->mutex);
803
804 /* alloc blocks that includes this section */
805 ret = block_alloc_fixed(dsp, &ba, &module->block_list);
806 if (ret < 0) {
807 dev_err(dsp->dev,
808 "error: no free blocks for section at offset 0x%x size 0x%x\n",
809 module->offset, module->size);
810 mutex_unlock(&dsp->mutex);
811 return -ENOMEM;
812 }
813
814 /* prepare DSP blocks for module copy */
815 ret = block_list_prepare(dsp, &module->block_list);
816 if (ret < 0) {
817 dev_err(dsp->dev, "error: fw module prepare failed\n");
818 goto err;
819 }
820
821 /* copy partial module data to blocks */
822 if (dsp->fw_use_dma) {
823 ret = sst_dsp_dma_copyto(dsp,
824 dsp->addr.lpe_base + module->offset,
825 sst_fw->dmable_fw_paddr + module->data_offset,
826 module->size);
827 if (ret < 0) {
828 dev_err(dsp->dev, "error: module copy failed\n");
829 goto err;
830 }
831 } else
832 sst_memcpy32(dsp->addr.lpe + module->offset, module->data,
833 module->size);
834
835 mutex_unlock(&dsp->mutex);
836 return ret;
837
838err:
839 block_list_remove(dsp, &module->block_list);
840 mutex_unlock(&dsp->mutex);
841 return ret;
842}
843EXPORT_SYMBOL_GPL(sst_module_alloc_blocks);
844
845/* Unload entire module from DSP memory */
846int sst_module_free_blocks(struct sst_module *module)
847{
848 struct sst_dsp *dsp = module->dsp;
849
850 mutex_lock(&dsp->mutex);
851 block_list_remove(dsp, &module->block_list);
852 mutex_unlock(&dsp->mutex);
853 return 0;
854}
855EXPORT_SYMBOL_GPL(sst_module_free_blocks);
856
857int sst_module_runtime_alloc_blocks(struct sst_module_runtime *runtime,
858 int offset)
859{
860 struct sst_dsp *dsp = runtime->dsp;
861 struct sst_module *module = runtime->module;
862 struct sst_block_allocator ba;
863 int ret;
864
865 if (module->persistent_size == 0)
866 return 0;
867
868 memset(&ba, 0, sizeof(ba));
869 ba.size = module->persistent_size;
870 ba.type = SST_MEM_DRAM;
871
872 mutex_lock(&dsp->mutex);
873
874 /* do we need to allocate at a fixed address ? */
875 if (offset != 0) {
876
877 ba.offset = offset;
878
879 dev_dbg(dsp->dev, "persistent fixed block request 0x%x bytes type %d offset 0x%x\n",
880 ba.size, ba.type, ba.offset);
881
882 /* alloc blocks that includes this section */
883 ret = block_alloc_fixed(dsp, &ba, &runtime->block_list);
884
885 } else {
886 dev_dbg(dsp->dev, "persistent block request 0x%x bytes type %d\n",
887 ba.size, ba.type);
888
889 /* alloc blocks that includes this section */
890 ret = block_alloc(dsp, &ba, &runtime->block_list);
891 }
892 if (ret < 0) {
893 dev_err(dsp->dev,
894 "error: no free blocks for runtime module size 0x%x\n",
895 module->persistent_size);
896 mutex_unlock(&dsp->mutex);
897 return -ENOMEM;
898 }
899 runtime->persistent_offset = ba.offset;
900
901 /* prepare DSP blocks for module copy */
902 ret = block_list_prepare(dsp, &runtime->block_list);
903 if (ret < 0) {
904 dev_err(dsp->dev, "error: runtime block prepare failed\n");
905 goto err;
906 }
907
908 mutex_unlock(&dsp->mutex);
909 return ret;
910
911err:
912 block_list_remove(dsp, &module->block_list);
913 mutex_unlock(&dsp->mutex);
914 return ret;
915}
916EXPORT_SYMBOL_GPL(sst_module_runtime_alloc_blocks);
917
918int sst_module_runtime_free_blocks(struct sst_module_runtime *runtime)
919{
920 struct sst_dsp *dsp = runtime->dsp;
921
922 mutex_lock(&dsp->mutex);
923 block_list_remove(dsp, &runtime->block_list);
924 mutex_unlock(&dsp->mutex);
925 return 0;
926}
927EXPORT_SYMBOL_GPL(sst_module_runtime_free_blocks);
928
929int sst_module_runtime_save(struct sst_module_runtime *runtime,
930 struct sst_module_runtime_context *context)
931{
932 struct sst_dsp *dsp = runtime->dsp;
933 struct sst_module *module = runtime->module;
934 int ret = 0;
935
936 dev_dbg(dsp->dev, "saving runtime %d memory at 0x%x size 0x%x\n",
937 runtime->id, runtime->persistent_offset,
938 module->persistent_size);
939
940 context->buffer = dma_alloc_coherent(dsp->dma_dev,
941 module->persistent_size,
942 &context->dma_buffer, GFP_DMA | GFP_KERNEL);
943 if (!context->buffer) {
944 dev_err(dsp->dev, "error: DMA context alloc failed\n");
945 return -ENOMEM;
946 }
947
948 mutex_lock(&dsp->mutex);
949
950 if (dsp->fw_use_dma) {
951
952 ret = sst_dsp_dma_get_channel(dsp, 0);
953 if (ret < 0)
954 goto err;
955
956 ret = sst_dsp_dma_copyfrom(dsp, context->dma_buffer,
957 dsp->addr.lpe_base + runtime->persistent_offset,
958 module->persistent_size);
959 sst_dsp_dma_put_channel(dsp);
960 if (ret < 0) {
961 dev_err(dsp->dev, "error: context copy failed\n");
962 goto err;
963 }
964 } else
965 sst_memcpy32(context->buffer, dsp->addr.lpe +
966 runtime->persistent_offset,
967 module->persistent_size);
968
969err:
970 mutex_unlock(&dsp->mutex);
971 return ret;
972}
973EXPORT_SYMBOL_GPL(sst_module_runtime_save);
974
975int sst_module_runtime_restore(struct sst_module_runtime *runtime,
976 struct sst_module_runtime_context *context)
977{
978 struct sst_dsp *dsp = runtime->dsp;
979 struct sst_module *module = runtime->module;
980 int ret = 0;
981
982 dev_dbg(dsp->dev, "restoring runtime %d memory at 0x%x size 0x%x\n",
983 runtime->id, runtime->persistent_offset,
984 module->persistent_size);
985
986 mutex_lock(&dsp->mutex);
987
988 if (!context->buffer) {
989 dev_info(dsp->dev, "no context buffer need to restore!\n");
990 goto err;
991 }
992
993 if (dsp->fw_use_dma) {
994
995 ret = sst_dsp_dma_get_channel(dsp, 0);
996 if (ret < 0)
997 goto err;
998
999 ret = sst_dsp_dma_copyto(dsp,
1000 dsp->addr.lpe_base + runtime->persistent_offset,
1001 context->dma_buffer, module->persistent_size);
1002 sst_dsp_dma_put_channel(dsp);
1003 if (ret < 0) {
1004 dev_err(dsp->dev, "error: module copy failed\n");
1005 goto err;
1006 }
1007 } else
1008 sst_memcpy32(dsp->addr.lpe + runtime->persistent_offset,
1009 context->buffer, module->persistent_size);
1010
1011 dma_free_coherent(dsp->dma_dev, module->persistent_size,
1012 context->buffer, context->dma_buffer);
1013 context->buffer = NULL;
1014
1015err:
1016 mutex_unlock(&dsp->mutex);
1017 return ret;
1018}
1019EXPORT_SYMBOL_GPL(sst_module_runtime_restore);
1020
1021/* register a DSP memory block for use with FW based modules */
1022struct sst_mem_block *sst_mem_block_register(struct sst_dsp *dsp, u32 offset,
1023 u32 size, enum sst_mem_type type, struct sst_block_ops *ops, u32 index,
1024 void *private)
1025{
1026 struct sst_mem_block *block;
1027
1028 block = kzalloc(sizeof(*block), GFP_KERNEL);
1029 if (block == NULL)
1030 return NULL;
1031
1032 block->offset = offset;
1033 block->size = size;
1034 block->index = index;
1035 block->type = type;
1036 block->dsp = dsp;
1037 block->private = private;
1038 block->ops = ops;
1039
1040 mutex_lock(&dsp->mutex);
1041 list_add(&block->list, &dsp->free_block_list);
1042 mutex_unlock(&dsp->mutex);
1043
1044 return block;
1045}
1046EXPORT_SYMBOL_GPL(sst_mem_block_register);
1047
1048/* unregister all DSP memory blocks */
1049void sst_mem_block_unregister_all(struct sst_dsp *dsp)
1050{
1051 struct sst_mem_block *block, *tmp;
1052
1053 mutex_lock(&dsp->mutex);
1054
1055 /* unregister used blocks */
1056 list_for_each_entry_safe(block, tmp, &dsp->used_block_list, list) {
1057 list_del(&block->list);
1058 kfree(block);
1059 }
1060
1061 /* unregister free blocks */
1062 list_for_each_entry_safe(block, tmp, &dsp->free_block_list, list) {
1063 list_del(&block->list);
1064 kfree(block);
1065 }
1066
1067 mutex_unlock(&dsp->mutex);
1068}
1069EXPORT_SYMBOL_GPL(sst_mem_block_unregister_all);
1070
1071/* allocate scratch buffer blocks */
1072int sst_block_alloc_scratch(struct sst_dsp *dsp)
1073{
1074 struct sst_module *module;
1075 struct sst_block_allocator ba;
1076 int ret;
1077
1078 mutex_lock(&dsp->mutex);
1079
1080 /* calculate required scratch size */
1081 dsp->scratch_size = 0;
1082 list_for_each_entry(module, &dsp->module_list, list) {
1083 dev_dbg(dsp->dev, "module %d scratch req 0x%x bytes\n",
1084 module->id, module->scratch_size);
1085 if (dsp->scratch_size < module->scratch_size)
1086 dsp->scratch_size = module->scratch_size;
1087 }
1088
1089 dev_dbg(dsp->dev, "scratch buffer required is 0x%x bytes\n",
1090 dsp->scratch_size);
1091
1092 if (dsp->scratch_size == 0) {
1093 dev_info(dsp->dev, "no modules need scratch buffer\n");
1094 mutex_unlock(&dsp->mutex);
1095 return 0;
1096 }
1097
1098 /* allocate blocks for module scratch buffers */
1099 dev_dbg(dsp->dev, "allocating scratch blocks\n");
1100
1101 ba.size = dsp->scratch_size;
1102 ba.type = SST_MEM_DRAM;
1103
1104 /* do we need to allocate at fixed offset */
1105 if (dsp->scratch_offset != 0) {
1106
1107 dev_dbg(dsp->dev, "block request 0x%x bytes type %d at 0x%x\n",
1108 ba.size, ba.type, ba.offset);
1109
1110 ba.offset = dsp->scratch_offset;
1111
1112 /* alloc blocks that includes this section */
1113 ret = block_alloc_fixed(dsp, &ba, &dsp->scratch_block_list);
1114
1115 } else {
1116 dev_dbg(dsp->dev, "block request 0x%x bytes type %d\n",
1117 ba.size, ba.type);
1118
1119 ba.offset = 0;
1120 ret = block_alloc(dsp, &ba, &dsp->scratch_block_list);
1121 }
1122 if (ret < 0) {
1123 dev_err(dsp->dev, "error: can't alloc scratch blocks\n");
1124 mutex_unlock(&dsp->mutex);
1125 return ret;
1126 }
1127
1128 ret = block_list_prepare(dsp, &dsp->scratch_block_list);
1129 if (ret < 0) {
1130 dev_err(dsp->dev, "error: scratch block prepare failed\n");
1131 mutex_unlock(&dsp->mutex);
1132 return ret;
1133 }
1134
1135 /* assign the same offset of scratch to each module */
1136 dsp->scratch_offset = ba.offset;
1137 mutex_unlock(&dsp->mutex);
1138 return dsp->scratch_size;
1139}
1140EXPORT_SYMBOL_GPL(sst_block_alloc_scratch);
1141
1142/* free all scratch blocks */
1143void sst_block_free_scratch(struct sst_dsp *dsp)
1144{
1145 mutex_lock(&dsp->mutex);
1146 block_list_remove(dsp, &dsp->scratch_block_list);
1147 mutex_unlock(&dsp->mutex);
1148}
1149EXPORT_SYMBOL_GPL(sst_block_free_scratch);
1150
1151/* get a module from it's unique ID */
1152struct sst_module *sst_module_get_from_id(struct sst_dsp *dsp, u32 id)
1153{
1154 struct sst_module *module;
1155
1156 mutex_lock(&dsp->mutex);
1157
1158 list_for_each_entry(module, &dsp->module_list, list) {
1159 if (module->id == id) {
1160 mutex_unlock(&dsp->mutex);
1161 return module;
1162 }
1163 }
1164
1165 mutex_unlock(&dsp->mutex);
1166 return NULL;
1167}
1168EXPORT_SYMBOL_GPL(sst_module_get_from_id);
1169
1170struct sst_module_runtime *sst_module_runtime_get_from_id(
1171 struct sst_module *module, u32 id)
1172{
1173 struct sst_module_runtime *runtime;
1174 struct sst_dsp *dsp = module->dsp;
1175
1176 mutex_lock(&dsp->mutex);
1177
1178 list_for_each_entry(runtime, &module->runtime_list, list) {
1179 if (runtime->id == id) {
1180 mutex_unlock(&dsp->mutex);
1181 return runtime;
1182 }
1183 }
1184
1185 mutex_unlock(&dsp->mutex);
1186 return NULL;
1187}
1188EXPORT_SYMBOL_GPL(sst_module_runtime_get_from_id);
1189
1190/* returns block address in DSP address space */
1191u32 sst_dsp_get_offset(struct sst_dsp *dsp, u32 offset,
1192 enum sst_mem_type type)
1193{
1194 switch (type) {
1195 case SST_MEM_IRAM:
1196 return offset - dsp->addr.iram_offset +
1197 dsp->addr.dsp_iram_offset;
1198 case SST_MEM_DRAM:
1199 return offset - dsp->addr.dram_offset +
1200 dsp->addr.dsp_dram_offset;
1201 default:
1202 return 0;
1203 }
1204}
1205EXPORT_SYMBOL_GPL(sst_dsp_get_offset);
diff --git a/sound/soc/intel/common/sst-ipc.c b/sound/soc/intel/common/sst-ipc.c
new file mode 100644
index 000000000000..4b62a553823c
--- /dev/null
+++ b/sound/soc/intel/common/sst-ipc.c
@@ -0,0 +1,294 @@
1/*
2 * Intel SST generic IPC Support
3 *
4 * Copyright (C) 2015, 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/types.h>
18#include <linux/kernel.h>
19#include <linux/list.h>
20#include <linux/wait.h>
21#include <linux/module.h>
22#include <linux/spinlock.h>
23#include <linux/device.h>
24#include <linux/slab.h>
25#include <linux/workqueue.h>
26#include <linux/sched.h>
27#include <linux/delay.h>
28#include <linux/platform_device.h>
29#include <linux/kthread.h>
30#include <sound/asound.h>
31
32#include "sst-dsp.h"
33#include "sst-dsp-priv.h"
34#include "sst-ipc.h"
35
36/* IPC message timeout (msecs) */
37#define IPC_TIMEOUT_MSECS 300
38
39#define IPC_EMPTY_LIST_SIZE 8
40
41/* locks held by caller */
42static struct ipc_message *msg_get_empty(struct sst_generic_ipc *ipc)
43{
44 struct ipc_message *msg = NULL;
45
46 if (!list_empty(&ipc->empty_list)) {
47 msg = list_first_entry(&ipc->empty_list, struct ipc_message,
48 list);
49 list_del(&msg->list);
50 }
51
52 return msg;
53}
54
55static int tx_wait_done(struct sst_generic_ipc *ipc,
56 struct ipc_message *msg, void *rx_data)
57{
58 unsigned long flags;
59 int ret;
60
61 /* wait for DSP completion (in all cases atm inc pending) */
62 ret = wait_event_timeout(msg->waitq, msg->complete,
63 msecs_to_jiffies(IPC_TIMEOUT_MSECS));
64
65 spin_lock_irqsave(&ipc->dsp->spinlock, flags);
66 if (ret == 0) {
67 if (ipc->ops.shim_dbg != NULL)
68 ipc->ops.shim_dbg(ipc, "message timeout");
69
70 list_del(&msg->list);
71 ret = -ETIMEDOUT;
72 } else {
73
74 /* copy the data returned from DSP */
75 if (msg->rx_size)
76 memcpy(rx_data, msg->rx_data, msg->rx_size);
77 ret = msg->errno;
78 }
79
80 list_add_tail(&msg->list, &ipc->empty_list);
81 spin_unlock_irqrestore(&ipc->dsp->spinlock, flags);
82 return ret;
83}
84
85static int ipc_tx_message(struct sst_generic_ipc *ipc, u64 header,
86 void *tx_data, size_t tx_bytes, void *rx_data,
87 size_t rx_bytes, int wait)
88{
89 struct ipc_message *msg;
90 unsigned long flags;
91
92 spin_lock_irqsave(&ipc->dsp->spinlock, flags);
93
94 msg = msg_get_empty(ipc);
95 if (msg == NULL) {
96 spin_unlock_irqrestore(&ipc->dsp->spinlock, flags);
97 return -EBUSY;
98 }
99
100 msg->header = header;
101 msg->tx_size = tx_bytes;
102 msg->rx_size = rx_bytes;
103 msg->wait = wait;
104 msg->errno = 0;
105 msg->pending = false;
106 msg->complete = false;
107
108 if ((tx_bytes) && (ipc->ops.tx_data_copy != NULL))
109 ipc->ops.tx_data_copy(msg, tx_data, tx_bytes);
110
111 list_add_tail(&msg->list, &ipc->tx_list);
112 spin_unlock_irqrestore(&ipc->dsp->spinlock, flags);
113
114 queue_kthread_work(&ipc->kworker, &ipc->kwork);
115
116 if (wait)
117 return tx_wait_done(ipc, msg, rx_data);
118 else
119 return 0;
120}
121
122static int msg_empty_list_init(struct sst_generic_ipc *ipc)
123{
124 int i;
125
126 ipc->msg = kzalloc(sizeof(struct ipc_message) *
127 IPC_EMPTY_LIST_SIZE, GFP_KERNEL);
128 if (ipc->msg == NULL)
129 return -ENOMEM;
130
131 for (i = 0; i < IPC_EMPTY_LIST_SIZE; i++) {
132 init_waitqueue_head(&ipc->msg[i].waitq);
133 list_add(&ipc->msg[i].list, &ipc->empty_list);
134 }
135
136 return 0;
137}
138
139static void ipc_tx_msgs(struct kthread_work *work)
140{
141 struct sst_generic_ipc *ipc =
142 container_of(work, struct sst_generic_ipc, kwork);
143 struct ipc_message *msg;
144 unsigned long flags;
145 u64 ipcx;
146
147 spin_lock_irqsave(&ipc->dsp->spinlock, flags);
148
149 if (list_empty(&ipc->tx_list) || ipc->pending) {
150 spin_unlock_irqrestore(&ipc->dsp->spinlock, flags);
151 return;
152 }
153
154 /* if the DSP is busy, we will TX messages after IRQ.
155 * also postpone if we are in the middle of procesing completion irq*/
156 ipcx = sst_dsp_shim_read_unlocked(ipc->dsp, SST_IPCX);
157 if (ipcx & (SST_IPCX_BUSY | SST_IPCX_DONE)) {
158 spin_unlock_irqrestore(&ipc->dsp->spinlock, flags);
159 return;
160 }
161
162 msg = list_first_entry(&ipc->tx_list, struct ipc_message, list);
163 list_move(&msg->list, &ipc->rx_list);
164
165 if (ipc->ops.tx_msg != NULL)
166 ipc->ops.tx_msg(ipc, msg);
167
168 spin_unlock_irqrestore(&ipc->dsp->spinlock, flags);
169}
170
171int sst_ipc_tx_message_wait(struct sst_generic_ipc *ipc, u64 header,
172 void *tx_data, size_t tx_bytes, void *rx_data, size_t rx_bytes)
173{
174 return ipc_tx_message(ipc, header, tx_data, tx_bytes,
175 rx_data, rx_bytes, 1);
176}
177EXPORT_SYMBOL_GPL(sst_ipc_tx_message_wait);
178
179int sst_ipc_tx_message_nowait(struct sst_generic_ipc *ipc, u64 header,
180 void *tx_data, size_t tx_bytes)
181{
182 return ipc_tx_message(ipc, header, tx_data, tx_bytes,
183 NULL, 0, 0);
184}
185EXPORT_SYMBOL_GPL(sst_ipc_tx_message_nowait);
186
187struct ipc_message *sst_ipc_reply_find_msg(struct sst_generic_ipc *ipc,
188 u64 header)
189{
190 struct ipc_message *msg;
191 u64 mask;
192
193 if (ipc->ops.reply_msg_match != NULL)
194 header = ipc->ops.reply_msg_match(header, &mask);
195
196 if (list_empty(&ipc->rx_list)) {
197 dev_err(ipc->dev, "error: rx list empty but received 0x%llx\n",
198 header);
199 return NULL;
200 }
201
202 list_for_each_entry(msg, &ipc->rx_list, list) {
203 if ((msg->header & mask) == header)
204 return msg;
205 }
206
207 return NULL;
208}
209EXPORT_SYMBOL_GPL(sst_ipc_reply_find_msg);
210
211/* locks held by caller */
212void sst_ipc_tx_msg_reply_complete(struct sst_generic_ipc *ipc,
213 struct ipc_message *msg)
214{
215 msg->complete = true;
216
217 if (!msg->wait)
218 list_add_tail(&msg->list, &ipc->empty_list);
219 else
220 wake_up(&msg->waitq);
221}
222EXPORT_SYMBOL_GPL(sst_ipc_tx_msg_reply_complete);
223
224void sst_ipc_drop_all(struct sst_generic_ipc *ipc)
225{
226 struct ipc_message *msg, *tmp;
227 unsigned long flags;
228 int tx_drop_cnt = 0, rx_drop_cnt = 0;
229
230 /* drop all TX and Rx messages before we stall + reset DSP */
231 spin_lock_irqsave(&ipc->dsp->spinlock, flags);
232
233 list_for_each_entry_safe(msg, tmp, &ipc->tx_list, list) {
234 list_move(&msg->list, &ipc->empty_list);
235 tx_drop_cnt++;
236 }
237
238 list_for_each_entry_safe(msg, tmp, &ipc->rx_list, list) {
239 list_move(&msg->list, &ipc->empty_list);
240 rx_drop_cnt++;
241 }
242
243 spin_unlock_irqrestore(&ipc->dsp->spinlock, flags);
244
245 if (tx_drop_cnt || rx_drop_cnt)
246 dev_err(ipc->dev, "dropped IPC msg RX=%d, TX=%d\n",
247 tx_drop_cnt, rx_drop_cnt);
248}
249EXPORT_SYMBOL_GPL(sst_ipc_drop_all);
250
251int sst_ipc_init(struct sst_generic_ipc *ipc)
252{
253 int ret;
254
255 INIT_LIST_HEAD(&ipc->tx_list);
256 INIT_LIST_HEAD(&ipc->rx_list);
257 INIT_LIST_HEAD(&ipc->empty_list);
258 init_waitqueue_head(&ipc->wait_txq);
259
260 ret = msg_empty_list_init(ipc);
261 if (ret < 0)
262 return -ENOMEM;
263
264 /* start the IPC message thread */
265 init_kthread_worker(&ipc->kworker);
266 ipc->tx_thread = kthread_run(kthread_worker_fn,
267 &ipc->kworker, "%s",
268 dev_name(ipc->dev));
269 if (IS_ERR(ipc->tx_thread)) {
270 dev_err(ipc->dev, "error: failed to create message TX task\n");
271 ret = PTR_ERR(ipc->tx_thread);
272 kfree(ipc->msg);
273 return ret;
274 }
275
276 init_kthread_work(&ipc->kwork, ipc_tx_msgs);
277 return 0;
278}
279EXPORT_SYMBOL_GPL(sst_ipc_init);
280
281void sst_ipc_fini(struct sst_generic_ipc *ipc)
282{
283 if (ipc->tx_thread)
284 kthread_stop(ipc->tx_thread);
285
286 if (ipc->msg)
287 kfree(ipc->msg);
288}
289EXPORT_SYMBOL_GPL(sst_ipc_fini);
290
291/* Module information */
292MODULE_AUTHOR("Jin Yao");
293MODULE_DESCRIPTION("Intel SST IPC generic");
294MODULE_LICENSE("GPL v2");
diff --git a/sound/soc/intel/common/sst-ipc.h b/sound/soc/intel/common/sst-ipc.h
new file mode 100644
index 000000000000..125ea451a373
--- /dev/null
+++ b/sound/soc/intel/common/sst-ipc.h
@@ -0,0 +1,91 @@
1/*
2 * Intel SST generic IPC Support
3 *
4 * Copyright (C) 2015, 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#ifndef __SST_GENERIC_IPC_H
18#define __SST_GENERIC_IPC_H
19
20#include <linux/types.h>
21#include <linux/kernel.h>
22#include <linux/wait.h>
23#include <linux/list.h>
24#include <linux/workqueue.h>
25#include <linux/sched.h>
26#include <linux/kthread.h>
27
28#define IPC_MAX_MAILBOX_BYTES 256
29
30struct ipc_message {
31 struct list_head list;
32 u64 header;
33
34 /* direction wrt host CPU */
35 char tx_data[IPC_MAX_MAILBOX_BYTES];
36 size_t tx_size;
37 char rx_data[IPC_MAX_MAILBOX_BYTES];
38 size_t rx_size;
39
40 wait_queue_head_t waitq;
41 bool pending;
42 bool complete;
43 bool wait;
44 int errno;
45};
46
47struct sst_generic_ipc;
48
49struct sst_plat_ipc_ops {
50 void (*tx_msg)(struct sst_generic_ipc *, struct ipc_message *);
51 void (*shim_dbg)(struct sst_generic_ipc *, const char *);
52 void (*tx_data_copy)(struct ipc_message *, char *, size_t);
53 u64 (*reply_msg_match)(u64 header, u64 *mask);
54};
55
56/* SST generic IPC data */
57struct sst_generic_ipc {
58 struct device *dev;
59 struct sst_dsp *dsp;
60
61 /* IPC messaging */
62 struct list_head tx_list;
63 struct list_head rx_list;
64 struct list_head empty_list;
65 wait_queue_head_t wait_txq;
66 struct task_struct *tx_thread;
67 struct kthread_worker kworker;
68 struct kthread_work kwork;
69 bool pending;
70 struct ipc_message *msg;
71
72 struct sst_plat_ipc_ops ops;
73};
74
75int sst_ipc_tx_message_wait(struct sst_generic_ipc *ipc, u64 header,
76 void *tx_data, size_t tx_bytes, void *rx_data, size_t rx_bytes);
77
78int sst_ipc_tx_message_nowait(struct sst_generic_ipc *ipc, u64 header,
79 void *tx_data, size_t tx_bytes);
80
81struct ipc_message *sst_ipc_reply_find_msg(struct sst_generic_ipc *ipc,
82 u64 header);
83
84void sst_ipc_tx_msg_reply_complete(struct sst_generic_ipc *ipc,
85 struct ipc_message *msg);
86
87void sst_ipc_drop_all(struct sst_generic_ipc *ipc);
88int sst_ipc_init(struct sst_generic_ipc *ipc);
89void sst_ipc_fini(struct sst_generic_ipc *ipc);
90
91#endif