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