• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1commit 05a74fdf81fd02bb178e41d96582c99eaaaf0031
2Author: zhaoxc0502 <zhaoxc0502@thundersoft.com>
3Date:   Thu Jun 16 17:14:54 2022 +0800
4
5    linux_sound
6
7    Change-Id: Ic34341fbcce5e6d02fefc2acad4ea1058da94b66
8
9diff --git a/sound/core/pcm_dmaengine.c b/sound/core/pcm_dmaengine.c
10index 4d0e8fe53..1fc2fa077 100644
11--- a/sound/core/pcm_dmaengine.c
12+++ b/sound/core/pcm_dmaengine.c
13@@ -125,6 +125,8 @@ void snd_dmaengine_pcm_set_config_from_dai_data(
14 	}
15
16 	slave_config->slave_id = dma_data->slave_id;
17+	slave_config->peripheral_config = dma_data->peripheral_config;
18+	slave_config->peripheral_size = dma_data->peripheral_size;
19 }
20 EXPORT_SYMBOL_GPL(snd_dmaengine_pcm_set_config_from_dai_data);
21
22diff --git a/sound/soc/codecs/hdmi-codec.c b/sound/soc/codecs/hdmi-codec.c
23index 403d4c6a4..709de03d9 100644
24--- a/sound/soc/codecs/hdmi-codec.c
25+++ b/sound/soc/codecs/hdmi-codec.c
26@@ -278,10 +278,12 @@ struct hdmi_codec_priv {
27 	bool busy;
28 	struct snd_soc_jack *jack;
29 	unsigned int jack_status;
30+	struct snd_aes_iec958 iec;
31 };
32
33 static const struct snd_soc_dapm_widget hdmi_widgets[] = {
34 	SND_SOC_DAPM_OUTPUT("TX"),
35+	SND_SOC_DAPM_OUTPUT("RX"),
36 };
37
38 enum {
39@@ -385,10 +387,56 @@ static int hdmi_codec_chmap_ctl_get(struct snd_kcontrol *kcontrol,
40 	return 0;
41 }
42
43+/*
44+ * ALSA iec958 controls
45+ */
46+static int hdmi_codec_iec958_info(struct snd_kcontrol *kcontrol,
47+				  struct snd_ctl_elem_info *uinfo)
48+{
49+	uinfo->type = SNDRV_CTL_ELEM_TYPE_IEC958;
50+	uinfo->count = 1;
51+	return 0;
52+}
53+
54+static int hdmi_codec_iec958_get(struct snd_kcontrol *kcontrol,
55+				 struct snd_ctl_elem_value *ucontrol)
56+{
57+	struct snd_soc_component *comp = snd_kcontrol_chip(kcontrol);
58+	struct hdmi_codec_priv *hcp = snd_soc_component_get_drvdata(comp);
59+	int i;
60+
61+	for (i = 0; i < 24; i++)
62+		ucontrol->value.iec958.status[i] = hcp->iec.status[i];
63+
64+	return 0;
65+}
66+
67+static int hdmi_codec_iec958_put(struct snd_kcontrol *kcontrol,
68+				 struct snd_ctl_elem_value *ucontrol)
69+{
70+	struct snd_soc_component *comp = snd_kcontrol_chip(kcontrol);
71+	struct hdmi_codec_priv *hcp = snd_soc_component_get_drvdata(comp);
72+	int i;
73+
74+	for (i = 0; i < 24; i++)
75+		hcp->iec.status[i] = ucontrol->value.iec958.status[i];
76+
77+	return 0;
78+}
79+
80+static const struct snd_kcontrol_new hdmi_codec_controls = {
81+	.iface = SNDRV_CTL_ELEM_IFACE_PCM,
82+	.name = SNDRV_CTL_NAME_IEC958("", PLAYBACK, DEFAULT),
83+	.info = hdmi_codec_iec958_info,
84+	.get = hdmi_codec_iec958_get,
85+	.put = hdmi_codec_iec958_put,
86+};
87+
88 static int hdmi_codec_startup(struct snd_pcm_substream *substream,
89 			      struct snd_soc_dai *dai)
90 {
91 	struct hdmi_codec_priv *hcp = snd_soc_dai_get_drvdata(dai);
92+	bool tx = substream->stream == SNDRV_PCM_STREAM_PLAYBACK;
93 	int ret = 0;
94
95 	mutex_lock(&hcp->lock);
96@@ -404,7 +452,7 @@ static int hdmi_codec_startup(struct snd_pcm_substream *substream,
97 			goto err;
98 	}
99
100-	if (hcp->hcd.ops->get_eld) {
101+	if (tx && hcp->hcd.ops->get_eld) {
102 		ret = hcp->hcd.ops->get_eld(dai->dev->parent, hcp->hcd.data,
103 					    hcp->eld, sizeof(hcp->eld));
104 		if (ret)
105@@ -466,6 +514,15 @@ static int hdmi_codec_hw_params(struct snd_pcm_substream *substream,
106 		return ret;
107 	}
108
109+	if (hcp->iec.status[0] || hcp->iec.status[1] || hcp->iec.status[2] ||
110+	    hcp->iec.status[3] || hcp->iec.status[4]) {
111+		hp.iec.status[0] = hcp->iec.status[0];
112+		hp.iec.status[1] = hcp->iec.status[1];
113+		hp.iec.status[2] = hcp->iec.status[2];
114+		hp.iec.status[3] = hcp->iec.status[3];
115+		hp.iec.status[4] = hcp->iec.status[4];
116+	}
117+
118 	hdmi_audio_infoframe_init(&hp.cea);
119 	hp.cea.channels = params_channels(params);
120 	hp.cea.coding_type = HDMI_AUDIO_CODING_TYPE_STREAM;
121@@ -475,13 +532,11 @@ static int hdmi_codec_hw_params(struct snd_pcm_substream *substream,
122 	/* Select a channel allocation that matches with ELD and pcm channels */
123 	idx = hdmi_codec_get_ch_alloc_table_idx(hcp, hp.cea.channels);
124 	if (idx < 0) {
125-		dev_err(dai->dev, "Not able to map channels to speakers (%d)\n",
126-			idx);
127 		hcp->chmap_idx = HDMI_CODEC_CHMAP_IDX_UNKNOWN;
128-		return idx;
129+	} else {
130+		hp.cea.channel_allocation = hdmi_codec_channel_alloc[idx].ca_id;
131+		hcp->chmap_idx = hdmi_codec_channel_alloc[idx].ca_id;
132 	}
133-	hp.cea.channel_allocation = hdmi_codec_channel_alloc[idx].ca_id;
134-	hcp->chmap_idx = hdmi_codec_channel_alloc[idx].ca_id;
135
136 	hp.sample_width = params_width(params);
137 	hp.sample_rate = params_rate(params);
138@@ -648,6 +703,14 @@ static int hdmi_codec_pcm_new(struct snd_soc_pcm_runtime *rtd,
139 	hcp->chmap_info->chmap = hdmi_codec_stereo_chmaps;
140 	hcp->chmap_idx = HDMI_CODEC_CHMAP_IDX_UNKNOWN;
141
142+	kctl = snd_ctl_new1(&hdmi_codec_controls, dai->component);
143+	if (!kctl)
144+		return -ENOMEM;
145+
146+	ret = snd_ctl_add(rtd->card->snd_card, kctl);
147+	if (ret < 0)
148+		return ret;
149+
150 	/* add ELD ctl with the device number corresponding to the PCM stream */
151 	kctl = snd_ctl_new1(&hdmi_eld_ctl, dai->component);
152 	if (!kctl)
153@@ -660,14 +723,20 @@ static int hdmi_dai_probe(struct snd_soc_dai *dai)
154 {
155 	struct snd_soc_dapm_context *dapm;
156 	struct hdmi_codec_daifmt *daifmt;
157-	struct snd_soc_dapm_route route = {
158-		.sink = "TX",
159-		.source = dai->driver->playback.stream_name,
160+	struct snd_soc_dapm_route route[] = {
161+		{
162+			.sink = "TX",
163+			.source = dai->driver->playback.stream_name,
164+		},
165+		{
166+			.sink = dai->driver->playback.stream_name,
167+			.source = "RX",
168+		},
169 	};
170 	int ret;
171
172 	dapm = snd_soc_component_get_dapm(dai->component);
173-	ret = snd_soc_dapm_add_routes(dapm, &route, 1);
174+	ret = snd_soc_dapm_add_routes(dapm, route, 2);
175 	if (ret)
176 		return ret;
177
178@@ -752,6 +821,14 @@ static const struct snd_soc_dai_driver hdmi_i2s_dai = {
179 		.sig_bits = 24,
180 	},
181 	.ops = &hdmi_codec_i2s_dai_ops,
182+	.capture = {
183+		.stream_name = "Capture",
184+		.channels_min = 2,
185+		.channels_max = 8,
186+		.rates = HDMI_RATES,
187+		.formats = I2S_FORMATS,
188+		.sig_bits = 24,
189+	},
190 	.pcm_new = hdmi_codec_pcm_new,
191 };
192
193@@ -768,6 +845,13 @@ static const struct snd_soc_dai_driver hdmi_spdif_dai = {
194 		.formats = SPDIF_FORMATS,
195 	},
196 	.ops = &hdmi_codec_spdif_dai_ops,
197+	.capture = {
198+		.stream_name = "Capture",
199+		.channels_min = 2,
200+		.channels_max = 2,
201+		.rates = HDMI_RATES,
202+		.formats = SPDIF_FORMATS,
203+	},
204 	.pcm_new = hdmi_codec_pcm_new,
205 };
206
207diff --git a/sound/soc/codecs/wm8904.c b/sound/soc/codecs/wm8904.c
208index 1c360bae5..78b0c1377 100644
209--- a/sound/soc/codecs/wm8904.c
210+++ b/sound/soc/codecs/wm8904.c
211@@ -9,6 +9,7 @@
212
213 #include <linux/clk.h>
214 #include <linux/module.h>
215+#include <linux/moduleparam.h>
216 #include <linux/init.h>
217 #include <linux/delay.h>
218 #include <linux/pm.h>
219@@ -545,6 +546,18 @@ static const DECLARE_TLV_DB_SCALE(out_tlv, -5700, 100, 0);
220 static const DECLARE_TLV_DB_SCALE(sidetone_tlv, -3600, 300, 0);
221 static const DECLARE_TLV_DB_SCALE(eq_tlv, -1200, 100, 0);
222
223+static const char *input_mode_text[] = {
224+	"Single-Ended", "Differential Line", "Differential Mic"
225+};
226+
227+static SOC_ENUM_SINGLE_DECL(lin_mode,
228+			    WM8904_ANALOGUE_LEFT_INPUT_1, 0,
229+			    input_mode_text);
230+
231+static SOC_ENUM_SINGLE_DECL(rin_mode,
232+			    WM8904_ANALOGUE_RIGHT_INPUT_1, 0,
233+			    input_mode_text);
234+
235 static const char *hpf_mode_text[] = {
236 	"Hi-fi", "Voice 1", "Voice 2", "Voice 3"
237 };
238@@ -579,6 +592,9 @@ static const struct snd_kcontrol_new wm8904_adc_snd_controls[] = {
239 SOC_DOUBLE_R_TLV("Digital Capture Volume", WM8904_ADC_DIGITAL_VOLUME_LEFT,
240 		 WM8904_ADC_DIGITAL_VOLUME_RIGHT, 1, 119, 0, digital_tlv),
241
242+SOC_ENUM("Left Capture Mode", lin_mode),
243+SOC_ENUM("Right Capture Mode", rin_mode),
244+
245 /* No TLV since it depends on mode */
246 SOC_DOUBLE_R("Capture Volume", WM8904_ANALOGUE_LEFT_INPUT_0,
247 	     WM8904_ANALOGUE_RIGHT_INPUT_0, 0, 31, 0),
248@@ -837,10 +853,6 @@ static int out_pga_event(struct snd_soc_dapm_widget *w,
249 	return 0;
250 }
251
252-static const char *input_mode_text[] = {
253-	"Single-Ended", "Differential Line", "Differential Mic"
254-};
255-
256 static const char *lin_text[] = {
257 	"IN1L", "IN2L", "IN3L"
258 };
259@@ -857,13 +869,6 @@ static SOC_ENUM_SINGLE_DECL(lin_inv_enum, WM8904_ANALOGUE_LEFT_INPUT_1, 4,
260 static const struct snd_kcontrol_new lin_inv_mux =
261 	SOC_DAPM_ENUM("Left Capture Inverting Mux", lin_inv_enum);
262
263-static SOC_ENUM_SINGLE_DECL(lin_mode_enum,
264-			    WM8904_ANALOGUE_LEFT_INPUT_1, 0,
265-			    input_mode_text);
266-
267-static const struct snd_kcontrol_new lin_mode =
268-	SOC_DAPM_ENUM("Left Capture Mode", lin_mode_enum);
269-
270 static const char *rin_text[] = {
271 	"IN1R", "IN2R", "IN3R"
272 };
273@@ -884,9 +889,6 @@ static SOC_ENUM_SINGLE_DECL(rin_mode_enum,
274 			    WM8904_ANALOGUE_RIGHT_INPUT_1, 0,
275 			    input_mode_text);
276
277-static const struct snd_kcontrol_new rin_mode =
278-	SOC_DAPM_ENUM("Right Capture Mode", rin_mode_enum);
279-
280 static const char *aif_text[] = {
281 	"Left", "Right"
282 };
283@@ -935,11 +937,9 @@ SND_SOC_DAPM_SUPPLY("MICBIAS", WM8904_MIC_BIAS_CONTROL_0, 0, 0, NULL, 0),
284 SND_SOC_DAPM_MUX("Left Capture Mux", SND_SOC_NOPM, 0, 0, &lin_mux),
285 SND_SOC_DAPM_MUX("Left Capture Inverting Mux", SND_SOC_NOPM, 0, 0,
286 		 &lin_inv_mux),
287-SND_SOC_DAPM_MUX("Left Capture Mode", SND_SOC_NOPM, 0, 0, &lin_mode),
288 SND_SOC_DAPM_MUX("Right Capture Mux", SND_SOC_NOPM, 0, 0, &rin_mux),
289 SND_SOC_DAPM_MUX("Right Capture Inverting Mux", SND_SOC_NOPM, 0, 0,
290 		 &rin_inv_mux),
291-SND_SOC_DAPM_MUX("Right Capture Mode", SND_SOC_NOPM, 0, 0, &rin_mode),
292
293 SND_SOC_DAPM_PGA("Left Capture PGA", WM8904_POWER_MANAGEMENT_0, 1, 0,
294 		 NULL, 0),
295@@ -1062,12 +1062,6 @@ static const struct snd_soc_dapm_route adc_intercon[] = {
296 	{ "Left Capture Inverting Mux", "IN2L", "IN2L" },
297 	{ "Left Capture Inverting Mux", "IN3L", "IN3L" },
298
299-	{ "Left Capture Mode", "Single-Ended", "Left Capture Inverting Mux" },
300-	{ "Left Capture Mode", "Differential Line", "Left Capture Mux" },
301-	{ "Left Capture Mode", "Differential Line", "Left Capture Inverting Mux" },
302-	{ "Left Capture Mode", "Differential Mic", "Left Capture Mux" },
303-	{ "Left Capture Mode", "Differential Mic", "Left Capture Inverting Mux" },
304-
305 	{ "Right Capture Mux", "IN1R", "IN1R" },
306 	{ "Right Capture Mux", "IN2R", "IN2R" },
307 	{ "Right Capture Mux", "IN3R", "IN3R" },
308@@ -1076,14 +1070,11 @@ static const struct snd_soc_dapm_route adc_intercon[] = {
309 	{ "Right Capture Inverting Mux", "IN2R", "IN2R" },
310 	{ "Right Capture Inverting Mux", "IN3R", "IN3R" },
311
312-	{ "Right Capture Mode", "Single-Ended", "Right Capture Inverting Mux" },
313-	{ "Right Capture Mode", "Differential Line", "Right Capture Mux" },
314-	{ "Right Capture Mode", "Differential Line", "Right Capture Inverting Mux" },
315-	{ "Right Capture Mode", "Differential Mic", "Right Capture Mux" },
316-	{ "Right Capture Mode", "Differential Mic", "Right Capture Inverting Mux" },
317+	{ "Left Capture PGA", NULL, "Left Capture Mux" },
318+	{ "Left Capture PGA", NULL, "Left Capture Inverting Mux" },
319
320-	{ "Left Capture PGA", NULL, "Left Capture Mode" },
321-	{ "Right Capture PGA", NULL, "Right Capture Mode" },
322+	{ "Right Capture PGA", NULL, "Right Capture Mux" },
323+	{ "Right Capture PGA", NULL, "Right Capture Inverting Mux" },
324
325 	{ "AIFOUTL Mux", "Left", "ADCL" },
326 	{ "AIFOUTL Mux", "Right", "ADCR" },
327@@ -1869,7 +1860,13 @@ static int wm8904_set_bias_level(struct snd_soc_component *component,
328
329 	switch (level) {
330 	case SND_SOC_BIAS_ON:
331-		break;
332+		ret = clk_prepare_enable(wm8904->mclk);
333+        snd_soc_component_update_bits(component, WM8904_ANALOGUE_LEFT_INPUT_1, WM8904_L_MODE_MASK, 0x01);
334+        snd_soc_component_update_bits(component, WM8904_ANALOGUE_RIGHT_INPUT_1, WM8904_R_MODE_MASK, 0x01);
335+        snd_soc_component_update_bits(component, WM8904_MIC_BIAS_CONTROL_0, WM8904_MIC_DET_EINT, 0x01);
336+		if (ret)
337+			return ret;
338+        break;
339
340 	case SND_SOC_BIAS_PREPARE:
341 		/* VMID resistance 2*50k */
342@@ -1893,15 +1890,6 @@ static int wm8904_set_bias_level(struct snd_soc_component *component,
343 				return ret;
344 			}
345
346-			ret = clk_prepare_enable(wm8904->mclk);
347-			if (ret) {
348-				dev_err(component->dev,
349-					"Failed to enable MCLK: %d\n", ret);
350-				regulator_bulk_disable(ARRAY_SIZE(wm8904->supplies),
351-						       wm8904->supplies);
352-				return ret;
353-			}
354-
355 			regcache_cache_only(wm8904->regmap, false);
356 			regcache_sync(wm8904->regmap);
357
358@@ -2148,16 +2136,18 @@ static const struct regmap_config wm8904_regmap = {
359 };
360
361 #ifdef CONFIG_OF
362+static enum wm8904_type wm8904_data = WM8904;
363+static enum wm8904_type wm8912_data = WM8912;
364 static const struct of_device_id wm8904_of_match[] = {
365-	{
366-		.compatible = "wlf,wm8904",
367-		.data = (void *)WM8904,
368-	}, {
369-		.compatible = "wlf,wm8912",
370-		.data = (void *)WM8912,
371-	}, {
372-		/* sentinel */
373-	}
374+    // {
375+    //    .compatible = "wlf,wm8904",
376+    //    .data = &wm8904_data,
377+    // }, {
378+    //    .compatible = "wlf,wm8912",
379+    //    .data = &wm8912_data,
380+    // }, {
381+    //    /* sentinel */
382+    // }
383 };
384 MODULE_DEVICE_TABLE(of, wm8904_of_match);
385 #endif
386@@ -2195,8 +2185,8 @@ static int wm8904_i2c_probe(struct i2c_client *i2c,
387 		match = of_match_node(wm8904_of_match, i2c->dev.of_node);
388 		if (match == NULL)
389 			return -EINVAL;
390-		wm8904->devtype = (enum wm8904_type)match->data;
391-	} else {
392+		wm8904->devtype = *((enum wm8904_type *)match->data);
393+    } else {
394 		wm8904->devtype = id->driver_data;
395 	}
396
397@@ -2332,7 +2322,7 @@ static struct i2c_driver wm8904_i2c_driver = {
398 	.id_table = wm8904_i2c_id,
399 };
400
401-module_i2c_driver(wm8904_i2c_driver);
402+// module_i2c_driver(wm8904_i2c_driver);
403
404 MODULE_DESCRIPTION("ASoC WM8904 driver");
405 MODULE_AUTHOR("Mark Brown <broonie@opensource.wolfsonmicro.com>");
406diff --git a/sound/soc/fsl/Kconfig b/sound/soc/fsl/Kconfig
407index 3f76ff71e..019fb795a 100644
408--- a/sound/soc/fsl/Kconfig
409+++ b/sound/soc/fsl/Kconfig
410@@ -95,6 +95,30 @@ config SND_SOC_FSL_EASRC
411 	  destination sample rate. It is a new design module compare with the
412 	  old ASRC.
413
414+
415+config SND_SOC_FSL_DSP
416+	tristate "dsp module support"
417+	select SND_SOC_COMPRESS
418+	select SND_SOC_FSL_DSP_AUDIOMIX
419+	help
420+	  Say Y if you want to add hifi 4 support for the Freescale CPUs.
421+	  which is a DSP core for audio processing.
422+	  This option is only useful for out-of-tree drivers since
423+	  in-tree drivers select it automatically.
424+
425+config SND_SOC_FSL_DSP_AUDIOMIX
426+	tristate "Audio MIX DSP helper"
427+	depends on MFD_IMX_MIX
428+	help
429+	  Say Y if you want to add Audio MIX helper for DSP
430+
431+config SND_SOC_FSL_AUD2HTX
432+	tristate "AUDIO TO HDMI TX module support"
433+	select REGMAP_MMIO
434+	select SND_SOC_GENERIC_DMAENGINE_PCM
435+	help
436+	  Say Y if you want to add AUDIO TO HDMI TX support for NXP.
437+
438 config SND_SOC_FSL_UTILS
439 	tristate
440
441@@ -102,6 +126,15 @@ config SND_SOC_IMX_PCM_DMA
442 	tristate
443 	select SND_SOC_GENERIC_DMAENGINE_PCM
444
445+config SND_SOC_IMX_AUDIO_RPMSG
446+	tristate
447+	depends on RPMSG
448+
449+config SND_SOC_IMX_PCM_RPMSG
450+	tristate
451+	depends on SND_SOC_IMX_AUDIO_RPMSG
452+	select SND_SOC_GENERIC_DMAENGINE_PCM
453+
454 config SND_SOC_IMX_AUDMUX
455 	tristate "Digital Audio Mux module support"
456 	help
457@@ -119,7 +152,7 @@ config SND_POWERPC_SOC
458
459 config SND_IMX_SOC
460 	tristate "SoC Audio for Freescale i.MX CPUs"
461-	depends on ARCH_MXC || COMPILE_TEST
462+	depends on ARCH_MXC || ARCH_MXC_ARM64 || COMPILE_TEST
463 	help
464 	  Say Y or M if you want to add support for codecs attached to
465 	  the i.MX CPUs.
466@@ -218,6 +251,19 @@ config SND_SOC_IMX_PCM_FIQ
467
468 if SND_IMX_SOC
469
470+config SND_SOC_IMX_WM8904
471+    tristate "SoC Audio support for i.MX boards with wm8904"
472+    depends on OF && I2C
473+    select SND_SOC_WM8904
474+    select SND_SOC_IMX_PCM_DMA
475+    select SND_SOC_FSL_SAI
476+    select SND_SOC_FSL_UTILS
477+    select SND_KCTL_JACK
478+    help
479+      SoC Audio support for i.MX boards with WM8904
480+      Say Y if you want to add support for SoC audio on an i.MX board with
481+      a wm8904 codec.
482+
483 config SND_SOC_IMX_SSI
484 	tristate
485 	select SND_SOC_FSL_UTILS
486@@ -270,6 +316,16 @@ config SND_SOC_EUKREA_TLV320
487 	  Enable I2S based access to the TLV320AIC23B codec attached
488 	  to the SSI interface
489
490+config SND_SOC_IMX_MICFIL
491+	tristate "SoC Audio support for i.MX boards with micfil"
492+	depends on OF && I2C
493+	select SND_SOC_IMX_PCM_DMA
494+	select SND_SOC_FSL_MICFIL
495+	help
496+	  Soc Audio support for i.MX boards with micfil
497+	  Say Y if you want to add support for SoC audio on
498+	  an i.MX board with micfil.
499+
500 config SND_SOC_IMX_ES8328
501 	tristate "SoC Audio support for i.MX boards with the ES8328 codec"
502 	depends on OF && (I2C || SPI)
503@@ -336,6 +392,48 @@ config SND_SOC_IMX_AUDMIX
504 	  Say Y if you want to add support for SoC audio on an i.MX board with
505 	  an Audio Mixer.
506
507+config SND_SOC_IMX_RPMSG
508+	tristate "SoC Audio support for i.MX boards with rpmsg"
509+	depends on RPMSG
510+	select SND_SOC_IMX_PCM_RPMSG
511+	select SND_SOC_IMX_AUDIO_RPMSG
512+	help
513+	  SoC Audio support for i.MX boards with rpmsg.
514+	  There should be rpmsg devices defined in other core (M core)
515+	  Say Y if you want to add support for SoC audio on an i.MX board with
516+	  a rpmsg devices.
517+
518+config SND_SOC_IMX_PDM_MIC
519+	tristate "SoC Audio support for i.MX boards with PDM mic on SAI"
520+	depends on OF
521+	select SND_SOC_IMX_PDM_DMA
522+	select SND_SOC_FSL_SAI
523+	help
524+	  SoC Audio support for i.MX boards with PDM microphones on SAI
525+	  Say Y if you want to add support for SoC Audio support for i.MX boards
526+	  with PDM microphones on SAI.
527+
528+config SND_SOC_IMX_DSP
529+	tristate "SoC Audio support for i.MX boards with DSP port"
530+	select SND_SOC_FSL_DSP
531+	select SND_SOC_COMPRESS
532+	help
533+	  SoC Audio support for i.MX boards with DSP audio
534+	  Say Y if you want to add support for SoC audio on an i.MX board with
535+	  IMX DSP.
536+
537+config SND_SOC_IMX_CDNHDMI
538+	tristate "SoC Audio support for i.MX boards with CDN HDMI port"
539+	depends on DRM_IMX_CDNS_MHDP
540+	select SND_SOC_IMX_PCM_DMA
541+	select SND_SOC_FSL_SAI
542+	select SND_SOC_HDMI_CODEC
543+	select SND_SOC_FSL_AUD2HTX
544+	help
545+	  SoC Audio support for i.MX boards with CDN HDMI audio
546+	  Say Y if you want to add support for SoC audio on an i.MX board with
547+	  IMX CDN HDMI.
548+
549 endif # SND_IMX_SOC
550
551 endmenu
552diff --git a/sound/soc/fsl/Makefile b/sound/soc/fsl/Makefile
553index b835eebf8..cc3b657dc 100644
554--- a/sound/soc/fsl/Makefile
555+++ b/sound/soc/fsl/Makefile
556@@ -14,21 +14,28 @@ obj-$(CONFIG_SND_SOC_P1022_RDK) += snd-soc-p1022-rdk.o
557 # Freescale SSI/DMA/SAI/SPDIF Support
558 snd-soc-fsl-audmix-objs := fsl_audmix.o
559 snd-soc-fsl-asoc-card-objs := fsl-asoc-card.o
560+snd-soc-fsl-dsp-audiomix-objs := fsl_dsp_audiomix.o
561 snd-soc-fsl-asrc-objs := fsl_asrc.o fsl_asrc_dma.o
562-snd-soc-fsl-sai-objs := fsl_sai.o
563+snd-soc-fsl-dsp-objs := fsl_dsp.o fsl_dsp_proxy.o fsl_dsp_pool.o \
564+	fsl_dsp_library_load.o fsl_dsp_xaf_api.o fsl_dsp_cpu.o \
565+	fsl_dsp_platform_compress.o
566+snd-soc-fsl-sai-objs := fsl_sai.o fsl_sai_sysfs.o
567 snd-soc-fsl-ssi-y := fsl_ssi.o
568 snd-soc-fsl-ssi-$(CONFIG_DEBUG_FS) += fsl_ssi_dbg.o
569 snd-soc-fsl-spdif-objs := fsl_spdif.o
570-snd-soc-fsl-esai-objs := fsl_esai.o
571+snd-soc-fsl-esai-objs := fsl_esai.o fsl_esai_mix.o
572 snd-soc-fsl-micfil-objs := fsl_micfil.o
573 snd-soc-fsl-utils-objs := fsl_utils.o
574 snd-soc-fsl-dma-objs := fsl_dma.o
575 snd-soc-fsl-mqs-objs := fsl_mqs.o
576 snd-soc-fsl-easrc-objs := fsl_easrc.o
577+snd-soc-fsl-aud2htx-objs := fsl_aud2htx.o
578
579 obj-$(CONFIG_SND_SOC_FSL_AUDMIX) += snd-soc-fsl-audmix.o
580 obj-$(CONFIG_SND_SOC_FSL_ASOC_CARD) += snd-soc-fsl-asoc-card.o
581 obj-$(CONFIG_SND_SOC_FSL_ASRC) += snd-soc-fsl-asrc.o
582+obj-$(CONFIG_SND_SOC_FSL_DSP) += snd-soc-fsl-dsp.o
583+obj-$(CONFIG_SND_SOC_FSL_DSP_AUDIOMIX) += snd-soc-fsl-dsp-audiomix.o
584 obj-$(CONFIG_SND_SOC_FSL_SAI) += snd-soc-fsl-sai.o
585 obj-$(CONFIG_SND_SOC_FSL_SSI) += snd-soc-fsl-ssi.o
586 obj-$(CONFIG_SND_SOC_FSL_SPDIF) += snd-soc-fsl-spdif.o
587@@ -38,6 +45,7 @@ obj-$(CONFIG_SND_SOC_FSL_UTILS) += snd-soc-fsl-utils.o
588 obj-$(CONFIG_SND_SOC_FSL_MQS) += snd-soc-fsl-mqs.o
589 obj-$(CONFIG_SND_SOC_FSL_EASRC) += snd-soc-fsl-easrc.o
590 obj-$(CONFIG_SND_SOC_POWERPC_DMA) += snd-soc-fsl-dma.o
591+obj-$(CONFIG_SND_SOC_FSL_AUD2HTX) += snd-soc-fsl-aud2htx.o
592
593 # MPC5200 Platform Support
594 obj-$(CONFIG_SND_MPC52xx_DMA) += mpc5200_dma.o
595@@ -55,7 +63,9 @@ obj-$(CONFIG_SND_SOC_IMX_SSI) += snd-soc-imx-ssi.o
596 obj-$(CONFIG_SND_SOC_IMX_AUDMUX) += snd-soc-imx-audmux.o
597
598 obj-$(CONFIG_SND_SOC_IMX_PCM_FIQ) += imx-pcm-fiq.o
599-obj-$(CONFIG_SND_SOC_IMX_PCM_DMA) += imx-pcm-dma.o
600+obj-$(CONFIG_SND_SOC_IMX_PCM_DMA) += imx-pcm-dma.o imx-pcm-dma-v2.o
601+obj-$(CONFIG_SND_SOC_IMX_AUDIO_RPMSG) += imx-audio-rpmsg.o
602+obj-$(CONFIG_SND_SOC_IMX_PCM_RPMSG) += imx-pcm-rpmsg.o
603
604 # i.MX Machine Support
605 snd-soc-eukrea-tlv320-objs := eukrea-tlv320.o
606@@ -64,9 +74,15 @@ snd-soc-mx27vis-aic32x4-objs := mx27vis-aic32x4.o
607 snd-soc-wm1133-ev1-objs := wm1133-ev1.o
608 snd-soc-imx-es8328-objs := imx-es8328.o
609 snd-soc-imx-sgtl5000-objs := imx-sgtl5000.o
610+snd-soc-imx-wm8904-objs := imx-wm8904.o
611 snd-soc-imx-spdif-objs := imx-spdif.o
612 snd-soc-imx-mc13783-objs := imx-mc13783.o
613 snd-soc-imx-audmix-objs := imx-audmix.o
614+snd-soc-imx-rpmsg-objs := imx-rpmsg.o
615+snd-soc-imx-pdm-objs := imx-pdm.o
616+snd-soc-imx-micfil-objs := imx-micfil.o
617+snd-soc-imx-dsp-objs := imx-dsp.o
618+snd-soc-imx-cdnhdmi-objs := imx-cdnhdmi.o
619
620 obj-$(CONFIG_SND_SOC_EUKREA_TLV320) += snd-soc-eukrea-tlv320.o
621 obj-$(CONFIG_SND_SOC_PHYCORE_AC97) += snd-soc-phycore-ac97.o
622@@ -74,6 +90,12 @@ obj-$(CONFIG_SND_SOC_MX27VIS_AIC32X4) += snd-soc-mx27vis-aic32x4.o
623 obj-$(CONFIG_SND_MXC_SOC_WM1133_EV1) += snd-soc-wm1133-ev1.o
624 obj-$(CONFIG_SND_SOC_IMX_ES8328) += snd-soc-imx-es8328.o
625 obj-$(CONFIG_SND_SOC_IMX_SGTL5000) += snd-soc-imx-sgtl5000.o
626+obj-$(CONFIG_SND_SOC_IMX_WM8904) += snd-soc-imx-wm8904.o
627 obj-$(CONFIG_SND_SOC_IMX_SPDIF) += snd-soc-imx-spdif.o
628 obj-$(CONFIG_SND_SOC_IMX_MC13783) += snd-soc-imx-mc13783.o
629 obj-$(CONFIG_SND_SOC_IMX_AUDMIX) += snd-soc-imx-audmix.o
630+obj-$(CONFIG_SND_SOC_IMX_RPMSG) += snd-soc-imx-rpmsg.o
631+obj-$(CONFIG_SND_SOC_IMX_PDM_MIC) += snd-soc-imx-pdm.o
632+obj-$(CONFIG_SND_SOC_IMX_MICFIL) += snd-soc-imx-micfil.o
633+obj-$(CONFIG_SND_SOC_IMX_DSP) += snd-soc-imx-dsp.o
634+obj-$(CONFIG_SND_SOC_IMX_CDNHDMI) += snd-soc-imx-cdnhdmi.o
635diff --git a/sound/soc/fsl/fsl_asrc.c b/sound/soc/fsl/fsl_asrc.c
636index 02c81d2e3..39e381c2f 100644
637--- a/sound/soc/fsl/fsl_asrc.c
638+++ b/sound/soc/fsl/fsl_asrc.c
639@@ -13,6 +13,8 @@
640 #include <linux/of_platform.h>
641 #include <linux/platform_data/dma-imx.h>
642 #include <linux/pm_runtime.h>
643+#include <linux/miscdevice.h>
644+#include <linux/sched/signal.h>
645 #include <sound/dmaengine_pcm.h>
646 #include <sound/pcm_params.h>
647
648@@ -464,8 +466,11 @@ static int fsl_asrc_config_pair(struct fsl_asrc_pair *pair, bool use_ideal_rate)
649 	/* Default setting: Automatic selection for processing mode */
650 	regmap_update_bits(asrc->regmap, REG_ASRCTR,
651 			   ASRCTR_ATSi_MASK(index), ASRCTR_ATS(index));
652+
653+	/* Default setting: use internal measured ratio */
654 	regmap_update_bits(asrc->regmap, REG_ASRCTR,
655-			   ASRCTR_USRi_MASK(index), 0);
656+			   ASRCTR_USRi_MASK(index) | ASRCTR_IDRi_MASK(index),
657+			   ASRCTR_USR(index));
658
659 	/* Set the input and output clock sources */
660 	regmap_update_bits(asrc->regmap, REG_ASRCSR,
661@@ -531,7 +536,7 @@ static void fsl_asrc_start_pair(struct fsl_asrc_pair *pair)
662 {
663 	struct fsl_asrc *asrc = pair->asrc;
664 	enum asrc_pair_index index = pair->index;
665-	int reg, retry = 10, i;
666+	int reg, retry = 50, i;
667
668 	/* Enable the current pair */
669 	regmap_update_bits(asrc->regmap, REG_ASRCTR,
670@@ -544,6 +549,9 @@ static void fsl_asrc_start_pair(struct fsl_asrc_pair *pair)
671 		reg &= ASRCFG_INIRQi_MASK(index);
672 	} while (!reg && --retry);
673
674+	if (retry == 0)
675+		dev_warn(&asrc->pdev->dev, "initialization is not finished\n");
676+
677 	/* Make the input fifo to ASRC STALL level */
678 	regmap_read(asrc->regmap, REG_ASRCNCR, &reg);
679 	for (i = 0; i < pair->channels * 4; i++)
680@@ -712,6 +720,8 @@ static int fsl_asrc_dai_trigger(struct snd_pcm_substream *substream, int cmd,
681 	case SNDRV_PCM_TRIGGER_RESUME:
682 	case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
683 		fsl_asrc_start_pair(pair);
684+		/* Output enough data to content the DMA burstsize of BE */
685+		mdelay(1);
686 		break;
687 	case SNDRV_PCM_TRIGGER_STOP:
688 	case SNDRV_PCM_TRIGGER_SUSPEND:
689@@ -913,6 +923,8 @@ static const struct regmap_config fsl_asrc_regmap_config = {
690 	.cache_type = REGCACHE_FLAT,
691 };
692
693+#include "fsl_asrc_m2m.c"
694+
695 /**
696  * fsl_asrc_init - Initialize ASRC registers with a default configuration
697  * @asrc: ASRC context
698@@ -1039,7 +1051,7 @@ static int fsl_asrc_probe(struct platform_device *pdev)
699
700 	asrc->paddr = res->start;
701
702-	asrc->regmap = devm_regmap_init_mmio_clk(&pdev->dev, "mem", regs,
703+	asrc->regmap = devm_regmap_init_mmio_clk(&pdev->dev, NULL, regs,
704 						 &fsl_asrc_regmap_config);
705 	if (IS_ERR(asrc->regmap)) {
706 		dev_err(&pdev->dev, "failed to init regmap\n");
707@@ -1098,9 +1110,13 @@ static int fsl_asrc_probe(struct platform_device *pdev)
708 	if (of_device_is_compatible(np, "fsl,imx35-asrc")) {
709 		asrc_priv->clk_map[IN] = input_clk_map_imx35;
710 		asrc_priv->clk_map[OUT] = output_clk_map_imx35;
711+		strncpy(asrc_priv->name, "mxc_asrc",
712+				sizeof(asrc_priv->name) - 1);
713 	} else if (of_device_is_compatible(np, "fsl,imx53-asrc")) {
714 		asrc_priv->clk_map[IN] = input_clk_map_imx53;
715 		asrc_priv->clk_map[OUT] = output_clk_map_imx53;
716+		strncpy(asrc_priv->name, "mxc_asrc",
717+				sizeof(asrc_priv->name) - 1);
718 	} else if (of_device_is_compatible(np, "fsl,imx8qm-asrc") ||
719 		   of_device_is_compatible(np, "fsl,imx8qxp-asrc")) {
720 		ret = of_property_read_u32(np, "fsl,asrc-clk-map", &map_idx);
721@@ -1120,14 +1136,28 @@ static int fsl_asrc_probe(struct platform_device *pdev)
722 			asrc_priv->clk_map[IN] = clk_map_imx8qxp[map_idx];
723 			asrc_priv->clk_map[OUT] = clk_map_imx8qxp[map_idx];
724 		}
725+
726+		if (map_idx == 0) {
727+			strncpy(asrc_priv->name, "mxc_asrc",
728+				sizeof(asrc_priv->name) - 1);
729+		} else {
730+			strncpy(asrc_priv->name, "mxc_asrc1",
731+				sizeof(asrc_priv->name) - 1);
732+		}
733 	}
734
735+	ret = clk_prepare_enable(asrc->mem_clk);
736+	if (ret)
737+		return ret;
738+
739 	ret = fsl_asrc_init(asrc);
740 	if (ret) {
741 		dev_err(&pdev->dev, "failed to init asrc %d\n", ret);
742 		return ret;
743 	}
744
745+	clk_disable_unprepare(asrc->mem_clk);
746+
747 	asrc->channel_avail = 10;
748
749 	ret = of_property_read_u32(np, "fsl,asrc-rate",
750@@ -1177,6 +1207,12 @@ static int fsl_asrc_probe(struct platform_device *pdev)
751 		return ret;
752 	}
753
754+	ret = fsl_asrc_m2m_init(asrc);
755+	if (ret) {
756+		dev_err(&pdev->dev, "failed to init m2m device %d\n", ret);
757+		return ret;
758+	}
759+
760 	return 0;
761 }
762
763@@ -1187,6 +1223,8 @@ static int fsl_asrc_runtime_resume(struct device *dev)
764 	struct fsl_asrc_priv *asrc_priv = asrc->private;
765 	int i, ret;
766 	u32 asrctr;
767+	u32 reg;
768+	int retry = 50;
769
770 	ret = clk_prepare_enable(asrc->mem_clk);
771 	if (ret)
772@@ -1223,6 +1261,16 @@ static int fsl_asrc_runtime_resume(struct device *dev)
773 	regmap_update_bits(asrc->regmap, REG_ASRCTR,
774 			   ASRCTR_ASRCEi_ALL_MASK, asrctr);
775
776+	/* Wait for status of initialization */
777+	do {
778+		udelay(5);
779+		regmap_read(asrc->regmap, REG_ASRCFG, &reg);
780+		reg = (reg >> ASRCFG_INIRQi_SHIFT(0)) & 0x7;
781+	} while (!(reg == ((asrctr & 0xE) >> 1)) && --retry);
782+
783+	if (retry == 0)
784+		dev_warn(dev, "initialization is not finished\n");
785+
786 	return 0;
787
788 disable_asrck_clk:
789@@ -1259,10 +1307,36 @@ static int fsl_asrc_runtime_suspend(struct device *dev)
790 }
791 #endif /* CONFIG_PM */
792
793+#ifdef CONFIG_PM_SLEEP
794+static int fsl_asrc_suspend(struct device *dev)
795+{
796+	struct fsl_asrc *asrc = dev_get_drvdata(dev);
797+	int ret;
798+
799+	fsl_asrc_m2m_suspend(asrc);
800+
801+	ret = pm_runtime_force_suspend(dev);
802+
803+	return ret;
804+}
805+
806+static int fsl_asrc_resume(struct device *dev)
807+{
808+	struct fsl_asrc *asrc = dev_get_drvdata(dev);
809+	int ret;
810+
811+	ret = pm_runtime_force_resume(dev);
812+
813+	fsl_asrc_m2m_resume(asrc);
814+
815+	return ret;
816+}
817+#endif /* CONFIG_PM_SLEEP */
818+
819 static const struct dev_pm_ops fsl_asrc_pm = {
820 	SET_RUNTIME_PM_OPS(fsl_asrc_runtime_suspend, fsl_asrc_runtime_resume, NULL)
821-	SET_SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend,
822-				pm_runtime_force_resume)
823+	SET_SYSTEM_SLEEP_PM_OPS(fsl_asrc_suspend,
824+				fsl_asrc_resume)
825 };
826
827 static const struct fsl_asrc_soc_data fsl_asrc_imx35_data = {
828@@ -1296,6 +1370,7 @@ MODULE_DEVICE_TABLE(of, fsl_asrc_ids);
829
830 static struct platform_driver fsl_asrc_driver = {
831 	.probe = fsl_asrc_probe,
832+	.remove = fsl_asrc_m2m_remove,
833 	.driver = {
834 		.name = "fsl-asrc",
835 		.of_match_table = fsl_asrc_ids,
836diff --git a/sound/soc/fsl/fsl_asrc.h b/sound/soc/fsl/fsl_asrc.h
837index 86d2422ad..18a9551cc 100644
838--- a/sound/soc/fsl/fsl_asrc.h
839+++ b/sound/soc/fsl/fsl_asrc.h
840@@ -11,6 +11,7 @@
841 #define _FSL_ASRC_H
842
843 #include  "fsl_asrc_common.h"
844+#include <sound/asound.h>
845
846 #define ASRC_DMA_BUFFER_NUM		2
847 #define ASRC_INPUTFIFO_THRESHOLD	32
848@@ -19,7 +20,8 @@
849 #define ASRC_FIFO_THRESHOLD_MAX		63
850 #define ASRC_DMA_BUFFER_SIZE		(1024 * 48 * 4)
851 #define ASRC_MAX_BUFFER_SIZE		(1024 * 48)
852-#define ASRC_OUTPUT_LAST_SAMPLE		8
853+#define ASRC_OUTPUT_LAST_SAMPLE_MAX	32
854+#define ASRC_OUTPUT_LAST_SAMPLE		4
855
856 #define IDEAL_RATIO_RATE		1000000
857
858@@ -284,139 +286,13 @@
859
860 #define ASRC_PAIR_MAX_NUM	(ASRC_PAIR_C + 1)
861
862-enum asrc_inclk {
863-	INCLK_NONE = 0x03,
864-	INCLK_ESAI_RX = 0x00,
865-	INCLK_SSI1_RX = 0x01,
866-	INCLK_SSI2_RX = 0x02,
867-	INCLK_SSI3_RX = 0x07,
868-	INCLK_SPDIF_RX = 0x04,
869-	INCLK_MLB_CLK = 0x05,
870-	INCLK_PAD = 0x06,
871-	INCLK_ESAI_TX = 0x08,
872-	INCLK_SSI1_TX = 0x09,
873-	INCLK_SSI2_TX = 0x0a,
874-	INCLK_SSI3_TX = 0x0b,
875-	INCLK_SPDIF_TX = 0x0c,
876-	INCLK_ASRCK1_CLK = 0x0f,
877-
878-	/* clocks for imx8 */
879-	INCLK_AUD_PLL_DIV_CLK0 = 0x10,
880-	INCLK_AUD_PLL_DIV_CLK1 = 0x11,
881-	INCLK_AUD_CLK0         = 0x12,
882-	INCLK_AUD_CLK1         = 0x13,
883-	INCLK_ESAI0_RX_CLK     = 0x14,
884-	INCLK_ESAI0_TX_CLK     = 0x15,
885-	INCLK_SPDIF0_RX        = 0x16,
886-	INCLK_SPDIF1_RX        = 0x17,
887-	INCLK_SAI0_RX_BCLK     = 0x18,
888-	INCLK_SAI0_TX_BCLK     = 0x19,
889-	INCLK_SAI1_RX_BCLK     = 0x1a,
890-	INCLK_SAI1_TX_BCLK     = 0x1b,
891-	INCLK_SAI2_RX_BCLK     = 0x1c,
892-	INCLK_SAI3_RX_BCLK     = 0x1d,
893-	INCLK_ASRC0_MUX_CLK    = 0x1e,
894-
895-	INCLK_ESAI1_RX_CLK     = 0x20,
896-	INCLK_ESAI1_TX_CLK     = 0x21,
897-	INCLK_SAI6_TX_BCLK     = 0x22,
898-	INCLK_HDMI_RX_SAI0_RX_BCLK     = 0x24,
899-	INCLK_HDMI_TX_SAI0_TX_BCLK     = 0x25,
900-};
901-
902-enum asrc_outclk {
903-	OUTCLK_NONE = 0x03,
904-	OUTCLK_ESAI_TX = 0x00,
905-	OUTCLK_SSI1_TX = 0x01,
906-	OUTCLK_SSI2_TX = 0x02,
907-	OUTCLK_SSI3_TX = 0x07,
908-	OUTCLK_SPDIF_TX = 0x04,
909-	OUTCLK_MLB_CLK = 0x05,
910-	OUTCLK_PAD = 0x06,
911-	OUTCLK_ESAI_RX = 0x08,
912-	OUTCLK_SSI1_RX = 0x09,
913-	OUTCLK_SSI2_RX = 0x0a,
914-	OUTCLK_SSI3_RX = 0x0b,
915-	OUTCLK_SPDIF_RX = 0x0c,
916-	OUTCLK_ASRCK1_CLK = 0x0f,
917-
918-	/* clocks for imx8 */
919-	OUTCLK_AUD_PLL_DIV_CLK0 = 0x10,
920-	OUTCLK_AUD_PLL_DIV_CLK1 = 0x11,
921-	OUTCLK_AUD_CLK0         = 0x12,
922-	OUTCLK_AUD_CLK1         = 0x13,
923-	OUTCLK_ESAI0_RX_CLK     = 0x14,
924-	OUTCLK_ESAI0_TX_CLK     = 0x15,
925-	OUTCLK_SPDIF0_RX        = 0x16,
926-	OUTCLK_SPDIF1_RX        = 0x17,
927-	OUTCLK_SAI0_RX_BCLK     = 0x18,
928-	OUTCLK_SAI0_TX_BCLK     = 0x19,
929-	OUTCLK_SAI1_RX_BCLK     = 0x1a,
930-	OUTCLK_SAI1_TX_BCLK     = 0x1b,
931-	OUTCLK_SAI2_RX_BCLK     = 0x1c,
932-	OUTCLK_SAI3_RX_BCLK     = 0x1d,
933-	OUTCLK_ASRCO_MUX_CLK    = 0x1e,
934-
935-	OUTCLK_ESAI1_RX_CLK     = 0x20,
936-	OUTCLK_ESAI1_TX_CLK     = 0x21,
937-	OUTCLK_SAI6_TX_BCLK     = 0x22,
938-	OUTCLK_HDMI_RX_SAI0_RX_BCLK     = 0x24,
939-	OUTCLK_HDMI_TX_SAI0_TX_BCLK     = 0x25,
940-};
941-
942 #define ASRC_CLK_MAX_NUM	16
943 #define ASRC_CLK_MAP_LEN	0x30
944
945 enum asrc_word_width {
946 	ASRC_WIDTH_24_BIT = 0,
947 	ASRC_WIDTH_16_BIT = 1,
948-	ASRC_WIDTH_8_BIT = 2,
949-};
950-
951-struct asrc_config {
952-	enum asrc_pair_index pair;
953-	unsigned int channel_num;
954-	unsigned int buffer_num;
955-	unsigned int dma_buffer_size;
956-	unsigned int input_sample_rate;
957-	unsigned int output_sample_rate;
958-	snd_pcm_format_t input_format;
959-	snd_pcm_format_t output_format;
960-	enum asrc_inclk inclk;
961-	enum asrc_outclk outclk;
962-};
963-
964-struct asrc_req {
965-	unsigned int chn_num;
966-	enum asrc_pair_index index;
967-};
968-
969-struct asrc_querybuf {
970-	unsigned int buffer_index;
971-	unsigned int input_length;
972-	unsigned int output_length;
973-	unsigned long input_offset;
974-	unsigned long output_offset;
975-};
976-
977-struct asrc_convert_buffer {
978-	void *input_buffer_vaddr;
979-	void *output_buffer_vaddr;
980-	unsigned int input_buffer_length;
981-	unsigned int output_buffer_length;
982-};
983-
984-struct asrc_status_flags {
985-	enum asrc_pair_index index;
986-	unsigned int overload_error;
987-};
988-
989-enum asrc_error_status {
990-	ASRC_TASK_Q_OVERLOAD		= 0x01,
991-	ASRC_OUTPUT_TASK_OVERLOAD	= 0x02,
992-	ASRC_INPUT_TASK_OVERLOAD	= 0x04,
993-	ASRC_OUTPUT_BUFFER_OVERFLOW	= 0x08,
994-	ASRC_INPUT_BUFFER_UNDERRUN	= 0x10,
995+	ASRC_WIDTH_8_BIT  = 2,
996 };
997
998 struct dma_block {
999@@ -459,6 +335,7 @@ struct fsl_asrc_priv {
1000 	unsigned char *clk_map[2];
1001
1002 	u32 regcache_cfg;
1003+	char name[20];
1004 };
1005
1006 #endif /* _FSL_ASRC_H */
1007diff --git a/sound/soc/fsl/fsl_asrc_common.h b/sound/soc/fsl/fsl_asrc_common.h
1008index 7e1c13ca3..da2e1aec0 100644
1009--- a/sound/soc/fsl/fsl_asrc_common.h
1010+++ b/sound/soc/fsl/fsl_asrc_common.h
1011@@ -7,18 +7,12 @@
1012 #ifndef _FSL_ASRC_COMMON_H
1013 #define _FSL_ASRC_COMMON_H
1014
1015+#include <linux/miscdevice.h>
1016+#include <uapi/linux/mxc_asrc.h>
1017 /* directions */
1018 #define IN	0
1019 #define OUT	1
1020
1021-enum asrc_pair_index {
1022-	ASRC_INVALID_PAIR = -1,
1023-	ASRC_PAIR_A = 0,
1024-	ASRC_PAIR_B = 1,
1025-	ASRC_PAIR_C = 2,
1026-	ASRC_PAIR_D = 3,
1027-};
1028-
1029 #define PAIR_CTX_NUM  0x4
1030
1031 /**
1032@@ -49,6 +43,7 @@ struct fsl_asrc_pair {
1033 	bool req_dma_chan;
1034
1035 	void *private;
1036+	void *private_m2m;
1037 };
1038
1039 /**
1040@@ -86,6 +81,7 @@ struct fsl_asrc {
1041 	struct clk *spba_clk;
1042 	spinlock_t lock;      /* spin lock for resource protection */
1043
1044+	struct miscdevice asrc_miscdev;
1045 	struct fsl_asrc_pair *pair[PAIR_CTX_NUM];
1046 	unsigned int channel_avail;
1047
1048diff --git a/sound/soc/fsl/fsl_asrc_dma.c b/sound/soc/fsl/fsl_asrc_dma.c
1049index 29f91cdec..6fd560e3f 100644
1050--- a/sound/soc/fsl/fsl_asrc_dma.c
1051+++ b/sound/soc/fsl/fsl_asrc_dma.c
1052@@ -23,7 +23,7 @@ static struct snd_pcm_hardware snd_imx_hardware = {
1053 		SNDRV_PCM_INFO_MMAP_VALID,
1054 	.buffer_bytes_max = FSL_ASRC_DMABUF_SIZE,
1055 	.period_bytes_min = 128,
1056-	.period_bytes_max = 65535, /* Limited by SDMA engine */
1057+	.period_bytes_max = 65532, /* Limited by SDMA engine */
1058 	.periods_min = 2,
1059 	.periods_max = 255,
1060 	.fifo_size = 0,
1061@@ -139,6 +139,7 @@ static int fsl_asrc_dma_hw_params(struct snd_soc_component *component,
1062 	struct snd_soc_component *component_be = NULL;
1063 	struct fsl_asrc *asrc = pair->asrc;
1064 	struct dma_slave_config config_fe, config_be;
1065+	struct sdma_audio_config audio_config;
1066 	enum asrc_pair_index index = pair->index;
1067 	struct device *dev = component->dev;
1068 	int stream = substream->stream;
1069@@ -148,6 +149,8 @@ static int fsl_asrc_dma_hw_params(struct snd_soc_component *component,
1070 	u8 dir = tx ? OUT : IN;
1071 	dma_cap_mask_t mask;
1072 	int ret, width;
1073+	enum sdma_peripheral_type be_peripheral_type = IMX_DMATYPE_SSI;
1074+	struct device_node *of_dma_node;
1075
1076 	/* Fetch the Back-End dma_data from DPCM */
1077 	for_each_dpcm_be(rtd, stream, dpcm) {
1078@@ -193,6 +196,7 @@ static int fsl_asrc_dma_hw_params(struct snd_soc_component *component,
1079 		return ret;
1080 	}
1081
1082+	of_dma_node = pair->dma_chan[!dir]->device->dev->of_node;
1083 	/* Request and config DMA channel for Back-End */
1084 	dma_cap_zero(mask);
1085 	dma_cap_set(DMA_SLAVE, mask);
1086@@ -220,6 +224,7 @@ static int fsl_asrc_dma_hw_params(struct snd_soc_component *component,
1087 		/* Get DMA request of Back-End */
1088 		tmp_data = tmp_chan->private;
1089 		pair->dma_data.dma_request = tmp_data->dma_request;
1090+		be_peripheral_type = tmp_data->peripheral_type;
1091 		if (!be_chan)
1092 			dma_release_channel(tmp_chan);
1093
1094@@ -232,7 +237,8 @@ static int fsl_asrc_dma_hw_params(struct snd_soc_component *component,
1095 		dma_release_channel(tmp_chan);
1096
1097 		pair->dma_chan[dir] =
1098-			dma_request_channel(mask, filter, &pair->dma_data);
1099+			__dma_request_channel(&mask, filter, &pair->dma_data,
1100+					      of_dma_node);
1101 		pair->req_dma_chan = true;
1102 	} else {
1103 		pair->dma_chan[dir] = tmp_chan;
1104@@ -259,12 +265,24 @@ static int fsl_asrc_dma_hw_params(struct snd_soc_component *component,
1105 	else
1106 		buswidth = DMA_SLAVE_BUSWIDTH_8_BYTES;
1107
1108+	memset(&config_be, 0, sizeof(config_be));
1109 	config_be.direction = DMA_DEV_TO_DEV;
1110 	config_be.src_addr_width = buswidth;
1111 	config_be.src_maxburst = dma_params_be->maxburst;
1112 	config_be.dst_addr_width = buswidth;
1113 	config_be.dst_maxburst = dma_params_be->maxburst;
1114
1115+	memset(&audio_config, 0, sizeof(audio_config));
1116+	config_be.peripheral_config = &audio_config;
1117+	config_be.peripheral_size  = sizeof(audio_config);
1118+
1119+	if (tx && (be_peripheral_type == IMX_DMATYPE_SSI_DUAL ||
1120+		   be_peripheral_type == IMX_DMATYPE_SPDIF))
1121+		audio_config.dst_fifo_num = 2;
1122+	if (!tx && (be_peripheral_type == IMX_DMATYPE_SSI_DUAL ||
1123+		    be_peripheral_type == IMX_DMATYPE_SPDIF))
1124+		audio_config.src_fifo_num = 2;
1125+
1126 	if (tx) {
1127 		config_be.src_addr = asrc->paddr + asrc->get_fifo_addr(OUT, index);
1128 		config_be.dst_addr = dma_params_be->addr;
1129diff --git a/sound/soc/fsl/fsl_asrc_m2m.c b/sound/soc/fsl/fsl_asrc_m2m.c
1130new file mode 100644
1131index 000000000..26f639678
1132--- /dev/null
1133+++ b/sound/soc/fsl/fsl_asrc_m2m.c
1134@@ -0,0 +1,1059 @@
1135+/*
1136+ * Freescale ASRC Memory to Memory (M2M) driver
1137+ *
1138+ * Copyright (C) 2014-2016 Freescale Semiconductor, Inc.
1139+ *
1140+ * This file is licensed under the terms of the GNU General Public License
1141+ * version 2. This program is licensed "as is" without any warranty of any
1142+ * kind, whether express or implied.
1143+ */
1144+
1145+#define FSL_ASRC_INPUTFIFO_WML	0x4
1146+#define FSL_ASRC_OUTPUTFIFO_WML	0x2
1147+
1148+#define DIR_STR(dir) dir == IN ? "in" : "out"
1149+
1150+struct fsl_asrc_m2m {
1151+	struct fsl_asrc_pair *pair;
1152+	struct completion complete[2];
1153+	struct dma_block dma_block[2];
1154+	unsigned int pair_hold;
1155+	unsigned int asrc_active;
1156+	unsigned int sg_nodes[2];
1157+	struct scatterlist sg[2][4];
1158+
1159+	snd_pcm_format_t word_format[2];
1160+	unsigned int rate[2];
1161+	unsigned int last_period_size;
1162+	u32 watermark[2];
1163+	spinlock_t lock;
1164+};
1165+
1166+static void fsl_asrc_get_status(struct fsl_asrc_pair *pair,
1167+				struct asrc_status_flags *flags)
1168+{
1169+	struct fsl_asrc *asrc = pair->asrc;
1170+	unsigned long lock_flags;
1171+
1172+	spin_lock_irqsave(&asrc->lock, lock_flags);
1173+
1174+	flags->overload_error = pair->error;
1175+
1176+	spin_unlock_irqrestore(&asrc->lock, lock_flags);
1177+}
1178+
1179+#define ASRC_xPUT_DMA_CALLBACK(dir) \
1180+	((dir == IN) ? fsl_asrc_input_dma_callback : fsl_asrc_output_dma_callback)
1181+
1182+static void fsl_asrc_input_dma_callback(void *data)
1183+{
1184+	struct fsl_asrc_pair *pair = (struct fsl_asrc_pair *)data;
1185+	struct fsl_asrc_m2m *m2m = pair->private_m2m;
1186+
1187+	complete(&m2m->complete[IN]);
1188+}
1189+
1190+static void fsl_asrc_output_dma_callback(void *data)
1191+{
1192+	struct fsl_asrc_pair *pair = (struct fsl_asrc_pair *)data;
1193+	struct fsl_asrc_m2m *m2m = pair->private_m2m;
1194+
1195+	complete(&m2m->complete[OUT]);
1196+}
1197+
1198+static unsigned int fsl_asrc_get_output_FIFO_size(struct fsl_asrc_pair *pair)
1199+{
1200+	struct fsl_asrc *asrc = pair->asrc;
1201+	enum asrc_pair_index index = pair->index;
1202+	u32 val;
1203+
1204+	regmap_read(asrc->regmap, REG_ASRFST(index), &val);
1205+
1206+	val &= ASRFSTi_OUTPUT_FIFO_MASK;
1207+
1208+	return val >> ASRFSTi_OUTPUT_FIFO_SHIFT;
1209+}
1210+
1211+static void fsl_asrc_read_last_FIFO(struct fsl_asrc_pair *pair)
1212+{
1213+	struct fsl_asrc_m2m *m2m = pair->private_m2m;
1214+	struct fsl_asrc *asrc = pair->asrc;
1215+	enum asrc_pair_index index = pair->index;
1216+	struct dma_block *output = &m2m->dma_block[OUT];
1217+	u32 i, reg, size, t_size = 0, width;
1218+	u32 *reg32 = NULL;
1219+	u16 *reg16 = NULL;
1220+	u8  *reg24 = NULL;
1221+
1222+	width = snd_pcm_format_physical_width(m2m->word_format[OUT]);
1223+
1224+	if (width == 32)
1225+		reg32 = output->dma_vaddr + output->length;
1226+	else if (width == 16)
1227+		reg16 = output->dma_vaddr + output->length;
1228+	else
1229+		reg24 = output->dma_vaddr + output->length;
1230+
1231+retry:
1232+	size = fsl_asrc_get_output_FIFO_size(pair);
1233+
1234+	for (i = 0; i < size * pair->channels; i++) {
1235+		regmap_read(asrc->regmap, REG_ASRDO(index), &reg);
1236+		if (reg32) {
1237+			*(reg32) = reg;
1238+			reg32++;
1239+		} else if (reg16) {
1240+			*(reg16) = (u16)reg;
1241+			reg16++;
1242+		} else {
1243+			*reg24++ = (u8)reg;
1244+			*reg24++ = (u8)(reg >> 8);
1245+			*reg24++ = (u8)(reg >> 16);
1246+		}
1247+	}
1248+	t_size += size;
1249+
1250+	if (size)
1251+		goto retry;
1252+
1253+	if (t_size > m2m->last_period_size)
1254+		t_size = m2m->last_period_size;
1255+
1256+	if (reg32)
1257+		output->length += t_size * pair->channels * 4;
1258+	else if (reg16)
1259+		output->length += t_size * pair->channels * 2;
1260+	else
1261+		output->length += t_size * pair->channels * 3;
1262+}
1263+
1264+static int fsl_allocate_dma_buf(struct fsl_asrc_pair *pair)
1265+{
1266+	struct fsl_asrc_m2m *m2m = pair->private_m2m;
1267+	struct fsl_asrc *asrc = pair->asrc;
1268+	struct dma_block *input = &m2m->dma_block[IN];
1269+	struct dma_block *output = &m2m->dma_block[OUT];
1270+	enum asrc_pair_index index = pair->index;
1271+
1272+	input->dma_vaddr = kzalloc(input->length, GFP_KERNEL);
1273+	if (!input->dma_vaddr) {
1274+		pair_err("failed to allocate input DMA buffer\n");
1275+		return -ENOMEM;
1276+	}
1277+
1278+	output->dma_vaddr = kzalloc(output->length, GFP_KERNEL);
1279+	if (!output->dma_vaddr) {
1280+		pair_err("failed to allocate output DMA buffer\n");
1281+		goto exit;
1282+	}
1283+
1284+	return 0;
1285+
1286+exit:
1287+	kfree(input->dma_vaddr);
1288+	input->dma_vaddr = NULL;
1289+	return -ENOMEM;
1290+}
1291+
1292+static int fsl_asrc_dmaconfig(struct fsl_asrc_pair *pair, struct dma_chan *chan,
1293+			      u32 dma_addr, void *buf_addr, u32 buf_len,
1294+			      bool dir, snd_pcm_format_t word_format)
1295+{
1296+	struct dma_async_tx_descriptor *desc = pair->desc[dir];
1297+	struct fsl_asrc *asrc = pair->asrc;
1298+	struct fsl_asrc_priv *asrc_priv = asrc->private;
1299+	struct fsl_asrc_m2m *m2m = pair->private_m2m;
1300+	unsigned int sg_nent = m2m->sg_nodes[dir];
1301+	enum asrc_pair_index index = pair->index;
1302+	struct scatterlist *sg = m2m->sg[dir];
1303+	struct dma_slave_config slave_config;
1304+	enum dma_slave_buswidth buswidth;
1305+	int ret, i;
1306+
1307+	switch (snd_pcm_format_physical_width(word_format)) {
1308+	case 8:
1309+		buswidth = DMA_SLAVE_BUSWIDTH_1_BYTE;
1310+		break;
1311+	case 16:
1312+		buswidth = DMA_SLAVE_BUSWIDTH_2_BYTES;
1313+		break;
1314+	case 24:
1315+		buswidth = DMA_SLAVE_BUSWIDTH_3_BYTES;
1316+		break;
1317+	case 32:
1318+		buswidth = DMA_SLAVE_BUSWIDTH_4_BYTES;
1319+		break;
1320+	default:
1321+		pair_err("invalid word width\n");
1322+		return -EINVAL;
1323+	}
1324+
1325+	memset(&slave_config, 0, sizeof(slave_config));
1326+	if (dir == IN) {
1327+		slave_config.direction = DMA_MEM_TO_DEV;
1328+		slave_config.dst_addr = dma_addr;
1329+		slave_config.dst_addr_width = buswidth;
1330+		if (!asrc_priv->soc->use_edma)
1331+			slave_config.dst_maxburst =
1332+				m2m->watermark[IN] * pair->channels;
1333+		else
1334+			slave_config.dst_maxburst = 1;
1335+	} else {
1336+		slave_config.direction = DMA_DEV_TO_MEM;
1337+		slave_config.src_addr = dma_addr;
1338+		slave_config.src_addr_width = buswidth;
1339+		if (!asrc_priv->soc->use_edma)
1340+			slave_config.src_maxburst =
1341+				m2m->watermark[OUT] * pair->channels;
1342+		else
1343+			slave_config.src_maxburst = 1;
1344+	}
1345+
1346+	ret = dmaengine_slave_config(chan, &slave_config);
1347+	if (ret) {
1348+		pair_err("failed to config dmaengine for %sput task: %d\n",
1349+				DIR_STR(dir), ret);
1350+		return -EINVAL;
1351+	}
1352+
1353+	sg_init_table(sg, sg_nent);
1354+	switch (sg_nent) {
1355+	case 1:
1356+		sg_init_one(sg, buf_addr, buf_len);
1357+		break;
1358+	case 2:
1359+	case 3:
1360+	case 4:
1361+		for (i = 0; i < (sg_nent - 1); i++)
1362+			sg_set_buf(&sg[i], buf_addr + i * ASRC_MAX_BUFFER_SIZE,
1363+					ASRC_MAX_BUFFER_SIZE);
1364+
1365+		sg_set_buf(&sg[i], buf_addr + i * ASRC_MAX_BUFFER_SIZE,
1366+				buf_len - ASRC_MAX_BUFFER_SIZE * i);
1367+		break;
1368+	default:
1369+		pair_err("invalid input DMA nodes number: %d\n", sg_nent);
1370+		return -EINVAL;
1371+	}
1372+
1373+	ret = dma_map_sg(&asrc->pdev->dev, sg, sg_nent, slave_config.direction);
1374+	if (ret != sg_nent) {
1375+		pair_err("failed to map DMA sg for %sput task\n", DIR_STR(dir));
1376+		return -EINVAL;
1377+	}
1378+
1379+	desc = dmaengine_prep_slave_sg(chan, sg, sg_nent,
1380+			slave_config.direction, DMA_PREP_INTERRUPT);
1381+	if (!desc) {
1382+		pair_err("failed to prepare dmaengine for %sput task\n",
1383+				DIR_STR(dir));
1384+		return -EINVAL;
1385+	}
1386+
1387+	pair->desc[dir] = desc;
1388+	pair->desc[dir]->callback = ASRC_xPUT_DMA_CALLBACK(dir);
1389+
1390+	desc->callback = ASRC_xPUT_DMA_CALLBACK(dir);
1391+	desc->callback_param = pair;
1392+
1393+	return 0;
1394+}
1395+
1396+static int fsl_asrc_prepare_io_buffer(struct fsl_asrc_pair *pair,
1397+				      struct asrc_convert_buffer *pbuf, bool dir)
1398+{
1399+	struct fsl_asrc_m2m *m2m = pair->private_m2m;
1400+	struct fsl_asrc *asrc = pair->asrc;
1401+	struct fsl_asrc_priv *asrc_priv = asrc->private;
1402+	unsigned int *dma_len = &m2m->dma_block[dir].length;
1403+	void *dma_vaddr = m2m->dma_block[dir].dma_vaddr;
1404+	struct dma_chan *dma_chan = pair->dma_chan[dir];
1405+	unsigned int buf_len, wm = m2m->watermark[dir];
1406+	unsigned int *sg_nodes = &m2m->sg_nodes[dir];
1407+	unsigned int last_period_size = m2m->last_period_size;
1408+	enum asrc_pair_index index = pair->index;
1409+	u32 word_size, fifo_addr;
1410+	void __user *buf_vaddr;
1411+
1412+	/* Clean the DMA buffer */
1413+	memset(dma_vaddr, 0, ASRC_DMA_BUFFER_SIZE);
1414+
1415+	if (dir == IN) {
1416+		buf_vaddr = (void __user *)pbuf->input_buffer_vaddr;
1417+		buf_len = pbuf->input_buffer_length;
1418+	} else {
1419+		buf_vaddr = (void __user *)pbuf->output_buffer_vaddr;
1420+		buf_len = pbuf->output_buffer_length;
1421+	}
1422+
1423+	word_size = snd_pcm_format_physical_width(m2m->word_format[dir]) / 8;
1424+
1425+	if (buf_len < word_size * pair->channels * wm ||
1426+	    buf_len > ASRC_DMA_BUFFER_SIZE ||
1427+	    (dir == OUT && buf_len < word_size * pair->channels * last_period_size)) {
1428+		pair_err("%sput buffer size is error: [%d]\n",
1429+				DIR_STR(dir), buf_len);
1430+		return -EINVAL;
1431+	}
1432+
1433+	/* Copy origin data into input buffer */
1434+	if (dir == IN && copy_from_user(dma_vaddr, buf_vaddr, buf_len))
1435+		return -EFAULT;
1436+
1437+	*dma_len = buf_len;
1438+	if (dir == OUT) {
1439+		*dma_len -= last_period_size * word_size * pair->channels;
1440+		*dma_len = *dma_len / (word_size * pair->channels) *
1441+				(word_size * pair->channels);
1442+		if (asrc_priv->soc->use_edma)
1443+			*dma_len = *dma_len / (word_size * pair->channels * m2m->watermark[OUT])
1444+					* (word_size * pair->channels * m2m->watermark[OUT]);
1445+	}
1446+
1447+	*sg_nodes = *dma_len / ASRC_MAX_BUFFER_SIZE;
1448+	if (*dma_len % ASRC_MAX_BUFFER_SIZE)
1449+		*sg_nodes += 1;
1450+
1451+	fifo_addr = asrc->paddr + REG_ASRDx(dir, index);
1452+
1453+	return fsl_asrc_dmaconfig(pair, dma_chan, fifo_addr, dma_vaddr,
1454+				  *dma_len, dir, m2m->word_format[dir]);
1455+}
1456+
1457+static int fsl_asrc_prepare_buffer(struct fsl_asrc_pair *pair,
1458+				   struct asrc_convert_buffer *pbuf)
1459+{
1460+	struct fsl_asrc *asrc = pair->asrc;
1461+	enum asrc_pair_index index = pair->index;
1462+	int ret;
1463+
1464+	ret = fsl_asrc_prepare_io_buffer(pair, pbuf, IN);
1465+	if (ret) {
1466+		pair_err("failed to prepare input buffer: %d\n", ret);
1467+		return ret;
1468+	}
1469+
1470+	ret = fsl_asrc_prepare_io_buffer(pair, pbuf, OUT);
1471+	if (ret) {
1472+		pair_err("failed to prepare output buffer: %d\n", ret);
1473+		return ret;
1474+	}
1475+
1476+	return 0;
1477+}
1478+
1479+int fsl_asrc_process_buffer_pre(struct completion *complete,
1480+				enum asrc_pair_index index, bool dir)
1481+{
1482+	if (!wait_for_completion_interruptible_timeout(complete, 10 * HZ)) {
1483+		pr_err("%sput DMA task timeout\n", DIR_STR(dir));
1484+		return -ETIME;
1485+	} else if (signal_pending(current)) {
1486+		pr_err("%sput task forcibly aborted\n", DIR_STR(dir));
1487+		return -ERESTARTSYS;
1488+	}
1489+
1490+	return 0;
1491+}
1492+
1493+#define mxc_asrc_dma_umap(dev, m2m) \
1494+	do { \
1495+		dma_unmap_sg(dev, m2m->sg[IN], m2m->sg_nodes[IN], \
1496+			     DMA_MEM_TO_DEV); \
1497+		dma_unmap_sg(dev, m2m->sg[OUT], m2m->sg_nodes[OUT], \
1498+			     DMA_DEV_TO_MEM); \
1499+	} while (0)
1500+
1501+int fsl_asrc_process_buffer(struct fsl_asrc_pair *pair,
1502+			    struct asrc_convert_buffer *pbuf)
1503+{
1504+	struct fsl_asrc *asrc = pair->asrc;
1505+	struct fsl_asrc_m2m *m2m = pair->private_m2m;
1506+	enum asrc_pair_index index = pair->index;
1507+	unsigned long lock_flags;
1508+	int ret;
1509+
1510+	/* Check input task first */
1511+	ret = fsl_asrc_process_buffer_pre(&m2m->complete[IN], index, IN);
1512+	if (ret) {
1513+		mxc_asrc_dma_umap(&asrc->pdev->dev, m2m);
1514+		return ret;
1515+	}
1516+
1517+	/* ...then output task*/
1518+	ret = fsl_asrc_process_buffer_pre(&m2m->complete[OUT], index, OUT);
1519+	if (ret) {
1520+		mxc_asrc_dma_umap(&asrc->pdev->dev, m2m);
1521+		return ret;
1522+	}
1523+
1524+	mxc_asrc_dma_umap(&asrc->pdev->dev, m2m);
1525+
1526+	/* Fetch the remaining data */
1527+	spin_lock_irqsave(&m2m->lock, lock_flags);
1528+	if (!m2m->pair_hold) {
1529+		spin_unlock_irqrestore(&m2m->lock, lock_flags);
1530+		return -EFAULT;
1531+	}
1532+	spin_unlock_irqrestore(&m2m->lock, lock_flags);
1533+
1534+	fsl_asrc_read_last_FIFO(pair);
1535+
1536+	/* Update final lengths after getting last FIFO */
1537+	pbuf->input_buffer_length = m2m->dma_block[IN].length;
1538+	pbuf->output_buffer_length = m2m->dma_block[OUT].length;
1539+
1540+	if (copy_to_user((void __user *)pbuf->output_buffer_vaddr,
1541+			 m2m->dma_block[OUT].dma_vaddr,
1542+			 m2m->dma_block[OUT].length))
1543+		return -EFAULT;
1544+
1545+	return 0;
1546+}
1547+
1548+#ifdef ASRC_POLLING_WITHOUT_DMA
1549+/* THIS FUNCTION ONLY EXISTS FOR DEBUGGING AND ONLY SUPPORTS TWO CHANNELS */
1550+static void fsl_asrc_polling_debug(struct fsl_asrc_pair *pair)
1551+{
1552+	struct fsl_asrc_m2m *m2m = pair->private_m2m;
1553+	enum asrc_pair_index index = pair->index;
1554+	u32 *in24 = m2m->dma_block[IN].dma_vaddr;
1555+	u32 dma_len = m2m->dma_block[IN].length / (pair->channels * 4);
1556+	u32 *reg24 = m2m->dma_block[OUT].dma_vaddr;
1557+	u32 size, i, j, t_size, reg;
1558+
1559+	t_size = 0;
1560+
1561+	for (i = 0; i < dma_len; ) {
1562+		for (j = 0; j < 2; j++) {
1563+			regmap_write(asrc->regmap, REG_ASRDx(index), *in24);
1564+			in24++;
1565+			regmap_write(asrc->regmap, REG_ASRDx(index), *in24);
1566+			in24++;
1567+			i++;
1568+		}
1569+		udelay(50);
1570+		udelay(50 * m2m->rate[OUT] / m2m->rate[IN]);
1571+
1572+		size = fsl_asrc_get_output_FIFO_size(index);
1573+		for (j = 0; j < size; j++) {
1574+			regmap_read(asrc->regmap, REG_ASRDO(index), &reg);
1575+			*(reg24) = reg;
1576+			reg24++;
1577+			regmap_read(asrc->regmap, REG_ASRDO(index), &reg);
1578+			*(reg24) = reg;
1579+			reg24++;
1580+		}
1581+		t_size += size;
1582+	}
1583+
1584+	mdelay(1);
1585+	size = fsl_asrc_get_output_FIFO_size(index);
1586+	for (j = 0; j < size; j++) {
1587+		regmap_read(asrc->regmap, REG_ASRDO(index), &reg);
1588+		*(reg24) = reg;
1589+		reg24++;
1590+		regmap_read(asrc->regmap, REG_ASRDO(index), &reg);
1591+		*(reg24) = reg;
1592+		reg24++;
1593+	}
1594+	t_size += size;
1595+
1596+	m2m->dma_block[OUT].length = t_size * pair->channels * 4;
1597+
1598+	complete(&m2m->complete[OUT]);
1599+	complete(&m2m->complete[IN]);
1600+}
1601+#else
1602+static void fsl_asrc_submit_dma(struct fsl_asrc_pair *pair)
1603+{
1604+	struct fsl_asrc *asrc = pair->asrc;
1605+	struct fsl_asrc_m2m *m2m = pair->private_m2m;
1606+	enum asrc_pair_index index = pair->index;
1607+	u32 size = fsl_asrc_get_output_FIFO_size(pair);
1608+	int i;
1609+
1610+	/* Read all data in OUTPUT FIFO */
1611+	while (size) {
1612+		u32 val;
1613+		for (i = 0; i < size * pair->channels; i++)
1614+			regmap_read(asrc->regmap, REG_ASRDO(index), &val);
1615+		/* Fetch the data every 100us */
1616+		udelay(100);
1617+
1618+		size = fsl_asrc_get_output_FIFO_size(pair);
1619+	}
1620+
1621+	/* Submit DMA request */
1622+	dmaengine_submit(pair->desc[IN]);
1623+	dma_async_issue_pending(pair->desc[IN]->chan);
1624+
1625+	dmaengine_submit(pair->desc[OUT]);
1626+	dma_async_issue_pending(pair->desc[OUT]->chan);
1627+
1628+	/*
1629+	 * Clear DMA request during the stall state of ASRC:
1630+	 * During STALL state, the remaining in input fifo would never be
1631+	 * smaller than the input threshold while the output fifo would not
1632+	 * be bigger than output one. Thus the DMA request would be cleared.
1633+	 */
1634+	fsl_asrc_set_watermarks(pair, ASRC_FIFO_THRESHOLD_MIN,
1635+				ASRC_FIFO_THRESHOLD_MAX);
1636+
1637+	/* Update the real input threshold to raise DMA request */
1638+	fsl_asrc_set_watermarks(pair, m2m->watermark[IN], m2m->watermark[OUT]);
1639+}
1640+#endif /* ASRC_POLLING_WITHOUT_DMA */
1641+
1642+static long fsl_asrc_ioctl_req_pair(struct fsl_asrc_pair *pair,
1643+				    void __user *user)
1644+{
1645+	struct fsl_asrc *asrc = pair->asrc;
1646+	struct fsl_asrc_priv *asrc_priv = asrc->private;
1647+	struct fsl_asrc_m2m *m2m = pair->private_m2m;
1648+	struct device *dev = &asrc->pdev->dev;
1649+	struct asrc_req req;
1650+	unsigned long lock_flags;
1651+	long ret;
1652+
1653+	ret = copy_from_user(&req, user, sizeof(req));
1654+	if (ret) {
1655+		dev_err(dev, "failed to get req from user space: %ld\n", ret);
1656+		return ret;
1657+	}
1658+
1659+	ret = fsl_asrc_request_pair(req.chn_num, pair);
1660+	if (ret) {
1661+		dev_err(dev, "failed to request pair: %ld\n", ret);
1662+		return ret;
1663+	}
1664+
1665+	spin_lock_irqsave(&m2m->lock, lock_flags);
1666+	m2m->pair_hold = 1;
1667+	spin_unlock_irqrestore(&m2m->lock, lock_flags);
1668+	pair->channels = req.chn_num;
1669+
1670+	req.index = pair->index;
1671+	req.supported_in_format = FSL_ASRC_FORMATS | SNDRV_PCM_FMTBIT_S8;
1672+	req.supported_out_format = FSL_ASRC_FORMATS;
1673+	if (asrc_priv->soc->use_edma) {
1674+		req.supported_in_format &= ~SNDRV_PCM_FMTBIT_S24_3LE;
1675+		req.supported_out_format &= ~SNDRV_PCM_FMTBIT_S24_3LE;
1676+	}
1677+
1678+	ret = copy_to_user(user, &req, sizeof(req));
1679+	if (ret) {
1680+		dev_err(dev, "failed to send req to user space: %ld\n", ret);
1681+		return ret;
1682+	}
1683+
1684+	return 0;
1685+}
1686+
1687+static long fsl_asrc_ioctl_config_pair(struct fsl_asrc_pair *pair,
1688+				       void __user *user)
1689+{
1690+	struct fsl_asrc *asrc = pair->asrc;
1691+	struct fsl_asrc_m2m *m2m = pair->private_m2m;
1692+	struct fsl_asrc_pair_priv *pair_priv = pair->private;
1693+	struct device *dev = &asrc->pdev->dev;
1694+	struct asrc_config config;
1695+	enum asrc_pair_index index;
1696+	long ret;
1697+
1698+	ret = copy_from_user(&config, user, sizeof(config));
1699+	if (ret) {
1700+		dev_err(dev, "failed to get config from user space: %ld\n", ret);
1701+		return ret;
1702+	}
1703+
1704+	index = config.pair;
1705+
1706+	pair_priv->config = &config;
1707+	ret = fsl_asrc_config_pair(pair, true);
1708+	if (ret) {
1709+		pair_err("failed to config pair: %ld\n", ret);
1710+		return ret;
1711+	}
1712+
1713+	m2m->watermark[IN] = FSL_ASRC_INPUTFIFO_WML;
1714+	m2m->watermark[OUT] = FSL_ASRC_OUTPUTFIFO_WML;
1715+
1716+	fsl_asrc_set_watermarks(pair, m2m->watermark[IN], m2m->watermark[OUT]);
1717+
1718+	m2m->dma_block[IN].length = ASRC_DMA_BUFFER_SIZE;
1719+	m2m->dma_block[OUT].length = ASRC_DMA_BUFFER_SIZE;
1720+
1721+	m2m->word_format[IN] = config.input_format;
1722+	m2m->word_format[OUT] = config.output_format;
1723+
1724+	m2m->rate[IN] = config.input_sample_rate;
1725+	m2m->rate[OUT] = config.output_sample_rate;
1726+
1727+	m2m->last_period_size = ASRC_OUTPUT_LAST_SAMPLE;
1728+
1729+	ret = fsl_allocate_dma_buf(pair);
1730+	if (ret) {
1731+		pair_err("failed to allocate DMA buffer: %ld\n", ret);
1732+		return ret;
1733+	}
1734+
1735+	/* Request DMA channel for both input and output */
1736+	pair->dma_chan[IN] = fsl_asrc_get_dma_channel(pair, IN);
1737+	if (pair->dma_chan[IN] == NULL) {
1738+		pair_err("failed to request input task DMA channel\n");
1739+		return  -EBUSY;
1740+	}
1741+
1742+	pair->dma_chan[OUT] = fsl_asrc_get_dma_channel(pair, OUT);
1743+	if (pair->dma_chan[OUT] == NULL) {
1744+		pair_err("failed to request output task DMA channel\n");
1745+		return  -EBUSY;
1746+	}
1747+
1748+	ret = copy_to_user(user, &config, sizeof(config));
1749+	if (ret) {
1750+		pair_err("failed to send config to user space: %ld\n", ret);
1751+		return ret;
1752+	}
1753+
1754+	return 0;
1755+}
1756+
1757+static long fsl_asrc_ioctl_release_pair(struct fsl_asrc_pair *pair,
1758+					void __user *user)
1759+{
1760+	struct fsl_asrc_m2m *m2m = pair->private_m2m;
1761+	struct fsl_asrc *asrc = pair->asrc;
1762+	enum asrc_pair_index index;
1763+	unsigned long lock_flags;
1764+	long ret;
1765+
1766+	ret = copy_from_user(&index, user, sizeof(index));
1767+	if (ret) {
1768+		pair_err("failed to get index from user space: %ld\n", ret);
1769+		return ret;
1770+	}
1771+
1772+	/* index might be not valid due to some application failure. */
1773+	if (index < 0)
1774+		return -EINVAL;
1775+
1776+	m2m->asrc_active = 0;
1777+
1778+	spin_lock_irqsave(&m2m->lock, lock_flags);
1779+	m2m->pair_hold = 0;
1780+	spin_unlock_irqrestore(&m2m->lock, lock_flags);
1781+
1782+	if (pair->dma_chan[IN])
1783+		dma_release_channel(pair->dma_chan[IN]);
1784+	if (pair->dma_chan[OUT])
1785+		dma_release_channel(pair->dma_chan[OUT]);
1786+	kfree(m2m->dma_block[IN].dma_vaddr);
1787+	kfree(m2m->dma_block[OUT].dma_vaddr);
1788+	fsl_asrc_release_pair(pair);
1789+
1790+	return 0;
1791+}
1792+
1793+static long fsl_asrc_calc_last_period_size(struct fsl_asrc_pair *pair,
1794+					struct asrc_convert_buffer *pbuf)
1795+{
1796+	struct fsl_asrc_m2m *m2m = pair->private_m2m;
1797+	struct fsl_asrc *asrc = pair->asrc;
1798+	struct fsl_asrc_priv *asrc_priv = asrc->private;
1799+	unsigned int out_length;
1800+	unsigned int in_width, out_width;
1801+	unsigned int channels = pair->channels;
1802+	unsigned int in_samples, out_samples;
1803+	unsigned int last_period_size;
1804+	unsigned int remain;
1805+
1806+	in_width = snd_pcm_format_physical_width(m2m->word_format[IN]) / 8;
1807+	out_width = snd_pcm_format_physical_width(m2m->word_format[OUT]) / 8;
1808+
1809+	in_samples = pbuf->input_buffer_length / (in_width * channels);
1810+
1811+	out_samples = (m2m->rate[OUT] * in_samples / m2m->rate[IN]);
1812+
1813+	out_length = out_samples * out_width * channels;
1814+
1815+	last_period_size = pbuf->output_buffer_length / (out_width * channels)
1816+					- out_samples;
1817+
1818+	m2m->last_period_size = last_period_size + 1 + ASRC_OUTPUT_LAST_SAMPLE;
1819+
1820+	if (asrc_priv->soc->use_edma) {
1821+		remain = pbuf->output_buffer_length % (out_width * channels * m2m->watermark[OUT]);
1822+		if (remain)
1823+			m2m->last_period_size += remain / (out_width * channels);
1824+	}
1825+
1826+	return 0;
1827+}
1828+
1829+static long fsl_asrc_ioctl_convert(struct fsl_asrc_pair *pair,
1830+				   void __user *user)
1831+{
1832+	struct fsl_asrc_m2m *m2m = pair->private_m2m;
1833+	struct fsl_asrc *asrc = pair->asrc;
1834+	enum asrc_pair_index index = pair->index;
1835+	struct asrc_convert_buffer buf;
1836+	long ret;
1837+
1838+	ret = copy_from_user(&buf, user, sizeof(buf));
1839+	if (ret) {
1840+		pair_err("failed to get buf from user space: %ld\n", ret);
1841+		return ret;
1842+	}
1843+
1844+	fsl_asrc_calc_last_period_size(pair, &buf);
1845+
1846+	ret = fsl_asrc_prepare_buffer(pair, &buf);
1847+	if (ret) {
1848+		pair_err("failed to prepare buffer: %ld\n", ret);
1849+		return ret;
1850+	}
1851+
1852+	reinit_completion(&m2m->complete[IN]);
1853+	reinit_completion(&m2m->complete[OUT]);
1854+
1855+#ifdef ASRC_POLLING_WITHOUT_DMA
1856+	fsl_asrc_polling_debug(pair);
1857+#else
1858+	fsl_asrc_submit_dma(pair);
1859+#endif
1860+
1861+	ret = fsl_asrc_process_buffer(pair, &buf);
1862+	if (ret) {
1863+		if (ret != -ERESTARTSYS)
1864+			pair_err("failed to process buffer: %ld\n", ret);
1865+		return ret;
1866+	}
1867+
1868+	ret = copy_to_user(user, &buf, sizeof(buf));
1869+	if (ret) {
1870+		pair_err("failed to send buf to user space: %ld\n", ret);
1871+		return ret;
1872+	}
1873+
1874+	return 0;
1875+}
1876+
1877+static long fsl_asrc_ioctl_start_conv(struct fsl_asrc_pair *pair,
1878+				      void __user *user)
1879+{
1880+	struct fsl_asrc *asrc = pair->asrc;
1881+	struct fsl_asrc_m2m *m2m = pair->private_m2m;
1882+	enum asrc_pair_index index;
1883+	long ret;
1884+
1885+	ret = copy_from_user(&index, user, sizeof(index));
1886+	if (ret) {
1887+		pair_err("failed to get index from user space: %ld\n", ret);
1888+		return ret;
1889+	}
1890+
1891+	m2m->asrc_active = 1;
1892+	fsl_asrc_start_pair(pair);
1893+
1894+	return 0;
1895+}
1896+
1897+static long fsl_asrc_ioctl_stop_conv(struct fsl_asrc_pair *pair,
1898+				     void __user *user)
1899+{
1900+	struct fsl_asrc *asrc = pair->asrc;
1901+	struct fsl_asrc_m2m *m2m = pair->private_m2m;
1902+	enum asrc_pair_index index;
1903+	long ret;
1904+
1905+	ret = copy_from_user(&index, user, sizeof(index));
1906+	if (ret) {
1907+		pair_err("failed to get index from user space: %ld\n", ret);
1908+		return ret;
1909+	}
1910+
1911+	dmaengine_terminate_all(pair->dma_chan[IN]);
1912+	dmaengine_terminate_all(pair->dma_chan[OUT]);
1913+
1914+	fsl_asrc_stop_pair(pair);
1915+	m2m->asrc_active = 0;
1916+
1917+	return 0;
1918+}
1919+
1920+static long fsl_asrc_ioctl_status(struct fsl_asrc_pair *pair, void __user *user)
1921+{
1922+	struct fsl_asrc *asrc = pair->asrc;
1923+	enum asrc_pair_index index = pair->index;
1924+	struct asrc_status_flags flags;
1925+	long ret;
1926+
1927+	ret = copy_from_user(&flags, user, sizeof(flags));
1928+	if (ret) {
1929+		pair_err("failed to get flags from user space: %ld\n", ret);
1930+		return ret;
1931+	}
1932+
1933+	fsl_asrc_get_status(pair, &flags);
1934+
1935+	ret = copy_to_user(user, &flags, sizeof(flags));
1936+	if (ret) {
1937+		pair_err("failed to send flags to user space: %ld\n", ret);
1938+		return ret;
1939+	}
1940+
1941+	return 0;
1942+}
1943+
1944+static long fsl_asrc_ioctl_flush(struct fsl_asrc_pair *pair, void __user *user)
1945+{
1946+	struct fsl_asrc *asrc = pair->asrc;
1947+	enum asrc_pair_index index = pair->index;
1948+
1949+	/* Release DMA and request again */
1950+	dma_release_channel(pair->dma_chan[IN]);
1951+	dma_release_channel(pair->dma_chan[OUT]);
1952+
1953+	pair->dma_chan[IN] = fsl_asrc_get_dma_channel(pair, IN);
1954+	if (pair->dma_chan[IN] == NULL) {
1955+		pair_err("failed to request input task DMA channel\n");
1956+		return -EBUSY;
1957+	}
1958+
1959+	pair->dma_chan[OUT] = fsl_asrc_get_dma_channel(pair, OUT);
1960+	if (pair->dma_chan[OUT] == NULL) {
1961+		pair_err("failed to request output task DMA channel\n");
1962+		return -EBUSY;
1963+	}
1964+
1965+	return 0;
1966+}
1967+
1968+static long fsl_asrc_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
1969+{
1970+	struct fsl_asrc_pair *pair = file->private_data;
1971+	struct fsl_asrc *asrc = pair->asrc;
1972+	void __user *user = (void __user *)arg;
1973+	long ret = 0;
1974+
1975+	switch (cmd) {
1976+	case ASRC_REQ_PAIR:
1977+		ret = fsl_asrc_ioctl_req_pair(pair, user);
1978+		break;
1979+	case ASRC_CONFIG_PAIR:
1980+		ret = fsl_asrc_ioctl_config_pair(pair, user);
1981+		break;
1982+	case ASRC_RELEASE_PAIR:
1983+		ret = fsl_asrc_ioctl_release_pair(pair, user);
1984+		break;
1985+	case ASRC_CONVERT:
1986+		ret = fsl_asrc_ioctl_convert(pair, user);
1987+		break;
1988+	case ASRC_START_CONV:
1989+		ret = fsl_asrc_ioctl_start_conv(pair, user);
1990+		break;
1991+	case ASRC_STOP_CONV:
1992+		ret = fsl_asrc_ioctl_stop_conv(pair, user);
1993+		break;
1994+	case ASRC_STATUS:
1995+		ret = fsl_asrc_ioctl_status(pair, user);
1996+		break;
1997+	case ASRC_FLUSH:
1998+		ret = fsl_asrc_ioctl_flush(pair, user);
1999+		break;
2000+	default:
2001+		dev_err(&asrc->pdev->dev, "invalid ioctl cmd!\n");
2002+		break;
2003+	}
2004+
2005+	return ret;
2006+}
2007+
2008+static int fsl_asrc_open(struct inode *inode, struct file *file)
2009+{
2010+	struct miscdevice *asrc_miscdev = file->private_data;
2011+	struct fsl_asrc *asrc = dev_get_drvdata(asrc_miscdev->parent);
2012+	struct device *dev = &asrc->pdev->dev;
2013+	struct fsl_asrc_pair *pair;
2014+	struct fsl_asrc_m2m *m2m;
2015+	int ret;
2016+
2017+	ret = signal_pending(current);
2018+	if (ret) {
2019+		dev_err(dev, "current process has a signal pending\n");
2020+		return ret;
2021+	}
2022+
2023+	pair = kzalloc(sizeof(struct fsl_asrc_pair) + asrc->pair_priv_size, GFP_KERNEL);
2024+	if (!pair) {
2025+		dev_err(dev, "failed to allocate pair\n");
2026+		return -ENOMEM;
2027+	}
2028+
2029+	pair->private = (void *)pair + sizeof(struct fsl_asrc_pair);
2030+
2031+	m2m = kzalloc(sizeof(struct fsl_asrc_m2m), GFP_KERNEL);
2032+	if (!m2m) {
2033+		dev_err(dev, "failed to allocate m2m resource\n");
2034+		ret = -ENOMEM;
2035+		goto out;
2036+	}
2037+
2038+	pair->private_m2m = m2m;
2039+	pair->asrc = asrc;
2040+
2041+	spin_lock_init(&m2m->lock);
2042+	init_completion(&m2m->complete[IN]);
2043+	init_completion(&m2m->complete[OUT]);
2044+
2045+	file->private_data = pair;
2046+
2047+	pm_runtime_get_sync(dev);
2048+
2049+	return 0;
2050+out:
2051+	kfree(pair);
2052+
2053+	return ret;
2054+}
2055+
2056+static int fsl_asrc_close(struct inode *inode, struct file *file)
2057+{
2058+	struct fsl_asrc_pair *pair = file->private_data;
2059+	struct fsl_asrc_m2m *m2m = pair->private_m2m;
2060+	struct fsl_asrc *asrc = pair->asrc;
2061+	struct device *dev = &asrc->pdev->dev;
2062+	unsigned long lock_flags;
2063+
2064+	if (m2m->asrc_active) {
2065+		m2m->asrc_active = 0;
2066+
2067+		dmaengine_terminate_all(pair->dma_chan[IN]);
2068+		dmaengine_terminate_all(pair->dma_chan[OUT]);
2069+
2070+		fsl_asrc_stop_pair(pair);
2071+		fsl_asrc_input_dma_callback((void *)pair);
2072+		fsl_asrc_output_dma_callback((void *)pair);
2073+	}
2074+
2075+	spin_lock_irqsave(&m2m->lock, lock_flags);
2076+	if (m2m->pair_hold) {
2077+		m2m->pair_hold = 0;
2078+		spin_unlock_irqrestore(&m2m->lock, lock_flags);
2079+
2080+		if (pair->dma_chan[IN])
2081+			dma_release_channel(pair->dma_chan[IN]);
2082+		if (pair->dma_chan[OUT])
2083+			dma_release_channel(pair->dma_chan[OUT]);
2084+
2085+		kfree(m2m->dma_block[IN].dma_vaddr);
2086+		kfree(m2m->dma_block[OUT].dma_vaddr);
2087+
2088+		fsl_asrc_release_pair(pair);
2089+	} else
2090+		spin_unlock_irqrestore(&m2m->lock, lock_flags);
2091+
2092+	spin_lock_irqsave(&asrc->lock, lock_flags);
2093+	kfree(m2m);
2094+	kfree(pair);
2095+	spin_unlock_irqrestore(&asrc->lock, lock_flags);
2096+	file->private_data = NULL;
2097+
2098+	pm_runtime_put_sync(dev);
2099+
2100+	return 0;
2101+}
2102+
2103+static const struct file_operations asrc_fops = {
2104+	.owner		= THIS_MODULE,
2105+	.unlocked_ioctl	= fsl_asrc_ioctl,
2106+	.open		= fsl_asrc_open,
2107+	.release	= fsl_asrc_close,
2108+};
2109+
2110+static int fsl_asrc_m2m_init(struct fsl_asrc *asrc)
2111+{
2112+	struct device *dev = &asrc->pdev->dev;
2113+	struct fsl_asrc_priv *asrc_priv = asrc->private;
2114+	int ret;
2115+
2116+	asrc->asrc_miscdev.fops = &asrc_fops;
2117+	asrc->asrc_miscdev.parent = dev;
2118+	asrc->asrc_miscdev.name = asrc_priv->name;
2119+	asrc->asrc_miscdev.minor = MISC_DYNAMIC_MINOR;
2120+	ret = misc_register(&asrc->asrc_miscdev);
2121+	if (ret) {
2122+		dev_err(dev, "failed to register char device %d\n", ret);
2123+		return ret;
2124+	}
2125+
2126+	return 0;
2127+}
2128+
2129+static int fsl_asrc_m2m_remove(struct platform_device *pdev)
2130+{
2131+	struct fsl_asrc *asrc = dev_get_drvdata(&pdev->dev);
2132+
2133+	misc_deregister(&asrc->asrc_miscdev);
2134+	return 0;
2135+}
2136+
2137+#ifdef CONFIG_PM_SLEEP
2138+static void fsl_asrc_m2m_suspend(struct fsl_asrc *asrc)
2139+{
2140+	struct fsl_asrc_pair *pair;
2141+	struct fsl_asrc_m2m *m2m;
2142+	unsigned long lock_flags;
2143+	int i;
2144+
2145+	for (i = 0; i < ASRC_PAIR_MAX_NUM; i++) {
2146+		spin_lock_irqsave(&asrc->lock, lock_flags);
2147+		pair = asrc->pair[i];
2148+		if (!pair || !pair->private_m2m) {
2149+			spin_unlock_irqrestore(&asrc->lock, lock_flags);
2150+			continue;
2151+		}
2152+		m2m = pair->private_m2m;
2153+
2154+		if (!completion_done(&m2m->complete[IN])) {
2155+			if (pair->dma_chan[IN])
2156+				dmaengine_terminate_all(pair->dma_chan[IN]);
2157+			fsl_asrc_input_dma_callback((void *)pair);
2158+		}
2159+		if (!completion_done(&m2m->complete[OUT])) {
2160+			if (pair->dma_chan[OUT])
2161+				dmaengine_terminate_all(pair->dma_chan[OUT]);
2162+			fsl_asrc_output_dma_callback((void *)pair);
2163+		}
2164+
2165+		spin_unlock_irqrestore(&asrc->lock, lock_flags);
2166+	}
2167+}
2168+
2169+static void fsl_asrc_m2m_resume(struct fsl_asrc *asrc)
2170+{
2171+	struct fsl_asrc_pair *pair;
2172+	struct fsl_asrc_m2m *m2m;
2173+	unsigned long lock_flags;
2174+	enum asrc_pair_index index;
2175+	int i, j;
2176+
2177+	for (i = 0; i < ASRC_PAIR_MAX_NUM; i++) {
2178+		spin_lock_irqsave(&asrc->lock, lock_flags);
2179+		pair = asrc->pair[i];
2180+		if (!pair || !pair->private_m2m) {
2181+			spin_unlock_irqrestore(&asrc->lock, lock_flags);
2182+			continue;
2183+		}
2184+		m2m = pair->private_m2m;
2185+		index = pair->index;
2186+
2187+		for (j = 0; j < pair->channels * 4; j++)
2188+			regmap_write(asrc->regmap, REG_ASRDI(index), 0);
2189+
2190+		spin_unlock_irqrestore(&asrc->lock, lock_flags);
2191+	}
2192+}
2193+#endif
2194diff --git a/sound/soc/fsl/fsl_aud2htx.c b/sound/soc/fsl/fsl_aud2htx.c
2195new file mode 100644
2196index 000000000..bb689ed93
2197--- /dev/null
2198+++ b/sound/soc/fsl/fsl_aud2htx.c
2199@@ -0,0 +1,345 @@
2200+// SPDX-License-Identifier: GPL-2.0+
2201+//
2202+// Freescale ALSA SoC Digital Audio Interface (SAI) driver.
2203+//
2204+// Copyright 2012-2016 Freescale Semiconductor, Inc.
2205+
2206+#include <linux/clk.h>
2207+#include <linux/clk-provider.h>
2208+#include <linux/delay.h>
2209+#include <linux/dmaengine.h>
2210+#include <linux/module.h>
2211+#include <linux/of_device.h>
2212+#include <linux/of_address.h>
2213+#include <linux/pm_runtime.h>
2214+#include <linux/regmap.h>
2215+#include <linux/slab.h>
2216+#include <linux/time.h>
2217+#include <linux/pm_qos.h>
2218+#include <sound/core.h>
2219+#include <sound/dmaengine_pcm.h>
2220+#include <sound/pcm_params.h>
2221+#include <linux/dma-mapping.h>
2222+#include "fsl_aud2htx.h"
2223+#include "imx-pcm.h"
2224+
2225+static int fsl_aud2htx_hw_params(struct snd_pcm_substream *substream,
2226+				 struct snd_pcm_hw_params *params,
2227+				 struct snd_soc_dai *cpu_dai)
2228+{
2229+	struct fsl_aud2htx *aud2htx = snd_soc_dai_get_drvdata(cpu_dai);
2230+
2231+	regmap_update_bits(aud2htx->regmap, AUD2HTX_CTRL_EXT,
2232+			   AUD2HTX_CTRE_DT_MASK, 0);
2233+
2234+	regmap_update_bits(aud2htx->regmap, AUD2HTX_IRQ_MASK,
2235+			   AUD2HTX_WM_HIGH_IRQ_MASK |
2236+			   AUD2HTX_WM_LOW_IRQ_MASK |
2237+			   AUD2HTX_OVF_MASK,
2238+			   AUD2HTX_WM_HIGH_IRQ_MASK |
2239+			   AUD2HTX_WM_LOW_IRQ_MASK |
2240+			   AUD2HTX_OVF_MASK);
2241+
2242+	regmap_update_bits(aud2htx->regmap, AUD2HTX_CTRL_EXT,
2243+			   AUD2HTX_CTRE_WL_MASK,
2244+			   0x10 << AUD2HTX_CTRE_WL_SHIFT);
2245+	regmap_update_bits(aud2htx->regmap, AUD2HTX_CTRL_EXT,
2246+			   AUD2HTX_CTRE_WH_MASK,
2247+			   0x10 << AUD2HTX_CTRE_WH_SHIFT);
2248+	return 0;
2249+}
2250+
2251+static int fsl_aud2htx_trigger(struct snd_pcm_substream *substream, int cmd,
2252+			       struct snd_soc_dai *dai)
2253+{
2254+	struct fsl_aud2htx *aud2htx = snd_soc_dai_get_drvdata(dai);
2255+
2256+	switch (cmd) {
2257+	case SNDRV_PCM_TRIGGER_START:
2258+	case SNDRV_PCM_TRIGGER_RESUME:
2259+	case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
2260+		regmap_update_bits(aud2htx->regmap, AUD2HTX_CTRL,
2261+				   AUD2HTX_CTRL_EN, AUD2HTX_CTRL_EN);
2262+		regmap_update_bits(aud2htx->regmap, AUD2HTX_CTRL_EXT,
2263+				   AUD2HTX_CTRE_DE, AUD2HTX_CTRE_DE);
2264+		break;
2265+	case SNDRV_PCM_TRIGGER_SUSPEND:
2266+	case SNDRV_PCM_TRIGGER_STOP:
2267+	case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
2268+		regmap_update_bits(aud2htx->regmap, AUD2HTX_CTRL_EXT,
2269+				   AUD2HTX_CTRE_DE, 0);
2270+		regmap_update_bits(aud2htx->regmap, AUD2HTX_CTRL,
2271+				   AUD2HTX_CTRL_EN, 0);
2272+		break;
2273+	default:
2274+		return -EINVAL;
2275+	}
2276+	return 0;
2277+}
2278+
2279+static int fsl_aud2htx_set_dai_sysclk(struct snd_soc_dai *cpu_dai,
2280+				      int clk_id, unsigned int freq, int dir)
2281+{
2282+	return 0;
2283+}
2284+
2285+static int fsl_aud2htx_set_dai_fmt(struct snd_soc_dai *cpu_dai,
2286+				   unsigned int fmt)
2287+{
2288+	return 0;
2289+}
2290+
2291+static int fsl_aud2htx_set_dai_tdm_slot(struct snd_soc_dai *cpu_dai,
2292+					u32 tx_mask,
2293+					u32 rx_mask, int slots, int slot_width)
2294+{
2295+	return 0;
2296+}
2297+
2298+static const struct snd_soc_dai_ops fsl_aud2htx_dai_ops = {
2299+	.hw_params	= fsl_aud2htx_hw_params,
2300+	.trigger	= fsl_aud2htx_trigger,
2301+	.set_sysclk	= fsl_aud2htx_set_dai_sysclk,
2302+	.set_fmt	= fsl_aud2htx_set_dai_fmt,
2303+	.set_tdm_slot	= fsl_aud2htx_set_dai_tdm_slot,
2304+};
2305+
2306+static int fsl_aud2htx_dai_probe(struct snd_soc_dai *cpu_dai)
2307+{
2308+	struct fsl_aud2htx *aud2htx = dev_get_drvdata(cpu_dai->dev);
2309+
2310+	snd_soc_dai_init_dma_data(cpu_dai, &aud2htx->dma_params_tx,
2311+				  &aud2htx->dma_params_rx);
2312+
2313+	return 0;
2314+}
2315+
2316+static struct snd_soc_dai_driver fsl_aud2htx_dai = {
2317+	.probe = fsl_aud2htx_dai_probe,
2318+	.playback = {
2319+		.stream_name = "CPU-Playback",
2320+		.channels_min = 2,
2321+		.channels_max = 8,
2322+		.rates = SNDRV_PCM_RATE_32000 |
2323+			 SNDRV_PCM_RATE_44100 |
2324+			 SNDRV_PCM_RATE_48000 |
2325+			 SNDRV_PCM_RATE_88200 |
2326+			 SNDRV_PCM_RATE_96000 |
2327+			 SNDRV_PCM_RATE_176400 |
2328+			 SNDRV_PCM_RATE_192000,
2329+		.formats = FSL_AUD2HTX_FORMATS,
2330+	},
2331+	.ops = &fsl_aud2htx_dai_ops,
2332+};
2333+
2334+static const struct snd_soc_component_driver fsl_aud2htx_component = {
2335+	.name	= "fsl-aud2htx",
2336+};
2337+
2338+static const struct reg_default fsl_aud2htx_reg_defaults[] = {
2339+	{AUD2HTX_CTRL,		0x00000000},
2340+	{AUD2HTX_CTRL_EXT,	0x00000000},
2341+	{AUD2HTX_WR,		0x00000000},
2342+	{AUD2HTX_STATUS,	0x00000000},
2343+	{AUD2HTX_IRQ_NOMASK,	0x00000000},
2344+	{AUD2HTX_IRQ_MASKED,	0x00000000},
2345+	{AUD2HTX_IRQ_MASK,	0x00000000},
2346+};
2347+
2348+static bool fsl_aud2htx_readable_reg(struct device *dev, unsigned int reg)
2349+{
2350+	switch (reg) {
2351+	case AUD2HTX_CTRL:
2352+	case AUD2HTX_CTRL_EXT:
2353+	case AUD2HTX_STATUS:
2354+	case AUD2HTX_IRQ_NOMASK:
2355+	case AUD2HTX_IRQ_MASKED:
2356+	case AUD2HTX_IRQ_MASK:
2357+		return true;
2358+	default:
2359+		return false;
2360+	}
2361+}
2362+
2363+static bool fsl_aud2htx_writeable_reg(struct device *dev, unsigned int reg)
2364+{
2365+	switch (reg) {
2366+	case AUD2HTX_CTRL:
2367+	case AUD2HTX_CTRL_EXT:
2368+	case AUD2HTX_WR:
2369+	case AUD2HTX_IRQ_NOMASK:
2370+	case AUD2HTX_IRQ_MASKED:
2371+	case AUD2HTX_IRQ_MASK:
2372+		return true;
2373+	default:
2374+		return false;
2375+	}
2376+}
2377+
2378+static bool fsl_aud2htx_volatile_reg(struct device *dev, unsigned int reg)
2379+{
2380+	switch (reg) {
2381+	case AUD2HTX_STATUS:
2382+	case AUD2HTX_IRQ_NOMASK:
2383+	case AUD2HTX_IRQ_MASKED:
2384+		return true;
2385+	default:
2386+		return false;
2387+	}
2388+}
2389+
2390+static const struct regmap_config fsl_aud2htx_regmap_config = {
2391+	.reg_bits = 32,
2392+	.reg_stride = 4,
2393+	.val_bits = 32,
2394+
2395+	.max_register = AUD2HTX_IRQ_MASK,
2396+	.reg_defaults = fsl_aud2htx_reg_defaults,
2397+	.num_reg_defaults = ARRAY_SIZE(fsl_aud2htx_reg_defaults),
2398+	.readable_reg = fsl_aud2htx_readable_reg,
2399+	.volatile_reg = fsl_aud2htx_volatile_reg,
2400+	.writeable_reg = fsl_aud2htx_writeable_reg,
2401+	.cache_type = REGCACHE_RBTREE,
2402+};
2403+
2404+static const struct of_device_id fsl_aud2htx_dt_ids[] = {
2405+	{ .compatible = "fsl,imx8mp-aud2htx",},
2406+	{}
2407+};
2408+
2409+MODULE_DEVICE_TABLE(of, fsl_aud2htx_dt_ids);
2410+
2411+static irqreturn_t fsl_aud2htx_isr(int irq, void *dev_id)
2412+{
2413+	return IRQ_HANDLED;
2414+}
2415+
2416+static int fsl_aud2htx_probe(struct platform_device *pdev)
2417+{
2418+	struct fsl_aud2htx *aud2htx;
2419+	struct resource *res;
2420+	struct device_node *np;
2421+	void __iomem *regs;
2422+	int ret, irq;
2423+
2424+	aud2htx = devm_kzalloc(&pdev->dev, sizeof(*aud2htx), GFP_KERNEL);
2425+	if (!aud2htx)
2426+		return -ENOMEM;
2427+
2428+	aud2htx->pdev = pdev;
2429+	np = pdev->dev.of_node;
2430+
2431+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
2432+	regs = devm_ioremap_resource(&pdev->dev, res);
2433+	if (IS_ERR(regs)) {
2434+		dev_err(&pdev->dev, "failed ioremap\n");
2435+		return PTR_ERR(regs);
2436+	}
2437+
2438+	aud2htx->regmap = devm_regmap_init_mmio_clk(&pdev->dev, NULL, regs,
2439+						    &fsl_aud2htx_regmap_config);
2440+	if (IS_ERR(aud2htx->regmap)) {
2441+		dev_err(&pdev->dev, "failed to init regmap");
2442+		return PTR_ERR(aud2htx->regmap);
2443+	}
2444+
2445+	irq = platform_get_irq(pdev, 0);
2446+	if (irq < 0) {
2447+		dev_err(&pdev->dev, "no irq for node %s\n",
2448+			dev_name(&pdev->dev));
2449+		return irq;
2450+	}
2451+
2452+	ret = devm_request_irq(&pdev->dev, irq, fsl_aud2htx_isr, 0,
2453+			       dev_name(&pdev->dev), aud2htx);
2454+	if (ret) {
2455+		dev_err(&pdev->dev, "failed to claim irq %u: %d\n", irq, ret);
2456+		return ret;
2457+	}
2458+
2459+	aud2htx->bus_clk = devm_clk_get(&pdev->dev, "bus");
2460+	if (IS_ERR(aud2htx->bus_clk)) {
2461+		dev_err(&pdev->dev, "failed to get mem clock\n");
2462+		return PTR_ERR(aud2htx->bus_clk);
2463+	}
2464+
2465+	aud2htx->dma_params_tx.chan_name = "tx";
2466+	aud2htx->dma_params_tx.maxburst = 16;
2467+	aud2htx->dma_params_tx.addr = res->start + AUD2HTX_WR;
2468+
2469+	platform_set_drvdata(pdev, aud2htx);
2470+	pm_runtime_enable(&pdev->dev);
2471+
2472+	regcache_cache_only(aud2htx->regmap, true);
2473+
2474+	ret = devm_snd_soc_register_component(&pdev->dev,
2475+					      &fsl_aud2htx_component,
2476+					      &fsl_aud2htx_dai, 1);
2477+	if (ret) {
2478+		dev_err(&pdev->dev, "failed to register ASoC DAI\n");
2479+		return ret;
2480+	}
2481+
2482+	ret = imx_pcm_dma_init(pdev, IMX_DEFAULT_DMABUF_SIZE);
2483+	if (ret)
2484+		dev_err(&pdev->dev, "failed to init imx pcm dma: %d\n", ret);
2485+
2486+	return ret;
2487+}
2488+
2489+static int fsl_aud2htx_remove(struct platform_device *pdev)
2490+{
2491+	pm_runtime_disable(&pdev->dev);
2492+
2493+	return 0;
2494+}
2495+
2496+#ifdef CONFIG_PM
2497+static int fsl_aud2htx_runtime_suspend(struct device *dev)
2498+{
2499+	struct fsl_aud2htx *aud2htx = dev_get_drvdata(dev);
2500+
2501+	regcache_cache_only(aud2htx->regmap, true);
2502+	clk_disable_unprepare(aud2htx->bus_clk);
2503+
2504+	return 0;
2505+}
2506+
2507+static int fsl_aud2htx_runtime_resume(struct device *dev)
2508+{
2509+	struct fsl_aud2htx *aud2htx = dev_get_drvdata(dev);
2510+	int ret;
2511+
2512+	ret = clk_prepare_enable(aud2htx->bus_clk);
2513+	if (ret)
2514+		return ret;
2515+
2516+	regcache_cache_only(aud2htx->regmap, false);
2517+	regcache_mark_dirty(aud2htx->regmap);
2518+	regcache_sync(aud2htx->regmap);
2519+
2520+	return 0;
2521+}
2522+#endif /*CONFIG_PM*/
2523+
2524+static const struct dev_pm_ops fsl_aud2htx_pm_ops = {
2525+	SET_RUNTIME_PM_OPS(fsl_aud2htx_runtime_suspend,
2526+			   fsl_aud2htx_runtime_resume,
2527+			   NULL)
2528+	SET_SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend,
2529+				pm_runtime_force_resume)
2530+};
2531+
2532+static struct platform_driver fsl_aud2htx_driver = {
2533+	.probe = fsl_aud2htx_probe,
2534+	.remove = fsl_aud2htx_remove,
2535+	.driver = {
2536+		.name = "fsl-aud2htx",
2537+		.pm = &fsl_aud2htx_pm_ops,
2538+		.of_match_table = fsl_aud2htx_dt_ids,
2539+	},
2540+};
2541+module_platform_driver(fsl_aud2htx_driver);
2542+
2543+MODULE_DESCRIPTION("NXP AUD2HTX driver");
2544+MODULE_LICENSE("GPL v2");
2545diff --git a/sound/soc/fsl/fsl_aud2htx.h b/sound/soc/fsl/fsl_aud2htx.h
2546new file mode 100644
2547index 000000000..8348e5e62
2548--- /dev/null
2549+++ b/sound/soc/fsl/fsl_aud2htx.h
2550@@ -0,0 +1,50 @@
2551+/* SPDX-License-Identifier: GPL-2.0 */
2552+/*
2553+ * Copyright (C) 2019 NXP
2554+ */
2555+
2556+#ifndef _FSL_AUD2HTX_H
2557+#define _FSL_AUD2HTX_H
2558+
2559+#define FSL_AUD2HTX_FORMATS (SNDRV_PCM_FMTBIT_S24_LE | \
2560+			     SNDRV_PCM_FMTBIT_S32_LE)
2561+
2562+#define AUD2HTX_CTRL          0x0
2563+#define AUD2HTX_CTRL_EXT      0x4
2564+#define AUD2HTX_WR            0x8
2565+#define AUD2HTX_STATUS        0xC
2566+#define AUD2HTX_IRQ_NOMASK    0x10
2567+#define AUD2HTX_IRQ_MASKED    0x14
2568+#define AUD2HTX_IRQ_MASK      0x18
2569+
2570+#define AUD2HTX_CTRL_EN          BIT(0)
2571+#define AUD2HTX_CTRE_DE          BIT(0)
2572+#define AUD2HTX_CTRE_DT_SHIFT    0x1
2573+#define AUD2HTX_CTRE_DT_WIDTH    0x2
2574+#define AUD2HTX_CTRE_DT_MASK     ((BIT(AUD2HTX_CTRE_DT_WIDTH) - 1) \
2575+				 << AUD2HTX_CTRE_DT_SHIFT)
2576+
2577+#define AUD2HTX_CTRE_WL_SHIFT    16
2578+#define AUD2HTX_CTRE_WL_WIDTH    5
2579+#define AUD2HTX_CTRE_WL_MASK     ((BIT(AUD2HTX_CTRE_WL_WIDTH) - 1) \
2580+				 << AUD2HTX_CTRE_WL_SHIFT)
2581+
2582+#define AUD2HTX_CTRE_WH_SHIFT    24
2583+#define AUD2HTX_CTRE_WH_WIDTH    5
2584+#define AUD2HTX_CTRE_WH_MASK     ((BIT(AUD2HTX_CTRE_WH_WIDTH) - 1) \
2585+				 << AUD2HTX_CTRE_WH_SHIFT)
2586+
2587+#define AUD2HTX_WM_HIGH_IRQ_MASK BIT(2)
2588+#define AUD2HTX_WM_LOW_IRQ_MASK  BIT(1)
2589+#define AUD2HTX_OVF_MASK         BIT(0)
2590+
2591+struct fsl_aud2htx {
2592+	struct platform_device *pdev;
2593+	struct regmap *regmap;
2594+	struct clk *bus_clk;
2595+
2596+	struct snd_dmaengine_dai_dma_data dma_params_rx;
2597+	struct snd_dmaengine_dai_dma_data dma_params_tx;
2598+};
2599+
2600+#endif /* _FSL_AUD2HTX_H */
2601diff --git a/sound/soc/fsl/fsl_audmix.c b/sound/soc/fsl/fsl_audmix.c
2602index 7ad592577..c44406ff1 100644
2603--- a/sound/soc/fsl/fsl_audmix.c
2604+++ b/sound/soc/fsl/fsl_audmix.c
2605@@ -199,18 +199,10 @@ static int fsl_audmix_put_out_src(struct snd_kcontrol *kcontrol,
2606
2607 static const struct snd_kcontrol_new fsl_audmix_snd_controls[] = {
2608 	/* FSL_AUDMIX_CTR controls */
2609-	{	.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
2610-		.name = "Mixing Clock Source",
2611-		.info = snd_soc_info_enum_double,
2612-		.access = SNDRV_CTL_ELEM_ACCESS_WRITE,
2613-		.put = fsl_audmix_put_mix_clk_src,
2614-		.private_value = (unsigned long)&fsl_audmix_enum[0] },
2615-	{	.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
2616-		.name = "Output Source",
2617-		.info = snd_soc_info_enum_double,
2618-		.access = SNDRV_CTL_ELEM_ACCESS_WRITE,
2619-		.put = fsl_audmix_put_out_src,
2620-		.private_value = (unsigned long)&fsl_audmix_enum[1] },
2621+	SOC_ENUM_EXT("Mixing Clock Source", fsl_audmix_enum[0],
2622+		     snd_soc_get_enum_double, fsl_audmix_put_mix_clk_src),
2623+	SOC_ENUM_EXT("Output Source", fsl_audmix_enum[1],
2624+		     snd_soc_get_enum_double, fsl_audmix_put_out_src),
2625 	SOC_ENUM("Output Width", fsl_audmix_enum[2]),
2626 	SOC_ENUM("Frame Rate Diff Error", fsl_audmix_enum[3]),
2627 	SOC_ENUM("Clock Freq Diff Error", fsl_audmix_enum[4]),
2628@@ -485,7 +477,7 @@ static int fsl_audmix_probe(struct platform_device *pdev)
2629 	if (IS_ERR(regs))
2630 		return PTR_ERR(regs);
2631
2632-	priv->regmap = devm_regmap_init_mmio_clk(dev, "ipg", regs,
2633+	priv->regmap = devm_regmap_init_mmio_clk(dev, NULL, regs,
2634 						 &fsl_audmix_regmap_config);
2635 	if (IS_ERR(priv->regmap)) {
2636 		dev_err(dev, "failed to init regmap\n");
2637diff --git a/sound/soc/fsl/fsl_dsd.h b/sound/soc/fsl/fsl_dsd.h
2638new file mode 100644
2639index 000000000..a45f31422
2640--- /dev/null
2641+++ b/sound/soc/fsl/fsl_dsd.h
2642@@ -0,0 +1,58 @@
2643+/*
2644+ * Copyright 2018 NXP
2645+ *
2646+ * This program is free software; you can redistribute it and/or modify
2647+ * it under the terms of the GNU General Public License version 2 as
2648+ * published by the Free Software Foundation.
2649+ */
2650+
2651+#ifndef __FSL_DSD_H
2652+#define __FSL_DSD_H
2653+
2654+#include <linux/pinctrl/consumer.h>
2655+#include <sound/pcm_params.h>
2656+#include <sound/soc.h>
2657+
2658+static bool fsl_is_dsd(struct snd_pcm_hw_params *params)
2659+{
2660+	snd_pcm_format_t format = params_format(params);
2661+
2662+	switch (format) {
2663+	case SNDRV_PCM_FORMAT_DSD_U8:
2664+	case SNDRV_PCM_FORMAT_DSD_U16_LE:
2665+	case SNDRV_PCM_FORMAT_DSD_U16_BE:
2666+	case SNDRV_PCM_FORMAT_DSD_U32_LE:
2667+	case SNDRV_PCM_FORMAT_DSD_U32_BE:
2668+		return true;
2669+	default:
2670+		return false;
2671+	}
2672+}
2673+
2674+static inline struct pinctrl_state *fsl_get_pins_state(struct pinctrl *pinctrl,
2675+	struct snd_pcm_hw_params *params, u32 bclk)
2676+{
2677+	struct pinctrl_state *state = 0;
2678+
2679+	if (fsl_is_dsd(params)) {
2680+		/* DSD512@44.1kHz, DSD512@48kHz */
2681+		if (bclk >= 22579200)
2682+			state = pinctrl_lookup_state(pinctrl, "dsd512");
2683+
2684+		/* Get default DSD state */
2685+		if (IS_ERR_OR_NULL(state))
2686+			state = pinctrl_lookup_state(pinctrl, "dsd");
2687+	} else {
2688+		/* 706k32b2c, 768k32b2c, etc */
2689+		if (bclk >= 45158400)
2690+			state = pinctrl_lookup_state(pinctrl, "pcm_b2m");
2691+	}
2692+
2693+	/* Get default state */
2694+	if (IS_ERR_OR_NULL(state))
2695+		state = pinctrl_lookup_state(pinctrl, "default");
2696+
2697+	return state;
2698+}
2699+
2700+#endif /* __FSL_DSD_H */
2701diff --git a/sound/soc/fsl/fsl_dsp.c b/sound/soc/fsl/fsl_dsp.c
2702new file mode 100644
2703index 000000000..c5400bfb5
2704--- /dev/null
2705+++ b/sound/soc/fsl/fsl_dsp.c
2706@@ -0,0 +1,1748 @@
2707+/*
2708+ * Freescale DSP driver
2709+ *
2710+ * Copyright (c) 2012-2013 by Tensilica Inc. ALL RIGHTS RESERVED.
2711+ * Copyright 2018-2020 NXP
2712+ *
2713+ * Permission is hereby granted, free of charge, to any person obtaining a copy
2714+ * of this software and associated documentation files (the "Software"), to deal
2715+ * in the Software without restriction, including without limitation the rights
2716+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
2717+ * copies of the Software, and to permit persons to whom the Software is
2718+ * furnished to do so, subject to the following conditions:
2719+ *
2720+ * The above copyright notice and this permission notice shall be included in
2721+ * all copies or substantial portions of the Software.
2722+ *
2723+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
2724+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
2725+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
2726+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
2727+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
2728+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
2729+ * THE SOFTWARE.
2730+ *
2731+ * Copyright (c) 2001 William L. Pitts
2732+ * All rights reserved.
2733+ *
2734+ * Redistribution and use in source and binary forms are freely
2735+ * permitted provided that the above copyright notice and this
2736+ * paragraph and the following disclaimer are duplicated in all
2737+ * such forms.
2738+ *
2739+ * This software is provided "AS IS" and without any express or
2740+ * implied warranties, including, without limitation, the implied
2741+ * warranties of merchantability and fitness for a particular
2742+ * purpose.
2743+ *
2744+ */
2745+
2746+#include <linux/clk.h>
2747+#include <linux/delay.h>
2748+#include <linux/dma-mapping.h>
2749+#include <linux/module.h>
2750+#include <linux/firmware.h>
2751+#include <linux/interrupt.h>
2752+#include <linux/file.h>
2753+#include <linux/of_platform.h>
2754+#include <linux/of_address.h>
2755+#include <linux/of_irq.h>
2756+#include <linux/slab.h>
2757+#include <linux/platform_data/dma-imx.h>
2758+#include <linux/miscdevice.h>
2759+#include <linux/fs.h>
2760+#include <linux/pm_runtime.h>
2761+#include <linux/pm_domain.h>
2762+#include <linux/uaccess.h>
2763+#include <linux/poll.h>
2764+#ifdef CONFIG_COMPAT
2765+#include <linux/compat.h>
2766+#endif
2767+#include <uapi/linux/mxc_dsp.h>
2768+#include <linux/firmware/imx/svc/misc.h>
2769+#include <dt-bindings/firmware/imx/rsrc.h>
2770+#include <linux/mfd/syscon.h>
2771+
2772+#include <sound/pcm.h>
2773+#include <sound/soc.h>
2774+#include <linux/arm-smccc.h>
2775+
2776+#include "fsl_dsp.h"
2777+#include "fsl_dsp_pool.h"
2778+#include "fsl_dsp_xaf_api.h"
2779+
2780+/* ...allocate new client */
2781+struct xf_client *xf_client_alloc(struct fsl_dsp *dsp_priv)
2782+{
2783+	struct xf_client *client;
2784+	u32             id;
2785+
2786+	id = dsp_priv->xf_client_map[0].next;
2787+
2788+	/* ...try to allocate a client handle */
2789+	if (id != 0) {
2790+		/* ...allocate client memory */
2791+		client = kmalloc(sizeof(*client), GFP_KERNEL);
2792+		if (!client)
2793+			return ERR_PTR(-ENOMEM);
2794+
2795+		/* ...advance the head of free clients */
2796+		dsp_priv->xf_client_map[0].next =
2797+				dsp_priv->xf_client_map[id].next;
2798+
2799+		/* ...put associate client id with given object */
2800+		dsp_priv->xf_client_map[id].client = client;
2801+
2802+		/* ...mark client is not yet bound to proxy */
2803+		client->proxy = NULL;
2804+
2805+		/* ...save global proxy client identifier */
2806+		client->id = id;
2807+
2808+		return client;
2809+	}
2810+
2811+	/* ...number of clients exceeded */
2812+	return ERR_PTR(-EBUSY);
2813+}
2814+
2815+/* ...recycle client object */
2816+static inline void xf_client_free(struct xf_client *client)
2817+{
2818+	int     id = client->id;
2819+	struct fsl_dsp *dsp_priv = (struct fsl_dsp *)client->global;
2820+
2821+	/* ...put proxy client id into free clients list */
2822+	dsp_priv->xf_client_map[id].next = dsp_priv->xf_client_map[0].next;
2823+	dsp_priv->xf_client_map[0].next = id;
2824+
2825+	/* ...destroy client data */
2826+	kfree(client);
2827+}
2828+
2829+/* ...lookup client basing on id */
2830+struct xf_client *xf_client_lookup(struct fsl_dsp *dsp_priv, u32 id)
2831+{
2832+	if ((id >= XF_CFG_MAX_IPC_CLIENTS) ||
2833+		(dsp_priv->xf_client_map[id].next < XF_CFG_MAX_IPC_CLIENTS)
2834+	   )
2835+		return NULL;
2836+	else
2837+		return dsp_priv->xf_client_map[id].client;
2838+}
2839+
2840+/* ...helper function for retrieving the client handle */
2841+static inline struct xf_client *xf_get_client(struct file *file)
2842+{
2843+	struct xf_client *client;
2844+	u32             id;
2845+
2846+	client = (struct xf_client *)file->private_data;
2847+	if (!client)
2848+		return ERR_PTR(-EINVAL);
2849+
2850+	id = client->id;
2851+	if (id >= XF_CFG_MAX_IPC_CLIENTS)
2852+		return ERR_PTR(-EINVAL);
2853+
2854+	return client;
2855+}
2856+
2857+static int fsl_dsp_client_register(struct xf_client *client)
2858+{
2859+	struct fsl_dsp *dsp_priv;
2860+	struct device *dev;
2861+
2862+	dsp_priv = (struct fsl_dsp *)client->global;
2863+	dev = dsp_priv->dev;
2864+
2865+	/* ...make sure client is not registered yet */
2866+	if (client->proxy != NULL) {
2867+		pr_err("client-%x already registered", client->id);
2868+		return -EBUSY;
2869+	}
2870+
2871+	/* ...complete association (no communication with remote proxy here) */
2872+	client->proxy = &dsp_priv->proxy;
2873+
2874+	pr_debug("client-%x registered within proxy", client->id);
2875+
2876+	return 0;
2877+}
2878+
2879+/* ...unregister client from shared memory interface */
2880+static int fsl_dsp_client_unregister(struct xf_client *client)
2881+{
2882+	struct xf_proxy *proxy = client->proxy;
2883+
2884+	/* ...make sure client is registered */
2885+	if (proxy == NULL) {
2886+		pr_err("client-%x is not registered", client->id);
2887+		return -EBUSY;
2888+	}
2889+
2890+	/* ...just clean proxy reference */
2891+	client->proxy = NULL;
2892+
2893+	pr_debug("client-%x registered within proxy", client->id);
2894+
2895+	return 0;
2896+}
2897+
2898+static int fsl_dsp_ipc_msg_to_dsp(struct xf_client *client,
2899+							void __user *user)
2900+{
2901+	struct fsl_dsp *dsp_priv = (struct fsl_dsp *)client->global;
2902+	struct device *dev = dsp_priv->dev;
2903+	struct xf_proxy_message msg;
2904+	void *buffer;
2905+	unsigned long ret = 0;
2906+
2907+	ret = copy_from_user(&msg, user, sizeof(struct xf_proxy_message));
2908+	if (ret) {
2909+		dev_err(dev, "failed to get message from user space\n");
2910+		return -EFAULT;
2911+	}
2912+
2913+	/* ...make sure message pointer is sane */
2914+	buffer = xf_proxy_a2b(&dsp_priv->proxy, msg.address);
2915+	if (buffer == (void *)-1)
2916+		return -EFAULT;
2917+
2918+	/* Remapping from ARM core to DSP core's view */
2919+	if (msg.opcode == XF_LOAD_LIB) {
2920+		struct icm_xtlib_pil_info *icm_info;
2921+
2922+		icm_info = (struct icm_xtlib_pil_info *)buffer;
2923+		icm_info->pil_info.dst_addr      -= dsp_priv->sdram_reserved_alias;
2924+		icm_info->pil_info.dst_data_addr -= dsp_priv->sdram_reserved_alias;
2925+		icm_info->pil_info.start_sym     -= dsp_priv->sdram_reserved_alias;
2926+		icm_info->pil_info.text_addr     -= dsp_priv->sdram_reserved_alias;
2927+		icm_info->pil_info.init          -= dsp_priv->sdram_reserved_alias;
2928+		icm_info->pil_info.fini          -= dsp_priv->sdram_reserved_alias;
2929+		icm_info->pil_info.rel           -= dsp_priv->sdram_reserved_alias;
2930+		icm_info->pil_info.hash          -= dsp_priv->sdram_reserved_alias;
2931+		icm_info->pil_info.symtab        -= dsp_priv->sdram_reserved_alias;
2932+		icm_info->pil_info.strtab        -= dsp_priv->sdram_reserved_alias;
2933+	}
2934+
2935+	/* ...put current proxy client into message session id */
2936+	msg.session_id = XF_MSG_AP_FROM_USER(msg.session_id, client->id);
2937+
2938+	xf_cmd_send(&dsp_priv->proxy,
2939+				msg.session_id,
2940+				msg.opcode,
2941+				buffer,
2942+				msg.length);
2943+
2944+	return 0;
2945+}
2946+
2947+static int fsl_dsp_ipc_msg_from_dsp(struct xf_client *client,
2948+							void __user *user)
2949+{
2950+	struct fsl_dsp *dsp_priv = (struct fsl_dsp *)client->global;
2951+	struct device *dev = dsp_priv->dev;
2952+	struct xf_message *m;
2953+	struct xf_proxy_message msg;
2954+	unsigned long ret = 0;
2955+
2956+	m = xf_cmd_recv(&dsp_priv->proxy, &client->wait, &client->queue, 0);
2957+	if (IS_ERR(m)) {
2958+		xf_unlock(&dsp_priv->proxy.lock);
2959+		dev_err(dev, "receiving failed: %d", (int)PTR_ERR(m));
2960+		return PTR_ERR(m);
2961+	}
2962+
2963+	/* ...check if there is a response available */
2964+	if (m == NULL)
2965+		return -EAGAIN;
2966+
2967+	/* ...prepare message parameters (lock is taken) */
2968+	msg.session_id = XF_MSG_AP_TO_USER(m->id);
2969+	msg.opcode = m->opcode;
2970+	msg.length = m->length;
2971+	msg.address = xf_proxy_b2a(&dsp_priv->proxy, m->buffer);
2972+	msg.ret = m->ret;
2973+
2974+	/* ...return the message back to a pool and release lock */
2975+	xf_msg_free(&dsp_priv->proxy, m);
2976+	xf_unlock(&dsp_priv->proxy.lock);
2977+
2978+	ret = copy_to_user(user, &msg, sizeof(struct xf_proxy_message));
2979+	if (ret) {
2980+		dev_err(dev, "failed to response message to user space\n");
2981+		return -EFAULT;
2982+	}
2983+
2984+	return 0;
2985+}
2986+
2987+static int fsl_dsp_get_shmem_info(struct xf_client *client,
2988+							void __user *user)
2989+{
2990+	struct fsl_dsp *dsp_priv = (struct fsl_dsp *)client->global;
2991+	struct device *dev = dsp_priv->dev;
2992+	struct shmem_info mem_info;
2993+	unsigned long ret = 0;
2994+
2995+	mem_info.phys_addr = dsp_priv->scratch_buf_phys;
2996+	mem_info.size = dsp_priv->scratch_buf_size;
2997+
2998+	ret = copy_to_user(user, &mem_info, sizeof(struct shmem_info));
2999+	if (ret) {
3000+		dev_err(dev, "failed to response message to user space\n");
3001+		return -EFAULT;
3002+	}
3003+
3004+	return ret;
3005+}
3006+
3007+static struct miscdevice dsp_miscdev = {
3008+	.name	= "mxc_hifi4",
3009+	.minor	= MISC_DYNAMIC_MINOR,
3010+};
3011+
3012+static long fsl_dsp_ioctl(struct file *file, unsigned int cmd,
3013+						unsigned long arg)
3014+{
3015+	struct xf_client *client;
3016+	struct fsl_dsp *dsp_priv;
3017+	struct xf_proxy  *proxy;
3018+	struct device *dev;
3019+	void __user *user;
3020+	long ret = 0;
3021+
3022+	/* ...basic sanity checks */
3023+	client = xf_get_client(file);
3024+	if (IS_ERR(client))
3025+		return PTR_ERR(client);
3026+
3027+	dsp_priv = (struct fsl_dsp *)client->global;
3028+	proxy = &dsp_priv->proxy;
3029+	dev = dsp_priv->dev;
3030+	user = (void __user *)arg;
3031+
3032+	mutex_lock(&dsp_priv->dsp_mutex);
3033+
3034+	if (!proxy->is_ready) {
3035+		mutex_unlock(&dsp_priv->dsp_mutex);
3036+		dev_err(dev, "dsp firmware is not ready\n");
3037+		return -EFAULT;
3038+	}
3039+
3040+	switch (cmd) {
3041+	case DSP_CLIENT_REGISTER:
3042+		ret = fsl_dsp_client_register(client);
3043+		break;
3044+	case DSP_CLIENT_UNREGISTER:
3045+		ret = fsl_dsp_client_unregister(client);
3046+		break;
3047+	case DSP_IPC_MSG_SEND:
3048+		ret = fsl_dsp_ipc_msg_to_dsp(client, user);
3049+		break;
3050+	case DSP_IPC_MSG_RECV:
3051+		ret = fsl_dsp_ipc_msg_from_dsp(client, user);
3052+		break;
3053+	case DSP_GET_SHMEM_INFO:
3054+		ret = fsl_dsp_get_shmem_info(client, user);
3055+		break;
3056+	default:
3057+		break;
3058+	}
3059+
3060+	mutex_unlock(&dsp_priv->dsp_mutex);
3061+
3062+	return ret;
3063+}
3064+
3065+void resource_release(struct fsl_dsp *dsp_priv)
3066+{
3067+	int i;
3068+
3069+	/* ...initialize client association map */
3070+	for (i = 0; i < XF_CFG_MAX_IPC_CLIENTS - 1; i++)
3071+		dsp_priv->xf_client_map[i].next = i + 1;
3072+	/* ...set list terminator */
3073+	dsp_priv->xf_client_map[i].next = 0;
3074+
3075+	/* ...set pointer to shared memory */
3076+	xf_proxy_init(&dsp_priv->proxy);
3077+}
3078+
3079+int fsl_dsp_open_func(struct fsl_dsp *dsp_priv, struct xf_client *client)
3080+{
3081+	struct device *dev = dsp_priv->dev;
3082+	int ret = 0;
3083+
3084+	/* ...initialize waiting queue */
3085+	init_waitqueue_head(&client->wait);
3086+
3087+	/* ...initialize client pending message queue */
3088+	xf_msg_queue_init(&client->queue);
3089+
3090+	/* ...mark user data is not mapped */
3091+	client->vm_start = 0;
3092+
3093+	/* ...reset mappings counter */
3094+	atomic_set(&client->vm_use, 0);
3095+
3096+	client->global = (void *)dsp_priv;
3097+	dsp_priv->proxy.is_active = 1;
3098+
3099+	pm_runtime_get_sync(dev);
3100+
3101+	mutex_lock(&dsp_priv->dsp_mutex);
3102+	/* increase reference counter when opening device */
3103+	atomic_long_inc(&dsp_priv->refcnt);
3104+	mutex_unlock(&dsp_priv->dsp_mutex);
3105+
3106+	return ret;
3107+}
3108+
3109+static int fsl_dsp_open(struct inode *inode, struct file *file)
3110+{
3111+	struct fsl_dsp *dsp_priv = dev_get_drvdata(dsp_miscdev.parent);
3112+	struct xf_client *client;
3113+	int ret = 0;
3114+
3115+	/* ...basic sanity checks */
3116+	if (!inode || !file)
3117+		return -EINVAL;
3118+
3119+	/* ...allocate new proxy client object */
3120+	client = xf_client_alloc(dsp_priv);
3121+	if (IS_ERR(client))
3122+		return PTR_ERR(client);
3123+
3124+	fsl_dsp_open_func(dsp_priv, client);
3125+
3126+	file->private_data = (void *)client;
3127+
3128+	return ret;
3129+}
3130+
3131+static int fsl_dsp_wait_idle(struct fsl_dsp *dsp_priv)
3132+{
3133+	int timeout = 200;
3134+
3135+	if (dsp_priv->dsp_is_lpa) {
3136+		/* FW code is on OCRAM_A, Need wait DSP idle before gate */
3137+		/* OCRAM_A clock. Or DSP will hang */
3138+		while (!imx_audiomix_dsp_pwaitmode(dsp_priv->audiomix)) {
3139+			if (!timeout--) {
3140+				dev_err(dsp_priv->dev, "DSP failed to idle\n");
3141+				return -ETIME;
3142+			}
3143+			udelay(5);
3144+		}
3145+	}
3146+
3147+	return 0;
3148+}
3149+
3150+int fsl_dsp_close_func(struct xf_client *client)
3151+{
3152+	struct fsl_dsp *dsp_priv;
3153+	struct device *dev;
3154+	struct xf_proxy *proxy;
3155+
3156+	/* ...basic sanity checks */
3157+	proxy = client->proxy;
3158+
3159+	/* release all pending messages */
3160+	if (proxy)
3161+		xf_msg_free_all(proxy, &client->queue);
3162+
3163+	dsp_priv = (struct fsl_dsp *)client->global;
3164+
3165+	/* wait until DSP idle */
3166+	fsl_dsp_wait_idle(dsp_priv);
3167+
3168+	dev = dsp_priv->dev;
3169+	pm_runtime_put_sync(dev);
3170+
3171+	/* ...recycle client id and release memory */
3172+	xf_client_free(client);
3173+
3174+	mutex_lock(&dsp_priv->dsp_mutex);
3175+	/* decrease reference counter when closing device */
3176+	atomic_long_dec(&dsp_priv->refcnt);
3177+	/* If device is free, reinitialize the resource of
3178+	 * dsp driver and framework
3179+	 */
3180+	if (atomic_long_read(&dsp_priv->refcnt) <= 0) {
3181+		/* we are closing up, wait for proxy processing
3182+		 * function to finish */
3183+		cancel_work_sync(&dsp_priv->proxy.work);
3184+		resource_release(dsp_priv);
3185+	}
3186+
3187+	mutex_unlock(&dsp_priv->dsp_mutex);
3188+
3189+	return 0;
3190+}
3191+
3192+static int fsl_dsp_close(struct inode *inode, struct file *file)
3193+{
3194+	struct xf_client *client;
3195+
3196+	/* ...basic sanity checks */
3197+	client = xf_get_client(file);
3198+	if (IS_ERR(client))
3199+		return PTR_ERR(client);
3200+
3201+	fsl_dsp_close_func(client);
3202+
3203+	return 0;
3204+}
3205+
3206+/* ...wait until data is available in the response queue */
3207+static unsigned int fsl_dsp_poll(struct file *file, poll_table *wait)
3208+{
3209+	struct xf_proxy *proxy;
3210+	struct xf_client *client;
3211+	int mask;
3212+
3213+	/* ...basic sanity checks */
3214+	client = xf_get_client(file);
3215+	if (IS_ERR(client))
3216+		return PTR_ERR(client);
3217+
3218+	/* ...get proxy interface */
3219+	proxy = client->proxy;
3220+	if (!proxy)
3221+		return -EPERM;
3222+
3223+	/* ...register client waiting queue */
3224+	poll_wait(file, &client->wait, wait);
3225+
3226+	/* ...return current queue state */
3227+	mask = (xf_msg_queue_head(&client->queue) ? POLLIN | POLLRDNORM : 0);
3228+
3229+	return mask;
3230+}
3231+
3232+/*******************************************************************************
3233+ * Low-level mmap interface
3234+ ******************************************************************************/
3235+
3236+/* ...add reference to shared buffer */
3237+static void dsp_mmap_open(struct vm_area_struct *vma)
3238+{
3239+	struct xf_client *client = vma->vm_private_data;
3240+
3241+	/* ...probably just increase counter of open references? - tbd */
3242+	atomic_inc(&client->vm_use);
3243+
3244+	pr_debug("xf_mmap_open: vma = %p, client = %p", vma, client);
3245+}
3246+
3247+/* ...close reference to shared buffer */
3248+static void dsp_mmap_close(struct vm_area_struct *vma)
3249+{
3250+	struct xf_client *client = vma->vm_private_data;
3251+
3252+	pr_debug("xf_mmap_close: vma = %p, b = %p", vma, client);
3253+
3254+	/* ...decrement number of mapping */
3255+	atomic_dec(&client->vm_use);
3256+}
3257+
3258+/* ...memory map operations */
3259+static const struct vm_operations_struct dsp_mmap_ops = {
3260+	.open   = dsp_mmap_open,
3261+	.close  = dsp_mmap_close,
3262+};
3263+
3264+/* ...shared memory mapping */
3265+static int fsl_dsp_mmap(struct file *file, struct vm_area_struct *vma)
3266+{
3267+	struct xf_proxy *proxy;
3268+	struct xf_client *client;
3269+	unsigned long   size;
3270+	unsigned long   pfn;
3271+	int             r;
3272+	struct fsl_dsp *dsp_priv;
3273+
3274+	/* ...basic sanity checks */
3275+	client = xf_get_client(file);
3276+	if (IS_ERR(client))
3277+		return PTR_ERR(client);
3278+
3279+	/* ...get proxy interface */
3280+	proxy = client->proxy;
3281+	if (!proxy)
3282+		return -EPERM;
3283+
3284+	/* ...check it was not mapped already */
3285+	if (client->vm_start != 0)
3286+		return -EBUSY;
3287+
3288+	/* ...check mapping flags (tbd) */
3289+	if ((vma->vm_flags & (VM_READ | VM_WRITE | VM_SHARED))
3290+				!= (VM_READ | VM_WRITE | VM_SHARED))
3291+		return -EPERM;
3292+
3293+	/* ...set memory map operations */
3294+	vma->vm_ops = &dsp_mmap_ops;
3295+
3296+	/* ...assign private data */
3297+	client->vm_start = vma->vm_start;
3298+
3299+	/* ...set private memory data */
3300+	vma->vm_private_data = client;
3301+
3302+	/* ...set page number of shared memory */
3303+	dsp_priv = (struct fsl_dsp *)client->global;
3304+	pfn = dsp_priv->scratch_buf_phys >> PAGE_SHIFT;
3305+	size = dsp_priv->scratch_buf_size;
3306+
3307+	/* ...remap shared memory to user-space */
3308+	vma->vm_page_prot = pgprot_writecombine(vma->vm_page_prot);
3309+	r = remap_pfn_range(vma, vma->vm_start, pfn, size, vma->vm_page_prot);
3310+	if (r != 0) {
3311+		pr_err("mapping failed: %d", r);
3312+		return r;
3313+	}
3314+
3315+	/* ...system-specific hook for registering shared memory mapping */
3316+	return 0;
3317+}
3318+
3319+void *memset_dsp(void *dest, int c, size_t count)
3320+{
3321+	uint *dl = (uint *)dest;
3322+	void *dl_1, *dl_2;
3323+	size_t align = 4;
3324+	size_t n, n1, n2;
3325+
3326+	/* while all data is aligned (common case), copy a word at a time */
3327+	if ((((ulong)dest) & (sizeof(*dl) - 1)) != 0) {
3328+		dl = (unsigned int *)(((ulong)dest + align - 1) &
3329+								(~(align - 1)));
3330+		dl_1 = dest;
3331+		dl_2 = (void *)(((ulong)dest + count) & (~(align - 1)));
3332+		n1 = (ulong)dl - (ulong)dl_1;
3333+		n2 = (ulong)dest + count - (ulong)dl_2;
3334+		n = (count - n1 - n2) / align;
3335+
3336+		while (n--) {
3337+			writel_relaxed(0,  dl);
3338+			dl++;
3339+		}
3340+		while (n1--) {
3341+			writeb_relaxed(0, dl_1);
3342+			dl_1++;
3343+		}
3344+		while (n2--) {
3345+			writeb_relaxed(0, dl_2);
3346+			dl_2++;
3347+		}
3348+	} else {
3349+		n = count / align;
3350+		n1 = count - n * align;
3351+		dl_1 = dest + n * align;
3352+		while (n--) {
3353+			writel_relaxed(0,  dl);
3354+			dl++;
3355+		}
3356+		while (n1--) {
3357+			writeb_relaxed(0, dl_1);
3358+			dl_1++;
3359+		}
3360+	}
3361+
3362+	return dest;
3363+}
3364+
3365+void *memcpy_dsp(void *dest, const void *src, size_t count)
3366+{
3367+	unsigned int *dl = (unsigned int *)dest, *sl = (unsigned int *)src;
3368+	size_t n = round_up(count, 4) / 4;
3369+
3370+	if (src == dest)
3371+		return dest;
3372+
3373+	/* while all data is aligned (common case), copy a word at a time */
3374+	if ((((ulong)dest | (ulong)src) & (sizeof(*dl) - 1)) != 0)
3375+		pr_info("dest %p src %p not 4 bytes aligned\n", dest, src);
3376+
3377+	while (n--) {
3378+		writel_relaxed(*sl,  dl);
3379+		dl++;
3380+		sl++;
3381+	}
3382+
3383+	return dest;
3384+}
3385+
3386+static void fsl_dsp_sim_lpav_start(struct fsl_dsp *dsp_priv)
3387+{
3388+	regmap_update_bits(dsp_priv->regmap, REG_SIM_LPAV_SYSCTRL0, DSP_STALL, 0);
3389+}
3390+
3391+static void fsl_dsp_start(struct fsl_dsp *dsp_priv)
3392+{
3393+	switch (dsp_priv->dsp_board_type){
3394+	case DSP_IMX8QM_TYPE:
3395+	case DSP_IMX8QXP_TYPE:
3396+		imx_sc_pm_cpu_start(dsp_priv->dsp_ipcHandle,
3397+				    IMX_SC_R_DSP, true, dsp_priv->iram);
3398+		break;
3399+	case DSP_IMX8MP_TYPE:
3400+		imx_audiomix_dsp_runstall(dsp_priv->audiomix, 0);
3401+		break;
3402+	case DSP_IMX8ULP_TYPE:
3403+		fsl_dsp_sim_lpav_start(dsp_priv);
3404+		break;
3405+	default:
3406+		break;
3407+	}
3408+}
3409+
3410+static void imx8mp_dsp_reset(struct fsl_dsp *dsp_priv)
3411+{
3412+	int pwrctl;
3413+	/* put DSP into reset and stall */
3414+	pwrctl = readl(dsp_priv->dap + IMX8M_DAP_PWRCTL);
3415+	pwrctl |= IMX8M_PWRCTL_CORERESET;
3416+	writel(pwrctl, dsp_priv->dap + IMX8M_DAP_PWRCTL);
3417+
3418+	/* keep reset asserted for 10 cycles */
3419+	usleep_range(1, 2);
3420+
3421+	imx_audiomix_dsp_runstall(dsp_priv->audiomix, AudioDSP_REG2_RUNSTALL);
3422+
3423+	/* take the DSP out of reset and keep stalled for FW loading */
3424+	pwrctl = readl(dsp_priv->dap + IMX8M_DAP_PWRCTL);
3425+	pwrctl &= ~IMX8M_PWRCTL_CORERESET;
3426+	writel(pwrctl, dsp_priv->dap + IMX8M_DAP_PWRCTL);
3427+}
3428+
3429+static void imx8ulp_dsp_reset(struct fsl_dsp *dsp_priv)
3430+{
3431+	struct arm_smccc_res res;
3432+
3433+	regmap_update_bits(dsp_priv->regmap, REG_SIM_LPAV_SYSCTRL0, DSP_RST, DSP_RST);
3434+	regmap_update_bits(dsp_priv->regmap, REG_SIM_LPAV_SYSCTRL0, DSP_STALL, DSP_STALL);
3435+
3436+	arm_smccc_smc(FSL_SIP_HIFI_XRDC, 0, 0, 0, 0, 0, 0, 0, &res);
3437+
3438+	regmap_update_bits(dsp_priv->regmap, REG_SIM_LPAV_SYSCTRL0, DSP_RST, 0);
3439+	regmap_update_bits(dsp_priv->regmap, REG_SIM_LPAV_SYSCTRL0, DSP_DBG_RST, 0);
3440+}
3441+
3442+static void fsl_dsp_reset(struct fsl_dsp *dsp_priv)
3443+{
3444+	switch (dsp_priv->dsp_board_type) {
3445+	case DSP_IMX8QM_TYPE:
3446+	case DSP_IMX8QXP_TYPE:
3447+		break;
3448+	case DSP_IMX8MP_TYPE:
3449+		imx8mp_dsp_reset(dsp_priv);
3450+		break;
3451+	case DSP_IMX8ULP_TYPE:
3452+		imx8ulp_dsp_reset(dsp_priv);
3453+		break;
3454+	default:
3455+		break;
3456+	}
3457+}
3458+
3459+static void dsp_load_firmware(const struct firmware *fw, void *context)
3460+{
3461+	struct fsl_dsp *dsp_priv = context;
3462+	struct device *dev = dsp_priv->dev;
3463+	Elf32_Ehdr *ehdr; /* Elf header structure pointer */
3464+	Elf32_Shdr *shdr; /* Section header structure pointer */
3465+	Elf32_Addr  sh_addr;
3466+	Elf32_Addr  base_addr;
3467+	unsigned char *strtab = 0; /* String table pointer */
3468+	unsigned char *image; /* Binary image pointer */
3469+	int i; /* Loop counter */
3470+	unsigned long addr;
3471+
3472+	if (!fw) {
3473+		dev_info(dev, "external firmware not found\n");
3474+		return;
3475+	}
3476+
3477+	addr = (unsigned long)fw->data;
3478+	ehdr = (Elf32_Ehdr *)addr;
3479+
3480+	/* Find the section header string table for output info */
3481+	shdr = (Elf32_Shdr *)(addr + ehdr->e_shoff +
3482+			(ehdr->e_shstrndx * sizeof(Elf32_Shdr)));
3483+
3484+	strtab = (unsigned char *)(addr + shdr->sh_offset);
3485+
3486+	/* Load each appropriate section */
3487+	for (i = 0; i < ehdr->e_shnum; ++i) {
3488+		shdr = (Elf32_Shdr *)(addr + ehdr->e_shoff +
3489+				(i * sizeof(Elf32_Shdr)));
3490+
3491+		if (!(shdr->sh_flags & SHF_ALLOC) ||
3492+			shdr->sh_addr == 0 || shdr->sh_size == 0)
3493+			continue;
3494+
3495+		dev_dbg(dev, "%sing %s @ 0x%08lx (%ld bytes)\n",
3496+			(shdr->sh_type == SHT_NOBITS) ? "Clear" : "Load",
3497+			&strtab[shdr->sh_name], (unsigned long)shdr->sh_addr,
3498+			(long)shdr->sh_size);
3499+
3500+		sh_addr = shdr->sh_addr;
3501+
3502+		if (shdr->sh_type == SHT_NOBITS) {
3503+			base_addr = sh_addr + dsp_priv->fixup_offset_dram;
3504+
3505+			memset_dsp((void *)(dsp_priv->sdram_vir_addr +
3506+				(base_addr - dsp_priv->sdram_phys_addr)),
3507+				0,
3508+				shdr->sh_size);
3509+		} else {
3510+			image = (unsigned char *)addr + shdr->sh_offset;
3511+			if ((!strcmp(&strtab[shdr->sh_name], ".rodata")) ||
3512+				(!strcmp(&strtab[shdr->sh_name], ".text"))   ||
3513+				(!strcmp(&strtab[shdr->sh_name], ".data"))   ||
3514+				(!strcmp(&strtab[shdr->sh_name], ".bss"))           ||
3515+				(!strcmp(&strtab[shdr->sh_name], ".rtos.rodata"))   ||
3516+				(!strcmp(&strtab[shdr->sh_name], ".clib.data"))     ||
3517+				(!strcmp(&strtab[shdr->sh_name], ".rtos.percpu.data"))
3518+			) {
3519+				base_addr = sh_addr + dsp_priv->sdram_reserved_alias;
3520+
3521+				memcpy_dsp((void *)(dsp_priv->sdram_vir_addr
3522+				  + (base_addr - dsp_priv->sdram_phys_addr)),
3523+				  (const void *)image,
3524+				  shdr->sh_size);
3525+			} else {
3526+				/* sh_addr is from DSP view, we need to
3527+				 * fixup addr because we load the firmware from
3528+				 * the ARM core side
3529+				 */
3530+				sh_addr -= dsp_priv->fixup_offset_itcm;
3531+
3532+				memcpy_dsp((void *)(dsp_priv->regs +
3533+						(sh_addr - dsp_priv->paddr)),
3534+						(const void *)image,
3535+						shdr->sh_size);
3536+			}
3537+		}
3538+	}
3539+
3540+	/* start the core */
3541+	fsl_dsp_start(dsp_priv);
3542+}
3543+
3544+static const struct file_operations dsp_fops = {
3545+	.owner		= THIS_MODULE,
3546+	.unlocked_ioctl	= fsl_dsp_ioctl,
3547+#ifdef CONFIG_COMPAT
3548+	.compat_ioctl = fsl_dsp_ioctl,
3549+#endif
3550+	.open		= fsl_dsp_open,
3551+	.poll		= fsl_dsp_poll,
3552+	.mmap		= fsl_dsp_mmap,
3553+	.release	= fsl_dsp_close,
3554+};
3555+
3556+extern struct snd_compress_ops dsp_platform_compr_lpa_ops;
3557+
3558+static const struct snd_soc_component_driver dsp_soc_platform_lpa_drv  = {
3559+	.name		= FSL_DSP_COMP_NAME,
3560+	.compress_ops      = &dsp_platform_compr_lpa_ops,
3561+};
3562+
3563+extern struct snd_compress_ops dsp_platform_compress_ops;
3564+
3565+static const struct snd_soc_component_driver dsp_soc_platform_drv  = {
3566+	.name		= FSL_DSP_COMP_NAME,
3567+	.compress_ops	= &dsp_platform_compress_ops
3568+};
3569+
3570+
3571+int fsl_dsp_configure_audmix(struct fsl_dsp *dsp_priv) {
3572+	struct device_node *np;
3573+	struct platform_device *pdev;
3574+
3575+	np = of_find_node_by_name(NULL, "audiomix_dsp");
3576+	if (!np)
3577+		return -EPROBE_DEFER;
3578+
3579+	pdev = of_find_device_by_node(np);
3580+	if (!pdev)
3581+		return -EPROBE_DEFER;
3582+
3583+	dsp_priv->audiomix = dev_get_drvdata(&pdev->dev);
3584+	if (!dsp_priv->audiomix)
3585+		return -EPROBE_DEFER;
3586+
3587+	return 0;
3588+}
3589+
3590+int fsl_dsp_configure_scu(struct fsl_dsp *dsp_priv)
3591+{
3592+	int ret;
3593+
3594+	/* there is no SCU on i.MX8MP */
3595+	if (dsp_priv->dsp_board_type == DSP_IMX8MP_TYPE)
3596+		return 0;
3597+
3598+	ret = imx_scu_get_handle(&dsp_priv->dsp_ipcHandle);
3599+	if (ret) {
3600+		dev_err(dsp_priv->dev, "Cannot get scu handle %d\n", ret);
3601+		return ret;
3602+	}
3603+
3604+	if (dsp_priv->dsp_board_type == DSP_IMX8QXP_TYPE) {
3605+		ret = imx_sc_misc_set_control(dsp_priv->dsp_ipcHandle, IMX_SC_R_DSP,
3606+					IMX_SC_C_OFS_SEL, 1);
3607+		if (ret) {
3608+			dev_err(dsp_priv->dev, "Error system address offset source select\n");
3609+			return -EIO;
3610+		}
3611+
3612+		ret = imx_sc_misc_set_control(dsp_priv->dsp_ipcHandle, IMX_SC_R_DSP,
3613+					IMX_SC_C_OFS_PERIPH, 0x5A);
3614+		if (ret) {
3615+			dev_err(dsp_priv->dev, "Error system address offset of PERIPH %d\n",
3616+				ret);
3617+			return -EIO;
3618+		}
3619+
3620+		ret = imx_sc_misc_set_control(dsp_priv->dsp_ipcHandle, IMX_SC_R_DSP,
3621+					IMX_SC_C_OFS_IRQ, 0x51);
3622+		if (ret) {
3623+			dev_err(dsp_priv->dev, "Error system address offset of IRQ\n");
3624+			return -EIO;
3625+		}
3626+
3627+		ret = imx_sc_misc_set_control(dsp_priv->dsp_ipcHandle, IMX_SC_R_DSP,
3628+					IMX_SC_C_OFS_AUDIO, 0x80);
3629+		if (ret) {
3630+			dev_err(dsp_priv->dev, "Error system address offset of AUDIO\n");
3631+			return -EIO;
3632+		}
3633+	} else {
3634+		ret = imx_sc_misc_set_control(dsp_priv->dsp_ipcHandle, IMX_SC_R_DSP,
3635+					IMX_SC_C_OFS_SEL, 0);
3636+		if (ret) {
3637+			dev_err(dsp_priv->dev, "Error system address offset source select\n");
3638+			return -EIO;
3639+		}
3640+	}
3641+
3642+	return 0;
3643+}
3644+
3645+int fsl_dsp_configure(struct fsl_dsp *dsp_priv)
3646+{
3647+	switch (dsp_priv->dsp_board_type) {
3648+	case DSP_IMX8QM_TYPE:
3649+	case DSP_IMX8QXP_TYPE:
3650+		return fsl_dsp_configure_scu(dsp_priv);
3651+	case DSP_IMX8MP_TYPE:
3652+		return fsl_dsp_configure_audmix(dsp_priv);
3653+	case DSP_IMX8ULP_TYPE:
3654+		return 0;
3655+	default:
3656+		return -ENODEV;
3657+	}
3658+}
3659+
3660+/**
3661+ * fsl_dsp_attach_pm_domains
3662+ */
3663+static int fsl_dsp_attach_pm_domains(struct device *dev,
3664+				     struct fsl_dsp *dsp)
3665+{
3666+	int ret;
3667+	int i;
3668+
3669+	if (dsp->num_domains <= 1)
3670+		return 0;
3671+
3672+	dsp->pd_dev = devm_kmalloc_array(dev, dsp->num_domains,
3673+					 sizeof(*dsp->pd_dev),
3674+					 GFP_KERNEL);
3675+	if (!dsp->pd_dev)
3676+		return -ENOMEM;
3677+
3678+	dsp->pd_dev_link = devm_kmalloc_array(dev,
3679+					      dsp->num_domains,
3680+					      sizeof(*dsp->pd_dev_link),
3681+					      GFP_KERNEL);
3682+	if (!dsp->pd_dev_link)
3683+		return -ENOMEM;
3684+
3685+	for (i = 0; i < dsp->num_domains; i++) {
3686+		dsp->pd_dev[i] = dev_pm_domain_attach_by_id(dev, i);
3687+		if (IS_ERR(dsp->pd_dev[i]))
3688+			return PTR_ERR(dsp->pd_dev[i]);
3689+
3690+		dsp->pd_dev_link[i] = device_link_add(dev,
3691+						      dsp->pd_dev[i],
3692+						      DL_FLAG_STATELESS |
3693+						      DL_FLAG_PM_RUNTIME |
3694+						      DL_FLAG_RPM_ACTIVE);
3695+		if (IS_ERR(dsp->pd_dev_link[i])) {
3696+			dev_pm_domain_detach(dsp->pd_dev[i], false);
3697+			ret = PTR_ERR(dsp->pd_dev_link[i]);
3698+			goto detach_pm;
3699+		}
3700+	}
3701+	return 0;
3702+
3703+detach_pm:
3704+	while (--i >= 0) {
3705+		device_link_del(dsp->pd_dev_link[i]);
3706+		dev_pm_domain_detach(dsp->pd_dev[i], false);
3707+	}
3708+	return ret;
3709+}
3710+
3711+/**
3712+ * fsl_dsp_detach_pm_domains
3713+ */
3714+static int fsl_dsp_detach_pm_domains(struct device *dev,
3715+				     struct fsl_dsp *dsp)
3716+{
3717+	int i;
3718+
3719+	if (dsp->num_domains <= 1)
3720+		return 0;
3721+
3722+	for (i = 0; i < dsp->num_domains; i++) {
3723+		device_link_del(dsp->pd_dev_link[i]);
3724+		dev_pm_domain_detach(dsp->pd_dev[i], false);
3725+	}
3726+
3727+	return 0;
3728+}
3729+
3730+static int fsl_dsp_mem_setup_lpa(struct fsl_dsp *dsp_priv)
3731+{
3732+	struct device_node *np = dsp_priv->dev->of_node;
3733+	struct device_node *reserved_node;
3734+	struct resource reserved_res;
3735+	int offset, size;
3736+
3737+	reserved_node = of_parse_phandle(np, "ocram", 0);
3738+	if (!reserved_node) {
3739+		dev_err(dsp_priv->dev, "failed to get reserved region node\n");
3740+		return -ENODEV;
3741+	}
3742+
3743+	if (of_address_to_resource(reserved_node, 0, &reserved_res)) {
3744+		dev_err(dsp_priv->dev, "failed to get reserved region address\n");
3745+		return -EINVAL;
3746+	}
3747+
3748+	dsp_priv->ocram_phys_addr = reserved_res.start;
3749+	dsp_priv->ocram_reserved_size = (reserved_res.end - reserved_res.start)
3750+		+ 1;
3751+	if (dsp_priv->ocram_reserved_size <= 0) {
3752+		dev_err(dsp_priv->dev, "invalid value of reserved region size\n");
3753+		return -EINVAL;
3754+	}
3755+
3756+	dsp_priv->ocram_vir_addr = ioremap_wc(dsp_priv->ocram_phys_addr,
3757+			dsp_priv->ocram_reserved_size);
3758+	if (!dsp_priv->ocram_vir_addr) {
3759+		dev_err(dsp_priv->dev, "failed to remap ocram space for dsp firmware\n");
3760+		return -ENXIO;
3761+	}
3762+	memset_io(dsp_priv->ocram_vir_addr, 0, dsp_priv->ocram_reserved_size);
3763+
3764+	size = MSG_BUF_SIZE + DSP_CONFIG_SIZE;
3765+
3766+	/* msg ring buffer memory */
3767+	dsp_priv->msg_buf_virt = dsp_priv->ocram_vir_addr + dsp_priv->ocram_reserved_size - size;
3768+	dsp_priv->msg_buf_phys = dsp_priv->ocram_phys_addr + dsp_priv->ocram_reserved_size - size;
3769+	dsp_priv->msg_buf_size = MSG_BUF_SIZE;
3770+	offset = MSG_BUF_SIZE;
3771+
3772+	/* keep dsp framework's global data when suspend/resume */
3773+	dsp_priv->dsp_config_virt = dsp_priv->ocram_vir_addr + dsp_priv->ocram_reserved_size - size + offset;
3774+	dsp_priv->dsp_config_phys = dsp_priv->ocram_phys_addr + dsp_priv->ocram_reserved_size - size + offset;
3775+	dsp_priv->dsp_config_size = DSP_CONFIG_SIZE;
3776+
3777+	dsp_priv->scratch_buf_virt = dsp_priv->ocram_vir_addr;
3778+	dsp_priv->scratch_buf_phys = dsp_priv->ocram_phys_addr;
3779+	dsp_priv->scratch_buf_size = dsp_priv->ocram_reserved_size - size;
3780+	dsp_priv->dram_reserved_vir_addr = dsp_priv->sdram_vir_addr;
3781+	dsp_priv->dram_reserved_phys_addr = dsp_priv->sdram_phys_addr;
3782+	dsp_priv->dram_reserved_size = dsp_priv->sdram_reserved_size;
3783+	dsp_priv->sdram_vir_addr = dsp_priv->regs + SYSRAM_OFFSET;
3784+	dsp_priv->sdram_phys_addr = dsp_priv->paddr + SYSRAM_OFFSET;
3785+	dsp_priv->sdram_reserved_size = SYSRAM_SIZE;
3786+
3787+	return 0;
3788+}
3789+
3790+static int fsl_dsp_mem_setup(struct fsl_dsp *dsp_priv)
3791+{
3792+	int offset;
3793+
3794+	/*
3795+	 * Memory allocation:
3796+	 * We alway reserve 32M memory from DRAM
3797+	 * The DRAM reserved memory is split into three parts currently.
3798+	 * The front part is used to keep the dsp firmware, the other part is
3799+	 * considered as scratch memory for dsp framework.
3800+	 *
3801+	 *---------------------------------------------------------------------------
3802+	 *| Offset                |  Size    |   Usage                              |
3803+	 *---------------------------------------------------------------------------
3804+	 *| 0x0 ~ 0xEFFFFF        |  15M     |   Code memory of firmware            |
3805+	 *---------------------------------------------------------------------------
3806+	 *| 0xF00000 ~ 0xFFFFFF   |  1M      |   Message buffer + Globle dsp struct |
3807+	 *---------------------------------------------------------------------------
3808+	 *| 0x1000000 ~ 0x1FFFFFF |  16M     |   Scratch memory                     |
3809+	 *---------------------------------------------------------------------------
3810+	 *
3811+	 */
3812+
3813+	dsp_priv->sdram_reserved_alias = dsp_priv->fixup_offset_dram;
3814+	/* 1M memory for msg and config */
3815+	offset = dsp_priv->sdram_reserved_size / 2 - MSG_PLUS_CONFIG_SIZE;
3816+	/* msg ring buffer memory */
3817+	dsp_priv->msg_buf_virt = dsp_priv->sdram_vir_addr + offset;
3818+	dsp_priv->msg_buf_phys = dsp_priv->sdram_phys_addr + offset;
3819+	dsp_priv->msg_buf_size = MSG_BUF_SIZE;
3820+	dsp_priv->msg_buf_alias = dsp_priv->fixup_offset_dram;
3821+	offset += MSG_BUF_SIZE;
3822+
3823+	/* keep dsp framework's global data when suspend/resume */
3824+	dsp_priv->dsp_config_virt = dsp_priv->sdram_vir_addr + offset;
3825+	dsp_priv->dsp_config_phys = dsp_priv->sdram_phys_addr + offset;
3826+	dsp_priv->dsp_config_size = DSP_CONFIG_SIZE;
3827+	dsp_priv->dsp_config_alias = dsp_priv->fixup_offset_dram;
3828+
3829+	dsp_priv->scratch_buf_virt = dsp_priv->sdram_vir_addr +
3830+		dsp_priv->sdram_reserved_size / 2;
3831+	dsp_priv->scratch_buf_phys = dsp_priv->sdram_phys_addr +
3832+		dsp_priv->sdram_reserved_size / 2;
3833+	dsp_priv->scratch_buf_size = dsp_priv->sdram_reserved_size / 2;
3834+	dsp_priv->scratch_buf_alias = dsp_priv->fixup_offset_dram;
3835+
3836+	return 0;
3837+}
3838+
3839+static int fsl_dsp_probe(struct platform_device *pdev)
3840+{
3841+	struct device_node *np = pdev->dev.of_node;
3842+	struct device_node *reserved_node;
3843+	struct resource reserved_res;
3844+	struct fsl_dsp *dsp_priv;
3845+	const char *fw_name;
3846+	const char *audio_iface;
3847+	struct resource *res;
3848+	void __iomem *regs;
3849+	int size, i;
3850+	int ret;
3851+	char tmp[16];
3852+
3853+	dsp_priv = devm_kzalloc(&pdev->dev, sizeof(*dsp_priv), GFP_KERNEL);
3854+	if (!dsp_priv)
3855+		return -ENOMEM;
3856+
3857+	if (of_device_is_compatible(np, "fsl,imx8qxp-dsp-v1"))
3858+		dsp_priv->dsp_board_type = DSP_IMX8QXP_TYPE;
3859+	else if (of_device_is_compatible(np, "fsl,imx8qm-dsp-v1"))
3860+		dsp_priv->dsp_board_type = DSP_IMX8QM_TYPE;
3861+	else if (of_device_is_compatible(np, "fsl,imx8ulp-dsp-v1")) {
3862+		dsp_priv->dsp_board_type = DSP_IMX8ULP_TYPE;
3863+		dsp_priv->regmap = syscon_regmap_lookup_by_compatible("nxp,imx8ulp-avd-sim");
3864+		if (IS_ERR(dsp_priv->regmap))
3865+			return -EPROBE_DEFER;
3866+	} else
3867+		dsp_priv->dsp_board_type = DSP_IMX8MP_TYPE;
3868+
3869+	if (of_device_is_compatible(np, "fsl,imx8mp-dsp-lpa")) {
3870+		dsp_priv->dsp_board_type = DSP_IMX8MP_TYPE;
3871+		dsp_priv->dsp_is_lpa = 1;
3872+	}
3873+
3874+	dsp_priv->dev = &pdev->dev;
3875+
3876+	/* Get the addresses and IRQ */
3877+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
3878+	regs = devm_ioremap_resource(&pdev->dev, res);
3879+	if (IS_ERR(regs))
3880+		return PTR_ERR(regs);
3881+
3882+	dsp_priv->paddr = res->start;
3883+	dsp_priv->regs  = regs;
3884+
3885+	dsp_priv->dram0 = dsp_priv->paddr + DRAM0_OFFSET;
3886+	dsp_priv->dram1 = dsp_priv->paddr + DRAM1_OFFSET;
3887+	dsp_priv->iram  = dsp_priv->paddr + IRAM_OFFSET;
3888+	dsp_priv->sram  = dsp_priv->paddr + SYSRAM_OFFSET;
3889+
3890+	dsp_priv->num_domains = of_count_phandle_with_args(np, "power-domains",
3891+							   "#power-domain-cells");
3892+	ret = fsl_dsp_attach_pm_domains(&pdev->dev, dsp_priv);
3893+	if (ret)
3894+		return ret;
3895+
3896+	platform_set_drvdata(pdev, dsp_priv);
3897+	pm_runtime_enable(&pdev->dev);
3898+	dsp_priv->proxy.is_ready = 1;
3899+	pm_runtime_get_sync(&pdev->dev);
3900+
3901+	ret = fsl_dsp_configure(dsp_priv);
3902+	if (ret < 0) {
3903+		pm_runtime_put_sync(&pdev->dev);
3904+		goto configure_fail;
3905+	}
3906+
3907+	pm_runtime_put_sync(&pdev->dev);
3908+	dsp_priv->proxy.is_ready = 0;
3909+
3910+	ret = of_property_read_string(np, "fsl,dsp-firmware", &fw_name);
3911+	dsp_priv->fw_name = fw_name;
3912+
3913+	ret = of_property_read_string(np, "audio-interface", &audio_iface);
3914+	dsp_priv->audio_iface = audio_iface;
3915+
3916+	ret = of_property_read_u32_index(np, "fixup-offset", 0, &dsp_priv->fixup_offset_itcm);
3917+	ret = of_property_read_u32_index(np, "fixup-offset", 1, &dsp_priv->fixup_offset_dram);
3918+
3919+	if (!dsp_priv->dsp_is_lpa) {
3920+		dsp_miscdev.fops = &dsp_fops,
3921+			dsp_miscdev.parent = &pdev->dev,
3922+			ret = misc_register(&dsp_miscdev);
3923+		if (ret) {
3924+			dev_err(&pdev->dev, "failed to register misc device %d\n", ret);
3925+			goto misc_register_fail;
3926+		}
3927+	}
3928+
3929+	reserved_node = of_parse_phandle(np, "memory-region", 0);
3930+	if (!reserved_node) {
3931+		dev_err(&pdev->dev, "failed to get reserved region node\n");
3932+		ret = -ENODEV;
3933+		goto reserved_node_fail;
3934+	}
3935+
3936+	if (of_address_to_resource(reserved_node, 0, &reserved_res)) {
3937+		dev_err(&pdev->dev, "failed to get reserved region address\n");
3938+		ret = -EINVAL;
3939+		goto reserved_node_fail;
3940+	}
3941+
3942+	dsp_priv->sdram_phys_addr = reserved_res.start;
3943+	dsp_priv->sdram_reserved_size = (reserved_res.end - reserved_res.start)
3944+									+ 1;
3945+	if (dsp_priv->sdram_reserved_size <= 0) {
3946+		dev_err(&pdev->dev, "invalid value of reserved region size\n");
3947+		ret = -EINVAL;
3948+		goto reserved_node_fail;
3949+	}
3950+
3951+	dsp_priv->sdram_vir_addr = ioremap_wc(dsp_priv->sdram_phys_addr,
3952+						dsp_priv->sdram_reserved_size);
3953+	if (!dsp_priv->sdram_vir_addr) {
3954+		dev_err(&pdev->dev, "failed to remap sdram space for dsp firmware\n");
3955+		ret = -ENXIO;
3956+		goto reserved_node_fail;
3957+	}
3958+	memset_io(dsp_priv->sdram_vir_addr, 0, dsp_priv->sdram_reserved_size);
3959+
3960+	size = MSG_BUF_SIZE + DSP_CONFIG_SIZE;
3961+
3962+	if (dsp_priv->dsp_is_lpa) {
3963+		ret = fsl_dsp_mem_setup_lpa(dsp_priv);
3964+		if (ret) {
3965+			dev_err(&pdev->dev, "lpa mem setup fail.\n");
3966+			goto reserved_node_fail;
3967+		}
3968+	} else {
3969+		if (fsl_dsp_mem_setup(dsp_priv)) {
3970+			dev_err(&pdev->dev, "failed alloc memory.\n");
3971+			ret = -ENOMEM;
3972+			goto alloc_coherent_fail;
3973+		}
3974+	}
3975+
3976+	if (dsp_priv->dsp_board_type == DSP_IMX8MP_TYPE) {
3977+		dsp_priv->dap = devm_ioremap(&pdev->dev, IMX8M_DAP_DEBUG, IMX8M_DAP_DEBUG_SIZE);
3978+		if (!dsp_priv->dap) {
3979+			dev_err(&pdev->dev, "error: failed to map DAP debug memory area");
3980+			ret = -ENODEV;
3981+			goto reserved_node_fail;
3982+		}
3983+	}
3984+
3985+	/* initialize the reference counter for dsp_priv
3986+	 * structure
3987+	 */
3988+	atomic_long_set(&dsp_priv->refcnt, 0);
3989+
3990+	/* ...initialize client association map */
3991+	for (i = 0; i < XF_CFG_MAX_IPC_CLIENTS - 1; i++)
3992+		dsp_priv->xf_client_map[i].next = i + 1;
3993+	/* ...set list terminator */
3994+	dsp_priv->xf_client_map[i].next = 0;
3995+
3996+	/* ...set pointer to shared memory */
3997+	xf_proxy_init(&dsp_priv->proxy);
3998+
3999+	/* ...initialize mutex */
4000+	mutex_init(&dsp_priv->dsp_mutex);
4001+
4002+	if (dsp_priv->dsp_is_lpa) {
4003+		ret = devm_snd_soc_register_component(&pdev->dev, &dsp_soc_platform_lpa_drv, NULL, 0);
4004+		if (ret) {
4005+			dev_err(&pdev->dev, "registering soc platform failed\n");
4006+			goto register_component_fail;
4007+		}
4008+	} else {
4009+		ret = devm_snd_soc_register_component(&pdev->dev, &dsp_soc_platform_drv, NULL, 0);
4010+		if (ret) {
4011+			dev_err(&pdev->dev, "registering soc platform failed\n");
4012+			goto register_component_fail;
4013+		}
4014+	}
4015+
4016+	dsp_priv->esai_ipg_clk = devm_clk_get(&pdev->dev, "esai_ipg");
4017+	if (IS_ERR(dsp_priv->esai_ipg_clk))
4018+		dsp_priv->esai_ipg_clk = NULL;
4019+
4020+	dsp_priv->esai_mclk = devm_clk_get(&pdev->dev, "esai_mclk");
4021+	if (IS_ERR(dsp_priv->esai_mclk))
4022+		dsp_priv->esai_mclk = NULL;
4023+
4024+	dsp_priv->asrc_mem_clk = devm_clk_get(&pdev->dev, "asrc_mem");
4025+	if (IS_ERR(dsp_priv->asrc_mem_clk))
4026+		dsp_priv->asrc_mem_clk = NULL;
4027+
4028+	dsp_priv->asrc_ipg_clk = devm_clk_get(&pdev->dev, "asrc_ipg");
4029+	if (IS_ERR(dsp_priv->asrc_ipg_clk))
4030+		dsp_priv->asrc_ipg_clk = NULL;
4031+
4032+	for (i = 0; i < 4; i++) {
4033+		sprintf(tmp, "asrck_%x", i);
4034+		dsp_priv->asrck_clk[i] = devm_clk_get(&pdev->dev, tmp);
4035+		if (IS_ERR(dsp_priv->asrck_clk[i]))
4036+			dsp_priv->asrck_clk[i] = NULL;
4037+	}
4038+
4039+	dsp_priv->dsp_ocrama_clk = devm_clk_get(&pdev->dev, "ocram");
4040+	if (IS_ERR(dsp_priv->dsp_ocrama_clk))
4041+		dsp_priv->dsp_ocrama_clk = NULL;
4042+
4043+	dsp_priv->audio_root_clk = devm_clk_get(&pdev->dev, "audio_root");
4044+	if (IS_ERR(dsp_priv->audio_root_clk))
4045+		dsp_priv->audio_root_clk = NULL;
4046+
4047+	dsp_priv->audio_axi_clk = devm_clk_get(&pdev->dev, "audio_axi");
4048+	if (IS_ERR(dsp_priv->audio_axi_clk))
4049+		dsp_priv->audio_axi_clk = NULL;
4050+
4051+	dsp_priv->dsp_root_clk = devm_clk_get(&pdev->dev, "core");
4052+	if (IS_ERR(dsp_priv->dsp_root_clk))
4053+		dsp_priv->dsp_root_clk = NULL;
4054+
4055+	dsp_priv->debug_clk = devm_clk_get(&pdev->dev, "debug");
4056+	if (IS_ERR(dsp_priv->debug_clk))
4057+		dsp_priv->debug_clk = NULL;
4058+
4059+	dsp_priv->mu_a_clk = devm_clk_get(&pdev->dev, "mu_a");
4060+	if (IS_ERR(dsp_priv->mu_a_clk))
4061+		dsp_priv->mu_a_clk = NULL;
4062+
4063+	dsp_priv->mu_b_clk = devm_clk_get(&pdev->dev, "mu_b");
4064+	if (IS_ERR(dsp_priv->mu_b_clk))
4065+		dsp_priv->mu_b_clk = NULL;
4066+
4067+	dsp_priv->pb_clk = devm_clk_get(&pdev->dev, "pbclk");
4068+	if (IS_ERR(dsp_priv->pb_clk))
4069+		dsp_priv->pb_clk = NULL;
4070+
4071+	dsp_priv->nic_clk = devm_clk_get(&pdev->dev, "nic");
4072+	if (IS_ERR(dsp_priv->nic_clk))
4073+		dsp_priv->nic_clk = NULL;
4074+
4075+	dsp_priv->sdma_root_clk = devm_clk_get(&pdev->dev, "sdma_root");
4076+	if (IS_ERR(dsp_priv->sdma_root_clk))
4077+		dsp_priv->sdma_root_clk = NULL;
4078+	dsp_priv->sai_ipg_clk = devm_clk_get(&pdev->dev, "sai_ipg");
4079+	if (IS_ERR(dsp_priv->sai_ipg_clk))
4080+		dsp_priv->sai_ipg_clk = NULL;
4081+	dsp_priv->sai_mclk = devm_clk_get(&pdev->dev, "sai_mclk");
4082+	if (IS_ERR(dsp_priv->sai_mclk))
4083+		dsp_priv->sai_mclk = NULL;
4084+	dsp_priv->pll8k_clk = devm_clk_get(&pdev->dev, "pll8k");
4085+	if (IS_ERR(dsp_priv->pll8k_clk))
4086+		dsp_priv->pll8k_clk = NULL;
4087+	dsp_priv->pll11k_clk = devm_clk_get(&pdev->dev, "pll11k");
4088+	if (IS_ERR(dsp_priv->pll11k_clk))
4089+		dsp_priv->pll11k_clk = NULL;
4090+	dsp_priv->uart_ipg_clk = devm_clk_get(&pdev->dev, "uart_ipg");
4091+	if (IS_ERR(dsp_priv->uart_ipg_clk))
4092+		dsp_priv->uart_ipg_clk = NULL;
4093+	dsp_priv->uart_per_clk = devm_clk_get(&pdev->dev, "uart_per");
4094+	if (IS_ERR(dsp_priv->uart_per_clk))
4095+		dsp_priv->uart_per_clk = NULL;
4096+
4097+	return 0;
4098+
4099+register_component_fail:
4100+alloc_coherent_fail:
4101+	if (dsp_priv->sdram_vir_addr)
4102+		iounmap(dsp_priv->sdram_vir_addr);
4103+	if (dsp_priv->ocram_vir_addr)
4104+		iounmap(dsp_priv->ocram_vir_addr);
4105+
4106+reserved_node_fail:
4107+	if (!dsp_priv->dsp_is_lpa)
4108+		misc_deregister(&dsp_miscdev);
4109+misc_register_fail:
4110+configure_fail:
4111+	pm_runtime_disable(&pdev->dev);
4112+	fsl_dsp_detach_pm_domains(&pdev->dev, dsp_priv);
4113+	return ret;
4114+}
4115+
4116+static int fsl_dsp_remove(struct platform_device *pdev)
4117+{
4118+	struct fsl_dsp *dsp_priv = platform_get_drvdata(pdev);
4119+
4120+	if (!dsp_priv->dsp_is_lpa)
4121+		misc_deregister(&dsp_miscdev);
4122+
4123+	if (dsp_priv->sdram_vir_addr)
4124+		iounmap(dsp_priv->sdram_vir_addr);
4125+	if (dsp_priv->ocram_vir_addr)
4126+		iounmap(dsp_priv->ocram_vir_addr);
4127+
4128+	pm_runtime_disable(&pdev->dev);
4129+	fsl_dsp_detach_pm_domains(&pdev->dev, dsp_priv);
4130+
4131+	return 0;
4132+}
4133+
4134+#ifdef CONFIG_PM
4135+static int fsl_dsp_runtime_resume(struct device *dev)
4136+{
4137+	struct fsl_dsp *dsp_priv = dev_get_drvdata(dev);
4138+	struct xf_proxy *proxy = &dsp_priv->proxy;
4139+	int ret;
4140+	int i;
4141+
4142+	ret = clk_prepare_enable(dsp_priv->esai_ipg_clk);
4143+	if (ret) {
4144+		dev_err(dev, "failed to enable esai ipg clock: %d\n", ret);
4145+		goto esai_ipg_clk;
4146+	}
4147+
4148+	ret = clk_prepare_enable(dsp_priv->esai_mclk);
4149+	if (ret) {
4150+		dev_err(dev, "failed to enable esai mclk: %d\n", ret);
4151+		goto esai_mclk;
4152+	}
4153+
4154+	ret = clk_prepare_enable(dsp_priv->asrc_mem_clk);
4155+	if (ret < 0) {
4156+		dev_err(dev, "Failed to enable asrc_mem_clk ret = %d\n", ret);
4157+		goto asrc_mem_clk;
4158+	}
4159+
4160+	ret = clk_prepare_enable(dsp_priv->asrc_ipg_clk);
4161+	if (ret < 0) {
4162+		dev_err(dev, "Failed to enable asrc_ipg_clk ret = %d\n", ret);
4163+		goto asrc_ipg_clk;
4164+	}
4165+
4166+	for (i = 0; i < 4; i++) {
4167+		ret = clk_prepare_enable(dsp_priv->asrck_clk[i]);
4168+		if (ret < 0) {
4169+			dev_err(dev, "failed to prepare arc clk %d\n", i);
4170+			goto asrck_clk;
4171+		}
4172+	}
4173+
4174+	ret = clk_prepare_enable(dsp_priv->dsp_ocrama_clk);
4175+	if (ret < 0) {
4176+		dev_err(dev, "Failed to enable dsp_ocrama_clk ret = %d\n", ret);
4177+		goto ocrama_clk;
4178+	}
4179+
4180+	ret = clk_prepare_enable(dsp_priv->dsp_root_clk);
4181+	if (ret < 0) {
4182+		dev_err(dev, "Failed to enable dsp_root_clk ret = %d\n", ret);
4183+		goto dsp_root_clk;
4184+	}
4185+
4186+	ret = clk_prepare_enable(dsp_priv->audio_root_clk);
4187+	if (ret < 0) {
4188+		dev_err(dev, "Failed to enable audio_root_clk ret = %d\n", ret);
4189+		goto audio_root_clk;
4190+	}
4191+
4192+	ret = clk_prepare_enable(dsp_priv->audio_axi_clk);
4193+	if (ret < 0) {
4194+		dev_err(dev, "Failed to enable audio_axi_clk ret = %d\n", ret);
4195+		goto audio_axi_clk;
4196+	}
4197+
4198+	ret = clk_prepare_enable(dsp_priv->debug_clk);
4199+	if (ret < 0) {
4200+		dev_err(dev, "Failed to enable debug_clk ret = %d\n", ret);
4201+		goto debug_clk;
4202+	}
4203+
4204+	ret = clk_prepare_enable(dsp_priv->mu_a_clk);
4205+	if (ret < 0) {
4206+		dev_err(dev, "Failed to enable mu_a_clk ret = %d\n", ret);
4207+		goto mu_a_clk;
4208+	}
4209+
4210+	ret = clk_prepare_enable(dsp_priv->mu_b_clk);
4211+	if (ret < 0) {
4212+		dev_err(dev, "Failed to enable mu_b_clk ret = %d\n", ret);
4213+		goto mu_b_clk;
4214+	}
4215+
4216+	ret = clk_prepare_enable(dsp_priv->nic_clk);
4217+	if (ret < 0) {
4218+		dev_err(dev, "Failed to enable nic_clk ret = %d\n", ret);
4219+		goto nic_clk;
4220+	}
4221+
4222+	ret = clk_prepare_enable(dsp_priv->pb_clk);
4223+	if (ret < 0) {
4224+		dev_err(dev, "Failed to enable pb_clk ret = %d\n", ret);
4225+		goto pb_clk;
4226+	}
4227+
4228+	ret = clk_prepare_enable(dsp_priv->sdma_root_clk);
4229+	if (ret < 0) {
4230+		dev_err(dev, "Failed to enable sdma_root _clk ret = %d\n", ret);
4231+		goto sdma_root_clk;
4232+	}
4233+	ret = clk_prepare_enable(dsp_priv->sai_ipg_clk);
4234+	if (ret < 0) {
4235+		dev_err(dev, "Failed to enable sai_ipg_clk ret = %d\n", ret);
4236+		goto sai_ipg_clk;
4237+	}
4238+	ret = clk_prepare_enable(dsp_priv->sai_mclk);
4239+	if (ret < 0) {
4240+		dev_err(dev, "Failed to enable sai_mclk ret = %d\n", ret);
4241+		goto sai_mclk;
4242+	}
4243+	ret = clk_prepare_enable(dsp_priv->pll8k_clk);
4244+	if (ret < 0) {
4245+		dev_err(dev, "Failed to enable pll8k_clk ret = %d\n", ret);
4246+		goto pll8k_clk;
4247+	}
4248+	ret = clk_prepare_enable(dsp_priv->pll11k_clk);
4249+	if (ret < 0) {
4250+		dev_err(dev, "Failed to enable pll11k_clk ret = %d\n", ret);
4251+		goto pll11k_clk;
4252+	}
4253+	ret = clk_prepare_enable(dsp_priv->uart_ipg_clk);
4254+	if (ret < 0) {
4255+		dev_err(dev, "Failed to enable uart_ipg_clk ret = %d\n", ret);
4256+		goto uart_ipg_clk;
4257+	}
4258+	ret = clk_prepare_enable(dsp_priv->uart_per_clk);
4259+	if (ret < 0) {
4260+		dev_err(dev, "Failed to enable uart_per_clk ret = %d\n", ret);
4261+		goto uart_per_clk;
4262+	}
4263+	ret = dsp_request_chan(proxy);
4264+	if (ret < 0)
4265+			dev_err(dev, "Failed to request mailbox chan, ret = %d\n", ret);
4266+
4267+	if (!proxy->is_ready) {
4268+		fsl_dsp_reset(dsp_priv);
4269+
4270+		init_completion(&proxy->cmd_complete);
4271+
4272+		ret = request_firmware_nowait(THIS_MODULE,
4273+				FW_ACTION_HOTPLUG, dsp_priv->fw_name,
4274+				dev,
4275+				GFP_KERNEL, dsp_priv, dsp_load_firmware);
4276+
4277+		if (ret) {
4278+			dev_err(dev, "failed to load firmware\n");
4279+			return ret;
4280+		}
4281+
4282+		ret = icm_ack_wait(proxy, 0);
4283+		if (ret)
4284+			return ret;
4285+
4286+		dev_info(dev, "dsp driver registered\n");
4287+	}
4288+
4289+	return 0;
4290+
4291+uart_per_clk:
4292+	clk_disable_unprepare(dsp_priv->uart_ipg_clk);
4293+uart_ipg_clk:
4294+	clk_disable_unprepare(dsp_priv->pll11k_clk);
4295+pll11k_clk:
4296+	clk_disable_unprepare(dsp_priv->pll8k_clk);
4297+pll8k_clk:
4298+	clk_disable_unprepare(dsp_priv->sai_mclk);
4299+sai_mclk:
4300+	clk_disable_unprepare(dsp_priv->sai_ipg_clk);
4301+sai_ipg_clk:
4302+	clk_disable_unprepare(dsp_priv->sdma_root_clk);
4303+sdma_root_clk:
4304+	clk_disable_unprepare(dsp_priv->pb_clk);
4305+pb_clk:
4306+	clk_disable_unprepare(dsp_priv->nic_clk);
4307+nic_clk:
4308+	clk_disable_unprepare(dsp_priv->mu_b_clk);
4309+mu_b_clk:
4310+	clk_disable_unprepare(dsp_priv->mu_a_clk);
4311+mu_a_clk:
4312+	clk_disable_unprepare(dsp_priv->debug_clk);
4313+debug_clk:
4314+	clk_disable_unprepare(dsp_priv->audio_axi_clk);
4315+audio_axi_clk:
4316+	clk_disable_unprepare(dsp_priv->audio_root_clk);
4317+audio_root_clk:
4318+	clk_disable_unprepare(dsp_priv->dsp_root_clk);
4319+dsp_root_clk:
4320+	clk_disable_unprepare(dsp_priv->dsp_ocrama_clk);
4321+ocrama_clk:
4322+	for (i = 0; i < 4; i++)
4323+		clk_disable_unprepare(dsp_priv->asrck_clk[i]);
4324+asrck_clk:
4325+	clk_disable_unprepare(dsp_priv->asrc_ipg_clk);
4326+asrc_ipg_clk:
4327+	clk_disable_unprepare(dsp_priv->asrc_mem_clk);
4328+asrc_mem_clk:
4329+	clk_disable_unprepare(dsp_priv->esai_mclk);
4330+esai_mclk:
4331+	clk_disable_unprepare(dsp_priv->esai_ipg_clk);
4332+esai_ipg_clk:
4333+	return ret;
4334+}
4335+
4336+static int fsl_dsp_runtime_suspend(struct device *dev)
4337+{
4338+	struct fsl_dsp *dsp_priv = dev_get_drvdata(dev);
4339+	struct xf_proxy *proxy = &dsp_priv->proxy;
4340+	int i;
4341+
4342+	dsp_free_chan(proxy);
4343+
4344+	proxy->is_ready = 0;
4345+
4346+	for (i = 0; i < 4; i++)
4347+		clk_disable_unprepare(dsp_priv->asrck_clk[i]);
4348+
4349+	clk_disable_unprepare(dsp_priv->asrc_ipg_clk);
4350+	clk_disable_unprepare(dsp_priv->asrc_mem_clk);
4351+
4352+	clk_disable_unprepare(dsp_priv->esai_mclk);
4353+	clk_disable_unprepare(dsp_priv->esai_ipg_clk);
4354+
4355+	clk_disable_unprepare(dsp_priv->dsp_ocrama_clk);
4356+	clk_disable_unprepare(dsp_priv->dsp_root_clk);
4357+	clk_disable_unprepare(dsp_priv->audio_root_clk);
4358+	clk_disable_unprepare(dsp_priv->audio_axi_clk);
4359+	clk_disable_unprepare(dsp_priv->debug_clk);
4360+	clk_disable_unprepare(dsp_priv->sdma_root_clk);
4361+	clk_disable_unprepare(dsp_priv->sai_ipg_clk);
4362+	clk_disable_unprepare(dsp_priv->sai_mclk);
4363+	clk_disable_unprepare(dsp_priv->pll8k_clk);
4364+	clk_disable_unprepare(dsp_priv->pll11k_clk);
4365+	clk_disable_unprepare(dsp_priv->uart_ipg_clk);
4366+	clk_disable_unprepare(dsp_priv->uart_per_clk);
4367+	clk_disable_unprepare(dsp_priv->mu_a_clk);
4368+	clk_disable_unprepare(dsp_priv->mu_b_clk);
4369+	clk_disable_unprepare(dsp_priv->nic_clk);
4370+	clk_disable_unprepare(dsp_priv->pb_clk);
4371+
4372+	return 0;
4373+}
4374+#endif /* CONFIG_PM */
4375+
4376+
4377+#ifdef CONFIG_PM_SLEEP
4378+static int fsl_dsp_suspend(struct device *dev)
4379+{
4380+	struct fsl_dsp *dsp_priv = dev_get_drvdata(dev);
4381+	struct xf_proxy *proxy = &dsp_priv->proxy;
4382+	int ret = 0;
4383+
4384+	if (dsp_priv->dsp_is_lpa)
4385+		return ret;
4386+
4387+	if (proxy->is_ready & pm_runtime_active(dev)) {
4388+		ret = xf_cmd_send_suspend(proxy);
4389+		if (ret) {
4390+			dev_err(dev, "dsp suspend fail\n");
4391+			return ret;
4392+		}
4393+	}
4394+
4395+	ret = pm_runtime_force_suspend(dev);
4396+
4397+	return ret;
4398+}
4399+
4400+static int fsl_dsp_resume(struct device *dev)
4401+{
4402+	struct fsl_dsp *dsp_priv = dev_get_drvdata(dev);
4403+	struct xf_proxy *proxy = &dsp_priv->proxy;
4404+	int ret = 0;
4405+
4406+	if (dsp_priv->dsp_is_lpa)
4407+		return ret;
4408+
4409+	ret = pm_runtime_force_resume(dev);
4410+	if (ret)
4411+		return ret;
4412+
4413+	if (proxy->is_ready) {
4414+		ret = xf_cmd_send_resume(proxy);
4415+		if (ret) {
4416+			dev_err(dev, "dsp resume fail\n");
4417+			return ret;
4418+		}
4419+	}
4420+
4421+	return 0;
4422+}
4423+#endif /* CONFIG_PM_SLEEP */
4424+
4425+static const struct dev_pm_ops fsl_dsp_pm = {
4426+	SET_RUNTIME_PM_OPS(fsl_dsp_runtime_suspend,
4427+					fsl_dsp_runtime_resume, NULL)
4428+	SET_SYSTEM_SLEEP_PM_OPS(fsl_dsp_suspend, fsl_dsp_resume)
4429+};
4430+
4431+static const struct of_device_id fsl_dsp_ids[] = {
4432+	{ .compatible = "fsl,imx8qxp-dsp-v1", },
4433+	{ .compatible = "fsl,imx8qm-dsp-v1", },
4434+	{ .compatible = "fsl,imx8mp-dsp-v1", },
4435+	{ .compatible = "fsl,imx8mp-dsp-lpa", },
4436+	{ .compatible = "fsl,imx8ulp-dsp-v1", },
4437+	{}
4438+};
4439+MODULE_DEVICE_TABLE(of, fsl_dsp_ids);
4440+
4441+static struct platform_driver fsl_dsp_driver = {
4442+	.probe = fsl_dsp_probe,
4443+	.remove = fsl_dsp_remove,
4444+	.driver = {
4445+		.name = "fsl-dsp",
4446+		.of_match_table = fsl_dsp_ids,
4447+		.pm = &fsl_dsp_pm,
4448+	},
4449+};
4450+module_platform_driver(fsl_dsp_driver);
4451+
4452+MODULE_DESCRIPTION("Freescale DSP driver");
4453+MODULE_ALIAS("platform:fsl-dsp");
4454+MODULE_LICENSE("Dual BSD/GPL");
4455diff --git a/sound/soc/fsl/fsl_dsp.h b/sound/soc/fsl/fsl_dsp.h
4456new file mode 100644
4457index 000000000..a81ee10ad
4458--- /dev/null
4459+++ b/sound/soc/fsl/fsl_dsp.h
4460@@ -0,0 +1,216 @@
4461+/* SPDX-License-Identifier: (GPL-2.0+ OR MIT)*/
4462+/*
4463+ * Copyright (C) 2017 Cadence Design Systems, Inc.
4464+ * Copyright 2018-2020 NXP
4465+ *
4466+ */
4467+
4468+#ifndef FSL_DSP_H
4469+#define FSL_DSP_H
4470+#include <uapi/linux/mxc_dsp.h>
4471+#include <linux/firmware/imx/ipc.h>
4472+#include <linux/mailbox_client.h>
4473+#include "fsl_dsp_proxy.h"
4474+#include "fsl_dsp_platform.h"
4475+#include "fsl_dsp_audiomix.h"
4476+
4477+
4478+#define FSL_DSP_COMP_NAME "fsl-dsp-component"
4479+
4480+typedef void (*memcpy_func) (void *dest, const void *src, size_t n);
4481+typedef void (*memset_func) (void *s, int c, size_t n);
4482+
4483+/* ...maximal number of IPC clients per proxy */
4484+#define XF_CFG_MAX_IPC_CLIENTS          (1 << 4)
4485+
4486+#define NUM_MAILBOX_CHAN 3
4487+
4488+enum {
4489+	DSP_IMX8QXP_TYPE = 0,
4490+	DSP_IMX8QM_TYPE,
4491+	DSP_IMX8MP_TYPE,
4492+	DSP_IMX8ULP_TYPE,
4493+};
4494+
4495+/* ...dsp mailbox chan */
4496+struct dsp_mailbox_chan {
4497+	struct fsl_dsp *dsp_priv;
4498+	char name[20];
4499+	struct mbox_client cl;
4500+	struct mbox_chan *ch;
4501+};
4502+
4503+/* ...proxy client data */
4504+struct xf_client {
4505+	/* ...pointer to proxy interface */
4506+	struct xf_proxy     *proxy;
4507+
4508+	/* ...allocated proxy client id */
4509+	u32 id;
4510+
4511+	/* ...pending response queue */
4512+	struct xf_msg_queue	queue;
4513+	/* ...response waiting queue */
4514+	wait_queue_head_t	wait;
4515+
4516+	/* ...virtual memory mapping */
4517+	unsigned long	vm_start;
4518+	/* ...counter of memory mappings (no real use of it yet - tbd) */
4519+	atomic_t	vm_use;
4520+
4521+	/* ...global structure pointer */
4522+	void	*global;
4523+	struct xf_message m;
4524+
4525+	struct snd_compr_stream *cstream;
4526+
4527+	struct work_struct work;
4528+	struct completion compr_complete;
4529+
4530+	int input_bytes;
4531+	int consume_bytes;
4532+	int offset;
4533+	atomic_t buffer_cnt;
4534+	int ping_pong_offset;
4535+};
4536+
4537+union xf_client_link {
4538+	/* ...index of next client in free list */
4539+	u32                 next;
4540+
4541+	/* ...reference to proxy data for allocated client */
4542+	struct xf_client    *client;
4543+};
4544+
4545+struct fsl_dsp {
4546+	struct device			*dev;
4547+	const char			*fw_name;
4548+	const char			*audio_iface;
4549+	void __iomem			*regs;
4550+	void __iomem			*mu_base_virtaddr;
4551+	void __iomem			*dap;
4552+	struct imx_sc_ipc		*dsp_ipcHandle;
4553+	struct imx_audiomix_dsp_data 	*audiomix;
4554+	struct dsp_mailbox_chan      chan_tx[3];
4555+	struct dsp_mailbox_chan      chan_rx0;
4556+	int				dsp_is_lpa;
4557+	atomic_long_t			refcnt;
4558+	unsigned long			paddr;
4559+	unsigned long			dram0;
4560+	unsigned long			dram1;
4561+	unsigned long			iram;
4562+	unsigned long			sram;
4563+	void			        *sdram_vir_addr;
4564+	unsigned long			sdram_phys_addr;
4565+	int				sdram_reserved_size;
4566+	int				sdram_reserved_alias;
4567+	void			        *dram_reserved_vir_addr;
4568+	unsigned long			dram_reserved_phys_addr;
4569+	int				dram_reserved_size;
4570+	void			        *ocram_vir_addr;
4571+	unsigned long			ocram_phys_addr;
4572+	int				ocram_reserved_size;
4573+	void				*msg_buf_virt;
4574+	dma_addr_t			 msg_buf_phys;
4575+	int				 msg_buf_size;
4576+	int				 msg_buf_alias;
4577+	void				*scratch_buf_virt;
4578+	dma_addr_t			 scratch_buf_phys;
4579+	int				 scratch_buf_size;
4580+	int				 scratch_buf_alias;
4581+	void				*dsp_config_virt;
4582+	dma_addr_t			 dsp_config_phys;
4583+	int				 dsp_config_size;
4584+	int				 dsp_config_alias;
4585+	int				 dsp_board_type;
4586+	unsigned int			fixup_offset_itcm;  /* itcm */
4587+	unsigned int			fixup_offset_dram;
4588+
4589+	/* ...proxy data structures */
4590+	struct xf_proxy proxy;
4591+
4592+	/* ...mutex lock */
4593+	struct mutex dsp_mutex;
4594+
4595+	struct dsp_data dsp_data;
4596+
4597+	/* ...global clients pool (item[0] serves as list terminator) */
4598+	union xf_client_link xf_client_map[XF_CFG_MAX_IPC_CLIENTS];
4599+
4600+	struct clk *esai_ipg_clk;
4601+	struct clk *esai_mclk;
4602+	struct clk *asrc_mem_clk;
4603+	struct clk *asrc_ipg_clk;
4604+	struct clk *asrck_clk[4];
4605+	struct clk *dsp_ocrama_clk;
4606+	struct clk *dsp_root_clk;
4607+	struct clk *audio_root_clk;
4608+	struct clk *audio_axi_clk;
4609+	struct clk *debug_clk;
4610+	struct clk *sdma_root_clk;
4611+	struct clk *sai_ipg_clk;
4612+	struct clk *sai_mclk;
4613+	struct clk *pll8k_clk;
4614+	struct clk *pll11k_clk;
4615+	struct clk *uart_ipg_clk;
4616+	struct clk *uart_per_clk;
4617+	struct clk *mu_a_clk;
4618+	struct clk *mu_b_clk;
4619+	struct clk *nic_clk;
4620+	struct clk *pb_clk;
4621+	struct device **pd_dev;
4622+	struct device_link **pd_dev_link;
4623+	struct regmap *regmap;
4624+	int    num_domains;
4625+};
4626+
4627+#define IRAM_OFFSET		0x10000
4628+#define IRAM_SIZE		2048
4629+
4630+#define DRAM0_OFFSET		0x0
4631+#define DRAM0_SIZE		0x8000
4632+
4633+#define DRAM1_OFFSET		0x8000
4634+#define DRAM1_SIZE		0x8000
4635+
4636+#define SYSRAM_OFFSET		0x18000
4637+#define SYSRAM_SIZE		0x40000
4638+
4639+#define SYSROM_OFFSET		0x58000
4640+#define SYSROM_SIZE		0x30000
4641+
4642+#define INPUT_BUF_SIZE		4096
4643+#define OUTPUT_BUF_SIZE		16384
4644+
4645+#define MSG_BUF_SIZE		8192
4646+#define DSP_CONFIG_SIZE		8192
4647+/* 1M memory for msg + config */
4648+#define MSG_PLUS_CONFIG_SIZE    0x100000
4649+
4650+void *memcpy_dsp(void *dest, const void *src, size_t count);
4651+void *memset_dsp(void *dest, int c, size_t count);
4652+struct xf_client *xf_client_lookup(struct fsl_dsp *dsp_priv, u32 id);
4653+struct xf_client *xf_client_alloc(struct fsl_dsp *dsp_priv);
4654+
4655+int fsl_dsp_open_func(struct fsl_dsp *dsp_priv, struct xf_client *client);
4656+int fsl_dsp_close_func(struct xf_client *client);
4657+
4658+/* DAP registers */
4659+#define IMX8M_DAP_DEBUG                0x28800000
4660+#define IMX8M_DAP_DEBUG_SIZE   (64 * 1024)
4661+#define IMX8M_DAP_PWRCTL       (0x4000 + 0x3020)
4662+#define IMX8M_PWRCTL_CORERESET         BIT(16)
4663+
4664+/* 8ULP SIM register */
4665+#define  REG_SIM_LPAV_SYSCTRL0     0x8
4666+#define  DSP_DBG_RST               BIT(25)
4667+#define  DSP_PLAT_CLK_EN           BIT(19)
4668+#define  DSP_PBCLK_EN              BIT(18)
4669+#define  DSP_CLK_EN                BIT(17)
4670+#define  DSP_RST                   BIT(16)
4671+#define  DSP_OCD_HALT              BIT(14)
4672+#define  DSP_STALL                 BIT(13)
4673+
4674+#define  FSL_SIP_HIFI_XRDC         0xc200000e
4675+
4676+#endif
4677diff --git a/sound/soc/fsl/fsl_dsp_audiomix.c b/sound/soc/fsl/fsl_dsp_audiomix.c
4678new file mode 100644
4679index 000000000..a8a3a35fb
4680--- /dev/null
4681+++ b/sound/soc/fsl/fsl_dsp_audiomix.c
4682@@ -0,0 +1,70 @@
4683+// SPDX-License-Identifier: GPL-2.0
4684+/*
4685+ * Copyright 2019 NXP.
4686+ */
4687+
4688+#include <linux/err.h>
4689+#include <linux/io.h>
4690+#include <linux/module.h>
4691+#include <linux/of.h>
4692+#include <linux/of_address.h>
4693+#include <linux/platform_device.h>
4694+#include <linux/regmap.h>
4695+#include <linux/mfd/syscon.h>
4696+#include <linux/pm_runtime.h>
4697+
4698+#include "fsl_dsp_audiomix.h"
4699+
4700+struct imx_audiomix_dsp_data {
4701+	struct regmap *regmap;
4702+};
4703+
4704+void imx_audiomix_dsp_runstall(struct imx_audiomix_dsp_data *data, u32 val)
4705+{
4706+	regmap_update_bits(data->regmap, AudioDSP_REG2, 1 << 5,  val);
4707+}
4708+EXPORT_SYMBOL(imx_audiomix_dsp_runstall);
4709+
4710+bool imx_audiomix_dsp_pwaitmode(struct imx_audiomix_dsp_data *data)
4711+{
4712+	u32 val;
4713+
4714+	regmap_read(data->regmap, AudioDSP_REG2, &val);
4715+	if (val & AudioDSP_REG2_PWAITMODE)
4716+		return true;
4717+	else
4718+		return false;
4719+}
4720+EXPORT_SYMBOL(imx_audiomix_dsp_pwaitmode);
4721+
4722+static int imx_audiomix_dsp_probe(struct platform_device *pdev)
4723+{
4724+	struct imx_audiomix_dsp_data *drvdata;
4725+
4726+	drvdata = devm_kzalloc(&pdev->dev, sizeof(*drvdata), GFP_KERNEL);
4727+	if (drvdata == NULL)
4728+		return -ENOMEM;
4729+
4730+	drvdata->regmap = syscon_regmap_lookup_by_compatible("fsl,imx8mp-audio-blk-ctrl");
4731+	if (IS_ERR(drvdata->regmap))
4732+		dev_warn(&pdev->dev, "cannot find iomuxc registers\n");
4733+
4734+	platform_set_drvdata(pdev, drvdata);
4735+	pm_runtime_enable(&pdev->dev);
4736+
4737+	return 0;
4738+}
4739+
4740+static const struct of_device_id imx_audiomix_dsp_dt_ids[] = {
4741+       { .compatible = "fsl,audiomix-dsp", },
4742+       { /* sentinel */ },
4743+};
4744+
4745+static struct platform_driver imx_audiomix_dsp_driver = {
4746+	.probe  = imx_audiomix_dsp_probe,
4747+	.driver = {
4748+		.name	= "audiomix-dsp",
4749+		.of_match_table = imx_audiomix_dsp_dt_ids,
4750+	},
4751+};
4752+module_platform_driver(imx_audiomix_dsp_driver);
4753diff --git a/sound/soc/fsl/fsl_dsp_audiomix.h b/sound/soc/fsl/fsl_dsp_audiomix.h
4754new file mode 100644
4755index 000000000..00c838565
4756--- /dev/null
4757+++ b/sound/soc/fsl/fsl_dsp_audiomix.h
4758@@ -0,0 +1,23 @@
4759+/* SPDX-License-Identifier: (GPL-2.0+ OR MIT)*/
4760+/*
4761+ * Copyright (C) 2017 Cadence Design Systems, Inc.
4762+ * Copyright 2018 NXP
4763+ *
4764+ */
4765+
4766+#ifndef FSL_DSP_AUDMIX_H
4767+#define FSL_DSP_AUDMIX_H
4768+
4769+#define AudioDSP_REG0 0x100
4770+#define AudioDSP_REG1 0x104
4771+#define AudioDSP_REG2 0x108
4772+#define AudioDSP_REG3 0x10c
4773+
4774+#define AudioDSP_REG2_RUNSTALL  BIT(5)
4775+#define AudioDSP_REG2_PWAITMODE BIT(1)
4776+
4777+struct imx_audiomix_dsp_data;
4778+void imx_audiomix_dsp_runstall(struct imx_audiomix_dsp_data *data, u32 val);
4779+bool imx_audiomix_dsp_pwaitmode(struct imx_audiomix_dsp_data *data);
4780+
4781+#endif
4782diff --git a/sound/soc/fsl/fsl_dsp_cpu.c b/sound/soc/fsl/fsl_dsp_cpu.c
4783new file mode 100644
4784index 000000000..e97d09ae0
4785--- /dev/null
4786+++ b/sound/soc/fsl/fsl_dsp_cpu.c
4787@@ -0,0 +1,97 @@
4788+// SPDX-License-Identifier: GPL-2.0+
4789+//
4790+// DSP Audio platform driver
4791+//
4792+// Copyright 2018 NXP
4793+
4794+#include <linux/clk.h>
4795+#include <linux/module.h>
4796+#include <linux/pm_runtime.h>
4797+#include <sound/soc.h>
4798+#include <sound/core.h>
4799+#include <sound/compress_driver.h>
4800+
4801+#include "fsl_dsp_cpu.h"
4802+
4803+static int dsp_audio_startup(struct snd_pcm_substream *substream,
4804+			     struct snd_soc_dai *cpu_dai) {
4805+	return 0;
4806+}
4807+
4808+
4809+static void dsp_audio_shutdown(struct snd_pcm_substream *substream,
4810+			       struct snd_soc_dai *cpu_dai) {
4811+}
4812+
4813+static const struct snd_soc_dai_ops dsp_audio_dai_ops = {
4814+	.startup = dsp_audio_startup,
4815+	.shutdown = dsp_audio_shutdown,
4816+};
4817+
4818+static struct snd_soc_dai_driver dsp_audio_dai = {
4819+	.name = "dsp-audio-cpu-dai",
4820+	.compress_new = snd_soc_new_compress,
4821+	.ops = &dsp_audio_dai_ops,
4822+	.playback = {
4823+		.stream_name = "Compress Playback",
4824+		.channels_min = 1,
4825+	},
4826+};
4827+
4828+static const struct snd_soc_component_driver audio_dsp_component = {
4829+	.name           = "audio-dsp",
4830+};
4831+
4832+static int dsp_audio_probe(struct platform_device *pdev)
4833+{
4834+	struct fsl_dsp_audio *dsp_audio;
4835+	int ret;
4836+
4837+	dsp_audio = devm_kzalloc(&pdev->dev, sizeof(*dsp_audio), GFP_KERNEL);
4838+	if (dsp_audio == NULL)
4839+		return -ENOMEM;
4840+
4841+	dev_dbg(&pdev->dev, "probing DSP device....\n");
4842+
4843+	/* intialise sof device */
4844+	dev_set_drvdata(&pdev->dev, dsp_audio);
4845+
4846+	pm_runtime_enable(&pdev->dev);
4847+
4848+	/* now register audio DSP platform driver */
4849+	ret = snd_soc_register_component(&pdev->dev, &audio_dsp_component,
4850+			&dsp_audio_dai, 1);
4851+	if (ret < 0) {
4852+		dev_err(&pdev->dev,
4853+			"error: failed to register DSP DAI driver %d\n", ret);
4854+		goto err;
4855+	}
4856+
4857+        return 0;
4858+
4859+err:
4860+	return ret;
4861+}
4862+
4863+static int dsp_audio_remove(struct platform_device *pdev)
4864+{
4865+	snd_soc_unregister_component(&pdev->dev);
4866+	return 0;
4867+}
4868+
4869+
4870+static const struct of_device_id dsp_audio_ids[] = {
4871+	{ .compatible = "fsl,dsp-audio"},
4872+	{ /* sentinel */ }
4873+};
4874+MODULE_DEVICE_TABLE(of, dsp_audio_ids);
4875+
4876+static struct platform_driver dsp_audio_driver = {
4877+	.driver = {
4878+		.name = "dsp-audio",
4879+		.of_match_table = dsp_audio_ids,
4880+	},
4881+	.probe = dsp_audio_probe,
4882+	.remove = dsp_audio_remove,
4883+};
4884+module_platform_driver(dsp_audio_driver);
4885diff --git a/sound/soc/fsl/fsl_dsp_cpu.h b/sound/soc/fsl/fsl_dsp_cpu.h
4886new file mode 100644
4887index 000000000..dac10b4ab
4888--- /dev/null
4889+++ b/sound/soc/fsl/fsl_dsp_cpu.h
4890@@ -0,0 +1,16 @@
4891+/* SPDX-License-Identifier: GPL-2.0+ */
4892+/*
4893+ * DSP Audio DAI header
4894+ *
4895+ * Copyright 2018 NXP
4896+ */
4897+
4898+#ifndef __FSL_DSP_CPU_H
4899+#define __FSL_DSP_CPU_H
4900+
4901+struct fsl_dsp_audio {
4902+	struct platform_device *pdev;
4903+};
4904+
4905+#endif /*__FSL_DSP_CPU_H*/
4906+
4907diff --git a/sound/soc/fsl/fsl_dsp_library_load.c b/sound/soc/fsl/fsl_dsp_library_load.c
4908new file mode 100644
4909index 000000000..d273f7296
4910--- /dev/null
4911+++ b/sound/soc/fsl/fsl_dsp_library_load.c
4912@@ -0,0 +1,642 @@
4913+// SPDX-License-Identifier: GPL-2.0+
4914+// Copyright 2018 NXP
4915+// Copyright (c) 2012-2013 by Tensilica Inc.
4916+
4917+#include <linux/fs.h>
4918+#include <linux/slab.h>
4919+#include <linux/elf.h>
4920+
4921+#include "fsl_dsp.h"
4922+#include "fsl_dsp_library_load.h"
4923+
4924+static Elf32_Half xtlib_host_half(Elf32_Half v, int byteswap)
4925+{
4926+	return (byteswap) ? (v >> 8) | (v << 8) : v;
4927+}
4928+
4929+static Elf32_Word xtlib_host_word(Elf32_Word v, int byteswap)
4930+{
4931+	if (byteswap) {
4932+		v = ((v & 0x00FF00FF) << 8) | ((v & 0xFF00FF00) >> 8);
4933+		v = (v >> 16) | (v << 16);
4934+	}
4935+	return v;
4936+}
4937+
4938+static int xtlib_verify_magic(Elf32_Ehdr *header,
4939+			      struct lib_info *lib_info)
4940+{
4941+	struct xtlib_loader_globals *xtlib_globals =
4942+					&lib_info->xtlib_globals;
4943+	Elf32_Byte magic_no;
4944+
4945+	magic_no =  header->e_ident[EI_MAG0];
4946+	if (magic_no != 0x7f)
4947+		return -1;
4948+
4949+	magic_no = header->e_ident[EI_MAG1];
4950+	if (magic_no != 'E')
4951+		return -1;
4952+
4953+	magic_no = header->e_ident[EI_MAG2];
4954+	if (magic_no != 'L')
4955+		return -1;
4956+
4957+	magic_no = header->e_ident[EI_MAG3];
4958+	if (magic_no != 'F')
4959+		return -1;
4960+
4961+	if (header->e_ident[EI_CLASS] != ELFCLASS32)
4962+		return -1;
4963+
4964+	{
4965+		/* determine byte order  */
4966+		union {
4967+			short s;
4968+			char c[sizeof(short)];
4969+		} u;
4970+
4971+		u.s = 1;
4972+
4973+		if (header->e_ident[EI_DATA] == ELFDATA2LSB)
4974+			xtlib_globals->byteswap = u.c[sizeof(short) - 1] == 1;
4975+		else if (header->e_ident[EI_DATA] == ELFDATA2MSB)
4976+			xtlib_globals->byteswap = u.c[0] == 1;
4977+		else
4978+			return -1;
4979+	}
4980+
4981+	return 0;
4982+}
4983+
4984+static void xtlib_load_seg(Elf32_Phdr *pheader, void *src_addr, xt_ptr dst_addr,
4985+			   struct lib_info *lib_info)
4986+{
4987+	struct xtlib_loader_globals *xtlib_globals =
4988+					&lib_info->xtlib_globals;
4989+	Elf32_Word bytes_to_copy = xtlib_host_word(pheader->p_filesz,
4990+						xtlib_globals->byteswap);
4991+	Elf32_Word bytes_to_zero = xtlib_host_word(pheader->p_memsz,
4992+						xtlib_globals->byteswap)
4993+						- bytes_to_copy;
4994+	unsigned int i;
4995+	char *src_back, *dst_back;
4996+
4997+	void *zero_addr = (void *)dst_addr + bytes_to_copy;
4998+
4999+	if (bytes_to_copy > 0) {
5000+	//	memcpy((void *)(dst_addr), src_addr, bytes_to_copy);
5001+		src_back = (char *)src_addr;
5002+		dst_back = (char *)dst_addr;
5003+		for (i = 0; i < bytes_to_copy; i++)
5004+			*dst_back++ = *src_back++;
5005+	}
5006+
5007+	if (bytes_to_zero > 0) {
5008+	//	memset(zero_addr, 0, bytes_to_zero);
5009+		dst_back = (char *)zero_addr;
5010+		for (i = 0; i < bytes_to_zero; i++)
5011+			*dst_back++ = 0;
5012+	}
5013+}
5014+
5015+#define xtlib_xt_half  xtlib_host_half
5016+#define xtlib_xt_word  xtlib_host_word
5017+
5018+static xt_ptr align_ptr(xt_ptr ptr, xt_uint align)
5019+{
5020+	return (xt_ptr)(((xt_uint)ptr + align - 1) & ~(align - 1));
5021+}
5022+
5023+static xt_ptr xt_ptr_offs(xt_ptr base, Elf32_Word offs,
5024+			  struct lib_info *lib_info)
5025+{
5026+	struct xtlib_loader_globals *xtlib_globals =
5027+					&lib_info->xtlib_globals;
5028+
5029+	return (xt_ptr)xtlib_xt_word((xt_uint)base +
5030+		xtlib_host_word(offs, xtlib_globals->byteswap),
5031+			xtlib_globals->byteswap);
5032+}
5033+
5034+static Elf32_Dyn *find_dynamic_info(Elf32_Ehdr *eheader,
5035+				    struct lib_info *lib_info)
5036+{
5037+	char *base_addr = (char *)eheader;
5038+	struct xtlib_loader_globals *xtlib_globals =
5039+					&lib_info->xtlib_globals;
5040+	Elf32_Phdr *pheader = (Elf32_Phdr *)(base_addr +
5041+			xtlib_host_word(eheader->e_phoff,
5042+					xtlib_globals->byteswap));
5043+
5044+	int seg = 0;
5045+	int num = xtlib_host_half(eheader->e_phnum, xtlib_globals->byteswap);
5046+
5047+	while (seg < num) {
5048+		if (xtlib_host_word(pheader[seg].p_type,
5049+				    xtlib_globals->byteswap) == PT_DYNAMIC) {
5050+			return (Elf32_Dyn *)(base_addr +
5051+				xtlib_host_word(pheader[seg].p_offset,
5052+						xtlib_globals->byteswap));
5053+		}
5054+		seg++;
5055+	}
5056+	return 0;
5057+}
5058+
5059+static int find_align(Elf32_Ehdr *header,
5060+		      struct lib_info *lib_info)
5061+{
5062+	struct xtlib_loader_globals *xtlib_globals =
5063+					&lib_info->xtlib_globals;
5064+	Elf32_Shdr *sheader = (Elf32_Shdr *) (((char *)header) +
5065+		xtlib_host_word(header->e_shoff, xtlib_globals->byteswap));
5066+
5067+	int sec = 0;
5068+	int num = xtlib_host_half(header->e_shnum, xtlib_globals->byteswap);
5069+
5070+	int align = 0;
5071+
5072+	while (sec < num) {
5073+		if (sheader[sec].sh_type != SHT_NULL &&
5074+		    xtlib_host_word(sheader[sec].sh_size,
5075+				    xtlib_globals->byteswap) > 0) {
5076+			int sec_align =
5077+				xtlib_host_word(sheader[sec].sh_addralign,
5078+						xtlib_globals->byteswap);
5079+			if (sec_align > align)
5080+				align = sec_align;
5081+		}
5082+		sec++;
5083+	}
5084+
5085+	return align;
5086+}
5087+
5088+static int validate_dynamic(Elf32_Ehdr *header,
5089+			    struct lib_info *lib_info)
5090+{
5091+	struct xtlib_loader_globals *xtlib_globals =
5092+					&lib_info->xtlib_globals;
5093+
5094+	if (xtlib_verify_magic(header, lib_info) != 0)
5095+		return XTLIB_NOT_ELF;
5096+
5097+	if (xtlib_host_half(header->e_type,
5098+			    xtlib_globals->byteswap) != ET_DYN)
5099+		return XTLIB_NOT_DYNAMIC;
5100+
5101+	return XTLIB_NO_ERR;
5102+}
5103+
5104+static int validate_dynamic_splitload(Elf32_Ehdr *header,
5105+				      struct lib_info *lib_info)
5106+{
5107+	struct xtlib_loader_globals *xtlib_globals =
5108+					&lib_info->xtlib_globals;
5109+	Elf32_Phdr *pheader;
5110+	int err = validate_dynamic(header, lib_info);
5111+
5112+	if (err != XTLIB_NO_ERR)
5113+		return err;
5114+
5115+	/* make sure it's split load pi library, expecting three headers,
5116+	 * code, data and dynamic, for example:
5117+	 *
5118+	 *LOAD	off    0x00000094 vaddr 0x00000000 paddr 0x00000000 align 2**0
5119+	 *	filesz 0x00000081 memsz 0x00000081 flags r-x
5120+	 *LOAD  off    0x00000124 vaddr 0x00000084 paddr 0x00000084 align 2**0
5121+	 *	filesz 0x000001ab memsz 0x000011bc flags rwx
5122+	 *DYNAMIC off  0x00000124 vaddr 0x00000084 paddr 0x00000084 align 2**2
5123+	 *	  filesz 0x000000a0 memsz 0x000000a0 flags rw-
5124+	 */
5125+
5126+	if (xtlib_host_half(header->e_phnum, xtlib_globals->byteswap) != 3)
5127+		return XTLIB_NOT_SPLITLOAD;
5128+
5129+	pheader = (Elf32_Phdr *)((char *)header +
5130+		xtlib_host_word(header->e_phoff, xtlib_globals->byteswap));
5131+
5132+	/* LOAD R-X */
5133+	if (xtlib_host_word(pheader[0].p_type,
5134+			    xtlib_globals->byteswap) != PT_LOAD ||
5135+				(xtlib_host_word(pheader[0].p_flags,
5136+						xtlib_globals->byteswap)
5137+				& (PF_R | PF_W | PF_X)) != (PF_R | PF_X))
5138+		return XTLIB_NOT_SPLITLOAD;
5139+
5140+	/* LOAD RWX */
5141+	if (xtlib_host_word(pheader[1].p_type,
5142+			    xtlib_globals->byteswap) != PT_LOAD ||
5143+			(xtlib_host_word(pheader[1].p_flags,
5144+			xtlib_globals->byteswap)
5145+			& (PF_R | PF_W | PF_X)) != (PF_R | PF_W | PF_X))
5146+		return XTLIB_NOT_SPLITLOAD;
5147+
5148+	/* DYNAMIC RW- */
5149+	if (xtlib_host_word(pheader[2].p_type,
5150+			    xtlib_globals->byteswap) != PT_DYNAMIC ||
5151+			(xtlib_host_word(pheader[2].p_flags,
5152+			xtlib_globals->byteswap)
5153+			& (PF_R | PF_W | PF_X)) != (PF_R | PF_W))
5154+		return XTLIB_NOT_SPLITLOAD;
5155+
5156+	return XTLIB_NO_ERR;
5157+}
5158+
5159+static unsigned int
5160+xtlib_split_pi_library_size(struct xtlib_packaged_library *library,
5161+			    unsigned int *code_size,
5162+			    unsigned int *data_size,
5163+			    struct lib_info *lib_info)
5164+{
5165+	struct xtlib_loader_globals *xtlib_globals =
5166+					&lib_info->xtlib_globals;
5167+	Elf32_Phdr *pheader;
5168+	Elf32_Ehdr *header = (Elf32_Ehdr *)library;
5169+	int align;
5170+	int err = validate_dynamic_splitload(header, lib_info);
5171+
5172+	if (err != XTLIB_NO_ERR) {
5173+		xtlib_globals->err = err;
5174+		return err;
5175+	}
5176+
5177+	align = find_align(header, lib_info);
5178+
5179+	pheader = (Elf32_Phdr *)((char *)library +
5180+		xtlib_host_word(header->e_phoff, xtlib_globals->byteswap));
5181+
5182+	*code_size = xtlib_host_word(pheader[0].p_memsz,
5183+					xtlib_globals->byteswap) + align;
5184+	*data_size = xtlib_host_word(pheader[1].p_memsz,
5185+					xtlib_globals->byteswap) + align;
5186+
5187+	return XTLIB_NO_ERR;
5188+}
5189+
5190+static int get_dyn_info(Elf32_Ehdr *eheader,
5191+			xt_ptr dst_addr, xt_uint src_offs,
5192+			xt_ptr dst_data_addr, xt_uint src_data_offs,
5193+			struct xtlib_pil_info *info,
5194+			struct lib_info *lib_info)
5195+{
5196+	unsigned int jmprel = 0;
5197+	unsigned int pltrelsz = 0;
5198+	struct xtlib_loader_globals *xtlib_globals =
5199+					&lib_info->xtlib_globals;
5200+	Elf32_Dyn *dyn_entry = find_dynamic_info(eheader, lib_info);
5201+
5202+	if (dyn_entry == 0)
5203+		return XTLIB_NO_DYNAMIC_SEGMENT;
5204+
5205+	info->dst_addr = (xt_uint)xtlib_xt_word((Elf32_Word)dst_addr,
5206+						xtlib_globals->byteswap);
5207+	info->src_offs = xtlib_xt_word(src_offs, xtlib_globals->byteswap);
5208+	info->dst_data_addr = (xt_uint)xtlib_xt_word(
5209+			(Elf32_Word)dst_data_addr + src_data_offs,
5210+			xtlib_globals->byteswap);
5211+	info->src_data_offs = xtlib_xt_word(src_data_offs,
5212+				xtlib_globals->byteswap);
5213+
5214+	dst_addr -= src_offs;
5215+	dst_data_addr = dst_data_addr + src_data_offs - src_data_offs;
5216+
5217+	info->start_sym = xt_ptr_offs(dst_addr, eheader->e_entry, lib_info);
5218+
5219+	info->align = xtlib_xt_word(find_align(eheader, lib_info),
5220+					xtlib_globals->byteswap);
5221+
5222+	info->text_addr = 0;
5223+
5224+	while (dyn_entry->d_tag != DT_NULL) {
5225+		switch ((Elf32_Sword) xtlib_host_word(
5226+			(Elf32_Word)dyn_entry->d_tag,
5227+			xtlib_globals->byteswap)) {
5228+		case DT_RELA:
5229+			info->rel = xt_ptr_offs(dst_data_addr,
5230+					dyn_entry->d_un.d_ptr, lib_info);
5231+			break;
5232+		case DT_RELASZ:
5233+			info->rela_count = xtlib_xt_word(
5234+				xtlib_host_word(dyn_entry->d_un.d_val,
5235+						xtlib_globals->byteswap) /
5236+				sizeof(Elf32_Rela),
5237+				xtlib_globals->byteswap);
5238+			break;
5239+		case DT_INIT:
5240+			info->init = xt_ptr_offs(dst_addr,
5241+					dyn_entry->d_un.d_ptr, lib_info);
5242+			break;
5243+		case DT_FINI:
5244+			info->fini = xt_ptr_offs(dst_addr,
5245+					dyn_entry->d_un.d_ptr, lib_info);
5246+			break;
5247+		case DT_HASH:
5248+			info->hash = xt_ptr_offs(dst_data_addr,
5249+					dyn_entry->d_un.d_ptr, lib_info);
5250+			break;
5251+		case DT_SYMTAB:
5252+			info->symtab = xt_ptr_offs(dst_data_addr,
5253+					dyn_entry->d_un.d_ptr, lib_info);
5254+			break;
5255+		case DT_STRTAB:
5256+			info->strtab = xt_ptr_offs(dst_data_addr,
5257+					dyn_entry->d_un.d_ptr, lib_info);
5258+			break;
5259+		case DT_JMPREL:
5260+			jmprel = dyn_entry->d_un.d_val;
5261+			break;
5262+		case DT_PLTRELSZ:
5263+			pltrelsz = dyn_entry->d_un.d_val;
5264+			break;
5265+		case DT_LOPROC + 2:
5266+			info->text_addr = xt_ptr_offs(dst_addr,
5267+					dyn_entry->d_un.d_ptr, lib_info);
5268+			break;
5269+
5270+		default:
5271+			/* do nothing */
5272+			break;
5273+		}
5274+		dyn_entry++;
5275+	}
5276+
5277+	return XTLIB_NO_ERR;
5278+}
5279+
5280+static xt_ptr
5281+xtlib_load_split_pi_library_common(struct xtlib_packaged_library *library,
5282+				   xt_ptr destination_code_address,
5283+				   xt_ptr destination_data_address,
5284+				   struct xtlib_pil_info *info,
5285+				   struct lib_info *lib_info)
5286+{
5287+	struct xtlib_loader_globals *xtlib_globals =
5288+					&lib_info->xtlib_globals;
5289+	Elf32_Ehdr *header = (Elf32_Ehdr *)library;
5290+	Elf32_Phdr *pheader;
5291+	unsigned int align;
5292+	int err = validate_dynamic_splitload(header, lib_info);
5293+	xt_ptr destination_code_address_back;
5294+	xt_ptr destination_data_address_back;
5295+
5296+	if (err != XTLIB_NO_ERR) {
5297+		xtlib_globals->err = err;
5298+		return 0;
5299+	}
5300+
5301+	align = find_align(header, lib_info);
5302+
5303+	destination_code_address_back = destination_code_address;
5304+	destination_data_address_back = destination_data_address;
5305+
5306+	destination_code_address = align_ptr(destination_code_address, align);
5307+	destination_data_address = align_ptr(destination_data_address, align);
5308+	lib_info->code_buf_virt += (destination_code_address -
5309+				destination_code_address_back);
5310+	lib_info->data_buf_virt += (destination_data_address -
5311+				destination_data_address_back);
5312+
5313+	pheader = (Elf32_Phdr *)((char *)library +
5314+			xtlib_host_word(header->e_phoff,
5315+					xtlib_globals->byteswap));
5316+
5317+	err = get_dyn_info(header,
5318+			   destination_code_address,
5319+			   xtlib_host_word(pheader[0].p_paddr,
5320+					   xtlib_globals->byteswap),
5321+			   destination_data_address,
5322+			   xtlib_host_word(pheader[1].p_paddr,
5323+					   xtlib_globals->byteswap),
5324+			   info,
5325+			   lib_info);
5326+
5327+	if (err != XTLIB_NO_ERR) {
5328+		xtlib_globals->err = err;
5329+		return 0;
5330+	}
5331+
5332+	/* loading code */
5333+	xtlib_load_seg(&pheader[0],
5334+		       (char *)library + xtlib_host_word(pheader[0].p_offset,
5335+			xtlib_globals->byteswap),
5336+			(xt_ptr)lib_info->code_buf_virt,
5337+			lib_info);
5338+
5339+	if (info->text_addr == 0)
5340+		info->text_addr =
5341+		(xt_ptr)xtlib_xt_word((Elf32_Word)destination_code_address,
5342+						xtlib_globals->byteswap);
5343+
5344+	/* loading data */
5345+	xtlib_load_seg(&pheader[1],
5346+		       (char *)library + xtlib_host_word(pheader[1].p_offset,
5347+						xtlib_globals->byteswap),
5348+		  (xt_ptr)lib_info->data_buf_virt +
5349+		  xtlib_host_word(pheader[1].p_paddr,
5350+				  xtlib_globals->byteswap),
5351+		  lib_info);
5352+
5353+	return (xt_ptr)xtlib_host_word((Elf32_Word)info->start_sym,
5354+				       xtlib_globals->byteswap);
5355+}
5356+
5357+static xt_ptr
5358+xtlib_host_load_split_pi_library(struct xtlib_packaged_library *library,
5359+				 xt_ptr destination_code_address,
5360+				 xt_ptr destination_data_address,
5361+				 struct xtlib_pil_info *info,
5362+				 struct lib_info *lib_info)
5363+{
5364+	return  xtlib_load_split_pi_library_common(library,
5365+						   destination_code_address,
5366+						   destination_data_address,
5367+						   info,
5368+						   lib_info);
5369+}
5370+
5371+static long
5372+load_dpu_with_library(struct xf_client *client, struct xf_proxy *proxy,
5373+		      struct lib_info *lib_info)
5374+{
5375+	struct fsl_dsp *dsp_priv = container_of(proxy, struct fsl_dsp, proxy);
5376+	unsigned char *srambuf;
5377+	struct lib_dnld_info_t dpulib;
5378+	struct file *file;
5379+	struct xf_buffer *buf;
5380+	Elf32_Phdr *pheader;
5381+	Elf32_Ehdr *header;
5382+	loff_t pos = 0;
5383+	unsigned int align;
5384+	int filesize = 0;
5385+	long ret_val = 0;
5386+
5387+	file = filp_open(lib_info->filename, O_RDONLY, 0);
5388+	if (IS_ERR(file))
5389+		return PTR_ERR(file);
5390+
5391+	vfs_llseek(file, 0, SEEK_END);
5392+	filesize = (int)file->f_pos;
5393+
5394+	srambuf = kmalloc(filesize, GFP_KERNEL);
5395+	if (!srambuf)
5396+		return -ENOMEM;
5397+
5398+	vfs_llseek(file, 0, SEEK_SET);
5399+	ret_val = kernel_read(file, srambuf, filesize, &pos);
5400+	if (ret_val < 0)
5401+		return ret_val;
5402+	filp_close(file, NULL);
5403+
5404+	ret_val = xtlib_split_pi_library_size(
5405+			(struct xtlib_packaged_library *)(srambuf),
5406+			(unsigned int *)&dpulib.size_code,
5407+			(unsigned int *)&dpulib.size_data,
5408+			lib_info);
5409+	if (ret_val != XTLIB_NO_ERR)
5410+		return -EINVAL;
5411+
5412+	lib_info->code_buf_size = dpulib.size_code;
5413+	lib_info->data_buf_size = dpulib.size_data;
5414+
5415+	header = (Elf32_Ehdr *)srambuf;
5416+	pheader = (Elf32_Phdr *)((char *)srambuf +
5417+				xtlib_host_word(header->e_phoff,
5418+						lib_info->xtlib_globals.byteswap));
5419+
5420+	align = find_align(header, lib_info);
5421+	ret_val = xf_pool_alloc(client, proxy, 1, dpulib.size_code + align,
5422+				XF_POOL_AUX, &lib_info->code_section_pool);
5423+        if (ret_val) {
5424+                kfree(srambuf);
5425+                pr_err("Allocation failure for loading code section\n");
5426+                return -ENOMEM;
5427+        }
5428+
5429+        ret_val = xf_pool_alloc(client, proxy, 1,
5430+                                dpulib.size_data + pheader[1].p_paddr + align,
5431+                                XF_POOL_AUX, &lib_info->data_section_pool);
5432+        if (ret_val) {
5433+                kfree(srambuf);
5434+                pr_err("Allocation failure for loading data section\n");
5435+                return -ENOMEM;
5436+        }
5437+
5438+	buf = xf_buffer_get(lib_info->code_section_pool);
5439+	lib_info->code_buf_virt = xf_buffer_data(buf);
5440+	lib_info->code_buf_phys = ((u64)xf_buffer_data(buf) -
5441+					(u64)dsp_priv->scratch_buf_virt) +
5442+					dsp_priv->scratch_buf_phys;
5443+	lib_info->code_buf_size = dpulib.size_code + align;
5444+	xf_buffer_put(buf);
5445+
5446+	buf = xf_buffer_get(lib_info->data_section_pool);
5447+	lib_info->data_buf_virt = xf_buffer_data(buf);
5448+	lib_info->data_buf_phys = ((u64)xf_buffer_data(buf) -
5449+					(u64)dsp_priv->scratch_buf_virt) +
5450+					dsp_priv->scratch_buf_phys;
5451+	lib_info->data_buf_size = dpulib.size_data + align + pheader[1].p_paddr;
5452+	xf_buffer_put(buf);
5453+
5454+	dpulib.pbuf_code = (unsigned long)lib_info->code_buf_phys;
5455+	dpulib.pbuf_data = (unsigned long)lib_info->data_buf_phys;
5456+
5457+	dpulib.ppil_inf = &lib_info->pil_info;
5458+	xtlib_host_load_split_pi_library((struct xtlib_packaged_library *)srambuf,
5459+					 (xt_ptr)(dpulib.pbuf_code),
5460+					 (xt_ptr)(dpulib.pbuf_data),
5461+					 (struct xtlib_pil_info *)dpulib.ppil_inf,
5462+					 (void *)lib_info);
5463+	kfree(srambuf);
5464+
5465+	return ret_val;
5466+}
5467+
5468+static long
5469+unload_dpu_with_library(struct xf_client *client, struct xf_proxy *proxy,
5470+			struct lib_info *lib_info)
5471+{
5472+        xf_pool_free(client, lib_info->code_section_pool);
5473+        xf_pool_free(client, lib_info->data_section_pool);
5474+
5475+	return 0;
5476+}
5477+
5478+long xf_load_lib(struct xf_client *client,
5479+		struct xf_handle *handle, struct lib_info *lib_info)
5480+{
5481+	void *b = xf_handle_aux(handle);
5482+	struct icm_xtlib_pil_info icm_info;
5483+	struct xf_proxy *proxy = handle->proxy;
5484+	struct xf_message  msg;
5485+	struct xf_message *rmsg;
5486+	long ret_val;
5487+
5488+	ret_val = load_dpu_with_library(client, proxy, lib_info);
5489+	if (ret_val)
5490+		return ret_val;
5491+
5492+	memcpy((void *)(&icm_info.pil_info), (void *)(&lib_info->pil_info),
5493+	       sizeof(struct xtlib_pil_info));
5494+
5495+	icm_info.lib_type = lib_info->lib_type;
5496+
5497+	/* ...set message parameters */
5498+	msg.id = __XF_MSG_ID(__XF_AP_CLIENT(0, 0), __XF_PORT_SPEC2(handle->id, 0));
5499+	msg.id = XF_MSG_AP_FROM_USER(msg.id, client->id);
5500+        msg.opcode = XF_LOAD_LIB;
5501+        msg.buffer = b;
5502+        msg.length = sizeof(struct icm_xtlib_pil_info);
5503+        msg.ret = 0;
5504+
5505+        /* ...copy lib info */
5506+        memcpy(b, (void *)&icm_info, xf_buffer_length(handle->aux));
5507+
5508+        /* ...execute command synchronously */
5509+	rmsg = xf_cmd_send_recv_complete(client, proxy, msg.id, msg.opcode,
5510+					 msg.buffer, msg.length, &client->work,
5511+					 &client->compr_complete);
5512+	if (IS_ERR(rmsg))
5513+		return PTR_ERR(rmsg);
5514+
5515+//	xf_msg_free(proxy, rmsg);
5516+//	xf_unlock(&proxy->lock);
5517+
5518+	return 0;
5519+}
5520+
5521+long xf_unload_lib(struct xf_client *client, struct xf_handle *handle, struct lib_info *lib_info)
5522+{
5523+	void *b = xf_handle_aux(handle);
5524+	struct xf_proxy *proxy = handle->proxy;
5525+	struct xf_message msg;
5526+	struct xf_message *rmsg;
5527+	struct icm_xtlib_pil_info icm_info;
5528+
5529+	memset((void *)&icm_info, 0, sizeof(struct icm_xtlib_pil_info));
5530+	icm_info.lib_type = lib_info->lib_type;
5531+
5532+	/* ...set message parameters */
5533+	msg.id = __XF_MSG_ID(__XF_AP_CLIENT(0, 0),__XF_PORT_SPEC2(handle->id, 0));
5534+	msg.id = XF_MSG_AP_FROM_USER(msg.id, client->id);
5535+	msg.opcode = XF_UNLOAD_LIB;
5536+	msg.buffer = b;
5537+	msg.length = sizeof(struct icm_xtlib_pil_info);
5538+	msg.ret = 0;
5539+
5540+	/* ...copy lib info */
5541+	memcpy(b, (void *)&icm_info, xf_buffer_length(handle->aux));
5542+
5543+	/* ...execute command synchronously */
5544+	rmsg = xf_cmd_send_recv_complete(client, proxy, msg.id, msg.opcode,
5545+					 msg.buffer, msg.length, &client->work,
5546+					 &client->compr_complete);
5547+	if (IS_ERR(rmsg))
5548+		return PTR_ERR(rmsg);
5549+
5550+//	xf_msg_free(proxy, rmsg);
5551+//	xf_unlock(&proxy->lock);
5552+
5553+	return unload_dpu_with_library(client, proxy, lib_info);
5554+}
5555diff --git a/sound/soc/fsl/fsl_dsp_library_load.h b/sound/soc/fsl/fsl_dsp_library_load.h
5556new file mode 100644
5557index 000000000..8c14dda20
5558--- /dev/null
5559+++ b/sound/soc/fsl/fsl_dsp_library_load.h
5560@@ -0,0 +1,92 @@
5561+// SPDX-License-Identifier: GPL-2.0+
5562+// Copyright 2018 NXP
5563+// Copyright (c) 2012-2013 by Tensilica Inc.
5564+
5565+#ifndef FSL_DSP_LIBRARY_LOAD_H
5566+#define FSL_DSP_LIBRARY_LOAD_H
5567+
5568+#include "fsl_dsp_pool.h"
5569+
5570+#define Elf32_Byte  unsigned char
5571+#define xt_ptr      unsigned long
5572+#define xt_int      int
5573+#define xt_uint     unsigned int
5574+#define xt_ulong    unsigned long
5575+
5576+struct xtlib_packaged_library;
5577+
5578+enum {
5579+	XTLIB_NO_ERR = 0,
5580+	XTLIB_NOT_ELF = 1,
5581+	XTLIB_NOT_DYNAMIC = 2,
5582+	XTLIB_NOT_STATIC = 3,
5583+	XTLIB_NO_DYNAMIC_SEGMENT = 4,
5584+	XTLIB_UNKNOWN_SYMBOL = 5,
5585+	XTLIB_NOT_ALIGNED = 6,
5586+	XTLIB_NOT_SPLITLOAD = 7,
5587+	XTLIB_RELOCATION_ERR = 8
5588+};
5589+
5590+enum lib_type {
5591+	DSP_CODEC_LIB = 1,
5592+	DSP_CODEC_WRAP_LIB
5593+};
5594+
5595+struct xtlib_loader_globals {
5596+	int err;
5597+	int byteswap;
5598+};
5599+
5600+struct xtlib_pil_info {
5601+	xt_uint  dst_addr;
5602+	xt_uint  src_offs;
5603+	xt_uint  dst_data_addr;
5604+	xt_uint  src_data_offs;
5605+	xt_uint  start_sym;
5606+	xt_uint  text_addr;
5607+	xt_uint  init;
5608+	xt_uint  fini;
5609+	xt_uint  rel;
5610+	xt_int  rela_count;
5611+	xt_uint  hash;
5612+	xt_uint  symtab;
5613+	xt_uint  strtab;
5614+	xt_int  align;
5615+};
5616+
5617+struct icm_xtlib_pil_info {
5618+	struct xtlib_pil_info pil_info;
5619+	unsigned int lib_type;
5620+};
5621+
5622+struct lib_dnld_info_t {
5623+	unsigned long pbuf_code;
5624+	unsigned long pbuf_data;
5625+	unsigned int size_code;
5626+	unsigned int size_data;
5627+	struct xtlib_pil_info *ppil_inf;
5628+	unsigned int lib_on_dpu;    /* 0: not loaded, 1: loaded. */
5629+};
5630+
5631+struct lib_info {
5632+	struct xtlib_pil_info  pil_info;
5633+	struct xtlib_loader_globals	xtlib_globals;
5634+
5635+	struct xf_pool	 *code_section_pool;
5636+	struct xf_pool	 *data_section_pool;
5637+
5638+	void        *code_buf_virt;
5639+	unsigned int code_buf_phys;
5640+	unsigned int code_buf_size;
5641+	void        *data_buf_virt;
5642+	unsigned int data_buf_phys;
5643+	unsigned int data_buf_size;
5644+
5645+	const char   *filename;
5646+	unsigned int lib_type;
5647+};
5648+
5649+long xf_load_lib(struct xf_client *client, struct xf_handle *handle, struct lib_info *lib_info);
5650+long xf_unload_lib(struct xf_client *client, struct xf_handle *handle, struct lib_info *lib_info);
5651+
5652+#endif
5653diff --git a/sound/soc/fsl/fsl_dsp_platform.h b/sound/soc/fsl/fsl_dsp_platform.h
5654new file mode 100644
5655index 000000000..b29f34b78
5656--- /dev/null
5657+++ b/sound/soc/fsl/fsl_dsp_platform.h
5658@@ -0,0 +1,22 @@
5659+/* SPDX-License-Identifier: GPL-2.0+ */
5660+/*
5661+ * Copyright (c) 2012-2013 by Tensilica Inc. ALL RIGHTS RESERVED.
5662+ * Copyright 2018 NXP
5663+ */
5664+
5665+#ifndef _FSL_DSP_PLATFORM_H
5666+#define _FSL_DSP_PLATFORM_H
5667+
5668+#include "fsl_dsp_xaf_api.h"
5669+
5670+struct dsp_data {
5671+	struct xf_client      *client;
5672+	struct xaf_pipeline   *p_pipe;
5673+	struct xaf_pipeline    pipeline;
5674+	struct xaf_comp        component[2];
5675+	int codec_type;
5676+	int renderer_type;
5677+	int status;
5678+};
5679+
5680+#endif /*_FSL_DSP_PLATFORM_H*/
5681diff --git a/sound/soc/fsl/fsl_dsp_platform_compress.c b/sound/soc/fsl/fsl_dsp_platform_compress.c
5682new file mode 100644
5683index 000000000..c2f09dfaf
5684--- /dev/null
5685+++ b/sound/soc/fsl/fsl_dsp_platform_compress.c
5686@@ -0,0 +1,744 @@
5687+// SPDX-License-Identifier: GPL-2.0+
5688+//
5689+// DSP driver compress implementation
5690+//
5691+// Copyright (c) 2012-2013 by Tensilica Inc. ALL RIGHTS RESERVED.
5692+// Copyright 2018-2020 NXP
5693+
5694+#include <linux/pm_runtime.h>
5695+#include <sound/soc.h>
5696+#include <sound/core.h>
5697+#include <sound/compress_driver.h>
5698+
5699+#include "fsl_dsp.h"
5700+#include "fsl_dsp_platform.h"
5701+#include "fsl_dsp_xaf_api.h"
5702+
5703+#define NUM_CODEC 3
5704+#define MIN_FRAGMENT 1
5705+#define MAX_FRAGMENT 1
5706+#define MIN_FRAGMENT_SIZE (4 * 1024)
5707+#define MAX_FRAGMENT_SIZE (4 * 1024)
5708+
5709+void dsp_platform_process(struct work_struct *w)
5710+{
5711+	struct xf_client *client = container_of(w, struct xf_client, work);
5712+	struct xf_proxy  *proxy  = client->proxy;
5713+	struct xf_message *rmsg;
5714+
5715+	while (1) {
5716+		rmsg = xf_cmd_recv(proxy, &client->wait, &client->queue, 1);
5717+
5718+		if (!proxy->is_active || IS_ERR(rmsg))
5719+			return;
5720+		if (rmsg->opcode == XF_EMPTY_THIS_BUFFER) {
5721+			client->consume_bytes += rmsg->length;
5722+			atomic_inc(&client->buffer_cnt);
5723+			snd_compr_fragment_elapsed(client->cstream);
5724+
5725+			if (rmsg->buffer == NULL && rmsg->length == 0)
5726+				snd_compr_drain_notify(client->cstream);
5727+
5728+		} else {
5729+			memcpy(&client->m, rmsg, sizeof(struct xf_message));
5730+			complete(&client->compr_complete);
5731+		}
5732+
5733+		xf_msg_free(proxy, rmsg);
5734+		xf_unlock(&proxy->lock);
5735+	}
5736+}
5737+
5738+static int dsp_platform_compr_open(struct snd_soc_component *component,
5739+				   struct snd_compr_stream *cstream)
5740+{
5741+	struct snd_soc_pcm_runtime *rtd = cstream->private_data;
5742+	struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(rtd, 0);
5743+	struct fsl_dsp  *dsp_priv = snd_soc_component_get_drvdata(component);
5744+	struct dsp_data *drv = &dsp_priv->dsp_data;
5745+
5746+	if (drv->client)
5747+		return -EBUSY;
5748+	drv->client = xf_client_alloc(dsp_priv);
5749+	if (IS_ERR(drv->client))
5750+		return PTR_ERR(drv->client);
5751+
5752+	fsl_dsp_open_func(dsp_priv, drv->client);
5753+
5754+	drv->client->proxy = &dsp_priv->proxy;
5755+
5756+	cpu_dai->driver->ops->startup(NULL, cpu_dai);
5757+
5758+	drv->client->cstream = cstream;
5759+
5760+	INIT_WORK(&drv->client->work, dsp_platform_process);
5761+
5762+	return 0;
5763+}
5764+
5765+static int dsp_platform_compr_free(struct snd_soc_component *component,
5766+				   struct snd_compr_stream *cstream)
5767+{
5768+	struct snd_soc_pcm_runtime *rtd = cstream->private_data;
5769+	struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(rtd, 0);
5770+	struct fsl_dsp  *dsp_priv = snd_soc_component_get_drvdata(component);
5771+	struct dsp_data *drv = &dsp_priv->dsp_data;
5772+	struct xf_proxy *p_proxy = &dsp_priv->proxy;
5773+	int ret;
5774+
5775+	if (cstream->runtime->state != SNDRV_PCM_STATE_PAUSED &&
5776+		cstream->runtime->state != SNDRV_PCM_STATE_DRAINING) {
5777+		if (dsp_priv->dsp_is_lpa) {
5778+			ret = xaf_comp_flush(drv->client, &drv->component[0]);
5779+			if (ret) {
5780+				dev_err(component->dev, "Fail to flush component, err = %d\n", ret);
5781+				return ret;
5782+			}
5783+
5784+			ret = xaf_comp_flush(drv->client, &drv->component[1]);
5785+			if (ret) {
5786+				dev_err(component->dev, "Fail to flush component, err = %d\n", ret);
5787+				return ret;
5788+			}
5789+		}
5790+
5791+		ret = xaf_comp_delete(drv->client, &drv->component[1]);
5792+		if (ret) {
5793+			dev_err(component->dev, "Fail to delete component, err = %d\n", ret);
5794+			return ret;
5795+		}
5796+
5797+		ret = xaf_comp_delete(drv->client, &drv->component[0]);
5798+		if (ret) {
5799+			dev_err(component->dev, "Fail to delete component, err = %d\n", ret);
5800+			return ret;
5801+		}
5802+		xf_pool_free(drv->client, p_proxy->aux);
5803+	}
5804+
5805+	cpu_dai->driver->ops->shutdown(NULL, cpu_dai);
5806+
5807+	drv->client->proxy->is_active = 0;
5808+	wake_up(&drv->client->wait);
5809+	cancel_work_sync(&drv->client->work);
5810+
5811+	fsl_dsp_close_func(drv->client);
5812+	drv->client = NULL;
5813+
5814+	return 0;
5815+}
5816+
5817+static int dsp_platform_compr_set_params(struct snd_soc_component *component,
5818+					struct snd_compr_stream *cstream,
5819+                                        struct snd_compr_params *params)
5820+{
5821+	/* accroding to the params, load the library and create component*/
5822+	struct fsl_dsp  *dsp_priv = snd_soc_component_get_drvdata(component);
5823+	struct dsp_data *drv = &dsp_priv->dsp_data;
5824+	struct xf_proxy *p_proxy = &dsp_priv->proxy;
5825+	struct xf_set_param_msg s_param;
5826+	int ret;
5827+
5828+	switch (params->codec.id) {
5829+	case SND_AUDIOCODEC_PCM:
5830+		drv->codec_type = CODEC_PCM_DEC;
5831+		atomic_set(&drv->client->buffer_cnt, 2);
5832+		break;
5833+	case SND_AUDIOCODEC_MP3:
5834+		drv->codec_type = CODEC_MP3_DEC;
5835+		break;
5836+	case SND_AUDIOCODEC_AAC:
5837+		drv->codec_type = CODEC_AAC_DEC;
5838+		break;
5839+	default:
5840+		dev_err(component->dev, "codec not supported, id =%d\n", params->codec.id);
5841+		return -EINVAL;
5842+	}
5843+
5844+	/* ...create auxiliary buffers pool for control commands */
5845+	ret = xf_pool_alloc(drv->client,
5846+				p_proxy,
5847+				XA_AUX_POOL_SIZE,
5848+				XA_AUX_POOL_MSG_LENGTH,
5849+				XF_POOL_AUX,
5850+				&p_proxy->aux);
5851+	if (ret) {
5852+		dev_err(component->dev, "xf_pool_alloc failed");
5853+		return ret;
5854+	}
5855+
5856+	/* ...create pipeline */
5857+	ret = xaf_pipeline_create(&drv->pipeline);
5858+	if (ret) {
5859+		dev_err(component->dev, "create pipeline error\n");
5860+		goto err_pool_alloc;
5861+	}
5862+
5863+	/* ...create component */
5864+	ret = xaf_comp_create(drv->client, p_proxy, &drv->component[0],
5865+			      drv->codec_type);
5866+	if (ret) {
5867+		dev_err(component->dev,
5868+			"create component failed type = %d, err = %d\n",
5869+			drv->codec_type, ret);
5870+		goto err_pool_alloc;
5871+	}
5872+	if (sysfs_streq(dsp_priv->audio_iface, "sai"))
5873+		drv->renderer_type = RENDER_SAI;
5874+	else
5875+		drv->renderer_type = RENDER_ESAI;
5876+	ret = xaf_comp_create(drv->client, p_proxy, &drv->component[1],
5877+			      drv->renderer_type);
5878+	if (ret) {
5879+		dev_err(component->dev,
5880+			"create component failed, type = %d, err = %d\n",
5881+			drv->renderer_type, ret);
5882+		goto err_comp0_create;
5883+	}
5884+
5885+	if (drv->codec_type == CODEC_AAC_DEC) {
5886+		s_param.id = XA_STREAM_TYPE;
5887+		if (params->codec.format == SND_AUDIOSTREAMFORMAT_MP4ADTS || params->codec.format == SND_AUDIOSTREAMFORMAT_MP2ADTS)
5888+			s_param.mixData.value = XA_STREAM_ADTS;
5889+		else if (params->codec.format == SND_AUDIOSTREAMFORMAT_ADIF)
5890+			s_param.mixData.value = XA_STREAM_ADIF;
5891+		else
5892+			s_param.mixData.value = XA_STREAM_RAW;
5893+		ret = xaf_comp_set_config(drv->client, &drv->component[0], 1, &s_param);
5894+		if (ret) {
5895+			dev_err(component->dev,
5896+				"set param[cmd:0x%x|val:0x%x] error, err = %d\n",
5897+				s_param.id, s_param.mixData.value, ret);
5898+			goto err_comp0_create;
5899+		}
5900+
5901+		/* ...set depth before init codec */
5902+		s_param.id = XA_DEPTH;
5903+		s_param.mixData.value = 16;
5904+		ret = xaf_comp_set_config(drv->client, &drv->component[0], 1, &s_param);
5905+		if (ret) {
5906+			dev_err(component->dev,
5907+			"set param[cmd:0x%x|val:0x%x] error, err = %d\n",
5908+			s_param.id, s_param.mixData.value, ret);
5909+			goto err_comp0_create;
5910+		}
5911+	}
5912+
5913+
5914+	/* ...add component into pipeline */
5915+	ret = xaf_comp_add(&drv->pipeline, &drv->component[0]);
5916+	if (ret) {
5917+		dev_err(component->dev,
5918+			"add component failed, type = %d, err = %d\n",
5919+			drv->codec_type, ret);
5920+		goto err_comp0_create;
5921+	}
5922+
5923+	ret = xaf_comp_add(&drv->pipeline, &drv->component[1]);
5924+	if (ret) {
5925+		dev_err(component->dev,
5926+			"add component failed, type = %d, err = %d\n",
5927+			drv->renderer_type, ret);
5928+		goto err_comp1_create;
5929+	}
5930+
5931+	ret = xaf_connect(drv->client,
5932+			&drv->component[0],
5933+			&drv->component[1],
5934+			1,
5935+			OUTBUF_SIZE);
5936+	if (ret) {
5937+		dev_err(component->dev, "Failed to connect component, err = %d\n", ret);
5938+		goto err_comp1_create;
5939+	}
5940+
5941+	drv->client->input_bytes = 0;
5942+	drv->client->consume_bytes = 0;
5943+	drv->client->offset = 0;
5944+	drv->client->ping_pong_offset = 0;
5945+
5946+	if (drv->codec_type == CODEC_PCM_DEC) {
5947+		s_param.id = XA_PCM_CONFIG_PARAM_IN_PCM_WIDTH;
5948+		if (params->codec.format == SNDRV_PCM_FORMAT_S32_LE)
5949+			s_param.mixData.value = 32;
5950+		else
5951+			s_param.mixData.value = 16;
5952+		ret = xaf_comp_set_config(drv->client, &drv->component[0], 1, &s_param);
5953+		if (ret) {
5954+			dev_err(component->dev,
5955+				"set param[cmd:0x%x|val:0x%x] error, err = %d\n",
5956+				s_param.id, s_param.mixData.value, ret);
5957+			goto err_comp1_create;
5958+		}
5959+	}
5960+
5961+	s_param.id = XA_RENDERER_CONFIG_PARAM_SAMPLE_RATE;
5962+	s_param.mixData.value = params->codec.sample_rate;
5963+	ret = xaf_comp_set_config(drv->client, &drv->component[1], 1, &s_param);
5964+	if (ret) {
5965+		dev_err(component->dev,
5966+			"set param[cmd:0x%x|val:0x%x] error, err = %d\n",
5967+			s_param.id, s_param.mixData.value, ret);
5968+		goto err_comp1_create;
5969+	}
5970+
5971+	s_param.id = XA_RENDERER_CONFIG_PARAM_CHANNELS;
5972+	s_param.mixData.value = params->codec.ch_out;
5973+	ret = xaf_comp_set_config(drv->client, &drv->component[1], 1, &s_param);
5974+	if (ret) {
5975+		dev_err(component->dev,
5976+			"set param[cmd:0x%x|val:0x%x] error, err = %d\n",
5977+			s_param.id, s_param.mixData.value, ret);
5978+		goto err_comp1_create;
5979+	}
5980+
5981+	s_param.id = XA_RENDERER_CONFIG_PARAM_PCM_WIDTH;
5982+	s_param.mixData.value = 16;
5983+	ret = xaf_comp_set_config(drv->client, &drv->component[1], 1, &s_param);
5984+	if (ret) {
5985+		dev_err(component->dev,
5986+			"set param[cmd:0x%x|val:0x%x] error, err = %d\n",
5987+			s_param.id, s_param.mixData.value, ret);
5988+		goto err_comp1_create;
5989+	}
5990+	return 0;
5991+
5992+err_comp1_create:
5993+	xaf_comp_delete(drv->client, &drv->component[1]);
5994+err_comp0_create:
5995+	xaf_comp_delete(drv->client, &drv->component[0]);
5996+err_pool_alloc:
5997+	xf_pool_free(drv->client, p_proxy->aux);
5998+
5999+	return ret;
6000+}
6001+
6002+static int dsp_platform_compr_trigger_start(struct snd_compr_stream *cstream)
6003+{
6004+	struct snd_soc_pcm_runtime *rtd = cstream->private_data;
6005+	struct snd_soc_component *component = snd_soc_rtdcom_lookup(rtd, FSL_DSP_COMP_NAME);
6006+	struct fsl_dsp *dsp_priv = snd_soc_component_get_drvdata(component);
6007+	struct dsp_data *drv = &dsp_priv->dsp_data;
6008+	struct xaf_comp *p_comp = &drv->component[0];
6009+	int ret;
6010+
6011+	if (!dsp_priv->dsp_is_lpa) {
6012+		ret = xaf_comp_process(drv->client,
6013+				p_comp,
6014+				p_comp->inptr,
6015+				drv->client->input_bytes,
6016+				XF_EMPTY_THIS_BUFFER);
6017+
6018+		schedule_work(&drv->client->work);
6019+	}
6020+
6021+	return 0;
6022+}
6023+
6024+static int dsp_platform_compr_trigger_stop(struct snd_compr_stream *cstream)
6025+{
6026+	struct snd_soc_pcm_runtime *rtd = cstream->private_data;
6027+	struct snd_soc_component *component = snd_soc_rtdcom_lookup(rtd, FSL_DSP_COMP_NAME);
6028+	struct fsl_dsp *dsp_priv = snd_soc_component_get_drvdata(component);
6029+	struct dsp_data *drv = &dsp_priv->dsp_data;
6030+	int ret;
6031+
6032+	ret = xaf_comp_flush(drv->client, &drv->component[0]);
6033+	if (ret) {
6034+		dev_err(component->dev, "Fail to flush component, err = %d\n", ret);
6035+		return ret;
6036+	}
6037+
6038+	ret = xaf_comp_flush(drv->client, &drv->component[1]);
6039+	if (ret) {
6040+		dev_err(component->dev, "Fail to flush component, err = %d\n", ret);
6041+		return ret;
6042+	}
6043+	drv->client->input_bytes = 0;
6044+	drv->client->consume_bytes = 0;
6045+	drv->client->offset = 0;
6046+	drv->client->ping_pong_offset = 0;
6047+
6048+	return 0;
6049+}
6050+
6051+static int dsp_platform_compr_trigger_drain(struct snd_compr_stream *cstream)
6052+{
6053+	struct snd_soc_pcm_runtime *rtd = cstream->private_data;
6054+	struct snd_soc_component *component = snd_soc_rtdcom_lookup(rtd, FSL_DSP_COMP_NAME);
6055+	struct fsl_dsp *dsp_priv = snd_soc_component_get_drvdata(component);
6056+	struct dsp_data *drv = &dsp_priv->dsp_data;
6057+	struct xaf_comp *p_comp = &drv->component[0];
6058+	int ret;
6059+
6060+	ret = xaf_comp_process(drv->client, p_comp, NULL, 0,
6061+			       XF_EMPTY_THIS_BUFFER);
6062+
6063+	schedule_work(&drv->client->work);
6064+	return 0;
6065+}
6066+
6067+static int dsp_platform_compr_trigger_pause(struct snd_compr_stream *cstream)
6068+{
6069+	struct snd_soc_pcm_runtime *rtd = cstream->private_data;
6070+	struct snd_soc_component *component = snd_soc_rtdcom_lookup(rtd, FSL_DSP_COMP_NAME);
6071+	struct fsl_dsp *dsp_priv = snd_soc_component_get_drvdata(component);
6072+	struct xf_proxy  *proxy  = &dsp_priv->proxy;
6073+	int ret;
6074+
6075+	ret = xf_cmd_send_pause(proxy);
6076+	if (ret) {
6077+		dev_err(component->dev, "trigger pause err = %d\n", ret);
6078+		return ret;
6079+	}
6080+	return 0;
6081+}
6082+
6083+static int dsp_platform_compr_trigger_pause_release(struct snd_compr_stream *cstream)
6084+{
6085+	struct snd_soc_pcm_runtime *rtd = cstream->private_data;
6086+	struct snd_soc_component *component = snd_soc_rtdcom_lookup(rtd, FSL_DSP_COMP_NAME);
6087+	struct fsl_dsp *dsp_priv = snd_soc_component_get_drvdata(component);
6088+	struct xf_proxy  *proxy  = &dsp_priv->proxy;
6089+	int ret;
6090+
6091+	ret = xf_cmd_send_pause_release(proxy);
6092+	if (ret) {
6093+		dev_err(component->dev, "trigger pause release err = %d\n", ret);
6094+		return ret;
6095+	}
6096+
6097+	return 0;
6098+}
6099+
6100+static int dsp_platform_compr_trigger(struct snd_soc_component *component,
6101+				      struct snd_compr_stream *cstream, int cmd)
6102+{
6103+	int ret = 0;
6104+
6105+	switch (cmd) {
6106+	case SNDRV_PCM_TRIGGER_START:
6107+		ret = dsp_platform_compr_trigger_start(cstream);
6108+		break;
6109+	case SNDRV_PCM_TRIGGER_STOP:
6110+		ret = dsp_platform_compr_trigger_stop(cstream);
6111+		break;
6112+	case SND_COMPR_TRIGGER_DRAIN:
6113+		ret = dsp_platform_compr_trigger_drain(cstream);
6114+		break;
6115+	case SND_COMPR_TRIGGER_PARTIAL_DRAIN:
6116+		break;
6117+	case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
6118+		ret = dsp_platform_compr_trigger_pause(cstream);
6119+		break;
6120+	case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
6121+		ret = dsp_platform_compr_trigger_pause_release(cstream);
6122+		break;
6123+	}
6124+
6125+	/*send command*/
6126+	return ret;
6127+}
6128+
6129+static int dsp_platform_compr_pointer(struct snd_soc_component *component,
6130+					struct snd_compr_stream *cstream,
6131+					struct snd_compr_tstamp *tstamp)
6132+{
6133+	struct fsl_dsp *dsp_priv = snd_soc_component_get_drvdata(component);
6134+	struct dsp_data *drv = &dsp_priv->dsp_data;
6135+	struct xf_get_param_msg g_param[2];
6136+	int ret;
6137+
6138+	g_param[0].id = XA_RENDERER_CONFIG_PARAM_SAMPLE_RATE;
6139+	g_param[1].id = XA_RENDERER_CONFIG_PARAM_CONSUMED;
6140+	ret = xaf_comp_get_config(drv->client, &drv->component[1], 2, &g_param);
6141+	if (ret) {
6142+		dev_err(component->dev,
6143+			"get param[cmd:0x%x|val:0x%x] error, err = %d\n",
6144+			g_param[0].id, g_param[0].mixData.value, ret);
6145+		goto out;
6146+	}
6147+
6148+	if ((drv->codec_type != CODEC_PCM_DEC && drv->client->input_bytes != drv->client->consume_bytes)
6149+			|| (drv->codec_type == CODEC_PCM_DEC && atomic_read(&drv->client->buffer_cnt) <= 0))
6150+		tstamp->copied_total = drv->client->input_bytes+drv->client->offset-4096;
6151+	else
6152+		tstamp->copied_total = drv->client->input_bytes+drv->client->offset;
6153+	tstamp->byte_offset = drv->client->input_bytes;
6154+	tstamp->pcm_frames = 0x900;
6155+	tstamp->pcm_io_frames = g_param[1].mixData.value;
6156+	tstamp->sampling_rate = g_param[0].mixData.value;
6157+
6158+out:
6159+	return 0;
6160+}
6161+
6162+static int dsp_platform_compr_copy(struct snd_soc_component *component,
6163+					struct snd_compr_stream *cstream,
6164+					char __user *buf,
6165+					size_t count)
6166+{
6167+	struct fsl_dsp *dsp_priv = snd_soc_component_get_drvdata(component);
6168+	struct dsp_data *drv = &dsp_priv->dsp_data;
6169+	struct xaf_comp *p_comp = &drv->component[0];
6170+	int copied = 0;
6171+	int ret;
6172+
6173+	if (drv->client->input_bytes == drv->client->consume_bytes) {
6174+		if (count > INBUF_SIZE){
6175+			ret = copy_from_user(p_comp->inptr, buf, INBUF_SIZE);
6176+			if (ret) {
6177+				dev_err(component->dev, "failed to get message from user space\n");
6178+				return -EFAULT;
6179+			}
6180+			copied = INBUF_SIZE;
6181+		} else {
6182+			ret = copy_from_user(p_comp->inptr, buf, count);
6183+			if (ret) {
6184+				dev_err(component->dev, "failed to get message from user space\n");
6185+				return -EFAULT;
6186+			}
6187+			copied = count;
6188+		}
6189+		drv->client->input_bytes += copied;
6190+
6191+		if (cstream->runtime->state == SNDRV_PCM_STATE_RUNNING && copied) {
6192+		        ret = xaf_comp_process(drv->client, p_comp,
6193+					       p_comp->inptr, copied,
6194+					       XF_EMPTY_THIS_BUFFER);
6195+			schedule_work(&drv->client->work);
6196+		}
6197+	}
6198+
6199+	return copied;
6200+}
6201+
6202+static int dsp_platform_compr_lpa_pcm_copy(struct snd_soc_component *component,
6203+					struct snd_compr_stream *cstream,
6204+					char __user *buf,
6205+					size_t count)
6206+{
6207+	struct fsl_dsp *dsp_priv = snd_soc_component_get_drvdata(component);
6208+	struct dsp_data *drv = &dsp_priv->dsp_data;
6209+	struct xaf_comp *p_comp = &drv->component[0];
6210+	int copied = 0;
6211+	int ret;
6212+
6213+	if (atomic_read(&drv->client->buffer_cnt) > 0) {
6214+		if (drv->client->offset+count >= (INBUF_SIZE_LPA_PCM>>1)-4096 || !buf) {
6215+			/* buf == NULL and count == 1 is for drain and */
6216+			/* suspend as tinycompress drain is blocking call */
6217+			copied = count;
6218+			if (!buf)
6219+				copied = 0;
6220+			if (buf) {
6221+				ret = copy_from_user(p_comp->inptr+drv->client->ping_pong_offset+drv->client->offset, buf, copied);
6222+				if (ret) {
6223+					dev_err(component->dev, "failed to get message from user space\n");
6224+					return -EFAULT;
6225+				}
6226+			}
6227+
6228+			if (cstream->runtime->state == SNDRV_PCM_STATE_RUNNING) {
6229+				ret = xaf_comp_process(drv->client, p_comp,
6230+						p_comp->inptr+drv->client->ping_pong_offset, drv->client->offset+copied,
6231+						XF_EMPTY_THIS_BUFFER);
6232+
6233+				schedule_work(&drv->client->work);
6234+				drv->client->input_bytes += drv->client->offset+copied;
6235+				drv->client->offset = 0;
6236+				atomic_dec(&drv->client->buffer_cnt);
6237+				if (drv->client->ping_pong_offset)
6238+					drv->client->ping_pong_offset = 0;
6239+				else
6240+					drv->client->ping_pong_offset = INBUF_SIZE_LPA_PCM>>1;
6241+			}
6242+			if (!buf)
6243+				copied = count;
6244+		} else {
6245+			ret = copy_from_user(p_comp->inptr+drv->client->ping_pong_offset+drv->client->offset, buf, count);
6246+			if (ret) {
6247+				dev_err(component->dev, "failed to get message from user space\n");
6248+				return -EFAULT;
6249+			}
6250+			copied = count;
6251+			drv->client->offset += copied;
6252+		}
6253+	}
6254+
6255+	return copied;
6256+}
6257+
6258+static int dsp_platform_compr_lpa_copy(struct snd_soc_component *component,
6259+					struct snd_compr_stream *cstream,
6260+					char __user *buf,
6261+					size_t count)
6262+{
6263+	struct fsl_dsp *dsp_priv = snd_soc_component_get_drvdata(component);
6264+	struct dsp_data *drv = &dsp_priv->dsp_data;
6265+	struct xaf_comp *p_comp = &drv->component[0];
6266+	int copied = 0;
6267+	int ret;
6268+
6269+	if (drv->codec_type == CODEC_PCM_DEC)
6270+		return dsp_platform_compr_lpa_pcm_copy(component, cstream, buf, count);
6271+
6272+	if (drv->client->input_bytes == drv->client->consume_bytes) {
6273+		if (drv->client->offset+count >= INBUF_SIZE_LPA-4096 || !buf) {
6274+			/* buf == NULL and count == 1 is for drain and */
6275+			/* suspend as tinycompress drain is blocking call */
6276+			copied = count;
6277+			if (!buf)
6278+				copied = 0;
6279+			if (buf) {
6280+				ret = copy_from_user(p_comp->inptr+drv->client->offset, buf, copied);
6281+				if (ret) {
6282+					dev_err(component->dev, "failed to get message from user space\n");
6283+					return -EFAULT;
6284+				}
6285+			}
6286+
6287+			if (cstream->runtime->state == SNDRV_PCM_STATE_RUNNING) {
6288+				ret = xaf_comp_process(drv->client, p_comp,
6289+						p_comp->inptr, drv->client->offset+copied,
6290+						XF_EMPTY_THIS_BUFFER);
6291+
6292+				schedule_work(&drv->client->work);
6293+				drv->client->input_bytes += drv->client->offset+copied;
6294+				drv->client->offset = 0;
6295+			}
6296+			if (!buf)
6297+				copied = count;
6298+		} else {
6299+			ret = copy_from_user(p_comp->inptr+drv->client->offset, buf, count);
6300+			if (ret) {
6301+				dev_err(component->dev, "failed to get message from user space\n");
6302+				return -EFAULT;
6303+			}
6304+			copied = count;
6305+			drv->client->offset += copied;
6306+		}
6307+	}
6308+
6309+	return copied;
6310+}
6311+
6312+static int dsp_platform_compr_get_caps(struct snd_soc_component *component,
6313+					struct snd_compr_stream *cstream,
6314+					struct snd_compr_caps *caps)
6315+{
6316+	caps->num_codecs = NUM_CODEC;
6317+	caps->min_fragment_size = MIN_FRAGMENT_SIZE;  /* 50KB */
6318+	caps->max_fragment_size = MAX_FRAGMENT_SIZE;  /* 1024KB */
6319+	caps->min_fragments = MIN_FRAGMENT;
6320+	caps->max_fragments = MAX_FRAGMENT;
6321+	caps->codecs[0] = SND_AUDIOCODEC_MP3;
6322+	caps->codecs[1] = SND_AUDIOCODEC_AAC;
6323+	caps->codecs[2] = SND_AUDIOCODEC_PCM;
6324+
6325+	return 0;
6326+}
6327+
6328+static struct snd_compr_codec_caps caps_pcm = {
6329+	.num_descriptors = 1,
6330+	.descriptor[0].max_ch = 2,
6331+	.descriptor[0].sample_rates[0] = 192000,
6332+	.descriptor[0].sample_rates[1] = 176400,
6333+	.descriptor[0].sample_rates[2] = 96000,
6334+	.descriptor[0].sample_rates[3] = 88200,
6335+	.descriptor[0].sample_rates[4] = 48000,
6336+	.descriptor[0].sample_rates[5] = 44100,
6337+	.descriptor[0].sample_rates[6] = 32000,
6338+	.descriptor[0].sample_rates[7] = 16000,
6339+	.descriptor[0].sample_rates[8] = 8000,
6340+	.descriptor[0].num_sample_rates = 9,
6341+	.descriptor[0].bit_rate[0] = 320,
6342+	.descriptor[0].bit_rate[1] = 192,
6343+	.descriptor[0].num_bitrates = 2,
6344+	.descriptor[0].profiles = SND_AUDIOPROFILE_PCM,
6345+	.descriptor[0].modes = 0,
6346+	.descriptor[0].formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S32_LE,
6347+};
6348+
6349+static struct snd_compr_codec_caps caps_mp3 = {
6350+	.num_descriptors = 1,
6351+	.descriptor[0].max_ch = 2,
6352+	.descriptor[0].sample_rates[0] = 48000,
6353+	.descriptor[0].sample_rates[1] = 44100,
6354+	.descriptor[0].sample_rates[2] = 32000,
6355+	.descriptor[0].sample_rates[3] = 16000,
6356+	.descriptor[0].sample_rates[4] = 8000,
6357+	.descriptor[0].num_sample_rates = 5,
6358+	.descriptor[0].bit_rate[0] = 320,
6359+	.descriptor[0].bit_rate[1] = 192,
6360+	.descriptor[0].num_bitrates = 2,
6361+	.descriptor[0].profiles = 0,
6362+	.descriptor[0].modes = SND_AUDIOCHANMODE_MP3_STEREO,
6363+	.descriptor[0].formats = 0,
6364+};
6365+
6366+static struct snd_compr_codec_caps caps_aac = {
6367+	.num_descriptors = 2,
6368+	.descriptor[1].max_ch = 2,
6369+	.descriptor[0].sample_rates[0] = 48000,
6370+	.descriptor[0].sample_rates[1] = 44100,
6371+	.descriptor[0].sample_rates[2] = 32000,
6372+	.descriptor[0].sample_rates[3] = 16000,
6373+	.descriptor[0].sample_rates[4] = 8000,
6374+	.descriptor[0].num_sample_rates = 5,
6375+	.descriptor[1].bit_rate[0] = 320,
6376+	.descriptor[1].bit_rate[1] = 192,
6377+	.descriptor[1].num_bitrates = 2,
6378+	.descriptor[1].profiles = 0,
6379+	.descriptor[1].modes = 0,
6380+	.descriptor[1].formats =
6381+			(SND_AUDIOSTREAMFORMAT_MP4ADTS | SND_AUDIOSTREAMFORMAT_MP2ADTS |
6382+				SND_AUDIOSTREAMFORMAT_ADIF | SND_AUDIOSTREAMFORMAT_RAW),
6383+};
6384+
6385+static int dsp_platform_compr_get_codec_caps(struct snd_soc_component *component,
6386+						struct snd_compr_stream *cstream,
6387+						struct snd_compr_codec_caps *codec)
6388+{
6389+	if (codec->codec == SND_AUDIOCODEC_MP3)
6390+		*codec = caps_mp3;
6391+	else if (codec->codec == SND_AUDIOCODEC_AAC)
6392+		*codec = caps_aac;
6393+	else if (codec->codec == SND_AUDIOCODEC_PCM)
6394+		*codec = caps_pcm;
6395+	else
6396+		return -EINVAL;
6397+
6398+	return 0;
6399+}
6400+
6401+static int dsp_platform_compr_set_metadata(struct snd_soc_component *component,
6402+						struct snd_compr_stream *cstream,
6403+						struct snd_compr_metadata *metadata)
6404+{
6405+	return 0;
6406+}
6407+
6408+const struct snd_compress_ops dsp_platform_compress_ops = {
6409+	.open = dsp_platform_compr_open,
6410+	.free = dsp_platform_compr_free,
6411+	.set_params = dsp_platform_compr_set_params,
6412+	.set_metadata = dsp_platform_compr_set_metadata,
6413+	.trigger = dsp_platform_compr_trigger,
6414+	.pointer = dsp_platform_compr_pointer,
6415+	.copy = dsp_platform_compr_copy,
6416+	.get_caps = dsp_platform_compr_get_caps,
6417+	.get_codec_caps = dsp_platform_compr_get_codec_caps,
6418+};
6419+
6420+const struct snd_compress_ops dsp_platform_compr_lpa_ops = {
6421+	.open = dsp_platform_compr_open,
6422+	.free = dsp_platform_compr_free,
6423+	.set_params = dsp_platform_compr_set_params,
6424+	.set_metadata = dsp_platform_compr_set_metadata,
6425+	.trigger = dsp_platform_compr_trigger,
6426+	.pointer = dsp_platform_compr_pointer,
6427+	.copy = dsp_platform_compr_lpa_copy,
6428+	.get_caps = dsp_platform_compr_get_caps,
6429+	.get_codec_caps = dsp_platform_compr_get_codec_caps,
6430+};
6431diff --git a/sound/soc/fsl/fsl_dsp_pool.c b/sound/soc/fsl/fsl_dsp_pool.c
6432new file mode 100644
6433index 000000000..637454d97
6434--- /dev/null
6435+++ b/sound/soc/fsl/fsl_dsp_pool.c
6436@@ -0,0 +1,150 @@
6437+// SPDX-License-Identifier: GPL-2.0+
6438+//
6439+// Xtensa buffer pool API
6440+//
6441+// Copyright 2018 NXP
6442+// Copyright (c) 2012-2013 by Tensilica Inc.
6443+
6444+#include <linux/slab.h>
6445+
6446+#include "fsl_dsp_pool.h"
6447+#include "fsl_dsp.h"
6448+
6449+/* ...allocate buffer pool */
6450+int xf_pool_alloc(struct xf_client *client, struct xf_proxy *proxy,
6451+		  u32 number, u32 length, xf_pool_type_t type,
6452+		  struct xf_pool **pool)
6453+{
6454+	struct xf_pool      *p;
6455+	struct xf_buffer    *b;
6456+	void  *data;
6457+	struct xf_message    msg;
6458+	struct xf_message   *rmsg;
6459+
6460+	/* ...basic sanity checks; number of buffers is positive */
6461+	if (number <=0)
6462+		return -EINVAL;
6463+
6464+	/* ...get properly aligned buffer length */
6465+	length = ALIGN(length, XF_PROXY_ALIGNMENT);
6466+
6467+	p = kzalloc(offsetof(struct xf_pool, buffer) +
6468+		    number * sizeof(struct xf_buffer), GFP_KERNEL);
6469+	if(!p)
6470+		return -ENOMEM;
6471+
6472+	/* ...prepare command parameters */
6473+	msg.id = __XF_MSG_ID(__XF_AP_PROXY(0), __XF_DSP_PROXY(0));
6474+	msg.id = XF_MSG_AP_FROM_USER(msg.id, client->id);
6475+	msg.opcode = XF_ALLOC;
6476+	msg.length = length * number;
6477+	msg.buffer = NULL;
6478+	msg.ret = 0;
6479+
6480+	/* ...execute command synchronously */
6481+	rmsg = xf_cmd_send_recv_complete(client, proxy, msg.id, msg.opcode,
6482+					 msg.buffer, msg.length, &client->work,
6483+					 &client->compr_complete);
6484+	if (IS_ERR(rmsg)) {
6485+		kfree(p);
6486+		return PTR_ERR(rmsg);
6487+	}
6488+
6489+	p->p = rmsg->buffer;
6490+	/* TODO: review cleanup */
6491+	/* xf_msg_free(proxy, rmsg);
6492+	 * xf_unlock(&proxy->lock); */
6493+
6494+	/* ...if operation is failed, do cleanup */
6495+	/* ...set pool parameters */
6496+	p->number = number, p->length = length;
6497+	p->proxy = proxy;
6498+
6499+	/* ...create individual buffers and link them into free list */
6500+	for (p->free = b = &p->buffer[0], data = p->p; number > 0;
6501+			number--, b++) {
6502+		/* ...set address of the buffer (no length there) */
6503+		b->address = data;
6504+
6505+		/* ...file buffer into the free list */
6506+		b->link.next = b + 1;
6507+
6508+		/* ...advance data pointer in contiguous buffer */
6509+		data += length;
6510+	}
6511+
6512+	/* ...terminate list of buffers (not too good - tbd) */
6513+	b[-1].link.next = NULL;
6514+
6515+	/* ...return buffer pointer */
6516+	*pool = p;
6517+
6518+	return 0;
6519+}
6520+/* ...buffer pool destruction */
6521+int xf_pool_free(struct xf_client *client, struct xf_pool *pool)
6522+{
6523+	struct xf_proxy     *proxy;
6524+	struct xf_message    msg;
6525+	struct xf_message   *rmsg;
6526+
6527+	/* ...basic sanity checks; pool is positive */
6528+	if (pool == NULL)
6529+		return -EINVAL;
6530+
6531+	/* ...get proxy pointer */
6532+	if ((proxy = pool->proxy) == NULL)
6533+		return -EINVAL;
6534+
6535+	/* ...prepare command parameters */
6536+	msg.id = __XF_MSG_ID(__XF_AP_PROXY(0), __XF_DSP_PROXY(0));
6537+	msg.id = XF_MSG_AP_FROM_USER(msg.id, client->id);
6538+	msg.opcode = XF_FREE;
6539+	msg.length = pool->length * pool->number;
6540+	msg.buffer = pool->p;
6541+	msg.ret = 0;
6542+
6543+	/* ...execute command synchronously */
6544+	rmsg = xf_cmd_send_recv_complete(client, proxy, msg.id, msg.opcode,
6545+					 msg.buffer, msg.length, &client->work,
6546+					 &client->compr_complete);
6547+	kfree(pool);
6548+	if (IS_ERR(rmsg))
6549+		return PTR_ERR(rmsg);
6550+
6551+	/* TODO: review cleanup */
6552+	/* xf_msg_free(proxy, rmsg);
6553+	 * xf_unlock(&proxy->lock); */
6554+
6555+	return 0;
6556+}
6557+
6558+/* ...get new buffer from a pool */
6559+struct xf_buffer *xf_buffer_get(struct xf_pool *pool)
6560+{
6561+	struct xf_buffer    *b;
6562+
6563+	xf_lock(&pool->proxy->lock);
6564+	/* ...take buffer from a head of the free list */
6565+	b = pool->free;
6566+	if (b) {
6567+		/* ...advance free list head */
6568+		pool->free = b->link.next, b->link.pool = pool;
6569+	}
6570+
6571+	xf_unlock(&pool->proxy->lock);
6572+	return b;
6573+}
6574+
6575+/* ...return buffer back to pool */
6576+void xf_buffer_put(struct xf_buffer *buffer)
6577+{
6578+	struct xf_pool  *pool = buffer->link.pool;
6579+
6580+	xf_lock(&pool->proxy->lock);
6581+	/* ...use global proxy lock for pool operations protection */
6582+	/* ...put buffer back to a pool */
6583+	buffer->link.next = pool->free, pool->free = buffer;
6584+
6585+	xf_unlock(&pool->proxy->lock);
6586+}
6587diff --git a/sound/soc/fsl/fsl_dsp_pool.h b/sound/soc/fsl/fsl_dsp_pool.h
6588new file mode 100644
6589index 000000000..4a56262fa
6590--- /dev/null
6591+++ b/sound/soc/fsl/fsl_dsp_pool.h
6592@@ -0,0 +1,113 @@
6593+/* SPDX-License-Identifier: GPL-2.0+ */
6594+/*
6595+ * Xtensa buffer pool API header
6596+ *
6597+ * Copyright 2018 NXP
6598+ * Copyright (c) 2012-2013 by Tensilica Inc
6599+ */
6600+#ifndef FSL_DSP_POOL_H
6601+#define FSL_DSP_POOL_H
6602+
6603+#include <linux/types.h>
6604+#include "fsl_dsp_proxy.h"
6605+
6606+/* ...buffer pool type */
6607+typedef u32 xf_pool_type_t;
6608+
6609+/* ...previous declaration of struct */
6610+struct xf_buffer;
6611+struct xf_pool;
6612+struct xf_handle;
6613+struct xf_message;
6614+struct xf_client;
6615+
6616+/* ...response callback */
6617+typedef void (*xf_response_cb)(struct xf_handle *h, struct xf_message *msg);
6618+
6619+/* ...buffer pool type */
6620+enum xf_pool_type {
6621+        XF_POOL_AUX = 0,
6622+        XF_POOL_INPUT = 1,
6623+        XF_POOL_OUTPUT = 2
6624+};
6625+
6626+/* ...buffer link pointer */
6627+union xf_buffer_link {
6628+        /* ...pointer to next free buffer in a pool (for free buffer) */
6629+        struct xf_buffer *next;
6630+        /* ...reference to a buffer pool (for allocated buffer) */
6631+        struct xf_pool *pool;
6632+};
6633+
6634+/* ...buffer descriptor */
6635+struct xf_buffer {
6636+        /* ...virtual address of contiguous buffer */
6637+        void *address;
6638+        /* ...link pointer */
6639+        union xf_buffer_link link;
6640+};
6641+
6642+/* ...buffer pool */
6643+struct xf_pool {
6644+        /* ...reference to proxy data */
6645+        struct xf_proxy *proxy;
6646+        /* ...length of individual buffer in a pool */
6647+        u32 length;
6648+        /* ...number of buffers in a pool */
6649+        u32 number;
6650+        /* ...pointer to pool memory */
6651+        void *p;
6652+        /* ...pointer to first free buffer in a pool */
6653+        struct xf_buffer *free;
6654+        /* ...individual buffers */
6655+        struct xf_buffer buffer[0];
6656+};
6657+
6658+/* component handle */
6659+struct xf_handle {
6660+        /* ...reference to proxy data */
6661+        struct xf_proxy *proxy;
6662+        /* ...auxiliary control buffer for control transactions */
6663+        struct xf_buffer *aux;
6664+        /* ...global client-id of the component */
6665+        u32 id;
6666+        /* ...local client number (think about merging into "id" field - tbd) */
6667+        u32 client;
6668+        /* ...response processing hook */
6669+        xf_response_cb response;
6670+};
6671+
6672+/* ...accessor to buffer data */
6673+static inline void *xf_buffer_data(struct xf_buffer *buffer)
6674+{
6675+        return buffer->address;
6676+}
6677+
6678+/* ...length of buffer data */
6679+static inline size_t xf_buffer_length(struct xf_buffer *buffer)
6680+{
6681+        struct xf_pool *pool = buffer->link.pool;
6682+
6683+        return (size_t)pool->length;
6684+}
6685+
6686+/* ...component client-id (global scope) */
6687+static inline u32 xf_handle_id(struct xf_handle *handle)
6688+{
6689+        return handle->id;
6690+}
6691+
6692+/* ...pointer to auxiliary buffer */
6693+static inline void *xf_handle_aux(struct xf_handle *handle)
6694+{
6695+        return xf_buffer_data(handle->aux);
6696+}
6697+
6698+int xf_pool_alloc(struct xf_client *client, struct xf_proxy *proxy, u32 number,
6699+		  u32 length, xf_pool_type_t type, struct xf_pool **pool);
6700+int xf_pool_free(struct xf_client *client, struct xf_pool *pool);
6701+
6702+struct xf_buffer *xf_buffer_get(struct xf_pool *pool);
6703+void xf_buffer_put(struct xf_buffer *buffer);
6704+
6705+#endif /* FSL_DSP_POOL_H */
6706diff --git a/sound/soc/fsl/fsl_dsp_proxy.c b/sound/soc/fsl/fsl_dsp_proxy.c
6707new file mode 100644
6708index 000000000..558010852
6709--- /dev/null
6710+++ b/sound/soc/fsl/fsl_dsp_proxy.c
6711@@ -0,0 +1,984 @@
6712+// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
6713+//
6714+// DSP proxy driver transfers messages between DSP driver and DSP framework
6715+//
6716+// Copyright 2018 NXP
6717+// Copyright (C) 2017 Cadence Design Systems, Inc.
6718+
6719+#include <linux/suspend.h>
6720+#include "fsl_dsp_proxy.h"
6721+#include "fsl_dsp.h"
6722+
6723+/* ...initialize message queue */
6724+void xf_msg_queue_init(struct xf_msg_queue *queue)
6725+{
6726+	queue->head = queue->tail = NULL;
6727+}
6728+
6729+/* ...get message queue head */
6730+struct xf_message *xf_msg_queue_head(struct xf_msg_queue *queue)
6731+{
6732+	return queue->head;
6733+}
6734+
6735+/* ...allocate new message from the pool */
6736+struct xf_message *xf_msg_alloc(struct xf_proxy *proxy)
6737+{
6738+	struct xf_message *m = proxy->free;
6739+
6740+	/* ...make sure we have a free message item */
6741+	if (m != NULL) {
6742+		/* ...get message from the pool */
6743+		proxy->free = m->next, m->next = NULL;
6744+	}
6745+
6746+	return m;
6747+}
6748+
6749+/* ...return message to the pool of free items */
6750+void xf_msg_free(struct xf_proxy *proxy, struct xf_message *m)
6751+{
6752+	/* ...put message into the head of free items list */
6753+	m->next = proxy->free, proxy->free = m;
6754+
6755+	/* ...notify potential client waiting for message */
6756+	wake_up(&proxy->busy);
6757+}
6758+
6759+/* ...return all messages from the queue to the pool of free items */
6760+void xf_msg_free_all(struct xf_proxy *proxy, struct xf_msg_queue *queue)
6761+{
6762+	struct xf_message *m = queue->head;
6763+
6764+	/* ...check if there is anything in the queue */
6765+	if (m != NULL) {
6766+		queue->tail->next = proxy->free;
6767+		proxy->free = queue->head;
6768+		queue->head = queue->tail = NULL;
6769+
6770+		/* ...notify potential client waiting for message */
6771+		wake_up(&proxy->busy);
6772+	}
6773+}
6774+
6775+/* ...submit message to a queue */
6776+int xf_msg_enqueue(struct xf_msg_queue *queue, struct xf_message *m)
6777+{
6778+	int first = (queue->head == NULL);
6779+
6780+	/* ...set pointer to next item */
6781+	m->next = NULL;
6782+
6783+	/* ...advance head/tail pointer as required */
6784+	if (first)
6785+		queue->head = m;
6786+	else
6787+		queue->tail->next = m;
6788+
6789+	/* ...new tail points to this message */
6790+	queue->tail = m;
6791+
6792+	return first;
6793+}
6794+
6795+/* ...retrieve next message from the per-task queue */
6796+struct xf_message *xf_msg_dequeue(struct xf_msg_queue *queue)
6797+{
6798+	struct xf_message *m = queue->head;
6799+
6800+	/* ...check if there is anything in the queue */
6801+	if (m != NULL) {
6802+		/* ...pop message from the head of the list */
6803+		queue->head = m->next;
6804+		if (queue->head == NULL)
6805+			queue->tail = NULL;
6806+	}
6807+
6808+	return m;
6809+}
6810+
6811+/* ...helper function for requesting execution message from a pool */
6812+struct xf_message *xf_msg_available(struct xf_proxy *proxy)
6813+{
6814+	struct xf_message *m;
6815+
6816+	/* ...acquire global lock */
6817+	xf_lock(&proxy->lock);
6818+
6819+	/* ...try to allocate the message */
6820+	m = xf_msg_alloc(proxy);
6821+	if (m  == NULL) {
6822+		/* ...failed to allocate message; release lock */
6823+		xf_unlock(&proxy->lock);
6824+	}
6825+
6826+	/* ...if successfully allocated */
6827+	return m;
6828+}
6829+
6830+/* ...helper function for receiving a message from per-client queue */
6831+struct xf_message *xf_msg_received(struct xf_proxy *proxy,
6832+				struct xf_msg_queue *queue)
6833+{
6834+	struct xf_message *m;
6835+
6836+	/* ...acquire global lock */
6837+	xf_lock(&proxy->lock);
6838+
6839+	/* ...try to peek message from the queue */
6840+	m = xf_msg_dequeue(queue);
6841+	if (m == NULL) {
6842+		/* ...queue is empty; release lock */
6843+		xf_unlock(&proxy->lock);
6844+	}
6845+
6846+	/* ...if message is non-null, lock is held */
6847+	return m;
6848+}
6849+
6850+/*
6851+ *  ...mailbox related functions.
6852+ */
6853+u32 icm_intr_send(struct xf_proxy *proxy, u32 msg)
6854+{
6855+	struct fsl_dsp *dsp_priv = container_of(proxy,
6856+					struct fsl_dsp, proxy);
6857+
6858+	mbox_send_message(dsp_priv->chan_tx[0].ch, &msg);
6859+	return 0;
6860+}
6861+
6862+int icm_intr_extended_send(struct xf_proxy *proxy,
6863+				u32 msg,
6864+				struct dsp_ext_msg *ext_msg)
6865+{
6866+	struct fsl_dsp *dsp_priv = container_of(proxy,
6867+					struct fsl_dsp, proxy);
6868+	struct device *dev = dsp_priv->dev;
6869+	union icm_header_t msghdr;
6870+
6871+	msghdr.allbits = msg;
6872+	if (msghdr.size != 8)
6873+		dev_err(dev, "too much ext msg\n");
6874+
6875+	mbox_send_message(dsp_priv->chan_tx[1].ch, &ext_msg->phys);
6876+	mbox_send_message(dsp_priv->chan_tx[2].ch, &ext_msg->size);
6877+	mbox_send_message(dsp_priv->chan_tx[0].ch, &msg);
6878+
6879+	return 0;
6880+}
6881+
6882+int send_dpu_ext_msg_addr(struct xf_proxy *proxy)
6883+{
6884+	struct fsl_dsp *dsp_priv = container_of(proxy,
6885+					struct fsl_dsp, proxy);
6886+	union icm_header_t msghdr;
6887+	struct dsp_ext_msg ext_msg;
6888+	struct dsp_mem_msg *dpu_ext_msg =
6889+	 (struct dsp_mem_msg *)((unsigned char *)dsp_priv->msg_buf_virt
6890+					+ (MSG_BUF_SIZE / 2));
6891+	int ret_val = 0;
6892+
6893+	msghdr.allbits = 0;	/* clear all bits; */
6894+	msghdr.ack  = 0;
6895+	msghdr.intr = 1;
6896+	msghdr.msg  = ICM_CORE_INIT;
6897+	msghdr.size = 8;
6898+	ext_msg.phys = dsp_priv->msg_buf_phys - dsp_priv->msg_buf_alias + (MSG_BUF_SIZE / 2);
6899+	ext_msg.size = sizeof(struct dsp_mem_msg);
6900+
6901+	dpu_ext_msg->ext_msg_phys = dsp_priv->msg_buf_phys - dsp_priv->msg_buf_alias;
6902+	dpu_ext_msg->ext_msg_size = MSG_BUF_SIZE;
6903+	dpu_ext_msg->scratch_phys =  dsp_priv->scratch_buf_phys - dsp_priv->scratch_buf_alias;
6904+	dpu_ext_msg->scratch_size =  dsp_priv->scratch_buf_size;
6905+	dpu_ext_msg->dsp_config_phys =  dsp_priv->dsp_config_phys - dsp_priv->dsp_config_alias;
6906+	dpu_ext_msg->dsp_config_size =  dsp_priv->dsp_config_size;
6907+	dpu_ext_msg->dsp_board_type = dsp_priv->dsp_board_type;
6908+
6909+	icm_intr_extended_send(proxy, msghdr.allbits, &ext_msg);
6910+
6911+	return ret_val;
6912+}
6913+
6914+long icm_ack_wait(struct xf_proxy *proxy, u32 msg)
6915+{
6916+	struct fsl_dsp *dsp_priv = container_of(proxy,
6917+					struct fsl_dsp, proxy);
6918+	struct device *dev = dsp_priv->dev;
6919+	union icm_header_t msghdr;
6920+	int err;
6921+
6922+	msghdr.allbits = msg;
6923+	/* wait response from mu */
6924+	err = wait_for_completion_timeout(&proxy->cmd_complete,
6925+				msecs_to_jiffies(1000));
6926+	if (!err) {
6927+		dev_err(dev, "icm ack timeout! %x\n", msg);
6928+		return -ETIMEDOUT;
6929+	}
6930+
6931+	dev_dbg(dev, "Ack recd for message 0x%08x\n", msghdr.allbits);
6932+
6933+	return 0;
6934+}
6935+
6936+/*
6937+ * ...mailbox related functions
6938+ */
6939+static void dsp_rx_callback(struct mbox_client *c, void *msg)
6940+{
6941+
6942+	struct device *dev = c->dev;
6943+	struct dsp_mailbox_chan *chan = container_of(c, struct dsp_mailbox_chan, cl);
6944+	struct fsl_dsp *dsp_priv = container_of(chan, struct fsl_dsp, chan_rx0);
6945+	struct xf_proxy *proxy = &dsp_priv->proxy;
6946+	union icm_header_t msghdr;
6947+
6948+	msghdr = *(union icm_header_t *)msg;
6949+
6950+	if (dsp_priv->dsp_is_lpa)
6951+		pm_system_wakeup();
6952+
6953+	if (msghdr.intr == 1) {
6954+		dev_dbg(dev, "INTR: Received ICM intr, msg 0x%08x\n",
6955+						msghdr.allbits);
6956+		switch (msghdr.msg) {
6957+		case ICM_CORE_EXIT:
6958+			break;
6959+		case ICM_CORE_READY:
6960+			send_dpu_ext_msg_addr(proxy);
6961+			proxy->is_ready = 1;
6962+			complete(&proxy->cmd_complete);
6963+			break;
6964+		case XF_SUSPEND:
6965+		case XF_RESUME:
6966+		case XF_PAUSE:
6967+		case XF_PAUSE_RELEASE:
6968+			complete(&proxy->cmd_complete);
6969+			break;
6970+		default:
6971+			schedule_work(&proxy->work);
6972+			break;
6973+		}
6974+	} else if (msghdr.ack == 1) {
6975+		dev_dbg(dev, "INTR: Received ICM ack 0x%08x\n", msghdr.size);
6976+		msghdr.ack = 0;
6977+	} else {
6978+		dev_dbg(dev, "Received false ICM intr 0x%08x\n",
6979+							msghdr.allbits);
6980+	}
6981+}
6982+
6983+static int request_chan(struct fsl_dsp *dsp_priv, struct dsp_mailbox_chan *chan)
6984+{
6985+	int ret = 0;
6986+	struct mbox_client *cl;
6987+	struct device *dev = dsp_priv->dev;
6988+
6989+	cl = &chan->cl;
6990+	cl->tx_block = false;
6991+	cl->knows_txdone = false;
6992+	cl->dev = dev;
6993+	cl->rx_callback = dsp_rx_callback;
6994+
6995+	chan->ch = mbox_request_channel_byname(cl, chan->name);
6996+	if (IS_ERR(chan->ch)) {
6997+		chan->ch = NULL;
6998+		return -EINVAL;
6999+	}
7000+
7001+	return ret;
7002+}
7003+
7004+void dsp_free_chan(struct xf_proxy *proxy)
7005+{
7006+	struct fsl_dsp *dsp_priv = container_of(proxy,
7007+				struct fsl_dsp, proxy);
7008+	int i;
7009+
7010+	for (i = 0; i < NUM_MAILBOX_CHAN; i++) {
7011+		if (dsp_priv->chan_tx[i].ch) {
7012+			mbox_free_channel(dsp_priv->chan_tx[i].ch);
7013+			dsp_priv->chan_tx[i].ch = NULL;
7014+			memset(dsp_priv->chan_tx[i].name, 0, sizeof(dsp_priv->chan_tx[i].name));
7015+		}
7016+	}
7017+	if (dsp_priv->chan_rx0.ch) {
7018+		mbox_free_channel(dsp_priv->chan_rx0.ch);
7019+		dsp_priv->chan_rx0.ch =  NULL;
7020+		memset(dsp_priv->chan_rx0.name, 0, sizeof(dsp_priv->chan_rx0.name));
7021+	}
7022+}
7023+
7024+/* ...request mailbox chan */
7025+int dsp_request_chan(struct xf_proxy *proxy)
7026+{
7027+	struct fsl_dsp *dsp_priv = container_of(proxy, struct fsl_dsp, proxy);
7028+	struct device *dev = dsp_priv->dev;
7029+	int i;
7030+	int ret = 0;
7031+
7032+	for (i = 0; i < NUM_MAILBOX_CHAN; i++) {
7033+		scnprintf(dsp_priv->chan_tx[i].name, sizeof(dsp_priv->chan_tx[i].name) - 1,
7034+			"tx%d", i);
7035+		ret = request_chan(dsp_priv, &dsp_priv->chan_tx[i]);
7036+		if (ret) {
7037+			dev_err(dev, "request chan_tx failed\n");
7038+			goto err;
7039+		}
7040+	}
7041+
7042+	scnprintf(dsp_priv->chan_rx0.name, sizeof(dsp_priv->chan_rx0.name) - 1,
7043+		"rx0");
7044+	ret = request_chan(dsp_priv, &dsp_priv->chan_rx0);
7045+	if (ret) {
7046+		dev_err(dev, "request chan_rx0 failed\n");
7047+		goto err;
7048+	}
7049+	return ret;
7050+
7051+err:
7052+	dsp_free_chan(proxy);
7053+	return ret;
7054+}
7055+
7056+/*
7057+ * Proxy related functions
7058+ */
7059+/* ...NULL-address specification */
7060+#define XF_PROXY_NULL           (~0U)
7061+
7062+#define XF_PROXY_BADADDR        (dsp_priv->scratch_buf_size)
7063+
7064+/* ...shared memory translation - kernel virtual address to shared address */
7065+u32 xf_proxy_b2a(struct xf_proxy *proxy, void *b)
7066+{
7067+	struct fsl_dsp *dsp_priv = container_of(proxy,
7068+					struct fsl_dsp, proxy);
7069+
7070+	if (b == NULL)
7071+		return XF_PROXY_NULL;
7072+	else if ((u32)(b - dsp_priv->scratch_buf_virt) <
7073+					dsp_priv->scratch_buf_size)
7074+		return (u32)(b - dsp_priv->scratch_buf_virt);
7075+	else if (dsp_priv->dsp_is_lpa && ((u32)(b - dsp_priv->dram_reserved_vir_addr) <
7076+					dsp_priv->dram_reserved_size))
7077+		return (u32)(b - dsp_priv->dram_reserved_vir_addr + dsp_priv->scratch_buf_size);
7078+	else
7079+		return XF_PROXY_BADADDR;
7080+}
7081+
7082+/* ...shared memory translation - shared address to kernel virtual address */
7083+void *xf_proxy_a2b(struct xf_proxy *proxy, u32 address)
7084+{
7085+	struct fsl_dsp *dsp_priv = container_of(proxy,
7086+					struct fsl_dsp, proxy);
7087+
7088+	if (address < dsp_priv->scratch_buf_size)
7089+		return dsp_priv->scratch_buf_virt + address;
7090+	else if (dsp_priv->dsp_is_lpa && (address < dsp_priv->scratch_buf_size + dsp_priv->dram_reserved_size))
7091+		return dsp_priv->dram_reserved_vir_addr + address - dsp_priv->scratch_buf_size;
7092+	else if (address == XF_PROXY_NULL)
7093+		return NULL;
7094+	else
7095+		return (void *) -1;
7096+}
7097+
7098+/* ...process association between response received and intended client */
7099+static void xf_cmap(struct xf_proxy *proxy, struct xf_message *m)
7100+{
7101+	struct fsl_dsp *dsp_priv = container_of(proxy,
7102+					struct fsl_dsp, proxy);
7103+	u32 id = XF_AP_IPC_CLIENT(m->id);
7104+	struct xf_client *client;
7105+
7106+	/* ...process messages addressed to proxy itself */
7107+	if (id == 0) {
7108+		/* ...place message into local response queue */
7109+		xf_msg_enqueue(&proxy->response, m);
7110+		wake_up(&proxy->wait);
7111+		return;
7112+	}
7113+
7114+	/* ...make sure the client ID is sane */
7115+	client = xf_client_lookup(dsp_priv, id);
7116+	if (!client) {
7117+		pr_err("rsp[id:%08x]: client lookup failed", m->id);
7118+		xf_msg_free(proxy, m);
7119+		return;
7120+	}
7121+
7122+	/* ...make sure client is bound to this proxy interface */
7123+	if (client->proxy != proxy) {
7124+		pr_err("rsp[id:%08x]: wrong proxy interface", m->id);
7125+		xf_msg_free(proxy, m);
7126+		return;
7127+	}
7128+
7129+	/* ...place message into local response queue */
7130+	if (xf_msg_enqueue(&client->queue, m))
7131+		wake_up(&client->wait);
7132+}
7133+
7134+/* ...retrieve pending responses from shared memory ring-buffer */
7135+static u32 xf_shmem_process_responses(struct xf_proxy *proxy)
7136+{
7137+	struct xf_message *m;
7138+	u32 read_idx, write_idx;
7139+	int status;
7140+
7141+	status = 0;
7142+
7143+	/* ...get current values of read/write pointers in response queue */
7144+	read_idx = XF_PROXY_READ(proxy, rsp_read_idx);
7145+	write_idx = XF_PROXY_READ(proxy, rsp_write_idx);
7146+
7147+	/* ...process all committed responses */
7148+	while (!XF_QUEUE_EMPTY(read_idx, write_idx)) {
7149+		struct xf_proxy_message *response;
7150+
7151+		/* ...allocate execution message */
7152+		m = xf_msg_alloc(proxy);
7153+		if (m  == NULL)
7154+			break;
7155+
7156+		/* ...mark the interface status has changed */
7157+		status |= (XF_QUEUE_FULL(read_idx, write_idx) ? 0x3 : 0x1);
7158+
7159+		/* ...get oldest not yet processed response */
7160+		response = XF_PROXY_RESPONSE(proxy, XF_QUEUE_IDX(read_idx));
7161+
7162+		/* ...fill message parameters */
7163+		m->id = response->session_id;
7164+		m->opcode = response->opcode;
7165+		m->length = response->length;
7166+		m->buffer = xf_proxy_a2b(proxy, response->address);
7167+		m->ret = response->ret;
7168+
7169+		/* ...advance local reading index copy */
7170+		read_idx = XF_QUEUE_ADVANCE_IDX(read_idx);
7171+
7172+		/* ...update shadow copy of reading index */
7173+		XF_PROXY_WRITE(proxy, rsp_read_idx, read_idx);
7174+
7175+		/* ...submit message to proper client */
7176+		xf_cmap(proxy, m);
7177+	}
7178+
7179+	return status;
7180+}
7181+
7182+/* ...put pending commands into shared memory ring-buffer */
7183+static u32 xf_shmem_process_commands(struct xf_proxy *proxy)
7184+{
7185+	struct xf_message *m;
7186+	u32 read_idx, write_idx;
7187+	int status = 0;
7188+
7189+	/* ...get current value of peer read pointer */
7190+	write_idx = XF_PROXY_READ(proxy, cmd_write_idx);
7191+	read_idx = XF_PROXY_READ(proxy, cmd_read_idx);
7192+
7193+	/* ...submit any pending commands */
7194+	while (!XF_QUEUE_FULL(read_idx, write_idx)) {
7195+		struct xf_proxy_message *command;
7196+
7197+		/* ...check if we have a pending command */
7198+		m = xf_msg_dequeue(&proxy->command);
7199+		if (m  == NULL)
7200+			break;
7201+
7202+		/* ...always mark the interface status has changed */
7203+		status |= 0x3;
7204+
7205+		/* ...select the place for the command */
7206+		command = XF_PROXY_COMMAND(proxy, XF_QUEUE_IDX(write_idx));
7207+
7208+		/* ...put the response message fields */
7209+		command->session_id = m->id;
7210+		command->opcode = m->opcode;
7211+		command->length = m->length;
7212+		command->address = xf_proxy_b2a(proxy, m->buffer);
7213+		command->ret = m->ret;
7214+
7215+		/* ...return message back to the pool */
7216+		xf_msg_free(proxy, m);
7217+
7218+		/* ...advance local writing index copy */
7219+		write_idx = XF_QUEUE_ADVANCE_IDX(write_idx);
7220+
7221+		/* ...update shared copy of queue write pointer */
7222+		XF_PROXY_WRITE(proxy, cmd_write_idx, write_idx);
7223+	}
7224+
7225+	if (status)
7226+		icm_intr_send(proxy, 0);
7227+
7228+	return status;
7229+}
7230+
7231+/* ...shared memory interface maintenance routine */
7232+void xf_proxy_process(struct work_struct *w)
7233+{
7234+	struct xf_proxy *proxy = container_of(w, struct xf_proxy, work);
7235+	int status = 0;
7236+
7237+	/* ...get exclusive access to internal data */
7238+	xf_lock(&proxy->lock);
7239+
7240+	do {
7241+		/* ...process outgoing commands first */
7242+		status = xf_shmem_process_commands(proxy);
7243+
7244+		/* ...process all pending responses */
7245+		status |= xf_shmem_process_responses(proxy);
7246+
7247+	} while (status);
7248+
7249+	/* ...unlock internal proxy data */
7250+	xf_unlock(&proxy->lock);
7251+}
7252+
7253+/* ...initialize shared memory interface */
7254+int xf_proxy_init(struct xf_proxy *proxy)
7255+{
7256+	struct fsl_dsp *dsp_priv = container_of(proxy,
7257+					struct fsl_dsp, proxy);
7258+	struct xf_message *m;
7259+	int i;
7260+
7261+	/* ...create a list of all messages in a pool; set head pointer */
7262+	proxy->free = &proxy->pool[0];
7263+
7264+	/* ...put all messages into a single-linked list */
7265+	for (i = 0, m = proxy->free; i < XF_CFG_MESSAGE_POOL_SIZE - 1; i++, m++)
7266+		m->next = m + 1;
7267+
7268+	/* ...set list tail pointer */
7269+	m->next = NULL;
7270+
7271+	/* ...initialize proxy lock */
7272+	xf_lock_init(&proxy->lock);
7273+
7274+	/* ...initialize proxy thread message queues */
7275+	xf_msg_queue_init(&proxy->command);
7276+	xf_msg_queue_init(&proxy->response);
7277+
7278+	/* ...initialize global busy queue */
7279+	init_waitqueue_head(&proxy->busy);
7280+	init_waitqueue_head(&proxy->wait);
7281+
7282+	/* ...create work structure */
7283+	INIT_WORK(&proxy->work, xf_proxy_process);
7284+
7285+	/* ...set pointer to shared memory */
7286+	proxy->ipc.shmem = (struct xf_shmem_data *)dsp_priv->msg_buf_virt;
7287+
7288+	/* ...initialize shared memory interface */
7289+	XF_PROXY_WRITE(proxy, cmd_read_idx, 0);
7290+	XF_PROXY_WRITE(proxy, cmd_write_idx, 0);
7291+	XF_PROXY_WRITE(proxy, cmd_invalid, 0);
7292+	XF_PROXY_WRITE(proxy, rsp_read_idx, 0);
7293+	XF_PROXY_WRITE(proxy, rsp_write_idx, 0);
7294+	XF_PROXY_WRITE(proxy, rsp_invalid, 0);
7295+
7296+	return 0;
7297+}
7298+
7299+/* ...trigger shared memory interface processing */
7300+void xf_proxy_notify(struct xf_proxy *proxy)
7301+{
7302+	schedule_work(&proxy->work);
7303+}
7304+
7305+/* ...submit a command to proxy pending queue (lock released upon return) */
7306+void xf_proxy_command(struct xf_proxy *proxy, struct xf_message *m)
7307+{
7308+	int first;
7309+
7310+	/* ...submit message to proxy thread */
7311+	first = xf_msg_enqueue(&proxy->command, m);
7312+
7313+	/* ...release the lock */
7314+	xf_unlock(&proxy->lock);
7315+
7316+	/* ...notify thread about command reception */
7317+	(first ? xf_proxy_notify(proxy), 1 : 0);
7318+}
7319+
7320+/*
7321+ * Proxy cmd send and receive functions
7322+ */
7323+int xf_cmd_send(struct xf_proxy *proxy,
7324+				u32 id,
7325+				u32 opcode,
7326+				void *buffer,
7327+				u32 length)
7328+{
7329+	struct xf_message *m;
7330+	int ret;
7331+
7332+	/* ...retrieve message handle (take the lock on success) */
7333+	ret = wait_event_interruptible(proxy->busy,
7334+					(m = xf_msg_available(proxy)) != NULL);
7335+	if (ret)
7336+		return -EINTR;
7337+
7338+	/* ...fill-in message parameters (lock is taken) */
7339+	m->id = id;
7340+	m->opcode = opcode;
7341+	m->length = length;
7342+	m->buffer = buffer;
7343+	m->ret = 0;
7344+
7345+	/* ...submit command to the proxy */
7346+	xf_proxy_command(proxy, m);
7347+
7348+	return 0;
7349+}
7350+
7351+struct xf_message *xf_cmd_recv(struct xf_proxy *proxy,
7352+						  wait_queue_head_t *wq,
7353+						  struct xf_msg_queue *queue,
7354+						  int wait)
7355+{
7356+	struct xf_message *m = NULL;
7357+	int ret;
7358+
7359+	/* ...wait for message reception (take lock on success) */
7360+	ret = wait_event_interruptible(*wq,
7361+			(m = xf_msg_received(proxy, queue)) != NULL || !wait
7362+			|| !proxy->is_active);
7363+	if (ret)
7364+		return ERR_PTR(-EINTR);
7365+
7366+	/* ...return message with a lock taken */
7367+	return m;
7368+}
7369+
7370+struct xf_message *xf_cmd_recv_timeout(struct xf_proxy *proxy,
7371+				       wait_queue_head_t *wq,
7372+				       struct xf_msg_queue *queue, int wait)
7373+{
7374+	struct xf_message *m;
7375+	int ret;
7376+
7377+	/* ...wait for message reception (take lock on success) */
7378+	ret = wait_event_interruptible_timeout(*wq,
7379+			(m = xf_msg_received(proxy, queue)) != NULL || !wait,
7380+			msecs_to_jiffies(1000));
7381+	if (ret < 0)
7382+		return ERR_PTR(-EINTR);
7383+
7384+	if (ret == 0)
7385+		return ERR_PTR(-ETIMEDOUT);
7386+
7387+	/* ...return message with a lock taken */
7388+	return m;
7389+}
7390+
7391+/* ...helper function for synchronous command execution */
7392+struct xf_message *xf_cmd_send_recv(struct xf_proxy *proxy,
7393+							   u32 id, u32 opcode,
7394+							   void *buffer,
7395+							   u32 length)
7396+{
7397+	int ret;
7398+
7399+	/* ...send command to remote proxy */
7400+	ret = xf_cmd_send(proxy, id, opcode, buffer, length);
7401+	if (ret)
7402+		return ERR_PTR(ret);
7403+
7404+	/* ...wait for message delivery */
7405+	return xf_cmd_recv(proxy, &proxy->wait, &proxy->response, 1);
7406+}
7407+
7408+struct xf_message *xf_cmd_send_recv_wq(struct xf_proxy *proxy, u32 id,
7409+				       u32 opcode, void *buffer, u32 length,
7410+				       wait_queue_head_t *wq,
7411+				       struct xf_msg_queue *queue)
7412+{
7413+	int ret;
7414+
7415+	/* ...send command to remote proxy */
7416+	ret = xf_cmd_send(proxy, id, opcode, buffer, length);
7417+	if (ret)
7418+		return ERR_PTR(ret);
7419+
7420+	/* ...wait for message delivery */
7421+	return xf_cmd_recv(proxy, wq, queue, 1);
7422+}
7423+
7424+struct xf_message *xf_cmd_send_recv_complete(struct xf_client *client,
7425+					     struct xf_proxy *proxy,
7426+					     u32 id, u32 opcode, void *buffer,
7427+					     u32 length,
7428+					     struct work_struct *work,
7429+					     struct completion *completion)
7430+{
7431+	struct xf_message *m;
7432+	int ret;
7433+
7434+	/* ...retrieve message handle (take the lock on success) */
7435+	m = xf_msg_available(proxy);
7436+	if (!m)
7437+		return ERR_PTR(-EBUSY);
7438+
7439+	/* ...fill-in message parameters (lock is taken) */
7440+	m->id = id;
7441+	m->opcode = opcode;
7442+	m->length = length;
7443+	m->buffer = buffer;
7444+	m->ret = 0;
7445+
7446+	init_completion(completion);
7447+
7448+	/* ...submit command to the proxy */
7449+	xf_proxy_command(proxy, m);
7450+
7451+	schedule_work(work);
7452+
7453+	/* ...wait for message reception (take lock on success) */
7454+	ret = wait_for_completion_timeout(completion,
7455+					  msecs_to_jiffies(1000));
7456+	if (!ret)
7457+		return ERR_PTR(-ETIMEDOUT);
7458+
7459+	m = &client->m;
7460+
7461+	/* ...return message with a lock taken */
7462+	return m;
7463+}
7464+/*
7465+ * Proxy allocate and free memory functions
7466+ */
7467+/* ...allocate memory buffer for kernel use */
7468+int xf_cmd_alloc(struct xf_proxy *proxy, void **buffer, u32 length)
7469+{
7470+	struct xf_message *m;
7471+	u32 id = 0;
7472+	int ret;
7473+
7474+	/* ...send command to remote proxy */
7475+	m = xf_cmd_send_recv(proxy, id, XF_ALLOC, NULL, length);
7476+	if (IS_ERR(m)) {
7477+		xf_unlock(&proxy->lock);
7478+		ret = PTR_ERR(m);
7479+		return ret;
7480+	}
7481+
7482+	/* ...check if response is expected */
7483+	if (m->opcode == XF_ALLOC && m->buffer != NULL) {
7484+		*buffer = m->buffer;
7485+		ret = 0;
7486+	} else {
7487+		ret = -ENOMEM;
7488+	}
7489+
7490+	/* ...free message and release proxy lock */
7491+	xf_msg_free(proxy, m);
7492+	xf_unlock(&proxy->lock);
7493+
7494+	return ret;
7495+}
7496+
7497+/* ...free memory buffer */
7498+int xf_cmd_free(struct xf_proxy *proxy, void *buffer, u32 length)
7499+{
7500+	struct xf_message *m;
7501+	u32 id = 0;
7502+	int ret;
7503+
7504+	/* ...synchronously execute freeing command */
7505+	m = xf_cmd_send_recv(proxy, id, XF_FREE, buffer, length);
7506+	if (IS_ERR(m)) {
7507+		xf_unlock(&proxy->lock);
7508+		ret = PTR_ERR(m);
7509+		return ret;
7510+	}
7511+
7512+	/* ...check if response is expected */
7513+	if (m->opcode == XF_FREE)
7514+		ret = 0;
7515+	else
7516+		ret = -EINVAL;
7517+
7518+	/* ...free message and release proxy lock */
7519+	xf_msg_free(proxy, m);
7520+	xf_unlock(&proxy->lock);
7521+
7522+	return ret;
7523+}
7524+
7525+/*
7526+ * suspend & resume functions
7527+ */
7528+int xf_cmd_send_suspend(struct xf_proxy *proxy)
7529+{
7530+	union icm_header_t msghdr;
7531+	int ret = 0;
7532+
7533+	init_completion(&proxy->cmd_complete);
7534+
7535+	msghdr.allbits = 0;	/* clear all bits; */
7536+	msghdr.ack  = 0;
7537+	msghdr.intr = 1;
7538+	msghdr.msg  = XF_SUSPEND;
7539+	msghdr.size = 0;
7540+	icm_intr_send(proxy, msghdr.allbits);
7541+
7542+	/* wait for response here */
7543+	ret = icm_ack_wait(proxy, msghdr.allbits);
7544+
7545+	return ret;
7546+}
7547+
7548+int xf_cmd_send_resume(struct xf_proxy *proxy)
7549+{
7550+	union icm_header_t msghdr;
7551+	int ret = 0;
7552+
7553+	init_completion(&proxy->cmd_complete);
7554+
7555+	msghdr.allbits = 0;	/* clear all bits; */
7556+	msghdr.ack  = 0;
7557+	msghdr.intr = 1;
7558+	msghdr.msg  = XF_RESUME;
7559+	msghdr.size = 0;
7560+	icm_intr_send(proxy, msghdr.allbits);
7561+
7562+	/* wait for response here */
7563+	ret = icm_ack_wait(proxy, msghdr.allbits);
7564+
7565+	return ret;
7566+}
7567+/*
7568+ * pause & pause_release functions
7569+ */
7570+int xf_cmd_send_pause(struct xf_proxy *proxy)
7571+{
7572+	union icm_header_t msghdr;
7573+	int ret = 0;
7574+
7575+	init_completion(&proxy->cmd_complete);
7576+
7577+	msghdr.allbits = 0;	/* clear all bits; */
7578+	msghdr.ack  = 0;
7579+	msghdr.intr = 1;
7580+	msghdr.msg  = XF_PAUSE;
7581+	msghdr.size = 0;
7582+	icm_intr_send(proxy, msghdr.allbits);
7583+
7584+	/* wait for response here */
7585+	ret = icm_ack_wait(proxy, msghdr.allbits);
7586+
7587+	return ret;
7588+}
7589+
7590+int xf_cmd_send_pause_release(struct xf_proxy *proxy)
7591+{
7592+	union icm_header_t msghdr;
7593+	int ret = 0;
7594+
7595+	init_completion(&proxy->cmd_complete);
7596+
7597+	msghdr.allbits = 0;	/* clear all bits; */
7598+	msghdr.ack  = 0;
7599+	msghdr.intr = 1;
7600+	msghdr.msg  = XF_PAUSE_RELEASE;
7601+	msghdr.size = 0;
7602+	icm_intr_send(proxy, msghdr.allbits);
7603+
7604+	/* wait for response here */
7605+	ret = icm_ack_wait(proxy, msghdr.allbits);
7606+
7607+	return ret;
7608+}
7609+
7610+/* ...open component handle */
7611+int xf_open(struct xf_client *client, struct xf_proxy *proxy,
7612+	    struct xf_handle *handle, const char *id, u32 core,
7613+	    xf_response_cb response)
7614+{
7615+	void *b;
7616+	struct xf_message   msg;
7617+	struct xf_message   *rmsg;
7618+
7619+	/* ...retrieve auxiliary control buffer from proxy - need I */
7620+	handle->aux = xf_buffer_get(proxy->aux);
7621+
7622+	b = xf_handle_aux(handle);
7623+
7624+	msg.id = __XF_MSG_ID(__XF_AP_PROXY(0), __XF_DSP_PROXY(0));
7625+	msg.id = XF_MSG_AP_FROM_USER(msg.id, client->id);
7626+	msg.opcode = XF_REGISTER;
7627+	msg.buffer = b;
7628+	msg.length = strlen(id) + 1;
7629+	msg.ret = 0;
7630+
7631+	/* ...copy component identifier */
7632+	memcpy(b, (void *)id, xf_buffer_length(handle->aux));
7633+
7634+	/* ...execute command synchronously */
7635+	rmsg = xf_cmd_send_recv_complete(client, proxy, msg.id, msg.opcode,
7636+					 msg.buffer, msg.length, &client->work,
7637+					 &client->compr_complete);
7638+
7639+	if (IS_ERR(rmsg)) {
7640+		xf_buffer_put(handle->aux), handle->aux = NULL;
7641+		return PTR_ERR(rmsg);
7642+	}
7643+	/* ...save received component global client-id */
7644+	handle->id = XF_MSG_SRC(rmsg->id);
7645+	/* TODO: review cleanup */
7646+	/* xf_msg_free(proxy, rmsg);
7647+	 * xf_unlock(&proxy->lock); */
7648+
7649+	/* ...if failed, release buffer handle */
7650+	/* ...operation completed successfully; assign handle data */
7651+	handle->response = response;
7652+	handle->proxy = proxy;
7653+
7654+	return 0;
7655+}
7656+
7657+/* ...close component handle */
7658+int xf_close(struct xf_client *client, struct xf_handle *handle)
7659+{
7660+	struct xf_proxy *proxy = handle->proxy;
7661+	struct xf_message   msg;
7662+	struct xf_message *rmsg;
7663+
7664+	/* ...do I need to take component lock here? guess no - tbd */
7665+
7666+	/* ...buffers and stuff? - tbd */
7667+
7668+	/* ...acquire global proxy lock */
7669+	/* ...unregister component from remote DSP proxy (ignore result code) */
7670+
7671+	msg.id = __XF_MSG_ID(__XF_AP_PROXY(0), handle->id);
7672+	msg.id = XF_MSG_AP_FROM_USER(msg.id, client->id);
7673+	msg.opcode = XF_UNREGISTER;
7674+	msg.buffer = NULL;
7675+	msg.length = 0;
7676+	msg.ret = 0;
7677+
7678+	/* ...execute command synchronously */
7679+	rmsg = xf_cmd_send_recv_complete(client, proxy, msg.id, msg.opcode,
7680+					 msg.buffer, msg.length, &client->work,
7681+					 &client->compr_complete);
7682+
7683+	if (IS_ERR(rmsg)) {
7684+		xf_buffer_put(handle->aux), handle->aux = NULL;
7685+		return PTR_ERR(rmsg);
7686+	}
7687+	/* TODO: review cleanup */
7688+	/* xf_msg_free(proxy, rmsg);
7689+	 * xf_unlock(&proxy->lock); */
7690+
7691+	/* ...wipe out proxy pointer */
7692+	handle->proxy = NULL;
7693+
7694+	return 0;
7695+}
7696diff --git a/sound/soc/fsl/fsl_dsp_proxy.h b/sound/soc/fsl/fsl_dsp_proxy.h
7697new file mode 100644
7698index 000000000..aa7e964ef
7699--- /dev/null
7700+++ b/sound/soc/fsl/fsl_dsp_proxy.h
7701@@ -0,0 +1,523 @@
7702+/* SPDX-License-Identifier: (GPL-2.0+ OR MIT) */
7703+/*
7704+ * DSP proxy header - commands/responses from DSP driver to DSP ramework
7705+ *
7706+ * Copyright 2018 NXP
7707+ * Copyright (c) 2017 Cadence Design Systems, Inc.
7708+ */
7709+
7710+#ifndef __FSL_DSP_PROXY_H
7711+#define __FSL_DSP_PROXY_H
7712+
7713+#include <linux/wait.h>
7714+#include <linux/device.h>
7715+#include <linux/workqueue.h>
7716+#include <linux/spinlock.h>
7717+#include <linux/compiler.h>
7718+#include <linux/dma-mapping.h>
7719+#include <linux/platform_data/dma-imx.h>
7720+#include <linux/mx8_mu.h>
7721+#include <linux/interrupt.h>
7722+
7723+#include "fsl_dsp_pool.h"
7724+#define XF_CFG_MESSAGE_POOL_SIZE        256
7725+
7726+struct xf_client;
7727+
7728+/*******************************************************************************
7729+ * Local proxy data
7730+ ******************************************************************************/
7731+
7732+struct xf_message;
7733+struct xf_handle;
7734+typedef void (*xf_response_cb)(struct xf_handle *h, struct xf_message *msg);
7735+
7736+/* ...execution message */
7737+struct xf_message {
7738+	/* ...pointer to next message in a list */
7739+	struct xf_message   *next;
7740+
7741+	/* ...session-id */
7742+	u32                 id;
7743+
7744+	/* ...operation code */
7745+	u32                 opcode;
7746+
7747+	/* ...length of data buffer */
7748+	u32                 length;
7749+
7750+	/* ...translated data pointer */
7751+	void               *buffer;
7752+
7753+	/* ...return message status */
7754+	u32                ret;
7755+};
7756+
7757+/* ...message queue */
7758+struct xf_msg_queue {
7759+	/* ...pointer to list head */
7760+	struct xf_message   *head;
7761+
7762+	/* ...pointer to list tail */
7763+	struct xf_message   *tail;
7764+};
7765+
7766+struct xf_proxy_message {
7767+	/* ...session ID */
7768+	u32 session_id;
7769+
7770+	/* ...proxy API command/response code */
7771+	u32 opcode;
7772+
7773+	/* ...length of attached buffer */
7774+	u32 length;
7775+
7776+	/* ...physical address of message buffer */
7777+	u32 address;
7778+
7779+	/* ...return message status */
7780+	u32 ret;
7781+};
7782+/**********************************************************************/
7783+
7784+enum icm_action_t {
7785+	ICM_CORE_READY = 1,
7786+	ICM_CORE_INIT,
7787+	ICM_CORE_EXIT,
7788+};
7789+
7790+/* ...adjust IPC client of message going from user-space */
7791+#define XF_MSG_AP_FROM_USER(id, client) (((id) & ~(0xF << 2)) | (client << 2))
7792+
7793+
7794+#define __XF_PORT_SPEC(core, id, port)  ((core) | ((id) << 2) | ((port) << 8))
7795+#define __XF_PORT_SPEC2(id, port)       ((id) | ((port) << 8))
7796+
7797+
7798+/* ...wipe out IPC client from message going to user-space */
7799+#define XF_MSG_AP_TO_USER(id)   ((id) & ~(0xF << 18))
7800+#define __XF_AP_PROXY(core)     ((core) | 0x8000)
7801+#define __XF_DSP_PROXY(core)    ((core) | 0x8000)
7802+
7803+/* ...message id contains source and destination ports specification */
7804+#define __XF_MSG_ID(src, dst)   (((src) & 0xFFFF) | (((dst) & 0xFFFF) << 16))
7805+#define XF_MSG_SRC(id)          (((id) >> 0) & 0xFFFF)
7806+#define XF_MSG_SRC_CORE(id)     (((id) >> 0) & 0x3)
7807+#define XF_MSG_SRC_CLIENT(id)   (((id) >> 2) & 0x3F)
7808+#define XF_MSG_DST_CLIENT(id)   (((id) >> 18) & 0x3F)
7809+
7810+/* ...special treatment of AP-proxy destination field */
7811+#define XF_AP_IPC_CLIENT(id)            (((id) >> 18) & 0xF)
7812+#define XF_AP_CLIENT(id)                (((id) >> 22) & 0x1FF)
7813+#define __XF_AP_PROXY(core)             ((core) | 0x8000)
7814+#define __XF_DSP_PROXY(core)            ((core) | 0x8000)
7815+#define __XF_AP_CLIENT(core, client)    ((core) | ((client) << 6) | 0x8000)
7816+
7817+/* ...opcode composition with command/response data tags */
7818+#define __XF_OPCODE(c, r, op)   (((c) << 31) | ((r) << 30) | ((op) & 0x3F))
7819+
7820+/* ...shared buffer allocation */
7821+#define XF_ALLOC                        __XF_OPCODE(0, 0, 4)
7822+
7823+/* ...shared buffer freeing */
7824+#define XF_FREE                         __XF_OPCODE(0, 0, 5)
7825+
7826+/* ...resume component operation */
7827+#define XF_RESUME                       __XF_OPCODE(0, 0, 14)
7828+
7829+/* ...resume component operation */
7830+#define XF_SUSPEND                      __XF_OPCODE(0, 0, 15)
7831+
7832+/*******************************************************************************
7833+ * Ring buffer support
7834+ ******************************************************************************/
7835+/* ...cache-line size on DSP */
7836+#define XF_PROXY_ALIGNMENT              64
7837+
7838+/* ...total length of shared memory queue (for commands and responses) */
7839+#define XF_PROXY_MESSAGE_QUEUE_LENGTH   (1 << 6)
7840+
7841+/* ...index mask */
7842+#define XF_PROXY_MESSAGE_QUEUE_MASK     0x3F
7843+
7844+/* ...ring-buffer index */
7845+#define __XF_QUEUE_IDX(idx, counter)    \
7846+		(((idx) & XF_PROXY_MESSAGE_QUEUE_MASK) | ((counter) << 16))
7847+
7848+/* ...retrieve ring-buffer index */
7849+#define XF_QUEUE_IDX(idx)               \
7850+		((idx) & XF_PROXY_MESSAGE_QUEUE_MASK)
7851+
7852+/* ...increment ring-buffer index */
7853+#define XF_QUEUE_ADVANCE_IDX(idx)       \
7854+		(((idx) + 0x10001) & (0xFFFF0000 | XF_PROXY_MESSAGE_QUEUE_MASK))
7855+
7856+/* ...test if ring buffer is empty */
7857+#define XF_QUEUE_EMPTY(read, write)     \
7858+		((read) == (write))
7859+
7860+/* ...test if ring buffer is full */
7861+#define XF_QUEUE_FULL(read, write)      \
7862+		((write) == (read) + (XF_PROXY_MESSAGE_QUEUE_LENGTH << 16))
7863+
7864+/* ...basic cache operations */
7865+#define XF_PROXY_INVALIDATE(addr, len)  { }
7866+
7867+#define XF_PROXY_FLUSH(addr, len)       { }
7868+
7869+/* ...data managed by host CPU (remote) - in case of shunt it is a IPC layer */
7870+struct xf_proxy_host_data {
7871+	/* ...command queue */
7872+	struct xf_proxy_message command[XF_PROXY_MESSAGE_QUEUE_LENGTH];
7873+
7874+	/* ...writing index into command queue */
7875+	u32                 cmd_write_idx;
7876+
7877+	/* ...reading index for response queue */
7878+	u32                 rsp_read_idx;
7879+
7880+	/* ...indicate command queue is valid or not */
7881+	u32                 cmd_invalid;
7882+};
7883+
7884+/* ...data managed by DSP (local) */
7885+struct xf_proxy_dsp_data {
7886+	/* ...response queue */
7887+	struct xf_proxy_message response[XF_PROXY_MESSAGE_QUEUE_LENGTH];
7888+
7889+	/* ...writing index into response queue */
7890+	u32                 rsp_write_idx;
7891+
7892+	/* ...reading index for command queue */
7893+	u32                 cmd_read_idx;
7894+
7895+	/* ...indicate response queue is valid or not */
7896+	u32                 rsp_invalid;
7897+};
7898+
7899+/* ...shared memory data */
7900+struct xf_shmem_data {
7901+	/* ...ingoing data (maintained by DSP (local side)) */
7902+	struct xf_proxy_host_data    local;
7903+
7904+	/* ...outgoing data (maintained by host CPU (remote side)) */
7905+	struct xf_proxy_dsp_data   remote;
7906+
7907+};
7908+
7909+/* ...shared memory data accessor */
7910+#define XF_SHMEM_DATA(proxy)                \
7911+		((proxy)->ipc.shmem)
7912+
7913+/* ...atomic reading */
7914+#define __XF_PROXY_READ_ATOMIC(var)         \
7915+	({ XF_PROXY_INVALIDATE(&(var), sizeof(var));  \
7916+	 *(u32 *)&(var); })
7917+
7918+/* ...atomic writing */
7919+#define __XF_PROXY_WRITE_ATOMIC(var, value) \
7920+	({*(u32 *)&(var) = (value);    \
7921+	 XF_PROXY_FLUSH(&(var), sizeof(var));   \
7922+	 (value); })
7923+
7924+/* ...accessors */
7925+#define XF_PROXY_READ(proxy, field)          \
7926+		__XF_PROXY_READ_##field(XF_SHMEM_DATA(proxy))
7927+
7928+#define XF_PROXY_WRITE(proxy, field, v)      \
7929+		__XF_PROXY_WRITE_##field(XF_SHMEM_DATA(proxy), (v))
7930+
7931+/* ...individual fields reading */
7932+#define __XF_PROXY_READ_cmd_write_idx(shmem)        \
7933+		__XF_PROXY_READ_ATOMIC(shmem->local.cmd_write_idx)
7934+
7935+#define __XF_PROXY_READ_cmd_read_idx(shmem)         \
7936+		shmem->remote.cmd_read_idx
7937+
7938+#define __XF_PROXY_READ_cmd_invalid(shmem)            \
7939+		__XF_PROXY_READ_ATOMIC(shmem->local.cmd_invalid)
7940+
7941+#define __XF_PROXY_READ_rsp_write_idx(shmem)        \
7942+		__XF_PROXY_READ_ATOMIC(shmem->remote.rsp_write_idx)
7943+
7944+#define __XF_PROXY_READ_rsp_read_idx(shmem)         \
7945+		shmem->local.rsp_read_idx
7946+
7947+#define __XF_PROXY_READ_rsp_invalid(shmem)            \
7948+		__XF_PROXY_READ_ATOMIC(shmem->remote.rsp_invalid)
7949+
7950+/* ...individual fields writings */
7951+#define __XF_PROXY_WRITE_cmd_write_idx(shmem, v)    \
7952+		__XF_PROXY_WRITE_ATOMIC(shmem->local.cmd_write_idx, v)
7953+
7954+#define __XF_PROXY_WRITE_cmd_read_idx(shmem, v)     \
7955+		__XF_PROXY_WRITE_ATOMIC(shmem->remote.cmd_read_idx, v)
7956+
7957+#define __XF_PROXY_WRITE_cmd_invalid(shmem, v)     \
7958+		__XF_PROXY_WRITE_ATOMIC(shmem->local.cmd_invalid, v)
7959+
7960+#define __XF_PROXY_WRITE_rsp_read_idx(shmem, v)     \
7961+		__XF_PROXY_WRITE_ATOMIC(shmem->local.rsp_read_idx, v)
7962+
7963+#define __XF_PROXY_WRITE_rsp_write_idx(shmem, v)    \
7964+		__XF_PROXY_WRITE_ATOMIC(shmem->remote.rsp_write_idx, v)
7965+
7966+#define __XF_PROXY_WRITE_rsp_invalid(shmem, v)     \
7967+		__XF_PROXY_WRITE_ATOMIC(shmem->remote.rsp_invalid, v)
7968+
7969+/* ...command buffer accessor */
7970+#define XF_PROXY_COMMAND(proxy, idx)                \
7971+		(&XF_SHMEM_DATA(proxy)->local.command[(idx)])
7972+
7973+/* ...response buffer accessor */
7974+#define XF_PROXY_RESPONSE(proxy, idx)               \
7975+		(&XF_SHMEM_DATA(proxy)->remote.response[(idx)])
7976+
7977+/*******************************************************************************
7978+ * Local proxy data
7979+ ******************************************************************************/
7980+
7981+struct xf_proxy_ipc_data {
7982+	/* ...shared memory data pointer */
7983+	struct xf_shmem_data __iomem     *shmem;
7984+
7985+	/* ...core identifier */
7986+	u32                     core;
7987+
7988+	/* ...IPC registers memory */
7989+	void __iomem           *regs;
7990+};
7991+
7992+/* ...proxy data */
7993+struct xf_proxy {
7994+	/* ...IPC layer data */
7995+	struct xf_proxy_ipc_data ipc;
7996+
7997+	/* ...shared memory status change processing item */
7998+	struct work_struct      work;
7999+
8000+	struct completion	cmd_complete;
8001+	int			is_ready;
8002+	int			is_active;
8003+
8004+	/* ...internal lock */
8005+	spinlock_t              lock;
8006+
8007+	/* ...busy queue (for clients waiting ON NOTIFIcation) */
8008+	wait_queue_head_t       busy;
8009+
8010+	/* ...waiting queue for synchronous proxy operations */
8011+	wait_queue_head_t       wait;
8012+
8013+	/* ...submitted commands queue */
8014+	struct xf_msg_queue     command;
8015+
8016+	/* ...pending responses queue */
8017+	struct xf_msg_queue     response;
8018+
8019+	/* ...global message pool */
8020+	struct xf_message       pool[XF_CFG_MESSAGE_POOL_SIZE];
8021+
8022+	/* ...pointer to first free message in the pool */
8023+	struct xf_message       *free;
8024+
8025+        /* ...auxiliary buffer pool for clients */
8026+	struct xf_pool          *aux;
8027+};
8028+
8029+union icm_header_t {
8030+	struct {
8031+		u32 msg:6;
8032+		u32 sub_msg:6;      // sub_msg will have ICM_MSG
8033+		u32 rsvd:3;     /* reserved */
8034+		u32 intr:1;     /* intr = 1 when sending msg. */
8035+		u32 size:15;    /* =size in bytes (excluding header) */
8036+		u32 ack:1;      /* response message when ack=1 */
8037+	};
8038+	u32 allbits;
8039+};
8040+
8041+struct dsp_ext_msg {
8042+	u32	phys;
8043+	u32	size;
8044+};
8045+
8046+struct dsp_mem_msg {
8047+	u32 ext_msg_phys;
8048+	u32 ext_msg_size;
8049+	u32 scratch_phys;
8050+	u32 scratch_size;
8051+	u32 dsp_config_phys;
8052+	u32 dsp_config_size;
8053+	u32 dsp_board_type;
8054+};
8055+
8056+static inline void xf_lock_init(spinlock_t *lock)
8057+{
8058+	spin_lock_init(lock);
8059+}
8060+
8061+static inline void xf_lock(spinlock_t *lock)
8062+{
8063+	spin_lock(lock);
8064+}
8065+
8066+static inline void xf_unlock(spinlock_t *lock)
8067+{
8068+	spin_unlock(lock);
8069+}
8070+
8071+/* ...init proxy */
8072+int xf_proxy_init(struct xf_proxy *proxy);
8073+
8074+/* ...send message to proxy */
8075+int xf_cmd_send(struct xf_proxy *proxy,
8076+				u32 id,
8077+				u32 opcode,
8078+				void *buffer,
8079+				u32 length);
8080+
8081+/* ...get message from proxy */
8082+struct xf_message *xf_cmd_recv(struct xf_proxy *proxy,
8083+					wait_queue_head_t *wq,
8084+					struct xf_msg_queue *queue,
8085+					int wait);
8086+
8087+struct xf_message*
8088+xf_cmd_recv_timeout(struct xf_proxy *proxy, wait_queue_head_t *wq,
8089+		    struct xf_msg_queue *queue, int wait);
8090+
8091+struct xf_message*
8092+xf_cmd_send_recv(struct xf_proxy *proxy, u32 id, u32 opcode,
8093+		 void *buffer, u32 length);
8094+
8095+struct xf_message*
8096+xf_cmd_send_recv_wq(struct xf_proxy *proxy, u32 id, u32 opcode, void *buffer,
8097+		    u32 length, wait_queue_head_t *wq,
8098+		    struct xf_msg_queue *queue);
8099+
8100+struct xf_message*
8101+xf_cmd_send_recv_complete(struct xf_client *client, struct xf_proxy *proxy,
8102+			  u32 id, u32 opcode, void *buffer, u32 length,
8103+			  struct work_struct *work,
8104+			  struct completion *completion);
8105+
8106+/* ...initialize client pending message queue */
8107+void xf_msg_queue_init(struct xf_msg_queue *queue);
8108+
8109+/* ...return current queue state */
8110+struct xf_message *xf_msg_queue_head(struct xf_msg_queue *queue);
8111+
8112+/* ...return the message back to a pool */
8113+void xf_msg_free(struct xf_proxy *proxy, struct xf_message *m);
8114+
8115+/* ...release all pending messages */
8116+void xf_msg_free_all(struct xf_proxy *proxy, struct xf_msg_queue *queue);
8117+
8118+/* ...wait mailbox callback */
8119+long icm_ack_wait(struct xf_proxy *proxy, u32 msg);
8120+
8121+/* ...shared memory translation - kernel virtual address to shared address */
8122+u32 xf_proxy_b2a(struct xf_proxy *proxy, void *b);
8123+
8124+/* ...shared memory translation - shared address to kernel virtual address */
8125+void *xf_proxy_a2b(struct xf_proxy *proxy, u32 address);
8126+
8127+/* ...mailbox request and free */
8128+int dsp_request_chan(struct xf_proxy *proxy);
8129+void dsp_free_chan(struct xf_proxy *proxy);
8130+
8131+int xf_cmd_send_suspend(struct xf_proxy *proxy);
8132+int xf_cmd_send_resume(struct xf_proxy *proxy);
8133+int xf_cmd_send_pause(struct xf_proxy *proxy);
8134+int xf_cmd_send_pause_release(struct xf_proxy *proxy);
8135+
8136+int xf_cmd_alloc(struct xf_proxy *proxy, void **buffer, u32 length);
8137+int xf_cmd_free(struct xf_proxy *proxy, void *buffer, u32 length);
8138+
8139+int xf_open(struct xf_client *client, struct xf_proxy *proxy,
8140+	    struct xf_handle *handle, const char *id, u32 core,
8141+	    xf_response_cb response);
8142+
8143+int xf_close(struct xf_client *client, struct xf_handle *handle);
8144+
8145+
8146+
8147+/*******************************************************************************
8148+ * Opcode composition
8149+ ******************************************************************************/
8150+
8151+/* ...opcode composition with command/response data tags */
8152+#define __XF_OPCODE(c, r, op)   (((c) << 31) | ((r) << 30) | ((op) & 0x3F))
8153+
8154+/* ...accessors */
8155+#define XF_OPCODE_CDATA(opcode)         ((opcode) & (1 << 31))
8156+#define XF_OPCODE_RDATA(opcode)         ((opcode) & (1 << 30))
8157+#define XF_OPCODE_TYPE(opcode)          ((opcode) & (0x3F))
8158+
8159+/*******************************************************************************
8160+ * Opcode types
8161+ ******************************************************************************/
8162+
8163+/* ...unregister client */
8164+#define XF_UNREGISTER                   __XF_OPCODE(0, 0, 0)
8165+
8166+/* ...register client at proxy */
8167+#define XF_REGISTER                     __XF_OPCODE(1, 0, 1)
8168+
8169+/* ...port routing command */
8170+#define XF_ROUTE                        __XF_OPCODE(1, 0, 2)
8171+
8172+/* ...port unrouting command */
8173+#define XF_UNROUTE                      __XF_OPCODE(1, 0, 3)
8174+
8175+/* ...shared buffer allocation */
8176+#define XF_ALLOC                        __XF_OPCODE(0, 0, 4)
8177+
8178+/* ...shared buffer freeing */
8179+#define XF_FREE                         __XF_OPCODE(0, 0, 5)
8180+
8181+/* ...set component parameters */
8182+#define XF_SET_PARAM                    __XF_OPCODE(1, 0, 6)
8183+
8184+/* ...get component parameters */
8185+#define XF_GET_PARAM                    __XF_OPCODE(1, 1, 7)
8186+
8187+/* ...input buffer reception */
8188+#define XF_EMPTY_THIS_BUFFER            __XF_OPCODE(1, 0, 8)
8189+
8190+/* ...output buffer reception */
8191+#define XF_FILL_THIS_BUFFER             __XF_OPCODE(0, 1, 9)
8192+
8193+/* ...flush specific port */
8194+#define XF_FLUSH                        __XF_OPCODE(0, 0, 10)
8195+
8196+/* ...start component operation */
8197+#define XF_START                        __XF_OPCODE(0, 0, 11)
8198+
8199+/* ...stop component operation */
8200+#define XF_STOP                         __XF_OPCODE(0, 0, 12)
8201+
8202+/* ...pause component operation */
8203+#define XF_PAUSE                        __XF_OPCODE(0, 0, 13)
8204+
8205+/* ...resume component operation */
8206+#define XF_RESUME                       __XF_OPCODE(0, 0, 14)
8207+
8208+/* ...resume component operation */
8209+#define XF_SUSPEND                      __XF_OPCODE(0, 0, 15)
8210+
8211+/* ...load lib for component operation */
8212+#define XF_LOAD_LIB                     __XF_OPCODE(0, 0, 16)
8213+
8214+/* ...unload lib for component operation */
8215+#define XF_UNLOAD_LIB                   __XF_OPCODE(0, 0, 17)
8216+
8217+/* ...component output eos operation */
8218+#define XF_OUTPUT_EOS                   __XF_OPCODE(0, 0, 18)
8219+
8220+#define XF_PAUSE_RELEASE                __XF_OPCODE(0, 0, 19)
8221+/* ...total amount of supported decoder commands */
8222+#define __XF_OP_NUM                     20
8223+
8224+#endif
8225diff --git a/sound/soc/fsl/fsl_dsp_xaf_api.c b/sound/soc/fsl/fsl_dsp_xaf_api.c
8226new file mode 100644
8227index 000000000..9819ad374
8228--- /dev/null
8229+++ b/sound/soc/fsl/fsl_dsp_xaf_api.c
8230@@ -0,0 +1,509 @@
8231+// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
8232+//
8233+// Xtensa Audio Framework API for communication with DSP
8234+//
8235+// Copyright (C) 2017 Cadence Design Systems, Inc.
8236+// Copyright 2018 NXP
8237+
8238+#include "fsl_dsp.h"
8239+#include "fsl_dsp_xaf_api.h"
8240+
8241+/* ...send a command message to component */
8242+int xf_command(struct xf_client *client, struct xf_handle *handle,
8243+	       u32 port, u32 opcode, void *buffer, u32 length)
8244+{
8245+	struct xf_proxy *proxy = handle->proxy;
8246+	struct xf_message  msg;
8247+
8248+	/* ...fill-in message parameters */
8249+	msg.id = __XF_MSG_ID(__XF_AP_CLIENT(0, 0),
8250+				__XF_PORT_SPEC2(handle->id, port));
8251+	msg.id = XF_MSG_AP_FROM_USER(msg.id, client->id);
8252+	msg.opcode = opcode;
8253+	msg.length = length;
8254+	msg.buffer = buffer;
8255+	msg.ret = 0;
8256+
8257+	/* ...execute command synchronously */
8258+	return xf_cmd_send(proxy, msg.id, msg.opcode, msg.buffer, msg.length);
8259+}
8260+
8261+int xaf_comp_set_config(struct xf_client *client, struct xaf_comp *p_comp,
8262+			u32 num_param, void *p_param)
8263+{
8264+	struct xf_handle *p_handle;
8265+	struct xf_message msg;
8266+	struct xf_message *rmsg;
8267+	struct xf_set_param_msg *smsg;
8268+	struct xf_set_param_msg *param = (struct xf_set_param_msg *)p_param;
8269+	struct xf_proxy *proxy;
8270+	u32 i;
8271+
8272+	p_handle = &p_comp->handle;
8273+	proxy = p_handle->proxy;
8274+
8275+	/* ...set persistent stream characteristics */
8276+	smsg = xf_buffer_data(p_handle->aux);
8277+
8278+	for (i = 0; i < num_param; i++) {
8279+		smsg[i].id = param[i].id;
8280+		smsg[i].mixData.value = param[i].mixData.value;
8281+	}
8282+
8283+	/* ...set command parameters */
8284+	msg.id = __XF_MSG_ID(__XF_AP_CLIENT(0, 0),
8285+				__XF_PORT_SPEC2(p_handle->id, 0));
8286+	msg.id = XF_MSG_AP_FROM_USER(msg.id, client->id);
8287+	msg.opcode = XF_SET_PARAM;
8288+	msg.length = sizeof(*smsg) * num_param;
8289+	msg.buffer = smsg;
8290+	msg.ret = 0;
8291+
8292+	/* ...execute command synchronously */
8293+	rmsg = xf_cmd_send_recv_complete(client, proxy, msg.id, msg.opcode,
8294+					 msg.buffer, msg.length, &client->work,
8295+					 &client->compr_complete);
8296+
8297+	if(IS_ERR(rmsg))
8298+		return PTR_ERR(rmsg);
8299+	/* ...save received component global client-id */
8300+	/* TODO: review cleanup */
8301+	/* xf_msg_free(proxy, rmsg);
8302+	 * xf_unlock(&proxy->lock);
8303+	 */
8304+
8305+	/* ...make sure response is expected */
8306+	if ((rmsg->opcode != XF_SET_PARAM) || (rmsg->buffer != smsg)) {
8307+		return -EPIPE;
8308+	}
8309+
8310+	return 0;
8311+}
8312+
8313+int xaf_comp_get_config(struct xf_client *client, struct xaf_comp *p_comp,
8314+			u32 num_param, void *p_param)
8315+{
8316+
8317+	struct xf_handle *p_handle;
8318+	struct xf_message msg;
8319+	struct xf_message *rmsg;
8320+	struct xf_get_param_msg *smsg;
8321+	struct xf_get_param_msg *param = (struct xf_get_param_msg *)p_param;
8322+	struct xf_proxy *proxy;
8323+	u32 i;
8324+
8325+	p_handle = &p_comp->handle;
8326+	proxy = p_handle->proxy;
8327+
8328+	/* ...set persistent stream characteristics */
8329+	smsg = xf_buffer_data(p_handle->aux);
8330+
8331+	for (i = 0; i < num_param; i++)
8332+		smsg[i].id = param[i].id;
8333+
8334+
8335+	msg.id = __XF_MSG_ID(__XF_AP_CLIENT(0, 0),
8336+				__XF_PORT_SPEC2(p_handle->id, 0));
8337+	msg.id = XF_MSG_AP_FROM_USER(msg.id, client->id);
8338+	msg.opcode = XF_GET_PARAM;
8339+	msg.length = sizeof(*smsg) * num_param;
8340+	msg.buffer = smsg;
8341+	msg.ret = 0;
8342+
8343+	/* ...execute command synchronously */
8344+	rmsg = xf_cmd_send_recv_complete(client, proxy, msg.id, msg.opcode,
8345+					 msg.buffer, msg.length, &client->work,
8346+					 &client->compr_complete);
8347+
8348+	/* ...save received component global client-id */
8349+	if(IS_ERR(rmsg))
8350+		return PTR_ERR(rmsg);
8351+
8352+	/* TODO: review cleanup */
8353+	/* xf_msg_free(proxy, rmsg);
8354+	 * xf_unlock(&proxy->lock); */
8355+
8356+	/* ...make sure response is expected */
8357+	if ((rmsg->opcode != (u32)XF_GET_PARAM) || (rmsg->buffer != smsg)) {
8358+		return -EPIPE;
8359+	}
8360+
8361+	for (i = 0; i < num_param; i++)
8362+		param[i].mixData.value = smsg[i].mixData.value;
8363+
8364+	return 0;
8365+}
8366+
8367+int xaf_comp_flush(struct xf_client *client, struct xaf_comp *p_comp)
8368+{
8369+
8370+	struct xf_handle       *p_handle;
8371+	struct xf_proxy        *proxy;
8372+	struct xf_message     msg;
8373+	struct xf_message     *rmsg;
8374+
8375+	p_handle = &p_comp->handle;
8376+	proxy = p_handle->proxy;
8377+
8378+	msg.id = __XF_MSG_ID(__XF_AP_CLIENT(0, 0),
8379+				__XF_PORT_SPEC2(p_handle->id, 0));
8380+	msg.id = XF_MSG_AP_FROM_USER(msg.id, client->id);
8381+	msg.opcode = XF_FLUSH;
8382+	msg.length = 0;
8383+	msg.buffer = NULL;
8384+	msg.ret = 0;
8385+
8386+
8387+	/* ...execute command synchronously */
8388+	rmsg = xf_cmd_send_recv_complete(client, proxy, msg.id, msg.opcode,
8389+					 msg.buffer, msg.length, &client->work,
8390+					 &client->compr_complete);
8391+
8392+	if(IS_ERR(rmsg))
8393+		return PTR_ERR(rmsg);
8394+
8395+	/* ...make sure response is expected */
8396+	if ((rmsg->opcode != (u32)XF_FLUSH) || rmsg->buffer) {
8397+		return -EPIPE;
8398+	}
8399+
8400+	return 0;
8401+}
8402+
8403+int xaf_comp_create(struct xf_client *client, struct xf_proxy *proxy,
8404+		    struct xaf_comp *p_comp, int comp_type)
8405+{
8406+	struct fsl_dsp *dsp_priv = container_of(proxy, struct fsl_dsp, proxy);
8407+	char   lib_path[200];
8408+	char   lib_wrap_path[200];
8409+	struct xf_handle *p_handle;
8410+	struct xf_buffer *buf;
8411+	int    ret = 0, size;
8412+	bool   loadlib = true;
8413+	bool   request_inbuf = true;
8414+
8415+	memset((void *)p_comp, 0, sizeof(struct xaf_comp));
8416+
8417+	strcpy(lib_path, "/usr/lib/imx-mm/audio-codec/dsp/");
8418+	strcpy(lib_wrap_path, "/usr/lib/imx-mm/audio-codec/dsp/");
8419+
8420+	p_handle = &p_comp->handle;
8421+
8422+	p_comp->comp_type = comp_type;
8423+
8424+	/* No need to load library for PCM */
8425+	if (comp_type == RENDER_ESAI || comp_type == RENDER_SAI || comp_type == CODEC_PCM_DEC)
8426+		loadlib = false;
8427+
8428+	/* Need to allocate in buffer for PCM */
8429+	if (comp_type == RENDER_ESAI || comp_type == RENDER_SAI)
8430+		request_inbuf = false;
8431+
8432+	if (loadlib) {
8433+		p_comp->codec_lib.filename      = lib_path;
8434+		p_comp->codec_wrap_lib.filename = lib_wrap_path;
8435+		p_comp->codec_lib.lib_type      = DSP_CODEC_LIB;
8436+	}
8437+
8438+	size = INBUF_SIZE;
8439+	switch (comp_type) {
8440+	case CODEC_PCM_DEC:
8441+		p_comp->dec_id = "audio-decoder/pcm";
8442+		if (dsp_priv->dsp_is_lpa)
8443+			size = INBUF_SIZE_LPA_PCM;
8444+		break;
8445+	case CODEC_MP3_DEC:
8446+		p_comp->dec_id = "audio-decoder/mp3";
8447+		strcat(lib_path, "lib_dsp_mp3_dec.so");
8448+		if (dsp_priv->dsp_is_lpa)
8449+			size = INBUF_SIZE_LPA;
8450+		break;
8451+	case CODEC_AAC_DEC:
8452+		p_comp->dec_id = "audio-decoder/aac";
8453+		strcat(lib_path, "lib_dsp_aac_dec.so");
8454+		break;
8455+	case RENDER_ESAI:
8456+		p_comp->dec_id = "renderer/esai";
8457+		break;
8458+	case RENDER_SAI:
8459+		p_comp->dec_id = "renderer/sai";
8460+		break;
8461+
8462+	default:
8463+		return -EINVAL;
8464+		break;
8465+	}
8466+
8467+	/* ...create decoder component instance (select core-0) */
8468+	ret = xf_open(client, proxy, p_handle, p_comp->dec_id, 0, NULL);
8469+	if (ret) {
8470+		dev_err(dsp_priv->dev, "create (%s) component error: %d\n",
8471+			p_comp->dec_id, ret);
8472+		return ret;
8473+	}
8474+
8475+	if (loadlib) {
8476+		strcat(lib_wrap_path, "lib_dsp_codec_wrap.so");
8477+		p_comp->codec_wrap_lib.lib_type = DSP_CODEC_WRAP_LIB;
8478+
8479+		/* ...load codec wrapper lib */
8480+		ret = xf_load_lib(client, p_handle, &p_comp->codec_wrap_lib);
8481+		if (ret) {
8482+			dev_err(dsp_priv->dev, "load codec wrap lib error\n");
8483+			goto err_wrap_load;
8484+		}
8485+
8486+		/* ...load codec lib */
8487+		ret = xf_load_lib(client, p_handle, &p_comp->codec_lib);
8488+		if (ret) {
8489+			dev_err(dsp_priv->dev, "load codec lib error\n");
8490+			goto err_codec_load;
8491+		}
8492+	}
8493+
8494+	if (request_inbuf) {
8495+		/* ...allocate input buffer */
8496+		ret = xf_pool_alloc(client, proxy, 1, size,
8497+				    XF_POOL_INPUT, &p_comp->inpool);
8498+		if (ret) {
8499+			dev_err(dsp_priv->dev, "alloc input buf error\n");
8500+			goto err_pool_alloc;
8501+		}
8502+
8503+		/* ...initialize input buffer pointer */
8504+		buf = xf_buffer_get(p_comp->inpool);
8505+		p_comp->inptr = xf_buffer_data(buf);
8506+	}
8507+
8508+	p_comp->active = true;
8509+
8510+	return ret;
8511+
8512+err_pool_alloc:
8513+	xf_unload_lib(client, p_handle, &p_comp->codec_lib);
8514+err_codec_load:
8515+	xf_unload_lib(client, p_handle, &p_comp->codec_wrap_lib);
8516+err_wrap_load:
8517+	xf_close(client, p_handle);
8518+
8519+	return ret;
8520+}
8521+
8522+int xaf_comp_delete(struct xf_client *client, struct xaf_comp *p_comp)
8523+{
8524+
8525+	struct xf_handle *p_handle;
8526+	bool   loadlib = true;
8527+	u32 ret = 0;
8528+
8529+	if (!p_comp->active)
8530+		return ret;
8531+
8532+	/* mark component as unusable from this point */
8533+	p_comp->active = false;
8534+
8535+	if (p_comp->comp_type == RENDER_ESAI || p_comp->comp_type == RENDER_SAI)
8536+		loadlib = false;
8537+
8538+	p_handle = &p_comp->handle;
8539+
8540+	if (loadlib) {
8541+		/* ...unload codec wrapper library */
8542+		xf_unload_lib(client, p_handle, &p_comp->codec_wrap_lib);
8543+
8544+		/* ...unload codec library */
8545+		xf_unload_lib(client, p_handle, &p_comp->codec_lib);
8546+
8547+		xf_pool_free(client, p_comp->inpool);
8548+	}
8549+
8550+	/* ...delete component */
8551+	xf_close(client, p_handle);
8552+
8553+	return ret;
8554+}
8555+
8556+int xaf_comp_process(struct xf_client *client, struct xaf_comp *p_comp, void *p_buf, u32 length, u32 flag)
8557+{
8558+	struct xf_handle *p_handle;
8559+	u32 ret = 0;
8560+
8561+	p_handle = &p_comp->handle;
8562+
8563+	switch (flag) {
8564+	case XF_FILL_THIS_BUFFER:
8565+		/* ...send message to component output port (port-id=1) */
8566+		ret = xf_command(client, p_handle, 1, XF_FILL_THIS_BUFFER,
8567+				 p_buf, length);
8568+		break;
8569+	case XF_EMPTY_THIS_BUFFER:
8570+		/* ...send message to component input port (port-id=0) */
8571+		ret = xf_command(client, p_handle, 0, XF_EMPTY_THIS_BUFFER,
8572+				 p_buf, length);
8573+		break;
8574+	default:
8575+		break;
8576+	}
8577+
8578+	return ret;
8579+}
8580+
8581+/* ...port binding function */
8582+int xf_route(struct xf_client *client, struct xf_handle *src, u32 src_port,
8583+	     struct xf_handle *dst, u32 dst_port, u32 num, u32 size, u32 align)
8584+{
8585+	struct xf_proxy *proxy = src->proxy;
8586+	struct xf_buffer *b;
8587+	struct xf_route_port_msg *m;
8588+	struct xf_message msg;
8589+	struct xf_message *rmsg;
8590+
8591+	/* ...sanity checks - proxy pointers are same */
8592+	if (proxy != dst->proxy)
8593+		return -EINVAL;
8594+
8595+	/* ...buffer data is sane */
8596+	if (!(num && size && xf_is_power_of_two(align)))
8597+		return -EINVAL;
8598+
8599+	/* ...get control buffer */
8600+	if ((b = xf_buffer_get(proxy->aux)) == NULL)
8601+		return -EBUSY;
8602+
8603+	/* ...get message buffer */
8604+	m = xf_buffer_data(b);
8605+
8606+	/* ...fill-in message parameters */
8607+	m->src = __XF_PORT_SPEC2(src->id, src_port);
8608+	m->dst = __XF_PORT_SPEC2(dst->id, dst_port);
8609+	m->alloc_number = num;
8610+	m->alloc_size = size;
8611+	m->alloc_align = align;
8612+
8613+	/* ...set command parameters */
8614+	msg.id = __XF_MSG_ID(__XF_AP_PROXY(0),
8615+			     __XF_PORT_SPEC2(src->id, src_port));
8616+	msg.id = XF_MSG_AP_FROM_USER(msg.id, client->id);
8617+	msg.opcode = XF_ROUTE;
8618+	msg.length = sizeof(*m);
8619+	msg.buffer = m;
8620+	msg.ret = 0;
8621+
8622+	/* ...execute command synchronously */
8623+	rmsg = xf_cmd_send_recv_complete(client, proxy, msg.id, msg.opcode,
8624+					 msg.buffer, msg.length, &client->work,
8625+					 &client->compr_complete);
8626+	if(IS_ERR(rmsg))
8627+		return PTR_ERR(rmsg);
8628+
8629+	/* ...save received component global client-id */
8630+	/* TODO: review cleanup */
8631+	/* xf_msg_free(proxy, rmsg);
8632+	 * xf_unlock(&proxy->lock); */
8633+
8634+
8635+        /* ...synchronously execute command on remote DSP */
8636+	/* XF_CHK_API(xf_proxy_cmd_exec(proxy, &msg)); */
8637+
8638+	/* ...return buffer to proxy */
8639+	xf_buffer_put(b);
8640+
8641+        /* ...check result is successful */
8642+	/* XF_CHK_ERR(msg.opcode == XF_ROUTE, -ENOMEM); */
8643+
8644+	return 0;
8645+}
8646+
8647+/* ...port unbinding function */
8648+int xf_unroute(struct xf_client *client, struct xf_handle *src, u32 src_port)
8649+{
8650+	struct xf_proxy        *proxy = src->proxy;
8651+	struct xf_buffer       *b;
8652+	struct xf_unroute_port_msg  *m;
8653+	struct xf_message      msg;
8654+	struct xf_message     *rmsg;
8655+	int                  r = 0;
8656+
8657+	/* ...get control buffer */
8658+	if((b = xf_buffer_get(proxy->aux)) == NULL)
8659+		return -EBUSY;
8660+
8661+	/* ...get message buffer */
8662+	m = xf_buffer_data(b);
8663+
8664+	/* ...fill-in message parameters */
8665+	m->src = __XF_PORT_SPEC2(src->id, src_port);
8666+
8667+	/* ...set command parameters */
8668+	msg.id = __XF_MSG_ID(__XF_AP_PROXY(0),
8669+			__XF_PORT_SPEC2(src->id, src_port));
8670+	msg.id = XF_MSG_AP_FROM_USER(msg.id, client->id);
8671+	msg.opcode = XF_UNROUTE;
8672+	msg.length = sizeof(*m);
8673+	msg.buffer = m;
8674+	msg.ret = 0;
8675+
8676+	/* ...execute command synchronously */
8677+	rmsg = xf_cmd_send_recv_complete(client, proxy, msg.id, msg.opcode,
8678+					 msg.buffer, msg.length, &client->work,
8679+					 &client->compr_complete);
8680+	if (IS_ERR(rmsg))
8681+		return PTR_ERR(rmsg);
8682+	/* ...save received component global client-id */
8683+
8684+	/*TODO: review cleanup */
8685+	/* xf_msg_free(proxy, rmsg); */
8686+	/* xf_unlock(&proxy->lock); */
8687+
8688+        /* ...return buffer to proxy */
8689+        xf_buffer_put(b);
8690+
8691+        return r;
8692+}
8693+
8694+int xaf_connect(struct xf_client *client,
8695+		struct xaf_comp *p_src,
8696+		struct xaf_comp *p_dest,
8697+		u32 num_buf,
8698+		u32 buf_length)
8699+{
8700+	/* ...connect p_src output port with p_dest input port */
8701+	return xf_route(client, &p_src->handle, 1, &p_dest->handle, 0,
8702+			num_buf, buf_length, 8);
8703+}
8704+
8705+int xaf_disconnect(struct xf_client *client, struct xaf_comp *p_comp)
8706+{
8707+	/* ...disconnect p_src output port with p_dest input port */
8708+	return xf_unroute(client, &p_comp->handle, 0);
8709+
8710+}
8711+
8712+int xaf_comp_add(struct xaf_pipeline *p_pipe, struct xaf_comp *p_comp)
8713+{
8714+	int ret = 0;
8715+
8716+	p_comp->next = p_pipe->comp_chain;
8717+	p_comp->pipeline = p_pipe;
8718+	p_pipe->comp_chain = p_comp;
8719+
8720+	return ret;
8721+}
8722+
8723+int xaf_pipeline_create(struct xaf_pipeline *p_pipe)
8724+{
8725+	int ret = 0;
8726+
8727+	memset(p_pipe, 0, sizeof(struct xaf_pipeline));
8728+
8729+	return ret;
8730+}
8731+
8732+int xaf_pipeline_delete(struct xaf_pipeline *p_pipe)
8733+{
8734+	int ret = 0;
8735+
8736+	memset(p_pipe, 0, sizeof(struct xaf_pipeline));
8737+
8738+	return ret;
8739+}
8740diff --git a/sound/soc/fsl/fsl_dsp_xaf_api.h b/sound/soc/fsl/fsl_dsp_xaf_api.h
8741new file mode 100644
8742index 000000000..7b2dfa489
8743--- /dev/null
8744+++ b/sound/soc/fsl/fsl_dsp_xaf_api.h
8745@@ -0,0 +1,178 @@
8746+/* SPDX-License-Identifier: (GPL-2.0+ OR MIT)*/
8747+/*
8748+ * Xtensa Audio Framework API for communication with DSP
8749+ *
8750+ * Copyright (C) 2017 Cadence Design Systems, Inc.
8751+ * Copyright 2018 NXP
8752+ */
8753+#ifndef FSL_DSP_XAF_API_H
8754+#define FSL_DSP_XAF_API_H
8755+
8756+#include "fsl_dsp_library_load.h"
8757+
8758+/* ...size of auxiliary pool for communication with DSP */
8759+#define XA_AUX_POOL_SIZE	32
8760+
8761+/* ...length of auxiliary pool messages */
8762+#define XA_AUX_POOL_MSG_LENGTH	128
8763+
8764+/* ...number of max input buffers */
8765+#define INBUF_SIZE	4096
8766+/* ...buffer size of the buffer shared between A core and DSP. Use large */
8767+/* ...to let A core suspend longer time to save power.*/
8768+#define INBUF_SIZE_LPA	(128*1024)
8769+/* ...ping-pong buffer locate in DRAM for PCM LPA. */
8770+#define INBUF_SIZE_LPA_PCM	(8*1024*1024)
8771+#define OUTBUF_SIZE	16384
8772+
8773+struct xaf_pipeline;
8774+
8775+struct xaf_info_s {
8776+	u32 opcode;
8777+	void *buf;
8778+	u32 length;
8779+	u32 ret;
8780+};
8781+
8782+struct xaf_comp {
8783+	struct xaf_comp *next;
8784+
8785+	struct xaf_pipeline *pipeline;
8786+	struct xf_handle handle;
8787+
8788+	const char *dec_id;
8789+	int comp_type;
8790+
8791+	struct xf_pool *inpool;
8792+	struct xf_pool *outpool;
8793+	void *inptr;
8794+	void *outptr;
8795+
8796+	struct lib_info codec_lib;
8797+	struct lib_info codec_wrap_lib;
8798+
8799+	int active; /* component fully initialized */
8800+};
8801+
8802+struct xaf_pipeline {
8803+	struct xaf_comp *comp_chain;
8804+
8805+	u32 input_eos;
8806+	u32 output_eos;
8807+};
8808+
8809+int xaf_comp_create(struct xf_client *client, struct xf_proxy *p_proxy,
8810+		    struct xaf_comp *p_comp, int comp_type);
8811+int xaf_comp_delete(struct xf_client *client, struct xaf_comp *p_comp);
8812+int xaf_comp_flush(struct xf_client *client, struct xaf_comp *p_comp);
8813+
8814+int xaf_comp_set_config(struct xf_client *client,struct xaf_comp *p_comp,
8815+			u32 num_param, void *p_param);
8816+int xaf_comp_get_config(struct xf_client *client,struct xaf_comp *p_comp,
8817+			u32 num_param, void *p_param);
8818+
8819+int xaf_comp_add(struct xaf_pipeline *p_pipe, struct xaf_comp *p_comp);
8820+int xaf_comp_process(struct xf_client *client, struct xaf_comp *p_comp,
8821+		     void *p_buf, u32 length, u32 flag);
8822+int xaf_comp_get_status(struct xaf_comp *p_comp, struct xaf_info_s *p_info);
8823+int xaf_comp_get_msg_count(struct xaf_comp *p_comp);
8824+
8825+int xaf_connect(struct xf_client *client,struct xaf_comp *p_src,
8826+		struct xaf_comp *p_dest, u32 num_buf, u32 buf_length);
8827+int xaf_disconnect(struct xf_client *client,struct xaf_comp *p_comp);
8828+
8829+int xaf_pipeline_create(struct xaf_pipeline *p_pipe);
8830+int xaf_pipeline_delete(struct xaf_pipeline *p_pipe);
8831+
8832+int xaf_pipeline_send_eos(struct xaf_pipeline *p_pipe);
8833+
8834+/* ...port routing command */
8835+struct __attribute__((__packed__)) xf_route_port_msg {
8836+	/* ...source port specification */
8837+	u32 src;
8838+	/* ...destination port specification */
8839+	u32 dst;
8840+	/* ...number of buffers to allocate */
8841+	u32 alloc_number;
8842+	/* ...length of buffer to allocate */
8843+	u32 alloc_size;
8844+	/* ...alignment restriction for a buffer */
8845+	u32 alloc_align;
8846+};
8847+
8848+/* ...port unrouting command */
8849+struct __attribute__((__packed__)) xf_unroute_port_msg {
8850+	/* ...source port specification */
8851+	u32 src;
8852+	/* ...destination port specification */
8853+	u32 dst;
8854+};
8855+
8856+/* ...check if non-zero value is a power-of-two */
8857+#define xf_is_power_of_two(v)       (((v) & ((v) - 1)) == 0)
8858+
8859+
8860+/*******************************************************************************
8861+ * bascial message
8862+ ******************************************************************************/
8863+typedef union DATA {
8864+	u32                 value;
8865+
8866+	struct {
8867+		u32 size;
8868+		u32 channel_table[10];
8869+	} chan_map_tab;
8870+
8871+	struct {
8872+		u32 samplerate;
8873+		u32 width;
8874+		u32 depth;
8875+		u32 channels;
8876+		u32 endian;
8877+		u32 interleave;
8878+		u32 layout[12];
8879+		u32 chan_pos_set;  // indicate if channel position is set outside or use codec default
8880+	} outputFormat;
8881+} data_t;
8882+
8883+/* ...component initialization parameter */
8884+struct __attribute__((__packed__)) xf_set_param_msg {
8885+	/* ...index of parameter passed to SET_CONFIG_PARAM call */
8886+	u32 id;
8887+	/* ...value of parameter */
8888+	data_t mixData;
8889+};
8890+
8891+/* ...message body (command/response) */
8892+struct __attribute__((__packed__)) xf_get_param_msg {
8893+	/* ...array of parameters requested */
8894+	u32 id;
8895+	/* ...array of parameters values */
8896+	data_t mixData;
8897+};
8898+
8899+/* ...renderer-specific configuration parameters */
8900+enum xa_config_param_renderer {
8901+	XA_RENDERER_CONFIG_PARAM_CB             = 0,
8902+	XA_RENDERER_CONFIG_PARAM_STATE          = 1,
8903+	XA_RENDERER_CONFIG_PARAM_PCM_WIDTH      = 2,
8904+	XA_RENDERER_CONFIG_PARAM_CHANNELS       = 3,
8905+	XA_RENDERER_CONFIG_PARAM_SAMPLE_RATE    = 4,
8906+	XA_RENDERER_CONFIG_PARAM_FRAME_SIZE     = 5,
8907+	XA_RENDERER_CONFIG_PARAM_CONSUMED       = 6,
8908+	XA_RENDERER_CONFIG_PARAM_NUM            = 7,
8909+};
8910+
8911+/* pcm codec configuration parameters */
8912+enum xa_config_param_pcm {
8913+	XA_PCM_CONFIG_PARAM_SAMPLE_RATE         = 0, /* not supported */
8914+	XA_PCM_CONFIG_PARAM_IN_PCM_WIDTH        = 1,
8915+	XA_PCM_CONFIG_PARAM_IN_CHANNELS         = 2, /* not supported */
8916+	XA_PCM_CONFIG_PARAM_OUT_PCM_WIDTH       = 3, /* not supported */
8917+	XA_PCM_CONFIG_PARAM_OUT_CHANNELS        = 4, /* not supported */
8918+	XA_PCM_CONFIG_PARAM_CHANROUTING         = 5, /* not supported */
8919+	XA_PCM_CONFIG_PARAM_FUNC_PRINT          = 13, /* not supported */
8920+	XA_PCM_CONFIG_PARAM_NUM                 = 14, /* not supported */
8921+};
8922+
8923+#endif /* FSL_DSP_XAF_API_H */
8924diff --git a/sound/soc/fsl/fsl_easrc.c b/sound/soc/fsl/fsl_easrc.c
8925index 60951a8aa..8e50d6654 100644
8926--- a/sound/soc/fsl/fsl_easrc.c
8927+++ b/sound/soc/fsl/fsl_easrc.c
8928@@ -1749,6 +1749,8 @@ static const struct regmap_config fsl_easrc_regmap_config = {
8929 	.cache_type = REGCACHE_RBTREE,
8930 };
8931
8932+#include "fsl_easrc_m2m.c"
8933+
8934 #ifdef DEBUG
8935 static void fsl_easrc_dump_firmware(struct fsl_asrc *easrc)
8936 {
8937@@ -1874,6 +1876,7 @@ static int fsl_easrc_probe(struct platform_device *pdev)
8938 	struct device_node *np;
8939 	void __iomem *regs;
8940 	int ret, irq;
8941+	int width;
8942
8943 	easrc = devm_kzalloc(dev, sizeof(*easrc), GFP_KERNEL);
8944 	if (!easrc)
8945@@ -1896,7 +1899,7 @@ static int fsl_easrc_probe(struct platform_device *pdev)
8946
8947 	easrc->paddr = res->start;
8948
8949-	easrc->regmap = devm_regmap_init_mmio_clk(dev, "mem", regs,
8950+	easrc->regmap = devm_regmap_init_mmio_clk(dev, NULL, regs,
8951 						  &fsl_easrc_regmap_config);
8952 	if (IS_ERR(easrc->regmap)) {
8953 		dev_err(dev, "failed to init regmap");
8954@@ -1941,8 +1944,25 @@ static int fsl_easrc_probe(struct platform_device *pdev)
8955
8956 	ret = of_property_read_u32(np, "fsl,asrc-format", &easrc->asrc_format);
8957 	if (ret) {
8958-		dev_err(dev, "failed to asrc format\n");
8959-		return ret;
8960+		ret = of_property_read_u32(np, "fsl,asrc-width", &width);
8961+		if (ret) {
8962+			dev_err(&pdev->dev, "failed to decide output format\n");
8963+			return ret;
8964+		}
8965+
8966+		switch (width) {
8967+		case 16:
8968+			easrc->asrc_format = SNDRV_PCM_FORMAT_S16_LE;
8969+			break;
8970+		case 24:
8971+			easrc->asrc_format = SNDRV_PCM_FORMAT_S24_LE;
8972+			break;
8973+		default:
8974+			dev_warn(&pdev->dev,
8975+				 "unsupported width, use default S24_LE\n");
8976+			easrc->asrc_format = SNDRV_PCM_FORMAT_S24_LE;
8977+			break;
8978+		}
8979 	}
8980
8981 	if (!(FSL_EASRC_FORMATS & (1ULL << easrc->asrc_format))) {
8982@@ -1950,7 +1970,7 @@ static int fsl_easrc_probe(struct platform_device *pdev)
8983 		easrc->asrc_format = SNDRV_PCM_FORMAT_S24_LE;
8984 	}
8985
8986-	ret = of_property_read_string(np, "firmware-name",
8987+	ret = of_property_read_string(np, "fsl,easrc-ram-script-name",
8988 				      &easrc_priv->fw_name);
8989 	if (ret) {
8990 		dev_err(dev, "failed to get firmware name\n");
8991@@ -1978,6 +1998,12 @@ static int fsl_easrc_probe(struct platform_device *pdev)
8992 		return ret;
8993 	}
8994
8995+	ret = fsl_easrc_m2m_init(easrc);
8996+	if (ret) {
8997+		dev_err(&pdev->dev, "failed to init m2m device %d\n", ret);
8998+		return ret;
8999+	}
9000+
9001 	return 0;
9002 }
9003
9004@@ -2085,12 +2111,38 @@ static __maybe_unused int fsl_easrc_runtime_resume(struct device *dev)
9005 	return ret;
9006 }
9007
9008+#ifdef CONFIG_PM_SLEEP
9009+static int fsl_easrc_suspend(struct device *dev)
9010+{
9011+	struct fsl_asrc *easrc = dev_get_drvdata(dev);
9012+	int ret;
9013+
9014+	fsl_easrc_m2m_suspend(easrc);
9015+
9016+	ret = pm_runtime_force_suspend(dev);
9017+
9018+	return ret;
9019+}
9020+
9021+static int fsl_easrc_resume(struct device *dev)
9022+{
9023+	struct fsl_asrc *easrc = dev_get_drvdata(dev);
9024+	int ret;
9025+
9026+	ret = pm_runtime_force_resume(dev);
9027+
9028+	fsl_easrc_m2m_resume(easrc);
9029+
9030+	return ret;
9031+}
9032+#endif /*CONFIG_PM_SLEEP*/
9033+
9034 static const struct dev_pm_ops fsl_easrc_pm_ops = {
9035 	SET_RUNTIME_PM_OPS(fsl_easrc_runtime_suspend,
9036 			   fsl_easrc_runtime_resume,
9037 			   NULL)
9038-	SET_SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend,
9039-				pm_runtime_force_resume)
9040+	SET_SYSTEM_SLEEP_PM_OPS(fsl_easrc_suspend,
9041+				fsl_easrc_resume)
9042 };
9043
9044 static struct platform_driver fsl_easrc_driver = {
9045diff --git a/sound/soc/fsl/fsl_easrc_m2m.c b/sound/soc/fsl/fsl_easrc_m2m.c
9046new file mode 100755
9047index 000000000..7a5d6a18d
9048--- /dev/null
9049+++ b/sound/soc/fsl/fsl_easrc_m2m.c
9050@@ -0,0 +1,978 @@
9051+// SPDX-License-Identifier: GPL-2.0
9052+// Copyright 2019 NXP
9053+
9054+struct fsl_easrc_m2m {
9055+	struct fsl_asrc *asrc;
9056+	struct fsl_asrc_pair *ctx;
9057+	struct completion complete[2];
9058+	struct dma_block dma_block[2];
9059+	unsigned int ctx_hold;
9060+	unsigned int easrc_active;
9061+	unsigned int first_convert;
9062+	unsigned int sg_nodes[2];
9063+	unsigned int in_filled_len;
9064+	struct scatterlist sg[2][9];
9065+	struct dma_async_tx_descriptor *desc[2];
9066+	spinlock_t lock;  /* protect mem resource */
9067+};
9068+
9069+void fsl_easrc_get_status(struct fsl_asrc_pair *ctx,
9070+			  struct asrc_status_flags *flags)
9071+{
9072+	flags->overload_error = 0;
9073+}
9074+
9075+#define mxc_easrc_dma_umap_in(dev, m2m) \
9076+	dma_unmap_sg(dev, m2m->sg[IN], m2m->sg_nodes[IN], \
9077+					DMA_MEM_TO_DEV) \
9078+
9079+#define mxc_easrc_dma_umap_out(dev, m2m) \
9080+	dma_unmap_sg(dev, m2m->sg[OUT], m2m->sg_nodes[OUT], \
9081+					DMA_DEV_TO_MEM) \
9082+
9083+#define EASRC_xPUT_DMA_CALLBACK(dir) \
9084+	((dir == IN) ? fsl_easrc_input_dma_callback \
9085+			: fsl_easrc_output_dma_callback)
9086+
9087+#define DIR_STR(dir) dir == IN ? "in" : "out"
9088+
9089+static void fsl_easrc_input_dma_callback(void *data)
9090+{
9091+	struct fsl_easrc_m2m *m2m = (struct fsl_easrc_m2m *)data;
9092+
9093+	complete(&m2m->complete[IN]);
9094+}
9095+
9096+static void fsl_easrc_output_dma_callback(void *data)
9097+{
9098+	struct fsl_easrc_m2m *m2m = (struct fsl_easrc_m2m *)data;
9099+
9100+	complete(&m2m->complete[OUT]);
9101+}
9102+
9103+static int fsl_allocate_dma_buf(struct fsl_easrc_m2m *m2m)
9104+{
9105+	struct dma_block *input = &m2m->dma_block[IN];
9106+	struct dma_block *output = &m2m->dma_block[OUT];
9107+
9108+	input->dma_vaddr = kzalloc(input->length, GFP_KERNEL);
9109+	if (!input->dma_vaddr)
9110+		return -ENOMEM;
9111+
9112+	output->dma_vaddr = kzalloc(output->length, GFP_KERNEL);
9113+	if (!output->dma_vaddr)
9114+		goto alloc_fail;
9115+
9116+	return 0;
9117+
9118+alloc_fail:
9119+	kfree(input->dma_vaddr);
9120+	input->dma_vaddr = NULL;
9121+	return -ENOMEM;
9122+}
9123+
9124+static int fsl_easrc_dmaconfig(struct fsl_easrc_m2m *m2m,
9125+			       struct dma_chan *chan,
9126+			       u32 dma_addr, void *buf_addr, u32 buf_len,
9127+			       bool dir, int bits)
9128+{
9129+	struct dma_async_tx_descriptor *desc = m2m->desc[dir];
9130+	struct fsl_asrc *asrc = m2m->asrc;
9131+	struct fsl_asrc_pair *ctx = m2m->ctx;
9132+	struct fsl_easrc_ctx_priv *ctx_priv = ctx->private;
9133+	struct device *dev = &asrc->pdev->dev;
9134+	unsigned int sg_nent = m2m->sg_nodes[dir];
9135+	struct scatterlist *sg = m2m->sg[dir];
9136+	struct dma_slave_config slave_config;
9137+	enum dma_slave_buswidth buswidth;
9138+	int ret, i;
9139+
9140+	switch (bits) {
9141+	case 16:
9142+		buswidth = DMA_SLAVE_BUSWIDTH_2_BYTES;
9143+		break;
9144+	case 24:
9145+		buswidth = DMA_SLAVE_BUSWIDTH_3_BYTES;
9146+		break;
9147+	default:
9148+		buswidth = DMA_SLAVE_BUSWIDTH_4_BYTES;
9149+	}
9150+
9151+	memset(&slave_config, 0, sizeof(slave_config));
9152+	if (dir == IN) {
9153+		slave_config.direction = DMA_MEM_TO_DEV;
9154+		slave_config.dst_addr = dma_addr;
9155+		slave_config.dst_addr_width = buswidth;
9156+		slave_config.dst_maxburst =
9157+			ctx_priv->in_params.fifo_wtmk * ctx->channels;
9158+	} else {
9159+		slave_config.direction = DMA_DEV_TO_MEM;
9160+		slave_config.src_addr = dma_addr;
9161+		slave_config.src_addr_width = buswidth;
9162+		slave_config.src_maxburst =
9163+			ctx_priv->out_params.fifo_wtmk * ctx->channels;
9164+	}
9165+
9166+	ret = dmaengine_slave_config(chan, &slave_config);
9167+	if (ret) {
9168+		dev_err(dev, "failed to config dmaengine for %sput task: %d\n",
9169+			DIR_STR(dir), ret);
9170+		return -EINVAL;
9171+	}
9172+
9173+	sg_init_table(sg, sg_nent);
9174+	switch (sg_nent) {
9175+	case 1:
9176+		sg_init_one(sg, buf_addr, buf_len);
9177+		break;
9178+	case 2:
9179+	case 3:
9180+	case 4:
9181+	case 5:
9182+	case 6:
9183+	case 7:
9184+	case 8:
9185+	case 9:
9186+		for (i = 0; i < (sg_nent - 1); i++)
9187+			sg_set_buf(&sg[i],
9188+				   buf_addr + i * m2m->dma_block[dir].max_buf_size,
9189+				   m2m->dma_block[dir].max_buf_size);
9190+
9191+		sg_set_buf(&sg[i],
9192+			   buf_addr + i * m2m->dma_block[dir].max_buf_size,
9193+			   buf_len - i * m2m->dma_block[dir].max_buf_size);
9194+		break;
9195+	default:
9196+		dev_err(dev, "invalid input DMA nodes number: %d\n", sg_nent);
9197+		return -EINVAL;
9198+	}
9199+
9200+	ret = dma_map_sg(dev, sg, sg_nent, slave_config.direction);
9201+	if (ret != sg_nent) {
9202+		dev_err(dev, "failed to map DMA sg for %sput task\n",
9203+			DIR_STR(dir));
9204+		return -EINVAL;
9205+	}
9206+
9207+	desc = dmaengine_prep_slave_sg(chan, sg, sg_nent,
9208+				       slave_config.direction,
9209+				       DMA_PREP_INTERRUPT);
9210+	if (!desc) {
9211+		dev_err(dev, "failed to prepare dmaengine for %sput task\n",
9212+			DIR_STR(dir));
9213+		return -EINVAL;
9214+	}
9215+
9216+	m2m->desc[dir] = desc;
9217+	m2m->desc[dir]->callback = EASRC_xPUT_DMA_CALLBACK(dir);
9218+
9219+	desc->callback = EASRC_xPUT_DMA_CALLBACK(dir);
9220+	desc->callback_param = m2m;
9221+
9222+	return 0;
9223+}
9224+
9225+static long fsl_easrc_calc_outbuf_len(struct fsl_easrc_m2m *m2m,
9226+				      struct asrc_convert_buffer *pbuf)
9227+{
9228+	struct fsl_asrc_pair *ctx = m2m->ctx;
9229+	struct fsl_easrc_ctx_priv *ctx_priv = ctx->private;
9230+	unsigned int out_length;
9231+	unsigned int in_width, out_width;
9232+	unsigned int channels = ctx->channels;
9233+	unsigned int in_samples, out_samples;
9234+
9235+	in_width = snd_pcm_format_physical_width(ctx_priv->in_params.sample_format) / 8;
9236+	out_width = snd_pcm_format_physical_width(ctx_priv->out_params.sample_format) / 8;
9237+
9238+	m2m->in_filled_len += pbuf->input_buffer_length;
9239+	if (m2m->in_filled_len <= ctx_priv->in_filled_sample * in_width * channels) {
9240+		out_length = 0;
9241+	} else {
9242+		in_samples = m2m->in_filled_len / (in_width * channels) - ctx_priv->in_filled_sample;
9243+		out_samples = ctx_priv->out_params.sample_rate * in_samples /
9244+				ctx_priv->in_params.sample_rate;
9245+		out_length = out_samples * out_width * channels;
9246+		m2m->in_filled_len = ctx_priv->in_filled_sample * in_width * channels;
9247+	}
9248+
9249+	return out_length;
9250+}
9251+
9252+static long fsl_easrc_prepare_io_buffer(struct fsl_easrc_m2m *m2m,
9253+					struct asrc_convert_buffer *buf,
9254+					bool dir)
9255+{
9256+	struct fsl_asrc *asrc = m2m->asrc;
9257+	struct device *dev = &asrc->pdev->dev;
9258+	struct fsl_asrc_pair *ctx = m2m->ctx;
9259+	struct fsl_easrc_ctx_priv *ctx_priv = ctx->private;
9260+	struct dma_chan *dma_chan = ctx->dma_chan[dir];
9261+	unsigned int *dma_len = &m2m->dma_block[dir].length;
9262+	unsigned int *sg_nodes = &m2m->sg_nodes[dir];
9263+	void *dma_vaddr = m2m->dma_block[dir].dma_vaddr;
9264+	enum asrc_pair_index index = m2m->ctx->index;
9265+	unsigned int buf_len, bits;
9266+	u32 fifo_addr;
9267+	void __user *buf_vaddr;
9268+
9269+	if (dir == IN) {
9270+		buf_vaddr = (void __user *)buf->input_buffer_vaddr;
9271+		buf_len = buf->input_buffer_length;
9272+		bits = snd_pcm_format_physical_width(ctx_priv->in_params.sample_format);
9273+		fifo_addr = asrc->paddr + REG_EASRC_WRFIFO(index);
9274+	} else {
9275+		buf_vaddr = (void __user *)buf->output_buffer_vaddr;
9276+		buf_len = buf->output_buffer_length;
9277+		bits = snd_pcm_format_physical_width(ctx_priv->out_params.sample_format);
9278+		fifo_addr = asrc->paddr + REG_EASRC_RDFIFO(index);
9279+	}
9280+
9281+	if (buf_len > EASRC_DMA_BUFFER_SIZE ||
9282+	    (dir == IN && (buf_len % (bits / 8)))) {
9283+		dev_err(dev, "%sput buffer size is error: [%d]\n",
9284+			DIR_STR(dir), buf_len);
9285+		return -EINVAL;
9286+	}
9287+
9288+	if (dir == IN && copy_from_user(dma_vaddr, buf_vaddr, buf_len))
9289+		return -EFAULT;
9290+
9291+	*dma_len = buf_len;
9292+
9293+	if (dir == OUT)
9294+		*dma_len = fsl_easrc_calc_outbuf_len(m2m, buf);
9295+
9296+	if (*dma_len <= 0)
9297+		return 0;
9298+
9299+	*sg_nodes = *dma_len / m2m->dma_block[dir].max_buf_size;
9300+	if (*dma_len % m2m->dma_block[dir].max_buf_size)
9301+		*sg_nodes += 1;
9302+
9303+	return fsl_easrc_dmaconfig(m2m, dma_chan, fifo_addr, dma_vaddr,
9304+				*dma_len, dir, bits);
9305+}
9306+
9307+static long fsl_easrc_prepare_buffer(struct fsl_easrc_m2m *m2m,
9308+				     struct asrc_convert_buffer *buf)
9309+{
9310+	struct fsl_asrc *asrc = m2m->asrc;
9311+	struct device *dev = &asrc->pdev->dev;
9312+	int ret;
9313+
9314+	ret = fsl_easrc_prepare_io_buffer(m2m, buf, IN);
9315+	if (ret) {
9316+		dev_err(dev, "failed to prepare input buffer %d\n", ret);
9317+		return ret;
9318+	}
9319+
9320+	ret = fsl_easrc_prepare_io_buffer(m2m, buf, OUT);
9321+	if (ret) {
9322+		dev_err(dev, "failed to prepare output buffer %d\n", ret);
9323+		return ret;
9324+	}
9325+
9326+	return 0;
9327+}
9328+
9329+int fsl_easrc_process_buffer_pre(struct fsl_easrc_m2m *m2m, bool dir)
9330+{
9331+	struct fsl_asrc *asrc = m2m->asrc;
9332+	struct device *dev = &asrc->pdev->dev;
9333+
9334+	if (!wait_for_completion_interruptible_timeout(&m2m->complete[dir],
9335+						       10 * HZ)) {
9336+		dev_err(dev, "%sput DMA task timeout\n", DIR_STR(dir));
9337+		return -ETIME;
9338+	} else if (signal_pending(current)) {
9339+		dev_err(dev, "%sput task forcibly aborted\n", DIR_STR(dir));
9340+		return -ERESTARTSYS;
9341+	}
9342+
9343+	return 0;
9344+}
9345+
9346+static unsigned int fsl_easrc_get_output_FIFO_size(struct fsl_easrc_m2m *m2m)
9347+{
9348+	struct fsl_asrc *asrc = m2m->asrc;
9349+	enum asrc_pair_index index = m2m->ctx->index;
9350+	u32 val;
9351+
9352+	regmap_read(asrc->regmap, REG_EASRC_SFS(index), &val);
9353+
9354+	val &= EASRC_SFS_NSGO_MASK;
9355+
9356+	return val >> EASRC_SFS_NSGO_SHIFT;
9357+}
9358+
9359+static void fsl_easrc_read_last_FIFO(struct fsl_easrc_m2m *m2m)
9360+{
9361+	struct fsl_asrc *asrc = m2m->asrc;
9362+	struct dma_block *output = &m2m->dma_block[OUT];
9363+	struct fsl_asrc_pair *ctx = m2m->ctx;
9364+	struct fsl_easrc_ctx_priv *ctx_priv = ctx->private;
9365+	enum asrc_pair_index index = m2m->ctx->index;
9366+	u32 i, reg, size, t_size = 0, width;
9367+	u32 *reg32 = NULL;
9368+	u16 *reg16 = NULL;
9369+	u8  *reg24 = NULL;
9370+
9371+	width = snd_pcm_format_physical_width(ctx_priv->out_params.sample_format);
9372+
9373+	if (width == 32)
9374+		reg32 = output->dma_vaddr + output->length;
9375+	else if (width == 16)
9376+		reg16 = output->dma_vaddr + output->length;
9377+	else
9378+		reg24 = output->dma_vaddr + output->length;
9379+retry:
9380+	size = fsl_easrc_get_output_FIFO_size(m2m);
9381+	for (i = 0; i < size * ctx->channels; i++) {
9382+		regmap_read(asrc->regmap, REG_EASRC_RDFIFO(index), &reg);
9383+
9384+		if (reg32) {
9385+			*(reg32) = reg;
9386+			reg32++;
9387+		} else if (reg16) {
9388+			*(reg16) = (u16)reg;
9389+			reg16++;
9390+		} else {
9391+			*reg24++ = (u8)reg;
9392+			*reg24++ = (u8)(reg >> 8);
9393+			*reg24++ = (u8)(reg >> 16);
9394+		}
9395+	}
9396+	t_size += size;
9397+
9398+	if (size)
9399+		goto retry;
9400+
9401+	if (reg32)
9402+		output->length += t_size * ctx->channels * 4;
9403+	else if (reg16)
9404+		output->length += t_size * ctx->channels * 2;
9405+	else
9406+		output->length += t_size * ctx->channels * 3;
9407+}
9408+
9409+static long fsl_easrc_process_buffer(struct fsl_easrc_m2m *m2m,
9410+				     struct asrc_convert_buffer *buf)
9411+{
9412+	struct fsl_asrc *asrc = m2m->asrc;
9413+	struct device *dev = &asrc->pdev->dev;
9414+	unsigned long lock_flags;
9415+	int ret;
9416+
9417+	/* Check input task first */
9418+	ret = fsl_easrc_process_buffer_pre(m2m, IN);
9419+	if (ret) {
9420+		mxc_easrc_dma_umap_in(dev, m2m);
9421+		if (m2m->dma_block[OUT].length > 0)
9422+			mxc_easrc_dma_umap_out(dev, m2m);
9423+		return ret;
9424+	}
9425+
9426+	/* ...then output task*/
9427+	if (m2m->dma_block[OUT].length > 0) {
9428+		ret = fsl_easrc_process_buffer_pre(m2m, OUT);
9429+		if (ret) {
9430+			mxc_easrc_dma_umap_in(dev, m2m);
9431+			mxc_easrc_dma_umap_out(dev, m2m);
9432+			return ret;
9433+		}
9434+	}
9435+
9436+	mxc_easrc_dma_umap_in(dev, m2m);
9437+	if (m2m->dma_block[OUT].length > 0)
9438+		mxc_easrc_dma_umap_out(dev, m2m);
9439+
9440+	spin_lock_irqsave(&m2m->lock, lock_flags);
9441+	if (!m2m->ctx_hold) {
9442+		spin_unlock_irqrestore(&m2m->lock, lock_flags);
9443+		return -EFAULT;
9444+	}
9445+	spin_unlock_irqrestore(&m2m->lock, lock_flags);
9446+
9447+	/* Fetch the remaining data */
9448+	fsl_easrc_read_last_FIFO(m2m);
9449+
9450+	/* Update final lengths after getting last FIFO */
9451+	buf->input_buffer_length = m2m->dma_block[IN].length;
9452+	buf->output_buffer_length = m2m->dma_block[OUT].length;
9453+
9454+	if (copy_to_user((void __user *)buf->output_buffer_vaddr,
9455+			 m2m->dma_block[OUT].dma_vaddr,
9456+			 m2m->dma_block[OUT].length))
9457+		return -EFAULT;
9458+
9459+	return 0;
9460+}
9461+
9462+void fsl_easrc_submit_dma(struct fsl_easrc_m2m *m2m)
9463+{
9464+	/* Submit DMA request */
9465+	dmaengine_submit(m2m->desc[IN]);
9466+	dma_async_issue_pending(m2m->desc[IN]->chan);
9467+
9468+	if (m2m->dma_block[OUT].length > 0) {
9469+		dmaengine_submit(m2m->desc[OUT]);
9470+		dma_async_issue_pending(m2m->desc[OUT]->chan);
9471+	}
9472+}
9473+
9474+static long fsl_easrc_ioctl_req_context(struct fsl_easrc_m2m *m2m,
9475+					void __user *user)
9476+{
9477+	struct fsl_asrc *asrc = m2m->asrc;
9478+	struct device *dev = &asrc->pdev->dev;
9479+	struct asrc_req req;
9480+	unsigned long lock_flags;
9481+	long ret;
9482+
9483+	ret = copy_from_user(&req, user, sizeof(req));
9484+	if (ret) {
9485+		dev_err(dev, "failed to get req from user space:%ld\n", ret);
9486+		return ret;
9487+	}
9488+
9489+	ret = fsl_easrc_request_context(req.chn_num, m2m->ctx);
9490+	if (ret < 0) {
9491+		dev_err(dev, "failed to request context:%ld\n", ret);
9492+		return ret;
9493+	}
9494+
9495+	/* request context returns the context id in case of success */
9496+	spin_lock_irqsave(&m2m->lock, lock_flags);
9497+	m2m->ctx_hold = 1;
9498+	req.index = m2m->ctx->index;
9499+	req.supported_in_format = FSL_EASRC_FORMATS;
9500+	req.supported_out_format = FSL_EASRC_FORMATS |
9501+				   SNDRV_PCM_FMTBIT_IEC958_SUBFRAME_LE;
9502+	spin_unlock_irqrestore(&m2m->lock, lock_flags);
9503+
9504+	ret = copy_to_user(user, &req, sizeof(req));
9505+	if (ret) {
9506+		dev_err(dev, "failed to send req to user space: %ld\n", ret);
9507+		return ret;
9508+	}
9509+
9510+	return 0;
9511+}
9512+
9513+static long fsl_easrc_ioctl_config_context(struct fsl_easrc_m2m *m2m,
9514+					   void __user *user)
9515+{
9516+	struct fsl_asrc *asrc = m2m->asrc;
9517+	struct fsl_asrc_pair *ctx = m2m->ctx;
9518+	struct fsl_easrc_ctx_priv *ctx_priv = ctx->private;
9519+	enum asrc_pair_index index = m2m->ctx->index;
9520+	struct device *dev = &asrc->pdev->dev;
9521+	struct asrc_config config;
9522+	int ret;
9523+	int in_word_size, out_word_size;
9524+
9525+	ret = copy_from_user(&config, user, sizeof(config));
9526+	if (ret) {
9527+		dev_err(dev, "failed to get config from user space: %d\n", ret);
9528+		return ret;
9529+	}
9530+
9531+	/* set context configuration parameters received from userspace */
9532+	ctx_priv->in_params.sample_rate = config.input_sample_rate;
9533+	ctx_priv->out_params.sample_rate = config.output_sample_rate;
9534+
9535+	ctx_priv->in_params.fifo_wtmk = FSL_EASRC_INPUTFIFO_WML;
9536+	ctx_priv->out_params.fifo_wtmk = FSL_EASRC_OUTPUTFIFO_WML;
9537+
9538+	ctx_priv->in_params.sample_format = config.input_format;
9539+	ctx_priv->out_params.sample_format = config.output_format;
9540+
9541+	ctx->channels = config.channel_num;
9542+	ctx_priv->rs_init_mode = 0x2;
9543+	ctx_priv->pf_init_mode = 0x2;
9544+
9545+	ret = fsl_easrc_set_ctx_format(ctx,
9546+				       &ctx_priv->in_params.sample_format,
9547+				       &ctx_priv->out_params.sample_format);
9548+	if (ret)
9549+		return ret;
9550+
9551+	ret = fsl_easrc_config_context(asrc, index);
9552+	if (ret) {
9553+		dev_err(dev, "failed to config context %d\n", ret);
9554+		return ret;
9555+	}
9556+
9557+	ctx_priv->in_params.iterations = 1;
9558+	ctx_priv->in_params.group_len = ctx->channels;
9559+	ctx_priv->in_params.access_len = ctx->channels;
9560+	ctx_priv->out_params.iterations = 1;
9561+	ctx_priv->out_params.group_len = ctx->channels;
9562+	ctx_priv->out_params.access_len = ctx->channels;
9563+
9564+	/* You can also call fsl_easrc_set_ctx_organziation for
9565+	 * sample interleaving support
9566+	 */
9567+	ret = fsl_easrc_set_ctx_organziation(ctx);
9568+	if (ret) {
9569+		dev_err(dev, "failed to set fifo organization\n");
9570+		return ret;
9571+	}
9572+
9573+	in_word_size = snd_pcm_format_physical_width(config.input_format) / 8;
9574+	out_word_size = snd_pcm_format_physical_width(config.output_format) / 8;
9575+
9576+	/* allocate dma buffers */
9577+	m2m->dma_block[IN].length = EASRC_DMA_BUFFER_SIZE;
9578+	m2m->dma_block[IN].max_buf_size = rounddown(EASRC_MAX_BUFFER_SIZE,
9579+						    in_word_size * ctx->channels);
9580+	m2m->dma_block[OUT].length = EASRC_DMA_BUFFER_SIZE;
9581+	m2m->dma_block[OUT].max_buf_size = rounddown(EASRC_MAX_BUFFER_SIZE,
9582+						     out_word_size * ctx->channels);
9583+
9584+	ret = fsl_allocate_dma_buf(m2m);
9585+	if (ret) {
9586+		dev_err(dev, "failed to allocate DMA buffers: %d\n", ret);
9587+		return ret;
9588+	}
9589+
9590+	ctx->dma_chan[IN] = fsl_easrc_get_dma_channel(ctx, IN);
9591+	if (!ctx->dma_chan[IN]) {
9592+		dev_err(dev, "[ctx%d] failed to get input DMA channel\n",
9593+			m2m->ctx->index);
9594+		return -EBUSY;
9595+	}
9596+	ctx->dma_chan[OUT] = fsl_easrc_get_dma_channel(ctx, OUT);
9597+	if (!ctx->dma_chan[OUT]) {
9598+		dev_err(dev, "[ctx%d] failed to get output DMA channel\n",
9599+			m2m->ctx->index);
9600+		return -EBUSY;
9601+	}
9602+
9603+	ret = copy_to_user(user, &config, sizeof(config));
9604+	if (ret) {
9605+		dev_err(dev, "failed to send config to user: %d\n", ret);
9606+		return ret;
9607+	}
9608+
9609+	return 0;
9610+}
9611+
9612+static long fsl_easrc_ioctl_release_context(struct fsl_easrc_m2m *m2m,
9613+					    void __user *user)
9614+{
9615+	struct fsl_asrc *asrc = m2m->asrc;
9616+	struct fsl_asrc_pair *ctx = m2m->ctx;
9617+	struct device *dev = &asrc->pdev->dev;
9618+	enum asrc_pair_index index;
9619+	unsigned long lock_flags;
9620+	int ret;
9621+
9622+	ret = copy_from_user(&index, user, sizeof(index));
9623+	if (ret) {
9624+		dev_err(dev,
9625+			"[ctx%d] failed to get index from user space %d\n",
9626+			m2m->ctx->index, ret);
9627+		return ret;
9628+	}
9629+
9630+	if (index != m2m->ctx->index) {
9631+		dev_err(dev,
9632+			"[ctx%d] releasing wrong context - %d\n",
9633+			m2m->ctx->index, index);
9634+		return -EINVAL;
9635+	}
9636+
9637+	if (m2m->easrc_active) {
9638+		m2m->easrc_active = 0;
9639+		fsl_easrc_stop_context(ctx);
9640+	}
9641+
9642+	spin_lock_irqsave(&m2m->lock, lock_flags);
9643+	m2m->ctx_hold = 0;
9644+	spin_unlock_irqrestore(&m2m->lock, lock_flags);
9645+
9646+	if (ctx->dma_chan[IN])
9647+		dma_release_channel(ctx->dma_chan[IN]);
9648+	if (ctx->dma_chan[OUT])
9649+		dma_release_channel(ctx->dma_chan[OUT]);
9650+
9651+	ctx->dma_chan[IN] = NULL;
9652+	ctx->dma_chan[OUT] = NULL;
9653+
9654+	/* free buffers allocated in config context*/
9655+	kfree(m2m->dma_block[IN].dma_vaddr);
9656+	kfree(m2m->dma_block[OUT].dma_vaddr);
9657+
9658+	fsl_easrc_release_context(ctx);
9659+
9660+	return 0;
9661+}
9662+
9663+static long fsl_easrc_ioctl_convert(struct fsl_easrc_m2m *m2m,
9664+				    void __user *user)
9665+{
9666+	struct fsl_asrc *asrc = m2m->asrc;
9667+	struct device *dev = &asrc->pdev->dev;
9668+	struct fsl_asrc_pair *ctx = m2m->ctx;
9669+	struct asrc_convert_buffer buf;
9670+	int ret;
9671+
9672+	ret = copy_from_user(&buf, user, sizeof(buf));
9673+	if (ret) {
9674+		dev_err(dev, "failed to get buf from user space: %d\n", ret);
9675+		return ret;
9676+	}
9677+
9678+	/* fsl_easrc_calc_last_period_size(ctx, &buf); */
9679+	ret = fsl_easrc_prepare_buffer(m2m, &buf);
9680+	if (ret) {
9681+		dev_err(dev, "failed to prepare buffer\n");
9682+		return ret;
9683+	}
9684+
9685+	reinit_completion(&m2m->complete[IN]);
9686+	reinit_completion(&m2m->complete[OUT]);
9687+
9688+	fsl_easrc_submit_dma(m2m);
9689+
9690+	if (m2m->first_convert) {
9691+		fsl_easrc_start_context(ctx);
9692+		m2m->first_convert = 0;
9693+	}
9694+
9695+	ret = fsl_easrc_process_buffer(m2m, &buf);
9696+	if (ret) {
9697+		dev_err(dev, "failed to process buffer %d\n", ret);
9698+		return ret;
9699+	}
9700+
9701+	ret = copy_to_user(user, &buf, sizeof(buf));
9702+	if (ret) {
9703+		dev_err(dev, "failed to send buffer to user: %d\n", ret);
9704+		return ret;
9705+	}
9706+
9707+	return 0;
9708+}
9709+
9710+static long fsl_easrc_ioctl_start_conv(struct fsl_easrc_m2m *m2m,
9711+				       void __user *user)
9712+{
9713+	struct fsl_asrc *asrc = m2m->asrc;
9714+	struct device *dev = &asrc->pdev->dev;
9715+	enum asrc_pair_index index;
9716+	int ret;
9717+
9718+	ret = copy_from_user(&index, user, sizeof(index));
9719+	if (ret) {
9720+		dev_err(dev, "failed to get index from user space: %d\n",
9721+			ret);
9722+		return ret;
9723+	}
9724+
9725+	if (index != m2m->ctx->index) {
9726+		dev_err(dev, "[ctx%d] attempting to start wrong context%d\n",
9727+			m2m->ctx->index, index);
9728+		return -EINVAL;
9729+	}
9730+
9731+	m2m->easrc_active = 1;
9732+	m2m->first_convert = 1;
9733+
9734+	return 0;
9735+}
9736+
9737+static long fsl_easrc_ioctl_stop_conv(struct fsl_easrc_m2m *m2m,
9738+				      void __user *user)
9739+{
9740+	struct fsl_asrc *asrc = m2m->asrc;
9741+	struct fsl_asrc_pair *ctx = m2m->ctx;
9742+	struct device *dev = &asrc->pdev->dev;
9743+	enum asrc_pair_index index;
9744+	int ret;
9745+
9746+	ret = copy_from_user(&index, user, sizeof(index));
9747+	if (ret) {
9748+		dev_err(dev, "failed to get index from user space: %d\n",
9749+			ret);
9750+		return ret;
9751+	}
9752+
9753+	if (index != m2m->ctx->index) {
9754+		dev_err(dev, "[ctx%d] attempting to start wrong context%d\n",
9755+			m2m->ctx->index, index);
9756+		return -EINVAL;
9757+	}
9758+
9759+	dmaengine_terminate_all(ctx->dma_chan[IN]);
9760+	dmaengine_terminate_all(ctx->dma_chan[OUT]);
9761+
9762+	fsl_easrc_stop_context(ctx);
9763+	m2m->easrc_active = 0;
9764+
9765+	return 0;
9766+}
9767+
9768+static long fsl_easrc_ioctl_status(struct fsl_easrc_m2m *m2m,
9769+				   void __user *user)
9770+{
9771+	struct fsl_asrc *asrc = m2m->asrc;
9772+	struct device *dev = &asrc->pdev->dev;
9773+	struct fsl_asrc_pair *ctx = m2m->ctx;
9774+	struct asrc_status_flags flags;
9775+	int ret;
9776+
9777+	ret = copy_from_user(&flags, user, sizeof(flags));
9778+	if (ret) {
9779+		dev_err(dev,
9780+			"[ctx%d] failed to get flags from user space: %d\n",
9781+			m2m->ctx->index, ret);
9782+		return ret;
9783+	}
9784+
9785+	if (m2m->ctx->index != flags.index) {
9786+		dev_err(dev, "[ctx%d] getting status for other context: %d\n",
9787+			m2m->ctx->index, flags.index);
9788+		return -EINVAL;
9789+	}
9790+
9791+	fsl_easrc_get_status(ctx, &flags);
9792+
9793+	ret = copy_to_user(user, &flags, sizeof(flags));
9794+	if (ret)
9795+		dev_err(dev, "[ctx%d] failed to send flags to user space\n",
9796+			m2m->ctx->index);
9797+
9798+	return ret;
9799+}
9800+
9801+static long fsl_easrc_ioctl_flush(struct fsl_easrc_m2m *m2m,
9802+				  void __user *user)
9803+{
9804+	struct fsl_asrc *asrc = m2m->asrc;
9805+	struct device *dev = &asrc->pdev->dev;
9806+	struct fsl_asrc_pair *ctx = m2m->ctx;
9807+
9808+	/* Release DMA and request again */
9809+	dma_release_channel(ctx->dma_chan[IN]);
9810+	dma_release_channel(ctx->dma_chan[OUT]);
9811+
9812+	ctx->dma_chan[IN] = fsl_easrc_get_dma_channel(ctx, IN);
9813+	if (!ctx->dma_chan[IN]) {
9814+		dev_err(dev, "failed to request input task DMA channel\n");
9815+		return -EBUSY;
9816+	}
9817+
9818+	ctx->dma_chan[OUT] = fsl_easrc_get_dma_channel(ctx, OUT);
9819+	if (!ctx->dma_chan[OUT]) {
9820+		dev_err(dev, "failed to request output task DMA channel\n");
9821+		return -EBUSY;
9822+	}
9823+
9824+	return 0;
9825+}
9826+
9827+static int fsl_easrc_open(struct inode *inode, struct file *file)
9828+{
9829+	struct miscdevice *easrc_miscdev = file->private_data;
9830+	struct fsl_asrc *asrc = dev_get_drvdata(easrc_miscdev->parent);
9831+	struct fsl_easrc_m2m *m2m;
9832+	struct fsl_asrc_pair *ctx;
9833+	struct device *dev = &asrc->pdev->dev;
9834+	int ret;
9835+
9836+	ret = signal_pending(current);
9837+	if (ret) {
9838+		dev_err(dev, "current process has a signal pending\n");
9839+		return ret;
9840+	}
9841+
9842+	ctx = kzalloc(sizeof(*ctx) + asrc->pair_priv_size, GFP_KERNEL);
9843+	if (!ctx)
9844+		return -ENOMEM;
9845+
9846+	ctx->private = (void *)ctx + sizeof(struct fsl_asrc_pair);
9847+
9848+	/* set the pointer to easrc private data */
9849+	m2m = kzalloc(sizeof(*m2m), GFP_KERNEL);
9850+	if (!m2m) {
9851+		ret = -ENOMEM;
9852+		goto out;
9853+	}
9854+	/* just save the pointer to easrc private data */
9855+	m2m->asrc = asrc;
9856+	m2m->ctx = ctx;
9857+	ctx->asrc = asrc;
9858+	ctx->private_m2m = m2m;
9859+
9860+	spin_lock_init(&m2m->lock);
9861+	init_completion(&m2m->complete[IN]);
9862+	init_completion(&m2m->complete[OUT]);
9863+
9864+	/* context structs are already allocated in fsl_easrc->ctx[i] */
9865+	file->private_data = m2m;
9866+
9867+	pm_runtime_get_sync(dev);
9868+
9869+	return 0;
9870+out:
9871+	kfree(ctx);
9872+	return ret;
9873+}
9874+
9875+static int fsl_easrc_close(struct inode *inode, struct file *file)
9876+{
9877+	struct fsl_easrc_m2m *m2m = file->private_data;
9878+	struct fsl_asrc *asrc = m2m->asrc;
9879+	struct fsl_asrc_pair *ctx = m2m->ctx;
9880+	struct device *dev = &asrc->pdev->dev;
9881+	unsigned long lock_flags;
9882+
9883+	if (m2m->easrc_active) {
9884+		m2m->easrc_active = 0;
9885+		dmaengine_terminate_all(ctx->dma_chan[IN]);
9886+		dmaengine_terminate_all(ctx->dma_chan[OUT]);
9887+
9888+		fsl_easrc_stop_context(ctx);
9889+		fsl_easrc_input_dma_callback((void *)m2m);
9890+		fsl_easrc_output_dma_callback((void *)m2m);
9891+	}
9892+
9893+	if (!ctx)
9894+		goto null_ctx;
9895+
9896+	spin_lock_irqsave(&m2m->lock, lock_flags);
9897+	if (m2m->ctx_hold) {
9898+		m2m->ctx_hold = 0;
9899+		spin_unlock_irqrestore(&m2m->lock, lock_flags);
9900+
9901+		if (ctx->dma_chan[IN])
9902+			dma_release_channel(ctx->dma_chan[IN]);
9903+		if (ctx->dma_chan[OUT])
9904+			dma_release_channel(ctx->dma_chan[OUT]);
9905+
9906+		kfree(m2m->dma_block[IN].dma_vaddr);
9907+		kfree(m2m->dma_block[OUT].dma_vaddr);
9908+
9909+		fsl_easrc_release_context(ctx);
9910+	} else {
9911+		spin_unlock_irqrestore(&m2m->lock, lock_flags);
9912+	}
9913+
9914+null_ctx:
9915+	spin_lock_irqsave(&asrc->lock, lock_flags);
9916+	kfree(m2m);
9917+	kfree(ctx);
9918+	file->private_data = NULL;
9919+	spin_unlock_irqrestore(&asrc->lock, lock_flags);
9920+
9921+	pm_runtime_put_sync(dev);
9922+
9923+	return 0;
9924+}
9925+
9926+static long fsl_easrc_ioctl(struct file *file, unsigned int cmd,
9927+			    unsigned long arg)
9928+{
9929+	struct fsl_easrc_m2m *m2m = file->private_data;
9930+	struct fsl_asrc *asrc = m2m->asrc;
9931+	void __user *user = (void __user *)arg;
9932+	long ret = 0;
9933+
9934+	switch (cmd) {
9935+	case ASRC_REQ_PAIR:
9936+		ret = fsl_easrc_ioctl_req_context(m2m, user);
9937+		break;
9938+	case ASRC_CONFIG_PAIR:
9939+		ret = fsl_easrc_ioctl_config_context(m2m, user);
9940+		break;
9941+	case ASRC_RELEASE_PAIR:
9942+		ret = fsl_easrc_ioctl_release_context(m2m, user);
9943+		break;
9944+	case ASRC_CONVERT:
9945+		ret = fsl_easrc_ioctl_convert(m2m, user);
9946+		break;
9947+	case ASRC_START_CONV:
9948+		ret = fsl_easrc_ioctl_start_conv(m2m, user);
9949+		break;
9950+	case ASRC_STOP_CONV:
9951+		ret = fsl_easrc_ioctl_stop_conv(m2m, user);
9952+		break;
9953+	case ASRC_STATUS:
9954+		ret = fsl_easrc_ioctl_status(m2m, user);
9955+		break;
9956+	case ASRC_FLUSH:
9957+		ret = fsl_easrc_ioctl_flush(m2m, user);
9958+		break;
9959+	default:
9960+		dev_err(&asrc->pdev->dev, "invalid ioctl command\n");
9961+	}
9962+
9963+	return ret;
9964+}
9965+
9966+static const struct file_operations easrc_fops = {
9967+	.owner = THIS_MODULE,
9968+	.unlocked_ioctl = fsl_easrc_ioctl,
9969+	.open = fsl_easrc_open,
9970+	.release = fsl_easrc_close,
9971+};
9972+
9973+static int fsl_easrc_m2m_init(struct fsl_asrc *asrc)
9974+{
9975+	struct device *dev = &asrc->pdev->dev;
9976+	int ret;
9977+
9978+	asrc->asrc_miscdev.fops = &easrc_fops;
9979+	asrc->asrc_miscdev.parent = dev;
9980+	asrc->asrc_miscdev.name = "mxc_asrc";
9981+	asrc->asrc_miscdev.minor = MISC_DYNAMIC_MINOR;
9982+	ret = misc_register(&asrc->asrc_miscdev);
9983+	if (ret)
9984+		dev_err(dev, "failed to register char device %d\n", ret);
9985+
9986+	return ret;
9987+}
9988+
9989+#ifdef CONFIG_PM_SLEEP
9990+static void fsl_easrc_m2m_suspend(struct fsl_asrc *asrc)
9991+{
9992+	struct fsl_asrc_pair *ctx;
9993+	struct fsl_easrc_m2m *m2m;
9994+	unsigned long lock_flags;
9995+	int i;
9996+
9997+	for (i = 0; i < EASRC_CTX_MAX_NUM; i++) {
9998+		spin_lock_irqsave(&asrc->lock, lock_flags);
9999+		ctx = asrc->pair[i];
10000+		if (!ctx || !ctx->private_m2m) {
10001+			spin_unlock_irqrestore(&asrc->lock, lock_flags);
10002+			continue;
10003+		}
10004+		m2m = ctx->private_m2m;
10005+
10006+		if (!completion_done(&m2m->complete[IN])) {
10007+			if (ctx->dma_chan[IN])
10008+				dmaengine_terminate_all(ctx->dma_chan[IN]);
10009+			fsl_easrc_input_dma_callback((void *)m2m);
10010+		}
10011+		if (!completion_done(&m2m->complete[OUT])) {
10012+			if (ctx->dma_chan[OUT])
10013+				dmaengine_terminate_all(ctx->dma_chan[OUT]);
10014+			fsl_easrc_output_dma_callback((void *)m2m);
10015+		}
10016+
10017+		m2m->first_convert = 1;
10018+		m2m->in_filled_len = 0;
10019+		fsl_easrc_stop_context(ctx);
10020+		spin_unlock_irqrestore(&asrc->lock, lock_flags);
10021+	}
10022+}
10023+
10024+static void fsl_easrc_m2m_resume(struct fsl_asrc *asrc)
10025+{
10026+	/* null */
10027+}
10028+#endif
10029diff --git a/sound/soc/fsl/fsl_esai.c b/sound/soc/fsl/fsl_esai.c
10030index 9f5f217a9..fbb126c88 100644
10031--- a/sound/soc/fsl/fsl_esai.c
10032+++ b/sound/soc/fsl/fsl_esai.c
10033@@ -14,6 +14,7 @@
10034 #include <sound/pcm_params.h>
10035
10036 #include "fsl_esai.h"
10037+#include "fsl_esai_mix.h"
10038 #include "imx-pcm.h"
10039
10040 #define FSL_ESAI_FORMATS	(SNDRV_PCM_FMTBIT_S8 | \
10041@@ -21,83 +22,28 @@
10042 				SNDRV_PCM_FMTBIT_S20_3LE | \
10043 				SNDRV_PCM_FMTBIT_S24_LE)
10044
10045-/**
10046- * struct fsl_esai_soc_data - soc specific data
10047- * @imx: for imx platform
10048- * @reset_at_xrun: flags for enable reset operaton
10049- */
10050-struct fsl_esai_soc_data {
10051-	bool imx;
10052-	bool reset_at_xrun;
10053-};
10054-
10055-/**
10056- * struct fsl_esai - ESAI private data
10057- * @dma_params_rx: DMA parameters for receive channel
10058- * @dma_params_tx: DMA parameters for transmit channel
10059- * @pdev: platform device pointer
10060- * @regmap: regmap handler
10061- * @coreclk: clock source to access register
10062- * @extalclk: esai clock source to derive HCK, SCK and FS
10063- * @fsysclk: system clock source to derive HCK, SCK and FS
10064- * @spbaclk: SPBA clock (optional, depending on SoC design)
10065- * @work: work to handle the reset operation
10066- * @soc: soc specific data
10067- * @lock: spin lock between hw_reset() and trigger()
10068- * @fifo_depth: depth of tx/rx FIFO
10069- * @slot_width: width of each DAI slot
10070- * @slots: number of slots
10071- * @tx_mask: slot mask for TX
10072- * @rx_mask: slot mask for RX
10073- * @channels: channel num for tx or rx
10074- * @hck_rate: clock rate of desired HCKx clock
10075- * @sck_rate: clock rate of desired SCKx clock
10076- * @hck_dir: the direction of HCKx pads
10077- * @sck_div: if using PSR/PM dividers for SCKx clock
10078- * @slave_mode: if fully using DAI slave mode
10079- * @synchronous: if using tx/rx synchronous mode
10080- * @name: driver name
10081- */
10082-struct fsl_esai {
10083-	struct snd_dmaengine_dai_dma_data dma_params_rx;
10084-	struct snd_dmaengine_dai_dma_data dma_params_tx;
10085-	struct platform_device *pdev;
10086-	struct regmap *regmap;
10087-	struct clk *coreclk;
10088-	struct clk *extalclk;
10089-	struct clk *fsysclk;
10090-	struct clk *spbaclk;
10091-	struct work_struct work;
10092-	const struct fsl_esai_soc_data *soc;
10093-	spinlock_t lock; /* Protect hw_reset and trigger */
10094-	u32 fifo_depth;
10095-	u32 slot_width;
10096-	u32 slots;
10097-	u32 tx_mask;
10098-	u32 rx_mask;
10099-	u32 channels[2];
10100-	u32 hck_rate[2];
10101-	u32 sck_rate[2];
10102-	bool hck_dir[2];
10103-	bool sck_div[2];
10104-	bool slave_mode;
10105-	bool synchronous;
10106-	char name[32];
10107-};
10108-
10109 static struct fsl_esai_soc_data fsl_esai_vf610 = {
10110 	.imx = false,
10111 	.reset_at_xrun = true,
10112+	.use_edma = false,
10113 };
10114
10115 static struct fsl_esai_soc_data fsl_esai_imx35 = {
10116 	.imx = true,
10117 	.reset_at_xrun = true,
10118+	.use_edma = false,
10119 };
10120
10121 static struct fsl_esai_soc_data fsl_esai_imx6ull = {
10122 	.imx = true,
10123 	.reset_at_xrun = false,
10124+	.use_edma = false,
10125+};
10126+
10127+static struct fsl_esai_soc_data fsl_esai_imx8qm = {
10128+	.imx = true,
10129+	.reset_at_xrun = false,
10130+	.use_edma = true,
10131 };
10132
10133 static irqreturn_t esai_isr(int irq, void *devid)
10134@@ -124,10 +70,10 @@ static irqreturn_t esai_isr(int irq, void *devid)
10135 		dev_dbg(&pdev->dev, "isr: Transmission Initialized\n");
10136
10137 	if (esr & ESAI_ESR_RFF_MASK)
10138-		dev_warn(&pdev->dev, "isr: Receiving overrun\n");
10139+		dev_dbg(&pdev->dev, "isr: Receiving overrun\n");
10140
10141 	if (esr & ESAI_ESR_TFE_MASK)
10142-		dev_warn(&pdev->dev, "isr: Transmission underrun\n");
10143+		dev_dbg(&pdev->dev, "isr: Transmission underrun\n");
10144
10145 	if (esr & ESAI_ESR_TLS_MASK)
10146 		dev_dbg(&pdev->dev, "isr: Just transmitted the last slot\n");
10147@@ -372,7 +318,7 @@ static int fsl_esai_set_bclk(struct snd_soc_dai *dai, bool tx, u32 freq)
10148 	int ret;
10149
10150 	/* Don't apply for fully slave mode or unchanged bclk */
10151-	if (esai_priv->slave_mode || esai_priv->sck_rate[tx] == freq)
10152+	if (esai_priv->slave_mode[tx] || esai_priv->sck_rate[tx] == freq)
10153 		return 0;
10154
10155 	if (ratio * freq > hck_rate)
10156@@ -481,35 +427,62 @@ static int fsl_esai_set_dai_fmt(struct snd_soc_dai *dai, unsigned int fmt)
10157 		return -EINVAL;
10158 	}
10159
10160-	esai_priv->slave_mode = false;
10161+	if (esai_priv->slave_mode[0] == esai_priv->slave_mode[1]) {
10162+		/* DAI clock master masks */
10163+		switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
10164+		case SND_SOC_DAIFMT_CBM_CFM:
10165+			esai_priv->slave_mode[0] = true;
10166+			esai_priv->slave_mode[1] = true;
10167+			break;
10168+		case SND_SOC_DAIFMT_CBS_CFM:
10169+			xccr |= ESAI_xCCR_xCKD;
10170+			break;
10171+		case SND_SOC_DAIFMT_CBM_CFS:
10172+			xccr |= ESAI_xCCR_xFSD;
10173+			break;
10174+		case SND_SOC_DAIFMT_CBS_CFS:
10175+			xccr |= ESAI_xCCR_xFSD | ESAI_xCCR_xCKD;
10176+			esai_priv->slave_mode[0] = false;
10177+			esai_priv->slave_mode[1] = false;
10178+			break;
10179+		default:
10180+			return -EINVAL;
10181+		}
10182
10183-	/* DAI clock master masks */
10184-	switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
10185-	case SND_SOC_DAIFMT_CBM_CFM:
10186-		esai_priv->slave_mode = true;
10187-		break;
10188-	case SND_SOC_DAIFMT_CBS_CFM:
10189-		xccr |= ESAI_xCCR_xCKD;
10190-		break;
10191-	case SND_SOC_DAIFMT_CBM_CFS:
10192-		xccr |= ESAI_xCCR_xFSD;
10193-		break;
10194-	case SND_SOC_DAIFMT_CBS_CFS:
10195-		xccr |= ESAI_xCCR_xFSD | ESAI_xCCR_xCKD;
10196-		break;
10197-	default:
10198-		return -EINVAL;
10199+		mask = ESAI_xCCR_xCKP | ESAI_xCCR_xHCKP | ESAI_xCCR_xFSP |
10200+			ESAI_xCCR_xFSD | ESAI_xCCR_xCKD;
10201+		regmap_update_bits(esai_priv->regmap,
10202+					REG_ESAI_TCCR, mask, xccr);
10203+		regmap_update_bits(esai_priv->regmap,
10204+					REG_ESAI_RCCR, mask, xccr);
10205+
10206+	} else {
10207+
10208+		mask = ESAI_xCCR_xCKP | ESAI_xCCR_xHCKP | ESAI_xCCR_xFSP |
10209+			ESAI_xCCR_xFSD | ESAI_xCCR_xCKD;
10210+		if (esai_priv->slave_mode[0])
10211+			regmap_update_bits(esai_priv->regmap,
10212+					REG_ESAI_RCCR, mask, xccr);
10213+		else
10214+			regmap_update_bits(esai_priv->regmap, REG_ESAI_RCCR,
10215+						mask,
10216+						xccr | ESAI_xCCR_xFSD |
10217+							ESAI_xCCR_xCKD);
10218+
10219+		if (esai_priv->slave_mode[1])
10220+			regmap_update_bits(esai_priv->regmap,
10221+						REG_ESAI_TCCR, mask, xccr);
10222+		else
10223+			regmap_update_bits(esai_priv->regmap, REG_ESAI_TCCR,
10224+						mask,
10225+						xccr | ESAI_xCCR_xFSD |
10226+							ESAI_xCCR_xCKD);
10227 	}
10228
10229 	mask = ESAI_xCR_xFSL | ESAI_xCR_xFSR | ESAI_xCR_xWA;
10230 	regmap_update_bits(esai_priv->regmap, REG_ESAI_TCR, mask, xcr);
10231 	regmap_update_bits(esai_priv->regmap, REG_ESAI_RCR, mask, xcr);
10232
10233-	mask = ESAI_xCCR_xCKP | ESAI_xCCR_xHCKP | ESAI_xCCR_xFSP |
10234-		ESAI_xCCR_xFSD | ESAI_xCCR_xCKD;
10235-	regmap_update_bits(esai_priv->regmap, REG_ESAI_TCCR, mask, xccr);
10236-	regmap_update_bits(esai_priv->regmap, REG_ESAI_RCCR, mask, xccr);
10237-
10238 	return 0;
10239 }
10240
10241@@ -517,6 +490,7 @@ static int fsl_esai_startup(struct snd_pcm_substream *substream,
10242 			    struct snd_soc_dai *dai)
10243 {
10244 	struct fsl_esai *esai_priv = snd_soc_dai_get_drvdata(dai);
10245+	bool tx = substream->stream == SNDRV_PCM_STREAM_PLAYBACK;
10246
10247 	if (!snd_soc_dai_active(dai)) {
10248 		/* Set synchronous mode */
10249@@ -533,10 +507,28 @@ static int fsl_esai_startup(struct snd_pcm_substream *substream,
10250 				   ESAI_xCCR_xDC(esai_priv->slots));
10251 	}
10252
10253+	if (esai_priv->soc->use_edma)
10254+		snd_pcm_hw_constraint_step(substream->runtime, 0,
10255+					   SNDRV_PCM_HW_PARAM_PERIOD_SIZE,
10256+					   tx ? esai_priv->dma_params_tx.maxburst :
10257+					   esai_priv->dma_params_rx.maxburst);
10258+	if (esai_priv->sw_mix)
10259+		fsl_esai_mix_open(substream, &esai_priv->mix[tx]);
10260+
10261 	return 0;
10262
10263 }
10264
10265+static void fsl_esai_shutdown(struct snd_pcm_substream *substream,
10266+			      struct snd_soc_dai *dai)
10267+{
10268+	struct fsl_esai *esai_priv = snd_soc_dai_get_drvdata(dai);
10269+	bool tx = substream->stream == SNDRV_PCM_STREAM_PLAYBACK;
10270+
10271+	if (esai_priv->sw_mix)
10272+		fsl_esai_mix_close(substream, &esai_priv->mix[tx]);
10273+}
10274+
10275 static int fsl_esai_hw_params(struct snd_pcm_substream *substream,
10276 			      struct snd_pcm_hw_params *params,
10277 			      struct snd_soc_dai *dai)
10278@@ -592,6 +584,10 @@ static int fsl_esai_hw_params(struct snd_pcm_substream *substream,
10279 			   ESAI_PRRC_PDC_MASK, ESAI_PRRC_PDC(ESAI_GPIO));
10280 	regmap_update_bits(esai_priv->regmap, REG_ESAI_PCRC,
10281 			   ESAI_PCRC_PC_MASK, ESAI_PCRC_PC(ESAI_GPIO));
10282+
10283+	if (esai_priv->sw_mix)
10284+		fsl_esai_mix_hw_params(substream, params, &esai_priv->mix[tx]);
10285+
10286 	return 0;
10287 }
10288
10289@@ -765,13 +761,23 @@ static int fsl_esai_trigger(struct snd_pcm_substream *substream, int cmd,
10290 	struct fsl_esai *esai_priv = snd_soc_dai_get_drvdata(dai);
10291 	bool tx = substream->stream == SNDRV_PCM_STREAM_PLAYBACK;
10292 	unsigned long lock_flags;
10293+	u32 state;
10294
10295-	esai_priv->channels[tx] = substream->runtime->channels;
10296+	if (esai_priv->sw_mix)
10297+		esai_priv->channels[tx] = esai_priv->mix[tx].channels;
10298+	else
10299+		esai_priv->channels[tx] = substream->runtime->channels;
10300
10301 	switch (cmd) {
10302 	case SNDRV_PCM_TRIGGER_START:
10303 	case SNDRV_PCM_TRIGGER_RESUME:
10304 	case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
10305+		if (esai_priv->sw_mix) {
10306+			state = atomic_cmpxchg(&esai_priv->mix[tx].active, 0, 1);
10307+			if (!state)
10308+				fsl_esai_mix_trigger(substream, cmd, &esai_priv->mix[tx]);
10309+		}
10310+
10311 		spin_lock_irqsave(&esai_priv->lock, lock_flags);
10312 		fsl_esai_trigger_start(esai_priv, tx);
10313 		spin_unlock_irqrestore(&esai_priv->lock, lock_flags);
10314@@ -779,6 +785,12 @@ static int fsl_esai_trigger(struct snd_pcm_substream *substream, int cmd,
10315 	case SNDRV_PCM_TRIGGER_SUSPEND:
10316 	case SNDRV_PCM_TRIGGER_STOP:
10317 	case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
10318+		if (esai_priv->sw_mix) {
10319+			state = atomic_cmpxchg(&esai_priv->mix[tx].active, 1, 0);
10320+			if (state)
10321+				fsl_esai_mix_trigger(substream, cmd, &esai_priv->mix[tx]);
10322+		}
10323+
10324 		spin_lock_irqsave(&esai_priv->lock, lock_flags);
10325 		fsl_esai_trigger_stop(esai_priv, tx);
10326 		spin_unlock_irqrestore(&esai_priv->lock, lock_flags);
10327@@ -792,6 +804,7 @@ static int fsl_esai_trigger(struct snd_pcm_substream *substream, int cmd,
10328
10329 static const struct snd_soc_dai_ops fsl_esai_dai_ops = {
10330 	.startup = fsl_esai_startup,
10331+	.shutdown = fsl_esai_shutdown,
10332 	.trigger = fsl_esai_trigger,
10333 	.hw_params = fsl_esai_hw_params,
10334 	.set_sysclk = fsl_esai_set_dai_sysclk,
10335@@ -981,7 +994,7 @@ static int fsl_esai_probe(struct platform_device *pdev)
10336 		return PTR_ERR(regs);
10337
10338 	esai_priv->regmap = devm_regmap_init_mmio_clk(&pdev->dev,
10339-			"core", regs, &fsl_esai_regmap_config);
10340+			NULL, regs, &fsl_esai_regmap_config);
10341 	if (IS_ERR(esai_priv->regmap)) {
10342 		dev_err(&pdev->dev, "failed to init regmap: %ld\n",
10343 				PTR_ERR(esai_priv->regmap));
10344@@ -1024,9 +1037,6 @@ static int fsl_esai_probe(struct platform_device *pdev)
10345 	/* Set a default slot number */
10346 	esai_priv->slots = 2;
10347
10348-	/* Set a default master/slave state */
10349-	esai_priv->slave_mode = true;
10350-
10351 	/* Determine the FIFO depth */
10352 	iprop = of_get_property(np, "fsl,fifo-depth", NULL);
10353 	if (iprop)
10354@@ -1042,6 +1052,20 @@ static int fsl_esai_probe(struct platform_device *pdev)
10355 	esai_priv->synchronous =
10356 		of_property_read_bool(np, "fsl,esai-synchronous");
10357
10358+	if (!esai_priv->synchronous) {
10359+		if (of_property_read_bool(pdev->dev.of_node, "fsl,txm-rxs")) {
10360+			/* 0 --  rx,  1 -- tx */
10361+			esai_priv->slave_mode[0] = true;
10362+			esai_priv->slave_mode[1] = false;
10363+		}
10364+
10365+		if (of_property_read_bool(pdev->dev.of_node, "fsl,txs-rxm")) {
10366+			/* 0 --  rx,  1 -- tx */
10367+			esai_priv->slave_mode[0] = false;
10368+			esai_priv->slave_mode[1] = true;
10369+		}
10370+	}
10371+
10372 	/* Implement full symmetry for synchronous mode */
10373 	if (esai_priv->synchronous) {
10374 		fsl_esai_dai.symmetric_rates = 1;
10375@@ -1052,6 +1076,11 @@ static int fsl_esai_probe(struct platform_device *pdev)
10376 	dev_set_drvdata(&pdev->dev, esai_priv);
10377
10378 	spin_lock_init(&esai_priv->lock);
10379+
10380+	ret = clk_prepare_enable(esai_priv->coreclk);
10381+	if (ret)
10382+		return ret;
10383+
10384 	ret = fsl_esai_hw_init(esai_priv);
10385 	if (ret)
10386 		return ret;
10387@@ -1065,6 +1094,8 @@ static int fsl_esai_probe(struct platform_device *pdev)
10388 	regmap_write(esai_priv->regmap, REG_ESAI_RSMA, 0);
10389 	regmap_write(esai_priv->regmap, REG_ESAI_RSMB, 0);
10390
10391+	clk_disable_unprepare(esai_priv->coreclk);
10392+
10393 	ret = devm_snd_soc_register_component(&pdev->dev, &fsl_esai_component,
10394 					      &fsl_esai_dai, 1);
10395 	if (ret) {
10396@@ -1078,9 +1109,16 @@ static int fsl_esai_probe(struct platform_device *pdev)
10397
10398 	regcache_cache_only(esai_priv->regmap, true);
10399
10400-	ret = imx_pcm_dma_init(pdev, IMX_ESAI_DMABUF_SIZE);
10401-	if (ret)
10402-		dev_err(&pdev->dev, "failed to init imx pcm dma: %d\n", ret);
10403+	if (of_property_read_bool(pdev->dev.of_node, "client-dais")) {
10404+		esai_priv->sw_mix = true;
10405+		ret = fsl_esai_mix_probe(&pdev->dev, &esai_priv->mix[0], &esai_priv->mix[1]);
10406+		if (ret)
10407+			dev_err(&pdev->dev, "failed to init imx pcm dma: %d\n", ret);
10408+	} else {
10409+		ret = imx_pcm_dma_init(pdev, IMX_ESAI_DMABUF_SIZE);
10410+		if (ret)
10411+			dev_err(&pdev->dev, "failed to init imx pcm dma: %d\n", ret);
10412+	}
10413
10414 	return ret;
10415 }
10416@@ -1089,6 +1127,9 @@ static int fsl_esai_remove(struct platform_device *pdev)
10417 {
10418 	struct fsl_esai *esai_priv = platform_get_drvdata(pdev);
10419
10420+	if (esai_priv->sw_mix)
10421+		fsl_esai_mix_remove(&pdev->dev, &esai_priv->mix[0], &esai_priv->mix[1]);
10422+
10423 	pm_runtime_disable(&pdev->dev);
10424 	cancel_work_sync(&esai_priv->work);
10425
10426@@ -1099,6 +1140,7 @@ static const struct of_device_id fsl_esai_dt_ids[] = {
10427 	{ .compatible = "fsl,imx35-esai", .data = &fsl_esai_imx35 },
10428 	{ .compatible = "fsl,vf610-esai", .data = &fsl_esai_vf610 },
10429 	{ .compatible = "fsl,imx6ull-esai", .data = &fsl_esai_imx6ull },
10430+	{ .compatible = "fsl,imx8qm-esai", .data = &fsl_esai_imx8qm },
10431 	{}
10432 };
10433 MODULE_DEVICE_TABLE(of, fsl_esai_dt_ids);
10434diff --git a/sound/soc/fsl/fsl_esai.h b/sound/soc/fsl/fsl_esai.h
10435index f873588d9..927ac7ebe 100644
10436--- a/sound/soc/fsl/fsl_esai.h
10437+++ b/sound/soc/fsl/fsl_esai.h
10438@@ -10,6 +10,9 @@
10439 #ifndef _FSL_ESAI_DAI_H
10440 #define _FSL_ESAI_DAI_H
10441
10442+#include <sound/dmaengine_pcm.h>
10443+#include "fsl_esai_mix.h"
10444+
10445 /* ESAI Register Map */
10446 #define REG_ESAI_ETDR		0x00
10447 #define REG_ESAI_ERDR		0x04
10448@@ -348,4 +351,72 @@
10449 #define ESAI_RX_DIV_PSR		3
10450 #define ESAI_RX_DIV_PM		4
10451 #define ESAI_RX_DIV_FP		5
10452+
10453+/**
10454+ * struct fsl_esai_soc_data - soc specific data
10455+ * @imx: for imx platform
10456+ * @reset_at_xrun: flags for enable reset operaton
10457+ * @use_edma: edma is used.
10458+ */
10459+struct fsl_esai_soc_data {
10460+	bool imx;
10461+	bool reset_at_xrun;
10462+	bool use_edma;
10463+};
10464+
10465+/**
10466+ * struct fsl_esai - ESAI private data
10467+ * @dma_params_rx: DMA parameters for receive channel
10468+ * @dma_params_tx: DMA parameters for transmit channel
10469+ * @pdev: platform device pointer
10470+ * @regmap: regmap handler
10471+ * @coreclk: clock source to access register
10472+ * @extalclk: esai clock source to derive HCK, SCK and FS
10473+ * @fsysclk: system clock source to derive HCK, SCK and FS
10474+ * @spbaclk: SPBA clock (optional, depending on SoC design)
10475+ * @task: tasklet to handle the reset operation
10476+ * @soc: soc specific data
10477+ * @lock: spin lock between hw_reset() and trigger()
10478+ * @fifo_depth: depth of tx/rx FIFO
10479+ * @slot_width: width of each DAI slot
10480+ * @slots: number of slots
10481+ * @tx_mask: slot mask for TX
10482+ * @rx_mask: slot mask for RX
10483+ * @channels: channel num for tx or rx
10484+ * @hck_rate: clock rate of desired HCKx clock
10485+ * @sck_rate: clock rate of desired SCKx clock
10486+ * @hck_dir: the direction of HCKx pads
10487+ * @sck_div: if using PSR/PM dividers for SCKx clock
10488+ * @slave_mode: if fully using DAI slave mode
10489+ * @synchronous: if using tx/rx synchronous mode
10490+ * @name: driver name
10491+ */
10492+struct fsl_esai {
10493+	struct snd_dmaengine_dai_dma_data dma_params_rx;
10494+	struct snd_dmaengine_dai_dma_data dma_params_tx;
10495+	struct platform_device *pdev;
10496+	struct regmap *regmap;
10497+	struct clk *coreclk;
10498+	struct clk *extalclk;
10499+	struct clk *fsysclk;
10500+	struct clk *spbaclk;
10501+	struct work_struct work;
10502+	const struct fsl_esai_soc_data *soc;
10503+	struct fsl_esai_mix mix[2];
10504+	spinlock_t lock; /* Protect hw_reset and trigger */
10505+	u32 fifo_depth;
10506+	u32 slot_width;
10507+	u32 slots;
10508+	u32 tx_mask;
10509+	u32 rx_mask;
10510+	u32 channels[2];
10511+	u32 hck_rate[2];
10512+	u32 sck_rate[2];
10513+	bool hck_dir[2];
10514+	bool sck_div[2];
10515+	bool slave_mode[2];
10516+	bool synchronous;
10517+	bool sw_mix;
10518+	char name[32];
10519+};
10520 #endif /* _FSL_ESAI_DAI_H */
10521diff --git a/sound/soc/fsl/fsl_esai_client.h b/sound/soc/fsl/fsl_esai_client.h
10522new file mode 100644
10523index 000000000..684300383
10524--- /dev/null
10525+++ b/sound/soc/fsl/fsl_esai_client.h
10526@@ -0,0 +1,40 @@
10527+/* SPDX-License-Identifier: GPL-2.0 */
10528+
10529+#ifndef __FSL_ESAI_CLIENT_H
10530+#define __FSL_ESAI_CLIENT_H
10531+
10532+/**
10533+ * fsl_esai_client_dma: esai dma client
10534+ * @dma_buffer: structure of dma buffer
10535+ * @buffer_bytes: buffer size in bytes
10536+ * @period_bytes: period size in bytes
10537+ * @period_num: period number
10538+ * @buffer_offset: read offset of buffer
10539+ * @channels: channel number
10540+ * @word_width: word width in bytes
10541+ * @active: dma transfer is active
10542+ */
10543+struct fsl_esai_client_dma {
10544+	struct snd_dma_buffer dma_buffer;
10545+	int   buffer_bytes;
10546+	int   period_bytes;
10547+	int   period_num;
10548+	int   buffer_offset;
10549+	int   channels;
10550+	int   word_width;
10551+	bool  active;
10552+};
10553+
10554+/**
10555+ * fsl_esai_client: esai client
10556+ * @cpu_dai_drv: CPU DAI driver for this device
10557+ * @dma: dma instance for playback and capture
10558+ * @id: client index
10559+ */
10560+struct fsl_esai_client {
10561+	struct snd_soc_dai_driver cpu_dai_drv;
10562+	struct fsl_esai_client_dma dma[2];
10563+	int id;
10564+};
10565+
10566+#endif /* __FSL_ESAI_CLIENT_H */
10567diff --git a/sound/soc/fsl/fsl_esai_mix.c b/sound/soc/fsl/fsl_esai_mix.c
10568new file mode 100644
10569index 000000000..6fef8891a
10570--- /dev/null
10571+++ b/sound/soc/fsl/fsl_esai_mix.c
10572@@ -0,0 +1,479 @@
10573+// SPDX-License-Identifier: GPL-2.0
10574+// Copyright 2019 NXP
10575+/*
10576+ * Support mix two streams for ESAI
10577+ *
10578+ */
10579+#include <linux/dma-mapping.h>
10580+#include <linux/slab.h>
10581+#include <linux/module.h>
10582+#include <linux/workqueue.h>
10583+#include <linux/kthread.h>
10584+#include <linux/freezer.h>
10585+#include <sound/core.h>
10586+#include <sound/pcm.h>
10587+#include <sound/pcm_params.h>
10588+#include <sound/dmaengine_pcm.h>
10589+#include <sound/soc.h>
10590+
10591+#include "imx-pcm.h"
10592+#include "fsl_esai_client.h"
10593+#include "fsl_esai.h"
10594+#include "fsl_esai_mix.h"
10595+
10596+int fsl_esai_mix_hw_params(struct snd_pcm_substream *substream,
10597+			   struct snd_pcm_hw_params *params,
10598+			   struct fsl_esai_mix *mix)
10599+{
10600+	struct snd_soc_pcm_runtime *rtd = substream->private_data;
10601+	struct snd_dmaengine_dai_dma_data *dma_data;
10602+	struct dma_slave_config config;
10603+	int err = 0;
10604+
10605+	mix->channels   = params_channels(params);
10606+	mix->word_width = snd_pcm_format_physical_width(params_format(params)) / 8;
10607+
10608+	dma_data = snd_soc_dai_get_dma_data(asoc_rtd_to_cpu(rtd, 0), substream);
10609+	if (!dma_data)
10610+		return 0;
10611+
10612+	/* fills in addr_width and direction */
10613+	err = snd_hwparams_to_dma_slave_config(substream, params, &config);
10614+	if (err)
10615+		return err;
10616+
10617+	snd_dmaengine_pcm_set_config_from_dai_data(substream,
10618+						   dma_data,
10619+						   &config);
10620+
10621+	return dmaengine_slave_config(mix->chan, &config);
10622+}
10623+
10624+int fsl_esai_mix_open(struct snd_pcm_substream *substream, struct fsl_esai_mix *mix)
10625+{
10626+	struct snd_soc_pcm_runtime *rtd = substream->private_data;
10627+	struct snd_dmaengine_dai_dma_data *dma_data;
10628+
10629+	dma_data = snd_soc_dai_get_dma_data(asoc_rtd_to_cpu(rtd, 0), substream);
10630+
10631+	mix->chan = dma_request_slave_channel(asoc_rtd_to_cpu(rtd, 0)->dev,
10632+					      dma_data->chan_name);
10633+
10634+	return 0;
10635+}
10636+
10637+int fsl_esai_mix_close(struct snd_pcm_substream *substream,
10638+		       struct fsl_esai_mix *mix)
10639+{
10640+	dmaengine_synchronize(mix->chan);
10641+	dma_release_channel(mix->chan);
10642+
10643+	return 0;
10644+}
10645+
10646+static int fsl_esai_mix_pointer(struct fsl_esai_mix *mix)
10647+{
10648+	struct dma_tx_state state;
10649+	enum dma_status status;
10650+	unsigned int buf_size;
10651+	unsigned int pos = 0;
10652+
10653+	status = dmaengine_tx_status(mix->chan, mix->cookie, &state);
10654+	if (status == DMA_IN_PROGRESS || status == DMA_PAUSED) {
10655+		buf_size = mix->buffer_bytes;
10656+		if (state.residue > 0 && state.residue <= buf_size)
10657+			pos = buf_size - state.residue;
10658+	}
10659+
10660+	return pos;
10661+}
10662+
10663+static int fsl_esai_tx_avail(struct fsl_esai_mix *mix)
10664+{
10665+	int avail;
10666+
10667+	mix->buffer_read_offset = fsl_esai_mix_pointer(mix);
10668+
10669+	avail = mix->buffer_bytes - mix->buffer_write_offset + mix->buffer_read_offset;
10670+	if (avail < 0)
10671+		avail += mix->buffer_bytes;
10672+	else if (avail > mix->buffer_bytes)
10673+		avail -=  mix->buffer_bytes;
10674+
10675+	return avail;
10676+}
10677+
10678+static int fsl_esai_rx_avail(struct fsl_esai_mix *mix)
10679+{
10680+	int avail;
10681+
10682+	mix->buffer_write_offset = fsl_esai_mix_pointer(mix);
10683+
10684+	avail = mix->buffer_bytes - mix->buffer_read_offset + mix->buffer_write_offset;
10685+	if (avail < 0)
10686+		avail += mix->buffer_bytes;
10687+	else if (avail > mix->buffer_bytes)
10688+		avail = avail -  mix->buffer_bytes;
10689+
10690+	return avail;
10691+}
10692+
10693+static void fsl_esai_mix_buffer_from_fe_tx(struct snd_pcm_substream *substream, bool elapse)
10694+{
10695+	bool tx = substream->stream == SNDRV_PCM_STREAM_PLAYBACK;
10696+	struct snd_soc_pcm_runtime *rtd = substream->private_data;
10697+	struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(rtd, 0);
10698+	struct fsl_esai *esai = snd_soc_dai_get_drvdata(cpu_dai);
10699+	struct fsl_esai_mix *mix = &esai->mix[tx];
10700+	struct fsl_esai_client *client;
10701+	struct fsl_esai_client_dma *client_dma;
10702+	struct snd_soc_dpcm *dpcm;
10703+	unsigned long flags;
10704+	int sample_offset = 0;
10705+	int client_chn = 0;
10706+	int mix_chn = 0;
10707+	int sdo_cnt = 0;
10708+	int loop_cnt = 0;
10709+	int avail = 0;
10710+	int size = 0;
10711+	int id = 0;
10712+	int i = 0, j = 0;
10713+	int dst_idx;
10714+	u16 *src16;
10715+	u16 *dst16;
10716+
10717+	for (j = 0; j < MAX_CLIENT_NUM; j++) {
10718+		mix->fe_substream[j] = NULL;
10719+		mix->client[j] = NULL;
10720+	}
10721+
10722+	/* Get the active client */
10723+	spin_lock_irqsave(&rtd->card->dpcm_lock, flags);
10724+	for_each_dpcm_fe(rtd, substream->stream, dpcm) {
10725+		if (dpcm->be != rtd)
10726+			continue;
10727+
10728+		mix->fe_substream[i] = snd_soc_dpcm_get_substream(dpcm->fe, substream->stream);
10729+		mix->client[i] = snd_soc_dai_get_drvdata(asoc_rtd_to_cpu(dpcm->fe, 0));
10730+
10731+		i++;
10732+		if (i >= MAX_CLIENT_NUM)
10733+			break;
10734+	}
10735+	spin_unlock_irqrestore(&rtd->card->dpcm_lock, flags);
10736+
10737+	avail = fsl_esai_tx_avail(mix);
10738+	if (avail >= mix->buffer_bytes && elapse)
10739+		dev_err(asoc_rtd_to_cpu(rtd, 0)->dev, "mix underrun\n");
10740+
10741+	while (avail >= mix->period_bytes) {
10742+		size = mix->period_bytes;
10743+		/* mix->word_width == client->word_width */
10744+		/* Mix the internal buffer */
10745+		dst16 = (u16 *)(mix->dma_buffer.area + (mix->buffer_write_offset % mix->buffer_bytes));
10746+		memset(dst16, 0, size);
10747+
10748+		for (i = 0;  i < mix->client_cnt;  i++) {
10749+			if (!mix->client[i])
10750+				continue;
10751+
10752+			client = mix->client[i];
10753+			client_dma = &client->dma[tx];
10754+
10755+			/* check client is active ? */
10756+			if (client_dma->active) {
10757+				sample_offset = 0;
10758+				id = client->id;
10759+				sdo_cnt = mix->sdo_cnt;
10760+				client_chn = client_dma->channels;
10761+				mix_chn = mix->channels;
10762+				loop_cnt = size / mix->word_width / mix_chn;
10763+
10764+				src16 = (u16 *)(client_dma->dma_buffer.area + client_dma->buffer_offset);
10765+				dst16 = (u16 *)(mix->dma_buffer.area + (mix->buffer_write_offset % mix->buffer_bytes));
10766+				while (sample_offset < loop_cnt) {
10767+
10768+					/* mix the data and reorder it for correct pin */
10769+					for (j = 0; j < client_chn; j++) {
10770+						dst_idx = id + j * sdo_cnt;
10771+						dst16[dst_idx] = *src16++;
10772+					}
10773+
10774+					sample_offset++;
10775+					dst16 = dst16 + mix_chn;
10776+				}
10777+
10778+				sample_offset = client_dma->buffer_offset + size / mix->client_cnt;
10779+				sample_offset = sample_offset % client_dma->buffer_bytes;
10780+				client_dma->buffer_offset = sample_offset;
10781+
10782+				if (elapse && mix->fe_substream[i])
10783+					snd_pcm_period_elapsed(mix->fe_substream[i]);
10784+			}
10785+		}
10786+
10787+		mix->buffer_write_offset += size;
10788+		if (mix->buffer_write_offset >= mix->buffer_bytes)
10789+			mix->buffer_write_offset -= mix->buffer_bytes;
10790+
10791+		avail -= mix->period_bytes;
10792+	}
10793+}
10794+
10795+static void fsl_esai_split_buffer_from_be_rx(struct snd_pcm_substream *substream, bool elapse)
10796+{
10797+	bool tx = substream->stream == SNDRV_PCM_STREAM_PLAYBACK;
10798+	struct snd_soc_pcm_runtime *rtd = substream->private_data;
10799+	struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(rtd, 0);
10800+	struct fsl_esai *esai = snd_soc_dai_get_drvdata(cpu_dai);
10801+	struct fsl_esai_mix *mix = &esai->mix[tx];
10802+	struct fsl_esai_client *client;
10803+	struct fsl_esai_client_dma *client_dma;
10804+	struct snd_soc_dpcm *dpcm;
10805+	unsigned long flags;
10806+	int sample_offset = 0;
10807+	int client_chn = 0;
10808+	int mix_chn = 0;
10809+	int sdi_cnt = 0;
10810+	int loop_cnt = 0;
10811+	int id = 0;
10812+	int size = 0;
10813+	int avail = 0;
10814+	int i = 0, j = 0;
10815+	int src_idx;
10816+	u16 *src16;
10817+	u16 *dst16;
10818+
10819+	for (j = 0; j < MAX_CLIENT_NUM; j++) {
10820+		mix->fe_substream[j] = NULL;
10821+		mix->client[j] = NULL;
10822+	}
10823+	/* Get the active client */
10824+	spin_lock_irqsave(&rtd->card->dpcm_lock, flags);
10825+	for_each_dpcm_fe(rtd, substream->stream, dpcm) {
10826+		if (dpcm->be != rtd)
10827+			continue;
10828+
10829+		mix->fe_substream[i] = snd_soc_dpcm_get_substream(dpcm->fe, substream->stream);
10830+		mix->client[i] = snd_soc_dai_get_drvdata(asoc_rtd_to_cpu(dpcm->fe, 0));
10831+
10832+		i++;
10833+		if (i >= MAX_CLIENT_NUM)
10834+			break;
10835+	}
10836+	spin_unlock_irqrestore(&rtd->card->dpcm_lock, flags);
10837+
10838+	avail = fsl_esai_rx_avail(mix);
10839+	if (avail >= mix->buffer_bytes && elapse)
10840+		dev_err(asoc_rtd_to_cpu(rtd, 0)->dev, "mix overrun\n");
10841+
10842+	while (avail >= mix->period_bytes) {
10843+		size = mix->period_bytes;
10844+		/* mix->word_width == client->word_width */
10845+		/* split the internal buffer */
10846+		for (i = 0;  i < mix->client_cnt;  i++) {
10847+			if (!mix->client[i])
10848+				continue;
10849+
10850+			client = mix->client[i];
10851+			client_dma = &client->dma[tx];
10852+
10853+			if (client_dma->active) {
10854+				sample_offset = 0;
10855+				id = client->id;
10856+				sdi_cnt = mix->sdi_cnt;
10857+				client_chn = client_dma->channels;
10858+				mix_chn = mix->channels;
10859+				loop_cnt = size / mix->word_width / mix_chn;
10860+
10861+				dst16 = (u16 *)(client_dma->dma_buffer.area + client_dma->buffer_offset);
10862+				src16 = (u16 *)(mix->dma_buffer.area + (mix->buffer_read_offset % mix->buffer_bytes));
10863+				while (sample_offset < loop_cnt) {
10864+
10865+					/* split the data to corret client*/
10866+					for (j = 0; j < client_chn; j++) {
10867+						src_idx = id + j * sdi_cnt;
10868+						*dst16++ = src16[src_idx];
10869+					}
10870+
10871+					sample_offset++;
10872+					src16 = src16 + mix_chn;
10873+				}
10874+				client_dma->buffer_offset += size / mix->client_cnt;
10875+				client_dma->buffer_offset = client_dma->buffer_offset % client_dma->buffer_bytes;
10876+
10877+				if (elapse && mix->fe_substream[i])
10878+					snd_pcm_period_elapsed(mix->fe_substream[i]);
10879+			}
10880+		}
10881+
10882+		mix->buffer_read_offset += size;
10883+		if (mix->buffer_read_offset >= mix->buffer_bytes)
10884+			mix->buffer_read_offset -= mix->buffer_bytes;
10885+
10886+		avail -= mix->period_bytes;
10887+	}
10888+}
10889+
10890+static void fsl_esai_mix_tx_worker(struct work_struct *work)
10891+{
10892+	struct fsl_esai_mix *mix;
10893+
10894+	mix = container_of(work, struct fsl_esai_mix, work);
10895+	fsl_esai_mix_buffer_from_fe_tx(mix->substream, true);
10896+}
10897+
10898+static void fsl_esai_mix_rx_worker(struct work_struct *work)
10899+{
10900+	struct fsl_esai_mix *mix;
10901+
10902+	mix = container_of(work, struct fsl_esai_mix, work);
10903+	fsl_esai_split_buffer_from_be_rx(mix->substream, true);
10904+}
10905+
10906+/* call back of dma event */
10907+static void fsl_esai_mix_dma_complete(void *arg)
10908+{
10909+	struct snd_pcm_substream *substream = arg;
10910+	struct snd_soc_pcm_runtime *rtd = substream->private_data;
10911+	struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(rtd, 0);
10912+	struct fsl_esai *esai = snd_soc_dai_get_drvdata(cpu_dai);
10913+	bool tx = substream->stream == SNDRV_PCM_STREAM_PLAYBACK;
10914+	struct fsl_esai_mix *mix = &esai->mix[tx];
10915+
10916+	mix->substream = substream;
10917+
10918+	queue_work(mix->mix_wq, &mix->work);
10919+}
10920+
10921+static int fsl_esai_mix_prepare_and_submit(struct snd_pcm_substream *substream,
10922+					   struct fsl_esai_mix *mix)
10923+{
10924+	struct dma_async_tx_descriptor *desc;
10925+	enum dma_transfer_direction direction;
10926+	unsigned long flags = DMA_CTRL_ACK | DMA_PREP_INTERRUPT;
10927+
10928+	direction = snd_pcm_substream_to_dma_direction(substream);
10929+
10930+	/* ping-pong buffer for mix */
10931+	desc = dmaengine_prep_dma_cyclic(mix->chan,
10932+					 mix->dma_buffer.addr,
10933+					 mix->buffer_bytes,
10934+					 mix->period_bytes,
10935+					 direction, flags);
10936+	if (!desc)
10937+		return -ENOMEM;
10938+
10939+	desc->callback = fsl_esai_mix_dma_complete;
10940+	desc->callback_param = substream;
10941+	mix->cookie = dmaengine_submit(desc);
10942+
10943+	/* Mix the tx buffer */
10944+	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
10945+		mix->buffer_read_offset = 0;
10946+		mix->buffer_write_offset = 0;
10947+		fsl_esai_mix_buffer_from_fe_tx(substream, false);
10948+	} else {
10949+		mix->buffer_read_offset = 0;
10950+		mix->buffer_write_offset = 0;
10951+	}
10952+
10953+	return 0;
10954+}
10955+
10956+int fsl_esai_mix_trigger(struct snd_pcm_substream *substream, int cmd,
10957+			 struct fsl_esai_mix *mix)
10958+{
10959+	int ret;
10960+
10961+	switch (cmd) {
10962+	case SNDRV_PCM_TRIGGER_START:
10963+	case SNDRV_PCM_TRIGGER_RESUME:
10964+	case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
10965+		ret = fsl_esai_mix_prepare_and_submit(substream, mix);
10966+		if (ret)
10967+			return ret;
10968+		dma_async_issue_pending(mix->chan);
10969+		break;
10970+	case SNDRV_PCM_TRIGGER_SUSPEND:
10971+	case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
10972+	case SNDRV_PCM_TRIGGER_STOP:
10973+		dmaengine_terminate_async(mix->chan);
10974+		break;
10975+	default:
10976+		return -EINVAL;
10977+	}
10978+
10979+	return 0;
10980+}
10981+
10982+int fsl_esai_mix_probe(struct device *dev, struct fsl_esai_mix *mix_rx, struct fsl_esai_mix *mix_tx)
10983+{
10984+	int ret = 0;
10985+
10986+	ret = dma_coerce_mask_and_coherent(dev, DMA_BIT_MASK(32));
10987+	if (ret)
10988+		return ret;
10989+
10990+	/**
10991+	 * initialize info for mixing
10992+	 * two clients, TX0 pin is for client 0, TX1 pin is for client 1
10993+	 * total supported channel is 4.
10994+	 */
10995+	mix_tx->client_cnt = 2;
10996+	mix_tx->sdo_cnt = 2;
10997+	mix_tx->sdi_cnt = 2;
10998+	mix_tx->channels = 4;
10999+	mix_tx->buffer_bytes = 2048 * mix_tx->client_cnt * 4;
11000+	mix_tx->period_bytes = 2048 * mix_tx->client_cnt;
11001+	ret = snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV,
11002+				  dev,
11003+				  IMX_SSI_DMABUF_SIZE * mix_tx->client_cnt,
11004+				  &mix_tx->dma_buffer);
11005+	if (ret)
11006+		return ret;
11007+
11008+	mix_tx->mix_wq = alloc_ordered_workqueue("esai_mix_tx", WQ_HIGHPRI | WQ_UNBOUND | WQ_FREEZABLE);
11009+	if (IS_ERR(mix_tx->mix_wq))
11010+		dev_err(dev, "failed  create easi mix tx thread\n");
11011+
11012+	INIT_WORK(&mix_tx->work, fsl_esai_mix_tx_worker);
11013+
11014+	/**
11015+	 * initialize info for mixing
11016+	 * two clients, TX0 pin is for client 0, TX1 pin is for client 1
11017+	 * total supported channel is 4.
11018+	 */
11019+	mix_rx->client_cnt = 2;
11020+	mix_rx->sdo_cnt = 2;
11021+	mix_rx->sdi_cnt = 2;
11022+	mix_rx->channels = 4;
11023+	mix_rx->buffer_bytes = 2048 * mix_rx->client_cnt * 4;
11024+	mix_rx->period_bytes = 2048 * mix_rx->client_cnt;
11025+	ret = snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV,
11026+				  dev,
11027+				  IMX_SSI_DMABUF_SIZE * mix_rx->client_cnt,
11028+				  &mix_rx->dma_buffer);
11029+	if (ret)
11030+		return ret;
11031+
11032+	mix_rx->mix_wq = alloc_ordered_workqueue("esai_mix_rx", WQ_HIGHPRI | WQ_UNBOUND | WQ_FREEZABLE);
11033+	if (IS_ERR(mix_rx->mix_wq))
11034+		dev_err(dev, "failed  create easi mix tx thread\n");
11035+
11036+	INIT_WORK(&mix_rx->work, fsl_esai_mix_rx_worker);
11037+
11038+	return ret;
11039+}
11040+
11041+int fsl_esai_mix_remove(struct device *dev, struct fsl_esai_mix *mix_rx, struct fsl_esai_mix *mix_tx)
11042+{
11043+	destroy_workqueue(mix_rx->mix_wq);
11044+	destroy_workqueue(mix_rx->mix_wq);
11045+
11046+	snd_dma_free_pages(&mix_tx->dma_buffer);
11047+	snd_dma_free_pages(&mix_rx->dma_buffer);
11048+
11049+	return 0;
11050+}
11051+MODULE_LICENSE("GPL");
11052diff --git a/sound/soc/fsl/fsl_esai_mix.h b/sound/soc/fsl/fsl_esai_mix.h
11053new file mode 100644
11054index 000000000..c7d2c74d0
11055--- /dev/null
11056+++ b/sound/soc/fsl/fsl_esai_mix.h
11057@@ -0,0 +1,58 @@
11058+/* SPDX-License-Identifier: GPL-2.0 */
11059+
11060+#ifndef _FSL_ESAI_MIX_H
11061+#define _FSL_ESAI_MIX_H
11062+
11063+/* maximum client number is 4; */
11064+#define MAX_CLIENT_NUM 4
11065+
11066+/**
11067+ * fsl_esai_mix: esai mix/split data
11068+ * @chan: dma channel
11069+ * @fe_substream: handler of front end substream
11070+ * @client: handler of client
11071+ * @dma_buffer: structure of dma buffer
11072+ * @buffer_offset: read offset of buffer
11073+ * @buffer_bytes: buffer size in bytes
11074+ * @period_bytes: period size in bytes
11075+ * @period_num: period number
11076+ * @word_width: word width in bytes
11077+ * @channels: channel number
11078+ * @client_cnt: client number, default 2.
11079+ * @sdo_cnt: output pin number of esai
11080+ * @sdi_cnt: input pin number of esai
11081+ * @active: mixer is enabled or not
11082+ */
11083+struct fsl_esai_mix {
11084+	struct dma_chan *chan;
11085+	struct snd_pcm_substream *fe_substream[MAX_CLIENT_NUM];
11086+	struct fsl_esai_client *client[MAX_CLIENT_NUM];
11087+	struct snd_dma_buffer dma_buffer;
11088+	struct workqueue_struct  *mix_wq;
11089+	struct work_struct       work;
11090+	struct snd_pcm_substream *substream;
11091+	dma_cookie_t cookie;
11092+	u32 buffer_read_offset;
11093+	u32 buffer_write_offset;
11094+	u32 buffer_bytes;
11095+	u32 period_bytes;
11096+	u32 period_num;
11097+	u32 word_width;
11098+	u32 channels;
11099+	u32 client_cnt;
11100+	u32 sdo_cnt;
11101+	u32 sdi_cnt;
11102+	atomic_t active;
11103+};
11104+
11105+int fsl_esai_mix_hw_params(struct snd_pcm_substream *substream,
11106+			   struct snd_pcm_hw_params *params,
11107+			   struct fsl_esai_mix *mix);
11108+int fsl_esai_mix_open(struct snd_pcm_substream *substream, struct fsl_esai_mix *mix);
11109+int fsl_esai_mix_close(struct snd_pcm_substream *substream, struct fsl_esai_mix *mix);
11110+int fsl_esai_mix_trigger(struct snd_pcm_substream *substream, int cmd,
11111+			 struct fsl_esai_mix *mix);
11112+int fsl_esai_mix_probe(struct device *dev, struct fsl_esai_mix *mix_rx, struct fsl_esai_mix *mix_tx);
11113+int fsl_esai_mix_remove(struct device *dev, struct fsl_esai_mix *mix_rx, struct fsl_esai_mix *mix_tx);
11114+
11115+#endif /* _FSL_ESAI_MIX_H */
11116diff --git a/sound/soc/fsl/fsl_micfil.c b/sound/soc/fsl/fsl_micfil.c
11117index efc5daf53..27ef6f989 100644
11118--- a/sound/soc/fsl/fsl_micfil.c
11119+++ b/sound/soc/fsl/fsl_micfil.c
11120@@ -1,6 +1,7 @@
11121 // SPDX-License-Identifier: GPL-2.0
11122 // Copyright 2018 NXP
11123
11124+#include <linux/atomic.h>
11125 #include <linux/clk.h>
11126 #include <linux/device.h>
11127 #include <linux/interrupt.h>
11128@@ -31,8 +32,13 @@ struct fsl_micfil {
11129 	struct platform_device *pdev;
11130 	struct regmap *regmap;
11131 	const struct fsl_micfil_soc_data *soc;
11132+	struct clk *busclk;
11133 	struct clk *mclk;
11134+	struct clk *clk_src[MICFIL_CLK_SRC_NUM];
11135 	struct snd_dmaengine_dai_dma_data dma_params_rx;
11136+	struct kobject *hwvad_kobject;
11137+	struct sdma_audio_config audio_config;
11138+	unsigned int vad_channel;
11139 	unsigned int dataline;
11140 	char name[32];
11141 	int irq[MICFIL_IRQ_LINES];
11142@@ -40,6 +46,25 @@ struct fsl_micfil {
11143 	int quality;	/*QUALITY 2-0 bits */
11144 	bool slave_mode;
11145 	int channel_gain[8];
11146+	int clk_src_id;
11147+	int dc_remover;
11148+	int vad_sound_gain;
11149+	int vad_noise_gain;
11150+	int vad_input_gain;
11151+	int vad_frame_time;
11152+	int vad_init_time;
11153+	int vad_init_mode;
11154+	int vad_nfil_adjust;
11155+	int vad_hpf;
11156+	int vad_zcd_th;
11157+	int vad_zcd_auto;
11158+	int vad_zcd_en;
11159+	int vad_zcd_adj;
11160+	int vad_rate_index;
11161+	atomic_t recording_state;
11162+	atomic_t hwvad_state;
11163+	/* spinlock to control HWVAD enable/disable */
11164+	spinlock_t hwvad_lock;
11165 };
11166
11167 struct fsl_micfil_soc_data {
11168@@ -47,6 +72,12 @@ struct fsl_micfil_soc_data {
11169 	unsigned int fifo_depth;
11170 	unsigned int dataline;
11171 	bool imx;
11172+	u64  formats;
11173+};
11174+
11175+static char *envp[] = {
11176+	"EVENT=PDM_VOICE_DETECT",
11177+	NULL,
11178 };
11179
11180 static struct fsl_micfil_soc_data fsl_micfil_imx8mm = {
11181@@ -54,10 +85,20 @@ static struct fsl_micfil_soc_data fsl_micfil_imx8mm = {
11182 	.fifos = 8,
11183 	.fifo_depth = 8,
11184 	.dataline =  0xf,
11185+	.formats = SNDRV_PCM_FMTBIT_S16_LE,
11186+};
11187+
11188+static struct fsl_micfil_soc_data fsl_micfil_imx8mp = {
11189+	.imx = true,
11190+	.fifos = 8,
11191+	.fifo_depth = 32,
11192+	.dataline =  0xf,
11193+	.formats = SNDRV_PCM_FMTBIT_S32_LE,
11194 };
11195
11196 static const struct of_device_id fsl_micfil_dt_ids[] = {
11197 	{ .compatible = "fsl,imx8mm-micfil", .data = &fsl_micfil_imx8mm },
11198+	{ .compatible = "fsl,imx8mp-micfil", .data = &fsl_micfil_imx8mp },
11199 	{}
11200 };
11201 MODULE_DEVICE_TABLE(of, fsl_micfil_dt_ids);
11202@@ -77,11 +118,525 @@ static const char * const micfil_quality_select_texts[] = {
11203 	"VLow0", "Low",
11204 };
11205
11206+static const char * const micfil_hwvad_init_mode[] = {
11207+	"Envelope mode", "Energy mode",
11208+};
11209+
11210+static const char * const micfil_hwvad_hpf_texts[] = {
11211+	"Filter bypass",
11212+	"Cut-off @1750Hz",
11213+	"Cut-off @215Hz",
11214+	"Cut-off @102Hz",
11215+};
11216+
11217+static const char * const micfil_hwvad_zcd_enable[] = {
11218+	"OFF", "ON",
11219+};
11220+
11221+static const char * const micfil_hwvad_zcdauto_enable[] = {
11222+	"OFF", "ON",
11223+};
11224+
11225+static const char * const micfil_hwvad_noise_decimation[] = {
11226+	"Disabled", "Enabled",
11227+};
11228+
11229+/* when adding new rate text, also add it to the
11230+ * micfil_hwvad_rate_ints
11231+ */
11232+static const char * const micfil_hwvad_rate[] = {
11233+	"48KHz", "44.1KHz",
11234+};
11235+
11236+static const int micfil_hwvad_rate_ints[] = {
11237+	48000, 44100,
11238+};
11239+
11240+static const char * const micfil_clk_src_texts[] = {
11241+	"Auto", "AudioPLL1", "AudioPLL2", "ExtClk3",
11242+};
11243+
11244+/* DC Remover Control
11245+ * Filter Bypassed	1 1
11246+ * Cut-off @21Hz	0 0
11247+ * Cut-off @83Hz	0 1
11248+ * Cut-off @152HZ	1 0
11249+ */
11250+static const char * const micfil_dc_remover_texts[] = {
11251+	"Cut-off @21Hz", "Cut-off @83Hz",
11252+	"Cut-off @152Hz", "Bypass",
11253+};
11254+
11255 static const struct soc_enum fsl_micfil_quality_enum =
11256 	SOC_ENUM_SINGLE(REG_MICFIL_CTRL2,
11257 			MICFIL_CTRL2_QSEL_SHIFT,
11258 			ARRAY_SIZE(micfil_quality_select_texts),
11259 			micfil_quality_select_texts);
11260+static const struct soc_enum fsl_micfil_hwvad_init_mode_enum =
11261+	SOC_ENUM_SINGLE_EXT(ARRAY_SIZE(micfil_hwvad_init_mode),
11262+			    micfil_hwvad_init_mode);
11263+static const struct soc_enum fsl_micfil_hwvad_hpf_enum =
11264+	SOC_ENUM_SINGLE_EXT(ARRAY_SIZE(micfil_hwvad_hpf_texts),
11265+			    micfil_hwvad_hpf_texts);
11266+static const struct soc_enum fsl_micfil_hwvad_zcd_enum =
11267+	SOC_ENUM_SINGLE_EXT(ARRAY_SIZE(micfil_hwvad_zcd_enable),
11268+			    micfil_hwvad_zcd_enable);
11269+static const struct soc_enum fsl_micfil_hwvad_zcdauto_enum =
11270+	SOC_ENUM_SINGLE_EXT(ARRAY_SIZE(micfil_hwvad_zcdauto_enable),
11271+			    micfil_hwvad_zcd_enable);
11272+static const struct soc_enum fsl_micfil_hwvad_ndec_enum =
11273+	SOC_ENUM_SINGLE(REG_MICFIL_VAD0_NCONFIG,
11274+			MICFIL_VAD0_NCONFIG_NOREN_SHIFT,
11275+			ARRAY_SIZE(micfil_hwvad_noise_decimation),
11276+			micfil_hwvad_noise_decimation);
11277+static const struct soc_enum fsl_micfil_hwvad_rate_enum =
11278+	SOC_ENUM_SINGLE_EXT(ARRAY_SIZE(micfil_hwvad_rate),
11279+			    micfil_hwvad_rate);
11280+static const struct soc_enum fsl_micfil_clk_src_enum =
11281+	SOC_ENUM_SINGLE_EXT(ARRAY_SIZE(micfil_clk_src_texts),
11282+			    micfil_clk_src_texts);
11283+static const struct soc_enum fsl_micfil_dc_remover_enum =
11284+	SOC_ENUM_SINGLE_EXT(ARRAY_SIZE(micfil_dc_remover_texts),
11285+			    micfil_dc_remover_texts);
11286+
11287+static int micfil_put_clk_src(struct snd_kcontrol *kcontrol,
11288+			      struct snd_ctl_elem_value *ucontrol)
11289+{
11290+	struct snd_soc_component *comp = snd_kcontrol_chip(kcontrol);
11291+	struct soc_enum *e = (struct soc_enum *)kcontrol->private_value;
11292+	unsigned int *item = ucontrol->value.enumerated.item;
11293+	struct fsl_micfil *micfil = snd_soc_component_get_drvdata(comp);
11294+	int val = snd_soc_enum_item_to_val(e, item[0]);
11295+
11296+	micfil->clk_src_id = val;
11297+
11298+	return 0;
11299+}
11300+
11301+static int micfil_get_clk_src(struct snd_kcontrol *kcontrol,
11302+			      struct snd_ctl_elem_value *ucontrol)
11303+{
11304+	struct snd_soc_component *comp = snd_kcontrol_chip(kcontrol);
11305+	struct fsl_micfil *micfil = snd_soc_component_get_drvdata(comp);
11306+
11307+	ucontrol->value.enumerated.item[0] = micfil->clk_src_id;
11308+
11309+	return 0;
11310+}
11311+
11312+static int micfil_put_dc_remover_state(struct snd_kcontrol *kcontrol,
11313+				       struct snd_ctl_elem_value *ucontrol)
11314+{
11315+	struct snd_soc_component *comp = snd_kcontrol_chip(kcontrol);
11316+	struct soc_enum *e = (struct soc_enum *)kcontrol->private_value;
11317+	struct fsl_micfil *micfil = snd_soc_component_get_drvdata(comp);
11318+	unsigned int *item = ucontrol->value.enumerated.item;
11319+	int val = snd_soc_enum_item_to_val(e, item[0]);
11320+	int i = 0, ret = 0;
11321+	u32 reg_val = 0;
11322+
11323+	if (val < 0 || val > 3)
11324+		return -EINVAL;
11325+
11326+	micfil->dc_remover = val;
11327+
11328+	/* Calculate total value for all channels */
11329+	for (i = 0; i < 8; i++)
11330+		reg_val |= MICFIL_DC_MODE(val, i);
11331+
11332+	/* Update DC Remover mode for all channels */
11333+	ret = snd_soc_component_update_bits(comp, REG_MICFIL_DC_CTRL,
11334+					    MICFIL_DC_CTRL_MASK, reg_val);
11335+	if (ret < 0)
11336+		return ret;
11337+
11338+	return 0;
11339+}
11340+
11341+static int micfil_get_dc_remover_state(struct snd_kcontrol *kcontrol,
11342+				       struct snd_ctl_elem_value *ucontrol)
11343+{
11344+	struct snd_soc_component *comp = snd_kcontrol_chip(kcontrol);
11345+	struct fsl_micfil *micfil = snd_soc_component_get_drvdata(comp);
11346+
11347+	ucontrol->value.enumerated.item[0] = micfil->dc_remover;
11348+
11349+	return 0;
11350+}
11351+
11352+static int hwvad_put_init_mode(struct snd_kcontrol *kcontrol,
11353+			       struct snd_ctl_elem_value *ucontrol)
11354+{
11355+	struct snd_soc_component *comp = snd_kcontrol_chip(kcontrol);
11356+	struct soc_enum *e = (struct soc_enum *)kcontrol->private_value;
11357+	unsigned int *item = ucontrol->value.enumerated.item;
11358+	struct fsl_micfil *micfil = snd_soc_component_get_drvdata(comp);
11359+	int val = snd_soc_enum_item_to_val(e, item[0]);
11360+
11361+	/* 0 - Envelope-based Mode
11362+	 * 1 - Energy-based Mode
11363+	 */
11364+	micfil->vad_init_mode = val;
11365+	return 0;
11366+}
11367+
11368+static int hwvad_get_init_mode(struct snd_kcontrol *kcontrol,
11369+			       struct snd_ctl_elem_value *ucontrol)
11370+{
11371+	struct snd_soc_component *comp = snd_kcontrol_chip(kcontrol);
11372+	struct fsl_micfil *micfil = snd_soc_component_get_drvdata(comp);
11373+
11374+	ucontrol->value.enumerated.item[0] = micfil->vad_init_mode;
11375+
11376+	return 0;
11377+}
11378+
11379+static int hwvad_put_hpf(struct snd_kcontrol *kcontrol,
11380+			 struct snd_ctl_elem_value *ucontrol)
11381+{
11382+	struct snd_soc_component *comp = snd_kcontrol_chip(kcontrol);
11383+	struct soc_enum *e = (struct soc_enum *)kcontrol->private_value;
11384+	unsigned int *item = ucontrol->value.enumerated.item;
11385+	struct fsl_micfil *micfil = snd_soc_component_get_drvdata(comp);
11386+	int val = snd_soc_enum_item_to_val(e, item[0]);
11387+
11388+	/* 00 - HPF Bypass
11389+	 * 01 - Cut-off frequency 1750Hz
11390+	 * 10 - Cut-off frequency 215Hz
11391+	 * 11 - Cut-off frequency 102Hz
11392+	 */
11393+	micfil->vad_hpf = val;
11394+
11395+	return 0;
11396+}
11397+
11398+static int hwvad_get_hpf(struct snd_kcontrol *kcontrol,
11399+			 struct snd_ctl_elem_value *ucontrol)
11400+{
11401+	struct snd_soc_component *comp = snd_kcontrol_chip(kcontrol);
11402+	struct fsl_micfil *micfil = snd_soc_component_get_drvdata(comp);
11403+
11404+	ucontrol->value.enumerated.item[0] = micfil->vad_hpf;
11405+
11406+	return 0;
11407+}
11408+
11409+static int hwvad_put_zcd_en(struct snd_kcontrol *kcontrol,
11410+			    struct snd_ctl_elem_value *ucontrol)
11411+{
11412+	struct snd_soc_component *comp = snd_kcontrol_chip(kcontrol);
11413+	struct soc_enum *e = (struct soc_enum *)kcontrol->private_value;
11414+	unsigned int *item = ucontrol->value.enumerated.item;
11415+	struct fsl_micfil *micfil = snd_soc_component_get_drvdata(comp);
11416+	int val = snd_soc_enum_item_to_val(e, item[0]);
11417+
11418+	micfil->vad_zcd_en = val;
11419+
11420+	return 0;
11421+}
11422+
11423+static int hwvad_get_zcd_en(struct snd_kcontrol *kcontrol,
11424+			    struct snd_ctl_elem_value *ucontrol)
11425+{
11426+	struct snd_soc_component *comp = snd_kcontrol_chip(kcontrol);
11427+	struct fsl_micfil *micfil = snd_soc_component_get_drvdata(comp);
11428+
11429+	ucontrol->value.enumerated.item[0] = micfil->vad_zcd_en;
11430+
11431+	return 0;
11432+}
11433+
11434+static int hwvad_put_rate(struct snd_kcontrol *kcontrol,
11435+			  struct snd_ctl_elem_value *ucontrol)
11436+{
11437+	struct snd_soc_component *comp = snd_kcontrol_chip(kcontrol);
11438+	struct soc_enum *e = (struct soc_enum *)kcontrol->private_value;
11439+	unsigned int *item = ucontrol->value.enumerated.item;
11440+	struct fsl_micfil *micfil = snd_soc_component_get_drvdata(comp);
11441+	int val = snd_soc_enum_item_to_val(e, item[0]);
11442+
11443+	micfil->vad_rate_index = val;
11444+
11445+	return 0;
11446+}
11447+
11448+static int hwvad_get_rate(struct snd_kcontrol *kcontrol,
11449+			  struct snd_ctl_elem_value *ucontrol)
11450+{
11451+	struct snd_soc_component *comp = snd_kcontrol_chip(kcontrol);
11452+	struct fsl_micfil *micfil = snd_soc_component_get_drvdata(comp);
11453+
11454+	ucontrol->value.enumerated.item[0] = micfil->vad_rate_index;
11455+
11456+	return 0;
11457+}
11458+
11459+static int hwvad_put_zcd_auto(struct snd_kcontrol *kcontrol,
11460+			      struct snd_ctl_elem_value *ucontrol)
11461+{
11462+	struct snd_soc_component *comp = snd_kcontrol_chip(kcontrol);
11463+	struct soc_enum *e = (struct soc_enum *)kcontrol->private_value;
11464+	unsigned int *item = ucontrol->value.enumerated.item;
11465+	struct fsl_micfil *micfil = snd_soc_component_get_drvdata(comp);
11466+	int val = snd_soc_enum_item_to_val(e, item[0]);
11467+
11468+	micfil->vad_zcd_auto = val;
11469+
11470+	return 0;
11471+}
11472+
11473+static int hwvad_get_zcd_auto(struct snd_kcontrol *kcontrol,
11474+			      struct snd_ctl_elem_value *ucontrol)
11475+{
11476+	struct snd_soc_component *comp = snd_kcontrol_chip(kcontrol);
11477+	struct fsl_micfil *micfil = snd_soc_component_get_drvdata(comp);
11478+
11479+	ucontrol->value.enumerated.item[0] = micfil->vad_zcd_auto;
11480+
11481+	return 0;
11482+}
11483+
11484+static int gain_info(struct snd_kcontrol *kcontrol,
11485+		     struct snd_ctl_elem_info *uinfo)
11486+{
11487+	uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
11488+	uinfo->count = 1;
11489+	uinfo->value.integer.min = 0;
11490+	uinfo->value.integer.max = 0xf;
11491+
11492+	return 0;
11493+}
11494+
11495+static int hwvad_put_input_gain(struct snd_kcontrol *kcontrol,
11496+				struct snd_ctl_elem_value *ucontrol)
11497+{
11498+	struct snd_soc_component *comp = snd_kcontrol_chip(kcontrol);
11499+	struct fsl_micfil *micfil = snd_soc_component_get_drvdata(comp);
11500+
11501+	micfil->vad_input_gain = ucontrol->value.integer.value[0];
11502+
11503+	return 0;
11504+}
11505+
11506+static int hwvad_get_input_gain(struct snd_kcontrol *kcontrol,
11507+				struct snd_ctl_elem_value *ucontrol)
11508+{
11509+	struct snd_soc_component *comp = snd_kcontrol_chip(kcontrol);
11510+	struct fsl_micfil *micfil = snd_soc_component_get_drvdata(comp);
11511+
11512+	ucontrol->value.enumerated.item[0] = micfil->vad_input_gain;
11513+
11514+	return 0;
11515+}
11516+
11517+static int hwvad_put_sound_gain(struct snd_kcontrol *kcontrol,
11518+				struct snd_ctl_elem_value *ucontrol)
11519+{
11520+	struct snd_soc_component *comp = snd_kcontrol_chip(kcontrol);
11521+	struct fsl_micfil *micfil = snd_soc_component_get_drvdata(comp);
11522+
11523+	micfil->vad_sound_gain = ucontrol->value.integer.value[0];
11524+
11525+	return 0;
11526+}
11527+
11528+static int hwvad_get_sound_gain(struct snd_kcontrol *kcontrol,
11529+				struct snd_ctl_elem_value *ucontrol)
11530+{
11531+	struct snd_soc_component *comp = snd_kcontrol_chip(kcontrol);
11532+	struct fsl_micfil *micfil = snd_soc_component_get_drvdata(comp);
11533+
11534+	ucontrol->value.enumerated.item[0] = micfil->vad_sound_gain;
11535+
11536+	return 0;
11537+}
11538+
11539+static int hwvad_put_noise_gain(struct snd_kcontrol *kcontrol,
11540+				struct snd_ctl_elem_value *ucontrol)
11541+{
11542+	struct snd_soc_component *comp = snd_kcontrol_chip(kcontrol);
11543+	struct fsl_micfil *micfil = snd_soc_component_get_drvdata(comp);
11544+
11545+	micfil->vad_noise_gain = ucontrol->value.integer.value[0];
11546+
11547+	return 0;
11548+}
11549+
11550+static int hwvad_get_noise_gain(struct snd_kcontrol *kcontrol,
11551+				struct snd_ctl_elem_value *ucontrol)
11552+{
11553+	struct snd_soc_component *comp = snd_kcontrol_chip(kcontrol);
11554+	struct fsl_micfil *micfil = snd_soc_component_get_drvdata(comp);
11555+
11556+	ucontrol->value.enumerated.item[0] = micfil->vad_noise_gain;
11557+
11558+	return 0;
11559+}
11560+
11561+static int hwvad_framet_info(struct snd_kcontrol *kcontrol,
11562+			     struct snd_ctl_elem_info *uinfo)
11563+{
11564+	uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
11565+	uinfo->count = 1;
11566+	uinfo->value.integer.min = 1;
11567+	uinfo->value.integer.max = 64;
11568+
11569+	return 0;
11570+}
11571+
11572+static int hwvad_put_frame_time(struct snd_kcontrol *kcontrol,
11573+				struct snd_ctl_elem_value *ucontrol)
11574+{
11575+	struct snd_soc_component *comp = snd_kcontrol_chip(kcontrol);
11576+	struct fsl_micfil *micfil = snd_soc_component_get_drvdata(comp);
11577+
11578+	micfil->vad_frame_time = ucontrol->value.integer.value[0];
11579+
11580+	return 0;
11581+}
11582+
11583+static int hwvad_get_frame_time(struct snd_kcontrol *kcontrol,
11584+				struct snd_ctl_elem_value *ucontrol)
11585+{
11586+	struct snd_soc_component *comp = snd_kcontrol_chip(kcontrol);
11587+	struct fsl_micfil *micfil = snd_soc_component_get_drvdata(comp);
11588+
11589+	ucontrol->value.enumerated.item[0] = micfil->vad_frame_time;
11590+
11591+	return 0;
11592+}
11593+
11594+static int hwvad_initt_info(struct snd_kcontrol *kcontrol,
11595+			    struct snd_ctl_elem_info *uinfo)
11596+{
11597+	uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
11598+	uinfo->count = 1;
11599+	uinfo->value.integer.min = 1;
11600+	uinfo->value.integer.max = 32;
11601+
11602+	return 0;
11603+}
11604+
11605+static int hwvad_put_init_time(struct snd_kcontrol *kcontrol,
11606+			       struct snd_ctl_elem_value *ucontrol)
11607+{
11608+	struct snd_soc_component *comp = snd_kcontrol_chip(kcontrol);
11609+	struct fsl_micfil *micfil = snd_soc_component_get_drvdata(comp);
11610+
11611+	micfil->vad_init_time = ucontrol->value.integer.value[0];
11612+
11613+	return 0;
11614+}
11615+
11616+static int hwvad_get_init_time(struct snd_kcontrol *kcontrol,
11617+			       struct snd_ctl_elem_value *ucontrol)
11618+{
11619+	struct snd_soc_component *comp = snd_kcontrol_chip(kcontrol);
11620+	struct fsl_micfil *micfil = snd_soc_component_get_drvdata(comp);
11621+
11622+	ucontrol->value.enumerated.item[0] = micfil->vad_init_time;
11623+
11624+	return 0;
11625+}
11626+
11627+static int hwvad_nfiladj_info(struct snd_kcontrol *kcontrol,
11628+			      struct snd_ctl_elem_info *uinfo)
11629+{
11630+	uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
11631+	uinfo->count = 1;
11632+	uinfo->value.integer.min = 1;
11633+	uinfo->value.integer.max = 32;
11634+
11635+	return 0;
11636+}
11637+
11638+static int hwvad_put_nfil_adjust(struct snd_kcontrol *kcontrol,
11639+				 struct snd_ctl_elem_value *ucontrol)
11640+{
11641+	struct snd_soc_component *comp = snd_kcontrol_chip(kcontrol);
11642+	struct fsl_micfil *micfil = snd_soc_component_get_drvdata(comp);
11643+
11644+	micfil->vad_nfil_adjust = ucontrol->value.integer.value[0];
11645+
11646+	return 0;
11647+}
11648+
11649+static int hwvad_get_nfil_adjust(struct snd_kcontrol *kcontrol,
11650+				 struct snd_ctl_elem_value *ucontrol)
11651+{
11652+	struct snd_soc_component *comp = snd_kcontrol_chip(kcontrol);
11653+	struct fsl_micfil *micfil = snd_soc_component_get_drvdata(comp);
11654+
11655+	ucontrol->value.enumerated.item[0] = micfil->vad_nfil_adjust;
11656+
11657+	return 0;
11658+}
11659+
11660+static int hwvad_zcdth_info(struct snd_kcontrol *kcontrol,
11661+			    struct snd_ctl_elem_info *uinfo)
11662+{
11663+	uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
11664+	uinfo->count = 1;
11665+	uinfo->value.integer.min = 1;
11666+	uinfo->value.integer.max = 1024;
11667+
11668+	return 0;
11669+}
11670+
11671+static int hwvad_put_zcd_th(struct snd_kcontrol *kcontrol,
11672+			    struct snd_ctl_elem_value *ucontrol)
11673+{
11674+	struct snd_soc_component *comp = snd_kcontrol_chip(kcontrol);
11675+	struct fsl_micfil *micfil = snd_soc_component_get_drvdata(comp);
11676+
11677+	micfil->vad_zcd_th = ucontrol->value.integer.value[0];
11678+
11679+	return 0;
11680+}
11681+
11682+static int hwvad_get_zcd_th(struct snd_kcontrol *kcontrol,
11683+			    struct snd_ctl_elem_value *ucontrol)
11684+{
11685+	struct snd_soc_component *comp = snd_kcontrol_chip(kcontrol);
11686+	struct fsl_micfil *micfil = snd_soc_component_get_drvdata(comp);
11687+
11688+	ucontrol->value.enumerated.item[0] = micfil->vad_zcd_th;
11689+
11690+	return 0;
11691+}
11692+
11693+static int hwvad_zcdadj_info(struct snd_kcontrol *kcontrol,
11694+			     struct snd_ctl_elem_info *uinfo)
11695+{
11696+	uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
11697+	uinfo->count = 1;
11698+	uinfo->value.integer.min = 1;
11699+	uinfo->value.integer.max = 16;
11700+
11701+	return 0;
11702+}
11703+
11704+static int hwvad_put_zcd_adj(struct snd_kcontrol *kcontrol,
11705+			     struct snd_ctl_elem_value *ucontrol)
11706+{
11707+	struct snd_soc_component *comp = snd_kcontrol_chip(kcontrol);
11708+	struct fsl_micfil *micfil = snd_soc_component_get_drvdata(comp);
11709+
11710+	micfil->vad_zcd_adj = ucontrol->value.integer.value[0];
11711+
11712+	return 0;
11713+}
11714+
11715+static int hwvad_get_zcd_adj(struct snd_kcontrol *kcontrol,
11716+			     struct snd_ctl_elem_value *ucontrol)
11717+{
11718+	struct snd_soc_component *comp = snd_kcontrol_chip(kcontrol);
11719+	struct fsl_micfil *micfil = snd_soc_component_get_drvdata(comp);
11720+
11721+	ucontrol->value.enumerated.item[0] = micfil->vad_zcd_adj;
11722+
11723+	return 0;
11724+}
11725
11726 static DECLARE_TLV_DB_SCALE(gain_tlv, 0, 100, 0);
11727
11728@@ -105,8 +660,107 @@ static const struct snd_kcontrol_new fsl_micfil_snd_controls[] = {
11729 	SOC_ENUM_EXT("MICFIL Quality Select",
11730 		     fsl_micfil_quality_enum,
11731 		     snd_soc_get_enum_double, snd_soc_put_enum_double),
11732+	SOC_ENUM_EXT("HWVAD Initialization Mode",
11733+		     fsl_micfil_hwvad_init_mode_enum,
11734+		     hwvad_get_init_mode, hwvad_put_init_mode),
11735+	SOC_ENUM_EXT("HWVAD High-Pass Filter",
11736+		     fsl_micfil_hwvad_hpf_enum,
11737+		     hwvad_get_hpf, hwvad_put_hpf),
11738+	SOC_ENUM_EXT("HWVAD Zero-Crossing Detector Enable",
11739+		     fsl_micfil_hwvad_zcd_enum,
11740+		     hwvad_get_zcd_en, hwvad_put_zcd_en),
11741+	SOC_ENUM_EXT("HWVAD Zero-Crossing Detector Auto Threshold",
11742+		     fsl_micfil_hwvad_zcdauto_enum,
11743+		     hwvad_get_zcd_auto, hwvad_put_zcd_auto),
11744+	SOC_ENUM_EXT("HWVAD Noise OR Enable",
11745+		     fsl_micfil_hwvad_ndec_enum,
11746+		     snd_soc_get_enum_double, snd_soc_put_enum_double),
11747+	SOC_ENUM_EXT("HWVAD Sampling Rate",
11748+		     fsl_micfil_hwvad_rate_enum,
11749+		     hwvad_get_rate, hwvad_put_rate),
11750+	SOC_ENUM_EXT("Clock Source",
11751+		     fsl_micfil_clk_src_enum,
11752+		     micfil_get_clk_src, micfil_put_clk_src),
11753+	SOC_ENUM_EXT("MICFIL DC Remover Control", fsl_micfil_dc_remover_enum,
11754+		     micfil_get_dc_remover_state, micfil_put_dc_remover_state),
11755+	{
11756+		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
11757+		.name = "HWVAD Input Gain",
11758+		.access = SNDRV_CTL_ELEM_ACCESS_READ |
11759+			  SNDRV_CTL_ELEM_ACCESS_WRITE,
11760+		.info = gain_info,
11761+		.get = hwvad_get_input_gain,
11762+		.put = hwvad_put_input_gain,
11763+	},
11764+	{
11765+		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
11766+		.name = "HWVAD Sound Gain",
11767+		.access = SNDRV_CTL_ELEM_ACCESS_READ |
11768+			  SNDRV_CTL_ELEM_ACCESS_WRITE,
11769+		.info = gain_info,
11770+		.get = hwvad_get_sound_gain,
11771+		.put = hwvad_put_sound_gain,
11772+	},
11773+	{
11774+		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
11775+		.name = "HWVAD Noise Gain",
11776+		.access = SNDRV_CTL_ELEM_ACCESS_READ |
11777+			  SNDRV_CTL_ELEM_ACCESS_WRITE,
11778+		.info = gain_info,
11779+		.get = hwvad_get_noise_gain,
11780+		.put = hwvad_put_noise_gain,
11781+	},
11782+	{
11783+		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
11784+		.name = "HWVAD Detector Frame Time",
11785+		.access = SNDRV_CTL_ELEM_ACCESS_READ |
11786+			  SNDRV_CTL_ELEM_ACCESS_WRITE,
11787+		.info = hwvad_framet_info,
11788+		.get = hwvad_get_frame_time,
11789+		.put = hwvad_put_frame_time,
11790+	},
11791+	{
11792+		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
11793+		.name = "HWVAD Detector Initialization Time",
11794+		.access = SNDRV_CTL_ELEM_ACCESS_READ |
11795+			  SNDRV_CTL_ELEM_ACCESS_WRITE,
11796+		.info = hwvad_initt_info,
11797+		.get = hwvad_get_init_time,
11798+		.put = hwvad_put_init_time,
11799+	},
11800+	{
11801+		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
11802+		.name = "HWVAD Noise Filter Adjustment",
11803+		.access = SNDRV_CTL_ELEM_ACCESS_READ |
11804+			  SNDRV_CTL_ELEM_ACCESS_WRITE,
11805+		.info = hwvad_nfiladj_info,
11806+		.get = hwvad_get_nfil_adjust,
11807+		.put = hwvad_put_nfil_adjust,
11808+	},
11809+	{
11810+		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
11811+		.name = "HWVAD Zero-Crossing Detector Threshold",
11812+		.access = SNDRV_CTL_ELEM_ACCESS_READ |
11813+			  SNDRV_CTL_ELEM_ACCESS_WRITE,
11814+		.info = hwvad_zcdth_info,
11815+		.get = hwvad_get_zcd_th,
11816+		.put = hwvad_put_zcd_th,
11817+	},
11818+	{
11819+		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
11820+		.name = "HWVAD Zero-Crossing Detector Adjustment",
11821+		.access = SNDRV_CTL_ELEM_ACCESS_READ |
11822+			  SNDRV_CTL_ELEM_ACCESS_WRITE,
11823+		.info = hwvad_zcdadj_info,
11824+		.get = hwvad_get_zcd_adj,
11825+		.put = hwvad_put_zcd_adj,
11826+	},
11827+
11828 };
11829
11830+static int disable_hwvad(struct device *dev, bool sync);
11831+
11832+
11833 static inline int get_pdm_clk(struct fsl_micfil *micfil,
11834 			      unsigned int rate)
11835 {
11836@@ -157,55 +811,629 @@ static inline int get_clk_div(struct fsl_micfil *micfil,
11837
11838 	mclk_rate = clk_get_rate(micfil->mclk);
11839
11840-	clk_div = mclk_rate / (get_pdm_clk(micfil, rate) * 2);
11841+	clk_div = mclk_rate / (get_pdm_clk(micfil, rate) * 2);
11842+
11843+	return clk_div;
11844+}
11845+
11846+/* The SRES is a self-negated bit which provides the CPU with the
11847+ * capability to initialize the PDM Interface module through the
11848+ * slave-bus interface. This bit always reads as zero, and this
11849+ * bit is only effective when MDIS is cleared
11850+ */
11851+static int fsl_micfil_reset(struct device *dev)
11852+{
11853+	struct fsl_micfil *micfil = dev_get_drvdata(dev);
11854+	int ret;
11855+
11856+	ret = regmap_update_bits(micfil->regmap,
11857+				 REG_MICFIL_CTRL1,
11858+				 MICFIL_CTRL1_MDIS_MASK,
11859+				 0);
11860+	if (ret) {
11861+		dev_err(dev, "failed to clear MDIS bit %d\n", ret);
11862+		return ret;
11863+	}
11864+
11865+	ret = regmap_update_bits(micfil->regmap,
11866+				 REG_MICFIL_CTRL1,
11867+				 MICFIL_CTRL1_SRES_MASK,
11868+				 MICFIL_CTRL1_SRES);
11869+	if (ret) {
11870+		dev_err(dev, "failed to reset MICFIL: %d\n", ret);
11871+		return ret;
11872+	}
11873+
11874+	/* w1c */
11875+	regmap_write_bits(micfil->regmap, REG_MICFIL_STAT, 0xFF, 0xFF);
11876+
11877+	return 0;
11878+}
11879+
11880+/* enable/disable hwvad interrupts */
11881+static int configure_hwvad_interrupts(struct device *dev,
11882+				      int enable)
11883+{
11884+	struct fsl_micfil *micfil = dev_get_drvdata(dev);
11885+	int ret;
11886+	u32 vadie_reg = enable ? MICFIL_VAD0_CTRL1_IE : 0;
11887+	u32 vaderie_reg = enable ? MICFIL_VAD0_CTRL1_ERIE : 0;
11888+
11889+	/* Voice Activity Detector Error Interruption Enable */
11890+	ret = regmap_update_bits(micfil->regmap, REG_MICFIL_VAD0_CTRL1,
11891+				 MICFIL_VAD0_CTRL1_ERIE_MASK,
11892+				 vaderie_reg);
11893+	if (ret) {
11894+		dev_err(dev,
11895+			"Failed to set/clear VADERIE in CTRL1_VAD0 [%d]\n",
11896+			ret);
11897+		return ret;
11898+	}
11899+
11900+	/* Voice Activity Detector Interruption Enable */
11901+	ret = regmap_update_bits(micfil->regmap, REG_MICFIL_VAD0_CTRL1,
11902+				 MICFIL_VAD0_CTRL1_IE_MASK,
11903+				 vadie_reg);
11904+	if (ret) {
11905+		dev_err(dev,
11906+			"Failed to set/clear VADIE in CTRL1_VAD0 [%d]\n",
11907+			ret);
11908+		return ret;
11909+	}
11910+
11911+	return 0;
11912+}
11913+
11914+static int init_hwvad_internal_filters(struct device *dev)
11915+{
11916+	struct fsl_micfil *micfil = dev_get_drvdata(dev);
11917+	int ret;
11918+
11919+	/* Voice Activity Detector Internal Filters Initialization*/
11920+	ret = regmap_update_bits(micfil->regmap, REG_MICFIL_VAD0_CTRL1,
11921+				 MICFIL_VAD0_CTRL1_ST10_MASK,
11922+				 MICFIL_VAD0_CTRL1_ST10);
11923+	if (ret) {
11924+		dev_err(dev,
11925+			"Failed to set VADST10 in CTRL1_VAD0 [%d]\n",
11926+			ret);
11927+		return ret;
11928+	}
11929+
11930+	/* sleep for 100ms - it should be enough for bit to stay
11931+	 * pulsed for more than 2 cycles
11932+	 */
11933+	mdelay(MICFIL_SLEEP);
11934+
11935+	/* Voice Activity Detector Enabled */
11936+	ret = regmap_update_bits(micfil->regmap, REG_MICFIL_VAD0_CTRL1,
11937+				 MICFIL_VAD0_CTRL1_ST10_MASK,
11938+				 0);
11939+	if (ret) {
11940+		dev_err(dev,
11941+			"Failed to clear VADST10 in CTRL1_VAD0 [%d]\n",
11942+			ret);
11943+		return ret;
11944+	}
11945+	return 0;
11946+}
11947+
11948+/* Zero-Crossing Detector Initialization
11949+ * Optionally a Zero-Crossing Detection block (ZCD) could
11950+ * be enabled to avoid low energy voiced speech be missed,
11951+ * improving the voice detection performance.
11952+ * See Section 8.4.3
11953+ */
11954+static int __maybe_unused init_zcd(struct device *dev)
11955+{
11956+	struct fsl_micfil *micfil = dev_get_drvdata(dev);
11957+	int ret;
11958+
11959+	/* exit if zcd is not enabled from userspace */
11960+	if (!micfil->vad_zcd_en)
11961+		return 0;
11962+
11963+	if (micfil->vad_zcd_auto) {
11964+		/* Zero-Crossing Detector Adjustment */
11965+		ret = regmap_update_bits(micfil->regmap, REG_MICFIL_VAD0_ZCD,
11966+					 MICFIL_VAD0_ZCD_ZCDADJ_MASK,
11967+					 micfil->vad_zcd_adj);
11968+		if (ret) {
11969+			dev_err(dev,
11970+				"Failed to set ZCDADJ in ZCD_VAD0 [%d]\n",
11971+				ret);
11972+			return ret;
11973+		}
11974+	}
11975+
11976+	/* Zero-Crossing Detector Threshold */
11977+	ret = regmap_update_bits(micfil->regmap, REG_MICFIL_VAD0_ZCD,
11978+				 MICFIL_VAD0_ZCD_ZCDTH_MASK,
11979+				 MICFIL_VAD0_ZCD_ZCDTH(micfil->vad_zcd_th));
11980+	if (ret) {
11981+		dev_err(dev, "Failed to set ZCDTH in ZCD_VAD0 [%d]\n", ret);
11982+		return ret;
11983+	}
11984+
11985+	/* Zero-Crossing Detector AND Behavior */
11986+	ret = regmap_update_bits(micfil->regmap, REG_MICFIL_VAD0_ZCD,
11987+				 MICFIL_VAD0_ZCD_ZCDAND_MASK,
11988+				 MICFIL_HWVAD_ZCDAND);
11989+	if (ret) {
11990+		dev_err(dev, "Failed to set ZCDAND in ZCD_VAD0 [%d]\n", ret);
11991+		return ret;
11992+	}
11993+
11994+	/* Zero-Crossing Detector Automatic Threshold */
11995+	ret = regmap_update_bits(micfil->regmap, REG_MICFIL_VAD0_ZCD,
11996+				 MICFIL_VAD0_ZCD_ZCDAUT_MASK,
11997+				 micfil->vad_zcd_auto);
11998+	if (ret) {
11999+		dev_err(dev,
12000+			"Failed to set/clear ZCDAUT in ZCD_VAD0 [%d]\n",
12001+			ret);
12002+		return ret;
12003+	}
12004+
12005+	/* Zero-Crossing Detector Enable */
12006+	ret = regmap_update_bits(micfil->regmap, REG_MICFIL_VAD0_ZCD,
12007+				 MICFIL_VAD0_ZCD_ZCDEN_MASK,
12008+				 MICFIL_VAD0_ZCD_ZCDEN);
12009+	if (ret) {
12010+		dev_err(dev, "Failed to set ZCDEN in ZCD_VAD0 [%d]\n", ret);
12011+		return ret;
12012+	}
12013+
12014+	return 0;
12015+}
12016+
12017+/* Configuration done only in energy-based initialization mode */
12018+static int init_hwvad_energy_mode(struct device *dev)
12019+{
12020+	struct fsl_micfil *micfil = dev_get_drvdata(dev);
12021+	int ret, i;
12022+	u32 stat;
12023+	u32 flag;
12024+
12025+	dev_info(dev, "Energy-based mode initialization\n");
12026+
12027+	/* Voice Activity Detector Reset */
12028+	ret = regmap_update_bits(micfil->regmap, REG_MICFIL_VAD0_CTRL1,
12029+				 MICFIL_VAD0_CTRL1_RST_SHIFT,
12030+				 MICFIL_VAD0_CTRL1_RST);
12031+	if (ret) {
12032+		dev_err(dev, "Failed to set VADRST in CTRL1_VAD0 [%d]\n", ret);
12033+		return ret;
12034+	}
12035+
12036+	/* Voice Activity Detector Enabled */
12037+	ret = regmap_update_bits(micfil->regmap, REG_MICFIL_VAD0_CTRL1,
12038+				 MICFIL_VAD0_CTRL1_EN_MASK,
12039+				 MICFIL_VAD0_CTRL1_EN);
12040+	if (ret) {
12041+		dev_err(dev, "Failed to set VADEN in CTRL1_VAD0 [%d]\n", ret);
12042+		return ret;
12043+	}
12044+
12045+	/* it would be a good idea to wait some time before VADEN
12046+	 * is set
12047+	 */
12048+	mdelay(5 * MICFIL_SLEEP);
12049+
12050+	/* Enable Interrupts */
12051+	ret = configure_hwvad_interrupts(dev, 1);
12052+
12053+	/* Initialize Zero Crossing Detector */
12054+	ret = init_zcd(dev);
12055+	if (ret)
12056+		return ret;
12057+
12058+	/* Enable MICFIL module */
12059+	ret = regmap_update_bits(micfil->regmap, REG_MICFIL_CTRL1,
12060+				 MICFIL_CTRL1_PDMIEN_MASK,
12061+				 MICFIL_CTRL1_PDMIEN);
12062+	if (ret) {
12063+		dev_err(dev, "failed to enable the module\n");
12064+		return ret;
12065+	}
12066+
12067+	/* Wait for INITF to be asserted */
12068+	for (i = 0; i < MICFIL_MAX_RETRY; i++) {
12069+		ret = regmap_read(micfil->regmap, REG_MICFIL_VAD0_STAT, &stat);
12070+		if (ret) {
12071+			dev_err(dev, "failed to read register %d\n",
12072+				REG_MICFIL_VAD0_STAT);
12073+			return ret;
12074+		}
12075+
12076+		flag = (stat & MICFIL_VAD0_STAT_INITF_MASK);
12077+		if (flag == 0)
12078+			break;
12079+
12080+		mdelay(MICFIL_SLEEP);
12081+	}
12082+
12083+	if (i == MICFIL_MAX_RETRY) {
12084+		dev_err(dev, "initf not asserted. Failed to init hwvad\n");
12085+		return -EBUSY;
12086+	}
12087+
12088+	/* Initialize Internal Filters */
12089+	ret = init_hwvad_internal_filters(dev);
12090+	if (ret)
12091+		return ret;
12092+
12093+	return ret;
12094+}
12095+
12096+/* Configuration done only in envelope-based initialization mode */
12097+static int init_hwvad_envelope_mode(struct device *dev)
12098+{
12099+	struct fsl_micfil *micfil = dev_get_drvdata(dev);
12100+	int ret, i;
12101+	u32 stat;
12102+	u32 flag;
12103+
12104+	/* Frame energy disable */
12105+	ret = regmap_update_bits(micfil->regmap, REG_MICFIL_VAD0_CTRL2,
12106+				 MICFIL_VAD0_CTRL2_FRENDIS_MASK,
12107+				 MICFIL_VAD0_CTRL2_FRENDIS);
12108+	if (ret) {
12109+		dev_err(dev, "Failed to set FRENDIS in CTRL2_VAD0 [%d]\n", ret);
12110+		return ret;
12111+	}
12112+
12113+	/* Enable pre-filter Noise & Signal */
12114+	ret = regmap_update_bits(micfil->regmap, REG_MICFIL_VAD0_CTRL2,
12115+				 MICFIL_VAD0_CTRL2_PREFEN_MASK,
12116+				 MICFIL_VAD0_CTRL2_PREFEN);
12117+	if (ret) {
12118+		dev_err(dev, "Failed to set PREFEN in CTRL2_VAD0 [%d]\n", ret);
12119+		return ret;
12120+	}
12121+
12122+	/* Enable Signal Filter */
12123+	ret = regmap_update_bits(micfil->regmap, REG_MICFIL_VAD0_SCONFIG,
12124+				 MICFIL_VAD0_SCONFIG_SFILEN_MASK,
12125+				 MICFIL_VAD0_SCONFIG_SFILEN);
12126+	if (ret) {
12127+		dev_err(dev,
12128+			"Failed to set SFILEN in SCONFIG_VAD0 [%d]\n",
12129+			ret);
12130+		return ret;
12131+	}
12132+
12133+	/* Signal Maximum Enable */
12134+	ret = regmap_update_bits(micfil->regmap, REG_MICFIL_VAD0_SCONFIG,
12135+				 MICFIL_VAD0_SCONFIG_SMAXEN_MASK,
12136+				 MICFIL_VAD0_SCONFIG_SMAXEN);
12137+	if (ret) {
12138+		dev_err(dev,
12139+			"Failed to set SMAXEN in SCONFIG_VAD0 [%d]\n",
12140+			ret);
12141+		return ret;
12142+	}
12143+
12144+	/* Allways enable noise filter, not based on voice activity
12145+	 * information
12146+	 */
12147+	ret = regmap_update_bits(micfil->regmap, REG_MICFIL_VAD0_NCONFIG,
12148+				 MICFIL_VAD0_NCONFIG_NFILAUT_MASK,
12149+				 0);
12150+	if (ret) {
12151+		dev_err(dev,
12152+			"Failed to set NFILAUT in NCONFIG_VAD0 [%d]\n",
12153+			ret);
12154+		return ret;
12155+	}
12156+
12157+	/* Noise Minimum Enable */
12158+	ret = regmap_update_bits(micfil->regmap, REG_MICFIL_VAD0_NCONFIG,
12159+				 MICFIL_VAD0_NCONFIG_NMINEN_MASK,
12160+				 MICFIL_VAD0_NCONFIG_NMINEN);
12161+	if (ret) {
12162+		dev_err(dev,
12163+			"Failed to set NMINEN in NCONFIG_VAD0 [%d]\n",
12164+			ret);
12165+		return ret;
12166+	}
12167+
12168+	/* Noise Decimation Enable */
12169+	ret = regmap_update_bits(micfil->regmap, REG_MICFIL_VAD0_NCONFIG,
12170+				 MICFIL_VAD0_NCONFIG_NDECEN_MASK,
12171+				 MICFIL_VAD0_NCONFIG_NDECEN);
12172+	if (ret) {
12173+		dev_err(dev,
12174+			"Failed to set NDECEN in NCONFIG_VAD0 [%d]\n",
12175+			ret);
12176+		return ret;
12177+	}
12178+
12179+	/* Voice Activity Detector Reset */
12180+	ret = regmap_update_bits(micfil->regmap, REG_MICFIL_VAD0_CTRL1,
12181+				 MICFIL_VAD0_CTRL1_RST_MASK,
12182+				 MICFIL_VAD0_CTRL1_RST);
12183+	if (ret) {
12184+		dev_err(dev, "Failed to set VADRST in CTRL1_VAD0 [%d]\n", ret);
12185+		return ret;
12186+	}
12187+
12188+	/* Initialize Zero Crossing Detector */
12189+	ret = init_zcd(dev);
12190+	if (ret)
12191+		return ret;
12192+
12193+	/* Voice Activity Detector Enabled */
12194+	ret = regmap_update_bits(micfil->regmap, REG_MICFIL_VAD0_CTRL1,
12195+				 MICFIL_VAD0_CTRL1_EN_MASK,
12196+				 MICFIL_VAD0_CTRL1_EN);
12197+	if (ret) {
12198+		dev_err(dev, "Failed to set VADEN in CTRL1_VAD0 [%d]\n", ret);
12199+		return ret;
12200+	}
12201+
12202+	/* Enable MICFIL module */
12203+	ret = regmap_update_bits(micfil->regmap, REG_MICFIL_CTRL1,
12204+				 MICFIL_CTRL1_PDMIEN_MASK,
12205+				 MICFIL_CTRL1_PDMIEN);
12206+	if (ret) {
12207+		dev_err(dev, "failed to enable the module\n");
12208+		return ret;
12209+	}
12210+
12211+	/* it would be a good idea to wait some time before VADEN
12212+	 * is set
12213+	 */
12214+	mdelay(3 * MICFIL_SLEEP);
12215+
12216+	/* Wait for INITF to be asserted */
12217+	for (i = 0; i < MICFIL_MAX_RETRY; i++) {
12218+		ret = regmap_read(micfil->regmap, REG_MICFIL_VAD0_STAT, &stat);
12219+		if (ret) {
12220+			dev_err(dev, "failed to read register %d\n",
12221+				REG_MICFIL_VAD0_STAT);
12222+			return ret;
12223+		}
12224+
12225+		flag = (stat & MICFIL_VAD0_STAT_INITF_MASK);
12226+		if (flag == 0)
12227+			break;
12228+
12229+		mdelay(MICFIL_SLEEP);
12230+	}
12231+
12232+	if (i == MICFIL_MAX_RETRY) {
12233+		dev_err(dev, "initf not asserted. Failed to init hwvad\n");
12234+		return -EBUSY;
12235+	}
12236+
12237+	/* Initialize Internal Filters */
12238+	ret = init_hwvad_internal_filters(dev);
12239+	if (ret)
12240+		return ret;
12241+
12242+	/* Enable interrupts */
12243+	ret = configure_hwvad_interrupts(dev, 1);
12244+	if (ret)
12245+		return ret;
12246+
12247+	return ret;
12248+}
12249+
12250+/* Hardware Voice Active Detection: The HWVAD takes data from the input
12251+ * of a selected PDM microphone to detect if there is any
12252+ * voice activity. When a voice activity is detected, an interrupt could
12253+ * be delivered to the system. Initialization in section 8.4:
12254+ * Can work in two modes:
12255+ *  -> Eneveope-based mode (section 8.4.1)
12256+ *  -> Energy-based mode (section 8.4.2)
12257+ *
12258+ * It is important to remark that the HWVAD detector could be enabled
12259+ * or reset only when the MICFIL isn't running i.e. when the BSY_FIL
12260+ * bit in STAT register is cleared
12261+ */
12262+static int __maybe_unused init_hwvad(struct device *dev)
12263+{
12264+	struct fsl_micfil *micfil = dev_get_drvdata(dev);
12265+	int ret;
12266+	u32 reg_val;
12267+
12268+	/* configure CIC OSR in VADCICOSR */
12269+	ret = regmap_update_bits(micfil->regmap, REG_MICFIL_VAD0_CTRL1,
12270+				 MICFIL_VAD0_CTRL1_CICOSR_MASK,
12271+				 MICFIL_CTRL2_OSR_DEFAULT);
12272+	if (ret) {
12273+		dev_err(dev, "Failed to set CICOSR in CTRL1_VAD0i [%d]\n", ret);
12274+		return ret;
12275+	}
12276+
12277+	/* configure source channel in VADCHSEL */
12278+	reg_val = MICFIL_VAD0_CTRL1_CHSEL(micfil->vad_channel);
12279+	ret = regmap_update_bits(micfil->regmap, REG_MICFIL_VAD0_CTRL1,
12280+				 MICFIL_VAD0_CTRL1_CHSEL_MASK,
12281+				 reg_val);
12282+	if (ret) {
12283+		dev_err(dev, "Failed to set CHSEL in CTRL1_VAD0 [%d]\n", ret);
12284+		return ret;
12285+	}
12286+
12287+	/* configure detector frame time VADFRAMET */
12288+	reg_val = MICFIL_VAD0_CTRL2_FRAMET(micfil->vad_frame_time);
12289+	ret = regmap_update_bits(micfil->regmap, REG_MICFIL_VAD0_CTRL2,
12290+				 MICFIL_VAD0_CTRL2_FRAMET_MASK,
12291+				 reg_val);
12292+	if (ret) {
12293+		dev_err(dev, "Failed to set FRAMET in CTRL2_VAD0 [%d]\n", ret);
12294+		return ret;
12295+	}
12296+
12297+	/* configure initialization time in VADINITT */
12298+	reg_val = MICFIL_VAD0_CTRL1_INITT(micfil->vad_init_time);
12299+	ret = regmap_update_bits(micfil->regmap, REG_MICFIL_VAD0_CTRL1,
12300+				 MICFIL_VAD0_CTRL1_INITT_MASK,
12301+				 reg_val);
12302+	if (ret) {
12303+		dev_err(dev, "Failed to set INITT in CTRL1_VAD0 [%d]\n", ret);
12304+		return ret;
12305+	}
12306+
12307+	/* configure input gain in VADINPGAIN */
12308+	reg_val = MICFIL_VAD0_CTRL2_INPGAIN(micfil->vad_input_gain);
12309+	ret = regmap_update_bits(micfil->regmap, REG_MICFIL_VAD0_CTRL2,
12310+				 MICFIL_VAD0_CTRL2_INPGAIN_MASK,
12311+				 reg_val);
12312+	if (ret) {
12313+		dev_err(dev, "Failed to set INPGAIN in CTRL2_VAD0 [%d]\n", ret);
12314+		return ret;
12315+	}
12316
12317-	return clk_div;
12318-}
12319+	/* configure sound gain in SGAIN */
12320+	reg_val = MICFIL_VAD0_SCONFIG_SGAIN(micfil->vad_sound_gain);
12321+	ret = regmap_update_bits(micfil->regmap, REG_MICFIL_VAD0_SCONFIG,
12322+				 MICFIL_VAD0_SCONFIG_SGAIN_MASK,
12323+				 reg_val);
12324+	if (ret) {
12325+		dev_err(dev, "Failed to set SGAIN in SCONFIG_VAD0 [%d]\n", ret);
12326+		return ret;
12327+	}
12328
12329-/* The SRES is a self-negated bit which provides the CPU with the
12330- * capability to initialize the PDM Interface module through the
12331- * slave-bus interface. This bit always reads as zero, and this
12332- * bit is only effective when MDIS is cleared
12333- */
12334-static int fsl_micfil_reset(struct device *dev)
12335-{
12336-	struct fsl_micfil *micfil = dev_get_drvdata(dev);
12337-	int ret;
12338+	/* configure noise gain in NGAIN */
12339+	reg_val = MICFIL_VAD0_NCONFIG_NGAIN(micfil->vad_noise_gain);
12340+	ret = regmap_update_bits(micfil->regmap, REG_MICFIL_VAD0_NCONFIG,
12341+				 MICFIL_VAD0_NCONFIG_NGAIN_MASK,
12342+				 reg_val);
12343+	if (ret) {
12344+		dev_err(dev, "Failed to set NGAIN in NCONFIG_VAD0 [%d]\n", ret);
12345+		return ret;
12346+	}
12347
12348-	ret = regmap_update_bits(micfil->regmap,
12349-				 REG_MICFIL_CTRL1,
12350-				 MICFIL_CTRL1_MDIS_MASK,
12351-				 0);
12352+	/* configure or clear the VADNFILADJ based on mode */
12353+	reg_val = MICFIL_VAD0_NCONFIG_NFILADJ(micfil->vad_nfil_adjust);
12354+	ret = regmap_update_bits(micfil->regmap, REG_MICFIL_VAD0_NCONFIG,
12355+				 MICFIL_VAD0_NCONFIG_NFILADJ_MASK,
12356+				 reg_val);
12357 	if (ret) {
12358-		dev_err(dev, "failed to clear MDIS bit %d\n", ret);
12359+		dev_err(dev,
12360+			"Failed to set VADNFILADJ in NCONFIG_VAD0 [%d]\n",
12361+			ret);
12362 		return ret;
12363 	}
12364
12365-	ret = regmap_update_bits(micfil->regmap,
12366-				 REG_MICFIL_CTRL1,
12367-				 MICFIL_CTRL1_SRES_MASK,
12368-				 MICFIL_CTRL1_SRES);
12369+	/* enable the high-pass filter in VADHPF */
12370+	reg_val = MICFIL_VAD0_CTRL2_HPF(micfil->vad_hpf);
12371+	ret = regmap_update_bits(micfil->regmap, REG_MICFIL_VAD0_CTRL2,
12372+				 MICFIL_VAD0_CTRL2_HPF_MASK,
12373+				 reg_val);
12374 	if (ret) {
12375-		dev_err(dev, "failed to reset MICFIL: %d\n", ret);
12376+		dev_err(dev, "Failed to set HPF in CTRL2_VAD0 [%d]\n", ret);
12377 		return ret;
12378 	}
12379
12380+	/* envelope-based specific initialization */
12381+	if (micfil->vad_init_mode == MICFIL_HWVAD_ENVELOPE_MODE) {
12382+		ret = init_hwvad_envelope_mode(dev);
12383+		if (ret)
12384+			return ret;
12385+	} else {
12386+		ret = init_hwvad_energy_mode(dev);
12387+		if (ret)
12388+			return ret;
12389+	}
12390+
12391 	return 0;
12392 }
12393
12394-static int fsl_micfil_set_mclk_rate(struct fsl_micfil *micfil,
12395+static inline bool clk_in_list(struct clk *p, struct clk *clk_src[])
12396+{
12397+	int i;
12398+
12399+	for (i = 0; i < MICFIL_CLK_SRC_NUM; i++)
12400+		if (clk_is_match(p, clk_src[i]))
12401+			return true;
12402+
12403+	return false;
12404+}
12405+
12406+#define CLK_8K_FREQ    24576000
12407+#define CLK_11K_FREQ   22579200
12408+
12409+static int fsl_micfil_set_mclk_rate(struct fsl_micfil *micfil, int clk_id,
12410 				    unsigned int freq)
12411 {
12412+	struct clk *p = micfil->mclk, *pll = 0, *npll = 0;
12413 	struct device *dev = &micfil->pdev->dev;
12414+	u64 ratio = freq;
12415+	u64 clk_rate;
12416 	int ret;
12417+	int i;
12418+
12419+	/* Do not touch the clock if hwvad is already enabled
12420+	 * since you can record only at hwvad rate and clock
12421+	 * has already been set to the required frequency
12422+	 */
12423+	if (atomic_read(&micfil->hwvad_state) == MICFIL_HWVAD_ON)
12424+		return 0;
12425+
12426+	/* check if all clock sources are valid */
12427+	for (i = 0; i < MICFIL_CLK_SRC_NUM; i++) {
12428+		if (micfil->clk_src[i])
12429+			continue;
12430+
12431+		dev_err(dev, "Clock Source %d is not valid.\n", i);
12432+		return -EINVAL;
12433+	}
12434+
12435+	while (p) {
12436+		struct clk *pp = clk_get_parent(p);
12437+
12438+		if (clk_in_list(pp, micfil->clk_src)) {
12439+			pll = pp;
12440+			break;
12441+		}
12442+		p = pp;
12443+	}
12444+
12445+	if (!pll) {
12446+		dev_err(dev, "reached a null clock\n");
12447+		return -EINVAL;
12448+	}
12449+
12450+	if (micfil->clk_src_id == MICFIL_CLK_AUTO) {
12451+		for (i = 0; i < MICFIL_CLK_SRC_NUM; i++) {
12452+			clk_rate = clk_get_rate(micfil->clk_src[i]);
12453+			/* This is an workaround since audio_pll2 clock
12454+			 * has 722534399 rate and this will never divide
12455+			 * to any known frequency ???
12456+			 */
12457+			clk_rate = round_up(clk_rate, 10);
12458+			if (do_div(clk_rate, ratio) == 0)
12459+				npll = micfil->clk_src[i];
12460+		}
12461+	} else {
12462+		/* clock id is offseted by 1 since ID=0 means
12463+		 * auto clock selection
12464+		 */
12465+		npll = micfil->clk_src[micfil->clk_src_id - 1];
12466+	}
12467+
12468+	if (!npll) {
12469+		dev_err(dev,
12470+			"failed to find a suitable clock source\n");
12471+		return -EINVAL;
12472+	}
12473
12474 	clk_disable_unprepare(micfil->mclk);
12475+	if (!clk_is_match(pll, npll)) {
12476+		ret = clk_set_parent(p, npll);
12477+		if (ret < 0)
12478+			dev_warn(dev,
12479+				 "failed to set parrent %d\n", ret);
12480+	}
12481
12482-	ret = clk_set_rate(micfil->mclk, freq * 1024);
12483+	clk_rate = freq % 8000 == 0 ? CLK_8K_FREQ : CLK_11K_FREQ;
12484+	ret = clk_set_rate(micfil->mclk, clk_rate);
12485 	if (ret)
12486-		dev_warn(dev, "failed to set rate (%u): %d\n",
12487-			 freq * 1024, ret);
12488-
12489+		dev_warn(dev, "failed to set rate (%llu): %d\n", clk_rate, ret);
12490 	clk_prepare_enable(micfil->mclk);
12491
12492 	return ret;
12493@@ -297,7 +1525,7 @@ static int fsl_set_clock_params(struct device *dev, unsigned int rate)
12494 	int clk_div;
12495 	int ret;
12496
12497-	ret = fsl_micfil_set_mclk_rate(micfil, rate);
12498+	ret = fsl_micfil_set_mclk_rate(micfil, 0, rate);
12499 	if (ret < 0)
12500 		dev_err(dev, "failed to set mclk[%lu] to rate %u\n",
12501 			clk_get_rate(micfil->mclk), rate);
12502@@ -332,14 +1560,32 @@ static int fsl_micfil_hw_params(struct snd_pcm_substream *substream,
12503 	unsigned int channels = params_channels(params);
12504 	unsigned int rate = params_rate(params);
12505 	struct device *dev = &micfil->pdev->dev;
12506+	unsigned int hwvad_rate;
12507 	int ret;
12508+	u32 hwvad_state;
12509
12510-	/* 1. Disable the module */
12511-	ret = regmap_update_bits(micfil->regmap, REG_MICFIL_CTRL1,
12512-				 MICFIL_CTRL1_PDMIEN_MASK, 0);
12513-	if (ret) {
12514-		dev_err(dev, "failed to disable the module\n");
12515-		return ret;
12516+	hwvad_rate = micfil_hwvad_rate_ints[micfil->vad_rate_index];
12517+	hwvad_state = atomic_read(&micfil->hwvad_state);
12518+
12519+	/* if hwvad is enabled, make sure you are recording at
12520+	 * the same rate the hwvad is on or reject it to avoid
12521+	 * changing the clock rate.
12522+	 */
12523+	if (hwvad_state == MICFIL_HWVAD_ON && rate != hwvad_rate) {
12524+		dev_err(dev, "Record at hwvad rate %u\n", hwvad_rate);
12525+		return -EINVAL;
12526+	}
12527+
12528+	atomic_set(&micfil->recording_state, MICFIL_RECORDING_ON);
12529+
12530+	if (hwvad_state == MICFIL_HWVAD_OFF) {
12531+		/* 1. Disable the module */
12532+		ret = regmap_update_bits(micfil->regmap, REG_MICFIL_CTRL1,
12533+					 MICFIL_CTRL1_PDMIEN_MASK, 0);
12534+		if (ret) {
12535+			dev_err(dev, "failed to disable the module\n");
12536+			return ret;
12537+		}
12538 	}
12539
12540 	/* enable channels */
12541@@ -357,11 +1603,25 @@ static int fsl_micfil_hw_params(struct snd_pcm_substream *substream,
12542 		return ret;
12543 	}
12544
12545+	micfil->audio_config.src_fifo_num = channels;
12546+	micfil->audio_config.sw_done_sel = BIT(31);
12547+	micfil->dma_params_rx.peripheral_config  = &micfil->audio_config;
12548+	micfil->dma_params_rx.peripheral_size    = sizeof(micfil->audio_config);
12549 	micfil->dma_params_rx.maxburst = channels * MICFIL_DMA_MAXBURST_RX;
12550
12551 	return 0;
12552 }
12553
12554+static int fsl_micfil_hw_free(struct snd_pcm_substream *substream,
12555+			      struct snd_soc_dai *dai)
12556+{
12557+	struct fsl_micfil *micfil = snd_soc_dai_get_drvdata(dai);
12558+
12559+	atomic_set(&micfil->recording_state, MICFIL_RECORDING_OFF);
12560+
12561+	return 0;
12562+}
12563+
12564 static int fsl_micfil_set_dai_sysclk(struct snd_soc_dai *dai, int clk_id,
12565 				     unsigned int freq, int dir)
12566 {
12567@@ -373,7 +1633,7 @@ static int fsl_micfil_set_dai_sysclk(struct snd_soc_dai *dai, int clk_id,
12568 	if (!freq)
12569 		return 0;
12570
12571-	ret = fsl_micfil_set_mclk_rate(micfil, freq);
12572+	ret = fsl_micfil_set_mclk_rate(micfil, clk_id, freq);
12573 	if (ret < 0)
12574 		dev_err(dev, "failed to set mclk[%lu] to rate %u\n",
12575 			clk_get_rate(micfil->mclk), freq);
12576@@ -381,11 +1641,38 @@ static int fsl_micfil_set_dai_sysclk(struct snd_soc_dai *dai, int clk_id,
12577 	return ret;
12578 }
12579
12580+static int fsl_micfil_set_dai_fmt(struct snd_soc_dai *dai, unsigned int fmt)
12581+{
12582+	struct fsl_micfil *micfil = snd_soc_dai_get_drvdata(dai);
12583+
12584+	/* DAI MODE */
12585+	switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
12586+	case SND_SOC_DAIFMT_I2S:
12587+		break;
12588+	default:
12589+		return -EINVAL;
12590+	}
12591+
12592+	/* DAI CLK INVERSION */
12593+	switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
12594+	case SND_SOC_DAIFMT_NB_NF:
12595+		break;
12596+	default:
12597+		return -EINVAL;
12598+	}
12599+
12600+	micfil->slave_mode = false;
12601+
12602+	return 0;
12603+}
12604+
12605 static struct snd_soc_dai_ops fsl_micfil_dai_ops = {
12606 	.startup = fsl_micfil_startup,
12607 	.trigger = fsl_micfil_trigger,
12608 	.hw_params = fsl_micfil_hw_params,
12609+	.hw_free = fsl_micfil_hw_free,
12610 	.set_sysclk = fsl_micfil_set_dai_sysclk,
12611+	.set_fmt = fsl_micfil_set_dai_fmt,
12612 };
12613
12614 static int fsl_micfil_dai_probe(struct snd_soc_dai *cpu_dai)
12615@@ -398,17 +1685,30 @@ static int fsl_micfil_dai_probe(struct snd_soc_dai *cpu_dai)
12616
12617 	/* set qsel to medium */
12618 	ret = regmap_update_bits(micfil->regmap, REG_MICFIL_CTRL2,
12619-				 MICFIL_CTRL2_QSEL_MASK, MICFIL_MEDIUM_QUALITY);
12620+				 MICFIL_CTRL2_QSEL_MASK, MICFIL_VLOW0_QUALITY);
12621 	if (ret) {
12622 		dev_err(dev, "failed to set quality mode bits, reg 0x%X\n",
12623 			REG_MICFIL_CTRL2);
12624 		return ret;
12625 	}
12626
12627-	/* set default gain to max_gain */
12628-	regmap_write(micfil->regmap, REG_MICFIL_OUT_CTRL, 0x77777777);
12629-	for (i = 0; i < 8; i++)
12630-		micfil->channel_gain[i] = 0xF;
12631+	/* set default gain to 2 */
12632+	regmap_write(micfil->regmap, REG_MICFIL_OUT_CTRL, 0x22222222);
12633+	for (i = 0; i < MICFIL_OUTPUT_CHANNELS; i++)
12634+		micfil->channel_gain[i] = 0xA;
12635+
12636+	/* set DC Remover in bypass mode*/
12637+	val = 0;
12638+	for (i = 0; i < MICFIL_OUTPUT_CHANNELS; i++)
12639+		val |= MICFIL_DC_MODE(MICFIL_DC_BYPASS, i);
12640+	ret = regmap_update_bits(micfil->regmap, REG_MICFIL_DC_CTRL,
12641+				MICFIL_DC_CTRL_MASK, val);
12642+	if (ret) {
12643+		dev_err(dev, "failed to set DC Remover mode bits, reg 0x%X\n",
12644+			REG_MICFIL_DC_CTRL);
12645+		return ret;
12646+	}
12647+	micfil->dc_remover = MICFIL_DC_BYPASS;
12648
12649 	snd_soc_dai_init_dma_data(cpu_dai, NULL,
12650 				  &micfil->dma_params_rx);
12651@@ -565,6 +1865,72 @@ static const struct regmap_config fsl_micfil_regmap_config = {
12652
12653 /* END OF REGMAP */
12654
12655+static irqreturn_t voice_detected_fn(int irq, void *devid)
12656+{
12657+	struct fsl_micfil *micfil = (struct fsl_micfil *)devid;
12658+	struct device *dev = &micfil->pdev->dev;
12659+	int ret;
12660+
12661+	/* disable hwvad */
12662+	spin_lock(&micfil->hwvad_lock);
12663+	ret = disable_hwvad(dev, true);
12664+	spin_unlock(&micfil->hwvad_lock);
12665+
12666+	if (ret)
12667+		dev_err(dev, "Failed to disable HWVAD module: %d\n", ret);
12668+
12669+	/* notify userspace that voice was detected */
12670+	kobject_uevent_env(&dev->kobj, KOBJ_CHANGE, envp);
12671+
12672+	return IRQ_HANDLED;
12673+}
12674+
12675+static irqreturn_t hwvad_isr(int irq, void *devid)
12676+{
12677+	struct fsl_micfil *micfil = (struct fsl_micfil *)devid;
12678+	struct device *dev = &micfil->pdev->dev;
12679+	int ret;
12680+	u32 vad0_reg;
12681+
12682+	regmap_read(micfil->regmap, REG_MICFIL_VAD0_STAT, &vad0_reg);
12683+
12684+	/* The only difference between MICFIL_VAD0_STAT_EF and
12685+	 * MICFIL_VAD0_STAT_IF is that the former requires Write
12686+	 * 1 to Clear. Since both flags are set, it is enough
12687+	 * to only read one of them
12688+	 */
12689+	if (vad0_reg & MICFIL_VAD0_STAT_IF_MASK) {
12690+		/* Write 1 to clear */
12691+		regmap_write_bits(micfil->regmap, REG_MICFIL_VAD0_STAT,
12692+				  MICFIL_VAD0_STAT_IF_MASK,
12693+				  MICFIL_VAD0_STAT_IF);
12694+
12695+		/* disable hwvad interrupts */
12696+		ret = configure_hwvad_interrupts(dev, 0);
12697+		if (ret)
12698+			dev_err(dev, "Failed to disable interrupts\n");
12699+	}
12700+
12701+	return IRQ_WAKE_THREAD;
12702+}
12703+
12704+static irqreturn_t hwvad_err_isr(int irq, void *devid)
12705+{
12706+	struct fsl_micfil *micfil = (struct fsl_micfil *)devid;
12707+	struct device *dev = &micfil->pdev->dev;
12708+	u32 vad0_reg;
12709+
12710+	regmap_read(micfil->regmap, REG_MICFIL_VAD0_STAT, &vad0_reg);
12711+
12712+	if (vad0_reg & MICFIL_VAD0_STAT_INSATF_MASK)
12713+		dev_dbg(dev, "voice activity input overflow/underflow detected\n");
12714+
12715+	if (vad0_reg & MICFIL_VAD0_STAT_INITF_MASK)
12716+		dev_dbg(dev, "voice activity dectector is initializing\n");
12717+
12718+	return IRQ_HANDLED;
12719+}
12720+
12721 static irqreturn_t micfil_isr(int irq, void *devid)
12722 {
12723 	struct fsl_micfil *micfil = (struct fsl_micfil *)devid;
12724@@ -634,6 +2000,196 @@ static irqreturn_t micfil_err_isr(int irq, void *devid)
12725 	return IRQ_HANDLED;
12726 }
12727
12728+static int fsl_set_clock_params(struct device *, unsigned int);
12729+
12730+static int enable_hwvad(struct device *dev, bool sync)
12731+{
12732+	struct fsl_micfil *micfil = dev_get_drvdata(dev);
12733+	int ret;
12734+	int rate;
12735+	u32 state;
12736+
12737+	if (sync)
12738+		pm_runtime_get_sync(dev);
12739+
12740+	state = atomic_cmpxchg(&micfil->hwvad_state,
12741+			       MICFIL_HWVAD_OFF,
12742+			       MICFIL_HWVAD_ON);
12743+
12744+	/* we should not reenable when sync = true because
12745+	 * this means enable was called for second time by
12746+	 * user. However state = ON and sync = false can only
12747+	 * occur when enable is called from system_resume. In
12748+	 * this case we should enable the hwvad
12749+	 */
12750+	if (sync && state == MICFIL_HWVAD_ON) {
12751+		dev_err(dev, "hwvad already on\n");
12752+		ret = -EBUSY;
12753+		goto enable_error;
12754+	}
12755+
12756+	if (micfil->vad_rate_index >= ARRAY_SIZE(micfil_hwvad_rate_ints)) {
12757+		dev_err(dev, "There are more select texts than rates\n");
12758+		ret = -EINVAL;
12759+		goto enable_error;
12760+	}
12761+
12762+	rate = micfil_hwvad_rate_ints[micfil->vad_rate_index];
12763+
12764+	/* This is required because if an arecord was done,
12765+	 * suspend function will mark regmap as cache only
12766+	 * and reads/writes in volatile regs will fail
12767+	 */
12768+	regcache_cache_only(micfil->regmap, false);
12769+	regcache_mark_dirty(micfil->regmap);
12770+	regcache_sync(micfil->regmap);
12771+
12772+	ret = fsl_set_clock_params(dev, rate);
12773+	if (ret)
12774+		goto enable_error;
12775+
12776+	ret = fsl_micfil_reset(dev);
12777+	if (ret)
12778+		goto enable_error;
12779+
12780+	/* Initialize Hardware Voice Activity */
12781+	ret = init_hwvad(dev);
12782+	if (ret == 0)
12783+		return 0;
12784+
12785+enable_error:
12786+	if (state == MICFIL_HWVAD_OFF)
12787+		atomic_cmpxchg(&micfil->hwvad_state,
12788+			       MICFIL_HWVAD_ON, MICFIL_HWVAD_OFF);
12789+	if (sync)
12790+		pm_runtime_put_sync(dev);
12791+	return ret;
12792+}
12793+
12794+static int disable_hwvad(struct device *dev, bool sync)
12795+{
12796+	struct fsl_micfil *micfil = dev_get_drvdata(dev);
12797+	int ret = 0;
12798+	u32 state;
12799+
12800+	/* disable is called with sync = false only from
12801+	 * system suspend and in this case, you should not
12802+	 * change the hwvad_state so we know at system_resume
12803+	 * to reenable hwvad
12804+	 */
12805+	if (sync)
12806+		state = atomic_cmpxchg(&micfil->hwvad_state,
12807+				       MICFIL_HWVAD_ON,
12808+				       MICFIL_HWVAD_OFF);
12809+	else
12810+		state = atomic_read(&micfil->hwvad_state);
12811+
12812+	if (state == MICFIL_HWVAD_ON) {
12813+		/* This is required because if an arecord was done,
12814+		 * suspend function will mark regmap as cache only
12815+		 * and reads/writes in volatile regs will fail
12816+		 */
12817+		regcache_cache_only(micfil->regmap, false);
12818+		regcache_mark_dirty(micfil->regmap);
12819+		regcache_sync(micfil->regmap);
12820+
12821+		/* Voice Activity Detector Reset */
12822+		ret |= regmap_update_bits(micfil->regmap,
12823+					  REG_MICFIL_VAD0_CTRL1,
12824+					  MICFIL_VAD0_CTRL1_RST_SHIFT,
12825+					  MICFIL_VAD0_CTRL1_RST);
12826+
12827+		/* Disable HWVAD */
12828+		ret |= regmap_update_bits(micfil->regmap,
12829+					  REG_MICFIL_VAD0_CTRL1,
12830+					  MICFIL_VAD0_CTRL1_EN_MASK,
12831+					  0);
12832+
12833+		/* Disable Signal Filter */
12834+		ret |= regmap_update_bits(micfil->regmap,
12835+					  REG_MICFIL_VAD0_SCONFIG,
12836+					  MICFIL_VAD0_SCONFIG_SFILEN_MASK,
12837+					  0);
12838+
12839+		/* Signal Maximum Enable */
12840+		ret |= regmap_update_bits(micfil->regmap,
12841+					  REG_MICFIL_VAD0_SCONFIG,
12842+					  MICFIL_VAD0_SCONFIG_SMAXEN_MASK,
12843+					  0);
12844+
12845+		/* Enable pre-filter Noise & Signal */
12846+		ret |= regmap_update_bits(micfil->regmap,
12847+					  REG_MICFIL_VAD0_CTRL2,
12848+					  MICFIL_VAD0_CTRL2_PREFEN_MASK,
12849+					  0);
12850+
12851+		/* Noise Decimation Enable */
12852+		ret |= regmap_update_bits(micfil->regmap,
12853+					  REG_MICFIL_VAD0_NCONFIG,
12854+					  MICFIL_VAD0_NCONFIG_NDECEN_MASK,
12855+					  0);
12856+
12857+		/* disable the module and clock only if recording
12858+		 * is not done in parallel
12859+		 */
12860+		state = atomic_read(&micfil->recording_state);
12861+		if (state == MICFIL_RECORDING_OFF) {
12862+		/* Disable MICFIL module */
12863+			ret |= regmap_update_bits(micfil->regmap,
12864+						  REG_MICFIL_CTRL1,
12865+						  MICFIL_CTRL1_PDMIEN_MASK,
12866+						  0);
12867+		}
12868+
12869+		if (sync)
12870+			pm_runtime_put_sync(dev);
12871+	} else {
12872+		ret = -EPERM;
12873+		dev_err(dev, "HWVAD is not enabled %d\n", ret);
12874+	}
12875+
12876+	return ret;
12877+}
12878+
12879+static ssize_t micfil_hwvad_handler(struct kobject *kobj,
12880+				    struct kobj_attribute *attr,
12881+				    const char *buf,
12882+				    size_t count)
12883+{
12884+	struct kobject *nand_kobj = kobj->parent;
12885+	struct device *dev = container_of(nand_kobj, struct device, kobj);
12886+	struct fsl_micfil *micfil = dev_get_drvdata(dev);
12887+	unsigned long vad_channel;
12888+	int ret;
12889+
12890+	ret = kstrtoul(buf, 16, &vad_channel);
12891+	if (ret < 0)
12892+		return -EINVAL;
12893+
12894+	spin_lock(&micfil->hwvad_lock);
12895+	if (vad_channel <= 7) {
12896+		micfil->vad_channel = vad_channel;
12897+		ret = enable_hwvad(dev, true);
12898+	} else {
12899+		micfil->vad_channel = -1;
12900+		ret = disable_hwvad(dev, true);
12901+	}
12902+	spin_unlock(&micfil->hwvad_lock);
12903+
12904+	if (ret) {
12905+		dev_err(dev, "Failed to %s hwvad: %d\n",
12906+			vad_channel <= 7 ? "enable" : "disable", ret);
12907+		return ret;
12908+	}
12909+
12910+	return count;
12911+}
12912+
12913+static struct kobj_attribute hwvad_en_attr = __ATTR(enable,
12914+						   0660,
12915+						   NULL,
12916+						   micfil_hwvad_handler);
12917+
12918 static int fsl_micfil_probe(struct platform_device *pdev)
12919 {
12920 	struct device_node *np = pdev->dev.of_node;
12921@@ -667,6 +2223,26 @@ static int fsl_micfil_probe(struct platform_device *pdev)
12922 		return PTR_ERR(micfil->mclk);
12923 	}
12924
12925+	micfil->busclk = devm_clk_get(&pdev->dev, "ipg_clk");
12926+	if (IS_ERR(micfil->busclk)) {
12927+		dev_err(&pdev->dev, "failed to get ipg clock: %ld\n",
12928+			PTR_ERR(micfil->busclk));
12929+		return PTR_ERR(micfil->busclk);
12930+	}
12931+
12932+	/* get audio pll1 and pll2 */
12933+	micfil->clk_src[MICFIL_AUDIO_PLL1] = devm_clk_get(&pdev->dev, "pll8k");
12934+	if (IS_ERR(micfil->clk_src[MICFIL_AUDIO_PLL1]))
12935+		micfil->clk_src[MICFIL_AUDIO_PLL1] = NULL;
12936+
12937+	micfil->clk_src[MICFIL_AUDIO_PLL2] = devm_clk_get(&pdev->dev, "pll11k");
12938+	if (IS_ERR(micfil->clk_src[MICFIL_AUDIO_PLL2]))
12939+		micfil->clk_src[MICFIL_AUDIO_PLL2] = NULL;
12940+
12941+	micfil->clk_src[MICFIL_CLK_EXT3] = devm_clk_get(&pdev->dev, "clkext3");
12942+	if (IS_ERR(micfil->clk_src[MICFIL_CLK_EXT3]))
12943+		micfil->clk_src[MICFIL_CLK_EXT3] = NULL;
12944+
12945 	/* init regmap */
12946 	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
12947 	regs = devm_ioremap_resource(&pdev->dev, res);
12948@@ -674,7 +2250,7 @@ static int fsl_micfil_probe(struct platform_device *pdev)
12949 		return PTR_ERR(regs);
12950
12951 	micfil->regmap = devm_regmap_init_mmio_clk(&pdev->dev,
12952-						   "ipg_clk",
12953+						   NULL,
12954 						   regs,
12955 						   &fsl_micfil_regmap_config);
12956 	if (IS_ERR(micfil->regmap)) {
12957@@ -708,7 +2284,31 @@ static int fsl_micfil_probe(struct platform_device *pdev)
12958 	if (of_property_read_bool(np, "fsl,shared-interrupt"))
12959 		irqflag = IRQF_SHARED;
12960
12961-	/* Digital Microphone interface interrupt */
12962+	/* Digital Microphone interface voice activity detector event
12963+	 * interrupt - IRQ 44
12964+	 */
12965+	ret = devm_request_threaded_irq(&pdev->dev, micfil->irq[2],
12966+					hwvad_isr, voice_detected_fn,
12967+					irqflag, micfil->name, micfil);
12968+	if (ret) {
12969+		dev_err(&pdev->dev, "failed to claim hwvad event irq %u\n",
12970+			micfil->irq[0]);
12971+		return ret;
12972+	}
12973+
12974+	/* Digital Microphone interface voice activity detector error
12975+	 * interrupt - IRQ 45
12976+	 */
12977+	ret = devm_request_irq(&pdev->dev, micfil->irq[3],
12978+			       hwvad_err_isr, irqflag,
12979+			       micfil->name, micfil);
12980+	if (ret) {
12981+		dev_err(&pdev->dev, "failed to claim hwvad error irq %u\n",
12982+			micfil->irq[1]);
12983+		return ret;
12984+	}
12985+
12986+	/* Digital Microphone interface interrupt - IRQ 109 */
12987 	ret = devm_request_irq(&pdev->dev, micfil->irq[0],
12988 			       micfil_isr, irqflag,
12989 			       micfil->name, micfil);
12990@@ -728,14 +2328,23 @@ static int fsl_micfil_probe(struct platform_device *pdev)
12991 		return ret;
12992 	}
12993
12994+	micfil->slave_mode = false;
12995+
12996 	micfil->dma_params_rx.chan_name = "rx";
12997 	micfil->dma_params_rx.addr = res->start + REG_MICFIL_DATACH0;
12998 	micfil->dma_params_rx.maxburst = MICFIL_DMA_MAXBURST_RX;
12999
13000+	/* set default rate to first value in available vad rates */
13001+	micfil->vad_rate_index = 0;
13002+	/* init HWVAD enable/disable spinlock */
13003+	spin_lock_init(&micfil->hwvad_lock);
13004
13005 	platform_set_drvdata(pdev, micfil);
13006
13007 	pm_runtime_enable(&pdev->dev);
13008+	regcache_cache_only(micfil->regmap, true);
13009+
13010+	fsl_micfil_dai.capture.formats = micfil->soc->formats;
13011
13012 	ret = devm_snd_soc_register_component(&pdev->dev, &fsl_micfil_component,
13013 					      &fsl_micfil_dai, 1);
13014@@ -746,19 +2355,44 @@ static int fsl_micfil_probe(struct platform_device *pdev)
13015 	}
13016
13017 	ret = devm_snd_dmaengine_pcm_register(&pdev->dev, NULL, 0);
13018-	if (ret)
13019+	if (ret) {
13020 		dev_err(&pdev->dev, "failed to pcm register\n");
13021+		return ret;
13022+	}
13023
13024-	return ret;
13025+	/* create sysfs entry used to enable hwvad from userspace */
13026+	micfil->hwvad_kobject = kobject_create_and_add("hwvad",
13027+						       &pdev->dev.kobj);
13028+	if (!micfil->hwvad_kobject)
13029+		return -ENOMEM;
13030+
13031+	ret = sysfs_create_file(micfil->hwvad_kobject,
13032+				&hwvad_en_attr.attr);
13033+	if (ret) {
13034+		dev_err(&pdev->dev, "failed to create file for hwvad_enable\n");
13035+		kobject_put(micfil->hwvad_kobject);
13036+		return -ENOMEM;
13037+	}
13038+
13039+	return 0;
13040 }
13041
13042 static int __maybe_unused fsl_micfil_runtime_suspend(struct device *dev)
13043 {
13044 	struct fsl_micfil *micfil = dev_get_drvdata(dev);
13045+	u32 state;
13046+
13047+	state = atomic_read(&micfil->hwvad_state);
13048+	if (state == MICFIL_HWVAD_ON)
13049+		return 0;
13050
13051 	regcache_cache_only(micfil->regmap, true);
13052
13053-	clk_disable_unprepare(micfil->mclk);
13054+	/* Disable the clock only if the hwvad is not enabled */
13055+	if (state == MICFIL_HWVAD_OFF)
13056+		clk_disable_unprepare(micfil->mclk);
13057+
13058+	clk_disable_unprepare(micfil->busclk);
13059
13060 	return 0;
13061 }
13062@@ -767,6 +2401,21 @@ static int __maybe_unused fsl_micfil_runtime_resume(struct device *dev)
13063 {
13064 	struct fsl_micfil *micfil = dev_get_drvdata(dev);
13065 	int ret;
13066+	u32 state;
13067+
13068+	ret = clk_prepare_enable(micfil->busclk);
13069+	if (ret < 0)
13070+		return ret;
13071+
13072+	state = atomic_read(&micfil->hwvad_state);
13073+
13074+	/* enable mclk only if the hwvad is not enabled
13075+	 * When hwvad is enabled, clock won't be disabled
13076+	 * in suspend since hwvad and recording share the
13077+	 * same clock
13078+	 */
13079+	if (state == MICFIL_HWVAD_ON)
13080+		return 0;
13081
13082 	ret = clk_prepare_enable(micfil->mclk);
13083 	if (ret < 0)
13084@@ -781,6 +2430,19 @@ static int __maybe_unused fsl_micfil_runtime_resume(struct device *dev)
13085
13086 static int __maybe_unused fsl_micfil_suspend(struct device *dev)
13087 {
13088+	struct fsl_micfil *micfil = dev_get_drvdata(dev);
13089+	int ret;
13090+	u32 state;
13091+
13092+	state = atomic_read(&micfil->hwvad_state);
13093+
13094+	if (state == MICFIL_HWVAD_ON) {
13095+		dev_err(dev, "Disabling hwvad on suspend");
13096+		ret = disable_hwvad(dev, false);
13097+		if (ret)
13098+			dev_warn(dev, "Failed to disable hwvad");
13099+	}
13100+
13101 	pm_runtime_force_suspend(dev);
13102
13103 	return 0;
13104@@ -788,8 +2450,20 @@ static int __maybe_unused fsl_micfil_suspend(struct device *dev)
13105
13106 static int __maybe_unused fsl_micfil_resume(struct device *dev)
13107 {
13108+	struct fsl_micfil *micfil = dev_get_drvdata(dev);
13109+	int ret;
13110+	u32 state;
13111+
13112 	pm_runtime_force_resume(dev);
13113
13114+	state = atomic_read(&micfil->hwvad_state);
13115+	if (state == MICFIL_HWVAD_ON) {
13116+		dev_err(dev, "Enabling hwvad on resume");
13117+		ret = enable_hwvad(dev, false);
13118+		if (ret)
13119+			dev_warn(dev, "Failed to re-enable hwvad");
13120+	}
13121+
13122 	return 0;
13123 }
13124
13125diff --git a/sound/soc/fsl/fsl_micfil.h b/sound/soc/fsl/fsl_micfil.h
13126index bac825c31..14ad08b6b 100644
13127--- a/sound/soc/fsl/fsl_micfil.h
13128+++ b/sound/soc/fsl/fsl_micfil.h
13129@@ -258,6 +258,40 @@
13130 #define MICFIL_VAD0_STAT_IF_MASK	BIT(MICFIL_VAD0_STAT_IF_SHIFT)
13131 #define MICFIL_VAD0_STAT_IF		BIT(MICFIL_VAD0_STAT_IF_SHIFT)
13132
13133+/* HWVAD Constants */
13134+#define MICFIL_HWVAD_ENVELOPE_MODE	0
13135+#define MICFIL_HWVAD_ENERGY_MODE	1
13136+#define MICFIL_HWVAD_INIT_FRAMES	10
13137+#define MICFIL_HWVAD_INPGAIN		0
13138+#define MICFIL_HWVAD_SGAIN		6
13139+#define MICFIL_HWVAD_NGAIN		3
13140+#define MICFIL_HWVAD_NFILADJ		0
13141+#define MICFIL_HWVAD_ZCDADJ		(1 << (MICFIL_VAD0_ZCD_ZCDADJ_WIDTH - 2))
13142+#define MICFIL_HWVAD_ZCDTH		10	/* initial threshold value */
13143+#define MICFIL_HWVAD_ZCDOR		0
13144+#define MICFIL_HWVAD_ZCDAND		1
13145+#define MICFIL_HWVAD_ZCD_MANUAL		0
13146+#define MICFIL_HWVAD_ZCD_AUTO		1
13147+#define MICFIL_HWVAD_HPF_BYPASS		0
13148+#define MICFIL_HWVAD_HPF_1750HZ		1
13149+#define MICFIL_HWVAD_HPF_215HZ		2
13150+#define MICFIL_HWVAD_HPF_102HZ		3
13151+#define MICFIL_HWVAD_FRAMET_DEFAULT	10
13152+
13153+/* MICFIL DC Remover Control Register -- REG_MICFIL_DC_CTRL */
13154+#define MICFIL_DC_CTRL_SHIFT		0
13155+#define MICFIL_DC_CTRL_MASK		0xFFFF
13156+#define MICFIL_DC_CTRL_WIDTH		2
13157+#define MICFIL_DC_CHX_SHIFT(v)		(2 * (v))
13158+#define MICFIL_DC_CHX_MASK(v)		((BIT(MICFIL_DC_CTRL_WIDTH) - 1) \
13159+					 << MICFIL_DC_CHX_SHIFT(v))
13160+#define MICFIL_DC_MODE(v1, v2)		(((v1) << MICFIL_DC_CHX_SHIFT(v2)) \
13161+					 & MICFIL_DC_CHX_MASK(v2))
13162+#define MICFIL_DC_CUTOFF_21HZ		0
13163+#define MICFIL_DC_CUTOFF_83HZ		1
13164+#define MICFIL_DC_CUTOFF_152Hz		2
13165+#define MICFIL_DC_BYPASS			3
13166+
13167 /* MICFIL Output Control Register */
13168 #define MICFIL_OUTGAIN_CHX_SHIFT(v)	(4 * (v))
13169
13170@@ -273,11 +307,24 @@
13171 #define FIFO_PTRWID			3
13172 #define FIFO_LEN			BIT(FIFO_PTRWID)
13173
13174-#define MICFIL_IRQ_LINES		2
13175+#define MICFIL_IRQ_LINES		4
13176 #define MICFIL_MAX_RETRY		25
13177-#define MICFIL_SLEEP_MIN		90000 /* in us */
13178-#define MICFIL_SLEEP_MAX		100000 /* in us */
13179+#define MICFIL_SLEEP			100 /* in ms */
13180 #define MICFIL_DMA_MAXBURST_RX		6
13181 #define MICFIL_CTRL2_OSR_DEFAULT	(0 << MICFIL_CTRL2_CICOSR_SHIFT)
13182+#define MICFIL_DEFAULT_RATE		48000
13183+#define MICFIL_CLK_SRC_NUM		3
13184+#define MICFIL_CLK_AUTO			0
13185+
13186+/* clock source ids */
13187+#define MICFIL_AUDIO_PLL1		0
13188+#define MICFIL_AUDIO_PLL2		1
13189+#define MICFIL_CLK_EXT3			2
13190+
13191+/* States of micfil */
13192+#define MICFIL_HWVAD_OFF		0
13193+#define MICFIL_HWVAD_ON			1
13194+#define MICFIL_RECORDING_OFF		0
13195+#define MICFIL_RECORDING_ON		1
13196
13197 #endif /* _FSL_MICFIL_H */
13198diff --git a/sound/soc/fsl/fsl_rpmsg.h b/sound/soc/fsl/fsl_rpmsg.h
13199new file mode 100644
13200index 000000000..71412a683
13201--- /dev/null
13202+++ b/sound/soc/fsl/fsl_rpmsg.h
13203@@ -0,0 +1,46 @@
13204+/* SPDX-License-Identifier: GPL-2.0 */
13205+/*
13206+ * Copyright 2017-2021 NXP
13207+ */
13208+
13209+#ifndef __FSL_RPMSG_H
13210+#define __FSL_RPMSG_H
13211+
13212+/* struct fsl_rpmsg_soc_data
13213+ * @rates: supported rates
13214+ * @formats: supported formats
13215+ */
13216+struct fsl_rpmsg_soc_data {
13217+	int rates;
13218+	u64 formats;
13219+};
13220+
13221+/*
13222+ * struct fsl_rpmsg - rpmsg private data
13223+ *
13224+ * @ipg: ipg clock for cpu dai (SAI)
13225+ * @mclk: master clock for cpu dai (SAI)
13226+ * @dma: clock for dma device
13227+ * @pll8k: parent clock for multiple of 8kHz frequency
13228+ * @pll11k: parent clock for multiple of 11kHz frequency
13229+ * @card_pdev: Platform_device pointer to register a sound card
13230+ * @soc_data: soc specific data
13231+ * @mclk_streams: Active streams that are using baudclk
13232+ * @force_lpa: force enable low power audio routine if condition satisfy
13233+ * @enable_lpa: enable low power audio routine according to dts setting
13234+ * @buffer_size: pre allocated dma buffer size
13235+ */
13236+struct fsl_rpmsg {
13237+	struct clk *ipg;
13238+	struct clk *mclk;
13239+	struct clk *dma;
13240+	struct clk *pll8k;
13241+	struct clk *pll11k;
13242+	struct platform_device *card_pdev;
13243+	const struct fsl_rpmsg_soc_data *soc_data;
13244+	unsigned int mclk_streams;
13245+	int force_lpa;
13246+	int enable_lpa;
13247+	int buffer_size;
13248+};
13249+#endif /* __FSL_RPMSG_H */
13250diff --git a/sound/soc/fsl/fsl_sai.c b/sound/soc/fsl/fsl_sai.c
13251index 3e5c1eacc..5d4a7289a 100644
13252--- a/sound/soc/fsl/fsl_sai.c
13253+++ b/sound/soc/fsl/fsl_sai.c
13254@@ -5,21 +5,28 @@
13255 // Copyright 2012-2015 Freescale Semiconductor, Inc.
13256
13257 #include <linux/clk.h>
13258+#include <linux/clk-provider.h>
13259 #include <linux/delay.h>
13260 #include <linux/dmaengine.h>
13261 #include <linux/module.h>
13262+#include <linux/of_device.h>
13263 #include <linux/of_address.h>
13264 #include <linux/of_device.h>
13265 #include <linux/pm_runtime.h>
13266 #include <linux/regmap.h>
13267 #include <linux/slab.h>
13268 #include <linux/time.h>
13269+#include <linux/pm_qos.h>
13270 #include <sound/core.h>
13271 #include <sound/dmaengine_pcm.h>
13272 #include <sound/pcm_params.h>
13273 #include <linux/mfd/syscon.h>
13274 #include <linux/mfd/syscon/imx6q-iomuxc-gpr.h>
13275+#include <linux/pm_runtime.h>
13276+#include <linux/pinctrl/consumer.h>
13277+#include <linux/busfreq-imx.h>
13278
13279+#include "fsl_dsd.h"
13280 #include "fsl_sai.h"
13281 #include "imx-pcm.h"
13282
13283@@ -29,7 +36,8 @@
13284 static const unsigned int fsl_sai_rates[] = {
13285 	8000, 11025, 12000, 16000, 22050,
13286 	24000, 32000, 44100, 48000, 64000,
13287-	88200, 96000, 176400, 192000
13288+	88200, 96000, 176400, 192000, 352800,
13289+	384000, 705600, 768000, 1411200, 2822400,
13290 };
13291
13292 static const struct snd_pcm_hw_constraint_list fsl_sai_rate_constraints = {
13293@@ -170,6 +178,7 @@ static int fsl_sai_set_dai_sysclk_tr(struct snd_soc_dai *cpu_dai,
13294 {
13295 	struct fsl_sai *sai = snd_soc_dai_get_drvdata(cpu_dai);
13296 	unsigned int ofs = sai->soc_data->reg_offset;
13297+
13298 	bool tx = fsl_dir == FSL_FMT_TRANSMITTER;
13299 	u32 val_cr2 = 0;
13300
13301@@ -196,14 +205,71 @@ static int fsl_sai_set_dai_sysclk_tr(struct snd_soc_dai *cpu_dai,
13302 	return 0;
13303 }
13304
13305+static int fsl_sai_set_mclk_rate(struct snd_soc_dai *dai, int clk_id,
13306+		unsigned int freq)
13307+{
13308+	struct fsl_sai *sai = snd_soc_dai_get_drvdata(dai);
13309+	struct clk *p = sai->mclk_clk[clk_id], *pll = 0, *npll = 0;
13310+	u64 ratio = freq;
13311+	int ret;
13312+
13313+	while (p && sai->pll8k_clk && sai->pll11k_clk) {
13314+		struct clk *pp = clk_get_parent(p);
13315+
13316+		if (clk_is_match(pp, sai->pll8k_clk) ||
13317+		    clk_is_match(pp, sai->pll11k_clk)) {
13318+			pll = pp;
13319+			break;
13320+		}
13321+		p = pp;
13322+	}
13323+
13324+	if (pll) {
13325+		npll = (do_div(ratio, 8000) ? sai->pll11k_clk : sai->pll8k_clk);
13326+		if (!clk_is_match(pll, npll)) {
13327+			ret = clk_set_parent(p, npll);
13328+			if (ret < 0)
13329+				dev_warn(dai->dev,
13330+					 "failed to set parent %s: %d\n",
13331+					 __clk_get_name(npll), ret);
13332+		}
13333+	}
13334+
13335+	ret = clk_set_rate(sai->mclk_clk[clk_id], freq);
13336+	if (ret < 0)
13337+		dev_err(dai->dev, "failed to set clock rate (%u): %d\n",
13338+			freq, ret);
13339+
13340+	return ret;
13341+}
13342+
13343 static int fsl_sai_set_dai_sysclk(struct snd_soc_dai *cpu_dai,
13344 		int clk_id, unsigned int freq, int dir)
13345 {
13346+	struct fsl_sai *sai = snd_soc_dai_get_drvdata(cpu_dai);
13347 	int ret;
13348
13349 	if (dir == SND_SOC_CLOCK_IN)
13350 		return 0;
13351
13352+	if (freq > 0 && clk_id != FSL_SAI_CLK_BUS) {
13353+		if (clk_id < 0 || clk_id >= FSL_SAI_MCLK_MAX) {
13354+			dev_err(cpu_dai->dev, "Unknown clock id: %d\n", clk_id);
13355+			return -EINVAL;
13356+		}
13357+
13358+		if (IS_ERR_OR_NULL(sai->mclk_clk[clk_id])) {
13359+			dev_err(cpu_dai->dev, "Unassigned clock: %d\n", clk_id);
13360+			return -EINVAL;
13361+		}
13362+
13363+		if (sai->mclk_streams == 0) {
13364+			ret = fsl_sai_set_mclk_rate(cpu_dai, clk_id, freq);
13365+			if (ret < 0)
13366+				return ret;
13367+		}
13368+	}
13369+
13370 	ret = fsl_sai_set_dai_sysclk_tr(cpu_dai, clk_id, freq,
13371 					FSL_FMT_TRANSMITTER);
13372 	if (ret) {
13373@@ -230,6 +296,7 @@ static int fsl_sai_set_dai_fmt_tr(struct snd_soc_dai *cpu_dai,
13374 	if (!sai->is_lsb_first)
13375 		val_cr4 |= FSL_SAI_CR4_MF;
13376
13377+	sai->is_dsp_mode = false;
13378 	/* DAI mode */
13379 	switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
13380 	case SND_SOC_DAIFMT_I2S:
13381@@ -268,6 +335,11 @@ static int fsl_sai_set_dai_fmt_tr(struct snd_soc_dai *cpu_dai,
13382 		val_cr2 |= FSL_SAI_CR2_BCP;
13383 		sai->is_dsp_mode = true;
13384 		break;
13385+	case SND_SOC_DAIFMT_PDM:
13386+		val_cr2 |= FSL_SAI_CR2_BCP;
13387+		val_cr4 &= ~FSL_SAI_CR4_MF;
13388+		sai->is_dsp_mode = true;
13389+		break;
13390 	case SND_SOC_DAIFMT_RIGHT_J:
13391 		/* To be done */
13392 	default:
13393@@ -296,23 +368,23 @@ static int fsl_sai_set_dai_fmt_tr(struct snd_soc_dai *cpu_dai,
13394 		return -EINVAL;
13395 	}
13396
13397+	sai->slave_mode[tx] = false;
13398+
13399 	/* DAI clock master masks */
13400 	switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
13401 	case SND_SOC_DAIFMT_CBS_CFS:
13402 		val_cr2 |= FSL_SAI_CR2_BCD_MSTR;
13403 		val_cr4 |= FSL_SAI_CR4_FSD_MSTR;
13404-		sai->is_slave_mode = false;
13405 		break;
13406 	case SND_SOC_DAIFMT_CBM_CFM:
13407-		sai->is_slave_mode = true;
13408+		sai->slave_mode[tx] = true;
13409 		break;
13410 	case SND_SOC_DAIFMT_CBS_CFM:
13411 		val_cr2 |= FSL_SAI_CR2_BCD_MSTR;
13412-		sai->is_slave_mode = false;
13413 		break;
13414 	case SND_SOC_DAIFMT_CBM_CFS:
13415 		val_cr4 |= FSL_SAI_CR4_FSD_MSTR;
13416-		sai->is_slave_mode = true;
13417+		sai->slave_mode[tx] = true;
13418 		break;
13419 	default:
13420 		return -EINVAL;
13421@@ -329,14 +401,23 @@ static int fsl_sai_set_dai_fmt_tr(struct snd_soc_dai *cpu_dai,
13422
13423 static int fsl_sai_set_dai_fmt(struct snd_soc_dai *cpu_dai, unsigned int fmt)
13424 {
13425+	struct fsl_sai *sai = snd_soc_dai_get_drvdata(cpu_dai);
13426 	int ret;
13427
13428+	if (sai->masterflag[FSL_FMT_TRANSMITTER])
13429+		fmt = (fmt & (~SND_SOC_DAIFMT_MASTER_MASK)) |
13430+				sai->masterflag[FSL_FMT_TRANSMITTER];
13431+
13432 	ret = fsl_sai_set_dai_fmt_tr(cpu_dai, fmt, FSL_FMT_TRANSMITTER);
13433 	if (ret) {
13434 		dev_err(cpu_dai->dev, "Cannot set tx format: %d\n", ret);
13435 		return ret;
13436 	}
13437
13438+	if (sai->masterflag[FSL_FMT_RECEIVER])
13439+		fmt = (fmt & (~SND_SOC_DAIFMT_MASTER_MASK)) |
13440+				sai->masterflag[FSL_FMT_RECEIVER];
13441+
13442 	ret = fsl_sai_set_dai_fmt_tr(cpu_dai, fmt, FSL_FMT_RECEIVER);
13443 	if (ret)
13444 		dev_err(cpu_dai->dev, "Cannot set rx format: %d\n", ret);
13445@@ -349,14 +430,15 @@ static int fsl_sai_set_bclk(struct snd_soc_dai *dai, bool tx, u32 freq)
13446 	struct fsl_sai *sai = snd_soc_dai_get_drvdata(dai);
13447 	unsigned int ofs = sai->soc_data->reg_offset;
13448 	unsigned long clk_rate;
13449-	u32 savediv = 0, ratio, savesub = freq;
13450 	int adir = tx ? RX : TX;
13451 	int dir = tx ? TX : RX;
13452+	unsigned int reg = 0;
13453+	u32 ratio, savesub = freq, saveratio = 0, savediv = 0;
13454 	u32 id;
13455 	int ret = 0;
13456
13457 	/* Don't apply to slave mode */
13458-	if (sai->is_slave_mode)
13459+	if (sai->slave_mode[tx])
13460 		return 0;
13461
13462 	for (id = 0; id < FSL_SAI_MCLK_MAX; id++) {
13463@@ -379,22 +461,21 @@ static int fsl_sai_set_bclk(struct snd_soc_dai *dai, bool tx, u32 freq)
13464 			"ratio %d for freq %dHz based on clock %ldHz\n",
13465 			ratio, freq, clk_rate);
13466
13467-		if (ratio % 2 == 0 && ratio >= 2 && ratio <= 512)
13468-			ratio /= 2;
13469-		else
13470-			continue;
13471+		if ((ratio % 2 == 0 && ratio >= 2 && ratio <= 512) ||
13472+		    (ratio == 1 && sai->verid.major >= 3 && sai->verid.minor >= 1)) {
13473
13474-		if (ret < savesub) {
13475-			savediv = ratio;
13476-			sai->mclk_id[tx] = id;
13477-			savesub = ret;
13478-		}
13479+			if (ret < savesub) {
13480+				saveratio = ratio;
13481+				sai->mclk_id[tx] = id;
13482+				savesub = ret;
13483+			}
13484
13485-		if (ret == 0)
13486-			break;
13487+			if (ret == 0)
13488+				break;
13489+		}
13490 	}
13491
13492-	if (savediv == 0) {
13493+	if (saveratio == 0) {
13494 		dev_err(dai->dev, "failed to derive required %cx rate: %d\n",
13495 				tx ? 'T' : 'R', freq);
13496 		return -EINVAL;
13497@@ -410,22 +491,32 @@ static int fsl_sai_set_bclk(struct snd_soc_dai *dai, bool tx, u32 freq)
13498 	 * 4) For Tx and Rx are both Synchronous with another SAI, we just
13499 	 *    ignore it.
13500 	 */
13501-	if (fsl_sai_dir_is_synced(sai, adir)) {
13502-		regmap_update_bits(sai->regmap, FSL_SAI_xCR2(!tx, ofs),
13503-				   FSL_SAI_CR2_MSEL_MASK,
13504-				   FSL_SAI_CR2_MSEL(sai->mclk_id[tx]));
13505-		regmap_update_bits(sai->regmap, FSL_SAI_xCR2(!tx, ofs),
13506-				   FSL_SAI_CR2_DIV_MASK, savediv - 1);
13507-	} else if (!sai->synchronous[dir]) {
13508-		regmap_update_bits(sai->regmap, FSL_SAI_xCR2(tx, ofs),
13509-				   FSL_SAI_CR2_MSEL_MASK,
13510-				   FSL_SAI_CR2_MSEL(sai->mclk_id[tx]));
13511-		regmap_update_bits(sai->regmap, FSL_SAI_xCR2(tx, ofs),
13512-				   FSL_SAI_CR2_DIV_MASK, savediv - 1);
13513+	if (fsl_sai_dir_is_synced(sai, adir))
13514+		reg = FSL_SAI_xCR2(!tx, ofs);
13515+	else if (!sai->synchronous[dir])
13516+		reg = FSL_SAI_xCR2(tx, ofs);
13517+
13518+	if (reg) {
13519+		regmap_update_bits(sai->regmap, reg, FSL_SAI_CR2_MSEL_MASK,
13520+			   FSL_SAI_CR2_MSEL(sai->mclk_id[tx]));
13521+
13522+		savediv = (saveratio == 1 ? 0 : (saveratio >> 1) - 1);
13523+		regmap_update_bits(sai->regmap, reg, FSL_SAI_CR2_DIV_MASK, savediv);
13524+
13525+		if (sai->verid.major >= 3 && sai->verid.minor >= 1) {
13526+			regmap_update_bits(sai->regmap, reg, FSL_SAI_CR2_BYP,
13527+				   (saveratio == 1 ? FSL_SAI_CR2_BYP : 0));
13528+		}
13529 	}
13530
13531-	dev_dbg(dai->dev, "best fit: clock id=%d, div=%d, deviation =%d\n",
13532-			sai->mclk_id[tx], savediv, savesub);
13533+	if (sai->soc_data->max_register >= FSL_SAI_MCTL) {
13534+		/* SAI is in master mode at this point, so enable MCLK */
13535+		regmap_update_bits(sai->regmap, FSL_SAI_MCTL,
13536+				FSL_SAI_MCTL_MCLK_EN, FSL_SAI_MCTL_MCLK_EN);
13537+	}
13538+
13539+	dev_dbg(dai->dev, "best fit: clock id=%d, ratio=%d, deviation=%d\n",
13540+			sai->mclk_id[tx], saveratio, savesub);
13541
13542 	return 0;
13543 }
13544@@ -439,30 +530,62 @@ static int fsl_sai_hw_params(struct snd_pcm_substream *substream,
13545 	bool tx = substream->stream == SNDRV_PCM_STREAM_PLAYBACK;
13546 	unsigned int channels = params_channels(params);
13547 	u32 word_width = params_width(params);
13548+	u32 rate = params_rate(params);
13549 	u32 val_cr4 = 0, val_cr5 = 0;
13550 	u32 slots = (channels == 1) ? 2 : channels;
13551 	u32 slot_width = word_width;
13552 	int adir = tx ? RX : TX;
13553-	u32 pins;
13554-	int ret;
13555+	u32 pins, bclk;
13556+	int ret, i, trce_mask = 0, dl_cfg_cnt, dl_cfg_idx = 0;
13557+	struct fsl_sai_dl_cfg *dl_cfg;
13558
13559 	if (sai->slots)
13560 		slots = sai->slots;
13561
13562+	pins = DIV_ROUND_UP(channels, slots);
13563+	sai->is_dsd = fsl_is_dsd(params);
13564+	if (sai->is_dsd) {
13565+		pins = channels;
13566+		dl_cfg = sai->dsd_dl_cfg;
13567+		dl_cfg_cnt = sai->dsd_dl_cfg_cnt;
13568+	} else {
13569+		dl_cfg = sai->pcm_dl_cfg;
13570+		dl_cfg_cnt = sai->pcm_dl_cfg_cnt;
13571+	}
13572+
13573+	for (i = 0; i < dl_cfg_cnt; i++) {
13574+		if (dl_cfg[i].pins == pins) {
13575+			dl_cfg_idx = i;
13576+			break;
13577+		}
13578+	}
13579+
13580+	if (dl_cfg_idx >= dl_cfg_cnt) {
13581+		dev_err(cpu_dai->dev, "fsl,dataline%s invalid or not provided.\n",
13582+			sai->is_dsd ? ",dsd" : "");
13583+		return -EINVAL;
13584+	}
13585+
13586 	if (sai->slot_width)
13587 		slot_width = sai->slot_width;
13588
13589-	pins = DIV_ROUND_UP(channels, slots);
13590+	bclk = rate*(sai->bclk_ratio ? sai->bclk_ratio : slots * slot_width);
13591
13592-	if (!sai->is_slave_mode) {
13593-		if (sai->bclk_ratio)
13594-			ret = fsl_sai_set_bclk(cpu_dai, tx,
13595-					       sai->bclk_ratio *
13596-					       params_rate(params));
13597-		else
13598-			ret = fsl_sai_set_bclk(cpu_dai, tx,
13599-					       slots * slot_width *
13600-					       params_rate(params));
13601+	if (!IS_ERR_OR_NULL(sai->pinctrl)) {
13602+		sai->pins_state = fsl_get_pins_state(sai->pinctrl, params, bclk);
13603+
13604+		if (!IS_ERR_OR_NULL(sai->pins_state)) {
13605+			ret = pinctrl_select_state(sai->pinctrl, sai->pins_state);
13606+			if (ret) {
13607+				dev_err(cpu_dai->dev,
13608+					"failed to set proper pins state: %d\n", ret);
13609+				return ret;
13610+			}
13611+		}
13612+	}
13613+
13614+	if (!sai->slave_mode[tx]) {
13615+		ret = fsl_sai_set_bclk(cpu_dai, tx, bclk);
13616 		if (ret)
13617 			return ret;
13618
13619@@ -482,7 +605,7 @@ static int fsl_sai_hw_params(struct snd_pcm_substream *substream,
13620 	val_cr5 |= FSL_SAI_CR5_WNW(slot_width);
13621 	val_cr5 |= FSL_SAI_CR5_W0W(slot_width);
13622
13623-	if (sai->is_lsb_first)
13624+	if (sai->is_lsb_first || sai->is_dsd)
13625 		val_cr5 |= FSL_SAI_CR5_FBT(0);
13626 	else
13627 		val_cr5 |= FSL_SAI_CR5_FBT(word_width - 1);
13628@@ -499,7 +622,7 @@ static int fsl_sai_hw_params(struct snd_pcm_substream *substream,
13629 	 * RCR5(TCR5) for playback(capture), or there will be sync error.
13630 	 */
13631
13632-	if (!sai->is_slave_mode && fsl_sai_dir_is_synced(sai, adir)) {
13633+	if (!sai->slave_mode[tx] && fsl_sai_dir_is_synced(sai, adir)) {
13634 		regmap_update_bits(sai->regmap, FSL_SAI_xCR4(!tx, ofs),
13635 				   FSL_SAI_CR4_SYWD_MASK | FSL_SAI_CR4_FRSZ_MASK |
13636 				   FSL_SAI_CR4_CHMOD_MASK,
13637@@ -509,9 +632,64 @@ static int fsl_sai_hw_params(struct snd_pcm_substream *substream,
13638 				   FSL_SAI_CR5_FBT_MASK, val_cr5);
13639 	}
13640
13641+	if (__sw_hweight8(dl_cfg[dl_cfg_idx].mask[tx]) <= 1 || sai->is_multi_lane)
13642+		regmap_update_bits(sai->regmap, FSL_SAI_xCR4(tx, ofs),
13643+				   FSL_SAI_CR4_FCOMB_MASK, 0);
13644+	else
13645+		regmap_update_bits(sai->regmap, FSL_SAI_xCR4(tx, ofs),
13646+				   FSL_SAI_CR4_FCOMB_MASK, FSL_SAI_CR4_FCOMB_SOFT);
13647+
13648+	if (tx)
13649+		sai->dma_params_tx.addr = sai->res->start + FSL_SAI_TDR0 +
13650+					  dl_cfg[dl_cfg_idx].start_off[tx] * 0x4;
13651+	else
13652+		sai->dma_params_rx.addr = sai->res->start + FSL_SAI_RDR0 +
13653+					  dl_cfg[dl_cfg_idx].start_off[tx] * 0x4;
13654+
13655+	if (sai->is_multi_lane) {
13656+		if (tx) {
13657+			sai->audio_config[tx].words_per_fifo = min(slots, channels);
13658+			sai->audio_config[tx].dst_fifo_num = pins;
13659+			sai->audio_config[tx].dst_fifo_off = dl_cfg[dl_cfg_idx].next_off[tx];
13660+			sai->dma_params_tx.maxburst = sai->audio_config[tx].words_per_fifo * pins;
13661+			sai->dma_params_tx.peripheral_config = &sai->audio_config[tx];
13662+			sai->dma_params_tx.peripheral_size = sizeof(sai->audio_config[tx]);
13663+
13664+			regmap_update_bits(sai->regmap, FSL_SAI_TCR1(ofs),
13665+					   FSL_SAI_CR1_RFW_MASK(sai->soc_data->fifo_depth),
13666+					   sai->soc_data->fifo_depth - sai->dma_params_tx.maxburst);
13667+		} else {
13668+			sai->audio_config[tx].words_per_fifo = min(slots, channels);
13669+			sai->audio_config[tx].src_fifo_num = pins;
13670+			sai->audio_config[tx].src_fifo_off = dl_cfg[dl_cfg_idx].next_off[tx];
13671+			sai->dma_params_rx.maxburst = sai->audio_config[tx].words_per_fifo * pins;
13672+			sai->dma_params_rx.peripheral_config = &sai->audio_config[tx];
13673+			sai->dma_params_rx.peripheral_size = sizeof(sai->audio_config[tx]);
13674+
13675+			regmap_update_bits(sai->regmap, FSL_SAI_RCR1(ofs),
13676+					   FSL_SAI_CR1_RFW_MASK(sai->soc_data->fifo_depth),
13677+					   sai->dma_params_rx.maxburst - 1);
13678+		}
13679+	}
13680+
13681+	snd_soc_dai_init_dma_data(cpu_dai, &sai->dma_params_tx, &sai->dma_params_rx);
13682+
13683+	if (__sw_hweight8(dl_cfg[dl_cfg_idx].mask[tx] & 0xFF) < pins) {
13684+		dev_err(cpu_dai->dev, "channel not supported\n");
13685+		return -EINVAL;
13686+	}
13687+
13688+	/*find a proper tcre setting*/
13689+	for (i = 0; i < 8; i++) {
13690+		trce_mask = (1 << (i + 1)) - 1;
13691+		if (__sw_hweight8(dl_cfg[dl_cfg_idx].mask[tx] & trce_mask) == pins)
13692+			break;
13693+	}
13694+
13695 	regmap_update_bits(sai->regmap, FSL_SAI_xCR3(tx, ofs),
13696-			   FSL_SAI_CR3_TRCE_MASK,
13697-			   FSL_SAI_CR3_TRCE((1 << pins) - 1));
13698+		   FSL_SAI_CR3_TRCE_MASK,
13699+		   FSL_SAI_CR3_TRCE((dl_cfg[dl_cfg_idx].mask[tx] & trce_mask)));
13700+
13701 	regmap_update_bits(sai->regmap, FSL_SAI_xCR4(tx, ofs),
13702 			   FSL_SAI_CR4_SYWD_MASK | FSL_SAI_CR4_FRSZ_MASK |
13703 			   FSL_SAI_CR4_CHMOD_MASK,
13704@@ -535,7 +713,7 @@ static int fsl_sai_hw_free(struct snd_pcm_substream *substream,
13705 	regmap_update_bits(sai->regmap, FSL_SAI_xCR3(tx, ofs),
13706 			   FSL_SAI_CR3_TRCE_MASK, 0);
13707
13708-	if (!sai->is_slave_mode &&
13709+	if (!sai->slave_mode[tx] &&
13710 			sai->mclk_streams & BIT(substream->stream)) {
13711 		clk_disable_unprepare(sai->mclk_clk[sai->mclk_id[tx]]);
13712 		sai->mclk_streams &= ~BIT(substream->stream);
13713@@ -569,7 +747,7 @@ static void fsl_sai_config_disable(struct fsl_sai *sai, int dir)
13714 	 * This is a hardware bug, and will be fix in the
13715 	 * next sai version.
13716 	 */
13717-	if (!sai->is_slave_mode) {
13718+	if (!sai->slave_mode[tx]) {
13719 		/* Software Reset */
13720 		regmap_write(sai->regmap, FSL_SAI_xCSR(tx, ofs), FSL_SAI_CSR_SR);
13721 		/* Clear SR bit to finish the reset */
13722@@ -582,11 +760,38 @@ static int fsl_sai_trigger(struct snd_pcm_substream *substream, int cmd,
13723 {
13724 	struct fsl_sai *sai = snd_soc_dai_get_drvdata(cpu_dai);
13725 	unsigned int ofs = sai->soc_data->reg_offset;
13726-
13727 	bool tx = substream->stream == SNDRV_PCM_STREAM_PLAYBACK;
13728+	u8 channels = substream->runtime->channels;
13729 	int adir = tx ? RX : TX;
13730 	int dir = tx ? TX : RX;
13731 	u32 xcsr;
13732+	u32 slots = (channels == 1) ? 2 : channels;
13733+	u32 pins;
13734+	int i = 0, j = 0, k = 0, dl_cfg_cnt, dl_cfg_idx = 0;
13735+	struct fsl_sai_dl_cfg *dl_cfg;
13736+
13737+	if (sai->slots)
13738+		slots = sai->slots;
13739+
13740+	pins = DIV_ROUND_UP(channels, slots);
13741+
13742+	if (sai->is_dsd) {
13743+		pins = channels;
13744+		dl_cfg = sai->dsd_dl_cfg;
13745+		dl_cfg_cnt = sai->dsd_dl_cfg_cnt;
13746+	} else {
13747+		dl_cfg = sai->pcm_dl_cfg;
13748+		dl_cfg_cnt = sai->pcm_dl_cfg_cnt;
13749+	}
13750+
13751+	for (i = 0; i < dl_cfg_cnt; i++) {
13752+		if (dl_cfg[i].pins == pins) {
13753+			dl_cfg_idx = i;
13754+			break;
13755+		}
13756+	}
13757+
13758+	i = 0;
13759
13760 	/*
13761 	 * Asynchronous mode: Clear SYNC for both Tx and Rx.
13762@@ -606,11 +811,25 @@ static int fsl_sai_trigger(struct snd_pcm_substream *substream, int cmd,
13763 	case SNDRV_PCM_TRIGGER_START:
13764 	case SNDRV_PCM_TRIGGER_RESUME:
13765 	case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
13766+
13767+		while (tx && i < channels) {
13768+			if (dl_cfg[dl_cfg_idx].mask[tx] & (1 << j)) {
13769+				regmap_write(sai->regmap, FSL_SAI_TDR0 + j * 0x4, 0x0);
13770+				i++;
13771+				k++;
13772+			}
13773+			j++;
13774+
13775+			if (k%pins == 0)
13776+				j = 0;
13777+		}
13778+
13779 		regmap_update_bits(sai->regmap, FSL_SAI_xCSR(tx, ofs),
13780 				   FSL_SAI_CSR_FRDE, FSL_SAI_CSR_FRDE);
13781-
13782 		regmap_update_bits(sai->regmap, FSL_SAI_xCSR(tx, ofs),
13783 				   FSL_SAI_CSR_TERE, FSL_SAI_CSR_TERE);
13784+		regmap_update_bits(sai->regmap, FSL_SAI_xCSR(tx, ofs),
13785+				   FSL_SAI_CSR_SE, FSL_SAI_CSR_SE);
13786 		/*
13787 		 * Enable the opposite direction for synchronous mode
13788 		 * 1. Tx sync with Rx: only set RE for Rx; set TE & RE for Tx
13789@@ -703,13 +922,6 @@ static int fsl_sai_dai_probe(struct snd_soc_dai *cpu_dai)
13790 	struct fsl_sai *sai = dev_get_drvdata(cpu_dai->dev);
13791 	unsigned int ofs = sai->soc_data->reg_offset;
13792
13793-	/* Software Reset for both Tx and Rx */
13794-	regmap_write(sai->regmap, FSL_SAI_TCSR(ofs), FSL_SAI_CSR_SR);
13795-	regmap_write(sai->regmap, FSL_SAI_RCSR(ofs), FSL_SAI_CSR_SR);
13796-	/* Clear SR bit to finish the reset */
13797-	regmap_write(sai->regmap, FSL_SAI_TCSR(ofs), 0);
13798-	regmap_write(sai->regmap, FSL_SAI_RCSR(ofs), 0);
13799-
13800 	regmap_update_bits(sai->regmap, FSL_SAI_TCR1(ofs),
13801 			   FSL_SAI_CR1_RFW_MASK(sai->soc_data->fifo_depth),
13802 			   sai->soc_data->fifo_depth - FSL_SAI_MAXBURST_TX);
13803@@ -725,6 +937,23 @@ static int fsl_sai_dai_probe(struct snd_soc_dai *cpu_dai)
13804 	return 0;
13805 }
13806
13807+static int fsl_sai_dai_resume(struct snd_soc_component *component)
13808+{
13809+	struct fsl_sai *sai = snd_soc_component_get_drvdata(component);
13810+	int ret;
13811+
13812+	if (!IS_ERR_OR_NULL(sai->pinctrl) && !IS_ERR_OR_NULL(sai->pins_state)) {
13813+		ret = pinctrl_select_state(sai->pinctrl, sai->pins_state);
13814+		if (ret) {
13815+			dev_err(&sai->pdev->dev,
13816+				"failed to set proper pins state: %d\n", ret);
13817+			return ret;
13818+		}
13819+	}
13820+
13821+	return 0;
13822+}
13823+
13824 static struct snd_soc_dai_driver fsl_sai_dai_template = {
13825 	.probe = fsl_sai_dai_probe,
13826 	.playback = {
13827@@ -732,7 +961,7 @@ static struct snd_soc_dai_driver fsl_sai_dai_template = {
13828 		.channels_min = 1,
13829 		.channels_max = 32,
13830 		.rate_min = 8000,
13831-		.rate_max = 192000,
13832+		.rate_max = 2822400,
13833 		.rates = SNDRV_PCM_RATE_KNOT,
13834 		.formats = FSL_SAI_FORMATS,
13835 	},
13836@@ -741,7 +970,7 @@ static struct snd_soc_dai_driver fsl_sai_dai_template = {
13837 		.channels_min = 1,
13838 		.channels_max = 32,
13839 		.rate_min = 8000,
13840-		.rate_max = 192000,
13841+		.rate_max = 2822400,
13842 		.rates = SNDRV_PCM_RATE_KNOT,
13843 		.formats = FSL_SAI_FORMATS,
13844 	},
13845@@ -750,6 +979,7 @@ static struct snd_soc_dai_driver fsl_sai_dai_template = {
13846
13847 static const struct snd_soc_component_driver fsl_component = {
13848 	.name           = "fsl-sai",
13849+	.resume  = fsl_sai_dai_resume,
13850 };
13851
13852 static struct reg_default fsl_sai_reg_defaults_ofs0[] = {
13853@@ -893,6 +1123,14 @@ static bool fsl_sai_volatile_reg(struct device *dev, unsigned int reg)
13854 	case FSL_SAI_RDR5:
13855 	case FSL_SAI_RDR6:
13856 	case FSL_SAI_RDR7:
13857+	case FSL_SAI_TTCTN:
13858+	case FSL_SAI_TTCTL:
13859+	case FSL_SAI_TBCTN:
13860+	case FSL_SAI_TTCAP:
13861+	case FSL_SAI_RTCTN:
13862+	case FSL_SAI_RTCTL:
13863+	case FSL_SAI_RBCTN:
13864+	case FSL_SAI_RTCAP:
13865 		return true;
13866 	default:
13867 		return false;
13868@@ -988,12 +1226,87 @@ static int fsl_sai_check_version(struct device *dev)
13869 	return 0;
13870 }
13871
13872+static unsigned int fsl_sai_calc_dl_off(unsigned long dl_mask)
13873+{
13874+	int fbidx, nbidx, offset;
13875+
13876+	fbidx = find_first_bit(&dl_mask, 8);
13877+	nbidx = find_next_bit(&dl_mask, 8, fbidx + 1);
13878+	offset = nbidx - fbidx - 1;
13879+
13880+	return (offset < 0 || offset >= 7 ? 0 : offset);
13881+}
13882+
13883+static int fsl_sai_read_dlcfg(struct platform_device *pdev, char *pn,
13884+	struct fsl_sai_dl_cfg **rcfg, unsigned int soc_dl)
13885+{
13886+	int ret, elems, i, index, num_cfg;
13887+	struct device_node *np = pdev->dev.of_node;
13888+	struct fsl_sai_dl_cfg *cfg;
13889+	unsigned long dl_mask;
13890+	u32 rx, tx, pins;
13891+
13892+	*rcfg = NULL;
13893+
13894+	elems = of_property_count_u32_elems(np, pn);
13895+
13896+	/* consider default value "0 0x1 0x1" if property is missing */
13897+	if (elems <= 0)
13898+		elems = 3;
13899+
13900+	if (elems % 3) {
13901+		dev_err(&pdev->dev,
13902+			"Number of elements in %s must be divisible to 3.\n", pn);
13903+		return -EINVAL;
13904+	}
13905+
13906+	num_cfg = elems / 3;
13907+	cfg = devm_kzalloc(&pdev->dev, num_cfg * sizeof(*cfg), GFP_KERNEL);
13908+	if (cfg == NULL) {
13909+		dev_err(&pdev->dev, "Cannot allocate memory for %s.\n", pn);
13910+		return -ENOMEM;
13911+	}
13912+
13913+	for (i = 0, index = 0; i < num_cfg; i++) {
13914+		ret = of_property_read_u32_index(np, pn, index++, &pins);
13915+		if (ret)
13916+			pins = 0;
13917+
13918+		ret = of_property_read_u32_index(np, pn, index++, &rx);
13919+		if (ret)
13920+			rx = 1;
13921+
13922+		ret = of_property_read_u32_index(np, pn, index++, &tx);
13923+		if (ret)
13924+			tx = 1;
13925+
13926+		if ((rx & ~soc_dl) || (tx & ~soc_dl)) {
13927+			dev_err(&pdev->dev,
13928+				"%s: dataline cfg[%d] setting error, mask is 0x%x\n",
13929+				 pn, i, soc_dl);
13930+			return -EINVAL;
13931+		}
13932+
13933+		cfg[i].pins = pins;
13934+		cfg[i].mask[0] = rx;
13935+		dl_mask = rx;
13936+		cfg[i].start_off[0] = find_first_bit(&dl_mask, 8);
13937+		cfg[i].next_off[0] = fsl_sai_calc_dl_off(rx);
13938+		cfg[i].mask[1] = tx;
13939+		dl_mask = tx;
13940+		cfg[i].start_off[1] = find_first_bit(&dl_mask, 8);
13941+		cfg[i].next_off[1] = fsl_sai_calc_dl_off(tx);
13942+	}
13943+
13944+	*rcfg = cfg;
13945+	return num_cfg;
13946+}
13947+
13948 static int fsl_sai_probe(struct platform_device *pdev)
13949 {
13950 	struct device_node *np = pdev->dev.of_node;
13951 	struct fsl_sai *sai;
13952 	struct regmap *gpr;
13953-	struct resource *res;
13954 	void __iomem *base;
13955 	char tmp[8];
13956 	int irq, ret, i;
13957@@ -1008,8 +1321,8 @@ static int fsl_sai_probe(struct platform_device *pdev)
13958
13959 	sai->is_lsb_first = of_property_read_bool(np, "lsb-first");
13960
13961-	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
13962-	base = devm_ioremap_resource(&pdev->dev, res);
13963+	sai->res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
13964+	base = devm_ioremap_resource(&pdev->dev, sai->res);
13965 	if (IS_ERR(base))
13966 		return PTR_ERR(base);
13967
13968@@ -1021,12 +1334,7 @@ static int fsl_sai_probe(struct platform_device *pdev)
13969 	}
13970
13971 	sai->regmap = devm_regmap_init_mmio_clk(&pdev->dev,
13972-			"bus", base, &fsl_sai_regmap_config);
13973-
13974-	/* Compatible with old DTB cases */
13975-	if (IS_ERR(sai->regmap) && PTR_ERR(sai->regmap) != -EPROBE_DEFER)
13976-		sai->regmap = devm_regmap_init_mmio_clk(&pdev->dev,
13977-				"sai", base, &fsl_sai_regmap_config);
13978+			NULL, base, &fsl_sai_regmap_config);
13979 	if (IS_ERR(sai->regmap)) {
13980 		dev_err(&pdev->dev, "regmap init failed\n");
13981 		return PTR_ERR(sai->regmap);
13982@@ -1037,20 +1345,60 @@ static int fsl_sai_probe(struct platform_device *pdev)
13983 	if (IS_ERR(sai->bus_clk)) {
13984 		dev_err(&pdev->dev, "failed to get bus clock: %ld\n",
13985 				PTR_ERR(sai->bus_clk));
13986+		return PTR_ERR(sai->bus_clk);
13987 		sai->bus_clk = NULL;
13988 	}
13989
13990-	sai->mclk_clk[0] = sai->bus_clk;
13991-	for (i = 1; i < FSL_SAI_MCLK_MAX; i++) {
13992+	for (i = 0; i < FSL_SAI_MCLK_MAX; i++) {
13993 		sprintf(tmp, "mclk%d", i);
13994 		sai->mclk_clk[i] = devm_clk_get(&pdev->dev, tmp);
13995 		if (IS_ERR(sai->mclk_clk[i])) {
13996 			dev_err(&pdev->dev, "failed to get mclk%d clock: %ld\n",
13997-					i + 1, PTR_ERR(sai->mclk_clk[i]));
13998+					i, PTR_ERR(sai->mclk_clk[i]));
13999 			sai->mclk_clk[i] = NULL;
14000 		}
14001 	}
14002
14003+	sai->pll8k_clk = devm_clk_get(&pdev->dev, "pll8k");
14004+	if (IS_ERR(sai->pll8k_clk))
14005+		sai->pll8k_clk = NULL;
14006+
14007+	sai->pll11k_clk = devm_clk_get(&pdev->dev, "pll11k");
14008+	if (IS_ERR(sai->pll11k_clk))
14009+		sai->pll11k_clk = NULL;
14010+
14011+	if (of_find_property(np, "fsl,sai-multi-lane", NULL))
14012+		sai->is_multi_lane = true;
14013+
14014+	/*dataline mask for rx and tx*/
14015+	ret = fsl_sai_read_dlcfg(pdev, "fsl,dataline", &sai->pcm_dl_cfg,
14016+					sai->soc_data->dataline);
14017+	if (ret < 0)
14018+		return ret;
14019+
14020+	sai->pcm_dl_cfg_cnt = ret;
14021+
14022+	ret = fsl_sai_read_dlcfg(pdev, "fsl,dataline,dsd", &sai->dsd_dl_cfg,
14023+					sai->soc_data->dataline);
14024+	if (ret < 0)
14025+		return ret;
14026+
14027+	sai->dsd_dl_cfg_cnt = ret;
14028+
14029+	if ((of_find_property(np, "fsl,i2s-xtor", NULL) != NULL) ||
14030+	    (of_find_property(np, "fsl,txm-rxs", NULL) != NULL))
14031+	{
14032+		sai->masterflag[FSL_FMT_TRANSMITTER] = SND_SOC_DAIFMT_CBS_CFS;
14033+		sai->masterflag[FSL_FMT_RECEIVER] = SND_SOC_DAIFMT_CBM_CFM;
14034+	} else {
14035+		if (!of_property_read_u32(np, "fsl,txmasterflag",
14036+			&sai->masterflag[FSL_FMT_TRANSMITTER]))
14037+			sai->masterflag[FSL_FMT_TRANSMITTER] <<= 12;
14038+		if (!of_property_read_u32(np, "fsl,rxmasterflag",
14039+			&sai->masterflag[FSL_FMT_RECEIVER]))
14040+			sai->masterflag[FSL_FMT_RECEIVER] <<= 12;
14041+	}
14042+
14043 	irq = platform_get_irq(pdev, 0);
14044 	if (irq < 0)
14045 		return irq;
14046@@ -1108,12 +1456,16 @@ static int fsl_sai_probe(struct platform_device *pdev)
14047 				   MCLK_DIR(index));
14048 	}
14049
14050-	sai->dma_params_rx.addr = res->start + FSL_SAI_RDR0;
14051-	sai->dma_params_tx.addr = res->start + FSL_SAI_TDR0;
14052+	sai->dma_params_rx.addr = sai->res->start + FSL_SAI_RDR0;
14053+	sai->dma_params_tx.addr = sai->res->start + FSL_SAI_TDR0;
14054 	sai->dma_params_rx.maxburst = FSL_SAI_MAXBURST_RX;
14055 	sai->dma_params_tx.maxburst = FSL_SAI_MAXBURST_TX;
14056
14057+	sai->pinctrl = devm_pinctrl_get(&pdev->dev);
14058+
14059 	platform_set_drvdata(pdev, sai);
14060+	pm_runtime_enable(&pdev->dev);
14061+	pm_runtime_get_sync(&pdev->dev);
14062
14063 	/* Get sai version */
14064 	ret = fsl_sai_check_version(&pdev->dev);
14065@@ -1122,31 +1474,59 @@ static int fsl_sai_probe(struct platform_device *pdev)
14066
14067 	/* Select MCLK direction */
14068 	if (of_find_property(np, "fsl,sai-mclk-direction-output", NULL) &&
14069-	    sai->verid.major >= 3 && sai->verid.minor >= 1) {
14070+	    sai->soc_data->max_register >= FSL_SAI_MCTL) {
14071 		regmap_update_bits(sai->regmap, FSL_SAI_MCTL,
14072 				   FSL_SAI_MCTL_MCLK_EN, FSL_SAI_MCTL_MCLK_EN);
14073 	}
14074
14075-	pm_runtime_enable(&pdev->dev);
14076+	if (sai->verid.feature & FSL_SAI_VERID_TSTMP_EN) {
14077+		if (of_find_property(np, "fsl,sai-monitor-spdif", NULL) &&
14078+		    of_device_is_compatible(np, "fsl,imx8mm-sai")) {
14079+			sai->regmap_gpr = syscon_regmap_lookup_by_compatible("fsl,imx8mm-iomuxc-gpr");
14080+			if (IS_ERR(sai->regmap_gpr))
14081+				dev_warn(&pdev->dev, "cannot find iomuxc registers\n");
14082+
14083+			sai->gpr_idx = of_alias_get_id(np, "sai");
14084+			if (sai->gpr_idx < 0)
14085+				dev_warn(&pdev->dev, "cannot find sai alias id\n");
14086+
14087+			if (sai->gpr_idx > 0 && !IS_ERR(sai->regmap_gpr))
14088+				sai->monitor_spdif = true;
14089+		}
14090+
14091+		ret = sysfs_create_group(&pdev->dev.kobj,
14092+					 fsl_sai_get_dev_attribute_group(sai->monitor_spdif));
14093+		if (ret) {
14094+			dev_err(&pdev->dev, "fail to create sys group\n");
14095+			goto err_pm_disable;
14096+		}
14097+	}
14098+
14099+	pm_runtime_put_sync(&pdev->dev);
14100 	regcache_cache_only(sai->regmap, true);
14101
14102 	ret = devm_snd_soc_register_component(&pdev->dev, &fsl_component,
14103 					      &sai->cpu_dai_drv, 1);
14104 	if (ret)
14105-		goto err_pm_disable;
14106+		goto err_component_register;
14107
14108 	if (sai->soc_data->use_imx_pcm) {
14109 		ret = imx_pcm_dma_init(pdev, IMX_SAI_DMABUF_SIZE);
14110 		if (ret)
14111-			goto err_pm_disable;
14112+			goto err_component_register;
14113 	} else {
14114 		ret = devm_snd_dmaengine_pcm_register(&pdev->dev, NULL, 0);
14115 		if (ret)
14116-			goto err_pm_disable;
14117+			goto err_component_register;
14118 	}
14119
14120 	return ret;
14121
14122+err_component_register:
14123+	if (sai->verid.feature & FSL_SAI_VERID_TSTMP_EN)
14124+		sysfs_remove_group(&pdev->dev.kobj,
14125+				   fsl_sai_get_dev_attribute_group(sai->monitor_spdif));
14126+
14127 err_pm_disable:
14128 	pm_runtime_disable(&pdev->dev);
14129
14130@@ -1155,8 +1535,13 @@ static int fsl_sai_probe(struct platform_device *pdev)
14131
14132 static int fsl_sai_remove(struct platform_device *pdev)
14133 {
14134+	struct fsl_sai *sai = dev_get_drvdata(&pdev->dev);
14135+
14136 	pm_runtime_disable(&pdev->dev);
14137
14138+	if (sai->verid.feature & FSL_SAI_VERID_TSTMP_EN)
14139+		sysfs_remove_group(&pdev->dev.kobj,  fsl_sai_get_dev_attribute_group(sai->monitor_spdif));
14140+
14141 	return 0;
14142 }
14143
14144@@ -1165,6 +1550,10 @@ static const struct fsl_sai_soc_data fsl_sai_vf610_data = {
14145 	.use_edma = false,
14146 	.fifo_depth = 32,
14147 	.reg_offset = 0,
14148+	.dataline = 0x1,
14149+	.fifos = 1,
14150+	.flags = 0,
14151+	.max_register = FSL_SAI_RMR,
14152 };
14153
14154 static const struct fsl_sai_soc_data fsl_sai_imx6sx_data = {
14155@@ -1172,6 +1561,10 @@ static const struct fsl_sai_soc_data fsl_sai_imx6sx_data = {
14156 	.use_edma = false,
14157 	.fifo_depth = 32,
14158 	.reg_offset = 0,
14159+	.dataline = 0x1,
14160+	.fifos = 1,
14161+	.flags = 0,
14162+	.max_register = FSL_SAI_RMR,
14163 };
14164
14165 static const struct fsl_sai_soc_data fsl_sai_imx7ulp_data = {
14166@@ -1179,6 +1572,10 @@ static const struct fsl_sai_soc_data fsl_sai_imx7ulp_data = {
14167 	.use_edma = false,
14168 	.fifo_depth = 16,
14169 	.reg_offset = 8,
14170+	.dataline = 0x3,
14171+	.fifos = 2,
14172+	.flags = SAI_FLAG_PMQOS,
14173+	.max_register = FSL_SAI_RMR,
14174 };
14175
14176 static const struct fsl_sai_soc_data fsl_sai_imx8mq_data = {
14177@@ -1186,6 +1583,10 @@ static const struct fsl_sai_soc_data fsl_sai_imx8mq_data = {
14178 	.use_edma = false,
14179 	.fifo_depth = 128,
14180 	.reg_offset = 8,
14181+	.dataline = 0xff,
14182+	.fifos = 8,
14183+	.flags = 0,
14184+	.max_register = FSL_SAI_RMR,
14185 };
14186
14187 static const struct fsl_sai_soc_data fsl_sai_imx8qm_data = {
14188@@ -1193,16 +1594,56 @@ static const struct fsl_sai_soc_data fsl_sai_imx8qm_data = {
14189 	.use_edma = true,
14190 	.fifo_depth = 64,
14191 	.reg_offset = 0,
14192+	.dataline = 0xf,
14193+	.fifos = 1,
14194+	.flags = 0,
14195+	.max_register = FSL_SAI_RMR,
14196+};
14197+
14198+static const struct fsl_sai_soc_data fsl_sai_imx8mm_data = {
14199+	.use_imx_pcm = true,
14200+	.use_edma = false,
14201+	.fifo_depth = 128,
14202+	.reg_offset = 8,
14203+	.dataline = 0xff,
14204+	.fifos = 8,
14205+	.flags = 0,
14206+	.max_register = FSL_SAI_MCTL,
14207+};
14208+
14209+static const struct fsl_sai_soc_data fsl_sai_imx8mp_data = {
14210+	.use_imx_pcm = true,
14211+	.use_edma = false,
14212+	.fifo_depth = 128,
14213+	.reg_offset = 8,
14214+	.dataline = 0xff,
14215+	.fifos = 8,
14216+	.flags = 0,
14217+	.max_register = FSL_SAI_MDIV,
14218+};
14219+
14220+static const struct fsl_sai_soc_data fsl_sai_imx8ulp_data = {
14221+	.use_imx_pcm = true,
14222+	.use_edma = true,
14223+	.fifo_depth = 16,
14224+	.reg_offset = 8,
14225+	.dataline = 0xf,
14226+	.fifos = 4,
14227+	.flags = SAI_FLAG_PMQOS,
14228+	.max_register = FSL_SAI_RTCAP,
14229 };
14230
14231 static const struct of_device_id fsl_sai_ids[] = {
14232-	{ .compatible = "fsl,vf610-sai", .data = &fsl_sai_vf610_data },
14233-	{ .compatible = "fsl,imx6sx-sai", .data = &fsl_sai_imx6sx_data },
14234-	{ .compatible = "fsl,imx6ul-sai", .data = &fsl_sai_imx6sx_data },
14235-	{ .compatible = "fsl,imx7ulp-sai", .data = &fsl_sai_imx7ulp_data },
14236-	{ .compatible = "fsl,imx8mq-sai", .data = &fsl_sai_imx8mq_data },
14237-	{ .compatible = "fsl,imx8qm-sai", .data = &fsl_sai_imx8qm_data },
14238-	{ /* sentinel */ }
14239+    // { .compatible = "fsl,vf610-sai", .data = &fsl_sai_vf610_data },
14240+    // { .compatible = "fsl,imx6sx-sai", .data = &fsl_sai_imx6sx_data },
14241+    // { .compatible = "fsl,imx6ul-sai", .data = &fsl_sai_imx6sx_data },
14242+    // { .compatible = "fsl,imx7ulp-sai", .data = &fsl_sai_imx7ulp_data },
14243+    // { .compatible = "fsl,imx8mq-sai", .data = &fsl_sai_imx8mq_data },
14244+    // { .compatible = "fsl,imx8mm-sai", .data = &fsl_sai_imx8mm_data },
14245+    // { .compatible = "fsl,imx8mp-sai", .data = &fsl_sai_imx8mp_data },
14246+    // { .compatible = "fsl,imx8qm-sai", .data = &fsl_sai_imx8qm_data },
14247+    // { .compatible = "fsl,imx8ulp-sai", .data = &fsl_sai_imx8ulp_data },
14248+    { /* sentinel */ }
14249 };
14250 MODULE_DEVICE_TABLE(of, fsl_sai_ids);
14251
14252@@ -1211,6 +1652,8 @@ static int fsl_sai_runtime_suspend(struct device *dev)
14253 {
14254 	struct fsl_sai *sai = dev_get_drvdata(dev);
14255
14256+	release_bus_freq(BUS_FREQ_AUDIO);
14257+
14258 	if (sai->mclk_streams & BIT(SNDRV_PCM_STREAM_CAPTURE))
14259 		clk_disable_unprepare(sai->mclk_clk[sai->mclk_id[0]]);
14260
14261@@ -1219,6 +1662,9 @@ static int fsl_sai_runtime_suspend(struct device *dev)
14262
14263 	clk_disable_unprepare(sai->bus_clk);
14264
14265+	if (sai->soc_data->flags & SAI_FLAG_PMQOS)
14266+		cpu_latency_qos_remove_request(&sai->pm_qos_req);
14267+
14268 	regcache_cache_only(sai->regmap, true);
14269
14270 	return 0;
14271@@ -1248,6 +1694,12 @@ static int fsl_sai_runtime_resume(struct device *dev)
14272 			goto disable_tx_clk;
14273 	}
14274
14275+	request_bus_freq(BUS_FREQ_AUDIO);
14276+
14277+	if (sai->soc_data->flags & SAI_FLAG_PMQOS)
14278+		cpu_latency_qos_add_request(&sai->pm_qos_req, 0);
14279+
14280+
14281 	regcache_cache_only(sai->regmap, false);
14282 	regcache_mark_dirty(sai->regmap);
14283 	regmap_write(sai->regmap, FSL_SAI_TCSR(ofs), FSL_SAI_CSR_SR);
14284@@ -1291,7 +1743,7 @@ static struct platform_driver fsl_sai_driver = {
14285 		.of_match_table = fsl_sai_ids,
14286 	},
14287 };
14288-module_platform_driver(fsl_sai_driver);
14289+// module_platform_driver(fsl_sai_driver);
14290
14291 MODULE_DESCRIPTION("Freescale Soc SAI Interface");
14292 MODULE_AUTHOR("Xiubo Li, <Li.Xiubo@freescale.com>");
14293diff --git a/sound/soc/fsl/fsl_sai.h b/sound/soc/fsl/fsl_sai.h
14294index 4bbcd0dbe..6692db4b6 100644
14295--- a/sound/soc/fsl/fsl_sai.h
14296+++ b/sound/soc/fsl/fsl_sai.h
14297@@ -6,12 +6,16 @@
14298 #ifndef __FSL_SAI_H
14299 #define __FSL_SAI_H
14300
14301+#include <linux/pm_qos.h>
14302+#include <linux/platform_data/dma-imx.h>
14303 #include <sound/dmaengine_pcm.h>
14304
14305 #define FSL_SAI_FORMATS (SNDRV_PCM_FMTBIT_S16_LE |\
14306-			 SNDRV_PCM_FMTBIT_S20_3LE |\
14307 			 SNDRV_PCM_FMTBIT_S24_LE |\
14308-			 SNDRV_PCM_FMTBIT_S32_LE)
14309+			 SNDRV_PCM_FMTBIT_S32_LE |\
14310+			 SNDRV_PCM_FMTBIT_DSD_U8 |\
14311+			 SNDRV_PCM_FMTBIT_DSD_U16_LE |\
14312+			 SNDRV_PCM_FMTBIT_DSD_U32_LE)
14313
14314 /* SAI Register Map Register */
14315 #define FSL_SAI_VERID	0x00 /* SAI Version ID Register */
14316@@ -211,16 +215,23 @@
14317 #define FSL_SAI_CLK_MAST3	3
14318
14319 #define FSL_SAI_MCLK_MAX	4
14320+#define FSL_SAI_CLK_BIT		5
14321
14322 /* SAI data transfer numbers per DMA request */
14323 #define FSL_SAI_MAXBURST_TX 6
14324 #define FSL_SAI_MAXBURST_RX 6
14325
14326+#define SAI_FLAG_PMQOS   BIT(0)
14327+
14328 struct fsl_sai_soc_data {
14329 	bool use_imx_pcm;
14330 	bool use_edma;
14331 	unsigned int fifo_depth;
14332 	unsigned int reg_offset;
14333+	unsigned int fifos;
14334+	unsigned int dataline;
14335+	unsigned int flags;
14336+	unsigned int max_register;
14337 };
14338
14339 /**
14340@@ -249,16 +260,39 @@ struct fsl_sai_param {
14341 	u32 dataline;
14342 };
14343
14344+struct fsl_sai_dl_cfg {
14345+	unsigned int pins;
14346+	unsigned int mask[2];
14347+	unsigned int start_off[2];
14348+	unsigned int next_off[2];
14349+};
14350+
14351 struct fsl_sai {
14352 	struct platform_device *pdev;
14353 	struct regmap *regmap;
14354+	struct regmap *regmap_gpr;
14355 	struct clk *bus_clk;
14356 	struct clk *mclk_clk[FSL_SAI_MCLK_MAX];
14357+	struct clk *pll8k_clk;
14358+	struct clk *pll11k_clk;
14359+	struct resource *res;
14360
14361-	bool is_slave_mode;
14362+	bool slave_mode[2];
14363 	bool is_lsb_first;
14364 	bool is_dsp_mode;
14365+	bool is_multi_lane;
14366 	bool synchronous[2];
14367+	bool is_dsd;
14368+	bool monitor_spdif;
14369+	bool monitor_spdif_start;
14370+
14371+	int gpr_idx;
14372+	int pcm_dl_cfg_cnt;
14373+	int dsd_dl_cfg_cnt;
14374+	struct fsl_sai_dl_cfg *pcm_dl_cfg;
14375+	struct fsl_sai_dl_cfg *dsd_dl_cfg;
14376+
14377+	unsigned int masterflag[2];
14378
14379 	unsigned int mclk_id[2];
14380 	unsigned int mclk_streams;
14381@@ -272,8 +306,14 @@ struct fsl_sai {
14382 	struct snd_dmaengine_dai_dma_data dma_params_tx;
14383 	struct fsl_sai_verid verid;
14384 	struct fsl_sai_param param;
14385+	struct pm_qos_request pm_qos_req;
14386+	struct sdma_audio_config audio_config[2];
14387+	struct pinctrl *pinctrl;
14388+	struct pinctrl_state *pins_state;
14389 };
14390
14391+const struct attribute_group *fsl_sai_get_dev_attribute_group(bool monitor_spdif);
14392+
14393 #define TX 1
14394 #define RX 0
14395
14396diff --git a/sound/soc/fsl/fsl_sai_sysfs.c b/sound/soc/fsl/fsl_sai_sysfs.c
14397new file mode 100644
14398index 000000000..609227e00
14399--- /dev/null
14400+++ b/sound/soc/fsl/fsl_sai_sysfs.c
14401@@ -0,0 +1,312 @@
14402+// SPDX-License-Identifier: GPL-2.0+
14403+// Copyright 2020 NXP
14404+
14405+#include <linux/clk.h>
14406+#include <linux/module.h>
14407+#include <linux/mutex.h>
14408+#include <linux/kdev_t.h>
14409+#include <linux/pm_runtime.h>
14410+#include <linux/mfd/syscon/imx7-iomuxc-gpr.h>
14411+
14412+#include "fsl_sai.h"
14413+
14414+static ssize_t tx_bitcnt_show(struct device *dev,
14415+		struct device_attribute *attr, char *buf)
14416+{
14417+	struct fsl_sai *sai = dev_get_drvdata(dev);
14418+	unsigned int val = 0;
14419+
14420+	/* read bitcounter */
14421+	regmap_read(sai->regmap, FSL_SAI_TBCTN, &val);
14422+
14423+	return sprintf(buf, "%u\n", val);
14424+}
14425+static DEVICE_ATTR_RO(tx_bitcnt);
14426+
14427+static ssize_t tx_timestamp_show(struct device *dev,
14428+		struct device_attribute *attr, char *buf)
14429+{
14430+	struct fsl_sai *sai = dev_get_drvdata(dev);
14431+	unsigned int val = 0;
14432+
14433+	/* read timestamp */
14434+	regmap_read(sai->regmap, FSL_SAI_TTCTN, &val);
14435+
14436+	return sprintf(buf, "%u\n", val);
14437+}
14438+static DEVICE_ATTR_RO(tx_timestamp);
14439+
14440+static ssize_t tx_bitcnt_latched_timestamp_show(struct device *dev,
14441+		struct device_attribute *attr, char *buf)
14442+{
14443+	struct fsl_sai *sai = dev_get_drvdata(dev);
14444+	unsigned int val = 0;
14445+
14446+	/* read timestamp */
14447+	regmap_read(sai->regmap, FSL_SAI_TTCAP, &val);
14448+
14449+	return sprintf(buf, "%u\n", val);
14450+}
14451+static DEVICE_ATTR_RO(tx_bitcnt_latched_timestamp);
14452+
14453+static ssize_t
14454+tx_timestamp_enable_store(struct device *dev, struct device_attribute *attr,
14455+		const char *buf, size_t n)
14456+{
14457+	struct fsl_sai *sai = dev_get_drvdata(dev);
14458+	unsigned int val = 0;
14459+
14460+	if (kstrtouint(buf, 0, &val))
14461+		return -EINVAL;
14462+
14463+	if (val != 0)
14464+		val = FSL_SAI_xTCTL_TSEN;
14465+	regmap_update_bits(sai->regmap, FSL_SAI_TTCTL, FSL_SAI_xTCTL_TSEN, val);
14466+	return n;
14467+}
14468+static DEVICE_ATTR_WO(tx_timestamp_enable);
14469+
14470+static ssize_t
14471+tx_timestamp_increment_store(struct device *dev, struct device_attribute *attr,
14472+		const char *buf, size_t n)
14473+{
14474+	struct fsl_sai *sai = dev_get_drvdata(dev);
14475+	unsigned int val = 0;
14476+
14477+	if (kstrtouint(buf, 0, &val))
14478+		return -EINVAL;
14479+
14480+	if (val != 0)
14481+		val = FSL_SAI_xTCTL_TSINC;
14482+	regmap_update_bits(sai->regmap, FSL_SAI_TTCTL, FSL_SAI_xTCTL_TSINC, val);
14483+	return n;
14484+}
14485+static DEVICE_ATTR_WO(tx_timestamp_increment);
14486+
14487+static ssize_t
14488+tx_bitcnt_reset_store(struct device *dev, struct device_attribute *attr,
14489+		const char *buf, size_t n)
14490+{
14491+	struct fsl_sai *sai = dev_get_drvdata(dev);
14492+	unsigned int val = 0;
14493+
14494+	if (kstrtouint(buf, 0, &val))
14495+		return -EINVAL;
14496+
14497+	if (val != 0)
14498+		val = FSL_SAI_xTCTL_RBC;
14499+	regmap_update_bits(sai->regmap, FSL_SAI_TTCTL, FSL_SAI_xTCTL_RBC, val);
14500+	return n;
14501+}
14502+static DEVICE_ATTR_WO(tx_bitcnt_reset);
14503+
14504+static ssize_t
14505+tx_timestamp_reset_store(struct device *dev, struct device_attribute *attr,
14506+		const char *buf, size_t n)
14507+{
14508+	struct fsl_sai *sai = dev_get_drvdata(dev);
14509+	unsigned int val = 0;
14510+
14511+	if (kstrtouint(buf, 0, &val))
14512+		return -EINVAL;
14513+
14514+	if (val != 0)
14515+		val = FSL_SAI_xTCTL_RTSC;
14516+	regmap_update_bits(sai->regmap, FSL_SAI_TTCTL, FSL_SAI_xTCTL_RTSC, val);
14517+	return n;
14518+}
14519+static DEVICE_ATTR_WO(tx_timestamp_reset);
14520+
14521+
14522+static ssize_t rx_bitcnt_show(struct device *dev,
14523+		struct device_attribute *attr, char *buf)
14524+{
14525+	struct fsl_sai *sai = dev_get_drvdata(dev);
14526+	unsigned int val = 0;
14527+
14528+	/* read bitcounter */
14529+	regmap_read(sai->regmap, FSL_SAI_RBCTN, &val);
14530+
14531+	return sprintf(buf, "%u\n", val);
14532+}
14533+static DEVICE_ATTR_RO(rx_bitcnt);
14534+
14535+static ssize_t rx_timestamp_show(struct device *dev,
14536+		struct device_attribute *attr, char *buf)
14537+{
14538+	struct fsl_sai *sai = dev_get_drvdata(dev);
14539+	unsigned int val = 0;
14540+
14541+	/* read timestamp */
14542+	regmap_read(sai->regmap, FSL_SAI_RTCTN, &val);
14543+
14544+	return sprintf(buf, "%u\n", val);
14545+}
14546+static DEVICE_ATTR_RO(rx_timestamp);
14547+
14548+static ssize_t rx_bitcnt_latched_timestamp_show(struct device *dev,
14549+		struct device_attribute *attr, char *buf)
14550+{
14551+	struct fsl_sai *sai = dev_get_drvdata(dev);
14552+	unsigned int val = 0;
14553+
14554+	/* read timestamp */
14555+	regmap_read(sai->regmap, FSL_SAI_RTCAP, &val);
14556+
14557+	return sprintf(buf, "%u\n", val);
14558+}
14559+static DEVICE_ATTR_RO(rx_bitcnt_latched_timestamp);
14560+
14561+static ssize_t
14562+rx_timestamp_enable_store(struct device *dev, struct device_attribute *attr,
14563+		const char *buf, size_t n)
14564+{
14565+	struct fsl_sai *sai = dev_get_drvdata(dev);
14566+	unsigned int val = 0;
14567+
14568+	if (kstrtouint(buf, 0, &val))
14569+		return -EINVAL;
14570+
14571+	if (val != 0)
14572+		val = FSL_SAI_xTCTL_TSEN;
14573+	regmap_update_bits(sai->regmap, FSL_SAI_RTCTL, FSL_SAI_xTCTL_TSEN, val);
14574+	return n;
14575+}
14576+static DEVICE_ATTR_WO(rx_timestamp_enable);
14577+
14578+static ssize_t
14579+rx_timestamp_increment_store(struct device *dev, struct device_attribute *attr,
14580+		const char *buf, size_t n)
14581+{
14582+	struct fsl_sai *sai = dev_get_drvdata(dev);
14583+	unsigned int val = 0;
14584+
14585+	if (kstrtouint(buf, 0, &val))
14586+		return -EINVAL;
14587+
14588+	if (val != 0)
14589+		val = FSL_SAI_xTCTL_TSINC;
14590+	regmap_update_bits(sai->regmap, FSL_SAI_RTCTL, FSL_SAI_xTCTL_TSINC, val);
14591+	return n;
14592+}
14593+static DEVICE_ATTR_WO(rx_timestamp_increment);
14594+
14595+static ssize_t
14596+rx_bitcnt_reset_store(struct device *dev, struct device_attribute *attr,
14597+		const char *buf, size_t n)
14598+{
14599+	struct fsl_sai *sai = dev_get_drvdata(dev);
14600+	unsigned int val = 0;
14601+
14602+	if (kstrtouint(buf, 0, &val))
14603+		return -EINVAL;
14604+
14605+	if (val != 0)
14606+		val = FSL_SAI_xTCTL_RBC;
14607+	regmap_update_bits(sai->regmap, FSL_SAI_RTCTL, FSL_SAI_xTCTL_RBC, val);
14608+	return n;
14609+}
14610+static DEVICE_ATTR_WO(rx_bitcnt_reset);
14611+
14612+static ssize_t
14613+rx_timestamp_reset_store(struct device *dev, struct device_attribute *attr,
14614+		const char *buf, size_t n)
14615+{
14616+	struct fsl_sai *sai = dev_get_drvdata(dev);
14617+	unsigned int val = 0;
14618+
14619+	if (kstrtouint(buf, 0, &val))
14620+		return -EINVAL;
14621+
14622+	if (val != 0)
14623+		val = FSL_SAI_xTCTL_RTSC;
14624+	regmap_update_bits(sai->regmap, FSL_SAI_RTCTL, FSL_SAI_xTCTL_RTSC, val);
14625+	return n;
14626+}
14627+static DEVICE_ATTR_WO(rx_timestamp_reset);
14628+
14629+static ssize_t
14630+rx_monitor_spdif_store(struct device *dev, struct device_attribute *attr,
14631+			const char *buf, size_t n)
14632+{
14633+	struct fsl_sai *sai = dev_get_drvdata(dev);
14634+	unsigned char offset = sai->soc_data->reg_offset;
14635+	unsigned int val = 0;
14636+	bool enable = false;
14637+	unsigned int reg;
14638+	unsigned int shift;
14639+	unsigned int mask;
14640+
14641+	if (kstrtouint(buf, 0, &val))
14642+		return -EINVAL;
14643+
14644+	if (val != 0)
14645+		enable = true;
14646+
14647+	if (pm_runtime_active(&sai->pdev->dev) && enable) {
14648+		dev_err(dev, "device is busy\n");
14649+		return -EBUSY;
14650+	}
14651+
14652+	reg = IOMUXC_GPR6 + (sai->gpr_idx - 1) / 2 * 4;
14653+	shift = ((sai->gpr_idx - 1) % 2) * 16;
14654+	mask = 0x1F << shift;
14655+
14656+	if (enable) {
14657+		pm_runtime_get_sync(&sai->pdev->dev);
14658+		/* Fix to MCLK3 */
14659+		regmap_update_bits(sai->regmap_gpr, reg, mask, 0xF << shift);
14660+		regmap_update_bits(sai->regmap, FSL_SAI_xCR2(false, offset),
14661+				   FSL_SAI_CR2_MSEL_MASK, FSL_SAI_CR2_MSEL(0x3));
14662+		regmap_update_bits(sai->regmap, FSL_SAI_xCR2(false, offset),
14663+				   FSL_SAI_CR2_DIV_MASK, 0x0);
14664+		regmap_update_bits(sai->regmap, FSL_SAI_xCR2(false, offset),
14665+				   FSL_SAI_CR2_BCD_MSTR, FSL_SAI_CR2_BCD_MSTR);
14666+		regmap_update_bits(sai->regmap, FSL_SAI_xCR4(false, offset),
14667+				   FSL_SAI_CR4_FSD_MSTR, FSL_SAI_CR4_FSD_MSTR);
14668+		regmap_update_bits(sai->regmap, FSL_SAI_xCSR(false, offset),
14669+				   FSL_SAI_CSR_TERE, FSL_SAI_CSR_TERE);
14670+		sai->monitor_spdif_start = true;
14671+	} else {
14672+		if (sai->monitor_spdif_start) {
14673+			regmap_update_bits(sai->regmap, FSL_SAI_xCSR(false, offset),
14674+					   FSL_SAI_CSR_TERE, 0);
14675+			pm_runtime_put_sync(&sai->pdev->dev);
14676+			sai->monitor_spdif_start = false;
14677+		}
14678+	}
14679+
14680+	return n;
14681+}
14682+static DEVICE_ATTR_WO(rx_monitor_spdif);
14683+
14684+static struct attribute *fsl_sai_attrs[] = {
14685+	&dev_attr_tx_bitcnt.attr,
14686+	&dev_attr_rx_bitcnt.attr,
14687+	&dev_attr_tx_timestamp.attr,
14688+	&dev_attr_rx_timestamp.attr,
14689+	&dev_attr_tx_bitcnt_latched_timestamp.attr,
14690+	&dev_attr_rx_bitcnt_latched_timestamp.attr,
14691+	&dev_attr_tx_timestamp_enable.attr,
14692+	&dev_attr_rx_timestamp_enable.attr,
14693+	&dev_attr_tx_timestamp_increment.attr,
14694+	&dev_attr_rx_timestamp_increment.attr,
14695+	&dev_attr_tx_bitcnt_reset.attr,
14696+	&dev_attr_rx_bitcnt_reset.attr,
14697+	&dev_attr_tx_timestamp_reset.attr,
14698+	&dev_attr_rx_timestamp_reset.attr,
14699+	NULL,
14700+	NULL,
14701+};
14702+
14703+static struct attribute_group fsl_sai_attr_group = {
14704+	.attrs = fsl_sai_attrs,
14705+};
14706+
14707+const struct attribute_group *fsl_sai_get_dev_attribute_group(bool monitor_spdif)
14708+{
14709+	if (monitor_spdif)
14710+		fsl_sai_attrs[ARRAY_SIZE(fsl_sai_attrs) - 2] = &dev_attr_rx_monitor_spdif.attr;
14711+
14712+	return &fsl_sai_attr_group;
14713+}
14714diff --git a/sound/soc/fsl/fsl_spdif.c b/sound/soc/fsl/fsl_spdif.c
14715index 15bcb0f38..24bc0ed5c 100644
14716--- a/sound/soc/fsl/fsl_spdif.c
14717+++ b/sound/soc/fsl/fsl_spdif.c
14718@@ -11,12 +11,14 @@
14719
14720 #include <linux/bitrev.h>
14721 #include <linux/clk.h>
14722+#include <linux/clk-provider.h>
14723 #include <linux/module.h>
14724 #include <linux/of_address.h>
14725 #include <linux/of_device.h>
14726 #include <linux/of_irq.h>
14727 #include <linux/regmap.h>
14728 #include <linux/pm_runtime.h>
14729+#include <linux/busfreq-imx.h>
14730
14731 #include <sound/asoundef.h>
14732 #include <sound/dmaengine_pcm.h>
14733@@ -53,6 +55,13 @@ static u8 srpc_dpll_locked[] = { 0x0, 0x1, 0x2, 0x3, 0x4, 0xa, 0xb };
14734 struct fsl_spdif_soc_data {
14735 	bool imx;
14736 	bool shared_root_clock;
14737+	bool constrain_period_size;
14738+	bool cchannel_192b;
14739+	u32 tx_burst;
14740+	u32 rx_burst;
14741+	u32 interrupts;
14742+	u64 tx_formats;
14743+	u64 rx_rates;
14744 };
14745
14746 /*
14747@@ -114,7 +123,7 @@ struct fsl_spdif_priv {
14748 	u16 sysclk_df[SPDIF_TXRATE_MAX];
14749 	u8 txclk_src[SPDIF_TXRATE_MAX];
14750 	u8 rxclk_src;
14751-	struct clk *txclk[SPDIF_TXRATE_MAX];
14752+	struct clk *txclk[STC_TXCLK_SRC_MAX];
14753 	struct clk *rxclk;
14754 	struct clk *coreclk;
14755 	struct clk *sysclk;
14756@@ -123,21 +132,78 @@ struct fsl_spdif_priv {
14757 	struct snd_dmaengine_dai_dma_data dma_params_rx;
14758 	/* regcache for SRPC */
14759 	u32 regcache_srpc;
14760+	struct clk *pll8k_clk;
14761+	struct clk *pll11k_clk;
14762+	bool bypass;
14763 };
14764
14765 static struct fsl_spdif_soc_data fsl_spdif_vf610 = {
14766 	.imx = false,
14767 	.shared_root_clock = false,
14768+	.tx_burst = FSL_SPDIF_TXFIFO_WML,
14769+	.rx_burst = FSL_SPDIF_RXFIFO_WML,
14770+	.interrupts = 1,
14771+	.tx_formats = FSL_SPDIF_FORMATS_PLAYBACK,
14772+	.rx_rates = FSL_SPDIF_RATES_CAPTURE,
14773+	.constrain_period_size = false,
14774 };
14775
14776 static struct fsl_spdif_soc_data fsl_spdif_imx35 = {
14777 	.imx = true,
14778 	.shared_root_clock = false,
14779+	.tx_burst = FSL_SPDIF_TXFIFO_WML,
14780+	.rx_burst = FSL_SPDIF_RXFIFO_WML,
14781+	.interrupts = 1,
14782+	.tx_formats = FSL_SPDIF_FORMATS_PLAYBACK,
14783+	.rx_rates = FSL_SPDIF_RATES_CAPTURE,
14784+	.constrain_period_size = false,
14785 };
14786
14787 static struct fsl_spdif_soc_data fsl_spdif_imx6sx = {
14788 	.imx = true,
14789 	.shared_root_clock = true,
14790+	.tx_burst = FSL_SPDIF_TXFIFO_WML,
14791+	.rx_burst = FSL_SPDIF_RXFIFO_WML,
14792+	.interrupts = 1,
14793+	.tx_formats = FSL_SPDIF_FORMATS_PLAYBACK,
14794+	.rx_rates = FSL_SPDIF_RATES_CAPTURE,
14795+	.constrain_period_size = false,
14796+
14797+};
14798+
14799+static struct fsl_spdif_soc_data fsl_spdif_imx8qm = {
14800+	.imx = true,
14801+	.shared_root_clock = true,
14802+	.tx_burst = 2,
14803+	.rx_burst = 2,
14804+	.interrupts = 2,
14805+	.tx_formats = SNDRV_PCM_FMTBIT_S24_LE,
14806+	.rx_rates = (FSL_SPDIF_RATES_CAPTURE | SNDRV_PCM_RATE_192000),
14807+	.constrain_period_size = true,
14808+};
14809+
14810+static struct fsl_spdif_soc_data fsl_spdif_imx8ulp = {
14811+	.imx = true,
14812+	.shared_root_clock = true,
14813+	.tx_burst = 2,
14814+	.rx_burst = 2,
14815+	.interrupts = 1,
14816+	.tx_formats = SNDRV_PCM_FMTBIT_S24_LE,
14817+	.rx_rates = (FSL_SPDIF_RATES_CAPTURE | SNDRV_PCM_RATE_192000),
14818+	.constrain_period_size = true,
14819+	.cchannel_192b = true,
14820+};
14821+
14822+static struct fsl_spdif_soc_data fsl_spdif_imx8mm = {
14823+	.imx = true,
14824+	.shared_root_clock = true,
14825+	.tx_burst = FSL_SPDIF_TXFIFO_WML,
14826+	.rx_burst = FSL_SPDIF_RXFIFO_WML,
14827+	.interrupts = 1,
14828+	.tx_formats = FSL_SPDIF_FORMATS_PLAYBACK,
14829+	.rx_rates = (FSL_SPDIF_RATES_CAPTURE | SNDRV_PCM_RATE_88200 |
14830+		     SNDRV_PCM_RATE_176400 | SNDRV_PCM_RATE_192000),
14831+	.constrain_period_size = false,
14832 };
14833
14834 /* Check if clk is a root clock that does not share clock source with others */
14835@@ -383,6 +449,24 @@ static void spdif_write_channel_status(struct fsl_spdif_priv *spdif_priv)
14836 	regmap_write(regmap, REG_SPDIF_STCSCL, ch_status);
14837
14838 	dev_dbg(&pdev->dev, "STCSCL: 0x%06x\n", ch_status);
14839+
14840+	if (spdif_priv->soc->cchannel_192b) {
14841+		ch_status = (bitrev8(ctrl->ch_status[0]) << 24) |
14842+			    (bitrev8(ctrl->ch_status[1]) << 16) |
14843+			    (bitrev8(ctrl->ch_status[2]) << 8) |
14844+			    bitrev8(ctrl->ch_status[3]);
14845+
14846+		regmap_update_bits(regmap, REG_SPDIF_SCR, 0x1000000, 0x1000000);
14847+
14848+		/*
14849+		 * FIXME: In theory, the first 32bit should be in
14850+		 * REG_SPDIF_STCCA_31_0 register, but here we need to
14851+		 * set REG_SPDIF_STCCA_191_160 on 8ULP then get correct
14852+		 * result with HDMI analyzer capture. suspect there is
14853+		 * a hardware bug here.
14854+		 */
14855+		regmap_write(regmap, REG_SPDIF_STCCA_191_160, ch_status);
14856+	}
14857 }
14858
14859 /* Set SPDIF PhaseConfig register for rx clock */
14860@@ -429,10 +513,18 @@ static int spdif_set_sample_rate(struct snd_pcm_substream *substream,
14861 		rate = SPDIF_TXRATE_48000;
14862 		csfs = IEC958_AES3_CON_FS_48000;
14863 		break;
14864+	case 88200:
14865+		rate = SPDIF_TXRATE_88200;
14866+		csfs = IEC958_AES3_CON_FS_88200;
14867+		break;
14868 	case 96000:
14869 		rate = SPDIF_TXRATE_96000;
14870 		csfs = IEC958_AES3_CON_FS_96000;
14871 		break;
14872+	case 176400:
14873+		rate = SPDIF_TXRATE_176400;
14874+		csfs = IEC958_AES3_CON_FS_176400;
14875+		break;
14876 	case 192000:
14877 		rate = SPDIF_TXRATE_192000;
14878 		csfs = IEC958_AES3_CON_FS_192000;
14879@@ -471,7 +563,7 @@ static int spdif_set_sample_rate(struct snd_pcm_substream *substream,
14880 	dev_dbg(&pdev->dev, "expected clock rate = %d\n",
14881 			(64 * sample_rate * txclk_df * sysclk_df));
14882 	dev_dbg(&pdev->dev, "actual clock rate = %ld\n",
14883-			clk_get_rate(spdif_priv->txclk[rate]));
14884+			clk_get_rate(spdif_priv->txclk[clk]));
14885
14886 	/* set fs field in consumer channel status */
14887 	spdif_set_cstatus(ctrl, IEC958_AES3_CON_FS, csfs);
14888@@ -528,6 +620,17 @@ static int fsl_spdif_startup(struct snd_pcm_substream *substream,
14889 	/* Power up SPDIF module */
14890 	regmap_update_bits(regmap, REG_SPDIF_SCR, SCR_LOW_POWER, 0);
14891
14892+	if (spdif_priv->soc->constrain_period_size) {
14893+		if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
14894+			snd_pcm_hw_constraint_step(substream->runtime, 0,
14895+				SNDRV_PCM_HW_PARAM_PERIOD_SIZE,
14896+				spdif_priv->dma_params_tx.maxburst);
14897+		else
14898+			snd_pcm_hw_constraint_step(substream->runtime, 0,
14899+				SNDRV_PCM_HW_PARAM_PERIOD_SIZE,
14900+				spdif_priv->dma_params_rx.maxburst);
14901+	}
14902+
14903 	return 0;
14904 }
14905
14906@@ -618,14 +721,183 @@ static int fsl_spdif_trigger(struct snd_pcm_substream *substream,
14907 	return 0;
14908 }
14909
14910+static u32 fsl_spdif_txclk_caldiv(struct fsl_spdif_priv *spdif_priv,
14911+				struct clk *clk, u64 savesub,
14912+				enum spdif_txrate index, bool round)
14913+{
14914+	static const u32 rate[] = { 32000, 44100, 48000, 88200, 96000, 176400,
14915+				    192000, };
14916+	bool is_sysclk = clk_is_match(clk, spdif_priv->sysclk);
14917+	u64 rate_ideal, rate_actual, sub;
14918+	u32 arate;
14919+	u16 sysclk_dfmin, sysclk_dfmax, sysclk_df;
14920+	u8 txclk_df;
14921+
14922+	/* The sysclk has an extra divisor [2, 512] */
14923+	sysclk_dfmin = is_sysclk ? 2 : 1;
14924+	sysclk_dfmax = is_sysclk ? 512 : 1;
14925+
14926+	for (sysclk_df = sysclk_dfmin; sysclk_df <= sysclk_dfmax; sysclk_df++) {
14927+		for (txclk_df = 1; txclk_df <= 128; txclk_df++) {
14928+			rate_ideal = rate[index] * txclk_df * 64ULL;
14929+			if (round)
14930+				rate_actual = clk_round_rate(clk, rate_ideal);
14931+			else
14932+				rate_actual = clk_get_rate(clk);
14933+
14934+			arate = rate_actual / 64;
14935+			arate /= txclk_df * sysclk_df;
14936+
14937+			if (arate == rate[index]) {
14938+				/* We are lucky */
14939+				savesub = 0;
14940+				spdif_priv->txclk_df[index] = txclk_df;
14941+				spdif_priv->sysclk_df[index] = sysclk_df;
14942+				spdif_priv->txrate[index] = arate;
14943+				goto out;
14944+			} else if (arate / rate[index] == 1) {
14945+				/* A little bigger than expect */
14946+				sub = (u64)(arate - rate[index]) * 100000;
14947+				do_div(sub, rate[index]);
14948+				if (sub >= savesub)
14949+					continue;
14950+				savesub = sub;
14951+				spdif_priv->txclk_df[index] = txclk_df;
14952+				spdif_priv->sysclk_df[index] = sysclk_df;
14953+				spdif_priv->txrate[index] = arate;
14954+			} else if (rate[index] / arate == 1) {
14955+				/* A little smaller than expect */
14956+				sub = (u64)(rate[index] - arate) * 100000;
14957+				do_div(sub, rate[index]);
14958+				if (sub >= savesub)
14959+					continue;
14960+				savesub = sub;
14961+				spdif_priv->txclk_df[index] = txclk_df;
14962+				spdif_priv->sysclk_df[index] = sysclk_df;
14963+				spdif_priv->txrate[index] = arate;
14964+			}
14965+		}
14966+	}
14967+
14968+out:
14969+	return savesub;
14970+}
14971+
14972+static int fsl_spdif_probe_txclk(struct fsl_spdif_priv *spdif_priv,
14973+				enum spdif_txrate index)
14974+{
14975+	static const u32 rate[] = { 32000, 44100, 48000, 88200, 96000, 176400,
14976+				    192000, };
14977+	struct platform_device *pdev = spdif_priv->pdev;
14978+	struct device *dev = &pdev->dev;
14979+	u64 savesub = 100000, ret;
14980+	struct clk *clk;
14981+	int i;
14982+
14983+	for (i = 0; i < STC_TXCLK_SRC_MAX; i++) {
14984+		clk = spdif_priv->txclk[i];
14985+		if (IS_ERR(clk)) {
14986+			dev_err(dev, "no rxtx%d clock in devicetree\n", i);
14987+			return PTR_ERR(clk);
14988+		}
14989+		if (!clk_get_rate(clk))
14990+			continue;
14991+
14992+		ret = fsl_spdif_txclk_caldiv(spdif_priv, clk, savesub, index,
14993+					     fsl_spdif_can_set_clk_rate(spdif_priv, i));
14994+		if (savesub == ret)
14995+			continue;
14996+
14997+		savesub = ret;
14998+		spdif_priv->txclk_src[index] = i;
14999+
15000+		/* To quick catch a divisor, we allow a 0.1% deviation */
15001+		if (savesub < 100)
15002+			break;
15003+	}
15004+
15005+	dev_dbg(&pdev->dev, "use rxtx%d as tx clock source for %dHz sample rate\n",
15006+			spdif_priv->txclk_src[index], rate[index]);
15007+	dev_dbg(&pdev->dev, "use txclk df %d for %dHz sample rate\n",
15008+			spdif_priv->txclk_df[index], rate[index]);
15009+	if (clk_is_match(spdif_priv->txclk[spdif_priv->txclk_src[index]], spdif_priv->sysclk))
15010+		dev_dbg(&pdev->dev, "use sysclk df %d for %dHz sample rate\n",
15011+				spdif_priv->sysclk_df[index], rate[index]);
15012+	dev_dbg(&pdev->dev, "the best rate for %dHz sample rate is %dHz\n",
15013+			rate[index], spdif_priv->txrate[index]);
15014+
15015+	return 0;
15016+}
15017+
15018+static int fsl_spdif_set_dai_sysclk(struct snd_soc_dai *cpu_dai,
15019+		int clk_id, unsigned int freq, int dir)
15020+{
15021+	struct fsl_spdif_priv *data = snd_soc_dai_get_drvdata(cpu_dai);
15022+	struct platform_device *pdev = data->pdev;
15023+	struct device *dev = &pdev->dev;
15024+	struct clk *clk, *p, *pll = 0, *npll = 0;
15025+	u64 ratio = freq;
15026+	int ret, i;
15027+	bool reparent = false;
15028+
15029+	if (dir != SND_SOC_CLOCK_OUT || freq == 0 || clk_id != STC_TXCLK_SPDIF_ROOT)
15030+		return 0;
15031+
15032+	if (data->pll8k_clk == NULL || data->pll11k_clk == NULL)
15033+		return 0;
15034+
15035+	clk = data->txclk[clk_id];
15036+	if (IS_ERR_OR_NULL(clk)) {
15037+		dev_err(dev, "no rxtx%d clock in devicetree\n", clk_id);
15038+		return PTR_ERR(clk);
15039+	}
15040+
15041+	p = clk;
15042+	while (p && data->pll8k_clk && data->pll11k_clk) {
15043+		struct clk *pp = clk_get_parent(p);
15044+
15045+		if (clk_is_match(pp, data->pll8k_clk) ||
15046+		    clk_is_match(pp, data->pll11k_clk)) {
15047+			pll = pp;
15048+			break;
15049+		}
15050+		p = pp;
15051+	}
15052+
15053+	npll = (do_div(ratio, 8000) ? data->pll11k_clk : data->pll8k_clk);
15054+	reparent = (pll && !clk_is_match(pll, npll));
15055+
15056+	clk_disable_unprepare(clk);
15057+	if (reparent) {
15058+		ret = clk_set_parent(p, npll);
15059+		if (ret < 0)
15060+			dev_warn(cpu_dai->dev, "failed to set parent %s: %d\n",
15061+				 __clk_get_name(npll), ret);
15062+	}
15063+
15064+	ret = clk_set_rate(clk, freq);
15065+	if (ret < 0)
15066+		dev_warn(cpu_dai->dev, "failed to set clock rate (%u): %d\n",
15067+			 freq, ret);
15068+	clk_prepare_enable(clk);
15069+
15070+	for (i = 0; i < SPDIF_TXRATE_MAX; i++) {
15071+		ret = fsl_spdif_probe_txclk(data, i);
15072+		if (ret)
15073+			return ret;
15074+	}
15075+
15076+	return 0;
15077+}
15078+
15079 static const struct snd_soc_dai_ops fsl_spdif_dai_ops = {
15080 	.startup = fsl_spdif_startup,
15081+	.set_sysclk = fsl_spdif_set_dai_sysclk,
15082 	.hw_params = fsl_spdif_hw_params,
15083 	.trigger = fsl_spdif_trigger,
15084 	.shutdown = fsl_spdif_shutdown,
15085 };
15086
15087-
15088 /*
15089  * FSL SPDIF IEC958 controller(mixer) functions
15090  *
15091@@ -763,18 +1035,6 @@ static int fsl_spdif_qget(struct snd_kcontrol *kcontrol,
15092 	return ret;
15093 }
15094
15095-/* Valid bit information */
15096-static int fsl_spdif_vbit_info(struct snd_kcontrol *kcontrol,
15097-				struct snd_ctl_elem_info *uinfo)
15098-{
15099-	uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
15100-	uinfo->count = 1;
15101-	uinfo->value.integer.min = 0;
15102-	uinfo->value.integer.max = 1;
15103-
15104-	return 0;
15105-}
15106-
15107 /* Get valid good bit from interrupt status register */
15108 static int fsl_spdif_rx_vbit_get(struct snd_kcontrol *kcontrol,
15109 				 struct snd_ctl_elem_value *ucontrol)
15110@@ -820,6 +1080,102 @@ static int fsl_spdif_tx_vbit_put(struct snd_kcontrol *kcontrol,
15111 	return 0;
15112 }
15113
15114+static int fsl_spdif_rx_rcm_get(struct snd_kcontrol *kcontrol,
15115+				struct snd_ctl_elem_value *ucontrol)
15116+{
15117+	struct snd_soc_dai *cpu_dai = snd_kcontrol_chip(kcontrol);
15118+	struct fsl_spdif_priv *spdif_priv = snd_soc_dai_get_drvdata(cpu_dai);
15119+	struct regmap *regmap = spdif_priv->regmap;
15120+	u32 val;
15121+
15122+	regmap_read(regmap, REG_SPDIF_SCR, &val);
15123+	val = (val & SCR_RAW_CAPTURE_MODE) ? 1 : 0;
15124+	ucontrol->value.integer.value[0] = val;
15125+
15126+	return 0;
15127+}
15128+
15129+static int fsl_spdif_rx_rcm_put(struct snd_kcontrol *kcontrol,
15130+				struct snd_ctl_elem_value *ucontrol)
15131+{
15132+	struct snd_soc_dai *cpu_dai = snd_kcontrol_chip(kcontrol);
15133+	struct fsl_spdif_priv *spdif_priv = snd_soc_dai_get_drvdata(cpu_dai);
15134+	struct regmap *regmap = spdif_priv->regmap;
15135+	u32 val = (ucontrol->value.integer.value[0] ? SCR_RAW_CAPTURE_MODE : 0);
15136+
15137+	if (val)
15138+		cpu_dai->driver->capture.formats |= SNDRV_PCM_FMTBIT_S32_LE;
15139+	else
15140+		cpu_dai->driver->capture.formats &= ~SNDRV_PCM_FMTBIT_S32_LE;
15141+
15142+	regmap_update_bits(regmap, REG_SPDIF_SCR, SCR_RAW_CAPTURE_MODE, val);
15143+
15144+	return 0;
15145+}
15146+
15147+static int fsl_spdif_bypass_get(struct snd_kcontrol *kcontrol,
15148+				struct snd_ctl_elem_value *ucontrol)
15149+{
15150+	struct snd_soc_dai *dai = snd_kcontrol_chip(kcontrol);
15151+	struct fsl_spdif_priv *priv = snd_soc_dai_get_drvdata(dai);
15152+
15153+	ucontrol->value.integer.value[0] = priv->bypass ? 1 : 0;
15154+
15155+	return 0;
15156+}
15157+
15158+static int fsl_spdif_bypass_put(struct snd_kcontrol *kcontrol,
15159+				struct snd_ctl_elem_value *ucontrol)
15160+{
15161+	struct snd_soc_dai *dai = snd_kcontrol_chip(kcontrol);
15162+	struct fsl_spdif_priv *priv = snd_soc_dai_get_drvdata(dai);
15163+	struct snd_soc_card *card = dai->component->card;
15164+	struct snd_soc_pcm_runtime *rtd;
15165+	struct regmap *regmap = priv->regmap;
15166+	bool set = (ucontrol->value.integer.value[0] != 0);
15167+	int stream;
15168+	u32 scr, mask;
15169+
15170+	rtd = snd_soc_get_pcm_runtime(card, card->dai_link);
15171+
15172+	if (priv->bypass == set)
15173+		return 0; /* nothing to do */
15174+
15175+	if (snd_soc_dai_active(dai)) {
15176+		dev_err(dai->dev, "Cannot change BYPASS mode while stream is running.\n");
15177+		return -EBUSY;
15178+	}
15179+
15180+	pm_runtime_get_sync(dai->dev);
15181+
15182+	if (set) {
15183+		/* Disable interrupts */
15184+		regmap_update_bits(regmap, REG_SPDIF_SIE, 0xffffff, 0);
15185+
15186+		/* Configure BYPASS mode */
15187+		scr = SCR_TXSEL_RX | SCR_RXFIFO_OFF;
15188+		mask = SCR_RXFIFO_FSEL_MASK | SCR_RXFIFO_AUTOSYNC_MASK |
15189+			SCR_RXFIFO_CTL_MASK | SCR_RXFIFO_OFF_MASK | SCR_TXSEL_MASK;
15190+		/* Power up SPDIF module */
15191+		mask |= SCR_LOW_POWER;
15192+	} else {
15193+		/* Power down SPDIF module, disable TX */
15194+		scr = SCR_LOW_POWER | SCR_TXSEL_OFF;
15195+		mask = SCR_LOW_POWER | SCR_TXSEL_MASK;
15196+	}
15197+
15198+	regmap_update_bits(regmap, REG_SPDIF_SCR, mask, scr);
15199+
15200+	/* Disable playback & capture if BYPASS mode is enabled, enable otherwise */
15201+	for_each_pcm_streams(stream)
15202+		rtd->pcm->streams[stream].substream_count = (set ? 0 : 1);
15203+
15204+	priv->bypass = set;
15205+	pm_runtime_put_sync(dai->dev);
15206+
15207+	return 0;
15208+}
15209+
15210 /* DPLL lock information */
15211 static int fsl_spdif_rxrate_info(struct snd_kcontrol *kcontrol,
15212 				struct snd_ctl_elem_info *uinfo)
15213@@ -887,18 +1243,6 @@ static int fsl_spdif_rxrate_get(struct snd_kcontrol *kcontrol,
15214 	return 0;
15215 }
15216
15217-/* User bit sync mode info */
15218-static int fsl_spdif_usync_info(struct snd_kcontrol *kcontrol,
15219-				struct snd_ctl_elem_info *uinfo)
15220-{
15221-	uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
15222-	uinfo->count = 1;
15223-	uinfo->value.integer.min = 0;
15224-	uinfo->value.integer.max = 1;
15225-
15226-	return 0;
15227-}
15228-
15229 /*
15230  * User bit sync mode:
15231  * 1 CD User channel subcode
15232@@ -980,7 +1324,7 @@ static struct snd_kcontrol_new fsl_spdif_ctrls[] = {
15233 		.name = "IEC958 RX V-Bit Errors",
15234 		.access = SNDRV_CTL_ELEM_ACCESS_READ |
15235 			SNDRV_CTL_ELEM_ACCESS_VOLATILE,
15236-		.info = fsl_spdif_vbit_info,
15237+		.info = snd_ctl_boolean_mono_info,
15238 		.get = fsl_spdif_rx_vbit_get,
15239 	},
15240 	{
15241@@ -989,7 +1333,7 @@ static struct snd_kcontrol_new fsl_spdif_ctrls[] = {
15242 		.access = SNDRV_CTL_ELEM_ACCESS_READ |
15243 			SNDRV_CTL_ELEM_ACCESS_WRITE |
15244 			SNDRV_CTL_ELEM_ACCESS_VOLATILE,
15245-		.info = fsl_spdif_vbit_info,
15246+		.info = snd_ctl_boolean_mono_info,
15247 		.get = fsl_spdif_tx_vbit_get,
15248 		.put = fsl_spdif_tx_vbit_put,
15249 	},
15250@@ -1002,6 +1346,15 @@ static struct snd_kcontrol_new fsl_spdif_ctrls[] = {
15251 		.info = fsl_spdif_rxrate_info,
15252 		.get = fsl_spdif_rxrate_get,
15253 	},
15254+	/* RX bypass controller */
15255+	{
15256+		.iface = SNDRV_CTL_ELEM_IFACE_PCM,
15257+		.name = "Bypass Mode",
15258+		.access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
15259+		.info = snd_ctl_boolean_mono_info,
15260+		.get = fsl_spdif_bypass_get,
15261+		.put = fsl_spdif_bypass_put,
15262+	},
15263 	/* User bit sync mode set/get controller */
15264 	{
15265 		.iface = SNDRV_CTL_ELEM_IFACE_PCM,
15266@@ -1009,10 +1362,20 @@ static struct snd_kcontrol_new fsl_spdif_ctrls[] = {
15267 		.access = SNDRV_CTL_ELEM_ACCESS_READ |
15268 			SNDRV_CTL_ELEM_ACCESS_WRITE |
15269 			SNDRV_CTL_ELEM_ACCESS_VOLATILE,
15270-		.info = fsl_spdif_usync_info,
15271+		.info = snd_ctl_boolean_mono_info,
15272 		.get = fsl_spdif_usync_get,
15273 		.put = fsl_spdif_usync_put,
15274 	},
15275+	{
15276+		.iface = SNDRV_CTL_ELEM_IFACE_PCM,
15277+		.name = "IEC958 Rx Raw Capture Mode Bit",
15278+		.access = SNDRV_CTL_ELEM_ACCESS_READ |
15279+			SNDRV_CTL_ELEM_ACCESS_WRITE |
15280+			SNDRV_CTL_ELEM_ACCESS_VOLATILE,
15281+		.info = snd_ctl_boolean_mono_info,
15282+		.get = fsl_spdif_rx_rcm_get,
15283+		.put = fsl_spdif_rx_rcm_put,
15284+	},
15285 };
15286
15287 static int fsl_spdif_dai_probe(struct snd_soc_dai *dai)
15288@@ -1063,6 +1426,8 @@ static const struct reg_default fsl_spdif_reg_defaults[] = {
15289 	{REG_SPDIF_STR,	   0x00000000},
15290 	{REG_SPDIF_STCSCH, 0x00000000},
15291 	{REG_SPDIF_STCSCL, 0x00000000},
15292+	{REG_SPDIF_STCSPH, 0x00000000},
15293+	{REG_SPDIF_STCSPL, 0x00000000},
15294 	{REG_SPDIF_STC,	   0x00020f00},
15295 };
15296
15297@@ -1082,8 +1447,22 @@ static bool fsl_spdif_readable_reg(struct device *dev, unsigned int reg)
15298 	case REG_SPDIF_SRQ:
15299 	case REG_SPDIF_STCSCH:
15300 	case REG_SPDIF_STCSCL:
15301+	case REG_SPDIF_STCSPH:
15302+	case REG_SPDIF_STCSPL:
15303 	case REG_SPDIF_SRFM:
15304 	case REG_SPDIF_STC:
15305+	case REG_SPDIF_SRCCA_31_0:
15306+	case REG_SPDIF_SRCCA_63_32:
15307+	case REG_SPDIF_SRCCA_95_64:
15308+	case REG_SPDIF_SRCCA_127_96:
15309+	case REG_SPDIF_SRCCA_159_128:
15310+	case REG_SPDIF_SRCCA_191_160:
15311+	case REG_SPDIF_STCCA_31_0:
15312+	case REG_SPDIF_STCCA_63_32:
15313+	case REG_SPDIF_STCCA_95_64:
15314+	case REG_SPDIF_STCCA_127_96:
15315+	case REG_SPDIF_STCCA_159_128:
15316+	case REG_SPDIF_STCCA_191_160:
15317 		return true;
15318 	default:
15319 		return false;
15320@@ -1102,6 +1481,12 @@ static bool fsl_spdif_volatile_reg(struct device *dev, unsigned int reg)
15321 	case REG_SPDIF_SRU:
15322 	case REG_SPDIF_SRQ:
15323 	case REG_SPDIF_SRFM:
15324+	case REG_SPDIF_SRCCA_31_0:
15325+	case REG_SPDIF_SRCCA_63_32:
15326+	case REG_SPDIF_SRCCA_95_64:
15327+	case REG_SPDIF_SRCCA_127_96:
15328+	case REG_SPDIF_SRCCA_159_128:
15329+	case REG_SPDIF_SRCCA_191_160:
15330 		return true;
15331 	default:
15332 		return false;
15333@@ -1120,7 +1505,15 @@ static bool fsl_spdif_writeable_reg(struct device *dev, unsigned int reg)
15334 	case REG_SPDIF_STR:
15335 	case REG_SPDIF_STCSCH:
15336 	case REG_SPDIF_STCSCL:
15337+	case REG_SPDIF_STCSPH:
15338+	case REG_SPDIF_STCSPL:
15339 	case REG_SPDIF_STC:
15340+	case REG_SPDIF_STCCA_31_0:
15341+	case REG_SPDIF_STCCA_63_32:
15342+	case REG_SPDIF_STCCA_95_64:
15343+	case REG_SPDIF_STCCA_127_96:
15344+	case REG_SPDIF_STCCA_159_128:
15345+	case REG_SPDIF_STCCA_191_160:
15346 		return true;
15347 	default:
15348 		return false;
15349@@ -1132,7 +1525,7 @@ static const struct regmap_config fsl_spdif_regmap_config = {
15350 	.reg_stride = 4,
15351 	.val_bits = 32,
15352
15353-	.max_register = REG_SPDIF_STC,
15354+	.max_register = REG_SPDIF_STCCA_191_160,
15355 	.reg_defaults = fsl_spdif_reg_defaults,
15356 	.num_reg_defaults = ARRAY_SIZE(fsl_spdif_reg_defaults),
15357 	.readable_reg = fsl_spdif_readable_reg,
15358@@ -1141,115 +1534,6 @@ static const struct regmap_config fsl_spdif_regmap_config = {
15359 	.cache_type = REGCACHE_FLAT,
15360 };
15361
15362-static u32 fsl_spdif_txclk_caldiv(struct fsl_spdif_priv *spdif_priv,
15363-				struct clk *clk, u64 savesub,
15364-				enum spdif_txrate index, bool round)
15365-{
15366-	static const u32 rate[] = { 32000, 44100, 48000, 96000, 192000 };
15367-	bool is_sysclk = clk_is_match(clk, spdif_priv->sysclk);
15368-	u64 rate_ideal, rate_actual, sub;
15369-	u32 arate;
15370-	u16 sysclk_dfmin, sysclk_dfmax, sysclk_df;
15371-	u8 txclk_df;
15372-
15373-	/* The sysclk has an extra divisor [2, 512] */
15374-	sysclk_dfmin = is_sysclk ? 2 : 1;
15375-	sysclk_dfmax = is_sysclk ? 512 : 1;
15376-
15377-	for (sysclk_df = sysclk_dfmin; sysclk_df <= sysclk_dfmax; sysclk_df++) {
15378-		for (txclk_df = 1; txclk_df <= 128; txclk_df++) {
15379-			rate_ideal = rate[index] * txclk_df * 64ULL;
15380-			if (round)
15381-				rate_actual = clk_round_rate(clk, rate_ideal);
15382-			else
15383-				rate_actual = clk_get_rate(clk);
15384-
15385-			arate = rate_actual / 64;
15386-			arate /= txclk_df * sysclk_df;
15387-
15388-			if (arate == rate[index]) {
15389-				/* We are lucky */
15390-				savesub = 0;
15391-				spdif_priv->txclk_df[index] = txclk_df;
15392-				spdif_priv->sysclk_df[index] = sysclk_df;
15393-				spdif_priv->txrate[index] = arate;
15394-				goto out;
15395-			} else if (arate / rate[index] == 1) {
15396-				/* A little bigger than expect */
15397-				sub = (u64)(arate - rate[index]) * 100000;
15398-				do_div(sub, rate[index]);
15399-				if (sub >= savesub)
15400-					continue;
15401-				savesub = sub;
15402-				spdif_priv->txclk_df[index] = txclk_df;
15403-				spdif_priv->sysclk_df[index] = sysclk_df;
15404-				spdif_priv->txrate[index] = arate;
15405-			} else if (rate[index] / arate == 1) {
15406-				/* A little smaller than expect */
15407-				sub = (u64)(rate[index] - arate) * 100000;
15408-				do_div(sub, rate[index]);
15409-				if (sub >= savesub)
15410-					continue;
15411-				savesub = sub;
15412-				spdif_priv->txclk_df[index] = txclk_df;
15413-				spdif_priv->sysclk_df[index] = sysclk_df;
15414-				spdif_priv->txrate[index] = arate;
15415-			}
15416-		}
15417-	}
15418-
15419-out:
15420-	return savesub;
15421-}
15422-
15423-static int fsl_spdif_probe_txclk(struct fsl_spdif_priv *spdif_priv,
15424-				enum spdif_txrate index)
15425-{
15426-	static const u32 rate[] = { 32000, 44100, 48000, 96000, 192000 };
15427-	struct platform_device *pdev = spdif_priv->pdev;
15428-	struct device *dev = &pdev->dev;
15429-	u64 savesub = 100000, ret;
15430-	struct clk *clk;
15431-	char tmp[16];
15432-	int i;
15433-
15434-	for (i = 0; i < STC_TXCLK_SRC_MAX; i++) {
15435-		sprintf(tmp, "rxtx%d", i);
15436-		clk = devm_clk_get(&pdev->dev, tmp);
15437-		if (IS_ERR(clk)) {
15438-			dev_err(dev, "no rxtx%d clock in devicetree\n", i);
15439-			return PTR_ERR(clk);
15440-		}
15441-		if (!clk_get_rate(clk))
15442-			continue;
15443-
15444-		ret = fsl_spdif_txclk_caldiv(spdif_priv, clk, savesub, index,
15445-					     fsl_spdif_can_set_clk_rate(spdif_priv, i));
15446-		if (savesub == ret)
15447-			continue;
15448-
15449-		savesub = ret;
15450-		spdif_priv->txclk[index] = clk;
15451-		spdif_priv->txclk_src[index] = i;
15452-
15453-		/* To quick catch a divisor, we allow a 0.1% deviation */
15454-		if (savesub < 100)
15455-			break;
15456-	}
15457-
15458-	dev_dbg(&pdev->dev, "use rxtx%d as tx clock source for %dHz sample rate\n",
15459-			spdif_priv->txclk_src[index], rate[index]);
15460-	dev_dbg(&pdev->dev, "use txclk df %d for %dHz sample rate\n",
15461-			spdif_priv->txclk_df[index], rate[index]);
15462-	if (clk_is_match(spdif_priv->txclk[index], spdif_priv->sysclk))
15463-		dev_dbg(&pdev->dev, "use sysclk df %d for %dHz sample rate\n",
15464-				spdif_priv->sysclk_df[index], rate[index]);
15465-	dev_dbg(&pdev->dev, "the best rate for %dHz sample rate is %dHz\n",
15466-			rate[index], spdif_priv->txrate[index]);
15467-
15468-	return 0;
15469-}
15470-
15471 static int fsl_spdif_probe(struct platform_device *pdev)
15472 {
15473 	struct fsl_spdif_priv *spdif_priv;
15474@@ -1257,6 +1541,7 @@ static int fsl_spdif_probe(struct platform_device *pdev)
15475 	struct resource *res;
15476 	void __iomem *regs;
15477 	int irq, ret, i;
15478+	char tmp[16];
15479
15480 	spdif_priv = devm_kzalloc(&pdev->dev, sizeof(*spdif_priv), GFP_KERNEL);
15481 	if (!spdif_priv)
15482@@ -1273,6 +1558,10 @@ static int fsl_spdif_probe(struct platform_device *pdev)
15483 	/* Initialize this copy of the CPU DAI driver structure */
15484 	memcpy(&spdif_priv->cpu_dai_drv, &fsl_spdif_dai, sizeof(fsl_spdif_dai));
15485 	spdif_priv->cpu_dai_drv.name = dev_name(&pdev->dev);
15486+	spdif_priv->cpu_dai_drv.playback.formats =
15487+				spdif_priv->soc->tx_formats;
15488+	spdif_priv->cpu_dai_drv.capture.rates =
15489+				spdif_priv->soc->rx_rates;
15490
15491 	/* Get the addresses and IRQ */
15492 	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
15493@@ -1281,7 +1570,7 @@ static int fsl_spdif_probe(struct platform_device *pdev)
15494 		return PTR_ERR(regs);
15495
15496 	spdif_priv->regmap = devm_regmap_init_mmio_clk(&pdev->dev,
15497-			"core", regs, &fsl_spdif_regmap_config);
15498+			NULL, regs, &fsl_spdif_regmap_config);
15499 	if (IS_ERR(spdif_priv->regmap)) {
15500 		dev_err(&pdev->dev, "regmap init failed\n");
15501 		return PTR_ERR(spdif_priv->regmap);
15502@@ -1298,8 +1587,32 @@ static int fsl_spdif_probe(struct platform_device *pdev)
15503 		return ret;
15504 	}
15505
15506+	if (spdif_priv->soc->interrupts > 1) {
15507+		irq = platform_get_irq(pdev, 1);
15508+		if (irq < 0) {
15509+			dev_err(&pdev->dev, "no irq for node %s\n", pdev->name);
15510+			return irq;
15511+		}
15512+
15513+		ret = devm_request_irq(&pdev->dev, irq, spdif_isr, 0,
15514+			       dev_name(&pdev->dev), spdif_priv);
15515+		if (ret) {
15516+			dev_err(&pdev->dev, "could not claim irq %u\n", irq);
15517+			return ret;
15518+		}
15519+	}
15520+
15521+	for (i = 0; i < STC_TXCLK_SRC_MAX; i++) {
15522+		sprintf(tmp, "rxtx%d", i);
15523+		spdif_priv->txclk[i] = devm_clk_get(&pdev->dev, tmp);
15524+		if (IS_ERR(spdif_priv->txclk[i])) {
15525+			dev_err(&pdev->dev, "no rxtx%d clock in devicetree\n", i);
15526+			return PTR_ERR(spdif_priv->txclk[i]);
15527+		}
15528+	}
15529+
15530 	/* Get system clock for rx clock rate calculation */
15531-	spdif_priv->sysclk = devm_clk_get(&pdev->dev, "rxtx5");
15532+	spdif_priv->sysclk = spdif_priv->txclk[5];
15533 	if (IS_ERR(spdif_priv->sysclk)) {
15534 		dev_err(&pdev->dev, "no sys clock (rxtx5) in devicetree\n");
15535 		return PTR_ERR(spdif_priv->sysclk);
15536@@ -1317,13 +1630,21 @@ static int fsl_spdif_probe(struct platform_device *pdev)
15537 		dev_warn(&pdev->dev, "no spba clock in devicetree\n");
15538
15539 	/* Select clock source for rx/tx clock */
15540-	spdif_priv->rxclk = devm_clk_get(&pdev->dev, "rxtx1");
15541+	spdif_priv->rxclk = spdif_priv->txclk[1];
15542 	if (IS_ERR(spdif_priv->rxclk)) {
15543 		dev_err(&pdev->dev, "no rxtx1 clock in devicetree\n");
15544 		return PTR_ERR(spdif_priv->rxclk);
15545 	}
15546 	spdif_priv->rxclk_src = DEFAULT_RXCLK_SRC;
15547
15548+	spdif_priv->pll8k_clk = devm_clk_get(&pdev->dev, "pll8k");
15549+	if (IS_ERR(spdif_priv->pll8k_clk))
15550+		spdif_priv->pll8k_clk = NULL;
15551+
15552+	spdif_priv->pll11k_clk = devm_clk_get(&pdev->dev, "pll11k");
15553+	if (IS_ERR(spdif_priv->pll11k_clk))
15554+		spdif_priv->pll11k_clk = NULL;
15555+
15556 	for (i = 0; i < SPDIF_TXRATE_MAX; i++) {
15557 		ret = fsl_spdif_probe_txclk(spdif_priv, i);
15558 		if (ret)
15559@@ -1344,8 +1665,8 @@ static int fsl_spdif_probe(struct platform_device *pdev)
15560
15561 	spdif_priv->dpll_locked = false;
15562
15563-	spdif_priv->dma_params_tx.maxburst = FSL_SPDIF_TXFIFO_WML;
15564-	spdif_priv->dma_params_rx.maxburst = FSL_SPDIF_RXFIFO_WML;
15565+	spdif_priv->dma_params_tx.maxburst = spdif_priv->soc->tx_burst;
15566+	spdif_priv->dma_params_rx.maxburst = spdif_priv->soc->rx_burst;
15567 	spdif_priv->dma_params_tx.addr = res->start + REG_SPDIF_STL;
15568 	spdif_priv->dma_params_rx.addr = res->start + REG_SPDIF_SRL;
15569
15570@@ -1394,9 +1715,9 @@ static int fsl_spdif_runtime_suspend(struct device *dev)
15571 			&spdif_priv->regcache_srpc);
15572 	regcache_cache_only(spdif_priv->regmap, true);
15573
15574-	clk_disable_unprepare(spdif_priv->rxclk);
15575+	release_bus_freq(BUS_FREQ_HIGH);
15576
15577-	for (i = 0; i < SPDIF_TXRATE_MAX; i++)
15578+	for (i = 0; i < STC_TXCLK_SRC_MAX; i++)
15579 		clk_disable_unprepare(spdif_priv->txclk[i]);
15580
15581 	if (!IS_ERR(spdif_priv->spbaclk))
15582@@ -1426,15 +1747,13 @@ static int fsl_spdif_runtime_resume(struct device *dev)
15583 		}
15584 	}
15585
15586-	for (i = 0; i < SPDIF_TXRATE_MAX; i++) {
15587+	for (i = 0; i < STC_TXCLK_SRC_MAX; i++) {
15588 		ret = clk_prepare_enable(spdif_priv->txclk[i]);
15589 		if (ret)
15590 			goto disable_tx_clk;
15591 	}
15592
15593-	ret = clk_prepare_enable(spdif_priv->rxclk);
15594-	if (ret)
15595-		goto disable_tx_clk;
15596+	request_bus_freq(BUS_FREQ_HIGH);
15597
15598 	regcache_cache_only(spdif_priv->regmap, false);
15599 	regcache_mark_dirty(spdif_priv->regmap);
15600@@ -1445,12 +1764,10 @@ static int fsl_spdif_runtime_resume(struct device *dev)
15601
15602 	ret = regcache_sync(spdif_priv->regmap);
15603 	if (ret)
15604-		goto disable_rx_clk;
15605+		goto disable_tx_clk;
15606
15607 	return 0;
15608
15609-disable_rx_clk:
15610-	clk_disable_unprepare(spdif_priv->rxclk);
15611 disable_tx_clk:
15612 	for (i--; i >= 0; i--)
15613 		clk_disable_unprepare(spdif_priv->txclk[i]);
15614@@ -1474,6 +1791,7 @@ static const struct of_device_id fsl_spdif_dt_ids[] = {
15615 	{ .compatible = "fsl,imx35-spdif", .data = &fsl_spdif_imx35, },
15616 	{ .compatible = "fsl,vf610-spdif", .data = &fsl_spdif_vf610, },
15617 	{ .compatible = "fsl,imx6sx-spdif", .data = &fsl_spdif_imx6sx, },
15618+	{ .compatible = "fsl,imx8mm-spdif", .data = &fsl_spdif_imx8mm, },
15619 	{}
15620 };
15621 MODULE_DEVICE_TABLE(of, fsl_spdif_dt_ids);
15622diff --git a/sound/soc/fsl/fsl_spdif.h b/sound/soc/fsl/fsl_spdif.h
15623index e6c61e07b..f2d11d164 100644
15624--- a/sound/soc/fsl/fsl_spdif.h
15625+++ b/sound/soc/fsl/fsl_spdif.h
15626@@ -31,9 +31,23 @@
15627 #define REG_SPDIF_STR			0x30	/* SPDIFTxRight Register */
15628 #define REG_SPDIF_STCSCH		0x34	/* SPDIFTxCChannelCons_h Register */
15629 #define REG_SPDIF_STCSCL		0x38	/* SPDIFTxCChannelCons_l Register */
15630+#define REG_SPDIF_STCSPH		0x3C	/* SPDIFTxCChannel_Prof_h Register */
15631+#define REG_SPDIF_STCSPL		0x40	/* SPDIFTxCChannel_Prof_l Register */
15632 #define REG_SPDIF_SRFM			0x44	/* FreqMeas Register */
15633 #define REG_SPDIF_STC			0x50	/* SPDIFTxClk Register */
15634
15635+#define REG_SPDIF_SRCCA_31_0		0x60
15636+#define REG_SPDIF_SRCCA_63_32		0x64
15637+#define REG_SPDIF_SRCCA_95_64		0x68
15638+#define REG_SPDIF_SRCCA_127_96		0x6C
15639+#define REG_SPDIF_SRCCA_159_128		0x70
15640+#define REG_SPDIF_SRCCA_191_160		0x74
15641+#define REG_SPDIF_STCCA_31_0		0x78
15642+#define REG_SPDIF_STCCA_63_32		0x7C
15643+#define REG_SPDIF_STCCA_95_64		0x80
15644+#define REG_SPDIF_STCCA_127_96		0x84
15645+#define REG_SPDIF_STCCA_159_128		0x88
15646+#define REG_SPDIF_STCCA_191_160		0x8C
15647
15648 /* SPDIF Configuration register */
15649 #define SCR_RXFIFO_CTL_OFFSET		23
15650@@ -63,6 +77,7 @@
15651 #define SCR_TXFIFO_FSEL_IF4		(0x1 << SCR_TXFIFO_FSEL_OFFSET)
15652 #define SCR_TXFIFO_FSEL_IF8		(0x2 << SCR_TXFIFO_FSEL_OFFSET)
15653 #define SCR_TXFIFO_FSEL_IF12		(0x3 << SCR_TXFIFO_FSEL_OFFSET)
15654+#define SCR_RAW_CAPTURE_MODE		(1 << 14)
15655 #define SCR_LOW_POWER			(1 << 13)
15656 #define SCR_SOFT_RESET			(1 << 12)
15657 #define SCR_TXFIFO_CTRL_OFFSET		10
15658@@ -163,7 +178,9 @@ enum spdif_txrate {
15659 	SPDIF_TXRATE_32000 = 0,
15660 	SPDIF_TXRATE_44100,
15661 	SPDIF_TXRATE_48000,
15662+	SPDIF_TXRATE_88200,
15663 	SPDIF_TXRATE_96000,
15664+	SPDIF_TXRATE_176400,
15665 	SPDIF_TXRATE_192000,
15666 };
15667 #define SPDIF_TXRATE_MAX		(SPDIF_TXRATE_192000 + 1)
15668@@ -177,7 +194,9 @@ enum spdif_txrate {
15669 #define FSL_SPDIF_RATES_PLAYBACK	(SNDRV_PCM_RATE_32000 |	\
15670 					 SNDRV_PCM_RATE_44100 |	\
15671 					 SNDRV_PCM_RATE_48000 |	\
15672+					 SNDRV_PCM_RATE_88200 | \
15673 					 SNDRV_PCM_RATE_96000 |	\
15674+					 SNDRV_PCM_RATE_176400 | \
15675 					 SNDRV_PCM_RATE_192000)
15676
15677 #define FSL_SPDIF_RATES_CAPTURE		(SNDRV_PCM_RATE_16000 | \
15678diff --git a/sound/soc/fsl/fsl_ssi.c b/sound/soc/fsl/fsl_ssi.c
15679index 1d774c876..ea3541143 100644
15680--- a/sound/soc/fsl/fsl_ssi.c
15681+++ b/sound/soc/fsl/fsl_ssi.c
15682@@ -40,6 +40,9 @@
15683 #include <linux/of_address.h>
15684 #include <linux/of_irq.h>
15685 #include <linux/of_platform.h>
15686+#include <linux/pm_runtime.h>
15687+#include <linux/busfreq-imx.h>
15688+#include <linux/platform_data/dma-imx.h>
15689
15690 #include <sound/core.h>
15691 #include <sound/pcm.h>
15692@@ -255,6 +258,7 @@ struct fsl_ssi {
15693 	bool synchronous;
15694 	bool use_dma;
15695 	bool use_dual_fifo;
15696+	bool use_dyna_fifo;
15697 	bool has_ipg_clk_name;
15698 	unsigned int fifo_depth;
15699 	unsigned int slot_width;
15700@@ -287,6 +291,7 @@ struct fsl_ssi {
15701 	u32 dma_maxburst;
15702
15703 	struct mutex ac97_reg_lock;
15704+	struct sdma_audio_config audio_config[2];
15705 };
15706
15707 /*
15708@@ -643,7 +648,7 @@ static int fsl_ssi_startup(struct snd_pcm_substream *substream,
15709 	 * task from fifo0, fifo1 would be neglected at the end of each
15710 	 * period. But SSI would still access fifo1 with an invalid data.
15711 	 */
15712-	if (ssi->use_dual_fifo)
15713+	if (ssi->use_dual_fifo || ssi->use_dyna_fifo)
15714 		snd_pcm_hw_constraint_step(substream->runtime, 0,
15715 					   SNDRV_PCM_HW_PARAM_PERIOD_SIZE, 2);
15716
15717@@ -808,6 +813,7 @@ static int fsl_ssi_hw_params(struct snd_pcm_substream *substream,
15718 	unsigned int sample_size = params_width(hw_params);
15719 	u32 wl = SSI_SxCCR_WL(sample_size);
15720 	int ret;
15721+	struct fsl_ssi_regvals *vals = ssi->regvals;
15722
15723 	if (fsl_ssi_is_i2s_master(ssi)) {
15724 		ret = fsl_ssi_set_bclk(substream, dai, hw_params);
15725@@ -857,6 +863,32 @@ static int fsl_ssi_hw_params(struct snd_pcm_substream *substream,
15726 	tx2 = tx || ssi->synchronous;
15727 	regmap_update_bits(regs, REG_SSI_SxCCR(tx2), SSI_SxCCR_WL_MASK, wl);
15728
15729+	if (ssi->use_dyna_fifo) {
15730+		if (channels == 1) {
15731+			ssi->audio_config[0].dst_fifo_num = 1;
15732+			ssi->audio_config[1].src_fifo_num = 1;
15733+			ssi->dma_params_tx.peripheral_config = &ssi->audio_config[0];
15734+			ssi->dma_params_tx.peripheral_size = sizeof(ssi->audio_config[0]);
15735+			ssi->dma_params_rx.peripheral_config = &ssi->audio_config[1];
15736+			ssi->dma_params_rx.peripheral_size = sizeof(ssi->audio_config[1]);
15737+			vals[RX].srcr &= ~SSI_SRCR_RFEN1;
15738+			vals[TX].stcr &= ~SSI_STCR_TFEN1;
15739+			vals[RX].scr  &= ~SSI_SCR_TCH_EN;
15740+			vals[TX].scr  &= ~SSI_SCR_TCH_EN;
15741+		} else {
15742+			ssi->audio_config[0].dst_fifo_num = 2;
15743+			ssi->audio_config[1].src_fifo_num = 2;
15744+			ssi->dma_params_tx.peripheral_config = &ssi->audio_config[0];
15745+			ssi->dma_params_tx.peripheral_size = sizeof(ssi->audio_config[0]);
15746+			ssi->dma_params_rx.peripheral_config = &ssi->audio_config[1];
15747+			ssi->dma_params_rx.peripheral_size = sizeof(ssi->audio_config[1]);
15748+			vals[RX].srcr |= SSI_SRCR_RFEN1;
15749+			vals[TX].stcr |= SSI_STCR_TFEN1;
15750+			vals[RX].scr  |= SSI_SCR_TCH_EN;
15751+			vals[TX].scr  |= SSI_SCR_TCH_EN;
15752+		}
15753+	}
15754+
15755 	return 0;
15756 }
15757
15758@@ -1348,6 +1380,8 @@ static int fsl_ssi_imx_probe(struct platform_device *pdev,
15759 		dev_dbg(dev, "failed to get baud clock: %ld\n",
15760 			 PTR_ERR(ssi->baudclk));
15761
15762+	ssi->dma_params_rx.chan_name = "rx";
15763+	ssi->dma_params_tx.chan_name = "tx";
15764 	ssi->dma_params_tx.maxburst = ssi->dma_maxburst;
15765 	ssi->dma_params_rx.maxburst = ssi->dma_maxburst;
15766 	ssi->dma_params_tx.addr = ssi->ssi_phys + REG_SSI_STX0;
15767@@ -1454,6 +1488,8 @@ static int fsl_ssi_probe_from_dt(struct fsl_ssi *ssi)
15768 	if (ssi->use_dma && !ret && dmas[2] == IMX_DMATYPE_SSI_DUAL)
15769 		ssi->use_dual_fifo = true;
15770
15771+	if (ssi->use_dma && !ret && dmas[2] == IMX_DMATYPE_MULTI_SAI)
15772+		ssi->use_dyna_fifo = true;
15773 	/*
15774 	 * Backward compatible for older bindings by manually triggering the
15775 	 * machine driver's probe(). Use /compatible property, including the
15776@@ -1572,6 +1608,7 @@ static int fsl_ssi_probe(struct platform_device *pdev)
15777 	}
15778
15779 	dev_set_drvdata(dev, ssi);
15780+	pm_runtime_enable(&pdev->dev);
15781
15782 	if (ssi->soc->imx) {
15783 		ret = fsl_ssi_imx_probe(pdev, ssi, iomem);
15784@@ -1671,6 +1708,20 @@ static int fsl_ssi_remove(struct platform_device *pdev)
15785 	return 0;
15786 }
15787
15788+#ifdef CONFIG_PM
15789+static int fsl_ssi_runtime_resume(struct device *dev)
15790+{
15791+	request_bus_freq(BUS_FREQ_AUDIO);
15792+	return 0;
15793+}
15794+
15795+static int fsl_ssi_runtime_suspend(struct device *dev)
15796+{
15797+	release_bus_freq(BUS_FREQ_AUDIO);
15798+	return 0;
15799+}
15800+#endif
15801+
15802 #ifdef CONFIG_PM_SLEEP
15803 static int fsl_ssi_suspend(struct device *dev)
15804 {
15805@@ -1705,6 +1756,8 @@ static int fsl_ssi_resume(struct device *dev)
15806
15807 static const struct dev_pm_ops fsl_ssi_pm = {
15808 	SET_SYSTEM_SLEEP_PM_OPS(fsl_ssi_suspend, fsl_ssi_resume)
15809+	SET_RUNTIME_PM_OPS(fsl_ssi_runtime_suspend, fsl_ssi_runtime_resume,
15810+			   NULL)
15811 };
15812
15813 static struct platform_driver fsl_ssi_driver = {
15814diff --git a/sound/soc/fsl/imx-audio-rpmsg.c b/sound/soc/fsl/imx-audio-rpmsg.c
15815new file mode 100644
15816index 000000000..2938bdfc7
15817--- /dev/null
15818+++ b/sound/soc/fsl/imx-audio-rpmsg.c
15819@@ -0,0 +1,178 @@
15820+// SPDX-License-Identifier: GPL-2.0+
15821+// Copyright 2017-2020 NXP
15822+
15823+#include <linux/module.h>
15824+#include <linux/rpmsg.h>
15825+#include "imx-pcm-rpmsg.h"
15826+
15827+/*
15828+ * struct imx_audio_rpmsg: private data
15829+ *
15830+ * @rpmsg_pdev: pointer of platform device
15831+ */
15832+struct imx_audio_rpmsg {
15833+	struct platform_device *rpmsg_pdev;
15834+};
15835+
15836+static int imx_audio_rpmsg_cb(struct rpmsg_device *rpdev, void *data, int len,
15837+			      void *priv, u32 src)
15838+{
15839+	struct imx_audio_rpmsg *rpmsg = dev_get_drvdata(&rpdev->dev);
15840+	struct rpmsg_r_msg *r_msg = (struct rpmsg_r_msg *)data;
15841+	struct rpmsg_info *info;
15842+	struct rpmsg_msg *msg;
15843+	unsigned long flags;
15844+
15845+	if (!rpmsg->rpmsg_pdev)
15846+		return 0;
15847+
15848+	info = platform_get_drvdata(rpmsg->rpmsg_pdev);
15849+
15850+	dev_dbg(&rpdev->dev, "get from%d: cmd:%d. %d\n",
15851+		src, r_msg->header.cmd, r_msg->param.resp);
15852+
15853+	switch (r_msg->header.type) {
15854+	case MSG_TYPE_C:
15855+		/* TYPE C is notification from M core */
15856+		switch (r_msg->header.cmd) {
15857+		case TX_PERIOD_DONE:
15858+			spin_lock_irqsave(&info->lock[TX], flags);
15859+			msg = &info->msg[TX_PERIOD_DONE + MSG_TYPE_A_NUM];
15860+			msg->r_msg.param.buffer_tail =
15861+						r_msg->param.buffer_tail;
15862+			msg->r_msg.param.buffer_tail %= info->num_period[TX];
15863+			spin_unlock_irqrestore(&info->lock[TX], flags);
15864+			info->callback[TX](info->callback_param[TX]);
15865+			break;
15866+		case RX_PERIOD_DONE:
15867+			spin_lock_irqsave(&info->lock[RX], flags);
15868+			msg = &info->msg[RX_PERIOD_DONE + MSG_TYPE_A_NUM];
15869+			msg->r_msg.param.buffer_tail =
15870+						r_msg->param.buffer_tail;
15871+			msg->r_msg.param.buffer_tail %= info->num_period[1];
15872+			spin_unlock_irqrestore(&info->lock[RX], flags);
15873+			info->callback[RX](info->callback_param[RX]);
15874+			break;
15875+		default:
15876+			dev_warn(&rpdev->dev, "unknown msg command\n");
15877+			break;
15878+		}
15879+		break;
15880+	case MSG_TYPE_B:
15881+		/* TYPE B is response msg */
15882+		memcpy(&info->r_msg, r_msg, sizeof(struct rpmsg_r_msg));
15883+		complete(&info->cmd_complete);
15884+		break;
15885+	default:
15886+		dev_warn(&rpdev->dev, "unknown msg type\n");
15887+		break;
15888+	}
15889+
15890+	return 0;
15891+}
15892+
15893+static int imx_audio_rpmsg_probe(struct rpmsg_device *rpdev)
15894+{
15895+	struct imx_audio_rpmsg *data;
15896+	struct platform_device *codec_pdev;
15897+	struct rpmsg_codec codec;
15898+	const char *model_string;
15899+	struct device_node *np;
15900+	int ret = 0;
15901+
15902+	dev_info(&rpdev->dev, "new channel: 0x%x -> 0x%x!\n",
15903+		 rpdev->src, rpdev->dst);
15904+
15905+	data = devm_kzalloc(&rpdev->dev, sizeof(*data), GFP_KERNEL);
15906+	if (!data)
15907+		return -ENOMEM;
15908+
15909+	dev_set_drvdata(&rpdev->dev, data);
15910+
15911+	/* Register platform driver for rpmsg routine */
15912+	data->rpmsg_pdev = platform_device_register_data(&rpdev->dev,
15913+							 IMX_PCM_DRV_NAME,
15914+							 PLATFORM_DEVID_AUTO,
15915+							 NULL, 0);
15916+	if (IS_ERR(data->rpmsg_pdev)) {
15917+		dev_err(&rpdev->dev, "failed to register rpmsg platform.\n");
15918+		ret = PTR_ERR(data->rpmsg_pdev);
15919+	}
15920+
15921+	if (!strcmp(rpdev->id.name, "rpmsg-micfil-channel"))
15922+		return ret;
15923+	np = of_find_node_by_name(NULL, "rpmsg_audio");
15924+	of_property_read_string(np, "model", &model_string);
15925+	if (np && of_device_is_compatible(np, "fsl,imx7ulp-rpmsg-audio")) {
15926+		codec.audioindex = 0;
15927+		codec.shared_lrclk = true;
15928+		codec.capless = false;
15929+		codec_pdev = platform_device_register_data(&data->rpmsg_pdev->dev,
15930+							   RPMSG_CODEC_DRV_NAME_WM8960,
15931+							   PLATFORM_DEVID_NONE,
15932+							   &codec,
15933+							   sizeof(struct rpmsg_codec));
15934+		if (IS_ERR(codec_pdev)) {
15935+			dev_err(&rpdev->dev, "failed to register rpmsg codec\n");
15936+			ret = PTR_ERR(codec_pdev);
15937+			goto fail;
15938+		}
15939+	} else if (np && of_device_is_compatible(np, "fsl,imx8mm-rpmsg-audio") &&
15940+			!strcmp("ak4497-audio", model_string)) {
15941+		codec.audioindex = 0;
15942+		codec_pdev = platform_device_register_data(&data->rpmsg_pdev->dev,
15943+							   RPMSG_CODEC_DRV_NAME_AK4497,
15944+							   PLATFORM_DEVID_NONE,
15945+							   &codec,
15946+							   sizeof(struct rpmsg_codec));
15947+		if (IS_ERR(codec_pdev)) {
15948+			dev_err(&rpdev->dev, "failed to register rpmsg codec\n");
15949+			ret = PTR_ERR(codec_pdev);
15950+			goto fail;
15951+		}
15952+	}
15953+fail:
15954+	return ret;
15955+}
15956+
15957+static void imx_audio_rpmsg_remove(struct rpmsg_device *rpdev)
15958+{
15959+	struct imx_audio_rpmsg *data = dev_get_drvdata(&rpdev->dev);
15960+
15961+	if (data->rpmsg_pdev)
15962+		platform_device_unregister(data->rpmsg_pdev);
15963+
15964+	dev_info(&rpdev->dev, "audio rpmsg driver is removed\n");
15965+}
15966+
15967+static struct rpmsg_device_id imx_audio_rpmsg_id_table[] = {
15968+	{ .name	= "rpmsg-audio-channel" },
15969+	{ .name = "rpmsg-micfil-channel" },
15970+	{ },
15971+};
15972+
15973+static struct rpmsg_driver imx_audio_rpmsg_driver = {
15974+	.drv.name	= "imx_audio_rpmsg",
15975+	.drv.owner	= THIS_MODULE,
15976+	.id_table	= imx_audio_rpmsg_id_table,
15977+	.probe		= imx_audio_rpmsg_probe,
15978+	.callback	= imx_audio_rpmsg_cb,
15979+	.remove		= imx_audio_rpmsg_remove,
15980+};
15981+
15982+static int __init imx_audio_rpmsg_init(void)
15983+{
15984+	return register_rpmsg_driver(&imx_audio_rpmsg_driver);
15985+}
15986+
15987+static void __exit imx_audio_rpmsg_exit(void)
15988+{
15989+	unregister_rpmsg_driver(&imx_audio_rpmsg_driver);
15990+}
15991+module_init(imx_audio_rpmsg_init);
15992+module_exit(imx_audio_rpmsg_exit);
15993+
15994+MODULE_DESCRIPTION("Freescale SoC Audio RPMSG interface");
15995+MODULE_AUTHOR("Shengjiu Wang <shengjiu.wang@nxp.com>");
15996+MODULE_ALIAS("platform:imx_audio_rpmsg");
15997+MODULE_LICENSE("GPL v2");
15998diff --git a/sound/soc/fsl/imx-cdnhdmi.c b/sound/soc/fsl/imx-cdnhdmi.c
15999new file mode 100644
16000index 000000000..cc7cf878a
16001--- /dev/null
16002+++ b/sound/soc/fsl/imx-cdnhdmi.c
16003@@ -0,0 +1,590 @@
16004+/*
16005+ * Copyright 2017-2018 NXP
16006+ *
16007+ * The code contained herein is licensed under the GNU General Public
16008+ * License. You may obtain a copy of the GNU General Public License
16009+ * Version 2 or later at the following locations:
16010+ *
16011+ * http://www.opensource.org/licenses/gpl-license.html
16012+ * http://www.gnu.org/copyleft/gpl.html
16013+ */
16014+
16015+#include <linux/module.h>
16016+#include <linux/of_platform.h>
16017+#include <linux/i2c.h>
16018+#include <linux/of_gpio.h>
16019+#include <linux/slab.h>
16020+#include <linux/gpio.h>
16021+#include <linux/clk.h>
16022+#include <sound/soc.h>
16023+#include <sound/jack.h>
16024+#include <sound/control.h>
16025+#include <sound/pcm_params.h>
16026+#include <sound/soc-dapm.h>
16027+#include <sound/hdmi-codec.h>
16028+#include <drm/drm_connector.h>
16029+#include "fsl_sai.h"
16030+
16031+#define SUPPORT_RATE_NUM 10
16032+#define SUPPORT_CHANNEL_NUM 10
16033+
16034+struct imx_cdnhdmi_data {
16035+	struct snd_soc_dai_link dai;
16036+	struct snd_soc_card card;
16037+	struct snd_soc_jack hdmi_jack;
16038+	struct snd_soc_jack_pin hdmi_jack_pin;
16039+	int protocol;
16040+	u32 support_rates[SUPPORT_RATE_NUM];
16041+	u32 support_rates_num;
16042+	u32 support_channels[SUPPORT_CHANNEL_NUM];
16043+	u32 support_channels_num;
16044+	u32 edid_rates[SUPPORT_RATE_NUM];
16045+	u32 edid_rates_count;
16046+	u32 edid_channels[SUPPORT_CHANNEL_NUM];
16047+	u32 edid_channels_count;
16048+	uint8_t eld[MAX_ELD_BYTES];
16049+};
16050+
16051+static int imx_cdnhdmi_startup(struct snd_pcm_substream *substream)
16052+{
16053+	struct snd_pcm_runtime *runtime = substream->runtime;
16054+	struct snd_soc_pcm_runtime *rtd = substream->private_data;
16055+	struct snd_soc_card *card = rtd->card;
16056+	struct imx_cdnhdmi_data *data = snd_soc_card_get_drvdata(card);
16057+	static struct snd_pcm_hw_constraint_list constraint_rates;
16058+	static struct snd_pcm_hw_constraint_list constraint_channels;
16059+	int ret;
16060+
16061+	constraint_rates.list = data->support_rates;
16062+	constraint_rates.count = data->support_rates_num;
16063+
16064+	ret = snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_RATE,
16065+						&constraint_rates);
16066+	if (ret)
16067+		return ret;
16068+
16069+	constraint_channels.list = data->support_channels;
16070+	constraint_channels.count = data->support_channels_num;
16071+
16072+	ret = snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_CHANNELS,
16073+						&constraint_channels);
16074+	if (ret)
16075+		return ret;
16076+
16077+	return 0;
16078+}
16079+
16080+static int imx_cdnhdmi_hw_params(struct snd_pcm_substream *substream,
16081+				     struct snd_pcm_hw_params *params)
16082+{
16083+	struct snd_soc_pcm_runtime *rtd = substream->private_data;
16084+	struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(rtd, 0);
16085+	struct snd_soc_card *card = rtd->card;
16086+	struct device *dev = card->dev;
16087+	bool tx = substream->stream == SNDRV_PCM_STREAM_PLAYBACK;
16088+	int ret;
16089+
16090+	/* set cpu DAI configuration */
16091+	if (tx)
16092+		ret = snd_soc_dai_set_fmt(cpu_dai,
16093+			SND_SOC_DAIFMT_I2S |
16094+			SND_SOC_DAIFMT_NB_NF |
16095+			SND_SOC_DAIFMT_CBS_CFS);
16096+	else
16097+		ret = snd_soc_dai_set_fmt(cpu_dai,
16098+			SND_SOC_DAIFMT_I2S |
16099+			SND_SOC_DAIFMT_NB_NF |
16100+			SND_SOC_DAIFMT_CBM_CFM);
16101+
16102+	if (ret) {
16103+		dev_err(dev, "failed to set cpu dai fmt: %d\n", ret);
16104+		return ret;
16105+	}
16106+
16107+
16108+	if (of_device_is_compatible(dev->of_node,
16109+				    "fsl,imx8mq-evk-cdnhdmi"))
16110+		ret = snd_soc_dai_set_sysclk(cpu_dai, FSL_SAI_CLK_MAST1,
16111+				256 * params_rate(params),
16112+				SND_SOC_CLOCK_OUT);
16113+	else
16114+		ret = snd_soc_dai_set_sysclk(cpu_dai, 0,
16115+				0,
16116+				tx ? SND_SOC_CLOCK_OUT : SND_SOC_CLOCK_IN);
16117+	if (ret) {
16118+		dev_err(dev, "failed to set cpu sysclk: %d\n", ret);
16119+		return ret;
16120+	}
16121+
16122+	ret = snd_soc_dai_set_tdm_slot(cpu_dai, 0, 0, 2, 32);
16123+	if (ret) {
16124+		dev_err(dev, "failed to set cpu dai tdm slot: %d\n", ret);
16125+		return ret;
16126+	}
16127+
16128+	return 0;
16129+}
16130+
16131+static struct snd_soc_ops imx_cdnhdmi_ops = {
16132+	.startup = imx_cdnhdmi_startup,
16133+	.hw_params = imx_cdnhdmi_hw_params,
16134+};
16135+
16136+static const unsigned int eld_rates[] = {
16137+	32000,
16138+	44100,
16139+	48000,
16140+	88200,
16141+	96000,
16142+	176400,
16143+	192000,
16144+};
16145+
16146+static unsigned int sad_max_channels(const u8 *sad)
16147+{
16148+	return 1 + (sad[0] & 7);
16149+}
16150+
16151+static int get_edid_info(struct snd_soc_card *card)
16152+{
16153+	struct snd_soc_pcm_runtime *rtd = list_first_entry(
16154+		&card->rtd_list, struct snd_soc_pcm_runtime, list);
16155+	struct snd_soc_dai *codec_dai = asoc_rtd_to_codec(rtd, 0);
16156+	struct snd_soc_component *component = codec_dai->component;
16157+	struct hdmi_codec_pdata *hcd = component->dev->platform_data;
16158+	struct imx_cdnhdmi_data *data = snd_soc_card_get_drvdata(card);
16159+	int i, j, ret;
16160+	const u8 *sad;
16161+	unsigned int channel_max = 0;
16162+	unsigned int rate_mask = 0;
16163+	unsigned int rate_mask_eld = 0;
16164+
16165+	ret = hcd->ops->get_eld(component->dev->parent, hcd->data,
16166+					    data->eld, sizeof(data->eld));
16167+	sad = drm_eld_sad(data->eld);
16168+	if (sad) {
16169+		for (j = 0; j < data->support_rates_num; j++) {
16170+			for (i = 0; i < ARRAY_SIZE(eld_rates); i++)
16171+				if (eld_rates[i] == data->support_rates[j])
16172+					rate_mask |= BIT(i);
16173+		}
16174+
16175+		for (i = drm_eld_sad_count(data->eld); i > 0; i--, sad += 3) {
16176+			if (rate_mask & sad[1])
16177+				channel_max = max(channel_max, sad_max_channels(sad));
16178+
16179+			if (sad_max_channels(sad) >= 2)
16180+				rate_mask_eld |= sad[1];
16181+		}
16182+	}
16183+
16184+	rate_mask = rate_mask & rate_mask_eld;
16185+
16186+	data->edid_rates_count = 0;
16187+	data->edid_channels_count = 0;
16188+
16189+	for (i = 0; i < ARRAY_SIZE(eld_rates); i++) {
16190+		if (rate_mask & BIT(i)) {
16191+			data->edid_rates[data->edid_rates_count] = eld_rates[i];
16192+			data->edid_rates_count++;
16193+		}
16194+	}
16195+
16196+	for (i = 0; i < data->support_channels_num; i++) {
16197+		if (data->support_channels[i] <= channel_max) {
16198+			data->edid_channels[data->edid_channels_count]
16199+					= data->support_channels[i];
16200+			data->edid_channels_count++;
16201+		}
16202+	}
16203+
16204+	return 0;
16205+}
16206+
16207+static int imx_cdnhdmi_channels_info(struct snd_kcontrol *kcontrol,
16208+			     struct snd_ctl_elem_info *uinfo)
16209+{
16210+	struct snd_soc_card *card = snd_kcontrol_chip(kcontrol);
16211+	struct imx_cdnhdmi_data *data = snd_soc_card_get_drvdata(card);
16212+
16213+	get_edid_info(card);
16214+
16215+	uinfo->type  = SNDRV_CTL_ELEM_TYPE_INTEGER;
16216+	uinfo->count = data->edid_channels_count;
16217+
16218+	return 0;
16219+}
16220+
16221+static int imx_cdnhdmi_channels_get(struct snd_kcontrol *kcontrol,
16222+			    struct snd_ctl_elem_value *uvalue)
16223+{
16224+	struct snd_soc_card *card = snd_kcontrol_chip(kcontrol);
16225+	struct imx_cdnhdmi_data *data = snd_soc_card_get_drvdata(card);
16226+	int i;
16227+
16228+	get_edid_info(card);
16229+
16230+	for (i = 0 ; i < data->edid_channels_count ; i++)
16231+		uvalue->value.integer.value[i] = data->edid_channels[i];
16232+
16233+	return 0;
16234+}
16235+
16236+static int imx_cdnhdmi_rates_info(struct snd_kcontrol *kcontrol,
16237+			     struct snd_ctl_elem_info *uinfo)
16238+{
16239+	struct snd_soc_card *card = snd_kcontrol_chip(kcontrol);
16240+	struct imx_cdnhdmi_data *data = snd_soc_card_get_drvdata(card);
16241+
16242+	get_edid_info(card);
16243+
16244+	uinfo->type  = SNDRV_CTL_ELEM_TYPE_INTEGER;
16245+	uinfo->count = data->edid_rates_count;
16246+
16247+	return 0;
16248+}
16249+
16250+static int imx_cdnhdmi_rates_get(struct snd_kcontrol *kcontrol,
16251+			    struct snd_ctl_elem_value *uvalue)
16252+{
16253+	struct snd_soc_card *card = snd_kcontrol_chip(kcontrol);
16254+	struct imx_cdnhdmi_data *data = snd_soc_card_get_drvdata(card);
16255+	int i;
16256+
16257+	get_edid_info(card);
16258+
16259+	for (i = 0 ; i < data->edid_rates_count; i++)
16260+		uvalue->value.integer.value[i] = data->edid_rates[i];
16261+
16262+	return 0;
16263+}
16264+
16265+static int imx_cdnhdmi_formats_info(struct snd_kcontrol *kcontrol,
16266+			     struct snd_ctl_elem_info *uinfo)
16267+{
16268+	uinfo->type  = SNDRV_CTL_ELEM_TYPE_INTEGER;
16269+	uinfo->count = 3;
16270+
16271+	return 0;
16272+}
16273+
16274+static int imx_cdnhdmi_formats_get(struct snd_kcontrol *kcontrol,
16275+			    struct snd_ctl_elem_value *uvalue)
16276+{
16277+	uvalue->value.integer.value[0] = 16;
16278+	uvalue->value.integer.value[1] = 24;
16279+	uvalue->value.integer.value[2] = 32;
16280+
16281+	return 0;
16282+}
16283+
16284+static int get_edid_rx_info(struct snd_soc_card *card)
16285+{
16286+	struct snd_soc_pcm_runtime *rtd = list_first_entry(
16287+		&card->rtd_list, struct snd_soc_pcm_runtime, list);
16288+	struct snd_soc_dai *codec_dai = asoc_rtd_to_codec(rtd, 0);
16289+	struct snd_soc_component *component = codec_dai->component;
16290+	struct hdmi_codec_pdata *hcd = component->dev->platform_data;
16291+	struct imx_cdnhdmi_data *data = snd_soc_card_get_drvdata(card);
16292+	int ret;
16293+
16294+	ret = hcd->ops->get_eld(component->dev->parent, hcd->data,
16295+					    data->eld, sizeof(data->eld));
16296+
16297+	if (ret)
16298+		return -EINVAL;
16299+
16300+	data->edid_rates[0] = data->eld[0] +
16301+		(data->eld[1] << 8) +
16302+		(data->eld[2] << 16) +
16303+		(data->eld[3] << 24);
16304+
16305+	data->edid_channels[0] = data->eld[4] +
16306+		(data->eld[5] << 8) +
16307+		(data->eld[6] << 16) +
16308+		(data->eld[7] << 24);
16309+
16310+
16311+	return 0;
16312+}
16313+
16314+static int imx_cdnhdmi_rx_channels_info(struct snd_kcontrol *kcontrol,
16315+			     struct snd_ctl_elem_info *uinfo)
16316+{
16317+	uinfo->type  = SNDRV_CTL_ELEM_TYPE_INTEGER;
16318+	uinfo->count = 1;
16319+	uinfo->value.integer.min = 2;
16320+	uinfo->value.integer.max = 8;
16321+
16322+	return 0;
16323+}
16324+
16325+static int imx_cdnhdmi_rx_channels_get(struct snd_kcontrol *kcontrol,
16326+			    struct snd_ctl_elem_value *uvalue)
16327+{
16328+	struct snd_soc_card *card = snd_kcontrol_chip(kcontrol);
16329+	struct imx_cdnhdmi_data *data = snd_soc_card_get_drvdata(card);
16330+	int ret;
16331+
16332+	ret = get_edid_rx_info(card);
16333+	if (ret)
16334+		return ret;
16335+	uvalue->value.integer.value[0] = data->edid_channels[0];
16336+
16337+	return 0;
16338+}
16339+
16340+static int imx_cdnhdmi_rx_rates_info(struct snd_kcontrol *kcontrol,
16341+			     struct snd_ctl_elem_info *uinfo)
16342+{
16343+	uinfo->type  = SNDRV_CTL_ELEM_TYPE_INTEGER;
16344+	uinfo->count = 1;
16345+	uinfo->value.integer.min = 16000;
16346+	uinfo->value.integer.max = 192000;
16347+
16348+	return 0;
16349+}
16350+
16351+static int imx_cdnhdmi_rx_rates_get(struct snd_kcontrol *kcontrol,
16352+			    struct snd_ctl_elem_value *uvalue)
16353+{
16354+	struct snd_soc_card *card = snd_kcontrol_chip(kcontrol);
16355+	struct imx_cdnhdmi_data *data = snd_soc_card_get_drvdata(card);
16356+	int ret;
16357+
16358+	ret = get_edid_rx_info(card);
16359+	if (ret)
16360+		return ret;
16361+
16362+	uvalue->value.integer.value[0] = data->edid_rates[0];
16363+
16364+	return 0;
16365+}
16366+
16367+static const struct snd_soc_dapm_widget imx_cdnhdmi_widgets[] = {
16368+	SND_SOC_DAPM_LINE("HDMI Jack", NULL),
16369+};
16370+
16371+static int imx_cdnhdmi_init(struct snd_soc_pcm_runtime *rtd)
16372+{
16373+	struct snd_soc_card *card = rtd->card;
16374+	struct snd_soc_dai *codec_dai = asoc_rtd_to_codec(rtd, 0);
16375+	struct snd_soc_component *component = codec_dai->component;
16376+	struct imx_cdnhdmi_data *data = snd_soc_card_get_drvdata(card);
16377+	int ret;
16378+
16379+	data->hdmi_jack_pin.pin = "HDMI Jack";
16380+	data->hdmi_jack_pin.mask = SND_JACK_LINEOUT;
16381+	/* enable jack detection */
16382+	ret = snd_soc_card_jack_new(card, "HDMI Jack", SND_JACK_LINEOUT,
16383+				    &data->hdmi_jack, &data->hdmi_jack_pin, 1);
16384+	if (ret) {
16385+		dev_err(card->dev, "Can't new HDMI Jack %d\n", ret);
16386+		return ret;
16387+	}
16388+
16389+	return snd_soc_component_set_jack(component, &data->hdmi_jack, NULL);
16390+};
16391+
16392+static struct snd_kcontrol_new imx_cdnhdmi_ctrls[] = {
16393+	{
16394+		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
16395+		.name = "HDMI Support Channels",
16396+		.access = SNDRV_CTL_ELEM_ACCESS_READ |
16397+			SNDRV_CTL_ELEM_ACCESS_VOLATILE,
16398+		.info = imx_cdnhdmi_channels_info,
16399+		.get = imx_cdnhdmi_channels_get,
16400+	},
16401+	{
16402+		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
16403+		.name = "HDMI Support Rates",
16404+		.access = SNDRV_CTL_ELEM_ACCESS_READ |
16405+			SNDRV_CTL_ELEM_ACCESS_VOLATILE,
16406+		.info = imx_cdnhdmi_rates_info,
16407+		.get = imx_cdnhdmi_rates_get,
16408+	},
16409+	{
16410+		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
16411+		.name = "HDMI Support Formats",
16412+		.access = SNDRV_CTL_ELEM_ACCESS_READ |
16413+			SNDRV_CTL_ELEM_ACCESS_VOLATILE,
16414+		.info = imx_cdnhdmi_formats_info,
16415+		.get = imx_cdnhdmi_formats_get,
16416+	},
16417+};
16418+
16419+static struct snd_kcontrol_new imx_cdnhdmi_rx_ctrls[] = {
16420+	{
16421+		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
16422+		.name = "HDMI Rx Channels",
16423+		.access = SNDRV_CTL_ELEM_ACCESS_READ |
16424+			SNDRV_CTL_ELEM_ACCESS_VOLATILE,
16425+		.info = imx_cdnhdmi_rx_channels_info,
16426+		.get = imx_cdnhdmi_rx_channels_get,
16427+	},
16428+	{
16429+		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
16430+		.name = "HDMI Rx Rates",
16431+		.access = SNDRV_CTL_ELEM_ACCESS_READ |
16432+			SNDRV_CTL_ELEM_ACCESS_VOLATILE,
16433+		.info = imx_cdnhdmi_rx_rates_info,
16434+		.get = imx_cdnhdmi_rx_rates_get,
16435+	},
16436+};
16437+
16438+static int imx_cdnhdmi_probe(struct platform_device *pdev)
16439+{
16440+	struct device_node *cpu_np;
16441+	struct platform_device *cpu_pdev;
16442+	struct imx_cdnhdmi_data *data;
16443+	struct snd_soc_dai_link_component *dlc;
16444+	int ret;
16445+	int i;
16446+
16447+	dlc = devm_kzalloc(&pdev->dev, 3 * sizeof(*dlc), GFP_KERNEL);
16448+	if (!dlc)
16449+		return -ENOMEM;
16450+
16451+	cpu_np = of_parse_phandle(pdev->dev.of_node, "audio-cpu", 0);
16452+	if (!cpu_np) {
16453+		dev_err(&pdev->dev, "cpu dai phandle missing or invalid\n");
16454+		ret = -EINVAL;
16455+		goto fail;
16456+	}
16457+
16458+	cpu_pdev = of_find_device_by_node(cpu_np);
16459+	if (!cpu_pdev) {
16460+		dev_err(&pdev->dev, "failed to find SAI platform device\n");
16461+		ret = -EINVAL;
16462+		goto fail;
16463+	}
16464+
16465+	data = devm_kzalloc(&pdev->dev, sizeof(*data), GFP_KERNEL);
16466+	if (!data) {
16467+		ret = -ENOMEM;
16468+		goto fail;
16469+	}
16470+
16471+	for (i = 0; i < SUPPORT_RATE_NUM; i++) {
16472+		ret = of_property_read_u32_index(pdev->dev.of_node,
16473+						"constraint-rate",
16474+						i, &data->support_rates[i]);
16475+		if (!ret)
16476+			data->support_rates_num = i + 1;
16477+		else
16478+			break;
16479+	}
16480+
16481+	if (data->support_rates_num == 0) {
16482+		data->support_rates[0] = 48000;
16483+		data->support_rates[1] = 96000;
16484+		data->support_rates[2] = 32000;
16485+		data->support_rates[3] = 192000;
16486+		data->support_rates_num = 4;
16487+	}
16488+
16489+	data->support_channels[0] = 2;
16490+	data->support_channels[1] = 4;
16491+	data->support_channels[2] = 6;
16492+	data->support_channels[3] = 8;
16493+	data->support_channels_num = 4;
16494+
16495+	of_property_read_u32(pdev->dev.of_node, "protocol",
16496+					&data->protocol);
16497+
16498+	data->dai.cpus = &dlc[0];
16499+	data->dai.num_cpus = 1;
16500+	data->dai.platforms = &dlc[1];
16501+	data->dai.num_platforms = 1;
16502+	data->dai.codecs = &dlc[2];
16503+	data->dai.num_codecs = 1;
16504+
16505+	data->dai.name = "imx8 hdmi";
16506+	data->dai.stream_name = "imx8 hdmi";
16507+	data->dai.cpus->dai_name = dev_name(&cpu_pdev->dev);
16508+	data->dai.platforms->of_node = cpu_np;
16509+	data->dai.ops = &imx_cdnhdmi_ops;
16510+	data->dai.playback_only = true;
16511+	data->dai.capture_only = false;
16512+	data->dai.dai_fmt = SND_SOC_DAIFMT_I2S |
16513+			    SND_SOC_DAIFMT_NB_NF |
16514+			    SND_SOC_DAIFMT_CBS_CFS;
16515+	data->dai.init = imx_cdnhdmi_init;
16516+
16517+	if (of_property_read_bool(pdev->dev.of_node, "hdmi-out")) {
16518+		data->dai.playback_only = true;
16519+		data->dai.capture_only = false;
16520+		data->dai.dai_fmt = SND_SOC_DAIFMT_I2S |
16521+			    SND_SOC_DAIFMT_NB_NF |
16522+			    SND_SOC_DAIFMT_CBS_CFS;
16523+		data->dai.codecs->dai_name = "i2s-hifi";
16524+		data->dai.codecs->name = "hdmi-audio-codec.1";
16525+		data->card.controls	= imx_cdnhdmi_ctrls;
16526+		data->card.num_controls	= ARRAY_SIZE(imx_cdnhdmi_ctrls);
16527+	}
16528+
16529+	if (of_property_read_bool(pdev->dev.of_node, "hdmi-in")) {
16530+		data->dai.playback_only = false;
16531+		data->dai.capture_only = true;
16532+		data->dai.dai_fmt = SND_SOC_DAIFMT_I2S |
16533+			    SND_SOC_DAIFMT_NB_NF |
16534+			    SND_SOC_DAIFMT_CBM_CFM;
16535+		data->dai.codecs->dai_name = "i2s-hifi";
16536+		data->dai.codecs->name = "hdmi-audio-codec.2";
16537+		data->card.controls	= imx_cdnhdmi_rx_ctrls;
16538+		data->card.num_controls	= ARRAY_SIZE(imx_cdnhdmi_rx_ctrls);
16539+	}
16540+
16541+	if ((data->dai.playback_only && data->dai.capture_only)
16542+		|| (!data->dai.playback_only && !data->dai.capture_only)) {
16543+		dev_err(&pdev->dev, "Wrongly enable HDMI DAI link\n");
16544+		goto fail;
16545+	}
16546+
16547+	data->card.dapm_widgets = imx_cdnhdmi_widgets;
16548+	data->card.num_dapm_widgets = ARRAY_SIZE(imx_cdnhdmi_widgets);
16549+	data->card.dev = &pdev->dev;
16550+	data->card.owner = THIS_MODULE;
16551+	ret = snd_soc_of_parse_card_name(&data->card, "model");
16552+	if (ret)
16553+		goto fail;
16554+	data->card.num_links = 1;
16555+	data->card.dai_link = &data->dai;
16556+
16557+
16558+	platform_set_drvdata(pdev, &data->card);
16559+	snd_soc_card_set_drvdata(&data->card, data);
16560+	ret = devm_snd_soc_register_card(&pdev->dev, &data->card);
16561+	if (ret) {
16562+		dev_err(&pdev->dev, "snd_soc_register_card failed (%d)\n", ret);
16563+		goto fail;
16564+	}
16565+
16566+fail:
16567+	if (cpu_np)
16568+		of_node_put(cpu_np);
16569+	return ret;
16570+}
16571+
16572+static const struct of_device_id imx_cdnhdmi_dt_ids[] = {
16573+	{ .compatible = "fsl,imx8mq-evk-cdnhdmi", },
16574+	{ .compatible = "fsl,imx-audio-cdnhdmi", },
16575+	{ /* sentinel */ }
16576+};
16577+MODULE_DEVICE_TABLE(of, imx_cdnhdmi_dt_ids);
16578+
16579+static struct platform_driver imx_cdnhdmi_driver = {
16580+	.driver = {
16581+		.name = "imx-cdnhdmi",
16582+		.owner = THIS_MODULE,
16583+		.pm = &snd_soc_pm_ops,
16584+		.of_match_table = imx_cdnhdmi_dt_ids,
16585+	},
16586+	.probe = imx_cdnhdmi_probe,
16587+};
16588+module_platform_driver(imx_cdnhdmi_driver);
16589+
16590+MODULE_AUTHOR("Freescale Semiconductor, Inc.");
16591+MODULE_DESCRIPTION("Freescale i.MX hdmi audio ASoC machine driver");
16592+MODULE_LICENSE("GPL v2");
16593+MODULE_ALIAS("platform:imx-cdnhdmi");
16594diff --git a/sound/soc/fsl/imx-dsp.c b/sound/soc/fsl/imx-dsp.c
16595new file mode 100644
16596index 000000000..fad3fac4e
16597--- /dev/null
16598+++ b/sound/soc/fsl/imx-dsp.c
16599@@ -0,0 +1,232 @@
16600+// SPDX-License-Identifier: (GPL-2.0+
16601+//
16602+// DSP machine driver
16603+//
16604+// Copyright (c) 2012-2013 by Tensilica Inc. ALL RIGHTS RESERVED.
16605+// Copyright 2018 NXP
16606+
16607+#include <linux/module.h>
16608+#include <linux/of_platform.h>
16609+#include <linux/i2c.h>
16610+#include <linux/of_gpio.h>
16611+#include <linux/slab.h>
16612+#include <linux/gpio.h>
16613+#include <linux/clk.h>
16614+#include <sound/soc.h>
16615+#include <sound/jack.h>
16616+#include <sound/control.h>
16617+#include <sound/pcm_params.h>
16618+#include <sound/soc-dapm.h>
16619+#include <linux/string.h>
16620+
16621+struct imx_dsp_audio_data {
16622+	struct snd_soc_dai_link dai[2];
16623+	struct snd_soc_card card;
16624+};
16625+
16626+static int imx_dsp_hw_params(struct snd_pcm_substream *substream,
16627+					 struct snd_pcm_hw_params *params)
16628+{
16629+	struct snd_soc_pcm_runtime *rtd = substream->private_data;
16630+	struct snd_soc_dai *codec_dai = asoc_rtd_to_codec(rtd, 0);
16631+	int ret;
16632+
16633+	ret = snd_soc_dai_set_sysclk(codec_dai, 0,
16634+				     clk_get_rate(devm_clk_get(codec_dai->dev, "mclk")), SND_SOC_CLOCK_IN);
16635+	if (ret) {
16636+		dev_err(rtd->dev, "failed to set codec sysclk: %d\n", ret);
16637+		return ret;
16638+	}
16639+	return 0;
16640+}
16641+
16642+static struct snd_soc_ops imx_dsp_ops_be = {
16643+	.hw_params = imx_dsp_hw_params,
16644+};
16645+
16646+static int be_hw_params_fixup(struct snd_soc_pcm_runtime *rtd,
16647+				struct snd_pcm_hw_params *params) {
16648+
16649+	struct snd_interval *rate;
16650+	struct snd_interval *channels;
16651+	struct snd_mask *mask;
16652+
16653+	rate = hw_param_interval(params, SNDRV_PCM_HW_PARAM_RATE);
16654+	rate->max = rate->min = 48000;
16655+
16656+	channels = hw_param_interval(params, SNDRV_PCM_HW_PARAM_CHANNELS);
16657+	channels->max = channels->min = 2;
16658+
16659+	mask = hw_param_mask(params, SNDRV_PCM_HW_PARAM_FORMAT);
16660+	snd_mask_none(mask);
16661+	snd_mask_set(mask, SNDRV_PCM_FORMAT_S16_LE);
16662+
16663+	return 0;
16664+}
16665+
16666+static const struct snd_soc_dapm_route imx_dsp_audio_map[] = {
16667+	{"Playback",  NULL, "Compress Playback"},/* dai route for be and fe */
16668+};
16669+
16670+static int imx_dsp_audio_probe(struct platform_device *pdev)
16671+{
16672+	struct device_node *np = pdev->dev.of_node;
16673+	struct device_node *cpu_np=NULL, *codec_np=NULL, *platform_np=NULL;
16674+	struct snd_soc_dai_link_component *comp;
16675+	struct platform_device *cpu_pdev;
16676+	struct imx_dsp_audio_data *data;
16677+	int ret;
16678+
16679+	data = devm_kzalloc(&pdev->dev, sizeof(*data), GFP_KERNEL);
16680+	if (!data) {
16681+		ret = -ENOMEM;
16682+		goto fail;
16683+	}
16684+
16685+	comp = devm_kzalloc(&pdev->dev, 6 * sizeof(*comp), GFP_KERNEL);
16686+	if (!comp) {
16687+		ret = -ENOMEM;
16688+		goto fail;
16689+	}
16690+
16691+	cpu_np = of_parse_phandle(pdev->dev.of_node, "cpu-dai", 0);
16692+	if (!cpu_np) {
16693+		dev_err(&pdev->dev, "cpu dai phandle missing or invalid\n");
16694+		ret = -EINVAL;
16695+		goto fail;
16696+	}
16697+
16698+	cpu_pdev = of_find_device_by_node(cpu_np);
16699+	if (!cpu_pdev) {
16700+		dev_err(&pdev->dev, "failed to find rpmsg platform device\n");
16701+		ret = -EINVAL;
16702+		goto fail;
16703+	}
16704+
16705+        codec_np = of_parse_phandle(pdev->dev.of_node, "audio-codec", 0);
16706+        if (!codec_np) {
16707+                dev_err(&pdev->dev, "phandle missing or invalid\n");
16708+                ret = -EINVAL;
16709+                goto fail;
16710+        }
16711+
16712+        platform_np = of_parse_phandle(pdev->dev.of_node, "audio-platform", 0);
16713+        if (!platform_np) {
16714+                dev_err(&pdev->dev, "platform missing or invalid\n");
16715+                ret = -EINVAL;
16716+                goto fail;
16717+        }
16718+
16719+
16720+	data->dai[0].cpus          = &comp[0];
16721+	data->dai[0].codecs        = &comp[1];
16722+	data->dai[0].platforms     = &comp[2];
16723+
16724+	data->dai[0].num_cpus      = 1;
16725+	data->dai[0].num_codecs    = 1;
16726+	data->dai[0].num_platforms = 1;
16727+
16728+	data->dai[0].name = "dsp hifi fe";
16729+	data->dai[0].stream_name = "dsp hifi fe";
16730+	data->dai[0].codecs->dai_name = "snd-soc-dummy-dai";
16731+	data->dai[0].codecs->name = "snd-soc-dummy";
16732+	data->dai[0].cpus->dai_name = dev_name(&cpu_pdev->dev);
16733+	data->dai[0].cpus->of_node = cpu_np;
16734+	data->dai[0].platforms->of_node = platform_np;
16735+	data->dai[0].playback_only = true;
16736+	data->dai[0].capture_only = false;
16737+	data->dai[0].dpcm_playback = 1;
16738+	data->dai[0].dpcm_capture = 0;
16739+	data->dai[0].dynamic = 1,
16740+	data->dai[0].ignore_pmdown_time = 1,
16741+	data->dai[0].dai_fmt = SND_SOC_DAIFMT_LEFT_J |
16742+			    SND_SOC_DAIFMT_NB_NF |
16743+			    SND_SOC_DAIFMT_CBS_CFS;
16744+
16745+	data->dai[1].cpus          = &comp[3];
16746+	data->dai[1].codecs        = &comp[4];
16747+	data->dai[1].platforms     = &comp[5];
16748+
16749+	data->dai[1].num_cpus      = 1;
16750+	data->dai[1].num_codecs    = 1;
16751+	data->dai[1].num_platforms = 1;
16752+
16753+	data->dai[1].name = "dsp hifi be";
16754+	data->dai[1].stream_name = "dsp hifi be";
16755+	if (sysfs_streq(codec_np->name, "wm8960")) {
16756+		if (of_device_is_compatible(np, "fsl,imx-dsp-audio-lpa"))
16757+			data->dai[1].codecs->dai_name = "rpmsg-wm8960-hifi";
16758+		else
16759+			data->dai[1].codecs->dai_name = "wm8960-hifi";
16760+		data->dai[1].dai_fmt = SND_SOC_DAIFMT_NB_NF |
16761+				       SND_SOC_DAIFMT_I2S |
16762+				       SND_SOC_DAIFMT_CBS_CFS;
16763+	} else {
16764+		data->dai[1].codecs->dai_name = "cs42888";
16765+		data->dai[1].dai_fmt = SND_SOC_DAIFMT_LEFT_J |
16766+				       SND_SOC_DAIFMT_NB_NF |
16767+				       SND_SOC_DAIFMT_CBS_CFS;
16768+	}
16769+	data->dai[1].codecs->of_node = codec_np;
16770+	data->dai[1].cpus->dai_name = "snd-soc-dummy-dai";
16771+	data->dai[1].cpus->name = "snd-soc-dummy";
16772+	data->dai[1].platforms->name = "snd-soc-dummy";
16773+	data->dai[1].playback_only = true;
16774+	data->dai[1].capture_only = false;
16775+	data->dai[1].dpcm_playback = 1;
16776+	if (of_device_is_compatible(np, "fsl,imx-dsp-audio-lpa"))
16777+		data->dai[1].ignore_suspend = 1;
16778+	data->dai[1].dpcm_capture = 0;
16779+	data->dai[1].no_pcm = 1,
16780+	data->dai[1].ignore_pmdown_time = 1,
16781+	data->dai[1].ops = &imx_dsp_ops_be;
16782+	data->dai[1].be_hw_params_fixup = be_hw_params_fixup;
16783+
16784+	data->card.dapm_routes = imx_dsp_audio_map;
16785+	data->card.num_dapm_routes = ARRAY_SIZE(imx_dsp_audio_map);
16786+	data->card.num_links = 2;
16787+	data->card.dai_link = data->dai;
16788+
16789+	data->card.dev = &pdev->dev;
16790+	data->card.owner = THIS_MODULE;
16791+	ret = snd_soc_of_parse_card_name(&data->card, "model");
16792+	if (ret)
16793+		goto fail;
16794+
16795+	platform_set_drvdata(pdev, &data->card);
16796+	snd_soc_card_set_drvdata(&data->card, data);
16797+	ret = devm_snd_soc_register_card(&pdev->dev, &data->card);
16798+	if (ret) {
16799+		dev_err(&pdev->dev, "snd_soc_register_card failed (%d)\n", ret);
16800+		goto fail;
16801+	}
16802+
16803+fail:
16804+	if (cpu_np)
16805+		of_node_put(cpu_np);
16806+	if (codec_np)
16807+		of_node_put(codec_np);
16808+	if (platform_np)
16809+		of_node_put(platform_np);
16810+	return ret;
16811+}
16812+
16813+static const struct of_device_id imx_dsp_audio_dt_ids[] = {
16814+	{ .compatible = "fsl,imx-dsp-audio", },
16815+	{ .compatible = "fsl,imx-dsp-audio-lpa", },
16816+	{ /* sentinel */ }
16817+};
16818+MODULE_DEVICE_TABLE(of, imx_dsp_audio_dt_ids);
16819+
16820+static struct platform_driver imx_dsp_audio_driver = {
16821+	.driver = {
16822+		.name = "imx-dsp-audio",
16823+		.owner = THIS_MODULE,
16824+		.pm = &snd_soc_pm_ops,
16825+		.of_match_table = imx_dsp_audio_dt_ids,
16826+	},
16827+	.probe = imx_dsp_audio_probe,
16828+};
16829+module_platform_driver(imx_dsp_audio_driver);
16830+
16831+MODULE_LICENSE("GPL v2");
16832diff --git a/sound/soc/fsl/imx-micfil.c b/sound/soc/fsl/imx-micfil.c
16833new file mode 100644
16834index 000000000..d972be6dc
16835--- /dev/null
16836+++ b/sound/soc/fsl/imx-micfil.c
16837@@ -0,0 +1,185 @@
16838+/*
16839+ * Copyright 2018 NXP
16840+ *
16841+ * The code contained herein is licensed under the GNU General Public
16842+ * License. You may obtain a copy of the GNU General Public License
16843+ * Version 2 or later at the following locations:
16844+ *
16845+ * http://www.opensource.org/licenses/gpl-license.html
16846+ * http://www.gnu.org/copyleft/gpl.html
16847+ */
16848+
16849+#include <linux/module.h>
16850+#include <linux/of_platform.h>
16851+#include <linux/i2c.h>
16852+#include <linux/of_gpio.h>
16853+#include <linux/slab.h>
16854+#include <linux/gpio.h>
16855+#include <linux/clk.h>
16856+#include <sound/soc.h>
16857+#include <sound/jack.h>
16858+#include <sound/control.h>
16859+#include <sound/pcm_params.h>
16860+#include <sound/soc-dapm.h>
16861+#include <linux/pinctrl/consumer.h>
16862+#include "fsl_micfil.h"
16863+
16864+#define RX 0
16865+#define TX 1
16866+
16867+struct imx_micfil_data {
16868+	char name[32];
16869+	struct snd_soc_dai_link dai;
16870+	struct snd_soc_card card;
16871+};
16872+
16873+static int imx_micfil_startup(struct snd_pcm_substream *substream)
16874+{
16875+	struct snd_pcm_runtime *runtime = substream->runtime;
16876+	static struct snd_pcm_hw_constraint_list constraint_rates;
16877+	int ret;
16878+	static u32 support_rates[] = {11025, 16000, 22050,
16879+				      32000, 44100, 48000,};
16880+
16881+	constraint_rates.list = support_rates;
16882+	constraint_rates.count = ARRAY_SIZE(support_rates);
16883+
16884+	ret = snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_RATE,
16885+					 &constraint_rates);
16886+	if (ret)
16887+		return ret;
16888+
16889+	return 0;
16890+}
16891+
16892+static int imx_micfil_hw_params(struct snd_pcm_substream *substream,
16893+				struct snd_pcm_hw_params *params)
16894+{
16895+	struct snd_soc_pcm_runtime *rtd = substream->private_data;
16896+	struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(rtd, 0);
16897+	bool tx = substream->stream == SNDRV_PCM_STREAM_PLAYBACK;
16898+	struct device *dev = rtd->card->dev;
16899+	unsigned int fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF;
16900+	unsigned int rate = params_rate(params);
16901+	int ret, dir;
16902+
16903+	/* For playback the XTOR is slave, and for record is master */
16904+	fmt |= tx ? SND_SOC_DAIFMT_CBS_CFS : SND_SOC_DAIFMT_CBM_CFM;
16905+	dir = tx ? SND_SOC_CLOCK_OUT : SND_SOC_CLOCK_IN;
16906+
16907+	/* set cpu DAI configuration */
16908+	ret = snd_soc_dai_set_fmt(cpu_dai, fmt);
16909+	if (ret) {
16910+		dev_err(dev, "failed to set cpu dai fmt: %d\n", ret);
16911+		return ret;
16912+	}
16913+
16914+	/* Specific configurations of DAIs starts from here */
16915+	ret = snd_soc_dai_set_sysclk(cpu_dai, 0,
16916+				     rate, dir);
16917+	if (ret) {
16918+		dev_err(dev,
16919+			"%s: failed to set cpu sysclk: %d\n", __func__,
16920+			ret);
16921+		return ret;
16922+	}
16923+
16924+	return 0;
16925+}
16926+
16927+struct snd_soc_ops imx_micfil_ops = {
16928+	.startup = imx_micfil_startup,
16929+	.hw_params = imx_micfil_hw_params,
16930+};
16931+
16932+static int imx_micfil_probe(struct platform_device *pdev)
16933+{
16934+	struct device_node *cpu_np;
16935+	struct platform_device *cpu_pdev;
16936+	struct imx_micfil_data *data;
16937+	struct snd_soc_dai_link_component *dlc;
16938+	int ret;
16939+
16940+	dlc = devm_kzalloc(&pdev->dev, 3 * sizeof(*dlc), GFP_KERNEL);
16941+	if (!dlc)
16942+		return -ENOMEM;
16943+
16944+	cpu_np = of_parse_phandle(pdev->dev.of_node, "cpu-dai", 0);
16945+	if (!cpu_np) {
16946+		dev_err(&pdev->dev, "cpu dai phandle missing or invalid\n");
16947+		ret = -EINVAL;
16948+		goto fail;
16949+	}
16950+
16951+	data = devm_kzalloc(&pdev->dev, sizeof(*data), GFP_KERNEL);
16952+	if (!data) {
16953+		ret = -ENOMEM;
16954+		goto fail;
16955+	}
16956+
16957+	strncpy(data->name, cpu_np->name, sizeof(data->name) - 1);
16958+
16959+	cpu_pdev = of_find_device_by_node(cpu_np);
16960+	if (!cpu_pdev) {
16961+		dev_err(&pdev->dev, "failed to find MICFIL platform device\n");
16962+		ret = -EINVAL;
16963+		goto fail;
16964+	}
16965+
16966+	data->dai.cpus = &dlc[0];
16967+	data->dai.num_cpus = 1;
16968+	data->dai.platforms = &dlc[1];
16969+	data->dai.num_platforms = 1;
16970+	data->dai.codecs = &dlc[2];
16971+	data->dai.num_codecs = 1;
16972+	data->dai.name = "micfil hifi";
16973+	data->dai.stream_name = "micfil hifi";
16974+	data->dai.codecs->dai_name = "snd-soc-dummy-dai";
16975+	data->dai.codecs->name = "snd-soc-dummy";
16976+	data->dai.cpus->dai_name = dev_name(&cpu_pdev->dev);
16977+	data->dai.platforms->of_node = cpu_np;
16978+	data->dai.playback_only = false;
16979+	data->dai.ops = &imx_micfil_ops;
16980+	data->card.num_links = 1;
16981+	data->card.dai_link = &data->dai;
16982+	data->card.dev = &pdev->dev;
16983+	data->card.owner = THIS_MODULE;
16984+	ret = snd_soc_of_parse_card_name(&data->card, "model");
16985+	if (ret)
16986+		goto fail;
16987+
16988+	platform_set_drvdata(pdev, &data->card);
16989+	snd_soc_card_set_drvdata(&data->card, data);
16990+	ret = devm_snd_soc_register_card(&pdev->dev, &data->card);
16991+	if (ret) {
16992+		dev_err(&pdev->dev, "snd_soc_register_card failed (%d)\n", ret);
16993+		goto fail;
16994+	}
16995+
16996+fail:
16997+	if (cpu_np)
16998+		of_node_put(cpu_np);
16999+	return ret;
17000+}
17001+
17002+static const struct of_device_id imx_micfil_dt_ids[] = {
17003+	{ .compatible = "fsl,imx-audio-micfil", },
17004+	{ /* sentinel */ }
17005+};
17006+MODULE_DEVICE_TABLE(of, imx_micfil_dt_ids);
17007+
17008+static struct platform_driver imx_micfil_driver = {
17009+	.driver = {
17010+		.name = "imx-micfil",
17011+		.owner = THIS_MODULE,
17012+		.pm = &snd_soc_pm_ops,
17013+		.of_match_table = imx_micfil_dt_ids,
17014+	},
17015+	.probe = imx_micfil_probe,
17016+};
17017+module_platform_driver(imx_micfil_driver);
17018+
17019+MODULE_AUTHOR("Cosmin-Gabriel Samoila <cosmin.samoila@nxp.com>");
17020+MODULE_DESCRIPTION("NXP Micfil ASoC machine driver");
17021+MODULE_LICENSE("GPL v2");
17022+MODULE_ALIAS("platform:imx-micfil");
17023diff --git a/sound/soc/fsl/imx-pcm-dma-v2.c b/sound/soc/fsl/imx-pcm-dma-v2.c
17024new file mode 100644
17025index 000000000..35a714511
17026--- /dev/null
17027+++ b/sound/soc/fsl/imx-pcm-dma-v2.c
17028@@ -0,0 +1,282 @@
17029+/*
17030+ * imx-pcm-dma-v2.c -- ALSA Soc Audio Layer
17031+ *
17032+ * Copyright 2009 Sascha Hauer <s.hauer@pengutronix.de>
17033+ *
17034+ * This code is based on code copyrighted by Freescale,
17035+ * Liam Girdwood, Javier Martin and probably others.
17036+ *
17037+ *  This program is free software; you can redistribute  it and/or modify it
17038+ *  under  the terms of  the GNU General  Public License as published by the
17039+ *  Free Software Foundation;  either version 2 of the  License, or (at your
17040+ *  option) any later version.
17041+ */
17042+#include <linux/dma-mapping.h>
17043+#include <linux/slab.h>
17044+#include <linux/module.h>
17045+#include <sound/core.h>
17046+#include <sound/pcm.h>
17047+#include <sound/pcm_params.h>
17048+#include <sound/dmaengine_pcm.h>
17049+#include <sound/soc.h>
17050+
17051+#include "imx-pcm.h"
17052+
17053+static struct snd_pcm_hardware imx_pcm_hardware = {
17054+	.info = SNDRV_PCM_INFO_INTERLEAVED |
17055+		SNDRV_PCM_INFO_BLOCK_TRANSFER |
17056+		SNDRV_PCM_INFO_MMAP |
17057+		SNDRV_PCM_INFO_MMAP_VALID,
17058+	.buffer_bytes_max = IMX_SSI_DMABUF_SIZE,
17059+	.period_bytes_min = 128,
17060+	.period_bytes_max = 65532, /* Limited by SDMA engine */
17061+	.periods_min = 2,
17062+	.periods_max = 255,
17063+	.fifo_size = 0,
17064+};
17065+
17066+static bool imx_dma_filter_fn(struct dma_chan *chan, void *param)
17067+{
17068+	if (!imx_dma_is_general_purpose(chan))
17069+		return false;
17070+
17071+	chan->private = param;
17072+
17073+	return true;
17074+}
17075+
17076+/* this may get called several times by oss emulation */
17077+static int imx_pcm_hw_params(struct snd_soc_component *component,
17078+			     struct snd_pcm_substream *substream,
17079+			     struct snd_pcm_hw_params *params)
17080+{
17081+	struct snd_pcm_runtime *runtime = substream->runtime;
17082+	struct snd_soc_pcm_runtime *rtd = substream->private_data;
17083+	struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(rtd, 0);
17084+	struct snd_dmaengine_dai_dma_data *dma_data;
17085+	struct dma_slave_config config;
17086+	struct dma_chan *chan;
17087+	int err = 0;
17088+
17089+	dma_data = snd_soc_dai_get_dma_data(cpu_dai, substream);
17090+
17091+	/* return if this is a bufferless transfer e.g.
17092+	 * codec <--> BT codec or GSM modem -- lg FIXME
17093+	 */
17094+	if (!dma_data)
17095+		return 0;
17096+
17097+	snd_pcm_set_runtime_buffer(substream, &substream->dma_buffer);
17098+	runtime->dma_bytes = params_buffer_bytes(params);
17099+
17100+	chan = snd_dmaengine_pcm_get_chan(substream);
17101+	if (!chan)
17102+		return -EINVAL;
17103+
17104+	/* fills in addr_width and direction */
17105+	err = snd_hwparams_to_dma_slave_config(substream, params, &config);
17106+	if (err)
17107+		return err;
17108+
17109+	snd_dmaengine_pcm_set_config_from_dai_data(substream,
17110+					dma_data,
17111+					&config);
17112+
17113+	return dmaengine_slave_config(chan, &config);
17114+}
17115+
17116+static int imx_pcm_hw_free(struct snd_soc_component *component,
17117+			   struct snd_pcm_substream *substream)
17118+{
17119+	snd_pcm_set_runtime_buffer(substream, NULL);
17120+	return 0;
17121+}
17122+
17123+static snd_pcm_uframes_t imx_pcm_pointer(struct snd_soc_component *component,
17124+					 struct snd_pcm_substream *substream)
17125+{
17126+	return snd_dmaengine_pcm_pointer(substream);
17127+}
17128+
17129+static int imx_pcm_preallocate_dma_buffer(struct snd_pcm_substream *substream,
17130+					  struct device *dev)
17131+{
17132+	size_t size = imx_pcm_hardware.buffer_bytes_max;
17133+	int ret;
17134+
17135+	ret = snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV_IRAM,
17136+				  dev,
17137+				  size,
17138+				  &substream->dma_buffer);
17139+	if (ret)
17140+		return ret;
17141+
17142+	return 0;
17143+}
17144+
17145+static void imx_pcm_free_dma_buffers(struct snd_pcm_substream *substream)
17146+{
17147+	if (substream) {
17148+		snd_dma_free_pages(&substream->dma_buffer);
17149+		substream->dma_buffer.area = NULL;
17150+		substream->dma_buffer.addr = 0;
17151+	}
17152+}
17153+
17154+static int imx_pcm_open(struct snd_soc_component *component,
17155+			struct snd_pcm_substream *substream)
17156+{
17157+	struct snd_soc_pcm_runtime *rtd = substream->private_data;
17158+	struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(rtd, 0);
17159+	struct snd_dmaengine_dai_dma_data *dma_data;
17160+	struct dma_slave_caps dma_caps;
17161+	struct dma_chan *chan;
17162+	u32 addr_widths = BIT(DMA_SLAVE_BUSWIDTH_1_BYTE) |
17163+			  BIT(DMA_SLAVE_BUSWIDTH_2_BYTES) |
17164+			  BIT(DMA_SLAVE_BUSWIDTH_4_BYTES);
17165+	int ret;
17166+	int i;
17167+
17168+	dma_data = snd_soc_dai_get_dma_data(cpu_dai, substream);
17169+
17170+	/* DT boot: filter_data is the DMA name */
17171+	if (cpu_dai->dev->of_node) {
17172+		struct dma_chan *chan;
17173+
17174+		chan = dma_request_slave_channel(cpu_dai->dev,
17175+						 dma_data->chan_name);
17176+		ret = snd_dmaengine_pcm_open(substream, chan);
17177+		if (ret)
17178+			return ret;
17179+	} else {
17180+		ret = snd_dmaengine_pcm_open_request_chan(substream,
17181+							  imx_dma_filter_fn,
17182+							  dma_data->filter_data);
17183+		if (ret)
17184+			return ret;
17185+	}
17186+
17187+	chan = snd_dmaengine_pcm_get_chan(substream);
17188+
17189+	ret = dma_get_slave_caps(chan, &dma_caps);
17190+	if (ret == 0) {
17191+		if (dma_caps.cmd_pause)
17192+			imx_pcm_hardware.info |= SNDRV_PCM_INFO_PAUSE | SNDRV_PCM_INFO_RESUME;
17193+		if (dma_caps.residue_granularity <= DMA_RESIDUE_GRANULARITY_SEGMENT)
17194+			imx_pcm_hardware.info |= SNDRV_PCM_INFO_BATCH;
17195+
17196+		if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
17197+			addr_widths = dma_caps.dst_addr_widths;
17198+		else
17199+			addr_widths = dma_caps.src_addr_widths;
17200+	}
17201+
17202+	/*
17203+	 * If SND_DMAENGINE_PCM_DAI_FLAG_PACK is set keep
17204+	 * hw.formats set to 0, meaning no restrictions are in place.
17205+	 * In this case it's the responsibility of the DAI driver to
17206+	 * provide the supported format information.
17207+	 */
17208+	if (!(dma_data->flags & SND_DMAENGINE_PCM_DAI_FLAG_PACK))
17209+		/*
17210+		 * Prepare formats mask for valid/allowed sample types. If the
17211+		 * dma does not have support for the given physical word size,
17212+		 * it needs to be masked out so user space can not use the
17213+		 * format which produces corrupted audio.
17214+		 * In case the dma driver does not implement the slave_caps the
17215+		 * default assumption is that it supports 1, 2 and 4 bytes
17216+		 * widths.
17217+		 */
17218+		for (i = 0; i <= SNDRV_PCM_FORMAT_LAST; i++) {
17219+			int bits = snd_pcm_format_physical_width(i);
17220+
17221+			/*
17222+			 * Enable only samples with DMA supported physical
17223+			 * widths
17224+			 */
17225+			switch (bits) {
17226+			case 8:
17227+			case 16:
17228+			case 24:
17229+			case 32:
17230+			case 64:
17231+				if (addr_widths & (1 << (bits / 8)))
17232+					imx_pcm_hardware.formats |= (1LL << i);
17233+				break;
17234+			default:
17235+				/* Unsupported types */
17236+				break;
17237+			}
17238+		}
17239+
17240+	snd_soc_set_runtime_hwparams(substream, &imx_pcm_hardware);
17241+
17242+	ret = imx_pcm_preallocate_dma_buffer(substream, chan->device->dev);
17243+	if (ret)
17244+		return ret;
17245+
17246+	ret = snd_pcm_hw_constraint_integer(substream->runtime,
17247+					    SNDRV_PCM_HW_PARAM_PERIODS);
17248+	if (ret < 0)
17249+		return ret;
17250+
17251+	return 0;
17252+}
17253+
17254+static int imx_pcm_mmap(struct snd_soc_component *component,
17255+			struct snd_pcm_substream *substream,
17256+			struct vm_area_struct *vma)
17257+{
17258+	struct snd_pcm_runtime *runtime = substream->runtime;
17259+
17260+	return dma_mmap_wc(substream->pcm->card->dev, vma,
17261+			   runtime->dma_area,
17262+			   runtime->dma_addr,
17263+			   runtime->dma_bytes);
17264+}
17265+
17266+static int imx_pcm_close(struct snd_soc_component *component,
17267+			 struct snd_pcm_substream *substream)
17268+{
17269+	imx_pcm_free_dma_buffers(substream);
17270+
17271+	return snd_dmaengine_pcm_close_release_chan(substream);
17272+}
17273+
17274+static int imx_pcm_new(struct snd_soc_component *component, struct snd_soc_pcm_runtime *rtd)
17275+{
17276+	struct snd_card *card = rtd->card->snd_card;
17277+	int ret = 0;
17278+
17279+	ret = dma_coerce_mask_and_coherent(card->dev, DMA_BIT_MASK(32));
17280+	if (ret)
17281+		return ret;
17282+
17283+	return ret;
17284+}
17285+
17286+static int imx_pcm_trigger(struct snd_soc_component *component,
17287+			   struct snd_pcm_substream *substream, int cmd)
17288+{
17289+	return snd_dmaengine_pcm_trigger(substream, cmd);
17290+}
17291+
17292+static struct snd_soc_component_driver imx_soc_platform = {
17293+	.name           = "imx-pcm-dma-v2",
17294+	.pcm_construct	= imx_pcm_new,
17295+	.open		= imx_pcm_open,
17296+	.close		= imx_pcm_close,
17297+	.hw_params	= imx_pcm_hw_params,
17298+	.hw_free	= imx_pcm_hw_free,
17299+	.trigger	= imx_pcm_trigger,
17300+	.pointer	= imx_pcm_pointer,
17301+	.mmap		= imx_pcm_mmap,
17302+};
17303+
17304+int imx_pcm_platform_register(struct device *dev)
17305+{
17306+	return devm_snd_soc_register_component(dev, &imx_soc_platform, NULL, 0);
17307+}
17308+EXPORT_SYMBOL_GPL(imx_pcm_platform_register);
17309+
17310+MODULE_LICENSE("GPL");
17311diff --git a/sound/soc/fsl/imx-pcm-rpmsg.c b/sound/soc/fsl/imx-pcm-rpmsg.c
17312new file mode 100644
17313index 000000000..0cba0e5c4
17314--- /dev/null
17315+++ b/sound/soc/fsl/imx-pcm-rpmsg.c
17316@@ -0,0 +1,929 @@
17317+// SPDX-License-Identifier: GPL-2.0+
17318+// Copyright 2017-2021 NXP
17319+
17320+#include <linux/dma-mapping.h>
17321+#include <linux/slab.h>
17322+#include <linux/module.h>
17323+#include <linux/delay.h>
17324+#include <linux/rpmsg.h>
17325+#include <sound/core.h>
17326+#include <sound/pcm.h>
17327+#include <sound/pcm_params.h>
17328+#include <sound/dmaengine_pcm.h>
17329+#include <sound/soc.h>
17330+
17331+#include "imx-pcm.h"
17332+#include "fsl_rpmsg.h"
17333+#include "imx-pcm-rpmsg.h"
17334+
17335+static struct snd_pcm_hardware imx_rpmsg_pcm_hardware = {
17336+	.info = SNDRV_PCM_INFO_INTERLEAVED |
17337+		SNDRV_PCM_INFO_BLOCK_TRANSFER |
17338+		SNDRV_PCM_INFO_MMAP |
17339+		SNDRV_PCM_INFO_MMAP_VALID |
17340+		SNDRV_PCM_INFO_NO_PERIOD_WAKEUP |
17341+		SNDRV_PCM_INFO_PAUSE |
17342+		SNDRV_PCM_INFO_RESUME,
17343+	.buffer_bytes_max = IMX_DEFAULT_DMABUF_SIZE,
17344+	.period_bytes_min = 512,
17345+	.period_bytes_max = 65536,
17346+	.periods_min = 2,
17347+	.periods_max = 6000,
17348+	.fifo_size = 0,
17349+};
17350+
17351+static int imx_rpmsg_pcm_send_message(struct rpmsg_msg *msg,
17352+				      struct rpmsg_info *info)
17353+{
17354+	struct rpmsg_device *rpdev = info->rpdev;
17355+	int ret = 0;
17356+
17357+	mutex_lock(&info->msg_lock);
17358+	if (!rpdev) {
17359+		dev_err(info->dev, "rpmsg channel not ready\n");
17360+		mutex_unlock(&info->msg_lock);
17361+		return -EINVAL;
17362+	}
17363+
17364+	dev_dbg(&rpdev->dev, "send cmd %d\n", msg->s_msg.header.cmd);
17365+
17366+	if (!(msg->s_msg.header.type == MSG_TYPE_C))
17367+		reinit_completion(&info->cmd_complete);
17368+
17369+	ret = rpmsg_send(rpdev->ept, (void *)&msg->s_msg,
17370+			 sizeof(struct rpmsg_s_msg));
17371+	if (ret) {
17372+		dev_err(&rpdev->dev, "rpmsg_send failed: %d\n", ret);
17373+		mutex_unlock(&info->msg_lock);
17374+		return ret;
17375+	}
17376+
17377+	/* No receive msg for TYPE_C command */
17378+	if (msg->s_msg.header.type == MSG_TYPE_C) {
17379+		mutex_unlock(&info->msg_lock);
17380+		return 0;
17381+	}
17382+
17383+	/* wait response from rpmsg */
17384+	ret = wait_for_completion_timeout(&info->cmd_complete,
17385+					  msecs_to_jiffies(RPMSG_TIMEOUT));
17386+	if (!ret) {
17387+		dev_err(&rpdev->dev, "rpmsg_send cmd %d timeout!\n",
17388+			msg->s_msg.header.cmd);
17389+		mutex_unlock(&info->msg_lock);
17390+		return -ETIMEDOUT;
17391+	}
17392+
17393+	memcpy(&msg->r_msg, &info->r_msg, sizeof(struct rpmsg_r_msg));
17394+	memcpy(&info->msg[msg->r_msg.header.cmd].r_msg,
17395+	       &msg->r_msg, sizeof(struct rpmsg_r_msg));
17396+
17397+	/*
17398+	 * Reset the buffer pointer to be zero, actully we have
17399+	 * set the buffer pointer to be zero in imx_rpmsg_terminate_all
17400+	 * But if there is timer task queued in queue, after it is
17401+	 * executed the buffer pointer will be changed, so need to
17402+	 * reset it again with TERMINATE command.
17403+	 */
17404+	switch (msg->s_msg.header.cmd) {
17405+	case TX_TERMINATE:
17406+		info->msg[TX_POINTER].r_msg.param.buffer_offset = 0;
17407+		break;
17408+	case RX_TERMINATE:
17409+		info->msg[RX_POINTER].r_msg.param.buffer_offset = 0;
17410+		break;
17411+	default:
17412+		break;
17413+	}
17414+
17415+	dev_dbg(&rpdev->dev, "cmd:%d, resp %d\n", msg->s_msg.header.cmd,
17416+		info->r_msg.param.resp);
17417+
17418+	mutex_unlock(&info->msg_lock);
17419+
17420+	return 0;
17421+}
17422+
17423+static int imx_rpmsg_insert_workqueue(struct snd_pcm_substream *substream,
17424+				      struct rpmsg_msg *msg,
17425+				      struct rpmsg_info *info)
17426+{
17427+	unsigned long flags;
17428+	int ret = 0;
17429+
17430+	/*
17431+	 * Queue the work to workqueue.
17432+	 * If the queue is full, drop the message.
17433+	 */
17434+	spin_lock_irqsave(&info->wq_lock, flags);
17435+	if (info->work_write_index != info->work_read_index) {
17436+		int index = info->work_write_index;
17437+
17438+		memcpy(&info->work_list[index].msg, msg,
17439+		       sizeof(struct rpmsg_s_msg));
17440+
17441+		queue_work(info->rpmsg_wq, &info->work_list[index].work);
17442+		info->work_write_index++;
17443+		info->work_write_index %= WORK_MAX_NUM;
17444+	} else {
17445+		info->msg_drop_count[substream->stream]++;
17446+		ret = -EPIPE;
17447+	}
17448+	spin_unlock_irqrestore(&info->wq_lock, flags);
17449+
17450+	return ret;
17451+}
17452+
17453+static int imx_rpmsg_pcm_hw_params(struct snd_soc_component *component,
17454+				   struct snd_pcm_substream *substream,
17455+				   struct snd_pcm_hw_params *params)
17456+{
17457+	struct rpmsg_info *info = dev_get_drvdata(component->dev);
17458+	struct snd_pcm_runtime *runtime = substream->runtime;
17459+	struct rpmsg_msg *msg;
17460+	int ret = 0;
17461+
17462+	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
17463+		msg = &info->msg[TX_HW_PARAM];
17464+		msg->s_msg.header.cmd = TX_HW_PARAM;
17465+	} else {
17466+		msg = &info->msg[RX_HW_PARAM];
17467+		msg->s_msg.header.cmd = RX_HW_PARAM;
17468+	}
17469+
17470+	msg->s_msg.param.rate = params_rate(params);
17471+
17472+	switch (params_format(params)) {
17473+	case SNDRV_PCM_FORMAT_S16_LE:
17474+		msg->s_msg.param.format   = RPMSG_S16_LE;
17475+		break;
17476+	case SNDRV_PCM_FORMAT_S24_LE:
17477+		msg->s_msg.param.format   = RPMSG_S24_LE;
17478+		break;
17479+	case SNDRV_PCM_FORMAT_DSD_U16_LE:
17480+		msg->s_msg.param.format   = RPMSG_DSD_U16_LE;
17481+		break;
17482+	case SNDRV_PCM_FORMAT_DSD_U32_LE:
17483+		msg->s_msg.param.format   = RPMSG_DSD_U32_LE;
17484+		break;
17485+	default:
17486+		msg->s_msg.param.format   = RPMSG_S32_LE;
17487+		break;
17488+	}
17489+
17490+	switch (params_channels(params)) {
17491+	case 1:
17492+		msg->s_msg.param.channels = RPMSG_CH_LEFT;
17493+		break;
17494+	case 2:
17495+		msg->s_msg.param.channels = RPMSG_CH_STEREO;
17496+		break;
17497+	default:
17498+		msg->s_msg.param.channels = params_channels(params);
17499+		break;
17500+	}
17501+
17502+	snd_pcm_set_runtime_buffer(substream, &substream->dma_buffer);
17503+	runtime->dma_bytes = params_buffer_bytes(params);
17504+
17505+	info->send_message(msg, info);
17506+
17507+	return ret;
17508+}
17509+
17510+static int imx_rpmsg_pcm_hw_free(struct snd_soc_component *component,
17511+				 struct snd_pcm_substream *substream)
17512+{
17513+	snd_pcm_set_runtime_buffer(substream, NULL);
17514+	return 0;
17515+}
17516+
17517+static snd_pcm_uframes_t imx_rpmsg_pcm_pointer(struct snd_soc_component *component,
17518+					       struct snd_pcm_substream *substream)
17519+{
17520+	struct rpmsg_info *info = dev_get_drvdata(component->dev);
17521+	struct rpmsg_msg *msg;
17522+	unsigned int pos = 0;
17523+	int buffer_tail = 0;
17524+
17525+	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
17526+		msg = &info->msg[TX_PERIOD_DONE + MSG_TYPE_A_NUM];
17527+	else
17528+		msg = &info->msg[RX_PERIOD_DONE + MSG_TYPE_A_NUM];
17529+
17530+	buffer_tail = msg->r_msg.param.buffer_tail;
17531+	pos = buffer_tail * snd_pcm_lib_period_bytes(substream);
17532+
17533+	return bytes_to_frames(substream->runtime, pos);
17534+}
17535+
17536+static void imx_rpmsg_timer_callback(struct timer_list *t)
17537+{
17538+	struct stream_timer  *stream_timer =
17539+			from_timer(stream_timer, t, timer);
17540+	struct snd_pcm_substream *substream = stream_timer->substream;
17541+	struct rpmsg_info *info = stream_timer->info;
17542+	struct rpmsg_msg *msg;
17543+
17544+	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
17545+		msg = &info->msg[TX_PERIOD_DONE + MSG_TYPE_A_NUM];
17546+		msg->s_msg.header.cmd = TX_PERIOD_DONE;
17547+	} else {
17548+		msg = &info->msg[RX_PERIOD_DONE + MSG_TYPE_A_NUM];
17549+		msg->s_msg.header.cmd = RX_PERIOD_DONE;
17550+	}
17551+
17552+	imx_rpmsg_insert_workqueue(substream, msg, info);
17553+}
17554+
17555+static int imx_rpmsg_pcm_open(struct snd_soc_component *component,
17556+			      struct snd_pcm_substream *substream)
17557+{
17558+	struct snd_pcm_hardware pcm_hardware = imx_rpmsg_pcm_hardware;
17559+	struct rpmsg_info *info = dev_get_drvdata(component->dev);
17560+	struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream);
17561+	struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(rtd, 0);
17562+	struct fsl_rpmsg *rpmsg = dev_get_drvdata(cpu_dai->dev);
17563+	struct rpmsg_msg *msg;
17564+	int ret = 0;
17565+	int cmd;
17566+
17567+	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
17568+		msg = &info->msg[TX_OPEN];
17569+		msg->s_msg.header.cmd = TX_OPEN;
17570+
17571+		/* reinitialize buffer counter*/
17572+		cmd = TX_PERIOD_DONE + MSG_TYPE_A_NUM;
17573+		info->msg[cmd].s_msg.param.buffer_tail = 0;
17574+		info->msg[cmd].r_msg.param.buffer_tail = 0;
17575+		info->msg[TX_POINTER].r_msg.param.buffer_offset = 0;
17576+
17577+	} else {
17578+		msg = &info->msg[RX_OPEN];
17579+		msg->s_msg.header.cmd = RX_OPEN;
17580+
17581+		/* reinitialize buffer counter*/
17582+		cmd = RX_PERIOD_DONE + MSG_TYPE_A_NUM;
17583+		info->msg[cmd].s_msg.param.buffer_tail = 0;
17584+		info->msg[cmd].r_msg.param.buffer_tail = 0;
17585+		info->msg[RX_POINTER].r_msg.param.buffer_offset = 0;
17586+	}
17587+
17588+	info->send_message(msg, info);
17589+
17590+	pcm_hardware.buffer_bytes_max = rpmsg->buffer_size;
17591+	pcm_hardware.period_bytes_max =
17592+			pcm_hardware.buffer_bytes_max / 2;
17593+
17594+	snd_soc_set_runtime_hwparams(substream, &pcm_hardware);
17595+
17596+	ret = snd_pcm_hw_constraint_integer(substream->runtime,
17597+					    SNDRV_PCM_HW_PARAM_PERIODS);
17598+	if (ret < 0)
17599+		return ret;
17600+
17601+	info->msg_drop_count[substream->stream] = 0;
17602+
17603+	/* Create timer*/
17604+	info->stream_timer[substream->stream].info = info;
17605+	info->stream_timer[substream->stream].substream = substream;
17606+	timer_setup(&info->stream_timer[substream->stream].timer,
17607+		    imx_rpmsg_timer_callback, 0);
17608+	return ret;
17609+}
17610+
17611+static int imx_rpmsg_pcm_close(struct snd_soc_component *component,
17612+			       struct snd_pcm_substream *substream)
17613+{
17614+	struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream);
17615+	struct rpmsg_info *info = dev_get_drvdata(component->dev);
17616+	struct rpmsg_msg *msg;
17617+	int ret = 0;
17618+
17619+	/* Flush work in workqueue to make TX_CLOSE is the last message */
17620+	flush_workqueue(info->rpmsg_wq);
17621+
17622+	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
17623+		msg = &info->msg[TX_CLOSE];
17624+		msg->s_msg.header.cmd = TX_CLOSE;
17625+	} else {
17626+		msg = &info->msg[RX_CLOSE];
17627+		msg->s_msg.header.cmd = RX_CLOSE;
17628+	}
17629+
17630+	info->send_message(msg, info);
17631+
17632+	del_timer(&info->stream_timer[substream->stream].timer);
17633+
17634+	rtd->dai_link->ignore_suspend = 0;
17635+
17636+	if (info->msg_drop_count[substream->stream])
17637+		dev_warn(rtd->dev, "Msg is dropped!, number is %d\n",
17638+			 info->msg_drop_count[substream->stream]);
17639+
17640+	return ret;
17641+}
17642+
17643+static int imx_rpmsg_pcm_prepare(struct snd_soc_component *component,
17644+				 struct snd_pcm_substream *substream)
17645+{
17646+	struct snd_pcm_runtime *runtime = substream->runtime;
17647+	struct snd_soc_pcm_runtime *rtd = substream->private_data;
17648+	struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(rtd, 0);
17649+	struct fsl_rpmsg *rpmsg = dev_get_drvdata(cpu_dai->dev);
17650+
17651+	/*
17652+	 * NON-MMAP mode, NONBLOCK, Version 2, enable lpa in dts
17653+	 * four conditions to determine the lpa is enabled.
17654+	 */
17655+	if ((runtime->access == SNDRV_PCM_ACCESS_RW_INTERLEAVED ||
17656+	     runtime->access == SNDRV_PCM_ACCESS_RW_NONINTERLEAVED) &&
17657+	     rpmsg->enable_lpa) {
17658+		/*
17659+		 * Ignore suspend operation in low power mode
17660+		 * M core will continue playback music on A core suspend.
17661+		 */
17662+		rtd->dai_link->ignore_suspend = 1;
17663+		rpmsg->force_lpa = 1;
17664+	} else {
17665+		rpmsg->force_lpa = 0;
17666+	}
17667+
17668+	return 0;
17669+}
17670+
17671+static int imx_rpmsg_pcm_mmap(struct snd_soc_component *component,
17672+			      struct snd_pcm_substream *substream,
17673+			      struct vm_area_struct *vma)
17674+{
17675+	struct snd_pcm_runtime *runtime = substream->runtime;
17676+
17677+	return dma_mmap_wc(substream->pcm->card->dev, vma,
17678+			   runtime->dma_area,
17679+			   runtime->dma_addr,
17680+			   runtime->dma_bytes);
17681+}
17682+
17683+static void imx_rpmsg_pcm_dma_complete(void *arg)
17684+{
17685+	struct snd_pcm_substream *substream = arg;
17686+
17687+	snd_pcm_period_elapsed(substream);
17688+}
17689+
17690+static int imx_rpmsg_prepare_and_submit(struct snd_soc_component *component,
17691+					struct snd_pcm_substream *substream)
17692+{
17693+	struct rpmsg_info *info = dev_get_drvdata(component->dev);
17694+	struct rpmsg_msg *msg;
17695+
17696+	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
17697+		msg = &info->msg[TX_BUFFER];
17698+		msg->s_msg.header.cmd = TX_BUFFER;
17699+	} else {
17700+		msg = &info->msg[RX_BUFFER];
17701+		msg->s_msg.header.cmd = RX_BUFFER;
17702+	}
17703+
17704+	/* Send buffer address and buffer size */
17705+	msg->s_msg.param.buffer_addr = substream->runtime->dma_addr;
17706+	msg->s_msg.param.buffer_size = snd_pcm_lib_buffer_bytes(substream);
17707+	msg->s_msg.param.period_size = snd_pcm_lib_period_bytes(substream);
17708+	msg->s_msg.param.buffer_tail = 0;
17709+
17710+	info->num_period[substream->stream] = msg->s_msg.param.buffer_size /
17711+					      msg->s_msg.param.period_size;
17712+
17713+	info->callback[substream->stream] = imx_rpmsg_pcm_dma_complete;
17714+	info->callback_param[substream->stream] = substream;
17715+
17716+	return imx_rpmsg_insert_workqueue(substream, msg, info);
17717+}
17718+
17719+static int imx_rpmsg_async_issue_pending(struct snd_soc_component *component,
17720+					 struct snd_pcm_substream *substream)
17721+{
17722+	struct rpmsg_info *info = dev_get_drvdata(component->dev);
17723+	struct rpmsg_msg *msg;
17724+
17725+	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
17726+		msg = &info->msg[TX_START];
17727+		msg->s_msg.header.cmd = TX_START;
17728+	} else {
17729+		msg = &info->msg[RX_START];
17730+		msg->s_msg.header.cmd = RX_START;
17731+	}
17732+
17733+	return imx_rpmsg_insert_workqueue(substream, msg, info);
17734+}
17735+
17736+static int imx_rpmsg_restart(struct snd_soc_component *component,
17737+			     struct snd_pcm_substream *substream)
17738+{
17739+	struct rpmsg_info *info = dev_get_drvdata(component->dev);
17740+	struct rpmsg_msg *msg;
17741+
17742+	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
17743+		msg = &info->msg[TX_RESTART];
17744+		msg->s_msg.header.cmd = TX_RESTART;
17745+	} else {
17746+		msg = &info->msg[RX_RESTART];
17747+		msg->s_msg.header.cmd = RX_RESTART;
17748+	}
17749+
17750+	return imx_rpmsg_insert_workqueue(substream, msg, info);
17751+}
17752+
17753+static int imx_rpmsg_pause(struct snd_soc_component *component,
17754+			   struct snd_pcm_substream *substream)
17755+{
17756+	struct rpmsg_info *info = dev_get_drvdata(component->dev);
17757+	struct rpmsg_msg *msg;
17758+
17759+	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
17760+		msg = &info->msg[TX_PAUSE];
17761+		msg->s_msg.header.cmd = TX_PAUSE;
17762+	} else {
17763+		msg = &info->msg[RX_PAUSE];
17764+		msg->s_msg.header.cmd = RX_PAUSE;
17765+	}
17766+
17767+	return imx_rpmsg_insert_workqueue(substream, msg, info);
17768+}
17769+
17770+static int imx_rpmsg_terminate_all(struct snd_soc_component *component,
17771+				   struct snd_pcm_substream *substream)
17772+{
17773+	struct rpmsg_info *info = dev_get_drvdata(component->dev);
17774+	struct rpmsg_msg *msg;
17775+	int cmd;
17776+
17777+	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
17778+		msg = &info->msg[TX_TERMINATE];
17779+		msg->s_msg.header.cmd = TX_TERMINATE;
17780+		/* Clear buffer count*/
17781+		cmd = TX_PERIOD_DONE + MSG_TYPE_A_NUM;
17782+		info->msg[cmd].s_msg.param.buffer_tail = 0;
17783+		info->msg[cmd].r_msg.param.buffer_tail = 0;
17784+		info->msg[TX_POINTER].r_msg.param.buffer_offset = 0;
17785+	} else {
17786+		msg = &info->msg[RX_TERMINATE];
17787+		msg->s_msg.header.cmd = RX_TERMINATE;
17788+		/* Clear buffer count*/
17789+		cmd = RX_PERIOD_DONE + MSG_TYPE_A_NUM;
17790+		info->msg[cmd].s_msg.param.buffer_tail = 0;
17791+		info->msg[cmd].r_msg.param.buffer_tail = 0;
17792+		info->msg[RX_POINTER].r_msg.param.buffer_offset = 0;
17793+	}
17794+
17795+	del_timer(&info->stream_timer[substream->stream].timer);
17796+
17797+	return imx_rpmsg_insert_workqueue(substream, msg, info);
17798+}
17799+
17800+static int imx_rpmsg_pcm_trigger(struct snd_soc_component *component,
17801+				 struct snd_pcm_substream *substream, int cmd)
17802+{
17803+	struct snd_pcm_runtime *runtime = substream->runtime;
17804+	struct snd_soc_pcm_runtime *rtd = substream->private_data;
17805+	struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(rtd, 0);
17806+	struct fsl_rpmsg *rpmsg = dev_get_drvdata(cpu_dai->dev);
17807+	int ret = 0;
17808+
17809+	switch (cmd) {
17810+	case SNDRV_PCM_TRIGGER_START:
17811+		ret = imx_rpmsg_prepare_and_submit(component, substream);
17812+		if (ret)
17813+			return ret;
17814+		ret = imx_rpmsg_async_issue_pending(component, substream);
17815+		break;
17816+	case SNDRV_PCM_TRIGGER_RESUME:
17817+		if (rpmsg->force_lpa)
17818+			break;
17819+		fallthrough;
17820+	case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
17821+		ret = imx_rpmsg_restart(component, substream);
17822+		break;
17823+	case SNDRV_PCM_TRIGGER_SUSPEND:
17824+		if (!rpmsg->force_lpa) {
17825+			if (runtime->info & SNDRV_PCM_INFO_PAUSE)
17826+				ret = imx_rpmsg_pause(component, substream);
17827+			else
17828+				ret = imx_rpmsg_terminate_all(component, substream);
17829+		}
17830+		break;
17831+	case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
17832+		ret = imx_rpmsg_pause(component, substream);
17833+		break;
17834+	case SNDRV_PCM_TRIGGER_STOP:
17835+		ret = imx_rpmsg_terminate_all(component, substream);
17836+		break;
17837+	default:
17838+		return -EINVAL;
17839+	}
17840+
17841+	if (ret)
17842+		return ret;
17843+
17844+	return 0;
17845+}
17846+
17847+/*
17848+ * imx_rpmsg_pcm_ack
17849+ *
17850+ * Send the period index to M core through rpmsg, but not send
17851+ * all the period index to M core, reduce some unnessesary msg
17852+ * to reduce the pressure of rpmsg bandwidth.
17853+ */
17854+static int imx_rpmsg_pcm_ack(struct snd_soc_component *component,
17855+			     struct snd_pcm_substream *substream)
17856+{
17857+	struct snd_pcm_runtime *runtime = substream->runtime;
17858+	struct snd_soc_pcm_runtime *rtd = substream->private_data;
17859+	struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(rtd, 0);
17860+	struct fsl_rpmsg *rpmsg = dev_get_drvdata(cpu_dai->dev);
17861+	struct rpmsg_info *info = dev_get_drvdata(component->dev);
17862+	snd_pcm_uframes_t period_size = runtime->period_size;
17863+	snd_pcm_sframes_t avail;
17864+	struct timer_list *timer;
17865+	struct rpmsg_msg *msg;
17866+	unsigned long flags;
17867+	int buffer_tail = 0;
17868+	int written_num;
17869+
17870+	if (!rpmsg->force_lpa)
17871+		return 0;
17872+
17873+	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
17874+		msg = &info->msg[TX_PERIOD_DONE + MSG_TYPE_A_NUM];
17875+		msg->s_msg.header.cmd = TX_PERIOD_DONE;
17876+	} else {
17877+		msg = &info->msg[RX_PERIOD_DONE + MSG_TYPE_A_NUM];
17878+		msg->s_msg.header.cmd = RX_PERIOD_DONE;
17879+	}
17880+
17881+	msg->s_msg.header.type = MSG_TYPE_C;
17882+
17883+	buffer_tail = (frames_to_bytes(runtime, runtime->control->appl_ptr) %
17884+		       snd_pcm_lib_buffer_bytes(substream));
17885+	buffer_tail = buffer_tail / snd_pcm_lib_period_bytes(substream);
17886+
17887+	/* There is update for period index */
17888+	if (buffer_tail != msg->s_msg.param.buffer_tail) {
17889+		written_num = buffer_tail - msg->s_msg.param.buffer_tail;
17890+		if (written_num < 0)
17891+			written_num += runtime->periods;
17892+
17893+		msg->s_msg.param.buffer_tail = buffer_tail;
17894+
17895+		/* The notification message is updated to latest */
17896+		spin_lock_irqsave(&info->lock[substream->stream], flags);
17897+		memcpy(&info->notify[substream->stream], msg,
17898+		       sizeof(struct rpmsg_s_msg));
17899+		info->notify_updated[substream->stream] = true;
17900+		spin_unlock_irqrestore(&info->lock[substream->stream], flags);
17901+
17902+		if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
17903+			avail = snd_pcm_playback_hw_avail(runtime);
17904+		else
17905+			avail = snd_pcm_capture_hw_avail(runtime);
17906+
17907+		timer = &info->stream_timer[substream->stream].timer;
17908+		/*
17909+		 * If the data in the buffer is less than one period before
17910+		 * this fill, which means the data may not enough on M
17911+		 * core side, we need to send message immediately to let
17912+		 * M core know the pointer is updated.
17913+		 * if there is more than one period data in the buffer before
17914+		 * this fill, which means the data is enough on M core side,
17915+		 * we can delay one period (using timer) to send the message
17916+		 * for reduce the message number in workqueue, because the
17917+		 * pointer may be updated by ack function later, we can
17918+		 * send latest pointer to M core side.
17919+		 */
17920+		if ((avail - written_num * period_size) <= period_size) {
17921+			imx_rpmsg_insert_workqueue(substream, msg, info);
17922+		} else if (rpmsg->force_lpa && !timer_pending(timer)) {
17923+			int time_msec;
17924+
17925+			time_msec = (int)(runtime->period_size * 1000 / runtime->rate);
17926+			mod_timer(timer, jiffies + msecs_to_jiffies(time_msec));
17927+		}
17928+	}
17929+
17930+	return 0;
17931+}
17932+
17933+static int imx_rpmsg_pcm_preallocate_dma_buffer(struct snd_pcm *pcm,
17934+						int stream, int size)
17935+{
17936+	struct snd_pcm_substream *substream = pcm->streams[stream].substream;
17937+	struct snd_dma_buffer *buf = &substream->dma_buffer;
17938+
17939+	buf->dev.type = SNDRV_DMA_TYPE_DEV;
17940+	buf->dev.dev = pcm->card->dev;
17941+	buf->private_data = NULL;
17942+	buf->area = dma_alloc_wc(pcm->card->dev, size,
17943+				 &buf->addr, GFP_KERNEL);
17944+	if (!buf->area)
17945+		return -ENOMEM;
17946+
17947+	buf->bytes = size;
17948+	return 0;
17949+}
17950+
17951+static void imx_rpmsg_pcm_free_dma_buffers(struct snd_soc_component *component,
17952+					   struct snd_pcm *pcm)
17953+{
17954+	struct snd_pcm_substream *substream;
17955+	struct snd_dma_buffer *buf;
17956+	int stream;
17957+
17958+	for (stream = SNDRV_PCM_STREAM_PLAYBACK;
17959+	     stream < SNDRV_PCM_STREAM_LAST; stream++) {
17960+		substream = pcm->streams[stream].substream;
17961+		if (!substream)
17962+			continue;
17963+
17964+		buf = &substream->dma_buffer;
17965+		if (!buf->area)
17966+			continue;
17967+
17968+		dma_free_wc(pcm->card->dev, buf->bytes,
17969+			    buf->area, buf->addr);
17970+		buf->area = NULL;
17971+	}
17972+}
17973+
17974+static int imx_rpmsg_pcm_new(struct snd_soc_component *component,
17975+			     struct snd_soc_pcm_runtime *rtd)
17976+{
17977+	struct snd_card *card = rtd->card->snd_card;
17978+	struct snd_pcm *pcm = rtd->pcm;
17979+	struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(rtd, 0);
17980+	struct fsl_rpmsg *rpmsg = dev_get_drvdata(cpu_dai->dev);
17981+	int ret;
17982+
17983+	ret = dma_coerce_mask_and_coherent(card->dev, DMA_BIT_MASK(32));
17984+	if (ret)
17985+		return ret;
17986+
17987+	if (pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream) {
17988+		ret = imx_rpmsg_pcm_preallocate_dma_buffer(pcm, SNDRV_PCM_STREAM_PLAYBACK,
17989+							   rpmsg->buffer_size);
17990+		if (ret)
17991+			goto out;
17992+	}
17993+
17994+	if (pcm->streams[SNDRV_PCM_STREAM_CAPTURE].substream) {
17995+		ret = imx_rpmsg_pcm_preallocate_dma_buffer(pcm, SNDRV_PCM_STREAM_CAPTURE,
17996+							   rpmsg->buffer_size);
17997+		if (ret)
17998+			goto out;
17999+	}
18000+
18001+out:
18002+	/* free preallocated buffers in case of error */
18003+	if (ret)
18004+		imx_rpmsg_pcm_free_dma_buffers(component, pcm);
18005+
18006+	return ret;
18007+}
18008+
18009+static const struct snd_soc_component_driver imx_rpmsg_soc_component = {
18010+	.name		= IMX_PCM_DRV_NAME,
18011+	.pcm_construct	= imx_rpmsg_pcm_new,
18012+	.pcm_destruct	= imx_rpmsg_pcm_free_dma_buffers,
18013+	.open		= imx_rpmsg_pcm_open,
18014+	.close		= imx_rpmsg_pcm_close,
18015+	.hw_params	= imx_rpmsg_pcm_hw_params,
18016+	.hw_free	= imx_rpmsg_pcm_hw_free,
18017+	.trigger	= imx_rpmsg_pcm_trigger,
18018+	.pointer	= imx_rpmsg_pcm_pointer,
18019+	.mmap		= imx_rpmsg_pcm_mmap,
18020+	.ack		= imx_rpmsg_pcm_ack,
18021+	.prepare	= imx_rpmsg_pcm_prepare,
18022+};
18023+
18024+static void imx_rpmsg_pcm_work(struct work_struct *work)
18025+{
18026+	struct work_of_rpmsg *work_of_rpmsg;
18027+	bool is_notification = false;
18028+	struct rpmsg_info *info;
18029+	struct rpmsg_msg msg;
18030+	unsigned long flags;
18031+
18032+	work_of_rpmsg = container_of(work, struct work_of_rpmsg, work);
18033+	info = work_of_rpmsg->info;
18034+
18035+	/*
18036+	 * Every work in the work queue, first we check if there
18037+	 * is update for period is filled, because there may be not
18038+	 * enough data in M core side, need to let M core know
18039+	 * data is updated immediately.
18040+	 */
18041+	spin_lock_irqsave(&info->lock[TX], flags);
18042+	if (info->notify_updated[TX]) {
18043+		memcpy(&msg, &info->notify[TX], sizeof(struct rpmsg_s_msg));
18044+		info->notify_updated[TX] = false;
18045+		spin_unlock_irqrestore(&info->lock[TX], flags);
18046+		info->send_message(&msg, info);
18047+	} else {
18048+		spin_unlock_irqrestore(&info->lock[TX], flags);
18049+	}
18050+
18051+	spin_lock_irqsave(&info->lock[RX], flags);
18052+	if (info->notify_updated[RX]) {
18053+		memcpy(&msg, &info->notify[RX], sizeof(struct rpmsg_s_msg));
18054+		info->notify_updated[RX] = false;
18055+		spin_unlock_irqrestore(&info->lock[RX], flags);
18056+		info->send_message(&msg, info);
18057+	} else {
18058+		spin_unlock_irqrestore(&info->lock[RX], flags);
18059+	}
18060+
18061+	/* Skip the notification message for it has been processed above */
18062+	if (work_of_rpmsg->msg.s_msg.header.type == MSG_TYPE_C &&
18063+	    (work_of_rpmsg->msg.s_msg.header.cmd == TX_PERIOD_DONE ||
18064+	     work_of_rpmsg->msg.s_msg.header.cmd == RX_PERIOD_DONE))
18065+		is_notification = true;
18066+
18067+	if (!is_notification)
18068+		info->send_message(&work_of_rpmsg->msg, info);
18069+
18070+	/* update read index */
18071+	spin_lock_irqsave(&info->wq_lock, flags);
18072+	info->work_read_index++;
18073+	info->work_read_index %= WORK_MAX_NUM;
18074+	spin_unlock_irqrestore(&info->wq_lock, flags);
18075+}
18076+
18077+static int imx_rpmsg_pcm_probe(struct platform_device *pdev)
18078+{
18079+	struct snd_soc_component *component;
18080+	struct device_node *np;
18081+	struct rpmsg_info *info;
18082+	int ret, i;
18083+
18084+	info = devm_kzalloc(&pdev->dev, sizeof(*info), GFP_KERNEL);
18085+	if (!info)
18086+		return -ENOMEM;
18087+
18088+	platform_set_drvdata(pdev, info);
18089+
18090+	info->rpdev = container_of(pdev->dev.parent, struct rpmsg_device, dev);
18091+	info->dev = &pdev->dev;
18092+	/* Setup work queue */
18093+	info->rpmsg_wq = alloc_ordered_workqueue(info->rpdev->id.name,
18094+						 WQ_HIGHPRI |
18095+						 WQ_UNBOUND |
18096+						 WQ_FREEZABLE);
18097+	if (!info->rpmsg_wq) {
18098+		dev_err(&pdev->dev, "workqueue create failed\n");
18099+		return -ENOMEM;
18100+	}
18101+
18102+	/* Write index initialize 1, make it differ with the read index */
18103+	info->work_write_index = 1;
18104+	info->send_message = imx_rpmsg_pcm_send_message;
18105+
18106+	for (i = 0; i < WORK_MAX_NUM; i++) {
18107+		INIT_WORK(&info->work_list[i].work, imx_rpmsg_pcm_work);
18108+		info->work_list[i].info = info;
18109+	}
18110+
18111+	/* Initialize msg */
18112+	for (i = 0; i < MSG_MAX_NUM; i++) {
18113+		info->msg[i].s_msg.header.cate  = IMX_RPMSG_AUDIO;
18114+		info->msg[i].s_msg.header.major = IMX_RMPSG_MAJOR;
18115+		info->msg[i].s_msg.header.minor = IMX_RMPSG_MINOR;
18116+		info->msg[i].s_msg.header.type  = MSG_TYPE_A;
18117+		info->msg[i].s_msg.param.audioindex = 0;
18118+	}
18119+
18120+	init_completion(&info->cmd_complete);
18121+	mutex_init(&info->msg_lock);
18122+	spin_lock_init(&info->lock[TX]);
18123+	spin_lock_init(&info->lock[RX]);
18124+	spin_lock_init(&info->wq_lock);
18125+
18126+	ret = devm_snd_soc_register_component(&pdev->dev,
18127+					      &imx_rpmsg_soc_component,
18128+					      NULL, 0);
18129+	if (ret)
18130+		goto fail;
18131+
18132+	component = snd_soc_lookup_component(&pdev->dev, NULL);
18133+	if (!component) {
18134+		ret = -EINVAL;
18135+		goto fail;
18136+	}
18137+	/* platform component name is used by machine driver to link with */
18138+	component->name = IMX_PCM_DRV_NAME;
18139+	np = of_find_node_by_name(NULL, "rpmsg_audio");
18140+	if (np && of_property_read_bool(np, "fsl,platform"))
18141+		component->name = info->rpdev->id.name;
18142+
18143+#ifdef CONFIG_DEBUG_FS
18144+	component->debugfs_prefix = "rpmsg";
18145+#endif
18146+
18147+	return 0;
18148+
18149+fail:
18150+	if (info->rpmsg_wq)
18151+		destroy_workqueue(info->rpmsg_wq);
18152+
18153+	return ret;
18154+}
18155+
18156+static int imx_rpmsg_pcm_remove(struct platform_device *pdev)
18157+{
18158+	struct rpmsg_info *info = platform_get_drvdata(pdev);
18159+
18160+	if (info->rpmsg_wq)
18161+		destroy_workqueue(info->rpmsg_wq);
18162+
18163+	return 0;
18164+}
18165+
18166+#ifdef CONFIG_PM
18167+static int imx_rpmsg_pcm_runtime_resume(struct device *dev)
18168+{
18169+	struct rpmsg_info *info = dev_get_drvdata(dev);
18170+
18171+	cpu_latency_qos_add_request(&info->pm_qos_req, 0);
18172+
18173+	return 0;
18174+}
18175+
18176+static int imx_rpmsg_pcm_runtime_suspend(struct device *dev)
18177+{
18178+	struct rpmsg_info *info = dev_get_drvdata(dev);
18179+
18180+	cpu_latency_qos_remove_request(&info->pm_qos_req);
18181+
18182+	return 0;
18183+}
18184+#endif
18185+
18186+#ifdef CONFIG_PM_SLEEP
18187+static int imx_rpmsg_pcm_suspend(struct device *dev)
18188+{
18189+	struct rpmsg_info *info = dev_get_drvdata(dev);
18190+	struct rpmsg_msg *rpmsg_tx;
18191+	struct rpmsg_msg *rpmsg_rx;
18192+
18193+	rpmsg_tx = &info->msg[TX_SUSPEND];
18194+	rpmsg_rx = &info->msg[RX_SUSPEND];
18195+
18196+	rpmsg_tx->s_msg.header.cmd = TX_SUSPEND;
18197+	info->send_message(rpmsg_tx, info);
18198+
18199+	rpmsg_rx->s_msg.header.cmd = RX_SUSPEND;
18200+	info->send_message(rpmsg_rx, info);
18201+
18202+	return 0;
18203+}
18204+
18205+static int imx_rpmsg_pcm_resume(struct device *dev)
18206+{
18207+	struct rpmsg_info *info = dev_get_drvdata(dev);
18208+	struct rpmsg_msg *rpmsg_tx;
18209+	struct rpmsg_msg *rpmsg_rx;
18210+
18211+	rpmsg_tx = &info->msg[TX_RESUME];
18212+	rpmsg_rx = &info->msg[RX_RESUME];
18213+
18214+	rpmsg_tx->s_msg.header.cmd = TX_RESUME;
18215+	info->send_message(rpmsg_tx, info);
18216+
18217+	rpmsg_rx->s_msg.header.cmd = RX_RESUME;
18218+	info->send_message(rpmsg_rx, info);
18219+
18220+	return 0;
18221+}
18222+#endif /* CONFIG_PM_SLEEP */
18223+
18224+static const struct dev_pm_ops imx_rpmsg_pcm_pm_ops = {
18225+	SET_RUNTIME_PM_OPS(imx_rpmsg_pcm_runtime_suspend,
18226+			   imx_rpmsg_pcm_runtime_resume,
18227+			   NULL)
18228+	SET_SYSTEM_SLEEP_PM_OPS(imx_rpmsg_pcm_suspend,
18229+				imx_rpmsg_pcm_resume)
18230+};
18231+
18232+static struct platform_driver imx_pcm_rpmsg_driver = {
18233+	.probe  = imx_rpmsg_pcm_probe,
18234+	.remove	= imx_rpmsg_pcm_remove,
18235+	.driver = {
18236+		.name = IMX_PCM_DRV_NAME,
18237+		.pm = &imx_rpmsg_pcm_pm_ops,
18238+	},
18239+};
18240+module_platform_driver(imx_pcm_rpmsg_driver);
18241+
18242+MODULE_DESCRIPTION("Freescale SoC Audio RPMSG PCM interface");
18243+MODULE_AUTHOR("Shengjiu Wang <shengjiu.wang@nxp.com>");
18244+MODULE_ALIAS("platform:" IMX_PCM_DRV_NAME);
18245+MODULE_LICENSE("GPL v2");
18246diff --git a/sound/soc/fsl/imx-pcm-rpmsg.h b/sound/soc/fsl/imx-pcm-rpmsg.h
18247new file mode 100644
18248index 000000000..cbc12a6d4
18249--- /dev/null
18250+++ b/sound/soc/fsl/imx-pcm-rpmsg.h
18251@@ -0,0 +1,525 @@
18252+/* SPDX-License-Identifier: GPL-2.0+ */
18253+/*
18254+ * Copyright 2017-2021  NXP
18255+ *
18256+ ******************************************************************************
18257+ * Communication stack of audio with rpmsg
18258+ ******************************************************************************
18259+ * Packet structure:
18260+ *   A SRTM message consists of a 10 bytes header followed by 0~N bytes of data
18261+ *
18262+ *   +---------------+-------------------------------+
18263+ *   |               |            Content            |
18264+ *   +---------------+-------------------------------+
18265+ *   |  Byte Offset  | 7   6   5   4   3   2   1   0 |
18266+ *   +---------------+---+---+---+---+---+---+---+---+
18267+ *   |       0       |           Category            |
18268+ *   +---------------+---+---+---+---+---+---+---+---+
18269+ *   |     1 ~ 2     |           Version             |
18270+ *   +---------------+---+---+---+---+---+---+---+---+
18271+ *   |       3       |             Type              |
18272+ *   +---------------+---+---+---+---+---+---+---+---+
18273+ *   |       4       |           Command             |
18274+ *   +---------------+---+---+---+---+---+---+---+---+
18275+ *   |       5       |           Reserved0           |
18276+ *   +---------------+---+---+---+---+---+---+---+---+
18277+ *   |       6       |           Reserved1           |
18278+ *   +---------------+---+---+---+---+---+---+---+---+
18279+ *   |       7       |           Reserved2           |
18280+ *   +---------------+---+---+---+---+---+---+---+---+
18281+ *   |       8       |           Reserved3           |
18282+ *   +---------------+---+---+---+---+---+---+---+---+
18283+ *   |       9       |           Reserved4           |
18284+ *   +---------------+---+---+---+---+---+---+---+---+
18285+ *   |       10      |            DATA 0             |
18286+ *   +---------------+---+---+---+---+---+---+---+---+
18287+ *   :   :   :   :   :   :   :   :   :   :   :   :   :
18288+ *   +---------------+---+---+---+---+---+---+---+---+
18289+ *   |   N + 10 - 1  |            DATA N-1           |
18290+ *   +---------------+---+---+---+---+---+---+---+---+
18291+ *
18292+ *   +----------+------------+------------------------------------------------+
18293+ *   |  Field   |    Byte    |                                                |
18294+ *   +----------+------------+------------------------------------------------+
18295+ *   | Category |     0      | The destination category.                      |
18296+ *   +----------+------------+------------------------------------------------+
18297+ *   | Version  |   1 ~ 2    | The category version of the sender of the      |
18298+ *   |          |            | packet.                                        |
18299+ *   |          |            | The first byte represent the major version of  |
18300+ *   |          |            | the packet.The second byte represent the minor |
18301+ *   |          |            | version of the packet.                         |
18302+ *   +----------+------------+------------------------------------------------+
18303+ *   |  Type    |     3      | The message type of current message packet.    |
18304+ *   +----------+------------+------------------------------------------------+
18305+ *   | Command  |     4      | The command byte sent to remote processor/SoC. |
18306+ *   +----------+------------+------------------------------------------------+
18307+ *   | Reserved |   5 ~ 9    | Reserved field for future extension.           |
18308+ *   +----------+------------+------------------------------------------------+
18309+ *   | Data     |     N      | The data payload of the message packet.        |
18310+ *   +----------+------------+------------------------------------------------+
18311+ *
18312+ * Audio control:
18313+ *   SRTM Audio Control Category Request Command Table:
18314+ *   +----------+---------+------+---------+-------------------------------+-----------------------+
18315+ *   | Category | Version | Type | Command | Data                          | Function              |
18316+ *   +----------+---------+------+---------+-------------------------------+-----------------------+
18317+ *   |  0x03    | 0x0100  | 0x00 |  0x00   | Data[0]: Audio Device Index   | Open a TX Instance.   |
18318+ *   |          |         |      |         | Data[1]:     format           |                       |
18319+ *   |          |         |      |         | Data[2]:     channels         |                       |
18320+ *   |          |         |      |         | Data[3-6]:   samplerate       |                       |
18321+ *   |          |         |      |         | Data[7-10]:  buffer_addr      |                       |
18322+ *   |          |         |      |         | Data[11-14]: buffer_size      |                       |
18323+ *   |          |         |      |         | Data[15-18]: period_size      |                       |
18324+ *   |          |         |      |         | Data[19-22]: buffer_tail      |                       |
18325+ *   +----------+---------+------+---------+-------------------------------+-----------------------+
18326+ *   |  0x03    | 0x0100  | 0x00 |  0x01   | Data[0]: Audio Device Index   | Start a TX Instance.  |
18327+ *   |          |         |      |         | Same as above command         |                       |
18328+ *   +----------+---------+------+---------+-------------------------------+-----------------------+
18329+ *   |  0x03    | 0x0100  | 0x00 |  0x02   | Data[0]: Audio Device Index   | Pause a TX Instance.  |
18330+ *   |          |         |      |         | Same as above command         |                       |
18331+ *   +----------+---------+------+---------+-------------------------------+-----------------------+
18332+ *   |  0x03    | 0x0100  | 0x00 |  0x03   | Data[0]: Audio Device Index   | Resume a TX Instance. |
18333+ *   +----------+---------+------+---------+-------------------------------+-----------------------+
18334+ *   |  0x03    | 0x0100  | 0x00 |  0x04   | Data[0]: Audio Device Index   | Stop a TX Instance.   |
18335+ *   +----------+---------+------+---------+-------------------------------+-----------------------+
18336+ *   |  0x03    | 0x0100  | 0x00 |  0x05   | Data[0]: Audio Device Index   | Close a TX Instance.  |
18337+ *   +----------+---------+------+---------+-------------------------------+-----------------------+
18338+ *   |  0x03    | 0x0100  | 0x00 |  0x06   | Data[0]: Audio Device Index   | Set Parameters for    |
18339+ *   |          |         |      |         | Data[1]:     format           | a TX Instance.        |
18340+ *   |          |         |      |         | Data[2]:     channels         |                       |
18341+ *   |          |         |      |         | Data[3-6]:   samplerate       |                       |
18342+ *   |          |         |      |         | Data[7-22]:  reserved         |                       |
18343+ *   +----------+---------+------+---------+-------------------------------+-----------------------+
18344+ *   |  0x03    | 0x0100  | 0x00 |  0x07   | Data[0]: Audio Device Index   | Set TX Buffer.        |
18345+ *   |          |         |      |         | Data[1-6]:   reserved         |                       |
18346+ *   |          |         |      |         | Data[7-10]:  buffer_addr      |                       |
18347+ *   |          |         |      |         | Data[11-14]: buffer_size      |                       |
18348+ *   |          |         |      |         | Data[15-18]: period_size      |                       |
18349+ *   |          |         |      |         | Data[19-22]: buffer_tail      |                       |
18350+ *   +----------+---------+------+---------+-------------------------------+-----------------------+
18351+ *   |  0x03    | 0x0100  | 0x00 |  0x08   | Data[0]: Audio Device Index   | Suspend a TX Instance |
18352+ *   +----------+---------+------+---------+-------------------------------+-----------------------+
18353+ *   |  0x03    | 0x0100  | 0x00 |  0x09   | Data[0]: Audio Device Index   | Resume a TX Instance. |
18354+ *   |          |         |      |         | Data[1]:     format           |                       |
18355+ *   |          |         |      |         | Data[2]:     channels         |                       |
18356+ *   |          |         |      |         | Data[3-6]:   samplerate       |                       |
18357+ *   |          |         |      |         | Data[7-10]:  buffer_addr      |                       |
18358+ *   |          |         |      |         | Data[11-14]: buffer_size      |                       |
18359+ *   |          |         |      |         | Data[15-18]: period_size      |                       |
18360+ *   |          |         |      |         | Data[19-22]: buffer_tail      |                       |
18361+ *   +----------+---------+------+---------+-------------------------------+-----------------------+
18362+ *   |  0x03    | 0x0100  | 0x00 |  0x0A   | Data[0]: Audio Device Index   | Open a RX Instance.   |
18363+ *   +----------+---------+------+---------+-------------------------------+-----------------------+
18364+ *   |  0x03    | 0x0100  | 0x00 |  0x0B   | Data[0]: Audio Device Index   | Start a RX Instance.  |
18365+ *   +----------+---------+------+---------+-------------------------------+-----------------------+
18366+ *   |  0x03    | 0x0100  | 0x00 |  0x0C   | Data[0]: Audio Device Index   | Pause a RX Instance.  |
18367+ *   +----------+---------+------+---------+-------------------------------+-----------------------+
18368+ *   |  0x03    | 0x0100  | 0x00 |  0x0D   | Data[0]: Audio Device Index   | Resume a RX Instance. |
18369+ *   +----------+---------+------+---------+-------------------------------+-----------------------+
18370+ *   |  0x03    | 0x0100  | 0x00 |  0x0E   | Data[0]: Audio Device Index   | Stop a RX Instance.   |
18371+ *   +----------+---------+------+---------+-------------------------------+-----------------------+
18372+ *   |  0x03    | 0x0100  | 0x00 |  0x0F   | Data[0]: Audio Device Index   | Close a RX Instance.  |
18373+ *   +----------+---------+------+---------+-------------------------------+-----------------------+
18374+ *   |  0x03    | 0x0100  | 0x00 |  0x10   | Data[0]: Audio Device Index   | Set Parameters for    |
18375+ *   |          |         |      |         | Data[1]:     format           | a RX Instance.        |
18376+ *   |          |         |      |         | Data[2]:     channels         |                       |
18377+ *   |          |         |      |         | Data[3-6]:   samplerate       |                       |
18378+ *   |          |         |      |         | Data[7-22]:  reserved         |                       |
18379+ *   +----------+---------+------+---------+-------------------------------+-----------------------+
18380+ *   |  0x03    | 0x0100  | 0x00 |  0x11   | Data[0]: Audio Device Index   | Set RX Buffer.        |
18381+ *   |          |         |      |         | Data[1-6]:   reserved         |                       |
18382+ *   |          |         |      |         | Data[7-10]:  buffer_addr      |                       |
18383+ *   |          |         |      |         | Data[11-14]: buffer_size      |                       |
18384+ *   |          |         |      |         | Data[15-18]: period_size      |                       |
18385+ *   |          |         |      |         | Data[19-22]: buffer_tail      |                       |
18386+ *   +----------+---------+------+---------+-------------------------------+-----------------------+
18387+ *   |  0x03    | 0x0100  | 0x00 |  0x12   | Data[0]: Audio Device Index   | Suspend a RX Instance.|
18388+ *   +----------+---------+------+---------+-------------------------------+-----------------------+
18389+ *   |  0x03    | 0x0100  | 0x00 |  0x13   | Data[0]: Audio Device Index   | Resume a RX Instance. |
18390+ *   |          |         |      |         | Data[1]:     format           |                       |
18391+ *   |          |         |      |         | Data[2]:     channels         |                       |
18392+ *   |          |         |      |         | Data[3-6]:   samplerate       |                       |
18393+ *   |          |         |      |         | Data[7-10]:  buffer_addr      |                       |
18394+ *   |          |         |      |         | Data[11-14]: buffer_size      |                       |
18395+ *   |          |         |      |         | Data[15-18]: period_size      |                       |
18396+ *   |          |         |      |         | Data[19-22]: buffer_tail      |                       |
18397+ *   +----------+---------+------+---------+-------------------------------+-----------------------+
18398+ *   |  0x03    | 0x0100  | 0x00 |  0x14   | Data[0]: Audio Device Index   | Set register value    |
18399+ *   |          |         |      |         | Data[1-6]:   reserved         | to codec              |
18400+ *   |          |         |      |         | Data[7-10]:  register         |                       |
18401+ *   |          |         |      |         | Data[11-14]: value            |                       |
18402+ *   |          |         |      |         | Data[15-22]: reserved         |                       |
18403+ *   +----------+---------+------+---------+-------------------------------+-----------------------+
18404+ *   |  0x03    | 0x0100  | 0x00 |  0x15   | Data[0]: Audio Device Index   | Get register value    |
18405+ *   |          |         |      |         | Data[1-6]:   reserved         | from codec            |
18406+ *   |          |         |      |         | Data[7-10]:  register         |                       |
18407+ *   |          |         |      |         | Data[11-22]: reserved         |                       |
18408+ *   +----------+---------+------+---------+-------------------------------+-----------------------+
18409+ *   Note 1: See <List of Sample Format> for available value of
18410+ *           Sample Format;
18411+ *   Note 2: See <List of Audio Channels> for available value of Channels;
18412+ *   Note 3: Sample Rate of Set Parameters for an Audio TX Instance
18413+ *           Command and Set Parameters for an Audio RX Instance Command is
18414+ *           in little-endian format.
18415+ *
18416+ *   SRTM Audio Control Category Response Command Table:
18417+ *   +----------+---------+------+---------+-------------------------------+-----------------------+
18418+ *   | Category | Version | Type | Command | Data                          | Function              |
18419+ *   +----------+---------+------+---------+-------------------------------+-----------------------+
18420+ *   |  0x03    | 0x0100  | 0x01 |  0x00   | Data[0]: Audio Device Index   | Reply for Open        |
18421+ *   |          |         |      |         | Data[1]: Return code          | a TX Instance         |
18422+ *   +----------+---------+------+---------+-------------------------------+-----------------------+
18423+ *   |  0x03    | 0x0100  | 0x01 |  0x01   | Data[0]: Audio Device Index   | Reply for Start       |
18424+ *   |          |         |      |         | Data[1]: Return code          | a TX Instance         |
18425+ *   +----------+---------+------+---------+-------------------------------+-----------------------+
18426+ *   |  0x03    | 0x0100  | 0x01 |  0x02   | Data[0]: Audio Device Index   | Reply for Pause       |
18427+ *   |          |         |      |         | Data[1]: Return code          | a TX Instance         |
18428+ *   +----------+---------+------+---------+-------------------------------+-----------------------+
18429+ *   |  0x03    | 0x0100  | 0x01 |  0x03   | Data[0]: Audio Device Index   | Reply for Resume      |
18430+ *   |          |         |      |         | Data[1]: Return code          | a TX Instance         |
18431+ *   +----------+---------+------+---------+-------------------------------+-----------------------+
18432+ *   |  0x03    | 0x0100  | 0x01 |  0x04   | Data[0]: Audio Device Index   | Reply for Stop        |
18433+ *   |          |         |      |         | Data[1]: Return code          | a TX Instance         |
18434+ *   +----------+---------+------+---------+-------------------------------+-----------------------+
18435+ *   |  0x03    | 0x0100  | 0x01 |  0x05   | Data[0]: Audio Device Index   | Reply for Close       |
18436+ *   |          |         |      |         | Data[1]: Return code          | a TX Instance         |
18437+ *   +----------+---------+------+---------+-------------------------------+-----------------------+
18438+ *   |  0x03    | 0x0100  | 0x01 |  0x06   | Data[0]: Audio Device Index   | Reply for Set Param   |
18439+ *   |          |         |      |         | Data[1]: Return code          | for a TX Instance.    |
18440+ *   +----------+---------+------+---------+-------------------------------+-----------------------+
18441+ *   |  0x03    | 0x0100  | 0x01 |  0x07   | Data[0]: Audio Device Index   | Reply for Set         |
18442+ *   |          |         |      |         | Data[1]: Return code          | TX Buffer             |
18443+ *   +----------+---------+------+---------+-------------------------------+-----------------------+
18444+ *   |  0x03    | 0x0100  | 0x01 |  0x08   | Data[0]: Audio Device Index   | Reply for Suspend     |
18445+ *   |          |         |      |         | Data[1]: Return code          | a TX Instance         |
18446+ *   +----------+---------+------+---------+-------------------------------+-----------------------+
18447+ *   |  0x03    | 0x0100  | 0x01 |  0x09   | Data[0]: Audio Device Index   | Reply for Resume      |
18448+ *   |          |         |      |         | Data[1]: Return code          | a TX Instance         |
18449+ *   +----------+---------+------+---------+-------------------------------+-----------------------+
18450+ *   |  0x03    | 0x0100  | 0x01 |  0x0A   | Data[0]: Audio Device Index   | Reply for Open        |
18451+ *   |          |         |      |         | Data[1]: Return code          | a TX Instance         |
18452+ *   +----------+---------+------+---------+-------------------------------+-----------------------+
18453+ *   |  0x03    | 0x0100  | 0x01 |  0x0B   | Data[0]: Audio Device Index   | Reply for Start       |
18454+ *   |          |         |      |         | Data[1]: Return code          | a TX Instance         |
18455+ *   +----------+---------+------+---------+-------------------------------+-----------------------+
18456+ *   |  0x03    | 0x0100  | 0x01 |  0x0C   | Data[0]: Audio Device Index   | Reply for Pause       |
18457+ *   |          |         |      |         | Data[1]: Return code          | a TX Instance         |
18458+ *   +----------+---------+------+---------+-------------------------------+-----------------------+
18459+ *   |  0x03    | 0x0100  | 0x01 |  0x0D   | Data[0]: Audio Device Index   | Reply for Resume      |
18460+ *   |          |         |      |         | Data[1]: Return code          | a RX Instance         |
18461+ *   +----------+---------+------+---------+-------------------------------+-----------------------+
18462+ *   |  0x03    | 0x0100  | 0x01 |  0x0E   | Data[0]: Audio Device Index   | Reply for Stop        |
18463+ *   |          |         |      |         | Data[1]: Return code          | a RX Instance         |
18464+ *   +----------+---------+------+---------+-------------------------------+-----------------------+
18465+ *   |  0x03    | 0x0100  | 0x01 |  0x0F   | Data[0]: Audio Device Index   | Reply for Close       |
18466+ *   |          |         |      |         | Data[1]: Return code          | a RX Instance         |
18467+ *   +----------+---------+------+---------+-------------------------------+-----------------------+
18468+ *   |  0x03    | 0x0100  | 0x01 |  0x10   | Data[0]: Audio Device Index   | Reply for Set Param   |
18469+ *   |          |         |      |         | Data[1]: Return code          | for a RX Instance.    |
18470+ *   +----------+---------+------+---------+-------------------------------+-----------------------+
18471+ *   |  0x03    | 0x0100  | 0x01 |  0x11   | Data[0]: Audio Device Index   | Reply for Set         |
18472+ *   |          |         |      |         | Data[1]: Return code          | RX Buffer             |
18473+ *   +----------+---------+------+---------+-------------------------------+-----------------------+
18474+ *   |  0x03    | 0x0100  | 0x01 |  0x12   | Data[0]: Audio Device Index   | Reply for Suspend     |
18475+ *   |          |         |      |         | Data[1]: Return code          | a RX Instance         |
18476+ *   +----------+---------+------+---------+-------------------------------+-----------------------+
18477+ *   |  0x03    | 0x0100  | 0x01 |  0x13   | Data[0]: Audio Device Index   | Reply for Resume      |
18478+ *   |          |         |      |         | Data[1]: Return code          | a RX Instance         |
18479+ *   +----------+---------+------+---------+-------------------------------+-----------------------+
18480+ *   |  0x03    | 0x0100  | 0x01 |  0x14   | Data[0]: Audio Device Index   | Reply for Set codec   |
18481+ *   |          |         |      |         | Data[1]: Return code          | register value        |
18482+ *   +----------+---------+------+---------+-------------------------------+-----------------------+
18483+ *   |  0x03    | 0x0100  | 0x01 |  0x15   | Data[0]: Audio Device Index   | Reply for Get codec   |
18484+ *   |          |         |      |         | Data[1]: Return code          | register value        |
18485+ *   |          |         |      |         | Data[2-6]:   reserved         |                       |
18486+ *   |          |         |      |         | Data[7-10]:  register         |                       |
18487+ *   |          |         |      |         | Data[11-14]: value            |                       |
18488+ *   |          |         |      |         | Data[15-22]: reserved         |                       |
18489+ *   +----------+---------+------+---------+-------------------------------+-----------------------+
18490+ *
18491+ *   SRTM Audio Control Category Notification Command Table:
18492+ *   +----------+---------+------+---------+-------------------------------+-----------------------+
18493+ *   | Category | Version | Type | Command | Data                          | Function              |
18494+ *   +----------+---------+------+---------+-------------------------------+-----------------------+
18495+ *   |  0x03    | 0x0100  | 0x02 |  0x00   | Data[0]: Audio Device Index   | Notify one TX period  |
18496+ *   |          |         |      |         |                               | is finished           |
18497+ *   +----------+---------+------+---------+-------------------------------+-----------------------+
18498+ *   |  0x03    | 0x0100  | 0x02 |  0x01   | Data[0]: Audio Device Index   | Notify one RX period  |
18499+ *   |          |         |      |         |                               | is finished           |
18500+ *   +----------+---------+------+---------+-------------------------------+-----------------------+
18501+ *
18502+ *   List of Sample Format:
18503+ *   +------------------+-----------------------+
18504+ *   | Sample Format    |   Description         |
18505+ *   +------------------+-----------------------+
18506+ *   |       0x0        | S16_LE                |
18507+ *   +------------------+-----------------------+
18508+ *   |       0x1        | S24_LE                |
18509+ *   +------------------+-----------------------+
18510+ *
18511+ *   List of Audio Channels
18512+ *   +------------------+-----------------------+
18513+ *   |  Audio Channel   |   Description         |
18514+ *   +------------------+-----------------------+
18515+ *   |       0x0        | Left Channel          |
18516+ *   +------------------+-----------------------+
18517+ *   |       0x1        | Right Channel         |
18518+ *   +------------------+---------------- ------+
18519+ *   |       0x2        | Left & Right Channel  |
18520+ *   +------------------+-----------------------+
18521+ *
18522+ */
18523+
18524+#ifndef _IMX_PCM_RPMSG_H
18525+#define _IMX_PCM_RPMSG_H
18526+
18527+#include <linux/pm_qos.h>
18528+#include <linux/interrupt.h>
18529+#include <sound/dmaengine_pcm.h>
18530+
18531+#define RPMSG_TIMEOUT 1000
18532+
18533+/* RPMSG Command (TYPE A)*/
18534+#define TX_OPEN		0x0
18535+#define	TX_START	0x1
18536+#define	TX_PAUSE	0x2
18537+#define	TX_RESTART	0x3
18538+#define	TX_TERMINATE	0x4
18539+#define	TX_CLOSE	0x5
18540+#define TX_HW_PARAM	0x6
18541+#define	TX_BUFFER	0x7
18542+#define	TX_SUSPEND	0x8
18543+#define	TX_RESUME	0x9
18544+
18545+#define	RX_OPEN		0xA
18546+#define	RX_START	0xB
18547+#define	RX_PAUSE	0xC
18548+#define	RX_RESTART	0xD
18549+#define	RX_TERMINATE	0xE
18550+#define	RX_CLOSE	0xF
18551+#define	RX_HW_PARAM	0x10
18552+#define	RX_BUFFER	0x11
18553+#define	RX_SUSPEND	0x12
18554+#define	RX_RESUME	0x13
18555+#define SET_CODEC_VALUE 0x14
18556+#define GET_CODEC_VALUE 0x15
18557+#define	TX_POINTER	0x16
18558+#define	RX_POINTER	0x17
18559+/* Total msg numver for type A */
18560+#define MSG_TYPE_A_NUM  0x18
18561+
18562+/* RPMSG Command (TYPE C)*/
18563+#define	TX_PERIOD_DONE	0x0
18564+#define	RX_PERIOD_DONE	0x1
18565+/* Total msg numver for type C */
18566+#define MSG_TYPE_C_NUM  0x2
18567+
18568+#define MSG_MAX_NUM     (MSG_TYPE_A_NUM + MSG_TYPE_C_NUM)
18569+
18570+#define MSG_TYPE_A	0x0
18571+#define MSG_TYPE_B	0x1
18572+#define MSG_TYPE_C	0x2
18573+
18574+#define RESP_NONE		0x0
18575+#define RESP_NOT_ALLOWED	0x1
18576+#define	RESP_SUCCESS		0x2
18577+#define	RESP_FAILED		0x3
18578+
18579+#define	RPMSG_S16_LE		0x0
18580+#define	RPMSG_S24_LE		0x1
18581+#define	RPMSG_S32_LE		0x2
18582+#define	RPMSG_DSD_U16_LE	49  /* SNDRV_PCM_FORMAT_DSD_U16_LE */
18583+#define	RPMSG_DSD_U24_LE	0x4
18584+#define	RPMSG_DSD_U32_LE	50  /* SNDRV_PCM_FORMAT_DSD_U32_LE */
18585+
18586+#define	RPMSG_CH_LEFT		0x0
18587+#define	RPMSG_CH_RIGHT		0x1
18588+#define	RPMSG_CH_STEREO		0x2
18589+
18590+#define WORK_MAX_NUM    0x30
18591+
18592+/* Category define */
18593+#define IMX_RMPSG_LIFECYCLE     1
18594+#define IMX_RPMSG_PMIC          2
18595+#define IMX_RPMSG_AUDIO         3
18596+#define IMX_RPMSG_KEY           4
18597+#define IMX_RPMSG_GPIO          5
18598+#define IMX_RPMSG_RTC           6
18599+#define IMX_RPMSG_SENSOR        7
18600+
18601+/* rpmsg version */
18602+#define IMX_RMPSG_MAJOR         1
18603+#define IMX_RMPSG_MINOR         0
18604+
18605+#define TX SNDRV_PCM_STREAM_PLAYBACK
18606+#define RX SNDRV_PCM_STREAM_CAPTURE
18607+
18608+/**
18609+ * struct rpmsg_head: rpmsg header structure
18610+ *
18611+ * @cate: category
18612+ * @major: major version
18613+ * @minor: minor version
18614+ * @type: message type (A/B/C)
18615+ * @cmd: message command
18616+ * @reserved: reserved space
18617+ */
18618+struct rpmsg_head {
18619+	u8 cate;
18620+	u8 major;
18621+	u8 minor;
18622+	u8 type;
18623+	u8 cmd;
18624+	u8 reserved[5];
18625+} __packed;
18626+
18627+/**
18628+ * struct param_s: sent rpmsg parameter
18629+ *
18630+ * @audioindex: audio instance index
18631+ * @format: audio format
18632+ * @channels: audio channel number
18633+ * @rate: sample rate
18634+ * @buffer_addr: dma buffer physical address or register for SET_CODEC_VALUE
18635+ * @buffer_size: dma buffer size or register value for SET_CODEC_VALUE
18636+ * @period_size: period size
18637+ * @buffer_tail: current period index
18638+ */
18639+struct param_s {
18640+	unsigned char audioindex;
18641+	unsigned char format;
18642+	unsigned char channels;
18643+	unsigned int  rate;
18644+	unsigned int  buffer_addr;
18645+	unsigned int  buffer_size;
18646+	unsigned int  period_size;
18647+	unsigned int  buffer_tail;
18648+} __packed;
18649+
18650+/**
18651+ * struct param_s: send rpmsg parameter
18652+ *
18653+ * @audioindex: audio instance index
18654+ * @resp: response value
18655+ * @reserved1: reserved space
18656+ * @buffer_offset: the consumed offset of buffer
18657+ * @reg_addr: register addr of codec
18658+ * @reg_data: register value of codec
18659+ * @reserved2: reserved space
18660+ * @buffer_tail: current period index
18661+ */
18662+struct param_r {
18663+	unsigned char audioindex;
18664+	unsigned char resp;
18665+	unsigned char reserved1[1];
18666+	unsigned int  buffer_offset;
18667+	unsigned int  reg_addr;
18668+	unsigned int  reg_data;
18669+	unsigned char reserved2[4];
18670+	unsigned int  buffer_tail;
18671+} __packed;
18672+
18673+/* Struct of sent message */
18674+struct rpmsg_s_msg {
18675+	struct rpmsg_head header;
18676+	struct param_s    param;
18677+};
18678+
18679+/* Struct of received message */
18680+struct rpmsg_r_msg {
18681+	struct rpmsg_head header;
18682+	struct param_r    param;
18683+};
18684+
18685+/* Struct of rpmsg */
18686+struct rpmsg_msg {
18687+	struct rpmsg_s_msg  s_msg;
18688+	struct rpmsg_r_msg  r_msg;
18689+};
18690+
18691+/* Struct of rpmsg for workqueue */
18692+struct work_of_rpmsg {
18693+	struct rpmsg_info   *info;
18694+	/* Sent msg for each work */
18695+	struct rpmsg_msg    msg;
18696+	struct work_struct  work;
18697+};
18698+
18699+/* Struct of timer */
18700+struct stream_timer {
18701+	struct timer_list   timer;
18702+	struct rpmsg_info   *info;
18703+	struct snd_pcm_substream *substream;
18704+};
18705+
18706+typedef void (*dma_callback)(void *arg);
18707+
18708+/**
18709+ * struct rpmsg_info: rpmsg audio information
18710+ *
18711+ * @rpdev: pointer of rpmsg_device
18712+ * @dev: pointer for imx_pcm_rpmsg device
18713+ * @cmd_complete: command is finished
18714+ * @pm_qos_req: request of pm qos
18715+ * @r_msg: received rpmsg
18716+ * @msg: array of rpmsg
18717+ * @notify: notification msg (type C) for TX & RX
18718+ * @notify_updated: notification flag for TX & RX
18719+ * @rpmsg_wq: rpmsg workqueue
18720+ * @work_list: array of work list for workqueue
18721+ * @work_write_index: write index of work list
18722+ * @work_read_index: read index of work list
18723+ * @msg_drop_count: counter of dropped msg for TX & RX
18724+ * @num_period: period number for TX & RX
18725+ * @callback_param: parameter for period elapse callback for TX & RX
18726+ * @callback: period elapse callback for TX & RX
18727+ * @send_message: function pointer for send message
18728+ * @lock: spin lock for TX & RX
18729+ * @wq_lock: lock for work queue
18730+ * @msg_lock: lock for send message
18731+ * @stream_timer: timer for tigger workqueue
18732+ */
18733+struct rpmsg_info {
18734+	struct rpmsg_device      *rpdev;
18735+	struct device            *dev;
18736+	struct completion        cmd_complete;
18737+	struct pm_qos_request    pm_qos_req;
18738+
18739+	/* Received msg (global) */
18740+	struct rpmsg_r_msg       r_msg;
18741+	struct rpmsg_msg         msg[MSG_MAX_NUM];
18742+	/* period done */
18743+	struct rpmsg_msg         notify[2];
18744+	bool                     notify_updated[2];
18745+
18746+	struct workqueue_struct  *rpmsg_wq;
18747+	struct work_of_rpmsg	 work_list[WORK_MAX_NUM];
18748+	int                      work_write_index;
18749+	int                      work_read_index;
18750+	int                      msg_drop_count[2];
18751+	int                      num_period[2];
18752+	void                     *callback_param[2];
18753+	dma_callback             callback[2];
18754+	int (*send_message)(struct rpmsg_msg *msg, struct rpmsg_info *info);
18755+	spinlock_t               lock[2]; /* spin lock for resource protection */
18756+	spinlock_t               wq_lock; /* spin lock for resource protection */
18757+	struct mutex             msg_lock; /* mutex for resource protection */
18758+	struct stream_timer      stream_timer[2];
18759+};
18760+
18761+struct rpmsg_codec {
18762+        int audioindex;
18763+
18764+        /*property for wm8960*/
18765+        bool capless;
18766+        bool shared_lrclk;
18767+};
18768+
18769+#define RPMSG_CODEC_WM8960 1
18770+#define RPMSG_CODEC_AK4497 2
18771+
18772+#define RPMSG_CODEC_DRV_NAME_WM8960 "rpmsg-codec-wm8960"
18773+#define RPMSG_CODEC_DRV_NAME_AK4497 "rpmsg-codec-ak4497"
18774+#define IMX_PCM_DRV_NAME "imx_pcm_rpmsg"
18775+
18776+#endif /* IMX_PCM_RPMSG_H */
18777diff --git a/sound/soc/fsl/imx-pcm.h b/sound/soc/fsl/imx-pcm.h
18778index 5dd406774..edbb26833 100644
18779--- a/sound/soc/fsl/imx-pcm.h
18780+++ b/sound/soc/fsl/imx-pcm.h
18781@@ -39,13 +39,27 @@ struct imx_pcm_fiq_params {
18782 	struct snd_dmaengine_dai_dma_data *dma_params_tx;
18783 };
18784
18785+#if IS_ENABLED(CONFIG_SND_SOC_IMX_PCM_RPMSG)
18786+int imx_rpmsg_platform_register(struct device *dev);
18787+#else
18788+static inline int imx_rpmsg_platform_register(struct device *dev)
18789+{
18790+	return -ENODEV;
18791+}
18792+#endif
18793+
18794 #if IS_ENABLED(CONFIG_SND_SOC_IMX_PCM_DMA)
18795 int imx_pcm_dma_init(struct platform_device *pdev, size_t size);
18796+int imx_pcm_platform_register(struct device *dev);
18797 #else
18798 static inline int imx_pcm_dma_init(struct platform_device *pdev, size_t size)
18799 {
18800 	return -ENODEV;
18801 }
18802+static inline int imx_pcm_platform_register(struct device *dev)
18803+{
18804+	return -ENODEV;
18805+}
18806 #endif
18807
18808 #if IS_ENABLED(CONFIG_SND_SOC_IMX_PCM_FIQ)
18809diff --git a/sound/soc/fsl/imx-pdm.c b/sound/soc/fsl/imx-pdm.c
18810new file mode 100644
18811index 000000000..32cf58404
18812--- /dev/null
18813+++ b/sound/soc/fsl/imx-pdm.c
18814@@ -0,0 +1,409 @@
18815+/*
18816+ * Copyright 2017-2020 NXP.
18817+ *
18818+ * The code contained herein is licensed under the GNU General Public
18819+ * License. You may obtain a copy of the GNU General Public License
18820+ * Version 2 or later at the following locations:
18821+ *
18822+ * http://www.opensource.org/licenses/gpl-license.html
18823+ * http://www.gnu.org/copyleft/gpl.html
18824+ */
18825+
18826+#include <linux/module.h>
18827+#include <linux/of_platform.h>
18828+#include <linux/slab.h>
18829+#include <linux/clk.h>
18830+#include <sound/soc.h>
18831+
18832+#include "fsl_sai.h"
18833+
18834+#define IMX_PDM_FORMATS (SNDRV_PCM_FMTBIT_DSD_U8 | \
18835+			 SNDRV_PCM_FMTBIT_DSD_U16_LE | \
18836+			 SNDRV_PCM_FMTBIT_DSD_U32_LE)
18837+
18838+struct imx_pdm_data {
18839+	struct snd_soc_dai_link dai;
18840+	struct snd_soc_card card;
18841+	unsigned int decimation;
18842+	unsigned long mclk_11k;
18843+	unsigned long mclk_8k;
18844+	bool fixed_mclk;
18845+	int osr_id;
18846+};
18847+
18848+static const struct imx_pdm_mic_fs_mul {
18849+	unsigned int min;
18850+	unsigned int max;
18851+	unsigned int mul;
18852+} fs_mul[] = {
18853+	{ .min =  8000, .max = 11025, .mul =  8 }, /* low power */
18854+	{ .min = 16000, .max = 64000, .mul = 16 }, /* performance */
18855+};
18856+
18857+/* Ratio based on default Audio PLLs
18858+ * Audio PLL1 = 393216000 Hz
18859+ * Audio PLL2 = 361267200 Hz
18860+ */
18861+static const struct imx_pdm_mic_mclk_fixed {
18862+	unsigned long mclk_11k;
18863+	unsigned long mclk_8k;
18864+	unsigned int ratio;
18865+} mclk_fixed[] = {
18866+	{ .mclk_11k = 11289600, .mclk_8k = 12288000, .ratio = 32 },
18867+	{ .mclk_11k = 15052800, .mclk_8k = 16384000, .ratio = 24 },
18868+	{ .mclk_11k = 22579200, .mclk_8k = 24576000, .ratio = 16 },
18869+	{ .mclk_11k = 45158400, .mclk_8k = 49152000, .ratio =  8 },
18870+};
18871+
18872+static const unsigned int imx_pdm_mic_rates[] = {
18873+	8000,  11025, 16000, 22050,
18874+	32000, 44100, 48000, 64000,
18875+};
18876+
18877+static const struct imx_pdm_mic_osr_map {
18878+	int id;
18879+	unsigned int osr;
18880+} osr_map[] = {
18881+	{ .id = 0, .osr =  48 }, /* 4x12 */
18882+	{ .id = 1, .osr =  64 }, /* 4x16 */
18883+	{ .id = 2, .osr =  96 }, /* 4x24 */
18884+	{ .id = 3, .osr = 128 }, /* 4x32 */
18885+	{ .id = 4, .osr = 192 }, /* 4x48 */
18886+};
18887+
18888+static int imx_pdm_mic_get_osr_id(int decimation)
18889+{
18890+	int i;
18891+
18892+	for (i = 0; i < ARRAY_SIZE(osr_map); i++) {
18893+		if (osr_map[i].osr == decimation)
18894+			return osr_map[i].id;
18895+	}
18896+
18897+	return -EINVAL;
18898+}
18899+
18900+static unsigned int imx_pdm_mic_get_osr_rate(int osr_id)
18901+{
18902+	int i;
18903+
18904+	for (i = 0; ARRAY_SIZE(osr_map); i++) {
18905+		if (osr_map[i].id == osr_id)
18906+			return osr_map[i].osr;
18907+	}
18908+
18909+	return -EINVAL;
18910+}
18911+
18912+static const char *const osr_rate_text[] = {
18913+	"OSR_4x12",
18914+	"OSR_4x16",
18915+	"OSR_4x24",
18916+	"OSR_4x32",
18917+	"OSR_4x48"
18918+};
18919+
18920+static int osr_rate_get(struct snd_kcontrol *kcontrol,
18921+		struct snd_ctl_elem_value *ucontrol)
18922+{
18923+	struct snd_soc_card *card = snd_kcontrol_chip(kcontrol);
18924+	struct imx_pdm_data *data = snd_soc_card_get_drvdata(card);
18925+
18926+	ucontrol->value.enumerated.item[0] = data->osr_id;
18927+
18928+	return 0;
18929+}
18930+
18931+static int osr_rate_set(struct snd_kcontrol *kcontrol,
18932+		struct snd_ctl_elem_value *ucontrol)
18933+{
18934+	struct snd_soc_card *card = snd_kcontrol_chip(kcontrol);
18935+	struct imx_pdm_data *data = snd_soc_card_get_drvdata(card);
18936+	struct soc_enum *e = (struct soc_enum *)kcontrol->private_value;
18937+	unsigned int *item = ucontrol->value.enumerated.item;
18938+	int osr = snd_soc_enum_item_to_val(e, item[0]);
18939+
18940+	data->decimation = imx_pdm_mic_get_osr_rate(osr);
18941+	data->osr_id = osr;
18942+
18943+	return 0;
18944+}
18945+
18946+static const struct soc_enum osr_rate_enum =
18947+	SOC_ENUM_SINGLE_EXT(ARRAY_SIZE(osr_rate_text), osr_rate_text);
18948+
18949+const struct snd_kcontrol_new imx_pdm_mic_snd_ctrls[] = {
18950+	SOC_ENUM_EXT("over sampling ratio", osr_rate_enum,
18951+		     osr_rate_get, osr_rate_set),
18952+};
18953+
18954+static struct snd_pcm_hw_constraint_list imx_pdm_mic_rate_constrains = {
18955+	.count = ARRAY_SIZE(imx_pdm_mic_rates),
18956+	.list = imx_pdm_mic_rates,
18957+};
18958+static unsigned int imx_pdm_mic_channels[] = { 1, 2, 4, 6, 8 };
18959+static struct snd_pcm_hw_constraint_list imx_pdm_mic_channels_constrains = {
18960+	.count = ARRAY_SIZE(imx_pdm_mic_channels),
18961+	.list = imx_pdm_mic_channels,
18962+};
18963+
18964+static unsigned long imx_pdm_mic_mclk_freq(unsigned int decimation,
18965+		unsigned int rate)
18966+{
18967+	int i;
18968+
18969+	/* Find appropriate mclk freq */
18970+	for (i = 0; i < ARRAY_SIZE(fs_mul); i++) {
18971+		if (rate >= fs_mul[i].min && rate <= fs_mul[i].max)
18972+			return (rate * decimation * fs_mul[i].mul);
18973+	}
18974+
18975+	return 0;
18976+}
18977+
18978+static int imx_pdm_mic_get_mclk_fixed(struct imx_pdm_data *data,
18979+		unsigned int ratio)
18980+{
18981+	int i;
18982+
18983+	for (i = 0; i < ARRAY_SIZE(mclk_fixed); i++) {
18984+		if (mclk_fixed[i].ratio == ratio) {
18985+			data->mclk_11k = mclk_fixed[i].mclk_11k;
18986+			data->mclk_8k = mclk_fixed[i].mclk_8k;
18987+			return 0;
18988+		}
18989+	}
18990+
18991+	return -EINVAL;
18992+}
18993+
18994+static int imx_pdm_mic_startup(struct snd_pcm_substream *substream)
18995+{
18996+	struct snd_soc_pcm_runtime *rtd = substream->private_data;
18997+	struct snd_pcm_runtime *runtime = substream->runtime;
18998+	struct snd_soc_card *card = rtd->card;
18999+	int ret;
19000+
19001+	ret = snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_RATE,
19002+			&imx_pdm_mic_rate_constrains);
19003+	if (ret) {
19004+		dev_err(card->dev,
19005+			"fail to set pcm hw rate constrains: %d\n", ret);
19006+		return ret;
19007+	}
19008+
19009+	ret = snd_pcm_hw_constraint_list(runtime, 0,
19010+		SNDRV_PCM_HW_PARAM_CHANNELS, &imx_pdm_mic_channels_constrains);
19011+	if (ret) {
19012+		dev_err(card->dev,
19013+			"fail to set pcm hw channels constrains: %d\n", ret);
19014+		return ret;
19015+	}
19016+
19017+	ret = snd_pcm_hw_constraint_mask64(runtime,
19018+			SNDRV_PCM_HW_PARAM_FORMAT, IMX_PDM_FORMATS);
19019+	if (ret) {
19020+		dev_err(card->dev,
19021+			"fail to set pcm hw format constrains: %d\n", ret);
19022+		return ret;
19023+	}
19024+
19025+	return 0;
19026+}
19027+
19028+static int imx_pdm_mic_hw_params(struct snd_pcm_substream *substream,
19029+		struct snd_pcm_hw_params *params)
19030+{
19031+	struct snd_soc_pcm_runtime *rtd = substream->private_data;
19032+	struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(rtd, 0);
19033+	struct snd_soc_card *card = rtd->card;
19034+	struct imx_pdm_data *data = snd_soc_card_get_drvdata(card);
19035+	unsigned int sample_rate = params_rate(params);
19036+	unsigned long mclk_freq;
19037+	int ret;
19038+
19039+	/* set cpu dai format configuration */
19040+	ret = snd_soc_dai_set_fmt(cpu_dai, SND_SOC_DAIFMT_PDM |
19041+			SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBS_CFS);
19042+	if (ret) {
19043+		dev_err(card->dev, "fail to set cpu dai fmt: %d\n", ret);
19044+		return ret;
19045+	}
19046+
19047+	/* Set bitclk ratio */
19048+	ret = snd_soc_dai_set_bclk_ratio(cpu_dai, data->decimation);
19049+	if (ret) {
19050+		dev_err(card->dev, "fail to set cpu sysclk: %d\n", ret);
19051+		return ret;
19052+	}
19053+
19054+	if (data->fixed_mclk) {
19055+		mclk_freq = (do_div(sample_rate, 8000) ?
19056+			data->mclk_11k : data->mclk_8k);
19057+	} else {
19058+		mclk_freq = imx_pdm_mic_mclk_freq(data->decimation,
19059+			sample_rate);
19060+	}
19061+	/* set mclk freq */
19062+	ret = snd_soc_dai_set_sysclk(cpu_dai, FSL_SAI_CLK_MAST1,
19063+			mclk_freq, SND_SOC_CLOCK_OUT);
19064+	if (ret) {
19065+		dev_err(card->dev, "fail to set cpu mclk1 rate: %lu\n",
19066+			mclk_freq);
19067+		return ret;
19068+	}
19069+
19070+	dev_dbg(card->dev, "mclk: %lu, bclk ratio: %u\n",
19071+			mclk_freq, data->decimation);
19072+
19073+	return 0;
19074+}
19075+
19076+static const struct snd_soc_ops imx_pdm_mic_ops = {
19077+	.startup = imx_pdm_mic_startup,
19078+	.hw_params = imx_pdm_mic_hw_params,
19079+};
19080+
19081+static int imx_pdm_mic_probe(struct platform_device *pdev)
19082+{
19083+	struct device_node *cpu_np = NULL;
19084+	struct device_node *np = pdev->dev.of_node;
19085+	struct platform_device *cpu_pdev;
19086+	struct imx_pdm_data *data;
19087+	struct snd_soc_dai_link_component *dlc;
19088+	unsigned long sai_mclk, sai_pll8k;
19089+	struct fsl_sai *sai;
19090+	unsigned int ratio;
19091+	int ret;
19092+
19093+	dlc = devm_kzalloc(&pdev->dev, 3 * sizeof(*dlc), GFP_KERNEL);
19094+	if (!dlc)
19095+		return -ENOMEM;
19096+
19097+	cpu_np = of_parse_phandle(np, "audio-cpu", 0);
19098+	if (!cpu_np) {
19099+		dev_err(&pdev->dev, "cpu dai phandle missing or invalid\n");
19100+		ret = -EINVAL;
19101+		goto fail;
19102+	}
19103+
19104+	cpu_pdev = of_find_device_by_node(cpu_np);
19105+	if (!cpu_pdev) {
19106+		dev_err(&pdev->dev, "fail to find SAI platform device\n");
19107+		ret = -EINVAL;
19108+		goto fail;
19109+	}
19110+
19111+	data = devm_kzalloc(&pdev->dev, sizeof(*data), GFP_KERNEL);
19112+	if (!data) {
19113+		ret = -ENOMEM;
19114+		goto fail;
19115+	}
19116+
19117+	ret = of_property_read_u32(np, "decimation", &data->decimation);
19118+	if (ret < 0) {
19119+		ret = -EINVAL;
19120+		goto fail;
19121+	}
19122+
19123+	data->osr_id = imx_pdm_mic_get_osr_id(data->decimation);
19124+	if (data->osr_id < 0) {
19125+		ret = -EINVAL;
19126+		goto fail;
19127+	}
19128+
19129+	if (of_find_property(np, "fixed-mclk", NULL))
19130+		data->fixed_mclk = true;
19131+
19132+	if (data->fixed_mclk) {
19133+		sai = dev_get_drvdata(&cpu_pdev->dev);
19134+		/* Get SAI clock settings */
19135+		sai_mclk = clk_get_rate(sai->mclk_clk[FSL_SAI_CLK_MAST1]);
19136+		sai_pll8k = clk_get_rate(sai->pll8k_clk);
19137+		ratio = sai_pll8k / sai_mclk;
19138+
19139+		ret = imx_pdm_mic_get_mclk_fixed(data, ratio);
19140+		if (ret) {
19141+			dev_err(&pdev->dev, "fail to set fixed mclk: %d\n", ret);
19142+			return ret;
19143+		}
19144+
19145+		dev_dbg(&pdev->dev, "sai_pll8k: %lu, sai_mclk: %lu, ratio: %u\n",
19146+			sai_pll8k, sai_mclk, ratio);
19147+	}
19148+
19149+	data->dai.cpus = &dlc[0];
19150+	data->dai.num_cpus = 1;
19151+	data->dai.platforms = &dlc[1];
19152+	data->dai.num_platforms = 1;
19153+	data->dai.codecs = &dlc[2];
19154+	data->dai.num_codecs = 1;
19155+
19156+	data->dai.name = "pdm hifi";
19157+	data->dai.stream_name = "pdm hifi";
19158+	data->dai.codecs->dai_name = "snd-soc-dummy-dai";
19159+	data->dai.codecs->name = "snd-soc-dummy";
19160+	data->dai.cpus->dai_name = dev_name(&cpu_pdev->dev);
19161+	data->dai.platforms->of_node = cpu_np;
19162+	data->dai.capture_only = 1;
19163+	data->dai.ops = &imx_pdm_mic_ops;
19164+
19165+	data->card.dev = &pdev->dev;
19166+	data->card.owner = THIS_MODULE;
19167+
19168+	ret = snd_soc_of_parse_card_name(&data->card, "model");
19169+	if (ret) {
19170+		dev_err(&pdev->dev, "fail to find card model name\n");
19171+		goto fail;
19172+	}
19173+
19174+	data->card.num_links = 1;
19175+	data->card.dai_link = &data->dai;
19176+	data->card.controls = imx_pdm_mic_snd_ctrls;
19177+	data->card.num_controls = ARRAY_SIZE(imx_pdm_mic_snd_ctrls);
19178+
19179+	platform_set_drvdata(pdev, &data->card);
19180+	snd_soc_card_set_drvdata(&data->card, data);
19181+
19182+	ret = devm_snd_soc_register_card(&pdev->dev, &data->card);
19183+	if (ret) {
19184+		dev_err(&pdev->dev, "snd soc register card failed: %d\n", ret);
19185+		goto fail;
19186+	}
19187+
19188+	ret = 0;
19189+fail:
19190+	if (cpu_np)
19191+		of_node_put(cpu_np);
19192+
19193+	return ret;
19194+}
19195+
19196+static int imx_pdm_mic_remove(struct platform_device *pdev)
19197+{
19198+	struct imx_pdm_data *data = platform_get_drvdata(pdev);
19199+	/* unregister card */
19200+	snd_soc_unregister_card(&data->card);
19201+	return 0;
19202+}
19203+
19204+static const struct of_device_id imx_pdm_mic_dt_ids[] = {
19205+	{ .compatible = "fsl,imx-pdm-mic", },
19206+	{ /* sentinel*/ }
19207+};
19208+MODULE_DEVICE_TABLE(of, imx_pdm_mic_dt_ids);
19209+
19210+static struct platform_driver imx_pdm_mic_driver = {
19211+	.driver = {
19212+		.name = "imx-pdm-mic",
19213+		.pm = &snd_soc_pm_ops,
19214+		.of_match_table = imx_pdm_mic_dt_ids,
19215+	},
19216+	.probe = imx_pdm_mic_probe,
19217+	.remove = imx_pdm_mic_remove,
19218+};
19219+module_platform_driver(imx_pdm_mic_driver);
19220+
19221+MODULE_DESCRIPTION("NXP i.MX PDM mic ASoC machine driver");
19222+MODULE_LICENSE("GPL v2");
19223+MODULE_ALIAS("platform:imx-pdm-mic");
19224diff --git a/sound/soc/fsl/imx-rpmsg.c b/sound/soc/fsl/imx-rpmsg.c
19225new file mode 100644
19226index 000000000..10cb67ee3
19227--- /dev/null
19228+++ b/sound/soc/fsl/imx-rpmsg.c
19229@@ -0,0 +1,200 @@
19230+// SPDX-License-Identifier: GPL-2.0+
19231+// Copyright 2017-2020 NXP
19232+
19233+#include <linux/module.h>
19234+#include <linux/of_platform.h>
19235+#include <linux/of_reserved_mem.h>
19236+#include <linux/i2c.h>
19237+#include <linux/of_gpio.h>
19238+#include <linux/slab.h>
19239+#include <linux/gpio.h>
19240+#include <linux/clk.h>
19241+#include <sound/soc.h>
19242+#include <sound/jack.h>
19243+#include <sound/control.h>
19244+#include <sound/pcm_params.h>
19245+#include <sound/soc-dapm.h>
19246+#include <sound/simple_card_utils.h>
19247+#include "imx-pcm-rpmsg.h"
19248+
19249+struct imx_rpmsg {
19250+	struct snd_soc_dai_link dai;
19251+	struct snd_soc_card card;
19252+	struct asoc_simple_jack hp_jack;
19253+	unsigned int sysclk;
19254+};
19255+
19256+static const struct snd_soc_dapm_widget imx_rpmsg_dapm_widgets[] = {
19257+	SND_SOC_DAPM_HP("Headphone Jack", NULL),
19258+	SND_SOC_DAPM_SPK("Ext Spk", NULL),
19259+	SND_SOC_DAPM_MIC("Mic Jack", NULL),
19260+	SND_SOC_DAPM_MIC("Main MIC", NULL),
19261+};
19262+
19263+static int imx_rpmsg_late_probe(struct snd_soc_card *card)
19264+{
19265+	struct imx_rpmsg *data = snd_soc_card_get_drvdata(card);
19266+	struct snd_soc_pcm_runtime *rtd = list_first_entry(&card->rtd_list,
19267+							   struct snd_soc_pcm_runtime, list);
19268+	struct snd_soc_dai *codec_dai = asoc_rtd_to_codec(rtd, 0);
19269+	struct device *dev = card->dev;
19270+	int ret;
19271+
19272+	if (data->sysclk) {
19273+		ret = snd_soc_dai_set_sysclk(codec_dai, 0, data->sysclk, SND_SOC_CLOCK_IN);
19274+		if (ret && ret != -ENOTSUPP) {
19275+			dev_err(dev, "failed to set sysclk in %s\n", __func__);
19276+			return ret;
19277+		}
19278+	}
19279+
19280+	return 0;
19281+}
19282+
19283+static int imx_rpmsg_probe(struct platform_device *pdev)
19284+{
19285+	struct snd_soc_dai_link_component *dlc;
19286+	struct device *dev = pdev->dev.parent;
19287+	/* rpmsg_pdev is the platform device for the rpmsg node that probed us */
19288+	struct platform_device *rpmsg_pdev = to_platform_device(dev);
19289+	struct device_node *np = rpmsg_pdev->dev.of_node;
19290+	struct of_phandle_args args;
19291+	const char *platform_name;
19292+	const char *model_string;
19293+	struct imx_rpmsg *data;
19294+	int ret = 0;
19295+
19296+	dlc = devm_kzalloc(&pdev->dev, 3 * sizeof(*dlc), GFP_KERNEL);
19297+	if (!dlc)
19298+		return -ENOMEM;
19299+
19300+	data = devm_kzalloc(&pdev->dev, sizeof(*data), GFP_KERNEL);
19301+	if (!data) {
19302+		ret = -ENOMEM;
19303+		goto fail;
19304+	}
19305+
19306+	ret = of_reserved_mem_device_init_by_idx(&pdev->dev, np, 0);
19307+	if (ret)
19308+		dev_warn(&pdev->dev, "no reserved DMA memory\n");
19309+
19310+	data->dai.cpus = &dlc[0];
19311+	data->dai.num_cpus = 1;
19312+	data->dai.platforms = &dlc[1];
19313+	data->dai.num_platforms = 1;
19314+	data->dai.codecs = &dlc[2];
19315+	data->dai.num_codecs = 1;
19316+
19317+	data->dai.name = "rpmsg hifi";
19318+	data->dai.stream_name = "rpmsg hifi";
19319+	data->dai.dai_fmt = SND_SOC_DAIFMT_I2S |
19320+			    SND_SOC_DAIFMT_NB_NF |
19321+			    SND_SOC_DAIFMT_CBS_CFS;
19322+
19323+	/* Optional codec node */
19324+	of_property_read_string(np, "model", &model_string);
19325+	ret = of_parse_phandle_with_fixed_args(np, "audio-codec", 0, 0, &args);
19326+	if (ret) {
19327+		if (of_device_is_compatible(np, "fsl,imx7ulp-rpmsg-audio")) {
19328+			data->dai.codecs->dai_name = "rpmsg-wm8960-hifi";
19329+			data->dai.codecs->name = RPMSG_CODEC_DRV_NAME_WM8960;
19330+		} else if (of_device_is_compatible(np, "fsl,imx8mm-rpmsg-audio") &&
19331+				!strcmp("ak4497-audio", model_string)) {
19332+			data->dai.codecs->dai_name = "rpmsg-ak4497-aif";
19333+			data->dai.codecs->name = RPMSG_CODEC_DRV_NAME_AK4497;
19334+		} else {
19335+			data->dai.codecs->dai_name = "snd-soc-dummy-dai";
19336+			data->dai.codecs->name = "snd-soc-dummy";
19337+		}
19338+	} else {
19339+		struct clk *clk;
19340+
19341+		data->dai.codecs->of_node = args.np;
19342+		ret = snd_soc_get_dai_name(&args, &data->dai.codecs->dai_name);
19343+		if (ret) {
19344+			dev_err(&pdev->dev, "Unable to get codec_dai_name\n");
19345+			goto fail;
19346+		}
19347+
19348+		clk = devm_get_clk_from_child(&pdev->dev, args.np, NULL);
19349+		if (!IS_ERR(clk))
19350+			data->sysclk = clk_get_rate(clk);
19351+	}
19352+
19353+	data->dai.cpus->dai_name = dev_name(&rpmsg_pdev->dev);
19354+	data->dai.platforms->name = IMX_PCM_DRV_NAME;
19355+	if (!of_property_read_string(np, "fsl,platform", &platform_name))
19356+		data->dai.platforms->name = platform_name;
19357+
19358+	data->dai.playback_only = true;
19359+	data->dai.capture_only = true;
19360+	data->card.num_links = 1;
19361+	data->card.dai_link = &data->dai;
19362+
19363+	if (of_property_read_bool(np, "fsl,rpmsg-out"))
19364+		data->dai.capture_only = false;
19365+
19366+	if (of_property_read_bool(np, "fsl,rpmsg-in"))
19367+		data->dai.playback_only = false;
19368+
19369+	if (data->dai.playback_only && data->dai.capture_only) {
19370+		dev_err(&pdev->dev, "no enabled rpmsg DAI link\n");
19371+		ret = -EINVAL;
19372+		goto fail;
19373+	}
19374+
19375+	data->card.dev = &pdev->dev;
19376+	data->card.owner = THIS_MODULE;
19377+	data->card.dapm_widgets = imx_rpmsg_dapm_widgets;
19378+	data->card.num_dapm_widgets = ARRAY_SIZE(imx_rpmsg_dapm_widgets);
19379+	data->card.late_probe = imx_rpmsg_late_probe;
19380+	/*
19381+	 * Inoder to use common api to get card name and audio routing.
19382+	 * Use parent of_node for this device, revert it after finishing using
19383+	 */
19384+	data->card.dev->of_node = np;
19385+
19386+	ret = snd_soc_of_parse_card_name(&data->card, "model");
19387+	if (ret)
19388+		goto fail;
19389+
19390+	if (of_property_read_bool(np, "audio-routing")) {
19391+		ret = snd_soc_of_parse_audio_routing(&data->card, "audio-routing");
19392+		if (ret) {
19393+			dev_err(&pdev->dev, "failed to parse audio-routing: %d\n", ret);
19394+			goto fail;
19395+		}
19396+	}
19397+
19398+	platform_set_drvdata(pdev, &data->card);
19399+	snd_soc_card_set_drvdata(&data->card, data);
19400+	ret = devm_snd_soc_register_card(&pdev->dev, &data->card);
19401+	if (ret) {
19402+		dev_err_probe(&pdev->dev, ret, "snd_soc_register_card failed\n");
19403+		goto fail;
19404+	}
19405+
19406+	data->hp_jack.pin.pin = "Headphone Jack";
19407+	data->hp_jack.pin.mask = SND_JACK_HEADPHONE;
19408+	snd_soc_card_jack_new(&data->card, "Headphone Jack", SND_JACK_HEADPHONE,
19409+			      &data->hp_jack.jack, &data->hp_jack.pin, 1);
19410+	snd_soc_jack_report(&data->hp_jack.jack, SND_JACK_HEADPHONE, SND_JACK_HEADPHONE);
19411+fail:
19412+	pdev->dev.of_node = NULL;
19413+	return ret;
19414+}
19415+
19416+static struct platform_driver imx_rpmsg_driver = {
19417+	.driver = {
19418+		.name = "imx-audio-rpmsg",
19419+		.owner = THIS_MODULE,
19420+		.pm = &snd_soc_pm_ops,
19421+	},
19422+	.probe = imx_rpmsg_probe,
19423+};
19424+module_platform_driver(imx_rpmsg_driver);
19425+
19426+MODULE_DESCRIPTION("Freescale SoC Audio RPMSG Machine Driver");
19427+MODULE_AUTHOR("Shengjiu Wang <shengjiu.wang@nxp.com>");
19428+MODULE_ALIAS("platform:imx-audio-rpmsg");
19429+MODULE_LICENSE("GPL v2");
19430diff --git a/sound/soc/fsl/imx-spdif.c b/sound/soc/fsl/imx-spdif.c
19431index 6c4dadf60..4d5589a5e 100644
19432--- a/sound/soc/fsl/imx-spdif.c
19433+++ b/sound/soc/fsl/imx-spdif.c
19434@@ -5,10 +5,67 @@
19435 #include <linux/module.h>
19436 #include <linux/of_platform.h>
19437 #include <sound/soc.h>
19438+#include "fsl_spdif.h"
19439+
19440+#define SUPPORT_RATE_NUM 10
19441
19442 struct imx_spdif_data {
19443 	struct snd_soc_dai_link dai;
19444 	struct snd_soc_card card;
19445+	u32 support_rates[SUPPORT_RATE_NUM];
19446+	u32 support_rates_num;
19447+};
19448+
19449+#define CLK_8K_FREQ    24576000
19450+#define CLK_11K_FREQ   22579200
19451+
19452+static int imx_spdif_startup(struct snd_pcm_substream *substream)
19453+{
19454+	struct snd_pcm_runtime *runtime = substream->runtime;
19455+	struct snd_soc_pcm_runtime *rtd = substream->private_data;
19456+	struct snd_soc_card *card = rtd->card;
19457+	struct imx_spdif_data *data = snd_soc_card_get_drvdata(card);
19458+	static struct snd_pcm_hw_constraint_list constraint_rates;
19459+	int ret;
19460+
19461+	if (!data->support_rates_num)
19462+		return 0;
19463+
19464+	constraint_rates.list = data->support_rates;
19465+	constraint_rates.count = data->support_rates_num;
19466+
19467+	ret = snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_RATE,
19468+					 &constraint_rates);
19469+	if (ret)
19470+		return ret;
19471+
19472+	return 0;
19473+}
19474+
19475+static int imx_spdif_hw_params(struct snd_pcm_substream *substream,
19476+		struct snd_pcm_hw_params *params)
19477+{
19478+	struct snd_soc_pcm_runtime *rtd = substream->private_data;
19479+	struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(rtd, 0);
19480+	struct device *dev = rtd->card->dev;
19481+	int ret = 0;
19482+	u64 rate = params_rate(params);
19483+	unsigned int freq;
19484+
19485+	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
19486+		freq = do_div(rate, 8000) ? CLK_11K_FREQ : CLK_8K_FREQ;
19487+		ret = snd_soc_dai_set_sysclk(cpu_dai, STC_TXCLK_SPDIF_ROOT,
19488+			freq, SND_SOC_CLOCK_OUT);
19489+		if (ret)
19490+			dev_err(dev, "failed to set cpu sysclk: %d\n", ret);
19491+	}
19492+
19493+	return ret;
19494+}
19495+
19496+static struct snd_soc_ops imx_spdif_ops = {
19497+	.startup = imx_spdif_startup,
19498+	.hw_params = imx_spdif_hw_params,
19499 };
19500
19501 static int imx_spdif_audio_probe(struct platform_device *pdev)
19502@@ -16,7 +73,7 @@ static int imx_spdif_audio_probe(struct platform_device *pdev)
19503 	struct device_node *spdif_np, *np = pdev->dev.of_node;
19504 	struct imx_spdif_data *data;
19505 	struct snd_soc_dai_link_component *comp;
19506-	int ret = 0;
19507+	int ret = 0, i;
19508
19509 	spdif_np = of_parse_phandle(np, "spdif-controller", 0);
19510 	if (!spdif_np) {
19511@@ -48,6 +105,7 @@ static int imx_spdif_audio_probe(struct platform_device *pdev)
19512 	data->dai.platforms->of_node = spdif_np;
19513 	data->dai.playback_only = true;
19514 	data->dai.capture_only = true;
19515+	data->dai.ops = &imx_spdif_ops;
19516
19517 	if (of_property_read_bool(np, "spdif-out"))
19518 		data->dai.capture_only = false;
19519@@ -60,6 +118,16 @@ static int imx_spdif_audio_probe(struct platform_device *pdev)
19520 		goto end;
19521 	}
19522
19523+	for (i = 0; i < SUPPORT_RATE_NUM; i++) {
19524+		ret = of_property_read_u32_index(pdev->dev.of_node,
19525+						 "fsl,constraint-rate",
19526+						 i, &data->support_rates[i]);
19527+		if (!ret)
19528+			data->support_rates_num = i + 1;
19529+		else
19530+			break;
19531+	}
19532+
19533 	data->card.dev = &pdev->dev;
19534 	data->card.dai_link = &data->dai;
19535 	data->card.num_links = 1;
19536@@ -69,6 +137,7 @@ static int imx_spdif_audio_probe(struct platform_device *pdev)
19537 	if (ret)
19538 		goto end;
19539
19540+	snd_soc_card_set_drvdata(&data->card, data);
19541 	ret = devm_snd_soc_register_card(&pdev->dev, &data->card);
19542 	if (ret && ret != -EPROBE_DEFER)
19543 		dev_err(&pdev->dev, "snd_soc_register_card failed: %d\n", ret);
19544diff --git a/sound/soc/fsl/imx-wm8904.c b/sound/soc/fsl/imx-wm8904.c
19545new file mode 100644
19546index 000000000..e6ee50f3d
19547--- /dev/null
19548+++ b/sound/soc/fsl/imx-wm8904.c
19549@@ -0,0 +1,525 @@
19550+/*
19551+ * Copyright (C) 2015-2016 Freescale Semiconductor, Inc.
19552+ *
19553+ * The code contained herein is licensed under the GNU General Public
19554+ * License. You may obtain a copy of the GNU General Public License
19555+ * Version 2 or later at the following locations:
19556+ *
19557+ * http://www.opensource.org/licenses/gpl-license.html
19558+ * http://www.gnu.org/copyleft/gpl.html
19559+ */
19560+
19561+#include <linux/module.h>
19562+#include <linux/of_platform.h>
19563+#include <linux/i2c.h>
19564+#include <linux/of_gpio.h>
19565+#include <linux/slab.h>
19566+#include <linux/gpio.h>
19567+#include <linux/clk.h>
19568+#include <sound/soc.h>
19569+#include <sound/jack.h>
19570+#include <sound/control.h>
19571+#include <sound/pcm_params.h>
19572+#include <sound/soc-dapm.h>
19573+#include <linux/pinctrl/consumer.h>
19574+#include <linux/mfd/syscon.h>
19575+#include "../codecs/wm8904.h"
19576+#include "fsl_sai.h"
19577+
19578+struct imx_wm8904_data {
19579+	struct snd_soc_card card;
19580+	struct clk *codec_clk;
19581+	unsigned int clk_frequency;
19582+	bool is_codec_master;
19583+	bool is_stream_in_use[2];
19584+	bool is_stream_opened[2];
19585+	struct regmap *gpr;
19586+	unsigned int hp_det[2];
19587+	u32 asrc_rate;
19588+	u32 asrc_format;
19589+};
19590+
19591+struct imx_priv {
19592+	enum of_gpio_flags hp_active_low;
19593+	enum of_gpio_flags mic_active_low;
19594+	bool is_headset_jack;
19595+	struct snd_kcontrol *headphone_kctl;
19596+	struct platform_device *pdev;
19597+	struct platform_device *asrc_pdev;
19598+	struct snd_card *snd_card;
19599+};
19600+
19601+static struct imx_priv card_priv;
19602+
19603+static const struct snd_soc_dapm_widget imx_wm8904_dapm_widgets[] = {
19604+	SND_SOC_DAPM_HP("Headphone Jack", NULL),
19605+	SND_SOC_DAPM_MIC("Mic Jack", NULL),
19606+	SND_SOC_DAPM_MIC("Line In Jack", NULL),
19607+};
19608+
19609+static int imx_hifi_hw_params(struct snd_pcm_substream *substream,
19610+				     struct snd_pcm_hw_params *params)
19611+{
19612+	struct snd_soc_pcm_runtime *rtd = substream->private_data;
19613+	struct snd_soc_dai *codec_dai = asoc_rtd_to_codec(rtd, 0);
19614+	struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(rtd, 0);
19615+	struct snd_soc_card *card = rtd->card;
19616+	struct imx_wm8904_data *data = snd_soc_card_get_drvdata(card);
19617+	bool tx = substream->stream == SNDRV_PCM_STREAM_PLAYBACK;
19618+	struct device *dev = card->dev;
19619+	unsigned int sample_rate = params_rate(params);
19620+	unsigned int pll_out;
19621+	unsigned int fmt;
19622+	int ret = 0;
19623+
19624+	data->is_stream_in_use[tx] = true;
19625+
19626+	if (data->is_stream_in_use[!tx])
19627+		return 0;
19628+
19629+	if (data->is_codec_master)
19630+		fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF |
19631+			SND_SOC_DAIFMT_CBM_CFM;
19632+	else
19633+		fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF |
19634+			SND_SOC_DAIFMT_CBS_CFS;
19635+
19636+	/* set cpu DAI configuration */
19637+	ret = snd_soc_dai_set_fmt(cpu_dai, fmt);
19638+	if (ret) {
19639+		dev_err(dev, "failed to set cpu dai fmt: %d\n", ret);
19640+		return ret;
19641+	}
19642+	/* set codec DAI configuration */
19643+	ret = snd_soc_dai_set_fmt(codec_dai, fmt);
19644+	if (ret) {
19645+		dev_err(dev, "failed to set codec dai fmt: %d\n", ret);
19646+		return ret;
19647+	}
19648+
19649+	if (!data->is_codec_master) {
19650+		ret = snd_soc_dai_set_tdm_slot(cpu_dai, 0, 0, 2, params_width(params));
19651+		if (ret) {
19652+			dev_err(dev, "failed to set cpu dai tdm slot: %d\n", ret);
19653+			return ret;
19654+		}
19655+
19656+		dev_err(dev, "params : %d\n", ret);
19657+	    ret = snd_soc_dai_set_sysclk(codec_dai, WM8904_CLK_MCLK,
19658+			0, SND_SOC_CLOCK_IN);
19659+		ret = snd_soc_dai_set_sysclk(cpu_dai, 0, 0, SND_SOC_CLOCK_OUT);
19660+		if (ret) {
19661+			dev_err(dev, "failed to set cpu sysclk: %d\n", ret);
19662+			return ret;
19663+		}
19664+		return 0;
19665+	} else {
19666+		ret = snd_soc_dai_set_sysclk(cpu_dai, 0, 0, SND_SOC_CLOCK_IN);
19667+		if (ret) {
19668+			dev_err(dev, "failed to set cpu sysclk: %d\n", ret);
19669+			return ret;
19670+		}
19671+	}
19672+
19673+	data->clk_frequency = clk_get_rate(data->codec_clk);
19674+
19675+	/* Set codec pll */
19676+	if (params_width(params) == 24)
19677+		pll_out = sample_rate * 768;
19678+	else
19679+		pll_out = sample_rate * 512;
19680+#if 1
19681+	ret = snd_soc_dai_set_pll(codec_dai, WM8904_FLL_MCLK, WM8904_FLL_MCLK,
19682+		32768, params_rate(params) * 256);
19683+	//ret = snd_soc_dai_set_pll(codec_dai, WM8960_SYSCLK_AUTO, 0, data->clk_frequency, pll_out);
19684+	if (ret)
19685+		return ret;
19686+#endif
19687+	ret = snd_soc_dai_set_sysclk(codec_dai, WM8904_CLK_MCLK,
19688+			0, SND_SOC_CLOCK_IN);
19689+	//ret = snd_soc_dai_set_sysclk(codec_dai, WM8960_SYSCLK_AUTO, pll_out, 0);
19690+
19691+	return ret;
19692+}
19693+
19694+static int imx_hifi_hw_free(struct snd_pcm_substream *substream)
19695+{
19696+	struct snd_soc_pcm_runtime *rtd = substream->private_data;
19697+	struct snd_soc_dai *codec_dai = asoc_rtd_to_codec(rtd, 0);
19698+	struct snd_soc_card *card = rtd->card;
19699+	struct imx_wm8904_data *data = snd_soc_card_get_drvdata(card);
19700+	bool tx = substream->stream == SNDRV_PCM_STREAM_PLAYBACK;
19701+	struct device *dev = card->dev;
19702+	int ret;
19703+
19704+	data->is_stream_in_use[tx] = false;
19705+
19706+	if (data->is_codec_master && !data->is_stream_in_use[!tx]) {
19707+		ret = snd_soc_dai_set_fmt(codec_dai, SND_SOC_DAIFMT_CBS_CFS | SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF);
19708+		if (ret)
19709+			dev_warn(dev, "failed to set codec dai fmt: %d\n", ret);
19710+	}
19711+
19712+	return 0;
19713+}
19714+
19715+static u32 imx_wm8904_rates[] = { 8000, 16000, 32000, 48000 };
19716+static struct snd_pcm_hw_constraint_list imx_wm8904_rate_constraints = {
19717+	.count = ARRAY_SIZE(imx_wm8904_rates),
19718+	.list = imx_wm8904_rates,
19719+};
19720+
19721+static int imx_hifi_startup(struct snd_pcm_substream *substream)
19722+{
19723+	struct snd_soc_pcm_runtime *rtd = substream->private_data;
19724+	struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(rtd, 0);
19725+	struct snd_soc_card *card = rtd->card;
19726+	struct imx_wm8904_data *data = snd_soc_card_get_drvdata(card);
19727+	bool tx = substream->stream == SNDRV_PCM_STREAM_PLAYBACK;
19728+	struct fsl_sai *sai = dev_get_drvdata(cpu_dai->dev);
19729+	int ret = 0;
19730+
19731+#if 0
19732+	data->is_stream_opened[tx] = true;
19733+	if (data->is_stream_opened[tx] != sai->is_stream_opened[tx] ||
19734+	    data->is_stream_opened[!tx] != sai->is_stream_opened[!tx]) {
19735+		data->is_stream_opened[tx] = false;
19736+		return -EBUSY;
19737+	}
19738+#endif
19739+
19740+	if (!data->is_codec_master) {
19741+		ret = snd_pcm_hw_constraint_list(substream->runtime, 0,
19742+				SNDRV_PCM_HW_PARAM_RATE, &imx_wm8904_rate_constraints);
19743+		if (ret)
19744+			return ret;
19745+	}
19746+
19747+	ret = clk_prepare_enable(data->codec_clk);
19748+	if (ret) {
19749+		dev_err(card->dev, "Failed to enable MCLK: %d\n", ret);
19750+		return ret;
19751+	}
19752+
19753+	return ret;
19754+}
19755+
19756+static void imx_hifi_shutdown(struct snd_pcm_substream *substream)
19757+{
19758+	struct snd_soc_pcm_runtime *rtd = substream->private_data;
19759+	struct snd_soc_card *card = rtd->card;
19760+	struct imx_wm8904_data *data = snd_soc_card_get_drvdata(card);
19761+	bool tx = substream->stream == SNDRV_PCM_STREAM_PLAYBACK;
19762+
19763+	clk_disable_unprepare(data->codec_clk);
19764+
19765+	data->is_stream_opened[tx] = false;
19766+}
19767+
19768+static struct snd_soc_ops imx_hifi_ops = {
19769+	.hw_params = imx_hifi_hw_params,
19770+	.hw_free = imx_hifi_hw_free,
19771+	.startup   = imx_hifi_startup,
19772+	.shutdown  = imx_hifi_shutdown,
19773+};
19774+
19775+static int imx_wm8904_late_probe(struct snd_soc_card *card)
19776+{
19777+	//struct snd_soc_dai *codec_dai = card->rtd[0].codec_dai;
19778+	//struct snd_soc_codec *codec = codec_dai->codec;
19779+	//struct imx_wm8904_data *data = snd_soc_card_get_drvdata(card);
19780+#if 0
19781+	/*
19782+	 * codec ADCLRC pin configured as GPIO, DACLRC pin is used as a frame
19783+	 * clock for ADCs and DACs
19784+	 */
19785+	snd_soc_update_bits(codec, WM8904_IFACE2, 1<<6, 1<<6);
19786+
19787+	/* GPIO1 used as headphone detect output */
19788+	snd_soc_update_bits(codec, WM8904_ADDCTL4, 7<<4, 3<<4);
19789+
19790+	/* Enable headphone jack detect */
19791+	snd_soc_update_bits(codec, WM8904_ADDCTL2, 1<<6, 1<<6);
19792+	snd_soc_update_bits(codec, WM8904_ADDCTL2, 1<<5, data->hp_det[1]<<5);
19793+	snd_soc_update_bits(codec, WM8904_ADDCTL4, 3<<2, data->hp_det[0]<<2);
19794+	snd_soc_update_bits(codec, WM8904_ADDCTL1, 3, 3);
19795+#endif
19796+	return 0;
19797+}
19798+
19799+static int be_hw_params_fixup(struct snd_soc_pcm_runtime *rtd,
19800+			struct snd_pcm_hw_params *params)
19801+{
19802+	struct snd_soc_card *card = rtd->card;
19803+	struct imx_wm8904_data *data = snd_soc_card_get_drvdata(card);
19804+	struct imx_priv *priv = &card_priv;
19805+	struct snd_interval *rate;
19806+	struct snd_mask *mask;
19807+
19808+	if (!priv->asrc_pdev)
19809+		return -EINVAL;
19810+
19811+	rate = hw_param_interval(params, SNDRV_PCM_HW_PARAM_RATE);
19812+	rate->max = rate->min = data->asrc_rate;
19813+
19814+	mask = hw_param_mask(params, SNDRV_PCM_HW_PARAM_FORMAT);
19815+	snd_mask_none(mask);
19816+	snd_mask_set(mask, data->asrc_format);
19817+
19818+	return 0;
19819+}
19820+
19821+//static struct snd_soc_dai_link imx_wm8904_dai[] = {
19822+//	{
19823+//		.name = "HiFi",
19824+//		.stream_name = "HiFi",
19825+//		//.codec_dai_name = "wm8904-hifi",
19826+//		.ops = &imx_hifi_ops,
19827+//	},
19828+//	{
19829+//		.name = "HiFi-ASRC-FE",
19830+//		.stream_name = "HiFi-ASRC-FE",
19831+//		//.codec_name = "snd-soc-dummy",
19832+//		//.codec_dai_name = "snd-soc-dummy-dai",
19833+//		.dynamic = 1,
19834+//		.ignore_pmdown_time = 1,
19835+//		.dpcm_playback = 1,
19836+//		.dpcm_capture = 1,
19837+//	},
19838+//	{
19839+//		.name = "HiFi-ASRC-BE",
19840+//		.stream_name = "HiFi-ASRC-BE",
19841+//		//.codec_dai_name = "wm8904-hifi",
19842+//	//	.platform_name = "snd-soc-dummy",
19843+//		.no_pcm = 1,
19844+//		.ignore_pmdown_time = 1,
19845+//		.dpcm_playback = 1,
19846+//		.dpcm_capture = 1,
19847+//		.ops = &imx_hifi_ops,
19848+//		.be_hw_params_fixup = be_hw_params_fixup,
19849+//	},
19850+//};
19851+
19852+SND_SOC_DAILINK_DEFS(hifi,
19853+    DAILINK_COMP_ARRAY(COMP_EMPTY()),
19854+    DAILINK_COMP_ARRAY(COMP_CODEC(NULL, "wm8904-hifi")),
19855+    DAILINK_COMP_ARRAY(COMP_EMPTY()));
19856+
19857+SND_SOC_DAILINK_DEFS(hifi_fe,
19858+    DAILINK_COMP_ARRAY(COMP_EMPTY()),
19859+    DAILINK_COMP_ARRAY(COMP_DUMMY()),
19860+    DAILINK_COMP_ARRAY(COMP_EMPTY()));
19861+
19862+SND_SOC_DAILINK_DEFS(hifi_be,
19863+    DAILINK_COMP_ARRAY(COMP_EMPTY()),
19864+    DAILINK_COMP_ARRAY(COMP_CODEC(NULL, "wm8904-hifi")),
19865+    DAILINK_COMP_ARRAY(COMP_DUMMY()));
19866+
19867+
19868+static struct snd_soc_dai_link imx_wm8904_dai[] = {
19869+    {
19870+        .name = "HiFi",
19871+        .stream_name = "HiFi",
19872+        .ops = &imx_hifi_ops,
19873+        SND_SOC_DAILINK_REG(hifi),
19874+    },
19875+    {
19876+        .name = "HiFi-ASRC-FE",
19877+        .stream_name = "HiFi-ASRC-FE",
19878+        .dynamic = 1,
19879+        .ignore_pmdown_time = 1,
19880+        .dpcm_playback = 1,
19881+        .dpcm_capture = 1,
19882+        .dpcm_merged_chan = 1,
19883+        SND_SOC_DAILINK_REG(hifi_fe),
19884+    },
19885+    {
19886+        .name = "HiFi-ASRC-BE",
19887+        .stream_name = "HiFi-ASRC-BE",
19888+        .no_pcm = 1,
19889+        .ignore_pmdown_time = 1,
19890+        .dpcm_playback = 1,
19891+        .dpcm_capture = 1,
19892+        .ops = &imx_hifi_ops,
19893+        .be_hw_params_fixup = be_hw_params_fixup,
19894+        SND_SOC_DAILINK_REG(hifi_be),
19895+    },
19896+};
19897+
19898+static int imx_wm8904_probe(struct platform_device *pdev)
19899+{
19900+	struct device_node *cpu_np, *codec_np = NULL;
19901+	struct device_node *gpr_np;
19902+	struct platform_device *cpu_pdev;
19903+	struct imx_priv *priv = &card_priv;
19904+	struct i2c_client *codec_dev;
19905+	struct imx_wm8904_data *data;
19906+	struct platform_device *asrc_pdev = NULL;
19907+	struct device_node *asrc_np;
19908+	u32 width;
19909+	int ret;
19910+
19911+	priv->pdev = pdev;
19912+
19913+	cpu_np = of_parse_phandle(pdev->dev.of_node, "cpu-dai", 0);
19914+	if (!cpu_np) {
19915+		dev_err(&pdev->dev, "cpu dai phandle missing or invalid\n");
19916+		ret = -EINVAL;
19917+		goto fail;
19918+	}
19919+
19920+	codec_np = of_parse_phandle(pdev->dev.of_node, "audio-codec", 0);
19921+	if (!codec_np) {
19922+		dev_err(&pdev->dev, "phandle missing or invalid\n");
19923+		ret = -EINVAL;
19924+		goto fail;
19925+	}
19926+
19927+	cpu_pdev = of_find_device_by_node(cpu_np);
19928+	if (!cpu_pdev) {
19929+		dev_err(&pdev->dev, "failed to find SAI platform device\n");
19930+		ret = -EINVAL;
19931+		goto fail;
19932+	}
19933+
19934+	codec_dev = of_find_i2c_device_by_node(codec_np);
19935+	if (!codec_dev || !codec_dev->dev.driver) {
19936+		dev_err(&pdev->dev, "failed to find codec platform device\n");
19937+		ret = -EINVAL;
19938+		goto fail;
19939+	}
19940+
19941+	data = devm_kzalloc(&pdev->dev, sizeof(*data), GFP_KERNEL);
19942+	if (!data) {
19943+		ret = -ENOMEM;
19944+		goto fail;
19945+	}
19946+
19947+	if (of_property_read_bool(pdev->dev.of_node, "codec-master"))
19948+		data->is_codec_master = true;
19949+
19950+	data->codec_clk = devm_clk_get(&codec_dev->dev, "mclk");
19951+	if (IS_ERR(data->codec_clk)) {
19952+		ret = PTR_ERR(data->codec_clk);
19953+		dev_err(&pdev->dev, "failed to get codec clk: %d\n", ret);
19954+		goto fail;
19955+	}
19956+
19957+	gpr_np = of_parse_phandle(pdev->dev.of_node, "gpr", 0);
19958+        if (gpr_np) {
19959+		data->gpr = syscon_node_to_regmap(gpr_np);
19960+		if (IS_ERR(data->gpr)) {
19961+			ret = PTR_ERR(data->gpr);
19962+			dev_err(&pdev->dev, "failed to get gpr regmap\n");
19963+			goto fail;
19964+		}
19965+
19966+		/* set SAI2_MCLK_DIR to enable codec MCLK for imx7d */
19967+		regmap_update_bits(data->gpr, 4, 1<<20, 1<<20);
19968+	}
19969+
19970+	asrc_np = of_parse_phandle(pdev->dev.of_node, "asrc-controller", 0);
19971+	if (asrc_np) {
19972+		asrc_pdev = of_find_device_by_node(asrc_np);
19973+		priv->asrc_pdev = asrc_pdev;
19974+	}
19975+
19976+	data->card.dai_link = imx_wm8904_dai;
19977+
19978+    imx_wm8904_dai[0].codecs->of_node   = codec_np;
19979+    imx_wm8904_dai[0].cpus->dai_name = dev_name(&cpu_pdev->dev);
19980+    imx_wm8904_dai[0].platforms->of_node = cpu_np;
19981+	if (!asrc_pdev) {
19982+		data->card.num_links = 1;
19983+	} else {
19984+        imx_wm8904_dai[1].cpus->of_node = asrc_np;
19985+        imx_wm8904_dai[1].platforms->of_node = asrc_np;
19986+		imx_wm8904_dai[2].codecs->of_node = codec_np;
19987+		imx_wm8904_dai[2].cpus->dai_name = dev_name(&cpu_pdev->dev);
19988+		data->card.num_links = 3;
19989+
19990+		ret = of_property_read_u32(asrc_np, "fsl,asrc-rate",
19991+				&data->asrc_rate);
19992+		if (ret) {
19993+			dev_err(&pdev->dev, "failed to get output rate\n");
19994+			ret = -EINVAL;
19995+			goto fail;
19996+		}
19997+
19998+		ret = of_property_read_u32(asrc_np, "fsl,asrc-width", &width);
19999+		if (ret) {
20000+			dev_err(&pdev->dev, "failed to get output rate\n");
20001+			ret = -EINVAL;
20002+			goto fail;
20003+		}
20004+
20005+		if (width == 24)
20006+			data->asrc_format = SNDRV_PCM_FORMAT_S24_LE;
20007+		else
20008+			data->asrc_format = SNDRV_PCM_FORMAT_S16_LE;
20009+	}
20010+
20011+	data->card.dev = &pdev->dev;
20012+	data->card.owner = THIS_MODULE;
20013+	ret = snd_soc_of_parse_card_name(&data->card, "model");
20014+	if (ret)
20015+		goto fail;
20016+	data->card.dapm_widgets = imx_wm8904_dapm_widgets;
20017+	data->card.num_dapm_widgets = ARRAY_SIZE(imx_wm8904_dapm_widgets);
20018+
20019+	ret = snd_soc_of_parse_audio_routing(&data->card, "audio-routing");
20020+	if (ret)
20021+		goto fail;
20022+
20023+	data->card.late_probe = imx_wm8904_late_probe;
20024+
20025+	platform_set_drvdata(pdev, &data->card);
20026+	snd_soc_card_set_drvdata(&data->card, data);
20027+	ret = devm_snd_soc_register_card(&pdev->dev, &data->card);
20028+	if (ret) {
20029+		dev_err(&pdev->dev, "snd_soc_register_card failed (%d)\n", ret);
20030+		goto fail;
20031+	}
20032+
20033+	priv->snd_card = data->card.snd_card;
20034+
20035+    return 0;
20036+
20037+fail:
20038+	if (cpu_np)
20039+		of_node_put(cpu_np);
20040+	if (codec_np)
20041+		of_node_put(codec_np);
20042+
20043+	return ret;
20044+}
20045+
20046+static int imx_wm8904_remove(struct platform_device *pdev)
20047+{
20048+	//driver_remove_file(pdev->dev.driver, &driver_attr_micphone);
20049+	//driver_remove_file(pdev->dev.driver, &driver_attr_headphone);
20050+
20051+	return 0;
20052+}
20053+
20054+static const struct of_device_id imx_wm8904_dt_ids[] = {
20055+    // { .compatible = "fsl,imx-audio-wm8904", },
20056+    { /* sentinel */ }
20057+};
20058+MODULE_DEVICE_TABLE(of, imx_wm8904_dt_ids);
20059+
20060+static struct platform_driver imx_wm8904_driver = {
20061+	.driver = {
20062+		.name = "imx-wm8904",
20063+		.pm = &snd_soc_pm_ops,
20064+		.of_match_table = imx_wm8904_dt_ids,
20065+	},
20066+	.probe = imx_wm8904_probe,
20067+	.remove = imx_wm8904_remove,
20068+};
20069+// module_platform_driver(imx_wm8904_driver);
20070+
20071+MODULE_AUTHOR("Freescale Semiconductor, Inc.");
20072+MODULE_DESCRIPTION("Freescale i.MX WM8904 ASoC machine driver");
20073+MODULE_LICENSE("GPL v2");
20074+MODULE_ALIAS("platform:imx-wm8904");
20075diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c
20076index e677422c1..c73768e7f 100644
20077--- a/sound/soc/soc-core.c
20078+++ b/sound/soc/soc-core.c
20079@@ -1668,7 +1668,9 @@ static void soc_check_tplg_fes(struct snd_soc_card *card)
20080 				dev_err(card->dev, "init platform error");
20081 				continue;
20082 			}
20083-			dai_link->platforms->name = component->name;
20084+
20085+			if (!dai_link->platforms->of_node)
20086+				dai_link->platforms->name = component->name;
20087
20088 			/* convert non BE into BE */
20089 			if (!dai_link->no_pcm) {
20090diff --git a/sound/soc/soc-pcm.c b/sound/soc/soc-pcm.c
20091index 8b8a9aca2..d6f397a71 100644
20092--- a/sound/soc/soc-pcm.c
20093+++ b/sound/soc/soc-pcm.c
20094@@ -2684,6 +2684,24 @@ static int dpcm_fe_dai_open(struct snd_pcm_substream *fe_substream)
20095 	return ret;
20096 }
20097
20098+static int soc_rtdcom_ack(struct snd_pcm_substream *substream)
20099+{
20100+	struct snd_soc_pcm_runtime *rtd = substream->private_data;
20101+	struct snd_soc_component *component;
20102+	int i;
20103+
20104+	for_each_rtd_components(rtd, i, component) {
20105+		if (!component->driver ||
20106+			!component->driver->ack)
20107+			continue;
20108+
20109+		/* FIXME. it returns 1st ask now */
20110+		return component->driver->ack(component, substream);
20111+	}
20112+
20113+	return -EINVAL;
20114+}
20115+
20116 /* create a new pcm */
20117 int soc_new_pcm(struct snd_soc_pcm_runtime *rtd, int num)
20118 {
20119@@ -2847,6 +2865,8 @@ int soc_new_pcm(struct snd_soc_pcm_runtime *rtd, int num)
20120 	for_each_rtd_components(rtd, i, component) {
20121 		const struct snd_soc_component_driver *drv = component->driver;
20122
20123+		if (drv->ack)
20124+			rtd->ops.ack            = soc_rtdcom_ack;
20125 		if (drv->ioctl)
20126 			rtd->ops.ioctl		= snd_soc_pcm_component_ioctl;
20127 		if (drv->sync_stop)
20128diff --git a/sound/soc/soc-utils.c b/sound/soc/soc-utils.c
20129index f27f94ca0..be92d8ae2 100644
20130--- a/sound/soc/soc-utils.c
20131+++ b/sound/soc/soc-utils.c
20132@@ -96,6 +96,9 @@ static const struct snd_soc_component_driver dummy_codec = {
20133 			SNDRV_PCM_FMTBIT_U24_LE | \
20134 			SNDRV_PCM_FMTBIT_S32_LE | \
20135 			SNDRV_PCM_FMTBIT_U32_LE | \
20136+			SNDRV_PCM_FMTBIT_DSD_U8 | \
20137+			SNDRV_PCM_FMTBIT_DSD_U16_LE | \
20138+			SNDRV_PCM_FMTBIT_DSD_U32_LE | \
20139 			SNDRV_PCM_FMTBIT_IEC958_SUBFRAME_LE)
20140 /*
20141  * The dummy CODEC is only meant to be used in situations where there is no
20142diff --git a/sound/soc/sof/Makefile b/sound/soc/sof/Makefile
20143index 05718dfe6..e95d4f1a7 100644
20144--- a/sound/soc/sof/Makefile
20145+++ b/sound/soc/sof/Makefile
20146@@ -1,7 +1,7 @@
20147 # SPDX-License-Identifier: (GPL-2.0-only OR BSD-3-Clause)
20148
20149 snd-sof-objs := core.o ops.o loader.o ipc.o pcm.o pm.o debug.o topology.o\
20150-		control.o trace.o utils.o sof-audio.o
20151+		control.o trace.o utils.o sof-audio.o ipc-stream.o
20152 snd-sof-$(CONFIG_SND_SOC_SOF_DEBUG_PROBES) += probe.o compress.o
20153
20154 snd-sof-pci-objs := sof-pci-dev.o
20155diff --git a/sound/soc/sof/imx/imx8.c b/sound/soc/sof/imx/imx8.c
20156index 4e7dccadd..c285b753f 100644
20157--- a/sound/soc/sof/imx/imx8.c
20158+++ b/sound/soc/sof/imx/imx8.c
20159@@ -6,6 +6,7 @@
20160 //
20161 // Hardware interface for audio DSP on i.MX8
20162
20163+#include <linux/clk.h>
20164 #include <linux/firmware.h>
20165 #include <linux/of_platform.h>
20166 #include <linux/of_address.h>
20167@@ -21,6 +22,7 @@
20168 #include <linux/firmware/imx/svc/misc.h>
20169 #include <dt-bindings/firmware/imx/rsrc.h>
20170 #include "../ops.h"
20171+#include "../sof-audio.h"
20172 #include "imx-common.h"
20173
20174 /* DSP memories */
20175@@ -40,6 +42,22 @@
20176 #define MBOX_OFFSET	0x800000
20177 #define MBOX_SIZE	0x1000
20178
20179+#define IMX8_DSP_CLK_NUM	3
20180+static const char *imx8_dsp_clks_names[IMX8_DSP_CLK_NUM] =
20181+{
20182+	/* DSP clocks */
20183+	"ipg", "ocram", "core",
20184+};
20185+
20186+#define IMX8_DAI_CLK_NUM	9
20187+static const char *imx8_dai_clks_names[IMX8_DAI_CLK_NUM] =
20188+{
20189+	/* ESAI0 clocks */
20190+	"esai0_core", "esai0_extal", "esai0_fsys", "esai0_spba",
20191+	/* SAI1 clocks */
20192+	"sai1_bus", "sai1_mclk0", "sai1_mclk1", "sai1_mclk2", "sai1_mclk3",
20193+};
20194+
20195 struct imx8_priv {
20196 	struct device *dev;
20197 	struct snd_sof_dev *sdev;
20198@@ -56,8 +74,75 @@ struct imx8_priv {
20199 	struct device **pd_dev;
20200 	struct device_link **link;
20201
20202+	struct clk *dsp_clks[IMX8_DSP_CLK_NUM];
20203+	struct clk *dai_clks[IMX8_DAI_CLK_NUM];
20204 };
20205
20206+static int imx8_init_clocks(struct snd_sof_dev *sdev)
20207+{
20208+	int i;
20209+	struct imx8_priv *priv = (struct imx8_priv *)sdev->pdata->hw_pdata;
20210+
20211+	for (i = 0; i < IMX8_DSP_CLK_NUM; i++) {
20212+		priv->dsp_clks[i] = devm_clk_get(priv->dev, imx8_dsp_clks_names[i]);
20213+		if (IS_ERR(priv->dsp_clks[i]))
20214+		    return PTR_ERR(priv->dsp_clks[i]);
20215+	}
20216+
20217+	for (i = 0; i < IMX8_DAI_CLK_NUM; i++)
20218+		priv->dai_clks[i] = devm_clk_get_optional(priv->dev, imx8_dai_clks_names[i]);
20219+
20220+	return 0;
20221+}
20222+
20223+static int imx8_prepare_clocks(struct snd_sof_dev *sdev)
20224+{
20225+	int i, j, ret;
20226+	struct imx8_priv *priv = (struct imx8_priv *)sdev->pdata->hw_pdata;
20227+
20228+	for (i = 0; i < IMX8_DSP_CLK_NUM; i++) {
20229+		ret = clk_prepare_enable(priv->dsp_clks[i]);
20230+		if (ret < 0) {
20231+			dev_err(priv->dev, "Failed to enable clk %s\n",
20232+				imx8_dsp_clks_names[i]);
20233+			goto err_dsp_clks;
20234+		}
20235+	}
20236+
20237+	for (j = 0; j < IMX8_DAI_CLK_NUM; j++) {
20238+		ret = clk_prepare_enable(priv->dai_clks[j]);
20239+		if (ret < 0) {
20240+			dev_err(priv->dev, "Failed to enable clk %s\n",
20241+				imx8_dai_clks_names[j]);
20242+			goto err_dai_clks;
20243+		}
20244+	}
20245+
20246+	return 0;
20247+
20248+err_dai_clks:
20249+	while (--j >= 0)
20250+		clk_disable_unprepare(priv->dai_clks[j]);
20251+
20252+err_dsp_clks:
20253+	while (--i >= 0)
20254+		clk_disable_unprepare(priv->dsp_clks[i]);
20255+
20256+	return ret;
20257+}
20258+
20259+static void imx8_disable_clocks(struct snd_sof_dev *sdev)
20260+{
20261+	int i;
20262+	struct imx8_priv *priv = (struct imx8_priv *)sdev->pdata->hw_pdata;
20263+
20264+	for (i = 0; i < IMX8_DSP_CLK_NUM; i++)
20265+		clk_disable_unprepare(priv->dsp_clks[i]);
20266+
20267+	for (i = 0; i < IMX8_DAI_CLK_NUM; i++)
20268+		clk_disable_unprepare(priv->dai_clks[i]);
20269+}
20270+
20271 static void imx8_get_reply(struct snd_sof_dev *sdev)
20272 {
20273 	struct snd_sof_ipc_msg *msg = sdev->msg;
20274@@ -333,6 +418,9 @@ static int imx8_probe(struct snd_sof_dev *sdev)
20275 	/* set default mailbox offset for FW ready message */
20276 	sdev->dsp_box.offset = MBOX_OFFSET;
20277
20278+	imx8_init_clocks(sdev);
20279+	imx8_prepare_clocks(sdev);
20280+
20281 	return 0;
20282
20283 exit_pdev_unregister:
20284@@ -367,20 +455,90 @@ static int imx8_get_bar_index(struct snd_sof_dev *sdev, u32 type)
20285 	return type;
20286 }
20287
20288-static void imx8_ipc_msg_data(struct snd_sof_dev *sdev,
20289-			      struct snd_pcm_substream *substream,
20290-			      void *p, size_t sz)
20291+int imx8_suspend(struct snd_sof_dev *sdev)
20292 {
20293-	sof_mailbox_read(sdev, sdev->dsp_box.offset, p, sz);
20294+	int i;
20295+	struct imx8_priv *priv = (struct imx8_priv *)sdev->pdata->hw_pdata;
20296+
20297+	for (i = 0; i < DSP_MU_CHAN_NUM; i++)
20298+		imx_dsp_free_channel(priv->dsp_ipc, i);
20299+
20300+	imx8_disable_clocks(priv->sdev);
20301+
20302+	return 0;
20303 }
20304
20305-static int imx8_ipc_pcm_params(struct snd_sof_dev *sdev,
20306-			       struct snd_pcm_substream *substream,
20307-			       const struct sof_ipc_pcm_params_reply *reply)
20308+int imx8_resume(struct snd_sof_dev *sdev)
20309 {
20310+	struct imx8_priv *priv = (struct imx8_priv *)sdev->pdata->hw_pdata;
20311+	int i;
20312+
20313+	imx8_prepare_clocks(sdev);
20314+
20315+	for (i = 0; i < DSP_MU_CHAN_NUM; i++)
20316+		imx_dsp_request_channel(priv->dsp_ipc, i);
20317+
20318 	return 0;
20319 }
20320
20321+int imx8_dsp_runtime_resume(struct snd_sof_dev *sdev)
20322+{
20323+	const struct sof_dsp_power_state target_dsp_state = {
20324+		.state = SOF_DSP_PM_D0,
20325+		.substate = 0,
20326+	};
20327+
20328+	imx8_resume(sdev);
20329+
20330+	return snd_sof_dsp_set_power_state(sdev, &target_dsp_state);
20331+}
20332+
20333+int imx8_dsp_runtime_suspend(struct snd_sof_dev *sdev)
20334+{
20335+	const struct sof_dsp_power_state target_dsp_state = {
20336+		.state = SOF_DSP_PM_D3,
20337+		.substate = 0,
20338+	};
20339+
20340+	imx8_suspend(sdev);
20341+
20342+	return snd_sof_dsp_set_power_state(sdev, &target_dsp_state);
20343+}
20344+
20345+
20346+int imx8_dsp_suspend(struct snd_sof_dev *sdev, unsigned int target_state)
20347+{
20348+	const struct sof_dsp_power_state target_dsp_state = {
20349+		.state = target_state,
20350+		.substate = 0,
20351+	};
20352+
20353+	if (!pm_runtime_suspended(sdev->dev))
20354+		imx8_suspend(sdev);
20355+
20356+	return snd_sof_dsp_set_power_state(sdev, &target_dsp_state);
20357+}
20358+
20359+int imx8_dsp_resume(struct snd_sof_dev *sdev)
20360+{
20361+	const struct sof_dsp_power_state target_dsp_state = {
20362+		.state = SOF_DSP_PM_D0,
20363+		.substate = 0,
20364+	};
20365+
20366+	imx8_resume(sdev);
20367+
20368+	if (pm_runtime_suspended(sdev->dev)) {
20369+		pm_runtime_disable(sdev->dev);
20370+		pm_runtime_set_active(sdev->dev);
20371+		pm_runtime_mark_last_busy(sdev->dev);
20372+		pm_runtime_enable(sdev->dev);
20373+		pm_runtime_idle(sdev->dev);
20374+	}
20375+
20376+	return snd_sof_dsp_set_power_state(sdev, &target_dsp_state);
20377+}
20378+
20379 static struct snd_soc_dai_driver imx8_dai[] = {
20380 {
20381 	.name = "esai0",
20382@@ -406,6 +564,14 @@ static struct snd_soc_dai_driver imx8_dai[] = {
20383 },
20384 };
20385
20386+int imx8_dsp_set_power_state(struct snd_sof_dev *sdev,
20387+			     const struct sof_dsp_power_state *target_state)
20388+{
20389+	sdev->dsp_power_state = *target_state;
20390+
20391+	return 0;
20392+}
20393+
20394 /* i.MX8 ops */
20395 struct snd_sof_dsp_ops sof_imx8_ops = {
20396 	/* probe and remove */
20397@@ -427,8 +593,8 @@ struct snd_sof_dsp_ops sof_imx8_ops = {
20398 	.get_mailbox_offset	= imx8_get_mailbox_offset,
20399 	.get_window_offset	= imx8_get_window_offset,
20400
20401-	.ipc_msg_data	= imx8_ipc_msg_data,
20402-	.ipc_pcm_params	= imx8_ipc_pcm_params,
20403+	.ipc_msg_data	= sof_ipc_msg_data,
20404+	.ipc_pcm_params	= sof_ipc_pcm_params,
20405
20406 	/* module loading */
20407 	.load_module	= snd_sof_parse_module_memcpy,
20408@@ -439,6 +605,10 @@ struct snd_sof_dsp_ops sof_imx8_ops = {
20409 	/* Debug information */
20410 	.dbg_dump = imx8_dump,
20411
20412+	/* stream callbacks */
20413+	.pcm_open = sof_stream_pcm_open,
20414+	.pcm_close = sof_stream_pcm_close,
20415+
20416 	/* Firmware ops */
20417 	.arch_ops = &sof_xtensa_arch_ops,
20418
20419@@ -452,6 +622,21 @@ struct snd_sof_dsp_ops sof_imx8_ops = {
20420 			SNDRV_PCM_INFO_INTERLEAVED |
20421 			SNDRV_PCM_INFO_PAUSE |
20422 			SNDRV_PCM_INFO_NO_PERIOD_WAKEUP,
20423+
20424+	/* PM */
20425+	.runtime_suspend	= imx8_dsp_runtime_suspend,
20426+	.runtime_resume		= imx8_dsp_runtime_resume,
20427+
20428+	.suspend	= imx8_dsp_suspend,
20429+	.resume		= imx8_dsp_resume,
20430+
20431+	.set_power_state	= imx8_dsp_set_power_state,
20432+	/* ALSA HW info flags */
20433+	.hw_info =	SNDRV_PCM_INFO_MMAP |
20434+			SNDRV_PCM_INFO_MMAP_VALID |
20435+			SNDRV_PCM_INFO_INTERLEAVED |
20436+			SNDRV_PCM_INFO_PAUSE |
20437+			SNDRV_PCM_INFO_NO_PERIOD_WAKEUP
20438 };
20439 EXPORT_SYMBOL(sof_imx8_ops);
20440
20441@@ -476,8 +661,8 @@ struct snd_sof_dsp_ops sof_imx8x_ops = {
20442 	.get_mailbox_offset	= imx8_get_mailbox_offset,
20443 	.get_window_offset	= imx8_get_window_offset,
20444
20445-	.ipc_msg_data	= imx8_ipc_msg_data,
20446-	.ipc_pcm_params	= imx8_ipc_pcm_params,
20447+	.ipc_msg_data	= sof_ipc_msg_data,
20448+	.ipc_pcm_params	= sof_ipc_pcm_params,
20449
20450 	/* module loading */
20451 	.load_module	= snd_sof_parse_module_memcpy,
20452@@ -488,6 +673,10 @@ struct snd_sof_dsp_ops sof_imx8x_ops = {
20453 	/* Debug information */
20454 	.dbg_dump = imx8_dump,
20455
20456+	/* stream callbacks */
20457+	.pcm_open = sof_stream_pcm_open,
20458+	.pcm_close = sof_stream_pcm_close,
20459+
20460 	/* Firmware ops */
20461 	.arch_ops = &sof_xtensa_arch_ops,
20462
20463@@ -495,6 +684,15 @@ struct snd_sof_dsp_ops sof_imx8x_ops = {
20464 	.drv = imx8_dai,
20465 	.num_drv = ARRAY_SIZE(imx8_dai),
20466
20467+	/* PM */
20468+	.runtime_suspend	= imx8_dsp_runtime_suspend,
20469+	.runtime_resume		= imx8_dsp_runtime_resume,
20470+
20471+	.suspend	= imx8_dsp_suspend,
20472+	.resume		= imx8_dsp_resume,
20473+
20474+	.set_power_state	= imx8_dsp_set_power_state,
20475+
20476 	/* ALSA HW info flags */
20477 	.hw_info =	SNDRV_PCM_INFO_MMAP |
20478 			SNDRV_PCM_INFO_MMAP_VALID |
20479diff --git a/sound/soc/sof/ipc-stream.c b/sound/soc/sof/ipc-stream.c
20480new file mode 100644
20481index 000000000..6e5e983e9
20482--- /dev/null
20483+++ b/sound/soc/sof/ipc-stream.c
20484@@ -0,0 +1,104 @@
20485+// SPDX-License-Identifier: (GPL-2.0-only OR BSD-3-Clause)
20486+//
20487+// This file is provided under a dual BSD/GPLv2 license.  When using or
20488+// redistributing this file, you may do so under either license.
20489+//
20490+// Copyright(c) 2019 Intel Corporation. All rights reserved.
20491+//
20492+// Authors: Guennadi Liakhovetski <guennadi.liakhovetski@linux.intel.com>
20493+
20494+/* Intel-specific SOF IPC code */
20495+
20496+#include <linux/device.h>
20497+#include <linux/export.h>
20498+#include <linux/module.h>
20499+#include <linux/types.h>
20500+
20501+#include <sound/pcm.h>
20502+#include <sound/sof/stream.h>
20503+
20504+#include "ops.h"
20505+#include "sof-audio.h"
20506+#include "sof-priv.h"
20507+
20508+struct sof_pcm_stream {
20509+	size_t posn_offset;
20510+};
20511+
20512+/* Mailbox-based Intel IPC implementation */
20513+void sof_ipc_msg_data(struct snd_sof_dev *sdev,
20514+		      struct snd_sof_pcm_stream *sps,
20515+		      void *p, size_t sz)
20516+{
20517+	if (!sps || !sdev->stream_box.size) {
20518+		sof_mailbox_read(sdev, sdev->dsp_box.offset, p, sz);
20519+	} else {
20520+		struct snd_pcm_substream *substream = sps->substream;
20521+		struct snd_compr_stream *cstream = sps->cstream;
20522+		struct sof_pcm_stream *pstream;
20523+		struct sof_compr_stream *sstream;
20524+		size_t posn_offset;
20525+
20526+		if (substream) {
20527+			pstream = substream->runtime->private_data;
20528+			posn_offset = pstream->posn_offset;
20529+		} else {
20530+			sstream = cstream->runtime->private_data;
20531+			posn_offset = sstream->posn_offset;
20532+		}
20533+		/* The stream might already be closed */
20534+		if (pstream || sstream)
20535+			sof_mailbox_read(sdev, posn_offset, p, sz);
20536+	}
20537+}
20538+EXPORT_SYMBOL(sof_ipc_msg_data);
20539+
20540+int sof_ipc_pcm_params(struct snd_sof_dev *sdev,
20541+		       struct snd_pcm_substream *substream,
20542+		       const struct sof_ipc_pcm_params_reply *reply)
20543+{
20544+	struct sof_pcm_stream *stream = substream->runtime->private_data;
20545+	size_t posn_offset = reply->posn_offset;
20546+
20547+	/* check if offset is overflow or it is not aligned */
20548+	if (posn_offset > sdev->stream_box.size ||
20549+	    posn_offset % sizeof(struct sof_ipc_stream_posn) != 0)
20550+		return -EINVAL;
20551+
20552+	stream->posn_offset = sdev->stream_box.offset + posn_offset;
20553+
20554+	dev_dbg(sdev->dev, "pcm: stream dir %d, posn mailbox offset is %zu",
20555+		substream->stream, stream->posn_offset);
20556+
20557+	return 0;
20558+}
20559+EXPORT_SYMBOL(sof_ipc_pcm_params);
20560+
20561+int sof_stream_pcm_open(struct snd_sof_dev *sdev,
20562+			struct snd_pcm_substream *substream)
20563+{
20564+	struct sof_pcm_stream *stream = kmalloc(sizeof(*stream), GFP_KERNEL);
20565+
20566+	if (!stream)
20567+		return -ENOMEM;
20568+
20569+	/* binding pcm substream to hda stream */
20570+	substream->runtime->private_data = stream;
20571+
20572+	return 0;
20573+}
20574+EXPORT_SYMBOL(sof_stream_pcm_open);
20575+
20576+int sof_stream_pcm_close(struct snd_sof_dev *sdev,
20577+		    struct snd_pcm_substream *substream)
20578+{
20579+	struct sof_pcm_stream *stream = substream->runtime->private_data;
20580+
20581+	substream->runtime->private_data = NULL;
20582+	kfree(stream);
20583+
20584+	return 0;
20585+}
20586+EXPORT_SYMBOL(sof_stream_pcm_close);
20587+
20588+MODULE_LICENSE("Dual BSD/GPL");
20589diff --git a/sound/soc/sof/ipc.c b/sound/soc/sof/ipc.c
20590index fd2b96ae4..e63fb9e88 100644
20591--- a/sound/soc/sof/ipc.c
20592+++ b/sound/soc/sof/ipc.c
20593@@ -453,15 +453,17 @@ static void ipc_period_elapsed(struct snd_sof_dev *sdev, u32 msg_id)
20594 	}
20595
20596 	stream = &spcm->stream[direction];
20597-	snd_sof_ipc_msg_data(sdev, stream->substream, &posn, sizeof(posn));
20598+	snd_sof_ipc_msg_data(sdev, stream, &posn, sizeof(posn));
20599
20600 	dev_vdbg(sdev->dev, "posn : host 0x%llx dai 0x%llx wall 0x%llx\n",
20601 		 posn.host_posn, posn.dai_posn, posn.wallclock);
20602
20603 	memcpy(&stream->posn, &posn, sizeof(posn));
20604
20605-	/* only inform ALSA for period_wakeup mode */
20606-	if (!stream->substream->runtime->no_period_wakeup)
20607+	if (spcm->pcm.compress)
20608+		snd_sof_compr_fragment_elapsed(stream->cstream);
20609+	else if (!stream->substream->runtime->no_period_wakeup)
20610+		/* only inform ALSA for period_wakeup mode */
20611 		snd_sof_pcm_period_elapsed(stream->substream);
20612 }
20613
20614@@ -482,7 +484,7 @@ static void ipc_xrun(struct snd_sof_dev *sdev, u32 msg_id)
20615 	}
20616
20617 	stream = &spcm->stream[direction];
20618-	snd_sof_ipc_msg_data(sdev, stream->substream, &posn, sizeof(posn));
20619+	snd_sof_ipc_msg_data(sdev, stream, &posn, sizeof(posn));
20620
20621 	dev_dbg(sdev->dev,  "posn XRUN: host %llx comp %d size %d\n",
20622 		posn.host_posn, posn.xrun_comp_id, posn.xrun_size);
20623diff --git a/sound/soc/sof/ops.h b/sound/soc/sof/ops.h
20624index b21632f55..2ce501a94 100644
20625--- a/sound/soc/sof/ops.h
20626+++ b/sound/soc/sof/ops.h
20627@@ -367,10 +367,10 @@ snd_sof_pcm_platform_trigger(struct snd_sof_dev *sdev,
20628
20629 /* host DSP message data */
20630 static inline void snd_sof_ipc_msg_data(struct snd_sof_dev *sdev,
20631-					struct snd_pcm_substream *substream,
20632+					struct snd_sof_pcm_stream *sps,
20633 					void *p, size_t sz)
20634 {
20635-	sof_ops(sdev)->ipc_msg_data(sdev, substream, p, sz);
20636+	sof_ops(sdev)->ipc_msg_data(sdev, sps, p, sz);
20637 }
20638
20639 /* host configure DSP HW parameters */
20640diff --git a/sound/soc/sof/pcm.c b/sound/soc/sof/pcm.c
20641index cbac6f17c..6a7444056 100644
20642--- a/sound/soc/sof/pcm.c
20643+++ b/sound/soc/sof/pcm.c
20644@@ -17,7 +17,7 @@
20645 #include "sof-audio.h"
20646 #include "ops.h"
20647 #if IS_ENABLED(CONFIG_SND_SOC_SOF_DEBUG_PROBES)
20648-#include "compress.h"
20649+#include "probe_compress.h"
20650 #endif
20651
20652 /* Create DMA buffer page table for DSP */
20653@@ -57,7 +57,7 @@ static int sof_pcm_dsp_params(struct snd_sof_pcm *spcm, struct snd_pcm_substream
20654 /*
20655  * sof pcm period elapse work
20656  */
20657-void snd_sof_pcm_period_elapsed_work(struct work_struct *work)
20658+static void snd_sof_pcm_period_elapsed_work(struct work_struct *work)
20659 {
20660 	struct snd_sof_pcm_stream *sps =
20661 		container_of(work, struct snd_sof_pcm_stream,
20662@@ -66,6 +66,11 @@ void snd_sof_pcm_period_elapsed_work(struct work_struct *work)
20663 	snd_pcm_period_elapsed(sps->substream);
20664 }
20665
20666+void snd_sof_pcm_init_elapsed_work(struct work_struct *work)
20667+{
20668+	 INIT_WORK(work, snd_sof_pcm_period_elapsed_work);
20669+}
20670+
20671 /*
20672  * sof pcm period elapse, this could be called at irq thread context.
20673  */
20674@@ -789,7 +794,11 @@ void snd_sof_new_platform_drv(struct snd_sof_dev *sdev)
20675 	struct snd_sof_pdata *plat_data = sdev->pdata;
20676 	const char *drv_name;
20677
20678-	drv_name = plat_data->machine->drv_name;
20679+
20680+	if (plat_data->machine)
20681+		drv_name = plat_data->machine->drv_name;
20682+	else
20683+		drv_name = plat_data->machine_drv_name;
20684
20685 	pd->name = "sof-audio-component";
20686 	pd->probe = sof_pcm_probe;
20687diff --git a/sound/soc/sof/sof-audio.c b/sound/soc/sof/sof-audio.c
20688index afe7e503b..18bf70721 100644
20689--- a/sound/soc/sof/sof-audio.c
20690+++ b/sound/soc/sof/sof-audio.c
20691@@ -451,7 +451,7 @@ int sof_machine_check(struct snd_sof_dev *sdev)
20692
20693 	/* find machine */
20694 	snd_sof_machine_select(sdev);
20695-	if (sof_pdata->machine) {
20696+	if (sof_pdata->machine || sof_pdata->machine_drv_name) {
20697 		snd_sof_set_mach_params(sof_pdata->machine, sdev->dev);
20698 		return 0;
20699 	}
20700diff --git a/sound/soc/sof/sof-audio.h b/sound/soc/sof/sof-audio.h
20701index 9f645a2e5..b2482a4df 100644
20702--- a/sound/soc/sof/sof-audio.h
20703+++ b/sound/soc/sof/sof-audio.h
20704@@ -34,6 +34,7 @@ struct snd_sof_pcm_stream {
20705 	struct snd_dma_buffer page_table;
20706 	struct sof_ipc_stream_posn posn;
20707 	struct snd_pcm_substream *substream;
20708+	struct snd_compr_stream *cstream;
20709 	struct work_struct period_elapsed_work;
20710 	bool d0i3_compatible; /* DSP can be in D0I3 when this pcm is opened */
20711 	/*
20712@@ -201,7 +202,15 @@ struct snd_sof_pcm *snd_sof_find_spcm_pcm_id(struct snd_soc_component *scomp,
20713 const struct sof_ipc_pipe_new *snd_sof_pipeline_find(struct snd_sof_dev *sdev,
20714 						     int pipeline_id);
20715 void snd_sof_pcm_period_elapsed(struct snd_pcm_substream *substream);
20716-void snd_sof_pcm_period_elapsed_work(struct work_struct *work);
20717+void snd_sof_pcm_init_elapsed_work(struct work_struct *work);
20718+
20719+#if defined(CONFIG_SND_SOC_SOF_COMPRESS)
20720+void snd_sof_compr_fragment_elapsed(struct snd_compr_stream *cstream);
20721+void snd_sof_compr_init_elapsed_work(struct work_struct *work);
20722+#else
20723+static inline void snd_sof_compr_fragment_elapsed(struct snd_compr_stream *cstream) { }
20724+static inline void snd_sof_compr_init_elapsed_work(struct work_struct *work) { }
20725+#endif
20726
20727 /*
20728  * Mixer IPC
20729diff --git a/sound/soc/sof/sof-of-dev.c b/sound/soc/sof/sof-of-dev.c
20730index 85ff0db88..2025bed50 100644
20731--- a/sound/soc/sof/sof-of-dev.c
20732+++ b/sound/soc/sof/sof-of-dev.c
20733@@ -15,6 +15,7 @@
20734 extern struct snd_sof_dsp_ops sof_imx8_ops;
20735 extern struct snd_sof_dsp_ops sof_imx8x_ops;
20736 extern struct snd_sof_dsp_ops sof_imx8m_ops;
20737+extern struct snd_sof_dsp_ops sof_imx8ulp_ops;
20738
20739 /* platform specific devices */
20740 #if IS_ENABLED(CONFIG_SND_SOC_SOF_IMX8)
20741@@ -45,6 +46,16 @@ static struct sof_dev_desc sof_of_imx8mp_desc = {
20742 };
20743 #endif
20744
20745+#if IS_ENABLED(CONFIG_SND_SOC_SOF_IMX8ULP)
20746+static struct sof_dev_desc sof_of_imx8ulp_desc = {
20747+	.default_fw_path = "imx/sof",
20748+	.default_tplg_path = "imx/sof-tplg",
20749+	.default_fw_filename = "sof-imx8ulp.ri",
20750+	.nocodec_tplg_filename = "sof-imx8ulp-nocodec.tplg",
20751+	.ops = &sof_imx8ulp_ops,
20752+};
20753+#endif
20754+
20755 static const struct dev_pm_ops sof_of_pm = {
20756 	.prepare = snd_sof_prepare,
20757 	.complete = snd_sof_complete,
20758@@ -58,11 +69,31 @@ static void sof_of_probe_complete(struct device *dev)
20759 	/* allow runtime_pm */
20760 	pm_runtime_set_autosuspend_delay(dev, SND_SOF_SUSPEND_DELAY_MS);
20761 	pm_runtime_use_autosuspend(dev);
20762+	pm_runtime_mark_last_busy(dev);
20763 	pm_runtime_set_active(dev);
20764 	pm_runtime_enable(dev);
20765+}
20766
20767-	pm_runtime_mark_last_busy(dev);
20768-	pm_runtime_put_autosuspend(dev);
20769+int sof_of_parse(struct platform_device *pdev)
20770+{
20771+	struct snd_sof_pdata *sof_pdata = platform_get_drvdata(pdev);
20772+	struct device_node *np = pdev->dev.of_node;
20773+	int ret;
20774+
20775+	/* firmware-name is optional in DT */
20776+	of_property_read_string(np, "firmware-name", &sof_pdata->fw_filename);
20777+
20778+	ret = of_property_read_string(np, "tplg-name",
20779+				      &sof_pdata->tplg_filename);
20780+	if (ret < 0)
20781+		return ret;
20782+
20783+	ret = of_property_read_string(np, "machine-drv-name",
20784+				      &sof_pdata->machine_drv_name);
20785+	if (ret < 0)
20786+		return ret;
20787+
20788+	return 0;
20789 }
20790
20791 static int sof_of_probe(struct platform_device *pdev)
20792@@ -79,6 +110,8 @@ static int sof_of_probe(struct platform_device *pdev)
20793 	if (!sof_pdata)
20794 		return -ENOMEM;
20795
20796+	platform_set_drvdata(pdev, sof_pdata);
20797+
20798 	desc = device_get_match_data(dev);
20799 	if (!desc)
20800 		return -ENODEV;
20801@@ -98,6 +131,16 @@ static int sof_of_probe(struct platform_device *pdev)
20802 	sof_pdata->fw_filename_prefix = sof_pdata->desc->default_fw_path;
20803 	sof_pdata->tplg_filename_prefix = sof_pdata->desc->default_tplg_path;
20804
20805+	ret = sof_of_parse(pdev);
20806+	if (ret < 0) {
20807+		dev_err(dev, "Could not parse SOF OF DSP node\n");
20808+		return ret;
20809+	}
20810+
20811+	/* use default fw filename if none provided in DT */
20812+	if (!sof_pdata->fw_filename)
20813+		sof_pdata->fw_filename = desc->default_fw_filename;
20814+
20815 #if IS_ENABLED(CONFIG_SND_SOC_SOF_PROBE_WORK_QUEUE)
20816 	/* set callback to enable runtime_pm */
20817 	sof_pdata->sof_probe_complete = sof_of_probe_complete;
20818@@ -119,6 +162,8 @@ static int sof_of_probe(struct platform_device *pdev)
20819 static int sof_of_remove(struct platform_device *pdev)
20820 {
20821 	pm_runtime_disable(&pdev->dev);
20822+	pm_runtime_set_suspended(&pdev->dev);
20823+	pm_runtime_put_noidle(&pdev->dev);
20824
20825 	/* call sof helper for DSP hardware remove */
20826 	snd_sof_device_remove(&pdev->dev);
20827@@ -133,6 +178,9 @@ static const struct of_device_id sof_of_ids[] = {
20828 #endif
20829 #if IS_ENABLED(CONFIG_SND_SOC_SOF_IMX8M)
20830 	{ .compatible = "fsl,imx8mp-dsp", .data = &sof_of_imx8mp_desc},
20831+#endif
20832+#if IS_ENABLED(CONFIG_SND_SOC_SOF_IMX8ULP)
20833+	{ .compatible = "fsl,imx8ulp-dsp", .data = &sof_of_imx8ulp_desc},
20834 #endif
20835 	{ }
20836 };
20837diff --git a/sound/soc/sof/sof-priv.h b/sound/soc/sof/sof-priv.h
20838index 0aed2a7ab..86a7ab3aa 100644
20839--- a/sound/soc/sof/sof-priv.h
20840+++ b/sound/soc/sof/sof-priv.h
20841@@ -19,6 +19,8 @@
20842 #include <sound/sof/trace.h>
20843 #include <uapi/sound/sof/fw.h>
20844
20845+struct snd_sof_pcm_stream;
20846+
20847 /* debug flags */
20848 #define SOF_DBG_ENABLE_TRACE	BIT(0)
20849 #define SOF_DBG_REGS		BIT(1)
20850@@ -79,6 +81,12 @@ enum sof_system_suspend_state {
20851 	SOF_SUSPEND_S3,
20852 };
20853
20854+struct sof_compr_stream {
20855+	unsigned int copied_total;
20856+	unsigned int sample_rate;
20857+	size_t posn_offset;
20858+};
20859+
20860 struct snd_sof_dev;
20861 struct snd_sof_ipc_msg;
20862 struct snd_sof_ipc;
20863@@ -196,7 +204,7 @@ struct snd_sof_dsp_ops {
20864
20865 	/* host read DSP stream data */
20866 	void (*ipc_msg_data)(struct snd_sof_dev *sdev,
20867-			     struct snd_pcm_substream *substream,
20868+			     struct snd_sof_pcm_stream *sps,
20869 			     void *p, size_t sz); /* mandatory */
20870
20871 	/* host configure DSP HW parameters */
20872@@ -564,17 +572,17 @@ void sof_block_read(struct snd_sof_dev *sdev, u32 bar, u32 offset, void *dest,
20873
20874 int sof_fw_ready(struct snd_sof_dev *sdev, u32 msg_id);
20875
20876-void intel_ipc_msg_data(struct snd_sof_dev *sdev,
20877-			struct snd_pcm_substream *substream,
20878-			void *p, size_t sz);
20879-int intel_ipc_pcm_params(struct snd_sof_dev *sdev,
20880-			 struct snd_pcm_substream *substream,
20881-			 const struct sof_ipc_pcm_params_reply *reply);
20882-
20883-int intel_pcm_open(struct snd_sof_dev *sdev,
20884-		   struct snd_pcm_substream *substream);
20885-int intel_pcm_close(struct snd_sof_dev *sdev,
20886-		    struct snd_pcm_substream *substream);
20887+void sof_ipc_msg_data(struct snd_sof_dev *sdev,
20888+		      struct snd_sof_pcm_stream *sps,
20889+		      void *p, size_t sz);
20890+int sof_ipc_pcm_params(struct snd_sof_dev *sdev,
20891+		       struct snd_pcm_substream *substream,
20892+		       const struct sof_ipc_pcm_params_reply *reply);
20893+
20894+int sof_stream_pcm_open(struct snd_sof_dev *sdev,
20895+			struct snd_pcm_substream *substream);
20896+int sof_stream_pcm_close(struct snd_sof_dev *sdev,
20897+			 struct snd_pcm_substream *substream);
20898
20899 int sof_machine_check(struct snd_sof_dev *sdev);
20900
20901diff --git a/sound/soc/sof/topology.c b/sound/soc/sof/topology.c
20902index 69313fbdb..08b2efca4 100644
20903--- a/sound/soc/sof/topology.c
20904+++ b/sound/soc/sof/topology.c
20905@@ -2667,8 +2667,10 @@ static int sof_dai_load(struct snd_soc_component *scomp, int index,
20906
20907 	for_each_pcm_streams(stream) {
20908 		spcm->stream[stream].comp_id = COMP_ID_UNASSIGNED;
20909-		INIT_WORK(&spcm->stream[stream].period_elapsed_work,
20910-			  snd_sof_pcm_period_elapsed_work);
20911+		if (pcm->compress)
20912+			snd_sof_compr_init_elapsed_work(&spcm->stream[stream].period_elapsed_work);
20913+		else
20914+			snd_sof_pcm_init_elapsed_work(&spcm->stream[stream].period_elapsed_work);
20915 	}
20916
20917 	spcm->pcm = *pcm;
20918