diff options
author | Linus Torvalds <torvalds@ppc970.osdl.org> | 2005-04-16 18:20:36 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@ppc970.osdl.org> | 2005-04-16 18:20:36 -0400 |
commit | 1da177e4c3f41524e886b7f1b8a0c1fc7321cac2 (patch) | |
tree | 0bba044c4ce775e45a88a51686b5d9f90697ea9d /include/sound/pcm-indirect.h |
Linux-2.6.12-rc2v2.6.12-rc2
Initial git repository build. I'm not bothering with the full history,
even though we have it. We can create a separate "historical" git
archive of that later if we want to, and in the meantime it's about
3.2GB when imported into git - space that would just make the early
git days unnecessarily complicated, when we don't have a lot of good
infrastructure for it.
Let it rip!
Diffstat (limited to 'include/sound/pcm-indirect.h')
-rw-r--r-- | include/sound/pcm-indirect.h | 177 |
1 files changed, 177 insertions, 0 deletions
diff --git a/include/sound/pcm-indirect.h b/include/sound/pcm-indirect.h new file mode 100644 index 000000000000..31fa7a54508a --- /dev/null +++ b/include/sound/pcm-indirect.h | |||
@@ -0,0 +1,177 @@ | |||
1 | /* | ||
2 | * Helper functions for indirect PCM data transfer | ||
3 | * | ||
4 | * Copyright (c) by Takashi Iwai <tiwai@suse.de> | ||
5 | * Jaroslav Kysela <perex@suse.cz> | ||
6 | * | ||
7 | * This program is free software; you can redistribute it and/or modify | ||
8 | * it under the terms of the GNU General Public License as published by | ||
9 | * the Free Software Foundation; either version 2 of the License, or | ||
10 | * (at your option) any later version. | ||
11 | * | ||
12 | * This program is distributed in the hope that it will be useful, | ||
13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
15 | * GNU General Public License for more details. | ||
16 | * | ||
17 | * You should have received a copy of the GNU General Public License | ||
18 | * along with this program; if not, write to the Free Software | ||
19 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
20 | */ | ||
21 | |||
22 | #ifndef __SOUND_PCM_INDIRECT_H | ||
23 | #define __SOUND_PCM_INDIRECT_H | ||
24 | |||
25 | #include <sound/pcm.h> | ||
26 | |||
27 | typedef struct sndrv_pcm_indirect { | ||
28 | unsigned int hw_buffer_size; /* Byte size of hardware buffer */ | ||
29 | unsigned int hw_queue_size; /* Max queue size of hw buffer (0 = buffer size) */ | ||
30 | unsigned int hw_data; /* Offset to next dst (or src) in hw ring buffer */ | ||
31 | unsigned int hw_io; /* Ring buffer hw pointer */ | ||
32 | int hw_ready; /* Bytes ready for play (or captured) in hw ring buffer */ | ||
33 | unsigned int sw_buffer_size; /* Byte size of software buffer */ | ||
34 | unsigned int sw_data; /* Offset to next dst (or src) in sw ring buffer */ | ||
35 | unsigned int sw_io; /* Current software pointer in bytes */ | ||
36 | int sw_ready; /* Bytes ready to be transferred to/from hw */ | ||
37 | snd_pcm_uframes_t appl_ptr; /* Last seen appl_ptr */ | ||
38 | } snd_pcm_indirect_t; | ||
39 | |||
40 | typedef void (*snd_pcm_indirect_copy_t)(snd_pcm_substream_t *substream, | ||
41 | snd_pcm_indirect_t *rec, size_t bytes); | ||
42 | |||
43 | /* | ||
44 | * helper function for playback ack callback | ||
45 | */ | ||
46 | static inline void | ||
47 | snd_pcm_indirect_playback_transfer(snd_pcm_substream_t *substream, | ||
48 | snd_pcm_indirect_t *rec, | ||
49 | snd_pcm_indirect_copy_t copy) | ||
50 | { | ||
51 | snd_pcm_runtime_t *runtime = substream->runtime; | ||
52 | snd_pcm_uframes_t appl_ptr = runtime->control->appl_ptr; | ||
53 | snd_pcm_sframes_t diff = appl_ptr - rec->appl_ptr; | ||
54 | int qsize; | ||
55 | |||
56 | if (diff) { | ||
57 | if (diff < -(snd_pcm_sframes_t) (runtime->boundary / 2)) | ||
58 | diff += runtime->boundary; | ||
59 | rec->sw_ready += (int)frames_to_bytes(runtime, diff); | ||
60 | rec->appl_ptr = appl_ptr; | ||
61 | } | ||
62 | qsize = rec->hw_queue_size ? rec->hw_queue_size : rec->hw_buffer_size; | ||
63 | while (rec->hw_ready < qsize && rec->sw_ready > 0) { | ||
64 | unsigned int hw_to_end = rec->hw_buffer_size - rec->hw_data; | ||
65 | unsigned int sw_to_end = rec->sw_buffer_size - rec->sw_data; | ||
66 | unsigned int bytes = qsize - rec->hw_ready; | ||
67 | if (rec->sw_ready < (int)bytes) | ||
68 | bytes = rec->sw_ready; | ||
69 | if (hw_to_end < bytes) | ||
70 | bytes = hw_to_end; | ||
71 | if (sw_to_end < bytes) | ||
72 | bytes = sw_to_end; | ||
73 | if (! bytes) | ||
74 | break; | ||
75 | copy(substream, rec, bytes); | ||
76 | rec->hw_data += bytes; | ||
77 | if (rec->hw_data == rec->hw_buffer_size) | ||
78 | rec->hw_data = 0; | ||
79 | rec->sw_data += bytes; | ||
80 | if (rec->sw_data == rec->sw_buffer_size) | ||
81 | rec->sw_data = 0; | ||
82 | rec->hw_ready += bytes; | ||
83 | rec->sw_ready -= bytes; | ||
84 | } | ||
85 | } | ||
86 | |||
87 | /* | ||
88 | * helper function for playback pointer callback | ||
89 | * ptr = current byte pointer | ||
90 | */ | ||
91 | static inline snd_pcm_uframes_t | ||
92 | snd_pcm_indirect_playback_pointer(snd_pcm_substream_t *substream, | ||
93 | snd_pcm_indirect_t *rec, unsigned int ptr) | ||
94 | { | ||
95 | int bytes = ptr - rec->hw_io; | ||
96 | if (bytes < 0) | ||
97 | bytes += rec->hw_buffer_size; | ||
98 | rec->hw_io = ptr; | ||
99 | rec->hw_ready -= bytes; | ||
100 | rec->sw_io += bytes; | ||
101 | if (rec->sw_io >= rec->sw_buffer_size) | ||
102 | rec->sw_io -= rec->sw_buffer_size; | ||
103 | if (substream->ops->ack) | ||
104 | substream->ops->ack(substream); | ||
105 | return bytes_to_frames(substream->runtime, rec->sw_io); | ||
106 | } | ||
107 | |||
108 | |||
109 | /* | ||
110 | * helper function for capture ack callback | ||
111 | */ | ||
112 | static inline void | ||
113 | snd_pcm_indirect_capture_transfer(snd_pcm_substream_t *substream, | ||
114 | snd_pcm_indirect_t *rec, | ||
115 | snd_pcm_indirect_copy_t copy) | ||
116 | { | ||
117 | snd_pcm_runtime_t *runtime = substream->runtime; | ||
118 | snd_pcm_uframes_t appl_ptr = runtime->control->appl_ptr; | ||
119 | snd_pcm_sframes_t diff = appl_ptr - rec->appl_ptr; | ||
120 | |||
121 | if (diff) { | ||
122 | if (diff < -(snd_pcm_sframes_t) (runtime->boundary / 2)) | ||
123 | diff += runtime->boundary; | ||
124 | rec->sw_ready -= frames_to_bytes(runtime, diff); | ||
125 | rec->appl_ptr = appl_ptr; | ||
126 | } | ||
127 | while (rec->hw_ready > 0 && | ||
128 | rec->sw_ready < (int)rec->sw_buffer_size) { | ||
129 | size_t hw_to_end = rec->hw_buffer_size - rec->hw_data; | ||
130 | size_t sw_to_end = rec->sw_buffer_size - rec->sw_data; | ||
131 | size_t bytes = rec->sw_buffer_size - rec->sw_ready; | ||
132 | if (rec->hw_ready < (int)bytes) | ||
133 | bytes = rec->hw_ready; | ||
134 | if (hw_to_end < bytes) | ||
135 | bytes = hw_to_end; | ||
136 | if (sw_to_end < bytes) | ||
137 | bytes = sw_to_end; | ||
138 | if (! bytes) | ||
139 | break; | ||
140 | copy(substream, rec, bytes); | ||
141 | rec->hw_data += bytes; | ||
142 | if ((int)rec->hw_data == rec->hw_buffer_size) | ||
143 | rec->hw_data = 0; | ||
144 | rec->sw_data += bytes; | ||
145 | if (rec->sw_data == rec->sw_buffer_size) | ||
146 | rec->sw_data = 0; | ||
147 | rec->hw_ready -= bytes; | ||
148 | rec->sw_ready += bytes; | ||
149 | } | ||
150 | } | ||
151 | |||
152 | /* | ||
153 | * helper function for capture pointer callback, | ||
154 | * ptr = current byte pointer | ||
155 | */ | ||
156 | static inline snd_pcm_uframes_t | ||
157 | snd_pcm_indirect_capture_pointer(snd_pcm_substream_t *substream, | ||
158 | snd_pcm_indirect_t *rec, unsigned int ptr) | ||
159 | { | ||
160 | int qsize; | ||
161 | int bytes = ptr - rec->hw_io; | ||
162 | if (bytes < 0) | ||
163 | bytes += rec->hw_buffer_size; | ||
164 | rec->hw_io = ptr; | ||
165 | rec->hw_ready += bytes; | ||
166 | qsize = rec->hw_queue_size ? rec->hw_queue_size : rec->hw_buffer_size; | ||
167 | if (rec->hw_ready > qsize) | ||
168 | return SNDRV_PCM_POS_XRUN; | ||
169 | rec->sw_io += bytes; | ||
170 | if (rec->sw_io >= rec->sw_buffer_size) | ||
171 | rec->sw_io -= rec->sw_buffer_size; | ||
172 | if (substream->ops->ack) | ||
173 | substream->ops->ack(substream); | ||
174 | return bytes_to_frames(substream->runtime, rec->sw_io); | ||
175 | } | ||
176 | |||
177 | #endif /* __SOUND_PCM_INDIRECT_H */ | ||