diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2013-05-03 12:10:23 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2013-05-03 12:10:23 -0400 |
commit | 9992ba72327fa0d8bdc9fb624e80f5cce338a711 (patch) | |
tree | e0bf31ae53cb19c44674df7e0d0343a26037ad34 /sound/soc/mxs | |
parent | 00fdffb5131125dce0702bf61e24a806ec3aed80 (diff) | |
parent | 4ca231b2e6ed171107c5b21f9e92d1965fd6fd9e (diff) |
Merge tag 'sound-3.10' of git://git.kernel.org/pub/scm/linux/kernel/git/tiwai/sound
Pull sound updates from Takashi Iwai:
"Mostly many small changes spread as seen in diffstat in sound/*
directory by this update. A significant change in the subsystem level
is the introduction of snd_soc_component, which will help more generic
handling of SoC and off-SoC components.
Also, snd_BUG_ON() macro is enabled unconditionally now due to its
misuses, so people might hit kernel warnings (it's a good thing for
us).
- compress-offload: support for capture by Charles Keepax
- HD-audio: codec delay support by Dylan Reid
- HD-audio: improvements/fixes in generic parser: better headphone
mic and headset mic support, jack_modes hint consolidation, proper
beep attach/detachment, generalized power filter controls by David
Henningsson, et al
- HD-audio: Improved management of HDMI codec pins/converters
- HD-audio: Better pin/DAC assignment for VIA codecs
- HD-audio: Haswell HDMI workarounds
- HD-audio: ALC268 codec support, a few new quirks for Chromebooks
- USB: regression fixes: USB-MIDI autopm fix, the recent ISO latency
fix by Clemens Ladisch
- USB: support for DSD formats by Daniel Mack
- USB: A few UAC2 device endian/cock fixes by Eldad Zack
- USB: quirks for Emu 192kHz support, Novation Twitch DJ controller,
Yamaha THRxx devices
- HDSPM: updates for TCO controls by Adrian Knoth
- ASoC: Add a snd_soc_component object type for generic handling of
SoC and off-SoC components by Kuninori Morimoto,
- dmaengine: a large set of cleanups and conversions by Lars-Peter
Clausen
- ASoC DAPM: performance optimizations from Ryo Tsutsui
- ASoC DAPM: support for mixer control sharing by Stephen Warren
- ASoC: multiplatform ARM cleanups from Arnd Bergmann
- ASoC: new codec drivers for AK5385 and TAS5086 from Daniel Mack"
* tag 'sound-3.10' of git://git.kernel.org/pub/scm/linux/kernel/git/tiwai/sound: (315 commits)
ALSA: usb-audio: caiaq: fix endianness bug in snd_usb_caiaq_maschine_dispatch
ALSA: asihpi: add format support check in snd_card_asihpi_capture_formats
ALSA: pcm_format_to_bits strong-typed conversion
ALSA: compress: fix the states to check for allowing read
ALSA: hda - Move Thinkpad X220 to use auto parser
ALSA: USB: adjust for changed 3.8 USB API
ALSA: usb - Avoid unnecessary sample rate changes on USB 2.0 clock sources
sound: oss/dmabuf: use dma_map_single
ALSA: ali5451: use mdelay instead of large udelay constants
ALSA: hda - Add the support for ALC286 codec
ALSA: usb-audio: USB quirk for Yamaha THR10C
ALSA: usb-audio: USB quirk for Yamaha THR5A
ALSA: usb-audio: USB quirk for Yamaha THR10
ALSA: usb-audio: Fix autopm error during probing
ALSA: snd-usb: try harder to find USB_DT_CS_ENDPOINT
ALSA: sound kconfig typo
ALSA: emu10k1: Fix dock firmware loading
ASoC: ux500: forward declare msp_i2s_platform_data
ASoC: davinci-mcasp: Add Support BCLK-to-LRCLK ratio for TDM modes
ASoC: davinci-pcm, davinci-mcasp: Clean up active_serializers
...
Diffstat (limited to 'sound/soc/mxs')
-rw-r--r-- | sound/soc/mxs/Kconfig | 2 | ||||
-rw-r--r-- | sound/soc/mxs/mxs-pcm.c | 176 | ||||
-rw-r--r-- | sound/soc/mxs/mxs-pcm.h | 4 | ||||
-rw-r--r-- | sound/soc/mxs/mxs-saif.c | 20 |
4 files changed, 32 insertions, 170 deletions
diff --git a/sound/soc/mxs/Kconfig b/sound/soc/mxs/Kconfig index b6fa77678d97..78d321cbe8b4 100644 --- a/sound/soc/mxs/Kconfig +++ b/sound/soc/mxs/Kconfig | |||
@@ -1,7 +1,7 @@ | |||
1 | menuconfig SND_MXS_SOC | 1 | menuconfig SND_MXS_SOC |
2 | tristate "SoC Audio for Freescale MXS CPUs" | 2 | tristate "SoC Audio for Freescale MXS CPUs" |
3 | depends on ARCH_MXS | 3 | depends on ARCH_MXS |
4 | select SND_SOC_DMAENGINE_PCM | 4 | select SND_SOC_GENERIC_DMAENGINE_PCM |
5 | help | 5 | help |
6 | Say Y or M if you want to add support for codecs attached to | 6 | Say Y or M if you want to add support for codecs attached to |
7 | the MXS SAIF interface. | 7 | the MXS SAIF interface. |
diff --git a/sound/soc/mxs/mxs-pcm.c b/sound/soc/mxs/mxs-pcm.c index 564b5b60319d..b41fffc056fb 100644 --- a/sound/soc/mxs/mxs-pcm.c +++ b/sound/soc/mxs/mxs-pcm.c | |||
@@ -18,38 +18,24 @@ | |||
18 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. | 18 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. |
19 | */ | 19 | */ |
20 | 20 | ||
21 | #include <linux/clk.h> | ||
22 | #include <linux/delay.h> | ||
23 | #include <linux/device.h> | 21 | #include <linux/device.h> |
24 | #include <linux/dma-mapping.h> | ||
25 | #include <linux/init.h> | 22 | #include <linux/init.h> |
26 | #include <linux/interrupt.h> | ||
27 | #include <linux/module.h> | 23 | #include <linux/module.h> |
28 | #include <linux/platform_device.h> | ||
29 | #include <linux/slab.h> | ||
30 | #include <linux/dmaengine.h> | ||
31 | #include <linux/fsl/mxs-dma.h> | ||
32 | 24 | ||
33 | #include <sound/core.h> | 25 | #include <sound/core.h> |
34 | #include <sound/initval.h> | ||
35 | #include <sound/pcm.h> | 26 | #include <sound/pcm.h> |
36 | #include <sound/pcm_params.h> | ||
37 | #include <sound/soc.h> | 27 | #include <sound/soc.h> |
38 | #include <sound/dmaengine_pcm.h> | 28 | #include <sound/dmaengine_pcm.h> |
39 | 29 | ||
40 | #include "mxs-pcm.h" | 30 | #include "mxs-pcm.h" |
41 | 31 | ||
42 | struct mxs_pcm_dma_data { | 32 | static const struct snd_pcm_hardware snd_mxs_hardware = { |
43 | struct mxs_dma_data dma_data; | ||
44 | struct mxs_pcm_dma_params *dma_params; | ||
45 | }; | ||
46 | |||
47 | static struct snd_pcm_hardware snd_mxs_hardware = { | ||
48 | .info = SNDRV_PCM_INFO_MMAP | | 33 | .info = SNDRV_PCM_INFO_MMAP | |
49 | SNDRV_PCM_INFO_MMAP_VALID | | 34 | SNDRV_PCM_INFO_MMAP_VALID | |
50 | SNDRV_PCM_INFO_PAUSE | | 35 | SNDRV_PCM_INFO_PAUSE | |
51 | SNDRV_PCM_INFO_RESUME | | 36 | SNDRV_PCM_INFO_RESUME | |
52 | SNDRV_PCM_INFO_INTERLEAVED, | 37 | SNDRV_PCM_INFO_INTERLEAVED | |
38 | SNDRV_PCM_INFO_HALF_DUPLEX, | ||
53 | .formats = SNDRV_PCM_FMTBIT_S16_LE | | 39 | .formats = SNDRV_PCM_FMTBIT_S16_LE | |
54 | SNDRV_PCM_FMTBIT_S20_3LE | | 40 | SNDRV_PCM_FMTBIT_S20_3LE | |
55 | SNDRV_PCM_FMTBIT_S24_LE, | 41 | SNDRV_PCM_FMTBIT_S24_LE, |
@@ -61,13 +47,11 @@ static struct snd_pcm_hardware snd_mxs_hardware = { | |||
61 | .periods_max = 52, | 47 | .periods_max = 52, |
62 | .buffer_bytes_max = 64 * 1024, | 48 | .buffer_bytes_max = 64 * 1024, |
63 | .fifo_size = 32, | 49 | .fifo_size = 32, |
64 | |||
65 | }; | 50 | }; |
66 | 51 | ||
67 | static bool filter(struct dma_chan *chan, void *param) | 52 | static bool filter(struct dma_chan *chan, void *param) |
68 | { | 53 | { |
69 | struct mxs_pcm_dma_data *pcm_dma_data = param; | 54 | struct mxs_pcm_dma_params *dma_params = param; |
70 | struct mxs_pcm_dma_params *dma_params = pcm_dma_data->dma_params; | ||
71 | 55 | ||
72 | if (!mxs_dma_is_apbx(chan)) | 56 | if (!mxs_dma_is_apbx(chan)) |
73 | return false; | 57 | return false; |
@@ -75,160 +59,30 @@ static bool filter(struct dma_chan *chan, void *param) | |||
75 | if (chan->chan_id != dma_params->chan_num) | 59 | if (chan->chan_id != dma_params->chan_num) |
76 | return false; | 60 | return false; |
77 | 61 | ||
78 | chan->private = &pcm_dma_data->dma_data; | 62 | chan->private = &dma_params->dma_data; |
79 | 63 | ||
80 | return true; | 64 | return true; |
81 | } | 65 | } |
82 | 66 | ||
83 | static int snd_mxs_pcm_hw_params(struct snd_pcm_substream *substream, | 67 | static const struct snd_dmaengine_pcm_config mxs_dmaengine_pcm_config = { |
84 | struct snd_pcm_hw_params *params) | 68 | .pcm_hardware = &snd_mxs_hardware, |
85 | { | 69 | .compat_filter_fn = filter, |
86 | snd_pcm_set_runtime_buffer(substream, &substream->dma_buffer); | 70 | .prealloc_buffer_size = 64 * 1024, |
87 | |||
88 | return 0; | ||
89 | } | ||
90 | |||
91 | static int snd_mxs_open(struct snd_pcm_substream *substream) | ||
92 | { | ||
93 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | ||
94 | struct mxs_pcm_dma_data *pcm_dma_data; | ||
95 | int ret; | ||
96 | |||
97 | pcm_dma_data = kzalloc(sizeof(*pcm_dma_data), GFP_KERNEL); | ||
98 | if (pcm_dma_data == NULL) | ||
99 | return -ENOMEM; | ||
100 | |||
101 | pcm_dma_data->dma_params = snd_soc_dai_get_dma_data(rtd->cpu_dai, substream); | ||
102 | pcm_dma_data->dma_data.chan_irq = pcm_dma_data->dma_params->chan_irq; | ||
103 | |||
104 | ret = snd_dmaengine_pcm_open(substream, filter, pcm_dma_data); | ||
105 | if (ret) { | ||
106 | kfree(pcm_dma_data); | ||
107 | return ret; | ||
108 | } | ||
109 | |||
110 | snd_soc_set_runtime_hwparams(substream, &snd_mxs_hardware); | ||
111 | |||
112 | snd_dmaengine_pcm_set_data(substream, pcm_dma_data); | ||
113 | |||
114 | return 0; | ||
115 | } | ||
116 | |||
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 | } | ||
126 | |||
127 | static int snd_mxs_pcm_mmap(struct snd_pcm_substream *substream, | ||
128 | struct vm_area_struct *vma) | ||
129 | { | ||
130 | struct snd_pcm_runtime *runtime = substream->runtime; | ||
131 | |||
132 | return dma_mmap_writecombine(substream->pcm->card->dev, vma, | ||
133 | runtime->dma_area, | ||
134 | runtime->dma_addr, | ||
135 | runtime->dma_bytes); | ||
136 | } | ||
137 | |||
138 | static struct snd_pcm_ops mxs_pcm_ops = { | ||
139 | .open = snd_mxs_open, | ||
140 | .close = snd_mxs_close, | ||
141 | .ioctl = snd_pcm_lib_ioctl, | ||
142 | .hw_params = snd_mxs_pcm_hw_params, | ||
143 | .trigger = snd_dmaengine_pcm_trigger, | ||
144 | .pointer = snd_dmaengine_pcm_pointer_no_residue, | ||
145 | .mmap = snd_mxs_pcm_mmap, | ||
146 | }; | ||
147 | |||
148 | static int mxs_pcm_preallocate_dma_buffer(struct snd_pcm *pcm, int stream) | ||
149 | { | ||
150 | struct snd_pcm_substream *substream = pcm->streams[stream].substream; | ||
151 | struct snd_dma_buffer *buf = &substream->dma_buffer; | ||
152 | size_t size = snd_mxs_hardware.buffer_bytes_max; | ||
153 | |||
154 | buf->dev.type = SNDRV_DMA_TYPE_DEV; | ||
155 | buf->dev.dev = pcm->card->dev; | ||
156 | buf->private_data = NULL; | ||
157 | buf->area = dma_alloc_writecombine(pcm->card->dev, size, | ||
158 | &buf->addr, GFP_KERNEL); | ||
159 | if (!buf->area) | ||
160 | return -ENOMEM; | ||
161 | buf->bytes = size; | ||
162 | |||
163 | return 0; | ||
164 | } | ||
165 | |||
166 | static u64 mxs_pcm_dmamask = DMA_BIT_MASK(32); | ||
167 | static int mxs_pcm_new(struct snd_soc_pcm_runtime *rtd) | ||
168 | { | ||
169 | struct snd_card *card = rtd->card->snd_card; | ||
170 | struct snd_pcm *pcm = rtd->pcm; | ||
171 | int ret = 0; | ||
172 | |||
173 | if (!card->dev->dma_mask) | ||
174 | card->dev->dma_mask = &mxs_pcm_dmamask; | ||
175 | if (!card->dev->coherent_dma_mask) | ||
176 | card->dev->coherent_dma_mask = DMA_BIT_MASK(32); | ||
177 | |||
178 | if (pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream) { | ||
179 | ret = mxs_pcm_preallocate_dma_buffer(pcm, | ||
180 | SNDRV_PCM_STREAM_PLAYBACK); | ||
181 | if (ret) | ||
182 | goto out; | ||
183 | } | ||
184 | |||
185 | if (pcm->streams[SNDRV_PCM_STREAM_CAPTURE].substream) { | ||
186 | ret = mxs_pcm_preallocate_dma_buffer(pcm, | ||
187 | SNDRV_PCM_STREAM_CAPTURE); | ||
188 | if (ret) | ||
189 | goto out; | ||
190 | } | ||
191 | |||
192 | out: | ||
193 | return ret; | ||
194 | } | ||
195 | |||
196 | static void mxs_pcm_free(struct snd_pcm *pcm) | ||
197 | { | ||
198 | struct snd_pcm_substream *substream; | ||
199 | struct snd_dma_buffer *buf; | ||
200 | int stream; | ||
201 | |||
202 | for (stream = 0; stream < 2; stream++) { | ||
203 | substream = pcm->streams[stream].substream; | ||
204 | if (!substream) | ||
205 | continue; | ||
206 | |||
207 | buf = &substream->dma_buffer; | ||
208 | if (!buf->area) | ||
209 | continue; | ||
210 | |||
211 | dma_free_writecombine(pcm->card->dev, buf->bytes, | ||
212 | buf->area, buf->addr); | ||
213 | buf->area = NULL; | ||
214 | } | ||
215 | } | ||
216 | |||
217 | static struct snd_soc_platform_driver mxs_soc_platform = { | ||
218 | .ops = &mxs_pcm_ops, | ||
219 | .pcm_new = mxs_pcm_new, | ||
220 | .pcm_free = mxs_pcm_free, | ||
221 | }; | 71 | }; |
222 | 72 | ||
223 | int mxs_pcm_platform_register(struct device *dev) | 73 | int mxs_pcm_platform_register(struct device *dev) |
224 | { | 74 | { |
225 | return snd_soc_register_platform(dev, &mxs_soc_platform); | 75 | return snd_dmaengine_pcm_register(dev, &mxs_dmaengine_pcm_config, |
76 | SND_DMAENGINE_PCM_FLAG_NO_RESIDUE | | ||
77 | SND_DMAENGINE_PCM_FLAG_NO_DT | | ||
78 | SND_DMAENGINE_PCM_FLAG_COMPAT | | ||
79 | SND_DMAENGINE_PCM_FLAG_HALF_DUPLEX); | ||
226 | } | 80 | } |
227 | EXPORT_SYMBOL_GPL(mxs_pcm_platform_register); | 81 | EXPORT_SYMBOL_GPL(mxs_pcm_platform_register); |
228 | 82 | ||
229 | void mxs_pcm_platform_unregister(struct device *dev) | 83 | void mxs_pcm_platform_unregister(struct device *dev) |
230 | { | 84 | { |
231 | snd_soc_unregister_platform(dev); | 85 | snd_dmaengine_pcm_unregister(dev); |
232 | } | 86 | } |
233 | EXPORT_SYMBOL_GPL(mxs_pcm_platform_unregister); | 87 | EXPORT_SYMBOL_GPL(mxs_pcm_platform_unregister); |
234 | 88 | ||
diff --git a/sound/soc/mxs/mxs-pcm.h b/sound/soc/mxs/mxs-pcm.h index 35ba2ca42384..3aa918f9ed3e 100644 --- a/sound/soc/mxs/mxs-pcm.h +++ b/sound/soc/mxs/mxs-pcm.h | |||
@@ -19,8 +19,10 @@ | |||
19 | #ifndef _MXS_PCM_H | 19 | #ifndef _MXS_PCM_H |
20 | #define _MXS_PCM_H | 20 | #define _MXS_PCM_H |
21 | 21 | ||
22 | #include <linux/fsl/mxs-dma.h> | ||
23 | |||
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 41a6136e3535..d31dc52fa862 100644 --- a/sound/soc/mxs/mxs-saif.c +++ b/sound/soc/mxs/mxs-saif.c | |||
@@ -370,7 +370,6 @@ static int mxs_saif_startup(struct snd_pcm_substream *substream, | |||
370 | struct snd_soc_dai *cpu_dai) | 370 | struct snd_soc_dai *cpu_dai) |
371 | { | 371 | { |
372 | struct mxs_saif *saif = snd_soc_dai_get_drvdata(cpu_dai); | 372 | struct mxs_saif *saif = snd_soc_dai_get_drvdata(cpu_dai); |
373 | snd_soc_dai_set_dma_data(cpu_dai, substream, &saif->dma_param); | ||
374 | 373 | ||
375 | /* clear error status to 0 for each re-open */ | 374 | /* clear error status to 0 for each re-open */ |
376 | saif->fifo_underrun = 0; | 375 | saif->fifo_underrun = 0; |
@@ -606,6 +605,8 @@ static int mxs_saif_dai_probe(struct snd_soc_dai *dai) | |||
606 | struct mxs_saif *saif = dev_get_drvdata(dai->dev); | 605 | struct mxs_saif *saif = dev_get_drvdata(dai->dev); |
607 | 606 | ||
608 | snd_soc_dai_set_drvdata(dai, saif); | 607 | snd_soc_dai_set_drvdata(dai, saif); |
608 | dai->playback_dma_data = &saif->dma_param; | ||
609 | dai->capture_dma_data = &saif->dma_param; | ||
609 | 610 | ||
610 | return 0; | 611 | return 0; |
611 | } | 612 | } |
@@ -628,6 +629,10 @@ static struct snd_soc_dai_driver mxs_saif_dai = { | |||
628 | .ops = &mxs_saif_dai_ops, | 629 | .ops = &mxs_saif_dai_ops, |
629 | }; | 630 | }; |
630 | 631 | ||
632 | static const struct snd_soc_component_driver mxs_saif_component = { | ||
633 | .name = "mxs-saif", | ||
634 | }; | ||
635 | |||
631 | static irqreturn_t mxs_saif_irq(int irq, void *dev_id) | 636 | static irqreturn_t mxs_saif_irq(int irq, void *dev_id) |
632 | { | 637 | { |
633 | struct mxs_saif *saif = dev_id; | 638 | struct mxs_saif *saif = dev_id; |
@@ -754,9 +759,9 @@ static int mxs_saif_probe(struct platform_device *pdev) | |||
754 | return ret; | 759 | return ret; |
755 | } | 760 | } |
756 | 761 | ||
757 | saif->dma_param.chan_irq = platform_get_irq(pdev, 1); | 762 | saif->dma_param.dma_data.chan_irq = platform_get_irq(pdev, 1); |
758 | if (saif->dma_param.chan_irq < 0) { | 763 | if (saif->dma_param.dma_data.chan_irq < 0) { |
759 | ret = saif->dma_param.chan_irq; | 764 | ret = saif->dma_param.dma_data.chan_irq; |
760 | dev_err(&pdev->dev, "failed to get dma irq resource: %d\n", | 765 | dev_err(&pdev->dev, "failed to get dma irq resource: %d\n", |
761 | ret); | 766 | ret); |
762 | return ret; | 767 | return ret; |
@@ -764,7 +769,8 @@ static int mxs_saif_probe(struct platform_device *pdev) | |||
764 | 769 | ||
765 | platform_set_drvdata(pdev, saif); | 770 | platform_set_drvdata(pdev, saif); |
766 | 771 | ||
767 | ret = snd_soc_register_dai(&pdev->dev, &mxs_saif_dai); | 772 | ret = snd_soc_register_component(&pdev->dev, &mxs_saif_component, |
773 | &mxs_saif_dai, 1); | ||
768 | if (ret) { | 774 | if (ret) { |
769 | dev_err(&pdev->dev, "register DAI failed\n"); | 775 | dev_err(&pdev->dev, "register DAI failed\n"); |
770 | return ret; | 776 | return ret; |
@@ -779,7 +785,7 @@ static int mxs_saif_probe(struct platform_device *pdev) | |||
779 | return 0; | 785 | return 0; |
780 | 786 | ||
781 | failed_pdev_alloc: | 787 | failed_pdev_alloc: |
782 | snd_soc_unregister_dai(&pdev->dev); | 788 | snd_soc_unregister_component(&pdev->dev); |
783 | 789 | ||
784 | return ret; | 790 | return ret; |
785 | } | 791 | } |
@@ -787,7 +793,7 @@ failed_pdev_alloc: | |||
787 | static int mxs_saif_remove(struct platform_device *pdev) | 793 | static int mxs_saif_remove(struct platform_device *pdev) |
788 | { | 794 | { |
789 | mxs_pcm_platform_unregister(&pdev->dev); | 795 | mxs_pcm_platform_unregister(&pdev->dev); |
790 | snd_soc_unregister_dai(&pdev->dev); | 796 | snd_soc_unregister_component(&pdev->dev); |
791 | 797 | ||
792 | return 0; | 798 | return 0; |
793 | } | 799 | } |