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