2 * Digital Audio (PCM) abstract layer
3 * Copyright (c) by Jaroslav Kysela <perex@suse.cz>
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
22 #define __NO_VERSION__
23 #include <sound/driver.h>
25 #include <linux/time.h>
26 #include <sound/core.h>
27 #include <sound/pcm.h>
28 #include <sound/info.h>
29 #include <sound/initval.h>
31 static int snd_preallocate_dma
= 1;
32 MODULE_PARM(snd_preallocate_dma
, "i");
33 MODULE_PARM_DESC(snd_preallocate_dma
, "Preallocate DMA memory when the PCM devices are initialized.");
34 MODULE_PARM_SYNTAX(snd_preallocate_dma
, SNDRV_BOOLEAN_TRUE_DESC
);
36 static int snd_maximum_substreams
= 4;
37 MODULE_PARM(snd_maximum_substreams
, "i");
38 MODULE_PARM_DESC(snd_maximum_substreams
, "Maximum substreams with preallocated DMA memory.");
39 MODULE_PARM_SYNTAX(snd_maximum_substreams
, SNDRV_BOOLEAN_TRUE_DESC
);
41 static int snd_minimum_buffer
= 16384;
44 static void snd_pcm_lib_preallocate_dma_free(snd_pcm_substream_t
*substream
)
46 if (substream
->dma_area
== NULL
)
48 switch (substream
->dma_type
) {
49 case SNDRV_PCM_DMA_TYPE_CONTINUOUS
:
50 snd_free_pages(substream
->dma_area
, substream
->dma_bytes
);
53 case SNDRV_PCM_DMA_TYPE_ISA
:
54 snd_free_isa_pages(substream
->dma_bytes
, substream
->dma_area
, substream
->dma_addr
);
58 case SNDRV_PCM_DMA_TYPE_PCI
:
59 snd_free_pci_pages((struct pci_dev
*)substream
->dma_private
, substream
->dma_bytes
, substream
->dma_area
, substream
->dma_addr
);
63 substream
->dma_area
= NULL
;
66 int snd_pcm_lib_preallocate_free(snd_pcm_substream_t
*substream
)
68 snd_pcm_lib_preallocate_dma_free(substream
);
69 if (substream
->proc_prealloc_entry
) {
70 snd_info_unregister(substream
->proc_prealloc_entry
);
71 substream
->proc_prealloc_entry
= NULL
;
76 int snd_pcm_lib_preallocate_free_for_all(snd_pcm_t
*pcm
)
78 snd_pcm_substream_t
*substream
;
81 for (stream
= 0; stream
< 2; stream
++)
82 for (substream
= pcm
->streams
[stream
].substream
; substream
; substream
= substream
->next
)
83 snd_pcm_lib_preallocate_free(substream
);
87 static void snd_pcm_lib_preallocate_proc_read(snd_info_entry_t
*entry
,
88 snd_info_buffer_t
*buffer
)
90 snd_pcm_substream_t
*substream
= (snd_pcm_substream_t
*)entry
->private_data
;
91 snd_iprintf(buffer
, "%lu\n", (unsigned long) substream
->dma_bytes
/ 1024);
94 static void snd_pcm_lib_preallocate_proc_write(snd_info_entry_t
*entry
,
95 snd_info_buffer_t
*buffer
)
97 snd_pcm_substream_t
*substream
= (snd_pcm_substream_t
*)entry
->private_data
;
98 char line
[64], str
[64];
103 if (substream
->runtime
) {
104 buffer
->error
= -EBUSY
;
107 if (!snd_info_get_line(buffer
, line
, sizeof(line
))) {
108 snd_info_get_str(str
, line
, sizeof(str
));
109 size
= simple_strtoul(str
, NULL
, 10) * 1024;
110 if ((size
!= 0 && size
< 8192) || size
> substream
->dma_max
) {
111 buffer
->error
= -EINVAL
;
114 if (substream
->dma_bytes
== size
)
117 switch (substream
->dma_type
) {
118 case SNDRV_PCM_DMA_TYPE_CONTINUOUS
:
119 dma_area
= snd_malloc_pages(size
, (unsigned int)((unsigned long)substream
->dma_private
& 0xffffffff));
120 dma_addr
= 0UL; /* not valid */
123 case SNDRV_PCM_DMA_TYPE_ISA
:
124 dma_area
= snd_malloc_isa_pages(size
, &dma_addr
);
128 case SNDRV_PCM_DMA_TYPE_PCI
:
129 dma_area
= snd_malloc_pci_pages((struct pci_dev
*)substream
->dma_private
, size
, &dma_addr
);
136 if (dma_area
== NULL
) {
137 buffer
->error
= -ENOMEM
;
140 substream
->buffer_bytes_max
= size
;
143 substream
->buffer_bytes_max
= UINT_MAX
;
145 snd_pcm_lib_preallocate_dma_free(substream
);
146 substream
->dma_area
= dma_area
;
147 substream
->dma_addr
= dma_addr
;
148 substream
->dma_bytes
= size
;
150 buffer
->error
= -EINVAL
;
154 static int snd_pcm_lib_preallocate_pages1(snd_pcm_substream_t
*substream
,
155 size_t size
, size_t max
)
157 unsigned long rsize
= 0;
158 void *dma_area
= NULL
;
159 dma_addr_t dma_addr
= 0UL;
160 snd_info_entry_t
*entry
;
162 if (!size
|| !snd_preallocate_dma
|| substream
->number
>= snd_maximum_substreams
) {
165 switch (substream
->dma_type
) {
166 case SNDRV_PCM_DMA_TYPE_CONTINUOUS
:
167 dma_area
= snd_malloc_pages_fallback(size
, (unsigned int)((unsigned long)substream
->dma_private
& 0xffffffff), &rsize
);
168 dma_addr
= 0UL; /* not valid */
171 case SNDRV_PCM_DMA_TYPE_ISA
:
172 dma_area
= snd_malloc_isa_pages_fallback(size
, &dma_addr
, &rsize
);
176 case SNDRV_PCM_DMA_TYPE_PCI
:
177 dma_area
= snd_malloc_pci_pages_fallback((struct pci_dev
*)substream
->dma_private
, size
, &dma_addr
, &rsize
);
183 if (rsize
< snd_minimum_buffer
) {
184 snd_pcm_lib_preallocate_dma_free(substream
);
188 substream
->dma_area
= dma_area
;
189 substream
->dma_addr
= dma_addr
;
190 substream
->dma_bytes
= rsize
;
192 substream
->buffer_bytes_max
= rsize
;
193 substream
->dma_max
= max
;
194 if ((entry
= snd_info_create_card_entry(substream
->pcm
->card
, "prealloc", substream
->proc_root
)) != NULL
) {
195 entry
->c
.text
.read_size
= 64;
196 entry
->c
.text
.read
= snd_pcm_lib_preallocate_proc_read
;
197 entry
->c
.text
.write_size
= 64;
198 entry
->c
.text
.write
= snd_pcm_lib_preallocate_proc_write
;
199 entry
->private_data
= substream
;
200 if (snd_info_register(entry
) < 0) {
201 snd_info_free_entry(entry
);
205 substream
->proc_prealloc_entry
= entry
;
209 int snd_pcm_lib_preallocate_pages(snd_pcm_substream_t
*substream
,
210 size_t size
, size_t max
,
213 substream
->dma_type
= SNDRV_PCM_DMA_TYPE_CONTINUOUS
;
214 substream
->dma_private
= (void *)(unsigned long)flags
;
215 return snd_pcm_lib_preallocate_pages1(substream
, size
, max
);
218 int snd_pcm_lib_preallocate_pages_for_all(snd_pcm_t
*pcm
,
219 size_t size
, size_t max
,
222 snd_pcm_substream_t
*substream
;
225 for (stream
= 0; stream
< 2; stream
++)
226 for (substream
= pcm
->streams
[stream
].substream
; substream
; substream
= substream
->next
)
227 if ((err
= snd_pcm_lib_preallocate_pages(substream
, size
, max
, flags
)) < 0)
233 int snd_pcm_lib_preallocate_isa_pages(snd_pcm_substream_t
*substream
,
234 size_t size
, size_t max
)
236 substream
->dma_type
= SNDRV_PCM_DMA_TYPE_ISA
;
237 substream
->dma_private
= NULL
;
238 return snd_pcm_lib_preallocate_pages1(substream
, size
, max
);
241 int snd_pcm_lib_preallocate_isa_pages_for_all(snd_pcm_t
*pcm
,
242 size_t size
, size_t max
)
244 snd_pcm_substream_t
*substream
;
247 for (stream
= 0; stream
< 2; stream
++)
248 for (substream
= pcm
->streams
[stream
].substream
; substream
; substream
= substream
->next
)
249 if ((err
= snd_pcm_lib_preallocate_isa_pages(substream
, size
, max
)) < 0)
253 #endif /* CONFIG_ISA */
255 int snd_pcm_lib_malloc_pages(snd_pcm_substream_t
*substream
, size_t size
)
257 snd_pcm_runtime_t
*runtime
;
258 void *dma_area
= NULL
;
259 dma_addr_t dma_addr
= 0UL;
261 snd_assert(substream
!= NULL
, return -EINVAL
);
262 runtime
= substream
->runtime
;
263 snd_assert(runtime
!= NULL
, return -EINVAL
);
264 if (runtime
->dma_area
!= NULL
) {
265 /* perphaps, we might free the large DMA memory region
266 to save some space here, but the actual solution
267 costs us less time */
268 if (runtime
->dma_bytes
>= size
)
269 return 0; /* ok, do not change */
270 snd_pcm_lib_free_pages(substream
);
272 if (substream
->dma_area
!= NULL
&& substream
->dma_bytes
>= size
) {
273 dma_area
= substream
->dma_area
;
274 dma_addr
= substream
->dma_addr
;
276 switch (substream
->dma_type
) {
277 case SNDRV_PCM_DMA_TYPE_CONTINUOUS
:
278 dma_area
= snd_malloc_pages(size
, (unsigned int)((unsigned long)substream
->dma_private
& 0xffffffff));
279 dma_addr
= 0UL; /* not valid */
282 case SNDRV_PCM_DMA_TYPE_ISA
:
283 dma_area
= snd_malloc_isa_pages(size
, &dma_addr
);
287 case SNDRV_PCM_DMA_TYPE_PCI
:
288 dma_area
= snd_malloc_pci_pages((struct pci_dev
*)substream
->dma_private
, size
, &dma_addr
);
297 runtime
->dma_area
= dma_area
;
298 runtime
->dma_addr
= dma_addr
;
299 runtime
->dma_bytes
= size
;
300 return 1; /* area was changed */
303 int snd_pcm_lib_free_pages(snd_pcm_substream_t
*substream
)
305 snd_pcm_runtime_t
*runtime
;
307 snd_assert(substream
!= NULL
, return -EINVAL
);
308 runtime
= substream
->runtime
;
309 snd_assert(runtime
!= NULL
, return -EINVAL
);
310 if (runtime
->dma_area
== NULL
)
312 if (runtime
->dma_area
!= substream
->dma_area
) {
313 switch (substream
->dma_type
) {
315 case SNDRV_PCM_DMA_TYPE_ISA
:
316 snd_free_isa_pages(runtime
->dma_bytes
, runtime
->dma_area
, runtime
->dma_addr
);
320 case SNDRV_PCM_DMA_TYPE_PCI
:
321 snd_free_pci_pages((struct pci_dev
*)substream
->dma_private
, runtime
->dma_bytes
, runtime
->dma_area
, runtime
->dma_addr
);
326 runtime
->dma_area
= NULL
;
327 runtime
->dma_addr
= 0UL;
328 runtime
->dma_bytes
= 0;
334 int snd_pcm_lib_preallocate_pci_pages(struct pci_dev
*pci
,
335 snd_pcm_substream_t
*substream
,
336 size_t size
, size_t max
)
338 substream
->dma_type
= SNDRV_PCM_DMA_TYPE_PCI
;
339 substream
->dma_private
= pci
;
340 return snd_pcm_lib_preallocate_pages1(substream
, size
, max
);
343 int snd_pcm_lib_preallocate_pci_pages_for_all(struct pci_dev
*pci
,
345 size_t size
, size_t max
)
347 snd_pcm_substream_t
*substream
;
350 for (stream
= 0; stream
< 2; stream
++)
351 for (substream
= pcm
->streams
[stream
].substream
; substream
; substream
= substream
->next
)
352 if ((err
= snd_pcm_lib_preallocate_pci_pages(pci
, substream
, size
, max
)) < 0)
357 #endif /* CONFIG_PCI */