Merge tag 'iio-fixes-for-6.6a' of https://git.kernel.org/pub/scm/linux/kernel/git...
[platform/kernel/linux-rpi.git] / drivers / misc / echo / fir.h
1 /* SPDX-License-Identifier: GPL-2.0-only */
2 /*
3  * SpanDSP - a series of DSP components for telephony
4  *
5  * fir.h - General telephony FIR routines
6  *
7  * Written by Steve Underwood <steveu@coppice.org>
8  *
9  * Copyright (C) 2002 Steve Underwood
10  *
11  * All rights reserved.
12  */
13
14 #if !defined(_FIR_H_)
15 #define _FIR_H_
16
17 /*
18    Ideas for improvement:
19
20    1/ Rewrite filter for dual MAC inner loop.  The issue here is handling
21    history sample offsets that are 16 bit aligned - the dual MAC needs
22    32 bit aligmnent.  There are some good examples in libbfdsp.
23
24    2/ Use the hardware circular buffer facility tohalve memory usage.
25
26    3/ Consider using internal memory.
27
28    Using less memory might also improve speed as cache misses will be
29    reduced. A drop in MIPs and memory approaching 50% should be
30    possible.
31
32    The foreground and background filters currenlty use a total of
33    about 10 MIPs/ch as measured with speedtest.c on a 256 TAP echo
34    can.
35 */
36
37 /*
38  * 16 bit integer FIR descriptor. This defines the working state for a single
39  * instance of an FIR filter using 16 bit integer coefficients.
40  */
41 struct fir16_state_t {
42         int taps;
43         int curr_pos;
44         const int16_t *coeffs;
45         int16_t *history;
46 };
47
48 /*
49  * 32 bit integer FIR descriptor. This defines the working state for a single
50  * instance of an FIR filter using 32 bit integer coefficients, and filtering
51  * 16 bit integer data.
52  */
53 struct fir32_state_t {
54         int taps;
55         int curr_pos;
56         const int32_t *coeffs;
57         int16_t *history;
58 };
59
60 /*
61  * Floating point FIR descriptor. This defines the working state for a single
62  * instance of an FIR filter using floating point coefficients and data.
63  */
64 struct fir_float_state_t {
65         int taps;
66         int curr_pos;
67         const float *coeffs;
68         float *history;
69 };
70
71 static inline const int16_t *fir16_create(struct fir16_state_t *fir,
72                                               const int16_t *coeffs, int taps)
73 {
74         fir->taps = taps;
75         fir->curr_pos = taps - 1;
76         fir->coeffs = coeffs;
77         fir->history = kcalloc(taps, sizeof(int16_t), GFP_KERNEL);
78         return fir->history;
79 }
80
81 static inline void fir16_flush(struct fir16_state_t *fir)
82 {
83         memset(fir->history, 0, fir->taps * sizeof(int16_t));
84 }
85
86 static inline void fir16_free(struct fir16_state_t *fir)
87 {
88         kfree(fir->history);
89 }
90
91 static inline int16_t fir16(struct fir16_state_t *fir, int16_t sample)
92 {
93         int32_t y;
94         int i;
95         int offset1;
96         int offset2;
97
98         fir->history[fir->curr_pos] = sample;
99
100         offset2 = fir->curr_pos;
101         offset1 = fir->taps - offset2;
102         y = 0;
103         for (i = fir->taps - 1; i >= offset1; i--)
104                 y += fir->coeffs[i] * fir->history[i - offset1];
105         for (; i >= 0; i--)
106                 y += fir->coeffs[i] * fir->history[i + offset2];
107         if (fir->curr_pos <= 0)
108                 fir->curr_pos = fir->taps;
109         fir->curr_pos--;
110         return (int16_t) (y >> 15);
111 }
112
113 static inline const int16_t *fir32_create(struct fir32_state_t *fir,
114                                               const int32_t *coeffs, int taps)
115 {
116         fir->taps = taps;
117         fir->curr_pos = taps - 1;
118         fir->coeffs = coeffs;
119         fir->history = kcalloc(taps, sizeof(int16_t), GFP_KERNEL);
120         return fir->history;
121 }
122
123 static inline void fir32_flush(struct fir32_state_t *fir)
124 {
125         memset(fir->history, 0, fir->taps * sizeof(int16_t));
126 }
127
128 static inline void fir32_free(struct fir32_state_t *fir)
129 {
130         kfree(fir->history);
131 }
132
133 static inline int16_t fir32(struct fir32_state_t *fir, int16_t sample)
134 {
135         int i;
136         int32_t y;
137         int offset1;
138         int offset2;
139
140         fir->history[fir->curr_pos] = sample;
141         offset2 = fir->curr_pos;
142         offset1 = fir->taps - offset2;
143         y = 0;
144         for (i = fir->taps - 1; i >= offset1; i--)
145                 y += fir->coeffs[i] * fir->history[i - offset1];
146         for (; i >= 0; i--)
147                 y += fir->coeffs[i] * fir->history[i + offset2];
148         if (fir->curr_pos <= 0)
149                 fir->curr_pos = fir->taps;
150         fir->curr_pos--;
151         return (int16_t) (y >> 15);
152 }
153
154 #endif