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, ®); 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, ®); 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), ®); 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), ®); 1575+ *(reg24) = reg; 1576+ reg24++; 1577+ regmap_read(asrc->regmap, REG_ASRDO(index), ®); 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), ®); 1588+ *(reg24) = reg; 1589+ reg24++; 1590+ regmap_read(asrc->regmap, REG_ASRDO(index), ®); 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), ®); 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