1e2bcbf99SRichard Fitzgerald // SPDX-License-Identifier: GPL-2.0-only
2e2bcbf99SRichard Fitzgerald //
3e2bcbf99SRichard Fitzgerald // Cirrus Logic CS48L32 audio DSP.
4e2bcbf99SRichard Fitzgerald //
5e2bcbf99SRichard Fitzgerald // Copyright (C) 2016-2018, 2020, 2022, 2025 Cirrus Logic, Inc. and
6e2bcbf99SRichard Fitzgerald // Cirrus Logic International Semiconductor Ltd.
7e2bcbf99SRichard Fitzgerald
8e2bcbf99SRichard Fitzgerald #include <dt-bindings/sound/cs48l32.h>
9e2bcbf99SRichard Fitzgerald #include <linux/array_size.h>
10e2bcbf99SRichard Fitzgerald #include <linux/build_bug.h>
11e2bcbf99SRichard Fitzgerald #include <linux/clk.h>
12e2bcbf99SRichard Fitzgerald #include <linux/container_of.h>
13e2bcbf99SRichard Fitzgerald #include <linux/delay.h>
14e2bcbf99SRichard Fitzgerald #include <linux/err.h>
15e2bcbf99SRichard Fitzgerald #include <linux/gcd.h>
16e2bcbf99SRichard Fitzgerald #include <linux/gpio/consumer.h>
17e2bcbf99SRichard Fitzgerald #include <linux/minmax.h>
18e2bcbf99SRichard Fitzgerald #include <linux/module.h>
19e2bcbf99SRichard Fitzgerald #include <linux/of.h>
20e2bcbf99SRichard Fitzgerald #include <linux/pm_runtime.h>
21e2bcbf99SRichard Fitzgerald #include <linux/property.h>
22e2bcbf99SRichard Fitzgerald #include <linux/regmap.h>
23e2bcbf99SRichard Fitzgerald #include <linux/regulator/consumer.h>
24e2bcbf99SRichard Fitzgerald #include <linux/slab.h>
25e2bcbf99SRichard Fitzgerald #include <linux/spi/spi.h>
26e2bcbf99SRichard Fitzgerald #include <linux/string_choices.h>
27e2bcbf99SRichard Fitzgerald #include <sound/cs48l32.h>
28e2bcbf99SRichard Fitzgerald #include <sound/cs48l32_registers.h>
29e2bcbf99SRichard Fitzgerald #include <sound/pcm.h>
30e2bcbf99SRichard Fitzgerald #include <sound/pcm_params.h>
31e2bcbf99SRichard Fitzgerald #include <sound/soc.h>
32e2bcbf99SRichard Fitzgerald #include <sound/soc-component.h>
33e2bcbf99SRichard Fitzgerald #include <sound/soc-dai.h>
34e2bcbf99SRichard Fitzgerald #include <sound/soc-dapm.h>
35e2bcbf99SRichard Fitzgerald #include <sound/tlv.h>
36e2bcbf99SRichard Fitzgerald
37e2bcbf99SRichard Fitzgerald #include "cs48l32.h"
38e2bcbf99SRichard Fitzgerald
39e2bcbf99SRichard Fitzgerald static const char * const cs48l32_core_supplies[] = { "vdd-a", "vdd-io" };
40e2bcbf99SRichard Fitzgerald
41e2bcbf99SRichard Fitzgerald static const struct cs_dsp_region cs48l32_dsp1_regions[] = {
42e2bcbf99SRichard Fitzgerald { .type = WMFW_HALO_PM_PACKED, .base = 0x3800000 },
43e2bcbf99SRichard Fitzgerald { .type = WMFW_HALO_XM_PACKED, .base = 0x2000000 },
44e2bcbf99SRichard Fitzgerald { .type = WMFW_ADSP2_XM, .base = 0x2800000 },
45e2bcbf99SRichard Fitzgerald { .type = WMFW_HALO_YM_PACKED, .base = 0x2C00000 },
46e2bcbf99SRichard Fitzgerald { .type = WMFW_ADSP2_YM, .base = 0x3400000 },
47e2bcbf99SRichard Fitzgerald };
48e2bcbf99SRichard Fitzgerald
49e2bcbf99SRichard Fitzgerald static const struct cs48l32_dsp_power_reg_block cs48l32_dsp1_sram_ext_regs[] = {
50e2bcbf99SRichard Fitzgerald { CS48L32_DSP1_XM_SRAM_IBUS_SETUP_1, CS48L32_DSP1_XM_SRAM_IBUS_SETUP_24 },
51e2bcbf99SRichard Fitzgerald { CS48L32_DSP1_YM_SRAM_IBUS_SETUP_1, CS48L32_DSP1_YM_SRAM_IBUS_SETUP_8 },
52e2bcbf99SRichard Fitzgerald { CS48L32_DSP1_PM_SRAM_IBUS_SETUP_1, CS48L32_DSP1_PM_SRAM_IBUS_SETUP_7 },
53e2bcbf99SRichard Fitzgerald };
54e2bcbf99SRichard Fitzgerald
55e2bcbf99SRichard Fitzgerald static const unsigned int cs48l32_dsp1_sram_pwd_regs[] = {
56e2bcbf99SRichard Fitzgerald CS48L32_DSP1_XM_SRAM_IBUS_SETUP_0,
57e2bcbf99SRichard Fitzgerald CS48L32_DSP1_YM_SRAM_IBUS_SETUP_0,
58e2bcbf99SRichard Fitzgerald CS48L32_DSP1_PM_SRAM_IBUS_SETUP_0,
59e2bcbf99SRichard Fitzgerald };
60e2bcbf99SRichard Fitzgerald
61e2bcbf99SRichard Fitzgerald static const struct cs48l32_dsp_power_regs cs48l32_dsp_sram_regs = {
62e2bcbf99SRichard Fitzgerald .ext = cs48l32_dsp1_sram_ext_regs,
63e2bcbf99SRichard Fitzgerald .n_ext = ARRAY_SIZE(cs48l32_dsp1_sram_ext_regs),
64e2bcbf99SRichard Fitzgerald .pwd = cs48l32_dsp1_sram_pwd_regs,
65e2bcbf99SRichard Fitzgerald .n_pwd = ARRAY_SIZE(cs48l32_dsp1_sram_pwd_regs),
66e2bcbf99SRichard Fitzgerald };
67e2bcbf99SRichard Fitzgerald
68e2bcbf99SRichard Fitzgerald static const char * const cs48l32_mixer_texts[] = {
69e2bcbf99SRichard Fitzgerald "None",
70e2bcbf99SRichard Fitzgerald "Tone Generator 1",
71e2bcbf99SRichard Fitzgerald "Tone Generator 2",
72e2bcbf99SRichard Fitzgerald "Noise Generator",
73e2bcbf99SRichard Fitzgerald "IN1L",
74e2bcbf99SRichard Fitzgerald "IN1R",
75e2bcbf99SRichard Fitzgerald "IN2L",
76e2bcbf99SRichard Fitzgerald "IN2R",
77e2bcbf99SRichard Fitzgerald "ASP1RX1",
78e2bcbf99SRichard Fitzgerald "ASP1RX2",
79e2bcbf99SRichard Fitzgerald "ASP1RX3",
80e2bcbf99SRichard Fitzgerald "ASP1RX4",
81e2bcbf99SRichard Fitzgerald "ASP1RX5",
82e2bcbf99SRichard Fitzgerald "ASP1RX6",
83e2bcbf99SRichard Fitzgerald "ASP1RX7",
84e2bcbf99SRichard Fitzgerald "ASP1RX8",
85e2bcbf99SRichard Fitzgerald "ASP2RX1",
86e2bcbf99SRichard Fitzgerald "ASP2RX2",
87e2bcbf99SRichard Fitzgerald "ASP2RX3",
88e2bcbf99SRichard Fitzgerald "ASP2RX4",
89e2bcbf99SRichard Fitzgerald "ISRC1INT1",
90e2bcbf99SRichard Fitzgerald "ISRC1INT2",
91e2bcbf99SRichard Fitzgerald "ISRC1INT3",
92e2bcbf99SRichard Fitzgerald "ISRC1INT4",
93e2bcbf99SRichard Fitzgerald "ISRC1DEC1",
94e2bcbf99SRichard Fitzgerald "ISRC1DEC2",
95e2bcbf99SRichard Fitzgerald "ISRC1DEC3",
96e2bcbf99SRichard Fitzgerald "ISRC1DEC4",
97e2bcbf99SRichard Fitzgerald "ISRC2INT1",
98e2bcbf99SRichard Fitzgerald "ISRC2INT2",
99e2bcbf99SRichard Fitzgerald "ISRC2DEC1",
100e2bcbf99SRichard Fitzgerald "ISRC2DEC2",
101e2bcbf99SRichard Fitzgerald "ISRC3INT1",
102e2bcbf99SRichard Fitzgerald "ISRC3INT2",
103e2bcbf99SRichard Fitzgerald "ISRC3DEC1",
104e2bcbf99SRichard Fitzgerald "ISRC3DEC2",
105e2bcbf99SRichard Fitzgerald "EQ1",
106e2bcbf99SRichard Fitzgerald "EQ2",
107e2bcbf99SRichard Fitzgerald "EQ3",
108e2bcbf99SRichard Fitzgerald "EQ4",
109e2bcbf99SRichard Fitzgerald "DRC1L",
110e2bcbf99SRichard Fitzgerald "DRC1R",
111e2bcbf99SRichard Fitzgerald "DRC2L",
112e2bcbf99SRichard Fitzgerald "DRC2R",
113e2bcbf99SRichard Fitzgerald "LHPF1",
114e2bcbf99SRichard Fitzgerald "LHPF2",
115e2bcbf99SRichard Fitzgerald "LHPF3",
116e2bcbf99SRichard Fitzgerald "LHPF4",
117e2bcbf99SRichard Fitzgerald "Ultrasonic 1",
118e2bcbf99SRichard Fitzgerald "Ultrasonic 2",
119e2bcbf99SRichard Fitzgerald "DSP1.1",
120e2bcbf99SRichard Fitzgerald "DSP1.2",
121e2bcbf99SRichard Fitzgerald "DSP1.3",
122e2bcbf99SRichard Fitzgerald "DSP1.4",
123e2bcbf99SRichard Fitzgerald "DSP1.5",
124e2bcbf99SRichard Fitzgerald "DSP1.6",
125e2bcbf99SRichard Fitzgerald "DSP1.7",
126e2bcbf99SRichard Fitzgerald "DSP1.8",
127e2bcbf99SRichard Fitzgerald };
128e2bcbf99SRichard Fitzgerald
129e2bcbf99SRichard Fitzgerald static unsigned int cs48l32_mixer_values[] = {
130e2bcbf99SRichard Fitzgerald 0x000, /* Silence (mute) */
131e2bcbf99SRichard Fitzgerald 0x004, /* Tone generator 1 */
132e2bcbf99SRichard Fitzgerald 0x005, /* Tone generator 2 */
133e2bcbf99SRichard Fitzgerald 0x00C, /* Noise Generator */
134e2bcbf99SRichard Fitzgerald 0x010, /* IN1L signal path */
135e2bcbf99SRichard Fitzgerald 0x011, /* IN1R signal path */
136e2bcbf99SRichard Fitzgerald 0x012, /* IN2L signal path */
137e2bcbf99SRichard Fitzgerald 0x013, /* IN2R signal path */
138e2bcbf99SRichard Fitzgerald 0x020, /* ASP1 RX1 */
139e2bcbf99SRichard Fitzgerald 0x021, /* ASP1 RX2 */
140e2bcbf99SRichard Fitzgerald 0x022, /* ASP1 RX3 */
141e2bcbf99SRichard Fitzgerald 0x023, /* ASP1 RX4 */
142e2bcbf99SRichard Fitzgerald 0x024, /* ASP1 RX5 */
143e2bcbf99SRichard Fitzgerald 0x025, /* ASP1 RX6 */
144e2bcbf99SRichard Fitzgerald 0x026, /* ASP1 RX7 */
145e2bcbf99SRichard Fitzgerald 0x027, /* ASP1 RX8 */
146e2bcbf99SRichard Fitzgerald 0x030, /* ASP2 RX1 */
147e2bcbf99SRichard Fitzgerald 0x031, /* ASP2 RX2 */
148e2bcbf99SRichard Fitzgerald 0x032, /* ASP2 RX3 */
149e2bcbf99SRichard Fitzgerald 0x033, /* ASP2 RX4 */
150e2bcbf99SRichard Fitzgerald 0x098, /* ISRC1 INT1 */
151e2bcbf99SRichard Fitzgerald 0x099, /* ISRC1 INT2 */
152e2bcbf99SRichard Fitzgerald 0x09a, /* ISRC1 INT3 */
153e2bcbf99SRichard Fitzgerald 0x09b, /* ISRC1 INT4 */
154e2bcbf99SRichard Fitzgerald 0x09C, /* ISRC1 DEC1 */
155e2bcbf99SRichard Fitzgerald 0x09D, /* ISRC1 DEC2 */
156e2bcbf99SRichard Fitzgerald 0x09e, /* ISRC1 DEC3 */
157e2bcbf99SRichard Fitzgerald 0x09f, /* ISRC1 DEC4 */
158e2bcbf99SRichard Fitzgerald 0x0A0, /* ISRC2 INT1 */
159e2bcbf99SRichard Fitzgerald 0x0A1, /* ISRC2 INT2 */
160e2bcbf99SRichard Fitzgerald 0x0A4, /* ISRC2 DEC1 */
161e2bcbf99SRichard Fitzgerald 0x0A5, /* ISRC2 DEC2 */
162e2bcbf99SRichard Fitzgerald 0x0A8, /* ISRC3 INT1 */
163e2bcbf99SRichard Fitzgerald 0x0A9, /* ISRC3 INT2 */
164e2bcbf99SRichard Fitzgerald 0x0AC, /* ISRC3 DEC1 */
165e2bcbf99SRichard Fitzgerald 0x0AD, /* ISRC3 DEC2 */
166e2bcbf99SRichard Fitzgerald 0x0B8, /* EQ1 */
167e2bcbf99SRichard Fitzgerald 0x0B9, /* EQ2 */
168e2bcbf99SRichard Fitzgerald 0x0BA, /* EQ3 */
169e2bcbf99SRichard Fitzgerald 0x0BB, /* EQ4 */
170e2bcbf99SRichard Fitzgerald 0x0C0, /* DRC1 Left */
171e2bcbf99SRichard Fitzgerald 0x0C1, /* DRC1 Right */
172e2bcbf99SRichard Fitzgerald 0x0C2, /* DRC2 Left */
173e2bcbf99SRichard Fitzgerald 0x0C3, /* DRC2 Right */
174e2bcbf99SRichard Fitzgerald 0x0C8, /* LHPF1 */
175e2bcbf99SRichard Fitzgerald 0x0C9, /* LHPF2 */
176e2bcbf99SRichard Fitzgerald 0x0CA, /* LHPF3 */
177e2bcbf99SRichard Fitzgerald 0x0CB, /* LHPF4 */
178e2bcbf99SRichard Fitzgerald 0x0D8, /* Ultrasonic 1 */
179e2bcbf99SRichard Fitzgerald 0x0D9, /* Ultrasonic 2 */
180e2bcbf99SRichard Fitzgerald 0x100, /* DSP1 channel 1 */
181e2bcbf99SRichard Fitzgerald 0x101, /* DSP1 channel 2 */
182e2bcbf99SRichard Fitzgerald 0x102, /* DSP1 channel 3 */
183e2bcbf99SRichard Fitzgerald 0x103, /* DSP1 channel 4 */
184e2bcbf99SRichard Fitzgerald 0x104, /* DSP1 channel 5 */
185e2bcbf99SRichard Fitzgerald 0x105, /* DSP1 channel 6 */
186e2bcbf99SRichard Fitzgerald 0x106, /* DSP1 channel 7 */
187e2bcbf99SRichard Fitzgerald 0x107, /* DSP1 channel 8 */
188e2bcbf99SRichard Fitzgerald };
189e2bcbf99SRichard Fitzgerald static_assert(ARRAY_SIZE(cs48l32_mixer_texts) == ARRAY_SIZE(cs48l32_mixer_values));
190e2bcbf99SRichard Fitzgerald #define CS48L32_NUM_MIXER_INPUTS ARRAY_SIZE(cs48l32_mixer_values)
191e2bcbf99SRichard Fitzgerald
192e2bcbf99SRichard Fitzgerald static const DECLARE_TLV_DB_SCALE(cs48l32_ana_tlv, 0, 100, 0);
193e2bcbf99SRichard Fitzgerald static const DECLARE_TLV_DB_SCALE(cs48l32_eq_tlv, -1200, 100, 0);
194e2bcbf99SRichard Fitzgerald static const DECLARE_TLV_DB_SCALE(cs48l32_digital_tlv, -6400, 50, 0);
195e2bcbf99SRichard Fitzgerald static const DECLARE_TLV_DB_SCALE(cs48l32_noise_tlv, -10800, 600, 0);
196e2bcbf99SRichard Fitzgerald static const DECLARE_TLV_DB_SCALE(cs48l32_mixer_tlv, -3200, 100, 0);
197e2bcbf99SRichard Fitzgerald static const DECLARE_TLV_DB_SCALE(cs48l32_us_tlv, 0, 600, 0);
198e2bcbf99SRichard Fitzgerald
cs48l32_spin_sysclk(struct cs48l32_codec * cs48l32_codec)199e2bcbf99SRichard Fitzgerald static void cs48l32_spin_sysclk(struct cs48l32_codec *cs48l32_codec)
200e2bcbf99SRichard Fitzgerald {
201e2bcbf99SRichard Fitzgerald struct cs48l32 *cs48l32 = &cs48l32_codec->core;
202e2bcbf99SRichard Fitzgerald unsigned int val;
203e2bcbf99SRichard Fitzgerald int ret, i;
204e2bcbf99SRichard Fitzgerald
205e2bcbf99SRichard Fitzgerald /* Skip this if the chip is down */
206e2bcbf99SRichard Fitzgerald if (pm_runtime_suspended(cs48l32->dev))
207e2bcbf99SRichard Fitzgerald return;
208e2bcbf99SRichard Fitzgerald
209e2bcbf99SRichard Fitzgerald /*
210e2bcbf99SRichard Fitzgerald * Just read a register a few times to ensure the internal
211e2bcbf99SRichard Fitzgerald * oscillator sends out some clocks.
212e2bcbf99SRichard Fitzgerald */
213e2bcbf99SRichard Fitzgerald for (i = 0; i < 4; i++) {
214e2bcbf99SRichard Fitzgerald ret = regmap_read(cs48l32->regmap, CS48L32_DEVID, &val);
215e2bcbf99SRichard Fitzgerald if (ret)
216e2bcbf99SRichard Fitzgerald dev_err(cs48l32_codec->core.dev, "%s Failed to read register: %d (%d)\n",
217e2bcbf99SRichard Fitzgerald __func__, ret, i);
218e2bcbf99SRichard Fitzgerald }
219e2bcbf99SRichard Fitzgerald
220e2bcbf99SRichard Fitzgerald udelay(300);
221e2bcbf99SRichard Fitzgerald }
222e2bcbf99SRichard Fitzgerald
223e2bcbf99SRichard Fitzgerald static const char * const cs48l32_rate_text[] = {
224e2bcbf99SRichard Fitzgerald "Sample Rate 1", "Sample Rate 2", "Sample Rate 3", "Sample Rate 4",
225e2bcbf99SRichard Fitzgerald };
226e2bcbf99SRichard Fitzgerald
227e2bcbf99SRichard Fitzgerald static const unsigned int cs48l32_rate_val[] = {
228e2bcbf99SRichard Fitzgerald 0x0, 0x1, 0x2, 0x3,
229e2bcbf99SRichard Fitzgerald };
230e2bcbf99SRichard Fitzgerald static_assert(ARRAY_SIZE(cs48l32_rate_val) == ARRAY_SIZE(cs48l32_rate_text));
231e2bcbf99SRichard Fitzgerald
cs48l32_rate_put(struct snd_kcontrol * kcontrol,struct snd_ctl_elem_value * ucontrol)232e2bcbf99SRichard Fitzgerald static int cs48l32_rate_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
233e2bcbf99SRichard Fitzgerald {
234e2bcbf99SRichard Fitzgerald struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol);
235e2bcbf99SRichard Fitzgerald struct cs48l32_codec *cs48l32_codec = snd_soc_component_get_drvdata(component);
236e2bcbf99SRichard Fitzgerald int ret;
237e2bcbf99SRichard Fitzgerald
238e2bcbf99SRichard Fitzgerald /* Prevent any mixer mux changes while we do this */
239e2bcbf99SRichard Fitzgerald mutex_lock(&cs48l32_codec->rate_lock);
240e2bcbf99SRichard Fitzgerald
241e2bcbf99SRichard Fitzgerald /* The write must be guarded by a number of SYSCLK cycles */
242e2bcbf99SRichard Fitzgerald cs48l32_spin_sysclk(cs48l32_codec);
243e2bcbf99SRichard Fitzgerald ret = snd_soc_put_enum_double(kcontrol, ucontrol);
244e2bcbf99SRichard Fitzgerald cs48l32_spin_sysclk(cs48l32_codec);
245e2bcbf99SRichard Fitzgerald
246e2bcbf99SRichard Fitzgerald mutex_unlock(&cs48l32_codec->rate_lock);
247e2bcbf99SRichard Fitzgerald
248e2bcbf99SRichard Fitzgerald return ret;
249e2bcbf99SRichard Fitzgerald }
250e2bcbf99SRichard Fitzgerald
251e2bcbf99SRichard Fitzgerald static const char * const cs48l32_sample_rate_text[] = {
252e2bcbf99SRichard Fitzgerald "12kHz",
253e2bcbf99SRichard Fitzgerald "24kHz",
254e2bcbf99SRichard Fitzgerald "48kHz",
255e2bcbf99SRichard Fitzgerald "96kHz",
256e2bcbf99SRichard Fitzgerald "192kHz",
257e2bcbf99SRichard Fitzgerald "384kHz",
258e2bcbf99SRichard Fitzgerald "768kHz",
259e2bcbf99SRichard Fitzgerald "11.025kHz",
260e2bcbf99SRichard Fitzgerald "22.05kHz",
261e2bcbf99SRichard Fitzgerald "44.1kHz",
262e2bcbf99SRichard Fitzgerald "88.2kHz",
263e2bcbf99SRichard Fitzgerald "176.4kHz",
264e2bcbf99SRichard Fitzgerald "352.8kHz",
265e2bcbf99SRichard Fitzgerald "705.6kHz",
266e2bcbf99SRichard Fitzgerald "8kHz",
267e2bcbf99SRichard Fitzgerald "16kHz",
268e2bcbf99SRichard Fitzgerald "32kHz",
269e2bcbf99SRichard Fitzgerald };
270e2bcbf99SRichard Fitzgerald
271e2bcbf99SRichard Fitzgerald static const unsigned int cs48l32_sample_rate_val[] = {
272e2bcbf99SRichard Fitzgerald 0x01, /* 12kHz */
273e2bcbf99SRichard Fitzgerald 0x02, /* 24kHz */
274e2bcbf99SRichard Fitzgerald 0x03, /* 48kHz */
275e2bcbf99SRichard Fitzgerald 0x04, /* 96kHz */
276e2bcbf99SRichard Fitzgerald 0x05, /* 192kHz */
277e2bcbf99SRichard Fitzgerald 0x06, /* 384kHz */
278e2bcbf99SRichard Fitzgerald 0x07, /* 768kHz */
279e2bcbf99SRichard Fitzgerald 0x09, /* 11.025kHz */
280e2bcbf99SRichard Fitzgerald 0x0a, /* 22.05kHz */
281e2bcbf99SRichard Fitzgerald 0x0b, /* 44.1kHz */
282e2bcbf99SRichard Fitzgerald 0x0c, /* 88.2kHz */
283e2bcbf99SRichard Fitzgerald 0x0d, /* 176.4kHz */
284e2bcbf99SRichard Fitzgerald 0x0e, /* 352.8kHz */
285e2bcbf99SRichard Fitzgerald 0x0f, /* 705.6kHz */
286e2bcbf99SRichard Fitzgerald 0x11, /* 8kHz */
287e2bcbf99SRichard Fitzgerald 0x12, /* 16kHz */
288e2bcbf99SRichard Fitzgerald 0x13, /* 32kHz */
289e2bcbf99SRichard Fitzgerald };
290e2bcbf99SRichard Fitzgerald static_assert(ARRAY_SIZE(cs48l32_sample_rate_val) == ARRAY_SIZE(cs48l32_sample_rate_text));
291e2bcbf99SRichard Fitzgerald #define CS48L32_SAMPLE_RATE_ENUM_SIZE ARRAY_SIZE(cs48l32_sample_rate_val)
292e2bcbf99SRichard Fitzgerald
293e2bcbf99SRichard Fitzgerald static const struct soc_enum cs48l32_sample_rate[] = {
294e2bcbf99SRichard Fitzgerald SOC_VALUE_ENUM_SINGLE(CS48L32_SAMPLE_RATE1,
295e2bcbf99SRichard Fitzgerald CS48L32_SAMPLE_RATE_1_SHIFT,
296e2bcbf99SRichard Fitzgerald CS48L32_SAMPLE_RATE_1_MASK >> CS48L32_SAMPLE_RATE_1_SHIFT,
297e2bcbf99SRichard Fitzgerald CS48L32_SAMPLE_RATE_ENUM_SIZE,
298e2bcbf99SRichard Fitzgerald cs48l32_sample_rate_text,
299e2bcbf99SRichard Fitzgerald cs48l32_sample_rate_val),
300e2bcbf99SRichard Fitzgerald SOC_VALUE_ENUM_SINGLE(CS48L32_SAMPLE_RATE2,
301e2bcbf99SRichard Fitzgerald CS48L32_SAMPLE_RATE_1_SHIFT,
302e2bcbf99SRichard Fitzgerald CS48L32_SAMPLE_RATE_1_MASK >> CS48L32_SAMPLE_RATE_1_SHIFT,
303e2bcbf99SRichard Fitzgerald CS48L32_SAMPLE_RATE_ENUM_SIZE,
304e2bcbf99SRichard Fitzgerald cs48l32_sample_rate_text,
305e2bcbf99SRichard Fitzgerald cs48l32_sample_rate_val),
306e2bcbf99SRichard Fitzgerald SOC_VALUE_ENUM_SINGLE(CS48L32_SAMPLE_RATE3,
307e2bcbf99SRichard Fitzgerald CS48L32_SAMPLE_RATE_1_SHIFT,
308e2bcbf99SRichard Fitzgerald CS48L32_SAMPLE_RATE_1_MASK >> CS48L32_SAMPLE_RATE_1_SHIFT,
309e2bcbf99SRichard Fitzgerald CS48L32_SAMPLE_RATE_ENUM_SIZE,
310e2bcbf99SRichard Fitzgerald cs48l32_sample_rate_text,
311e2bcbf99SRichard Fitzgerald cs48l32_sample_rate_val),
312e2bcbf99SRichard Fitzgerald SOC_VALUE_ENUM_SINGLE(CS48L32_SAMPLE_RATE4,
313e2bcbf99SRichard Fitzgerald CS48L32_SAMPLE_RATE_1_SHIFT,
314e2bcbf99SRichard Fitzgerald CS48L32_SAMPLE_RATE_1_MASK >> CS48L32_SAMPLE_RATE_1_SHIFT,
315e2bcbf99SRichard Fitzgerald CS48L32_SAMPLE_RATE_ENUM_SIZE,
316e2bcbf99SRichard Fitzgerald cs48l32_sample_rate_text,
317e2bcbf99SRichard Fitzgerald cs48l32_sample_rate_val),
318e2bcbf99SRichard Fitzgerald };
319e2bcbf99SRichard Fitzgerald
cs48l32_inmux_put(struct snd_kcontrol * kcontrol,struct snd_ctl_elem_value * ucontrol)320e2bcbf99SRichard Fitzgerald static int cs48l32_inmux_put(struct snd_kcontrol *kcontrol,
321e2bcbf99SRichard Fitzgerald struct snd_ctl_elem_value *ucontrol)
322e2bcbf99SRichard Fitzgerald {
323e2bcbf99SRichard Fitzgerald struct snd_soc_component *component = snd_soc_dapm_kcontrol_component(kcontrol);
324e2bcbf99SRichard Fitzgerald struct snd_soc_dapm_context *dapm = snd_soc_dapm_kcontrol_dapm(kcontrol);
325e2bcbf99SRichard Fitzgerald struct cs48l32_codec *cs48l32_codec = snd_soc_component_get_drvdata(component);
326e2bcbf99SRichard Fitzgerald struct soc_enum *e = (struct soc_enum *) kcontrol->private_value;
327e2bcbf99SRichard Fitzgerald unsigned int mux, src_val, in_type;
328e2bcbf99SRichard Fitzgerald int ret;
329e2bcbf99SRichard Fitzgerald
330e2bcbf99SRichard Fitzgerald mux = ucontrol->value.enumerated.item[0];
331e2bcbf99SRichard Fitzgerald if (mux > 1)
332e2bcbf99SRichard Fitzgerald return -EINVAL;
333e2bcbf99SRichard Fitzgerald
334e2bcbf99SRichard Fitzgerald switch (e->reg) {
335e2bcbf99SRichard Fitzgerald case CS48L32_IN1L_CONTROL1:
336e2bcbf99SRichard Fitzgerald in_type = cs48l32_codec->in_type[0][mux];
337e2bcbf99SRichard Fitzgerald break;
338e2bcbf99SRichard Fitzgerald case CS48L32_IN1R_CONTROL1:
339e2bcbf99SRichard Fitzgerald in_type = cs48l32_codec->in_type[1][mux];
340e2bcbf99SRichard Fitzgerald break;
341e2bcbf99SRichard Fitzgerald default:
342e2bcbf99SRichard Fitzgerald return -EINVAL;
343e2bcbf99SRichard Fitzgerald }
344e2bcbf99SRichard Fitzgerald
345e2bcbf99SRichard Fitzgerald src_val = mux << e->shift_l;
346e2bcbf99SRichard Fitzgerald
347e2bcbf99SRichard Fitzgerald if (in_type == CS48L32_IN_TYPE_SE)
348e2bcbf99SRichard Fitzgerald src_val |= 1 << CS48L32_INx_SRC_SHIFT;
349e2bcbf99SRichard Fitzgerald
350e2bcbf99SRichard Fitzgerald ret = snd_soc_component_update_bits(dapm->component,
351e2bcbf99SRichard Fitzgerald e->reg,
352e2bcbf99SRichard Fitzgerald CS48L32_INx_SRC_MASK,
353e2bcbf99SRichard Fitzgerald src_val);
354e2bcbf99SRichard Fitzgerald if (ret > 0)
355e2bcbf99SRichard Fitzgerald snd_soc_dapm_mux_update_power(dapm, kcontrol, mux, e, NULL);
356e2bcbf99SRichard Fitzgerald
357e2bcbf99SRichard Fitzgerald return ret;
358e2bcbf99SRichard Fitzgerald }
359e2bcbf99SRichard Fitzgerald
360e2bcbf99SRichard Fitzgerald static const char * const cs48l32_inmux_texts[] = {
361e2bcbf99SRichard Fitzgerald "Analog 1", "Analog 2",
362e2bcbf99SRichard Fitzgerald };
363e2bcbf99SRichard Fitzgerald
364e2bcbf99SRichard Fitzgerald static SOC_ENUM_SINGLE_DECL(cs48l32_in1muxl_enum,
365e2bcbf99SRichard Fitzgerald CS48L32_IN1L_CONTROL1,
366e2bcbf99SRichard Fitzgerald CS48L32_INx_SRC_SHIFT + 1,
367e2bcbf99SRichard Fitzgerald cs48l32_inmux_texts);
368e2bcbf99SRichard Fitzgerald
369e2bcbf99SRichard Fitzgerald static SOC_ENUM_SINGLE_DECL(cs48l32_in1muxr_enum,
370e2bcbf99SRichard Fitzgerald CS48L32_IN1R_CONTROL1,
371e2bcbf99SRichard Fitzgerald CS48L32_INx_SRC_SHIFT + 1,
372e2bcbf99SRichard Fitzgerald cs48l32_inmux_texts);
373e2bcbf99SRichard Fitzgerald
374e2bcbf99SRichard Fitzgerald static const struct snd_kcontrol_new cs48l32_inmux[] = {
375e2bcbf99SRichard Fitzgerald SOC_DAPM_ENUM_EXT("IN1L Mux", cs48l32_in1muxl_enum,
376e2bcbf99SRichard Fitzgerald snd_soc_dapm_get_enum_double, cs48l32_inmux_put),
377e2bcbf99SRichard Fitzgerald SOC_DAPM_ENUM_EXT("IN1R Mux", cs48l32_in1muxr_enum,
378e2bcbf99SRichard Fitzgerald snd_soc_dapm_get_enum_double, cs48l32_inmux_put),
379e2bcbf99SRichard Fitzgerald };
380e2bcbf99SRichard Fitzgerald
381e2bcbf99SRichard Fitzgerald static const char * const cs48l32_dmode_texts[] = {
382e2bcbf99SRichard Fitzgerald "Analog", "Digital",
383e2bcbf99SRichard Fitzgerald };
384e2bcbf99SRichard Fitzgerald
cs48l32_dmode_put(struct snd_kcontrol * kcontrol,struct snd_ctl_elem_value * ucontrol)385e2bcbf99SRichard Fitzgerald static int cs48l32_dmode_put(struct snd_kcontrol *kcontrol,
386e2bcbf99SRichard Fitzgerald struct snd_ctl_elem_value *ucontrol)
387e2bcbf99SRichard Fitzgerald {
388e2bcbf99SRichard Fitzgerald struct snd_soc_dapm_context *dapm = snd_soc_dapm_kcontrol_dapm(kcontrol);
389e2bcbf99SRichard Fitzgerald struct snd_soc_component *component = snd_soc_dapm_to_component(dapm);
390e2bcbf99SRichard Fitzgerald struct soc_enum *e = (struct soc_enum *) kcontrol->private_value;
391e2bcbf99SRichard Fitzgerald unsigned int mode;
392e2bcbf99SRichard Fitzgerald int ret, result;
393e2bcbf99SRichard Fitzgerald
394e2bcbf99SRichard Fitzgerald mode = ucontrol->value.enumerated.item[0];
395e2bcbf99SRichard Fitzgerald switch (mode) {
396e2bcbf99SRichard Fitzgerald case 0:
397e2bcbf99SRichard Fitzgerald ret = snd_soc_component_update_bits(component,
398e2bcbf99SRichard Fitzgerald CS48L32_ADC1L_ANA_CONTROL1,
399e2bcbf99SRichard Fitzgerald CS48L32_ADC1x_INT_ENA_FRC_MASK,
400e2bcbf99SRichard Fitzgerald CS48L32_ADC1x_INT_ENA_FRC_MASK);
401e2bcbf99SRichard Fitzgerald if (ret < 0) {
402e2bcbf99SRichard Fitzgerald dev_err(component->dev,
403e2bcbf99SRichard Fitzgerald "Failed to set ADC1L_INT_ENA_FRC: %d\n", ret);
404e2bcbf99SRichard Fitzgerald return ret;
405e2bcbf99SRichard Fitzgerald }
406e2bcbf99SRichard Fitzgerald
407e2bcbf99SRichard Fitzgerald ret = snd_soc_component_update_bits(component,
408e2bcbf99SRichard Fitzgerald CS48L32_ADC1R_ANA_CONTROL1,
409e2bcbf99SRichard Fitzgerald CS48L32_ADC1x_INT_ENA_FRC_MASK,
410e2bcbf99SRichard Fitzgerald CS48L32_ADC1x_INT_ENA_FRC_MASK);
411e2bcbf99SRichard Fitzgerald if (ret < 0) {
412e2bcbf99SRichard Fitzgerald dev_err(component->dev,
413e2bcbf99SRichard Fitzgerald "Failed to set ADC1R_INT_ENA_FRC: %d\n", ret);
414e2bcbf99SRichard Fitzgerald return ret;
415e2bcbf99SRichard Fitzgerald }
416e2bcbf99SRichard Fitzgerald
417e2bcbf99SRichard Fitzgerald result = snd_soc_component_update_bits(component,
418e2bcbf99SRichard Fitzgerald e->reg,
419e2bcbf99SRichard Fitzgerald BIT(CS48L32_IN1_MODE_SHIFT),
420e2bcbf99SRichard Fitzgerald 0);
421e2bcbf99SRichard Fitzgerald if (result < 0) {
422e2bcbf99SRichard Fitzgerald dev_err(component->dev, "Failed to set input mode: %d\n", result);
423e2bcbf99SRichard Fitzgerald return result;
424e2bcbf99SRichard Fitzgerald }
425e2bcbf99SRichard Fitzgerald
426e2bcbf99SRichard Fitzgerald usleep_range(200, 300);
427e2bcbf99SRichard Fitzgerald
428e2bcbf99SRichard Fitzgerald ret = snd_soc_component_update_bits(component,
429e2bcbf99SRichard Fitzgerald CS48L32_ADC1L_ANA_CONTROL1,
430e2bcbf99SRichard Fitzgerald CS48L32_ADC1x_INT_ENA_FRC_MASK,
431e2bcbf99SRichard Fitzgerald 0);
432e2bcbf99SRichard Fitzgerald if (ret < 0) {
433e2bcbf99SRichard Fitzgerald dev_err(component->dev,
434e2bcbf99SRichard Fitzgerald "Failed to clear ADC1L_INT_ENA_FRC: %d\n", ret);
435e2bcbf99SRichard Fitzgerald return ret;
436e2bcbf99SRichard Fitzgerald }
437e2bcbf99SRichard Fitzgerald
438e2bcbf99SRichard Fitzgerald ret = snd_soc_component_update_bits(component,
439e2bcbf99SRichard Fitzgerald CS48L32_ADC1R_ANA_CONTROL1,
440e2bcbf99SRichard Fitzgerald CS48L32_ADC1x_INT_ENA_FRC_MASK,
441e2bcbf99SRichard Fitzgerald 0);
442e2bcbf99SRichard Fitzgerald if (ret < 0) {
443e2bcbf99SRichard Fitzgerald dev_err(component->dev,
444e2bcbf99SRichard Fitzgerald "Failed to clear ADC1R_INT_ENA_FRC: %d\n", ret);
445e2bcbf99SRichard Fitzgerald return ret;
446e2bcbf99SRichard Fitzgerald }
447e2bcbf99SRichard Fitzgerald
448e2bcbf99SRichard Fitzgerald if (result > 0)
449e2bcbf99SRichard Fitzgerald snd_soc_dapm_mux_update_power(dapm, kcontrol, mode, e, NULL);
450e2bcbf99SRichard Fitzgerald
451e2bcbf99SRichard Fitzgerald return result;
452e2bcbf99SRichard Fitzgerald case 1:
453e2bcbf99SRichard Fitzgerald return snd_soc_dapm_put_enum_double(kcontrol, ucontrol);
454e2bcbf99SRichard Fitzgerald default:
455e2bcbf99SRichard Fitzgerald return -EINVAL;
456e2bcbf99SRichard Fitzgerald }
457e2bcbf99SRichard Fitzgerald }
458e2bcbf99SRichard Fitzgerald
459e2bcbf99SRichard Fitzgerald static SOC_ENUM_SINGLE_DECL(cs48l32_in1dmode_enum,
460e2bcbf99SRichard Fitzgerald CS48L32_INPUT1_CONTROL1,
461e2bcbf99SRichard Fitzgerald CS48L32_IN1_MODE_SHIFT,
462e2bcbf99SRichard Fitzgerald cs48l32_dmode_texts);
463e2bcbf99SRichard Fitzgerald
464e2bcbf99SRichard Fitzgerald static const struct snd_kcontrol_new cs48l32_dmode_mux[] = {
465e2bcbf99SRichard Fitzgerald SOC_DAPM_ENUM_EXT("IN1 Mode", cs48l32_in1dmode_enum,
466e2bcbf99SRichard Fitzgerald snd_soc_dapm_get_enum_double, cs48l32_dmode_put),
467e2bcbf99SRichard Fitzgerald };
468e2bcbf99SRichard Fitzgerald
469e2bcbf99SRichard Fitzgerald static const char * const cs48l32_in_texts[] = {
470e2bcbf99SRichard Fitzgerald "IN1L", "IN1R", "IN2L", "IN2R",
471e2bcbf99SRichard Fitzgerald };
472e2bcbf99SRichard Fitzgerald static_assert(ARRAY_SIZE(cs48l32_in_texts) == CS48L32_MAX_INPUT);
473e2bcbf99SRichard Fitzgerald
474e2bcbf99SRichard Fitzgerald static const char * const cs48l32_us_freq_texts[] = {
475e2bcbf99SRichard Fitzgerald "16-24kHz", "20-28kHz",
476e2bcbf99SRichard Fitzgerald };
477e2bcbf99SRichard Fitzgerald
478e2bcbf99SRichard Fitzgerald static const unsigned int cs48l32_us_freq_val[] = {
479e2bcbf99SRichard Fitzgerald 0x2, 0x3,
480e2bcbf99SRichard Fitzgerald };
481e2bcbf99SRichard Fitzgerald
482e2bcbf99SRichard Fitzgerald static const struct soc_enum cs48l32_us_freq[] = {
483e2bcbf99SRichard Fitzgerald SOC_VALUE_ENUM_SINGLE(CS48L32_US1_CONTROL,
484e2bcbf99SRichard Fitzgerald CS48L32_US1_FREQ_SHIFT,
485e2bcbf99SRichard Fitzgerald CS48L32_US1_FREQ_MASK >> CS48L32_US1_FREQ_SHIFT,
486e2bcbf99SRichard Fitzgerald ARRAY_SIZE(cs48l32_us_freq_val),
487e2bcbf99SRichard Fitzgerald cs48l32_us_freq_texts,
488e2bcbf99SRichard Fitzgerald cs48l32_us_freq_val),
489e2bcbf99SRichard Fitzgerald SOC_VALUE_ENUM_SINGLE(CS48L32_US2_CONTROL,
490e2bcbf99SRichard Fitzgerald CS48L32_US1_FREQ_SHIFT,
491e2bcbf99SRichard Fitzgerald CS48L32_US1_FREQ_MASK >> CS48L32_US1_FREQ_SHIFT,
492e2bcbf99SRichard Fitzgerald ARRAY_SIZE(cs48l32_us_freq_val),
493e2bcbf99SRichard Fitzgerald cs48l32_us_freq_texts,
494e2bcbf99SRichard Fitzgerald cs48l32_us_freq_val),
495e2bcbf99SRichard Fitzgerald };
496e2bcbf99SRichard Fitzgerald
497e2bcbf99SRichard Fitzgerald static const unsigned int cs48l32_us_in_val[] = {
498e2bcbf99SRichard Fitzgerald 0x0, 0x1, 0x2, 0x3,
499e2bcbf99SRichard Fitzgerald };
500e2bcbf99SRichard Fitzgerald
501e2bcbf99SRichard Fitzgerald static const struct soc_enum cs48l32_us_inmux_enum[] = {
502e2bcbf99SRichard Fitzgerald SOC_VALUE_ENUM_SINGLE(CS48L32_US1_CONTROL,
503e2bcbf99SRichard Fitzgerald CS48L32_US1_SRC_SHIFT,
504e2bcbf99SRichard Fitzgerald CS48L32_US1_SRC_MASK >> CS48L32_US1_SRC_SHIFT,
505e2bcbf99SRichard Fitzgerald ARRAY_SIZE(cs48l32_us_in_val),
506e2bcbf99SRichard Fitzgerald cs48l32_in_texts,
507e2bcbf99SRichard Fitzgerald cs48l32_us_in_val),
508e2bcbf99SRichard Fitzgerald SOC_VALUE_ENUM_SINGLE(CS48L32_US2_CONTROL,
509e2bcbf99SRichard Fitzgerald CS48L32_US1_SRC_SHIFT,
510e2bcbf99SRichard Fitzgerald CS48L32_US1_SRC_MASK >> CS48L32_US1_SRC_SHIFT,
511e2bcbf99SRichard Fitzgerald ARRAY_SIZE(cs48l32_us_in_val),
512e2bcbf99SRichard Fitzgerald cs48l32_in_texts,
513e2bcbf99SRichard Fitzgerald cs48l32_us_in_val),
514e2bcbf99SRichard Fitzgerald };
515e2bcbf99SRichard Fitzgerald
516e2bcbf99SRichard Fitzgerald static const struct snd_kcontrol_new cs48l32_us_inmux[] = {
517e2bcbf99SRichard Fitzgerald SOC_DAPM_ENUM("Ultrasonic 1 Input", cs48l32_us_inmux_enum[0]),
518e2bcbf99SRichard Fitzgerald SOC_DAPM_ENUM("Ultrasonic 2 Input", cs48l32_us_inmux_enum[1]),
519e2bcbf99SRichard Fitzgerald };
520e2bcbf99SRichard Fitzgerald
521e2bcbf99SRichard Fitzgerald static const char * const cs48l32_us_det_thr_texts[] = {
522e2bcbf99SRichard Fitzgerald "-6dB", "-9dB", "-12dB", "-15dB", "-18dB", "-21dB", "-24dB", "-27dB",
523e2bcbf99SRichard Fitzgerald };
524e2bcbf99SRichard Fitzgerald
525e2bcbf99SRichard Fitzgerald static const struct soc_enum cs48l32_us_det_thr[] = {
526e2bcbf99SRichard Fitzgerald SOC_ENUM_SINGLE(CS48L32_US1_DET_CONTROL,
527e2bcbf99SRichard Fitzgerald CS48L32_US1_DET_THR_SHIFT,
528e2bcbf99SRichard Fitzgerald ARRAY_SIZE(cs48l32_us_det_thr_texts),
529e2bcbf99SRichard Fitzgerald cs48l32_us_det_thr_texts),
530e2bcbf99SRichard Fitzgerald SOC_ENUM_SINGLE(CS48L32_US2_DET_CONTROL,
531e2bcbf99SRichard Fitzgerald CS48L32_US1_DET_THR_SHIFT,
532e2bcbf99SRichard Fitzgerald ARRAY_SIZE(cs48l32_us_det_thr_texts),
533e2bcbf99SRichard Fitzgerald cs48l32_us_det_thr_texts),
534e2bcbf99SRichard Fitzgerald };
535e2bcbf99SRichard Fitzgerald
536e2bcbf99SRichard Fitzgerald static const char * const cs48l32_us_det_num_texts[] = {
537e2bcbf99SRichard Fitzgerald "1 Sample",
538e2bcbf99SRichard Fitzgerald "2 Samples",
539e2bcbf99SRichard Fitzgerald "4 Samples",
540e2bcbf99SRichard Fitzgerald "8 Samples",
541e2bcbf99SRichard Fitzgerald "16 Samples",
542e2bcbf99SRichard Fitzgerald "32 Samples",
543e2bcbf99SRichard Fitzgerald "64 Samples",
544e2bcbf99SRichard Fitzgerald "128 Samples",
545e2bcbf99SRichard Fitzgerald "256 Samples",
546e2bcbf99SRichard Fitzgerald "512 Samples",
547e2bcbf99SRichard Fitzgerald "1024 Samples",
548e2bcbf99SRichard Fitzgerald "2048 Samples",
549e2bcbf99SRichard Fitzgerald "4096 Samples",
550e2bcbf99SRichard Fitzgerald "8192 Samples",
551e2bcbf99SRichard Fitzgerald "16384 Samples",
552e2bcbf99SRichard Fitzgerald "32768 Samples",
553e2bcbf99SRichard Fitzgerald };
554e2bcbf99SRichard Fitzgerald
555e2bcbf99SRichard Fitzgerald static const struct soc_enum cs48l32_us_det_num[] = {
556e2bcbf99SRichard Fitzgerald SOC_ENUM_SINGLE(CS48L32_US1_DET_CONTROL,
557e2bcbf99SRichard Fitzgerald CS48L32_US1_DET_NUM_SHIFT,
558e2bcbf99SRichard Fitzgerald ARRAY_SIZE(cs48l32_us_det_num_texts),
559e2bcbf99SRichard Fitzgerald cs48l32_us_det_num_texts),
560e2bcbf99SRichard Fitzgerald SOC_ENUM_SINGLE(CS48L32_US2_DET_CONTROL,
561e2bcbf99SRichard Fitzgerald CS48L32_US1_DET_NUM_SHIFT,
562e2bcbf99SRichard Fitzgerald ARRAY_SIZE(cs48l32_us_det_num_texts),
563e2bcbf99SRichard Fitzgerald cs48l32_us_det_num_texts),
564e2bcbf99SRichard Fitzgerald };
565e2bcbf99SRichard Fitzgerald
566e2bcbf99SRichard Fitzgerald static const char * const cs48l32_us_det_hold_texts[] = {
567e2bcbf99SRichard Fitzgerald "0 Samples",
568e2bcbf99SRichard Fitzgerald "31 Samples",
569e2bcbf99SRichard Fitzgerald "63 Samples",
570e2bcbf99SRichard Fitzgerald "127 Samples",
571e2bcbf99SRichard Fitzgerald "255 Samples",
572e2bcbf99SRichard Fitzgerald "511 Samples",
573e2bcbf99SRichard Fitzgerald "1023 Samples",
574e2bcbf99SRichard Fitzgerald "2047 Samples",
575e2bcbf99SRichard Fitzgerald "4095 Samples",
576e2bcbf99SRichard Fitzgerald "8191 Samples",
577e2bcbf99SRichard Fitzgerald "16383 Samples",
578e2bcbf99SRichard Fitzgerald "32767 Samples",
579e2bcbf99SRichard Fitzgerald "65535 Samples",
580e2bcbf99SRichard Fitzgerald "131071 Samples",
581e2bcbf99SRichard Fitzgerald "262143 Samples",
582e2bcbf99SRichard Fitzgerald "524287 Samples",
583e2bcbf99SRichard Fitzgerald };
584e2bcbf99SRichard Fitzgerald
585e2bcbf99SRichard Fitzgerald static const struct soc_enum cs48l32_us_det_hold[] = {
586e2bcbf99SRichard Fitzgerald SOC_ENUM_SINGLE(CS48L32_US1_DET_CONTROL,
587e2bcbf99SRichard Fitzgerald CS48L32_US1_DET_HOLD_SHIFT,
588e2bcbf99SRichard Fitzgerald ARRAY_SIZE(cs48l32_us_det_hold_texts),
589e2bcbf99SRichard Fitzgerald cs48l32_us_det_hold_texts),
590e2bcbf99SRichard Fitzgerald SOC_ENUM_SINGLE(CS48L32_US2_DET_CONTROL,
591e2bcbf99SRichard Fitzgerald CS48L32_US1_DET_HOLD_SHIFT,
592e2bcbf99SRichard Fitzgerald ARRAY_SIZE(cs48l32_us_det_hold_texts),
593e2bcbf99SRichard Fitzgerald cs48l32_us_det_hold_texts),
594e2bcbf99SRichard Fitzgerald };
595e2bcbf99SRichard Fitzgerald
596e2bcbf99SRichard Fitzgerald static const struct soc_enum cs48l32_us_output_rate[] = {
597e2bcbf99SRichard Fitzgerald SOC_VALUE_ENUM_SINGLE(CS48L32_US1_CONTROL,
598e2bcbf99SRichard Fitzgerald CS48L32_US1_RATE_SHIFT,
599e2bcbf99SRichard Fitzgerald CS48L32_US1_RATE_MASK >> CS48L32_US1_RATE_SHIFT,
600e2bcbf99SRichard Fitzgerald ARRAY_SIZE(cs48l32_rate_text),
601e2bcbf99SRichard Fitzgerald cs48l32_rate_text,
602e2bcbf99SRichard Fitzgerald cs48l32_rate_val),
603e2bcbf99SRichard Fitzgerald SOC_VALUE_ENUM_SINGLE(CS48L32_US2_CONTROL,
604e2bcbf99SRichard Fitzgerald CS48L32_US1_RATE_SHIFT,
605e2bcbf99SRichard Fitzgerald CS48L32_US1_RATE_MASK >> CS48L32_US1_RATE_SHIFT,
606e2bcbf99SRichard Fitzgerald ARRAY_SIZE(cs48l32_rate_text),
607e2bcbf99SRichard Fitzgerald cs48l32_rate_text,
608e2bcbf99SRichard Fitzgerald cs48l32_rate_val),
609e2bcbf99SRichard Fitzgerald };
610e2bcbf99SRichard Fitzgerald
611e2bcbf99SRichard Fitzgerald static const char * const cs48l32_us_det_lpf_cut_texts[] = {
612e2bcbf99SRichard Fitzgerald "1722Hz", "833Hz", "408Hz", "203Hz",
613e2bcbf99SRichard Fitzgerald };
614e2bcbf99SRichard Fitzgerald
615e2bcbf99SRichard Fitzgerald static const struct soc_enum cs48l32_us_det_lpf_cut[] = {
616e2bcbf99SRichard Fitzgerald SOC_ENUM_SINGLE(CS48L32_US1_DET_CONTROL,
617e2bcbf99SRichard Fitzgerald CS48L32_US1_DET_LPF_CUT_SHIFT,
618e2bcbf99SRichard Fitzgerald ARRAY_SIZE(cs48l32_us_det_lpf_cut_texts),
619e2bcbf99SRichard Fitzgerald cs48l32_us_det_lpf_cut_texts),
620e2bcbf99SRichard Fitzgerald SOC_ENUM_SINGLE(CS48L32_US2_DET_CONTROL,
621e2bcbf99SRichard Fitzgerald CS48L32_US1_DET_LPF_CUT_SHIFT,
622e2bcbf99SRichard Fitzgerald ARRAY_SIZE(cs48l32_us_det_lpf_cut_texts),
623e2bcbf99SRichard Fitzgerald cs48l32_us_det_lpf_cut_texts),
624e2bcbf99SRichard Fitzgerald };
625e2bcbf99SRichard Fitzgerald
626e2bcbf99SRichard Fitzgerald static const char * const cs48l32_us_det_dcy_texts[] = {
627e2bcbf99SRichard Fitzgerald "0 ms", "0.79 ms", "1.58 ms", "3.16 ms", "6.33 ms", "12.67 ms", "25.34 ms", "50.69 ms",
628e2bcbf99SRichard Fitzgerald };
629e2bcbf99SRichard Fitzgerald
630e2bcbf99SRichard Fitzgerald static const struct soc_enum cs48l32_us_det_dcy[] = {
631e2bcbf99SRichard Fitzgerald SOC_ENUM_SINGLE(CS48L32_US1_DET_CONTROL,
632e2bcbf99SRichard Fitzgerald CS48L32_US1_DET_DCY_SHIFT,
633e2bcbf99SRichard Fitzgerald ARRAY_SIZE(cs48l32_us_det_dcy_texts),
634e2bcbf99SRichard Fitzgerald cs48l32_us_det_dcy_texts),
635e2bcbf99SRichard Fitzgerald SOC_ENUM_SINGLE(CS48L32_US2_DET_CONTROL,
636e2bcbf99SRichard Fitzgerald CS48L32_US1_DET_DCY_SHIFT,
637e2bcbf99SRichard Fitzgerald ARRAY_SIZE(cs48l32_us_det_dcy_texts),
638e2bcbf99SRichard Fitzgerald cs48l32_us_det_dcy_texts),
639e2bcbf99SRichard Fitzgerald };
640e2bcbf99SRichard Fitzgerald
641e2bcbf99SRichard Fitzgerald static const struct snd_kcontrol_new cs48l32_us_switch[] = {
642e2bcbf99SRichard Fitzgerald SOC_DAPM_SINGLE("Switch", SND_SOC_NOPM, 0, 1, 0),
643e2bcbf99SRichard Fitzgerald SOC_DAPM_SINGLE("Switch", SND_SOC_NOPM, 0, 1, 0),
644e2bcbf99SRichard Fitzgerald };
645e2bcbf99SRichard Fitzgerald
646e2bcbf99SRichard Fitzgerald static const char * const cs48l32_vol_ramp_text[] = {
647e2bcbf99SRichard Fitzgerald "0ms/6dB", "0.5ms/6dB", "1ms/6dB", "2ms/6dB", "4ms/6dB", "8ms/6dB", "16ms/6dB", "32ms/6dB",
648e2bcbf99SRichard Fitzgerald };
649e2bcbf99SRichard Fitzgerald
650e2bcbf99SRichard Fitzgerald static SOC_ENUM_SINGLE_DECL(cs48l32_in_vd_ramp,
651e2bcbf99SRichard Fitzgerald CS48L32_INPUT_VOL_CONTROL,
652e2bcbf99SRichard Fitzgerald CS48L32_IN_VD_RAMP_SHIFT,
653e2bcbf99SRichard Fitzgerald cs48l32_vol_ramp_text);
654e2bcbf99SRichard Fitzgerald
655e2bcbf99SRichard Fitzgerald static SOC_ENUM_SINGLE_DECL(cs48l32_in_vi_ramp,
656e2bcbf99SRichard Fitzgerald CS48L32_INPUT_VOL_CONTROL,
657e2bcbf99SRichard Fitzgerald CS48L32_IN_VI_RAMP_SHIFT,
658e2bcbf99SRichard Fitzgerald cs48l32_vol_ramp_text);
659e2bcbf99SRichard Fitzgerald
660e2bcbf99SRichard Fitzgerald static const char * const cs48l32_in_hpf_cut_text[] = {
661e2bcbf99SRichard Fitzgerald "2.5Hz", "5Hz", "10Hz", "20Hz", "40Hz"
662e2bcbf99SRichard Fitzgerald };
663e2bcbf99SRichard Fitzgerald
664e2bcbf99SRichard Fitzgerald static SOC_ENUM_SINGLE_DECL(cs48l32_in_hpf_cut_enum,
665e2bcbf99SRichard Fitzgerald CS48L32_INPUT_HPF_CONTROL,
666e2bcbf99SRichard Fitzgerald CS48L32_IN_HPF_CUT_SHIFT,
667e2bcbf99SRichard Fitzgerald cs48l32_in_hpf_cut_text);
668e2bcbf99SRichard Fitzgerald
669e2bcbf99SRichard Fitzgerald static const char * const cs48l32_in_dmic_osr_text[] = {
670e2bcbf99SRichard Fitzgerald "384kHz", "768kHz", "1.536MHz", "2.048MHz", "2.4576MHz", "3.072MHz", "6.144MHz",
671e2bcbf99SRichard Fitzgerald };
672e2bcbf99SRichard Fitzgerald
673e2bcbf99SRichard Fitzgerald static const struct soc_enum cs48l32_in_dmic_osr[] = {
674e2bcbf99SRichard Fitzgerald SOC_ENUM_SINGLE(CS48L32_INPUT1_CONTROL1,
675e2bcbf99SRichard Fitzgerald CS48L32_IN1_OSR_SHIFT,
676e2bcbf99SRichard Fitzgerald ARRAY_SIZE(cs48l32_in_dmic_osr_text),
677e2bcbf99SRichard Fitzgerald cs48l32_in_dmic_osr_text),
678e2bcbf99SRichard Fitzgerald SOC_ENUM_SINGLE(CS48L32_INPUT2_CONTROL1,
679e2bcbf99SRichard Fitzgerald CS48L32_IN1_OSR_SHIFT,
680e2bcbf99SRichard Fitzgerald ARRAY_SIZE(cs48l32_in_dmic_osr_text),
681e2bcbf99SRichard Fitzgerald cs48l32_in_dmic_osr_text),
682e2bcbf99SRichard Fitzgerald };
683e2bcbf99SRichard Fitzgerald
cs48l32_is_input_enabled(struct snd_soc_component * component,unsigned int reg)684e2bcbf99SRichard Fitzgerald static bool cs48l32_is_input_enabled(struct snd_soc_component *component,
685e2bcbf99SRichard Fitzgerald unsigned int reg)
686e2bcbf99SRichard Fitzgerald {
687e2bcbf99SRichard Fitzgerald unsigned int input_active;
688e2bcbf99SRichard Fitzgerald
689e2bcbf99SRichard Fitzgerald input_active = snd_soc_component_read(component, CS48L32_INPUT_CONTROL);
690e2bcbf99SRichard Fitzgerald switch (reg) {
691e2bcbf99SRichard Fitzgerald case CS48L32_IN1L_CONTROL1:
692e2bcbf99SRichard Fitzgerald return input_active & BIT(CS48L32_IN1L_EN_SHIFT);
693e2bcbf99SRichard Fitzgerald case CS48L32_IN1R_CONTROL1:
694e2bcbf99SRichard Fitzgerald return input_active & BIT(CS48L32_IN1R_EN_SHIFT);
695e2bcbf99SRichard Fitzgerald case CS48L32_IN2L_CONTROL1:
696e2bcbf99SRichard Fitzgerald return input_active & BIT(CS48L32_IN2L_EN_SHIFT);
697e2bcbf99SRichard Fitzgerald case CS48L32_IN2R_CONTROL1:
698e2bcbf99SRichard Fitzgerald return input_active & BIT(CS48L32_IN2R_EN_SHIFT);
699e2bcbf99SRichard Fitzgerald default:
700e2bcbf99SRichard Fitzgerald return false;
701e2bcbf99SRichard Fitzgerald }
702e2bcbf99SRichard Fitzgerald }
703e2bcbf99SRichard Fitzgerald
cs48l32_in_rate_put(struct snd_kcontrol * kcontrol,struct snd_ctl_elem_value * ucontrol)704e2bcbf99SRichard Fitzgerald static int cs48l32_in_rate_put(struct snd_kcontrol *kcontrol,
705e2bcbf99SRichard Fitzgerald struct snd_ctl_elem_value *ucontrol)
706e2bcbf99SRichard Fitzgerald {
707e2bcbf99SRichard Fitzgerald struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol);
708e2bcbf99SRichard Fitzgerald struct snd_soc_dapm_context *dapm = snd_soc_component_get_dapm(component);
709e2bcbf99SRichard Fitzgerald struct soc_enum *e = (struct soc_enum *)kcontrol->private_value;
710e2bcbf99SRichard Fitzgerald int ret;
711e2bcbf99SRichard Fitzgerald
712e2bcbf99SRichard Fitzgerald snd_soc_dapm_mutex_lock(dapm);
713e2bcbf99SRichard Fitzgerald
714e2bcbf99SRichard Fitzgerald /* Cannot change rate on an active input */
715e2bcbf99SRichard Fitzgerald if (cs48l32_is_input_enabled(component, e->reg)) {
716e2bcbf99SRichard Fitzgerald ret = -EBUSY;
717e2bcbf99SRichard Fitzgerald goto exit;
718e2bcbf99SRichard Fitzgerald }
719e2bcbf99SRichard Fitzgerald
720e2bcbf99SRichard Fitzgerald ret = snd_soc_put_enum_double(kcontrol, ucontrol);
721e2bcbf99SRichard Fitzgerald exit:
722e2bcbf99SRichard Fitzgerald snd_soc_dapm_mutex_unlock(dapm);
723e2bcbf99SRichard Fitzgerald
724e2bcbf99SRichard Fitzgerald return ret;
725e2bcbf99SRichard Fitzgerald }
726e2bcbf99SRichard Fitzgerald
727e2bcbf99SRichard Fitzgerald static const struct soc_enum cs48l32_input_rate[] = {
728e2bcbf99SRichard Fitzgerald SOC_VALUE_ENUM_SINGLE(CS48L32_IN1L_CONTROL1,
729e2bcbf99SRichard Fitzgerald CS48L32_INx_RATE_SHIFT,
730e2bcbf99SRichard Fitzgerald CS48L32_INx_RATE_MASK >> CS48L32_INx_RATE_SHIFT,
731e2bcbf99SRichard Fitzgerald ARRAY_SIZE(cs48l32_rate_text),
732e2bcbf99SRichard Fitzgerald cs48l32_rate_text,
733e2bcbf99SRichard Fitzgerald cs48l32_rate_val),
734e2bcbf99SRichard Fitzgerald SOC_VALUE_ENUM_SINGLE(CS48L32_IN1R_CONTROL1,
735e2bcbf99SRichard Fitzgerald CS48L32_INx_RATE_SHIFT,
736e2bcbf99SRichard Fitzgerald CS48L32_INx_RATE_MASK >> CS48L32_INx_RATE_SHIFT,
737e2bcbf99SRichard Fitzgerald ARRAY_SIZE(cs48l32_rate_text),
738e2bcbf99SRichard Fitzgerald cs48l32_rate_text,
739e2bcbf99SRichard Fitzgerald cs48l32_rate_val),
740e2bcbf99SRichard Fitzgerald SOC_VALUE_ENUM_SINGLE(CS48L32_IN2L_CONTROL1,
741e2bcbf99SRichard Fitzgerald CS48L32_INx_RATE_SHIFT,
742e2bcbf99SRichard Fitzgerald CS48L32_INx_RATE_MASK >> CS48L32_INx_RATE_SHIFT,
743e2bcbf99SRichard Fitzgerald ARRAY_SIZE(cs48l32_rate_text),
744e2bcbf99SRichard Fitzgerald cs48l32_rate_text,
745e2bcbf99SRichard Fitzgerald cs48l32_rate_val),
746e2bcbf99SRichard Fitzgerald SOC_VALUE_ENUM_SINGLE(CS48L32_IN2R_CONTROL1,
747e2bcbf99SRichard Fitzgerald CS48L32_INx_RATE_SHIFT,
748e2bcbf99SRichard Fitzgerald CS48L32_INx_RATE_MASK >> CS48L32_INx_RATE_SHIFT,
749e2bcbf99SRichard Fitzgerald ARRAY_SIZE(cs48l32_rate_text),
750e2bcbf99SRichard Fitzgerald cs48l32_rate_text,
751e2bcbf99SRichard Fitzgerald cs48l32_rate_val),
752e2bcbf99SRichard Fitzgerald };
753e2bcbf99SRichard Fitzgerald
cs48l32_low_power_mode_put(struct snd_kcontrol * kcontrol,struct snd_ctl_elem_value * ucontrol)754e2bcbf99SRichard Fitzgerald static int cs48l32_low_power_mode_put(struct snd_kcontrol *kcontrol,
755e2bcbf99SRichard Fitzgerald struct snd_ctl_elem_value *ucontrol)
756e2bcbf99SRichard Fitzgerald {
757e2bcbf99SRichard Fitzgerald struct soc_mixer_control *mc = (struct soc_mixer_control *)kcontrol->private_value;
758e2bcbf99SRichard Fitzgerald struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol);
759e2bcbf99SRichard Fitzgerald struct snd_soc_dapm_context *dapm = snd_soc_component_get_dapm(component);
760e2bcbf99SRichard Fitzgerald int ret;
761e2bcbf99SRichard Fitzgerald
762e2bcbf99SRichard Fitzgerald snd_soc_dapm_mutex_lock(dapm);
763e2bcbf99SRichard Fitzgerald
764e2bcbf99SRichard Fitzgerald /* Cannot change rate on an active input */
765e2bcbf99SRichard Fitzgerald if (cs48l32_is_input_enabled(component, mc->reg)) {
766e2bcbf99SRichard Fitzgerald ret = -EBUSY;
767e2bcbf99SRichard Fitzgerald goto exit;
768e2bcbf99SRichard Fitzgerald }
769e2bcbf99SRichard Fitzgerald
770e2bcbf99SRichard Fitzgerald ret = snd_soc_put_volsw(kcontrol, ucontrol);
771e2bcbf99SRichard Fitzgerald
772e2bcbf99SRichard Fitzgerald exit:
773e2bcbf99SRichard Fitzgerald snd_soc_dapm_mutex_unlock(dapm);
774e2bcbf99SRichard Fitzgerald return ret;
775e2bcbf99SRichard Fitzgerald }
776e2bcbf99SRichard Fitzgerald
777e2bcbf99SRichard Fitzgerald static const struct soc_enum noise_gen_rate =
778e2bcbf99SRichard Fitzgerald SOC_VALUE_ENUM_SINGLE(CS48L32_COMFORT_NOISE_GENERATOR,
779e2bcbf99SRichard Fitzgerald CS48L32_NOISE_GEN_RATE_SHIFT,
780e2bcbf99SRichard Fitzgerald CS48L32_NOISE_GEN_RATE_MASK >> CS48L32_NOISE_GEN_RATE_SHIFT,
781e2bcbf99SRichard Fitzgerald ARRAY_SIZE(cs48l32_rate_text),
782e2bcbf99SRichard Fitzgerald cs48l32_rate_text,
783e2bcbf99SRichard Fitzgerald cs48l32_rate_val);
784e2bcbf99SRichard Fitzgerald
785e2bcbf99SRichard Fitzgerald static const char * const cs48l32_auxpdm_freq_texts[] = {
786e2bcbf99SRichard Fitzgerald "3.072MHz", "2.048MHz", "1.536MHz", "768kHz",
787e2bcbf99SRichard Fitzgerald };
788e2bcbf99SRichard Fitzgerald
789e2bcbf99SRichard Fitzgerald static SOC_ENUM_SINGLE_DECL(cs48l32_auxpdm1_freq,
790e2bcbf99SRichard Fitzgerald CS48L32_AUXPDM1_CONTROL1,
791e2bcbf99SRichard Fitzgerald CS48L32_AUXPDM1_FREQ_SHIFT,
792e2bcbf99SRichard Fitzgerald cs48l32_auxpdm_freq_texts);
793e2bcbf99SRichard Fitzgerald
794e2bcbf99SRichard Fitzgerald static SOC_ENUM_SINGLE_DECL(cs48l32_auxpdm2_freq,
795e2bcbf99SRichard Fitzgerald CS48L32_AUXPDM2_CONTROL1,
796e2bcbf99SRichard Fitzgerald CS48L32_AUXPDM1_FREQ_SHIFT,
797e2bcbf99SRichard Fitzgerald cs48l32_auxpdm_freq_texts);
798e2bcbf99SRichard Fitzgerald
799e2bcbf99SRichard Fitzgerald static const char * const cs48l32_auxpdm_src_texts[] = {
800e2bcbf99SRichard Fitzgerald "Analog", "IN1 Digital", "IN2 Digital",
801e2bcbf99SRichard Fitzgerald };
802e2bcbf99SRichard Fitzgerald
803e2bcbf99SRichard Fitzgerald static SOC_ENUM_SINGLE_DECL(cs48l32_auxpdm1_in,
804e2bcbf99SRichard Fitzgerald CS48L32_AUXPDM_CTRL2,
805e2bcbf99SRichard Fitzgerald CS48L32_AUXPDMDAT1_SRC_SHIFT,
806e2bcbf99SRichard Fitzgerald cs48l32_auxpdm_src_texts);
807e2bcbf99SRichard Fitzgerald
808e2bcbf99SRichard Fitzgerald static SOC_ENUM_SINGLE_DECL(cs48l32_auxpdm2_in,
809e2bcbf99SRichard Fitzgerald CS48L32_AUXPDM_CTRL2,
810e2bcbf99SRichard Fitzgerald CS48L32_AUXPDMDAT2_SRC_SHIFT,
811e2bcbf99SRichard Fitzgerald cs48l32_auxpdm_src_texts);
812e2bcbf99SRichard Fitzgerald
813e2bcbf99SRichard Fitzgerald static const struct snd_kcontrol_new cs48l32_auxpdm_inmux[] = {
814e2bcbf99SRichard Fitzgerald SOC_DAPM_ENUM("AUXPDM1 Input", cs48l32_auxpdm1_in),
815e2bcbf99SRichard Fitzgerald SOC_DAPM_ENUM("AUXPDM2 Input", cs48l32_auxpdm2_in),
816e2bcbf99SRichard Fitzgerald };
817e2bcbf99SRichard Fitzgerald
818e2bcbf99SRichard Fitzgerald static const unsigned int cs48l32_auxpdm_analog_in_val[] = {
819e2bcbf99SRichard Fitzgerald 0x0, 0x1,
820e2bcbf99SRichard Fitzgerald };
821e2bcbf99SRichard Fitzgerald
822e2bcbf99SRichard Fitzgerald static const struct soc_enum cs48l32_auxpdm_analog_inmux_enum[] = {
823e2bcbf99SRichard Fitzgerald SOC_VALUE_ENUM_SINGLE(CS48L32_AUXPDM1_CONTROL1,
824e2bcbf99SRichard Fitzgerald CS48L32_AUXPDM1_SRC_SHIFT,
825e2bcbf99SRichard Fitzgerald CS48L32_AUXPDM1_SRC_MASK >> CS48L32_AUXPDM1_SRC_SHIFT,
826e2bcbf99SRichard Fitzgerald ARRAY_SIZE(cs48l32_auxpdm_analog_in_val),
827e2bcbf99SRichard Fitzgerald cs48l32_in_texts,
828e2bcbf99SRichard Fitzgerald cs48l32_auxpdm_analog_in_val),
829e2bcbf99SRichard Fitzgerald SOC_VALUE_ENUM_SINGLE(CS48L32_AUXPDM2_CONTROL1,
830e2bcbf99SRichard Fitzgerald CS48L32_AUXPDM1_SRC_SHIFT,
831e2bcbf99SRichard Fitzgerald CS48L32_AUXPDM1_SRC_MASK >> CS48L32_AUXPDM1_SRC_SHIFT,
832e2bcbf99SRichard Fitzgerald ARRAY_SIZE(cs48l32_auxpdm_analog_in_val),
833e2bcbf99SRichard Fitzgerald cs48l32_in_texts,
834e2bcbf99SRichard Fitzgerald cs48l32_auxpdm_analog_in_val),
835e2bcbf99SRichard Fitzgerald };
836e2bcbf99SRichard Fitzgerald
837e2bcbf99SRichard Fitzgerald static const struct snd_kcontrol_new cs48l32_auxpdm_analog_inmux[] = {
838e2bcbf99SRichard Fitzgerald SOC_DAPM_ENUM("AUXPDM1 Analog Input", cs48l32_auxpdm_analog_inmux_enum[0]),
839e2bcbf99SRichard Fitzgerald SOC_DAPM_ENUM("AUXPDM2 Analog Input", cs48l32_auxpdm_analog_inmux_enum[1]),
840e2bcbf99SRichard Fitzgerald };
841e2bcbf99SRichard Fitzgerald
842e2bcbf99SRichard Fitzgerald static const struct snd_kcontrol_new cs48l32_auxpdm_switch[] = {
843e2bcbf99SRichard Fitzgerald SOC_DAPM_SINGLE("Switch", SND_SOC_NOPM, 0, 1, 0),
844e2bcbf99SRichard Fitzgerald SOC_DAPM_SINGLE("Switch", SND_SOC_NOPM, 0, 1, 0),
845e2bcbf99SRichard Fitzgerald };
846e2bcbf99SRichard Fitzgerald
847e2bcbf99SRichard Fitzgerald static const struct soc_enum cs48l32_isrc_fsh[] = {
848e2bcbf99SRichard Fitzgerald SOC_VALUE_ENUM_SINGLE(CS48L32_ISRC1_CONTROL1,
849e2bcbf99SRichard Fitzgerald CS48L32_ISRC1_FSH_SHIFT,
850e2bcbf99SRichard Fitzgerald CS48L32_ISRC1_FSH_MASK >> CS48L32_ISRC1_FSH_SHIFT,
851e2bcbf99SRichard Fitzgerald ARRAY_SIZE(cs48l32_rate_text),
852e2bcbf99SRichard Fitzgerald cs48l32_rate_text,
853e2bcbf99SRichard Fitzgerald cs48l32_rate_val),
854e2bcbf99SRichard Fitzgerald SOC_VALUE_ENUM_SINGLE(CS48L32_ISRC2_CONTROL1,
855e2bcbf99SRichard Fitzgerald CS48L32_ISRC1_FSH_SHIFT,
856e2bcbf99SRichard Fitzgerald CS48L32_ISRC1_FSH_MASK >> CS48L32_ISRC1_FSH_SHIFT,
857e2bcbf99SRichard Fitzgerald ARRAY_SIZE(cs48l32_rate_text),
858e2bcbf99SRichard Fitzgerald cs48l32_rate_text,
859e2bcbf99SRichard Fitzgerald cs48l32_rate_val),
860e2bcbf99SRichard Fitzgerald SOC_VALUE_ENUM_SINGLE(CS48L32_ISRC3_CONTROL1,
861e2bcbf99SRichard Fitzgerald CS48L32_ISRC1_FSH_SHIFT,
862e2bcbf99SRichard Fitzgerald CS48L32_ISRC1_FSH_MASK >> CS48L32_ISRC1_FSH_SHIFT,
863e2bcbf99SRichard Fitzgerald ARRAY_SIZE(cs48l32_rate_text),
864e2bcbf99SRichard Fitzgerald cs48l32_rate_text,
865e2bcbf99SRichard Fitzgerald cs48l32_rate_val),
866e2bcbf99SRichard Fitzgerald };
867e2bcbf99SRichard Fitzgerald
868e2bcbf99SRichard Fitzgerald static const struct soc_enum cs48l32_isrc_fsl[] = {
869e2bcbf99SRichard Fitzgerald SOC_VALUE_ENUM_SINGLE(CS48L32_ISRC1_CONTROL1,
870e2bcbf99SRichard Fitzgerald CS48L32_ISRC1_FSL_SHIFT,
871e2bcbf99SRichard Fitzgerald CS48L32_ISRC1_FSL_MASK >> CS48L32_ISRC1_FSL_SHIFT,
872e2bcbf99SRichard Fitzgerald ARRAY_SIZE(cs48l32_rate_text),
873e2bcbf99SRichard Fitzgerald cs48l32_rate_text,
874e2bcbf99SRichard Fitzgerald cs48l32_rate_val),
875e2bcbf99SRichard Fitzgerald SOC_VALUE_ENUM_SINGLE(CS48L32_ISRC2_CONTROL1,
876e2bcbf99SRichard Fitzgerald CS48L32_ISRC1_FSL_SHIFT,
877e2bcbf99SRichard Fitzgerald CS48L32_ISRC1_FSL_MASK >> CS48L32_ISRC1_FSL_SHIFT,
878e2bcbf99SRichard Fitzgerald ARRAY_SIZE(cs48l32_rate_text),
879e2bcbf99SRichard Fitzgerald cs48l32_rate_text,
880e2bcbf99SRichard Fitzgerald cs48l32_rate_val),
881e2bcbf99SRichard Fitzgerald SOC_VALUE_ENUM_SINGLE(CS48L32_ISRC3_CONTROL1,
882e2bcbf99SRichard Fitzgerald CS48L32_ISRC1_FSL_SHIFT,
883e2bcbf99SRichard Fitzgerald CS48L32_ISRC1_FSL_MASK >> CS48L32_ISRC1_FSL_SHIFT,
884e2bcbf99SRichard Fitzgerald ARRAY_SIZE(cs48l32_rate_text),
885e2bcbf99SRichard Fitzgerald cs48l32_rate_text,
886e2bcbf99SRichard Fitzgerald cs48l32_rate_val),
887e2bcbf99SRichard Fitzgerald };
888e2bcbf99SRichard Fitzgerald
889e2bcbf99SRichard Fitzgerald static const struct soc_enum cs48l32_fx_rate =
890e2bcbf99SRichard Fitzgerald SOC_VALUE_ENUM_SINGLE(CS48L32_FX_SAMPLE_RATE,
891e2bcbf99SRichard Fitzgerald CS48L32_FX_RATE_SHIFT,
892e2bcbf99SRichard Fitzgerald CS48L32_FX_RATE_MASK >> CS48L32_FX_RATE_SHIFT,
893e2bcbf99SRichard Fitzgerald ARRAY_SIZE(cs48l32_rate_text),
894e2bcbf99SRichard Fitzgerald cs48l32_rate_text,
895e2bcbf99SRichard Fitzgerald cs48l32_rate_val);
896e2bcbf99SRichard Fitzgerald
897e2bcbf99SRichard Fitzgerald static const char * const cs48l32_lhpf_mode_text[] = {
898e2bcbf99SRichard Fitzgerald "Low-pass", "High-pass"
899e2bcbf99SRichard Fitzgerald };
900e2bcbf99SRichard Fitzgerald
901e2bcbf99SRichard Fitzgerald static const struct soc_enum cs48l32_lhpf_mode[] = {
902e2bcbf99SRichard Fitzgerald SOC_ENUM_SINGLE(CS48L32_LHPF_CONTROL2, 0,
903e2bcbf99SRichard Fitzgerald ARRAY_SIZE(cs48l32_lhpf_mode_text), cs48l32_lhpf_mode_text),
904e2bcbf99SRichard Fitzgerald SOC_ENUM_SINGLE(CS48L32_LHPF_CONTROL2, 1,
905e2bcbf99SRichard Fitzgerald ARRAY_SIZE(cs48l32_lhpf_mode_text), cs48l32_lhpf_mode_text),
906e2bcbf99SRichard Fitzgerald SOC_ENUM_SINGLE(CS48L32_LHPF_CONTROL2, 2,
907e2bcbf99SRichard Fitzgerald ARRAY_SIZE(cs48l32_lhpf_mode_text), cs48l32_lhpf_mode_text),
908e2bcbf99SRichard Fitzgerald SOC_ENUM_SINGLE(CS48L32_LHPF_CONTROL2, 3,
909e2bcbf99SRichard Fitzgerald ARRAY_SIZE(cs48l32_lhpf_mode_text), cs48l32_lhpf_mode_text),
910e2bcbf99SRichard Fitzgerald };
911e2bcbf99SRichard Fitzgerald
cs48l32_lhpf_coeff_put(struct snd_kcontrol * kcontrol,struct snd_ctl_elem_value * ucontrol)912e2bcbf99SRichard Fitzgerald static int cs48l32_lhpf_coeff_put(struct snd_kcontrol *kcontrol,
913e2bcbf99SRichard Fitzgerald struct snd_ctl_elem_value *ucontrol)
914e2bcbf99SRichard Fitzgerald {
915e2bcbf99SRichard Fitzgerald struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol);
916e2bcbf99SRichard Fitzgerald struct cs48l32_codec *cs48l32_codec = snd_soc_component_get_drvdata(component);
917e2bcbf99SRichard Fitzgerald __be32 *data = (__be32 *)ucontrol->value.bytes.data;
918e2bcbf99SRichard Fitzgerald s16 val = (s16)be32_to_cpu(*data);
919e2bcbf99SRichard Fitzgerald
920e2bcbf99SRichard Fitzgerald if (abs(val) > CS48L32_LHPF_MAX_COEFF) {
921e2bcbf99SRichard Fitzgerald dev_err(cs48l32_codec->core.dev, "Rejecting unstable LHPF coefficients\n");
922e2bcbf99SRichard Fitzgerald return -EINVAL;
923e2bcbf99SRichard Fitzgerald }
924e2bcbf99SRichard Fitzgerald
925e2bcbf99SRichard Fitzgerald return snd_soc_bytes_put(kcontrol, ucontrol);
926e2bcbf99SRichard Fitzgerald }
927e2bcbf99SRichard Fitzgerald
928e2bcbf99SRichard Fitzgerald static const char * const cs48l32_eq_mode_text[] = {
929e2bcbf99SRichard Fitzgerald "Low-pass", "High-pass",
930e2bcbf99SRichard Fitzgerald };
931e2bcbf99SRichard Fitzgerald
932e2bcbf99SRichard Fitzgerald static const struct soc_enum cs48l32_eq_mode[] = {
933e2bcbf99SRichard Fitzgerald SOC_ENUM_SINGLE(CS48L32_EQ_CONTROL2, 0,
934e2bcbf99SRichard Fitzgerald ARRAY_SIZE(cs48l32_eq_mode_text),
935e2bcbf99SRichard Fitzgerald cs48l32_eq_mode_text),
936e2bcbf99SRichard Fitzgerald SOC_ENUM_SINGLE(CS48L32_EQ_CONTROL2, 1,
937e2bcbf99SRichard Fitzgerald ARRAY_SIZE(cs48l32_eq_mode_text),
938e2bcbf99SRichard Fitzgerald cs48l32_eq_mode_text),
939e2bcbf99SRichard Fitzgerald SOC_ENUM_SINGLE(CS48L32_EQ_CONTROL2, 2,
940e2bcbf99SRichard Fitzgerald ARRAY_SIZE(cs48l32_eq_mode_text),
941e2bcbf99SRichard Fitzgerald cs48l32_eq_mode_text),
942e2bcbf99SRichard Fitzgerald SOC_ENUM_SINGLE(CS48L32_EQ_CONTROL2, 3,
943e2bcbf99SRichard Fitzgerald ARRAY_SIZE(cs48l32_eq_mode_text),
944e2bcbf99SRichard Fitzgerald cs48l32_eq_mode_text),
945e2bcbf99SRichard Fitzgerald };
946e2bcbf99SRichard Fitzgerald
cs48l32_eq_mode_get(struct snd_kcontrol * kcontrol,struct snd_ctl_elem_value * ucontrol)947e2bcbf99SRichard Fitzgerald static int cs48l32_eq_mode_get(struct snd_kcontrol *kcontrol,
948e2bcbf99SRichard Fitzgerald struct snd_ctl_elem_value *ucontrol)
949e2bcbf99SRichard Fitzgerald {
950e2bcbf99SRichard Fitzgerald struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol);
951e2bcbf99SRichard Fitzgerald struct cs48l32_codec *cs48l32_codec = snd_soc_component_get_drvdata(component);
952e2bcbf99SRichard Fitzgerald struct soc_enum *e = (struct soc_enum *) kcontrol->private_value;
953e2bcbf99SRichard Fitzgerald unsigned int item;
954e2bcbf99SRichard Fitzgerald
955e2bcbf99SRichard Fitzgerald item = snd_soc_enum_val_to_item(e, cs48l32_codec->eq_mode[e->shift_l]);
956e2bcbf99SRichard Fitzgerald ucontrol->value.enumerated.item[0] = item;
957e2bcbf99SRichard Fitzgerald
958e2bcbf99SRichard Fitzgerald return 0;
959e2bcbf99SRichard Fitzgerald }
960e2bcbf99SRichard Fitzgerald
cs48l32_eq_mode_put(struct snd_kcontrol * kcontrol,struct snd_ctl_elem_value * ucontrol)961e2bcbf99SRichard Fitzgerald static int cs48l32_eq_mode_put(struct snd_kcontrol *kcontrol,
962e2bcbf99SRichard Fitzgerald struct snd_ctl_elem_value *ucontrol)
963e2bcbf99SRichard Fitzgerald {
964e2bcbf99SRichard Fitzgerald struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol);
965e2bcbf99SRichard Fitzgerald struct snd_soc_dapm_context *dapm = snd_soc_component_get_dapm(component);
966e2bcbf99SRichard Fitzgerald struct cs48l32_codec *cs48l32_codec = snd_soc_component_get_drvdata(component);
967e2bcbf99SRichard Fitzgerald struct soc_enum *e = (struct soc_enum *) kcontrol->private_value;
968e2bcbf99SRichard Fitzgerald unsigned int *item = ucontrol->value.enumerated.item;
969e2bcbf99SRichard Fitzgerald unsigned int val;
970e2bcbf99SRichard Fitzgerald bool changed = false;
971e2bcbf99SRichard Fitzgerald
972e2bcbf99SRichard Fitzgerald if (item[0] >= e->items)
973e2bcbf99SRichard Fitzgerald return -EINVAL;
974e2bcbf99SRichard Fitzgerald
975e2bcbf99SRichard Fitzgerald val = snd_soc_enum_item_to_val(e, item[0]);
976e2bcbf99SRichard Fitzgerald
977e2bcbf99SRichard Fitzgerald snd_soc_dapm_mutex_lock(dapm);
978e2bcbf99SRichard Fitzgerald if (cs48l32_codec->eq_mode[e->shift_l] != val) {
979e2bcbf99SRichard Fitzgerald cs48l32_codec->eq_mode[e->shift_l] = val;
980e2bcbf99SRichard Fitzgerald changed = true;
981e2bcbf99SRichard Fitzgerald }
982e2bcbf99SRichard Fitzgerald snd_soc_dapm_mutex_unlock(dapm);
983e2bcbf99SRichard Fitzgerald
984e2bcbf99SRichard Fitzgerald return changed;
985e2bcbf99SRichard Fitzgerald }
986e2bcbf99SRichard Fitzgerald
cs48l32_eq_coeff_info(struct snd_kcontrol * kcontrol,struct snd_ctl_elem_info * uinfo)987e2bcbf99SRichard Fitzgerald static int cs48l32_eq_coeff_info(struct snd_kcontrol *kcontrol,
988e2bcbf99SRichard Fitzgerald struct snd_ctl_elem_info *uinfo)
989e2bcbf99SRichard Fitzgerald {
990e2bcbf99SRichard Fitzgerald struct cs48l32_eq_control *ctl = (void *) kcontrol->private_value;
991e2bcbf99SRichard Fitzgerald
992e2bcbf99SRichard Fitzgerald uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
993e2bcbf99SRichard Fitzgerald uinfo->count = 1;
994e2bcbf99SRichard Fitzgerald uinfo->value.integer.min = 0;
995e2bcbf99SRichard Fitzgerald uinfo->value.integer.max = ctl->max;
996e2bcbf99SRichard Fitzgerald
997e2bcbf99SRichard Fitzgerald return 0;
998e2bcbf99SRichard Fitzgerald }
999e2bcbf99SRichard Fitzgerald
cs48l32_eq_coeff_get(struct snd_kcontrol * kcontrol,struct snd_ctl_elem_value * ucontrol)1000e2bcbf99SRichard Fitzgerald static int cs48l32_eq_coeff_get(struct snd_kcontrol *kcontrol,
1001e2bcbf99SRichard Fitzgerald struct snd_ctl_elem_value *ucontrol)
1002e2bcbf99SRichard Fitzgerald {
1003e2bcbf99SRichard Fitzgerald struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol);
1004e2bcbf99SRichard Fitzgerald struct cs48l32_codec *cs48l32_codec = snd_soc_component_get_drvdata(component);
1005e2bcbf99SRichard Fitzgerald struct cs48l32_eq_control *params = (void *)kcontrol->private_value;
1006e2bcbf99SRichard Fitzgerald __be16 *coeffs;
1007e2bcbf99SRichard Fitzgerald unsigned int coeff_idx;
1008e2bcbf99SRichard Fitzgerald int block_idx;
1009e2bcbf99SRichard Fitzgerald
1010e2bcbf99SRichard Fitzgerald block_idx = ((int) params->block_base - (int) CS48L32_EQ1_BAND1_COEFF1);
1011e2bcbf99SRichard Fitzgerald block_idx /= (CS48L32_EQ2_BAND1_COEFF1 - CS48L32_EQ1_BAND1_COEFF1);
1012e2bcbf99SRichard Fitzgerald
1013e2bcbf99SRichard Fitzgerald coeffs = &cs48l32_codec->eq_coefficients[block_idx][0];
1014e2bcbf99SRichard Fitzgerald coeff_idx = (params->reg - params->block_base) / 2;
1015e2bcbf99SRichard Fitzgerald
1016e2bcbf99SRichard Fitzgerald /* High __be16 is in [coeff_idx] and low __be16 in [coeff_idx + 1] */
1017e2bcbf99SRichard Fitzgerald if (params->shift == 0)
1018e2bcbf99SRichard Fitzgerald coeff_idx++;
1019e2bcbf99SRichard Fitzgerald
1020e2bcbf99SRichard Fitzgerald ucontrol->value.integer.value[0] = be16_to_cpu(coeffs[coeff_idx]);
1021e2bcbf99SRichard Fitzgerald
1022e2bcbf99SRichard Fitzgerald return 0;
1023e2bcbf99SRichard Fitzgerald }
1024e2bcbf99SRichard Fitzgerald
cs48l32_eq_coeff_put(struct snd_kcontrol * kcontrol,struct snd_ctl_elem_value * ucontrol)1025e2bcbf99SRichard Fitzgerald static int cs48l32_eq_coeff_put(struct snd_kcontrol *kcontrol,
1026e2bcbf99SRichard Fitzgerald struct snd_ctl_elem_value *ucontrol)
1027e2bcbf99SRichard Fitzgerald {
1028e2bcbf99SRichard Fitzgerald struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol);
1029e2bcbf99SRichard Fitzgerald struct snd_soc_dapm_context *dapm = snd_soc_component_get_dapm(component);
1030e2bcbf99SRichard Fitzgerald struct cs48l32_codec *cs48l32_codec = snd_soc_component_get_drvdata(component);
1031e2bcbf99SRichard Fitzgerald struct cs48l32_eq_control *params = (void *)kcontrol->private_value;
1032e2bcbf99SRichard Fitzgerald __be16 *coeffs;
1033e2bcbf99SRichard Fitzgerald unsigned int coeff_idx;
1034e2bcbf99SRichard Fitzgerald int block_idx;
1035e2bcbf99SRichard Fitzgerald
1036e2bcbf99SRichard Fitzgerald block_idx = ((int) params->block_base - (int) CS48L32_EQ1_BAND1_COEFF1);
1037e2bcbf99SRichard Fitzgerald block_idx /= (CS48L32_EQ2_BAND1_COEFF1 - CS48L32_EQ1_BAND1_COEFF1);
1038e2bcbf99SRichard Fitzgerald
1039e2bcbf99SRichard Fitzgerald coeffs = &cs48l32_codec->eq_coefficients[block_idx][0];
1040e2bcbf99SRichard Fitzgerald coeff_idx = (params->reg - params->block_base) / 2;
1041e2bcbf99SRichard Fitzgerald
1042e2bcbf99SRichard Fitzgerald /* Put high __be16 in [coeff_idx] and low __be16 in [coeff_idx + 1] */
1043e2bcbf99SRichard Fitzgerald if (params->shift == 0)
1044e2bcbf99SRichard Fitzgerald coeff_idx++;
1045e2bcbf99SRichard Fitzgerald
1046e2bcbf99SRichard Fitzgerald snd_soc_dapm_mutex_lock(dapm);
1047e2bcbf99SRichard Fitzgerald coeffs[coeff_idx] = cpu_to_be16(ucontrol->value.integer.value[0]);
1048e2bcbf99SRichard Fitzgerald snd_soc_dapm_mutex_unlock(dapm);
1049e2bcbf99SRichard Fitzgerald
1050e2bcbf99SRichard Fitzgerald return 0;
1051e2bcbf99SRichard Fitzgerald }
1052e2bcbf99SRichard Fitzgerald
1053e2bcbf99SRichard Fitzgerald static const struct snd_kcontrol_new cs48l32_drc_activity_output_mux[] = {
1054e2bcbf99SRichard Fitzgerald SOC_DAPM_SINGLE("Switch", SND_SOC_NOPM, 0, 1, 0),
1055e2bcbf99SRichard Fitzgerald SOC_DAPM_SINGLE("Switch", SND_SOC_NOPM, 0, 1, 0),
1056e2bcbf99SRichard Fitzgerald };
1057e2bcbf99SRichard Fitzgerald
1058e2bcbf99SRichard Fitzgerald static const struct snd_kcontrol_new cs48l32_dsp_trigger_output_mux[] = {
1059e2bcbf99SRichard Fitzgerald SOC_DAPM_SINGLE("Switch", SND_SOC_NOPM, 0, 1, 0),
1060e2bcbf99SRichard Fitzgerald };
1061e2bcbf99SRichard Fitzgerald
cs48l32_dsp_rate_get(struct snd_kcontrol * kcontrol,struct snd_ctl_elem_value * ucontrol)1062e2bcbf99SRichard Fitzgerald static int cs48l32_dsp_rate_get(struct snd_kcontrol *kcontrol,
1063e2bcbf99SRichard Fitzgerald struct snd_ctl_elem_value *ucontrol)
1064e2bcbf99SRichard Fitzgerald {
1065e2bcbf99SRichard Fitzgerald struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol);
1066e2bcbf99SRichard Fitzgerald struct cs48l32_codec *cs48l32_codec = snd_soc_component_get_drvdata(component);
1067e2bcbf99SRichard Fitzgerald struct soc_enum *e = (struct soc_enum *) kcontrol->private_value;
1068e2bcbf99SRichard Fitzgerald unsigned int cached_rate;
1069e2bcbf99SRichard Fitzgerald const unsigned int rate_num = e->mask;
1070e2bcbf99SRichard Fitzgerald int item;
1071e2bcbf99SRichard Fitzgerald
1072e2bcbf99SRichard Fitzgerald if (rate_num >= ARRAY_SIZE(cs48l32_codec->dsp_dma_rates))
1073e2bcbf99SRichard Fitzgerald return -EINVAL;
1074e2bcbf99SRichard Fitzgerald
1075e2bcbf99SRichard Fitzgerald cached_rate = cs48l32_codec->dsp_dma_rates[rate_num];
1076e2bcbf99SRichard Fitzgerald item = snd_soc_enum_val_to_item(e, cached_rate);
1077e2bcbf99SRichard Fitzgerald ucontrol->value.enumerated.item[0] = item;
1078e2bcbf99SRichard Fitzgerald
1079e2bcbf99SRichard Fitzgerald return 0;
1080e2bcbf99SRichard Fitzgerald }
1081e2bcbf99SRichard Fitzgerald
cs48l32_dsp_rate_put(struct snd_kcontrol * kcontrol,struct snd_ctl_elem_value * ucontrol)1082e2bcbf99SRichard Fitzgerald static int cs48l32_dsp_rate_put(struct snd_kcontrol *kcontrol,
1083e2bcbf99SRichard Fitzgerald struct snd_ctl_elem_value *ucontrol)
1084e2bcbf99SRichard Fitzgerald {
1085e2bcbf99SRichard Fitzgerald struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol);
1086e2bcbf99SRichard Fitzgerald struct snd_soc_dapm_context *dapm = snd_soc_component_get_dapm(component);
1087e2bcbf99SRichard Fitzgerald struct cs48l32_codec *cs48l32_codec = snd_soc_component_get_drvdata(component);
1088e2bcbf99SRichard Fitzgerald struct soc_enum *e = (struct soc_enum *) kcontrol->private_value;
1089e2bcbf99SRichard Fitzgerald const unsigned int rate_num = e->mask;
1090e2bcbf99SRichard Fitzgerald const unsigned int item = ucontrol->value.enumerated.item[0];
1091e2bcbf99SRichard Fitzgerald unsigned int val;
1092e2bcbf99SRichard Fitzgerald bool changed = false;
1093e2bcbf99SRichard Fitzgerald
1094e2bcbf99SRichard Fitzgerald if (item >= e->items)
1095e2bcbf99SRichard Fitzgerald return -EINVAL;
1096e2bcbf99SRichard Fitzgerald
1097e2bcbf99SRichard Fitzgerald if (rate_num >= ARRAY_SIZE(cs48l32_codec->dsp_dma_rates))
1098e2bcbf99SRichard Fitzgerald return -EINVAL;
1099e2bcbf99SRichard Fitzgerald
1100e2bcbf99SRichard Fitzgerald val = snd_soc_enum_item_to_val(e, item);
1101e2bcbf99SRichard Fitzgerald
1102e2bcbf99SRichard Fitzgerald snd_soc_dapm_mutex_lock(dapm);
1103e2bcbf99SRichard Fitzgerald if (cs48l32_codec->dsp_dma_rates[rate_num] != val) {
1104e2bcbf99SRichard Fitzgerald cs48l32_codec->dsp_dma_rates[rate_num] = val;
1105e2bcbf99SRichard Fitzgerald changed = true;
1106e2bcbf99SRichard Fitzgerald }
1107e2bcbf99SRichard Fitzgerald snd_soc_dapm_mutex_unlock(dapm);
1108e2bcbf99SRichard Fitzgerald
1109e2bcbf99SRichard Fitzgerald return changed;
1110e2bcbf99SRichard Fitzgerald }
1111e2bcbf99SRichard Fitzgerald
1112e2bcbf99SRichard Fitzgerald static const struct soc_enum cs48l32_dsp_rate_enum[] = {
1113e2bcbf99SRichard Fitzgerald /* RX rates */
1114e2bcbf99SRichard Fitzgerald SOC_VALUE_ENUM_SINGLE(SND_SOC_NOPM, 0,
1115e2bcbf99SRichard Fitzgerald 0,
1116e2bcbf99SRichard Fitzgerald ARRAY_SIZE(cs48l32_rate_text),
1117e2bcbf99SRichard Fitzgerald cs48l32_rate_text, cs48l32_rate_val),
1118e2bcbf99SRichard Fitzgerald SOC_VALUE_ENUM_SINGLE(SND_SOC_NOPM, 0,
1119e2bcbf99SRichard Fitzgerald 1,
1120e2bcbf99SRichard Fitzgerald ARRAY_SIZE(cs48l32_rate_text),
1121e2bcbf99SRichard Fitzgerald cs48l32_rate_text, cs48l32_rate_val),
1122e2bcbf99SRichard Fitzgerald SOC_VALUE_ENUM_SINGLE(SND_SOC_NOPM, 0,
1123e2bcbf99SRichard Fitzgerald 2,
1124e2bcbf99SRichard Fitzgerald ARRAY_SIZE(cs48l32_rate_text),
1125e2bcbf99SRichard Fitzgerald cs48l32_rate_text, cs48l32_rate_val),
1126e2bcbf99SRichard Fitzgerald SOC_VALUE_ENUM_SINGLE(SND_SOC_NOPM, 0,
1127e2bcbf99SRichard Fitzgerald 3,
1128e2bcbf99SRichard Fitzgerald ARRAY_SIZE(cs48l32_rate_text),
1129e2bcbf99SRichard Fitzgerald cs48l32_rate_text, cs48l32_rate_val),
1130e2bcbf99SRichard Fitzgerald SOC_VALUE_ENUM_SINGLE(SND_SOC_NOPM, 0,
1131e2bcbf99SRichard Fitzgerald 4,
1132e2bcbf99SRichard Fitzgerald ARRAY_SIZE(cs48l32_rate_text),
1133e2bcbf99SRichard Fitzgerald cs48l32_rate_text, cs48l32_rate_val),
1134e2bcbf99SRichard Fitzgerald SOC_VALUE_ENUM_SINGLE(SND_SOC_NOPM, 0,
1135e2bcbf99SRichard Fitzgerald 5,
1136e2bcbf99SRichard Fitzgerald ARRAY_SIZE(cs48l32_rate_text),
1137e2bcbf99SRichard Fitzgerald cs48l32_rate_text, cs48l32_rate_val),
1138e2bcbf99SRichard Fitzgerald SOC_VALUE_ENUM_SINGLE(SND_SOC_NOPM, 0,
1139e2bcbf99SRichard Fitzgerald 6,
1140e2bcbf99SRichard Fitzgerald ARRAY_SIZE(cs48l32_rate_text),
1141e2bcbf99SRichard Fitzgerald cs48l32_rate_text, cs48l32_rate_val),
1142e2bcbf99SRichard Fitzgerald SOC_VALUE_ENUM_SINGLE(SND_SOC_NOPM, 0,
1143e2bcbf99SRichard Fitzgerald 7,
1144e2bcbf99SRichard Fitzgerald ARRAY_SIZE(cs48l32_rate_text),
1145e2bcbf99SRichard Fitzgerald cs48l32_rate_text, cs48l32_rate_val),
1146e2bcbf99SRichard Fitzgerald /* TX rates */
1147e2bcbf99SRichard Fitzgerald SOC_VALUE_ENUM_SINGLE(SND_SOC_NOPM, 0,
1148e2bcbf99SRichard Fitzgerald 8,
1149e2bcbf99SRichard Fitzgerald ARRAY_SIZE(cs48l32_rate_text),
1150e2bcbf99SRichard Fitzgerald cs48l32_rate_text, cs48l32_rate_val),
1151e2bcbf99SRichard Fitzgerald SOC_VALUE_ENUM_SINGLE(SND_SOC_NOPM, 0,
1152e2bcbf99SRichard Fitzgerald 9,
1153e2bcbf99SRichard Fitzgerald ARRAY_SIZE(cs48l32_rate_text),
1154e2bcbf99SRichard Fitzgerald cs48l32_rate_text, cs48l32_rate_val),
1155e2bcbf99SRichard Fitzgerald SOC_VALUE_ENUM_SINGLE(SND_SOC_NOPM, 0,
1156e2bcbf99SRichard Fitzgerald 10,
1157e2bcbf99SRichard Fitzgerald ARRAY_SIZE(cs48l32_rate_text),
1158e2bcbf99SRichard Fitzgerald cs48l32_rate_text, cs48l32_rate_val),
1159e2bcbf99SRichard Fitzgerald SOC_VALUE_ENUM_SINGLE(SND_SOC_NOPM, 0,
1160e2bcbf99SRichard Fitzgerald 11,
1161e2bcbf99SRichard Fitzgerald ARRAY_SIZE(cs48l32_rate_text),
1162e2bcbf99SRichard Fitzgerald cs48l32_rate_text, cs48l32_rate_val),
1163e2bcbf99SRichard Fitzgerald SOC_VALUE_ENUM_SINGLE(SND_SOC_NOPM, 0,
1164e2bcbf99SRichard Fitzgerald 12,
1165e2bcbf99SRichard Fitzgerald ARRAY_SIZE(cs48l32_rate_text),
1166e2bcbf99SRichard Fitzgerald cs48l32_rate_text, cs48l32_rate_val),
1167e2bcbf99SRichard Fitzgerald SOC_VALUE_ENUM_SINGLE(SND_SOC_NOPM, 0,
1168e2bcbf99SRichard Fitzgerald 13,
1169e2bcbf99SRichard Fitzgerald ARRAY_SIZE(cs48l32_rate_text),
1170e2bcbf99SRichard Fitzgerald cs48l32_rate_text, cs48l32_rate_val),
1171e2bcbf99SRichard Fitzgerald SOC_VALUE_ENUM_SINGLE(SND_SOC_NOPM, 0,
1172e2bcbf99SRichard Fitzgerald 14,
1173e2bcbf99SRichard Fitzgerald ARRAY_SIZE(cs48l32_rate_text),
1174e2bcbf99SRichard Fitzgerald cs48l32_rate_text, cs48l32_rate_val),
1175e2bcbf99SRichard Fitzgerald SOC_VALUE_ENUM_SINGLE(SND_SOC_NOPM, 0,
1176e2bcbf99SRichard Fitzgerald 15,
1177e2bcbf99SRichard Fitzgerald ARRAY_SIZE(cs48l32_rate_text),
1178e2bcbf99SRichard Fitzgerald cs48l32_rate_text, cs48l32_rate_val),
1179e2bcbf99SRichard Fitzgerald };
1180e2bcbf99SRichard Fitzgerald
cs48l32_dsp_pre_run(struct wm_adsp * dsp)1181e2bcbf99SRichard Fitzgerald static int cs48l32_dsp_pre_run(struct wm_adsp *dsp)
1182e2bcbf99SRichard Fitzgerald {
1183e2bcbf99SRichard Fitzgerald struct cs48l32_codec *cs48l32_codec = container_of(dsp, struct cs48l32_codec, dsp);
1184e2bcbf99SRichard Fitzgerald unsigned int reg;
1185e2bcbf99SRichard Fitzgerald const u8 *rate = cs48l32_codec->dsp_dma_rates;
1186e2bcbf99SRichard Fitzgerald int i;
1187e2bcbf99SRichard Fitzgerald
1188e2bcbf99SRichard Fitzgerald reg = dsp->cs_dsp.base + CS48L32_HALO_SAMPLE_RATE_RX1;
1189e2bcbf99SRichard Fitzgerald for (i = 0; i < CS48L32_DSP_N_RX_CHANNELS; ++i) {
1190e2bcbf99SRichard Fitzgerald regmap_update_bits(dsp->cs_dsp.regmap, reg, CS48L32_HALO_DSP_RATE_MASK, *rate);
1191e2bcbf99SRichard Fitzgerald reg += 8;
1192e2bcbf99SRichard Fitzgerald rate++;
1193e2bcbf99SRichard Fitzgerald }
1194e2bcbf99SRichard Fitzgerald
1195e2bcbf99SRichard Fitzgerald reg = dsp->cs_dsp.base + CS48L32_HALO_SAMPLE_RATE_TX1;
1196e2bcbf99SRichard Fitzgerald for (i = 0; i < CS48L32_DSP_N_TX_CHANNELS; ++i) {
1197e2bcbf99SRichard Fitzgerald regmap_update_bits(dsp->cs_dsp.regmap, reg, CS48L32_HALO_DSP_RATE_MASK, *rate);
1198e2bcbf99SRichard Fitzgerald reg += 8;
1199e2bcbf99SRichard Fitzgerald rate++;
1200e2bcbf99SRichard Fitzgerald }
1201e2bcbf99SRichard Fitzgerald
1202e2bcbf99SRichard Fitzgerald usleep_range(300, 600);
1203e2bcbf99SRichard Fitzgerald
1204e2bcbf99SRichard Fitzgerald return 0;
1205e2bcbf99SRichard Fitzgerald }
1206e2bcbf99SRichard Fitzgerald
cs48l32_dsp_memory_disable(struct cs48l32_codec * cs48l32_codec,const struct cs48l32_dsp_power_regs * regs)1207e2bcbf99SRichard Fitzgerald static void cs48l32_dsp_memory_disable(struct cs48l32_codec *cs48l32_codec,
1208e2bcbf99SRichard Fitzgerald const struct cs48l32_dsp_power_regs *regs)
1209e2bcbf99SRichard Fitzgerald {
1210e2bcbf99SRichard Fitzgerald struct regmap *regmap = cs48l32_codec->core.regmap;
1211e2bcbf99SRichard Fitzgerald int i, j, ret;
1212e2bcbf99SRichard Fitzgerald
1213e2bcbf99SRichard Fitzgerald for (i = 0; i < regs->n_pwd; ++i) {
1214e2bcbf99SRichard Fitzgerald ret = regmap_write(regmap, regs->pwd[i], 0);
1215e2bcbf99SRichard Fitzgerald if (ret)
1216e2bcbf99SRichard Fitzgerald goto err;
1217e2bcbf99SRichard Fitzgerald }
1218e2bcbf99SRichard Fitzgerald
1219e2bcbf99SRichard Fitzgerald for (i = 0; i < regs->n_ext; ++i) {
1220e2bcbf99SRichard Fitzgerald for (j = regs->ext[i].start; j <= regs->ext[i].end; j += 4) {
1221e2bcbf99SRichard Fitzgerald ret = regmap_write(regmap, j, 0);
1222e2bcbf99SRichard Fitzgerald if (ret)
1223e2bcbf99SRichard Fitzgerald goto err;
1224e2bcbf99SRichard Fitzgerald }
1225e2bcbf99SRichard Fitzgerald }
1226e2bcbf99SRichard Fitzgerald
1227e2bcbf99SRichard Fitzgerald return;
1228e2bcbf99SRichard Fitzgerald
1229e2bcbf99SRichard Fitzgerald err:
1230e2bcbf99SRichard Fitzgerald dev_warn(cs48l32_codec->core.dev, "Failed to write SRAM enables (%d)\n", ret);
1231e2bcbf99SRichard Fitzgerald }
1232e2bcbf99SRichard Fitzgerald
cs48l32_dsp_memory_enable(struct cs48l32_codec * cs48l32_codec,const struct cs48l32_dsp_power_regs * regs)1233e2bcbf99SRichard Fitzgerald static int cs48l32_dsp_memory_enable(struct cs48l32_codec *cs48l32_codec,
1234e2bcbf99SRichard Fitzgerald const struct cs48l32_dsp_power_regs *regs)
1235e2bcbf99SRichard Fitzgerald {
1236e2bcbf99SRichard Fitzgerald struct regmap *regmap = cs48l32_codec->core.regmap;
1237e2bcbf99SRichard Fitzgerald int i, j, ret;
1238e2bcbf99SRichard Fitzgerald
1239e2bcbf99SRichard Fitzgerald /* disable power-off */
1240e2bcbf99SRichard Fitzgerald for (i = 0; i < regs->n_ext; ++i) {
1241e2bcbf99SRichard Fitzgerald for (j = regs->ext[i].start; j <= regs->ext[i].end; j += 4) {
1242e2bcbf99SRichard Fitzgerald ret = regmap_write(regmap, j, 0x3);
1243e2bcbf99SRichard Fitzgerald if (ret)
1244e2bcbf99SRichard Fitzgerald goto err;
1245e2bcbf99SRichard Fitzgerald }
1246e2bcbf99SRichard Fitzgerald }
1247e2bcbf99SRichard Fitzgerald
1248e2bcbf99SRichard Fitzgerald /* power-up the banks in sequence */
1249e2bcbf99SRichard Fitzgerald for (i = 0; i < regs->n_pwd; ++i) {
1250e2bcbf99SRichard Fitzgerald ret = regmap_write(regmap, regs->pwd[i], 0x1);
1251e2bcbf99SRichard Fitzgerald if (ret)
1252e2bcbf99SRichard Fitzgerald goto err;
1253e2bcbf99SRichard Fitzgerald
1254e2bcbf99SRichard Fitzgerald udelay(1); /* allow bank to power-up */
1255e2bcbf99SRichard Fitzgerald
1256e2bcbf99SRichard Fitzgerald ret = regmap_write(regmap, regs->pwd[i], 0x3);
1257e2bcbf99SRichard Fitzgerald if (ret)
1258e2bcbf99SRichard Fitzgerald goto err;
1259e2bcbf99SRichard Fitzgerald
1260e2bcbf99SRichard Fitzgerald udelay(1); /* allow bank to power-up */
1261e2bcbf99SRichard Fitzgerald }
1262e2bcbf99SRichard Fitzgerald
1263e2bcbf99SRichard Fitzgerald return 0;
1264e2bcbf99SRichard Fitzgerald
1265e2bcbf99SRichard Fitzgerald err:
1266e2bcbf99SRichard Fitzgerald dev_err(cs48l32_codec->core.dev, "Failed to write SRAM enables (%d)\n", ret);
1267e2bcbf99SRichard Fitzgerald cs48l32_dsp_memory_disable(cs48l32_codec, regs);
1268e2bcbf99SRichard Fitzgerald
1269e2bcbf99SRichard Fitzgerald return ret;
1270e2bcbf99SRichard Fitzgerald }
1271e2bcbf99SRichard Fitzgerald
cs48l32_dsp_freq_update(struct snd_soc_dapm_widget * w,unsigned int freq_reg,unsigned int freqsel_reg)1272e2bcbf99SRichard Fitzgerald static int cs48l32_dsp_freq_update(struct snd_soc_dapm_widget *w, unsigned int freq_reg,
1273e2bcbf99SRichard Fitzgerald unsigned int freqsel_reg)
1274e2bcbf99SRichard Fitzgerald {
1275e2bcbf99SRichard Fitzgerald struct snd_soc_component *component = snd_soc_dapm_to_component(w->dapm);
1276e2bcbf99SRichard Fitzgerald struct cs48l32_codec *cs48l32_codec = snd_soc_component_get_drvdata(component);
1277e2bcbf99SRichard Fitzgerald struct regmap *regmap = cs48l32_codec->core.regmap;
1278e2bcbf99SRichard Fitzgerald struct wm_adsp *dsp = &cs48l32_codec->dsp;
1279e2bcbf99SRichard Fitzgerald int ret;
1280e2bcbf99SRichard Fitzgerald unsigned int freq, freq_sel, freq_sts;
1281e2bcbf99SRichard Fitzgerald
1282e2bcbf99SRichard Fitzgerald if (!freq_reg)
1283e2bcbf99SRichard Fitzgerald return -EINVAL;
1284e2bcbf99SRichard Fitzgerald
1285e2bcbf99SRichard Fitzgerald ret = regmap_read(regmap, freq_reg, &freq);
1286e2bcbf99SRichard Fitzgerald if (ret) {
1287e2bcbf99SRichard Fitzgerald dev_err(component->dev, "Failed to read #%x: %d\n", freq_reg, ret);
1288e2bcbf99SRichard Fitzgerald return ret;
1289e2bcbf99SRichard Fitzgerald }
1290e2bcbf99SRichard Fitzgerald
1291e2bcbf99SRichard Fitzgerald if (freqsel_reg) {
1292e2bcbf99SRichard Fitzgerald freq_sts = (freq & CS48L32_SYSCLK_FREQ_STS_MASK) >> CS48L32_SYSCLK_FREQ_STS_SHIFT;
1293e2bcbf99SRichard Fitzgerald
1294e2bcbf99SRichard Fitzgerald ret = regmap_read(regmap, freqsel_reg, &freq_sel);
1295e2bcbf99SRichard Fitzgerald if (ret) {
1296e2bcbf99SRichard Fitzgerald dev_err(component->dev, "Failed to read #%x: %d\n", freqsel_reg, ret);
1297e2bcbf99SRichard Fitzgerald return ret;
1298e2bcbf99SRichard Fitzgerald }
1299e2bcbf99SRichard Fitzgerald freq_sel = (freq_sel & CS48L32_SYSCLK_FREQ_MASK) >> CS48L32_SYSCLK_FREQ_SHIFT;
1300e2bcbf99SRichard Fitzgerald
1301e2bcbf99SRichard Fitzgerald if (freq_sts != freq_sel) {
1302e2bcbf99SRichard Fitzgerald dev_err(component->dev, "SYSCLK FREQ (#%x) != FREQ STS (#%x)\n",
1303e2bcbf99SRichard Fitzgerald freq_sel, freq_sts);
1304e2bcbf99SRichard Fitzgerald return -ETIMEDOUT;
1305e2bcbf99SRichard Fitzgerald }
1306e2bcbf99SRichard Fitzgerald }
1307e2bcbf99SRichard Fitzgerald
1308e2bcbf99SRichard Fitzgerald freq &= CS48L32_DSP_CLK_FREQ_MASK;
1309e2bcbf99SRichard Fitzgerald freq >>= CS48L32_DSP_CLK_FREQ_SHIFT;
1310e2bcbf99SRichard Fitzgerald
1311e2bcbf99SRichard Fitzgerald ret = regmap_write(dsp->cs_dsp.regmap,
1312e2bcbf99SRichard Fitzgerald dsp->cs_dsp.base + CS48L32_DSP_CLOCK_FREQ_OFFS, freq);
1313e2bcbf99SRichard Fitzgerald if (ret) {
1314e2bcbf99SRichard Fitzgerald dev_err(component->dev, "Failed to set HALO clock freq: %d\n", ret);
1315e2bcbf99SRichard Fitzgerald return ret;
1316e2bcbf99SRichard Fitzgerald }
1317e2bcbf99SRichard Fitzgerald
1318e2bcbf99SRichard Fitzgerald return 0;
1319e2bcbf99SRichard Fitzgerald }
1320e2bcbf99SRichard Fitzgerald
cs48l32_dsp_freq_ev(struct snd_soc_dapm_widget * w,struct snd_kcontrol * kcontrol,int event)1321e2bcbf99SRichard Fitzgerald static int cs48l32_dsp_freq_ev(struct snd_soc_dapm_widget *w,
1322e2bcbf99SRichard Fitzgerald struct snd_kcontrol *kcontrol, int event)
1323e2bcbf99SRichard Fitzgerald {
1324e2bcbf99SRichard Fitzgerald switch (event) {
1325e2bcbf99SRichard Fitzgerald case SND_SOC_DAPM_POST_PMU:
1326e2bcbf99SRichard Fitzgerald return cs48l32_dsp_freq_update(w, CS48L32_SYSTEM_CLOCK2, CS48L32_SYSTEM_CLOCK1);
1327e2bcbf99SRichard Fitzgerald default:
1328e2bcbf99SRichard Fitzgerald return 0;
1329e2bcbf99SRichard Fitzgerald }
1330e2bcbf99SRichard Fitzgerald }
1331e2bcbf99SRichard Fitzgerald
cs48l32_irq(int irq,void * data)1332e2bcbf99SRichard Fitzgerald static irqreturn_t cs48l32_irq(int irq, void *data)
1333e2bcbf99SRichard Fitzgerald {
1334e2bcbf99SRichard Fitzgerald static const unsigned int eint1_regs[] = {
1335e2bcbf99SRichard Fitzgerald CS48L32_IRQ1_EINT_9, CS48L32_IRQ1_MASK_9,
1336e2bcbf99SRichard Fitzgerald CS48L32_IRQ1_EINT_7, CS48L32_IRQ1_MASK_7
1337e2bcbf99SRichard Fitzgerald };
1338e2bcbf99SRichard Fitzgerald u32 reg_vals[4];
1339e2bcbf99SRichard Fitzgerald struct cs48l32_codec *cs48l32_codec = data;
1340e2bcbf99SRichard Fitzgerald struct regmap *regmap = cs48l32_codec->core.regmap;
1341e2bcbf99SRichard Fitzgerald irqreturn_t result = IRQ_NONE;
1342e2bcbf99SRichard Fitzgerald unsigned int eint_pending;
1343e2bcbf99SRichard Fitzgerald int i, ret;
1344e2bcbf99SRichard Fitzgerald
1345e2bcbf99SRichard Fitzgerald static_assert(ARRAY_SIZE(eint1_regs) == ARRAY_SIZE(reg_vals));
1346e2bcbf99SRichard Fitzgerald
1347e2bcbf99SRichard Fitzgerald ret = pm_runtime_resume_and_get(cs48l32_codec->core.dev);
1348e2bcbf99SRichard Fitzgerald if (ret) {
1349e2bcbf99SRichard Fitzgerald dev_warn(cs48l32_codec->core.dev, "irq could not get pm runtime: %d\n", ret);
1350e2bcbf99SRichard Fitzgerald return IRQ_NONE;
1351e2bcbf99SRichard Fitzgerald }
1352e2bcbf99SRichard Fitzgerald
1353e2bcbf99SRichard Fitzgerald ret = regmap_read(regmap, CS48L32_IRQ1_STATUS, &eint_pending);
1354e2bcbf99SRichard Fitzgerald if (ret) {
1355e2bcbf99SRichard Fitzgerald dev_warn(cs48l32_codec->core.dev, "Read IRQ1_STATUS failed: %d\n", ret);
1356e2bcbf99SRichard Fitzgerald return IRQ_NONE;
1357e2bcbf99SRichard Fitzgerald }
1358e2bcbf99SRichard Fitzgerald if ((eint_pending & CS48L32_IRQ1_STS_MASK) == 0)
1359e2bcbf99SRichard Fitzgerald goto out;
1360e2bcbf99SRichard Fitzgerald
1361e2bcbf99SRichard Fitzgerald ret = regmap_multi_reg_read(regmap, eint1_regs, reg_vals, ARRAY_SIZE(reg_vals));
1362e2bcbf99SRichard Fitzgerald if (ret) {
1363e2bcbf99SRichard Fitzgerald dev_warn(cs48l32_codec->core.dev, "Read IRQ regs failed: %d\n", ret);
1364e2bcbf99SRichard Fitzgerald return IRQ_NONE;
1365e2bcbf99SRichard Fitzgerald }
1366e2bcbf99SRichard Fitzgerald
1367e2bcbf99SRichard Fitzgerald for (i = 0; i < ARRAY_SIZE(reg_vals); i += 2) {
1368e2bcbf99SRichard Fitzgerald reg_vals[i] &= ~reg_vals[i + 1];
1369e2bcbf99SRichard Fitzgerald regmap_write(regmap, eint1_regs[i], reg_vals[i]);
1370e2bcbf99SRichard Fitzgerald }
1371e2bcbf99SRichard Fitzgerald
1372e2bcbf99SRichard Fitzgerald if (reg_vals[0] & CS48L32_DSP1_IRQ0_EINT1_MASK)
1373e2bcbf99SRichard Fitzgerald wm_adsp_compr_handle_irq(&cs48l32_codec->dsp);
1374e2bcbf99SRichard Fitzgerald
1375e2bcbf99SRichard Fitzgerald if (reg_vals[2] & CS48L32_DSP1_MPU_ERR_EINT1_MASK) {
1376e2bcbf99SRichard Fitzgerald dev_warn(cs48l32_codec->core.dev, "MPU err IRQ\n");
1377e2bcbf99SRichard Fitzgerald wm_halo_bus_error(irq, &cs48l32_codec->dsp);
1378e2bcbf99SRichard Fitzgerald }
1379e2bcbf99SRichard Fitzgerald
1380e2bcbf99SRichard Fitzgerald if (reg_vals[2] & CS48L32_DSP1_WDT_EXPIRE_EINT1_MASK) {
1381e2bcbf99SRichard Fitzgerald dev_warn(cs48l32_codec->core.dev, "WDT expire IRQ\n");
1382e2bcbf99SRichard Fitzgerald wm_halo_wdt_expire(irq, &cs48l32_codec->dsp);
1383e2bcbf99SRichard Fitzgerald }
1384e2bcbf99SRichard Fitzgerald
1385e2bcbf99SRichard Fitzgerald result = IRQ_HANDLED;
1386e2bcbf99SRichard Fitzgerald
1387e2bcbf99SRichard Fitzgerald out:
1388e2bcbf99SRichard Fitzgerald pm_runtime_mark_last_busy(cs48l32_codec->core.dev);
1389e2bcbf99SRichard Fitzgerald pm_runtime_put_autosuspend(cs48l32_codec->core.dev);
1390e2bcbf99SRichard Fitzgerald
1391e2bcbf99SRichard Fitzgerald return result;
1392e2bcbf99SRichard Fitzgerald }
1393e2bcbf99SRichard Fitzgerald
cs48l32_get_dspclk_setting(struct cs48l32_codec * cs48l32_codec,unsigned int freq,int src,unsigned int * val)1394e2bcbf99SRichard Fitzgerald static int cs48l32_get_dspclk_setting(struct cs48l32_codec *cs48l32_codec, unsigned int freq,
1395e2bcbf99SRichard Fitzgerald int src, unsigned int *val)
1396e2bcbf99SRichard Fitzgerald {
1397e2bcbf99SRichard Fitzgerald freq /= 15625; /* convert to 1/64ths of 1MHz */
1398e2bcbf99SRichard Fitzgerald *val |= freq << CS48L32_DSP_CLK_FREQ_SHIFT;
1399e2bcbf99SRichard Fitzgerald
1400e2bcbf99SRichard Fitzgerald return 0;
1401e2bcbf99SRichard Fitzgerald }
1402e2bcbf99SRichard Fitzgerald
cs48l32_get_sysclk_setting(unsigned int freq)1403e2bcbf99SRichard Fitzgerald static int cs48l32_get_sysclk_setting(unsigned int freq)
1404e2bcbf99SRichard Fitzgerald {
1405e2bcbf99SRichard Fitzgerald switch (freq) {
1406e2bcbf99SRichard Fitzgerald case 0:
1407e2bcbf99SRichard Fitzgerald case 5644800:
1408e2bcbf99SRichard Fitzgerald case 6144000:
1409e2bcbf99SRichard Fitzgerald return CS48L32_SYSCLK_RATE_6MHZ;
1410e2bcbf99SRichard Fitzgerald case 11289600:
1411e2bcbf99SRichard Fitzgerald case 12288000:
1412e2bcbf99SRichard Fitzgerald return CS48L32_SYSCLK_RATE_12MHZ << CS48L32_SYSCLK_FREQ_SHIFT;
1413e2bcbf99SRichard Fitzgerald case 22579200:
1414e2bcbf99SRichard Fitzgerald case 24576000:
1415e2bcbf99SRichard Fitzgerald return CS48L32_SYSCLK_RATE_24MHZ << CS48L32_SYSCLK_FREQ_SHIFT;
1416e2bcbf99SRichard Fitzgerald case 45158400:
1417e2bcbf99SRichard Fitzgerald case 49152000:
1418e2bcbf99SRichard Fitzgerald return CS48L32_SYSCLK_RATE_49MHZ << CS48L32_SYSCLK_FREQ_SHIFT;
1419e2bcbf99SRichard Fitzgerald case 90316800:
1420e2bcbf99SRichard Fitzgerald case 98304000:
1421e2bcbf99SRichard Fitzgerald return CS48L32_SYSCLK_RATE_98MHZ << CS48L32_SYSCLK_FREQ_SHIFT;
1422e2bcbf99SRichard Fitzgerald default:
1423e2bcbf99SRichard Fitzgerald return -EINVAL;
1424e2bcbf99SRichard Fitzgerald }
1425e2bcbf99SRichard Fitzgerald }
1426e2bcbf99SRichard Fitzgerald
cs48l32_set_pdm_fllclk(struct snd_soc_component * component,int source)1427e2bcbf99SRichard Fitzgerald static int cs48l32_set_pdm_fllclk(struct snd_soc_component *component, int source)
1428e2bcbf99SRichard Fitzgerald {
1429e2bcbf99SRichard Fitzgerald struct cs48l32_codec *cs48l32_codec = snd_soc_component_get_drvdata(component);
1430e2bcbf99SRichard Fitzgerald struct regmap *regmap = cs48l32_codec->core.regmap;
1431e2bcbf99SRichard Fitzgerald unsigned int val;
1432e2bcbf99SRichard Fitzgerald
1433e2bcbf99SRichard Fitzgerald switch (source) {
1434e2bcbf99SRichard Fitzgerald case CS48L32_PDMCLK_SRC_IN1_PDMCLK:
1435e2bcbf99SRichard Fitzgerald case CS48L32_PDMCLK_SRC_IN2_PDMCLK:
1436e2bcbf99SRichard Fitzgerald case CS48L32_PDMCLK_SRC_IN3_PDMCLK:
1437e2bcbf99SRichard Fitzgerald case CS48L32_PDMCLK_SRC_IN4_PDMCLK:
1438e2bcbf99SRichard Fitzgerald case CS48L32_PDMCLK_SRC_AUXPDM1_CLK:
1439e2bcbf99SRichard Fitzgerald case CS48L32_PDMCLK_SRC_AUXPDM2_CLK:
1440e2bcbf99SRichard Fitzgerald val = source << CS48L32_PDM_FLLCLK_SRC_SHIFT;
1441e2bcbf99SRichard Fitzgerald break;
1442e2bcbf99SRichard Fitzgerald default:
1443e2bcbf99SRichard Fitzgerald dev_err(cs48l32_codec->core.dev, "Invalid PDM FLLCLK src %d\n", source);
1444e2bcbf99SRichard Fitzgerald return -EINVAL;
1445e2bcbf99SRichard Fitzgerald }
1446e2bcbf99SRichard Fitzgerald
1447e2bcbf99SRichard Fitzgerald return regmap_update_bits(regmap, CS48L32_INPUT_CONTROL2,
1448e2bcbf99SRichard Fitzgerald CS48L32_PDM_FLLCLK_SRC_MASK, val);
1449e2bcbf99SRichard Fitzgerald }
1450e2bcbf99SRichard Fitzgerald
cs48l32_set_sysclk(struct snd_soc_component * component,int clk_id,int source,unsigned int freq,int dir)1451e2bcbf99SRichard Fitzgerald static int cs48l32_set_sysclk(struct snd_soc_component *component, int clk_id, int source,
1452e2bcbf99SRichard Fitzgerald unsigned int freq, int dir)
1453e2bcbf99SRichard Fitzgerald {
1454e2bcbf99SRichard Fitzgerald struct cs48l32_codec *cs48l32_codec = snd_soc_component_get_drvdata(component);
1455e2bcbf99SRichard Fitzgerald struct regmap *regmap = cs48l32_codec->core.regmap;
1456e2bcbf99SRichard Fitzgerald char *name;
1457e2bcbf99SRichard Fitzgerald unsigned int reg;
1458e2bcbf99SRichard Fitzgerald unsigned int mask = CS48L32_SYSCLK_SRC_MASK;
1459e2bcbf99SRichard Fitzgerald unsigned int val = source << CS48L32_SYSCLK_SRC_SHIFT;
1460e2bcbf99SRichard Fitzgerald int clk_freq_sel, *clk;
1461e2bcbf99SRichard Fitzgerald
1462e2bcbf99SRichard Fitzgerald switch (clk_id) {
1463e2bcbf99SRichard Fitzgerald case CS48L32_CLK_SYSCLK_1:
1464e2bcbf99SRichard Fitzgerald name = "SYSCLK";
1465e2bcbf99SRichard Fitzgerald reg = CS48L32_SYSTEM_CLOCK1;
1466e2bcbf99SRichard Fitzgerald clk = &cs48l32_codec->sysclk;
1467e2bcbf99SRichard Fitzgerald clk_freq_sel = cs48l32_get_sysclk_setting(freq);
1468e2bcbf99SRichard Fitzgerald mask |= CS48L32_SYSCLK_FREQ_MASK | CS48L32_SYSCLK_FRAC_MASK;
1469e2bcbf99SRichard Fitzgerald break;
1470e2bcbf99SRichard Fitzgerald case CS48L32_CLK_DSPCLK:
1471e2bcbf99SRichard Fitzgerald name = "DSPCLK";
1472e2bcbf99SRichard Fitzgerald reg = CS48L32_DSP_CLOCK1;
1473e2bcbf99SRichard Fitzgerald clk = &cs48l32_codec->dspclk;
1474e2bcbf99SRichard Fitzgerald clk_freq_sel = cs48l32_get_dspclk_setting(cs48l32_codec, freq, source, &val);
1475e2bcbf99SRichard Fitzgerald mask |= CS48L32_DSP_CLK_FREQ_MASK;
1476e2bcbf99SRichard Fitzgerald break;
1477e2bcbf99SRichard Fitzgerald case CS48L32_CLK_PDM_FLLCLK:
1478e2bcbf99SRichard Fitzgerald return cs48l32_set_pdm_fllclk(component, source);
1479e2bcbf99SRichard Fitzgerald default:
1480e2bcbf99SRichard Fitzgerald return -EINVAL;
1481e2bcbf99SRichard Fitzgerald }
1482e2bcbf99SRichard Fitzgerald
1483e2bcbf99SRichard Fitzgerald if (clk_freq_sel < 0) {
1484e2bcbf99SRichard Fitzgerald dev_err(cs48l32_codec->core.dev, "Failed to get %s setting for %dHZ\n", name, freq);
1485e2bcbf99SRichard Fitzgerald return clk_freq_sel;
1486e2bcbf99SRichard Fitzgerald }
1487e2bcbf99SRichard Fitzgerald
1488e2bcbf99SRichard Fitzgerald *clk = freq;
1489e2bcbf99SRichard Fitzgerald
1490e2bcbf99SRichard Fitzgerald if (freq == 0) {
1491e2bcbf99SRichard Fitzgerald dev_dbg(cs48l32_codec->core.dev, "%s cleared\n", name);
1492e2bcbf99SRichard Fitzgerald return 0;
1493e2bcbf99SRichard Fitzgerald }
1494e2bcbf99SRichard Fitzgerald
1495e2bcbf99SRichard Fitzgerald val |= clk_freq_sel;
1496e2bcbf99SRichard Fitzgerald
1497e2bcbf99SRichard Fitzgerald if (freq % 6144000)
1498e2bcbf99SRichard Fitzgerald val |= CS48L32_SYSCLK_FRAC_MASK;
1499e2bcbf99SRichard Fitzgerald
1500e2bcbf99SRichard Fitzgerald dev_dbg(cs48l32_codec->core.dev, "%s set to %uHz", name, freq);
1501e2bcbf99SRichard Fitzgerald
1502e2bcbf99SRichard Fitzgerald return regmap_update_bits(regmap, reg, mask, val);
1503e2bcbf99SRichard Fitzgerald }
1504e2bcbf99SRichard Fitzgerald
cs48l32_is_enabled_fll(struct cs48l32_fll * fll,int base)1505e2bcbf99SRichard Fitzgerald static int cs48l32_is_enabled_fll(struct cs48l32_fll *fll, int base)
1506e2bcbf99SRichard Fitzgerald {
1507e2bcbf99SRichard Fitzgerald struct regmap *regmap = fll->codec->core.regmap;
1508e2bcbf99SRichard Fitzgerald unsigned int reg;
1509e2bcbf99SRichard Fitzgerald int ret;
1510e2bcbf99SRichard Fitzgerald
1511e2bcbf99SRichard Fitzgerald ret = regmap_read(regmap, base + CS48L32_FLL_CONTROL1_OFFS, ®);
1512e2bcbf99SRichard Fitzgerald if (ret != 0) {
1513e2bcbf99SRichard Fitzgerald cs48l32_fll_err(fll, "Failed to read current state: %d\n", ret);
1514e2bcbf99SRichard Fitzgerald return ret;
1515e2bcbf99SRichard Fitzgerald }
1516e2bcbf99SRichard Fitzgerald
1517e2bcbf99SRichard Fitzgerald return reg & CS48L32_FLL_EN_MASK;
1518e2bcbf99SRichard Fitzgerald }
1519e2bcbf99SRichard Fitzgerald
cs48l32_wait_for_fll(struct cs48l32_fll * fll,bool requested)1520e2bcbf99SRichard Fitzgerald static int cs48l32_wait_for_fll(struct cs48l32_fll *fll, bool requested)
1521e2bcbf99SRichard Fitzgerald {
1522e2bcbf99SRichard Fitzgerald struct regmap *regmap = fll->codec->core.regmap;
1523e2bcbf99SRichard Fitzgerald unsigned int val = 0;
1524e2bcbf99SRichard Fitzgerald int i;
1525e2bcbf99SRichard Fitzgerald
1526e2bcbf99SRichard Fitzgerald cs48l32_fll_dbg(fll, "Waiting for FLL...\n");
1527e2bcbf99SRichard Fitzgerald
1528e2bcbf99SRichard Fitzgerald for (i = 0; i < 30; i++) {
1529e2bcbf99SRichard Fitzgerald regmap_read(regmap, fll->sts_addr, &val);
1530e2bcbf99SRichard Fitzgerald if (!!(val & fll->sts_mask) == requested)
1531e2bcbf99SRichard Fitzgerald return 0;
1532e2bcbf99SRichard Fitzgerald
1533e2bcbf99SRichard Fitzgerald switch (i) {
1534e2bcbf99SRichard Fitzgerald case 0 ... 5:
1535e2bcbf99SRichard Fitzgerald usleep_range(75, 125);
1536e2bcbf99SRichard Fitzgerald break;
1537e2bcbf99SRichard Fitzgerald case 6 ... 20:
1538e2bcbf99SRichard Fitzgerald usleep_range(750, 1250);
1539e2bcbf99SRichard Fitzgerald break;
1540e2bcbf99SRichard Fitzgerald default:
1541e2bcbf99SRichard Fitzgerald fsleep(20000);
1542e2bcbf99SRichard Fitzgerald break;
1543e2bcbf99SRichard Fitzgerald }
1544e2bcbf99SRichard Fitzgerald }
1545e2bcbf99SRichard Fitzgerald
1546e2bcbf99SRichard Fitzgerald cs48l32_fll_warn(fll, "Timed out waiting for %s\n", requested ? "lock" : "unlock");
1547e2bcbf99SRichard Fitzgerald
1548e2bcbf99SRichard Fitzgerald return -ETIMEDOUT;
1549e2bcbf99SRichard Fitzgerald }
1550e2bcbf99SRichard Fitzgerald
cs48l32_fllhj_disable(struct cs48l32_fll * fll)1551e2bcbf99SRichard Fitzgerald static int cs48l32_fllhj_disable(struct cs48l32_fll *fll)
1552e2bcbf99SRichard Fitzgerald {
1553e2bcbf99SRichard Fitzgerald struct cs48l32 *cs48l32 = &fll->codec->core;
1554e2bcbf99SRichard Fitzgerald bool change;
1555e2bcbf99SRichard Fitzgerald
1556e2bcbf99SRichard Fitzgerald cs48l32_fll_dbg(fll, "Disabling FLL\n");
1557e2bcbf99SRichard Fitzgerald
1558e2bcbf99SRichard Fitzgerald /*
1559e2bcbf99SRichard Fitzgerald * Disable lockdet, but don't set ctrl_upd update bit. This allows the
1560e2bcbf99SRichard Fitzgerald * lock status bit to clear as normal, but should the FLL be enabled
1561e2bcbf99SRichard Fitzgerald * again due to a control clock being required, the lock won't re-assert
1562e2bcbf99SRichard Fitzgerald * as the FLL config registers are automatically applied when the FLL
1563e2bcbf99SRichard Fitzgerald * enables.
1564e2bcbf99SRichard Fitzgerald */
1565e2bcbf99SRichard Fitzgerald regmap_set_bits(cs48l32->regmap,
1566e2bcbf99SRichard Fitzgerald fll->base + CS48L32_FLL_CONTROL1_OFFS,
1567e2bcbf99SRichard Fitzgerald CS48L32_FLL_HOLD_MASK);
1568e2bcbf99SRichard Fitzgerald regmap_clear_bits(cs48l32->regmap,
1569e2bcbf99SRichard Fitzgerald fll->base + CS48L32_FLL_CONTROL2_OFFS,
1570e2bcbf99SRichard Fitzgerald CS48L32_FLL_LOCKDET_MASK);
1571e2bcbf99SRichard Fitzgerald regmap_set_bits(cs48l32->regmap,
1572e2bcbf99SRichard Fitzgerald fll->base + CS48L32_FLL_CONTROL5_OFFS,
1573e2bcbf99SRichard Fitzgerald CS48L32_FLL_FRC_INTEG_UPD_MASK);
1574e2bcbf99SRichard Fitzgerald regmap_update_bits_check(cs48l32->regmap,
1575e2bcbf99SRichard Fitzgerald fll->base + CS48L32_FLL_CONTROL1_OFFS,
1576e2bcbf99SRichard Fitzgerald CS48L32_FLL_EN_MASK,
1577e2bcbf99SRichard Fitzgerald 0,
1578e2bcbf99SRichard Fitzgerald &change);
1579e2bcbf99SRichard Fitzgerald
1580e2bcbf99SRichard Fitzgerald cs48l32_wait_for_fll(fll, false);
1581e2bcbf99SRichard Fitzgerald
1582e2bcbf99SRichard Fitzgerald /*
1583e2bcbf99SRichard Fitzgerald * ctrl_up gates the writes to all the fll's registers, setting it to 0
1584e2bcbf99SRichard Fitzgerald * here ensures that after a runtime suspend/resume cycle when one
1585e2bcbf99SRichard Fitzgerald * enables the fll then ctrl_up is the last bit that is configured
1586e2bcbf99SRichard Fitzgerald * by the fll enable code rather than the cache sync operation which
1587e2bcbf99SRichard Fitzgerald * would have updated it much earlier before writing out all fll
1588e2bcbf99SRichard Fitzgerald * registers
1589e2bcbf99SRichard Fitzgerald */
1590e2bcbf99SRichard Fitzgerald regmap_clear_bits(cs48l32->regmap,
1591e2bcbf99SRichard Fitzgerald fll->base + CS48L32_FLL_CONTROL1_OFFS,
1592e2bcbf99SRichard Fitzgerald CS48L32_FLL_CTRL_UPD_MASK);
1593e2bcbf99SRichard Fitzgerald
1594e2bcbf99SRichard Fitzgerald if (change)
1595e2bcbf99SRichard Fitzgerald pm_runtime_put_autosuspend(cs48l32->dev);
1596e2bcbf99SRichard Fitzgerald
1597e2bcbf99SRichard Fitzgerald return 0;
1598e2bcbf99SRichard Fitzgerald }
1599e2bcbf99SRichard Fitzgerald
cs48l32_fllhj_apply(struct cs48l32_fll * fll,int fin)1600e2bcbf99SRichard Fitzgerald static int cs48l32_fllhj_apply(struct cs48l32_fll *fll, int fin)
1601e2bcbf99SRichard Fitzgerald {
1602e2bcbf99SRichard Fitzgerald struct regmap *regmap = fll->codec->core.regmap;
1603e2bcbf99SRichard Fitzgerald int refdiv, fref, fout, lockdet_thr, fbdiv, fllgcd;
1604e2bcbf99SRichard Fitzgerald bool frac = false;
1605e2bcbf99SRichard Fitzgerald unsigned int fll_n, min_n, max_n, ratio, theta, lambda, hp;
1606e2bcbf99SRichard Fitzgerald unsigned int gains, num;
1607e2bcbf99SRichard Fitzgerald
1608e2bcbf99SRichard Fitzgerald cs48l32_fll_dbg(fll, "fin=%d, fout=%d\n", fin, fll->fout);
1609e2bcbf99SRichard Fitzgerald
1610e2bcbf99SRichard Fitzgerald for (refdiv = 0; refdiv < 4; refdiv++) {
1611e2bcbf99SRichard Fitzgerald if ((fin / (1 << refdiv)) <= CS48L32_FLLHJ_MAX_THRESH)
1612e2bcbf99SRichard Fitzgerald break;
1613e2bcbf99SRichard Fitzgerald }
1614e2bcbf99SRichard Fitzgerald
1615e2bcbf99SRichard Fitzgerald fref = fin / (1 << refdiv);
1616e2bcbf99SRichard Fitzgerald fout = fll->fout;
1617e2bcbf99SRichard Fitzgerald frac = fout % fref;
1618e2bcbf99SRichard Fitzgerald
1619e2bcbf99SRichard Fitzgerald /*
1620e2bcbf99SRichard Fitzgerald * Use simple heuristic approach to find a configuration that
1621e2bcbf99SRichard Fitzgerald * should work for most input clocks.
1622e2bcbf99SRichard Fitzgerald */
1623e2bcbf99SRichard Fitzgerald if (fref < CS48L32_FLLHJ_LOW_THRESH) {
1624e2bcbf99SRichard Fitzgerald lockdet_thr = 2;
1625e2bcbf99SRichard Fitzgerald gains = CS48L32_FLLHJ_LOW_GAINS;
1626e2bcbf99SRichard Fitzgerald
1627e2bcbf99SRichard Fitzgerald if (frac)
1628e2bcbf99SRichard Fitzgerald fbdiv = 256;
1629e2bcbf99SRichard Fitzgerald else
1630e2bcbf99SRichard Fitzgerald fbdiv = 4;
1631e2bcbf99SRichard Fitzgerald } else if (fref < CS48L32_FLLHJ_MID_THRESH) {
1632e2bcbf99SRichard Fitzgerald lockdet_thr = 8;
1633e2bcbf99SRichard Fitzgerald gains = CS48L32_FLLHJ_MID_GAINS;
1634e2bcbf99SRichard Fitzgerald fbdiv = (frac) ? 16 : 2;
1635e2bcbf99SRichard Fitzgerald } else {
1636e2bcbf99SRichard Fitzgerald lockdet_thr = 8;
1637e2bcbf99SRichard Fitzgerald gains = CS48L32_FLLHJ_HIGH_GAINS;
1638e2bcbf99SRichard Fitzgerald fbdiv = 1;
1639e2bcbf99SRichard Fitzgerald }
1640e2bcbf99SRichard Fitzgerald /* Use high performance mode for fractional configurations. */
1641e2bcbf99SRichard Fitzgerald if (frac) {
1642e2bcbf99SRichard Fitzgerald hp = 3;
1643e2bcbf99SRichard Fitzgerald min_n = CS48L32_FLLHJ_FRAC_MIN_N;
1644e2bcbf99SRichard Fitzgerald max_n = CS48L32_FLLHJ_FRAC_MAX_N;
1645e2bcbf99SRichard Fitzgerald } else {
1646e2bcbf99SRichard Fitzgerald if (fref < CS48L32_FLLHJ_LP_INT_MODE_THRESH)
1647e2bcbf99SRichard Fitzgerald hp = 0;
1648e2bcbf99SRichard Fitzgerald else
1649e2bcbf99SRichard Fitzgerald hp = 1;
1650e2bcbf99SRichard Fitzgerald
1651e2bcbf99SRichard Fitzgerald min_n = CS48L32_FLLHJ_INT_MIN_N;
1652e2bcbf99SRichard Fitzgerald max_n = CS48L32_FLLHJ_INT_MAX_N;
1653e2bcbf99SRichard Fitzgerald }
1654e2bcbf99SRichard Fitzgerald
1655e2bcbf99SRichard Fitzgerald ratio = fout / fref;
1656e2bcbf99SRichard Fitzgerald
1657e2bcbf99SRichard Fitzgerald cs48l32_fll_dbg(fll, "refdiv=%d, fref=%d, frac:%d\n", refdiv, fref, frac);
1658e2bcbf99SRichard Fitzgerald
1659e2bcbf99SRichard Fitzgerald while (ratio / fbdiv < min_n) {
1660e2bcbf99SRichard Fitzgerald fbdiv /= 2;
1661e2bcbf99SRichard Fitzgerald if (fbdiv < min_n) {
1662e2bcbf99SRichard Fitzgerald cs48l32_fll_err(fll, "FBDIV (%u) < minimum N (%u)\n", fbdiv, min_n);
1663e2bcbf99SRichard Fitzgerald return -EINVAL;
1664e2bcbf99SRichard Fitzgerald }
1665e2bcbf99SRichard Fitzgerald }
1666e2bcbf99SRichard Fitzgerald while (frac && (ratio / fbdiv > max_n)) {
1667e2bcbf99SRichard Fitzgerald fbdiv *= 2;
1668e2bcbf99SRichard Fitzgerald if (fbdiv >= 1024) {
1669e2bcbf99SRichard Fitzgerald cs48l32_fll_err(fll, "FBDIV (%u) >= 1024\n", fbdiv);
1670e2bcbf99SRichard Fitzgerald return -EINVAL;
1671e2bcbf99SRichard Fitzgerald }
1672e2bcbf99SRichard Fitzgerald }
1673e2bcbf99SRichard Fitzgerald
1674e2bcbf99SRichard Fitzgerald cs48l32_fll_dbg(fll, "lockdet=%d, hp=#%x, fbdiv:%d\n", lockdet_thr, hp, fbdiv);
1675e2bcbf99SRichard Fitzgerald
1676e2bcbf99SRichard Fitzgerald /* Calculate N.K values */
1677e2bcbf99SRichard Fitzgerald fllgcd = gcd(fout, fbdiv * fref);
1678e2bcbf99SRichard Fitzgerald num = fout / fllgcd;
1679e2bcbf99SRichard Fitzgerald lambda = (fref * fbdiv) / fllgcd;
1680e2bcbf99SRichard Fitzgerald fll_n = num / lambda;
1681e2bcbf99SRichard Fitzgerald theta = num % lambda;
1682e2bcbf99SRichard Fitzgerald
1683e2bcbf99SRichard Fitzgerald cs48l32_fll_dbg(fll, "fll_n=%d, gcd=%d, theta=%d, lambda=%d\n",
1684e2bcbf99SRichard Fitzgerald fll_n, fllgcd, theta, lambda);
1685e2bcbf99SRichard Fitzgerald
1686e2bcbf99SRichard Fitzgerald /* Some sanity checks before any registers are written. */
1687e2bcbf99SRichard Fitzgerald if (fll_n < min_n || fll_n > max_n) {
1688e2bcbf99SRichard Fitzgerald cs48l32_fll_err(fll, "N not in valid %s mode range %d-%d: %d\n",
1689e2bcbf99SRichard Fitzgerald frac ? "fractional" : "integer", min_n, max_n, fll_n);
1690e2bcbf99SRichard Fitzgerald return -EINVAL;
1691e2bcbf99SRichard Fitzgerald }
1692e2bcbf99SRichard Fitzgerald if (fbdiv < 1 || (frac && fbdiv >= 1024) || (!frac && fbdiv >= 256)) {
1693e2bcbf99SRichard Fitzgerald cs48l32_fll_err(fll, "Invalid fbdiv for %s mode (%u)\n",
1694e2bcbf99SRichard Fitzgerald frac ? "fractional" : "integer", fbdiv);
1695e2bcbf99SRichard Fitzgerald return -EINVAL;
1696e2bcbf99SRichard Fitzgerald }
1697e2bcbf99SRichard Fitzgerald
1698e2bcbf99SRichard Fitzgerald /* clear the ctrl_upd bit to guarantee we write to it later. */
1699e2bcbf99SRichard Fitzgerald regmap_update_bits(regmap,
1700e2bcbf99SRichard Fitzgerald fll->base + CS48L32_FLL_CONTROL2_OFFS,
1701e2bcbf99SRichard Fitzgerald CS48L32_FLL_LOCKDET_THR_MASK |
1702e2bcbf99SRichard Fitzgerald CS48L32_FLL_PHASEDET_MASK |
1703e2bcbf99SRichard Fitzgerald CS48L32_FLL_REFCLK_DIV_MASK |
1704e2bcbf99SRichard Fitzgerald CS48L32_FLL_N_MASK |
1705e2bcbf99SRichard Fitzgerald CS48L32_FLL_CTRL_UPD_MASK,
1706e2bcbf99SRichard Fitzgerald (lockdet_thr << CS48L32_FLL_LOCKDET_THR_SHIFT) |
1707e2bcbf99SRichard Fitzgerald (1 << CS48L32_FLL_PHASEDET_SHIFT) |
1708e2bcbf99SRichard Fitzgerald (refdiv << CS48L32_FLL_REFCLK_DIV_SHIFT) |
1709e2bcbf99SRichard Fitzgerald (fll_n << CS48L32_FLL_N_SHIFT));
1710e2bcbf99SRichard Fitzgerald
1711e2bcbf99SRichard Fitzgerald regmap_update_bits(regmap,
1712e2bcbf99SRichard Fitzgerald fll->base + CS48L32_FLL_CONTROL3_OFFS,
1713e2bcbf99SRichard Fitzgerald CS48L32_FLL_LAMBDA_MASK |
1714e2bcbf99SRichard Fitzgerald CS48L32_FLL_THETA_MASK,
1715e2bcbf99SRichard Fitzgerald (lambda << CS48L32_FLL_LAMBDA_SHIFT) |
1716e2bcbf99SRichard Fitzgerald (theta << CS48L32_FLL_THETA_SHIFT));
1717e2bcbf99SRichard Fitzgerald
1718e2bcbf99SRichard Fitzgerald regmap_update_bits(regmap,
1719e2bcbf99SRichard Fitzgerald fll->base + CS48L32_FLL_CONTROL4_OFFS,
1720e2bcbf99SRichard Fitzgerald (0xffff << CS48L32_FLL_FD_GAIN_COARSE_SHIFT) |
1721e2bcbf99SRichard Fitzgerald CS48L32_FLL_HP_MASK |
1722e2bcbf99SRichard Fitzgerald CS48L32_FLL_FB_DIV_MASK,
1723e2bcbf99SRichard Fitzgerald (gains << CS48L32_FLL_FD_GAIN_COARSE_SHIFT) |
1724e2bcbf99SRichard Fitzgerald (hp << CS48L32_FLL_HP_SHIFT) |
1725e2bcbf99SRichard Fitzgerald (fbdiv << CS48L32_FLL_FB_DIV_SHIFT));
1726e2bcbf99SRichard Fitzgerald
1727e2bcbf99SRichard Fitzgerald return 0;
1728e2bcbf99SRichard Fitzgerald }
1729e2bcbf99SRichard Fitzgerald
cs48l32_fllhj_enable(struct cs48l32_fll * fll)1730e2bcbf99SRichard Fitzgerald static int cs48l32_fllhj_enable(struct cs48l32_fll *fll)
1731e2bcbf99SRichard Fitzgerald {
1732e2bcbf99SRichard Fitzgerald struct cs48l32 *cs48l32 = &fll->codec->core;
1733e2bcbf99SRichard Fitzgerald int already_enabled = cs48l32_is_enabled_fll(fll, fll->base);
1734e2bcbf99SRichard Fitzgerald int ret;
1735e2bcbf99SRichard Fitzgerald
1736e2bcbf99SRichard Fitzgerald if (already_enabled < 0)
1737e2bcbf99SRichard Fitzgerald return already_enabled;
1738e2bcbf99SRichard Fitzgerald
1739e2bcbf99SRichard Fitzgerald if (!already_enabled)
1740e2bcbf99SRichard Fitzgerald pm_runtime_get_sync(cs48l32->dev);
1741e2bcbf99SRichard Fitzgerald
1742e2bcbf99SRichard Fitzgerald cs48l32_fll_dbg(fll, "Enabling FLL, initially %s\n",
1743e2bcbf99SRichard Fitzgerald str_enabled_disabled(already_enabled));
1744e2bcbf99SRichard Fitzgerald
1745e2bcbf99SRichard Fitzgerald /* FLLn_HOLD must be set before configuring any registers */
1746e2bcbf99SRichard Fitzgerald regmap_set_bits(cs48l32->regmap,
1747e2bcbf99SRichard Fitzgerald fll->base + CS48L32_FLL_CONTROL1_OFFS,
1748e2bcbf99SRichard Fitzgerald CS48L32_FLL_HOLD_MASK);
1749e2bcbf99SRichard Fitzgerald
1750e2bcbf99SRichard Fitzgerald /* Apply refclk */
1751e2bcbf99SRichard Fitzgerald ret = cs48l32_fllhj_apply(fll, fll->ref_freq);
1752e2bcbf99SRichard Fitzgerald if (ret) {
1753e2bcbf99SRichard Fitzgerald cs48l32_fll_err(fll, "Failed to set FLL: %d\n", ret);
1754e2bcbf99SRichard Fitzgerald goto out;
1755e2bcbf99SRichard Fitzgerald }
1756e2bcbf99SRichard Fitzgerald regmap_update_bits(cs48l32->regmap,
1757e2bcbf99SRichard Fitzgerald fll->base + CS48L32_FLL_CONTROL2_OFFS,
1758e2bcbf99SRichard Fitzgerald CS48L32_FLL_REFCLK_SRC_MASK,
1759e2bcbf99SRichard Fitzgerald fll->ref_src << CS48L32_FLL_REFCLK_SRC_SHIFT);
1760e2bcbf99SRichard Fitzgerald
1761e2bcbf99SRichard Fitzgerald regmap_set_bits(cs48l32->regmap,
1762e2bcbf99SRichard Fitzgerald fll->base + CS48L32_FLL_CONTROL1_OFFS,
1763e2bcbf99SRichard Fitzgerald CS48L32_FLL_EN_MASK);
1764e2bcbf99SRichard Fitzgerald
1765e2bcbf99SRichard Fitzgerald out:
1766e2bcbf99SRichard Fitzgerald regmap_set_bits(cs48l32->regmap,
1767e2bcbf99SRichard Fitzgerald fll->base + CS48L32_FLL_CONTROL2_OFFS,
1768e2bcbf99SRichard Fitzgerald CS48L32_FLL_LOCKDET_MASK);
1769e2bcbf99SRichard Fitzgerald
1770e2bcbf99SRichard Fitzgerald regmap_set_bits(cs48l32->regmap,
1771e2bcbf99SRichard Fitzgerald fll->base + CS48L32_FLL_CONTROL1_OFFS,
1772e2bcbf99SRichard Fitzgerald CS48L32_FLL_CTRL_UPD_MASK);
1773e2bcbf99SRichard Fitzgerald
1774e2bcbf99SRichard Fitzgerald /* Release the hold so that flln locks to external frequency */
1775e2bcbf99SRichard Fitzgerald regmap_clear_bits(cs48l32->regmap,
1776e2bcbf99SRichard Fitzgerald fll->base + CS48L32_FLL_CONTROL1_OFFS,
1777e2bcbf99SRichard Fitzgerald CS48L32_FLL_HOLD_MASK);
1778e2bcbf99SRichard Fitzgerald
1779e2bcbf99SRichard Fitzgerald if (!already_enabled)
1780e2bcbf99SRichard Fitzgerald cs48l32_wait_for_fll(fll, true);
1781e2bcbf99SRichard Fitzgerald
1782e2bcbf99SRichard Fitzgerald return 0;
1783e2bcbf99SRichard Fitzgerald }
1784e2bcbf99SRichard Fitzgerald
cs48l32_fllhj_validate(struct cs48l32_fll * fll,unsigned int ref_in,unsigned int fout)1785e2bcbf99SRichard Fitzgerald static int cs48l32_fllhj_validate(struct cs48l32_fll *fll,
1786e2bcbf99SRichard Fitzgerald unsigned int ref_in,
1787e2bcbf99SRichard Fitzgerald unsigned int fout)
1788e2bcbf99SRichard Fitzgerald {
1789e2bcbf99SRichard Fitzgerald if (fout && !ref_in) {
1790e2bcbf99SRichard Fitzgerald cs48l32_fll_err(fll, "fllout set without valid input clk\n");
1791e2bcbf99SRichard Fitzgerald return -EINVAL;
1792e2bcbf99SRichard Fitzgerald }
1793e2bcbf99SRichard Fitzgerald
1794e2bcbf99SRichard Fitzgerald if (fll->fout && fout != fll->fout) {
1795e2bcbf99SRichard Fitzgerald cs48l32_fll_err(fll, "Can't change output on active FLL\n");
1796e2bcbf99SRichard Fitzgerald return -EINVAL;
1797e2bcbf99SRichard Fitzgerald }
1798e2bcbf99SRichard Fitzgerald
1799e2bcbf99SRichard Fitzgerald if (ref_in / CS48L32_FLL_MAX_REFDIV > CS48L32_FLLHJ_MAX_THRESH) {
1800e2bcbf99SRichard Fitzgerald cs48l32_fll_err(fll, "Can't scale %dMHz to <=13MHz\n", ref_in);
1801e2bcbf99SRichard Fitzgerald return -EINVAL;
1802e2bcbf99SRichard Fitzgerald }
1803e2bcbf99SRichard Fitzgerald
1804e2bcbf99SRichard Fitzgerald if (fout > CS48L32_FLL_MAX_FOUT) {
18057ed50dc5SColin Ian King cs48l32_fll_err(fll, "Fout=%dMHz exceeds maximum %dMHz\n",
1806e2bcbf99SRichard Fitzgerald fout, CS48L32_FLL_MAX_FOUT);
1807e2bcbf99SRichard Fitzgerald return -EINVAL;
1808e2bcbf99SRichard Fitzgerald }
1809e2bcbf99SRichard Fitzgerald
1810e2bcbf99SRichard Fitzgerald return 0;
1811e2bcbf99SRichard Fitzgerald }
1812e2bcbf99SRichard Fitzgerald
cs48l32_fllhj_set_refclk(struct cs48l32_fll * fll,int source,unsigned int fin,unsigned int fout)1813e2bcbf99SRichard Fitzgerald static int cs48l32_fllhj_set_refclk(struct cs48l32_fll *fll, int source,
1814e2bcbf99SRichard Fitzgerald unsigned int fin, unsigned int fout)
1815e2bcbf99SRichard Fitzgerald {
1816e2bcbf99SRichard Fitzgerald int ret = 0;
1817e2bcbf99SRichard Fitzgerald
1818e2bcbf99SRichard Fitzgerald if (fll->ref_src == source && fll->ref_freq == fin && fll->fout == fout)
1819e2bcbf99SRichard Fitzgerald return 0;
1820e2bcbf99SRichard Fitzgerald
1821e2bcbf99SRichard Fitzgerald if (fin && fout && cs48l32_fllhj_validate(fll, fin, fout))
1822e2bcbf99SRichard Fitzgerald return -EINVAL;
1823e2bcbf99SRichard Fitzgerald
1824e2bcbf99SRichard Fitzgerald fll->ref_src = source;
1825e2bcbf99SRichard Fitzgerald fll->ref_freq = fin;
1826e2bcbf99SRichard Fitzgerald fll->fout = fout;
1827e2bcbf99SRichard Fitzgerald
1828e2bcbf99SRichard Fitzgerald if (fout)
1829e2bcbf99SRichard Fitzgerald ret = cs48l32_fllhj_enable(fll);
1830e2bcbf99SRichard Fitzgerald else
1831e2bcbf99SRichard Fitzgerald cs48l32_fllhj_disable(fll);
1832e2bcbf99SRichard Fitzgerald
1833e2bcbf99SRichard Fitzgerald return ret;
1834e2bcbf99SRichard Fitzgerald }
1835e2bcbf99SRichard Fitzgerald
cs48l32_init_fll(struct cs48l32_fll * fll)1836e2bcbf99SRichard Fitzgerald static int cs48l32_init_fll(struct cs48l32_fll *fll)
1837e2bcbf99SRichard Fitzgerald {
1838e2bcbf99SRichard Fitzgerald fll->ref_src = CS48L32_FLL_SRC_NONE;
1839e2bcbf99SRichard Fitzgerald
1840e2bcbf99SRichard Fitzgerald return 0;
1841e2bcbf99SRichard Fitzgerald }
1842e2bcbf99SRichard Fitzgerald
cs48l32_set_fll(struct snd_soc_component * component,int fll_id,int source,unsigned int fref,unsigned int fout)1843e2bcbf99SRichard Fitzgerald static int cs48l32_set_fll(struct snd_soc_component *component, int fll_id,
1844e2bcbf99SRichard Fitzgerald int source, unsigned int fref, unsigned int fout)
1845e2bcbf99SRichard Fitzgerald {
1846e2bcbf99SRichard Fitzgerald struct cs48l32_codec *cs48l32_codec = snd_soc_component_get_drvdata(component);
1847e2bcbf99SRichard Fitzgerald
1848e2bcbf99SRichard Fitzgerald switch (fll_id) {
1849e2bcbf99SRichard Fitzgerald case CS48L32_FLL1_REFCLK:
1850e2bcbf99SRichard Fitzgerald break;
1851e2bcbf99SRichard Fitzgerald default:
1852e2bcbf99SRichard Fitzgerald return -EINVAL;
1853e2bcbf99SRichard Fitzgerald }
1854e2bcbf99SRichard Fitzgerald
1855e2bcbf99SRichard Fitzgerald return cs48l32_fllhj_set_refclk(&cs48l32_codec->fll, source, fref, fout);
1856e2bcbf99SRichard Fitzgerald }
1857e2bcbf99SRichard Fitzgerald
cs48l32_asp_dai_probe(struct snd_soc_dai * dai)1858e2bcbf99SRichard Fitzgerald static int cs48l32_asp_dai_probe(struct snd_soc_dai *dai)
1859e2bcbf99SRichard Fitzgerald {
1860e2bcbf99SRichard Fitzgerald struct snd_soc_component *component = dai->component;
1861e2bcbf99SRichard Fitzgerald struct cs48l32_codec *cs48l32_codec = snd_soc_component_get_drvdata(component);
1862e2bcbf99SRichard Fitzgerald struct regmap *regmap = cs48l32_codec->core.regmap;
1863e2bcbf99SRichard Fitzgerald unsigned int pin_reg, last_pin_reg, hiz_reg;
1864e2bcbf99SRichard Fitzgerald
1865e2bcbf99SRichard Fitzgerald switch (dai->id) {
1866e2bcbf99SRichard Fitzgerald case 1:
1867e2bcbf99SRichard Fitzgerald pin_reg = CS48L32_GPIO3_CTRL1;
1868e2bcbf99SRichard Fitzgerald hiz_reg = CS48L32_ASP1_CONTROL3;
1869e2bcbf99SRichard Fitzgerald break;
1870e2bcbf99SRichard Fitzgerald case 2:
1871e2bcbf99SRichard Fitzgerald pin_reg = CS48L32_GPIO7_CTRL1;
1872e2bcbf99SRichard Fitzgerald hiz_reg = CS48L32_ASP2_CONTROL3;
1873e2bcbf99SRichard Fitzgerald break;
1874e2bcbf99SRichard Fitzgerald default:
1875e2bcbf99SRichard Fitzgerald return -EINVAL;
1876e2bcbf99SRichard Fitzgerald }
1877e2bcbf99SRichard Fitzgerald
1878e2bcbf99SRichard Fitzgerald for (last_pin_reg = pin_reg + 12; pin_reg <= last_pin_reg; ++pin_reg)
1879e2bcbf99SRichard Fitzgerald regmap_clear_bits(regmap, pin_reg, CS48L32_GPIOX_CTRL1_FN_MASK);
1880e2bcbf99SRichard Fitzgerald
1881e2bcbf99SRichard Fitzgerald /* DOUT high-impendance when not transmitting */
1882e2bcbf99SRichard Fitzgerald regmap_set_bits(regmap, hiz_reg, CS48L32_ASP_DOUT_HIZ_MASK);
1883e2bcbf99SRichard Fitzgerald
1884e2bcbf99SRichard Fitzgerald return 0;
1885e2bcbf99SRichard Fitzgerald }
1886e2bcbf99SRichard Fitzgerald
cs48l32_set_fmt(struct snd_soc_dai * dai,unsigned int fmt)1887e2bcbf99SRichard Fitzgerald static int cs48l32_set_fmt(struct snd_soc_dai *dai, unsigned int fmt)
1888e2bcbf99SRichard Fitzgerald {
1889e2bcbf99SRichard Fitzgerald struct snd_soc_component *component = dai->component;
1890e2bcbf99SRichard Fitzgerald struct cs48l32_codec *cs48l32_codec = snd_soc_component_get_drvdata(component);
1891e2bcbf99SRichard Fitzgerald struct regmap *regmap = cs48l32_codec->core.regmap;
1892e2bcbf99SRichard Fitzgerald unsigned int val = 0U;
1893e2bcbf99SRichard Fitzgerald unsigned int base = dai->driver->base;
1894e2bcbf99SRichard Fitzgerald unsigned int mask = CS48L32_ASP_FMT_MASK | CS48L32_ASP_BCLK_INV_MASK |
1895e2bcbf99SRichard Fitzgerald CS48L32_ASP_BCLK_MSTR_MASK |
1896e2bcbf99SRichard Fitzgerald CS48L32_ASP_FSYNC_INV_MASK |
1897e2bcbf99SRichard Fitzgerald CS48L32_ASP_FSYNC_MSTR_MASK;
1898e2bcbf99SRichard Fitzgerald
1899e2bcbf99SRichard Fitzgerald switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
1900e2bcbf99SRichard Fitzgerald case SND_SOC_DAIFMT_DSP_A:
1901e2bcbf99SRichard Fitzgerald val |= (CS48L32_ASP_FMT_DSP_MODE_A << CS48L32_ASP_FMT_SHIFT);
1902e2bcbf99SRichard Fitzgerald break;
1903e2bcbf99SRichard Fitzgerald case SND_SOC_DAIFMT_DSP_B:
1904e2bcbf99SRichard Fitzgerald if ((fmt & SND_SOC_DAIFMT_CLOCK_PROVIDER_MASK) != SND_SOC_DAIFMT_BP_FP) {
1905e2bcbf99SRichard Fitzgerald cs48l32_asp_err(dai, "DSP_B cannot be clock consumer\n");
1906e2bcbf99SRichard Fitzgerald return -EINVAL;
1907e2bcbf99SRichard Fitzgerald }
1908e2bcbf99SRichard Fitzgerald val |= (CS48L32_ASP_FMT_DSP_MODE_B << CS48L32_ASP_FMT_SHIFT);
1909e2bcbf99SRichard Fitzgerald break;
1910e2bcbf99SRichard Fitzgerald case SND_SOC_DAIFMT_I2S:
1911e2bcbf99SRichard Fitzgerald val |= (CS48L32_ASP_FMT_I2S_MODE << CS48L32_ASP_FMT_SHIFT);
1912e2bcbf99SRichard Fitzgerald break;
1913e2bcbf99SRichard Fitzgerald case SND_SOC_DAIFMT_LEFT_J:
1914e2bcbf99SRichard Fitzgerald if ((fmt & SND_SOC_DAIFMT_CLOCK_PROVIDER_MASK) != SND_SOC_DAIFMT_BP_FP) {
1915e2bcbf99SRichard Fitzgerald cs48l32_asp_err(dai, "LEFT_J cannot be clock consumer\n");
1916e2bcbf99SRichard Fitzgerald return -EINVAL;
1917e2bcbf99SRichard Fitzgerald }
1918e2bcbf99SRichard Fitzgerald val |= (CS48L32_ASP_FMT_LEFT_JUSTIFIED_MODE << CS48L32_ASP_FMT_SHIFT);
1919e2bcbf99SRichard Fitzgerald break;
1920e2bcbf99SRichard Fitzgerald default:
1921e2bcbf99SRichard Fitzgerald cs48l32_asp_err(dai, "Unsupported DAI format %d\n",
1922e2bcbf99SRichard Fitzgerald fmt & SND_SOC_DAIFMT_FORMAT_MASK);
1923e2bcbf99SRichard Fitzgerald return -EINVAL;
1924e2bcbf99SRichard Fitzgerald }
1925e2bcbf99SRichard Fitzgerald
1926e2bcbf99SRichard Fitzgerald switch (fmt & SND_SOC_DAIFMT_CLOCK_PROVIDER_MASK) {
1927e2bcbf99SRichard Fitzgerald case SND_SOC_DAIFMT_BC_FC:
1928e2bcbf99SRichard Fitzgerald break;
1929e2bcbf99SRichard Fitzgerald case SND_SOC_DAIFMT_BC_FP:
1930e2bcbf99SRichard Fitzgerald val |= CS48L32_ASP_FSYNC_MSTR_MASK;
1931e2bcbf99SRichard Fitzgerald break;
1932e2bcbf99SRichard Fitzgerald case SND_SOC_DAIFMT_BP_FC:
1933e2bcbf99SRichard Fitzgerald val |= CS48L32_ASP_BCLK_MSTR_MASK;
1934e2bcbf99SRichard Fitzgerald break;
1935e2bcbf99SRichard Fitzgerald case SND_SOC_DAIFMT_BP_FP:
1936e2bcbf99SRichard Fitzgerald val |= CS48L32_ASP_BCLK_MSTR_MASK;
1937e2bcbf99SRichard Fitzgerald val |= CS48L32_ASP_FSYNC_MSTR_MASK;
1938e2bcbf99SRichard Fitzgerald break;
1939e2bcbf99SRichard Fitzgerald default:
1940e2bcbf99SRichard Fitzgerald cs48l32_asp_err(dai, "Unsupported clock direction %d\n",
1941e2bcbf99SRichard Fitzgerald fmt & SND_SOC_DAIFMT_CLOCK_PROVIDER_MASK);
1942e2bcbf99SRichard Fitzgerald return -EINVAL;
1943e2bcbf99SRichard Fitzgerald }
1944e2bcbf99SRichard Fitzgerald
1945e2bcbf99SRichard Fitzgerald switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
1946e2bcbf99SRichard Fitzgerald case SND_SOC_DAIFMT_NB_NF:
1947e2bcbf99SRichard Fitzgerald break;
1948e2bcbf99SRichard Fitzgerald case SND_SOC_DAIFMT_IB_IF:
1949e2bcbf99SRichard Fitzgerald val |= CS48L32_ASP_BCLK_INV_MASK;
1950e2bcbf99SRichard Fitzgerald val |= CS48L32_ASP_FSYNC_INV_MASK;
1951e2bcbf99SRichard Fitzgerald break;
1952e2bcbf99SRichard Fitzgerald case SND_SOC_DAIFMT_IB_NF:
1953e2bcbf99SRichard Fitzgerald val |= CS48L32_ASP_BCLK_INV_MASK;
1954e2bcbf99SRichard Fitzgerald break;
1955e2bcbf99SRichard Fitzgerald case SND_SOC_DAIFMT_NB_IF:
1956e2bcbf99SRichard Fitzgerald val |= CS48L32_ASP_FSYNC_INV_MASK;
1957e2bcbf99SRichard Fitzgerald break;
1958e2bcbf99SRichard Fitzgerald default:
1959e2bcbf99SRichard Fitzgerald return -EINVAL;
1960e2bcbf99SRichard Fitzgerald }
1961e2bcbf99SRichard Fitzgerald
1962e2bcbf99SRichard Fitzgerald regmap_update_bits(regmap, base + CS48L32_ASP_CONTROL2, mask, val);
1963e2bcbf99SRichard Fitzgerald
1964e2bcbf99SRichard Fitzgerald return 0;
1965e2bcbf99SRichard Fitzgerald }
1966e2bcbf99SRichard Fitzgerald
1967e2bcbf99SRichard Fitzgerald static const struct {
1968e2bcbf99SRichard Fitzgerald u32 freq;
1969e2bcbf99SRichard Fitzgerald u32 id;
1970e2bcbf99SRichard Fitzgerald } cs48l32_sclk_rates[] = {
1971e2bcbf99SRichard Fitzgerald { 128000, 12 },
1972e2bcbf99SRichard Fitzgerald { 176400, 13 },
1973e2bcbf99SRichard Fitzgerald { 192000, 14 },
1974e2bcbf99SRichard Fitzgerald { 256000, 15 },
1975e2bcbf99SRichard Fitzgerald { 352800, 16 },
1976e2bcbf99SRichard Fitzgerald { 384000, 17 },
1977e2bcbf99SRichard Fitzgerald { 512000, 18 },
1978e2bcbf99SRichard Fitzgerald { 705600, 19 },
1979e2bcbf99SRichard Fitzgerald { 768000, 21 },
1980e2bcbf99SRichard Fitzgerald { 1024000, 23 },
1981e2bcbf99SRichard Fitzgerald { 1411200, 25 },
1982e2bcbf99SRichard Fitzgerald { 1536000, 27 },
1983e2bcbf99SRichard Fitzgerald { 2048000, 29 },
1984e2bcbf99SRichard Fitzgerald { 2822400, 31 },
1985e2bcbf99SRichard Fitzgerald { 3072000, 33 },
1986e2bcbf99SRichard Fitzgerald { 4096000, 36 },
1987e2bcbf99SRichard Fitzgerald { 5644800, 38 },
1988e2bcbf99SRichard Fitzgerald { 6144000, 40 },
1989e2bcbf99SRichard Fitzgerald { 8192000, 47 },
1990e2bcbf99SRichard Fitzgerald { 11289600, 49 },
1991e2bcbf99SRichard Fitzgerald { 12288000, 51 },
1992e2bcbf99SRichard Fitzgerald { 22579200, 57 },
1993e2bcbf99SRichard Fitzgerald { 24576000, 59 },
1994e2bcbf99SRichard Fitzgerald };
1995e2bcbf99SRichard Fitzgerald
1996e2bcbf99SRichard Fitzgerald #define CS48L32_48K_RATE_MASK 0x0e00fe
1997e2bcbf99SRichard Fitzgerald #define CS48L32_44K1_RATE_MASK 0x00fe00
1998e2bcbf99SRichard Fitzgerald #define CS48L32_RATE_MASK (CS48L32_48K_RATE_MASK | CS48L32_44K1_RATE_MASK)
1999e2bcbf99SRichard Fitzgerald
2000e2bcbf99SRichard Fitzgerald static const unsigned int cs48l32_sr_vals[] = {
2001e2bcbf99SRichard Fitzgerald 0,
2002e2bcbf99SRichard Fitzgerald 12000, /* CS48L32_48K_RATE_MASK */
2003e2bcbf99SRichard Fitzgerald 24000, /* CS48L32_48K_RATE_MASK */
2004e2bcbf99SRichard Fitzgerald 48000, /* CS48L32_48K_RATE_MASK */
2005e2bcbf99SRichard Fitzgerald 96000, /* CS48L32_48K_RATE_MASK */
2006e2bcbf99SRichard Fitzgerald 192000, /* CS48L32_48K_RATE_MASK */
2007e2bcbf99SRichard Fitzgerald 384000, /* CS48L32_48K_RATE_MASK */
2008e2bcbf99SRichard Fitzgerald 768000, /* CS48L32_48K_RATE_MASK */
2009e2bcbf99SRichard Fitzgerald 0,
2010e2bcbf99SRichard Fitzgerald 11025, /* CS48L32_44K1_RATE_MASK */
2011e2bcbf99SRichard Fitzgerald 22050, /* CS48L32_44K1_RATE_MASK */
2012e2bcbf99SRichard Fitzgerald 44100, /* CS48L32_44K1_RATE_MASK */
2013e2bcbf99SRichard Fitzgerald 88200, /* CS48L32_44K1_RATE_MASK */
2014e2bcbf99SRichard Fitzgerald 176400, /* CS48L32_44K1_RATE_MASK */
2015e2bcbf99SRichard Fitzgerald 352800, /* CS48L32_44K1_RATE_MASK */
2016e2bcbf99SRichard Fitzgerald 705600, /* CS48L32_44K1_RATE_MASK */
2017e2bcbf99SRichard Fitzgerald 0,
2018e2bcbf99SRichard Fitzgerald 8000, /* CS48L32_48K_RATE_MASK */
2019e2bcbf99SRichard Fitzgerald 16000, /* CS48L32_48K_RATE_MASK */
2020e2bcbf99SRichard Fitzgerald 32000, /* CS48L32_48K_RATE_MASK */
2021e2bcbf99SRichard Fitzgerald };
2022e2bcbf99SRichard Fitzgerald
2023e2bcbf99SRichard Fitzgerald static const struct snd_pcm_hw_constraint_list cs48l32_constraint = {
2024e2bcbf99SRichard Fitzgerald .count = ARRAY_SIZE(cs48l32_sr_vals),
2025e2bcbf99SRichard Fitzgerald .list = cs48l32_sr_vals,
2026e2bcbf99SRichard Fitzgerald };
2027e2bcbf99SRichard Fitzgerald
cs48l32_startup(struct snd_pcm_substream * substream,struct snd_soc_dai * dai)2028e2bcbf99SRichard Fitzgerald static int cs48l32_startup(struct snd_pcm_substream *substream, struct snd_soc_dai *dai)
2029e2bcbf99SRichard Fitzgerald {
2030e2bcbf99SRichard Fitzgerald struct snd_soc_component *component = dai->component;
2031e2bcbf99SRichard Fitzgerald struct cs48l32_codec *cs48l32_codec = snd_soc_component_get_drvdata(component);
2032e2bcbf99SRichard Fitzgerald struct cs48l32_dai_priv *dai_priv = &cs48l32_codec->dai[dai->id - 1];
2033e2bcbf99SRichard Fitzgerald unsigned int base_rate;
2034e2bcbf99SRichard Fitzgerald
2035e2bcbf99SRichard Fitzgerald if (!substream->runtime)
2036e2bcbf99SRichard Fitzgerald return 0;
2037e2bcbf99SRichard Fitzgerald
2038e2bcbf99SRichard Fitzgerald switch (dai_priv->clk) {
2039e2bcbf99SRichard Fitzgerald case CS48L32_CLK_SYSCLK_1:
2040e2bcbf99SRichard Fitzgerald case CS48L32_CLK_SYSCLK_2:
2041e2bcbf99SRichard Fitzgerald case CS48L32_CLK_SYSCLK_3:
2042e2bcbf99SRichard Fitzgerald case CS48L32_CLK_SYSCLK_4:
2043e2bcbf99SRichard Fitzgerald base_rate = cs48l32_codec->sysclk;
2044e2bcbf99SRichard Fitzgerald break;
2045e2bcbf99SRichard Fitzgerald default:
2046e2bcbf99SRichard Fitzgerald return 0;
2047e2bcbf99SRichard Fitzgerald }
2048e2bcbf99SRichard Fitzgerald
2049e2bcbf99SRichard Fitzgerald if (base_rate == 0)
2050e2bcbf99SRichard Fitzgerald dai_priv->constraint.mask = CS48L32_RATE_MASK;
2051e2bcbf99SRichard Fitzgerald else if (base_rate % 4000)
2052e2bcbf99SRichard Fitzgerald dai_priv->constraint.mask = CS48L32_44K1_RATE_MASK;
2053e2bcbf99SRichard Fitzgerald else
2054e2bcbf99SRichard Fitzgerald dai_priv->constraint.mask = CS48L32_48K_RATE_MASK;
2055e2bcbf99SRichard Fitzgerald
2056e2bcbf99SRichard Fitzgerald return snd_pcm_hw_constraint_list(substream->runtime, 0,
2057e2bcbf99SRichard Fitzgerald SNDRV_PCM_HW_PARAM_RATE,
2058e2bcbf99SRichard Fitzgerald &dai_priv->constraint);
2059e2bcbf99SRichard Fitzgerald }
2060e2bcbf99SRichard Fitzgerald
cs48l32_hw_params_rate(struct snd_pcm_substream * substream,struct snd_pcm_hw_params * params,struct snd_soc_dai * dai)2061e2bcbf99SRichard Fitzgerald static int cs48l32_hw_params_rate(struct snd_pcm_substream *substream,
2062e2bcbf99SRichard Fitzgerald struct snd_pcm_hw_params *params,
2063e2bcbf99SRichard Fitzgerald struct snd_soc_dai *dai)
2064e2bcbf99SRichard Fitzgerald {
2065e2bcbf99SRichard Fitzgerald struct snd_soc_component *component = dai->component;
2066e2bcbf99SRichard Fitzgerald struct cs48l32_codec *cs48l32_codec = snd_soc_component_get_drvdata(component);
2067e2bcbf99SRichard Fitzgerald struct cs48l32_dai_priv *dai_priv = &cs48l32_codec->dai[dai->id - 1];
2068e2bcbf99SRichard Fitzgerald unsigned int sr_val, sr_reg, rate;
2069e2bcbf99SRichard Fitzgerald
2070e2bcbf99SRichard Fitzgerald rate = params_rate(params);
2071e2bcbf99SRichard Fitzgerald for (sr_val = 0; sr_val < ARRAY_SIZE(cs48l32_sr_vals); sr_val++)
2072e2bcbf99SRichard Fitzgerald if (cs48l32_sr_vals[sr_val] == rate)
2073e2bcbf99SRichard Fitzgerald break;
2074e2bcbf99SRichard Fitzgerald
2075e2bcbf99SRichard Fitzgerald if (sr_val == ARRAY_SIZE(cs48l32_sr_vals)) {
2076e2bcbf99SRichard Fitzgerald cs48l32_asp_err(dai, "Unsupported sample rate %dHz\n", rate);
2077e2bcbf99SRichard Fitzgerald return -EINVAL;
2078e2bcbf99SRichard Fitzgerald }
2079e2bcbf99SRichard Fitzgerald
2080e2bcbf99SRichard Fitzgerald switch (dai_priv->clk) {
2081e2bcbf99SRichard Fitzgerald case CS48L32_CLK_SYSCLK_1:
2082e2bcbf99SRichard Fitzgerald sr_reg = CS48L32_SAMPLE_RATE1;
2083e2bcbf99SRichard Fitzgerald break;
2084e2bcbf99SRichard Fitzgerald case CS48L32_CLK_SYSCLK_2:
2085e2bcbf99SRichard Fitzgerald sr_reg = CS48L32_SAMPLE_RATE2;
2086e2bcbf99SRichard Fitzgerald break;
2087e2bcbf99SRichard Fitzgerald case CS48L32_CLK_SYSCLK_3:
2088e2bcbf99SRichard Fitzgerald sr_reg = CS48L32_SAMPLE_RATE3;
2089e2bcbf99SRichard Fitzgerald break;
2090e2bcbf99SRichard Fitzgerald case CS48L32_CLK_SYSCLK_4:
2091e2bcbf99SRichard Fitzgerald sr_reg = CS48L32_SAMPLE_RATE4;
2092e2bcbf99SRichard Fitzgerald break;
2093e2bcbf99SRichard Fitzgerald default:
2094e2bcbf99SRichard Fitzgerald return -EINVAL;
2095e2bcbf99SRichard Fitzgerald }
2096e2bcbf99SRichard Fitzgerald
2097e2bcbf99SRichard Fitzgerald snd_soc_component_update_bits(component, sr_reg, CS48L32_SAMPLE_RATE_1_MASK, sr_val);
2098e2bcbf99SRichard Fitzgerald
2099e2bcbf99SRichard Fitzgerald return 0;
2100e2bcbf99SRichard Fitzgerald }
2101e2bcbf99SRichard Fitzgerald
cs48l32_asp_cfg_changed(struct snd_soc_component * component,unsigned int base,unsigned int sclk,unsigned int slotws,unsigned int dataw)2102e2bcbf99SRichard Fitzgerald static bool cs48l32_asp_cfg_changed(struct snd_soc_component *component,
2103e2bcbf99SRichard Fitzgerald unsigned int base, unsigned int sclk,
2104e2bcbf99SRichard Fitzgerald unsigned int slotws, unsigned int dataw)
2105e2bcbf99SRichard Fitzgerald {
2106e2bcbf99SRichard Fitzgerald unsigned int val;
2107e2bcbf99SRichard Fitzgerald
2108e2bcbf99SRichard Fitzgerald val = snd_soc_component_read(component, base + CS48L32_ASP_CONTROL1);
2109e2bcbf99SRichard Fitzgerald if (sclk != (val & CS48L32_ASP_BCLK_FREQ_MASK))
2110e2bcbf99SRichard Fitzgerald return true;
2111e2bcbf99SRichard Fitzgerald
2112e2bcbf99SRichard Fitzgerald val = snd_soc_component_read(component, base + CS48L32_ASP_CONTROL2);
2113e2bcbf99SRichard Fitzgerald if (slotws != (val & (CS48L32_ASP_RX_WIDTH_MASK | CS48L32_ASP_TX_WIDTH_MASK)))
2114e2bcbf99SRichard Fitzgerald return true;
2115e2bcbf99SRichard Fitzgerald
2116e2bcbf99SRichard Fitzgerald val = snd_soc_component_read(component, base + CS48L32_ASP_DATA_CONTROL1);
2117e2bcbf99SRichard Fitzgerald if (dataw != (val & (CS48L32_ASP_TX_WL_MASK)))
2118e2bcbf99SRichard Fitzgerald return true;
2119e2bcbf99SRichard Fitzgerald
2120e2bcbf99SRichard Fitzgerald val = snd_soc_component_read(component, base + CS48L32_ASP_DATA_CONTROL5);
2121e2bcbf99SRichard Fitzgerald if (dataw != (val & (CS48L32_ASP_RX_WL_MASK)))
2122e2bcbf99SRichard Fitzgerald return true;
2123e2bcbf99SRichard Fitzgerald
2124e2bcbf99SRichard Fitzgerald return false;
2125e2bcbf99SRichard Fitzgerald }
2126e2bcbf99SRichard Fitzgerald
cs48l32_hw_params(struct snd_pcm_substream * substream,struct snd_pcm_hw_params * params,struct snd_soc_dai * dai)2127e2bcbf99SRichard Fitzgerald static int cs48l32_hw_params(struct snd_pcm_substream *substream,
2128e2bcbf99SRichard Fitzgerald struct snd_pcm_hw_params *params,
2129e2bcbf99SRichard Fitzgerald struct snd_soc_dai *dai)
2130e2bcbf99SRichard Fitzgerald {
2131e2bcbf99SRichard Fitzgerald struct snd_soc_component *component = dai->component;
2132e2bcbf99SRichard Fitzgerald struct cs48l32_codec *cs48l32_codec = snd_soc_component_get_drvdata(component);
2133e2bcbf99SRichard Fitzgerald struct regmap *regmap = cs48l32_codec->core.regmap;
2134e2bcbf99SRichard Fitzgerald int base = dai->driver->base;
2135e2bcbf99SRichard Fitzgerald int dai_id = dai->id - 1;
2136e2bcbf99SRichard Fitzgerald unsigned int rate = params_rate(params);
2137e2bcbf99SRichard Fitzgerald unsigned int dataw = snd_pcm_format_width(params_format(params));
2138e2bcbf99SRichard Fitzgerald unsigned int asp_state = 0;
2139e2bcbf99SRichard Fitzgerald int sclk, sclk_target;
2140e2bcbf99SRichard Fitzgerald unsigned int slotw, n_slots, n_slots_multiple, val;
2141e2bcbf99SRichard Fitzgerald int i, ret;
2142e2bcbf99SRichard Fitzgerald
2143e2bcbf99SRichard Fitzgerald cs48l32_asp_dbg(dai, "hwparams in: ch:%u dataw:%u rate:%u\n",
2144e2bcbf99SRichard Fitzgerald params_channels(params), dataw, rate);
2145e2bcbf99SRichard Fitzgerald /*
2146e2bcbf99SRichard Fitzgerald * The following calculations hold only under the assumption that
2147e2bcbf99SRichard Fitzgerald * symmetric_[rates|channels|samplebits] are set to 1
2148e2bcbf99SRichard Fitzgerald */
2149e2bcbf99SRichard Fitzgerald if (cs48l32_codec->tdm_slots[dai_id]) {
2150e2bcbf99SRichard Fitzgerald n_slots = cs48l32_codec->tdm_slots[dai_id];
2151e2bcbf99SRichard Fitzgerald slotw = cs48l32_codec->tdm_width[dai_id];
2152e2bcbf99SRichard Fitzgerald } else {
2153e2bcbf99SRichard Fitzgerald n_slots = params_channels(params);
2154e2bcbf99SRichard Fitzgerald slotw = dataw;
2155e2bcbf99SRichard Fitzgerald }
2156e2bcbf99SRichard Fitzgerald
2157e2bcbf99SRichard Fitzgerald val = snd_soc_component_read(component, base + CS48L32_ASP_CONTROL2);
2158e2bcbf99SRichard Fitzgerald val = (val & CS48L32_ASP_FMT_MASK) >> CS48L32_ASP_FMT_SHIFT;
2159e2bcbf99SRichard Fitzgerald if (val == CS48L32_ASP_FMT_I2S_MODE)
2160e2bcbf99SRichard Fitzgerald n_slots_multiple = 2;
2161e2bcbf99SRichard Fitzgerald else
2162e2bcbf99SRichard Fitzgerald n_slots_multiple = 1;
2163e2bcbf99SRichard Fitzgerald
2164e2bcbf99SRichard Fitzgerald sclk_target = snd_soc_tdm_params_to_bclk(params, slotw, n_slots, n_slots_multiple);
2165*22188b9dSHarshit Mogalapalli if (sclk_target < 0) {
2166*22188b9dSHarshit Mogalapalli cs48l32_asp_err(dai, "Invalid parameters\n");
2167*22188b9dSHarshit Mogalapalli return sclk_target;
2168*22188b9dSHarshit Mogalapalli }
2169e2bcbf99SRichard Fitzgerald
2170e2bcbf99SRichard Fitzgerald for (i = 0; i < ARRAY_SIZE(cs48l32_sclk_rates); i++) {
2171e2bcbf99SRichard Fitzgerald if ((cs48l32_sclk_rates[i].freq >= sclk_target) &&
2172e2bcbf99SRichard Fitzgerald (cs48l32_sclk_rates[i].freq % rate == 0)) {
2173e2bcbf99SRichard Fitzgerald sclk = cs48l32_sclk_rates[i].id;
2174e2bcbf99SRichard Fitzgerald break;
2175e2bcbf99SRichard Fitzgerald }
2176e2bcbf99SRichard Fitzgerald }
2177e2bcbf99SRichard Fitzgerald if (i == ARRAY_SIZE(cs48l32_sclk_rates)) {
2178e2bcbf99SRichard Fitzgerald cs48l32_asp_err(dai, "Unsupported sample rate %dHz\n", rate);
2179e2bcbf99SRichard Fitzgerald return -EINVAL;
2180e2bcbf99SRichard Fitzgerald }
2181e2bcbf99SRichard Fitzgerald
2182e2bcbf99SRichard Fitzgerald cs48l32_asp_dbg(dai, "hwparams out: n_slots:%u dataw:%u slotw:%u bclk:%u bclkid:%u\n",
2183e2bcbf99SRichard Fitzgerald n_slots, dataw, slotw, sclk_target, sclk);
2184e2bcbf99SRichard Fitzgerald
2185e2bcbf99SRichard Fitzgerald slotw = (slotw << CS48L32_ASP_TX_WIDTH_SHIFT) |
2186e2bcbf99SRichard Fitzgerald (slotw << CS48L32_ASP_RX_WIDTH_SHIFT);
2187e2bcbf99SRichard Fitzgerald
2188e2bcbf99SRichard Fitzgerald if (!cs48l32_asp_cfg_changed(component, base, sclk, slotw, dataw))
2189e2bcbf99SRichard Fitzgerald return cs48l32_hw_params_rate(substream, params, dai);
2190e2bcbf99SRichard Fitzgerald
2191e2bcbf99SRichard Fitzgerald /* ASP must be disabled while changing configuration */
2192e2bcbf99SRichard Fitzgerald asp_state = snd_soc_component_read(component, base + CS48L32_ASP_ENABLES1);
2193e2bcbf99SRichard Fitzgerald regmap_clear_bits(regmap, base + CS48L32_ASP_ENABLES1, 0xff00ff);
2194e2bcbf99SRichard Fitzgerald
2195e2bcbf99SRichard Fitzgerald ret = cs48l32_hw_params_rate(substream, params, dai);
2196e2bcbf99SRichard Fitzgerald if (ret != 0)
2197e2bcbf99SRichard Fitzgerald goto restore_asp;
2198e2bcbf99SRichard Fitzgerald
2199e2bcbf99SRichard Fitzgerald regmap_update_bits_async(regmap,
2200e2bcbf99SRichard Fitzgerald base + CS48L32_ASP_CONTROL1,
2201e2bcbf99SRichard Fitzgerald CS48L32_ASP_BCLK_FREQ_MASK,
2202e2bcbf99SRichard Fitzgerald sclk);
2203e2bcbf99SRichard Fitzgerald regmap_update_bits_async(regmap,
2204e2bcbf99SRichard Fitzgerald base + CS48L32_ASP_CONTROL2,
2205e2bcbf99SRichard Fitzgerald CS48L32_ASP_RX_WIDTH_MASK | CS48L32_ASP_TX_WIDTH_MASK,
2206e2bcbf99SRichard Fitzgerald slotw);
2207e2bcbf99SRichard Fitzgerald regmap_update_bits_async(regmap,
2208e2bcbf99SRichard Fitzgerald base + CS48L32_ASP_DATA_CONTROL1,
2209e2bcbf99SRichard Fitzgerald CS48L32_ASP_TX_WL_MASK,
2210e2bcbf99SRichard Fitzgerald dataw);
2211e2bcbf99SRichard Fitzgerald regmap_update_bits(regmap,
2212e2bcbf99SRichard Fitzgerald base + CS48L32_ASP_DATA_CONTROL5,
2213e2bcbf99SRichard Fitzgerald CS48L32_ASP_RX_WL_MASK,
2214e2bcbf99SRichard Fitzgerald dataw);
2215e2bcbf99SRichard Fitzgerald
2216e2bcbf99SRichard Fitzgerald restore_asp:
2217e2bcbf99SRichard Fitzgerald /* Restore ASP TX/RX enable state */
2218e2bcbf99SRichard Fitzgerald regmap_update_bits(regmap,
2219e2bcbf99SRichard Fitzgerald base + CS48L32_ASP_ENABLES1,
2220e2bcbf99SRichard Fitzgerald 0xff00ff,
2221e2bcbf99SRichard Fitzgerald asp_state);
2222e2bcbf99SRichard Fitzgerald return ret;
2223e2bcbf99SRichard Fitzgerald }
2224e2bcbf99SRichard Fitzgerald
cs48l32_dai_clk_str(int clk_id)2225e2bcbf99SRichard Fitzgerald static const char *cs48l32_dai_clk_str(int clk_id)
2226e2bcbf99SRichard Fitzgerald {
2227e2bcbf99SRichard Fitzgerald switch (clk_id) {
2228e2bcbf99SRichard Fitzgerald case CS48L32_CLK_SYSCLK_1:
2229e2bcbf99SRichard Fitzgerald case CS48L32_CLK_SYSCLK_2:
2230e2bcbf99SRichard Fitzgerald case CS48L32_CLK_SYSCLK_3:
2231e2bcbf99SRichard Fitzgerald case CS48L32_CLK_SYSCLK_4:
2232e2bcbf99SRichard Fitzgerald return "SYSCLK";
2233e2bcbf99SRichard Fitzgerald default:
2234e2bcbf99SRichard Fitzgerald return "Unknown clock";
2235e2bcbf99SRichard Fitzgerald }
2236e2bcbf99SRichard Fitzgerald }
2237e2bcbf99SRichard Fitzgerald
cs48l32_dai_set_sysclk(struct snd_soc_dai * dai,int clk_id,unsigned int freq,int dir)2238e2bcbf99SRichard Fitzgerald static int cs48l32_dai_set_sysclk(struct snd_soc_dai *dai,
2239e2bcbf99SRichard Fitzgerald int clk_id, unsigned int freq, int dir)
2240e2bcbf99SRichard Fitzgerald {
2241e2bcbf99SRichard Fitzgerald struct snd_soc_component *component = dai->component;
2242e2bcbf99SRichard Fitzgerald struct cs48l32_codec *cs48l32_codec = snd_soc_component_get_drvdata(component);
2243e2bcbf99SRichard Fitzgerald struct cs48l32_dai_priv *dai_priv = &cs48l32_codec->dai[dai->id - 1];
2244e2bcbf99SRichard Fitzgerald unsigned int base = dai->driver->base;
2245e2bcbf99SRichard Fitzgerald unsigned int current_asp_rate, target_asp_rate;
2246e2bcbf99SRichard Fitzgerald bool change_rate_domain = false;
2247e2bcbf99SRichard Fitzgerald int ret;
2248e2bcbf99SRichard Fitzgerald
2249e2bcbf99SRichard Fitzgerald if (clk_id == dai_priv->clk)
2250e2bcbf99SRichard Fitzgerald return 0;
2251e2bcbf99SRichard Fitzgerald
2252e2bcbf99SRichard Fitzgerald if (snd_soc_dai_active(dai)) {
2253e2bcbf99SRichard Fitzgerald cs48l32_asp_err(dai, "Can't change clock on active DAI\n");
2254e2bcbf99SRichard Fitzgerald return -EBUSY;
2255e2bcbf99SRichard Fitzgerald }
2256e2bcbf99SRichard Fitzgerald
2257e2bcbf99SRichard Fitzgerald switch (clk_id) {
2258e2bcbf99SRichard Fitzgerald case CS48L32_CLK_SYSCLK_1:
2259e2bcbf99SRichard Fitzgerald target_asp_rate = 0U << CS48L32_ASP_RATE_SHIFT;
2260e2bcbf99SRichard Fitzgerald break;
2261e2bcbf99SRichard Fitzgerald case CS48L32_CLK_SYSCLK_2:
2262e2bcbf99SRichard Fitzgerald target_asp_rate = 1U << CS48L32_ASP_RATE_SHIFT;
2263e2bcbf99SRichard Fitzgerald break;
2264e2bcbf99SRichard Fitzgerald case CS48L32_CLK_SYSCLK_3:
2265e2bcbf99SRichard Fitzgerald target_asp_rate = 2U << CS48L32_ASP_RATE_SHIFT;
2266e2bcbf99SRichard Fitzgerald break;
2267e2bcbf99SRichard Fitzgerald case CS48L32_CLK_SYSCLK_4:
2268e2bcbf99SRichard Fitzgerald target_asp_rate = 3U << CS48L32_ASP_RATE_SHIFT;
2269e2bcbf99SRichard Fitzgerald break;
2270e2bcbf99SRichard Fitzgerald default:
2271e2bcbf99SRichard Fitzgerald return -EINVAL;
2272e2bcbf99SRichard Fitzgerald }
2273e2bcbf99SRichard Fitzgerald
2274e2bcbf99SRichard Fitzgerald dai_priv->clk = clk_id;
2275e2bcbf99SRichard Fitzgerald cs48l32_asp_dbg(dai, "Setting to %s\n", cs48l32_dai_clk_str(clk_id));
2276e2bcbf99SRichard Fitzgerald
2277e2bcbf99SRichard Fitzgerald if (base) {
2278e2bcbf99SRichard Fitzgerald ret = regmap_read(cs48l32_codec->core.regmap,
2279e2bcbf99SRichard Fitzgerald base + CS48L32_ASP_CONTROL1,
2280e2bcbf99SRichard Fitzgerald ¤t_asp_rate);
2281e2bcbf99SRichard Fitzgerald if (ret != 0) {
2282e2bcbf99SRichard Fitzgerald cs48l32_asp_err(dai, "Failed to check rate: %d\n", ret);
2283e2bcbf99SRichard Fitzgerald return ret;
2284e2bcbf99SRichard Fitzgerald }
2285e2bcbf99SRichard Fitzgerald
2286e2bcbf99SRichard Fitzgerald if ((current_asp_rate & CS48L32_ASP_RATE_MASK) !=
2287e2bcbf99SRichard Fitzgerald (target_asp_rate & CS48L32_ASP_RATE_MASK)) {
2288e2bcbf99SRichard Fitzgerald change_rate_domain = true;
2289e2bcbf99SRichard Fitzgerald
2290e2bcbf99SRichard Fitzgerald mutex_lock(&cs48l32_codec->rate_lock);
2291e2bcbf99SRichard Fitzgerald /* Guard the rate change with SYSCLK cycles */
2292e2bcbf99SRichard Fitzgerald cs48l32_spin_sysclk(cs48l32_codec);
2293e2bcbf99SRichard Fitzgerald }
2294e2bcbf99SRichard Fitzgerald
2295e2bcbf99SRichard Fitzgerald snd_soc_component_update_bits(component, base + CS48L32_ASP_CONTROL1,
2296e2bcbf99SRichard Fitzgerald CS48L32_ASP_RATE_MASK, target_asp_rate);
2297e2bcbf99SRichard Fitzgerald
2298e2bcbf99SRichard Fitzgerald if (change_rate_domain) {
2299e2bcbf99SRichard Fitzgerald cs48l32_spin_sysclk(cs48l32_codec);
2300e2bcbf99SRichard Fitzgerald mutex_unlock(&cs48l32_codec->rate_lock);
2301e2bcbf99SRichard Fitzgerald }
2302e2bcbf99SRichard Fitzgerald }
2303e2bcbf99SRichard Fitzgerald
2304e2bcbf99SRichard Fitzgerald return 0;
2305e2bcbf99SRichard Fitzgerald }
2306e2bcbf99SRichard Fitzgerald
cs48l32_set_channels_to_mask(struct snd_soc_dai * dai,unsigned int base,int channels,unsigned int mask)2307e2bcbf99SRichard Fitzgerald static void cs48l32_set_channels_to_mask(struct snd_soc_dai *dai,
2308e2bcbf99SRichard Fitzgerald unsigned int base,
2309e2bcbf99SRichard Fitzgerald int channels, unsigned int mask)
2310e2bcbf99SRichard Fitzgerald {
2311e2bcbf99SRichard Fitzgerald struct snd_soc_component *component = dai->component;
2312e2bcbf99SRichard Fitzgerald struct cs48l32_codec *cs48l32_codec = snd_soc_component_get_drvdata(component);
2313e2bcbf99SRichard Fitzgerald struct regmap *regmap = cs48l32_codec->core.regmap;
2314e2bcbf99SRichard Fitzgerald int slot, i, j = 0, shift;
2315e2bcbf99SRichard Fitzgerald unsigned int frame_ctls[2] = {0, 0};
2316e2bcbf99SRichard Fitzgerald
2317e2bcbf99SRichard Fitzgerald for (i = 0; i < channels; ++i) {
2318e2bcbf99SRichard Fitzgerald slot = ffs(mask) - 1;
2319e2bcbf99SRichard Fitzgerald if (slot < 0)
2320e2bcbf99SRichard Fitzgerald return;
2321e2bcbf99SRichard Fitzgerald
2322e2bcbf99SRichard Fitzgerald if (i - (j * 4) >= 4) {
2323e2bcbf99SRichard Fitzgerald ++j;
2324e2bcbf99SRichard Fitzgerald if (j >= 2)
2325e2bcbf99SRichard Fitzgerald break;
2326e2bcbf99SRichard Fitzgerald }
2327e2bcbf99SRichard Fitzgerald
2328e2bcbf99SRichard Fitzgerald shift = (8 * (i - j * 4));
2329e2bcbf99SRichard Fitzgerald
2330e2bcbf99SRichard Fitzgerald frame_ctls[j] |= slot << shift;
2331e2bcbf99SRichard Fitzgerald
2332e2bcbf99SRichard Fitzgerald mask &= ~(1 << slot); /* ? mask ^= 1 << slot ? */
2333e2bcbf99SRichard Fitzgerald }
2334e2bcbf99SRichard Fitzgerald
2335e2bcbf99SRichard Fitzgerald regmap_write(regmap, base, frame_ctls[0]);
2336e2bcbf99SRichard Fitzgerald regmap_write(regmap, base + 0x4, frame_ctls[1]);
2337e2bcbf99SRichard Fitzgerald
2338e2bcbf99SRichard Fitzgerald if (mask)
2339e2bcbf99SRichard Fitzgerald cs48l32_asp_warn(dai, "Too many channels in TDM mask\n");
2340e2bcbf99SRichard Fitzgerald }
2341e2bcbf99SRichard Fitzgerald
cs48l32_set_tdm_slot(struct snd_soc_dai * dai,unsigned int tx_mask,unsigned int rx_mask,int slots,int slot_width)2342e2bcbf99SRichard Fitzgerald static int cs48l32_set_tdm_slot(struct snd_soc_dai *dai, unsigned int tx_mask,
2343e2bcbf99SRichard Fitzgerald unsigned int rx_mask, int slots, int slot_width)
2344e2bcbf99SRichard Fitzgerald {
2345e2bcbf99SRichard Fitzgerald struct snd_soc_component *component = dai->component;
2346e2bcbf99SRichard Fitzgerald struct cs48l32_codec *cs48l32_codec = snd_soc_component_get_drvdata(component);
2347e2bcbf99SRichard Fitzgerald int base = dai->driver->base;
2348e2bcbf99SRichard Fitzgerald int rx_max_chan = dai->driver->playback.channels_max;
2349e2bcbf99SRichard Fitzgerald int tx_max_chan = dai->driver->capture.channels_max;
2350e2bcbf99SRichard Fitzgerald
2351e2bcbf99SRichard Fitzgerald /* Only support TDM for the physical ASPs */
2352e2bcbf99SRichard Fitzgerald if (dai->id > CS48L32_MAX_ASP)
2353e2bcbf99SRichard Fitzgerald return -EINVAL;
2354e2bcbf99SRichard Fitzgerald
2355e2bcbf99SRichard Fitzgerald if (slots == 0) {
2356e2bcbf99SRichard Fitzgerald tx_mask = (1 << tx_max_chan) - 1;
2357e2bcbf99SRichard Fitzgerald rx_mask = (1 << rx_max_chan) - 1;
2358e2bcbf99SRichard Fitzgerald }
2359e2bcbf99SRichard Fitzgerald
2360e2bcbf99SRichard Fitzgerald cs48l32_set_channels_to_mask(dai, base + CS48L32_ASP_FRAME_CONTROL1,
2361e2bcbf99SRichard Fitzgerald tx_max_chan, tx_mask);
2362e2bcbf99SRichard Fitzgerald cs48l32_set_channels_to_mask(dai, base + CS48L32_ASP_FRAME_CONTROL5,
2363e2bcbf99SRichard Fitzgerald rx_max_chan, rx_mask);
2364e2bcbf99SRichard Fitzgerald
2365e2bcbf99SRichard Fitzgerald cs48l32_codec->tdm_width[dai->id - 1] = slot_width;
2366e2bcbf99SRichard Fitzgerald cs48l32_codec->tdm_slots[dai->id - 1] = slots;
2367e2bcbf99SRichard Fitzgerald
2368e2bcbf99SRichard Fitzgerald return 0;
2369e2bcbf99SRichard Fitzgerald }
2370e2bcbf99SRichard Fitzgerald
2371e2bcbf99SRichard Fitzgerald static const struct snd_soc_dai_ops cs48l32_dai_ops = {
2372e2bcbf99SRichard Fitzgerald .probe = &cs48l32_asp_dai_probe,
2373e2bcbf99SRichard Fitzgerald .startup = &cs48l32_startup,
2374e2bcbf99SRichard Fitzgerald .set_fmt = &cs48l32_set_fmt,
2375e2bcbf99SRichard Fitzgerald .set_tdm_slot = &cs48l32_set_tdm_slot,
2376e2bcbf99SRichard Fitzgerald .hw_params = &cs48l32_hw_params,
2377e2bcbf99SRichard Fitzgerald .set_sysclk = &cs48l32_dai_set_sysclk,
2378e2bcbf99SRichard Fitzgerald };
2379e2bcbf99SRichard Fitzgerald
cs48l32_sysclk_ev(struct snd_soc_dapm_widget * w,struct snd_kcontrol * kcontrol,int event)2380e2bcbf99SRichard Fitzgerald static int cs48l32_sysclk_ev(struct snd_soc_dapm_widget *w,
2381e2bcbf99SRichard Fitzgerald struct snd_kcontrol *kcontrol, int event)
2382e2bcbf99SRichard Fitzgerald {
2383e2bcbf99SRichard Fitzgerald struct snd_soc_component *component = snd_soc_dapm_to_component(w->dapm);
2384e2bcbf99SRichard Fitzgerald struct cs48l32_codec *cs48l32_codec = snd_soc_component_get_drvdata(component);
2385e2bcbf99SRichard Fitzgerald
2386e2bcbf99SRichard Fitzgerald cs48l32_spin_sysclk(cs48l32_codec);
2387e2bcbf99SRichard Fitzgerald
2388e2bcbf99SRichard Fitzgerald return 0;
2389e2bcbf99SRichard Fitzgerald }
2390e2bcbf99SRichard Fitzgerald
cs48l32_in_ev(struct snd_soc_dapm_widget * w,struct snd_kcontrol * kcontrol,int event)2391e2bcbf99SRichard Fitzgerald static int cs48l32_in_ev(struct snd_soc_dapm_widget *w, struct snd_kcontrol *kcontrol, int event)
2392e2bcbf99SRichard Fitzgerald {
2393e2bcbf99SRichard Fitzgerald struct snd_soc_component *component = snd_soc_dapm_to_component(w->dapm);
2394e2bcbf99SRichard Fitzgerald struct cs48l32_codec *cs48l32_codec = snd_soc_component_get_drvdata(component);
2395e2bcbf99SRichard Fitzgerald unsigned int reg;
2396e2bcbf99SRichard Fitzgerald
2397e2bcbf99SRichard Fitzgerald if (w->shift % 2)
2398e2bcbf99SRichard Fitzgerald reg = CS48L32_IN1L_CONTROL2;
2399e2bcbf99SRichard Fitzgerald else
2400e2bcbf99SRichard Fitzgerald reg = CS48L32_IN1R_CONTROL2;
2401e2bcbf99SRichard Fitzgerald
2402e2bcbf99SRichard Fitzgerald reg += (w->shift / 2) * (CS48L32_IN2L_CONTROL2 - CS48L32_IN1L_CONTROL2);
2403e2bcbf99SRichard Fitzgerald
2404e2bcbf99SRichard Fitzgerald switch (event) {
2405e2bcbf99SRichard Fitzgerald case SND_SOC_DAPM_PRE_PMU:
2406e2bcbf99SRichard Fitzgerald switch (w->shift) {
2407e2bcbf99SRichard Fitzgerald case CS48L32_IN1L_EN_SHIFT:
2408e2bcbf99SRichard Fitzgerald snd_soc_component_update_bits(component,
2409e2bcbf99SRichard Fitzgerald CS48L32_ADC1L_ANA_CONTROL1,
2410e2bcbf99SRichard Fitzgerald CS48L32_ADC1x_INT_ENA_FRC_MASK,
2411e2bcbf99SRichard Fitzgerald CS48L32_ADC1x_INT_ENA_FRC_MASK);
2412e2bcbf99SRichard Fitzgerald break;
2413e2bcbf99SRichard Fitzgerald case CS48L32_IN1R_EN_SHIFT:
2414e2bcbf99SRichard Fitzgerald snd_soc_component_update_bits(component,
2415e2bcbf99SRichard Fitzgerald CS48L32_ADC1R_ANA_CONTROL1,
2416e2bcbf99SRichard Fitzgerald CS48L32_ADC1x_INT_ENA_FRC_MASK,
2417e2bcbf99SRichard Fitzgerald CS48L32_ADC1x_INT_ENA_FRC_MASK);
2418e2bcbf99SRichard Fitzgerald break;
2419e2bcbf99SRichard Fitzgerald default:
2420e2bcbf99SRichard Fitzgerald break;
2421e2bcbf99SRichard Fitzgerald }
2422e2bcbf99SRichard Fitzgerald cs48l32_codec->in_up_pending++;
2423e2bcbf99SRichard Fitzgerald break;
2424e2bcbf99SRichard Fitzgerald case SND_SOC_DAPM_POST_PMU:
2425e2bcbf99SRichard Fitzgerald usleep_range(200, 300);
2426e2bcbf99SRichard Fitzgerald
2427e2bcbf99SRichard Fitzgerald switch (w->shift) {
2428e2bcbf99SRichard Fitzgerald case CS48L32_IN1L_EN_SHIFT:
2429e2bcbf99SRichard Fitzgerald snd_soc_component_update_bits(component,
2430e2bcbf99SRichard Fitzgerald CS48L32_ADC1L_ANA_CONTROL1,
2431e2bcbf99SRichard Fitzgerald CS48L32_ADC1x_INT_ENA_FRC_MASK,
2432e2bcbf99SRichard Fitzgerald 0);
2433e2bcbf99SRichard Fitzgerald break;
2434e2bcbf99SRichard Fitzgerald case CS48L32_IN1R_EN_SHIFT:
2435e2bcbf99SRichard Fitzgerald snd_soc_component_update_bits(component,
2436e2bcbf99SRichard Fitzgerald CS48L32_ADC1R_ANA_CONTROL1,
2437e2bcbf99SRichard Fitzgerald CS48L32_ADC1x_INT_ENA_FRC_MASK,
2438e2bcbf99SRichard Fitzgerald 0);
2439e2bcbf99SRichard Fitzgerald break;
2440e2bcbf99SRichard Fitzgerald
2441e2bcbf99SRichard Fitzgerald default:
2442e2bcbf99SRichard Fitzgerald break;
2443e2bcbf99SRichard Fitzgerald }
2444e2bcbf99SRichard Fitzgerald cs48l32_codec->in_up_pending--;
2445e2bcbf99SRichard Fitzgerald snd_soc_component_update_bits(component, reg, CS48L32_INx_MUTE_MASK, 0);
2446e2bcbf99SRichard Fitzgerald
2447e2bcbf99SRichard Fitzgerald /* Uncached write-only register, no need for update_bits */
2448e2bcbf99SRichard Fitzgerald if (!cs48l32_codec->in_up_pending) {
2449e2bcbf99SRichard Fitzgerald snd_soc_component_write(component, cs48l32_codec->in_vu_reg,
2450e2bcbf99SRichard Fitzgerald CS48L32_IN_VU_MASK);
2451e2bcbf99SRichard Fitzgerald }
2452e2bcbf99SRichard Fitzgerald break;
2453e2bcbf99SRichard Fitzgerald case SND_SOC_DAPM_PRE_PMD:
2454e2bcbf99SRichard Fitzgerald snd_soc_component_update_bits(component, reg,
2455e2bcbf99SRichard Fitzgerald CS48L32_INx_MUTE_MASK, CS48L32_INx_MUTE_MASK);
2456e2bcbf99SRichard Fitzgerald snd_soc_component_write(component, cs48l32_codec->in_vu_reg,
2457e2bcbf99SRichard Fitzgerald CS48L32_IN_VU_MASK);
2458e2bcbf99SRichard Fitzgerald break;
2459e2bcbf99SRichard Fitzgerald default:
2460e2bcbf99SRichard Fitzgerald break;
2461e2bcbf99SRichard Fitzgerald }
2462e2bcbf99SRichard Fitzgerald
2463e2bcbf99SRichard Fitzgerald return 0;
2464e2bcbf99SRichard Fitzgerald }
2465e2bcbf99SRichard Fitzgerald
cs48l32_in_put_volsw(struct snd_kcontrol * kcontrol,struct snd_ctl_elem_value * ucontrol)2466e2bcbf99SRichard Fitzgerald static int cs48l32_in_put_volsw(struct snd_kcontrol *kcontrol,
2467e2bcbf99SRichard Fitzgerald struct snd_ctl_elem_value *ucontrol)
2468e2bcbf99SRichard Fitzgerald {
2469e2bcbf99SRichard Fitzgerald struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol);
2470e2bcbf99SRichard Fitzgerald struct cs48l32_codec *cs48l32_codec = snd_soc_component_get_drvdata(component);
2471e2bcbf99SRichard Fitzgerald int ret;
2472e2bcbf99SRichard Fitzgerald
2473e2bcbf99SRichard Fitzgerald ret = snd_soc_put_volsw(kcontrol, ucontrol);
2474e2bcbf99SRichard Fitzgerald if (ret < 0)
2475e2bcbf99SRichard Fitzgerald return ret;
2476e2bcbf99SRichard Fitzgerald
2477e2bcbf99SRichard Fitzgerald /*
2478e2bcbf99SRichard Fitzgerald * Uncached write-only register, no need for update_bits.
2479e2bcbf99SRichard Fitzgerald * Will fail if codec is off but that will be handled by cs48l32_in_ev
2480e2bcbf99SRichard Fitzgerald */
2481e2bcbf99SRichard Fitzgerald snd_soc_component_write(component, cs48l32_codec->in_vu_reg, CS48L32_IN_VU);
2482e2bcbf99SRichard Fitzgerald
2483e2bcbf99SRichard Fitzgerald return ret;
2484e2bcbf99SRichard Fitzgerald }
2485e2bcbf99SRichard Fitzgerald
cs48l32_eq_filter_unstable(bool mode,__be16 in_a,__be16 in_b)2486e2bcbf99SRichard Fitzgerald static bool cs48l32_eq_filter_unstable(bool mode, __be16 in_a, __be16 in_b)
2487e2bcbf99SRichard Fitzgerald {
2488e2bcbf99SRichard Fitzgerald s16 a = be16_to_cpu(in_a);
2489e2bcbf99SRichard Fitzgerald s16 b = be16_to_cpu(in_b);
2490e2bcbf99SRichard Fitzgerald
2491e2bcbf99SRichard Fitzgerald if (!mode)
2492e2bcbf99SRichard Fitzgerald return abs(a) > CS48L32_EQ_MAX_COEFF;
2493e2bcbf99SRichard Fitzgerald
2494e2bcbf99SRichard Fitzgerald if (abs(b) > CS48L32_EQ_MAX_COEFF)
2495e2bcbf99SRichard Fitzgerald return true;
2496e2bcbf99SRichard Fitzgerald
2497e2bcbf99SRichard Fitzgerald if (abs((a << 16) / (CS48L32_EQ_MAX_COEFF + 1 - b)) >= ((CS48L32_EQ_MAX_COEFF + 1) << 4))
2498e2bcbf99SRichard Fitzgerald return true;
2499e2bcbf99SRichard Fitzgerald
2500e2bcbf99SRichard Fitzgerald return false;
2501e2bcbf99SRichard Fitzgerald }
2502e2bcbf99SRichard Fitzgerald
cs48l32_eq_ev(struct snd_soc_dapm_widget * w,struct snd_kcontrol * kcontrol,int event)2503e2bcbf99SRichard Fitzgerald static int cs48l32_eq_ev(struct snd_soc_dapm_widget *w,
2504e2bcbf99SRichard Fitzgerald struct snd_kcontrol *kcontrol, int event)
2505e2bcbf99SRichard Fitzgerald {
2506e2bcbf99SRichard Fitzgerald struct snd_soc_component *component = snd_soc_dapm_to_component(w->dapm);
2507e2bcbf99SRichard Fitzgerald struct cs48l32_codec *cs48l32_codec = snd_soc_component_get_drvdata(component);
2508e2bcbf99SRichard Fitzgerald struct regmap *regmap = cs48l32_codec->core.regmap;
2509e2bcbf99SRichard Fitzgerald unsigned int mode = cs48l32_codec->eq_mode[w->shift];
2510e2bcbf99SRichard Fitzgerald unsigned int reg;
2511e2bcbf99SRichard Fitzgerald __be16 *data = &cs48l32_codec->eq_coefficients[w->shift][0];
2512e2bcbf99SRichard Fitzgerald int ret = 0;
2513e2bcbf99SRichard Fitzgerald
2514e2bcbf99SRichard Fitzgerald reg = CS48L32_EQ1_BAND1_COEFF1;
2515e2bcbf99SRichard Fitzgerald reg += w->shift * (CS48L32_EQ2_BAND1_COEFF1 - CS48L32_EQ1_BAND1_COEFF1);
2516e2bcbf99SRichard Fitzgerald
2517e2bcbf99SRichard Fitzgerald switch (event) {
2518e2bcbf99SRichard Fitzgerald case SND_SOC_DAPM_PRE_PMU:
2519e2bcbf99SRichard Fitzgerald if (cs48l32_eq_filter_unstable(!!mode, data[1], data[0]) ||
2520e2bcbf99SRichard Fitzgerald cs48l32_eq_filter_unstable(true, data[7], data[6]) ||
2521e2bcbf99SRichard Fitzgerald cs48l32_eq_filter_unstable(true, data[13], data[12]) ||
2522e2bcbf99SRichard Fitzgerald cs48l32_eq_filter_unstable(true, data[19], data[18]) ||
2523e2bcbf99SRichard Fitzgerald cs48l32_eq_filter_unstable(false, data[25], data[24])) {
2524e2bcbf99SRichard Fitzgerald dev_err(cs48l32_codec->core.dev, "Rejecting unstable EQ coefficients.\n");
2525e2bcbf99SRichard Fitzgerald ret = -EINVAL;
2526e2bcbf99SRichard Fitzgerald } else {
2527e2bcbf99SRichard Fitzgerald ret = regmap_raw_write(regmap, reg, data, CS48L32_EQ_BLOCK_SZ);
2528e2bcbf99SRichard Fitzgerald if (ret < 0) {
2529e2bcbf99SRichard Fitzgerald dev_err(cs48l32_codec->core.dev,
2530e2bcbf99SRichard Fitzgerald "Error writing EQ coefficients: %d\n", ret);
2531e2bcbf99SRichard Fitzgerald goto out;
2532e2bcbf99SRichard Fitzgerald }
2533e2bcbf99SRichard Fitzgerald
2534e2bcbf99SRichard Fitzgerald ret = snd_soc_component_update_bits(component,
2535e2bcbf99SRichard Fitzgerald CS48L32_EQ_CONTROL2,
2536e2bcbf99SRichard Fitzgerald w->mask,
2537e2bcbf99SRichard Fitzgerald mode << w->shift);
2538e2bcbf99SRichard Fitzgerald if (ret < 0) {
2539e2bcbf99SRichard Fitzgerald dev_err(cs48l32_codec->core.dev,
2540e2bcbf99SRichard Fitzgerald "Error writing EQ mode: %d\n", ret);
2541e2bcbf99SRichard Fitzgerald }
2542e2bcbf99SRichard Fitzgerald }
2543e2bcbf99SRichard Fitzgerald break;
2544e2bcbf99SRichard Fitzgerald default:
2545e2bcbf99SRichard Fitzgerald break;
2546e2bcbf99SRichard Fitzgerald }
2547e2bcbf99SRichard Fitzgerald
2548e2bcbf99SRichard Fitzgerald out:
2549e2bcbf99SRichard Fitzgerald return ret;
2550e2bcbf99SRichard Fitzgerald }
2551e2bcbf99SRichard Fitzgerald
2552e2bcbf99SRichard Fitzgerald static const struct snd_kcontrol_new cs48l32_snd_controls[] = {
2553e2bcbf99SRichard Fitzgerald SOC_ENUM("IN1 OSR", cs48l32_in_dmic_osr[0]),
2554e2bcbf99SRichard Fitzgerald SOC_ENUM("IN2 OSR", cs48l32_in_dmic_osr[1]),
2555e2bcbf99SRichard Fitzgerald
2556e2bcbf99SRichard Fitzgerald SOC_SINGLE_RANGE_TLV("IN1L Volume", CS48L32_IN1L_CONTROL2,
2557e2bcbf99SRichard Fitzgerald CS48L32_INx_PGA_VOL_SHIFT, 0x40, 0x5f, 0, cs48l32_ana_tlv),
2558e2bcbf99SRichard Fitzgerald SOC_SINGLE_RANGE_TLV("IN1R Volume", CS48L32_IN1R_CONTROL2,
2559e2bcbf99SRichard Fitzgerald CS48L32_INx_PGA_VOL_SHIFT, 0x40, 0x5f, 0, cs48l32_ana_tlv),
2560e2bcbf99SRichard Fitzgerald
2561e2bcbf99SRichard Fitzgerald SOC_ENUM("IN HPF Cutoff Frequency", cs48l32_in_hpf_cut_enum),
2562e2bcbf99SRichard Fitzgerald
2563e2bcbf99SRichard Fitzgerald SOC_SINGLE_EXT("IN1L LP Switch", CS48L32_IN1L_CONTROL1, CS48L32_INx_LP_MODE_SHIFT,
2564e2bcbf99SRichard Fitzgerald 1, 0, snd_soc_get_volsw, cs48l32_low_power_mode_put),
2565e2bcbf99SRichard Fitzgerald SOC_SINGLE_EXT("IN1R LP Switch", CS48L32_IN1R_CONTROL1, CS48L32_INx_LP_MODE_SHIFT,
2566e2bcbf99SRichard Fitzgerald 1, 0, snd_soc_get_volsw, cs48l32_low_power_mode_put),
2567e2bcbf99SRichard Fitzgerald
2568e2bcbf99SRichard Fitzgerald SOC_SINGLE("IN1L HPF Switch", CS48L32_IN1L_CONTROL1, CS48L32_INx_HPF_SHIFT, 1, 0),
2569e2bcbf99SRichard Fitzgerald SOC_SINGLE("IN1R HPF Switch", CS48L32_IN1R_CONTROL1, CS48L32_INx_HPF_SHIFT, 1, 0),
2570e2bcbf99SRichard Fitzgerald SOC_SINGLE("IN2L HPF Switch", CS48L32_IN2L_CONTROL1, CS48L32_INx_HPF_SHIFT, 1, 0),
2571e2bcbf99SRichard Fitzgerald SOC_SINGLE("IN2R HPF Switch", CS48L32_IN2R_CONTROL1, CS48L32_INx_HPF_SHIFT, 1, 0),
2572e2bcbf99SRichard Fitzgerald
2573e2bcbf99SRichard Fitzgerald SOC_SINGLE_EXT_TLV("IN1L Digital Volume", CS48L32_IN1L_CONTROL2,
2574e2bcbf99SRichard Fitzgerald CS48L32_INx_VOL_SHIFT, 0xbf, 0, snd_soc_get_volsw,
2575e2bcbf99SRichard Fitzgerald cs48l32_in_put_volsw, cs48l32_digital_tlv),
2576e2bcbf99SRichard Fitzgerald SOC_SINGLE_EXT_TLV("IN1R Digital Volume", CS48L32_IN1R_CONTROL2,
2577e2bcbf99SRichard Fitzgerald CS48L32_INx_VOL_SHIFT, 0xbf, 0, snd_soc_get_volsw,
2578e2bcbf99SRichard Fitzgerald cs48l32_in_put_volsw, cs48l32_digital_tlv),
2579e2bcbf99SRichard Fitzgerald SOC_SINGLE_EXT_TLV("IN2L Digital Volume", CS48L32_IN2L_CONTROL2,
2580e2bcbf99SRichard Fitzgerald CS48L32_INx_VOL_SHIFT, 0xbf, 0, snd_soc_get_volsw,
2581e2bcbf99SRichard Fitzgerald cs48l32_in_put_volsw, cs48l32_digital_tlv),
2582e2bcbf99SRichard Fitzgerald SOC_SINGLE_EXT_TLV("IN2R Digital Volume", CS48L32_IN2R_CONTROL2,
2583e2bcbf99SRichard Fitzgerald CS48L32_INx_VOL_SHIFT, 0xbf, 0, snd_soc_get_volsw,
2584e2bcbf99SRichard Fitzgerald cs48l32_in_put_volsw, cs48l32_digital_tlv),
2585e2bcbf99SRichard Fitzgerald
2586e2bcbf99SRichard Fitzgerald SOC_ENUM("Input Ramp Up", cs48l32_in_vi_ramp),
2587e2bcbf99SRichard Fitzgerald SOC_ENUM("Input Ramp Down", cs48l32_in_vd_ramp),
2588e2bcbf99SRichard Fitzgerald
2589e2bcbf99SRichard Fitzgerald CS48L32_RATE_ENUM("Ultrasonic 1 Rate", cs48l32_us_output_rate[0]),
2590e2bcbf99SRichard Fitzgerald CS48L32_RATE_ENUM("Ultrasonic 2 Rate", cs48l32_us_output_rate[1]),
2591e2bcbf99SRichard Fitzgerald
2592e2bcbf99SRichard Fitzgerald SOC_ENUM("Ultrasonic 1 Freq", cs48l32_us_freq[0]),
2593e2bcbf99SRichard Fitzgerald SOC_ENUM("Ultrasonic 2 Freq", cs48l32_us_freq[1]),
2594e2bcbf99SRichard Fitzgerald
2595e2bcbf99SRichard Fitzgerald SOC_SINGLE_TLV("Ultrasonic 1 Volume", CS48L32_US1_CONTROL, CS48L32_US1_GAIN_SHIFT,
2596e2bcbf99SRichard Fitzgerald 3, 0, cs48l32_us_tlv),
2597e2bcbf99SRichard Fitzgerald SOC_SINGLE_TLV("Ultrasonic 2 Volume", CS48L32_US2_CONTROL, CS48L32_US1_GAIN_SHIFT,
2598e2bcbf99SRichard Fitzgerald 3, 0, cs48l32_us_tlv),
2599e2bcbf99SRichard Fitzgerald
2600e2bcbf99SRichard Fitzgerald SOC_ENUM("Ultrasonic 1 Detect Threshold", cs48l32_us_det_thr[0]),
2601e2bcbf99SRichard Fitzgerald SOC_ENUM("Ultrasonic 2 Detect Threshold", cs48l32_us_det_thr[1]),
2602e2bcbf99SRichard Fitzgerald
2603e2bcbf99SRichard Fitzgerald SOC_ENUM("Ultrasonic 1 Detect Pulse Length", cs48l32_us_det_num[0]),
2604e2bcbf99SRichard Fitzgerald SOC_ENUM("Ultrasonic 2 Detect Pulse Length", cs48l32_us_det_num[1]),
2605e2bcbf99SRichard Fitzgerald
2606e2bcbf99SRichard Fitzgerald SOC_ENUM("Ultrasonic 1 Detect Hold", cs48l32_us_det_hold[0]),
2607e2bcbf99SRichard Fitzgerald SOC_ENUM("Ultrasonic 2 Detect Hold", cs48l32_us_det_hold[1]),
2608e2bcbf99SRichard Fitzgerald
2609e2bcbf99SRichard Fitzgerald SOC_ENUM("Ultrasonic 1 Detect Decay", cs48l32_us_det_dcy[0]),
2610e2bcbf99SRichard Fitzgerald SOC_ENUM("Ultrasonic 2 Detect Decay", cs48l32_us_det_dcy[1]),
2611e2bcbf99SRichard Fitzgerald
2612e2bcbf99SRichard Fitzgerald SOC_SINGLE("Ultrasonic 1 Detect LPF Switch",
2613e2bcbf99SRichard Fitzgerald CS48L32_US1_DET_CONTROL, CS48L32_US1_DET_LPF_SHIFT, 1, 0),
2614e2bcbf99SRichard Fitzgerald SOC_SINGLE("Ultrasonic 2 Detect LPF Switch",
2615e2bcbf99SRichard Fitzgerald CS48L32_US2_DET_CONTROL, CS48L32_US1_DET_LPF_SHIFT, 1, 0),
2616e2bcbf99SRichard Fitzgerald
2617e2bcbf99SRichard Fitzgerald SOC_ENUM("Ultrasonic 1 Detect LPF Cut-off", cs48l32_us_det_lpf_cut[0]),
2618e2bcbf99SRichard Fitzgerald SOC_ENUM("Ultrasonic 2 Detect LPF Cut-off", cs48l32_us_det_lpf_cut[1]),
2619e2bcbf99SRichard Fitzgerald
2620e2bcbf99SRichard Fitzgerald CS48L32_MIXER_CONTROLS("EQ1", CS48L32_EQ1_INPUT1),
2621e2bcbf99SRichard Fitzgerald CS48L32_MIXER_CONTROLS("EQ2", CS48L32_EQ2_INPUT1),
2622e2bcbf99SRichard Fitzgerald CS48L32_MIXER_CONTROLS("EQ3", CS48L32_EQ3_INPUT1),
2623e2bcbf99SRichard Fitzgerald CS48L32_MIXER_CONTROLS("EQ4", CS48L32_EQ4_INPUT1),
2624e2bcbf99SRichard Fitzgerald
2625e2bcbf99SRichard Fitzgerald SOC_ENUM_EXT("EQ1 Mode", cs48l32_eq_mode[0], cs48l32_eq_mode_get, cs48l32_eq_mode_put),
2626e2bcbf99SRichard Fitzgerald
2627e2bcbf99SRichard Fitzgerald CS48L32_EQ_COEFF_CONTROLS(EQ1),
2628e2bcbf99SRichard Fitzgerald
2629e2bcbf99SRichard Fitzgerald SOC_SINGLE_TLV("EQ1 B1 Volume", CS48L32_EQ1_GAIN1, 0, 24, 0, cs48l32_eq_tlv),
2630e2bcbf99SRichard Fitzgerald SOC_SINGLE_TLV("EQ1 B2 Volume", CS48L32_EQ1_GAIN1, 8, 24, 0, cs48l32_eq_tlv),
2631e2bcbf99SRichard Fitzgerald SOC_SINGLE_TLV("EQ1 B3 Volume", CS48L32_EQ1_GAIN1, 16, 24, 0, cs48l32_eq_tlv),
2632e2bcbf99SRichard Fitzgerald SOC_SINGLE_TLV("EQ1 B4 Volume", CS48L32_EQ1_GAIN1, 24, 24, 0, cs48l32_eq_tlv),
2633e2bcbf99SRichard Fitzgerald SOC_SINGLE_TLV("EQ1 B5 Volume", CS48L32_EQ1_GAIN2, 0, 24, 0, cs48l32_eq_tlv),
2634e2bcbf99SRichard Fitzgerald
2635e2bcbf99SRichard Fitzgerald SOC_ENUM_EXT("EQ2 Mode", cs48l32_eq_mode[1], cs48l32_eq_mode_get, cs48l32_eq_mode_put),
2636e2bcbf99SRichard Fitzgerald CS48L32_EQ_COEFF_CONTROLS(EQ2),
2637e2bcbf99SRichard Fitzgerald SOC_SINGLE_TLV("EQ2 B1 Volume", CS48L32_EQ2_GAIN1, 0, 24, 0, cs48l32_eq_tlv),
2638e2bcbf99SRichard Fitzgerald SOC_SINGLE_TLV("EQ2 B2 Volume", CS48L32_EQ2_GAIN1, 8, 24, 0, cs48l32_eq_tlv),
2639e2bcbf99SRichard Fitzgerald SOC_SINGLE_TLV("EQ2 B3 Volume", CS48L32_EQ2_GAIN1, 16, 24, 0, cs48l32_eq_tlv),
2640e2bcbf99SRichard Fitzgerald SOC_SINGLE_TLV("EQ2 B4 Volume", CS48L32_EQ2_GAIN1, 24, 24, 0, cs48l32_eq_tlv),
2641e2bcbf99SRichard Fitzgerald SOC_SINGLE_TLV("EQ2 B5 Volume", CS48L32_EQ2_GAIN2, 0, 24, 0, cs48l32_eq_tlv),
2642e2bcbf99SRichard Fitzgerald
2643e2bcbf99SRichard Fitzgerald SOC_ENUM_EXT("EQ3 Mode", cs48l32_eq_mode[2], cs48l32_eq_mode_get, cs48l32_eq_mode_put),
2644e2bcbf99SRichard Fitzgerald CS48L32_EQ_COEFF_CONTROLS(EQ3),
2645e2bcbf99SRichard Fitzgerald SOC_SINGLE_TLV("EQ3 B1 Volume", CS48L32_EQ3_GAIN1, 0, 24, 0, cs48l32_eq_tlv),
2646e2bcbf99SRichard Fitzgerald SOC_SINGLE_TLV("EQ3 B2 Volume", CS48L32_EQ3_GAIN1, 8, 24, 0, cs48l32_eq_tlv),
2647e2bcbf99SRichard Fitzgerald SOC_SINGLE_TLV("EQ3 B3 Volume", CS48L32_EQ3_GAIN1, 16, 24, 0, cs48l32_eq_tlv),
2648e2bcbf99SRichard Fitzgerald SOC_SINGLE_TLV("EQ3 B4 Volume", CS48L32_EQ3_GAIN1, 24, 24, 0, cs48l32_eq_tlv),
2649e2bcbf99SRichard Fitzgerald SOC_SINGLE_TLV("EQ3 B5 Volume", CS48L32_EQ3_GAIN2, 0, 24, 0, cs48l32_eq_tlv),
2650e2bcbf99SRichard Fitzgerald
2651e2bcbf99SRichard Fitzgerald SOC_ENUM_EXT("EQ4 Mode", cs48l32_eq_mode[3], cs48l32_eq_mode_get, cs48l32_eq_mode_put),
2652e2bcbf99SRichard Fitzgerald CS48L32_EQ_COEFF_CONTROLS(EQ4),
2653e2bcbf99SRichard Fitzgerald SOC_SINGLE_TLV("EQ4 B1 Volume", CS48L32_EQ4_GAIN1, 0, 24, 0, cs48l32_eq_tlv),
2654e2bcbf99SRichard Fitzgerald SOC_SINGLE_TLV("EQ4 B2 Volume", CS48L32_EQ4_GAIN1, 8, 24, 0, cs48l32_eq_tlv),
2655e2bcbf99SRichard Fitzgerald SOC_SINGLE_TLV("EQ4 B3 Volume", CS48L32_EQ4_GAIN1, 16, 24, 0, cs48l32_eq_tlv),
2656e2bcbf99SRichard Fitzgerald SOC_SINGLE_TLV("EQ4 B4 Volume", CS48L32_EQ4_GAIN1, 24, 24, 0, cs48l32_eq_tlv),
2657e2bcbf99SRichard Fitzgerald SOC_SINGLE_TLV("EQ4 B5 Volume", CS48L32_EQ4_GAIN2, 0, 24, 0, cs48l32_eq_tlv),
2658e2bcbf99SRichard Fitzgerald
2659e2bcbf99SRichard Fitzgerald CS48L32_MIXER_CONTROLS("DRC1L", CS48L32_DRC1L_INPUT1),
2660e2bcbf99SRichard Fitzgerald CS48L32_MIXER_CONTROLS("DRC1R", CS48L32_DRC1R_INPUT1),
2661e2bcbf99SRichard Fitzgerald CS48L32_MIXER_CONTROLS("DRC2L", CS48L32_DRC2L_INPUT1),
2662e2bcbf99SRichard Fitzgerald CS48L32_MIXER_CONTROLS("DRC2R", CS48L32_DRC2R_INPUT1),
2663e2bcbf99SRichard Fitzgerald
2664e2bcbf99SRichard Fitzgerald SND_SOC_BYTES_MASK("DRC1 Coefficients", CS48L32_DRC1_CONTROL1, 4,
2665e2bcbf99SRichard Fitzgerald BIT(CS48L32_DRC1R_EN_SHIFT) | BIT(CS48L32_DRC1L_EN_SHIFT)),
2666e2bcbf99SRichard Fitzgerald SND_SOC_BYTES_MASK("DRC2 Coefficients", CS48L32_DRC2_CONTROL1, 4,
2667e2bcbf99SRichard Fitzgerald BIT(CS48L32_DRC1R_EN_SHIFT) | BIT(CS48L32_DRC1L_EN_SHIFT)),
2668e2bcbf99SRichard Fitzgerald
2669e2bcbf99SRichard Fitzgerald CS48L32_MIXER_CONTROLS("LHPF1", CS48L32_LHPF1_INPUT1),
2670e2bcbf99SRichard Fitzgerald CS48L32_MIXER_CONTROLS("LHPF2", CS48L32_LHPF2_INPUT1),
2671e2bcbf99SRichard Fitzgerald CS48L32_MIXER_CONTROLS("LHPF3", CS48L32_LHPF3_INPUT1),
2672e2bcbf99SRichard Fitzgerald CS48L32_MIXER_CONTROLS("LHPF4", CS48L32_LHPF4_INPUT1),
2673e2bcbf99SRichard Fitzgerald
2674e2bcbf99SRichard Fitzgerald CS48L32_LHPF_CONTROL("LHPF1 Coefficients", CS48L32_LHPF1_COEFF),
2675e2bcbf99SRichard Fitzgerald CS48L32_LHPF_CONTROL("LHPF2 Coefficients", CS48L32_LHPF2_COEFF),
2676e2bcbf99SRichard Fitzgerald CS48L32_LHPF_CONTROL("LHPF3 Coefficients", CS48L32_LHPF3_COEFF),
2677e2bcbf99SRichard Fitzgerald CS48L32_LHPF_CONTROL("LHPF4 Coefficients", CS48L32_LHPF4_COEFF),
2678e2bcbf99SRichard Fitzgerald
2679e2bcbf99SRichard Fitzgerald SOC_ENUM("LHPF1 Mode", cs48l32_lhpf_mode[0]),
2680e2bcbf99SRichard Fitzgerald SOC_ENUM("LHPF2 Mode", cs48l32_lhpf_mode[1]),
2681e2bcbf99SRichard Fitzgerald SOC_ENUM("LHPF3 Mode", cs48l32_lhpf_mode[2]),
2682e2bcbf99SRichard Fitzgerald SOC_ENUM("LHPF4 Mode", cs48l32_lhpf_mode[3]),
2683e2bcbf99SRichard Fitzgerald
2684e2bcbf99SRichard Fitzgerald CS48L32_RATE_CONTROL("Sample Rate 1", 1),
2685e2bcbf99SRichard Fitzgerald CS48L32_RATE_CONTROL("Sample Rate 2", 2),
2686e2bcbf99SRichard Fitzgerald CS48L32_RATE_CONTROL("Sample Rate 3", 3),
2687e2bcbf99SRichard Fitzgerald CS48L32_RATE_CONTROL("Sample Rate 4", 4),
2688e2bcbf99SRichard Fitzgerald
2689e2bcbf99SRichard Fitzgerald CS48L32_RATE_ENUM("FX Rate", cs48l32_fx_rate),
2690e2bcbf99SRichard Fitzgerald
2691e2bcbf99SRichard Fitzgerald CS48L32_RATE_ENUM("ISRC1 FSL", cs48l32_isrc_fsl[0]),
2692e2bcbf99SRichard Fitzgerald CS48L32_RATE_ENUM("ISRC2 FSL", cs48l32_isrc_fsl[1]),
2693e2bcbf99SRichard Fitzgerald CS48L32_RATE_ENUM("ISRC3 FSL", cs48l32_isrc_fsl[2]),
2694e2bcbf99SRichard Fitzgerald CS48L32_RATE_ENUM("ISRC1 FSH", cs48l32_isrc_fsh[0]),
2695e2bcbf99SRichard Fitzgerald CS48L32_RATE_ENUM("ISRC2 FSH", cs48l32_isrc_fsh[1]),
2696e2bcbf99SRichard Fitzgerald CS48L32_RATE_ENUM("ISRC3 FSH", cs48l32_isrc_fsh[2]),
2697e2bcbf99SRichard Fitzgerald
2698e2bcbf99SRichard Fitzgerald SOC_ENUM("AUXPDM1 Rate", cs48l32_auxpdm1_freq),
2699e2bcbf99SRichard Fitzgerald SOC_ENUM("AUXPDM2 Rate", cs48l32_auxpdm2_freq),
2700e2bcbf99SRichard Fitzgerald
2701e2bcbf99SRichard Fitzgerald SOC_ENUM_EXT("IN1L Rate", cs48l32_input_rate[0], snd_soc_get_enum_double, cs48l32_in_rate_put),
2702e2bcbf99SRichard Fitzgerald SOC_ENUM_EXT("IN1R Rate", cs48l32_input_rate[1], snd_soc_get_enum_double, cs48l32_in_rate_put),
2703e2bcbf99SRichard Fitzgerald SOC_ENUM_EXT("IN2L Rate", cs48l32_input_rate[2], snd_soc_get_enum_double, cs48l32_in_rate_put),
2704e2bcbf99SRichard Fitzgerald SOC_ENUM_EXT("IN2R Rate", cs48l32_input_rate[3], snd_soc_get_enum_double, cs48l32_in_rate_put),
2705e2bcbf99SRichard Fitzgerald
2706e2bcbf99SRichard Fitzgerald CS48L32_RATE_ENUM("Noise Generator Rate", noise_gen_rate),
2707e2bcbf99SRichard Fitzgerald
2708e2bcbf99SRichard Fitzgerald SOC_SINGLE_TLV("Noise Generator Volume", CS48L32_COMFORT_NOISE_GENERATOR,
2709e2bcbf99SRichard Fitzgerald CS48L32_NOISE_GEN_GAIN_SHIFT, 0x12, 0, cs48l32_noise_tlv),
2710e2bcbf99SRichard Fitzgerald
2711e2bcbf99SRichard Fitzgerald CS48L32_MIXER_CONTROLS("ASP1TX1", CS48L32_ASP1TX1_INPUT1),
2712e2bcbf99SRichard Fitzgerald CS48L32_MIXER_CONTROLS("ASP1TX2", CS48L32_ASP1TX2_INPUT1),
2713e2bcbf99SRichard Fitzgerald CS48L32_MIXER_CONTROLS("ASP1TX3", CS48L32_ASP1TX3_INPUT1),
2714e2bcbf99SRichard Fitzgerald CS48L32_MIXER_CONTROLS("ASP1TX4", CS48L32_ASP1TX4_INPUT1),
2715e2bcbf99SRichard Fitzgerald CS48L32_MIXER_CONTROLS("ASP1TX5", CS48L32_ASP1TX5_INPUT1),
2716e2bcbf99SRichard Fitzgerald CS48L32_MIXER_CONTROLS("ASP1TX6", CS48L32_ASP1TX6_INPUT1),
2717e2bcbf99SRichard Fitzgerald CS48L32_MIXER_CONTROLS("ASP1TX7", CS48L32_ASP1TX7_INPUT1),
2718e2bcbf99SRichard Fitzgerald CS48L32_MIXER_CONTROLS("ASP1TX8", CS48L32_ASP1TX8_INPUT1),
2719e2bcbf99SRichard Fitzgerald
2720e2bcbf99SRichard Fitzgerald CS48L32_MIXER_CONTROLS("ASP2TX1", CS48L32_ASP2TX1_INPUT1),
2721e2bcbf99SRichard Fitzgerald CS48L32_MIXER_CONTROLS("ASP2TX2", CS48L32_ASP2TX2_INPUT1),
2722e2bcbf99SRichard Fitzgerald CS48L32_MIXER_CONTROLS("ASP2TX3", CS48L32_ASP2TX3_INPUT1),
2723e2bcbf99SRichard Fitzgerald CS48L32_MIXER_CONTROLS("ASP2TX4", CS48L32_ASP2TX4_INPUT1),
2724e2bcbf99SRichard Fitzgerald
2725e2bcbf99SRichard Fitzgerald WM_ADSP2_PRELOAD_SWITCH("DSP1", 1),
2726e2bcbf99SRichard Fitzgerald
2727e2bcbf99SRichard Fitzgerald CS48L32_MIXER_CONTROLS("DSP1RX1", CS48L32_DSP1RX1_INPUT1),
2728e2bcbf99SRichard Fitzgerald CS48L32_MIXER_CONTROLS("DSP1RX2", CS48L32_DSP1RX2_INPUT1),
2729e2bcbf99SRichard Fitzgerald CS48L32_MIXER_CONTROLS("DSP1RX3", CS48L32_DSP1RX3_INPUT1),
2730e2bcbf99SRichard Fitzgerald CS48L32_MIXER_CONTROLS("DSP1RX4", CS48L32_DSP1RX4_INPUT1),
2731e2bcbf99SRichard Fitzgerald CS48L32_MIXER_CONTROLS("DSP1RX5", CS48L32_DSP1RX5_INPUT1),
2732e2bcbf99SRichard Fitzgerald CS48L32_MIXER_CONTROLS("DSP1RX6", CS48L32_DSP1RX6_INPUT1),
2733e2bcbf99SRichard Fitzgerald CS48L32_MIXER_CONTROLS("DSP1RX7", CS48L32_DSP1RX7_INPUT1),
2734e2bcbf99SRichard Fitzgerald CS48L32_MIXER_CONTROLS("DSP1RX8", CS48L32_DSP1RX8_INPUT1),
2735e2bcbf99SRichard Fitzgerald
2736e2bcbf99SRichard Fitzgerald WM_ADSP_FW_CONTROL("DSP1", 0),
2737e2bcbf99SRichard Fitzgerald
2738e2bcbf99SRichard Fitzgerald CS48L32_DSP_RATE_CONTROL("DSP1RX1", 0),
2739e2bcbf99SRichard Fitzgerald CS48L32_DSP_RATE_CONTROL("DSP1RX2", 1),
2740e2bcbf99SRichard Fitzgerald CS48L32_DSP_RATE_CONTROL("DSP1RX3", 2),
2741e2bcbf99SRichard Fitzgerald CS48L32_DSP_RATE_CONTROL("DSP1RX4", 3),
2742e2bcbf99SRichard Fitzgerald CS48L32_DSP_RATE_CONTROL("DSP1RX5", 4),
2743e2bcbf99SRichard Fitzgerald CS48L32_DSP_RATE_CONTROL("DSP1RX6", 5),
2744e2bcbf99SRichard Fitzgerald CS48L32_DSP_RATE_CONTROL("DSP1RX7", 6),
2745e2bcbf99SRichard Fitzgerald CS48L32_DSP_RATE_CONTROL("DSP1RX8", 7),
2746e2bcbf99SRichard Fitzgerald CS48L32_DSP_RATE_CONTROL("DSP1TX1", 8),
2747e2bcbf99SRichard Fitzgerald CS48L32_DSP_RATE_CONTROL("DSP1TX2", 9),
2748e2bcbf99SRichard Fitzgerald CS48L32_DSP_RATE_CONTROL("DSP1TX3", 10),
2749e2bcbf99SRichard Fitzgerald CS48L32_DSP_RATE_CONTROL("DSP1TX4", 11),
2750e2bcbf99SRichard Fitzgerald CS48L32_DSP_RATE_CONTROL("DSP1TX5", 12),
2751e2bcbf99SRichard Fitzgerald CS48L32_DSP_RATE_CONTROL("DSP1TX6", 13),
2752e2bcbf99SRichard Fitzgerald CS48L32_DSP_RATE_CONTROL("DSP1TX7", 14),
2753e2bcbf99SRichard Fitzgerald CS48L32_DSP_RATE_CONTROL("DSP1TX8", 15),
2754e2bcbf99SRichard Fitzgerald };
2755e2bcbf99SRichard Fitzgerald
2756e2bcbf99SRichard Fitzgerald CS48L32_MIXER_ENUMS(EQ1, CS48L32_EQ1_INPUT1);
2757e2bcbf99SRichard Fitzgerald CS48L32_MIXER_ENUMS(EQ2, CS48L32_EQ2_INPUT1);
2758e2bcbf99SRichard Fitzgerald CS48L32_MIXER_ENUMS(EQ3, CS48L32_EQ3_INPUT1);
2759e2bcbf99SRichard Fitzgerald CS48L32_MIXER_ENUMS(EQ4, CS48L32_EQ4_INPUT1);
2760e2bcbf99SRichard Fitzgerald
2761e2bcbf99SRichard Fitzgerald CS48L32_MIXER_ENUMS(DRC1L, CS48L32_DRC1L_INPUT1);
2762e2bcbf99SRichard Fitzgerald CS48L32_MIXER_ENUMS(DRC1R, CS48L32_DRC1R_INPUT1);
2763e2bcbf99SRichard Fitzgerald CS48L32_MIXER_ENUMS(DRC2L, CS48L32_DRC2L_INPUT1);
2764e2bcbf99SRichard Fitzgerald CS48L32_MIXER_ENUMS(DRC2R, CS48L32_DRC2R_INPUT1);
2765e2bcbf99SRichard Fitzgerald
2766e2bcbf99SRichard Fitzgerald CS48L32_MIXER_ENUMS(LHPF1, CS48L32_LHPF1_INPUT1);
2767e2bcbf99SRichard Fitzgerald CS48L32_MIXER_ENUMS(LHPF2, CS48L32_LHPF2_INPUT1);
2768e2bcbf99SRichard Fitzgerald CS48L32_MIXER_ENUMS(LHPF3, CS48L32_LHPF3_INPUT1);
2769e2bcbf99SRichard Fitzgerald CS48L32_MIXER_ENUMS(LHPF4, CS48L32_LHPF4_INPUT1);
2770e2bcbf99SRichard Fitzgerald
2771e2bcbf99SRichard Fitzgerald CS48L32_MIXER_ENUMS(ASP1TX1, CS48L32_ASP1TX1_INPUT1);
2772e2bcbf99SRichard Fitzgerald CS48L32_MIXER_ENUMS(ASP1TX2, CS48L32_ASP1TX2_INPUT1);
2773e2bcbf99SRichard Fitzgerald CS48L32_MIXER_ENUMS(ASP1TX3, CS48L32_ASP1TX3_INPUT1);
2774e2bcbf99SRichard Fitzgerald CS48L32_MIXER_ENUMS(ASP1TX4, CS48L32_ASP1TX4_INPUT1);
2775e2bcbf99SRichard Fitzgerald CS48L32_MIXER_ENUMS(ASP1TX5, CS48L32_ASP1TX5_INPUT1);
2776e2bcbf99SRichard Fitzgerald CS48L32_MIXER_ENUMS(ASP1TX6, CS48L32_ASP1TX6_INPUT1);
2777e2bcbf99SRichard Fitzgerald CS48L32_MIXER_ENUMS(ASP1TX7, CS48L32_ASP1TX7_INPUT1);
2778e2bcbf99SRichard Fitzgerald CS48L32_MIXER_ENUMS(ASP1TX8, CS48L32_ASP1TX8_INPUT1);
2779e2bcbf99SRichard Fitzgerald
2780e2bcbf99SRichard Fitzgerald CS48L32_MIXER_ENUMS(ASP2TX1, CS48L32_ASP2TX1_INPUT1);
2781e2bcbf99SRichard Fitzgerald CS48L32_MIXER_ENUMS(ASP2TX2, CS48L32_ASP2TX2_INPUT1);
2782e2bcbf99SRichard Fitzgerald CS48L32_MIXER_ENUMS(ASP2TX3, CS48L32_ASP2TX3_INPUT1);
2783e2bcbf99SRichard Fitzgerald CS48L32_MIXER_ENUMS(ASP2TX4, CS48L32_ASP2TX4_INPUT1);
2784e2bcbf99SRichard Fitzgerald
2785e2bcbf99SRichard Fitzgerald CS48L32_MUX_ENUMS(ISRC1INT1, CS48L32_ISRC1INT1_INPUT1);
2786e2bcbf99SRichard Fitzgerald CS48L32_MUX_ENUMS(ISRC1INT2, CS48L32_ISRC1INT2_INPUT1);
2787e2bcbf99SRichard Fitzgerald CS48L32_MUX_ENUMS(ISRC1INT3, CS48L32_ISRC1INT3_INPUT1);
2788e2bcbf99SRichard Fitzgerald CS48L32_MUX_ENUMS(ISRC1INT4, CS48L32_ISRC1INT4_INPUT1);
2789e2bcbf99SRichard Fitzgerald
2790e2bcbf99SRichard Fitzgerald CS48L32_MUX_ENUMS(ISRC1DEC1, CS48L32_ISRC1DEC1_INPUT1);
2791e2bcbf99SRichard Fitzgerald CS48L32_MUX_ENUMS(ISRC1DEC2, CS48L32_ISRC1DEC2_INPUT1);
2792e2bcbf99SRichard Fitzgerald CS48L32_MUX_ENUMS(ISRC1DEC3, CS48L32_ISRC1DEC3_INPUT1);
2793e2bcbf99SRichard Fitzgerald CS48L32_MUX_ENUMS(ISRC1DEC4, CS48L32_ISRC1DEC4_INPUT1);
2794e2bcbf99SRichard Fitzgerald
2795e2bcbf99SRichard Fitzgerald CS48L32_MUX_ENUMS(ISRC2INT1, CS48L32_ISRC2INT1_INPUT1);
2796e2bcbf99SRichard Fitzgerald CS48L32_MUX_ENUMS(ISRC2INT2, CS48L32_ISRC2INT2_INPUT1);
2797e2bcbf99SRichard Fitzgerald
2798e2bcbf99SRichard Fitzgerald CS48L32_MUX_ENUMS(ISRC2DEC1, CS48L32_ISRC2DEC1_INPUT1);
2799e2bcbf99SRichard Fitzgerald CS48L32_MUX_ENUMS(ISRC2DEC2, CS48L32_ISRC2DEC2_INPUT1);
2800e2bcbf99SRichard Fitzgerald
2801e2bcbf99SRichard Fitzgerald CS48L32_MUX_ENUMS(ISRC3INT1, CS48L32_ISRC3INT1_INPUT1);
2802e2bcbf99SRichard Fitzgerald CS48L32_MUX_ENUMS(ISRC3INT2, CS48L32_ISRC3INT2_INPUT1);
2803e2bcbf99SRichard Fitzgerald
2804e2bcbf99SRichard Fitzgerald CS48L32_MUX_ENUMS(ISRC3DEC1, CS48L32_ISRC3DEC1_INPUT1);
2805e2bcbf99SRichard Fitzgerald CS48L32_MUX_ENUMS(ISRC3DEC2, CS48L32_ISRC3DEC2_INPUT1);
2806e2bcbf99SRichard Fitzgerald
2807e2bcbf99SRichard Fitzgerald CS48L32_MIXER_ENUMS(DSP1RX1, CS48L32_DSP1RX1_INPUT1);
2808e2bcbf99SRichard Fitzgerald CS48L32_MIXER_ENUMS(DSP1RX2, CS48L32_DSP1RX2_INPUT1);
2809e2bcbf99SRichard Fitzgerald CS48L32_MIXER_ENUMS(DSP1RX3, CS48L32_DSP1RX3_INPUT1);
2810e2bcbf99SRichard Fitzgerald CS48L32_MIXER_ENUMS(DSP1RX4, CS48L32_DSP1RX4_INPUT1);
2811e2bcbf99SRichard Fitzgerald CS48L32_MIXER_ENUMS(DSP1RX5, CS48L32_DSP1RX5_INPUT1);
2812e2bcbf99SRichard Fitzgerald CS48L32_MIXER_ENUMS(DSP1RX6, CS48L32_DSP1RX6_INPUT1);
2813e2bcbf99SRichard Fitzgerald CS48L32_MIXER_ENUMS(DSP1RX7, CS48L32_DSP1RX7_INPUT1);
2814e2bcbf99SRichard Fitzgerald CS48L32_MIXER_ENUMS(DSP1RX8, CS48L32_DSP1RX8_INPUT1);
2815e2bcbf99SRichard Fitzgerald
cs48l32_dsp_mem_ev(struct snd_soc_dapm_widget * w,struct snd_kcontrol * kcontrol,int event)2816e2bcbf99SRichard Fitzgerald static int cs48l32_dsp_mem_ev(struct snd_soc_dapm_widget *w,
2817e2bcbf99SRichard Fitzgerald struct snd_kcontrol *kcontrol, int event)
2818e2bcbf99SRichard Fitzgerald {
2819e2bcbf99SRichard Fitzgerald struct snd_soc_component *component = snd_soc_dapm_to_component(w->dapm);
2820e2bcbf99SRichard Fitzgerald struct cs48l32_codec *cs48l32_codec = snd_soc_component_get_drvdata(component);
2821e2bcbf99SRichard Fitzgerald
2822e2bcbf99SRichard Fitzgerald switch (event) {
2823e2bcbf99SRichard Fitzgerald case SND_SOC_DAPM_POST_PMU:
2824e2bcbf99SRichard Fitzgerald return cs48l32_dsp_memory_enable(cs48l32_codec, &cs48l32_dsp_sram_regs);
2825e2bcbf99SRichard Fitzgerald case SND_SOC_DAPM_PRE_PMD:
2826e2bcbf99SRichard Fitzgerald cs48l32_dsp_memory_disable(cs48l32_codec, &cs48l32_dsp_sram_regs);
2827e2bcbf99SRichard Fitzgerald return 0;
2828e2bcbf99SRichard Fitzgerald default:
2829e2bcbf99SRichard Fitzgerald return 0;
2830e2bcbf99SRichard Fitzgerald }
2831e2bcbf99SRichard Fitzgerald }
2832e2bcbf99SRichard Fitzgerald
2833e2bcbf99SRichard Fitzgerald static const struct snd_soc_dapm_widget cs48l32_dapm_widgets[] = {
2834e2bcbf99SRichard Fitzgerald SND_SOC_DAPM_SUPPLY("SYSCLK", CS48L32_SYSTEM_CLOCK1, CS48L32_SYSCLK_EN_SHIFT, 0,
2835e2bcbf99SRichard Fitzgerald cs48l32_sysclk_ev, SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD),
2836e2bcbf99SRichard Fitzgerald
2837e2bcbf99SRichard Fitzgerald SND_SOC_DAPM_REGULATOR_SUPPLY("vdd-cp", 20, 0),
2838e2bcbf99SRichard Fitzgerald
2839e2bcbf99SRichard Fitzgerald SND_SOC_DAPM_SUPPLY("VOUT_MIC", CS48L32_CHARGE_PUMP1, CS48L32_CP2_EN_SHIFT, 0, NULL, 0),
2840e2bcbf99SRichard Fitzgerald SND_SOC_DAPM_SUPPLY("VOUT_MIC_REGULATED", CS48L32_CHARGE_PUMP1, CS48L32_CP2_BYPASS_SHIFT,
2841e2bcbf99SRichard Fitzgerald 1, NULL, 0),
2842e2bcbf99SRichard Fitzgerald SND_SOC_DAPM_SUPPLY("MICBIAS1", CS48L32_MICBIAS_CTRL1, CS48L32_MICB1_EN_SHIFT, 0, NULL, 0),
2843e2bcbf99SRichard Fitzgerald SND_SOC_DAPM_SUPPLY("MICBIAS1A", CS48L32_MICBIAS_CTRL5, CS48L32_MICB1A_EN_SHIFT, 0, NULL, 0),
2844e2bcbf99SRichard Fitzgerald SND_SOC_DAPM_SUPPLY("MICBIAS1B", CS48L32_MICBIAS_CTRL5, CS48L32_MICB1B_EN_SHIFT, 0, NULL, 0),
2845e2bcbf99SRichard Fitzgerald SND_SOC_DAPM_SUPPLY("MICBIAS1C", CS48L32_MICBIAS_CTRL5, CS48L32_MICB1C_EN_SHIFT, 0, NULL, 0),
2846e2bcbf99SRichard Fitzgerald
2847e2bcbf99SRichard Fitzgerald SND_SOC_DAPM_SUPPLY("DSP1MEM", SND_SOC_NOPM, 0, 0, cs48l32_dsp_mem_ev,
2848e2bcbf99SRichard Fitzgerald SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD),
2849e2bcbf99SRichard Fitzgerald
2850e2bcbf99SRichard Fitzgerald CS48L32_DSP_FREQ_WIDGET_EV("DSP1", 0, cs48l32_dsp_freq_ev),
2851e2bcbf99SRichard Fitzgerald
2852e2bcbf99SRichard Fitzgerald SND_SOC_DAPM_SIGGEN("TONE"),
2853e2bcbf99SRichard Fitzgerald SND_SOC_DAPM_SIGGEN("NOISE"),
2854e2bcbf99SRichard Fitzgerald
2855e2bcbf99SRichard Fitzgerald SND_SOC_DAPM_INPUT("IN1LN_1"),
2856e2bcbf99SRichard Fitzgerald SND_SOC_DAPM_INPUT("IN1LN_2"),
2857e2bcbf99SRichard Fitzgerald SND_SOC_DAPM_INPUT("IN1LP_1"),
2858e2bcbf99SRichard Fitzgerald SND_SOC_DAPM_INPUT("IN1LP_2"),
2859e2bcbf99SRichard Fitzgerald SND_SOC_DAPM_INPUT("IN1RN_1"),
2860e2bcbf99SRichard Fitzgerald SND_SOC_DAPM_INPUT("IN1RN_2"),
2861e2bcbf99SRichard Fitzgerald SND_SOC_DAPM_INPUT("IN1RP_1"),
2862e2bcbf99SRichard Fitzgerald SND_SOC_DAPM_INPUT("IN1RP_2"),
2863e2bcbf99SRichard Fitzgerald SND_SOC_DAPM_INPUT("IN1_PDMCLK"),
2864e2bcbf99SRichard Fitzgerald SND_SOC_DAPM_INPUT("IN1_PDMDATA"),
2865e2bcbf99SRichard Fitzgerald
2866e2bcbf99SRichard Fitzgerald SND_SOC_DAPM_INPUT("IN2_PDMCLK"),
2867e2bcbf99SRichard Fitzgerald SND_SOC_DAPM_INPUT("IN2_PDMDATA"),
2868e2bcbf99SRichard Fitzgerald
2869e2bcbf99SRichard Fitzgerald SND_SOC_DAPM_MUX("Ultrasonic 1 Input", SND_SOC_NOPM, 0, 0, &cs48l32_us_inmux[0]),
2870e2bcbf99SRichard Fitzgerald SND_SOC_DAPM_MUX("Ultrasonic 2 Input", SND_SOC_NOPM, 0, 0, &cs48l32_us_inmux[1]),
2871e2bcbf99SRichard Fitzgerald
2872e2bcbf99SRichard Fitzgerald SND_SOC_DAPM_OUTPUT("DRC1 Signal Activity"),
2873e2bcbf99SRichard Fitzgerald SND_SOC_DAPM_OUTPUT("DRC2 Signal Activity"),
2874e2bcbf99SRichard Fitzgerald
2875e2bcbf99SRichard Fitzgerald SND_SOC_DAPM_OUTPUT("DSP Trigger Out"),
2876e2bcbf99SRichard Fitzgerald
2877e2bcbf99SRichard Fitzgerald SND_SOC_DAPM_MUX("IN1L Mux", SND_SOC_NOPM, 0, 0, &cs48l32_inmux[0]),
2878e2bcbf99SRichard Fitzgerald SND_SOC_DAPM_MUX("IN1R Mux", SND_SOC_NOPM, 0, 0, &cs48l32_inmux[1]),
2879e2bcbf99SRichard Fitzgerald
2880e2bcbf99SRichard Fitzgerald SND_SOC_DAPM_MUX("IN1L Mode", SND_SOC_NOPM, 0, 0, &cs48l32_dmode_mux[0]),
2881e2bcbf99SRichard Fitzgerald SND_SOC_DAPM_MUX("IN1R Mode", SND_SOC_NOPM, 0, 0, &cs48l32_dmode_mux[0]),
2882e2bcbf99SRichard Fitzgerald
2883e2bcbf99SRichard Fitzgerald SND_SOC_DAPM_AIF_OUT("ASP1TX1", NULL, 0, CS48L32_ASP1_ENABLES1, 0, 0),
2884e2bcbf99SRichard Fitzgerald SND_SOC_DAPM_AIF_OUT("ASP1TX2", NULL, 1, CS48L32_ASP1_ENABLES1, 1, 0),
2885e2bcbf99SRichard Fitzgerald SND_SOC_DAPM_AIF_OUT("ASP1TX3", NULL, 2, CS48L32_ASP1_ENABLES1, 2, 0),
2886e2bcbf99SRichard Fitzgerald SND_SOC_DAPM_AIF_OUT("ASP1TX4", NULL, 3, CS48L32_ASP1_ENABLES1, 3, 0),
2887e2bcbf99SRichard Fitzgerald SND_SOC_DAPM_AIF_OUT("ASP1TX5", NULL, 4, CS48L32_ASP1_ENABLES1, 4, 0),
2888e2bcbf99SRichard Fitzgerald SND_SOC_DAPM_AIF_OUT("ASP1TX6", NULL, 5, CS48L32_ASP1_ENABLES1, 5, 0),
2889e2bcbf99SRichard Fitzgerald SND_SOC_DAPM_AIF_OUT("ASP1TX7", NULL, 6, CS48L32_ASP1_ENABLES1, 6, 0),
2890e2bcbf99SRichard Fitzgerald SND_SOC_DAPM_AIF_OUT("ASP1TX8", NULL, 7, CS48L32_ASP1_ENABLES1, 7, 0),
2891e2bcbf99SRichard Fitzgerald
2892e2bcbf99SRichard Fitzgerald SND_SOC_DAPM_AIF_OUT("ASP2TX1", NULL, 0, CS48L32_ASP2_ENABLES1, 0, 0),
2893e2bcbf99SRichard Fitzgerald SND_SOC_DAPM_AIF_OUT("ASP2TX2", NULL, 1, CS48L32_ASP2_ENABLES1, 1, 0),
2894e2bcbf99SRichard Fitzgerald SND_SOC_DAPM_AIF_OUT("ASP2TX3", NULL, 2, CS48L32_ASP2_ENABLES1, 2, 0),
2895e2bcbf99SRichard Fitzgerald SND_SOC_DAPM_AIF_OUT("ASP2TX4", NULL, 3, CS48L32_ASP2_ENABLES1, 3, 0),
2896e2bcbf99SRichard Fitzgerald
2897e2bcbf99SRichard Fitzgerald SND_SOC_DAPM_SWITCH("AUXPDM1 Output", CS48L32_AUXPDM_CONTROL1, 0, 0, &cs48l32_auxpdm_switch[0]),
2898e2bcbf99SRichard Fitzgerald SND_SOC_DAPM_SWITCH("AUXPDM2 Output", CS48L32_AUXPDM_CONTROL1, 1, 0, &cs48l32_auxpdm_switch[1]),
2899e2bcbf99SRichard Fitzgerald
2900e2bcbf99SRichard Fitzgerald SND_SOC_DAPM_MUX("AUXPDM1 Input", SND_SOC_NOPM, 0, 0, &cs48l32_auxpdm_inmux[0]),
2901e2bcbf99SRichard Fitzgerald SND_SOC_DAPM_MUX("AUXPDM2 Input", SND_SOC_NOPM, 0, 0, &cs48l32_auxpdm_inmux[1]),
2902e2bcbf99SRichard Fitzgerald
2903e2bcbf99SRichard Fitzgerald SND_SOC_DAPM_MUX("AUXPDM1 Analog Input", SND_SOC_NOPM, 0, 0,
2904e2bcbf99SRichard Fitzgerald &cs48l32_auxpdm_analog_inmux[0]),
2905e2bcbf99SRichard Fitzgerald SND_SOC_DAPM_MUX("AUXPDM2 Analog Input", SND_SOC_NOPM, 0, 0,
2906e2bcbf99SRichard Fitzgerald &cs48l32_auxpdm_analog_inmux[1]),
2907e2bcbf99SRichard Fitzgerald
2908e2bcbf99SRichard Fitzgerald SND_SOC_DAPM_SWITCH("Ultrasonic 1 Detect", CS48L32_US_CONTROL,
2909e2bcbf99SRichard Fitzgerald CS48L32_US1_DET_EN_SHIFT, 0, &cs48l32_us_switch[0]),
2910e2bcbf99SRichard Fitzgerald SND_SOC_DAPM_SWITCH("Ultrasonic 2 Detect", CS48L32_US_CONTROL,
2911e2bcbf99SRichard Fitzgerald CS48L32_US1_DET_EN_SHIFT, 0, &cs48l32_us_switch[1]),
2912e2bcbf99SRichard Fitzgerald
2913e2bcbf99SRichard Fitzgerald /*
2914e2bcbf99SRichard Fitzgerald * mux_in widgets : arranged in the order of sources
2915e2bcbf99SRichard Fitzgerald * specified in CS48L32_MIXER_INPUT_ROUTES
2916e2bcbf99SRichard Fitzgerald */
2917e2bcbf99SRichard Fitzgerald SND_SOC_DAPM_PGA("Tone Generator 1", CS48L32_TONE_GENERATOR1, 0, 0, NULL, 0),
2918e2bcbf99SRichard Fitzgerald SND_SOC_DAPM_PGA("Tone Generator 2", CS48L32_TONE_GENERATOR1, 1, 0, NULL, 0),
2919e2bcbf99SRichard Fitzgerald
2920e2bcbf99SRichard Fitzgerald SND_SOC_DAPM_PGA("Noise Generator", CS48L32_COMFORT_NOISE_GENERATOR,
2921e2bcbf99SRichard Fitzgerald CS48L32_NOISE_GEN_EN_SHIFT, 0, NULL, 0),
2922e2bcbf99SRichard Fitzgerald
2923e2bcbf99SRichard Fitzgerald SND_SOC_DAPM_PGA_E("IN1L PGA", CS48L32_INPUT_CONTROL, CS48L32_IN1L_EN_SHIFT,
2924e2bcbf99SRichard Fitzgerald 0, NULL, 0, cs48l32_in_ev,
2925e2bcbf99SRichard Fitzgerald SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU),
2926e2bcbf99SRichard Fitzgerald SND_SOC_DAPM_PGA_E("IN1R PGA", CS48L32_INPUT_CONTROL, CS48L32_IN1R_EN_SHIFT,
2927e2bcbf99SRichard Fitzgerald 0, NULL, 0, cs48l32_in_ev,
2928e2bcbf99SRichard Fitzgerald SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU),
2929e2bcbf99SRichard Fitzgerald SND_SOC_DAPM_PGA_E("IN2L PGA", CS48L32_INPUT_CONTROL, CS48L32_IN2L_EN_SHIFT,
2930e2bcbf99SRichard Fitzgerald 0, NULL, 0, cs48l32_in_ev,
2931e2bcbf99SRichard Fitzgerald SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU),
2932e2bcbf99SRichard Fitzgerald SND_SOC_DAPM_PGA_E("IN2R PGA", CS48L32_INPUT_CONTROL, CS48L32_IN2R_EN_SHIFT,
2933e2bcbf99SRichard Fitzgerald 0, NULL, 0, cs48l32_in_ev,
2934e2bcbf99SRichard Fitzgerald SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU),
2935e2bcbf99SRichard Fitzgerald
2936e2bcbf99SRichard Fitzgerald SND_SOC_DAPM_AIF_IN("ASP1RX1", NULL, 0, CS48L32_ASP1_ENABLES1, 16, 0),
2937e2bcbf99SRichard Fitzgerald SND_SOC_DAPM_AIF_IN("ASP1RX2", NULL, 1, CS48L32_ASP1_ENABLES1, 17, 0),
2938e2bcbf99SRichard Fitzgerald SND_SOC_DAPM_AIF_IN("ASP1RX3", NULL, 2, CS48L32_ASP1_ENABLES1, 18, 0),
2939e2bcbf99SRichard Fitzgerald SND_SOC_DAPM_AIF_IN("ASP1RX4", NULL, 3, CS48L32_ASP1_ENABLES1, 19, 0),
2940e2bcbf99SRichard Fitzgerald SND_SOC_DAPM_AIF_IN("ASP1RX5", NULL, 4, CS48L32_ASP1_ENABLES1, 20, 0),
2941e2bcbf99SRichard Fitzgerald SND_SOC_DAPM_AIF_IN("ASP1RX6", NULL, 5, CS48L32_ASP1_ENABLES1, 21, 0),
2942e2bcbf99SRichard Fitzgerald SND_SOC_DAPM_AIF_IN("ASP1RX7", NULL, 6, CS48L32_ASP1_ENABLES1, 22, 0),
2943e2bcbf99SRichard Fitzgerald SND_SOC_DAPM_AIF_IN("ASP1RX8", NULL, 7, CS48L32_ASP1_ENABLES1, 23, 0),
2944e2bcbf99SRichard Fitzgerald
2945e2bcbf99SRichard Fitzgerald SND_SOC_DAPM_AIF_IN("ASP2RX1", NULL, 0, CS48L32_ASP2_ENABLES1, 16, 0),
2946e2bcbf99SRichard Fitzgerald SND_SOC_DAPM_AIF_IN("ASP2RX2", NULL, 1, CS48L32_ASP2_ENABLES1, 17, 0),
2947e2bcbf99SRichard Fitzgerald SND_SOC_DAPM_AIF_IN("ASP2RX3", NULL, 2, CS48L32_ASP2_ENABLES1, 18, 0),
2948e2bcbf99SRichard Fitzgerald SND_SOC_DAPM_AIF_IN("ASP2RX4", NULL, 3, CS48L32_ASP2_ENABLES1, 19, 0),
2949e2bcbf99SRichard Fitzgerald
2950e2bcbf99SRichard Fitzgerald SND_SOC_DAPM_PGA("ISRC1DEC1", CS48L32_ISRC1_CONTROL2, CS48L32_ISRC1_DEC1_EN_SHIFT, 0, NULL, 0),
2951e2bcbf99SRichard Fitzgerald SND_SOC_DAPM_PGA("ISRC1DEC2", CS48L32_ISRC1_CONTROL2, CS48L32_ISRC1_DEC2_EN_SHIFT, 0, NULL, 0),
2952e2bcbf99SRichard Fitzgerald SND_SOC_DAPM_PGA("ISRC1DEC3", CS48L32_ISRC1_CONTROL2, CS48L32_ISRC1_DEC3_EN_SHIFT, 0, NULL, 0),
2953e2bcbf99SRichard Fitzgerald SND_SOC_DAPM_PGA("ISRC1DEC4", CS48L32_ISRC1_CONTROL2, CS48L32_ISRC1_DEC4_EN_SHIFT, 0, NULL, 0),
2954e2bcbf99SRichard Fitzgerald
2955e2bcbf99SRichard Fitzgerald SND_SOC_DAPM_PGA("ISRC1INT1", CS48L32_ISRC1_CONTROL2, CS48L32_ISRC1_INT1_EN_SHIFT, 0, NULL, 0),
2956e2bcbf99SRichard Fitzgerald SND_SOC_DAPM_PGA("ISRC1INT2", CS48L32_ISRC1_CONTROL2, CS48L32_ISRC1_INT2_EN_SHIFT, 0, NULL, 0),
2957e2bcbf99SRichard Fitzgerald SND_SOC_DAPM_PGA("ISRC1INT3", CS48L32_ISRC1_CONTROL2, CS48L32_ISRC1_INT3_EN_SHIFT, 0, NULL, 0),
2958e2bcbf99SRichard Fitzgerald SND_SOC_DAPM_PGA("ISRC1INT4", CS48L32_ISRC1_CONTROL2, CS48L32_ISRC1_INT4_EN_SHIFT, 0, NULL, 0),
2959e2bcbf99SRichard Fitzgerald
2960e2bcbf99SRichard Fitzgerald SND_SOC_DAPM_PGA("ISRC2DEC1", CS48L32_ISRC2_CONTROL2, CS48L32_ISRC1_DEC1_EN_SHIFT, 0, NULL, 0),
2961e2bcbf99SRichard Fitzgerald SND_SOC_DAPM_PGA("ISRC2DEC2", CS48L32_ISRC2_CONTROL2, CS48L32_ISRC1_DEC2_EN_SHIFT, 0, NULL, 0),
2962e2bcbf99SRichard Fitzgerald
2963e2bcbf99SRichard Fitzgerald SND_SOC_DAPM_PGA("ISRC2INT1", CS48L32_ISRC2_CONTROL2, CS48L32_ISRC1_INT1_EN_SHIFT, 0, NULL, 0),
2964e2bcbf99SRichard Fitzgerald SND_SOC_DAPM_PGA("ISRC2INT2", CS48L32_ISRC2_CONTROL2, CS48L32_ISRC1_INT2_EN_SHIFT, 0, NULL, 0),
2965e2bcbf99SRichard Fitzgerald
2966e2bcbf99SRichard Fitzgerald SND_SOC_DAPM_PGA("ISRC3DEC1", CS48L32_ISRC3_CONTROL2, CS48L32_ISRC1_DEC1_EN_SHIFT, 0, NULL, 0),
2967e2bcbf99SRichard Fitzgerald SND_SOC_DAPM_PGA("ISRC3DEC2", CS48L32_ISRC3_CONTROL2, CS48L32_ISRC1_DEC2_EN_SHIFT, 0, NULL, 0),
2968e2bcbf99SRichard Fitzgerald
2969e2bcbf99SRichard Fitzgerald SND_SOC_DAPM_PGA("ISRC3INT1", CS48L32_ISRC3_CONTROL2, CS48L32_ISRC1_INT1_EN_SHIFT, 0, NULL, 0),
2970e2bcbf99SRichard Fitzgerald SND_SOC_DAPM_PGA("ISRC3INT2", CS48L32_ISRC3_CONTROL2, CS48L32_ISRC1_INT2_EN_SHIFT, 0, NULL, 0),
2971e2bcbf99SRichard Fitzgerald
2972e2bcbf99SRichard Fitzgerald SND_SOC_DAPM_PGA_E("EQ1", CS48L32_EQ_CONTROL1, 0, 0, NULL, 0, cs48l32_eq_ev, SND_SOC_DAPM_PRE_PMU),
2973e2bcbf99SRichard Fitzgerald SND_SOC_DAPM_PGA_E("EQ2", CS48L32_EQ_CONTROL1, 1, 0, NULL, 0, cs48l32_eq_ev, SND_SOC_DAPM_PRE_PMU),
2974e2bcbf99SRichard Fitzgerald SND_SOC_DAPM_PGA_E("EQ3", CS48L32_EQ_CONTROL1, 2, 0, NULL, 0, cs48l32_eq_ev, SND_SOC_DAPM_PRE_PMU),
2975e2bcbf99SRichard Fitzgerald SND_SOC_DAPM_PGA_E("EQ4", CS48L32_EQ_CONTROL1, 3, 0, NULL, 0, cs48l32_eq_ev, SND_SOC_DAPM_PRE_PMU),
2976e2bcbf99SRichard Fitzgerald
2977e2bcbf99SRichard Fitzgerald SND_SOC_DAPM_PGA("DRC1L", CS48L32_DRC1_CONTROL1, CS48L32_DRC1L_EN_SHIFT, 0, NULL, 0),
2978e2bcbf99SRichard Fitzgerald SND_SOC_DAPM_PGA("DRC1R", CS48L32_DRC1_CONTROL1, CS48L32_DRC1R_EN_SHIFT, 0, NULL, 0),
2979e2bcbf99SRichard Fitzgerald SND_SOC_DAPM_PGA("DRC2L", CS48L32_DRC2_CONTROL1, CS48L32_DRC1L_EN_SHIFT, 0, NULL, 0),
2980e2bcbf99SRichard Fitzgerald SND_SOC_DAPM_PGA("DRC2R", CS48L32_DRC2_CONTROL1, CS48L32_DRC1R_EN_SHIFT, 0, NULL, 0),
2981e2bcbf99SRichard Fitzgerald
2982e2bcbf99SRichard Fitzgerald SND_SOC_DAPM_PGA("LHPF1", CS48L32_LHPF_CONTROL1, 0, 0, NULL, 0),
2983e2bcbf99SRichard Fitzgerald SND_SOC_DAPM_PGA("LHPF2", CS48L32_LHPF_CONTROL1, 1, 0, NULL, 0),
2984e2bcbf99SRichard Fitzgerald SND_SOC_DAPM_PGA("LHPF3", CS48L32_LHPF_CONTROL1, 2, 0, NULL, 0),
2985e2bcbf99SRichard Fitzgerald SND_SOC_DAPM_PGA("LHPF4", CS48L32_LHPF_CONTROL1, 3, 0, NULL, 0),
2986e2bcbf99SRichard Fitzgerald
2987e2bcbf99SRichard Fitzgerald SND_SOC_DAPM_PGA("Ultrasonic 1", CS48L32_US_CONTROL, 0, 0, NULL, 0),
2988e2bcbf99SRichard Fitzgerald SND_SOC_DAPM_PGA("Ultrasonic 2", CS48L32_US_CONTROL, 1, 0, NULL, 0),
2989e2bcbf99SRichard Fitzgerald
2990e2bcbf99SRichard Fitzgerald WM_ADSP2("DSP1", 0, wm_adsp_early_event),
2991e2bcbf99SRichard Fitzgerald
2992e2bcbf99SRichard Fitzgerald /* end of ordered widget list */
2993e2bcbf99SRichard Fitzgerald
2994e2bcbf99SRichard Fitzgerald CS48L32_MIXER_WIDGETS(EQ1, "EQ1"),
2995e2bcbf99SRichard Fitzgerald CS48L32_MIXER_WIDGETS(EQ2, "EQ2"),
2996e2bcbf99SRichard Fitzgerald CS48L32_MIXER_WIDGETS(EQ3, "EQ3"),
2997e2bcbf99SRichard Fitzgerald CS48L32_MIXER_WIDGETS(EQ4, "EQ4"),
2998e2bcbf99SRichard Fitzgerald
2999e2bcbf99SRichard Fitzgerald CS48L32_MIXER_WIDGETS(DRC1L, "DRC1L"),
3000e2bcbf99SRichard Fitzgerald CS48L32_MIXER_WIDGETS(DRC1R, "DRC1R"),
3001e2bcbf99SRichard Fitzgerald CS48L32_MIXER_WIDGETS(DRC2L, "DRC2L"),
3002e2bcbf99SRichard Fitzgerald CS48L32_MIXER_WIDGETS(DRC2R, "DRC2R"),
3003e2bcbf99SRichard Fitzgerald
3004e2bcbf99SRichard Fitzgerald SND_SOC_DAPM_SWITCH("DRC1 Activity Output", SND_SOC_NOPM, 0, 0,
3005e2bcbf99SRichard Fitzgerald &cs48l32_drc_activity_output_mux[0]),
3006e2bcbf99SRichard Fitzgerald SND_SOC_DAPM_SWITCH("DRC2 Activity Output", SND_SOC_NOPM, 0, 0,
3007e2bcbf99SRichard Fitzgerald &cs48l32_drc_activity_output_mux[1]),
3008e2bcbf99SRichard Fitzgerald
3009e2bcbf99SRichard Fitzgerald CS48L32_MIXER_WIDGETS(LHPF1, "LHPF1"),
3010e2bcbf99SRichard Fitzgerald CS48L32_MIXER_WIDGETS(LHPF2, "LHPF2"),
3011e2bcbf99SRichard Fitzgerald CS48L32_MIXER_WIDGETS(LHPF3, "LHPF3"),
3012e2bcbf99SRichard Fitzgerald CS48L32_MIXER_WIDGETS(LHPF4, "LHPF4"),
3013e2bcbf99SRichard Fitzgerald
3014e2bcbf99SRichard Fitzgerald CS48L32_MIXER_WIDGETS(ASP1TX1, "ASP1TX1"),
3015e2bcbf99SRichard Fitzgerald CS48L32_MIXER_WIDGETS(ASP1TX2, "ASP1TX2"),
3016e2bcbf99SRichard Fitzgerald CS48L32_MIXER_WIDGETS(ASP1TX3, "ASP1TX3"),
3017e2bcbf99SRichard Fitzgerald CS48L32_MIXER_WIDGETS(ASP1TX4, "ASP1TX4"),
3018e2bcbf99SRichard Fitzgerald CS48L32_MIXER_WIDGETS(ASP1TX5, "ASP1TX5"),
3019e2bcbf99SRichard Fitzgerald CS48L32_MIXER_WIDGETS(ASP1TX6, "ASP1TX6"),
3020e2bcbf99SRichard Fitzgerald CS48L32_MIXER_WIDGETS(ASP1TX7, "ASP1TX7"),
3021e2bcbf99SRichard Fitzgerald CS48L32_MIXER_WIDGETS(ASP1TX8, "ASP1TX8"),
3022e2bcbf99SRichard Fitzgerald
3023e2bcbf99SRichard Fitzgerald CS48L32_MIXER_WIDGETS(ASP2TX1, "ASP2TX1"),
3024e2bcbf99SRichard Fitzgerald CS48L32_MIXER_WIDGETS(ASP2TX2, "ASP2TX2"),
3025e2bcbf99SRichard Fitzgerald CS48L32_MIXER_WIDGETS(ASP2TX3, "ASP2TX3"),
3026e2bcbf99SRichard Fitzgerald CS48L32_MIXER_WIDGETS(ASP2TX4, "ASP2TX4"),
3027e2bcbf99SRichard Fitzgerald
3028e2bcbf99SRichard Fitzgerald CS48L32_MUX_WIDGETS(ISRC1DEC1, "ISRC1DEC1"),
3029e2bcbf99SRichard Fitzgerald CS48L32_MUX_WIDGETS(ISRC1DEC2, "ISRC1DEC2"),
3030e2bcbf99SRichard Fitzgerald CS48L32_MUX_WIDGETS(ISRC1DEC3, "ISRC1DEC3"),
3031e2bcbf99SRichard Fitzgerald CS48L32_MUX_WIDGETS(ISRC1DEC4, "ISRC1DEC4"),
3032e2bcbf99SRichard Fitzgerald
3033e2bcbf99SRichard Fitzgerald CS48L32_MUX_WIDGETS(ISRC1INT1, "ISRC1INT1"),
3034e2bcbf99SRichard Fitzgerald CS48L32_MUX_WIDGETS(ISRC1INT2, "ISRC1INT2"),
3035e2bcbf99SRichard Fitzgerald CS48L32_MUX_WIDGETS(ISRC1INT3, "ISRC1INT3"),
3036e2bcbf99SRichard Fitzgerald CS48L32_MUX_WIDGETS(ISRC1INT4, "ISRC1INT4"),
3037e2bcbf99SRichard Fitzgerald
3038e2bcbf99SRichard Fitzgerald CS48L32_MUX_WIDGETS(ISRC2DEC1, "ISRC2DEC1"),
3039e2bcbf99SRichard Fitzgerald CS48L32_MUX_WIDGETS(ISRC2DEC2, "ISRC2DEC2"),
3040e2bcbf99SRichard Fitzgerald
3041e2bcbf99SRichard Fitzgerald CS48L32_MUX_WIDGETS(ISRC2INT1, "ISRC2INT1"),
3042e2bcbf99SRichard Fitzgerald CS48L32_MUX_WIDGETS(ISRC2INT2, "ISRC2INT2"),
3043e2bcbf99SRichard Fitzgerald
3044e2bcbf99SRichard Fitzgerald CS48L32_MUX_WIDGETS(ISRC3DEC1, "ISRC3DEC1"),
3045e2bcbf99SRichard Fitzgerald CS48L32_MUX_WIDGETS(ISRC3DEC2, "ISRC3DEC2"),
3046e2bcbf99SRichard Fitzgerald
3047e2bcbf99SRichard Fitzgerald CS48L32_MUX_WIDGETS(ISRC3INT1, "ISRC3INT1"),
3048e2bcbf99SRichard Fitzgerald CS48L32_MUX_WIDGETS(ISRC3INT2, "ISRC3INT2"),
3049e2bcbf99SRichard Fitzgerald
3050e2bcbf99SRichard Fitzgerald CS48L32_MIXER_WIDGETS(DSP1RX1, "DSP1RX1"),
3051e2bcbf99SRichard Fitzgerald CS48L32_MIXER_WIDGETS(DSP1RX2, "DSP1RX2"),
3052e2bcbf99SRichard Fitzgerald CS48L32_MIXER_WIDGETS(DSP1RX3, "DSP1RX3"),
3053e2bcbf99SRichard Fitzgerald CS48L32_MIXER_WIDGETS(DSP1RX4, "DSP1RX4"),
3054e2bcbf99SRichard Fitzgerald CS48L32_MIXER_WIDGETS(DSP1RX5, "DSP1RX5"),
3055e2bcbf99SRichard Fitzgerald CS48L32_MIXER_WIDGETS(DSP1RX6, "DSP1RX6"),
3056e2bcbf99SRichard Fitzgerald CS48L32_MIXER_WIDGETS(DSP1RX7, "DSP1RX7"),
3057e2bcbf99SRichard Fitzgerald CS48L32_MIXER_WIDGETS(DSP1RX8, "DSP1RX8"),
3058e2bcbf99SRichard Fitzgerald
3059e2bcbf99SRichard Fitzgerald SND_SOC_DAPM_SWITCH("DSP1 Trigger Output", SND_SOC_NOPM, 0, 0,
3060e2bcbf99SRichard Fitzgerald &cs48l32_dsp_trigger_output_mux[0]),
3061e2bcbf99SRichard Fitzgerald
3062e2bcbf99SRichard Fitzgerald SND_SOC_DAPM_OUTPUT("AUXPDM1_CLK"),
3063e2bcbf99SRichard Fitzgerald SND_SOC_DAPM_OUTPUT("AUXPDM1_DOUT"),
3064e2bcbf99SRichard Fitzgerald SND_SOC_DAPM_OUTPUT("AUXPDM2_CLK"),
3065e2bcbf99SRichard Fitzgerald SND_SOC_DAPM_OUTPUT("AUXPDM2_DOUT"),
3066e2bcbf99SRichard Fitzgerald
3067e2bcbf99SRichard Fitzgerald SND_SOC_DAPM_OUTPUT("MICSUPP"),
3068e2bcbf99SRichard Fitzgerald
3069e2bcbf99SRichard Fitzgerald SND_SOC_DAPM_OUTPUT("Ultrasonic Dummy Output"),
3070e2bcbf99SRichard Fitzgerald };
3071e2bcbf99SRichard Fitzgerald
3072e2bcbf99SRichard Fitzgerald static const struct snd_soc_dapm_route cs48l32_dapm_routes[] = {
3073e2bcbf99SRichard Fitzgerald { "IN1LN_1", NULL, "SYSCLK" },
3074e2bcbf99SRichard Fitzgerald { "IN1LN_2", NULL, "SYSCLK" },
3075e2bcbf99SRichard Fitzgerald { "IN1LP_1", NULL, "SYSCLK" },
3076e2bcbf99SRichard Fitzgerald { "IN1LP_2", NULL, "SYSCLK" },
3077e2bcbf99SRichard Fitzgerald { "IN1RN_1", NULL, "SYSCLK" },
3078e2bcbf99SRichard Fitzgerald { "IN1RN_2", NULL, "SYSCLK" },
3079e2bcbf99SRichard Fitzgerald { "IN1RP_1", NULL, "SYSCLK" },
3080e2bcbf99SRichard Fitzgerald { "IN1RP_2", NULL, "SYSCLK" },
3081e2bcbf99SRichard Fitzgerald
3082e2bcbf99SRichard Fitzgerald { "IN1_PDMCLK", NULL, "SYSCLK" },
3083e2bcbf99SRichard Fitzgerald { "IN1_PDMDATA", NULL, "SYSCLK" },
3084e2bcbf99SRichard Fitzgerald { "IN2_PDMCLK", NULL, "SYSCLK" },
3085e2bcbf99SRichard Fitzgerald { "IN2_PDMDATA", NULL, "SYSCLK" },
3086e2bcbf99SRichard Fitzgerald
3087e2bcbf99SRichard Fitzgerald { "DSP1 Preloader", NULL, "DSP1MEM" },
3088e2bcbf99SRichard Fitzgerald { "DSP1", NULL, "DSP1FREQ" },
3089e2bcbf99SRichard Fitzgerald
3090e2bcbf99SRichard Fitzgerald { "Audio Trace DSP", NULL, "DSP1" },
3091e2bcbf99SRichard Fitzgerald { "Voice Ctrl DSP", NULL, "DSP1" },
3092e2bcbf99SRichard Fitzgerald
3093e2bcbf99SRichard Fitzgerald { "VOUT_MIC_REGULATED", NULL, "VOUT_MIC" },
3094e2bcbf99SRichard Fitzgerald { "MICBIAS1", NULL, "VOUT_MIC_REGULATED" },
3095e2bcbf99SRichard Fitzgerald { "MICBIAS1A", NULL, "MICBIAS1" },
3096e2bcbf99SRichard Fitzgerald { "MICBIAS1B", NULL, "MICBIAS1" },
3097e2bcbf99SRichard Fitzgerald { "MICBIAS1C", NULL, "MICBIAS1" },
3098e2bcbf99SRichard Fitzgerald
3099e2bcbf99SRichard Fitzgerald { "Tone Generator 1", NULL, "SYSCLK" },
3100e2bcbf99SRichard Fitzgerald { "Tone Generator 2", NULL, "SYSCLK" },
3101e2bcbf99SRichard Fitzgerald { "Noise Generator", NULL, "SYSCLK" },
3102e2bcbf99SRichard Fitzgerald
3103e2bcbf99SRichard Fitzgerald { "Tone Generator 1", NULL, "TONE" },
3104e2bcbf99SRichard Fitzgerald { "Tone Generator 2", NULL, "TONE" },
3105e2bcbf99SRichard Fitzgerald { "Noise Generator", NULL, "NOISE" },
3106e2bcbf99SRichard Fitzgerald
3107e2bcbf99SRichard Fitzgerald { "ASP1 Capture", NULL, "ASP1TX1" },
3108e2bcbf99SRichard Fitzgerald { "ASP1 Capture", NULL, "ASP1TX2" },
3109e2bcbf99SRichard Fitzgerald { "ASP1 Capture", NULL, "ASP1TX3" },
3110e2bcbf99SRichard Fitzgerald { "ASP1 Capture", NULL, "ASP1TX4" },
3111e2bcbf99SRichard Fitzgerald { "ASP1 Capture", NULL, "ASP1TX5" },
3112e2bcbf99SRichard Fitzgerald { "ASP1 Capture", NULL, "ASP1TX6" },
3113e2bcbf99SRichard Fitzgerald { "ASP1 Capture", NULL, "ASP1TX7" },
3114e2bcbf99SRichard Fitzgerald { "ASP1 Capture", NULL, "ASP1TX8" },
3115e2bcbf99SRichard Fitzgerald
3116e2bcbf99SRichard Fitzgerald { "ASP1RX1", NULL, "ASP1 Playback" },
3117e2bcbf99SRichard Fitzgerald { "ASP1RX2", NULL, "ASP1 Playback" },
3118e2bcbf99SRichard Fitzgerald { "ASP1RX3", NULL, "ASP1 Playback" },
3119e2bcbf99SRichard Fitzgerald { "ASP1RX4", NULL, "ASP1 Playback" },
3120e2bcbf99SRichard Fitzgerald { "ASP1RX5", NULL, "ASP1 Playback" },
3121e2bcbf99SRichard Fitzgerald { "ASP1RX6", NULL, "ASP1 Playback" },
3122e2bcbf99SRichard Fitzgerald { "ASP1RX7", NULL, "ASP1 Playback" },
3123e2bcbf99SRichard Fitzgerald { "ASP1RX8", NULL, "ASP1 Playback" },
3124e2bcbf99SRichard Fitzgerald
3125e2bcbf99SRichard Fitzgerald { "ASP2 Capture", NULL, "ASP2TX1" },
3126e2bcbf99SRichard Fitzgerald { "ASP2 Capture", NULL, "ASP2TX2" },
3127e2bcbf99SRichard Fitzgerald { "ASP2 Capture", NULL, "ASP2TX3" },
3128e2bcbf99SRichard Fitzgerald { "ASP2 Capture", NULL, "ASP2TX4" },
3129e2bcbf99SRichard Fitzgerald
3130e2bcbf99SRichard Fitzgerald { "ASP2RX1", NULL, "ASP2 Playback" },
3131e2bcbf99SRichard Fitzgerald { "ASP2RX2", NULL, "ASP2 Playback" },
3132e2bcbf99SRichard Fitzgerald { "ASP2RX3", NULL, "ASP2 Playback" },
3133e2bcbf99SRichard Fitzgerald { "ASP2RX4", NULL, "ASP2 Playback" },
3134e2bcbf99SRichard Fitzgerald
3135e2bcbf99SRichard Fitzgerald { "ASP1 Playback", NULL, "SYSCLK" },
3136e2bcbf99SRichard Fitzgerald { "ASP2 Playback", NULL, "SYSCLK" },
3137e2bcbf99SRichard Fitzgerald
3138e2bcbf99SRichard Fitzgerald { "ASP1 Capture", NULL, "SYSCLK" },
3139e2bcbf99SRichard Fitzgerald { "ASP2 Capture", NULL, "SYSCLK" },
3140e2bcbf99SRichard Fitzgerald
3141e2bcbf99SRichard Fitzgerald { "IN1L Mux", "Analog 1", "IN1LN_1" },
3142e2bcbf99SRichard Fitzgerald { "IN1L Mux", "Analog 2", "IN1LN_2" },
3143e2bcbf99SRichard Fitzgerald { "IN1L Mux", "Analog 1", "IN1LP_1" },
3144e2bcbf99SRichard Fitzgerald { "IN1L Mux", "Analog 2", "IN1LP_2" },
3145e2bcbf99SRichard Fitzgerald { "IN1R Mux", "Analog 1", "IN1RN_1" },
3146e2bcbf99SRichard Fitzgerald { "IN1R Mux", "Analog 2", "IN1RN_2" },
3147e2bcbf99SRichard Fitzgerald { "IN1R Mux", "Analog 1", "IN1RP_1" },
3148e2bcbf99SRichard Fitzgerald { "IN1R Mux", "Analog 2", "IN1RP_2" },
3149e2bcbf99SRichard Fitzgerald
3150e2bcbf99SRichard Fitzgerald { "IN1L PGA", NULL, "IN1L Mode" },
3151e2bcbf99SRichard Fitzgerald { "IN1R PGA", NULL, "IN1R Mode" },
3152e2bcbf99SRichard Fitzgerald
3153e2bcbf99SRichard Fitzgerald { "IN1L Mode", "Analog", "IN1L Mux" },
3154e2bcbf99SRichard Fitzgerald { "IN1R Mode", "Analog", "IN1R Mux" },
3155e2bcbf99SRichard Fitzgerald
3156e2bcbf99SRichard Fitzgerald { "IN1L Mode", "Digital", "IN1_PDMCLK" },
3157e2bcbf99SRichard Fitzgerald { "IN1L Mode", "Digital", "IN1_PDMDATA" },
3158e2bcbf99SRichard Fitzgerald { "IN1R Mode", "Digital", "IN1_PDMCLK" },
3159e2bcbf99SRichard Fitzgerald { "IN1R Mode", "Digital", "IN1_PDMDATA" },
3160e2bcbf99SRichard Fitzgerald
3161e2bcbf99SRichard Fitzgerald { "IN1L PGA", NULL, "VOUT_MIC" },
3162e2bcbf99SRichard Fitzgerald { "IN1R PGA", NULL, "VOUT_MIC" },
3163e2bcbf99SRichard Fitzgerald
3164e2bcbf99SRichard Fitzgerald { "IN2L PGA", NULL, "VOUT_MIC" },
3165e2bcbf99SRichard Fitzgerald { "IN2R PGA", NULL, "VOUT_MIC" },
3166e2bcbf99SRichard Fitzgerald
3167e2bcbf99SRichard Fitzgerald { "IN2L PGA", NULL, "IN2_PDMCLK" },
3168e2bcbf99SRichard Fitzgerald { "IN2R PGA", NULL, "IN2_PDMCLK" },
3169e2bcbf99SRichard Fitzgerald { "IN2L PGA", NULL, "IN2_PDMDATA" },
3170e2bcbf99SRichard Fitzgerald { "IN2R PGA", NULL, "IN2_PDMDATA" },
3171e2bcbf99SRichard Fitzgerald
3172e2bcbf99SRichard Fitzgerald { "Ultrasonic 1", NULL, "Ultrasonic 1 Input" },
3173e2bcbf99SRichard Fitzgerald { "Ultrasonic 2", NULL, "Ultrasonic 2 Input" },
3174e2bcbf99SRichard Fitzgerald
3175e2bcbf99SRichard Fitzgerald { "Ultrasonic 1 Input", "IN1L", "IN1L PGA" },
3176e2bcbf99SRichard Fitzgerald { "Ultrasonic 1 Input", "IN1R", "IN1R PGA" },
3177e2bcbf99SRichard Fitzgerald { "Ultrasonic 1 Input", "IN2L", "IN2L PGA" },
3178e2bcbf99SRichard Fitzgerald { "Ultrasonic 1 Input", "IN2R", "IN2R PGA" },
3179e2bcbf99SRichard Fitzgerald
3180e2bcbf99SRichard Fitzgerald { "Ultrasonic 2 Input", "IN1L", "IN1L PGA" },
3181e2bcbf99SRichard Fitzgerald { "Ultrasonic 2 Input", "IN1R", "IN1R PGA" },
3182e2bcbf99SRichard Fitzgerald { "Ultrasonic 2 Input", "IN2L", "IN2L PGA" },
3183e2bcbf99SRichard Fitzgerald { "Ultrasonic 2 Input", "IN2R", "IN2R PGA" },
3184e2bcbf99SRichard Fitzgerald
3185e2bcbf99SRichard Fitzgerald { "Ultrasonic 1 Detect", "Switch", "Ultrasonic 1 Input" },
3186e2bcbf99SRichard Fitzgerald { "Ultrasonic 2 Detect", "Switch", "Ultrasonic 2 Input" },
3187e2bcbf99SRichard Fitzgerald
3188e2bcbf99SRichard Fitzgerald { "Ultrasonic Dummy Output", NULL, "Ultrasonic 1 Detect" },
3189e2bcbf99SRichard Fitzgerald { "Ultrasonic Dummy Output", NULL, "Ultrasonic 2 Detect" },
3190e2bcbf99SRichard Fitzgerald
3191e2bcbf99SRichard Fitzgerald CS48L32_MIXER_ROUTES("ASP1TX1", "ASP1TX1"),
3192e2bcbf99SRichard Fitzgerald CS48L32_MIXER_ROUTES("ASP1TX2", "ASP1TX2"),
3193e2bcbf99SRichard Fitzgerald CS48L32_MIXER_ROUTES("ASP1TX3", "ASP1TX3"),
3194e2bcbf99SRichard Fitzgerald CS48L32_MIXER_ROUTES("ASP1TX4", "ASP1TX4"),
3195e2bcbf99SRichard Fitzgerald CS48L32_MIXER_ROUTES("ASP1TX5", "ASP1TX5"),
3196e2bcbf99SRichard Fitzgerald CS48L32_MIXER_ROUTES("ASP1TX6", "ASP1TX6"),
3197e2bcbf99SRichard Fitzgerald CS48L32_MIXER_ROUTES("ASP1TX7", "ASP1TX7"),
3198e2bcbf99SRichard Fitzgerald CS48L32_MIXER_ROUTES("ASP1TX8", "ASP1TX8"),
3199e2bcbf99SRichard Fitzgerald
3200e2bcbf99SRichard Fitzgerald CS48L32_MIXER_ROUTES("ASP2TX1", "ASP2TX1"),
3201e2bcbf99SRichard Fitzgerald CS48L32_MIXER_ROUTES("ASP2TX2", "ASP2TX2"),
3202e2bcbf99SRichard Fitzgerald CS48L32_MIXER_ROUTES("ASP2TX3", "ASP2TX3"),
3203e2bcbf99SRichard Fitzgerald CS48L32_MIXER_ROUTES("ASP2TX4", "ASP2TX4"),
3204e2bcbf99SRichard Fitzgerald
3205e2bcbf99SRichard Fitzgerald CS48L32_MIXER_ROUTES("EQ1", "EQ1"),
3206e2bcbf99SRichard Fitzgerald CS48L32_MIXER_ROUTES("EQ2", "EQ2"),
3207e2bcbf99SRichard Fitzgerald CS48L32_MIXER_ROUTES("EQ3", "EQ3"),
3208e2bcbf99SRichard Fitzgerald CS48L32_MIXER_ROUTES("EQ4", "EQ4"),
3209e2bcbf99SRichard Fitzgerald
3210e2bcbf99SRichard Fitzgerald CS48L32_MIXER_ROUTES("DRC1L", "DRC1L"),
3211e2bcbf99SRichard Fitzgerald CS48L32_MIXER_ROUTES("DRC1R", "DRC1R"),
3212e2bcbf99SRichard Fitzgerald CS48L32_MIXER_ROUTES("DRC2L", "DRC2L"),
3213e2bcbf99SRichard Fitzgerald CS48L32_MIXER_ROUTES("DRC2R", "DRC2R"),
3214e2bcbf99SRichard Fitzgerald
3215e2bcbf99SRichard Fitzgerald CS48L32_MIXER_ROUTES("LHPF1", "LHPF1"),
3216e2bcbf99SRichard Fitzgerald CS48L32_MIXER_ROUTES("LHPF2", "LHPF2"),
3217e2bcbf99SRichard Fitzgerald CS48L32_MIXER_ROUTES("LHPF3", "LHPF3"),
3218e2bcbf99SRichard Fitzgerald CS48L32_MIXER_ROUTES("LHPF4", "LHPF4"),
3219e2bcbf99SRichard Fitzgerald
3220e2bcbf99SRichard Fitzgerald CS48L32_MUX_ROUTES("ISRC1INT1", "ISRC1INT1"),
3221e2bcbf99SRichard Fitzgerald CS48L32_MUX_ROUTES("ISRC1INT2", "ISRC1INT2"),
3222e2bcbf99SRichard Fitzgerald CS48L32_MUX_ROUTES("ISRC1INT3", "ISRC1INT3"),
3223e2bcbf99SRichard Fitzgerald CS48L32_MUX_ROUTES("ISRC1INT4", "ISRC1INT4"),
3224e2bcbf99SRichard Fitzgerald
3225e2bcbf99SRichard Fitzgerald CS48L32_MUX_ROUTES("ISRC1DEC1", "ISRC1DEC1"),
3226e2bcbf99SRichard Fitzgerald CS48L32_MUX_ROUTES("ISRC1DEC2", "ISRC1DEC2"),
3227e2bcbf99SRichard Fitzgerald CS48L32_MUX_ROUTES("ISRC1DEC3", "ISRC1DEC3"),
3228e2bcbf99SRichard Fitzgerald CS48L32_MUX_ROUTES("ISRC1DEC4", "ISRC1DEC4"),
3229e2bcbf99SRichard Fitzgerald
3230e2bcbf99SRichard Fitzgerald CS48L32_MUX_ROUTES("ISRC2INT1", "ISRC2INT1"),
3231e2bcbf99SRichard Fitzgerald CS48L32_MUX_ROUTES("ISRC2INT2", "ISRC2INT2"),
3232e2bcbf99SRichard Fitzgerald
3233e2bcbf99SRichard Fitzgerald CS48L32_MUX_ROUTES("ISRC2DEC1", "ISRC2DEC1"),
3234e2bcbf99SRichard Fitzgerald CS48L32_MUX_ROUTES("ISRC2DEC2", "ISRC2DEC2"),
3235e2bcbf99SRichard Fitzgerald
3236e2bcbf99SRichard Fitzgerald CS48L32_MUX_ROUTES("ISRC3INT1", "ISRC3INT1"),
3237e2bcbf99SRichard Fitzgerald CS48L32_MUX_ROUTES("ISRC3INT2", "ISRC3INT2"),
3238e2bcbf99SRichard Fitzgerald
3239e2bcbf99SRichard Fitzgerald CS48L32_MUX_ROUTES("ISRC3DEC1", "ISRC3DEC1"),
3240e2bcbf99SRichard Fitzgerald CS48L32_MUX_ROUTES("ISRC3DEC2", "ISRC3DEC2"),
3241e2bcbf99SRichard Fitzgerald
3242e2bcbf99SRichard Fitzgerald CS48L32_DSP_ROUTES_1_8_SYSCLK("DSP1"),
3243e2bcbf99SRichard Fitzgerald
3244e2bcbf99SRichard Fitzgerald { "DSP Trigger Out", NULL, "DSP1 Trigger Output" },
3245e2bcbf99SRichard Fitzgerald
3246e2bcbf99SRichard Fitzgerald { "DSP1 Trigger Output", "Switch", "DSP1" },
3247e2bcbf99SRichard Fitzgerald
3248e2bcbf99SRichard Fitzgerald { "AUXPDM1 Analog Input", "IN1L", "IN1L PGA" },
3249e2bcbf99SRichard Fitzgerald { "AUXPDM1 Analog Input", "IN1R", "IN1R PGA" },
3250e2bcbf99SRichard Fitzgerald
3251e2bcbf99SRichard Fitzgerald { "AUXPDM2 Analog Input", "IN1L", "IN1L PGA" },
3252e2bcbf99SRichard Fitzgerald { "AUXPDM2 Analog Input", "IN1R", "IN1R PGA" },
3253e2bcbf99SRichard Fitzgerald
3254e2bcbf99SRichard Fitzgerald { "AUXPDM1 Input", "Analog", "AUXPDM1 Analog Input" },
3255e2bcbf99SRichard Fitzgerald { "AUXPDM1 Input", "IN1 Digital", "IN1L PGA" },
3256e2bcbf99SRichard Fitzgerald { "AUXPDM1 Input", "IN1 Digital", "IN1R PGA" },
3257e2bcbf99SRichard Fitzgerald { "AUXPDM1 Input", "IN2 Digital", "IN2L PGA" },
3258e2bcbf99SRichard Fitzgerald { "AUXPDM1 Input", "IN2 Digital", "IN2R PGA" },
3259e2bcbf99SRichard Fitzgerald
3260e2bcbf99SRichard Fitzgerald { "AUXPDM2 Input", "Analog", "AUXPDM2 Analog Input" },
3261e2bcbf99SRichard Fitzgerald { "AUXPDM2 Input", "IN1 Digital", "IN1L PGA" },
3262e2bcbf99SRichard Fitzgerald { "AUXPDM2 Input", "IN1 Digital", "IN1R PGA" },
3263e2bcbf99SRichard Fitzgerald { "AUXPDM2 Input", "IN2 Digital", "IN2L PGA" },
3264e2bcbf99SRichard Fitzgerald { "AUXPDM2 Input", "IN2 Digital", "IN2R PGA" },
3265e2bcbf99SRichard Fitzgerald
3266e2bcbf99SRichard Fitzgerald { "AUXPDM1 Output", "Switch", "AUXPDM1 Input" },
3267e2bcbf99SRichard Fitzgerald { "AUXPDM1_CLK", NULL, "AUXPDM1 Output" },
3268e2bcbf99SRichard Fitzgerald { "AUXPDM1_DOUT", NULL, "AUXPDM1 Output" },
3269e2bcbf99SRichard Fitzgerald
3270e2bcbf99SRichard Fitzgerald { "AUXPDM2 Output", "Switch", "AUXPDM2 Input" },
3271e2bcbf99SRichard Fitzgerald { "AUXPDM2_CLK", NULL, "AUXPDM2 Output" },
3272e2bcbf99SRichard Fitzgerald { "AUXPDM2_DOUT", NULL, "AUXPDM2 Output" },
3273e2bcbf99SRichard Fitzgerald
3274e2bcbf99SRichard Fitzgerald { "MICSUPP", NULL, "SYSCLK" },
3275e2bcbf99SRichard Fitzgerald
3276e2bcbf99SRichard Fitzgerald { "DRC1 Signal Activity", NULL, "DRC1 Activity Output" },
3277e2bcbf99SRichard Fitzgerald { "DRC2 Signal Activity", NULL, "DRC2 Activity Output" },
3278e2bcbf99SRichard Fitzgerald { "DRC1 Activity Output", "Switch", "DRC1L" },
3279e2bcbf99SRichard Fitzgerald { "DRC1 Activity Output", "Switch", "DRC1R" },
3280e2bcbf99SRichard Fitzgerald { "DRC2 Activity Output", "Switch", "DRC2L" },
3281e2bcbf99SRichard Fitzgerald { "DRC2 Activity Output", "Switch", "DRC2R" },
3282e2bcbf99SRichard Fitzgerald };
3283e2bcbf99SRichard Fitzgerald
cs48l32_compr_open(struct snd_soc_component * component,struct snd_compr_stream * stream)3284e2bcbf99SRichard Fitzgerald static int cs48l32_compr_open(struct snd_soc_component *component,
3285e2bcbf99SRichard Fitzgerald struct snd_compr_stream *stream)
3286e2bcbf99SRichard Fitzgerald {
3287e2bcbf99SRichard Fitzgerald struct snd_soc_pcm_runtime *rtd = stream->private_data;
3288e2bcbf99SRichard Fitzgerald struct cs48l32_codec *cs48l32_codec = snd_soc_component_get_drvdata(component);
3289e2bcbf99SRichard Fitzgerald
3290e2bcbf99SRichard Fitzgerald if (strcmp(snd_soc_rtd_to_codec(rtd, 0)->name, "cs48l32-dsp-trace") &&
3291e2bcbf99SRichard Fitzgerald strcmp(snd_soc_rtd_to_codec(rtd, 0)->name, "cs48l32-dsp-voicectrl")) {
3292e2bcbf99SRichard Fitzgerald dev_err(cs48l32_codec->core.dev, "No suitable compressed stream for DAI '%s'\n",
3293e2bcbf99SRichard Fitzgerald snd_soc_rtd_to_codec(rtd, 0)->name);
3294e2bcbf99SRichard Fitzgerald return -EINVAL;
3295e2bcbf99SRichard Fitzgerald }
3296e2bcbf99SRichard Fitzgerald
3297e2bcbf99SRichard Fitzgerald return wm_adsp_compr_open(&cs48l32_codec->dsp, stream);
3298e2bcbf99SRichard Fitzgerald }
3299e2bcbf99SRichard Fitzgerald
3300e2bcbf99SRichard Fitzgerald static const struct snd_compress_ops cs48l32_compress_ops = {
3301e2bcbf99SRichard Fitzgerald .open = &cs48l32_compr_open,
3302e2bcbf99SRichard Fitzgerald .free = &wm_adsp_compr_free,
3303e2bcbf99SRichard Fitzgerald .set_params = &wm_adsp_compr_set_params,
3304e2bcbf99SRichard Fitzgerald .get_caps = &wm_adsp_compr_get_caps,
3305e2bcbf99SRichard Fitzgerald .trigger = &wm_adsp_compr_trigger,
3306e2bcbf99SRichard Fitzgerald .pointer = &wm_adsp_compr_pointer,
3307e2bcbf99SRichard Fitzgerald .copy = &wm_adsp_compr_copy,
3308e2bcbf99SRichard Fitzgerald };
3309e2bcbf99SRichard Fitzgerald
3310e2bcbf99SRichard Fitzgerald static const struct snd_soc_dai_ops cs48l32_compress_dai_ops = {
3311e2bcbf99SRichard Fitzgerald .compress_new = snd_soc_new_compress,
3312e2bcbf99SRichard Fitzgerald };
3313e2bcbf99SRichard Fitzgerald
3314e2bcbf99SRichard Fitzgerald static struct snd_soc_dai_driver cs48l32_dai[] = {
3315e2bcbf99SRichard Fitzgerald {
3316e2bcbf99SRichard Fitzgerald .name = "cs48l32-asp1",
3317e2bcbf99SRichard Fitzgerald .id = 1,
3318e2bcbf99SRichard Fitzgerald .base = CS48L32_ASP1_ENABLES1,
3319e2bcbf99SRichard Fitzgerald .playback = {
3320e2bcbf99SRichard Fitzgerald .stream_name = "ASP1 Playback",
3321e2bcbf99SRichard Fitzgerald .channels_min = 1,
3322e2bcbf99SRichard Fitzgerald .channels_max = 8,
3323e2bcbf99SRichard Fitzgerald .rates = CS48L32_RATES,
3324e2bcbf99SRichard Fitzgerald .formats = CS48L32_FORMATS,
3325e2bcbf99SRichard Fitzgerald },
3326e2bcbf99SRichard Fitzgerald .capture = {
3327e2bcbf99SRichard Fitzgerald .stream_name = "ASP1 Capture",
3328e2bcbf99SRichard Fitzgerald .channels_min = 1,
3329e2bcbf99SRichard Fitzgerald .channels_max = 8,
3330e2bcbf99SRichard Fitzgerald .rates = CS48L32_RATES,
3331e2bcbf99SRichard Fitzgerald .formats = CS48L32_FORMATS,
3332e2bcbf99SRichard Fitzgerald },
3333e2bcbf99SRichard Fitzgerald .ops = &cs48l32_dai_ops,
3334e2bcbf99SRichard Fitzgerald .symmetric_rate = 1,
3335e2bcbf99SRichard Fitzgerald .symmetric_sample_bits = 1,
3336e2bcbf99SRichard Fitzgerald },
3337e2bcbf99SRichard Fitzgerald {
3338e2bcbf99SRichard Fitzgerald .name = "cs48l32-asp2",
3339e2bcbf99SRichard Fitzgerald .id = 2,
3340e2bcbf99SRichard Fitzgerald .base = CS48L32_ASP2_ENABLES1,
3341e2bcbf99SRichard Fitzgerald .playback = {
3342e2bcbf99SRichard Fitzgerald .stream_name = "ASP2 Playback",
3343e2bcbf99SRichard Fitzgerald .channels_min = 1,
3344e2bcbf99SRichard Fitzgerald .channels_max = 4,
3345e2bcbf99SRichard Fitzgerald .rates = CS48L32_RATES,
3346e2bcbf99SRichard Fitzgerald .formats = CS48L32_FORMATS,
3347e2bcbf99SRichard Fitzgerald },
3348e2bcbf99SRichard Fitzgerald .capture = {
3349e2bcbf99SRichard Fitzgerald .stream_name = "ASP2 Capture",
3350e2bcbf99SRichard Fitzgerald .channels_min = 1,
3351e2bcbf99SRichard Fitzgerald .channels_max = 4,
3352e2bcbf99SRichard Fitzgerald .rates = CS48L32_RATES,
3353e2bcbf99SRichard Fitzgerald .formats = CS48L32_FORMATS,
3354e2bcbf99SRichard Fitzgerald },
3355e2bcbf99SRichard Fitzgerald .ops = &cs48l32_dai_ops,
3356e2bcbf99SRichard Fitzgerald .symmetric_rate = 1,
3357e2bcbf99SRichard Fitzgerald .symmetric_sample_bits = 1,
3358e2bcbf99SRichard Fitzgerald },
3359e2bcbf99SRichard Fitzgerald {
3360e2bcbf99SRichard Fitzgerald .name = "cs48l32-cpu-trace",
3361e2bcbf99SRichard Fitzgerald .id = 3,
3362e2bcbf99SRichard Fitzgerald .capture = {
3363e2bcbf99SRichard Fitzgerald .stream_name = "Audio Trace CPU",
3364e2bcbf99SRichard Fitzgerald .channels_min = 1,
3365e2bcbf99SRichard Fitzgerald .channels_max = 8,
3366e2bcbf99SRichard Fitzgerald .rates = CS48L32_RATES,
3367e2bcbf99SRichard Fitzgerald .formats = CS48L32_FORMATS,
3368e2bcbf99SRichard Fitzgerald },
3369e2bcbf99SRichard Fitzgerald .ops = &cs48l32_compress_dai_ops,
3370e2bcbf99SRichard Fitzgerald },
3371e2bcbf99SRichard Fitzgerald {
3372e2bcbf99SRichard Fitzgerald .name = "cs48l32-dsp-trace",
3373e2bcbf99SRichard Fitzgerald .id = 4,
3374e2bcbf99SRichard Fitzgerald .capture = {
3375e2bcbf99SRichard Fitzgerald .stream_name = "Audio Trace DSP",
3376e2bcbf99SRichard Fitzgerald .channels_min = 1,
3377e2bcbf99SRichard Fitzgerald .channels_max = 8,
3378e2bcbf99SRichard Fitzgerald .rates = CS48L32_RATES,
3379e2bcbf99SRichard Fitzgerald .formats = CS48L32_FORMATS,
3380e2bcbf99SRichard Fitzgerald },
3381e2bcbf99SRichard Fitzgerald },
3382e2bcbf99SRichard Fitzgerald {
3383e2bcbf99SRichard Fitzgerald .name = "cs48l32-cpu-voicectrl",
3384e2bcbf99SRichard Fitzgerald .id = 5,
3385e2bcbf99SRichard Fitzgerald .capture = {
3386e2bcbf99SRichard Fitzgerald .stream_name = "Voice Ctrl CPU",
3387e2bcbf99SRichard Fitzgerald .channels_min = 1,
3388e2bcbf99SRichard Fitzgerald .channels_max = 8,
3389e2bcbf99SRichard Fitzgerald .rates = CS48L32_RATES,
3390e2bcbf99SRichard Fitzgerald .formats = CS48L32_FORMATS,
3391e2bcbf99SRichard Fitzgerald },
3392e2bcbf99SRichard Fitzgerald .ops = &cs48l32_compress_dai_ops,
3393e2bcbf99SRichard Fitzgerald },
3394e2bcbf99SRichard Fitzgerald {
3395e2bcbf99SRichard Fitzgerald .name = "cs48l32-dsp-voicectrl",
3396e2bcbf99SRichard Fitzgerald .id = 6,
3397e2bcbf99SRichard Fitzgerald .capture = {
3398e2bcbf99SRichard Fitzgerald .stream_name = "Voice Ctrl DSP",
3399e2bcbf99SRichard Fitzgerald .channels_min = 1,
3400e2bcbf99SRichard Fitzgerald .channels_max = 8,
3401e2bcbf99SRichard Fitzgerald .rates = CS48L32_RATES,
3402e2bcbf99SRichard Fitzgerald .formats = CS48L32_FORMATS,
3403e2bcbf99SRichard Fitzgerald },
3404e2bcbf99SRichard Fitzgerald },
3405e2bcbf99SRichard Fitzgerald };
3406e2bcbf99SRichard Fitzgerald
cs48l32_init_inputs(struct snd_soc_component * component)3407e2bcbf99SRichard Fitzgerald static int cs48l32_init_inputs(struct snd_soc_component *component)
3408e2bcbf99SRichard Fitzgerald {
3409e2bcbf99SRichard Fitzgerald struct cs48l32_codec *cs48l32_codec = snd_soc_component_get_drvdata(component);
3410e2bcbf99SRichard Fitzgerald struct regmap *regmap = cs48l32_codec->core.regmap;
3411e2bcbf99SRichard Fitzgerald unsigned int ana_mode_l, ana_mode_r, dig_mode;
3412e2bcbf99SRichard Fitzgerald int i;
3413e2bcbf99SRichard Fitzgerald
3414e2bcbf99SRichard Fitzgerald /*
3415e2bcbf99SRichard Fitzgerald * Initialize input modes from the A settings. For muxed inputs the
3416e2bcbf99SRichard Fitzgerald * B settings will be applied if the mux is changed
3417e2bcbf99SRichard Fitzgerald */
3418e2bcbf99SRichard Fitzgerald switch (cs48l32_codec->in_type[0][0]) {
3419e2bcbf99SRichard Fitzgerald default:
3420e2bcbf99SRichard Fitzgerald case CS48L32_IN_TYPE_DIFF:
3421e2bcbf99SRichard Fitzgerald ana_mode_l = 0;
3422e2bcbf99SRichard Fitzgerald break;
3423e2bcbf99SRichard Fitzgerald case CS48L32_IN_TYPE_SE:
3424e2bcbf99SRichard Fitzgerald ana_mode_l = 1 << CS48L32_INx_SRC_SHIFT;
3425e2bcbf99SRichard Fitzgerald break;
3426e2bcbf99SRichard Fitzgerald }
3427e2bcbf99SRichard Fitzgerald
3428e2bcbf99SRichard Fitzgerald switch (cs48l32_codec->in_type[1][0]) {
3429e2bcbf99SRichard Fitzgerald default:
3430e2bcbf99SRichard Fitzgerald case CS48L32_IN_TYPE_DIFF:
3431e2bcbf99SRichard Fitzgerald ana_mode_r = 0;
3432e2bcbf99SRichard Fitzgerald break;
3433e2bcbf99SRichard Fitzgerald case CS48L32_IN_TYPE_SE:
3434e2bcbf99SRichard Fitzgerald ana_mode_r = 1 << CS48L32_INx_SRC_SHIFT;
3435e2bcbf99SRichard Fitzgerald break;
3436e2bcbf99SRichard Fitzgerald }
3437e2bcbf99SRichard Fitzgerald
3438e2bcbf99SRichard Fitzgerald dev_dbg(cs48l32_codec->core.dev, "IN1_1 Analogue mode=#%x,#%x\n",
3439e2bcbf99SRichard Fitzgerald ana_mode_l, ana_mode_r);
3440e2bcbf99SRichard Fitzgerald
3441e2bcbf99SRichard Fitzgerald regmap_update_bits(regmap,
3442e2bcbf99SRichard Fitzgerald CS48L32_IN1L_CONTROL1,
3443e2bcbf99SRichard Fitzgerald CS48L32_INx_SRC_MASK,
3444e2bcbf99SRichard Fitzgerald ana_mode_l);
3445e2bcbf99SRichard Fitzgerald
3446e2bcbf99SRichard Fitzgerald regmap_update_bits(regmap,
3447e2bcbf99SRichard Fitzgerald CS48L32_IN1R_CONTROL1,
3448e2bcbf99SRichard Fitzgerald CS48L32_INx_SRC_MASK,
3449e2bcbf99SRichard Fitzgerald ana_mode_r);
3450e2bcbf99SRichard Fitzgerald
3451e2bcbf99SRichard Fitzgerald for (i = 0; i < ARRAY_SIZE(cs48l32_codec->pdm_sup); i++) {
3452e2bcbf99SRichard Fitzgerald dig_mode = cs48l32_codec->pdm_sup[i] << CS48L32_IN1_PDM_SUP_SHIFT;
3453e2bcbf99SRichard Fitzgerald
3454e2bcbf99SRichard Fitzgerald dev_dbg(cs48l32_codec->core.dev, "IN%d PDM_SUP=#%x\n", i + 1, dig_mode);
3455e2bcbf99SRichard Fitzgerald
3456e2bcbf99SRichard Fitzgerald regmap_update_bits(regmap,
3457e2bcbf99SRichard Fitzgerald CS48L32_INPUT1_CONTROL1 + (i * 0x40),
3458e2bcbf99SRichard Fitzgerald CS48L32_IN1_PDM_SUP_MASK, dig_mode);
3459e2bcbf99SRichard Fitzgerald }
3460e2bcbf99SRichard Fitzgerald
3461e2bcbf99SRichard Fitzgerald return 0;
3462e2bcbf99SRichard Fitzgerald }
3463e2bcbf99SRichard Fitzgerald
cs48l32_init_dai(struct cs48l32_codec * cs48l32_codec,int id)3464e2bcbf99SRichard Fitzgerald static int cs48l32_init_dai(struct cs48l32_codec *cs48l32_codec, int id)
3465e2bcbf99SRichard Fitzgerald {
3466e2bcbf99SRichard Fitzgerald struct cs48l32_dai_priv *dai_priv = &cs48l32_codec->dai[id];
3467e2bcbf99SRichard Fitzgerald
3468e2bcbf99SRichard Fitzgerald dai_priv->clk = CS48L32_CLK_SYSCLK_1;
3469e2bcbf99SRichard Fitzgerald dai_priv->constraint = cs48l32_constraint;
3470e2bcbf99SRichard Fitzgerald
3471e2bcbf99SRichard Fitzgerald return 0;
3472e2bcbf99SRichard Fitzgerald }
3473e2bcbf99SRichard Fitzgerald
cs48l32_init_eq(struct cs48l32_codec * cs48l32_codec)3474e2bcbf99SRichard Fitzgerald static int cs48l32_init_eq(struct cs48l32_codec *cs48l32_codec)
3475e2bcbf99SRichard Fitzgerald {
3476e2bcbf99SRichard Fitzgerald struct regmap *regmap = cs48l32_codec->core.regmap;
3477e2bcbf99SRichard Fitzgerald unsigned int reg = CS48L32_EQ1_BAND1_COEFF1, mode;
3478e2bcbf99SRichard Fitzgerald __be16 *data;
3479e2bcbf99SRichard Fitzgerald int i, ret;
3480e2bcbf99SRichard Fitzgerald
3481e2bcbf99SRichard Fitzgerald ret = regmap_read(regmap, CS48L32_EQ_CONTROL2, &mode);
3482e2bcbf99SRichard Fitzgerald if (ret < 0) {
3483e2bcbf99SRichard Fitzgerald dev_err(cs48l32_codec->core.dev, "Error reading EQ mode: %d\n", ret);
3484e2bcbf99SRichard Fitzgerald goto out;
3485e2bcbf99SRichard Fitzgerald }
3486e2bcbf99SRichard Fitzgerald
3487e2bcbf99SRichard Fitzgerald for (i = 0; i < 4; ++i) {
3488e2bcbf99SRichard Fitzgerald cs48l32_codec->eq_mode[i] = (mode >> i) & 0x1;
3489e2bcbf99SRichard Fitzgerald
3490e2bcbf99SRichard Fitzgerald data = &cs48l32_codec->eq_coefficients[i][0];
3491e2bcbf99SRichard Fitzgerald ret = regmap_raw_read(regmap, reg + (i * 68), data,
3492e2bcbf99SRichard Fitzgerald CS48L32_EQ_BLOCK_SZ);
3493e2bcbf99SRichard Fitzgerald if (ret < 0) {
3494e2bcbf99SRichard Fitzgerald dev_err(cs48l32_codec->core.dev,
3495e2bcbf99SRichard Fitzgerald "Error reading EQ coefficients: %d\n", ret);
3496e2bcbf99SRichard Fitzgerald goto out;
3497e2bcbf99SRichard Fitzgerald }
3498e2bcbf99SRichard Fitzgerald }
3499e2bcbf99SRichard Fitzgerald
3500e2bcbf99SRichard Fitzgerald out:
3501e2bcbf99SRichard Fitzgerald return ret;
3502e2bcbf99SRichard Fitzgerald }
3503e2bcbf99SRichard Fitzgerald
cs48l32_component_probe(struct snd_soc_component * component)3504e2bcbf99SRichard Fitzgerald static int cs48l32_component_probe(struct snd_soc_component *component)
3505e2bcbf99SRichard Fitzgerald {
3506e2bcbf99SRichard Fitzgerald struct cs48l32_codec *cs48l32_codec = snd_soc_component_get_drvdata(component);
3507e2bcbf99SRichard Fitzgerald int i, ret;
3508e2bcbf99SRichard Fitzgerald
3509e2bcbf99SRichard Fitzgerald snd_soc_component_init_regmap(component, cs48l32_codec->core.regmap);
3510e2bcbf99SRichard Fitzgerald
3511e2bcbf99SRichard Fitzgerald ret = cs48l32_init_inputs(component);
3512e2bcbf99SRichard Fitzgerald if (ret)
3513e2bcbf99SRichard Fitzgerald return ret;
3514e2bcbf99SRichard Fitzgerald
3515e2bcbf99SRichard Fitzgerald for (i = 0; i < ARRAY_SIZE(cs48l32_dai); i++)
3516e2bcbf99SRichard Fitzgerald cs48l32_init_dai(cs48l32_codec, i);
3517e2bcbf99SRichard Fitzgerald
3518e2bcbf99SRichard Fitzgerald ret = cs48l32_init_eq(cs48l32_codec);
3519e2bcbf99SRichard Fitzgerald if (ret)
3520e2bcbf99SRichard Fitzgerald return ret;
3521e2bcbf99SRichard Fitzgerald
3522e2bcbf99SRichard Fitzgerald wm_adsp2_component_probe(&cs48l32_codec->dsp, component);
3523e2bcbf99SRichard Fitzgerald
3524e2bcbf99SRichard Fitzgerald /* Unmask DSP IRQs */
3525e2bcbf99SRichard Fitzgerald regmap_clear_bits(cs48l32_codec->core.regmap, CS48L32_IRQ1_MASK_7,
3526e2bcbf99SRichard Fitzgerald CS48L32_DSP1_MPU_ERR_EINT1_MASK | CS48L32_DSP1_WDT_EXPIRE_EINT1_MASK);
3527e2bcbf99SRichard Fitzgerald regmap_clear_bits(cs48l32_codec->core.regmap, CS48L32_IRQ1_MASK_9,
3528e2bcbf99SRichard Fitzgerald CS48L32_DSP1_IRQ0_EINT1_MASK);
3529e2bcbf99SRichard Fitzgerald
3530e2bcbf99SRichard Fitzgerald return 0;
3531e2bcbf99SRichard Fitzgerald }
3532e2bcbf99SRichard Fitzgerald
cs48l32_component_remove(struct snd_soc_component * component)3533e2bcbf99SRichard Fitzgerald static void cs48l32_component_remove(struct snd_soc_component *component)
3534e2bcbf99SRichard Fitzgerald {
3535e2bcbf99SRichard Fitzgerald struct cs48l32_codec *cs48l32_codec = snd_soc_component_get_drvdata(component);
3536e2bcbf99SRichard Fitzgerald
3537e2bcbf99SRichard Fitzgerald /* Mask DSP IRQs */
3538e2bcbf99SRichard Fitzgerald regmap_set_bits(cs48l32_codec->core.regmap, CS48L32_IRQ1_MASK_7,
3539e2bcbf99SRichard Fitzgerald CS48L32_DSP1_MPU_ERR_EINT1_MASK | CS48L32_DSP1_WDT_EXPIRE_EINT1_MASK);
3540e2bcbf99SRichard Fitzgerald regmap_set_bits(cs48l32_codec->core.regmap, CS48L32_IRQ1_MASK_9,
3541e2bcbf99SRichard Fitzgerald CS48L32_DSP1_IRQ0_EINT1_MASK);
3542e2bcbf99SRichard Fitzgerald
3543e2bcbf99SRichard Fitzgerald wm_adsp2_component_remove(&cs48l32_codec->dsp, component);
3544e2bcbf99SRichard Fitzgerald }
3545e2bcbf99SRichard Fitzgerald
3546e2bcbf99SRichard Fitzgerald static const struct snd_soc_component_driver cs48l32_soc_component_drv = {
3547e2bcbf99SRichard Fitzgerald .probe = &cs48l32_component_probe,
3548e2bcbf99SRichard Fitzgerald .remove = &cs48l32_component_remove,
3549e2bcbf99SRichard Fitzgerald .set_sysclk = &cs48l32_set_sysclk,
3550e2bcbf99SRichard Fitzgerald .set_pll = &cs48l32_set_fll,
3551e2bcbf99SRichard Fitzgerald .name = "cs48l32-codec",
3552e2bcbf99SRichard Fitzgerald .compress_ops = &cs48l32_compress_ops,
3553e2bcbf99SRichard Fitzgerald .controls = cs48l32_snd_controls,
3554e2bcbf99SRichard Fitzgerald .num_controls = ARRAY_SIZE(cs48l32_snd_controls),
3555e2bcbf99SRichard Fitzgerald .dapm_widgets = cs48l32_dapm_widgets,
3556e2bcbf99SRichard Fitzgerald .num_dapm_widgets = ARRAY_SIZE(cs48l32_dapm_widgets),
3557e2bcbf99SRichard Fitzgerald .dapm_routes = cs48l32_dapm_routes,
3558e2bcbf99SRichard Fitzgerald .num_dapm_routes = ARRAY_SIZE(cs48l32_dapm_routes),
3559e2bcbf99SRichard Fitzgerald .use_pmdown_time = 1,
3560e2bcbf99SRichard Fitzgerald .endianness = 1,
3561e2bcbf99SRichard Fitzgerald };
3562e2bcbf99SRichard Fitzgerald
cs48l32_prop_read_u32_array(struct cs48l32_codec * cs48l32_codec,const char * propname,u32 * dest,int n_max)3563e2bcbf99SRichard Fitzgerald static int cs48l32_prop_read_u32_array(struct cs48l32_codec *cs48l32_codec,
3564e2bcbf99SRichard Fitzgerald const char *propname,
3565e2bcbf99SRichard Fitzgerald u32 *dest,
3566e2bcbf99SRichard Fitzgerald int n_max)
3567e2bcbf99SRichard Fitzgerald {
3568e2bcbf99SRichard Fitzgerald struct cs48l32 *cs48l32 = &cs48l32_codec->core;
3569e2bcbf99SRichard Fitzgerald int ret;
3570e2bcbf99SRichard Fitzgerald
3571e2bcbf99SRichard Fitzgerald ret = device_property_read_u32_array(cs48l32->dev, propname, dest, n_max);
3572e2bcbf99SRichard Fitzgerald if (ret == -EINVAL)
3573e2bcbf99SRichard Fitzgerald return -ENOENT;
3574e2bcbf99SRichard Fitzgerald
3575e2bcbf99SRichard Fitzgerald if (ret < 0)
3576e2bcbf99SRichard Fitzgerald return dev_err_probe(cs48l32->dev, ret, "%s malformed\n", propname);
3577e2bcbf99SRichard Fitzgerald
3578e2bcbf99SRichard Fitzgerald return 0;
3579e2bcbf99SRichard Fitzgerald }
3580e2bcbf99SRichard Fitzgerald
cs48l32_prop_get_in_type(struct cs48l32_codec * cs48l32_codec)3581e2bcbf99SRichard Fitzgerald static void cs48l32_prop_get_in_type(struct cs48l32_codec *cs48l32_codec)
3582e2bcbf99SRichard Fitzgerald {
3583e2bcbf99SRichard Fitzgerald const char *propname = "cirrus,in-type";
3584e2bcbf99SRichard Fitzgerald u32 tmp[CS48L32_MAX_ANALOG_INPUT * CS48L32_MAX_IN_MUX_WAYS];
3585e2bcbf99SRichard Fitzgerald int i, in_idx, mux_way_idx, ret;
3586e2bcbf99SRichard Fitzgerald
3587e2bcbf99SRichard Fitzgerald static_assert(ARRAY_SIZE(tmp) ==
3588e2bcbf99SRichard Fitzgerald ARRAY_SIZE(cs48l32_codec->in_type) * ARRAY_SIZE(cs48l32_codec->in_type[0]));
3589e2bcbf99SRichard Fitzgerald
3590e2bcbf99SRichard Fitzgerald ret = cs48l32_prop_read_u32_array(cs48l32_codec, propname, tmp, ARRAY_SIZE(tmp));
3591e2bcbf99SRichard Fitzgerald if (ret < 0)
3592e2bcbf99SRichard Fitzgerald return;
3593e2bcbf99SRichard Fitzgerald
3594e2bcbf99SRichard Fitzgerald in_idx = 0;
3595e2bcbf99SRichard Fitzgerald mux_way_idx = 0;
3596e2bcbf99SRichard Fitzgerald for (i = 0; i < ARRAY_SIZE(tmp); ++i) {
3597e2bcbf99SRichard Fitzgerald switch (tmp[i]) {
3598e2bcbf99SRichard Fitzgerald case CS48L32_IN_TYPE_DIFF:
3599e2bcbf99SRichard Fitzgerald case CS48L32_IN_TYPE_SE:
3600e2bcbf99SRichard Fitzgerald cs48l32_codec->in_type[in_idx][mux_way_idx] = tmp[i];
3601e2bcbf99SRichard Fitzgerald break;
3602e2bcbf99SRichard Fitzgerald default:
3603e2bcbf99SRichard Fitzgerald dev_warn(cs48l32_codec->core.dev, "Illegal %s value %d ignored\n",
3604e2bcbf99SRichard Fitzgerald propname, tmp[i]);
3605e2bcbf99SRichard Fitzgerald break;
3606e2bcbf99SRichard Fitzgerald }
3607e2bcbf99SRichard Fitzgerald
3608e2bcbf99SRichard Fitzgerald /*
3609e2bcbf99SRichard Fitzgerald * Property array is [mux_way][in_channel]. Swap to
3610e2bcbf99SRichard Fitzgerald * [in_channel][mux_way] for convenience.
3611e2bcbf99SRichard Fitzgerald */
3612e2bcbf99SRichard Fitzgerald if (++in_idx == ARRAY_SIZE(cs48l32_codec->in_type)) {
3613e2bcbf99SRichard Fitzgerald in_idx = 0;
3614e2bcbf99SRichard Fitzgerald ++mux_way_idx;
3615e2bcbf99SRichard Fitzgerald }
3616e2bcbf99SRichard Fitzgerald }
3617e2bcbf99SRichard Fitzgerald }
3618e2bcbf99SRichard Fitzgerald
cs48l32_prop_get_pdm_sup(struct cs48l32_codec * cs48l32_codec)3619e2bcbf99SRichard Fitzgerald static void cs48l32_prop_get_pdm_sup(struct cs48l32_codec *cs48l32_codec)
3620e2bcbf99SRichard Fitzgerald {
3621e2bcbf99SRichard Fitzgerald const char *propname = "cirrus,pdm-sup";
3622e2bcbf99SRichard Fitzgerald u32 tmp[CS48L32_MAX_ANALOG_INPUT];
3623e2bcbf99SRichard Fitzgerald int i;
3624e2bcbf99SRichard Fitzgerald
3625e2bcbf99SRichard Fitzgerald static_assert(ARRAY_SIZE(tmp) == ARRAY_SIZE(cs48l32_codec->pdm_sup));
3626e2bcbf99SRichard Fitzgerald
3627e2bcbf99SRichard Fitzgerald cs48l32_prop_read_u32_array(cs48l32_codec, propname, tmp, ARRAY_SIZE(tmp));
3628e2bcbf99SRichard Fitzgerald
3629e2bcbf99SRichard Fitzgerald for (i = 0; i < ARRAY_SIZE(cs48l32_codec->pdm_sup); i++) {
3630e2bcbf99SRichard Fitzgerald switch (tmp[i]) {
3631e2bcbf99SRichard Fitzgerald case CS48L32_PDM_SUP_VOUT_MIC:
3632e2bcbf99SRichard Fitzgerald case CS48L32_PDM_SUP_MICBIAS1:
3633e2bcbf99SRichard Fitzgerald cs48l32_codec->pdm_sup[i] = tmp[i];
3634e2bcbf99SRichard Fitzgerald break;
3635e2bcbf99SRichard Fitzgerald default:
3636e2bcbf99SRichard Fitzgerald dev_warn(cs48l32_codec->core.dev, "Illegal %s value %d ignored\n",
3637e2bcbf99SRichard Fitzgerald propname, cs48l32_codec->pdm_sup[i]);
3638e2bcbf99SRichard Fitzgerald break;
3639e2bcbf99SRichard Fitzgerald }
3640e2bcbf99SRichard Fitzgerald }
3641e2bcbf99SRichard Fitzgerald }
3642e2bcbf99SRichard Fitzgerald
cs48l32_handle_properties(struct cs48l32_codec * cs48l32_codec)3643e2bcbf99SRichard Fitzgerald static void cs48l32_handle_properties(struct cs48l32_codec *cs48l32_codec)
3644e2bcbf99SRichard Fitzgerald {
3645e2bcbf99SRichard Fitzgerald cs48l32_prop_get_in_type(cs48l32_codec);
3646e2bcbf99SRichard Fitzgerald cs48l32_prop_get_pdm_sup(cs48l32_codec);
3647e2bcbf99SRichard Fitzgerald }
3648e2bcbf99SRichard Fitzgerald
cs48l32_request_interrupt(struct cs48l32_codec * cs48l32_codec)3649e2bcbf99SRichard Fitzgerald static int cs48l32_request_interrupt(struct cs48l32_codec *cs48l32_codec)
3650e2bcbf99SRichard Fitzgerald {
3651e2bcbf99SRichard Fitzgerald int irq = cs48l32_codec->core.irq;
3652e2bcbf99SRichard Fitzgerald int ret;
3653e2bcbf99SRichard Fitzgerald
3654e2bcbf99SRichard Fitzgerald if (irq < 1)
3655e2bcbf99SRichard Fitzgerald return 0;
3656e2bcbf99SRichard Fitzgerald
3657e2bcbf99SRichard Fitzgerald /*
3658e2bcbf99SRichard Fitzgerald * Don't use devm because this must be freed before destroying the
3659e2bcbf99SRichard Fitzgerald * rest of the driver
3660e2bcbf99SRichard Fitzgerald */
3661e2bcbf99SRichard Fitzgerald ret = request_threaded_irq(irq, NULL, cs48l32_irq,
3662e2bcbf99SRichard Fitzgerald IRQF_ONESHOT | IRQF_SHARED | IRQF_TRIGGER_LOW,
3663e2bcbf99SRichard Fitzgerald "cs48l32", cs48l32_codec);
3664e2bcbf99SRichard Fitzgerald if (ret)
3665e2bcbf99SRichard Fitzgerald return dev_err_probe(cs48l32_codec->core.dev, ret, "Failed to get IRQ\n");
3666e2bcbf99SRichard Fitzgerald
3667e2bcbf99SRichard Fitzgerald return 0;
3668e2bcbf99SRichard Fitzgerald }
3669e2bcbf99SRichard Fitzgerald
cs48l32_create_codec_component(struct cs48l32_codec * cs48l32_codec)3670e2bcbf99SRichard Fitzgerald static int cs48l32_create_codec_component(struct cs48l32_codec *cs48l32_codec)
3671e2bcbf99SRichard Fitzgerald {
3672e2bcbf99SRichard Fitzgerald struct wm_adsp *dsp;
3673e2bcbf99SRichard Fitzgerald int ret;
3674e2bcbf99SRichard Fitzgerald
3675e2bcbf99SRichard Fitzgerald ASSERT_STRUCT_OFFSET(struct cs48l32_codec, dsp, 0);
3676e2bcbf99SRichard Fitzgerald static_assert(ARRAY_SIZE(cs48l32_dai) == ARRAY_SIZE(cs48l32_codec->dai));
3677e2bcbf99SRichard Fitzgerald
3678e2bcbf99SRichard Fitzgerald cs48l32_handle_properties(cs48l32_codec);
3679e2bcbf99SRichard Fitzgerald
3680e2bcbf99SRichard Fitzgerald dsp = &cs48l32_codec->dsp;
3681e2bcbf99SRichard Fitzgerald dsp->part = "cs48l32";
3682e2bcbf99SRichard Fitzgerald dsp->cs_dsp.num = 1;
3683e2bcbf99SRichard Fitzgerald dsp->cs_dsp.type = WMFW_HALO;
3684e2bcbf99SRichard Fitzgerald dsp->cs_dsp.rev = 0;
3685e2bcbf99SRichard Fitzgerald dsp->cs_dsp.dev = cs48l32_codec->core.dev;
3686e2bcbf99SRichard Fitzgerald dsp->cs_dsp.regmap = cs48l32_codec->core.regmap;
3687e2bcbf99SRichard Fitzgerald dsp->cs_dsp.base = CS48L32_DSP1_CLOCK_FREQ;
3688e2bcbf99SRichard Fitzgerald dsp->cs_dsp.base_sysinfo = CS48L32_DSP1_SYS_INFO_ID;
3689e2bcbf99SRichard Fitzgerald dsp->cs_dsp.mem = cs48l32_dsp1_regions;
3690e2bcbf99SRichard Fitzgerald dsp->cs_dsp.num_mems = ARRAY_SIZE(cs48l32_dsp1_regions);
3691e2bcbf99SRichard Fitzgerald dsp->pre_run = cs48l32_dsp_pre_run;
3692e2bcbf99SRichard Fitzgerald
3693e2bcbf99SRichard Fitzgerald ret = wm_halo_init(dsp);
3694e2bcbf99SRichard Fitzgerald if (ret != 0)
3695e2bcbf99SRichard Fitzgerald return ret;
3696e2bcbf99SRichard Fitzgerald
3697e2bcbf99SRichard Fitzgerald cs48l32_codec->fll.codec = cs48l32_codec;
3698e2bcbf99SRichard Fitzgerald cs48l32_codec->fll.id = 1;
3699e2bcbf99SRichard Fitzgerald cs48l32_codec->fll.base = CS48L32_FLL1_CONTROL1;
3700e2bcbf99SRichard Fitzgerald cs48l32_codec->fll.sts_addr = CS48L32_IRQ1_STS_6;
3701e2bcbf99SRichard Fitzgerald cs48l32_codec->fll.sts_mask = CS48L32_FLL1_LOCK_STS1_MASK;
3702e2bcbf99SRichard Fitzgerald cs48l32_init_fll(&cs48l32_codec->fll);
3703e2bcbf99SRichard Fitzgerald
3704e2bcbf99SRichard Fitzgerald ret = cs48l32_request_interrupt(cs48l32_codec);
3705e2bcbf99SRichard Fitzgerald if (ret)
3706e2bcbf99SRichard Fitzgerald goto err_dsp;
3707e2bcbf99SRichard Fitzgerald
3708e2bcbf99SRichard Fitzgerald ret = devm_snd_soc_register_component(cs48l32_codec->core.dev,
3709e2bcbf99SRichard Fitzgerald &cs48l32_soc_component_drv,
3710e2bcbf99SRichard Fitzgerald cs48l32_dai,
3711e2bcbf99SRichard Fitzgerald ARRAY_SIZE(cs48l32_dai));
3712e2bcbf99SRichard Fitzgerald if (ret < 0) {
3713e2bcbf99SRichard Fitzgerald dev_err_probe(cs48l32_codec->core.dev, ret, "Failed to register component\n");
3714e2bcbf99SRichard Fitzgerald goto err_dsp;
3715e2bcbf99SRichard Fitzgerald }
3716e2bcbf99SRichard Fitzgerald
3717e2bcbf99SRichard Fitzgerald return 0;
3718e2bcbf99SRichard Fitzgerald
3719e2bcbf99SRichard Fitzgerald err_dsp:
3720e2bcbf99SRichard Fitzgerald wm_adsp2_remove(&cs48l32_codec->dsp);
3721e2bcbf99SRichard Fitzgerald
3722e2bcbf99SRichard Fitzgerald return ret;
3723e2bcbf99SRichard Fitzgerald }
3724e2bcbf99SRichard Fitzgerald
cs48l32_wait_for_boot(struct cs48l32 * cs48l32)3725e2bcbf99SRichard Fitzgerald static int cs48l32_wait_for_boot(struct cs48l32 *cs48l32)
3726e2bcbf99SRichard Fitzgerald {
3727e2bcbf99SRichard Fitzgerald unsigned int val;
3728e2bcbf99SRichard Fitzgerald int ret;
3729e2bcbf99SRichard Fitzgerald
3730e2bcbf99SRichard Fitzgerald ret = regmap_read_poll_timeout(cs48l32->regmap, CS48L32_IRQ1_EINT_2, val,
3731e2bcbf99SRichard Fitzgerald ((val < 0xffffffff) && (val & CS48L32_BOOT_DONE_EINT1_MASK)),
3732e2bcbf99SRichard Fitzgerald 1000, CS48L32_BOOT_TIMEOUT_US);
3733e2bcbf99SRichard Fitzgerald if (ret) {
3734e2bcbf99SRichard Fitzgerald dev_err(cs48l32->dev, "BOOT_DONE timed out\n");
3735e2bcbf99SRichard Fitzgerald return -ETIMEDOUT;
3736e2bcbf99SRichard Fitzgerald }
3737e2bcbf99SRichard Fitzgerald
3738e2bcbf99SRichard Fitzgerald ret = regmap_read(cs48l32->regmap, CS48L32_MCU_CTRL1, &val);
3739e2bcbf99SRichard Fitzgerald if (ret) {
3740e2bcbf99SRichard Fitzgerald dev_err(cs48l32->dev, "Failed to read MCU_CTRL1: %d\n", ret);
3741e2bcbf99SRichard Fitzgerald return ret;
3742e2bcbf99SRichard Fitzgerald }
3743e2bcbf99SRichard Fitzgerald
3744e2bcbf99SRichard Fitzgerald if (val & BIT(CS48L32_MCU_STS_SHIFT)) {
3745e2bcbf99SRichard Fitzgerald dev_err(cs48l32->dev, "MCU boot failed\n");
3746e2bcbf99SRichard Fitzgerald return -EIO;
3747e2bcbf99SRichard Fitzgerald }
3748e2bcbf99SRichard Fitzgerald
3749e2bcbf99SRichard Fitzgerald pm_runtime_mark_last_busy(cs48l32->dev);
3750e2bcbf99SRichard Fitzgerald
3751e2bcbf99SRichard Fitzgerald return 0;
3752e2bcbf99SRichard Fitzgerald }
3753e2bcbf99SRichard Fitzgerald
cs48l32_soft_reset(struct cs48l32 * cs48l32)3754e2bcbf99SRichard Fitzgerald static int cs48l32_soft_reset(struct cs48l32 *cs48l32)
3755e2bcbf99SRichard Fitzgerald {
3756e2bcbf99SRichard Fitzgerald int ret;
3757e2bcbf99SRichard Fitzgerald
3758e2bcbf99SRichard Fitzgerald ret = regmap_write(cs48l32->regmap, CS48L32_SFT_RESET, CS48L32_SFT_RESET_MAGIC);
3759e2bcbf99SRichard Fitzgerald if (ret != 0) {
3760e2bcbf99SRichard Fitzgerald dev_err(cs48l32->dev, "Failed to write soft reset: %d\n", ret);
3761e2bcbf99SRichard Fitzgerald return ret;
3762e2bcbf99SRichard Fitzgerald }
3763e2bcbf99SRichard Fitzgerald
3764e2bcbf99SRichard Fitzgerald usleep_range(CS48L32_SOFT_RESET_US, CS48L32_SOFT_RESET_US + 1000);
3765e2bcbf99SRichard Fitzgerald
3766e2bcbf99SRichard Fitzgerald return 0;
3767e2bcbf99SRichard Fitzgerald }
3768e2bcbf99SRichard Fitzgerald
cs48l32_enable_hard_reset(struct cs48l32 * cs48l32)3769e2bcbf99SRichard Fitzgerald static void cs48l32_enable_hard_reset(struct cs48l32 *cs48l32)
3770e2bcbf99SRichard Fitzgerald {
3771e2bcbf99SRichard Fitzgerald if (cs48l32->reset_gpio)
3772e2bcbf99SRichard Fitzgerald gpiod_set_raw_value_cansleep(cs48l32->reset_gpio, 0);
3773e2bcbf99SRichard Fitzgerald }
3774e2bcbf99SRichard Fitzgerald
cs48l32_disable_hard_reset(struct cs48l32 * cs48l32)3775e2bcbf99SRichard Fitzgerald static void cs48l32_disable_hard_reset(struct cs48l32 *cs48l32)
3776e2bcbf99SRichard Fitzgerald {
3777e2bcbf99SRichard Fitzgerald if (cs48l32->reset_gpio) {
3778e2bcbf99SRichard Fitzgerald gpiod_set_raw_value_cansleep(cs48l32->reset_gpio, 1);
3779e2bcbf99SRichard Fitzgerald usleep_range(CS48L32_HARD_RESET_MIN_US, CS48L32_HARD_RESET_MIN_US + 1000);
3780e2bcbf99SRichard Fitzgerald }
3781e2bcbf99SRichard Fitzgerald }
3782e2bcbf99SRichard Fitzgerald
cs48l32_runtime_resume(struct device * dev)3783e2bcbf99SRichard Fitzgerald static int cs48l32_runtime_resume(struct device *dev)
3784e2bcbf99SRichard Fitzgerald {
3785e2bcbf99SRichard Fitzgerald struct cs48l32_codec *cs48l32_codec = dev_get_drvdata(dev);
3786e2bcbf99SRichard Fitzgerald struct cs48l32 *cs48l32 = &cs48l32_codec->core;
3787e2bcbf99SRichard Fitzgerald unsigned int val;
3788e2bcbf99SRichard Fitzgerald int ret;
3789e2bcbf99SRichard Fitzgerald
3790e2bcbf99SRichard Fitzgerald ret = regulator_enable(cs48l32->vdd_d);
3791e2bcbf99SRichard Fitzgerald if (ret) {
3792e2bcbf99SRichard Fitzgerald dev_err(cs48l32->dev, "Failed to enable VDD_D: %d\n", ret);
3793e2bcbf99SRichard Fitzgerald return ret;
3794e2bcbf99SRichard Fitzgerald }
3795e2bcbf99SRichard Fitzgerald
3796e2bcbf99SRichard Fitzgerald usleep_range(CS48L32_SOFT_RESET_US, CS48L32_SOFT_RESET_US + 1000);
3797e2bcbf99SRichard Fitzgerald
3798e2bcbf99SRichard Fitzgerald regcache_cache_only(cs48l32->regmap, false);
3799e2bcbf99SRichard Fitzgerald
3800e2bcbf99SRichard Fitzgerald ret = cs48l32_wait_for_boot(cs48l32);
3801e2bcbf99SRichard Fitzgerald if (ret)
3802e2bcbf99SRichard Fitzgerald goto err;
3803e2bcbf99SRichard Fitzgerald
3804e2bcbf99SRichard Fitzgerald /* Check whether registers reset during suspend */
3805e2bcbf99SRichard Fitzgerald regmap_read(cs48l32->regmap, CS48L32_CTRL_IF_DEBUG3, &val);
3806e2bcbf99SRichard Fitzgerald if (!val)
3807e2bcbf99SRichard Fitzgerald regcache_mark_dirty(cs48l32->regmap);
3808e2bcbf99SRichard Fitzgerald else
3809e2bcbf99SRichard Fitzgerald dev_dbg(cs48l32->dev, "Did not reset during suspend\n");
3810e2bcbf99SRichard Fitzgerald
3811e2bcbf99SRichard Fitzgerald ret = regcache_sync(cs48l32->regmap);
3812e2bcbf99SRichard Fitzgerald if (ret) {
3813e2bcbf99SRichard Fitzgerald dev_err(cs48l32->dev, "Failed to restore register cache\n");
3814e2bcbf99SRichard Fitzgerald goto err;
3815e2bcbf99SRichard Fitzgerald }
3816e2bcbf99SRichard Fitzgerald
3817e2bcbf99SRichard Fitzgerald return 0;
3818e2bcbf99SRichard Fitzgerald
3819e2bcbf99SRichard Fitzgerald err:
3820e2bcbf99SRichard Fitzgerald regcache_cache_only(cs48l32->regmap, true);
3821e2bcbf99SRichard Fitzgerald regulator_disable(cs48l32->vdd_d);
3822e2bcbf99SRichard Fitzgerald
3823e2bcbf99SRichard Fitzgerald return ret;
3824e2bcbf99SRichard Fitzgerald }
3825e2bcbf99SRichard Fitzgerald
cs48l32_runtime_suspend(struct device * dev)3826e2bcbf99SRichard Fitzgerald static int cs48l32_runtime_suspend(struct device *dev)
3827e2bcbf99SRichard Fitzgerald {
3828e2bcbf99SRichard Fitzgerald struct cs48l32_codec *cs48l32_codec = dev_get_drvdata(dev);
3829e2bcbf99SRichard Fitzgerald struct cs48l32 *cs48l32 = &cs48l32_codec->core;
3830e2bcbf99SRichard Fitzgerald
3831e2bcbf99SRichard Fitzgerald /* Flag to detect if the registers reset during suspend */
3832e2bcbf99SRichard Fitzgerald regmap_write(cs48l32->regmap, CS48L32_CTRL_IF_DEBUG3, 1);
3833e2bcbf99SRichard Fitzgerald
3834e2bcbf99SRichard Fitzgerald regcache_cache_only(cs48l32->regmap, true);
3835e2bcbf99SRichard Fitzgerald regulator_disable(cs48l32->vdd_d);
3836e2bcbf99SRichard Fitzgerald
3837e2bcbf99SRichard Fitzgerald return 0;
3838e2bcbf99SRichard Fitzgerald }
3839e2bcbf99SRichard Fitzgerald
3840e2bcbf99SRichard Fitzgerald static const struct dev_pm_ops cs48l32_pm_ops = {
38416070ef6eSNathan Chancellor RUNTIME_PM_OPS(cs48l32_runtime_suspend, cs48l32_runtime_resume, NULL)
3842e2bcbf99SRichard Fitzgerald };
3843e2bcbf99SRichard Fitzgerald
cs48l32_configure_clk32k(struct cs48l32 * cs48l32)3844e2bcbf99SRichard Fitzgerald static int cs48l32_configure_clk32k(struct cs48l32 *cs48l32)
3845e2bcbf99SRichard Fitzgerald {
3846e2bcbf99SRichard Fitzgerald int ret = 0;
3847e2bcbf99SRichard Fitzgerald
3848e2bcbf99SRichard Fitzgerald ret = clk_prepare_enable(cs48l32->mclk1);
3849e2bcbf99SRichard Fitzgerald if (ret)
3850e2bcbf99SRichard Fitzgerald return dev_err_probe(cs48l32->dev, ret, "Failed to enable 32k clock\n");
3851e2bcbf99SRichard Fitzgerald
3852e2bcbf99SRichard Fitzgerald ret = regmap_update_bits(cs48l32->regmap, CS48L32_CLOCK32K,
3853e2bcbf99SRichard Fitzgerald CS48L32_CLK_32K_EN_MASK | CS48L32_CLK_32K_SRC_MASK,
3854e2bcbf99SRichard Fitzgerald CS48L32_CLK_32K_EN_MASK | CS48L32_32K_MCLK1);
3855e2bcbf99SRichard Fitzgerald if (ret) {
3856e2bcbf99SRichard Fitzgerald clk_disable_unprepare(cs48l32->mclk1);
3857e2bcbf99SRichard Fitzgerald return dev_err_probe(cs48l32->dev, ret, "Failed to init 32k clock\n");
3858e2bcbf99SRichard Fitzgerald }
3859e2bcbf99SRichard Fitzgerald
3860e2bcbf99SRichard Fitzgerald return 0;
3861e2bcbf99SRichard Fitzgerald }
3862e2bcbf99SRichard Fitzgerald
cs48l32_get_clocks(struct cs48l32 * cs48l32)3863e2bcbf99SRichard Fitzgerald static int cs48l32_get_clocks(struct cs48l32 *cs48l32)
3864e2bcbf99SRichard Fitzgerald {
3865e2bcbf99SRichard Fitzgerald cs48l32->mclk1 = devm_clk_get_optional(cs48l32->dev, "mclk1");
3866e2bcbf99SRichard Fitzgerald if (IS_ERR(cs48l32->mclk1))
3867e2bcbf99SRichard Fitzgerald return dev_err_probe(cs48l32->dev, PTR_ERR(cs48l32->mclk1),
3868e2bcbf99SRichard Fitzgerald "Failed to get mclk1\n");
3869e2bcbf99SRichard Fitzgerald
3870e2bcbf99SRichard Fitzgerald return 0;
3871e2bcbf99SRichard Fitzgerald }
3872e2bcbf99SRichard Fitzgerald
cs48l32_get_reset_gpio(struct cs48l32 * cs48l32)3873e2bcbf99SRichard Fitzgerald static int cs48l32_get_reset_gpio(struct cs48l32 *cs48l32)
3874e2bcbf99SRichard Fitzgerald {
3875e2bcbf99SRichard Fitzgerald struct gpio_desc *reset;
3876e2bcbf99SRichard Fitzgerald
3877e2bcbf99SRichard Fitzgerald reset = devm_gpiod_get_optional(cs48l32->dev, "reset", GPIOD_OUT_LOW);
3878e2bcbf99SRichard Fitzgerald if (IS_ERR(reset))
3879e2bcbf99SRichard Fitzgerald return dev_err_probe(cs48l32->dev, PTR_ERR(reset), "Failed to request /RESET\n");
3880e2bcbf99SRichard Fitzgerald
3881e2bcbf99SRichard Fitzgerald /* ACPI can override the GPIOD_OUT_LOW so ensure it starts low */
3882e2bcbf99SRichard Fitzgerald gpiod_set_raw_value_cansleep(reset, 0);
3883e2bcbf99SRichard Fitzgerald
3884e2bcbf99SRichard Fitzgerald cs48l32->reset_gpio = reset;
3885e2bcbf99SRichard Fitzgerald
3886e2bcbf99SRichard Fitzgerald return 0;
3887e2bcbf99SRichard Fitzgerald }
3888e2bcbf99SRichard Fitzgerald
cs48l32_spi_probe(struct spi_device * spi)3889e2bcbf99SRichard Fitzgerald static int cs48l32_spi_probe(struct spi_device *spi)
3890e2bcbf99SRichard Fitzgerald {
3891e2bcbf99SRichard Fitzgerald struct device *dev = &spi->dev;
3892e2bcbf99SRichard Fitzgerald struct cs48l32_codec *cs48l32_codec;
3893e2bcbf99SRichard Fitzgerald struct cs48l32 *cs48l32;
3894e2bcbf99SRichard Fitzgerald unsigned int hwid, rev, otp_rev;
3895e2bcbf99SRichard Fitzgerald int i, ret;
3896e2bcbf99SRichard Fitzgerald
3897e2bcbf99SRichard Fitzgerald cs48l32_codec = devm_kzalloc(&spi->dev, sizeof(*cs48l32_codec), GFP_KERNEL);
3898e2bcbf99SRichard Fitzgerald if (!cs48l32_codec)
3899e2bcbf99SRichard Fitzgerald return -ENOMEM;
3900e2bcbf99SRichard Fitzgerald
3901e2bcbf99SRichard Fitzgerald cs48l32 = &cs48l32_codec->core;
3902e2bcbf99SRichard Fitzgerald cs48l32->dev = dev;
3903e2bcbf99SRichard Fitzgerald cs48l32->irq = spi->irq;
3904e2bcbf99SRichard Fitzgerald mutex_init(&cs48l32_codec->rate_lock);
3905e2bcbf99SRichard Fitzgerald cs48l32_codec->in_vu_reg = CS48L32_INPUT_CONTROL3;
3906e2bcbf99SRichard Fitzgerald
3907e2bcbf99SRichard Fitzgerald dev_set_drvdata(cs48l32->dev, cs48l32_codec);
3908e2bcbf99SRichard Fitzgerald
3909e2bcbf99SRichard Fitzgerald ret = cs48l32_create_regmap(spi, cs48l32);
3910e2bcbf99SRichard Fitzgerald if (ret)
3911e2bcbf99SRichard Fitzgerald return dev_err_probe(&spi->dev, ret, "Failed to allocate regmap\n");
3912e2bcbf99SRichard Fitzgerald
3913e2bcbf99SRichard Fitzgerald regcache_cache_only(cs48l32->regmap, true);
3914e2bcbf99SRichard Fitzgerald
3915e2bcbf99SRichard Fitzgerald ret = cs48l32_get_reset_gpio(cs48l32);
3916e2bcbf99SRichard Fitzgerald if (ret)
3917e2bcbf99SRichard Fitzgerald return ret;
3918e2bcbf99SRichard Fitzgerald
3919e2bcbf99SRichard Fitzgerald ret = cs48l32_get_clocks(cs48l32);
3920e2bcbf99SRichard Fitzgerald if (ret)
3921e2bcbf99SRichard Fitzgerald return ret;
3922e2bcbf99SRichard Fitzgerald
3923e2bcbf99SRichard Fitzgerald static_assert(ARRAY_SIZE(cs48l32_core_supplies) == ARRAY_SIZE(cs48l32->core_supplies));
3924e2bcbf99SRichard Fitzgerald for (i = 0; i < ARRAY_SIZE(cs48l32->core_supplies); i++)
3925e2bcbf99SRichard Fitzgerald cs48l32->core_supplies[i].supply = cs48l32_core_supplies[i];
3926e2bcbf99SRichard Fitzgerald
3927e2bcbf99SRichard Fitzgerald ret = devm_regulator_bulk_get(dev, ARRAY_SIZE(cs48l32->core_supplies),
3928e2bcbf99SRichard Fitzgerald cs48l32->core_supplies);
3929e2bcbf99SRichard Fitzgerald if (ret)
3930e2bcbf99SRichard Fitzgerald return dev_err_probe(dev, ret, "Failed to request core supplies\n");
3931e2bcbf99SRichard Fitzgerald
3932e2bcbf99SRichard Fitzgerald cs48l32->vdd_d = devm_regulator_get(cs48l32->dev, "vdd-d");
3933e2bcbf99SRichard Fitzgerald if (IS_ERR(cs48l32->vdd_d))
3934e2bcbf99SRichard Fitzgerald return dev_err_probe(dev, PTR_ERR(cs48l32->vdd_d), "Failed to request vdd-d\n");
3935e2bcbf99SRichard Fitzgerald
3936e2bcbf99SRichard Fitzgerald ret = regulator_bulk_enable(ARRAY_SIZE(cs48l32->core_supplies), cs48l32->core_supplies);
3937e2bcbf99SRichard Fitzgerald if (ret)
3938e2bcbf99SRichard Fitzgerald return dev_err_probe(dev, ret, "Failed to enable core supplies\n");
3939e2bcbf99SRichard Fitzgerald
3940e2bcbf99SRichard Fitzgerald ret = regulator_enable(cs48l32->vdd_d);
3941e2bcbf99SRichard Fitzgerald if (ret) {
3942e2bcbf99SRichard Fitzgerald dev_err(dev, "Failed to enable vdd-d: %d\n", ret);
3943e2bcbf99SRichard Fitzgerald goto err_enable;
3944e2bcbf99SRichard Fitzgerald }
3945e2bcbf99SRichard Fitzgerald
3946e2bcbf99SRichard Fitzgerald cs48l32_disable_hard_reset(cs48l32);
3947e2bcbf99SRichard Fitzgerald
3948e2bcbf99SRichard Fitzgerald regcache_cache_only(cs48l32->regmap, false);
3949e2bcbf99SRichard Fitzgerald
3950e2bcbf99SRichard Fitzgerald /* If we don't have a reset GPIO use a soft reset */
3951e2bcbf99SRichard Fitzgerald if (!cs48l32->reset_gpio) {
3952e2bcbf99SRichard Fitzgerald ret = cs48l32_soft_reset(cs48l32);
3953e2bcbf99SRichard Fitzgerald if (ret)
3954e2bcbf99SRichard Fitzgerald goto err_reset;
3955e2bcbf99SRichard Fitzgerald }
3956e2bcbf99SRichard Fitzgerald
3957e2bcbf99SRichard Fitzgerald ret = cs48l32_wait_for_boot(cs48l32);
3958e2bcbf99SRichard Fitzgerald if (ret) {
3959e2bcbf99SRichard Fitzgerald dev_err(cs48l32->dev, "Device failed initial boot: %d\n", ret);
3960e2bcbf99SRichard Fitzgerald goto err_reset;
3961e2bcbf99SRichard Fitzgerald }
3962e2bcbf99SRichard Fitzgerald
3963e2bcbf99SRichard Fitzgerald ret = regmap_read(cs48l32->regmap, CS48L32_DEVID, &hwid);
3964e2bcbf99SRichard Fitzgerald if (ret) {
3965e2bcbf99SRichard Fitzgerald dev_err(dev, "Failed to read ID register: %d\n", ret);
3966e2bcbf99SRichard Fitzgerald goto err_reset;
3967e2bcbf99SRichard Fitzgerald }
3968e2bcbf99SRichard Fitzgerald hwid &= CS48L32_DEVID_MASK;
3969e2bcbf99SRichard Fitzgerald
3970e2bcbf99SRichard Fitzgerald switch (hwid) {
3971e2bcbf99SRichard Fitzgerald case CS48L32_SILICON_ID:
3972e2bcbf99SRichard Fitzgerald break;
3973e2bcbf99SRichard Fitzgerald default:
3974e2bcbf99SRichard Fitzgerald ret = -ENODEV;
3975e2bcbf99SRichard Fitzgerald dev_err_probe(cs48l32->dev, ret, "Unknown device ID: %#x\n", hwid);
3976e2bcbf99SRichard Fitzgerald goto err_reset;
3977e2bcbf99SRichard Fitzgerald }
3978e2bcbf99SRichard Fitzgerald
3979e2bcbf99SRichard Fitzgerald ret = regmap_read(cs48l32->regmap, CS48L32_REVID, &rev);
3980e2bcbf99SRichard Fitzgerald if (ret) {
3981e2bcbf99SRichard Fitzgerald dev_err(dev, "Failed to read revision register: %d\n", ret);
3982e2bcbf99SRichard Fitzgerald goto err_reset;
3983e2bcbf99SRichard Fitzgerald }
3984e2bcbf99SRichard Fitzgerald rev &= CS48L32_AREVID_MASK | CS48L32_MTLREVID_MASK;
3985e2bcbf99SRichard Fitzgerald
3986e2bcbf99SRichard Fitzgerald ret = regmap_read(cs48l32->regmap, CS48L32_OTPID, &otp_rev);
3987e2bcbf99SRichard Fitzgerald if (ret) {
3988e2bcbf99SRichard Fitzgerald dev_err(dev, "Failed to read OTP revision register: %d\n", ret);
3989e2bcbf99SRichard Fitzgerald goto err_reset;
3990e2bcbf99SRichard Fitzgerald }
3991e2bcbf99SRichard Fitzgerald otp_rev &= CS48L32_OTPID_MASK;
3992e2bcbf99SRichard Fitzgerald
3993e2bcbf99SRichard Fitzgerald dev_info(dev, "CS48L%x revision %X%u OTP%u\n", hwid & 0xff,
3994e2bcbf99SRichard Fitzgerald rev >> CS48L32_AREVID_SHIFT, rev & CS48L32_MTLREVID_MASK, otp_rev);
3995e2bcbf99SRichard Fitzgerald
3996e2bcbf99SRichard Fitzgerald /* Apply hardware patch */
3997e2bcbf99SRichard Fitzgerald ret = cs48l32_apply_patch(cs48l32);
3998e2bcbf99SRichard Fitzgerald if (ret) {
3999e2bcbf99SRichard Fitzgerald dev_err(cs48l32->dev, "Failed to apply patch %d\n", ret);
4000e2bcbf99SRichard Fitzgerald goto err_reset;
4001e2bcbf99SRichard Fitzgerald }
4002e2bcbf99SRichard Fitzgerald
4003e2bcbf99SRichard Fitzgerald /* BOOT_DONE interrupt is unmasked by default, so mask it */
4004e2bcbf99SRichard Fitzgerald ret = regmap_set_bits(cs48l32->regmap, CS48L32_IRQ1_MASK_2, CS48L32_BOOT_DONE_EINT1_MASK);
4005e2bcbf99SRichard Fitzgerald
4006e2bcbf99SRichard Fitzgerald ret = cs48l32_configure_clk32k(cs48l32);
4007e2bcbf99SRichard Fitzgerald if (ret)
4008e2bcbf99SRichard Fitzgerald goto err_reset;
4009e2bcbf99SRichard Fitzgerald
4010e2bcbf99SRichard Fitzgerald pm_runtime_set_active(cs48l32->dev);
4011e2bcbf99SRichard Fitzgerald pm_runtime_set_autosuspend_delay(cs48l32->dev, 100);
4012e2bcbf99SRichard Fitzgerald pm_runtime_use_autosuspend(cs48l32->dev);
4013e2bcbf99SRichard Fitzgerald pm_runtime_enable(cs48l32->dev);
4014e2bcbf99SRichard Fitzgerald
4015e2bcbf99SRichard Fitzgerald ret = cs48l32_create_codec_component(cs48l32_codec);
4016e2bcbf99SRichard Fitzgerald if (ret)
4017e2bcbf99SRichard Fitzgerald goto err_clk32k;
4018e2bcbf99SRichard Fitzgerald
4019e2bcbf99SRichard Fitzgerald return 0;
4020e2bcbf99SRichard Fitzgerald
4021e2bcbf99SRichard Fitzgerald err_clk32k:
4022e2bcbf99SRichard Fitzgerald clk_disable_unprepare(cs48l32->mclk1);
4023e2bcbf99SRichard Fitzgerald err_reset:
4024e2bcbf99SRichard Fitzgerald cs48l32_enable_hard_reset(cs48l32);
4025e2bcbf99SRichard Fitzgerald regulator_disable(cs48l32->vdd_d);
4026e2bcbf99SRichard Fitzgerald err_enable:
4027e2bcbf99SRichard Fitzgerald regulator_bulk_disable(ARRAY_SIZE(cs48l32->core_supplies), cs48l32->core_supplies);
4028e2bcbf99SRichard Fitzgerald
4029e2bcbf99SRichard Fitzgerald return ret;
4030e2bcbf99SRichard Fitzgerald }
4031e2bcbf99SRichard Fitzgerald
cs48l32_spi_remove(struct spi_device * spi)4032e2bcbf99SRichard Fitzgerald static void cs48l32_spi_remove(struct spi_device *spi)
4033e2bcbf99SRichard Fitzgerald {
4034e2bcbf99SRichard Fitzgerald struct cs48l32_codec *cs48l32_codec = spi_get_drvdata(spi);
4035e2bcbf99SRichard Fitzgerald struct cs48l32 *cs48l32 = &cs48l32_codec->core;
4036e2bcbf99SRichard Fitzgerald
4037e2bcbf99SRichard Fitzgerald /* Remove IRQ handler before destroying anything else */
4038e2bcbf99SRichard Fitzgerald if (cs48l32->irq >= 1)
4039e2bcbf99SRichard Fitzgerald free_irq(cs48l32->irq, cs48l32_codec);
4040e2bcbf99SRichard Fitzgerald
4041e2bcbf99SRichard Fitzgerald pm_runtime_disable(cs48l32->dev);
4042e2bcbf99SRichard Fitzgerald regulator_disable(cs48l32->vdd_d);
4043e2bcbf99SRichard Fitzgerald clk_disable_unprepare(cs48l32->mclk1);
4044e2bcbf99SRichard Fitzgerald cs48l32_enable_hard_reset(cs48l32);
4045e2bcbf99SRichard Fitzgerald regulator_bulk_disable(ARRAY_SIZE(cs48l32->core_supplies), cs48l32->core_supplies);
4046e2bcbf99SRichard Fitzgerald
4047e2bcbf99SRichard Fitzgerald mutex_destroy(&cs48l32_codec->rate_lock);
4048e2bcbf99SRichard Fitzgerald }
4049e2bcbf99SRichard Fitzgerald
4050e2bcbf99SRichard Fitzgerald static const struct of_device_id cs48l32_of_match[] = {
4051e2bcbf99SRichard Fitzgerald { .compatible = "cirrus,cs48l32", },
4052e2bcbf99SRichard Fitzgerald {},
4053e2bcbf99SRichard Fitzgerald };
4054e2bcbf99SRichard Fitzgerald
4055e2bcbf99SRichard Fitzgerald static const struct spi_device_id cs48l32_spi_ids[] = {
4056e2bcbf99SRichard Fitzgerald { "cs48l32", },
4057e2bcbf99SRichard Fitzgerald { },
4058e2bcbf99SRichard Fitzgerald };
4059e2bcbf99SRichard Fitzgerald MODULE_DEVICE_TABLE(spi, cs48l32_spi_ids);
4060e2bcbf99SRichard Fitzgerald
4061e2bcbf99SRichard Fitzgerald static struct spi_driver cs48l32_spi_driver = {
4062e2bcbf99SRichard Fitzgerald .driver = {
4063e2bcbf99SRichard Fitzgerald .name = "cs48l32",
40646070ef6eSNathan Chancellor .pm = pm_ptr(&cs48l32_pm_ops),
4065e2bcbf99SRichard Fitzgerald .of_match_table = cs48l32_of_match,
4066e2bcbf99SRichard Fitzgerald },
4067e2bcbf99SRichard Fitzgerald .probe = &cs48l32_spi_probe,
4068e2bcbf99SRichard Fitzgerald .remove = &cs48l32_spi_remove,
4069e2bcbf99SRichard Fitzgerald .id_table = cs48l32_spi_ids,
4070e2bcbf99SRichard Fitzgerald };
4071e2bcbf99SRichard Fitzgerald module_spi_driver(cs48l32_spi_driver);
4072e2bcbf99SRichard Fitzgerald
4073e2bcbf99SRichard Fitzgerald MODULE_DESCRIPTION("CS48L32 ASoC codec driver");
4074e2bcbf99SRichard Fitzgerald MODULE_AUTHOR("Stuart Henderson <stuarth@opensource.cirrus.com>");
4075e2bcbf99SRichard Fitzgerald MODULE_AUTHOR("Piotr Stankiewicz <piotrs@opensource.cirrus.com>");
4076e2bcbf99SRichard Fitzgerald MODULE_AUTHOR("Richard Fitzgerald <rf@opensource.cirrus.com>");
4077e2bcbf99SRichard Fitzgerald MODULE_LICENSE("GPL");
4078