OpenCores
URL https://opencores.org/ocsvn/test_project/test_project/trunk

Subversion Repositories test_project

[/] [test_project/] [trunk/] [linux_sd_driver/] [include/] [sound/] [pcm-indirect.h] - Blame information for rev 81

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 62 marcus.erl
/*
2
 * Helper functions for indirect PCM data transfer
3
 *
4
 *  Copyright (c) by Takashi Iwai <tiwai@suse.de>
5
 *                   Jaroslav Kysela <perex@perex.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
struct snd_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
};
39
 
40
typedef void (*snd_pcm_indirect_copy_t)(struct snd_pcm_substream *substream,
41
                                        struct snd_pcm_indirect *rec, size_t bytes);
42
 
43
/*
44
 * helper function for playback ack callback
45
 */
46
static inline void
47
snd_pcm_indirect_playback_transfer(struct snd_pcm_substream *substream,
48
                                   struct snd_pcm_indirect *rec,
49
                                   snd_pcm_indirect_copy_t copy)
50
{
51
        struct snd_pcm_runtime *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(struct snd_pcm_substream *substream,
93
                                  struct snd_pcm_indirect *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(struct snd_pcm_substream *substream,
114
                                  struct snd_pcm_indirect *rec,
115
                                  snd_pcm_indirect_copy_t copy)
116
{
117
        struct snd_pcm_runtime *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(struct snd_pcm_substream *substream,
158
                                 struct snd_pcm_indirect *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 */

powered by: WebSVN 2.1.0

© copyright 1999-2025 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.