aboutsummaryrefslogtreecommitdiffstats
path: root/sound/soc/mxs
diff options
context:
space:
mode:
Diffstat (limited to 'sound/soc/mxs')
-rw-r--r--sound/soc/mxs/Kconfig2
-rw-r--r--sound/soc/mxs/mxs-pcm.c176
-rw-r--r--sound/soc/mxs/mxs-pcm.h4
-rw-r--r--sound/soc/mxs/mxs-saif.c20
4 files changed, 32 insertions, 170 deletions
diff --git a/sound/soc/mxs/Kconfig b/sound/soc/mxs/Kconfig
index b6fa77678d97..78d321cbe8b4 100644
--- a/sound/soc/mxs/Kconfig
+++ b/sound/soc/mxs/Kconfig
@@ -1,7 +1,7 @@
1menuconfig SND_MXS_SOC 1menuconfig SND_MXS_SOC
2 tristate "SoC Audio for Freescale MXS CPUs" 2 tristate "SoC Audio for Freescale MXS CPUs"
3 depends on ARCH_MXS 3 depends on ARCH_MXS
4 select SND_SOC_DMAENGINE_PCM 4 select SND_SOC_GENERIC_DMAENGINE_PCM
5 help 5 help
6 Say Y or M if you want to add support for codecs attached to 6 Say Y or M if you want to add support for codecs attached to
7 the MXS SAIF interface. 7 the MXS SAIF interface.
diff --git a/sound/soc/mxs/mxs-pcm.c b/sound/soc/mxs/mxs-pcm.c
index 564b5b60319d..b41fffc056fb 100644
--- a/sound/soc/mxs/mxs-pcm.c
+++ b/sound/soc/mxs/mxs-pcm.c
@@ -18,38 +18,24 @@
18 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 18 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
19 */ 19 */
20 20
21#include <linux/clk.h>
22#include <linux/delay.h>
23#include <linux/device.h> 21#include <linux/device.h>
24#include <linux/dma-mapping.h>
25#include <linux/init.h> 22#include <linux/init.h>
26#include <linux/interrupt.h>
27#include <linux/module.h> 23#include <linux/module.h>
28#include <linux/platform_device.h>
29#include <linux/slab.h>
30#include <linux/dmaengine.h>
31#include <linux/fsl/mxs-dma.h>
32 24
33#include <sound/core.h> 25#include <sound/core.h>
34#include <sound/initval.h>
35#include <sound/pcm.h> 26#include <sound/pcm.h>
36#include <sound/pcm_params.h>
37#include <sound/soc.h> 27#include <sound/soc.h>
38#include <sound/dmaengine_pcm.h> 28#include <sound/dmaengine_pcm.h>
39 29
40#include "mxs-pcm.h" 30#include "mxs-pcm.h"
41 31
42struct mxs_pcm_dma_data { 32static const struct snd_pcm_hardware snd_mxs_hardware = {
43 struct mxs_dma_data dma_data;
44 struct mxs_pcm_dma_params *dma_params;
45};
46
47static struct snd_pcm_hardware snd_mxs_hardware = {
48 .info = SNDRV_PCM_INFO_MMAP | 33 .info = SNDRV_PCM_INFO_MMAP |
49 SNDRV_PCM_INFO_MMAP_VALID | 34 SNDRV_PCM_INFO_MMAP_VALID |
50 SNDRV_PCM_INFO_PAUSE | 35 SNDRV_PCM_INFO_PAUSE |
51 SNDRV_PCM_INFO_RESUME | 36 SNDRV_PCM_INFO_RESUME |
52 SNDRV_PCM_INFO_INTERLEAVED, 37 SNDRV_PCM_INFO_INTERLEAVED |
38 SNDRV_PCM_INFO_HALF_DUPLEX,
53 .formats = SNDRV_PCM_FMTBIT_S16_LE | 39 .formats = SNDRV_PCM_FMTBIT_S16_LE |
54 SNDRV_PCM_FMTBIT_S20_3LE | 40 SNDRV_PCM_FMTBIT_S20_3LE |
55 SNDRV_PCM_FMTBIT_S24_LE, 41 SNDRV_PCM_FMTBIT_S24_LE,
@@ -61,13 +47,11 @@ static struct snd_pcm_hardware snd_mxs_hardware = {
61 .periods_max = 52, 47 .periods_max = 52,
62 .buffer_bytes_max = 64 * 1024, 48 .buffer_bytes_max = 64 * 1024,
63 .fifo_size = 32, 49 .fifo_size = 32,
64
65}; 50};
66 51
67static bool filter(struct dma_chan *chan, void *param) 52static bool filter(struct dma_chan *chan, void *param)
68{ 53{
69 struct mxs_pcm_dma_data *pcm_dma_data = param; 54 struct mxs_pcm_dma_params *dma_params = param;
70 struct mxs_pcm_dma_params *dma_params = pcm_dma_data->dma_params;
71 55
72 if (!mxs_dma_is_apbx(chan)) 56 if (!mxs_dma_is_apbx(chan))
73 return false; 57 return false;
@@ -75,160 +59,30 @@ static bool filter(struct dma_chan *chan, void *param)
75 if (chan->chan_id != dma_params->chan_num) 59 if (chan->chan_id != dma_params->chan_num)
76 return false; 60 return false;
77 61
78 chan->private = &pcm_dma_data->dma_data; 62 chan->private = &dma_params->dma_data;
79 63
80 return true; 64 return true;
81} 65}
82 66
83static int snd_mxs_pcm_hw_params(struct snd_pcm_substream *substream, 67static const struct snd_dmaengine_pcm_config mxs_dmaengine_pcm_config = {
84 struct snd_pcm_hw_params *params) 68 .pcm_hardware = &snd_mxs_hardware,
85{ 69 .compat_filter_fn = filter,
86 snd_pcm_set_runtime_buffer(substream, &substream->dma_buffer); 70 .prealloc_buffer_size = 64 * 1024,
87
88 return 0;
89}
90
91static int snd_mxs_open(struct snd_pcm_substream *substream)
92{
93 struct snd_soc_pcm_runtime *rtd = substream->private_data;
94 struct mxs_pcm_dma_data *pcm_dma_data;
95 int ret;
96
97 pcm_dma_data = kzalloc(sizeof(*pcm_dma_data), GFP_KERNEL);
98 if (pcm_dma_data == NULL)
99 return -ENOMEM;
100
101 pcm_dma_data->dma_params = snd_soc_dai_get_dma_data(rtd->cpu_dai, substream);
102 pcm_dma_data->dma_data.chan_irq = pcm_dma_data->dma_params->chan_irq;
103
104 ret = snd_dmaengine_pcm_open(substream, filter, pcm_dma_data);
105 if (ret) {
106 kfree(pcm_dma_data);
107 return ret;
108 }
109
110 snd_soc_set_runtime_hwparams(substream, &snd_mxs_hardware);
111
112 snd_dmaengine_pcm_set_data(substream, pcm_dma_data);
113
114 return 0;
115}
116
117static int snd_mxs_close(struct snd_pcm_substream *substream)
118{
119 struct mxs_pcm_dma_data *pcm_dma_data = snd_dmaengine_pcm_get_data(substream);
120
121 snd_dmaengine_pcm_close(substream);
122 kfree(pcm_dma_data);
123
124 return 0;
125}
126
127static int snd_mxs_pcm_mmap(struct snd_pcm_substream *substream,
128 struct vm_area_struct *vma)
129{
130 struct snd_pcm_runtime *runtime = substream->runtime;
131
132 return dma_mmap_writecombine(substream->pcm->card->dev, vma,
133 runtime->dma_area,
134 runtime->dma_addr,
135 runtime->dma_bytes);
136}
137
138static struct snd_pcm_ops mxs_pcm_ops = {
139 .open = snd_mxs_open,
140 .close = snd_mxs_close,
141 .ioctl = snd_pcm_lib_ioctl,
142 .hw_params = snd_mxs_pcm_hw_params,
143 .trigger = snd_dmaengine_pcm_trigger,
144 .pointer = snd_dmaengine_pcm_pointer_no_residue,
145 .mmap = snd_mxs_pcm_mmap,
146};
147
148static int mxs_pcm_preallocate_dma_buffer(struct snd_pcm *pcm, int stream)
149{
150 struct snd_pcm_substream *substream = pcm->streams[stream].substream;
151 struct snd_dma_buffer *buf = &substream->dma_buffer;
152 size_t size = snd_mxs_hardware.buffer_bytes_max;
153
154 buf->dev.type = SNDRV_DMA_TYPE_DEV;
155 buf->dev.dev = pcm->card->dev;
156 buf->private_data = NULL;
157 buf->area = dma_alloc_writecombine(pcm->card->dev, size,
158 &buf->addr, GFP_KERNEL);
159 if (!buf->area)
160 return -ENOMEM;
161 buf->bytes = size;
162
163 return 0;
164}
165
166static u64 mxs_pcm_dmamask = DMA_BIT_MASK(32);
167static int mxs_pcm_new(struct snd_soc_pcm_runtime *rtd)
168{
169 struct snd_card *card = rtd->card->snd_card;
170 struct snd_pcm *pcm = rtd->pcm;
171 int ret = 0;
172
173 if (!card->dev->dma_mask)
174 card->dev->dma_mask = &mxs_pcm_dmamask;
175 if (!card->dev->coherent_dma_mask)
176 card->dev->coherent_dma_mask = DMA_BIT_MASK(32);
177
178 if (pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream) {
179 ret = mxs_pcm_preallocate_dma_buffer(pcm,
180 SNDRV_PCM_STREAM_PLAYBACK);
181 if (ret)
182 goto out;
183 }
184
185 if (pcm->streams[SNDRV_PCM_STREAM_CAPTURE].substream) {
186 ret = mxs_pcm_preallocate_dma_buffer(pcm,
187 SNDRV_PCM_STREAM_CAPTURE);
188 if (ret)
189 goto out;
190 }
191
192out:
193 return ret;
194}
195
196static void mxs_pcm_free(struct snd_pcm *pcm)
197{
198 struct snd_pcm_substream *substream;
199 struct snd_dma_buffer *buf;
200 int stream;
201
202 for (stream = 0; stream < 2; stream++) {
203 substream = pcm->streams[stream].substream;
204 if (!substream)
205 continue;
206
207 buf = &substream->dma_buffer;
208 if (!buf->area)
209 continue;
210
211 dma_free_writecombine(pcm->card->dev, buf->bytes,
212 buf->area, buf->addr);
213 buf->area = NULL;
214 }
215}
216
217static struct snd_soc_platform_driver mxs_soc_platform = {
218 .ops = &mxs_pcm_ops,
219 .pcm_new = mxs_pcm_new,
220 .pcm_free = mxs_pcm_free,
221}; 71};
222 72
223int mxs_pcm_platform_register(struct device *dev) 73int mxs_pcm_platform_register(struct device *dev)
224{ 74{
225 return snd_soc_register_platform(dev, &mxs_soc_platform); 75 return snd_dmaengine_pcm_register(dev, &mxs_dmaengine_pcm_config,
76 SND_DMAENGINE_PCM_FLAG_NO_RESIDUE |
77 SND_DMAENGINE_PCM_FLAG_NO_DT |
78 SND_DMAENGINE_PCM_FLAG_COMPAT |
79 SND_DMAENGINE_PCM_FLAG_HALF_DUPLEX);
226} 80}
227EXPORT_SYMBOL_GPL(mxs_pcm_platform_register); 81EXPORT_SYMBOL_GPL(mxs_pcm_platform_register);
228 82
229void mxs_pcm_platform_unregister(struct device *dev) 83void mxs_pcm_platform_unregister(struct device *dev)
230{ 84{
231 snd_soc_unregister_platform(dev); 85 snd_dmaengine_pcm_unregister(dev);
232} 86}
233EXPORT_SYMBOL_GPL(mxs_pcm_platform_unregister); 87EXPORT_SYMBOL_GPL(mxs_pcm_platform_unregister);
234 88
diff --git a/sound/soc/mxs/mxs-pcm.h b/sound/soc/mxs/mxs-pcm.h
index 35ba2ca42384..3aa918f9ed3e 100644
--- a/sound/soc/mxs/mxs-pcm.h
+++ b/sound/soc/mxs/mxs-pcm.h
@@ -19,8 +19,10 @@
19#ifndef _MXS_PCM_H 19#ifndef _MXS_PCM_H
20#define _MXS_PCM_H 20#define _MXS_PCM_H
21 21
22#include <linux/fsl/mxs-dma.h>
23
22struct mxs_pcm_dma_params { 24struct mxs_pcm_dma_params {
23 int chan_irq; 25 struct mxs_dma_data dma_data;
24 int chan_num; 26 int chan_num;
25}; 27};
26 28
diff --git a/sound/soc/mxs/mxs-saif.c b/sound/soc/mxs/mxs-saif.c
index 41a6136e3535..d31dc52fa862 100644
--- a/sound/soc/mxs/mxs-saif.c
+++ b/sound/soc/mxs/mxs-saif.c
@@ -370,7 +370,6 @@ static int mxs_saif_startup(struct snd_pcm_substream *substream,
370 struct snd_soc_dai *cpu_dai) 370 struct snd_soc_dai *cpu_dai)
371{ 371{
372 struct mxs_saif *saif = snd_soc_dai_get_drvdata(cpu_dai); 372 struct mxs_saif *saif = snd_soc_dai_get_drvdata(cpu_dai);
373 snd_soc_dai_set_dma_data(cpu_dai, substream, &saif->dma_param);
374 373
375 /* clear error status to 0 for each re-open */ 374 /* clear error status to 0 for each re-open */
376 saif->fifo_underrun = 0; 375 saif->fifo_underrun = 0;
@@ -606,6 +605,8 @@ static int mxs_saif_dai_probe(struct snd_soc_dai *dai)
606 struct mxs_saif *saif = dev_get_drvdata(dai->dev); 605 struct mxs_saif *saif = dev_get_drvdata(dai->dev);
607 606
608 snd_soc_dai_set_drvdata(dai, saif); 607 snd_soc_dai_set_drvdata(dai, saif);
608 dai->playback_dma_data = &saif->dma_param;
609 dai->capture_dma_data = &saif->dma_param;
609 610
610 return 0; 611 return 0;
611} 612}
@@ -628,6 +629,10 @@ static struct snd_soc_dai_driver mxs_saif_dai = {
628 .ops = &mxs_saif_dai_ops, 629 .ops = &mxs_saif_dai_ops,
629}; 630};
630 631
632static const struct snd_soc_component_driver mxs_saif_component = {
633 .name = "mxs-saif",
634};
635
631static irqreturn_t mxs_saif_irq(int irq, void *dev_id) 636static irqreturn_t mxs_saif_irq(int irq, void *dev_id)
632{ 637{
633 struct mxs_saif *saif = dev_id; 638 struct mxs_saif *saif = dev_id;
@@ -754,9 +759,9 @@ static int mxs_saif_probe(struct platform_device *pdev)
754 return ret; 759 return ret;
755 } 760 }
756 761
757 saif->dma_param.chan_irq = platform_get_irq(pdev, 1); 762 saif->dma_param.dma_data.chan_irq = platform_get_irq(pdev, 1);
758 if (saif->dma_param.chan_irq < 0) { 763 if (saif->dma_param.dma_data.chan_irq < 0) {
759 ret = saif->dma_param.chan_irq; 764 ret = saif->dma_param.dma_data.chan_irq;
760 dev_err(&pdev->dev, "failed to get dma irq resource: %d\n", 765 dev_err(&pdev->dev, "failed to get dma irq resource: %d\n",
761 ret); 766 ret);
762 return ret; 767 return ret;
@@ -764,7 +769,8 @@ static int mxs_saif_probe(struct platform_device *pdev)
764 769
765 platform_set_drvdata(pdev, saif); 770 platform_set_drvdata(pdev, saif);
766 771
767 ret = snd_soc_register_dai(&pdev->dev, &mxs_saif_dai); 772 ret = snd_soc_register_component(&pdev->dev, &mxs_saif_component,
773 &mxs_saif_dai, 1);
768 if (ret) { 774 if (ret) {
769 dev_err(&pdev->dev, "register DAI failed\n"); 775 dev_err(&pdev->dev, "register DAI failed\n");
770 return ret; 776 return ret;
@@ -779,7 +785,7 @@ static int mxs_saif_probe(struct platform_device *pdev)
779 return 0; 785 return 0;
780 786
781failed_pdev_alloc: 787failed_pdev_alloc:
782 snd_soc_unregister_dai(&pdev->dev); 788 snd_soc_unregister_component(&pdev->dev);
783 789
784 return ret; 790 return ret;
785} 791}
@@ -787,7 +793,7 @@ failed_pdev_alloc:
787static int mxs_saif_remove(struct platform_device *pdev) 793static int mxs_saif_remove(struct platform_device *pdev)
788{ 794{
789 mxs_pcm_platform_unregister(&pdev->dev); 795 mxs_pcm_platform_unregister(&pdev->dev);
790 snd_soc_unregister_dai(&pdev->dev); 796 snd_soc_unregister_component(&pdev->dev);
791 797
792 return 0; 798 return 0;
793} 799}