1 /*
2 * Copyright (c) 2022 Intel Corporation.
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 */
6
7 #ifndef __INTEL_DAI_DRIVER_DMIC_H__
8 #define __INTEL_DAI_DRIVER_DMIC_H__
9
10 #include <zephyr/sys/util_macro.h>
11
12 /* The microphones create a low frequecy thump sound when clock is enabled.
13 * The unmute linear gain ramp chacteristic is defined here.
14 * NOTE: Do not set any of these to 0.
15 */
16 #define DMIC_UNMUTE_RAMP_US 1000 /* 1 ms (in microseconds) */
17 #define DMIC_UNMUTE_CIC 1 /* Unmute CIC at 1 ms */
18 #define DMIC_UNMUTE_FIR 2 /* Unmute FIR at 2 ms */
19
20 /* Parameters used in modes computation */
21 #define DMIC_HW_BITS_CIC 26
22 #define DMIC_HW_BITS_FIR_COEF 20
23 #define DMIC_HW_BITS_FIR_GAIN 20
24 #define DMIC_HW_BITS_FIR_INPUT 22
25 #define DMIC_HW_BITS_FIR_OUTPUT 24
26 #define DMIC_HW_BITS_FIR_INTERNAL 26
27 #define DMIC_HW_BITS_GAIN_OUTPUT 22
28 #define DMIC_HW_FIR_LENGTH_MAX 250
29 #define DMIC_HW_CIC_SHIFT_MIN -8
30 #define DMIC_HW_CIC_SHIFT_MAX 4
31 #define DMIC_HW_FIR_SHIFT_MIN 0
32 #define DMIC_HW_FIR_SHIFT_MAX 8
33 #define DMIC_HW_CIC_DECIM_MIN 5
34 #define DMIC_HW_CIC_DECIM_MAX 31 /* Note: Limited by BITS_CIC */
35 #define DMIC_HW_FIR_DECIM_MIN 2
36 #define DMIC_HW_FIR_DECIM_MAX 20 /* Note: Practical upper limit */
37 #define DMIC_HW_SENS_Q28 Q_CONVERT_FLOAT(1.0, 28) /* Q1.28 */
38 #define DMIC_HW_PDM_CLK_MIN 100000 /* Note: Practical min value */
39 #define DMIC_HW_DUTY_MIN 20 /* Note: Practical min value */
40 #define DMIC_HW_DUTY_MAX 80 /* Note: Practical max value */
41
42 /* DC offset compensation time constants */
43 #define DCCOMP_TC0 0
44 #define DCCOMP_TC1 1
45 #define DCCOMP_TC2 2
46 #define DCCOMP_TC3 3
47 #define DCCOMP_TC4 4
48 #define DCCOMP_TC5 5
49 #define DCCOMP_TC6 6
50 #define DCCOMP_TC7 7
51
52 /* Used for scaling FIR coefficients for HW */
53 #define DMIC_HW_FIR_COEF_MAX ((1 << (DMIC_HW_BITS_FIR_COEF - 1)) - 1)
54 #define DMIC_HW_FIR_COEF_Q (DMIC_HW_BITS_FIR_COEF - 1)
55
56 /* Internal precision in gains computation, e.g. Q4.28 in int32_t */
57 #define DMIC_FIR_SCALE_Q 28
58
59 /* Used in unmute ramp values calculation */
60 #define DMIC_HW_FIR_GAIN_MAX ((1 << (DMIC_HW_BITS_FIR_GAIN - 1)) - 1)
61
62 #define DB2LIN_FIXED_INPUT_QY 24
63 #define DB2LIN_FIXED_OUTPUT_QY 20
64
65 /* Hardcoded log ramp parameters. The default ramp is 100 ms for 48 kHz
66 * and 200 ms for 16 kHz. The first parameter is the initial gain in
67 * decibels, set to -90 dB.
68 * The rate dependent ramp duration is provided by 1st order equation
69 * duration = coef * samplerate + offset.
70 * E.g. 100 ms @ 48 kHz, 200 ms @ 16 kHz
71 * y48 = 100; y16 = 200;
72 * dy = y48 - y16; dx = 48000 - 16000;
73 * coef = round(dy/dx * 2^15)
74 * offs = round(y16 - coef/2^15 * 16000)
75 * Note: The rate dependence can be disabled with zero time_coef with
76 * use of just the offset.
77 */
78 #define LOGRAMP_START_DB Q_CONVERT_FLOAT(-90, DB2LIN_FIXED_INPUT_QY)
79 #define LOGRAMP_TIME_COEF_Q15 -102 /* coef = dy/dx */
80 #define LOGRAMP_TIME_OFFS_Q0 250 /* offs = Offset for line slope in ms */
81
82 /* Limits for ramp time from topology */
83 #define LOGRAMP_TIME_MIN_MS 10 /* Min. 10 ms */
84 #define LOGRAMP_TIME_MAX_MS 1000 /* Max. 1s */
85
86 /* Simplify log ramp step calculation equation with this constant term */
87 #define LOGRAMP_CONST_TERM ((int32_t) \
88 ((int64_t)-LOGRAMP_START_DB * DMIC_UNMUTE_RAMP_US / 1000))
89
90 /* Fractional shift for gain update. Gain format is Q2.30. */
91 #define Q_SHIFT_GAIN_X_GAIN_COEF \
92 (Q_SHIFT_BITS_32(30, DB2LIN_FIXED_OUTPUT_QY, 30))
93
94 /* Compute the number of shifts
95 * This will result in a compiler overflow error if shift bits are out of
96 * range as INT64_MAX/MIN is greater than 32 bit Q shift parameter
97 */
98 #define Q_SHIFT_BITS_64(qx, qy, qz) \
99 ((qx + qy - qz) <= 63 ? (((qx + qy - qz) >= 0) ? \
100 (qx + qy - qz) : INT64_MIN) : INT64_MAX)
101
102 #define Q_SHIFT_BITS_32(qx, qy, qz) \
103 ((qx + qy - qz) <= 31 ? (((qx + qy - qz) >= 0) ? \
104 (qx + qy - qz) : INT32_MIN) : INT32_MAX)
105
106 /* Fractional multiplication with shift and round
107 * Note that the parameters px and py must be cast to (int64_t) if other type.
108 */
109 #define Q_MULTSR_32X32(px, py, qx, qy, qp) \
110 ((((px) * (py) >> ((qx)+(qy)-(qp)-1)) + 1) >> 1)
111
112 /* A more clever macro for Q-shifts */
113 #define Q_SHIFT(x, src_q, dst_q) ((x) >> ((src_q) - (dst_q)))
114 #define Q_SHIFT_RND(x, src_q, dst_q) \
115 ((((x) >> ((src_q) - (dst_q) - 1)) + 1) >> 1)
116
117 /* Alternative version since compiler does not allow (x >> -1) */
118 #define Q_SHIFT_LEFT(x, src_q, dst_q) ((x) << ((dst_q) - (src_q)))
119
120 /* Convert a float number to fractional Qnx.ny format. Note that there is no
121 * check for nx+ny number of bits to fit the word length of int. The parameter
122 * qy must be 31 or less.
123 */
124 #define Q_CONVERT_FLOAT(f, qy) \
125 ((int32_t)(((const double)f) * ((int64_t)1 << (const int)qy) + 0.5))
126
127 #define TWO_Q27 Q_CONVERT_FLOAT(2.0, 27) /* Use Q5.27 */
128 #define MINUS_TWO_Q27 Q_CONVERT_FLOAT(-2.0, 27) /* Use Q5.27 */
129 #define ONE_Q20 Q_CONVERT_FLOAT(1.0, 20) /* Use Q12.20 */
130 #define ONE_Q23 Q_CONVERT_FLOAT(1.0, 23) /* Use Q9.23 */
131 #define LOG10_DIV20_Q27 Q_CONVERT_FLOAT(0.1151292546, 27) /* Use Q5.27 */
132
133 #define DMA_HANDSHAKE_DMIC_CH0 0
134 #define DMA_HANDSHAKE_DMIC_CH1 1
135
136 enum dai_dmic_frame_format {
137 DAI_DMIC_FRAME_S16_LE = 0,
138 DAI_DMIC_FRAME_S24_4LE,
139 DAI_DMIC_FRAME_S32_LE,
140 DAI_DMIC_FRAME_FLOAT,
141 /* other formats here */
142 DAI_DMIC_FRAME_S24_3LE,
143 };
144
145 /* Common data for all DMIC DAI instances */
146 struct dai_dmic_global_shared {
147 uint32_t active_fifos_mask; /* Bits (dai->index) are set to indicate active FIFO */
148 uint32_t pause_mask; /* Bits (dai->index) are set to indicate driver pause */
149 };
150
151 struct dai_dmic_plat_fifo_data {
152 uint32_t offset;
153 uint32_t width;
154 uint32_t depth;
155 uint32_t watermark;
156 uint32_t handshake;
157 };
158
159
160 struct dai_intel_dmic {
161 struct dai_config dai_config_params;
162
163 struct k_spinlock lock; /**< locking mechanism */
164 int sref; /**< simple ref counter, guarded by lock */
165 enum dai_state state; /* Driver component state */
166 uint16_t enable[CONFIG_DAI_DMIC_HW_CONTROLLERS];/* Mic 0 and 1 enable bits array for PDMx */
167 struct dai_dmic_plat_fifo_data fifo; /* dmic capture fifo stream */
168 int32_t gain_coef; /* Gain update constant */
169 int32_t gain; /* Gain value to be applied to HW */
170 int32_t startcount; /* Counter that controls HW unmute */
171 int32_t unmute_time_ms; /* Unmute ramp time in milliseconds */
172
173 /* hardware parameters */
174 uint32_t reg_base;
175 uint32_t shim_base;
176 #if defined(CONFIG_SOC_INTEL_ACE20_LNL) || defined(CONFIG_SOC_INTEL_ACE30_PTL)
177 uint32_t hdamldmic_base;
178 uint32_t vshim_base;
179 #endif
180 int irq;
181 uint32_t flags;
182 uint32_t gain_left;
183 uint32_t gain_right;
184 };
185
sat_int32(int64_t x)186 static inline int32_t sat_int32(int64_t x)
187 {
188 if (x > INT32_MAX)
189 return INT32_MAX;
190 else if (x < INT32_MIN)
191 return INT32_MIN;
192 else
193 return (int32_t)x;
194 }
195 /* Fractional multiplication with shift and saturation */
q_multsr_sat_32x32(int32_t x,int32_t y,const int shift_bits)196 static inline int32_t q_multsr_sat_32x32(int32_t x, int32_t y,
197 const int shift_bits)
198 {
199 return sat_int32(((((int64_t)x * y) >> (shift_bits - 1)) + 1) >> 1);
200 }
201
dmic_get_unmute_ramp_from_samplerate(int rate)202 static inline int dmic_get_unmute_ramp_from_samplerate(int rate)
203 {
204 int time_ms;
205
206 time_ms = Q_MULTSR_32X32((int32_t)rate, LOGRAMP_TIME_COEF_Q15, 0, 15, 0) +
207 LOGRAMP_TIME_OFFS_Q0;
208 if (time_ms > LOGRAMP_TIME_MAX_MS)
209 return LOGRAMP_TIME_MAX_MS;
210
211 if (time_ms < LOGRAMP_TIME_MIN_MS)
212 return LOGRAMP_TIME_MIN_MS;
213
214 return time_ms;
215 }
216
217 #endif /* __INTEL_DAI_DRIVER_DMIC_H__ */
218