1 | // SPDX-License-Identifier: GPL-2.0 |
2 | // |
3 | // CS42L43 CODEC driver |
4 | // |
5 | // Copyright (C) 2022-2023 Cirrus Logic, Inc. and |
6 | // Cirrus Logic International Semiconductor Ltd. |
7 | |
8 | #include <linux/bitops.h> |
9 | #include <linux/bits.h> |
10 | #include <linux/clk.h> |
11 | #include <linux/device.h> |
12 | #include <linux/err.h> |
13 | #include <linux/errno.h> |
14 | #include <linux/find.h> |
15 | #include <linux/gcd.h> |
16 | #include <linux/irq.h> |
17 | #include <linux/irqdomain.h> |
18 | #include <linux/jiffies.h> |
19 | #include <linux/mfd/cs42l43.h> |
20 | #include <linux/mfd/cs42l43-regs.h> |
21 | #include <linux/mod_devicetable.h> |
22 | #include <linux/module.h> |
23 | #include <linux/platform_device.h> |
24 | #include <linux/pm_runtime.h> |
25 | #include <linux/regmap.h> |
26 | #include <linux/string.h> |
27 | #include <linux/workqueue.h> |
28 | #include <sound/control.h> |
29 | #include <sound/cs42l43.h> |
30 | #include <sound/pcm.h> |
31 | #include <sound/pcm_params.h> |
32 | #include <sound/soc-component.h> |
33 | #include <sound/soc-dapm.h> |
34 | #include <sound/soc-dai.h> |
35 | #include <sound/soc.h> |
36 | #include <sound/tlv.h> |
37 | |
38 | #include "cs42l43.h" |
39 | |
40 | #define CS42L43_DECL_MUX(name, reg) \ |
41 | static SOC_VALUE_ENUM_SINGLE_DECL(cs42l43_##name##_enum, reg, \ |
42 | 0, CS42L43_MIXER_SRC_MASK, \ |
43 | cs42l43_mixer_texts, cs42l43_mixer_values); \ |
44 | static const struct snd_kcontrol_new cs42l43_##name##_mux = \ |
45 | SOC_DAPM_ENUM("Route", cs42l43_##name##_enum) |
46 | |
47 | #define CS42L43_DECL_MIXER(name, reg) \ |
48 | CS42L43_DECL_MUX(name##_in1, reg); \ |
49 | CS42L43_DECL_MUX(name##_in2, reg + 0x4); \ |
50 | CS42L43_DECL_MUX(name##_in3, reg + 0x8); \ |
51 | CS42L43_DECL_MUX(name##_in4, reg + 0xC) |
52 | |
53 | #define CS42L43_DAPM_MUX(name_str, name) \ |
54 | SND_SOC_DAPM_MUX(name_str " Input", SND_SOC_NOPM, 0, 0, &cs42l43_##name##_mux) |
55 | |
56 | #define CS42L43_DAPM_MIXER(name_str, name) \ |
57 | SND_SOC_DAPM_MUX(name_str " Input 1", SND_SOC_NOPM, 0, 0, &cs42l43_##name##_in1_mux), \ |
58 | SND_SOC_DAPM_MUX(name_str " Input 2", SND_SOC_NOPM, 0, 0, &cs42l43_##name##_in2_mux), \ |
59 | SND_SOC_DAPM_MUX(name_str " Input 3", SND_SOC_NOPM, 0, 0, &cs42l43_##name##_in3_mux), \ |
60 | SND_SOC_DAPM_MUX(name_str " Input 4", SND_SOC_NOPM, 0, 0, &cs42l43_##name##_in4_mux), \ |
61 | SND_SOC_DAPM_MIXER(name_str " Mixer", SND_SOC_NOPM, 0, 0, NULL, 0) |
62 | |
63 | #define CS42L43_BASE_ROUTES(name_str) \ |
64 | { name_str, "Tone Generator 1", "Tone 1" }, \ |
65 | { name_str, "Tone Generator 2", "Tone 2" }, \ |
66 | { name_str, "Decimator 1", "Decimator 1" }, \ |
67 | { name_str, "Decimator 2", "Decimator 2" }, \ |
68 | { name_str, "Decimator 3", "Decimator 3" }, \ |
69 | { name_str, "Decimator 4", "Decimator 4" }, \ |
70 | { name_str, "ASPRX1", "ASPRX1" }, \ |
71 | { name_str, "ASPRX2", "ASPRX2" }, \ |
72 | { name_str, "ASPRX3", "ASPRX3" }, \ |
73 | { name_str, "ASPRX4", "ASPRX4" }, \ |
74 | { name_str, "ASPRX5", "ASPRX5" }, \ |
75 | { name_str, "ASPRX6", "ASPRX6" }, \ |
76 | { name_str, "DP5RX1", "DP5RX1" }, \ |
77 | { name_str, "DP5RX2", "DP5RX2" }, \ |
78 | { name_str, "DP6RX1", "DP6RX1" }, \ |
79 | { name_str, "DP6RX2", "DP6RX2" }, \ |
80 | { name_str, "DP7RX1", "DP7RX1" }, \ |
81 | { name_str, "DP7RX2", "DP7RX2" }, \ |
82 | { name_str, "ASRC INT1", "ASRC_INT1" }, \ |
83 | { name_str, "ASRC INT2", "ASRC_INT2" }, \ |
84 | { name_str, "ASRC INT3", "ASRC_INT3" }, \ |
85 | { name_str, "ASRC INT4", "ASRC_INT4" }, \ |
86 | { name_str, "ASRC DEC1", "ASRC_DEC1" }, \ |
87 | { name_str, "ASRC DEC2", "ASRC_DEC2" }, \ |
88 | { name_str, "ASRC DEC3", "ASRC_DEC3" }, \ |
89 | { name_str, "ASRC DEC4", "ASRC_DEC4" }, \ |
90 | { name_str, "ISRC1 INT1", "ISRC1INT1" }, \ |
91 | { name_str, "ISRC1 INT2", "ISRC1INT2" }, \ |
92 | { name_str, "ISRC1 DEC1", "ISRC1DEC1" }, \ |
93 | { name_str, "ISRC1 DEC2", "ISRC1DEC2" }, \ |
94 | { name_str, "ISRC2 INT1", "ISRC2INT1" }, \ |
95 | { name_str, "ISRC2 INT2", "ISRC2INT2" }, \ |
96 | { name_str, "ISRC2 DEC1", "ISRC2DEC1" }, \ |
97 | { name_str, "ISRC2 DEC2", "ISRC2DEC2" }, \ |
98 | { name_str, "EQ1", "EQ" }, \ |
99 | { name_str, "EQ2", "EQ" } |
100 | |
101 | #define CS42L43_MUX_ROUTES(name_str, widget) \ |
102 | { widget, NULL, name_str " Input" }, \ |
103 | { name_str " Input", NULL, "Mixer Core" }, \ |
104 | CS42L43_BASE_ROUTES(name_str " Input") |
105 | |
106 | #define CS42L43_MIXER_ROUTES(name_str, widget) \ |
107 | { name_str " Mixer", NULL, name_str " Input 1" }, \ |
108 | { name_str " Mixer", NULL, name_str " Input 2" }, \ |
109 | { name_str " Mixer", NULL, name_str " Input 3" }, \ |
110 | { name_str " Mixer", NULL, name_str " Input 4" }, \ |
111 | { widget, NULL, name_str " Mixer" }, \ |
112 | { name_str " Mixer", NULL, "Mixer Core" }, \ |
113 | CS42L43_BASE_ROUTES(name_str " Input 1"), \ |
114 | CS42L43_BASE_ROUTES(name_str " Input 2"), \ |
115 | CS42L43_BASE_ROUTES(name_str " Input 3"), \ |
116 | CS42L43_BASE_ROUTES(name_str " Input 4") |
117 | |
118 | #define CS42L43_MIXER_VOLUMES(name_str, base) \ |
119 | SOC_SINGLE_RANGE_TLV(name_str " Input 1 Volume", base, \ |
120 | CS42L43_MIXER_VOL_SHIFT, 0x20, 0x50, 0, \ |
121 | cs42l43_mixer_tlv), \ |
122 | SOC_SINGLE_RANGE_TLV(name_str " Input 2 Volume", base + 4, \ |
123 | CS42L43_MIXER_VOL_SHIFT, 0x20, 0x50, 0, \ |
124 | cs42l43_mixer_tlv), \ |
125 | SOC_SINGLE_RANGE_TLV(name_str " Input 3 Volume", base + 8, \ |
126 | CS42L43_MIXER_VOL_SHIFT, 0x20, 0x50, 0, \ |
127 | cs42l43_mixer_tlv), \ |
128 | SOC_SINGLE_RANGE_TLV(name_str " Input 4 Volume", base + 12, \ |
129 | CS42L43_MIXER_VOL_SHIFT, 0x20, 0x50, 0, \ |
130 | cs42l43_mixer_tlv) |
131 | |
132 | #define CS42L43_IRQ_ERROR(name) \ |
133 | static irqreturn_t cs42l43_##name(int irq, void *data) \ |
134 | { \ |
135 | struct cs42l43_codec *priv = data; \ |
136 | dev_err(priv->dev, "Error " #name " IRQ\n"); \ |
137 | return IRQ_HANDLED; \ |
138 | } |
139 | |
140 | CS42L43_IRQ_ERROR(pll_lost_lock) |
141 | CS42L43_IRQ_ERROR(spkr_clock_stop) |
142 | CS42L43_IRQ_ERROR(spkl_clock_stop) |
143 | CS42L43_IRQ_ERROR(spkr_brown_out) |
144 | CS42L43_IRQ_ERROR(spkl_brown_out) |
145 | CS42L43_IRQ_ERROR(spkr_therm_shutdown) |
146 | CS42L43_IRQ_ERROR(spkl_therm_shutdown) |
147 | CS42L43_IRQ_ERROR(spkr_therm_warm) |
148 | CS42L43_IRQ_ERROR(spkl_therm_warm) |
149 | CS42L43_IRQ_ERROR(spkr_sc_detect) |
150 | CS42L43_IRQ_ERROR(spkl_sc_detect) |
151 | |
152 | static void cs42l43_hp_ilimit_clear_work(struct work_struct *work) |
153 | { |
154 | struct cs42l43_codec *priv = container_of(work, struct cs42l43_codec, |
155 | hp_ilimit_clear_work.work); |
156 | struct snd_soc_dapm_context *dapm = snd_soc_component_get_dapm(component: priv->component); |
157 | |
158 | snd_soc_dapm_mutex_lock(dapm); |
159 | |
160 | priv->hp_ilimit_count--; |
161 | |
162 | if (priv->hp_ilimit_count) |
163 | queue_delayed_work(wq: system_wq, dwork: &priv->hp_ilimit_clear_work, |
164 | delay: msecs_to_jiffies(CS42L43_HP_ILIMIT_DECAY_MS)); |
165 | |
166 | snd_soc_dapm_mutex_unlock(dapm); |
167 | } |
168 | |
169 | static void cs42l43_hp_ilimit_work(struct work_struct *work) |
170 | { |
171 | struct cs42l43_codec *priv = container_of(work, struct cs42l43_codec, |
172 | hp_ilimit_work); |
173 | struct snd_soc_dapm_context *dapm = snd_soc_component_get_dapm(component: priv->component); |
174 | struct cs42l43 *cs42l43 = priv->core; |
175 | |
176 | snd_soc_dapm_mutex_lock(dapm); |
177 | |
178 | if (priv->hp_ilimit_count < CS42L43_HP_ILIMIT_MAX_COUNT) { |
179 | if (!priv->hp_ilimit_count) |
180 | queue_delayed_work(wq: system_wq, dwork: &priv->hp_ilimit_clear_work, |
181 | delay: msecs_to_jiffies(CS42L43_HP_ILIMIT_DECAY_MS)); |
182 | |
183 | priv->hp_ilimit_count++; |
184 | snd_soc_dapm_mutex_unlock(dapm); |
185 | return; |
186 | } |
187 | |
188 | dev_err(priv->dev, "Disabling headphone for %dmS, due to frequent current limit\n" , |
189 | CS42L43_HP_ILIMIT_BACKOFF_MS); |
190 | |
191 | priv->hp_ilimited = true; |
192 | |
193 | // No need to wait for disable, as just disabling for a period of time |
194 | regmap_update_bits(map: cs42l43->regmap, CS42L43_BLOCK_EN8, |
195 | CS42L43_HP_EN_MASK, val: 0); |
196 | |
197 | snd_soc_dapm_mutex_unlock(dapm); |
198 | |
199 | msleep(CS42L43_HP_ILIMIT_BACKOFF_MS); |
200 | |
201 | snd_soc_dapm_mutex_lock(dapm); |
202 | |
203 | if (priv->hp_ena && !priv->load_detect_running) { |
204 | unsigned long time_left; |
205 | |
206 | reinit_completion(x: &priv->hp_startup); |
207 | |
208 | regmap_update_bits(map: cs42l43->regmap, CS42L43_BLOCK_EN8, |
209 | CS42L43_HP_EN_MASK, val: priv->hp_ena); |
210 | |
211 | time_left = wait_for_completion_timeout(x: &priv->hp_startup, |
212 | timeout: msecs_to_jiffies(CS42L43_HP_TIMEOUT_MS)); |
213 | if (!time_left) |
214 | dev_err(priv->dev, "ilimit HP restore timed out\n" ); |
215 | } |
216 | |
217 | priv->hp_ilimited = false; |
218 | |
219 | snd_soc_dapm_mutex_unlock(dapm); |
220 | } |
221 | |
222 | static irqreturn_t cs42l43_hp_ilimit(int irq, void *data) |
223 | { |
224 | struct cs42l43_codec *priv = data; |
225 | |
226 | dev_dbg(priv->dev, "headphone ilimit IRQ\n" ); |
227 | |
228 | queue_work(wq: system_long_wq, work: &priv->hp_ilimit_work); |
229 | |
230 | return IRQ_HANDLED; |
231 | } |
232 | |
233 | #define CS42L43_IRQ_COMPLETE(name) \ |
234 | static irqreturn_t cs42l43_##name(int irq, void *data) \ |
235 | { \ |
236 | struct cs42l43_codec *priv = data; \ |
237 | dev_dbg(priv->dev, #name " completed\n"); \ |
238 | complete(&priv->name); \ |
239 | return IRQ_HANDLED; \ |
240 | } |
241 | |
242 | CS42L43_IRQ_COMPLETE(pll_ready) |
243 | CS42L43_IRQ_COMPLETE(hp_startup) |
244 | CS42L43_IRQ_COMPLETE(hp_shutdown) |
245 | CS42L43_IRQ_COMPLETE(type_detect) |
246 | CS42L43_IRQ_COMPLETE(spkr_shutdown) |
247 | CS42L43_IRQ_COMPLETE(spkl_shutdown) |
248 | CS42L43_IRQ_COMPLETE(spkr_startup) |
249 | CS42L43_IRQ_COMPLETE(spkl_startup) |
250 | CS42L43_IRQ_COMPLETE(load_detect) |
251 | |
252 | static irqreturn_t cs42l43_mic_shutter(int irq, void *data) |
253 | { |
254 | struct cs42l43_codec *priv = data; |
255 | static const char * const controls[] = { |
256 | "Decimator 1 Switch" , |
257 | "Decimator 2 Switch" , |
258 | "Decimator 3 Switch" , |
259 | "Decimator 4 Switch" , |
260 | }; |
261 | int i, ret; |
262 | |
263 | dev_dbg(priv->dev, "Microphone shutter changed\n" ); |
264 | |
265 | if (!priv->component) |
266 | return IRQ_NONE; |
267 | |
268 | for (i = 0; i < ARRAY_SIZE(controls); i++) { |
269 | ret = snd_soc_component_notify_control(component: priv->component, |
270 | ctl: controls[i]); |
271 | if (ret) |
272 | return IRQ_NONE; |
273 | } |
274 | |
275 | return IRQ_HANDLED; |
276 | } |
277 | |
278 | static irqreturn_t cs42l43_spk_shutter(int irq, void *data) |
279 | { |
280 | struct cs42l43_codec *priv = data; |
281 | int ret; |
282 | |
283 | dev_dbg(priv->dev, "Speaker shutter changed\n" ); |
284 | |
285 | if (!priv->component) |
286 | return IRQ_NONE; |
287 | |
288 | ret = snd_soc_component_notify_control(component: priv->component, |
289 | ctl: "Speaker Digital Switch" ); |
290 | if (ret) |
291 | return IRQ_NONE; |
292 | |
293 | return IRQ_HANDLED; |
294 | } |
295 | |
296 | static const unsigned int cs42l43_sample_rates[] = { |
297 | 8000, 16000, 24000, 32000, 44100, 48000, 96000, 192000, |
298 | }; |
299 | |
300 | #define CS42L43_CONSUMER_RATE_MASK 0xFF |
301 | #define CS42L43_PROVIDER_RATE_MASK 0xEF // 44.1k only supported as consumer |
302 | |
303 | static const struct snd_pcm_hw_constraint_list cs42l43_constraint = { |
304 | .count = ARRAY_SIZE(cs42l43_sample_rates), |
305 | .list = cs42l43_sample_rates, |
306 | }; |
307 | |
308 | static int cs42l43_startup(struct snd_pcm_substream *substream, struct snd_soc_dai *dai) |
309 | { |
310 | struct snd_soc_component *component = dai->component; |
311 | struct cs42l43_codec *priv = snd_soc_component_get_drvdata(c: component); |
312 | struct cs42l43 *cs42l43 = priv->core; |
313 | int provider = !!regmap_test_bits(map: cs42l43->regmap, CS42L43_ASP_CLK_CONFIG2, |
314 | CS42L43_ASP_MASTER_MODE_MASK); |
315 | |
316 | if (provider) |
317 | priv->constraint.mask = CS42L43_PROVIDER_RATE_MASK; |
318 | else |
319 | priv->constraint.mask = CS42L43_CONSUMER_RATE_MASK; |
320 | |
321 | return snd_pcm_hw_constraint_list(runtime: substream->runtime, cond: 0, |
322 | SNDRV_PCM_HW_PARAM_RATE, |
323 | l: &priv->constraint); |
324 | } |
325 | |
326 | static int cs42l43_convert_sample_rate(unsigned int rate) |
327 | { |
328 | switch (rate) { |
329 | case 8000: |
330 | return 0x11; |
331 | case 16000: |
332 | return 0x12; |
333 | case 24000: |
334 | return 0x02; |
335 | case 32000: |
336 | return 0x13; |
337 | case 44100: |
338 | return 0x0B; |
339 | case 48000: |
340 | return 0x03; |
341 | case 96000: |
342 | return 0x04; |
343 | case 192000: |
344 | return 0x05; |
345 | default: |
346 | return -EINVAL; |
347 | } |
348 | } |
349 | |
350 | static int cs42l43_set_sample_rate(struct snd_pcm_substream *substream, |
351 | struct snd_pcm_hw_params *params, |
352 | struct snd_soc_dai *dai) |
353 | { |
354 | struct cs42l43_codec *priv = snd_soc_component_get_drvdata(c: dai->component); |
355 | struct cs42l43 *cs42l43 = priv->core; |
356 | int ret; |
357 | |
358 | ret = cs42l43_convert_sample_rate(rate: params_rate(p: params)); |
359 | if (ret < 0) { |
360 | dev_err(priv->dev, "Failed to convert sample rate: %d\n" , ret); |
361 | return ret; |
362 | } |
363 | |
364 | //FIXME: For now lets just set sample rate 1, this needs expanded in the future |
365 | regmap_update_bits(map: cs42l43->regmap, CS42L43_SAMPLE_RATE1, |
366 | CS42L43_SAMPLE_RATE_MASK, val: ret); |
367 | |
368 | return 0; |
369 | } |
370 | |
371 | static int cs42l43_asp_hw_params(struct snd_pcm_substream *substream, |
372 | struct snd_pcm_hw_params *params, |
373 | struct snd_soc_dai *dai) |
374 | { |
375 | struct cs42l43_codec *priv = snd_soc_component_get_drvdata(c: dai->component); |
376 | struct cs42l43 *cs42l43 = priv->core; |
377 | int dsp_mode = !!regmap_test_bits(map: cs42l43->regmap, CS42L43_ASP_CTRL, |
378 | CS42L43_ASP_FSYNC_MODE_MASK); |
379 | int provider = !!regmap_test_bits(map: cs42l43->regmap, CS42L43_ASP_CLK_CONFIG2, |
380 | CS42L43_ASP_MASTER_MODE_MASK); |
381 | int n_chans = params_channels(p: params); |
382 | int data_width = params_width(p: params); |
383 | int n_slots = n_chans; |
384 | int slot_width = data_width; |
385 | int frame, bclk_target, i; |
386 | unsigned int reg; |
387 | int *slots; |
388 | |
389 | if (priv->n_slots) { |
390 | n_slots = priv->n_slots; |
391 | slot_width = priv->slot_width; |
392 | } |
393 | |
394 | if (!dsp_mode && (n_slots & 0x1)) { |
395 | dev_dbg(priv->dev, "Forcing balanced channels on ASP\n" ); |
396 | n_slots++; |
397 | } |
398 | |
399 | frame = n_slots * slot_width; |
400 | bclk_target = params_rate(p: params) * frame; |
401 | |
402 | if (provider) { |
403 | unsigned int gcd_nm = gcd(a: bclk_target, CS42L43_INTERNAL_SYSCLK); |
404 | int n = bclk_target / gcd_nm; |
405 | int m = CS42L43_INTERNAL_SYSCLK / gcd_nm; |
406 | |
407 | if (n > (CS42L43_ASP_BCLK_N_MASK >> CS42L43_ASP_BCLK_N_SHIFT) || |
408 | m > CS42L43_ASP_BCLK_M_MASK) { |
409 | dev_err(priv->dev, "Can't produce %dHz bclk\n" , bclk_target); |
410 | return -EINVAL; |
411 | } |
412 | |
413 | dev_dbg(priv->dev, "bclk %d/%d = %dHz, with %dx%d frame\n" , |
414 | n, m, bclk_target, n_slots, slot_width); |
415 | |
416 | regmap_update_bits(map: cs42l43->regmap, CS42L43_ASP_CLK_CONFIG1, |
417 | CS42L43_ASP_BCLK_N_MASK | CS42L43_ASP_BCLK_M_MASK, |
418 | val: n << CS42L43_ASP_BCLK_N_SHIFT | |
419 | m << CS42L43_ASP_BCLK_M_SHIFT); |
420 | regmap_update_bits(map: cs42l43->regmap, CS42L43_ASP_FSYNC_CTRL1, |
421 | CS42L43_ASP_FSYNC_M_MASK, val: frame); |
422 | } |
423 | |
424 | regmap_update_bits(map: cs42l43->regmap, CS42L43_ASP_FSYNC_CTRL4, |
425 | CS42L43_ASP_NUM_BCLKS_PER_FSYNC_MASK, |
426 | val: frame << CS42L43_ASP_NUM_BCLKS_PER_FSYNC_SHIFT); |
427 | |
428 | if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) { |
429 | reg = CS42L43_ASP_TX_CH1_CTRL; |
430 | slots = priv->tx_slots; |
431 | } else { |
432 | reg = CS42L43_ASP_RX_CH1_CTRL; |
433 | slots = priv->rx_slots; |
434 | } |
435 | |
436 | for (i = 0; i < n_chans; i++, reg += 4) { |
437 | int slot_phase = dsp_mode | (i & CS42L43_ASP_CH_SLOT_PHASE_MASK); |
438 | int slot_pos; |
439 | |
440 | if (dsp_mode) |
441 | slot_pos = slots[i] * slot_width; |
442 | else |
443 | slot_pos = (slots[i] / 2) * slot_width; |
444 | |
445 | dev_dbg(priv->dev, "Configure channel %d at slot %d (%d,%d)\n" , |
446 | i, slots[i], slot_pos, slot_phase); |
447 | |
448 | regmap_update_bits(map: cs42l43->regmap, reg, |
449 | CS42L43_ASP_CH_WIDTH_MASK | |
450 | CS42L43_ASP_CH_SLOT_MASK | |
451 | CS42L43_ASP_CH_SLOT_PHASE_MASK, |
452 | val: ((data_width - 1) << CS42L43_ASP_CH_WIDTH_SHIFT) | |
453 | (slot_pos << CS42L43_ASP_CH_SLOT_SHIFT) | |
454 | slot_phase); |
455 | } |
456 | |
457 | return cs42l43_set_sample_rate(substream, params, dai); |
458 | } |
459 | |
460 | static int cs42l43_asp_set_fmt(struct snd_soc_dai *dai, unsigned int fmt) |
461 | { |
462 | struct snd_soc_component *component = dai->component; |
463 | struct snd_soc_dapm_context *dapm = snd_soc_component_get_dapm(component); |
464 | struct cs42l43_codec *priv = snd_soc_component_get_drvdata(c: component); |
465 | struct cs42l43 *cs42l43 = priv->core; |
466 | int provider = regmap_test_bits(map: cs42l43->regmap, CS42L43_ASP_CLK_CONFIG2, |
467 | CS42L43_ASP_MASTER_MODE_MASK); |
468 | struct snd_soc_dapm_route routes[] = { |
469 | { "BCLK" , NULL, "FSYNC" }, |
470 | }; |
471 | unsigned int asp_ctrl = 0; |
472 | unsigned int data_ctrl = 0; |
473 | unsigned int fsync_ctrl = 0; |
474 | unsigned int clk_config = 0; |
475 | |
476 | switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { |
477 | case SND_SOC_DAIFMT_DSP_A: |
478 | data_ctrl |= 2 << CS42L43_ASP_FSYNC_FRAME_START_DLY_SHIFT; |
479 | fallthrough; |
480 | case SND_SOC_DAIFMT_DSP_B: |
481 | asp_ctrl |= CS42L43_ASP_FSYNC_MODE_MASK; |
482 | data_ctrl |= CS42L43_ASP_FSYNC_FRAME_START_PHASE_MASK; |
483 | break; |
484 | case SND_SOC_DAIFMT_I2S: |
485 | data_ctrl |= 2 << CS42L43_ASP_FSYNC_FRAME_START_DLY_SHIFT; |
486 | break; |
487 | case SND_SOC_DAIFMT_LEFT_J: |
488 | data_ctrl |= CS42L43_ASP_FSYNC_FRAME_START_PHASE_MASK; |
489 | break; |
490 | default: |
491 | dev_err(priv->dev, "Unsupported DAI format 0x%x\n" , |
492 | fmt & SND_SOC_DAIFMT_FORMAT_MASK); |
493 | return -EINVAL; |
494 | } |
495 | |
496 | switch (fmt & SND_SOC_DAIFMT_CLOCK_PROVIDER_MASK) { |
497 | case SND_SOC_DAIFMT_CBC_CFC: |
498 | if (provider) |
499 | snd_soc_dapm_del_routes(dapm, route: routes, ARRAY_SIZE(routes)); |
500 | break; |
501 | case SND_SOC_DAIFMT_CBP_CFP: |
502 | if (!provider) |
503 | snd_soc_dapm_add_routes(dapm, route: routes, ARRAY_SIZE(routes)); |
504 | clk_config |= CS42L43_ASP_MASTER_MODE_MASK; |
505 | break; |
506 | default: |
507 | dev_err(priv->dev, "Unsupported ASP mode 0x%x\n" , |
508 | fmt & SND_SOC_DAIFMT_MASTER_MASK); |
509 | return -EINVAL; |
510 | } |
511 | |
512 | switch (fmt & SND_SOC_DAIFMT_INV_MASK) { |
513 | case SND_SOC_DAIFMT_NB_NF: |
514 | clk_config |= CS42L43_ASP_BCLK_INV_MASK; /* Yes BCLK_INV = NB */ |
515 | break; |
516 | case SND_SOC_DAIFMT_IB_NF: |
517 | break; |
518 | case SND_SOC_DAIFMT_NB_IF: |
519 | clk_config |= CS42L43_ASP_BCLK_INV_MASK; |
520 | fsync_ctrl |= CS42L43_ASP_FSYNC_IN_INV_MASK | |
521 | CS42L43_ASP_FSYNC_OUT_INV_MASK; |
522 | break; |
523 | case SND_SOC_DAIFMT_IB_IF: |
524 | fsync_ctrl |= CS42L43_ASP_FSYNC_IN_INV_MASK | |
525 | CS42L43_ASP_FSYNC_OUT_INV_MASK; |
526 | break; |
527 | default: |
528 | dev_err(priv->dev, "Unsupported invert mode 0x%x\n" , |
529 | fmt & SND_SOC_DAIFMT_INV_MASK); |
530 | return -EINVAL; |
531 | } |
532 | |
533 | regmap_update_bits(map: cs42l43->regmap, CS42L43_ASP_CTRL, |
534 | CS42L43_ASP_FSYNC_MODE_MASK, |
535 | val: asp_ctrl); |
536 | regmap_update_bits(map: cs42l43->regmap, CS42L43_ASP_DATA_CTRL, |
537 | CS42L43_ASP_FSYNC_FRAME_START_DLY_MASK | |
538 | CS42L43_ASP_FSYNC_FRAME_START_PHASE_MASK, |
539 | val: data_ctrl); |
540 | regmap_update_bits(map: cs42l43->regmap, CS42L43_ASP_CLK_CONFIG2, |
541 | CS42L43_ASP_MASTER_MODE_MASK | |
542 | CS42L43_ASP_BCLK_INV_MASK, |
543 | val: clk_config); |
544 | regmap_update_bits(map: cs42l43->regmap, CS42L43_ASP_FSYNC_CTRL3, |
545 | CS42L43_ASP_FSYNC_IN_INV_MASK | |
546 | CS42L43_ASP_FSYNC_OUT_INV_MASK, |
547 | val: fsync_ctrl); |
548 | |
549 | return 0; |
550 | } |
551 | |
552 | static void cs42l43_mask_to_slots(struct cs42l43_codec *priv, unsigned long mask, |
553 | int *slots, unsigned int nslots) |
554 | { |
555 | int i = 0; |
556 | int slot; |
557 | |
558 | for_each_set_bit(slot, &mask, BITS_PER_TYPE(mask)) { |
559 | if (i == nslots) { |
560 | dev_warn(priv->dev, "Too many channels in TDM mask: %lx\n" , |
561 | mask); |
562 | return; |
563 | } |
564 | |
565 | slots[i++] = slot; |
566 | } |
567 | |
568 | } |
569 | |
570 | static int cs42l43_asp_set_tdm_slot(struct snd_soc_dai *dai, unsigned int tx_mask, |
571 | unsigned int rx_mask, int slots, int slot_width) |
572 | { |
573 | struct snd_soc_component *component = dai->component; |
574 | struct cs42l43_codec *priv = snd_soc_component_get_drvdata(c: component); |
575 | |
576 | priv->n_slots = slots; |
577 | priv->slot_width = slot_width; |
578 | |
579 | if (!slots) { |
580 | tx_mask = CS42L43_DEFAULT_SLOTS; |
581 | rx_mask = CS42L43_DEFAULT_SLOTS; |
582 | } |
583 | |
584 | cs42l43_mask_to_slots(priv, mask: tx_mask, slots: priv->tx_slots, |
585 | ARRAY_SIZE(priv->tx_slots)); |
586 | cs42l43_mask_to_slots(priv, mask: rx_mask, slots: priv->rx_slots, |
587 | ARRAY_SIZE(priv->rx_slots)); |
588 | |
589 | return 0; |
590 | } |
591 | |
592 | static const struct snd_soc_dai_ops cs42l43_asp_ops = { |
593 | .startup = cs42l43_startup, |
594 | .hw_params = cs42l43_asp_hw_params, |
595 | .set_fmt = cs42l43_asp_set_fmt, |
596 | .set_tdm_slot = cs42l43_asp_set_tdm_slot, |
597 | }; |
598 | |
599 | static int cs42l43_sdw_hw_params(struct snd_pcm_substream *substream, |
600 | struct snd_pcm_hw_params *params, |
601 | struct snd_soc_dai *dai) |
602 | { |
603 | int ret; |
604 | |
605 | ret = cs42l43_sdw_add_peripheral(substream, params, dai); |
606 | if (ret) |
607 | return ret; |
608 | |
609 | return cs42l43_set_sample_rate(substream, params, dai); |
610 | }; |
611 | |
612 | static const struct snd_soc_dai_ops cs42l43_sdw_ops = { |
613 | .startup = cs42l43_startup, |
614 | .set_stream = cs42l43_sdw_set_stream, |
615 | .hw_params = cs42l43_sdw_hw_params, |
616 | .hw_free = cs42l43_sdw_remove_peripheral, |
617 | }; |
618 | |
619 | #define CS42L43_ASP_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S24_LE | \ |
620 | SNDRV_PCM_FMTBIT_S32_LE) |
621 | #define CS42L43_SDW_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S24_LE) |
622 | |
623 | static struct snd_soc_dai_driver cs42l43_dais[] = { |
624 | { |
625 | .name = "cs42l43-asp" , |
626 | .ops = &cs42l43_asp_ops, |
627 | .symmetric_rate = 1, |
628 | .capture = { |
629 | .stream_name = "ASP Capture" , |
630 | .channels_min = 1, |
631 | .channels_max = CS42L43_ASP_MAX_CHANNELS, |
632 | .rates = SNDRV_PCM_RATE_KNOT, |
633 | .formats = CS42L43_ASP_FORMATS, |
634 | }, |
635 | .playback = { |
636 | .stream_name = "ASP Playback" , |
637 | .channels_min = 1, |
638 | .channels_max = CS42L43_ASP_MAX_CHANNELS, |
639 | .rates = SNDRV_PCM_RATE_KNOT, |
640 | .formats = CS42L43_ASP_FORMATS, |
641 | }, |
642 | }, |
643 | { |
644 | .name = "cs42l43-dp1" , |
645 | .id = 1, |
646 | .ops = &cs42l43_sdw_ops, |
647 | .capture = { |
648 | .stream_name = "DP1 Capture" , |
649 | .channels_min = 1, |
650 | .channels_max = 4, |
651 | .rates = SNDRV_PCM_RATE_KNOT, |
652 | .formats = CS42L43_SDW_FORMATS, |
653 | }, |
654 | }, |
655 | { |
656 | .name = "cs42l43-dp2" , |
657 | .id = 2, |
658 | .ops = &cs42l43_sdw_ops, |
659 | .capture = { |
660 | .stream_name = "DP2 Capture" , |
661 | .channels_min = 1, |
662 | .channels_max = 2, |
663 | .rates = SNDRV_PCM_RATE_KNOT, |
664 | .formats = CS42L43_SDW_FORMATS, |
665 | }, |
666 | }, |
667 | { |
668 | .name = "cs42l43-dp3" , |
669 | .id = 3, |
670 | .ops = &cs42l43_sdw_ops, |
671 | .capture = { |
672 | .stream_name = "DP3 Capture" , |
673 | .channels_min = 1, |
674 | .channels_max = 2, |
675 | .rates = SNDRV_PCM_RATE_KNOT, |
676 | .formats = CS42L43_SDW_FORMATS, |
677 | }, |
678 | }, |
679 | { |
680 | .name = "cs42l43-dp4" , |
681 | .id = 4, |
682 | .ops = &cs42l43_sdw_ops, |
683 | .capture = { |
684 | .stream_name = "DP4 Capture" , |
685 | .channels_min = 1, |
686 | .channels_max = 2, |
687 | .rates = SNDRV_PCM_RATE_KNOT, |
688 | .formats = CS42L43_SDW_FORMATS, |
689 | }, |
690 | }, |
691 | { |
692 | .name = "cs42l43-dp5" , |
693 | .id = 5, |
694 | .ops = &cs42l43_sdw_ops, |
695 | .playback = { |
696 | .stream_name = "DP5 Playback" , |
697 | .channels_min = 1, |
698 | .channels_max = 2, |
699 | .rates = SNDRV_PCM_RATE_KNOT, |
700 | .formats = CS42L43_SDW_FORMATS, |
701 | }, |
702 | }, |
703 | { |
704 | .name = "cs42l43-dp6" , |
705 | .id = 6, |
706 | .ops = &cs42l43_sdw_ops, |
707 | .playback = { |
708 | .stream_name = "DP6 Playback" , |
709 | .channels_min = 1, |
710 | .channels_max = 2, |
711 | .rates = SNDRV_PCM_RATE_KNOT, |
712 | .formats = CS42L43_SDW_FORMATS, |
713 | }, |
714 | }, |
715 | { |
716 | .name = "cs42l43-dp7" , |
717 | .id = 7, |
718 | .ops = &cs42l43_sdw_ops, |
719 | .playback = { |
720 | .stream_name = "DP7 Playback" , |
721 | .channels_min = 1, |
722 | .channels_max = 2, |
723 | .rates = SNDRV_PCM_RATE_KNOT, |
724 | .formats = CS42L43_SDW_FORMATS, |
725 | }, |
726 | }, |
727 | }; |
728 | |
729 | static const DECLARE_TLV_DB_SCALE(cs42l43_mixer_tlv, -3200, 100, 0); |
730 | |
731 | static const char * const cs42l43_ramp_text[] = { |
732 | "0ms/6dB" , "0.5ms/6dB" , "1ms/6dB" , "2ms/6dB" , "4ms/6dB" , "8ms/6dB" , |
733 | "15ms/6dB" , "30ms/6dB" , |
734 | }; |
735 | |
736 | static const char * const cs42l43_adc1_input_text[] = { "IN1" , "IN2" }; |
737 | |
738 | static SOC_ENUM_SINGLE_DECL(cs42l43_adc1_input, CS42L43_ADC_B_CTRL1, |
739 | CS42L43_ADC_AIN_SEL_SHIFT, |
740 | cs42l43_adc1_input_text); |
741 | |
742 | static const struct snd_kcontrol_new cs42l43_adc1_input_ctl = |
743 | SOC_DAPM_ENUM("ADC1 Input" , cs42l43_adc1_input); |
744 | |
745 | static const char * const cs42l43_dec_mode_text[] = { "ADC" , "PDM" }; |
746 | |
747 | static SOC_ENUM_SINGLE_VIRT_DECL(cs42l43_dec1_mode, cs42l43_dec_mode_text); |
748 | static SOC_ENUM_SINGLE_VIRT_DECL(cs42l43_dec2_mode, cs42l43_dec_mode_text); |
749 | |
750 | static const struct snd_kcontrol_new cs42l43_dec_mode_ctl[] = { |
751 | SOC_DAPM_ENUM("Decimator 1 Mode" , cs42l43_dec1_mode), |
752 | SOC_DAPM_ENUM("Decimator 2 Mode" , cs42l43_dec2_mode), |
753 | }; |
754 | |
755 | static const char * const cs42l43_pdm_clk_text[] = { |
756 | "3.072MHz" , "1.536MHz" , "768kHz" , |
757 | }; |
758 | |
759 | static SOC_ENUM_SINGLE_DECL(cs42l43_pdm1_clk, CS42L43_PDM_CONTROL, |
760 | CS42L43_PDM1_CLK_DIV_SHIFT, cs42l43_pdm_clk_text); |
761 | static SOC_ENUM_SINGLE_DECL(cs42l43_pdm2_clk, CS42L43_PDM_CONTROL, |
762 | CS42L43_PDM2_CLK_DIV_SHIFT, cs42l43_pdm_clk_text); |
763 | |
764 | static DECLARE_TLV_DB_SCALE(cs42l43_adc_tlv, -600, 600, 0); |
765 | static DECLARE_TLV_DB_SCALE(cs42l43_dec_tlv, -6400, 50, 0); |
766 | |
767 | static const char * const cs42l43_wnf_corner_text[] = { |
768 | "160Hz" , "180Hz" , "200Hz" , "220Hz" , "240Hz" , "260Hz" , "280Hz" , "300Hz" , |
769 | }; |
770 | |
771 | static SOC_ENUM_SINGLE_DECL(cs42l43_dec1_wnf_corner, CS42L43_DECIM_HPF_WNF_CTRL1, |
772 | CS42L43_DECIM_WNF_CF_SHIFT, cs42l43_wnf_corner_text); |
773 | static SOC_ENUM_SINGLE_DECL(cs42l43_dec2_wnf_corner, CS42L43_DECIM_HPF_WNF_CTRL2, |
774 | CS42L43_DECIM_WNF_CF_SHIFT, cs42l43_wnf_corner_text); |
775 | static SOC_ENUM_SINGLE_DECL(cs42l43_dec3_wnf_corner, CS42L43_DECIM_HPF_WNF_CTRL3, |
776 | CS42L43_DECIM_WNF_CF_SHIFT, cs42l43_wnf_corner_text); |
777 | static SOC_ENUM_SINGLE_DECL(cs42l43_dec4_wnf_corner, CS42L43_DECIM_HPF_WNF_CTRL4, |
778 | CS42L43_DECIM_WNF_CF_SHIFT, cs42l43_wnf_corner_text); |
779 | |
780 | static const char * const cs42l43_hpf_corner_text[] = { |
781 | "3Hz" , "12Hz" , "48Hz" , "96Hz" , |
782 | }; |
783 | |
784 | static SOC_ENUM_SINGLE_DECL(cs42l43_dec1_hpf_corner, CS42L43_DECIM_HPF_WNF_CTRL1, |
785 | CS42L43_DECIM_HPF_CF_SHIFT, cs42l43_hpf_corner_text); |
786 | static SOC_ENUM_SINGLE_DECL(cs42l43_dec2_hpf_corner, CS42L43_DECIM_HPF_WNF_CTRL2, |
787 | CS42L43_DECIM_HPF_CF_SHIFT, cs42l43_hpf_corner_text); |
788 | static SOC_ENUM_SINGLE_DECL(cs42l43_dec3_hpf_corner, CS42L43_DECIM_HPF_WNF_CTRL3, |
789 | CS42L43_DECIM_HPF_CF_SHIFT, cs42l43_hpf_corner_text); |
790 | static SOC_ENUM_SINGLE_DECL(cs42l43_dec4_hpf_corner, CS42L43_DECIM_HPF_WNF_CTRL4, |
791 | CS42L43_DECIM_HPF_CF_SHIFT, cs42l43_hpf_corner_text); |
792 | |
793 | static SOC_ENUM_SINGLE_DECL(cs42l43_dec1_ramp_up, CS42L43_DECIM_VOL_CTRL_CH1_CH2, |
794 | CS42L43_DECIM1_VI_RAMP_SHIFT, cs42l43_ramp_text); |
795 | static SOC_ENUM_SINGLE_DECL(cs42l43_dec1_ramp_down, CS42L43_DECIM_VOL_CTRL_CH1_CH2, |
796 | CS42L43_DECIM1_VD_RAMP_SHIFT, cs42l43_ramp_text); |
797 | static SOC_ENUM_SINGLE_DECL(cs42l43_dec2_ramp_up, CS42L43_DECIM_VOL_CTRL_CH1_CH2, |
798 | CS42L43_DECIM2_VI_RAMP_SHIFT, cs42l43_ramp_text); |
799 | static SOC_ENUM_SINGLE_DECL(cs42l43_dec2_ramp_down, CS42L43_DECIM_VOL_CTRL_CH1_CH2, |
800 | CS42L43_DECIM2_VD_RAMP_SHIFT, cs42l43_ramp_text); |
801 | static SOC_ENUM_SINGLE_DECL(cs42l43_dec3_ramp_up, CS42L43_DECIM_VOL_CTRL_CH3_CH4, |
802 | CS42L43_DECIM3_VI_RAMP_SHIFT, cs42l43_ramp_text); |
803 | static SOC_ENUM_SINGLE_DECL(cs42l43_dec3_ramp_down, CS42L43_DECIM_VOL_CTRL_CH3_CH4, |
804 | CS42L43_DECIM3_VD_RAMP_SHIFT, cs42l43_ramp_text); |
805 | static SOC_ENUM_SINGLE_DECL(cs42l43_dec4_ramp_up, CS42L43_DECIM_VOL_CTRL_CH3_CH4, |
806 | CS42L43_DECIM4_VI_RAMP_SHIFT, cs42l43_ramp_text); |
807 | static SOC_ENUM_SINGLE_DECL(cs42l43_dec4_ramp_down, CS42L43_DECIM_VOL_CTRL_CH3_CH4, |
808 | CS42L43_DECIM4_VD_RAMP_SHIFT, cs42l43_ramp_text); |
809 | |
810 | static DECLARE_TLV_DB_SCALE(cs42l43_speaker_tlv, -6400, 50, 0); |
811 | |
812 | static SOC_ENUM_SINGLE_DECL(cs42l43_speaker_ramp_up, CS42L43_AMP1_2_VOL_RAMP, |
813 | CS42L43_AMP1_2_VI_RAMP_SHIFT, cs42l43_ramp_text); |
814 | |
815 | static SOC_ENUM_SINGLE_DECL(cs42l43_speaker_ramp_down, CS42L43_AMP1_2_VOL_RAMP, |
816 | CS42L43_AMP1_2_VD_RAMP_SHIFT, cs42l43_ramp_text); |
817 | |
818 | static DECLARE_TLV_DB_SCALE(cs42l43_headphone_tlv, -11450, 50, 1); |
819 | |
820 | static const char * const cs42l43_headphone_ramp_text[] = { |
821 | "1" , "2" , "4" , "6" , "8" , "11" , "12" , "16" , "22" , "24" , "33" , "36" , "44" , |
822 | "48" , "66" , "72" , |
823 | }; |
824 | |
825 | static SOC_ENUM_SINGLE_DECL(cs42l43_headphone_ramp, CS42L43_PGAVOL, |
826 | CS42L43_HP_PATH_VOL_RAMP_SHIFT, |
827 | cs42l43_headphone_ramp_text); |
828 | |
829 | static const char * const cs42l43_tone_freq_text[] = { |
830 | "1kHz" , "2kHz" , "4kHz" , "6kHz" , "8kHz" , |
831 | }; |
832 | |
833 | static SOC_ENUM_SINGLE_DECL(cs42l43_tone1_freq, CS42L43_TONE_CH1_CTRL, |
834 | CS42L43_TONE_FREQ_SHIFT, cs42l43_tone_freq_text); |
835 | |
836 | static SOC_ENUM_SINGLE_DECL(cs42l43_tone2_freq, CS42L43_TONE_CH2_CTRL, |
837 | CS42L43_TONE_FREQ_SHIFT, cs42l43_tone_freq_text); |
838 | |
839 | static const char * const cs42l43_mixer_texts[] = { |
840 | "None" , |
841 | "Tone Generator 1" , "Tone Generator 2" , |
842 | "Decimator 1" , "Decimator 2" , "Decimator 3" , "Decimator 4" , |
843 | "ASPRX1" , "ASPRX2" , "ASPRX3" , "ASPRX4" , "ASPRX5" , "ASPRX6" , |
844 | "DP5RX1" , "DP5RX2" , "DP6RX1" , "DP6RX2" , "DP7RX1" , "DP7RX2" , |
845 | "ASRC INT1" , "ASRC INT2" , "ASRC INT3" , "ASRC INT4" , |
846 | "ASRC DEC1" , "ASRC DEC2" , "ASRC DEC3" , "ASRC DEC4" , |
847 | "ISRC1 INT1" , "ISRC1 INT2" , |
848 | "ISRC1 DEC1" , "ISRC1 DEC2" , |
849 | "ISRC2 INT1" , "ISRC2 INT2" , |
850 | "ISRC2 DEC1" , "ISRC2 DEC2" , |
851 | "EQ1" , "EQ2" , |
852 | }; |
853 | |
854 | static const unsigned int cs42l43_mixer_values[] = { |
855 | 0x00, // None |
856 | 0x04, 0x05, // Tone Generator 1, 2 |
857 | 0x10, 0x11, 0x12, 0x13, // Decimator 1, 2, 3, 4 |
858 | 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, // ASPRX1,2,3,4,5,6 |
859 | 0x28, 0x29, 0x2A, 0x2B, 0x2C, 0x2D, // DP5, 6, 7RX1, 2 |
860 | 0x40, 0x41, 0x42, 0x43, // ASRC INT1, 2, 3, 4 |
861 | 0x44, 0x45, 0x46, 0x47, // ASRC DEC1, 2, 3, 4 |
862 | 0x50, 0x51, // ISRC1 INT1, 2 |
863 | 0x52, 0x53, // ISRC1 DEC1, 2 |
864 | 0x54, 0x55, // ISRC2 INT1, 2 |
865 | 0x56, 0x57, // ISRC2 DEC1, 2 |
866 | 0x58, 0x59, // EQ1, 2 |
867 | }; |
868 | |
869 | CS42L43_DECL_MUX(asptx1, CS42L43_ASPTX1_INPUT); |
870 | CS42L43_DECL_MUX(asptx2, CS42L43_ASPTX2_INPUT); |
871 | CS42L43_DECL_MUX(asptx3, CS42L43_ASPTX3_INPUT); |
872 | CS42L43_DECL_MUX(asptx4, CS42L43_ASPTX4_INPUT); |
873 | CS42L43_DECL_MUX(asptx5, CS42L43_ASPTX5_INPUT); |
874 | CS42L43_DECL_MUX(asptx6, CS42L43_ASPTX6_INPUT); |
875 | |
876 | CS42L43_DECL_MUX(dp1tx1, CS42L43_SWIRE_DP1_CH1_INPUT); |
877 | CS42L43_DECL_MUX(dp1tx2, CS42L43_SWIRE_DP1_CH2_INPUT); |
878 | CS42L43_DECL_MUX(dp1tx3, CS42L43_SWIRE_DP1_CH3_INPUT); |
879 | CS42L43_DECL_MUX(dp1tx4, CS42L43_SWIRE_DP1_CH4_INPUT); |
880 | CS42L43_DECL_MUX(dp2tx1, CS42L43_SWIRE_DP2_CH1_INPUT); |
881 | CS42L43_DECL_MUX(dp2tx2, CS42L43_SWIRE_DP2_CH2_INPUT); |
882 | CS42L43_DECL_MUX(dp3tx1, CS42L43_SWIRE_DP3_CH1_INPUT); |
883 | CS42L43_DECL_MUX(dp3tx2, CS42L43_SWIRE_DP3_CH2_INPUT); |
884 | CS42L43_DECL_MUX(dp4tx1, CS42L43_SWIRE_DP4_CH1_INPUT); |
885 | CS42L43_DECL_MUX(dp4tx2, CS42L43_SWIRE_DP4_CH2_INPUT); |
886 | |
887 | CS42L43_DECL_MUX(asrcint1, CS42L43_ASRC_INT1_INPUT1); |
888 | CS42L43_DECL_MUX(asrcint2, CS42L43_ASRC_INT2_INPUT1); |
889 | CS42L43_DECL_MUX(asrcint3, CS42L43_ASRC_INT3_INPUT1); |
890 | CS42L43_DECL_MUX(asrcint4, CS42L43_ASRC_INT4_INPUT1); |
891 | CS42L43_DECL_MUX(asrcdec1, CS42L43_ASRC_DEC1_INPUT1); |
892 | CS42L43_DECL_MUX(asrcdec2, CS42L43_ASRC_DEC2_INPUT1); |
893 | CS42L43_DECL_MUX(asrcdec3, CS42L43_ASRC_DEC3_INPUT1); |
894 | CS42L43_DECL_MUX(asrcdec4, CS42L43_ASRC_DEC4_INPUT1); |
895 | |
896 | CS42L43_DECL_MUX(isrc1int1, CS42L43_ISRC1INT1_INPUT1); |
897 | CS42L43_DECL_MUX(isrc1int2, CS42L43_ISRC1INT2_INPUT1); |
898 | CS42L43_DECL_MUX(isrc1dec1, CS42L43_ISRC1DEC1_INPUT1); |
899 | CS42L43_DECL_MUX(isrc1dec2, CS42L43_ISRC1DEC2_INPUT1); |
900 | CS42L43_DECL_MUX(isrc2int1, CS42L43_ISRC2INT1_INPUT1); |
901 | CS42L43_DECL_MUX(isrc2int2, CS42L43_ISRC2INT2_INPUT1); |
902 | CS42L43_DECL_MUX(isrc2dec1, CS42L43_ISRC2DEC1_INPUT1); |
903 | CS42L43_DECL_MUX(isrc2dec2, CS42L43_ISRC2DEC2_INPUT1); |
904 | |
905 | CS42L43_DECL_MUX(spdif1, CS42L43_SPDIF1_INPUT1); |
906 | CS42L43_DECL_MUX(spdif2, CS42L43_SPDIF2_INPUT1); |
907 | |
908 | CS42L43_DECL_MIXER(eq1, CS42L43_EQ1MIX_INPUT1); |
909 | CS42L43_DECL_MIXER(eq2, CS42L43_EQ2MIX_INPUT1); |
910 | |
911 | CS42L43_DECL_MIXER(amp1, CS42L43_AMP1MIX_INPUT1); |
912 | CS42L43_DECL_MIXER(amp2, CS42L43_AMP2MIX_INPUT1); |
913 | |
914 | CS42L43_DECL_MIXER(amp3, CS42L43_AMP3MIX_INPUT1); |
915 | CS42L43_DECL_MIXER(amp4, CS42L43_AMP4MIX_INPUT1); |
916 | |
917 | static int cs42l43_dapm_get_volsw(struct snd_kcontrol *kcontrol, |
918 | struct snd_ctl_elem_value *ucontrol) |
919 | { |
920 | struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol); |
921 | struct snd_soc_dapm_context *dapm = snd_soc_component_get_dapm(component); |
922 | int ret; |
923 | |
924 | snd_soc_dapm_mutex_lock(dapm); |
925 | ret = snd_soc_get_volsw(kcontrol, ucontrol); |
926 | snd_soc_dapm_mutex_unlock(dapm); |
927 | |
928 | return ret; |
929 | } |
930 | |
931 | static int cs42l43_dapm_put_volsw(struct snd_kcontrol *kcontrol, |
932 | struct snd_ctl_elem_value *ucontrol) |
933 | { |
934 | struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol); |
935 | struct snd_soc_dapm_context *dapm = snd_soc_component_get_dapm(component); |
936 | int ret; |
937 | |
938 | snd_soc_dapm_mutex_lock(dapm); |
939 | ret = snd_soc_put_volsw(kcontrol, ucontrol); |
940 | snd_soc_dapm_mutex_unlock(dapm); |
941 | |
942 | return ret; |
943 | } |
944 | |
945 | static int cs42l43_dapm_get_enum(struct snd_kcontrol *kcontrol, |
946 | struct snd_ctl_elem_value *ucontrol) |
947 | { |
948 | struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol); |
949 | struct snd_soc_dapm_context *dapm = snd_soc_component_get_dapm(component); |
950 | int ret; |
951 | |
952 | snd_soc_dapm_mutex_lock(dapm); |
953 | ret = snd_soc_get_enum_double(kcontrol, ucontrol); |
954 | snd_soc_dapm_mutex_unlock(dapm); |
955 | |
956 | return ret; |
957 | } |
958 | |
959 | static int cs42l43_dapm_put_enum(struct snd_kcontrol *kcontrol, |
960 | struct snd_ctl_elem_value *ucontrol) |
961 | { |
962 | struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol); |
963 | struct snd_soc_dapm_context *dapm = snd_soc_component_get_dapm(component); |
964 | int ret; |
965 | |
966 | snd_soc_dapm_mutex_lock(dapm); |
967 | ret = snd_soc_put_enum_double(kcontrol, ucontrol); |
968 | snd_soc_dapm_mutex_unlock(dapm); |
969 | |
970 | return ret; |
971 | } |
972 | |
973 | static int cs42l43_eq_get(struct snd_kcontrol *kcontrol, |
974 | struct snd_ctl_elem_value *ucontrol) |
975 | { |
976 | struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol); |
977 | struct cs42l43_codec *priv = snd_soc_component_get_drvdata(c: component); |
978 | |
979 | memcpy(ucontrol->value.integer.value, priv->eq_coeffs, sizeof(priv->eq_coeffs)); |
980 | |
981 | return 0; |
982 | } |
983 | |
984 | static int cs42l43_eq_put(struct snd_kcontrol *kcontrol, |
985 | struct snd_ctl_elem_value *ucontrol) |
986 | { |
987 | struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol); |
988 | struct snd_soc_dapm_context *dapm = snd_soc_component_get_dapm(component); |
989 | struct cs42l43_codec *priv = snd_soc_component_get_drvdata(c: component); |
990 | |
991 | snd_soc_dapm_mutex_lock(dapm); |
992 | |
993 | memcpy(priv->eq_coeffs, ucontrol->value.integer.value, sizeof(priv->eq_coeffs)); |
994 | |
995 | snd_soc_dapm_mutex_unlock(dapm); |
996 | |
997 | return 0; |
998 | } |
999 | |
1000 | static void cs42l43_spk_vu_sync(struct cs42l43_codec *priv) |
1001 | { |
1002 | struct cs42l43 *cs42l43 = priv->core; |
1003 | |
1004 | mutex_lock(&priv->spk_vu_lock); |
1005 | |
1006 | regmap_update_bits(map: cs42l43->regmap, CS42L43_INTP_VOLUME_CTRL1, |
1007 | CS42L43_AMP1_2_VU_MASK, CS42L43_AMP1_2_VU_MASK); |
1008 | regmap_update_bits(map: cs42l43->regmap, CS42L43_INTP_VOLUME_CTRL1, |
1009 | CS42L43_AMP1_2_VU_MASK, val: 0); |
1010 | |
1011 | mutex_unlock(lock: &priv->spk_vu_lock); |
1012 | } |
1013 | |
1014 | static int cs42l43_shutter_get(struct cs42l43_codec *priv, unsigned int shift) |
1015 | { |
1016 | struct cs42l43 *cs42l43 = priv->core; |
1017 | unsigned int val; |
1018 | int ret; |
1019 | |
1020 | ret = pm_runtime_resume_and_get(dev: priv->dev); |
1021 | if (ret) { |
1022 | dev_err(priv->dev, "Failed to resume for shutters: %d\n" , ret); |
1023 | return ret; |
1024 | } |
1025 | |
1026 | /* |
1027 | * SHUTTER_CONTROL is a mix of volatile and non-volatile bits, so must |
1028 | * be cached for the non-volatiles, so drop it from the cache here so |
1029 | * we force a read. |
1030 | */ |
1031 | ret = regcache_drop_region(map: cs42l43->regmap, CS42L43_SHUTTER_CONTROL, |
1032 | CS42L43_SHUTTER_CONTROL); |
1033 | if (ret) { |
1034 | dev_err(priv->dev, "Failed to drop shutter from cache: %d\n" , ret); |
1035 | goto error; |
1036 | } |
1037 | |
1038 | ret = regmap_read(map: cs42l43->regmap, CS42L43_SHUTTER_CONTROL, val: &val); |
1039 | if (ret) { |
1040 | dev_err(priv->dev, "Failed to check shutter status: %d\n" , ret); |
1041 | goto error; |
1042 | } |
1043 | |
1044 | ret = !(val & BIT(shift)); |
1045 | |
1046 | dev_dbg(priv->dev, "%s shutter is %s\n" , |
1047 | BIT(shift) == CS42L43_STATUS_MIC_SHUTTER_MUTE_MASK ? "Mic" : "Speaker" , |
1048 | ret ? "open" : "closed" ); |
1049 | |
1050 | error: |
1051 | pm_runtime_mark_last_busy(dev: priv->dev); |
1052 | pm_runtime_put_autosuspend(dev: priv->dev); |
1053 | |
1054 | return ret; |
1055 | } |
1056 | |
1057 | static int cs42l43_decim_get(struct snd_kcontrol *kcontrol, |
1058 | struct snd_ctl_elem_value *ucontrol) |
1059 | { |
1060 | struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol); |
1061 | struct cs42l43_codec *priv = snd_soc_component_get_drvdata(c: component); |
1062 | int ret; |
1063 | |
1064 | ret = cs42l43_shutter_get(priv, CS42L43_STATUS_MIC_SHUTTER_MUTE_SHIFT); |
1065 | if (ret > 0) |
1066 | ret = cs42l43_dapm_get_volsw(kcontrol, ucontrol); |
1067 | else if (!ret) |
1068 | ucontrol->value.integer.value[0] = ret; |
1069 | |
1070 | return ret; |
1071 | } |
1072 | |
1073 | static int cs42l43_spk_get(struct snd_kcontrol *kcontrol, |
1074 | struct snd_ctl_elem_value *ucontrol) |
1075 | { |
1076 | struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol); |
1077 | struct cs42l43_codec *priv = snd_soc_component_get_drvdata(c: component); |
1078 | int ret; |
1079 | |
1080 | ret = cs42l43_shutter_get(priv, CS42L43_STATUS_SPK_SHUTTER_MUTE_SHIFT); |
1081 | if (ret > 0) |
1082 | ret = snd_soc_get_volsw(kcontrol, ucontrol); |
1083 | else if (!ret) |
1084 | ucontrol->value.integer.value[0] = ret; |
1085 | |
1086 | return ret; |
1087 | } |
1088 | |
1089 | static int cs42l43_spk_put(struct snd_kcontrol *kcontrol, |
1090 | struct snd_ctl_elem_value *ucontrol) |
1091 | { |
1092 | struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol); |
1093 | struct cs42l43_codec *priv = snd_soc_component_get_drvdata(c: component); |
1094 | int ret; |
1095 | |
1096 | ret = snd_soc_put_volsw(kcontrol, ucontrol); |
1097 | if (ret > 0) |
1098 | cs42l43_spk_vu_sync(priv); |
1099 | |
1100 | return ret; |
1101 | } |
1102 | |
1103 | static const struct snd_kcontrol_new cs42l43_controls[] = { |
1104 | SOC_ENUM_EXT("Jack Override" , cs42l43_jack_enum, |
1105 | cs42l43_jack_get, cs42l43_jack_put), |
1106 | |
1107 | SOC_DOUBLE_R_SX_TLV("ADC Volume" , CS42L43_ADC_B_CTRL1, CS42L43_ADC_B_CTRL2, |
1108 | CS42L43_ADC_PGA_GAIN_SHIFT, |
1109 | 0xF, 5, cs42l43_adc_tlv), |
1110 | |
1111 | SOC_DOUBLE("PDM1 Invert Switch" , CS42L43_DMIC_PDM_CTRL, |
1112 | CS42L43_PDM1L_INV_SHIFT, CS42L43_PDM1R_INV_SHIFT, 1, 0), |
1113 | SOC_DOUBLE("PDM2 Invert Switch" , CS42L43_DMIC_PDM_CTRL, |
1114 | CS42L43_PDM2L_INV_SHIFT, CS42L43_PDM2R_INV_SHIFT, 1, 0), |
1115 | SOC_ENUM("PDM1 Clock" , cs42l43_pdm1_clk), |
1116 | SOC_ENUM("PDM2 Clock" , cs42l43_pdm2_clk), |
1117 | |
1118 | SOC_SINGLE("Decimator 1 WNF Switch" , CS42L43_DECIM_HPF_WNF_CTRL1, |
1119 | CS42L43_DECIM_WNF_EN_SHIFT, 1, 0), |
1120 | SOC_SINGLE("Decimator 2 WNF Switch" , CS42L43_DECIM_HPF_WNF_CTRL2, |
1121 | CS42L43_DECIM_WNF_EN_SHIFT, 1, 0), |
1122 | SOC_SINGLE("Decimator 3 WNF Switch" , CS42L43_DECIM_HPF_WNF_CTRL3, |
1123 | CS42L43_DECIM_WNF_EN_SHIFT, 1, 0), |
1124 | SOC_SINGLE("Decimator 4 WNF Switch" , CS42L43_DECIM_HPF_WNF_CTRL4, |
1125 | CS42L43_DECIM_WNF_EN_SHIFT, 1, 0), |
1126 | |
1127 | SOC_ENUM("Decimator 1 WNF Corner Frequency" , cs42l43_dec1_wnf_corner), |
1128 | SOC_ENUM("Decimator 2 WNF Corner Frequency" , cs42l43_dec2_wnf_corner), |
1129 | SOC_ENUM("Decimator 3 WNF Corner Frequency" , cs42l43_dec3_wnf_corner), |
1130 | SOC_ENUM("Decimator 4 WNF Corner Frequency" , cs42l43_dec4_wnf_corner), |
1131 | |
1132 | SOC_SINGLE("Decimator 1 HPF Switch" , CS42L43_DECIM_HPF_WNF_CTRL1, |
1133 | CS42L43_DECIM_HPF_EN_SHIFT, 1, 0), |
1134 | SOC_SINGLE("Decimator 2 HPF Switch" , CS42L43_DECIM_HPF_WNF_CTRL2, |
1135 | CS42L43_DECIM_HPF_EN_SHIFT, 1, 0), |
1136 | SOC_SINGLE("Decimator 3 HPF Switch" , CS42L43_DECIM_HPF_WNF_CTRL3, |
1137 | CS42L43_DECIM_HPF_EN_SHIFT, 1, 0), |
1138 | SOC_SINGLE("Decimator 4 HPF Switch" , CS42L43_DECIM_HPF_WNF_CTRL4, |
1139 | CS42L43_DECIM_HPF_EN_SHIFT, 1, 0), |
1140 | |
1141 | SOC_ENUM("Decimator 1 HPF Corner Frequency" , cs42l43_dec1_hpf_corner), |
1142 | SOC_ENUM("Decimator 2 HPF Corner Frequency" , cs42l43_dec2_hpf_corner), |
1143 | SOC_ENUM("Decimator 3 HPF Corner Frequency" , cs42l43_dec3_hpf_corner), |
1144 | SOC_ENUM("Decimator 4 HPF Corner Frequency" , cs42l43_dec4_hpf_corner), |
1145 | |
1146 | SOC_SINGLE_TLV("Decimator 1 Volume" , CS42L43_DECIM_VOL_CTRL_CH1_CH2, |
1147 | CS42L43_DECIM1_VOL_SHIFT, 0xBF, 0, cs42l43_dec_tlv), |
1148 | SOC_SINGLE_EXT("Decimator 1 Switch" , CS42L43_DECIM_VOL_CTRL_CH1_CH2, |
1149 | CS42L43_DECIM1_MUTE_SHIFT, 1, 1, |
1150 | cs42l43_decim_get, cs42l43_dapm_put_volsw), |
1151 | SOC_SINGLE_TLV("Decimator 2 Volume" , CS42L43_DECIM_VOL_CTRL_CH1_CH2, |
1152 | CS42L43_DECIM2_VOL_SHIFT, 0xBF, 0, cs42l43_dec_tlv), |
1153 | SOC_SINGLE_EXT("Decimator 2 Switch" , CS42L43_DECIM_VOL_CTRL_CH1_CH2, |
1154 | CS42L43_DECIM2_MUTE_SHIFT, 1, 1, |
1155 | cs42l43_decim_get, cs42l43_dapm_put_volsw), |
1156 | SOC_SINGLE_TLV("Decimator 3 Volume" , CS42L43_DECIM_VOL_CTRL_CH3_CH4, |
1157 | CS42L43_DECIM3_VOL_SHIFT, 0xBF, 0, cs42l43_dec_tlv), |
1158 | SOC_SINGLE_EXT("Decimator 3 Switch" , CS42L43_DECIM_VOL_CTRL_CH3_CH4, |
1159 | CS42L43_DECIM3_MUTE_SHIFT, 1, 1, |
1160 | cs42l43_decim_get, cs42l43_dapm_put_volsw), |
1161 | SOC_SINGLE_TLV("Decimator 4 Volume" , CS42L43_DECIM_VOL_CTRL_CH3_CH4, |
1162 | CS42L43_DECIM4_VOL_SHIFT, 0xBF, 0, cs42l43_dec_tlv), |
1163 | SOC_SINGLE_EXT("Decimator 4 Switch" , CS42L43_DECIM_VOL_CTRL_CH3_CH4, |
1164 | CS42L43_DECIM4_MUTE_SHIFT, 1, 1, |
1165 | cs42l43_decim_get, cs42l43_dapm_put_volsw), |
1166 | |
1167 | SOC_ENUM_EXT("Decimator 1 Ramp Up" , cs42l43_dec1_ramp_up, |
1168 | cs42l43_dapm_get_enum, cs42l43_dapm_put_enum), |
1169 | SOC_ENUM_EXT("Decimator 1 Ramp Down" , cs42l43_dec1_ramp_down, |
1170 | cs42l43_dapm_get_enum, cs42l43_dapm_put_enum), |
1171 | SOC_ENUM_EXT("Decimator 2 Ramp Up" , cs42l43_dec2_ramp_up, |
1172 | cs42l43_dapm_get_enum, cs42l43_dapm_put_enum), |
1173 | SOC_ENUM_EXT("Decimator 2 Ramp Down" , cs42l43_dec2_ramp_down, |
1174 | cs42l43_dapm_get_enum, cs42l43_dapm_put_enum), |
1175 | SOC_ENUM_EXT("Decimator 3 Ramp Up" , cs42l43_dec3_ramp_up, |
1176 | cs42l43_dapm_get_enum, cs42l43_dapm_put_enum), |
1177 | SOC_ENUM_EXT("Decimator 3 Ramp Down" , cs42l43_dec3_ramp_down, |
1178 | cs42l43_dapm_get_enum, cs42l43_dapm_put_enum), |
1179 | SOC_ENUM_EXT("Decimator 4 Ramp Up" , cs42l43_dec4_ramp_up, |
1180 | cs42l43_dapm_get_enum, cs42l43_dapm_put_enum), |
1181 | SOC_ENUM_EXT("Decimator 4 Ramp Down" , cs42l43_dec4_ramp_down, |
1182 | cs42l43_dapm_get_enum, cs42l43_dapm_put_enum), |
1183 | |
1184 | SOC_DOUBLE_R_EXT("Speaker Digital Switch" , |
1185 | CS42L43_INTP_VOLUME_CTRL1, CS42L43_INTP_VOLUME_CTRL2, |
1186 | CS42L43_AMP_MUTE_SHIFT, 1, 1, |
1187 | cs42l43_spk_get, cs42l43_spk_put), |
1188 | |
1189 | SOC_DOUBLE_R_EXT_TLV("Speaker Digital Volume" , |
1190 | CS42L43_INTP_VOLUME_CTRL1, CS42L43_INTP_VOLUME_CTRL2, |
1191 | CS42L43_AMP_VOL_SHIFT, |
1192 | 0xBF, 0, snd_soc_get_volsw, cs42l43_spk_put, |
1193 | cs42l43_speaker_tlv), |
1194 | |
1195 | SOC_ENUM("Speaker Ramp Up" , cs42l43_speaker_ramp_up), |
1196 | SOC_ENUM("Speaker Ramp Down" , cs42l43_speaker_ramp_down), |
1197 | |
1198 | CS42L43_MIXER_VOLUMES("Speaker L" , CS42L43_AMP1MIX_INPUT1), |
1199 | CS42L43_MIXER_VOLUMES("Speaker R" , CS42L43_AMP2MIX_INPUT1), |
1200 | |
1201 | SOC_DOUBLE_SX_TLV("Headphone Digital Volume" , CS42L43_HPPATHVOL, |
1202 | CS42L43_AMP3_PATH_VOL_SHIFT, CS42L43_AMP4_PATH_VOL_SHIFT, |
1203 | 0x11B, 229, cs42l43_headphone_tlv), |
1204 | |
1205 | SOC_DOUBLE("Headphone Invert Switch" , CS42L43_DACCNFG1, |
1206 | CS42L43_AMP3_INV_SHIFT, CS42L43_AMP4_INV_SHIFT, 1, 0), |
1207 | |
1208 | SOC_SINGLE("Headphone Zero Cross Switch" , CS42L43_PGAVOL, |
1209 | CS42L43_HP_PATH_VOL_ZC_SHIFT, 1, 0), |
1210 | SOC_SINGLE("Headphone Ramp Switch" , CS42L43_PGAVOL, |
1211 | CS42L43_HP_PATH_VOL_SFT_SHIFT, 1, 0), |
1212 | SOC_ENUM("Headphone Ramp Rate" , cs42l43_headphone_ramp), |
1213 | |
1214 | CS42L43_MIXER_VOLUMES("Headphone L" , CS42L43_AMP3MIX_INPUT1), |
1215 | CS42L43_MIXER_VOLUMES("Headphone R" , CS42L43_AMP4MIX_INPUT1), |
1216 | |
1217 | SOC_ENUM("Tone 1 Frequency" , cs42l43_tone1_freq), |
1218 | SOC_ENUM("Tone 2 Frequency" , cs42l43_tone2_freq), |
1219 | |
1220 | SOC_DOUBLE_EXT("EQ Switch" , |
1221 | CS42L43_MUTE_EQ_IN0, CS42L43_MUTE_EQ_CH1_SHIFT, |
1222 | CS42L43_MUTE_EQ_CH2_SHIFT, 1, 1, |
1223 | cs42l43_dapm_get_volsw, cs42l43_dapm_put_volsw), |
1224 | |
1225 | SND_SOC_BYTES_E("EQ Coefficients" , 0, CS42L43_N_EQ_COEFFS, |
1226 | cs42l43_eq_get, cs42l43_eq_put), |
1227 | |
1228 | CS42L43_MIXER_VOLUMES("EQ1" , CS42L43_EQ1MIX_INPUT1), |
1229 | CS42L43_MIXER_VOLUMES("EQ2" , CS42L43_EQ2MIX_INPUT1), |
1230 | }; |
1231 | |
1232 | static int cs42l43_eq_ev(struct snd_soc_dapm_widget *w, |
1233 | struct snd_kcontrol *kcontrol, int event) |
1234 | { |
1235 | struct snd_soc_component *component = snd_soc_dapm_to_component(dapm: w->dapm); |
1236 | struct cs42l43_codec *priv = snd_soc_component_get_drvdata(c: component); |
1237 | struct cs42l43 *cs42l43 = priv->core; |
1238 | unsigned int val; |
1239 | int i, ret; |
1240 | |
1241 | switch (event) { |
1242 | case SND_SOC_DAPM_PRE_PMU: |
1243 | regmap_update_bits(map: cs42l43->regmap, CS42L43_MUTE_EQ_IN0, |
1244 | CS42L43_MUTE_EQ_CH1_MASK | CS42L43_MUTE_EQ_CH2_MASK, |
1245 | CS42L43_MUTE_EQ_CH1_MASK | CS42L43_MUTE_EQ_CH2_MASK); |
1246 | |
1247 | regmap_update_bits(map: cs42l43->regmap, CS42L43_COEFF_RD_WR0, |
1248 | CS42L43_WRITE_MODE_MASK, CS42L43_WRITE_MODE_MASK); |
1249 | |
1250 | for (i = 0; i < CS42L43_N_EQ_COEFFS; i++) |
1251 | regmap_write(map: cs42l43->regmap, CS42L43_COEFF_DATA_IN0, |
1252 | val: priv->eq_coeffs[i]); |
1253 | |
1254 | regmap_update_bits(map: cs42l43->regmap, CS42L43_COEFF_RD_WR0, |
1255 | CS42L43_WRITE_MODE_MASK, val: 0); |
1256 | |
1257 | return 0; |
1258 | case SND_SOC_DAPM_POST_PMU: |
1259 | ret = regmap_read_poll_timeout(cs42l43->regmap, CS42L43_INIT_DONE0, |
1260 | val, (val & CS42L43_INITIALIZE_DONE_MASK), |
1261 | 2000, 10000); |
1262 | if (ret) |
1263 | dev_err(priv->dev, "Failed to start EQs: %d\n" , ret); |
1264 | |
1265 | regmap_update_bits(map: cs42l43->regmap, CS42L43_MUTE_EQ_IN0, |
1266 | CS42L43_MUTE_EQ_CH1_MASK | CS42L43_MUTE_EQ_CH2_MASK, val: 0); |
1267 | return ret; |
1268 | default: |
1269 | return 0; |
1270 | } |
1271 | } |
1272 | |
1273 | struct cs42l43_pll_config { |
1274 | unsigned int freq; |
1275 | |
1276 | unsigned int div; |
1277 | unsigned int mode; |
1278 | unsigned int cal; |
1279 | }; |
1280 | |
1281 | static const struct cs42l43_pll_config cs42l43_pll_configs[] = { |
1282 | { 2400000, 0x50000000, 0x1, 0xA4 }, |
1283 | { 3000000, 0x40000000, 0x1, 0x83 }, |
1284 | { 3072000, 0x40000000, 0x3, 0x80 }, |
1285 | }; |
1286 | |
1287 | static int cs42l43_set_pll(struct cs42l43_codec *priv, unsigned int src, |
1288 | unsigned int freq) |
1289 | { |
1290 | struct cs42l43 *cs42l43 = priv->core; |
1291 | |
1292 | lockdep_assert_held(&cs42l43->pll_lock); |
1293 | |
1294 | if (priv->refclk_src == src && priv->refclk_freq == freq) |
1295 | return 0; |
1296 | |
1297 | if (regmap_test_bits(map: cs42l43->regmap, CS42L43_CTRL_REG, CS42L43_PLL_EN_MASK)) { |
1298 | dev_err(priv->dev, "PLL active, can't change configuration\n" ); |
1299 | return -EBUSY; |
1300 | } |
1301 | |
1302 | switch (src) { |
1303 | case CS42L43_SYSCLK_MCLK: |
1304 | case CS42L43_SYSCLK_SDW: |
1305 | dev_dbg(priv->dev, "Source PLL from %s at %uHz\n" , |
1306 | src ? "SoundWire" : "MCLK" , freq); |
1307 | |
1308 | priv->refclk_src = src; |
1309 | priv->refclk_freq = freq; |
1310 | |
1311 | return 0; |
1312 | default: |
1313 | dev_err(priv->dev, "Invalid PLL source: 0x%x\n" , src); |
1314 | return -EINVAL; |
1315 | } |
1316 | } |
1317 | |
1318 | static int cs42l43_enable_pll(struct cs42l43_codec *priv) |
1319 | { |
1320 | static const struct reg_sequence enable_seq[] = { |
1321 | { CS42L43_OSC_DIV_SEL, 0x0, }, |
1322 | { CS42L43_MCLK_SRC_SEL, CS42L43_OSC_PLL_MCLK_SEL_MASK, 5, }, |
1323 | }; |
1324 | struct cs42l43 *cs42l43 = priv->core; |
1325 | const struct cs42l43_pll_config *config = NULL; |
1326 | unsigned int div = 0; |
1327 | unsigned int freq = priv->refclk_freq; |
1328 | unsigned long time_left; |
1329 | |
1330 | lockdep_assert_held(&cs42l43->pll_lock); |
1331 | |
1332 | if (priv->refclk_src == CS42L43_SYSCLK_SDW) { |
1333 | if (!freq) |
1334 | freq = cs42l43->sdw_freq; |
1335 | else if (!cs42l43->sdw_freq) |
1336 | cs42l43->sdw_freq = freq; |
1337 | } |
1338 | |
1339 | dev_dbg(priv->dev, "Enabling PLL at %uHz\n" , freq); |
1340 | |
1341 | div = fls(x: freq) - |
1342 | fls(x: cs42l43_pll_configs[ARRAY_SIZE(cs42l43_pll_configs) - 1].freq); |
1343 | freq >>= div; |
1344 | |
1345 | if (div <= CS42L43_PLL_REFCLK_DIV_MASK) { |
1346 | int i; |
1347 | |
1348 | for (i = 0; i < ARRAY_SIZE(cs42l43_pll_configs); i++) { |
1349 | if (freq == cs42l43_pll_configs[i].freq) { |
1350 | config = &cs42l43_pll_configs[i]; |
1351 | break; |
1352 | } |
1353 | } |
1354 | } |
1355 | |
1356 | if (!config) { |
1357 | dev_err(priv->dev, "No suitable PLL config: 0x%x, %uHz\n" , div, freq); |
1358 | return -EINVAL; |
1359 | } |
1360 | |
1361 | regmap_update_bits(map: cs42l43->regmap, CS42L43_PLL_CONTROL, |
1362 | CS42L43_PLL_REFCLK_DIV_MASK | CS42L43_PLL_REFCLK_SRC_MASK, |
1363 | val: div << CS42L43_PLL_REFCLK_DIV_SHIFT | |
1364 | priv->refclk_src << CS42L43_PLL_REFCLK_SRC_SHIFT); |
1365 | regmap_write(map: cs42l43->regmap, CS42L43_FDIV_FRAC, val: config->div); |
1366 | regmap_update_bits(map: cs42l43->regmap, CS42L43_CTRL_REG, |
1367 | CS42L43_PLL_MODE_BYPASS_500_MASK | |
1368 | CS42L43_PLL_MODE_BYPASS_1029_MASK, |
1369 | val: config->mode << CS42L43_PLL_MODE_BYPASS_1029_SHIFT); |
1370 | regmap_update_bits(map: cs42l43->regmap, CS42L43_CAL_RATIO, |
1371 | CS42L43_PLL_CAL_RATIO_MASK, val: config->cal); |
1372 | regmap_update_bits(map: cs42l43->regmap, CS42L43_PLL_CONTROL, |
1373 | CS42L43_PLL_REFCLK_EN_MASK, CS42L43_PLL_REFCLK_EN_MASK); |
1374 | |
1375 | reinit_completion(x: &priv->pll_ready); |
1376 | |
1377 | regmap_update_bits(map: cs42l43->regmap, CS42L43_CTRL_REG, |
1378 | CS42L43_PLL_EN_MASK, CS42L43_PLL_EN_MASK); |
1379 | |
1380 | time_left = wait_for_completion_timeout(x: &priv->pll_ready, |
1381 | timeout: msecs_to_jiffies(CS42L43_PLL_TIMEOUT_MS)); |
1382 | if (!time_left) { |
1383 | regmap_update_bits(map: cs42l43->regmap, CS42L43_CTRL_REG, |
1384 | CS42L43_PLL_EN_MASK, val: 0); |
1385 | regmap_update_bits(map: cs42l43->regmap, CS42L43_PLL_CONTROL, |
1386 | CS42L43_PLL_REFCLK_EN_MASK, val: 0); |
1387 | |
1388 | dev_err(priv->dev, "Timeout out waiting for PLL\n" ); |
1389 | return -ETIMEDOUT; |
1390 | } |
1391 | |
1392 | if (priv->refclk_src == CS42L43_SYSCLK_SDW) |
1393 | cs42l43->sdw_pll_active = true; |
1394 | |
1395 | dev_dbg(priv->dev, "PLL locked in %ums\n" , 200 - jiffies_to_msecs(time_left)); |
1396 | |
1397 | /* |
1398 | * Reads are not allowed over Soundwire without OSC_DIV2_EN or the PLL, |
1399 | * but you can not change to PLL with OSC_DIV2_EN set. So ensure the whole |
1400 | * change over happens under the regmap lock to prevent any reads. |
1401 | */ |
1402 | regmap_multi_reg_write(map: cs42l43->regmap, regs: enable_seq, ARRAY_SIZE(enable_seq)); |
1403 | |
1404 | return 0; |
1405 | } |
1406 | |
1407 | static int cs42l43_disable_pll(struct cs42l43_codec *priv) |
1408 | { |
1409 | static const struct reg_sequence disable_seq[] = { |
1410 | { CS42L43_MCLK_SRC_SEL, 0x0, 5, }, |
1411 | { CS42L43_OSC_DIV_SEL, CS42L43_OSC_DIV2_EN_MASK, }, |
1412 | }; |
1413 | struct cs42l43 *cs42l43 = priv->core; |
1414 | |
1415 | dev_dbg(priv->dev, "Disabling PLL\n" ); |
1416 | |
1417 | lockdep_assert_held(&cs42l43->pll_lock); |
1418 | |
1419 | regmap_multi_reg_write(map: cs42l43->regmap, regs: disable_seq, ARRAY_SIZE(disable_seq)); |
1420 | regmap_update_bits(map: cs42l43->regmap, CS42L43_CTRL_REG, CS42L43_PLL_EN_MASK, val: 0); |
1421 | regmap_update_bits(map: cs42l43->regmap, CS42L43_PLL_CONTROL, |
1422 | CS42L43_PLL_REFCLK_EN_MASK, val: 0); |
1423 | |
1424 | cs42l43->sdw_pll_active = false; |
1425 | |
1426 | return 0; |
1427 | } |
1428 | |
1429 | static int cs42l43_pll_ev(struct snd_soc_dapm_widget *w, |
1430 | struct snd_kcontrol *kcontrol, int event) |
1431 | { |
1432 | struct snd_soc_component *component = snd_soc_dapm_to_component(dapm: w->dapm); |
1433 | struct cs42l43_codec *priv = snd_soc_component_get_drvdata(c: component); |
1434 | struct cs42l43 *cs42l43 = priv->core; |
1435 | int ret; |
1436 | |
1437 | mutex_lock(&cs42l43->pll_lock); |
1438 | |
1439 | switch (event) { |
1440 | case SND_SOC_DAPM_PRE_PMU: |
1441 | if (priv->refclk_src == CS42L43_SYSCLK_MCLK) { |
1442 | ret = clk_prepare_enable(clk: priv->mclk); |
1443 | if (ret) { |
1444 | dev_err(priv->dev, "Failed to enable MCLK: %d\n" , ret); |
1445 | break; |
1446 | } |
1447 | } |
1448 | |
1449 | ret = cs42l43_enable_pll(priv); |
1450 | break; |
1451 | case SND_SOC_DAPM_POST_PMD: |
1452 | ret = cs42l43_disable_pll(priv); |
1453 | |
1454 | if (priv->refclk_src == CS42L43_SYSCLK_MCLK) |
1455 | clk_disable_unprepare(clk: priv->mclk); |
1456 | break; |
1457 | default: |
1458 | ret = 0; |
1459 | break; |
1460 | } |
1461 | |
1462 | mutex_unlock(lock: &cs42l43->pll_lock); |
1463 | |
1464 | return ret; |
1465 | } |
1466 | |
1467 | static int cs42l43_dapm_wait_completion(struct completion *pmu, struct completion *pmd, |
1468 | int event, int timeout_ms) |
1469 | { |
1470 | unsigned long time_left; |
1471 | |
1472 | switch (event) { |
1473 | case SND_SOC_DAPM_PRE_PMU: |
1474 | reinit_completion(x: pmu); |
1475 | return 0; |
1476 | case SND_SOC_DAPM_PRE_PMD: |
1477 | reinit_completion(x: pmd); |
1478 | return 0; |
1479 | case SND_SOC_DAPM_POST_PMU: |
1480 | time_left = wait_for_completion_timeout(x: pmu, timeout: msecs_to_jiffies(m: timeout_ms)); |
1481 | break; |
1482 | case SND_SOC_DAPM_POST_PMD: |
1483 | time_left = wait_for_completion_timeout(x: pmd, timeout: msecs_to_jiffies(m: timeout_ms)); |
1484 | break; |
1485 | default: |
1486 | return 0; |
1487 | } |
1488 | |
1489 | if (!time_left) |
1490 | return -ETIMEDOUT; |
1491 | else |
1492 | return 0; |
1493 | } |
1494 | |
1495 | static int cs42l43_spkr_ev(struct snd_soc_dapm_widget *w, |
1496 | struct snd_kcontrol *kcontrol, int event) |
1497 | { |
1498 | struct snd_soc_component *component = snd_soc_dapm_to_component(dapm: w->dapm); |
1499 | struct cs42l43_codec *priv = snd_soc_component_get_drvdata(c: component); |
1500 | |
1501 | return cs42l43_dapm_wait_completion(pmu: &priv->spkr_startup, |
1502 | pmd: &priv->spkr_shutdown, event, |
1503 | CS42L43_SPK_TIMEOUT_MS); |
1504 | } |
1505 | |
1506 | static int cs42l43_spkl_ev(struct snd_soc_dapm_widget *w, |
1507 | struct snd_kcontrol *kcontrol, int event) |
1508 | { |
1509 | struct snd_soc_component *component = snd_soc_dapm_to_component(dapm: w->dapm); |
1510 | struct cs42l43_codec *priv = snd_soc_component_get_drvdata(c: component); |
1511 | |
1512 | return cs42l43_dapm_wait_completion(pmu: &priv->spkl_startup, |
1513 | pmd: &priv->spkl_shutdown, event, |
1514 | CS42L43_SPK_TIMEOUT_MS); |
1515 | } |
1516 | |
1517 | static int cs42l43_hp_ev(struct snd_soc_dapm_widget *w, |
1518 | struct snd_kcontrol *kcontrol, int event) |
1519 | { |
1520 | struct snd_soc_component *component = snd_soc_dapm_to_component(dapm: w->dapm); |
1521 | struct cs42l43_codec *priv = snd_soc_component_get_drvdata(c: component); |
1522 | struct cs42l43 *cs42l43 = priv->core; |
1523 | unsigned int mask = 1 << w->shift; |
1524 | unsigned int val = 0; |
1525 | int ret; |
1526 | |
1527 | switch (event) { |
1528 | case SND_SOC_DAPM_PRE_PMU: |
1529 | val = mask; |
1530 | fallthrough; |
1531 | case SND_SOC_DAPM_PRE_PMD: |
1532 | priv->hp_ena &= ~mask; |
1533 | priv->hp_ena |= val; |
1534 | |
1535 | ret = cs42l43_dapm_wait_completion(pmu: &priv->hp_startup, |
1536 | pmd: &priv->hp_shutdown, event, |
1537 | CS42L43_HP_TIMEOUT_MS); |
1538 | if (ret) |
1539 | return ret; |
1540 | |
1541 | if (!priv->load_detect_running && !priv->hp_ilimited) |
1542 | regmap_update_bits(map: cs42l43->regmap, CS42L43_BLOCK_EN8, |
1543 | mask, val); |
1544 | break; |
1545 | case SND_SOC_DAPM_POST_PMU: |
1546 | case SND_SOC_DAPM_POST_PMD: |
1547 | if (priv->load_detect_running || priv->hp_ilimited) |
1548 | break; |
1549 | |
1550 | ret = cs42l43_dapm_wait_completion(pmu: &priv->hp_startup, |
1551 | pmd: &priv->hp_shutdown, event, |
1552 | CS42L43_HP_TIMEOUT_MS); |
1553 | if (ret) |
1554 | return ret; |
1555 | break; |
1556 | default: |
1557 | break; |
1558 | } |
1559 | |
1560 | return 0; |
1561 | } |
1562 | |
1563 | static int cs42l43_mic_ev(struct snd_soc_dapm_widget *w, |
1564 | struct snd_kcontrol *kcontrol, int event) |
1565 | { |
1566 | struct snd_soc_component *component = snd_soc_dapm_to_component(dapm: w->dapm); |
1567 | struct cs42l43_codec *priv = snd_soc_component_get_drvdata(c: component); |
1568 | struct cs42l43 *cs42l43 = priv->core; |
1569 | unsigned int reg, ramp, mute; |
1570 | unsigned int *val; |
1571 | int ret; |
1572 | |
1573 | switch (w->shift) { |
1574 | case CS42L43_ADC1_EN_SHIFT: |
1575 | case CS42L43_PDM1_DIN_L_EN_SHIFT: |
1576 | reg = CS42L43_DECIM_VOL_CTRL_CH1_CH2; |
1577 | ramp = CS42L43_DECIM1_VD_RAMP_MASK; |
1578 | mute = CS42L43_DECIM1_MUTE_MASK; |
1579 | val = &priv->decim_cache[0]; |
1580 | break; |
1581 | case CS42L43_ADC2_EN_SHIFT: |
1582 | case CS42L43_PDM1_DIN_R_EN_SHIFT: |
1583 | reg = CS42L43_DECIM_VOL_CTRL_CH1_CH2; |
1584 | ramp = CS42L43_DECIM2_VD_RAMP_MASK; |
1585 | mute = CS42L43_DECIM2_MUTE_MASK; |
1586 | val = &priv->decim_cache[1]; |
1587 | break; |
1588 | case CS42L43_PDM2_DIN_L_EN_SHIFT: |
1589 | reg = CS42L43_DECIM_VOL_CTRL_CH3_CH4; |
1590 | ramp = CS42L43_DECIM3_VD_RAMP_MASK; |
1591 | mute = CS42L43_DECIM3_MUTE_MASK; |
1592 | val = &priv->decim_cache[2]; |
1593 | break; |
1594 | case CS42L43_PDM2_DIN_R_EN_SHIFT: |
1595 | reg = CS42L43_DECIM_VOL_CTRL_CH3_CH4; |
1596 | ramp = CS42L43_DECIM4_VD_RAMP_MASK; |
1597 | mute = CS42L43_DECIM4_MUTE_MASK; |
1598 | val = &priv->decim_cache[3]; |
1599 | break; |
1600 | default: |
1601 | dev_err(priv->dev, "Invalid microphone shift: %d\n" , w->shift); |
1602 | return -EINVAL; |
1603 | } |
1604 | |
1605 | switch (event) { |
1606 | case SND_SOC_DAPM_PRE_PMU: |
1607 | ret = regmap_read(map: cs42l43->regmap, reg, val); |
1608 | if (ret) { |
1609 | dev_err(priv->dev, |
1610 | "Failed to cache decimator settings: %d\n" , |
1611 | ret); |
1612 | return ret; |
1613 | } |
1614 | |
1615 | regmap_update_bits(map: cs42l43->regmap, reg, mask: mute | ramp, val: mute); |
1616 | break; |
1617 | case SND_SOC_DAPM_POST_PMU: |
1618 | regmap_update_bits(map: cs42l43->regmap, reg, mask: mute | ramp, val: *val); |
1619 | break; |
1620 | default: |
1621 | break; |
1622 | } |
1623 | |
1624 | return 0; |
1625 | } |
1626 | |
1627 | static int cs42l43_adc_ev(struct snd_soc_dapm_widget *w, |
1628 | struct snd_kcontrol *kcontrol, int event) |
1629 | { |
1630 | struct snd_soc_component *component = snd_soc_dapm_to_component(dapm: w->dapm); |
1631 | struct cs42l43_codec *priv = snd_soc_component_get_drvdata(c: component); |
1632 | struct cs42l43 *cs42l43 = priv->core; |
1633 | unsigned int mask = 1 << w->shift; |
1634 | unsigned int val = 0; |
1635 | int ret; |
1636 | |
1637 | ret = cs42l43_mic_ev(w, kcontrol, event); |
1638 | if (ret) |
1639 | return ret; |
1640 | |
1641 | switch (event) { |
1642 | case SND_SOC_DAPM_PRE_PMU: |
1643 | val = mask; |
1644 | fallthrough; |
1645 | case SND_SOC_DAPM_PRE_PMD: |
1646 | priv->adc_ena &= ~mask; |
1647 | priv->adc_ena |= val; |
1648 | |
1649 | if (!priv->load_detect_running) |
1650 | regmap_update_bits(map: cs42l43->regmap, CS42L43_BLOCK_EN3, |
1651 | mask, val); |
1652 | fallthrough; |
1653 | default: |
1654 | return 0; |
1655 | } |
1656 | } |
1657 | |
1658 | static const struct snd_soc_dapm_widget cs42l43_widgets[] = { |
1659 | SND_SOC_DAPM_SUPPLY("PLL" , SND_SOC_NOPM, 0, 0, cs42l43_pll_ev, |
1660 | SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD), |
1661 | |
1662 | SND_SOC_DAPM_INPUT("ADC1_IN1_P" ), |
1663 | SND_SOC_DAPM_INPUT("ADC1_IN1_N" ), |
1664 | SND_SOC_DAPM_INPUT("ADC1_IN2_P" ), |
1665 | SND_SOC_DAPM_INPUT("ADC1_IN2_N" ), |
1666 | SND_SOC_DAPM_INPUT("ADC2_IN_P" ), |
1667 | SND_SOC_DAPM_INPUT("ADC2_IN_N" ), |
1668 | |
1669 | SND_SOC_DAPM_INPUT("PDM1_DIN" ), |
1670 | SND_SOC_DAPM_INPUT("PDM2_DIN" ), |
1671 | |
1672 | SND_SOC_DAPM_MUX("ADC1 Input" , SND_SOC_NOPM, 0, 0, &cs42l43_adc1_input_ctl), |
1673 | |
1674 | SND_SOC_DAPM_PGA_E("ADC1" , SND_SOC_NOPM, CS42L43_ADC1_EN_SHIFT, 0, NULL, 0, |
1675 | cs42l43_adc_ev, SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU | |
1676 | SND_SOC_DAPM_PRE_PMD), |
1677 | SND_SOC_DAPM_PGA_E("ADC2" , SND_SOC_NOPM, CS42L43_ADC2_EN_SHIFT, 0, NULL, 0, |
1678 | cs42l43_adc_ev, SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU | |
1679 | SND_SOC_DAPM_PRE_PMD), |
1680 | |
1681 | SND_SOC_DAPM_PGA_E("PDM1L" , CS42L43_BLOCK_EN3, CS42L43_PDM1_DIN_L_EN_SHIFT, |
1682 | 0, NULL, 0, cs42l43_mic_ev, |
1683 | SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU), |
1684 | SND_SOC_DAPM_PGA_E("PDM1R" , CS42L43_BLOCK_EN3, CS42L43_PDM1_DIN_R_EN_SHIFT, |
1685 | 0, NULL, 0, cs42l43_mic_ev, |
1686 | SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU), |
1687 | SND_SOC_DAPM_PGA_E("PDM2L" , CS42L43_BLOCK_EN3, CS42L43_PDM2_DIN_L_EN_SHIFT, |
1688 | 0, NULL, 0, cs42l43_mic_ev, |
1689 | SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU), |
1690 | SND_SOC_DAPM_PGA_E("PDM2R" , CS42L43_BLOCK_EN3, CS42L43_PDM2_DIN_R_EN_SHIFT, |
1691 | 0, NULL, 0, cs42l43_mic_ev, |
1692 | SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU), |
1693 | |
1694 | SND_SOC_DAPM_MUX("Decimator 1 Mode" , SND_SOC_NOPM, 0, 0, |
1695 | &cs42l43_dec_mode_ctl[0]), |
1696 | SND_SOC_DAPM_MUX("Decimator 2 Mode" , SND_SOC_NOPM, 0, 0, |
1697 | &cs42l43_dec_mode_ctl[1]), |
1698 | |
1699 | SND_SOC_DAPM_PGA("Decimator 1" , SND_SOC_NOPM, 0, 0, NULL, 0), |
1700 | SND_SOC_DAPM_PGA("Decimator 2" , SND_SOC_NOPM, 0, 0, NULL, 0), |
1701 | SND_SOC_DAPM_PGA("Decimator 3" , SND_SOC_NOPM, 0, 0, NULL, 0), |
1702 | SND_SOC_DAPM_PGA("Decimator 4" , SND_SOC_NOPM, 0, 0, NULL, 0), |
1703 | |
1704 | SND_SOC_DAPM_SUPPLY_S("FSYNC" , 0, CS42L43_ASP_CTRL, CS42L43_ASP_FSYNC_EN_SHIFT, |
1705 | 0, NULL, 0), |
1706 | SND_SOC_DAPM_SUPPLY_S("BCLK" , 1, CS42L43_ASP_CTRL, CS42L43_ASP_BCLK_EN_SHIFT, |
1707 | 0, NULL, 0), |
1708 | |
1709 | SND_SOC_DAPM_AIF_OUT("ASPTX1" , NULL, 0, |
1710 | CS42L43_ASP_TX_EN, CS42L43_ASP_TX_CH1_EN_SHIFT, 0), |
1711 | SND_SOC_DAPM_AIF_OUT("ASPTX2" , NULL, 1, |
1712 | CS42L43_ASP_TX_EN, CS42L43_ASP_TX_CH2_EN_SHIFT, 0), |
1713 | SND_SOC_DAPM_AIF_OUT("ASPTX3" , NULL, 2, |
1714 | CS42L43_ASP_TX_EN, CS42L43_ASP_TX_CH3_EN_SHIFT, 0), |
1715 | SND_SOC_DAPM_AIF_OUT("ASPTX4" , NULL, 3, |
1716 | CS42L43_ASP_TX_EN, CS42L43_ASP_TX_CH4_EN_SHIFT, 0), |
1717 | SND_SOC_DAPM_AIF_OUT("ASPTX5" , NULL, 4, |
1718 | CS42L43_ASP_TX_EN, CS42L43_ASP_TX_CH5_EN_SHIFT, 0), |
1719 | SND_SOC_DAPM_AIF_OUT("ASPTX6" , NULL, 5, |
1720 | CS42L43_ASP_TX_EN, CS42L43_ASP_TX_CH6_EN_SHIFT, 0), |
1721 | |
1722 | SND_SOC_DAPM_AIF_IN("ASPRX1" , NULL, 0, |
1723 | CS42L43_ASP_RX_EN, CS42L43_ASP_RX_CH1_EN_SHIFT, 0), |
1724 | SND_SOC_DAPM_AIF_IN("ASPRX2" , NULL, 1, |
1725 | CS42L43_ASP_RX_EN, CS42L43_ASP_RX_CH2_EN_SHIFT, 0), |
1726 | SND_SOC_DAPM_AIF_IN("ASPRX3" , NULL, 2, |
1727 | CS42L43_ASP_RX_EN, CS42L43_ASP_RX_CH3_EN_SHIFT, 0), |
1728 | SND_SOC_DAPM_AIF_IN("ASPRX4" , NULL, 3, |
1729 | CS42L43_ASP_RX_EN, CS42L43_ASP_RX_CH4_EN_SHIFT, 0), |
1730 | SND_SOC_DAPM_AIF_IN("ASPRX5" , NULL, 4, |
1731 | CS42L43_ASP_RX_EN, CS42L43_ASP_RX_CH5_EN_SHIFT, 0), |
1732 | SND_SOC_DAPM_AIF_IN("ASPRX6" , NULL, 5, |
1733 | CS42L43_ASP_RX_EN, CS42L43_ASP_RX_CH6_EN_SHIFT, 0), |
1734 | |
1735 | SND_SOC_DAPM_AIF_OUT("DP1TX1" , NULL, 0, SND_SOC_NOPM, 0, 0), |
1736 | SND_SOC_DAPM_AIF_OUT("DP1TX2" , NULL, 1, SND_SOC_NOPM, 0, 0), |
1737 | SND_SOC_DAPM_AIF_OUT("DP1TX3" , NULL, 2, SND_SOC_NOPM, 0, 0), |
1738 | SND_SOC_DAPM_AIF_OUT("DP1TX4" , NULL, 3, SND_SOC_NOPM, 0, 0), |
1739 | |
1740 | SND_SOC_DAPM_AIF_OUT("DP2TX1" , NULL, 0, SND_SOC_NOPM, 0, 0), |
1741 | SND_SOC_DAPM_AIF_OUT("DP2TX2" , NULL, 1, SND_SOC_NOPM, 0, 0), |
1742 | |
1743 | SND_SOC_DAPM_AIF_OUT("DP3TX1" , NULL, 0, SND_SOC_NOPM, 0, 0), |
1744 | SND_SOC_DAPM_AIF_OUT("DP3TX2" , NULL, 1, SND_SOC_NOPM, 0, 0), |
1745 | |
1746 | SND_SOC_DAPM_AIF_OUT("DP4TX1" , NULL, 0, SND_SOC_NOPM, 0, 0), |
1747 | SND_SOC_DAPM_AIF_OUT("DP4TX2" , NULL, 1, SND_SOC_NOPM, 0, 0), |
1748 | |
1749 | SND_SOC_DAPM_AIF_IN("DP5RX1" , NULL, 0, SND_SOC_NOPM, 0, 0), |
1750 | SND_SOC_DAPM_AIF_IN("DP5RX2" , NULL, 1, SND_SOC_NOPM, 0, 0), |
1751 | |
1752 | SND_SOC_DAPM_AIF_IN("DP6RX1" , NULL, 0, SND_SOC_NOPM, 0, 0), |
1753 | SND_SOC_DAPM_AIF_IN("DP6RX2" , NULL, 1, SND_SOC_NOPM, 0, 0), |
1754 | |
1755 | SND_SOC_DAPM_AIF_IN("DP7RX1" , NULL, 0, SND_SOC_NOPM, 0, 0), |
1756 | SND_SOC_DAPM_AIF_IN("DP7RX2" , NULL, 1, SND_SOC_NOPM, 0, 0), |
1757 | |
1758 | SND_SOC_DAPM_REGULATOR_SUPPLY("vdd-amp" , 0, 0), |
1759 | |
1760 | SND_SOC_DAPM_PGA_E("AMP1" , CS42L43_BLOCK_EN10, CS42L43_AMP1_EN_SHIFT, 0, NULL, 0, |
1761 | cs42l43_spkl_ev, SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU | |
1762 | SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD), |
1763 | SND_SOC_DAPM_PGA_E("AMP2" , CS42L43_BLOCK_EN10, CS42L43_AMP2_EN_SHIFT, 0, NULL, 0, |
1764 | cs42l43_spkr_ev, SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU | |
1765 | SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD), |
1766 | |
1767 | SND_SOC_DAPM_OUTPUT("AMP1_OUT_P" ), |
1768 | SND_SOC_DAPM_OUTPUT("AMP1_OUT_N" ), |
1769 | SND_SOC_DAPM_OUTPUT("AMP2_OUT_P" ), |
1770 | SND_SOC_DAPM_OUTPUT("AMP2_OUT_N" ), |
1771 | |
1772 | SND_SOC_DAPM_PGA("SPDIF" , CS42L43_BLOCK_EN11, CS42L43_SPDIF_EN_SHIFT, |
1773 | 0, NULL, 0), |
1774 | SND_SOC_DAPM_OUTPUT("SPDIF_TX" ), |
1775 | |
1776 | SND_SOC_DAPM_PGA_E("HP" , SND_SOC_NOPM, CS42L43_HP_EN_SHIFT, 0, NULL, 0, |
1777 | cs42l43_hp_ev, SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU | |
1778 | SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD), |
1779 | SND_SOC_DAPM_OUTPUT("AMP3_OUT" ), |
1780 | SND_SOC_DAPM_OUTPUT("AMP4_OUT" ), |
1781 | |
1782 | SND_SOC_DAPM_SIGGEN("Tone" ), |
1783 | SND_SOC_DAPM_SUPPLY("Tone Generator" , CS42L43_BLOCK_EN9, CS42L43_TONE_EN_SHIFT, |
1784 | 0, NULL, 0), |
1785 | SND_SOC_DAPM_REG(snd_soc_dapm_pga, "Tone 1" , CS42L43_TONE_CH1_CTRL, |
1786 | CS42L43_TONE_SEL_SHIFT, CS42L43_TONE_SEL_MASK, 0xA, 0), |
1787 | SND_SOC_DAPM_REG(snd_soc_dapm_pga, "Tone 2" , CS42L43_TONE_CH2_CTRL, |
1788 | CS42L43_TONE_SEL_SHIFT, CS42L43_TONE_SEL_MASK, 0xA, 0), |
1789 | |
1790 | SND_SOC_DAPM_SUPPLY("ISRC1" , CS42L43_BLOCK_EN5, CS42L43_ISRC1_BANK_EN_SHIFT, |
1791 | 0, NULL, 0), |
1792 | SND_SOC_DAPM_SUPPLY("ISRC2" , CS42L43_BLOCK_EN5, CS42L43_ISRC2_BANK_EN_SHIFT, |
1793 | 0, NULL, 0), |
1794 | |
1795 | SND_SOC_DAPM_PGA("ISRC1INT2" , CS42L43_ISRC1_CTRL, |
1796 | CS42L43_ISRC_INT2_EN_SHIFT, 0, NULL, 0), |
1797 | SND_SOC_DAPM_PGA("ISRC1INT1" , CS42L43_ISRC1_CTRL, |
1798 | CS42L43_ISRC_INT1_EN_SHIFT, 0, NULL, 0), |
1799 | SND_SOC_DAPM_PGA("ISRC1DEC2" , CS42L43_ISRC1_CTRL, |
1800 | CS42L43_ISRC_DEC2_EN_SHIFT, 0, NULL, 0), |
1801 | SND_SOC_DAPM_PGA("ISRC1DEC1" , CS42L43_ISRC1_CTRL, |
1802 | CS42L43_ISRC_DEC1_EN_SHIFT, 0, NULL, 0), |
1803 | |
1804 | SND_SOC_DAPM_PGA("ISRC2INT2" , CS42L43_ISRC2_CTRL, |
1805 | CS42L43_ISRC_INT2_EN_SHIFT, 0, NULL, 0), |
1806 | SND_SOC_DAPM_PGA("ISRC2INT1" , CS42L43_ISRC2_CTRL, |
1807 | CS42L43_ISRC_INT1_EN_SHIFT, 0, NULL, 0), |
1808 | SND_SOC_DAPM_PGA("ISRC2DEC2" , CS42L43_ISRC2_CTRL, |
1809 | CS42L43_ISRC_DEC2_EN_SHIFT, 0, NULL, 0), |
1810 | SND_SOC_DAPM_PGA("ISRC2DEC1" , CS42L43_ISRC2_CTRL, |
1811 | CS42L43_ISRC_DEC1_EN_SHIFT, 0, NULL, 0), |
1812 | |
1813 | SND_SOC_DAPM_SUPPLY("ASRC_INT" , CS42L43_BLOCK_EN4, |
1814 | CS42L43_ASRC_INT_BANK_EN_SHIFT, 0, NULL, 0), |
1815 | SND_SOC_DAPM_SUPPLY("ASRC_DEC" , CS42L43_BLOCK_EN4, |
1816 | CS42L43_ASRC_DEC_BANK_EN_SHIFT, 0, NULL, 0), |
1817 | |
1818 | SND_SOC_DAPM_PGA("ASRC_INT1" , CS42L43_ASRC_INT_ENABLES, |
1819 | CS42L43_ASRC_INT1_EN_SHIFT, 0, NULL, 0), |
1820 | SND_SOC_DAPM_PGA("ASRC_INT2" , CS42L43_ASRC_INT_ENABLES, |
1821 | CS42L43_ASRC_INT2_EN_SHIFT, 0, NULL, 0), |
1822 | SND_SOC_DAPM_PGA("ASRC_INT3" , CS42L43_ASRC_INT_ENABLES, |
1823 | CS42L43_ASRC_INT3_EN_SHIFT, 0, NULL, 0), |
1824 | SND_SOC_DAPM_PGA("ASRC_INT4" , CS42L43_ASRC_INT_ENABLES, |
1825 | CS42L43_ASRC_INT4_EN_SHIFT, 0, NULL, 0), |
1826 | SND_SOC_DAPM_PGA("ASRC_DEC1" , CS42L43_ASRC_DEC_ENABLES, |
1827 | CS42L43_ASRC_DEC1_EN_SHIFT, 0, NULL, 0), |
1828 | SND_SOC_DAPM_PGA("ASRC_DEC2" , CS42L43_ASRC_DEC_ENABLES, |
1829 | CS42L43_ASRC_DEC2_EN_SHIFT, 0, NULL, 0), |
1830 | SND_SOC_DAPM_PGA("ASRC_DEC3" , CS42L43_ASRC_DEC_ENABLES, |
1831 | CS42L43_ASRC_DEC3_EN_SHIFT, 0, NULL, 0), |
1832 | SND_SOC_DAPM_PGA("ASRC_DEC4" , CS42L43_ASRC_DEC_ENABLES, |
1833 | CS42L43_ASRC_DEC4_EN_SHIFT, 0, NULL, 0), |
1834 | |
1835 | SND_SOC_DAPM_SUPPLY("EQ Clock" , CS42L43_BLOCK_EN7, CS42L43_EQ_EN_SHIFT, |
1836 | 0, NULL, 0), |
1837 | SND_SOC_DAPM_PGA_E("EQ" , CS42L43_START_EQZ0, CS42L43_START_FILTER_SHIFT, |
1838 | 0, NULL, 0, cs42l43_eq_ev, |
1839 | SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU), |
1840 | |
1841 | SND_SOC_DAPM_SUPPLY("Mixer Core" , CS42L43_BLOCK_EN6, CS42L43_MIXER_EN_SHIFT, |
1842 | 0, NULL, 0), |
1843 | CS42L43_DAPM_MUX("ASPTX1" , asptx1), |
1844 | CS42L43_DAPM_MUX("ASPTX2" , asptx2), |
1845 | CS42L43_DAPM_MUX("ASPTX3" , asptx3), |
1846 | CS42L43_DAPM_MUX("ASPTX4" , asptx4), |
1847 | CS42L43_DAPM_MUX("ASPTX5" , asptx5), |
1848 | CS42L43_DAPM_MUX("ASPTX6" , asptx6), |
1849 | |
1850 | CS42L43_DAPM_MUX("DP1TX1" , dp1tx1), |
1851 | CS42L43_DAPM_MUX("DP1TX2" , dp1tx2), |
1852 | CS42L43_DAPM_MUX("DP1TX3" , dp1tx3), |
1853 | CS42L43_DAPM_MUX("DP1TX4" , dp1tx4), |
1854 | CS42L43_DAPM_MUX("DP2TX1" , dp2tx1), |
1855 | CS42L43_DAPM_MUX("DP2TX2" , dp2tx2), |
1856 | CS42L43_DAPM_MUX("DP3TX1" , dp3tx1), |
1857 | CS42L43_DAPM_MUX("DP3TX2" , dp3tx2), |
1858 | CS42L43_DAPM_MUX("DP4TX1" , dp4tx1), |
1859 | CS42L43_DAPM_MUX("DP4TX2" , dp4tx2), |
1860 | |
1861 | CS42L43_DAPM_MUX("ASRC INT1" , asrcint1), |
1862 | CS42L43_DAPM_MUX("ASRC INT2" , asrcint2), |
1863 | CS42L43_DAPM_MUX("ASRC INT3" , asrcint3), |
1864 | CS42L43_DAPM_MUX("ASRC INT4" , asrcint4), |
1865 | CS42L43_DAPM_MUX("ASRC DEC1" , asrcdec1), |
1866 | CS42L43_DAPM_MUX("ASRC DEC2" , asrcdec2), |
1867 | CS42L43_DAPM_MUX("ASRC DEC3" , asrcdec3), |
1868 | CS42L43_DAPM_MUX("ASRC DEC4" , asrcdec4), |
1869 | |
1870 | CS42L43_DAPM_MUX("ISRC1INT1" , isrc1int1), |
1871 | CS42L43_DAPM_MUX("ISRC1INT2" , isrc1int2), |
1872 | CS42L43_DAPM_MUX("ISRC1DEC1" , isrc1dec1), |
1873 | CS42L43_DAPM_MUX("ISRC1DEC2" , isrc1dec2), |
1874 | CS42L43_DAPM_MUX("ISRC2INT1" , isrc2int1), |
1875 | CS42L43_DAPM_MUX("ISRC2INT2" , isrc2int2), |
1876 | CS42L43_DAPM_MUX("ISRC2DEC1" , isrc2dec1), |
1877 | CS42L43_DAPM_MUX("ISRC2DEC2" , isrc2dec2), |
1878 | |
1879 | CS42L43_DAPM_MUX("SPDIF1" , spdif1), |
1880 | CS42L43_DAPM_MUX("SPDIF2" , spdif2), |
1881 | |
1882 | CS42L43_DAPM_MIXER("EQ1" , eq1), |
1883 | CS42L43_DAPM_MIXER("EQ2" , eq2), |
1884 | |
1885 | CS42L43_DAPM_MIXER("Speaker L" , amp1), |
1886 | CS42L43_DAPM_MIXER("Speaker R" , amp2), |
1887 | |
1888 | CS42L43_DAPM_MIXER("Headphone L" , amp3), |
1889 | CS42L43_DAPM_MIXER("Headphone R" , amp4), |
1890 | }; |
1891 | |
1892 | static const struct snd_soc_dapm_route cs42l43_routes[] = { |
1893 | { "ADC1_IN1_P" , NULL, "PLL" }, |
1894 | { "ADC1_IN1_N" , NULL, "PLL" }, |
1895 | { "ADC1_IN2_P" , NULL, "PLL" }, |
1896 | { "ADC1_IN2_N" , NULL, "PLL" }, |
1897 | { "ADC2_IN_P" , NULL, "PLL" }, |
1898 | { "ADC2_IN_N" , NULL, "PLL" }, |
1899 | { "PDM1_DIN" , NULL, "PLL" }, |
1900 | { "PDM2_DIN" , NULL, "PLL" }, |
1901 | { "AMP1_OUT_P" , NULL, "PLL" }, |
1902 | { "AMP1_OUT_N" , NULL, "PLL" }, |
1903 | { "AMP2_OUT_P" , NULL, "PLL" }, |
1904 | { "AMP2_OUT_N" , NULL, "PLL" }, |
1905 | { "SPDIF_TX" , NULL, "PLL" }, |
1906 | { "HP" , NULL, "PLL" }, |
1907 | { "AMP3_OUT" , NULL, "PLL" }, |
1908 | { "AMP4_OUT" , NULL, "PLL" }, |
1909 | { "Tone 1" , NULL, "PLL" }, |
1910 | { "Tone 2" , NULL, "PLL" }, |
1911 | { "ASP Playback" , NULL, "PLL" }, |
1912 | { "ASP Capture" , NULL, "PLL" }, |
1913 | { "DP1 Capture" , NULL, "PLL" }, |
1914 | { "DP2 Capture" , NULL, "PLL" }, |
1915 | { "DP3 Capture" , NULL, "PLL" }, |
1916 | { "DP4 Capture" , NULL, "PLL" }, |
1917 | { "DP5 Playback" , NULL, "PLL" }, |
1918 | { "DP6 Playback" , NULL, "PLL" }, |
1919 | { "DP7 Playback" , NULL, "PLL" }, |
1920 | |
1921 | { "ADC1 Input" , "IN1" , "ADC1_IN1_P" }, |
1922 | { "ADC1 Input" , "IN1" , "ADC1_IN1_N" }, |
1923 | { "ADC1 Input" , "IN2" , "ADC1_IN2_P" }, |
1924 | { "ADC1 Input" , "IN2" , "ADC1_IN2_N" }, |
1925 | |
1926 | { "ADC1" , NULL, "ADC1 Input" }, |
1927 | { "ADC2" , NULL, "ADC2_IN_P" }, |
1928 | { "ADC2" , NULL, "ADC2_IN_N" }, |
1929 | |
1930 | { "PDM1L" , NULL, "PDM1_DIN" }, |
1931 | { "PDM1R" , NULL, "PDM1_DIN" }, |
1932 | { "PDM2L" , NULL, "PDM2_DIN" }, |
1933 | { "PDM2R" , NULL, "PDM2_DIN" }, |
1934 | |
1935 | { "Decimator 1 Mode" , "PDM" , "PDM1L" }, |
1936 | { "Decimator 1 Mode" , "ADC" , "ADC1" }, |
1937 | { "Decimator 2 Mode" , "PDM" , "PDM1R" }, |
1938 | { "Decimator 2 Mode" , "ADC" , "ADC2" }, |
1939 | |
1940 | { "Decimator 1" , NULL, "Decimator 1 Mode" }, |
1941 | { "Decimator 2" , NULL, "Decimator 2 Mode" }, |
1942 | { "Decimator 3" , NULL, "PDM2L" }, |
1943 | { "Decimator 4" , NULL, "PDM2R" }, |
1944 | |
1945 | { "ASP Capture" , NULL, "ASPTX1" }, |
1946 | { "ASP Capture" , NULL, "ASPTX2" }, |
1947 | { "ASP Capture" , NULL, "ASPTX3" }, |
1948 | { "ASP Capture" , NULL, "ASPTX4" }, |
1949 | { "ASP Capture" , NULL, "ASPTX5" }, |
1950 | { "ASP Capture" , NULL, "ASPTX6" }, |
1951 | { "ASPTX1" , NULL, "BCLK" }, |
1952 | { "ASPTX2" , NULL, "BCLK" }, |
1953 | { "ASPTX3" , NULL, "BCLK" }, |
1954 | { "ASPTX4" , NULL, "BCLK" }, |
1955 | { "ASPTX5" , NULL, "BCLK" }, |
1956 | { "ASPTX6" , NULL, "BCLK" }, |
1957 | |
1958 | { "ASPRX1" , NULL, "ASP Playback" }, |
1959 | { "ASPRX2" , NULL, "ASP Playback" }, |
1960 | { "ASPRX3" , NULL, "ASP Playback" }, |
1961 | { "ASPRX4" , NULL, "ASP Playback" }, |
1962 | { "ASPRX5" , NULL, "ASP Playback" }, |
1963 | { "ASPRX6" , NULL, "ASP Playback" }, |
1964 | { "ASPRX1" , NULL, "BCLK" }, |
1965 | { "ASPRX2" , NULL, "BCLK" }, |
1966 | { "ASPRX3" , NULL, "BCLK" }, |
1967 | { "ASPRX4" , NULL, "BCLK" }, |
1968 | { "ASPRX5" , NULL, "BCLK" }, |
1969 | { "ASPRX6" , NULL, "BCLK" }, |
1970 | |
1971 | { "DP1 Capture" , NULL, "DP1TX1" }, |
1972 | { "DP1 Capture" , NULL, "DP1TX2" }, |
1973 | { "DP1 Capture" , NULL, "DP1TX3" }, |
1974 | { "DP1 Capture" , NULL, "DP1TX4" }, |
1975 | |
1976 | { "DP2 Capture" , NULL, "DP2TX1" }, |
1977 | { "DP2 Capture" , NULL, "DP2TX2" }, |
1978 | |
1979 | { "DP3 Capture" , NULL, "DP3TX1" }, |
1980 | { "DP3 Capture" , NULL, "DP3TX2" }, |
1981 | |
1982 | { "DP4 Capture" , NULL, "DP4TX1" }, |
1983 | { "DP4 Capture" , NULL, "DP4TX2" }, |
1984 | |
1985 | { "DP5RX1" , NULL, "DP5 Playback" }, |
1986 | { "DP5RX2" , NULL, "DP5 Playback" }, |
1987 | |
1988 | { "DP6RX1" , NULL, "DP6 Playback" }, |
1989 | { "DP6RX2" , NULL, "DP6 Playback" }, |
1990 | |
1991 | { "DP7RX1" , NULL, "DP7 Playback" }, |
1992 | { "DP7RX2" , NULL, "DP7 Playback" }, |
1993 | |
1994 | { "AMP1" , NULL, "vdd-amp" }, |
1995 | { "AMP2" , NULL, "vdd-amp" }, |
1996 | |
1997 | { "AMP1_OUT_P" , NULL, "AMP1" }, |
1998 | { "AMP1_OUT_N" , NULL, "AMP1" }, |
1999 | { "AMP2_OUT_P" , NULL, "AMP2" }, |
2000 | { "AMP2_OUT_N" , NULL, "AMP2" }, |
2001 | |
2002 | { "SPDIF_TX" , NULL, "SPDIF" }, |
2003 | |
2004 | { "AMP3_OUT" , NULL, "HP" }, |
2005 | { "AMP4_OUT" , NULL, "HP" }, |
2006 | |
2007 | { "Tone 1" , NULL, "Tone" }, |
2008 | { "Tone 1" , NULL, "Tone Generator" }, |
2009 | { "Tone 2" , NULL, "Tone" }, |
2010 | { "Tone 2" , NULL, "Tone Generator" }, |
2011 | |
2012 | { "ISRC1INT2" , NULL, "ISRC1" }, |
2013 | { "ISRC1INT1" , NULL, "ISRC1" }, |
2014 | { "ISRC1DEC2" , NULL, "ISRC1" }, |
2015 | { "ISRC1DEC1" , NULL, "ISRC1" }, |
2016 | |
2017 | { "ISRC2INT2" , NULL, "ISRC2" }, |
2018 | { "ISRC2INT1" , NULL, "ISRC2" }, |
2019 | { "ISRC2DEC2" , NULL, "ISRC2" }, |
2020 | { "ISRC2DEC1" , NULL, "ISRC2" }, |
2021 | |
2022 | { "ASRC_INT1" , NULL, "ASRC_INT" }, |
2023 | { "ASRC_INT2" , NULL, "ASRC_INT" }, |
2024 | { "ASRC_INT3" , NULL, "ASRC_INT" }, |
2025 | { "ASRC_INT4" , NULL, "ASRC_INT" }, |
2026 | { "ASRC_DEC1" , NULL, "ASRC_DEC" }, |
2027 | { "ASRC_DEC2" , NULL, "ASRC_DEC" }, |
2028 | { "ASRC_DEC3" , NULL, "ASRC_DEC" }, |
2029 | { "ASRC_DEC4" , NULL, "ASRC_DEC" }, |
2030 | |
2031 | { "EQ" , NULL, "EQ Clock" }, |
2032 | |
2033 | CS42L43_MUX_ROUTES("ASPTX1" , "ASPTX1" ), |
2034 | CS42L43_MUX_ROUTES("ASPTX2" , "ASPTX2" ), |
2035 | CS42L43_MUX_ROUTES("ASPTX3" , "ASPTX3" ), |
2036 | CS42L43_MUX_ROUTES("ASPTX4" , "ASPTX4" ), |
2037 | CS42L43_MUX_ROUTES("ASPTX5" , "ASPTX5" ), |
2038 | CS42L43_MUX_ROUTES("ASPTX6" , "ASPTX6" ), |
2039 | |
2040 | CS42L43_MUX_ROUTES("DP1TX1" , "DP1TX1" ), |
2041 | CS42L43_MUX_ROUTES("DP1TX2" , "DP1TX2" ), |
2042 | CS42L43_MUX_ROUTES("DP1TX3" , "DP1TX3" ), |
2043 | CS42L43_MUX_ROUTES("DP1TX4" , "DP1TX4" ), |
2044 | CS42L43_MUX_ROUTES("DP2TX1" , "DP2TX1" ), |
2045 | CS42L43_MUX_ROUTES("DP2TX2" , "DP2TX2" ), |
2046 | CS42L43_MUX_ROUTES("DP3TX1" , "DP3TX1" ), |
2047 | CS42L43_MUX_ROUTES("DP3TX2" , "DP3TX2" ), |
2048 | CS42L43_MUX_ROUTES("DP4TX1" , "DP4TX1" ), |
2049 | CS42L43_MUX_ROUTES("DP4TX2" , "DP4TX2" ), |
2050 | |
2051 | CS42L43_MUX_ROUTES("ASRC INT1" , "ASRC_INT1" ), |
2052 | CS42L43_MUX_ROUTES("ASRC INT2" , "ASRC_INT2" ), |
2053 | CS42L43_MUX_ROUTES("ASRC INT3" , "ASRC_INT3" ), |
2054 | CS42L43_MUX_ROUTES("ASRC INT4" , "ASRC_INT4" ), |
2055 | CS42L43_MUX_ROUTES("ASRC DEC1" , "ASRC_DEC1" ), |
2056 | CS42L43_MUX_ROUTES("ASRC DEC2" , "ASRC_DEC2" ), |
2057 | CS42L43_MUX_ROUTES("ASRC DEC3" , "ASRC_DEC3" ), |
2058 | CS42L43_MUX_ROUTES("ASRC DEC4" , "ASRC_DEC4" ), |
2059 | |
2060 | CS42L43_MUX_ROUTES("ISRC1INT1" , "ISRC1INT1" ), |
2061 | CS42L43_MUX_ROUTES("ISRC1INT2" , "ISRC1INT2" ), |
2062 | CS42L43_MUX_ROUTES("ISRC1DEC1" , "ISRC1DEC1" ), |
2063 | CS42L43_MUX_ROUTES("ISRC1DEC2" , "ISRC1DEC2" ), |
2064 | CS42L43_MUX_ROUTES("ISRC2INT1" , "ISRC2INT1" ), |
2065 | CS42L43_MUX_ROUTES("ISRC2INT2" , "ISRC2INT2" ), |
2066 | CS42L43_MUX_ROUTES("ISRC2DEC1" , "ISRC2DEC1" ), |
2067 | CS42L43_MUX_ROUTES("ISRC2DEC2" , "ISRC2DEC2" ), |
2068 | |
2069 | CS42L43_MUX_ROUTES("SPDIF1" , "SPDIF" ), |
2070 | CS42L43_MUX_ROUTES("SPDIF2" , "SPDIF" ), |
2071 | |
2072 | CS42L43_MIXER_ROUTES("EQ1" , "EQ" ), |
2073 | CS42L43_MIXER_ROUTES("EQ2" , "EQ" ), |
2074 | |
2075 | CS42L43_MIXER_ROUTES("Speaker L" , "AMP1" ), |
2076 | CS42L43_MIXER_ROUTES("Speaker R" , "AMP2" ), |
2077 | |
2078 | CS42L43_MIXER_ROUTES("Headphone L" , "HP" ), |
2079 | CS42L43_MIXER_ROUTES("Headphone R" , "HP" ), |
2080 | }; |
2081 | |
2082 | static int cs42l43_set_sysclk(struct snd_soc_component *component, int clk_id, |
2083 | int src, unsigned int freq, int dir) |
2084 | { |
2085 | struct cs42l43_codec *priv = snd_soc_component_get_drvdata(c: component); |
2086 | struct cs42l43 *cs42l43 = priv->core; |
2087 | int ret; |
2088 | |
2089 | mutex_lock(&cs42l43->pll_lock); |
2090 | ret = cs42l43_set_pll(priv, src, freq); |
2091 | mutex_unlock(lock: &cs42l43->pll_lock); |
2092 | |
2093 | return ret; |
2094 | } |
2095 | |
2096 | static int cs42l43_component_probe(struct snd_soc_component *component) |
2097 | { |
2098 | struct cs42l43_codec *priv = snd_soc_component_get_drvdata(c: component); |
2099 | struct cs42l43 *cs42l43 = priv->core; |
2100 | |
2101 | snd_soc_component_init_regmap(component, regmap: cs42l43->regmap); |
2102 | |
2103 | cs42l43_mask_to_slots(priv, CS42L43_DEFAULT_SLOTS, slots: priv->tx_slots, |
2104 | ARRAY_SIZE(priv->tx_slots)); |
2105 | cs42l43_mask_to_slots(priv, CS42L43_DEFAULT_SLOTS, slots: priv->rx_slots, |
2106 | ARRAY_SIZE(priv->rx_slots)); |
2107 | |
2108 | priv->component = component; |
2109 | priv->constraint = cs42l43_constraint; |
2110 | |
2111 | return 0; |
2112 | } |
2113 | |
2114 | static void cs42l43_component_remove(struct snd_soc_component *component) |
2115 | { |
2116 | struct cs42l43_codec *priv = snd_soc_component_get_drvdata(c: component); |
2117 | |
2118 | cs42l43_set_jack(component: priv->component, NULL, NULL); |
2119 | |
2120 | cancel_delayed_work_sync(dwork: &priv->bias_sense_timeout); |
2121 | cancel_delayed_work_sync(dwork: &priv->tip_sense_work); |
2122 | cancel_delayed_work_sync(dwork: &priv->button_press_work); |
2123 | cancel_work_sync(work: &priv->button_release_work); |
2124 | |
2125 | cancel_work_sync(work: &priv->hp_ilimit_work); |
2126 | cancel_delayed_work_sync(dwork: &priv->hp_ilimit_clear_work); |
2127 | |
2128 | priv->component = NULL; |
2129 | } |
2130 | |
2131 | static const struct snd_soc_component_driver cs42l43_component_drv = { |
2132 | .name = "cs42l43-codec" , |
2133 | |
2134 | .probe = cs42l43_component_probe, |
2135 | .remove = cs42l43_component_remove, |
2136 | .set_sysclk = cs42l43_set_sysclk, |
2137 | .set_jack = cs42l43_set_jack, |
2138 | |
2139 | .endianness = 1, |
2140 | |
2141 | .controls = cs42l43_controls, |
2142 | .num_controls = ARRAY_SIZE(cs42l43_controls), |
2143 | .dapm_widgets = cs42l43_widgets, |
2144 | .num_dapm_widgets = ARRAY_SIZE(cs42l43_widgets), |
2145 | .dapm_routes = cs42l43_routes, |
2146 | .num_dapm_routes = ARRAY_SIZE(cs42l43_routes), |
2147 | }; |
2148 | |
2149 | struct cs42l43_irq { |
2150 | unsigned int irq; |
2151 | const char *name; |
2152 | irq_handler_t handler; |
2153 | }; |
2154 | |
2155 | static const struct cs42l43_irq cs42l43_irqs[] = { |
2156 | { CS42L43_PLL_LOST_LOCK, "pll lost lock" , cs42l43_pll_lost_lock }, |
2157 | { CS42L43_PLL_READY, "pll ready" , cs42l43_pll_ready }, |
2158 | { CS42L43_HP_STARTUP_DONE, "hp startup" , cs42l43_hp_startup }, |
2159 | { CS42L43_HP_SHUTDOWN_DONE, "hp shutdown" , cs42l43_hp_shutdown }, |
2160 | { CS42L43_HSDET_DONE, "type detect" , cs42l43_type_detect }, |
2161 | { CS42L43_TIPSENSE_UNPLUG_PDET, "tip sense unplug" , cs42l43_tip_sense }, |
2162 | { CS42L43_TIPSENSE_PLUG_PDET, "tip sense plug" , cs42l43_tip_sense }, |
2163 | { CS42L43_DC_DETECT1_TRUE, "button press" , cs42l43_button_press }, |
2164 | { CS42L43_DC_DETECT1_FALSE, "button release" , cs42l43_button_release }, |
2165 | { CS42L43_HSBIAS_CLAMPED, "hsbias detect clamp" , cs42l43_bias_detect_clamp }, |
2166 | { CS42L43_AMP2_CLK_STOP_FAULT, "spkr clock stop" , cs42l43_spkr_clock_stop }, |
2167 | { CS42L43_AMP1_CLK_STOP_FAULT, "spkl clock stop" , cs42l43_spkl_clock_stop }, |
2168 | { CS42L43_AMP2_VDDSPK_FAULT, "spkr brown out" , cs42l43_spkr_brown_out }, |
2169 | { CS42L43_AMP1_VDDSPK_FAULT, "spkl brown out" , cs42l43_spkl_brown_out }, |
2170 | { CS42L43_AMP2_SHUTDOWN_DONE, "spkr shutdown" , cs42l43_spkr_shutdown }, |
2171 | { CS42L43_AMP1_SHUTDOWN_DONE, "spkl shutdown" , cs42l43_spkl_shutdown }, |
2172 | { CS42L43_AMP2_STARTUP_DONE, "spkr startup" , cs42l43_spkr_startup }, |
2173 | { CS42L43_AMP1_STARTUP_DONE, "spkl startup" , cs42l43_spkl_startup }, |
2174 | { CS42L43_AMP2_THERM_SHDN, "spkr thermal shutdown" , cs42l43_spkr_therm_shutdown }, |
2175 | { CS42L43_AMP1_THERM_SHDN, "spkl thermal shutdown" , cs42l43_spkl_therm_shutdown }, |
2176 | { CS42L43_AMP2_THERM_WARN, "spkr thermal warning" , cs42l43_spkr_therm_warm }, |
2177 | { CS42L43_AMP1_THERM_WARN, "spkl thermal warning" , cs42l43_spkl_therm_warm }, |
2178 | { CS42L43_AMP2_SCDET, "spkr short circuit" , cs42l43_spkr_sc_detect }, |
2179 | { CS42L43_AMP1_SCDET, "spkl short circuit" , cs42l43_spkl_sc_detect }, |
2180 | { CS42L43_HP_ILIMIT, "hp ilimit" , cs42l43_hp_ilimit }, |
2181 | { CS42L43_HP_LOADDET_DONE, "load detect done" , cs42l43_load_detect }, |
2182 | }; |
2183 | |
2184 | static int cs42l43_request_irq(struct cs42l43_codec *priv, |
2185 | struct irq_domain *dom, const char * const name, |
2186 | unsigned int irq, irq_handler_t handler, |
2187 | unsigned long flags) |
2188 | { |
2189 | int ret; |
2190 | |
2191 | ret = irq_create_mapping(host: dom, hwirq: irq); |
2192 | if (ret < 0) |
2193 | return dev_err_probe(dev: priv->dev, err: ret, fmt: "Failed to map IRQ %s\n" , name); |
2194 | |
2195 | dev_dbg(priv->dev, "Request IRQ %d for %s\n" , ret, name); |
2196 | |
2197 | ret = devm_request_threaded_irq(dev: priv->dev, irq: ret, NULL, thread_fn: handler, |
2198 | IRQF_ONESHOT | flags, devname: name, dev_id: priv); |
2199 | if (ret) |
2200 | return dev_err_probe(dev: priv->dev, err: ret, fmt: "Failed to request IRQ %s\n" , name); |
2201 | |
2202 | return 0; |
2203 | } |
2204 | |
2205 | static int cs42l43_shutter_irq(struct cs42l43_codec *priv, |
2206 | struct irq_domain *dom, unsigned int shutter, |
2207 | const char * const open_name, |
2208 | const char * const close_name, |
2209 | irq_handler_t handler) |
2210 | { |
2211 | unsigned int open_irq, close_irq; |
2212 | int ret; |
2213 | |
2214 | switch (shutter) { |
2215 | case 0x1: |
2216 | dev_warn(priv->dev, "Manual shutters, notifications not available\n" ); |
2217 | return 0; |
2218 | case 0x2: |
2219 | open_irq = CS42L43_GPIO1_RISE; |
2220 | close_irq = CS42L43_GPIO1_FALL; |
2221 | break; |
2222 | case 0x4: |
2223 | open_irq = CS42L43_GPIO2_RISE; |
2224 | close_irq = CS42L43_GPIO2_FALL; |
2225 | break; |
2226 | case 0x8: |
2227 | open_irq = CS42L43_GPIO3_RISE; |
2228 | close_irq = CS42L43_GPIO3_FALL; |
2229 | break; |
2230 | default: |
2231 | return 0; |
2232 | } |
2233 | |
2234 | ret = cs42l43_request_irq(priv, dom, name: close_name, irq: close_irq, handler, IRQF_SHARED); |
2235 | if (ret) |
2236 | return ret; |
2237 | |
2238 | return cs42l43_request_irq(priv, dom, name: open_name, irq: open_irq, handler, IRQF_SHARED); |
2239 | } |
2240 | |
2241 | static int cs42l43_codec_probe(struct platform_device *pdev) |
2242 | { |
2243 | struct cs42l43 *cs42l43 = dev_get_drvdata(dev: pdev->dev.parent); |
2244 | struct cs42l43_codec *priv; |
2245 | struct irq_domain *dom; |
2246 | unsigned int val; |
2247 | int i, ret; |
2248 | |
2249 | dom = irq_find_matching_fwnode(dev_fwnode(cs42l43->dev), bus_token: DOMAIN_BUS_ANY); |
2250 | if (!dom) |
2251 | return -EPROBE_DEFER; |
2252 | |
2253 | priv = devm_kzalloc(dev: &pdev->dev, size: sizeof(*priv), GFP_KERNEL); |
2254 | if (!priv) |
2255 | return -ENOMEM; |
2256 | |
2257 | priv->dev = &pdev->dev; |
2258 | priv->core = cs42l43; |
2259 | |
2260 | platform_set_drvdata(pdev, data: priv); |
2261 | |
2262 | mutex_init(&priv->jack_lock); |
2263 | mutex_init(&priv->spk_vu_lock); |
2264 | |
2265 | init_completion(x: &priv->hp_startup); |
2266 | init_completion(x: &priv->hp_shutdown); |
2267 | init_completion(x: &priv->spkr_shutdown); |
2268 | init_completion(x: &priv->spkl_shutdown); |
2269 | init_completion(x: &priv->spkr_startup); |
2270 | init_completion(x: &priv->spkl_startup); |
2271 | init_completion(x: &priv->pll_ready); |
2272 | init_completion(x: &priv->type_detect); |
2273 | init_completion(x: &priv->load_detect); |
2274 | |
2275 | INIT_DELAYED_WORK(&priv->tip_sense_work, cs42l43_tip_sense_work); |
2276 | INIT_DELAYED_WORK(&priv->bias_sense_timeout, cs42l43_bias_sense_timeout); |
2277 | INIT_DELAYED_WORK(&priv->button_press_work, cs42l43_button_press_work); |
2278 | INIT_DELAYED_WORK(&priv->hp_ilimit_clear_work, cs42l43_hp_ilimit_clear_work); |
2279 | INIT_WORK(&priv->button_release_work, cs42l43_button_release_work); |
2280 | INIT_WORK(&priv->hp_ilimit_work, cs42l43_hp_ilimit_work); |
2281 | |
2282 | pm_runtime_set_autosuspend_delay(dev: priv->dev, delay: 100); |
2283 | pm_runtime_use_autosuspend(dev: priv->dev); |
2284 | pm_runtime_set_active(dev: priv->dev); |
2285 | pm_runtime_get_noresume(dev: priv->dev); |
2286 | |
2287 | ret = devm_pm_runtime_enable(dev: priv->dev); |
2288 | if (ret) |
2289 | goto err_pm; |
2290 | |
2291 | for (i = 0; i < ARRAY_SIZE(cs42l43_irqs); i++) { |
2292 | ret = cs42l43_request_irq(priv, dom, name: cs42l43_irqs[i].name, |
2293 | irq: cs42l43_irqs[i].irq, |
2294 | handler: cs42l43_irqs[i].handler, flags: 0); |
2295 | if (ret) |
2296 | goto err_pm; |
2297 | } |
2298 | |
2299 | ret = regmap_read(map: cs42l43->regmap, CS42L43_SHUTTER_CONTROL, val: &val); |
2300 | if (ret) { |
2301 | dev_err(priv->dev, "Failed to check shutter source: %d\n" , ret); |
2302 | goto err_pm; |
2303 | } |
2304 | |
2305 | ret = cs42l43_shutter_irq(priv, dom, shutter: val & CS42L43_MIC_SHUTTER_CFG_MASK, |
2306 | open_name: "mic shutter open" , close_name: "mic shutter close" , |
2307 | handler: cs42l43_mic_shutter); |
2308 | if (ret) |
2309 | goto err_pm; |
2310 | |
2311 | ret = cs42l43_shutter_irq(priv, dom, shutter: (val & CS42L43_SPK_SHUTTER_CFG_MASK) >> |
2312 | CS42L43_SPK_SHUTTER_CFG_SHIFT, |
2313 | open_name: "spk shutter open" , close_name: "spk shutter close" , |
2314 | handler: cs42l43_spk_shutter); |
2315 | if (ret) |
2316 | goto err_pm; |
2317 | |
2318 | // Don't use devm as we need to get against the MFD device |
2319 | priv->mclk = clk_get_optional(dev: cs42l43->dev, id: "mclk" ); |
2320 | if (IS_ERR(ptr: priv->mclk)) { |
2321 | ret = PTR_ERR(ptr: priv->mclk); |
2322 | dev_err_probe(dev: priv->dev, err: ret, fmt: "Failed to get mclk\n" ); |
2323 | goto err_pm; |
2324 | } |
2325 | |
2326 | ret = devm_snd_soc_register_component(dev: priv->dev, component_driver: &cs42l43_component_drv, |
2327 | dai_drv: cs42l43_dais, ARRAY_SIZE(cs42l43_dais)); |
2328 | if (ret) { |
2329 | dev_err_probe(dev: priv->dev, err: ret, fmt: "Failed to register component\n" ); |
2330 | goto err_clk; |
2331 | } |
2332 | |
2333 | pm_runtime_mark_last_busy(dev: priv->dev); |
2334 | pm_runtime_put_autosuspend(dev: priv->dev); |
2335 | |
2336 | return 0; |
2337 | |
2338 | err_clk: |
2339 | clk_put(clk: priv->mclk); |
2340 | err_pm: |
2341 | pm_runtime_put_sync(dev: priv->dev); |
2342 | |
2343 | return ret; |
2344 | } |
2345 | |
2346 | static void cs42l43_codec_remove(struct platform_device *pdev) |
2347 | { |
2348 | struct cs42l43_codec *priv = platform_get_drvdata(pdev); |
2349 | |
2350 | clk_put(clk: priv->mclk); |
2351 | } |
2352 | |
2353 | static int cs42l43_codec_runtime_resume(struct device *dev) |
2354 | { |
2355 | struct cs42l43_codec *priv = dev_get_drvdata(dev); |
2356 | |
2357 | dev_dbg(priv->dev, "Runtime resume\n" ); |
2358 | |
2359 | // Toggle the speaker volume update incase the speaker volume was synced |
2360 | cs42l43_spk_vu_sync(priv); |
2361 | |
2362 | return 0; |
2363 | } |
2364 | |
2365 | static int cs42l43_codec_suspend(struct device *dev) |
2366 | { |
2367 | struct cs42l43_codec *priv = dev_get_drvdata(dev); |
2368 | struct cs42l43 *cs42l43 = priv->core; |
2369 | |
2370 | disable_irq(irq: cs42l43->irq); |
2371 | |
2372 | return 0; |
2373 | } |
2374 | |
2375 | static int cs42l43_codec_suspend_noirq(struct device *dev) |
2376 | { |
2377 | struct cs42l43_codec *priv = dev_get_drvdata(dev); |
2378 | struct cs42l43 *cs42l43 = priv->core; |
2379 | |
2380 | enable_irq(irq: cs42l43->irq); |
2381 | |
2382 | return 0; |
2383 | } |
2384 | |
2385 | static int cs42l43_codec_resume(struct device *dev) |
2386 | { |
2387 | struct cs42l43_codec *priv = dev_get_drvdata(dev); |
2388 | struct cs42l43 *cs42l43 = priv->core; |
2389 | |
2390 | enable_irq(irq: cs42l43->irq); |
2391 | |
2392 | return 0; |
2393 | } |
2394 | |
2395 | static int cs42l43_codec_resume_noirq(struct device *dev) |
2396 | { |
2397 | struct cs42l43_codec *priv = dev_get_drvdata(dev); |
2398 | struct cs42l43 *cs42l43 = priv->core; |
2399 | |
2400 | disable_irq(irq: cs42l43->irq); |
2401 | |
2402 | return 0; |
2403 | } |
2404 | |
2405 | static const struct dev_pm_ops cs42l43_codec_pm_ops = { |
2406 | SYSTEM_SLEEP_PM_OPS(cs42l43_codec_suspend, cs42l43_codec_resume) |
2407 | NOIRQ_SYSTEM_SLEEP_PM_OPS(cs42l43_codec_suspend_noirq, cs42l43_codec_resume_noirq) |
2408 | RUNTIME_PM_OPS(NULL, cs42l43_codec_runtime_resume, NULL) |
2409 | }; |
2410 | |
2411 | static const struct platform_device_id cs42l43_codec_id_table[] = { |
2412 | { "cs42l43-codec" , }, |
2413 | {} |
2414 | }; |
2415 | MODULE_DEVICE_TABLE(platform, cs42l43_codec_id_table); |
2416 | |
2417 | static struct platform_driver cs42l43_codec_driver = { |
2418 | .driver = { |
2419 | .name = "cs42l43-codec" , |
2420 | .pm = pm_ptr(&cs42l43_codec_pm_ops), |
2421 | }, |
2422 | |
2423 | .probe = cs42l43_codec_probe, |
2424 | .remove_new = cs42l43_codec_remove, |
2425 | .id_table = cs42l43_codec_id_table, |
2426 | }; |
2427 | module_platform_driver(cs42l43_codec_driver); |
2428 | |
2429 | MODULE_IMPORT_NS(SND_SOC_CS42L43); |
2430 | |
2431 | MODULE_DESCRIPTION("CS42L43 CODEC Driver" ); |
2432 | MODULE_AUTHOR("Charles Keepax <ckeepax@opensource.cirrus.com>" ); |
2433 | MODULE_LICENSE("GPL" ); |
2434 | |