1 // SPDX-License-Identifier: BSD-3-Clause
2 //
3 // Copyright(c) 2016 Intel Corporation. All rights reserved.
4 //
5 // Author: Seppo Ingalsuo <seppo.ingalsuo@linux.intel.com>
6 // Liam Girdwood <liam.r.girdwood@linux.intel.com>
7 // Keyon Jie <yang.jie@linux.intel.com>
8
9 #include <sof/audio/buffer.h>
10 #include <sof/audio/component.h>
11 #include <sof/audio/format.h>
12 #include <sof/audio/pipeline.h>
13 #include <sof/audio/ipc-config.h>
14 #include <sof/common.h>
15 #include <sof/debug/panic.h>
16 #include <sof/ipc/msg.h>
17 #include <sof/lib/alloc.h>
18 #include <sof/lib/memory.h>
19 #include <sof/lib/uuid.h>
20 #include <sof/list.h>
21 #include <sof/math/trig.h>
22 #include <sof/platform.h>
23 #include <sof/string.h>
24 #include <sof/trace/trace.h>
25 #include <sof/ut.h>
26 #include <ipc/control.h>
27 #include <ipc/stream.h>
28 #include <ipc/topology.h>
29 #include <user/tone.h>
30 #include <user/trace.h>
31 #include <errno.h>
32 #include <stdbool.h>
33 #include <stddef.h>
34 #include <stdint.h>
35
36 /* Convert float frequency in Hz to Q16.16 fractional format */
37 #define TONE_FREQ(f) Q_CONVERT_FLOAT(f, 16)
38
39 /* Convert float gain to Q1.31 fractional format */
40 #define TONE_GAIN(v) Q_CONVERT_FLOAT(v, 31)
41
42 /* Set default tone amplitude and frequency */
43 #define TONE_AMPLITUDE_DEFAULT TONE_GAIN(0.1) /* -20 dB */
44 #define TONE_FREQUENCY_DEFAULT TONE_FREQ(997.0)
45 #define TONE_NUM_FS 13 /* Table size for 8-192 kHz range */
46
47 static const struct comp_driver comp_tone;
48
49 /* 04e3f894-2c5c-4f2e-8dc1-694eeaab53fa */
50 DECLARE_SOF_RT_UUID("tone", tone_uuid, 0x04e3f894, 0x2c5c, 0x4f2e,
51 0x8d, 0xc1, 0x69, 0x4e, 0xea, 0xab, 0x53, 0xfa);
52
53 DECLARE_TR_CTX(tone_tr, SOF_UUID(tone_uuid), LOG_LEVEL_INFO);
54
55 /* 2*pi/Fs lookup tables in Q1.31 for each Fs */
56 static const int32_t tone_fs_list[TONE_NUM_FS] = {
57 8000, 11025, 16000, 22050, 24000, 32000, 44100, 48000,
58 64000, 88200, 96000, 176400, 192000
59 };
60
61 static const int32_t tone_pi2_div_fs[TONE_NUM_FS] = {
62 1686630, 1223858, 843315, 611929, 562210, 421657, 305965,
63 281105, 210829, 152982, 140552, 76491, 70276
64 };
65
66 /* tone component private data */
67
68 struct tone_state {
69 int mute;
70 int32_t a; /* Current amplitude Q1.31 */
71 int32_t a_target; /* Target amplitude Q1.31 */
72 int32_t ampl_coef; /* Amplitude multiplier Q2.30 */
73 int32_t c; /* Coefficient 2*pi/Fs Q1.31 */
74 int32_t f; /* Frequency Q16.16 */
75 int32_t freq_coef; /* Frequency multiplier Q2.30 */
76 int32_t fs; /* Sample rate in Hertz Q32.0 */
77 int32_t ramp_step; /* Amplitude ramp step Q1.31 */
78 int32_t w; /* Angle radians Q4.28 */
79 int32_t w_step; /* Angle step Q4.28 */
80 uint32_t block_count;
81 uint32_t repeat_count;
82 uint32_t repeats; /* Number of repeats for tone (sweep steps) */
83 uint32_t sample_count;
84 uint32_t samples_in_block; /* Samples in 125 us block */
85 uint32_t tone_length; /* Active length in 125 us blocks */
86 uint32_t tone_period; /* Active + idle time in 125 us blocks */
87 };
88
89 struct comp_data {
90 uint32_t period_bytes;
91 uint32_t channels;
92 uint32_t frame_bytes;
93 uint32_t rate;
94 struct tone_state sg[PLATFORM_MAX_CHANNELS];
95 void (*tone_func)(struct comp_dev *dev, struct audio_stream *sink,
96 uint32_t frames);
97 };
98
99 static int32_t tonegen(struct tone_state *sg);
100 static void tonegen_control(struct tone_state *sg);
101 static void tonegen_update_f(struct tone_state *sg, int32_t f);
102
103 /*
104 * Tone generator algorithm code
105 */
106
tone_circ_inc_wrap(int32_t ** ptr,int32_t * end,size_t size)107 static inline void tone_circ_inc_wrap(int32_t **ptr, int32_t *end, size_t size)
108 {
109 if (*ptr >= end)
110 *ptr = (int32_t *)((size_t)*ptr - size);
111 }
112
tone_s32_default(struct comp_dev * dev,struct audio_stream * sink,uint32_t frames)113 static void tone_s32_default(struct comp_dev *dev, struct audio_stream *sink,
114 uint32_t frames)
115 {
116 struct comp_data *cd = comp_get_drvdata(dev);
117 int32_t *dest = (int32_t *)sink->w_ptr;
118 int i;
119 int n;
120 int n_wrap_dest;
121 int n_min;
122 int nch = cd->channels;
123
124 n = frames * nch;
125 while (n > 0) {
126 n_wrap_dest = (int32_t *)sink->end_addr - dest;
127 n_min = (n < n_wrap_dest) ? n : n_wrap_dest;
128 /* Process until wrap or completed n */
129 while (n_min > 0) {
130 n -= nch;
131 n_min -= nch;
132 for (i = 0; i < nch; i++) {
133 tonegen_control(&cd->sg[i]);
134 *dest = tonegen(&cd->sg[i]);
135 dest++;
136 }
137 }
138 tone_circ_inc_wrap(&dest, sink->end_addr, sink->size);
139 }
140 }
141
tonegen(struct tone_state * sg)142 static int32_t tonegen(struct tone_state *sg)
143 {
144 int64_t sine;
145 int64_t w;
146 /* sg->w is angle in Q4.28 radians format, sin() returns Q1.31 */
147 /* sg->a is amplitude as Q1.31 */
148 sine =
149 q_mults_32x32(sin_fixed_32b(sg->w), sg->a,
150 Q_SHIFT_BITS_64(31, 31, 31));
151
152 /* Next point */
153 w = (int64_t)sg->w + sg->w_step;
154 sg->w = (w > PI_MUL2_Q4_28)
155 ? (int32_t)(w - PI_MUL2_Q4_28) : (int32_t)w;
156
157 if (sg->mute)
158 return 0;
159 else
160 return (int32_t)sine; /* Q1.31 no saturation need */
161 }
162
tonegen_control(struct tone_state * sg)163 static void tonegen_control(struct tone_state *sg)
164 {
165 int64_t a;
166 int64_t p;
167
168 /* Count samples, 125 us blocks */
169 sg->sample_count++;
170 if (sg->sample_count < sg->samples_in_block)
171 return;
172
173 sg->sample_count = 0;
174 if (sg->block_count < INT32_MAX)
175 sg->block_count++;
176
177 /* Fade-in ramp during tone */
178 if (sg->block_count < sg->tone_length) {
179 if (sg->a == 0)
180 sg->w = 0; /* Reset phase to have less clicky ramp */
181
182 if (sg->a > sg->a_target) {
183 a = (int64_t)sg->a - sg->ramp_step;
184 if (a < sg->a_target)
185 a = sg->a_target;
186
187 } else {
188 a = (int64_t)sg->a + sg->ramp_step;
189 if (a > sg->a_target)
190 a = sg->a_target;
191 }
192 sg->a = (int32_t)a;
193 }
194
195 /* Fade-out ramp after tone*/
196 if (sg->block_count > sg->tone_length) {
197 a = (int64_t)sg->a - sg->ramp_step;
198 if (a < 0)
199 a = 0;
200
201 sg->a = (int32_t)a;
202 }
203
204 /* New repeated tone, update for frequency or amplitude sweep */
205 if ((sg->block_count > sg->tone_period) &&
206 (sg->repeat_count + 1 < sg->repeats)) {
207 sg->block_count = 0;
208 if (sg->ampl_coef > 0) {
209 sg->a_target =
210 sat_int32(q_multsr_32x32(sg->a_target,
211 sg->ampl_coef, Q_SHIFT_BITS_64(31, 30, 31)));
212 sg->a = (sg->ramp_step > sg->a_target)
213 ? sg->a_target : sg->ramp_step;
214 }
215 if (sg->freq_coef > 0) {
216 /* f is Q16.16, freq_coef is Q2.30 */
217 p = q_multsr_32x32(sg->f, sg->freq_coef,
218 Q_SHIFT_BITS_64(16, 30, 16));
219 tonegen_update_f(sg, (int32_t)p); /* No saturation */
220 }
221 sg->repeat_count++;
222 }
223 }
224
225 /* Set sine amplitude */
tonegen_set_a(struct tone_state * sg,int32_t a)226 static inline void tonegen_set_a(struct tone_state *sg, int32_t a)
227 {
228 sg->a_target = a;
229 }
230
231 /* Repeated number of beeps */
tonegen_set_repeats(struct tone_state * sg,uint32_t r)232 static void tonegen_set_repeats(struct tone_state *sg, uint32_t r)
233 {
234 sg->repeats = r;
235 }
236
237 /* The next functions support zero as shortcut for defaults to get
238 * make a nicer API without need to remember the neutral steady
239 * non-swept tone settings.
240 */
241
242 /* Multiplication factor for frequency as Q2.30 for logarithmic change */
tonegen_set_freq_mult(struct tone_state * sg,int32_t fm)243 static void tonegen_set_freq_mult(struct tone_state *sg, int32_t fm)
244 {
245 sg->freq_coef = (fm > 0) ? fm : ONE_Q2_30; /* Set freq mult to 1.0 */
246 }
247
248 /* Multiplication factor for amplitude as Q2.30 for logarithmic change */
tonegen_set_ampl_mult(struct tone_state * sg,int32_t am)249 static void tonegen_set_ampl_mult(struct tone_state *sg, int32_t am)
250 {
251 sg->ampl_coef = (am > 0) ? am : ONE_Q2_30; /* Set ampl mult to 1.0 */
252 }
253
254 /* Tone length in samples, this is the active length of tone */
tonegen_set_length(struct tone_state * sg,uint32_t tl)255 static void tonegen_set_length(struct tone_state *sg, uint32_t tl)
256 {
257 sg->tone_length = (tl > 0) ? tl : INT32_MAX; /* Count rate 125 us */
258 }
259
260 /* Tone period in samples, this is the length including the pause after beep */
tonegen_set_period(struct tone_state * sg,uint32_t tp)261 static void tonegen_set_period(struct tone_state *sg, uint32_t tp)
262 {
263 sg->tone_period = (tp > 0) ? tp : INT32_MAX; /* Count rate 125 us */
264 }
265
266 /* Tone ramp parameters:
267 * step - Value that is added or subtracted to amplitude. A zero or negative
268 * number disables the ramp and amplitude is immediately modified to
269 * final value.
270 */
271
tonegen_set_linramp(struct tone_state * sg,int32_t step)272 static inline void tonegen_set_linramp(struct tone_state *sg, int32_t step)
273 {
274 sg->ramp_step = (step > 0) ? step : INT32_MAX;
275 }
276
tonegen_get_f(struct tone_state * sg)277 static inline int32_t tonegen_get_f(struct tone_state *sg)
278 {
279 return sg->f;
280 }
281
tonegen_get_a(struct tone_state * sg)282 static inline int32_t tonegen_get_a(struct tone_state *sg)
283 {
284 return sg->a_target;
285 }
286
tonegen_mute(struct tone_state * sg)287 static inline void tonegen_mute(struct tone_state *sg)
288 {
289 sg->mute = 1;
290 }
291
tonegen_unmute(struct tone_state * sg)292 static inline void tonegen_unmute(struct tone_state *sg)
293 {
294 sg->mute = 0;
295 }
296
tonegen_update_f(struct tone_state * sg,int32_t f)297 static void tonegen_update_f(struct tone_state *sg, int32_t f)
298 {
299 int64_t w_tmp;
300 int64_t f_max;
301
302 /* Calculate Fs/2, fs is Q32.0, f is Q16.16 */
303 f_max = Q_SHIFT_LEFT((int64_t)sg->fs, 0, 16 - 1);
304 f_max = (f_max > INT32_MAX) ? INT32_MAX : f_max;
305 sg->f = (f > f_max) ? f_max : f;
306 /* Q16 x Q31 -> Q28 */
307 w_tmp = q_multsr_32x32(sg->f, sg->c, Q_SHIFT_BITS_64(16, 31, 28));
308 w_tmp = (w_tmp > PI_Q4_28) ? PI_Q4_28 : w_tmp; /* Limit to pi Q4.28 */
309 sg->w_step = (int32_t)w_tmp;
310 }
311
tonegen_reset(struct tone_state * sg)312 static void tonegen_reset(struct tone_state *sg)
313 {
314 sg->mute = 1;
315 sg->a = 0;
316 sg->a_target = TONE_AMPLITUDE_DEFAULT;
317 sg->c = 0;
318 sg->f = TONE_FREQUENCY_DEFAULT;
319 sg->w = 0;
320 sg->w_step = 0;
321
322 sg->block_count = 0;
323 sg->repeat_count = 0;
324 sg->repeats = 0;
325 sg->sample_count = 0;
326 sg->samples_in_block = 0;
327
328 /* Continuous tone */
329 sg->freq_coef = ONE_Q2_30; /* Set freq multiplier to 1.0 */
330 sg->ampl_coef = ONE_Q2_30; /* Set ampl multiplier to 1.0 */
331 sg->tone_length = INT32_MAX;
332 sg->tone_period = INT32_MAX;
333 sg->ramp_step = ONE_Q1_31; /* Set lin ramp modification to max */
334 }
335
tonegen_init(struct tone_state * sg,int32_t fs,int32_t f,int32_t a)336 static int tonegen_init(struct tone_state *sg, int32_t fs, int32_t f, int32_t a)
337 {
338 int idx;
339 int i;
340
341 sg->a_target = a;
342 sg->a = (sg->ramp_step > sg->a_target) ? sg->a_target : sg->ramp_step;
343
344 idx = -1;
345 sg->mute = 1;
346 sg->fs = 0;
347
348 /* Find index of current sample rate and then get from lookup table the
349 * corresponding 2*pi/Fs value.
350 */
351 for (i = 0; i < TONE_NUM_FS; i++) {
352 if (fs == tone_fs_list[i])
353 idx = i;
354 }
355
356 if (idx < 0) {
357 sg->w_step = 0;
358 return -EINVAL;
359 }
360
361 sg->fs = fs;
362 sg->c = tone_pi2_div_fs[idx]; /* Store 2*pi/Fs */
363 sg->mute = 0;
364 tonegen_update_f(sg, f);
365
366 /* 125us as Q1.31 is 268435, calculate fs * 125e-6 in Q31.0 */
367 sg->samples_in_block =
368 (int32_t) q_multsr_32x32(fs, 268435, Q_SHIFT_BITS_64(0, 31, 0));
369
370 return 0;
371 }
372
373 /*
374 * End of algorithm code. Next the standard component methods.
375 */
376
tone_new(const struct comp_driver * drv,struct comp_ipc_config * config,void * spec)377 static struct comp_dev *tone_new(const struct comp_driver *drv,
378 struct comp_ipc_config *config,
379 void *spec)
380 {
381 struct comp_dev *dev;
382 struct ipc_config_tone *ipc_tone = spec;
383 struct comp_data *cd;
384 int i;
385
386 comp_cl_info(&comp_tone, "tone_new()");
387
388 dev = comp_alloc(drv, sizeof(*dev));
389 if (!dev)
390 return NULL;
391 dev->ipc_config = *config;
392
393 cd = rzalloc(SOF_MEM_ZONE_RUNTIME, 0, SOF_MEM_CAPS_RAM, sizeof(*cd));
394 if (!cd) {
395 rfree(dev);
396 return NULL;
397 }
398
399 comp_set_drvdata(dev, cd);
400 cd->tone_func = tone_s32_default;
401
402 cd->rate = ipc_tone->sample_rate;
403
404 /* Reset tone generator and set channels volumes to default */
405 for (i = 0; i < PLATFORM_MAX_CHANNELS; i++)
406 tonegen_reset(&cd->sg[i]);
407
408 dev->state = COMP_STATE_READY;
409 return dev;
410 }
411
tone_free(struct comp_dev * dev)412 static void tone_free(struct comp_dev *dev)
413 {
414 struct tone_data *td = comp_get_drvdata(dev);
415
416 comp_info(dev, "tone_free()");
417
418 rfree(td);
419 rfree(dev);
420 }
421
422 /* set component audio stream parameters */
tone_params(struct comp_dev * dev,struct sof_ipc_stream_params * params)423 static int tone_params(struct comp_dev *dev,
424 struct sof_ipc_stream_params *params)
425 {
426 struct comp_data *cd = comp_get_drvdata(dev);
427 struct comp_buffer *sourceb;
428 struct comp_buffer *sinkb;
429 uint32_t flags = 0;
430
431 sourceb = list_first_item(&dev->bsource_list, struct comp_buffer,
432 sink_list);
433
434 sinkb = list_first_item(&dev->bsink_list, struct comp_buffer,
435 source_list);
436
437 comp_info(dev, "tone_params(), config->frame_fmt = %u",
438 dev->ipc_config.frame_fmt);
439
440 /* Tone supports only S32_LE PCM format atm */
441 if (dev->ipc_config.frame_fmt != SOF_IPC_FRAME_S32_LE)
442 return -EINVAL;
443
444 buffer_lock(sourceb, &flags);
445 buffer_lock(sinkb, &flags);
446
447 sourceb->stream.frame_fmt = dev->ipc_config.frame_fmt;
448 sinkb->stream.frame_fmt = dev->ipc_config.frame_fmt;
449
450 /* calculate period size based on config */
451 cd->period_bytes = dev->frames *
452 audio_stream_frame_bytes(&sourceb->stream);
453
454 buffer_unlock(sinkb, flags);
455 buffer_unlock(sourceb, flags);
456
457 return 0;
458 }
459
tone_cmd_get_value(struct comp_dev * dev,struct sof_ipc_ctrl_data * cdata,int max_size)460 static int tone_cmd_get_value(struct comp_dev *dev,
461 struct sof_ipc_ctrl_data *cdata, int max_size)
462 {
463 struct comp_data *cd = comp_get_drvdata(dev);
464 int j;
465
466 comp_info(dev, "tone_cmd_get_value()");
467
468 if (cdata->cmd == SOF_CTRL_CMD_SWITCH) {
469 for (j = 0; j < cdata->num_elems; j++) {
470 cdata->chanv[j].channel = j;
471 cdata->chanv[j].value = !cd->sg[j].mute;
472 comp_info(dev, "tone_cmd_get_value(), j = %u, cd->sg[j].mute = %u",
473 j, cd->sg[j].mute);
474 }
475 }
476 return 0;
477 }
478
tone_cmd_set_value(struct comp_dev * dev,struct sof_ipc_ctrl_data * cdata)479 static int tone_cmd_set_value(struct comp_dev *dev,
480 struct sof_ipc_ctrl_data *cdata)
481 {
482 struct comp_data *cd = comp_get_drvdata(dev);
483 int j;
484 uint32_t ch;
485 bool val;
486
487 if (cdata->cmd == SOF_CTRL_CMD_SWITCH) {
488 comp_info(dev, "tone_cmd_set_value(), SOF_CTRL_CMD_SWITCH");
489 for (j = 0; j < cdata->num_elems; j++) {
490 ch = cdata->chanv[j].channel;
491 val = cdata->chanv[j].value;
492 comp_info(dev, "tone_cmd_set_value(), SOF_CTRL_CMD_SWITCH, ch = %u, val = %u",
493 ch, val);
494 if (ch >= PLATFORM_MAX_CHANNELS) {
495 comp_err(dev, "tone_cmd_set_value(): ch >= PLATFORM_MAX_CHANNELS");
496 return -EINVAL;
497 }
498
499 if (val)
500 tonegen_unmute(&cd->sg[ch]);
501 else
502 tonegen_mute(&cd->sg[ch]);
503 }
504 } else {
505 comp_err(dev, "tone_cmd_set_value(): invalid cdata->cmd");
506 return -EINVAL;
507 }
508
509 return 0;
510 }
511
tone_cmd_set_data(struct comp_dev * dev,struct sof_ipc_ctrl_data * cdata)512 static int tone_cmd_set_data(struct comp_dev *dev,
513 struct sof_ipc_ctrl_data *cdata)
514 {
515 struct comp_data *cd = comp_get_drvdata(dev);
516 struct sof_ipc_ctrl_value_comp *compv;
517 int i;
518 uint32_t ch;
519 uint32_t val;
520
521 comp_info(dev, "tone_cmd_set_data()");
522
523 switch (cdata->cmd) {
524 case SOF_CTRL_CMD_ENUM:
525 comp_info(dev, "tone_cmd_set_data(), SOF_CTRL_CMD_ENUM, cdata->index = %u",
526 cdata->index);
527 compv = (struct sof_ipc_ctrl_value_comp *)ASSUME_ALIGNED(cdata->data->data, 4);
528
529 for (i = 0; i < (int)cdata->num_elems; i++) {
530 ch = compv[i].index;
531 val = compv[i].svalue;
532 comp_info(dev, "tone_cmd_set_data(), SOF_CTRL_CMD_ENUM, ch = %u, val = %u",
533 ch, val);
534 switch (cdata->index) {
535 case SOF_TONE_IDX_FREQUENCY:
536 comp_info(dev, "tone_cmd_set_data(), SOF_TONE_IDX_FREQUENCY");
537 tonegen_update_f(&cd->sg[ch], val);
538 break;
539 case SOF_TONE_IDX_AMPLITUDE:
540 comp_info(dev, "tone_cmd_set_data(), SOF_TONE_IDX_AMPLITUDE");
541 tonegen_set_a(&cd->sg[ch], val);
542 break;
543 case SOF_TONE_IDX_FREQ_MULT:
544 comp_info(dev, "tone_cmd_set_data(), SOF_TONE_IDX_FREQ_MULT");
545 tonegen_set_freq_mult(&cd->sg[ch], val);
546 break;
547 case SOF_TONE_IDX_AMPL_MULT:
548 comp_info(dev, "tone_cmd_set_data(), SOF_TONE_IDX_AMPL_MULT");
549 tonegen_set_ampl_mult(&cd->sg[ch], val);
550 break;
551 case SOF_TONE_IDX_LENGTH:
552 comp_info(dev, "tone_cmd_set_data(), SOF_TONE_IDX_LENGTH");
553 tonegen_set_length(&cd->sg[ch], val);
554 break;
555 case SOF_TONE_IDX_PERIOD:
556 comp_info(dev, "tone_cmd_set_data(), SOF_TONE_IDX_PERIOD");
557 tonegen_set_period(&cd->sg[ch], val);
558 break;
559 case SOF_TONE_IDX_REPEATS:
560 comp_info(dev, "tone_cmd_set_data(), SOF_TONE_IDX_REPEATS");
561 tonegen_set_repeats(&cd->sg[ch], val);
562 break;
563 case SOF_TONE_IDX_LIN_RAMP_STEP:
564 comp_info(dev, "tone_cmd_set_data(), SOF_TONE_IDX_LIN_RAMP_STEP");
565 tonegen_set_linramp(&cd->sg[ch], val);
566 break;
567 default:
568 comp_err(dev, "tone_cmd_set_data(): invalid cdata->index");
569 return -EINVAL;
570 }
571 }
572 break;
573 default:
574 comp_err(dev, "tone_cmd_set_data(): invalid cdata->cmd");
575 return -EINVAL;
576 }
577
578 return 0;
579 }
580
581 /* used to pass standard and bespoke commands (with data) to component */
tone_cmd(struct comp_dev * dev,int cmd,void * data,int max_data_size)582 static int tone_cmd(struct comp_dev *dev, int cmd, void *data,
583 int max_data_size)
584 {
585 struct sof_ipc_ctrl_data *cdata = ASSUME_ALIGNED(data, 4);
586 int ret = 0;
587
588 comp_info(dev, "tone_cmd()");
589
590 switch (cmd) {
591 case COMP_CMD_SET_DATA:
592 ret = tone_cmd_set_data(dev, cdata);
593 break;
594 case COMP_CMD_SET_VALUE:
595 ret = tone_cmd_set_value(dev, cdata);
596 break;
597 case COMP_CMD_GET_VALUE:
598 ret = tone_cmd_get_value(dev, cdata, max_data_size);
599 break;
600 }
601
602 return ret;
603 }
604
tone_trigger(struct comp_dev * dev,int cmd)605 static int tone_trigger(struct comp_dev *dev, int cmd)
606 {
607 comp_info(dev, "tone_trigger()");
608
609 return comp_set_state(dev, cmd);
610 }
611
612 /* copy and process stream data from source to sink buffers */
tone_copy(struct comp_dev * dev)613 static int tone_copy(struct comp_dev *dev)
614 {
615 struct comp_buffer *sink;
616 struct comp_data *cd = comp_get_drvdata(dev);
617 uint32_t free;
618 uint32_t flags = 0;
619
620 comp_dbg(dev, "tone_copy()");
621
622 /* tone component sink buffer */
623 sink = list_first_item(&dev->bsink_list, struct comp_buffer,
624 source_list);
625
626 buffer_lock(sink, &flags);
627 free = audio_stream_get_free_bytes(&sink->stream);
628 buffer_unlock(sink, flags);
629
630 /* Test that sink has enough free frames. Then run once to maintain
631 * low latency and steady load for tones.
632 */
633 if (free >= cd->period_bytes) {
634 /* create tone */
635 cd->tone_func(dev, &sink->stream, dev->frames);
636 buffer_writeback(sink, cd->period_bytes);
637
638 /* calc new free and available */
639 comp_update_buffer_produce(sink, cd->period_bytes);
640
641 return dev->frames;
642 }
643
644 return 0;
645 }
646
tone_prepare(struct comp_dev * dev)647 static int tone_prepare(struct comp_dev *dev)
648 {
649 struct comp_data *cd = comp_get_drvdata(dev);
650 struct comp_buffer *sourceb;
651 int32_t f;
652 int32_t a;
653 int ret;
654 int i;
655
656 comp_info(dev, "tone_prepare()");
657
658 ret = comp_set_state(dev, COMP_TRIGGER_PREPARE);
659 if (ret < 0)
660 return ret;
661
662 if (ret == COMP_STATUS_STATE_ALREADY_SET)
663 return PPL_STATUS_PATH_STOP;
664
665 sourceb = list_first_item(&dev->bsource_list, struct comp_buffer,
666 sink_list);
667
668 cd->channels = sourceb->stream.channels;
669 comp_info(dev, "tone_prepare(), cd->channels = %u, cd->rate = %u",
670 cd->channels, cd->rate);
671
672 for (i = 0; i < cd->channels; i++) {
673 f = tonegen_get_f(&cd->sg[i]);
674 a = tonegen_get_a(&cd->sg[i]);
675 if (tonegen_init(&cd->sg[i], cd->rate, f, a) < 0) {
676 comp_set_state(dev, COMP_TRIGGER_RESET);
677 return -EINVAL;
678 }
679 }
680
681 return 0;
682 }
683
tone_reset(struct comp_dev * dev)684 static int tone_reset(struct comp_dev *dev)
685 {
686 struct comp_data *cd = comp_get_drvdata(dev);
687 int i;
688
689 comp_info(dev, "tone_reset()");
690
691 /* Initialize with the defaults */
692 for (i = 0; i < PLATFORM_MAX_CHANNELS; i++)
693 tonegen_reset(&cd->sg[i]);
694
695 comp_set_state(dev, COMP_TRIGGER_RESET);
696
697 return 0;
698 }
699
700 static const struct comp_driver comp_tone = {
701 .type = SOF_COMP_TONE,
702 .uid = SOF_RT_UUID(tone_uuid),
703 .tctx = &tone_tr,
704 .ops = {
705 .create = tone_new,
706 .free = tone_free,
707 .params = tone_params,
708 .cmd = tone_cmd,
709 .trigger = tone_trigger,
710 .copy = tone_copy,
711 .prepare = tone_prepare,
712 .reset = tone_reset,
713 },
714 };
715
716 static SHARED_DATA struct comp_driver_info comp_tone_info = {
717 .drv = &comp_tone,
718 };
719
sys_comp_tone_init(void)720 UT_STATIC void sys_comp_tone_init(void)
721 {
722 comp_register(platform_shared_get(&comp_tone_info,
723 sizeof(comp_tone_info)));
724 }
725
726 DECLARE_MODULE(sys_comp_tone_init);
727