aboutsummaryrefslogtreecommitdiffstats
path: root/sound/soc/fsl
diff options
context:
space:
mode:
Diffstat (limited to 'sound/soc/fsl')
-rw-r--r--sound/soc/fsl/Kconfig5
-rw-r--r--sound/soc/fsl/Makefile4
-rw-r--r--sound/soc/fsl/fsl_dma.c2
-rw-r--r--sound/soc/fsl/fsl_sai.c460
-rw-r--r--sound/soc/fsl/fsl_sai.h114
-rw-r--r--sound/soc/fsl/fsl_spdif.c8
-rw-r--r--sound/soc/fsl/fsl_ssi.c435
-rw-r--r--sound/soc/fsl/fsl_ssi.h2
-rw-r--r--sound/soc/fsl/imx-pcm-dma.c9
-rw-r--r--sound/soc/fsl/imx-pcm.h5
-rw-r--r--sound/soc/fsl/imx-spdif.c85
-rw-r--r--sound/soc/fsl/imx-ssi.c12
-rw-r--r--sound/soc/fsl/imx-ssi.h1
-rw-r--r--sound/soc/fsl/imx-wm8962.c2
-rw-r--r--sound/soc/fsl/pcm030-audio-fabric.c3
15 files changed, 941 insertions, 206 deletions
diff --git a/sound/soc/fsl/Kconfig b/sound/soc/fsl/Kconfig
index b7ab71f2ccc1..514c275c6108 100644
--- a/sound/soc/fsl/Kconfig
+++ b/sound/soc/fsl/Kconfig
@@ -1,3 +1,7 @@
1config SND_SOC_FSL_SAI
2 tristate
3 select SND_SOC_GENERIC_DMAENGINE_PCM
4
1config SND_SOC_FSL_SSI 5config SND_SOC_FSL_SSI
2 tristate 6 tristate
3 7
@@ -197,7 +201,6 @@ config SND_SOC_IMX_SPDIF
197 tristate "SoC Audio support for i.MX boards with S/PDIF" 201 tristate "SoC Audio support for i.MX boards with S/PDIF"
198 select SND_SOC_IMX_PCM_DMA 202 select SND_SOC_IMX_PCM_DMA
199 select SND_SOC_FSL_SPDIF 203 select SND_SOC_FSL_SPDIF
200 select SND_SOC_SPDIF
201 select REGMAP_MMIO 204 select REGMAP_MMIO
202 help 205 help
203 SoC Audio support for i.MX boards with S/PDIF 206 SoC Audio support for i.MX boards with S/PDIF
diff --git a/sound/soc/fsl/Makefile b/sound/soc/fsl/Makefile
index 8db705b0fdf9..aaccbee17006 100644
--- a/sound/soc/fsl/Makefile
+++ b/sound/soc/fsl/Makefile
@@ -10,11 +10,13 @@ obj-$(CONFIG_SND_SOC_P1022_DS) += snd-soc-p1022-ds.o
10snd-soc-p1022-rdk-objs := p1022_rdk.o 10snd-soc-p1022-rdk-objs := p1022_rdk.o
11obj-$(CONFIG_SND_SOC_P1022_RDK) += snd-soc-p1022-rdk.o 11obj-$(CONFIG_SND_SOC_P1022_RDK) += snd-soc-p1022-rdk.o
12 12
13# Freescale PowerPC SSI/DMA Platform Support 13# Freescale SSI/DMA/SAI/SPDIF Support
14snd-soc-fsl-sai-objs := fsl_sai.o
14snd-soc-fsl-ssi-objs := fsl_ssi.o 15snd-soc-fsl-ssi-objs := fsl_ssi.o
15snd-soc-fsl-spdif-objs := fsl_spdif.o 16snd-soc-fsl-spdif-objs := fsl_spdif.o
16snd-soc-fsl-utils-objs := fsl_utils.o 17snd-soc-fsl-utils-objs := fsl_utils.o
17snd-soc-fsl-dma-objs := fsl_dma.o 18snd-soc-fsl-dma-objs := fsl_dma.o
19obj-$(CONFIG_SND_SOC_FSL_SAI) += snd-soc-fsl-sai.o
18obj-$(CONFIG_SND_SOC_FSL_SSI) += snd-soc-fsl-ssi.o 20obj-$(CONFIG_SND_SOC_FSL_SSI) += snd-soc-fsl-ssi.o
19obj-$(CONFIG_SND_SOC_FSL_SPDIF) += snd-soc-fsl-spdif.o 21obj-$(CONFIG_SND_SOC_FSL_SPDIF) += snd-soc-fsl-spdif.o
20obj-$(CONFIG_SND_SOC_FSL_UTILS) += snd-soc-fsl-utils.o 22obj-$(CONFIG_SND_SOC_FSL_UTILS) += snd-soc-fsl-utils.o
diff --git a/sound/soc/fsl/fsl_dma.c b/sound/soc/fsl/fsl_dma.c
index fb9bb9eb5ca3..d570f8c81dc6 100644
--- a/sound/soc/fsl/fsl_dma.c
+++ b/sound/soc/fsl/fsl_dma.c
@@ -852,7 +852,7 @@ static void fsl_dma_free_dma_buffers(struct snd_pcm *pcm)
852} 852}
853 853
854/** 854/**
855 * find_ssi_node -- returns the SSI node that points to his DMA channel node 855 * find_ssi_node -- returns the SSI node that points to its DMA channel node
856 * 856 *
857 * Although this DMA driver attempts to operate independently of the other 857 * Although this DMA driver attempts to operate independently of the other
858 * devices, it still needs to determine some information about the SSI device 858 * devices, it still needs to determine some information about the SSI device
diff --git a/sound/soc/fsl/fsl_sai.c b/sound/soc/fsl/fsl_sai.c
new file mode 100644
index 000000000000..5d38a6749b9f
--- /dev/null
+++ b/sound/soc/fsl/fsl_sai.c
@@ -0,0 +1,460 @@
1/*
2 * Freescale ALSA SoC Digital Audio Interface (SAI) driver.
3 *
4 * Copyright 2012-2013 Freescale Semiconductor, Inc.
5 *
6 * This program is free software, you can redistribute it and/or modify it
7 * under the terms of the GNU General Public License as published by the
8 * Free Software Foundation, either version 2 of the License, or(at your
9 * option) any later version.
10 *
11 */
12
13#include <linux/clk.h>
14#include <linux/delay.h>
15#include <linux/dmaengine.h>
16#include <linux/module.h>
17#include <linux/of_address.h>
18#include <linux/slab.h>
19#include <sound/core.h>
20#include <sound/dmaengine_pcm.h>
21#include <sound/pcm_params.h>
22
23#include "fsl_sai.h"
24
25static inline u32 sai_readl(struct fsl_sai *sai,
26 const void __iomem *addr)
27{
28 u32 val;
29
30 val = __raw_readl(addr);
31
32 if (likely(sai->big_endian_regs))
33 val = be32_to_cpu(val);
34 else
35 val = le32_to_cpu(val);
36 rmb();
37
38 return val;
39}
40
41static inline void sai_writel(struct fsl_sai *sai,
42 u32 val, void __iomem *addr)
43{
44 wmb();
45 if (likely(sai->big_endian_regs))
46 val = cpu_to_be32(val);
47 else
48 val = cpu_to_le32(val);
49
50 __raw_writel(val, addr);
51}
52
53static int fsl_sai_set_dai_sysclk_tr(struct snd_soc_dai *cpu_dai,
54 int clk_id, unsigned int freq, int fsl_dir)
55{
56 struct fsl_sai *sai = snd_soc_dai_get_drvdata(cpu_dai);
57 u32 val_cr2, reg_cr2;
58
59 if (fsl_dir == FSL_FMT_TRANSMITTER)
60 reg_cr2 = FSL_SAI_TCR2;
61 else
62 reg_cr2 = FSL_SAI_RCR2;
63
64 val_cr2 = sai_readl(sai, sai->base + reg_cr2);
65 switch (clk_id) {
66 case FSL_SAI_CLK_BUS:
67 val_cr2 &= ~FSL_SAI_CR2_MSEL_MASK;
68 val_cr2 |= FSL_SAI_CR2_MSEL_BUS;
69 break;
70 case FSL_SAI_CLK_MAST1:
71 val_cr2 &= ~FSL_SAI_CR2_MSEL_MASK;
72 val_cr2 |= FSL_SAI_CR2_MSEL_MCLK1;
73 break;
74 case FSL_SAI_CLK_MAST2:
75 val_cr2 &= ~FSL_SAI_CR2_MSEL_MASK;
76 val_cr2 |= FSL_SAI_CR2_MSEL_MCLK2;
77 break;
78 case FSL_SAI_CLK_MAST3:
79 val_cr2 &= ~FSL_SAI_CR2_MSEL_MASK;
80 val_cr2 |= FSL_SAI_CR2_MSEL_MCLK3;
81 break;
82 default:
83 return -EINVAL;
84 }
85 sai_writel(sai, val_cr2, sai->base + reg_cr2);
86
87 return 0;
88}
89
90static int fsl_sai_set_dai_sysclk(struct snd_soc_dai *cpu_dai,
91 int clk_id, unsigned int freq, int dir)
92{
93 struct fsl_sai *sai = snd_soc_dai_get_drvdata(cpu_dai);
94 int ret;
95
96 if (dir == SND_SOC_CLOCK_IN)
97 return 0;
98
99 ret = clk_prepare_enable(sai->clk);
100 if (ret)
101 return ret;
102
103 ret = fsl_sai_set_dai_sysclk_tr(cpu_dai, clk_id, freq,
104 FSL_FMT_TRANSMITTER);
105 if (ret) {
106 dev_err(cpu_dai->dev, "Cannot set tx sysclk: %d\n", ret);
107 goto err_clk;
108 }
109
110 ret = fsl_sai_set_dai_sysclk_tr(cpu_dai, clk_id, freq,
111 FSL_FMT_RECEIVER);
112 if (ret) {
113 dev_err(cpu_dai->dev, "Cannot set rx sysclk: %d\n", ret);
114 goto err_clk;
115 }
116
117err_clk:
118 clk_disable_unprepare(sai->clk);
119
120 return ret;
121}
122
123static int fsl_sai_set_dai_fmt_tr(struct snd_soc_dai *cpu_dai,
124 unsigned int fmt, int fsl_dir)
125{
126 struct fsl_sai *sai = snd_soc_dai_get_drvdata(cpu_dai);
127 u32 val_cr2, val_cr4, reg_cr2, reg_cr4;
128
129 if (fsl_dir == FSL_FMT_TRANSMITTER) {
130 reg_cr2 = FSL_SAI_TCR2;
131 reg_cr4 = FSL_SAI_TCR4;
132 } else {
133 reg_cr2 = FSL_SAI_RCR2;
134 reg_cr4 = FSL_SAI_RCR4;
135 }
136
137 val_cr2 = sai_readl(sai, sai->base + reg_cr2);
138 val_cr4 = sai_readl(sai, sai->base + reg_cr4);
139
140 if (sai->big_endian_data)
141 val_cr4 &= ~FSL_SAI_CR4_MF;
142 else
143 val_cr4 |= FSL_SAI_CR4_MF;
144
145 switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
146 case SND_SOC_DAIFMT_I2S:
147 val_cr4 |= FSL_SAI_CR4_FSE;
148 break;
149 default:
150 return -EINVAL;
151 }
152
153 switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
154 case SND_SOC_DAIFMT_IB_IF:
155 val_cr4 |= FSL_SAI_CR4_FSP;
156 val_cr2 &= ~FSL_SAI_CR2_BCP;
157 break;
158 case SND_SOC_DAIFMT_IB_NF:
159 val_cr4 &= ~FSL_SAI_CR4_FSP;
160 val_cr2 &= ~FSL_SAI_CR2_BCP;
161 break;
162 case SND_SOC_DAIFMT_NB_IF:
163 val_cr4 |= FSL_SAI_CR4_FSP;
164 val_cr2 |= FSL_SAI_CR2_BCP;
165 break;
166 case SND_SOC_DAIFMT_NB_NF:
167 val_cr4 &= ~FSL_SAI_CR4_FSP;
168 val_cr2 |= FSL_SAI_CR2_BCP;
169 break;
170 default:
171 return -EINVAL;
172 }
173
174 switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
175 case SND_SOC_DAIFMT_CBS_CFS:
176 val_cr2 |= FSL_SAI_CR2_BCD_MSTR;
177 val_cr4 |= FSL_SAI_CR4_FSD_MSTR;
178 break;
179 case SND_SOC_DAIFMT_CBM_CFM:
180 val_cr2 &= ~FSL_SAI_CR2_BCD_MSTR;
181 val_cr4 &= ~FSL_SAI_CR4_FSD_MSTR;
182 break;
183 default:
184 return -EINVAL;
185 }
186
187 sai_writel(sai, val_cr2, sai->base + reg_cr2);
188 sai_writel(sai, val_cr4, sai->base + reg_cr4);
189
190 return 0;
191}
192
193static int fsl_sai_set_dai_fmt(struct snd_soc_dai *cpu_dai, unsigned int fmt)
194{
195 struct fsl_sai *sai = snd_soc_dai_get_drvdata(cpu_dai);
196 int ret;
197
198 ret = clk_prepare_enable(sai->clk);
199 if (ret)
200 return ret;
201
202 ret = fsl_sai_set_dai_fmt_tr(cpu_dai, fmt, FSL_FMT_TRANSMITTER);
203 if (ret) {
204 dev_err(cpu_dai->dev, "Cannot set tx format: %d\n", ret);
205 goto err_clk;
206 }
207
208 ret = fsl_sai_set_dai_fmt_tr(cpu_dai, fmt, FSL_FMT_RECEIVER);
209 if (ret) {
210 dev_err(cpu_dai->dev, "Cannot set rx format: %d\n", ret);
211 goto err_clk;
212 }
213
214err_clk:
215 clk_disable_unprepare(sai->clk);
216
217 return ret;
218}
219
220static int fsl_sai_hw_params(struct snd_pcm_substream *substream,
221 struct snd_pcm_hw_params *params,
222 struct snd_soc_dai *cpu_dai)
223{
224 struct fsl_sai *sai = snd_soc_dai_get_drvdata(cpu_dai);
225 u32 val_cr4, val_cr5, val_mr, reg_cr4, reg_cr5, reg_mr;
226 unsigned int channels = params_channels(params);
227 u32 word_width = snd_pcm_format_width(params_format(params));
228
229 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
230 reg_cr4 = FSL_SAI_TCR4;
231 reg_cr5 = FSL_SAI_TCR5;
232 reg_mr = FSL_SAI_TMR;
233 } else {
234 reg_cr4 = FSL_SAI_RCR4;
235 reg_cr5 = FSL_SAI_RCR5;
236 reg_mr = FSL_SAI_RMR;
237 }
238
239 val_cr4 = sai_readl(sai, sai->base + reg_cr4);
240 val_cr4 &= ~FSL_SAI_CR4_SYWD_MASK;
241 val_cr4 &= ~FSL_SAI_CR4_FRSZ_MASK;
242
243 val_cr5 = sai_readl(sai, sai->base + reg_cr5);
244 val_cr5 &= ~FSL_SAI_CR5_WNW_MASK;
245 val_cr5 &= ~FSL_SAI_CR5_W0W_MASK;
246 val_cr5 &= ~FSL_SAI_CR5_FBT_MASK;
247
248 val_cr4 |= FSL_SAI_CR4_SYWD(word_width);
249 val_cr5 |= FSL_SAI_CR5_WNW(word_width);
250 val_cr5 |= FSL_SAI_CR5_W0W(word_width);
251
252 val_cr5 &= ~FSL_SAI_CR5_FBT_MASK;
253 if (sai->big_endian_data)
254 val_cr5 |= FSL_SAI_CR5_FBT(0);
255 else
256 val_cr5 |= FSL_SAI_CR5_FBT(word_width - 1);
257
258 val_cr4 |= FSL_SAI_CR4_FRSZ(channels);
259 val_mr = ~0UL - ((1 << channels) - 1);
260
261 sai_writel(sai, val_cr4, sai->base + reg_cr4);
262 sai_writel(sai, val_cr5, sai->base + reg_cr5);
263 sai_writel(sai, val_mr, sai->base + reg_mr);
264
265 return 0;
266}
267
268static int fsl_sai_trigger(struct snd_pcm_substream *substream, int cmd,
269 struct snd_soc_dai *cpu_dai)
270{
271 struct fsl_sai *sai = snd_soc_dai_get_drvdata(cpu_dai);
272 u32 tcsr, rcsr, val_cr2, val_cr3, reg_cr3;
273
274 val_cr2 = sai_readl(sai, sai->base + FSL_SAI_TCR2);
275 val_cr2 &= ~FSL_SAI_CR2_SYNC;
276 sai_writel(sai, val_cr2, sai->base + FSL_SAI_TCR2);
277
278 val_cr2 = sai_readl(sai, sai->base + FSL_SAI_RCR2);
279 val_cr2 |= FSL_SAI_CR2_SYNC;
280 sai_writel(sai, val_cr2, sai->base + FSL_SAI_RCR2);
281
282 tcsr = sai_readl(sai, sai->base + FSL_SAI_TCSR);
283 rcsr = sai_readl(sai, sai->base + FSL_SAI_RCSR);
284
285 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
286 tcsr |= FSL_SAI_CSR_FRDE;
287 rcsr &= ~FSL_SAI_CSR_FRDE;
288 reg_cr3 = FSL_SAI_TCR3;
289 } else {
290 rcsr |= FSL_SAI_CSR_FRDE;
291 tcsr &= ~FSL_SAI_CSR_FRDE;
292 reg_cr3 = FSL_SAI_RCR3;
293 }
294
295 val_cr3 = sai_readl(sai, sai->base + reg_cr3);
296
297 switch (cmd) {
298 case SNDRV_PCM_TRIGGER_START:
299 case SNDRV_PCM_TRIGGER_RESUME:
300 case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
301 tcsr |= FSL_SAI_CSR_TERE;
302 rcsr |= FSL_SAI_CSR_TERE;
303 val_cr3 |= FSL_SAI_CR3_TRCE;
304
305 sai_writel(sai, val_cr3, sai->base + reg_cr3);
306 sai_writel(sai, rcsr, sai->base + FSL_SAI_RCSR);
307 sai_writel(sai, tcsr, sai->base + FSL_SAI_TCSR);
308 break;
309
310 case SNDRV_PCM_TRIGGER_STOP:
311 case SNDRV_PCM_TRIGGER_SUSPEND:
312 case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
313 if (!(cpu_dai->playback_active || cpu_dai->capture_active)) {
314 tcsr &= ~FSL_SAI_CSR_TERE;
315 rcsr &= ~FSL_SAI_CSR_TERE;
316 }
317
318 val_cr3 &= ~FSL_SAI_CR3_TRCE;
319
320 sai_writel(sai, tcsr, sai->base + FSL_SAI_TCSR);
321 sai_writel(sai, rcsr, sai->base + FSL_SAI_RCSR);
322 sai_writel(sai, val_cr3, sai->base + reg_cr3);
323 break;
324 default:
325 return -EINVAL;
326 }
327
328 return 0;
329}
330
331static int fsl_sai_startup(struct snd_pcm_substream *substream,
332 struct snd_soc_dai *cpu_dai)
333{
334 struct fsl_sai *sai = snd_soc_dai_get_drvdata(cpu_dai);
335
336 return clk_prepare_enable(sai->clk);
337}
338
339static void fsl_sai_shutdown(struct snd_pcm_substream *substream,
340 struct snd_soc_dai *cpu_dai)
341{
342 struct fsl_sai *sai = snd_soc_dai_get_drvdata(cpu_dai);
343
344 clk_disable_unprepare(sai->clk);
345}
346
347static const struct snd_soc_dai_ops fsl_sai_pcm_dai_ops = {
348 .set_sysclk = fsl_sai_set_dai_sysclk,
349 .set_fmt = fsl_sai_set_dai_fmt,
350 .hw_params = fsl_sai_hw_params,
351 .trigger = fsl_sai_trigger,
352 .startup = fsl_sai_startup,
353 .shutdown = fsl_sai_shutdown,
354};
355
356static int fsl_sai_dai_probe(struct snd_soc_dai *cpu_dai)
357{
358 struct fsl_sai *sai = dev_get_drvdata(cpu_dai->dev);
359 int ret;
360
361 ret = clk_prepare_enable(sai->clk);
362 if (ret)
363 return ret;
364
365 sai_writel(sai, 0x0, sai->base + FSL_SAI_RCSR);
366 sai_writel(sai, 0x0, sai->base + FSL_SAI_TCSR);
367 sai_writel(sai, FSL_SAI_MAXBURST_TX * 2, sai->base + FSL_SAI_TCR1);
368 sai_writel(sai, FSL_SAI_MAXBURST_RX - 1, sai->base + FSL_SAI_RCR1);
369
370 clk_disable_unprepare(sai->clk);
371
372 snd_soc_dai_init_dma_data(cpu_dai, &sai->dma_params_tx,
373 &sai->dma_params_rx);
374
375 snd_soc_dai_set_drvdata(cpu_dai, sai);
376
377 return 0;
378}
379
380static struct snd_soc_dai_driver fsl_sai_dai = {
381 .probe = fsl_sai_dai_probe,
382 .playback = {
383 .channels_min = 1,
384 .channels_max = 2,
385 .rates = SNDRV_PCM_RATE_8000_96000,
386 .formats = FSL_SAI_FORMATS,
387 },
388 .capture = {
389 .channels_min = 1,
390 .channels_max = 2,
391 .rates = SNDRV_PCM_RATE_8000_96000,
392 .formats = FSL_SAI_FORMATS,
393 },
394 .ops = &fsl_sai_pcm_dai_ops,
395};
396
397static const struct snd_soc_component_driver fsl_component = {
398 .name = "fsl-sai",
399};
400
401static int fsl_sai_probe(struct platform_device *pdev)
402{
403 struct device_node *np = pdev->dev.of_node;
404 struct fsl_sai *sai;
405 struct resource *res;
406 int ret;
407
408 sai = devm_kzalloc(&pdev->dev, sizeof(*sai), GFP_KERNEL);
409 if (!sai)
410 return -ENOMEM;
411
412 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
413 sai->base = devm_ioremap_resource(&pdev->dev, res);
414 if (IS_ERR(sai->base))
415 return PTR_ERR(sai->base);
416
417 sai->clk = devm_clk_get(&pdev->dev, "sai");
418 if (IS_ERR(sai->clk)) {
419 dev_err(&pdev->dev, "Cannot get SAI's clock\n");
420 return PTR_ERR(sai->clk);
421 }
422
423 sai->dma_params_rx.addr = res->start + FSL_SAI_RDR;
424 sai->dma_params_tx.addr = res->start + FSL_SAI_TDR;
425 sai->dma_params_rx.maxburst = FSL_SAI_MAXBURST_RX;
426 sai->dma_params_tx.maxburst = FSL_SAI_MAXBURST_TX;
427
428 sai->big_endian_regs = of_property_read_bool(np, "big-endian-regs");
429 sai->big_endian_data = of_property_read_bool(np, "big-endian-data");
430
431 platform_set_drvdata(pdev, sai);
432
433 ret = devm_snd_soc_register_component(&pdev->dev, &fsl_component,
434 &fsl_sai_dai, 1);
435 if (ret)
436 return ret;
437
438 return devm_snd_dmaengine_pcm_register(&pdev->dev, NULL,
439 SND_DMAENGINE_PCM_FLAG_NO_RESIDUE);
440}
441
442static const struct of_device_id fsl_sai_ids[] = {
443 { .compatible = "fsl,vf610-sai", },
444 { /* sentinel */ }
445};
446
447static struct platform_driver fsl_sai_driver = {
448 .probe = fsl_sai_probe,
449 .driver = {
450 .name = "fsl-sai",
451 .owner = THIS_MODULE,
452 .of_match_table = fsl_sai_ids,
453 },
454};
455module_platform_driver(fsl_sai_driver);
456
457MODULE_DESCRIPTION("Freescale Soc SAI Interface");
458MODULE_AUTHOR("Xiubo Li, <Li.Xiubo@freescale.com>");
459MODULE_ALIAS("platform:fsl-sai");
460MODULE_LICENSE("GPL");
diff --git a/sound/soc/fsl/fsl_sai.h b/sound/soc/fsl/fsl_sai.h
new file mode 100644
index 000000000000..41bb62e69361
--- /dev/null
+++ b/sound/soc/fsl/fsl_sai.h
@@ -0,0 +1,114 @@
1/*
2 * Copyright 2012-2013 Freescale Semiconductor, Inc.
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License version 2 as
6 * published by the Free Software Foundation.
7 */
8
9#ifndef __FSL_SAI_H
10#define __FSL_SAI_H
11
12#include <sound/dmaengine_pcm.h>
13
14#define FSL_SAI_FORMATS (SNDRV_PCM_FMTBIT_S16_LE |\
15 SNDRV_PCM_FMTBIT_S20_3LE |\
16 SNDRV_PCM_FMTBIT_S24_LE)
17
18/* SAI Transmit/Recieve Control Register */
19#define FSL_SAI_TCSR 0x00
20#define FSL_SAI_RCSR 0x80
21#define FSL_SAI_CSR_TERE BIT(31)
22#define FSL_SAI_CSR_FWF BIT(17)
23#define FSL_SAI_CSR_FRIE BIT(8)
24#define FSL_SAI_CSR_FRDE BIT(0)
25
26/* SAI Transmit Data/FIFO/MASK Register */
27#define FSL_SAI_TDR 0x20
28#define FSL_SAI_TFR 0x40
29#define FSL_SAI_TMR 0x60
30
31/* SAI Recieve Data/FIFO/MASK Register */
32#define FSL_SAI_RDR 0xa0
33#define FSL_SAI_RFR 0xc0
34#define FSL_SAI_RMR 0xe0
35
36/* SAI Transmit and Recieve Configuration 1 Register */
37#define FSL_SAI_TCR1 0x04
38#define FSL_SAI_RCR1 0x84
39
40/* SAI Transmit and Recieve Configuration 2 Register */
41#define FSL_SAI_TCR2 0x08
42#define FSL_SAI_RCR2 0x88
43#define FSL_SAI_CR2_SYNC BIT(30)
44#define FSL_SAI_CR2_MSEL_MASK (0xff << 26)
45#define FSL_SAI_CR2_MSEL_BUS 0
46#define FSL_SAI_CR2_MSEL_MCLK1 BIT(26)
47#define FSL_SAI_CR2_MSEL_MCLK2 BIT(27)
48#define FSL_SAI_CR2_MSEL_MCLK3 (BIT(26) | BIT(27))
49#define FSL_SAI_CR2_BCP BIT(25)
50#define FSL_SAI_CR2_BCD_MSTR BIT(24)
51
52/* SAI Transmit and Recieve Configuration 3 Register */
53#define FSL_SAI_TCR3 0x0c
54#define FSL_SAI_RCR3 0x8c
55#define FSL_SAI_CR3_TRCE BIT(16)
56#define FSL_SAI_CR3_WDFL(x) (x)
57#define FSL_SAI_CR3_WDFL_MASK 0x1f
58
59/* SAI Transmit and Recieve Configuration 4 Register */
60#define FSL_SAI_TCR4 0x10
61#define FSL_SAI_RCR4 0x90
62#define FSL_SAI_CR4_FRSZ(x) (((x) - 1) << 16)
63#define FSL_SAI_CR4_FRSZ_MASK (0x1f << 16)
64#define FSL_SAI_CR4_SYWD(x) (((x) - 1) << 8)
65#define FSL_SAI_CR4_SYWD_MASK (0x1f << 8)
66#define FSL_SAI_CR4_MF BIT(4)
67#define FSL_SAI_CR4_FSE BIT(3)
68#define FSL_SAI_CR4_FSP BIT(1)
69#define FSL_SAI_CR4_FSD_MSTR BIT(0)
70
71/* SAI Transmit and Recieve Configuration 5 Register */
72#define FSL_SAI_TCR5 0x14
73#define FSL_SAI_RCR5 0x94
74#define FSL_SAI_CR5_WNW(x) (((x) - 1) << 24)
75#define FSL_SAI_CR5_WNW_MASK (0x1f << 24)
76#define FSL_SAI_CR5_W0W(x) (((x) - 1) << 16)
77#define FSL_SAI_CR5_W0W_MASK (0x1f << 16)
78#define FSL_SAI_CR5_FBT(x) ((x) << 8)
79#define FSL_SAI_CR5_FBT_MASK (0x1f << 8)
80
81/* SAI type */
82#define FSL_SAI_DMA BIT(0)
83#define FSL_SAI_USE_AC97 BIT(1)
84#define FSL_SAI_NET BIT(2)
85#define FSL_SAI_TRA_SYN BIT(3)
86#define FSL_SAI_REC_SYN BIT(4)
87#define FSL_SAI_USE_I2S_SLAVE BIT(5)
88
89#define FSL_FMT_TRANSMITTER 0
90#define FSL_FMT_RECEIVER 1
91
92/* SAI clock sources */
93#define FSL_SAI_CLK_BUS 0
94#define FSL_SAI_CLK_MAST1 1
95#define FSL_SAI_CLK_MAST2 2
96#define FSL_SAI_CLK_MAST3 3
97
98/* SAI data transfer numbers per DMA request */
99#define FSL_SAI_MAXBURST_TX 6
100#define FSL_SAI_MAXBURST_RX 6
101
102struct fsl_sai {
103 struct clk *clk;
104
105 void __iomem *base;
106
107 bool big_endian_regs;
108 bool big_endian_data;
109
110 struct snd_dmaengine_dai_dma_data dma_params_rx;
111 struct snd_dmaengine_dai_dma_data dma_params_tx;
112};
113
114#endif /* __FSL_SAI_H */
diff --git a/sound/soc/fsl/fsl_spdif.c b/sound/soc/fsl/fsl_spdif.c
index 55193a5596ca..4d075f1abe78 100644
--- a/sound/soc/fsl/fsl_spdif.c
+++ b/sound/soc/fsl/fsl_spdif.c
@@ -1181,13 +1181,6 @@ static int fsl_spdif_probe(struct platform_device *pdev)
1181 return ret; 1181 return ret;
1182} 1182}
1183 1183
1184static int fsl_spdif_remove(struct platform_device *pdev)
1185{
1186 imx_pcm_dma_exit(pdev);
1187
1188 return 0;
1189}
1190
1191static const struct of_device_id fsl_spdif_dt_ids[] = { 1184static const struct of_device_id fsl_spdif_dt_ids[] = {
1192 { .compatible = "fsl,imx35-spdif", }, 1185 { .compatible = "fsl,imx35-spdif", },
1193 {} 1186 {}
@@ -1201,7 +1194,6 @@ static struct platform_driver fsl_spdif_driver = {
1201 .of_match_table = fsl_spdif_dt_ids, 1194 .of_match_table = fsl_spdif_dt_ids,
1202 }, 1195 },
1203 .probe = fsl_spdif_probe, 1196 .probe = fsl_spdif_probe,
1204 .remove = fsl_spdif_remove,
1205}; 1197};
1206 1198
1207module_platform_driver(fsl_spdif_driver); 1199module_platform_driver(fsl_spdif_driver);
diff --git a/sound/soc/fsl/fsl_ssi.c b/sound/soc/fsl/fsl_ssi.c
index 35e277379b86..b2ebaf811599 100644
--- a/sound/soc/fsl/fsl_ssi.c
+++ b/sound/soc/fsl/fsl_ssi.c
@@ -38,6 +38,7 @@
38#include <linux/device.h> 38#include <linux/device.h>
39#include <linux/delay.h> 39#include <linux/delay.h>
40#include <linux/slab.h> 40#include <linux/slab.h>
41#include <linux/spinlock.h>
41#include <linux/of_address.h> 42#include <linux/of_address.h>
42#include <linux/of_irq.h> 43#include <linux/of_irq.h>
43#include <linux/of_platform.h> 44#include <linux/of_platform.h>
@@ -119,8 +120,6 @@ static inline void write_ssi_mask(u32 __iomem *addr, u32 clear, u32 set)
119 * @ssi: pointer to the SSI's registers 120 * @ssi: pointer to the SSI's registers
120 * @ssi_phys: physical address of the SSI registers 121 * @ssi_phys: physical address of the SSI registers
121 * @irq: IRQ of this SSI 122 * @irq: IRQ of this SSI
122 * @first_stream: pointer to the stream that was opened first
123 * @second_stream: pointer to second stream
124 * @playback: the number of playback streams opened 123 * @playback: the number of playback streams opened
125 * @capture: the number of capture streams opened 124 * @capture: the number of capture streams opened
126 * @cpu_dai: the CPU DAI for this device 125 * @cpu_dai: the CPU DAI for this device
@@ -132,8 +131,6 @@ struct fsl_ssi_private {
132 struct ccsr_ssi __iomem *ssi; 131 struct ccsr_ssi __iomem *ssi;
133 dma_addr_t ssi_phys; 132 dma_addr_t ssi_phys;
134 unsigned int irq; 133 unsigned int irq;
135 struct snd_pcm_substream *first_stream;
136 struct snd_pcm_substream *second_stream;
137 unsigned int fifo_depth; 134 unsigned int fifo_depth;
138 struct snd_soc_dai_driver cpu_dai_drv; 135 struct snd_soc_dai_driver cpu_dai_drv;
139 struct device_attribute dev_attr; 136 struct device_attribute dev_attr;
@@ -143,6 +140,10 @@ struct fsl_ssi_private {
143 bool ssi_on_imx; 140 bool ssi_on_imx;
144 bool imx_ac97; 141 bool imx_ac97;
145 bool use_dma; 142 bool use_dma;
143 bool baudclk_locked;
144 u8 i2s_mode;
145 spinlock_t baudclk_lock;
146 struct clk *baudclk;
146 struct clk *clk; 147 struct clk *clk;
147 struct snd_dmaengine_dai_dma_data dma_params_tx; 148 struct snd_dmaengine_dai_dma_data dma_params_tx;
148 struct snd_dmaengine_dai_dma_data dma_params_rx; 149 struct snd_dmaengine_dai_dma_data dma_params_rx;
@@ -321,17 +322,46 @@ static irqreturn_t fsl_ssi_isr(int irq, void *dev_id)
321 return ret; 322 return ret;
322} 323}
323 324
325static void fsl_ssi_setup_ac97(struct fsl_ssi_private *ssi_private)
326{
327 struct ccsr_ssi __iomem *ssi = ssi_private->ssi;
328
329 /*
330 * Setup the clock control register
331 */
332 write_ssi(CCSR_SSI_SxCCR_WL(17) | CCSR_SSI_SxCCR_DC(13),
333 &ssi->stccr);
334 write_ssi(CCSR_SSI_SxCCR_WL(17) | CCSR_SSI_SxCCR_DC(13),
335 &ssi->srccr);
336
337 /*
338 * Enable AC97 mode and startup the SSI
339 */
340 write_ssi(CCSR_SSI_SACNT_AC97EN | CCSR_SSI_SACNT_FV,
341 &ssi->sacnt);
342 write_ssi(0xff, &ssi->saccdis);
343 write_ssi(0x300, &ssi->saccen);
344
345 /*
346 * Enable SSI, Transmit and Receive. AC97 has to communicate with the
347 * codec before a stream is started.
348 */
349 write_ssi_mask(&ssi->scr, 0, CCSR_SSI_SCR_SSIEN |
350 CCSR_SSI_SCR_TE | CCSR_SSI_SCR_RE);
351
352 write_ssi(CCSR_SSI_SOR_WAIT(3), &ssi->sor);
353}
354
324static int fsl_ssi_setup(struct fsl_ssi_private *ssi_private) 355static int fsl_ssi_setup(struct fsl_ssi_private *ssi_private)
325{ 356{
326 struct ccsr_ssi __iomem *ssi = ssi_private->ssi; 357 struct ccsr_ssi __iomem *ssi = ssi_private->ssi;
327 u8 i2s_mode;
328 u8 wm; 358 u8 wm;
329 int synchronous = ssi_private->cpu_dai_drv.symmetric_rates; 359 int synchronous = ssi_private->cpu_dai_drv.symmetric_rates;
330 360
331 if (ssi_private->imx_ac97) 361 if (ssi_private->imx_ac97)
332 i2s_mode = CCSR_SSI_SCR_I2S_MODE_NORMAL | CCSR_SSI_SCR_NET; 362 ssi_private->i2s_mode = CCSR_SSI_SCR_I2S_MODE_NORMAL | CCSR_SSI_SCR_NET;
333 else 363 else
334 i2s_mode = CCSR_SSI_SCR_I2S_MODE_SLAVE; 364 ssi_private->i2s_mode = CCSR_SSI_SCR_I2S_MODE_SLAVE;
335 365
336 /* 366 /*
337 * Section 16.5 of the MPC8610 reference manual says that the SSI needs 367 * Section 16.5 of the MPC8610 reference manual says that the SSI needs
@@ -348,7 +378,7 @@ static int fsl_ssi_setup(struct fsl_ssi_private *ssi_private)
348 write_ssi_mask(&ssi->scr, 378 write_ssi_mask(&ssi->scr,
349 CCSR_SSI_SCR_I2S_MODE_MASK | CCSR_SSI_SCR_SYN, 379 CCSR_SSI_SCR_I2S_MODE_MASK | CCSR_SSI_SCR_SYN,
350 CCSR_SSI_SCR_TFR_CLK_DIS | 380 CCSR_SSI_SCR_TFR_CLK_DIS |
351 i2s_mode | 381 ssi_private->i2s_mode |
352 (synchronous ? CCSR_SSI_SCR_SYN : 0)); 382 (synchronous ? CCSR_SSI_SCR_SYN : 0));
353 383
354 write_ssi(CCSR_SSI_STCR_TXBIT0 | CCSR_SSI_STCR_TFEN0 | 384 write_ssi(CCSR_SSI_STCR_TXBIT0 | CCSR_SSI_STCR_TFEN0 |
@@ -387,31 +417,8 @@ static int fsl_ssi_setup(struct fsl_ssi_private *ssi_private)
387 * because it is also running without an active substream. Normally SSI 417 * because it is also running without an active substream. Normally SSI
388 * is only enabled when there is a substream. 418 * is only enabled when there is a substream.
389 */ 419 */
390 if (ssi_private->imx_ac97) { 420 if (ssi_private->imx_ac97)
391 /* 421 fsl_ssi_setup_ac97(ssi_private);
392 * Setup the clock control register
393 */
394 write_ssi(CCSR_SSI_SxCCR_WL(17) | CCSR_SSI_SxCCR_DC(13),
395 &ssi->stccr);
396 write_ssi(CCSR_SSI_SxCCR_WL(17) | CCSR_SSI_SxCCR_DC(13),
397 &ssi->srccr);
398
399 /*
400 * Enable AC97 mode and startup the SSI
401 */
402 write_ssi(CCSR_SSI_SACNT_AC97EN | CCSR_SSI_SACNT_FV,
403 &ssi->sacnt);
404 write_ssi(0xff, &ssi->saccdis);
405 write_ssi(0x300, &ssi->saccen);
406
407 /*
408 * Enable SSI, Transmit and Receive
409 */
410 write_ssi_mask(&ssi->scr, 0, CCSR_SSI_SCR_SSIEN |
411 CCSR_SSI_SCR_TE | CCSR_SSI_SCR_RE);
412
413 write_ssi(CCSR_SSI_SOR_WAIT(3), &ssi->sor);
414 }
415 422
416 return 0; 423 return 0;
417} 424}
@@ -431,53 +438,17 @@ static int fsl_ssi_startup(struct snd_pcm_substream *substream,
431 struct snd_soc_pcm_runtime *rtd = substream->private_data; 438 struct snd_soc_pcm_runtime *rtd = substream->private_data;
432 struct fsl_ssi_private *ssi_private = 439 struct fsl_ssi_private *ssi_private =
433 snd_soc_dai_get_drvdata(rtd->cpu_dai); 440 snd_soc_dai_get_drvdata(rtd->cpu_dai);
434 int synchronous = ssi_private->cpu_dai_drv.symmetric_rates; 441 unsigned long flags;
435 442
436 /* 443 /* First, we only do fsl_ssi_setup() when SSI is going to be active.
437 * If this is the first stream opened, then request the IRQ 444 * Second, fsl_ssi_setup was already called by ac97_init earlier if
438 * and initialize the SSI registers. 445 * the driver is in ac97 mode.
439 */ 446 */
440 if (!ssi_private->first_stream) { 447 if (!dai->active && !ssi_private->imx_ac97) {
441 ssi_private->first_stream = substream; 448 fsl_ssi_setup(ssi_private);
442 449 spin_lock_irqsave(&ssi_private->baudclk_lock, flags);
443 /* 450 ssi_private->baudclk_locked = false;
444 * fsl_ssi_setup was already called by ac97_init earlier if 451 spin_unlock_irqrestore(&ssi_private->baudclk_lock, flags);
445 * the driver is in ac97 mode.
446 */
447 if (!ssi_private->imx_ac97)
448 fsl_ssi_setup(ssi_private);
449 } else {
450 if (synchronous) {
451 struct snd_pcm_runtime *first_runtime =
452 ssi_private->first_stream->runtime;
453 /*
454 * This is the second stream open, and we're in
455 * synchronous mode, so we need to impose sample
456 * sample size constraints. This is because STCCR is
457 * used for playback and capture in synchronous mode,
458 * so there's no way to specify different word
459 * lengths.
460 *
461 * Note that this can cause a race condition if the
462 * second stream is opened before the first stream is
463 * fully initialized. We provide some protection by
464 * checking to make sure the first stream is
465 * initialized, but it's not perfect. ALSA sometimes
466 * re-initializes the driver with a different sample
467 * rate or size. If the second stream is opened
468 * before the first stream has received its final
469 * parameters, then the second stream may be
470 * constrained to the wrong sample rate or size.
471 */
472 if (first_runtime->sample_bits) {
473 snd_pcm_hw_constraint_minmax(substream->runtime,
474 SNDRV_PCM_HW_PARAM_SAMPLE_BITS,
475 first_runtime->sample_bits,
476 first_runtime->sample_bits);
477 }
478 }
479
480 ssi_private->second_stream = substream;
481 } 452 }
482 453
483 return 0; 454 return 0;
@@ -501,6 +472,7 @@ static int fsl_ssi_hw_params(struct snd_pcm_substream *substream,
501{ 472{
502 struct fsl_ssi_private *ssi_private = snd_soc_dai_get_drvdata(cpu_dai); 473 struct fsl_ssi_private *ssi_private = snd_soc_dai_get_drvdata(cpu_dai);
503 struct ccsr_ssi __iomem *ssi = ssi_private->ssi; 474 struct ccsr_ssi __iomem *ssi = ssi_private->ssi;
475 unsigned int channels = params_channels(hw_params);
504 unsigned int sample_size = 476 unsigned int sample_size =
505 snd_pcm_format_width(params_format(hw_params)); 477 snd_pcm_format_width(params_format(hw_params));
506 u32 wl = CCSR_SSI_SxCCR_WL(sample_size); 478 u32 wl = CCSR_SSI_SxCCR_WL(sample_size);
@@ -530,6 +502,248 @@ static int fsl_ssi_hw_params(struct snd_pcm_substream *substream,
530 else 502 else
531 write_ssi_mask(&ssi->srccr, CCSR_SSI_SxCCR_WL_MASK, wl); 503 write_ssi_mask(&ssi->srccr, CCSR_SSI_SxCCR_WL_MASK, wl);
532 504
505 if (!ssi_private->imx_ac97)
506 write_ssi_mask(&ssi->scr,
507 CCSR_SSI_SCR_NET | CCSR_SSI_SCR_I2S_MODE_MASK,
508 channels == 1 ? 0 : ssi_private->i2s_mode);
509
510 return 0;
511}
512
513/**
514 * fsl_ssi_set_dai_fmt - configure Digital Audio Interface Format.
515 */
516static int fsl_ssi_set_dai_fmt(struct snd_soc_dai *cpu_dai, unsigned int fmt)
517{
518 struct fsl_ssi_private *ssi_private = snd_soc_dai_get_drvdata(cpu_dai);
519 struct ccsr_ssi __iomem *ssi = ssi_private->ssi;
520 u32 strcr = 0, stcr, srcr, scr, mask;
521
522 scr = read_ssi(&ssi->scr) & ~(CCSR_SSI_SCR_SYN | CCSR_SSI_SCR_I2S_MODE_MASK);
523 scr |= CCSR_SSI_SCR_NET;
524
525 mask = CCSR_SSI_STCR_TXBIT0 | CCSR_SSI_STCR_TFDIR | CCSR_SSI_STCR_TXDIR |
526 CCSR_SSI_STCR_TSCKP | CCSR_SSI_STCR_TFSI | CCSR_SSI_STCR_TFSL |
527 CCSR_SSI_STCR_TEFS;
528 stcr = read_ssi(&ssi->stcr) & ~mask;
529 srcr = read_ssi(&ssi->srcr) & ~mask;
530
531 switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
532 case SND_SOC_DAIFMT_I2S:
533 switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
534 case SND_SOC_DAIFMT_CBS_CFS:
535 ssi_private->i2s_mode = CCSR_SSI_SCR_I2S_MODE_MASTER;
536 break;
537 case SND_SOC_DAIFMT_CBM_CFM:
538 ssi_private->i2s_mode = CCSR_SSI_SCR_I2S_MODE_SLAVE;
539 break;
540 default:
541 return -EINVAL;
542 }
543 scr |= ssi_private->i2s_mode;
544
545 /* Data on rising edge of bclk, frame low, 1clk before data */
546 strcr |= CCSR_SSI_STCR_TFSI | CCSR_SSI_STCR_TSCKP |
547 CCSR_SSI_STCR_TXBIT0 | CCSR_SSI_STCR_TEFS;
548 break;
549 case SND_SOC_DAIFMT_LEFT_J:
550 /* Data on rising edge of bclk, frame high */
551 strcr |= CCSR_SSI_STCR_TXBIT0 | CCSR_SSI_STCR_TSCKP;
552 break;
553 case SND_SOC_DAIFMT_DSP_A:
554 /* Data on rising edge of bclk, frame high, 1clk before data */
555 strcr |= CCSR_SSI_STCR_TFSL | CCSR_SSI_STCR_TSCKP |
556 CCSR_SSI_STCR_TXBIT0 | CCSR_SSI_STCR_TEFS;
557 break;
558 case SND_SOC_DAIFMT_DSP_B:
559 /* Data on rising edge of bclk, frame high */
560 strcr |= CCSR_SSI_STCR_TFSL | CCSR_SSI_STCR_TSCKP |
561 CCSR_SSI_STCR_TXBIT0;
562 break;
563 default:
564 return -EINVAL;
565 }
566
567 /* DAI clock inversion */
568 switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
569 case SND_SOC_DAIFMT_NB_NF:
570 /* Nothing to do for both normal cases */
571 break;
572 case SND_SOC_DAIFMT_IB_NF:
573 /* Invert bit clock */
574 strcr ^= CCSR_SSI_STCR_TSCKP;
575 break;
576 case SND_SOC_DAIFMT_NB_IF:
577 /* Invert frame clock */
578 strcr ^= CCSR_SSI_STCR_TFSI;
579 break;
580 case SND_SOC_DAIFMT_IB_IF:
581 /* Invert both clocks */
582 strcr ^= CCSR_SSI_STCR_TSCKP;
583 strcr ^= CCSR_SSI_STCR_TFSI;
584 break;
585 default:
586 return -EINVAL;
587 }
588
589 /* DAI clock master masks */
590 switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
591 case SND_SOC_DAIFMT_CBS_CFS:
592 strcr |= CCSR_SSI_STCR_TFDIR | CCSR_SSI_STCR_TXDIR;
593 scr |= CCSR_SSI_SCR_SYS_CLK_EN;
594 break;
595 case SND_SOC_DAIFMT_CBM_CFM:
596 scr &= ~CCSR_SSI_SCR_SYS_CLK_EN;
597 break;
598 default:
599 return -EINVAL;
600 }
601
602 stcr |= strcr;
603 srcr |= strcr;
604
605 if (ssi_private->cpu_dai_drv.symmetric_rates) {
606 /* Need to clear RXDIR when using SYNC mode */
607 srcr &= ~CCSR_SSI_SRCR_RXDIR;
608 scr |= CCSR_SSI_SCR_SYN;
609 }
610
611 write_ssi(stcr, &ssi->stcr);
612 write_ssi(srcr, &ssi->srcr);
613 write_ssi(scr, &ssi->scr);
614
615 return 0;
616}
617
618/**
619 * fsl_ssi_set_dai_sysclk - configure Digital Audio Interface bit clock
620 *
621 * Note: This function can be only called when using SSI as DAI master
622 *
623 * Quick instruction for parameters:
624 * freq: Output BCLK frequency = samplerate * 32 (fixed) * channels
625 * dir: SND_SOC_CLOCK_OUT -> TxBCLK, SND_SOC_CLOCK_IN -> RxBCLK.
626 */
627static int fsl_ssi_set_dai_sysclk(struct snd_soc_dai *cpu_dai,
628 int clk_id, unsigned int freq, int dir)
629{
630 struct fsl_ssi_private *ssi_private = snd_soc_dai_get_drvdata(cpu_dai);
631 struct ccsr_ssi __iomem *ssi = ssi_private->ssi;
632 int synchronous = ssi_private->cpu_dai_drv.symmetric_rates, ret;
633 u32 pm = 999, div2, psr, stccr, mask, afreq, factor, i;
634 unsigned long flags, clkrate, baudrate, tmprate;
635 u64 sub, savesub = 100000;
636
637 /* Don't apply it to any non-baudclk circumstance */
638 if (IS_ERR(ssi_private->baudclk))
639 return -EINVAL;
640
641 /* It should be already enough to divide clock by setting pm alone */
642 psr = 0;
643 div2 = 0;
644
645 factor = (div2 + 1) * (7 * psr + 1) * 2;
646
647 for (i = 0; i < 255; i++) {
648 /* The bclk rate must be smaller than 1/5 sysclk rate */
649 if (factor * (i + 1) < 5)
650 continue;
651
652 tmprate = freq * factor * (i + 2);
653 clkrate = clk_round_rate(ssi_private->baudclk, tmprate);
654
655 do_div(clkrate, factor);
656 afreq = (u32)clkrate / (i + 1);
657
658 if (freq == afreq)
659 sub = 0;
660 else if (freq / afreq == 1)
661 sub = freq - afreq;
662 else if (afreq / freq == 1)
663 sub = afreq - freq;
664 else
665 continue;
666
667 /* Calculate the fraction */
668 sub *= 100000;
669 do_div(sub, freq);
670
671 if (sub < savesub) {
672 baudrate = tmprate;
673 savesub = sub;
674 pm = i;
675 }
676
677 /* We are lucky */
678 if (savesub == 0)
679 break;
680 }
681
682 /* No proper pm found if it is still remaining the initial value */
683 if (pm == 999) {
684 dev_err(cpu_dai->dev, "failed to handle the required sysclk\n");
685 return -EINVAL;
686 }
687
688 stccr = CCSR_SSI_SxCCR_PM(pm + 1) | (div2 ? CCSR_SSI_SxCCR_DIV2 : 0) |
689 (psr ? CCSR_SSI_SxCCR_PSR : 0);
690 mask = CCSR_SSI_SxCCR_PM_MASK | CCSR_SSI_SxCCR_DIV2 | CCSR_SSI_SxCCR_PSR;
691
692 if (dir == SND_SOC_CLOCK_OUT || synchronous)
693 write_ssi_mask(&ssi->stccr, mask, stccr);
694 else
695 write_ssi_mask(&ssi->srccr, mask, stccr);
696
697 spin_lock_irqsave(&ssi_private->baudclk_lock, flags);
698 if (!ssi_private->baudclk_locked) {
699 ret = clk_set_rate(ssi_private->baudclk, baudrate);
700 if (ret) {
701 spin_unlock_irqrestore(&ssi_private->baudclk_lock, flags);
702 dev_err(cpu_dai->dev, "failed to set baudclk rate\n");
703 return -EINVAL;
704 }
705 ssi_private->baudclk_locked = true;
706 }
707 spin_unlock_irqrestore(&ssi_private->baudclk_lock, flags);
708
709 return 0;
710}
711
712/**
713 * fsl_ssi_set_dai_tdm_slot - set TDM slot number
714 *
715 * Note: This function can be only called when using SSI as DAI master
716 */
717static int fsl_ssi_set_dai_tdm_slot(struct snd_soc_dai *cpu_dai, u32 tx_mask,
718 u32 rx_mask, int slots, int slot_width)
719{
720 struct fsl_ssi_private *ssi_private = snd_soc_dai_get_drvdata(cpu_dai);
721 struct ccsr_ssi __iomem *ssi = ssi_private->ssi;
722 u32 val;
723
724 /* The slot number should be >= 2 if using Network mode or I2S mode */
725 val = read_ssi(&ssi->scr) & (CCSR_SSI_SCR_I2S_MODE_MASK | CCSR_SSI_SCR_NET);
726 if (val && slots < 2) {
727 dev_err(cpu_dai->dev, "slot number should be >= 2 in I2S or NET\n");
728 return -EINVAL;
729 }
730
731 write_ssi_mask(&ssi->stccr, CCSR_SSI_SxCCR_DC_MASK,
732 CCSR_SSI_SxCCR_DC(slots));
733 write_ssi_mask(&ssi->srccr, CCSR_SSI_SxCCR_DC_MASK,
734 CCSR_SSI_SxCCR_DC(slots));
735
736 /* The register SxMSKs needs SSI to provide essential clock due to
737 * hardware design. So we here temporarily enable SSI to set them.
738 */
739 val = read_ssi(&ssi->scr) & CCSR_SSI_SCR_SSIEN;
740 write_ssi_mask(&ssi->scr, 0, CCSR_SSI_SCR_SSIEN);
741
742 write_ssi(tx_mask, &ssi->stmsk);
743 write_ssi(rx_mask, &ssi->srmsk);
744
745 write_ssi_mask(&ssi->scr, CCSR_SSI_SCR_SSIEN, val);
746
533 return 0; 747 return 0;
534} 748}
535 749
@@ -549,6 +763,7 @@ static int fsl_ssi_trigger(struct snd_pcm_substream *substream, int cmd,
549 struct fsl_ssi_private *ssi_private = snd_soc_dai_get_drvdata(rtd->cpu_dai); 763 struct fsl_ssi_private *ssi_private = snd_soc_dai_get_drvdata(rtd->cpu_dai);
550 struct ccsr_ssi __iomem *ssi = ssi_private->ssi; 764 struct ccsr_ssi __iomem *ssi = ssi_private->ssi;
551 unsigned int sier_bits; 765 unsigned int sier_bits;
766 unsigned long flags;
552 767
553 /* 768 /*
554 * Enable only the interrupts and DMA requests 769 * Enable only the interrupts and DMA requests
@@ -589,8 +804,12 @@ static int fsl_ssi_trigger(struct snd_pcm_substream *substream, int cmd,
589 write_ssi_mask(&ssi->scr, CCSR_SSI_SCR_RE, 0); 804 write_ssi_mask(&ssi->scr, CCSR_SSI_SCR_RE, 0);
590 805
591 if (!ssi_private->imx_ac97 && (read_ssi(&ssi->scr) & 806 if (!ssi_private->imx_ac97 && (read_ssi(&ssi->scr) &
592 (CCSR_SSI_SCR_TE | CCSR_SSI_SCR_RE)) == 0) 807 (CCSR_SSI_SCR_TE | CCSR_SSI_SCR_RE)) == 0) {
593 write_ssi_mask(&ssi->scr, CCSR_SSI_SCR_SSIEN, 0); 808 write_ssi_mask(&ssi->scr, CCSR_SSI_SCR_SSIEN, 0);
809 spin_lock_irqsave(&ssi_private->baudclk_lock, flags);
810 ssi_private->baudclk_locked = false;
811 spin_unlock_irqrestore(&ssi_private->baudclk_lock, flags);
812 }
594 break; 813 break;
595 814
596 default: 815 default:
@@ -602,23 +821,6 @@ static int fsl_ssi_trigger(struct snd_pcm_substream *substream, int cmd,
602 return 0; 821 return 0;
603} 822}
604 823
605/**
606 * fsl_ssi_shutdown: shutdown the SSI
607 *
608 * Shutdown the SSI if there are no other substreams open.
609 */
610static void fsl_ssi_shutdown(struct snd_pcm_substream *substream,
611 struct snd_soc_dai *dai)
612{
613 struct snd_soc_pcm_runtime *rtd = substream->private_data;
614 struct fsl_ssi_private *ssi_private = snd_soc_dai_get_drvdata(rtd->cpu_dai);
615
616 if (ssi_private->first_stream == substream)
617 ssi_private->first_stream = ssi_private->second_stream;
618
619 ssi_private->second_stream = NULL;
620}
621
622static int fsl_ssi_dai_probe(struct snd_soc_dai *dai) 824static int fsl_ssi_dai_probe(struct snd_soc_dai *dai)
623{ 825{
624 struct fsl_ssi_private *ssi_private = snd_soc_dai_get_drvdata(dai); 826 struct fsl_ssi_private *ssi_private = snd_soc_dai_get_drvdata(dai);
@@ -634,7 +836,9 @@ static int fsl_ssi_dai_probe(struct snd_soc_dai *dai)
634static const struct snd_soc_dai_ops fsl_ssi_dai_ops = { 836static const struct snd_soc_dai_ops fsl_ssi_dai_ops = {
635 .startup = fsl_ssi_startup, 837 .startup = fsl_ssi_startup,
636 .hw_params = fsl_ssi_hw_params, 838 .hw_params = fsl_ssi_hw_params,
637 .shutdown = fsl_ssi_shutdown, 839 .set_fmt = fsl_ssi_set_dai_fmt,
840 .set_sysclk = fsl_ssi_set_dai_sysclk,
841 .set_tdm_slot = fsl_ssi_set_dai_tdm_slot,
638 .trigger = fsl_ssi_trigger, 842 .trigger = fsl_ssi_trigger,
639}; 843};
640 844
@@ -642,14 +846,13 @@ static const struct snd_soc_dai_ops fsl_ssi_dai_ops = {
642static struct snd_soc_dai_driver fsl_ssi_dai_template = { 846static struct snd_soc_dai_driver fsl_ssi_dai_template = {
643 .probe = fsl_ssi_dai_probe, 847 .probe = fsl_ssi_dai_probe,
644 .playback = { 848 .playback = {
645 /* The SSI does not support monaural audio. */ 849 .channels_min = 1,
646 .channels_min = 2,
647 .channels_max = 2, 850 .channels_max = 2,
648 .rates = FSLSSI_I2S_RATES, 851 .rates = FSLSSI_I2S_RATES,
649 .formats = FSLSSI_I2S_FORMATS, 852 .formats = FSLSSI_I2S_FORMATS,
650 }, 853 },
651 .capture = { 854 .capture = {
652 .channels_min = 2, 855 .channels_min = 1,
653 .channels_max = 2, 856 .channels_max = 2,
654 .rates = FSLSSI_I2S_RATES, 857 .rates = FSLSSI_I2S_RATES,
655 .formats = FSLSSI_I2S_FORMATS, 858 .formats = FSLSSI_I2S_FORMATS,
@@ -710,7 +913,6 @@ static int fsl_ssi_ac97_trigger(struct snd_pcm_substream *substream, int cmd,
710 913
711static const struct snd_soc_dai_ops fsl_ssi_ac97_dai_ops = { 914static const struct snd_soc_dai_ops fsl_ssi_ac97_dai_ops = {
712 .startup = fsl_ssi_startup, 915 .startup = fsl_ssi_startup,
713 .shutdown = fsl_ssi_shutdown,
714 .trigger = fsl_ssi_ac97_trigger, 916 .trigger = fsl_ssi_ac97_trigger,
715}; 917};
716 918
@@ -935,8 +1137,11 @@ static int fsl_ssi_probe(struct platform_device *pdev)
935 } 1137 }
936 1138
937 /* Are the RX and the TX clocks locked? */ 1139 /* Are the RX and the TX clocks locked? */
938 if (!of_find_property(np, "fsl,ssi-asynchronous", NULL)) 1140 if (!of_find_property(np, "fsl,ssi-asynchronous", NULL)) {
939 ssi_private->cpu_dai_drv.symmetric_rates = 1; 1141 ssi_private->cpu_dai_drv.symmetric_rates = 1;
1142 ssi_private->cpu_dai_drv.symmetric_channels = 1;
1143 ssi_private->cpu_dai_drv.symmetric_samplebits = 1;
1144 }
940 1145
941 /* Determine the FIFO depth. */ 1146 /* Determine the FIFO depth. */
942 iprop = of_get_property(np, "fsl,fifo-depth", NULL); 1147 iprop = of_get_property(np, "fsl,fifo-depth", NULL);
@@ -946,6 +1151,9 @@ static int fsl_ssi_probe(struct platform_device *pdev)
946 /* Older 8610 DTs didn't have the fifo-depth property */ 1151 /* Older 8610 DTs didn't have the fifo-depth property */
947 ssi_private->fifo_depth = 8; 1152 ssi_private->fifo_depth = 8;
948 1153
1154 ssi_private->baudclk_locked = false;
1155 spin_lock_init(&ssi_private->baudclk_lock);
1156
949 if (of_device_is_compatible(pdev->dev.of_node, "fsl,imx21-ssi")) { 1157 if (of_device_is_compatible(pdev->dev.of_node, "fsl,imx21-ssi")) {
950 u32 dma_events[2]; 1158 u32 dma_events[2];
951 ssi_private->ssi_on_imx = true; 1159 ssi_private->ssi_on_imx = true;
@@ -963,6 +1171,15 @@ static int fsl_ssi_probe(struct platform_device *pdev)
963 goto error_irqmap; 1171 goto error_irqmap;
964 } 1172 }
965 1173
1174 /* For those SLAVE implementations, we ingore non-baudclk cases
1175 * and, instead, abandon MASTER mode that needs baud clock.
1176 */
1177 ssi_private->baudclk = devm_clk_get(&pdev->dev, "baud");
1178 if (IS_ERR(ssi_private->baudclk))
1179 dev_warn(&pdev->dev, "could not get baud clock: %d\n", ret);
1180 else
1181 clk_prepare_enable(ssi_private->baudclk);
1182
966 /* 1183 /*
967 * We have burstsize be "fifo_depth - 2" to match the SSI 1184 * We have burstsize be "fifo_depth - 2" to match the SSI
968 * watermark setting in fsl_ssi_startup(). 1185 * watermark setting in fsl_ssi_startup().
@@ -1102,16 +1319,17 @@ done:
1102 return 0; 1319 return 0;
1103 1320
1104error_dai: 1321error_dai:
1105 if (ssi_private->ssi_on_imx)
1106 imx_pcm_dma_exit(pdev);
1107 snd_soc_unregister_component(&pdev->dev); 1322 snd_soc_unregister_component(&pdev->dev);
1108 1323
1109error_dev: 1324error_dev:
1110 device_remove_file(&pdev->dev, dev_attr); 1325 device_remove_file(&pdev->dev, dev_attr);
1111 1326
1112error_clk: 1327error_clk:
1113 if (ssi_private->ssi_on_imx) 1328 if (ssi_private->ssi_on_imx) {
1329 if (!IS_ERR(ssi_private->baudclk))
1330 clk_disable_unprepare(ssi_private->baudclk);
1114 clk_disable_unprepare(ssi_private->clk); 1331 clk_disable_unprepare(ssi_private->clk);
1332 }
1115 1333
1116error_irqmap: 1334error_irqmap:
1117 irq_dispose_mapping(ssi_private->irq); 1335 irq_dispose_mapping(ssi_private->irq);
@@ -1125,12 +1343,13 @@ static int fsl_ssi_remove(struct platform_device *pdev)
1125 1343
1126 if (!ssi_private->new_binding) 1344 if (!ssi_private->new_binding)
1127 platform_device_unregister(ssi_private->pdev); 1345 platform_device_unregister(ssi_private->pdev);
1128 if (ssi_private->ssi_on_imx)
1129 imx_pcm_dma_exit(pdev);
1130 snd_soc_unregister_component(&pdev->dev); 1346 snd_soc_unregister_component(&pdev->dev);
1131 device_remove_file(&pdev->dev, &ssi_private->dev_attr); 1347 device_remove_file(&pdev->dev, &ssi_private->dev_attr);
1132 if (ssi_private->ssi_on_imx) 1348 if (ssi_private->ssi_on_imx) {
1349 if (!IS_ERR(ssi_private->baudclk))
1350 clk_disable_unprepare(ssi_private->baudclk);
1133 clk_disable_unprepare(ssi_private->clk); 1351 clk_disable_unprepare(ssi_private->clk);
1352 }
1134 irq_dispose_mapping(ssi_private->irq); 1353 irq_dispose_mapping(ssi_private->irq);
1135 1354
1136 return 0; 1355 return 0;
diff --git a/sound/soc/fsl/fsl_ssi.h b/sound/soc/fsl/fsl_ssi.h
index e6b9a69e2a68..e6b63240a3d7 100644
--- a/sound/soc/fsl/fsl_ssi.h
+++ b/sound/soc/fsl/fsl_ssi.h
@@ -125,7 +125,9 @@ struct ccsr_ssi {
125#define CCSR_SSI_SRCR_REFS 0x00000001 125#define CCSR_SSI_SRCR_REFS 0x00000001
126 126
127/* STCCR and SRCCR */ 127/* STCCR and SRCCR */
128#define CCSR_SSI_SxCCR_DIV2_SHIFT 18
128#define CCSR_SSI_SxCCR_DIV2 0x00040000 129#define CCSR_SSI_SxCCR_DIV2 0x00040000
130#define CCSR_SSI_SxCCR_PSR_SHIFT 17
129#define CCSR_SSI_SxCCR_PSR 0x00020000 131#define CCSR_SSI_SxCCR_PSR 0x00020000
130#define CCSR_SSI_SxCCR_WL_SHIFT 13 132#define CCSR_SSI_SxCCR_WL_SHIFT 13
131#define CCSR_SSI_SxCCR_WL_MASK 0x0001E000 133#define CCSR_SSI_SxCCR_WL_MASK 0x0001E000
diff --git a/sound/soc/fsl/imx-pcm-dma.c b/sound/soc/fsl/imx-pcm-dma.c
index aee23077080a..c5e47f866b4b 100644
--- a/sound/soc/fsl/imx-pcm-dma.c
+++ b/sound/soc/fsl/imx-pcm-dma.c
@@ -61,16 +61,11 @@ static const struct snd_dmaengine_pcm_config imx_dmaengine_pcm_config = {
61 61
62int imx_pcm_dma_init(struct platform_device *pdev) 62int imx_pcm_dma_init(struct platform_device *pdev)
63{ 63{
64 return snd_dmaengine_pcm_register(&pdev->dev, &imx_dmaengine_pcm_config, 64 return devm_snd_dmaengine_pcm_register(&pdev->dev,
65 &imx_dmaengine_pcm_config,
65 SND_DMAENGINE_PCM_FLAG_NO_RESIDUE | 66 SND_DMAENGINE_PCM_FLAG_NO_RESIDUE |
66 SND_DMAENGINE_PCM_FLAG_COMPAT); 67 SND_DMAENGINE_PCM_FLAG_COMPAT);
67} 68}
68EXPORT_SYMBOL_GPL(imx_pcm_dma_init); 69EXPORT_SYMBOL_GPL(imx_pcm_dma_init);
69 70
70void imx_pcm_dma_exit(struct platform_device *pdev)
71{
72 snd_dmaengine_pcm_unregister(&pdev->dev);
73}
74EXPORT_SYMBOL_GPL(imx_pcm_dma_exit);
75
76MODULE_LICENSE("GPL"); 71MODULE_LICENSE("GPL");
diff --git a/sound/soc/fsl/imx-pcm.h b/sound/soc/fsl/imx-pcm.h
index 5d5b73303e11..c79cb27473be 100644
--- a/sound/soc/fsl/imx-pcm.h
+++ b/sound/soc/fsl/imx-pcm.h
@@ -40,16 +40,11 @@ struct imx_pcm_fiq_params {
40 40
41#if IS_ENABLED(CONFIG_SND_SOC_IMX_PCM_DMA) 41#if IS_ENABLED(CONFIG_SND_SOC_IMX_PCM_DMA)
42int imx_pcm_dma_init(struct platform_device *pdev); 42int imx_pcm_dma_init(struct platform_device *pdev);
43void imx_pcm_dma_exit(struct platform_device *pdev);
44#else 43#else
45static inline int imx_pcm_dma_init(struct platform_device *pdev) 44static inline int imx_pcm_dma_init(struct platform_device *pdev)
46{ 45{
47 return -ENODEV; 46 return -ENODEV;
48} 47}
49
50static inline void imx_pcm_dma_exit(struct platform_device *pdev)
51{
52}
53#endif 48#endif
54 49
55#if IS_ENABLED(CONFIG_SND_SOC_IMX_PCM_FIQ) 50#if IS_ENABLED(CONFIG_SND_SOC_IMX_PCM_FIQ)
diff --git a/sound/soc/fsl/imx-spdif.c b/sound/soc/fsl/imx-spdif.c
index 8499d5292f08..e1dc40143600 100644
--- a/sound/soc/fsl/imx-spdif.c
+++ b/sound/soc/fsl/imx-spdif.c
@@ -14,17 +14,15 @@
14#include <sound/soc.h> 14#include <sound/soc.h>
15 15
16struct imx_spdif_data { 16struct imx_spdif_data {
17 struct snd_soc_dai_link dai[2]; 17 struct snd_soc_dai_link dai;
18 struct snd_soc_card card; 18 struct snd_soc_card card;
19 struct platform_device *txdev;
20 struct platform_device *rxdev;
21}; 19};
22 20
23static int imx_spdif_audio_probe(struct platform_device *pdev) 21static int imx_spdif_audio_probe(struct platform_device *pdev)
24{ 22{
25 struct device_node *spdif_np, *np = pdev->dev.of_node; 23 struct device_node *spdif_np, *np = pdev->dev.of_node;
26 struct imx_spdif_data *data; 24 struct imx_spdif_data *data;
27 int ret = 0, num_links = 0; 25 int ret = 0;
28 26
29 spdif_np = of_parse_phandle(np, "spdif-controller", 0); 27 spdif_np = of_parse_phandle(np, "spdif-controller", 0);
30 if (!spdif_np) { 28 if (!spdif_np) {
@@ -35,74 +33,46 @@ static int imx_spdif_audio_probe(struct platform_device *pdev)
35 33
36 data = devm_kzalloc(&pdev->dev, sizeof(*data), GFP_KERNEL); 34 data = devm_kzalloc(&pdev->dev, sizeof(*data), GFP_KERNEL);
37 if (!data) { 35 if (!data) {
38 dev_err(&pdev->dev, "failed to allocate memory\n");
39 ret = -ENOMEM; 36 ret = -ENOMEM;
40 goto end; 37 goto end;
41 } 38 }
42 39
43 if (of_property_read_bool(np, "spdif-out")) { 40 data->dai.name = "S/PDIF PCM";
44 data->dai[num_links].name = "S/PDIF TX"; 41 data->dai.stream_name = "S/PDIF PCM";
45 data->dai[num_links].stream_name = "S/PDIF PCM Playback"; 42 data->dai.codec_dai_name = "snd-soc-dummy-dai";
46 data->dai[num_links].codec_dai_name = "dit-hifi"; 43 data->dai.codec_name = "snd-soc-dummy";
47 data->dai[num_links].codec_name = "spdif-dit"; 44 data->dai.cpu_of_node = spdif_np;
48 data->dai[num_links].cpu_of_node = spdif_np; 45 data->dai.platform_of_node = spdif_np;
49 data->dai[num_links].platform_of_node = spdif_np; 46 data->dai.playback_only = true;
50 num_links++; 47 data->dai.capture_only = true;
51
52 data->txdev = platform_device_register_simple("spdif-dit", -1, NULL, 0);
53 if (IS_ERR(data->txdev)) {
54 ret = PTR_ERR(data->txdev);
55 dev_err(&pdev->dev, "register dit failed: %d\n", ret);
56 goto end;
57 }
58 }
59 48
60 if (of_property_read_bool(np, "spdif-in")) { 49 if (of_property_read_bool(np, "spdif-out"))
61 data->dai[num_links].name = "S/PDIF RX"; 50 data->dai.capture_only = false;
62 data->dai[num_links].stream_name = "S/PDIF PCM Capture"; 51
63 data->dai[num_links].codec_dai_name = "dir-hifi"; 52 if (of_property_read_bool(np, "spdif-in"))
64 data->dai[num_links].codec_name = "spdif-dir"; 53 data->dai.playback_only = false;
65 data->dai[num_links].cpu_of_node = spdif_np;
66 data->dai[num_links].platform_of_node = spdif_np;
67 num_links++;
68
69 data->rxdev = platform_device_register_simple("spdif-dir", -1, NULL, 0);
70 if (IS_ERR(data->rxdev)) {
71 ret = PTR_ERR(data->rxdev);
72 dev_err(&pdev->dev, "register dir failed: %d\n", ret);
73 goto error_dit;
74 }
75 }
76 54
77 if (!num_links) { 55 if (data->dai.playback_only && data->dai.capture_only) {
78 dev_err(&pdev->dev, "no enabled S/PDIF DAI link\n"); 56 dev_err(&pdev->dev, "no enabled S/PDIF DAI link\n");
79 goto error_dir; 57 goto end;
80 } 58 }
81 59
82 data->card.dev = &pdev->dev; 60 data->card.dev = &pdev->dev;
83 data->card.num_links = num_links; 61 data->card.dai_link = &data->dai;
84 data->card.dai_link = data->dai; 62 data->card.num_links = 1;
85 63
86 ret = snd_soc_of_parse_card_name(&data->card, "model"); 64 ret = snd_soc_of_parse_card_name(&data->card, "model");
87 if (ret) 65 if (ret)
88 goto error_dir; 66 goto end;
89 67
90 ret = devm_snd_soc_register_card(&pdev->dev, &data->card); 68 ret = devm_snd_soc_register_card(&pdev->dev, &data->card);
91 if (ret) { 69 if (ret) {
92 dev_err(&pdev->dev, "snd_soc_register_card failed: %d\n", ret); 70 dev_err(&pdev->dev, "snd_soc_register_card failed: %d\n", ret);
93 goto error_dir; 71 goto end;
94 } 72 }
95 73
96 platform_set_drvdata(pdev, data); 74 platform_set_drvdata(pdev, data);
97 75
98 goto end;
99
100error_dir:
101 if (data->rxdev)
102 platform_device_unregister(data->rxdev);
103error_dit:
104 if (data->txdev)
105 platform_device_unregister(data->txdev);
106end: 76end:
107 if (spdif_np) 77 if (spdif_np)
108 of_node_put(spdif_np); 78 of_node_put(spdif_np);
@@ -110,18 +80,6 @@ end:
110 return ret; 80 return ret;
111} 81}
112 82
113static int imx_spdif_audio_remove(struct platform_device *pdev)
114{
115 struct imx_spdif_data *data = platform_get_drvdata(pdev);
116
117 if (data->rxdev)
118 platform_device_unregister(data->rxdev);
119 if (data->txdev)
120 platform_device_unregister(data->txdev);
121
122 return 0;
123}
124
125static const struct of_device_id imx_spdif_dt_ids[] = { 83static const struct of_device_id imx_spdif_dt_ids[] = {
126 { .compatible = "fsl,imx-audio-spdif", }, 84 { .compatible = "fsl,imx-audio-spdif", },
127 { /* sentinel */ } 85 { /* sentinel */ }
@@ -135,7 +93,6 @@ static struct platform_driver imx_spdif_driver = {
135 .of_match_table = imx_spdif_dt_ids, 93 .of_match_table = imx_spdif_dt_ids,
136 }, 94 },
137 .probe = imx_spdif_audio_probe, 95 .probe = imx_spdif_audio_probe,
138 .remove = imx_spdif_audio_remove,
139}; 96};
140 97
141module_platform_driver(imx_spdif_driver); 98module_platform_driver(imx_spdif_driver);
diff --git a/sound/soc/fsl/imx-ssi.c b/sound/soc/fsl/imx-ssi.c
index f5f248c91c16..df552fa1aa65 100644
--- a/sound/soc/fsl/imx-ssi.c
+++ b/sound/soc/fsl/imx-ssi.c
@@ -304,8 +304,7 @@ static int imx_ssi_trigger(struct snd_pcm_substream *substream, int cmd,
304 scr |= SSI_SCR_RE; 304 scr |= SSI_SCR_RE;
305 sier |= sier_bits; 305 sier |= sier_bits;
306 306
307 if (++ssi->enabled == 1) 307 scr |= SSI_SCR_SSIEN;
308 scr |= SSI_SCR_SSIEN;
309 308
310 break; 309 break;
311 310
@@ -318,7 +317,7 @@ static int imx_ssi_trigger(struct snd_pcm_substream *substream, int cmd,
318 scr &= ~SSI_SCR_RE; 317 scr &= ~SSI_SCR_RE;
319 sier &= ~sier_bits; 318 sier &= ~sier_bits;
320 319
321 if (--ssi->enabled == 0) 320 if (!(scr & (SSI_SCR_TE | SSI_SCR_RE)))
322 scr &= ~SSI_SCR_SSIEN; 321 scr &= ~SSI_SCR_SSIEN;
323 322
324 break; 323 break;
@@ -536,7 +535,9 @@ static int imx_ssi_probe(struct platform_device *pdev)
536 ret); 535 ret);
537 goto failed_clk; 536 goto failed_clk;
538 } 537 }
539 clk_prepare_enable(ssi->clk); 538 ret = clk_prepare_enable(ssi->clk);
539 if (ret)
540 goto failed_clk;
540 541
541 res = platform_get_resource(pdev, IORESOURCE_MEM, 0); 542 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
542 ssi->base = devm_ioremap_resource(&pdev->dev, res); 543 ssi->base = devm_ioremap_resource(&pdev->dev, res);
@@ -624,9 +625,6 @@ static int imx_ssi_remove(struct platform_device *pdev)
624{ 625{
625 struct imx_ssi *ssi = platform_get_drvdata(pdev); 626 struct imx_ssi *ssi = platform_get_drvdata(pdev);
626 627
627 if (!ssi->dma_init)
628 imx_pcm_dma_exit(pdev);
629
630 if (!ssi->fiq_init) 628 if (!ssi->fiq_init)
631 imx_pcm_fiq_exit(pdev); 629 imx_pcm_fiq_exit(pdev);
632 630
diff --git a/sound/soc/fsl/imx-ssi.h b/sound/soc/fsl/imx-ssi.h
index 560c40fc9ebb..be6562365b6a 100644
--- a/sound/soc/fsl/imx-ssi.h
+++ b/sound/soc/fsl/imx-ssi.h
@@ -213,7 +213,6 @@ struct imx_ssi {
213 213
214 int fiq_init; 214 int fiq_init;
215 int dma_init; 215 int dma_init;
216 int enabled;
217}; 216};
218 217
219#endif /* _IMX_SSI_H */ 218#endif /* _IMX_SSI_H */
diff --git a/sound/soc/fsl/imx-wm8962.c b/sound/soc/fsl/imx-wm8962.c
index 61e48852b9e8..3fd76bc391de 100644
--- a/sound/soc/fsl/imx-wm8962.c
+++ b/sound/soc/fsl/imx-wm8962.c
@@ -130,8 +130,6 @@ static int imx_wm8962_set_bias_level(struct snd_soc_card *card,
130 break; 130 break;
131 } 131 }
132 132
133 dapm->bias_level = level;
134
135 return 0; 133 return 0;
136} 134}
137 135
diff --git a/sound/soc/fsl/pcm030-audio-fabric.c b/sound/soc/fsl/pcm030-audio-fabric.c
index eb4373840bb6..3665f612819d 100644
--- a/sound/soc/fsl/pcm030-audio-fabric.c
+++ b/sound/soc/fsl/pcm030-audio-fabric.c
@@ -69,7 +69,6 @@ static int pcm030_fabric_probe(struct platform_device *op)
69 return -ENOMEM; 69 return -ENOMEM;
70 70
71 card->dev = &op->dev; 71 card->dev = &op->dev;
72 platform_set_drvdata(op, pdata);
73 72
74 pdata->card = card; 73 pdata->card = card;
75 74
@@ -98,6 +97,8 @@ static int pcm030_fabric_probe(struct platform_device *op)
98 if (ret) 97 if (ret)
99 dev_err(&op->dev, "snd_soc_register_card() failed: %d\n", ret); 98 dev_err(&op->dev, "snd_soc_register_card() failed: %d\n", ret);
100 99
100 platform_set_drvdata(op, pdata);
101
101 return ret; 102 return ret;
102} 103}
103 104