blob: 7a86a5437e5c7cee73badfd0f80b071dbf729f0a [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>
45#include "src_core.h"
46
47#ifdef MODULE_TEST
48#include <stdio.h>
49#endif
50
51#define trace_src(__e) trace_event(TRACE_CLASS_SRC, __e)
52#define tracev_src(__e) tracev_event(TRACE_CLASS_SRC, __e)
53#define trace_src_error(__e) trace_error(TRACE_CLASS_SRC, __e)
54
55/* src component private data */
56struct comp_data {
57 struct polyphase_src src[PLATFORM_MAX_CHANNELS];
58 int32_t *delay_lines;
59 int scratch_length;
60 //int32_t z[STAGE_BUF_SIZE];
61 void (*src_func)(struct comp_dev *dev,
62 struct comp_buffer *source,
63 struct comp_buffer *sink,
64 uint32_t source_frames,
65 uint32_t sink_frames);
66};
67
68/* Common mute function for 2s and 1s SRC. This preserves the same
69 * buffer consume and produce pattern as normal operation.
70 */
71static void src_muted_s32(struct comp_buffer *source, struct comp_buffer *sink,
72 int blk_in, int blk_out, int nch, int source_frames)
73{
74
75 int i;
76 int32_t *src = (int32_t *) source->r_ptr;
77 int32_t *dest = (int32_t *) sink->w_ptr;
78 int32_t *end = (int32_t *) sink->end_addr;
79 int n_read = 0;
80 int n_max;
81 int n;
82 int n_written = 0;
83
84 for (i = 0; i < source_frames - blk_in + 1; i += blk_in) {
85 n_max = end - dest;
86 n = nch*blk_out;
87 if (n < n_max) {
88 bzero(dest, n * sizeof(int32_t));
89 dest += n;
90 } else {
91 /* Also case n_max == n is done here */
92 bzero(dest, n_max * sizeof(int32_t));
93 dest = (int32_t *) sink->addr;
94 bzero(dest, (n - n_max) * sizeof(int32_t));
95 dest += n - n_max;
96 }
97 n_read += nch*blk_in;
98 n_written += nch*blk_out;
99 }
100 source->r_ptr = src + n_read;
101 sink->w_ptr = dest;
102 comp_wrap_source_r_ptr_circular(source);
103 comp_wrap_sink_w_ptr_circular(sink);
104 comp_update_source_free_avail(source, n_read);
105 comp_update_sink_free_avail(sink, n_written);
106}
107
108/* Fallback function to just output muted samples and advance
109 * pointers. Note that a buffer that is not having integer number of
110 * frames in a period will drift since there is no similar blk in/out
111 * check as for SRC.
112 */
113static void fallback_s32(struct comp_dev *dev,
114 struct comp_buffer *source,
115 struct comp_buffer *sink,
116 uint32_t source_frames,
117 uint32_t sink_frames)
118{
119
120 struct comp_data *cd = comp_get_drvdata(dev);
121 //int32_t *src = (int32_t*) source->r_ptr;
122 //int32_t *dest = (int32_t*) sink->w_ptr;
123 int nch = sink->params.pcm->channels;
124 int blk_in = cd->src[0].blk_in;
125 int blk_out = cd->src[0].blk_out;
126
127 src_muted_s32(source, sink, blk_in, blk_out, nch, source_frames);
128
129}
130
131/* Normal 2 stage SRC */
132static void src_2s_s32_default(struct comp_dev *dev,
133 struct comp_buffer *source, struct comp_buffer *sink,
134 uint32_t source_frames, uint32_t sink_frames)
135{
136 int i, j;
137 struct polyphase_src *s;
138 struct comp_data *cd = comp_get_drvdata(dev);
139 int blk_in = cd->src[0].blk_in;
140 int blk_out = cd->src[0].blk_out;
141 int n_times1 = cd->src[0].stage1_times;
142 int n_times2 = cd->src[0].stage2_times;
143 int nch = sink->params.pcm->channels;
144 int32_t *dest = (int32_t *) sink->w_ptr;
145 int32_t *src = (int32_t *) source->r_ptr;
146 struct src_stage_prm s1, s2;
147 int n_read = 0;
148 int n_written = 0;
149
150 if (cd->src[0].mute) {
151 src_muted_s32(source, sink, blk_in, blk_out, nch, source_frames);
152 return;
153 }
154
155 s1.times = n_times1;
156 s1.x_end_addr = source->end_addr;
157 s1.x_size = source->alloc_size;
158 s1.x_inc = nch;
159 s1.y_end_addr = &cd->delay_lines[cd->scratch_length];
160 s1.y_size = STAGE_BUF_SIZE * sizeof(int32_t);
161 s1.y_inc = 1;
162
163 s2.times = n_times2;
164 s2.x_end_addr = &cd->delay_lines[cd->scratch_length];
165 s2.x_size = STAGE_BUF_SIZE * sizeof(int32_t);
166 s2.x_inc = 1;
167 s2.y_end_addr = sink->end_addr;
168 s2.y_size = sink->alloc_size;
169 s2.y_inc = nch;
170
171 for (j = 0; j < nch; j++) {
172 s = &cd->src[j]; /* Point to src[] for this channel */
173 s1.x_rptr = src++;
174 s2.y_wptr = dest++;
175 s1.state = &s->state1;
176 s1.stage = s->stage1;
177 s2.state = &s->state2;
178 s2.stage = s->stage2;
179
180 for (i = 0; i < source_frames - blk_in + 1; i += blk_in) {
181 /* Reset output to buffer start, read interleaved */
182 s1.y_wptr = cd->delay_lines;
183 src_polyphase_stage_cir(&s1);
184 s2.x_rptr = cd->delay_lines;
185 src_polyphase_stage_cir(&s2);
186
187 n_read += blk_in;
188 n_written += blk_out;
189 }
190 }
191 source->r_ptr = s1.x_rptr - nch + 1;
192 sink->w_ptr = s2.y_wptr - nch + 1;
193 comp_wrap_source_r_ptr_circular(source);
194 comp_wrap_sink_w_ptr_circular(sink);
195 comp_update_source_free_avail(source, n_read);
196 comp_update_sink_free_avail(sink, n_written);
197}
198
199/* 1 stage SRC for simple conversions */
200static void src_1s_s32_default(struct comp_dev *dev,
201 struct comp_buffer *source, struct comp_buffer *sink,
202 uint32_t source_frames, uint32_t sink_frames)
203{
204 int i, j;
205 //int32_t *xp, *yp;
206 struct polyphase_src *s;
207
208 struct comp_data *cd = comp_get_drvdata(dev);
209 int blk_in = cd->src[0].blk_in;
210 int blk_out = cd->src[0].blk_out;
211 int n_times = cd->src[0].stage1_times;
212 int nch = sink->params.pcm->channels;
213 int32_t *dest = (int32_t*) sink->w_ptr;
214 int32_t *src = (int32_t*) source->r_ptr;
215 int n_read = 0;
216 int n_written = 0;
217 struct src_stage_prm s1;
218
219 if (cd->src[0].mute) {
220 src_muted_s32(source, sink, blk_in, blk_out, nch, source_frames);
221 return;
222 }
223
224 s1.times = n_times;
225 s1.x_end_addr = source->end_addr;
226 s1.x_size = source->alloc_size;
227 s1.x_inc = nch;
228 s1.y_end_addr = sink->end_addr;
229 s1.y_size = sink->alloc_size;
230 s1.y_inc = nch;
231
232 for (j = 0; j < nch; j++) {
233 s = &cd->src[j]; /* Point to src for this channel */
234 s1.x_rptr = src++;
235 s1.y_wptr = dest++;
236 s1.state = &s->state1;
237 s1.stage = s->stage1;
238
239 for (i = 0; i + blk_in - 1 < source_frames; i += blk_in) {
240 src_polyphase_stage_cir(&s1);
241
242 n_read += blk_in;
243 n_written += blk_out;
244 }
245
246 }
247 source->r_ptr = s1.x_rptr - nch + 1;
248 sink->w_ptr = s1.y_wptr - nch + 1;
249
250 comp_wrap_source_r_ptr_circular(source);
251 comp_wrap_sink_w_ptr_circular(sink);
252 comp_update_source_free_avail(source, n_read);
253 comp_update_sink_free_avail(sink, n_written);
254}
255
256static struct comp_dev *src_new(struct sof_ipc_comp *comp)
257{
258 int i;
259 struct comp_dev *dev;
260 struct comp_data *cd;
261
262 trace_src("SNw");
263 dev = rmalloc(RZONE_RUNTIME, RFLAGS_NONE, sizeof(*dev));
264 if (dev == NULL)
265 return NULL;
266
267 memcpy(&dev->comp, comp, sizeof(struct sof_ipc_comp_src));
268
269 cd = rmalloc(RZONE_RUNTIME, RFLAGS_NONE, sizeof(*cd));
270 if (cd == NULL) {
271#if SRC_SOF == 1
272 rfree(dev);
273#else
274 rfree(dev);
275#endif
276 return NULL;
277 }
278
279 comp_set_drvdata(dev, cd);
280#if SRC_SOF == 0
281
282#endif
283
284 cd->delay_lines = NULL;
285 cd->src_func = src_2s_s32_default;
286 for (i = 0; i < PLATFORM_MAX_CHANNELS; i++)
287 src_polyphase_reset(&cd->src[i]);
288
289 return dev;
290}
291
292static void src_free(struct comp_dev *dev)
293{
294 struct comp_data *cd = comp_get_drvdata(dev);
295
296 trace_src("SFr");
297
298#if SRC_SOF == 1
299 /* Free dynamically reserved buffers for SRC algorithm */
300 if (cd->delay_lines != NULL)
301 rfree(cd->delay_lines);
302
303 rfree(cd);
304 rfree(dev);
305#else
306 /* Free dynamically reserved buffers for SRC algorithm */
307 if (cd->delay_lines != NULL)
308 rfree(cd->delay_lines);
309
310 rfree(cd);
311 rfree(dev);
312#endif
313}
314
315/* set component audio stream parameters */
316static int src_params(struct comp_dev *dev, struct stream_params *params)
317{
318 int i;
319 struct comp_buffer *source, *sink;
320 struct src_alloc need;
321 size_t delay_lines_size;
322 int32_t *buffer_start;
323 int n = 0;
324 struct comp_data *cd = comp_get_drvdata(dev);
325
326 trace_src("SPa");
327
328 /* SRC supports only S32_LE PCM format */
329 if ((params->type != STREAM_TYPE_PCM)
330 || (params->pcm->frame_fmt != SOF_IPC_FRAME_S32_LE))
331 return -EINVAL;
332
333 /* No data transformation */
334 comp_set_sink_params(dev, params);
335
336 /* Allocate needed memory for delay lines */
337 source = list_first_item(&dev->bsource_list, struct comp_buffer,
338 sink_list);
339 sink = list_first_item(&dev->bsink_list, struct comp_buffer,
340 source_list);
341 src_buffer_lengths(&need, source->params.pcm->rate,
342 sink->params.pcm->rate, source->params.pcm->channels);
343 delay_lines_size = sizeof(int32_t) * need.total;
344 if (cd->delay_lines != NULL)
345 rfree(cd->delay_lines);
346
347 cd->delay_lines = rmalloc(RZONE_RUNTIME, RFLAGS_NONE, delay_lines_size);
348 if (cd->delay_lines == NULL)
349 return -EINVAL;
350
351 /* Clear all delay lines here */
352 memset(cd->delay_lines, 0, delay_lines_size);
353 cd->scratch_length = need.scratch;
354 buffer_start = cd->delay_lines + need.scratch;
355
356 /* Initize SRC for actual sample rate */
357 for (i = 0; i < source->params.pcm->channels; i++) {
358 n = src_polyphase_init(&cd->src[i], source->params.pcm->rate,
359 sink->params.pcm->rate, buffer_start);
360 buffer_start += need.single_src;
361 }
362
363 switch (n) {
364 case 1:
365 cd->src_func = src_1s_s32_default; /* Simpler 1 stage SRC */
366 break;
367 case 2:
368 cd->src_func = src_2s_s32_default; /* Default 2 stage SRC */
369 break;
370 default:
371 /* This is possibly due to missing coefficients for
372 * requested rates combination. Sink audio will be
373 * muted if copy() is run.
374 */
375 trace_src("SFa");
376 cd->src_func = fallback_s32;
377 return(-EINVAL);
378 break;
379 }
380
381 /* Check that src blk_in and blk_out are less than params.period_frames.
382 * Return an error if the period is too short.
383 */
384 if (src_polyphase_get_blk_in(&cd->src[0]) > source->params.pcm->period_count)
385 return(-EINVAL);
386
387 if (src_polyphase_get_blk_out(&cd->src[0]) > sink->params.pcm->period_count)
388 return(-EINVAL);
389
390
391 return 0;
392}
393
394/* used to pass standard and bespoke commands (with data) to component */
395static int src_cmd(struct comp_dev *dev, int cmd, void *data)
396{
397 trace_src("SCm");
398 struct comp_data *cd = comp_get_drvdata(dev);
399 struct sof_ipc_comp_src *cv;
400 int i;
401
402 switch (cmd) {
403 case COMP_CMD_SRC:
404 trace_src("SMa");
405 cv = (struct sof_ipc_comp_src *) data;
406 cv->in_mask = src_input_rates();
407 cv->out_mask = src_output_rates();
408 break;
409 case COMP_CMD_MUTE:
410 trace_src("SMu");
411 for (i = 0; i < PLATFORM_MAX_CHANNELS; i++)
412 src_polyphase_mute(&cd->src[i]);
413
414 break;
415 case COMP_CMD_UNMUTE:
416 trace_src("SUm");
417 for (i = 0; i < PLATFORM_MAX_CHANNELS; i++)
418 src_polyphase_unmute(&cd->src[i]);
419
420 break;
421 case COMP_CMD_START:
422 trace_src("SSt");
423 dev->state = COMP_STATE_RUNNING;
424 break;
425 case COMP_CMD_STOP:
426 trace_src("SSp");
427 if (dev->state == COMP_STATE_RUNNING ||
428 dev->state == COMP_STATE_DRAINING ||
429 dev->state == COMP_STATE_PAUSED) {
430 comp_buffer_reset(dev);
431 dev->state = COMP_STATE_SETUP;
432 }
433 break;
434 case COMP_CMD_PAUSE:
435 trace_src("SPe");
436 /* only support pausing for running */
437 if (dev->state == COMP_STATE_RUNNING)
438 dev->state = COMP_STATE_PAUSED;
439
440 break;
441 case COMP_CMD_RELEASE:
442 trace_src("SRl");
443 dev->state = COMP_STATE_RUNNING;
444 break;
445 default:
446 trace_src("SDf");
447 break;
448 }
449
450 return 0;
451}
452
453/* copy and process stream data from source to sink buffers */
454static int src_copy(struct comp_dev *dev)
455{
456 struct comp_data *cd = comp_get_drvdata(dev);
457 struct comp_buffer *source;
458 struct comp_buffer *sink;
459 uint32_t frames_source;
460 uint32_t frames_sink;
461 int need_source, need_sink, min_frames;
462
463 trace_comp("SRC");
464
465 /* src component needs 1 source and 1 sink buffer */
466 source = list_first_item(&dev->bsource_list, struct comp_buffer,
467 sink_list);
468 sink = list_first_item(&dev->bsink_list, struct comp_buffer,
469 source_list);
470
471 /* Check that source has enough frames available and sink enough
472 * frames free.
473 */
474 frames_source = source->params.pcm->period_count;
475 frames_sink = sink->params.pcm->period_count;
476 min_frames = src_polyphase_get_blk_in(&cd->src[0]);
477 if (frames_source > min_frames)
478 need_source = frames_source * source->params.pcm->frame_size;
479 else {
480 frames_source = min_frames;
481 need_source = min_frames * source->params.pcm->frame_size;
482 }
483
484 min_frames = src_polyphase_get_blk_out(&cd->src[0]);
485 if (frames_sink > min_frames)
486 need_sink = frames_sink * sink->params.pcm->frame_size;
487 else {
488 frames_sink = min_frames;
489 need_sink = min_frames * sink->params.pcm->frame_size;
490 }
491
492 /* Run as many times as buffers allow */
493 while ((source->avail >= need_source) && (sink->free >= need_sink)) {
494 /* Run src */
495 cd->src_func(dev, source, sink, frames_source, frames_sink);
496
497 }
498
499 return 0;
500}
501
502static int src_prepare(struct comp_dev *dev)
503{
504 // struct comp_data *cd = comp_get_drvdata(dev);
505 struct comp_buffer *source;
506 struct comp_buffer *sink;
507 // int i;
508
509 trace_src("SPp");
510
511#if 1
512 source = list_first_item(&dev->bsource_list, struct comp_buffer,
513 sink_list);
514 sink = list_first_item(&dev->bsink_list, struct comp_buffer,
515 source_list);
516
517 trace_value(source->params.pcm->channels);
518 trace_value(source->params.pcm->rate);
519 trace_value(sink->params.pcm->rate);
520#endif
521
522 //dev->preload = PLAT_INT_PERIODS;
523 dev->state = COMP_STATE_PREPARE;
524 return 0;
525}
526
527static int src_preload(struct comp_dev *dev)
528{
529 //int i;
530 trace_src("SPl");
531
532
533 //for (i = 0; i < dev->preload; i++)
534 // src_copy(dev);
535
536 return 0;
537}
538
539static int src_reset(struct comp_dev *dev)
540{
541 int i;
542 struct comp_data *cd = comp_get_drvdata(dev);
543
544 trace_src("SRe");
545
546 cd->src_func = src_2s_s32_default;
547 for (i = 0; i < PLATFORM_MAX_CHANNELS; i++)
548 src_polyphase_reset(&cd->src[i]);
549
550 dev->state = COMP_STATE_INIT;
551 return 0;
552}
553
554struct comp_driver comp_src = {
555 .type = SOF_COMP_SRC,
556 .ops =
557 {
558 .new = src_new,
559 .free = src_free,
560 .params = src_params,
561 .cmd = src_cmd,
562 .copy = src_copy,
563 .prepare = src_prepare,
564 .reset = src_reset,
565 .preload = src_preload,
566 },
567};
568
569void sys_comp_src_init(void)
570{
571 comp_register(&comp_src);
572}