summaryrefslogtreecommitdiffstats
path: root/sound
diff options
context:
space:
mode:
Diffstat (limited to 'sound')
-rw-r--r--sound/pci/hda/patch_realtek.c42
-rw-r--r--sound/soc/codecs/Kconfig5
-rw-r--r--sound/soc/codecs/Makefile2
-rw-r--r--sound/soc/codecs/ad193x.c76
-rw-r--r--sound/soc/codecs/ad193x.h8
-rw-r--r--sound/soc/codecs/adau1977.c12
-rw-r--r--sound/soc/codecs/cros_ec_codec.c2
-rw-r--r--sound/soc/codecs/cs35l36.c1957
-rw-r--r--sound/soc/codecs/cs35l36.h446
-rw-r--r--sound/soc/codecs/da7219.c116
-rw-r--r--sound/soc/codecs/da7219.h1
-rw-r--r--sound/soc/codecs/hdac_hdmi.c87
-rw-r--r--sound/soc/codecs/jz4725b.c12
-rw-r--r--sound/soc/codecs/max9860.c3
-rw-r--r--sound/soc/codecs/msm8916-wcd-analog.c3
-rw-r--r--sound/soc/codecs/msm8916-wcd-digital.c13
-rw-r--r--sound/soc/codecs/pcm186x.c8
-rw-r--r--sound/soc/codecs/pcm3060.c35
-rw-r--r--sound/soc/codecs/pcm3060.h5
-rw-r--r--sound/soc/codecs/pcm512x.c5
-rw-r--r--sound/soc/codecs/tlv320aic31xx.c16
-rw-r--r--sound/soc/codecs/tlv320aic32x4.c1
-rw-r--r--sound/soc/codecs/tlv320aic3x.c25
-rw-r--r--sound/soc/codecs/wm8741.c22
-rw-r--r--sound/soc/codecs/wm8770.c18
-rw-r--r--sound/soc/codecs/wm8962.c9
-rw-r--r--sound/soc/codecs/wm8995.c29
-rw-r--r--sound/soc/codecs/wm8996.c9
-rw-r--r--sound/soc/codecs/wm_adsp.c498
-rw-r--r--sound/soc/codecs/wm_adsp.h4
-rw-r--r--sound/soc/fsl/fsl_esai.c7
-rw-r--r--sound/soc/fsl/fsl_spdif.c10
-rw-r--r--sound/soc/fsl/fsl_spdif.h2
-rw-r--r--sound/soc/fsl/fsl_ssi.c6
-rw-r--r--sound/soc/fsl/imx-sgtl5000.c1
-rw-r--r--sound/soc/generic/simple-card.c21
-rw-r--r--sound/soc/intel/boards/Kconfig1
-rw-r--r--sound/soc/intel/boards/bxt_da7219_max98357a.c101
-rw-r--r--sound/soc/intel/boards/bytcr_rt5651.c74
-rw-r--r--sound/soc/intel/boards/kbl_da7219_max98927.c203
-rw-r--r--sound/soc/intel/common/soc-acpi-intel-bxt-match.c25
-rw-r--r--sound/soc/intel/common/soc-acpi-intel-byt-match.c60
-rw-r--r--sound/soc/intel/common/soc-acpi-intel-cht-match.c70
-rw-r--r--sound/soc/intel/common/soc-acpi-intel-cnl-match.c5
-rw-r--r--sound/soc/intel/common/soc-acpi-intel-glk-match.c10
-rw-r--r--sound/soc/intel/common/soc-acpi-intel-hda-match.c2
-rw-r--r--sound/soc/intel/common/soc-acpi-intel-hsw-bdw-match.c20
-rw-r--r--sound/soc/intel/common/soc-acpi-intel-icl-match.c5
-rw-r--r--sound/soc/intel/common/soc-acpi-intel-kbl-match.c19
-rw-r--r--sound/soc/intel/skylake/skl-pcm.c1
-rw-r--r--sound/soc/mediatek/common/mtk-btcvsd.c4
-rw-r--r--sound/soc/mediatek/mt8183/mt8183-afe-pcm.c2
-rw-r--r--sound/soc/mediatek/mt8183/mt8183-dai-i2s.c4
-rw-r--r--sound/soc/qcom/Kconfig3
-rw-r--r--sound/soc/qcom/apq8016_sbc.c21
-rw-r--r--sound/soc/qcom/common.c10
-rw-r--r--sound/soc/samsung/dma.h3
-rw-r--r--sound/soc/samsung/dmaengine.c16
-rw-r--r--sound/soc/samsung/i2s.c725
-rw-r--r--sound/soc/samsung/odroid.c206
-rw-r--r--sound/soc/samsung/pcm.c2
-rw-r--r--sound/soc/samsung/s3c2412-i2s.c2
-rw-r--r--sound/soc/samsung/s3c24xx-i2s.c2
-rw-r--r--sound/soc/samsung/spdif.c2
-rw-r--r--sound/soc/sh/fsi.c2
-rw-r--r--sound/soc/sh/rcar/gen.c24
-rw-r--r--sound/soc/sh/rcar/rsnd.h27
-rw-r--r--sound/soc/sh/rcar/ssiu.c24
-rw-r--r--sound/soc/soc-core.c6
-rw-r--r--sound/soc/soc-dapm.c5
-rw-r--r--sound/soc/soc-generic-dmaengine-pcm.c13
-rw-r--r--sound/soc/soc-topology.c8
-rw-r--r--sound/soc/stm/stm32_i2s.c136
-rw-r--r--sound/soc/stm/stm32_sai.c11
-rw-r--r--sound/soc/stm/stm32_sai_sub.c8
-rw-r--r--sound/soc/sunxi/sun50i-codec-analog.c4
76 files changed, 4254 insertions, 1128 deletions
diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c
index 3bd1286eb5a8..c8413d44973c 100644
--- a/sound/pci/hda/patch_realtek.c
+++ b/sound/pci/hda/patch_realtek.c
@@ -1864,6 +1864,8 @@ enum {
ALC887_FIXUP_BASS_CHMAP,
ALC1220_FIXUP_GB_DUAL_CODECS,
ALC1220_FIXUP_CLEVO_P950,
+ ALC1220_FIXUP_SYSTEM76_ORYP5,
+ ALC1220_FIXUP_SYSTEM76_ORYP5_PINS,
};
static void alc889_fixup_coef(struct hda_codec *codec,
@@ -2065,6 +2067,17 @@ static void alc1220_fixup_clevo_p950(struct hda_codec *codec,
snd_hda_override_conn_list(codec, 0x1b, 1, conn1);
}
+static void alc_fixup_headset_mode_no_hp_mic(struct hda_codec *codec,
+ const struct hda_fixup *fix, int action);
+
+static void alc1220_fixup_system76_oryp5(struct hda_codec *codec,
+ const struct hda_fixup *fix,
+ int action)
+{
+ alc1220_fixup_clevo_p950(codec, fix, action);
+ alc_fixup_headset_mode_no_hp_mic(codec, fix, action);
+}
+
static const struct hda_fixup alc882_fixups[] = {
[ALC882_FIXUP_ABIT_AW9D_MAX] = {
.type = HDA_FIXUP_PINS,
@@ -2309,6 +2322,19 @@ static const struct hda_fixup alc882_fixups[] = {
.type = HDA_FIXUP_FUNC,
.v.func = alc1220_fixup_clevo_p950,
},
+ [ALC1220_FIXUP_SYSTEM76_ORYP5] = {
+ .type = HDA_FIXUP_FUNC,
+ .v.func = alc1220_fixup_system76_oryp5,
+ },
+ [ALC1220_FIXUP_SYSTEM76_ORYP5_PINS] = {
+ .type = HDA_FIXUP_PINS,
+ .v.pins = (const struct hda_pintbl[]) {
+ { 0x19, 0x01a1913c }, /* use as headset mic, without its own jack detect */
+ {}
+ },
+ .chained = true,
+ .chain_id = ALC1220_FIXUP_SYSTEM76_ORYP5,
+ },
};
static const struct snd_pci_quirk alc882_fixup_tbl[] = {
@@ -2385,6 +2411,8 @@ static const struct snd_pci_quirk alc882_fixup_tbl[] = {
SND_PCI_QUIRK(0x1558, 0x9501, "Clevo P950HR", ALC1220_FIXUP_CLEVO_P950),
SND_PCI_QUIRK(0x1558, 0x95e1, "Clevo P95xER", ALC1220_FIXUP_CLEVO_P950),
SND_PCI_QUIRK(0x1558, 0x95e2, "Clevo P950ER", ALC1220_FIXUP_CLEVO_P950),
+ SND_PCI_QUIRK(0x1558, 0x96e1, "System76 Oryx Pro (oryp5)", ALC1220_FIXUP_SYSTEM76_ORYP5_PINS),
+ SND_PCI_QUIRK(0x1558, 0x97e1, "System76 Oryx Pro (oryp5)", ALC1220_FIXUP_SYSTEM76_ORYP5_PINS),
SND_PCI_QUIRK_VENDOR(0x1558, "Clevo laptop", ALC882_FIXUP_EAPD),
SND_PCI_QUIRK(0x161f, 0x2054, "Medion laptop", ALC883_FIXUP_EAPD),
SND_PCI_QUIRK(0x17aa, 0x3a0d, "Lenovo Y530", ALC882_FIXUP_LENOVO_Y530),
@@ -5644,6 +5672,7 @@ enum {
ALC294_FIXUP_ASUS_SPK,
ALC225_FIXUP_HEADSET_JACK,
ALC293_FIXUP_SYSTEM76_MIC_NO_PRESENCE,
+ ALC285_FIXUP_LENOVO_PC_BEEP_IN_NOISE,
};
static const struct hda_fixup alc269_fixups[] = {
@@ -6599,6 +6628,17 @@ static const struct hda_fixup alc269_fixups[] = {
.chained = true,
.chain_id = ALC269_FIXUP_HEADSET_MODE_NO_HP_MIC
},
+ [ALC285_FIXUP_LENOVO_PC_BEEP_IN_NOISE] = {
+ .type = HDA_FIXUP_VERBS,
+ .v.verbs = (const struct hda_verb[]) {
+ /* Disable PCBEEP-IN passthrough */
+ { 0x20, AC_VERB_SET_COEF_INDEX, 0x36 },
+ { 0x20, AC_VERB_SET_PROC_COEF, 0x57d7 },
+ { }
+ },
+ .chained = true,
+ .chain_id = ALC285_FIXUP_LENOVO_HEADPHONE_NOISE
+ },
};
static const struct snd_pci_quirk alc269_fixup_tbl[] = {
@@ -7284,7 +7324,7 @@ static const struct snd_hda_pin_quirk alc269_pin_fixup_tbl[] = {
{0x12, 0x90a60130},
{0x19, 0x03a11020},
{0x21, 0x0321101f}),
- SND_HDA_PIN_QUIRK(0x10ec0285, 0x17aa, "Lenovo", ALC285_FIXUP_LENOVO_HEADPHONE_NOISE,
+ SND_HDA_PIN_QUIRK(0x10ec0285, 0x17aa, "Lenovo", ALC285_FIXUP_LENOVO_PC_BEEP_IN_NOISE,
{0x12, 0x90a60130},
{0x14, 0x90170110},
{0x19, 0x04a11040},
diff --git a/sound/soc/codecs/Kconfig b/sound/soc/codecs/Kconfig
index e6ce18c21b98..419114edfd57 100644
--- a/sound/soc/codecs/Kconfig
+++ b/sound/soc/codecs/Kconfig
@@ -55,6 +55,7 @@ config SND_SOC_ALL_CODECS
select SND_SOC_CS35L33 if I2C
select SND_SOC_CS35L34 if I2C
select SND_SOC_CS35L35 if I2C
+ select SND_SOC_CS35L36 if I2C
select SND_SOC_CS42L42 if I2C
select SND_SOC_CS42L51_I2C if I2C
select SND_SOC_CS42L52 if I2C && INPUT
@@ -484,6 +485,10 @@ config SND_SOC_CS35L35
tristate "Cirrus Logic CS35L35 CODEC"
depends on I2C
+config SND_SOC_CS35L36
+ tristate "Cirrus Logic CS35L36 CODEC"
+ depends on I2C
+
config SND_SOC_CS42L42
tristate "Cirrus Logic CS42L42 CODEC"
depends on I2C
diff --git a/sound/soc/codecs/Makefile b/sound/soc/codecs/Makefile
index b07dfb5fa700..aab2ad95a137 100644
--- a/sound/soc/codecs/Makefile
+++ b/sound/soc/codecs/Makefile
@@ -47,6 +47,7 @@ snd-soc-cs35l32-objs := cs35l32.o
snd-soc-cs35l33-objs := cs35l33.o
snd-soc-cs35l34-objs := cs35l34.o
snd-soc-cs35l35-objs := cs35l35.o
+snd-soc-cs35l36-objs := cs35l36.o
snd-soc-cs42l42-objs := cs42l42.o
snd-soc-cs42l51-objs := cs42l51.o
snd-soc-cs42l51-i2c-objs := cs42l51-i2c.o
@@ -319,6 +320,7 @@ obj-$(CONFIG_SND_SOC_CS35L32) += snd-soc-cs35l32.o
obj-$(CONFIG_SND_SOC_CS35L33) += snd-soc-cs35l33.o
obj-$(CONFIG_SND_SOC_CS35L34) += snd-soc-cs35l34.o
obj-$(CONFIG_SND_SOC_CS35L35) += snd-soc-cs35l35.o
+obj-$(CONFIG_SND_SOC_CS35L36) += snd-soc-cs35l36.o
obj-$(CONFIG_SND_SOC_CS42L42) += snd-soc-cs42l42.o
obj-$(CONFIG_SND_SOC_CS42L51) += snd-soc-cs42l51.o
obj-$(CONFIG_SND_SOC_CS42L51_I2C) += snd-soc-cs42l51-i2c.o
diff --git a/sound/soc/codecs/ad193x.c b/sound/soc/codecs/ad193x.c
index 4b60ebee491d..96d7cb2e4a56 100644
--- a/sound/soc/codecs/ad193x.c
+++ b/sound/soc/codecs/ad193x.c
@@ -37,6 +37,13 @@ static SOC_ENUM_SINGLE_DECL(ad193x_deemp_enum, AD193X_DAC_CTRL2, 1,
static const DECLARE_TLV_DB_MINMAX(adau193x_tlv, -9563, 0);
+static const unsigned int ad193x_sb[] = {32};
+
+static struct snd_pcm_hw_constraint_list constr = {
+ .list = ad193x_sb,
+ .count = ARRAY_SIZE(ad193x_sb),
+};
+
static const struct snd_kcontrol_new ad193x_snd_controls[] = {
/* DAC volume control */
SOC_DOUBLE_R_TLV("DAC1 Volume", AD193X_DAC_L1_VOL,
@@ -93,6 +100,15 @@ static const struct snd_soc_dapm_widget ad193x_adc_widgets[] = {
SND_SOC_DAPM_INPUT("ADC2IN"),
};
+static int ad193x_check_pll(struct snd_soc_dapm_widget *source,
+ struct snd_soc_dapm_widget *sink)
+{
+ struct snd_soc_component *component = snd_soc_dapm_to_component(source->dapm);
+ struct ad193x_priv *ad193x = snd_soc_component_get_drvdata(component);
+
+ return !!ad193x->sysclk;
+}
+
static const struct snd_soc_dapm_route audio_paths[] = {
{ "DAC", NULL, "SYSCLK" },
{ "DAC Output", NULL, "DAC" },
@@ -101,7 +117,7 @@ static const struct snd_soc_dapm_route audio_paths[] = {
{ "DAC2OUT", NULL, "DAC Output" },
{ "DAC3OUT", NULL, "DAC Output" },
{ "DAC4OUT", NULL, "DAC Output" },
- { "SYSCLK", NULL, "PLL_PWR" },
+ { "SYSCLK", NULL, "PLL_PWR", &ad193x_check_pll },
};
static const struct snd_soc_dapm_route ad193x_adc_audio_paths[] = {
@@ -181,23 +197,26 @@ static int ad193x_set_dai_fmt(struct snd_soc_dai *codec_dai,
{
struct ad193x_priv *ad193x = snd_soc_component_get_drvdata(codec_dai->component);
unsigned int adc_serfmt = 0;
+ unsigned int dac_serfmt = 0;
unsigned int adc_fmt = 0;
unsigned int dac_fmt = 0;
/* At present, the driver only support AUX ADC mode(SND_SOC_DAIFMT_I2S
- * with TDM) and ADC&DAC TDM mode(SND_SOC_DAIFMT_DSP_A)
+ * with TDM), ADC&DAC TDM mode(SND_SOC_DAIFMT_DSP_A) and DAC I2S mode
+ * (SND_SOC_DAIFMT_I2S)
*/
switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
case SND_SOC_DAIFMT_I2S:
adc_serfmt |= AD193X_ADC_SERFMT_TDM;
+ dac_serfmt |= AD193X_DAC_SERFMT_STEREO;
break;
case SND_SOC_DAIFMT_DSP_A:
adc_serfmt |= AD193X_ADC_SERFMT_AUX;
+ dac_serfmt |= AD193X_DAC_SERFMT_TDM;
break;
default:
if (ad193x_has_adc(ad193x))
return -EINVAL;
- break;
}
switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
@@ -221,6 +240,12 @@ static int ad193x_set_dai_fmt(struct snd_soc_dai *codec_dai,
return -EINVAL;
}
+ /* For DSP_*, LRCLK's polarity must be inverted */
+ if (fmt & SND_SOC_DAIFMT_DSP_A) {
+ change_bit(ffs(AD193X_DAC_LEFT_HIGH) - 1,
+ (unsigned long *)&dac_fmt);
+ }
+
switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
case SND_SOC_DAIFMT_CBM_CFM: /* codec clk & frm master */
adc_fmt |= AD193X_ADC_LCR_MASTER;
@@ -248,6 +273,8 @@ static int ad193x_set_dai_fmt(struct snd_soc_dai *codec_dai,
regmap_update_bits(ad193x->regmap, AD193X_ADC_CTRL2,
AD193X_ADC_FMT_MASK, adc_fmt);
}
+ regmap_update_bits(ad193x->regmap, AD193X_DAC_CTRL0,
+ AD193X_DAC_SERFMT_MASK, dac_serfmt);
regmap_update_bits(ad193x->regmap, AD193X_DAC_CTRL1,
AD193X_DAC_FMT_MASK, dac_fmt);
@@ -258,7 +285,22 @@ static int ad193x_set_dai_sysclk(struct snd_soc_dai *codec_dai,
int clk_id, unsigned int freq, int dir)
{
struct snd_soc_component *component = codec_dai->component;
+ struct snd_soc_dapm_context *dapm = snd_soc_component_get_dapm(component);
struct ad193x_priv *ad193x = snd_soc_component_get_drvdata(component);
+
+ if (clk_id == AD193X_SYSCLK_MCLK) {
+ /* MCLK must be 512 x fs */
+ if (dir == SND_SOC_CLOCK_OUT || freq != 24576000)
+ return -EINVAL;
+
+ regmap_update_bits(ad193x->regmap, AD193X_PLL_CLK_CTRL1,
+ AD193X_PLL_SRC_MASK,
+ AD193X_PLL_DAC_SRC_MCLK |
+ AD193X_PLL_CLK_SRC_MCLK);
+
+ snd_soc_dapm_sync(dapm);
+ return 0;
+ }
switch (freq) {
case 12288000:
case 18432000:
@@ -321,7 +363,16 @@ static int ad193x_hw_params(struct snd_pcm_substream *substream,
return 0;
}
+static int ad193x_startup(struct snd_pcm_substream *substream,
+ struct snd_soc_dai *dai)
+{
+ return snd_pcm_hw_constraint_list(substream->runtime, 0,
+ SNDRV_PCM_HW_PARAM_SAMPLE_BITS,
+ &constr);
+}
+
static const struct snd_soc_dai_ops ad193x_dai_ops = {
+ .startup = ad193x_startup,
.hw_params = ad193x_hw_params,
.digital_mute = ad193x_mute,
.set_tdm_slot = ad193x_set_tdm_slot,
@@ -351,6 +402,20 @@ static struct snd_soc_dai_driver ad193x_dai = {
.ops = &ad193x_dai_ops,
};
+/* codec DAI instance for DAC only */
+static struct snd_soc_dai_driver ad193x_no_adc_dai = {
+ .name = "ad193x-hifi",
+ .playback = {
+ .stream_name = "Playback",
+ .channels_min = 2,
+ .channels_max = 8,
+ .rates = SNDRV_PCM_RATE_48000,
+ .formats = SNDRV_PCM_FMTBIT_S32_LE | SNDRV_PCM_FMTBIT_S16_LE |
+ SNDRV_PCM_FMTBIT_S20_3LE | SNDRV_PCM_FMTBIT_S24_LE,
+ },
+ .ops = &ad193x_dai_ops,
+};
+
static int ad193x_component_probe(struct snd_soc_component *component)
{
struct ad193x_priv *ad193x = snd_soc_component_get_drvdata(component);
@@ -444,8 +509,11 @@ int ad193x_probe(struct device *dev, struct regmap *regmap,
dev_set_drvdata(dev, ad193x);
+ if (ad193x_has_adc(ad193x))
+ return devm_snd_soc_register_component(dev, &soc_component_dev_ad193x,
+ &ad193x_dai, 1);
return devm_snd_soc_register_component(dev, &soc_component_dev_ad193x,
- &ad193x_dai, 1);
+ &ad193x_no_adc_dai, 1);
}
EXPORT_SYMBOL_GPL(ad193x_probe);
diff --git a/sound/soc/codecs/ad193x.h b/sound/soc/codecs/ad193x.h
index 8b1e65f928d2..27d6afbd7dfb 100644
--- a/sound/soc/codecs/ad193x.h
+++ b/sound/soc/codecs/ad193x.h
@@ -31,6 +31,11 @@ int ad193x_probe(struct device *dev, struct regmap *regmap,
#define AD193X_PLL_INPUT_512 (2 << 1)
#define AD193X_PLL_INPUT_768 (3 << 1)
#define AD193X_PLL_CLK_CTRL1 0x01
+#define AD193X_PLL_SRC_MASK 0x03
+#define AD193X_PLL_DAC_SRC_PLL 0
+#define AD193X_PLL_DAC_SRC_MCLK 1
+#define AD193X_PLL_CLK_SRC_PLL (0 << 1)
+#define AD193X_PLL_CLK_SRC_MCLK (1 << 1)
#define AD193X_DAC_CTRL0 0x02
#define AD193X_DAC_POWERDOWN 0x01
#define AD193X_DAC_SERFMT_MASK 0xC0
@@ -96,4 +101,7 @@ int ad193x_probe(struct device *dev, struct regmap *regmap,
#define AD193X_NUM_REGS 17
+#define AD193X_SYSCLK_PLL 0
+#define AD193X_SYSCLK_MCLK 1
+
#endif
diff --git a/sound/soc/codecs/adau1977.c b/sound/soc/codecs/adau1977.c
index 116af6a9ce3b..11c53bcb71dd 100644
--- a/sound/soc/codecs/adau1977.c
+++ b/sound/soc/codecs/adau1977.c
@@ -885,13 +885,15 @@ static int adau1977_setup_micbias(struct adau1977 *adau1977)
struct adau1977_platform_data *pdata = adau1977->dev->platform_data;
unsigned int micbias;
- if (pdata) {
+ if (pdata)
micbias = pdata->micbias;
- if (micbias > ADAU1977_MICBIAS_9V0)
- return -EINVAL;
-
- } else {
+ else if (device_property_read_u32(adau1977->dev, "adi,micbias",
+ &micbias))
micbias = ADAU1977_MICBIAS_8V5;
+
+ if (micbias > ADAU1977_MICBIAS_9V0) {
+ dev_err(adau1977->dev, "Invalid value for 'adi,micbias'\n");
+ return -EINVAL;
}
return regmap_update_bits(adau1977->regmap, ADAU1977_REG_MICBIAS,
diff --git a/sound/soc/codecs/cros_ec_codec.c b/sound/soc/codecs/cros_ec_codec.c
index b14100b6a939..99a3af8a15ff 100644
--- a/sound/soc/codecs/cros_ec_codec.c
+++ b/sound/soc/codecs/cros_ec_codec.c
@@ -206,7 +206,7 @@ static const struct snd_soc_dai_ops cros_ec_i2s_dai_ops = {
.set_fmt = cros_ec_i2s_set_dai_fmt,
};
-struct snd_soc_dai_driver cros_ec_dai[] = {
+static struct snd_soc_dai_driver cros_ec_dai[] = {
{
.name = "cros_ec_codec I2S",
.id = 0,
diff --git a/sound/soc/codecs/cs35l36.c b/sound/soc/codecs/cs35l36.c
new file mode 100644
index 000000000000..e9b5f76f27a8
--- /dev/null
+++ b/sound/soc/codecs/cs35l36.c
@@ -0,0 +1,1957 @@
+// SPDX-License-Identifier: GPL-2.0
+//
+// cs35l36.c -- CS35L36 ALSA SoC audio driver
+//
+// Copyright 2018 Cirrus Logic, Inc.
+//
+// Author: James Schulman <james.schulman@cirrus.com>
+
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/delay.h>
+#include <linux/i2c.h>
+#include <linux/slab.h>
+#include <linux/workqueue.h>
+#include <linux/platform_device.h>
+#include <linux/regulator/consumer.h>
+#include <linux/gpio/consumer.h>
+#include <linux/of_device.h>
+#include <linux/of_gpio.h>
+#include <linux/regmap.h>
+#include <sound/core.h>
+#include <sound/pcm.h>
+#include <sound/pcm_params.h>
+#include <sound/soc.h>
+#include <sound/soc-dapm.h>
+#include <linux/gpio.h>
+#include <sound/initval.h>
+#include <sound/tlv.h>
+#include <sound/cs35l36.h>
+#include <linux/of_irq.h>
+#include <linux/completion.h>
+
+#include "cs35l36.h"
+
+/*
+ * Some fields take zero as a valid value so use a high bit flag that won't
+ * get written to the device to mark those.
+ */
+#define CS35L36_VALID_PDATA 0x80000000
+
+static const char * const cs35l36_supplies[] = {
+ "VA",
+ "VP",
+};
+
+struct cs35l36_private {
+ struct device *dev;
+ struct cs35l36_platform_data pdata;
+ struct regmap *regmap;
+ struct regulator_bulk_data supplies[2];
+ int num_supplies;
+ int clksrc;
+ int chip_version;
+ int rev_id;
+ int ldm_mode_sel;
+ struct gpio_desc *reset_gpio;
+};
+
+struct cs35l36_pll_config {
+ int freq;
+ int clk_cfg;
+ int fll_igain;
+};
+
+static const struct cs35l36_pll_config cs35l36_pll_sysclk[] = {
+ {32768, 0x00, 0x05},
+ {8000, 0x01, 0x03},
+ {11025, 0x02, 0x03},
+ {12000, 0x03, 0x03},
+ {16000, 0x04, 0x04},
+ {22050, 0x05, 0x04},
+ {24000, 0x06, 0x04},
+ {32000, 0x07, 0x05},
+ {44100, 0x08, 0x05},
+ {48000, 0x09, 0x05},
+ {88200, 0x0A, 0x06},
+ {96000, 0x0B, 0x06},
+ {128000, 0x0C, 0x07},
+ {176400, 0x0D, 0x07},
+ {192000, 0x0E, 0x07},
+ {256000, 0x0F, 0x08},
+ {352800, 0x10, 0x08},
+ {384000, 0x11, 0x08},
+ {512000, 0x12, 0x09},
+ {705600, 0x13, 0x09},
+ {750000, 0x14, 0x09},
+ {768000, 0x15, 0x09},
+ {1000000, 0x16, 0x0A},
+ {1024000, 0x17, 0x0A},
+ {1200000, 0x18, 0x0A},
+ {1411200, 0x19, 0x0A},
+ {1500000, 0x1A, 0x0A},
+ {1536000, 0x1B, 0x0A},
+ {2000000, 0x1C, 0x0A},
+ {2048000, 0x1D, 0x0A},
+ {2400000, 0x1E, 0x0A},
+ {2822400, 0x1F, 0x0A},
+ {3000000, 0x20, 0x0A},
+ {3072000, 0x21, 0x0A},
+ {3200000, 0x22, 0x0A},
+ {4000000, 0x23, 0x0A},
+ {4096000, 0x24, 0x0A},
+ {4800000, 0x25, 0x0A},
+ {5644800, 0x26, 0x0A},
+ {6000000, 0x27, 0x0A},
+ {6144000, 0x28, 0x0A},
+ {6250000, 0x29, 0x08},
+ {6400000, 0x2A, 0x0A},
+ {6500000, 0x2B, 0x08},
+ {6750000, 0x2C, 0x09},
+ {7526400, 0x2D, 0x0A},
+ {8000000, 0x2E, 0x0A},
+ {8192000, 0x2F, 0x0A},
+ {9600000, 0x30, 0x0A},
+ {11289600, 0x31, 0x0A},
+ {12000000, 0x32, 0x0A},
+ {12288000, 0x33, 0x0A},
+ {12500000, 0x34, 0x08},
+ {12800000, 0x35, 0x0A},
+ {13000000, 0x36, 0x0A},
+ {13500000, 0x37, 0x0A},
+ {19200000, 0x38, 0x0A},
+ {22579200, 0x39, 0x0A},
+ {24000000, 0x3A, 0x0A},
+ {24576000, 0x3B, 0x0A},
+ {25000000, 0x3C, 0x0A},
+ {25600000, 0x3D, 0x0A},
+ {26000000, 0x3E, 0x0A},
+ {27000000, 0x3F, 0x0A},
+};
+
+static struct reg_default cs35l36_reg[] = {
+ {CS35L36_TESTKEY_CTRL, 0x00000000},
+ {CS35L36_USERKEY_CTL, 0x00000000},
+ {CS35L36_OTP_CTRL1, 0x00002460},
+ {CS35L36_OTP_CTRL2, 0x00000000},
+ {CS35L36_OTP_CTRL3, 0x00000000},
+ {CS35L36_OTP_CTRL4, 0x00000000},