diff options
author | Mark Brown <broonie@opensource.wolfsonmicro.com> | 2013-04-18 10:05:30 -0400 |
---|---|---|
committer | Mark Brown <broonie@opensource.wolfsonmicro.com> | 2013-04-18 10:05:30 -0400 |
commit | d45a26bd9790fcde58cf4b11a775ff56c6b44e0b (patch) | |
tree | 71b75e94b7a586123331eed46e91d25dd88ff52a /sound/soc | |
parent | 8ef53f689afea7f2da360cb27d7af040c1216bfa (diff) | |
parent | 22f38f792ec53e2a93be13ecb609bbe911ed8ff9 (diff) |
Merge remote-tracking branch 'asoc/topic/dma' into asoc-next
Diffstat (limited to 'sound/soc')
58 files changed, 808 insertions, 1079 deletions
diff --git a/sound/soc/Kconfig b/sound/soc/Kconfig index 5da8ca7aee05..9e675c76436c 100644 --- a/sound/soc/Kconfig +++ b/sound/soc/Kconfig | |||
@@ -29,6 +29,10 @@ config SND_SOC_AC97_BUS | |||
29 | config SND_SOC_DMAENGINE_PCM | 29 | config SND_SOC_DMAENGINE_PCM |
30 | bool | 30 | bool |
31 | 31 | ||
32 | config SND_SOC_GENERIC_DMAENGINE_PCM | ||
33 | bool | ||
34 | select SND_SOC_DMAENGINE_PCM | ||
35 | |||
32 | # All the supported SoCs | 36 | # All the supported SoCs |
33 | source "sound/soc/atmel/Kconfig" | 37 | source "sound/soc/atmel/Kconfig" |
34 | source "sound/soc/au1x/Kconfig" | 38 | source "sound/soc/au1x/Kconfig" |
diff --git a/sound/soc/Makefile b/sound/soc/Makefile index 99f32f7c0692..197b6ae54c8d 100644 --- a/sound/soc/Makefile +++ b/sound/soc/Makefile | |||
@@ -5,6 +5,10 @@ ifneq ($(CONFIG_SND_SOC_DMAENGINE_PCM),) | |||
5 | snd-soc-core-objs += soc-dmaengine-pcm.o | 5 | snd-soc-core-objs += soc-dmaengine-pcm.o |
6 | endif | 6 | endif |
7 | 7 | ||
8 | ifneq ($(CONFIG_SND_SOC_GENERIC_DMAENGINE_PCM),) | ||
9 | snd-soc-core-objs += soc-generic-dmaengine-pcm.o | ||
10 | endif | ||
11 | |||
8 | obj-$(CONFIG_SND_SOC) += snd-soc-core.o | 12 | obj-$(CONFIG_SND_SOC) += snd-soc-core.o |
9 | obj-$(CONFIG_SND_SOC) += codecs/ | 13 | obj-$(CONFIG_SND_SOC) += codecs/ |
10 | obj-$(CONFIG_SND_SOC) += generic/ | 14 | obj-$(CONFIG_SND_SOC) += generic/ |
diff --git a/sound/soc/atmel/atmel-pcm-dma.c b/sound/soc/atmel/atmel-pcm-dma.c index 30184a4a147a..1d38fd0bc4e2 100644 --- a/sound/soc/atmel/atmel-pcm-dma.c +++ b/sound/soc/atmel/atmel-pcm-dma.c | |||
@@ -67,9 +67,10 @@ static const struct snd_pcm_hardware atmel_pcm_dma_hardware = { | |||
67 | static void atmel_pcm_dma_irq(u32 ssc_sr, | 67 | static void atmel_pcm_dma_irq(u32 ssc_sr, |
68 | struct snd_pcm_substream *substream) | 68 | struct snd_pcm_substream *substream) |
69 | { | 69 | { |
70 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | ||
70 | struct atmel_pcm_dma_params *prtd; | 71 | struct atmel_pcm_dma_params *prtd; |
71 | 72 | ||
72 | prtd = snd_dmaengine_pcm_get_data(substream); | 73 | prtd = snd_soc_dai_get_dma_data(rtd->cpu_dai, substream); |
73 | 74 | ||
74 | if (ssc_sr & prtd->mask->ssc_error) { | 75 | if (ssc_sr & prtd->mask->ssc_error) { |
75 | if (snd_pcm_running(substream)) | 76 | if (snd_pcm_running(substream)) |
@@ -104,15 +105,13 @@ static bool filter(struct dma_chan *chan, void *slave) | |||
104 | } | 105 | } |
105 | 106 | ||
106 | static int atmel_pcm_configure_dma(struct snd_pcm_substream *substream, | 107 | static int atmel_pcm_configure_dma(struct snd_pcm_substream *substream, |
107 | struct snd_pcm_hw_params *params) | 108 | struct snd_pcm_hw_params *params, struct atmel_pcm_dma_params *prtd) |
108 | { | 109 | { |
109 | struct atmel_pcm_dma_params *prtd; | ||
110 | struct ssc_device *ssc; | 110 | struct ssc_device *ssc; |
111 | struct dma_chan *dma_chan; | 111 | struct dma_chan *dma_chan; |
112 | struct dma_slave_config slave_config; | 112 | struct dma_slave_config slave_config; |
113 | int ret; | 113 | int ret; |
114 | 114 | ||
115 | prtd = snd_dmaengine_pcm_get_data(substream); | ||
116 | ssc = prtd->ssc; | 115 | ssc = prtd->ssc; |
117 | 116 | ||
118 | ret = snd_hwparams_to_dma_slave_config(substream, params, | 117 | ret = snd_hwparams_to_dma_slave_config(substream, params, |
@@ -130,8 +129,6 @@ static int atmel_pcm_configure_dma(struct snd_pcm_substream *substream, | |||
130 | slave_config.src_maxburst = 1; | 129 | slave_config.src_maxburst = 1; |
131 | } | 130 | } |
132 | 131 | ||
133 | slave_config.device_fc = false; | ||
134 | |||
135 | dma_chan = snd_dmaengine_pcm_get_chan(substream); | 132 | dma_chan = snd_dmaengine_pcm_get_chan(substream); |
136 | if (dmaengine_slave_config(dma_chan, &slave_config)) { | 133 | if (dmaengine_slave_config(dma_chan, &slave_config)) { |
137 | pr_err("atmel-pcm: failed to configure dma channel\n"); | 134 | pr_err("atmel-pcm: failed to configure dma channel\n"); |
@@ -158,15 +155,13 @@ static int atmel_pcm_hw_params(struct snd_pcm_substream *substream, | |||
158 | if (ssc->pdev) | 155 | if (ssc->pdev) |
159 | sdata = ssc->pdev->dev.platform_data; | 156 | sdata = ssc->pdev->dev.platform_data; |
160 | 157 | ||
161 | ret = snd_dmaengine_pcm_open(substream, filter, sdata); | 158 | ret = snd_dmaengine_pcm_open_request_chan(substream, filter, sdata); |
162 | if (ret) { | 159 | if (ret) { |
163 | pr_err("atmel-pcm: dmaengine pcm open failed\n"); | 160 | pr_err("atmel-pcm: dmaengine pcm open failed\n"); |
164 | return -EINVAL; | 161 | return -EINVAL; |
165 | } | 162 | } |
166 | 163 | ||
167 | snd_dmaengine_pcm_set_data(substream, prtd); | 164 | ret = atmel_pcm_configure_dma(substream, params, prtd); |
168 | |||
169 | ret = atmel_pcm_configure_dma(substream, params); | ||
170 | if (ret) { | 165 | if (ret) { |
171 | pr_err("atmel-pcm: failed to configure dmai\n"); | 166 | pr_err("atmel-pcm: failed to configure dmai\n"); |
172 | goto err; | 167 | goto err; |
@@ -176,15 +171,16 @@ static int atmel_pcm_hw_params(struct snd_pcm_substream *substream, | |||
176 | 171 | ||
177 | return 0; | 172 | return 0; |
178 | err: | 173 | err: |
179 | snd_dmaengine_pcm_close(substream); | 174 | snd_dmaengine_pcm_close_release_chan(substream); |
180 | return ret; | 175 | return ret; |
181 | } | 176 | } |
182 | 177 | ||
183 | static int atmel_pcm_dma_prepare(struct snd_pcm_substream *substream) | 178 | static int atmel_pcm_dma_prepare(struct snd_pcm_substream *substream) |
184 | { | 179 | { |
180 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | ||
185 | struct atmel_pcm_dma_params *prtd; | 181 | struct atmel_pcm_dma_params *prtd; |
186 | 182 | ||
187 | prtd = snd_dmaengine_pcm_get_data(substream); | 183 | prtd = snd_soc_dai_get_dma_data(rtd->cpu_dai, substream); |
188 | 184 | ||
189 | ssc_writex(prtd->ssc->regs, SSC_IER, prtd->mask->ssc_error); | 185 | ssc_writex(prtd->ssc->regs, SSC_IER, prtd->mask->ssc_error); |
190 | ssc_writex(prtd->ssc->regs, SSC_CR, prtd->mask->ssc_enable); | 186 | ssc_writex(prtd->ssc->regs, SSC_CR, prtd->mask->ssc_enable); |
@@ -199,16 +195,9 @@ static int atmel_pcm_open(struct snd_pcm_substream *substream) | |||
199 | return 0; | 195 | return 0; |
200 | } | 196 | } |
201 | 197 | ||
202 | static int atmel_pcm_close(struct snd_pcm_substream *substream) | ||
203 | { | ||
204 | snd_dmaengine_pcm_close(substream); | ||
205 | |||
206 | return 0; | ||
207 | } | ||
208 | |||
209 | static struct snd_pcm_ops atmel_pcm_ops = { | 198 | static struct snd_pcm_ops atmel_pcm_ops = { |
210 | .open = atmel_pcm_open, | 199 | .open = atmel_pcm_open, |
211 | .close = atmel_pcm_close, | 200 | .close = snd_dmaengine_pcm_close_release_chan, |
212 | .ioctl = snd_pcm_lib_ioctl, | 201 | .ioctl = snd_pcm_lib_ioctl, |
213 | .hw_params = atmel_pcm_hw_params, | 202 | .hw_params = atmel_pcm_hw_params, |
214 | .prepare = atmel_pcm_dma_prepare, | 203 | .prepare = atmel_pcm_dma_prepare, |
diff --git a/sound/soc/cirrus/edb93xx.c b/sound/soc/cirrus/edb93xx.c index 5db68cf7b281..c43fb214558a 100644 --- a/sound/soc/cirrus/edb93xx.c +++ b/sound/soc/cirrus/edb93xx.c | |||
@@ -27,7 +27,6 @@ | |||
27 | #include <sound/soc.h> | 27 | #include <sound/soc.h> |
28 | #include <asm/mach-types.h> | 28 | #include <asm/mach-types.h> |
29 | #include <mach/hardware.h> | 29 | #include <mach/hardware.h> |
30 | #include "ep93xx-pcm.h" | ||
31 | 30 | ||
32 | static int edb93xx_hw_params(struct snd_pcm_substream *substream, | 31 | static int edb93xx_hw_params(struct snd_pcm_substream *substream, |
33 | struct snd_pcm_hw_params *params) | 32 | struct snd_pcm_hw_params *params) |
diff --git a/sound/soc/cirrus/ep93xx-ac97.c b/sound/soc/cirrus/ep93xx-ac97.c index 1738d28fb04f..8d3088647e44 100644 --- a/sound/soc/cirrus/ep93xx-ac97.c +++ b/sound/soc/cirrus/ep93xx-ac97.c | |||
@@ -23,7 +23,6 @@ | |||
23 | #include <sound/soc.h> | 23 | #include <sound/soc.h> |
24 | 24 | ||
25 | #include <linux/platform_data/dma-ep93xx.h> | 25 | #include <linux/platform_data/dma-ep93xx.h> |
26 | #include "ep93xx-pcm.h" | ||
27 | 26 | ||
28 | /* | 27 | /* |
29 | * Per channel (1-4) registers. | 28 | * Per channel (1-4) registers. |
@@ -101,14 +100,16 @@ struct ep93xx_ac97_info { | |||
101 | /* currently ALSA only supports a single AC97 device */ | 100 | /* currently ALSA only supports a single AC97 device */ |
102 | static struct ep93xx_ac97_info *ep93xx_ac97_info; | 101 | static struct ep93xx_ac97_info *ep93xx_ac97_info; |
103 | 102 | ||
104 | static struct ep93xx_pcm_dma_params ep93xx_ac97_pcm_out = { | 103 | static struct ep93xx_dma_data ep93xx_ac97_pcm_out = { |
105 | .name = "ac97-pcm-out", | 104 | .name = "ac97-pcm-out", |
106 | .dma_port = EP93XX_DMA_AAC1, | 105 | .dma_port = EP93XX_DMA_AAC1, |
106 | .direction = DMA_MEM_TO_DEV, | ||
107 | }; | 107 | }; |
108 | 108 | ||
109 | static struct ep93xx_pcm_dma_params ep93xx_ac97_pcm_in = { | 109 | static struct ep93xx_dma_data ep93xx_ac97_pcm_in = { |
110 | .name = "ac97-pcm-in", | 110 | .name = "ac97-pcm-in", |
111 | .dma_port = EP93XX_DMA_AAC1, | 111 | .dma_port = EP93XX_DMA_AAC1, |
112 | .direction = DMA_DEV_TO_MEM, | ||
112 | }; | 113 | }; |
113 | 114 | ||
114 | static inline unsigned ep93xx_ac97_read_reg(struct ep93xx_ac97_info *info, | 115 | static inline unsigned ep93xx_ac97_read_reg(struct ep93xx_ac97_info *info, |
@@ -316,7 +317,7 @@ static int ep93xx_ac97_trigger(struct snd_pcm_substream *substream, | |||
316 | static int ep93xx_ac97_startup(struct snd_pcm_substream *substream, | 317 | static int ep93xx_ac97_startup(struct snd_pcm_substream *substream, |
317 | struct snd_soc_dai *dai) | 318 | struct snd_soc_dai *dai) |
318 | { | 319 | { |
319 | struct ep93xx_pcm_dma_params *dma_data; | 320 | struct ep93xx_dma_data *dma_data; |
320 | 321 | ||
321 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) | 322 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) |
322 | dma_data = &ep93xx_ac97_pcm_out; | 323 | dma_data = &ep93xx_ac97_pcm_out; |
diff --git a/sound/soc/cirrus/ep93xx-i2s.c b/sound/soc/cirrus/ep93xx-i2s.c index 323ed69b7975..83075b3c180c 100644 --- a/sound/soc/cirrus/ep93xx-i2s.c +++ b/sound/soc/cirrus/ep93xx-i2s.c | |||
@@ -30,8 +30,6 @@ | |||
30 | #include <mach/ep93xx-regs.h> | 30 | #include <mach/ep93xx-regs.h> |
31 | #include <linux/platform_data/dma-ep93xx.h> | 31 | #include <linux/platform_data/dma-ep93xx.h> |
32 | 32 | ||
33 | #include "ep93xx-pcm.h" | ||
34 | |||
35 | #define EP93XX_I2S_TXCLKCFG 0x00 | 33 | #define EP93XX_I2S_TXCLKCFG 0x00 |
36 | #define EP93XX_I2S_RXCLKCFG 0x04 | 34 | #define EP93XX_I2S_RXCLKCFG 0x04 |
37 | #define EP93XX_I2S_GLCTRL 0x0C | 35 | #define EP93XX_I2S_GLCTRL 0x0C |
@@ -62,18 +60,20 @@ struct ep93xx_i2s_info { | |||
62 | struct clk *mclk; | 60 | struct clk *mclk; |
63 | struct clk *sclk; | 61 | struct clk *sclk; |
64 | struct clk *lrclk; | 62 | struct clk *lrclk; |
65 | struct ep93xx_pcm_dma_params *dma_params; | 63 | struct ep93xx_dma_data *dma_data; |
66 | void __iomem *regs; | 64 | void __iomem *regs; |
67 | }; | 65 | }; |
68 | 66 | ||
69 | struct ep93xx_pcm_dma_params ep93xx_i2s_dma_params[] = { | 67 | struct ep93xx_dma_data ep93xx_i2s_dma_data[] = { |
70 | [SNDRV_PCM_STREAM_PLAYBACK] = { | 68 | [SNDRV_PCM_STREAM_PLAYBACK] = { |
71 | .name = "i2s-pcm-out", | 69 | .name = "i2s-pcm-out", |
72 | .dma_port = EP93XX_DMA_I2S1, | 70 | .port = EP93XX_DMA_I2S1, |
71 | .direction = DMA_MEM_TO_DEV, | ||
73 | }, | 72 | }, |
74 | [SNDRV_PCM_STREAM_CAPTURE] = { | 73 | [SNDRV_PCM_STREAM_CAPTURE] = { |
75 | .name = "i2s-pcm-in", | 74 | .name = "i2s-pcm-in", |
76 | .dma_port = EP93XX_DMA_I2S1, | 75 | .port = EP93XX_DMA_I2S1, |
76 | .direction = DMA_DEV_TO_MEM, | ||
77 | }, | 77 | }, |
78 | }; | 78 | }; |
79 | 79 | ||
@@ -147,7 +147,7 @@ static int ep93xx_i2s_startup(struct snd_pcm_substream *substream, | |||
147 | struct snd_soc_dai *cpu_dai = rtd->cpu_dai; | 147 | struct snd_soc_dai *cpu_dai = rtd->cpu_dai; |
148 | 148 | ||
149 | snd_soc_dai_set_dma_data(cpu_dai, substream, | 149 | snd_soc_dai_set_dma_data(cpu_dai, substream, |
150 | &info->dma_params[substream->stream]); | 150 | &info->dma_data[substream->stream]); |
151 | return 0; | 151 | return 0; |
152 | } | 152 | } |
153 | 153 | ||
@@ -403,7 +403,7 @@ static int ep93xx_i2s_probe(struct platform_device *pdev) | |||
403 | } | 403 | } |
404 | 404 | ||
405 | dev_set_drvdata(&pdev->dev, info); | 405 | dev_set_drvdata(&pdev->dev, info); |
406 | info->dma_params = ep93xx_i2s_dma_params; | 406 | info->dma_data = ep93xx_i2s_dma_data; |
407 | 407 | ||
408 | err = snd_soc_register_dai(&pdev->dev, &ep93xx_i2s_dai); | 408 | err = snd_soc_register_dai(&pdev->dev, &ep93xx_i2s_dai); |
409 | if (err) | 409 | if (err) |
diff --git a/sound/soc/cirrus/ep93xx-pcm.c b/sound/soc/cirrus/ep93xx-pcm.c index 72eb7a49e16a..488032690378 100644 --- a/sound/soc/cirrus/ep93xx-pcm.c +++ b/sound/soc/cirrus/ep93xx-pcm.c | |||
@@ -29,8 +29,6 @@ | |||
29 | #include <mach/hardware.h> | 29 | #include <mach/hardware.h> |
30 | #include <mach/ep93xx-regs.h> | 30 | #include <mach/ep93xx-regs.h> |
31 | 31 | ||
32 | #include "ep93xx-pcm.h" | ||
33 | |||
34 | static const struct snd_pcm_hardware ep93xx_pcm_hardware = { | 32 | static const struct snd_pcm_hardware ep93xx_pcm_hardware = { |
35 | .info = (SNDRV_PCM_INFO_MMAP | | 33 | .info = (SNDRV_PCM_INFO_MMAP | |
36 | SNDRV_PCM_INFO_MMAP_VALID | | 34 | SNDRV_PCM_INFO_MMAP_VALID | |
@@ -68,40 +66,12 @@ static bool ep93xx_pcm_dma_filter(struct dma_chan *chan, void *filter_param) | |||
68 | static int ep93xx_pcm_open(struct snd_pcm_substream *substream) | 66 | static int ep93xx_pcm_open(struct snd_pcm_substream *substream) |
69 | { | 67 | { |
70 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | 68 | struct snd_soc_pcm_runtime *rtd = substream->private_data; |
71 | struct snd_soc_dai *cpu_dai = rtd->cpu_dai; | ||
72 | struct ep93xx_pcm_dma_params *dma_params; | ||
73 | struct ep93xx_dma_data *dma_data; | ||
74 | int ret; | ||
75 | 69 | ||
76 | snd_soc_set_runtime_hwparams(substream, &ep93xx_pcm_hardware); | 70 | snd_soc_set_runtime_hwparams(substream, &ep93xx_pcm_hardware); |
77 | 71 | ||
78 | dma_data = kmalloc(sizeof(*dma_data), GFP_KERNEL); | 72 | return snd_dmaengine_pcm_open_request_chan(substream, |
79 | if (!dma_data) | 73 | ep93xx_pcm_dma_filter, |
80 | return -ENOMEM; | 74 | snd_soc_dai_get_dma_data(rtd->cpu_dai, substream)); |
81 | |||
82 | dma_params = snd_soc_dai_get_dma_data(cpu_dai, substream); | ||
83 | dma_data->port = dma_params->dma_port; | ||
84 | dma_data->name = dma_params->name; | ||
85 | dma_data->direction = snd_pcm_substream_to_dma_direction(substream); | ||
86 | |||
87 | ret = snd_dmaengine_pcm_open(substream, ep93xx_pcm_dma_filter, dma_data); | ||
88 | if (ret) { | ||
89 | kfree(dma_data); | ||
90 | return ret; | ||
91 | } | ||
92 | |||
93 | snd_dmaengine_pcm_set_data(substream, dma_data); | ||
94 | |||
95 | return 0; | ||
96 | } | ||
97 | |||
98 | static int ep93xx_pcm_close(struct snd_pcm_substream *substream) | ||
99 | { | ||
100 | struct dma_data *dma_data = snd_dmaengine_pcm_get_data(substream); | ||
101 | |||
102 | snd_dmaengine_pcm_close(substream); | ||
103 | kfree(dma_data); | ||
104 | return 0; | ||
105 | } | 75 | } |
106 | 76 | ||
107 | static int ep93xx_pcm_hw_params(struct snd_pcm_substream *substream, | 77 | static int ep93xx_pcm_hw_params(struct snd_pcm_substream *substream, |
@@ -131,7 +101,7 @@ static int ep93xx_pcm_mmap(struct snd_pcm_substream *substream, | |||
131 | 101 | ||
132 | static struct snd_pcm_ops ep93xx_pcm_ops = { | 102 | static struct snd_pcm_ops ep93xx_pcm_ops = { |
133 | .open = ep93xx_pcm_open, | 103 | .open = ep93xx_pcm_open, |
134 | .close = ep93xx_pcm_close, | 104 | .close = snd_dmaengine_pcm_close_release_chan, |
135 | .ioctl = snd_pcm_lib_ioctl, | 105 | .ioctl = snd_pcm_lib_ioctl, |
136 | .hw_params = ep93xx_pcm_hw_params, | 106 | .hw_params = ep93xx_pcm_hw_params, |
137 | .hw_free = ep93xx_pcm_hw_free, | 107 | .hw_free = ep93xx_pcm_hw_free, |
diff --git a/sound/soc/cirrus/ep93xx-pcm.h b/sound/soc/cirrus/ep93xx-pcm.h deleted file mode 100644 index 111e1121ecb8..000000000000 --- a/sound/soc/cirrus/ep93xx-pcm.h +++ /dev/null | |||
@@ -1,20 +0,0 @@ | |||
1 | /* | ||
2 | * sound/soc/ep93xx/ep93xx-pcm.h - EP93xx ALSA PCM interface | ||
3 | * | ||
4 | * Copyright (C) 2006 Lennert Buytenhek <buytenh@wantstofly.org> | ||
5 | * Copyright (C) 2006 Applied Data Systems | ||
6 | * | ||
7 | * This program is free software; you can redistribute it and/or modify | ||
8 | * it under the terms of the GNU General Public License version 2 as | ||
9 | * published by the Free Software Foundation. | ||
10 | */ | ||
11 | |||
12 | #ifndef _EP93XX_SND_SOC_PCM_H | ||
13 | #define _EP93XX_SND_SOC_PCM_H | ||
14 | |||
15 | struct ep93xx_pcm_dma_params { | ||
16 | char *name; | ||
17 | int dma_port; | ||
18 | }; | ||
19 | |||
20 | #endif /* _EP93XX_SND_SOC_PCM_H */ | ||
diff --git a/sound/soc/cirrus/simone.c b/sound/soc/cirrus/simone.c index a397bb0d8179..4d094d00c34a 100644 --- a/sound/soc/cirrus/simone.c +++ b/sound/soc/cirrus/simone.c | |||
@@ -21,8 +21,6 @@ | |||
21 | #include <asm/mach-types.h> | 21 | #include <asm/mach-types.h> |
22 | #include <mach/hardware.h> | 22 | #include <mach/hardware.h> |
23 | 23 | ||
24 | #include "ep93xx-pcm.h" | ||
25 | |||
26 | static struct snd_soc_dai_link simone_dai = { | 24 | static struct snd_soc_dai_link simone_dai = { |
27 | .name = "AC97", | 25 | .name = "AC97", |
28 | .stream_name = "AC97 HiFi", | 26 | .stream_name = "AC97 HiFi", |
diff --git a/sound/soc/cirrus/snappercl15.c b/sound/soc/cirrus/snappercl15.c index 9d77fe28dfcc..69041074f2c1 100644 --- a/sound/soc/cirrus/snappercl15.c +++ b/sound/soc/cirrus/snappercl15.c | |||
@@ -21,7 +21,6 @@ | |||
21 | #include <mach/hardware.h> | 21 | #include <mach/hardware.h> |
22 | 22 | ||
23 | #include "../codecs/tlv320aic23.h" | 23 | #include "../codecs/tlv320aic23.h" |
24 | #include "ep93xx-pcm.h" | ||
25 | 24 | ||
26 | #define CODEC_CLOCK 5644800 | 25 | #define CODEC_CLOCK 5644800 |
27 | 26 | ||
diff --git a/sound/soc/fsl/Kconfig b/sound/soc/fsl/Kconfig index 3b98159d9645..3843a18d4e56 100644 --- a/sound/soc/fsl/Kconfig +++ b/sound/soc/fsl/Kconfig | |||
@@ -118,7 +118,7 @@ config SND_SOC_IMX_PCM_FIQ | |||
118 | 118 | ||
119 | config SND_SOC_IMX_PCM_DMA | 119 | config SND_SOC_IMX_PCM_DMA |
120 | bool | 120 | bool |
121 | select SND_SOC_DMAENGINE_PCM | 121 | select SND_SOC_GENERIC_DMAENGINE_PCM |
122 | select SND_SOC_IMX_PCM | 122 | select SND_SOC_IMX_PCM |
123 | 123 | ||
124 | config SND_SOC_IMX_AUDMUX | 124 | config SND_SOC_IMX_AUDMUX |
diff --git a/sound/soc/fsl/fsl_ssi.c b/sound/soc/fsl/fsl_ssi.c index 7decbd9b2340..ab27ffab83f3 100644 --- a/sound/soc/fsl/fsl_ssi.c +++ b/sound/soc/fsl/fsl_ssi.c | |||
@@ -27,6 +27,7 @@ | |||
27 | #include <sound/pcm_params.h> | 27 | #include <sound/pcm_params.h> |
28 | #include <sound/initval.h> | 28 | #include <sound/initval.h> |
29 | #include <sound/soc.h> | 29 | #include <sound/soc.h> |
30 | #include <sound/dmaengine_pcm.h> | ||
30 | 31 | ||
31 | #include "fsl_ssi.h" | 32 | #include "fsl_ssi.h" |
32 | #include "imx-pcm.h" | 33 | #include "imx-pcm.h" |
@@ -122,8 +123,10 @@ struct fsl_ssi_private { | |||
122 | bool ssi_on_imx; | 123 | bool ssi_on_imx; |
123 | struct clk *clk; | 124 | struct clk *clk; |
124 | struct platform_device *imx_pcm_pdev; | 125 | struct platform_device *imx_pcm_pdev; |
125 | struct imx_pcm_dma_params dma_params_tx; | 126 | struct snd_dmaengine_dai_dma_data dma_params_tx; |
126 | struct imx_pcm_dma_params dma_params_rx; | 127 | struct snd_dmaengine_dai_dma_data dma_params_rx; |
128 | struct imx_dma_data filter_data_tx; | ||
129 | struct imx_dma_data filter_data_rx; | ||
127 | 130 | ||
128 | struct { | 131 | struct { |
129 | unsigned int rfrc; | 132 | unsigned int rfrc; |
@@ -422,12 +425,6 @@ static int fsl_ssi_startup(struct snd_pcm_substream *substream, | |||
422 | ssi_private->second_stream = substream; | 425 | ssi_private->second_stream = substream; |
423 | } | 426 | } |
424 | 427 | ||
425 | if (ssi_private->ssi_on_imx) | ||
426 | snd_soc_dai_set_dma_data(dai, substream, | ||
427 | (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) ? | ||
428 | &ssi_private->dma_params_tx : | ||
429 | &ssi_private->dma_params_rx); | ||
430 | |||
431 | return 0; | 428 | return 0; |
432 | } | 429 | } |
433 | 430 | ||
@@ -549,6 +546,18 @@ static void fsl_ssi_shutdown(struct snd_pcm_substream *substream, | |||
549 | } | 546 | } |
550 | } | 547 | } |
551 | 548 | ||
549 | static int fsl_ssi_dai_probe(struct snd_soc_dai *dai) | ||
550 | { | ||
551 | struct fsl_ssi_private *ssi_private = snd_soc_dai_get_drvdata(dai); | ||
552 | |||
553 | if (ssi_private->ssi_on_imx) { | ||
554 | dai->playback_dma_data = &ssi_private->dma_params_tx; | ||
555 | dai->capture_dma_data = &ssi_private->dma_params_rx; | ||
556 | } | ||
557 | |||
558 | return 0; | ||
559 | } | ||
560 | |||
552 | static const struct snd_soc_dai_ops fsl_ssi_dai_ops = { | 561 | static const struct snd_soc_dai_ops fsl_ssi_dai_ops = { |
553 | .startup = fsl_ssi_startup, | 562 | .startup = fsl_ssi_startup, |
554 | .hw_params = fsl_ssi_hw_params, | 563 | .hw_params = fsl_ssi_hw_params, |
@@ -558,6 +567,7 @@ static const struct snd_soc_dai_ops fsl_ssi_dai_ops = { | |||
558 | 567 | ||
559 | /* Template for the CPU dai driver structure */ | 568 | /* Template for the CPU dai driver structure */ |
560 | static struct snd_soc_dai_driver fsl_ssi_dai_template = { | 569 | static struct snd_soc_dai_driver fsl_ssi_dai_template = { |
570 | .probe = fsl_ssi_dai_probe, | ||
561 | .playback = { | 571 | .playback = { |
562 | /* The SSI does not support monaural audio. */ | 572 | /* The SSI does not support monaural audio. */ |
563 | .channels_min = 2, | 573 | .channels_min = 2, |
@@ -649,6 +659,7 @@ static int fsl_ssi_probe(struct platform_device *pdev) | |||
649 | const uint32_t *iprop; | 659 | const uint32_t *iprop; |
650 | struct resource res; | 660 | struct resource res; |
651 | char name[64]; | 661 | char name[64]; |
662 | bool shared; | ||
652 | 663 | ||
653 | /* SSIs that are not connected on the board should have a | 664 | /* SSIs that are not connected on the board should have a |
654 | * status = "disabled" | 665 | * status = "disabled" |
@@ -737,14 +748,18 @@ static int fsl_ssi_probe(struct platform_device *pdev) | |||
737 | * We have burstsize be "fifo_depth - 2" to match the SSI | 748 | * We have burstsize be "fifo_depth - 2" to match the SSI |
738 | * watermark setting in fsl_ssi_startup(). | 749 | * watermark setting in fsl_ssi_startup(). |
739 | */ | 750 | */ |
740 | ssi_private->dma_params_tx.burstsize = | 751 | ssi_private->dma_params_tx.maxburst = |
741 | ssi_private->fifo_depth - 2; | 752 | ssi_private->fifo_depth - 2; |
742 | ssi_private->dma_params_rx.burstsize = | 753 | ssi_private->dma_params_rx.maxburst = |
743 | ssi_private->fifo_depth - 2; | 754 | ssi_private->fifo_depth - 2; |
744 | ssi_private->dma_params_tx.dma_addr = | 755 | ssi_private->dma_params_tx.addr = |
745 | ssi_private->ssi_phys + offsetof(struct ccsr_ssi, stx0); | 756 | ssi_private->ssi_phys + offsetof(struct ccsr_ssi, stx0); |
746 | ssi_private->dma_params_rx.dma_addr = | 757 | ssi_private->dma_params_rx.addr = |
747 | ssi_private->ssi_phys + offsetof(struct ccsr_ssi, srx0); | 758 | ssi_private->ssi_phys + offsetof(struct ccsr_ssi, srx0); |
759 | ssi_private->dma_params_tx.filter_data = | ||
760 | &ssi_private->filter_data_tx; | ||
761 | ssi_private->dma_params_rx.filter_data = | ||
762 | &ssi_private->filter_data_rx; | ||
748 | /* | 763 | /* |
749 | * TODO: This is a temporary solution and should be changed | 764 | * TODO: This is a temporary solution and should be changed |
750 | * to use generic DMA binding later when the helplers get in. | 765 | * to use generic DMA binding later when the helplers get in. |
@@ -755,14 +770,14 @@ static int fsl_ssi_probe(struct platform_device *pdev) | |||
755 | dev_err(&pdev->dev, "could not get dma events\n"); | 770 | dev_err(&pdev->dev, "could not get dma events\n"); |
756 | goto error_clk; | 771 | goto error_clk; |
757 | } | 772 | } |
758 | ssi_private->dma_params_tx.dma = dma_events[0]; | 773 | |
759 | ssi_private->dma_params_rx.dma = dma_events[1]; | 774 | shared = of_device_is_compatible(of_get_parent(np), |
760 | 775 | "fsl,spba-bus"); | |
761 | ssi_private->dma_params_tx.shared_peripheral = | 776 | |
762 | of_device_is_compatible(of_get_parent(np), | 777 | imx_pcm_dma_params_init_data(&ssi_private->filter_data_tx, |
763 | "fsl,spba-bus"); | 778 | dma_events[0], shared); |
764 | ssi_private->dma_params_rx.shared_peripheral = | 779 | imx_pcm_dma_params_init_data(&ssi_private->filter_data_rx, |
765 | ssi_private->dma_params_tx.shared_peripheral; | 780 | dma_events[1], shared); |
766 | } | 781 | } |
767 | 782 | ||
768 | /* Initialize the the device_attribute structure */ | 783 | /* Initialize the the device_attribute structure */ |
diff --git a/sound/soc/fsl/imx-pcm-dma.c b/sound/soc/fsl/imx-pcm-dma.c index 500f8ce55d78..c246fb514930 100644 --- a/sound/soc/fsl/imx-pcm-dma.c +++ b/sound/soc/fsl/imx-pcm-dma.c | |||
@@ -11,74 +11,30 @@ | |||
11 | * Free Software Foundation; either version 2 of the License, or (at your | 11 | * Free Software Foundation; either version 2 of the License, or (at your |
12 | * option) any later version. | 12 | * option) any later version. |
13 | */ | 13 | */ |
14 | #include <linux/clk.h> | ||
15 | #include <linux/delay.h> | ||
16 | #include <linux/device.h> | ||
17 | #include <linux/dma-mapping.h> | ||
18 | #include <linux/init.h> | ||
19 | #include <linux/interrupt.h> | ||
20 | #include <linux/module.h> | ||
21 | #include <linux/platform_device.h> | 14 | #include <linux/platform_device.h> |
22 | #include <linux/slab.h> | ||
23 | #include <linux/dmaengine.h> | 15 | #include <linux/dmaengine.h> |
24 | #include <linux/types.h> | 16 | #include <linux/types.h> |
25 | 17 | ||
26 | #include <sound/core.h> | 18 | #include <sound/core.h> |
27 | #include <sound/initval.h> | ||
28 | #include <sound/pcm.h> | 19 | #include <sound/pcm.h> |
29 | #include <sound/pcm_params.h> | ||
30 | #include <sound/soc.h> | 20 | #include <sound/soc.h> |
31 | #include <sound/dmaengine_pcm.h> | 21 | #include <sound/dmaengine_pcm.h> |
32 | 22 | ||
33 | #include <linux/platform_data/dma-imx.h> | ||
34 | |||
35 | #include "imx-pcm.h" | 23 | #include "imx-pcm.h" |
36 | 24 | ||
37 | static bool filter(struct dma_chan *chan, void *param) | 25 | static bool filter(struct dma_chan *chan, void *param) |
38 | { | 26 | { |
27 | struct snd_dmaengine_dai_dma_data *dma_data = param; | ||
28 | |||
39 | if (!imx_dma_is_general_purpose(chan)) | 29 | if (!imx_dma_is_general_purpose(chan)) |
40 | return false; | 30 | return false; |
41 | 31 | ||
42 | chan->private = param; | 32 | chan->private = dma_data->filter_data; |
43 | 33 | ||
44 | return true; | 34 | return true; |
45 | } | 35 | } |
46 | 36 | ||
47 | static int snd_imx_pcm_hw_params(struct snd_pcm_substream *substream, | 37 | static const struct snd_pcm_hardware imx_pcm_hardware = { |
48 | struct snd_pcm_hw_params *params) | ||
49 | { | ||
50 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | ||
51 | struct dma_chan *chan = snd_dmaengine_pcm_get_chan(substream); | ||
52 | struct imx_pcm_dma_params *dma_params; | ||
53 | struct dma_slave_config slave_config; | ||
54 | int ret; | ||
55 | |||
56 | dma_params = snd_soc_dai_get_dma_data(rtd->cpu_dai, substream); | ||
57 | |||
58 | ret = snd_hwparams_to_dma_slave_config(substream, params, &slave_config); | ||
59 | if (ret) | ||
60 | return ret; | ||
61 | |||
62 | slave_config.device_fc = false; | ||
63 | |||
64 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { | ||
65 | slave_config.dst_addr = dma_params->dma_addr; | ||
66 | slave_config.dst_maxburst = dma_params->burstsize; | ||
67 | } else { | ||
68 | slave_config.src_addr = dma_params->dma_addr; | ||
69 | slave_config.src_maxburst = dma_params->burstsize; | ||
70 | } | ||
71 | |||
72 | ret = dmaengine_slave_config(chan, &slave_config); | ||
73 | if (ret) | ||
74 | return ret; | ||
75 | |||
76 | snd_pcm_set_runtime_buffer(substream, &substream->dma_buffer); | ||
77 | |||
78 | return 0; | ||
79 | } | ||
80 | |||
81 | static struct snd_pcm_hardware snd_imx_hardware = { | ||
82 | .info = SNDRV_PCM_INFO_INTERLEAVED | | 38 | .info = SNDRV_PCM_INFO_INTERLEAVED | |
83 | SNDRV_PCM_INFO_BLOCK_TRANSFER | | 39 | SNDRV_PCM_INFO_BLOCK_TRANSFER | |
84 | SNDRV_PCM_INFO_MMAP | | 40 | SNDRV_PCM_INFO_MMAP | |
@@ -97,64 +53,22 @@ static struct snd_pcm_hardware snd_imx_hardware = { | |||
97 | .fifo_size = 0, | 53 | .fifo_size = 0, |
98 | }; | 54 | }; |
99 | 55 | ||
100 | static int snd_imx_open(struct snd_pcm_substream *substream) | 56 | static const struct snd_dmaengine_pcm_config imx_dmaengine_pcm_config = { |
101 | { | 57 | .pcm_hardware = &imx_pcm_hardware, |
102 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | 58 | .prepare_slave_config = snd_dmaengine_pcm_prepare_slave_config, |
103 | struct imx_pcm_dma_params *dma_params; | 59 | .compat_filter_fn = filter, |
104 | struct imx_dma_data *dma_data; | 60 | .prealloc_buffer_size = IMX_SSI_DMABUF_SIZE, |
105 | int ret; | 61 | }; |
106 | |||
107 | snd_soc_set_runtime_hwparams(substream, &snd_imx_hardware); | ||
108 | |||
109 | dma_params = snd_soc_dai_get_dma_data(rtd->cpu_dai, substream); | ||
110 | |||
111 | dma_data = kzalloc(sizeof(*dma_data), GFP_KERNEL); | ||
112 | if (!dma_data) | ||
113 | return -ENOMEM; | ||
114 | |||
115 | dma_data->peripheral_type = dma_params->shared_peripheral ? | ||
116 | IMX_DMATYPE_SSI_SP : IMX_DMATYPE_SSI; | ||
117 | dma_data->priority = DMA_PRIO_HIGH; | ||
118 | dma_data->dma_request = dma_params->dma; | ||
119 | |||
120 | ret = snd_dmaengine_pcm_open(substream, filter, dma_data); | ||
121 | if (ret) { | ||
122 | kfree(dma_data); | ||
123 | return ret; | ||
124 | } | ||
125 | |||
126 | snd_dmaengine_pcm_set_data(substream, dma_data); | ||
127 | |||
128 | return 0; | ||
129 | } | ||
130 | 62 | ||
131 | static int snd_imx_close(struct snd_pcm_substream *substream) | 63 | int imx_pcm_dma_init(struct platform_device *pdev) |
132 | { | 64 | { |
133 | struct imx_dma_data *dma_data = snd_dmaengine_pcm_get_data(substream); | 65 | return snd_dmaengine_pcm_register(&pdev->dev, &imx_dmaengine_pcm_config, |
134 | 66 | SND_DMAENGINE_PCM_FLAG_NO_RESIDUE | | |
135 | snd_dmaengine_pcm_close(substream); | 67 | SND_DMAENGINE_PCM_FLAG_NO_DT | |
136 | kfree(dma_data); | 68 | SND_DMAENGINE_PCM_FLAG_COMPAT); |
137 | |||
138 | return 0; | ||
139 | } | 69 | } |
140 | 70 | ||
141 | static struct snd_pcm_ops imx_pcm_ops = { | 71 | void imx_pcm_dma_exit(struct platform_device *pdev) |
142 | .open = snd_imx_open, | ||
143 | .close = snd_imx_close, | ||
144 | .ioctl = snd_pcm_lib_ioctl, | ||
145 | .hw_params = snd_imx_pcm_hw_params, | ||
146 | .trigger = snd_dmaengine_pcm_trigger, | ||
147 | .pointer = snd_dmaengine_pcm_pointer_no_residue, | ||
148 | .mmap = snd_imx_pcm_mmap, | ||
149 | }; | ||
150 | |||
151 | static struct snd_soc_platform_driver imx_soc_platform_mx2 = { | ||
152 | .ops = &imx_pcm_ops, | ||
153 | .pcm_new = imx_pcm_new, | ||
154 | .pcm_free = imx_pcm_free, | ||
155 | }; | ||
156 | |||
157 | int imx_pcm_dma_init(struct platform_device *pdev) | ||
158 | { | 72 | { |
159 | return snd_soc_register_platform(&pdev->dev, &imx_soc_platform_mx2); | 73 | snd_dmaengine_pcm_unregister(&pdev->dev); |
160 | } | 74 | } |
diff --git a/sound/soc/fsl/imx-pcm-fiq.c b/sound/soc/fsl/imx-pcm-fiq.c index 920f945cb2f4..025d0d9494f4 100644 --- a/sound/soc/fsl/imx-pcm-fiq.c +++ b/sound/soc/fsl/imx-pcm-fiq.c | |||
@@ -299,8 +299,8 @@ int imx_pcm_fiq_init(struct platform_device *pdev) | |||
299 | 299 | ||
300 | imx_ssi_fiq_base = (unsigned long)ssi->base; | 300 | imx_ssi_fiq_base = (unsigned long)ssi->base; |
301 | 301 | ||
302 | ssi->dma_params_tx.burstsize = 4; | 302 | ssi->dma_params_tx.maxburst = 4; |
303 | ssi->dma_params_rx.burstsize = 6; | 303 | ssi->dma_params_rx.maxburst = 6; |
304 | 304 | ||
305 | ret = snd_soc_register_platform(&pdev->dev, &imx_soc_platform_fiq); | 305 | ret = snd_soc_register_platform(&pdev->dev, &imx_soc_platform_fiq); |
306 | if (ret) | 306 | if (ret) |
diff --git a/sound/soc/fsl/imx-pcm.c b/sound/soc/fsl/imx-pcm.c index 0d0625bfcb65..c49896442d8e 100644 --- a/sound/soc/fsl/imx-pcm.c +++ b/sound/soc/fsl/imx-pcm.c | |||
@@ -114,7 +114,11 @@ static int imx_pcm_probe(struct platform_device *pdev) | |||
114 | 114 | ||
115 | static int imx_pcm_remove(struct platform_device *pdev) | 115 | static int imx_pcm_remove(struct platform_device *pdev) |
116 | { | 116 | { |
117 | snd_soc_unregister_platform(&pdev->dev); | 117 | if (strcmp(pdev->id_entry->name, "imx-fiq-pcm-audio") == 0) |
118 | snd_soc_unregister_platform(&pdev->dev); | ||
119 | else | ||
120 | imx_pcm_dma_exit(pdev); | ||
121 | |||
118 | return 0; | 122 | return 0; |
119 | } | 123 | } |
120 | 124 | ||
diff --git a/sound/soc/fsl/imx-pcm.h b/sound/soc/fsl/imx-pcm.h index 5ae13a13a353..b7fa0d75c687 100644 --- a/sound/soc/fsl/imx-pcm.h +++ b/sound/soc/fsl/imx-pcm.h | |||
@@ -13,17 +13,24 @@ | |||
13 | #ifndef _IMX_PCM_H | 13 | #ifndef _IMX_PCM_H |
14 | #define _IMX_PCM_H | 14 | #define _IMX_PCM_H |
15 | 15 | ||
16 | #include <linux/platform_data/dma-imx.h> | ||
17 | |||
16 | /* | 18 | /* |
17 | * Do not change this as the FIQ handler depends on this size | 19 | * Do not change this as the FIQ handler depends on this size |
18 | */ | 20 | */ |
19 | #define IMX_SSI_DMABUF_SIZE (64 * 1024) | 21 | #define IMX_SSI_DMABUF_SIZE (64 * 1024) |
20 | 22 | ||
21 | struct imx_pcm_dma_params { | 23 | static inline void |
22 | int dma; | 24 | imx_pcm_dma_params_init_data(struct imx_dma_data *dma_data, |
23 | unsigned long dma_addr; | 25 | int dma, bool shared) |
24 | int burstsize; | 26 | { |
25 | bool shared_peripheral; /* The peripheral is on SPBA bus */ | 27 | dma_data->dma_request = dma; |
26 | }; | 28 | dma_data->priority = DMA_PRIO_HIGH; |
29 | if (shared) | ||
30 | dma_data->peripheral_type = IMX_DMATYPE_SSI_SP; | ||
31 | else | ||
32 | dma_data->peripheral_type = IMX_DMATYPE_SSI; | ||
33 | } | ||
27 | 34 | ||
28 | int snd_imx_pcm_mmap(struct snd_pcm_substream *substream, | 35 | int snd_imx_pcm_mmap(struct snd_pcm_substream *substream, |
29 | struct vm_area_struct *vma); | 36 | struct vm_area_struct *vma); |
@@ -32,11 +39,16 @@ void imx_pcm_free(struct snd_pcm *pcm); | |||
32 | 39 | ||
33 | #ifdef CONFIG_SND_SOC_IMX_PCM_DMA | 40 | #ifdef CONFIG_SND_SOC_IMX_PCM_DMA |
34 | int imx_pcm_dma_init(struct platform_device *pdev); | 41 | int imx_pcm_dma_init(struct platform_device *pdev); |
42 | void imx_pcm_dma_exit(struct platform_device *pdev); | ||
35 | #else | 43 | #else |
36 | static inline int imx_pcm_dma_init(struct platform_device *pdev) | 44 | static inline int imx_pcm_dma_init(struct platform_device *pdev) |
37 | { | 45 | { |
38 | return -ENODEV; | 46 | return -ENODEV; |
39 | } | 47 | } |
48 | |||
49 | static inline void imx_pcm_dma_exit(struct platform_device *pdev) | ||
50 | { | ||
51 | } | ||
40 | #endif | 52 | #endif |
41 | 53 | ||
42 | #ifdef CONFIG_SND_SOC_IMX_PCM_FIQ | 54 | #ifdef CONFIG_SND_SOC_IMX_PCM_FIQ |
diff --git a/sound/soc/fsl/imx-ssi.c b/sound/soc/fsl/imx-ssi.c index 810c7eeb7b03..9128b7b26ecf 100644 --- a/sound/soc/fsl/imx-ssi.c +++ b/sound/soc/fsl/imx-ssi.c | |||
@@ -232,23 +232,6 @@ static int imx_ssi_set_dai_clkdiv(struct snd_soc_dai *cpu_dai, | |||
232 | return 0; | 232 | return 0; |
233 | } | 233 | } |
234 | 234 | ||
235 | static int imx_ssi_startup(struct snd_pcm_substream *substream, | ||
236 | struct snd_soc_dai *cpu_dai) | ||
237 | { | ||
238 | struct imx_ssi *ssi = snd_soc_dai_get_drvdata(cpu_dai); | ||
239 | struct imx_pcm_dma_params *dma_data; | ||
240 | |||
241 | /* Tx/Rx config */ | ||
242 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) | ||
243 | dma_data = &ssi->dma_params_tx; | ||
244 | else | ||
245 | dma_data = &ssi->dma_params_rx; | ||
246 | |||
247 | snd_soc_dai_set_dma_data(cpu_dai, substream, dma_data); | ||
248 | |||
249 | return 0; | ||
250 | } | ||
251 | |||
252 | /* | 235 | /* |
253 | * Should only be called when port is inactive (i.e. SSIEN = 0), | 236 | * Should only be called when port is inactive (i.e. SSIEN = 0), |
254 | * although can be called multiple times by upper layers. | 237 | * although can be called multiple times by upper layers. |
@@ -353,7 +336,6 @@ static int imx_ssi_trigger(struct snd_pcm_substream *substream, int cmd, | |||
353 | } | 336 | } |
354 | 337 | ||
355 | static const struct snd_soc_dai_ops imx_ssi_pcm_dai_ops = { | 338 | static const struct snd_soc_dai_ops imx_ssi_pcm_dai_ops = { |
356 | .startup = imx_ssi_startup, | ||
357 | .hw_params = imx_ssi_hw_params, | 339 | .hw_params = imx_ssi_hw_params, |
358 | .set_fmt = imx_ssi_set_dai_fmt, | 340 | .set_fmt = imx_ssi_set_dai_fmt, |
359 | .set_clkdiv = imx_ssi_set_dai_clkdiv, | 341 | .set_clkdiv = imx_ssi_set_dai_clkdiv, |
@@ -369,10 +351,14 @@ static int imx_ssi_dai_probe(struct snd_soc_dai *dai) | |||
369 | 351 | ||
370 | snd_soc_dai_set_drvdata(dai, ssi); | 352 | snd_soc_dai_set_drvdata(dai, ssi); |
371 | 353 | ||
372 | val = SSI_SFCSR_TFWM0(ssi->dma_params_tx.burstsize) | | 354 | val = SSI_SFCSR_TFWM0(ssi->dma_params_tx.maxburst) | |
373 | SSI_SFCSR_RFWM0(ssi->dma_params_rx.burstsize); | 355 | SSI_SFCSR_RFWM0(ssi->dma_params_rx.maxburst); |
374 | writel(val, ssi->base + SSI_SFCSR); | 356 | writel(val, ssi->base + SSI_SFCSR); |
375 | 357 | ||
358 | /* Tx/Rx config */ | ||
359 | dai->playback_dma_data = &ssi->dma_params_tx; | ||
360 | dai->capture_dma_data = &ssi->dma_params_rx; | ||
361 | |||
376 | return 0; | 362 | return 0; |
377 | } | 363 | } |
378 | 364 | ||
@@ -575,19 +561,26 @@ static int imx_ssi_probe(struct platform_device *pdev) | |||
575 | 561 | ||
576 | writel(0x0, ssi->base + SSI_SIER); | 562 | writel(0x0, ssi->base + SSI_SIER); |
577 | 563 | ||
578 | ssi->dma_params_rx.dma_addr = res->start + SSI_SRX0; | 564 | ssi->dma_params_rx.addr = res->start + SSI_SRX0; |
579 | ssi->dma_params_tx.dma_addr = res->start + SSI_STX0; | 565 | ssi->dma_params_tx.addr = res->start + SSI_STX0; |
566 | |||
567 | ssi->dma_params_tx.maxburst = 6; | ||
568 | ssi->dma_params_rx.maxburst = 4; | ||
580 | 569 | ||
581 | ssi->dma_params_tx.burstsize = 6; | 570 | ssi->dma_params_tx.filter_data = &ssi->filter_data_tx; |
582 | ssi->dma_params_rx.burstsize = 4; | 571 | ssi->dma_params_rx.filter_data = &ssi->filter_data_rx; |
583 | 572 | ||
584 | res = platform_get_resource_byname(pdev, IORESOURCE_DMA, "tx0"); | 573 | res = platform_get_resource_byname(pdev, IORESOURCE_DMA, "tx0"); |
585 | if (res) | 574 | if (res) { |
586 | ssi->dma_params_tx.dma = res->start; | 575 | imx_pcm_dma_params_init_data(&ssi->filter_data_tx, res->start, |
576 | false); | ||
577 | } | ||
587 | 578 | ||
588 | res = platform_get_resource_byname(pdev, IORESOURCE_DMA, "rx0"); | 579 | res = platform_get_resource_byname(pdev, IORESOURCE_DMA, "rx0"); |
589 | if (res) | 580 | if (res) { |
590 | ssi->dma_params_rx.dma = res->start; | 581 | imx_pcm_dma_params_init_data(&ssi->filter_data_rx, res->start, |
582 | false); | ||
583 | } | ||
591 | 584 | ||
592 | platform_set_drvdata(pdev, ssi); | 585 | platform_set_drvdata(pdev, ssi); |
593 | 586 | ||
diff --git a/sound/soc/fsl/imx-ssi.h b/sound/soc/fsl/imx-ssi.h index dc114bdedce5..bb6b3dbb13fd 100644 --- a/sound/soc/fsl/imx-ssi.h +++ b/sound/soc/fsl/imx-ssi.h | |||
@@ -187,6 +187,7 @@ | |||
187 | 187 | ||
188 | #include <linux/dmaengine.h> | 188 | #include <linux/dmaengine.h> |
189 | #include <linux/platform_data/dma-imx.h> | 189 | #include <linux/platform_data/dma-imx.h> |
190 | #include <sound/dmaengine_pcm.h> | ||
190 | #include "imx-pcm.h" | 191 | #include "imx-pcm.h" |
191 | 192 | ||
192 | struct imx_ssi { | 193 | struct imx_ssi { |
@@ -204,8 +205,10 @@ struct imx_ssi { | |||
204 | void (*ac97_reset) (struct snd_ac97 *ac97); | 205 | void (*ac97_reset) (struct snd_ac97 *ac97); |
205 | void (*ac97_warm_reset)(struct snd_ac97 *ac97); | 206 | void (*ac97_warm_reset)(struct snd_ac97 *ac97); |
206 | 207 | ||
207 | struct imx_pcm_dma_params dma_params_rx; | 208 | struct snd_dmaengine_dai_dma_data dma_params_rx; |
208 | struct imx_pcm_dma_params dma_params_tx; | 209 | struct snd_dmaengine_dai_dma_data dma_params_tx; |
210 | struct imx_dma_data filter_data_tx; | ||
211 | struct imx_dma_data filter_data_rx; | ||
209 | 212 | ||
210 | int enabled; | 213 | int enabled; |
211 | 214 | ||
diff --git a/sound/soc/mxs/mxs-pcm.c b/sound/soc/mxs/mxs-pcm.c index 564b5b60319d..7bceb16d0fd9 100644 --- a/sound/soc/mxs/mxs-pcm.c +++ b/sound/soc/mxs/mxs-pcm.c | |||
@@ -28,7 +28,6 @@ | |||
28 | #include <linux/platform_device.h> | 28 | #include <linux/platform_device.h> |
29 | #include <linux/slab.h> | 29 | #include <linux/slab.h> |
30 | #include <linux/dmaengine.h> | 30 | #include <linux/dmaengine.h> |
31 | #include <linux/fsl/mxs-dma.h> | ||
32 | 31 | ||
33 | #include <sound/core.h> | 32 | #include <sound/core.h> |
34 | #include <sound/initval.h> | 33 | #include <sound/initval.h> |
@@ -39,11 +38,6 @@ | |||
39 | 38 | ||
40 | #include "mxs-pcm.h" | 39 | #include "mxs-pcm.h" |
41 | 40 | ||
42 | struct mxs_pcm_dma_data { | ||
43 | struct mxs_dma_data dma_data; | ||
44 | struct mxs_pcm_dma_params *dma_params; | ||
45 | }; | ||
46 | |||
47 | static struct snd_pcm_hardware snd_mxs_hardware = { | 41 | static struct snd_pcm_hardware snd_mxs_hardware = { |
48 | .info = SNDRV_PCM_INFO_MMAP | | 42 | .info = SNDRV_PCM_INFO_MMAP | |
49 | SNDRV_PCM_INFO_MMAP_VALID | | 43 | SNDRV_PCM_INFO_MMAP_VALID | |
@@ -66,8 +60,7 @@ static struct snd_pcm_hardware snd_mxs_hardware = { | |||
66 | 60 | ||
67 | static bool filter(struct dma_chan *chan, void *param) | 61 | static bool filter(struct dma_chan *chan, void *param) |
68 | { | 62 | { |
69 | struct mxs_pcm_dma_data *pcm_dma_data = param; | 63 | struct mxs_pcm_dma_params *dma_params = param; |
70 | struct mxs_pcm_dma_params *dma_params = pcm_dma_data->dma_params; | ||
71 | 64 | ||
72 | if (!mxs_dma_is_apbx(chan)) | 65 | if (!mxs_dma_is_apbx(chan)) |
73 | return false; | 66 | return false; |
@@ -75,7 +68,7 @@ static bool filter(struct dma_chan *chan, void *param) | |||
75 | if (chan->chan_id != dma_params->chan_num) | 68 | if (chan->chan_id != dma_params->chan_num) |
76 | return false; | 69 | return false; |
77 | 70 | ||
78 | chan->private = &pcm_dma_data->dma_data; | 71 | chan->private = &dma_params->dma_data; |
79 | 72 | ||
80 | return true; | 73 | return true; |
81 | } | 74 | } |
@@ -91,37 +84,11 @@ static int snd_mxs_pcm_hw_params(struct snd_pcm_substream *substream, | |||
91 | static int snd_mxs_open(struct snd_pcm_substream *substream) | 84 | static int snd_mxs_open(struct snd_pcm_substream *substream) |
92 | { | 85 | { |
93 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | 86 | 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 | 87 | ||
110 | snd_soc_set_runtime_hwparams(substream, &snd_mxs_hardware); | 88 | snd_soc_set_runtime_hwparams(substream, &snd_mxs_hardware); |
111 | 89 | ||
112 | snd_dmaengine_pcm_set_data(substream, pcm_dma_data); | 90 | return snd_dmaengine_pcm_open_request_chan(substream, filter, |
113 | 91 | snd_soc_dai_get_dma_data(rtd->cpu_dai, substream)); | |
114 | return 0; | ||
115 | } | ||
116 | |||
117 | static 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 | } | 92 | } |
126 | 93 | ||
127 | static int snd_mxs_pcm_mmap(struct snd_pcm_substream *substream, | 94 | static int snd_mxs_pcm_mmap(struct snd_pcm_substream *substream, |
@@ -137,7 +104,7 @@ static int snd_mxs_pcm_mmap(struct snd_pcm_substream *substream, | |||
137 | 104 | ||
138 | static struct snd_pcm_ops mxs_pcm_ops = { | 105 | static struct snd_pcm_ops mxs_pcm_ops = { |
139 | .open = snd_mxs_open, | 106 | .open = snd_mxs_open, |
140 | .close = snd_mxs_close, | 107 | .close = snd_dmaengine_pcm_close_release_chan, |
141 | .ioctl = snd_pcm_lib_ioctl, | 108 | .ioctl = snd_pcm_lib_ioctl, |
142 | .hw_params = snd_mxs_pcm_hw_params, | 109 | .hw_params = snd_mxs_pcm_hw_params, |
143 | .trigger = snd_dmaengine_pcm_trigger, | 110 | .trigger = snd_dmaengine_pcm_trigger, |
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 | |||
22 | struct mxs_pcm_dma_params { | 24 | struct 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 3a2aa1d19b93..f13bd8730b0f 100644 --- a/sound/soc/mxs/mxs-saif.c +++ b/sound/soc/mxs/mxs-saif.c | |||
@@ -753,9 +753,9 @@ static int mxs_saif_probe(struct platform_device *pdev) | |||
753 | return ret; | 753 | return ret; |
754 | } | 754 | } |
755 | 755 | ||
756 | saif->dma_param.chan_irq = platform_get_irq(pdev, 1); | 756 | saif->dma_param.dma_data.chan_irq = platform_get_irq(pdev, 1); |
757 | if (saif->dma_param.chan_irq < 0) { | 757 | if (saif->dma_param.dma_data.chan_irq < 0) { |
758 | ret = saif->dma_param.chan_irq; | 758 | ret = saif->dma_param.dma_data.chan_irq; |
759 | dev_err(&pdev->dev, "failed to get dma irq resource: %d\n", | 759 | dev_err(&pdev->dev, "failed to get dma irq resource: %d\n", |
760 | ret); | 760 | ret); |
761 | return ret; | 761 | return ret; |
diff --git a/sound/soc/omap/am3517evm.c b/sound/soc/omap/am3517evm.c index c1900b2a6f28..994dcf345975 100644 --- a/sound/soc/omap/am3517evm.c +++ b/sound/soc/omap/am3517evm.c | |||
@@ -28,7 +28,6 @@ | |||
28 | #include <linux/platform_data/asoc-ti-mcbsp.h> | 28 | #include <linux/platform_data/asoc-ti-mcbsp.h> |
29 | 29 | ||
30 | #include "omap-mcbsp.h" | 30 | #include "omap-mcbsp.h" |
31 | #include "omap-pcm.h" | ||
32 | 31 | ||
33 | #include "../codecs/tlv320aic23.h" | 32 | #include "../codecs/tlv320aic23.h" |
34 | 33 | ||
diff --git a/sound/soc/omap/ams-delta.c b/sound/soc/omap/ams-delta.c index 2600447fa74f..629446482a91 100644 --- a/sound/soc/omap/ams-delta.c +++ b/sound/soc/omap/ams-delta.c | |||
@@ -36,7 +36,6 @@ | |||
36 | #include <linux/platform_data/asoc-ti-mcbsp.h> | 36 | #include <linux/platform_data/asoc-ti-mcbsp.h> |
37 | 37 | ||
38 | #include "omap-mcbsp.h" | 38 | #include "omap-mcbsp.h" |
39 | #include "omap-pcm.h" | ||
40 | #include "../codecs/cx20442.h" | 39 | #include "../codecs/cx20442.h" |
41 | 40 | ||
42 | 41 | ||
diff --git a/sound/soc/omap/mcbsp.c b/sound/soc/omap/mcbsp.c index 285c8368cb47..eb68c7db1cf3 100644 --- a/sound/soc/omap/mcbsp.c +++ b/sound/soc/omap/mcbsp.c | |||
@@ -1018,9 +1018,10 @@ int omap_mcbsp_init(struct platform_device *pdev) | |||
1018 | return -ENODEV; | 1018 | return -ENODEV; |
1019 | } | 1019 | } |
1020 | /* RX DMA request number, and port address configuration */ | 1020 | /* RX DMA request number, and port address configuration */ |
1021 | mcbsp->dma_data[1].name = "Audio Capture"; | 1021 | mcbsp->dma_req[1] = res->start; |
1022 | mcbsp->dma_data[1].dma_req = res->start; | 1022 | mcbsp->dma_data[1].filter_data = &mcbsp->dma_req[1]; |
1023 | mcbsp->dma_data[1].port_addr = omap_mcbsp_dma_reg_params(mcbsp, 1); | 1023 | mcbsp->dma_data[1].addr = omap_mcbsp_dma_reg_params(mcbsp, 1); |
1024 | mcbsp->dma_data[1].maxburst = 4; | ||
1024 | 1025 | ||
1025 | res = platform_get_resource_byname(pdev, IORESOURCE_DMA, "tx"); | 1026 | res = platform_get_resource_byname(pdev, IORESOURCE_DMA, "tx"); |
1026 | if (!res) { | 1027 | if (!res) { |
@@ -1028,9 +1029,10 @@ int omap_mcbsp_init(struct platform_device *pdev) | |||
1028 | return -ENODEV; | 1029 | return -ENODEV; |
1029 | } | 1030 | } |
1030 | /* TX DMA request number, and port address configuration */ | 1031 | /* TX DMA request number, and port address configuration */ |
1031 | mcbsp->dma_data[0].name = "Audio Playback"; | 1032 | mcbsp->dma_req[0] = res->start; |
1032 | mcbsp->dma_data[0].dma_req = res->start; | 1033 | mcbsp->dma_data[0].filter_data = &mcbsp->dma_req[0]; |
1033 | mcbsp->dma_data[0].port_addr = omap_mcbsp_dma_reg_params(mcbsp, 0); | 1034 | mcbsp->dma_data[0].addr = omap_mcbsp_dma_reg_params(mcbsp, 0); |
1035 | mcbsp->dma_data[0].maxburst = 4; | ||
1034 | 1036 | ||
1035 | mcbsp->fclk = clk_get(&pdev->dev, "fck"); | 1037 | mcbsp->fclk = clk_get(&pdev->dev, "fck"); |
1036 | if (IS_ERR(mcbsp->fclk)) { | 1038 | if (IS_ERR(mcbsp->fclk)) { |
diff --git a/sound/soc/omap/mcbsp.h b/sound/soc/omap/mcbsp.h index f93e0b0af303..96d1b086bcf8 100644 --- a/sound/soc/omap/mcbsp.h +++ b/sound/soc/omap/mcbsp.h | |||
@@ -24,14 +24,14 @@ | |||
24 | #ifndef __ASOC_MCBSP_H | 24 | #ifndef __ASOC_MCBSP_H |
25 | #define __ASOC_MCBSP_H | 25 | #define __ASOC_MCBSP_H |
26 | 26 | ||
27 | #include "omap-pcm.h" | ||
28 | |||
29 | #ifdef CONFIG_ARCH_OMAP1 | 27 | #ifdef CONFIG_ARCH_OMAP1 |
30 | #define mcbsp_omap1() 1 | 28 | #define mcbsp_omap1() 1 |
31 | #else | 29 | #else |
32 | #define mcbsp_omap1() 0 | 30 | #define mcbsp_omap1() 0 |
33 | #endif | 31 | #endif |
34 | 32 | ||
33 | #include <sound/dmaengine_pcm.h> | ||
34 | |||
35 | /* McBSP register numbers. Register address offset = num * reg_step */ | 35 | /* McBSP register numbers. Register address offset = num * reg_step */ |
36 | enum { | 36 | enum { |
37 | /* Common registers */ | 37 | /* Common registers */ |
@@ -312,7 +312,8 @@ struct omap_mcbsp { | |||
312 | struct omap_mcbsp_platform_data *pdata; | 312 | struct omap_mcbsp_platform_data *pdata; |
313 | struct omap_mcbsp_st_data *st_data; | 313 | struct omap_mcbsp_st_data *st_data; |
314 | struct omap_mcbsp_reg_cfg cfg_regs; | 314 | struct omap_mcbsp_reg_cfg cfg_regs; |
315 | struct omap_pcm_dma_data dma_data[2]; | 315 | struct snd_dmaengine_dai_dma_data dma_data[2]; |
316 | unsigned int dma_req[2]; | ||
316 | int dma_op_mode; | 317 | int dma_op_mode; |
317 | u16 max_tx_thres; | 318 | u16 max_tx_thres; |
318 | u16 max_rx_thres; | 319 | u16 max_rx_thres; |
diff --git a/sound/soc/omap/n810.c b/sound/soc/omap/n810.c index ee7cd53aa3ee..5e8d640d314f 100644 --- a/sound/soc/omap/n810.c +++ b/sound/soc/omap/n810.c | |||
@@ -34,7 +34,6 @@ | |||
34 | #include <linux/platform_data/asoc-ti-mcbsp.h> | 34 | #include <linux/platform_data/asoc-ti-mcbsp.h> |
35 | 35 | ||
36 | #include "omap-mcbsp.h" | 36 | #include "omap-mcbsp.h" |
37 | #include "omap-pcm.h" | ||
38 | 37 | ||
39 | #define N810_HEADSET_AMP_GPIO 10 | 38 | #define N810_HEADSET_AMP_GPIO 10 |
40 | #define N810_SPEAKER_AMP_GPIO 101 | 39 | #define N810_SPEAKER_AMP_GPIO 101 |
diff --git a/sound/soc/omap/omap-abe-twl6040.c b/sound/soc/omap/omap-abe-twl6040.c index e7d93fa412a9..70cd5c7b2e14 100644 --- a/sound/soc/omap/omap-abe-twl6040.c +++ b/sound/soc/omap/omap-abe-twl6040.c | |||
@@ -34,7 +34,6 @@ | |||
34 | 34 | ||
35 | #include "omap-dmic.h" | 35 | #include "omap-dmic.h" |
36 | #include "omap-mcpdm.h" | 36 | #include "omap-mcpdm.h" |
37 | #include "omap-pcm.h" | ||
38 | #include "../codecs/twl6040.h" | 37 | #include "../codecs/twl6040.h" |
39 | 38 | ||
40 | struct abe_twl6040 { | 39 | struct abe_twl6040 { |
diff --git a/sound/soc/omap/omap-dmic.c b/sound/soc/omap/omap-dmic.c index ba49ccd9eed9..a2597fab33a3 100644 --- a/sound/soc/omap/omap-dmic.c +++ b/sound/soc/omap/omap-dmic.c | |||
@@ -39,8 +39,8 @@ | |||
39 | #include <sound/pcm_params.h> | 39 | #include <sound/pcm_params.h> |
40 | #include <sound/initval.h> | 40 | #include <sound/initval.h> |
41 | #include <sound/soc.h> | 41 | #include <sound/soc.h> |
42 | #include <sound/dmaengine_pcm.h> | ||
42 | 43 | ||
43 | #include "omap-pcm.h" | ||
44 | #include "omap-dmic.h" | 44 | #include "omap-dmic.h" |
45 | 45 | ||
46 | struct omap_dmic { | 46 | struct omap_dmic { |
@@ -55,13 +55,9 @@ struct omap_dmic { | |||
55 | u32 ch_enabled; | 55 | u32 ch_enabled; |
56 | bool active; | 56 | bool active; |
57 | struct mutex mutex; | 57 | struct mutex mutex; |
58 | }; | ||
59 | 58 | ||
60 | /* | 59 | struct snd_dmaengine_dai_dma_data dma_data; |
61 | * Stream DMA parameters | 60 | unsigned int dma_req; |
62 | */ | ||
63 | static struct omap_pcm_dma_data omap_dmic_dai_dma_params = { | ||
64 | .name = "DMIC capture", | ||
65 | }; | 61 | }; |
66 | 62 | ||
67 | static inline void omap_dmic_write(struct omap_dmic *dmic, u16 reg, u32 val) | 63 | static inline void omap_dmic_write(struct omap_dmic *dmic, u16 reg, u32 val) |
@@ -118,7 +114,7 @@ static int omap_dmic_dai_startup(struct snd_pcm_substream *substream, | |||
118 | 114 | ||
119 | mutex_unlock(&dmic->mutex); | 115 | mutex_unlock(&dmic->mutex); |
120 | 116 | ||
121 | snd_soc_dai_set_dma_data(dai, substream, &omap_dmic_dai_dma_params); | 117 | snd_soc_dai_set_dma_data(dai, substream, &dmic->dma_data); |
122 | return ret; | 118 | return ret; |
123 | } | 119 | } |
124 | 120 | ||
@@ -203,7 +199,7 @@ static int omap_dmic_dai_hw_params(struct snd_pcm_substream *substream, | |||
203 | struct snd_soc_dai *dai) | 199 | struct snd_soc_dai *dai) |
204 | { | 200 | { |
205 | struct omap_dmic *dmic = snd_soc_dai_get_drvdata(dai); | 201 | struct omap_dmic *dmic = snd_soc_dai_get_drvdata(dai); |
206 | struct omap_pcm_dma_data *dma_data; | 202 | struct snd_dmaengine_dai_dma_data *dma_data; |
207 | int channels; | 203 | int channels; |
208 | 204 | ||
209 | dmic->clk_div = omap_dmic_select_divider(dmic, params_rate(params)); | 205 | dmic->clk_div = omap_dmic_select_divider(dmic, params_rate(params)); |
@@ -230,7 +226,7 @@ static int omap_dmic_dai_hw_params(struct snd_pcm_substream *substream, | |||
230 | 226 | ||
231 | /* packet size is threshold * channels */ | 227 | /* packet size is threshold * channels */ |
232 | dma_data = snd_soc_dai_get_dma_data(dai, substream); | 228 | dma_data = snd_soc_dai_get_dma_data(dai, substream); |
233 | dma_data->packet_size = dmic->threshold * channels; | 229 | dma_data->maxburst = dmic->threshold * channels; |
234 | 230 | ||
235 | return 0; | 231 | return 0; |
236 | } | 232 | } |
@@ -476,7 +472,7 @@ static int asoc_dmic_probe(struct platform_device *pdev) | |||
476 | ret = -ENODEV; | 472 | ret = -ENODEV; |
477 | goto err_put_clk; | 473 | goto err_put_clk; |
478 | } | 474 | } |
479 | omap_dmic_dai_dma_params.port_addr = res->start + OMAP_DMIC_DATA_REG; | 475 | dmic->dma_data.addr = res->start + OMAP_DMIC_DATA_REG; |
480 | 476 | ||
481 | res = platform_get_resource(pdev, IORESOURCE_DMA, 0); | 477 | res = platform_get_resource(pdev, IORESOURCE_DMA, 0); |
482 | if (!res) { | 478 | if (!res) { |
@@ -484,7 +480,9 @@ static int asoc_dmic_probe(struct platform_device *pdev) | |||
484 | ret = -ENODEV; | 480 | ret = -ENODEV; |
485 | goto err_put_clk; | 481 | goto err_put_clk; |
486 | } | 482 | } |
487 | omap_dmic_dai_dma_params.dma_req = res->start; | 483 | |
484 | dmic->dma_req = res->start; | ||
485 | dmic->dma_data.filter_data = &dmic->dma_req; | ||
488 | 486 | ||
489 | res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "mpu"); | 487 | res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "mpu"); |
490 | if (!res) { | 488 | if (!res) { |
@@ -493,19 +491,9 @@ static int asoc_dmic_probe(struct platform_device *pdev) | |||
493 | goto err_put_clk; | 491 | goto err_put_clk; |
494 | } | 492 | } |
495 | 493 | ||
496 | if (!devm_request_mem_region(&pdev->dev, res->start, | 494 | dmic->io_base = devm_ioremap_resource(&pdev->dev, res); |
497 | resource_size(res), pdev->name)) { | 495 | if (IS_ERR(dmic->io_base)) |
498 | dev_err(dmic->dev, "memory region already claimed\n"); | 496 | return PTR_ERR(dmic->io_base); |
499 | ret = -ENODEV; | ||
500 | goto err_put_clk; | ||
501 | } | ||
502 | |||
503 | dmic->io_base = devm_ioremap(&pdev->dev, res->start, | ||
504 | resource_size(res)); | ||
505 | if (!dmic->io_base) { | ||
506 | ret = -ENOMEM; | ||
507 | goto err_put_clk; | ||
508 | } | ||
509 | 497 | ||
510 | ret = snd_soc_register_dai(&pdev->dev, &omap_dmic_dai); | 498 | ret = snd_soc_register_dai(&pdev->dev, &omap_dmic_dai); |
511 | if (ret) | 499 | if (ret) |
diff --git a/sound/soc/omap/omap-hdmi.c b/sound/soc/omap/omap-hdmi.c index 32fa840c493e..b4bfab9f33e8 100644 --- a/sound/soc/omap/omap-hdmi.c +++ b/sound/soc/omap/omap-hdmi.c | |||
@@ -32,15 +32,16 @@ | |||
32 | #include <sound/soc.h> | 32 | #include <sound/soc.h> |
33 | #include <sound/asound.h> | 33 | #include <sound/asound.h> |
34 | #include <sound/asoundef.h> | 34 | #include <sound/asoundef.h> |
35 | #include <sound/dmaengine_pcm.h> | ||
35 | #include <video/omapdss.h> | 36 | #include <video/omapdss.h> |
36 | 37 | ||
37 | #include "omap-pcm.h" | ||
38 | #include "omap-hdmi.h" | 38 | #include "omap-hdmi.h" |
39 | 39 | ||
40 | #define DRV_NAME "omap-hdmi-audio-dai" | 40 | #define DRV_NAME "omap-hdmi-audio-dai" |
41 | 41 | ||
42 | struct hdmi_priv { | 42 | struct hdmi_priv { |
43 | struct omap_pcm_dma_data dma_params; | 43 | struct snd_dmaengine_dai_dma_data dma_data; |
44 | unsigned int dma_req; | ||
44 | struct omap_dss_audio dss_audio; | 45 | struct omap_dss_audio dss_audio; |
45 | struct snd_aes_iec958 iec; | 46 | struct snd_aes_iec958 iec; |
46 | struct snd_cea_861_aud_if cea; | 47 | struct snd_cea_861_aud_if cea; |
@@ -68,7 +69,7 @@ static int omap_hdmi_dai_startup(struct snd_pcm_substream *substream, | |||
68 | return -ENODEV; | 69 | return -ENODEV; |
69 | } | 70 | } |
70 | 71 | ||
71 | snd_soc_dai_set_dma_data(dai, substream, &priv->dma_params); | 72 | snd_soc_dai_set_dma_data(dai, substream, &priv->dma_data); |
72 | 73 | ||
73 | return 0; | 74 | return 0; |
74 | } | 75 | } |
@@ -88,25 +89,20 @@ static int omap_hdmi_dai_hw_params(struct snd_pcm_substream *substream, | |||
88 | struct hdmi_priv *priv = snd_soc_dai_get_drvdata(dai); | 89 | struct hdmi_priv *priv = snd_soc_dai_get_drvdata(dai); |
89 | struct snd_aes_iec958 *iec = &priv->iec; | 90 | struct snd_aes_iec958 *iec = &priv->iec; |
90 | struct snd_cea_861_aud_if *cea = &priv->cea; | 91 | struct snd_cea_861_aud_if *cea = &priv->cea; |
91 | struct omap_pcm_dma_data *dma_data; | ||
92 | int err = 0; | 92 | int err = 0; |
93 | 93 | ||
94 | dma_data = snd_soc_dai_get_dma_data(dai, substream); | ||
95 | |||
96 | switch (params_format(params)) { | 94 | switch (params_format(params)) { |
97 | case SNDRV_PCM_FORMAT_S16_LE: | 95 | case SNDRV_PCM_FORMAT_S16_LE: |
98 | dma_data->packet_size = 16; | 96 | priv->dma_data.maxburst = 16; |
99 | break; | 97 | break; |
100 | case SNDRV_PCM_FORMAT_S24_LE: | 98 | case SNDRV_PCM_FORMAT_S24_LE: |
101 | dma_data->packet_size = 32; | 99 | priv->dma_data.maxburst = 32; |
102 | break; | 100 | break; |
103 | default: | 101 | default: |
104 | dev_err(dai->dev, "format not supported!\n"); | 102 | dev_err(dai->dev, "format not supported!\n"); |
105 | return -EINVAL; | 103 | return -EINVAL; |
106 | } | 104 | } |
107 | 105 | ||
108 | dma_data->data_type = 32; | ||
109 | |||
110 | /* | 106 | /* |
111 | * fill the IEC-60958 channel status word | 107 | * fill the IEC-60958 channel status word |
112 | */ | 108 | */ |
@@ -283,8 +279,7 @@ static int omap_hdmi_probe(struct platform_device *pdev) | |||
283 | return -ENODEV; | 279 | return -ENODEV; |
284 | } | 280 | } |
285 | 281 | ||
286 | hdmi_data->dma_params.port_addr = hdmi_rsrc->start | 282 | hdmi_data->dma_data.addr = hdmi_rsrc->start + OMAP_HDMI_AUDIO_DMA_PORT; |
287 | + OMAP_HDMI_AUDIO_DMA_PORT; | ||
288 | 283 | ||
289 | hdmi_rsrc = platform_get_resource(pdev, IORESOURCE_DMA, 0); | 284 | hdmi_rsrc = platform_get_resource(pdev, IORESOURCE_DMA, 0); |
290 | if (!hdmi_rsrc) { | 285 | if (!hdmi_rsrc) { |
@@ -292,8 +287,9 @@ static int omap_hdmi_probe(struct platform_device *pdev) | |||
292 | return -ENODEV; | 287 | return -ENODEV; |
293 | } | 288 | } |
294 | 289 | ||
295 | hdmi_data->dma_params.dma_req = hdmi_rsrc->start; | 290 | hdmi_data->dma_req = hdmi_rsrc->start; |
296 | hdmi_data->dma_params.name = "HDMI playback"; | 291 | hdmi_data->dma_data.filter_data = &hdmi_data->dma_req; |
292 | hdmi_data->dma_data.addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES; | ||
297 | 293 | ||
298 | /* | 294 | /* |
299 | * TODO: We assume that there is only one DSS HDMI device. Future | 295 | * TODO: We assume that there is only one DSS HDMI device. Future |
diff --git a/sound/soc/omap/omap-mcbsp.c b/sound/soc/omap/omap-mcbsp.c index 8d2defd6fdbe..1e7b3e89e04f 100644 --- a/sound/soc/omap/omap-mcbsp.c +++ b/sound/soc/omap/omap-mcbsp.c | |||
@@ -33,11 +33,11 @@ | |||
33 | #include <sound/pcm_params.h> | 33 | #include <sound/pcm_params.h> |
34 | #include <sound/initval.h> | 34 | #include <sound/initval.h> |
35 | #include <sound/soc.h> | 35 | #include <sound/soc.h> |
36 | #include <sound/dmaengine_pcm.h> | ||
36 | 37 | ||
37 | #include <linux/platform_data/asoc-ti-mcbsp.h> | 38 | #include <linux/platform_data/asoc-ti-mcbsp.h> |
38 | #include "mcbsp.h" | 39 | #include "mcbsp.h" |
39 | #include "omap-mcbsp.h" | 40 | #include "omap-mcbsp.h" |
40 | #include "omap-pcm.h" | ||
41 | 41 | ||
42 | #define OMAP_MCBSP_RATES (SNDRV_PCM_RATE_8000_96000) | 42 | #define OMAP_MCBSP_RATES (SNDRV_PCM_RATE_8000_96000) |
43 | 43 | ||
@@ -62,24 +62,22 @@ enum { | |||
62 | * Stream DMA parameters. DMA request line and port address are set runtime | 62 | * Stream DMA parameters. DMA request line and port address are set runtime |
63 | * since they are different between OMAP1 and later OMAPs | 63 | * since they are different between OMAP1 and later OMAPs |
64 | */ | 64 | */ |
65 | static void omap_mcbsp_set_threshold(struct snd_pcm_substream *substream) | 65 | static void omap_mcbsp_set_threshold(struct snd_pcm_substream *substream, |
66 | unsigned int packet_size) | ||
66 | { | 67 | { |
67 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | 68 | struct snd_soc_pcm_runtime *rtd = substream->private_data; |
68 | struct snd_soc_dai *cpu_dai = rtd->cpu_dai; | 69 | struct snd_soc_dai *cpu_dai = rtd->cpu_dai; |
69 | struct omap_mcbsp *mcbsp = snd_soc_dai_get_drvdata(cpu_dai); | 70 | struct omap_mcbsp *mcbsp = snd_soc_dai_get_drvdata(cpu_dai); |
70 | struct omap_pcm_dma_data *dma_data; | ||
71 | int words; | 71 | int words; |
72 | 72 | ||
73 | dma_data = snd_soc_dai_get_dma_data(rtd->cpu_dai, substream); | ||
74 | |||
75 | /* | 73 | /* |
76 | * Configure McBSP threshold based on either: | 74 | * Configure McBSP threshold based on either: |
77 | * packet_size, when the sDMA is in packet mode, or based on the | 75 | * packet_size, when the sDMA is in packet mode, or based on the |
78 | * period size in THRESHOLD mode, otherwise use McBSP threshold = 1 | 76 | * period size in THRESHOLD mode, otherwise use McBSP threshold = 1 |
79 | * for mono streams. | 77 | * for mono streams. |
80 | */ | 78 | */ |
81 | if (dma_data->packet_size) | 79 | if (packet_size) |
82 | words = dma_data->packet_size; | 80 | words = packet_size; |
83 | else | 81 | else |
84 | words = 1; | 82 | words = 1; |
85 | 83 | ||
@@ -226,7 +224,7 @@ static int omap_mcbsp_dai_hw_params(struct snd_pcm_substream *substream, | |||
226 | { | 224 | { |
227 | struct omap_mcbsp *mcbsp = snd_soc_dai_get_drvdata(cpu_dai); | 225 | struct omap_mcbsp *mcbsp = snd_soc_dai_get_drvdata(cpu_dai); |
228 | struct omap_mcbsp_reg_cfg *regs = &mcbsp->cfg_regs; | 226 | struct omap_mcbsp_reg_cfg *regs = &mcbsp->cfg_regs; |
229 | struct omap_pcm_dma_data *dma_data; | 227 | struct snd_dmaengine_dai_dma_data *dma_data; |
230 | int wlen, channels, wpf; | 228 | int wlen, channels, wpf; |
231 | int pkt_size = 0; | 229 | int pkt_size = 0; |
232 | unsigned int format, div, framesize, master; | 230 | unsigned int format, div, framesize, master; |
@@ -245,7 +243,6 @@ static int omap_mcbsp_dai_hw_params(struct snd_pcm_substream *substream, | |||
245 | return -EINVAL; | 243 | return -EINVAL; |
246 | } | 244 | } |
247 | if (mcbsp->pdata->buffer_size) { | 245 | if (mcbsp->pdata->buffer_size) { |
248 | dma_data->set_threshold = omap_mcbsp_set_threshold; | ||
249 | if (mcbsp->dma_op_mode == MCBSP_DMA_MODE_THRESHOLD) { | 246 | if (mcbsp->dma_op_mode == MCBSP_DMA_MODE_THRESHOLD) { |
250 | int period_words, max_thrsh; | 247 | int period_words, max_thrsh; |
251 | int divider = 0; | 248 | int divider = 0; |
@@ -276,9 +273,10 @@ static int omap_mcbsp_dai_hw_params(struct snd_pcm_substream *substream, | |||
276 | /* Use packet mode for non mono streams */ | 273 | /* Use packet mode for non mono streams */ |
277 | pkt_size = channels; | 274 | pkt_size = channels; |
278 | } | 275 | } |
276 | omap_mcbsp_set_threshold(substream, pkt_size); | ||
279 | } | 277 | } |
280 | 278 | ||
281 | dma_data->packet_size = pkt_size; | 279 | dma_data->maxburst = pkt_size; |
282 | 280 | ||
283 | if (mcbsp->configured) { | 281 | if (mcbsp->configured) { |
284 | /* McBSP already configured by another stream */ | 282 | /* McBSP already configured by another stream */ |
diff --git a/sound/soc/omap/omap-mcpdm.c b/sound/soc/omap/omap-mcpdm.c index 5ca11bdac21e..49f102a1dbae 100644 --- a/sound/soc/omap/omap-mcpdm.c +++ b/sound/soc/omap/omap-mcpdm.c | |||
@@ -39,11 +39,14 @@ | |||
39 | #include <sound/pcm.h> | 39 | #include <sound/pcm.h> |
40 | #include <sound/pcm_params.h> | 40 | #include <sound/pcm_params.h> |
41 | #include <sound/soc.h> | 41 | #include <sound/soc.h> |
42 | #include <sound/dmaengine_pcm.h> | ||
42 | 43 | ||
43 | #include "omap-mcpdm.h" | 44 | #include "omap-mcpdm.h" |
44 | #include "omap-pcm.h" | ||
45 | 45 | ||
46 | #define OMAP44XX_MCPDM_L3_BASE 0x49032000 | 46 | struct mcpdm_link_config { |
47 | u32 link_mask; /* channel mask for the direction */ | ||
48 | u32 threshold; /* FIFO threshold */ | ||
49 | }; | ||
47 | 50 | ||
48 | struct omap_mcpdm { | 51 | struct omap_mcpdm { |
49 | struct device *dev; | 52 | struct device *dev; |
@@ -53,29 +56,22 @@ struct omap_mcpdm { | |||
53 | 56 | ||
54 | struct mutex mutex; | 57 | struct mutex mutex; |
55 | 58 | ||
56 | /* channel data */ | 59 | /* Playback/Capture configuration */ |
57 | u32 dn_channels; | 60 | struct mcpdm_link_config config[2]; |
58 | u32 up_channels; | ||
59 | |||
60 | /* McPDM FIFO thresholds */ | ||
61 | u32 dn_threshold; | ||
62 | u32 up_threshold; | ||
63 | 61 | ||
64 | /* McPDM dn offsets for rx1, and 2 channels */ | 62 | /* McPDM dn offsets for rx1, and 2 channels */ |
65 | u32 dn_rx_offset; | 63 | u32 dn_rx_offset; |
64 | |||
65 | /* McPDM needs to be restarted due to runtime reconfiguration */ | ||
66 | bool restart; | ||
67 | |||
68 | struct snd_dmaengine_dai_dma_data dma_data[2]; | ||
69 | unsigned int dma_req[2]; | ||
66 | }; | 70 | }; |
67 | 71 | ||
68 | /* | 72 | /* |
69 | * Stream DMA parameters | 73 | * Stream DMA parameters |
70 | */ | 74 | */ |
71 | static struct omap_pcm_dma_data omap_mcpdm_dai_dma_params[] = { | ||
72 | { | ||
73 | .name = "Audio playback", | ||
74 | }, | ||
75 | { | ||
76 | .name = "Audio capture", | ||
77 | }, | ||
78 | }; | ||
79 | 75 | ||
80 | static inline void omap_mcpdm_write(struct omap_mcpdm *mcpdm, u16 reg, u32 val) | 76 | static inline void omap_mcpdm_write(struct omap_mcpdm *mcpdm, u16 reg, u32 val) |
81 | { | 77 | { |
@@ -130,11 +126,12 @@ static void omap_mcpdm_reg_dump(struct omap_mcpdm *mcpdm) {} | |||
130 | static void omap_mcpdm_start(struct omap_mcpdm *mcpdm) | 126 | static void omap_mcpdm_start(struct omap_mcpdm *mcpdm) |
131 | { | 127 | { |
132 | u32 ctrl = omap_mcpdm_read(mcpdm, MCPDM_REG_CTRL); | 128 | u32 ctrl = omap_mcpdm_read(mcpdm, MCPDM_REG_CTRL); |
129 | u32 link_mask = mcpdm->config[0].link_mask | mcpdm->config[1].link_mask; | ||
133 | 130 | ||
134 | ctrl |= (MCPDM_SW_DN_RST | MCPDM_SW_UP_RST); | 131 | ctrl |= (MCPDM_SW_DN_RST | MCPDM_SW_UP_RST); |
135 | omap_mcpdm_write(mcpdm, MCPDM_REG_CTRL, ctrl); | 132 | omap_mcpdm_write(mcpdm, MCPDM_REG_CTRL, ctrl); |
136 | 133 | ||
137 | ctrl |= mcpdm->dn_channels | mcpdm->up_channels; | 134 | ctrl |= link_mask; |
138 | omap_mcpdm_write(mcpdm, MCPDM_REG_CTRL, ctrl); | 135 | omap_mcpdm_write(mcpdm, MCPDM_REG_CTRL, ctrl); |
139 | 136 | ||
140 | ctrl &= ~(MCPDM_SW_DN_RST | MCPDM_SW_UP_RST); | 137 | ctrl &= ~(MCPDM_SW_DN_RST | MCPDM_SW_UP_RST); |
@@ -148,11 +145,12 @@ static void omap_mcpdm_start(struct omap_mcpdm *mcpdm) | |||
148 | static void omap_mcpdm_stop(struct omap_mcpdm *mcpdm) | 145 | static void omap_mcpdm_stop(struct omap_mcpdm *mcpdm) |
149 | { | 146 | { |
150 | u32 ctrl = omap_mcpdm_read(mcpdm, MCPDM_REG_CTRL); | 147 | u32 ctrl = omap_mcpdm_read(mcpdm, MCPDM_REG_CTRL); |
148 | u32 link_mask = MCPDM_PDM_DN_MASK | MCPDM_PDM_UP_MASK; | ||
151 | 149 | ||
152 | ctrl |= (MCPDM_SW_DN_RST | MCPDM_SW_UP_RST); | 150 | ctrl |= (MCPDM_SW_DN_RST | MCPDM_SW_UP_RST); |
153 | omap_mcpdm_write(mcpdm, MCPDM_REG_CTRL, ctrl); | 151 | omap_mcpdm_write(mcpdm, MCPDM_REG_CTRL, ctrl); |
154 | 152 | ||
155 | ctrl &= ~(mcpdm->dn_channels | mcpdm->up_channels); | 153 | ctrl &= ~(link_mask); |
156 | omap_mcpdm_write(mcpdm, MCPDM_REG_CTRL, ctrl); | 154 | omap_mcpdm_write(mcpdm, MCPDM_REG_CTRL, ctrl); |
157 | 155 | ||
158 | ctrl &= ~(MCPDM_SW_DN_RST | MCPDM_SW_UP_RST); | 156 | ctrl &= ~(MCPDM_SW_DN_RST | MCPDM_SW_UP_RST); |
@@ -188,8 +186,10 @@ static void omap_mcpdm_open_streams(struct omap_mcpdm *mcpdm) | |||
188 | omap_mcpdm_write(mcpdm, MCPDM_REG_DN_OFFSET, dn_offset); | 186 | omap_mcpdm_write(mcpdm, MCPDM_REG_DN_OFFSET, dn_offset); |
189 | } | 187 | } |
190 | 188 | ||
191 | omap_mcpdm_write(mcpdm, MCPDM_REG_FIFO_CTRL_DN, mcpdm->dn_threshold); | 189 | omap_mcpdm_write(mcpdm, MCPDM_REG_FIFO_CTRL_DN, |
192 | omap_mcpdm_write(mcpdm, MCPDM_REG_FIFO_CTRL_UP, mcpdm->up_threshold); | 190 | mcpdm->config[SNDRV_PCM_STREAM_PLAYBACK].threshold); |
191 | omap_mcpdm_write(mcpdm, MCPDM_REG_FIFO_CTRL_UP, | ||
192 | mcpdm->config[SNDRV_PCM_STREAM_CAPTURE].threshold); | ||
193 | 193 | ||
194 | omap_mcpdm_write(mcpdm, MCPDM_REG_DMAENABLE_SET, | 194 | omap_mcpdm_write(mcpdm, MCPDM_REG_DMAENABLE_SET, |
195 | MCPDM_DMA_DN_ENABLE | MCPDM_DMA_UP_ENABLE); | 195 | MCPDM_DMA_DN_ENABLE | MCPDM_DMA_UP_ENABLE); |
@@ -267,7 +267,7 @@ static int omap_mcpdm_dai_startup(struct snd_pcm_substream *substream, | |||
267 | mutex_unlock(&mcpdm->mutex); | 267 | mutex_unlock(&mcpdm->mutex); |
268 | 268 | ||
269 | snd_soc_dai_set_dma_data(dai, substream, | 269 | snd_soc_dai_set_dma_data(dai, substream, |
270 | &omap_mcpdm_dai_dma_params[substream->stream]); | 270 | &mcpdm->dma_data[substream->stream]); |
271 | 271 | ||
272 | return 0; | 272 | return 0; |
273 | } | 273 | } |
@@ -283,6 +283,8 @@ static void omap_mcpdm_dai_shutdown(struct snd_pcm_substream *substream, | |||
283 | if (omap_mcpdm_active(mcpdm)) { | 283 | if (omap_mcpdm_active(mcpdm)) { |
284 | omap_mcpdm_stop(mcpdm); | 284 | omap_mcpdm_stop(mcpdm); |
285 | omap_mcpdm_close_streams(mcpdm); | 285 | omap_mcpdm_close_streams(mcpdm); |
286 | mcpdm->config[0].link_mask = 0; | ||
287 | mcpdm->config[1].link_mask = 0; | ||
286 | } | 288 | } |
287 | } | 289 | } |
288 | 290 | ||
@@ -295,7 +297,8 @@ static int omap_mcpdm_dai_hw_params(struct snd_pcm_substream *substream, | |||
295 | { | 297 | { |
296 | struct omap_mcpdm *mcpdm = snd_soc_dai_get_drvdata(dai); | 298 | struct omap_mcpdm *mcpdm = snd_soc_dai_get_drvdata(dai); |
297 | int stream = substream->stream; | 299 | int stream = substream->stream; |
298 | struct omap_pcm_dma_data *dma_data; | 300 | struct snd_dmaengine_dai_dma_data *dma_data; |
301 | u32 threshold; | ||
299 | int channels; | 302 | int channels; |
300 | int link_mask = 0; | 303 | int link_mask = 0; |
301 | 304 | ||
@@ -325,16 +328,32 @@ static int omap_mcpdm_dai_hw_params(struct snd_pcm_substream *substream, | |||
325 | 328 | ||
326 | dma_data = snd_soc_dai_get_dma_data(dai, substream); | 329 | dma_data = snd_soc_dai_get_dma_data(dai, substream); |
327 | 330 | ||
331 | threshold = mcpdm->config[stream].threshold; | ||
328 | /* Configure McPDM channels, and DMA packet size */ | 332 | /* Configure McPDM channels, and DMA packet size */ |
329 | if (stream == SNDRV_PCM_STREAM_PLAYBACK) { | 333 | if (stream == SNDRV_PCM_STREAM_PLAYBACK) { |
330 | mcpdm->dn_channels = link_mask << 3; | 334 | link_mask <<= 3; |
331 | dma_data->packet_size = | 335 | |
332 | (MCPDM_DN_THRES_MAX - mcpdm->dn_threshold) * channels; | 336 | /* If capture is not running assume a stereo stream to come */ |
337 | if (!mcpdm->config[!stream].link_mask) | ||
338 | mcpdm->config[!stream].link_mask = 0x3; | ||
339 | |||
340 | dma_data->maxburst = | ||
341 | (MCPDM_DN_THRES_MAX - threshold) * channels; | ||
333 | } else { | 342 | } else { |
334 | mcpdm->up_channels = link_mask << 0; | 343 | /* If playback is not running assume a stereo stream to come */ |
335 | dma_data->packet_size = mcpdm->up_threshold * channels; | 344 | if (!mcpdm->config[!stream].link_mask) |
345 | mcpdm->config[!stream].link_mask = (0x3 << 3); | ||
346 | |||
347 | dma_data->maxburst = threshold * channels; | ||
336 | } | 348 | } |
337 | 349 | ||
350 | /* Check if we need to restart McPDM with this stream */ | ||
351 | if (mcpdm->config[stream].link_mask && | ||
352 | mcpdm->config[stream].link_mask != link_mask) | ||
353 | mcpdm->restart = true; | ||
354 | |||
355 | mcpdm->config[stream].link_mask = link_mask; | ||
356 | |||
338 | return 0; | 357 | return 0; |
339 | } | 358 | } |
340 | 359 | ||
@@ -346,6 +365,11 @@ static int omap_mcpdm_prepare(struct snd_pcm_substream *substream, | |||
346 | if (!omap_mcpdm_active(mcpdm)) { | 365 | if (!omap_mcpdm_active(mcpdm)) { |
347 | omap_mcpdm_start(mcpdm); | 366 | omap_mcpdm_start(mcpdm); |
348 | omap_mcpdm_reg_dump(mcpdm); | 367 | omap_mcpdm_reg_dump(mcpdm); |
368 | } else if (mcpdm->restart) { | ||
369 | omap_mcpdm_stop(mcpdm); | ||
370 | omap_mcpdm_start(mcpdm); | ||
371 | mcpdm->restart = false; | ||
372 | omap_mcpdm_reg_dump(mcpdm); | ||
349 | } | 373 | } |
350 | 374 | ||
351 | return 0; | 375 | return 0; |
@@ -369,7 +393,7 @@ static int omap_mcpdm_probe(struct snd_soc_dai *dai) | |||
369 | pm_runtime_get_sync(mcpdm->dev); | 393 | pm_runtime_get_sync(mcpdm->dev); |
370 | omap_mcpdm_write(mcpdm, MCPDM_REG_CTRL, 0x00); | 394 | omap_mcpdm_write(mcpdm, MCPDM_REG_CTRL, 0x00); |
371 | 395 | ||
372 | ret = request_irq(mcpdm->irq, omap_mcpdm_irq_handler, | 396 | ret = devm_request_irq(mcpdm->dev, mcpdm->irq, omap_mcpdm_irq_handler, |
373 | 0, "McPDM", (void *)mcpdm); | 397 | 0, "McPDM", (void *)mcpdm); |
374 | 398 | ||
375 | pm_runtime_put_sync(mcpdm->dev); | 399 | pm_runtime_put_sync(mcpdm->dev); |
@@ -380,8 +404,9 @@ static int omap_mcpdm_probe(struct snd_soc_dai *dai) | |||
380 | } | 404 | } |
381 | 405 | ||
382 | /* Configure McPDM threshold values */ | 406 | /* Configure McPDM threshold values */ |
383 | mcpdm->dn_threshold = 2; | 407 | mcpdm->config[SNDRV_PCM_STREAM_PLAYBACK].threshold = 2; |
384 | mcpdm->up_threshold = MCPDM_UP_THRES_MAX - 3; | 408 | mcpdm->config[SNDRV_PCM_STREAM_CAPTURE].threshold = |
409 | MCPDM_UP_THRES_MAX - 3; | ||
385 | return ret; | 410 | return ret; |
386 | } | 411 | } |
387 | 412 | ||
@@ -389,7 +414,6 @@ static int omap_mcpdm_remove(struct snd_soc_dai *dai) | |||
389 | { | 414 | { |
390 | struct omap_mcpdm *mcpdm = snd_soc_dai_get_drvdata(dai); | 415 | struct omap_mcpdm *mcpdm = snd_soc_dai_get_drvdata(dai); |
391 | 416 | ||
392 | free_irq(mcpdm->irq, (void *)mcpdm); | ||
393 | pm_runtime_disable(mcpdm->dev); | 417 | pm_runtime_disable(mcpdm->dev); |
394 | 418 | ||
395 | return 0; | 419 | return 0; |
@@ -446,33 +470,30 @@ static int asoc_mcpdm_probe(struct platform_device *pdev) | |||
446 | if (res == NULL) | 470 | if (res == NULL) |
447 | return -ENOMEM; | 471 | return -ENOMEM; |
448 | 472 | ||
449 | omap_mcpdm_dai_dma_params[0].port_addr = res->start + MCPDM_REG_DN_DATA; | 473 | mcpdm->dma_data[0].addr = res->start + MCPDM_REG_DN_DATA; |
450 | omap_mcpdm_dai_dma_params[1].port_addr = res->start + MCPDM_REG_UP_DATA; | 474 | mcpdm->dma_data[1].addr = res->start + MCPDM_REG_UP_DATA; |
451 | 475 | ||
452 | res = platform_get_resource_byname(pdev, IORESOURCE_DMA, "dn_link"); | 476 | res = platform_get_resource_byname(pdev, IORESOURCE_DMA, "dn_link"); |
453 | if (!res) | 477 | if (!res) |
454 | return -ENODEV; | 478 | return -ENODEV; |
455 | 479 | ||
456 | omap_mcpdm_dai_dma_params[0].dma_req = res->start; | 480 | mcpdm->dma_req[0] = res->start; |
481 | mcpdm->dma_data[0].filter_data = &mcpdm->dma_req[0]; | ||
457 | 482 | ||
458 | res = platform_get_resource_byname(pdev, IORESOURCE_DMA, "up_link"); | 483 | res = platform_get_resource_byname(pdev, IORESOURCE_DMA, "up_link"); |
459 | if (!res) | 484 | if (!res) |
460 | return -ENODEV; | 485 | return -ENODEV; |
461 | 486 | ||
462 | omap_mcpdm_dai_dma_params[1].dma_req = res->start; | 487 | mcpdm->dma_req[1] = res->start; |
488 | mcpdm->dma_data[1].filter_data = &mcpdm->dma_req[1]; | ||
463 | 489 | ||
464 | res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "mpu"); | 490 | res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "mpu"); |
465 | if (res == NULL) | 491 | if (res == NULL) |
466 | return -ENOMEM; | 492 | return -ENOMEM; |
467 | 493 | ||
468 | if (!devm_request_mem_region(&pdev->dev, res->start, | 494 | mcpdm->io_base = devm_ioremap_resource(&pdev->dev, res); |
469 | resource_size(res), "McPDM")) | 495 | if (IS_ERR(mcpdm->io_base)) |
470 | return -EBUSY; | 496 | return PTR_ERR(mcpdm->io_base); |
471 | |||
472 | mcpdm->io_base = devm_ioremap(&pdev->dev, res->start, | ||
473 | resource_size(res)); | ||
474 | if (!mcpdm->io_base) | ||
475 | return -ENOMEM; | ||
476 | 497 | ||
477 | mcpdm->irq = platform_get_irq(pdev, 0); | 498 | mcpdm->irq = platform_get_irq(pdev, 0); |
478 | if (mcpdm->irq < 0) | 499 | if (mcpdm->irq < 0) |
diff --git a/sound/soc/omap/omap-pcm.c b/sound/soc/omap/omap-pcm.c index c722c2ef9665..c28e042f2208 100644 --- a/sound/soc/omap/omap-pcm.c +++ b/sound/soc/omap/omap-pcm.c | |||
@@ -32,8 +32,6 @@ | |||
32 | #include <sound/dmaengine_pcm.h> | 32 | #include <sound/dmaengine_pcm.h> |
33 | #include <sound/soc.h> | 33 | #include <sound/soc.h> |
34 | 34 | ||
35 | #include "omap-pcm.h" | ||
36 | |||
37 | #ifdef CONFIG_ARCH_OMAP1 | 35 | #ifdef CONFIG_ARCH_OMAP1 |
38 | #define pcm_omap1510() cpu_is_omap1510() | 36 | #define pcm_omap1510() cpu_is_omap1510() |
39 | #else | 37 | #else |
@@ -56,25 +54,6 @@ static const struct snd_pcm_hardware omap_pcm_hardware = { | |||
56 | .buffer_bytes_max = 128 * 1024, | 54 | .buffer_bytes_max = 128 * 1024, |
57 | }; | 55 | }; |
58 | 56 | ||
59 | static int omap_pcm_get_dma_buswidth(int num_bits) | ||
60 | { | ||
61 | int buswidth; | ||
62 | |||
63 | switch (num_bits) { | ||
64 | case 16: | ||
65 | buswidth = DMA_SLAVE_BUSWIDTH_2_BYTES; | ||
66 | break; | ||
67 | case 32: | ||
68 | buswidth = DMA_SLAVE_BUSWIDTH_4_BYTES; | ||
69 | break; | ||
70 | default: | ||
71 | buswidth = -EINVAL; | ||
72 | break; | ||
73 | } | ||
74 | return buswidth; | ||
75 | } | ||
76 | |||
77 | |||
78 | /* this may get called several times by oss emulation */ | 57 | /* this may get called several times by oss emulation */ |
79 | static int omap_pcm_hw_params(struct snd_pcm_substream *substream, | 58 | static int omap_pcm_hw_params(struct snd_pcm_substream *substream, |
80 | struct snd_pcm_hw_params *params) | 59 | struct snd_pcm_hw_params *params) |
@@ -105,20 +84,9 @@ static int omap_pcm_hw_params(struct snd_pcm_substream *substream, | |||
105 | if (err) | 84 | if (err) |
106 | return err; | 85 | return err; |
107 | 86 | ||
108 | /* Override the *_dma addr_width if requested by the DAI driver */ | 87 | snd_dmaengine_pcm_set_config_from_dai_data(substream, |
109 | if (dma_data->data_type) { | 88 | snd_soc_dai_get_dma_data(rtd->cpu_dai, substream), |
110 | int buswidth = omap_pcm_get_dma_buswidth(dma_data->data_type); | 89 | &config); |
111 | |||
112 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) | ||
113 | config.dst_addr_width = buswidth; | ||
114 | else | ||
115 | config.src_addr_width = buswidth; | ||
116 | } | ||
117 | |||
118 | config.src_addr = dma_data->port_addr; | ||
119 | config.dst_addr = dma_data->port_addr; | ||
120 | config.src_maxburst = dma_data->packet_size; | ||
121 | config.dst_maxburst = dma_data->packet_size; | ||
122 | 90 | ||
123 | return dmaengine_slave_config(chan, &config); | 91 | return dmaengine_slave_config(chan, &config); |
124 | } | 92 | } |
@@ -129,37 +97,6 @@ static int omap_pcm_hw_free(struct snd_pcm_substream *substream) | |||
129 | return 0; | 97 | return 0; |
130 | } | 98 | } |
131 | 99 | ||
132 | static int omap_pcm_trigger(struct snd_pcm_substream *substream, int cmd) | ||
133 | { | ||
134 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | ||
135 | struct omap_pcm_dma_data *dma_data; | ||
136 | int ret = 0; | ||
137 | |||
138 | dma_data = snd_soc_dai_get_dma_data(rtd->cpu_dai, substream); | ||
139 | |||
140 | switch (cmd) { | ||
141 | case SNDRV_PCM_TRIGGER_START: | ||
142 | case SNDRV_PCM_TRIGGER_RESUME: | ||
143 | case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: | ||
144 | /* Configure McBSP internal buffer usage */ | ||
145 | if (dma_data->set_threshold) | ||
146 | dma_data->set_threshold(substream); | ||
147 | break; | ||
148 | |||
149 | case SNDRV_PCM_TRIGGER_STOP: | ||
150 | case SNDRV_PCM_TRIGGER_SUSPEND: | ||
151 | case SNDRV_PCM_TRIGGER_PAUSE_PUSH: | ||
152 | break; | ||
153 | default: | ||
154 | ret = -EINVAL; | ||
155 | } | ||
156 | |||
157 | if (ret == 0) | ||
158 | ret = snd_dmaengine_pcm_trigger(substream, cmd); | ||
159 | |||
160 | return ret; | ||
161 | } | ||
162 | |||
163 | static snd_pcm_uframes_t omap_pcm_pointer(struct snd_pcm_substream *substream) | 100 | static snd_pcm_uframes_t omap_pcm_pointer(struct snd_pcm_substream *substream) |
164 | { | 101 | { |
165 | snd_pcm_uframes_t offset; | 102 | snd_pcm_uframes_t offset; |
@@ -175,20 +112,15 @@ static snd_pcm_uframes_t omap_pcm_pointer(struct snd_pcm_substream *substream) | |||
175 | static int omap_pcm_open(struct snd_pcm_substream *substream) | 112 | static int omap_pcm_open(struct snd_pcm_substream *substream) |
176 | { | 113 | { |
177 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | 114 | struct snd_soc_pcm_runtime *rtd = substream->private_data; |
178 | struct omap_pcm_dma_data *dma_data; | 115 | struct snd_dmaengine_dai_dma_data *dma_data; |
179 | 116 | ||
180 | snd_soc_set_runtime_hwparams(substream, &omap_pcm_hardware); | 117 | snd_soc_set_runtime_hwparams(substream, &omap_pcm_hardware); |
181 | 118 | ||
182 | dma_data = snd_soc_dai_get_dma_data(rtd->cpu_dai, substream); | 119 | dma_data = snd_soc_dai_get_dma_data(rtd->cpu_dai, substream); |
183 | 120 | ||
184 | return snd_dmaengine_pcm_open(substream, omap_dma_filter_fn, | 121 | return snd_dmaengine_pcm_open_request_chan(substream, |
185 | &dma_data->dma_req); | 122 | omap_dma_filter_fn, |
186 | } | 123 | dma_data->filter_data); |
187 | |||
188 | static int omap_pcm_close(struct snd_pcm_substream *substream) | ||
189 | { | ||
190 | snd_dmaengine_pcm_close(substream); | ||
191 | return 0; | ||
192 | } | 124 | } |
193 | 125 | ||
194 | static int omap_pcm_mmap(struct snd_pcm_substream *substream, | 126 | static int omap_pcm_mmap(struct snd_pcm_substream *substream, |
@@ -204,11 +136,11 @@ static int omap_pcm_mmap(struct snd_pcm_substream *substream, | |||
204 | 136 | ||
205 | static struct snd_pcm_ops omap_pcm_ops = { | 137 | static struct snd_pcm_ops omap_pcm_ops = { |
206 | .open = omap_pcm_open, | 138 | .open = omap_pcm_open, |
207 | .close = omap_pcm_close, | 139 | .close = snd_dmaengine_pcm_close_release_chan, |
208 | .ioctl = snd_pcm_lib_ioctl, | 140 | .ioctl = snd_pcm_lib_ioctl, |
209 | .hw_params = omap_pcm_hw_params, | 141 | .hw_params = omap_pcm_hw_params, |
210 | .hw_free = omap_pcm_hw_free, | 142 | .hw_free = omap_pcm_hw_free, |
211 | .trigger = omap_pcm_trigger, | 143 | .trigger = snd_dmaengine_pcm_trigger, |
212 | .pointer = omap_pcm_pointer, | 144 | .pointer = omap_pcm_pointer, |
213 | .mmap = omap_pcm_mmap, | 145 | .mmap = omap_pcm_mmap, |
214 | }; | 146 | }; |
diff --git a/sound/soc/omap/omap-pcm.h b/sound/soc/omap/omap-pcm.h deleted file mode 100644 index cabe74c4068b..000000000000 --- a/sound/soc/omap/omap-pcm.h +++ /dev/null | |||
@@ -1,40 +0,0 @@ | |||
1 | /* | ||
2 | * omap-pcm.h | ||
3 | * | ||
4 | * Copyright (C) 2008 Nokia Corporation | ||
5 | * | ||
6 | * Contact: Jarkko Nikula <jarkko.nikula@bitmer.com> | ||
7 | * Peter Ujfalusi <peter.ujfalusi@ti.com> | ||
8 | * | ||
9 | * This program is free software; you can redistribute it and/or | ||
10 | * modify it under the terms of the GNU General Public License | ||
11 | * version 2 as published by the Free Software Foundation. | ||
12 | * | ||
13 | * This program is distributed in the hope that it will be useful, but | ||
14 | * WITHOUT ANY WARRANTY; without even the implied warranty of | ||
15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
16 | * General Public License for more details. | ||
17 | * | ||
18 | * You should have received a copy of the GNU General Public License | ||
19 | * along with this program; if not, write to the Free Software | ||
20 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA | ||
21 | * 02110-1301 USA | ||
22 | * | ||
23 | */ | ||
24 | |||
25 | #ifndef __OMAP_PCM_H__ | ||
26 | #define __OMAP_PCM_H__ | ||
27 | |||
28 | struct snd_pcm_substream; | ||
29 | |||
30 | struct omap_pcm_dma_data { | ||
31 | char *name; /* stream identifier */ | ||
32 | int dma_req; /* DMA request line */ | ||
33 | unsigned long port_addr; /* transmit/receive register */ | ||
34 | void (*set_threshold)(struct snd_pcm_substream *substream); | ||
35 | int data_type; /* 8, 16, 32 (bits) or 0 to let omap-pcm | ||
36 | * to decide the sDMA data type */ | ||
37 | int packet_size; /* packet size only in PACKET mode */ | ||
38 | }; | ||
39 | |||
40 | #endif | ||
diff --git a/sound/soc/omap/omap-twl4030.c b/sound/soc/omap/omap-twl4030.c index fd98509d0f49..2a9324f794d8 100644 --- a/sound/soc/omap/omap-twl4030.c +++ b/sound/soc/omap/omap-twl4030.c | |||
@@ -43,7 +43,6 @@ | |||
43 | #include <sound/jack.h> | 43 | #include <sound/jack.h> |
44 | 44 | ||
45 | #include "omap-mcbsp.h" | 45 | #include "omap-mcbsp.h" |
46 | #include "omap-pcm.h" | ||
47 | 46 | ||
48 | struct omap_twl4030 { | 47 | struct omap_twl4030 { |
49 | int jack_detect; /* board can detect jack events */ | 48 | int jack_detect; /* board can detect jack events */ |
diff --git a/sound/soc/omap/omap3pandora.c b/sound/soc/omap/omap3pandora.c index 805512f2555a..cf604a2faa18 100644 --- a/sound/soc/omap/omap3pandora.c +++ b/sound/soc/omap/omap3pandora.c | |||
@@ -34,7 +34,6 @@ | |||
34 | #include <linux/platform_data/asoc-ti-mcbsp.h> | 34 | #include <linux/platform_data/asoc-ti-mcbsp.h> |
35 | 35 | ||
36 | #include "omap-mcbsp.h" | 36 | #include "omap-mcbsp.h" |
37 | #include "omap-pcm.h" | ||
38 | 37 | ||
39 | #define OMAP3_PANDORA_DAC_POWER_GPIO 118 | 38 | #define OMAP3_PANDORA_DAC_POWER_GPIO 118 |
40 | #define OMAP3_PANDORA_AMP_POWER_GPIO 14 | 39 | #define OMAP3_PANDORA_AMP_POWER_GPIO 14 |
@@ -80,12 +79,18 @@ static int omap3pandora_hw_params(struct snd_pcm_substream *substream, | |||
80 | static int omap3pandora_dac_event(struct snd_soc_dapm_widget *w, | 79 | static int omap3pandora_dac_event(struct snd_soc_dapm_widget *w, |
81 | struct snd_kcontrol *k, int event) | 80 | struct snd_kcontrol *k, int event) |
82 | { | 81 | { |
82 | int ret; | ||
83 | |||
83 | /* | 84 | /* |
84 | * The PCM1773 DAC datasheet requires 1ms delay between switching | 85 | * The PCM1773 DAC datasheet requires 1ms delay between switching |
85 | * VCC power on/off and /PD pin high/low | 86 | * VCC power on/off and /PD pin high/low |
86 | */ | 87 | */ |
87 | if (SND_SOC_DAPM_EVENT_ON(event)) { | 88 | if (SND_SOC_DAPM_EVENT_ON(event)) { |
88 | regulator_enable(omap3pandora_dac_reg); | 89 | ret = regulator_enable(omap3pandora_dac_reg); |
90 | if (ret) { | ||
91 | dev_err(w->dapm->dev, "Failed to power DAC: %d\n", ret); | ||
92 | return ret; | ||
93 | } | ||
89 | mdelay(1); | 94 | mdelay(1); |
90 | gpio_set_value(OMAP3_PANDORA_DAC_POWER_GPIO, 1); | 95 | gpio_set_value(OMAP3_PANDORA_DAC_POWER_GPIO, 1); |
91 | } else { | 96 | } else { |
diff --git a/sound/soc/omap/osk5912.c b/sound/soc/omap/osk5912.c index 06ef8d67ed1c..d03e57da7708 100644 --- a/sound/soc/omap/osk5912.c +++ b/sound/soc/omap/osk5912.c | |||
@@ -33,7 +33,6 @@ | |||
33 | #include <linux/platform_data/asoc-ti-mcbsp.h> | 33 | #include <linux/platform_data/asoc-ti-mcbsp.h> |
34 | 34 | ||
35 | #include "omap-mcbsp.h" | 35 | #include "omap-mcbsp.h" |
36 | #include "omap-pcm.h" | ||
37 | #include "../codecs/tlv320aic23.h" | 36 | #include "../codecs/tlv320aic23.h" |
38 | 37 | ||
39 | #define CODEC_CLOCK 12000000 | 38 | #define CODEC_CLOCK 12000000 |
diff --git a/sound/soc/omap/rx51.c b/sound/soc/omap/rx51.c index 3cd525748975..249cd230ad8f 100644 --- a/sound/soc/omap/rx51.c +++ b/sound/soc/omap/rx51.c | |||
@@ -37,7 +37,6 @@ | |||
37 | #include <asm/mach-types.h> | 37 | #include <asm/mach-types.h> |
38 | 38 | ||
39 | #include "omap-mcbsp.h" | 39 | #include "omap-mcbsp.h" |
40 | #include "omap-pcm.h" | ||
41 | 40 | ||
42 | #define RX51_TVOUT_SEL_GPIO 40 | 41 | #define RX51_TVOUT_SEL_GPIO 40 |
43 | #define RX51_JACK_DETECT_GPIO 177 | 42 | #define RX51_JACK_DETECT_GPIO 177 |
diff --git a/sound/soc/pxa/mmp-pcm.c b/sound/soc/pxa/mmp-pcm.c index 190eb0bccf5f..349930015264 100644 --- a/sound/soc/pxa/mmp-pcm.c +++ b/sound/soc/pxa/mmp-pcm.c | |||
@@ -118,9 +118,8 @@ static int mmp_pcm_open(struct snd_pcm_substream *substream) | |||
118 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | 118 | struct snd_soc_pcm_runtime *rtd = substream->private_data; |
119 | struct platform_device *pdev = to_platform_device(rtd->platform->dev); | 119 | struct platform_device *pdev = to_platform_device(rtd->platform->dev); |
120 | struct snd_soc_dai *cpu_dai = rtd->cpu_dai; | 120 | struct snd_soc_dai *cpu_dai = rtd->cpu_dai; |
121 | struct mmp_dma_data *dma_data; | 121 | struct mmp_dma_data dma_data; |
122 | struct resource *r; | 122 | struct resource *r; |
123 | int ret; | ||
124 | 123 | ||
125 | r = platform_get_resource(pdev, IORESOURCE_DMA, substream->stream); | 124 | r = platform_get_resource(pdev, IORESOURCE_DMA, substream->stream); |
126 | if (!r) | 125 | if (!r) |
@@ -128,33 +127,12 @@ static int mmp_pcm_open(struct snd_pcm_substream *substream) | |||
128 | 127 | ||
129 | snd_soc_set_runtime_hwparams(substream, | 128 | snd_soc_set_runtime_hwparams(substream, |
130 | &mmp_pcm_hardware[substream->stream]); | 129 | &mmp_pcm_hardware[substream->stream]); |
131 | dma_data = devm_kzalloc(&pdev->dev, | ||
132 | sizeof(struct mmp_dma_data), GFP_KERNEL); | ||
133 | if (dma_data == NULL) | ||
134 | return -ENOMEM; | ||
135 | 130 | ||
136 | dma_data->dma_res = r; | 131 | dma_data.dma_res = r; |
137 | dma_data->ssp_id = cpu_dai->id; | 132 | dma_data.ssp_id = cpu_dai->id; |
138 | 133 | ||
139 | ret = snd_dmaengine_pcm_open(substream, filter, dma_data); | 134 | return snd_dmaengine_pcm_open_request_chan(substream, filter, |
140 | if (ret) { | 135 | &dma_data); |
141 | devm_kfree(&pdev->dev, dma_data); | ||
142 | return ret; | ||
143 | } | ||
144 | |||
145 | snd_dmaengine_pcm_set_data(substream, dma_data); | ||
146 | return 0; | ||
147 | } | ||
148 | |||
149 | static int mmp_pcm_close(struct snd_pcm_substream *substream) | ||
150 | { | ||
151 | struct mmp_dma_data *dma_data = snd_dmaengine_pcm_get_data(substream); | ||
152 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | ||
153 | struct platform_device *pdev = to_platform_device(rtd->platform->dev); | ||
154 | |||
155 | snd_dmaengine_pcm_close(substream); | ||
156 | devm_kfree(&pdev->dev, dma_data); | ||
157 | return 0; | ||
158 | } | 136 | } |
159 | 137 | ||
160 | static int mmp_pcm_mmap(struct snd_pcm_substream *substream, | 138 | static int mmp_pcm_mmap(struct snd_pcm_substream *substream, |
@@ -171,7 +149,7 @@ static int mmp_pcm_mmap(struct snd_pcm_substream *substream, | |||
171 | 149 | ||
172 | struct snd_pcm_ops mmp_pcm_ops = { | 150 | struct snd_pcm_ops mmp_pcm_ops = { |
173 | .open = mmp_pcm_open, | 151 | .open = mmp_pcm_open, |
174 | .close = mmp_pcm_close, | 152 | .close = snd_dmaengine_pcm_close_release_chan, |
175 | .ioctl = snd_pcm_lib_ioctl, | 153 | .ioctl = snd_pcm_lib_ioctl, |
176 | .hw_params = mmp_pcm_hw_params, | 154 | .hw_params = mmp_pcm_hw_params, |
177 | .trigger = snd_dmaengine_pcm_trigger, | 155 | .trigger = snd_dmaengine_pcm_trigger, |
diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c index c70f9e072043..78468c64dd86 100644 --- a/sound/soc/soc-core.c +++ b/sound/soc/soc-core.c | |||
@@ -3903,21 +3903,14 @@ void snd_soc_unregister_dais(struct device *dev, size_t count) | |||
3903 | EXPORT_SYMBOL_GPL(snd_soc_unregister_dais); | 3903 | EXPORT_SYMBOL_GPL(snd_soc_unregister_dais); |
3904 | 3904 | ||
3905 | /** | 3905 | /** |
3906 | * snd_soc_register_platform - Register a platform with the ASoC core | 3906 | * snd_soc_add_platform - Add a platform to the ASoC core |
3907 | * | 3907 | * @dev: The parent device for the platform |
3908 | * @platform: platform to register | 3908 | * @platform: The platform to add |
3909 | * @platform_driver: The driver for the platform | ||
3909 | */ | 3910 | */ |
3910 | int snd_soc_register_platform(struct device *dev, | 3911 | int snd_soc_add_platform(struct device *dev, struct snd_soc_platform *platform, |
3911 | const struct snd_soc_platform_driver *platform_drv) | 3912 | const struct snd_soc_platform_driver *platform_drv) |
3912 | { | 3913 | { |
3913 | struct snd_soc_platform *platform; | ||
3914 | |||
3915 | dev_dbg(dev, "ASoC: platform register %s\n", dev_name(dev)); | ||
3916 | |||
3917 | platform = kzalloc(sizeof(struct snd_soc_platform), GFP_KERNEL); | ||
3918 | if (platform == NULL) | ||
3919 | return -ENOMEM; | ||
3920 | |||
3921 | /* create platform component name */ | 3914 | /* create platform component name */ |
3922 | platform->name = fmt_single_name(dev, &platform->id); | 3915 | platform->name = fmt_single_name(dev, &platform->id); |
3923 | if (platform->name == NULL) { | 3916 | if (platform->name == NULL) { |
@@ -3940,30 +3933,76 @@ int snd_soc_register_platform(struct device *dev, | |||
3940 | 3933 | ||
3941 | return 0; | 3934 | return 0; |
3942 | } | 3935 | } |
3943 | EXPORT_SYMBOL_GPL(snd_soc_register_platform); | 3936 | EXPORT_SYMBOL_GPL(snd_soc_add_platform); |
3944 | 3937 | ||
3945 | /** | 3938 | /** |
3946 | * snd_soc_unregister_platform - Unregister a platform from the ASoC core | 3939 | * snd_soc_register_platform - Register a platform with the ASoC core |
3947 | * | 3940 | * |
3948 | * @platform: platform to unregister | 3941 | * @platform: platform to register |
3949 | */ | 3942 | */ |
3950 | void snd_soc_unregister_platform(struct device *dev) | 3943 | int snd_soc_register_platform(struct device *dev, |
3944 | const struct snd_soc_platform_driver *platform_drv) | ||
3951 | { | 3945 | { |
3952 | struct snd_soc_platform *platform; | 3946 | struct snd_soc_platform *platform; |
3947 | int ret; | ||
3953 | 3948 | ||
3954 | list_for_each_entry(platform, &platform_list, list) { | 3949 | dev_dbg(dev, "ASoC: platform register %s\n", dev_name(dev)); |
3955 | if (dev == platform->dev) | ||
3956 | goto found; | ||
3957 | } | ||
3958 | return; | ||
3959 | 3950 | ||
3960 | found: | 3951 | platform = kzalloc(sizeof(struct snd_soc_platform), GFP_KERNEL); |
3952 | if (platform == NULL) | ||
3953 | return -ENOMEM; | ||
3954 | |||
3955 | ret = snd_soc_add_platform(dev, platform, platform_drv); | ||
3956 | if (ret) | ||
3957 | kfree(platform); | ||
3958 | |||
3959 | return ret; | ||
3960 | } | ||
3961 | EXPORT_SYMBOL_GPL(snd_soc_register_platform); | ||
3962 | |||
3963 | /** | ||
3964 | * snd_soc_remove_platform - Remove a platform from the ASoC core | ||
3965 | * @platform: the platform to remove | ||
3966 | */ | ||
3967 | void snd_soc_remove_platform(struct snd_soc_platform *platform) | ||
3968 | { | ||
3961 | mutex_lock(&client_mutex); | 3969 | mutex_lock(&client_mutex); |
3962 | list_del(&platform->list); | 3970 | list_del(&platform->list); |
3963 | mutex_unlock(&client_mutex); | 3971 | mutex_unlock(&client_mutex); |
3964 | 3972 | ||
3965 | dev_dbg(dev, "ASoC: Unregistered platform '%s'\n", platform->name); | 3973 | dev_dbg(platform->dev, "ASoC: Unregistered platform '%s'\n", |
3974 | platform->name); | ||
3966 | kfree(platform->name); | 3975 | kfree(platform->name); |
3976 | } | ||
3977 | EXPORT_SYMBOL_GPL(snd_soc_remove_platform); | ||
3978 | |||
3979 | struct snd_soc_platform *snd_soc_lookup_platform(struct device *dev) | ||
3980 | { | ||
3981 | struct snd_soc_platform *platform; | ||
3982 | |||
3983 | list_for_each_entry(platform, &platform_list, list) { | ||
3984 | if (dev == platform->dev) | ||
3985 | return platform; | ||
3986 | } | ||
3987 | |||
3988 | return NULL; | ||
3989 | } | ||
3990 | EXPORT_SYMBOL_GPL(snd_soc_lookup_platform); | ||
3991 | |||
3992 | /** | ||
3993 | * snd_soc_unregister_platform - Unregister a platform from the ASoC core | ||
3994 | * | ||
3995 | * @platform: platform to unregister | ||
3996 | */ | ||
3997 | void snd_soc_unregister_platform(struct device *dev) | ||
3998 | { | ||
3999 | struct snd_soc_platform *platform; | ||
4000 | |||
4001 | platform = snd_soc_lookup_platform(dev); | ||
4002 | if (!platform) | ||
4003 | return; | ||
4004 | |||
4005 | snd_soc_remove_platform(platform); | ||
3967 | kfree(platform); | 4006 | kfree(platform); |
3968 | } | 4007 | } |
3969 | EXPORT_SYMBOL_GPL(snd_soc_unregister_platform); | 4008 | EXPORT_SYMBOL_GPL(snd_soc_unregister_platform); |
diff --git a/sound/soc/soc-dmaengine-pcm.c b/sound/soc/soc-dmaengine-pcm.c index 111b7d921e89..aa924d9b7986 100644 --- a/sound/soc/soc-dmaengine-pcm.c +++ b/sound/soc/soc-dmaengine-pcm.c | |||
@@ -33,8 +33,6 @@ struct dmaengine_pcm_runtime_data { | |||
33 | dma_cookie_t cookie; | 33 | dma_cookie_t cookie; |
34 | 34 | ||
35 | unsigned int pos; | 35 | unsigned int pos; |
36 | |||
37 | void *data; | ||
38 | }; | 36 | }; |
39 | 37 | ||
40 | static inline struct dmaengine_pcm_runtime_data *substream_to_prtd( | 38 | static inline struct dmaengine_pcm_runtime_data *substream_to_prtd( |
@@ -43,33 +41,6 @@ static inline struct dmaengine_pcm_runtime_data *substream_to_prtd( | |||
43 | return substream->runtime->private_data; | 41 | return substream->runtime->private_data; |
44 | } | 42 | } |
45 | 43 | ||
46 | /** | ||
47 | * snd_dmaengine_pcm_set_data - Set dmaengine substream private data | ||
48 | * @substream: PCM substream | ||
49 | * @data: Data to set | ||
50 | */ | ||
51 | void snd_dmaengine_pcm_set_data(struct snd_pcm_substream *substream, void *data) | ||
52 | { | ||
53 | struct dmaengine_pcm_runtime_data *prtd = substream_to_prtd(substream); | ||
54 | |||
55 | prtd->data = data; | ||
56 | } | ||
57 | EXPORT_SYMBOL_GPL(snd_dmaengine_pcm_set_data); | ||
58 | |||
59 | /** | ||
60 | * snd_dmaengine_pcm_get_data - Get dmaeinge substream private data | ||
61 | * @substream: PCM substream | ||
62 | * | ||
63 | * Returns the data previously set with snd_dmaengine_pcm_set_data | ||
64 | */ | ||
65 | void *snd_dmaengine_pcm_get_data(struct snd_pcm_substream *substream) | ||
66 | { | ||
67 | struct dmaengine_pcm_runtime_data *prtd = substream_to_prtd(substream); | ||
68 | |||
69 | return prtd->data; | ||
70 | } | ||
71 | EXPORT_SYMBOL_GPL(snd_dmaengine_pcm_get_data); | ||
72 | |||
73 | struct dma_chan *snd_dmaengine_pcm_get_chan(struct snd_pcm_substream *substream) | 44 | struct dma_chan *snd_dmaengine_pcm_get_chan(struct snd_pcm_substream *substream) |
74 | { | 45 | { |
75 | struct dmaengine_pcm_runtime_data *prtd = substream_to_prtd(substream); | 46 | struct dmaengine_pcm_runtime_data *prtd = substream_to_prtd(substream); |
@@ -118,10 +89,49 @@ int snd_hwparams_to_dma_slave_config(const struct snd_pcm_substream *substream, | |||
118 | slave_config->src_addr_width = buswidth; | 89 | slave_config->src_addr_width = buswidth; |
119 | } | 90 | } |
120 | 91 | ||
92 | slave_config->device_fc = false; | ||
93 | |||
121 | return 0; | 94 | return 0; |
122 | } | 95 | } |
123 | EXPORT_SYMBOL_GPL(snd_hwparams_to_dma_slave_config); | 96 | EXPORT_SYMBOL_GPL(snd_hwparams_to_dma_slave_config); |
124 | 97 | ||
98 | /** | ||
99 | * snd_dmaengine_pcm_set_config_from_dai_data() - Initializes a dma slave config | ||
100 | * using DAI DMA data. | ||
101 | * @substream: PCM substream | ||
102 | * @dma_data: DAI DMA data | ||
103 | * @slave_config: DMA slave configuration | ||
104 | * | ||
105 | * Initializes the {dst,src}_addr, {dst,src}_maxburst, {dst,src}_addr_width and | ||
106 | * slave_id fields of the DMA slave config from the same fields of the DAI DMA | ||
107 | * data struct. The src and dst fields will be initialized depending on the | ||
108 | * direction of the substream. If the substream is a playback stream the dst | ||
109 | * fields will be initialized, if it is a capture stream the src fields will be | ||
110 | * initialized. The {dst,src}_addr_width field will only be initialized if the | ||
111 | * addr_width field of the DAI DMA data struct is not equal to | ||
112 | * DMA_SLAVE_BUSWIDTH_UNDEFINED. | ||
113 | */ | ||
114 | void snd_dmaengine_pcm_set_config_from_dai_data( | ||
115 | const struct snd_pcm_substream *substream, | ||
116 | const struct snd_dmaengine_dai_dma_data *dma_data, | ||
117 | struct dma_slave_config *slave_config) | ||
118 | { | ||
119 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { | ||
120 | slave_config->dst_addr = dma_data->addr; | ||
121 | slave_config->dst_maxburst = dma_data->maxburst; | ||
122 | if (dma_data->addr_width != DMA_SLAVE_BUSWIDTH_UNDEFINED) | ||
123 | slave_config->dst_addr_width = dma_data->addr_width; | ||
124 | } else { | ||
125 | slave_config->src_addr = dma_data->addr; | ||
126 | slave_config->src_maxburst = dma_data->maxburst; | ||
127 | if (dma_data->addr_width != DMA_SLAVE_BUSWIDTH_UNDEFINED) | ||
128 | slave_config->src_addr_width = dma_data->addr_width; | ||
129 | } | ||
130 | |||
131 | slave_config->slave_id = dma_data->slave_id; | ||
132 | } | ||
133 | EXPORT_SYMBOL_GPL(snd_dmaengine_pcm_set_config_from_dai_data); | ||
134 | |||
125 | static void dmaengine_pcm_dma_complete(void *arg) | 135 | static void dmaengine_pcm_dma_complete(void *arg) |
126 | { | 136 | { |
127 | struct snd_pcm_substream *substream = arg; | 137 | struct snd_pcm_substream *substream = arg; |
@@ -244,44 +254,48 @@ snd_pcm_uframes_t snd_dmaengine_pcm_pointer(struct snd_pcm_substream *substream) | |||
244 | } | 254 | } |
245 | EXPORT_SYMBOL_GPL(snd_dmaengine_pcm_pointer); | 255 | EXPORT_SYMBOL_GPL(snd_dmaengine_pcm_pointer); |
246 | 256 | ||
247 | static int dmaengine_pcm_request_channel(struct dmaengine_pcm_runtime_data *prtd, | 257 | /** |
248 | dma_filter_fn filter_fn, void *filter_data) | 258 | * snd_dmaengine_pcm_request_channel - Request channel for the dmaengine PCM |
259 | * @filter_fn: Filter function used to request the DMA channel | ||
260 | * @filter_data: Data passed to the DMA filter function | ||
261 | * | ||
262 | * Returns NULL or the requested DMA channel. | ||
263 | * | ||
264 | * This function request a DMA channel for usage with dmaengine PCM. | ||
265 | */ | ||
266 | struct dma_chan *snd_dmaengine_pcm_request_channel(dma_filter_fn filter_fn, | ||
267 | void *filter_data) | ||
249 | { | 268 | { |
250 | dma_cap_mask_t mask; | 269 | dma_cap_mask_t mask; |
251 | 270 | ||
252 | dma_cap_zero(mask); | 271 | dma_cap_zero(mask); |
253 | dma_cap_set(DMA_SLAVE, mask); | 272 | dma_cap_set(DMA_SLAVE, mask); |
254 | dma_cap_set(DMA_CYCLIC, mask); | 273 | dma_cap_set(DMA_CYCLIC, mask); |
255 | prtd->dma_chan = dma_request_channel(mask, filter_fn, filter_data); | ||
256 | 274 | ||
257 | if (!prtd->dma_chan) | 275 | return dma_request_channel(mask, filter_fn, filter_data); |
258 | return -ENXIO; | ||
259 | |||
260 | return 0; | ||
261 | } | 276 | } |
277 | EXPORT_SYMBOL_GPL(snd_dmaengine_pcm_request_channel); | ||
262 | 278 | ||
263 | /** | 279 | /** |
264 | * snd_dmaengine_pcm_open - Open a dmaengine based PCM substream | 280 | * snd_dmaengine_pcm_open - Open a dmaengine based PCM substream |
265 | * @substream: PCM substream | 281 | * @substream: PCM substream |
266 | * @filter_fn: Filter function used to request the DMA channel | 282 | * @chan: DMA channel to use for data transfers |
267 | * @filter_data: Data passed to the DMA filter function | ||
268 | * | 283 | * |
269 | * Returns 0 on success, a negative error code otherwise. | 284 | * Returns 0 on success, a negative error code otherwise. |
270 | * | 285 | * |
271 | * This function will request a DMA channel using the passed filter function and | 286 | * The function should usually be called from the pcm open callback. Note that |
272 | * data. The function should usually be called from the pcm open callback. | 287 | * this function will use private_data field of the substream's runtime. So it |
273 | * | 288 | * is not availabe to your pcm driver implementation. |
274 | * Note that this function will use private_data field of the substream's | ||
275 | * runtime. So it is not availabe to your pcm driver implementation. If you need | ||
276 | * to keep additional data attached to a substream use | ||
277 | * snd_dmaengine_pcm_{set,get}_data. | ||
278 | */ | 289 | */ |
279 | int snd_dmaengine_pcm_open(struct snd_pcm_substream *substream, | 290 | int snd_dmaengine_pcm_open(struct snd_pcm_substream *substream, |
280 | dma_filter_fn filter_fn, void *filter_data) | 291 | struct dma_chan *chan) |
281 | { | 292 | { |
282 | struct dmaengine_pcm_runtime_data *prtd; | 293 | struct dmaengine_pcm_runtime_data *prtd; |
283 | int ret; | 294 | int ret; |
284 | 295 | ||
296 | if (!chan) | ||
297 | return -ENXIO; | ||
298 | |||
285 | ret = snd_pcm_hw_constraint_integer(substream->runtime, | 299 | ret = snd_pcm_hw_constraint_integer(substream->runtime, |
286 | SNDRV_PCM_HW_PARAM_PERIODS); | 300 | SNDRV_PCM_HW_PARAM_PERIODS); |
287 | if (ret < 0) | 301 | if (ret < 0) |
@@ -291,11 +305,7 @@ int snd_dmaengine_pcm_open(struct snd_pcm_substream *substream, | |||
291 | if (!prtd) | 305 | if (!prtd) |
292 | return -ENOMEM; | 306 | return -ENOMEM; |
293 | 307 | ||
294 | ret = dmaengine_pcm_request_channel(prtd, filter_fn, filter_data); | 308 | prtd->dma_chan = chan; |
295 | if (ret < 0) { | ||
296 | kfree(prtd); | ||
297 | return ret; | ||
298 | } | ||
299 | 309 | ||
300 | substream->runtime->private_data = prtd; | 310 | substream->runtime->private_data = prtd; |
301 | 311 | ||
@@ -304,6 +314,27 @@ int snd_dmaengine_pcm_open(struct snd_pcm_substream *substream, | |||
304 | EXPORT_SYMBOL_GPL(snd_dmaengine_pcm_open); | 314 | EXPORT_SYMBOL_GPL(snd_dmaengine_pcm_open); |
305 | 315 | ||
306 | /** | 316 | /** |
317 | * snd_dmaengine_pcm_open_request_chan - Open a dmaengine based PCM substream and request channel | ||
318 | * @substream: PCM substream | ||
319 | * @filter_fn: Filter function used to request the DMA channel | ||
320 | * @filter_data: Data passed to the DMA filter function | ||
321 | * | ||
322 | * Returns 0 on success, a negative error code otherwise. | ||
323 | * | ||
324 | * This function will request a DMA channel using the passed filter function and | ||
325 | * data. The function should usually be called from the pcm open callback. Note | ||
326 | * that this function will use private_data field of the substream's runtime. So | ||
327 | * it is not availabe to your pcm driver implementation. | ||
328 | */ | ||
329 | int snd_dmaengine_pcm_open_request_chan(struct snd_pcm_substream *substream, | ||
330 | dma_filter_fn filter_fn, void *filter_data) | ||
331 | { | ||
332 | return snd_dmaengine_pcm_open(substream, | ||
333 | snd_dmaengine_pcm_request_channel(filter_fn, filter_data)); | ||
334 | } | ||
335 | EXPORT_SYMBOL_GPL(snd_dmaengine_pcm_open_request_chan); | ||
336 | |||
337 | /** | ||
307 | * snd_dmaengine_pcm_close - Close a dmaengine based PCM substream | 338 | * snd_dmaengine_pcm_close - Close a dmaengine based PCM substream |
308 | * @substream: PCM substream | 339 | * @substream: PCM substream |
309 | */ | 340 | */ |
@@ -311,11 +342,26 @@ int snd_dmaengine_pcm_close(struct snd_pcm_substream *substream) | |||
311 | { | 342 | { |
312 | struct dmaengine_pcm_runtime_data *prtd = substream_to_prtd(substream); | 343 | struct dmaengine_pcm_runtime_data *prtd = substream_to_prtd(substream); |
313 | 344 | ||
314 | dma_release_channel(prtd->dma_chan); | ||
315 | kfree(prtd); | 345 | kfree(prtd); |
316 | 346 | ||
317 | return 0; | 347 | return 0; |
318 | } | 348 | } |
319 | EXPORT_SYMBOL_GPL(snd_dmaengine_pcm_close); | 349 | EXPORT_SYMBOL_GPL(snd_dmaengine_pcm_close); |
320 | 350 | ||
351 | /** | ||
352 | * snd_dmaengine_pcm_release_chan_close - Close a dmaengine based PCM substream and release channel | ||
353 | * @substream: PCM substream | ||
354 | * | ||
355 | * Releases the DMA channel associated with the PCM substream. | ||
356 | */ | ||
357 | int snd_dmaengine_pcm_close_release_chan(struct snd_pcm_substream *substream) | ||
358 | { | ||
359 | struct dmaengine_pcm_runtime_data *prtd = substream_to_prtd(substream); | ||
360 | |||
361 | dma_release_channel(prtd->dma_chan); | ||
362 | |||
363 | return snd_dmaengine_pcm_close(substream); | ||
364 | } | ||
365 | EXPORT_SYMBOL_GPL(snd_dmaengine_pcm_close_release_chan); | ||
366 | |||
321 | MODULE_LICENSE("GPL"); | 367 | MODULE_LICENSE("GPL"); |
diff --git a/sound/soc/soc-generic-dmaengine-pcm.c b/sound/soc/soc-generic-dmaengine-pcm.c new file mode 100644 index 000000000000..ae0c37e66ae0 --- /dev/null +++ b/sound/soc/soc-generic-dmaengine-pcm.c | |||
@@ -0,0 +1,284 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2013, Analog Devices Inc. | ||
3 | * Author: Lars-Peter Clausen <lars@metafoo.de> | ||
4 | * | ||
5 | * This program is free software; you can redistribute it and/or modify it | ||
6 | * under the terms of the GNU General Public License as published by the | ||
7 | * Free Software Foundation; either version 2 of the License, or (at your | ||
8 | * option) any later version. | ||
9 | * | ||
10 | * You should have received a copy of the GNU General Public License along | ||
11 | * with this program; if not, write to the Free Software Foundation, Inc., | ||
12 | * 675 Mass Ave, Cambridge, MA 02139, USA. | ||
13 | * | ||
14 | */ | ||
15 | #include <linux/module.h> | ||
16 | #include <linux/init.h> | ||
17 | #include <linux/dmaengine.h> | ||
18 | #include <linux/slab.h> | ||
19 | #include <sound/pcm.h> | ||
20 | #include <sound/pcm_params.h> | ||
21 | #include <sound/soc.h> | ||
22 | #include <linux/dma-mapping.h> | ||
23 | #include <linux/of.h> | ||
24 | #include <linux/of_dma.h> | ||
25 | |||
26 | #include <sound/dmaengine_pcm.h> | ||
27 | |||
28 | struct dmaengine_pcm { | ||
29 | struct dma_chan *chan[SNDRV_PCM_STREAM_CAPTURE + 1]; | ||
30 | const struct snd_dmaengine_pcm_config *config; | ||
31 | struct snd_soc_platform platform; | ||
32 | bool compat; | ||
33 | }; | ||
34 | |||
35 | static struct dmaengine_pcm *soc_platform_to_pcm(struct snd_soc_platform *p) | ||
36 | { | ||
37 | return container_of(p, struct dmaengine_pcm, platform); | ||
38 | } | ||
39 | |||
40 | /** | ||
41 | * snd_dmaengine_pcm_prepare_slave_config() - Generic prepare_slave_config callback | ||
42 | * @substream: PCM substream | ||
43 | * @params: hw_params | ||
44 | * @slave_config: DMA slave config to prepare | ||
45 | * | ||
46 | * This function can be used as a generic prepare_slave_config callback for | ||
47 | * platforms which make use of the snd_dmaengine_dai_dma_data struct for their | ||
48 | * DAI DMA data. Internally the function will first call | ||
49 | * snd_hwparams_to_dma_slave_config to fill in the slave config based on the | ||
50 | * hw_params, followed by snd_dmaengine_set_config_from_dai_data to fill in the | ||
51 | * remaining fields based on the DAI DMA data. | ||
52 | */ | ||
53 | int snd_dmaengine_pcm_prepare_slave_config(struct snd_pcm_substream *substream, | ||
54 | struct snd_pcm_hw_params *params, struct dma_slave_config *slave_config) | ||
55 | { | ||
56 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | ||
57 | struct snd_dmaengine_dai_dma_data *dma_data; | ||
58 | int ret; | ||
59 | |||
60 | dma_data = snd_soc_dai_get_dma_data(rtd->cpu_dai, substream); | ||
61 | |||
62 | ret = snd_hwparams_to_dma_slave_config(substream, params, slave_config); | ||
63 | if (ret) | ||
64 | return ret; | ||
65 | |||
66 | snd_dmaengine_pcm_set_config_from_dai_data(substream, dma_data, | ||
67 | slave_config); | ||
68 | |||
69 | return 0; | ||
70 | } | ||
71 | EXPORT_SYMBOL_GPL(snd_dmaengine_pcm_prepare_slave_config); | ||
72 | |||
73 | static int dmaengine_pcm_hw_params(struct snd_pcm_substream *substream, | ||
74 | struct snd_pcm_hw_params *params) | ||
75 | { | ||
76 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | ||
77 | struct dmaengine_pcm *pcm = soc_platform_to_pcm(rtd->platform); | ||
78 | struct dma_chan *chan = snd_dmaengine_pcm_get_chan(substream); | ||
79 | struct dma_slave_config slave_config; | ||
80 | int ret; | ||
81 | |||
82 | if (pcm->config->prepare_slave_config) { | ||
83 | ret = pcm->config->prepare_slave_config(substream, params, | ||
84 | &slave_config); | ||
85 | if (ret) | ||
86 | return ret; | ||
87 | |||
88 | ret = dmaengine_slave_config(chan, &slave_config); | ||
89 | if (ret) | ||
90 | return ret; | ||
91 | } | ||
92 | |||
93 | return snd_pcm_lib_malloc_pages(substream, params_buffer_bytes(params)); | ||
94 | } | ||
95 | |||
96 | static int dmaengine_pcm_open(struct snd_pcm_substream *substream) | ||
97 | { | ||
98 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | ||
99 | struct dmaengine_pcm *pcm = soc_platform_to_pcm(rtd->platform); | ||
100 | struct dma_chan *chan = pcm->chan[substream->stream]; | ||
101 | int ret; | ||
102 | |||
103 | ret = snd_soc_set_runtime_hwparams(substream, | ||
104 | pcm->config->pcm_hardware); | ||
105 | if (ret) | ||
106 | return ret; | ||
107 | |||
108 | return snd_dmaengine_pcm_open(substream, chan); | ||
109 | } | ||
110 | |||
111 | static struct device *dmaengine_dma_dev(struct dmaengine_pcm *pcm, | ||
112 | struct snd_pcm_substream *substream) | ||
113 | { | ||
114 | if (!pcm->chan[substream->stream]) | ||
115 | return NULL; | ||
116 | |||
117 | return pcm->chan[substream->stream]->device->dev; | ||
118 | } | ||
119 | |||
120 | static void dmaengine_pcm_free(struct snd_pcm *pcm) | ||
121 | { | ||
122 | snd_pcm_lib_preallocate_free_for_all(pcm); | ||
123 | } | ||
124 | |||
125 | static struct dma_chan *dmaengine_pcm_compat_request_channel( | ||
126 | struct snd_soc_pcm_runtime *rtd, | ||
127 | struct snd_pcm_substream *substream) | ||
128 | { | ||
129 | struct dmaengine_pcm *pcm = soc_platform_to_pcm(rtd->platform); | ||
130 | |||
131 | if (pcm->config->compat_request_channel) | ||
132 | return pcm->config->compat_request_channel(rtd, substream); | ||
133 | |||
134 | return snd_dmaengine_pcm_request_channel(pcm->config->compat_filter_fn, | ||
135 | snd_soc_dai_get_dma_data(rtd->cpu_dai, substream)); | ||
136 | } | ||
137 | |||
138 | static int dmaengine_pcm_new(struct snd_soc_pcm_runtime *rtd) | ||
139 | { | ||
140 | struct dmaengine_pcm *pcm = soc_platform_to_pcm(rtd->platform); | ||
141 | const struct snd_dmaengine_pcm_config *config = pcm->config; | ||
142 | struct snd_pcm_substream *substream; | ||
143 | unsigned int i; | ||
144 | int ret; | ||
145 | |||
146 | for (i = SNDRV_PCM_STREAM_PLAYBACK; i <= SNDRV_PCM_STREAM_CAPTURE; i++) { | ||
147 | substream = rtd->pcm->streams[i].substream; | ||
148 | if (!substream) | ||
149 | continue; | ||
150 | |||
151 | if (!pcm->chan[i] && pcm->compat) { | ||
152 | pcm->chan[i] = dmaengine_pcm_compat_request_channel(rtd, | ||
153 | substream); | ||
154 | } | ||
155 | |||
156 | if (!pcm->chan[i]) { | ||
157 | dev_err(rtd->platform->dev, | ||
158 | "Missing dma channel for stream: %d\n", i); | ||
159 | ret = -EINVAL; | ||
160 | goto err_free; | ||
161 | } | ||
162 | |||
163 | ret = snd_pcm_lib_preallocate_pages(substream, | ||
164 | SNDRV_DMA_TYPE_DEV, | ||
165 | dmaengine_dma_dev(pcm, substream), | ||
166 | config->prealloc_buffer_size, | ||
167 | config->pcm_hardware->buffer_bytes_max); | ||
168 | if (ret) | ||
169 | goto err_free; | ||
170 | } | ||
171 | |||
172 | return 0; | ||
173 | |||
174 | err_free: | ||
175 | dmaengine_pcm_free(rtd->pcm); | ||
176 | return ret; | ||
177 | } | ||
178 | |||
179 | static const struct snd_pcm_ops dmaengine_pcm_ops = { | ||
180 | .open = dmaengine_pcm_open, | ||
181 | .close = snd_dmaengine_pcm_close, | ||
182 | .ioctl = snd_pcm_lib_ioctl, | ||
183 | .hw_params = dmaengine_pcm_hw_params, | ||
184 | .hw_free = snd_pcm_lib_free_pages, | ||
185 | .trigger = snd_dmaengine_pcm_trigger, | ||
186 | .pointer = snd_dmaengine_pcm_pointer, | ||
187 | }; | ||
188 | |||
189 | static const struct snd_soc_platform_driver dmaengine_pcm_platform = { | ||
190 | .ops = &dmaengine_pcm_ops, | ||
191 | .pcm_new = dmaengine_pcm_new, | ||
192 | .pcm_free = dmaengine_pcm_free, | ||
193 | .probe_order = SND_SOC_COMP_ORDER_LATE, | ||
194 | }; | ||
195 | |||
196 | static const struct snd_pcm_ops dmaengine_no_residue_pcm_ops = { | ||
197 | .open = dmaengine_pcm_open, | ||
198 | .close = snd_dmaengine_pcm_close, | ||
199 | .ioctl = snd_pcm_lib_ioctl, | ||
200 | .hw_params = dmaengine_pcm_hw_params, | ||
201 | .hw_free = snd_pcm_lib_free_pages, | ||
202 | .trigger = snd_dmaengine_pcm_trigger, | ||
203 | .pointer = snd_dmaengine_pcm_pointer_no_residue, | ||
204 | }; | ||
205 | |||
206 | static const struct snd_soc_platform_driver dmaengine_no_residue_pcm_platform = { | ||
207 | .ops = &dmaengine_no_residue_pcm_ops, | ||
208 | .pcm_new = dmaengine_pcm_new, | ||
209 | .pcm_free = dmaengine_pcm_free, | ||
210 | .probe_order = SND_SOC_COMP_ORDER_LATE, | ||
211 | }; | ||
212 | |||
213 | static const char * const dmaengine_pcm_dma_channel_names[] = { | ||
214 | [SNDRV_PCM_STREAM_PLAYBACK] = "tx", | ||
215 | [SNDRV_PCM_STREAM_CAPTURE] = "rx", | ||
216 | }; | ||
217 | |||
218 | /** | ||
219 | * snd_dmaengine_pcm_register - Register a dmaengine based PCM device | ||
220 | * @dev: The parent device for the PCM device | ||
221 | * @config: Platform specific PCM configuration | ||
222 | * @flags: Platform specific quirks | ||
223 | */ | ||
224 | int snd_dmaengine_pcm_register(struct device *dev, | ||
225 | const struct snd_dmaengine_pcm_config *config, unsigned int flags) | ||
226 | { | ||
227 | struct dmaengine_pcm *pcm; | ||
228 | unsigned int i; | ||
229 | |||
230 | pcm = kzalloc(sizeof(*pcm), GFP_KERNEL); | ||
231 | if (!pcm) | ||
232 | return -ENOMEM; | ||
233 | |||
234 | pcm->config = config; | ||
235 | |||
236 | if (flags & SND_DMAENGINE_PCM_FLAG_COMPAT) | ||
237 | pcm->compat = true; | ||
238 | |||
239 | if (!(flags & SND_DMAENGINE_PCM_FLAG_NO_DT) && dev->of_node) { | ||
240 | for (i = SNDRV_PCM_STREAM_PLAYBACK; i <= SNDRV_PCM_STREAM_CAPTURE; i++) { | ||
241 | pcm->chan[i] = of_dma_request_slave_channel(dev->of_node, | ||
242 | dmaengine_pcm_dma_channel_names[i]); | ||
243 | } | ||
244 | } | ||
245 | |||
246 | if (flags & SND_DMAENGINE_PCM_FLAG_NO_RESIDUE) | ||
247 | return snd_soc_add_platform(dev, &pcm->platform, | ||
248 | &dmaengine_no_residue_pcm_platform); | ||
249 | else | ||
250 | return snd_soc_add_platform(dev, &pcm->platform, | ||
251 | &dmaengine_pcm_platform); | ||
252 | } | ||
253 | EXPORT_SYMBOL_GPL(snd_dmaengine_pcm_register); | ||
254 | |||
255 | /** | ||
256 | * snd_dmaengine_pcm_unregister - Removes a dmaengine based PCM device | ||
257 | * @dev: Parent device the PCM was register with | ||
258 | * | ||
259 | * Removes a dmaengine based PCM device previously registered with | ||
260 | * snd_dmaengine_pcm_register. | ||
261 | */ | ||
262 | void snd_dmaengine_pcm_unregister(struct device *dev) | ||
263 | { | ||
264 | struct snd_soc_platform *platform; | ||
265 | struct dmaengine_pcm *pcm; | ||
266 | unsigned int i; | ||
267 | |||
268 | platform = snd_soc_lookup_platform(dev); | ||
269 | if (!platform) | ||
270 | return; | ||
271 | |||
272 | pcm = soc_platform_to_pcm(platform); | ||
273 | |||
274 | for (i = SNDRV_PCM_STREAM_PLAYBACK; i <= SNDRV_PCM_STREAM_CAPTURE; i++) { | ||
275 | if (pcm->chan[i]) | ||
276 | dma_release_channel(pcm->chan[i]); | ||
277 | } | ||
278 | |||
279 | snd_soc_remove_platform(platform); | ||
280 | kfree(pcm); | ||
281 | } | ||
282 | EXPORT_SYMBOL_GPL(snd_dmaengine_pcm_unregister); | ||
283 | |||
284 | MODULE_LICENSE("GPL"); | ||
diff --git a/sound/soc/spear/spear_pcm.c b/sound/soc/spear/spear_pcm.c index 5e7aebe1e664..d653763f83b7 100644 --- a/sound/soc/spear/spear_pcm.c +++ b/sound/soc/spear/spear_pcm.c | |||
@@ -64,21 +64,8 @@ static int spear_pcm_open(struct snd_pcm_substream *substream) | |||
64 | if (ret) | 64 | if (ret) |
65 | return ret; | 65 | return ret; |
66 | 66 | ||
67 | ret = snd_dmaengine_pcm_open(substream, dma_data->filter, dma_data); | 67 | return snd_dmaengine_pcm_open_request_chan(substream, dma_data->filter, |
68 | if (ret) | 68 | dma_data); |
69 | return ret; | ||
70 | |||
71 | snd_dmaengine_pcm_set_data(substream, dma_data); | ||
72 | |||
73 | return 0; | ||
74 | } | ||
75 | |||
76 | static int spear_pcm_close(struct snd_pcm_substream *substream) | ||
77 | { | ||
78 | |||
79 | snd_dmaengine_pcm_close(substream); | ||
80 | |||
81 | return 0; | ||
82 | } | 69 | } |
83 | 70 | ||
84 | static int spear_pcm_mmap(struct snd_pcm_substream *substream, | 71 | static int spear_pcm_mmap(struct snd_pcm_substream *substream, |
@@ -93,7 +80,7 @@ static int spear_pcm_mmap(struct snd_pcm_substream *substream, | |||
93 | 80 | ||
94 | static struct snd_pcm_ops spear_pcm_ops = { | 81 | static struct snd_pcm_ops spear_pcm_ops = { |
95 | .open = spear_pcm_open, | 82 | .open = spear_pcm_open, |
96 | .close = spear_pcm_close, | 83 | .close = snd_dmaengine_pcm_close_release_chan, |
97 | .ioctl = snd_pcm_lib_ioctl, | 84 | .ioctl = snd_pcm_lib_ioctl, |
98 | .hw_params = spear_pcm_hw_params, | 85 | .hw_params = spear_pcm_hw_params, |
99 | .hw_free = spear_pcm_hw_free, | 86 | .hw_free = spear_pcm_hw_free, |
diff --git a/sound/soc/tegra/Kconfig b/sound/soc/tegra/Kconfig index dbc27ce1d4de..b1c9d573da05 100644 --- a/sound/soc/tegra/Kconfig +++ b/sound/soc/tegra/Kconfig | |||
@@ -2,7 +2,7 @@ config SND_SOC_TEGRA | |||
2 | tristate "SoC Audio for the Tegra System-on-Chip" | 2 | tristate "SoC Audio for the Tegra System-on-Chip" |
3 | depends on ARCH_TEGRA && TEGRA20_APB_DMA | 3 | depends on ARCH_TEGRA && TEGRA20_APB_DMA |
4 | select REGMAP_MMIO | 4 | select REGMAP_MMIO |
5 | select SND_SOC_DMAENGINE_PCM if TEGRA20_APB_DMA | 5 | select SND_SOC_GENERIC_DMAENGINE_PCM if TEGRA20_APB_DMA |
6 | help | 6 | help |
7 | Say Y or M here if you want support for SoC audio on Tegra. | 7 | Say Y or M here if you want support for SoC audio on Tegra. |
8 | 8 | ||
diff --git a/sound/soc/tegra/tegra20_ac97.c b/sound/soc/tegra/tegra20_ac97.c index 336dcdd3e8a4..2d7b8c2719ce 100644 --- a/sound/soc/tegra/tegra20_ac97.c +++ b/sound/soc/tegra/tegra20_ac97.c | |||
@@ -35,6 +35,7 @@ | |||
35 | #include <sound/pcm.h> | 35 | #include <sound/pcm.h> |
36 | #include <sound/pcm_params.h> | 36 | #include <sound/pcm_params.h> |
37 | #include <sound/soc.h> | 37 | #include <sound/soc.h> |
38 | #include <sound/dmaengine_pcm.h> | ||
38 | 39 | ||
39 | #include "tegra_asoc_utils.h" | 40 | #include "tegra_asoc_utils.h" |
40 | #include "tegra20_ac97.h" | 41 | #include "tegra20_ac97.h" |
@@ -389,14 +390,14 @@ static int tegra20_ac97_platform_probe(struct platform_device *pdev) | |||
389 | } | 390 | } |
390 | 391 | ||
391 | ac97->capture_dma_data.addr = mem->start + TEGRA20_AC97_FIFO_RX1; | 392 | ac97->capture_dma_data.addr = mem->start + TEGRA20_AC97_FIFO_RX1; |
392 | ac97->capture_dma_data.wrap = 4; | 393 | ac97->capture_dma_data.addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES; |
393 | ac97->capture_dma_data.width = 32; | 394 | ac97->capture_dma_data.maxburst = 4; |
394 | ac97->capture_dma_data.req_sel = of_dma[1]; | 395 | ac97->capture_dma_data.slave_id = of_dma[1]; |
395 | 396 | ||
396 | ac97->playback_dma_data.addr = mem->start + TEGRA20_AC97_FIFO_TX1; | 397 | ac97->playback_dma_data.addr = mem->start + TEGRA20_AC97_FIFO_TX1; |
397 | ac97->playback_dma_data.wrap = 4; | 398 | ac97->capture_dma_data.addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES; |
398 | ac97->playback_dma_data.width = 32; | 399 | ac97->capture_dma_data.maxburst = 4; |
399 | ac97->playback_dma_data.req_sel = of_dma[1]; | 400 | ac97->capture_dma_data.slave_id = of_dma[0]; |
400 | 401 | ||
401 | ret = snd_soc_register_dais(&pdev->dev, &tegra20_ac97_dai, 1); | 402 | ret = snd_soc_register_dais(&pdev->dev, &tegra20_ac97_dai, 1); |
402 | if (ret) { | 403 | if (ret) { |
diff --git a/sound/soc/tegra/tegra20_ac97.h b/sound/soc/tegra/tegra20_ac97.h index dddc6828004e..4acb3aaba29b 100644 --- a/sound/soc/tegra/tegra20_ac97.h +++ b/sound/soc/tegra/tegra20_ac97.h | |||
@@ -85,8 +85,8 @@ | |||
85 | 85 | ||
86 | struct tegra20_ac97 { | 86 | struct tegra20_ac97 { |
87 | struct clk *clk_ac97; | 87 | struct clk *clk_ac97; |
88 | struct tegra_pcm_dma_params capture_dma_data; | 88 | struct snd_dmaengine_dai_dma_data capture_dma_data; |
89 | struct tegra_pcm_dma_params playback_dma_data; | 89 | struct snd_dmaengine_dai_dma_data playback_dma_data; |
90 | struct regmap *regmap; | 90 | struct regmap *regmap; |
91 | int reset_gpio; | 91 | int reset_gpio; |
92 | int sync_gpio; | 92 | int sync_gpio; |
diff --git a/sound/soc/tegra/tegra20_i2s.c b/sound/soc/tegra/tegra20_i2s.c index caa772de5a18..e6651e0eaeed 100644 --- a/sound/soc/tegra/tegra20_i2s.c +++ b/sound/soc/tegra/tegra20_i2s.c | |||
@@ -41,6 +41,7 @@ | |||
41 | #include <sound/pcm.h> | 41 | #include <sound/pcm.h> |
42 | #include <sound/pcm_params.h> | 42 | #include <sound/pcm_params.h> |
43 | #include <sound/soc.h> | 43 | #include <sound/soc.h> |
44 | #include <sound/dmaengine_pcm.h> | ||
44 | 45 | ||
45 | #include "tegra20_i2s.h" | 46 | #include "tegra20_i2s.h" |
46 | 47 | ||
@@ -403,14 +404,14 @@ static int tegra20_i2s_platform_probe(struct platform_device *pdev) | |||
403 | } | 404 | } |
404 | 405 | ||
405 | i2s->capture_dma_data.addr = mem->start + TEGRA20_I2S_FIFO2; | 406 | i2s->capture_dma_data.addr = mem->start + TEGRA20_I2S_FIFO2; |
406 | i2s->capture_dma_data.wrap = 4; | 407 | i2s->capture_dma_data.addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES; |
407 | i2s->capture_dma_data.width = 32; | 408 | i2s->capture_dma_data.maxburst = 4; |
408 | i2s->capture_dma_data.req_sel = dma_ch; | 409 | i2s->capture_dma_data.slave_id = dma_ch; |
409 | 410 | ||
410 | i2s->playback_dma_data.addr = mem->start + TEGRA20_I2S_FIFO1; | 411 | i2s->playback_dma_data.addr = mem->start + TEGRA20_I2S_FIFO1; |
411 | i2s->playback_dma_data.wrap = 4; | 412 | i2s->playback_dma_data.addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES; |
412 | i2s->playback_dma_data.width = 32; | 413 | i2s->playback_dma_data.maxburst = 4; |
413 | i2s->playback_dma_data.req_sel = dma_ch; | 414 | i2s->playback_dma_data.slave_id = dma_ch; |
414 | 415 | ||
415 | pm_runtime_enable(&pdev->dev); | 416 | pm_runtime_enable(&pdev->dev); |
416 | if (!pm_runtime_enabled(&pdev->dev)) { | 417 | if (!pm_runtime_enabled(&pdev->dev)) { |
diff --git a/sound/soc/tegra/tegra20_i2s.h b/sound/soc/tegra/tegra20_i2s.h index 729958713cd4..fa6c29cc12b9 100644 --- a/sound/soc/tegra/tegra20_i2s.h +++ b/sound/soc/tegra/tegra20_i2s.h | |||
@@ -155,8 +155,8 @@ | |||
155 | struct tegra20_i2s { | 155 | struct tegra20_i2s { |
156 | struct snd_soc_dai_driver dai; | 156 | struct snd_soc_dai_driver dai; |
157 | struct clk *clk_i2s; | 157 | struct clk *clk_i2s; |
158 | struct tegra_pcm_dma_params capture_dma_data; | 158 | struct snd_dmaengine_dai_dma_data capture_dma_data; |
159 | struct tegra_pcm_dma_params playback_dma_data; | 159 | struct snd_dmaengine_dai_dma_data playback_dma_data; |
160 | struct regmap *regmap; | 160 | struct regmap *regmap; |
161 | }; | 161 | }; |
162 | 162 | ||
diff --git a/sound/soc/tegra/tegra20_spdif.c b/sound/soc/tegra/tegra20_spdif.c index 04771d14d343..b7b4743cc94d 100644 --- a/sound/soc/tegra/tegra20_spdif.c +++ b/sound/soc/tegra/tegra20_spdif.c | |||
@@ -32,6 +32,7 @@ | |||
32 | #include <sound/pcm.h> | 32 | #include <sound/pcm.h> |
33 | #include <sound/pcm_params.h> | 33 | #include <sound/pcm_params.h> |
34 | #include <sound/soc.h> | 34 | #include <sound/soc.h> |
35 | #include <sound/dmaengine_pcm.h> | ||
35 | 36 | ||
36 | #include "tegra20_spdif.h" | 37 | #include "tegra20_spdif.h" |
37 | 38 | ||
@@ -318,9 +319,9 @@ static int tegra20_spdif_platform_probe(struct platform_device *pdev) | |||
318 | } | 319 | } |
319 | 320 | ||
320 | spdif->playback_dma_data.addr = mem->start + TEGRA20_SPDIF_DATA_OUT; | 321 | spdif->playback_dma_data.addr = mem->start + TEGRA20_SPDIF_DATA_OUT; |
321 | spdif->playback_dma_data.wrap = 4; | 322 | spdif->capture_dma_data.addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES; |
322 | spdif->playback_dma_data.width = 32; | 323 | spdif->capture_dma_data.maxburst = 4; |
323 | spdif->playback_dma_data.req_sel = dmareq->start; | 324 | spdif->playback_dma_data.slave_id = dmareq->start; |
324 | 325 | ||
325 | pm_runtime_enable(&pdev->dev); | 326 | pm_runtime_enable(&pdev->dev); |
326 | if (!pm_runtime_enabled(&pdev->dev)) { | 327 | if (!pm_runtime_enabled(&pdev->dev)) { |
diff --git a/sound/soc/tegra/tegra20_spdif.h b/sound/soc/tegra/tegra20_spdif.h index b48d699fd583..85a9aefcc287 100644 --- a/sound/soc/tegra/tegra20_spdif.h +++ b/sound/soc/tegra/tegra20_spdif.h | |||
@@ -462,8 +462,8 @@ | |||
462 | 462 | ||
463 | struct tegra20_spdif { | 463 | struct tegra20_spdif { |
464 | struct clk *clk_spdif_out; | 464 | struct clk *clk_spdif_out; |
465 | struct tegra_pcm_dma_params capture_dma_data; | 465 | struct snd_dmaengine_dai_dma_data capture_dma_data; |
466 | struct tegra_pcm_dma_params playback_dma_data; | 466 | struct snd_dmaengine_dai_dma_data playback_dma_data; |
467 | struct regmap *regmap; | 467 | struct regmap *regmap; |
468 | }; | 468 | }; |
469 | 469 | ||
diff --git a/sound/soc/tegra/tegra30_ahub.c b/sound/soc/tegra/tegra30_ahub.c index e5cfb4ac41ba..5e08f3e7e6cf 100644 --- a/sound/soc/tegra/tegra30_ahub.c +++ b/sound/soc/tegra/tegra30_ahub.c | |||
@@ -95,8 +95,8 @@ static int tegra30_ahub_runtime_resume(struct device *dev) | |||
95 | } | 95 | } |
96 | 96 | ||
97 | int tegra30_ahub_allocate_rx_fifo(enum tegra30_ahub_rxcif *rxcif, | 97 | int tegra30_ahub_allocate_rx_fifo(enum tegra30_ahub_rxcif *rxcif, |
98 | unsigned long *fiforeg, | 98 | dma_addr_t *fiforeg, |
99 | unsigned long *reqsel) | 99 | unsigned int *reqsel) |
100 | { | 100 | { |
101 | int channel; | 101 | int channel; |
102 | u32 reg, val; | 102 | u32 reg, val; |
@@ -178,8 +178,8 @@ int tegra30_ahub_free_rx_fifo(enum tegra30_ahub_rxcif rxcif) | |||
178 | EXPORT_SYMBOL_GPL(tegra30_ahub_free_rx_fifo); | 178 | EXPORT_SYMBOL_GPL(tegra30_ahub_free_rx_fifo); |
179 | 179 | ||
180 | int tegra30_ahub_allocate_tx_fifo(enum tegra30_ahub_txcif *txcif, | 180 | int tegra30_ahub_allocate_tx_fifo(enum tegra30_ahub_txcif *txcif, |
181 | unsigned long *fiforeg, | 181 | dma_addr_t *fiforeg, |
182 | unsigned long *reqsel) | 182 | unsigned int *reqsel) |
183 | { | 183 | { |
184 | int channel; | 184 | int channel; |
185 | u32 reg, val; | 185 | u32 reg, val; |
diff --git a/sound/soc/tegra/tegra30_ahub.h b/sound/soc/tegra/tegra30_ahub.h index e690e2eecc92..b7d7c1a30302 100644 --- a/sound/soc/tegra/tegra30_ahub.h +++ b/sound/soc/tegra/tegra30_ahub.h | |||
@@ -451,15 +451,15 @@ enum tegra30_ahub_rxcif { | |||
451 | }; | 451 | }; |
452 | 452 | ||
453 | extern int tegra30_ahub_allocate_rx_fifo(enum tegra30_ahub_rxcif *rxcif, | 453 | extern int tegra30_ahub_allocate_rx_fifo(enum tegra30_ahub_rxcif *rxcif, |
454 | unsigned long *fiforeg, | 454 | dma_addr_t *fiforeg, |
455 | unsigned long *reqsel); | 455 | unsigned int *reqsel); |
456 | extern int tegra30_ahub_enable_rx_fifo(enum tegra30_ahub_rxcif rxcif); | 456 | extern int tegra30_ahub_enable_rx_fifo(enum tegra30_ahub_rxcif rxcif); |
457 | extern int tegra30_ahub_disable_rx_fifo(enum tegra30_ahub_rxcif rxcif); | 457 | extern int tegra30_ahub_disable_rx_fifo(enum tegra30_ahub_rxcif rxcif); |
458 | extern int tegra30_ahub_free_rx_fifo(enum tegra30_ahub_rxcif rxcif); | 458 | extern int tegra30_ahub_free_rx_fifo(enum tegra30_ahub_rxcif rxcif); |
459 | 459 | ||
460 | extern int tegra30_ahub_allocate_tx_fifo(enum tegra30_ahub_txcif *txcif, | 460 | extern int tegra30_ahub_allocate_tx_fifo(enum tegra30_ahub_txcif *txcif, |
461 | unsigned long *fiforeg, | 461 | dma_addr_t *fiforeg, |
462 | unsigned long *reqsel); | 462 | unsigned int *reqsel); |
463 | extern int tegra30_ahub_enable_tx_fifo(enum tegra30_ahub_txcif txcif); | 463 | extern int tegra30_ahub_enable_tx_fifo(enum tegra30_ahub_txcif txcif); |
464 | extern int tegra30_ahub_disable_tx_fifo(enum tegra30_ahub_txcif txcif); | 464 | extern int tegra30_ahub_disable_tx_fifo(enum tegra30_ahub_txcif txcif); |
465 | extern int tegra30_ahub_free_tx_fifo(enum tegra30_ahub_txcif txcif); | 465 | extern int tegra30_ahub_free_tx_fifo(enum tegra30_ahub_txcif txcif); |
diff --git a/sound/soc/tegra/tegra30_i2s.c b/sound/soc/tegra/tegra30_i2s.c index f4e1ce82750a..857ec21e3c7d 100644 --- a/sound/soc/tegra/tegra30_i2s.c +++ b/sound/soc/tegra/tegra30_i2s.c | |||
@@ -38,6 +38,7 @@ | |||
38 | #include <sound/pcm.h> | 38 | #include <sound/pcm.h> |
39 | #include <sound/pcm_params.h> | 39 | #include <sound/pcm_params.h> |
40 | #include <sound/soc.h> | 40 | #include <sound/soc.h> |
41 | #include <sound/dmaengine_pcm.h> | ||
41 | 42 | ||
42 | #include "tegra30_ahub.h" | 43 | #include "tegra30_ahub.h" |
43 | #include "tegra30_i2s.h" | 44 | #include "tegra30_i2s.h" |
@@ -80,17 +81,17 @@ static int tegra30_i2s_startup(struct snd_pcm_substream *substream, | |||
80 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { | 81 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { |
81 | ret = tegra30_ahub_allocate_tx_fifo(&i2s->playback_fifo_cif, | 82 | ret = tegra30_ahub_allocate_tx_fifo(&i2s->playback_fifo_cif, |
82 | &i2s->playback_dma_data.addr, | 83 | &i2s->playback_dma_data.addr, |
83 | &i2s->playback_dma_data.req_sel); | 84 | &i2s->playback_dma_data.slave_id); |
84 | i2s->playback_dma_data.wrap = 4; | 85 | i2s->playback_dma_data.addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES; |
85 | i2s->playback_dma_data.width = 32; | 86 | i2s->playback_dma_data.maxburst = 4; |
86 | tegra30_ahub_set_rx_cif_source(i2s->playback_i2s_cif, | 87 | tegra30_ahub_set_rx_cif_source(i2s->playback_i2s_cif, |
87 | i2s->playback_fifo_cif); | 88 | i2s->playback_fifo_cif); |
88 | } else { | 89 | } else { |
89 | ret = tegra30_ahub_allocate_rx_fifo(&i2s->capture_fifo_cif, | 90 | ret = tegra30_ahub_allocate_rx_fifo(&i2s->capture_fifo_cif, |
90 | &i2s->capture_dma_data.addr, | 91 | &i2s->capture_dma_data.addr, |
91 | &i2s->capture_dma_data.req_sel); | 92 | &i2s->capture_dma_data.slave_id); |
92 | i2s->capture_dma_data.wrap = 4; | 93 | i2s->capture_dma_data.addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES; |
93 | i2s->capture_dma_data.width = 32; | 94 | i2s->capture_dma_data.maxburst = 4; |
94 | tegra30_ahub_set_rx_cif_source(i2s->capture_fifo_cif, | 95 | tegra30_ahub_set_rx_cif_source(i2s->capture_fifo_cif, |
95 | i2s->capture_i2s_cif); | 96 | i2s->capture_i2s_cif); |
96 | } | 97 | } |
diff --git a/sound/soc/tegra/tegra30_i2s.h b/sound/soc/tegra/tegra30_i2s.h index a294d942b9f7..bea23afe3b9f 100644 --- a/sound/soc/tegra/tegra30_i2s.h +++ b/sound/soc/tegra/tegra30_i2s.h | |||
@@ -231,10 +231,10 @@ struct tegra30_i2s { | |||
231 | struct clk *clk_i2s; | 231 | struct clk *clk_i2s; |
232 | enum tegra30_ahub_txcif capture_i2s_cif; | 232 | enum tegra30_ahub_txcif capture_i2s_cif; |
233 | enum tegra30_ahub_rxcif capture_fifo_cif; | 233 | enum tegra30_ahub_rxcif capture_fifo_cif; |
234 | struct tegra_pcm_dma_params capture_dma_data; | 234 | struct snd_dmaengine_dai_dma_data capture_dma_data; |
235 | enum tegra30_ahub_rxcif playback_i2s_cif; | 235 | enum tegra30_ahub_rxcif playback_i2s_cif; |
236 | enum tegra30_ahub_txcif playback_fifo_cif; | 236 | enum tegra30_ahub_txcif playback_fifo_cif; |
237 | struct tegra_pcm_dma_params playback_dma_data; | 237 | struct snd_dmaengine_dai_dma_data playback_dma_data; |
238 | struct regmap *regmap; | 238 | struct regmap *regmap; |
239 | }; | 239 | }; |
240 | 240 | ||
diff --git a/sound/soc/tegra/tegra_pcm.c b/sound/soc/tegra/tegra_pcm.c index 5e2c55c5b255..f056f632557c 100644 --- a/sound/soc/tegra/tegra_pcm.c +++ b/sound/soc/tegra/tegra_pcm.c | |||
@@ -29,9 +29,7 @@ | |||
29 | * | 29 | * |
30 | */ | 30 | */ |
31 | 31 | ||
32 | #include <linux/dma-mapping.h> | ||
33 | #include <linux/module.h> | 32 | #include <linux/module.h> |
34 | #include <linux/slab.h> | ||
35 | #include <sound/core.h> | 33 | #include <sound/core.h> |
36 | #include <sound/pcm.h> | 34 | #include <sound/pcm.h> |
37 | #include <sound/pcm_params.h> | 35 | #include <sound/pcm_params.h> |
@@ -55,191 +53,24 @@ static const struct snd_pcm_hardware tegra_pcm_hardware = { | |||
55 | .fifo_size = 4, | 53 | .fifo_size = 4, |
56 | }; | 54 | }; |
57 | 55 | ||
58 | static int tegra_pcm_open(struct snd_pcm_substream *substream) | 56 | static const struct snd_dmaengine_pcm_config tegra_dmaengine_pcm_config = { |
59 | { | 57 | .pcm_hardware = &tegra_pcm_hardware, |
60 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | 58 | .prepare_slave_config = snd_dmaengine_pcm_prepare_slave_config, |
61 | struct device *dev = rtd->platform->dev; | 59 | .compat_filter_fn = NULL, |
62 | int ret; | 60 | .prealloc_buffer_size = PAGE_SIZE * 8, |
63 | |||
64 | /* Set HW params now that initialization is complete */ | ||
65 | snd_soc_set_runtime_hwparams(substream, &tegra_pcm_hardware); | ||
66 | |||
67 | ret = snd_dmaengine_pcm_open(substream, NULL, NULL); | ||
68 | if (ret) { | ||
69 | dev_err(dev, "dmaengine pcm open failed with err %d\n", ret); | ||
70 | return ret; | ||
71 | } | ||
72 | |||
73 | return 0; | ||
74 | } | ||
75 | |||
76 | static int tegra_pcm_close(struct snd_pcm_substream *substream) | ||
77 | { | ||
78 | snd_dmaengine_pcm_close(substream); | ||
79 | return 0; | ||
80 | } | ||
81 | |||
82 | static int tegra_pcm_hw_params(struct snd_pcm_substream *substream, | ||
83 | struct snd_pcm_hw_params *params) | ||
84 | { | ||
85 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | ||
86 | struct device *dev = rtd->platform->dev; | ||
87 | struct dma_chan *chan = snd_dmaengine_pcm_get_chan(substream); | ||
88 | struct tegra_pcm_dma_params *dmap; | ||
89 | struct dma_slave_config slave_config; | ||
90 | int ret; | ||
91 | |||
92 | dmap = snd_soc_dai_get_dma_data(rtd->cpu_dai, substream); | ||
93 | |||
94 | ret = snd_hwparams_to_dma_slave_config(substream, params, | ||
95 | &slave_config); | ||
96 | if (ret) { | ||
97 | dev_err(dev, "hw params config failed with err %d\n", ret); | ||
98 | return ret; | ||
99 | } | ||
100 | |||
101 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { | ||
102 | slave_config.dst_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES; | ||
103 | slave_config.dst_addr = dmap->addr; | ||
104 | slave_config.dst_maxburst = 4; | ||
105 | } else { | ||
106 | slave_config.src_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES; | ||
107 | slave_config.src_addr = dmap->addr; | ||
108 | slave_config.src_maxburst = 4; | ||
109 | } | ||
110 | slave_config.slave_id = dmap->req_sel; | ||
111 | |||
112 | ret = dmaengine_slave_config(chan, &slave_config); | ||
113 | if (ret < 0) { | ||
114 | dev_err(dev, "dma slave config failed with err %d\n", ret); | ||
115 | return ret; | ||
116 | } | ||
117 | |||
118 | snd_pcm_set_runtime_buffer(substream, &substream->dma_buffer); | ||
119 | return 0; | ||
120 | } | ||
121 | |||
122 | static int tegra_pcm_hw_free(struct snd_pcm_substream *substream) | ||
123 | { | ||
124 | snd_pcm_set_runtime_buffer(substream, NULL); | ||
125 | return 0; | ||
126 | } | ||
127 | |||
128 | static int tegra_pcm_mmap(struct snd_pcm_substream *substream, | ||
129 | struct vm_area_struct *vma) | ||
130 | { | ||
131 | struct snd_pcm_runtime *runtime = substream->runtime; | ||
132 | |||
133 | return dma_mmap_writecombine(substream->pcm->card->dev, vma, | ||
134 | runtime->dma_area, | ||
135 | runtime->dma_addr, | ||
136 | runtime->dma_bytes); | ||
137 | } | ||
138 | |||
139 | static struct snd_pcm_ops tegra_pcm_ops = { | ||
140 | .open = tegra_pcm_open, | ||
141 | .close = tegra_pcm_close, | ||
142 | .ioctl = snd_pcm_lib_ioctl, | ||
143 | .hw_params = tegra_pcm_hw_params, | ||
144 | .hw_free = tegra_pcm_hw_free, | ||
145 | .trigger = snd_dmaengine_pcm_trigger, | ||
146 | .pointer = snd_dmaengine_pcm_pointer, | ||
147 | .mmap = tegra_pcm_mmap, | ||
148 | }; | ||
149 | |||
150 | static int tegra_pcm_preallocate_dma_buffer(struct snd_pcm *pcm, int stream) | ||
151 | { | ||
152 | struct snd_pcm_substream *substream = pcm->streams[stream].substream; | ||
153 | struct snd_dma_buffer *buf = &substream->dma_buffer; | ||
154 | size_t size = tegra_pcm_hardware.buffer_bytes_max; | ||
155 | |||
156 | buf->area = dma_alloc_writecombine(pcm->card->dev, size, | ||
157 | &buf->addr, GFP_KERNEL); | ||
158 | if (!buf->area) | ||
159 | return -ENOMEM; | ||
160 | |||
161 | buf->dev.type = SNDRV_DMA_TYPE_DEV; | ||
162 | buf->dev.dev = pcm->card->dev; | ||
163 | buf->private_data = NULL; | ||
164 | buf->bytes = size; | ||
165 | |||
166 | return 0; | ||
167 | } | ||
168 | |||
169 | static void tegra_pcm_deallocate_dma_buffer(struct snd_pcm *pcm, int stream) | ||
170 | { | ||
171 | struct snd_pcm_substream *substream; | ||
172 | struct snd_dma_buffer *buf; | ||
173 | |||
174 | substream = pcm->streams[stream].substream; | ||
175 | if (!substream) | ||
176 | return; | ||
177 | |||
178 | buf = &substream->dma_buffer; | ||
179 | if (!buf->area) | ||
180 | return; | ||
181 | |||
182 | dma_free_writecombine(pcm->card->dev, buf->bytes, | ||
183 | buf->area, buf->addr); | ||
184 | buf->area = NULL; | ||
185 | } | ||
186 | |||
187 | static u64 tegra_dma_mask = DMA_BIT_MASK(32); | ||
188 | |||
189 | static int tegra_pcm_new(struct snd_soc_pcm_runtime *rtd) | ||
190 | { | ||
191 | struct snd_card *card = rtd->card->snd_card; | ||
192 | struct snd_pcm *pcm = rtd->pcm; | ||
193 | int ret = 0; | ||
194 | |||
195 | if (!card->dev->dma_mask) | ||
196 | card->dev->dma_mask = &tegra_dma_mask; | ||
197 | if (!card->dev->coherent_dma_mask) | ||
198 | card->dev->coherent_dma_mask = DMA_BIT_MASK(32); | ||
199 | |||
200 | if (pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream) { | ||
201 | ret = tegra_pcm_preallocate_dma_buffer(pcm, | ||
202 | SNDRV_PCM_STREAM_PLAYBACK); | ||
203 | if (ret) | ||
204 | goto err; | ||
205 | } | ||
206 | |||
207 | if (pcm->streams[SNDRV_PCM_STREAM_CAPTURE].substream) { | ||
208 | ret = tegra_pcm_preallocate_dma_buffer(pcm, | ||
209 | SNDRV_PCM_STREAM_CAPTURE); | ||
210 | if (ret) | ||
211 | goto err_free_play; | ||
212 | } | ||
213 | |||
214 | return 0; | ||
215 | |||
216 | err_free_play: | ||
217 | tegra_pcm_deallocate_dma_buffer(pcm, SNDRV_PCM_STREAM_PLAYBACK); | ||
218 | err: | ||
219 | return ret; | ||
220 | } | ||
221 | |||
222 | static void tegra_pcm_free(struct snd_pcm *pcm) | ||
223 | { | ||
224 | tegra_pcm_deallocate_dma_buffer(pcm, SNDRV_PCM_STREAM_CAPTURE); | ||
225 | tegra_pcm_deallocate_dma_buffer(pcm, SNDRV_PCM_STREAM_PLAYBACK); | ||
226 | } | ||
227 | |||
228 | static struct snd_soc_platform_driver tegra_pcm_platform = { | ||
229 | .ops = &tegra_pcm_ops, | ||
230 | .pcm_new = tegra_pcm_new, | ||
231 | .pcm_free = tegra_pcm_free, | ||
232 | }; | 61 | }; |
233 | 62 | ||
234 | int tegra_pcm_platform_register(struct device *dev) | 63 | int tegra_pcm_platform_register(struct device *dev) |
235 | { | 64 | { |
236 | return snd_soc_register_platform(dev, &tegra_pcm_platform); | 65 | return snd_dmaengine_pcm_register(dev, &tegra_dmaengine_pcm_config, |
66 | SND_DMAENGINE_PCM_FLAG_NO_DT | | ||
67 | SND_DMAENGINE_PCM_FLAG_COMPAT); | ||
237 | } | 68 | } |
238 | EXPORT_SYMBOL_GPL(tegra_pcm_platform_register); | 69 | EXPORT_SYMBOL_GPL(tegra_pcm_platform_register); |
239 | 70 | ||
240 | void tegra_pcm_platform_unregister(struct device *dev) | 71 | void tegra_pcm_platform_unregister(struct device *dev) |
241 | { | 72 | { |
242 | snd_soc_unregister_platform(dev); | 73 | return snd_dmaengine_pcm_unregister(dev); |
243 | } | 74 | } |
244 | EXPORT_SYMBOL_GPL(tegra_pcm_platform_unregister); | 75 | EXPORT_SYMBOL_GPL(tegra_pcm_platform_unregister); |
245 | 76 | ||
diff --git a/sound/soc/tegra/tegra_pcm.h b/sound/soc/tegra/tegra_pcm.h index bc8b46af928e..68ad901714a9 100644 --- a/sound/soc/tegra/tegra_pcm.h +++ b/sound/soc/tegra/tegra_pcm.h | |||
@@ -31,13 +31,6 @@ | |||
31 | #ifndef __TEGRA_PCM_H__ | 31 | #ifndef __TEGRA_PCM_H__ |
32 | #define __TEGRA_PCM_H__ | 32 | #define __TEGRA_PCM_H__ |
33 | 33 | ||
34 | struct tegra_pcm_dma_params { | ||
35 | unsigned long addr; | ||
36 | unsigned long wrap; | ||
37 | unsigned long width; | ||
38 | unsigned long req_sel; | ||
39 | }; | ||
40 | |||
41 | int tegra_pcm_platform_register(struct device *dev); | 34 | int tegra_pcm_platform_register(struct device *dev); |
42 | void tegra_pcm_platform_unregister(struct device *dev); | 35 | void tegra_pcm_platform_unregister(struct device *dev); |
43 | 36 | ||
diff --git a/sound/soc/ux500/Kconfig b/sound/soc/ux500/Kconfig index 069330d82be5..c73c5907eb11 100644 --- a/sound/soc/ux500/Kconfig +++ b/sound/soc/ux500/Kconfig | |||
@@ -16,7 +16,7 @@ config SND_SOC_UX500_PLAT_MSP_I2S | |||
16 | config SND_SOC_UX500_PLAT_DMA | 16 | config SND_SOC_UX500_PLAT_DMA |
17 | tristate "Platform - DB8500 (DMA)" | 17 | tristate "Platform - DB8500 (DMA)" |
18 | depends on SND_SOC_UX500 | 18 | depends on SND_SOC_UX500 |
19 | select SND_SOC_DMAENGINE_PCM | 19 | select SND_SOC_GENERIC_DMAENGINE_PCM |
20 | help | 20 | help |
21 | Say Y if you want to enable the Ux500 platform-driver. | 21 | Say Y if you want to enable the Ux500 platform-driver. |
22 | 22 | ||
diff --git a/sound/soc/ux500/ux500_pcm.c b/sound/soc/ux500/ux500_pcm.c index 846fa82a58d0..b6e5ae277299 100644 --- a/sound/soc/ux500/ux500_pcm.c +++ b/sound/soc/ux500/ux500_pcm.c | |||
@@ -28,28 +28,19 @@ | |||
28 | #include "ux500_msp_i2s.h" | 28 | #include "ux500_msp_i2s.h" |
29 | #include "ux500_pcm.h" | 29 | #include "ux500_pcm.h" |
30 | 30 | ||
31 | static struct snd_pcm_hardware ux500_pcm_hw_playback = { | 31 | #define UX500_PLATFORM_MIN_RATE 8000 |
32 | .info = SNDRV_PCM_INFO_INTERLEAVED | | 32 | #define UX500_PLATFORM_MAX_RATE 48000 |
33 | SNDRV_PCM_INFO_MMAP | | 33 | |
34 | SNDRV_PCM_INFO_RESUME | | 34 | #define UX500_PLATFORM_MIN_CHANNELS 1 |
35 | SNDRV_PCM_INFO_PAUSE, | 35 | #define UX500_PLATFORM_MAX_CHANNELS 8 |
36 | .formats = SNDRV_PCM_FMTBIT_S16_LE | | ||
37 | SNDRV_PCM_FMTBIT_U16_LE | | ||
38 | SNDRV_PCM_FMTBIT_S16_BE | | ||
39 | SNDRV_PCM_FMTBIT_U16_BE, | ||
40 | .rates = SNDRV_PCM_RATE_KNOT, | ||
41 | .rate_min = UX500_PLATFORM_MIN_RATE_PLAYBACK, | ||
42 | .rate_max = UX500_PLATFORM_MAX_RATE_PLAYBACK, | ||
43 | .channels_min = UX500_PLATFORM_MIN_CHANNELS, | ||
44 | .channels_max = UX500_PLATFORM_MAX_CHANNELS, | ||
45 | .buffer_bytes_max = UX500_PLATFORM_BUFFER_BYTES_MAX, | ||
46 | .period_bytes_min = UX500_PLATFORM_PERIODS_BYTES_MIN, | ||
47 | .period_bytes_max = UX500_PLATFORM_PERIODS_BYTES_MAX, | ||
48 | .periods_min = UX500_PLATFORM_PERIODS_MIN, | ||
49 | .periods_max = UX500_PLATFORM_PERIODS_MAX, | ||
50 | }; | ||
51 | 36 | ||
52 | static struct snd_pcm_hardware ux500_pcm_hw_capture = { | 37 | #define UX500_PLATFORM_PERIODS_BYTES_MIN 128 |
38 | #define UX500_PLATFORM_PERIODS_BYTES_MAX (64 * PAGE_SIZE) | ||
39 | #define UX500_PLATFORM_PERIODS_MIN 2 | ||
40 | #define UX500_PLATFORM_PERIODS_MAX 48 | ||
41 | #define UX500_PLATFORM_BUFFER_BYTES_MAX (2048 * PAGE_SIZE) | ||
42 | |||
43 | static const struct snd_pcm_hardware ux500_pcm_hw = { | ||
53 | .info = SNDRV_PCM_INFO_INTERLEAVED | | 44 | .info = SNDRV_PCM_INFO_INTERLEAVED | |
54 | SNDRV_PCM_INFO_MMAP | | 45 | SNDRV_PCM_INFO_MMAP | |
55 | SNDRV_PCM_INFO_RESUME | | 46 | SNDRV_PCM_INFO_RESUME | |
@@ -59,8 +50,8 @@ static struct snd_pcm_hardware ux500_pcm_hw_capture = { | |||
59 | SNDRV_PCM_FMTBIT_S16_BE | | 50 | SNDRV_PCM_FMTBIT_S16_BE | |
60 | SNDRV_PCM_FMTBIT_U16_BE, | 51 | SNDRV_PCM_FMTBIT_U16_BE, |
61 | .rates = SNDRV_PCM_RATE_KNOT, | 52 | .rates = SNDRV_PCM_RATE_KNOT, |
62 | .rate_min = UX500_PLATFORM_MIN_RATE_CAPTURE, | 53 | .rate_min = UX500_PLATFORM_MIN_RATE, |
63 | .rate_max = UX500_PLATFORM_MAX_RATE_CAPTURE, | 54 | .rate_max = UX500_PLATFORM_MAX_RATE, |
64 | .channels_min = UX500_PLATFORM_MIN_CHANNELS, | 55 | .channels_min = UX500_PLATFORM_MIN_CHANNELS, |
65 | .channels_max = UX500_PLATFORM_MAX_CHANNELS, | 56 | .channels_max = UX500_PLATFORM_MAX_CHANNELS, |
66 | .buffer_bytes_max = UX500_PLATFORM_BUFFER_BYTES_MAX, | 57 | .buffer_bytes_max = UX500_PLATFORM_BUFFER_BYTES_MAX, |
@@ -70,64 +61,23 @@ static struct snd_pcm_hardware ux500_pcm_hw_capture = { | |||
70 | .periods_max = UX500_PLATFORM_PERIODS_MAX, | 61 | .periods_max = UX500_PLATFORM_PERIODS_MAX, |
71 | }; | 62 | }; |
72 | 63 | ||
73 | static void ux500_pcm_dma_hw_free(struct device *dev, | 64 | static struct dma_chan *ux500_pcm_request_chan(struct snd_soc_pcm_runtime *rtd, |
74 | struct snd_pcm_substream *substream) | 65 | struct snd_pcm_substream *substream) |
75 | { | 66 | { |
76 | struct snd_pcm_runtime *runtime = substream->runtime; | ||
77 | struct snd_dma_buffer *buf = runtime->dma_buffer_p; | ||
78 | |||
79 | if (runtime->dma_area == NULL) | ||
80 | return; | ||
81 | |||
82 | if (buf != &substream->dma_buffer) { | ||
83 | dma_free_coherent(buf->dev.dev, buf->bytes, buf->area, | ||
84 | buf->addr); | ||
85 | kfree(runtime->dma_buffer_p); | ||
86 | } | ||
87 | |||
88 | snd_pcm_set_runtime_buffer(substream, NULL); | ||
89 | } | ||
90 | |||
91 | static int ux500_pcm_open(struct snd_pcm_substream *substream) | ||
92 | { | ||
93 | int stream_id = substream->pstr->stream; | ||
94 | struct snd_pcm_runtime *runtime = substream->runtime; | ||
95 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | ||
96 | struct snd_soc_dai *dai = rtd->cpu_dai; | 67 | struct snd_soc_dai *dai = rtd->cpu_dai; |
97 | struct device *dev = dai->dev; | 68 | struct device *dev = dai->dev; |
98 | int ret; | ||
99 | struct ux500_msp_dma_params *dma_params; | ||
100 | u16 per_data_width, mem_data_width; | 69 | u16 per_data_width, mem_data_width; |
101 | struct stedma40_chan_cfg *dma_cfg; | 70 | struct stedma40_chan_cfg *dma_cfg; |
71 | struct ux500_msp_dma_params *dma_params; | ||
102 | 72 | ||
103 | dev_dbg(dev, "%s: MSP %d (%s): Enter.\n", __func__, dai->id, | 73 | dev_dbg(dev, "%s: MSP %d (%s): Enter.\n", __func__, dai->id, |
104 | snd_pcm_stream_str(substream)); | 74 | snd_pcm_stream_str(substream)); |
105 | 75 | ||
106 | dev_dbg(dev, "%s: Set runtime hwparams.\n", __func__); | 76 | dma_params = snd_soc_dai_get_dma_data(dai, substream); |
107 | if (stream_id == SNDRV_PCM_STREAM_PLAYBACK) | 77 | dma_cfg = dma_params->dma_cfg; |
108 | snd_soc_set_runtime_hwparams(substream, | ||
109 | &ux500_pcm_hw_playback); | ||
110 | else | ||
111 | snd_soc_set_runtime_hwparams(substream, | ||
112 | &ux500_pcm_hw_capture); | ||
113 | |||
114 | /* ensure that buffer size is a multiple of period size */ | ||
115 | ret = snd_pcm_hw_constraint_integer(runtime, | ||
116 | SNDRV_PCM_HW_PARAM_PERIODS); | ||
117 | if (ret < 0) { | ||
118 | dev_err(dev, "%s: Error: snd_pcm_hw_constraints failed (%d)\n", | ||
119 | __func__, ret); | ||
120 | return ret; | ||
121 | } | ||
122 | |||
123 | dev_dbg(dev, "%s: Set hw-struct for %s.\n", __func__, | ||
124 | snd_pcm_stream_str(substream)); | ||
125 | runtime->hw = (stream_id == SNDRV_PCM_STREAM_PLAYBACK) ? | ||
126 | ux500_pcm_hw_playback : ux500_pcm_hw_capture; | ||
127 | 78 | ||
128 | mem_data_width = STEDMA40_HALFWORD_WIDTH; | 79 | mem_data_width = STEDMA40_HALFWORD_WIDTH; |
129 | 80 | ||
130 | dma_params = snd_soc_dai_get_dma_data(dai, substream); | ||
131 | switch (dma_params->data_size) { | 81 | switch (dma_params->data_size) { |
132 | case 32: | 82 | case 32: |
133 | per_data_width = STEDMA40_WORD_WIDTH; | 83 | per_data_width = STEDMA40_WORD_WIDTH; |
@@ -140,13 +90,8 @@ static int ux500_pcm_open(struct snd_pcm_substream *substream) | |||
140 | break; | 90 | break; |
141 | default: | 91 | default: |
142 | per_data_width = STEDMA40_WORD_WIDTH; | 92 | per_data_width = STEDMA40_WORD_WIDTH; |
143 | dev_warn(rtd->platform->dev, | ||
144 | "%s: Unknown data-size (%d)! Assuming 32 bits.\n", | ||
145 | __func__, dma_params->data_size); | ||
146 | } | 93 | } |
147 | 94 | ||
148 | dma_cfg = dma_params->dma_cfg; | ||
149 | |||
150 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { | 95 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { |
151 | dma_cfg->src_info.data_width = mem_data_width; | 96 | dma_cfg->src_info.data_width = mem_data_width; |
152 | dma_cfg->dst_info.data_width = per_data_width; | 97 | dma_cfg->dst_info.data_width = per_data_width; |
@@ -155,137 +100,24 @@ static int ux500_pcm_open(struct snd_pcm_substream *substream) | |||
155 | dma_cfg->dst_info.data_width = mem_data_width; | 100 | dma_cfg->dst_info.data_width = mem_data_width; |
156 | } | 101 | } |
157 | 102 | ||
158 | 103 | return snd_dmaengine_pcm_request_channel(stedma40_filter, dma_cfg); | |
159 | ret = snd_dmaengine_pcm_open(substream, stedma40_filter, dma_cfg); | ||
160 | if (ret) { | ||
161 | dev_dbg(dai->dev, | ||
162 | "%s: ERROR: snd_dmaengine_pcm_open failed (%d)!\n", | ||
163 | __func__, ret); | ||
164 | return ret; | ||
165 | } | ||
166 | |||
167 | snd_dmaengine_pcm_set_data(substream, dma_cfg); | ||
168 | |||
169 | return 0; | ||
170 | } | ||
171 | |||
172 | static int ux500_pcm_close(struct snd_pcm_substream *substream) | ||
173 | { | ||
174 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | ||
175 | struct snd_soc_dai *dai = rtd->cpu_dai; | ||
176 | |||
177 | dev_dbg(dai->dev, "%s: Enter\n", __func__); | ||
178 | |||
179 | snd_dmaengine_pcm_close(substream); | ||
180 | |||
181 | return 0; | ||
182 | } | ||
183 | |||
184 | static int ux500_pcm_hw_params(struct snd_pcm_substream *substream, | ||
185 | struct snd_pcm_hw_params *hw_params) | ||
186 | { | ||
187 | struct snd_pcm_runtime *runtime = substream->runtime; | ||
188 | struct snd_dma_buffer *buf = runtime->dma_buffer_p; | ||
189 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | ||
190 | int ret = 0; | ||
191 | int size; | ||
192 | |||
193 | dev_dbg(rtd->platform->dev, "%s: Enter\n", __func__); | ||
194 | |||
195 | size = params_buffer_bytes(hw_params); | ||
196 | |||
197 | if (buf) { | ||
198 | if (buf->bytes >= size) | ||
199 | goto out; | ||
200 | ux500_pcm_dma_hw_free(NULL, substream); | ||
201 | } | ||
202 | |||
203 | if (substream->dma_buffer.area != NULL && | ||
204 | substream->dma_buffer.bytes >= size) { | ||
205 | buf = &substream->dma_buffer; | ||
206 | } else { | ||
207 | buf = kmalloc(sizeof(struct snd_dma_buffer), GFP_KERNEL); | ||
208 | if (!buf) | ||
209 | goto nomem; | ||
210 | |||
211 | buf->dev.type = SNDRV_DMA_TYPE_DEV; | ||
212 | buf->dev.dev = NULL; | ||
213 | buf->area = dma_alloc_coherent(NULL, size, &buf->addr, | ||
214 | GFP_KERNEL); | ||
215 | buf->bytes = size; | ||
216 | buf->private_data = NULL; | ||
217 | |||
218 | if (!buf->area) | ||
219 | goto free; | ||
220 | } | ||
221 | snd_pcm_set_runtime_buffer(substream, buf); | ||
222 | ret = 1; | ||
223 | out: | ||
224 | runtime->dma_bytes = size; | ||
225 | return ret; | ||
226 | |||
227 | free: | ||
228 | kfree(buf); | ||
229 | nomem: | ||
230 | return -ENOMEM; | ||
231 | } | 104 | } |
232 | 105 | ||
233 | static int ux500_pcm_hw_free(struct snd_pcm_substream *substream) | 106 | static const struct snd_dmaengine_pcm_config ux500_dmaengine_pcm_config = { |
234 | { | 107 | .pcm_hardware = &ux500_pcm_hw, |
235 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | 108 | .compat_request_channel = ux500_pcm_request_chan, |
236 | 109 | .prealloc_buffer_size = 128 * 1024, | |
237 | dev_dbg(rtd->platform->dev, "%s: Enter\n", __func__); | ||
238 | |||
239 | ux500_pcm_dma_hw_free(NULL, substream); | ||
240 | |||
241 | return 0; | ||
242 | } | ||
243 | |||
244 | static int ux500_pcm_mmap(struct snd_pcm_substream *substream, | ||
245 | struct vm_area_struct *vma) | ||
246 | { | ||
247 | struct snd_pcm_runtime *runtime = substream->runtime; | ||
248 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | ||
249 | |||
250 | dev_dbg(rtd->platform->dev, "%s: Enter.\n", __func__); | ||
251 | |||
252 | return dma_mmap_coherent(NULL, vma, runtime->dma_area, | ||
253 | runtime->dma_addr, runtime->dma_bytes); | ||
254 | } | ||
255 | |||
256 | static struct snd_pcm_ops ux500_pcm_ops = { | ||
257 | .open = ux500_pcm_open, | ||
258 | .close = ux500_pcm_close, | ||
259 | .ioctl = snd_pcm_lib_ioctl, | ||
260 | .hw_params = ux500_pcm_hw_params, | ||
261 | .hw_free = ux500_pcm_hw_free, | ||
262 | .trigger = snd_dmaengine_pcm_trigger, | ||
263 | .pointer = snd_dmaengine_pcm_pointer_no_residue, | ||
264 | .mmap = ux500_pcm_mmap | ||
265 | }; | ||
266 | |||
267 | int ux500_pcm_new(struct snd_soc_pcm_runtime *rtd) | ||
268 | { | ||
269 | struct snd_pcm *pcm = rtd->pcm; | ||
270 | |||
271 | dev_dbg(rtd->platform->dev, "%s: Enter (id = '%s').\n", __func__, | ||
272 | pcm->id); | ||
273 | |||
274 | pcm->info_flags = 0; | ||
275 | |||
276 | return 0; | ||
277 | } | ||
278 | |||
279 | static struct snd_soc_platform_driver ux500_pcm_soc_drv = { | ||
280 | .ops = &ux500_pcm_ops, | ||
281 | .pcm_new = ux500_pcm_new, | ||
282 | }; | 110 | }; |
283 | 111 | ||
284 | int ux500_pcm_register_platform(struct platform_device *pdev) | 112 | int ux500_pcm_register_platform(struct platform_device *pdev) |
285 | { | 113 | { |
286 | int ret; | 114 | int ret; |
287 | 115 | ||
288 | ret = snd_soc_register_platform(&pdev->dev, &ux500_pcm_soc_drv); | 116 | ret = snd_dmaengine_pcm_register(&pdev->dev, |
117 | &ux500_dmaengine_pcm_config, | ||
118 | SND_DMAENGINE_PCM_FLAG_NO_RESIDUE | | ||
119 | SND_DMAENGINE_PCM_FLAG_COMPAT | | ||
120 | SND_DMAENGINE_PCM_FLAG_NO_DT); | ||
289 | if (ret < 0) { | 121 | if (ret < 0) { |
290 | dev_err(&pdev->dev, | 122 | dev_err(&pdev->dev, |
291 | "%s: ERROR: Failed to register platform '%s' (%d)!\n", | 123 | "%s: ERROR: Failed to register platform '%s' (%d)!\n", |
@@ -299,8 +131,7 @@ EXPORT_SYMBOL_GPL(ux500_pcm_register_platform); | |||
299 | 131 | ||
300 | int ux500_pcm_unregister_platform(struct platform_device *pdev) | 132 | int ux500_pcm_unregister_platform(struct platform_device *pdev) |
301 | { | 133 | { |
302 | snd_soc_unregister_platform(&pdev->dev); | 134 | snd_dmaengine_pcm_unregister(&pdev->dev); |
303 | |||
304 | return 0; | 135 | return 0; |
305 | } | 136 | } |
306 | EXPORT_SYMBOL_GPL(ux500_pcm_unregister_platform); | 137 | EXPORT_SYMBOL_GPL(ux500_pcm_unregister_platform); |
diff --git a/sound/soc/ux500/ux500_pcm.h b/sound/soc/ux500/ux500_pcm.h index 76d344476afc..d76e1aff6458 100644 --- a/sound/soc/ux500/ux500_pcm.h +++ b/sound/soc/ux500/ux500_pcm.h | |||
@@ -18,20 +18,6 @@ | |||
18 | 18 | ||
19 | #include <linux/workqueue.h> | 19 | #include <linux/workqueue.h> |
20 | 20 | ||
21 | #define UX500_PLATFORM_MIN_RATE_PLAYBACK 8000 | ||
22 | #define UX500_PLATFORM_MAX_RATE_PLAYBACK 48000 | ||
23 | #define UX500_PLATFORM_MIN_RATE_CAPTURE 8000 | ||
24 | #define UX500_PLATFORM_MAX_RATE_CAPTURE 48000 | ||
25 | |||
26 | #define UX500_PLATFORM_MIN_CHANNELS 1 | ||
27 | #define UX500_PLATFORM_MAX_CHANNELS 8 | ||
28 | |||
29 | #define UX500_PLATFORM_PERIODS_BYTES_MIN 128 | ||
30 | #define UX500_PLATFORM_PERIODS_BYTES_MAX (64 * PAGE_SIZE) | ||
31 | #define UX500_PLATFORM_PERIODS_MIN 2 | ||
32 | #define UX500_PLATFORM_PERIODS_MAX 48 | ||
33 | #define UX500_PLATFORM_BUFFER_BYTES_MAX (2048 * PAGE_SIZE) | ||
34 | |||
35 | int ux500_pcm_register_platform(struct platform_device *pdev); | 21 | int ux500_pcm_register_platform(struct platform_device *pdev); |
36 | int ux500_pcm_unregister_platform(struct platform_device *pdev); | 22 | int ux500_pcm_unregister_platform(struct platform_device *pdev); |
37 | 23 | ||