1 // SPDX-License-Identifier: BSD-3-Clause
2 //
3 // Copyright(c) 2020 Maxim Integrated All rights reserved.
4 //
5 // Author: Ryan Lee <ryans.lee@maximintegrated.com>
6 
7 #include <stdint.h>
8 #include <sof/audio/component.h>
9 #include <sof/audio/format.h>
10 #include <sof/audio/smart_amp/smart_amp.h>
11 
12 #ifdef CONFIG_GENERIC
13 
smart_amp_ff_generic(int32_t x)14 static int32_t smart_amp_ff_generic(int32_t x)
15 {
16 	/* Add speaker protection feed forward process here */
17 	return x;
18 }
19 
smart_amp_fb_generic(int32_t x)20 static void smart_amp_fb_generic(int32_t x)
21 {
22 	/* Add speaker protection feedback process here */
23 }
24 
25 #if CONFIG_FORMAT_S16LE
smart_amp_s16_ff_default(const struct comp_dev * dev,const struct audio_stream __sparse_cache * source,const struct audio_stream __sparse_cache * sink,const struct audio_stream __sparse_cache * feedback,uint32_t frames)26 static void smart_amp_s16_ff_default(const struct comp_dev *dev,
27 				     const struct audio_stream __sparse_cache *source,
28 				     const struct audio_stream __sparse_cache *sink,
29 				     const struct audio_stream __sparse_cache *feedback,
30 				     uint32_t frames)
31 {
32 	int16_t *x;
33 	int16_t *y;
34 	int32_t tmp;
35 	int idx;
36 	int ch;
37 	int i;
38 	int nch = source->channels;
39 
40 	for (ch = 0; ch < nch; ch++) {
41 		idx = ch;
42 		for (i = 0; i < frames; i++) {
43 			x = audio_stream_read_frag_s16(source, idx);
44 			y = audio_stream_read_frag_s16(sink, idx);
45 			tmp = smart_amp_ff_generic(*x << 16);
46 			*y = sat_int16(Q_SHIFT_RND(tmp, 31, 15));
47 			idx += nch;
48 		}
49 	}
50 }
51 #endif /* CONFIG_FORMAT_S16LE */
52 
53 #if CONFIG_FORMAT_S24LE
smart_amp_s24_ff_default(const struct comp_dev * dev,const struct audio_stream __sparse_cache * source,const struct audio_stream __sparse_cache * sink,const struct audio_stream __sparse_cache * feedback,uint32_t frames)54 static void smart_amp_s24_ff_default(const struct comp_dev *dev,
55 				     const struct audio_stream __sparse_cache *source,
56 				     const struct audio_stream __sparse_cache *sink,
57 				     const struct audio_stream __sparse_cache *feedback,
58 				     uint32_t frames)
59 {
60 	int32_t *x;
61 	int32_t *y;
62 	int32_t tmp;
63 	int idx;
64 	int ch;
65 	int i;
66 	int nch = source->channels;
67 
68 	for (ch = 0; ch < nch; ch++) {
69 		idx = ch;
70 		for (i = 0; i < frames; i++) {
71 			x = audio_stream_read_frag_s32(source, idx);
72 			y = audio_stream_read_frag_s32(sink, idx);
73 			tmp = smart_amp_ff_generic(*x << 8);
74 			*y = sat_int24(Q_SHIFT_RND(tmp, 31, 23));
75 			idx += nch;
76 		}
77 	}
78 }
79 #endif /* CONFIG_FORMAT_S24LE */
80 
81 #if CONFIG_FORMAT_S32LE
smart_amp_s32_ff_default(const struct comp_dev * dev,const struct audio_stream __sparse_cache * source,const struct audio_stream __sparse_cache * sink,const struct audio_stream __sparse_cache * feedback,uint32_t frames)82 static void smart_amp_s32_ff_default(const struct comp_dev *dev,
83 				     const struct audio_stream __sparse_cache *source,
84 				     const struct audio_stream __sparse_cache *sink,
85 				     const struct audio_stream __sparse_cache *feedback,
86 				     uint32_t frames)
87 {
88 	int32_t *x;
89 	int32_t *y;
90 	int idx;
91 	int ch;
92 	int i;
93 	int nch = source->channels;
94 
95 	for (ch = 0; ch < nch; ch++) {
96 		idx = ch;
97 		for (i = 0; i < frames; i++) {
98 			x = audio_stream_read_frag_s32(source, idx);
99 			y = audio_stream_read_frag_s32(sink, idx);
100 			*y = smart_amp_ff_generic(*x);
101 			idx += nch;
102 		}
103 	}
104 }
105 #endif /* CONFIG_FORMAT_S32LE */
106 
107 #if CONFIG_FORMAT_S16LE
smart_amp_s16_fb_default(const struct comp_dev * dev,const struct audio_stream __sparse_cache * source,const struct audio_stream __sparse_cache * sink,const struct audio_stream __sparse_cache * feedback,uint32_t frames)108 static void smart_amp_s16_fb_default(const struct comp_dev *dev,
109 				     const struct audio_stream __sparse_cache *source,
110 				     const struct audio_stream __sparse_cache *sink,
111 				     const struct audio_stream __sparse_cache *feedback,
112 				     uint32_t frames)
113 {
114 	int16_t *x;
115 	int idx;
116 	int ch;
117 	int i;
118 	int nch = source->channels;
119 
120 	for (ch = 0; ch < nch; ch++) {
121 		idx = ch;
122 		for (i = 0; i < frames; i++) {
123 			x = audio_stream_read_frag_s16(feedback, idx);
124 			smart_amp_fb_generic(*x << 16);
125 			idx += nch;
126 		}
127 	}
128 }
129 #endif /* CONFIG_FORMAT_S16LE */
130 
131 #if CONFIG_FORMAT_S24LE
smart_amp_s24_fb_default(const struct comp_dev * dev,const struct audio_stream __sparse_cache * source,const struct audio_stream __sparse_cache * sink,const struct audio_stream __sparse_cache * feedback,uint32_t frames)132 static void smart_amp_s24_fb_default(const struct comp_dev *dev,
133 				     const struct audio_stream __sparse_cache *source,
134 				     const struct audio_stream __sparse_cache *sink,
135 				     const struct audio_stream __sparse_cache *feedback,
136 				     uint32_t frames)
137 {
138 	int32_t *x;
139 	int idx;
140 	int ch;
141 	int i;
142 	int nch = source->channels;
143 
144 	for (ch = 0; ch < nch; ch++) {
145 		idx = ch;
146 		for (i = 0; i < frames; i++) {
147 			x = audio_stream_read_frag_s32(feedback, idx);
148 			smart_amp_fb_generic(*x << 8);
149 			idx += nch;
150 		}
151 	}
152 }
153 #endif /* CONFIG_FORMAT_S24LE */
154 
155 #if CONFIG_FORMAT_S32LE
smart_amp_s32_fb_default(const struct comp_dev * dev,const struct audio_stream __sparse_cache * source,const struct audio_stream __sparse_cache * sink,const struct audio_stream __sparse_cache * feedback,uint32_t frames)156 static void smart_amp_s32_fb_default(const struct comp_dev *dev,
157 				     const struct audio_stream __sparse_cache *source,
158 				     const struct audio_stream __sparse_cache *sink,
159 				     const struct audio_stream __sparse_cache *feedback,
160 				     uint32_t frames)
161 {
162 	int32_t *x;
163 	int idx;
164 	int ch;
165 	int i;
166 	int nch = source->channels;
167 
168 	for (ch = 0; ch < nch; ch++) {
169 		idx = ch;
170 		for (i = 0; i < frames; i++) {
171 			x = audio_stream_read_frag_s32(feedback, idx);
172 			smart_amp_ff_generic(*x);
173 			idx += nch;
174 		}
175 	}
176 }
177 #endif /* CONFIG_FORMAT_S32LE */
178 
179 const struct smart_amp_func_map smart_amp_function_map[] = {
180 /* { SOURCE_FORMAT , PROCESSING FUNCTION } */
181 #if CONFIG_FORMAT_S16LE
182 	{ SOF_IPC_FRAME_S16_LE, smart_amp_s16_ff_default },
183 #endif /* CONFIG_FORMAT_S16LE */
184 #if CONFIG_FORMAT_S24LE
185 	{ SOF_IPC_FRAME_S24_4LE, smart_amp_s24_ff_default },
186 #endif /* CONFIG_FORMAT_S24LE */
187 #if CONFIG_FORMAT_S32LE
188 	{ SOF_IPC_FRAME_S32_LE, smart_amp_s32_ff_default },
189 #endif /* CONFIG_FORMAT_S32LE */
190 #if CONFIG_FORMAT_S16LE
191 	{ SOF_IPC_FRAME_S16_LE, smart_amp_s16_fb_default },
192 #endif /* CONFIG_FORMAT_S16LE */
193 #if CONFIG_FORMAT_S24LE
194 	{ SOF_IPC_FRAME_S24_4LE, smart_amp_s24_fb_default },
195 #endif /* CONFIG_FORMAT_S24LE */
196 #if CONFIG_FORMAT_S32LE
197 	{ SOF_IPC_FRAME_S32_LE, smart_amp_s32_fb_default },
198 #endif /* CONFIG_FORMAT_S32LE */
199 };
200 
201 const size_t smart_amp_func_count = ARRAY_SIZE(smart_amp_function_map);
202 #endif
203