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