xref: /linux/sound/soc/codecs/cs48l32.c (revision 299f489f5bad3554531f67335d1762225448ff39)
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, &reg);
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 				  &current_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