1 // SPDX-License-Identifier: BSD-3-Clause
2 //
3 // Copyright(c) 2018 Intel Corporation. All rights reserved.
4
5 /* file component for reading/writing pcm samples to/from a file */
6
7 #include <stdio.h>
8 #include <stdint.h>
9 #include <stddef.h>
10 #include <stdlib.h>
11 #include <errno.h>
12 #include <inttypes.h>
13 #include <sof/sof.h>
14 #include <sof/list.h>
15 #include <sof/audio/stream.h>
16 #include <sof/audio/ipc-config.h>
17 #include <sof/lib/clk.h>
18 #include <sof/ipc/driver.h>
19 #include <sof/audio/component.h>
20 #include <sof/audio/format.h>
21 #include <sof/audio/pipeline.h>
22 #include <ipc/stream.h>
23 #include "testbench/common_test.h"
24 #include "testbench/file.h"
25
26 /* bfc7488c-75aa-4ce8-9bde-d8da08a698c2 */
27 DECLARE_SOF_UUID("file", file_uuid, 0xbfc7488c, 0x75aa, 0x4ce8,
28 0x9d, 0xbe, 0xd8, 0xda, 0x08, 0xa6, 0x98, 0xc2);
29 DECLARE_TR_CTX(file_tr, SOF_UUID(file_uuid), LOG_LEVEL_INFO);
30
31 static const struct comp_driver comp_file_dai;
32 static const struct comp_driver comp_file_host;
33
buffer_check_wrap_32(int32_t ** ptr,int32_t * end,size_t size)34 static inline void buffer_check_wrap_32(int32_t **ptr, int32_t *end,
35 size_t size)
36 {
37 if (*ptr >= end)
38 *ptr = (int32_t *)((size_t)*ptr - size);
39 }
40
buffer_check_wrap_16(int16_t ** ptr,int16_t * end,size_t size)41 static inline void buffer_check_wrap_16(int16_t **ptr, int16_t *end,
42 size_t size)
43 {
44 if (*ptr >= end)
45 *ptr = (int16_t *)((size_t)*ptr - size);
46 }
47
48 /*
49 * Read 32-bit samples from file
50 * currently only supports txt files
51 */
read_samples_32(struct comp_dev * dev,const struct audio_stream * sink,int n,int fmt,int nch)52 static int read_samples_32(struct comp_dev *dev,
53 const struct audio_stream *sink,
54 int n, int fmt, int nch)
55 {
56 struct file_comp_data *cd = comp_get_drvdata(dev);
57 int32_t *dest = (int32_t *)sink->w_ptr;
58 int32_t sample;
59 int n_wrap;
60 int n_min;
61 int i;
62 int n_samples = 0;
63 int ret = 0;
64
65 while (n > 0) {
66 n_wrap = (int32_t *)sink->end_addr - dest;
67
68 /* check for buffer wrap and copy to the end of the buffer */
69 n_min = (n < n_wrap) ? n : n_wrap;
70 while (n_min > 0) {
71 n -= nch;
72 n_min -= nch;
73
74 /* copy sample per channel */
75 for (i = 0; i < nch; i++) {
76 /* read sample from file */
77 switch (cd->fs.f_format) {
78 /* text input file */
79 case FILE_TEXT:
80 if (fmt == SOF_IPC_FRAME_S32_LE)
81 ret = fscanf(cd->fs.rfh, "%d",
82 dest);
83
84 /* mask bits if 24-bit samples */
85 if (fmt == SOF_IPC_FRAME_S24_4LE) {
86 ret = fscanf(cd->fs.rfh, "%d",
87 &sample);
88 *dest = sample & 0x00ffffff;
89 }
90 /* quit if eof is reached */
91 if (ret == EOF) {
92 cd->fs.reached_eof = 1;
93 goto quit;
94 }
95 break;
96
97 /* raw input file */
98 default:
99 if (fmt == SOF_IPC_FRAME_S32_LE)
100 ret = fread(dest,
101 sizeof(int32_t),
102 1, cd->fs.rfh);
103
104 /* mask bits if 24-bit samples */
105 if (fmt == SOF_IPC_FRAME_S24_4LE) {
106 ret = fread(&sample,
107 sizeof(int32_t),
108 1, cd->fs.rfh);
109 *dest = sample & 0x00ffffff;
110 }
111 /* quit if eof is reached */
112 if (ret != 1) {
113 cd->fs.reached_eof = 1;
114 goto quit;
115 }
116 break;
117 }
118 dest++;
119 n_samples++;
120 }
121 }
122 /* check for buffer wrap and update pointer */
123 buffer_check_wrap_32(&dest, sink->end_addr,
124 sink->size);
125 }
126 quit:
127 return n_samples;
128 }
129
130 /*
131 * Read 16-bit samples from file
132 * currently only supports txt files
133 */
read_samples_16(struct comp_dev * dev,const struct audio_stream * sink,int n,int nch)134 static int read_samples_16(struct comp_dev *dev,
135 const struct audio_stream *sink,
136 int n, int nch)
137 {
138 struct file_comp_data *cd = comp_get_drvdata(dev);
139 int16_t *dest = (int16_t *)sink->w_ptr;
140 int i, n_wrap, n_min, ret;
141 int n_samples = 0;
142
143 /* copy samples */
144 while (n > 0) {
145 n_wrap = (int16_t *)sink->end_addr - dest;
146
147 /* check for buffer wrap and copy to the end of the buffer */
148 n_min = (n < n_wrap) ? n : n_wrap;
149 while (n_min > 0) {
150 n -= nch;
151 n_min -= nch;
152
153 /* copy sample per channel */
154 for (i = 0; i < nch; i++) {
155 switch (cd->fs.f_format) {
156 /* text input file */
157 case FILE_TEXT:
158 ret = fscanf(cd->fs.rfh, "%hd", dest);
159 if (ret == EOF) {
160 cd->fs.reached_eof = 1;
161 goto quit;
162 }
163 break;
164
165 /* rw pcm input file */
166 default:
167 ret = fread(dest, sizeof(int16_t), 1,
168 cd->fs.rfh);
169 if (ret != 1) {
170 cd->fs.reached_eof = 1;
171 goto quit;
172 }
173 break;
174 }
175
176 dest++;
177 n_samples++;
178 }
179 }
180 /* check for buffer wrap and update pointer */
181 buffer_check_wrap_16(&dest, sink->end_addr,
182 sink->size);
183 }
184
185 quit:
186 return n_samples;
187 }
188
189 /*
190 * Write 16-bit samples from file
191 * currently only supports txt files
192 */
write_samples_16(struct comp_dev * dev,struct audio_stream * source,int n,int nch)193 static int write_samples_16(struct comp_dev *dev, struct audio_stream *source,
194 int n, int nch)
195 {
196 struct file_comp_data *cd = comp_get_drvdata(dev);
197 int16_t *src = (int16_t *)source->r_ptr;
198 int i, n_wrap, n_min, ret;
199 int n_samples = 0;
200
201 /* copy samples */
202 while (n > 0) {
203 n_wrap = (int16_t *)source->end_addr - src;
204
205 /* check for buffer wrap and copy to the end of the buffer */
206 n_min = (n < n_wrap) ? n : n_wrap;
207 while (n_min > 0) {
208 n -= nch;
209 n_min -= nch;
210
211 /* copy sample per channel */
212 for (i = 0; i < nch; i++) {
213 switch (cd->fs.f_format) {
214 /* text output file */
215 case FILE_TEXT:
216 ret = fprintf(cd->fs.wfh,
217 "%d\n", *src);
218 if (ret < 0)
219 goto quit;
220 break;
221
222 /* raw pcm output file */
223 default:
224 ret = fwrite(src,
225 sizeof(int16_t),
226 1, cd->fs.wfh);
227 if (ret != 1)
228 goto quit;
229 break;
230 }
231
232 src++;
233 n_samples++;
234 }
235 }
236 /* check for buffer wrap and update pointer */
237 buffer_check_wrap_16(&src, source->end_addr,
238 source->size);
239 }
240 quit:
241 return n_samples;
242 }
243
244 /*
245 * Write 32-bit samples from file
246 * currently only supports txt files
247 */
write_samples_32(struct comp_dev * dev,struct audio_stream * source,int n,int fmt,int nch)248 static int write_samples_32(struct comp_dev *dev, struct audio_stream *source,
249 int n, int fmt, int nch)
250 {
251 struct file_comp_data *cd = comp_get_drvdata(dev);
252 int32_t *src = (int32_t *)source->r_ptr;
253 int i, n_wrap, n_min, ret;
254 int n_samples = 0;
255 int32_t sample;
256
257 /* copy samples */
258 while (n > 0) {
259 n_wrap = (int32_t *)source->end_addr - src;
260
261 /* check for buffer wrap and copy to the end of the buffer */
262 n_min = (n < n_wrap) ? n : n_wrap;
263 while (n_min > 0) {
264 n -= nch;
265 n_min -= nch;
266
267 /* copy sample per channel */
268 for (i = 0; i < nch; i++) {
269 switch (cd->fs.f_format) {
270 /* text output file */
271 case FILE_TEXT:
272 if (fmt == SOF_IPC_FRAME_S32_LE)
273 ret = fprintf(cd->fs.wfh,
274 "%d\n", *src);
275 if (fmt == SOF_IPC_FRAME_S24_4LE) {
276 sample = *src << 8;
277 ret = fprintf(cd->fs.wfh,
278 "%d\n",
279 sample >> 8);
280 }
281 if (ret < 0)
282 goto quit;
283 break;
284
285 /* raw pcm output file */
286 default:
287 if (fmt == SOF_IPC_FRAME_S32_LE)
288 ret = fwrite(src,
289 sizeof(int32_t),
290 1, cd->fs.wfh);
291 if (fmt == SOF_IPC_FRAME_S24_4LE) {
292 sample = *src << 8;
293 sample >>= 8;
294 ret = fwrite(&sample,
295 sizeof(int32_t),
296 1, cd->fs.wfh);
297 }
298 if (ret != 1)
299 goto quit;
300 break;
301 }
302
303 /* increment read pointer */
304 src++;
305
306 /* increment number of samples written */
307 n_samples++;
308 }
309 }
310 /* check for buffer wrap and update pointer */
311 buffer_check_wrap_32(&src, source->end_addr,
312 source->size);
313 }
314 quit:
315 return n_samples;
316 }
317
318 /* function for processing 32-bit samples */
file_s32_default(struct comp_dev * dev,struct audio_stream * sink,struct audio_stream * source,uint32_t frames)319 static int file_s32_default(struct comp_dev *dev, struct audio_stream *sink,
320 struct audio_stream *source, uint32_t frames)
321 {
322 struct file_comp_data *cd = comp_get_drvdata(dev);
323 int nch;
324 int n_samples = 0;
325
326 switch (cd->fs.mode) {
327 case FILE_READ:
328 /* read samples */
329 nch = sink->channels;
330 n_samples = read_samples_32(dev, sink, frames * nch,
331 SOF_IPC_FRAME_S32_LE, nch);
332 break;
333 case FILE_WRITE:
334 /* write samples */
335 nch = source->channels;
336 n_samples = write_samples_32(dev, source, frames * nch,
337 SOF_IPC_FRAME_S32_LE, nch);
338 break;
339 default:
340 /* TODO: duplex mode */
341 break;
342 }
343
344 cd->fs.n += n_samples;
345 return n_samples;
346 }
347
348 /* function for processing 16-bit samples */
file_s16(struct comp_dev * dev,struct audio_stream * sink,struct audio_stream * source,uint32_t frames)349 static int file_s16(struct comp_dev *dev, struct audio_stream *sink,
350 struct audio_stream *source, uint32_t frames)
351 {
352 struct file_comp_data *cd = comp_get_drvdata(dev);
353 int nch;
354 int n_samples = 0;
355
356 switch (cd->fs.mode) {
357 case FILE_READ:
358 /* read samples */
359 nch = sink->channels;
360 n_samples = read_samples_16(dev, sink, frames * nch, nch);
361 break;
362 case FILE_WRITE:
363 /* write samples */
364 nch = source->channels;
365 n_samples = write_samples_16(dev, source, frames * nch, nch);
366 break;
367 default:
368 /* TODO: duplex mode */
369 break;
370 }
371
372 cd->fs.n += n_samples;
373 return n_samples;
374 }
375
376 /* function for processing 24-bit samples */
file_s24(struct comp_dev * dev,struct audio_stream * sink,struct audio_stream * source,uint32_t frames)377 static int file_s24(struct comp_dev *dev, struct audio_stream *sink,
378 struct audio_stream *source, uint32_t frames)
379 {
380 struct file_comp_data *cd = comp_get_drvdata(dev);
381 int nch;
382 int n_samples = 0;
383
384 switch (cd->fs.mode) {
385 case FILE_READ:
386 /* read samples */
387 nch = sink->channels;
388 n_samples = read_samples_32(dev, sink, frames * nch,
389 SOF_IPC_FRAME_S24_4LE, nch);
390 break;
391 case FILE_WRITE:
392 /* write samples */
393 nch = source->channels;
394 n_samples = write_samples_32(dev, source, frames * nch,
395 SOF_IPC_FRAME_S24_4LE, nch);
396 break;
397 default:
398 /* TODO: duplex mode */
399 break;
400 }
401
402 cd->fs.n += n_samples;
403 return n_samples;
404 }
405
get_file_format(char * filename)406 static enum file_format get_file_format(char *filename)
407 {
408 char *ext = strrchr(filename, '.');
409
410 if (!ext)
411 return FILE_RAW;
412
413 if (!strcmp(ext, ".txt"))
414 return FILE_TEXT;
415
416 return FILE_RAW;
417 }
418
file_new(const struct comp_driver * drv,struct comp_ipc_config * config,void * spec)419 static struct comp_dev *file_new(const struct comp_driver *drv,
420 struct comp_ipc_config *config,
421 void *spec)
422 {
423 struct comp_dev *dev;
424 struct ipc_comp_file *ipc_file = spec;
425 struct file_comp_data *cd;
426
427 debug_print("file_new()\n");
428
429
430 dev = comp_alloc(drv, sizeof(*dev));
431 if (!dev)
432 return NULL;
433 dev->ipc_config = *config;
434
435 /* allocate memory for file comp data */
436 cd = rzalloc(SOF_MEM_ZONE_RUNTIME, 0, SOF_MEM_CAPS_RAM, sizeof(*cd));
437 if (!cd) {
438 free(dev);
439 return NULL;
440 }
441
442 comp_set_drvdata(dev, cd);
443
444 /* default function for processing samples */
445 cd->file_func = file_s32_default;
446
447 /* get filename from IPC and open file */
448 cd->fs.fn = strdup(ipc_file->fn);
449
450 /* set file format */
451 cd->fs.f_format = get_file_format(cd->fs.fn);
452
453 /* set file comp mode */
454 cd->fs.mode = ipc_file->mode;
455
456 cd->rate = ipc_file->rate;
457 cd->channels = ipc_file->channels;
458 cd->frame_fmt = ipc_file->frame_fmt;
459
460 /* open file handle(s) depending on mode */
461 switch (cd->fs.mode) {
462 case FILE_READ:
463 cd->fs.rfh = fopen(cd->fs.fn, "r");
464 if (!cd->fs.rfh) {
465 fprintf(stderr, "error: opening file %s for reading - %s\n",
466 cd->fs.fn, strerror(errno));
467 free(cd);
468 free(dev);
469 return NULL;
470 }
471 break;
472 case FILE_WRITE:
473 cd->fs.wfh = fopen(cd->fs.fn, "w+");
474 if (!cd->fs.wfh) {
475 fprintf(stderr, "error: opening file %s for writing - %s\n",
476 cd->fs.fn, strerror(errno));
477 free(cd);
478 free(dev);
479 return NULL;
480 }
481 break;
482 default:
483 /* TODO: duplex mode */
484 break;
485 }
486
487 cd->fs.reached_eof = 0;
488 cd->fs.n = 0;
489
490 dev->state = COMP_STATE_READY;
491
492 return dev;
493 }
494
file_free(struct comp_dev * dev)495 static void file_free(struct comp_dev *dev)
496 {
497 struct file_comp_data *cd = comp_get_drvdata(dev);
498
499 comp_dbg(dev, "file_free()");
500
501 if (cd->fs.mode == FILE_READ)
502 fclose(cd->fs.rfh);
503 else
504 fclose(cd->fs.wfh);
505
506 free(cd->fs.fn);
507 free(cd);
508 free(dev);
509 }
510
file_verify_params(struct comp_dev * dev,struct sof_ipc_stream_params * params)511 static int file_verify_params(struct comp_dev *dev,
512 struct sof_ipc_stream_params *params)
513 {
514 int ret;
515
516 comp_dbg(dev, "file_verify_params()");
517
518 ret = comp_verify_params(dev, 0, params);
519 if (ret < 0) {
520 comp_err(dev, "file_verify_params() error: comp_verify_params() failed.");
521 return ret;
522 }
523
524 return 0;
525 }
526
527 /**
528 * \brief Sets file component audio stream parameters.
529 * \param[in,out] dev Volume base component device.
530 * \param[in] params Audio (PCM) stream parameters (ignored for this component)
531 * \return Error code.
532 *
533 * All done in prepare() since we need to know source and sink component params.
534 */
file_params(struct comp_dev * dev,struct sof_ipc_stream_params * params)535 static int file_params(struct comp_dev *dev,
536 struct sof_ipc_stream_params *params)
537 {
538 int err;
539
540 comp_info(dev, "file_params()");
541
542 err = file_verify_params(dev, params);
543 if (err < 0) {
544 comp_err(dev, "file_params(): pcm params verification failed.");
545 return -EINVAL;
546 }
547
548 return 0;
549 }
550
fr_cmd(struct comp_dev * dev,struct sof_ipc_ctrl_data * cdata)551 static int fr_cmd(struct comp_dev *dev, struct sof_ipc_ctrl_data *cdata)
552 {
553 return -EINVAL;
554 }
555
file_trigger(struct comp_dev * dev,int cmd)556 static int file_trigger(struct comp_dev *dev, int cmd)
557 {
558 comp_info(dev, "file_trigger()");
559 return comp_set_state(dev, cmd);
560 }
561
562 /* used to pass standard and bespoke commands (with data) to component */
file_cmd(struct comp_dev * dev,int cmd,void * data,int max_data_size)563 static int file_cmd(struct comp_dev *dev, int cmd, void *data,
564 int max_data_size)
565 {
566 struct sof_ipc_ctrl_data *cdata = ASSUME_ALIGNED(data, 4);
567 int ret = 0;
568
569 comp_info(dev, "file_cmd()");
570 switch (cmd) {
571 case COMP_CMD_SET_DATA:
572 ret = fr_cmd(dev, cdata);
573 break;
574 default:
575 break;
576 }
577
578 return ret;
579 }
580
581 /*
582 * copy and process stream samples
583 * returns the number of bytes copied
584 */
file_copy(struct comp_dev * dev)585 static int file_copy(struct comp_dev *dev)
586 {
587 struct comp_buffer *buffer;
588 struct file_comp_data *cd = comp_get_drvdata(dev);
589 int snk_frames;
590 int src_frames;
591 int bytes = cd->sample_container_bytes;
592 int ret = 0;
593
594 switch (cd->fs.mode) {
595 case FILE_READ:
596 /* file component sink buffer */
597 buffer = list_first_item(&dev->bsink_list, struct comp_buffer,
598 source_list);
599
600 /* test sink has enough free frames */
601 snk_frames = audio_stream_get_free_frames(&buffer->stream);
602 if (snk_frames > 0 && !cd->fs.reached_eof) {
603 /* read PCM samples from file */
604 ret = cd->file_func(dev, &buffer->stream, NULL,
605 snk_frames);
606
607 /* update sink buffer pointers */
608 if (ret > 0)
609 comp_update_buffer_produce(buffer,
610 ret * bytes);
611 }
612 break;
613 case FILE_WRITE:
614 /* file component source buffer */
615 buffer = list_first_item(&dev->bsource_list,
616 struct comp_buffer, sink_list);
617
618 /* test source has enough free frames */
619 src_frames = audio_stream_get_avail_frames(&buffer->stream);
620 if (src_frames > 0) {
621 /* write PCM samples into file */
622 ret = cd->file_func(dev, NULL, &buffer->stream,
623 src_frames);
624
625 /* update source buffer pointers */
626 if (ret > 0)
627 comp_update_buffer_consume(buffer,
628 ret * bytes);
629 }
630 break;
631 default:
632 /* TODO: duplex mode */
633 break;
634 }
635
636 return ret;
637 }
638
file_prepare(struct comp_dev * dev)639 static int file_prepare(struct comp_dev *dev)
640 {
641 struct comp_buffer *buffer = NULL;
642 struct file_comp_data *cd = comp_get_drvdata(dev);
643 struct audio_stream *stream;
644 int periods;
645 int ret = 0;
646
647 comp_info(dev, "file_prepare()");
648
649 ret = comp_set_state(dev, COMP_TRIGGER_PREPARE);
650 if (ret < 0)
651 return ret;
652
653 if (ret == COMP_STATUS_STATE_ALREADY_SET)
654 return PPL_STATUS_PATH_STOP;
655
656 /* file component source or sink buffer */
657 if (cd->fs.mode == FILE_WRITE) {
658 stream = &list_first_item(&dev->bsource_list,
659 struct comp_buffer, sink_list)->stream;
660 } else {
661 stream = &list_first_item(&dev->bsink_list, struct comp_buffer,
662 source_list)->stream;
663 }
664
665 if (stream->frame_fmt == SOF_IPC_FRAME_S16_LE)
666 cd->sample_container_bytes = 2;
667 else
668 cd->sample_container_bytes = 4;
669
670 /* calculate period size based on config */
671 cd->period_bytes = dev->frames * cd->sample_container_bytes *
672 stream->channels;
673
674 /* file component sink/source buffer period count */
675 switch (cd->fs.mode) {
676 case FILE_READ:
677 buffer = list_first_item(&dev->bsink_list, struct comp_buffer,
678 source_list);
679 periods = dev->ipc_config.periods_sink;
680 break;
681 case FILE_WRITE:
682 buffer = list_first_item(&dev->bsource_list,
683 struct comp_buffer, sink_list);
684 periods = dev->ipc_config.periods_source;
685 break;
686 default:
687 /* TODO: duplex mode */
688 break;
689 }
690
691 if (!buffer) {
692 fprintf(stderr, "error: no sink/source buffer\n");
693 return -EINVAL;
694 }
695
696 /* set downstream buffer size */
697 switch (dev->ipc_config.frame_fmt) {
698 case(SOF_IPC_FRAME_S16_LE):
699 ret = buffer_set_size(buffer, dev->frames * 2 *
700 periods * buffer->stream.channels);
701 if (ret < 0) {
702 fprintf(stderr, "error: file buffer size set\n");
703 return ret;
704 }
705 buffer_reset_pos(buffer, NULL);
706
707 /* set file function */
708 cd->file_func = file_s16;
709 break;
710 case(SOF_IPC_FRAME_S24_4LE):
711 ret = buffer_set_size(buffer, dev->frames * 4 *
712 periods * buffer->stream.channels);
713 if (ret < 0) {
714 fprintf(stderr, "error: file buffer size set\n");
715 return ret;
716 }
717 buffer_reset_pos(buffer, NULL);
718
719 /* set file function */
720 cd->file_func = file_s24;
721 break;
722 case(SOF_IPC_FRAME_S32_LE):
723 ret = buffer_set_size(buffer, dev->frames * 4 *
724 periods * buffer->stream.channels);
725 if (ret < 0) {
726 fprintf(stderr, "error: file buffer size set\n");
727 return ret;
728 }
729 buffer_reset_pos(buffer, NULL);
730 break;
731 default:
732 return -EINVAL;
733 }
734
735 dev->state = COMP_STATE_PREPARE;
736
737 return ret;
738 }
739
file_reset(struct comp_dev * dev)740 static int file_reset(struct comp_dev *dev)
741 {
742 comp_info(dev, "file_reset()");
743 comp_set_state(dev, COMP_TRIGGER_RESET);
744 return 0;
745 }
746
file_get_hw_params(struct comp_dev * dev,struct sof_ipc_stream_params * params,int dir)747 static int file_get_hw_params(struct comp_dev *dev,
748 struct sof_ipc_stream_params *params, int dir)
749 {
750 struct file_comp_data *cd = comp_get_drvdata(dev);
751
752 comp_info(dev, "file_hw_params()");
753 params->direction = dir;
754 params->rate = cd->rate;
755 params->channels = cd->channels;
756 params->buffer_fmt = 0;
757 params->frame_fmt = cd->frame_fmt;
758 return 0;
759 }
760
761 static const struct comp_driver comp_file_host = {
762 .type = SOF_COMP_HOST,
763 .uid = SOF_UUID(file_tr),
764 .tctx = &file_tr,
765 .ops = {
766 .create = file_new,
767 .free = file_free,
768 .params = file_params,
769 .cmd = file_cmd,
770 .trigger = file_trigger,
771 .copy = file_copy,
772 .prepare = file_prepare,
773 .reset = file_reset,
774 },
775
776 };
777
778 static const struct comp_driver comp_file_dai = {
779 .type = SOF_COMP_DAI,
780 .uid = SOF_UUID(file_tr),
781 .tctx = &file_tr,
782 .ops = {
783 .create = file_new,
784 .free = file_free,
785 .params = file_params,
786 .cmd = file_cmd,
787 .trigger = file_trigger,
788 .copy = file_copy,
789 .prepare = file_prepare,
790 .reset = file_reset,
791 .dai_get_hw_params = file_get_hw_params,
792 },
793 };
794
795 static struct comp_driver_info comp_file_host_info = {
796 .drv = &comp_file_host,
797 };
798
799 static struct comp_driver_info comp_file_dai_info = {
800 .drv = &comp_file_dai,
801 };
802
sys_comp_file_init(void)803 void sys_comp_file_init(void)
804 {
805 comp_register(&comp_file_host_info);
806 comp_register(&comp_file_dai_info);
807 }
808