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 #include "pxa2xx-pcm.h"
21 static const struct snd_pcm_hardware pxa2xx_pcm_hardware
= {
22 .info
= SNDRV_PCM_INFO_MMAP
|
23 SNDRV_PCM_INFO_MMAP_VALID
|
24 SNDRV_PCM_INFO_INTERLEAVED
|
25 SNDRV_PCM_INFO_PAUSE
|
26 SNDRV_PCM_INFO_RESUME
,
27 .formats
= SNDRV_PCM_FMTBIT_S16_LE
|
28 SNDRV_PCM_FMTBIT_S24_LE
|
29 SNDRV_PCM_FMTBIT_S32_LE
,
30 .period_bytes_min
= 32,
31 .period_bytes_max
= 8192 - 32,
34 .buffer_bytes_max
= 128 * 1024,
38 int __pxa2xx_pcm_hw_params(struct snd_pcm_substream
*substream
,
39 struct snd_pcm_hw_params
*params
)
41 struct dma_chan
*chan
= snd_dmaengine_pcm_get_chan(substream
);
42 struct snd_soc_pcm_runtime
*rtd
= substream
->private_data
;
43 struct snd_dmaengine_dai_dma_data
*dma_params
;
44 struct dma_slave_config config
;
47 dma_params
= snd_soc_dai_get_dma_data(rtd
->cpu_dai
, substream
);
51 ret
= snd_hwparams_to_dma_slave_config(substream
, params
, &config
);
55 snd_dmaengine_pcm_set_config_from_dai_data(substream
,
56 snd_soc_dai_get_dma_data(rtd
->cpu_dai
, substream
),
59 ret
= dmaengine_slave_config(chan
, &config
);
63 snd_pcm_set_runtime_buffer(substream
, &substream
->dma_buffer
);
67 EXPORT_SYMBOL(__pxa2xx_pcm_hw_params
);
69 int __pxa2xx_pcm_hw_free(struct snd_pcm_substream
*substream
)
71 snd_pcm_set_runtime_buffer(substream
, NULL
);
74 EXPORT_SYMBOL(__pxa2xx_pcm_hw_free
);
76 int pxa2xx_pcm_trigger(struct snd_pcm_substream
*substream
, int cmd
)
78 return snd_dmaengine_pcm_trigger(substream
, cmd
);
80 EXPORT_SYMBOL(pxa2xx_pcm_trigger
);
83 pxa2xx_pcm_pointer(struct snd_pcm_substream
*substream
)
85 return snd_dmaengine_pcm_pointer(substream
);
87 EXPORT_SYMBOL(pxa2xx_pcm_pointer
);
89 int __pxa2xx_pcm_prepare(struct snd_pcm_substream
*substream
)
93 EXPORT_SYMBOL(__pxa2xx_pcm_prepare
);
95 int __pxa2xx_pcm_open(struct snd_pcm_substream
*substream
)
97 struct snd_soc_pcm_runtime
*rtd
= substream
->private_data
;
98 struct snd_pcm_runtime
*runtime
= substream
->runtime
;
99 struct snd_dmaengine_dai_dma_data
*dma_params
;
102 runtime
->hw
= pxa2xx_pcm_hardware
;
104 dma_params
= snd_soc_dai_get_dma_data(rtd
->cpu_dai
, substream
);
109 * For mysterious reasons (and despite what the manual says)
110 * playback samples are lost if the DMA count is not a multiple
111 * of the DMA burst size. Let's add a rule to enforce that.
113 ret
= snd_pcm_hw_constraint_step(runtime
, 0,
114 SNDRV_PCM_HW_PARAM_PERIOD_BYTES
, 32);
118 ret
= snd_pcm_hw_constraint_step(runtime
, 0,
119 SNDRV_PCM_HW_PARAM_BUFFER_BYTES
, 32);
123 ret
= snd_pcm_hw_constraint_integer(runtime
,
124 SNDRV_PCM_HW_PARAM_PERIODS
);
128 return snd_dmaengine_pcm_open_request_chan(substream
,
130 dma_params
->filter_data
);
132 EXPORT_SYMBOL(__pxa2xx_pcm_open
);
134 int __pxa2xx_pcm_close(struct snd_pcm_substream
*substream
)
136 return snd_dmaengine_pcm_close_release_chan(substream
);
138 EXPORT_SYMBOL(__pxa2xx_pcm_close
);
140 int pxa2xx_pcm_mmap(struct snd_pcm_substream
*substream
,
141 struct vm_area_struct
*vma
)
143 struct snd_pcm_runtime
*runtime
= substream
->runtime
;
144 return dma_mmap_wc(substream
->pcm
->card
->dev
, vma
, runtime
->dma_area
,
145 runtime
->dma_addr
, runtime
->dma_bytes
);
147 EXPORT_SYMBOL(pxa2xx_pcm_mmap
);
149 int pxa2xx_pcm_preallocate_dma_buffer(struct snd_pcm
*pcm
, int stream
)
151 struct snd_pcm_substream
*substream
= pcm
->streams
[stream
].substream
;
152 struct snd_dma_buffer
*buf
= &substream
->dma_buffer
;
153 size_t size
= pxa2xx_pcm_hardware
.buffer_bytes_max
;
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_wc(pcm
->card
->dev
, size
, &buf
->addr
, GFP_KERNEL
);
163 EXPORT_SYMBOL(pxa2xx_pcm_preallocate_dma_buffer
);
165 void pxa2xx_pcm_free_dma_buffers(struct snd_pcm
*pcm
)
167 struct snd_pcm_substream
*substream
;
168 struct snd_dma_buffer
*buf
;
171 for (stream
= 0; stream
< 2; stream
++) {
172 substream
= pcm
->streams
[stream
].substream
;
175 buf
= &substream
->dma_buffer
;
178 dma_free_wc(pcm
->card
->dev
, buf
->bytes
, buf
->area
, buf
->addr
);
182 EXPORT_SYMBOL(pxa2xx_pcm_free_dma_buffers
);
184 MODULE_AUTHOR("Nicolas Pitre");
185 MODULE_DESCRIPTION("Intel PXA2xx sound library");
186 MODULE_LICENSE("GPL");