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