diff options
Diffstat (limited to 'sound/soc')
89 files changed, 6174 insertions, 1754 deletions
diff --git a/sound/soc/Makefile b/sound/soc/Makefile index d90ce8a32887..919c3c027c62 100644 --- a/sound/soc/Makefile +++ b/sound/soc/Makefile @@ -1,5 +1,5 @@ # SPDX-License-Identifier: GPL-2.0 -snd-soc-core-objs := soc-core.o soc-dapm.o soc-jack.o soc-utils.o +snd-soc-core-objs := soc-core.o soc-dapm.o soc-jack.o soc-utils.o soc-dai.o snd-soc-core-objs += soc-pcm.o soc-io.o soc-devres.o soc-ops.o snd-soc-core-$(CONFIG_SND_SOC_COMPRESS) += soc-compress.o diff --git a/sound/soc/bcm/cygnus-pcm.c b/sound/soc/bcm/cygnus-pcm.c index 123ecf5479d7..8966b02844dc 100644 --- a/sound/soc/bcm/cygnus-pcm.c +++ b/sound/soc/bcm/cygnus-pcm.c @@ -639,7 +639,6 @@ static int cygnus_pcm_hw_params(struct snd_pcm_substream *substream, struct snd_soc_pcm_runtime *rtd = substream->private_data; struct snd_pcm_runtime *runtime = substream->runtime; struct cygnus_aio_port *aio; - int ret = 0; aio = cygnus_dai_get_dma_data(substream); dev_dbg(rtd->cpu_dai->dev, "%s port %d\n", __func__, aio->portnum); @@ -647,7 +646,7 @@ static int cygnus_pcm_hw_params(struct snd_pcm_substream *substream, snd_pcm_set_runtime_buffer(substream, &substream->dma_buffer); runtime->dma_bytes = params_buffer_bytes(params); - return ret; + return 0; } static int cygnus_pcm_hw_free(struct snd_pcm_substream *substream) @@ -668,7 +667,6 @@ static int cygnus_pcm_prepare(struct snd_pcm_substream *substream) struct snd_pcm_runtime *runtime = substream->runtime; struct cygnus_aio_port *aio; unsigned long bufsize, periodsize; - int ret = 0; bool is_play; u32 start; struct ringbuf_regs *p_rbuf = NULL; @@ -693,7 +691,7 @@ static int cygnus_pcm_prepare(struct snd_pcm_substream *substream) ringbuf_set_initial(aio->cygaud->audio, p_rbuf, is_play, start, periodsize, bufsize); - return ret; + return 0; } static snd_pcm_uframes_t cygnus_pcm_pointer(struct snd_pcm_substream *substream) diff --git a/sound/soc/codecs/Kconfig b/sound/soc/codecs/Kconfig index 9f89a5346299..da4c1ae89742 100644 --- a/sound/soc/codecs/Kconfig +++ b/sound/soc/codecs/Kconfig @@ -70,10 +70,12 @@ config SND_SOC_ALL_CODECS select SND_SOC_CS43130 if I2C select SND_SOC_CS4341 if SND_SOC_I2C_AND_SPI select SND_SOC_CS4349 if I2C + select SND_SOC_CS47L15 if MFD_CS47L15 select SND_SOC_CS47L24 if MFD_CS47L24 select SND_SOC_CS47L35 if MFD_CS47L35 select SND_SOC_CS47L85 if MFD_CS47L85 select SND_SOC_CS47L90 if MFD_CS47L90 + select SND_SOC_CS47L92 if MFD_CS47L92 select SND_SOC_CS53L30 if I2C select SND_SOC_CX20442 if TTY select SND_SOC_CX2072X if I2C @@ -581,6 +583,9 @@ config SND_SOC_CS4349 tristate "Cirrus Logic CS4349 CODEC" depends on I2C +config SND_SOC_CS47L15 + tristate + config SND_SOC_CS47L24 tristate @@ -593,6 +598,9 @@ config SND_SOC_CS47L85 config SND_SOC_CS47L90 tristate +config SND_SOC_CS47L92 + tristate + # Cirrus Logic Quad-Channel ADC config SND_SOC_CS53L30 tristate "Cirrus Logic CS53L30 CODEC" @@ -722,12 +730,16 @@ config SND_SOC_LOCHNAGAR_SC config SND_SOC_MADERA tristate + default y if SND_SOC_CS47L15=y default y if SND_SOC_CS47L35=y default y if SND_SOC_CS47L85=y default y if SND_SOC_CS47L90=y + default y if SND_SOC_CS47L92=y + default m if SND_SOC_CS47L15=m default m if SND_SOC_CS47L35=m default m if SND_SOC_CS47L85=m default m if SND_SOC_CS47L90=m + default m if SND_SOC_CS47L92=m config SND_SOC_MAX98088 tristate "Maxim MAX98088/9 Low-Power, Stereo Audio Codec" diff --git a/sound/soc/codecs/Makefile b/sound/soc/codecs/Makefile index 5b4bb8cf4325..9230016b0f9f 100644 --- a/sound/soc/codecs/Makefile +++ b/sound/soc/codecs/Makefile @@ -64,10 +64,12 @@ snd-soc-cs42xx8-i2c-objs := cs42xx8-i2c.o snd-soc-cs43130-objs := cs43130.o snd-soc-cs4341-objs := cs4341.o snd-soc-cs4349-objs := cs4349.o +snd-soc-cs47l15-objs := cs47l15.o snd-soc-cs47l24-objs := cs47l24.o snd-soc-cs47l35-objs := cs47l35.o snd-soc-cs47l85-objs := cs47l85.o snd-soc-cs47l90-objs := cs47l90.o +snd-soc-cs47l92-objs := cs47l92.o snd-soc-cs53l30-objs := cs53l30.o snd-soc-cx20442-objs := cx20442.o snd-soc-cx2072x-objs := cx2072x.o @@ -346,9 +348,11 @@ obj-$(CONFIG_SND_SOC_CS43130) += snd-soc-cs43130.o obj-$(CONFIG_SND_SOC_CS4341) += snd-soc-cs4341.o obj-$(CONFIG_SND_SOC_CS4349) += snd-soc-cs4349.o obj-$(CONFIG_SND_SOC_CS47L24) += snd-soc-cs47l24.o +obj-$(CONFIG_SND_SOC_CS47L15) += snd-soc-cs47l15.o obj-$(CONFIG_SND_SOC_CS47L35) += snd-soc-cs47l35.o obj-$(CONFIG_SND_SOC_CS47L85) += snd-soc-cs47l85.o obj-$(CONFIG_SND_SOC_CS47L90) += snd-soc-cs47l90.o +obj-$(CONFIG_SND_SOC_CS47L92) += snd-soc-cs47l92.o obj-$(CONFIG_SND_SOC_CS53L30) += snd-soc-cs53l30.o obj-$(CONFIG_SND_SOC_CX20442) += snd-soc-cx20442.o obj-$(CONFIG_SND_SOC_CX2072X) += snd-soc-cx2072x.o diff --git a/sound/soc/codecs/ad193x.c b/sound/soc/codecs/ad193x.c index 9615e786d049..fb04c9379b71 100644 --- a/sound/soc/codecs/ad193x.c +++ b/sound/soc/codecs/ad193x.c @@ -240,10 +240,8 @@ static int ad193x_set_dai_fmt(struct snd_soc_dai *codec_dai, } /* 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); - } + if (fmt & SND_SOC_DAIFMT_DSP_A) + dac_fmt ^= AD193X_DAC_LEFT_HIGH; switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { case SND_SOC_DAIFMT_CBM_CFM: /* codec clk & frm master */ @@ -415,15 +413,10 @@ static struct snd_soc_dai_driver ad193x_no_adc_dai = { .ops = &ad193x_dai_ops, }; -struct ad193x_reg_default { - unsigned int reg; - unsigned int val; -}; - /* codec register values to set after reset */ static void ad193x_reg_default_init(struct ad193x_priv *ad193x) { - const struct ad193x_reg_default reg_init[] = { + const struct reg_sequence reg_init[] = { { 0, 0x99 }, /* PLL_CLK_CTRL0: pll input: mclki/xi 12.288Mhz */ { 1, 0x04 }, /* PLL_CLK_CTRL1: no on-chip Vref */ { 2, 0x40 }, /* DAC_CTRL0: TDM mode */ @@ -439,21 +432,17 @@ static void ad193x_reg_default_init(struct ad193x_priv *ad193x) { 12, 0x00 }, /* DAC_L4_VOL: no attenuation */ { 13, 0x00 }, /* DAC_R4_VOL: no attenuation */ }; - const struct ad193x_reg_default reg_adc_init[] = { + const struct reg_sequence reg_adc_init[] = { { 14, 0x03 }, /* ADC_CTRL0: high-pass filter enable */ { 15, 0x43 }, /* ADC_CTRL1: sata delay=1, adc aux mode */ { 16, 0x00 }, /* ADC_CTRL2: reset */ }; - int i; - for (i = 0; i < ARRAY_SIZE(reg_init); i++) - regmap_write(ad193x->regmap, reg_init[i].reg, reg_init[i].val); + regmap_multi_reg_write(ad193x->regmap, reg_init, ARRAY_SIZE(reg_init)); if (ad193x_has_adc(ad193x)) { - for (i = 0; i < ARRAY_SIZE(reg_adc_init); i++) { - regmap_write(ad193x->regmap, reg_adc_init[i].reg, - reg_adc_init[i].val); - } + regmap_multi_reg_write(ad193x->regmap, reg_adc_init, + ARRAY_SIZE(reg_adc_init)); } } diff --git a/sound/soc/codecs/cros_ec_codec.c b/sound/soc/codecs/cros_ec_codec.c index 0ac3e520653f..85beef265cc8 100644 --- a/sound/soc/codecs/cros_ec_codec.c +++ b/sound/soc/codecs/cros_ec_codec.c @@ -38,21 +38,21 @@ static const DECLARE_TLV_DB_SCALE(ec_mic_gain_tlv, 0, 100, 0); static int ec_command_get_gain(struct snd_soc_component *component, struct ec_param_codec_i2s *param, - struct ec_response_codec_gain *resp) + struct ec_codec_i2s_gain *resp) { struct cros_ec_codec_data *codec_data = snd_soc_component_get_drvdata(component); struct cros_ec_device *ec_device = codec_data->ec_device; u8 buffer[sizeof(struct cros_ec_command) + max(sizeof(struct ec_param_codec_i2s), - sizeof(struct ec_response_codec_gain))]; + sizeof(struct ec_codec_i2s_gain))]; struct cros_ec_command *msg = (struct cros_ec_command *)&buffer; int ret; msg->version = 0; msg->command = EC_CMD_CODEC_I2S; msg->outsize = sizeof(struct ec_param_codec_i2s); - msg->insize = sizeof(struct ec_response_codec_gain); + msg->insize = sizeof(struct ec_codec_i2s_gain); memcpy(msg->data, param, msg->outsize); @@ -226,7 +226,7 @@ static int get_ec_mic_gain(struct snd_soc_component *component, u8 *left, u8 *right) { struct ec_param_codec_i2s param; - struct ec_response_codec_gain resp; + struct ec_codec_i2s_gain resp; int ret; param.cmd = EC_CODEC_GET_GAIN; diff --git a/sound/soc/codecs/cs47l15.c b/sound/soc/codecs/cs47l15.c new file mode 100644 index 000000000000..ece1276f38eb --- /dev/null +++ b/sound/soc/codecs/cs47l15.c @@ -0,0 +1,1490 @@ +// SPDX-License-Identifier: GPL-2.0-only +// +// ALSA SoC Audio driver for CS47L15 codec +// +// Copyright (C) 2016-2019 Cirrus Logic, Inc. and +// Cirrus Logic International Semiconductor Ltd. +// + +#include <linux/module.h> +#include <linux/moduleparam.h> +#include <linux/device.h> +#include <linux/delay.h> +#include <linux/init.h> +#include <linux/pm.h> +#include <linux/pm_runtime.h> +#include <linux/regmap.h> +#include <sound/core.h> +#include <sound/pcm.h> +#include <sound/pcm_params.h> +#include <sound/soc.h> +#include <sound/tlv.h> + +#include <linux/irqchip/irq-madera.h> +#include <linux/mfd/madera/core.h> +#include <linux/mfd/madera/registers.h> + +#include "madera.h" +#include "wm_adsp.h" + +#define CS47L15_NUM_ADSP 1 +#define CS47L15_MONO_OUTPUTS 1 + +/* Mid-mode registers */ +#define CS47L15_ADC_INT_BIAS_MASK 0x3800 +#define CS47L15_ADC_INT_BIAS_SHIFT 11 +#define CS47L15_PGA_BIAS_SEL_MASK 0x03 +#define CS47L15_PGA_BIAS_SEL_SHIFT 0 + +#define DRV_NAME "cs47l15-codec" + +struct cs47l15 { + struct madera_priv core; + struct madera_fll fll[2]; + + bool in1_lp_mode; +}; + +static const struct wm_adsp_region cs47l15_dsp1_regions[] = { + { .type = WMFW_ADSP2_PM, .base = 0x080000 }, + { .type = WMFW_ADSP2_ZM, .base = 0x0e0000 }, + { .type = WMFW_ADSP2_XM, .base = 0x0a0000 }, + { .type = WMFW_ADSP2_YM, .base = 0x0c0000 }, +}; + +static const char * const cs47l15_outdemux_texts[] = { + "HPOUT", + "EPOUT", +}; + +static SOC_ENUM_SINGLE_DECL(cs47l15_outdemux_enum, SND_SOC_NOPM, 0, + cs47l15_outdemux_texts); + +static const struct snd_kcontrol_new cs47l15_outdemux = + SOC_DAPM_ENUM_EXT("HPOUT1 Demux", cs47l15_outdemux_enum, + madera_out1_demux_get, madera_out1_demux_put); + +static int cs47l15_adsp_power_ev(struct snd_soc_dapm_widget *w, + struct snd_kcontrol *kcontrol, + int event) +{ + struct snd_soc_component *component = + snd_soc_dapm_to_component(w->dapm); + struct cs47l15 *cs47l15 = snd_soc_component_get_drvdata(component); + struct madera_priv *priv = &cs47l15->core; + struct madera *madera = priv->madera; + unsigned int freq; + int ret; + + ret = regmap_read(madera->regmap, MADERA_DSP_CLOCK_2, &freq); + if (ret != 0) { + dev_err(madera->dev, + "Failed to read MADERA_DSP_CLOCK_2: %d\n", ret); + return ret; + } + + switch (event) { + case SND_SOC_DAPM_PRE_PMU: + ret = madera_set_adsp_clk(&cs47l15->core, w->shift, freq); + if (r |