blob: 1b5d1c911ff87a5c0690f1cf6ba3d0afc1438fbc [file] [log] [blame]
Seppo Ingalsuo6a274832017-06-07 14:17:55 +03001/*
2 * Copyright (c) 2017, Intel Corporation
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 * * Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * * Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * * Neither the name of the Intel Corporation nor the
13 * names of its contributors may be used to endorse or promote products
14 * derived from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
17 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
20 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
21 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
22 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
23 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
24 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
25 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
26 * POSSIBILITY OF SUCH DAMAGE.
27 *
28 * Author: Seppo Ingalsuo <seppo.ingalsuo@linux.intel.com>
29 * Liam Girdwood <liam.r.girdwood@linux.intel.com>
30 * Keyon Jie <yang.jie@linux.intel.com>
31 */
32
33#include <stdint.h>
34#include <stddef.h>
35#include <errno.h>
36#include <reef/reef.h>
37#include <reef/lock.h>
38#include <reef/list.h>
39#include <reef/stream.h>
40#include <reef/alloc.h>
41#include <reef/work.h>
42#include <reef/clock.h>
43#include <reef/audio/component.h>
44#include <reef/audio/pipeline.h>
Liam Girdwood17641522017-06-09 17:27:02 +010045#include <uapi/ipc.h>
Seppo Ingalsuo6a274832017-06-07 14:17:55 +030046#include "src_core.h"
47
48#ifdef MODULE_TEST
49#include <stdio.h>
50#endif
51
52#define trace_src(__e) trace_event(TRACE_CLASS_SRC, __e)
53#define tracev_src(__e) tracev_event(TRACE_CLASS_SRC, __e)
54#define trace_src_error(__e) trace_error(TRACE_CLASS_SRC, __e)
55
56/* src component private data */
57struct comp_data {
58 struct polyphase_src src[PLATFORM_MAX_CHANNELS];
59 int32_t *delay_lines;
60 int scratch_length;
Liam Girdwood3488cce2017-08-10 11:59:08 +010061 uint32_t sink_rate;
62 uint32_t source_rate;
63 //int32_t z[STAGE_BUF_SIZE];
Seppo Ingalsuo6a274832017-06-07 14:17:55 +030064 void (*src_func)(struct comp_dev *dev,
65 struct comp_buffer *source,
66 struct comp_buffer *sink,
67 uint32_t source_frames,
68 uint32_t sink_frames);
69};
70
71/* Common mute function for 2s and 1s SRC. This preserves the same
72 * buffer consume and produce pattern as normal operation.
73 */
74static void src_muted_s32(struct comp_buffer *source, struct comp_buffer *sink,
75 int blk_in, int blk_out, int nch, int source_frames)
76{
77
78 int i;
79 int32_t *src = (int32_t *) source->r_ptr;
80 int32_t *dest = (int32_t *) sink->w_ptr;
81 int32_t *end = (int32_t *) sink->end_addr;
82 int n_read = 0;
83 int n_max;
84 int n;
85 int n_written = 0;
86
87 for (i = 0; i < source_frames - blk_in + 1; i += blk_in) {
88 n_max = end - dest;
89 n = nch*blk_out;
90 if (n < n_max) {
91 bzero(dest, n * sizeof(int32_t));
92 dest += n;
93 } else {
94 /* Also case n_max == n is done here */
95 bzero(dest, n_max * sizeof(int32_t));
96 dest = (int32_t *) sink->addr;
97 bzero(dest, (n - n_max) * sizeof(int32_t));
98 dest += n - n_max;
99 }
100 n_read += nch*blk_in;
101 n_written += nch*blk_out;
102 }
103 source->r_ptr = src + n_read;
104 sink->w_ptr = dest;
Seppo Ingalsuo6a274832017-06-07 14:17:55 +0300105}
106
107/* Fallback function to just output muted samples and advance
108 * pointers. Note that a buffer that is not having integer number of
109 * frames in a period will drift since there is no similar blk in/out
110 * check as for SRC.
111 */
112static void fallback_s32(struct comp_dev *dev,
113 struct comp_buffer *source,
114 struct comp_buffer *sink,
115 uint32_t source_frames,
116 uint32_t sink_frames)
117{
118
119 struct comp_data *cd = comp_get_drvdata(dev);
120 //int32_t *src = (int32_t*) source->r_ptr;
121 //int32_t *dest = (int32_t*) sink->w_ptr;
Liam Girdwood3488cce2017-08-10 11:59:08 +0100122 int nch = dev->params.channels;
Seppo Ingalsuo6a274832017-06-07 14:17:55 +0300123 int blk_in = cd->src[0].blk_in;
124 int blk_out = cd->src[0].blk_out;
125
126 src_muted_s32(source, sink, blk_in, blk_out, nch, source_frames);
127
128}
129
130/* Normal 2 stage SRC */
131static void src_2s_s32_default(struct comp_dev *dev,
132 struct comp_buffer *source, struct comp_buffer *sink,
133 uint32_t source_frames, uint32_t sink_frames)
134{
135 int i, j;
136 struct polyphase_src *s;
137 struct comp_data *cd = comp_get_drvdata(dev);
138 int blk_in = cd->src[0].blk_in;
139 int blk_out = cd->src[0].blk_out;
140 int n_times1 = cd->src[0].stage1_times;
141 int n_times2 = cd->src[0].stage2_times;
Liam Girdwood3488cce2017-08-10 11:59:08 +0100142 int nch = dev->params.channels;
Seppo Ingalsuo6a274832017-06-07 14:17:55 +0300143 int32_t *dest = (int32_t *) sink->w_ptr;
144 int32_t *src = (int32_t *) source->r_ptr;
145 struct src_stage_prm s1, s2;
146 int n_read = 0;
147 int n_written = 0;
148
149 if (cd->src[0].mute) {
Liam Girdwood3488cce2017-08-10 11:59:08 +0100150 src_muted_s32(source, sink, blk_in, blk_out, nch, source_frames);
Seppo Ingalsuo6a274832017-06-07 14:17:55 +0300151 return;
152 }
153
154 s1.times = n_times1;
155 s1.x_end_addr = source->end_addr;
156 s1.x_size = source->alloc_size;
157 s1.x_inc = nch;
158 s1.y_end_addr = &cd->delay_lines[cd->scratch_length];
159 s1.y_size = STAGE_BUF_SIZE * sizeof(int32_t);
160 s1.y_inc = 1;
161
162 s2.times = n_times2;
163 s2.x_end_addr = &cd->delay_lines[cd->scratch_length];
164 s2.x_size = STAGE_BUF_SIZE * sizeof(int32_t);
165 s2.x_inc = 1;
166 s2.y_end_addr = sink->end_addr;
167 s2.y_size = sink->alloc_size;
168 s2.y_inc = nch;
169
Seppo Ingalsuo6f27ab62017-06-12 11:31:15 +0300170 s1.x_rptr = src + nch - 1;
171 s2.y_wptr = dest + nch - 1;
172
Seppo Ingalsuo6a274832017-06-07 14:17:55 +0300173 for (j = 0; j < nch; j++) {
174 s = &cd->src[j]; /* Point to src[] for this channel */
175 s1.x_rptr = src++;
176 s2.y_wptr = dest++;
177 s1.state = &s->state1;
178 s1.stage = s->stage1;
179 s2.state = &s->state2;
180 s2.stage = s->stage2;
181
182 for (i = 0; i < source_frames - blk_in + 1; i += blk_in) {
183 /* Reset output to buffer start, read interleaved */
184 s1.y_wptr = cd->delay_lines;
185 src_polyphase_stage_cir(&s1);
186 s2.x_rptr = cd->delay_lines;
187 src_polyphase_stage_cir(&s2);
188
189 n_read += blk_in;
190 n_written += blk_out;
191 }
192 }
193 source->r_ptr = s1.x_rptr - nch + 1;
194 sink->w_ptr = s2.y_wptr - nch + 1;
Seppo Ingalsuo6a274832017-06-07 14:17:55 +0300195}
196
197/* 1 stage SRC for simple conversions */
198static void src_1s_s32_default(struct comp_dev *dev,
199 struct comp_buffer *source, struct comp_buffer *sink,
200 uint32_t source_frames, uint32_t sink_frames)
201{
202 int i, j;
203 //int32_t *xp, *yp;
204 struct polyphase_src *s;
205
206 struct comp_data *cd = comp_get_drvdata(dev);
207 int blk_in = cd->src[0].blk_in;
208 int blk_out = cd->src[0].blk_out;
209 int n_times = cd->src[0].stage1_times;
Liam Girdwood3488cce2017-08-10 11:59:08 +0100210 int nch = dev->params.channels;
Seppo Ingalsuo4a006912017-06-28 19:25:51 +0300211 int32_t *dest = (int32_t *) sink->w_ptr;
212 int32_t *src = (int32_t *) source->r_ptr;
Seppo Ingalsuo6a274832017-06-07 14:17:55 +0300213 int n_read = 0;
214 int n_written = 0;
215 struct src_stage_prm s1;
216
217 if (cd->src[0].mute) {
Seppo Ingalsuo4a006912017-06-28 19:25:51 +0300218 src_muted_s32(source, sink, blk_in, blk_out, nch,
219 source_frames);
Seppo Ingalsuo6a274832017-06-07 14:17:55 +0300220 return;
221 }
222
223 s1.times = n_times;
224 s1.x_end_addr = source->end_addr;
225 s1.x_size = source->alloc_size;
226 s1.x_inc = nch;
227 s1.y_end_addr = sink->end_addr;
228 s1.y_size = sink->alloc_size;
229 s1.y_inc = nch;
Seppo Ingalsuo6f27ab62017-06-12 11:31:15 +0300230 s1.x_rptr = src + nch - 1;
231 s1.y_wptr = dest + nch - 1;
Seppo Ingalsuo6a274832017-06-07 14:17:55 +0300232
233 for (j = 0; j < nch; j++) {
234 s = &cd->src[j]; /* Point to src for this channel */
235 s1.x_rptr = src++;
236 s1.y_wptr = dest++;
237 s1.state = &s->state1;
238 s1.stage = s->stage1;
239
240 for (i = 0; i + blk_in - 1 < source_frames; i += blk_in) {
241 src_polyphase_stage_cir(&s1);
242
243 n_read += blk_in;
244 n_written += blk_out;
245 }
246
247 }
248 source->r_ptr = s1.x_rptr - nch + 1;
249 sink->w_ptr = s1.y_wptr - nch + 1;
Seppo Ingalsuo6a274832017-06-07 14:17:55 +0300250}
251
252static struct comp_dev *src_new(struct sof_ipc_comp *comp)
253{
Seppo Ingalsuo6a274832017-06-07 14:17:55 +0300254 struct comp_dev *dev;
Liam Girdwood960cf8e2017-06-12 11:38:07 +0100255 struct sof_ipc_comp_src *src;
Liam Girdwood3488cce2017-08-10 11:59:08 +0100256 struct sof_ipc_comp_src *ipc_src = (struct sof_ipc_comp_src *)comp;
Seppo Ingalsuo6a274832017-06-07 14:17:55 +0300257 struct comp_data *cd;
Liam Girdwood960cf8e2017-06-12 11:38:07 +0100258 int i;
Seppo Ingalsuo6a274832017-06-07 14:17:55 +0300259
Liam Girdwood3488cce2017-08-10 11:59:08 +0100260 trace_src("new");
Liam Girdwood960cf8e2017-06-12 11:38:07 +0100261
Liam Girdwood3488cce2017-08-10 11:59:08 +0100262 dev = rzalloc(RZONE_RUNTIME, RFLAGS_NONE,
Liam Girdwood17641522017-06-09 17:27:02 +0100263 COMP_SIZE(struct sof_ipc_comp_src));
Seppo Ingalsuo6a274832017-06-07 14:17:55 +0300264 if (dev == NULL)
265 return NULL;
266
Liam Girdwood3488cce2017-08-10 11:59:08 +0100267 src = (struct sof_ipc_comp_src *)&dev->comp;
Liam Girdwood960cf8e2017-06-12 11:38:07 +0100268 memcpy(src, ipc_src, sizeof(struct sof_ipc_comp_src));
Seppo Ingalsuo6a274832017-06-07 14:17:55 +0300269
Liam Girdwood3488cce2017-08-10 11:59:08 +0100270 cd = rzalloc(RZONE_RUNTIME, RFLAGS_NONE, sizeof(*cd));
Seppo Ingalsuo6a274832017-06-07 14:17:55 +0300271 if (cd == NULL) {
Seppo Ingalsuo6a274832017-06-07 14:17:55 +0300272 rfree(dev);
Seppo Ingalsuo6a274832017-06-07 14:17:55 +0300273 return NULL;
274 }
275
276 comp_set_drvdata(dev, cd);
Seppo Ingalsuo6a274832017-06-07 14:17:55 +0300277
278 cd->delay_lines = NULL;
279 cd->src_func = src_2s_s32_default;
280 for (i = 0; i < PLATFORM_MAX_CHANNELS; i++)
281 src_polyphase_reset(&cd->src[i]);
282
283 return dev;
284}
285
286static void src_free(struct comp_dev *dev)
287{
288 struct comp_data *cd = comp_get_drvdata(dev);
289
Liam Girdwood3488cce2017-08-10 11:59:08 +0100290 trace_src("fre");
Seppo Ingalsuo6a274832017-06-07 14:17:55 +0300291
Seppo Ingalsuo6a274832017-06-07 14:17:55 +0300292 /* Free dynamically reserved buffers for SRC algorithm */
293 if (cd->delay_lines != NULL)
294 rfree(cd->delay_lines);
295
296 rfree(cd);
297 rfree(dev);
Seppo Ingalsuo6a274832017-06-07 14:17:55 +0300298}
299
300/* set component audio stream parameters */
Liam Girdwood3488cce2017-08-10 11:59:08 +0100301static int src_params(struct comp_dev *dev, struct stream_params *host_params)
Seppo Ingalsuo6a274832017-06-07 14:17:55 +0300302{
Liam Girdwood3488cce2017-08-10 11:59:08 +0100303 struct sof_ipc_stream_params *params = &dev->params;
304 struct sof_ipc_comp_src *src = COMP_GET_IPC(dev, sof_ipc_comp_src);
305 struct sof_ipc_comp_config *config = COMP_GET_CONFIG(dev);
306 struct comp_data *cd = comp_get_drvdata(dev);
Seppo Ingalsuo6a274832017-06-07 14:17:55 +0300307 struct src_alloc need;
308 size_t delay_lines_size;
Liam Girdwood3488cce2017-08-10 11:59:08 +0100309 uint32_t source_rate, sink_rate;
Seppo Ingalsuo6a274832017-06-07 14:17:55 +0300310 int32_t *buffer_start;
Liam Girdwood3488cce2017-08-10 11:59:08 +0100311 int n = 0, i;
Seppo Ingalsuo6a274832017-06-07 14:17:55 +0300312
Liam Girdwood3488cce2017-08-10 11:59:08 +0100313 trace_src("par");
Seppo Ingalsuo6a274832017-06-07 14:17:55 +0300314
Liam Girdwood3488cce2017-08-10 11:59:08 +0100315 comp_install_params(dev, host_params);
316
317 /* EQ supports only S32_LE PCM format */
318 if (config->frame_fmt != SOF_IPC_FRAME_S32_LE)
Seppo Ingalsuo6a274832017-06-07 14:17:55 +0300319 return -EINVAL;
320
Liam Girdwood3488cce2017-08-10 11:59:08 +0100321 /* Calculate source and sink rates, one rate will come from IPC new
322 * and the other from params. */
323 if (src->source_rate == 0) {
324 /* params rate is source rate */
325 source_rate = params->rate;
326 sink_rate = src->sink_rate;
327 /* re-write our params with output rate for next component */
328 params->rate = sink_rate;
329 } else {
330 /* params rate is sink rate */
331 source_rate = src->source_rate;
332 sink_rate = params->rate;
333 /* re-write our params with output rate for next component */
334 params->rate = source_rate;
335 }
Seppo Ingalsuo4a006912017-06-28 19:25:51 +0300336
337 /* Allocate needed memory for delay lines */
Liam Girdwood3488cce2017-08-10 11:59:08 +0100338 src_buffer_lengths(&need, source_rate, sink_rate, params->channels);
Seppo Ingalsuo6a274832017-06-07 14:17:55 +0300339 delay_lines_size = sizeof(int32_t) * need.total;
340 if (cd->delay_lines != NULL)
341 rfree(cd->delay_lines);
342
Liam Girdwood3488cce2017-08-10 11:59:08 +0100343 cd->delay_lines = rzalloc(RZONE_RUNTIME, RFLAGS_NONE, delay_lines_size);
Seppo Ingalsuo6a274832017-06-07 14:17:55 +0300344 if (cd->delay_lines == NULL)
Liam Girdwood3488cce2017-08-10 11:59:08 +0100345 return -EINVAL;
Seppo Ingalsuo6a274832017-06-07 14:17:55 +0300346
347 /* Clear all delay lines here */
348 memset(cd->delay_lines, 0, delay_lines_size);
349 cd->scratch_length = need.scratch;
350 buffer_start = cd->delay_lines + need.scratch;
351
352 /* Initize SRC for actual sample rate */
Liam Girdwood3488cce2017-08-10 11:59:08 +0100353 for (i = 0; i < params->channels; i++) {
354 n = src_polyphase_init(&cd->src[i], source_rate,
355 sink_rate, buffer_start);
Seppo Ingalsuo6a274832017-06-07 14:17:55 +0300356 buffer_start += need.single_src;
357 }
358
359 switch (n) {
360 case 1:
361 cd->src_func = src_1s_s32_default; /* Simpler 1 stage SRC */
362 break;
363 case 2:
364 cd->src_func = src_2s_s32_default; /* Default 2 stage SRC */
365 break;
366 default:
367 /* This is possibly due to missing coefficients for
368 * requested rates combination. Sink audio will be
369 * muted if copy() is run.
370 */
371 trace_src("SFa");
372 cd->src_func = fallback_s32;
Seppo Ingalsuo4a006912017-06-28 19:25:51 +0300373 return -EINVAL;
Liam Girdwood3488cce2017-08-10 11:59:08 +0100374 break;
Seppo Ingalsuo6a274832017-06-07 14:17:55 +0300375 }
376
377 /* Check that src blk_in and blk_out are less than params.period_frames.
378 * Return an error if the period is too short.
379 */
Liam Girdwood3488cce2017-08-10 11:59:08 +0100380 if (src_polyphase_get_blk_in(&cd->src[0]) > config->frames)
Seppo Ingalsuo4a006912017-06-28 19:25:51 +0300381 return -EINVAL;
Seppo Ingalsuo6a274832017-06-07 14:17:55 +0300382
Liam Girdwood3488cce2017-08-10 11:59:08 +0100383 if (src_polyphase_get_blk_out(&cd->src[0]) > config->frames)
Seppo Ingalsuo4a006912017-06-28 19:25:51 +0300384 return -EINVAL;
Seppo Ingalsuo6a274832017-06-07 14:17:55 +0300385
Seppo Ingalsuo6a274832017-06-07 14:17:55 +0300386 return 0;
387}
388
389/* used to pass standard and bespoke commands (with data) to component */
390static int src_cmd(struct comp_dev *dev, int cmd, void *data)
391{
392 trace_src("SCm");
393 struct comp_data *cd = comp_get_drvdata(dev);
Liam Girdwood3488cce2017-08-10 11:59:08 +0100394// struct sof_ipc_comp_src *cv;
Seppo Ingalsuo6a274832017-06-07 14:17:55 +0300395 int i;
396
397 switch (cmd) {
398 case COMP_CMD_SRC:
399 trace_src("SMa");
Liam Girdwood3488cce2017-08-10 11:59:08 +0100400// cv = (struct sof_ipc_comp_src *) data;
401// cv->in_mask = src_input_rates();
402// cv->out_mask = src_output_rates();
Seppo Ingalsuo6a274832017-06-07 14:17:55 +0300403 break;
404 case COMP_CMD_MUTE:
405 trace_src("SMu");
406 for (i = 0; i < PLATFORM_MAX_CHANNELS; i++)
407 src_polyphase_mute(&cd->src[i]);
408
409 break;
410 case COMP_CMD_UNMUTE:
411 trace_src("SUm");
412 for (i = 0; i < PLATFORM_MAX_CHANNELS; i++)
413 src_polyphase_unmute(&cd->src[i]);
414
415 break;
416 case COMP_CMD_START:
417 trace_src("SSt");
418 dev->state = COMP_STATE_RUNNING;
419 break;
420 case COMP_CMD_STOP:
421 trace_src("SSp");
422 if (dev->state == COMP_STATE_RUNNING ||
423 dev->state == COMP_STATE_DRAINING ||
424 dev->state == COMP_STATE_PAUSED) {
425 comp_buffer_reset(dev);
426 dev->state = COMP_STATE_SETUP;
427 }
428 break;
429 case COMP_CMD_PAUSE:
430 trace_src("SPe");
431 /* only support pausing for running */
432 if (dev->state == COMP_STATE_RUNNING)
433 dev->state = COMP_STATE_PAUSED;
434
435 break;
436 case COMP_CMD_RELEASE:
437 trace_src("SRl");
438 dev->state = COMP_STATE_RUNNING;
439 break;
440 default:
441 trace_src("SDf");
442 break;
443 }
444
445 return 0;
446}
447
448/* copy and process stream data from source to sink buffers */
449static int src_copy(struct comp_dev *dev)
450{
451 struct comp_data *cd = comp_get_drvdata(dev);
Liam Girdwood3488cce2017-08-10 11:59:08 +0100452 struct sof_ipc_comp_config *config = COMP_GET_CONFIG(dev);
Seppo Ingalsuo6a274832017-06-07 14:17:55 +0300453 struct comp_buffer *source;
454 struct comp_buffer *sink;
455 uint32_t frames_source;
456 uint32_t frames_sink;
457 int need_source, need_sink, min_frames;
458
459 trace_comp("SRC");
460
461 /* src component needs 1 source and 1 sink buffer */
462 source = list_first_item(&dev->bsource_list, struct comp_buffer,
463 sink_list);
464 sink = list_first_item(&dev->bsink_list, struct comp_buffer,
465 source_list);
466
467 /* Check that source has enough frames available and sink enough
468 * frames free.
469 */
Liam Girdwood3488cce2017-08-10 11:59:08 +0100470 frames_source = config->frames;
471 frames_sink = config->frames;
472
Seppo Ingalsuo6a274832017-06-07 14:17:55 +0300473 min_frames = src_polyphase_get_blk_in(&cd->src[0]);
474 if (frames_source > min_frames)
Liam Girdwood3488cce2017-08-10 11:59:08 +0100475 need_source = frames_source * config->frame_size;
Seppo Ingalsuo6a274832017-06-07 14:17:55 +0300476 else {
477 frames_source = min_frames;
Liam Girdwood3488cce2017-08-10 11:59:08 +0100478 need_source = min_frames * config->frame_size;
Seppo Ingalsuo6a274832017-06-07 14:17:55 +0300479 }
480
481 min_frames = src_polyphase_get_blk_out(&cd->src[0]);
482 if (frames_sink > min_frames)
Liam Girdwood3488cce2017-08-10 11:59:08 +0100483 need_sink = frames_sink * config->frame_size;
Seppo Ingalsuo6a274832017-06-07 14:17:55 +0300484 else {
485 frames_sink = min_frames;
Liam Girdwood3488cce2017-08-10 11:59:08 +0100486 need_sink = min_frames * config->frame_size;
Seppo Ingalsuo6a274832017-06-07 14:17:55 +0300487 }
488
489 /* Run as many times as buffers allow */
490 while ((source->avail >= need_source) && (sink->free >= need_sink)) {
491 /* Run src */
492 cd->src_func(dev, source, sink, frames_source, frames_sink);
493
494 }
495
Liam Girdwood3488cce2017-08-10 11:59:08 +0100496 /* calc new free and available - offset calc by conversion func */
497 comp_update_buffer_consume(source, 0);
498 comp_update_buffer_produce(sink, 0);
499
Seppo Ingalsuo6a274832017-06-07 14:17:55 +0300500 return 0;
501}
502
503static int src_prepare(struct comp_dev *dev)
504{
Seppo Ingalsuo6a274832017-06-07 14:17:55 +0300505 dev->state = COMP_STATE_PREPARE;
506 return 0;
507}
508
509static int src_preload(struct comp_dev *dev)
510{
Liam Girdwood3488cce2017-08-10 11:59:08 +0100511 return src_copy(dev);
Seppo Ingalsuo6a274832017-06-07 14:17:55 +0300512}
513
514static int src_reset(struct comp_dev *dev)
515{
516 int i;
517 struct comp_data *cd = comp_get_drvdata(dev);
518
519 trace_src("SRe");
520
521 cd->src_func = src_2s_s32_default;
522 for (i = 0; i < PLATFORM_MAX_CHANNELS; i++)
523 src_polyphase_reset(&cd->src[i]);
524
525 dev->state = COMP_STATE_INIT;
526 return 0;
527}
528
529struct comp_driver comp_src = {
530 .type = SOF_COMP_SRC,
Seppo Ingalsuo4a006912017-06-28 19:25:51 +0300531 .ops = {
Seppo Ingalsuo6a274832017-06-07 14:17:55 +0300532 .new = src_new,
533 .free = src_free,
534 .params = src_params,
535 .cmd = src_cmd,
536 .copy = src_copy,
537 .prepare = src_prepare,
538 .reset = src_reset,
539 .preload = src_preload,
540 },
541};
542
543void sys_comp_src_init(void)
544{
545 comp_register(&comp_src);
546}