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