forked from thesofproject/sof
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathbuffer.h
More file actions
227 lines (183 loc) · 6.13 KB
/
buffer.h
File metadata and controls
227 lines (183 loc) · 6.13 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
/* SPDX-License-Identifier: BSD-3-Clause
*
* Copyright(c) 2017 Intel Corporation. All rights reserved.
*
* Author: Liam Girdwood <liam.r.girdwood@linux.intel.com>
*/
#ifndef __SOF_AUDIO_BUFFER_H__
#define __SOF_AUDIO_BUFFER_H__
#include <sof/audio/pipeline.h>
#include <sof/common.h>
#include <sof/lib/alloc.h>
#include <sof/lib/cache.h>
#include <sof/list.h>
#include <sof/spinlock.h>
#include <sof/trace/trace.h>
#include <ipc/topology.h>
#include <stddef.h>
#include <stdint.h>
struct comp_dev;
/* buffer tracing */
#define trace_buffer(__e, ...) \
trace_event(TRACE_CLASS_BUFFER, __e, ##__VA_ARGS__)
#define trace_buffer_error(__e, ...) \
trace_error(TRACE_CLASS_BUFFER, __e, ##__VA_ARGS__)
#define tracev_buffer(__e, ...) \
tracev_event(TRACE_CLASS_BUFFER, __e, ##__VA_ARGS__)
#define trace_buffer_error_atomic(__e, ...) \
trace_error_atomic(TRACE_CLASS_BUFFER, __e, ##__VA_ARGS__)
/* buffer callback types */
#define BUFF_CB_TYPE_PRODUCE BIT(0)
#define BUFF_CB_TYPE_CONSUME BIT(1)
/* audio component buffer - connects 2 audio components together in pipeline */
struct comp_buffer {
/* runtime data */
uint32_t size; /* runtime buffer size in bytes (period multiple) */
uint32_t alloc_size; /* allocated size in bytes */
uint32_t avail; /* available bytes for reading */
uint32_t free; /* free bytes for writing */
void *w_ptr; /* buffer write pointer */
void *r_ptr; /* buffer read position */
void *addr; /* buffer base address */
void *end_addr; /* buffer end address */
/* IPC configuration */
struct sof_ipc_buffer ipc_buffer;
/* connected components */
struct comp_dev *source; /* source component */
struct comp_dev *sink; /* sink component */
/* lists */
struct list_item source_list; /* list in comp buffers */
struct list_item sink_list; /* list in comp buffers */
/* callbacks */
void (*cb)(void *data, uint32_t bytes);
void *cb_data;
int cb_type;
spinlock_t lock; /* component buffer spinlock */
};
#define buffer_comp_list(buffer, dir) \
((dir) == PPL_DIR_DOWNSTREAM ? &buffer->source_list : \
&buffer->sink_list)
#define buffer_from_list(ptr, type, dir) \
((dir) == PPL_DIR_DOWNSTREAM ? \
container_of(ptr, type, source_list) : \
container_of(ptr, type, sink_list))
#define buffer_get_comp(buffer, dir) \
((dir) == PPL_DIR_DOWNSTREAM ? buffer->sink : \
buffer->source)
#define buffer_set_comp(buffer, comp, dir) \
do { \
if (dir == PPL_CONN_DIR_COMP_TO_BUFFER) \
buffer->source = comp; \
else \
buffer->sink = comp; \
} while (0) \
#define buffer_set_cb(buffer, func, data, type) \
do { \
buffer->cb = func; \
buffer->cb_data = data; \
buffer->cb_type = type; \
} while (0)
#define buffer_read_frag(buffer, idx, size) \
buffer_get_frag(buffer, buffer->r_ptr, idx, size)
#define buffer_read_frag_s16(buffer, idx) \
buffer_get_frag(buffer, buffer->r_ptr, idx, sizeof(int16_t))
#define buffer_read_frag_s32(buffer, idx) \
buffer_get_frag(buffer, buffer->r_ptr, idx, sizeof(int32_t))
#define buffer_write_frag(buffer, idx, size) \
buffer_get_frag(buffer, buffer->w_ptr, idx, size)
#define buffer_write_frag_s16(buffer, idx) \
buffer_get_frag(buffer, buffer->w_ptr, idx, sizeof(int16_t))
#define buffer_write_frag_s32(buffer, idx) \
buffer_get_frag(buffer, buffer->w_ptr, idx, sizeof(int32_t))
typedef void (*cache_buff_op)(struct comp_buffer *);
/* pipeline buffer creation and destruction */
struct comp_buffer *buffer_new(struct sof_ipc_buffer *desc);
int buffer_set_size(struct comp_buffer *buffer, uint32_t size);
void buffer_free(struct comp_buffer *buffer);
/* called by a component after producing data into this buffer */
void comp_update_buffer_produce(struct comp_buffer *buffer, uint32_t bytes);
/* called by a component after consuming data from this buffer */
void comp_update_buffer_consume(struct comp_buffer *buffer, uint32_t bytes);
static inline void buffer_zero(struct comp_buffer *buffer)
{
tracev_buffer("buffer_zero()");
bzero(buffer->addr, buffer->size);
if (buffer->ipc_buffer.caps & SOF_MEM_CAPS_DMA)
dcache_writeback_region(buffer->addr, buffer->size);
}
/* get the max number of bytes that can be copied between sink and source */
static inline int comp_buffer_can_copy_bytes(struct comp_buffer *source,
struct comp_buffer *sink,
uint32_t bytes)
{
/* check for underrun */
if (source->avail < bytes)
return -1;
/* check for overrun */
if (sink->free < bytes)
return 1;
/* we are good to copy */
return 0;
}
static inline uint32_t comp_buffer_get_copy_bytes(struct comp_buffer *source,
struct comp_buffer *sink)
{
if (source->avail > sink->free)
return sink->free;
else
return source->avail;
}
static inline void comp_buffer_cache_wtb_inv(struct comp_buffer *buffer)
{
dcache_writeback_invalidate_region(buffer, sizeof(*buffer));
}
static inline void comp_buffer_cache_inv(struct comp_buffer *buffer)
{
dcache_invalidate_region(buffer, sizeof(*buffer));
}
static inline cache_buff_op comp_buffer_cache_op(int cmd)
{
switch (cmd) {
case CACHE_WRITEBACK_INV:
return &comp_buffer_cache_wtb_inv;
case CACHE_INVALIDATE:
return &comp_buffer_cache_inv;
default:
trace_buffer_error("comp_buffer_cache_op() error: "
"invalid cmd = %u", cmd);
return NULL;
}
}
static inline void buffer_reset_pos(struct comp_buffer *buffer)
{
/* reset read and write pointer to buffer bas */
buffer->w_ptr = buffer->addr;
buffer->r_ptr = buffer->addr;
/* free space is buffer size */
buffer->free = buffer->size;
/* there are no avail samples at reset */
buffer->avail = 0;
/* clear buffer contents */
buffer_zero(buffer);
}
static inline void *buffer_get_frag(struct comp_buffer *buffer, void *ptr,
uint32_t idx, uint32_t size)
{
void *current = ptr + (idx * size);
/* check for pointer wrap */
if (current >= buffer->end_addr)
current = buffer->addr + (current - buffer->end_addr);
return current;
}
static inline void buffer_init(struct comp_buffer *buffer, uint32_t size)
{
buffer->alloc_size = size;
buffer->size = size;
buffer->w_ptr = buffer->addr;
buffer->r_ptr = buffer->addr;
buffer->end_addr = buffer->addr + size;
buffer->free = size;
buffer->avail = 0;
buffer_zero(buffer);
}
#endif /* __SOF_AUDIO_BUFFER_H__ */