2 * This program is free software; you can redistribute it and/or modify
3 * it under the terms of the GNU General Public License version 2 as
4 * published by the Free Software Foundation.
7 #include <linux/slab.h>
8 #include <linux/module.h>
9 #include <linux/dma-mapping.h>
10 #include <linux/dmaengine.h>
11 #include <linux/dma/pxa-dma.h>
13 #include <sound/core.h>
14 #include <sound/pcm.h>
15 #include <sound/pcm_params.h>
16 #include <sound/pxa2xx-lib.h>
17 #include <sound/dmaengine_pcm.h>
19 static const struct snd_pcm_hardware pxa2xx_pcm_hardware
= {
20 .info
= SNDRV_PCM_INFO_MMAP
|
21 SNDRV_PCM_INFO_MMAP_VALID
|
22 SNDRV_PCM_INFO_INTERLEAVED
|
23 SNDRV_PCM_INFO_PAUSE
|
24 SNDRV_PCM_INFO_RESUME
,
25 .formats
= SNDRV_PCM_FMTBIT_S16_LE
|
26 SNDRV_PCM_FMTBIT_S24_LE
|
27 SNDRV_PCM_FMTBIT_S32_LE
,
28 .period_bytes_min
= 32,
29 .period_bytes_max
= 8192 - 32,
32 .buffer_bytes_max
= 128 * 1024,
36 int pxa2xx_pcm_hw_params(struct snd_pcm_substream
*substream
,
37 struct snd_pcm_hw_params
*params
)
39 struct dma_chan
*chan
= snd_dmaengine_pcm_get_chan(substream
);
40 struct snd_soc_pcm_runtime
*rtd
= substream
->private_data
;
41 struct snd_dmaengine_dai_dma_data
*dma_params
;
42 struct dma_slave_config config
;
45 dma_params
= snd_soc_dai_get_dma_data(rtd
->cpu_dai
, substream
);
49 ret
= snd_hwparams_to_dma_slave_config(substream
, params
, &config
);
53 snd_dmaengine_pcm_set_config_from_dai_data(substream
,
54 snd_soc_dai_get_dma_data(rtd
->cpu_dai
, substream
),
57 ret
= dmaengine_slave_config(chan
, &config
);
61 snd_pcm_set_runtime_buffer(substream
, &substream
->dma_buffer
);
65 EXPORT_SYMBOL(pxa2xx_pcm_hw_params
);
67 int pxa2xx_pcm_hw_free(struct snd_pcm_substream
*substream
)
69 snd_pcm_set_runtime_buffer(substream
, NULL
);
72 EXPORT_SYMBOL(pxa2xx_pcm_hw_free
);
74 int pxa2xx_pcm_trigger(struct snd_pcm_substream
*substream
, int cmd
)
76 return snd_dmaengine_pcm_trigger(substream
, cmd
);
78 EXPORT_SYMBOL(pxa2xx_pcm_trigger
);
81 pxa2xx_pcm_pointer(struct snd_pcm_substream
*substream
)
83 return snd_dmaengine_pcm_pointer(substream
);
85 EXPORT_SYMBOL(pxa2xx_pcm_pointer
);
87 int pxa2xx_pcm_prepare(struct snd_pcm_substream
*substream
)
91 EXPORT_SYMBOL(pxa2xx_pcm_prepare
);
93 int pxa2xx_pcm_open(struct snd_pcm_substream
*substream
)
95 struct snd_soc_pcm_runtime
*rtd
= substream
->private_data
;
96 struct snd_pcm_runtime
*runtime
= substream
->runtime
;
97 struct snd_dmaengine_dai_dma_data
*dma_params
;
100 runtime
->hw
= pxa2xx_pcm_hardware
;
102 dma_params
= snd_soc_dai_get_dma_data(rtd
->cpu_dai
, substream
);
107 * For mysterious reasons (and despite what the manual says)
108 * playback samples are lost if the DMA count is not a multiple
109 * of the DMA burst size. Let's add a rule to enforce that.
111 ret
= snd_pcm_hw_constraint_step(runtime
, 0,
112 SNDRV_PCM_HW_PARAM_PERIOD_BYTES
, 32);
116 ret
= snd_pcm_hw_constraint_step(runtime
, 0,
117 SNDRV_PCM_HW_PARAM_BUFFER_BYTES
, 32);
121 ret
= snd_pcm_hw_constraint_integer(runtime
,
122 SNDRV_PCM_HW_PARAM_PERIODS
);
126 return snd_dmaengine_pcm_open(
127 substream
, dma_request_slave_channel(rtd
->cpu_dai
->dev
,
128 dma_params
->chan_name
));
130 EXPORT_SYMBOL(pxa2xx_pcm_open
);
132 int pxa2xx_pcm_close(struct snd_pcm_substream
*substream
)
134 return snd_dmaengine_pcm_close_release_chan(substream
);
136 EXPORT_SYMBOL(pxa2xx_pcm_close
);
138 int pxa2xx_pcm_mmap(struct snd_pcm_substream
*substream
,
139 struct vm_area_struct
*vma
)
141 struct snd_pcm_runtime
*runtime
= substream
->runtime
;
142 return dma_mmap_wc(substream
->pcm
->card
->dev
, vma
, runtime
->dma_area
,
143 runtime
->dma_addr
, runtime
->dma_bytes
);
145 EXPORT_SYMBOL(pxa2xx_pcm_mmap
);
147 int pxa2xx_pcm_preallocate_dma_buffer(struct snd_pcm
*pcm
, int stream
)
149 struct snd_pcm_substream
*substream
= pcm
->streams
[stream
].substream
;
150 struct snd_dma_buffer
*buf
= &substream
->dma_buffer
;
151 size_t size
= pxa2xx_pcm_hardware
.buffer_bytes_max
;
152 buf
->dev
.type
= SNDRV_DMA_TYPE_DEV
;
153 buf
->dev
.dev
= pcm
->card
->dev
;
154 buf
->private_data
= NULL
;
155 buf
->area
= dma_alloc_wc(pcm
->card
->dev
, size
, &buf
->addr
, GFP_KERNEL
);
161 EXPORT_SYMBOL(pxa2xx_pcm_preallocate_dma_buffer
);
163 void pxa2xx_pcm_free_dma_buffers(struct snd_pcm
*pcm
)
165 struct snd_pcm_substream
*substream
;
166 struct snd_dma_buffer
*buf
;
169 for (stream
= 0; stream
< 2; stream
++) {
170 substream
= pcm
->streams
[stream
].substream
;
173 buf
= &substream
->dma_buffer
;
176 dma_free_wc(pcm
->card
->dev
, buf
->bytes
, buf
->area
, buf
->addr
);
180 EXPORT_SYMBOL(pxa2xx_pcm_free_dma_buffers
);
182 int pxa2xx_soc_pcm_new(struct snd_soc_pcm_runtime
*rtd
)
184 struct snd_card
*card
= rtd
->card
->snd_card
;
185 struct snd_pcm
*pcm
= rtd
->pcm
;
188 ret
= dma_coerce_mask_and_coherent(card
->dev
, DMA_BIT_MASK(32));
192 if (pcm
->streams
[SNDRV_PCM_STREAM_PLAYBACK
].substream
) {
193 ret
= pxa2xx_pcm_preallocate_dma_buffer(pcm
,
194 SNDRV_PCM_STREAM_PLAYBACK
);
199 if (pcm
->streams
[SNDRV_PCM_STREAM_CAPTURE
].substream
) {
200 ret
= pxa2xx_pcm_preallocate_dma_buffer(pcm
,
201 SNDRV_PCM_STREAM_CAPTURE
);
208 EXPORT_SYMBOL(pxa2xx_soc_pcm_new
);
210 const struct snd_pcm_ops pxa2xx_pcm_ops
= {
211 .open
= pxa2xx_pcm_open
,
212 .close
= pxa2xx_pcm_close
,
213 .ioctl
= snd_pcm_lib_ioctl
,
214 .hw_params
= pxa2xx_pcm_hw_params
,
215 .hw_free
= pxa2xx_pcm_hw_free
,
216 .prepare
= pxa2xx_pcm_prepare
,
217 .trigger
= pxa2xx_pcm_trigger
,
218 .pointer
= pxa2xx_pcm_pointer
,
219 .mmap
= pxa2xx_pcm_mmap
,
221 EXPORT_SYMBOL(pxa2xx_pcm_ops
);
223 MODULE_AUTHOR("Nicolas Pitre");
224 MODULE_DESCRIPTION("Intel PXA2xx sound library");
225 MODULE_LICENSE("GPL");