]>
Commit | Line | Data |
---|---|---|
1a59d1b8 | 1 | // SPDX-License-Identifier: GPL-2.0-or-later |
1da177e4 LT |
2 | /* |
3 | * ISA DMA support functions | |
c1017a4c | 4 | * Copyright (c) by Jaroslav Kysela <perex@perex.cz> |
1da177e4 LT |
5 | */ |
6 | ||
7 | /* | |
8 | * Defining following add some delay. Maybe this helps for some broken | |
9 | * ISA DMA controllers. | |
10 | */ | |
11 | ||
12 | #undef HAVE_REALLY_SLOW_DMA_CONTROLLER | |
13 | ||
d81a6d71 | 14 | #include <linux/export.h> |
1da177e4 LT |
15 | #include <sound/core.h> |
16 | #include <asm/dma.h> | |
17 | ||
18 | /** | |
19 | * snd_dma_program - program an ISA DMA transfer | |
20 | * @dma: the dma number | |
21 | * @addr: the physical address of the buffer | |
22 | * @size: the DMA transfer size | |
23 | * @mode: the DMA transfer mode, DMA_MODE_XXX | |
24 | * | |
25 | * Programs an ISA DMA transfer for the given buffer. | |
26 | */ | |
27 | void snd_dma_program(unsigned long dma, | |
28 | unsigned long addr, unsigned int size, | |
29 | unsigned short mode) | |
30 | { | |
31 | unsigned long flags; | |
32 | ||
33 | flags = claim_dma_lock(); | |
34 | disable_dma(dma); | |
35 | clear_dma_ff(dma); | |
36 | set_dma_mode(dma, mode); | |
37 | set_dma_addr(dma, addr); | |
38 | set_dma_count(dma, size); | |
39 | if (!(mode & DMA_MODE_NO_ENABLE)) | |
40 | enable_dma(dma); | |
41 | release_dma_lock(flags); | |
42 | } | |
c0d3fb39 TI |
43 | EXPORT_SYMBOL(snd_dma_program); |
44 | ||
1da177e4 LT |
45 | /** |
46 | * snd_dma_disable - stop the ISA DMA transfer | |
47 | * @dma: the dma number | |
48 | * | |
49 | * Stops the ISA DMA transfer. | |
50 | */ | |
51 | void snd_dma_disable(unsigned long dma) | |
52 | { | |
53 | unsigned long flags; | |
54 | ||
55 | flags = claim_dma_lock(); | |
56 | clear_dma_ff(dma); | |
57 | disable_dma(dma); | |
58 | release_dma_lock(flags); | |
59 | } | |
c0d3fb39 TI |
60 | EXPORT_SYMBOL(snd_dma_disable); |
61 | ||
1da177e4 LT |
62 | /** |
63 | * snd_dma_pointer - return the current pointer to DMA transfer buffer in bytes | |
64 | * @dma: the dma number | |
65 | * @size: the dma transfer size | |
66 | * | |
eb7c06e8 | 67 | * Return: The current pointer in DMA transfer buffer in bytes. |
1da177e4 LT |
68 | */ |
69 | unsigned int snd_dma_pointer(unsigned long dma, unsigned int size) | |
70 | { | |
71 | unsigned long flags; | |
8066e51a | 72 | unsigned int result, result1; |
1da177e4 LT |
73 | |
74 | flags = claim_dma_lock(); | |
75 | clear_dma_ff(dma); | |
76 | if (!isa_dma_bridge_buggy) | |
77 | disable_dma(dma); | |
78 | result = get_dma_residue(dma); | |
8066e51a KH |
79 | /* |
80 | * HACK - read the counter again and choose higher value in order to | |
81 | * avoid reading during counter lower byte roll over if the | |
82 | * isa_dma_bridge_buggy is set. | |
83 | */ | |
84 | result1 = get_dma_residue(dma); | |
1da177e4 LT |
85 | if (!isa_dma_bridge_buggy) |
86 | enable_dma(dma); | |
87 | release_dma_lock(flags); | |
8066e51a KH |
88 | if (unlikely(result < result1)) |
89 | result = result1; | |
1da177e4 LT |
90 | #ifdef CONFIG_SND_DEBUG |
91 | if (result > size) | |
f2f9307a | 92 | pr_err("ALSA: pointer (0x%x) for DMA #%ld is greater than transfer size (0x%x)\n", result, dma, size); |
1da177e4 LT |
93 | #endif |
94 | if (result >= size || result == 0) | |
95 | return 0; | |
96 | else | |
97 | return size - result; | |
98 | } | |
c0d3fb39 | 99 | EXPORT_SYMBOL(snd_dma_pointer); |