1 | // SPDX-License-Identifier: GPL-2.0-only |
2 | // Copyright (c) 2018-2020, The Linux Foundation. All rights reserved. |
3 | |
4 | #include <linux/clk.h> |
5 | #include <linux/clk-provider.h> |
6 | #include <linux/init.h> |
7 | #include <linux/io.h> |
8 | #include <linux/module.h> |
9 | #include <linux/of_clk.h> |
10 | #include <linux/of_platform.h> |
11 | #include <linux/platform_device.h> |
12 | #include <linux/pm_runtime.h> |
13 | #include <linux/regmap.h> |
14 | #include <linux/regulator/consumer.h> |
15 | #include <sound/soc.h> |
16 | #include <sound/soc-dapm.h> |
17 | #include <sound/tlv.h> |
18 | |
19 | #include "lpass-macro-common.h" |
20 | |
21 | /* VA macro registers */ |
22 | #define CDC_VA_CLK_RST_CTRL_MCLK_CONTROL (0x0000) |
23 | #define CDC_VA_MCLK_CONTROL_EN BIT(0) |
24 | #define CDC_VA_CLK_RST_CTRL_FS_CNT_CONTROL (0x0004) |
25 | #define CDC_VA_FS_CONTROL_EN BIT(0) |
26 | #define CDC_VA_FS_COUNTER_CLR BIT(1) |
27 | #define CDC_VA_CLK_RST_CTRL_SWR_CONTROL (0x0008) |
28 | #define CDC_VA_SWR_RESET_MASK BIT(1) |
29 | #define CDC_VA_SWR_RESET_ENABLE BIT(1) |
30 | #define CDC_VA_SWR_CLK_EN_MASK BIT(0) |
31 | #define CDC_VA_SWR_CLK_ENABLE BIT(0) |
32 | #define CDC_VA_TOP_CSR_TOP_CFG0 (0x0080) |
33 | #define CDC_VA_FS_BROADCAST_EN BIT(1) |
34 | #define CDC_VA_TOP_CSR_DMIC0_CTL (0x0084) |
35 | #define CDC_VA_TOP_CSR_DMIC1_CTL (0x0088) |
36 | #define CDC_VA_TOP_CSR_DMIC2_CTL (0x008C) |
37 | #define CDC_VA_TOP_CSR_DMIC3_CTL (0x0090) |
38 | #define CDC_VA_DMIC_EN_MASK BIT(0) |
39 | #define CDC_VA_DMIC_ENABLE BIT(0) |
40 | #define CDC_VA_DMIC_CLK_SEL_MASK GENMASK(3, 1) |
41 | #define CDC_VA_DMIC_CLK_SEL_SHFT 1 |
42 | #define CDC_VA_DMIC_CLK_SEL_DIV0 0x0 |
43 | #define CDC_VA_DMIC_CLK_SEL_DIV1 0x2 |
44 | #define CDC_VA_DMIC_CLK_SEL_DIV2 0x4 |
45 | #define CDC_VA_DMIC_CLK_SEL_DIV3 0x6 |
46 | #define CDC_VA_DMIC_CLK_SEL_DIV4 0x8 |
47 | #define CDC_VA_DMIC_CLK_SEL_DIV5 0xa |
48 | #define CDC_VA_TOP_CSR_DMIC_CFG (0x0094) |
49 | #define CDC_VA_RESET_ALL_DMICS_MASK BIT(7) |
50 | #define CDC_VA_RESET_ALL_DMICS_RESET BIT(7) |
51 | #define CDC_VA_RESET_ALL_DMICS_DISABLE 0 |
52 | #define CDC_VA_DMIC3_FREQ_CHANGE_MASK BIT(3) |
53 | #define CDC_VA_DMIC3_FREQ_CHANGE_EN BIT(3) |
54 | #define CDC_VA_DMIC2_FREQ_CHANGE_MASK BIT(2) |
55 | #define CDC_VA_DMIC2_FREQ_CHANGE_EN BIT(2) |
56 | #define CDC_VA_DMIC1_FREQ_CHANGE_MASK BIT(1) |
57 | #define CDC_VA_DMIC1_FREQ_CHANGE_EN BIT(1) |
58 | #define CDC_VA_DMIC0_FREQ_CHANGE_MASK BIT(0) |
59 | #define CDC_VA_DMIC0_FREQ_CHANGE_EN BIT(0) |
60 | #define CDC_VA_DMIC_FREQ_CHANGE_DISABLE 0 |
61 | #define CDC_VA_TOP_CSR_DEBUG_BUS (0x009C) |
62 | #define CDC_VA_TOP_CSR_DEBUG_EN (0x00A0) |
63 | #define CDC_VA_TOP_CSR_TX_I2S_CTL (0x00A4) |
64 | #define CDC_VA_TOP_CSR_I2S_CLK (0x00A8) |
65 | #define CDC_VA_TOP_CSR_I2S_RESET (0x00AC) |
66 | #define CDC_VA_TOP_CSR_CORE_ID_0 (0x00C0) |
67 | #define CDC_VA_TOP_CSR_CORE_ID_1 (0x00C4) |
68 | #define CDC_VA_TOP_CSR_CORE_ID_2 (0x00C8) |
69 | #define CDC_VA_TOP_CSR_CORE_ID_3 (0x00CC) |
70 | #define CDC_VA_TOP_CSR_SWR_MIC_CTL0 (0x00D0) |
71 | #define CDC_VA_TOP_CSR_SWR_MIC_CTL1 (0x00D4) |
72 | #define CDC_VA_TOP_CSR_SWR_MIC_CTL2 (0x00D8) |
73 | #define CDC_VA_SWR_MIC_CLK_SEL_0_1_MASK (0xEE) |
74 | #define CDC_VA_SWR_MIC_CLK_SEL_0_1_DIV1 (0xCC) |
75 | #define CDC_VA_TOP_CSR_SWR_CTRL (0x00DC) |
76 | #define CDC_VA_INP_MUX_ADC_MUX0_CFG0 (0x0100) |
77 | #define CDC_VA_INP_MUX_ADC_MUX0_CFG1 (0x0104) |
78 | #define CDC_VA_INP_MUX_ADC_MUX1_CFG0 (0x0108) |
79 | #define CDC_VA_INP_MUX_ADC_MUX1_CFG1 (0x010C) |
80 | #define CDC_VA_INP_MUX_ADC_MUX2_CFG0 (0x0110) |
81 | #define CDC_VA_INP_MUX_ADC_MUX2_CFG1 (0x0114) |
82 | #define CDC_VA_INP_MUX_ADC_MUX3_CFG0 (0x0118) |
83 | #define CDC_VA_INP_MUX_ADC_MUX3_CFG1 (0x011C) |
84 | #define CDC_VA_TX0_TX_PATH_CTL (0x0400) |
85 | #define CDC_VA_TX_PATH_CLK_EN_MASK BIT(5) |
86 | #define CDC_VA_TX_PATH_CLK_EN BIT(5) |
87 | #define CDC_VA_TX_PATH_CLK_DISABLE 0 |
88 | #define CDC_VA_TX_PATH_PGA_MUTE_EN_MASK BIT(4) |
89 | #define CDC_VA_TX_PATH_PGA_MUTE_EN BIT(4) |
90 | #define CDC_VA_TX_PATH_PGA_MUTE_DISABLE 0 |
91 | #define CDC_VA_TX0_TX_PATH_CFG0 (0x0404) |
92 | #define CDC_VA_ADC_MODE_MASK GENMASK(2, 1) |
93 | #define CDC_VA_ADC_MODE_SHIFT 1 |
94 | #define TX_HPF_CUT_OFF_FREQ_MASK GENMASK(6, 5) |
95 | #define CF_MIN_3DB_4HZ 0x0 |
96 | #define CF_MIN_3DB_75HZ 0x1 |
97 | #define CF_MIN_3DB_150HZ 0x2 |
98 | #define CDC_VA_TX0_TX_PATH_CFG1 (0x0408) |
99 | #define CDC_VA_TX0_TX_VOL_CTL (0x040C) |
100 | #define CDC_VA_TX0_TX_PATH_SEC0 (0x0410) |
101 | #define CDC_VA_TX0_TX_PATH_SEC1 (0x0414) |
102 | #define CDC_VA_TX0_TX_PATH_SEC2 (0x0418) |
103 | #define CDC_VA_TX_HPF_CUTOFF_FREQ_CHANGE_MASK BIT(1) |
104 | #define CDC_VA_TX_HPF_CUTOFF_FREQ_CHANGE_REQ BIT(1) |
105 | #define CDC_VA_TX_HPF_ZERO_GATE_MASK BIT(0) |
106 | #define CDC_VA_TX_HPF_ZERO_NO_GATE BIT(0) |
107 | #define CDC_VA_TX_HPF_ZERO_GATE 0 |
108 | #define CDC_VA_TX0_TX_PATH_SEC3 (0x041C) |
109 | #define CDC_VA_TX0_TX_PATH_SEC4 (0x0420) |
110 | #define CDC_VA_TX0_TX_PATH_SEC5 (0x0424) |
111 | #define CDC_VA_TX0_TX_PATH_SEC6 (0x0428) |
112 | #define CDC_VA_TX0_TX_PATH_SEC7 (0x042C) |
113 | #define CDC_VA_TX1_TX_PATH_CTL (0x0480) |
114 | #define CDC_VA_TX1_TX_PATH_CFG0 (0x0484) |
115 | #define CDC_VA_TX1_TX_PATH_CFG1 (0x0488) |
116 | #define CDC_VA_TX1_TX_VOL_CTL (0x048C) |
117 | #define CDC_VA_TX1_TX_PATH_SEC0 (0x0490) |
118 | #define CDC_VA_TX1_TX_PATH_SEC1 (0x0494) |
119 | #define CDC_VA_TX1_TX_PATH_SEC2 (0x0498) |
120 | #define CDC_VA_TX1_TX_PATH_SEC3 (0x049C) |
121 | #define CDC_VA_TX1_TX_PATH_SEC4 (0x04A0) |
122 | #define CDC_VA_TX1_TX_PATH_SEC5 (0x04A4) |
123 | #define CDC_VA_TX1_TX_PATH_SEC6 (0x04A8) |
124 | #define CDC_VA_TX2_TX_PATH_CTL (0x0500) |
125 | #define CDC_VA_TX2_TX_PATH_CFG0 (0x0504) |
126 | #define CDC_VA_TX2_TX_PATH_CFG1 (0x0508) |
127 | #define CDC_VA_TX2_TX_VOL_CTL (0x050C) |
128 | #define CDC_VA_TX2_TX_PATH_SEC0 (0x0510) |
129 | #define CDC_VA_TX2_TX_PATH_SEC1 (0x0514) |
130 | #define CDC_VA_TX2_TX_PATH_SEC2 (0x0518) |
131 | #define CDC_VA_TX2_TX_PATH_SEC3 (0x051C) |
132 | #define CDC_VA_TX2_TX_PATH_SEC4 (0x0520) |
133 | #define CDC_VA_TX2_TX_PATH_SEC5 (0x0524) |
134 | #define CDC_VA_TX2_TX_PATH_SEC6 (0x0528) |
135 | #define CDC_VA_TX3_TX_PATH_CTL (0x0580) |
136 | #define CDC_VA_TX3_TX_PATH_CFG0 (0x0584) |
137 | #define CDC_VA_TX_PATH_ADC_DMIC_SEL_MASK BIT(7) |
138 | #define CDC_VA_TX_PATH_ADC_DMIC_SEL_DMIC BIT(7) |
139 | #define CDC_VA_TX_PATH_ADC_DMIC_SEL_ADC 0 |
140 | #define CDC_VA_TX3_TX_PATH_CFG1 (0x0588) |
141 | #define CDC_VA_TX3_TX_VOL_CTL (0x058C) |
142 | #define CDC_VA_TX3_TX_PATH_SEC0 (0x0590) |
143 | #define CDC_VA_TX3_TX_PATH_SEC1 (0x0594) |
144 | #define CDC_VA_TX3_TX_PATH_SEC2 (0x0598) |
145 | #define CDC_VA_TX3_TX_PATH_SEC3 (0x059C) |
146 | #define CDC_VA_TX3_TX_PATH_SEC4 (0x05A0) |
147 | #define CDC_VA_TX3_TX_PATH_SEC5 (0x05A4) |
148 | #define CDC_VA_TX3_TX_PATH_SEC6 (0x05A8) |
149 | |
150 | #define VA_MAX_OFFSET (0x07A8) |
151 | |
152 | #define VA_MACRO_NUM_DECIMATORS 4 |
153 | #define VA_MACRO_RATES (SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_16000 |\ |
154 | SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_48000 |\ |
155 | SNDRV_PCM_RATE_96000 | SNDRV_PCM_RATE_192000) |
156 | #define VA_MACRO_FORMATS (SNDRV_PCM_FMTBIT_S16_LE |\ |
157 | SNDRV_PCM_FMTBIT_S24_LE |\ |
158 | SNDRV_PCM_FMTBIT_S24_3LE) |
159 | |
160 | #define VA_MACRO_MCLK_FREQ 9600000 |
161 | #define VA_MACRO_TX_PATH_OFFSET 0x80 |
162 | #define VA_MACRO_SWR_MIC_MUX_SEL_MASK 0xF |
163 | #define VA_MACRO_ADC_MUX_CFG_OFFSET 0x8 |
164 | |
165 | static const DECLARE_TLV_DB_SCALE(digital_gain, -8400, 100, -8400); |
166 | |
167 | enum { |
168 | VA_MACRO_AIF_INVALID = 0, |
169 | VA_MACRO_AIF1_CAP, |
170 | VA_MACRO_AIF2_CAP, |
171 | VA_MACRO_AIF3_CAP, |
172 | VA_MACRO_MAX_DAIS, |
173 | }; |
174 | |
175 | enum { |
176 | VA_MACRO_DEC0, |
177 | VA_MACRO_DEC1, |
178 | VA_MACRO_DEC2, |
179 | VA_MACRO_DEC3, |
180 | VA_MACRO_DEC4, |
181 | VA_MACRO_DEC5, |
182 | VA_MACRO_DEC6, |
183 | VA_MACRO_DEC7, |
184 | VA_MACRO_DEC_MAX, |
185 | }; |
186 | |
187 | enum { |
188 | VA_MACRO_CLK_DIV_2, |
189 | VA_MACRO_CLK_DIV_3, |
190 | VA_MACRO_CLK_DIV_4, |
191 | VA_MACRO_CLK_DIV_6, |
192 | VA_MACRO_CLK_DIV_8, |
193 | VA_MACRO_CLK_DIV_16, |
194 | }; |
195 | |
196 | #define VA_NUM_CLKS_MAX 3 |
197 | |
198 | struct va_macro { |
199 | struct device *dev; |
200 | unsigned long active_ch_mask[VA_MACRO_MAX_DAIS]; |
201 | unsigned long active_ch_cnt[VA_MACRO_MAX_DAIS]; |
202 | u16 dmic_clk_div; |
203 | bool has_swr_master; |
204 | bool has_npl_clk; |
205 | |
206 | int dec_mode[VA_MACRO_NUM_DECIMATORS]; |
207 | struct regmap *regmap; |
208 | struct clk *mclk; |
209 | struct clk *npl; |
210 | struct clk *macro; |
211 | struct clk *dcodec; |
212 | struct clk *fsgen; |
213 | struct clk_hw hw; |
214 | struct lpass_macro *pds; |
215 | |
216 | s32 dmic_0_1_clk_cnt; |
217 | s32 dmic_2_3_clk_cnt; |
218 | s32 dmic_4_5_clk_cnt; |
219 | s32 dmic_6_7_clk_cnt; |
220 | u8 dmic_0_1_clk_div; |
221 | u8 dmic_2_3_clk_div; |
222 | u8 dmic_4_5_clk_div; |
223 | u8 dmic_6_7_clk_div; |
224 | }; |
225 | |
226 | #define to_va_macro(_hw) container_of(_hw, struct va_macro, hw) |
227 | |
228 | struct va_macro_data { |
229 | bool has_swr_master; |
230 | bool has_npl_clk; |
231 | }; |
232 | |
233 | static const struct va_macro_data sm8250_va_data = { |
234 | .has_swr_master = false, |
235 | .has_npl_clk = false, |
236 | }; |
237 | |
238 | static const struct va_macro_data sm8450_va_data = { |
239 | .has_swr_master = true, |
240 | .has_npl_clk = true, |
241 | }; |
242 | |
243 | static const struct va_macro_data sm8550_va_data = { |
244 | .has_swr_master = true, |
245 | .has_npl_clk = false, |
246 | }; |
247 | |
248 | static bool va_is_volatile_register(struct device *dev, unsigned int reg) |
249 | { |
250 | switch (reg) { |
251 | case CDC_VA_TOP_CSR_CORE_ID_0: |
252 | case CDC_VA_TOP_CSR_CORE_ID_1: |
253 | case CDC_VA_TOP_CSR_CORE_ID_2: |
254 | case CDC_VA_TOP_CSR_CORE_ID_3: |
255 | case CDC_VA_TOP_CSR_DMIC0_CTL: |
256 | case CDC_VA_TOP_CSR_DMIC1_CTL: |
257 | case CDC_VA_TOP_CSR_DMIC2_CTL: |
258 | case CDC_VA_TOP_CSR_DMIC3_CTL: |
259 | return true; |
260 | } |
261 | return false; |
262 | } |
263 | |
264 | static const struct reg_default va_defaults[] = { |
265 | /* VA macro */ |
266 | { CDC_VA_CLK_RST_CTRL_MCLK_CONTROL, 0x00}, |
267 | { CDC_VA_CLK_RST_CTRL_FS_CNT_CONTROL, 0x00}, |
268 | { CDC_VA_CLK_RST_CTRL_SWR_CONTROL, 0x00}, |
269 | { CDC_VA_TOP_CSR_TOP_CFG0, 0x00}, |
270 | { CDC_VA_TOP_CSR_DMIC0_CTL, 0x00}, |
271 | { CDC_VA_TOP_CSR_DMIC1_CTL, 0x00}, |
272 | { CDC_VA_TOP_CSR_DMIC2_CTL, 0x00}, |
273 | { CDC_VA_TOP_CSR_DMIC3_CTL, 0x00}, |
274 | { CDC_VA_TOP_CSR_DMIC_CFG, 0x80}, |
275 | { CDC_VA_TOP_CSR_DEBUG_BUS, 0x00}, |
276 | { CDC_VA_TOP_CSR_DEBUG_EN, 0x00}, |
277 | { CDC_VA_TOP_CSR_TX_I2S_CTL, 0x0C}, |
278 | { CDC_VA_TOP_CSR_I2S_CLK, 0x00}, |
279 | { CDC_VA_TOP_CSR_I2S_RESET, 0x00}, |
280 | { CDC_VA_TOP_CSR_CORE_ID_0, 0x00}, |
281 | { CDC_VA_TOP_CSR_CORE_ID_1, 0x00}, |
282 | { CDC_VA_TOP_CSR_CORE_ID_2, 0x00}, |
283 | { CDC_VA_TOP_CSR_CORE_ID_3, 0x00}, |
284 | { CDC_VA_TOP_CSR_SWR_MIC_CTL0, 0xEE}, |
285 | { CDC_VA_TOP_CSR_SWR_MIC_CTL1, 0xEE}, |
286 | { CDC_VA_TOP_CSR_SWR_MIC_CTL2, 0xEE}, |
287 | { CDC_VA_TOP_CSR_SWR_CTRL, 0x06}, |
288 | |
289 | /* VA core */ |
290 | { CDC_VA_INP_MUX_ADC_MUX0_CFG0, 0x00}, |
291 | { CDC_VA_INP_MUX_ADC_MUX0_CFG1, 0x00}, |
292 | { CDC_VA_INP_MUX_ADC_MUX1_CFG0, 0x00}, |
293 | { CDC_VA_INP_MUX_ADC_MUX1_CFG1, 0x00}, |
294 | { CDC_VA_INP_MUX_ADC_MUX2_CFG0, 0x00}, |
295 | { CDC_VA_INP_MUX_ADC_MUX2_CFG1, 0x00}, |
296 | { CDC_VA_INP_MUX_ADC_MUX3_CFG0, 0x00}, |
297 | { CDC_VA_INP_MUX_ADC_MUX3_CFG1, 0x00}, |
298 | { CDC_VA_TX0_TX_PATH_CTL, 0x04}, |
299 | { CDC_VA_TX0_TX_PATH_CFG0, 0x10}, |
300 | { CDC_VA_TX0_TX_PATH_CFG1, 0x0B}, |
301 | { CDC_VA_TX0_TX_VOL_CTL, 0x00}, |
302 | { CDC_VA_TX0_TX_PATH_SEC0, 0x00}, |
303 | { CDC_VA_TX0_TX_PATH_SEC1, 0x00}, |
304 | { CDC_VA_TX0_TX_PATH_SEC2, 0x01}, |
305 | { CDC_VA_TX0_TX_PATH_SEC3, 0x3C}, |
306 | { CDC_VA_TX0_TX_PATH_SEC4, 0x20}, |
307 | { CDC_VA_TX0_TX_PATH_SEC5, 0x00}, |
308 | { CDC_VA_TX0_TX_PATH_SEC6, 0x00}, |
309 | { CDC_VA_TX0_TX_PATH_SEC7, 0x25}, |
310 | { CDC_VA_TX1_TX_PATH_CTL, 0x04}, |
311 | { CDC_VA_TX1_TX_PATH_CFG0, 0x10}, |
312 | { CDC_VA_TX1_TX_PATH_CFG1, 0x0B}, |
313 | { CDC_VA_TX1_TX_VOL_CTL, 0x00}, |
314 | { CDC_VA_TX1_TX_PATH_SEC0, 0x00}, |
315 | { CDC_VA_TX1_TX_PATH_SEC1, 0x00}, |
316 | { CDC_VA_TX1_TX_PATH_SEC2, 0x01}, |
317 | { CDC_VA_TX1_TX_PATH_SEC3, 0x3C}, |
318 | { CDC_VA_TX1_TX_PATH_SEC4, 0x20}, |
319 | { CDC_VA_TX1_TX_PATH_SEC5, 0x00}, |
320 | { CDC_VA_TX1_TX_PATH_SEC6, 0x00}, |
321 | { CDC_VA_TX2_TX_PATH_CTL, 0x04}, |
322 | { CDC_VA_TX2_TX_PATH_CFG0, 0x10}, |
323 | { CDC_VA_TX2_TX_PATH_CFG1, 0x0B}, |
324 | { CDC_VA_TX2_TX_VOL_CTL, 0x00}, |
325 | { CDC_VA_TX2_TX_PATH_SEC0, 0x00}, |
326 | { CDC_VA_TX2_TX_PATH_SEC1, 0x00}, |
327 | { CDC_VA_TX2_TX_PATH_SEC2, 0x01}, |
328 | { CDC_VA_TX2_TX_PATH_SEC3, 0x3C}, |
329 | { CDC_VA_TX2_TX_PATH_SEC4, 0x20}, |
330 | { CDC_VA_TX2_TX_PATH_SEC5, 0x00}, |
331 | { CDC_VA_TX2_TX_PATH_SEC6, 0x00}, |
332 | { CDC_VA_TX3_TX_PATH_CTL, 0x04}, |
333 | { CDC_VA_TX3_TX_PATH_CFG0, 0x10}, |
334 | { CDC_VA_TX3_TX_PATH_CFG1, 0x0B}, |
335 | { CDC_VA_TX3_TX_VOL_CTL, 0x00}, |
336 | { CDC_VA_TX3_TX_PATH_SEC0, 0x00}, |
337 | { CDC_VA_TX3_TX_PATH_SEC1, 0x00}, |
338 | { CDC_VA_TX3_TX_PATH_SEC2, 0x01}, |
339 | { CDC_VA_TX3_TX_PATH_SEC3, 0x3C}, |
340 | { CDC_VA_TX3_TX_PATH_SEC4, 0x20}, |
341 | { CDC_VA_TX3_TX_PATH_SEC5, 0x00}, |
342 | { CDC_VA_TX3_TX_PATH_SEC6, 0x00}, |
343 | }; |
344 | |
345 | static bool va_is_rw_register(struct device *dev, unsigned int reg) |
346 | { |
347 | switch (reg) { |
348 | case CDC_VA_CLK_RST_CTRL_MCLK_CONTROL: |
349 | case CDC_VA_CLK_RST_CTRL_FS_CNT_CONTROL: |
350 | case CDC_VA_CLK_RST_CTRL_SWR_CONTROL: |
351 | case CDC_VA_TOP_CSR_TOP_CFG0: |
352 | case CDC_VA_TOP_CSR_DMIC0_CTL: |
353 | case CDC_VA_TOP_CSR_DMIC1_CTL: |
354 | case CDC_VA_TOP_CSR_DMIC2_CTL: |
355 | case CDC_VA_TOP_CSR_DMIC3_CTL: |
356 | case CDC_VA_TOP_CSR_DMIC_CFG: |
357 | case CDC_VA_TOP_CSR_SWR_MIC_CTL0: |
358 | case CDC_VA_TOP_CSR_SWR_MIC_CTL1: |
359 | case CDC_VA_TOP_CSR_SWR_MIC_CTL2: |
360 | case CDC_VA_TOP_CSR_DEBUG_BUS: |
361 | case CDC_VA_TOP_CSR_DEBUG_EN: |
362 | case CDC_VA_TOP_CSR_TX_I2S_CTL: |
363 | case CDC_VA_TOP_CSR_I2S_CLK: |
364 | case CDC_VA_TOP_CSR_I2S_RESET: |
365 | case CDC_VA_INP_MUX_ADC_MUX0_CFG0: |
366 | case CDC_VA_INP_MUX_ADC_MUX0_CFG1: |
367 | case CDC_VA_INP_MUX_ADC_MUX1_CFG0: |
368 | case CDC_VA_INP_MUX_ADC_MUX1_CFG1: |
369 | case CDC_VA_INP_MUX_ADC_MUX2_CFG0: |
370 | case CDC_VA_INP_MUX_ADC_MUX2_CFG1: |
371 | case CDC_VA_INP_MUX_ADC_MUX3_CFG0: |
372 | case CDC_VA_INP_MUX_ADC_MUX3_CFG1: |
373 | case CDC_VA_TX0_TX_PATH_CTL: |
374 | case CDC_VA_TX0_TX_PATH_CFG0: |
375 | case CDC_VA_TX0_TX_PATH_CFG1: |
376 | case CDC_VA_TX0_TX_VOL_CTL: |
377 | case CDC_VA_TX0_TX_PATH_SEC0: |
378 | case CDC_VA_TX0_TX_PATH_SEC1: |
379 | case CDC_VA_TX0_TX_PATH_SEC2: |
380 | case CDC_VA_TX0_TX_PATH_SEC3: |
381 | case CDC_VA_TX0_TX_PATH_SEC4: |
382 | case CDC_VA_TX0_TX_PATH_SEC5: |
383 | case CDC_VA_TX0_TX_PATH_SEC6: |
384 | case CDC_VA_TX0_TX_PATH_SEC7: |
385 | case CDC_VA_TX1_TX_PATH_CTL: |
386 | case CDC_VA_TX1_TX_PATH_CFG0: |
387 | case CDC_VA_TX1_TX_PATH_CFG1: |
388 | case CDC_VA_TX1_TX_VOL_CTL: |
389 | case CDC_VA_TX1_TX_PATH_SEC0: |
390 | case CDC_VA_TX1_TX_PATH_SEC1: |
391 | case CDC_VA_TX1_TX_PATH_SEC2: |
392 | case CDC_VA_TX1_TX_PATH_SEC3: |
393 | case CDC_VA_TX1_TX_PATH_SEC4: |
394 | case CDC_VA_TX1_TX_PATH_SEC5: |
395 | case CDC_VA_TX1_TX_PATH_SEC6: |
396 | case CDC_VA_TX2_TX_PATH_CTL: |
397 | case CDC_VA_TX2_TX_PATH_CFG0: |
398 | case CDC_VA_TX2_TX_PATH_CFG1: |
399 | case CDC_VA_TX2_TX_VOL_CTL: |
400 | case CDC_VA_TX2_TX_PATH_SEC0: |
401 | case CDC_VA_TX2_TX_PATH_SEC1: |
402 | case CDC_VA_TX2_TX_PATH_SEC2: |
403 | case CDC_VA_TX2_TX_PATH_SEC3: |
404 | case CDC_VA_TX2_TX_PATH_SEC4: |
405 | case CDC_VA_TX2_TX_PATH_SEC5: |
406 | case CDC_VA_TX2_TX_PATH_SEC6: |
407 | case CDC_VA_TX3_TX_PATH_CTL: |
408 | case CDC_VA_TX3_TX_PATH_CFG0: |
409 | case CDC_VA_TX3_TX_PATH_CFG1: |
410 | case CDC_VA_TX3_TX_VOL_CTL: |
411 | case CDC_VA_TX3_TX_PATH_SEC0: |
412 | case CDC_VA_TX3_TX_PATH_SEC1: |
413 | case CDC_VA_TX3_TX_PATH_SEC2: |
414 | case CDC_VA_TX3_TX_PATH_SEC3: |
415 | case CDC_VA_TX3_TX_PATH_SEC4: |
416 | case CDC_VA_TX3_TX_PATH_SEC5: |
417 | case CDC_VA_TX3_TX_PATH_SEC6: |
418 | return true; |
419 | } |
420 | |
421 | return false; |
422 | } |
423 | |
424 | static bool va_is_readable_register(struct device *dev, unsigned int reg) |
425 | { |
426 | switch (reg) { |
427 | case CDC_VA_TOP_CSR_CORE_ID_0: |
428 | case CDC_VA_TOP_CSR_CORE_ID_1: |
429 | case CDC_VA_TOP_CSR_CORE_ID_2: |
430 | case CDC_VA_TOP_CSR_CORE_ID_3: |
431 | return true; |
432 | } |
433 | |
434 | return va_is_rw_register(dev, reg); |
435 | } |
436 | |
437 | static const struct regmap_config va_regmap_config = { |
438 | .name = "va_macro" , |
439 | .reg_bits = 32, |
440 | .val_bits = 32, |
441 | .reg_stride = 4, |
442 | .cache_type = REGCACHE_FLAT, |
443 | .reg_defaults = va_defaults, |
444 | .num_reg_defaults = ARRAY_SIZE(va_defaults), |
445 | .max_register = VA_MAX_OFFSET, |
446 | .volatile_reg = va_is_volatile_register, |
447 | .readable_reg = va_is_readable_register, |
448 | .writeable_reg = va_is_rw_register, |
449 | }; |
450 | |
451 | static int va_clk_rsc_fs_gen_request(struct va_macro *va, bool enable) |
452 | { |
453 | struct regmap *regmap = va->regmap; |
454 | |
455 | if (enable) { |
456 | regmap_update_bits(map: regmap, CDC_VA_CLK_RST_CTRL_MCLK_CONTROL, |
457 | CDC_VA_MCLK_CONTROL_EN, |
458 | CDC_VA_MCLK_CONTROL_EN); |
459 | /* clear the fs counter */ |
460 | regmap_update_bits(map: regmap, CDC_VA_CLK_RST_CTRL_FS_CNT_CONTROL, |
461 | CDC_VA_FS_CONTROL_EN | CDC_VA_FS_COUNTER_CLR, |
462 | CDC_VA_FS_CONTROL_EN | CDC_VA_FS_COUNTER_CLR); |
463 | regmap_update_bits(map: regmap, CDC_VA_CLK_RST_CTRL_FS_CNT_CONTROL, |
464 | CDC_VA_FS_CONTROL_EN | CDC_VA_FS_COUNTER_CLR, |
465 | CDC_VA_FS_CONTROL_EN); |
466 | |
467 | regmap_update_bits(map: regmap, CDC_VA_TOP_CSR_TOP_CFG0, |
468 | CDC_VA_FS_BROADCAST_EN, |
469 | CDC_VA_FS_BROADCAST_EN); |
470 | } else { |
471 | regmap_update_bits(map: regmap, CDC_VA_CLK_RST_CTRL_MCLK_CONTROL, |
472 | CDC_VA_MCLK_CONTROL_EN, val: 0x0); |
473 | |
474 | regmap_update_bits(map: regmap, CDC_VA_CLK_RST_CTRL_FS_CNT_CONTROL, |
475 | CDC_VA_FS_CONTROL_EN, val: 0x0); |
476 | |
477 | regmap_update_bits(map: regmap, CDC_VA_TOP_CSR_TOP_CFG0, |
478 | CDC_VA_FS_BROADCAST_EN, val: 0x0); |
479 | } |
480 | |
481 | return 0; |
482 | } |
483 | |
484 | static int va_macro_mclk_enable(struct va_macro *va, bool mclk_enable) |
485 | { |
486 | struct regmap *regmap = va->regmap; |
487 | |
488 | if (mclk_enable) { |
489 | va_clk_rsc_fs_gen_request(va, enable: true); |
490 | regcache_mark_dirty(map: regmap); |
491 | regcache_sync_region(map: regmap, min: 0x0, VA_MAX_OFFSET); |
492 | } else { |
493 | va_clk_rsc_fs_gen_request(va, enable: false); |
494 | } |
495 | |
496 | return 0; |
497 | } |
498 | |
499 | static int va_macro_mclk_event(struct snd_soc_dapm_widget *w, |
500 | struct snd_kcontrol *kcontrol, int event) |
501 | { |
502 | struct snd_soc_component *comp = snd_soc_dapm_to_component(dapm: w->dapm); |
503 | struct va_macro *va = snd_soc_component_get_drvdata(c: comp); |
504 | |
505 | switch (event) { |
506 | case SND_SOC_DAPM_PRE_PMU: |
507 | return clk_prepare_enable(clk: va->fsgen); |
508 | case SND_SOC_DAPM_POST_PMD: |
509 | clk_disable_unprepare(clk: va->fsgen); |
510 | } |
511 | |
512 | return 0; |
513 | } |
514 | |
515 | static int va_macro_put_dec_enum(struct snd_kcontrol *kcontrol, |
516 | struct snd_ctl_elem_value *ucontrol) |
517 | { |
518 | struct snd_soc_dapm_widget *widget = |
519 | snd_soc_dapm_kcontrol_widget(kcontrol); |
520 | struct snd_soc_component *component = |
521 | snd_soc_dapm_to_component(dapm: widget->dapm); |
522 | struct soc_enum *e = (struct soc_enum *)kcontrol->private_value; |
523 | unsigned int val; |
524 | u16 mic_sel_reg; |
525 | |
526 | val = ucontrol->value.enumerated.item[0]; |
527 | |
528 | switch (e->reg) { |
529 | case CDC_VA_INP_MUX_ADC_MUX0_CFG0: |
530 | mic_sel_reg = CDC_VA_TX0_TX_PATH_CFG0; |
531 | break; |
532 | case CDC_VA_INP_MUX_ADC_MUX1_CFG0: |
533 | mic_sel_reg = CDC_VA_TX1_TX_PATH_CFG0; |
534 | break; |
535 | case CDC_VA_INP_MUX_ADC_MUX2_CFG0: |
536 | mic_sel_reg = CDC_VA_TX2_TX_PATH_CFG0; |
537 | break; |
538 | case CDC_VA_INP_MUX_ADC_MUX3_CFG0: |
539 | mic_sel_reg = CDC_VA_TX3_TX_PATH_CFG0; |
540 | break; |
541 | default: |
542 | dev_err(component->dev, "%s: e->reg: 0x%x not expected\n" , |
543 | __func__, e->reg); |
544 | return -EINVAL; |
545 | } |
546 | |
547 | if (val != 0) |
548 | snd_soc_component_update_bits(component, reg: mic_sel_reg, |
549 | CDC_VA_TX_PATH_ADC_DMIC_SEL_MASK, |
550 | CDC_VA_TX_PATH_ADC_DMIC_SEL_DMIC); |
551 | |
552 | return snd_soc_dapm_put_enum_double(kcontrol, ucontrol); |
553 | } |
554 | |
555 | static int va_macro_tx_mixer_get(struct snd_kcontrol *kcontrol, |
556 | struct snd_ctl_elem_value *ucontrol) |
557 | { |
558 | struct snd_soc_dapm_widget *widget = |
559 | snd_soc_dapm_kcontrol_widget(kcontrol); |
560 | struct snd_soc_component *component = |
561 | snd_soc_dapm_to_component(dapm: widget->dapm); |
562 | struct soc_mixer_control *mc = |
563 | (struct soc_mixer_control *)kcontrol->private_value; |
564 | u32 dai_id = widget->shift; |
565 | u32 dec_id = mc->shift; |
566 | struct va_macro *va = snd_soc_component_get_drvdata(c: component); |
567 | |
568 | if (test_bit(dec_id, &va->active_ch_mask[dai_id])) |
569 | ucontrol->value.integer.value[0] = 1; |
570 | else |
571 | ucontrol->value.integer.value[0] = 0; |
572 | |
573 | return 0; |
574 | } |
575 | |
576 | static int va_macro_tx_mixer_put(struct snd_kcontrol *kcontrol, |
577 | struct snd_ctl_elem_value *ucontrol) |
578 | { |
579 | struct snd_soc_dapm_widget *widget = |
580 | snd_soc_dapm_kcontrol_widget(kcontrol); |
581 | struct snd_soc_component *component = |
582 | snd_soc_dapm_to_component(dapm: widget->dapm); |
583 | struct snd_soc_dapm_update *update = NULL; |
584 | struct soc_mixer_control *mc = |
585 | (struct soc_mixer_control *)kcontrol->private_value; |
586 | u32 dai_id = widget->shift; |
587 | u32 dec_id = mc->shift; |
588 | u32 enable = ucontrol->value.integer.value[0]; |
589 | struct va_macro *va = snd_soc_component_get_drvdata(c: component); |
590 | |
591 | if (enable) { |
592 | set_bit(nr: dec_id, addr: &va->active_ch_mask[dai_id]); |
593 | va->active_ch_cnt[dai_id]++; |
594 | } else { |
595 | clear_bit(nr: dec_id, addr: &va->active_ch_mask[dai_id]); |
596 | va->active_ch_cnt[dai_id]--; |
597 | } |
598 | |
599 | snd_soc_dapm_mixer_update_power(dapm: widget->dapm, kcontrol, connect: enable, update); |
600 | |
601 | return 0; |
602 | } |
603 | |
604 | static int va_dmic_clk_enable(struct snd_soc_component *component, |
605 | u32 dmic, bool enable) |
606 | { |
607 | struct va_macro *va = snd_soc_component_get_drvdata(c: component); |
608 | u16 dmic_clk_reg; |
609 | s32 *dmic_clk_cnt; |
610 | u8 *dmic_clk_div; |
611 | u8 freq_change_mask; |
612 | u8 clk_div; |
613 | |
614 | switch (dmic) { |
615 | case 0: |
616 | case 1: |
617 | dmic_clk_cnt = &(va->dmic_0_1_clk_cnt); |
618 | dmic_clk_div = &(va->dmic_0_1_clk_div); |
619 | dmic_clk_reg = CDC_VA_TOP_CSR_DMIC0_CTL; |
620 | freq_change_mask = CDC_VA_DMIC0_FREQ_CHANGE_MASK; |
621 | break; |
622 | case 2: |
623 | case 3: |
624 | dmic_clk_cnt = &(va->dmic_2_3_clk_cnt); |
625 | dmic_clk_div = &(va->dmic_2_3_clk_div); |
626 | dmic_clk_reg = CDC_VA_TOP_CSR_DMIC1_CTL; |
627 | freq_change_mask = CDC_VA_DMIC1_FREQ_CHANGE_MASK; |
628 | break; |
629 | case 4: |
630 | case 5: |
631 | dmic_clk_cnt = &(va->dmic_4_5_clk_cnt); |
632 | dmic_clk_div = &(va->dmic_4_5_clk_div); |
633 | dmic_clk_reg = CDC_VA_TOP_CSR_DMIC2_CTL; |
634 | freq_change_mask = CDC_VA_DMIC2_FREQ_CHANGE_MASK; |
635 | break; |
636 | case 6: |
637 | case 7: |
638 | dmic_clk_cnt = &(va->dmic_6_7_clk_cnt); |
639 | dmic_clk_div = &(va->dmic_6_7_clk_div); |
640 | dmic_clk_reg = CDC_VA_TOP_CSR_DMIC3_CTL; |
641 | freq_change_mask = CDC_VA_DMIC3_FREQ_CHANGE_MASK; |
642 | break; |
643 | default: |
644 | dev_err(component->dev, "%s: Invalid DMIC Selection\n" , |
645 | __func__); |
646 | return -EINVAL; |
647 | } |
648 | |
649 | if (enable) { |
650 | clk_div = va->dmic_clk_div; |
651 | (*dmic_clk_cnt)++; |
652 | if (*dmic_clk_cnt == 1) { |
653 | snd_soc_component_update_bits(component, |
654 | CDC_VA_TOP_CSR_DMIC_CFG, |
655 | CDC_VA_RESET_ALL_DMICS_MASK, |
656 | CDC_VA_RESET_ALL_DMICS_DISABLE); |
657 | snd_soc_component_update_bits(component, reg: dmic_clk_reg, |
658 | CDC_VA_DMIC_CLK_SEL_MASK, |
659 | val: clk_div << CDC_VA_DMIC_CLK_SEL_SHFT); |
660 | snd_soc_component_update_bits(component, reg: dmic_clk_reg, |
661 | CDC_VA_DMIC_EN_MASK, |
662 | CDC_VA_DMIC_ENABLE); |
663 | } else { |
664 | if (*dmic_clk_div > clk_div) { |
665 | snd_soc_component_update_bits(component, |
666 | CDC_VA_TOP_CSR_DMIC_CFG, |
667 | mask: freq_change_mask, |
668 | val: freq_change_mask); |
669 | snd_soc_component_update_bits(component, reg: dmic_clk_reg, |
670 | CDC_VA_DMIC_CLK_SEL_MASK, |
671 | val: clk_div << CDC_VA_DMIC_CLK_SEL_SHFT); |
672 | snd_soc_component_update_bits(component, |
673 | CDC_VA_TOP_CSR_DMIC_CFG, |
674 | mask: freq_change_mask, |
675 | CDC_VA_DMIC_FREQ_CHANGE_DISABLE); |
676 | } else { |
677 | clk_div = *dmic_clk_div; |
678 | } |
679 | } |
680 | *dmic_clk_div = clk_div; |
681 | } else { |
682 | (*dmic_clk_cnt)--; |
683 | if (*dmic_clk_cnt == 0) { |
684 | snd_soc_component_update_bits(component, reg: dmic_clk_reg, |
685 | CDC_VA_DMIC_EN_MASK, val: 0); |
686 | clk_div = 0; |
687 | snd_soc_component_update_bits(component, reg: dmic_clk_reg, |
688 | CDC_VA_DMIC_CLK_SEL_MASK, |
689 | val: clk_div << CDC_VA_DMIC_CLK_SEL_SHFT); |
690 | } else { |
691 | clk_div = va->dmic_clk_div; |
692 | if (*dmic_clk_div > clk_div) { |
693 | clk_div = va->dmic_clk_div; |
694 | snd_soc_component_update_bits(component, |
695 | CDC_VA_TOP_CSR_DMIC_CFG, |
696 | mask: freq_change_mask, |
697 | val: freq_change_mask); |
698 | snd_soc_component_update_bits(component, reg: dmic_clk_reg, |
699 | CDC_VA_DMIC_CLK_SEL_MASK, |
700 | val: clk_div << CDC_VA_DMIC_CLK_SEL_SHFT); |
701 | snd_soc_component_update_bits(component, |
702 | CDC_VA_TOP_CSR_DMIC_CFG, |
703 | mask: freq_change_mask, |
704 | CDC_VA_DMIC_FREQ_CHANGE_DISABLE); |
705 | } else { |
706 | clk_div = *dmic_clk_div; |
707 | } |
708 | } |
709 | *dmic_clk_div = clk_div; |
710 | } |
711 | |
712 | return 0; |
713 | } |
714 | |
715 | static int va_macro_enable_dmic(struct snd_soc_dapm_widget *w, |
716 | struct snd_kcontrol *kcontrol, int event) |
717 | { |
718 | struct snd_soc_component *comp = snd_soc_dapm_to_component(dapm: w->dapm); |
719 | unsigned int dmic = w->shift; |
720 | |
721 | switch (event) { |
722 | case SND_SOC_DAPM_PRE_PMU: |
723 | va_dmic_clk_enable(component: comp, dmic, enable: true); |
724 | break; |
725 | case SND_SOC_DAPM_POST_PMD: |
726 | va_dmic_clk_enable(component: comp, dmic, enable: false); |
727 | break; |
728 | } |
729 | |
730 | return 0; |
731 | } |
732 | |
733 | static int va_macro_enable_dec(struct snd_soc_dapm_widget *w, |
734 | struct snd_kcontrol *kcontrol, int event) |
735 | { |
736 | struct snd_soc_component *comp = snd_soc_dapm_to_component(dapm: w->dapm); |
737 | unsigned int decimator; |
738 | u16 tx_vol_ctl_reg, dec_cfg_reg, hpf_gate_reg; |
739 | u16 tx_gain_ctl_reg; |
740 | u8 hpf_cut_off_freq; |
741 | |
742 | struct va_macro *va = snd_soc_component_get_drvdata(c: comp); |
743 | |
744 | decimator = w->shift; |
745 | |
746 | tx_vol_ctl_reg = CDC_VA_TX0_TX_PATH_CTL + |
747 | VA_MACRO_TX_PATH_OFFSET * decimator; |
748 | hpf_gate_reg = CDC_VA_TX0_TX_PATH_SEC2 + |
749 | VA_MACRO_TX_PATH_OFFSET * decimator; |
750 | dec_cfg_reg = CDC_VA_TX0_TX_PATH_CFG0 + |
751 | VA_MACRO_TX_PATH_OFFSET * decimator; |
752 | tx_gain_ctl_reg = CDC_VA_TX0_TX_VOL_CTL + |
753 | VA_MACRO_TX_PATH_OFFSET * decimator; |
754 | |
755 | switch (event) { |
756 | case SND_SOC_DAPM_PRE_PMU: |
757 | snd_soc_component_update_bits(component: comp, |
758 | reg: dec_cfg_reg, CDC_VA_ADC_MODE_MASK, |
759 | val: va->dec_mode[decimator] << CDC_VA_ADC_MODE_SHIFT); |
760 | /* Enable TX PGA Mute */ |
761 | break; |
762 | case SND_SOC_DAPM_POST_PMU: |
763 | /* Enable TX CLK */ |
764 | snd_soc_component_update_bits(component: comp, reg: tx_vol_ctl_reg, |
765 | CDC_VA_TX_PATH_CLK_EN_MASK, |
766 | CDC_VA_TX_PATH_CLK_EN); |
767 | snd_soc_component_update_bits(component: comp, reg: hpf_gate_reg, |
768 | CDC_VA_TX_HPF_ZERO_GATE_MASK, |
769 | CDC_VA_TX_HPF_ZERO_GATE); |
770 | |
771 | usleep_range(min: 1000, max: 1010); |
772 | hpf_cut_off_freq = (snd_soc_component_read(component: comp, reg: dec_cfg_reg) & |
773 | TX_HPF_CUT_OFF_FREQ_MASK) >> 5; |
774 | |
775 | if (hpf_cut_off_freq != CF_MIN_3DB_150HZ) { |
776 | snd_soc_component_update_bits(component: comp, reg: dec_cfg_reg, |
777 | TX_HPF_CUT_OFF_FREQ_MASK, |
778 | CF_MIN_3DB_150HZ << 5); |
779 | |
780 | snd_soc_component_update_bits(component: comp, reg: hpf_gate_reg, |
781 | CDC_VA_TX_HPF_CUTOFF_FREQ_CHANGE_MASK, |
782 | CDC_VA_TX_HPF_CUTOFF_FREQ_CHANGE_REQ); |
783 | |
784 | /* |
785 | * Minimum 1 clk cycle delay is required as per HW spec |
786 | */ |
787 | usleep_range(min: 1000, max: 1010); |
788 | |
789 | snd_soc_component_update_bits(component: comp, |
790 | reg: hpf_gate_reg, |
791 | CDC_VA_TX_HPF_CUTOFF_FREQ_CHANGE_MASK, |
792 | val: 0x0); |
793 | } |
794 | |
795 | |
796 | usleep_range(min: 1000, max: 1010); |
797 | snd_soc_component_update_bits(component: comp, reg: hpf_gate_reg, |
798 | CDC_VA_TX_HPF_ZERO_GATE_MASK, |
799 | CDC_VA_TX_HPF_ZERO_NO_GATE); |
800 | /* |
801 | * 6ms delay is required as per HW spec |
802 | */ |
803 | usleep_range(min: 6000, max: 6010); |
804 | /* apply gain after decimator is enabled */ |
805 | snd_soc_component_write(component: comp, reg: tx_gain_ctl_reg, |
806 | val: snd_soc_component_read(component: comp, reg: tx_gain_ctl_reg)); |
807 | break; |
808 | case SND_SOC_DAPM_POST_PMD: |
809 | /* Disable TX CLK */ |
810 | snd_soc_component_update_bits(component: comp, reg: tx_vol_ctl_reg, |
811 | CDC_VA_TX_PATH_CLK_EN_MASK, |
812 | CDC_VA_TX_PATH_CLK_DISABLE); |
813 | break; |
814 | } |
815 | return 0; |
816 | } |
817 | |
818 | static int va_macro_dec_mode_get(struct snd_kcontrol *kcontrol, |
819 | struct snd_ctl_elem_value *ucontrol) |
820 | { |
821 | struct snd_soc_component *comp = snd_soc_kcontrol_component(kcontrol); |
822 | struct va_macro *va = snd_soc_component_get_drvdata(c: comp); |
823 | struct soc_enum *e = (struct soc_enum *)kcontrol->private_value; |
824 | int path = e->shift_l; |
825 | |
826 | ucontrol->value.enumerated.item[0] = va->dec_mode[path]; |
827 | |
828 | return 0; |
829 | } |
830 | |
831 | static int va_macro_dec_mode_put(struct snd_kcontrol *kcontrol, |
832 | struct snd_ctl_elem_value *ucontrol) |
833 | { |
834 | struct snd_soc_component *comp = snd_soc_kcontrol_component(kcontrol); |
835 | int value = ucontrol->value.enumerated.item[0]; |
836 | struct soc_enum *e = (struct soc_enum *)kcontrol->private_value; |
837 | int path = e->shift_l; |
838 | struct va_macro *va = snd_soc_component_get_drvdata(c: comp); |
839 | |
840 | va->dec_mode[path] = value; |
841 | |
842 | return 0; |
843 | } |
844 | |
845 | static int va_macro_hw_params(struct snd_pcm_substream *substream, |
846 | struct snd_pcm_hw_params *params, |
847 | struct snd_soc_dai *dai) |
848 | { |
849 | int tx_fs_rate; |
850 | struct snd_soc_component *component = dai->component; |
851 | u32 decimator, sample_rate; |
852 | u16 tx_fs_reg; |
853 | struct device *va_dev = component->dev; |
854 | struct va_macro *va = snd_soc_component_get_drvdata(c: component); |
855 | |
856 | sample_rate = params_rate(p: params); |
857 | switch (sample_rate) { |
858 | case 8000: |
859 | tx_fs_rate = 0; |
860 | break; |
861 | case 16000: |
862 | tx_fs_rate = 1; |
863 | break; |
864 | case 32000: |
865 | tx_fs_rate = 3; |
866 | break; |
867 | case 48000: |
868 | tx_fs_rate = 4; |
869 | break; |
870 | case 96000: |
871 | tx_fs_rate = 5; |
872 | break; |
873 | case 192000: |
874 | tx_fs_rate = 6; |
875 | break; |
876 | case 384000: |
877 | tx_fs_rate = 7; |
878 | break; |
879 | default: |
880 | dev_err(va_dev, "%s: Invalid TX sample rate: %d\n" , |
881 | __func__, params_rate(params)); |
882 | return -EINVAL; |
883 | } |
884 | |
885 | for_each_set_bit(decimator, &va->active_ch_mask[dai->id], |
886 | VA_MACRO_DEC_MAX) { |
887 | tx_fs_reg = CDC_VA_TX0_TX_PATH_CTL + |
888 | VA_MACRO_TX_PATH_OFFSET * decimator; |
889 | snd_soc_component_update_bits(component, reg: tx_fs_reg, mask: 0x0F, |
890 | val: tx_fs_rate); |
891 | } |
892 | return 0; |
893 | } |
894 | |
895 | static int va_macro_get_channel_map(struct snd_soc_dai *dai, |
896 | unsigned int *tx_num, unsigned int *tx_slot, |
897 | unsigned int *rx_num, unsigned int *rx_slot) |
898 | { |
899 | struct snd_soc_component *component = dai->component; |
900 | struct device *va_dev = component->dev; |
901 | struct va_macro *va = snd_soc_component_get_drvdata(c: component); |
902 | |
903 | switch (dai->id) { |
904 | case VA_MACRO_AIF1_CAP: |
905 | case VA_MACRO_AIF2_CAP: |
906 | case VA_MACRO_AIF3_CAP: |
907 | *tx_slot = va->active_ch_mask[dai->id]; |
908 | *tx_num = va->active_ch_cnt[dai->id]; |
909 | break; |
910 | default: |
911 | dev_err(va_dev, "%s: Invalid AIF\n" , __func__); |
912 | break; |
913 | } |
914 | return 0; |
915 | } |
916 | |
917 | static int va_macro_digital_mute(struct snd_soc_dai *dai, int mute, int stream) |
918 | { |
919 | struct snd_soc_component *component = dai->component; |
920 | struct va_macro *va = snd_soc_component_get_drvdata(c: component); |
921 | u16 tx_vol_ctl_reg, decimator; |
922 | |
923 | for_each_set_bit(decimator, &va->active_ch_mask[dai->id], |
924 | VA_MACRO_DEC_MAX) { |
925 | tx_vol_ctl_reg = CDC_VA_TX0_TX_PATH_CTL + |
926 | VA_MACRO_TX_PATH_OFFSET * decimator; |
927 | if (mute) |
928 | snd_soc_component_update_bits(component, reg: tx_vol_ctl_reg, |
929 | CDC_VA_TX_PATH_PGA_MUTE_EN_MASK, |
930 | CDC_VA_TX_PATH_PGA_MUTE_EN); |
931 | else |
932 | snd_soc_component_update_bits(component, reg: tx_vol_ctl_reg, |
933 | CDC_VA_TX_PATH_PGA_MUTE_EN_MASK, |
934 | CDC_VA_TX_PATH_PGA_MUTE_DISABLE); |
935 | } |
936 | |
937 | return 0; |
938 | } |
939 | |
940 | static const struct snd_soc_dai_ops va_macro_dai_ops = { |
941 | .hw_params = va_macro_hw_params, |
942 | .get_channel_map = va_macro_get_channel_map, |
943 | .mute_stream = va_macro_digital_mute, |
944 | }; |
945 | |
946 | static struct snd_soc_dai_driver va_macro_dais[] = { |
947 | { |
948 | .name = "va_macro_tx1" , |
949 | .id = VA_MACRO_AIF1_CAP, |
950 | .capture = { |
951 | .stream_name = "VA_AIF1 Capture" , |
952 | .rates = VA_MACRO_RATES, |
953 | .formats = VA_MACRO_FORMATS, |
954 | .rate_max = 192000, |
955 | .rate_min = 8000, |
956 | .channels_min = 1, |
957 | .channels_max = 8, |
958 | }, |
959 | .ops = &va_macro_dai_ops, |
960 | }, |
961 | { |
962 | .name = "va_macro_tx2" , |
963 | .id = VA_MACRO_AIF2_CAP, |
964 | .capture = { |
965 | .stream_name = "VA_AIF2 Capture" , |
966 | .rates = VA_MACRO_RATES, |
967 | .formats = VA_MACRO_FORMATS, |
968 | .rate_max = 192000, |
969 | .rate_min = 8000, |
970 | .channels_min = 1, |
971 | .channels_max = 8, |
972 | }, |
973 | .ops = &va_macro_dai_ops, |
974 | }, |
975 | { |
976 | .name = "va_macro_tx3" , |
977 | .id = VA_MACRO_AIF3_CAP, |
978 | .capture = { |
979 | .stream_name = "VA_AIF3 Capture" , |
980 | .rates = VA_MACRO_RATES, |
981 | .formats = VA_MACRO_FORMATS, |
982 | .rate_max = 192000, |
983 | .rate_min = 8000, |
984 | .channels_min = 1, |
985 | .channels_max = 8, |
986 | }, |
987 | .ops = &va_macro_dai_ops, |
988 | }, |
989 | }; |
990 | |
991 | static const char * const adc_mux_text[] = { |
992 | "VA_DMIC" , "SWR_MIC" |
993 | }; |
994 | |
995 | static SOC_ENUM_SINGLE_DECL(va_dec0_enum, CDC_VA_INP_MUX_ADC_MUX0_CFG1, |
996 | 0, adc_mux_text); |
997 | static SOC_ENUM_SINGLE_DECL(va_dec1_enum, CDC_VA_INP_MUX_ADC_MUX1_CFG1, |
998 | 0, adc_mux_text); |
999 | static SOC_ENUM_SINGLE_DECL(va_dec2_enum, CDC_VA_INP_MUX_ADC_MUX2_CFG1, |
1000 | 0, adc_mux_text); |
1001 | static SOC_ENUM_SINGLE_DECL(va_dec3_enum, CDC_VA_INP_MUX_ADC_MUX3_CFG1, |
1002 | 0, adc_mux_text); |
1003 | |
1004 | static const struct snd_kcontrol_new va_dec0_mux = SOC_DAPM_ENUM("va_dec0" , |
1005 | va_dec0_enum); |
1006 | static const struct snd_kcontrol_new va_dec1_mux = SOC_DAPM_ENUM("va_dec1" , |
1007 | va_dec1_enum); |
1008 | static const struct snd_kcontrol_new va_dec2_mux = SOC_DAPM_ENUM("va_dec2" , |
1009 | va_dec2_enum); |
1010 | static const struct snd_kcontrol_new va_dec3_mux = SOC_DAPM_ENUM("va_dec3" , |
1011 | va_dec3_enum); |
1012 | |
1013 | static const char * const dmic_mux_text[] = { |
1014 | "ZERO" , "DMIC0" , "DMIC1" , "DMIC2" , "DMIC3" , |
1015 | "DMIC4" , "DMIC5" , "DMIC6" , "DMIC7" |
1016 | }; |
1017 | |
1018 | static SOC_ENUM_SINGLE_DECL(va_dmic0_enum, CDC_VA_INP_MUX_ADC_MUX0_CFG0, |
1019 | 4, dmic_mux_text); |
1020 | |
1021 | static SOC_ENUM_SINGLE_DECL(va_dmic1_enum, CDC_VA_INP_MUX_ADC_MUX1_CFG0, |
1022 | 4, dmic_mux_text); |
1023 | |
1024 | static SOC_ENUM_SINGLE_DECL(va_dmic2_enum, CDC_VA_INP_MUX_ADC_MUX2_CFG0, |
1025 | 4, dmic_mux_text); |
1026 | |
1027 | static SOC_ENUM_SINGLE_DECL(va_dmic3_enum, CDC_VA_INP_MUX_ADC_MUX3_CFG0, |
1028 | 4, dmic_mux_text); |
1029 | |
1030 | static const struct snd_kcontrol_new va_dmic0_mux = SOC_DAPM_ENUM_EXT("va_dmic0" , |
1031 | va_dmic0_enum, snd_soc_dapm_get_enum_double, |
1032 | va_macro_put_dec_enum); |
1033 | |
1034 | static const struct snd_kcontrol_new va_dmic1_mux = SOC_DAPM_ENUM_EXT("va_dmic1" , |
1035 | va_dmic1_enum, snd_soc_dapm_get_enum_double, |
1036 | va_macro_put_dec_enum); |
1037 | |
1038 | static const struct snd_kcontrol_new va_dmic2_mux = SOC_DAPM_ENUM_EXT("va_dmic2" , |
1039 | va_dmic2_enum, snd_soc_dapm_get_enum_double, |
1040 | va_macro_put_dec_enum); |
1041 | |
1042 | static const struct snd_kcontrol_new va_dmic3_mux = SOC_DAPM_ENUM_EXT("va_dmic3" , |
1043 | va_dmic3_enum, snd_soc_dapm_get_enum_double, |
1044 | va_macro_put_dec_enum); |
1045 | |
1046 | static const struct snd_kcontrol_new va_aif1_cap_mixer[] = { |
1047 | SOC_SINGLE_EXT("DEC0" , SND_SOC_NOPM, VA_MACRO_DEC0, 1, 0, |
1048 | va_macro_tx_mixer_get, va_macro_tx_mixer_put), |
1049 | SOC_SINGLE_EXT("DEC1" , SND_SOC_NOPM, VA_MACRO_DEC1, 1, 0, |
1050 | va_macro_tx_mixer_get, va_macro_tx_mixer_put), |
1051 | SOC_SINGLE_EXT("DEC2" , SND_SOC_NOPM, VA_MACRO_DEC2, 1, 0, |
1052 | va_macro_tx_mixer_get, va_macro_tx_mixer_put), |
1053 | SOC_SINGLE_EXT("DEC3" , SND_SOC_NOPM, VA_MACRO_DEC3, 1, 0, |
1054 | va_macro_tx_mixer_get, va_macro_tx_mixer_put), |
1055 | SOC_SINGLE_EXT("DEC4" , SND_SOC_NOPM, VA_MACRO_DEC4, 1, 0, |
1056 | va_macro_tx_mixer_get, va_macro_tx_mixer_put), |
1057 | SOC_SINGLE_EXT("DEC5" , SND_SOC_NOPM, VA_MACRO_DEC5, 1, 0, |
1058 | va_macro_tx_mixer_get, va_macro_tx_mixer_put), |
1059 | SOC_SINGLE_EXT("DEC6" , SND_SOC_NOPM, VA_MACRO_DEC6, 1, 0, |
1060 | va_macro_tx_mixer_get, va_macro_tx_mixer_put), |
1061 | SOC_SINGLE_EXT("DEC7" , SND_SOC_NOPM, VA_MACRO_DEC7, 1, 0, |
1062 | va_macro_tx_mixer_get, va_macro_tx_mixer_put), |
1063 | }; |
1064 | |
1065 | static const struct snd_kcontrol_new va_aif2_cap_mixer[] = { |
1066 | SOC_SINGLE_EXT("DEC0" , SND_SOC_NOPM, VA_MACRO_DEC0, 1, 0, |
1067 | va_macro_tx_mixer_get, va_macro_tx_mixer_put), |
1068 | SOC_SINGLE_EXT("DEC1" , SND_SOC_NOPM, VA_MACRO_DEC1, 1, 0, |
1069 | va_macro_tx_mixer_get, va_macro_tx_mixer_put), |
1070 | SOC_SINGLE_EXT("DEC2" , SND_SOC_NOPM, VA_MACRO_DEC2, 1, 0, |
1071 | va_macro_tx_mixer_get, va_macro_tx_mixer_put), |
1072 | SOC_SINGLE_EXT("DEC3" , SND_SOC_NOPM, VA_MACRO_DEC3, 1, 0, |
1073 | va_macro_tx_mixer_get, va_macro_tx_mixer_put), |
1074 | SOC_SINGLE_EXT("DEC4" , SND_SOC_NOPM, VA_MACRO_DEC4, 1, 0, |
1075 | va_macro_tx_mixer_get, va_macro_tx_mixer_put), |
1076 | SOC_SINGLE_EXT("DEC5" , SND_SOC_NOPM, VA_MACRO_DEC5, 1, 0, |
1077 | va_macro_tx_mixer_get, va_macro_tx_mixer_put), |
1078 | SOC_SINGLE_EXT("DEC6" , SND_SOC_NOPM, VA_MACRO_DEC6, 1, 0, |
1079 | va_macro_tx_mixer_get, va_macro_tx_mixer_put), |
1080 | SOC_SINGLE_EXT("DEC7" , SND_SOC_NOPM, VA_MACRO_DEC7, 1, 0, |
1081 | va_macro_tx_mixer_get, va_macro_tx_mixer_put), |
1082 | }; |
1083 | |
1084 | static const struct snd_kcontrol_new va_aif3_cap_mixer[] = { |
1085 | SOC_SINGLE_EXT("DEC0" , SND_SOC_NOPM, VA_MACRO_DEC0, 1, 0, |
1086 | va_macro_tx_mixer_get, va_macro_tx_mixer_put), |
1087 | SOC_SINGLE_EXT("DEC1" , SND_SOC_NOPM, VA_MACRO_DEC1, 1, 0, |
1088 | va_macro_tx_mixer_get, va_macro_tx_mixer_put), |
1089 | SOC_SINGLE_EXT("DEC2" , SND_SOC_NOPM, VA_MACRO_DEC2, 1, 0, |
1090 | va_macro_tx_mixer_get, va_macro_tx_mixer_put), |
1091 | SOC_SINGLE_EXT("DEC3" , SND_SOC_NOPM, VA_MACRO_DEC3, 1, 0, |
1092 | va_macro_tx_mixer_get, va_macro_tx_mixer_put), |
1093 | SOC_SINGLE_EXT("DEC4" , SND_SOC_NOPM, VA_MACRO_DEC4, 1, 0, |
1094 | va_macro_tx_mixer_get, va_macro_tx_mixer_put), |
1095 | SOC_SINGLE_EXT("DEC5" , SND_SOC_NOPM, VA_MACRO_DEC5, 1, 0, |
1096 | va_macro_tx_mixer_get, va_macro_tx_mixer_put), |
1097 | SOC_SINGLE_EXT("DEC6" , SND_SOC_NOPM, VA_MACRO_DEC6, 1, 0, |
1098 | va_macro_tx_mixer_get, va_macro_tx_mixer_put), |
1099 | SOC_SINGLE_EXT("DEC7" , SND_SOC_NOPM, VA_MACRO_DEC7, 1, 0, |
1100 | va_macro_tx_mixer_get, va_macro_tx_mixer_put), |
1101 | }; |
1102 | |
1103 | static const struct snd_soc_dapm_widget va_macro_dapm_widgets[] = { |
1104 | SND_SOC_DAPM_AIF_OUT("VA_AIF1 CAP" , "VA_AIF1 Capture" , 0, |
1105 | SND_SOC_NOPM, VA_MACRO_AIF1_CAP, 0), |
1106 | |
1107 | SND_SOC_DAPM_AIF_OUT("VA_AIF2 CAP" , "VA_AIF2 Capture" , 0, |
1108 | SND_SOC_NOPM, VA_MACRO_AIF2_CAP, 0), |
1109 | |
1110 | SND_SOC_DAPM_AIF_OUT("VA_AIF3 CAP" , "VA_AIF3 Capture" , 0, |
1111 | SND_SOC_NOPM, VA_MACRO_AIF3_CAP, 0), |
1112 | |
1113 | SND_SOC_DAPM_MIXER("VA_AIF1_CAP Mixer" , SND_SOC_NOPM, |
1114 | VA_MACRO_AIF1_CAP, 0, |
1115 | va_aif1_cap_mixer, ARRAY_SIZE(va_aif1_cap_mixer)), |
1116 | |
1117 | SND_SOC_DAPM_MIXER("VA_AIF2_CAP Mixer" , SND_SOC_NOPM, |
1118 | VA_MACRO_AIF2_CAP, 0, |
1119 | va_aif2_cap_mixer, ARRAY_SIZE(va_aif2_cap_mixer)), |
1120 | |
1121 | SND_SOC_DAPM_MIXER("VA_AIF3_CAP Mixer" , SND_SOC_NOPM, |
1122 | VA_MACRO_AIF3_CAP, 0, |
1123 | va_aif3_cap_mixer, ARRAY_SIZE(va_aif3_cap_mixer)), |
1124 | |
1125 | SND_SOC_DAPM_MUX("VA DMIC MUX0" , SND_SOC_NOPM, 0, 0, &va_dmic0_mux), |
1126 | SND_SOC_DAPM_MUX("VA DMIC MUX1" , SND_SOC_NOPM, 0, 0, &va_dmic1_mux), |
1127 | SND_SOC_DAPM_MUX("VA DMIC MUX2" , SND_SOC_NOPM, 0, 0, &va_dmic2_mux), |
1128 | SND_SOC_DAPM_MUX("VA DMIC MUX3" , SND_SOC_NOPM, 0, 0, &va_dmic3_mux), |
1129 | |
1130 | SND_SOC_DAPM_REGULATOR_SUPPLY("vdd-micb" , 0, 0), |
1131 | SND_SOC_DAPM_INPUT("DMIC0 Pin" ), |
1132 | SND_SOC_DAPM_INPUT("DMIC1 Pin" ), |
1133 | SND_SOC_DAPM_INPUT("DMIC2 Pin" ), |
1134 | SND_SOC_DAPM_INPUT("DMIC3 Pin" ), |
1135 | SND_SOC_DAPM_INPUT("DMIC4 Pin" ), |
1136 | SND_SOC_DAPM_INPUT("DMIC5 Pin" ), |
1137 | SND_SOC_DAPM_INPUT("DMIC6 Pin" ), |
1138 | SND_SOC_DAPM_INPUT("DMIC7 Pin" ), |
1139 | |
1140 | SND_SOC_DAPM_ADC_E("VA DMIC0" , NULL, SND_SOC_NOPM, 0, 0, |
1141 | va_macro_enable_dmic, SND_SOC_DAPM_PRE_PMU | |
1142 | SND_SOC_DAPM_POST_PMD), |
1143 | |
1144 | SND_SOC_DAPM_ADC_E("VA DMIC1" , NULL, SND_SOC_NOPM, 1, 0, |
1145 | va_macro_enable_dmic, SND_SOC_DAPM_PRE_PMU | |
1146 | SND_SOC_DAPM_POST_PMD), |
1147 | |
1148 | SND_SOC_DAPM_ADC_E("VA DMIC2" , NULL, SND_SOC_NOPM, 2, 0, |
1149 | va_macro_enable_dmic, SND_SOC_DAPM_PRE_PMU | |
1150 | SND_SOC_DAPM_POST_PMD), |
1151 | |
1152 | SND_SOC_DAPM_ADC_E("VA DMIC3" , NULL, SND_SOC_NOPM, 3, 0, |
1153 | va_macro_enable_dmic, SND_SOC_DAPM_PRE_PMU | |
1154 | SND_SOC_DAPM_POST_PMD), |
1155 | |
1156 | SND_SOC_DAPM_ADC_E("VA DMIC4" , NULL, SND_SOC_NOPM, 4, 0, |
1157 | va_macro_enable_dmic, SND_SOC_DAPM_PRE_PMU | |
1158 | SND_SOC_DAPM_POST_PMD), |
1159 | |
1160 | SND_SOC_DAPM_ADC_E("VA DMIC5" , NULL, SND_SOC_NOPM, 5, 0, |
1161 | va_macro_enable_dmic, SND_SOC_DAPM_PRE_PMU | |
1162 | SND_SOC_DAPM_POST_PMD), |
1163 | |
1164 | SND_SOC_DAPM_ADC_E("VA DMIC6" , NULL, SND_SOC_NOPM, 6, 0, |
1165 | va_macro_enable_dmic, SND_SOC_DAPM_PRE_PMU | |
1166 | SND_SOC_DAPM_POST_PMD), |
1167 | |
1168 | SND_SOC_DAPM_ADC_E("VA DMIC7" , NULL, SND_SOC_NOPM, 7, 0, |
1169 | va_macro_enable_dmic, SND_SOC_DAPM_PRE_PMU | |
1170 | SND_SOC_DAPM_POST_PMD), |
1171 | |
1172 | SND_SOC_DAPM_INPUT("VA SWR_ADC0" ), |
1173 | SND_SOC_DAPM_INPUT("VA SWR_ADC1" ), |
1174 | SND_SOC_DAPM_INPUT("VA SWR_ADC2" ), |
1175 | SND_SOC_DAPM_INPUT("VA SWR_ADC3" ), |
1176 | SND_SOC_DAPM_INPUT("VA SWR_MIC0" ), |
1177 | SND_SOC_DAPM_INPUT("VA SWR_MIC1" ), |
1178 | SND_SOC_DAPM_INPUT("VA SWR_MIC2" ), |
1179 | SND_SOC_DAPM_INPUT("VA SWR_MIC3" ), |
1180 | SND_SOC_DAPM_INPUT("VA SWR_MIC4" ), |
1181 | SND_SOC_DAPM_INPUT("VA SWR_MIC5" ), |
1182 | SND_SOC_DAPM_INPUT("VA SWR_MIC6" ), |
1183 | SND_SOC_DAPM_INPUT("VA SWR_MIC7" ), |
1184 | |
1185 | SND_SOC_DAPM_MUX_E("VA DEC0 MUX" , SND_SOC_NOPM, VA_MACRO_DEC0, 0, |
1186 | &va_dec0_mux, va_macro_enable_dec, |
1187 | SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU | |
1188 | SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD), |
1189 | |
1190 | SND_SOC_DAPM_MUX_E("VA DEC1 MUX" , SND_SOC_NOPM, VA_MACRO_DEC1, 0, |
1191 | &va_dec1_mux, va_macro_enable_dec, |
1192 | SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU | |
1193 | SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD), |
1194 | |
1195 | SND_SOC_DAPM_MUX_E("VA DEC2 MUX" , SND_SOC_NOPM, VA_MACRO_DEC2, 0, |
1196 | &va_dec2_mux, va_macro_enable_dec, |
1197 | SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU | |
1198 | SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD), |
1199 | |
1200 | SND_SOC_DAPM_MUX_E("VA DEC3 MUX" , SND_SOC_NOPM, VA_MACRO_DEC3, 0, |
1201 | &va_dec3_mux, va_macro_enable_dec, |
1202 | SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU | |
1203 | SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD), |
1204 | |
1205 | SND_SOC_DAPM_SUPPLY_S("VA_MCLK" , -1, SND_SOC_NOPM, 0, 0, |
1206 | va_macro_mclk_event, |
1207 | SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD), |
1208 | }; |
1209 | |
1210 | static const struct snd_soc_dapm_route va_audio_map[] = { |
1211 | {"VA_AIF1 CAP" , NULL, "VA_MCLK" }, |
1212 | {"VA_AIF2 CAP" , NULL, "VA_MCLK" }, |
1213 | {"VA_AIF3 CAP" , NULL, "VA_MCLK" }, |
1214 | |
1215 | {"VA_AIF1 CAP" , NULL, "VA_AIF1_CAP Mixer" }, |
1216 | {"VA_AIF2 CAP" , NULL, "VA_AIF2_CAP Mixer" }, |
1217 | {"VA_AIF3 CAP" , NULL, "VA_AIF3_CAP Mixer" }, |
1218 | |
1219 | {"VA_AIF1_CAP Mixer" , "DEC0" , "VA DEC0 MUX" }, |
1220 | {"VA_AIF1_CAP Mixer" , "DEC1" , "VA DEC1 MUX" }, |
1221 | {"VA_AIF1_CAP Mixer" , "DEC2" , "VA DEC2 MUX" }, |
1222 | {"VA_AIF1_CAP Mixer" , "DEC3" , "VA DEC3 MUX" }, |
1223 | |
1224 | {"VA_AIF2_CAP Mixer" , "DEC0" , "VA DEC0 MUX" }, |
1225 | {"VA_AIF2_CAP Mixer" , "DEC1" , "VA DEC1 MUX" }, |
1226 | {"VA_AIF2_CAP Mixer" , "DEC2" , "VA DEC2 MUX" }, |
1227 | {"VA_AIF2_CAP Mixer" , "DEC3" , "VA DEC3 MUX" }, |
1228 | |
1229 | {"VA_AIF3_CAP Mixer" , "DEC0" , "VA DEC0 MUX" }, |
1230 | {"VA_AIF3_CAP Mixer" , "DEC1" , "VA DEC1 MUX" }, |
1231 | {"VA_AIF3_CAP Mixer" , "DEC2" , "VA DEC2 MUX" }, |
1232 | {"VA_AIF3_CAP Mixer" , "DEC3" , "VA DEC3 MUX" }, |
1233 | |
1234 | {"VA DEC0 MUX" , "VA_DMIC" , "VA DMIC MUX0" }, |
1235 | {"VA DMIC MUX0" , "DMIC0" , "VA DMIC0" }, |
1236 | {"VA DMIC MUX0" , "DMIC1" , "VA DMIC1" }, |
1237 | {"VA DMIC MUX0" , "DMIC2" , "VA DMIC2" }, |
1238 | {"VA DMIC MUX0" , "DMIC3" , "VA DMIC3" }, |
1239 | {"VA DMIC MUX0" , "DMIC4" , "VA DMIC4" }, |
1240 | {"VA DMIC MUX0" , "DMIC5" , "VA DMIC5" }, |
1241 | {"VA DMIC MUX0" , "DMIC6" , "VA DMIC6" }, |
1242 | {"VA DMIC MUX0" , "DMIC7" , "VA DMIC7" }, |
1243 | |
1244 | {"VA DEC1 MUX" , "VA_DMIC" , "VA DMIC MUX1" }, |
1245 | {"VA DMIC MUX1" , "DMIC0" , "VA DMIC0" }, |
1246 | {"VA DMIC MUX1" , "DMIC1" , "VA DMIC1" }, |
1247 | {"VA DMIC MUX1" , "DMIC2" , "VA DMIC2" }, |
1248 | {"VA DMIC MUX1" , "DMIC3" , "VA DMIC3" }, |
1249 | {"VA DMIC MUX1" , "DMIC4" , "VA DMIC4" }, |
1250 | {"VA DMIC MUX1" , "DMIC5" , "VA DMIC5" }, |
1251 | {"VA DMIC MUX1" , "DMIC6" , "VA DMIC6" }, |
1252 | {"VA DMIC MUX1" , "DMIC7" , "VA DMIC7" }, |
1253 | |
1254 | {"VA DEC2 MUX" , "VA_DMIC" , "VA DMIC MUX2" }, |
1255 | {"VA DMIC MUX2" , "DMIC0" , "VA DMIC0" }, |
1256 | {"VA DMIC MUX2" , "DMIC1" , "VA DMIC1" }, |
1257 | {"VA DMIC MUX2" , "DMIC2" , "VA DMIC2" }, |
1258 | {"VA DMIC MUX2" , "DMIC3" , "VA DMIC3" }, |
1259 | {"VA DMIC MUX2" , "DMIC4" , "VA DMIC4" }, |
1260 | {"VA DMIC MUX2" , "DMIC5" , "VA DMIC5" }, |
1261 | {"VA DMIC MUX2" , "DMIC6" , "VA DMIC6" }, |
1262 | {"VA DMIC MUX2" , "DMIC7" , "VA DMIC7" }, |
1263 | |
1264 | {"VA DEC3 MUX" , "VA_DMIC" , "VA DMIC MUX3" }, |
1265 | {"VA DMIC MUX3" , "DMIC0" , "VA DMIC0" }, |
1266 | {"VA DMIC MUX3" , "DMIC1" , "VA DMIC1" }, |
1267 | {"VA DMIC MUX3" , "DMIC2" , "VA DMIC2" }, |
1268 | {"VA DMIC MUX3" , "DMIC3" , "VA DMIC3" }, |
1269 | {"VA DMIC MUX3" , "DMIC4" , "VA DMIC4" }, |
1270 | {"VA DMIC MUX3" , "DMIC5" , "VA DMIC5" }, |
1271 | {"VA DMIC MUX3" , "DMIC6" , "VA DMIC6" }, |
1272 | {"VA DMIC MUX3" , "DMIC7" , "VA DMIC7" }, |
1273 | |
1274 | { "VA DMIC0" , NULL, "DMIC0 Pin" }, |
1275 | { "VA DMIC1" , NULL, "DMIC1 Pin" }, |
1276 | { "VA DMIC2" , NULL, "DMIC2 Pin" }, |
1277 | { "VA DMIC3" , NULL, "DMIC3 Pin" }, |
1278 | { "VA DMIC4" , NULL, "DMIC4 Pin" }, |
1279 | { "VA DMIC5" , NULL, "DMIC5 Pin" }, |
1280 | { "VA DMIC6" , NULL, "DMIC6 Pin" }, |
1281 | { "VA DMIC7" , NULL, "DMIC7 Pin" }, |
1282 | }; |
1283 | |
1284 | static const char * const dec_mode_mux_text[] = { |
1285 | "ADC_DEFAULT" , "ADC_LOW_PWR" , "ADC_HIGH_PERF" , |
1286 | }; |
1287 | |
1288 | static const struct soc_enum dec_mode_mux_enum[] = { |
1289 | SOC_ENUM_SINGLE(SND_SOC_NOPM, 0, ARRAY_SIZE(dec_mode_mux_text), |
1290 | dec_mode_mux_text), |
1291 | SOC_ENUM_SINGLE(SND_SOC_NOPM, 1, ARRAY_SIZE(dec_mode_mux_text), |
1292 | dec_mode_mux_text), |
1293 | SOC_ENUM_SINGLE(SND_SOC_NOPM, 2, ARRAY_SIZE(dec_mode_mux_text), |
1294 | dec_mode_mux_text), |
1295 | SOC_ENUM_SINGLE(SND_SOC_NOPM, 3, ARRAY_SIZE(dec_mode_mux_text), |
1296 | dec_mode_mux_text), |
1297 | }; |
1298 | |
1299 | static const struct snd_kcontrol_new va_macro_snd_controls[] = { |
1300 | SOC_SINGLE_S8_TLV("VA_DEC0 Volume" , CDC_VA_TX0_TX_VOL_CTL, |
1301 | -84, 40, digital_gain), |
1302 | SOC_SINGLE_S8_TLV("VA_DEC1 Volume" , CDC_VA_TX1_TX_VOL_CTL, |
1303 | -84, 40, digital_gain), |
1304 | SOC_SINGLE_S8_TLV("VA_DEC2 Volume" , CDC_VA_TX2_TX_VOL_CTL, |
1305 | -84, 40, digital_gain), |
1306 | SOC_SINGLE_S8_TLV("VA_DEC3 Volume" , CDC_VA_TX3_TX_VOL_CTL, |
1307 | -84, 40, digital_gain), |
1308 | |
1309 | SOC_ENUM_EXT("VA_DEC0 MODE" , dec_mode_mux_enum[0], |
1310 | va_macro_dec_mode_get, va_macro_dec_mode_put), |
1311 | SOC_ENUM_EXT("VA_DEC1 MODE" , dec_mode_mux_enum[1], |
1312 | va_macro_dec_mode_get, va_macro_dec_mode_put), |
1313 | SOC_ENUM_EXT("VA_DEC2 MODE" , dec_mode_mux_enum[2], |
1314 | va_macro_dec_mode_get, va_macro_dec_mode_put), |
1315 | SOC_ENUM_EXT("VA_DEC3 MODE" , dec_mode_mux_enum[3], |
1316 | va_macro_dec_mode_get, va_macro_dec_mode_put), |
1317 | }; |
1318 | |
1319 | static int va_macro_component_probe(struct snd_soc_component *component) |
1320 | { |
1321 | struct va_macro *va = snd_soc_component_get_drvdata(c: component); |
1322 | |
1323 | snd_soc_component_init_regmap(component, regmap: va->regmap); |
1324 | |
1325 | return 0; |
1326 | } |
1327 | |
1328 | static const struct snd_soc_component_driver va_macro_component_drv = { |
1329 | .name = "VA MACRO" , |
1330 | .probe = va_macro_component_probe, |
1331 | .controls = va_macro_snd_controls, |
1332 | .num_controls = ARRAY_SIZE(va_macro_snd_controls), |
1333 | .dapm_widgets = va_macro_dapm_widgets, |
1334 | .num_dapm_widgets = ARRAY_SIZE(va_macro_dapm_widgets), |
1335 | .dapm_routes = va_audio_map, |
1336 | .num_dapm_routes = ARRAY_SIZE(va_audio_map), |
1337 | }; |
1338 | |
1339 | static int fsgen_gate_enable(struct clk_hw *hw) |
1340 | { |
1341 | struct va_macro *va = to_va_macro(hw); |
1342 | struct regmap *regmap = va->regmap; |
1343 | int ret; |
1344 | |
1345 | if (va->has_swr_master) { |
1346 | ret = clk_prepare_enable(clk: va->mclk); |
1347 | if (ret) |
1348 | return ret; |
1349 | } |
1350 | |
1351 | ret = va_macro_mclk_enable(va, mclk_enable: true); |
1352 | if (va->has_swr_master) |
1353 | regmap_update_bits(map: regmap, CDC_VA_CLK_RST_CTRL_SWR_CONTROL, |
1354 | CDC_VA_SWR_CLK_EN_MASK, CDC_VA_SWR_CLK_ENABLE); |
1355 | |
1356 | return ret; |
1357 | } |
1358 | |
1359 | static void fsgen_gate_disable(struct clk_hw *hw) |
1360 | { |
1361 | struct va_macro *va = to_va_macro(hw); |
1362 | struct regmap *regmap = va->regmap; |
1363 | |
1364 | if (va->has_swr_master) |
1365 | regmap_update_bits(map: regmap, CDC_VA_CLK_RST_CTRL_SWR_CONTROL, |
1366 | CDC_VA_SWR_CLK_EN_MASK, val: 0x0); |
1367 | |
1368 | va_macro_mclk_enable(va, mclk_enable: false); |
1369 | if (va->has_swr_master) |
1370 | clk_disable_unprepare(clk: va->mclk); |
1371 | } |
1372 | |
1373 | static int fsgen_gate_is_enabled(struct clk_hw *hw) |
1374 | { |
1375 | struct va_macro *va = to_va_macro(hw); |
1376 | int val; |
1377 | |
1378 | regmap_read(map: va->regmap, CDC_VA_TOP_CSR_TOP_CFG0, val: &val); |
1379 | |
1380 | return !!(val & CDC_VA_FS_BROADCAST_EN); |
1381 | } |
1382 | |
1383 | static const struct clk_ops fsgen_gate_ops = { |
1384 | .prepare = fsgen_gate_enable, |
1385 | .unprepare = fsgen_gate_disable, |
1386 | .is_enabled = fsgen_gate_is_enabled, |
1387 | }; |
1388 | |
1389 | static int va_macro_register_fsgen_output(struct va_macro *va) |
1390 | { |
1391 | struct clk *parent = va->mclk; |
1392 | struct device *dev = va->dev; |
1393 | struct device_node *np = dev->of_node; |
1394 | const char *parent_clk_name; |
1395 | const char *clk_name = "fsgen" ; |
1396 | struct clk_init_data init; |
1397 | int ret; |
1398 | |
1399 | if (va->has_npl_clk) |
1400 | parent = va->npl; |
1401 | |
1402 | parent_clk_name = __clk_get_name(clk: parent); |
1403 | |
1404 | of_property_read_string(np, propname: "clock-output-names" , out_string: &clk_name); |
1405 | |
1406 | init.name = clk_name; |
1407 | init.ops = &fsgen_gate_ops; |
1408 | init.flags = 0; |
1409 | init.parent_names = &parent_clk_name; |
1410 | init.num_parents = 1; |
1411 | va->hw.init = &init; |
1412 | ret = devm_clk_hw_register(dev: va->dev, hw: &va->hw); |
1413 | if (ret) |
1414 | return ret; |
1415 | |
1416 | return devm_of_clk_add_hw_provider(dev, get: of_clk_hw_simple_get, data: &va->hw); |
1417 | } |
1418 | |
1419 | static int va_macro_validate_dmic_sample_rate(u32 dmic_sample_rate, |
1420 | struct va_macro *va) |
1421 | { |
1422 | u32 div_factor; |
1423 | u32 mclk_rate = VA_MACRO_MCLK_FREQ; |
1424 | |
1425 | if (!dmic_sample_rate || mclk_rate % dmic_sample_rate != 0) |
1426 | goto undefined_rate; |
1427 | |
1428 | div_factor = mclk_rate / dmic_sample_rate; |
1429 | |
1430 | switch (div_factor) { |
1431 | case 2: |
1432 | va->dmic_clk_div = VA_MACRO_CLK_DIV_2; |
1433 | break; |
1434 | case 3: |
1435 | va->dmic_clk_div = VA_MACRO_CLK_DIV_3; |
1436 | break; |
1437 | case 4: |
1438 | va->dmic_clk_div = VA_MACRO_CLK_DIV_4; |
1439 | break; |
1440 | case 6: |
1441 | va->dmic_clk_div = VA_MACRO_CLK_DIV_6; |
1442 | break; |
1443 | case 8: |
1444 | va->dmic_clk_div = VA_MACRO_CLK_DIV_8; |
1445 | break; |
1446 | case 16: |
1447 | va->dmic_clk_div = VA_MACRO_CLK_DIV_16; |
1448 | break; |
1449 | default: |
1450 | /* Any other DIV factor is invalid */ |
1451 | goto undefined_rate; |
1452 | } |
1453 | |
1454 | return dmic_sample_rate; |
1455 | |
1456 | undefined_rate: |
1457 | dev_err(va->dev, "%s: Invalid rate %d, for mclk %d\n" , |
1458 | __func__, dmic_sample_rate, mclk_rate); |
1459 | dmic_sample_rate = 0; |
1460 | |
1461 | return dmic_sample_rate; |
1462 | } |
1463 | |
1464 | static int va_macro_probe(struct platform_device *pdev) |
1465 | { |
1466 | struct device *dev = &pdev->dev; |
1467 | const struct va_macro_data *data; |
1468 | struct va_macro *va; |
1469 | void __iomem *base; |
1470 | u32 sample_rate = 0; |
1471 | int ret; |
1472 | |
1473 | va = devm_kzalloc(dev, size: sizeof(*va), GFP_KERNEL); |
1474 | if (!va) |
1475 | return -ENOMEM; |
1476 | |
1477 | va->dev = dev; |
1478 | |
1479 | va->macro = devm_clk_get_optional(dev, id: "macro" ); |
1480 | if (IS_ERR(ptr: va->macro)) |
1481 | return dev_err_probe(dev, err: PTR_ERR(ptr: va->macro), fmt: "unable to get macro clock\n" ); |
1482 | |
1483 | va->dcodec = devm_clk_get_optional(dev, id: "dcodec" ); |
1484 | if (IS_ERR(ptr: va->dcodec)) |
1485 | return dev_err_probe(dev, err: PTR_ERR(ptr: va->dcodec), fmt: "unable to get dcodec clock\n" ); |
1486 | |
1487 | va->mclk = devm_clk_get(dev, id: "mclk" ); |
1488 | if (IS_ERR(ptr: va->mclk)) |
1489 | return dev_err_probe(dev, err: PTR_ERR(ptr: va->mclk), fmt: "unable to get mclk clock\n" ); |
1490 | |
1491 | va->pds = lpass_macro_pds_init(dev); |
1492 | if (IS_ERR(ptr: va->pds)) |
1493 | return PTR_ERR(ptr: va->pds); |
1494 | |
1495 | ret = of_property_read_u32(np: dev->of_node, propname: "qcom,dmic-sample-rate" , |
1496 | out_value: &sample_rate); |
1497 | if (ret) { |
1498 | dev_err(dev, "qcom,dmic-sample-rate dt entry missing\n" ); |
1499 | va->dmic_clk_div = VA_MACRO_CLK_DIV_2; |
1500 | } else { |
1501 | ret = va_macro_validate_dmic_sample_rate(dmic_sample_rate: sample_rate, va); |
1502 | if (!ret) { |
1503 | ret = -EINVAL; |
1504 | goto err; |
1505 | } |
1506 | } |
1507 | |
1508 | base = devm_platform_ioremap_resource(pdev, index: 0); |
1509 | if (IS_ERR(ptr: base)) { |
1510 | ret = PTR_ERR(ptr: base); |
1511 | goto err; |
1512 | } |
1513 | |
1514 | va->regmap = devm_regmap_init_mmio(dev, base, &va_regmap_config); |
1515 | if (IS_ERR(ptr: va->regmap)) { |
1516 | ret = -EINVAL; |
1517 | goto err; |
1518 | } |
1519 | |
1520 | dev_set_drvdata(dev, data: va); |
1521 | |
1522 | data = of_device_get_match_data(dev); |
1523 | va->has_swr_master = data->has_swr_master; |
1524 | va->has_npl_clk = data->has_npl_clk; |
1525 | |
1526 | /* mclk rate */ |
1527 | clk_set_rate(clk: va->mclk, rate: 2 * VA_MACRO_MCLK_FREQ); |
1528 | |
1529 | if (va->has_npl_clk) { |
1530 | va->npl = devm_clk_get(dev, id: "npl" ); |
1531 | if (IS_ERR(ptr: va->npl)) { |
1532 | ret = PTR_ERR(ptr: va->npl); |
1533 | goto err; |
1534 | } |
1535 | |
1536 | clk_set_rate(clk: va->npl, rate: 2 * VA_MACRO_MCLK_FREQ); |
1537 | } |
1538 | |
1539 | ret = clk_prepare_enable(clk: va->macro); |
1540 | if (ret) |
1541 | goto err; |
1542 | |
1543 | ret = clk_prepare_enable(clk: va->dcodec); |
1544 | if (ret) |
1545 | goto err_dcodec; |
1546 | |
1547 | ret = clk_prepare_enable(clk: va->mclk); |
1548 | if (ret) |
1549 | goto err_mclk; |
1550 | |
1551 | if (va->has_npl_clk) { |
1552 | ret = clk_prepare_enable(clk: va->npl); |
1553 | if (ret) |
1554 | goto err_npl; |
1555 | } |
1556 | |
1557 | if (va->has_swr_master) { |
1558 | /* Set default CLK div to 1 */ |
1559 | regmap_update_bits(map: va->regmap, CDC_VA_TOP_CSR_SWR_MIC_CTL0, |
1560 | CDC_VA_SWR_MIC_CLK_SEL_0_1_MASK, |
1561 | CDC_VA_SWR_MIC_CLK_SEL_0_1_DIV1); |
1562 | regmap_update_bits(map: va->regmap, CDC_VA_TOP_CSR_SWR_MIC_CTL1, |
1563 | CDC_VA_SWR_MIC_CLK_SEL_0_1_MASK, |
1564 | CDC_VA_SWR_MIC_CLK_SEL_0_1_DIV1); |
1565 | regmap_update_bits(map: va->regmap, CDC_VA_TOP_CSR_SWR_MIC_CTL2, |
1566 | CDC_VA_SWR_MIC_CLK_SEL_0_1_MASK, |
1567 | CDC_VA_SWR_MIC_CLK_SEL_0_1_DIV1); |
1568 | |
1569 | } |
1570 | |
1571 | if (va->has_swr_master) { |
1572 | regmap_update_bits(map: va->regmap, CDC_VA_CLK_RST_CTRL_SWR_CONTROL, |
1573 | CDC_VA_SWR_RESET_MASK, CDC_VA_SWR_RESET_ENABLE); |
1574 | regmap_update_bits(map: va->regmap, CDC_VA_CLK_RST_CTRL_SWR_CONTROL, |
1575 | CDC_VA_SWR_CLK_EN_MASK, CDC_VA_SWR_CLK_ENABLE); |
1576 | regmap_update_bits(map: va->regmap, CDC_VA_CLK_RST_CTRL_SWR_CONTROL, |
1577 | CDC_VA_SWR_RESET_MASK, val: 0x0); |
1578 | } |
1579 | |
1580 | ret = devm_snd_soc_register_component(dev, component_driver: &va_macro_component_drv, |
1581 | dai_drv: va_macro_dais, |
1582 | ARRAY_SIZE(va_macro_dais)); |
1583 | if (ret) |
1584 | goto err_clkout; |
1585 | |
1586 | pm_runtime_set_autosuspend_delay(dev, delay: 3000); |
1587 | pm_runtime_use_autosuspend(dev); |
1588 | pm_runtime_mark_last_busy(dev); |
1589 | pm_runtime_set_active(dev); |
1590 | pm_runtime_enable(dev); |
1591 | |
1592 | ret = va_macro_register_fsgen_output(va); |
1593 | if (ret) |
1594 | goto err_clkout; |
1595 | |
1596 | va->fsgen = clk_hw_get_clk(hw: &va->hw, con_id: "fsgen" ); |
1597 | if (IS_ERR(ptr: va->fsgen)) { |
1598 | ret = PTR_ERR(ptr: va->fsgen); |
1599 | goto err_clkout; |
1600 | } |
1601 | |
1602 | return 0; |
1603 | |
1604 | err_clkout: |
1605 | if (va->has_npl_clk) |
1606 | clk_disable_unprepare(clk: va->npl); |
1607 | err_npl: |
1608 | clk_disable_unprepare(clk: va->mclk); |
1609 | err_mclk: |
1610 | clk_disable_unprepare(clk: va->dcodec); |
1611 | err_dcodec: |
1612 | clk_disable_unprepare(clk: va->macro); |
1613 | err: |
1614 | lpass_macro_pds_exit(pds: va->pds); |
1615 | |
1616 | return ret; |
1617 | } |
1618 | |
1619 | static void va_macro_remove(struct platform_device *pdev) |
1620 | { |
1621 | struct va_macro *va = dev_get_drvdata(dev: &pdev->dev); |
1622 | |
1623 | if (va->has_npl_clk) |
1624 | clk_disable_unprepare(clk: va->npl); |
1625 | |
1626 | clk_disable_unprepare(clk: va->mclk); |
1627 | clk_disable_unprepare(clk: va->dcodec); |
1628 | clk_disable_unprepare(clk: va->macro); |
1629 | |
1630 | lpass_macro_pds_exit(pds: va->pds); |
1631 | } |
1632 | |
1633 | static int __maybe_unused va_macro_runtime_suspend(struct device *dev) |
1634 | { |
1635 | struct va_macro *va = dev_get_drvdata(dev); |
1636 | |
1637 | regcache_cache_only(map: va->regmap, enable: true); |
1638 | regcache_mark_dirty(map: va->regmap); |
1639 | |
1640 | if (va->has_npl_clk) |
1641 | clk_disable_unprepare(clk: va->npl); |
1642 | |
1643 | clk_disable_unprepare(clk: va->mclk); |
1644 | |
1645 | return 0; |
1646 | } |
1647 | |
1648 | static int __maybe_unused va_macro_runtime_resume(struct device *dev) |
1649 | { |
1650 | struct va_macro *va = dev_get_drvdata(dev); |
1651 | int ret; |
1652 | |
1653 | ret = clk_prepare_enable(clk: va->mclk); |
1654 | if (ret) { |
1655 | dev_err(va->dev, "unable to prepare mclk\n" ); |
1656 | return ret; |
1657 | } |
1658 | |
1659 | if (va->has_npl_clk) { |
1660 | ret = clk_prepare_enable(clk: va->npl); |
1661 | if (ret) { |
1662 | clk_disable_unprepare(clk: va->mclk); |
1663 | dev_err(va->dev, "unable to prepare npl\n" ); |
1664 | return ret; |
1665 | } |
1666 | } |
1667 | |
1668 | regcache_cache_only(map: va->regmap, enable: false); |
1669 | regcache_sync(map: va->regmap); |
1670 | |
1671 | return 0; |
1672 | } |
1673 | |
1674 | |
1675 | static const struct dev_pm_ops va_macro_pm_ops = { |
1676 | SET_RUNTIME_PM_OPS(va_macro_runtime_suspend, va_macro_runtime_resume, NULL) |
1677 | }; |
1678 | |
1679 | static const struct of_device_id va_macro_dt_match[] = { |
1680 | { .compatible = "qcom,sc7280-lpass-va-macro" , .data = &sm8250_va_data }, |
1681 | { .compatible = "qcom,sm8250-lpass-va-macro" , .data = &sm8250_va_data }, |
1682 | { .compatible = "qcom,sm8450-lpass-va-macro" , .data = &sm8450_va_data }, |
1683 | { .compatible = "qcom,sm8550-lpass-va-macro" , .data = &sm8550_va_data }, |
1684 | { .compatible = "qcom,sc8280xp-lpass-va-macro" , .data = &sm8450_va_data }, |
1685 | {} |
1686 | }; |
1687 | MODULE_DEVICE_TABLE(of, va_macro_dt_match); |
1688 | |
1689 | static struct platform_driver va_macro_driver = { |
1690 | .driver = { |
1691 | .name = "va_macro" , |
1692 | .of_match_table = va_macro_dt_match, |
1693 | .suppress_bind_attrs = true, |
1694 | .pm = &va_macro_pm_ops, |
1695 | }, |
1696 | .probe = va_macro_probe, |
1697 | .remove_new = va_macro_remove, |
1698 | }; |
1699 | |
1700 | module_platform_driver(va_macro_driver); |
1701 | MODULE_DESCRIPTION("VA macro driver" ); |
1702 | MODULE_LICENSE("GPL" ); |
1703 | |