slc90e66 update
[linux-2.6/history.git] / sound / core / pcm_memory.c
blobdfc207c1af23731e8d6b44d9b12ef5d30982acf2
1 /*
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>
24 #include <asm/io.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)
47 return;
48 switch (substream->dma_type) {
49 case SNDRV_PCM_DMA_TYPE_CONTINUOUS:
50 snd_free_pages(substream->dma_area, substream->dma_bytes);
51 break;
52 #ifdef CONFIG_ISA
53 case SNDRV_PCM_DMA_TYPE_ISA:
54 snd_free_isa_pages(substream->dma_bytes, substream->dma_area, substream->dma_addr);
55 break;
56 #endif
57 #ifdef CONFIG_PCI
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);
60 break;
61 #endif
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;
73 return 0;
76 int snd_pcm_lib_preallocate_free_for_all(snd_pcm_t *pcm)
78 snd_pcm_substream_t *substream;
79 int stream;
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);
84 return 0;
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];
99 size_t size;
100 void *dma_area;
101 dma_addr_t dma_addr;
103 if (substream->runtime) {
104 buffer->error = -EBUSY;
105 return;
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;
112 return;
114 if (substream->dma_bytes == size)
115 return;
116 if (size > 0) {
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 */
121 break;
122 #ifdef CONFIG_ISA
123 case SNDRV_PCM_DMA_TYPE_ISA:
124 dma_area = snd_malloc_isa_pages(size, &dma_addr);
125 break;
126 #endif
127 #ifdef CONFIG_PCI
128 case SNDRV_PCM_DMA_TYPE_PCI:
129 dma_area = snd_malloc_pci_pages((struct pci_dev *)substream->dma_private, size, &dma_addr);
130 break;
131 #endif
132 default:
133 dma_area = NULL;
134 dma_addr = 0UL;
136 if (dma_area == NULL) {
137 buffer->error = -ENOMEM;
138 return;
140 substream->buffer_bytes_max = size;
141 } else {
142 dma_area = NULL;
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;
149 } else {
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) {
163 size = 0;
164 } else {
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 */
169 break;
170 #ifdef CONFIG_ISA
171 case SNDRV_PCM_DMA_TYPE_ISA:
172 dma_area = snd_malloc_isa_pages_fallback(size, &dma_addr, &rsize);
173 break;
174 #endif
175 #ifdef CONFIG_PCI
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);
178 break;
179 #endif
180 default:
181 size = 0;
183 if (rsize < snd_minimum_buffer) {
184 snd_pcm_lib_preallocate_dma_free(substream);
185 size = 0;
188 substream->dma_area = dma_area;
189 substream->dma_addr = dma_addr;
190 substream->dma_bytes = rsize;
191 if (rsize > 0)
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);
202 entry = NULL;
205 substream->proc_prealloc_entry = entry;
206 return 0;
209 int snd_pcm_lib_preallocate_pages(snd_pcm_substream_t *substream,
210 size_t size, size_t max,
211 unsigned int flags)
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,
220 unsigned int flags)
222 snd_pcm_substream_t *substream;
223 int stream, err;
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)
228 return err;
229 return 0;
232 #ifdef CONFIG_ISA
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;
245 int stream, err;
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)
250 return err;
251 return 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;
275 } else {
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 */
280 break;
281 #ifdef CONFIG_ISA
282 case SNDRV_PCM_DMA_TYPE_ISA:
283 dma_area = snd_malloc_isa_pages(size, &dma_addr);
284 break;
285 #endif
286 #ifdef CONFIG_PCI
287 case SNDRV_PCM_DMA_TYPE_PCI:
288 dma_area = snd_malloc_pci_pages((struct pci_dev *)substream->dma_private, size, &dma_addr);
289 break;
290 #endif
291 default:
292 return -ENXIO;
295 if (! dma_area)
296 return -ENOMEM;
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)
311 return 0;
312 if (runtime->dma_area != substream->dma_area) {
313 switch (substream->dma_type) {
314 #ifdef CONFIG_ISA
315 case SNDRV_PCM_DMA_TYPE_ISA:
316 snd_free_isa_pages(runtime->dma_bytes, runtime->dma_area, runtime->dma_addr);
317 break;
318 #endif
319 #ifdef CONFIG_PCI
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);
322 break;
323 #endif
326 runtime->dma_area = NULL;
327 runtime->dma_addr = 0UL;
328 runtime->dma_bytes = 0;
329 return 0;
332 #ifdef CONFIG_PCI
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,
344 snd_pcm_t *pcm,
345 size_t size, size_t max)
347 snd_pcm_substream_t *substream;
348 int stream, err;
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)
353 return err;
354 return 0;
357 #endif /* CONFIG_PCI */