diff options
author | John W. Linville <linville@tuxdriver.com> | 2011-11-22 14:05:46 -0500 |
---|---|---|
committer | John W. Linville <linville@tuxdriver.com> | 2011-11-22 14:05:46 -0500 |
commit | 515db09338704a6ad7d27b5f1e33820d3052edd2 (patch) | |
tree | 74f915531710303397d34069b325c2be7a5ac93c /sound/soc/codecs | |
parent | 30be52e44fd4276d768efffb55d424fb682e6505 (diff) | |
parent | cfcfc9eca2bcbd26a8e206baeb005b055dbf8e37 (diff) |
Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux
Conflicts:
drivers/net/wireless/iwlegacy/iwl-debugfs.c
drivers/net/wireless/iwlegacy/iwl-rx.c
drivers/net/wireless/iwlegacy/iwl-scan.c
drivers/net/wireless/iwlegacy/iwl-tx.c
include/net/bluetooth/bluetooth.h
Diffstat (limited to 'sound/soc/codecs')
89 files changed, 16326 insertions, 1995 deletions
diff --git a/sound/soc/codecs/88pm860x-codec.c b/sound/soc/codecs/88pm860x-codec.c index 19241576b6b..5ca122e5118 100644 --- a/sound/soc/codecs/88pm860x-codec.c +++ b/sound/soc/codecs/88pm860x-codec.c @@ -15,6 +15,7 @@ #include <linux/platform_device.h> #include <linux/mfd/88pm860x.h> #include <linux/slab.h> +#include <linux/delay.h> #include <sound/core.h> #include <sound/pcm.h> #include <sound/pcm_params.h> @@ -772,11 +773,12 @@ static const struct snd_soc_dapm_widget pm860x_dapm_widgets[] = { SND_SOC_DAPM_AIF_IN("I2S DIN", "I2S Playback", 0, - PM860X_DAC_EN_2, 0, 0), + SND_SOC_NOPM, 0, 0), SND_SOC_DAPM_AIF_IN("I2S DIN1", "I2S Playback", 0, - PM860X_DAC_EN_2, 0, 0), + SND_SOC_NOPM, 0, 0), SND_SOC_DAPM_AIF_OUT("I2S DOUT", "I2S Capture", 0, PM860X_I2S_IFACE_3, 5, 1), + SND_SOC_DAPM_SUPPLY("I2S CLK", PM860X_DAC_EN_2, 0, 0, NULL, 0), SND_SOC_DAPM_MUX("I2S Mic Mux", SND_SOC_NOPM, 0, 0, &i2s_mic_mux), SND_SOC_DAPM_MUX("ADC Left Mux", SND_SOC_NOPM, 0, 0, &adcl_mux), SND_SOC_DAPM_MUX("ADC Right Mux", SND_SOC_NOPM, 0, 0, &adcr_mux), @@ -868,6 +870,11 @@ static const struct snd_soc_dapm_route audio_map[] = { {"Left ADC", NULL, "Left ADC MOD"}, {"Right ADC", NULL, "Right ADC MOD"}, + /* I2S Clock */ + {"I2S DIN", NULL, "I2S CLK"}, + {"I2S DIN1", NULL, "I2S CLK"}, + {"I2S DOUT", NULL, "I2S CLK"}, + /* PCM/AIF1 Inputs */ {"PCM SDO", NULL, "ADC Left Mux"}, {"PCM SDO", NULL, "ADCR EC Mux"}, @@ -1173,6 +1180,9 @@ static int pm860x_set_bias_level(struct snd_soc_codec *codec, case SND_SOC_BIAS_STANDBY: if (codec->dapm.bias_level == SND_SOC_BIAS_OFF) { /* Enable Audio PLL & Audio section */ + data = AUDIO_PLL | AUDIO_SECTION_ON; + pm860x_reg_write(codec->control_data, REG_MISC2, data); + udelay(300); data = AUDIO_PLL | AUDIO_SECTION_RESET | AUDIO_SECTION_ON; pm860x_reg_write(codec->control_data, REG_MISC2, data); diff --git a/sound/soc/codecs/Kconfig b/sound/soc/codecs/Kconfig index 665d9240c4a..4584514d93d 100644 --- a/sound/soc/codecs/Kconfig +++ b/sound/soc/codecs/Kconfig @@ -17,6 +17,7 @@ config SND_SOC_ALL_CODECS select SND_SOC_AD193X if SND_SOC_I2C_AND_SPI select SND_SOC_AD1980 if SND_SOC_AC97_BUS select SND_SOC_AD73311 + select SND_SOC_ADAU1373 if I2C select SND_SOC_ADAV80X select SND_SOC_ADS117X select SND_SOC_AK4104 if SPI_MASTER @@ -39,6 +40,7 @@ config SND_SOC_ALL_CODECS select SND_SOC_MAX9850 if I2C select SND_SOC_MAX9877 if I2C select SND_SOC_PCM3008 + select SND_SOC_RT5631 if I2C select SND_SOC_SGTL5000 if I2C select SND_SOC_SN95031 if INTEL_SCU_IPC select SND_SOC_SPDIF @@ -47,7 +49,7 @@ config SND_SOC_ALL_CODECS select SND_SOC_STAC9766 if SND_SOC_AC97_BUS select SND_SOC_TLV320AIC23 if I2C select SND_SOC_TLV320AIC26 if SPI_MASTER - select SND_SOC_TVL320AIC32X4 if I2C + select SND_SOC_TLV320AIC32X4 if I2C select SND_SOC_TLV320AIC3X if I2C select SND_SOC_TPA6130A2 if I2C select SND_SOC_TLV320DAC33 if I2C @@ -58,6 +60,7 @@ config SND_SOC_ALL_CODECS select SND_SOC_WL1273 if MFD_WL1273_CORE select SND_SOC_WM1250_EV1 if I2C select SND_SOC_WM2000 if I2C + select SND_SOC_WM5100 if I2C select SND_SOC_WM8350 if MFD_WM8350 select SND_SOC_WM8400 if MFD_WM8400 select SND_SOC_WM8510 if SND_SOC_I2C_AND_SPI @@ -139,6 +142,9 @@ config SND_SOC_ADAU1701 select SIGMA tristate +config SND_SOC_ADAU1373 + tristate + config SND_SOC_ADAV80X tristate @@ -214,6 +220,9 @@ config SND_SOC_MAX9850 config SND_SOC_PCM3008 tristate +config SND_SOC_RT5631 + tristate + #Freescale sgtl5000 codec config SND_SOC_SGTL5000 tristate @@ -240,7 +249,7 @@ config SND_SOC_TLV320AIC26 tristate "TI TLV320AIC26 Codec support" if SND_SOC_OF_SIMPLE depends on SPI -config SND_SOC_TVL320AIC32X4 +config SND_SOC_TLV320AIC32X4 tristate config SND_SOC_TLV320AIC3X @@ -269,6 +278,9 @@ config SND_SOC_WL1273 config SND_SOC_WM1250_EV1 tristate +config SND_SOC_WM5100 + tristate + config SND_SOC_WM8350 tristate diff --git a/sound/soc/codecs/Makefile b/sound/soc/codecs/Makefile index 5119a7e2c1a..a2c7842e357 100644 --- a/sound/soc/codecs/Makefile +++ b/sound/soc/codecs/Makefile @@ -5,6 +5,7 @@ snd-soc-ad193x-objs := ad193x.o snd-soc-ad1980-objs := ad1980.o snd-soc-ad73311-objs := ad73311.o snd-soc-adau1701-objs := adau1701.o +snd-soc-adau1373-objs := adau1373.o snd-soc-adav80x-objs := adav80x.o snd-soc-ads117x-objs := ads117x.o snd-soc-ak4104-objs := ak4104.o @@ -25,6 +26,7 @@ snd-soc-max98088-objs := max98088.o snd-soc-max98095-objs := max98095.o snd-soc-max9850-objs := max9850.o snd-soc-pcm3008-objs := pcm3008.o +snd-soc-rt5631-objs := rt5631.o snd-soc-sgtl5000-objs := sgtl5000.o snd-soc-alc5623-objs := alc5623.o snd-soc-sn95031-objs := sn95031.o @@ -43,6 +45,7 @@ snd-soc-uda134x-objs := uda134x.o snd-soc-uda1380-objs := uda1380.o snd-soc-wl1273-objs := wl1273.o snd-soc-wm1250-ev1-objs := wm1250-ev1.o +snd-soc-wm5100-objs := wm5100.o wm5100-tables.o snd-soc-wm8350-objs := wm8350.o snd-soc-wm8400-objs := wm8400.o snd-soc-wm8510-objs := wm8510.o @@ -100,6 +103,7 @@ obj-$(CONFIG_SND_SOC_AD1836) += snd-soc-ad1836.o obj-$(CONFIG_SND_SOC_AD193X) += snd-soc-ad193x.o obj-$(CONFIG_SND_SOC_AD1980) += snd-soc-ad1980.o obj-$(CONFIG_SND_SOC_AD73311) += snd-soc-ad73311.o +obj-$(CONFIG_SND_SOC_ADAU1373) += snd-soc-adau1373.o obj-$(CONFIG_SND_SOC_ADAU1701) += snd-soc-adau1701.o obj-$(CONFIG_SND_SOC_ADAV80X) += snd-soc-adav80x.o obj-$(CONFIG_SND_SOC_ADS117X) += snd-soc-ads117x.o @@ -123,6 +127,7 @@ obj-$(CONFIG_SND_SOC_MAX98088) += snd-soc-max98088.o obj-$(CONFIG_SND_SOC_MAX98095) += snd-soc-max98095.o obj-$(CONFIG_SND_SOC_MAX9850) += snd-soc-max9850.o obj-$(CONFIG_SND_SOC_PCM3008) += snd-soc-pcm3008.o +obj-$(CONFIG_SND_SOC_RT5631) += snd-soc-rt5631.o obj-$(CONFIG_SND_SOC_SGTL5000) += snd-soc-sgtl5000.o obj-$(CONFIG_SND_SOC_SN95031) +=snd-soc-sn95031.o obj-$(CONFIG_SND_SOC_SPDIF) += snd-soc-spdif.o @@ -132,7 +137,7 @@ obj-$(CONFIG_SND_SOC_STAC9766) += snd-soc-stac9766.o obj-$(CONFIG_SND_SOC_TLV320AIC23) += snd-soc-tlv320aic23.o obj-$(CONFIG_SND_SOC_TLV320AIC26) += snd-soc-tlv320aic26.o obj-$(CONFIG_SND_SOC_TLV320AIC3X) += snd-soc-tlv320aic3x.o -obj-$(CONFIG_SND_SOC_TVL320AIC32X4) += snd-soc-tlv320aic32x4.o +obj-$(CONFIG_SND_SOC_TLV320AIC32X4) += snd-soc-tlv320aic32x4.o obj-$(CONFIG_SND_SOC_TLV320DAC33) += snd-soc-tlv320dac33.o obj-$(CONFIG_SND_SOC_TWL4030) += snd-soc-twl4030.o obj-$(CONFIG_SND_SOC_TWL6040) += snd-soc-twl6040.o @@ -140,6 +145,7 @@ obj-$(CONFIG_SND_SOC_UDA134X) += snd-soc-uda134x.o obj-$(CONFIG_SND_SOC_UDA1380) += snd-soc-uda1380.o obj-$(CONFIG_SND_SOC_WL1273) += snd-soc-wl1273.o obj-$(CONFIG_SND_SOC_WM1250_EV1) += snd-soc-wm1250-ev1.o +obj-$(CONFIG_SND_SOC_WM5100) += snd-soc-wm5100.o obj-$(CONFIG_SND_SOC_WM8350) += snd-soc-wm8350.o obj-$(CONFIG_SND_SOC_WM8400) += snd-soc-wm8400.o obj-$(CONFIG_SND_SOC_WM8510) += snd-soc-wm8510.o diff --git a/sound/soc/codecs/ac97.c b/sound/soc/codecs/ac97.c index 3c087936aa5..e715186b430 100644 --- a/sound/soc/codecs/ac97.c +++ b/sound/soc/codecs/ac97.c @@ -16,6 +16,7 @@ #include <linux/slab.h> #include <linux/kernel.h> #include <linux/device.h> +#include <linux/module.h> #include <sound/core.h> #include <sound/pcm.h> #include <sound/ac97_codec.h> diff --git a/sound/soc/codecs/ad193x.c b/sound/soc/codecs/ad193x.c index eedb6f5e582..120602130b5 100644 --- a/sound/soc/codecs/ad193x.c +++ b/sound/soc/codecs/ad193x.c @@ -23,7 +23,7 @@ /* codec private data */ struct ad193x_priv { - enum snd_soc_control_type control_type; + struct regmap *regmap; int sysclk; }; @@ -103,12 +103,14 @@ static const struct snd_soc_dapm_route audio_paths[] = { static int ad193x_mute(struct snd_soc_dai *dai, int mute) { struct snd_soc_codec *codec = dai->codec; - int reg; - reg = snd_soc_read(codec, AD193X_DAC_CTRL2); - reg = (mute > 0) ? reg | AD193X_DAC_MASTER_MUTE : reg & - (~AD193X_DAC_MASTER_MUTE); - snd_soc_write(codec, AD193X_DAC_CTRL2, reg); + if (mute) + snd_soc_update_bits(codec, AD193X_DAC_CTRL2, + AD193X_DAC_MASTER_MUTE, + AD193X_DAC_MASTER_MUTE); + else + snd_soc_update_bits(codec, AD193X_DAC_CTRL2, + AD193X_DAC_MASTER_MUTE, 0); return 0; } @@ -262,7 +264,7 @@ static int ad193x_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params, struct snd_soc_dai *dai) { - int word_len = 0, reg = 0, master_rate = 0; + int word_len = 0, master_rate = 0; struct snd_soc_pcm_runtime *rtd = substream->private_data; struct snd_soc_codec *codec = rtd->codec; @@ -297,18 +299,15 @@ static int ad193x_hw_params(struct snd_pcm_substream *substream, break; } - reg = snd_soc_read(codec, AD193X_PLL_CLK_CTRL0); - reg = (reg & AD193X_PLL_INPUT_MASK) | master_rate; - snd_soc_write(codec, AD193X_PLL_CLK_CTRL0, reg); + snd_soc_update_bits(codec, AD193X_PLL_CLK_CTRL0, + AD193X_PLL_INPUT_MASK, master_rate); - reg = snd_soc_read(codec, AD193X_DAC_CTRL2); - reg = (reg & (~AD193X_DAC_WORD_LEN_MASK)) - | (word_len << AD193X_DAC_WORD_LEN_SHFT); - snd_soc_write(codec, AD193X_DAC_CTRL2, reg); + snd_soc_update_bits(codec, AD193X_DAC_CTRL2, + AD193X_DAC_WORD_LEN_MASK, + word_len << AD193X_DAC_WORD_LEN_SHFT); - reg = snd_soc_read(codec, AD193X_ADC_CTRL1); - reg = (reg & (~AD193X_ADC_WORD_LEN_MASK)) | word_len; - snd_soc_write(codec, AD193X_ADC_CTRL1, reg); + snd_soc_update_bits(codec, AD193X_ADC_CTRL1, + AD193X_ADC_WORD_LEN_MASK, word_len); return 0; } @@ -349,10 +348,8 @@ static int ad193x_probe(struct snd_soc_codec *codec) struct snd_soc_dapm_context *dapm = &codec->dapm; int ret; - if (ad193x->control_type == SND_SOC_I2C) - ret = snd_soc_codec_set_cache_io(codec, 8, 8, ad193x->control_type); - else - ret = snd_soc_codec_set_cache_io(codec, 16, 8, ad193x->control_type); + codec->control_data = ad193x->regmap; + ret = snd_soc_codec_set_cache_io(codec, 0, 0, SND_SOC_REGMAP); if (ret < 0) { dev_err(codec->dev, "failed to set cache I/O: %d\n", ret); return ret; @@ -388,6 +385,14 @@ static struct snd_soc_codec_driver soc_codec_dev_ad193x = { }; #if defined(CONFIG_SPI_MASTER) + +static const struct regmap_config ad193x_spi_regmap_config = { + .val_bits = 8, + .reg_bits = 16, + .read_flag_mask = 0x09, + .write_flag_mask = 0x08, +}; + static int __devinit ad193x_spi_probe(struct spi_device *spi) { struct ad193x_priv *ad193x; @@ -397,20 +402,36 @@ static int __devinit ad193x_spi_probe(struct spi_device *spi) if (ad193x == NULL) return -ENOMEM; + ad193x->regmap = regmap_init_spi(spi, &ad193x_spi_regmap_config); + if (IS_ERR(ad193x->regmap)) { + ret = PTR_ERR(ad193x->regmap); + goto err_free; + } + spi_set_drvdata(spi, ad193x); - ad193x->control_type = SND_SOC_SPI; ret = snd_soc_register_codec(&spi->dev, &soc_codec_dev_ad193x, &ad193x_dai, 1); if (ret < 0) - kfree(ad193x); + goto err_regmap_exit; + + return 0; + +err_regmap_exit: + regmap_exit(ad193x->regmap); +err_free: + kfree(ad193x); + return ret; } static int __devexit ad193x_spi_remove(struct spi_device *spi) { + struct ad193x_priv *ad193x = spi_get_drvdata(spi); + snd_soc_unregister_codec(&spi->dev); - kfree(spi_get_drvdata(spi)); + regmap_exit(ad193x->regmap); + kfree(ad193x); return 0; } @@ -425,6 +446,12 @@ static struct spi_driver ad193x_spi_driver = { #endif #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) + +static const struct regmap_config ad193x_i2c_regmap_config = { + .val_bits = 8, + .reg_bits = 8, +}; + static const struct i2c_device_id ad193x_id[] = { { "ad1936", 0 }, { "ad1937", 0 }, @@ -442,20 +469,35 @@ static int __devinit ad193x_i2c_probe(struct i2c_client *client, if (ad193x == NULL) return -ENOMEM; + ad193x->regmap = regmap_init_i2c(client, &ad193x_i2c_regmap_config); + if (IS_ERR(ad193x->regmap)) { + ret = PTR_ERR(ad193x->regmap); + goto err_free; + } + i2c_set_clientdata(client, ad193x); - ad193x->control_type = SND_SOC_I2C; ret = snd_soc_register_codec(&client->dev, &soc_codec_dev_ad193x, &ad193x_dai, 1); if (ret < 0) - kfree(ad193x); + goto err_regmap_exit; + + return 0; + +err_regmap_exit: + regmap_exit(ad193x->regmap); +err_free: + kfree(ad193x); return ret; } static int __devexit ad193x_i2c_remove(struct i2c_client *client) { + struct ad193x_priv *ad193x = i2c_get_clientdata(client); + snd_soc_unregister_codec(&client->dev); - kfree(i2c_get_clientdata(client)); + regmap_exit(ad193x->regmap); + kfree(ad193x); return 0; } diff --git a/sound/soc/codecs/ad193x.h b/sound/soc/codecs/ad193x.h index cccc2e8e5fb..1507eaa425a 100644 --- a/sound/soc/codecs/ad193x.h +++ b/sound/soc/codecs/ad193x.h @@ -9,20 +9,20 @@ #ifndef __AD193X_H__ #define __AD193X_H__ -#define AD193X_PLL_CLK_CTRL0 0x800 +#define AD193X_PLL_CLK_CTRL0 0x00 #define AD193X_PLL_POWERDOWN 0x01 -#define AD193X_PLL_INPUT_MASK (~0x6) +#define AD193X_PLL_INPUT_MASK 0x6 #define AD193X_PLL_INPUT_256 (0 << 1) #define AD193X_PLL_INPUT_384 (1 << 1) #define AD193X_PLL_INPUT_512 (2 << 1) #define AD193X_PLL_INPUT_768 (3 << 1) -#define AD193X_PLL_CLK_CTRL1 0x801 -#define AD193X_DAC_CTRL0 0x802 +#define AD193X_PLL_CLK_CTRL1 0x01 +#define AD193X_DAC_CTRL0 0x02 #define AD193X_DAC_POWERDOWN 0x01 #define AD193X_DAC_SERFMT_MASK 0xC0 #define AD193X_DAC_SERFMT_STEREO (0 << 6) #define AD193X_DAC_SERFMT_TDM (1 << 6) -#define AD193X_DAC_CTRL1 0x803 +#define AD193X_DAC_CTRL1 0x03 #define AD193X_DAC_2_CHANNELS 0 #define AD193X_DAC_4_CHANNELS 1 #define AD193X_DAC_8_CHANNELS 2 @@ -33,11 +33,11 @@ #define AD193X_DAC_BCLK_MASTER (1 << 5) #define AD193X_DAC_LEFT_HIGH (1 << 3) #define AD193X_DAC_BCLK_INV (1 << 7) -#define AD193X_DAC_CTRL2 0x804 +#define AD193X_DAC_CTRL2 0x04 #define AD193X_DAC_WORD_LEN_SHFT 3 #define AD193X_DAC_WORD_LEN_MASK 0x18 #define AD193X_DAC_MASTER_MUTE 1 -#define AD193X_DAC_CHNL_MUTE 0x805 +#define AD193X_DAC_CHNL_MUTE 0x05 #define AD193X_DACL1_MUTE 0 #define AD193X_DACR1_MUTE 1 #define AD193X_DACL2_MUTE 2 @@ -46,28 +46,28 @@ #define AD193X_DACR3_MUTE 5 #define AD193X_DACL4_MUTE 6 #define AD193X_DACR4_MUTE 7 -#define AD193X_DAC_L1_VOL 0x806 -#define AD193X_DAC_R1_VOL 0x807 -#define AD193X_DAC_L2_VOL 0x808 -#define AD193X_DAC_R2_VOL 0x809 -#define AD193X_DAC_L3_VOL 0x80a -#define AD193X_DAC_R3_VOL 0x80b -#define AD193X_DAC_L4_VOL 0x80c -#define AD193X_DAC_R4_VOL 0x80d -#define AD193X_ADC_CTRL0 0x80e +#define AD193X_DAC_L1_VOL 0x06 +#define AD193X_DAC_R1_VOL 0x07 +#define AD193X_DAC_L2_VOL 0x08 +#define AD193X_DAC_R2_VOL 0x09 +#define AD193X_DAC_L3_VOL 0x0a +#define AD193X_DAC_R3_VOL 0x0b +#define AD193X_DAC_L4_VOL 0x0c +#define AD193X_DAC_R4_VOL 0x0d +#define AD193X_ADC_CTRL0 0x0e #define AD193X_ADC_POWERDOWN 0x01 #define AD193X_ADC_HIGHPASS_FILTER 1 #define AD193X_ADCL1_MUTE 2 #define AD193X_ADCR1_MUTE 3 #define AD193X_ADCL2_MUTE 4 #define AD193X_ADCR2_MUTE 5 -#define AD193X_ADC_CTRL1 0x80f +#define AD193X_ADC_CTRL1 0x0f #define AD193X_ADC_SERFMT_MASK 0x60 #define AD193X_ADC_SERFMT_STEREO (0 << 5) #define AD193X_ADC_SERFMT_TDM (1 << 5) #define AD193X_ADC_SERFMT_AUX (2 << 5) #define AD193X_ADC_WORD_LEN_MASK 0x3 -#define AD193X_ADC_CTRL2 0x810 +#define AD193X_ADC_CTRL2 0x10 #define AD193X_ADC_2_CHANNELS 0 #define AD193X_ADC_4_CHANNELS 1 #define AD193X_ADC_8_CHANNELS 2 diff --git a/sound/soc/codecs/ad1980.c b/sound/soc/codecs/ad1980.c index 923b364a3e4..e3931cc5e66 100644 --- a/sound/soc/codecs/ad1980.c +++ b/sound/soc/codecs/ad1980.c @@ -148,7 +148,6 @@ static struct snd_soc_dai_driver ad1980_dai = { .rates = SNDRV_PCM_RATE_48000, .formats = SND_SOC_STD_AC97_FMTS, }, }; -EXPORT_SYMBOL_GPL(ad1980_dai); static int ad1980_reset(struct snd_soc_codec *codec, int try_warm) { @@ -200,18 +199,22 @@ static int ad1980_soc_probe(struct snd_soc_codec *codec) } /* Read out vendor ID to make sure it is ad1980 */ - if (ac97_read(codec, AC97_VENDOR_ID1) != 0x4144) + if (ac97_read(codec, AC97_VENDOR_ID1) != 0x4144) { + ret = -ENODEV; goto reset_err; + } vendor_id2 = ac97_read(codec, AC97_VENDOR_ID2); if (vendor_id2 != 0x5370) { - if (vendor_id2 != 0x5374) + if (vendor_id2 != 0x5374) { + ret = -ENODEV; goto reset_err; - else + } else { printk(KERN_WARNING "ad1980: " "Found AD1981 - only 2/2 IN/OUT Channels " "supported\n"); + } } /* unmute captures and playbacks volume */ diff --git a/sound/soc/codecs/adau1373.c b/sound/soc/codecs/adau1373.c new file mode 100644 index 00000000000..1ccf8dd4757 --- /dev/null +++ b/sound/soc/codecs/adau1373.c @@ -0,0 +1,1414 @@ +/* + * Analog Devices ADAU1373 Audio Codec drive + * + * Copyright 2011 Analog Devices Inc. + * Author: Lars-Peter Clausen <lars@metafoo.de> + * + * Licensed under the GPL-2 or later. + */ + +#include <linux/module.h> +#include <linux/init.h> +#include <linux/delay.h> +#include <linux/pm.h> +#include <linux/i2c.h> +#include <linux/slab.h> +#include <linux/gcd.h> + +#include <sound/core.h> +#include <sound/pcm.h> +#include <sound/pcm_params.h> +#include <sound/tlv.h> +#include <sound/soc.h> +#include <sound/adau1373.h> + +#include "adau1373.h" + +struct adau1373_dai { + unsigned int clk_src; + unsigned int sysclk; + bool enable_src; + bool master; +}; + +struct adau1373 { + struct adau1373_dai dais[3]; +}; + +#define ADAU1373_INPUT_MODE 0x00 +#define ADAU1373_AINL_CTRL(x) (0x01 + (x) * 2) +#define ADAU1373_AINR_CTRL(x) (0x02 + (x) * 2) +#define ADAU1373_LLINE_OUT(x) (0x9 + (x) * 2) +#define ADAU1373_RLINE_OUT(x) (0xa + (x) * 2) +#define ADAU1373_LSPK_OUT 0x0d +#define ADAU1373_RSPK_OUT 0x0e +#define ADAU1373_LHP_OUT 0x0f +#define ADAU1373_RHP_OUT 0x10 +#define ADAU1373_ADC_GAIN 0x11 +#define ADAU1373_LADC_MIXER 0x12 +#define ADAU1373_RADC_MIXER 0x13 +#define ADAU1373_LLINE1_MIX 0x14 +#define ADAU1373_RLINE1_MIX 0x15 +#define ADAU1373_LLINE2_MIX 0x16 +#define ADAU1373_RLINE2_MIX 0x17 +#define ADAU1373_LSPK_MIX 0x18 +#define ADAU1373_RSPK_MIX 0x19 +#define ADAU1373_LHP_MIX 0x1a +#define ADAU1373_RHP_MIX 0x1b +#define ADAU1373_EP_MIX 0x1c +#define ADAU1373_HP_CTRL 0x1d +#define ADAU1373_HP_CTRL2 0x1e +#define ADAU1373_LS_CTRL 0x1f +#define ADAU1373_EP_CTRL 0x21 +#define ADAU1373_MICBIAS_CTRL1 0x22 +#define ADAU1373_MICBIAS_CTRL2 0x23 +#define ADAU1373_OUTPUT_CTRL 0x24 +#define ADAU1373_PWDN_CTRL1 0x25 +#define ADAU1373_PWDN_CTRL2 0x26 +#define ADAU1373_PWDN_CTRL3 0x27 +#define ADAU1373_DPLL_CTRL(x) (0x28 + (x) * 7) +#define ADAU1373_PLL_CTRL1(x) (0x29 + (x) * 7) +#define ADAU1373_PLL_CTRL2(x) (0x2a + (x) * 7) +#define ADAU1373_PLL_CTRL3(x) (0x2b + (x) * 7) +#define ADAU1373_PLL_CTRL4(x) (0x2c + (x) * 7) +#define ADAU1373_PLL_CTRL5(x) (0x2d + (x) * 7) +#define ADAU1373_PLL_CTRL6(x) (0x2e + (x) * 7) +#define ADAU1373_PLL_CTRL7(x) (0x2f + (x) * 7) +#define ADAU1373_HEADDECT 0x36 +#define ADAU1373_ADC_DAC_STATUS 0x37 +#define ADAU1373_ADC_CTRL 0x3c +#define ADAU1373_DAI(x) (0x44 + (x)) +#define ADAU1373_CLK_SRC_DIV(x) (0x40 + (x) * 2) +#define ADAU1373_BCLKDIV(x) (0x47 + (x)) +#define ADAU1373_SRC_RATIOA(x) (0x4a + (x) * 2) +#define ADAU1373_SRC_RATIOB(x) (0x4b + (x) * 2) +#define ADAU1373_DEEMP_CTRL 0x50 +#define ADAU1373_SRC_DAI_CTRL(x) (0x51 + (x)) +#define ADAU1373_DIN_MIX_CTRL(x) (0x56 + (x)) +#define ADAU1373_DOUT_MIX_CTRL(x) (0x5b + (x)) +#define ADAU1373_DAI_PBL_VOL(x) (0x62 + (x) * 2) +#define ADAU1373_DAI_PBR_VOL(x) (0x63 + (x) * 2) +#define ADAU1373_DAI_RECL_VOL(x) (0x68 + (x) * 2) +#define ADAU1373_DAI_RECR_VOL(x) (0x69 + (x) * 2) +#define ADAU1373_DAC1_PBL_VOL 0x6e +#define ADAU1373_DAC1_PBR_VOL 0x6f +#define ADAU1373_DAC2_PBL_VOL 0x70 +#define ADAU1373_DAC2_PBR_VOL 0x71 +#define ADAU1373_ADC_RECL_VOL 0x72 +#define ADAU1373_ADC_RECR_VOL 0x73 +#define ADAU1373_DMIC_RECL_VOL 0x74 +#define ADAU1373_DMIC_RECR_VOL 0x75 +#define ADAU1373_VOL_GAIN1 0x76 +#define ADAU1373_VOL_GAIN2 0x77 +#define ADAU1373_VOL_GAIN3 0x78 +#define ADAU1373_HPF_CTRL 0x7d +#define ADAU1373_BASS1 0x7e +#define ADAU1373_BASS2 0x7f +#define ADAU1373_DRC(x) (0x80 + (x) * 0x10) +#define ADAU1373_3D_CTRL1 0xc0 +#define ADAU1373_3D_CTRL2 0xc1 +#define ADAU1373_FDSP_SEL1 0xdc +#define ADAU1373_FDSP_SEL2 0xdd +#define ADAU1373_FDSP_SEL3 0xde +#define ADAU1373_FDSP_SEL4 0xdf +#define ADAU1373_DIGMICCTRL 0xe2 +#define ADAU1373_DIGEN 0xeb +#define ADAU1373_SOFT_RESET 0xff + + +#define ADAU1373_PLL_CTRL6_DPLL_BYPASS BIT(1) +#define ADAU1373_PLL_CTRL6_PLL_EN BIT(0) + +#define ADAU1373_DAI_INVERT_BCLK BIT(7) +#define ADAU1373_DAI_MASTER BIT(6) +#define ADAU1373_DAI_INVERT_LRCLK BIT(4) +#define ADAU1373_DAI_WLEN_16 0x0 +#define ADAU1373_DAI_WLEN_20 0x4 +#define ADAU1373_DAI_WLEN_24 0x8 +#define ADAU1373_DAI_WLEN_32 0xc +#define ADAU1373_DAI_WLEN_MASK 0xc +#define ADAU1373_DAI_FORMAT_RIGHT_J 0x0 +#define ADAU1373_DAI_FORMAT_LEFT_J 0x1 +#define ADAU1373_DAI_FORMAT_I2S 0x2 +#define ADAU1373_DAI_FORMAT_DSP 0x3 + +#define ADAU1373_BCLKDIV_SOURCE BIT(5) +#define ADAU1373_BCLKDIV_32 0x03 +#define ADAU1373_BCLKDIV_64 0x02 +#define ADAU1373_BCLKDIV_128 0x01 +#define ADAU1373_BCLKDIV_256 0x00 + +#define ADAU1373_ADC_CTRL_PEAK_DETECT BIT(0) +#define ADAU1373_ADC_CTRL_RESET BIT(1) +#define ADAU1373_ADC_CTRL_RESET_FORCE BIT(2) + +#define ADAU1373_OUTPUT_CTRL_LDIFF BIT(3) +#define ADAU1373_OUTPUT_CTRL_LNFBEN BIT(2) + +#define ADAU1373_PWDN_CTRL3_PWR_EN BIT(0) + +#define ADAU1373_EP_CTRL_MICBIAS1_OFFSET 4 +#define ADAU1373_EP_CTRL_MICBIAS2_OFFSET 2 + +static const uint8_t adau1373_default_regs[] = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x00 */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x10 */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x20 */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, /* 0x30 */ + 0x00, 0x00, 0x00, 0x80, 0x00, 0x01, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x0a, 0x0a, 0x0a, 0x00, /* 0x40 */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x08, 0x08, 0x08, 0x00, 0x00, 0x00, 0x00, /* 0x50 */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x60 */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x70 */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x78, 0x18, 0x00, 0x00, 0x00, 0xc0, 0x00, 0x00, /* 0x80 */ + 0x00, 0xc0, 0x88, 0x7a, 0xdf, 0x20, 0x00, 0x00, + 0x78, 0x18, 0x00, 0x00, 0x00, 0xc0, 0x00, 0x00, /* 0x90 */ + 0x00, 0xc0, 0x88, 0x7a, 0xdf, 0x20, 0x00, 0x00, + 0x78, 0x18, 0x00, 0x00, 0x00, 0xc0, 0x00, 0x00, /* 0xa0 */ + 0x00, 0xc0, 0x88, 0x7a, 0xdf, 0x20, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, /* 0xb0 */ + 0xff, 0xff, 0xff, 0xff, 0xff, 0x1f, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xc0 */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xd0 */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, /* 0xe0 */ + 0x00, 0x1f, 0x0f, 0x00, 0x00, +}; + +static const unsigned int adau1373_out_tlv[] = { + TLV_DB_RANGE_HEAD(4), + 0, 7, TLV_DB_SCALE_ITEM(-7900, 400, 1), + 8, 15, TLV_DB_SCALE_ITEM(-4700, 300, 0), + 16, 23, TLV_DB_SCALE_ITEM(-2300, 200, 0), + 24, 31, TLV_DB_SCALE_ITEM(-700, 100, 0), +}; + +static const DECLARE_TLV_DB_MINMAX(adau1373_digital_tlv, -9563, 0); +static const DECLARE_TLV_DB_SCALE(adau1373_in_pga_tlv, -1300, 100, 1); +static const DECLARE_TLV_DB_SCALE(adau1373_ep_tlv, -600, 600, 1); + +static const DECLARE_TLV_DB_SCALE(adau1373_input_boost_tlv, 0, 2000, 0); +static const DECLARE_TLV_DB_SCALE(adau1373_gain_boost_tlv, 0, 600, 0); +static const DECLARE_TLV_DB_SCALE(adau1373_speaker_boost_tlv, 1200, 600, 0); + +static const char *adau1373_fdsp_sel_text[] = { + "None", + "Channel 1", + "Channel 2", + "Channel 3", + "Channel 4", + "Channel 5", +}; + +static const SOC_ENUM_SINGLE_DECL(adau1373_drc1_channel_enum, + ADAU1373_FDSP_SEL1, 4, adau1373_fdsp_sel_text); +static const SOC_ENUM_SINGLE_DECL(adau1373_drc2_channel_enum, + ADAU1373_FDSP_SEL1, 0, adau1373_fdsp_sel_text); +static const SOC_ENUM_SINGLE_DECL(adau1373_drc3_channel_enum, + ADAU1373_FDSP_SEL2, 0, adau1373_fdsp_sel_text); +static const SOC_ENUM_SINGLE_DECL(adau1373_hpf_channel_enum, + ADAU1373_FDSP_SEL3, 0, adau1373_fdsp_sel_text); +static const SOC_ENUM_SINGLE_DECL(adau1373_bass_channel_enum, + ADAU1373_FDSP_SEL4, 4, adau1373_fdsp_sel_text); + +static const char *adau1373_hpf_cutoff_text[] = { + "3.7Hz", "50Hz", "100Hz", "150Hz", "200Hz", "250Hz", "300Hz", "350Hz", + "400Hz", "450Hz", "500Hz", "550Hz", "600Hz", "650Hz", "700Hz", "750Hz", + "800Hz", +}; + +static const SOC_ENUM_SINGLE_DECL(adau1373_hpf_cutoff_enum, + ADAU1373_HPF_CTRL, 3, adau1373_hpf_cutoff_text); + +static const char *adau1373_bass_lpf_cutoff_text[] = { + "801Hz", "1001Hz", +}; + +static const char *adau1373_bass_clip_level_text[] = { + "0.125", "0.250", "0.370", "0.500", "0.625", "0.750", "0.875", +}; + +static const unsigned int adau1373_bass_clip_level_values[] = { + 1, 2, 3, 4, 5, 6, 7, +}; + +static const char *adau1373_bass_hpf_cutoff_text[] = { + "158Hz", "232Hz", "347Hz", "520Hz", +}; + +static const unsigned int adau1373_bass_tlv[] = { + TLV_DB_RANGE_HEAD(4), + 0, 2, TLV_DB_SCALE_ITEM(-600, 600, 1), + 3, 4, TLV_DB_SCALE_ITEM(950, 250, 0), + 5, 7, TLV_DB_SCALE_ITEM(1400, 150, 0), +}; + +static const SOC_ENUM_SINGLE_DECL(adau1373_bass_lpf_cutoff_enum, + ADAU1373_BASS1, 5, adau1373_bass_lpf_cutoff_text); + +static const SOC_VALUE_ENUM_SINGLE_DECL(adau1373_bass_clip_level_enum, + ADAU1373_BASS1, 2, 7, adau1373_bass_clip_level_text, + adau1373_bass_clip_level_values); + +static const SOC_ENUM_SINGLE_DECL(adau1373_bass_hpf_cutoff_enum, + ADAU1373_BASS1, 0, adau1373_bass_hpf_cutoff_text); + +static const char *adau1373_3d_level_text[] = { + "0%", "6.67%", "13.33%", "20%", "26.67%", "33.33%", + "40%", "46.67%", "53.33%", "60%", "66.67%", "73.33%", + "80%", "86.67", "99.33%", "100%" +}; + +static const char *adau1373_3d_cutoff_text[] = { + "No 3D", "0.03125 fs", "0.04583 fs", "0.075 fs", "0.11458 fs", + "0.16875 fs", "0.27083 fs" +}; + +static const SOC_ENUM_SINGLE_DECL(adau1373_3d_level_enum, + ADAU1373_3D_CTRL1, 4, adau1373_3d_level_text); +static const SOC_ENUM_SINGLE_DECL(adau1373_3d_cutoff_enum, + ADAU1373_3D_CTRL1, 0, adau1373_3d_cutoff_text); + +static const unsigned int adau1373_3d_tlv[] = { + TLV_DB_RANGE_HEAD(2), + 0, 0, TLV_DB_SCALE_ITEM(0, 0, 0), + 1, 7, TLV_DB_LINEAR_ITEM(-1800, -120), +}; + +static const char *adau1373_lr_mux_text[] = { + "Mute", + "Right Channel (L+R)", + "Left Channel (L+R)", + "Stereo", +}; + +static const SOC_ENUM_SINGLE_DECL(adau1373_lineout1_lr_mux_enum, + ADAU1373_OUTPUT_CTRL, 4, adau1373_lr_mux_text); +static const SOC_ENUM_SINGLE_DECL(adau1373_lineout2_lr_mux_enum, + ADAU1373_OUTPUT_CTRL, 6, adau1373_lr_mux_text); +static const SOC_ENUM_SINGLE_DECL(adau1373_speaker_lr_mux_enum, + ADAU1373_LS_CTRL, 4, adau1373_lr_mux_text); + +static const struct snd_kcontrol_new adau1373_controls[] = { + SOC_DOUBLE_R_TLV("AIF1 Capture Volume", ADAU1373_DAI_RECL_VOL(0), + ADAU1373_DAI_RECR_VOL(0), 0, 0xff, 1, adau1373_digital_tlv), + SOC_DOUBLE_R_TLV("AIF2 Capture Volume", ADAU1373_DAI_RECL_VOL(1), + ADAU1373_DAI_RECR_VOL(1), 0, 0xff, 1, adau1373_digital_tlv), + SOC_DOUBLE_R_TLV("AIF3 Capture Volume", ADAU1373_DAI_RECL_VOL(2), + ADAU1373_DAI_RECR_VOL(2), 0, 0xff, 1, adau1373_digital_tlv), + + SOC_DOUBLE_R_TLV("ADC Capture Volume", ADAU1373_ADC_RECL_VOL, + ADAU1373_ADC_RECR_VOL, 0, 0xff, 1, adau1373_digital_tlv), + SOC_DOUBLE_R_TLV("DMIC Capture Volume", ADAU1373_DMIC_RECL_VOL, + ADAU1373_DMIC_RECR_VOL, 0, 0xff, 1, adau1373_digital_tlv), + + SOC_DOUBLE_R_TLV("AIF1 Playback Volume", ADAU1373_DAI_PBL_VOL(0), + ADAU1373_DAI_PBR_VOL(0), 0, 0xff, 1, adau1373_digital_tlv), + SOC_DOUBLE_R_TLV("AIF2 Playback Volume", ADAU1373_DAI_PBL_VOL(1), + ADAU1373_DAI_PBR_VOL(1), 0, 0xff, 1, adau1373_digital_tlv), + SOC_DOUBLE_R_TLV("AIF3 Playback Volume", ADAU1373_DAI_PBL_VOL(2), + ADAU1373_DAI_PBR_VOL(2), 0, 0xff, 1, adau1373_digital_tlv), + + SOC_DOUBLE_R_TLV("DAC1 Playback Volume", ADAU1373_DAC1_PBL_VOL, + ADAU1373_DAC1_PBR_VOL, 0, 0xff, 1, adau1373_digital_tlv), + SOC_DOUBLE_R_TLV("DAC2 Playback Volume", ADAU1373_DAC2_PBL_VOL, + ADAU1373_DAC2_PBR_VOL, 0, 0xff, 1, adau1373_digital_tlv), + + SOC_DOUBLE_R_TLV("Lineout1 Playback Volume", ADAU1373_LLINE_OUT(0), + ADAU1373_RLINE_OUT(0), 0, 0x1f, 0, adau1373_out_tlv), + SOC_DOUBLE_R_TLV("Speaker Playback Volume", ADAU1373_LSPK_OUT, + ADAU1373_RSPK_OUT, 0, 0x1f, 0, adau1373_out_tlv), + SOC_DOUBLE_R_TLV("Headphone Playback Volume", ADAU1373_LHP_OUT, + ADAU1373_RHP_OUT, 0, 0x1f, 0, adau1373_out_tlv), + + SOC_DOUBLE_R_TLV("Input 1 Capture Volume", ADAU1373_AINL_CTRL(0), + ADAU1373_AINR_CTRL(0), 0, 0x1f, 0, adau1373_in_pga_tlv), + SOC_DOUBLE_R_TLV("Input 2 Capture Volume", ADAU1373_AINL_CTRL(1), + ADAU1373_AINR_CTRL(1), 0, 0x1f, 0, adau1373_in_pga_tlv), + SOC_DOUBLE_R_TLV("Input 3 Capture Volume", ADAU1373_AINL_CTRL(2), + ADAU1373_AINR_CTRL(2), 0, 0x1f, 0, adau1373_in_pga_tlv), + SOC_DOUBLE_R_TLV("Input 4 Capture Volume", ADAU1373_AINL_CTRL(3), + ADAU1373_AINR_CTRL(3), 0, 0x1f, 0, adau1373_in_pga_tlv), + + SOC_SINGLE_TLV("Earpiece Playback Volume", ADAU1373_EP_CTRL, 0, 3, 0, + adau1373_ep_tlv), + + SOC_DOUBLE_TLV("AIF3 Boost Playback Volume", ADAU1373_VOL_GAIN1, 4, 5, + 1, 0, adau1373_gain_boost_tlv), + SOC_DOUBLE_TLV("AIF2 Boost Playback Volume", ADAU1373_VOL_GAIN1, 2, 3, + 1, 0, adau1373_gain_boost_tlv), + SOC_DOUBLE_TLV("AIF1 Boost Playback Volume", ADAU1373_VOL_GAIN1, 0, 1, + 1, 0, adau1373_gain_boost_tlv), + SOC_DOUBLE_TLV("AIF3 Boost Capture Volume", ADAU1373_VOL_GAIN2, 4, 5, + 1, 0, adau1373_gain_boost_tlv), + SOC_DOUBLE_TLV("AIF2 Boost Capture Volume", ADAU1373_VOL_GAIN2, 2, 3, + 1, 0, adau1373_gain_boost_tlv), + SOC_DOUBLE_TLV("AIF1 Boost Capture Volume", ADAU1373_VOL_GAIN2, 0, 1, + 1, 0, adau1373_gain_boost_tlv), + SOC_DOUBLE_TLV("DMIC Boost Capture Volume", ADAU1373_VOL_GAIN3, 6, 7, + 1, 0, adau1373_gain_boost_tlv), + SOC_DOUBLE_TLV("ADC Boost Capture Volume", ADAU1373_VOL_GAIN3, 4, 5, + 1, 0, adau1373_gain_boost_tlv), + SOC_DOUBLE_TLV("DAC2 Boost Playback Volume", ADAU1373_VOL_GAIN3, 2, 3, + 1, 0, adau1373_gain_boost_tlv), + SOC_DOUBLE_TLV("DAC1 Boost Playback Volume", ADAU1373_VOL_GAIN3, 0, 1, + 1, 0, adau1373_gain_boost_tlv), + + SOC_DOUBLE_TLV("Input 1 Boost Capture Volume", ADAU1373_ADC_GAIN, 0, 4, + 1, 0, adau1373_input_boost_tlv), + SOC_DOUBLE_TLV("Input 2 Boost Capture Volume", ADAU1373_ADC_GAIN, 1, 5, + 1, 0, adau1373_input_boost_tlv), + SOC_DOUBLE_TLV("Input 3 Boost Capture Volume", ADAU1373_ADC_GAIN, 2, 6, + 1, 0, adau1373_input_boost_tlv), + SOC_DOUBLE_TLV("Input 4 Boost Capture Volume", ADAU1373_ADC_GAIN, 3, 7, + 1, 0, adau1373_input_boost_tlv), + + SOC_DOUBLE_TLV("Speaker Boost Playback Volume", ADAU1373_LS_CTRL, 2, 3, + 1, 0, adau1373_speaker_boost_tlv), + + SOC_ENUM("Lineout1 LR Mux", adau1373_lineout1_lr_mux_enum), + SOC_ENUM("Speaker LR Mux", adau1373_speaker_lr_mux_enum), + + SOC_ENUM("HPF Cutoff", adau1373_hpf_cutoff_enum), + SOC_DOUBLE("HPF Switch", ADAU1373_HPF_CTRL, 1, 0, 1, 0), + SOC_ENUM("HPF Channel", adau1373_hpf_channel_enum), + + SOC_ENUM("Bass HPF Cutoff", adau1373_bass_hpf_cutoff_enum), + SOC_VALUE_ENUM("Bass Clip Level Threshold", + adau1373_bass_clip_level_enum), + SOC_ENUM("Bass LPF Cutoff", adau1373_bass_lpf_cutoff_enum), + SOC_DOUBLE("Bass Playback Switch", ADAU1373_BASS2, 0, 1, 1, 0), + SOC_SINGLE_TLV("Bass Playback Volume", ADAU1373_BASS2, 2, 7, 0, + adau1373_bass_tlv), + SOC_ENUM("Bass Channel", adau1373_bass_channel_enum), + + SOC_ENUM("3D Freq", adau1373_3d_cutoff_enum), + SOC_ENUM("3D Level", adau1373_3d_level_enum), + SOC_SINGLE("3D Playback Switch", ADAU1373_3D_CTRL2, 0, 1, 0), + SOC_SINGLE_TLV("3D Playback Volume", ADAU1373_3D_CTRL2, 2, 7, 0, + adau1373_3d_tlv), + SOC_ENUM("3D Channel", adau1373_bass_channel_enum), + + SOC_SINGLE("Zero Cross Switch", ADAU1373_PWDN_CTRL3, 7, 1, 0), +}; + +static const struct snd_kcontrol_new adau1373_lineout2_controls[] = { + SOC_DOUBLE_R_TLV("Lineout2 Playback Volume", ADAU1373_LLINE_OUT(1), + ADAU1373_RLINE_OUT(1), 0, 0x1f, 0, adau1373_out_tlv), + SOC_ENUM("Lineout2 LR Mux", adau1373_lineout2_lr_mux_enum), +}; + +static const struct snd_kcontrol_new adau1373_drc_controls[] = { + SOC_ENUM("DRC1 Channel", adau1373_drc1_channel_enum), + SOC_ENUM("DRC2 Channel", adau1373_drc2_channel_enum), + SOC_ENUM("DRC3 Channel", adau1373_drc3_channel_enum), +}; + +static int adau1373_pll_event(struct snd_soc_dapm_widget *w, + struct snd_kcontrol *kcontrol, int event) +{ + struct snd_soc_codec *codec = w->codec; + unsigned int pll_id = w->name[3] - '1'; + unsigned int val; + + if (SND_SOC_DAPM_EVENT_ON(event)) + val = ADAU1373_PLL_CTRL6_PLL_EN; + else + val = 0; + + snd_soc_update_bits(codec, ADAU1373_PLL_CTRL6(pll_id), + ADAU1373_PLL_CTRL6_PLL_EN, val); + + if (SND_SOC_DAPM_EVENT_ON(event)) + mdelay(5); + + return 0; +} + +static const char *adau1373_decimator_text[] = { + "ADC", + "DMIC1", +}; + +static const struct soc_enum adau1373_decimator_enum = + SOC_ENUM_SINGLE(0, 0, 2, adau1373_decimator_text); + +static const struct snd_kcontrol_new adau1373_decimator_mux = + SOC_DAPM_ENUM_VIRT("Decimator Mux", adau1373_decimator_enum); + +static const struct snd_kcontrol_new adau1373_left_adc_mixer_controls[] = { + SOC_DAPM_SINGLE("DAC1 Switch", ADAU1373_LADC_MIXER, 4, 1, 0), + SOC_DAPM_SINGLE("Input 4 Switch", ADAU1373_LADC_MIXER, 3, 1, 0), + SOC_DAPM_SINGLE("Input 3 Switch", ADAU1373_LADC_MIXER, 2, 1, 0), + SOC_DAPM_SINGLE("Input 2 Switch", ADAU1373_LADC_MIXER, 1, 1, 0), + SOC_DAPM_SINGLE("Input 1 Switch", ADAU1373_LADC_MIXER, 0, 1, 0), +}; + +static const struct snd_kcontrol_new adau1373_right_adc_mixer_controls[] = { + SOC_DAPM_SINGLE("DAC1 Switch", ADAU1373_RADC_MIXER, 4, 1, 0), + SOC_DAPM_SINGLE("Input 4 Switch", ADAU1373_RADC_MIXER, 3, 1, 0), + SOC_DAPM_SINGLE("Input 3 Switch", ADAU1373_RADC_MIXER, 2, 1, 0), + SOC_DAPM_SINGLE("Input 2 Switch", ADAU1373_RADC_MIXER, 1, 1, 0), + SOC_DAPM_SINGLE("Input 1 Switch", ADAU1373_RADC_MIXER, 0, 1, 0), +}; + +#define DECLARE_ADAU1373_OUTPUT_MIXER_CTRLS(_name, _reg) \ +const struct snd_kcontrol_new _name[] = { \ + SOC_DAPM_SINGLE("Left DAC2 Switch", _reg, 7, 1, 0), \ + SOC_DAPM_SINGLE("Right DAC2 Switch", _reg, 6, 1, 0), \ + SOC_DAPM_SINGLE("Left DAC1 Switch", _reg, 5, 1, 0), \ + SOC_DAPM_SINGLE("Right DAC1 Switch", _reg, 4, 1, 0), \ + SOC_DAPM_SINGLE("Input 4 Bypass Switch", _reg, 3, 1, 0), \ + SOC_DAPM_SINGLE("Input 3 Bypass Switch", _reg, 2, 1, 0), \ + SOC_DAPM_SINGLE("Input 2 Bypass Switch", _reg, 1, 1, 0), \ + SOC_DAPM_SINGLE("Input 1 Bypass Switch", _reg, 0, 1, 0), \ +} + +static DECLARE_ADAU1373_OUTPUT_MIXER_CTRLS(adau1373_left_line1_mixer_controls, + ADAU1373_LLINE1_MIX); +static DECLARE_ADAU1373_OUTPUT_MIXER_CTRLS(adau1373_right_line1_mixer_controls, + ADAU1373_RLINE1_MIX); +static DECLARE_ADAU1373_OUTPUT_MIXER_CTRLS(adau1373_left_line2_mixer_controls, + ADAU1373_LLINE2_MIX); +static DECLARE_ADAU1373_OUTPUT_MIXER_CTRLS(adau1373_right_line2_mixer_controls, + ADAU1373_RLINE2_MIX); +static DECLARE_ADAU1373_OUTPUT_MIXER_CTRLS(adau1373_left_spk_mixer_controls, + ADAU1373_LSPK_MIX); +static DECLARE_ADAU1373_OUTPUT_MIXER_CTRLS(adau1373_right_spk_mixer_controls, + ADAU1373_RSPK_MIX); +static DECLARE_ADAU1373_OUTPUT_MIXER_CTRLS(adau1373_ep_mixer_controls, + ADAU1373_EP_MIX); + +static const struct snd_kcontrol_new adau1373_left_hp_mixer_controls[] = { + SOC_DAPM_SINGLE("Left DAC1 Switch", ADAU1373_LHP_MIX, 5, 1, 0), + SOC_DAPM_SINGLE("Left DAC2 Switch", ADAU1373_LHP_MIX, 4, 1, 0), + SOC_DAPM_SINGLE("Input 4 Bypass Switch", ADAU1373_LHP_MIX, 3, 1, 0), + SOC_DAPM_SINGLE("Input 3 Bypass Switch", ADAU1373_LHP_MIX, 2, 1, 0), + SOC_DAPM_SINGLE("Input 2 Bypass Switch", ADAU1373_LHP_MIX, 1, 1, 0), + SOC_DAPM_SINGLE("Input 1 Bypass Switch", ADAU1373_LHP_MIX, 0, 1, 0), +}; + +static const struct snd_kcontrol_new adau1373_right_hp_mixer_controls[] = { + SOC_DAPM_SINGLE("Right DAC1 Switch", ADAU1373_RHP_MIX, 5, 1, 0), + SOC_DAPM_SINGLE("Right DAC2 Switch", ADAU1373_RHP_MIX, 4, 1, 0), + SOC_DAPM_SINGLE("Input 4 Bypass Switch", ADAU1373_RHP_MIX, 3, 1, 0), + SOC_DAPM_SINGLE("Input 3 Bypass Switch", ADAU1373_RHP_MIX, 2, 1, 0), + SOC_DAPM_SINGLE("Input 2 Bypass Switch", ADAU1373_RHP_MIX, 1, 1, 0), + SOC_DAPM_SINGLE("Input 1 Bypass Switch", ADAU1373_RHP_MIX, 0, 1, 0), +}; + +#define DECLARE_ADAU1373_DSP_CHANNEL_MIXER_CTRLS(_name, _reg) \ +const struct snd_kcontrol_new _name[] = { \ + SOC_DAPM_SINGLE("DMIC2 Swapped Switch", _reg, 6, 1, 0), \ + SOC_DAPM_SINGLE("DMIC2 Switch", _reg, 5, 1, 0), \ + SOC_DAPM_SINGLE("ADC/DMIC1 Swapped Switch", _reg, 4, 1, 0), \ + SOC_DAPM_SINGLE("ADC/DMIC1 Switch", _reg, 3, 1, 0), \ + SOC_DAPM_SINGLE("AIF3 Switch", _reg, 2, 1, 0), \ + SOC_DAPM_SINGLE("AIF2 Switch", _reg, 1, 1, 0), \ + SOC_DAPM_SINGLE("AIF1 Switch", _reg, 0, 1, 0), \ +} + +static DECLARE_ADAU1373_DSP_CHANNEL_MIXER_CTRLS(adau1373_dsp_channel1_mixer_controls, + ADAU1373_DIN_MIX_CTRL(0)); +static DECLARE_ADAU1373_DSP_CHANNEL_MIXER_CTRLS(adau1373_dsp_channel2_mixer_controls, + ADAU1373_DIN_MIX_CTRL(1)); +static DECLARE_ADAU1373_DSP_CHANNEL_MIXER_CTRLS(adau1373_dsp_channel3_mixer_controls, + ADAU1373_DIN_MIX_CTRL(2)); +static DECLARE_ADAU1373_DSP_CHANNEL_MIXER_CTRLS(adau1373_dsp_channel4_mixer_controls, + ADAU1373_DIN_MIX_CTRL(3)); +static DECLARE_ADAU1373_DSP_CHANNEL_MIXER_CTRLS(adau1373_dsp_channel5_mixer_controls, + ADAU1373_DIN_MIX_CTRL(4)); + +#define DECLARE_ADAU1373_DSP_OUTPUT_MIXER_CTRLS(_name, _reg) \ +const struct snd_kcontrol_new _name[] = { \ + SOC_DAPM_SINGLE("DSP Channel5 Switch", _reg, 4, 1, 0), \ + SOC_DAPM_SINGLE("DSP Channel4 Switch", _reg, 3, 1, 0), \ + SOC_DAPM_SINGLE("DSP Channel3 Switch", _reg, 2, 1, 0), \ + SOC_DAPM_SINGLE("DSP Channel2 Switch", _reg, 1, 1, 0), \ + SOC_DAPM_SINGLE("DSP Channel1 Switch", _reg, 0, 1, 0), \ +} + +static DECLARE_ADAU1373_DSP_OUTPUT_MIXER_CTRLS(adau1373_aif1_mixer_controls, + ADAU1373_DOUT_MIX_CTRL(0)); +static DECLARE_ADAU1373_DSP_OUTPUT_MIXER_CTRLS(adau1373_aif2_mixer_controls, + ADAU1373_DOUT_MIX_CTRL(1)); +static DECLARE_ADAU1373_DSP_OUTPUT_MIXER_CTRLS(adau1373_aif3_mixer_controls, + ADAU1373_DOUT_MIX_CTRL(2)); +static DECLARE_ADAU1373_DSP_OUTPUT_MIXER_CTRLS(adau1373_dac1_mixer_controls, + ADAU1373_DOUT_MIX_CTRL(3)); +static DECLARE_ADAU1373_DSP_OUTPUT_MIXER_CTRLS(adau1373_dac2_mixer_controls, + ADAU1373_DOUT_MIX_CTRL(4)); + +static const struct snd_soc_dapm_widget adau1373_dapm_widgets[] = { + /* Datasheet claims Left ADC is bit 6 and Right ADC is bit 7, but that + * doesn't seem to be the case. */ + SND_SOC_DAPM_ADC("Left ADC", NULL, ADAU1373_PWDN_CTRL1, 7, 0), + SND_SOC_DAPM_ADC("Right ADC", NULL, ADAU1373_PWDN_CTRL1, 6, 0), + + SND_SOC_DAPM_ADC("DMIC1", NULL, ADAU1373_DIGMICCTRL, 0, 0), + SND_SOC_DAPM_ADC("DMIC2", NULL, ADAU1373_DIGMICCTRL, 2, 0), + + SND_SOC_DAPM_VIRT_MUX("Decimator Mux", SND_SOC_NOPM, 0, 0, + &adau1373_decimator_mux), + + SND_SOC_DAPM_SUPPLY("MICBIAS2", ADAU1373_PWDN_CTRL1, 5, 0, NULL, 0), + SND_SOC_DAPM_SUPPLY("MICBIAS1", ADAU1373_PWDN_CTRL1, 4, 0, NULL, 0), + + SND_SOC_DAPM_PGA("IN4PGA", ADAU1373_PWDN_CTRL1, 3, 0, NULL, 0), + SND_SOC_DAPM_PGA("IN3PGA", ADAU1373_PWDN_CTRL1, 2, 0, NULL, 0), + SND_SOC_DAPM_PGA("IN2PGA", ADAU1373_PWDN_CTRL1, 1, 0, NULL, 0), + SND_SOC_DAPM_PGA("IN1PGA", ADAU1373_PWDN_CTRL1, 0, 0, NULL, 0), + + SND_SOC_DAPM_DAC("Left DAC2", NULL, ADAU1373_PWDN_CTRL2, 7, 0), + SND_SOC_DAPM_DAC("Right DAC2", NULL, ADAU1373_PWDN_CTRL2, 6, 0), + SND_SOC_DAPM_DAC("Left DAC1", NULL, ADAU1373_PWDN_CTRL2, 5, 0), + SND_SOC_DAPM_DAC("Right DAC1", NULL, ADAU1373_PWDN_CTRL2, 4, 0), + + SOC_MIXER_ARRAY("Left ADC Mixer", SND_SOC_NOPM, 0, 0, + adau1373_left_adc_mixer_controls), + SOC_MIXER_ARRAY("Right ADC Mixer", SND_SOC_NOPM, 0, 0, + adau1373_right_adc_mixer_controls), + + SOC_MIXER_ARRAY("Left Lineout2 Mixer", ADAU1373_PWDN_CTRL2, 3, 0, + adau1373_left_line2_mixer_controls), + SOC_MIXER_ARRAY("Right Lineout2 Mixer", ADAU1373_PWDN_CTRL2, 2, 0, + adau1373_right_line2_mixer_controls), + SOC_MIXER_ARRAY("Left Lineout1 Mixer", ADAU1373_PWDN_CTRL2, 1, 0, + adau1373_left_line1_mixer_controls), + SOC_MIXER_ARRAY("Right Lineout1 Mixer", ADAU1373_PWDN_CTRL2, 0, 0, + adau1373_right_line1_mixer_controls), + + SOC_MIXER_ARRAY("Earpiece Mixer", ADAU1373_PWDN_CTRL3, 4, 0, + adau1373_ep_mixer_controls), + SOC_MIXER_ARRAY("Left Speaker Mixer", ADAU1373_PWDN_CTRL3, 3, 0, + adau1373_left_spk_mixer_controls), + SOC_MIXER_ARRAY("Right Speaker Mixer", ADAU1373_PWDN_CTRL3, 2, 0, + adau1373_right_spk_mixer_controls), + SOC_MIXER_ARRAY("Left Headphone Mixer", SND_SOC_NOPM, 0, 0, + adau1373_left_hp_mixer_controls), + SOC_MIXER_ARRAY("Right Headphone Mixer", SND_SOC_NOPM, 0, 0, + adau1373_right_hp_mixer_controls), + SND_SOC_DAPM_SUPPLY("Headphone Enable", ADAU1373_PWDN_CTRL3, 1, 0, + NULL, 0), + + SND_SOC_DAPM_SUPPLY("AIF1 CLK", ADAU1373_SRC_DAI_CTRL(0), 0, 0, + NULL, 0), + SND_SOC_DAPM_SUPPLY("AIF2 CLK", ADAU1373_SRC_DAI_CTRL(1), 0, 0, + NULL, 0), + SND_SOC_DAPM_SUPPLY("AIF3 CLK", ADAU1373_SRC_DAI_CTRL(2), 0, 0, + NULL, 0), + SND_SOC_DAPM_SUPPLY("AIF1 IN SRC", ADAU1373_SRC_DAI_CTRL(0), 2, 0, + NULL, 0), + SND_SOC_DAPM_SUPPLY("AIF1 OUT SRC", ADAU1373_SRC_DAI_CTRL(0), 1, 0, + NULL, 0), + SND_SOC_DAPM_SUPPLY("AIF2 IN SRC", ADAU1373_SRC_DAI_CTRL(1), 2, 0, + NULL, 0), + SND_SOC_DAPM_SUPPLY("AIF2 OUT SRC", ADAU1373_SRC_DAI_CTRL(1), 1, 0, + NULL, 0), + SND_SOC_DAPM_SUPPLY("AIF3 IN SRC", ADAU1373_SRC_DAI_CTRL(2), 2, 0, + NULL, 0), + SND_SOC_DAPM_SUPPLY("AIF3 OUT SRC", ADAU1373_SRC_DAI_CTRL(2), 1, 0, + NULL, 0), + + SND_SOC_DAPM_AIF_IN("AIF1 IN", "AIF1 Playback", 0, SND_SOC_NOPM, 0, 0), + SND_SOC_DAPM_AIF_OUT("AIF1 OUT", "AIF1 Capture", 0, SND_SOC_NOPM, 0, 0), + SND_SOC_DAPM_AIF_IN("AIF2 IN", "AIF2 Playback", 0, SND_SOC_NOPM, 0, 0), + SND_SOC_DAPM_AIF_OUT("AIF2 OUT", "AIF2 Capture", 0, SND_SOC_NOPM, 0, 0), + SND_SOC_DAPM_AIF_IN("AIF3 IN", "AIF3 Playback", 0, SND_SOC_NOPM, 0, 0), + SND_SOC_DAPM_AIF_OUT("AIF3 OUT", "AIF3 Capture", 0, SND_SOC_NOPM, 0, 0), + + SOC_MIXER_ARRAY("DSP Channel1 Mixer", SND_SOC_NOPM, 0, 0, + adau1373_dsp_channel1_mixer_controls), + SOC_MIXER_ARRAY("DSP Channel2 Mixer", SND_SOC_NOPM, 0, 0, + adau1373_dsp_channel2_mixer_controls), + SOC_MIXER_ARRAY("DSP Channel3 Mixer", SND_SOC_NOPM, 0, 0, + adau1373_dsp_channel3_mixer_controls), + SOC_MIXER_ARRAY("DSP Channel4 Mixer", SND_SOC_NOPM, 0, 0, + adau1373_dsp_channel4_mixer_controls), + SOC_MIXER_ARRAY("DSP Channel5 Mixer", SND_SOC_NOPM, 0, 0, + adau1373_dsp_channel5_mixer_controls), + + SOC_MIXER_ARRAY("AIF1 Mixer", SND_SOC_NOPM, 0, 0, + adau1373_aif1_mixer_controls), + SOC_MIXER_ARRAY("AIF2 Mixer", SND_SOC_NOPM, 0, 0, + adau1373_aif2_mixer_controls), + SOC_MIXER_ARRAY("AIF3 Mixer", SND_SOC_NOPM, 0, 0, + adau1373_aif3_mixer_controls), + SOC_MIXER_ARRAY("DAC1 Mixer", SND_SOC_NOPM, 0, 0, + adau1373_dac1_mixer_controls), + SOC_MIXER_ARRAY("DAC2 Mixer", SND_SOC_NOPM, 0, 0, + adau1373_dac2_mixer_controls), + + SND_SOC_DAPM_SUPPLY("DSP", ADAU1373_DIGEN, 4, 0, NULL, 0), + SND_SOC_DAPM_SUPPLY("Recording Engine B", ADAU1373_DIGEN, 3, 0, NULL, 0), + SND_SOC_DAPM_SUPPLY("Recording Engine A", ADAU1373_DIGEN, 2, 0, NULL, 0), + SND_SOC_DAPM_SUPPLY("Playback Engine B", ADAU1373_DIGEN, 1, 0, NULL, 0), + SND_SOC_DAPM_SUPPLY("Playback Engine A", ADAU1373_DIGEN, 0, 0, NULL, 0), + + SND_SOC_DAPM_SUPPLY("PLL1", SND_SOC_NOPM, 0, 0, adau1373_pll_event, + SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD), + SND_SOC_DAPM_SUPPLY("PLL2", SND_SOC_NOPM, 0, 0, adau1373_pll_event, + SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD), + SND_SOC_DAPM_SUPPLY("SYSCLK1", ADAU1373_CLK_SRC_DIV(0), 7, 0, NULL, 0), + SND_SOC_DAPM_SUPPLY("SYSCLK2", ADAU1373_CLK_SRC_DIV(1), 7, 0, NULL, 0), + + SND_SOC_DAPM_INPUT("AIN1L"), + SND_SOC_DAPM_INPUT("AIN1R"), + SND_SOC_DAPM_INPUT("AIN2L"), + SND_SOC_DAPM_INPUT("AIN2R"), + SND_SOC_DAPM_INPUT("AIN3L"), + SND_SOC_DAPM_INPUT("AIN3R"), + SND_SOC_DAPM_INPUT("AIN4L"), + SND_SOC_DAPM_INPUT("AIN4R"), + + SND_SOC_DAPM_INPUT("DMIC1DAT"), + SND_SOC_DAPM_INPUT("DMIC2DAT"), + + SND_SOC_DAPM_OUTPUT("LOUT1L"), + SND_SOC_DAPM_OUTPUT("LOUT1R"), + SND_SOC_DAPM_OUTPUT("LOUT2L"), + SND_SOC_DAPM_OUTPUT("LOUT2R"), + SND_SOC_DAPM_OUTPUT("HPL"), + SND_SOC_DAPM_OUTPUT("HPR"), + SND_SOC_DAPM_OUTPUT("SPKL"), + SND_SOC_DAPM_OUTPUT("SPKR"), + SND_SOC_DAPM_OUTPUT("EP"), +}; + +static int adau1373_check_aif_clk(struct snd_soc_dapm_widget *source, + struct snd_soc_dapm_widget *sink) +{ + struct snd_soc_codec *codec = source->codec; + struct adau1373 *adau1373 = snd_soc_codec_get_drvdata(codec); + unsigned int dai; + const char *clk; + + dai = sink->name[3] - '1'; + + if (!adau1373->dais[dai].master) + return 0; + + if (adau1373->dais[dai].clk_src == ADAU1373_CLK_SRC_PLL1) + clk = "SYSCLK1"; + else + clk = "SYSCLK2"; + + return strcmp(source->name, clk) == 0; +} + +static int adau1373_check_src(struct snd_soc_dapm_widget *source, + struct snd_soc_dapm_widget *sink) +{ + struct snd_soc_codec *codec = source->codec; + struct adau1373 *adau1373 = snd_soc_codec_get_drvdata(codec); + unsigned int dai; + + dai = sink->name[3] - '1'; + + return adau1373->dais[dai].enable_src; +} + +#define DSP_CHANNEL_MIXER_ROUTES(_sink) \ + { _sink, "DMIC2 Swapped Switch", "DMIC2" }, \ + { _sink, "DMIC2 Switch", "DMIC2" }, \ + { _sink, "ADC/DMIC1 Swapped Switch", "Decimator Mux" }, \ + { _sink, "ADC/DMIC1 Switch", "Decimator Mux" }, \ + { _sink, "AIF1 Switch", "AIF1 IN" }, \ + { _sink, "AIF2 Switch", "AIF2 IN" }, \ + { _sink, "AIF3 Switch", "AIF3 IN" } + +#define DSP_OUTPUT_MIXER_ROUTES(_sink) \ + { _sink, "DSP Channel1 Switch", "DSP Channel1 Mixer" }, \ + { _sink, "DSP Channel2 Switch", "DSP Channel2 Mixer" }, \ + { _sink, "DSP Channel3 Switch", "DSP Channel3 Mixer" }, \ + { _sink, "DSP Channel4 Switch", "DSP Channel4 Mixer" }, \ + { _sink, "DSP Channel5 Switch", "DSP Channel5 Mixer" } + +#define LEFT_OUTPUT_MIXER_ROUTES(_sink) \ + { _sink, "Right DAC2 Switch", "Right DAC2" }, \ + { _sink, "Left DAC2 Switch", "Left DAC2" }, \ + { _sink, "Right DAC1 Switch", "Right DAC1" }, \ + { _sink, "Left DAC1 Switch", "Left DAC1" }, \ + { _sink, "Input 1 Bypass Switch", "IN1PGA" }, \ + { _sink, "Input 2 Bypass Switch", "IN2PGA" }, \ + { _sink, "Input 3 Bypass Switch", "IN3PGA" }, \ + { _sink, "Input 4 Bypass Switch", "IN4PGA" } + +#define RIGHT_OUTPUT_MIXER_ROUTES(_sink) \ + { _sink, "Right DAC2 Switch", "Right DAC2" }, \ + { _sink, "Left DAC2 Switch", "Left DAC2" }, \ + { _sink, "Right DAC1 Switch", "Right DAC1" }, \ + { _sink, "Left DAC1 Switch", "Left DAC1" }, \ + { _sink, "Input 1 Bypass Switch", "IN1PGA" }, \ + { _sink, "Input 2 Bypass Switch", "IN2PGA" }, \ + { _sink, "Input 3 Bypass Switch", "IN3PGA" }, \ + { _sink, "Input 4 Bypass Switch", "IN4PGA" } + +static const struct snd_soc_dapm_route adau1373_dapm_routes[] = { + { "Left ADC Mixer", "DAC1 Switch", "Left DAC1" }, + { "Left ADC Mixer", "Input 1 Switch", "IN1PGA" }, + { "Left ADC Mixer", "Input 2 Switch", "IN2PGA" }, + { "Left ADC Mixer", "Input 3 Switch", "IN3PGA" }, + { "Left ADC Mixer", "Input 4 Switch", "IN4PGA" }, + + { "Right ADC Mixer", "DAC1 Switch", "Right DAC1" }, + { "Right ADC Mixer", "Input 1 Switch", "IN1PGA" }, + { "Right ADC Mixer", "Input 2 Switch", "IN2PGA" }, + { "Right ADC Mixer", "Input 3 Switch", "IN3PGA" }, + { "Right ADC Mixer", "Input 4 Switch", "IN4PGA" }, + + { "Left ADC", NULL, "Left ADC Mixer" }, + { "Right ADC", NULL, "Right ADC Mixer" }, + + { "Decimator Mux", "ADC", "Left ADC" }, + { "Decimator Mux", "ADC", "Right ADC" }, + { "Decimator Mux", "DMIC1", "DMIC1" }, + + DSP_CHANNEL_MIXER_ROUTES("DSP Channel1 Mixer"), + DSP_CHANNEL_MIXER_ROUTES("DSP Channel2 Mixer"), + DSP_CHANNEL_MIXER_ROUTES("DSP Channel3 Mixer"), + DSP_CHANNEL_MIXER_ROUTES("DSP Channel4 Mixer"), + DSP_CHANNEL_MIXER_ROUTES("DSP Channel5 Mixer"), + + DSP_OUTPUT_MIXER_ROUTES("AIF1 Mixer"), + DSP_OUTPUT_MIXER_ROUTES("AIF2 Mixer"), + DSP_OUTPUT_MIXER_ROUTES("AIF3 Mixer"), + DSP_OUTPUT_MIXER_ROUTES("DAC1 Mixer"), + DSP_OUTPUT_MIXER_ROUTES("DAC2 Mixer"), + + { "AIF1 OUT", NULL, "AIF1 Mixer" }, + { "AIF2 OUT", NULL, "AIF2 Mixer" }, + { "AIF3 OUT", NULL, "AIF3 Mixer" }, + { "Left DAC1", NULL, "DAC1 Mixer" }, + { "Right DAC1", NULL, "DAC1 Mixer" }, + { "Left DAC2", NULL, "DAC2 Mixer" }, + { "Right DAC2", NULL, "DAC2 Mixer" }, + + LEFT_OUTPUT_MIXER_ROUTES("Left Lineout1 Mixer"), + RIGHT_OUTPUT_MIXER_ROUTES("Right Lineout1 Mixer"), + LEFT_OUTPUT_MIXER_ROUTES("Left Lineout2 Mixer"), + RIGHT_OUTPUT_MIXER_ROUTES("Right Lineout2 Mixer"), + LEFT_OUTPUT_MIXER_ROUTES("Left Speaker Mixer"), + RIGHT_OUTPUT_MIXER_ROUTES("Right Speaker Mixer"), + + { "Left Headphone Mixer", "Left DAC2 Switch", "Left DAC2" }, + { "Left Headphone Mixer", "Left DAC1 Switch", "Left DAC1" }, + { "Left Headphone Mixer", "Input 1 Bypass Switch", "IN1PGA" }, + { "Left Headphone Mixer", "Input 2 Bypass Switch", "IN2PGA" }, + { "Left Headphone Mixer", "Input 3 Bypass Switch", "IN3PGA" }, + { "Left Headphone Mixer", "Input 4 Bypass Switch", "IN4PGA" }, + { "Right Headphone Mixer", "Right DAC2 Switch", "Right DAC2" }, + { "Right Headphone Mixer", "Right DAC1 Switch", "Right DAC1" }, + { "Right Headphone Mixer", "Input 1 Bypass Switch", "IN1PGA" }, + { "Right Headphone Mixer", "Input 2 Bypass Switch", "IN2PGA" }, + { "Right Headphone Mixer", "Input 3 Bypass Switch", "IN3PGA" }, + { "Right Headphone Mixer", "Input 4 Bypass Switch", "IN4PGA" }, + + { "Left Headphone Mixer", NULL, "Headphone Enable" }, + { "Right Headphone Mixer", NULL, "Headphone Enable" }, + + { "Earpiece Mixer", "Right DAC2 Switch", "Right DAC2" }, + { "Earpiece Mixer", "Left DAC2 Switch", "Left DAC2" }, + { "Earpiece Mixer", "Right DAC1 Switch", "Right DAC1" }, + { "Earpiece Mixer", "Left DAC1 Switch", "Left DAC1" }, + { "Earpiece Mixer", "Input 1 Bypass Switch", "IN1PGA" }, + { "Earpiece Mixer", "Input 2 Bypass Switch", "IN2PGA" }, + { "Earpiece Mixer", "Input 3 Bypass Switch", "IN3PGA" }, + { "Earpiece Mixer", "Input 4 Bypass Switch", "IN4PGA" }, + + { "LOUT1L", NULL, "Left Lineout1 Mixer" }, + { "LOUT1R", NULL, "Right Lineout1 Mixer" }, + { "LOUT2L", NULL, "Left Lineout2 Mixer" }, + { "LOUT2R", NULL, "Right Lineout2 Mixer" }, + { "SPKL", NULL, "Left Speaker Mixer" }, + { "SPKR", NULL, "Right Speaker Mixer" }, + { "HPL", NULL, "Left Headphone Mixer" }, + { "HPR", NULL, "Right Headphone Mixer" }, + { "EP", NULL, "Earpiece Mixer" }, + + { "IN1PGA", NULL, "AIN1L" }, + { "IN2PGA", NULL, "AIN2L" }, + { "IN3PGA", NULL, "AIN3L" }, + { "IN4PGA", NULL, "AIN4L" }, + { "IN1PGA", NULL, "AIN1R" }, + { "IN2PGA", NULL, "AIN2R" }, + { "IN3PGA", NULL, "AIN3R" }, + { "IN4PGA", NULL, "AIN4R" }, + + { "SYSCLK1", NULL, "PLL1" }, + { "SYSCLK2", NULL, "PLL2" }, + + { "Left DAC1", NULL, "SYSCLK1" }, + { "Right DAC1", NULL, "SYSCLK1" }, + { "Left DAC2", NULL, "SYSCLK1" }, + { "Right DAC2", NULL, "SYSCLK1" }, + { "Left ADC", NULL, "SYSCLK1" }, + { "Right ADC", NULL, "SYSCLK1" }, + + { "DSP", NULL, "SYSCLK1" }, + + { "AIF1 Mixer", NULL, "DSP" }, + { "AIF2 Mixer", NULL, "DSP" }, + { "AIF3 Mixer", NULL, "DSP" }, + { "DAC1 Mixer", NULL, "DSP" }, + { "DAC2 Mixer", NULL, "DSP" }, + { "DAC1 Mixer", NULL, "Playback Engine A" }, + { "DAC2 Mixer", NULL, "Playback Engine B" }, + { "Left ADC Mixer", NULL, "Recording Engine A" }, + { "Right ADC Mixer", NULL, "Recording Engine A" }, + + { "AIF1 CLK", NULL, "SYSCLK1", adau1373_check_aif_clk }, + { "AIF2 CLK", NULL, "SYSCLK1", adau1373_check_aif_clk }, + { "AIF3 CLK", NULL, "SYSCLK1", adau1373_check_aif_clk }, + { "AIF1 CLK", NULL, "SYSCLK2", adau1373_check_aif_clk }, + { "AIF2 CLK", NULL, "SYSCLK2", adau1373_check_aif_clk }, + { "AIF3 CLK", NULL, "SYSCLK2", adau1373_check_aif_clk }, + + { "AIF1 IN", NULL, "AIF1 CLK" }, + { "AIF1 OUT", NULL, "AIF1 CLK" }, + { "AIF2 IN", NULL, "AIF2 CLK" }, + { "AIF2 OUT", NULL, "AIF2 CLK" }, + { "AIF3 IN", NULL, "AIF3 CLK" }, + { "AIF3 OUT", NULL, "AIF3 CLK" }, + { "AIF1 IN", NULL, "AIF1 IN SRC", adau1373_check_src }, + { "AIF1 OUT", NULL, "AIF1 OUT SRC", adau1373_check_src }, + { "AIF2 IN", NULL, "AIF2 IN SRC", adau1373_check_src }, + { "AIF2 OUT", NULL, "AIF2 OUT SRC", adau1373_check_src }, + { "AIF3 IN", NULL, "AIF3 IN SRC", adau1373_check_src }, + { "AIF3 OUT", NULL, "AIF3 OUT SRC", adau1373_check_src }, + + { "DMIC1", NULL, "DMIC1DAT" }, + { "DMIC1", NULL, "SYSCLK1" }, + { "DMIC1", NULL, "Recording Engine A" }, + { "DMIC2", NULL, "DMIC2DAT" }, + { "DMIC2", NULL, "SYSCLK1" }, + { "DMIC2", NULL, "Recording Engine B" }, +}; + +static int adau1373_hw_params(struct snd_pcm_substream *substream, + struct snd_pcm_hw_params *params, struct snd_soc_dai *dai) +{ + struct snd_soc_codec *codec = dai->codec; + struct adau1373 *adau1373 = snd_soc_codec_get_drvdata(codec); + struct adau1373_dai *adau1373_dai = &adau1373->dais[dai->id]; + unsigned int div; + unsigned int freq; + unsigned int ctrl; + + freq = adau1373_dai->sysclk; + + if (freq % params_rate(params) != 0) + return -EINVAL; + + switch (freq / params_rate(params)) { + case 1024: /* sysclk / 256 */ + div = 0; + break; + case 1536: /* 2/3 sysclk / 256 */ + div = 1; + break; + case 2048: /* 1/2 sysclk / 256 */ + div = 2; + break; + case 3072: /* 1/3 sysclk / 256 */ + div = 3; + break; + case 4096: /* 1/4 sysclk / 256 */ + div = 4; + break; + case 6144: /* 1/6 sysclk / 256 */ + div = 5; + break; + case 5632: /* 2/11 sysclk / 256 */ + div = 6; + break; + default: + return -EINVAL; + } + + adau1373_dai->enable_src = (div != 0); + + snd_soc_update_bits(codec, ADAU1373_BCLKDIV(dai->id), + ~ADAU1373_BCLKDIV_SOURCE, (div << 2) | ADAU1373_BCLKDIV_64); + + switch (params_format(params)) { + case SNDRV_PCM_FORMAT_S16_LE: + ctrl = ADAU1373_DAI_WLEN_16; + break; + case SNDRV_PCM_FORMAT_S20_3LE: + ctrl = ADAU1373_DAI_WLEN_20; + break; + case SNDRV_PCM_FORMAT_S24_LE: + ctrl = ADAU1373_DAI_WLEN_24; + break; + case SNDRV_PCM_FORMAT_S32_LE: + ctrl = ADAU1373_DAI_WLEN_32; + break; + default: + return -EINVAL; + } + + return snd_soc_update_bits(codec, ADAU1373_DAI(dai->id), + ADAU1373_DAI_WLEN_MASK, ctrl); +} + +static int adau1373_set_dai_fmt(struct snd_soc_dai *dai, unsigned int fmt) +{ + struct snd_soc_codec *codec = dai->codec; + struct adau1373 *adau1373 = snd_soc_codec_get_drvdata(codec); + struct adau1373_dai *adau1373_dai = &adau1373->dais[dai->id]; + unsigned int ctrl; + + switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { + case SND_SOC_DAIFMT_CBM_CFM: + ctrl = ADAU1373_DAI_MASTER; + adau1373_dai->master = true; + break; + case SND_SOC_DAIFMT_CBS_CFS: + ctrl = 0; + adau1373_dai->master = false; + break; + default: + return -EINVAL; + } + + switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { + case SND_SOC_DAIFMT_I2S: + ctrl |= ADAU1373_DAI_FORMAT_I2S; + break; + case SND_SOC_DAIFMT_LEFT_J: + ctrl |= ADAU1373_DAI_FORMAT_LEFT_J; + break; + case SND_SOC_DAIFMT_RIGHT_J: + ctrl |= ADAU1373_DAI_FORMAT_RIGHT_J; + break; + case SND_SOC_DAIFMT_DSP_B: + ctrl |= ADAU1373_DAI_FORMAT_DSP; + break; + default: + return -EINVAL; + } + + switch (fmt & SND_SOC_DAIFMT_INV_MASK) { + case SND_SOC_DAIFMT_NB_NF: + break; + case SND_SOC_DAIFMT_IB_NF: + ctrl |= ADAU1373_DAI_INVERT_BCLK; + break; + case SND_SOC_DAIFMT_NB_IF: + ctrl |= ADAU1373_DAI_INVERT_LRCLK; + break; + case SND_SOC_DAIFMT_IB_IF: + ctrl |= ADAU1373_DAI_INVERT_LRCLK | ADAU1373_DAI_INVERT_BCLK; + break; + default: + return -EINVAL; + } + + snd_soc_update_bits(codec, ADAU1373_DAI(dai->id), + ~ADAU1373_DAI_WLEN_MASK, ctrl); + + return 0; +} + +static int adau1373_set_dai_sysclk(struct snd_soc_dai *dai, + int clk_id, unsigned int freq, int dir) +{ + struct adau1373 *adau1373 = snd_soc_codec_get_drvdata(dai->codec); + struct adau1373_dai *adau1373_dai = &adau1373->dais[dai->id]; + + switch (clk_id) { + case ADAU1373_CLK_SRC_PLL1: + case ADAU1373_CLK_SRC_PLL2: + break; + default: + return -EINVAL; + } + + adau1373_dai->sysclk = freq; + adau1373_dai->clk_src = clk_id; + + snd_soc_update_bits(dai->codec, ADAU1373_BCLKDIV(dai->id), + ADAU1373_BCLKDIV_SOURCE, clk_id << 5); + + return 0; +} + +static const struct snd_soc_dai_ops adau1373_dai_ops = { + .hw_params = adau1373_hw_params, + .set_sysclk = adau1373_set_dai_sysclk, + .set_fmt = adau1373_set_dai_fmt, +}; + +#define ADAU1373_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE | \ + SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S32_LE) + +static struct snd_soc_dai_driver adau1373_dai_driver[] = { + { + .id = 0, + .name = "adau1373-aif1", + .playback = { + .stream_name = "AIF1 Playback", + .channels_min = 2, + .channels_max = 2, + .rates = SNDRV_PCM_RATE_8000_48000, + .formats = ADAU1373_FORMATS, + }, + .capture = { + .stream_name = "AIF1 Capture", + .channels_min = 2, + .channels_max = 2, + .rates = SNDRV_PCM_RATE_8000_48000, + .formats = ADAU1373_FORMATS, + }, + .ops = &adau1373_dai_ops, + .symmetric_rates = 1, + }, + { + .id = 1, + .name = "adau1373-aif2", + .playback = { + .stream_name = "AIF2 Playback", + .channels_min = 2, + .channels_max = 2, + .rates = SNDRV_PCM_RATE_8000_48000, + .formats = ADAU1373_FORMATS, + }, + .capture = { + .stream_name = "AIF2 Capture", + .channels_min = 2, + .channels_max = 2, + .rates = SNDRV_PCM_RATE_8000_48000, + .formats = ADAU1373_FORMATS, + }, + .ops = &adau1373_dai_ops, + .symmetric_rates = 1, + }, + { + .id = 2, + .name = "adau1373-aif3", + .playback = { + .stream_name = "AIF3 Playback", + .channels_min = 2, + .channels_max = 2, + .rates = SNDRV_PCM_RATE_8000_48000, + .formats = ADAU1373_FORMATS, + }, + .capture = { + .stream_name = "AIF3 Capture", + .channels_min = 2, + .channels_max = 2, + .rates = SNDRV_PCM_RATE_8000_48000, + .formats = ADAU1373_FORMATS, + }, + .ops = &adau1373_dai_ops, + .symmetric_rates = 1, + }, +}; + +static int adau1373_set_pll(struct snd_soc_codec *codec, int pll_id, + int source, unsigned int freq_in, unsigned int freq_out) +{ + unsigned int dpll_div = 0; + unsigned int x, r, n, m, i, j, mode; + + switch (pll_id) { + case ADAU1373_PLL1: + case ADAU1373_PLL2: + break; + default: + return -EINVAL; + } + + switch (source) { + case ADAU1373_PLL_SRC_BCLK1: + case ADAU1373_PLL_SRC_BCLK2: + case ADAU1373_PLL_SRC_BCLK3: + case ADAU1373_PLL_SRC_LRCLK1: + case ADAU1373_PLL_SRC_LRCLK2: + case ADAU1373_PLL_SRC_LRCLK3: + case ADAU1373_PLL_SRC_MCLK1: + case ADAU1373_PLL_SRC_MCLK2: + case ADAU1373_PLL_SRC_GPIO1: + case ADAU1373_PLL_SRC_GPIO2: + case ADAU1373_PLL_SRC_GPIO3: + case ADAU1373_PLL_SRC_GPIO4: + break; + default: + return -EINVAL; + } + + if (freq_in < 7813 || freq_in > 27000000) + return -EINVAL; + + if (freq_out < 45158000 || freq_out > 49152000) + return -EINVAL; + + /* APLL input needs to be >= 8Mhz, so in case freq_in is less we use the + * DPLL to get it there. DPLL_out = (DPLL_in / div) * 1024 */ + while (freq_in < 8000000) { + freq_in *= 2; + dpll_div++; + } + + if (freq_out % freq_in != 0) { + /* fout = fin * (r + (n/m)) / x */ + x = DIV_ROUND_UP(freq_in, 13500000); + freq_in /= x; + r = freq_out / freq_in; + i = freq_out % freq_in; + j = gcd(i, freq_in); + n = i / j; + m = freq_in / j; + x--; + mode = 1; + } else { + /* fout = fin / r */ + r = freq_out / freq_in; + n = 0; + m = 0; + x = 0; + mode = 0; + } + + if (r < 2 || r > 8 || x > 3 || m > 0xffff || n > 0xffff) + return -EINVAL; + + if (dpll_div) { + dpll_div = 11 - dpll_div; + snd_soc_update_bits(codec, ADAU1373_PLL_CTRL6(pll_id), + ADAU1373_PLL_CTRL6_DPLL_BYPASS, 0); + } else { + snd_soc_update_bits(codec, ADAU1373_PLL_CTRL6(pll_id), + ADAU1373_PLL_CTRL6_DPLL_BYPASS, + ADAU1373_PLL_CTRL6_DPLL_BYPASS); + } + + snd_soc_write(codec, ADAU1373_DPLL_CTRL(pll_id), + (source << 4) | dpll_div); + snd_soc_write(codec, ADAU1373_PLL_CTRL1(pll_id), (m >> 8) & 0xff); + snd_soc_write(codec, ADAU1373_PLL_CTRL2(pll_id), m & 0xff); + snd_soc_write(codec, ADAU1373_PLL_CTRL3(pll_id), (n >> 8) & 0xff); + snd_soc_write(codec, ADAU1373_PLL_CTRL4(pll_id), n & 0xff); + snd_soc_write(codec, ADAU1373_PLL_CTRL5(pll_id), + (r << 3) | (x << 1) | mode); + + /* Set sysclk to pll_rate / 4 */ + snd_soc_update_bits(codec, ADAU1373_CLK_SRC_DIV(pll_id), 0x3f, 0x09); + + return 0; +} + +static void adau1373_load_drc_settings(struct snd_soc_codec *codec, + unsigned int nr, uint8_t *drc) +{ + unsigned int i; + + for (i = 0; i < ADAU1373_DRC_SIZE; ++i) + snd_soc_write(codec, ADAU1373_DRC(nr) + i, drc[i]); +} + +static bool adau1373_valid_micbias(enum adau1373_micbias_voltage micbias) +{ + switch (micbias) { + case ADAU1373_MICBIAS_2_9V: + case ADAU1373_MICBIAS_2_2V: + case ADAU1373_MICBIAS_2_6V: + case ADAU1373_MICBIAS_1_8V: + return true; + default: + break; + } + return false; +} + +static int adau1373_probe(struct snd_soc_codec *codec) +{ + struct adau1373_platform_data *pdata = codec->dev->platform_data; + bool lineout_differential = false; + unsigned int val; + int ret; + int i; + + ret = snd_soc_codec_set_cache_io(codec, 8, 8, SND_SOC_I2C); + if (ret) { + dev_err(codec->dev, "failed to set cache I/O: %d\n", ret); + return ret; + } + + codec->dapm.idle_bias_off = true; + + if (pdata) { + if (pdata->num_drc > ARRAY_SIZE(pdata->drc_setting)) + return -EINVAL; + + if (!adau1373_valid_micbias(pdata->micbias1) || + !adau1373_valid_micbias(pdata->micbias2)) + return -EINVAL; + + for (i = 0; i < pdata->num_drc; ++i) { + adau1373_load_drc_settings(codec, i, + pdata->drc_setting[i]); + } + + snd_soc_add_controls(codec, adau1373_drc_controls, + pdata->num_drc); + + val = 0; + for (i = 0; i < 4; ++i) { + if (pdata->input_differential[i]) + val |= BIT(i); + } + snd_soc_write(codec, ADAU1373_INPUT_MODE, val); + + val = 0; + if (pdata->lineout_differential) + val |= ADAU1373_OUTPUT_CTRL_LDIFF; + if (pdata->lineout_ground_sense) + val |= ADAU1373_OUTPUT_CTRL_LNFBEN; + snd_soc_write(codec, ADAU1373_OUTPUT_CTRL, val); + + lineout_differential = pdata->lineout_differential; + + snd_soc_write(codec, ADAU1373_EP_CTRL, + (pdata->micbias1 << ADAU1373_EP_CTRL_MICBIAS1_OFFSET) | + (pdata->micbias2 << ADAU1373_EP_CTRL_MICBIAS2_OFFSET)); + } + + if (!lineout_differential) { + snd_soc_add_controls(codec, adau1373_lineout2_controls, + ARRAY_SIZE(adau1373_lineout2_controls)); + } + + snd_soc_write(codec, ADAU1373_ADC_CTRL, + ADAU1373_ADC_CTRL_RESET_FORCE | ADAU1373_ADC_CTRL_PEAK_DETECT); + + return 0; +} + +static int adau1373_set_bias_level(struct snd_soc_codec *codec, + enum snd_soc_bias_level level) +{ + switch (level) { + case SND_SOC_BIAS_ON: + break; + case SND_SOC_BIAS_PREPARE: + break; + case SND_SOC_BIAS_STANDBY: + snd_soc_update_bits(codec, ADAU1373_PWDN_CTRL3, + ADAU1373_PWDN_CTRL3_PWR_EN, ADAU1373_PWDN_CTRL3_PWR_EN); + break; + case SND_SOC_BIAS_OFF: + snd_soc_update_bits(codec, ADAU1373_PWDN_CTRL3, + ADAU1373_PWDN_CTRL3_PWR_EN, 0); + break; + } + codec->dapm.bias_level = level; + return 0; +} + +static int adau1373_remove(struct snd_soc_codec *codec) +{ + adau1373_set_bias_level(codec, SND_SOC_BIAS_OFF); + return 0; +} + +static int adau1373_suspend(struct snd_soc_codec *codec, pm_message_t state) +{ + return adau1373_set_bias_level(codec, SND_SOC_BIAS_OFF); +} + +static int adau1373_resume(struct snd_soc_codec *codec) +{ + adau1373_set_bias_level(codec, SND_SOC_BIAS_STANDBY); + snd_soc_cache_sync(codec); + + return 0; +} + +static struct snd_soc_codec_driver adau1373_codec_driver = { + .probe = adau1373_probe, + .remove = adau1373_remove, + .suspend = adau1373_suspend, + .resume = adau1373_resume, + .set_bias_level = adau1373_set_bias_level, + .reg_cache_size = ARRAY_SIZE(adau1373_default_regs), + .reg_cache_default = adau1373_default_regs, + .reg_word_size = sizeof(uint8_t), + + .set_pll = adau1373_set_pll, + + .controls = adau1373_controls, + .num_controls = ARRAY_SIZE(adau1373_controls), + .dapm_widgets = adau1373_dapm_widgets, + .num_dapm_widgets = ARRAY_SIZE(adau1373_dapm_widgets), + .dapm_routes = adau1373_dapm_routes, + .num_dapm_routes = ARRAY_SIZE(adau1373_dapm_routes), +}; + +static int __devinit adau1373_i2c_probe(struct i2c_client *client, + const struct i2c_device_id *id) +{ + struct adau1373 *adau1373; + int ret; + + adau1373 = kzalloc(sizeof(*adau1373), GFP_KERNEL); + if (!adau1373) + return -ENOMEM; + + dev_set_drvdata(&client->dev, adau1373); + + ret = snd_soc_register_codec(&client->dev, &adau1373_codec_driver, + adau1373_dai_driver, ARRAY_SIZE(adau1373_dai_driver)); + if (ret < 0) + kfree(adau1373); + + return ret; +} + +static int __devexit adau1373_i2c_remove(struct i2c_client *client) +{ + snd_soc_unregister_codec(&client->dev); + kfree(dev_get_drvdata(&client->dev)); + return 0; +} + +static const struct i2c_device_id adau1373_i2c_id[] = { + { "adau1373", 0 }, + { } +}; +MODULE_DEVICE_TABLE(i2c, adau1373_i2c_id); + +static struct i2c_driver adau1373_i2c_driver = { + .driver = { + .name = "adau1373", + .owner = THIS_MODULE, + }, + .probe = adau1373_i2c_probe, + .remove = __devexit_p(adau1373_i2c_remove), + .id_table = adau1373_i2c_id, +}; + +static int __init adau1373_init(void) +{ + return i2c_add_driver(&adau1373_i2c_driver); +} +module_init(adau1373_init); + +static void __exit adau1373_exit(void) +{ + i2c_del_driver(&adau1373_i2c_driver); +} +module_exit(adau1373_exit); + +MODULE_DESCRIPTION("ASoC ADAU1373 driver"); +MODULE_AUTHOR("Lars-Peter Clausen <lars@metafoo.de>"); +MODULE_LICENSE("GPL"); diff --git a/sound/soc/codecs/adau1373.h b/sound/soc/codecs/adau1373.h new file mode 100644 index 00000000000..c6ab5530760 --- /dev/null +++ b/sound/soc/codecs/adau1373.h @@ -0,0 +1,29 @@ +#ifndef __ADAU1373_H__ +#define __ADAU1373_H__ + +enum adau1373_pll_src { + ADAU1373_PLL_SRC_MCLK1 = 0, + ADAU1373_PLL_SRC_BCLK1 = 1, + ADAU1373_PLL_SRC_BCLK2 = 2, + ADAU1373_PLL_SRC_BCLK3 = 3, + ADAU1373_PLL_SRC_LRCLK1 = 4, + ADAU1373_PLL_SRC_LRCLK2 = 5, + ADAU1373_PLL_SRC_LRCLK3 = 6, + ADAU1373_PLL_SRC_GPIO1 = 7, + ADAU1373_PLL_SRC_GPIO2 = 8, + ADAU1373_PLL_SRC_GPIO3 = 9, + ADAU1373_PLL_SRC_GPIO4 = 10, + ADAU1373_PLL_SRC_MCLK2 = 11, +}; + +enum adau1373_pll { + ADAU1373_PLL1 = 0, + ADAU1373_PLL2 = 1, +}; + +enum adau1373_clk_src { + ADAU1373_CLK_SRC_PLL1 = 0, + ADAU1373_CLK_SRC_PLL2 = 1, +}; + +#endif diff --git a/sound/soc/codecs/adau1701.c b/sound/soc/codecs/adau1701.c index 2758d5fc60d..8b7e1c50d6e 100644 --- a/sound/soc/codecs/adau1701.c +++ b/sound/soc/codecs/adau1701.c @@ -401,7 +401,7 @@ static int adau1701_digital_mute(struct snd_soc_dai *dai, int mute) } static int adau1701_set_sysclk(struct snd_soc_codec *codec, int clk_id, - unsigned int freq, int dir) + int source, unsigned int freq, int dir) { unsigned int val; @@ -458,6 +458,7 @@ static int adau1701_probe(struct snd_soc_codec *codec) int ret; codec->dapm.idle_bias_off = 1; + codec->control_data = to_i2c_client(codec->dev); ret = adau1701_load_firmware(codec); if (ret) diff --git a/sound/soc/codecs/adav80x.c b/sound/soc/codecs/adav80x.c index 300c04b70e7..f9f08948e5e 100644 --- a/sound/soc/codecs/adav80x.c +++ b/sound/soc/codecs/adav80x.c @@ -523,7 +523,8 @@ static int adav80x_hw_params(struct snd_pcm_substream *substream, } static int adav80x_set_sysclk(struct snd_soc_codec *codec, - int clk_id, unsigned int freq, int dir) + int clk_id, int source, + unsigned int freq, int dir) { struct adav80x *adav80x = snd_soc_codec_get_drvdata(codec); diff --git a/sound/soc/codecs/ads117x.c b/sound/soc/codecs/ads117x.c index 8402854ec15..9082e0f729f 100644 --- a/sound/soc/codecs/ads117x.c +++ b/sound/soc/codecs/ads117x.c @@ -14,6 +14,7 @@ #include <linux/slab.h> #include <linux/init.h> #include <linux/device.h> +#include <linux/module.h> #include <sound/core.h> #include <sound/pcm.h> #include <sound/initval.h> diff --git a/sound/soc/codecs/ads117x.h b/sound/soc/codecs/ads117x.h deleted file mode 100644 index 3ce02861400..00000000000 --- a/sound/soc/codecs/ads117x.h +++ /dev/null @@ -1,13 +0,0 @@ -/* - * ads117x.h -- Driver for ads1174/8 ADC chips - * - * Copyright 2009 ShotSpotter Inc. - * Author: Graeme Gregory <gg@slimlogic.co.uk> - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2 of the License, or (at your - * option) any later version. - */ -extern struct snd_soc_dai_driver ads117x_dai; -extern struct snd_soc_codec_driver soc_codec_dev_ads117x; diff --git a/sound/soc/codecs/ak4104.c b/sound/soc/codecs/ak4104.c index cbf0b6d400b..d3b29dce6ed 100644 --- a/sound/soc/codecs/ak4104.c +++ b/sound/soc/codecs/ak4104.c @@ -247,7 +247,7 @@ static struct snd_soc_codec_driver soc_codec_device_ak4104 = { .probe = ak4104_probe, .remove = ak4104_remove, .reg_cache_size = AK4104_NUM_REGS, - .reg_word_size = sizeof(u16), + .reg_word_size = sizeof(u8), }; static int ak4104_spi_probe(struct spi_device *spi) diff --git a/sound/soc/codecs/ak4535.c b/sound/soc/codecs/ak4535.c index e1a214ee757..95d782d86e7 100644 --- a/sound/soc/codecs/ak4535.c +++ b/sound/soc/codecs/ak4535.c @@ -34,74 +34,16 @@ struct ak4535_priv { unsigned int sysclk; enum snd_soc_control_type control_type; - void *control_data; }; /* * ak4535 register cache */ -static const u16 ak4535_reg[AK4535_CACHEREGNUM] = { - 0x0000, 0x0080, 0x0000, 0x0003, - 0x0002, 0x0000, 0x0011, 0x0001, - 0x0000, 0x0040, 0x0036, 0x0010, - 0x0000, 0x0000, 0x0057, 0x0000, -}; - -/* - * read ak4535 register cache - */ -static inline unsigned int ak4535_read_reg_cache(struct snd_soc_codec *codec, - unsigned int reg) -{ - u16 *cache = codec->reg_cache; - if (reg >= AK4535_CACHEREGNUM) - return -1; - return cache[reg]; -} - -/* - * write ak4535 register cache - */ -static inline void ak4535_write_reg_cache(struct snd_soc_codec *codec, - u16 reg, unsigned int value) -{ - u16 *cache = codec->reg_cache; - if (reg >= AK4535_CACHEREGNUM) - return; - cache[reg] = value; -} - -/* - * write to the AK4535 register space - */ -static int ak4535_write(struct snd_soc_codec *codec, unsigned int reg, - unsigned int value) -{ - u8 data[2]; - - /* data is - * D15..D8 AK4535 register offset - * D7...D0 register data - */ - data[0] = reg & 0xff; - data[1] = value & 0xff; - - ak4535_write_reg_cache(codec, reg, value); - if (codec->hw_write(codec->control_data, data, 2) == 2) - return 0; - else - return -EIO; -} - -static int ak4535_sync(struct snd_soc_codec *codec) -{ - u16 *cache = codec->reg_cache; - int i, r = 0; - - for (i = 0; i < AK4535_CACHEREGNUM; i++) - r |= ak4535_write(codec, i, cache[i]); - - return r; +static const u8 ak4535_reg[AK4535_CACHEREGNUM] = { + 0x00, 0x80, 0x00, 0x03, + 0x02, 0x00, 0x11, 0x01, + 0x00, 0x40, 0x36, 0x10, + 0x00, 0x00, 0x57, 0x00, }; static const char *ak4535_mono_gain[] = {"+6dB", "-17dB"}; @@ -304,7 +246,7 @@ static int ak4535_hw_params(struct snd_pcm_substream *substream, struct snd_soc_pcm_runtime *rtd = substream->private_data; struct snd_soc_codec *codec = rtd->codec; struct ak4535_priv *ak4535 = snd_soc_codec_get_drvdata(codec); - u8 mode2 = ak4535_read_reg_cache(codec, AK4535_MODE2) & ~(0x3 << 5); + u8 mode2 = snd_soc_read(codec, AK4535_MODE2) & ~(0x3 << 5); int rate = params_rate(params), fs = 256; if (rate) @@ -323,7 +265,7 @@ static int ak4535_hw_params(struct snd_pcm_substream *substream, } /* set rate */ - ak4535_write(codec, AK4535_MODE2, mode2); + snd_soc_write(codec, AK4535_MODE2, mode2); return 0; } @@ -348,44 +290,37 @@ static int ak4535_set_dai_fmt(struct snd_soc_dai *codec_dai, /* use 32 fs for BCLK to save power */ mode1 |= 0x4; - ak4535_write(codec, AK4535_MODE1, mode1); + snd_soc_write(codec, AK4535_MODE1, mode1); return 0; } static int ak4535_mute(struct snd_soc_dai *dai, int mute) { struct snd_soc_codec *codec = dai->codec; - u16 mute_reg = ak4535_read_reg_cache(codec, AK4535_DAC); + u16 mute_reg = snd_soc_read(codec, AK4535_DAC); if (!mute) - ak4535_write(codec, AK4535_DAC, mute_reg & ~0x20); + snd_soc_write(codec, AK4535_DAC, mute_reg & ~0x20); else - ak4535_write(codec, AK4535_DAC, mute_reg | 0x20); + snd_soc_write(codec, AK4535_DAC, mute_reg | 0x20); return 0; } static int ak4535_set_bias_level(struct snd_soc_codec *codec, enum snd_soc_bias_level level) { - u16 i, mute_reg; - switch (level) { case SND_SOC_BIAS_ON: - mute_reg = ak4535_read_reg_cache(codec, AK4535_DAC); - ak4535_write(codec, AK4535_DAC, mute_reg & ~0x20); + snd_soc_update_bits(codec, AK4535_DAC, 0x20, 0); break; case SND_SOC_BIAS_PREPARE: - mute_reg = ak4535_read_reg_cache(codec, AK4535_DAC); - ak4535_write(codec, AK4535_DAC, mute_reg | 0x20); + snd_soc_update_bits(codec, AK4535_DAC, 0x20, 0x20); break; case SND_SOC_BIAS_STANDBY: - i = ak4535_read_reg_cache(codec, AK4535_PM1); - ak4535_write(codec, AK4535_PM1, i | 0x80); - i = ak4535_read_reg_cache(codec, AK4535_PM2); - ak4535_write(codec, AK4535_PM2, i & (~0x80)); + snd_soc_update_bits(codec, AK4535_PM1, 0x80, 0x80); + snd_soc_update_bits(codec, AK4535_PM2, 0x80, 0); break; case SND_SOC_BIAS_OFF: - i = ak4535_read_reg_cache(codec, AK4535_PM1); - ak4535_write(codec, AK4535_PM1, i & (~0x80)); + snd_soc_update_bits(codec, AK4535_PM1, 0x80, 0); break; } codec->dapm.bias_level = level; @@ -428,7 +363,7 @@ static int ak4535_suspend(struct snd_soc_codec *codec, pm_message_t state) static int ak4535_resume(struct snd_soc_codec *codec) { - ak4535_sync(codec); + snd_soc_cache_sync(codec); ak4535_set_bias_level(codec, SND_SOC_BIAS_STANDBY); return 0; } @@ -436,11 +371,15 @@ static int ak4535_resume(struct snd_soc_codec *codec) static int ak4535_probe(struct snd_soc_codec *codec) { struct ak4535_priv *ak4535 = snd_soc_codec_get_drvdata(codec); + int ret; printk(KERN_INFO "AK4535 Audio Codec %s", AK4535_VERSION); - codec->control_data = ak4535->control_data; - + ret = snd_soc_codec_set_cache_io(codec, 8, 8, ak4535->control_type); + if (ret < 0) { + dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret); + return ret; + } /* power on device */ ak4535_set_bias_level(codec, SND_SOC_BIAS_STANDBY); @@ -461,8 +400,6 @@ static struct snd_soc_codec_driver soc_codec_dev_ak4535 = { .remove = ak4535_remove, .suspend = ak4535_suspend, .resume = ak4535_resume, - .read = ak4535_read_reg_cache, - .write = ak4535_write, .set_bias_level = ak4535_set_bias_level, .reg_cache_size = ARRAY_SIZE(ak4535_reg), .reg_word_size = sizeof(u8), @@ -485,7 +422,6 @@ static __devinit int ak4535_i2c_probe(struct i2c_client *i2c, return -ENOMEM; i2c_set_clientdata(i2c, ak4535); - ak4535->control_data = i2c; ak4535->control_type = SND_SOC_I2C; ret = snd_soc_register_codec(&i2c->dev, diff --git a/sound/soc/codecs/ak4641.c b/sound/soc/codecs/ak4641.c index 7a64e58cddc..77838586f35 100644 --- a/sound/soc/codecs/ak4641.c +++ b/sound/soc/codecs/ak4641.c @@ -31,7 +31,6 @@ /* codec private data */ struct ak4641_priv { - struct snd_soc_codec *codec; unsigned int sysclk; int deemph; int playback_fs; @@ -226,7 +225,7 @@ static const struct snd_soc_dapm_widget ak4641_dapm_widgets[] = { SND_SOC_DAPM_PGA("Mono Out 2", AK4641_PM2, 3, 0, NULL, 0), SND_SOC_DAPM_ADC("Voice ADC", "Voice Capture", AK4641_BTIF, 0, 0), - SND_SOC_DAPM_ADC("Voice DAC", "Voice Playback", AK4641_BTIF, 1, 0), + SND_SOC_DAPM_DAC("Voice DAC", "Voice Playback", AK4641_BTIF, 1, 0), SND_SOC_DAPM_MICBIAS("Mic Int Bias", AK4641_MIC, 3, 0), SND_SOC_DAPM_MICBIAS("Mic Ext Bias", AK4641_MIC, 4, 0), diff --git a/sound/soc/codecs/ak4642.c b/sound/soc/codecs/ak4642.c index 65f46047b1c..12c1bdef673 100644 --- a/sound/soc/codecs/ak4642.c +++ b/sound/soc/codecs/ak4642.c @@ -26,6 +26,7 @@ #include <linux/i2c.h> #include <linux/platform_device.h> #include <linux/slab.h> +#include <linux/module.h> #include <sound/soc.h> #include <sound/initval.h> #include <sound/tlv.h> @@ -156,81 +157,22 @@ static const struct snd_kcontrol_new ak4642_snd_controls[] = { struct ak4642_priv { unsigned int sysclk; enum snd_soc_control_type control_type; - void *control_data; }; /* * ak4642 register cache */ -static const u16 ak4642_reg[AK4642_CACHEREGNUM] = { - 0x0000, 0x0000, 0x0001, 0x0000, - 0x0002, 0x0000, 0x0000, 0x0000, - 0x00e1, 0x00e1, 0x0018, 0x0000, - 0x00e1, 0x0018, 0x0011, 0x0008, - 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, -}; - -/* - * read ak4642 register cache - */ -static inline unsigned int ak4642_read_reg_cache(struct snd_soc_codec *codec, - unsigned int reg) -{ - u16 *cache = codec->reg_cache; - if (reg >= AK4642_CACHEREGNUM) - return -1; - return cache[reg]; -} - -/* - * write ak4642 register cache - */ -static inline void ak4642_write_reg_cache(struct snd_soc_codec *codec, - u16 reg, unsigned int value) -{ - u16 *cache = codec->reg_cache; - if (reg >= AK4642_CACHEREGNUM) - return; - - cache[reg] = value; -} - -/* - * write to the AK4642 register space - */ -static int ak4642_write(struct snd_soc_codec *codec, unsigned int reg, - unsigned int value) -{ - u8 data[2]; - - /* data is - * D15..D8 AK4642 register offset - * D7...D0 register data - */ - data[0] = reg & 0xff; - data[1] = value & 0xff; - - if (codec->hw_write(codec->control_data, data, 2) == 2) { - ak4642_write_reg_cache(codec, reg, value); - return 0; - } else - return -EIO; -} - -static int ak4642_sync(struct snd_soc_codec *codec) -{ - u16 *cache = codec->reg_cache; - int i, r = 0; - - for (i = 0; i < AK4642_CACHEREGNUM; i++) - r |= ak4642_write(codec, i, cache[i]); - - return r; +static const u8 ak4642_reg[AK4642_CACHEREGNUM] = { + 0x00, 0x00, 0x01, 0x00, + 0x02, 0x00, 0x00, 0x00, + 0xe1, 0xe1, 0x18, 0x00, + 0xe1, 0x18, 0x11, 0x08, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, }; static int ak4642_dai_startup(struct snd_pcm_substream *substream, @@ -252,8 +194,8 @@ static int ak4642_dai_startup(struct snd_pcm_substream *substream, */ snd_soc_update_bits(codec, MD_CTL4, DACH, DACH); snd_soc_update_bits(codec, MD_CTL3, BST1, BST1); - ak4642_write(codec, L_IVC, 0x91); /* volume */ - ak4642_write(codec, R_IVC, 0x91); /* volume */ + snd_soc_write(codec, L_IVC, 0x91); /* volume */ + snd_soc_write(codec, R_IVC, 0x91); /* volume */ snd_soc_update_bits(codec, PW_MGMT1, PMVCM | PMMIN | PMDAC, PMVCM | PMMIN | PMDAC); snd_soc_update_bits(codec, PW_MGMT2, PMHP_MASK, PMHP); @@ -272,9 +214,9 @@ static int ak4642_dai_startup(struct snd_pcm_substream *substream, * This operation came from example code of * "ASAHI KASEI AK4642" (japanese) manual p94. */ - ak4642_write(codec, SG_SL1, PMMP | MGAIN0); - ak4642_write(codec, TIMER, ZTM(0x3) | WTM(0x3)); - ak4642_write(codec, ALC_CTL1, ALC | LMTH0); + snd_soc_write(codec, SG_SL1, PMMP | MGAIN0); + snd_soc_write(codec, TIMER, ZTM(0x3) | WTM(0x3)); + snd_soc_write(codec, ALC_CTL1, ALC | LMTH0); snd_soc_update_bits(codec, PW_MGMT1, PMVCM | PMADL, PMVCM | PMADL); snd_soc_update_bits(codec, PW_MGMT3, PMADR, PMADR); @@ -462,7 +404,7 @@ static struct snd_soc_dai_driver ak4642_dai = { static int ak4642_resume(struct snd_soc_codec *codec) { - ak4642_sync(codec); + snd_soc_cache_sync(codec); return 0; } @@ -470,11 +412,15 @@ static int ak4642_resume(struct snd_soc_codec *codec) static int ak4642_probe(struct snd_soc_codec *codec) { struct ak4642_priv *ak4642 = snd_soc_codec_get_drvdata(codec); + int ret; dev_info(codec->dev, "AK4642 Audio Codec %s", AK4642_VERSION); - codec->hw_write = (hw_write_t)i2c_master_send; - codec->control_data = ak4642->control_data; + ret = snd_soc_codec_set_cache_io(codec, 8, 8, ak4642->control_type); + if (ret < 0) { + dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret); + return ret; + } snd_soc_add_controls(codec, ak4642_snd_controls, ARRAY_SIZE(ak4642_snd_controls)); @@ -485,8 +431,6 @@ static int ak4642_probe(struct snd_soc_codec *codec) static struct snd_soc_codec_driver soc_codec_dev_ak4642 = { .probe = ak4642_probe, .resume = ak4642_resume, - .read = ak4642_read_reg_cache, - .write = ak4642_write, .reg_cache_size = ARRAY_SIZE(ak4642_reg), .reg_word_size = sizeof(u8), .reg_cache_default = ak4642_reg, @@ -504,7 +448,6 @@ static __devinit int ak4642_i2c_probe(struct i2c_client *i2c, return -ENOMEM; i2c_set_clientdata(i2c, ak4642); - ak4642->control_data = i2c; ak4642->control_type = SND_SOC_I2C; ret = snd_soc_register_codec(&i2c->dev, diff --git a/sound/soc/codecs/ak4671.c b/sound/soc/codecs/ak4671.c index 88b29f8c748..de9ff66d372 100644 --- a/sound/soc/codecs/ak4671.c +++ b/sound/soc/codecs/ak4671.c @@ -26,7 +26,6 @@ /* codec private data */ struct ak4671_priv { enum snd_soc_control_type control_type; - void *control_data; }; /* ak4671 register cache & default register settings */ @@ -169,18 +168,15 @@ static int ak4671_out2_event(struct snd_soc_dapm_widget *w, struct snd_kcontrol *kcontrol, int event) { struct snd_soc_codec *codec = w->codec; - u8 reg; switch (event) { case SND_SOC_DAPM_POST_PMU: - reg = snd_soc_read(codec, AK4671_LOUT2_POWER_MANAGERMENT); - reg |= AK4671_MUTEN; - snd_soc_write(codec, AK4671_LOUT2_POWER_MANAGERMENT, reg); + snd_soc_update_bits(codec, AK4671_LOUT2_POWER_MANAGERMENT, + AK4671_MUTEN, AK4671_MUTEN); break; case SND_SOC_DAPM_PRE_PMD: - reg = snd_soc_read(codec, AK4671_LOUT2_POWER_MANAGERMENT); - reg &= ~AK4671_MUTEN; - snd_soc_write(codec, AK4671_LOUT2_POWER_MANAGERMENT, reg); + snd_soc_update_bits(codec, AK4671_LOUT2_POWER_MANAGERMENT, + AK4671_MUTEN, 0); break; } @@ -576,15 +572,12 @@ static int ak4671_set_dai_fmt(struct snd_soc_dai *dai, unsigned int fmt) static int ak4671_set_bias_level(struct snd_soc_codec *codec, enum snd_soc_bias_level level) { - u8 reg; - switch (level) { case SND_SOC_BIAS_ON: case SND_SOC_BIAS_PREPARE: case SND_SOC_BIAS_STANDBY: - reg = snd_soc_read(codec, AK4671_AD_DA_POWER_MANAGEMENT); - snd_soc_write(codec, AK4671_AD_DA_POWER_MANAGEMENT, - reg | AK4671_PMVCM); + snd_soc_update_bits(codec, AK4671_AD_DA_POWER_MANAGEMENT, + AK4671_PMVCM, AK4671_PMVCM); break; case SND_SOC_BIAS_OFF: snd_soc_write(codec, AK4671_AD_DA_POWER_MANAGEMENT, 0x00); @@ -629,8 +622,6 @@ static int ak4671_probe(struct snd_soc_codec *codec) struct ak4671_priv *ak4671 = snd_soc_codec_get_drvdata(codec); int ret; - codec->hw_write = (hw_write_t)i2c_master_send; - ret = snd_soc_codec_set_cache_io(codec, 8, 8, ak4671->control_type); if (ret < 0) { dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret); @@ -675,7 +666,6 @@ static int __devinit ak4671_i2c_probe(struct i2c_client *client, return -ENOMEM; i2c_set_clientdata(client, ak4671); - ak4671->control_data = client; ak4671->control_type = SND_SOC_I2C; ret = snd_soc_register_codec(&client->dev, diff --git a/sound/soc/codecs/alc5623.c b/sound/soc/codecs/alc5623.c index eecffb54894..984b14bcb60 100644 --- a/sound/soc/codecs/alc5623.c +++ b/sound/soc/codecs/alc5623.c @@ -40,8 +40,6 @@ MODULE_PARM_DESC(caps_charge, "ALC5623 cap charge time (msecs)"); /* codec private data */ struct alc5623_priv { enum snd_soc_control_type control_type; - void *control_data; - struct mutex mutex; u8 id; unsigned int sysclk; u16 reg_cache[ALC5623_VENDOR_ID2+2]; @@ -55,8 +53,10 @@ static void alc5623_fill_cache(struct snd_soc_codec *codec) u16 *cache = codec->reg_cache; /* not really efficient ... */ + codec->cache_bypass = 1; for (i = 0 ; i < codec->driver->reg_cache_size ; i += step) - cache[i] = codec->hw_read(codec, i); + cache[i] = snd_soc_read(codec, i); + codec->cache_bypass = 0; } static inline int alc5623_reset(struct snd_soc_codec *codec) @@ -1050,9 +1050,7 @@ static int alc5623_i2c_probe(struct i2c_client *client, } i2c_set_clientdata(client, alc5623); - alc5623->control_data = client; alc5623->control_type = SND_SOC_I2C; - mutex_init(&alc5623->mutex); ret = snd_soc_register_codec(&client->dev, &soc_codec_device_alc5623, &alc5623_dai, 1); diff --git a/sound/soc/codecs/cs4270.c b/sound/soc/codecs/cs4270.c index 6cc8678f49f..f1f237ecec2 100644 --- a/sound/soc/codecs/cs4270.c +++ b/sound/soc/codecs/cs4270.c @@ -128,7 +128,6 @@ static const char *supply_names[] = { /* Private data for the CS4270 */ struct cs4270_private { enum snd_soc_control_type control_type; - void *control_data; unsigned int mclk; /* Input frequency of the MCLK pin */ unsigned int mode; /* The mode (I2S or left-justified) */ unsigned int slave_mode; @@ -262,7 +261,6 @@ static int cs4270_set_dai_fmt(struct snd_soc_dai *codec_dai, { struct snd_soc_codec *codec = codec_dai->codec; struct cs4270_private *cs4270 = snd_soc_codec_get_drvdata(codec); - int ret = 0; /* set DAI format */ switch (format & SND_SOC_DAIFMT_FORMAT_MASK) { @@ -272,7 +270,7 @@ static int cs4270_set_dai_fmt(struct snd_soc_dai *codec_dai, break; default: dev_err(codec->dev, "invalid dai format\n"); - ret = -EINVAL; + return -EINVAL; } /* set master/slave audio interface */ @@ -285,10 +283,11 @@ static int cs4270_set_dai_fmt(struct snd_soc_dai *codec_dai, break; default: /* all other modes are unsupported by the hardware */ - ret = -EINVAL; + dev_err(codec->dev, "Unknown master/slave configuration\n"); + return -EINVAL; } - return ret; + return 0; } /** @@ -490,8 +489,6 @@ static int cs4270_probe(struct snd_soc_codec *codec) struct cs4270_private *cs4270 = snd_soc_codec_get_drvdata(codec); int i, ret; - codec->control_data = cs4270->control_data; - /* Tell ASoC what kind of I/O to use to read the registers. ASoC will * then do the I2C transactions itself. */ @@ -604,7 +601,7 @@ static int cs4270_soc_suspend(struct snd_soc_codec *codec, pm_message_t mesg) static int cs4270_soc_resume(struct snd_soc_codec *codec) { struct cs4270_private *cs4270 = snd_soc_codec_get_drvdata(codec); - struct i2c_client *i2c_client = codec->control_data; + struct i2c_client *i2c_client = to_i2c_client(codec->dev); int reg; regulator_bulk_enable(ARRAY_SIZE(cs4270->supplies), @@ -690,7 +687,6 @@ static int cs4270_i2c_probe(struct i2c_client *i2c_client, } i2c_set_clientdata(i2c_client, cs4270); - cs4270->control_data = i2c_client; cs4270->control_type = SND_SOC_I2C; ret = snd_soc_register_codec(&i2c_client->dev, diff --git a/sound/soc/codecs/cs4271.c b/sound/soc/codecs/cs4271.c index 083aab96ca8..23d1bd5dadd 100644 --- a/sound/soc/codecs/cs4271.c +++ b/sound/soc/codecs/cs4271.c @@ -156,7 +156,6 @@ static const u8 cs4271_dflt_reg[CS4271_NR_REGS] = { struct cs4271_private { /* SND_SOC_I2C or SND_SOC_SPI */ enum snd_soc_control_type bus_type; - void *control_data; unsigned int mclk; bool master; bool deemph; @@ -466,8 +465,6 @@ static int cs4271_probe(struct snd_soc_codec *codec) int ret; int gpio_nreset = -EINVAL; - codec->control_data = cs4271->control_data; - if (cs4271plat && gpio_is_valid(cs4271plat->gpio_nreset)) gpio_nreset = cs4271plat->gpio_nreset; @@ -555,7 +552,6 @@ static int __devinit cs4271_spi_probe(struct spi_device *spi) return -ENOMEM; spi_set_drvdata(spi, cs4271); - cs4271->control_data = spi; cs4271->bus_type = SND_SOC_SPI; return snd_soc_register_codec(&spi->dev, &soc_codec_dev_cs4271, @@ -595,7 +591,6 @@ static int __devinit cs4271_i2c_probe(struct i2c_client *client, return -ENOMEM; i2c_set_clientdata(client, cs4271); - cs4271->control_data = client; cs4271->bus_type = SND_SOC_I2C; return snd_soc_register_codec(&client->dev, &soc_codec_dev_cs4271, diff --git a/sound/soc/codecs/cs42l51.c b/sound/soc/codecs/cs42l51.c index 8fb7070108d..8c3c8205d19 100644 --- a/sound/soc/codecs/cs42l51.c +++ b/sound/soc/codecs/cs42l51.c @@ -42,7 +42,6 @@ enum master_slave_mode { struct cs42l51_private { enum snd_soc_control_type control_type; - void *control_data; unsigned int mclk; unsigned int audio_mode; /* The mode (I2S or left-justified) */ enum master_slave_mode func; @@ -57,7 +56,7 @@ struct cs42l51_private { static int cs42l51_fill_cache(struct snd_soc_codec *codec) { u8 *cache = codec->reg_cache + 1; - struct i2c_client *i2c_client = codec->control_data; + struct i2c_client *i2c_client = to_i2c_client(codec->dev); s32 length; length = i2c_smbus_read_i2c_block_data(i2c_client, @@ -289,7 +288,6 @@ static int cs42l51_set_dai_fmt(struct snd_soc_dai *codec_dai, { struct snd_soc_codec *codec = codec_dai->codec; struct cs42l51_private *cs42l51 = snd_soc_codec_get_drvdata(codec); - int ret = 0; switch (format & SND_SOC_DAIFMT_FORMAT_MASK) { case SND_SOC_DAIFMT_I2S: @@ -299,7 +297,7 @@ static int cs42l51_set_dai_fmt(struct snd_soc_dai *codec_dai, break; default: dev_err(codec->dev, "invalid DAI format\n"); - ret = -EINVAL; + return -EINVAL; } switch (format & SND_SOC_DAIFMT_MASTER_MASK) { @@ -310,11 +308,11 @@ static int cs42l51_set_dai_fmt(struct snd_soc_dai *codec_dai, cs42l51->func = MODE_SLAVE_AUTO; break; default: - ret = -EINVAL; - break; + dev_err(codec->dev, "Unknown master/slave configuration\n"); + return -EINVAL; } - return ret; + return 0; } struct cs42l51_ratios { @@ -520,8 +518,6 @@ static int cs42l51_probe(struct snd_soc_codec *codec) struct snd_soc_dapm_context *dapm = &codec->dapm; int ret, reg; - codec->control_data = cs42l51->control_data; - ret = cs42l51_fill_cache(codec); if (ret < 0) { dev_err(codec->dev, "failed to fill register cache\n"); @@ -593,7 +589,6 @@ static int cs42l51_i2c_probe(struct i2c_client *i2c_client, } i2c_set_clientdata(i2c_client, cs42l51); - cs42l51->control_data = i2c_client; cs42l51->control_type = SND_SOC_I2C; ret = snd_soc_register_codec(&i2c_client->dev, diff --git a/sound/soc/codecs/cx20442.c b/sound/soc/codecs/cx20442.c index d68ea532cc7..bc7067db8ae 100644 --- a/sound/soc/codecs/cx20442.c +++ b/sound/soc/codecs/cx20442.c @@ -15,6 +15,7 @@ #include <linux/tty.h> #include <linux/slab.h> +#include <linux/module.h> #include <sound/core.h> #include <sound/initval.h> diff --git a/sound/soc/codecs/da7210.c b/sound/soc/codecs/da7210.c index 92fd9d7a922..b545b7d3722 100644 --- a/sound/soc/codecs/da7210.c +++ b/sound/soc/codecs/da7210.c @@ -19,6 +19,7 @@ #include <linux/i2c.h> #include <linux/platform_device.h> #include <linux/slab.h> +#include <linux/module.h> #include <sound/pcm.h> #include <sound/pcm_params.h> #include <sound/soc.h> @@ -26,23 +27,41 @@ #include <sound/tlv.h> /* DA7210 register space */ +#define DA7210_CONTROL 0x01 #define DA7210_STATUS 0x02 #define DA7210_STARTUP1 0x03 +#define DA7210_STARTUP2 0x04 +#define DA7210_STARTUP3 0x05 #define DA7210_MIC_L 0x07 #define DA7210_MIC_R 0x08 +#define DA7210_AUX1_L 0x09 +#define DA7210_AUX1_R 0x0A +#define DA7210_AUX2 0x0B +#define DA7210_IN_GAIN 0x0C #define DA7210_INMIX_L 0x0D #define DA7210_INMIX_R 0x0E #define DA7210_ADC_HPF 0x0F #define DA7210_ADC 0x10 +#define DA7210_ADC_EQ1_2 0X11 +#define DA7210_ADC_EQ3_4 0x12 +#define DA7210_ADC_EQ5 0x13 #define DA7210_DAC_HPF 0x14 #define DA7210_DAC_L 0x15 #define DA7210_DAC_R 0x16 #define DA7210_DAC_SEL 0x17 +#define DA7210_SOFTMUTE 0x18 +#define DA7210_DAC_EQ1_2 0x19 +#define DA7210_DAC_EQ3_4 0x1A +#define DA7210_DAC_EQ5 0x1B #define DA7210_OUTMIX_L 0x1C #define DA7210_OUTMIX_R 0x1D +#define DA7210_OUT1_L 0x1E +#define DA7210_OUT1_R 0x1F +#define DA7210_OUT2 0x20 #define DA7210_HP_L_VOL 0x21 #define DA7210_HP_R_VOL 0x22 #define DA7210_HP_CFG 0x23 +#define DA7210_ZERO_CROSS 0x24 #define DA7210_DAI_SRC_SEL 0x25 #define DA7210_DAI_CFG1 0x26 #define DA7210_DAI_CFG3 0x28 @@ -50,6 +69,12 @@ #define DA7210_PLL_DIV2 0x2A #define DA7210_PLL_DIV3 0x2B #define DA7210_PLL 0x2C +#define DA7210_ALC_MAX 0x83 +#define DA7210_ALC_MIN 0x84 +#define DA7210_ALC_NOIS 0x85 +#define DA7210_ALC_ATT 0x86 +#define DA7210_ALC_REL 0x87 +#define DA7210_ALC_DEL 0x88 #define DA7210_A_HID_UNLOCK 0x8A #define DA7210_A_TEST_UNLOCK 0x8B #define DA7210_A_PLL1 0x90 @@ -72,6 +97,7 @@ #define DA7210_IN_R_EN (1 << 7) /* ADC bit fields */ +#define DA7210_ADC_ALC_EN (1 << 0) #define DA7210_ADC_L_EN (1 << 3) #define DA7210_ADC_R_EN (1 << 7) @@ -105,12 +131,17 @@ /* DAI_CFG1 bit fields */ #define DA7210_DAI_WORD_S16_LE (0 << 0) +#define DA7210_DAI_WORD_S20_3LE (1 << 0) #define DA7210_DAI_WORD_S24_LE (2 << 0) +#define DA7210_DAI_WORD_S32_LE (3 << 0) #define DA7210_DAI_FLEN_64BIT (1 << 2) +#define DA7210_DAI_MODE_SLAVE (0 << 7) #define DA7210_DAI_MODE_MASTER (1 << 7) /* DAI_CFG3 bit fields */ #define DA7210_DAI_FORMAT_I2SMODE (0 << 0) +#define DA7210_DAI_FORMAT_LEFT_J (1 << 0) +#define DA7210_DAI_FORMAT_RIGHT_J (2 << 0) #define DA7210_DAI_OE (1 << 3) #define DA7210_DAI_EN (1 << 7) @@ -133,6 +164,43 @@ #define DA7210_PLL_FS_96000 (0xF << 0) #define DA7210_PLL_EN (0x1 << 7) +/* SOFTMUTE bit fields */ +#define DA7210_RAMP_EN (1 << 6) + +/* CONTROL bit fields */ +#define DA7210_NOISE_SUP_EN (1 << 3) + +/* IN_GAIN bit fields */ +#define DA7210_INPGA_L_VOL (0x0F << 0) +#define DA7210_INPGA_R_VOL (0xF0 << 0) + +/* ZERO_CROSS bit fields */ +#define DA7210_AUX1_L_ZC (1 << 0) +#define DA7210_AUX1_R_ZC (1 << 1) +#define DA7210_HP_L_ZC (1 << 6) +#define DA7210_HP_R_ZC (1 << 7) + +/* AUX1_L bit fields */ +#define DA7210_AUX1_L_VOL (0x3F << 0) + +/* AUX1_R bit fields */ +#define DA7210_AUX1_R_VOL (0x3F << 0) + +/* Minimum INPGA and AUX1 volume to enable noise suppression */ +#define DA7210_INPGA_MIN_VOL_NS 0x0A /* 10.5dB */ +#define DA7210_AUX1_MIN_VOL_NS 0x35 /* 6dB */ + +/* OUT1_L bit fields */ +#define DA7210_OUT1_L_EN (1 << 7) + +/* OUT1_R bit fields */ +#define DA7210_OUT1_R_EN (1 << 7) + +/* OUT2 bit fields */ +#define DA7210_OUT2_OUTMIX_R (1 << 5) +#define DA7210_OUT2_OUTMIX_L (1 << 6) +#define DA7210_OUT2_EN (1 << 7) + #define DA7210_VERSION "0.0.1" /* @@ -144,24 +212,351 @@ * mute : 0x10 * reserved : 0x00 - 0x0F * - * ** FIXME ** - * * Reserved area are considered as "mute". - * -> min = -79.5 dB */ -static const DECLARE_TLV_DB_SCALE(hp_out_tlv, -7950, 150, 1); +static const unsigned int hp_out_tlv[] = { + TLV_DB_RANGE_HEAD(2), + 0x0, 0x10, TLV_DB_SCALE_ITEM(TLV_DB_GAIN_MUTE, 0, 1), + /* -54 dB to +15 dB */ + 0x11, 0x3f, TLV_DB_SCALE_ITEM(-5400, 150, 0), +}; + +static const unsigned int lineout_vol_tlv[] = { + TLV_DB_RANGE_HEAD(2), + 0x0, 0x10, TLV_DB_SCALE_ITEM(TLV_DB_GAIN_MUTE, 0, 1), + /* -54dB to 15dB */ + 0x11, 0x3f, TLV_DB_SCALE_ITEM(-5400, 150, 0) +}; + +static const unsigned int mono_vol_tlv[] = { + TLV_DB_RANGE_HEAD(2), + 0x0, 0x2, TLV_DB_SCALE_ITEM(-1800, 0, 1), + /* -18dB to 6dB */ + 0x3, 0x7, TLV_DB_SCALE_ITEM(-1800, 600, 0) +}; + +static const DECLARE_TLV_DB_SCALE(eq_gain_tlv, -1050, 150, 0); +static const DECLARE_TLV_DB_SCALE(adc_eq_master_gain_tlv, -1800, 600, 1); +static const DECLARE_TLV_DB_SCALE(dac_gain_tlv, -7725, 75, 0); + +/* ADC and DAC high pass filter f0 value */ +static const char const *da7210_hpf_cutoff_txt[] = { + "Fs/8192*pi", "Fs/4096*pi", "Fs/2048*pi", "Fs/1024*pi" +}; + +static const struct soc_enum da7210_dac_hpf_cutoff = + SOC_ENUM_SINGLE(DA7210_DAC_HPF, 0, 4, da7210_hpf_cutoff_txt); + +static const struct soc_enum da7210_adc_hpf_cutoff = + SOC_ENUM_SINGLE(DA7210_ADC_HPF, 0, 4, da7210_hpf_cutoff_txt); + +/* ADC and DAC voice (8kHz) high pass cutoff value */ +static const char const *da7210_vf_cutoff_txt[] = { + "2.5Hz", "25Hz", "50Hz", "100Hz", "150Hz", "200Hz", "300Hz", "400Hz" +}; + +static const struct soc_enum da7210_dac_vf_cutoff = + SOC_ENUM_SINGLE(DA7210_DAC_HPF, 4, 8, da7210_vf_cutoff_txt); + +static const struct soc_enum da7210_adc_vf_cutoff = + SOC_ENUM_SINGLE(DA7210_ADC_HPF, 4, 8, da7210_vf_cutoff_txt); + +static const char *da7210_hp_mode_txt[] = { + "Class H", "Class G" +}; + +static const struct soc_enum da7210_hp_mode_sel = + SOC_ENUM_SINGLE(DA7210_HP_CFG, 0, 2, da7210_hp_mode_txt); + +/* ALC can be enabled only if noise suppression is disabled */ +static int da7210_put_alc_sw(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); + + if (ucontrol->value.integer.value[0]) { + /* Check if noise suppression is enabled */ + if (snd_soc_read(codec, DA7210_CONTROL) & DA7210_NOISE_SUP_EN) { + dev_dbg(codec->dev, + "Disable noise suppression to enable ALC\n"); + return -EINVAL; + } + } + /* If all conditions are met or we are actually disabling ALC */ + return snd_soc_put_volsw(kcontrol, ucontrol); +} + +/* Noise suppression can be enabled only if following conditions are met + * ALC disabled + * ZC enabled for HP and AUX1 PGA + * INPGA_L_VOL and INPGA_R_VOL >= 10.5 dB + * AUX1_L_VOL and AUX1_R_VOL >= 6 dB + */ +static int da7210_put_noise_sup_sw(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); + u8 val; + + if (ucontrol->value.integer.value[0]) { + /* Check if ALC is enabled */ + if (snd_soc_read(codec, DA7210_ADC) & DA7210_ADC_ALC_EN) + goto err; + + /* Check ZC for HP and AUX1 PGA */ + if ((snd_soc_read(codec, DA7210_ZERO_CROSS) & + (DA7210_AUX1_L_ZC | DA7210_AUX1_R_ZC | DA7210_HP_L_ZC | + DA7210_HP_R_ZC)) != (DA7210_AUX1_L_ZC | + DA7210_AUX1_R_ZC | DA7210_HP_L_ZC | DA7210_HP_R_ZC)) + goto err; + + /* Check INPGA_L_VOL and INPGA_R_VOL */ + val = snd_soc_read(codec, DA7210_IN_GAIN); + if (((val & DA7210_INPGA_L_VOL) < DA7210_INPGA_MIN_VOL_NS) || + (((val & DA7210_INPGA_R_VOL) >> 4) < + DA7210_INPGA_MIN_VOL_NS)) + goto err; + + /* Check AUX1_L_VOL and AUX1_R_VOL */ + if (((snd_soc_read(codec, DA7210_AUX1_L) & DA7210_AUX1_L_VOL) < + DA7210_AUX1_MIN_VOL_NS) || + ((snd_soc_read(codec, DA7210_AUX1_R) & DA7210_AUX1_R_VOL) < + DA7210_AUX1_MIN_VOL_NS)) + goto err; + } + /* If all conditions are met or we are actually disabling Noise sup */ + return snd_soc_put_volsw(kcontrol, ucontrol); + +err: + return -EINVAL; +} static const struct snd_kcontrol_new da7210_snd_controls[] = { SOC_DOUBLE_R_TLV("HeadPhone Playback Volume", DA7210_HP_L_VOL, DA7210_HP_R_VOL, 0, 0x3F, 0, hp_out_tlv), + SOC_DOUBLE_R_TLV("Digital Playback Volume", + DA7210_DAC_L, DA7210_DAC_R, + 0, 0x77, 1, dac_gain_tlv), + SOC_DOUBLE_R_TLV("Lineout Playback Volume", + DA7210_OUT1_L, DA7210_OUT1_R, + 0, 0x3f, 0, lineout_vol_tlv), + SOC_SINGLE_TLV("Mono Playback Volume", DA7210_OUT2, 0, 0x7, 0, + mono_vol_tlv), + + /* DAC Equalizer controls */ + SOC_SINGLE("DAC EQ Switch", DA7210_DAC_EQ5, 7, 1, 0), + SOC_SINGLE_TLV("DAC EQ1 Volume", DA7210_DAC_EQ1_2, 0, 0xf, 1, + eq_gain_tlv), + SOC_SINGLE_TLV("DAC EQ2 Volume", DA7210_DAC_EQ1_2, 4, 0xf, 1, + eq_gain_tlv), + SOC_SINGLE_TLV("DAC EQ3 Volume", DA7210_DAC_EQ3_4, 0, 0xf, 1, + eq_gain_tlv), + SOC_SINGLE_TLV("DAC EQ4 Volume", DA7210_DAC_EQ3_4, 4, 0xf, 1, + eq_gain_tlv), + SOC_SINGLE_TLV("DAC EQ5 Volume", DA7210_DAC_EQ5, 0, 0xf, 1, + eq_gain_tlv), + + /* ADC Equalizer controls */ + SOC_SINGLE("ADC EQ Switch", DA7210_ADC_EQ5, 7, 1, 0), + SOC_SINGLE_TLV("ADC EQ Master Volume", DA7210_ADC_EQ5, 4, 0x3, + 1, adc_eq_master_gain_tlv), + SOC_SINGLE_TLV("ADC EQ1 Volume", DA7210_ADC_EQ1_2, 0, 0xf, 1, + eq_gain_tlv), + SOC_SINGLE_TLV("ADC EQ2 Volume", DA7210_ADC_EQ1_2, 4, 0xf, 1, + eq_gain_tlv), + SOC_SINGLE_TLV("ADC EQ3 Volume", DA7210_ADC_EQ3_4, 0, 0xf, 1, + eq_gain_tlv), + SOC_SINGLE_TLV("ADC EQ4 Volume", DA7210_ADC_EQ3_4, 4, 0xf, 1, + eq_gain_tlv), + SOC_SINGLE_TLV("ADC EQ5 Volume", DA7210_ADC_EQ5, 0, 0xf, 1, + eq_gain_tlv), + + SOC_SINGLE("DAC HPF Switch", DA7210_DAC_HPF, 3, 1, 0), + SOC_ENUM("DAC HPF Cutoff", da7210_dac_hpf_cutoff), + SOC_SINGLE("DAC Voice Mode Switch", DA7210_DAC_HPF, 7, 1, 0), + SOC_ENUM("DAC Voice Cutoff", da7210_dac_vf_cutoff), + + SOC_SINGLE("ADC HPF Switch", DA7210_ADC_HPF, 3, 1, 0), + SOC_ENUM("ADC HPF Cutoff", da7210_adc_hpf_cutoff), + SOC_SINGLE("ADC Voice Mode Switch", DA7210_ADC_HPF, 7, 1, 0), + SOC_ENUM("ADC Voice Cutoff", da7210_adc_vf_cutoff), + + /* Mute controls */ + SOC_DOUBLE_R("Mic Capture Switch", DA7210_MIC_L, DA7210_MIC_R, 3, 1, 0), + SOC_SINGLE("Aux2 Capture Switch", DA7210_AUX2, 2, 1, 0), + SOC_DOUBLE("ADC Capture Switch", DA7210_ADC, 2, 6, 1, 0), + SOC_SINGLE("Digital Soft Mute Switch", DA7210_SOFTMUTE, 7, 1, 0), + SOC_SINGLE("Digital Soft Mute Rate", DA7210_SOFTMUTE, 0, 0x7, 0), + + /* Zero cross controls */ + SOC_DOUBLE("Aux1 ZC Switch", DA7210_ZERO_CROSS, 0, 1, 1, 0), + SOC_DOUBLE("In PGA ZC Switch", DA7210_ZERO_CROSS, 2, 3, 1, 0), + SOC_DOUBLE("Lineout ZC Switch", DA7210_ZERO_CROSS, 4, 5, 1, 0), + SOC_DOUBLE("Headphone ZC Switch", DA7210_ZERO_CROSS, 6, 7, 1, 0), + + SOC_ENUM("Headphone Class", da7210_hp_mode_sel), + + /* ALC controls */ + SOC_SINGLE_EXT("ALC Enable Switch", DA7210_ADC, 0, 1, 0, + snd_soc_get_volsw, da7210_put_alc_sw), + SOC_SINGLE("ALC Capture Max Volume", DA7210_ALC_MAX, 0, 0x3F, 0), + SOC_SINGLE("ALC Capture Min Volume", DA7210_ALC_MIN, 0, 0x3F, 0), + SOC_SINGLE("ALC Capture Noise Volume", DA7210_ALC_NOIS, 0, 0x3F, 0), + SOC_SINGLE("ALC Capture Attack Rate", DA7210_ALC_ATT, 0, 0xFF, 0), + SOC_SINGLE("ALC Capture Release Rate", DA7210_ALC_REL, 0, 0xFF, 0), + SOC_SINGLE("ALC Capture Release Delay", DA7210_ALC_DEL, 0, 0xFF, 0), + + SOC_SINGLE_EXT("Noise Suppression Enable Switch", DA7210_CONTROL, 3, 1, + 0, snd_soc_get_volsw, da7210_put_noise_sup_sw), +}; + +/* + * DAPM Controls + * + * Current DAPM implementation covers almost all codec components e.g. IOs, + * mixers, PGAs,ADC and DAC. + */ +/* In Mixer Left */ +static const struct snd_kcontrol_new da7210_dapm_inmixl_controls[] = { + SOC_DAPM_SINGLE("Mic Left Switch", DA7210_INMIX_L, 0, 1, 0), + SOC_DAPM_SINGLE("Mic Right Switch", DA7210_INMIX_L, 1, 1, 0), +}; + +/* In Mixer Right */ +static const struct snd_kcontrol_new da7210_dapm_inmixr_controls[] = { + SOC_DAPM_SINGLE("Mic Right Switch", DA7210_INMIX_R, 0, 1, 0), + SOC_DAPM_SINGLE("Mic Left Switch", DA7210_INMIX_R, 1, 1, 0), +}; + +/* Out Mixer Left */ +static const struct snd_kcontrol_new da7210_dapm_outmixl_controls[] = { + SOC_DAPM_SINGLE("DAC Left Switch", DA7210_OUTMIX_L, 4, 1, 0), +}; + +/* Out Mixer Right */ +static const struct snd_kcontrol_new da7210_dapm_outmixr_controls[] = { + SOC_DAPM_SINGLE("DAC Right Switch", DA7210_OUTMIX_R, 4, 1, 0), +}; + +/* Mono Mixer */ +static const struct snd_kcontrol_new da7210_dapm_monomix_controls[] = { + SOC_DAPM_SINGLE("Outmix Right Switch", DA7210_OUT2, 5, 1, 0), + SOC_DAPM_SINGLE("Outmix Left Switch", DA7210_OUT2, 6, 1, 0), +}; + +/* DAPM widgets */ +static const struct snd_soc_dapm_widget da7210_dapm_widgets[] = { + /* Input Side */ + /* Input Lines */ + SND_SOC_DAPM_INPUT("MICL"), + SND_SOC_DAPM_INPUT("MICR"), + + /* Input PGAs */ + SND_SOC_DAPM_PGA("Mic Left", DA7210_STARTUP3, 0, 1, NULL, 0), + SND_SOC_DAPM_PGA("Mic Right", DA7210_STARTUP3, 1, 1, NULL, 0), + + SND_SOC_DAPM_PGA("INPGA Left", DA7210_INMIX_L, 7, 0, NULL, 0), + SND_SOC_DAPM_PGA("INPGA Right", DA7210_INMIX_R, 7, 0, NULL, 0), + + /* Input Mixers */ + SND_SOC_DAPM_MIXER("In Mixer Left", SND_SOC_NOPM, 0, 0, + &da7210_dapm_inmixl_controls[0], + ARRAY_SIZE(da7210_dapm_inmixl_controls)), + + SND_SOC_DAPM_MIXER("In Mixer Right", SND_SOC_NOPM, 0, 0, + &da7210_dapm_inmixr_controls[0], + ARRAY_SIZE(da7210_dapm_inmixr_controls)), + + /* ADCs */ + SND_SOC_DAPM_ADC("ADC Left", "Capture", DA7210_STARTUP3, 5, 1), + SND_SOC_DAPM_ADC("ADC Right", "Capture", DA7210_STARTUP3, 6, 1), + + /* Output Side */ + /* DACs */ + SND_SOC_DAPM_DAC("DAC Left", "Playback", DA7210_STARTUP2, 5, 1), + SND_SOC_DAPM_DAC("DAC Right", "Playback", DA7210_STARTUP2, 6, 1), + + /* Output Mixers */ + SND_SOC_DAPM_MIXER("Out Mixer Left", SND_SOC_NOPM, 0, 0, + &da7210_dapm_outmixl_controls[0], + ARRAY_SIZE(da7210_dapm_outmixl_controls)), + + SND_SOC_DAPM_MIXER("Out Mixer Right", SND_SOC_NOPM, 0, 0, + &da7210_dapm_outmixr_controls[0], + ARRAY_SIZE(da7210_dapm_outmixr_controls)), + + SND_SOC_DAPM_MIXER("Mono Mixer", SND_SOC_NOPM, 0, 0, + &da7210_dapm_monomix_controls[0], + ARRAY_SIZE(da7210_dapm_monomix_controls)), + + /* Output PGAs */ + SND_SOC_DAPM_PGA("OUTPGA Left Enable", DA7210_OUTMIX_L, 7, 0, NULL, 0), + SND_SOC_DAPM_PGA("OUTPGA Right Enable", DA7210_OUTMIX_R, 7, 0, NULL, 0), + + SND_SOC_DAPM_PGA("Out1 Left", DA7210_STARTUP2, 0, 1, NULL, 0), + SND_SOC_DAPM_PGA("Out1 Right", DA7210_STARTUP2, 1, 1, NULL, 0), + SND_SOC_DAPM_PGA("Out2 Mono", DA7210_STARTUP2, 2, 1, NULL, 0), + SND_SOC_DAPM_PGA("Headphone Left", DA7210_STARTUP2, 3, 1, NULL, 0), + SND_SOC_DAPM_PGA("Headphone Right", DA7210_STARTUP2, 4, 1, NULL, 0), + + /* Output Lines */ + SND_SOC_DAPM_OUTPUT("OUT1L"), + SND_SOC_DAPM_OUTPUT("OUT1R"), + SND_SOC_DAPM_OUTPUT("HPL"), + SND_SOC_DAPM_OUTPUT("HPR"), + SND_SOC_DAPM_OUTPUT("OUT2"), +}; + +/* DAPM audio route definition */ +static const struct snd_soc_dapm_route da7210_audio_map[] = { + /* Dest Connecting Widget source */ + /* Input path */ + {"Mic Left", NULL, "MICL"}, + {"Mic Right", NULL, "MICR"}, + + {"In Mixer Left", "Mic Left Switch", "Mic Left"}, + {"In Mixer Left", "Mic Right Switch", "Mic Right"}, + + {"In Mixer Right", "Mic Right Switch", "Mic Right"}, + {"In Mixer Right", "Mic Left Switch", "Mic Left"}, + + {"INPGA Left", NULL, "In Mixer Left"}, + {"ADC Left", NULL, "INPGA Left"}, + + {"INPGA Right", NULL, "In Mixer Right"}, + {"ADC Right", NULL, "INPGA Right"}, + + /* Output path */ + {"Out Mixer Left", "DAC Left Switch", "DAC Left"}, + {"Out Mixer Right", "DAC Right Switch", "DAC Right"}, + + {"Mono Mixer", "Outmix Right Switch", "Out Mixer Right"}, + {"Mono Mixer", "Outmix Left Switch", "Out Mixer Left"}, + + {"OUTPGA Left Enable", NULL, "Out Mixer Left"}, + {"OUTPGA Right Enable", NULL, "Out Mixer Right"}, + + {"Out1 Left", NULL, "OUTPGA Left Enable"}, + {"OUT1L", NULL, "Out1 Left"}, + + {"Out1 Right", NULL, "OUTPGA Right Enable"}, + {"OUT1R", NULL, "Out1 Right"}, + + {"Headphone Left", NULL, "OUTPGA Left Enable"}, + {"HPL", NULL, "Headphone Left"}, + + {"Headphone Right", NULL, "OUTPGA Right Enable"}, + {"HPR", NULL, "Headphone Right"}, + + {"Out2 Mono", NULL, "Mono Mixer"}, + {"OUT2", NULL, "Out2 Mono"}, }; /* Codec private data */ struct da7210_priv { enum snd_soc_control_type control_type; - void *control_data; }; /* @@ -188,72 +583,15 @@ static const u8 da7210_reg[] = { 0x00, /* R88 */ }; -/* - * Read da7210 register cache - */ -static inline u32 da7210_read_reg_cache(struct snd_soc_codec *codec, u32 reg) -{ - u8 *cache = codec->reg_cache; - BUG_ON(reg >= ARRAY_SIZE(da7210_reg)); - return cache[reg]; -} - -/* - * Write to the da7210 register space - */ -static int da7210_write(struct snd_soc_codec *codec, u32 reg, u32 value) +static int da7210_volatile_register(struct snd_soc_codec *codec, + unsigned int reg) { - u8 *cache = codec->reg_cache; - u8 data[2]; - - BUG_ON(codec->driver->volatile_register); - - data[0] = reg & 0xff; - data[1] = value & 0xff; - - if (reg >= codec->driver->reg_cache_size) - return -EIO; - - if (2 != codec->hw_write(codec->control_data, data, 2)) - return -EIO; - - cache[reg] = value; - return 0; -} - -/* - * Read from the da7210 register space. - */ -static inline u32 da7210_read(struct snd_soc_codec *codec, u32 reg) -{ - if (DA7210_STATUS == reg) - return i2c_smbus_read_byte_data(codec->control_data, reg); - - return da7210_read_reg_cache(codec, reg); -} - -static int da7210_startup(struct snd_pcm_substream *substream, - struct snd_soc_dai *dai) -{ - int is_play = substream->stream == SNDRV_PCM_STREAM_PLAYBACK; - struct snd_soc_codec *codec = dai->codec; - - if (is_play) { - /* Enable Out */ - snd_soc_update_bits(codec, DA7210_OUTMIX_L, 0x1F, 0x10); - snd_soc_update_bits(codec, DA7210_OUTMIX_R, 0x1F, 0x10); - - } else { - /* Volume 7 */ - snd_soc_update_bits(codec, DA7210_MIC_L, 0x7, 0x7); - snd_soc_update_bits(codec, DA7210_MIC_R, 0x7, 0x7); - - /* Enable Mic */ - snd_soc_update_bits(codec, DA7210_INMIX_L, 0x1F, 0x1); - snd_soc_update_bits(codec, DA7210_INMIX_R, 0x1F, 0x1); + switch (reg) { + case DA7210_STATUS: + return 1; + default: + return 0; } - - return 0; } /* @@ -266,93 +604,75 @@ static int da7210_hw_params(struct snd_pcm_substream *substream, struct snd_soc_pcm_runtime *rtd = substream->private_data; struct snd_soc_codec *codec = rtd->codec; u32 dai_cfg1; - u32 hpf_reg, hpf_mask, hpf_value; u32 fs, bypass; /* set DAI source to Left and Right ADC */ - da7210_write(codec, DA7210_DAI_SRC_SEL, + snd_soc_write(codec, DA7210_DAI_SRC_SEL, DA7210_DAI_OUT_R_SRC | DA7210_DAI_OUT_L_SRC); /* Enable DAI */ - da7210_write(codec, DA7210_DAI_CFG3, DA7210_DAI_OE | DA7210_DAI_EN); + snd_soc_write(codec, DA7210_DAI_CFG3, DA7210_DAI_OE | DA7210_DAI_EN); - dai_cfg1 = 0xFC & da7210_read(codec, DA7210_DAI_CFG1); + dai_cfg1 = 0xFC & snd_soc_read(codec, DA7210_DAI_CFG1); switch (params_format(params)) { case SNDRV_PCM_FORMAT_S16_LE: dai_cfg1 |= DA7210_DAI_WORD_S16_LE; break; + case SNDRV_PCM_FORMAT_S20_3LE: + dai_cfg1 |= DA7210_DAI_WORD_S20_3LE; + break; case SNDRV_PCM_FORMAT_S24_LE: dai_cfg1 |= DA7210_DAI_WORD_S24_LE; break; + case SNDRV_PCM_FORMAT_S32_LE: + dai_cfg1 |= DA7210_DAI_WORD_S32_LE; + break; default: return -EINVAL; } - da7210_write(codec, DA7210_DAI_CFG1, dai_cfg1); - - hpf_reg = (SNDRV_PCM_STREAM_PLAYBACK == substream->stream) ? - DA7210_DAC_HPF : DA7210_ADC_HPF; + snd_soc_write(codec, DA7210_DAI_CFG1, dai_cfg1); switch (params_rate(params)) { case 8000: fs = DA7210_PLL_FS_8000; - hpf_mask = DA7210_VOICE_F0_MASK | DA7210_VOICE_EN; - hpf_value = DA7210_VOICE_F0_25 | DA7210_VOICE_EN; bypass = DA7210_PLL_BYP; break; case 11025: fs = DA7210_PLL_FS_11025; - hpf_mask = DA7210_VOICE_F0_MASK | DA7210_VOICE_EN; - hpf_value = DA7210_VOICE_F0_25 | DA7210_VOICE_EN; bypass = 0; break; case 12000: fs = DA7210_PLL_FS_12000; - hpf_mask = DA7210_VOICE_F0_MASK | DA7210_VOICE_EN; - hpf_value = DA7210_VOICE_F0_25 | DA7210_VOICE_EN; bypass = DA7210_PLL_BYP; break; case 16000: fs = DA7210_PLL_FS_16000; - hpf_mask = DA7210_VOICE_F0_MASK | DA7210_VOICE_EN; - hpf_value = DA7210_VOICE_F0_25 | DA7210_VOICE_EN; bypass = DA7210_PLL_BYP; break; case 22050: fs = DA7210_PLL_FS_22050; - hpf_mask = DA7210_VOICE_EN; - hpf_value = 0; bypass = 0; break; case 32000: fs = DA7210_PLL_FS_32000; - hpf_mask = DA7210_VOICE_EN; - hpf_value = 0; bypass = DA7210_PLL_BYP; break; case 44100: fs = DA7210_PLL_FS_44100; - hpf_mask = DA7210_VOICE_EN; - hpf_value = 0; bypass = 0; break; case 48000: fs = DA7210_PLL_FS_48000; - hpf_mask = DA7210_VOICE_EN; - hpf_value = 0; bypass = DA7210_PLL_BYP; break; case 88200: fs = DA7210_PLL_FS_88200; - hpf_mask = DA7210_VOICE_EN; - hpf_value = 0; bypass = 0; break; case 96000: fs = DA7210_PLL_FS_96000; - hpf_mask = DA7210_VOICE_EN; - hpf_value = 0; bypass = DA7210_PLL_BYP; break; default: @@ -362,7 +682,6 @@ static int da7210_hw_params(struct snd_pcm_substream *substream, /* Disable active mode */ snd_soc_update_bits(codec, DA7210_STARTUP1, DA7210_SC_MST_EN, 0); - snd_soc_update_bits(codec, hpf_reg, hpf_mask, hpf_value); snd_soc_update_bits(codec, DA7210_PLL, DA7210_PLL_FS_MASK, fs); snd_soc_update_bits(codec, DA7210_PLL_DIV3, DA7210_PLL_BYP, bypass); @@ -382,13 +701,16 @@ static int da7210_set_dai_fmt(struct snd_soc_dai *codec_dai, u32 fmt) u32 dai_cfg1; u32 dai_cfg3; - dai_cfg1 = 0x7f & da7210_read(codec, DA7210_DAI_CFG1); - dai_cfg3 = 0xfc & da7210_read(codec, DA7210_DAI_CFG3); + dai_cfg1 = 0x7f & snd_soc_read(codec, DA7210_DAI_CFG1); + dai_cfg3 = 0xfc & snd_soc_read(codec, DA7210_DAI_CFG3); switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { case SND_SOC_DAIFMT_CBM_CFM: dai_cfg1 |= DA7210_DAI_MODE_MASTER; break; + case SND_SOC_DAIFMT_CBS_CFS: + dai_cfg1 |= DA7210_DAI_MODE_SLAVE; + break; default: return -EINVAL; } @@ -401,6 +723,12 @@ static int da7210_set_dai_fmt(struct snd_soc_dai *codec_dai, u32 fmt) case SND_SOC_DAIFMT_I2S: dai_cfg3 |= DA7210_DAI_FORMAT_I2SMODE; break; + case SND_SOC_DAIFMT_LEFT_J: + dai_cfg3 |= DA7210_DAI_FORMAT_LEFT_J; + break; + case SND_SOC_DAIFMT_RIGHT_J: + dai_cfg3 |= DA7210_DAI_FORMAT_RIGHT_J; + break; default: return -EINVAL; } @@ -411,19 +739,32 @@ static int da7210_set_dai_fmt(struct snd_soc_dai *codec_dai, u32 fmt) */ dai_cfg1 |= DA7210_DAI_FLEN_64BIT; - da7210_write(codec, DA7210_DAI_CFG1, dai_cfg1); - da7210_write(codec, DA7210_DAI_CFG3, dai_cfg3); + snd_soc_write(codec, DA7210_DAI_CFG1, dai_cfg1); + snd_soc_write(codec, DA7210_DAI_CFG3, dai_cfg3); + + return 0; +} + +static int da7210_mute(struct snd_soc_dai *dai, int mute) +{ + struct snd_soc_codec *codec = dai->codec; + u8 mute_reg = snd_soc_read(codec, DA7210_DAC_HPF) & 0xFB; + if (mute) + snd_soc_write(codec, DA7210_DAC_HPF, mute_reg | 0x4); + else + snd_soc_write(codec, DA7210_DAC_HPF, mute_reg); return 0; } -#define DA7210_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S24_LE) +#define DA7210_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE |\ + SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S32_LE) /* DAI operations */ static struct snd_soc_dai_ops da7210_dai_ops = { - .startup = da7210_startup, .hw_params = da7210_hw_params, .set_fmt = da7210_set_dai_fmt, + .digital_mute = da7210_mute, }; static struct snd_soc_dai_driver da7210_dai = { @@ -451,11 +792,15 @@ static struct snd_soc_dai_driver da7210_dai = { static int da7210_probe(struct snd_soc_codec *codec) { struct da7210_priv *da7210 = snd_soc_codec_get_drvdata(codec); + int ret; dev_info(codec->dev, "DA7210 Audio Codec %s\n", DA7210_VERSION); - codec->control_data = da7210->control_data; - codec->hw_write = (hw_write_t)i2c_master_send; + ret = snd_soc_codec_set_cache_io(codec, 8, 8, da7210->control_type); + if (ret < 0) { + dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret); + return ret; + } /* FIXME * @@ -472,8 +817,8 @@ static int da7210_probe(struct snd_soc_codec *codec) /* * make sure that DA7210 use bypass mode before start up */ - da7210_write(codec, DA7210_STARTUP1, 0); - da7210_write(codec, DA7210_PLL_DIV3, + snd_soc_write(codec, DA7210_STARTUP1, 0); + snd_soc_write(codec, DA7210_PLL_DIV3, DA7210_MCLK_RANGE_10_20_MHZ | DA7210_PLL_BYP); /* @@ -481,36 +826,70 @@ static int da7210_probe(struct snd_soc_codec *codec) */ /* Enable Left & Right MIC PGA and Mic Bias */ - da7210_write(codec, DA7210_MIC_L, DA7210_MIC_L_EN | DA7210_MICBIAS_EN); - da7210_write(codec, DA7210_MIC_R, DA7210_MIC_R_EN); + snd_soc_write(codec, DA7210_MIC_L, DA7210_MIC_L_EN | DA7210_MICBIAS_EN); + snd_soc_write(codec, DA7210_MIC_R, DA7210_MIC_R_EN); /* Enable Left and Right input PGA */ - da7210_write(codec, DA7210_INMIX_L, DA7210_IN_L_EN); - da7210_write(codec, DA7210_INMIX_R, DA7210_IN_R_EN); + snd_soc_write(codec, DA7210_INMIX_L, DA7210_IN_L_EN); + snd_soc_write(codec, DA7210_INMIX_R, DA7210_IN_R_EN); /* Enable Left and Right ADC */ - da7210_write(codec, DA7210_ADC, DA7210_ADC_L_EN | DA7210_ADC_R_EN); + snd_soc_write(codec, DA7210_ADC, DA7210_ADC_L_EN | DA7210_ADC_R_EN); /* * DAC settings */ /* Enable Left and Right DAC */ - da7210_write(codec, DA7210_DAC_SEL, + snd_soc_write(codec, DA7210_DAC_SEL, DA7210_DAC_L_SRC_DAI_L | DA7210_DAC_L_EN | DA7210_DAC_R_SRC_DAI_R | DA7210_DAC_R_EN); /* Enable Left and Right out PGA */ - da7210_write(codec, DA7210_OUTMIX_L, DA7210_OUT_L_EN); - da7210_write(codec, DA7210_OUTMIX_R, DA7210_OUT_R_EN); + snd_soc_write(codec, DA7210_OUTMIX_L, DA7210_OUT_L_EN); + snd_soc_write(codec, DA7210_OUTMIX_R, DA7210_OUT_R_EN); /* Enable Left and Right HeadPhone PGA */ - da7210_write(codec, DA7210_HP_CFG, + snd_soc_write(codec, DA7210_HP_CFG, DA7210_HP_2CAP_MODE | DA7210_HP_SENSE_EN | DA7210_HP_L_EN | DA7210_HP_MODE | DA7210_HP_R_EN); + /* Enable ramp mode for DAC gain update */ + snd_soc_write(codec, DA7210_SOFTMUTE, DA7210_RAMP_EN); + + /* + * For DA7210 codec, there are two ways to enable/disable analog IOs + * and ADC/DAC, + * (1) Using "Enable Bit" of register associated with that IO + * (or ADC/DAC) + * e.g. Mic Left can be enabled using bit 7 of MIC_L(0x7) reg + * + * (2) Using "Standby Bit" of STARTUP2 or STARTUP3 register + * e.g. Mic left can be put to STANDBY using bit 0 of STARTUP3(0x5) + * + * Out of these two methods, the one using STANDBY bits is preferred + * way to enable/disable individual blocks. This is because STANDBY + * registers are part of system controller which allows system power + * up/down in a controlled, pop-free manner. Also, as per application + * note of DA7210, STANDBY register bits are only effective if a + * particular IO (or ADC/DAC) is already enabled using enable/disable + * register bits. Keeping these things in mind, current DAPM + * implementation manipulates only STANDBY bits. + * + * Overall implementation can be outlined as below, + * + * - "Enable bit" of an IO or ADC/DAC is used to enable it in probe() + * - "STANDBY bit" is controlled by DAPM + */ + + /* Enable Line out amplifiers */ + snd_soc_write(codec, DA7210_OUT1_L, DA7210_OUT1_L_EN); + snd_soc_write(codec, DA7210_OUT1_R, DA7210_OUT1_R_EN); + snd_soc_write(codec, DA7210_OUT2, DA7210_OUT2_EN | + DA7210_OUT2_OUTMIX_L | DA7210_OUT2_OUTMIX_R); + /* Diable PLL and bypass it */ - da7210_write(codec, DA7210_PLL, DA7210_PLL_FS_48000); + snd_soc_write(codec, DA7210_PLL, DA7210_PLL_FS_48000); /* * If 48kHz sound came, it use bypass mode, @@ -521,25 +900,22 @@ static int da7210_probe(struct snd_soc_codec *codec) * DA7210_PLL_DIV3 :: DA7210_PLL_BYP bit. * see da7210_hw_params */ - da7210_write(codec, DA7210_PLL_DIV1, 0xE5); /* MCLK = 12.288MHz */ - da7210_write(codec, DA7210_PLL_DIV2, 0x99); - da7210_write(codec, DA7210_PLL_DIV3, 0x0A | + snd_soc_write(codec, DA7210_PLL_DIV1, 0xE5); /* MCLK = 12.288MHz */ + snd_soc_write(codec, DA7210_PLL_DIV2, 0x99); + snd_soc_write(codec, DA7210_PLL_DIV3, 0x0A | DA7210_MCLK_RANGE_10_20_MHZ | DA7210_PLL_BYP); snd_soc_update_bits(codec, DA7210_PLL, DA7210_PLL_EN, DA7210_PLL_EN); /* As suggested by Dialog */ - da7210_write(codec, DA7210_A_HID_UNLOCK, 0x8B); /* unlock */ - da7210_write(codec, DA7210_A_TEST_UNLOCK, 0xB4); - da7210_write(codec, DA7210_A_PLL1, 0x01); - da7210_write(codec, DA7210_A_CP_MODE, 0x7C); - da7210_write(codec, DA7210_A_HID_UNLOCK, 0x00); /* re-lock */ - da7210_write(codec, DA7210_A_TEST_UNLOCK, 0x00); + snd_soc_write(codec, DA7210_A_HID_UNLOCK, 0x8B); /* unlock */ + snd_soc_write(codec, DA7210_A_TEST_UNLOCK, 0xB4); + snd_soc_write(codec, DA7210_A_PLL1, 0x01); + snd_soc_write(codec, DA7210_A_CP_MODE, 0x7C); + snd_soc_write(codec, DA7210_A_HID_UNLOCK, 0x00); /* re-lock */ + snd_soc_write(codec, DA7210_A_TEST_UNLOCK, 0x00); /* Activate all enabled subsystem */ - da7210_write(codec, DA7210_STARTUP1, DA7210_SC_MST_EN); - - snd_soc_add_controls(codec, da7210_snd_controls, - ARRAY_SIZE(da7210_snd_controls)); + snd_soc_write(codec, DA7210_STARTUP1, DA7210_SC_MST_EN); dev_info(codec->dev, "DA7210 Audio Codec %s\n", DA7210_VERSION); @@ -548,11 +924,18 @@ static int da7210_probe(struct snd_soc_codec *codec) static struct snd_soc_codec_driver soc_codec_dev_da7210 = { .probe = da7210_probe, - .read = da7210_read, - .write = da7210_write, .reg_cache_size = ARRAY_SIZE(da7210_reg), .reg_word_size = sizeof(u8), .reg_cache_default = da7210_reg, + .volatile_register = da7210_volatile_register, + + .controls = da7210_snd_controls, + .num_controls = ARRAY_SIZE(da7210_snd_controls), + + .dapm_widgets = da7210_dapm_widgets, + .num_dapm_widgets = ARRAY_SIZE(da7210_dapm_widgets), + .dapm_routes = da7210_audio_map, + .num_dapm_routes = ARRAY_SIZE(da7210_audio_map), }; #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) @@ -567,7 +950,6 @@ static int __devinit da7210_i2c_probe(struct i2c_client *i2c, return -ENOMEM; i2c_set_clientdata(i2c, da7210); - da7210->control_data = i2c; da7210->control_type = SND_SOC_I2C; ret = snd_soc_register_codec(&i2c->dev, diff --git a/sound/soc/codecs/dmic.c b/sound/soc/codecs/dmic.c index f9a87737ec1..6fae765e3ad 100644 --- a/sound/soc/codecs/dmic.c +++ b/sound/soc/codecs/dmic.c @@ -21,6 +21,7 @@ #include <linux/platform_device.h> #include <linux/slab.h> +#include <linux/module.h> #include <sound/core.h> #include <sound/pcm.h> #include <sound/soc.h> diff --git a/sound/soc/codecs/lm4857.c b/sound/soc/codecs/lm4857.c index 2c2a681da0d..c387dafc6ab 100644 --- a/sound/soc/codecs/lm4857.c +++ b/sound/soc/codecs/lm4857.c @@ -3,7 +3,7 @@ * * Copyright 2007 Wolfson Microelectronics PLC. * Author: Graeme Gregory - * graeme.gregory@wolfsonmicro.com or linux@wolfsonmicro.com + * graeme.gregory@wolfsonmicro.com * Copyright 2011 Lars-Peter Clausen <lars@metafoo.de> * * This program is free software; you can redistribute it and/or modify it diff --git a/sound/soc/codecs/max98088.c b/sound/soc/codecs/max98088.c index ac65a2d3640..ebbf63c79c3 100644 --- a/sound/soc/codecs/max98088.c +++ b/sound/soc/codecs/max98088.c @@ -40,7 +40,6 @@ struct max98088_cdata { struct max98088_priv { enum max98088_type devtype; - void *control_data; struct max98088_pdata *pdata; unsigned int sysclk; struct max98088_cdata dai[2]; @@ -1697,13 +1696,19 @@ static struct snd_soc_dai_driver max98088_dai[] = { } }; -static int max98088_get_channel(const char *name) +static const char *eq_mode_name[] = {"EQ1 Mode", "EQ2 Mode"}; + +static int max98088_get_channel(struct snd_soc_codec *codec, const char *name) { - if (strcmp(name, "EQ1 Mode") == 0) - return 0; - if (strcmp(name, "EQ2 Mode") == 0) - return 1; - return -EINVAL; + int i; + + for (i = 0; i < ARRAY_SIZE(eq_mode_name); i++) + if (strcmp(name, eq_mode_name[i]) == 0) + return i; + + /* Shouldn't happen */ + dev_err(codec->dev, "Bad EQ channel name '%s'\n", name); + return -EINVAL; } static void max98088_setup_eq1(struct snd_soc_codec *codec) @@ -1807,10 +1812,13 @@ static int max98088_put_eq_enum(struct snd_kcontrol *kcontrol, struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); struct max98088_priv *max98088 = snd_soc_codec_get_drvdata(codec); struct max98088_pdata *pdata = max98088->pdata; - int channel = max98088_get_channel(kcontrol->id.name); + int channel = max98088_get_channel(codec, kcontrol->id.name); struct max98088_cdata *cdata; int sel = ucontrol->value.integer.value[0]; + if (channel < 0) + return channel; + cdata = &max98088->dai[channel]; if (sel >= pdata->eq_cfgcnt) @@ -1835,9 +1843,12 @@ static int max98088_get_eq_enum(struct snd_kcontrol *kcontrol, { struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); struct max98088_priv *max98088 = snd_soc_codec_get_drvdata(codec); - int channel = max98088_get_channel(kcontrol->id.name); + int channel = max98088_get_channel(codec, kcontrol->id.name); struct max98088_cdata *cdata; + if (channel < 0) + return channel; + cdata = &max98088->dai[channel]; ucontrol->value.enumerated.item[0] = cdata->eq_sel; return 0; @@ -1852,17 +1863,17 @@ static void max98088_handle_eq_pdata(struct snd_soc_codec *codec) int i, j; const char **t; int ret; - struct snd_kcontrol_new controls[] = { - SOC_ENUM_EXT("EQ1 Mode", + SOC_ENUM_EXT((char *)eq_mode_name[0], max98088->eq_enum, max98088_get_eq_enum, max98088_put_eq_enum), - SOC_ENUM_EXT("EQ2 Mode", + SOC_ENUM_EXT((char *)eq_mode_name[1], max98088->eq_enum, max98088_get_eq_enum, max98088_put_eq_enum), }; + BUILD_BUG_ON(ARRAY_SIZE(controls) != ARRAY_SIZE(eq_mode_name)); cfg = pdata->eq_cfg; cfgcnt = pdata->eq_cfgcnt; @@ -2066,7 +2077,6 @@ static int max98088_i2c_probe(struct i2c_client *i2c, max98088->devtype = id->driver_data; i2c_set_clientdata(i2c, max98088); - max98088->control_data = i2c; max98088->pdata = i2c->dev.platform_data; ret = snd_soc_register_codec(&i2c->dev, diff --git a/sound/soc/codecs/max98095.c b/sound/soc/codecs/max98095.c index 668434d4430..26d7b089fb9 100644 --- a/sound/soc/codecs/max98095.c +++ b/sound/soc/codecs/max98095.c @@ -40,7 +40,6 @@ struct max98095_cdata { struct max98095_priv { enum max98095_type devtype; - void *control_data; struct max98095_pdata *pdata; unsigned int sysclk; struct max98095_cdata dai[3]; @@ -618,14 +617,13 @@ static int max98095_volatile(struct snd_soc_codec *codec, unsigned int reg) static int max98095_hw_write(struct snd_soc_codec *codec, unsigned int reg, unsigned int value) { - u8 data[2]; + int ret; - data[0] = reg; - data[1] = value; - if (codec->hw_write(codec->control_data, data, 2) == 2) - return 0; - else - return -EIO; + codec->cache_bypass = 1; + ret = snd_soc_write(codec, reg, value); + codec->cache_bypass = 0; + + return ret ? -EIO : 0; } /* @@ -1992,12 +1990,19 @@ static void max98095_handle_eq_pdata(struct snd_soc_codec *codec) dev_err(codec->dev, "Failed to add EQ control: %d\n", ret); } -static int max98095_get_bq_channel(const char *name) +static const char *bq_mode_name[] = {"Biquad1 Mode", "Biquad2 Mode"}; + +static int max98095_get_bq_channel(struct snd_soc_codec *codec, + const char *name) { - if (strcmp(name, "Biquad1 Mode") == 0) - return 0; - if (strcmp(name, "Biquad2 Mode") == 0) - return 1; + int i; + + for (i = 0; i < ARRAY_SIZE(bq_mode_name); i++) + if (strcmp(name, bq_mode_name[i]) == 0) + return i; + + /* Shouldn't happen */ + dev_err(codec->dev, "Bad biquad channel name '%s'\n", name); return -EINVAL; } @@ -2007,14 +2012,15 @@ static int max98095_put_bq_enum(struct snd_kcontrol *kcontrol, struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); struct max98095_priv *max98095 = snd_soc_codec_get_drvdata(codec); struct max98095_pdata *pdata = max98095->pdata; - int channel = max98095_get_bq_channel(kcontrol->id.name); + int channel = max98095_get_bq_channel(codec, kcontrol->id.name); struct max98095_cdata *cdata; int sel = ucontrol->value.integer.value[0]; struct max98095_biquad_cfg *coef_set; int fs, best, best_val, i; int regmask, regsave; - BUG_ON(channel > 1); + if (channel < 0) + return channel; if (!pdata || !max98095->bq_textcnt) return 0; @@ -2066,9 +2072,12 @@ static int max98095_get_bq_enum(struct snd_kcontrol *kcontrol, { struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); struct max98095_priv *max98095 = snd_soc_codec_get_drvdata(codec); - int channel = max98095_get_bq_channel(kcontrol->id.name); + int channel = max98095_get_bq_channel(codec, kcontrol->id.name); struct max98095_cdata *cdata; + if (channel < 0) + return channel; + cdata = &max98095->dai[channel]; ucontrol->value.enumerated.item[0] = cdata->bq_sel; @@ -2086,15 +2095,16 @@ static void max98095_handle_bq_pdata(struct snd_soc_codec *codec) int ret; struct snd_kcontrol_new controls[] = { - SOC_ENUM_EXT("Biquad1 Mode", + SOC_ENUM_EXT((char *)bq_mode_name[0], max98095->bq_enum, max98095_get_bq_enum, max98095_put_bq_enum), - SOC_ENUM_EXT("Biquad2 Mode", + SOC_ENUM_EXT((char *)bq_mode_name[1], max98095->bq_enum, max98095_get_bq_enum, max98095_put_bq_enum), }; + BUILD_BUG_ON(ARRAY_SIZE(controls) != ARRAY_SIZE(bq_mode_name)); cfg = pdata->bq_cfg; cfgcnt = pdata->bq_cfgcnt; @@ -2337,7 +2347,6 @@ static int max98095_i2c_probe(struct i2c_client *i2c, max98095->devtype = id->driver_data; i2c_set_clientdata(i2c, max98095); - max98095->control_data = i2c; max98095->pdata = i2c->dev.platform_data; ret = snd_soc_register_codec(&i2c->dev, &soc_codec_dev_max98095, diff --git a/sound/soc/codecs/pcm3008.c b/sound/soc/codecs/pcm3008.c index bd8f26e4160..f7316519432 100644 --- a/sound/soc/codecs/pcm3008.c +++ b/sound/soc/codecs/pcm3008.c @@ -20,6 +20,7 @@ #include <linux/device.h> #include <linux/gpio.h> #include <linux/slab.h> +#include <linux/module.h> #include <sound/core.h> #include <sound/pcm.h> #include <sound/initval.h> diff --git a/sound/soc/codecs/rt5631.c b/sound/soc/codecs/rt5631.c new file mode 100644 index 00000000000..27a078cbb6e --- /dev/null +++ b/sound/soc/codecs/rt5631.c @@ -0,0 +1,1773 @@ +/* + * rt5631.c -- RT5631 ALSA Soc Audio driver + * + * Copyright 2011 Realtek Microelectronics + * + * Author: flove <flove@realtek.com> + * + * Based on WM8753.c + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + */ +#include <linux/module.h> +#include <linux/moduleparam.h> +#include <linux/init.h> +#include <linux/delay.h> +#include <linux/pm.h> +#include <linux/i2c.h> +#include <linux/platform_device.h> +#include <linux/spi/spi.h> +#include <sound/core.h> +#include <sound/pcm.h> +#include <sound/pcm_params.h> +#include <sound/soc.h> +#include <sound/soc-dapm.h> +#include <sound/initval.h> +#include <sound/tlv.h> + +#include "rt5631.h" + +struct rt5631_priv { + int codec_version; + int master; + int sysclk; + int rx_rate; + int bclk_rate; + int dmic_used_flag; +}; + +static const u16 rt5631_reg[RT5631_VENDOR_ID2 + 1] = { + [RT5631_SPK_OUT_VOL] = 0x8888, + [RT5631_HP_OUT_VOL] = 0x8080, + [RT5631_MONO_AXO_1_2_VOL] = 0xa080, + [RT5631_AUX_IN_VOL] = 0x0808, + [RT5631_ADC_REC_MIXER] = 0xf0f0, + [RT5631_VDAC_DIG_VOL] = 0x0010, + [RT5631_OUTMIXER_L_CTRL] = 0xffc0, + [RT5631_OUTMIXER_R_CTRL] = 0xffc0, + [RT5631_AXO1MIXER_CTRL] = 0x88c0, + [RT5631_AXO2MIXER_CTRL] = 0x88c0, + [RT5631_DIG_MIC_CTRL] = 0x3000, + [RT5631_MONO_INPUT_VOL] = 0x8808, + [RT5631_SPK_MIXER_CTRL] = 0xf8f8, + [RT5631_SPK_MONO_OUT_CTRL] = 0xfc00, + [RT5631_SPK_MONO_HP_OUT_CTRL] = 0x4440, + [RT5631_SDP_CTRL] = 0x8000, + [RT5631_MONO_SDP_CTRL] = 0x8000, + [RT5631_STEREO_AD_DA_CLK_CTRL] = 0x2010, + [RT5631_GEN_PUR_CTRL_REG] = 0x0e00, + [RT5631_INT_ST_IRQ_CTRL_2] = 0x071a, + [RT5631_MISC_CTRL] = 0x2040, + [RT5631_DEPOP_FUN_CTRL_2] = 0x8000, + [RT5631_SOFT_VOL_CTRL] = 0x07e0, + [RT5631_ALC_CTRL_1] = 0x0206, + [RT5631_ALC_CTRL_3] = 0x2000, + [RT5631_PSEUDO_SPATL_CTRL] = 0x0553, +}; + +/** + * rt5631_write_index - write index register of 2nd layer + */ +static void rt5631_write_index(struct snd_soc_codec *codec, + unsigned int reg, unsigned int value) +{ + snd_soc_write(codec, RT5631_INDEX_ADD, reg); + snd_soc_write(codec, RT5631_INDEX_DATA, value); +} + +/** + * rt5631_read_index - read index register of 2nd layer + */ +static unsigned int rt5631_read_index(struct snd_soc_codec *codec, + unsigned int reg) +{ + unsigned int value; + + snd_soc_write(codec, RT5631_INDEX_ADD, reg); + value = snd_soc_read(codec, RT5631_INDEX_DATA); + + return value; +} + +static int rt5631_reset(struct snd_soc_codec *codec) +{ + return snd_soc_write(codec, RT5631_RESET, 0); +} + +static int rt5631_volatile_register(struct snd_soc_codec *codec, + unsigned int reg) +{ + switch (reg) { + case RT5631_RESET: + case RT5631_INT_ST_IRQ_CTRL_2: + case RT5631_INDEX_ADD: + case RT5631_INDEX_DATA: + case RT5631_EQ_CTRL: + return 1; + default: + return 0; + } +} + +static int rt5631_readable_register(struct snd_soc_codec *codec, + unsigned int reg) +{ + switch (reg) { + case RT5631_RESET: + case RT5631_SPK_OUT_VOL: + case RT5631_HP_OUT_VOL: + case RT5631_MONO_AXO_1_2_VOL: + case RT5631_AUX_IN_VOL: + case RT5631_STEREO_DAC_VOL_1: + case RT5631_MIC_CTRL_1: + case RT5631_STEREO_DAC_VOL_2: + case RT5631_ADC_CTRL_1: + case RT5631_ADC_REC_MIXER: + case RT5631_ADC_CTRL_2: + case RT5631_VDAC_DIG_VOL: + case RT5631_OUTMIXER_L_CTRL: + case RT5631_OUTMIXER_R_CTRL: + case RT5631_AXO1MIXER_CTRL: + case RT5631_AXO2MIXER_CTRL: + case RT5631_MIC_CTRL_2: + case RT5631_DIG_MIC_CTRL: + case RT5631_MONO_INPUT_VOL: + case RT5631_SPK_MIXER_CTRL: + case RT5631_SPK_MONO_OUT_CTRL: + case RT5631_SPK_MONO_HP_OUT_CTRL: + case RT5631_SDP_CTRL: + case RT5631_MONO_SDP_CTRL: + case RT5631_STEREO_AD_DA_CLK_CTRL: + case RT5631_PWR_MANAG_ADD1: + case RT5631_PWR_MANAG_ADD2: + case RT5631_PWR_MANAG_ADD3: + case RT5631_PWR_MANAG_ADD4: + case RT5631_GEN_PUR_CTRL_REG: + case RT5631_GLOBAL_CLK_CTRL: + case RT5631_PLL_CTRL: + case RT5631_INT_ST_IRQ_CTRL_1: + case RT5631_INT_ST_IRQ_CTRL_2: + case RT5631_GPIO_CTRL: + case RT5631_MISC_CTRL: + case RT5631_DEPOP_FUN_CTRL_1: + case RT5631_DEPOP_FUN_CTRL_2: + case RT5631_JACK_DET_CTRL: + case RT5631_SOFT_VOL_CTRL: + case RT5631_ALC_CTRL_1: + case RT5631_ALC_CTRL_2: + case RT5631_ALC_CTRL_3: + case RT5631_PSEUDO_SPATL_CTRL: + case RT5631_INDEX_ADD: + case RT5631_INDEX_DATA: + case RT5631_EQ_CTRL: + case RT5631_VENDOR_ID: + case RT5631_VENDOR_ID1: + case RT5631_VENDOR_ID2: + return 1; + default: + return 0; + } +} + +static const DECLARE_TLV_DB_SCALE(out_vol_tlv, -4650, 150, 0); +static const DECLARE_TLV_DB_SCALE(dac_vol_tlv, -95625, 375, 0); +static const DECLARE_TLV_DB_SCALE(in_vol_tlv, -3450, 150, 0); +/* {0, +20, +24, +30, +35, +40, +44, +50, +52}dB */ +static unsigned int mic_bst_tlv[] = { + TLV_DB_RANGE_HEAD(6), + 0, 0, TLV_DB_SCALE_ITEM(0, 0, 0), + 1, 1, TLV_DB_SCALE_ITEM(2000, 0, 0), + 2, 2, TLV_DB_SCALE_ITEM(2400, 0, 0), + 3, 5, TLV_DB_SCALE_ITEM(3000, 500, 0), + 6, 6, TLV_DB_SCALE_ITEM(4400, 0, 0), + 7, 7, TLV_DB_SCALE_ITEM(5000, 0, 0), + 8, 8, TLV_DB_SCALE_ITEM(5200, 0, 0), +}; + +static int rt5631_dmic_get(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); + struct rt5631_priv *rt5631 = snd_soc_codec_get_drvdata(codec); + + ucontrol->value.integer.value[0] = rt5631->dmic_used_flag; + + return 0; +} + +static int rt5631_dmic_put(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); + struct rt5631_priv *rt5631 = snd_soc_codec_get_drvdata(codec); + + rt5631->dmic_used_flag = ucontrol->value.integer.value[0]; + return 0; +} + +/* MIC Input Type */ +static const char *rt5631_input_mode[] = { + "Single ended", "Differential"}; + +static const SOC_ENUM_SINGLE_DECL( + rt5631_mic1_mode_enum, RT5631_MIC_CTRL_1, + RT5631_MIC1_DIFF_INPUT_SHIFT, rt5631_input_mode); + +static const SOC_ENUM_SINGLE_DECL( + rt5631_mic2_mode_enum, RT5631_MIC_CTRL_1, + RT5631_MIC2_DIFF_INPUT_SHIFT, rt5631_input_mode); + +/* MONO Input Type */ +static const SOC_ENUM_SINGLE_DECL( + rt5631_monoin_mode_enum, RT5631_MONO_INPUT_VOL, + RT5631_MONO_DIFF_INPUT_SHIFT, rt5631_input_mode); + +/* SPK Ratio Gain Control */ +static const char *rt5631_spk_ratio[] = {"1.00x", "1.09x", "1.27x", "1.44x", + "1.56x", "1.68x", "1.99x", "2.34x"}; + +static const SOC_ENUM_SINGLE_DECL( + rt5631_spk_ratio_enum, RT5631_GEN_PUR_CTRL_REG, + RT5631_SPK_AMP_RATIO_CTRL_SHIFT, rt5631_spk_ratio); + +static const struct snd_kcontrol_new rt5631_snd_controls[] = { + /* MIC */ + SOC_ENUM("MIC1 Mode Control", rt5631_mic1_mode_enum), + SOC_SINGLE_TLV("MIC1 Boost", RT5631_MIC_CTRL_2, + RT5631_MIC1_BOOST_SHIFT, 8, 0, mic_bst_tlv), + SOC_ENUM("MIC2 Mode Control", rt5631_mic2_mode_enum), + SOC_SINGLE_TLV("MIC2 Boost", RT5631_MIC_CTRL_2, + RT5631_MIC2_BOOST_SHIFT, 8, 0, mic_bst_tlv), + /* MONO IN */ + SOC_ENUM("MONOIN Mode Control", rt5631_monoin_mode_enum), + SOC_DOUBLE_TLV("MONOIN_RX Capture Volume", RT5631_MONO_INPUT_VOL, + RT5631_L_VOL_SHIFT, RT5631_R_VOL_SHIFT, + RT5631_VOL_MASK, 1, in_vol_tlv), + /* AXI */ + SOC_DOUBLE_TLV("AXI Capture Volume", RT5631_AUX_IN_VOL, + RT5631_L_VOL_SHIFT, RT5631_R_VOL_SHIFT, + RT5631_VOL_MASK, 1, in_vol_tlv), + /* DAC */ + SOC_DOUBLE_TLV("PCM Playback Volume", RT5631_STEREO_DAC_VOL_2, + RT5631_L_VOL_SHIFT, RT5631_R_VOL_SHIFT, + RT5631_DAC_VOL_MASK, 1, dac_vol_tlv), + SOC_DOUBLE("PCM Playback Switch", RT5631_STEREO_DAC_VOL_1, + RT5631_L_MUTE_SHIFT, RT5631_R_MUTE_SHIFT, 1, 1), + /* AXO */ + SOC_SINGLE("AXO1 Playback Switch", RT5631_MONO_AXO_1_2_VOL, + RT5631_L_MUTE_SHIFT, 1, 1), + SOC_SINGLE("AXO2 Playback Switch", RT5631_MONO_AXO_1_2_VOL, + RT5631_R_VOL_SHIFT, 1, 1), + /* OUTVOL */ + SOC_DOUBLE("OUTVOL Channel Switch", RT5631_SPK_OUT_VOL, + RT5631_L_EN_SHIFT, RT5631_R_EN_SHIFT, 1, 0), + + /* SPK */ + SOC_DOUBLE("Speaker Playback Switch", RT5631_SPK_OUT_VOL, + RT5631_L_MUTE_SHIFT, RT5631_R_MUTE_SHIFT, 1, 1), + SOC_DOUBLE_TLV("Speaker Playback Volume", RT5631_SPK_OUT_VOL, + RT5631_L_VOL_SHIFT, RT5631_R_VOL_SHIFT, 39, 1, out_vol_tlv), + /* MONO OUT */ + SOC_SINGLE("MONO Playback Switch", RT5631_MONO_AXO_1_2_VOL, + RT5631_MUTE_MONO_SHIFT, 1, 1), + /* HP */ + SOC_DOUBLE("HP Playback Switch", RT5631_HP_OUT_VOL, + RT5631_L_MUTE_SHIFT, RT5631_R_MUTE_SHIFT, 1, 1), + SOC_DOUBLE_TLV("HP Playback Volume", RT5631_HP_OUT_VOL, + RT5631_L_VOL_SHIFT, RT5631_R_VOL_SHIFT, + RT5631_VOL_MASK, 1, out_vol_tlv), + /* DMIC */ + SOC_SINGLE_EXT("DMIC Switch", 0, 0, 1, 0, + rt5631_dmic_get, rt5631_dmic_put), + SOC_DOUBLE("DMIC Capture Switch", RT5631_DIG_MIC_CTRL, + RT5631_DMIC_L_CH_MUTE_SHIFT, + RT5631_DMIC_R_CH_MUTE_SHIFT, 1, 1), + + /* SPK Ratio Gain Control */ + SOC_ENUM("SPK Ratio Control", rt5631_spk_ratio_enum), +}; + +static int check_sysclk1_source(struct snd_soc_dapm_widget *source, + struct snd_soc_dapm_widget *sink) +{ + unsigned int reg; + + reg = snd_soc_read(source->codec, RT5631_GLOBAL_CLK_CTRL); + return reg & RT5631_SYSCLK_SOUR_SEL_PLL; +} + +static int check_dmic_used(struct snd_soc_dapm_widget *source, + struct snd_soc_dapm_widget *sink) +{ + struct rt5631_priv *rt5631 = snd_soc_codec_get_drvdata(source->codec); + return rt5631->dmic_used_flag; +} + +static int check_dacl_to_outmixl(struct snd_soc_dapm_widget *source, + struct snd_soc_dapm_widget *sink) +{ + unsigned int reg; + + reg = snd_soc_read(source->codec, RT5631_OUTMIXER_L_CTRL); + return !(reg & RT5631_M_DAC_L_TO_OUTMIXER_L); +} + +static int check_dacr_to_outmixr(struct snd_soc_dapm_widget *source, + struct snd_soc_dapm_widget *sink) +{ + unsigned int reg; + + reg = snd_soc_read(source->codec, RT5631_OUTMIXER_R_CTRL); + return !(reg & RT5631_M_DAC_R_TO_OUTMIXER_R); +} + +static int check_dacl_to_spkmixl(struct snd_soc_dapm_widget *source, + struct snd_soc_dapm_widget *sink) +{ + unsigned int reg; + + reg = snd_soc_read(source->codec, RT5631_SPK_MIXER_CTRL); + return !(reg & RT5631_M_DAC_L_TO_SPKMIXER_L); +} + +static int check_dacr_to_spkmixr(struct snd_soc_dapm_widget *source, + struct snd_soc_dapm_widget *sink) +{ + unsigned int reg; + + reg = snd_soc_read(source->codec, RT5631_SPK_MIXER_CTRL); + return !(reg & RT5631_M_DAC_R_TO_SPKMIXER_R); +} + +static int check_adcl_select(struct snd_soc_dapm_widget *source, + struct snd_soc_dapm_widget *sink) +{ + unsigned int reg; + + reg = snd_soc_read(source->codec, RT5631_ADC_REC_MIXER); + return !(reg & RT5631_M_MIC1_TO_RECMIXER_L); +} + +static int check_adcr_select(struct snd_soc_dapm_widget *source, + struct snd_soc_dapm_widget *sink) +{ + unsigned int reg; + + reg = snd_soc_read(source->codec, RT5631_ADC_REC_MIXER); + return !(reg & RT5631_M_MIC2_TO_RECMIXER_R); +} + +/** + * onebit_depop_power_stage - auto depop in power stage. + * @enable: power on/off + * + * When power on/off headphone, the depop sequence is done by hardware. + */ +static void onebit_depop_power_stage(struct snd_soc_codec *codec, int enable) +{ + unsigned int soft_vol, hp_zc; + + /* enable one-bit depop function */ + snd_soc_update_bits(codec, RT5631_DEPOP_FUN_CTRL_2, + RT5631_EN_ONE_BIT_DEPOP, 0); + + /* keep soft volume and zero crossing setting */ + soft_vol = snd_soc_read(codec, RT5631_SOFT_VOL_CTRL); + snd_soc_write(codec, RT5631_SOFT_VOL_CTRL, 0); + hp_zc = snd_soc_read(codec, RT5631_INT_ST_IRQ_CTRL_2); + snd_soc_write(codec, RT5631_INT_ST_IRQ_CTRL_2, hp_zc & 0xf7ff); + if (enable) { + /* config one-bit depop parameter */ + rt5631_write_index(codec, RT5631_TEST_MODE_CTRL, 0x84c0); + rt5631_write_index(codec, RT5631_SPK_INTL_CTRL, 0x309f); + rt5631_write_index(codec, RT5631_CP_INTL_REG2, 0x6530); + /* power on capless block */ + snd_soc_write(codec, RT5631_DEPOP_FUN_CTRL_2, + RT5631_EN_CAP_FREE_DEPOP); + } else { + /* power off capless block */ + snd_soc_write(codec, RT5631_DEPOP_FUN_CTRL_2, 0); + msleep(100); + } + + /* recover soft volume and zero crossing setting */ + snd_soc_write(codec, RT5631_SOFT_VOL_CTRL, soft_vol); + snd_soc_write(codec, RT5631_INT_ST_IRQ_CTRL_2, hp_zc); +} + +/** + * onebit_depop_mute_stage - auto depop in mute stage. + * @enable: mute/unmute + * + * When mute/unmute headphone, the depop sequence is done by hardware. + */ +static void onebit_depop_mute_stage(struct snd_soc_codec *codec, int enable) +{ + unsigned int soft_vol, hp_zc; + + /* enable one-bit depop function */ + snd_soc_update_bits(codec, RT5631_DEPOP_FUN_CTRL_2, + RT5631_EN_ONE_BIT_DEPOP, 0); + + /* keep soft volume and zero crossing setting */ + soft_vol = snd_soc_read(codec, RT5631_SOFT_VOL_CTRL); + snd_soc_write(codec, RT5631_SOFT_VOL_CTRL, 0); + hp_zc = snd_soc_read(codec, RT5631_INT_ST_IRQ_CTRL_2); + snd_soc_write(codec, RT5631_INT_ST_IRQ_CTRL_2, hp_zc & 0xf7ff); + if (enable) { + schedule_timeout_uninterruptible(msecs_to_jiffies(10)); + /* config one-bit depop parameter */ + rt5631_write_index(codec, RT5631_SPK_INTL_CTRL, 0x307f); + snd_soc_update_bits(codec, RT5631_HP_OUT_VOL, + RT5631_L_MUTE | RT5631_R_MUTE, 0); + msleep(300); + } else { + snd_soc_update_bits(codec, RT5631_HP_OUT_VOL, + RT5631_L_MUTE | RT5631_R_MUTE, + RT5631_L_MUTE | RT5631_R_MUTE); + msleep(100); + } + + /* recover soft volume and zero crossing setting */ + snd_soc_write(codec, RT5631_SOFT_VOL_CTRL, soft_vol); + snd_soc_write(codec, RT5631_INT_ST_IRQ_CTRL_2, hp_zc); +} + +/** + * onebit_depop_power_stage - step by step depop sequence in power stage. + * @enable: power on/off + * + * When power on/off headphone, the depop sequence is done in step by step. + */ +static void depop_seq_power_stage(struct snd_soc_codec *codec, int enable) +{ + unsigned int soft_vol, hp_zc; + + /* depop control by register */ + snd_soc_update_bits(codec, RT5631_DEPOP_FUN_CTRL_2, + RT5631_EN_ONE_BIT_DEPOP, RT5631_EN_ONE_BIT_DEPOP); + + /* keep soft volume and zero crossing setting */ + soft_vol = snd_soc_read(codec, RT5631_SOFT_VOL_CTRL); + snd_soc_write(codec, RT5631_SOFT_VOL_CTRL, 0); + hp_zc = snd_soc_read(codec, RT5631_INT_ST_IRQ_CTRL_2); + snd_soc_write(codec, RT5631_INT_ST_IRQ_CTRL_2, hp_zc & 0xf7ff); + if (enable) { + /* config depop sequence parameter */ + rt5631_write_index(codec, RT5631_SPK_INTL_CTRL, 0x303e); + + /* power on headphone and charge pump */ + snd_soc_update_bits(codec, RT5631_PWR_MANAG_ADD3, + RT5631_PWR_CHARGE_PUMP | RT5631_PWR_HP_L_AMP | + RT5631_PWR_HP_R_AMP, + RT5631_PWR_CHARGE_PUMP | RT5631_PWR_HP_L_AMP | + RT5631_PWR_HP_R_AMP); + + /* power on soft generator and depop mode2 */ + snd_soc_write(codec, RT5631_DEPOP_FUN_CTRL_1, + RT5631_POW_ON_SOFT_GEN | RT5631_EN_DEPOP2_FOR_HP); + msleep(100); + + /* stop depop mode */ + snd_soc_update_bits(codec, RT5631_PWR_MANAG_ADD3, + RT5631_PWR_HP_DEPOP_DIS, RT5631_PWR_HP_DEPOP_DIS); + } else { + /* config depop sequence parameter */ + rt5631_write_index(codec, RT5631_SPK_INTL_CTRL, 0x303F); + snd_soc_write(codec, RT5631_DEPOP_FUN_CTRL_1, + RT5631_POW_ON_SOFT_GEN | RT5631_EN_MUTE_UNMUTE_DEPOP | + RT5631_PD_HPAMP_L_ST_UP | RT5631_PD_HPAMP_R_ST_UP); + msleep(75); + snd_soc_write(codec, RT5631_DEPOP_FUN_CTRL_1, + RT5631_POW_ON_SOFT_GEN | RT5631_PD_HPAMP_L_ST_UP | + RT5631_PD_HPAMP_R_ST_UP); + + /* start depop mode */ + snd_soc_update_bits(codec, RT5631_PWR_MANAG_ADD3, + RT5631_PWR_HP_DEPOP_DIS, 0); + + /* config depop sequence parameter */ + snd_soc_write(codec, RT5631_DEPOP_FUN_CTRL_1, + RT5631_POW_ON_SOFT_GEN | RT5631_EN_DEPOP2_FOR_HP | + RT5631_PD_HPAMP_L_ST_UP | RT5631_PD_HPAMP_R_ST_UP); + msleep(80); + snd_soc_write(codec, RT5631_DEPOP_FUN_CTRL_1, + RT5631_POW_ON_SOFT_GEN); + + /* power down headphone and charge pump */ + snd_soc_update_bits(codec, RT5631_PWR_MANAG_ADD3, + RT5631_PWR_CHARGE_PUMP | RT5631_PWR_HP_L_AMP | + RT5631_PWR_HP_R_AMP, 0); + } + + /* recover soft volume and zero crossing setting */ + snd_soc_write(codec, RT5631_SOFT_VOL_CTRL, soft_vol); + snd_soc_write(codec, RT5631_INT_ST_IRQ_CTRL_2, hp_zc); +} + +/** + * depop_seq_mute_stage - step by step depop sequence in mute stage. + * @enable: mute/unmute + * + * When mute/unmute headphone, the depop sequence is done in step by step. + */ +static void depop_seq_mute_stage(struct snd_soc_codec *codec, int enable) +{ + unsigned int soft_vol, hp_zc; + + /* depop control by register */ + snd_soc_update_bits(codec, RT5631_DEPOP_FUN_CTRL_2, + RT5631_EN_ONE_BIT_DEPOP, RT5631_EN_ONE_BIT_DEPOP); + + /* keep soft volume and zero crossing setting */ + soft_vol = snd_soc_read(codec, RT5631_SOFT_VOL_CTRL); + snd_soc_write(codec, RT5631_SOFT_VOL_CTRL, 0); + hp_zc = snd_soc_read(codec, RT5631_INT_ST_IRQ_CTRL_2); + snd_soc_write(codec, RT5631_INT_ST_IRQ_CTRL_2, hp_zc & 0xf7ff); + if (enable) { + schedule_timeout_uninterruptible(msecs_to_jiffies(10)); + + /* config depop sequence parameter */ + rt5631_write_index(codec, RT5631_SPK_INTL_CTRL, 0x302f); + snd_soc_write(codec, RT5631_DEPOP_FUN_CTRL_1, + RT5631_POW_ON_SOFT_GEN | RT5631_EN_MUTE_UNMUTE_DEPOP | + RT5631_EN_HP_R_M_UN_MUTE_DEPOP | + RT5631_EN_HP_L_M_UN_MUTE_DEPOP); + + snd_soc_update_bits(codec, RT5631_HP_OUT_VOL, + RT5631_L_MUTE | RT5631_R_MUTE, 0); + msleep(160); + } else { + /* config depop sequence parameter */ + rt5631_write_index(codec, RT5631_SPK_INTL_CTRL, 0x302f); + snd_soc_write(codec, RT5631_DEPOP_FUN_CTRL_1, + RT5631_POW_ON_SOFT_GEN | RT5631_EN_MUTE_UNMUTE_DEPOP | + RT5631_EN_HP_R_M_UN_MUTE_DEPOP | + RT5631_EN_HP_L_M_UN_MUTE_DEPOP); + + snd_soc_update_bits(codec, RT5631_HP_OUT_VOL, + RT5631_L_MUTE | RT5631_R_MUTE, + RT5631_L_MUTE | RT5631_R_MUTE); + msleep(150); + } + + /* recover soft volume and zero crossing setting */ + snd_soc_write(codec, RT5631_SOFT_VOL_CTRL, soft_vol); + snd_soc_write(codec, RT5631_INT_ST_IRQ_CTRL_2, hp_zc); +} + +static int hp_event(struct snd_soc_dapm_widget *w, + struct snd_kcontrol *kcontrol, int event) +{ + struct snd_soc_codec *codec = w->codec; + struct rt5631_priv *rt5631 = snd_soc_codec_get_drvdata(codec); + + switch (event) { + case SND_SOC_DAPM_PRE_PMD: + if (rt5631->codec_version) { + onebit_depop_mute_stage(codec, 0); + onebit_depop_power_stage(codec, 0); + } else { + depop_seq_mute_stage(codec, 0); + depop_seq_power_stage(codec, 0); + } + break; + + case SND_SOC_DAPM_POST_PMU: + if (rt5631->codec_version) { + onebit_depop_power_stage(codec, 1); + onebit_depop_mute_stage(codec, 1); + } else { + depop_seq_power_stage(codec, 1); + depop_seq_mute_stage(codec, 1); + } + break; + + default: + break; + } + + return 0; +} + +static int set_dmic_params(struct snd_soc_dapm_widget *w, + struct snd_kcontrol *kcontrol, int event) +{ + struct snd_soc_codec *codec = w->codec; + struct rt5631_priv *rt5631 = snd_soc_codec_get_drvdata(codec); + + switch (rt5631->rx_rate) { + case 44100: + case 48000: + snd_soc_update_bits(codec, RT5631_DIG_MIC_CTRL, + RT5631_DMIC_CLK_CTRL_MASK, + RT5631_DMIC_CLK_CTRL_TO_32FS); + break; + + case 32000: + case 22050: + snd_soc_update_bits(codec, RT5631_DIG_MIC_CTRL, + RT5631_DMIC_CLK_CTRL_MASK, + RT5631_DMIC_CLK_CTRL_TO_64FS); + break; + + case 16000: + case 11025: + case 8000: + snd_soc_update_bits(codec, RT5631_DIG_MIC_CTRL, + RT5631_DMIC_CLK_CTRL_MASK, + RT5631_DMIC_CLK_CTRL_TO_128FS); + break; + + default: + return -EINVAL; + } + + return 0; +} + +static const struct snd_kcontrol_new rt5631_recmixl_mixer_controls[] = { + SOC_DAPM_SINGLE("OUTMIXL Capture Switch", RT5631_ADC_REC_MIXER, + RT5631_M_OUTMIXL_RECMIXL_BIT, 1, 1), + SOC_DAPM_SINGLE("MIC1_BST1 Capture Switch", RT5631_ADC_REC_MIXER, + RT5631_M_MIC1_RECMIXL_BIT, 1, 1), + SOC_DAPM_SINGLE("AXILVOL Capture Switch", RT5631_ADC_REC_MIXER, + RT5631_M_AXIL_RECMIXL_BIT, 1, 1), + SOC_DAPM_SINGLE("MONOIN_RX Capture Switch", RT5631_ADC_REC_MIXER, + RT5631_M_MONO_IN_RECMIXL_BIT, 1, 1), +}; + +static const struct snd_kcontrol_new rt5631_recmixr_mixer_controls[] = { + SOC_DAPM_SINGLE("MONOIN_RX Capture Switch", RT5631_ADC_REC_MIXER, + RT5631_M_MONO_IN_RECMIXR_BIT, 1, 1), + SOC_DAPM_SINGLE("AXIRVOL Capture Switch", RT5631_ADC_REC_MIXER, + RT5631_M_AXIR_RECMIXR_BIT, 1, 1), + SOC_DAPM_SINGLE("MIC2_BST2 Capture Switch", RT5631_ADC_REC_MIXER, + RT5631_M_MIC2_RECMIXR_BIT, 1, 1), + SOC_DAPM_SINGLE("OUTMIXR Capture Switch", RT5631_ADC_REC_MIXER, + RT5631_M_OUTMIXR_RECMIXR_BIT, 1, 1), +}; + +static const struct snd_kcontrol_new rt5631_spkmixl_mixer_controls[] = { + SOC_DAPM_SINGLE("RECMIXL Playback Switch", RT5631_SPK_MIXER_CTRL, + RT5631_M_RECMIXL_SPKMIXL_BIT, 1, 1), + SOC_DAPM_SINGLE("MIC1_P Playback Switch", RT5631_SPK_MIXER_CTRL, + RT5631_M_MIC1P_SPKMIXL_BIT, 1, 1), + SOC_DAPM_SINGLE("DACL Playback Switch", RT5631_SPK_MIXER_CTRL, + RT5631_M_DACL_SPKMIXL_BIT, 1, 1), + SOC_DAPM_SINGLE("OUTMIXL Playback Switch", RT5631_SPK_MIXER_CTRL, + RT5631_M_OUTMIXL_SPKMIXL_BIT, 1, 1), +}; + +static const struct snd_kcontrol_new rt5631_spkmixr_mixer_controls[] = { + SOC_DAPM_SINGLE("OUTMIXR Playback Switch", RT5631_SPK_MIXER_CTRL, + RT5631_M_OUTMIXR_SPKMIXR_BIT, 1, 1), + SOC_DAPM_SINGLE("DACR Playback Switch", RT5631_SPK_MIXER_CTRL, + RT5631_M_DACR_SPKMIXR_BIT, 1, 1), + SOC_DAPM_SINGLE("MIC2_P Playback Switch", RT5631_SPK_MIXER_CTRL, + RT5631_M_MIC2P_SPKMIXR_BIT, 1, 1), + SOC_DAPM_SINGLE("RECMIXR Playback Switch", RT5631_SPK_MIXER_CTRL, + RT5631_M_RECMIXR_SPKMIXR_BIT, 1, 1), +}; + +static const struct snd_kcontrol_new rt5631_outmixl_mixer_controls[] = { + SOC_DAPM_SINGLE("RECMIXL Playback Switch", RT5631_OUTMIXER_L_CTRL, + RT5631_M_RECMIXL_OUTMIXL_BIT, 1, 1), + SOC_DAPM_SINGLE("RECMIXR Playback Switch", RT5631_OUTMIXER_L_CTRL, + RT5631_M_RECMIXR_OUTMIXL_BIT, 1, 1), + SOC_DAPM_SINGLE("DACL Playback Switch", RT5631_OUTMIXER_L_CTRL, + RT5631_M_DACL_OUTMIXL_BIT, 1, 1), + SOC_DAPM_SINGLE("MIC1_BST1 Playback Switch", RT5631_OUTMIXER_L_CTRL, + RT5631_M_MIC1_OUTMIXL_BIT, 1, 1), + SOC_DAPM_SINGLE("MIC2_BST2 Playback Switch", RT5631_OUTMIXER_L_CTRL, + RT5631_M_MIC2_OUTMIXL_BIT, 1, 1), + SOC_DAPM_SINGLE("MONOIN_RXP Playback Switch", RT5631_OUTMIXER_L_CTRL, + RT5631_M_MONO_INP_OUTMIXL_BIT, 1, 1), + SOC_DAPM_SINGLE("AXILVOL Playback Switch", RT5631_OUTMIXER_L_CTRL, + RT5631_M_AXIL_OUTMIXL_BIT, 1, 1), + SOC_DAPM_SINGLE("AXIRVOL Playback Switch", RT5631_OUTMIXER_L_CTRL, + RT5631_M_AXIR_OUTMIXL_BIT, 1, 1), + SOC_DAPM_SINGLE("VDAC Playback Switch", RT5631_OUTMIXER_L_CTRL, + RT5631_M_VDAC_OUTMIXL_BIT, 1, 1), +}; + +static const struct snd_kcontrol_new rt5631_outmixr_mixer_controls[] = { + SOC_DAPM_SINGLE("VDAC Playback Switch", RT5631_OUTMIXER_R_CTRL, + RT5631_M_VDAC_OUTMIXR_BIT, 1, 1), + SOC_DAPM_SINGLE("AXIRVOL Playback Switch", RT5631_OUTMIXER_R_CTRL, + RT5631_M_AXIR_OUTMIXR_BIT, 1, 1), + SOC_DAPM_SINGLE("AXILVOL Playback Switch", RT5631_OUTMIXER_R_CTRL, + RT5631_M_AXIL_OUTMIXR_BIT, 1, 1), + SOC_DAPM_SINGLE("MONOIN_RXN Playback Switch", RT5631_OUTMIXER_R_CTRL, + RT5631_M_MONO_INN_OUTMIXR_BIT, 1, 1), + SOC_DAPM_SINGLE("MIC2_BST2 Playback Switch", RT5631_OUTMIXER_R_CTRL, + RT5631_M_MIC2_OUTMIXR_BIT, 1, 1), + SOC_DAPM_SINGLE("MIC1_BST1 Playback Switch", RT5631_OUTMIXER_R_CTRL, + RT5631_M_MIC1_OUTMIXR_BIT, 1, 1), + SOC_DAPM_SINGLE("DACR Playback Switch", RT5631_OUTMIXER_R_CTRL, + RT5631_M_DACR_OUTMIXR_BIT, 1, 1), + SOC_DAPM_SINGLE("RECMIXR Playback Switch", RT5631_OUTMIXER_R_CTRL, + RT5631_M_RECMIXR_OUTMIXR_BIT, 1, 1), + SOC_DAPM_SINGLE("RECMIXL Playback Switch", RT5631_OUTMIXER_R_CTRL, + RT5631_M_RECMIXL_OUTMIXR_BIT, 1, 1), +}; + +static const struct snd_kcontrol_new rt5631_AXO1MIX_mixer_controls[] = { + SOC_DAPM_SINGLE("MIC1_BST1 Playback Switch", RT5631_AXO1MIXER_CTRL, + RT5631_M_MIC1_AXO1MIX_BIT , 1, 1), + SOC_DAPM_SINGLE("MIC2_BST2 Playback Switch", RT5631_AXO1MIXER_CTRL, + RT5631_M_MIC2_AXO1MIX_BIT, 1, 1), + SOC_DAPM_SINGLE("OUTVOLL Playback Switch", RT5631_AXO1MIXER_CTRL, + RT5631_M_OUTMIXL_AXO1MIX_BIT , 1 , 1), + SOC_DAPM_SINGLE("OUTVOLR Playback Switch", RT5631_AXO1MIXER_CTRL, + RT5631_M_OUTMIXR_AXO1MIX_BIT, 1, 1), +}; + +static const struct snd_kcontrol_new rt5631_AXO2MIX_mixer_controls[] = { + SOC_DAPM_SINGLE("MIC1_BST1 Playback Switch", RT5631_AXO2MIXER_CTRL, + RT5631_M_MIC1_AXO2MIX_BIT, 1, 1), + SOC_DAPM_SINGLE("MIC2_BST2 Playback Switch", RT5631_AXO2MIXER_CTRL, + RT5631_M_MIC2_AXO2MIX_BIT, 1, 1), + SOC_DAPM_SINGLE("OUTVOLL Playback Switch", RT5631_AXO2MIXER_CTRL, + RT5631_M_OUTMIXL_AXO2MIX_BIT, 1, 1), + SOC_DAPM_SINGLE("OUTVOLR Playback Switch", RT5631_AXO2MIXER_CTRL, + RT5631_M_OUTMIXR_AXO2MIX_BIT, 1 , 1), +}; + +static const struct snd_kcontrol_new rt5631_spolmix_mixer_controls[] = { + SOC_DAPM_SINGLE("SPKVOLL Playback Switch", RT5631_SPK_MONO_OUT_CTRL, + RT5631_M_SPKVOLL_SPOLMIX_BIT, 1, 1), + SOC_DAPM_SINGLE("SPKVOLR Playback Switch", RT5631_SPK_MONO_OUT_CTRL, + RT5631_M_SPKVOLR_SPOLMIX_BIT, 1, 1), +}; + +static const struct snd_kcontrol_new rt5631_spormix_mixer_controls[] = { + SOC_DAPM_SINGLE("SPKVOLL Playback Switch", RT5631_SPK_MONO_OUT_CTRL, + RT5631_M_SPKVOLL_SPORMIX_BIT, 1, 1), + SOC_DAPM_SINGLE("SPKVOLR Playback Switch", RT5631_SPK_MONO_OUT_CTRL, + RT5631_M_SPKVOLR_SPORMIX_BIT, 1, 1), +}; + +static const struct snd_kcontrol_new rt5631_monomix_mixer_controls[] = { + SOC_DAPM_SINGLE("OUTVOLL Playback Switch", RT5631_SPK_MONO_OUT_CTRL, + RT5631_M_OUTVOLL_MONOMIX_BIT, 1, 1), + SOC_DAPM_SINGLE("OUTVOLR Playback Switch", RT5631_SPK_MONO_OUT_CTRL, + RT5631_M_OUTVOLR_MONOMIX_BIT, 1, 1), +}; + +/* Left SPK Volume Input */ +static const char *rt5631_spkvoll_sel[] = {"Vmid", "SPKMIXL"}; + +static const SOC_ENUM_SINGLE_DECL( + rt5631_spkvoll_enum, RT5631_SPK_OUT_VOL, + RT5631_L_EN_SHIFT, rt5631_spkvoll_sel); + +static const struct snd_kcontrol_new rt5631_spkvoll_mux_control = + SOC_DAPM_ENUM("Left SPKVOL SRC", rt5631_spkvoll_enum); + +/* Left HP Volume Input */ +static const char *rt5631_hpvoll_sel[] = {"Vmid", "OUTMIXL"}; + +static const SOC_ENUM_SINGLE_DECL( + rt5631_hpvoll_enum, RT5631_HP_OUT_VOL, + RT5631_L_EN_SHIFT, rt5631_hpvoll_sel); + +static const struct snd_kcontrol_new rt5631_hpvoll_mux_control = + SOC_DAPM_ENUM("Left HPVOL SRC", rt5631_hpvoll_enum); + +/* Left Out Volume Input */ +static const char *rt5631_outvoll_sel[] = {"Vmid", "OUTMIXL"}; + +static const SOC_ENUM_SINGLE_DECL( + rt5631_outvoll_enum, RT5631_MONO_AXO_1_2_VOL, + RT5631_L_EN_SHIFT, rt5631_outvoll_sel); + +static const struct snd_kcontrol_new rt5631_outvoll_mux_control = + SOC_DAPM_ENUM("Left OUTVOL SRC", rt5631_outvoll_enum); + +/* Right Out Volume Input */ +static const char *rt5631_outvolr_sel[] = {"Vmid", "OUTMIXR"}; + +static const SOC_ENUM_SINGLE_DECL( + rt5631_outvolr_enum, RT5631_MONO_AXO_1_2_VOL, + RT5631_R_EN_SHIFT, rt5631_outvolr_sel); + +static const struct snd_kcontrol_new rt5631_outvolr_mux_control = + SOC_DAPM_ENUM("Right OUTVOL SRC", rt5631_outvolr_enum); + +/* Right HP Volume Input */ +static const char *rt5631_hpvolr_sel[] = {"Vmid", "OUTMIXR"}; + +static const SOC_ENUM_SINGLE_DECL( + rt5631_hpvolr_enum, RT5631_HP_OUT_VOL, + RT5631_R_EN_SHIFT, rt5631_hpvolr_sel); + +static const struct snd_kcontrol_new rt5631_hpvolr_mux_control = + SOC_DAPM_ENUM("Right HPVOL SRC", rt5631_hpvolr_enum); + +/* Right SPK Volume Input */ +static const char *rt5631_spkvolr_sel[] = {"Vmid", "SPKMIXR"}; + +static const SOC_ENUM_SINGLE_DECL( + rt5631_spkvolr_enum, RT5631_SPK_OUT_VOL, + RT5631_R_EN_SHIFT, rt5631_spkvolr_sel); + +static const struct snd_kcontrol_new rt5631_spkvolr_mux_control = + SOC_DAPM_ENUM("Right SPKVOL SRC", rt5631_spkvolr_enum); + +/* SPO Left Channel Input */ +static const char *rt5631_spol_src_sel[] = { + "SPOLMIX", "MONOIN_RX", "VDAC", "DACL"}; + +static const SOC_ENUM_SINGLE_DECL( + rt5631_spol_src_enum, RT5631_SPK_MONO_HP_OUT_CTRL, + RT5631_SPK_L_MUX_SEL_SHIFT, rt5631_spol_src_sel); + +static const struct snd_kcontrol_new rt5631_spol_mux_control = + SOC_DAPM_ENUM("SPOL SRC", rt5631_spol_src_enum); + +/* SPO Right Channel Input */ +static const char *rt5631_spor_src_sel[] = { + "SPORMIX", "MONOIN_RX", "VDAC", "DACR"}; + +static const SOC_ENUM_SINGLE_DECL( + rt5631_spor_src_enum, RT5631_SPK_MONO_HP_OUT_CTRL, + RT5631_SPK_R_MUX_SEL_SHIFT, rt5631_spor_src_sel); + +static const struct snd_kcontrol_new rt5631_spor_mux_control = + SOC_DAPM_ENUM("SPOR SRC", rt5631_spor_src_enum); + +/* MONO Input */ +static const char *rt5631_mono_src_sel[] = {"MONOMIX", "MONOIN_RX", "VDAC"}; + +static const SOC_ENUM_SINGLE_DECL( + rt5631_mono_src_enum, RT5631_SPK_MONO_HP_OUT_CTRL, + RT5631_MONO_MUX_SEL_SHIFT, rt5631_mono_src_sel); + +static const struct snd_kcontrol_new rt5631_mono_mux_control = + SOC_DAPM_ENUM("MONO SRC", rt5631_mono_src_enum); + +/* Left HPO Input */ +static const char *rt5631_hpl_src_sel[] = {"Left HPVOL", "Left DAC"}; + +static const SOC_ENUM_SINGLE_DECL( + rt5631_hpl_src_enum, RT5631_SPK_MONO_HP_OUT_CTRL, + RT5631_HP_L_MUX_SEL_SHIFT, rt5631_hpl_src_sel); + +static const struct snd_kcontrol_new rt5631_hpl_mux_control = + SOC_DAPM_ENUM("HPL SRC", rt5631_hpl_src_enum); + +/* Right HPO Input */ +static const char *rt5631_hpr_src_sel[] = {"Right HPVOL", "Right DAC"}; + +static const SOC_ENUM_SINGLE_DECL( + rt5631_hpr_src_enum, RT5631_SPK_MONO_HP_OUT_CTRL, + RT5631_HP_R_MUX_SEL_SHIFT, rt5631_hpr_src_sel); + +static const struct snd_kcontrol_new rt5631_hpr_mux_control = + SOC_DAPM_ENUM("HPR SRC", rt5631_hpr_src_enum); + +static const struct snd_soc_dapm_widget rt5631_dapm_widgets[] = { + /* Vmid */ + SND_SOC_DAPM_VMID("Vmid"), + /* PLL1 */ + SND_SOC_DAPM_SUPPLY("PLL1", RT5631_PWR_MANAG_ADD2, + RT5631_PWR_PLL1_BIT, 0, NULL, 0), + + /* Input Side */ + /* Input Lines */ + SND_SOC_DAPM_INPUT("MIC1"), + SND_SOC_DAPM_INPUT("MIC2"), + SND_SOC_DAPM_INPUT("AXIL"), + SND_SOC_DAPM_INPUT("AXIR"), + SND_SOC_DAPM_INPUT("MONOIN_RXN"), + SND_SOC_DAPM_INPUT("MONOIN_RXP"), + SND_SOC_DAPM_INPUT("DMIC"), + + /* MICBIAS */ + SND_SOC_DAPM_MICBIAS("MIC Bias1", RT5631_PWR_MANAG_ADD2, + RT5631_PWR_MICBIAS1_VOL_BIT, 0), + SND_SOC_DAPM_MICBIAS("MIC Bias2", RT5631_PWR_MANAG_ADD2, + RT5631_PWR_MICBIAS2_VOL_BIT, 0), + + /* Boost */ + SND_SOC_DAPM_PGA("MIC1 Boost", RT5631_PWR_MANAG_ADD2, + RT5631_PWR_MIC1_BOOT_GAIN_BIT, 0, NULL, 0), + SND_SOC_DAPM_PGA("MIC2 Boost", RT5631_PWR_MANAG_ADD2, + RT5631_PWR_MIC2_BOOT_GAIN_BIT, 0, NULL, 0), + SND_SOC_DAPM_PGA("MONOIN_RXP Boost", RT5631_PWR_MANAG_ADD4, + RT5631_PWR_MONO_IN_P_VOL_BIT, 0, NULL, 0), + SND_SOC_DAPM_PGA("MONOIN_RXN Boost", RT5631_PWR_MANAG_ADD4, + RT5631_PWR_MONO_IN_N_VOL_BIT, 0, NULL, 0), + SND_SOC_DAPM_PGA("AXIL Boost", RT5631_PWR_MANAG_ADD4, + RT5631_PWR_AXIL_IN_VOL_BIT, 0, NULL, 0), + SND_SOC_DAPM_PGA("AXIR Boost", RT5631_PWR_MANAG_ADD4, + RT5631_PWR_AXIR_IN_VOL_BIT, 0, NULL, 0), + + /* MONO In */ + SND_SOC_DAPM_MIXER("MONO_IN", SND_SOC_NOPM, 0, 0, NULL, 0), + + /* REC Mixer */ + SND_SOC_DAPM_MIXER("RECMIXL Mixer", RT5631_PWR_MANAG_ADD2, + RT5631_PWR_RECMIXER_L_BIT, 0, + &rt5631_recmixl_mixer_controls[0], + ARRAY_SIZE(rt5631_recmixl_mixer_controls)), + SND_SOC_DAPM_MIXER("RECMIXR Mixer", RT5631_PWR_MANAG_ADD2, + RT5631_PWR_RECMIXER_R_BIT, 0, + &rt5631_recmixr_mixer_controls[0], + ARRAY_SIZE(rt5631_recmixr_mixer_controls)), + /* Because of record duplication for L/R channel, + * L/R ADCs need power up at the same time */ + SND_SOC_DAPM_MIXER("ADC Mixer", SND_SOC_NOPM, 0, 0, NULL, 0), + + /* DMIC */ + SND_SOC_DAPM_SUPPLY("DMIC Supply", RT5631_DIG_MIC_CTRL, + RT5631_DMIC_ENA_SHIFT, 0, + set_dmic_params, SND_SOC_DAPM_PRE_PMU), + /* ADC Data Srouce */ + SND_SOC_DAPM_SUPPLY("Left ADC Select", RT5631_INT_ST_IRQ_CTRL_2, + RT5631_ADC_DATA_SEL_MIC1_SHIFT, 0, NULL, 0), + SND_SOC_DAPM_SUPPLY("Right ADC Select", RT5631_INT_ST_IRQ_CTRL_2, + RT5631_ADC_DATA_SEL_MIC2_SHIFT, 0, NULL, 0), + + /* ADCs */ + SND_SOC_DAPM_ADC("Left ADC", "HIFI Capture", + RT5631_PWR_MANAG_ADD1, RT5631_PWR_ADC_L_CLK_BIT, 0), + SND_SOC_DAPM_ADC("Right ADC", "HIFI Capture", + RT5631_PWR_MANAG_ADD1, RT5631_PWR_ADC_R_CLK_BIT, 0), + + /* DAC and ADC supply power */ + SND_SOC_DAPM_SUPPLY("I2S", RT5631_PWR_MANAG_ADD1, + RT5631_PWR_MAIN_I2S_BIT, 0, NULL, 0), + SND_SOC_DAPM_SUPPLY("DAC REF", RT5631_PWR_MANAG_ADD1, + RT5631_PWR_DAC_REF_BIT, 0, NULL, 0), + + /* Output Side */ + /* DACs */ + SND_SOC_DAPM_DAC("Left DAC", "HIFI Playback", + RT5631_PWR_MANAG_ADD1, RT5631_PWR_DAC_L_CLK_BIT, 0), + SND_SOC_DAPM_DAC("Right DAC", "HIFI Playback", + RT5631_PWR_MANAG_ADD1, RT5631_PWR_DAC_R_CLK_BIT, 0), + SND_SOC_DAPM_DAC("Voice DAC", "Voice DAC Mono Playback", + SND_SOC_NOPM, 0, 0), + SND_SOC_DAPM_PGA("Voice DAC Boost", SND_SOC_NOPM, 0, 0, NULL, 0), + /* DAC supply power */ + SND_SOC_DAPM_SUPPLY("Left DAC To Mixer", RT5631_PWR_MANAG_ADD1, + RT5631_PWR_DAC_L_TO_MIXER_BIT, 0, NULL, 0), + SND_SOC_DAPM_SUPPLY("Right DAC To Mixer", RT5631_PWR_MANAG_ADD1, + RT5631_PWR_DAC_R_TO_MIXER_BIT, 0, NULL, 0), + + /* Left SPK Mixer */ + SND_SOC_DAPM_MIXER("SPKMIXL Mixer", RT5631_PWR_MANAG_ADD2, + RT5631_PWR_SPKMIXER_L_BIT, 0, + &rt5631_spkmixl_mixer_controls[0], + ARRAY_SIZE(rt5631_spkmixl_mixer_controls)), + /* Left Out Mixer */ + SND_SOC_DAPM_MIXER("OUTMIXL Mixer", RT5631_PWR_MANAG_ADD2, + RT5631_PWR_OUTMIXER_L_BIT, 0, + &rt5631_outmixl_mixer_controls[0], + ARRAY_SIZE(rt5631_outmixl_mixer_controls)), + /* Right Out Mixer */ + SND_SOC_DAPM_MIXER("OUTMIXR Mixer", RT5631_PWR_MANAG_ADD2, + RT5631_PWR_OUTMIXER_R_BIT, 0, + &rt5631_outmixr_mixer_controls[0], + ARRAY_SIZE(rt5631_outmixr_mixer_controls)), + /* Right SPK Mixer */ + SND_SOC_DAPM_MIXER("SPKMIXR Mixer", RT5631_PWR_MANAG_ADD2, + RT5631_PWR_SPKMIXER_R_BIT, 0, + &rt5631_spkmixr_mixer_controls[0], + ARRAY_SIZE(rt5631_spkmixr_mixer_controls)), + + /* Volume Mux */ + SND_SOC_DAPM_MUX("Left SPKVOL Mux", RT5631_PWR_MANAG_ADD4, + RT5631_PWR_SPK_L_VOL_BIT, 0, + &rt5631_spkvoll_mux_control), + SND_SOC_DAPM_MUX("Left HPVOL Mux", RT5631_PWR_MANAG_ADD4, + RT5631_PWR_HP_L_OUT_VOL_BIT, 0, + &rt5631_hpvoll_mux_control), + SND_SOC_DAPM_MUX("Left OUTVOL Mux", RT5631_PWR_MANAG_ADD4, + RT5631_PWR_LOUT_VOL_BIT, 0, + &rt5631_outvoll_mux_control), + SND_SOC_DAPM_MUX("Right OUTVOL Mux", RT5631_PWR_MANAG_ADD4, + RT5631_PWR_ROUT_VOL_BIT, 0, + &rt5631_outvolr_mux_control), + SND_SOC_DAPM_MUX("Right HPVOL Mux", RT5631_PWR_MANAG_ADD4, + RT5631_PWR_HP_R_OUT_VOL_BIT, 0, + &rt5631_hpvolr_mux_control), + SND_SOC_DAPM_MUX("Right SPKVOL Mux", RT5631_PWR_MANAG_ADD4, + RT5631_PWR_SPK_R_VOL_BIT, 0, + &rt5631_spkvolr_mux_control), + + /* DAC To HP */ + SND_SOC_DAPM_PGA_S("Left DAC_HP", 0, SND_SOC_NOPM, 0, 0, NULL, 0), + SND_SOC_DAPM_PGA_S("Right DAC_HP", 0, SND_SOC_NOPM, 0, 0, NULL, 0), + + /* HP Depop */ + SND_SOC_DAPM_PGA_S("HP Depop", 1, SND_SOC_NOPM, 0, 0, + hp_event, SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMU), + + /* AXO1 Mixer */ + SND_SOC_DAPM_MIXER("AXO1MIX Mixer", RT5631_PWR_MANAG_ADD3, + RT5631_PWR_AXO1MIXER_BIT, 0, + &rt5631_AXO1MIX_mixer_controls[0], + ARRAY_SIZE(rt5631_AXO1MIX_mixer_controls)), + /* SPOL Mixer */ + SND_SOC_DAPM_MIXER("SPOLMIX Mixer", SND_SOC_NOPM, 0, 0, + &rt5631_spolmix_mixer_controls[0], + ARRAY_SIZE(rt5631_spolmix_mixer_controls)), + /* MONO Mixer */ + SND_SOC_DAPM_MIXER("MONOMIX Mixer", RT5631_PWR_MANAG_ADD3, + RT5631_PWR_MONOMIXER_BIT, 0, + &rt5631_monomix_mixer_controls[0], + ARRAY_SIZE(rt5631_monomix_mixer_controls)), + /* SPOR Mixer */ + SND_SOC_DAPM_MIXER("SPORMIX Mixer", SND_SOC_NOPM, 0, 0, + &rt5631_spormix_mixer_controls[0], + ARRAY_SIZE(rt5631_spormix_mixer_controls)), + /* AXO2 Mixer */ + SND_SOC_DAPM_MIXER("AXO2MIX Mixer", RT5631_PWR_MANAG_ADD3, + RT5631_PWR_AXO2MIXER_BIT, 0, + &rt5631_AXO2MIX_mixer_controls[0], + ARRAY_SIZE(rt5631_AXO2MIX_mixer_controls)), + + /* Mux */ + SND_SOC_DAPM_MUX("SPOL Mux", SND_SOC_NOPM, 0, 0, + &rt5631_spol_mux_control), + SND_SOC_DAPM_MUX("SPOR Mux", SND_SOC_NOPM, 0, 0, + &rt5631_spor_mux_control), + SND_SOC_DAPM_MUX("MONO Mux", SND_SOC_NOPM, 0, 0, + &rt5631_mono_mux_control), + SND_SOC_DAPM_MUX("HPL Mux", SND_SOC_NOPM, 0, 0, + &rt5631_hpl_mux_control), + SND_SOC_DAPM_MUX("HPR Mux", SND_SOC_NOPM, 0, 0, + &rt5631_hpr_mux_control), + + /* AMP supply */ + SND_SOC_DAPM_SUPPLY("MONO Depop", RT5631_PWR_MANAG_ADD3, + RT5631_PWR_MONO_DEPOP_DIS_BIT, 0, NULL, 0), + SND_SOC_DAPM_SUPPLY("Class D", RT5631_PWR_MANAG_ADD1, + RT5631_PWR_CLASS_D_BIT, 0, NULL, 0), + + /* Output Lines */ + SND_SOC_DAPM_OUTPUT("AUXO1"), + SND_SOC_DAPM_OUTPUT("AUXO2"), + SND_SOC_DAPM_OUTPUT("SPOL"), + SND_SOC_DAPM_OUTPUT("SPOR"), + SND_SOC_DAPM_OUTPUT("HPOL"), + SND_SOC_DAPM_OUTPUT("HPOR"), + SND_SOC_DAPM_OUTPUT("MONO"), +}; + +static const struct snd_soc_dapm_route rt5631_dapm_routes[] = { + {"MIC1 Boost", NULL, "MIC1"}, + {"MIC2 Boost", NULL, "MIC2"}, + {"MONOIN_RXP Boost", NULL, "MONOIN_RXP"}, + {"MONOIN_RXN Boost", NULL, "MONOIN_RXN"}, + {"AXIL Boost", NULL, "AXIL"}, + {"AXIR Boost", NULL, "AXIR"}, + + {"MONO_IN", NULL, "MONOIN_RXP Boost"}, + {"MONO_IN", NULL, "MONOIN_RXN Boost"}, + + {"RECMIXL Mixer", "OUTMIXL Capture Switch", "OUTMIXL Mixer"}, + {"RECMIXL Mixer", "MIC1_BST1 Capture Switch", "MIC1 Boost"}, + {"RECMIXL Mixer", "AXILVOL Capture Switch", "AXIL Boost"}, + {"RECMIXL Mixer", "MONOIN_RX Capture Switch", "MONO_IN"}, + + {"RECMIXR Mixer", "OUTMIXR Capture Switch", "OUTMIXR Mixer"}, + {"RECMIXR Mixer", "MIC2_BST2 Capture Switch", "MIC2 Boost"}, + {"RECMIXR Mixer", "AXIRVOL Capture Switch", "AXIR Boost"}, + {"RECMIXR Mixer", "MONOIN_RX Capture Switch", "MONO_IN"}, + + {"ADC Mixer", NULL, "RECMIXL Mixer"}, + {"ADC Mixer", NULL, "RECMIXR Mixer"}, + + {"Left ADC", NULL, "ADC Mixer"}, + {"Left ADC", NULL, "Left ADC Select", check_adcl_select}, + {"Left ADC", NULL, "PLL1", check_sysclk1_source}, + {"Left ADC", NULL, "I2S"}, + {"Left ADC", NULL, "DAC REF"}, + + {"Right ADC", NULL, "ADC Mixer"}, + {"Right ADC", NULL, "Right ADC Select", check_adcr_select}, + {"Right ADC", NULL, "PLL1", check_sysclk1_source}, + {"Right ADC", NULL, "I2S"}, + {"Right ADC", NULL, "DAC REF"}, + + {"DMIC", NULL, "DMIC Supply", check_dmic_used}, + {"Left ADC", NULL, "DMIC"}, + {"Right ADC", NULL, "DMIC"}, + + {"Left DAC", NULL, "PLL1", check_sysclk1_source}, + {"Left DAC", NULL, "I2S"}, + {"Left DAC", NULL, "DAC REF"}, + {"Right DAC", NULL, "PLL1", check_sysclk1_source}, + {"Right DAC", NULL, "I2S"}, + {"Right DAC", NULL, "DAC REF"}, + + {"Voice DAC Boost", NULL, "Voice DAC"}, + + {"SPKMIXL Mixer", NULL, "Left DAC To Mixer", check_dacl_to_spkmixl}, + {"SPKMIXL Mixer", "RECMIXL Playback Switch", "RECMIXL Mixer"}, + {"SPKMIXL Mixer", "MIC1_P Playback Switch", "MIC1"}, + {"SPKMIXL Mixer", "DACL Playback Switch", "Left DAC"}, + {"SPKMIXL Mixer", "OUTMIXL Playback Switch", "OUTMIXL Mixer"}, + + {"SPKMIXR Mixer", NULL, "Right DAC To Mixer", check_dacr_to_spkmixr}, + {"SPKMIXR Mixer", "OUTMIXR Playback Switch", "OUTMIXR Mixer"}, + {"SPKMIXR Mixer", "DACR Playback Switch", "Right DAC"}, + {"SPKMIXR Mixer", "MIC2_P Playback Switch", "MIC2"}, + {"SPKMIXR Mixer", "RECMIXR Playback Switch", "RECMIXR Mixer"}, + + {"OUTMIXL Mixer", NULL, "Left DAC To Mixer", check_dacl_to_outmixl}, + {"OUTMIXL Mixer", "RECMIXL Playback Switch", "RECMIXL Mixer"}, + {"OUTMIXL Mixer", "RECMIXR Playback Switch", "RECMIXR Mixer"}, + {"OUTMIXL Mixer", "DACL Playback Switch", "Left DAC"}, + {"OUTMIXL Mixer", "MIC1_BST1 Playback Switch", "MIC1 Boost"}, + {"OUTMIXL Mixer", "MIC2_BST2 Playback Switch", "MIC2 Boost"}, + {"OUTMIXL Mixer", "MONOIN_RXP Playback Switch", "MONOIN_RXP Boost"}, + {"OUTMIXL Mixer", "AXILVOL Playback Switch", "AXIL Boost"}, + {"OUTMIXL Mixer", "AXIRVOL Playback Switch", "AXIR Boost"}, + {"OUTMIXL Mixer", "VDAC Playback Switch", "Voice DAC Boost"}, + + {"OUTMIXR Mixer", NULL, "Right DAC To Mixer", check_dacr_to_outmixr}, + {"OUTMIXR Mixer", "RECMIXL Playback Switch", "RECMIXL Mixer"}, + {"OUTMIXR Mixer", "RECMIXR Playback Switch", "RECMIXR Mixer"}, + {"OUTMIXR Mixer", "DACR Playback Switch", "Right DAC"}, + {"OUTMIXR Mixer", "MIC1_BST1 Playback Switch", "MIC1 Boost"}, + {"OUTMIXR Mixer", "MIC2_BST2 Playback Switch", "MIC2 Boost"}, + {"OUTMIXR Mixer", "MONOIN_RXN Playback Switch", "MONOIN_RXN Boost"}, + {"OUTMIXR Mixer", "AXILVOL Playback Switch", "AXIL Boost"}, + {"OUTMIXR Mixer", "AXIRVOL Playback Switch", "AXIR Boost"}, + {"OUTMIXR Mixer", "VDAC Playback Switch", "Voice DAC Boost"}, + + {"Left SPKVOL Mux", "SPKMIXL", "SPKMIXL Mixer"}, + {"Left SPKVOL Mux", "Vmid", "Vmid"}, + {"Left HPVOL Mux", "OUTMIXL", "OUTMIXL Mixer"}, + {"Left HPVOL Mux", "Vmid", "Vmid"}, + {"Left OUTVOL Mux", "OUTMIXL", "OUTMIXL Mixer"}, + {"Left OUTVOL Mux", "Vmid", "Vmid"}, + {"Right OUTVOL Mux", "OUTMIXR", "OUTMIXR Mixer"}, + {"Right OUTVOL Mux", "Vmid", "Vmid"}, + {"Right HPVOL Mux", "OUTMIXR", "OUTMIXR Mixer"}, + {"Right HPVOL Mux", "Vmid", "Vmid"}, + {"Right SPKVOL Mux", "SPKMIXR", "SPKMIXR Mixer"}, + {"Right SPKVOL Mux", "Vmid", "Vmid"}, + + {"AXO1MIX Mixer", "MIC1_BST1 Playback Switch", "MIC1 Boost"}, + {"AXO1MIX Mixer", "OUTVOLL Playback Switch", "Left OUTVOL Mux"}, + {"AXO1MIX Mixer", "OUTVOLR Playback Switch", "Right OUTVOL Mux"}, + {"AXO1MIX Mixer", "MIC2_BST2 Playback Switch", "MIC2 Boost"}, + + {"AXO2MIX Mixer", "MIC1_BST1 Playback Switch", "MIC1 Boost"}, + {"AXO2MIX Mixer", "OUTVOLL Playback Switch", "Left OUTVOL Mux"}, + {"AXO2MIX Mixer", "OUTVOLR Playback Switch", "Right OUTVOL Mux"}, + {"AXO2MIX Mixer", "MIC2_BST2 Playback Switch", "MIC2 Boost"}, + + {"SPOLMIX Mixer", "SPKVOLL Playback Switch", "Left SPKVOL Mux"}, + {"SPOLMIX Mixer", "SPKVOLR Playback Switch", "Right SPKVOL Mux"}, + + {"SPORMIX Mixer", "SPKVOLL Playback Switch", "Left SPKVOL Mux"}, + {"SPORMIX Mixer", "SPKVOLR Playback Switch", "Right SPKVOL Mux"}, + + {"MONOMIX Mixer", "OUTVOLL Playback Switch", "Left OUTVOL Mux"}, + {"MONOMIX Mixer", "OUTVOLR Playback Switch", "Right OUTVOL Mux"}, + + {"SPOL Mux", "SPOLMIX", "SPOLMIX Mixer"}, + {"SPOL Mux", "MONOIN_RX", "MONO_IN"}, + {"SPOL Mux", "VDAC", "Voice DAC Boost"}, + {"SPOL Mux", "DACL", "Left DAC"}, + + {"SPOR Mux", "SPORMIX", "SPORMIX Mixer"}, + {"SPOR Mux", "MONOIN_RX", "MONO_IN"}, + {"SPOR Mux", "VDAC", "Voice DAC Boost"}, + {"SPOR Mux", "DACR", "Right DAC"}, + + {"MONO Mux", "MONOMIX", "MONOMIX Mixer"}, + {"MONO Mux", "MONOIN_RX", "MONO_IN"}, + {"MONO Mux", "VDAC", "Voice DAC Boost"}, + + {"Right DAC_HP", NULL, "Right DAC"}, + {"Left DAC_HP", NULL, "Left DAC"}, + + {"HPL Mux", "Left HPVOL", "Left HPVOL Mux"}, + {"HPL Mux", "Left DAC", "Left DAC_HP"}, + {"HPR Mux", "Right HPVOL", "Right HPVOL Mux"}, + {"HPR Mux", "Right DAC", "Right DAC_HP"}, + + {"HP Depop", NULL, "HPL Mux"}, + {"HP Depop", NULL, "HPR Mux"}, + + {"AUXO1", NULL, "AXO1MIX Mixer"}, + {"AUXO2", NULL, "AXO2MIX Mixer"}, + + {"SPOL", NULL, "Class D"}, + {"SPOL", NULL, "SPOL Mux"}, + {"SPOR", NULL, "Class D"}, + {"SPOR", NULL, "SPOR Mux"}, + + {"HPOL", NULL, "HP Depop"}, + {"HPOR", NULL, "HP Depop"}, + + {"MONO", NULL, "MONO Depop"}, + {"MONO", NULL, "MONO Mux"}, +}; + +struct coeff_clk_div { + u32 mclk; + u32 bclk; + u32 rate; + u16 reg_val; +}; + +/* PLL divisors */ +struct pll_div { + u32 pll_in; + u32 pll_out; + u16 reg_val; +}; + +static const struct pll_div codec_master_pll_div[] = { + {2048000, 8192000, 0x0ea0}, + {3686400, 8192000, 0x4e27}, + {12000000, 8192000, 0x456b}, + {13000000, 8192000, 0x495f}, + {13100000, 8192000, 0x0320}, + {2048000, 11289600, 0xf637}, + {3686400, 11289600, 0x2f22}, + {12000000, 11289600, 0x3e2f}, + {13000000, 11289600, 0x4d5b}, + {13100000, 11289600, 0x363b}, + {2048000, 16384000, 0x1ea0}, + {3686400, 16384000, 0x9e27}, + {12000000, 16384000, 0x452b}, + {13000000, 16384000, 0x542f}, + {13100000, 16384000, 0x03a0}, + {2048000, 16934400, 0xe625}, + {3686400, 16934400, 0x9126}, + {12000000, 16934400, 0x4d2c}, + {13000000, 16934400, 0x742f}, + {13100000, 16934400, 0x3c27}, + {2048000, 22579200, 0x2aa0}, + {3686400, 22579200, 0x2f20}, + {12000000, 22579200, 0x7e2f}, + {13000000, 22579200, 0x742f}, + {13100000, 22579200, 0x3c27}, + {2048000, 24576000, 0x2ea0}, + {3686400, 24576000, 0xee27}, + {12000000, 24576000, 0x2915}, + {13000000, 24576000, 0x772e}, + {13100000, 24576000, 0x0d20}, + {26000000, 24576000, 0x2027}, + {26000000, 22579200, 0x392f}, + {24576000, 22579200, 0x0921}, + {24576000, 24576000, 0x02a0}, +}; + +static const struct pll_div codec_slave_pll_div[] = { + {256000, 2048000, 0x46f0}, + {256000, 4096000, 0x3ea0}, + {352800, 5644800, 0x3ea0}, + {512000, 8192000, 0x3ea0}, + {1024000, 8192000, 0x46f0}, + {705600, 11289600, 0x3ea0}, + {1024000, 16384000, 0x3ea0}, + {1411200, 22579200, 0x3ea0}, + {1536000, 24576000, 0x3ea0}, + {2048000, 16384000, 0x1ea0}, + {2822400, 22579200, 0x1ea0}, + {2822400, 45158400, 0x5ec0}, + {5644800, 45158400, 0x46f0}, + {3072000, 24576000, 0x1ea0}, + {3072000, 49152000, 0x5ec0}, + {6144000, 49152000, 0x46f0}, + {705600, 11289600, 0x3ea0}, + {705600, 8467200, 0x3ab0}, + {24576000, 24576000, 0x02a0}, + {1411200, 11289600, 0x1690}, + {2822400, 11289600, 0x0a90}, + {1536000, 12288000, 0x1690}, + {3072000, 12288000, 0x0a90}, +}; + +static struct coeff_clk_div coeff_div[] = { + /* sysclk is 256fs */ + {2048000, 8000 * 32, 8000, 0x1000}, + {2048000, 8000 * 64, 8000, 0x0000}, + {2822400, 11025 * 32, 11025, 0x1000}, + {2822400, 11025 * 64, 11025, 0x0000}, + {4096000, 16000 * 32, 16000, 0x1000}, + {4096000, 16000 * 64, 16000, 0x0000}, + {5644800, 22050 * 32, 22050, 0x1000}, + {5644800, 22050 * 64, 22050, 0x0000}, + {8192000, 32000 * 32, 32000, 0x1000}, + {8192000, 32000 * 64, 32000, 0x0000}, + {11289600, 44100 * 32, 44100, 0x1000}, + {11289600, 44100 * 64, 44100, 0x0000}, + {12288000, 48000 * 32, 48000, 0x1000}, + {12288000, 48000 * 64, 48000, 0x0000}, + {22579200, 88200 * 32, 88200, 0x1000}, + {22579200, 88200 * 64, 88200, 0x0000}, + {24576000, 96000 * 32, 96000, 0x1000}, + {24576000, 96000 * 64, 96000, 0x0000}, + /* sysclk is 512fs */ + {4096000, 8000 * 32, 8000, 0x3000}, + {4096000, 8000 * 64, 8000, 0x2000}, + {5644800, 11025 * 32, 11025, 0x3000}, + {5644800, 11025 * 64, 11025, 0x2000}, + {8192000, 16000 * 32, 16000, 0x3000}, + {8192000, 16000 * 64, 16000, 0x2000}, + {11289600, 22050 * 32, 22050, 0x3000}, + {11289600, 22050 * 64, 22050, 0x2000}, + {16384000, 32000 * 32, 32000, 0x3000}, + {16384000, 32000 * 64, 32000, 0x2000}, + {22579200, 44100 * 32, 44100, 0x3000}, + {22579200, 44100 * 64, 44100, 0x2000}, + {24576000, 48000 * 32, 48000, 0x3000}, + {24576000, 48000 * 64, 48000, 0x2000}, + {45158400, 88200 * 32, 88200, 0x3000}, + {45158400, 88200 * 64, 88200, 0x2000}, + {49152000, 96000 * 32, 96000, 0x3000}, + {49152000, 96000 * 64, 96000, 0x2000}, + /* sysclk is 24.576Mhz or 22.5792Mhz */ + {24576000, 8000 * 32, 8000, 0x7080}, + {24576000, 8000 * 64, 8000, 0x6080}, + {24576000, 16000 * 32, 16000, 0x5080}, + {24576000, 16000 * 64, 16000, 0x4080}, + {24576000, 24000 * 32, 24000, 0x5000}, + {24576000, 24000 * 64, 24000, 0x4000}, + {24576000, 32000 * 32, 32000, 0x3080}, + {24576000, 32000 * 64, 32000, 0x2080}, + {22579200, 11025 * 32, 11025, 0x7000}, + {22579200, 11025 * 64, 11025, 0x6000}, + {22579200, 22050 * 32, 22050, 0x5000}, + {22579200, 22050 * 64, 22050, 0x4000}, +}; + +static int get_coeff(int mclk, int rate, int timesofbclk) +{ + int i; + + for (i = 0; i < ARRAY_SIZE(coeff_div); i++) { + if (coeff_div[i].mclk == mclk && coeff_div[i].rate == rate && + (coeff_div[i].bclk / coeff_div[i].rate) == timesofbclk) + return i; + } + return -EINVAL; +} + +static int rt5631_hifi_pcm_params(struct snd_pcm_substream *substream, + struct snd_pcm_hw_params *params, struct snd_soc_dai *dai) +{ + struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_codec *codec = rtd->codec; + struct rt5631_priv *rt5631 = snd_soc_codec_get_drvdata(codec); + int timesofbclk = 32, coeff; + unsigned int iface = 0; + + dev_dbg(codec->dev, "enter %s\n", __func__); + + rt5631->bclk_rate = snd_soc_params_to_bclk(params); + if (rt5631->bclk_rate < 0) { + dev_err(codec->dev, "Fail to get BCLK rate\n"); + return rt5631->bclk_rate; + } + rt5631->rx_rate = params_rate(params); + + if (rt5631->master) + coeff = get_coeff(rt5631->sysclk, rt5631->rx_rate, + rt5631->bclk_rate / rt5631->rx_rate); + else + coeff = get_coeff(rt5631->sysclk, rt5631->rx_rate, + timesofbclk); + if (coeff < 0) { + dev_err(codec->dev, "Fail to get coeff\n"); + return -EINVAL; + } + + switch (params_format(params)) { + case SNDRV_PCM_FORMAT_S16_LE: + break; + case SNDRV_PCM_FORMAT_S20_3LE: + iface |= RT5631_SDP_I2S_DL_20; + break; + case SNDRV_PCM_FORMAT_S24_LE: + iface |= RT5631_SDP_I2S_DL_24; + break; + case SNDRV_PCM_FORMAT_S8: + iface |= RT5631_SDP_I2S_DL_8; + break; + default: + return -EINVAL; + } + + snd_soc_update_bits(codec, RT5631_SDP_CTRL, + RT5631_SDP_I2S_DL_MASK, iface); + snd_soc_write(codec, RT5631_STEREO_AD_DA_CLK_CTRL, + coeff_div[coeff].reg_val); + + return 0; +} + +static int rt5631_hifi_codec_set_dai_fmt(struct snd_soc_dai *codec_dai, + unsigned int fmt) +{ + struct snd_soc_codec *codec = codec_dai->codec; + struct rt5631_priv *rt5631 = snd_soc_codec_get_drvdata(codec); + unsigned int iface = 0; + + dev_dbg(codec->dev, "enter %s\n", __func__); + + switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { + case SND_SOC_DAIFMT_CBM_CFM: + rt5631->master = 1; + break; + case SND_SOC_DAIFMT_CBS_CFS: + iface |= RT5631_SDP_MODE_SEL_SLAVE; + rt5631->master = 0; + break; + default: + return -EINVAL; + } + + switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { + case SND_SOC_DAIFMT_I2S: + break; + case SND_SOC_DAIFMT_LEFT_J: + iface |= RT5631_SDP_I2S_DF_LEFT; + break; + case SND_SOC_DAIFMT_DSP_A: + iface |= RT5631_SDP_I2S_DF_PCM_A; + break; + case SND_SOC_DAIFMT_DSP_B: + iface |= RT5631_SDP_I2S_DF_PCM_B; + break; + default: + return -EINVAL; + } + + switch (fmt & SND_SOC_DAIFMT_INV_MASK) { + case SND_SOC_DAIFMT_NB_NF: + break; + case SND_SOC_DAIFMT_IB_NF: + iface |= RT5631_SDP_I2S_BCLK_POL_CTRL; + break; + default: + return -EINVAL; + } + + snd_soc_write(codec, RT5631_SDP_CTRL, iface); + + return 0; +} + +static int rt5631_hifi_codec_set_dai_sysclk(struct snd_soc_dai *codec_dai, + int clk_id, unsigned int freq, int dir) +{ + struct snd_soc_codec *codec = codec_dai->codec; + struct rt5631_priv *rt5631 = snd_soc_codec_get_drvdata(codec); + + dev_dbg(codec->dev, "enter %s, syclk=%d\n", __func__, freq); + + if ((freq >= (256 * 8000)) && (freq <= (512 * 96000))) { + rt5631->sysclk = freq; + return 0; + } + + return -EINVAL; +} + +static int rt5631_codec_set_dai_pll(struct snd_soc_dai *codec_dai, int pll_id, + int source, unsigned int freq_in, unsigned int freq_out) +{ + struct snd_soc_codec *codec = codec_dai->codec; + struct rt5631_priv *rt5631 = snd_soc_codec_get_drvdata(codec); + int i, ret = -EINVAL; + + dev_dbg(codec->dev, "enter %s\n", __func__); + + if (!freq_in || !freq_out) { + dev_dbg(codec->dev, "PLL disabled\n"); + + snd_soc_update_bits(codec, RT5631_GLOBAL_CLK_CTRL, + RT5631_SYSCLK_SOUR_SEL_MASK, + RT5631_SYSCLK_SOUR_SEL_MCLK); + + return 0; + } + + if (rt5631->master) { + for (i = 0; i < ARRAY_SIZE(codec_master_pll_div); i++) + if (freq_in == codec_master_pll_div[i].pll_in && + freq_out == codec_master_pll_div[i].pll_out) { + dev_info(codec->dev, + "change PLL in master mode\n"); + snd_soc_write(codec, RT5631_PLL_CTRL, + codec_master_pll_div[i].reg_val); + schedule_timeout_uninterruptible( + msecs_to_jiffies(20)); + snd_soc_update_bits(codec, + RT5631_GLOBAL_CLK_CTRL, + RT5631_SYSCLK_SOUR_SEL_MASK | + RT5631_PLLCLK_SOUR_SEL_MASK, + RT5631_SYSCLK_SOUR_SEL_PLL | + RT5631_PLLCLK_SOUR_SEL_MCLK); + ret = 0; + break; + } + } else { + for (i = 0; i < ARRAY_SIZE(codec_slave_pll_div); i++) + if (freq_in == codec_slave_pll_div[i].pll_in && + freq_out == codec_slave_pll_div[i].pll_out) { + dev_info(codec->dev, + "change PLL in slave mode\n"); + snd_soc_write(codec, RT5631_PLL_CTRL, + codec_slave_pll_div[i].reg_val); + schedule_timeout_uninterruptible( + msecs_to_jiffies(20)); + snd_soc_update_bits(codec, + RT5631_GLOBAL_CLK_CTRL, + RT5631_SYSCLK_SOUR_SEL_MASK | + RT5631_PLLCLK_SOUR_SEL_MASK, + RT5631_SYSCLK_SOUR_SEL_PLL | + RT5631_PLLCLK_SOUR_SEL_BCLK); + ret = 0; + break; + } + } + + return ret; +} + +static int rt5631_set_bias_level(struct snd_soc_codec *codec, + enum snd_soc_bias_level level) +{ + switch (level) { + case SND_SOC_BIAS_ON: + case SND_SOC_BIAS_PREPARE: + snd_soc_update_bits(codec, RT5631_PWR_MANAG_ADD2, + RT5631_PWR_MICBIAS1_VOL | RT5631_PWR_MICBIAS2_VOL, + RT5631_PWR_MICBIAS1_VOL | RT5631_PWR_MICBIAS2_VOL); + break; + + case SND_SOC_BIAS_STANDBY: + if (codec->dapm.bias_level == SND_SOC_BIAS_OFF) { + snd_soc_update_bits(codec, RT5631_PWR_MANAG_ADD3, + RT5631_PWR_VREF | RT5631_PWR_MAIN_BIAS, + RT5631_PWR_VREF | RT5631_PWR_MAIN_BIAS); + msleep(80); + snd_soc_update_bits(codec, RT5631_PWR_MANAG_ADD3, + RT5631_PWR_FAST_VREF_CTRL, + RT5631_PWR_FAST_VREF_CTRL); + codec->cache_only = false; + snd_soc_cache_sync(codec); + } + break; + + case SND_SOC_BIAS_OFF: + snd_soc_write(codec, RT5631_PWR_MANAG_ADD1, 0x0000); + snd_soc_write(codec, RT5631_PWR_MANAG_ADD2, 0x0000); + snd_soc_write(codec, RT5631_PWR_MANAG_ADD3, 0x0000); + snd_soc_write(codec, RT5631_PWR_MANAG_ADD4, 0x0000); + break; + + default: + break; + } + codec->dapm.bias_level = level; + + return 0; +} + +static int rt5631_probe(struct snd_soc_codec *codec) +{ + struct rt5631_priv *rt5631 = snd_soc_codec_get_drvdata(codec); + unsigned int val; + int ret; + + ret = snd_soc_codec_set_cache_io(codec, 8, 16, SND_SOC_I2C); + if (ret != 0) { + dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret); + return ret; + } + + val = rt5631_read_index(codec, RT5631_ADDA_MIXER_INTL_REG3); + if (val & 0x0002) + rt5631->codec_version = 1; + else + rt5631->codec_version = 0; + + rt5631_reset(codec); + snd_soc_update_bits(codec, RT5631_PWR_MANAG_ADD3, + RT5631_PWR_VREF | RT5631_PWR_MAIN_BIAS, + RT5631_PWR_VREF | RT5631_PWR_MAIN_BIAS); + msleep(80); + snd_soc_update_bits(codec, RT5631_PWR_MANAG_ADD3, + RT5631_PWR_FAST_VREF_CTRL, RT5631_PWR_FAST_VREF_CTRL); + /* enable HP zero cross */ + snd_soc_write(codec, RT5631_INT_ST_IRQ_CTRL_2, 0x0f18); + /* power off ClassD auto Recovery */ + if (rt5631->codec_version) + snd_soc_update_bits(codec, RT5631_INT_ST_IRQ_CTRL_2, + 0x2000, 0x2000); + else + snd_soc_update_bits(codec, RT5631_INT_ST_IRQ_CTRL_2, + 0x2000, 0); + /* DMIC */ + if (rt5631->dmic_used_flag) { + snd_soc_update_bits(codec, RT5631_GPIO_CTRL, + RT5631_GPIO_PIN_FUN_SEL_MASK | + RT5631_GPIO_DMIC_FUN_SEL_MASK, + RT5631_GPIO_PIN_FUN_SEL_GPIO_DIMC | + RT5631_GPIO_DMIC_FUN_SEL_DIMC); + snd_soc_update_bits(codec, RT5631_DIG_MIC_CTRL, + RT5631_DMIC_L_CH_LATCH_MASK | + RT5631_DMIC_R_CH_LATCH_MASK, + RT5631_DMIC_L_CH_LATCH_FALLING | + RT5631_DMIC_R_CH_LATCH_RISING); + } + + codec->dapm.bias_level = SND_SOC_BIAS_STANDBY; + + return 0; +} + +static int rt5631_remove(struct snd_soc_codec *codec) +{ + rt5631_set_bias_level(codec, SND_SOC_BIAS_OFF); + return 0; +} + +#ifdef CONFIG_PM +static int rt5631_suspend(struct snd_soc_codec *codec, pm_message_t state) +{ + rt5631_set_bias_level(codec, SND_SOC_BIAS_OFF); + return 0; +} + +static int rt5631_resume(struct snd_soc_codec *codec) +{ + rt5631_set_bias_level(codec, SND_SOC_BIAS_STANDBY); + return 0; +} +#else +#define rt5631_suspend NULL +#define rt5631_resume NULL +#endif + +#define RT5631_STEREO_RATES SNDRV_PCM_RATE_8000_96000 +#define RT5631_FORMAT (SNDRV_PCM_FMTBIT_S16_LE | \ + SNDRV_PCM_FMTBIT_S20_3LE | \ + SNDRV_PCM_FMTBIT_S24_LE | \ + SNDRV_PCM_FMTBIT_S8) + +static struct snd_soc_dai_ops rt5631_ops = { + .hw_params = rt5631_hifi_pcm_params, + .set_fmt = rt5631_hifi_codec_set_dai_fmt, + .set_sysclk = rt5631_hifi_codec_set_dai_sysclk, + .set_pll = rt5631_codec_set_dai_pll, +}; + +static struct snd_soc_dai_driver rt5631_dai[] = { + { + .name = "rt5631-hifi", + .id = 1, + .playback = { + .stream_name = "HIFI Playback", + .channels_min = 1, + .channels_max = 2, + .rates = RT5631_STEREO_RATES, + .formats = RT5631_FORMAT, + }, + .capture = { + .stream_name = "HIFI Capture", + .channels_min = 1, + .channels_max = 2, + .rates = RT5631_STEREO_RATES, + .formats = RT5631_FORMAT, + }, + .ops = &rt5631_ops, + }, +}; + +static struct snd_soc_codec_driver soc_codec_dev_rt5631 = { + .probe = rt5631_probe, + .remove = rt5631_remove, + .suspend = rt5631_suspend, + .resume = rt5631_resume, + .set_bias_level = rt5631_set_bias_level, + .reg_cache_size = RT5631_VENDOR_ID2 + 1, + .reg_word_size = sizeof(u16), + .reg_cache_default = rt5631_reg, + .volatile_register = rt5631_volatile_register, + .readable_register = rt5631_readable_register, + .reg_cache_step = 1, + .controls = rt5631_snd_controls, + .num_controls = ARRAY_SIZE(rt5631_snd_controls), + .dapm_widgets = rt5631_dapm_widgets, + .num_dapm_widgets = ARRAY_SIZE(rt5631_dapm_widgets), + .dapm_routes = rt5631_dapm_routes, + .num_dapm_routes = ARRAY_SIZE(rt5631_dapm_routes), +}; + +static const struct i2c_device_id rt5631_i2c_id[] = { + { "rt5631", 0 }, + { } +}; +MODULE_DEVICE_TABLE(i2c, rt5631_i2c_id); + +static int rt5631_i2c_probe(struct i2c_client *i2c, + const struct i2c_device_id *id) +{ + struct rt5631_priv *rt5631; + int ret; + + rt5631 = kzalloc(sizeof(struct rt5631_priv), GFP_KERNEL); + if (NULL == rt5631) + return -ENOMEM; + + i2c_set_clientdata(i2c, rt5631); + + ret = snd_soc_register_codec(&i2c->dev, &soc_codec_dev_rt5631, + rt5631_dai, ARRAY_SIZE(rt5631_dai)); + if (ret < 0) + kfree(rt5631); + + return ret; +} + +static __devexit int rt5631_i2c_remove(struct i2c_client *client) +{ + snd_soc_unregister_codec(&client->dev); + kfree(i2c_get_clientdata(client)); + return 0; +} + +static struct i2c_driver rt5631_i2c_driver = { + .driver = { + .name = "rt5631", + .owner = THIS_MODULE, + }, + .probe = rt5631_i2c_probe, + .remove = __devexit_p(rt5631_i2c_remove), + .id_table = rt5631_i2c_id, +}; + +static int __init rt5631_modinit(void) +{ + return i2c_add_driver(&rt5631_i2c_driver); +} +module_init(rt5631_modinit); + +static void __exit rt5631_modexit(void) +{ + i2c_del_driver(&rt5631_i2c_driver); +} +module_exit(rt5631_modexit); + +MODULE_DESCRIPTION("ASoC RT5631 driver"); +MODULE_AUTHOR("flove <flove@realtek.com>"); +MODULE_LICENSE("GPL"); diff --git a/sound/soc/codecs/rt5631.h b/sound/soc/codecs/rt5631.h new file mode 100644 index 00000000000..13401581b0d --- /dev/null +++ b/sound/soc/codecs/rt5631.h @@ -0,0 +1,701 @@ +#ifndef __RTCODEC5631_H__ +#define __RTCODEC5631_H__ + + +#define RT5631_RESET 0x00 +#define RT5631_SPK_OUT_VOL 0x02 +#define RT5631_HP_OUT_VOL 0x04 +#define RT5631_MONO_AXO_1_2_VOL 0x06 +#define RT5631_AUX_IN_VOL 0x0A +#define RT5631_STEREO_DAC_VOL_1 0x0C +#define RT5631_MIC_CTRL_1 0x0E +#define RT5631_STEREO_DAC_VOL_2 0x10 +#define RT5631_ADC_CTRL_1 0x12 +#define RT5631_ADC_REC_MIXER 0x14 +#define RT5631_ADC_CTRL_2 0x16 +#define RT5631_VDAC_DIG_VOL 0x18 +#define RT5631_OUTMIXER_L_CTRL 0x1A +#define RT5631_OUTMIXER_R_CTRL 0x1C +#define RT5631_AXO1MIXER_CTRL 0x1E +#define RT5631_AXO2MIXER_CTRL 0x20 +#define RT5631_MIC_CTRL_2 0x22 +#define RT5631_DIG_MIC_CTRL 0x24 +#define RT5631_MONO_INPUT_VOL 0x26 +#define RT5631_SPK_MIXER_CTRL 0x28 +#define RT5631_SPK_MONO_OUT_CTRL 0x2A +#define RT5631_SPK_MONO_HP_OUT_CTRL 0x2C +#define RT5631_SDP_CTRL 0x34 +#define RT5631_MONO_SDP_CTRL 0x36 +#define RT5631_STEREO_AD_DA_CLK_CTRL 0x38 +#define RT5631_PWR_MANAG_ADD1 0x3A +#define RT5631_PWR_MANAG_ADD2 0x3B +#define RT5631_PWR_MANAG_ADD3 0x3C +#define RT5631_PWR_MANAG_ADD4 0x3E +#define RT5631_GEN_PUR_CTRL_REG 0x40 +#define RT5631_GLOBAL_CLK_CTRL 0x42 +#define RT5631_PLL_CTRL 0x44 +#define RT5631_INT_ST_IRQ_CTRL_1 0x48 +#define RT5631_INT_ST_IRQ_CTRL_2 0x4A +#define RT5631_GPIO_CTRL 0x4C +#define RT5631_MISC_CTRL 0x52 +#define RT5631_DEPOP_FUN_CTRL_1 0x54 +#define RT5631_DEPOP_FUN_CTRL_2 0x56 +#define RT5631_JACK_DET_CTRL 0x5A +#define RT5631_SOFT_VOL_CTRL 0x5C +#define RT5631_ALC_CTRL_1 0x64 +#define RT5631_ALC_CTRL_2 0x65 +#define RT5631_ALC_CTRL_3 0x66 +#define RT5631_PSEUDO_SPATL_CTRL 0x68 +#define RT5631_INDEX_ADD 0x6A +#define RT5631_INDEX_DATA 0x6C +#define RT5631_EQ_CTRL 0x6E +#define RT5631_VENDOR_ID 0x7A +#define RT5631_VENDOR_ID1 0x7C +#define RT5631_VENDOR_ID2 0x7E + +/* Index of Codec Private Register definition */ +#define RT5631_EQ_BW_LOP 0x00 +#define RT5631_EQ_GAIN_LOP 0x01 +#define RT5631_EQ_FC_BP1 0x02 +#define RT5631_EQ_BW_BP1 0x03 +#define RT5631_EQ_GAIN_BP1 0x04 +#define RT5631_EQ_FC_BP2 0x05 +#define RT5631_EQ_BW_BP2 0x06 +#define RT5631_EQ_GAIN_BP2 0x07 +#define RT5631_EQ_FC_BP3 0x08 +#define RT5631_EQ_BW_BP3 0x09 +#define RT5631_EQ_GAIN_BP3 0x0a +#define RT5631_EQ_BW_HIP 0x0b +#define RT5631_EQ_GAIN_HIP 0x0c +#define RT5631_EQ_HPF_A1 0x0d +#define RT5631_EQ_HPF_A2 0x0e +#define RT5631_EQ_HPF_GAIN 0x0f +#define RT5631_EQ_PRE_VOL_CTRL 0x11 +#define RT5631_EQ_POST_VOL_CTRL 0x12 +#define RT5631_TEST_MODE_CTRL 0x39 +#define RT5631_CP_INTL_REG2 0x45 +#define RT5631_ADDA_MIXER_INTL_REG3 0x52 +#define RT5631_SPK_INTL_CTRL 0x56 + + +/* global definition */ +#define RT5631_L_MUTE (0x1 << 15) +#define RT5631_L_MUTE_SHIFT 15 +#define RT5631_L_EN (0x1 << 14) +#define RT5631_L_EN_SHIFT 14 +#define RT5631_R_MUTE (0x1 << 7) +#define RT5631_R_MUTE_SHIFT 7 +#define RT5631_R_EN (0x1 << 6) +#define RT5631_R_EN_SHIFT 6 +#define RT5631_VOL_MASK 0x1f +#define RT5631_L_VOL_SHIFT 8 +#define RT5631_R_VOL_SHIFT 0 + +/* Speaker Output Control(0x02) */ +#define RT5631_SPK_L_VOL_SEL_MASK (0x1 << 14) +#define RT5631_SPK_L_VOL_SEL_VMID (0x0 << 14) +#define RT5631_SPK_L_VOL_SEL_SPKMIX_L (0x1 << 14) +#define RT5631_SPK_R_VOL_SEL_MASK (0x1 << 6) +#define RT5631_SPK_R_VOL_SEL_VMID (0x0 << 6) +#define RT5631_SPK_R_VOL_SEL_SPKMIX_R (0x1 << 6) + +/* Headphone Output Control(0x04) */ +#define RT5631_HP_L_VOL_SEL_MASK (0x1 << 14) +#define RT5631_HP_L_VOL_SEL_VMID (0x0 << 14) +#define RT5631_HP_L_VOL_SEL_OUTMIX_L (0x1 << 14) +#define RT5631_HP_R_VOL_SEL_MASK (0x1 << 6) +#define RT5631_HP_R_VOL_SEL_VMID (0x0 << 6) +#define RT5631_HP_R_VOL_SEL_OUTMIX_R (0x1 << 6) + +/* Output Control for AUXOUT/MONO(0x06) */ +#define RT5631_AUXOUT_1_VOL_SEL_MASK (0x1 << 14) +#define RT5631_AUXOUT_1_VOL_SEL_VMID (0x0 << 14) +#define RT5631_AUXOUT_1_VOL_SEL_OUTMIX_L (0x1 << 14) +#define RT5631_MUTE_MONO (0x1 << 13) +#define RT5631_MUTE_MONO_SHIFT 13 +#define RT5631_AUXOUT_2_VOL_SEL_MASK (0x1 << 6) +#define RT5631_AUXOUT_2_VOL_SEL_VMID (0x0 << 6) +#define RT5631_AUXOUT_2_VOL_SEL_OUTMIX_R (0x1 << 6) + +/* Microphone Input Control 1(0x0E) */ +#define RT5631_MIC1_DIFF_INPUT_CTRL (0x1 << 15) +#define RT5631_MIC1_DIFF_INPUT_SHIFT 15 +#define RT5631_MIC2_DIFF_INPUT_CTRL (0x1 << 7) +#define RT5631_MIC2_DIFF_INPUT_SHIFT 7 + +/* Stereo DAC Digital Volume2(0x10) */ +#define RT5631_DAC_VOL_MASK 0xff + +/* ADC Recording Mixer Control(0x14) */ +#define RT5631_M_OUTMIXER_L_TO_RECMIXER_L (0x1 << 15) +#define RT5631_M_OUTMIXL_RECMIXL_BIT 15 +#define RT5631_M_MIC1_TO_RECMIXER_L (0x1 << 14) +#define RT5631_M_MIC1_RECMIXL_BIT 14 +#define RT5631_M_AXIL_TO_RECMIXER_L (0x1 << 13) +#define RT5631_M_AXIL_RECMIXL_BIT 13 +#define RT5631_M_MONO_IN_TO_RECMIXER_L (0x1 << 12) +#define RT5631_M_MONO_IN_RECMIXL_BIT 12 +#define RT5631_M_OUTMIXER_R_TO_RECMIXER_R (0x1 << 7) +#define RT5631_M_OUTMIXR_RECMIXR_BIT 7 +#define RT5631_M_MIC2_TO_RECMIXER_R (0x1 << 6) +#define RT5631_M_MIC2_RECMIXR_BIT 6 +#define RT5631_M_AXIR_TO_RECMIXER_R (0x1 << 5) +#define RT5631_M_AXIR_RECMIXR_BIT 5 +#define RT5631_M_MONO_IN_TO_RECMIXER_R (0x1 << 4) +#define RT5631_M_MONO_IN_RECMIXR_BIT 4 + +/* Left Output Mixer Control(0x1A) */ +#define RT5631_M_RECMIXER_L_TO_OUTMIXER_L (0x1 << 15) +#define RT5631_M_RECMIXL_OUTMIXL_BIT 15 +#define RT5631_M_RECMIXER_R_TO_OUTMIXER_L (0x1 << 14) +#define RT5631_M_RECMIXR_OUTMIXL_BIT 14 +#define RT5631_M_DAC_L_TO_OUTMIXER_L (0x1 << 13) +#define RT5631_M_DACL_OUTMIXL_BIT 13 +#define RT5631_M_MIC1_TO_OUTMIXER_L (0x1 << 12) +#define RT5631_M_MIC1_OUTMIXL_BIT 12 +#define RT5631_M_MIC2_TO_OUTMIXER_L (0x1 << 11) +#define RT5631_M_MIC2_OUTMIXL_BIT 11 +#define RT5631_M_MONO_IN_P_TO_OUTMIXER_L (0x1 << 10) +#define RT5631_M_MONO_INP_OUTMIXL_BIT 10 +#define RT5631_M_AXIL_TO_OUTMIXER_L (0x1 << 9) +#define RT5631_M_AXIL_OUTMIXL_BIT 9 +#define RT5631_M_AXIR_TO_OUTMIXER_L (0x1 << 8) +#define RT5631_M_AXIR_OUTMIXL_BIT 8 +#define RT5631_M_VDAC_TO_OUTMIXER_L (0x1 << 7) +#define RT5631_M_VDAC_OUTMIXL_BIT 7 + +/* Right Output Mixer Control(0x1C) */ +#define RT5631_M_RECMIXER_L_TO_OUTMIXER_R (0x1 << 15) +#define RT5631_M_RECMIXL_OUTMIXR_BIT 15 +#define RT5631_M_RECMIXER_R_TO_OUTMIXER_R (0x1 << 14) +#define RT5631_M_RECMIXR_OUTMIXR_BIT 14 +#define RT5631_M_DAC_R_TO_OUTMIXER_R (0x1 << 13) +#define RT5631_M_DACR_OUTMIXR_BIT 13 +#define RT5631_M_MIC1_TO_OUTMIXER_R (0x1 << 12) +#define RT5631_M_MIC1_OUTMIXR_BIT 12 +#define RT5631_M_MIC2_TO_OUTMIXER_R (0x1 << 11) +#define RT5631_M_MIC2_OUTMIXR_BIT 11 +#define RT5631_M_MONO_IN_N_TO_OUTMIXER_R (0x1 << 10) +#define RT5631_M_MONO_INN_OUTMIXR_BIT 10 +#define RT5631_M_AXIL_TO_OUTMIXER_R (0x1 << 9) +#define RT5631_M_AXIL_OUTMIXR_BIT 9 +#define RT5631_M_AXIR_TO_OUTMIXER_R (0x1 << 8) +#define RT5631_M_AXIR_OUTMIXR_BIT 8 +#define RT5631_M_VDAC_TO_OUTMIXER_R (0x1 << 7) +#define RT5631_M_VDAC_OUTMIXR_BIT 7 + +/* Lout Mixer Control(0x1E) */ +#define RT5631_M_MIC1_TO_AXO1MIXER (0x1 << 15) +#define RT5631_M_MIC1_AXO1MIX_BIT 15 +#define RT5631_M_MIC2_TO_AXO1MIXER (0x1 << 11) +#define RT5631_M_MIC2_AXO1MIX_BIT 11 +#define RT5631_M_OUTMIXER_L_TO_AXO1MIXER (0x1 << 7) +#define RT5631_M_OUTMIXL_AXO1MIX_BIT 7 +#define RT5631_M_OUTMIXER_R_TO_AXO1MIXER (0x1 << 6) +#define RT5631_M_OUTMIXR_AXO1MIX_BIT 6 + +/* Rout Mixer Control(0x20) */ +#define RT5631_M_MIC1_TO_AXO2MIXER (0x1 << 15) +#define RT5631_M_MIC1_AXO2MIX_BIT 15 +#define RT5631_M_MIC2_TO_AXO2MIXER (0x1 << 11) +#define RT5631_M_MIC2_AXO2MIX_BIT 11 +#define RT5631_M_OUTMIXER_L_TO_AXO2MIXER (0x1 << 7) +#define RT5631_M_OUTMIXL_AXO2MIX_BIT 7 +#define RT5631_M_OUTMIXER_R_TO_AXO2MIXER (0x1 << 6) +#define RT5631_M_OUTMIXR_AXO2MIX_BIT 6 + +/* Micphone Input Control 2(0x22) */ +#define RT5631_MIC_BIAS_90_PRECNET_AVDD 1 +#define RT5631_MIC_BIAS_75_PRECNET_AVDD 2 + +#define RT5631_MIC1_BOOST_CTRL_MASK (0xf << 12) +#define RT5631_MIC1_BOOST_CTRL_BYPASS (0x0 << 12) +#define RT5631_MIC1_BOOST_CTRL_20DB (0x1 << 12) +#define RT5631_MIC1_BOOST_CTRL_24DB (0x2 << 12) +#define RT5631_MIC1_BOOST_CTRL_30DB (0x3 << 12) +#define RT5631_MIC1_BOOST_CTRL_35DB (0x4 << 12) +#define RT5631_MIC1_BOOST_CTRL_40DB (0x5 << 12) +#define RT5631_MIC1_BOOST_CTRL_34DB (0x6 << 12) +#define RT5631_MIC1_BOOST_CTRL_50DB (0x7 << 12) +#define RT5631_MIC1_BOOST_CTRL_52DB (0x8 << 12) +#define RT5631_MIC1_BOOST_SHIFT 12 + +#define RT5631_MIC2_BOOST_CTRL_MASK (0xf << 8) +#define RT5631_MIC2_BOOST_CTRL_BYPASS (0x0 << 8) +#define RT5631_MIC2_BOOST_CTRL_20DB (0x1 << 8) +#define RT5631_MIC2_BOOST_CTRL_24DB (0x2 << 8) +#define RT5631_MIC2_BOOST_CTRL_30DB (0x3 << 8) +#define RT5631_MIC2_BOOST_CTRL_35DB (0x4 << 8) +#define RT5631_MIC2_BOOST_CTRL_40DB (0x5 << 8) +#define RT5631_MIC2_BOOST_CTRL_34DB (0x6 << 8) +#define RT5631_MIC2_BOOST_CTRL_50DB (0x7 << 8) +#define RT5631_MIC2_BOOST_CTRL_52DB (0x8 << 8) +#define RT5631_MIC2_BOOST_SHIFT 8 + +#define RT5631_MICBIAS1_VOLT_CTRL_MASK (0x1 << 7) +#define RT5631_MICBIAS1_VOLT_CTRL_90P (0x0 << 7) +#define RT5631_MICBIAS1_VOLT_CTRL_75P (0x1 << 7) + +#define RT5631_MICBIAS1_S_C_DET_MASK (0x1 << 6) +#define RT5631_MICBIAS1_S_C_DET_DIS (0x0 << 6) +#define RT5631_MICBIAS1_S_C_DET_ENA (0x1 << 6) + +#define RT5631_MICBIAS1_SHORT_CURR_DET_MASK (0x3 << 4) +#define RT5631_MICBIAS1_SHORT_CURR_DET_600UA (0x0 << 4) +#define RT5631_MICBIAS1_SHORT_CURR_DET_1500UA (0x1 << 4) +#define RT5631_MICBIAS1_SHORT_CURR_DET_2000UA (0x2 << 4) + +#define RT5631_MICBIAS2_VOLT_CTRL_MASK (0x1 << 3) +#define RT5631_MICBIAS2_VOLT_CTRL_90P (0x0 << 3) +#define RT5631_MICBIAS2_VOLT_CTRL_75P (0x1 << 3) + +#define RT5631_MICBIAS2_S_C_DET_MASK (0x1 << 2) +#define RT5631_MICBIAS2_S_C_DET_DIS (0x0 << 2) +#define RT5631_MICBIAS2_S_C_DET_ENA (0x1 << 2) + +#define RT5631_MICBIAS2_SHORT_CURR_DET_MASK (0x3) +#define RT5631_MICBIAS2_SHORT_CURR_DET_600UA (0x0) +#define RT5631_MICBIAS2_SHORT_CURR_DET_1500UA (0x1) +#define RT5631_MICBIAS2_SHORT_CURR_DET_2000UA (0x2) + + +/* Digital Microphone Control(0x24) */ +#define RT5631_DMIC_ENA_MASK (0x1 << 15) +#define RT5631_DMIC_ENA_SHIFT 15 +/* DMIC_ENA: DMIC to ADC Digital filter */ +#define RT5631_DMIC_ENA (0x1 << 15) +/* DMIC_DIS: ADC mixer to ADC Digital filter */ +#define RT5631_DMIC_DIS (0x0 << 15) +#define RT5631_DMIC_L_CH_MUTE (0x1 << 13) +#define RT5631_DMIC_L_CH_MUTE_SHIFT 13 +#define RT5631_DMIC_R_CH_MUTE (0x1 << 12) +#define RT5631_DMIC_R_CH_MUTE_SHIFT 12 +#define RT5631_DMIC_L_CH_LATCH_MASK (0x1 << 9) +#define RT5631_DMIC_L_CH_LATCH_RISING (0x1 << 9) +#define RT5631_DMIC_L_CH_LATCH_FALLING (0x0 << 9) +#define RT5631_DMIC_R_CH_LATCH_MASK (0x1 << 8) +#define RT5631_DMIC_R_CH_LATCH_RISING (0x1 << 8) +#define RT5631_DMIC_R_CH_LATCH_FALLING (0x0 << 8) +#define RT5631_DMIC_CLK_CTRL_MASK (0x3 << 4) +#define RT5631_DMIC_CLK_CTRL_TO_128FS (0x0 << 4) +#define RT5631_DMIC_CLK_CTRL_TO_64FS (0x1 << 4) +#define RT5631_DMIC_CLK_CTRL_TO_32FS (0x2 << 4) + +/* Microphone Input Volume(0x26) */ +#define RT5631_MONO_DIFF_INPUT_SHIFT 15 + +/* Speaker Mixer Control(0x28) */ +#define RT5631_M_RECMIXER_L_TO_SPKMIXER_L (0x1 << 15) +#define RT5631_M_RECMIXL_SPKMIXL_BIT 15 +#define RT5631_M_MIC1_P_TO_SPKMIXER_L (0x1 << 14) +#define RT5631_M_MIC1P_SPKMIXL_BIT 14 +#define RT5631_M_DAC_L_TO_SPKMIXER_L (0x1 << 13) +#define RT5631_M_DACL_SPKMIXL_BIT 13 +#define RT5631_M_OUTMIXER_L_TO_SPKMIXER_L (0x1 << 12) +#define RT5631_M_OUTMIXL_SPKMIXL_BIT 12 + +#define RT5631_M_RECMIXER_R_TO_SPKMIXER_R (0x1 << 7) +#define RT5631_M_RECMIXR_SPKMIXR_BIT 7 +#define RT5631_M_MIC2_P_TO_SPKMIXER_R (0x1 << 6) +#define RT5631_M_MIC2P_SPKMIXR_BIT 6 +#define RT5631_M_DAC_R_TO_SPKMIXER_R (0x1 << 5) +#define RT5631_M_DACR_SPKMIXR_BIT 5 +#define RT5631_M_OUTMIXER_R_TO_SPKMIXER_R (0x1 << 4) +#define RT5631_M_OUTMIXR_SPKMIXR_BIT 4 + +/* Speaker/Mono Output Control(0x2A) */ +#define RT5631_M_SPKVOL_L_TO_SPOL_MIXER (0x1 << 15) +#define RT5631_M_SPKVOLL_SPOLMIX_BIT 15 +#define RT5631_M_SPKVOL_R_TO_SPOL_MIXER (0x1 << 14) +#define RT5631_M_SPKVOLR_SPOLMIX_BIT 14 +#define RT5631_M_SPKVOL_L_TO_SPOR_MIXER (0x1 << 13) +#define RT5631_M_SPKVOLL_SPORMIX_BIT 13 +#define RT5631_M_SPKVOL_R_TO_SPOR_MIXER (0x1 << 12) +#define RT5631_M_SPKVOLR_SPORMIX_BIT 12 +#define RT5631_M_OUTVOL_L_TO_MONOMIXER (0x1 << 11) +#define RT5631_M_OUTVOLL_MONOMIX_BIT 11 +#define RT5631_M_OUTVOL_R_TO_MONOMIXER (0x1 << 10) +#define RT5631_M_OUTVOLR_MONOMIX_BIT 10 + +/* Speaker/Mono/HP Output Control(0x2C) */ +#define RT5631_SPK_L_MUX_SEL_MASK (0x3 << 14) +#define RT5631_SPK_L_MUX_SEL_SPKMIXER_L (0x0 << 14) +#define RT5631_SPK_L_MUX_SEL_MONO_IN (0x1 << 14) +#define RT5631_SPK_L_MUX_SEL_DAC_L (0x3 << 14) +#define RT5631_SPK_L_MUX_SEL_SHIFT 14 + +#define RT5631_SPK_R_MUX_SEL_MASK (0x3 << 10) +#define RT5631_SPK_R_MUX_SEL_SPKMIXER_R (0x0 << 10) +#define RT5631_SPK_R_MUX_SEL_MONO_IN (0x1 << 10) +#define RT5631_SPK_R_MUX_SEL_DAC_R (0x3 << 10) +#define RT5631_SPK_R_MUX_SEL_SHIFT 10 + +#define RT5631_MONO_MUX_SEL_MASK (0x3 << 6) +#define RT5631_MONO_MUX_SEL_MONOMIXER (0x0 << 6) +#define RT5631_MONO_MUX_SEL_MONO_IN (0x1 << 6) +#define RT5631_MONO_MUX_SEL_SHIFT 6 + +#define RT5631_HP_L_MUX_SEL_MASK (0x1 << 3) +#define RT5631_HP_L_MUX_SEL_HPVOL_L (0x0 << 3) +#define RT5631_HP_L_MUX_SEL_DAC_L (0x1 << 3) +#define RT5631_HP_L_MUX_SEL_SHIFT 3 + +#define RT5631_HP_R_MUX_SEL_MASK (0x1 << 2) +#define RT5631_HP_R_MUX_SEL_HPVOL_R (0x0 << 2) +#define RT5631_HP_R_MUX_SEL_DAC_R (0x1 << 2) +#define RT5631_HP_R_MUX_SEL_SHIFT 2 + +/* Stereo I2S Serial Data Port Control(0x34) */ +#define RT5631_SDP_MODE_SEL_MASK (0x1 << 15) +#define RT5631_SDP_MODE_SEL_MASTER (0x0 << 15) +#define RT5631_SDP_MODE_SEL_SLAVE (0x1 << 15) + +#define RT5631_SDP_ADC_CPS_SEL_MASK (0x3 << 10) +#define RT5631_SDP_ADC_CPS_SEL_OFF (0x0 << 10) +#define RT5631_SDP_ADC_CPS_SEL_U_LAW (0x1 << 10) +#define RT5631_SDP_ADC_CPS_SEL_A_LAW (0x2 << 10) + +#define RT5631_SDP_DAC_CPS_SEL_MASK (0x3 << 8) +#define RT5631_SDP_DAC_CPS_SEL_OFF (0x0 << 8) +#define RT5631_SDP_DAC_CPS_SEL_U_LAW (0x1 << 8) +#define RT5631_SDP_DAC_CPS_SEL_A_LAW (0x2 << 8) +/* 0:Normal 1:Invert */ +#define RT5631_SDP_I2S_BCLK_POL_CTRL (0x1 << 7) +/* 0:Normal 1:Invert */ +#define RT5631_SDP_DAC_R_INV (0x1 << 6) +/* 0:ADC data appear at left phase of LRCK + * 1:ADC data appear at right phase of LRCK + */ +#define RT5631_SDP_ADC_DATA_L_R_SWAP (0x1 << 5) +/* 0:DAC data appear at left phase of LRCK + * 1:DAC data appear at right phase of LRCK + */ +#define RT5631_SDP_DAC_DATA_L_R_SWAP (0x1 << 4) + +/* Data Length Slection */ +#define RT5631_SDP_I2S_DL_MASK (0x3 << 2) +#define RT5631_SDP_I2S_DL_16 (0x0 << 2) +#define RT5631_SDP_I2S_DL_20 (0x1 << 2) +#define RT5631_SDP_I2S_DL_24 (0x2 << 2) +#define RT5631_SDP_I2S_DL_8 (0x3 << 2) + +/* PCM Data Format Selection */ +#define RT5631_SDP_I2S_DF_MASK (0x3) +#define RT5631_SDP_I2S_DF_I2S (0x0) +#define RT5631_SDP_I2S_DF_LEFT (0x1) +#define RT5631_SDP_I2S_DF_PCM_A (0x2) +#define RT5631_SDP_I2S_DF_PCM_B (0x3) + +/* Stereo AD/DA Clock Control(0x38h) */ +#define RT5631_I2S_PRE_DIV_MASK (0x7 << 13) +#define RT5631_I2S_PRE_DIV_1 (0x0 << 13) +#define RT5631_I2S_PRE_DIV_2 (0x1 << 13) +#define RT5631_I2S_PRE_DIV_4 (0x2 << 13) +#define RT5631_I2S_PRE_DIV_8 (0x3 << 13) +#define RT5631_I2S_PRE_DIV_16 (0x4 << 13) +#define RT5631_I2S_PRE_DIV_32 (0x5 << 13) +/* CLOCK RELATIVE OF BCLK AND LCRK */ +#define RT5631_I2S_LRCK_SEL_N_BCLK_MASK (0x1 << 12) +#define RT5631_I2S_LRCK_SEL_64_BCLK (0x0 << 12) /* 64FS */ +#define RT5631_I2S_LRCK_SEL_32_BCLK (0x1 << 12) /* 32FS */ + +#define RT5631_DAC_OSR_SEL_MASK (0x3 << 10) +#define RT5631_DAC_OSR_SEL_128FS (0x3 << 10) +#define RT5631_DAC_OSR_SEL_64FS (0x3 << 10) +#define RT5631_DAC_OSR_SEL_32FS (0x3 << 10) +#define RT5631_DAC_OSR_SEL_16FS (0x3 << 10) + +#define RT5631_ADC_OSR_SEL_MASK (0x3 << 8) +#define RT5631_ADC_OSR_SEL_128FS (0x3 << 8) +#define RT5631_ADC_OSR_SEL_64FS (0x3 << 8) +#define RT5631_ADC_OSR_SEL_32FS (0x3 << 8) +#define RT5631_ADC_OSR_SEL_16FS (0x3 << 8) + +#define RT5631_ADDA_FILTER_CLK_SEL_256FS (0 << 7) /* 256FS */ +#define RT5631_ADDA_FILTER_CLK_SEL_384FS (1 << 7) /* 384FS */ + +/* Power managment addition 1 (0x3A) */ +#define RT5631_PWR_MAIN_I2S_EN (0x1 << 15) +#define RT5631_PWR_MAIN_I2S_BIT 15 +#define RT5631_PWR_CLASS_D (0x1 << 12) +#define RT5631_PWR_CLASS_D_BIT 12 +#define RT5631_PWR_ADC_L_CLK (0x1 << 11) +#define RT5631_PWR_ADC_L_CLK_BIT 11 +#define RT5631_PWR_ADC_R_CLK (0x1 << 10) +#define RT5631_PWR_ADC_R_CLK_BIT 10 +#define RT5631_PWR_DAC_L_CLK (0x1 << 9) +#define RT5631_PWR_DAC_L_CLK_BIT 9 +#define RT5631_PWR_DAC_R_CLK (0x1 << 8) +#define RT5631_PWR_DAC_R_CLK_BIT 8 +#define RT5631_PWR_DAC_REF (0x1 << 7) +#define RT5631_PWR_DAC_REF_BIT 7 +#define RT5631_PWR_DAC_L_TO_MIXER (0x1 << 6) +#define RT5631_PWR_DAC_L_TO_MIXER_BIT 6 +#define RT5631_PWR_DAC_R_TO_MIXER (0x1 << 5) +#define RT5631_PWR_DAC_R_TO_MIXER_BIT 5 + +/* Power managment addition 2 (0x3B) */ +#define RT5631_PWR_OUTMIXER_L (0x1 << 15) +#define RT5631_PWR_OUTMIXER_L_BIT 15 +#define RT5631_PWR_OUTMIXER_R (0x1 << 14) +#define RT5631_PWR_OUTMIXER_R_BIT 14 +#define RT5631_PWR_SPKMIXER_L (0x1 << 13) +#define RT5631_PWR_SPKMIXER_L_BIT 13 +#define RT5631_PWR_SPKMIXER_R (0x1 << 12) +#define RT5631_PWR_SPKMIXER_R_BIT 12 +#define RT5631_PWR_RECMIXER_L (0x1 << 11) +#define RT5631_PWR_RECMIXER_L_BIT 11 +#define RT5631_PWR_RECMIXER_R (0x1 << 10) +#define RT5631_PWR_RECMIXER_R_BIT 10 +#define RT5631_PWR_MIC1_BOOT_GAIN (0x1 << 5) +#define RT5631_PWR_MIC1_BOOT_GAIN_BIT 5 +#define RT5631_PWR_MIC2_BOOT_GAIN (0x1 << 4) +#define RT5631_PWR_MIC2_BOOT_GAIN_BIT 4 +#define RT5631_PWR_MICBIAS1_VOL (0x1 << 3) +#define RT5631_PWR_MICBIAS1_VOL_BIT 3 +#define RT5631_PWR_MICBIAS2_VOL (0x1 << 2) +#define RT5631_PWR_MICBIAS2_VOL_BIT 2 +#define RT5631_PWR_PLL1 (0x1 << 1) +#define RT5631_PWR_PLL1_BIT 1 +#define RT5631_PWR_PLL2 (0x1 << 0) +#define RT5631_PWR_PLL2_BIT 0 + +/* Power managment addition 3(0x3C) */ +#define RT5631_PWR_VREF (0x1 << 15) +#define RT5631_PWR_VREF_BIT 15 +#define RT5631_PWR_FAST_VREF_CTRL (0x1 << 14) +#define RT5631_PWR_FAST_VREF_CTRL_BIT 14 +#define RT5631_PWR_MAIN_BIAS (0x1 << 13) +#define RT5631_PWR_MAIN_BIAS_BIT 13 +#define RT5631_PWR_AXO1MIXER (0x1 << 11) +#define RT5631_PWR_AXO1MIXER_BIT 11 +#define RT5631_PWR_AXO2MIXER (0x1 << 10) +#define RT5631_PWR_AXO2MIXER_BIT 10 +#define RT5631_PWR_MONOMIXER (0x1 << 9) +#define RT5631_PWR_MONOMIXER_BIT 9 +#define RT5631_PWR_MONO_DEPOP_DIS (0x1 << 8) +#define RT5631_PWR_MONO_DEPOP_DIS_BIT 8 +#define RT5631_PWR_MONO_AMP_EN (0x1 << 7) +#define RT5631_PWR_MONO_AMP_EN_BIT 7 +#define RT5631_PWR_CHARGE_PUMP (0x1 << 4) +#define RT5631_PWR_CHARGE_PUMP_BIT 4 +#define RT5631_PWR_HP_L_AMP (0x1 << 3) +#define RT5631_PWR_HP_L_AMP_BIT 3 +#define RT5631_PWR_HP_R_AMP (0x1 << 2) +#define RT5631_PWR_HP_R_AMP_BIT 2 +#define RT5631_PWR_HP_DEPOP_DIS (0x1 << 1) +#define RT5631_PWR_HP_DEPOP_DIS_BIT 1 +#define RT5631_PWR_HP_AMP_DRIVING (0x1 << 0) +#define RT5631_PWR_HP_AMP_DRIVING_BIT 0 + +/* Power managment addition 4(0x3E) */ +#define RT5631_PWR_SPK_L_VOL (0x1 << 15) +#define RT5631_PWR_SPK_L_VOL_BIT 15 +#define RT5631_PWR_SPK_R_VOL (0x1 << 14) +#define RT5631_PWR_SPK_R_VOL_BIT 14 +#define RT5631_PWR_LOUT_VOL (0x1 << 13) +#define RT5631_PWR_LOUT_VOL_BIT 13 +#define RT5631_PWR_ROUT_VOL (0x1 << 12) +#define RT5631_PWR_ROUT_VOL_BIT 12 +#define RT5631_PWR_HP_L_OUT_VOL (0x1 << 11) +#define RT5631_PWR_HP_L_OUT_VOL_BIT 11 +#define RT5631_PWR_HP_R_OUT_VOL (0x1 << 10) +#define RT5631_PWR_HP_R_OUT_VOL_BIT 10 +#define RT5631_PWR_AXIL_IN_VOL (0x1 << 9) +#define RT5631_PWR_AXIL_IN_VOL_BIT 9 +#define RT5631_PWR_AXIR_IN_VOL (0x1 << 8) +#define RT5631_PWR_AXIR_IN_VOL_BIT 8 +#define RT5631_PWR_MONO_IN_P_VOL (0x1 << 7) +#define RT5631_PWR_MONO_IN_P_VOL_BIT 7 +#define RT5631_PWR_MONO_IN_N_VOL (0x1 << 6) +#define RT5631_PWR_MONO_IN_N_VOL_BIT 6 + +/* General Purpose Control Register(0x40) */ +#define RT5631_SPK_AMP_AUTO_RATIO_EN (0x1 << 15) + +#define RT5631_SPK_AMP_RATIO_CTRL_MASK (0x7 << 12) +#define RT5631_SPK_AMP_RATIO_CTRL_2_34 (0x0 << 12) /* 7.40DB */ +#define RT5631_SPK_AMP_RATIO_CTRL_1_99 (0x1 << 12) /* 5.99DB */ +#define RT5631_SPK_AMP_RATIO_CTRL_1_68 (0x2 << 12) /* 4.50DB */ +#define RT5631_SPK_AMP_RATIO_CTRL_1_56 (0x3 << 12) /* 3.86DB */ +#define RT5631_SPK_AMP_RATIO_CTRL_1_44 (0x4 << 12) /* 3.16DB */ +#define RT5631_SPK_AMP_RATIO_CTRL_1_27 (0x5 << 12) /* 2.10DB */ +#define RT5631_SPK_AMP_RATIO_CTRL_1_09 (0x6 << 12) /* 0.80DB */ +#define RT5631_SPK_AMP_RATIO_CTRL_1_00 (0x7 << 12) /* 0.00DB */ +#define RT5631_SPK_AMP_RATIO_CTRL_SHIFT 12 + +#define RT5631_STEREO_DAC_HI_PASS_FILT_EN (0x1 << 11) +#define RT5631_STEREO_ADC_HI_PASS_FILT_EN (0x1 << 10) +/* Select ADC Wind Filter Clock type */ +#define RT5631_ADC_WIND_FILT_MASK (0x3 << 4) +#define RT5631_ADC_WIND_FILT_8_16_32K (0x0 << 4) /*8/16/32k*/ +#define RT5631_ADC_WIND_FILT_11_22_44K (0x1 << 4) /*11/22/44k*/ +#define RT5631_ADC_WIND_FILT_12_24_48K (0x2 << 4) /*12/24/48k*/ +#define RT5631_ADC_WIND_FILT_EN (0x1 << 3) +/* SelectADC Wind Filter Corner Frequency */ +#define RT5631_ADC_WIND_CNR_FREQ_MASK (0x7 << 0) +#define RT5631_ADC_WIND_CNR_FREQ_82_113_122 (0x0 << 0) /* 82/113/122 Hz */ +#define RT5631_ADC_WIND_CNR_FREQ_102_141_153 (0x1 << 0) /* 102/141/153 Hz */ +#define RT5631_ADC_WIND_CNR_FREQ_131_180_156 (0x2 << 0) /* 131/180/156 Hz */ +#define RT5631_ADC_WIND_CNR_FREQ_163_225_245 (0x3 << 0) /* 163/225/245 Hz */ +#define RT5631_ADC_WIND_CNR_FREQ_204_281_306 (0x4 << 0) /* 204/281/306 Hz */ +#define RT5631_ADC_WIND_CNR_FREQ_261_360_392 (0x5 << 0) /* 261/360/392 Hz */ +#define RT5631_ADC_WIND_CNR_FREQ_327_450_490 (0x6 << 0) /* 327/450/490 Hz */ +#define RT5631_ADC_WIND_CNR_FREQ_408_563_612 (0x7 << 0) /* 408/563/612 Hz */ + +/* Global Clock Control Register(0x42) */ +#define RT5631_SYSCLK_SOUR_SEL_MASK (0x3 << 14) +#define RT5631_SYSCLK_SOUR_SEL_MCLK (0x0 << 14) +#define RT5631_SYSCLK_SOUR_SEL_PLL (0x1 << 14) +#define RT5631_SYSCLK_SOUR_SEL_PLL_TCK (0x2 << 14) + +#define RT5631_PLLCLK_SOUR_SEL_MASK (0x3 << 12) +#define RT5631_PLLCLK_SOUR_SEL_MCLK (0x0 << 12) +#define RT5631_PLLCLK_SOUR_SEL_BCLK (0x1 << 12) +#define RT5631_PLLCLK_SOUR_SEL_VBCLK (0x2 << 12) + +#define RT5631_PLLCLK_PRE_DIV1 (0x0 << 11) +#define RT5631_PLLCLK_PRE_DIV2 (0x1 << 11) + +/* PLL Control(0x44) */ +#define RT5631_PLL_CTRL_M_VAL(m) ((m)&0xf) +#define RT5631_PLL_CTRL_K_VAL(k) (((k)&0x7) << 4) +#define RT5631_PLL_CTRL_N_VAL(n) (((n)&0xff) << 8) + +/* Internal Status and IRQ Control2(0x4A) */ +#define RT5631_ADC_DATA_SEL_MASK (0x3 << 14) +#define RT5631_ADC_DATA_SEL_Disable (0x0 << 14) +#define RT5631_ADC_DATA_SEL_MIC1 (0x1 << 14) +#define RT5631_ADC_DATA_SEL_MIC1_SHIFT 14 +#define RT5631_ADC_DATA_SEL_MIC2 (0x2 << 14) +#define RT5631_ADC_DATA_SEL_MIC2_SHIFT 15 +#define RT5631_ADC_DATA_SEL_STO (0x3 << 14) +#define RT5631_ADC_DATA_SEL_SHIFT 14 + +/* GPIO Pin Configuration(0x4C) */ +#define RT5631_GPIO_PIN_FUN_SEL_MASK (0x1 << 15) +#define RT5631_GPIO_PIN_FUN_SEL_IRQ (0x1 << 15) +#define RT5631_GPIO_PIN_FUN_SEL_GPIO_DIMC (0x0 << 15) + +#define RT5631_GPIO_DMIC_FUN_SEL_MASK (0x1 << 3) +#define RT5631_GPIO_DMIC_FUN_SEL_DIMC (0x1 << 3) +#define RT5631_GPIO_DMIC_FUN_SEL_GPIO (0x0 << 3) + +#define RT5631_GPIO_PIN_CON_MASK (0x1 << 2) +#define RT5631_GPIO_PIN_SET_INPUT (0x0 << 2) +#define RT5631_GPIO_PIN_SET_OUTPUT (0x1 << 2) + +/* De-POP function Control 1(0x54) */ +#define RT5631_POW_ON_SOFT_GEN (0x1 << 15) +#define RT5631_EN_MUTE_UNMUTE_DEPOP (0x1 << 14) +#define RT5631_EN_DEPOP2_FOR_HP (0x1 << 7) +/* Power Down HPAMP_L Starts Up Signal */ +#define RT5631_PD_HPAMP_L_ST_UP (0x1 << 5) +/* Power Down HPAMP_R Starts Up Signal */ +#define RT5631_PD_HPAMP_R_ST_UP (0x1 << 4) +/* Enable left HP mute/unmute depop */ +#define RT5631_EN_HP_L_M_UN_MUTE_DEPOP (0x1 << 1) +/* Enable right HP mute/unmute depop */ +#define RT5631_EN_HP_R_M_UN_MUTE_DEPOP (0x1 << 0) + +/* De-POP Fnction Control(0x56) */ +#define RT5631_EN_ONE_BIT_DEPOP (0x1 << 15) +#define RT5631_EN_CAP_FREE_DEPOP (0x1 << 14) + +/* Jack Detect Control Register(0x5A) */ +#define RT5631_JD_USE_MASK (0x3 << 14) +#define RT5631_JD_USE_JD2 (0x3 << 14) +#define RT5631_JD_USE_JD1 (0x2 << 14) +#define RT5631_JD_USE_GPIO (0x1 << 14) +#define RT5631_JD_OFF (0x0 << 14) +/* JD trigger enable for HP */ +#define RT5631_JD_HP_EN (0x1 << 11) +#define RT5631_JD_HP_TRI_MASK (0x1 << 10) +#define RT5631_JD_HP_TRI_HI (0x1 << 10) +#define RT5631_JD_HP_TRI_LO (0x1 << 10) +/* JD trigger enable for speaker LP/LN */ +#define RT5631_JD_SPK_L_EN (0x1 << 9) +#define RT5631_JD_SPK_L_TRI_MASK (0x1 << 8) +#define RT5631_JD_SPK_L_TRI_HI (0x1 << 8) +#define RT5631_JD_SPK_L_TRI_LO (0x0 << 8) +/* JD trigger enable for speaker RP/RN */ +#define RT5631_JD_SPK_R_EN (0x1 << 7) +#define RT5631_JD_SPK_R_TRI_MASK (0x1 << 6) +#define RT5631_JD_SPK_R_TRI_HI (0x1 << 6) +#define RT5631_JD_SPK_R_TRI_LO (0x0 << 6) +/* JD trigger enable for monoout */ +#define RT5631_JD_MONO_EN (0x1 << 5) +#define RT5631_JD_MONO_TRI_MASK (0x1 << 4) +#define RT5631_JD_MONO_TRI_HI (0x1 << 4) +#define RT5631_JD_MONO_TRI_LO (0x0 << 4) +/* JD trigger enable for Lout */ +#define RT5631_JD_AUX_1_EN (0x1 << 3) +#define RT5631_JD_AUX_1_MASK (0x1 << 2) +#define RT5631_JD_AUX_1_TRI_HI (0x1 << 2) +#define RT5631_JD_AUX_1_TRI_LO (0x0 << 2) +/* JD trigger enable for Rout */ +#define RT5631_JD_AUX_2_EN (0x1 << 1) +#define RT5631_JD_AUX_2_MASK (0x1 << 0) +#define RT5631_JD_AUX_2_TRI_HI (0x1 << 0) +#define RT5631_JD_AUX_2_TRI_LO (0x0 << 0) + +/* ALC CONTROL 1(0x64) */ +#define RT5631_ALC_ATTACK_RATE_MASK (0x1F << 8) +#define RT5631_ALC_RECOVERY_RATE_MASK (0x1F << 0) + +/* ALC CONTROL 2(0x65) */ +/* select Compensation gain for Noise gate function */ +#define RT5631_ALC_COM_NOISE_GATE_MASK (0xF << 0) + +/* ALC CONTROL 3(0x66) */ +#define RT5631_ALC_FUN_MASK (0x3 << 14) +#define RT5631_ALC_FUN_DIS (0x0 << 14) +#define RT5631_ALC_ENA_DAC_PATH (0x1 << 14) +#define RT5631_ALC_ENA_ADC_PATH (0x3 << 14) +#define RT5631_ALC_PARA_UPDATE (0x1 << 13) +#define RT5631_ALC_LIMIT_LEVEL_MASK (0x1F << 8) +#define RT5631_ALC_NOISE_GATE_FUN_MASK (0x1 << 7) +#define RT5631_ALC_NOISE_GATE_FUN_DIS (0x0 << 7) +#define RT5631_ALC_NOISE_GATE_FUN_ENA (0x1 << 7) +/* ALC noise gate hold data function */ +#define RT5631_ALC_NOISE_GATE_H_D_MASK (0x1 << 6) +#define RT5631_ALC_NOISE_GATE_H_D_DIS (0x0 << 6) +#define RT5631_ALC_NOISE_GATE_H_D_ENA (0x1 << 6) + +/* Psedueo Stereo & Spatial Effect Block Control(0x68) */ +#define RT5631_SPATIAL_CTRL_EN (0x1 << 15) +#define RT5631_ALL_PASS_FILTER_EN (0x1 << 14) +#define RT5631_PSEUDO_STEREO_EN (0x1 << 13) +#define RT5631_STEREO_EXPENSION_EN (0x1 << 12) +/* 3D gain parameter */ +#define RT5631_GAIN_3D_PARA_MASK (0x3 << 6) +#define RT5631_GAIN_3D_PARA_1_00 (0x0 << 6) /* 3D gain 1.0 */ +#define RT5631_GAIN_3D_PARA_1_50 (0x1 << 6) /* 3D gain 1.5 */ +#define RT5631_GAIN_3D_PARA_2_00 (0x2 << 6) /* 3D gain 2.0 */ +/* 3D ratio parameter */ +#define RT5631_RATIO_3D_MASK (0x3 << 4) +#define RT5631_RATIO_3D_0_0 (0x0 << 4) /* 3D ratio 0.0 */ +#define RT5631_RATIO_3D_0_66 (0x1 << 4) /* 3D ratio 0.66 */ +#define RT5631_RATIO_3D_1_0 (0x2 << 4) /* 3D ratio 1.0 */ +/* select samplerate for all pass filter */ +#define RT5631_APF_FUN_SLE_MASK (0x3 << 0) +#define RT5631_APF_FUN_SEL_48K (0x3 << 0) +#define RT5631_APF_FUN_SEL_44_1K (0x2 << 0) +#define RT5631_APF_FUN_SEL_32K (0x1 << 0) +#define RT5631_APF_FUN_DIS (0x0 << 0) + +/* EQ CONTROL 1(0x6E) */ +#define RT5631_HW_EQ_PATH_SEL_MASK (0x1 << 15) +#define RT5631_HW_EQ_PATH_SEL_DAC (0x0 << 15) +#define RT5631_HW_EQ_PATH_SEL_ADC (0x1 << 15) +#define RT5631_HW_EQ_UPDATE_CTRL (0x1 << 14) + +#define RT5631_EN_HW_EQ_HPF2 (0x1 << 5) +#define RT5631_EN_HW_EQ_HPF1 (0x1 << 4) +#define RT5631_EN_HW_EQ_BP3 (0x1 << 3) +#define RT5631_EN_HW_EQ_BP2 (0x1 << 2) +#define RT5631_EN_HW_EQ_BP1 (0x1 << 1) +#define RT5631_EN_HW_EQ_LPF (0x1 << 0) + + +#endif /* __RTCODEC5631_H__ */ diff --git a/sound/soc/codecs/sgtl5000.c b/sound/soc/codecs/sgtl5000.c index 7e4066e131e..d15695d1c27 100644 --- a/sound/soc/codecs/sgtl5000.c +++ b/sound/soc/codecs/sgtl5000.c @@ -20,6 +20,7 @@ #include <linux/regulator/driver.h> #include <linux/regulator/machine.h> #include <linux/regulator/consumer.h> +#include <linux/of_device.h> #include <sound/core.h> #include <sound/tlv.h> #include <sound/pcm.h> @@ -130,16 +131,13 @@ static int mic_bias_event(struct snd_soc_dapm_widget *w, case SND_SOC_DAPM_POST_PMU: /* change mic bias resistor to 4Kohm */ snd_soc_update_bits(w->codec, SGTL5000_CHIP_MIC_CTRL, - SGTL5000_BIAS_R_4k, SGTL5000_BIAS_R_4k); + SGTL5000_BIAS_R_MASK, + SGTL5000_BIAS_R_4k << SGTL5000_BIAS_R_SHIFT); break; case SND_SOC_DAPM_PRE_PMD: - /* - * SGTL5000_BIAS_R_8k as mask to clean the two bits - * of mic bias and output impedance - */ snd_soc_update_bits(w->codec, SGTL5000_CHIP_MIC_CTRL, - SGTL5000_BIAS_R_8k, 0); + SGTL5000_BIAS_R_MASK, 0); break; } return 0; @@ -725,7 +723,9 @@ static int sgtl5000_pcm_hw_params(struct snd_pcm_substream *substream, return -EINVAL; } - snd_soc_update_bits(codec, SGTL5000_CHIP_I2S_CTRL, i2s_ctl, i2s_ctl); + snd_soc_update_bits(codec, SGTL5000_CHIP_I2S_CTRL, + SGTL5000_I2S_DLEN_MASK | SGTL5000_I2S_SCLKFREQ_MASK, + i2s_ctl); return 0; } @@ -756,7 +756,7 @@ static int ldo_regulator_enable(struct regulator_dev *dev) /* set voltage to register */ snd_soc_update_bits(codec, SGTL5000_CHIP_LINREG_CTRL, - (0x1 << 4) - 1, reg); + SGTL5000_LINREG_VDDD_MASK, reg); snd_soc_update_bits(codec, SGTL5000_CHIP_ANA_POWER, SGTL5000_LINEREG_D_POWERUP, @@ -782,7 +782,7 @@ static int ldo_regulator_disable(struct regulator_dev *dev) /* clear voltage info */ snd_soc_update_bits(codec, SGTL5000_CHIP_LINREG_CTRL, - (0x1 << 4) - 1, 0); + SGTL5000_LINREG_VDDD_MASK, 0); ldo->enabled = 0; @@ -808,6 +808,7 @@ static int ldo_regulator_register(struct snd_soc_codec *codec, int voltage) { struct ldo_regulator *ldo; + struct sgtl5000_priv *sgtl5000 = snd_soc_codec_get_drvdata(codec); ldo = kzalloc(sizeof(struct ldo_regulator), GFP_KERNEL); @@ -842,6 +843,7 @@ static int ldo_regulator_register(struct snd_soc_codec *codec, return ret; } + sgtl5000->ldo = ldo; return 0; } @@ -1115,7 +1117,7 @@ static int sgtl5000_set_power_regs(struct snd_soc_codec *codec) /* set voltage to register */ snd_soc_update_bits(codec, SGTL5000_CHIP_LINREG_CTRL, - (0x1 << 4) - 1, 0x8); + SGTL5000_LINREG_VDDD_MASK, 0x8); /* * if vddd linear reg has been enabled, @@ -1146,8 +1148,7 @@ static int sgtl5000_set_power_regs(struct snd_soc_codec *codec) vag = (vag - SGTL5000_ANA_GND_BASE) / SGTL5000_ANA_GND_STP; snd_soc_update_bits(codec, SGTL5000_CHIP_REF_CTRL, - vag << SGTL5000_ANA_GND_SHIFT, - vag << SGTL5000_ANA_GND_SHIFT); + SGTL5000_ANA_GND_MASK, vag << SGTL5000_ANA_GND_SHIFT); /* set line out VAG to vddio / 2, in range (0.8v, 1.675v) */ vag = vddio / 2; @@ -1161,9 +1162,8 @@ static int sgtl5000_set_power_regs(struct snd_soc_codec *codec) SGTL5000_LINE_OUT_GND_STP; snd_soc_update_bits(codec, SGTL5000_CHIP_LINE_OUT_CTRL, - vag << SGTL5000_LINE_OUT_GND_SHIFT | - SGTL5000_LINE_OUT_CURRENT_360u << - SGTL5000_LINE_OUT_CURRENT_SHIFT, + SGTL5000_LINE_OUT_CURRENT_MASK | + SGTL5000_LINE_OUT_GND_MASK, vag << SGTL5000_LINE_OUT_GND_SHIFT | SGTL5000_LINE_OUT_CURRENT_360u << SGTL5000_LINE_OUT_CURRENT_SHIFT); @@ -1436,10 +1436,17 @@ static const struct i2c_device_id sgtl5000_id[] = { MODULE_DEVICE_TABLE(i2c, sgtl5000_id); +static const struct of_device_id sgtl5000_dt_ids[] = { + { .compatible = "fsl,sgtl5000", }, + { /* sentinel */ } +}; +MODULE_DEVICE_TABLE(of, sgtl5000_dt_ids); + static struct i2c_driver sgtl5000_i2c_driver = { .driver = { .name = "sgtl5000", .owner = THIS_MODULE, + .of_match_table = sgtl5000_dt_ids, }, .probe = sgtl5000_i2c_probe, .remove = __devexit_p(sgtl5000_i2c_remove), diff --git a/sound/soc/codecs/sgtl5000.h b/sound/soc/codecs/sgtl5000.h index eec3ab368f3..8a9f43534b7 100644 --- a/sound/soc/codecs/sgtl5000.h +++ b/sound/soc/codecs/sgtl5000.h @@ -280,7 +280,7 @@ /* * SGTL5000_CHIP_MIC_CTRL */ -#define SGTL5000_BIAS_R_MASK 0x0200 +#define SGTL5000_BIAS_R_MASK 0x0300 #define SGTL5000_BIAS_R_SHIFT 8 #define SGTL5000_BIAS_R_WIDTH 2 #define SGTL5000_BIAS_R_off 0x0 diff --git a/sound/soc/codecs/sn95031.c b/sound/soc/codecs/sn95031.c index 84ffdebb8a8..887d618f4a6 100644 --- a/sound/soc/codecs/sn95031.c +++ b/sound/soc/codecs/sn95031.c @@ -28,6 +28,7 @@ #include <linux/platform_device.h> #include <linux/delay.h> #include <linux/slab.h> +#include <linux/module.h> #include <asm/intel_scu_ipc.h> #include <sound/pcm.h> @@ -79,7 +80,7 @@ static void configure_adc(struct snd_soc_codec *sn95031_codec, int val) */ static int find_free_channel(struct snd_soc_codec *sn95031_codec) { - int ret = 0, i, value; + int i, value; /* check whether ADC is enabled */ value = snd_soc_read(sn95031_codec, SN95031_ADC1CNTL1); @@ -91,12 +92,10 @@ static int find_free_channel(struct snd_soc_codec *sn95031_codec) for (i = 0; i < SN95031_ADC_CHANLS_MAX; i++) { value = snd_soc_read(sn95031_codec, SN95031_ADC_CHNL_START_ADDR + i); - if (value & SN95031_STOPBIT_MASK) { - ret = i; + if (value & SN95031_STOPBIT_MASK) break; - } } - return (ret > SN95031_ADC_LOOP_MAX) ? (-EINVAL) : ret; + return (i == SN95031_ADC_CHANLS_MAX) ? (-EINVAL) : i; } /* Initialize the ADC for reading micbias values. Can sleep. */ @@ -104,7 +103,7 @@ static int sn95031_initialize_adc(struct snd_soc_codec *sn95031_codec) { int base_addr, chnl_addr; int value; - static int channel_index; + int channel_index; /* Index of the first channel in which the stop bit is set */ channel_index = find_free_channel(sn95031_codec); @@ -163,7 +162,6 @@ static unsigned int sn95031_get_mic_bias(struct snd_soc_codec *codec) pr_debug("mic bias = %dmV\n", mic_bias); return mic_bias; } -EXPORT_SYMBOL_GPL(sn95031_get_mic_bias); /*end - adc helper functions */ static inline unsigned int sn95031_read(struct snd_soc_codec *codec, @@ -660,7 +658,7 @@ static int sn95031_pcm_spkr_mute(struct snd_soc_dai *dai, int mute) return 0; } -int sn95031_pcm_hw_params(struct snd_pcm_substream *substream, +static int sn95031_pcm_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params, struct snd_soc_dai *dai) { unsigned int format, rate; @@ -718,7 +716,7 @@ static struct snd_soc_dai_ops sn95031_vib2_dai_ops = { .hw_params = sn95031_pcm_hw_params, }; -struct snd_soc_dai_driver sn95031_dais[] = { +static struct snd_soc_dai_driver sn95031_dais[] = { { .name = "SN95031 Headset", .playback = { @@ -829,7 +827,6 @@ static int sn95031_codec_probe(struct snd_soc_codec *codec) { pr_debug("codec_probe called\n"); - codec->dapm.bias_level = SND_SOC_BIAS_OFF; codec->dapm.idle_bias_off = 1; /* PCM interface config diff --git a/sound/soc/codecs/ssm2602.c b/sound/soc/codecs/ssm2602.c index 9801cd7cfcb..3cb3271c5fe 100644 --- a/sound/soc/codecs/ssm2602.c +++ b/sound/soc/codecs/ssm2602.c @@ -59,6 +59,7 @@ struct ssm2602_priv { struct snd_pcm_substream *slave_substream; enum ssm2602_type type; + unsigned int clk_out_pwr; }; /* @@ -294,7 +295,6 @@ static int ssm2602_startup(struct snd_pcm_substream *substream, struct snd_soc_pcm_runtime *rtd = substream->private_data; struct snd_soc_codec *codec = rtd->codec; struct ssm2602_priv *ssm2602 = snd_soc_codec_get_drvdata(codec); - struct i2c_client *i2c = codec->control_data; struct snd_pcm_runtime *master_runtime; /* The DAI has shared clocks so if we already have a playback or @@ -303,7 +303,7 @@ static int ssm2602_startup(struct snd_pcm_substream *substream, */ if (ssm2602->master_substream) { master_runtime = ssm2602->master_substream->runtime; - dev_dbg(&i2c->dev, "Constraining to %d bits at %dHz\n", + dev_dbg(codec->dev, "Constraining to %d bits at %dHz\n", master_runtime->sample_bits, master_runtime->rate); @@ -343,12 +343,14 @@ static void ssm2602_shutdown(struct snd_pcm_substream *substream, static int ssm2602_mute(struct snd_soc_dai *dai, int mute) { struct snd_soc_codec *codec = dai->codec; - u16 mute_reg = snd_soc_read(codec, SSM2602_APDIGI) & ~APDIGI_ENABLE_DAC_MUTE; + if (mute) - snd_soc_write(codec, SSM2602_APDIGI, - mute_reg | APDIGI_ENABLE_DAC_MUTE); + snd_soc_update_bits(codec, SSM2602_APDIGI, + APDIGI_ENABLE_DAC_MUTE, + APDIGI_ENABLE_DAC_MUTE); else - snd_soc_write(codec, SSM2602_APDIGI, mute_reg); + snd_soc_update_bits(codec, SSM2602_APDIGI, + APDIGI_ENABLE_DAC_MUTE, 0); return 0; } @@ -357,16 +359,46 @@ static int ssm2602_set_dai_sysclk(struct snd_soc_dai *codec_dai, { struct snd_soc_codec *codec = codec_dai->codec; struct ssm2602_priv *ssm2602 = snd_soc_codec_get_drvdata(codec); - switch (freq) { - case 11289600: - case 12000000: - case 12288000: - case 16934400: - case 18432000: - ssm2602->sysclk = freq; - return 0; + + if (dir == SND_SOC_CLOCK_IN) { + if (clk_id != SSM2602_SYSCLK) + return -EINVAL; + + switch (freq) { + case 11289600: + case 12000000: + case 12288000: + case 16934400: + case 18432000: + ssm2602->sysclk = freq; + break; + default: + return -EINVAL; + } + } else { + unsigned int mask; + + switch (clk_id) { + case SSM2602_CLK_CLKOUT: + mask = PWR_CLK_OUT_PDN; + break; + case SSM2602_CLK_XTO: + mask = PWR_OSC_PDN; + break; + default: + return -EINVAL; + } + + if (freq == 0) + ssm2602->clk_out_pwr |= mask; + else + ssm2602->clk_out_pwr &= ~mask; + + snd_soc_update_bits(codec, SSM2602_PWR, + PWR_CLK_OUT_PDN | PWR_OSC_PDN, ssm2602->clk_out_pwr); } - return -EINVAL; + + return 0; } static int ssm2602_set_dai_fmt(struct snd_soc_dai *codec_dai, @@ -431,23 +463,27 @@ static int ssm2602_set_dai_fmt(struct snd_soc_dai *codec_dai, static int ssm2602_set_bias_level(struct snd_soc_codec *codec, enum snd_soc_bias_level level) { - u16 reg = snd_soc_read(codec, SSM2602_PWR); - reg &= ~(PWR_POWER_OFF | PWR_OSC_PDN); + struct ssm2602_priv *ssm2602 = snd_soc_codec_get_drvdata(codec); switch (level) { case SND_SOC_BIAS_ON: - /* vref/mid, osc on, dac unmute */ - snd_soc_write(codec, SSM2602_PWR, reg); + /* vref/mid on, osc and clkout on if enabled */ + snd_soc_update_bits(codec, SSM2602_PWR, + PWR_POWER_OFF | PWR_CLK_OUT_PDN | PWR_OSC_PDN, + ssm2602->clk_out_pwr); break; case SND_SOC_BIAS_PREPARE: break; case SND_SOC_BIAS_STANDBY: /* everything off except vref/vmid, */ - snd_soc_write(codec, SSM2602_PWR, reg | PWR_CLK_OUT_PDN); + snd_soc_update_bits(codec, SSM2602_PWR, + PWR_POWER_OFF | PWR_CLK_OUT_PDN | PWR_OSC_PDN, + PWR_CLK_OUT_PDN | PWR_OSC_PDN); break; case SND_SOC_BIAS_OFF: - /* everything off, dac mute, inactive */ - snd_soc_write(codec, SSM2602_PWR, 0xffff); + /* everything off */ + snd_soc_update_bits(codec, SSM2602_PWR, + PWR_POWER_OFF, PWR_POWER_OFF); break; } @@ -506,12 +542,12 @@ static int ssm2602_resume(struct snd_soc_codec *codec) static int ssm2602_probe(struct snd_soc_codec *codec) { struct snd_soc_dapm_context *dapm = &codec->dapm; - int ret, reg; + int ret; - reg = snd_soc_read(codec, SSM2602_LOUT1V); - snd_soc_write(codec, SSM2602_LOUT1V, reg | LOUT1V_LRHP_BOTH); - reg = snd_soc_read(codec, SSM2602_ROUT1V); - snd_soc_write(codec, SSM2602_ROUT1V, reg | ROUT1V_RLHP_BOTH); + snd_soc_update_bits(codec, SSM2602_LOUT1V, + LOUT1V_LRHP_BOTH, LOUT1V_LRHP_BOTH); + snd_soc_update_bits(codec, SSM2602_ROUT1V, + ROUT1V_RLHP_BOTH, ROUT1V_RLHP_BOTH); ret = snd_soc_add_controls(codec, ssm2602_snd_controls, ARRAY_SIZE(ssm2602_snd_controls)); @@ -544,7 +580,7 @@ static int ssm2604_probe(struct snd_soc_codec *codec) static int ssm260x_probe(struct snd_soc_codec *codec) { struct ssm2602_priv *ssm2602 = snd_soc_codec_get_drvdata(codec); - int ret, reg; + int ret; pr_info("ssm2602 Audio Codec %s", SSM2602_VERSION); @@ -561,10 +597,10 @@ static int ssm260x_probe(struct snd_soc_codec *codec) } /* set the update bits */ - reg = snd_soc_read(codec, SSM2602_LINVOL); - snd_soc_write(codec, SSM2602_LINVOL, reg | LINVOL_LRIN_BOTH); - reg = snd_soc_read(codec, SSM2602_RINVOL); - snd_soc_write(codec, SSM2602_RINVOL, reg | RINVOL_RLIN_BOTH); + snd_soc_update_bits(codec, SSM2602_LINVOL, + LINVOL_LRIN_BOTH, LINVOL_LRIN_BOTH); + snd_soc_update_bits(codec, SSM2602_RINVOL, + RINVOL_RLIN_BOTH, RINVOL_RLIN_BOTH); /*select Line in as default input*/ snd_soc_write(codec, SSM2602_APANA, APANA_SELECT_DAC | APANA_ENABLE_MIC_BOOST); @@ -578,7 +614,12 @@ static int ssm260x_probe(struct snd_soc_codec *codec) break; } - return ret; + if (ret) + return ret; + + ssm2602_set_bias_level(codec, SND_SOC_BIAS_STANDBY); + + return 0; } /* remove everything here */ diff --git a/sound/soc/codecs/ssm2602.h b/sound/soc/codecs/ssm2602.h index b98c6916803..fbd07d7b73c 100644 --- a/sound/soc/codecs/ssm2602.h +++ b/sound/soc/codecs/ssm2602.h @@ -116,6 +116,10 @@ #define SSM2602_CACHEREGNUM 10 -#define SSM2602_SYSCLK 0 +enum ssm2602_clk { + SSM2602_SYSCLK, + SSM2602_CLK_CLKOUT, + SSM2602_CLK_XTO +}; #endif diff --git a/sound/soc/codecs/sta32x.c b/sound/soc/codecs/sta32x.c index fbd7eb9e61c..bb82408ab8e 100644 --- a/sound/soc/codecs/sta32x.c +++ b/sound/soc/codecs/sta32x.c @@ -524,13 +524,17 @@ static int sta32x_hw_params(struct snd_pcm_substream *substream, rate = params_rate(params); pr_debug("rate: %u\n", rate); for (i = 0; i < ARRAY_SIZE(interpolation_ratios); i++) - if (interpolation_ratios[i].fs == rate) + if (interpolation_ratios[i].fs == rate) { ir = interpolation_ratios[i].ir; + break; + } if (ir < 0) return -EINVAL; for (i = 0; mclk_ratios[ir][i].ratio; i++) - if (mclk_ratios[ir][i].ratio * rate == sta32x->mclk) + if (mclk_ratios[ir][i].ratio * rate == sta32x->mclk) { mcs = mclk_ratios[ir][i].mcs; + break; + } if (mcs < 0) return -EINVAL; @@ -752,25 +756,19 @@ static int sta32x_probe(struct snd_soc_codec *codec) return ret; } - /* read reg reset values into cache */ - for (i = 0; i < STA32X_REGISTER_COUNT; i++) - snd_soc_cache_write(codec, i, sta32x_regs[i]); - - /* preserve reset values of reserved register bits */ - snd_soc_cache_write(codec, STA32X_CONFC, - codec->hw_read(codec, STA32X_CONFC)); - snd_soc_cache_write(codec, STA32X_CONFE, - codec->hw_read(codec, STA32X_CONFE)); - snd_soc_cache_write(codec, STA32X_CONFF, - codec->hw_read(codec, STA32X_CONFF)); - snd_soc_cache_write(codec, STA32X_MMUTE, - codec->hw_read(codec, STA32X_MMUTE)); - snd_soc_cache_write(codec, STA32X_AUTO1, - codec->hw_read(codec, STA32X_AUTO1)); - snd_soc_cache_write(codec, STA32X_AUTO3, - codec->hw_read(codec, STA32X_AUTO3)); - snd_soc_cache_write(codec, STA32X_C3CFG, - codec->hw_read(codec, STA32X_C3CFG)); + /* Chip documentation explicitly requires that the reset values + * of reserved register bits are left untouched. + * Write the register default value to cache for reserved registers, + * so the write to the these registers are suppressed by the cache + * restore code when it skips writes of default registers. + */ + snd_soc_cache_write(codec, STA32X_CONFC, 0xc2); + snd_soc_cache_write(codec, STA32X_CONFE, 0xc2); + snd_soc_cache_write(codec, STA32X_CONFF, 0x5c); + snd_soc_cache_write(codec, STA32X_MMUTE, 0x10); + snd_soc_cache_write(codec, STA32X_AUTO1, 0x60); + snd_soc_cache_write(codec, STA32X_AUTO3, 0x00); + snd_soc_cache_write(codec, STA32X_C3CFG, 0x40); /* FIXME enable thermal warning adjustment and recovery */ snd_soc_update_bits(codec, STA32X_CONFA, @@ -808,6 +806,7 @@ static int sta32x_remove(struct snd_soc_codec *codec) { struct sta32x_priv *sta32x = snd_soc_codec_get_drvdata(codec); + sta32x_set_bias_level(codec, SND_SOC_BIAS_OFF); regulator_bulk_disable(ARRAY_SIZE(sta32x->supplies), sta32x->supplies); regulator_bulk_free(ARRAY_SIZE(sta32x->supplies), sta32x->supplies); @@ -832,6 +831,7 @@ static const struct snd_soc_codec_driver sta32x_codec = { .resume = sta32x_resume, .reg_cache_size = STA32X_REGISTER_COUNT, .reg_word_size = sizeof(u8), + .reg_cache_default = sta32x_regs, .volatile_register = sta32x_reg_is_volatile, .set_bias_level = sta32x_set_bias_level, .controls = sta32x_snd_controls, @@ -867,18 +867,8 @@ static __devinit int sta32x_i2c_probe(struct i2c_client *i2c, static __devexit int sta32x_i2c_remove(struct i2c_client *client) { struct sta32x_priv *sta32x = i2c_get_clientdata(client); - struct snd_soc_codec *codec = sta32x->codec; - - if (codec) - sta32x_set_bias_level(codec, SND_SOC_BIAS_OFF); - - regulator_bulk_free(ARRAY_SIZE(sta32x->supplies), sta32x->supplies); - - if (codec) { - snd_soc_unregister_codec(&client->dev); - snd_soc_codec_set_drvdata(codec, NULL); - } + snd_soc_unregister_codec(&client->dev); kfree(sta32x); return 0; } diff --git a/sound/soc/codecs/tlv320aic23.c b/sound/soc/codecs/tlv320aic23.c index 33bb52f3f68..336de8f69a0 100644 --- a/sound/soc/codecs/tlv320aic23.c +++ b/sound/soc/codecs/tlv320aic23.c @@ -47,63 +47,6 @@ static const u16 tlv320aic23_reg[] = { 0x0000, 0x0000, 0x0000, 0x0000, /* 12 */ }; -/* - * read tlv320aic23 register cache - */ -static inline unsigned int tlv320aic23_read_reg_cache(struct snd_soc_codec - *codec, unsigned int reg) -{ - u16 *cache = codec->reg_cache; - if (reg >= ARRAY_SIZE(tlv320aic23_reg)) - return -1; - return cache[reg]; -} - -/* - * write tlv320aic23 register cache - */ -static inline void tlv320aic23_write_reg_cache(struct snd_soc_codec *codec, - u8 reg, u16 value) -{ - u16 *cache = codec->reg_cache; - if (reg >= ARRAY_SIZE(tlv320aic23_reg)) - return; - cache[reg] = value; -} - -/* - * write to the tlv320aic23 register space - */ -static int tlv320aic23_write(struct snd_soc_codec *codec, unsigned int reg, - unsigned int value) -{ - - u8 data[2]; - - /* TLV320AIC23 has 7 bit address and 9 bits of data - * so we need to switch one data bit into reg and rest - * of data into val - */ - - if (reg > 9 && reg != 15) { - printk(KERN_WARNING "%s Invalid register R%u\n", __func__, reg); - return -1; - } - - data[0] = (reg << 1) | (value >> 8 & 0x01); - data[1] = value & 0xff; - - tlv320aic23_write_reg_cache(codec, reg, value); - - if (codec->hw_write(codec->control_data, data, 2) == 2) - return 0; - - printk(KERN_ERR "%s cannot write %03x to register R%u\n", __func__, - value, reg); - - return -EIO; -} - static const char *rec_src_text[] = { "Line", "Mic" }; static const char *deemph_text[] = {"None", "32Khz", "44.1Khz", "48Khz"}; @@ -139,8 +82,8 @@ static int snd_soc_tlv320aic23_put_volsw(struct snd_kcontrol *kcontrol, */ val = (val >= 4) ? 4 : (3 - val); - reg = tlv320aic23_read_reg_cache(codec, TLV320AIC23_ANLG) & (~0x1C0); - tlv320aic23_write(codec, TLV320AIC23_ANLG, reg | (val << 6)); + reg = snd_soc_read(codec, TLV320AIC23_ANLG) & (~0x1C0); + snd_soc_write(codec, TLV320AIC23_ANLG, reg | (val << 6)); return 0; } @@ -151,7 +94,7 @@ static int snd_soc_tlv320aic23_get_volsw(struct snd_kcontrol *kcontrol, struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); u16 val; - val = tlv320aic23_read_reg_cache(codec, TLV320AIC23_ANLG) & (0x1C0); + val = snd_soc_read(codec, TLV320AIC23_ANLG) & (0x1C0); val = val >> 6; val = (val >= 4) ? 4 : (3 - val); ucontrol->value.integer.value[0] = val; @@ -159,15 +102,6 @@ static int snd_soc_tlv320aic23_get_volsw(struct snd_kcontrol *kcontrol, } -#define SOC_TLV320AIC23_SINGLE_TLV(xname, reg, shift, max, invert, tlv_array) \ -{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \ - .access = SNDRV_CTL_ELEM_ACCESS_TLV_READ |\ - SNDRV_CTL_ELEM_ACCESS_READWRITE,\ - .tlv.p = (tlv_array), \ - .info = snd_soc_info_volsw, .get = snd_soc_tlv320aic23_get_volsw,\ - .put = snd_soc_tlv320aic23_put_volsw, \ - .private_value = SOC_SINGLE_VALUE(reg, shift, max, invert) } - static const struct snd_kcontrol_new tlv320aic23_snd_controls[] = { SOC_DOUBLE_R_TLV("Digital Playback Volume", TLV320AIC23_LCHNVOL, TLV320AIC23_RCHNVOL, 0, 127, 0, out_gain_tlv), @@ -178,8 +112,9 @@ static const struct snd_kcontrol_new tlv320aic23_snd_controls[] = { TLV320AIC23_RINVOL, 0, 31, 0, input_gain_tlv), SOC_SINGLE("Mic Input Switch", TLV320AIC23_ANLG, 1, 1, 1), SOC_SINGLE("Mic Booster Switch", TLV320AIC23_ANLG, 0, 1, 0), - SOC_TLV320AIC23_SINGLE_TLV("Sidetone Volume", TLV320AIC23_ANLG, - 6, 4, 0, sidetone_vol_tlv), + SOC_SINGLE_EXT_TLV("Sidetone Volume", TLV320AIC23_ANLG, 6, 4, 0, + snd_soc_tlv320aic23_get_volsw, + snd_soc_tlv320aic23_put_volsw, sidetone_vol_tlv), SOC_ENUM("Playback De-emphasis", tlv320aic23_deemph), }; @@ -240,7 +175,6 @@ static const struct snd_soc_dapm_route tlv320aic23_intercon[] = { /* AIC23 driver data */ struct aic23 { enum snd_soc_control_type control_type; - void *control_data; int mclk; int requested_adc; int requested_dac; @@ -352,7 +286,7 @@ static int find_rate(int mclk, u32 need_adc, u32 need_dac) static void get_current_sample_rates(struct snd_soc_codec *codec, int mclk, u32 *sample_rate_adc, u32 *sample_rate_dac) { - int src = tlv320aic23_read_reg_cache(codec, TLV320AIC23_SRATE); + int src = snd_soc_read(codec, TLV320AIC23_SRATE); int sr = (src >> 2) & 0x0f; int val = (mclk / bosr_usb_divisor_table[src & 3]); int adc = (val * sr_adc_mult_table[sr]) / SR_MULT; @@ -376,7 +310,7 @@ static int set_sample_rate_control(struct snd_soc_codec *codec, int mclk, __func__, sample_rate_adc, sample_rate_dac); return -EINVAL; } - tlv320aic23_write(codec, TLV320AIC23_SRATE, data); + snd_soc_write(codec, TLV320AIC23_SRATE, data); #ifdef DEBUG { u32 adc, dac; @@ -415,9 +349,8 @@ static int tlv320aic23_hw_params(struct snd_pcm_substream *substream, if (ret < 0) return ret; - iface_reg = - tlv320aic23_read_reg_cache(codec, - TLV320AIC23_DIGT_FMT) & ~(0x03 << 2); + iface_reg = snd_soc_read(codec, TLV320AIC23_DIGT_FMT) & ~(0x03 << 2); + switch (params_format(params)) { case SNDRV_PCM_FORMAT_S16_LE: break; @@ -431,7 +364,7 @@ static int tlv320aic23_hw_params(struct snd_pcm_substream *substream, iface_reg |= (0x03 << 2); break; } - tlv320aic23_write(codec, TLV320AIC23_DIGT_FMT, iface_reg); + snd_soc_write(codec, TLV320AIC23_DIGT_FMT, iface_reg); return 0; } @@ -443,7 +376,7 @@ static int tlv320aic23_pcm_prepare(struct snd_pcm_substream *substream, struct snd_soc_codec *codec = rtd->codec; /* set active */ - tlv320aic23_write(codec, TLV320AIC23_ACTIVE, 0x0001); + snd_soc_write(codec, TLV320AIC23_ACTIVE, 0x0001); return 0; } @@ -458,7 +391,7 @@ static void tlv320aic23_shutdown(struct snd_pcm_substream *substream, /* deactivate */ if (!codec->active) { udelay(50); - tlv320aic23_write(codec, TLV320AIC23_ACTIVE, 0x0); + snd_soc_write(codec, TLV320AIC23_ACTIVE, 0x0); } if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) aic23->requested_dac = 0; @@ -471,14 +404,14 @@ static int tlv320aic23_mute(struct snd_soc_dai *dai, int mute) struct snd_soc_codec *codec = dai->codec; u16 reg; - reg = tlv320aic23_read_reg_cache(codec, TLV320AIC23_DIGT); + reg = snd_soc_read(codec, TLV320AIC23_DIGT); if (mute) reg |= TLV320AIC23_DACM_MUTE; else reg &= ~TLV320AIC23_DACM_MUTE; - tlv320aic23_write(codec, TLV320AIC23_DIGT, reg); + snd_soc_write(codec, TLV320AIC23_DIGT, reg); return 0; } @@ -489,8 +422,7 @@ static int tlv320aic23_set_dai_fmt(struct snd_soc_dai *codec_dai, struct snd_soc_codec *codec = codec_dai->codec; u16 iface_reg; - iface_reg = - tlv320aic23_read_reg_cache(codec, TLV320AIC23_DIGT_FMT) & (~0x03); + iface_reg = snd_soc_read(codec, TLV320AIC23_DIGT_FMT) & (~0x03); /* set master/slave audio interface */ switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { @@ -498,6 +430,7 @@ static int tlv320aic23_set_dai_fmt(struct snd_soc_dai *codec_dai, iface_reg |= TLV320AIC23_MS_MASTER; break; case SND_SOC_DAIFMT_CBS_CFS: + iface_reg &= ~TLV320AIC23_MS_MASTER; break; default: return -EINVAL; @@ -524,7 +457,7 @@ static int tlv320aic23_set_dai_fmt(struct snd_soc_dai *codec_dai, } - tlv320aic23_write(codec, TLV320AIC23_DIGT_FMT, iface_reg); + snd_soc_write(codec, TLV320AIC23_DIGT_FMT, iface_reg); return 0; } @@ -540,26 +473,26 @@ static int tlv320aic23_set_dai_sysclk(struct snd_soc_dai *codec_dai, static int tlv320aic23_set_bias_level(struct snd_soc_codec *codec, enum snd_soc_bias_level level) { - u16 reg = tlv320aic23_read_reg_cache(codec, TLV320AIC23_PWR) & 0xff7f; + u16 reg = snd_soc_read(codec, TLV320AIC23_PWR) & 0xff7f; switch (level) { case SND_SOC_BIAS_ON: /* vref/mid, osc on, dac unmute */ reg &= ~(TLV320AIC23_DEVICE_PWR_OFF | TLV320AIC23_OSC_OFF | \ TLV320AIC23_DAC_OFF); - tlv320aic23_write(codec, TLV320AIC23_PWR, reg); + snd_soc_write(codec, TLV320AIC23_PWR, reg); break; case SND_SOC_BIAS_PREPARE: break; case SND_SOC_BIAS_STANDBY: /* everything off except vref/vmid, */ - tlv320aic23_write(codec, TLV320AIC23_PWR, reg | \ - TLV320AIC23_CLK_OFF); + snd_soc_write(codec, TLV320AIC23_PWR, + reg | TLV320AIC23_CLK_OFF); break; case SND_SOC_BIAS_OFF: /* everything off, dac mute, inactive */ - tlv320aic23_write(codec, TLV320AIC23_ACTIVE, 0x0); - tlv320aic23_write(codec, TLV320AIC23_PWR, 0xffff); + snd_soc_write(codec, TLV320AIC23_ACTIVE, 0x0); + snd_soc_write(codec, TLV320AIC23_PWR, 0xffff); break; } codec->dapm.bias_level = level; @@ -606,13 +539,7 @@ static int tlv320aic23_suspend(struct snd_soc_codec *codec, static int tlv320aic23_resume(struct snd_soc_codec *codec) { - u16 reg; - - /* Sync reg_cache with the hardware */ - for (reg = 0; reg <= TLV320AIC23_ACTIVE; reg++) { - u16 val = tlv320aic23_read_reg_cache(codec, reg); - tlv320aic23_write(codec, reg, val); - } + snd_soc_cache_sync(codec); tlv320aic23_set_bias_level(codec, SND_SOC_BIAS_STANDBY); return 0; @@ -621,46 +548,52 @@ static int tlv320aic23_resume(struct snd_soc_codec *codec) static int tlv320aic23_probe(struct snd_soc_codec *codec) { struct aic23 *aic23 = snd_soc_codec_get_drvdata(codec); - int reg; + int ret; printk(KERN_INFO "AIC23 Audio Codec %s\n", AIC23_VERSION); - codec->control_data = aic23->control_data; - codec->hw_write = (hw_write_t)i2c_master_send; - codec->hw_read = NULL; + + ret = snd_soc_codec_set_cache_io(codec, 7, 9, aic23->control_type); + if (ret < 0) { + dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret); + return ret; + } /* Reset codec */ - tlv320aic23_write(codec, TLV320AIC23_RESET, 0); + snd_soc_write(codec, TLV320AIC23_RESET, 0); + + /* Write the register default value to cache for reserved registers, + * so the write to the these registers are suppressed by the cache + * restore code when it skips writes of default registers. + */ + snd_soc_cache_write(codec, 0x0A, 0); + snd_soc_cache_write(codec, 0x0B, 0); + snd_soc_cache_write(codec, 0x0C, 0); + snd_soc_cache_write(codec, 0x0D, 0); + snd_soc_cache_write(codec, 0x0E, 0); /* power on device */ tlv320aic23_set_bias_level(codec, SND_SOC_BIAS_STANDBY); - tlv320aic23_write(codec, TLV320AIC23_DIGT, TLV320AIC23_DEEMP_44K); + snd_soc_write(codec, TLV320AIC23_DIGT, TLV320AIC23_DEEMP_44K); /* Unmute input */ - reg = tlv320aic23_read_reg_cache(codec, TLV320AIC23_LINVOL); - tlv320aic23_write(codec, TLV320AIC23_LINVOL, - (reg & (~TLV320AIC23_LIM_MUTED)) | - (TLV320AIC23_LRS_ENABLED)); + snd_soc_update_bits(codec, TLV320AIC23_LINVOL, + TLV320AIC23_LIM_MUTED, TLV320AIC23_LRS_ENABLED); - reg = tlv320aic23_read_reg_cache(codec, TLV320AIC23_RINVOL); - tlv320aic23_write(codec, TLV320AIC23_RINVOL, - (reg & (~TLV320AIC23_LIM_MUTED)) | - TLV320AIC23_LRS_ENABLED); + snd_soc_update_bits(codec, TLV320AIC23_RINVOL, + TLV320AIC23_LIM_MUTED, TLV320AIC23_LRS_ENABLED); - reg = tlv320aic23_read_reg_cache(codec, TLV320AIC23_ANLG); - tlv320aic23_write(codec, TLV320AIC23_ANLG, - (reg) & (~TLV320AIC23_BYPASS_ON) & - (~TLV320AIC23_MICM_MUTED)); + snd_soc_update_bits(codec, TLV320AIC23_ANLG, + TLV320AIC23_BYPASS_ON | TLV320AIC23_MICM_MUTED, + 0); /* Default output volume */ - tlv320aic23_write(codec, TLV320AIC23_LCHNVOL, - TLV320AIC23_DEFAULT_OUT_VOL & - TLV320AIC23_OUT_VOL_MASK); - tlv320aic23_write(codec, TLV320AIC23_RCHNVOL, - TLV320AIC23_DEFAULT_OUT_VOL & - TLV320AIC23_OUT_VOL_MASK); + snd_soc_write(codec, TLV320AIC23_LCHNVOL, + TLV320AIC23_DEFAULT_OUT_VOL & TLV320AIC23_OUT_VOL_MASK); + snd_soc_write(codec, TLV320AIC23_RCHNVOL, + TLV320AIC23_DEFAULT_OUT_VOL & TLV320AIC23_OUT_VOL_MASK); - tlv320aic23_write(codec, TLV320AIC23_ACTIVE, 0x1); + snd_soc_write(codec, TLV320AIC23_ACTIVE, 0x1); snd_soc_add_controls(codec, tlv320aic23_snd_controls, ARRAY_SIZE(tlv320aic23_snd_controls)); @@ -682,8 +615,6 @@ static struct snd_soc_codec_driver soc_codec_dev_tlv320aic23 = { .remove = tlv320aic23_remove, .suspend = tlv320aic23_suspend, .resume = tlv320aic23_resume, - .read = tlv320aic23_read_reg_cache, - .write = tlv320aic23_write, .set_bias_level = tlv320aic23_set_bias_level, .dapm_widgets = tlv320aic23_dapm_widgets, .num_dapm_widgets = ARRAY_SIZE(tlv320aic23_dapm_widgets), @@ -710,7 +641,6 @@ static int tlv320aic23_codec_probe(struct i2c_client *i2c, return -ENOMEM; i2c_set_clientdata(i2c, aic23); - aic23->control_data = i2c; aic23->control_type = SND_SOC_I2C; ret = snd_soc_register_codec(&i2c->dev, diff --git a/sound/soc/codecs/tlv320aic32x4.c b/sound/soc/codecs/tlv320aic32x4.c index e93b9d1ae1d..b21c610051c 100644 --- a/sound/soc/codecs/tlv320aic32x4.c +++ b/sound/soc/codecs/tlv320aic32x4.c @@ -528,40 +528,33 @@ static int aic32x4_set_bias_level(struct snd_soc_codec *codec, enum snd_soc_bias_level level) { struct aic32x4_priv *aic32x4 = snd_soc_codec_get_drvdata(codec); - u8 value; switch (level) { case SND_SOC_BIAS_ON: if (aic32x4->master) { /* Switch on PLL */ - value = snd_soc_read(codec, AIC32X4_PLLPR); - snd_soc_write(codec, AIC32X4_PLLPR, - (value | AIC32X4_PLLEN)); + snd_soc_update_bits(codec, AIC32X4_PLLPR, + AIC32X4_PLLEN, AIC32X4_PLLEN); /* Switch on NDAC Divider */ - value = snd_soc_read(codec, AIC32X4_NDAC); - snd_soc_write(codec, AIC32X4_NDAC, - value | AIC32X4_NDACEN); + snd_soc_update_bits(codec, AIC32X4_NDAC, + AIC32X4_NDACEN, AIC32X4_NDACEN); /* Switch on MDAC Divider */ - value = snd_soc_read(codec, AIC32X4_MDAC); - snd_soc_write(codec, AIC32X4_MDAC, - value | AIC32X4_MDACEN); + snd_soc_update_bits(codec, AIC32X4_MDAC, + AIC32X4_MDACEN, AIC32X4_MDACEN); /* Switch on NADC Divider */ - value = snd_soc_read(codec, AIC32X4_NADC); - snd_soc_write(codec, AIC32X4_NADC, - value | AIC32X4_MDACEN); + snd_soc_update_bits(codec, AIC32X4_NADC, + AIC32X4_NADCEN, AIC32X4_NADCEN); /* Switch on MADC Divider */ - value = snd_soc_read(codec, AIC32X4_MADC); - snd_soc_write(codec, AIC32X4_MADC, - value | AIC32X4_MDACEN); + snd_soc_update_bits(codec, AIC32X4_MADC, + AIC32X4_MADCEN, AIC32X4_MADCEN); /* Switch on BCLK_N Divider */ - value = snd_soc_read(codec, AIC32X4_BCLKN); - snd_soc_write(codec, AIC32X4_BCLKN, - value | AIC32X4_BCLKEN); + snd_soc_update_bits(codec, AIC32X4_BCLKN, + AIC32X4_BCLKEN, AIC32X4_BCLKEN); } break; case SND_SOC_BIAS_PREPARE: @@ -569,34 +562,28 @@ static int aic32x4_set_bias_level(struct snd_soc_codec *codec, case SND_SOC_BIAS_STANDBY: if (aic32x4->master) { /* Switch off PLL */ - value = snd_soc_read(codec, AIC32X4_PLLPR); - snd_soc_write(codec, AIC32X4_PLLPR, - (value & ~AIC32X4_PLLEN)); + snd_soc_update_bits(codec, AIC32X4_PLLPR, + AIC32X4_PLLEN, 0); /* Switch off NDAC Divider */ - value = snd_soc_read(codec, AIC32X4_NDAC); - snd_soc_write(codec, AIC32X4_NDAC, - value & ~AIC32X4_NDACEN); + snd_soc_update_bits(codec, AIC32X4_NDAC, + AIC32X4_NDACEN, 0); /* Switch off MDAC Divider */ - value = snd_soc_read(codec, AIC32X4_MDAC); - snd_soc_write(codec, AIC32X4_MDAC, - value & ~AIC32X4_MDACEN); + snd_soc_update_bits(codec, AIC32X4_MDAC, + AIC32X4_MDACEN, 0); /* Switch off NADC Divider */ - value = snd_soc_read(codec, AIC32X4_NADC); - snd_soc_write(codec, AIC32X4_NADC, - value & ~AIC32X4_NDACEN); + snd_soc_update_bits(codec, AIC32X4_NADC, + AIC32X4_NADCEN, 0); /* Switch off MADC Divider */ - value = snd_soc_read(codec, AIC32X4_MADC); - snd_soc_write(codec, AIC32X4_MADC, - value & ~AIC32X4_MDACEN); - value = snd_soc_read(codec, AIC32X4_BCLKN); + snd_soc_update_bits(codec, AIC32X4_MADC, + AIC32X4_MADCEN, 0); /* Switch off BCLK_N Divider */ - snd_soc_write(codec, AIC32X4_BCLKN, - value & ~AIC32X4_BCLKEN); + snd_soc_update_bits(codec, AIC32X4_BCLKN, + AIC32X4_BCLKEN, 0); } break; case SND_SOC_BIAS_OFF: @@ -685,10 +672,10 @@ static int aic32x4_probe(struct snd_soc_codec *codec) } /* Mic PGA routing */ - if (aic32x4->micpga_routing | AIC32X4_MICPGA_ROUTE_LMIC_IN2R_10K) { + if (aic32x4->micpga_routing & AIC32X4_MICPGA_ROUTE_LMIC_IN2R_10K) { snd_soc_write(codec, AIC32X4_LMICPGANIN, AIC32X4_LMICPGANIN_IN2R_10K); } - if (aic32x4->micpga_routing | AIC32X4_MICPGA_ROUTE_RMIC_IN1L_10K) { + if (aic32x4->micpga_routing & AIC32X4_MICPGA_ROUTE_RMIC_IN1L_10K) { snd_soc_write(codec, AIC32X4_RMICPGANIN, AIC32X4_RMICPGANIN_IN1L_10K); } diff --git a/sound/soc/codecs/tlv320aic3x.c b/sound/soc/codecs/tlv320aic3x.c index 0963c4c7a83..87d5ef188e2 100644 --- a/sound/soc/codecs/tlv320aic3x.c +++ b/sound/soc/codecs/tlv320aic3x.c @@ -76,7 +76,6 @@ struct aic3x_priv { struct aic3x_disable_nb disable_nb[AIC3X_NUM_SUPPLIES]; enum snd_soc_control_type control_type; struct aic3x_setup_data *setup; - void *control_data; unsigned int sysclk; struct list_head list; int master; @@ -138,7 +137,10 @@ static int aic3x_read(struct snd_soc_codec *codec, unsigned int reg, if (reg >= AIC3X_CACHEREGNUM) return -1; - *value = codec->hw_read(codec, reg); + codec->cache_bypass = 1; + *value = snd_soc_read(codec, reg); + codec->cache_bypass = 0; + cache[reg] = *value; return 0; @@ -198,6 +200,10 @@ static int snd_soc_dapm_put_volsw_aic3x(struct snd_kcontrol *kcontrol, else /* old connection must be powered down */ path->connect = invert ? 1 : 0; + + dapm_mark_dirty(path->source, "tlv320aic3x source"); + dapm_mark_dirty(path->sink, "tlv320aic3x sink"); + break; } @@ -1017,6 +1023,7 @@ static int aic3x_set_dai_fmt(struct snd_soc_dai *codec_dai, break; case SND_SOC_DAIFMT_CBS_CFS: aic3x->master = 0; + iface_areg &= ~(BIT_CLK_MASTER | WORD_CLK_MASTER); break; default: return -EINVAL; @@ -1383,7 +1390,6 @@ static int aic3x_probe(struct snd_soc_codec *codec) int ret, i; INIT_LIST_HEAD(&aic3x->list); - codec->control_data = aic3x->control_data; aic3x->codec = codec; codec->dapm.idle_bias_off = 1; @@ -1495,9 +1501,9 @@ static struct snd_soc_codec_driver soc_codec_dev_aic3x = { */ static const struct i2c_device_id aic3x_i2c_id[] = { - [AIC3X_MODEL_3X] = { "tlv320aic3x", 0 }, - [AIC3X_MODEL_33] = { "tlv320aic33", 0 }, - [AIC3X_MODEL_3007] = { "tlv320aic3007", 0 }, + { "tlv320aic3x", AIC3X_MODEL_3X }, + { "tlv320aic33", AIC3X_MODEL_33 }, + { "tlv320aic3007", AIC3X_MODEL_3007 }, { } }; MODULE_DEVICE_TABLE(i2c, aic3x_i2c_id); @@ -1512,7 +1518,6 @@ static int aic3x_i2c_probe(struct i2c_client *i2c, struct aic3x_pdata *pdata = i2c->dev.platform_data; struct aic3x_priv *aic3x; int ret; - const struct i2c_device_id *tbl; aic3x = kzalloc(sizeof(struct aic3x_priv), GFP_KERNEL); if (aic3x == NULL) { @@ -1520,7 +1525,6 @@ static int aic3x_i2c_probe(struct i2c_client *i2c, return -ENOMEM; } - aic3x->control_data = i2c; aic3x->control_type = SND_SOC_I2C; i2c_set_clientdata(i2c, aic3x); @@ -1531,11 +1535,7 @@ static int aic3x_i2c_probe(struct i2c_client *i2c, aic3x->gpio_reset = -1; } - for (tbl = aic3x_i2c_id; tbl->name[0]; tbl++) { - if (!strcmp(tbl->name, id->name)) - break; - } - aic3x->model = tbl - aic3x_i2c_id; + aic3x->model = id->driver_data; ret = snd_soc_register_codec(&i2c->dev, &soc_codec_dev_aic3x, &aic3x_dai, 1); diff --git a/sound/soc/codecs/tlv320dac33.c b/sound/soc/codecs/tlv320dac33.c index faa5e9fb147..dc8a2b2bdc1 100644 --- a/sound/soc/codecs/tlv320dac33.c +++ b/sound/soc/codecs/tlv320dac33.c @@ -55,13 +55,13 @@ #define BURST_BASEFREQ_HZ 49152000 #define SAMPLES_TO_US(rate, samples) \ - (1000000000 / ((rate * 1000) / samples)) + (1000000000 / (((rate) * 1000) / (samples))) #define US_TO_SAMPLES(rate, us) \ - (rate / (1000000 / (us < 1000000 ? us : 1000000))) + ((rate) / (1000000 / ((us) < 1000000 ? (us) : 1000000))) #define UTHR_FROM_PERIOD_SIZE(samples, playrate, burstrate) \ - ((samples * 5000) / ((burstrate * 5000) / (burstrate - playrate))) + (((samples)*5000) / (((burstrate)*5000) / ((burstrate) - (playrate)))) static void dac33_calculate_times(struct snd_pcm_substream *substream); static int dac33_prepare_chip(struct snd_pcm_substream *substream); @@ -627,18 +627,6 @@ static const struct snd_soc_dapm_route audio_map[] = { {"RIGHT_LO", NULL, "Codec Power"}, }; -static int dac33_add_widgets(struct snd_soc_codec *codec) -{ - struct snd_soc_dapm_context *dapm = &codec->dapm; - - snd_soc_dapm_new_controls(dapm, dac33_dapm_widgets, - ARRAY_SIZE(dac33_dapm_widgets)); - /* set up audio path interconnects */ - snd_soc_dapm_add_routes(dapm, audio_map, ARRAY_SIZE(audio_map)); - - return 0; -} - static int dac33_set_bias_level(struct snd_soc_codec *codec, enum snd_soc_bias_level level) { @@ -1431,7 +1419,7 @@ static int dac33_soc_probe(struct snd_soc_codec *codec) /* Check if the IRQ number is valid and request it */ if (dac33->irq >= 0) { ret = request_irq(dac33->irq, dac33_interrupt_handler, - IRQF_TRIGGER_RISING | IRQF_DISABLED, + IRQF_TRIGGER_RISING, codec->name, codec); if (ret < 0) { dev_err(codec->dev, "Could not request IRQ%d (%d)\n", @@ -1451,15 +1439,11 @@ static int dac33_soc_probe(struct snd_soc_codec *codec) } } - snd_soc_add_controls(codec, dac33_snd_controls, - ARRAY_SIZE(dac33_snd_controls)); /* Only add the FIFO controls, if we have valid IRQ number */ if (dac33->irq >= 0) snd_soc_add_controls(codec, dac33_mode_snd_controls, ARRAY_SIZE(dac33_mode_snd_controls)); - dac33_add_widgets(codec); - err_power: return ret; } @@ -1502,6 +1486,13 @@ static struct snd_soc_codec_driver soc_codec_dev_tlv320dac33 = { .remove = dac33_soc_remove, .suspend = dac33_soc_suspend, .resume = dac33_soc_resume, + + .controls = dac33_snd_controls, + .num_controls = ARRAY_SIZE(dac33_snd_controls), + .dapm_widgets = dac33_dapm_widgets, + .num_dapm_widgets = ARRAY_SIZE(dac33_dapm_widgets), + .dapm_routes = audio_map, + .num_dapm_routes = ARRAY_SIZE(audio_map), }; #define DAC33_RATES (SNDRV_PCM_RATE_44100 | \ diff --git a/sound/soc/codecs/tpa6130a2.c b/sound/soc/codecs/tpa6130a2.c index 239e0c46106..7eeca79d738 100644 --- a/sound/soc/codecs/tpa6130a2.c +++ b/sound/soc/codecs/tpa6130a2.c @@ -33,6 +33,11 @@ #include "tpa6130a2.h" +enum tpa_model { + TPA6130A2, + TPA6140A2, +}; + static struct i2c_client *tpa6130a2_client; /* This struct is used to save the context */ @@ -383,7 +388,7 @@ static int __devinit tpa6130a2_probe(struct i2c_client *client, pdata = client->dev.platform_data; data->power_gpio = pdata->power_gpio; - data->id = pdata->id; + data->id = id->driver_data; mutex_init(&data->mutex); @@ -405,7 +410,7 @@ static int __devinit tpa6130a2_probe(struct i2c_client *client, switch (data->id) { default: dev_warn(dev, "Unknown TPA model (%d). Assuming 6130A2\n", - pdata->id); + data->id); case TPA6130A2: regulator = "Vdd"; break; @@ -446,7 +451,6 @@ err_regulator: gpio_free(data->power_gpio); err_gpio: kfree(data); - i2c_set_clientdata(tpa6130a2_client, NULL); tpa6130a2_client = NULL; return ret; @@ -470,7 +474,8 @@ static int __devexit tpa6130a2_remove(struct i2c_client *client) } static const struct i2c_device_id tpa6130a2_id[] = { - { "tpa6130a2", 0 }, + { "tpa6130a2", TPA6130A2 }, + { "tpa6140a2", TPA6140A2 }, { } }; MODULE_DEVICE_TABLE(i2c, tpa6130a2_id); diff --git a/sound/soc/codecs/twl4030.c b/sound/soc/codecs/twl4030.c index 71674bec960..f798247ac1b 100644 --- a/sound/soc/codecs/twl4030.c +++ b/sound/soc/codecs/twl4030.c @@ -863,34 +863,6 @@ static int digimic_event(struct snd_soc_dapm_widget *w, * Inverting not going to help with these. * Custom volsw and volsw_2r get/put functions to handle these gain bits. */ -#define SOC_DOUBLE_TLV_TWL4030(xname, xreg, shift_left, shift_right, xmax,\ - xinvert, tlv_array) \ -{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = (xname),\ - .access = SNDRV_CTL_ELEM_ACCESS_TLV_READ |\ - SNDRV_CTL_ELEM_ACCESS_READWRITE,\ - .tlv.p = (tlv_array), \ - .info = snd_soc_info_volsw, \ - .get = snd_soc_get_volsw_twl4030, \ - .put = snd_soc_put_volsw_twl4030, \ - .private_value = (unsigned long)&(struct soc_mixer_control) \ - {.reg = xreg, .shift = shift_left, .rshift = shift_right,\ - .max = xmax, .invert = xinvert} } -#define SOC_DOUBLE_R_TLV_TWL4030(xname, reg_left, reg_right, xshift, xmax,\ - xinvert, tlv_array) \ -{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = (xname),\ - .access = SNDRV_CTL_ELEM_ACCESS_TLV_READ |\ - SNDRV_CTL_ELEM_ACCESS_READWRITE,\ - .tlv.p = (tlv_array), \ - .info = snd_soc_info_volsw_2r, \ - .get = snd_soc_get_volsw_r2_twl4030,\ - .put = snd_soc_put_volsw_r2_twl4030, \ - .private_value = (unsigned long)&(struct soc_mixer_control) \ - {.reg = reg_left, .rreg = reg_right, .shift = xshift, \ - .rshift = xshift, .max = xmax, .invert = xinvert} } -#define SOC_SINGLE_TLV_TWL4030(xname, xreg, xshift, xmax, xinvert, tlv_array) \ - SOC_DOUBLE_TLV_TWL4030(xname, xreg, xshift, xshift, xmax, \ - xinvert, tlv_array) - static int snd_soc_get_volsw_twl4030(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { @@ -1197,19 +1169,23 @@ static const struct snd_kcontrol_new twl4030_snd_controls[] = { TWL4030_REG_VDL_APGA_CTL, 1, 1, 0), /* Separate output gain controls */ - SOC_DOUBLE_R_TLV_TWL4030("PreDriv Playback Volume", + SOC_DOUBLE_R_EXT_TLV("PreDriv Playback Volume", TWL4030_REG_PREDL_CTL, TWL4030_REG_PREDR_CTL, - 4, 3, 0, output_tvl), + 4, 3, 0, snd_soc_get_volsw_r2_twl4030, + snd_soc_put_volsw_r2_twl4030, output_tvl), - SOC_DOUBLE_TLV_TWL4030("Headset Playback Volume", - TWL4030_REG_HS_GAIN_SET, 0, 2, 3, 0, output_tvl), + SOC_DOUBLE_EXT_TLV("Headset Playback Volume", + TWL4030_REG_HS_GAIN_SET, 0, 2, 3, 0, snd_soc_get_volsw_twl4030, + snd_soc_put_volsw_twl4030, output_tvl), - SOC_DOUBLE_R_TLV_TWL4030("Carkit Playback Volume", + SOC_DOUBLE_R_EXT_TLV("Carkit Playback Volume", TWL4030_REG_PRECKL_CTL, TWL4030_REG_PRECKR_CTL, - 4, 3, 0, output_tvl), + 4, 3, 0, snd_soc_get_volsw_r2_twl4030, + snd_soc_put_volsw_r2_twl4030, output_tvl), - SOC_SINGLE_TLV_TWL4030("Earpiece Playback Volume", - TWL4030_REG_EAR_CTL, 4, 3, 0, output_ear_tvl), + SOC_SINGLE_EXT_TLV("Earpiece Playback Volume", + TWL4030_REG_EAR_CTL, 4, 3, 0, snd_soc_get_volsw_twl4030, + snd_soc_put_volsw_twl4030, output_ear_tvl), /* Common capture gain controls */ SOC_DOUBLE_R_TLV("TX1 Digital Capture Volume", @@ -1633,17 +1609,6 @@ static const struct snd_soc_dapm_route intercon[] = { }; -static int twl4030_add_widgets(struct snd_soc_codec *codec) -{ - struct snd_soc_dapm_context *dapm = &codec->dapm; - - snd_soc_dapm_new_controls(dapm, twl4030_dapm_widgets, - ARRAY_SIZE(twl4030_dapm_widgets)); - snd_soc_dapm_add_routes(dapm, intercon, ARRAY_SIZE(intercon)); - - return 0; -} - static int twl4030_set_bias_level(struct snd_soc_codec *codec, enum snd_soc_bias_level level) { @@ -2265,9 +2230,6 @@ static int twl4030_soc_probe(struct snd_soc_codec *codec) twl4030_init_chip(codec); - snd_soc_add_controls(codec, twl4030_snd_controls, - ARRAY_SIZE(twl4030_snd_controls)); - twl4030_add_widgets(codec); return 0; } @@ -2293,6 +2255,13 @@ static struct snd_soc_codec_driver soc_codec_dev_twl4030 = { .reg_cache_size = sizeof(twl4030_reg), .reg_word_size = sizeof(u8), .reg_cache_default = twl4030_reg, + + .controls = twl4030_snd_controls, + .num_controls = ARRAY_SIZE(twl4030_snd_controls), + .dapm_widgets = twl4030_dapm_widgets, + .num_dapm_widgets = ARRAY_SIZE(twl4030_dapm_widgets), + .dapm_routes = intercon, + .num_dapm_routes = ARRAY_SIZE(intercon), }; static int __devinit twl4030_codec_probe(struct platform_device *pdev) diff --git a/sound/soc/codecs/twl6040.c b/sound/soc/codecs/twl6040.c index 443032b3b32..73e11f022de 100644 --- a/sound/soc/codecs/twl6040.c +++ b/sound/soc/codecs/twl6040.c @@ -57,6 +57,13 @@ #define TWL6040_HF_VOL_MASK 0x1F #define TWL6040_HF_VOL_SHIFT 0 +/* Shadow register used by the driver */ +#define TWL6040_REG_SW_SHADOW 0x2F +#define TWL6040_CACHEREGNUM (TWL6040_REG_SW_SHADOW + 1) + +/* TWL6040_REG_SW_SHADOW (0x2F) fields */ +#define TWL6040_EAR_PATH_ENABLE 0x01 + struct twl6040_output { u16 active; u16 left_vol; @@ -65,12 +72,13 @@ struct twl6040_output { u16 right_step; unsigned int step_delay; u16 ramp; - u16 mute; + struct delayed_work work; struct completion ramp_done; }; struct twl6040_jack_data { struct snd_soc_jack *jack; + struct delayed_work work; int report; }; @@ -79,7 +87,6 @@ struct twl6040_data { int plug_irq; int codec_powered; int pll; - int non_lp; int pll_power_mode; int hs_power_mode; int hs_power_mode_locked; @@ -92,104 +99,68 @@ struct twl6040_data { struct twl6040_jack_data hs_jack; struct snd_soc_codec *codec; struct workqueue_struct *workqueue; - struct delayed_work delayed_work; struct mutex mutex; struct twl6040_output headset; struct twl6040_output handsfree; - struct workqueue_struct *hf_workqueue; - struct workqueue_struct *hs_workqueue; - struct delayed_work hs_delayed_work; - struct delayed_work hf_delayed_work; }; /* * twl6040 register cache & default register settings */ static const u8 twl6040_reg[TWL6040_CACHEREGNUM] = { - 0x00, /* not used 0x00 */ - 0x4B, /* TWL6040_ASICID (ro) 0x01 */ - 0x00, /* TWL6040_ASICREV (ro) 0x02 */ - 0x00, /* TWL6040_INTID 0x03 */ - 0x00, /* TWL6040_INTMR 0x04 */ - 0x00, /* TWL6040_NCPCTRL 0x05 */ - 0x00, /* TWL6040_LDOCTL 0x06 */ - 0x60, /* TWL6040_HPPLLCTL 0x07 */ - 0x00, /* TWL6040_LPPLLCTL 0x08 */ - 0x4A, /* TWL6040_LPPLLDIV 0x09 */ - 0x00, /* TWL6040_AMICBCTL 0x0A */ - 0x00, /* TWL6040_DMICBCTL 0x0B */ - 0x18, /* TWL6040_MICLCTL 0x0C - No input selected on Left Mic */ - 0x18, /* TWL6040_MICRCTL 0x0D - No input selected on Right Mic */ - 0x00, /* TWL6040_MICGAIN 0x0E */ - 0x1B, /* TWL6040_LINEGAIN 0x0F */ - 0x00, /* TWL6040_HSLCTL 0x10 */ - 0x00, /* TWL6040_HSRCTL 0x11 */ - 0x00, /* TWL6040_HSGAIN 0x12 */ - 0x00, /* TWL6040_EARCTL 0x13 */ - 0x00, /* TWL6040_HFLCTL 0x14 */ - 0x00, /* TWL6040_HFLGAIN 0x15 */ - 0x00, /* TWL6040_HFRCTL 0x16 */ - 0x00, /* TWL6040_HFRGAIN 0x17 */ - 0x00, /* TWL6040_VIBCTLL 0x18 */ - 0x00, /* TWL6040_VIBDATL 0x19 */ - 0x00, /* TWL6040_VIBCTLR 0x1A */ - 0x00, /* TWL6040_VIBDATR 0x1B */ - 0x00, /* TWL6040_HKCTL1 0x1C */ - 0x00, /* TWL6040_HKCTL2 0x1D */ - 0x00, /* TWL6040_GPOCTL 0x1E */ - 0x00, /* TWL6040_ALB 0x1F */ - 0x00, /* TWL6040_DLB 0x20 */ - 0x00, /* not used 0x21 */ - 0x00, /* not used 0x22 */ - 0x00, /* not used 0x23 */ - 0x00, /* not used 0x24 */ - 0x00, /* not used 0x25 */ - 0x00, /* not used 0x26 */ - 0x00, /* not used 0x27 */ - 0x00, /* TWL6040_TRIM1 0x28 */ - 0x00, /* TWL6040_TRIM2 0x29 */ - 0x00, /* TWL6040_TRIM3 0x2A */ - 0x00, /* TWL6040_HSOTRIM 0x2B */ - 0x00, /* TWL6040_HFOTRIM 0x2C */ - 0x09, /* TWL6040_ACCCTL 0x2D */ - 0x00, /* TWL6040_STATUS (ro) 0x2E */ -}; - -/* - * twl6040 vio/gnd registers: - * registers under vio/gnd supply can be accessed - * before the power-up sequence, after NRESPWRON goes high - */ -static const int twl6040_vio_reg[TWL6040_VIOREGNUM] = { - TWL6040_REG_ASICID, - TWL6040_REG_ASICREV, - TWL6040_REG_INTID, - TWL6040_REG_INTMR, - TWL6040_REG_NCPCTL, - TWL6040_REG_LDOCTL, - TWL6040_REG_AMICBCTL, - TWL6040_REG_DMICBCTL, - TWL6040_REG_HKCTL1, - TWL6040_REG_HKCTL2, - TWL6040_REG_GPOCTL, - TWL6040_REG_TRIM1, - TWL6040_REG_TRIM2, - TWL6040_REG_TRIM3, - TWL6040_REG_HSOTRIM, - TWL6040_REG_HFOTRIM, - TWL6040_REG_ACCCTL, - TWL6040_REG_STATUS, + 0x00, /* not used 0x00 */ + 0x4B, /* REG_ASICID 0x01 (ro) */ + 0x00, /* REG_ASICREV 0x02 (ro) */ + 0x00, /* REG_INTID 0x03 */ + 0x00, /* REG_INTMR 0x04 */ + 0x00, /* REG_NCPCTRL 0x05 */ + 0x00, /* REG_LDOCTL 0x06 */ + 0x60, /* REG_HPPLLCTL 0x07 */ + 0x00, /* REG_LPPLLCTL 0x08 */ + 0x4A, /* REG_LPPLLDIV 0x09 */ + 0x00, /* REG_AMICBCTL 0x0A */ + 0x00, /* REG_DMICBCTL 0x0B */ + 0x00, /* REG_MICLCTL 0x0C */ + 0x00, /* REG_MICRCTL 0x0D */ + 0x00, /* REG_MICGAIN 0x0E */ + 0x1B, /* REG_LINEGAIN 0x0F */ + 0x00, /* REG_HSLCTL 0x10 */ + 0x00, /* REG_HSRCTL 0x11 */ + 0x00, /* REG_HSGAIN 0x12 */ + 0x00, /* REG_EARCTL 0x13 */ + 0x00, /* REG_HFLCTL 0x14 */ + 0x00, /* REG_HFLGAIN 0x15 */ + 0x00, /* REG_HFRCTL 0x16 */ + 0x00, /* REG_HFRGAIN 0x17 */ + 0x00, /* REG_VIBCTLL 0x18 */ + 0x00, /* REG_VIBDATL 0x19 */ + 0x00, /* REG_VIBCTLR 0x1A */ + 0x00, /* REG_VIBDATR 0x1B */ + 0x00, /* REG_HKCTL1 0x1C */ + 0x00, /* REG_HKCTL2 0x1D */ + 0x00, /* REG_GPOCTL 0x1E */ + 0x00, /* REG_ALB 0x1F */ + 0x00, /* REG_DLB 0x20 */ + 0x00, /* not used 0x21 */ + 0x00, /* not used 0x22 */ + 0x00, /* not used 0x23 */ + 0x00, /* not used 0x24 */ + 0x00, /* not used 0x25 */ + 0x00, /* not used 0x26 */ + 0x00, /* not used 0x27 */ + 0x00, /* REG_TRIM1 0x28 */ + 0x00, /* REG_TRIM2 0x29 */ + 0x00, /* REG_TRIM3 0x2A */ + 0x00, /* REG_HSOTRIM 0x2B */ + 0x00, /* REG_HFOTRIM 0x2C */ + 0x09, /* REG_ACCCTL 0x2D */ + 0x00, /* REG_STATUS 0x2E (ro) */ + + 0x00, /* REG_SW_SHADOW 0x2F - Shadow, non HW register */ }; -/* - * twl6040 vdd/vss registers: - * registers under vdd/vss supplies can only be accessed - * after the power-up sequence - */ -static const int twl6040_vdd_reg[TWL6040_VDDREGNUM] = { - TWL6040_REG_HPPLLCTL, - TWL6040_REG_LPPLLCTL, - TWL6040_REG_LPPLLDIV, +/* List of registers to be restored after power up */ +static const int twl6040_restore_list[] = { TWL6040_REG_MICLCTL, TWL6040_REG_MICRCTL, TWL6040_REG_MICGAIN, @@ -202,12 +173,6 @@ static const int twl6040_vdd_reg[TWL6040_VDDREGNUM] = { TWL6040_REG_HFLGAIN, TWL6040_REG_HFRCTL, TWL6040_REG_HFRGAIN, - TWL6040_REG_VIBCTLL, - TWL6040_REG_VIBDATL, - TWL6040_REG_VIBCTLR, - TWL6040_REG_VIBDATR, - TWL6040_REG_ALB, - TWL6040_REG_DLB, }; /* set of rates for each pll: low-power and high-performance */ @@ -275,8 +240,12 @@ static int twl6040_read_reg_volatile(struct snd_soc_codec *codec, if (reg >= TWL6040_CACHEREGNUM) return -EIO; - value = twl6040_reg_read(twl6040, reg); - twl6040_write_reg_cache(codec, reg, value); + if (likely(reg < TWL6040_REG_SW_SHADOW)) { + value = twl6040_reg_read(twl6040, reg); + twl6040_write_reg_cache(codec, reg, value); + } else { + value = twl6040_read_reg_cache(codec, reg); + } return value; } @@ -293,59 +262,51 @@ static int twl6040_write(struct snd_soc_codec *codec, return -EIO; twl6040_write_reg_cache(codec, reg, value); - return twl6040_reg_write(twl6040, reg, value); + if (likely(reg < TWL6040_REG_SW_SHADOW)) + return twl6040_reg_write(twl6040, reg, value); + else + return 0; } -static void twl6040_init_vio_regs(struct snd_soc_codec *codec) +static void twl6040_init_chip(struct snd_soc_codec *codec) { - u8 *cache = codec->reg_cache; - int reg, i; - - for (i = 0; i < TWL6040_VIOREGNUM; i++) { - reg = twl6040_vio_reg[i]; - /* - * skip read-only registers (ASICID, ASICREV, STATUS) - * and registers shared among MFD children - */ - switch (reg) { - case TWL6040_REG_ASICID: - case TWL6040_REG_ASICREV: - case TWL6040_REG_INTID: - case TWL6040_REG_INTMR: - case TWL6040_REG_NCPCTL: - case TWL6040_REG_LDOCTL: - case TWL6040_REG_GPOCTL: - case TWL6040_REG_ACCCTL: - case TWL6040_REG_STATUS: - continue; - default: - break; - } - twl6040_write(codec, reg, cache[reg]); - } + struct twl6040 *twl6040 = codec->control_data; + u8 val; + + /* Update reg_cache: ASICREV, and TRIM values */ + val = twl6040_get_revid(twl6040); + twl6040_write_reg_cache(codec, TWL6040_REG_ASICREV, val); + + twl6040_read_reg_volatile(codec, TWL6040_REG_TRIM1); + twl6040_read_reg_volatile(codec, TWL6040_REG_TRIM2); + twl6040_read_reg_volatile(codec, TWL6040_REG_TRIM3); + twl6040_read_reg_volatile(codec, TWL6040_REG_HSOTRIM); + twl6040_read_reg_volatile(codec, TWL6040_REG_HFOTRIM); + + /* Change chip defaults */ + /* No imput selected for microphone amplifiers */ + twl6040_write_reg_cache(codec, TWL6040_REG_MICLCTL, 0x18); + twl6040_write_reg_cache(codec, TWL6040_REG_MICRCTL, 0x18); + + /* + * We need to lower the default gain values, so the ramp code + * can work correctly for the first playback. + * This reduces the pop noise heard at the first playback. + */ + twl6040_write_reg_cache(codec, TWL6040_REG_HSGAIN, 0xff); + twl6040_write_reg_cache(codec, TWL6040_REG_EARCTL, 0x1e); + twl6040_write_reg_cache(codec, TWL6040_REG_HFLGAIN, 0x1d); + twl6040_write_reg_cache(codec, TWL6040_REG_HFRGAIN, 0x1d); + twl6040_write_reg_cache(codec, TWL6040_REG_LINEGAIN, 0); } -static void twl6040_init_vdd_regs(struct snd_soc_codec *codec) +static void twl6040_restore_regs(struct snd_soc_codec *codec) { u8 *cache = codec->reg_cache; int reg, i; - for (i = 0; i < TWL6040_VDDREGNUM; i++) { - reg = twl6040_vdd_reg[i]; - /* skip vibra and PLL registers */ - switch (reg) { - case TWL6040_REG_VIBCTLL: - case TWL6040_REG_VIBDATL: - case TWL6040_REG_VIBCTLR: - case TWL6040_REG_VIBDATR: - case TWL6040_REG_HPPLLCTL: - case TWL6040_REG_LPPLLCTL: - case TWL6040_REG_LPPLLDIV: - continue; - default: - break; - } - + for (i = 0; i < ARRAY_SIZE(twl6040_restore_list); i++) { + reg = twl6040_restore_list[i]; twl6040_write(codec, reg, cache[reg]); } } @@ -524,18 +485,17 @@ static inline int twl6040_hf_ramp_step(struct snd_soc_codec *codec, static void twl6040_pga_hs_work(struct work_struct *work) { struct twl6040_data *priv = - container_of(work, struct twl6040_data, hs_delayed_work.work); + container_of(work, struct twl6040_data, headset.work.work); struct snd_soc_codec *codec = priv->codec; struct twl6040_output *headset = &priv->headset; - unsigned int delay = headset->step_delay; int i, headset_complete; /* do we need to ramp at all ? */ if (headset->ramp == TWL6040_RAMP_NONE) return; - /* HS PGA volumes have 4 bits of resolution to ramp */ - for (i = 0; i <= 16; i++) { + /* HS PGA gain range: 0x0 - 0xf (0 - 15) */ + for (i = 0; i < 16; i++) { headset_complete = twl6040_hs_ramp_step(codec, headset->left_step, headset->right_step); @@ -544,15 +504,8 @@ static void twl6040_pga_hs_work(struct work_struct *work) if (headset_complete) break; - /* - * TODO: tune: delay is longer over 0dB - * as increases are larger. - */ - if (i >= 8) - schedule_timeout_interruptible(msecs_to_jiffies(delay + - (delay >> 1))); - else - schedule_timeout_interruptible(msecs_to_jiffies(delay)); + schedule_timeout_interruptible( + msecs_to_jiffies(headset->step_delay)); } if (headset->ramp == TWL6040_RAMP_DOWN) { @@ -567,18 +520,18 @@ static void twl6040_pga_hs_work(struct work_struct *work) static void twl6040_pga_hf_work(struct work_struct *work) { struct twl6040_data *priv = - container_of(work, struct twl6040_data, hf_delayed_work.work); + container_of(work, struct twl6040_data, handsfree.work.work); struct snd_soc_codec *codec = priv->codec; struct twl6040_output *handsfree = &priv->handsfree; - unsigned int delay = handsfree->step_delay; int i, handsfree_complete; /* do we need to ramp at all ? */ if (handsfree->ramp == TWL6040_RAMP_NONE) return; - /* HF PGA volumes have 5 bits of resolution to ramp */ - for (i = 0; i <= 32; i++) { + /* + * HF PGA gain range: 0x00 - 0x1d (0 - 29) */ + for (i = 0; i < 30; i++) { handsfree_complete = twl6040_hf_ramp_step(codec, handsfree->left_step, handsfree->right_step); @@ -587,15 +540,8 @@ static void twl6040_pga_hf_work(struct work_struct *work) if (handsfree_complete) break; - /* - * TODO: tune: delay is longer over 0dB - * as increases are larger. - */ - if (i >= 16) - schedule_timeout_interruptible(msecs_to_jiffies(delay + - (delay >> 1))); - else - schedule_timeout_interruptible(msecs_to_jiffies(delay)); + schedule_timeout_interruptible( + msecs_to_jiffies(handsfree->step_delay)); } @@ -607,36 +553,40 @@ static void twl6040_pga_hf_work(struct work_struct *work) handsfree->ramp = TWL6040_RAMP_NONE; } -static int pga_event(struct snd_soc_dapm_widget *w, +static int out_drv_event(struct snd_soc_dapm_widget *w, struct snd_kcontrol *kcontrol, int event) { struct snd_soc_codec *codec = w->codec; struct twl6040_data *priv = snd_soc_codec_get_drvdata(codec); struct twl6040_output *out; struct delayed_work *work; - struct workqueue_struct *queue; switch (w->shift) { - case 2: - case 3: + case 2: /* Headset output driver */ out = &priv->headset; - work = &priv->hs_delayed_work; - queue = priv->hs_workqueue; + work = &out->work; + /* + * Make sure, that we do not mess up variables for already + * executing work. + */ + cancel_delayed_work_sync(work); + out->left_step = priv->hs_left_step; out->right_step = priv->hs_right_step; out->step_delay = 5; /* 5 ms between volume ramp steps */ break; - case 4: + case 4: /* Handsfree output driver */ out = &priv->handsfree; - work = &priv->hf_delayed_work; - queue = priv->hf_workqueue; + work = &out->work; + /* + * Make sure, that we do not mess up variables for already + * executing work. + */ + cancel_delayed_work_sync(work); + out->left_step = priv->hf_left_step; out->right_step = priv->hf_right_step; out->step_delay = 5; /* 5 ms between volume ramp steps */ - if (SND_SOC_DAPM_EVENT_ON(event)) - priv->non_lp++; - else - priv->non_lp--; break; default: return -1; @@ -648,31 +598,25 @@ static int pga_event(struct snd_soc_dapm_widget *w, break; /* don't use volume ramp for power-up */ + out->ramp = TWL6040_RAMP_UP; out->left_step = out->left_vol; out->right_step = out->right_vol; - if (!delayed_work_pending(work)) { - out->ramp = TWL6040_RAMP_UP; - queue_delayed_work(queue, work, - msecs_to_jiffies(1)); - } + queue_delayed_work(priv->workqueue, work, msecs_to_jiffies(1)); break; case SND_SOC_DAPM_PRE_PMD: if (!out->active) break; - if (!delayed_work_pending(work)) { - /* use volume ramp for power-down */ - out->ramp = TWL6040_RAMP_DOWN; - INIT_COMPLETION(out->ramp_done); + /* use volume ramp for power-down */ + out->ramp = TWL6040_RAMP_DOWN; + INIT_COMPLETION(out->ramp_done); - queue_delayed_work(queue, work, - msecs_to_jiffies(1)); + queue_delayed_work(priv->workqueue, work, msecs_to_jiffies(1)); - wait_for_completion_timeout(&out->ramp_done, - msecs_to_jiffies(2000)); - } + wait_for_completion_timeout(&out->ramp_done, + msecs_to_jiffies(2000)); break; } @@ -683,7 +627,7 @@ static int pga_event(struct snd_soc_dapm_widget *w, static int headset_power_mode(struct snd_soc_codec *codec, int high_perf) { int hslctl, hsrctl; - int mask = TWL6040_HSDRVMODEL | TWL6040_HSDACMODEL; + int mask = TWL6040_HSDRVMODE | TWL6040_HSDACMODE; hslctl = twl6040_read_reg_cache(codec, TWL6040_REG_HSLCTL); hsrctl = twl6040_read_reg_cache(codec, TWL6040_REG_HSRCTL); @@ -705,11 +649,31 @@ static int headset_power_mode(struct snd_soc_codec *codec, int high_perf) static int twl6040_hs_dac_event(struct snd_soc_dapm_widget *w, struct snd_kcontrol *kcontrol, int event) { + struct snd_soc_codec *codec = w->codec; + u8 hslctl, hsrctl; + + /* + * Workaround for Headset DC offset caused pop noise: + * Both HS DAC need to be turned on (before the HS driver) and off at + * the same time. + */ + hslctl = twl6040_read_reg_cache(codec, TWL6040_REG_HSLCTL); + hsrctl = twl6040_read_reg_cache(codec, TWL6040_REG_HSRCTL); + if (SND_SOC_DAPM_EVENT_ON(event)) { + hslctl |= TWL6040_HSDACENA; + hsrctl |= TWL6040_HSDACENA; + } else { + hslctl &= ~TWL6040_HSDACENA; + hsrctl &= ~TWL6040_HSDACENA; + } + twl6040_write(codec, TWL6040_REG_HSLCTL, hslctl); + twl6040_write(codec, TWL6040_REG_HSRCTL, hsrctl); + msleep(1); return 0; } -static int twl6040_power_mode_event(struct snd_soc_dapm_widget *w, +static int twl6040_ep_drv_event(struct snd_soc_dapm_widget *w, struct snd_kcontrol *kcontrol, int event) { struct snd_soc_codec *codec = w->codec; @@ -717,18 +681,12 @@ static int twl6040_power_mode_event(struct snd_soc_dapm_widget *w, int ret = 0; if (SND_SOC_DAPM_EVENT_ON(event)) { - priv->non_lp++; - if (!strcmp(w->name, "Earphone Driver")) { - /* Earphone doesn't support low power mode */ - priv->hs_power_mode_locked = 1; - ret = headset_power_mode(codec, 1); - } + /* Earphone doesn't support low power mode */ + priv->hs_power_mode_locked = 1; + ret = headset_power_mode(codec, 1); } else { - priv->non_lp--; - if (!strcmp(w->name, "Earphone Driver")) { - priv->hs_power_mode_locked = 0; - ret = headset_power_mode(codec, priv->hs_power_mode); - } + priv->hs_power_mode_locked = 0; + ret = headset_power_mode(codec, priv->hs_power_mode); } msleep(1); @@ -770,7 +728,7 @@ EXPORT_SYMBOL_GPL(twl6040_hs_jack_detect); static void twl6040_accessory_work(struct work_struct *work) { struct twl6040_data *priv = container_of(work, - struct twl6040_data, delayed_work.work); + struct twl6040_data, hs_jack.work.work); struct snd_soc_codec *codec = priv->codec; struct twl6040_jack_data *hs_jack = &priv->hs_jack; @@ -781,15 +739,10 @@ static void twl6040_accessory_work(struct work_struct *work) static irqreturn_t twl6040_audio_handler(int irq, void *data) { struct snd_soc_codec *codec = data; - struct twl6040 *twl6040 = codec->control_data; struct twl6040_data *priv = snd_soc_codec_get_drvdata(codec); - u8 intid; - - intid = twl6040_reg_read(twl6040, TWL6040_REG_INTID); - if ((intid & TWL6040_PLUGINT) || (intid & TWL6040_UNPLUGINT)) - queue_delayed_work(priv->workqueue, &priv->delayed_work, - msecs_to_jiffies(200)); + queue_delayed_work(priv->workqueue, &priv->hs_jack.work, + msecs_to_jiffies(200)); return IRQ_HANDLED; } @@ -803,25 +756,27 @@ static int twl6040_put_volsw(struct snd_kcontrol *kcontrol, struct soc_mixer_control *mc = (struct soc_mixer_control *)kcontrol->private_value; int ret; - unsigned int reg = mc->reg; /* For HS and HF we shadow the values and only actually write * them out when active in order to ensure the amplifier comes on * as quietly as possible. */ - switch (reg) { + switch (mc->reg) { case TWL6040_REG_HSGAIN: out = &twl6040_priv->headset; break; - default: + case TWL6040_REG_HFLGAIN: + out = &twl6040_priv->handsfree; break; + default: + dev_warn(codec->dev, "%s: Unexpected register: 0x%02x\n", + __func__, mc->reg); + return -EINVAL; } - if (out) { - out->left_vol = ucontrol->value.integer.value[0]; - out->right_vol = ucontrol->value.integer.value[1]; - if (!out->active) - return 1; - } + out->left_vol = ucontrol->value.integer.value[0]; + out->right_vol = ucontrol->value.integer.value[1]; + if (!out->active) + return 1; ret = snd_soc_put_volsw(kcontrol, ucontrol); if (ret < 0) @@ -838,112 +793,42 @@ static int twl6040_get_volsw(struct snd_kcontrol *kcontrol, struct twl6040_output *out = &twl6040_priv->headset; struct soc_mixer_control *mc = (struct soc_mixer_control *)kcontrol->private_value; - unsigned int reg = mc->reg; - switch (reg) { + switch (mc->reg) { case TWL6040_REG_HSGAIN: out = &twl6040_priv->headset; - ucontrol->value.integer.value[0] = out->left_vol; - ucontrol->value.integer.value[1] = out->right_vol; - return 0; - - default: break; - } - - return snd_soc_get_volsw(kcontrol, ucontrol); -} - -static int twl6040_put_volsw_2r_vu(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); - struct twl6040_data *twl6040_priv = snd_soc_codec_get_drvdata(codec); - struct twl6040_output *out = NULL; - struct soc_mixer_control *mc = - (struct soc_mixer_control *)kcontrol->private_value; - int ret; - unsigned int reg = mc->reg; - - /* For HS and HF we shadow the values and only actually write - * them out when active in order to ensure the amplifier comes on - * as quietly as possible. */ - switch (reg) { case TWL6040_REG_HFLGAIN: - case TWL6040_REG_HFRGAIN: out = &twl6040_priv->handsfree; break; default: - break; - } - - if (out) { - out->left_vol = ucontrol->value.integer.value[0]; - out->right_vol = ucontrol->value.integer.value[1]; - if (!out->active) - return 1; + dev_warn(codec->dev, "%s: Unexpected register: 0x%02x\n", + __func__, mc->reg); + return -EINVAL; } - ret = snd_soc_put_volsw_2r(kcontrol, ucontrol); - if (ret < 0) - return ret; - - return 1; + ucontrol->value.integer.value[0] = out->left_vol; + ucontrol->value.integer.value[1] = out->right_vol; + return 0; } -static int twl6040_get_volsw_2r(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) +static int twl6040_soc_dapm_put_vibra_enum(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) { - struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); - struct twl6040_data *twl6040_priv = snd_soc_codec_get_drvdata(codec); - struct twl6040_output *out = &twl6040_priv->handsfree; - struct soc_mixer_control *mc = - (struct soc_mixer_control *)kcontrol->private_value; - unsigned int reg = mc->reg; - - /* If these are cached registers use the cache */ - switch (reg) { - case TWL6040_REG_HFLGAIN: - case TWL6040_REG_HFRGAIN: - out = &twl6040_priv->handsfree; - ucontrol->value.integer.value[0] = out->left_vol; - ucontrol->value.integer.value[1] = out->right_vol; - return 0; - - default: - break; - } - - return snd_soc_get_volsw_2r(kcontrol, ucontrol); + struct snd_soc_dapm_widget_list *wlist = snd_kcontrol_chip(kcontrol); + struct snd_soc_dapm_widget *widget = wlist->widgets[0]; + struct snd_soc_codec *codec = widget->codec; + struct soc_enum *e = (struct soc_enum *)kcontrol->private_value; + unsigned int val; + + /* Do not allow changes while Input/FF efect is running */ + val = twl6040_read_reg_volatile(codec, e->reg); + if (val & TWL6040_VIBENA && !(val & TWL6040_VIBSEL)) + return -EBUSY; + + return snd_soc_dapm_put_enum_double(kcontrol, ucontrol); } -/* double control with volume update */ -#define SOC_TWL6040_DOUBLE_TLV(xname, xreg, shift_left, shift_right, xmax,\ - xinvert, tlv_array)\ -{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = (xname),\ - .access = SNDRV_CTL_ELEM_ACCESS_TLV_READ |\ - SNDRV_CTL_ELEM_ACCESS_READWRITE,\ - .tlv.p = (tlv_array), \ - .info = snd_soc_info_volsw, .get = twl6040_get_volsw, \ - .put = twl6040_put_volsw, \ - .private_value = (unsigned long)&(struct soc_mixer_control) \ - {.reg = xreg, .shift = shift_left, .rshift = shift_right,\ - .max = xmax, .platform_max = xmax, .invert = xinvert} } - -/* double control with volume update */ -#define SOC_TWL6040_DOUBLE_R_TLV(xname, reg_left, reg_right, xshift, xmax,\ - xinvert, tlv_array)\ -{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = (xname),\ - .access = SNDRV_CTL_ELEM_ACCESS_TLV_READ | \ - SNDRV_CTL_ELEM_ACCESS_READWRITE | \ - SNDRV_CTL_ELEM_ACCESS_VOLATILE, \ - .tlv.p = (tlv_array), \ - .info = snd_soc_info_volsw_2r, \ - .get = twl6040_get_volsw_2r, .put = twl6040_put_volsw_2r_vu, \ - .private_value = (unsigned long)&(struct soc_mixer_control) \ - {.reg = reg_left, .rreg = reg_right, .shift = xshift, \ - .rshift = xshift, .max = xmax, .invert = xinvert}, } - /* * MICATT volume control: * from -6 to 0 dB in 6 dB steps @@ -1015,6 +900,19 @@ static const struct soc_enum twl6040_hf_enum[] = { twl6040_hf_texts), }; +static const char *twl6040_vibrapath_texts[] = { + "Input FF", "Audio PDM" +}; + +static const struct soc_enum twl6040_vibra_enum[] = { + SOC_ENUM_SINGLE(TWL6040_REG_VIBCTLL, 1, + ARRAY_SIZE(twl6040_vibrapath_texts), + twl6040_vibrapath_texts), + SOC_ENUM_SINGLE(TWL6040_REG_VIBCTLR, 1, + ARRAY_SIZE(twl6040_vibrapath_texts), + twl6040_vibrapath_texts), +}; + static const struct snd_kcontrol_new amicl_control = SOC_DAPM_ENUM("Route", twl6040_enum[0]); @@ -1035,8 +933,25 @@ static const struct snd_kcontrol_new hfl_mux_controls = static const struct snd_kcontrol_new hfr_mux_controls = SOC_DAPM_ENUM("Route", twl6040_hf_enum[1]); -static const struct snd_kcontrol_new ep_driver_switch_controls = - SOC_DAPM_SINGLE("Switch", TWL6040_REG_EARCTL, 0, 1, 0); +static const struct snd_kcontrol_new ep_path_enable_control = + SOC_DAPM_SINGLE("Switch", TWL6040_REG_SW_SHADOW, 0, 1, 0); + +static const struct snd_kcontrol_new auxl_switch_control = + SOC_DAPM_SINGLE("Switch", TWL6040_REG_HFLCTL, 6, 1, 0); + +static const struct snd_kcontrol_new auxr_switch_control = + SOC_DAPM_SINGLE("Switch", TWL6040_REG_HFRCTL, 6, 1, 0); + +/* Vibra playback switches */ +static const struct snd_kcontrol_new vibral_mux_controls = + SOC_DAPM_ENUM_EXT("Route", twl6040_vibra_enum[0], + snd_soc_dapm_get_enum_double, + twl6040_soc_dapm_put_vibra_enum); + +static const struct snd_kcontrol_new vibrar_mux_controls = + SOC_DAPM_ENUM_EXT("Route", twl6040_vibra_enum[1], + snd_soc_dapm_get_enum_double, + twl6040_soc_dapm_put_vibra_enum); /* Headset power mode */ static const char *twl6040_power_mode_texts[] = { @@ -1105,6 +1020,15 @@ int twl6040_get_clk_id(struct snd_soc_codec *codec) } EXPORT_SYMBOL_GPL(twl6040_get_clk_id); +int twl6040_get_trim_value(struct snd_soc_codec *codec, enum twl6040_trim trim) +{ + if (unlikely(trim >= TWL6040_TRIM_INVAL)) + return -EINVAL; + + return twl6040_read_reg_cache(codec, TWL6040_REG_TRIM1 + trim); +} +EXPORT_SYMBOL_GPL(twl6040_get_trim_value); + static const struct snd_kcontrol_new twl6040_snd_controls[] = { /* Capture gains */ SOC_DOUBLE_TLV("Capture Preamplifier Volume", @@ -1117,10 +1041,12 @@ static const struct snd_kcontrol_new twl6040_snd_controls[] = { TWL6040_REG_LINEGAIN, 0, 3, 7, 0, afm_amp_tlv), /* Playback gains */ - SOC_TWL6040_DOUBLE_TLV("Headset Playback Volume", - TWL6040_REG_HSGAIN, 0, 4, 0xF, 1, hs_tlv), - SOC_TWL6040_DOUBLE_R_TLV("Handsfree Playback Volume", - TWL6040_REG_HFLGAIN, TWL6040_REG_HFRGAIN, 0, 0x1D, 1, hf_tlv), + SOC_DOUBLE_EXT_TLV("Headset Playback Volume", + TWL6040_REG_HSGAIN, 0, 4, 0xF, 1, twl6040_get_volsw, + twl6040_put_volsw, hs_tlv), + SOC_DOUBLE_R_EXT_TLV("Handsfree Playback Volume", + TWL6040_REG_HFLGAIN, TWL6040_REG_HFRGAIN, 0, 0x1D, 1, + twl6040_get_volsw, twl6040_put_volsw, hf_tlv), SOC_SINGLE_TLV("Earphone Playback Volume", TWL6040_REG_EARCTL, 1, 0xF, 1, ep_tlv), @@ -1146,6 +1072,10 @@ static const struct snd_soc_dapm_widget twl6040_dapm_widgets[] = { SND_SOC_DAPM_OUTPUT("HFL"), SND_SOC_DAPM_OUTPUT("HFR"), SND_SOC_DAPM_OUTPUT("EP"), + SND_SOC_DAPM_OUTPUT("AUXL"), + SND_SOC_DAPM_OUTPUT("AUXR"), + SND_SOC_DAPM_OUTPUT("VIBRAL"), + SND_SOC_DAPM_OUTPUT("VIBRAR"), /* Analog input muxes for the capture amplifiers */ SND_SOC_DAPM_MUX("Analog Left Capture Route", @@ -1182,59 +1112,76 @@ static const struct snd_soc_dapm_widget twl6040_dapm_widgets[] = { TWL6040_REG_DMICBCTL, 4, 0), /* DACs */ - SND_SOC_DAPM_DAC_E("HSDAC Left", "Headset Playback", - TWL6040_REG_HSLCTL, 0, 0, - twl6040_hs_dac_event, - SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD), - SND_SOC_DAPM_DAC_E("HSDAC Right", "Headset Playback", - TWL6040_REG_HSRCTL, 0, 0, - twl6040_hs_dac_event, - SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD), - SND_SOC_DAPM_DAC_E("HFDAC Left", "Handsfree Playback", - TWL6040_REG_HFLCTL, 0, 0, - twl6040_power_mode_event, - SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD), - SND_SOC_DAPM_DAC_E("HFDAC Right", "Handsfree Playback", - TWL6040_REG_HFRCTL, 0, 0, - twl6040_power_mode_event, - SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD), - - SND_SOC_DAPM_MUX("HF Left Playback", + SND_SOC_DAPM_DAC("HSDAC Left", "Headset Playback", SND_SOC_NOPM, 0, 0), + SND_SOC_DAPM_DAC("HSDAC Right", "Headset Playback", SND_SOC_NOPM, 0, 0), + SND_SOC_DAPM_DAC("HFDAC Left", "Handsfree Playback", + TWL6040_REG_HFLCTL, 0, 0), + SND_SOC_DAPM_DAC("HFDAC Right", "Handsfree Playback", + TWL6040_REG_HFRCTL, 0, 0), + /* Virtual DAC for vibra path (DL4 channel) */ + SND_SOC_DAPM_DAC("VIBRA DAC", "Vibra Playback", + SND_SOC_NOPM, 0, 0), + + SND_SOC_DAPM_MUX("Handsfree Left Playback", SND_SOC_NOPM, 0, 0, &hfl_mux_controls), - SND_SOC_DAPM_MUX("HF Right Playback", + SND_SOC_DAPM_MUX("Handsfree Right Playback", SND_SOC_NOPM, 0, 0, &hfr_mux_controls), /* Analog playback Muxes */ - SND_SOC_DAPM_MUX("HS Left Playback", + SND_SOC_DAPM_MUX("Headset Left Playback", SND_SOC_NOPM, 0, 0, &hsl_mux_controls), - SND_SOC_DAPM_MUX("HS Right Playback", + SND_SOC_DAPM_MUX("Headset Right Playback", SND_SOC_NOPM, 0, 0, &hsr_mux_controls), + SND_SOC_DAPM_MUX("Vibra Left Playback", SND_SOC_NOPM, 0, 0, + &vibral_mux_controls), + SND_SOC_DAPM_MUX("Vibra Right Playback", SND_SOC_NOPM, 0, 0, + &vibrar_mux_controls), + + SND_SOC_DAPM_SWITCH("Earphone Playback", SND_SOC_NOPM, 0, 0, + &ep_path_enable_control), + SND_SOC_DAPM_SWITCH("AUXL Playback", SND_SOC_NOPM, 0, 0, + &auxl_switch_control), + SND_SOC_DAPM_SWITCH("AUXR Playback", SND_SOC_NOPM, 0, 0, + &auxr_switch_control), + /* Analog playback drivers */ - SND_SOC_DAPM_OUT_DRV_E("Handsfree Left Driver", + SND_SOC_DAPM_OUT_DRV_E("HF Left Driver", TWL6040_REG_HFLCTL, 4, 0, NULL, 0, - pga_event, + out_drv_event, SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD), - SND_SOC_DAPM_OUT_DRV_E("Handsfree Right Driver", + SND_SOC_DAPM_OUT_DRV_E("HF Right Driver", TWL6040_REG_HFRCTL, 4, 0, NULL, 0, - pga_event, + out_drv_event, SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD), - SND_SOC_DAPM_OUT_DRV_E("Headset Left Driver", + SND_SOC_DAPM_OUT_DRV_E("HS Left Driver", TWL6040_REG_HSLCTL, 2, 0, NULL, 0, - pga_event, + out_drv_event, SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD), - SND_SOC_DAPM_OUT_DRV_E("Headset Right Driver", + SND_SOC_DAPM_OUT_DRV_E("HS Right Driver", TWL6040_REG_HSRCTL, 2, 0, NULL, 0, - pga_event, + out_drv_event, SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD), - SND_SOC_DAPM_SWITCH_E("Earphone Driver", - SND_SOC_NOPM, 0, 0, &ep_driver_switch_controls, - twl6040_power_mode_event, - SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD), + SND_SOC_DAPM_OUT_DRV_E("Earphone Driver", + TWL6040_REG_EARCTL, 0, 0, NULL, 0, + twl6040_ep_drv_event, + SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD), + SND_SOC_DAPM_OUT_DRV("Vibra Left Driver", + TWL6040_REG_VIBCTLL, 0, 0, NULL, 0), + SND_SOC_DAPM_OUT_DRV("Vibra Right Driver", + TWL6040_REG_VIBCTLR, 0, 0, NULL, 0), + + SND_SOC_DAPM_SUPPLY("Vibra Left Control", TWL6040_REG_VIBCTLL, 2, 0, + NULL, 0), + SND_SOC_DAPM_SUPPLY("Vibra Right Control", TWL6040_REG_VIBCTLR, 2, 0, + NULL, 0), + SND_SOC_DAPM_SUPPLY_S("HSDAC Power", 1, SND_SOC_NOPM, 0, 0, + twl6040_hs_dac_event, + SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD), /* Analog playback PGAs */ - SND_SOC_DAPM_PGA("HFDAC Left PGA", + SND_SOC_DAPM_PGA("HF Left PGA", TWL6040_REG_HFLCTL, 1, 0, NULL, 0), - SND_SOC_DAPM_PGA("HFDAC Right PGA", + SND_SOC_DAPM_PGA("HF Right PGA", TWL6040_REG_HFRCTL, 1, 0, NULL, 0), }; @@ -1256,52 +1203,62 @@ static const struct snd_soc_dapm_route intercon[] = { {"ADC Right", NULL, "MicAmpR"}, /* AFM path */ - {"AFMAmpL", "NULL", "AFML"}, - {"AFMAmpR", "NULL", "AFMR"}, + {"AFMAmpL", NULL, "AFML"}, + {"AFMAmpR", NULL, "AFMR"}, + + {"HSDAC Left", NULL, "HSDAC Power"}, + {"HSDAC Right", NULL, "HSDAC Power"}, - {"HS Left Playback", "HS DAC", "HSDAC Left"}, - {"HS Left Playback", "Line-In amp", "AFMAmpL"}, + {"Headset Left Playback", "HS DAC", "HSDAC Left"}, + {"Headset Left Playback", "Line-In amp", "AFMAmpL"}, - {"HS Right Playback", "HS DAC", "HSDAC Right"}, - {"HS Right Playback", "Line-In amp", "AFMAmpR"}, + {"Headset Right Playback", "HS DAC", "HSDAC Right"}, + {"Headset Right Playback", "Line-In amp", "AFMAmpR"}, - {"Headset Left Driver", "NULL", "HS Left Playback"}, - {"Headset Right Driver", "NULL", "HS Right Playback"}, + {"HS Left Driver", NULL, "Headset Left Playback"}, + {"HS Right Driver", NULL, "Headset Right Playback"}, - {"HSOL", NULL, "Headset Left Driver"}, - {"HSOR", NULL, "Headset Right Driver"}, + {"HSOL", NULL, "HS Left Driver"}, + {"HSOR", NULL, "HS Right Driver"}, /* Earphone playback path */ - {"Earphone Driver", "Switch", "HSDAC Left"}, + {"Earphone Playback", "Switch", "HSDAC Left"}, + {"Earphone Driver", NULL, "Earphone Playback"}, {"EP", NULL, "Earphone Driver"}, - {"HF Left Playback", "HF DAC", "HFDAC Left"}, - {"HF Left Playback", "Line-In amp", "AFMAmpL"}, + {"Handsfree Left Playback", "HF DAC", "HFDAC Left"}, + {"Handsfree Left Playback", "Line-In amp", "AFMAmpL"}, - {"HF Right Playback", "HF DAC", "HFDAC Right"}, - {"HF Right Playback", "Line-In amp", "AFMAmpR"}, + {"Handsfree Right Playback", "HF DAC", "HFDAC Right"}, + {"Handsfree Right Playback", "Line-In amp", "AFMAmpR"}, - {"HFDAC Left PGA", NULL, "HF Left Playback"}, - {"HFDAC Right PGA", NULL, "HF Right Playback"}, + {"HF Left PGA", NULL, "Handsfree Left Playback"}, + {"HF Right PGA", NULL, "Handsfree Right Playback"}, - {"Handsfree Left Driver", "Switch", "HFDAC Left PGA"}, - {"Handsfree Right Driver", "Switch", "HFDAC Right PGA"}, + {"HF Left Driver", NULL, "HF Left PGA"}, + {"HF Right Driver", NULL, "HF Right PGA"}, - {"HFL", NULL, "Handsfree Left Driver"}, - {"HFR", NULL, "Handsfree Right Driver"}, -}; + {"HFL", NULL, "HF Left Driver"}, + {"HFR", NULL, "HF Right Driver"}, -static int twl6040_add_widgets(struct snd_soc_codec *codec) -{ - struct snd_soc_dapm_context *dapm = &codec->dapm; + {"AUXL Playback", "Switch", "HF Left PGA"}, + {"AUXR Playback", "Switch", "HF Right PGA"}, - snd_soc_dapm_new_controls(dapm, twl6040_dapm_widgets, - ARRAY_SIZE(twl6040_dapm_widgets)); - snd_soc_dapm_add_routes(dapm, intercon, ARRAY_SIZE(intercon)); - snd_soc_dapm_new_widgets(dapm); + {"AUXL", NULL, "AUXL Playback"}, + {"AUXR", NULL, "AUXR Playback"}, - return 0; -} + /* Vibrator paths */ + {"Vibra Left Playback", "Audio PDM", "VIBRA DAC"}, + {"Vibra Right Playback", "Audio PDM", "VIBRA DAC"}, + + {"Vibra Left Driver", NULL, "Vibra Left Playback"}, + {"Vibra Right Driver", NULL, "Vibra Right Playback"}, + {"Vibra Left Driver", NULL, "Vibra Left Control"}, + {"Vibra Right Driver", NULL, "Vibra Right Control"}, + + {"VIBRAL", NULL, "Vibra Left Driver"}, + {"VIBRAR", NULL, "Vibra Right Driver"}, +}; static int twl6040_set_bias_level(struct snd_soc_codec *codec, enum snd_soc_bias_level level) @@ -1325,8 +1282,7 @@ static int twl6040_set_bias_level(struct snd_soc_codec *codec, priv->codec_powered = 1; - /* initialize vdd/vss registers with reg_cache */ - twl6040_init_vdd_regs(codec); + twl6040_restore_regs(codec); /* Set external boost GPO */ twl6040_write(codec, TWL6040_REG_GPOCTL, 0x02); @@ -1380,13 +1336,6 @@ static int twl6040_hw_params(struct snd_pcm_substream *substream, rate); return -EINVAL; } - /* Capture is not supported with 17.64MHz sysclk */ - if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) { - dev_err(codec->dev, - "capture mode is not supported at %dHz\n", - rate); - return -EINVAL; - } priv->sysclk = 17640000; break; case 8000: @@ -1419,13 +1368,6 @@ static int twl6040_prepare(struct snd_pcm_substream *substream, return -EINVAL; } - if ((priv->sysclk == 17640000) && priv->non_lp) { - dev_err(codec->dev, - "some enabled paths aren't supported at %dHz\n", - priv->sysclk); - return -EPERM; - } - ret = twl6040_set_pll(twl6040, priv->pll, priv->clk_in, priv->sysclk); if (ret) { dev_err(codec->dev, "Can not set PLL (%d)\n", ret); @@ -1464,11 +1406,11 @@ static struct snd_soc_dai_ops twl6040_dai_ops = { static struct snd_soc_dai_driver twl6040_dai[] = { { - .name = "twl6040-hifi", + .name = "twl6040-legacy", .playback = { .stream_name = "Playback", .channels_min = 1, - .channels_max = 2, + .channels_max = 5, .rates = TWL6040_RATES, .formats = TWL6040_FORMATS, }, @@ -1518,8 +1460,8 @@ static struct snd_soc_dai_driver twl6040_dai[] = { .name = "twl6040-vib", .playback = { .stream_name = "Vibra Playback", - .channels_min = 2, - .channels_max = 2, + .channels_min = 1, + .channels_max = 1, .rates = SNDRV_PCM_RATE_CONTINUOUS, .formats = TWL6040_FORMATS, }, @@ -1562,6 +1504,7 @@ static int twl6040_probe(struct snd_soc_codec *codec) priv->codec = codec; codec->control_data = dev_get_drvdata(codec->dev->parent); + codec->ignore_pmdown_time = 1; if (pdata && pdata->hs_left_step && pdata->hs_right_step) { priv->hs_left_step = pdata->hs_left_step; @@ -1586,33 +1529,21 @@ static int twl6040_probe(struct snd_soc_codec *codec) goto work_err; } - priv->workqueue = create_singlethread_workqueue("twl6040-codec"); + priv->workqueue = alloc_workqueue("twl6040-codec", 0, 0); if (!priv->workqueue) { ret = -ENOMEM; goto work_err; } - INIT_DELAYED_WORK(&priv->delayed_work, twl6040_accessory_work); + INIT_DELAYED_WORK(&priv->hs_jack.work, twl6040_accessory_work); + INIT_DELAYED_WORK(&priv->headset.work, twl6040_pga_hs_work); + INIT_DELAYED_WORK(&priv->handsfree.work, twl6040_pga_hf_work); mutex_init(&priv->mutex); init_completion(&priv->headset.ramp_done); init_completion(&priv->handsfree.ramp_done); - priv->hf_workqueue = create_singlethread_workqueue("twl6040-hf"); - if (priv->hf_workqueue == NULL) { - ret = -ENOMEM; - goto hfwq_err; - } - priv->hs_workqueue = create_singlethread_workqueue("twl6040-hs"); - if (priv->hs_workqueue == NULL) { - ret = -ENOMEM; - goto hswq_err; - } - - INIT_DELAYED_WORK(&priv->hs_delayed_work, twl6040_pga_hs_work); - INIT_DELAYED_WORK(&priv->hf_delayed_work, twl6040_pga_hf_work); - ret = request_threaded_irq(priv->plug_irq, NULL, twl6040_audio_handler, 0, "twl6040_irq_plug", codec); if (ret) { @@ -1620,27 +1551,16 @@ static int twl6040_probe(struct snd_soc_codec *codec) goto plugirq_err; } - /* init vio registers */ - twl6040_init_vio_regs(codec); + twl6040_init_chip(codec); /* power on device */ ret = twl6040_set_bias_level(codec, SND_SOC_BIAS_STANDBY); - if (ret) - goto bias_err; - - snd_soc_add_controls(codec, twl6040_snd_controls, - ARRAY_SIZE(twl6040_snd_controls)); - twl6040_add_widgets(codec); - - return 0; + if (!ret) + return 0; -bias_err: + /* Error path */ free_irq(priv->plug_irq, codec); plugirq_err: - destroy_workqueue(priv->hs_workqueue); -hswq_err: - destroy_workqueue(priv->hf_workqueue); -hfwq_err: destroy_workqueue(priv->workqueue); work_err: kfree(priv); @@ -1654,8 +1574,6 @@ static int twl6040_remove(struct snd_soc_codec *codec) twl6040_set_bias_level(codec, SND_SOC_BIAS_OFF); free_irq(priv->plug_irq, codec); destroy_workqueue(priv->workqueue); - destroy_workqueue(priv->hf_workqueue); - destroy_workqueue(priv->hs_workqueue); kfree(priv); return 0; @@ -1672,6 +1590,13 @@ static struct snd_soc_codec_driver soc_codec_dev_twl6040 = { .reg_cache_size = ARRAY_SIZE(twl6040_reg), .reg_word_size = sizeof(u8), .reg_cache_default = twl6040_reg, + + .controls = twl6040_snd_controls, + .num_controls = ARRAY_SIZE(twl6040_snd_controls), + .dapm_widgets = twl6040_dapm_widgets, + .num_dapm_widgets = ARRAY_SIZE(twl6040_dapm_widgets), + .dapm_routes = intercon, + .num_dapm_routes = ARRAY_SIZE(intercon), }; static int __devinit twl6040_codec_probe(struct platform_device *pdev) diff --git a/sound/soc/codecs/twl6040.h b/sound/soc/codecs/twl6040.h index d8de67869dd..a83277bdb85 100644 --- a/sound/soc/codecs/twl6040.h +++ b/sound/soc/codecs/twl6040.h @@ -22,8 +22,21 @@ #ifndef __TWL6040_H__ #define __TWL6040_H__ +enum twl6040_trim { + TWL6040_TRIM_TRIM1 = 0, + TWL6040_TRIM_TRIM2, + TWL6040_TRIM_TRIM3, + TWL6040_TRIM_HSOTRIM, + TWL6040_TRIM_HFOTRIM, + TWL6040_TRIM_INVAL, +}; + +#define TWL6040_HSF_TRIM_LEFT(x) (x & 0x0f) +#define TWL6040_HSF_TRIM_RIGHT(x) ((x >> 4) & 0x0f) + void twl6040_hs_jack_detect(struct snd_soc_codec *codec, struct snd_soc_jack *jack, int report); int twl6040_get_clk_id(struct snd_soc_codec *codec); +int twl6040_get_trim_value(struct snd_soc_codec *codec, enum twl6040_trim trim); #endif /* End of __TWL6040_H__ */ diff --git a/sound/soc/codecs/wl1273.c b/sound/soc/codecs/wl1273.c index 5836201834d..a8549898299 100644 --- a/sound/soc/codecs/wl1273.c +++ b/sound/soc/codecs/wl1273.c @@ -23,6 +23,7 @@ #include <linux/mfd/wl1273-core.h> #include <linux/slab.h> +#include <linux/module.h> #include <sound/pcm.h> #include <sound/pcm_params.h> #include <sound/soc.h> @@ -462,7 +463,6 @@ static int wl1273_probe(struct snd_soc_codec *codec) wl1273->core = *core; snd_soc_codec_set_drvdata(codec, wl1273); - mutex_init(&codec->mutex); r = snd_soc_add_controls(codec, wl1273_controls, ARRAY_SIZE(wl1273_controls)); diff --git a/sound/soc/codecs/wm1250-ev1.c b/sound/soc/codecs/wm1250-ev1.c index bcc20896791..cd0ec0fd1db 100644 --- a/sound/soc/codecs/wm1250-ev1.c +++ b/sound/soc/codecs/wm1250-ev1.c @@ -12,10 +12,59 @@ #include <linux/init.h> #include <linux/module.h> +#include <linux/slab.h> #include <linux/i2c.h> +#include <linux/gpio.h> #include <sound/soc.h> #include <sound/soc-dapm.h> +#include <sound/wm1250-ev1.h> + +static const char *wm1250_gpio_names[WM1250_EV1_NUM_GPIOS] = { + "WM1250 CLK_ENA", + "WM1250 CLK_SEL0", + "WM1250 CLK_SEL1", + "WM1250 OSR", + "WM1250 MASTER", +}; + +struct wm1250_priv { + struct gpio gpios[WM1250_EV1_NUM_GPIOS]; +}; + +static int wm1250_ev1_set_bias_level(struct snd_soc_codec *codec, + enum snd_soc_bias_level level) +{ + struct wm1250_priv *wm1250 = dev_get_drvdata(codec->dev); + int ena; + + if (wm1250) + ena = wm1250->gpios[WM1250_EV1_GPIO_CLK_ENA].gpio; + else + ena = -1; + + switch (level) { + case SND_SOC_BIAS_ON: + break; + + case SND_SOC_BIAS_PREPARE: + break; + + case SND_SOC_BIAS_STANDBY: + if (ena >= 0) + gpio_set_value_cansleep(ena, 1); + break; + + case SND_SOC_BIAS_OFF: + if (ena >= 0) + gpio_set_value_cansleep(ena, 0); + break; + } + + codec->dapm.bias_level = level; + + return 0; +} static const struct snd_soc_dapm_widget wm1250_ev1_dapm_widgets[] = { SND_SOC_DAPM_ADC("ADC", "wm1250-ev1 Capture", SND_SOC_NOPM, 0, 0), @@ -53,18 +102,103 @@ static struct snd_soc_codec_driver soc_codec_dev_wm1250_ev1 = { .num_dapm_widgets = ARRAY_SIZE(wm1250_ev1_dapm_widgets), .dapm_routes = wm1250_ev1_dapm_routes, .num_dapm_routes = ARRAY_SIZE(wm1250_ev1_dapm_routes), + + .set_bias_level = wm1250_ev1_set_bias_level, + .idle_bias_off = true, }; +static int __devinit wm1250_ev1_pdata(struct i2c_client *i2c) +{ + struct wm1250_ev1_pdata *pdata = dev_get_platdata(&i2c->dev); + struct wm1250_priv *wm1250; + int i, ret; + + if (!pdata) + return 0; + + wm1250 = kzalloc(sizeof(*wm1250), GFP_KERNEL); + if (!wm1250) { + dev_err(&i2c->dev, "Unable to allocate private data\n"); + ret = -ENOMEM; + goto err; + } + + for (i = 0; i < ARRAY_SIZE(wm1250->gpios); i++) { + wm1250->gpios[i].gpio = pdata->gpios[i]; + wm1250->gpios[i].label = wm1250_gpio_names[i]; + wm1250->gpios[i].flags = GPIOF_OUT_INIT_LOW; + } + wm1250->gpios[WM1250_EV1_GPIO_CLK_SEL0].flags = GPIOF_OUT_INIT_HIGH; + wm1250->gpios[WM1250_EV1_GPIO_CLK_SEL1].flags = GPIOF_OUT_INIT_HIGH; + + ret = gpio_request_array(wm1250->gpios, ARRAY_SIZE(wm1250->gpios)); + if (ret != 0) { + dev_err(&i2c->dev, "Failed to get GPIOs: %d\n", ret); + goto err_alloc; + } + + dev_set_drvdata(&i2c->dev, wm1250); + + return ret; + +err_alloc: + kfree(wm1250); +err: + return ret; +} + +static void wm1250_ev1_free(struct i2c_client *i2c) +{ + struct wm1250_priv *wm1250 = dev_get_drvdata(&i2c->dev); + + if (wm1250) { + gpio_free_array(wm1250->gpios, ARRAY_SIZE(wm1250->gpios)); + kfree(wm1250); + } +} + static int __devinit wm1250_ev1_probe(struct i2c_client *i2c, - const struct i2c_device_id *id) + const struct i2c_device_id *i2c_id) { - return snd_soc_register_codec(&i2c->dev, &soc_codec_dev_wm1250_ev1, - &wm1250_ev1_dai, 1); + int id, board, rev, ret; + + dev_set_drvdata(&i2c->dev, NULL); + + board = i2c_smbus_read_byte_data(i2c, 0); + if (board < 0) { + dev_err(&i2c->dev, "Failed to read ID: %d\n", board); + return board; + } + + id = (board & 0xfe) >> 2; + rev = board & 0x3; + + if (id != 1) { + dev_err(&i2c->dev, "Unknown board ID %d\n", id); + return -ENODEV; + } + + dev_info(&i2c->dev, "revision %d\n", rev + 1); + + ret = wm1250_ev1_pdata(i2c); + if (ret != 0) + return ret; + + ret = snd_soc_register_codec(&i2c->dev, &soc_codec_dev_wm1250_ev1, + &wm1250_ev1_dai, 1); + if (ret != 0) { + dev_err(&i2c->dev, "Failed to register CODEC: %d\n", ret); + wm1250_ev1_free(i2c); + return ret; + } + + return 0; } static int __devexit wm1250_ev1_remove(struct i2c_client *i2c) { snd_soc_unregister_codec(&i2c->dev); + wm1250_ev1_free(i2c); return 0; } diff --git a/sound/soc/codecs/wm5100-tables.c b/sound/soc/codecs/wm5100-tables.c new file mode 100644 index 00000000000..e9ce81a57b8 --- /dev/null +++ b/sound/soc/codecs/wm5100-tables.c @@ -0,0 +1,1531 @@ +/* + * wm5100-tables.c -- WM5100 ALSA SoC Audio driver data + * + * Copyright 2011 Wolfson Microelectronics plc + * + * Author: Mark Brown <broonie@opensource.wolfsonmicro.com> + * + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#include "wm5100.h" + +int wm5100_volatile_register(struct snd_soc_codec *codec, unsigned int reg) +{ + switch (reg) { + case WM5100_SOFTWARE_RESET: + case WM5100_DEVICE_REVISION: + case WM5100_FX_CTRL: + case WM5100_INTERRUPT_STATUS_1: + case WM5100_INTERRUPT_STATUS_2: + case WM5100_INTERRUPT_STATUS_3: + case WM5100_INTERRUPT_STATUS_4: + case WM5100_INTERRUPT_RAW_STATUS_2: + case WM5100_INTERRUPT_RAW_STATUS_3: + case WM5100_INTERRUPT_RAW_STATUS_4: + case WM5100_OUTPUT_STATUS_1: + case WM5100_OUTPUT_STATUS_2: + case WM5100_INPUT_ENABLES_STATUS: + case WM5100_MIC_DETECT_3: + return 1; + default: + return 0; + } +} + +int wm5100_readable_register(struct snd_soc_codec *codec, unsigned int reg) +{ + switch (reg) { + case WM5100_SOFTWARE_RESET: + case WM5100_DEVICE_REVISION: + case WM5100_CTRL_IF_1: + case WM5100_TONE_GENERATOR_1: + case WM5100_PWM_DRIVE_1: + case WM5100_PWM_DRIVE_2: + case WM5100_PWM_DRIVE_3: + case WM5100_CLOCKING_1: + case WM5100_CLOCKING_3: + case WM5100_CLOCKING_4: + case WM5100_CLOCKING_5: + case WM5100_CLOCKING_6: + case WM5100_CLOCKING_7: + case WM5100_CLOCKING_8: + case WM5100_ASRC_ENABLE: + case WM5100_ASRC_STATUS: + case WM5100_ASRC_RATE1: + case WM5100_ISRC_1_CTRL_1: + case WM5100_ISRC_1_CTRL_2: + case WM5100_ISRC_2_CTRL1: + case WM5100_ISRC_2_CTRL_2: + case WM5100_FLL1_CONTROL_1: + case WM5100_FLL1_CONTROL_2: + case WM5100_FLL1_CONTROL_3: + case WM5100_FLL1_CONTROL_5: + case WM5100_FLL1_CONTROL_6: + case WM5100_FLL1_EFS_1: + case WM5100_FLL2_CONTROL_1: + case WM5100_FLL2_CONTROL_2: + case WM5100_FLL2_CONTROL_3: + case WM5100_FLL2_CONTROL_5: + case WM5100_FLL2_CONTROL_6: + case WM5100_FLL2_EFS_1: + case WM5100_MIC_CHARGE_PUMP_1: + case WM5100_MIC_CHARGE_PUMP_2: + case WM5100_HP_CHARGE_PUMP_1: + case WM5100_LDO1_CONTROL: + case WM5100_MIC_BIAS_CTRL_1: + case WM5100_MIC_BIAS_CTRL_2: + case WM5100_MIC_BIAS_CTRL_3: + case WM5100_ACCESSORY_DETECT_MODE_1: + case WM5100_HEADPHONE_DETECT_1: + case WM5100_HEADPHONE_DETECT_2: + case WM5100_MIC_DETECT_1: + case WM5100_MIC_DETECT_2: + case WM5100_MIC_DETECT_3: + case WM5100_INPUT_ENABLES: + case WM5100_INPUT_ENABLES_STATUS: + case WM5100_IN1L_CONTROL: + case WM5100_IN1R_CONTROL: + case WM5100_IN2L_CONTROL: + case WM5100_IN2R_CONTROL: + case WM5100_IN3L_CONTROL: + case WM5100_IN3R_CONTROL: + case WM5100_IN4L_CONTROL: + case WM5100_IN4R_CONTROL: + case WM5100_RXANC_SRC: + case WM5100_INPUT_VOLUME_RAMP: + case WM5100_ADC_DIGITAL_VOLUME_1L: + case WM5100_ADC_DIGITAL_VOLUME_1R: + case WM5100_ADC_DIGITAL_VOLUME_2L: + case WM5100_ADC_DIGITAL_VOLUME_2R: + case WM5100_ADC_DIGITAL_VOLUME_3L: + case WM5100_ADC_DIGITAL_VOLUME_3R: + case WM5100_ADC_DIGITAL_VOLUME_4L: + case WM5100_ADC_DIGITAL_VOLUME_4R: + case WM5100_OUTPUT_ENABLES_2: + case WM5100_OUTPUT_STATUS_1: + case WM5100_OUTPUT_STATUS_2: + case WM5100_CHANNEL_ENABLES_1: + case WM5100_OUT_VOLUME_1L: + case WM5100_OUT_VOLUME_1R: + case WM5100_DAC_VOLUME_LIMIT_1L: + case WM5100_DAC_VOLUME_LIMIT_1R: + case WM5100_OUT_VOLUME_2L: + case WM5100_OUT_VOLUME_2R: + case WM5100_DAC_VOLUME_LIMIT_2L: + case WM5100_DAC_VOLUME_LIMIT_2R: + case WM5100_OUT_VOLUME_3L: + case WM5100_OUT_VOLUME_3R: + case WM5100_DAC_VOLUME_LIMIT_3L: + case WM5100_DAC_VOLUME_LIMIT_3R: + case WM5100_OUT_VOLUME_4L: + case WM5100_OUT_VOLUME_4R: + case WM5100_DAC_VOLUME_LIMIT_5L: + case WM5100_DAC_VOLUME_LIMIT_5R: + case WM5100_DAC_VOLUME_LIMIT_6L: + case WM5100_DAC_VOLUME_LIMIT_6R: + case WM5100_DAC_AEC_CONTROL_1: + case WM5100_OUTPUT_VOLUME_RAMP: + case WM5100_DAC_DIGITAL_VOLUME_1L: + case WM5100_DAC_DIGITAL_VOLUME_1R: + case WM5100_DAC_DIGITAL_VOLUME_2L: + case WM5100_DAC_DIGITAL_VOLUME_2R: + case WM5100_DAC_DIGITAL_VOLUME_3L: + case WM5100_DAC_DIGITAL_VOLUME_3R: + case WM5100_DAC_DIGITAL_VOLUME_4L: + case WM5100_DAC_DIGITAL_VOLUME_4R: + case WM5100_DAC_DIGITAL_VOLUME_5L: + case WM5100_DAC_DIGITAL_VOLUME_5R: + case WM5100_DAC_DIGITAL_VOLUME_6L: + case WM5100_DAC_DIGITAL_VOLUME_6R: + case WM5100_PDM_SPK1_CTRL_1: + case WM5100_PDM_SPK1_CTRL_2: + case WM5100_PDM_SPK2_CTRL_1: + case WM5100_PDM_SPK2_CTRL_2: + case WM5100_AUDIO_IF_1_1: + case WM5100_AUDIO_IF_1_2: + case WM5100_AUDIO_IF_1_3: + case WM5100_AUDIO_IF_1_4: + case WM5100_AUDIO_IF_1_5: + case WM5100_AUDIO_IF_1_6: + case WM5100_AUDIO_IF_1_7: + case WM5100_AUDIO_IF_1_8: + case WM5100_AUDIO_IF_1_9: + case WM5100_AUDIO_IF_1_10: + case WM5100_AUDIO_IF_1_11: + case WM5100_AUDIO_IF_1_12: + case WM5100_AUDIO_IF_1_13: + case WM5100_AUDIO_IF_1_14: + case WM5100_AUDIO_IF_1_15: + case WM5100_AUDIO_IF_1_16: + case WM5100_AUDIO_IF_1_17: + case WM5100_AUDIO_IF_1_18: + case WM5100_AUDIO_IF_1_19: + case WM5100_AUDIO_IF_1_20: + case WM5100_AUDIO_IF_1_21: + case WM5100_AUDIO_IF_1_22: + case WM5100_AUDIO_IF_1_23: + case WM5100_AUDIO_IF_1_24: + case WM5100_AUDIO_IF_1_25: + case WM5100_AUDIO_IF_1_26: + case WM5100_AUDIO_IF_1_27: + case WM5100_AUDIO_IF_2_1: + case WM5100_AUDIO_IF_2_2: + case WM5100_AUDIO_IF_2_3: + case WM5100_AUDIO_IF_2_4: + case WM5100_AUDIO_IF_2_5: + case WM5100_AUDIO_IF_2_6: + case WM5100_AUDIO_IF_2_7: + case WM5100_AUDIO_IF_2_8: + case WM5100_AUDIO_IF_2_9: + case WM5100_AUDIO_IF_2_10: + case WM5100_AUDIO_IF_2_11: + case WM5100_AUDIO_IF_2_18: + case WM5100_AUDIO_IF_2_19: + case WM5100_AUDIO_IF_2_26: + case WM5100_AUDIO_IF_2_27: + case WM5100_AUDIO_IF_3_1: + case WM5100_AUDIO_IF_3_2: + case WM5100_AUDIO_IF_3_3: + case WM5100_AUDIO_IF_3_4: + case WM5100_AUDIO_IF_3_5: + case WM5100_AUDIO_IF_3_6: + case WM5100_AUDIO_IF_3_7: + case WM5100_AUDIO_IF_3_8: + case WM5100_AUDIO_IF_3_9: + case WM5100_AUDIO_IF_3_10: + case WM5100_AUDIO_IF_3_11: + case WM5100_AUDIO_IF_3_18: + case WM5100_AUDIO_IF_3_19: + case WM5100_AUDIO_IF_3_26: + case WM5100_AUDIO_IF_3_27: + case WM5100_PWM1MIX_INPUT_1_SOURCE: + case WM5100_PWM1MIX_INPUT_1_VOLUME: + case WM5100_PWM1MIX_INPUT_2_SOURCE: + case WM5100_PWM1MIX_INPUT_2_VOLUME: + case WM5100_PWM1MIX_INPUT_3_SOURCE: + case WM5100_PWM1MIX_INPUT_3_VOLUME: + case WM5100_PWM1MIX_INPUT_4_SOURCE: + case WM5100_PWM1MIX_INPUT_4_VOLUME: + case WM5100_PWM2MIX_INPUT_1_SOURCE: + case WM5100_PWM2MIX_INPUT_1_VOLUME: + case WM5100_PWM2MIX_INPUT_2_SOURCE: + case WM5100_PWM2MIX_INPUT_2_VOLUME: + case WM5100_PWM2MIX_INPUT_3_SOURCE: + case WM5100_PWM2MIX_INPUT_3_VOLUME: + case WM5100_PWM2MIX_INPUT_4_SOURCE: + case WM5100_PWM2MIX_INPUT_4_VOLUME: + case WM5100_OUT1LMIX_INPUT_1_SOURCE: + case WM5100_OUT1LMIX_INPUT_1_VOLUME: + case WM5100_OUT1LMIX_INPUT_2_SOURCE: + case WM5100_OUT1LMIX_INPUT_2_VOLUME: + case WM5100_OUT1LMIX_INPUT_3_SOURCE: + case WM5100_OUT1LMIX_INPUT_3_VOLUME: + case WM5100_OUT1LMIX_INPUT_4_SOURCE: + case WM5100_OUT1LMIX_INPUT_4_VOLUME: + case WM5100_OUT1RMIX_INPUT_1_SOURCE: + case WM5100_OUT1RMIX_INPUT_1_VOLUME: + case WM5100_OUT1RMIX_INPUT_2_SOURCE: + case WM5100_OUT1RMIX_INPUT_2_VOLUME: + case WM5100_OUT1RMIX_INPUT_3_SOURCE: + case WM5100_OUT1RMIX_INPUT_3_VOLUME: + case WM5100_OUT1RMIX_INPUT_4_SOURCE: + case WM5100_OUT1RMIX_INPUT_4_VOLUME: + case WM5100_OUT2LMIX_INPUT_1_SOURCE: + case WM5100_OUT2LMIX_INPUT_1_VOLUME: + case WM5100_OUT2LMIX_INPUT_2_SOURCE: + case WM5100_OUT2LMIX_INPUT_2_VOLUME: + case WM5100_OUT2LMIX_INPUT_3_SOURCE: + case WM5100_OUT2LMIX_INPUT_3_VOLUME: + case WM5100_OUT2LMIX_INPUT_4_SOURCE: + case WM5100_OUT2LMIX_INPUT_4_VOLUME: + case WM5100_OUT2RMIX_INPUT_1_SOURCE: + case WM5100_OUT2RMIX_INPUT_1_VOLUME: + case WM5100_OUT2RMIX_INPUT_2_SOURCE: + case WM5100_OUT2RMIX_INPUT_2_VOLUME: + case WM5100_OUT2RMIX_INPUT_3_SOURCE: + case WM5100_OUT2RMIX_INPUT_3_VOLUME: + case WM5100_OUT2RMIX_INPUT_4_SOURCE: + case WM5100_OUT2RMIX_INPUT_4_VOLUME: + case WM5100_OUT3LMIX_INPUT_1_SOURCE: + case WM5100_OUT3LMIX_INPUT_1_VOLUME: + case WM5100_OUT3LMIX_INPUT_2_SOURCE: + case WM5100_OUT3LMIX_INPUT_2_VOLUME: + case WM5100_OUT3LMIX_INPUT_3_SOURCE: + case WM5100_OUT3LMIX_INPUT_3_VOLUME: + case WM5100_OUT3LMIX_INPUT_4_SOURCE: + case WM5100_OUT3LMIX_INPUT_4_VOLUME: + case WM5100_OUT3RMIX_INPUT_1_SOURCE: + case WM5100_OUT3RMIX_INPUT_1_VOLUME: + case WM5100_OUT3RMIX_INPUT_2_SOURCE: + case WM5100_OUT3RMIX_INPUT_2_VOLUME: + case WM5100_OUT3RMIX_INPUT_3_SOURCE: + case WM5100_OUT3RMIX_INPUT_3_VOLUME: + case WM5100_OUT3RMIX_INPUT_4_SOURCE: + case WM5100_OUT3RMIX_INPUT_4_VOLUME: + case WM5100_OUT4LMIX_INPUT_1_SOURCE: + case WM5100_OUT4LMIX_INPUT_1_VOLUME: + case WM5100_OUT4LMIX_INPUT_2_SOURCE: + case WM5100_OUT4LMIX_INPUT_2_VOLUME: + case WM5100_OUT4LMIX_INPUT_3_SOURCE: + case WM5100_OUT4LMIX_INPUT_3_VOLUME: + case WM5100_OUT4LMIX_INPUT_4_SOURCE: + case WM5100_OUT4LMIX_INPUT_4_VOLUME: + case WM5100_OUT4RMIX_INPUT_1_SOURCE: + case WM5100_OUT4RMIX_INPUT_1_VOLUME: + case WM5100_OUT4RMIX_INPUT_2_SOURCE: + case WM5100_OUT4RMIX_INPUT_2_VOLUME: + case WM5100_OUT4RMIX_INPUT_3_SOURCE: + case WM5100_OUT4RMIX_INPUT_3_VOLUME: + case WM5100_OUT4RMIX_INPUT_4_SOURCE: + case WM5100_OUT4RMIX_INPUT_4_VOLUME: + case WM5100_OUT5LMIX_INPUT_1_SOURCE: + case WM5100_OUT5LMIX_INPUT_1_VOLUME: + case WM5100_OUT5LMIX_INPUT_2_SOURCE: + case WM5100_OUT5LMIX_INPUT_2_VOLUME: + case WM5100_OUT5LMIX_INPUT_3_SOURCE: + case WM5100_OUT5LMIX_INPUT_3_VOLUME: + case WM5100_OUT5LMIX_INPUT_4_SOURCE: + case WM5100_OUT5LMIX_INPUT_4_VOLUME: + case WM5100_OUT5RMIX_INPUT_1_SOURCE: + case WM5100_OUT5RMIX_INPUT_1_VOLUME: + case WM5100_OUT5RMIX_INPUT_2_SOURCE: + case WM5100_OUT5RMIX_INPUT_2_VOLUME: + case WM5100_OUT5RMIX_INPUT_3_SOURCE: + case WM5100_OUT5RMIX_INPUT_3_VOLUME: + case WM5100_OUT5RMIX_INPUT_4_SOURCE: + case WM5100_OUT5RMIX_INPUT_4_VOLUME: + case WM5100_OUT6LMIX_INPUT_1_SOURCE: + case WM5100_OUT6LMIX_INPUT_1_VOLUME: + case WM5100_OUT6LMIX_INPUT_2_SOURCE: + case WM5100_OUT6LMIX_INPUT_2_VOLUME: + case WM5100_OUT6LMIX_INPUT_3_SOURCE: + case WM5100_OUT6LMIX_INPUT_3_VOLUME: + case WM5100_OUT6LMIX_INPUT_4_SOURCE: + case WM5100_OUT6LMIX_INPUT_4_VOLUME: + case WM5100_OUT6RMIX_INPUT_1_SOURCE: + case WM5100_OUT6RMIX_INPUT_1_VOLUME: + case WM5100_OUT6RMIX_INPUT_2_SOURCE: + case WM5100_OUT6RMIX_INPUT_2_VOLUME: + case WM5100_OUT6RMIX_INPUT_3_SOURCE: + case WM5100_OUT6RMIX_INPUT_3_VOLUME: + case WM5100_OUT6RMIX_INPUT_4_SOURCE: + case WM5100_OUT6RMIX_INPUT_4_VOLUME: + case WM5100_AIF1TX1MIX_INPUT_1_SOURCE: + case WM5100_AIF1TX1MIX_INPUT_1_VOLUME: + case WM5100_AIF1TX1MIX_INPUT_2_SOURCE: + case WM5100_AIF1TX1MIX_INPUT_2_VOLUME: + case WM5100_AIF1TX1MIX_INPUT_3_SOURCE: + case WM5100_AIF1TX1MIX_INPUT_3_VOLUME: + case WM5100_AIF1TX1MIX_INPUT_4_SOURCE: + case WM5100_AIF1TX1MIX_INPUT_4_VOLUME: + case WM5100_AIF1TX2MIX_INPUT_1_SOURCE: + case WM5100_AIF1TX2MIX_INPUT_1_VOLUME: + case WM5100_AIF1TX2MIX_INPUT_2_SOURCE: + case WM5100_AIF1TX2MIX_INPUT_2_VOLUME: + case WM5100_AIF1TX2MIX_INPUT_3_SOURCE: + case WM5100_AIF1TX2MIX_INPUT_3_VOLUME: + case WM5100_AIF1TX2MIX_INPUT_4_SOURCE: + case WM5100_AIF1TX2MIX_INPUT_4_VOLUME: + case WM5100_AIF1TX3MIX_INPUT_1_SOURCE: + case WM5100_AIF1TX3MIX_INPUT_1_VOLUME: + case WM5100_AIF1TX3MIX_INPUT_2_SOURCE: + case WM5100_AIF1TX3MIX_INPUT_2_VOLUME: + case WM5100_AIF1TX3MIX_INPUT_3_SOURCE: + case WM5100_AIF1TX3MIX_INPUT_3_VOLUME: + case WM5100_AIF1TX3MIX_INPUT_4_SOURCE: + case WM5100_AIF1TX3MIX_INPUT_4_VOLUME: + case WM5100_AIF1TX4MIX_INPUT_1_SOURCE: + case WM5100_AIF1TX4MIX_INPUT_1_VOLUME: + case WM5100_AIF1TX4MIX_INPUT_2_SOURCE: + case WM5100_AIF1TX4MIX_INPUT_2_VOLUME: + case WM5100_AIF1TX4MIX_INPUT_3_SOURCE: + case WM5100_AIF1TX4MIX_INPUT_3_VOLUME: + case WM5100_AIF1TX4MIX_INPUT_4_SOURCE: + case WM5100_AIF1TX4MIX_INPUT_4_VOLUME: + case WM5100_AIF1TX5MIX_INPUT_1_SOURCE: + case WM5100_AIF1TX5MIX_INPUT_1_VOLUME: + case WM5100_AIF1TX5MIX_INPUT_2_SOURCE: + case WM5100_AIF1TX5MIX_INPUT_2_VOLUME: + case WM5100_AIF1TX5MIX_INPUT_3_SOURCE: + case WM5100_AIF1TX5MIX_INPUT_3_VOLUME: + case WM5100_AIF1TX5MIX_INPUT_4_SOURCE: + case WM5100_AIF1TX5MIX_INPUT_4_VOLUME: + case WM5100_AIF1TX6MIX_INPUT_1_SOURCE: + case WM5100_AIF1TX6MIX_INPUT_1_VOLUME: + case WM5100_AIF1TX6MIX_INPUT_2_SOURCE: + case WM5100_AIF1TX6MIX_INPUT_2_VOLUME: + case WM5100_AIF1TX6MIX_INPUT_3_SOURCE: + case WM5100_AIF1TX6MIX_INPUT_3_VOLUME: + case WM5100_AIF1TX6MIX_INPUT_4_SOURCE: + case WM5100_AIF1TX6MIX_INPUT_4_VOLUME: + case WM5100_AIF1TX7MIX_INPUT_1_SOURCE: + case WM5100_AIF1TX7MIX_INPUT_1_VOLUME: + case WM5100_AIF1TX7MIX_INPUT_2_SOURCE: + case WM5100_AIF1TX7MIX_INPUT_2_VOLUME: + case WM5100_AIF1TX7MIX_INPUT_3_SOURCE: + case WM5100_AIF1TX7MIX_INPUT_3_VOLUME: + case WM5100_AIF1TX7MIX_INPUT_4_SOURCE: + case WM5100_AIF1TX7MIX_INPUT_4_VOLUME: + case WM5100_AIF1TX8MIX_INPUT_1_SOURCE: + case WM5100_AIF1TX8MIX_INPUT_1_VOLUME: + case WM5100_AIF1TX8MIX_INPUT_2_SOURCE: + case WM5100_AIF1TX8MIX_INPUT_2_VOLUME: + case WM5100_AIF1TX8MIX_INPUT_3_SOURCE: + case WM5100_AIF1TX8MIX_INPUT_3_VOLUME: + case WM5100_AIF1TX8MIX_INPUT_4_SOURCE: + case WM5100_AIF1TX8MIX_INPUT_4_VOLUME: + case WM5100_AIF2TX1MIX_INPUT_1_SOURCE: + case WM5100_AIF2TX1MIX_INPUT_1_VOLUME: + case WM5100_AIF2TX1MIX_INPUT_2_SOURCE: + case WM5100_AIF2TX1MIX_INPUT_2_VOLUME: + case WM5100_AIF2TX1MIX_INPUT_3_SOURCE: + case WM5100_AIF2TX1MIX_INPUT_3_VOLUME: + case WM5100_AIF2TX1MIX_INPUT_4_SOURCE: + case WM5100_AIF2TX1MIX_INPUT_4_VOLUME: + case WM5100_AIF2TX2MIX_INPUT_1_SOURCE: + case WM5100_AIF2TX2MIX_INPUT_1_VOLUME: + case WM5100_AIF2TX2MIX_INPUT_2_SOURCE: + case WM5100_AIF2TX2MIX_INPUT_2_VOLUME: + case WM5100_AIF2TX2MIX_INPUT_3_SOURCE: + case WM5100_AIF2TX2MIX_INPUT_3_VOLUME: + case WM5100_AIF2TX2MIX_INPUT_4_SOURCE: + case WM5100_AIF2TX2MIX_INPUT_4_VOLUME: + case WM5100_AIF3TX1MIX_INPUT_1_SOURCE: + case WM5100_AIF3TX1MIX_INPUT_1_VOLUME: + case WM5100_AIF3TX1MIX_INPUT_2_SOURCE: + case WM5100_AIF3TX1MIX_INPUT_2_VOLUME: + case WM5100_AIF3TX1MIX_INPUT_3_SOURCE: + case WM5100_AIF3TX1MIX_INPUT_3_VOLUME: + case WM5100_AIF3TX1MIX_INPUT_4_SOURCE: + case WM5100_AIF3TX1MIX_INPUT_4_VOLUME: + case WM5100_AIF3TX2MIX_INPUT_1_SOURCE: + case WM5100_AIF3TX2MIX_INPUT_1_VOLUME: + case WM5100_AIF3TX2MIX_INPUT_2_SOURCE: + case WM5100_AIF3TX2MIX_INPUT_2_VOLUME: + case WM5100_AIF3TX2MIX_INPUT_3_SOURCE: + case WM5100_AIF3TX2MIX_INPUT_3_VOLUME: + case WM5100_AIF3TX2MIX_INPUT_4_SOURCE: + case WM5100_AIF3TX2MIX_INPUT_4_VOLUME: + case WM5100_EQ1MIX_INPUT_1_SOURCE: + case WM5100_EQ1MIX_INPUT_1_VOLUME: + case WM5100_EQ1MIX_INPUT_2_SOURCE: + case WM5100_EQ1MIX_INPUT_2_VOLUME: + case WM5100_EQ1MIX_INPUT_3_SOURCE: + case WM5100_EQ1MIX_INPUT_3_VOLUME: + case WM5100_EQ1MIX_INPUT_4_SOURCE: + case WM5100_EQ1MIX_INPUT_4_VOLUME: + case WM5100_EQ2MIX_INPUT_1_SOURCE: + case WM5100_EQ2MIX_INPUT_1_VOLUME: + case WM5100_EQ2MIX_INPUT_2_SOURCE: + case WM5100_EQ2MIX_INPUT_2_VOLUME: + case WM5100_EQ2MIX_INPUT_3_SOURCE: + case WM5100_EQ2MIX_INPUT_3_VOLUME: + case WM5100_EQ2MIX_INPUT_4_SOURCE: + case WM5100_EQ2MIX_INPUT_4_VOLUME: + case WM5100_EQ3MIX_INPUT_1_SOURCE: + case WM5100_EQ3MIX_INPUT_1_VOLUME: + case WM5100_EQ3MIX_INPUT_2_SOURCE: + case WM5100_EQ3MIX_INPUT_2_VOLUME: + case WM5100_EQ3MIX_INPUT_3_SOURCE: + case WM5100_EQ3MIX_INPUT_3_VOLUME: + case WM5100_EQ3MIX_INPUT_4_SOURCE: + case WM5100_EQ3MIX_INPUT_4_VOLUME: + case WM5100_EQ4MIX_INPUT_1_SOURCE: + case WM5100_EQ4MIX_INPUT_1_VOLUME: + case WM5100_EQ4MIX_INPUT_2_SOURCE: + case WM5100_EQ4MIX_INPUT_2_VOLUME: + case WM5100_EQ4MIX_INPUT_3_SOURCE: + case WM5100_EQ4MIX_INPUT_3_VOLUME: + case WM5100_EQ4MIX_INPUT_4_SOURCE: + case WM5100_EQ4MIX_INPUT_4_VOLUME: + case WM5100_DRC1LMIX_INPUT_1_SOURCE: + case WM5100_DRC1LMIX_INPUT_1_VOLUME: + case WM5100_DRC1LMIX_INPUT_2_SOURCE: + case WM5100_DRC1LMIX_INPUT_2_VOLUME: + case WM5100_DRC1LMIX_INPUT_3_SOURCE: + case WM5100_DRC1LMIX_INPUT_3_VOLUME: + case WM5100_DRC1LMIX_INPUT_4_SOURCE: + case WM5100_DRC1LMIX_INPUT_4_VOLUME: + case WM5100_DRC1RMIX_INPUT_1_SOURCE: + case WM5100_DRC1RMIX_INPUT_1_VOLUME: + case WM5100_DRC1RMIX_INPUT_2_SOURCE: + case WM5100_DRC1RMIX_INPUT_2_VOLUME: + case WM5100_DRC1RMIX_INPUT_3_SOURCE: + case WM5100_DRC1RMIX_INPUT_3_VOLUME: + case WM5100_DRC1RMIX_INPUT_4_SOURCE: + case WM5100_DRC1RMIX_INPUT_4_VOLUME: + case WM5100_HPLP1MIX_INPUT_1_SOURCE: + case WM5100_HPLP1MIX_INPUT_1_VOLUME: + case WM5100_HPLP1MIX_INPUT_2_SOURCE: + case WM5100_HPLP1MIX_INPUT_2_VOLUME: + case WM5100_HPLP1MIX_INPUT_3_SOURCE: + case WM5100_HPLP1MIX_INPUT_3_VOLUME: + case WM5100_HPLP1MIX_INPUT_4_SOURCE: + case WM5100_HPLP1MIX_INPUT_4_VOLUME: + case WM5100_HPLP2MIX_INPUT_1_SOURCE: + case WM5100_HPLP2MIX_INPUT_1_VOLUME: + case WM5100_HPLP2MIX_INPUT_2_SOURCE: + case WM5100_HPLP2MIX_INPUT_2_VOLUME: + case WM5100_HPLP2MIX_INPUT_3_SOURCE: + case WM5100_HPLP2MIX_INPUT_3_VOLUME: + case WM5100_HPLP2MIX_INPUT_4_SOURCE: + case WM5100_HPLP2MIX_INPUT_4_VOLUME: + case WM5100_HPLP3MIX_INPUT_1_SOURCE: + case WM5100_HPLP3MIX_INPUT_1_VOLUME: + case WM5100_HPLP3MIX_INPUT_2_SOURCE: + case WM5100_HPLP3MIX_INPUT_2_VOLUME: + case WM5100_HPLP3MIX_INPUT_3_SOURCE: + case WM5100_HPLP3MIX_INPUT_3_VOLUME: + case WM5100_HPLP3MIX_INPUT_4_SOURCE: + case WM5100_HPLP3MIX_INPUT_4_VOLUME: + case WM5100_HPLP4MIX_INPUT_1_SOURCE: + case WM5100_HPLP4MIX_INPUT_1_VOLUME: + case WM5100_HPLP4MIX_INPUT_2_SOURCE: + case WM5100_HPLP4MIX_INPUT_2_VOLUME: + case WM5100_HPLP4MIX_INPUT_3_SOURCE: + case WM5100_HPLP4MIX_INPUT_3_VOLUME: + case WM5100_HPLP4MIX_INPUT_4_SOURCE: + case WM5100_HPLP4MIX_INPUT_4_VOLUME: + case WM5100_DSP1LMIX_INPUT_1_SOURCE: + case WM5100_DSP1LMIX_INPUT_1_VOLUME: + case WM5100_DSP1LMIX_INPUT_2_SOURCE: + case WM5100_DSP1LMIX_INPUT_2_VOLUME: + case WM5100_DSP1LMIX_INPUT_3_SOURCE: + case WM5100_DSP1LMIX_INPUT_3_VOLUME: + case WM5100_DSP1LMIX_INPUT_4_SOURCE: + case WM5100_DSP1LMIX_INPUT_4_VOLUME: + case WM5100_DSP1RMIX_INPUT_1_SOURCE: + case WM5100_DSP1RMIX_INPUT_1_VOLUME: + case WM5100_DSP1RMIX_INPUT_2_SOURCE: + case WM5100_DSP1RMIX_INPUT_2_VOLUME: + case WM5100_DSP1RMIX_INPUT_3_SOURCE: + case WM5100_DSP1RMIX_INPUT_3_VOLUME: + case WM5100_DSP1RMIX_INPUT_4_SOURCE: + case WM5100_DSP1RMIX_INPUT_4_VOLUME: + case WM5100_DSP1AUX1MIX_INPUT_1_SOURCE: + case WM5100_DSP1AUX2MIX_INPUT_1_SOURCE: + case WM5100_DSP1AUX3MIX_INPUT_1_SOURCE: + case WM5100_DSP1AUX4MIX_INPUT_1_SOURCE: + case WM5100_DSP1AUX5MIX_INPUT_1_SOURCE: + case WM5100_DSP1AUX6MIX_INPUT_1_SOURCE: + case WM5100_DSP2LMIX_INPUT_1_SOURCE: + case WM5100_DSP2LMIX_INPUT_1_VOLUME: + case WM5100_DSP2LMIX_INPUT_2_SOURCE: + case WM5100_DSP2LMIX_INPUT_2_VOLUME: + case WM5100_DSP2LMIX_INPUT_3_SOURCE: + case WM5100_DSP2LMIX_INPUT_3_VOLUME: + case WM5100_DSP2LMIX_INPUT_4_SOURCE: + case WM5100_DSP2LMIX_INPUT_4_VOLUME: + case WM5100_DSP2RMIX_INPUT_1_SOURCE: + case WM5100_DSP2RMIX_INPUT_1_VOLUME: + case WM5100_DSP2RMIX_INPUT_2_SOURCE: + case WM5100_DSP2RMIX_INPUT_2_VOLUME: + case WM5100_DSP2RMIX_INPUT_3_SOURCE: + case WM5100_DSP2RMIX_INPUT_3_VOLUME: + case WM5100_DSP2RMIX_INPUT_4_SOURCE: + case WM5100_DSP2RMIX_INPUT_4_VOLUME: + case WM5100_DSP2AUX1MIX_INPUT_1_SOURCE: + case WM5100_DSP2AUX2MIX_INPUT_1_SOURCE: + case WM5100_DSP2AUX3MIX_INPUT_1_SOURCE: + case WM5100_DSP2AUX4MIX_INPUT_1_SOURCE: + case WM5100_DSP2AUX5MIX_INPUT_1_SOURCE: + case WM5100_DSP2AUX6MIX_INPUT_1_SOURCE: + case WM5100_DSP3LMIX_INPUT_1_SOURCE: + case WM5100_DSP3LMIX_INPUT_1_VOLUME: + case WM5100_DSP3LMIX_INPUT_2_SOURCE: + case WM5100_DSP3LMIX_INPUT_2_VOLUME: + case WM5100_DSP3LMIX_INPUT_3_SOURCE: + case WM5100_DSP3LMIX_INPUT_3_VOLUME: + case WM5100_DSP3LMIX_INPUT_4_SOURCE: + case WM5100_DSP3LMIX_INPUT_4_VOLUME: + case WM5100_DSP3RMIX_INPUT_1_SOURCE: + case WM5100_DSP3RMIX_INPUT_1_VOLUME: + case WM5100_DSP3RMIX_INPUT_2_SOURCE: + case WM5100_DSP3RMIX_INPUT_2_VOLUME: + case WM5100_DSP3RMIX_INPUT_3_SOURCE: + case WM5100_DSP3RMIX_INPUT_3_VOLUME: + case WM5100_DSP3RMIX_INPUT_4_SOURCE: + case WM5100_DSP3RMIX_INPUT_4_VOLUME: + case WM5100_DSP3AUX1MIX_INPUT_1_SOURCE: + case WM5100_DSP3AUX2MIX_INPUT_1_SOURCE: + case WM5100_DSP3AUX3MIX_INPUT_1_SOURCE: + case WM5100_DSP3AUX4MIX_INPUT_1_SOURCE: + case WM5100_DSP3AUX5MIX_INPUT_1_SOURCE: + case WM5100_DSP3AUX6MIX_INPUT_1_SOURCE: + case WM5100_ASRC1LMIX_INPUT_1_SOURCE: + case WM5100_ASRC1RMIX_INPUT_1_SOURCE: + case WM5100_ASRC2LMIX_INPUT_1_SOURCE: + case WM5100_ASRC2RMIX_INPUT_1_SOURCE: + case WM5100_ISRC1DEC1MIX_INPUT_1_SOURCE: + case WM5100_ISRC1DEC2MIX_INPUT_1_SOURCE: + case WM5100_ISRC1DEC3MIX_INPUT_1_SOURCE: + case WM5100_ISRC1DEC4MIX_INPUT_1_SOURCE: + case WM5100_ISRC1INT1MIX_INPUT_1_SOURCE: + case WM5100_ISRC1INT2MIX_INPUT_1_SOURCE: + case WM5100_ISRC1INT3MIX_INPUT_1_SOURCE: + case WM5100_ISRC1INT4MIX_INPUT_1_SOURCE: + case WM5100_ISRC2DEC1MIX_INPUT_1_SOURCE: + case WM5100_ISRC2DEC2MIX_INPUT_1_SOURCE: + case WM5100_ISRC2DEC3MIX_INPUT_1_SOURCE: + case WM5100_ISRC2DEC4MIX_INPUT_1_SOURCE: + case WM5100_ISRC2INT1MIX_INPUT_1_SOURCE: + case WM5100_ISRC2INT2MIX_INPUT_1_SOURCE: + case WM5100_ISRC2INT3MIX_INPUT_1_SOURCE: + case WM5100_ISRC2INT4MIX_INPUT_1_SOURCE: + case WM5100_GPIO_CTRL_1: + case WM5100_GPIO_CTRL_2: + case WM5100_GPIO_CTRL_3: + case WM5100_GPIO_CTRL_4: + case WM5100_GPIO_CTRL_5: + case WM5100_GPIO_CTRL_6: + case WM5100_MISC_PAD_CTRL_1: + case WM5100_MISC_PAD_CTRL_2: + case WM5100_MISC_PAD_CTRL_3: + case WM5100_MISC_PAD_CTRL_4: + case WM5100_MISC_PAD_CTRL_5: + case WM5100_MISC_GPIO_1: + case WM5100_INTERRUPT_STATUS_1: + case WM5100_INTERRUPT_STATUS_2: + case WM5100_INTERRUPT_STATUS_3: + case WM5100_INTERRUPT_STATUS_4: + case WM5100_INTERRUPT_RAW_STATUS_2: + case WM5100_INTERRUPT_RAW_STATUS_3: + case WM5100_INTERRUPT_RAW_STATUS_4: + case WM5100_INTERRUPT_STATUS_1_MASK: + case WM5100_INTERRUPT_STATUS_2_MASK: + case WM5100_INTERRUPT_STATUS_3_MASK: + case WM5100_INTERRUPT_STATUS_4_MASK: + case WM5100_INTERRUPT_CONTROL: + case WM5100_IRQ_DEBOUNCE_1: + case WM5100_IRQ_DEBOUNCE_2: + case WM5100_FX_CTRL: + case WM5100_EQ1_1: + case WM5100_EQ1_2: + case WM5100_EQ1_3: + case WM5100_EQ1_4: + case WM5100_EQ1_5: + case WM5100_EQ1_6: + case WM5100_EQ1_7: + case WM5100_EQ1_8: + case WM5100_EQ1_9: + case WM5100_EQ1_10: + case WM5100_EQ1_11: + case WM5100_EQ1_12: + case WM5100_EQ1_13: + case WM5100_EQ1_14: + case WM5100_EQ1_15: + case WM5100_EQ1_16: + case WM5100_EQ1_17: + case WM5100_EQ1_18: + case WM5100_EQ1_19: + case WM5100_EQ1_20: + case WM5100_EQ2_1: + case WM5100_EQ2_2: + case WM5100_EQ2_3: + case WM5100_EQ2_4: + case WM5100_EQ2_5: + case WM5100_EQ2_6: + case WM5100_EQ2_7: + case WM5100_EQ2_8: + case WM5100_EQ2_9: + case WM5100_EQ2_10: + case WM5100_EQ2_11: + case WM5100_EQ2_12: + case WM5100_EQ2_13: + case WM5100_EQ2_14: + case WM5100_EQ2_15: + case WM5100_EQ2_16: + case WM5100_EQ2_17: + case WM5100_EQ2_18: + case WM5100_EQ2_19: + case WM5100_EQ2_20: + case WM5100_EQ3_1: + case WM5100_EQ3_2: + case WM5100_EQ3_3: + case WM5100_EQ3_4: + case WM5100_EQ3_5: + case WM5100_EQ3_6: + case WM5100_EQ3_7: + case WM5100_EQ3_8: + case WM5100_EQ3_9: + case WM5100_EQ3_10: + case WM5100_EQ3_11: + case WM5100_EQ3_12: + case WM5100_EQ3_13: + case WM5100_EQ3_14: + case WM5100_EQ3_15: + case WM5100_EQ3_16: + case WM5100_EQ3_17: + case WM5100_EQ3_18: + case WM5100_EQ3_19: + case WM5100_EQ3_20: + case WM5100_EQ4_1: + case WM5100_EQ4_2: + case WM5100_EQ4_3: + case WM5100_EQ4_4: + case WM5100_EQ4_5: + case WM5100_EQ4_6: + case WM5100_EQ4_7: + case WM5100_EQ4_8: + case WM5100_EQ4_9: + case WM5100_EQ4_10: + case WM5100_EQ4_11: + case WM5100_EQ4_12: + case WM5100_EQ4_13: + case WM5100_EQ4_14: + case WM5100_EQ4_15: + case WM5100_EQ4_16: + case WM5100_EQ4_17: + case WM5100_EQ4_18: + case WM5100_EQ4_19: + case WM5100_EQ4_20: + case WM5100_DRC1_CTRL1: + case WM5100_DRC1_CTRL2: + case WM5100_DRC1_CTRL3: + case WM5100_DRC1_CTRL4: + case WM5100_DRC1_CTRL5: + case WM5100_HPLPF1_1: + case WM5100_HPLPF1_2: + case WM5100_HPLPF2_1: + case WM5100_HPLPF2_2: + case WM5100_HPLPF3_1: + case WM5100_HPLPF3_2: + case WM5100_HPLPF4_1: + case WM5100_HPLPF4_2: + case WM5100_DSP1_DM_0: + case WM5100_DSP1_DM_1: + case WM5100_DSP1_DM_2: + case WM5100_DSP1_DM_3: + case WM5100_DSP1_DM_508: + case WM5100_DSP1_DM_509: + case WM5100_DSP1_DM_510: + case WM5100_DSP1_DM_511: + case WM5100_DSP1_PM_0: + case WM5100_DSP1_PM_1: + case WM5100_DSP1_PM_2: + case WM5100_DSP1_PM_3: + case WM5100_DSP1_PM_4: + case WM5100_DSP1_PM_5: + case WM5100_DSP1_PM_1530: + case WM5100_DSP1_PM_1531: + case WM5100_DSP1_PM_1532: + case WM5100_DSP1_PM_1533: + case WM5100_DSP1_PM_1534: + case WM5100_DSP1_PM_1535: + case WM5100_DSP1_ZM_0: + case WM5100_DSP1_ZM_1: + case WM5100_DSP1_ZM_2: + case WM5100_DSP1_ZM_3: + case WM5100_DSP1_ZM_2044: + case WM5100_DSP1_ZM_2045: + case WM5100_DSP1_ZM_2046: + case WM5100_DSP1_ZM_2047: + case WM5100_DSP2_DM_0: + case WM5100_DSP2_DM_1: + case WM5100_DSP2_DM_2: + case WM5100_DSP2_DM_3: + case WM5100_DSP2_DM_508: + case WM5100_DSP2_DM_509: + case WM5100_DSP2_DM_510: + case WM5100_DSP2_DM_511: + case WM5100_DSP2_PM_0: + case WM5100_DSP2_PM_1: + case WM5100_DSP2_PM_2: + case WM5100_DSP2_PM_3: + case WM5100_DSP2_PM_4: + case WM5100_DSP2_PM_5: + case WM5100_DSP2_PM_1530: + case WM5100_DSP2_PM_1531: + case WM5100_DSP2_PM_1532: + case WM5100_DSP2_PM_1533: + case WM5100_DSP2_PM_1534: + case WM5100_DSP2_PM_1535: + case WM5100_DSP2_ZM_0: + case WM5100_DSP2_ZM_1: + case WM5100_DSP2_ZM_2: + case WM5100_DSP2_ZM_3: + case WM5100_DSP2_ZM_2044: + case WM5100_DSP2_ZM_2045: + case WM5100_DSP2_ZM_2046: + case WM5100_DSP2_ZM_2047: + case WM5100_DSP3_DM_0: + case WM5100_DSP3_DM_1: + case WM5100_DSP3_DM_2: + case WM5100_DSP3_DM_3: + case WM5100_DSP3_DM_508: + case WM5100_DSP3_DM_509: + case WM5100_DSP3_DM_510: + case WM5100_DSP3_DM_511: + case WM5100_DSP3_PM_0: + case WM5100_DSP3_PM_1: + case WM5100_DSP3_PM_2: + case WM5100_DSP3_PM_3: + case WM5100_DSP3_PM_4: + case WM5100_DSP3_PM_5: + case WM5100_DSP3_PM_1530: + case WM5100_DSP3_PM_1531: + case WM5100_DSP3_PM_1532: + case WM5100_DSP3_PM_1533: + case WM5100_DSP3_PM_1534: + case WM5100_DSP3_PM_1535: + case WM5100_DSP3_ZM_0: + case WM5100_DSP3_ZM_1: + case WM5100_DSP3_ZM_2: + case WM5100_DSP3_ZM_3: + case WM5100_DSP3_ZM_2044: + case WM5100_DSP3_ZM_2045: + case WM5100_DSP3_ZM_2046: + case WM5100_DSP3_ZM_2047: + return 1; + default: + return 0; + } +} + +u16 wm5100_reg_defaults[WM5100_MAX_REGISTER + 1] = { + [0x0000] = 0x0000, /* R0 - software reset */ + [0x0001] = 0x0000, /* R1 - Device Revision */ + [0x0010] = 0x0801, /* R16 - Ctrl IF 1 */ + [0x0020] = 0x0000, /* R32 - Tone Generator 1 */ + [0x0030] = 0x0000, /* R48 - PWM Drive 1 */ + [0x0031] = 0x0100, /* R49 - PWM Drive 2 */ + [0x0032] = 0x0100, /* R50 - PWM Drive 3 */ + [0x0100] = 0x0002, /* R256 - Clocking 1 */ + [0x0101] = 0x0000, /* R257 - Clocking 3 */ + [0x0102] = 0x0011, /* R258 - Clocking 4 */ + [0x0103] = 0x0011, /* R259 - Clocking 5 */ + [0x0104] = 0x0011, /* R260 - Clocking 6 */ + [0x0107] = 0x0000, /* R263 - Clocking 7 */ + [0x0108] = 0x0000, /* R264 - Clocking 8 */ + [0x0120] = 0x0000, /* R288 - ASRC_ENABLE */ + [0x0121] = 0x0000, /* R289 - ASRC_STATUS */ + [0x0122] = 0x0000, /* R290 - ASRC_RATE1 */ + [0x0141] = 0x8000, /* R321 - ISRC 1 CTRL 1 */ + [0x0142] = 0x0000, /* R322 - ISRC 1 CTRL 2 */ + [0x0143] = 0x8000, /* R323 - ISRC 2 CTRL1 */ + [0x0144] = 0x0000, /* R324 - ISRC 2 CTRL 2 */ + [0x0182] = 0x0000, /* R386 - FLL1 Control 1 */ + [0x0183] = 0x0000, /* R387 - FLL1 Control 2 */ + [0x0184] = 0x0000, /* R388 - FLL1 Control 3 */ + [0x0186] = 0x0177, /* R390 - FLL1 Control 5 */ + [0x0187] = 0x0001, /* R391 - FLL1 Control 6 */ + [0x0188] = 0x0000, /* R392 - FLL1 EFS 1 */ + [0x01A2] = 0x0000, /* R418 - FLL2 Control 1 */ + [0x01A3] = 0x0000, /* R419 - FLL2 Control 2 */ + [0x01A4] = 0x0000, /* R420 - FLL2 Control 3 */ + [0x01A6] = 0x0177, /* R422 - FLL2 Control 5 */ + [0x01A7] = 0x0001, /* R423 - FLL2 Control 6 */ + [0x01A8] = 0x0000, /* R424 - FLL2 EFS 1 */ + [0x0200] = 0x0020, /* R512 - Mic Charge Pump 1 */ + [0x0201] = 0xB084, /* R513 - Mic Charge Pump 2 */ + [0x0202] = 0xBBDE, /* R514 - HP Charge Pump 1 */ + [0x0211] = 0x20D4, /* R529 - LDO1 Control */ + [0x0215] = 0x0062, /* R533 - Mic Bias Ctrl 1 */ + [0x0216] = 0x0062, /* R534 - Mic Bias Ctrl 2 */ + [0x0217] = 0x0062, /* R535 - Mic Bias Ctrl 3 */ + [0x0280] = 0x0004, /* R640 - Accessory Detect Mode 1 */ + [0x0288] = 0x0020, /* R648 - Headphone Detect 1 */ + [0x0289] = 0x0000, /* R649 - Headphone Detect 2 */ + [0x0290] = 0x1100, /* R656 - Mic Detect 1 */ + [0x0291] = 0x009F, /* R657 - Mic Detect 2 */ + [0x0292] = 0x0000, /* R658 - Mic Detect 3 */ + [0x0301] = 0x0000, /* R769 - Input Enables */ + [0x0302] = 0x0000, /* R770 - Input Enables Status */ + [0x0310] = 0x2280, /* R784 - Status */ + [0x0311] = 0x0080, /* R785 - IN1R Control */ + [0x0312] = 0x2280, /* R786 - IN2L Control */ + [0x0313] = 0x0080, /* R787 - IN2R Control */ + [0x0314] = 0x2280, /* R788 - IN3L Control */ + [0x0315] = 0x0080, /* R789 - IN3R Control */ + [0x0316] = 0x2280, /* R790 - IN4L Control */ + [0x0317] = 0x0080, /* R791 - IN4R Control */ + [0x0318] = 0x0000, /* R792 - RXANC_SRC */ + [0x0319] = 0x0022, /* R793 - Input Volume Ramp */ + [0x0320] = 0x0180, /* R800 - ADC Digital Volume 1L */ + [0x0321] = 0x0180, /* R801 - ADC Digital Volume 1R */ + [0x0322] = 0x0180, /* R802 - ADC Digital Volume 2L */ + [0x0323] = 0x0180, /* R803 - ADC Digital Volume 2R */ + [0x0324] = 0x0180, /* R804 - ADC Digital Volume 3L */ + [0x0325] = 0x0180, /* R805 - ADC Digital Volume 3R */ + [0x0326] = 0x0180, /* R806 - ADC Digital Volume 4L */ + [0x0327] = 0x0180, /* R807 - ADC Digital Volume 4R */ + [0x0401] = 0x0000, /* R1025 - Output Enables 2 */ + [0x0402] = 0x0000, /* R1026 - Output Status 1 */ + [0x0403] = 0x0000, /* R1027 - Output Status 2 */ + [0x0408] = 0x0000, /* R1032 - Channel Enables 1 */ + [0x0410] = 0x0080, /* R1040 - Out Volume 1L */ + [0x0411] = 0x0080, /* R1041 - Out Volume 1R */ + [0x0412] = 0x0080, /* R1042 - DAC Volume Limit 1L */ + [0x0413] = 0x0080, /* R1043 - DAC Volume Limit 1R */ + [0x0414] = 0x0080, /* R1044 - Out Volume 2L */ + [0x0415] = 0x0080, /* R1045 - Out Volume 2R */ + [0x0416] = 0x0080, /* R1046 - DAC Volume Limit 2L */ + [0x0417] = 0x0080, /* R1047 - DAC Volume Limit 2R */ + [0x0418] = 0x0080, /* R1048 - Out Volume 3L */ + [0x0419] = 0x0080, /* R1049 - Out Volume 3R */ + [0x041A] = 0x0080, /* R1050 - DAC Volume Limit 3L */ + [0x041B] = 0x0080, /* R1051 - DAC Volume Limit 3R */ + [0x041C] = 0x0080, /* R1052 - Out Volume 4L */ + [0x041D] = 0x0080, /* R1053 - Out Volume 4R */ + [0x041E] = 0x0080, /* R1054 - DAC Volume Limit 5L */ + [0x041F] = 0x0080, /* R1055 - DAC Volume Limit 5R */ + [0x0420] = 0x0080, /* R1056 - DAC Volume Limit 6L */ + [0x0421] = 0x0080, /* R1057 - DAC Volume Limit 6R */ + [0x0440] = 0x0000, /* R1088 - DAC AEC Control 1 */ + [0x0441] = 0x0022, /* R1089 - Output Volume Ramp */ + [0x0480] = 0x0180, /* R1152 - DAC Digital Volume 1L */ + [0x0481] = 0x0180, /* R1153 - DAC Digital Volume 1R */ + [0x0482] = 0x0180, /* R1154 - DAC Digital Volume 2L */ + [0x0483] = 0x0180, /* R1155 - DAC Digital Volume 2R */ + [0x0484] = 0x0180, /* R1156 - DAC Digital Volume 3L */ + [0x0485] = 0x0180, /* R1157 - DAC Digital Volume 3R */ + [0x0486] = 0x0180, /* R1158 - DAC Digital Volume 4L */ + [0x0487] = 0x0180, /* R1159 - DAC Digital Volume 4R */ + [0x0488] = 0x0180, /* R1160 - DAC Digital Volume 5L */ + [0x0489] = 0x0180, /* R1161 - DAC Digital Volume 5R */ + [0x048A] = 0x0180, /* R1162 - DAC Digital Volume 6L */ + [0x048B] = 0x0180, /* R1163 - DAC Digital Volume 6R */ + [0x04C0] = 0x0069, /* R1216 - PDM SPK1 CTRL 1 */ + [0x04C1] = 0x0000, /* R1217 - PDM SPK1 CTRL 2 */ + [0x04C2] = 0x0069, /* R1218 - PDM SPK2 CTRL 1 */ + [0x04C3] = 0x0000, /* R1219 - PDM SPK2 CTRL 2 */ + [0x0500] = 0x000C, /* R1280 - Audio IF 1_1 */ + [0x0501] = 0x0008, /* R1281 - Audio IF 1_2 */ + [0x0502] = 0x0000, /* R1282 - Audio IF 1_3 */ + [0x0503] = 0x0000, /* R1283 - Audio IF 1_4 */ + [0x0504] = 0x0000, /* R1284 - Audio IF 1_5 */ + [0x0505] = 0x0300, /* R1285 - Audio IF 1_6 */ + [0x0506] = 0x0300, /* R1286 - Audio IF 1_7 */ + [0x0507] = 0x1820, /* R1287 - Audio IF 1_8 */ + [0x0508] = 0x1820, /* R1288 - Audio IF 1_9 */ + [0x0509] = 0x0000, /* R1289 - Audio IF 1_10 */ + [0x050A] = 0x0001, /* R1290 - Audio IF 1_11 */ + [0x050B] = 0x0002, /* R1291 - Audio IF 1_12 */ + [0x050C] = 0x0003, /* R1292 - Audio IF 1_13 */ + [0x050D] = 0x0004, /* R1293 - Audio IF 1_14 */ + [0x050E] = 0x0005, /* R1294 - Audio IF 1_15 */ + [0x050F] = 0x0006, /* R1295 - Audio IF 1_16 */ + [0x0510] = 0x0007, /* R1296 - Audio IF 1_17 */ + [0x0511] = 0x0000, /* R1297 - Audio IF 1_18 */ + [0x0512] = 0x0001, /* R1298 - Audio IF 1_19 */ + [0x0513] = 0x0002, /* R1299 - Audio IF 1_20 */ + [0x0514] = 0x0003, /* R1300 - Audio IF 1_21 */ + [0x0515] = 0x0004, /* R1301 - Audio IF 1_22 */ + [0x0516] = 0x0005, /* R1302 - Audio IF 1_23 */ + [0x0517] = 0x0006, /* R1303 - Audio IF 1_24 */ + [0x0518] = 0x0007, /* R1304 - Audio IF 1_25 */ + [0x0519] = 0x0000, /* R1305 - Audio IF 1_26 */ + [0x051A] = 0x0000, /* R1306 - Audio IF 1_27 */ + [0x0540] = 0x000C, /* R1344 - Audio IF 2_1 */ + [0x0541] = 0x0008, /* R1345 - Audio IF 2_2 */ + [0x0542] = 0x0000, /* R1346 - Audio IF 2_3 */ + [0x0543] = 0x0000, /* R1347 - Audio IF 2_4 */ + [0x0544] = 0x0000, /* R1348 - Audio IF 2_5 */ + [0x0545] = 0x0300, /* R1349 - Audio IF 2_6 */ + [0x0546] = 0x0300, /* R1350 - Audio IF 2_7 */ + [0x0547] = 0x1820, /* R1351 - Audio IF 2_8 */ + [0x0548] = 0x1820, /* R1352 - Audio IF 2_9 */ + [0x0549] = 0x0000, /* R1353 - Audio IF 2_10 */ + [0x054A] = 0x0001, /* R1354 - Audio IF 2_11 */ + [0x0551] = 0x0000, /* R1361 - Audio IF 2_18 */ + [0x0552] = 0x0001, /* R1362 - Audio IF 2_19 */ + [0x0559] = 0x0000, /* R1369 - Audio IF 2_26 */ + [0x055A] = 0x0000, /* R1370 - Audio IF 2_27 */ + [0x0580] = 0x000C, /* R1408 - Audio IF 3_1 */ + [0x0581] = 0x0008, /* R1409 - Audio IF 3_2 */ + [0x0582] = 0x0000, /* R1410 - Audio IF 3_3 */ + [0x0583] = 0x0000, /* R1411 - Audio IF 3_4 */ + [0x0584] = 0x0000, /* R1412 - Audio IF 3_5 */ + [0x0585] = 0x0300, /* R1413 - Audio IF 3_6 */ + [0x0586] = 0x0300, /* R1414 - Audio IF 3_7 */ + [0x0587] = 0x1820, /* R1415 - Audio IF 3_8 */ + [0x0588] = 0x1820, /* R1416 - Audio IF 3_9 */ + [0x0589] = 0x0000, /* R1417 - Audio IF 3_10 */ + [0x058A] = 0x0001, /* R1418 - Audio IF 3_11 */ + [0x0591] = 0x0000, /* R1425 - Audio IF 3_18 */ + [0x0592] = 0x0001, /* R1426 - Audio IF 3_19 */ + [0x0599] = 0x0000, /* R1433 - Audio IF 3_26 */ + [0x059A] = 0x0000, /* R1434 - Audio IF 3_27 */ + [0x0640] = 0x0000, /* R1600 - PWM1MIX Input 1 Source */ + [0x0641] = 0x0080, /* R1601 - PWM1MIX Input 1 Volume */ + [0x0642] = 0x0000, /* R1602 - PWM1MIX Input 2 Source */ + [0x0643] = 0x0080, /* R1603 - PWM1MIX Input 2 Volume */ + [0x0644] = 0x0000, /* R1604 - PWM1MIX Input 3 Source */ + [0x0645] = 0x0080, /* R1605 - PWM1MIX Input 3 Volume */ + [0x0646] = 0x0000, /* R1606 - PWM1MIX Input 4 Source */ + [0x0647] = 0x0080, /* R1607 - PWM1MIX Input 4 Volume */ + [0x0648] = 0x0000, /* R1608 - PWM2MIX Input 1 Source */ + [0x0649] = 0x0080, /* R1609 - PWM2MIX Input 1 Volume */ + [0x064A] = 0x0000, /* R1610 - PWM2MIX Input 2 Source */ + [0x064B] = 0x0080, /* R1611 - PWM2MIX Input 2 Volume */ + [0x064C] = 0x0000, /* R1612 - PWM2MIX Input 3 Source */ + [0x064D] = 0x0080, /* R1613 - PWM2MIX Input 3 Volume */ + [0x064E] = 0x0000, /* R1614 - PWM2MIX Input 4 Source */ + [0x064F] = 0x0080, /* R1615 - PWM2MIX Input 4 Volume */ + [0x0680] = 0x0000, /* R1664 - OUT1LMIX Input 1 Source */ + [0x0681] = 0x0080, /* R1665 - OUT1LMIX Input 1 Volume */ + [0x0682] = 0x0000, /* R1666 - OUT1LMIX Input 2 Source */ + [0x0683] = 0x0080, /* R1667 - OUT1LMIX Input 2 Volume */ + [0x0684] = 0x0000, /* R1668 - OUT1LMIX Input 3 Source */ + [0x0685] = 0x0080, /* R1669 - OUT1LMIX Input 3 Volume */ + [0x0686] = 0x0000, /* R1670 - OUT1LMIX Input 4 Source */ + [0x0687] = 0x0080, /* R1671 - OUT1LMIX Input 4 Volume */ + [0x0688] = 0x0000, /* R1672 - OUT1RMIX Input 1 Source */ + [0x0689] = 0x0080, /* R1673 - OUT1RMIX Input 1 Volume */ + [0x068A] = 0x0000, /* R1674 - OUT1RMIX Input 2 Source */ + [0x068B] = 0x0080, /* R1675 - OUT1RMIX Input 2 Volume */ + [0x068C] = 0x0000, /* R1676 - OUT1RMIX Input 3 Source */ + [0x068D] = 0x0080, /* R1677 - OUT1RMIX Input 3 Volume */ + [0x068E] = 0x0000, /* R1678 - OUT1RMIX Input 4 Source */ + [0x068F] = 0x0080, /* R1679 - OUT1RMIX Input 4 Volume */ + [0x0690] = 0x0000, /* R1680 - OUT2LMIX Input 1 Source */ + [0x0691] = 0x0080, /* R1681 - OUT2LMIX Input 1 Volume */ + [0x0692] = 0x0000, /* R1682 - OUT2LMIX Input 2 Source */ + [0x0693] = 0x0080, /* R1683 - OUT2LMIX Input 2 Volume */ + [0x0694] = 0x0000, /* R1684 - OUT2LMIX Input 3 Source */ + [0x0695] = 0x0080, /* R1685 - OUT2LMIX Input 3 Volume */ + [0x0696] = 0x0000, /* R1686 - OUT2LMIX Input 4 Source */ + [0x0697] = 0x0080, /* R1687 - OUT2LMIX Input 4 Volume */ + [0x0698] = 0x0000, /* R1688 - OUT2RMIX Input 1 Source */ + [0x0699] = 0x0080, /* R1689 - OUT2RMIX Input 1 Volume */ + [0x069A] = 0x0000, /* R1690 - OUT2RMIX Input 2 Source */ + [0x069B] = 0x0080, /* R1691 - OUT2RMIX Input 2 Volume */ + [0x069C] = 0x0000, /* R1692 - OUT2RMIX Input 3 Source */ + [0x069D] = 0x0080, /* R1693 - OUT2RMIX Input 3 Volume */ + [0x069E] = 0x0000, /* R1694 - OUT2RMIX Input 4 Source */ + [0x069F] = 0x0080, /* R1695 - OUT2RMIX Input 4 Volume */ + [0x06A0] = 0x0000, /* R1696 - OUT3LMIX Input 1 Source */ + [0x06A1] = 0x0080, /* R1697 - OUT3LMIX Input 1 Volume */ + [0x06A2] = 0x0000, /* R1698 - OUT3LMIX Input 2 Source */ + [0x06A3] = 0x0080, /* R1699 - OUT3LMIX Input 2 Volume */ + [0x06A4] = 0x0000, /* R1700 - OUT3LMIX Input 3 Source */ + [0x06A5] = 0x0080, /* R1701 - OUT3LMIX Input 3 Volume */ + [0x06A6] = 0x0000, /* R1702 - OUT3LMIX Input 4 Source */ + [0x06A7] = 0x0080, /* R1703 - OUT3LMIX Input 4 Volume */ + [0x06A8] = 0x0000, /* R1704 - OUT3RMIX Input 1 Source */ + [0x06A9] = 0x0080, /* R1705 - OUT3RMIX Input 1 Volume */ + [0x06AA] = 0x0000, /* R1706 - OUT3RMIX Input 2 Source */ + [0x06AB] = 0x0080, /* R1707 - OUT3RMIX Input 2 Volume */ + [0x06AC] = 0x0000, /* R1708 - OUT3RMIX Input 3 Source */ + [0x06AD] = 0x0080, /* R1709 - OUT3RMIX Input 3 Volume */ + [0x06AE] = 0x0000, /* R1710 - OUT3RMIX Input 4 Source */ + [0x06AF] = 0x0080, /* R1711 - OUT3RMIX Input 4 Volume */ + [0x06B0] = 0x0000, /* R1712 - OUT4LMIX Input 1 Source */ + [0x06B1] = 0x0080, /* R1713 - OUT4LMIX Input 1 Volume */ + [0x06B2] = 0x0000, /* R1714 - OUT4LMIX Input 2 Source */ + [0x06B3] = 0x0080, /* R1715 - OUT4LMIX Input 2 Volume */ + [0x06B4] = 0x0000, /* R1716 - OUT4LMIX Input 3 Source */ + [0x06B5] = 0x0080, /* R1717 - OUT4LMIX Input 3 Volume */ + [0x06B6] = 0x0000, /* R1718 - OUT4LMIX Input 4 Source */ + [0x06B7] = 0x0080, /* R1719 - OUT4LMIX Input 4 Volume */ + [0x06B8] = 0x0000, /* R1720 - OUT4RMIX Input 1 Source */ + [0x06B9] = 0x0080, /* R1721 - OUT4RMIX Input 1 Volume */ + [0x06BA] = 0x0000, /* R1722 - OUT4RMIX Input 2 Source */ + [0x06BB] = 0x0080, /* R1723 - OUT4RMIX Input 2 Volume */ + [0x06BC] = 0x0000, /* R1724 - OUT4RMIX Input 3 Source */ + [0x06BD] = 0x0080, /* R1725 - OUT4RMIX Input 3 Volume */ + [0x06BE] = 0x0000, /* R1726 - OUT4RMIX Input 4 Source */ + [0x06BF] = 0x0080, /* R1727 - OUT4RMIX Input 4 Volume */ + [0x06C0] = 0x0000, /* R1728 - OUT5LMIX Input 1 Source */ + [0x06C1] = 0x0080, /* R1729 - OUT5LMIX Input 1 Volume */ + [0x06C2] = 0x0000, /* R1730 - OUT5LMIX Input 2 Source */ + [0x06C3] = 0x0080, /* R1731 - OUT5LMIX Input 2 Volume */ + [0x06C4] = 0x0000, /* R1732 - OUT5LMIX Input 3 Source */ + [0x06C5] = 0x0080, /* R1733 - OUT5LMIX Input 3 Volume */ + [0x06C6] = 0x0000, /* R1734 - OUT5LMIX Input 4 Source */ + [0x06C7] = 0x0080, /* R1735 - OUT5LMIX Input 4 Volume */ + [0x06C8] = 0x0000, /* R1736 - OUT5RMIX Input 1 Source */ + [0x06C9] = 0x0080, /* R1737 - OUT5RMIX Input 1 Volume */ + [0x06CA] = 0x0000, /* R1738 - OUT5RMIX Input 2 Source */ + [0x06CB] = 0x0080, /* R1739 - OUT5RMIX Input 2 Volume */ + [0x06CC] = 0x0000, /* R1740 - OUT5RMIX Input 3 Source */ + [0x06CD] = 0x0080, /* R1741 - OUT5RMIX Input 3 Volume */ + [0x06CE] = 0x0000, /* R1742 - OUT5RMIX Input 4 Source */ + [0x06CF] = 0x0080, /* R1743 - OUT5RMIX Input 4 Volume */ + [0x06D0] = 0x0000, /* R1744 - OUT6LMIX Input 1 Source */ + [0x06D1] = 0x0080, /* R1745 - OUT6LMIX Input 1 Volume */ + [0x06D2] = 0x0000, /* R1746 - OUT6LMIX Input 2 Source */ + [0x06D3] = 0x0080, /* R1747 - OUT6LMIX Input 2 Volume */ + [0x06D4] = 0x0000, /* R1748 - OUT6LMIX Input 3 Source */ + [0x06D5] = 0x0080, /* R1749 - OUT6LMIX Input 3 Volume */ + [0x06D6] = 0x0000, /* R1750 - OUT6LMIX Input 4 Source */ + [0x06D7] = 0x0080, /* R1751 - OUT6LMIX Input 4 Volume */ + [0x06D8] = 0x0000, /* R1752 - OUT6RMIX Input 1 Source */ + [0x06D9] = 0x0080, /* R1753 - OUT6RMIX Input 1 Volume */ + [0x06DA] = 0x0000, /* R1754 - OUT6RMIX Input 2 Source */ + [0x06DB] = 0x0080, /* R1755 - OUT6RMIX Input 2 Volume */ + [0x06DC] = 0x0000, /* R1756 - OUT6RMIX Input 3 Source */ + [0x06DD] = 0x0080, /* R1757 - OUT6RMIX Input 3 Volume */ + [0x06DE] = 0x0000, /* R1758 - OUT6RMIX Input 4 Source */ + [0x06DF] = 0x0080, /* R1759 - OUT6RMIX Input 4 Volume */ + [0x0700] = 0x0000, /* R1792 - AIF1TX1MIX Input 1 Source */ + [0x0701] = 0x0080, /* R1793 - AIF1TX1MIX Input 1 Volume */ + [0x0702] = 0x0000, /* R1794 - AIF1TX1MIX Input 2 Source */ + [0x0703] = 0x0080, /* R1795 - AIF1TX1MIX Input 2 Volume */ + [0x0704] = 0x0000, /* R1796 - AIF1TX1MIX Input 3 Source */ + [0x0705] = 0x0080, /* R1797 - AIF1TX1MIX Input 3 Volume */ + [0x0706] = 0x0000, /* R1798 - AIF1TX1MIX Input 4 Source */ + [0x0707] = 0x0080, /* R1799 - AIF1TX1MIX Input 4 Volume */ + [0x0708] = 0x0000, /* R1800 - AIF1TX2MIX Input 1 Source */ + [0x0709] = 0x0080, /* R1801 - AIF1TX2MIX Input 1 Volume */ + [0x070A] = 0x0000, /* R1802 - AIF1TX2MIX Input 2 Source */ + [0x070B] = 0x0080, /* R1803 - AIF1TX2MIX Input 2 Volume */ + [0x070C] = 0x0000, /* R1804 - AIF1TX2MIX Input 3 Source */ + [0x070D] = 0x0080, /* R1805 - AIF1TX2MIX Input 3 Volume */ + [0x070E] = 0x0000, /* R1806 - AIF1TX2MIX Input 4 Source */ + [0x070F] = 0x0080, /* R1807 - AIF1TX2MIX Input 4 Volume */ + [0x0710] = 0x0000, /* R1808 - AIF1TX3MIX Input 1 Source */ + [0x0711] = 0x0080, /* R1809 - AIF1TX3MIX Input 1 Volume */ + [0x0712] = 0x0000, /* R1810 - AIF1TX3MIX Input 2 Source */ + [0x0713] = 0x0080, /* R1811 - AIF1TX3MIX Input 2 Volume */ + [0x0714] = 0x0000, /* R1812 - AIF1TX3MIX Input 3 Source */ + [0x0715] = 0x0080, /* R1813 - AIF1TX3MIX Input 3 Volume */ + [0x0716] = 0x0000, /* R1814 - AIF1TX3MIX Input 4 Source */ + [0x0717] = 0x0080, /* R1815 - AIF1TX3MIX Input 4 Volume */ + [0x0718] = 0x0000, /* R1816 - AIF1TX4MIX Input 1 Source */ + [0x0719] = 0x0080, /* R1817 - AIF1TX4MIX Input 1 Volume */ + [0x071A] = 0x0000, /* R1818 - AIF1TX4MIX Input 2 Source */ + [0x071B] = 0x0080, /* R1819 - AIF1TX4MIX Input 2 Volume */ + [0x071C] = 0x0000, /* R1820 - AIF1TX4MIX Input 3 Source */ + [0x071D] = 0x0080, /* R1821 - AIF1TX4MIX Input 3 Volume */ + [0x071E] = 0x0000, /* R1822 - AIF1TX4MIX Input 4 Source */ + [0x071F] = 0x0080, /* R1823 - AIF1TX4MIX Input 4 Volume */ + [0x0720] = 0x0000, /* R1824 - AIF1TX5MIX Input 1 Source */ + [0x0721] = 0x0080, /* R1825 - AIF1TX5MIX Input 1 Volume */ + [0x0722] = 0x0000, /* R1826 - AIF1TX5MIX Input 2 Source */ + [0x0723] = 0x0080, /* R1827 - AIF1TX5MIX Input 2 Volume */ + [0x0724] = 0x0000, /* R1828 - AIF1TX5MIX Input 3 Source */ + [0x0725] = 0x0080, /* R1829 - AIF1TX5MIX Input 3 Volume */ + [0x0726] = 0x0000, /* R1830 - AIF1TX5MIX Input 4 Source */ + [0x0727] = 0x0080, /* R1831 - AIF1TX5MIX Input 4 Volume */ + [0x0728] = 0x0000, /* R1832 - AIF1TX6MIX Input 1 Source */ + [0x0729] = 0x0080, /* R1833 - AIF1TX6MIX Input 1 Volume */ + [0x072A] = 0x0000, /* R1834 - AIF1TX6MIX Input 2 Source */ + [0x072B] = 0x0080, /* R1835 - AIF1TX6MIX Input 2 Volume */ + [0x072C] = 0x0000, /* R1836 - AIF1TX6MIX Input 3 Source */ + [0x072D] = 0x0080, /* R1837 - AIF1TX6MIX Input 3 Volume */ + [0x072E] = 0x0000, /* R1838 - AIF1TX6MIX Input 4 Source */ + [0x072F] = 0x0080, /* R1839 - AIF1TX6MIX Input 4 Volume */ + [0x0730] = 0x0000, /* R1840 - AIF1TX7MIX Input 1 Source */ + [0x0731] = 0x0080, /* R1841 - AIF1TX7MIX Input 1 Volume */ + [0x0732] = 0x0000, /* R1842 - AIF1TX7MIX Input 2 Source */ + [0x0733] = 0x0080, /* R1843 - AIF1TX7MIX Input 2 Volume */ + [0x0734] = 0x0000, /* R1844 - AIF1TX7MIX Input 3 Source */ + [0x0735] = 0x0080, /* R1845 - AIF1TX7MIX Input 3 Volume */ + [0x0736] = 0x0000, /* R1846 - AIF1TX7MIX Input 4 Source */ + [0x0737] = 0x0080, /* R1847 - AIF1TX7MIX Input 4 Volume */ + [0x0738] = 0x0000, /* R1848 - AIF1TX8MIX Input 1 Source */ + [0x0739] = 0x0080, /* R1849 - AIF1TX8MIX Input 1 Volume */ + [0x073A] = 0x0000, /* R1850 - AIF1TX8MIX Input 2 Source */ + [0x073B] = 0x0080, /* R1851 - AIF1TX8MIX Input 2 Volume */ + [0x073C] = 0x0000, /* R1852 - AIF1TX8MIX Input 3 Source */ + [0x073D] = 0x0080, /* R1853 - AIF1TX8MIX Input 3 Volume */ + [0x073E] = 0x0000, /* R1854 - AIF1TX8MIX Input 4 Source */ + [0x073F] = 0x0080, /* R1855 - AIF1TX8MIX Input 4 Volume */ + [0x0740] = 0x0000, /* R1856 - AIF2TX1MIX Input 1 Source */ + [0x0741] = 0x0080, /* R1857 - AIF2TX1MIX Input 1 Volume */ + [0x0742] = 0x0000, /* R1858 - AIF2TX1MIX Input 2 Source */ + [0x0743] = 0x0080, /* R1859 - AIF2TX1MIX Input 2 Volume */ + [0x0744] = 0x0000, /* R1860 - AIF2TX1MIX Input 3 Source */ + [0x0745] = 0x0080, /* R1861 - AIF2TX1MIX Input 3 Volume */ + [0x0746] = 0x0000, /* R1862 - AIF2TX1MIX Input 4 Source */ + [0x0747] = 0x0080, /* R1863 - AIF2TX1MIX Input 4 Volume */ + [0x0748] = 0x0000, /* R1864 - AIF2TX2MIX Input 1 Source */ + [0x0749] = 0x0080, /* R1865 - AIF2TX2MIX Input 1 Volume */ + [0x074A] = 0x0000, /* R1866 - AIF2TX2MIX Input 2 Source */ + [0x074B] = 0x0080, /* R1867 - AIF2TX2MIX Input 2 Volume */ + [0x074C] = 0x0000, /* R1868 - AIF2TX2MIX Input 3 Source */ + [0x074D] = 0x0080, /* R1869 - AIF2TX2MIX Input 3 Volume */ + [0x074E] = 0x0000, /* R1870 - AIF2TX2MIX Input 4 Source */ + [0x074F] = 0x0080, /* R1871 - AIF2TX2MIX Input 4 Volume */ + [0x0780] = 0x0000, /* R1920 - AIF3TX1MIX Input 1 Source */ + [0x0781] = 0x0080, /* R1921 - AIF3TX1MIX Input 1 Volume */ + [0x0782] = 0x0000, /* R1922 - AIF3TX1MIX Input 2 Source */ + [0x0783] = 0x0080, /* R1923 - AIF3TX1MIX Input 2 Volume */ + [0x0784] = 0x0000, /* R1924 - AIF3TX1MIX Input 3 Source */ + [0x0785] = 0x0080, /* R1925 - AIF3TX1MIX Input 3 Volume */ + [0x0786] = 0x0000, /* R1926 - AIF3TX1MIX Input 4 Source */ + [0x0787] = 0x0080, /* R1927 - AIF3TX1MIX Input 4 Volume */ + [0x0788] = 0x0000, /* R1928 - AIF3TX2MIX Input 1 Source */ + [0x0789] = 0x0080, /* R1929 - AIF3TX2MIX Input 1 Volume */ + [0x078A] = 0x0000, /* R1930 - AIF3TX2MIX Input 2 Source */ + [0x078B] = 0x0080, /* R1931 - AIF3TX2MIX Input 2 Volume */ + [0x078C] = 0x0000, /* R1932 - AIF3TX2MIX Input 3 Source */ + [0x078D] = 0x0080, /* R1933 - AIF3TX2MIX Input 3 Volume */ + [0x078E] = 0x0000, /* R1934 - AIF3TX2MIX Input 4 Source */ + [0x078F] = 0x0080, /* R1935 - AIF3TX2MIX Input 4 Volume */ + [0x0880] = 0x0000, /* R2176 - EQ1MIX Input 1 Source */ + [0x0881] = 0x0080, /* R2177 - EQ1MIX Input 1 Volume */ + [0x0882] = 0x0000, /* R2178 - EQ1MIX Input 2 Source */ + [0x0883] = 0x0080, /* R2179 - EQ1MIX Input 2 Volume */ + [0x0884] = 0x0000, /* R2180 - EQ1MIX Input 3 Source */ + [0x0885] = 0x0080, /* R2181 - EQ1MIX Input 3 Volume */ + [0x0886] = 0x0000, /* R2182 - EQ1MIX Input 4 Source */ + [0x0887] = 0x0080, /* R2183 - EQ1MIX Input 4 Volume */ + [0x0888] = 0x0000, /* R2184 - EQ2MIX Input 1 Source */ + [0x0889] = 0x0080, /* R2185 - EQ2MIX Input 1 Volume */ + [0x088A] = 0x0000, /* R2186 - EQ2MIX Input 2 Source */ + [0x088B] = 0x0080, /* R2187 - EQ2MIX Input 2 Volume */ + [0x088C] = 0x0000, /* R2188 - EQ2MIX Input 3 Source */ + [0x088D] = 0x0080, /* R2189 - EQ2MIX Input 3 Volume */ + [0x088E] = 0x0000, /* R2190 - EQ2MIX Input 4 Source */ + [0x088F] = 0x0080, /* R2191 - EQ2MIX Input 4 Volume */ + [0x0890] = 0x0000, /* R2192 - EQ3MIX Input 1 Source */ + [0x0891] = 0x0080, /* R2193 - EQ3MIX Input 1 Volume */ + [0x0892] = 0x0000, /* R2194 - EQ3MIX Input 2 Source */ + [0x0893] = 0x0080, /* R2195 - EQ3MIX Input 2 Volume */ + [0x0894] = 0x0000, /* R2196 - EQ3MIX Input 3 Source */ + [0x0895] = 0x0080, /* R2197 - EQ3MIX Input 3 Volume */ + [0x0896] = 0x0000, /* R2198 - EQ3MIX Input 4 Source */ + [0x0897] = 0x0080, /* R2199 - EQ3MIX Input 4 Volume */ + [0x0898] = 0x0000, /* R2200 - EQ4MIX Input 1 Source */ + [0x0899] = 0x0080, /* R2201 - EQ4MIX Input 1 Volume */ + [0x089A] = 0x0000, /* R2202 - EQ4MIX Input 2 Source */ + [0x089B] = 0x0080, /* R2203 - EQ4MIX Input 2 Volume */ + [0x089C] = 0x0000, /* R2204 - EQ4MIX Input 3 Source */ + [0x089D] = 0x0080, /* R2205 - EQ4MIX Input 3 Volume */ + [0x089E] = 0x0000, /* R2206 - EQ4MIX Input 4 Source */ + [0x089F] = 0x0080, /* R2207 - EQ4MIX Input 4 Volume */ + [0x08C0] = 0x0000, /* R2240 - DRC1LMIX Input 1 Source */ + [0x08C1] = 0x0080, /* R2241 - DRC1LMIX Input 1 Volume */ + [0x08C2] = 0x0000, /* R2242 - DRC1LMIX Input 2 Source */ + [0x08C3] = 0x0080, /* R2243 - DRC1LMIX Input 2 Volume */ + [0x08C4] = 0x0000, /* R2244 - DRC1LMIX Input 3 Source */ + [0x08C5] = 0x0080, /* R2245 - DRC1LMIX Input 3 Volume */ + [0x08C6] = 0x0000, /* R2246 - DRC1LMIX Input 4 Source */ + [0x08C7] = 0x0080, /* R2247 - DRC1LMIX Input 4 Volume */ + [0x08C8] = 0x0000, /* R2248 - DRC1RMIX Input 1 Source */ + [0x08C9] = 0x0080, /* R2249 - DRC1RMIX Input 1 Volume */ + [0x08CA] = 0x0000, /* R2250 - DRC1RMIX Input 2 Source */ + [0x08CB] = 0x0080, /* R2251 - DRC1RMIX Input 2 Volume */ + [0x08CC] = 0x0000, /* R2252 - DRC1RMIX Input 3 Source */ + [0x08CD] = 0x0080, /* R2253 - DRC1RMIX Input 3 Volume */ + [0x08CE] = 0x0000, /* R2254 - DRC1RMIX Input 4 Source */ + [0x08CF] = 0x0080, /* R2255 - DRC1RMIX Input 4 Volume */ + [0x0900] = 0x0000, /* R2304 - HPLP1MIX Input 1 Source */ + [0x0901] = 0x0080, /* R2305 - HPLP1MIX Input 1 Volume */ + [0x0902] = 0x0000, /* R2306 - HPLP1MIX Input 2 Source */ + [0x0903] = 0x0080, /* R2307 - HPLP1MIX Input 2 Volume */ + [0x0904] = 0x0000, /* R2308 - HPLP1MIX Input 3 Source */ + [0x0905] = 0x0080, /* R2309 - HPLP1MIX Input 3 Volume */ + [0x0906] = 0x0000, /* R2310 - HPLP1MIX Input 4 Source */ + [0x0907] = 0x0080, /* R2311 - HPLP1MIX Input 4 Volume */ + [0x0908] = 0x0000, /* R2312 - HPLP2MIX Input 1 Source */ + [0x0909] = 0x0080, /* R2313 - HPLP2MIX Input 1 Volume */ + [0x090A] = 0x0000, /* R2314 - HPLP2MIX Input 2 Source */ + [0x090B] = 0x0080, /* R2315 - HPLP2MIX Input 2 Volume */ + [0x090C] = 0x0000, /* R2316 - HPLP2MIX Input 3 Source */ + [0x090D] = 0x0080, /* R2317 - HPLP2MIX Input 3 Volume */ + [0x090E] = 0x0000, /* R2318 - HPLP2MIX Input 4 Source */ + [0x090F] = 0x0080, /* R2319 - HPLP2MIX Input 4 Volume */ + [0x0910] = 0x0000, /* R2320 - HPLP3MIX Input 1 Source */ + [0x0911] = 0x0080, /* R2321 - HPLP3MIX Input 1 Volume */ + [0x0912] = 0x0000, /* R2322 - HPLP3MIX Input 2 Source */ + [0x0913] = 0x0080, /* R2323 - HPLP3MIX Input 2 Volume */ + [0x0914] = 0x0000, /* R2324 - HPLP3MIX Input 3 Source */ + [0x0915] = 0x0080, /* R2325 - HPLP3MIX Input 3 Volume */ + [0x0916] = 0x0000, /* R2326 - HPLP3MIX Input 4 Source */ + [0x0917] = 0x0080, /* R2327 - HPLP3MIX Input 4 Volume */ + [0x0918] = 0x0000, /* R2328 - HPLP4MIX Input 1 Source */ + [0x0919] = 0x0080, /* R2329 - HPLP4MIX Input 1 Volume */ + [0x091A] = 0x0000, /* R2330 - HPLP4MIX Input 2 Source */ + [0x091B] = 0x0080, /* R2331 - HPLP4MIX Input 2 Volume */ + [0x091C] = 0x0000, /* R2332 - HPLP4MIX Input 3 Source */ + [0x091D] = 0x0080, /* R2333 - HPLP4MIX Input 3 Volume */ + [0x091E] = 0x0000, /* R2334 - HPLP4MIX Input 4 Source */ + [0x091F] = 0x0080, /* R2335 - HPLP4MIX Input 4 Volume */ + [0x0940] = 0x0000, /* R2368 - DSP1LMIX Input 1 Source */ + [0x0941] = 0x0080, /* R2369 - DSP1LMIX Input 1 Volume */ + [0x0942] = 0x0000, /* R2370 - DSP1LMIX Input 2 Source */ + [0x0943] = 0x0080, /* R2371 - DSP1LMIX Input 2 Volume */ + [0x0944] = 0x0000, /* R2372 - DSP1LMIX Input 3 Source */ + [0x0945] = 0x0080, /* R2373 - DSP1LMIX Input 3 Volume */ + [0x0946] = 0x0000, /* R2374 - DSP1LMIX Input 4 Source */ + [0x0947] = 0x0080, /* R2375 - DSP1LMIX Input 4 Volume */ + [0x0948] = 0x0000, /* R2376 - DSP1RMIX Input 1 Source */ + [0x0949] = 0x0080, /* R2377 - DSP1RMIX Input 1 Volume */ + [0x094A] = 0x0000, /* R2378 - DSP1RMIX Input 2 Source */ + [0x094B] = 0x0080, /* R2379 - DSP1RMIX Input 2 Volume */ + [0x094C] = 0x0000, /* R2380 - DSP1RMIX Input 3 Source */ + [0x094D] = 0x0080, /* R2381 - DSP1RMIX Input 3 Volume */ + [0x094E] = 0x0000, /* R2382 - DSP1RMIX Input 4 Source */ + [0x094F] = 0x0080, /* R2383 - DSP1RMIX Input 4 Volume */ + [0x0950] = 0x0000, /* R2384 - DSP1AUX1MIX Input 1 Source */ + [0x0958] = 0x0000, /* R2392 - DSP1AUX2MIX Input 1 Source */ + [0x0960] = 0x0000, /* R2400 - DSP1AUX3MIX Input 1 Source */ + [0x0968] = 0x0000, /* R2408 - DSP1AUX4MIX Input 1 Source */ + [0x0970] = 0x0000, /* R2416 - DSP1AUX5MIX Input 1 Source */ + [0x0978] = 0x0000, /* R2424 - DSP1AUX6MIX Input 1 Source */ + [0x0980] = 0x0000, /* R2432 - DSP2LMIX Input 1 Source */ + [0x0981] = 0x0080, /* R2433 - DSP2LMIX Input 1 Volume */ + [0x0982] = 0x0000, /* R2434 - DSP2LMIX Input 2 Source */ + [0x0983] = 0x0080, /* R2435 - DSP2LMIX Input 2 Volume */ + [0x0984] = 0x0000, /* R2436 - DSP2LMIX Input 3 Source */ + [0x0985] = 0x0080, /* R2437 - DSP2LMIX Input 3 Volume */ + [0x0986] = 0x0000, /* R2438 - DSP2LMIX Input 4 Source */ + [0x0987] = 0x0080, /* R2439 - DSP2LMIX Input 4 Volume */ + [0x0988] = 0x0000, /* R2440 - DSP2RMIX Input 1 Source */ + [0x0989] = 0x0080, /* R2441 - DSP2RMIX Input 1 Volume */ + [0x098A] = 0x0000, /* R2442 - DSP2RMIX Input 2 Source */ + [0x098B] = 0x0080, /* R2443 - DSP2RMIX Input 2 Volume */ + [0x098C] = 0x0000, /* R2444 - DSP2RMIX Input 3 Source */ + [0x098D] = 0x0080, /* R2445 - DSP2RMIX Input 3 Volume */ + [0x098E] = 0x0000, /* R2446 - DSP2RMIX Input 4 Source */ + [0x098F] = 0x0080, /* R2447 - DSP2RMIX Input 4 Volume */ + [0x0990] = 0x0000, /* R2448 - DSP2AUX1MIX Input 1 Source */ + [0x0998] = 0x0000, /* R2456 - DSP2AUX2MIX Input 1 Source */ + [0x09A0] = 0x0000, /* R2464 - DSP2AUX3MIX Input 1 Source */ + [0x09A8] = 0x0000, /* R2472 - DSP2AUX4MIX Input 1 Source */ + [0x09B0] = 0x0000, /* R2480 - DSP2AUX5MIX Input 1 Source */ + [0x09B8] = 0x0000, /* R2488 - DSP2AUX6MIX Input 1 Source */ + [0x09C0] = 0x0000, /* R2496 - DSP3LMIX Input 1 Source */ + [0x09C1] = 0x0080, /* R2497 - DSP3LMIX Input 1 Volume */ + [0x09C2] = 0x0000, /* R2498 - DSP3LMIX Input 2 Source */ + [0x09C3] = 0x0080, /* R2499 - DSP3LMIX Input 2 Volume */ + [0x09C4] = 0x0000, /* R2500 - DSP3LMIX Input 3 Source */ + [0x09C5] = 0x0080, /* R2501 - DSP3LMIX Input 3 Volume */ + [0x09C6] = 0x0000, /* R2502 - DSP3LMIX Input 4 Source */ + [0x09C7] = 0x0080, /* R2503 - DSP3LMIX Input 4 Volume */ + [0x09C8] = 0x0000, /* R2504 - DSP3RMIX Input 1 Source */ + [0x09C9] = 0x0080, /* R2505 - DSP3RMIX Input 1 Volume */ + [0x09CA] = 0x0000, /* R2506 - DSP3RMIX Input 2 Source */ + [0x09CB] = 0x0080, /* R2507 - DSP3RMIX Input 2 Volume */ + [0x09CC] = 0x0000, /* R2508 - DSP3RMIX Input 3 Source */ + [0x09CD] = 0x0080, /* R2509 - DSP3RMIX Input 3 Volume */ + [0x09CE] = 0x0000, /* R2510 - DSP3RMIX Input 4 Source */ + [0x09CF] = 0x0080, /* R2511 - DSP3RMIX Input 4 Volume */ + [0x09D0] = 0x0000, /* R2512 - DSP3AUX1MIX Input 1 Source */ + [0x09D8] = 0x0000, /* R2520 - DSP3AUX2MIX Input 1 Source */ + [0x09E0] = 0x0000, /* R2528 - DSP3AUX3MIX Input 1 Source */ + [0x09E8] = 0x0000, /* R2536 - DSP3AUX4MIX Input 1 Source */ + [0x09F0] = 0x0000, /* R2544 - DSP3AUX5MIX Input 1 Source */ + [0x09F8] = 0x0000, /* R2552 - DSP3AUX6MIX Input 1 Source */ + [0x0A80] = 0x0000, /* R2688 - ASRC1LMIX Input 1 Source */ + [0x0A88] = 0x0000, /* R2696 - ASRC1RMIX Input 1 Source */ + [0x0A90] = 0x0000, /* R2704 - ASRC2LMIX Input 1 Source */ + [0x0A98] = 0x0000, /* R2712 - ASRC2RMIX Input 1 Source */ + [0x0B00] = 0x0000, /* R2816 - ISRC1DEC1MIX Input 1 Source */ + [0x0B08] = 0x0000, /* R2824 - ISRC1DEC2MIX Input 1 Source */ + [0x0B10] = 0x0000, /* R2832 - ISRC1DEC3MIX Input 1 Source */ + [0x0B18] = 0x0000, /* R2840 - ISRC1DEC4MIX Input 1 Source */ + [0x0B20] = 0x0000, /* R2848 - ISRC1INT1MIX Input 1 Source */ + [0x0B28] = 0x0000, /* R2856 - ISRC1INT2MIX Input 1 Source */ + [0x0B30] = 0x0000, /* R2864 - ISRC1INT3MIX Input 1 Source */ + [0x0B38] = 0x0000, /* R2872 - ISRC1INT4MIX Input 1 Source */ + [0x0B40] = 0x0000, /* R2880 - ISRC2DEC1MIX Input 1 Source */ + [0x0B48] = 0x0000, /* R2888 - ISRC2DEC2MIX Input 1 Source */ + [0x0B50] = 0x0000, /* R2896 - ISRC2DEC3MIX Input 1 Source */ + [0x0B58] = 0x0000, /* R2904 - ISRC2DEC4MIX Input 1 Source */ + [0x0B60] = 0x0000, /* R2912 - ISRC2INT1MIX Input 1 Source */ + [0x0B68] = 0x0000, /* R2920 - ISRC2INT2MIX Input 1 Source */ + [0x0B70] = 0x0000, /* R2928 - ISRC2INT3MIX Input 1 Source */ + [0x0B78] = 0x0000, /* R2936 - ISRC2INT4MIX Input 1 Source */ + [0x0C00] = 0xA001, /* R3072 - GPIO CTRL 1 */ + [0x0C01] = 0xA001, /* R3073 - GPIO CTRL 2 */ + [0x0C02] = 0xA001, /* R3074 - GPIO CTRL 3 */ + [0x0C03] = 0xA001, /* R3075 - GPIO CTRL 4 */ + [0x0C04] = 0xA001, /* R3076 - GPIO CTRL 5 */ + [0x0C05] = 0xA001, /* R3077 - GPIO CTRL 6 */ + [0x0C23] = 0x4003, /* R3107 - Misc Pad Ctrl 1 */ + [0x0C24] = 0x0000, /* R3108 - Misc Pad Ctrl 2 */ + [0x0C25] = 0x0000, /* R3109 - Misc Pad Ctrl 3 */ + [0x0C26] = 0x0000, /* R3110 - Misc Pad Ctrl 4 */ + [0x0C27] = 0x0000, /* R3111 - Misc Pad Ctrl 5 */ + [0x0C28] = 0x0000, /* R3112 - Misc GPIO 1 */ + [0x0D00] = 0x0000, /* R3328 - Interrupt Status 1 */ + [0x0D01] = 0x0000, /* R3329 - Interrupt Status 2 */ + [0x0D02] = 0x0000, /* R3330 - Interrupt Status 3 */ + [0x0D03] = 0x0000, /* R3331 - Interrupt Status 4 */ + [0x0D04] = 0x0000, /* R3332 - Interrupt Raw Status 2 */ + [0x0D05] = 0x0000, /* R3333 - Interrupt Raw Status 3 */ + [0x0D06] = 0x0000, /* R3334 - Interrupt Raw Status 4 */ + [0x0D07] = 0xFFFF, /* R3335 - Interrupt Status 1 Mask */ + [0x0D08] = 0xFFFF, /* R3336 - Interrupt Status 2 Mask */ + [0x0D09] = 0xFFFF, /* R3337 - Interrupt Status 3 Mask */ + [0x0D0A] = 0xFFFF, /* R3338 - Interrupt Status 4 Mask */ + [0x0D1F] = 0x0000, /* R3359 - Interrupt Control */ + [0x0D20] = 0xFFFF, /* R3360 - IRQ Debounce 1 */ + [0x0D21] = 0xFFFF, /* R3361 - IRQ Debounce 2 */ + [0x0E00] = 0x0000, /* R3584 - FX_Ctrl */ + [0x0E10] = 0x6318, /* R3600 - EQ1_1 */ + [0x0E11] = 0x6300, /* R3601 - EQ1_2 */ + [0x0E12] = 0x0FC8, /* R3602 - EQ1_3 */ + [0x0E13] = 0x03FE, /* R3603 - EQ1_4 */ + [0x0E14] = 0x00E0, /* R3604 - EQ1_5 */ + [0x0E15] = 0x1EC4, /* R3605 - EQ1_6 */ + [0x0E16] = 0xF136, /* R3606 - EQ1_7 */ + [0x0E17] = 0x0409, /* R3607 - EQ1_8 */ + [0x0E18] = 0x04CC, /* R3608 - EQ1_9 */ + [0x0E19] = 0x1C9B, /* R3609 - EQ1_10 */ + [0x0E1A] = 0xF337, /* R3610 - EQ1_11 */ + [0x0E1B] = 0x040B, /* R3611 - EQ1_12 */ + [0x0E1C] = 0x0CBB, /* R3612 - EQ1_13 */ + [0x0E1D] = 0x16F8, /* R3613 - EQ1_14 */ + [0x0E1E] = 0xF7D9, /* R3614 - EQ1_15 */ + [0x0E1F] = 0x040A, /* R3615 - EQ1_16 */ + [0x0E20] = 0x1F14, /* R3616 - EQ1_17 */ + [0x0E21] = 0x058C, /* R3617 - EQ1_18 */ + [0x0E22] = 0x0563, /* R3618 - EQ1_19 */ + [0x0E23] = 0x4000, /* R3619 - EQ1_20 */ + [0x0E26] = 0x6318, /* R3622 - EQ2_1 */ + [0x0E27] = 0x6300, /* R3623 - EQ2_2 */ + [0x0E28] = 0x0FC8, /* R3624 - EQ2_3 */ + [0x0E29] = 0x03FE, /* R3625 - EQ2_4 */ + [0x0E2A] = 0x00E0, /* R3626 - EQ2_5 */ + [0x0E2B] = 0x1EC4, /* R3627 - EQ2_6 */ + [0x0E2C] = 0xF136, /* R3628 - EQ2_7 */ + [0x0E2D] = 0x0409, /* R3629 - EQ2_8 */ + [0x0E2E] = 0x04CC, /* R3630 - EQ2_9 */ + [0x0E2F] = 0x1C9B, /* R3631 - EQ2_10 */ + [0x0E30] = 0xF337, /* R3632 - EQ2_11 */ + [0x0E31] = 0x040B, /* R3633 - EQ2_12 */ + [0x0E32] = 0x0CBB, /* R3634 - EQ2_13 */ + [0x0E33] = 0x16F8, /* R3635 - EQ2_14 */ + [0x0E34] = 0xF7D9, /* R3636 - EQ2_15 */ + [0x0E35] = 0x040A, /* R3637 - EQ2_16 */ + [0x0E36] = 0x1F14, /* R3638 - EQ2_17 */ + [0x0E37] = 0x058C, /* R3639 - EQ2_18 */ + [0x0E38] = 0x0563, /* R3640 - EQ2_19 */ + [0x0E39] = 0x4000, /* R3641 - EQ2_20 */ + [0x0E3C] = 0x6318, /* R3644 - EQ3_1 */ + [0x0E3D] = 0x6300, /* R3645 - EQ3_2 */ + [0x0E3E] = 0x0FC8, /* R3646 - EQ3_3 */ + [0x0E3F] = 0x03FE, /* R3647 - EQ3_4 */ + [0x0E40] = 0x00E0, /* R3648 - EQ3_5 */ + [0x0E41] = 0x1EC4, /* R3649 - EQ3_6 */ + [0x0E42] = 0xF136, /* R3650 - EQ3_7 */ + [0x0E43] = 0x0409, /* R3651 - EQ3_8 */ + [0x0E44] = 0x04CC, /* R3652 - EQ3_9 */ + [0x0E45] = 0x1C9B, /* R3653 - EQ3_10 */ + [0x0E46] = 0xF337, /* R3654 - EQ3_11 */ + [0x0E47] = 0x040B, /* R3655 - EQ3_12 */ + [0x0E48] = 0x0CBB, /* R3656 - EQ3_13 */ + [0x0E49] = 0x16F8, /* R3657 - EQ3_14 */ + [0x0E4A] = 0xF7D9, /* R3658 - EQ3_15 */ + [0x0E4B] = 0x040A, /* R3659 - EQ3_16 */ + [0x0E4C] = 0x1F14, /* R3660 - EQ3_17 */ + [0x0E4D] = 0x058C, /* R3661 - EQ3_18 */ + [0x0E4E] = 0x0563, /* R3662 - EQ3_19 */ + [0x0E4F] = 0x4000, /* R3663 - EQ3_20 */ + [0x0E52] = 0x6318, /* R3666 - EQ4_1 */ + [0x0E53] = 0x6300, /* R3667 - EQ4_2 */ + [0x0E54] = 0x0FC8, /* R3668 - EQ4_3 */ + [0x0E55] = 0x03FE, /* R3669 - EQ4_4 */ + [0x0E56] = 0x00E0, /* R3670 - EQ4_5 */ + [0x0E57] = 0x1EC4, /* R3671 - EQ4_6 */ + [0x0E58] = 0xF136, /* R3672 - EQ4_7 */ + [0x0E59] = 0x0409, /* R3673 - EQ4_8 */ + [0x0E5A] = 0x04CC, /* R3674 - EQ4_9 */ + [0x0E5B] = 0x1C9B, /* R3675 - EQ4_10 */ + [0x0E5C] = 0xF337, /* R3676 - EQ4_11 */ + [0x0E5D] = 0x040B, /* R3677 - EQ4_12 */ + [0x0E5E] = 0x0CBB, /* R3678 - EQ4_13 */ + [0x0E5F] = 0x16F8, /* R3679 - EQ4_14 */ + [0x0E60] = 0xF7D9, /* R3680 - EQ4_15 */ + [0x0E61] = 0x040A, /* R3681 - EQ4_16 */ + [0x0E62] = 0x1F14, /* R3682 - EQ4_17 */ + [0x0E63] = 0x058C, /* R3683 - EQ4_18 */ + [0x0E64] = 0x0563, /* R3684 - EQ4_19 */ + [0x0E65] = 0x4000, /* R3685 - EQ4_20 */ + [0x0E80] = 0x0018, /* R3712 - DRC1 ctrl1 */ + [0x0E81] = 0x0933, /* R3713 - DRC1 ctrl2 */ + [0x0E82] = 0x0018, /* R3714 - DRC1 ctrl3 */ + [0x0E83] = 0x0000, /* R3715 - DRC1 ctrl4 */ + [0x0E84] = 0x0000, /* R3716 - DRC1 ctrl5 */ + [0x0EC0] = 0x0000, /* R3776 - HPLPF1_1 */ + [0x0EC1] = 0x0000, /* R3777 - HPLPF1_2 */ + [0x0EC4] = 0x0000, /* R3780 - HPLPF2_1 */ + [0x0EC5] = 0x0000, /* R3781 - HPLPF2_2 */ + [0x0EC8] = 0x0000, /* R3784 - HPLPF3_1 */ + [0x0EC9] = 0x0000, /* R3785 - HPLPF3_2 */ + [0x0ECC] = 0x0000, /* R3788 - HPLPF4_1 */ + [0x0ECD] = 0x0000, /* R3789 - HPLPF4_2 */ + [0x4000] = 0x0000, /* R16384 - DSP1 DM 0 */ + [0x4001] = 0x0000, /* R16385 - DSP1 DM 1 */ + [0x4002] = 0x0000, /* R16386 - DSP1 DM 2 */ + [0x4003] = 0x0000, /* R16387 - DSP1 DM 3 */ + [0x41FC] = 0x0000, /* R16892 - DSP1 DM 508 */ + [0x41FD] = 0x0000, /* R16893 - DSP1 DM 509 */ + [0x41FE] = 0x0000, /* R16894 - DSP1 DM 510 */ + [0x41FF] = 0x0000, /* R16895 - DSP1 DM 511 */ + [0x4800] = 0x0000, /* R18432 - DSP1 PM 0 */ + [0x4801] = 0x0000, /* R18433 - DSP1 PM 1 */ + [0x4802] = 0x0000, /* R18434 - DSP1 PM 2 */ + [0x4803] = 0x0000, /* R18435 - DSP1 PM 3 */ + [0x4804] = 0x0000, /* R18436 - DSP1 PM 4 */ + [0x4805] = 0x0000, /* R18437 - DSP1 PM 5 */ + [0x4DFA] = 0x0000, /* R19962 - DSP1 PM 1530 */ + [0x4DFB] = 0x0000, /* R19963 - DSP1 PM 1531 */ + [0x4DFC] = 0x0000, /* R19964 - DSP1 PM 1532 */ + [0x4DFD] = 0x0000, /* R19965 - DSP1 PM 1533 */ + [0x4DFE] = 0x0000, /* R19966 - DSP1 PM 1534 */ + [0x4DFF] = 0x0000, /* R19967 - DSP1 PM 1535 */ + [0x5000] = 0x0000, /* R20480 - DSP1 ZM 0 */ + [0x5001] = 0x0000, /* R20481 - DSP1 ZM 1 */ + [0x5002] = 0x0000, /* R20482 - DSP1 ZM 2 */ + [0x5003] = 0x0000, /* R20483 - DSP1 ZM 3 */ + [0x57FC] = 0x0000, /* R22524 - DSP1 ZM 2044 */ + [0x57FD] = 0x0000, /* R22525 - DSP1 ZM 2045 */ + [0x57FE] = 0x0000, /* R22526 - DSP1 ZM 2046 */ + [0x57FF] = 0x0000, /* R22527 - DSP1 ZM 2047 */ + [0x6000] = 0x0000, /* R24576 - DSP2 DM 0 */ + [0x6001] = 0x0000, /* R24577 - DSP2 DM 1 */ + [0x6002] = 0x0000, /* R24578 - DSP2 DM 2 */ + [0x6003] = 0x0000, /* R24579 - DSP2 DM 3 */ + [0x61FC] = 0x0000, /* R25084 - DSP2 DM 508 */ + [0x61FD] = 0x0000, /* R25085 - DSP2 DM 509 */ + [0x61FE] = 0x0000, /* R25086 - DSP2 DM 510 */ + [0x61FF] = 0x0000, /* R25087 - DSP2 DM 511 */ + [0x6800] = 0x0000, /* R26624 - DSP2 PM 0 */ + [0x6801] = 0x0000, /* R26625 - DSP2 PM 1 */ + [0x6802] = 0x0000, /* R26626 - DSP2 PM 2 */ + [0x6803] = 0x0000, /* R26627 - DSP2 PM 3 */ + [0x6804] = 0x0000, /* R26628 - DSP2 PM 4 */ + [0x6805] = 0x0000, /* R26629 - DSP2 PM 5 */ + [0x6DFA] = 0x0000, /* R28154 - DSP2 PM 1530 */ + [0x6DFB] = 0x0000, /* R28155 - DSP2 PM 1531 */ + [0x6DFC] = 0x0000, /* R28156 - DSP2 PM 1532 */ + [0x6DFD] = 0x0000, /* R28157 - DSP2 PM 1533 */ + [0x6DFE] = 0x0000, /* R28158 - DSP2 PM 1534 */ + [0x6DFF] = 0x0000, /* R28159 - DSP2 PM 1535 */ + [0x7000] = 0x0000, /* R28672 - DSP2 ZM 0 */ + [0x7001] = 0x0000, /* R28673 - DSP2 ZM 1 */ + [0x7002] = 0x0000, /* R28674 - DSP2 ZM 2 */ + [0x7003] = 0x0000, /* R28675 - DSP2 ZM 3 */ + [0x77FC] = 0x0000, /* R30716 - DSP2 ZM 2044 */ + [0x77FD] = 0x0000, /* R30717 - DSP2 ZM 2045 */ + [0x77FE] = 0x0000, /* R30718 - DSP2 ZM 2046 */ + [0x77FF] = 0x0000, /* R30719 - DSP2 ZM 2047 */ + [0x8000] = 0x0000, /* R32768 - DSP3 DM 0 */ + [0x8001] = 0x0000, /* R32769 - DSP3 DM 1 */ + [0x8002] = 0x0000, /* R32770 - DSP3 DM 2 */ + [0x8003] = 0x0000, /* R32771 - DSP3 DM 3 */ + [0x81FC] = 0x0000, /* R33276 - DSP3 DM 508 */ + [0x81FD] = 0x0000, /* R33277 - DSP3 DM 509 */ + [0x81FE] = 0x0000, /* R33278 - DSP3 DM 510 */ + [0x81FF] = 0x0000, /* R33279 - DSP3 DM 511 */ + [0x8800] = 0x0000, /* R34816 - DSP3 PM 0 */ + [0x8801] = 0x0000, /* R34817 - DSP3 PM 1 */ + [0x8802] = 0x0000, /* R34818 - DSP3 PM 2 */ + [0x8803] = 0x0000, /* R34819 - DSP3 PM 3 */ + [0x8804] = 0x0000, /* R34820 - DSP3 PM 4 */ + [0x8805] = 0x0000, /* R34821 - DSP3 PM 5 */ + [0x8DFA] = 0x0000, /* R36346 - DSP3 PM 1530 */ + [0x8DFB] = 0x0000, /* R36347 - DSP3 PM 1531 */ + [0x8DFC] = 0x0000, /* R36348 - DSP3 PM 1532 */ + [0x8DFD] = 0x0000, /* R36349 - DSP3 PM 1533 */ + [0x8DFE] = 0x0000, /* R36350 - DSP3 PM 1534 */ + [0x8DFF] = 0x0000, /* R36351 - DSP3 PM 1535 */ + [0x9000] = 0x0000, /* R36864 - DSP3 ZM 0 */ + [0x9001] = 0x0000, /* R36865 - DSP3 ZM 1 */ + [0x9002] = 0x0000, /* R36866 - DSP3 ZM 2 */ + [0x9003] = 0x0000, /* R36867 - DSP3 ZM 3 */ + [0x97FC] = 0x0000, /* R38908 - DSP3 ZM 2044 */ + [0x97FD] = 0x0000, /* R38909 - DSP3 ZM 2045 */ + [0x97FE] = 0x0000, /* R38910 - DSP3 ZM 2046 */ + [0x97FF] = 0x0000 /* R38911 - DSP3 ZM 2047 */ +}; diff --git a/sound/soc/codecs/wm5100.c b/sound/soc/codecs/wm5100.c new file mode 100644 index 00000000000..42d9039a49e --- /dev/null +++ b/sound/soc/codecs/wm5100.c @@ -0,0 +1,2813 @@ +/* + * wm5100.c -- WM5100 ALSA SoC Audio driver + * + * Copyright 2011 Wolfson Microelectronics plc + * + * Author: Mark Brown <broonie@opensource.wolfsonmicro.com> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#include <linux/module.h> +#include <linux/moduleparam.h> +#include <linux/init.h> +#include <linux/delay.h> +#include <linux/pm.h> +#include <linux/gcd.h> +#include <linux/gpio.h> +#include <linux/i2c.h> +#include <linux/platform_device.h> +#include <linux/regulator/consumer.h> +#include <linux/regulator/fixed.h> +#include <linux/slab.h> +#include <sound/core.h> +#include <sound/pcm.h> +#include <sound/pcm_params.h> +#include <sound/soc.h> +#include <sound/jack.h> +#include <sound/initval.h> +#include <sound/tlv.h> +#include <sound/wm5100.h> + +#include "wm5100.h" + +#define WM5100_NUM_CORE_SUPPLIES 2 +static const char *wm5100_core_supply_names[WM5100_NUM_CORE_SUPPLIES] = { + "DBVDD1", + "LDOVDD", /* If DCVDD is supplied externally specify as LDOVDD */ +}; + +#define WM5100_AIFS 3 +#define WM5100_SYNC_SRS 3 + +struct wm5100_fll { + int fref; + int fout; + int src; + struct completion lock; +}; + +/* codec private data */ +struct wm5100_priv { + struct snd_soc_codec *codec; + + struct regulator_bulk_data core_supplies[WM5100_NUM_CORE_SUPPLIES]; + struct regulator *cpvdd; + struct regulator *dbvdd2; + struct regulator *dbvdd3; + + int rev; + + int sysclk; + int asyncclk; + + bool aif_async[WM5100_AIFS]; + bool aif_symmetric[WM5100_AIFS]; + int sr_ref[WM5100_SYNC_SRS]; + + bool out_ena[2]; + + struct snd_soc_jack *jack; + bool jack_detecting; + bool jack_mic; + int jack_mode; + + struct wm5100_fll fll[2]; + + struct wm5100_pdata pdata; + +#ifdef CONFIG_GPIOLIB + struct gpio_chip gpio_chip; +#endif +}; + +static int wm5100_sr_code[] = { + 0, + 12000, + 24000, + 48000, + 96000, + 192000, + 384000, + 768000, + 0, + 11025, + 22050, + 44100, + 88200, + 176400, + 352800, + 705600, + 4000, + 8000, + 16000, + 32000, + 64000, + 128000, + 256000, + 512000, +}; + +static int wm5100_sr_regs[WM5100_SYNC_SRS] = { + WM5100_CLOCKING_4, + WM5100_CLOCKING_5, + WM5100_CLOCKING_6, +}; + +static int wm5100_alloc_sr(struct snd_soc_codec *codec, int rate) +{ + struct wm5100_priv *wm5100 = snd_soc_codec_get_drvdata(codec); + int sr_code, sr_free, i; + + for (i = 0; i < ARRAY_SIZE(wm5100_sr_code); i++) + if (wm5100_sr_code[i] == rate) + break; + if (i == ARRAY_SIZE(wm5100_sr_code)) { + dev_err(codec->dev, "Unsupported sample rate: %dHz\n", rate); + return -EINVAL; + } + sr_code = i; + + if ((wm5100->sysclk % rate) == 0) { + /* Is this rate already in use? */ + sr_free = -1; + for (i = 0; i < ARRAY_SIZE(wm5100_sr_regs); i++) { + if (!wm5100->sr_ref[i] && sr_free == -1) { + sr_free = i; + continue; + } + if ((snd_soc_read(codec, wm5100_sr_regs[i]) & + WM5100_SAMPLE_RATE_1_MASK) == sr_code) + break; + } + + if (i < ARRAY_SIZE(wm5100_sr_regs)) { + wm5100->sr_ref[i]++; + dev_dbg(codec->dev, "SR %dHz, slot %d, ref %d\n", + rate, i, wm5100->sr_ref[i]); + return i; + } + + if (sr_free == -1) { + dev_err(codec->dev, "All SR slots already in use\n"); + return -EBUSY; + } + + dev_dbg(codec->dev, "Allocating SR slot %d for %dHz\n", + sr_free, rate); + wm5100->sr_ref[sr_free]++; + snd_soc_update_bits(codec, wm5100_sr_regs[sr_free], + WM5100_SAMPLE_RATE_1_MASK, + sr_code); + + return sr_free; + + } else { + dev_err(codec->dev, + "SR %dHz incompatible with %dHz SYSCLK and %dHz ASYNCCLK\n", + rate, wm5100->sysclk, wm5100->asyncclk); + return -EINVAL; + } +} + +static void wm5100_free_sr(struct snd_soc_codec *codec, int rate) +{ + struct wm5100_priv *wm5100 = snd_soc_codec_get_drvdata(codec); + int i, sr_code; + + for (i = 0; i < ARRAY_SIZE(wm5100_sr_code); i++) + if (wm5100_sr_code[i] == rate) + break; + if (i == ARRAY_SIZE(wm5100_sr_code)) { + dev_err(codec->dev, "Unsupported sample rate: %dHz\n", rate); + return; + } + sr_code = wm5100_sr_code[i]; + + for (i = 0; i < ARRAY_SIZE(wm5100_sr_regs); i++) { + if (!wm5100->sr_ref[i]) + continue; + + if ((snd_soc_read(codec, wm5100_sr_regs[i]) & + WM5100_SAMPLE_RATE_1_MASK) == sr_code) + break; + } + if (i < ARRAY_SIZE(wm5100_sr_regs)) { + wm5100->sr_ref[i]--; + dev_dbg(codec->dev, "Dereference SR %dHz, count now %d\n", + rate, wm5100->sr_ref[i]); + } else { + dev_warn(codec->dev, "Freeing unreferenced sample rate %dHz\n", + rate); + } +} + +static int wm5100_reset(struct snd_soc_codec *codec) +{ + struct wm5100_priv *wm5100 = snd_soc_codec_get_drvdata(codec); + + if (wm5100->pdata.reset) { + gpio_set_value_cansleep(wm5100->pdata.reset, 0); + gpio_set_value_cansleep(wm5100->pdata.reset, 1); + + return 0; + } else { + return snd_soc_write(codec, WM5100_SOFTWARE_RESET, 0); + } +} + +static DECLARE_TLV_DB_SCALE(in_tlv, -6300, 100, 0); +static DECLARE_TLV_DB_SCALE(eq_tlv, -1200, 100, 0); +static DECLARE_TLV_DB_SCALE(mixer_tlv, -3200, 100, 0); +static DECLARE_TLV_DB_SCALE(out_tlv, -6400, 100, 0); +static DECLARE_TLV_DB_SCALE(digital_tlv, -6400, 50, 0); + +static const char *wm5100_mixer_texts[] = { + "None", + "Tone Generator 1", + "Tone Generator 2", + "AEC loopback", + "IN1L", + "IN1R", + "IN2L", + "IN2R", + "IN3L", + "IN3R", + "IN4L", + "IN4R", + "AIF1RX1", + "AIF1RX2", + "AIF1RX3", + "AIF1RX4", + "AIF1RX5", + "AIF1RX6", + "AIF1RX7", + "AIF1RX8", + "AIF2RX1", + "AIF2RX2", + "AIF3RX1", + "AIF3RX2", + "EQ1", + "EQ2", + "EQ3", + "EQ4", + "DRC1L", + "DRC1R", + "LHPF1", + "LHPF2", + "LHPF3", + "LHPF4", + "DSP1.1", + "DSP1.2", + "DSP1.3", + "DSP1.4", + "DSP1.5", + "DSP1.6", + "DSP2.1", + "DSP2.2", + "DSP2.3", + "DSP2.4", + "DSP2.5", + "DSP2.6", + "DSP3.1", + "DSP3.2", + "DSP3.3", + "DSP3.4", + "DSP3.5", + "DSP3.6", + "ASRC1L", + "ASRC1R", + "ASRC2L", + "ASRC2R", + "ISRC1INT1", + "ISRC1INT2", + "ISRC1INT3", + "ISRC1INT4", + "ISRC2INT1", + "ISRC2INT2", + "ISRC2INT3", + "ISRC2INT4", + "ISRC1DEC1", + "ISRC1DEC2", + "ISRC1DEC3", + "ISRC1DEC4", + "ISRC2DEC1", + "ISRC2DEC2", + "ISRC2DEC3", + "ISRC2DEC4", +}; + +static int wm5100_mixer_values[] = { + 0x00, + 0x04, /* Tone */ + 0x05, + 0x08, /* AEC */ + 0x10, /* Input */ + 0x11, + 0x12, + 0x13, + 0x14, + 0x15, + 0x16, + 0x17, + 0x20, /* AIF */ + 0x21, + 0x22, + 0x23, + 0x24, + 0x25, + 0x26, + 0x27, + 0x28, + 0x29, + 0x30, /* AIF3 - check */ + 0x31, + 0x50, /* EQ */ + 0x51, + 0x52, + 0x53, + 0x54, + 0x58, /* DRC */ + 0x59, + 0x60, /* LHPF1 */ + 0x61, /* LHPF2 */ + 0x62, /* LHPF3 */ + 0x63, /* LHPF4 */ + 0x68, /* DSP1 */ + 0x69, + 0x6a, + 0x6b, + 0x6c, + 0x6d, + 0x70, /* DSP2 */ + 0x71, + 0x72, + 0x73, + 0x74, + 0x75, + 0x78, /* DSP3 */ + 0x79, + 0x7a, + 0x7b, + 0x7c, + 0x7d, + 0x90, /* ASRC1 */ + 0x91, + 0x92, /* ASRC2 */ + 0x93, + 0xa0, /* ISRC1DEC1 */ + 0xa1, + 0xa2, + 0xa3, + 0xa4, /* ISRC1INT1 */ + 0xa5, + 0xa6, + 0xa7, + 0xa8, /* ISRC2DEC1 */ + 0xa9, + 0xaa, + 0xab, + 0xac, /* ISRC2INT1 */ + 0xad, + 0xae, + 0xaf, +}; + +#define WM5100_MIXER_CONTROLS(name, base) \ + SOC_SINGLE_TLV(name " Input 1 Volume", base + 1 , \ + WM5100_MIXER_VOL_SHIFT, 80, 0, mixer_tlv), \ + SOC_SINGLE_TLV(name " Input 2 Volume", base + 3 , \ + WM5100_MIXER_VOL_SHIFT, 80, 0, mixer_tlv), \ + SOC_SINGLE_TLV(name " Input 3 Volume", base + 5 , \ + WM5100_MIXER_VOL_SHIFT, 80, 0, mixer_tlv), \ + SOC_SINGLE_TLV(name " Input 4 Volume", base + 7 , \ + WM5100_MIXER_VOL_SHIFT, 80, 0, mixer_tlv) + +#define WM5100_MUX_ENUM_DECL(name, reg) \ + SOC_VALUE_ENUM_SINGLE_DECL(name, reg, 0, 0xff, \ + wm5100_mixer_texts, wm5100_mixer_values) + +#define WM5100_MUX_CTL_DECL(name) \ + const struct snd_kcontrol_new name##_mux = \ + SOC_DAPM_VALUE_ENUM("Route", name##_enum) + +#define WM5100_MIXER_ENUMS(name, base_reg) \ + static WM5100_MUX_ENUM_DECL(name##_in1_enum, base_reg); \ + static WM5100_MUX_ENUM_DECL(name##_in2_enum, base_reg + 2); \ + static WM5100_MUX_ENUM_DECL(name##_in3_enum, base_reg + 4); \ + static WM5100_MUX_ENUM_DECL(name##_in4_enum, base_reg + 6); \ + static WM5100_MUX_CTL_DECL(name##_in1); \ + static WM5100_MUX_CTL_DECL(name##_in2); \ + static WM5100_MUX_CTL_DECL(name##_in3); \ + static WM5100_MUX_CTL_DECL(name##_in4) + +WM5100_MIXER_ENUMS(HPOUT1L, WM5100_OUT1LMIX_INPUT_1_SOURCE); +WM5100_MIXER_ENUMS(HPOUT1R, WM5100_OUT1RMIX_INPUT_1_SOURCE); +WM5100_MIXER_ENUMS(HPOUT2L, WM5100_OUT2LMIX_INPUT_1_SOURCE); +WM5100_MIXER_ENUMS(HPOUT2R, WM5100_OUT2RMIX_INPUT_1_SOURCE); +WM5100_MIXER_ENUMS(HPOUT3L, WM5100_OUT3LMIX_INPUT_1_SOURCE); +WM5100_MIXER_ENUMS(HPOUT3R, WM5100_OUT3RMIX_INPUT_1_SOURCE); + +WM5100_MIXER_ENUMS(SPKOUTL, WM5100_OUT4LMIX_INPUT_1_SOURCE); +WM5100_MIXER_ENUMS(SPKOUTR, WM5100_OUT4RMIX_INPUT_1_SOURCE); +WM5100_MIXER_ENUMS(SPKDAT1L, WM5100_OUT5LMIX_INPUT_1_SOURCE); +WM5100_MIXER_ENUMS(SPKDAT1R, WM5100_OUT5RMIX_INPUT_1_SOURCE); +WM5100_MIXER_ENUMS(SPKDAT2L, WM5100_OUT6LMIX_INPUT_1_SOURCE); +WM5100_MIXER_ENUMS(SPKDAT2R, WM5100_OUT6RMIX_INPUT_1_SOURCE); + +WM5100_MIXER_ENUMS(PWM1, WM5100_PWM1MIX_INPUT_1_SOURCE); +WM5100_MIXER_ENUMS(PWM2, WM5100_PWM1MIX_INPUT_1_SOURCE); + +WM5100_MIXER_ENUMS(AIF1TX1, WM5100_AIF1TX1MIX_INPUT_1_SOURCE); +WM5100_MIXER_ENUMS(AIF1TX2, WM5100_AIF1TX2MIX_INPUT_1_SOURCE); +WM5100_MIXER_ENUMS(AIF1TX3, WM5100_AIF1TX3MIX_INPUT_1_SOURCE); +WM5100_MIXER_ENUMS(AIF1TX4, WM5100_AIF1TX4MIX_INPUT_1_SOURCE); +WM5100_MIXER_ENUMS(AIF1TX5, WM5100_AIF1TX5MIX_INPUT_1_SOURCE); +WM5100_MIXER_ENUMS(AIF1TX6, WM5100_AIF1TX6MIX_INPUT_1_SOURCE); +WM5100_MIXER_ENUMS(AIF1TX7, WM5100_AIF1TX7MIX_INPUT_1_SOURCE); +WM5100_MIXER_ENUMS(AIF1TX8, WM5100_AIF1TX8MIX_INPUT_1_SOURCE); + +WM5100_MIXER_ENUMS(AIF2TX1, WM5100_AIF2TX1MIX_INPUT_1_SOURCE); +WM5100_MIXER_ENUMS(AIF2TX2, WM5100_AIF2TX2MIX_INPUT_1_SOURCE); + +WM5100_MIXER_ENUMS(AIF3TX1, WM5100_AIF1TX1MIX_INPUT_1_SOURCE); +WM5100_MIXER_ENUMS(AIF3TX2, WM5100_AIF1TX2MIX_INPUT_1_SOURCE); + +WM5100_MIXER_ENUMS(EQ1, WM5100_EQ1MIX_INPUT_1_SOURCE); +WM5100_MIXER_ENUMS(EQ2, WM5100_EQ2MIX_INPUT_1_SOURCE); +WM5100_MIXER_ENUMS(EQ3, WM5100_EQ3MIX_INPUT_1_SOURCE); +WM5100_MIXER_ENUMS(EQ4, WM5100_EQ4MIX_INPUT_1_SOURCE); + +WM5100_MIXER_ENUMS(DRC1L, WM5100_DRC1LMIX_INPUT_1_SOURCE); +WM5100_MIXER_ENUMS(DRC1R, WM5100_DRC1RMIX_INPUT_1_SOURCE); + +WM5100_MIXER_ENUMS(LHPF1, WM5100_HPLP1MIX_INPUT_1_SOURCE); +WM5100_MIXER_ENUMS(LHPF2, WM5100_HPLP2MIX_INPUT_1_SOURCE); +WM5100_MIXER_ENUMS(LHPF3, WM5100_HPLP3MIX_INPUT_1_SOURCE); +WM5100_MIXER_ENUMS(LHPF4, WM5100_HPLP4MIX_INPUT_1_SOURCE); + +#define WM5100_MUX(name, ctrl) \ + SND_SOC_DAPM_VALUE_MUX(name, SND_SOC_NOPM, 0, 0, ctrl) + +#define WM5100_MIXER_WIDGETS(name, name_str) \ + WM5100_MUX(name_str " Input 1", &name##_in1_mux), \ + WM5100_MUX(name_str " Input 2", &name##_in2_mux), \ + WM5100_MUX(name_str " Input 3", &name##_in3_mux), \ + WM5100_MUX(name_str " Input 4", &name##_in4_mux), \ + SND_SOC_DAPM_MIXER(name_str " Mixer", SND_SOC_NOPM, 0, 0, NULL, 0) + +#define WM5100_MIXER_INPUT_ROUTES(name) \ + { name, "Tone Generator 1", "Tone Generator 1" }, \ + { name, "Tone Generator 2", "Tone Generator 2" }, \ + { name, "IN1L", "IN1L PGA" }, \ + { name, "IN1R", "IN1R PGA" }, \ + { name, "IN2L", "IN2L PGA" }, \ + { name, "IN2R", "IN2R PGA" }, \ + { name, "IN3L", "IN3L PGA" }, \ + { name, "IN3R", "IN3R PGA" }, \ + { name, "IN4L", "IN4L PGA" }, \ + { name, "IN4R", "IN4R PGA" }, \ + { name, "AIF1RX1", "AIF1RX1" }, \ + { name, "AIF1RX2", "AIF1RX2" }, \ + { name, "AIF1RX3", "AIF1RX3" }, \ + { name, "AIF1RX4", "AIF1RX4" }, \ + { name, "AIF1RX5", "AIF1RX5" }, \ + { name, "AIF1RX6", "AIF1RX6" }, \ + { name, "AIF1RX7", "AIF1RX7" }, \ + { name, "AIF1RX8", "AIF1RX8" }, \ + { name, "AIF2RX1", "AIF2RX1" }, \ + { name, "AIF2RX2", "AIF2RX2" }, \ + { name, "AIF3RX1", "AIF3RX1" }, \ + { name, "AIF3RX2", "AIF3RX2" }, \ + { name, "EQ1", "EQ1" }, \ + { name, "EQ2", "EQ2" }, \ + { name, "EQ3", "EQ3" }, \ + { name, "EQ4", "EQ4" }, \ + { name, "DRC1L", "DRC1L" }, \ + { name, "DRC1R", "DRC1R" }, \ + { name, "LHPF1", "LHPF1" }, \ + { name, "LHPF2", "LHPF2" }, \ + { name, "LHPF3", "LHPF3" }, \ + { name, "LHPF4", "LHPF4" } + +#define WM5100_MIXER_ROUTES(widget, name) \ + { widget, NULL, name " Mixer" }, \ + { name " Mixer", NULL, name " Input 1" }, \ + { name " Mixer", NULL, name " Input 2" }, \ + { name " Mixer", NULL, name " Input 3" }, \ + { name " Mixer", NULL, name " Input 4" }, \ + WM5100_MIXER_INPUT_ROUTES(name " Input 1"), \ + WM5100_MIXER_INPUT_ROUTES(name " Input 2"), \ + WM5100_MIXER_INPUT_ROUTES(name " Input 3"), \ + WM5100_MIXER_INPUT_ROUTES(name " Input 4") + +static const char *wm5100_lhpf_mode_text[] = { + "Low-pass", "High-pass" +}; + +static const struct soc_enum wm5100_lhpf1_mode = + SOC_ENUM_SINGLE(WM5100_HPLPF1_1, WM5100_LHPF1_MODE_SHIFT, 2, + wm5100_lhpf_mode_text); + +static const struct soc_enum wm5100_lhpf2_mode = + SOC_ENUM_SINGLE(WM5100_HPLPF2_1, WM5100_LHPF2_MODE_SHIFT, 2, + wm5100_lhpf_mode_text); + +static const struct soc_enum wm5100_lhpf3_mode = + SOC_ENUM_SINGLE(WM5100_HPLPF3_1, WM5100_LHPF3_MODE_SHIFT, 2, + wm5100_lhpf_mode_text); + +static const struct soc_enum wm5100_lhpf4_mode = + SOC_ENUM_SINGLE(WM5100_HPLPF4_1, WM5100_LHPF4_MODE_SHIFT, 2, + wm5100_lhpf_mode_text); + +static const struct snd_kcontrol_new wm5100_snd_controls[] = { +SOC_SINGLE("IN1 High Performance Switch", WM5100_IN1L_CONTROL, + WM5100_IN1_OSR_SHIFT, 1, 0), +SOC_SINGLE("IN2 High Performance Switch", WM5100_IN2L_CONTROL, + WM5100_IN2_OSR_SHIFT, 1, 0), +SOC_SINGLE("IN3 High Performance Switch", WM5100_IN3L_CONTROL, + WM5100_IN3_OSR_SHIFT, 1, 0), +SOC_SINGLE("IN4 High Performance Switch", WM5100_IN4L_CONTROL, + WM5100_IN4_OSR_SHIFT, 1, 0), + +/* Only applicable for analogue inputs */ +SOC_DOUBLE_R_TLV("IN1 Volume", WM5100_IN1L_CONTROL, WM5100_IN1R_CONTROL, + WM5100_IN1L_PGA_VOL_SHIFT, 94, 0, in_tlv), +SOC_DOUBLE_R_TLV("IN2 Volume", WM5100_IN2L_CONTROL, WM5100_IN2R_CONTROL, + WM5100_IN2L_PGA_VOL_SHIFT, 94, 0, in_tlv), +SOC_DOUBLE_R_TLV("IN3 Volume", WM5100_IN3L_CONTROL, WM5100_IN3R_CONTROL, + WM5100_IN3L_PGA_VOL_SHIFT, 94, 0, in_tlv), +SOC_DOUBLE_R_TLV("IN4 Volume", WM5100_IN4L_CONTROL, WM5100_IN4R_CONTROL, + WM5100_IN4L_PGA_VOL_SHIFT, 94, 0, in_tlv), + +SOC_DOUBLE_R_TLV("IN1 Digital Volume", WM5100_ADC_DIGITAL_VOLUME_1L, + WM5100_ADC_DIGITAL_VOLUME_1R, WM5100_IN1L_VOL_SHIFT, 191, + 0, digital_tlv), +SOC_DOUBLE_R_TLV("IN2 Digital Volume", WM5100_ADC_DIGITAL_VOLUME_2L, + WM5100_ADC_DIGITAL_VOLUME_2R, WM5100_IN2L_VOL_SHIFT, 191, + 0, digital_tlv), +SOC_DOUBLE_R_TLV("IN3 Digital Volume", WM5100_ADC_DIGITAL_VOLUME_3L, + WM5100_ADC_DIGITAL_VOLUME_3R, WM5100_IN3L_VOL_SHIFT, 191, + 0, digital_tlv), +SOC_DOUBLE_R_TLV("IN4 Digital Volume", WM5100_ADC_DIGITAL_VOLUME_4L, + WM5100_ADC_DIGITAL_VOLUME_4R, WM5100_IN4L_VOL_SHIFT, 191, + 0, digital_tlv), + +SOC_DOUBLE_R("IN1 Switch", WM5100_ADC_DIGITAL_VOLUME_1L, + WM5100_ADC_DIGITAL_VOLUME_1R, WM5100_IN1L_MUTE_SHIFT, 1, 1), +SOC_DOUBLE_R("IN2 Switch", WM5100_ADC_DIGITAL_VOLUME_2L, + WM5100_ADC_DIGITAL_VOLUME_2R, WM5100_IN2L_MUTE_SHIFT, 1, 1), +SOC_DOUBLE_R("IN3 Switch", WM5100_ADC_DIGITAL_VOLUME_3L, + WM5100_ADC_DIGITAL_VOLUME_3R, WM5100_IN3L_MUTE_SHIFT, 1, 1), +SOC_DOUBLE_R("IN4 Switch", WM5100_ADC_DIGITAL_VOLUME_4L, + WM5100_ADC_DIGITAL_VOLUME_4R, WM5100_IN4L_MUTE_SHIFT, 1, 1), + +SOC_SINGLE("HPOUT1 High Performance Switch", WM5100_OUT_VOLUME_1L, + WM5100_OUT1_OSR_SHIFT, 1, 0), +SOC_SINGLE("HPOUT2 High Performance Switch", WM5100_OUT_VOLUME_2L, + WM5100_OUT2_OSR_SHIFT, 1, 0), +SOC_SINGLE("HPOUT3 High Performance Switch", WM5100_OUT_VOLUME_3L, + WM5100_OUT3_OSR_SHIFT, 1, 0), +SOC_SINGLE("SPKOUT High Performance Switch", WM5100_OUT_VOLUME_4L, + WM5100_OUT4_OSR_SHIFT, 1, 0), +SOC_SINGLE("SPKDAT1 High Performance Switch", WM5100_DAC_VOLUME_LIMIT_5L, + WM5100_OUT5_OSR_SHIFT, 1, 0), +SOC_SINGLE("SPKDAT2 High Performance Switch", WM5100_DAC_VOLUME_LIMIT_6L, + WM5100_OUT6_OSR_SHIFT, 1, 0), + +SOC_DOUBLE_R_TLV("HPOUT1 Digital Volume", WM5100_DAC_DIGITAL_VOLUME_1L, + WM5100_DAC_DIGITAL_VOLUME_1R, WM5100_OUT1L_VOL_SHIFT, 159, 0, + digital_tlv), +SOC_DOUBLE_R_TLV("HPOUT2 Digital Volume", WM5100_DAC_DIGITAL_VOLUME_2L, + WM5100_DAC_DIGITAL_VOLUME_2R, WM5100_OUT2L_VOL_SHIFT, 159, 0, + digital_tlv), +SOC_DOUBLE_R_TLV("HPOUT3 Digital Volume", WM5100_DAC_DIGITAL_VOLUME_3L, + WM5100_DAC_DIGITAL_VOLUME_3R, WM5100_OUT3L_VOL_SHIFT, 159, 0, + digital_tlv), +SOC_DOUBLE_R_TLV("SPKOUT Digital Volume", WM5100_DAC_DIGITAL_VOLUME_4L, + WM5100_DAC_DIGITAL_VOLUME_4R, WM5100_OUT4L_VOL_SHIFT, 159, 0, + digital_tlv), +SOC_DOUBLE_R_TLV("SPKDAT1 Digital Volume", WM5100_DAC_DIGITAL_VOLUME_5L, + WM5100_DAC_DIGITAL_VOLUME_5R, WM5100_OUT5L_VOL_SHIFT, 159, 0, + digital_tlv), +SOC_DOUBLE_R_TLV("SPKDAT2 Digital Volume", WM5100_DAC_DIGITAL_VOLUME_6L, + WM5100_DAC_DIGITAL_VOLUME_6R, WM5100_OUT6L_VOL_SHIFT, 159, 0, + digital_tlv), + +SOC_DOUBLE_R("HPOUT1 Digital Switch", WM5100_DAC_DIGITAL_VOLUME_1L, + WM5100_DAC_DIGITAL_VOLUME_1R, WM5100_OUT1L_MUTE_SHIFT, 1, 1), +SOC_DOUBLE_R("HPOUT2 Digital Switch", WM5100_DAC_DIGITAL_VOLUME_2L, + WM5100_DAC_DIGITAL_VOLUME_2R, WM5100_OUT2L_MUTE_SHIFT, 1, 1), +SOC_DOUBLE_R("HPOUT3 Digital Switch", WM5100_DAC_DIGITAL_VOLUME_3L, + WM5100_DAC_DIGITAL_VOLUME_3R, WM5100_OUT3L_MUTE_SHIFT, 1, 1), +SOC_DOUBLE_R("SPKOUT Digital Switch", WM5100_DAC_DIGITAL_VOLUME_4L, + WM5100_DAC_DIGITAL_VOLUME_4R, WM5100_OUT4L_MUTE_SHIFT, 1, 1), +SOC_DOUBLE_R("SPKDAT1 Digital Switch", WM5100_DAC_DIGITAL_VOLUME_5L, + WM5100_DAC_DIGITAL_VOLUME_5R, WM5100_OUT5L_MUTE_SHIFT, 1, 1), +SOC_DOUBLE_R("SPKDAT2 Digital Switch", WM5100_DAC_DIGITAL_VOLUME_6L, + WM5100_DAC_DIGITAL_VOLUME_6R, WM5100_OUT6L_MUTE_SHIFT, 1, 1), + +/* FIXME: Only valid from -12dB to 0dB (52-64) */ +SOC_DOUBLE_R_TLV("HPOUT1 Volume", WM5100_OUT_VOLUME_1L, WM5100_OUT_VOLUME_1R, + WM5100_OUT1L_PGA_VOL_SHIFT, 64, 0, out_tlv), +SOC_DOUBLE_R_TLV("HPOUT2 Volume", WM5100_OUT_VOLUME_2L, WM5100_OUT_VOLUME_2R, + WM5100_OUT2L_PGA_VOL_SHIFT, 64, 0, out_tlv), +SOC_DOUBLE_R_TLV("HPOUT3 Volume", WM5100_OUT_VOLUME_3L, WM5100_OUT_VOLUME_3R, + WM5100_OUT2L_PGA_VOL_SHIFT, 64, 0, out_tlv), + +SOC_DOUBLE("SPKDAT1 Switch", WM5100_PDM_SPK1_CTRL_1, WM5100_SPK1L_MUTE_SHIFT, + WM5100_SPK1R_MUTE_SHIFT, 1, 1), +SOC_DOUBLE("SPKDAT2 Switch", WM5100_PDM_SPK2_CTRL_1, WM5100_SPK2L_MUTE_SHIFT, + WM5100_SPK2R_MUTE_SHIFT, 1, 1), + +SOC_SINGLE_TLV("EQ1 Band 1 Volume", WM5100_EQ1_1, WM5100_EQ1_B1_GAIN_SHIFT, + 24, 0, eq_tlv), +SOC_SINGLE_TLV("EQ1 Band 2 Volume", WM5100_EQ1_1, WM5100_EQ1_B2_GAIN_SHIFT, + 24, 0, eq_tlv), +SOC_SINGLE_TLV("EQ1 Band 3 Volume", WM5100_EQ1_1, WM5100_EQ1_B3_GAIN_SHIFT, + 24, 0, eq_tlv), +SOC_SINGLE_TLV("EQ1 Band 4 Volume", WM5100_EQ1_2, WM5100_EQ1_B4_GAIN_SHIFT, + 24, 0, eq_tlv), +SOC_SINGLE_TLV("EQ1 Band 5 Volume", WM5100_EQ1_2, WM5100_EQ1_B5_GAIN_SHIFT, + 24, 0, eq_tlv), + +SOC_SINGLE_TLV("EQ2 Band 1 Volume", WM5100_EQ2_1, WM5100_EQ2_B1_GAIN_SHIFT, + 24, 0, eq_tlv), +SOC_SINGLE_TLV("EQ2 Band 2 Volume", WM5100_EQ2_1, WM5100_EQ2_B2_GAIN_SHIFT, + 24, 0, eq_tlv), +SOC_SINGLE_TLV("EQ2 Band 3 Volume", WM5100_EQ2_1, WM5100_EQ2_B3_GAIN_SHIFT, + 24, 0, eq_tlv), +SOC_SINGLE_TLV("EQ2 Band 4 Volume", WM5100_EQ2_2, WM5100_EQ2_B4_GAIN_SHIFT, + 24, 0, eq_tlv), +SOC_SINGLE_TLV("EQ2 Band 5 Volume", WM5100_EQ2_2, WM5100_EQ2_B5_GAIN_SHIFT, + 24, 0, eq_tlv), + +SOC_SINGLE_TLV("EQ3 Band 1 Volume", WM5100_EQ1_1, WM5100_EQ3_B1_GAIN_SHIFT, + 24, 0, eq_tlv), +SOC_SINGLE_TLV("EQ3 Band 2 Volume", WM5100_EQ3_1, WM5100_EQ3_B2_GAIN_SHIFT, + 24, 0, eq_tlv), +SOC_SINGLE_TLV("EQ3 Band 3 Volume", WM5100_EQ3_1, WM5100_EQ3_B3_GAIN_SHIFT, + 24, 0, eq_tlv), +SOC_SINGLE_TLV("EQ3 Band 4 Volume", WM5100_EQ3_2, WM5100_EQ3_B4_GAIN_SHIFT, + 24, 0, eq_tlv), +SOC_SINGLE_TLV("EQ3 Band 5 Volume", WM5100_EQ3_2, WM5100_EQ3_B5_GAIN_SHIFT, + 24, 0, eq_tlv), + +SOC_SINGLE_TLV("EQ4 Band 1 Volume", WM5100_EQ4_1, WM5100_EQ4_B1_GAIN_SHIFT, + 24, 0, eq_tlv), +SOC_SINGLE_TLV("EQ4 Band 2 Volume", WM5100_EQ4_1, WM5100_EQ4_B2_GAIN_SHIFT, + 24, 0, eq_tlv), +SOC_SINGLE_TLV("EQ4 Band 3 Volume", WM5100_EQ4_1, WM5100_EQ4_B3_GAIN_SHIFT, + 24, 0, eq_tlv), +SOC_SINGLE_TLV("EQ4 Band 4 Volume", WM5100_EQ4_2, WM5100_EQ4_B4_GAIN_SHIFT, + 24, 0, eq_tlv), +SOC_SINGLE_TLV("EQ4 Band 5 Volume", WM5100_EQ4_2, WM5100_EQ4_B5_GAIN_SHIFT, + 24, 0, eq_tlv), + +SOC_ENUM("LHPF1 Mode", wm5100_lhpf1_mode), +SOC_ENUM("LHPF2 Mode", wm5100_lhpf2_mode), +SOC_ENUM("LHPF3 Mode", wm5100_lhpf3_mode), +SOC_ENUM("LHPF4 Mode", wm5100_lhpf4_mode), + +WM5100_MIXER_CONTROLS("HPOUT1L", WM5100_OUT1LMIX_INPUT_1_SOURCE), +WM5100_MIXER_CONTROLS("HPOUT1R", WM5100_OUT1RMIX_INPUT_1_SOURCE), +WM5100_MIXER_CONTROLS("HPOUT2L", WM5100_OUT2LMIX_INPUT_1_SOURCE), +WM5100_MIXER_CONTROLS("HPOUT2R", WM5100_OUT2RMIX_INPUT_1_SOURCE), +WM5100_MIXER_CONTROLS("HPOUT3L", WM5100_OUT3LMIX_INPUT_1_SOURCE), +WM5100_MIXER_CONTROLS("HPOUT3R", WM5100_OUT3RMIX_INPUT_1_SOURCE), + +WM5100_MIXER_CONTROLS("SPKOUTL", WM5100_OUT4LMIX_INPUT_1_SOURCE), +WM5100_MIXER_CONTROLS("SPKOUTR", WM5100_OUT4RMIX_INPUT_1_SOURCE), +WM5100_MIXER_CONTROLS("SPKDAT1L", WM5100_OUT5LMIX_INPUT_1_SOURCE), +WM5100_MIXER_CONTROLS("SPKDAT1R", WM5100_OUT5RMIX_INPUT_1_SOURCE), +WM5100_MIXER_CONTROLS("SPKDAT2L", WM5100_OUT6LMIX_INPUT_1_SOURCE), +WM5100_MIXER_CONTROLS("SPKDAT2R", WM5100_OUT6RMIX_INPUT_1_SOURCE), + +WM5100_MIXER_CONTROLS("PWM1", WM5100_PWM1MIX_INPUT_1_SOURCE), +WM5100_MIXER_CONTROLS("PWM2", WM5100_PWM2MIX_INPUT_1_SOURCE), + +WM5100_MIXER_CONTROLS("AIF1TX1", WM5100_AIF1TX1MIX_INPUT_1_SOURCE), +WM5100_MIXER_CONTROLS("AIF1TX2", WM5100_AIF1TX2MIX_INPUT_1_SOURCE), +WM5100_MIXER_CONTROLS("AIF1TX3", WM5100_AIF1TX3MIX_INPUT_1_SOURCE), +WM5100_MIXER_CONTROLS("AIF1TX4", WM5100_AIF1TX4MIX_INPUT_1_SOURCE), +WM5100_MIXER_CONTROLS("AIF1TX5", WM5100_AIF1TX5MIX_INPUT_1_SOURCE), +WM5100_MIXER_CONTROLS("AIF1TX6", WM5100_AIF1TX6MIX_INPUT_1_SOURCE), +WM5100_MIXER_CONTROLS("AIF1TX7", WM5100_AIF1TX7MIX_INPUT_1_SOURCE), +WM5100_MIXER_CONTROLS("AIF1TX8", WM5100_AIF1TX8MIX_INPUT_1_SOURCE), + +WM5100_MIXER_CONTROLS("AIF2TX1", WM5100_AIF2TX1MIX_INPUT_1_SOURCE), +WM5100_MIXER_CONTROLS("AIF2TX2", WM5100_AIF2TX2MIX_INPUT_1_SOURCE), + +WM5100_MIXER_CONTROLS("AIF3TX1", WM5100_AIF3TX1MIX_INPUT_1_SOURCE), +WM5100_MIXER_CONTROLS("AIF3TX2", WM5100_AIF3TX2MIX_INPUT_1_SOURCE), + +WM5100_MIXER_CONTROLS("EQ1", WM5100_EQ1MIX_INPUT_1_SOURCE), +WM5100_MIXER_CONTROLS("EQ2", WM5100_EQ2MIX_INPUT_1_SOURCE), +WM5100_MIXER_CONTROLS("EQ3", WM5100_EQ3MIX_INPUT_1_SOURCE), +WM5100_MIXER_CONTROLS("EQ4", WM5100_EQ4MIX_INPUT_1_SOURCE), + +WM5100_MIXER_CONTROLS("DRC1L", WM5100_DRC1LMIX_INPUT_1_SOURCE), +WM5100_MIXER_CONTROLS("DRC1R", WM5100_DRC1RMIX_INPUT_1_SOURCE), + +WM5100_MIXER_CONTROLS("LHPF1", WM5100_HPLP1MIX_INPUT_1_SOURCE), +WM5100_MIXER_CONTROLS("LHPF2", WM5100_HPLP2MIX_INPUT_1_SOURCE), +WM5100_MIXER_CONTROLS("LHPF3", WM5100_HPLP3MIX_INPUT_1_SOURCE), +WM5100_MIXER_CONTROLS("LHPF4", WM5100_HPLP4MIX_INPUT_1_SOURCE), +}; + +static void wm5100_seq_notifier(struct snd_soc_dapm_context *dapm, + enum snd_soc_dapm_type event, int subseq) +{ + struct snd_soc_codec *codec = container_of(dapm, + struct snd_soc_codec, dapm); + struct wm5100_priv *wm5100 = snd_soc_codec_get_drvdata(codec); + u16 val, expect, i; + + /* Wait for the outputs to flag themselves as enabled */ + if (wm5100->out_ena[0]) { + expect = snd_soc_read(codec, WM5100_CHANNEL_ENABLES_1); + for (i = 0; i < 200; i++) { + val = snd_soc_read(codec, WM5100_OUTPUT_STATUS_1); + if (val == expect) { + wm5100->out_ena[0] = false; + break; + } + } + if (i == 200) { + dev_err(codec->dev, "Timeout waiting for OUTPUT1 %x\n", + expect); + } + } + + if (wm5100->out_ena[1]) { + expect = snd_soc_read(codec, WM5100_OUTPUT_ENABLES_2); + for (i = 0; i < 200; i++) { + val = snd_soc_read(codec, WM5100_OUTPUT_STATUS_2); + if (val == expect) { + wm5100->out_ena[1] = false; + break; + } + } + if (i == 200) { + dev_err(codec->dev, "Timeout waiting for OUTPUT2 %x\n", + expect); + } + } +} + +static int wm5100_out_ev(struct snd_soc_dapm_widget *w, + struct snd_kcontrol *kcontrol, + int event) +{ + struct wm5100_priv *wm5100 = snd_soc_codec_get_drvdata(w->codec); + + switch (w->reg) { + case WM5100_CHANNEL_ENABLES_1: + wm5100->out_ena[0] = true; + break; + case WM5100_OUTPUT_ENABLES_2: + wm5100->out_ena[0] = true; + break; + default: + break; + } + + return 0; +} + +static int wm5100_cp_ev(struct snd_soc_dapm_widget *w, + struct snd_kcontrol *kcontrol, + int event) +{ + struct snd_soc_codec *codec = w->codec; + struct wm5100_priv *wm5100 = snd_soc_codec_get_drvdata(codec); + int ret; + + switch (event) { + case SND_SOC_DAPM_PRE_PMU: + ret = regulator_enable(wm5100->cpvdd); + if (ret != 0) { + dev_err(codec->dev, "Failed to enable CPVDD: %d\n", + ret); + return ret; + } + return ret; + + case SND_SOC_DAPM_POST_PMD: + ret = regulator_disable_deferred(wm5100->cpvdd, 20); + if (ret != 0) { + dev_err(codec->dev, "Failed to disable CPVDD: %d\n", + ret); + return ret; + } + return ret; + + default: + BUG(); + return 0; + } +} + +static int wm5100_dbvdd_ev(struct snd_soc_dapm_widget *w, + struct snd_kcontrol *kcontrol, + int event) +{ + struct snd_soc_codec *codec = w->codec; + struct wm5100_priv *wm5100 = snd_soc_codec_get_drvdata(codec); + struct regulator *regulator; + int ret; + + switch (w->shift) { + case 2: + regulator = wm5100->dbvdd2; + break; + case 3: + regulator = wm5100->dbvdd3; + break; + default: + BUG(); + return 0; + } + + switch (event) { + case SND_SOC_DAPM_PRE_PMU: + ret = regulator_enable(regulator); + if (ret != 0) { + dev_err(codec->dev, "Failed to enable DBVDD%d: %d\n", + w->shift, ret); + return ret; + } + return ret; + + case SND_SOC_DAPM_POST_PMD: + ret = regulator_disable(regulator); + if (ret != 0) { + dev_err(codec->dev, "Failed to enable DBVDD%d: %d\n", + w->shift, ret); + return ret; + } + return ret; + + default: + BUG(); + return 0; + } +} + +static void wm5100_log_status3(struct snd_soc_codec *codec, int val) +{ + if (val & WM5100_SPK_SHUTDOWN_WARN_EINT) + dev_crit(codec->dev, "Speaker shutdown warning\n"); + if (val & WM5100_SPK_SHUTDOWN_EINT) + dev_crit(codec->dev, "Speaker shutdown\n"); + if (val & WM5100_CLKGEN_ERR_EINT) + dev_crit(codec->dev, "SYSCLK underclocked\n"); + if (val & WM5100_CLKGEN_ERR_ASYNC_EINT) + dev_crit(codec->dev, "ASYNCCLK underclocked\n"); +} + +static void wm5100_log_status4(struct snd_soc_codec *codec, int val) +{ + if (val & WM5100_AIF3_ERR_EINT) + dev_err(codec->dev, "AIF3 configuration error\n"); + if (val & WM5100_AIF2_ERR_EINT) + dev_err(codec->dev, "AIF2 configuration error\n"); + if (val & WM5100_AIF1_ERR_EINT) + dev_err(codec->dev, "AIF1 configuration error\n"); + if (val & WM5100_CTRLIF_ERR_EINT) + dev_err(codec->dev, "Control interface error\n"); + if (val & WM5100_ISRC2_UNDERCLOCKED_EINT) + dev_err(codec->dev, "ISRC2 underclocked\n"); + if (val & WM5100_ISRC1_UNDERCLOCKED_EINT) + dev_err(codec->dev, "ISRC1 underclocked\n"); + if (val & WM5100_FX_UNDERCLOCKED_EINT) + dev_err(codec->dev, "FX underclocked\n"); + if (val & WM5100_AIF3_UNDERCLOCKED_EINT) + dev_err(codec->dev, "AIF3 underclocked\n"); + if (val & WM5100_AIF2_UNDERCLOCKED_EINT) + dev_err(codec->dev, "AIF2 underclocked\n"); + if (val & WM5100_AIF1_UNDERCLOCKED_EINT) + dev_err(codec->dev, "AIF1 underclocked\n"); + if (val & WM5100_ASRC_UNDERCLOCKED_EINT) + dev_err(codec->dev, "ASRC underclocked\n"); + if (val & WM5100_DAC_UNDERCLOCKED_EINT) + dev_err(codec->dev, "DAC underclocked\n"); + if (val & WM5100_ADC_UNDERCLOCKED_EINT) + dev_err(codec->dev, "ADC underclocked\n"); + if (val & WM5100_MIXER_UNDERCLOCKED_EINT) + dev_err(codec->dev, "Mixer underclocked\n"); +} + +static int wm5100_post_ev(struct snd_soc_dapm_widget *w, + struct snd_kcontrol *kcontrol, + int event) +{ + struct snd_soc_codec *codec = w->codec; + int ret; + + ret = snd_soc_read(codec, WM5100_INTERRUPT_RAW_STATUS_3); + ret &= WM5100_SPK_SHUTDOWN_WARN_STS | + WM5100_SPK_SHUTDOWN_STS | WM5100_CLKGEN_ERR_STS | + WM5100_CLKGEN_ERR_ASYNC_STS; + wm5100_log_status3(codec, ret); + + ret = snd_soc_read(codec, WM5100_INTERRUPT_RAW_STATUS_4); + wm5100_log_status4(codec, ret); + + return 0; +} + +static const struct snd_soc_dapm_widget wm5100_dapm_widgets[] = { +SND_SOC_DAPM_SUPPLY("SYSCLK", WM5100_CLOCKING_3, WM5100_SYSCLK_ENA_SHIFT, 0, + NULL, 0), +SND_SOC_DAPM_SUPPLY("ASYNCCLK", WM5100_CLOCKING_6, WM5100_ASYNC_CLK_ENA_SHIFT, + 0, NULL, 0), + +SND_SOC_DAPM_SUPPLY("CP1", WM5100_HP_CHARGE_PUMP_1, WM5100_CP1_ENA_SHIFT, 0, + wm5100_cp_ev, + SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD), +SND_SOC_DAPM_SUPPLY("CP2", WM5100_MIC_CHARGE_PUMP_1, WM5100_CP2_ENA_SHIFT, 0, + NULL, 0), +SND_SOC_DAPM_SUPPLY("CP2 Active", WM5100_MIC_CHARGE_PUMP_1, + WM5100_CP2_BYPASS_SHIFT, 1, wm5100_cp_ev, + SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD), +SND_SOC_DAPM_SUPPLY("DBVDD2", SND_SOC_NOPM, 2, 0, wm5100_dbvdd_ev, + SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD), +SND_SOC_DAPM_SUPPLY("DBVDD3", SND_SOC_NOPM, 3, 0, wm5100_dbvdd_ev, + SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD), + +SND_SOC_DAPM_SUPPLY("MICBIAS1", WM5100_MIC_BIAS_CTRL_1, WM5100_MICB1_ENA_SHIFT, + 0, NULL, 0), +SND_SOC_DAPM_SUPPLY("MICBIAS2", WM5100_MIC_BIAS_CTRL_2, WM5100_MICB2_ENA_SHIFT, + 0, NULL, 0), +SND_SOC_DAPM_SUPPLY("MICBIAS3", WM5100_MIC_BIAS_CTRL_3, WM5100_MICB3_ENA_SHIFT, + 0, NULL, 0), + +SND_SOC_DAPM_INPUT("IN1L"), +SND_SOC_DAPM_INPUT("IN1R"), +SND_SOC_DAPM_INPUT("IN2L"), +SND_SOC_DAPM_INPUT("IN2R"), +SND_SOC_DAPM_INPUT("IN3L"), +SND_SOC_DAPM_INPUT("IN3R"), +SND_SOC_DAPM_INPUT("IN4L"), +SND_SOC_DAPM_INPUT("IN4R"), +SND_SOC_DAPM_INPUT("TONE"), + +SND_SOC_DAPM_PGA_E("IN1L PGA", WM5100_INPUT_ENABLES, WM5100_IN1L_ENA_SHIFT, 0, + NULL, 0, wm5100_out_ev, SND_SOC_DAPM_POST_PMU), +SND_SOC_DAPM_PGA_E("IN1R PGA", WM5100_INPUT_ENABLES, WM5100_IN1R_ENA_SHIFT, 0, + NULL, 0, wm5100_out_ev, SND_SOC_DAPM_POST_PMU), +SND_SOC_DAPM_PGA_E("IN2L PGA", WM5100_INPUT_ENABLES, WM5100_IN2L_ENA_SHIFT, 0, + NULL, 0, wm5100_out_ev, SND_SOC_DAPM_POST_PMU), +SND_SOC_DAPM_PGA_E("IN2R PGA", WM5100_INPUT_ENABLES, WM5100_IN2R_ENA_SHIFT, 0, + NULL, 0, wm5100_out_ev, SND_SOC_DAPM_POST_PMU), +SND_SOC_DAPM_PGA_E("IN3L PGA", WM5100_INPUT_ENABLES, WM5100_IN3L_ENA_SHIFT, 0, + NULL, 0, wm5100_out_ev, SND_SOC_DAPM_POST_PMU), +SND_SOC_DAPM_PGA_E("IN3R PGA", WM5100_INPUT_ENABLES, WM5100_IN3R_ENA_SHIFT, 0, + NULL, 0, wm5100_out_ev, SND_SOC_DAPM_POST_PMU), +SND_SOC_DAPM_PGA_E("IN4L PGA", WM5100_INPUT_ENABLES, WM5100_IN4L_ENA_SHIFT, 0, + NULL, 0, wm5100_out_ev, SND_SOC_DAPM_POST_PMU), +SND_SOC_DAPM_PGA_E("IN4R PGA", WM5100_INPUT_ENABLES, WM5100_IN4R_ENA_SHIFT, 0, + NULL, 0, wm5100_out_ev, SND_SOC_DAPM_POST_PMU), + +SND_SOC_DAPM_PGA("Tone Generator 1", WM5100_TONE_GENERATOR_1, + WM5100_TONE1_ENA_SHIFT, 0, NULL, 0), +SND_SOC_DAPM_PGA("Tone Generator 2", WM5100_TONE_GENERATOR_1, + WM5100_TONE2_ENA_SHIFT, 0, NULL, 0), + +SND_SOC_DAPM_AIF_IN("AIF1RX1", "AIF1 Playback", 0, + WM5100_AUDIO_IF_1_27, WM5100_AIF1RX1_ENA_SHIFT, 0), +SND_SOC_DAPM_AIF_IN("AIF1RX2", "AIF1 Playback", 1, + WM5100_AUDIO_IF_1_27, WM5100_AIF1RX2_ENA_SHIFT, 0), +SND_SOC_DAPM_AIF_IN("AIF1RX3", "AIF1 Playback", 2, + WM5100_AUDIO_IF_1_27, WM5100_AIF1RX3_ENA_SHIFT, 0), +SND_SOC_DAPM_AIF_IN("AIF1RX4", "AIF1 Playback", 3, + WM5100_AUDIO_IF_1_27, WM5100_AIF1RX4_ENA_SHIFT, 0), +SND_SOC_DAPM_AIF_IN("AIF1RX5", "AIF1 Playback", 4, + WM5100_AUDIO_IF_1_27, WM5100_AIF1RX5_ENA_SHIFT, 0), +SND_SOC_DAPM_AIF_IN("AIF1RX6", "AIF1 Playback", 5, + WM5100_AUDIO_IF_1_27, WM5100_AIF1RX6_ENA_SHIFT, 0), +SND_SOC_DAPM_AIF_IN("AIF1RX7", "AIF1 Playback", 6, + WM5100_AUDIO_IF_1_27, WM5100_AIF1RX7_ENA_SHIFT, 0), +SND_SOC_DAPM_AIF_IN("AIF1RX8", "AIF1 Playback", 7, + WM5100_AUDIO_IF_1_27, WM5100_AIF1RX8_ENA_SHIFT, 0), + +SND_SOC_DAPM_AIF_IN("AIF2RX1", "AIF2 Playback", 0, + WM5100_AUDIO_IF_2_27, WM5100_AIF2RX1_ENA_SHIFT, 0), +SND_SOC_DAPM_AIF_IN("AIF2RX2", "AIF2 Playback", 1, + WM5100_AUDIO_IF_2_27, WM5100_AIF2RX2_ENA_SHIFT, 0), + +SND_SOC_DAPM_AIF_IN("AIF3RX1", "AIF3 Playback", 0, + WM5100_AUDIO_IF_3_27, WM5100_AIF3RX1_ENA_SHIFT, 0), +SND_SOC_DAPM_AIF_IN("AIF3RX2", "AIF3 Playback", 1, + WM5100_AUDIO_IF_3_27, WM5100_AIF3RX2_ENA_SHIFT, 0), + +SND_SOC_DAPM_AIF_OUT("AIF1TX1", "AIF1 Capture", 0, + WM5100_AUDIO_IF_1_26, WM5100_AIF1TX1_ENA_SHIFT, 0), +SND_SOC_DAPM_AIF_OUT("AIF1TX2", "AIF1 Capture", 1, + WM5100_AUDIO_IF_1_26, WM5100_AIF1TX2_ENA_SHIFT, 0), +SND_SOC_DAPM_AIF_OUT("AIF1TX3", "AIF1 Capture", 2, + WM5100_AUDIO_IF_1_26, WM5100_AIF1TX3_ENA_SHIFT, 0), +SND_SOC_DAPM_AIF_OUT("AIF1TX4", "AIF1 Capture", 3, + WM5100_AUDIO_IF_1_26, WM5100_AIF1TX4_ENA_SHIFT, 0), +SND_SOC_DAPM_AIF_OUT("AIF1TX5", "AIF1 Capture", 4, + WM5100_AUDIO_IF_1_26, WM5100_AIF1TX5_ENA_SHIFT, 0), +SND_SOC_DAPM_AIF_OUT("AIF1TX6", "AIF1 Capture", 5, + WM5100_AUDIO_IF_1_26, WM5100_AIF1TX6_ENA_SHIFT, 0), +SND_SOC_DAPM_AIF_OUT("AIF1TX7", "AIF1 Capture", 6, + WM5100_AUDIO_IF_1_26, WM5100_AIF1TX7_ENA_SHIFT, 0), +SND_SOC_DAPM_AIF_OUT("AIF1TX8", "AIF1 Capture", 7, + WM5100_AUDIO_IF_1_26, WM5100_AIF1TX8_ENA_SHIFT, 0), + +SND_SOC_DAPM_AIF_OUT("AIF2TX1", "AIF2 Capture", 0, + WM5100_AUDIO_IF_2_26, WM5100_AIF2TX1_ENA_SHIFT, 0), +SND_SOC_DAPM_AIF_OUT("AIF2TX2", "AIF2 Capture", 1, + WM5100_AUDIO_IF_2_26, WM5100_AIF2TX2_ENA_SHIFT, 0), + +SND_SOC_DAPM_AIF_OUT("AIF3TX1", "AIF3 Capture", 0, + WM5100_AUDIO_IF_3_26, WM5100_AIF3TX1_ENA_SHIFT, 0), +SND_SOC_DAPM_AIF_OUT("AIF3TX2", "AIF3 Capture", 1, + WM5100_AUDIO_IF_3_26, WM5100_AIF3TX2_ENA_SHIFT, 0), + +SND_SOC_DAPM_PGA_E("OUT6L", WM5100_OUTPUT_ENABLES_2, WM5100_OUT6L_ENA_SHIFT, 0, + NULL, 0, wm5100_out_ev, SND_SOC_DAPM_POST_PMU), +SND_SOC_DAPM_PGA_E("OUT6R", WM5100_OUTPUT_ENABLES_2, WM5100_OUT6R_ENA_SHIFT, 0, + NULL, 0, wm5100_out_ev, SND_SOC_DAPM_POST_PMU), +SND_SOC_DAPM_PGA_E("OUT5L", WM5100_OUTPUT_ENABLES_2, WM5100_OUT5L_ENA_SHIFT, 0, + NULL, 0, wm5100_out_ev, SND_SOC_DAPM_POST_PMU), +SND_SOC_DAPM_PGA_E("OUT5R", WM5100_OUTPUT_ENABLES_2, WM5100_OUT5R_ENA_SHIFT, 0, + NULL, 0, wm5100_out_ev, SND_SOC_DAPM_POST_PMU), +SND_SOC_DAPM_PGA_E("OUT4L", WM5100_OUTPUT_ENABLES_2, WM5100_OUT4L_ENA_SHIFT, 0, + NULL, 0, wm5100_out_ev, SND_SOC_DAPM_POST_PMU), +SND_SOC_DAPM_PGA_E("OUT4R", WM5100_OUTPUT_ENABLES_2, WM5100_OUT4R_ENA_SHIFT, 0, + NULL, 0, wm5100_out_ev, SND_SOC_DAPM_POST_PMU), +SND_SOC_DAPM_PGA_E("OUT3L", WM5100_CHANNEL_ENABLES_1, WM5100_HP3L_ENA_SHIFT, 0, + NULL, 0, wm5100_out_ev, SND_SOC_DAPM_POST_PMU), +SND_SOC_DAPM_PGA_E("OUT3R", WM5100_CHANNEL_ENABLES_1, WM5100_HP3R_ENA_SHIFT, 0, + NULL, 0, wm5100_out_ev, SND_SOC_DAPM_POST_PMU), +SND_SOC_DAPM_PGA_E("OUT2L", WM5100_CHANNEL_ENABLES_1, WM5100_HP2L_ENA_SHIFT, 0, + NULL, 0, wm5100_out_ev, SND_SOC_DAPM_POST_PMU), +SND_SOC_DAPM_PGA_E("OUT2R", WM5100_CHANNEL_ENABLES_1, WM5100_HP2R_ENA_SHIFT, 0, + NULL, 0, wm5100_out_ev, SND_SOC_DAPM_POST_PMU), +SND_SOC_DAPM_PGA_E("OUT1L", WM5100_CHANNEL_ENABLES_1, WM5100_HP1L_ENA_SHIFT, 0, + NULL, 0, wm5100_out_ev, SND_SOC_DAPM_POST_PMU), +SND_SOC_DAPM_PGA_E("OUT1R", WM5100_CHANNEL_ENABLES_1, WM5100_HP1R_ENA_SHIFT, 0, + NULL, 0, wm5100_out_ev, SND_SOC_DAPM_POST_PMU), +SND_SOC_DAPM_PGA_E("PWM1 Driver", WM5100_PWM_DRIVE_1, WM5100_PWM1_ENA_SHIFT, 0, + NULL, 0, wm5100_out_ev, SND_SOC_DAPM_POST_PMU), +SND_SOC_DAPM_PGA_E("PWM2 Driver", WM5100_PWM_DRIVE_1, WM5100_PWM2_ENA_SHIFT, 0, + NULL, 0, wm5100_out_ev, SND_SOC_DAPM_POST_PMU), + +SND_SOC_DAPM_PGA("EQ1", WM5100_EQ1_1, WM5100_EQ1_ENA_SHIFT, 0, NULL, 0), +SND_SOC_DAPM_PGA("EQ2", WM5100_EQ2_1, WM5100_EQ2_ENA_SHIFT, 0, NULL, 0), +SND_SOC_DAPM_PGA("EQ3", WM5100_EQ3_1, WM5100_EQ3_ENA_SHIFT, 0, NULL, 0), +SND_SOC_DAPM_PGA("EQ4", WM5100_EQ4_1, WM5100_EQ4_ENA_SHIFT, 0, NULL, 0), + +SND_SOC_DAPM_PGA("DRC1L", WM5100_DRC1_CTRL1, WM5100_DRCL_ENA_SHIFT, 0, + NULL, 0), +SND_SOC_DAPM_PGA("DRC1R", WM5100_DRC1_CTRL1, WM5100_DRCR_ENA_SHIFT, 0, + NULL, 0), + +SND_SOC_DAPM_PGA("LHPF1", WM5100_HPLPF1_1, WM5100_LHPF1_ENA_SHIFT, 0, + NULL, 0), +SND_SOC_DAPM_PGA("LHPF2", WM5100_HPLPF2_1, WM5100_LHPF2_ENA_SHIFT, 0, + NULL, 0), +SND_SOC_DAPM_PGA("LHPF3", WM5100_HPLPF3_1, WM5100_LHPF3_ENA_SHIFT, 0, + NULL, 0), +SND_SOC_DAPM_PGA("LHPF4", WM5100_HPLPF4_1, WM5100_LHPF4_ENA_SHIFT, 0, + NULL, 0), + +WM5100_MIXER_WIDGETS(EQ1, "EQ1"), +WM5100_MIXER_WIDGETS(EQ2, "EQ2"), +WM5100_MIXER_WIDGETS(EQ3, "EQ3"), +WM5100_MIXER_WIDGETS(EQ4, "EQ4"), + +WM5100_MIXER_WIDGETS(DRC1L, "DRC1L"), +WM5100_MIXER_WIDGETS(DRC1R, "DRC1R"), + +WM5100_MIXER_WIDGETS(LHPF1, "LHPF1"), +WM5100_MIXER_WIDGETS(LHPF2, "LHPF2"), +WM5100_MIXER_WIDGETS(LHPF3, "LHPF3"), +WM5100_MIXER_WIDGETS(LHPF4, "LHPF4"), + +WM5100_MIXER_WIDGETS(AIF1TX1, "AIF1TX1"), +WM5100_MIXER_WIDGETS(AIF1TX2, "AIF1TX2"), +WM5100_MIXER_WIDGETS(AIF1TX3, "AIF1TX3"), +WM5100_MIXER_WIDGETS(AIF1TX4, "AIF1TX4"), +WM5100_MIXER_WIDGETS(AIF1TX5, "AIF1TX5"), +WM5100_MIXER_WIDGETS(AIF1TX6, "AIF1TX6"), +WM5100_MIXER_WIDGETS(AIF1TX7, "AIF1TX7"), +WM5100_MIXER_WIDGETS(AIF1TX8, "AIF1TX8"), + +WM5100_MIXER_WIDGETS(AIF2TX1, "AIF2TX1"), +WM5100_MIXER_WIDGETS(AIF2TX2, "AIF2TX2"), + +WM5100_MIXER_WIDGETS(AIF3TX1, "AIF3TX1"), +WM5100_MIXER_WIDGETS(AIF3TX2, "AIF3TX2"), + +WM5100_MIXER_WIDGETS(HPOUT1L, "HPOUT1L"), +WM5100_MIXER_WIDGETS(HPOUT1R, "HPOUT1R"), +WM5100_MIXER_WIDGETS(HPOUT2L, "HPOUT2L"), +WM5100_MIXER_WIDGETS(HPOUT2R, "HPOUT2R"), +WM5100_MIXER_WIDGETS(HPOUT3L, "HPOUT3L"), +WM5100_MIXER_WIDGETS(HPOUT3R, "HPOUT3R"), + +WM5100_MIXER_WIDGETS(SPKOUTL, "SPKOUTL"), +WM5100_MIXER_WIDGETS(SPKOUTR, "SPKOUTR"), +WM5100_MIXER_WIDGETS(SPKDAT1L, "SPKDAT1L"), +WM5100_MIXER_WIDGETS(SPKDAT1R, "SPKDAT1R"), +WM5100_MIXER_WIDGETS(SPKDAT2L, "SPKDAT2L"), +WM5100_MIXER_WIDGETS(SPKDAT2R, "SPKDAT2R"), + +WM5100_MIXER_WIDGETS(PWM1, "PWM1"), +WM5100_MIXER_WIDGETS(PWM2, "PWM2"), + +SND_SOC_DAPM_OUTPUT("HPOUT1L"), +SND_SOC_DAPM_OUTPUT("HPOUT1R"), +SND_SOC_DAPM_OUTPUT("HPOUT2L"), +SND_SOC_DAPM_OUTPUT("HPOUT2R"), +SND_SOC_DAPM_OUTPUT("HPOUT3L"), +SND_SOC_DAPM_OUTPUT("HPOUT3R"), +SND_SOC_DAPM_OUTPUT("SPKOUTL"), +SND_SOC_DAPM_OUTPUT("SPKOUTR"), +SND_SOC_DAPM_OUTPUT("SPKDAT1"), +SND_SOC_DAPM_OUTPUT("SPKDAT2"), +SND_SOC_DAPM_OUTPUT("PWM1"), +SND_SOC_DAPM_OUTPUT("PWM2"), +}; + +/* We register a _POST event if we don't have IRQ support so we can + * look at the error status from the CODEC - if we've got the IRQ + * hooked up then we will get prompted to look by an interrupt. + */ +static const struct snd_soc_dapm_widget wm5100_dapm_widgets_noirq[] = { +SND_SOC_DAPM_POST("Post", wm5100_post_ev), +}; + +static const struct snd_soc_dapm_route wm5100_dapm_routes[] = { + { "IN1L", NULL, "SYSCLK" }, + { "IN1R", NULL, "SYSCLK" }, + { "IN2L", NULL, "SYSCLK" }, + { "IN2R", NULL, "SYSCLK" }, + { "IN3L", NULL, "SYSCLK" }, + { "IN3R", NULL, "SYSCLK" }, + { "IN4L", NULL, "SYSCLK" }, + { "IN4R", NULL, "SYSCLK" }, + + { "OUT1L", NULL, "SYSCLK" }, + { "OUT1R", NULL, "SYSCLK" }, + { "OUT2L", NULL, "SYSCLK" }, + { "OUT2R", NULL, "SYSCLK" }, + { "OUT3L", NULL, "SYSCLK" }, + { "OUT3R", NULL, "SYSCLK" }, + { "OUT4L", NULL, "SYSCLK" }, + { "OUT4R", NULL, "SYSCLK" }, + { "OUT5L", NULL, "SYSCLK" }, + { "OUT5R", NULL, "SYSCLK" }, + { "OUT6L", NULL, "SYSCLK" }, + { "OUT6R", NULL, "SYSCLK" }, + + { "AIF1RX1", NULL, "SYSCLK" }, + { "AIF1RX2", NULL, "SYSCLK" }, + { "AIF1RX3", NULL, "SYSCLK" }, + { "AIF1RX4", NULL, "SYSCLK" }, + { "AIF1RX5", NULL, "SYSCLK" }, + { "AIF1RX6", NULL, "SYSCLK" }, + { "AIF1RX7", NULL, "SYSCLK" }, + { "AIF1RX8", NULL, "SYSCLK" }, + + { "AIF2RX1", NULL, "SYSCLK" }, + { "AIF2RX1", NULL, "DBVDD2" }, + { "AIF2RX2", NULL, "SYSCLK" }, + { "AIF2RX2", NULL, "DBVDD2" }, + + { "AIF3RX1", NULL, "SYSCLK" }, + { "AIF3RX1", NULL, "DBVDD3" }, + { "AIF3RX2", NULL, "SYSCLK" }, + { "AIF3RX2", NULL, "DBVDD3" }, + + { "AIF1TX1", NULL, "SYSCLK" }, + { "AIF1TX2", NULL, "SYSCLK" }, + { "AIF1TX3", NULL, "SYSCLK" }, + { "AIF1TX4", NULL, "SYSCLK" }, + { "AIF1TX5", NULL, "SYSCLK" }, + { "AIF1TX6", NULL, "SYSCLK" }, + { "AIF1TX7", NULL, "SYSCLK" }, + { "AIF1TX8", NULL, "SYSCLK" }, + + { "AIF2TX1", NULL, "SYSCLK" }, + { "AIF2TX1", NULL, "DBVDD2" }, + { "AIF2TX2", NULL, "SYSCLK" }, + { "AIF2TX2", NULL, "DBVDD2" }, + + { "AIF3TX1", NULL, "SYSCLK" }, + { "AIF3TX1", NULL, "DBVDD3" }, + { "AIF3TX2", NULL, "SYSCLK" }, + { "AIF3TX2", NULL, "DBVDD3" }, + + { "MICBIAS1", NULL, "CP2" }, + { "MICBIAS2", NULL, "CP2" }, + { "MICBIAS3", NULL, "CP2" }, + + { "IN1L PGA", NULL, "CP2" }, + { "IN1R PGA", NULL, "CP2" }, + { "IN2L PGA", NULL, "CP2" }, + { "IN2R PGA", NULL, "CP2" }, + { "IN3L PGA", NULL, "CP2" }, + { "IN3R PGA", NULL, "CP2" }, + { "IN4L PGA", NULL, "CP2" }, + { "IN4R PGA", NULL, "CP2" }, + + { "IN1L PGA", NULL, "CP2 Active" }, + { "IN1R PGA", NULL, "CP2 Active" }, + { "IN2L PGA", NULL, "CP2 Active" }, + { "IN2R PGA", NULL, "CP2 Active" }, + { "IN3L PGA", NULL, "CP2 Active" }, + { "IN3R PGA", NULL, "CP2 Active" }, + { "IN4L PGA", NULL, "CP2 Active" }, + { "IN4R PGA", NULL, "CP2 Active" }, + + { "OUT1L", NULL, "CP1" }, + { "OUT1R", NULL, "CP1" }, + { "OUT2L", NULL, "CP1" }, + { "OUT2R", NULL, "CP1" }, + { "OUT3L", NULL, "CP1" }, + { "OUT3R", NULL, "CP1" }, + + { "Tone Generator 1", NULL, "TONE" }, + { "Tone Generator 2", NULL, "TONE" }, + + { "IN1L PGA", NULL, "IN1L" }, + { "IN1R PGA", NULL, "IN1R" }, + { "IN2L PGA", NULL, "IN2L" }, + { "IN2R PGA", NULL, "IN2R" }, + { "IN3L PGA", NULL, "IN3L" }, + { "IN3R PGA", NULL, "IN3R" }, + { "IN4L PGA", NULL, "IN4L" }, + { "IN4R PGA", NULL, "IN4R" }, + + WM5100_MIXER_ROUTES("OUT1L", "HPOUT1L"), + WM5100_MIXER_ROUTES("OUT1R", "HPOUT1R"), + WM5100_MIXER_ROUTES("OUT2L", "HPOUT2L"), + WM5100_MIXER_ROUTES("OUT2R", "HPOUT2R"), + WM5100_MIXER_ROUTES("OUT3L", "HPOUT3L"), + WM5100_MIXER_ROUTES("OUT3R", "HPOUT3R"), + + WM5100_MIXER_ROUTES("OUT4L", "SPKOUTL"), + WM5100_MIXER_ROUTES("OUT4R", "SPKOUTR"), + WM5100_MIXER_ROUTES("OUT5L", "SPKDAT1L"), + WM5100_MIXER_ROUTES("OUT5R", "SPKDAT1R"), + WM5100_MIXER_ROUTES("OUT6L", "SPKDAT2L"), + WM5100_MIXER_ROUTES("OUT6R", "SPKDAT2R"), + + WM5100_MIXER_ROUTES("PWM1 Driver", "PWM1"), + WM5100_MIXER_ROUTES("PWM2 Driver", "PWM2"), + + WM5100_MIXER_ROUTES("AIF1TX1", "AIF1TX1"), + WM5100_MIXER_ROUTES("AIF1TX2", "AIF1TX2"), + WM5100_MIXER_ROUTES("AIF1TX3", "AIF1TX3"), + WM5100_MIXER_ROUTES("AIF1TX4", "AIF1TX4"), + WM5100_MIXER_ROUTES("AIF1TX5", "AIF1TX5"), + WM5100_MIXER_ROUTES("AIF1TX6", "AIF1TX6"), + WM5100_MIXER_ROUTES("AIF1TX7", "AIF1TX7"), + WM5100_MIXER_ROUTES("AIF1TX8", "AIF1TX8"), + + WM5100_MIXER_ROUTES("AIF2TX1", "AIF2TX1"), + WM5100_MIXER_ROUTES("AIF2TX2", "AIF2TX2"), + + WM5100_MIXER_ROUTES("AIF3TX1", "AIF3TX1"), + WM5100_MIXER_ROUTES("AIF3TX2", "AIF3TX2"), + + WM5100_MIXER_ROUTES("EQ1", "EQ1"), + WM5100_MIXER_ROUTES("EQ2", "EQ2"), + WM5100_MIXER_ROUTES("EQ3", "EQ3"), + WM5100_MIXER_ROUTES("EQ4", "EQ4"), + + WM5100_MIXER_ROUTES("DRC1L", "DRC1L"), + WM5100_MIXER_ROUTES("DRC1R", "DRC1R"), + + WM5100_MIXER_ROUTES("LHPF1", "LHPF1"), + WM5100_MIXER_ROUTES("LHPF2", "LHPF2"), + WM5100_MIXER_ROUTES("LHPF3", "LHPF3"), + WM5100_MIXER_ROUTES("LHPF4", "LHPF4"), + + { "HPOUT1L", NULL, "OUT1L" }, + { "HPOUT1R", NULL, "OUT1R" }, + { "HPOUT2L", NULL, "OUT2L" }, + { "HPOUT2R", NULL, "OUT2R" }, + { "HPOUT3L", NULL, "OUT3L" }, + { "HPOUT3R", NULL, "OUT3R" }, + { "SPKOUTL", NULL, "OUT4L" }, + { "SPKOUTR", NULL, "OUT4R" }, + { "SPKDAT1", NULL, "OUT5L" }, + { "SPKDAT1", NULL, "OUT5R" }, + { "SPKDAT2", NULL, "OUT6L" }, + { "SPKDAT2", NULL, "OUT6R" }, + { "PWM1", NULL, "PWM1 Driver" }, + { "PWM2", NULL, "PWM2 Driver" }, +}; + +static struct { + int reg; + int val; +} wm5100_reva_patches[] = { + { WM5100_AUDIO_IF_1_10, 0 }, + { WM5100_AUDIO_IF_1_11, 1 }, + { WM5100_AUDIO_IF_1_12, 2 }, + { WM5100_AUDIO_IF_1_13, 3 }, + { WM5100_AUDIO_IF_1_14, 4 }, + { WM5100_AUDIO_IF_1_15, 5 }, + { WM5100_AUDIO_IF_1_16, 6 }, + { WM5100_AUDIO_IF_1_17, 7 }, + + { WM5100_AUDIO_IF_1_18, 0 }, + { WM5100_AUDIO_IF_1_19, 1 }, + { WM5100_AUDIO_IF_1_20, 2 }, + { WM5100_AUDIO_IF_1_21, 3 }, + { WM5100_AUDIO_IF_1_22, 4 }, + { WM5100_AUDIO_IF_1_23, 5 }, + { WM5100_AUDIO_IF_1_24, 6 }, + { WM5100_AUDIO_IF_1_25, 7 }, + + { WM5100_AUDIO_IF_2_10, 0 }, + { WM5100_AUDIO_IF_2_11, 1 }, + + { WM5100_AUDIO_IF_2_18, 0 }, + { WM5100_AUDIO_IF_2_19, 1 }, + + { WM5100_AUDIO_IF_3_10, 0 }, + { WM5100_AUDIO_IF_3_11, 1 }, + + { WM5100_AUDIO_IF_3_18, 0 }, + { WM5100_AUDIO_IF_3_19, 1 }, +}; + +static int wm5100_set_bias_level(struct snd_soc_codec *codec, + enum snd_soc_bias_level level) +{ + struct wm5100_priv *wm5100 = snd_soc_codec_get_drvdata(codec); + int ret, i; + + switch (level) { + case SND_SOC_BIAS_ON: + break; + + case SND_SOC_BIAS_PREPARE: + break; + + case SND_SOC_BIAS_STANDBY: + if (codec->dapm.bias_level == SND_SOC_BIAS_OFF) { + ret = regulator_bulk_enable(ARRAY_SIZE(wm5100->core_supplies), + wm5100->core_supplies); + if (ret != 0) { + dev_err(codec->dev, + "Failed to enable supplies: %d\n", + ret); + return ret; + } + + if (wm5100->pdata.ldo_ena) { + gpio_set_value_cansleep(wm5100->pdata.ldo_ena, + 1); + msleep(2); + } + + codec->cache_only = false; + + switch (wm5100->rev) { + case 0: + snd_soc_write(codec, 0x11, 0x3); + snd_soc_write(codec, 0x203, 0xc); + snd_soc_write(codec, 0x206, 0); + snd_soc_write(codec, 0x207, 0xf0); + snd_soc_write(codec, 0x208, 0x3c); + snd_soc_write(codec, 0x209, 0); + snd_soc_write(codec, 0x211, 0x20d8); + snd_soc_write(codec, 0x11, 0); + + for (i = 0; + i < ARRAY_SIZE(wm5100_reva_patches); + i++) + snd_soc_write(codec, + wm5100_reva_patches[i].reg, + wm5100_reva_patches[i].val); + break; + default: + break; + } + + snd_soc_cache_sync(codec); + } + break; + + case SND_SOC_BIAS_OFF: + if (wm5100->pdata.ldo_ena) + gpio_set_value_cansleep(wm5100->pdata.ldo_ena, 0); + regulator_bulk_disable(ARRAY_SIZE(wm5100->core_supplies), + wm5100->core_supplies); + break; + } + codec->dapm.bias_level = level; + + return 0; +} + +static int wm5100_dai_to_base(struct snd_soc_dai *dai) +{ + switch (dai->id) { + case 0: + return WM5100_AUDIO_IF_1_1 - 1; + case 1: + return WM5100_AUDIO_IF_2_1 - 1; + case 2: + return WM5100_AUDIO_IF_3_1 - 1; + default: + BUG(); + return -EINVAL; + } +} + +static int wm5100_set_fmt(struct snd_soc_dai *dai, unsigned int fmt) +{ + struct snd_soc_codec *codec = dai->codec; + int lrclk, bclk, mask, base; + + base = wm5100_dai_to_base(dai); + if (base < 0) + return base; + + lrclk = 0; + bclk = 0; + + switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { + case SND_SOC_DAIFMT_DSP_A: + mask = 0; + break; + case SND_SOC_DAIFMT_DSP_B: + mask = 1; + break; + case SND_SOC_DAIFMT_I2S: + mask = 2; + break; + case SND_SOC_DAIFMT_LEFT_J: + mask = 3; + break; + default: + dev_err(codec->dev, "Unsupported DAI format %d\n", + fmt & SND_SOC_DAIFMT_FORMAT_MASK); + return -EINVAL; + } + + switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { + case SND_SOC_DAIFMT_CBS_CFS: + break; + case SND_SOC_DAIFMT_CBS_CFM: + lrclk |= WM5100_AIF1TX_LRCLK_MSTR; + break; + case SND_SOC_DAIFMT_CBM_CFS: + bclk |= WM5100_AIF1_BCLK_MSTR; + break; + case SND_SOC_DAIFMT_CBM_CFM: + lrclk |= WM5100_AIF1TX_LRCLK_MSTR; + bclk |= WM5100_AIF1_BCLK_MSTR; + break; + default: + dev_err(codec->dev, "Unsupported master mode %d\n", + fmt & SND_SOC_DAIFMT_MASTER_MASK); + return -EINVAL; + } + + switch (fmt & SND_SOC_DAIFMT_INV_MASK) { + case SND_SOC_DAIFMT_NB_NF: + break; + case SND_SOC_DAIFMT_IB_IF: + bclk |= WM5100_AIF1_BCLK_INV; + lrclk |= WM5100_AIF1TX_LRCLK_INV; + break; + case SND_SOC_DAIFMT_IB_NF: + bclk |= WM5100_AIF1_BCLK_INV; + break; + case SND_SOC_DAIFMT_NB_IF: + lrclk |= WM5100_AIF1TX_LRCLK_INV; + break; + default: + return -EINVAL; + } + + snd_soc_update_bits(codec, base + 1, WM5100_AIF1_BCLK_MSTR | + WM5100_AIF1_BCLK_INV, bclk); + snd_soc_update_bits(codec, base + 2, WM5100_AIF1TX_LRCLK_MSTR | + WM5100_AIF1TX_LRCLK_INV, lrclk); + snd_soc_update_bits(codec, base + 3, WM5100_AIF1TX_LRCLK_MSTR | + WM5100_AIF1TX_LRCLK_INV, lrclk); + snd_soc_update_bits(codec, base + 5, WM5100_AIF1_FMT_MASK, mask); + + return 0; +} + +#define WM5100_NUM_BCLK_RATES 19 + +static int wm5100_bclk_rates_dat[WM5100_NUM_BCLK_RATES] = { + 32000, + 48000, + 64000, + 96000, + 128000, + 192000, + 256000, + 384000, + 512000, + 768000, + 1024000, + 1536000, + 2048000, + 3072000, + 4096000, + 6144000, + 8192000, + 12288000, + 24576000, +}; + +static int wm5100_bclk_rates_cd[WM5100_NUM_BCLK_RATES] = { + 29400, + 44100, + 58800, + 88200, + 117600, + 176400, + 235200, + 352800, + 470400, + 705600, + 940800, + 1411200, + 1881600, + 2882400, + 3763200, + 5644800, + 7526400, + 11289600, + 22579600, +}; + +static int wm5100_hw_params(struct snd_pcm_substream *substream, + struct snd_pcm_hw_params *params, + struct snd_soc_dai *dai) +{ + struct snd_soc_codec *codec = dai->codec; + struct wm5100_priv *wm5100 = snd_soc_codec_get_drvdata(codec); + bool async = wm5100->aif_async[dai->id]; + int i, base, bclk, aif_rate, lrclk, wl, fl, sr; + int *bclk_rates; + + base = wm5100_dai_to_base(dai); + if (base < 0) + return base; + + /* Data sizes if not using TDM */ + wl = snd_pcm_format_width(params_format(params)); + if (wl < 0) + return wl; + fl = snd_soc_params_to_frame_size(params); + if (fl < 0) + return fl; + + dev_dbg(codec->dev, "Word length %d bits, frame length %d bits\n", + wl, fl); + + /* Target BCLK rate */ + bclk = snd_soc_params_to_bclk(params); + if (bclk < 0) + return bclk; + + /* Root for BCLK depends on SYS/ASYNCCLK */ + if (!async) { + aif_rate = wm5100->sysclk; + sr = wm5100_alloc_sr(codec, params_rate(params)); + if (sr < 0) + return sr; + } else { + /* If we're in ASYNCCLK set the ASYNC sample rate */ + aif_rate = wm5100->asyncclk; + sr = 3; + + for (i = 0; i < ARRAY_SIZE(wm5100_sr_code); i++) + if (params_rate(params) == wm5100_sr_code[i]) + break; + if (i == ARRAY_SIZE(wm5100_sr_code)) { + dev_err(codec->dev, "Invalid rate %dHzn", + params_rate(params)); + return -EINVAL; + } + + /* TODO: We should really check for symmetry */ + snd_soc_update_bits(codec, WM5100_CLOCKING_8, + WM5100_ASYNC_SAMPLE_RATE_MASK, i); + } + + if (!aif_rate) { + dev_err(codec->dev, "%s has no rate set\n", + async ? "ASYNCCLK" : "SYSCLK"); + return -EINVAL; + } + + dev_dbg(codec->dev, "Target BCLK is %dHz, using %dHz %s\n", + bclk, aif_rate, async ? "ASYNCCLK" : "SYSCLK"); + + if (aif_rate % 4000) + bclk_rates = wm5100_bclk_rates_cd; + else + bclk_rates = wm5100_bclk_rates_dat; + + for (i = 0; i < WM5100_NUM_BCLK_RATES; i++) + if (bclk_rates[i] >= bclk && (bclk_rates[i] % bclk == 0)) + break; + if (i == WM5100_NUM_BCLK_RATES) { + dev_err(codec->dev, + "No valid BCLK for %dHz found from %dHz %s\n", + bclk, aif_rate, async ? "ASYNCCLK" : "SYSCLK"); + return -EINVAL; + } + + bclk = i; + dev_dbg(codec->dev, "Setting %dHz BCLK\n", bclk_rates[bclk]); + snd_soc_update_bits(codec, base + 1, WM5100_AIF1_BCLK_FREQ_MASK, bclk); + + lrclk = bclk_rates[bclk] / params_rate(params); + dev_dbg(codec->dev, "Setting %dHz LRCLK\n", bclk_rates[bclk] / lrclk); + if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK || + wm5100->aif_symmetric[dai->id]) + snd_soc_update_bits(codec, base + 7, + WM5100_AIF1RX_BCPF_MASK, lrclk); + else + snd_soc_update_bits(codec, base + 6, + WM5100_AIF1TX_BCPF_MASK, lrclk); + + i = (wl << WM5100_AIF1TX_WL_SHIFT) | fl; + if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) + snd_soc_update_bits(codec, base + 9, + WM5100_AIF1RX_WL_MASK | + WM5100_AIF1RX_SLOT_LEN_MASK, i); + else + snd_soc_update_bits(codec, base + 8, + WM5100_AIF1TX_WL_MASK | + WM5100_AIF1TX_SLOT_LEN_MASK, i); + + snd_soc_update_bits(codec, base + 4, WM5100_AIF1_RATE_MASK, sr); + + return 0; +} + +static struct snd_soc_dai_ops wm5100_dai_ops = { + .set_fmt = wm5100_set_fmt, + .hw_params = wm5100_hw_params, +}; + +static int wm5100_set_sysclk(struct snd_soc_codec *codec, int clk_id, + int source, unsigned int freq, int dir) +{ + struct wm5100_priv *wm5100 = snd_soc_codec_get_drvdata(codec); + int *rate_store; + int fval, audio_rate, ret, reg; + + switch (clk_id) { + case WM5100_CLK_SYSCLK: + reg = WM5100_CLOCKING_3; + rate_store = &wm5100->sysclk; + break; + case WM5100_CLK_ASYNCCLK: + reg = WM5100_CLOCKING_7; + rate_store = &wm5100->asyncclk; + break; + case WM5100_CLK_32KHZ: + /* The 32kHz clock is slightly different to the others */ + switch (source) { + case WM5100_CLKSRC_MCLK1: + case WM5100_CLKSRC_MCLK2: + case WM5100_CLKSRC_SYSCLK: + snd_soc_update_bits(codec, WM5100_CLOCKING_1, + WM5100_CLK_32K_SRC_MASK, + source); + break; + default: + return -EINVAL; + } + return 0; + + case WM5100_CLK_AIF1: + case WM5100_CLK_AIF2: + case WM5100_CLK_AIF3: + /* Not real clocks, record which clock domain they're in */ + switch (source) { + case WM5100_CLKSRC_SYSCLK: + wm5100->aif_async[clk_id - 1] = false; + break; + case WM5100_CLKSRC_ASYNCCLK: + wm5100->aif_async[clk_id - 1] = true; + break; + default: + dev_err(codec->dev, "Invalid source %d\n", source); + return -EINVAL; + } + return 0; + + case WM5100_CLK_OPCLK: + switch (freq) { + case 5644800: + case 6144000: + snd_soc_update_bits(codec, WM5100_MISC_GPIO_1, + WM5100_OPCLK_SEL_MASK, 0); + break; + case 11289600: + case 12288000: + snd_soc_update_bits(codec, WM5100_MISC_GPIO_1, + WM5100_OPCLK_SEL_MASK, 0); + break; + case 22579200: + case 24576000: + snd_soc_update_bits(codec, WM5100_MISC_GPIO_1, + WM5100_OPCLK_SEL_MASK, 0); + break; + default: + dev_err(codec->dev, "Unsupported OPCLK %dHz\n", + freq); + return -EINVAL; + } + return 0; + + default: + dev_err(codec->dev, "Unknown clock %d\n", clk_id); + return -EINVAL; + } + + switch (source) { + case WM5100_CLKSRC_SYSCLK: + case WM5100_CLKSRC_ASYNCCLK: + dev_err(codec->dev, "Invalid source %d\n", source); + return -EINVAL; + } + + switch (freq) { + case 5644800: + case 6144000: + fval = 0; + break; + case 11289600: + case 12288000: + fval = 1; + break; + case 22579200: + case 24576000: + fval = 2; + break; + default: + dev_err(codec->dev, "Invalid clock rate: %d\n", freq); + return -EINVAL; + } + + switch (freq) { + case 5644800: + case 11289600: + case 22579200: + audio_rate = 44100; + break; + + case 6144000: + case 12288000: + case 24576000: + audio_rate = 48000; + break; + + default: + BUG(); + audio_rate = 0; + break; + } + + /* TODO: Check if MCLKs are in use and enable/disable pulls to + * match. + */ + + snd_soc_update_bits(codec, reg, WM5100_SYSCLK_FREQ_MASK | + WM5100_SYSCLK_SRC_MASK, + fval << WM5100_SYSCLK_FREQ_SHIFT | source); + + /* If this is SYSCLK then configure the clock rate for the + * internal audio functions to the natural sample rate for + * this clock rate. + */ + if (clk_id == WM5100_CLK_SYSCLK) { + dev_dbg(codec->dev, "Setting primary audio rate to %dHz", + audio_rate); + if (0 && *rate_store) + wm5100_free_sr(codec, audio_rate); + ret = wm5100_alloc_sr(codec, audio_rate); + if (ret != 0) + dev_warn(codec->dev, "Primary audio slot is %d\n", + ret); + } + + *rate_store = freq; + + return 0; +} + +struct _fll_div { + u16 fll_fratio; + u16 fll_outdiv; + u16 fll_refclk_div; + u16 n; + u16 theta; + u16 lambda; +}; + +static struct { + unsigned int min; + unsigned int max; + u16 fll_fratio; + int ratio; +} fll_fratios[] = { + { 0, 64000, 4, 16 }, + { 64000, 128000, 3, 8 }, + { 128000, 256000, 2, 4 }, + { 256000, 1000000, 1, 2 }, + { 1000000, 13500000, 0, 1 }, +}; + +static int fll_factors(struct _fll_div *fll_div, unsigned int Fref, + unsigned int Fout) +{ + unsigned int target; + unsigned int div; + unsigned int fratio, gcd_fll; + int i; + + /* Fref must be <=13.5MHz */ + div = 1; + fll_div->fll_refclk_div = 0; + while ((Fref / div) > 13500000) { + div *= 2; + fll_div->fll_refclk_div++; + + if (div > 8) { + pr_err("Can't scale %dMHz input down to <=13.5MHz\n", + Fref); + return -EINVAL; + } + } + + pr_debug("FLL Fref=%u Fout=%u\n", Fref, Fout); + + /* Apply the division for our remaining calculations */ + Fref /= div; + + /* Fvco should be 90-100MHz; don't check the upper bound */ + div = 2; + while (Fout * div < 90000000) { + div++; + if (div > 64) { + pr_err("Unable to find FLL_OUTDIV for Fout=%uHz\n", + Fout); + return -EINVAL; + } + } + target = Fout * div; + fll_div->fll_outdiv = div - 1; + + pr_debug("FLL Fvco=%dHz\n", target); + + /* Find an appropraite FLL_FRATIO and factor it out of the target */ + for (i = 0; i < ARRAY_SIZE(fll_fratios); i++) { + if (fll_fratios[i].min <= Fref && Fref <= fll_fratios[i].max) { + fll_div->fll_fratio = fll_fratios[i].fll_fratio; + fratio = fll_fratios[i].ratio; + break; + } + } + if (i == ARRAY_SIZE(fll_fratios)) { + pr_err("Unable to find FLL_FRATIO for Fref=%uHz\n", Fref); + return -EINVAL; + } + + fll_div->n = target / (fratio * Fref); + + if (target % Fref == 0) { + fll_div->theta = 0; + fll_div->lambda = 0; + } else { + gcd_fll = gcd(target, fratio * Fref); + + fll_div->theta = (target - (fll_div->n * fratio * Fref)) + / gcd_fll; + fll_div->lambda = (fratio * Fref) / gcd_fll; + } + + pr_debug("FLL N=%x THETA=%x LAMBDA=%x\n", + fll_div->n, fll_div->theta, fll_div->lambda); + pr_debug("FLL_FRATIO=%x(%d) FLL_OUTDIV=%x FLL_REFCLK_DIV=%x\n", + fll_div->fll_fratio, fratio, fll_div->fll_outdiv, + fll_div->fll_refclk_div); + + return 0; +} + +static int wm5100_set_fll(struct snd_soc_codec *codec, int fll_id, int source, + unsigned int Fref, unsigned int Fout) +{ + struct i2c_client *i2c = to_i2c_client(codec->dev); + struct wm5100_priv *wm5100 = snd_soc_codec_get_drvdata(codec); + struct _fll_div factors; + struct wm5100_fll *fll; + int ret, base, lock, i, timeout; + + switch (fll_id) { + case WM5100_FLL1: + fll = &wm5100->fll[0]; + base = WM5100_FLL1_CONTROL_1 - 1; + lock = WM5100_FLL1_LOCK_STS; + break; + case WM5100_FLL2: + fll = &wm5100->fll[1]; + base = WM5100_FLL2_CONTROL_2 - 1; + lock = WM5100_FLL2_LOCK_STS; + break; + default: + dev_err(codec->dev, "Unknown FLL %d\n",fll_id); + return -EINVAL; + } + + if (!Fout) { + dev_dbg(codec->dev, "FLL%d disabled", fll_id); + fll->fout = 0; + snd_soc_update_bits(codec, base + 1, WM5100_FLL1_ENA, 0); + return 0; + } + + switch (source) { + case WM5100_FLL_SRC_MCLK1: + case WM5100_FLL_SRC_MCLK2: + case WM5100_FLL_SRC_FLL1: + case WM5100_FLL_SRC_FLL2: + case WM5100_FLL_SRC_AIF1BCLK: + case WM5100_FLL_SRC_AIF2BCLK: + case WM5100_FLL_SRC_AIF3BCLK: + break; + default: + dev_err(codec->dev, "Invalid FLL source %d\n", source); + return -EINVAL; + } + + ret = fll_factors(&factors, Fref, Fout); + if (ret < 0) + return ret; + + /* Disable the FLL while we reconfigure */ + snd_soc_update_bits(codec, base + 1, WM5100_FLL1_ENA, 0); + + snd_soc_update_bits(codec, base + 2, + WM5100_FLL1_OUTDIV_MASK | WM5100_FLL1_FRATIO_MASK, + (factors.fll_outdiv << WM5100_FLL1_OUTDIV_SHIFT) | + factors.fll_fratio); + snd_soc_update_bits(codec, base + 3, WM5100_FLL1_THETA_MASK, + factors.theta); + snd_soc_update_bits(codec, base + 5, WM5100_FLL1_N_MASK, factors.n); + snd_soc_update_bits(codec, base + 6, + WM5100_FLL1_REFCLK_DIV_MASK | + WM5100_FLL1_REFCLK_SRC_MASK, + (factors.fll_refclk_div + << WM5100_FLL1_REFCLK_DIV_SHIFT) | source); + snd_soc_update_bits(codec, base + 7, WM5100_FLL1_LAMBDA_MASK, + factors.lambda); + + /* Clear any pending completions */ + try_wait_for_completion(&fll->lock); + + snd_soc_update_bits(codec, base + 1, WM5100_FLL1_ENA, WM5100_FLL1_ENA); + + if (i2c->irq) + timeout = 2; + else + timeout = 50; + + /* Poll for the lock; will use interrupt when we can test */ + for (i = 0; i < timeout; i++) { + if (i2c->irq) { + ret = wait_for_completion_timeout(&fll->lock, + msecs_to_jiffies(25)); + if (ret > 0) + break; + } else { + msleep(1); + } + + ret = snd_soc_read(codec, + WM5100_INTERRUPT_RAW_STATUS_3); + if (ret < 0) { + dev_err(codec->dev, + "Failed to read FLL status: %d\n", + ret); + continue; + } + if (ret & lock) + break; + } + if (i == timeout) { + dev_err(codec->dev, "FLL%d lock timed out\n", fll_id); + return -ETIMEDOUT; + } + + fll->src = source; + fll->fref = Fref; + fll->fout = Fout; + + dev_dbg(codec->dev, "FLL%d running %dHz->%dHz\n", fll_id, + Fref, Fout); + + return 0; +} + +/* Actually go much higher */ +#define WM5100_RATES SNDRV_PCM_RATE_8000_192000 + +#define WM5100_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE |\ + SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S32_LE) + +static struct snd_soc_dai_driver wm5100_dai[] = { + { + .name = "wm5100-aif1", + .playback = { + .stream_name = "AIF1 Playback", + .channels_min = 2, + .channels_max = 2, + .rates = WM5100_RATES, + .formats = WM5100_FORMATS, + }, + .capture = { + .stream_name = "AIF1 Capture", + .channels_min = 2, + .channels_max = 2, + .rates = WM5100_RATES, + .formats = WM5100_FORMATS, + }, + .ops = &wm5100_dai_ops, + }, + { + .name = "wm5100-aif2", + .id = 1, + .playback = { + .stream_name = "AIF2 Playback", + .channels_min = 2, + .channels_max = 2, + .rates = WM5100_RATES, + .formats = WM5100_FORMATS, + }, + .capture = { + .stream_name = "AIF2 Capture", + .channels_min = 2, + .channels_max = 2, + .rates = WM5100_RATES, + .formats = WM5100_FORMATS, + }, + .ops = &wm5100_dai_ops, + }, + { + .name = "wm5100-aif3", + .id = 2, + .playback = { + .stream_name = "AIF3 Playback", + .channels_min = 2, + .channels_max = 2, + .rates = WM5100_RATES, + .formats = WM5100_FORMATS, + }, + .capture = { + .stream_name = "AIF3 Capture", + .channels_min = 2, + .channels_max = 2, + .rates = WM5100_RATES, + .formats = WM5100_FORMATS, + }, + .ops = &wm5100_dai_ops, + }, +}; + +static int wm5100_dig_vu[] = { + WM5100_ADC_DIGITAL_VOLUME_1L, + WM5100_ADC_DIGITAL_VOLUME_1R, + WM5100_ADC_DIGITAL_VOLUME_2L, + WM5100_ADC_DIGITAL_VOLUME_2R, + WM5100_ADC_DIGITAL_VOLUME_3L, + WM5100_ADC_DIGITAL_VOLUME_3R, + WM5100_ADC_DIGITAL_VOLUME_4L, + WM5100_ADC_DIGITAL_VOLUME_4R, + + WM5100_DAC_DIGITAL_VOLUME_1L, + WM5100_DAC_DIGITAL_VOLUME_1R, + WM5100_DAC_DIGITAL_VOLUME_2L, + WM5100_DAC_DIGITAL_VOLUME_2R, + WM5100_DAC_DIGITAL_VOLUME_3L, + WM5100_DAC_DIGITAL_VOLUME_3R, + WM5100_DAC_DIGITAL_VOLUME_4L, + WM5100_DAC_DIGITAL_VOLUME_4R, + WM5100_DAC_DIGITAL_VOLUME_5L, + WM5100_DAC_DIGITAL_VOLUME_5R, + WM5100_DAC_DIGITAL_VOLUME_6L, + WM5100_DAC_DIGITAL_VOLUME_6R, +}; + +static void wm5100_set_detect_mode(struct snd_soc_codec *codec, int the_mode) +{ + struct wm5100_priv *wm5100 = snd_soc_codec_get_drvdata(codec); + struct wm5100_jack_mode *mode = &wm5100->pdata.jack_modes[the_mode]; + + BUG_ON(the_mode >= ARRAY_SIZE(wm5100->pdata.jack_modes)); + + gpio_set_value_cansleep(wm5100->pdata.hp_pol, mode->hp_pol); + snd_soc_update_bits(codec, WM5100_ACCESSORY_DETECT_MODE_1, + WM5100_ACCDET_BIAS_SRC_MASK | + WM5100_ACCDET_SRC, + (mode->bias << WM5100_ACCDET_BIAS_SRC_SHIFT) | + mode->micd_src << WM5100_ACCDET_SRC_SHIFT); + snd_soc_update_bits(codec, WM5100_MISC_CONTROL, + WM5100_HPCOM_SRC, + mode->micd_src << WM5100_HPCOM_SRC_SHIFT); + + wm5100->jack_mode = the_mode; + + dev_dbg(codec->dev, "Set microphone polarity to %d\n", + wm5100->jack_mode); +} + +static void wm5100_micd_irq(struct snd_soc_codec *codec) +{ + struct wm5100_priv *wm5100 = snd_soc_codec_get_drvdata(codec); + int val; + + val = snd_soc_read(codec, WM5100_MIC_DETECT_3); + + dev_dbg(codec->dev, "Microphone event: %x\n", val); + + if (!(val & WM5100_ACCDET_VALID)) { + dev_warn(codec->dev, "Microphone detection state invalid\n"); + return; + } + + /* No accessory, reset everything and report removal */ + if (!(val & WM5100_ACCDET_STS)) { + dev_dbg(codec->dev, "Jack removal detected\n"); + wm5100->jack_mic = false; + wm5100->jack_detecting = true; + snd_soc_jack_report(wm5100->jack, 0, + SND_JACK_LINEOUT | SND_JACK_HEADSET | + SND_JACK_BTN_0); + + snd_soc_update_bits(codec, WM5100_MIC_DETECT_1, + WM5100_ACCDET_RATE_MASK, + WM5100_ACCDET_RATE_MASK); + return; + } + + /* If the measurement is very high we've got a microphone, + * either we just detected one or if we already reported then + * we've got a button release event. + */ + if (val & 0x400) { + if (wm5100->jack_detecting) { + dev_dbg(codec->dev, "Microphone detected\n"); + wm5100->jack_mic = true; + snd_soc_jack_report(wm5100->jack, + SND_JACK_HEADSET, + SND_JACK_HEADSET | SND_JACK_BTN_0); + + /* Increase poll rate to give better responsiveness + * for buttons */ + snd_soc_update_bits(codec, WM5100_MIC_DETECT_1, + WM5100_ACCDET_RATE_MASK, + 5 << WM5100_ACCDET_RATE_SHIFT); + } else { + dev_dbg(codec->dev, "Mic button up\n"); + snd_soc_jack_report(wm5100->jack, 0, SND_JACK_BTN_0); + } + + return; + } + + /* If we detected a lower impedence during initial startup + * then we probably have the wrong polarity, flip it. Don't + * do this for the lowest impedences to speed up detection of + * plain headphones. + */ + if (wm5100->jack_detecting && (val & 0x3f8)) { + wm5100_set_detect_mode(codec, !wm5100->jack_mode); + + return; + } + + /* Don't distinguish between buttons, just report any low + * impedence as BTN_0. + */ + if (val & 0x3fc) { + if (wm5100->jack_mic) { + dev_dbg(codec->dev, "Mic button detected\n"); + snd_soc_jack_report(wm5100->jack, SND_JACK_BTN_0, + SND_JACK_BTN_0); + } else if (wm5100->jack_detecting) { + dev_dbg(codec->dev, "Headphone detected\n"); + snd_soc_jack_report(wm5100->jack, SND_JACK_HEADPHONE, + SND_JACK_HEADPHONE); + + /* Increase the detection rate a bit for + * responsiveness. + */ + snd_soc_update_bits(codec, WM5100_MIC_DETECT_1, + WM5100_ACCDET_RATE_MASK, + 7 << WM5100_ACCDET_RATE_SHIFT); + } + } +} + +int wm5100_detect(struct snd_soc_codec *codec, struct snd_soc_jack *jack) +{ + struct wm5100_priv *wm5100 = snd_soc_codec_get_drvdata(codec); + + if (jack) { + wm5100->jack = jack; + wm5100->jack_detecting = true; + + wm5100_set_detect_mode(codec, 0); + + /* Slowest detection rate, gives debounce for initial + * detection */ + snd_soc_update_bits(codec, WM5100_MIC_DETECT_1, + WM5100_ACCDET_BIAS_STARTTIME_MASK | + WM5100_ACCDET_RATE_MASK, + (7 << WM5100_ACCDET_BIAS_STARTTIME_SHIFT) | + WM5100_ACCDET_RATE_MASK); + + /* We need the charge pump to power MICBIAS */ + snd_soc_dapm_force_enable_pin(&codec->dapm, "CP2"); + snd_soc_dapm_force_enable_pin(&codec->dapm, "SYSCLK"); + snd_soc_dapm_sync(&codec->dapm); + + /* We start off just enabling microphone detection - even a + * plain headphone will trigger detection. + */ + snd_soc_update_bits(codec, WM5100_MIC_DETECT_1, + WM5100_ACCDET_ENA, WM5100_ACCDET_ENA); + + snd_soc_update_bits(codec, WM5100_INTERRUPT_STATUS_3_MASK, + WM5100_IM_ACCDET_EINT, 0); + } else { + snd_soc_update_bits(codec, WM5100_INTERRUPT_STATUS_3_MASK, + WM5100_IM_HPDET_EINT | + WM5100_IM_ACCDET_EINT, + WM5100_IM_HPDET_EINT | + WM5100_IM_ACCDET_EINT); + snd_soc_update_bits(codec, WM5100_MIC_DETECT_1, + WM5100_ACCDET_ENA, 0); + wm5100->jack = NULL; + } + + return 0; +} + +static irqreturn_t wm5100_irq(int irq, void *data) +{ + struct snd_soc_codec *codec = data; + struct wm5100_priv *wm5100 = snd_soc_codec_get_drvdata(codec); + irqreturn_t status = IRQ_NONE; + int irq_val; + + irq_val = snd_soc_read(codec, WM5100_INTERRUPT_STATUS_3); + if (irq_val < 0) { + dev_err(codec->dev, "Failed to read IRQ status 3: %d\n", + irq_val); + irq_val = 0; + } + irq_val &= ~snd_soc_read(codec, WM5100_INTERRUPT_STATUS_3_MASK); + + snd_soc_write(codec, WM5100_INTERRUPT_STATUS_3, irq_val); + + if (irq_val) + status = IRQ_HANDLED; + + wm5100_log_status3(codec, irq_val); + + if (irq_val & WM5100_FLL1_LOCK_EINT) { + dev_dbg(codec->dev, "FLL1 locked\n"); + complete(&wm5100->fll[0].lock); + } + if (irq_val & WM5100_FLL2_LOCK_EINT) { + dev_dbg(codec->dev, "FLL2 locked\n"); + complete(&wm5100->fll[1].lock); + } + + if (irq_val & WM5100_ACCDET_EINT) + wm5100_micd_irq(codec); + + irq_val = snd_soc_read(codec, WM5100_INTERRUPT_STATUS_4); + if (irq_val < 0) { + dev_err(codec->dev, "Failed to read IRQ status 4: %d\n", + irq_val); + irq_val = 0; + } + irq_val &= ~snd_soc_read(codec, WM5100_INTERRUPT_STATUS_4_MASK); + + if (irq_val) + status = IRQ_HANDLED; + + snd_soc_write(codec, WM5100_INTERRUPT_STATUS_4, irq_val); + + wm5100_log_status4(codec, irq_val); + + return status; +} + +static irqreturn_t wm5100_edge_irq(int irq, void *data) +{ + irqreturn_t ret = IRQ_NONE; + irqreturn_t val; + + do { + val = wm5100_irq(irq, data); + if (val != IRQ_NONE) + ret = val; + } while (val != IRQ_NONE); + + return ret; +} + +#ifdef CONFIG_GPIOLIB +static inline struct wm5100_priv *gpio_to_wm5100(struct gpio_chip *chip) +{ + return container_of(chip, struct wm5100_priv, gpio_chip); +} + +static void wm5100_gpio_set(struct gpio_chip *chip, unsigned offset, int value) +{ + struct wm5100_priv *wm5100 = gpio_to_wm5100(chip); + struct snd_soc_codec *codec = wm5100->codec; + + snd_soc_update_bits(codec, WM5100_GPIO_CTRL_1 + offset, + WM5100_GP1_LVL, !!value << WM5100_GP1_LVL_SHIFT); +} + +static int wm5100_gpio_direction_out(struct gpio_chip *chip, + unsigned offset, int value) +{ + struct wm5100_priv *wm5100 = gpio_to_wm5100(chip); + struct snd_soc_codec *codec = wm5100->codec; + int val, ret; + + val = (1 << WM5100_GP1_FN_SHIFT) | (!!value << WM5100_GP1_LVL_SHIFT); + + ret = snd_soc_update_bits(codec, WM5100_GPIO_CTRL_1 + offset, + WM5100_GP1_FN_MASK | WM5100_GP1_DIR | + WM5100_GP1_LVL, val); + if (ret < 0) + return ret; + else + return 0; +} + +static int wm5100_gpio_get(struct gpio_chip *chip, unsigned offset) +{ + struct wm5100_priv *wm5100 = gpio_to_wm5100(chip); + struct snd_soc_codec *codec = wm5100->codec; + int ret; + + ret = snd_soc_read(codec, WM5100_GPIO_CTRL_1 + offset); + if (ret < 0) + return ret; + + return (ret & WM5100_GP1_LVL) != 0; +} + +static int wm5100_gpio_direction_in(struct gpio_chip *chip, unsigned offset) +{ + struct wm5100_priv *wm5100 = gpio_to_wm5100(chip); + struct snd_soc_codec *codec = wm5100->codec; + + return snd_soc_update_bits(codec, WM5100_GPIO_CTRL_1 + offset, + WM5100_GP1_FN_MASK | WM5100_GP1_DIR, + (1 << WM5100_GP1_FN_SHIFT) | + (1 << WM5100_GP1_DIR_SHIFT)); +} + +static struct gpio_chip wm5100_template_chip = { + .label = "wm5100", + .owner = THIS_MODULE, + .direction_output = wm5100_gpio_direction_out, + .set = wm5100_gpio_set, + .direction_input = wm5100_gpio_direction_in, + .get = wm5100_gpio_get, + .can_sleep = 1, +}; + +static void wm5100_init_gpio(struct snd_soc_codec *codec) +{ + struct wm5100_priv *wm5100 = snd_soc_codec_get_drvdata(codec); + int ret; + + wm5100->gpio_chip = wm5100_template_chip; + wm5100->gpio_chip.ngpio = 6; + wm5100->gpio_chip.dev = codec->dev; + + if (wm5100->pdata.gpio_base) + wm5100->gpio_chip.base = wm5100->pdata.gpio_base; + else + wm5100->gpio_chip.base = -1; + + ret = gpiochip_add(&wm5100->gpio_chip); + if (ret != 0) + dev_err(codec->dev, "Failed to add GPIOs: %d\n", ret); +} + +static void wm5100_free_gpio(struct snd_soc_codec *codec) +{ + struct wm5100_priv *wm5100 = snd_soc_codec_get_drvdata(codec); + int ret; + + ret = gpiochip_remove(&wm5100->gpio_chip); + if (ret != 0) + dev_err(codec->dev, "Failed to remove GPIOs: %d\n", ret); +} +#else +static void wm5100_init_gpio(struct snd_soc_codec *codec) +{ +} + +static void wm5100_free_gpio(struct snd_soc_codec *codec) +{ +} +#endif + +static int wm5100_probe(struct snd_soc_codec *codec) +{ + struct i2c_client *i2c = to_i2c_client(codec->dev); + struct wm5100_priv *wm5100 = snd_soc_codec_get_drvdata(codec); + int ret, i, irq_flags; + + wm5100->codec = codec; + + ret = snd_soc_codec_set_cache_io(codec, 16, 16, SND_SOC_I2C); + if (ret != 0) { + dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret); + return ret; + } + + for (i = 0; i < ARRAY_SIZE(wm5100->core_supplies); i++) + wm5100->core_supplies[i].supply = wm5100_core_supply_names[i]; + + ret = regulator_bulk_get(&i2c->dev, ARRAY_SIZE(wm5100->core_supplies), + wm5100->core_supplies); + if (ret != 0) { + dev_err(codec->dev, "Failed to request core supplies: %d\n", + ret); + return ret; + } + + wm5100->cpvdd = regulator_get(&i2c->dev, "CPVDD"); + if (IS_ERR(wm5100->cpvdd)) { + ret = PTR_ERR(wm5100->cpvdd); + dev_err(&i2c->dev, "Failed to get CPVDD: %d\n", ret); + goto err_core; + } + + wm5100->dbvdd2 = regulator_get(&i2c->dev, "DBVDD2"); + if (IS_ERR(wm5100->dbvdd2)) { + ret = PTR_ERR(wm5100->dbvdd2); + dev_err(&i2c->dev, "Failed to get DBVDD2: %d\n", ret); + goto err_cpvdd; + } + + wm5100->dbvdd3 = regulator_get(&i2c->dev, "DBVDD3"); + if (IS_ERR(wm5100->dbvdd3)) { + ret = PTR_ERR(wm5100->dbvdd3); + dev_err(&i2c->dev, "Failed to get DBVDD2: %d\n", ret); + goto err_dbvdd2; + } + + ret = regulator_bulk_enable(ARRAY_SIZE(wm5100->core_supplies), + wm5100->core_supplies); + if (ret != 0) { + dev_err(codec->dev, "Failed to enable core supplies: %d\n", + ret); + goto err_dbvdd3; + } + + if (wm5100->pdata.ldo_ena) { + ret = gpio_request_one(wm5100->pdata.ldo_ena, + GPIOF_OUT_INIT_HIGH, "WM5100 LDOENA"); + if (ret < 0) { + dev_err(&i2c->dev, "Failed to request LDOENA %d: %d\n", + wm5100->pdata.ldo_ena, ret); + goto err_enable; + } + msleep(2); + } + + if (wm5100->pdata.reset) { + ret = gpio_request_one(wm5100->pdata.reset, + GPIOF_OUT_INIT_HIGH, "WM5100 /RESET"); + if (ret < 0) { + dev_err(&i2c->dev, "Failed to request /RESET %d: %d\n", + wm5100->pdata.reset, ret); + goto err_ldo; + } + } + + ret = snd_soc_read(codec, WM5100_SOFTWARE_RESET); + if (ret < 0) { + dev_err(codec->dev, "Failed to read ID register\n"); + goto err_reset; + } + switch (ret) { + case 0x8997: + case 0x5100: + break; + + default: + dev_err(codec->dev, "Device is not a WM5100, ID is %x\n", ret); + ret = -EINVAL; + goto err_reset; + } + + ret = snd_soc_read(codec, WM5100_DEVICE_REVISION); + if (ret < 0) { + dev_err(codec->dev, "Failed to read revision register\n"); + goto err_reset; + } + wm5100->rev = ret & WM5100_DEVICE_REVISION_MASK; + + dev_info(codec->dev, "revision %c\n", wm5100->rev + 'A'); + + ret = wm5100_reset(codec); + if (ret < 0) { + dev_err(codec->dev, "Failed to issue reset\n"); + goto err_reset; + } + + codec->cache_only = true; + + wm5100_init_gpio(codec); + + for (i = 0; i < ARRAY_SIZE(wm5100_dig_vu); i++) + snd_soc_update_bits(codec, wm5100_dig_vu[i], WM5100_OUT_VU, + WM5100_OUT_VU); + + for (i = 0; i < ARRAY_SIZE(wm5100->pdata.in_mode); i++) { + snd_soc_update_bits(codec, WM5100_IN1L_CONTROL, + WM5100_IN1_MODE_MASK | + WM5100_IN1_DMIC_SUP_MASK, + (wm5100->pdata.in_mode[i] << + WM5100_IN1_MODE_SHIFT) | + (wm5100->pdata.dmic_sup[i] << + WM5100_IN1_DMIC_SUP_SHIFT)); + } + + for (i = 0; i < ARRAY_SIZE(wm5100->pdata.gpio_defaults); i++) { + if (!wm5100->pdata.gpio_defaults[i]) + continue; + + snd_soc_write(codec, WM5100_GPIO_CTRL_1 + i, + wm5100->pdata.gpio_defaults[i]); + } + + /* Don't debounce interrupts to support use of SYSCLK only */ + snd_soc_write(codec, WM5100_IRQ_DEBOUNCE_1, 0); + snd_soc_write(codec, WM5100_IRQ_DEBOUNCE_2, 0); + + /* TODO: check if we're symmetric */ + + if (i2c->irq) { + if (wm5100->pdata.irq_flags) + irq_flags = wm5100->pdata.irq_flags; + else + irq_flags = IRQF_TRIGGER_LOW; + + irq_flags |= IRQF_ONESHOT; + + if (irq_flags & (IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING)) + ret = request_threaded_irq(i2c->irq, NULL, + wm5100_edge_irq, + irq_flags, "wm5100", codec); + else + ret = request_threaded_irq(i2c->irq, NULL, wm5100_irq, + irq_flags, "wm5100", codec); + + if (ret != 0) { + dev_err(codec->dev, "Failed to request IRQ %d: %d\n", + i2c->irq, ret); + } else { + /* Enable default interrupts */ + snd_soc_update_bits(codec, + WM5100_INTERRUPT_STATUS_3_MASK, + WM5100_IM_SPK_SHUTDOWN_WARN_EINT | + WM5100_IM_SPK_SHUTDOWN_EINT | + WM5100_IM_ASRC2_LOCK_EINT | + WM5100_IM_ASRC1_LOCK_EINT | + WM5100_IM_FLL2_LOCK_EINT | + WM5100_IM_FLL1_LOCK_EINT | + WM5100_CLKGEN_ERR_EINT | + WM5100_CLKGEN_ERR_ASYNC_EINT, 0); + + snd_soc_update_bits(codec, + WM5100_INTERRUPT_STATUS_4_MASK, + WM5100_AIF3_ERR_EINT | + WM5100_AIF2_ERR_EINT | + WM5100_AIF1_ERR_EINT | + WM5100_CTRLIF_ERR_EINT | + WM5100_ISRC2_UNDERCLOCKED_EINT | + WM5100_ISRC1_UNDERCLOCKED_EINT | + WM5100_FX_UNDERCLOCKED_EINT | + WM5100_AIF3_UNDERCLOCKED_EINT | + WM5100_AIF2_UNDERCLOCKED_EINT | + WM5100_AIF1_UNDERCLOCKED_EINT | + WM5100_ASRC_UNDERCLOCKED_EINT | + WM5100_DAC_UNDERCLOCKED_EINT | + WM5100_ADC_UNDERCLOCKED_EINT | + WM5100_MIXER_UNDERCLOCKED_EINT, 0); + } + } else { + snd_soc_dapm_new_controls(&codec->dapm, + wm5100_dapm_widgets_noirq, + ARRAY_SIZE(wm5100_dapm_widgets_noirq)); + } + + if (wm5100->pdata.hp_pol) { + ret = gpio_request_one(wm5100->pdata.hp_pol, + GPIOF_OUT_INIT_HIGH, "WM5100 HP_POL"); + if (ret < 0) { + dev_err(&i2c->dev, "Failed to request HP_POL %d: %d\n", + wm5100->pdata.hp_pol, ret); + goto err_gpio; + } + } + + /* We'll get woken up again when the system has something useful + * for us to do. + */ + if (wm5100->pdata.ldo_ena) + gpio_set_value_cansleep(wm5100->pdata.ldo_ena, 0); + regulator_bulk_disable(ARRAY_SIZE(wm5100->core_supplies), + wm5100->core_supplies); + + return 0; + +err_gpio: + if (i2c->irq) + free_irq(i2c->irq, codec); + wm5100_free_gpio(codec); +err_reset: + if (wm5100->pdata.reset) { + gpio_set_value_cansleep(wm5100->pdata.reset, 1); + gpio_free(wm5100->pdata.reset); + } +err_ldo: + if (wm5100->pdata.ldo_ena) { + gpio_set_value_cansleep(wm5100->pdata.ldo_ena, 0); + gpio_free(wm5100->pdata.ldo_ena); + } +err_enable: + regulator_bulk_disable(ARRAY_SIZE(wm5100->core_supplies), + wm5100->core_supplies); +err_dbvdd3: + regulator_put(wm5100->dbvdd3); +err_dbvdd2: + regulator_put(wm5100->dbvdd2); +err_cpvdd: + regulator_put(wm5100->cpvdd); +err_core: + regulator_bulk_free(ARRAY_SIZE(wm5100->core_supplies), + wm5100->core_supplies); + + return ret; +} + +static int wm5100_remove(struct snd_soc_codec *codec) +{ + struct wm5100_priv *wm5100 = snd_soc_codec_get_drvdata(codec); + struct i2c_client *i2c = to_i2c_client(codec->dev); + + wm5100_set_bias_level(codec, SND_SOC_BIAS_OFF); + if (wm5100->pdata.hp_pol) { + gpio_free(wm5100->pdata.hp_pol); + } + if (i2c->irq) + free_irq(i2c->irq, codec); + wm5100_free_gpio(codec); + if (wm5100->pdata.reset) { + gpio_set_value_cansleep(wm5100->pdata.reset, 1); + gpio_free(wm5100->pdata.reset); + } + if (wm5100->pdata.ldo_ena) { + gpio_set_value_cansleep(wm5100->pdata.ldo_ena, 0); + gpio_free(wm5100->pdata.ldo_ena); + } + regulator_put(wm5100->dbvdd3); + regulator_put(wm5100->dbvdd2); + regulator_put(wm5100->cpvdd); + regulator_bulk_free(ARRAY_SIZE(wm5100->core_supplies), + wm5100->core_supplies); + return 0; +} + +static struct snd_soc_codec_driver soc_codec_dev_wm5100 = { + .probe = wm5100_probe, + .remove = wm5100_remove, + + .set_sysclk = wm5100_set_sysclk, + .set_pll = wm5100_set_fll, + .set_bias_level = wm5100_set_bias_level, + .idle_bias_off = 1, + + .seq_notifier = wm5100_seq_notifier, + .controls = wm5100_snd_controls, + .num_controls = ARRAY_SIZE(wm5100_snd_controls), + .dapm_widgets = wm5100_dapm_widgets, + .num_dapm_widgets = ARRAY_SIZE(wm5100_dapm_widgets), + .dapm_routes = wm5100_dapm_routes, + .num_dapm_routes = ARRAY_SIZE(wm5100_dapm_routes), + + .reg_cache_size = ARRAY_SIZE(wm5100_reg_defaults), + .reg_word_size = sizeof(u16), + .compress_type = SND_SOC_RBTREE_COMPRESSION, + .reg_cache_default = wm5100_reg_defaults, + + .volatile_register = wm5100_volatile_register, + .readable_register = wm5100_readable_register, +}; + +static __devinit int wm5100_i2c_probe(struct i2c_client *i2c, + const struct i2c_device_id *id) +{ + struct wm5100_pdata *pdata = dev_get_platdata(&i2c->dev); + struct wm5100_priv *wm5100; + int ret, i; + + wm5100 = kzalloc(sizeof(struct wm5100_priv), GFP_KERNEL); + if (wm5100 == NULL) + return -ENOMEM; + + for (i = 0; i < ARRAY_SIZE(wm5100->fll); i++) + init_completion(&wm5100->fll[i].lock); + + if (pdata) + wm5100->pdata = *pdata; + + i2c_set_clientdata(i2c, wm5100); + + ret = snd_soc_register_codec(&i2c->dev, + &soc_codec_dev_wm5100, wm5100_dai, + ARRAY_SIZE(wm5100_dai)); + if (ret < 0) { + dev_err(&i2c->dev, "Failed to register WM5100: %d\n", ret); + kfree(wm5100); + } + + return ret; +} + +static __devexit int wm5100_i2c_remove(struct i2c_client *client) +{ + snd_soc_unregister_codec(&client->dev); + kfree(i2c_get_clientdata(client)); + return 0; +} + +static const struct i2c_device_id wm5100_i2c_id[] = { + { "wm5100", 0 }, + { } +}; +MODULE_DEVICE_TABLE(i2c, wm5100_i2c_id); + +static struct i2c_driver wm5100_i2c_driver = { + .driver = { + .name = "wm5100", + .owner = THIS_MODULE, + }, + .probe = wm5100_i2c_probe, + .remove = __devexit_p(wm5100_i2c_remove), + .id_table = wm5100_i2c_id, +}; + +static int __init wm5100_modinit(void) +{ + return i2c_add_driver(&wm5100_i2c_driver); +} +module_init(wm5100_modinit); + +static void __exit wm5100_exit(void) +{ + i2c_del_driver(&wm5100_i2c_driver); +} +module_exit(wm5100_exit); + +MODULE_DESCRIPTION("ASoC WM5100 driver"); +MODULE_AUTHOR("Mark Brown <broonie@opensource.wolfsonmicro.com>"); +MODULE_LICENSE("GPL"); diff --git a/sound/soc/codecs/wm5100.h b/sound/soc/codecs/wm5100.h new file mode 100644 index 00000000000..970759636bd --- /dev/null +++ b/sound/soc/codecs/wm5100.h @@ -0,0 +1,5155 @@ +/* + * wm5100.h -- WM5100 ALSA SoC Audio driver + * + * Copyright 2011 Wolfson Microelectronics plc + * + * Author: Mark Brown <broonie@opensource.wolfsonmicro.com> + * + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#ifndef WM5100_ASOC_H +#define WM5100_ASOC_H + +#include <sound/soc.h> + +int wm5100_detect(struct snd_soc_codec *codec, struct snd_soc_jack *jack); + +#define WM5100_CLK_AIF1 1 +#define WM5100_CLK_AIF2 2 +#define WM5100_CLK_AIF3 3 +#define WM5100_CLK_SYSCLK 4 +#define WM5100_CLK_ASYNCCLK 5 +#define WM5100_CLK_32KHZ 6 +#define WM5100_CLK_OPCLK 7 + +#define WM5100_CLKSRC_MCLK1 0 +#define WM5100_CLKSRC_MCLK2 1 +#define WM5100_CLKSRC_SYSCLK 2 +#define WM5100_CLKSRC_FLL1 4 +#define WM5100_CLKSRC_FLL2 5 +#define WM5100_CLKSRC_AIF1BCLK 8 +#define WM5100_CLKSRC_AIF2BCLK 9 +#define WM5100_CLKSRC_AIF3BCLK 10 +#define WM5100_CLKSRC_ASYNCCLK 0x100 + +#define WM5100_FLL1 1 +#define WM5100_FLL2 2 + +#define WM5100_FLL_SRC_MCLK1 0x0 +#define WM5100_FLL_SRC_MCLK2 0x1 +#define WM5100_FLL_SRC_FLL1 0x4 +#define WM5100_FLL_SRC_FLL2 0x5 +#define WM5100_FLL_SRC_AIF1BCLK 0x8 +#define WM5100_FLL_SRC_AIF2BCLK 0x9 +#define WM5100_FLL_SRC_AIF3BCLK 0xa + +/* + * Register values. + */ +#define WM5100_SOFTWARE_RESET 0x00 +#define WM5100_DEVICE_REVISION 0x01 +#define WM5100_CTRL_IF_1 0x10 +#define WM5100_TONE_GENERATOR_1 0x20 +#define WM5100_PWM_DRIVE_1 0x30 +#define WM5100_PWM_DRIVE_2 0x31 +#define WM5100_PWM_DRIVE_3 0x32 +#define WM5100_CLOCKING_1 0x100 +#define WM5100_CLOCKING_3 0x101 +#define WM5100_CLOCKING_4 0x102 +#define WM5100_CLOCKING_5 0x103 +#define WM5100_CLOCKING_6 0x104 +#define WM5100_CLOCKING_7 0x107 +#define WM5100_CLOCKING_8 0x108 +#define WM5100_ASRC_ENABLE 0x120 +#define WM5100_ASRC_STATUS 0x121 +#define WM5100_ASRC_RATE1 0x122 +#define WM5100_ISRC_1_CTRL_1 0x141 +#define WM5100_ISRC_1_CTRL_2 0x142 +#define WM5100_ISRC_2_CTRL1 0x143 +#define WM5100_ISRC_2_CTRL_2 0x144 +#define WM5100_FLL1_CONTROL_1 0x182 +#define WM5100_FLL1_CONTROL_2 0x183 +#define WM5100_FLL1_CONTROL_3 0x184 +#define WM5100_FLL1_CONTROL_5 0x186 +#define WM5100_FLL1_CONTROL_6 0x187 +#define WM5100_FLL1_EFS_1 0x188 +#define WM5100_FLL2_CONTROL_1 0x1A2 +#define WM5100_FLL2_CONTROL_2 0x1A3 +#define WM5100_FLL2_CONTROL_3 0x1A4 +#define WM5100_FLL2_CONTROL_5 0x1A6 +#define WM5100_FLL2_CONTROL_6 0x1A7 +#define WM5100_FLL2_EFS_1 0x1A8 +#define WM5100_MIC_CHARGE_PUMP_1 0x200 +#define WM5100_MIC_CHARGE_PUMP_2 0x201 +#define WM5100_HP_CHARGE_PUMP_1 0x202 +#define WM5100_LDO1_CONTROL 0x211 +#define WM5100_MIC_BIAS_CTRL_1 0x215 +#define WM5100_MIC_BIAS_CTRL_2 0x216 +#define WM5100_MIC_BIAS_CTRL_3 0x217 +#define WM5100_ACCESSORY_DETECT_MODE_1 0x280 +#define WM5100_HEADPHONE_DETECT_1 0x288 +#define WM5100_HEADPHONE_DETECT_2 0x289 +#define WM5100_MIC_DETECT_1 0x290 +#define WM5100_MIC_DETECT_2 0x291 +#define WM5100_MIC_DETECT_3 0x292 +#define WM5100_MISC_CONTROL 0x2BB +#define WM5100_INPUT_ENABLES 0x301 +#define WM5100_INPUT_ENABLES_STATUS 0x302 +#define WM5100_IN1L_CONTROL 0x310 +#define WM5100_IN1R_CONTROL 0x311 +#define WM5100_IN2L_CONTROL 0x312 +#define WM5100_IN2R_CONTROL 0x313 +#define WM5100_IN3L_CONTROL 0x314 +#define WM5100_IN3R_CONTROL 0x315 +#define WM5100_IN4L_CONTROL 0x316 +#define WM5100_IN4R_CONTROL 0x317 +#define WM5100_RXANC_SRC 0x318 +#define WM5100_INPUT_VOLUME_RAMP 0x319 +#define WM5100_ADC_DIGITAL_VOLUME_1L 0x320 +#define WM5100_ADC_DIGITAL_VOLUME_1R 0x321 +#define WM5100_ADC_DIGITAL_VOLUME_2L 0x322 +#define WM5100_ADC_DIGITAL_VOLUME_2R 0x323 +#define WM5100_ADC_DIGITAL_VOLUME_3L 0x324 +#define WM5100_ADC_DIGITAL_VOLUME_3R 0x325 +#define WM5100_ADC_DIGITAL_VOLUME_4L 0x326 +#define WM5100_ADC_DIGITAL_VOLUME_4R 0x327 +#define WM5100_OUTPUT_ENABLES_2 0x401 +#define WM5100_OUTPUT_STATUS_1 0x402 +#define WM5100_OUTPUT_STATUS_2 0x403 +#define WM5100_CHANNEL_ENABLES_1 0x408 +#define WM5100_OUT_VOLUME_1L 0x410 +#define WM5100_OUT_VOLUME_1R 0x411 +#define WM5100_DAC_VOLUME_LIMIT_1L 0x412 +#define WM5100_DAC_VOLUME_LIMIT_1R 0x413 +#define WM5100_OUT_VOLUME_2L 0x414 +#define WM5100_OUT_VOLUME_2R 0x415 +#define WM5100_DAC_VOLUME_LIMIT_2L 0x416 +#define WM5100_DAC_VOLUME_LIMIT_2R 0x417 +#define WM5100_OUT_VOLUME_3L 0x418 +#define WM5100_OUT_VOLUME_3R 0x419 +#define WM5100_DAC_VOLUME_LIMIT_3L 0x41A +#define WM5100_DAC_VOLUME_LIMIT_3R 0x41B +#define WM5100_OUT_VOLUME_4L 0x41C +#define WM5100_OUT_VOLUME_4R 0x41D +#define WM5100_DAC_VOLUME_LIMIT_5L 0x41E +#define WM5100_DAC_VOLUME_LIMIT_5R 0x41F +#define WM5100_DAC_VOLUME_LIMIT_6L 0x420 +#define WM5100_DAC_VOLUME_LIMIT_6R 0x421 +#define WM5100_DAC_AEC_CONTROL_1 0x440 +#define WM5100_OUTPUT_VOLUME_RAMP 0x441 +#define WM5100_DAC_DIGITAL_VOLUME_1L 0x480 +#define WM5100_DAC_DIGITAL_VOLUME_1R 0x481 +#define WM5100_DAC_DIGITAL_VOLUME_2L 0x482 +#define WM5100_DAC_DIGITAL_VOLUME_2R 0x483 +#define WM5100_DAC_DIGITAL_VOLUME_3L 0x484 +#define WM5100_DAC_DIGITAL_VOLUME_3R 0x485 +#define WM5100_DAC_DIGITAL_VOLUME_4L 0x486 +#define WM5100_DAC_DIGITAL_VOLUME_4R 0x487 +#define WM5100_DAC_DIGITAL_VOLUME_5L 0x488 +#define WM5100_DAC_DIGITAL_VOLUME_5R 0x489 +#define WM5100_DAC_DIGITAL_VOLUME_6L 0x48A +#define WM5100_DAC_DIGITAL_VOLUME_6R 0x48B +#define WM5100_PDM_SPK1_CTRL_1 0x4C0 +#define WM5100_PDM_SPK1_CTRL_2 0x4C1 +#define WM5100_PDM_SPK2_CTRL_1 0x4C2 +#define WM5100_PDM_SPK2_CTRL_2 0x4C3 +#define WM5100_AUDIO_IF_1_1 0x500 +#define WM5100_AUDIO_IF_1_2 0x501 +#define WM5100_AUDIO_IF_1_3 0x502 +#define WM5100_AUDIO_IF_1_4 0x503 +#define WM5100_AUDIO_IF_1_5 0x504 +#define WM5100_AUDIO_IF_1_6 0x505 +#define WM5100_AUDIO_IF_1_7 0x506 +#define WM5100_AUDIO_IF_1_8 0x507 +#define WM5100_AUDIO_IF_1_9 0x508 +#define WM5100_AUDIO_IF_1_10 0x509 +#define WM5100_AUDIO_IF_1_11 0x50A +#define WM5100_AUDIO_IF_1_12 0x50B +#define WM5100_AUDIO_IF_1_13 0x50C +#define WM5100_AUDIO_IF_1_14 0x50D +#define WM5100_AUDIO_IF_1_15 0x50E +#define WM5100_AUDIO_IF_1_16 0x50F +#define WM5100_AUDIO_IF_1_17 0x510 +#define WM5100_AUDIO_IF_1_18 0x511 +#define WM5100_AUDIO_IF_1_19 0x512 +#define WM5100_AUDIO_IF_1_20 0x513 +#define WM5100_AUDIO_IF_1_21 0x514 +#define WM5100_AUDIO_IF_1_22 0x515 +#define WM5100_AUDIO_IF_1_23 0x516 +#define WM5100_AUDIO_IF_1_24 0x517 +#define WM5100_AUDIO_IF_1_25 0x518 +#define WM5100_AUDIO_IF_1_26 0x519 +#define WM5100_AUDIO_IF_1_27 0x51A +#define WM5100_AUDIO_IF_2_1 0x540 +#define WM5100_AUDIO_IF_2_2 0x541 +#define WM5100_AUDIO_IF_2_3 0x542 +#define WM5100_AUDIO_IF_2_4 0x543 +#define WM5100_AUDIO_IF_2_5 0x544 +#define WM5100_AUDIO_IF_2_6 0x545 +#define WM5100_AUDIO_IF_2_7 0x546 +#define WM5100_AUDIO_IF_2_8 0x547 +#define WM5100_AUDIO_IF_2_9 0x548 +#define WM5100_AUDIO_IF_2_10 0x549 +#define WM5100_AUDIO_IF_2_11 0x54A +#define WM5100_AUDIO_IF_2_18 0x551 +#define WM5100_AUDIO_IF_2_19 0x552 +#define WM5100_AUDIO_IF_2_26 0x559 +#define WM5100_AUDIO_IF_2_27 0x55A +#define WM5100_AUDIO_IF_3_1 0x580 +#define WM5100_AUDIO_IF_3_2 0x581 +#define WM5100_AUDIO_IF_3_3 0x582 +#define WM5100_AUDIO_IF_3_4 0x583 +#define WM5100_AUDIO_IF_3_5 0x584 +#define WM5100_AUDIO_IF_3_6 0x585 +#define WM5100_AUDIO_IF_3_7 0x586 +#define WM5100_AUDIO_IF_3_8 0x587 +#define WM5100_AUDIO_IF_3_9 0x588 +#define WM5100_AUDIO_IF_3_10 0x589 +#define WM5100_AUDIO_IF_3_11 0x58A +#define WM5100_AUDIO_IF_3_18 0x591 +#define WM5100_AUDIO_IF_3_19 0x592 +#define WM5100_AUDIO_IF_3_26 0x599 +#define WM5100_AUDIO_IF_3_27 0x59A +#define WM5100_PWM1MIX_INPUT_1_SOURCE 0x640 +#define WM5100_PWM1MIX_INPUT_1_VOLUME 0x641 +#define WM5100_PWM1MIX_INPUT_2_SOURCE 0x642 +#define WM5100_PWM1MIX_INPUT_2_VOLUME 0x643 +#define WM5100_PWM1MIX_INPUT_3_SOURCE 0x644 +#define WM5100_PWM1MIX_INPUT_3_VOLUME 0x645 +#define WM5100_PWM1MIX_INPUT_4_SOURCE 0x646 +#define WM5100_PWM1MIX_INPUT_4_VOLUME 0x647 +#define WM5100_PWM2MIX_INPUT_1_SOURCE 0x648 +#define WM5100_PWM2MIX_INPUT_1_VOLUME 0x649 +#define WM5100_PWM2MIX_INPUT_2_SOURCE 0x64A +#define WM5100_PWM2MIX_INPUT_2_VOLUME 0x64B +#define WM5100_PWM2MIX_INPUT_3_SOURCE 0x64C +#define WM5100_PWM2MIX_INPUT_3_VOLUME 0x64D +#define WM5100_PWM2MIX_INPUT_4_SOURCE 0x64E +#define WM5100_PWM2MIX_INPUT_4_VOLUME 0x64F +#define WM5100_OUT1LMIX_INPUT_1_SOURCE 0x680 +#define WM5100_OUT1LMIX_INPUT_1_VOLUME 0x681 +#define WM5100_OUT1LMIX_INPUT_2_SOURCE 0x682 +#define WM5100_OUT1LMIX_INPUT_2_VOLUME 0x683 +#define WM5100_OUT1LMIX_INPUT_3_SOURCE 0x684 +#define WM5100_OUT1LMIX_INPUT_3_VOLUME 0x685 +#define WM5100_OUT1LMIX_INPUT_4_SOURCE 0x686 +#define WM5100_OUT1LMIX_INPUT_4_VOLUME 0x687 +#define WM5100_OUT1RMIX_INPUT_1_SOURCE 0x688 +#define WM5100_OUT1RMIX_INPUT_1_VOLUME 0x689 +#define WM5100_OUT1RMIX_INPUT_2_SOURCE 0x68A +#define WM5100_OUT1RMIX_INPUT_2_VOLUME 0x68B +#define WM5100_OUT1RMIX_INPUT_3_SOURCE 0x68C +#define WM5100_OUT1RMIX_INPUT_3_VOLUME 0x68D +#define WM5100_OUT1RMIX_INPUT_4_SOURCE 0x68E +#define WM5100_OUT1RMIX_INPUT_4_VOLUME 0x68F +#define WM5100_OUT2LMIX_INPUT_1_SOURCE 0x690 +#define WM5100_OUT2LMIX_INPUT_1_VOLUME 0x691 +#define WM5100_OUT2LMIX_INPUT_2_SOURCE 0x692 +#define WM5100_OUT2LMIX_INPUT_2_VOLUME 0x693 +#define WM5100_OUT2LMIX_INPUT_3_SOURCE 0x694 +#define WM5100_OUT2LMIX_INPUT_3_VOLUME 0x695 +#define WM5100_OUT2LMIX_INPUT_4_SOURCE 0x696 +#define WM5100_OUT2LMIX_INPUT_4_VOLUME 0x697 +#define WM5100_OUT2RMIX_INPUT_1_SOURCE 0x698 +#define WM5100_OUT2RMIX_INPUT_1_VOLUME 0x699 +#define WM5100_OUT2RMIX_INPUT_2_SOURCE 0x69A +#define WM5100_OUT2RMIX_INPUT_2_VOLUME 0x69B +#define WM5100_OUT2RMIX_INPUT_3_SOURCE 0x69C +#define WM5100_OUT2RMIX_INPUT_3_VOLUME 0x69D +#define WM5100_OUT2RMIX_INPUT_4_SOURCE 0x69E +#define WM5100_OUT2RMIX_INPUT_4_VOLUME 0x69F +#define WM5100_OUT3LMIX_INPUT_1_SOURCE 0x6A0 +#define WM5100_OUT3LMIX_INPUT_1_VOLUME 0x6A1 +#define WM5100_OUT3LMIX_INPUT_2_SOURCE 0x6A2 +#define WM5100_OUT3LMIX_INPUT_2_VOLUME 0x6A3 +#define WM5100_OUT3LMIX_INPUT_3_SOURCE 0x6A4 +#define WM5100_OUT3LMIX_INPUT_3_VOLUME 0x6A5 +#define WM5100_OUT3LMIX_INPUT_4_SOURCE 0x6A6 +#define WM5100_OUT3LMIX_INPUT_4_VOLUME 0x6A7 +#define WM5100_OUT3RMIX_INPUT_1_SOURCE 0x6A8 +#define WM5100_OUT3RMIX_INPUT_1_VOLUME 0x6A9 +#define WM5100_OUT3RMIX_INPUT_2_SOURCE 0x6AA +#define WM5100_OUT3RMIX_INPUT_2_VOLUME 0x6AB +#define WM5100_OUT3RMIX_INPUT_3_SOURCE 0x6AC +#define WM5100_OUT3RMIX_INPUT_3_VOLUME 0x6AD +#define WM5100_OUT3RMIX_INPUT_4_SOURCE 0x6AE +#define WM5100_OUT3RMIX_INPUT_4_VOLUME 0x6AF +#define WM5100_OUT4LMIX_INPUT_1_SOURCE 0x6B0 +#define WM5100_OUT4LMIX_INPUT_1_VOLUME 0x6B1 +#define WM5100_OUT4LMIX_INPUT_2_SOURCE 0x6B2 +#define WM5100_OUT4LMIX_INPUT_2_VOLUME 0x6B3 +#define WM5100_OUT4LMIX_INPUT_3_SOURCE 0x6B4 +#define WM5100_OUT4LMIX_INPUT_3_VOLUME 0x6B5 +#define WM5100_OUT4LMIX_INPUT_4_SOURCE 0x6B6 +#define WM5100_OUT4LMIX_INPUT_4_VOLUME 0x6B7 +#define WM5100_OUT4RMIX_INPUT_1_SOURCE 0x6B8 +#define WM5100_OUT4RMIX_INPUT_1_VOLUME 0x6B9 +#define WM5100_OUT4RMIX_INPUT_2_SOURCE 0x6BA +#define WM5100_OUT4RMIX_INPUT_2_VOLUME 0x6BB +#define WM5100_OUT4RMIX_INPUT_3_SOURCE 0x6BC +#define WM5100_OUT4RMIX_INPUT_3_VOLUME 0x6BD +#define WM5100_OUT4RMIX_INPUT_4_SOURCE 0x6BE +#define WM5100_OUT4RMIX_INPUT_4_VOLUME 0x6BF +#define WM5100_OUT5LMIX_INPUT_1_SOURCE 0x6C0 +#define WM5100_OUT5LMIX_INPUT_1_VOLUME 0x6C1 +#define WM5100_OUT5LMIX_INPUT_2_SOURCE 0x6C2 +#define WM5100_OUT5LMIX_INPUT_2_VOLUME 0x6C3 +#define WM5100_OUT5LMIX_INPUT_3_SOURCE 0x6C4 +#define WM5100_OUT5LMIX_INPUT_3_VOLUME 0x6C5 +#define WM5100_OUT5LMIX_INPUT_4_SOURCE 0x6C6 +#define WM5100_OUT5LMIX_INPUT_4_VOLUME 0x6C7 +#define WM5100_OUT5RMIX_INPUT_1_SOURCE 0x6C8 +#define WM5100_OUT5RMIX_INPUT_1_VOLUME 0x6C9 +#define WM5100_OUT5RMIX_INPUT_2_SOURCE 0x6CA +#define WM5100_OUT5RMIX_INPUT_2_VOLUME 0x6CB +#define WM5100_OUT5RMIX_INPUT_3_SOURCE 0x6CC +#define WM5100_OUT5RMIX_INPUT_3_VOLUME 0x6CD +#define WM5100_OUT5RMIX_INPUT_4_SOURCE 0x6CE +#define WM5100_OUT5RMIX_INPUT_4_VOLUME 0x6CF +#define WM5100_OUT6LMIX_INPUT_1_SOURCE 0x6D0 +#define WM5100_OUT6LMIX_INPUT_1_VOLUME 0x6D1 +#define WM5100_OUT6LMIX_INPUT_2_SOURCE 0x6D2 +#define WM5100_OUT6LMIX_INPUT_2_VOLUME 0x6D3 +#define WM5100_OUT6LMIX_INPUT_3_SOURCE 0x6D4 +#define WM5100_OUT6LMIX_INPUT_3_VOLUME 0x6D5 +#define WM5100_OUT6LMIX_INPUT_4_SOURCE 0x6D6 +#define WM5100_OUT6LMIX_INPUT_4_VOLUME 0x6D7 +#define WM5100_OUT6RMIX_INPUT_1_SOURCE 0x6D8 +#define WM5100_OUT6RMIX_INPUT_1_VOLUME 0x6D9 +#define WM5100_OUT6RMIX_INPUT_2_SOURCE 0x6DA +#define WM5100_OUT6RMIX_INPUT_2_VOLUME 0x6DB +#define WM5100_OUT6RMIX_INPUT_3_SOURCE 0x6DC +#define WM5100_OUT6RMIX_INPUT_3_VOLUME 0x6DD +#define WM5100_OUT6RMIX_INPUT_4_SOURCE 0x6DE +#define WM5100_OUT6RMIX_INPUT_4_VOLUME 0x6DF +#define WM5100_AIF1TX1MIX_INPUT_1_SOURCE 0x700 +#define WM5100_AIF1TX1MIX_INPUT_1_VOLUME 0x701 +#define WM5100_AIF1TX1MIX_INPUT_2_SOURCE 0x702 +#define WM5100_AIF1TX1MIX_INPUT_2_VOLUME 0x703 +#define WM5100_AIF1TX1MIX_INPUT_3_SOURCE 0x704 +#define WM5100_AIF1TX1MIX_INPUT_3_VOLUME 0x705 +#define WM5100_AIF1TX1MIX_INPUT_4_SOURCE 0x706 +#define WM5100_AIF1TX1MIX_INPUT_4_VOLUME 0x707 +#define WM5100_AIF1TX2MIX_INPUT_1_SOURCE 0x708 +#define WM5100_AIF1TX2MIX_INPUT_1_VOLUME 0x709 +#define WM5100_AIF1TX2MIX_INPUT_2_SOURCE 0x70A +#define WM5100_AIF1TX2MIX_INPUT_2_VOLUME 0x70B +#define WM5100_AIF1TX2MIX_INPUT_3_SOURCE 0x70C +#define WM5100_AIF1TX2MIX_INPUT_3_VOLUME 0x70D +#define WM5100_AIF1TX2MIX_INPUT_4_SOURCE 0x70E +#define WM5100_AIF1TX2MIX_INPUT_4_VOLUME 0x70F +#define WM5100_AIF1TX3MIX_INPUT_1_SOURCE 0x710 +#define WM5100_AIF1TX3MIX_INPUT_1_VOLUME 0x711 +#define WM5100_AIF1TX3MIX_INPUT_2_SOURCE 0x712 +#define WM5100_AIF1TX3MIX_INPUT_2_VOLUME 0x713 +#define WM5100_AIF1TX3MIX_INPUT_3_SOURCE 0x714 +#define WM5100_AIF1TX3MIX_INPUT_3_VOLUME 0x715 +#define WM5100_AIF1TX3MIX_INPUT_4_SOURCE 0x716 +#define WM5100_AIF1TX3MIX_INPUT_4_VOLUME 0x717 +#define WM5100_AIF1TX4MIX_INPUT_1_SOURCE 0x718 +#define WM5100_AIF1TX4MIX_INPUT_1_VOLUME 0x719 +#define WM5100_AIF1TX4MIX_INPUT_2_SOURCE 0x71A +#define WM5100_AIF1TX4MIX_INPUT_2_VOLUME 0x71B +#define WM5100_AIF1TX4MIX_INPUT_3_SOURCE 0x71C +#define WM5100_AIF1TX4MIX_INPUT_3_VOLUME 0x71D +#define WM5100_AIF1TX4MIX_INPUT_4_SOURCE 0x71E +#define WM5100_AIF1TX4MIX_INPUT_4_VOLUME 0x71F +#define WM5100_AIF1TX5MIX_INPUT_1_SOURCE 0x720 +#define WM5100_AIF1TX5MIX_INPUT_1_VOLUME 0x721 +#define WM5100_AIF1TX5MIX_INPUT_2_SOURCE 0x722 +#define WM5100_AIF1TX5MIX_INPUT_2_VOLUME 0x723 +#define WM5100_AIF1TX5MIX_INPUT_3_SOURCE 0x724 +#define WM5100_AIF1TX5MIX_INPUT_3_VOLUME 0x725 +#define WM5100_AIF1TX5MIX_INPUT_4_SOURCE 0x726 +#define WM5100_AIF1TX5MIX_INPUT_4_VOLUME 0x727 +#define WM5100_AIF1TX6MIX_INPUT_1_SOURCE 0x728 +#define WM5100_AIF1TX6MIX_INPUT_1_VOLUME 0x729 +#define WM5100_AIF1TX6MIX_INPUT_2_SOURCE 0x72A +#define WM5100_AIF1TX6MIX_INPUT_2_VOLUME 0x72B +#define WM5100_AIF1TX6MIX_INPUT_3_SOURCE 0x72C +#define WM5100_AIF1TX6MIX_INPUT_3_VOLUME 0x72D +#define WM5100_AIF1TX6MIX_INPUT_4_SOURCE 0x72E +#define WM5100_AIF1TX6MIX_INPUT_4_VOLUME 0x72F +#define WM5100_AIF1TX7MIX_INPUT_1_SOURCE 0x730 +#define WM5100_AIF1TX7MIX_INPUT_1_VOLUME 0x731 +#define WM5100_AIF1TX7MIX_INPUT_2_SOURCE 0x732 +#define WM5100_AIF1TX7MIX_INPUT_2_VOLUME 0x733 +#define WM5100_AIF1TX7MIX_INPUT_3_SOURCE 0x734 +#define WM5100_AIF1TX7MIX_INPUT_3_VOLUME 0x735 +#define WM5100_AIF1TX7MIX_INPUT_4_SOURCE 0x736 +#define WM5100_AIF1TX7MIX_INPUT_4_VOLUME 0x737 +#define WM5100_AIF1TX8MIX_INPUT_1_SOURCE 0x738 +#define WM5100_AIF1TX8MIX_INPUT_1_VOLUME 0x739 +#define WM5100_AIF1TX8MIX_INPUT_2_SOURCE 0x73A +#define WM5100_AIF1TX8MIX_INPUT_2_VOLUME 0x73B +#define WM5100_AIF1TX8MIX_INPUT_3_SOURCE 0x73C +#define WM5100_AIF1TX8MIX_INPUT_3_VOLUME 0x73D +#define WM5100_AIF1TX8MIX_INPUT_4_SOURCE 0x73E +#define WM5100_AIF1TX8MIX_INPUT_4_VOLUME 0x73F +#define WM5100_AIF2TX1MIX_INPUT_1_SOURCE 0x740 +#define WM5100_AIF2TX1MIX_INPUT_1_VOLUME 0x741 +#define WM5100_AIF2TX1MIX_INPUT_2_SOURCE 0x742 +#define WM5100_AIF2TX1MIX_INPUT_2_VOLUME 0x743 +#define WM5100_AIF2TX1MIX_INPUT_3_SOURCE 0x744 +#define WM5100_AIF2TX1MIX_INPUT_3_VOLUME 0x745 +#define WM5100_AIF2TX1MIX_INPUT_4_SOURCE 0x746 +#define WM5100_AIF2TX1MIX_INPUT_4_VOLUME 0x747 +#define WM5100_AIF2TX2MIX_INPUT_1_SOURCE 0x748 +#define WM5100_AIF2TX2MIX_INPUT_1_VOLUME 0x749 +#define WM5100_AIF2TX2MIX_INPUT_2_SOURCE 0x74A +#define WM5100_AIF2TX2MIX_INPUT_2_VOLUME 0x74B +#define WM5100_AIF2TX2MIX_INPUT_3_SOURCE 0x74C +#define WM5100_AIF2TX2MIX_INPUT_3_VOLUME 0x74D +#define WM5100_AIF2TX2MIX_INPUT_4_SOURCE 0x74E +#define WM5100_AIF2TX2MIX_INPUT_4_VOLUME 0x74F +#define WM5100_AIF3TX1MIX_INPUT_1_SOURCE 0x780 +#define WM5100_AIF3TX1MIX_INPUT_1_VOLUME 0x781 +#define WM5100_AIF3TX1MIX_INPUT_2_SOURCE 0x782 +#define WM5100_AIF3TX1MIX_INPUT_2_VOLUME 0x783 +#define WM5100_AIF3TX1MIX_INPUT_3_SOURCE 0x784 +#define WM5100_AIF3TX1MIX_INPUT_3_VOLUME 0x785 +#define WM5100_AIF3TX1MIX_INPUT_4_SOURCE 0x786 +#define WM5100_AIF3TX1MIX_INPUT_4_VOLUME 0x787 +#define WM5100_AIF3TX2MIX_INPUT_1_SOURCE 0x788 +#define WM5100_AIF3TX2MIX_INPUT_1_VOLUME 0x789 +#define WM5100_AIF3TX2MIX_INPUT_2_SOURCE 0x78A +#define WM5100_AIF3TX2MIX_INPUT_2_VOLUME 0x78B +#define WM5100_AIF3TX2MIX_INPUT_3_SOURCE 0x78C +#define WM5100_AIF3TX2MIX_INPUT_3_VOLUME 0x78D +#define WM5100_AIF3TX2MIX_INPUT_4_SOURCE 0x78E +#define WM5100_AIF3TX2MIX_INPUT_4_VOLUME 0x78F +#define WM5100_EQ1MIX_INPUT_1_SOURCE 0x880 +#define WM5100_EQ1MIX_INPUT_1_VOLUME 0x881 +#define WM5100_EQ1MIX_INPUT_2_SOURCE 0x882 +#define WM5100_EQ1MIX_INPUT_2_VOLUME 0x883 +#define WM5100_EQ1MIX_INPUT_3_SOURCE 0x884 +#define WM5100_EQ1MIX_INPUT_3_VOLUME 0x885 +#define WM5100_EQ1MIX_INPUT_4_SOURCE 0x886 +#define WM5100_EQ1MIX_INPUT_4_VOLUME 0x887 +#define WM5100_EQ2MIX_INPUT_1_SOURCE 0x888 +#define WM5100_EQ2MIX_INPUT_1_VOLUME 0x889 +#define WM5100_EQ2MIX_INPUT_2_SOURCE 0x88A +#define WM5100_EQ2MIX_INPUT_2_VOLUME 0x88B +#define WM5100_EQ2MIX_INPUT_3_SOURCE 0x88C +#define WM5100_EQ2MIX_INPUT_3_VOLUME 0x88D +#define WM5100_EQ2MIX_INPUT_4_SOURCE 0x88E +#define WM5100_EQ2MIX_INPUT_4_VOLUME 0x88F +#define WM5100_EQ3MIX_INPUT_1_SOURCE 0x890 +#define WM5100_EQ3MIX_INPUT_1_VOLUME 0x891 +#define WM5100_EQ3MIX_INPUT_2_SOURCE 0x892 +#define WM5100_EQ3MIX_INPUT_2_VOLUME 0x893 +#define WM5100_EQ3MIX_INPUT_3_SOURCE 0x894 +#define WM5100_EQ3MIX_INPUT_3_VOLUME 0x895 +#define WM5100_EQ3MIX_INPUT_4_SOURCE 0x896 +#define WM5100_EQ3MIX_INPUT_4_VOLUME 0x897 +#define WM5100_EQ4MIX_INPUT_1_SOURCE 0x898 +#define WM5100_EQ4MIX_INPUT_1_VOLUME 0x899 +#define WM5100_EQ4MIX_INPUT_2_SOURCE 0x89A +#define WM5100_EQ4MIX_INPUT_2_VOLUME 0x89B +#define WM5100_EQ4MIX_INPUT_3_SOURCE 0x89C +#define WM5100_EQ4MIX_INPUT_3_VOLUME 0x89D +#define WM5100_EQ4MIX_INPUT_4_SOURCE 0x89E +#define WM5100_EQ4MIX_INPUT_4_VOLUME 0x89F +#define WM5100_DRC1LMIX_INPUT_1_SOURCE 0x8C0 +#define WM5100_DRC1LMIX_INPUT_1_VOLUME 0x8C1 +#define WM5100_DRC1LMIX_INPUT_2_SOURCE 0x8C2 +#define WM5100_DRC1LMIX_INPUT_2_VOLUME 0x8C3 +#define WM5100_DRC1LMIX_INPUT_3_SOURCE 0x8C4 +#define WM5100_DRC1LMIX_INPUT_3_VOLUME 0x8C5 +#define WM5100_DRC1LMIX_INPUT_4_SOURCE 0x8C6 +#define WM5100_DRC1LMIX_INPUT_4_VOLUME 0x8C7 +#define WM5100_DRC1RMIX_INPUT_1_SOURCE 0x8C8 +#define WM5100_DRC1RMIX_INPUT_1_VOLUME 0x8C9 +#define WM5100_DRC1RMIX_INPUT_2_SOURCE 0x8CA +#define WM5100_DRC1RMIX_INPUT_2_VOLUME 0x8CB +#define WM5100_DRC1RMIX_INPUT_3_SOURCE 0x8CC +#define WM5100_DRC1RMIX_INPUT_3_VOLUME 0x8CD +#define WM5100_DRC1RMIX_INPUT_4_SOURCE 0x8CE +#define WM5100_DRC1RMIX_INPUT_4_VOLUME 0x8CF +#define WM5100_HPLP1MIX_INPUT_1_SOURCE 0x900 +#define WM5100_HPLP1MIX_INPUT_1_VOLUME 0x901 +#define WM5100_HPLP1MIX_INPUT_2_SOURCE 0x902 +#define WM5100_HPLP1MIX_INPUT_2_VOLUME 0x903 +#define WM5100_HPLP1MIX_INPUT_3_SOURCE 0x904 +#define WM5100_HPLP1MIX_INPUT_3_VOLUME 0x905 +#define WM5100_HPLP1MIX_INPUT_4_SOURCE 0x906 +#define WM5100_HPLP1MIX_INPUT_4_VOLUME 0x907 +#define WM5100_HPLP2MIX_INPUT_1_SOURCE 0x908 +#define WM5100_HPLP2MIX_INPUT_1_VOLUME 0x909 +#define WM5100_HPLP2MIX_INPUT_2_SOURCE 0x90A +#define WM5100_HPLP2MIX_INPUT_2_VOLUME 0x90B +#define WM5100_HPLP2MIX_INPUT_3_SOURCE 0x90C +#define WM5100_HPLP2MIX_INPUT_3_VOLUME 0x90D +#define WM5100_HPLP2MIX_INPUT_4_SOURCE 0x90E +#define WM5100_HPLP2MIX_INPUT_4_VOLUME 0x90F +#define WM5100_HPLP3MIX_INPUT_1_SOURCE 0x910 +#define WM5100_HPLP3MIX_INPUT_1_VOLUME 0x911 +#define WM5100_HPLP3MIX_INPUT_2_SOURCE 0x912 +#define WM5100_HPLP3MIX_INPUT_2_VOLUME 0x913 +#define WM5100_HPLP3MIX_INPUT_3_SOURCE 0x914 +#define WM5100_HPLP3MIX_INPUT_3_VOLUME 0x915 +#define WM5100_HPLP3MIX_INPUT_4_SOURCE 0x916 +#define WM5100_HPLP3MIX_INPUT_4_VOLUME 0x917 +#define WM5100_HPLP4MIX_INPUT_1_SOURCE 0x918 +#define WM5100_HPLP4MIX_INPUT_1_VOLUME 0x919 +#define WM5100_HPLP4MIX_INPUT_2_SOURCE 0x91A +#define WM5100_HPLP4MIX_INPUT_2_VOLUME 0x91B +#define WM5100_HPLP4MIX_INPUT_3_SOURCE 0x91C +#define WM5100_HPLP4MIX_INPUT_3_VOLUME 0x91D +#define WM5100_HPLP4MIX_INPUT_4_SOURCE 0x91E +#define WM5100_HPLP4MIX_INPUT_4_VOLUME 0x91F +#define WM5100_DSP1LMIX_INPUT_1_SOURCE 0x940 +#define WM5100_DSP1LMIX_INPUT_1_VOLUME 0x941 +#define WM5100_DSP1LMIX_INPUT_2_SOURCE 0x942 +#define WM5100_DSP1LMIX_INPUT_2_VOLUME 0x943 +#define WM5100_DSP1LMIX_INPUT_3_SOURCE 0x944 +#define WM5100_DSP1LMIX_INPUT_3_VOLUME 0x945 +#define WM5100_DSP1LMIX_INPUT_4_SOURCE 0x946 +#define WM5100_DSP1LMIX_INPUT_4_VOLUME 0x947 +#define WM5100_DSP1RMIX_INPUT_1_SOURCE 0x948 +#define WM5100_DSP1RMIX_INPUT_1_VOLUME 0x949 +#define WM5100_DSP1RMIX_INPUT_2_SOURCE 0x94A +#define WM5100_DSP1RMIX_INPUT_2_VOLUME 0x94B +#define WM5100_DSP1RMIX_INPUT_3_SOURCE 0x94C +#define WM5100_DSP1RMIX_INPUT_3_VOLUME 0x94D +#define WM5100_DSP1RMIX_INPUT_4_SOURCE 0x94E +#define WM5100_DSP1RMIX_INPUT_4_VOLUME 0x94F +#define WM5100_DSP1AUX1MIX_INPUT_1_SOURCE 0x950 +#define WM5100_DSP1AUX2MIX_INPUT_1_SOURCE 0x958 +#define WM5100_DSP1AUX3MIX_INPUT_1_SOURCE 0x960 +#define WM5100_DSP1AUX4MIX_INPUT_1_SOURCE 0x968 +#define WM5100_DSP1AUX5MIX_INPUT_1_SOURCE 0x970 +#define WM5100_DSP1AUX6MIX_INPUT_1_SOURCE 0x978 +#define WM5100_DSP2LMIX_INPUT_1_SOURCE 0x980 +#define WM5100_DSP2LMIX_INPUT_1_VOLUME 0x981 +#define WM5100_DSP2LMIX_INPUT_2_SOURCE 0x982 +#define WM5100_DSP2LMIX_INPUT_2_VOLUME 0x983 +#define WM5100_DSP2LMIX_INPUT_3_SOURCE 0x984 +#define WM5100_DSP2LMIX_INPUT_3_VOLUME 0x985 +#define WM5100_DSP2LMIX_INPUT_4_SOURCE 0x986 +#define WM5100_DSP2LMIX_INPUT_4_VOLUME 0x987 +#define WM5100_DSP2RMIX_INPUT_1_SOURCE 0x988 +#define WM5100_DSP2RMIX_INPUT_1_VOLUME 0x989 +#define WM5100_DSP2RMIX_INPUT_2_SOURCE 0x98A +#define WM5100_DSP2RMIX_INPUT_2_VOLUME 0x98B +#define WM5100_DSP2RMIX_INPUT_3_SOURCE 0x98C +#define WM5100_DSP2RMIX_INPUT_3_VOLUME 0x98D +#define WM5100_DSP2RMIX_INPUT_4_SOURCE 0x98E +#define WM5100_DSP2RMIX_INPUT_4_VOLUME 0x98F +#define WM5100_DSP2AUX1MIX_INPUT_1_SOURCE 0x990 +#define WM5100_DSP2AUX2MIX_INPUT_1_SOURCE 0x998 +#define WM5100_DSP2AUX3MIX_INPUT_1_SOURCE 0x9A0 +#define WM5100_DSP2AUX4MIX_INPUT_1_SOURCE 0x9A8 +#define WM5100_DSP2AUX5MIX_INPUT_1_SOURCE 0x9B0 +#define WM5100_DSP2AUX6MIX_INPUT_1_SOURCE 0x9B8 +#define WM5100_DSP3LMIX_INPUT_1_SOURCE 0x9C0 +#define WM5100_DSP3LMIX_INPUT_1_VOLUME 0x9C1 +#define WM5100_DSP3LMIX_INPUT_2_SOURCE 0x9C2 +#define WM5100_DSP3LMIX_INPUT_2_VOLUME 0x9C3 +#define WM5100_DSP3LMIX_INPUT_3_SOURCE 0x9C4 +#define WM5100_DSP3LMIX_INPUT_3_VOLUME 0x9C5 +#define WM5100_DSP3LMIX_INPUT_4_SOURCE 0x9C6 +#define WM5100_DSP3LMIX_INPUT_4_VOLUME 0x9C7 +#define WM5100_DSP3RMIX_INPUT_1_SOURCE 0x9C8 +#define WM5100_DSP3RMIX_INPUT_1_VOLUME 0x9C9 +#define WM5100_DSP3RMIX_INPUT_2_SOURCE 0x9CA +#define WM5100_DSP3RMIX_INPUT_2_VOLUME 0x9CB +#define WM5100_DSP3RMIX_INPUT_3_SOURCE 0x9CC +#define WM5100_DSP3RMIX_INPUT_3_VOLUME 0x9CD +#define WM5100_DSP3RMIX_INPUT_4_SOURCE 0x9CE +#define WM5100_DSP3RMIX_INPUT_4_VOLUME 0x9CF +#define WM5100_DSP3AUX1MIX_INPUT_1_SOURCE 0x9D0 +#define WM5100_DSP3AUX2MIX_INPUT_1_SOURCE 0x9D8 +#define WM5100_DSP3AUX3MIX_INPUT_1_SOURCE 0x9E0 +#define WM5100_DSP3AUX4MIX_INPUT_1_SOURCE 0x9E8 +#define WM5100_DSP3AUX5MIX_INPUT_1_SOURCE 0x9F0 +#define WM5100_DSP3AUX6MIX_INPUT_1_SOURCE 0x9F8 +#define WM5100_ASRC1LMIX_INPUT_1_SOURCE 0xA80 +#define WM5100_ASRC1RMIX_INPUT_1_SOURCE 0xA88 +#define WM5100_ASRC2LMIX_INPUT_1_SOURCE 0xA90 +#define WM5100_ASRC2RMIX_INPUT_1_SOURCE 0xA98 +#define WM5100_ISRC1DEC1MIX_INPUT_1_SOURCE 0xB00 +#define WM5100_ISRC1DEC2MIX_INPUT_1_SOURCE 0xB08 +#define WM5100_ISRC1DEC3MIX_INPUT_1_SOURCE 0xB10 +#define WM5100_ISRC1DEC4MIX_INPUT_1_SOURCE 0xB18 +#define WM5100_ISRC1INT1MIX_INPUT_1_SOURCE 0xB20 +#define WM5100_ISRC1INT2MIX_INPUT_1_SOURCE 0xB28 +#define WM5100_ISRC1INT3MIX_INPUT_1_SOURCE 0xB30 +#define WM5100_ISRC1INT4MIX_INPUT_1_SOURCE 0xB38 +#define WM5100_ISRC2DEC1MIX_INPUT_1_SOURCE 0xB40 +#define WM5100_ISRC2DEC2MIX_INPUT_1_SOURCE 0xB48 +#define WM5100_ISRC2DEC3MIX_INPUT_1_SOURCE 0xB50 +#define WM5100_ISRC2DEC4MIX_INPUT_1_SOURCE 0xB58 +#define WM5100_ISRC2INT1MIX_INPUT_1_SOURCE 0xB60 +#define WM5100_ISRC2INT2MIX_INPUT_1_SOURCE 0xB68 +#define WM5100_ISRC2INT3MIX_INPUT_1_SOURCE 0xB70 +#define WM5100_ISRC2INT4MIX_INPUT_1_SOURCE 0xB78 +#define WM5100_GPIO_CTRL_1 0xC00 +#define WM5100_GPIO_CTRL_2 0xC01 +#define WM5100_GPIO_CTRL_3 0xC02 +#define WM5100_GPIO_CTRL_4 0xC03 +#define WM5100_GPIO_CTRL_5 0xC04 +#define WM5100_GPIO_CTRL_6 0xC05 +#define WM5100_MISC_PAD_CTRL_1 0xC23 +#define WM5100_MISC_PAD_CTRL_2 0xC24 +#define WM5100_MISC_PAD_CTRL_3 0xC25 +#define WM5100_MISC_PAD_CTRL_4 0xC26 +#define WM5100_MISC_PAD_CTRL_5 0xC27 +#define WM5100_MISC_GPIO_1 0xC28 +#define WM5100_INTERRUPT_STATUS_1 0xD00 +#define WM5100_INTERRUPT_STATUS_2 0xD01 +#define WM5100_INTERRUPT_STATUS_3 0xD02 +#define WM5100_INTERRUPT_STATUS_4 0xD03 +#define WM5100_INTERRUPT_RAW_STATUS_2 0xD04 +#define WM5100_INTERRUPT_RAW_STATUS_3 0xD05 +#define WM5100_INTERRUPT_RAW_STATUS_4 0xD06 +#define WM5100_INTERRUPT_STATUS_1_MASK 0xD07 +#define WM5100_INTERRUPT_STATUS_2_MASK 0xD08 +#define WM5100_INTERRUPT_STATUS_3_MASK 0xD09 +#define WM5100_INTERRUPT_STATUS_4_MASK 0xD0A +#define WM5100_INTERRUPT_CONTROL 0xD1F +#define WM5100_IRQ_DEBOUNCE_1 0xD20 +#define WM5100_IRQ_DEBOUNCE_2 0xD21 +#define WM5100_FX_CTRL 0xE00 +#define WM5100_EQ1_1 0xE10 +#define WM5100_EQ1_2 0xE11 +#define WM5100_EQ1_3 0xE12 +#define WM5100_EQ1_4 0xE13 +#define WM5100_EQ1_5 0xE14 +#define WM5100_EQ1_6 0xE15 +#define WM5100_EQ1_7 0xE16 +#define WM5100_EQ1_8 0xE17 +#define WM5100_EQ1_9 0xE18 +#define WM5100_EQ1_10 0xE19 +#define WM5100_EQ1_11 0xE1A +#define WM5100_EQ1_12 0xE1B +#define WM5100_EQ1_13 0xE1C +#define WM5100_EQ1_14 0xE1D +#define WM5100_EQ1_15 0xE1E +#define WM5100_EQ1_16 0xE1F +#define WM5100_EQ1_17 0xE20 +#define WM5100_EQ1_18 0xE21 +#define WM5100_EQ1_19 0xE22 +#define WM5100_EQ1_20 0xE23 +#define WM5100_EQ2_1 0xE26 +#define WM5100_EQ2_2 0xE27 +#define WM5100_EQ2_3 0xE28 +#define WM5100_EQ2_4 0xE29 +#define WM5100_EQ2_5 0xE2A +#define WM5100_EQ2_6 0xE2B +#define WM5100_EQ2_7 0xE2C +#define WM5100_EQ2_8 0xE2D +#define WM5100_EQ2_9 0xE2E +#define WM5100_EQ2_10 0xE2F +#define WM5100_EQ2_11 0xE30 +#define WM5100_EQ2_12 0xE31 +#define WM5100_EQ2_13 0xE32 +#define WM5100_EQ2_14 0xE33 +#define WM5100_EQ2_15 0xE34 +#define WM5100_EQ2_16 0xE35 +#define WM5100_EQ2_17 0xE36 +#define WM5100_EQ2_18 0xE37 +#define WM5100_EQ2_19 0xE38 +#define WM5100_EQ2_20 0xE39 +#define WM5100_EQ3_1 0xE3C +#define WM5100_EQ3_2 0xE3D +#define WM5100_EQ3_3 0xE3E +#define WM5100_EQ3_4 0xE3F +#define WM5100_EQ3_5 0xE40 +#define WM5100_EQ3_6 0xE41 +#define WM5100_EQ3_7 0xE42 +#define WM5100_EQ3_8 0xE43 +#define WM5100_EQ3_9 0xE44 +#define WM5100_EQ3_10 0xE45 +#define WM5100_EQ3_11 0xE46 +#define WM5100_EQ3_12 0xE47 +#define WM5100_EQ3_13 0xE48 +#define WM5100_EQ3_14 0xE49 +#define WM5100_EQ3_15 0xE4A +#define WM5100_EQ3_16 0xE4B +#define WM5100_EQ3_17 0xE4C +#define WM5100_EQ3_18 0xE4D +#define WM5100_EQ3_19 0xE4E +#define WM5100_EQ3_20 0xE4F +#define WM5100_EQ4_1 0xE52 +#define WM5100_EQ4_2 0xE53 +#define WM5100_EQ4_3 0xE54 +#define WM5100_EQ4_4 0xE55 +#define WM5100_EQ4_5 0xE56 +#define WM5100_EQ4_6 0xE57 +#define WM5100_EQ4_7 0xE58 +#define WM5100_EQ4_8 0xE59 +#define WM5100_EQ4_9 0xE5A +#define WM5100_EQ4_10 0xE5B +#define WM5100_EQ4_11 0xE5C +#define WM5100_EQ4_12 0xE5D +#define WM5100_EQ4_13 0xE5E +#define WM5100_EQ4_14 0xE5F +#define WM5100_EQ4_15 0xE60 +#define WM5100_EQ4_16 0xE61 +#define WM5100_EQ4_17 0xE62 +#define WM5100_EQ4_18 0xE63 +#define WM5100_EQ4_19 0xE64 +#define WM5100_EQ4_20 0xE65 +#define WM5100_DRC1_CTRL1 0xE80 +#define WM5100_DRC1_CTRL2 0xE81 +#define WM5100_DRC1_CTRL3 0xE82 +#define WM5100_DRC1_CTRL4 0xE83 +#define WM5100_DRC1_CTRL5 0xE84 +#define WM5100_HPLPF1_1 0xEC0 +#define WM5100_HPLPF1_2 0xEC1 +#define WM5100_HPLPF2_1 0xEC4 +#define WM5100_HPLPF2_2 0xEC5 +#define WM5100_HPLPF3_1 0xEC8 +#define WM5100_HPLPF3_2 0xEC9 +#define WM5100_HPLPF4_1 0xECC +#define WM5100_HPLPF4_2 0xECD +#define WM5100_DSP1_DM_0 0x4000 +#define WM5100_DSP1_DM_1 0x4001 +#define WM5100_DSP1_DM_2 0x4002 +#define WM5100_DSP1_DM_3 0x4003 +#define WM5100_DSP1_DM_508 0x41FC +#define WM5100_DSP1_DM_509 0x41FD +#define WM5100_DSP1_DM_510 0x41FE +#define WM5100_DSP1_DM_511 0x41FF +#define WM5100_DSP1_PM_0 0x4800 +#define WM5100_DSP1_PM_1 0x4801 +#define WM5100_DSP1_PM_2 0x4802 +#define WM5100_DSP1_PM_3 0x4803 +#define WM5100_DSP1_PM_4 0x4804 +#define WM5100_DSP1_PM_5 0x4805 +#define WM5100_DSP1_PM_1530 0x4DFA +#define WM5100_DSP1_PM_1531 0x4DFB +#define WM5100_DSP1_PM_1532 0x4DFC +#define WM5100_DSP1_PM_1533 0x4DFD +#define WM5100_DSP1_PM_1534 0x4DFE +#define WM5100_DSP1_PM_1535 0x4DFF +#define WM5100_DSP1_ZM_0 0x5000 +#define WM5100_DSP1_ZM_1 0x5001 +#define WM5100_DSP1_ZM_2 0x5002 +#define WM5100_DSP1_ZM_3 0x5003 +#define WM5100_DSP1_ZM_2044 0x57FC +#define WM5100_DSP1_ZM_2045 0x57FD +#define WM5100_DSP1_ZM_2046 0x57FE +#define WM5100_DSP1_ZM_2047 0x57FF +#define WM5100_DSP2_DM_0 0x6000 +#define WM5100_DSP2_DM_1 0x6001 +#define WM5100_DSP2_DM_2 0x6002 +#define WM5100_DSP2_DM_3 0x6003 +#define WM5100_DSP2_DM_508 0x61FC +#define WM5100_DSP2_DM_509 0x61FD +#define WM5100_DSP2_DM_510 0x61FE +#define WM5100_DSP2_DM_511 0x61FF +#define WM5100_DSP2_PM_0 0x6800 +#define WM5100_DSP2_PM_1 0x6801 +#define WM5100_DSP2_PM_2 0x6802 +#define WM5100_DSP2_PM_3 0x6803 +#define WM5100_DSP2_PM_4 0x6804 +#define WM5100_DSP2_PM_5 0x6805 +#define WM5100_DSP2_PM_1530 0x6DFA +#define WM5100_DSP2_PM_1531 0x6DFB +#define WM5100_DSP2_PM_1532 0x6DFC +#define WM5100_DSP2_PM_1533 0x6DFD +#define WM5100_DSP2_PM_1534 0x6DFE +#define WM5100_DSP2_PM_1535 0x6DFF +#define WM5100_DSP2_ZM_0 0x7000 +#define WM5100_DSP2_ZM_1 0x7001 +#define WM5100_DSP2_ZM_2 0x7002 +#define WM5100_DSP2_ZM_3 0x7003 +#define WM5100_DSP2_ZM_2044 0x77FC +#define WM5100_DSP2_ZM_2045 0x77FD +#define WM5100_DSP2_ZM_2046 0x77FE +#define WM5100_DSP2_ZM_2047 0x77FF +#define WM5100_DSP3_DM_0 0x8000 +#define WM5100_DSP3_DM_1 0x8001 +#define WM5100_DSP3_DM_2 0x8002 +#define WM5100_DSP3_DM_3 0x8003 +#define WM5100_DSP3_DM_508 0x81FC +#define WM5100_DSP3_DM_509 0x81FD +#define WM5100_DSP3_DM_510 0x81FE +#define WM5100_DSP3_DM_511 0x81FF +#define WM5100_DSP3_PM_0 0x8800 +#define WM5100_DSP3_PM_1 0x8801 +#define WM5100_DSP3_PM_2 0x8802 +#define WM5100_DSP3_PM_3 0x8803 +#define WM5100_DSP3_PM_4 0x8804 +#define WM5100_DSP3_PM_5 0x8805 +#define WM5100_DSP3_PM_1530 0x8DFA +#define WM5100_DSP3_PM_1531 0x8DFB +#define WM5100_DSP3_PM_1532 0x8DFC +#define WM5100_DSP3_PM_1533 0x8DFD +#define WM5100_DSP3_PM_1534 0x8DFE +#define WM5100_DSP3_PM_1535 0x8DFF +#define WM5100_DSP3_ZM_0 0x9000 +#define WM5100_DSP3_ZM_1 0x9001 +#define WM5100_DSP3_ZM_2 0x9002 +#define WM5100_DSP3_ZM_3 0x9003 +#define WM5100_DSP3_ZM_2044 0x97FC +#define WM5100_DSP3_ZM_2045 0x97FD +#define WM5100_DSP3_ZM_2046 0x97FE +#define WM5100_DSP3_ZM_2047 0x97FF + +#define WM5100_REGISTER_COUNT 1435 +#define WM5100_MAX_REGISTER 0x97FF + +/* + * Field Definitions. + */ + +/* + * R0 (0x00) - software reset + */ +#define WM5100_SW_RST_DEV_ID1_MASK 0xFFFF /* SW_RST_DEV_ID1 - [15:0] */ +#define WM5100_SW_RST_DEV_ID1_SHIFT 0 /* SW_RST_DEV_ID1 - [15:0] */ +#define WM5100_SW_RST_DEV_ID1_WIDTH 16 /* SW_RST_DEV_ID1 - [15:0] */ + +/* + * R1 (0x01) - Device Revision + */ +#define WM5100_DEVICE_REVISION_MASK 0x000F /* DEVICE_REVISION - [3:0] */ +#define WM5100_DEVICE_REVISION_SHIFT 0 /* DEVICE_REVISION - [3:0] */ +#define WM5100_DEVICE_REVISION_WIDTH 4 /* DEVICE_REVISION - [3:0] */ + +/* + * R16 (0x10) - Ctrl IF 1 + */ +#define WM5100_AUTO_INC 0x0001 /* AUTO_INC */ +#define WM5100_AUTO_INC_MASK 0x0001 /* AUTO_INC */ +#define WM5100_AUTO_INC_SHIFT 0 /* AUTO_INC */ +#define WM5100_AUTO_INC_WIDTH 1 /* AUTO_INC */ + +/* + * R32 (0x20) - Tone Generator 1 + */ +#define WM5100_TONE_RATE_MASK 0x3000 /* TONE_RATE - [13:12] */ +#define WM5100_TONE_RATE_SHIFT 12 /* TONE_RATE - [13:12] */ +#define WM5100_TONE_RATE_WIDTH 2 /* TONE_RATE - [13:12] */ +#define WM5100_TONE_OFFSET_MASK 0x0300 /* TONE_OFFSET - [9:8] */ +#define WM5100_TONE_OFFSET_SHIFT 8 /* TONE_OFFSET - [9:8] */ +#define WM5100_TONE_OFFSET_WIDTH 2 /* TONE_OFFSET - [9:8] */ +#define WM5100_TONE2_ENA 0x0002 /* TONE2_ENA */ +#define WM5100_TONE2_ENA_MASK 0x0002 /* TONE2_ENA */ +#define WM5100_TONE2_ENA_SHIFT 1 /* TONE2_ENA */ +#define WM5100_TONE2_ENA_WIDTH 1 /* TONE2_ENA */ +#define WM5100_TONE1_ENA 0x0001 /* TONE1_ENA */ +#define WM5100_TONE1_ENA_MASK 0x0001 /* TONE1_ENA */ +#define WM5100_TONE1_ENA_SHIFT 0 /* TONE1_ENA */ +#define WM5100_TONE1_ENA_WIDTH 1 /* TONE1_ENA */ + +/* + * R48 (0x30) - PWM Drive 1 + */ +#define WM5100_PWM_RATE_MASK 0x3000 /* PWM_RATE - [13:12] */ +#define WM5100_PWM_RATE_SHIFT 12 /* PWM_RATE - [13:12] */ +#define WM5100_PWM_RATE_WIDTH 2 /* PWM_RATE - [13:12] */ +#define WM5100_PWM_CLK_SEL_MASK 0x0300 /* PWM_CLK_SEL - [9:8] */ +#define WM5100_PWM_CLK_SEL_SHIFT 8 /* PWM_CLK_SEL - [9:8] */ +#define WM5100_PWM_CLK_SEL_WIDTH 2 /* PWM_CLK_SEL - [9:8] */ +#define WM5100_PWM2_OVD 0x0020 /* PWM2_OVD */ +#define WM5100_PWM2_OVD_MASK 0x0020 /* PWM2_OVD */ +#define WM5100_PWM2_OVD_SHIFT 5 /* PWM2_OVD */ +#define WM5100_PWM2_OVD_WIDTH 1 /* PWM2_OVD */ +#define WM5100_PWM1_OVD 0x0010 /* PWM1_OVD */ +#define WM5100_PWM1_OVD_MASK 0x0010 /* PWM1_OVD */ +#define WM5100_PWM1_OVD_SHIFT 4 /* PWM1_OVD */ +#define WM5100_PWM1_OVD_WIDTH 1 /* PWM1_OVD */ +#define WM5100_PWM2_ENA 0x0002 /* PWM2_ENA */ +#define WM5100_PWM2_ENA_MASK 0x0002 /* PWM2_ENA */ +#define WM5100_PWM2_ENA_SHIFT 1 /* PWM2_ENA */ +#define WM5100_PWM2_ENA_WIDTH 1 /* PWM2_ENA */ +#define WM5100_PWM1_ENA 0x0001 /* PWM1_ENA */ +#define WM5100_PWM1_ENA_MASK 0x0001 /* PWM1_ENA */ +#define WM5100_PWM1_ENA_SHIFT 0 /* PWM1_ENA */ +#define WM5100_PWM1_ENA_WIDTH 1 /* PWM1_ENA */ + +/* + * R49 (0x31) - PWM Drive 2 + */ +#define WM5100_PWM1_LVL_MASK 0x03FF /* PWM1_LVL - [9:0] */ +#define WM5100_PWM1_LVL_SHIFT 0 /* PWM1_LVL - [9:0] */ +#define WM5100_PWM1_LVL_WIDTH 10 /* PWM1_LVL - [9:0] */ + +/* + * R50 (0x32) - PWM Drive 3 + */ +#define WM5100_PWM2_LVL_MASK 0x03FF /* PWM2_LVL - [9:0] */ +#define WM5100_PWM2_LVL_SHIFT 0 /* PWM2_LVL - [9:0] */ +#define WM5100_PWM2_LVL_WIDTH 10 /* PWM2_LVL - [9:0] */ + +/* + * R256 (0x100) - Clocking 1 + */ +#define WM5100_CLK_32K_SRC_MASK 0x000F /* CLK_32K_SRC - [3:0] */ +#define WM5100_CLK_32K_SRC_SHIFT 0 /* CLK_32K_SRC - [3:0] */ +#define WM5100_CLK_32K_SRC_WIDTH 4 /* CLK_32K_SRC - [3:0] */ + +/* + * R257 (0x101) - Clocking 3 + */ +#define WM5100_SYSCLK_FREQ_MASK 0x0700 /* SYSCLK_FREQ - [10:8] */ +#define WM5100_SYSCLK_FREQ_SHIFT 8 /* SYSCLK_FREQ - [10:8] */ +#define WM5100_SYSCLK_FREQ_WIDTH 3 /* SYSCLK_FREQ - [10:8] */ +#define WM5100_SYSCLK_ENA 0x0040 /* SYSCLK_ENA */ +#define WM5100_SYSCLK_ENA_MASK 0x0040 /* SYSCLK_ENA */ +#define WM5100_SYSCLK_ENA_SHIFT 6 /* SYSCLK_ENA */ +#define WM5100_SYSCLK_ENA_WIDTH 1 /* SYSCLK_ENA */ +#define WM5100_SYSCLK_SRC_MASK 0x000F /* SYSCLK_SRC - [3:0] */ +#define WM5100_SYSCLK_SRC_SHIFT 0 /* SYSCLK_SRC - [3:0] */ +#define WM5100_SYSCLK_SRC_WIDTH 4 /* SYSCLK_SRC - [3:0] */ + +/* + * R258 (0x102) - Clocking 4 + */ +#define WM5100_SAMPLE_RATE_1_MASK 0x001F /* SAMPLE_RATE_1 - [4:0] */ +#define WM5100_SAMPLE_RATE_1_SHIFT 0 /* SAMPLE_RATE_1 - [4:0] */ +#define WM5100_SAMPLE_RATE_1_WIDTH 5 /* SAMPLE_RATE_1 - [4:0] */ + +/* + * R259 (0x103) - Clocking 5 + */ +#define WM5100_SAMPLE_RATE_2_MASK 0x001F /* SAMPLE_RATE_2 - [4:0] */ +#define WM5100_SAMPLE_RATE_2_SHIFT 0 /* SAMPLE_RATE_2 - [4:0] */ +#define WM5100_SAMPLE_RATE_2_WIDTH 5 /* SAMPLE_RATE_2 - [4:0] */ + +/* + * R260 (0x104) - Clocking 6 + */ +#define WM5100_SAMPLE_RATE_3_MASK 0x001F /* SAMPLE_RATE_3 - [4:0] */ +#define WM5100_SAMPLE_RATE_3_SHIFT 0 /* SAMPLE_RATE_3 - [4:0] */ +#define WM5100_SAMPLE_RATE_3_WIDTH 5 /* SAMPLE_RATE_3 - [4:0] */ + +/* + * R263 (0x107) - Clocking 7 + */ +#define WM5100_ASYNC_CLK_FREQ_MASK 0x0700 /* ASYNC_CLK_FREQ - [10:8] */ +#define WM5100_ASYNC_CLK_FREQ_SHIFT 8 /* ASYNC_CLK_FREQ - [10:8] */ +#define WM5100_ASYNC_CLK_FREQ_WIDTH 3 /* ASYNC_CLK_FREQ - [10:8] */ +#define WM5100_ASYNC_CLK_ENA 0x0040 /* ASYNC_CLK_ENA */ +#define WM5100_ASYNC_CLK_ENA_MASK 0x0040 /* ASYNC_CLK_ENA */ +#define WM5100_ASYNC_CLK_ENA_SHIFT 6 /* ASYNC_CLK_ENA */ +#define WM5100_ASYNC_CLK_ENA_WIDTH 1 /* ASYNC_CLK_ENA */ +#define WM5100_ASYNC_CLK_SRC_MASK 0x000F /* ASYNC_CLK_SRC - [3:0] */ +#define WM5100_ASYNC_CLK_SRC_SHIFT 0 /* ASYNC_CLK_SRC - [3:0] */ +#define WM5100_ASYNC_CLK_SRC_WIDTH 4 /* ASYNC_CLK_SRC - [3:0] */ + +/* + * R264 (0x108) - Clocking 8 + */ +#define WM5100_ASYNC_SAMPLE_RATE_MASK 0x001F /* ASYNC_SAMPLE_RATE - [4:0] */ +#define WM5100_ASYNC_SAMPLE_RATE_SHIFT 0 /* ASYNC_SAMPLE_RATE - [4:0] */ +#define WM5100_ASYNC_SAMPLE_RATE_WIDTH 5 /* ASYNC_SAMPLE_RATE - [4:0] */ + +/* + * R288 (0x120) - ASRC_ENABLE + */ +#define WM5100_ASRC2L_ENA 0x0008 /* ASRC2L_ENA */ +#define WM5100_ASRC2L_ENA_MASK 0x0008 /* ASRC2L_ENA */ +#define WM5100_ASRC2L_ENA_SHIFT 3 /* ASRC2L_ENA */ +#define WM5100_ASRC2L_ENA_WIDTH 1 /* ASRC2L_ENA */ +#define WM5100_ASRC2R_ENA 0x0004 /* ASRC2R_ENA */ +#define WM5100_ASRC2R_ENA_MASK 0x0004 /* ASRC2R_ENA */ +#define WM5100_ASRC2R_ENA_SHIFT 2 /* ASRC2R_ENA */ +#define WM5100_ASRC2R_ENA_WIDTH 1 /* ASRC2R_ENA */ +#define WM5100_ASRC1L_ENA 0x0002 /* ASRC1L_ENA */ +#define WM5100_ASRC1L_ENA_MASK 0x0002 /* ASRC1L_ENA */ +#define WM5100_ASRC1L_ENA_SHIFT 1 /* ASRC1L_ENA */ +#define WM5100_ASRC1L_ENA_WIDTH 1 /* ASRC1L_ENA */ +#define WM5100_ASRC1R_ENA 0x0001 /* ASRC1R_ENA */ +#define WM5100_ASRC1R_ENA_MASK 0x0001 /* ASRC1R_ENA */ +#define WM5100_ASRC1R_ENA_SHIFT 0 /* ASRC1R_ENA */ +#define WM5100_ASRC1R_ENA_WIDTH 1 /* ASRC1R_ENA */ + +/* + * R289 (0x121) - ASRC_STATUS + */ +#define WM5100_ASRC2L_ENA_STS 0x0008 /* ASRC2L_ENA_STS */ +#define WM5100_ASRC2L_ENA_STS_MASK 0x0008 /* ASRC2L_ENA_STS */ +#define WM5100_ASRC2L_ENA_STS_SHIFT 3 /* ASRC2L_ENA_STS */ +#define WM5100_ASRC2L_ENA_STS_WIDTH 1 /* ASRC2L_ENA_STS */ +#define WM5100_ASRC2R_ENA_STS 0x0004 /* ASRC2R_ENA_STS */ +#define WM5100_ASRC2R_ENA_STS_MASK 0x0004 /* ASRC2R_ENA_STS */ +#define WM5100_ASRC2R_ENA_STS_SHIFT 2 /* ASRC2R_ENA_STS */ +#define WM5100_ASRC2R_ENA_STS_WIDTH 1 /* ASRC2R_ENA_STS */ +#define WM5100_ASRC1L_ENA_STS 0x0002 /* ASRC1L_ENA_STS */ +#define WM5100_ASRC1L_ENA_STS_MASK 0x0002 /* ASRC1L_ENA_STS */ +#define WM5100_ASRC1L_ENA_STS_SHIFT 1 /* ASRC1L_ENA_STS */ +#define WM5100_ASRC1L_ENA_STS_WIDTH 1 /* ASRC1L_ENA_STS */ +#define WM5100_ASRC1R_ENA_STS 0x0001 /* ASRC1R_ENA_STS */ +#define WM5100_ASRC1R_ENA_STS_MASK 0x0001 /* ASRC1R_ENA_STS */ +#define WM5100_ASRC1R_ENA_STS_SHIFT 0 /* ASRC1R_ENA_STS */ +#define WM5100_ASRC1R_ENA_STS_WIDTH 1 /* ASRC1R_ENA_STS */ + +/* + * R290 (0x122) - ASRC_RATE1 + */ +#define WM5100_ASRC_RATE1_MASK 0x0006 /* ASRC_RATE1 - [2:1] */ +#define WM5100_ASRC_RATE1_SHIFT 1 /* ASRC_RATE1 - [2:1] */ +#define WM5100_ASRC_RATE1_WIDTH 2 /* ASRC_RATE1 - [2:1] */ + +/* + * R321 (0x141) - ISRC 1 CTRL 1 + */ +#define WM5100_ISRC1_DFS_ENA 0x2000 /* ISRC1_DFS_ENA */ +#define WM5100_ISRC1_DFS_ENA_MASK 0x2000 /* ISRC1_DFS_ENA */ +#define WM5100_ISRC1_DFS_ENA_SHIFT 13 /* ISRC1_DFS_ENA */ +#define WM5100_ISRC1_DFS_ENA_WIDTH 1 /* ISRC1_DFS_ENA */ +#define WM5100_ISRC1_CLK_SEL_MASK 0x0300 /* ISRC1_CLK_SEL - [9:8] */ +#define WM5100_ISRC1_CLK_SEL_SHIFT 8 /* ISRC1_CLK_SEL - [9:8] */ +#define WM5100_ISRC1_CLK_SEL_WIDTH 2 /* ISRC1_CLK_SEL - [9:8] */ +#define WM5100_ISRC1_FSH_MASK 0x000C /* ISRC1_FSH - [3:2] */ +#define WM5100_ISRC1_FSH_SHIFT 2 /* ISRC1_FSH - [3:2] */ +#define WM5100_ISRC1_FSH_WIDTH 2 /* ISRC1_FSH - [3:2] */ +#define WM5100_ISRC1_FSL_MASK 0x0003 /* ISRC1_FSL - [1:0] */ +#define WM5100_ISRC1_FSL_SHIFT 0 /* ISRC1_FSL - [1:0] */ +#define WM5100_ISRC1_FSL_WIDTH 2 /* ISRC1_FSL - [1:0] */ + +/* + * R322 (0x142) - ISRC 1 CTRL 2 + */ +#define WM5100_ISRC1_INT1_ENA 0x8000 /* ISRC1_INT1_ENA */ +#define WM5100_ISRC1_INT1_ENA_MASK 0x8000 /* ISRC1_INT1_ENA */ +#define WM5100_ISRC1_INT1_ENA_SHIFT 15 /* ISRC1_INT1_ENA */ +#define WM5100_ISRC1_INT1_ENA_WIDTH 1 /* ISRC1_INT1_ENA */ +#define WM5100_ISRC1_INT2_ENA 0x4000 /* ISRC1_INT2_ENA */ +#define WM5100_ISRC1_INT2_ENA_MASK 0x4000 /* ISRC1_INT2_ENA */ +#define WM5100_ISRC1_INT2_ENA_SHIFT 14 /* ISRC1_INT2_ENA */ +#define WM5100_ISRC1_INT2_ENA_WIDTH 1 /* ISRC1_INT2_ENA */ +#define WM5100_ISRC1_INT3_ENA 0x2000 /* ISRC1_INT3_ENA */ +#define WM5100_ISRC1_INT3_ENA_MASK 0x2000 /* ISRC1_INT3_ENA */ +#define WM5100_ISRC1_INT3_ENA_SHIFT 13 /* ISRC1_INT3_ENA */ +#define WM5100_ISRC1_INT3_ENA_WIDTH 1 /* ISRC1_INT3_ENA */ +#define WM5100_ISRC1_INT4_ENA 0x1000 /* ISRC1_INT4_ENA */ +#define WM5100_ISRC1_INT4_ENA_MASK 0x1000 /* ISRC1_INT4_ENA */ +#define WM5100_ISRC1_INT4_ENA_SHIFT 12 /* ISRC1_INT4_ENA */ +#define WM5100_ISRC1_INT4_ENA_WIDTH 1 /* ISRC1_INT4_ENA */ +#define WM5100_ISRC1_DEC1_ENA 0x0200 /* ISRC1_DEC1_ENA */ +#define WM5100_ISRC1_DEC1_ENA_MASK 0x0200 /* ISRC1_DEC1_ENA */ +#define WM5100_ISRC1_DEC1_ENA_SHIFT 9 /* ISRC1_DEC1_ENA */ +#define WM5100_ISRC1_DEC1_ENA_WIDTH 1 /* ISRC1_DEC1_ENA */ +#define WM5100_ISRC1_DEC2_ENA 0x0100 /* ISRC1_DEC2_ENA */ +#define WM5100_ISRC1_DEC2_ENA_MASK 0x0100 /* ISRC1_DEC2_ENA */ +#define WM5100_ISRC1_DEC2_ENA_SHIFT 8 /* ISRC1_DEC2_ENA */ +#define WM5100_ISRC1_DEC2_ENA_WIDTH 1 /* ISRC1_DEC2_ENA */ +#define WM5100_ISRC1_DEC3_ENA 0x0080 /* ISRC1_DEC3_ENA */ +#define WM5100_ISRC1_DEC3_ENA_MASK 0x0080 /* ISRC1_DEC3_ENA */ +#define WM5100_ISRC1_DEC3_ENA_SHIFT 7 /* ISRC1_DEC3_ENA */ +#define WM5100_ISRC1_DEC3_ENA_WIDTH 1 /* ISRC1_DEC3_ENA */ +#define WM5100_ISRC1_DEC4_ENA 0x0040 /* ISRC1_DEC4_ENA */ +#define WM5100_ISRC1_DEC4_ENA_MASK 0x0040 /* ISRC1_DEC4_ENA */ +#define WM5100_ISRC1_DEC4_ENA_SHIFT 6 /* ISRC1_DEC4_ENA */ +#define WM5100_ISRC1_DEC4_ENA_WIDTH 1 /* ISRC1_DEC4_ENA */ +#define WM5100_ISRC1_NOTCH_ENA 0x0001 /* ISRC1_NOTCH_ENA */ +#define WM5100_ISRC1_NOTCH_ENA_MASK 0x0001 /* ISRC1_NOTCH_ENA */ +#define WM5100_ISRC1_NOTCH_ENA_SHIFT 0 /* ISRC1_NOTCH_ENA */ +#define WM5100_ISRC1_NOTCH_ENA_WIDTH 1 /* ISRC1_NOTCH_ENA */ + +/* + * R323 (0x143) - ISRC 2 CTRL1 + */ +#define WM5100_ISRC2_DFS_ENA 0x2000 /* ISRC2_DFS_ENA */ +#define WM5100_ISRC2_DFS_ENA_MASK 0x2000 /* ISRC2_DFS_ENA */ +#define WM5100_ISRC2_DFS_ENA_SHIFT 13 /* ISRC2_DFS_ENA */ +#define WM5100_ISRC2_DFS_ENA_WIDTH 1 /* ISRC2_DFS_ENA */ +#define WM5100_ISRC2_CLK_SEL_MASK 0x0300 /* ISRC2_CLK_SEL - [9:8] */ +#define WM5100_ISRC2_CLK_SEL_SHIFT 8 /* ISRC2_CLK_SEL - [9:8] */ +#define WM5100_ISRC2_CLK_SEL_WIDTH 2 /* ISRC2_CLK_SEL - [9:8] */ +#define WM5100_ISRC2_FSH_MASK 0x000C /* ISRC2_FSH - [3:2] */ +#define WM5100_ISRC2_FSH_SHIFT 2 /* ISRC2_FSH - [3:2] */ +#define WM5100_ISRC2_FSH_WIDTH 2 /* ISRC2_FSH - [3:2] */ +#define WM5100_ISRC2_FSL_MASK 0x0003 /* ISRC2_FSL - [1:0] */ +#define WM5100_ISRC2_FSL_SHIFT 0 /* ISRC2_FSL - [1:0] */ +#define WM5100_ISRC2_FSL_WIDTH 2 /* ISRC2_FSL - [1:0] */ + +/* + * R324 (0x144) - ISRC 2 CTRL 2 + */ +#define WM5100_ISRC2_INT1_ENA 0x8000 /* ISRC2_INT1_ENA */ +#define WM5100_ISRC2_INT1_ENA_MASK 0x8000 /* ISRC2_INT1_ENA */ +#define WM5100_ISRC2_INT1_ENA_SHIFT 15 /* ISRC2_INT1_ENA */ +#define WM5100_ISRC2_INT1_ENA_WIDTH 1 /* ISRC2_INT1_ENA */ +#define WM5100_ISRC2_INT2_ENA 0x4000 /* ISRC2_INT2_ENA */ +#define WM5100_ISRC2_INT2_ENA_MASK 0x4000 /* ISRC2_INT2_ENA */ +#define WM5100_ISRC2_INT2_ENA_SHIFT 14 /* ISRC2_INT2_ENA */ +#define WM5100_ISRC2_INT2_ENA_WIDTH 1 /* ISRC2_INT2_ENA */ +#define WM5100_ISRC2_INT3_ENA 0x2000 /* ISRC2_INT3_ENA */ +#define WM5100_ISRC2_INT3_ENA_MASK 0x2000 /* ISRC2_INT3_ENA */ +#define WM5100_ISRC2_INT3_ENA_SHIFT 13 /* ISRC2_INT3_ENA */ +#define WM5100_ISRC2_INT3_ENA_WIDTH 1 /* ISRC2_INT3_ENA */ +#define WM5100_ISRC2_INT4_ENA 0x1000 /* ISRC2_INT4_ENA */ +#define WM5100_ISRC2_INT4_ENA_MASK 0x1000 /* ISRC2_INT4_ENA */ +#define WM5100_ISRC2_INT4_ENA_SHIFT 12 /* ISRC2_INT4_ENA */ +#define WM5100_ISRC2_INT4_ENA_WIDTH 1 /* ISRC2_INT4_ENA */ +#define WM5100_ISRC2_DEC1_ENA 0x0200 /* ISRC2_DEC1_ENA */ +#define WM5100_ISRC2_DEC1_ENA_MASK 0x0200 /* ISRC2_DEC1_ENA */ +#define WM5100_ISRC2_DEC1_ENA_SHIFT 9 /* ISRC2_DEC1_ENA */ +#define WM5100_ISRC2_DEC1_ENA_WIDTH 1 /* ISRC2_DEC1_ENA */ +#define WM5100_ISRC2_DEC2_ENA 0x0100 /* ISRC2_DEC2_ENA */ +#define WM5100_ISRC2_DEC2_ENA_MASK 0x0100 /* ISRC2_DEC2_ENA */ +#define WM5100_ISRC2_DEC2_ENA_SHIFT 8 /* ISRC2_DEC2_ENA */ +#define WM5100_ISRC2_DEC2_ENA_WIDTH 1 /* ISRC2_DEC2_ENA */ +#define WM5100_ISRC2_DEC3_ENA 0x0080 /* ISRC2_DEC3_ENA */ +#define WM5100_ISRC2_DEC3_ENA_MASK 0x0080 /* ISRC2_DEC3_ENA */ +#define WM5100_ISRC2_DEC3_ENA_SHIFT 7 /* ISRC2_DEC3_ENA */ +#define WM5100_ISRC2_DEC3_ENA_WIDTH 1 /* ISRC2_DEC3_ENA */ +#define WM5100_ISRC2_DEC4_ENA 0x0040 /* ISRC2_DEC4_ENA */ +#define WM5100_ISRC2_DEC4_ENA_MASK 0x0040 /* ISRC2_DEC4_ENA */ +#define WM5100_ISRC2_DEC4_ENA_SHIFT 6 /* ISRC2_DEC4_ENA */ +#define WM5100_ISRC2_DEC4_ENA_WIDTH 1 /* ISRC2_DEC4_ENA */ +#define WM5100_ISRC2_NOTCH_ENA 0x0001 /* ISRC2_NOTCH_ENA */ +#define WM5100_ISRC2_NOTCH_ENA_MASK 0x0001 /* ISRC2_NOTCH_ENA */ +#define WM5100_ISRC2_NOTCH_ENA_SHIFT 0 /* ISRC2_NOTCH_ENA */ +#define WM5100_ISRC2_NOTCH_ENA_WIDTH 1 /* ISRC2_NOTCH_ENA */ + +/* + * R386 (0x182) - FLL1 Control 1 + */ +#define WM5100_FLL1_ENA 0x0001 /* FLL1_ENA */ +#define WM5100_FLL1_ENA_MASK 0x0001 /* FLL1_ENA */ +#define WM5100_FLL1_ENA_SHIFT 0 /* FLL1_ENA */ +#define WM5100_FLL1_ENA_WIDTH 1 /* FLL1_ENA */ + +/* + * R387 (0x183) - FLL1 Control 2 + */ +#define WM5100_FLL1_OUTDIV_MASK 0x3F00 /* FLL1_OUTDIV - [13:8] */ +#define WM5100_FLL1_OUTDIV_SHIFT 8 /* FLL1_OUTDIV - [13:8] */ +#define WM5100_FLL1_OUTDIV_WIDTH 6 /* FLL1_OUTDIV - [13:8] */ +#define WM5100_FLL1_FRATIO_MASK 0x0007 /* FLL1_FRATIO - [2:0] */ +#define WM5100_FLL1_FRATIO_SHIFT 0 /* FLL1_FRATIO - [2:0] */ +#define WM5100_FLL1_FRATIO_WIDTH 3 /* FLL1_FRATIO - [2:0] */ + +/* + * R388 (0x184) - FLL1 Control 3 + */ +#define WM5100_FLL1_THETA_MASK 0xFFFF /* FLL1_THETA - [15:0] */ +#define WM5100_FLL1_THETA_SHIFT 0 /* FLL1_THETA - [15:0] */ +#define WM5100_FLL1_THETA_WIDTH 16 /* FLL1_THETA - [15:0] */ + +/* + * R390 (0x186) - FLL1 Control 5 + */ +#define WM5100_FLL1_N_MASK 0x03FF /* FLL1_N - [9:0] */ +#define WM5100_FLL1_N_SHIFT 0 /* FLL1_N - [9:0] */ +#define WM5100_FLL1_N_WIDTH 10 /* FLL1_N - [9:0] */ + +/* + * R391 (0x187) - FLL1 Control 6 + */ +#define WM5100_FLL1_REFCLK_DIV_MASK 0x00C0 /* FLL1_REFCLK_DIV - [7:6] */ +#define WM5100_FLL1_REFCLK_DIV_SHIFT 6 /* FLL1_REFCLK_DIV - [7:6] */ +#define WM5100_FLL1_REFCLK_DIV_WIDTH 2 /* FLL1_REFCLK_DIV - [7:6] */ +#define WM5100_FLL1_REFCLK_SRC_MASK 0x000F /* FLL1_REFCLK_SRC - [3:0] */ +#define WM5100_FLL1_REFCLK_SRC_SHIFT 0 /* FLL1_REFCLK_SRC - [3:0] */ +#define WM5100_FLL1_REFCLK_SRC_WIDTH 4 /* FLL1_REFCLK_SRC - [3:0] */ + +/* + * R392 (0x188) - FLL1 EFS 1 + */ +#define WM5100_FLL1_LAMBDA_MASK 0xFFFF /* FLL1_LAMBDA - [15:0] */ +#define WM5100_FLL1_LAMBDA_SHIFT 0 /* FLL1_LAMBDA - [15:0] */ +#define WM5100_FLL1_LAMBDA_WIDTH 16 /* FLL1_LAMBDA - [15:0] */ + +/* + * R418 (0x1A2) - FLL2 Control 1 + */ +#define WM5100_FLL2_ENA 0x0001 /* FLL2_ENA */ +#define WM5100_FLL2_ENA_MASK 0x0001 /* FLL2_ENA */ +#define WM5100_FLL2_ENA_SHIFT 0 /* FLL2_ENA */ +#define WM5100_FLL2_ENA_WIDTH 1 /* FLL2_ENA */ + +/* + * R419 (0x1A3) - FLL2 Control 2 + */ +#define WM5100_FLL2_OUTDIV_MASK 0x3F00 /* FLL2_OUTDIV - [13:8] */ +#define WM5100_FLL2_OUTDIV_SHIFT 8 /* FLL2_OUTDIV - [13:8] */ +#define WM5100_FLL2_OUTDIV_WIDTH 6 /* FLL2_OUTDIV - [13:8] */ +#define WM5100_FLL2_FRATIO_MASK 0x0007 /* FLL2_FRATIO - [2:0] */ +#define WM5100_FLL2_FRATIO_SHIFT 0 /* FLL2_FRATIO - [2:0] */ +#define WM5100_FLL2_FRATIO_WIDTH 3 /* FLL2_FRATIO - [2:0] */ + +/* + * R420 (0x1A4) - FLL2 Control 3 + */ +#define WM5100_FLL2_THETA_MASK 0xFFFF /* FLL2_THETA - [15:0] */ +#define WM5100_FLL2_THETA_SHIFT 0 /* FLL2_THETA - [15:0] */ +#define WM5100_FLL2_THETA_WIDTH 16 /* FLL2_THETA - [15:0] */ + +/* + * R422 (0x1A6) - FLL2 Control 5 + */ +#define WM5100_FLL2_N_MASK 0x03FF /* FLL2_N - [9:0] */ +#define WM5100_FLL2_N_SHIFT 0 /* FLL2_N - [9:0] */ +#define WM5100_FLL2_N_WIDTH 10 /* FLL2_N - [9:0] */ + +/* + * R423 (0x1A7) - FLL2 Control 6 + */ +#define WM5100_FLL2_REFCLK_DIV_MASK 0x00C0 /* FLL2_REFCLK_DIV - [7:6] */ +#define WM5100_FLL2_REFCLK_DIV_SHIFT 6 /* FLL2_REFCLK_DIV - [7:6] */ +#define WM5100_FLL2_REFCLK_DIV_WIDTH 2 /* FLL2_REFCLK_DIV - [7:6] */ +#define WM5100_FLL2_REFCLK_SRC_MASK 0x000F /* FLL2_REFCLK_SRC - [3:0] */ +#define WM5100_FLL2_REFCLK_SRC_SHIFT 0 /* FLL2_REFCLK_SRC - [3:0] */ +#define WM5100_FLL2_REFCLK_SRC_WIDTH 4 /* FLL2_REFCLK_SRC - [3:0] */ + +/* + * R424 (0x1A8) - FLL2 EFS 1 + */ +#define WM5100_FLL2_LAMBDA_MASK 0xFFFF /* FLL2_LAMBDA - [15:0] */ +#define WM5100_FLL2_LAMBDA_SHIFT 0 /* FLL2_LAMBDA - [15:0] */ +#define WM5100_FLL2_LAMBDA_WIDTH 16 /* FLL2_LAMBDA - [15:0] */ + +/* + * R512 (0x200) - Mic Charge Pump 1 + */ +#define WM5100_CP2_BYPASS 0x0020 /* CP2_BYPASS */ +#define WM5100_CP2_BYPASS_MASK 0x0020 /* CP2_BYPASS */ +#define WM5100_CP2_BYPASS_SHIFT 5 /* CP2_BYPASS */ +#define WM5100_CP2_BYPASS_WIDTH 1 /* CP2_BYPASS */ +#define WM5100_CP2_ENA 0x0001 /* CP2_ENA */ +#define WM5100_CP2_ENA_MASK 0x0001 /* CP2_ENA */ +#define WM5100_CP2_ENA_SHIFT 0 /* CP2_ENA */ +#define WM5100_CP2_ENA_WIDTH 1 /* CP2_ENA */ + +/* + * R513 (0x201) - Mic Charge Pump 2 + */ +#define WM5100_LDO2_VSEL_MASK 0xF800 /* LDO2_VSEL - [15:11] */ +#define WM5100_LDO2_VSEL_SHIFT 11 /* LDO2_VSEL - [15:11] */ +#define WM5100_LDO2_VSEL_WIDTH 5 /* LDO2_VSEL - [15:11] */ + +/* + * R514 (0x202) - HP Charge Pump 1 + */ +#define WM5100_CP1_ENA 0x0001 /* CP1_ENA */ +#define WM5100_CP1_ENA_MASK 0x0001 /* CP1_ENA */ +#define WM5100_CP1_ENA_SHIFT 0 /* CP1_ENA */ +#define WM5100_CP1_ENA_WIDTH 1 /* CP1_ENA */ + +/* + * R529 (0x211) - LDO1 Control + */ +#define WM5100_LDO1_BYPASS 0x0002 /* LDO1_BYPASS */ +#define WM5100_LDO1_BYPASS_MASK 0x0002 /* LDO1_BYPASS */ +#define WM5100_LDO1_BYPASS_SHIFT 1 /* LDO1_BYPASS */ +#define WM5100_LDO1_BYPASS_WIDTH 1 /* LDO1_BYPASS */ + +/* + * R533 (0x215) - Mic Bias Ctrl 1 + */ +#define WM5100_MICB1_DISCH 0x0040 /* MICB1_DISCH */ +#define WM5100_MICB1_DISCH_MASK 0x0040 /* MICB1_DISCH */ +#define WM5100_MICB1_DISCH_SHIFT 6 /* MICB1_DISCH */ +#define WM5100_MICB1_DISCH_WIDTH 1 /* MICB1_DISCH */ +#define WM5100_MICB1_RATE 0x0020 /* MICB1_RATE */ +#define WM5100_MICB1_RATE_MASK 0x0020 /* MICB1_RATE */ +#define WM5100_MICB1_RATE_SHIFT 5 /* MICB1_RATE */ +#define WM5100_MICB1_RATE_WIDTH 1 /* MICB1_RATE */ +#define WM5100_MICB1_LVL_MASK 0x001C /* MICB1_LVL - [4:2] */ +#define WM5100_MICB1_LVL_SHIFT 2 /* MICB1_LVL - [4:2] */ +#define WM5100_MICB1_LVL_WIDTH 3 /* MICB1_LVL - [4:2] */ +#define WM5100_MICB1_BYPASS 0x0002 /* MICB1_BYPASS */ +#define WM5100_MICB1_BYPASS_MASK 0x0002 /* MICB1_BYPASS */ +#define WM5100_MICB1_BYPASS_SHIFT 1 /* MICB1_BYPASS */ +#define WM5100_MICB1_BYPASS_WIDTH 1 /* MICB1_BYPASS */ +#define WM5100_MICB1_ENA 0x0001 /* MICB1_ENA */ +#define WM5100_MICB1_ENA_MASK 0x0001 /* MICB1_ENA */ +#define WM5100_MICB1_ENA_SHIFT 0 /* MICB1_ENA */ +#define WM5100_MICB1_ENA_WIDTH 1 /* MICB1_ENA */ + +/* + * R534 (0x216) - Mic Bias Ctrl 2 + */ +#define WM5100_MICB2_DISCH 0x0040 /* MICB2_DISCH */ +#define WM5100_MICB2_DISCH_MASK 0x0040 /* MICB2_DISCH */ +#define WM5100_MICB2_DISCH_SHIFT 6 /* MICB2_DISCH */ +#define WM5100_MICB2_DISCH_WIDTH 1 /* MICB2_DISCH */ +#define WM5100_MICB2_RATE 0x0020 /* MICB2_RATE */ +#define WM5100_MICB2_RATE_MASK 0x0020 /* MICB2_RATE */ +#define WM5100_MICB2_RATE_SHIFT 5 /* MICB2_RATE */ +#define WM5100_MICB2_RATE_WIDTH 1 /* MICB2_RATE */ +#define WM5100_MICB2_LVL_MASK 0x001C /* MICB2_LVL - [4:2] */ +#define WM5100_MICB2_LVL_SHIFT 2 /* MICB2_LVL - [4:2] */ +#define WM5100_MICB2_LVL_WIDTH 3 /* MICB2_LVL - [4:2] */ +#define WM5100_MICB2_BYPASS 0x0002 /* MICB2_BYPASS */ +#define WM5100_MICB2_BYPASS_MASK 0x0002 /* MICB2_BYPASS */ +#define WM5100_MICB2_BYPASS_SHIFT 1 /* MICB2_BYPASS */ +#define WM5100_MICB2_BYPASS_WIDTH 1 /* MICB2_BYPASS */ +#define WM5100_MICB2_ENA 0x0001 /* MICB2_ENA */ +#define WM5100_MICB2_ENA_MASK 0x0001 /* MICB2_ENA */ +#define WM5100_MICB2_ENA_SHIFT 0 /* MICB2_ENA */ +#define WM5100_MICB2_ENA_WIDTH 1 /* MICB2_ENA */ + +/* + * R535 (0x217) - Mic Bias Ctrl 3 + */ +#define WM5100_MICB3_DISCH 0x0040 /* MICB3_DISCH */ +#define WM5100_MICB3_DISCH_MASK 0x0040 /* MICB3_DISCH */ +#define WM5100_MICB3_DISCH_SHIFT 6 /* MICB3_DISCH */ +#define WM5100_MICB3_DISCH_WIDTH 1 /* MICB3_DISCH */ +#define WM5100_MICB3_RATE 0x0020 /* MICB3_RATE */ +#define WM5100_MICB3_RATE_MASK 0x0020 /* MICB3_RATE */ +#define WM5100_MICB3_RATE_SHIFT 5 /* MICB3_RATE */ +#define WM5100_MICB3_RATE_WIDTH 1 /* MICB3_RATE */ +#define WM5100_MICB3_LVL_MASK 0x001C /* MICB3_LVL - [4:2] */ +#define WM5100_MICB3_LVL_SHIFT 2 /* MICB3_LVL - [4:2] */ +#define WM5100_MICB3_LVL_WIDTH 3 /* MICB3_LVL - [4:2] */ +#define WM5100_MICB3_BYPASS 0x0002 /* MICB3_BYPASS */ +#define WM5100_MICB3_BYPASS_MASK 0x0002 /* MICB3_BYPASS */ +#define WM5100_MICB3_BYPASS_SHIFT 1 /* MICB3_BYPASS */ +#define WM5100_MICB3_BYPASS_WIDTH 1 /* MICB3_BYPASS */ +#define WM5100_MICB3_ENA 0x0001 /* MICB3_ENA */ +#define WM5100_MICB3_ENA_MASK 0x0001 /* MICB3_ENA */ +#define WM5100_MICB3_ENA_SHIFT 0 /* MICB3_ENA */ +#define WM5100_MICB3_ENA_WIDTH 1 /* MICB3_ENA */ + +/* + * R640 (0x280) - Accessory Detect Mode 1 + */ +#define WM5100_ACCDET_BIAS_SRC_MASK 0xC000 /* ACCDET_BIAS_SRC - [15:14] */ +#define WM5100_ACCDET_BIAS_SRC_SHIFT 14 /* ACCDET_BIAS_SRC - [15:14] */ +#define WM5100_ACCDET_BIAS_SRC_WIDTH 2 /* ACCDET_BIAS_SRC - [15:14] */ +#define WM5100_ACCDET_SRC 0x2000 /* ACCDET_SRC */ +#define WM5100_ACCDET_SRC_MASK 0x2000 /* ACCDET_SRC */ +#define WM5100_ACCDET_SRC_SHIFT 13 /* ACCDET_SRC */ +#define WM5100_ACCDET_SRC_WIDTH 1 /* ACCDET_SRC */ +#define WM5100_ACCDET_MODE_MASK 0x0003 /* ACCDET_MODE - [1:0] */ +#define WM5100_ACCDET_MODE_SHIFT 0 /* ACCDET_MODE - [1:0] */ +#define WM5100_ACCDET_MODE_WIDTH 2 /* ACCDET_MODE - [1:0] */ + +/* + * R648 (0x288) - Headphone Detect 1 + */ +#define WM5100_HP_HOLDTIME_MASK 0x00E0 /* HP_HOLDTIME - [7:5] */ +#define WM5100_HP_HOLDTIME_SHIFT 5 /* HP_HOLDTIME - [7:5] */ +#define WM5100_HP_HOLDTIME_WIDTH 3 /* HP_HOLDTIME - [7:5] */ +#define WM5100_HP_CLK_DIV_MASK 0x0018 /* HP_CLK_DIV - [4:3] */ +#define WM5100_HP_CLK_DIV_SHIFT 3 /* HP_CLK_DIV - [4:3] */ +#define WM5100_HP_CLK_DIV_WIDTH 2 /* HP_CLK_DIV - [4:3] */ +#define WM5100_HP_STEP_SIZE 0x0002 /* HP_STEP_SIZE */ +#define WM5100_HP_STEP_SIZE_MASK 0x0002 /* HP_STEP_SIZE */ +#define WM5100_HP_STEP_SIZE_SHIFT 1 /* HP_STEP_SIZE */ +#define WM5100_HP_STEP_SIZE_WIDTH 1 /* HP_STEP_SIZE */ +#define WM5100_HP_POLL 0x0001 /* HP_POLL */ +#define WM5100_HP_POLL_MASK 0x0001 /* HP_POLL */ +#define WM5100_HP_POLL_SHIFT 0 /* HP_POLL */ +#define WM5100_HP_POLL_WIDTH 1 /* HP_POLL */ + +/* + * R649 (0x289) - Headphone Detect 2 + */ +#define WM5100_HP_DONE 0x0080 /* HP_DONE */ +#define WM5100_HP_DONE_MASK 0x0080 /* HP_DONE */ +#define WM5100_HP_DONE_SHIFT 7 /* HP_DONE */ +#define WM5100_HP_DONE_WIDTH 1 /* HP_DONE */ +#define WM5100_HP_LVL_MASK 0x007F /* HP_LVL - [6:0] */ +#define WM5100_HP_LVL_SHIFT 0 /* HP_LVL - [6:0] */ +#define WM5100_HP_LVL_WIDTH 7 /* HP_LVL - [6:0] */ + +/* + * R656 (0x290) - Mic Detect 1 + */ +#define WM5100_ACCDET_BIAS_STARTTIME_MASK 0xF000 /* ACCDET_BIAS_STARTTIME - [15:12] */ +#define WM5100_ACCDET_BIAS_STARTTIME_SHIFT 12 /* ACCDET_BIAS_STARTTIME - [15:12] */ +#define WM5100_ACCDET_BIAS_STARTTIME_WIDTH 4 /* ACCDET_BIAS_STARTTIME - [15:12] */ +#define WM5100_ACCDET_RATE_MASK 0x0F00 /* ACCDET_RATE - [11:8] */ +#define WM5100_ACCDET_RATE_SHIFT 8 /* ACCDET_RATE - [11:8] */ +#define WM5100_ACCDET_RATE_WIDTH 4 /* ACCDET_RATE - [11:8] */ +#define WM5100_ACCDET_DBTIME 0x0002 /* ACCDET_DBTIME */ +#define WM5100_ACCDET_DBTIME_MASK 0x0002 /* ACCDET_DBTIME */ +#define WM5100_ACCDET_DBTIME_SHIFT 1 /* ACCDET_DBTIME */ +#define WM5100_ACCDET_DBTIME_WIDTH 1 /* ACCDET_DBTIME */ +#define WM5100_ACCDET_ENA 0x0001 /* ACCDET_ENA */ +#define WM5100_ACCDET_ENA_MASK 0x0001 /* ACCDET_ENA */ +#define WM5100_ACCDET_ENA_SHIFT 0 /* ACCDET_ENA */ +#define WM5100_ACCDET_ENA_WIDTH 1 /* ACCDET_ENA */ + +/* + * R657 (0x291) - Mic Detect 2 + */ +#define WM5100_ACCDET_LVL_SEL_MASK 0x00FF /* ACCDET_LVL_SEL - [7:0] */ +#define WM5100_ACCDET_LVL_SEL_SHIFT 0 /* ACCDET_LVL_SEL - [7:0] */ +#define WM5100_ACCDET_LVL_SEL_WIDTH 8 /* ACCDET_LVL_SEL - [7:0] */ + +/* + * R658 (0x292) - Mic Detect 3 + */ +#define WM5100_ACCDET_LVL_MASK 0x07FC /* ACCDET_LVL - [10:2] */ +#define WM5100_ACCDET_LVL_SHIFT 2 /* ACCDET_LVL - [10:2] */ +#define WM5100_ACCDET_LVL_WIDTH 9 /* ACCDET_LVL - [10:2] */ +#define WM5100_ACCDET_VALID 0x0002 /* ACCDET_VALID */ +#define WM5100_ACCDET_VALID_MASK 0x0002 /* ACCDET_VALID */ +#define WM5100_ACCDET_VALID_SHIFT 1 /* ACCDET_VALID */ +#define WM5100_ACCDET_VALID_WIDTH 1 /* ACCDET_VALID */ +#define WM5100_ACCDET_STS 0x0001 /* ACCDET_STS */ +#define WM5100_ACCDET_STS_MASK 0x0001 /* ACCDET_STS */ +#define WM5100_ACCDET_STS_SHIFT 0 /* ACCDET_STS */ +#define WM5100_ACCDET_STS_WIDTH 1 /* ACCDET_STS */ + +/* + * R699 (0x2BB) - Misc Control + */ +#define WM5100_HPCOM_SRC 0x200 /* HPCOM_SRC */ +#define WM5100_HPCOM_SRC_SHIFT 9 /* HPCOM_SRC */ + +/* + * R769 (0x301) - Input Enables + */ +#define WM5100_IN4L_ENA 0x0080 /* IN4L_ENA */ +#define WM5100_IN4L_ENA_MASK 0x0080 /* IN4L_ENA */ +#define WM5100_IN4L_ENA_SHIFT 7 /* IN4L_ENA */ +#define WM5100_IN4L_ENA_WIDTH 1 /* IN4L_ENA */ +#define WM5100_IN4R_ENA 0x0040 /* IN4R_ENA */ +#define WM5100_IN4R_ENA_MASK 0x0040 /* IN4R_ENA */ +#define WM5100_IN4R_ENA_SHIFT 6 /* IN4R_ENA */ +#define WM5100_IN4R_ENA_WIDTH 1 /* IN4R_ENA */ +#define WM5100_IN3L_ENA 0x0020 /* IN3L_ENA */ +#define WM5100_IN3L_ENA_MASK 0x0020 /* IN3L_ENA */ +#define WM5100_IN3L_ENA_SHIFT 5 /* IN3L_ENA */ +#define WM5100_IN3L_ENA_WIDTH 1 /* IN3L_ENA */ +#define WM5100_IN3R_ENA 0x0010 /* IN3R_ENA */ +#define WM5100_IN3R_ENA_MASK 0x0010 /* IN3R_ENA */ +#define WM5100_IN3R_ENA_SHIFT 4 /* IN3R_ENA */ +#define WM5100_IN3R_ENA_WIDTH 1 /* IN3R_ENA */ +#define WM5100_IN2L_ENA 0x0008 /* IN2L_ENA */ +#define WM5100_IN2L_ENA_MASK 0x0008 /* IN2L_ENA */ +#define WM5100_IN2L_ENA_SHIFT 3 /* IN2L_ENA */ +#define WM5100_IN2L_ENA_WIDTH 1 /* IN2L_ENA */ +#define WM5100_IN2R_ENA 0x0004 /* IN2R_ENA */ +#define WM5100_IN2R_ENA_MASK 0x0004 /* IN2R_ENA */ +#define WM5100_IN2R_ENA_SHIFT 2 /* IN2R_ENA */ +#define WM5100_IN2R_ENA_WIDTH 1 /* IN2R_ENA */ +#define WM5100_IN1L_ENA 0x0002 /* IN1L_ENA */ +#define WM5100_IN1L_ENA_MASK 0x0002 /* IN1L_ENA */ +#define WM5100_IN1L_ENA_SHIFT 1 /* IN1L_ENA */ +#define WM5100_IN1L_ENA_WIDTH 1 /* IN1L_ENA */ +#define WM5100_IN1R_ENA 0x0001 /* IN1R_ENA */ +#define WM5100_IN1R_ENA_MASK 0x0001 /* IN1R_ENA */ +#define WM5100_IN1R_ENA_SHIFT 0 /* IN1R_ENA */ +#define WM5100_IN1R_ENA_WIDTH 1 /* IN1R_ENA */ + +/* + * R770 (0x302) - Input Enables Status + */ +#define WM5100_IN4L_ENA_STS 0x0080 /* IN4L_ENA_STS */ +#define WM5100_IN4L_ENA_STS_MASK 0x0080 /* IN4L_ENA_STS */ +#define WM5100_IN4L_ENA_STS_SHIFT 7 /* IN4L_ENA_STS */ +#define WM5100_IN4L_ENA_STS_WIDTH 1 /* IN4L_ENA_STS */ +#define WM5100_IN4R_ENA_STS 0x0040 /* IN4R_ENA_STS */ +#define WM5100_IN4R_ENA_STS_MASK 0x0040 /* IN4R_ENA_STS */ +#define WM5100_IN4R_ENA_STS_SHIFT 6 /* IN4R_ENA_STS */ +#define WM5100_IN4R_ENA_STS_WIDTH 1 /* IN4R_ENA_STS */ +#define WM5100_IN3L_ENA_STS 0x0020 /* IN3L_ENA_STS */ +#define WM5100_IN3L_ENA_STS_MASK 0x0020 /* IN3L_ENA_STS */ +#define WM5100_IN3L_ENA_STS_SHIFT 5 /* IN3L_ENA_STS */ +#define WM5100_IN3L_ENA_STS_WIDTH 1 /* IN3L_ENA_STS */ +#define WM5100_IN3R_ENA_STS 0x0010 /* IN3R_ENA_STS */ +#define WM5100_IN3R_ENA_STS_MASK 0x0010 /* IN3R_ENA_STS */ +#define WM5100_IN3R_ENA_STS_SHIFT 4 /* IN3R_ENA_STS */ +#define WM5100_IN3R_ENA_STS_WIDTH 1 /* IN3R_ENA_STS */ +#define WM5100_IN2L_ENA_STS 0x0008 /* IN2L_ENA_STS */ +#define WM5100_IN2L_ENA_STS_MASK 0x0008 /* IN2L_ENA_STS */ +#define WM5100_IN2L_ENA_STS_SHIFT 3 /* IN2L_ENA_STS */ +#define WM5100_IN2L_ENA_STS_WIDTH 1 /* IN2L_ENA_STS */ +#define WM5100_IN2R_ENA_STS 0x0004 /* IN2R_ENA_STS */ +#define WM5100_IN2R_ENA_STS_MASK 0x0004 /* IN2R_ENA_STS */ +#define WM5100_IN2R_ENA_STS_SHIFT 2 /* IN2R_ENA_STS */ +#define WM5100_IN2R_ENA_STS_WIDTH 1 /* IN2R_ENA_STS */ +#define WM5100_IN1L_ENA_STS 0x0002 /* IN1L_ENA_STS */ +#define WM5100_IN1L_ENA_STS_MASK 0x0002 /* IN1L_ENA_STS */ +#define WM5100_IN1L_ENA_STS_SHIFT 1 /* IN1L_ENA_STS */ +#define WM5100_IN1L_ENA_STS_WIDTH 1 /* IN1L_ENA_STS */ +#define WM5100_IN1R_ENA_STS 0x0001 /* IN1R_ENA_STS */ +#define WM5100_IN1R_ENA_STS_MASK 0x0001 /* IN1R_ENA_STS */ +#define WM5100_IN1R_ENA_STS_SHIFT 0 /* IN1R_ENA_STS */ +#define WM5100_IN1R_ENA_STS_WIDTH 1 /* IN1R_ENA_STS */ + +/* + * R784 (0x310) - IN1L Control + */ +#define WM5100_IN_RATE_MASK 0xC000 /* IN_RATE - [15:14] */ +#define WM5100_IN_RATE_SHIFT 14 /* IN_RATE - [15:14] */ +#define WM5100_IN_RATE_WIDTH 2 /* IN_RATE - [15:14] */ +#define WM5100_IN1_OSR 0x2000 /* IN1_OSR */ +#define WM5100_IN1_OSR_MASK 0x2000 /* IN1_OSR */ +#define WM5100_IN1_OSR_SHIFT 13 /* IN1_OSR */ +#define WM5100_IN1_OSR_WIDTH 1 /* IN1_OSR */ +#define WM5100_IN1_DMIC_SUP_MASK 0x1800 /* IN1_DMIC_SUP - [12:11] */ +#define WM5100_IN1_DMIC_SUP_SHIFT 11 /* IN1_DMIC_SUP - [12:11] */ +#define WM5100_IN1_DMIC_SUP_WIDTH 2 /* IN1_DMIC_SUP - [12:11] */ +#define WM5100_IN1_MODE_MASK 0x0600 /* IN1_MODE - [10:9] */ +#define WM5100_IN1_MODE_SHIFT 9 /* IN1_MODE - [10:9] */ +#define WM5100_IN1_MODE_WIDTH 2 /* IN1_MODE - [10:9] */ +#define WM5100_IN1L_PGA_VOL_MASK 0x00FE /* IN1L_PGA_VOL - [7:1] */ +#define WM5100_IN1L_PGA_VOL_SHIFT 1 /* IN1L_PGA_VOL - [7:1] */ +#define WM5100_IN1L_PGA_VOL_WIDTH 7 /* IN1L_PGA_VOL - [7:1] */ + +/* + * R785 (0x311) - IN1R Control + */ +#define WM5100_IN1R_PGA_VOL_MASK 0x00FE /* IN1R_PGA_VOL - [7:1] */ +#define WM5100_IN1R_PGA_VOL_SHIFT 1 /* IN1R_PGA_VOL - [7:1] */ +#define WM5100_IN1R_PGA_VOL_WIDTH 7 /* IN1R_PGA_VOL - [7:1] */ + +/* + * R786 (0x312) - IN2L Control + */ +#define WM5100_IN2_OSR 0x2000 /* IN2_OSR */ +#define WM5100_IN2_OSR_MASK 0x2000 /* IN2_OSR */ +#define WM5100_IN2_OSR_SHIFT 13 /* IN2_OSR */ +#define WM5100_IN2_OSR_WIDTH 1 /* IN2_OSR */ +#define WM5100_IN2_DMIC_SUP_MASK 0x1800 /* IN2_DMIC_SUP - [12:11] */ +#define WM5100_IN2_DMIC_SUP_SHIFT 11 /* IN2_DMIC_SUP - [12:11] */ +#define WM5100_IN2_DMIC_SUP_WIDTH 2 /* IN2_DMIC_SUP - [12:11] */ +#define WM5100_IN2_MODE_MASK 0x0600 /* IN2_MODE - [10:9] */ +#define WM5100_IN2_MODE_SHIFT 9 /* IN2_MODE - [10:9] */ +#define WM5100_IN2_MODE_WIDTH 2 /* IN2_MODE - [10:9] */ +#define WM5100_IN2L_PGA_VOL_MASK 0x00FE /* IN2L_PGA_VOL - [7:1] */ +#define WM5100_IN2L_PGA_VOL_SHIFT 1 /* IN2L_PGA_VOL - [7:1] */ +#define WM5100_IN2L_PGA_VOL_WIDTH 7 /* IN2L_PGA_VOL - [7:1] */ + +/* + * R787 (0x313) - IN2R Control + */ +#define WM5100_IN2R_PGA_VOL_MASK 0x00FE /* IN2R_PGA_VOL - [7:1] */ +#define WM5100_IN2R_PGA_VOL_SHIFT 1 /* IN2R_PGA_VOL - [7:1] */ +#define WM5100_IN2R_PGA_VOL_WIDTH 7 /* IN2R_PGA_VOL - [7:1] */ + +/* + * R788 (0x314) - IN3L Control + */ +#define WM5100_IN3_OSR 0x2000 /* IN3_OSR */ +#define WM5100_IN3_OSR_MASK 0x2000 /* IN3_OSR */ +#define WM5100_IN3_OSR_SHIFT 13 /* IN3_OSR */ +#define WM5100_IN3_OSR_WIDTH 1 /* IN3_OSR */ +#define WM5100_IN3_DMIC_SUP_MASK 0x1800 /* IN3_DMIC_SUP - [12:11] */ +#define WM5100_IN3_DMIC_SUP_SHIFT 11 /* IN3_DMIC_SUP - [12:11] */ +#define WM5100_IN3_DMIC_SUP_WIDTH 2 /* IN3_DMIC_SUP - [12:11] */ +#define WM5100_IN3_MODE_MASK 0x0600 /* IN3_MODE - [10:9] */ +#define WM5100_IN3_MODE_SHIFT 9 /* IN3_MODE - [10:9] */ +#define WM5100_IN3_MODE_WIDTH 2 /* IN3_MODE - [10:9] */ +#define WM5100_IN3L_PGA_VOL_MASK 0x00FE /* IN3L_PGA_VOL - [7:1] */ +#define WM5100_IN3L_PGA_VOL_SHIFT 1 /* IN3L_PGA_VOL - [7:1] */ +#define WM5100_IN3L_PGA_VOL_WIDTH 7 /* IN3L_PGA_VOL - [7:1] */ + +/* + * R789 (0x315) - IN3R Control + */ +#define WM5100_IN3R_PGA_VOL_MASK 0x00FE /* IN3R_PGA_VOL - [7:1] */ +#define WM5100_IN3R_PGA_VOL_SHIFT 1 /* IN3R_PGA_VOL - [7:1] */ +#define WM5100_IN3R_PGA_VOL_WIDTH 7 /* IN3R_PGA_VOL - [7:1] */ + +/* + * R790 (0x316) - IN4L Control + */ +#define WM5100_IN4_OSR 0x2000 /* IN4_OSR */ +#define WM5100_IN4_OSR_MASK 0x2000 /* IN4_OSR */ +#define WM5100_IN4_OSR_SHIFT 13 /* IN4_OSR */ +#define WM5100_IN4_OSR_WIDTH 1 /* IN4_OSR */ +#define WM5100_IN4_DMIC_SUP_MASK 0x1800 /* IN4_DMIC_SUP - [12:11] */ +#define WM5100_IN4_DMIC_SUP_SHIFT 11 /* IN4_DMIC_SUP - [12:11] */ +#define WM5100_IN4_DMIC_SUP_WIDTH 2 /* IN4_DMIC_SUP - [12:11] */ +#define WM5100_IN4_MODE_MASK 0x0600 /* IN4_MODE - [10:9] */ +#define WM5100_IN4_MODE_SHIFT 9 /* IN4_MODE - [10:9] */ +#define WM5100_IN4_MODE_WIDTH 2 /* IN4_MODE - [10:9] */ +#define WM5100_IN4L_PGA_VOL_MASK 0x00FE /* IN4L_PGA_VOL - [7:1] */ +#define WM5100_IN4L_PGA_VOL_SHIFT 1 /* IN4L_PGA_VOL - [7:1] */ +#define WM5100_IN4L_PGA_VOL_WIDTH 7 /* IN4L_PGA_VOL - [7:1] */ + +/* + * R791 (0x317) - IN4R Control + */ +#define WM5100_IN4R_PGA_VOL_MASK 0x00FE /* IN4R_PGA_VOL - [7:1] */ +#define WM5100_IN4R_PGA_VOL_SHIFT 1 /* IN4R_PGA_VOL - [7:1] */ +#define WM5100_IN4R_PGA_VOL_WIDTH 7 /* IN4R_PGA_VOL - [7:1] */ + +/* + * R792 (0x318) - RXANC_SRC + */ +#define WM5100_IN_RXANC_SEL_MASK 0x0007 /* IN_RXANC_SEL - [2:0] */ +#define WM5100_IN_RXANC_SEL_SHIFT 0 /* IN_RXANC_SEL - [2:0] */ +#define WM5100_IN_RXANC_SEL_WIDTH 3 /* IN_RXANC_SEL - [2:0] */ + +/* + * R793 (0x319) - Input Volume Ramp + */ +#define WM5100_IN_VD_RAMP_MASK 0x0070 /* IN_VD_RAMP - [6:4] */ +#define WM5100_IN_VD_RAMP_SHIFT 4 /* IN_VD_RAMP - [6:4] */ +#define WM5100_IN_VD_RAMP_WIDTH 3 /* IN_VD_RAMP - [6:4] */ +#define WM5100_IN_VI_RAMP_MASK 0x0007 /* IN_VI_RAMP - [2:0] */ +#define WM5100_IN_VI_RAMP_SHIFT 0 /* IN_VI_RAMP - [2:0] */ +#define WM5100_IN_VI_RAMP_WIDTH 3 /* IN_VI_RAMP - [2:0] */ + +/* + * R800 (0x320) - ADC Digital Volume 1L + */ +#define WM5100_IN_VU 0x0200 /* IN_VU */ +#define WM5100_IN_VU_MASK 0x0200 /* IN_VU */ +#define WM5100_IN_VU_SHIFT 9 /* IN_VU */ +#define WM5100_IN_VU_WIDTH 1 /* IN_VU */ +#define WM5100_IN1L_MUTE 0x0100 /* IN1L_MUTE */ +#define WM5100_IN1L_MUTE_MASK 0x0100 /* IN1L_MUTE */ +#define WM5100_IN1L_MUTE_SHIFT 8 /* IN1L_MUTE */ +#define WM5100_IN1L_MUTE_WIDTH 1 /* IN1L_MUTE */ +#define WM5100_IN1L_VOL_MASK 0x00FF /* IN1L_VOL - [7:0] */ +#define WM5100_IN1L_VOL_SHIFT 0 /* IN1L_VOL - [7:0] */ +#define WM5100_IN1L_VOL_WIDTH 8 /* IN1L_VOL - [7:0] */ + +/* + * R801 (0x321) - ADC Digital Volume 1R + */ +#define WM5100_IN_VU 0x0200 /* IN_VU */ +#define WM5100_IN_VU_MASK 0x0200 /* IN_VU */ +#define WM5100_IN_VU_SHIFT 9 /* IN_VU */ +#define WM5100_IN_VU_WIDTH 1 /* IN_VU */ +#define WM5100_IN1R_MUTE 0x0100 /* IN1R_MUTE */ +#define WM5100_IN1R_MUTE_MASK 0x0100 /* IN1R_MUTE */ +#define WM5100_IN1R_MUTE_SHIFT 8 /* IN1R_MUTE */ +#define WM5100_IN1R_MUTE_WIDTH 1 /* IN1R_MUTE */ +#define WM5100_IN1R_VOL_MASK 0x00FF /* IN1R_VOL - [7:0] */ +#define WM5100_IN1R_VOL_SHIFT 0 /* IN1R_VOL - [7:0] */ +#define WM5100_IN1R_VOL_WIDTH 8 /* IN1R_VOL - [7:0] */ + +/* + * R802 (0x322) - ADC Digital Volume 2L + */ +#define WM5100_IN_VU 0x0200 /* IN_VU */ +#define WM5100_IN_VU_MASK 0x0200 /* IN_VU */ +#define WM5100_IN_VU_SHIFT 9 /* IN_VU */ +#define WM5100_IN_VU_WIDTH 1 /* IN_VU */ +#define WM5100_IN2L_MUTE 0x0100 /* IN2L_MUTE */ +#define WM5100_IN2L_MUTE_MASK 0x0100 /* IN2L_MUTE */ +#define WM5100_IN2L_MUTE_SHIFT 8 /* IN2L_MUTE */ +#define WM5100_IN2L_MUTE_WIDTH 1 /* IN2L_MUTE */ +#define WM5100_IN2L_VOL_MASK 0x00FF /* IN2L_VOL - [7:0] */ +#define WM5100_IN2L_VOL_SHIFT 0 /* IN2L_VOL - [7:0] */ +#define WM5100_IN2L_VOL_WIDTH 8 /* IN2L_VOL - [7:0] */ + +/* + * R803 (0x323) - ADC Digital Volume 2R + */ +#define WM5100_IN_VU 0x0200 /* IN_VU */ +#define WM5100_IN_VU_MASK 0x0200 /* IN_VU */ +#define WM5100_IN_VU_SHIFT 9 /* IN_VU */ +#define WM5100_IN_VU_WIDTH 1 /* IN_VU */ +#define WM5100_IN2R_MUTE 0x0100 /* IN2R_MUTE */ +#define WM5100_IN2R_MUTE_MASK 0x0100 /* IN2R_MUTE */ +#define WM5100_IN2R_MUTE_SHIFT 8 /* IN2R_MUTE */ +#define WM5100_IN2R_MUTE_WIDTH 1 /* IN2R_MUTE */ +#define WM5100_IN2R_VOL_MASK 0x00FF /* IN2R_VOL - [7:0] */ +#define WM5100_IN2R_VOL_SHIFT 0 /* IN2R_VOL - [7:0] */ +#define WM5100_IN2R_VOL_WIDTH 8 /* IN2R_VOL - [7:0] */ + +/* + * R804 (0x324) - ADC Digital Volume 3L + */ +#define WM5100_IN_VU 0x0200 /* IN_VU */ +#define WM5100_IN_VU_MASK 0x0200 /* IN_VU */ +#define WM5100_IN_VU_SHIFT 9 /* IN_VU */ +#define WM5100_IN_VU_WIDTH 1 /* IN_VU */ +#define WM5100_IN3L_MUTE 0x0100 /* IN3L_MUTE */ +#define WM5100_IN3L_MUTE_MASK 0x0100 /* IN3L_MUTE */ +#define WM5100_IN3L_MUTE_SHIFT 8 /* IN3L_MUTE */ +#define WM5100_IN3L_MUTE_WIDTH 1 /* IN3L_MUTE */ +#define WM5100_IN3L_VOL_MASK 0x00FF /* IN3L_VOL - [7:0] */ +#define WM5100_IN3L_VOL_SHIFT 0 /* IN3L_VOL - [7:0] */ +#define WM5100_IN3L_VOL_WIDTH 8 /* IN3L_VOL - [7:0] */ + +/* + * R805 (0x325) - ADC Digital Volume 3R + */ +#define WM5100_IN_VU 0x0200 /* IN_VU */ +#define WM5100_IN_VU_MASK 0x0200 /* IN_VU */ +#define WM5100_IN_VU_SHIFT 9 /* IN_VU */ +#define WM5100_IN_VU_WIDTH 1 /* IN_VU */ +#define WM5100_IN3R_MUTE 0x0100 /* IN3R_MUTE */ +#define WM5100_IN3R_MUTE_MASK 0x0100 /* IN3R_MUTE */ +#define WM5100_IN3R_MUTE_SHIFT 8 /* IN3R_MUTE */ +#define WM5100_IN3R_MUTE_WIDTH 1 /* IN3R_MUTE */ +#define WM5100_IN3R_VOL_MASK 0x00FF /* IN3R_VOL - [7:0] */ +#define WM5100_IN3R_VOL_SHIFT 0 /* IN3R_VOL - [7:0] */ +#define WM5100_IN3R_VOL_WIDTH 8 /* IN3R_VOL - [7:0] */ + +/* + * R806 (0x326) - ADC Digital Volume 4L + */ +#define WM5100_IN_VU 0x0200 /* IN_VU */ +#define WM5100_IN_VU_MASK 0x0200 /* IN_VU */ +#define WM5100_IN_VU_SHIFT 9 /* IN_VU */ +#define WM5100_IN_VU_WIDTH 1 /* IN_VU */ +#define WM5100_IN4L_MUTE 0x0100 /* IN4L_MUTE */ +#define WM5100_IN4L_MUTE_MASK 0x0100 /* IN4L_MUTE */ +#define WM5100_IN4L_MUTE_SHIFT 8 /* IN4L_MUTE */ +#define WM5100_IN4L_MUTE_WIDTH 1 /* IN4L_MUTE */ +#define WM5100_IN4L_VOL_MASK 0x00FF /* IN4L_VOL - [7:0] */ +#define WM5100_IN4L_VOL_SHIFT 0 /* IN4L_VOL - [7:0] */ +#define WM5100_IN4L_VOL_WIDTH 8 /* IN4L_VOL - [7:0] */ + +/* + * R807 (0x327) - ADC Digital Volume 4R + */ +#define WM5100_IN_VU 0x0200 /* IN_VU */ +#define WM5100_IN_VU_MASK 0x0200 /* IN_VU */ +#define WM5100_IN_VU_SHIFT 9 /* IN_VU */ +#define WM5100_IN_VU_WIDTH 1 /* IN_VU */ +#define WM5100_IN4R_MUTE 0x0100 /* IN4R_MUTE */ +#define WM5100_IN4R_MUTE_MASK 0x0100 /* IN4R_MUTE */ +#define WM5100_IN4R_MUTE_SHIFT 8 /* IN4R_MUTE */ +#define WM5100_IN4R_MUTE_WIDTH 1 /* IN4R_MUTE */ +#define WM5100_IN4R_VOL_MASK 0x00FF /* IN4R_VOL - [7:0] */ +#define WM5100_IN4R_VOL_SHIFT 0 /* IN4R_VOL - [7:0] */ +#define WM5100_IN4R_VOL_WIDTH 8 /* IN4R_VOL - [7:0] */ + +/* + * R1025 (0x401) - Output Enables 2 + */ +#define WM5100_OUT6L_ENA 0x0800 /* OUT6L_ENA */ +#define WM5100_OUT6L_ENA_MASK 0x0800 /* OUT6L_ENA */ +#define WM5100_OUT6L_ENA_SHIFT 11 /* OUT6L_ENA */ +#define WM5100_OUT6L_ENA_WIDTH 1 /* OUT6L_ENA */ +#define WM5100_OUT6R_ENA 0x0400 /* OUT6R_ENA */ +#define WM5100_OUT6R_ENA_MASK 0x0400 /* OUT6R_ENA */ +#define WM5100_OUT6R_ENA_SHIFT 10 /* OUT6R_ENA */ +#define WM5100_OUT6R_ENA_WIDTH 1 /* OUT6R_ENA */ +#define WM5100_OUT5L_ENA 0x0200 /* OUT5L_ENA */ +#define WM5100_OUT5L_ENA_MASK 0x0200 /* OUT5L_ENA */ +#define WM5100_OUT5L_ENA_SHIFT 9 /* OUT5L_ENA */ +#define WM5100_OUT5L_ENA_WIDTH 1 /* OUT5L_ENA */ +#define WM5100_OUT5R_ENA 0x0100 /* OUT5R_ENA */ +#define WM5100_OUT5R_ENA_MASK 0x0100 /* OUT5R_ENA */ +#define WM5100_OUT5R_ENA_SHIFT 8 /* OUT5R_ENA */ +#define WM5100_OUT5R_ENA_WIDTH 1 /* OUT5R_ENA */ +#define WM5100_OUT4L_ENA 0x0080 /* OUT4L_ENA */ +#define WM5100_OUT4L_ENA_MASK 0x0080 /* OUT4L_ENA */ +#define WM5100_OUT4L_ENA_SHIFT 7 /* OUT4L_ENA */ +#define WM5100_OUT4L_ENA_WIDTH 1 /* OUT4L_ENA */ +#define WM5100_OUT4R_ENA 0x0040 /* OUT4R_ENA */ +#define WM5100_OUT4R_ENA_MASK 0x0040 /* OUT4R_ENA */ +#define WM5100_OUT4R_ENA_SHIFT 6 /* OUT4R_ENA */ +#define WM5100_OUT4R_ENA_WIDTH 1 /* OUT4R_ENA */ + +/* + * R1026 (0x402) - Output Status 1 + */ +#define WM5100_OUT3L_ENA_STS 0x0020 /* OUT3L_ENA_STS */ +#define WM5100_OUT3L_ENA_STS_MASK 0x0020 /* OUT3L_ENA_STS */ +#define WM5100_OUT3L_ENA_STS_SHIFT 5 /* OUT3L_ENA_STS */ +#define WM5100_OUT3L_ENA_STS_WIDTH 1 /* OUT3L_ENA_STS */ +#define WM5100_OUT3R_ENA_STS 0x0010 /* OUT3R_ENA_STS */ +#define WM5100_OUT3R_ENA_STS_MASK 0x0010 /* OUT3R_ENA_STS */ +#define WM5100_OUT3R_ENA_STS_SHIFT 4 /* OUT3R_ENA_STS */ +#define WM5100_OUT3R_ENA_STS_WIDTH 1 /* OUT3R_ENA_STS */ +#define WM5100_OUT2L_ENA_STS 0x0008 /* OUT2L_ENA_STS */ +#define WM5100_OUT2L_ENA_STS_MASK 0x0008 /* OUT2L_ENA_STS */ +#define WM5100_OUT2L_ENA_STS_SHIFT 3 /* OUT2L_ENA_STS */ +#define WM5100_OUT2L_ENA_STS_WIDTH 1 /* OUT2L_ENA_STS */ +#define WM5100_OUT2R_ENA_STS 0x0004 /* OUT2R_ENA_STS */ +#define WM5100_OUT2R_ENA_STS_MASK 0x0004 /* OUT2R_ENA_STS */ +#define WM5100_OUT2R_ENA_STS_SHIFT 2 /* OUT2R_ENA_STS */ +#define WM5100_OUT2R_ENA_STS_WIDTH 1 /* OUT2R_ENA_STS */ +#define WM5100_OUT1L_ENA_STS 0x0002 /* OUT1L_ENA_STS */ +#define WM5100_OUT1L_ENA_STS_MASK 0x0002 /* OUT1L_ENA_STS */ +#define WM5100_OUT1L_ENA_STS_SHIFT 1 /* OUT1L_ENA_STS */ +#define WM5100_OUT1L_ENA_STS_WIDTH 1 /* OUT1L_ENA_STS */ +#define WM5100_OUT1R_ENA_STS 0x0001 /* OUT1R_ENA_STS */ +#define WM5100_OUT1R_ENA_STS_MASK 0x0001 /* OUT1R_ENA_STS */ +#define WM5100_OUT1R_ENA_STS_SHIFT 0 /* OUT1R_ENA_STS */ +#define WM5100_OUT1R_ENA_STS_WIDTH 1 /* OUT1R_ENA_STS */ + +/* + * R1027 (0x403) - Output Status 2 + */ +#define WM5100_OUT6L_ENA_STS 0x0800 /* OUT6L_ENA_STS */ +#define WM5100_OUT6L_ENA_STS_MASK 0x0800 /* OUT6L_ENA_STS */ +#define WM5100_OUT6L_ENA_STS_SHIFT 11 /* OUT6L_ENA_STS */ +#define WM5100_OUT6L_ENA_STS_WIDTH 1 /* OUT6L_ENA_STS */ +#define WM5100_OUT6R_ENA_STS 0x0400 /* OUT6R_ENA_STS */ +#define WM5100_OUT6R_ENA_STS_MASK 0x0400 /* OUT6R_ENA_STS */ +#define WM5100_OUT6R_ENA_STS_SHIFT 10 /* OUT6R_ENA_STS */ +#define WM5100_OUT6R_ENA_STS_WIDTH 1 /* OUT6R_ENA_STS */ +#define WM5100_OUT5L_ENA_STS 0x0200 /* OUT5L_ENA_STS */ +#define WM5100_OUT5L_ENA_STS_MASK 0x0200 /* OUT5L_ENA_STS */ +#define WM5100_OUT5L_ENA_STS_SHIFT 9 /* OUT5L_ENA_STS */ +#define WM5100_OUT5L_ENA_STS_WIDTH 1 /* OUT5L_ENA_STS */ +#define WM5100_OUT5R_ENA_STS 0x0100 /* OUT5R_ENA_STS */ +#define WM5100_OUT5R_ENA_STS_MASK 0x0100 /* OUT5R_ENA_STS */ +#define WM5100_OUT5R_ENA_STS_SHIFT 8 /* OUT5R_ENA_STS */ +#define WM5100_OUT5R_ENA_STS_WIDTH 1 /* OUT5R_ENA_STS */ +#define WM5100_OUT4L_ENA_STS 0x0080 /* OUT4L_ENA_STS */ +#define WM5100_OUT4L_ENA_STS_MASK 0x0080 /* OUT4L_ENA_STS */ +#define WM5100_OUT4L_ENA_STS_SHIFT 7 /* OUT4L_ENA_STS */ +#define WM5100_OUT4L_ENA_STS_WIDTH 1 /* OUT4L_ENA_STS */ +#define WM5100_OUT4R_ENA_STS 0x0040 /* OUT4R_ENA_STS */ +#define WM5100_OUT4R_ENA_STS_MASK 0x0040 /* OUT4R_ENA_STS */ +#define WM5100_OUT4R_ENA_STS_SHIFT 6 /* OUT4R_ENA_STS */ +#define WM5100_OUT4R_ENA_STS_WIDTH 1 /* OUT4R_ENA_STS */ + +/* + * R1032 (0x408) - Channel Enables 1 + */ +#define WM5100_HP3L_ENA 0x0020 /* HP3L_ENA */ +#define WM5100_HP3L_ENA_MASK 0x0020 /* HP3L_ENA */ +#define WM5100_HP3L_ENA_SHIFT 5 /* HP3L_ENA */ +#define WM5100_HP3L_ENA_WIDTH 1 /* HP3L_ENA */ +#define WM5100_HP3R_ENA 0x0010 /* HP3R_ENA */ +#define WM5100_HP3R_ENA_MASK 0x0010 /* HP3R_ENA */ +#define WM5100_HP3R_ENA_SHIFT 4 /* HP3R_ENA */ +#define WM5100_HP3R_ENA_WIDTH 1 /* HP3R_ENA */ +#define WM5100_HP2L_ENA 0x0008 /* HP2L_ENA */ +#define WM5100_HP2L_ENA_MASK 0x0008 /* HP2L_ENA */ +#define WM5100_HP2L_ENA_SHIFT 3 /* HP2L_ENA */ +#define WM5100_HP2L_ENA_WIDTH 1 /* HP2L_ENA */ +#define WM5100_HP2R_ENA 0x0004 /* HP2R_ENA */ +#define WM5100_HP2R_ENA_MASK 0x0004 /* HP2R_ENA */ +#define WM5100_HP2R_ENA_SHIFT 2 /* HP2R_ENA */ +#define WM5100_HP2R_ENA_WIDTH 1 /* HP2R_ENA */ +#define WM5100_HP1L_ENA 0x0002 /* HP1L_ENA */ +#define WM5100_HP1L_ENA_MASK 0x0002 /* HP1L_ENA */ +#define WM5100_HP1L_ENA_SHIFT 1 /* HP1L_ENA */ +#define WM5100_HP1L_ENA_WIDTH 1 /* HP1L_ENA */ +#define WM5100_HP1R_ENA 0x0001 /* HP1R_ENA */ +#define WM5100_HP1R_ENA_MASK 0x0001 /* HP1R_ENA */ +#define WM5100_HP1R_ENA_SHIFT 0 /* HP1R_ENA */ +#define WM5100_HP1R_ENA_WIDTH 1 /* HP1R_ENA */ + +/* + * R1040 (0x410) - Out Volume 1L + */ +#define WM5100_OUT_RATE_MASK 0xC000 /* OUT_RATE - [15:14] */ +#define WM5100_OUT_RATE_SHIFT 14 /* OUT_RATE - [15:14] */ +#define WM5100_OUT_RATE_WIDTH 2 /* OUT_RATE - [15:14] */ +#define WM5100_OUT1_OSR 0x2000 /* OUT1_OSR */ +#define WM5100_OUT1_OSR_MASK 0x2000 /* OUT1_OSR */ +#define WM5100_OUT1_OSR_SHIFT 13 /* OUT1_OSR */ +#define WM5100_OUT1_OSR_WIDTH 1 /* OUT1_OSR */ +#define WM5100_OUT1_MONO 0x1000 /* OUT1_MONO */ +#define WM5100_OUT1_MONO_MASK 0x1000 /* OUT1_MONO */ +#define WM5100_OUT1_MONO_SHIFT 12 /* OUT1_MONO */ +#define WM5100_OUT1_MONO_WIDTH 1 /* OUT1_MONO */ +#define WM5100_OUT1L_ANC_SRC 0x0800 /* OUT1L_ANC_SRC */ +#define WM5100_OUT1L_ANC_SRC_MASK 0x0800 /* OUT1L_ANC_SRC */ +#define WM5100_OUT1L_ANC_SRC_SHIFT 11 /* OUT1L_ANC_SRC */ +#define WM5100_OUT1L_ANC_SRC_WIDTH 1 /* OUT1L_ANC_SRC */ +#define WM5100_OUT1L_PGA_VOL_MASK 0x00FE /* OUT1L_PGA_VOL - [7:1] */ +#define WM5100_OUT1L_PGA_VOL_SHIFT 1 /* OUT1L_PGA_VOL - [7:1] */ +#define WM5100_OUT1L_PGA_VOL_WIDTH 7 /* OUT1L_PGA_VOL - [7:1] */ + +/* + * R1041 (0x411) - Out Volume 1R + */ +#define WM5100_OUT1R_ANC_SRC 0x0800 /* OUT1R_ANC_SRC */ +#define WM5100_OUT1R_ANC_SRC_MASK 0x0800 /* OUT1R_ANC_SRC */ +#define WM5100_OUT1R_ANC_SRC_SHIFT 11 /* OUT1R_ANC_SRC */ +#define WM5100_OUT1R_ANC_SRC_WIDTH 1 /* OUT1R_ANC_SRC */ +#define WM5100_OUT1R_PGA_VOL_MASK 0x00FE /* OUT1R_PGA_VOL - [7:1] */ +#define WM5100_OUT1R_PGA_VOL_SHIFT 1 /* OUT1R_PGA_VOL - [7:1] */ +#define WM5100_OUT1R_PGA_VOL_WIDTH 7 /* OUT1R_PGA_VOL - [7:1] */ + +/* + * R1042 (0x412) - DAC Volume Limit 1L + */ +#define WM5100_OUT1L_VOL_LIM_MASK 0x00FF /* OUT1L_VOL_LIM - [7:0] */ +#define WM5100_OUT1L_VOL_LIM_SHIFT 0 /* OUT1L_VOL_LIM - [7:0] */ +#define WM5100_OUT1L_VOL_LIM_WIDTH 8 /* OUT1L_VOL_LIM - [7:0] */ + +/* + * R1043 (0x413) - DAC Volume Limit 1R + */ +#define WM5100_OUT1R_VOL_LIM_MASK 0x00FF /* OUT1R_VOL_LIM - [7:0] */ +#define WM5100_OUT1R_VOL_LIM_SHIFT 0 /* OUT1R_VOL_LIM - [7:0] */ +#define WM5100_OUT1R_VOL_LIM_WIDTH 8 /* OUT1R_VOL_LIM - [7:0] */ + +/* + * R1044 (0x414) - Out Volume 2L + */ +#define WM5100_OUT2_OSR 0x2000 /* OUT2_OSR */ +#define WM5100_OUT2_OSR_MASK 0x2000 /* OUT2_OSR */ +#define WM5100_OUT2_OSR_SHIFT 13 /* OUT2_OSR */ +#define WM5100_OUT2_OSR_WIDTH 1 /* OUT2_OSR */ +#define WM5100_OUT2_MONO 0x1000 /* OUT2_MONO */ +#define WM5100_OUT2_MONO_MASK 0x1000 /* OUT2_MONO */ +#define WM5100_OUT2_MONO_SHIFT 12 /* OUT2_MONO */ +#define WM5100_OUT2_MONO_WIDTH 1 /* OUT2_MONO */ +#define WM5100_OUT2L_ANC_SRC 0x0800 /* OUT2L_ANC_SRC */ +#define WM5100_OUT2L_ANC_SRC_MASK 0x0800 /* OUT2L_ANC_SRC */ +#define WM5100_OUT2L_ANC_SRC_SHIFT 11 /* OUT2L_ANC_SRC */ +#define WM5100_OUT2L_ANC_SRC_WIDTH 1 /* OUT2L_ANC_SRC */ +#define WM5100_OUT2L_PGA_VOL_MASK 0x00FE /* OUT2L_PGA_VOL - [7:1] */ +#define WM5100_OUT2L_PGA_VOL_SHIFT 1 /* OUT2L_PGA_VOL - [7:1] */ +#define WM5100_OUT2L_PGA_VOL_WIDTH 7 /* OUT2L_PGA_VOL - [7:1] */ + +/* + * R1045 (0x415) - Out Volume 2R + */ +#define WM5100_OUT2R_ANC_SRC 0x0800 /* OUT2R_ANC_SRC */ +#define WM5100_OUT2R_ANC_SRC_MASK 0x0800 /* OUT2R_ANC_SRC */ +#define WM5100_OUT2R_ANC_SRC_SHIFT 11 /* OUT2R_ANC_SRC */ +#define WM5100_OUT2R_ANC_SRC_WIDTH 1 /* OUT2R_ANC_SRC */ +#define WM5100_OUT2R_PGA_VOL_MASK 0x00FE /* OUT2R_PGA_VOL - [7:1] */ +#define WM5100_OUT2R_PGA_VOL_SHIFT 1 /* OUT2R_PGA_VOL - [7:1] */ +#define WM5100_OUT2R_PGA_VOL_WIDTH 7 /* OUT2R_PGA_VOL - [7:1] */ + +/* + * R1046 (0x416) - DAC Volume Limit 2L + */ +#define WM5100_OUT2L_VOL_LIM_MASK 0x00FF /* OUT2L_VOL_LIM - [7:0] */ +#define WM5100_OUT2L_VOL_LIM_SHIFT 0 /* OUT2L_VOL_LIM - [7:0] */ +#define WM5100_OUT2L_VOL_LIM_WIDTH 8 /* OUT2L_VOL_LIM - [7:0] */ + +/* + * R1047 (0x417) - DAC Volume Limit 2R + */ +#define WM5100_OUT2R_VOL_LIM_MASK 0x00FF /* OUT2R_VOL_LIM - [7:0] */ +#define WM5100_OUT2R_VOL_LIM_SHIFT 0 /* OUT2R_VOL_LIM - [7:0] */ +#define WM5100_OUT2R_VOL_LIM_WIDTH 8 /* OUT2R_VOL_LIM - [7:0] */ + +/* + * R1048 (0x418) - Out Volume 3L + */ +#define WM5100_OUT3_OSR 0x2000 /* OUT3_OSR */ +#define WM5100_OUT3_OSR_MASK 0x2000 /* OUT3_OSR */ +#define WM5100_OUT3_OSR_SHIFT 13 /* OUT3_OSR */ +#define WM5100_OUT3_OSR_WIDTH 1 /* OUT3_OSR */ +#define WM5100_OUT3_MONO 0x1000 /* OUT3_MONO */ +#define WM5100_OUT3_MONO_MASK 0x1000 /* OUT3_MONO */ +#define WM5100_OUT3_MONO_SHIFT 12 /* OUT3_MONO */ +#define WM5100_OUT3_MONO_WIDTH 1 /* OUT3_MONO */ +#define WM5100_OUT3L_ANC_SRC 0x0800 /* OUT3L_ANC_SRC */ +#define WM5100_OUT3L_ANC_SRC_MASK 0x0800 /* OUT3L_ANC_SRC */ +#define WM5100_OUT3L_ANC_SRC_SHIFT 11 /* OUT3L_ANC_SRC */ +#define WM5100_OUT3L_ANC_SRC_WIDTH 1 /* OUT3L_ANC_SRC */ +#define WM5100_OUT3L_PGA_VOL_MASK 0x00FE /* OUT3L_PGA_VOL - [7:1] */ +#define WM5100_OUT3L_PGA_VOL_SHIFT 1 /* OUT3L_PGA_VOL - [7:1] */ +#define WM5100_OUT3L_PGA_VOL_WIDTH 7 /* OUT3L_PGA_VOL - [7:1] */ + +/* + * R1049 (0x419) - Out Volume 3R + */ +#define WM5100_OUT3R_ANC_SRC 0x0800 /* OUT3R_ANC_SRC */ +#define WM5100_OUT3R_ANC_SRC_MASK 0x0800 /* OUT3R_ANC_SRC */ +#define WM5100_OUT3R_ANC_SRC_SHIFT 11 /* OUT3R_ANC_SRC */ +#define WM5100_OUT3R_ANC_SRC_WIDTH 1 /* OUT3R_ANC_SRC */ +#define WM5100_OUT3R_PGA_VOL_MASK 0x00FE /* OUT3R_PGA_VOL - [7:1] */ +#define WM5100_OUT3R_PGA_VOL_SHIFT 1 /* OUT3R_PGA_VOL - [7:1] */ +#define WM5100_OUT3R_PGA_VOL_WIDTH 7 /* OUT3R_PGA_VOL - [7:1] */ + +/* + * R1050 (0x41A) - DAC Volume Limit 3L + */ +#define WM5100_OUT3L_VOL_LIM_MASK 0x00FF /* OUT3L_VOL_LIM - [7:0] */ +#define WM5100_OUT3L_VOL_LIM_SHIFT 0 /* OUT3L_VOL_LIM - [7:0] */ +#define WM5100_OUT3L_VOL_LIM_WIDTH 8 /* OUT3L_VOL_LIM - [7:0] */ + +/* + * R1051 (0x41B) - DAC Volume Limit 3R + */ +#define WM5100_OUT3R_VOL_LIM_MASK 0x00FF /* OUT3R_VOL_LIM - [7:0] */ +#define WM5100_OUT3R_VOL_LIM_SHIFT 0 /* OUT3R_VOL_LIM - [7:0] */ +#define WM5100_OUT3R_VOL_LIM_WIDTH 8 /* OUT3R_VOL_LIM - [7:0] */ + +/* + * R1052 (0x41C) - Out Volume 4L + */ +#define WM5100_OUT4_OSR 0x2000 /* OUT4_OSR */ +#define WM5100_OUT4_OSR_MASK 0x2000 /* OUT4_OSR */ +#define WM5100_OUT4_OSR_SHIFT 13 /* OUT4_OSR */ +#define WM5100_OUT4_OSR_WIDTH 1 /* OUT4_OSR */ +#define WM5100_OUT4L_ANC_SRC 0x0800 /* OUT4L_ANC_SRC */ +#define WM5100_OUT4L_ANC_SRC_MASK 0x0800 /* OUT4L_ANC_SRC */ +#define WM5100_OUT4L_ANC_SRC_SHIFT 11 /* OUT4L_ANC_SRC */ +#define WM5100_OUT4L_ANC_SRC_WIDTH 1 /* OUT4L_ANC_SRC */ +#define WM5100_OUT4L_VOL_LIM_MASK 0x00FF /* OUT4L_VOL_LIM - [7:0] */ +#define WM5100_OUT4L_VOL_LIM_SHIFT 0 /* OUT4L_VOL_LIM - [7:0] */ +#define WM5100_OUT4L_VOL_LIM_WIDTH 8 /* OUT4L_VOL_LIM - [7:0] */ + +/* + * R1053 (0x41D) - Out Volume 4R + */ +#define WM5100_OUT4R_ANC_SRC 0x0800 /* OUT4R_ANC_SRC */ +#define WM5100_OUT4R_ANC_SRC_MASK 0x0800 /* OUT4R_ANC_SRC */ +#define WM5100_OUT4R_ANC_SRC_SHIFT 11 /* OUT4R_ANC_SRC */ +#define WM5100_OUT4R_ANC_SRC_WIDTH 1 /* OUT4R_ANC_SRC */ +#define WM5100_OUT4R_VOL_LIM_MASK 0x00FF /* OUT4R_VOL_LIM - [7:0] */ +#define WM5100_OUT4R_VOL_LIM_SHIFT 0 /* OUT4R_VOL_LIM - [7:0] */ +#define WM5100_OUT4R_VOL_LIM_WIDTH 8 /* OUT4R_VOL_LIM - [7:0] */ + +/* + * R1054 (0x41E) - DAC Volume Limit 5L + */ +#define WM5100_OUT5_OSR 0x2000 /* OUT5_OSR */ +#define WM5100_OUT5_OSR_MASK 0x2000 /* OUT5_OSR */ +#define WM5100_OUT5_OSR_SHIFT 13 /* OUT5_OSR */ +#define WM5100_OUT5_OSR_WIDTH 1 /* OUT5_OSR */ +#define WM5100_OUT5L_ANC_SRC 0x0800 /* OUT5L_ANC_SRC */ +#define WM5100_OUT5L_ANC_SRC_MASK 0x0800 /* OUT5L_ANC_SRC */ +#define WM5100_OUT5L_ANC_SRC_SHIFT 11 /* OUT5L_ANC_SRC */ +#define WM5100_OUT5L_ANC_SRC_WIDTH 1 /* OUT5L_ANC_SRC */ +#define WM5100_OUT5L_VOL_LIM_MASK 0x00FF /* OUT5L_VOL_LIM - [7:0] */ +#define WM5100_OUT5L_VOL_LIM_SHIFT 0 /* OUT5L_VOL_LIM - [7:0] */ +#define WM5100_OUT5L_VOL_LIM_WIDTH 8 /* OUT5L_VOL_LIM - [7:0] */ + +/* + * R1055 (0x41F) - DAC Volume Limit 5R + */ +#define WM5100_OUT5R_ANC_SRC 0x0800 /* OUT5R_ANC_SRC */ +#define WM5100_OUT5R_ANC_SRC_MASK 0x0800 /* OUT5R_ANC_SRC */ +#define WM5100_OUT5R_ANC_SRC_SHIFT 11 /* OUT5R_ANC_SRC */ +#define WM5100_OUT5R_ANC_SRC_WIDTH 1 /* OUT5R_ANC_SRC */ +#define WM5100_OUT5R_VOL_LIM_MASK 0x00FF /* OUT5R_VOL_LIM - [7:0] */ +#define WM5100_OUT5R_VOL_LIM_SHIFT 0 /* OUT5R_VOL_LIM - [7:0] */ +#define WM5100_OUT5R_VOL_LIM_WIDTH 8 /* OUT5R_VOL_LIM - [7:0] */ + +/* + * R1056 (0x420) - DAC Volume Limit 6L + */ +#define WM5100_OUT6_OSR 0x2000 /* OUT6_OSR */ +#define WM5100_OUT6_OSR_MASK 0x2000 /* OUT6_OSR */ +#define WM5100_OUT6_OSR_SHIFT 13 /* OUT6_OSR */ +#define WM5100_OUT6_OSR_WIDTH 1 /* OUT6_OSR */ +#define WM5100_OUT6L_ANC_SRC 0x0800 /* OUT6L_ANC_SRC */ +#define WM5100_OUT6L_ANC_SRC_MASK 0x0800 /* OUT6L_ANC_SRC */ +#define WM5100_OUT6L_ANC_SRC_SHIFT 11 /* OUT6L_ANC_SRC */ +#define WM5100_OUT6L_ANC_SRC_WIDTH 1 /* OUT6L_ANC_SRC */ +#define WM5100_OUT6L_VOL_LIM_MASK 0x00FF /* OUT6L_VOL_LIM - [7:0] */ +#define WM5100_OUT6L_VOL_LIM_SHIFT 0 /* OUT6L_VOL_LIM - [7:0] */ +#define WM5100_OUT6L_VOL_LIM_WIDTH 8 /* OUT6L_VOL_LIM - [7:0] */ + +/* + * R1057 (0x421) - DAC Volume Limit 6R + */ +#define WM5100_OUT6R_ANC_SRC 0x0800 /* OUT6R_ANC_SRC */ +#define WM5100_OUT6R_ANC_SRC_MASK 0x0800 /* OUT6R_ANC_SRC */ +#define WM5100_OUT6R_ANC_SRC_SHIFT 11 /* OUT6R_ANC_SRC */ +#define WM5100_OUT6R_ANC_SRC_WIDTH 1 /* OUT6R_ANC_SRC */ +#define WM5100_OUT6R_VOL_LIM_MASK 0x00FF /* OUT6R_VOL_LIM - [7:0] */ +#define WM5100_OUT6R_VOL_LIM_SHIFT 0 /* OUT6R_VOL_LIM - [7:0] */ +#define WM5100_OUT6R_VOL_LIM_WIDTH 8 /* OUT6R_VOL_LIM - [7:0] */ + +/* + * R1088 (0x440) - DAC AEC Control 1 + */ +#define WM5100_AEC_LOOPBACK_SRC_MASK 0x003C /* AEC_LOOPBACK_SRC - [5:2] */ +#define WM5100_AEC_LOOPBACK_SRC_SHIFT 2 /* AEC_LOOPBACK_SRC - [5:2] */ +#define WM5100_AEC_LOOPBACK_SRC_WIDTH 4 /* AEC_LOOPBACK_SRC - [5:2] */ +#define WM5100_AEC_ENA_STS 0x0002 /* AEC_ENA_STS */ +#define WM5100_AEC_ENA_STS_MASK 0x0002 /* AEC_ENA_STS */ +#define WM5100_AEC_ENA_STS_SHIFT 1 /* AEC_ENA_STS */ +#define WM5100_AEC_ENA_STS_WIDTH 1 /* AEC_ENA_STS */ +#define WM5100_AEC_LOOPBACK_ENA 0x0001 /* AEC_LOOPBACK_ENA */ +#define WM5100_AEC_LOOPBACK_ENA_MASK 0x0001 /* AEC_LOOPBACK_ENA */ +#define WM5100_AEC_LOOPBACK_ENA_SHIFT 0 /* AEC_LOOPBACK_ENA */ +#define WM5100_AEC_LOOPBACK_ENA_WIDTH 1 /* AEC_LOOPBACK_ENA */ + +/* + * R1089 (0x441) - Output Volume Ramp + */ +#define WM5100_OUT_VD_RAMP_MASK 0x0070 /* OUT_VD_RAMP - [6:4] */ +#define WM5100_OUT_VD_RAMP_SHIFT 4 /* OUT_VD_RAMP - [6:4] */ +#define WM5100_OUT_VD_RAMP_WIDTH 3 /* OUT_VD_RAMP - [6:4] */ +#define WM5100_OUT_VI_RAMP_MASK 0x0007 /* OUT_VI_RAMP - [2:0] */ +#define WM5100_OUT_VI_RAMP_SHIFT 0 /* OUT_VI_RAMP - [2:0] */ +#define WM5100_OUT_VI_RAMP_WIDTH 3 /* OUT_VI_RAMP - [2:0] */ + +/* + * R1152 (0x480) - DAC Digital Volume 1L + */ +#define WM5100_OUT_VU 0x0200 /* OUT_VU */ +#define WM5100_OUT_VU_MASK 0x0200 /* OUT_VU */ +#define WM5100_OUT_VU_SHIFT 9 /* OUT_VU */ +#define WM5100_OUT_VU_WIDTH 1 /* OUT_VU */ +#define WM5100_OUT1L_MUTE 0x0100 /* OUT1L_MUTE */ +#define WM5100_OUT1L_MUTE_MASK 0x0100 /* OUT1L_MUTE */ +#define WM5100_OUT1L_MUTE_SHIFT 8 /* OUT1L_MUTE */ +#define WM5100_OUT1L_MUTE_WIDTH 1 /* OUT1L_MUTE */ +#define WM5100_OUT1L_VOL_MASK 0x00FF /* OUT1L_VOL - [7:0] */ +#define WM5100_OUT1L_VOL_SHIFT 0 /* OUT1L_VOL - [7:0] */ +#define WM5100_OUT1L_VOL_WIDTH 8 /* OUT1L_VOL - [7:0] */ + +/* + * R1153 (0x481) - DAC Digital Volume 1R + */ +#define WM5100_OUT_VU 0x0200 /* OUT_VU */ +#define WM5100_OUT_VU_MASK 0x0200 /* OUT_VU */ +#define WM5100_OUT_VU_SHIFT 9 /* OUT_VU */ +#define WM5100_OUT_VU_WIDTH 1 /* OUT_VU */ +#define WM5100_OUT1R_MUTE 0x0100 /* OUT1R_MUTE */ +#define WM5100_OUT1R_MUTE_MASK 0x0100 /* OUT1R_MUTE */ +#define WM5100_OUT1R_MUTE_SHIFT 8 /* OUT1R_MUTE */ +#define WM5100_OUT1R_MUTE_WIDTH 1 /* OUT1R_MUTE */ +#define WM5100_OUT1R_VOL_MASK 0x00FF /* OUT1R_VOL - [7:0] */ +#define WM5100_OUT1R_VOL_SHIFT 0 /* OUT1R_VOL - [7:0] */ +#define WM5100_OUT1R_VOL_WIDTH 8 /* OUT1R_VOL - [7:0] */ + +/* + * R1154 (0x482) - DAC Digital Volume 2L + */ +#define WM5100_OUT_VU 0x0200 /* OUT_VU */ +#define WM5100_OUT_VU_MASK 0x0200 /* OUT_VU */ +#define WM5100_OUT_VU_SHIFT 9 /* OUT_VU */ +#define WM5100_OUT_VU_WIDTH 1 /* OUT_VU */ +#define WM5100_OUT2L_MUTE 0x0100 /* OUT2L_MUTE */ +#define WM5100_OUT2L_MUTE_MASK 0x0100 /* OUT2L_MUTE */ +#define WM5100_OUT2L_MUTE_SHIFT 8 /* OUT2L_MUTE */ +#define WM5100_OUT2L_MUTE_WIDTH 1 /* OUT2L_MUTE */ +#define WM5100_OUT2L_VOL_MASK 0x00FF /* OUT2L_VOL - [7:0] */ +#define WM5100_OUT2L_VOL_SHIFT 0 /* OUT2L_VOL - [7:0] */ +#define WM5100_OUT2L_VOL_WIDTH 8 /* OUT2L_VOL - [7:0] */ + +/* + * R1155 (0x483) - DAC Digital Volume 2R + */ +#define WM5100_OUT_VU 0x0200 /* OUT_VU */ +#define WM5100_OUT_VU_MASK 0x0200 /* OUT_VU */ +#define WM5100_OUT_VU_SHIFT 9 /* OUT_VU */ +#define WM5100_OUT_VU_WIDTH 1 /* OUT_VU */ +#define WM5100_OUT2R_MUTE 0x0100 /* OUT2R_MUTE */ +#define WM5100_OUT2R_MUTE_MASK 0x0100 /* OUT2R_MUTE */ +#define WM5100_OUT2R_MUTE_SHIFT 8 /* OUT2R_MUTE */ +#define WM5100_OUT2R_MUTE_WIDTH 1 /* OUT2R_MUTE */ +#define WM5100_OUT2R_VOL_MASK 0x00FF /* OUT2R_VOL - [7:0] */ +#define WM5100_OUT2R_VOL_SHIFT 0 /* OUT2R_VOL - [7:0] */ +#define WM5100_OUT2R_VOL_WIDTH 8 /* OUT2R_VOL - [7:0] */ + +/* + * R1156 (0x484) - DAC Digital Volume 3L + */ +#define WM5100_OUT_VU 0x0200 /* OUT_VU */ +#define WM5100_OUT_VU_MASK 0x0200 /* OUT_VU */ +#define WM5100_OUT_VU_SHIFT 9 /* OUT_VU */ +#define WM5100_OUT_VU_WIDTH 1 /* OUT_VU */ +#define WM5100_OUT3L_MUTE 0x0100 /* OUT3L_MUTE */ +#define WM5100_OUT3L_MUTE_MASK 0x0100 /* OUT3L_MUTE */ +#define WM5100_OUT3L_MUTE_SHIFT 8 /* OUT3L_MUTE */ +#define WM5100_OUT3L_MUTE_WIDTH 1 /* OUT3L_MUTE */ +#define WM5100_OUT3L_VOL_MASK 0x00FF /* OUT3L_VOL - [7:0] */ +#define WM5100_OUT3L_VOL_SHIFT 0 /* OUT3L_VOL - [7:0] */ +#define WM5100_OUT3L_VOL_WIDTH 8 /* OUT3L_VOL - [7:0] */ + +/* + * R1157 (0x485) - DAC Digital Volume 3R + */ +#define WM5100_OUT_VU 0x0200 /* OUT_VU */ +#define WM5100_OUT_VU_MASK 0x0200 /* OUT_VU */ +#define WM5100_OUT_VU_SHIFT 9 /* OUT_VU */ +#define WM5100_OUT_VU_WIDTH 1 /* OUT_VU */ +#define WM5100_OUT3R_MUTE 0x0100 /* OUT3R_MUTE */ +#define WM5100_OUT3R_MUTE_MASK 0x0100 /* OUT3R_MUTE */ +#define WM5100_OUT3R_MUTE_SHIFT 8 /* OUT3R_MUTE */ +#define WM5100_OUT3R_MUTE_WIDTH 1 /* OUT3R_MUTE */ +#define WM5100_OUT3R_VOL_MASK 0x00FF /* OUT3R_VOL - [7:0] */ +#define WM5100_OUT3R_VOL_SHIFT 0 /* OUT3R_VOL - [7:0] */ +#define WM5100_OUT3R_VOL_WIDTH 8 /* OUT3R_VOL - [7:0] */ + +/* + * R1158 (0x486) - DAC Digital Volume 4L + */ +#define WM5100_OUT_VU 0x0200 /* OUT_VU */ +#define WM5100_OUT_VU_MASK 0x0200 /* OUT_VU */ +#define WM5100_OUT_VU_SHIFT 9 /* OUT_VU */ +#define WM5100_OUT_VU_WIDTH 1 /* OUT_VU */ +#define WM5100_OUT4L_MUTE 0x0100 /* OUT4L_MUTE */ +#define WM5100_OUT4L_MUTE_MASK 0x0100 /* OUT4L_MUTE */ +#define WM5100_OUT4L_MUTE_SHIFT 8 /* OUT4L_MUTE */ +#define WM5100_OUT4L_MUTE_WIDTH 1 /* OUT4L_MUTE */ +#define WM5100_OUT4L_VOL_MASK 0x00FF /* OUT4L_VOL - [7:0] */ +#define WM5100_OUT4L_VOL_SHIFT 0 /* OUT4L_VOL - [7:0] */ +#define WM5100_OUT4L_VOL_WIDTH 8 /* OUT4L_VOL - [7:0] */ + +/* + * R1159 (0x487) - DAC Digital Volume 4R + */ +#define WM5100_OUT_VU 0x0200 /* OUT_VU */ +#define WM5100_OUT_VU_MASK 0x0200 /* OUT_VU */ +#define WM5100_OUT_VU_SHIFT 9 /* OUT_VU */ +#define WM5100_OUT_VU_WIDTH 1 /* OUT_VU */ +#define WM5100_OUT4R_MUTE 0x0100 /* OUT4R_MUTE */ +#define WM5100_OUT4R_MUTE_MASK 0x0100 /* OUT4R_MUTE */ +#define WM5100_OUT4R_MUTE_SHIFT 8 /* OUT4R_MUTE */ +#define WM5100_OUT4R_MUTE_WIDTH 1 /* OUT4R_MUTE */ +#define WM5100_OUT4R_VOL_MASK 0x00FF /* OUT4R_VOL - [7:0] */ +#define WM5100_OUT4R_VOL_SHIFT 0 /* OUT4R_VOL - [7:0] */ +#define WM5100_OUT4R_VOL_WIDTH 8 /* OUT4R_VOL - [7:0] */ + +/* + * R1160 (0x488) - DAC Digital Volume 5L + */ +#define WM5100_OUT_VU 0x0200 /* OUT_VU */ +#define WM5100_OUT_VU_MASK 0x0200 /* OUT_VU */ +#define WM5100_OUT_VU_SHIFT 9 /* OUT_VU */ +#define WM5100_OUT_VU_WIDTH 1 /* OUT_VU */ +#define WM5100_OUT5L_MUTE 0x0100 /* OUT5L_MUTE */ +#define WM5100_OUT5L_MUTE_MASK 0x0100 /* OUT5L_MUTE */ +#define WM5100_OUT5L_MUTE_SHIFT 8 /* OUT5L_MUTE */ +#define WM5100_OUT5L_MUTE_WIDTH 1 /* OUT5L_MUTE */ +#define WM5100_OUT5L_VOL_MASK 0x00FF /* OUT5L_VOL - [7:0] */ +#define WM5100_OUT5L_VOL_SHIFT 0 /* OUT5L_VOL - [7:0] */ +#define WM5100_OUT5L_VOL_WIDTH 8 /* OUT5L_VOL - [7:0] */ + +/* + * R1161 (0x489) - DAC Digital Volume 5R + */ +#define WM5100_OUT_VU 0x0200 /* OUT_VU */ +#define WM5100_OUT_VU_MASK 0x0200 /* OUT_VU */ +#define WM5100_OUT_VU_SHIFT 9 /* OUT_VU */ +#define WM5100_OUT_VU_WIDTH 1 /* OUT_VU */ +#define WM5100_OUT5R_MUTE 0x0100 /* OUT5R_MUTE */ +#define WM5100_OUT5R_MUTE_MASK 0x0100 /* OUT5R_MUTE */ +#define WM5100_OUT5R_MUTE_SHIFT 8 /* OUT5R_MUTE */ +#define WM5100_OUT5R_MUTE_WIDTH 1 /* OUT5R_MUTE */ +#define WM5100_OUT5R_VOL_MASK 0x00FF /* OUT5R_VOL - [7:0] */ +#define WM5100_OUT5R_VOL_SHIFT 0 /* OUT5R_VOL - [7:0] */ +#define WM5100_OUT5R_VOL_WIDTH 8 /* OUT5R_VOL - [7:0] */ + +/* + * R1162 (0x48A) - DAC Digital Volume 6L + */ +#define WM5100_OUT_VU 0x0200 /* OUT_VU */ +#define WM5100_OUT_VU_MASK 0x0200 /* OUT_VU */ +#define WM5100_OUT_VU_SHIFT 9 /* OUT_VU */ +#define WM5100_OUT_VU_WIDTH 1 /* OUT_VU */ +#define WM5100_OUT6L_MUTE 0x0100 /* OUT6L_MUTE */ +#define WM5100_OUT6L_MUTE_MASK 0x0100 /* OUT6L_MUTE */ +#define WM5100_OUT6L_MUTE_SHIFT 8 /* OUT6L_MUTE */ +#define WM5100_OUT6L_MUTE_WIDTH 1 /* OUT6L_MUTE */ +#define WM5100_OUT6L_VOL_MASK 0x00FF /* OUT6L_VOL - [7:0] */ +#define WM5100_OUT6L_VOL_SHIFT 0 /* OUT6L_VOL - [7:0] */ +#define WM5100_OUT6L_VOL_WIDTH 8 /* OUT6L_VOL - [7:0] */ + +/* + * R1163 (0x48B) - DAC Digital Volume 6R + */ +#define WM5100_OUT_VU 0x0200 /* OUT_VU */ +#define WM5100_OUT_VU_MASK 0x0200 /* OUT_VU */ +#define WM5100_OUT_VU_SHIFT 9 /* OUT_VU */ +#define WM5100_OUT_VU_WIDTH 1 /* OUT_VU */ +#define WM5100_OUT6R_MUTE 0x0100 /* OUT6R_MUTE */ +#define WM5100_OUT6R_MUTE_MASK 0x0100 /* OUT6R_MUTE */ +#define WM5100_OUT6R_MUTE_SHIFT 8 /* OUT6R_MUTE */ +#define WM5100_OUT6R_MUTE_WIDTH 1 /* OUT6R_MUTE */ +#define WM5100_OUT6R_VOL_MASK 0x00FF /* OUT6R_VOL - [7:0] */ +#define WM5100_OUT6R_VOL_SHIFT 0 /* OUT6R_VOL - [7:0] */ +#define WM5100_OUT6R_VOL_WIDTH 8 /* OUT6R_VOL - [7:0] */ + +/* + * R1216 (0x4C0) - PDM SPK1 CTRL 1 + */ +#define WM5100_SPK1R_MUTE 0x2000 /* SPK1R_MUTE */ +#define WM5100_SPK1R_MUTE_MASK 0x2000 /* SPK1R_MUTE */ +#define WM5100_SPK1R_MUTE_SHIFT 13 /* SPK1R_MUTE */ +#define WM5100_SPK1R_MUTE_WIDTH 1 /* SPK1R_MUTE */ +#define WM5100_SPK1L_MUTE 0x1000 /* SPK1L_MUTE */ +#define WM5100_SPK1L_MUTE_MASK 0x1000 /* SPK1L_MUTE */ +#define WM5100_SPK1L_MUTE_SHIFT 12 /* SPK1L_MUTE */ +#define WM5100_SPK1L_MUTE_WIDTH 1 /* SPK1L_MUTE */ +#define WM5100_SPK1_MUTE_ENDIAN 0x0100 /* SPK1_MUTE_ENDIAN */ +#define WM5100_SPK1_MUTE_ENDIAN_MASK 0x0100 /* SPK1_MUTE_ENDIAN */ +#define WM5100_SPK1_MUTE_ENDIAN_SHIFT 8 /* SPK1_MUTE_ENDIAN */ +#define WM5100_SPK1_MUTE_ENDIAN_WIDTH 1 /* SPK1_MUTE_ENDIAN */ +#define WM5100_SPK1_MUTE_SEQ1_MASK 0x00FF /* SPK1_MUTE_SEQ1 - [7:0] */ +#define WM5100_SPK1_MUTE_SEQ1_SHIFT 0 /* SPK1_MUTE_SEQ1 - [7:0] */ +#define WM5100_SPK1_MUTE_SEQ1_WIDTH 8 /* SPK1_MUTE_SEQ1 - [7:0] */ + +/* + * R1217 (0x4C1) - PDM SPK1 CTRL 2 + */ +#define WM5100_SPK1_FMT 0x0001 /* SPK1_FMT */ +#define WM5100_SPK1_FMT_MASK 0x0001 /* SPK1_FMT */ +#define WM5100_SPK1_FMT_SHIFT 0 /* SPK1_FMT */ +#define WM5100_SPK1_FMT_WIDTH 1 /* SPK1_FMT */ + +/* + * R1218 (0x4C2) - PDM SPK2 CTRL 1 + */ +#define WM5100_SPK2R_MUTE 0x2000 /* SPK2R_MUTE */ +#define WM5100_SPK2R_MUTE_MASK 0x2000 /* SPK2R_MUTE */ +#define WM5100_SPK2R_MUTE_SHIFT 13 /* SPK2R_MUTE */ +#define WM5100_SPK2R_MUTE_WIDTH 1 /* SPK2R_MUTE */ +#define WM5100_SPK2L_MUTE 0x1000 /* SPK2L_MUTE */ +#define WM5100_SPK2L_MUTE_MASK 0x1000 /* SPK2L_MUTE */ +#define WM5100_SPK2L_MUTE_SHIFT 12 /* SPK2L_MUTE */ +#define WM5100_SPK2L_MUTE_WIDTH 1 /* SPK2L_MUTE */ +#define WM5100_SPK2_MUTE_ENDIAN 0x0100 /* SPK2_MUTE_ENDIAN */ +#define WM5100_SPK2_MUTE_ENDIAN_MASK 0x0100 /* SPK2_MUTE_ENDIAN */ +#define WM5100_SPK2_MUTE_ENDIAN_SHIFT 8 /* SPK2_MUTE_ENDIAN */ +#define WM5100_SPK2_MUTE_ENDIAN_WIDTH 1 /* SPK2_MUTE_ENDIAN */ +#define WM5100_SPK2_MUTE_SEQ1_MASK 0x00FF /* SPK2_MUTE_SEQ1 - [7:0] */ +#define WM5100_SPK2_MUTE_SEQ1_SHIFT 0 /* SPK2_MUTE_SEQ1 - [7:0] */ +#define WM5100_SPK2_MUTE_SEQ1_WIDTH 8 /* SPK2_MUTE_SEQ1 - [7:0] */ + +/* + * R1219 (0x4C3) - PDM SPK2 CTRL 2 + */ +#define WM5100_SPK2_FMT 0x0001 /* SPK2_FMT */ +#define WM5100_SPK2_FMT_MASK 0x0001 /* SPK2_FMT */ +#define WM5100_SPK2_FMT_SHIFT 0 /* SPK2_FMT */ +#define WM5100_SPK2_FMT_WIDTH 1 /* SPK2_FMT */ + +/* + * R1280 (0x500) - Audio IF 1_1 + */ +#define WM5100_AIF1_BCLK_INV 0x0080 /* AIF1_BCLK_INV */ +#define WM5100_AIF1_BCLK_INV_MASK 0x0080 /* AIF1_BCLK_INV */ +#define WM5100_AIF1_BCLK_INV_SHIFT 7 /* AIF1_BCLK_INV */ +#define WM5100_AIF1_BCLK_INV_WIDTH 1 /* AIF1_BCLK_INV */ +#define WM5100_AIF1_BCLK_FRC 0x0040 /* AIF1_BCLK_FRC */ +#define WM5100_AIF1_BCLK_FRC_MASK 0x0040 /* AIF1_BCLK_FRC */ +#define WM5100_AIF1_BCLK_FRC_SHIFT 6 /* AIF1_BCLK_FRC */ +#define WM5100_AIF1_BCLK_FRC_WIDTH 1 /* AIF1_BCLK_FRC */ +#define WM5100_AIF1_BCLK_MSTR 0x0020 /* AIF1_BCLK_MSTR */ +#define WM5100_AIF1_BCLK_MSTR_MASK 0x0020 /* AIF1_BCLK_MSTR */ +#define WM5100_AIF1_BCLK_MSTR_SHIFT 5 /* AIF1_BCLK_MSTR */ +#define WM5100_AIF1_BCLK_MSTR_WIDTH 1 /* AIF1_BCLK_MSTR */ +#define WM5100_AIF1_BCLK_FREQ_MASK 0x001F /* AIF1_BCLK_FREQ - [4:0] */ +#define WM5100_AIF1_BCLK_FREQ_SHIFT 0 /* AIF1_BCLK_FREQ - [4:0] */ +#define WM5100_AIF1_BCLK_FREQ_WIDTH 5 /* AIF1_BCLK_FREQ - [4:0] */ + +/* + * R1281 (0x501) - Audio IF 1_2 + */ +#define WM5100_AIF1TX_DAT_TRI 0x0020 /* AIF1TX_DAT_TRI */ +#define WM5100_AIF1TX_DAT_TRI_MASK 0x0020 /* AIF1TX_DAT_TRI */ +#define WM5100_AIF1TX_DAT_TRI_SHIFT 5 /* AIF1TX_DAT_TRI */ +#define WM5100_AIF1TX_DAT_TRI_WIDTH 1 /* AIF1TX_DAT_TRI */ +#define WM5100_AIF1TX_LRCLK_SRC 0x0008 /* AIF1TX_LRCLK_SRC */ +#define WM5100_AIF1TX_LRCLK_SRC_MASK 0x0008 /* AIF1TX_LRCLK_SRC */ +#define WM5100_AIF1TX_LRCLK_SRC_SHIFT 3 /* AIF1TX_LRCLK_SRC */ +#define WM5100_AIF1TX_LRCLK_SRC_WIDTH 1 /* AIF1TX_LRCLK_SRC */ +#define WM5100_AIF1TX_LRCLK_INV 0x0004 /* AIF1TX_LRCLK_INV */ +#define WM5100_AIF1TX_LRCLK_INV_MASK 0x0004 /* AIF1TX_LRCLK_INV */ +#define WM5100_AIF1TX_LRCLK_INV_SHIFT 2 /* AIF1TX_LRCLK_INV */ +#define WM5100_AIF1TX_LRCLK_INV_WIDTH 1 /* AIF1TX_LRCLK_INV */ +#define WM5100_AIF1TX_LRCLK_FRC 0x0002 /* AIF1TX_LRCLK_FRC */ +#define WM5100_AIF1TX_LRCLK_FRC_MASK 0x0002 /* AIF1TX_LRCLK_FRC */ +#define WM5100_AIF1TX_LRCLK_FRC_SHIFT 1 /* AIF1TX_LRCLK_FRC */ +#define WM5100_AIF1TX_LRCLK_FRC_WIDTH 1 /* AIF1TX_LRCLK_FRC */ +#define WM5100_AIF1TX_LRCLK_MSTR 0x0001 /* AIF1TX_LRCLK_MSTR */ +#define WM5100_AIF1TX_LRCLK_MSTR_MASK 0x0001 /* AIF1TX_LRCLK_MSTR */ +#define WM5100_AIF1TX_LRCLK_MSTR_SHIFT 0 /* AIF1TX_LRCLK_MSTR */ +#define WM5100_AIF1TX_LRCLK_MSTR_WIDTH 1 /* AIF1TX_LRCLK_MSTR */ + +/* + * R1282 (0x502) - Audio IF 1_3 + */ +#define WM5100_AIF1RX_LRCLK_INV 0x0004 /* AIF1RX_LRCLK_INV */ +#define WM5100_AIF1RX_LRCLK_INV_MASK 0x0004 /* AIF1RX_LRCLK_INV */ +#define WM5100_AIF1RX_LRCLK_INV_SHIFT 2 /* AIF1RX_LRCLK_INV */ +#define WM5100_AIF1RX_LRCLK_INV_WIDTH 1 /* AIF1RX_LRCLK_INV */ +#define WM5100_AIF1RX_LRCLK_FRC 0x0002 /* AIF1RX_LRCLK_FRC */ +#define WM5100_AIF1RX_LRCLK_FRC_MASK 0x0002 /* AIF1RX_LRCLK_FRC */ +#define WM5100_AIF1RX_LRCLK_FRC_SHIFT 1 /* AIF1RX_LRCLK_FRC */ +#define WM5100_AIF1RX_LRCLK_FRC_WIDTH 1 /* AIF1RX_LRCLK_FRC */ +#define WM5100_AIF1RX_LRCLK_MSTR 0x0001 /* AIF1RX_LRCLK_MSTR */ +#define WM5100_AIF1RX_LRCLK_MSTR_MASK 0x0001 /* AIF1RX_LRCLK_MSTR */ +#define WM5100_AIF1RX_LRCLK_MSTR_SHIFT 0 /* AIF1RX_LRCLK_MSTR */ +#define WM5100_AIF1RX_LRCLK_MSTR_WIDTH 1 /* AIF1RX_LRCLK_MSTR */ + +/* + * R1283 (0x503) - Audio IF 1_4 + */ +#define WM5100_AIF1_TRI 0x0040 /* AIF1_TRI */ +#define WM5100_AIF1_TRI_MASK 0x0040 /* AIF1_TRI */ +#define WM5100_AIF1_TRI_SHIFT 6 /* AIF1_TRI */ +#define WM5100_AIF1_TRI_WIDTH 1 /* AIF1_TRI */ +#define WM5100_AIF1_RATE_MASK 0x0003 /* AIF1_RATE - [1:0] */ +#define WM5100_AIF1_RATE_SHIFT 0 /* AIF1_RATE - [1:0] */ +#define WM5100_AIF1_RATE_WIDTH 2 /* AIF1_RATE - [1:0] */ + +/* + * R1284 (0x504) - Audio IF 1_5 + */ +#define WM5100_AIF1_FMT_MASK 0x0007 /* AIF1_FMT - [2:0] */ +#define WM5100_AIF1_FMT_SHIFT 0 /* AIF1_FMT - [2:0] */ +#define WM5100_AIF1_FMT_WIDTH 3 /* AIF1_FMT - [2:0] */ + +/* + * R1285 (0x505) - Audio IF 1_6 + */ +#define WM5100_AIF1TX_BCPF_MASK 0x1FFF /* AIF1TX_BCPF - [12:0] */ +#define WM5100_AIF1TX_BCPF_SHIFT 0 /* AIF1TX_BCPF - [12:0] */ +#define WM5100_AIF1TX_BCPF_WIDTH 13 /* AIF1TX_BCPF - [12:0] */ + +/* + * R1286 (0x506) - Audio IF 1_7 + */ +#define WM5100_AIF1RX_BCPF_MASK 0x1FFF /* AIF1RX_BCPF - [12:0] */ +#define WM5100_AIF1RX_BCPF_SHIFT 0 /* AIF1RX_BCPF - [12:0] */ +#define WM5100_AIF1RX_BCPF_WIDTH 13 /* AIF1RX_BCPF - [12:0] */ + +/* + * R1287 (0x507) - Audio IF 1_8 + */ +#define WM5100_AIF1TX_WL_MASK 0x3F00 /* AIF1TX_WL - [13:8] */ +#define WM5100_AIF1TX_WL_SHIFT 8 /* AIF1TX_WL - [13:8] */ +#define WM5100_AIF1TX_WL_WIDTH 6 /* AIF1TX_WL - [13:8] */ +#define WM5100_AIF1TX_SLOT_LEN_MASK 0x00FF /* AIF1TX_SLOT_LEN - [7:0] */ +#define WM5100_AIF1TX_SLOT_LEN_SHIFT 0 /* AIF1TX_SLOT_LEN - [7:0] */ +#define WM5100_AIF1TX_SLOT_LEN_WIDTH 8 /* AIF1TX_SLOT_LEN - [7:0] */ + +/* + * R1288 (0x508) - Audio IF 1_9 + */ +#define WM5100_AIF1RX_WL_MASK 0x3F00 /* AIF1RX_WL - [13:8] */ +#define WM5100_AIF1RX_WL_SHIFT 8 /* AIF1RX_WL - [13:8] */ +#define WM5100_AIF1RX_WL_WIDTH 6 /* AIF1RX_WL - [13:8] */ +#define WM5100_AIF1RX_SLOT_LEN_MASK 0x00FF /* AIF1RX_SLOT_LEN - [7:0] */ +#define WM5100_AIF1RX_SLOT_LEN_SHIFT 0 /* AIF1RX_SLOT_LEN - [7:0] */ +#define WM5100_AIF1RX_SLOT_LEN_WIDTH 8 /* AIF1RX_SLOT_LEN - [7:0] */ + +/* + * R1289 (0x509) - Audio IF 1_10 + */ +#define WM5100_AIF1TX1_SLOT_MASK 0x003F /* AIF1TX1_SLOT - [5:0] */ +#define WM5100_AIF1TX1_SLOT_SHIFT 0 /* AIF1TX1_SLOT - [5:0] */ +#define WM5100_AIF1TX1_SLOT_WIDTH 6 /* AIF1TX1_SLOT - [5:0] */ + +/* + * R1290 (0x50A) - Audio IF 1_11 + */ +#define WM5100_AIF1TX2_SLOT_MASK 0x003F /* AIF1TX2_SLOT - [5:0] */ +#define WM5100_AIF1TX2_SLOT_SHIFT 0 /* AIF1TX2_SLOT - [5:0] */ +#define WM5100_AIF1TX2_SLOT_WIDTH 6 /* AIF1TX2_SLOT - [5:0] */ + +/* + * R1291 (0x50B) - Audio IF 1_12 + */ +#define WM5100_AIF1TX3_SLOT_MASK 0x003F /* AIF1TX3_SLOT - [5:0] */ +#define WM5100_AIF1TX3_SLOT_SHIFT 0 /* AIF1TX3_SLOT - [5:0] */ +#define WM5100_AIF1TX3_SLOT_WIDTH 6 /* AIF1TX3_SLOT - [5:0] */ + +/* + * R1292 (0x50C) - Audio IF 1_13 + */ +#define WM5100_AIF1TX4_SLOT_MASK 0x003F /* AIF1TX4_SLOT - [5:0] */ +#define WM5100_AIF1TX4_SLOT_SHIFT 0 /* AIF1TX4_SLOT - [5:0] */ +#define WM5100_AIF1TX4_SLOT_WIDTH 6 /* AIF1TX4_SLOT - [5:0] */ + +/* + * R1293 (0x50D) - Audio IF 1_14 + */ +#define WM5100_AIF1TX5_SLOT_MASK 0x003F /* AIF1TX5_SLOT - [5:0] */ +#define WM5100_AIF1TX5_SLOT_SHIFT 0 /* AIF1TX5_SLOT - [5:0] */ +#define WM5100_AIF1TX5_SLOT_WIDTH 6 /* AIF1TX5_SLOT - [5:0] */ + +/* + * R1294 (0x50E) - Audio IF 1_15 + */ +#define WM5100_AIF1TX6_SLOT_MASK 0x003F /* AIF1TX6_SLOT - [5:0] */ +#define WM5100_AIF1TX6_SLOT_SHIFT 0 /* AIF1TX6_SLOT - [5:0] */ +#define WM5100_AIF1TX6_SLOT_WIDTH 6 /* AIF1TX6_SLOT - [5:0] */ + +/* + * R1295 (0x50F) - Audio IF 1_16 + */ +#define WM5100_AIF1TX7_SLOT_MASK 0x003F /* AIF1TX7_SLOT - [5:0] */ +#define WM5100_AIF1TX7_SLOT_SHIFT 0 /* AIF1TX7_SLOT - [5:0] */ +#define WM5100_AIF1TX7_SLOT_WIDTH 6 /* AIF1TX7_SLOT - [5:0] */ + +/* + * R1296 (0x510) - Audio IF 1_17 + */ +#define WM5100_AIF1TX8_SLOT_MASK 0x003F /* AIF1TX8_SLOT - [5:0] */ +#define WM5100_AIF1TX8_SLOT_SHIFT 0 /* AIF1TX8_SLOT - [5:0] */ +#define WM5100_AIF1TX8_SLOT_WIDTH 6 /* AIF1TX8_SLOT - [5:0] */ + +/* + * R1297 (0x511) - Audio IF 1_18 + */ +#define WM5100_AIF1RX1_SLOT_MASK 0x003F /* AIF1RX1_SLOT - [5:0] */ +#define WM5100_AIF1RX1_SLOT_SHIFT 0 /* AIF1RX1_SLOT - [5:0] */ +#define WM5100_AIF1RX1_SLOT_WIDTH 6 /* AIF1RX1_SLOT - [5:0] */ + +/* + * R1298 (0x512) - Audio IF 1_19 + */ +#define WM5100_AIF1RX2_SLOT_MASK 0x003F /* AIF1RX2_SLOT - [5:0] */ +#define WM5100_AIF1RX2_SLOT_SHIFT 0 /* AIF1RX2_SLOT - [5:0] */ +#define WM5100_AIF1RX2_SLOT_WIDTH 6 /* AIF1RX2_SLOT - [5:0] */ + +/* + * R1299 (0x513) - Audio IF 1_20 + */ +#define WM5100_AIF1RX3_SLOT_MASK 0x003F /* AIF1RX3_SLOT - [5:0] */ +#define WM5100_AIF1RX3_SLOT_SHIFT 0 /* AIF1RX3_SLOT - [5:0] */ +#define WM5100_AIF1RX3_SLOT_WIDTH 6 /* AIF1RX3_SLOT - [5:0] */ + +/* + * R1300 (0x514) - Audio IF 1_21 + */ +#define WM5100_AIF1RX4_SLOT_MASK 0x003F /* AIF1RX4_SLOT - [5:0] */ +#define WM5100_AIF1RX4_SLOT_SHIFT 0 /* AIF1RX4_SLOT - [5:0] */ +#define WM5100_AIF1RX4_SLOT_WIDTH 6 /* AIF1RX4_SLOT - [5:0] */ + +/* + * R1301 (0x515) - Audio IF 1_22 + */ +#define WM5100_AIF1RX5_SLOT_MASK 0x003F /* AIF1RX5_SLOT - [5:0] */ +#define WM5100_AIF1RX5_SLOT_SHIFT 0 /* AIF1RX5_SLOT - [5:0] */ +#define WM5100_AIF1RX5_SLOT_WIDTH 6 /* AIF1RX5_SLOT - [5:0] */ + +/* + * R1302 (0x516) - Audio IF 1_23 + */ +#define WM5100_AIF1RX6_SLOT_MASK 0x003F /* AIF1RX6_SLOT - [5:0] */ +#define WM5100_AIF1RX6_SLOT_SHIFT 0 /* AIF1RX6_SLOT - [5:0] */ +#define WM5100_AIF1RX6_SLOT_WIDTH 6 /* AIF1RX6_SLOT - [5:0] */ + +/* + * R1303 (0x517) - Audio IF 1_24 + */ +#define WM5100_AIF1RX7_SLOT_MASK 0x003F /* AIF1RX7_SLOT - [5:0] */ +#define WM5100_AIF1RX7_SLOT_SHIFT 0 /* AIF1RX7_SLOT - [5:0] */ +#define WM5100_AIF1RX7_SLOT_WIDTH 6 /* AIF1RX7_SLOT - [5:0] */ + +/* + * R1304 (0x518) - Audio IF 1_25 + */ +#define WM5100_AIF1RX8_SLOT_MASK 0x003F /* AIF1RX8_SLOT - [5:0] */ +#define WM5100_AIF1RX8_SLOT_SHIFT 0 /* AIF1RX8_SLOT - [5:0] */ +#define WM5100_AIF1RX8_SLOT_WIDTH 6 /* AIF1RX8_SLOT - [5:0] */ + +/* + * R1305 (0x519) - Audio IF 1_26 + */ +#define WM5100_AIF1TX8_ENA 0x0080 /* AIF1TX8_ENA */ +#define WM5100_AIF1TX8_ENA_MASK 0x0080 /* AIF1TX8_ENA */ +#define WM5100_AIF1TX8_ENA_SHIFT 7 /* AIF1TX8_ENA */ +#define WM5100_AIF1TX8_ENA_WIDTH 1 /* AIF1TX8_ENA */ +#define WM5100_AIF1TX7_ENA 0x0040 /* AIF1TX7_ENA */ +#define WM5100_AIF1TX7_ENA_MASK 0x0040 /* AIF1TX7_ENA */ +#define WM5100_AIF1TX7_ENA_SHIFT 6 /* AIF1TX7_ENA */ +#define WM5100_AIF1TX7_ENA_WIDTH 1 /* AIF1TX7_ENA */ +#define WM5100_AIF1TX6_ENA 0x0020 /* AIF1TX6_ENA */ +#define WM5100_AIF1TX6_ENA_MASK 0x0020 /* AIF1TX6_ENA */ +#define WM5100_AIF1TX6_ENA_SHIFT 5 /* AIF1TX6_ENA */ +#define WM5100_AIF1TX6_ENA_WIDTH 1 /* AIF1TX6_ENA */ +#define WM5100_AIF1TX5_ENA 0x0010 /* AIF1TX5_ENA */ +#define WM5100_AIF1TX5_ENA_MASK 0x0010 /* AIF1TX5_ENA */ +#define WM5100_AIF1TX5_ENA_SHIFT 4 /* AIF1TX5_ENA */ +#define WM5100_AIF1TX5_ENA_WIDTH 1 /* AIF1TX5_ENA */ +#define WM5100_AIF1TX4_ENA 0x0008 /* AIF1TX4_ENA */ +#define WM5100_AIF1TX4_ENA_MASK 0x0008 /* AIF1TX4_ENA */ +#define WM5100_AIF1TX4_ENA_SHIFT 3 /* AIF1TX4_ENA */ +#define WM5100_AIF1TX4_ENA_WIDTH 1 /* AIF1TX4_ENA */ +#define WM5100_AIF1TX3_ENA 0x0004 /* AIF1TX3_ENA */ +#define WM5100_AIF1TX3_ENA_MASK 0x0004 /* AIF1TX3_ENA */ +#define WM5100_AIF1TX3_ENA_SHIFT 2 /* AIF1TX3_ENA */ +#define WM5100_AIF1TX3_ENA_WIDTH 1 /* AIF1TX3_ENA */ +#define WM5100_AIF1TX2_ENA 0x0002 /* AIF1TX2_ENA */ +#define WM5100_AIF1TX2_ENA_MASK 0x0002 /* AIF1TX2_ENA */ +#define WM5100_AIF1TX2_ENA_SHIFT 1 /* AIF1TX2_ENA */ +#define WM5100_AIF1TX2_ENA_WIDTH 1 /* AIF1TX2_ENA */ +#define WM5100_AIF1TX1_ENA 0x0001 /* AIF1TX1_ENA */ +#define WM5100_AIF1TX1_ENA_MASK 0x0001 /* AIF1TX1_ENA */ +#define WM5100_AIF1TX1_ENA_SHIFT 0 /* AIF1TX1_ENA */ +#define WM5100_AIF1TX1_ENA_WIDTH 1 /* AIF1TX1_ENA */ + +/* + * R1306 (0x51A) - Audio IF 1_27 + */ +#define WM5100_AIF1RX8_ENA 0x0080 /* AIF1RX8_ENA */ +#define WM5100_AIF1RX8_ENA_MASK 0x0080 /* AIF1RX8_ENA */ +#define WM5100_AIF1RX8_ENA_SHIFT 7 /* AIF1RX8_ENA */ +#define WM5100_AIF1RX8_ENA_WIDTH 1 /* AIF1RX8_ENA */ +#define WM5100_AIF1RX7_ENA 0x0040 /* AIF1RX7_ENA */ +#define WM5100_AIF1RX7_ENA_MASK 0x0040 /* AIF1RX7_ENA */ +#define WM5100_AIF1RX7_ENA_SHIFT 6 /* AIF1RX7_ENA */ +#define WM5100_AIF1RX7_ENA_WIDTH 1 /* AIF1RX7_ENA */ +#define WM5100_AIF1RX6_ENA 0x0020 /* AIF1RX6_ENA */ +#define WM5100_AIF1RX6_ENA_MASK 0x0020 /* AIF1RX6_ENA */ +#define WM5100_AIF1RX6_ENA_SHIFT 5 /* AIF1RX6_ENA */ +#define WM5100_AIF1RX6_ENA_WIDTH 1 /* AIF1RX6_ENA */ +#define WM5100_AIF1RX5_ENA 0x0010 /* AIF1RX5_ENA */ +#define WM5100_AIF1RX5_ENA_MASK 0x0010 /* AIF1RX5_ENA */ +#define WM5100_AIF1RX5_ENA_SHIFT 4 /* AIF1RX5_ENA */ +#define WM5100_AIF1RX5_ENA_WIDTH 1 /* AIF1RX5_ENA */ +#define WM5100_AIF1RX4_ENA 0x0008 /* AIF1RX4_ENA */ +#define WM5100_AIF1RX4_ENA_MASK 0x0008 /* AIF1RX4_ENA */ +#define WM5100_AIF1RX4_ENA_SHIFT 3 /* AIF1RX4_ENA */ +#define WM5100_AIF1RX4_ENA_WIDTH 1 /* AIF1RX4_ENA */ +#define WM5100_AIF1RX3_ENA 0x0004 /* AIF1RX3_ENA */ +#define WM5100_AIF1RX3_ENA_MASK 0x0004 /* AIF1RX3_ENA */ +#define WM5100_AIF1RX3_ENA_SHIFT 2 /* AIF1RX3_ENA */ +#define WM5100_AIF1RX3_ENA_WIDTH 1 /* AIF1RX3_ENA */ +#define WM5100_AIF1RX2_ENA 0x0002 /* AIF1RX2_ENA */ +#define WM5100_AIF1RX2_ENA_MASK 0x0002 /* AIF1RX2_ENA */ +#define WM5100_AIF1RX2_ENA_SHIFT 1 /* AIF1RX2_ENA */ +#define WM5100_AIF1RX2_ENA_WIDTH 1 /* AIF1RX2_ENA */ +#define WM5100_AIF1RX1_ENA 0x0001 /* AIF1RX1_ENA */ +#define WM5100_AIF1RX1_ENA_MASK 0x0001 /* AIF1RX1_ENA */ +#define WM5100_AIF1RX1_ENA_SHIFT 0 /* AIF1RX1_ENA */ +#define WM5100_AIF1RX1_ENA_WIDTH 1 /* AIF1RX1_ENA */ + +/* + * R1344 (0x540) - Audio IF 2_1 + */ +#define WM5100_AIF2_BCLK_INV 0x0080 /* AIF2_BCLK_INV */ +#define WM5100_AIF2_BCLK_INV_MASK 0x0080 /* AIF2_BCLK_INV */ +#define WM5100_AIF2_BCLK_INV_SHIFT 7 /* AIF2_BCLK_INV */ +#define WM5100_AIF2_BCLK_INV_WIDTH 1 /* AIF2_BCLK_INV */ +#define WM5100_AIF2_BCLK_FRC 0x0040 /* AIF2_BCLK_FRC */ +#define WM5100_AIF2_BCLK_FRC_MASK 0x0040 /* AIF2_BCLK_FRC */ +#define WM5100_AIF2_BCLK_FRC_SHIFT 6 /* AIF2_BCLK_FRC */ +#define WM5100_AIF2_BCLK_FRC_WIDTH 1 /* AIF2_BCLK_FRC */ +#define WM5100_AIF2_BCLK_MSTR 0x0020 /* AIF2_BCLK_MSTR */ +#define WM5100_AIF2_BCLK_MSTR_MASK 0x0020 /* AIF2_BCLK_MSTR */ +#define WM5100_AIF2_BCLK_MSTR_SHIFT 5 /* AIF2_BCLK_MSTR */ +#define WM5100_AIF2_BCLK_MSTR_WIDTH 1 /* AIF2_BCLK_MSTR */ +#define WM5100_AIF2_BCLK_FREQ_MASK 0x001F /* AIF2_BCLK_FREQ - [4:0] */ +#define WM5100_AIF2_BCLK_FREQ_SHIFT 0 /* AIF2_BCLK_FREQ - [4:0] */ +#define WM5100_AIF2_BCLK_FREQ_WIDTH 5 /* AIF2_BCLK_FREQ - [4:0] */ + +/* + * R1345 (0x541) - Audio IF 2_2 + */ +#define WM5100_AIF2TX_DAT_TRI 0x0020 /* AIF2TX_DAT_TRI */ +#define WM5100_AIF2TX_DAT_TRI_MASK 0x0020 /* AIF2TX_DAT_TRI */ +#define WM5100_AIF2TX_DAT_TRI_SHIFT 5 /* AIF2TX_DAT_TRI */ +#define WM5100_AIF2TX_DAT_TRI_WIDTH 1 /* AIF2TX_DAT_TRI */ +#define WM5100_AIF2TX_LRCLK_SRC 0x0008 /* AIF2TX_LRCLK_SRC */ +#define WM5100_AIF2TX_LRCLK_SRC_MASK 0x0008 /* AIF2TX_LRCLK_SRC */ +#define WM5100_AIF2TX_LRCLK_SRC_SHIFT 3 /* AIF2TX_LRCLK_SRC */ +#define WM5100_AIF2TX_LRCLK_SRC_WIDTH 1 /* AIF2TX_LRCLK_SRC */ +#define WM5100_AIF2TX_LRCLK_INV 0x0004 /* AIF2TX_LRCLK_INV */ +#define WM5100_AIF2TX_LRCLK_INV_MASK 0x0004 /* AIF2TX_LRCLK_INV */ +#define WM5100_AIF2TX_LRCLK_INV_SHIFT 2 /* AIF2TX_LRCLK_INV */ +#define WM5100_AIF2TX_LRCLK_INV_WIDTH 1 /* AIF2TX_LRCLK_INV */ +#define WM5100_AIF2TX_LRCLK_FRC 0x0002 /* AIF2TX_LRCLK_FRC */ +#define WM5100_AIF2TX_LRCLK_FRC_MASK 0x0002 /* AIF2TX_LRCLK_FRC */ +#define WM5100_AIF2TX_LRCLK_FRC_SHIFT 1 /* AIF2TX_LRCLK_FRC */ +#define WM5100_AIF2TX_LRCLK_FRC_WIDTH 1 /* AIF2TX_LRCLK_FRC */ +#define WM5100_AIF2TX_LRCLK_MSTR 0x0001 /* AIF2TX_LRCLK_MSTR */ +#define WM5100_AIF2TX_LRCLK_MSTR_MASK 0x0001 /* AIF2TX_LRCLK_MSTR */ +#define WM5100_AIF2TX_LRCLK_MSTR_SHIFT 0 /* AIF2TX_LRCLK_MSTR */ +#define WM5100_AIF2TX_LRCLK_MSTR_WIDTH 1 /* AIF2TX_LRCLK_MSTR */ + +/* + * R1346 (0x542) - Audio IF 2_3 + */ +#define WM5100_AIF2RX_LRCLK_INV 0x0004 /* AIF2RX_LRCLK_INV */ +#define WM5100_AIF2RX_LRCLK_INV_MASK 0x0004 /* AIF2RX_LRCLK_INV */ +#define WM5100_AIF2RX_LRCLK_INV_SHIFT 2 /* AIF2RX_LRCLK_INV */ +#define WM5100_AIF2RX_LRCLK_INV_WIDTH 1 /* AIF2RX_LRCLK_INV */ +#define WM5100_AIF2RX_LRCLK_FRC 0x0002 /* AIF2RX_LRCLK_FRC */ +#define WM5100_AIF2RX_LRCLK_FRC_MASK 0x0002 /* AIF2RX_LRCLK_FRC */ +#define WM5100_AIF2RX_LRCLK_FRC_SHIFT 1 /* AIF2RX_LRCLK_FRC */ +#define WM5100_AIF2RX_LRCLK_FRC_WIDTH 1 /* AIF2RX_LRCLK_FRC */ +#define WM5100_AIF2RX_LRCLK_MSTR 0x0001 /* AIF2RX_LRCLK_MSTR */ +#define WM5100_AIF2RX_LRCLK_MSTR_MASK 0x0001 /* AIF2RX_LRCLK_MSTR */ +#define WM5100_AIF2RX_LRCLK_MSTR_SHIFT 0 /* AIF2RX_LRCLK_MSTR */ +#define WM5100_AIF2RX_LRCLK_MSTR_WIDTH 1 /* AIF2RX_LRCLK_MSTR */ + +/* + * R1347 (0x543) - Audio IF 2_4 + */ +#define WM5100_AIF2_TRI 0x0040 /* AIF2_TRI */ +#define WM5100_AIF2_TRI_MASK 0x0040 /* AIF2_TRI */ +#define WM5100_AIF2_TRI_SHIFT 6 /* AIF2_TRI */ +#define WM5100_AIF2_TRI_WIDTH 1 /* AIF2_TRI */ +#define WM5100_AIF2_RATE_MASK 0x0003 /* AIF2_RATE - [1:0] */ +#define WM5100_AIF2_RATE_SHIFT 0 /* AIF2_RATE - [1:0] */ +#define WM5100_AIF2_RATE_WIDTH 2 /* AIF2_RATE - [1:0] */ + +/* + * R1348 (0x544) - Audio IF 2_5 + */ +#define WM5100_AIF2_FMT_MASK 0x0007 /* AIF2_FMT - [2:0] */ +#define WM5100_AIF2_FMT_SHIFT 0 /* AIF2_FMT - [2:0] */ +#define WM5100_AIF2_FMT_WIDTH 3 /* AIF2_FMT - [2:0] */ + +/* + * R1349 (0x545) - Audio IF 2_6 + */ +#define WM5100_AIF2TX_BCPF_MASK 0x1FFF /* AIF2TX_BCPF - [12:0] */ +#define WM5100_AIF2TX_BCPF_SHIFT 0 /* AIF2TX_BCPF - [12:0] */ +#define WM5100_AIF2TX_BCPF_WIDTH 13 /* AIF2TX_BCPF - [12:0] */ + +/* + * R1350 (0x546) - Audio IF 2_7 + */ +#define WM5100_AIF2RX_BCPF_MASK 0x1FFF /* AIF2RX_BCPF - [12:0] */ +#define WM5100_AIF2RX_BCPF_SHIFT 0 /* AIF2RX_BCPF - [12:0] */ +#define WM5100_AIF2RX_BCPF_WIDTH 13 /* AIF2RX_BCPF - [12:0] */ + +/* + * R1351 (0x547) - Audio IF 2_8 + */ +#define WM5100_AIF2TX_WL_MASK 0x3F00 /* AIF2TX_WL - [13:8] */ +#define WM5100_AIF2TX_WL_SHIFT 8 /* AIF2TX_WL - [13:8] */ +#define WM5100_AIF2TX_WL_WIDTH 6 /* AIF2TX_WL - [13:8] */ +#define WM5100_AIF2TX_SLOT_LEN_MASK 0x00FF /* AIF2TX_SLOT_LEN - [7:0] */ +#define WM5100_AIF2TX_SLOT_LEN_SHIFT 0 /* AIF2TX_SLOT_LEN - [7:0] */ +#define WM5100_AIF2TX_SLOT_LEN_WIDTH 8 /* AIF2TX_SLOT_LEN - [7:0] */ + +/* + * R1352 (0x548) - Audio IF 2_9 + */ +#define WM5100_AIF2RX_WL_MASK 0x3F00 /* AIF2RX_WL - [13:8] */ +#define WM5100_AIF2RX_WL_SHIFT 8 /* AIF2RX_WL - [13:8] */ +#define WM5100_AIF2RX_WL_WIDTH 6 /* AIF2RX_WL - [13:8] */ +#define WM5100_AIF2RX_SLOT_LEN_MASK 0x00FF /* AIF2RX_SLOT_LEN - [7:0] */ +#define WM5100_AIF2RX_SLOT_LEN_SHIFT 0 /* AIF2RX_SLOT_LEN - [7:0] */ +#define WM5100_AIF2RX_SLOT_LEN_WIDTH 8 /* AIF2RX_SLOT_LEN - [7:0] */ + +/* + * R1353 (0x549) - Audio IF 2_10 + */ +#define WM5100_AIF2TX1_SLOT_MASK 0x003F /* AIF2TX1_SLOT - [5:0] */ +#define WM5100_AIF2TX1_SLOT_SHIFT 0 /* AIF2TX1_SLOT - [5:0] */ +#define WM5100_AIF2TX1_SLOT_WIDTH 6 /* AIF2TX1_SLOT - [5:0] */ + +/* + * R1354 (0x54A) - Audio IF 2_11 + */ +#define WM5100_AIF2TX2_SLOT_MASK 0x003F /* AIF2TX2_SLOT - [5:0] */ +#define WM5100_AIF2TX2_SLOT_SHIFT 0 /* AIF2TX2_SLOT - [5:0] */ +#define WM5100_AIF2TX2_SLOT_WIDTH 6 /* AIF2TX2_SLOT - [5:0] */ + +/* + * R1361 (0x551) - Audio IF 2_18 + */ +#define WM5100_AIF2RX1_SLOT_MASK 0x003F /* AIF2RX1_SLOT - [5:0] */ +#define WM5100_AIF2RX1_SLOT_SHIFT 0 /* AIF2RX1_SLOT - [5:0] */ +#define WM5100_AIF2RX1_SLOT_WIDTH 6 /* AIF2RX1_SLOT - [5:0] */ + +/* + * R1362 (0x552) - Audio IF 2_19 + */ +#define WM5100_AIF2RX2_SLOT_MASK 0x003F /* AIF2RX2_SLOT - [5:0] */ +#define WM5100_AIF2RX2_SLOT_SHIFT 0 /* AIF2RX2_SLOT - [5:0] */ +#define WM5100_AIF2RX2_SLOT_WIDTH 6 /* AIF2RX2_SLOT - [5:0] */ + +/* + * R1369 (0x559) - Audio IF 2_26 + */ +#define WM5100_AIF2TX2_ENA 0x0002 /* AIF2TX2_ENA */ +#define WM5100_AIF2TX2_ENA_MASK 0x0002 /* AIF2TX2_ENA */ +#define WM5100_AIF2TX2_ENA_SHIFT 1 /* AIF2TX2_ENA */ +#define WM5100_AIF2TX2_ENA_WIDTH 1 /* AIF2TX2_ENA */ +#define WM5100_AIF2TX1_ENA 0x0001 /* AIF2TX1_ENA */ +#define WM5100_AIF2TX1_ENA_MASK 0x0001 /* AIF2TX1_ENA */ +#define WM5100_AIF2TX1_ENA_SHIFT 0 /* AIF2TX1_ENA */ +#define WM5100_AIF2TX1_ENA_WIDTH 1 /* AIF2TX1_ENA */ + +/* + * R1370 (0x55A) - Audio IF 2_27 + */ +#define WM5100_AIF2RX2_ENA 0x0002 /* AIF2RX2_ENA */ +#define WM5100_AIF2RX2_ENA_MASK 0x0002 /* AIF2RX2_ENA */ +#define WM5100_AIF2RX2_ENA_SHIFT 1 /* AIF2RX2_ENA */ +#define WM5100_AIF2RX2_ENA_WIDTH 1 /* AIF2RX2_ENA */ +#define WM5100_AIF2RX1_ENA 0x0001 /* AIF2RX1_ENA */ +#define WM5100_AIF2RX1_ENA_MASK 0x0001 /* AIF2RX1_ENA */ +#define WM5100_AIF2RX1_ENA_SHIFT 0 /* AIF2RX1_ENA */ +#define WM5100_AIF2RX1_ENA_WIDTH 1 /* AIF2RX1_ENA */ + +/* + * R1408 (0x580) - Audio IF 3_1 + */ +#define WM5100_AIF3_BCLK_INV 0x0080 /* AIF3_BCLK_INV */ +#define WM5100_AIF3_BCLK_INV_MASK 0x0080 /* AIF3_BCLK_INV */ +#define WM5100_AIF3_BCLK_INV_SHIFT 7 /* AIF3_BCLK_INV */ +#define WM5100_AIF3_BCLK_INV_WIDTH 1 /* AIF3_BCLK_INV */ +#define WM5100_AIF3_BCLK_FRC 0x0040 /* AIF3_BCLK_FRC */ +#define WM5100_AIF3_BCLK_FRC_MASK 0x0040 /* AIF3_BCLK_FRC */ +#define WM5100_AIF3_BCLK_FRC_SHIFT 6 /* AIF3_BCLK_FRC */ +#define WM5100_AIF3_BCLK_FRC_WIDTH 1 /* AIF3_BCLK_FRC */ +#define WM5100_AIF3_BCLK_MSTR 0x0020 /* AIF3_BCLK_MSTR */ +#define WM5100_AIF3_BCLK_MSTR_MASK 0x0020 /* AIF3_BCLK_MSTR */ +#define WM5100_AIF3_BCLK_MSTR_SHIFT 5 /* AIF3_BCLK_MSTR */ +#define WM5100_AIF3_BCLK_MSTR_WIDTH 1 /* AIF3_BCLK_MSTR */ +#define WM5100_AIF3_BCLK_FREQ_MASK 0x001F /* AIF3_BCLK_FREQ - [4:0] */ +#define WM5100_AIF3_BCLK_FREQ_SHIFT 0 /* AIF3_BCLK_FREQ - [4:0] */ +#define WM5100_AIF3_BCLK_FREQ_WIDTH 5 /* AIF3_BCLK_FREQ - [4:0] */ + +/* + * R1409 (0x581) - Audio IF 3_2 + */ +#define WM5100_AIF3TX_DAT_TRI 0x0020 /* AIF3TX_DAT_TRI */ +#define WM5100_AIF3TX_DAT_TRI_MASK 0x0020 /* AIF3TX_DAT_TRI */ +#define WM5100_AIF3TX_DAT_TRI_SHIFT 5 /* AIF3TX_DAT_TRI */ +#define WM5100_AIF3TX_DAT_TRI_WIDTH 1 /* AIF3TX_DAT_TRI */ +#define WM5100_AIF3TX_LRCLK_SRC 0x0008 /* AIF3TX_LRCLK_SRC */ +#define WM5100_AIF3TX_LRCLK_SRC_MASK 0x0008 /* AIF3TX_LRCLK_SRC */ +#define WM5100_AIF3TX_LRCLK_SRC_SHIFT 3 /* AIF3TX_LRCLK_SRC */ +#define WM5100_AIF3TX_LRCLK_SRC_WIDTH 1 /* AIF3TX_LRCLK_SRC */ +#define WM5100_AIF3TX_LRCLK_INV 0x0004 /* AIF3TX_LRCLK_INV */ +#define WM5100_AIF3TX_LRCLK_INV_MASK 0x0004 /* AIF3TX_LRCLK_INV */ +#define WM5100_AIF3TX_LRCLK_INV_SHIFT 2 /* AIF3TX_LRCLK_INV */ +#define WM5100_AIF3TX_LRCLK_INV_WIDTH 1 /* AIF3TX_LRCLK_INV */ +#define WM5100_AIF3TX_LRCLK_FRC 0x0002 /* AIF3TX_LRCLK_FRC */ +#define WM5100_AIF3TX_LRCLK_FRC_MASK 0x0002 /* AIF3TX_LRCLK_FRC */ +#define WM5100_AIF3TX_LRCLK_FRC_SHIFT 1 /* AIF3TX_LRCLK_FRC */ +#define WM5100_AIF3TX_LRCLK_FRC_WIDTH 1 /* AIF3TX_LRCLK_FRC */ +#define WM5100_AIF3TX_LRCLK_MSTR 0x0001 /* AIF3TX_LRCLK_MSTR */ +#define WM5100_AIF3TX_LRCLK_MSTR_MASK 0x0001 /* AIF3TX_LRCLK_MSTR */ +#define WM5100_AIF3TX_LRCLK_MSTR_SHIFT 0 /* AIF3TX_LRCLK_MSTR */ +#define WM5100_AIF3TX_LRCLK_MSTR_WIDTH 1 /* AIF3TX_LRCLK_MSTR */ + +/* + * R1410 (0x582) - Audio IF 3_3 + */ +#define WM5100_AIF3RX_LRCLK_INV 0x0004 /* AIF3RX_LRCLK_INV */ +#define WM5100_AIF3RX_LRCLK_INV_MASK 0x0004 /* AIF3RX_LRCLK_INV */ +#define WM5100_AIF3RX_LRCLK_INV_SHIFT 2 /* AIF3RX_LRCLK_INV */ +#define WM5100_AIF3RX_LRCLK_INV_WIDTH 1 /* AIF3RX_LRCLK_INV */ +#define WM5100_AIF3RX_LRCLK_FRC 0x0002 /* AIF3RX_LRCLK_FRC */ +#define WM5100_AIF3RX_LRCLK_FRC_MASK 0x0002 /* AIF3RX_LRCLK_FRC */ +#define WM5100_AIF3RX_LRCLK_FRC_SHIFT 1 /* AIF3RX_LRCLK_FRC */ +#define WM5100_AIF3RX_LRCLK_FRC_WIDTH 1 /* AIF3RX_LRCLK_FRC */ +#define WM5100_AIF3RX_LRCLK_MSTR 0x0001 /* AIF3RX_LRCLK_MSTR */ +#define WM5100_AIF3RX_LRCLK_MSTR_MASK 0x0001 /* AIF3RX_LRCLK_MSTR */ +#define WM5100_AIF3RX_LRCLK_MSTR_SHIFT 0 /* AIF3RX_LRCLK_MSTR */ +#define WM5100_AIF3RX_LRCLK_MSTR_WIDTH 1 /* AIF3RX_LRCLK_MSTR */ + +/* + * R1411 (0x583) - Audio IF 3_4 + */ +#define WM5100_AIF3_TRI 0x0040 /* AIF3_TRI */ +#define WM5100_AIF3_TRI_MASK 0x0040 /* AIF3_TRI */ +#define WM5100_AIF3_TRI_SHIFT 6 /* AIF3_TRI */ +#define WM5100_AIF3_TRI_WIDTH 1 /* AIF3_TRI */ +#define WM5100_AIF3_RATE_MASK 0x0003 /* AIF3_RATE - [1:0] */ +#define WM5100_AIF3_RATE_SHIFT 0 /* AIF3_RATE - [1:0] */ +#define WM5100_AIF3_RATE_WIDTH 2 /* AIF3_RATE - [1:0] */ + +/* + * R1412 (0x584) - Audio IF 3_5 + */ +#define WM5100_AIF3_FMT_MASK 0x0007 /* AIF3_FMT - [2:0] */ +#define WM5100_AIF3_FMT_SHIFT 0 /* AIF3_FMT - [2:0] */ +#define WM5100_AIF3_FMT_WIDTH 3 /* AIF3_FMT - [2:0] */ + +/* + * R1413 (0x585) - Audio IF 3_6 + */ +#define WM5100_AIF3TX_BCPF_MASK 0x1FFF /* AIF3TX_BCPF - [12:0] */ +#define WM5100_AIF3TX_BCPF_SHIFT 0 /* AIF3TX_BCPF - [12:0] */ +#define WM5100_AIF3TX_BCPF_WIDTH 13 /* AIF3TX_BCPF - [12:0] */ + +/* + * R1414 (0x586) - Audio IF 3_7 + */ +#define WM5100_AIF3RX_BCPF_MASK 0x1FFF /* AIF3RX_BCPF - [12:0] */ +#define WM5100_AIF3RX_BCPF_SHIFT 0 /* AIF3RX_BCPF - [12:0] */ +#define WM5100_AIF3RX_BCPF_WIDTH 13 /* AIF3RX_BCPF - [12:0] */ + +/* + * R1415 (0x587) - Audio IF 3_8 + */ +#define WM5100_AIF3TX_WL_MASK 0x3F00 /* AIF3TX_WL - [13:8] */ +#define WM5100_AIF3TX_WL_SHIFT 8 /* AIF3TX_WL - [13:8] */ +#define WM5100_AIF3TX_WL_WIDTH 6 /* AIF3TX_WL - [13:8] */ +#define WM5100_AIF3TX_SLOT_LEN_MASK 0x00FF /* AIF3TX_SLOT_LEN - [7:0] */ +#define WM5100_AIF3TX_SLOT_LEN_SHIFT 0 /* AIF3TX_SLOT_LEN - [7:0] */ +#define WM5100_AIF3TX_SLOT_LEN_WIDTH 8 /* AIF3TX_SLOT_LEN - [7:0] */ + +/* + * R1416 (0x588) - Audio IF 3_9 + */ +#define WM5100_AIF3RX_WL_MASK 0x3F00 /* AIF3RX_WL - [13:8] */ +#define WM5100_AIF3RX_WL_SHIFT 8 /* AIF3RX_WL - [13:8] */ +#define WM5100_AIF3RX_WL_WIDTH 6 /* AIF3RX_WL - [13:8] */ +#define WM5100_AIF3RX_SLOT_LEN_MASK 0x00FF /* AIF3RX_SLOT_LEN - [7:0] */ +#define WM5100_AIF3RX_SLOT_LEN_SHIFT 0 /* AIF3RX_SLOT_LEN - [7:0] */ +#define WM5100_AIF3RX_SLOT_LEN_WIDTH 8 /* AIF3RX_SLOT_LEN - [7:0] */ + +/* + * R1417 (0x589) - Audio IF 3_10 + */ +#define WM5100_AIF3TX1_SLOT_MASK 0x003F /* AIF3TX1_SLOT - [5:0] */ +#define WM5100_AIF3TX1_SLOT_SHIFT 0 /* AIF3TX1_SLOT - [5:0] */ +#define WM5100_AIF3TX1_SLOT_WIDTH 6 /* AIF3TX1_SLOT - [5:0] */ + +/* + * R1418 (0x58A) - Audio IF 3_11 + */ +#define WM5100_AIF3TX2_SLOT_MASK 0x003F /* AIF3TX2_SLOT - [5:0] */ +#define WM5100_AIF3TX2_SLOT_SHIFT 0 /* AIF3TX2_SLOT - [5:0] */ +#define WM5100_AIF3TX2_SLOT_WIDTH 6 /* AIF3TX2_SLOT - [5:0] */ + +/* + * R1425 (0x591) - Audio IF 3_18 + */ +#define WM5100_AIF3RX1_SLOT_MASK 0x003F /* AIF3RX1_SLOT - [5:0] */ +#define WM5100_AIF3RX1_SLOT_SHIFT 0 /* AIF3RX1_SLOT - [5:0] */ +#define WM5100_AIF3RX1_SLOT_WIDTH 6 /* AIF3RX1_SLOT - [5:0] */ + +/* + * R1426 (0x592) - Audio IF 3_19 + */ +#define WM5100_AIF3RX2_SLOT_MASK 0x003F /* AIF3RX2_SLOT - [5:0] */ +#define WM5100_AIF3RX2_SLOT_SHIFT 0 /* AIF3RX2_SLOT - [5:0] */ +#define WM5100_AIF3RX2_SLOT_WIDTH 6 /* AIF3RX2_SLOT - [5:0] */ + +/* + * R1433 (0x599) - Audio IF 3_26 + */ +#define WM5100_AIF3TX2_ENA 0x0002 /* AIF3TX2_ENA */ +#define WM5100_AIF3TX2_ENA_MASK 0x0002 /* AIF3TX2_ENA */ +#define WM5100_AIF3TX2_ENA_SHIFT 1 /* AIF3TX2_ENA */ +#define WM5100_AIF3TX2_ENA_WIDTH 1 /* AIF3TX2_ENA */ +#define WM5100_AIF3TX1_ENA 0x0001 /* AIF3TX1_ENA */ +#define WM5100_AIF3TX1_ENA_MASK 0x0001 /* AIF3TX1_ENA */ +#define WM5100_AIF3TX1_ENA_SHIFT 0 /* AIF3TX1_ENA */ +#define WM5100_AIF3TX1_ENA_WIDTH 1 /* AIF3TX1_ENA */ + +/* + * R1434 (0x59A) - Audio IF 3_27 + */ +#define WM5100_AIF3RX2_ENA 0x0002 /* AIF3RX2_ENA */ +#define WM5100_AIF3RX2_ENA_MASK 0x0002 /* AIF3RX2_ENA */ +#define WM5100_AIF3RX2_ENA_SHIFT 1 /* AIF3RX2_ENA */ +#define WM5100_AIF3RX2_ENA_WIDTH 1 /* AIF3RX2_ENA */ +#define WM5100_AIF3RX1_ENA 0x0001 /* AIF3RX1_ENA */ +#define WM5100_AIF3RX1_ENA_MASK 0x0001 /* AIF3RX1_ENA */ +#define WM5100_AIF3RX1_ENA_SHIFT 0 /* AIF3RX1_ENA */ +#define WM5100_AIF3RX1_ENA_WIDTH 1 /* AIF3RX1_ENA */ + +#define WM5100_MIXER_VOL_MASK 0x00FE /* MIXER_VOL - [7:1] */ +#define WM5100_MIXER_VOL_SHIFT 1 /* MIXER_VOL - [7:1] */ +#define WM5100_MIXER_VOL_WIDTH 7 /* MIXER_VOL - [7:1] */ + +/* + * R3072 (0xC00) - GPIO CTRL 1 + */ +#define WM5100_GP1_DIR 0x8000 /* GP1_DIR */ +#define WM5100_GP1_DIR_MASK 0x8000 /* GP1_DIR */ +#define WM5100_GP1_DIR_SHIFT 15 /* GP1_DIR */ +#define WM5100_GP1_DIR_WIDTH 1 /* GP1_DIR */ +#define WM5100_GP1_PU 0x4000 /* GP1_PU */ +#define WM5100_GP1_PU_MASK 0x4000 /* GP1_PU */ +#define WM5100_GP1_PU_SHIFT 14 /* GP1_PU */ +#define WM5100_GP1_PU_WIDTH 1 /* GP1_PU */ +#define WM5100_GP1_PD 0x2000 /* GP1_PD */ +#define WM5100_GP1_PD_MASK 0x2000 /* GP1_PD */ +#define WM5100_GP1_PD_SHIFT 13 /* GP1_PD */ +#define WM5100_GP1_PD_WIDTH 1 /* GP1_PD */ +#define WM5100_GP1_POL 0x0400 /* GP1_POL */ +#define WM5100_GP1_POL_MASK 0x0400 /* GP1_POL */ +#define WM5100_GP1_POL_SHIFT 10 /* GP1_POL */ +#define WM5100_GP1_POL_WIDTH 1 /* GP1_POL */ +#define WM5100_GP1_OP_CFG 0x0200 /* GP1_OP_CFG */ +#define WM5100_GP1_OP_CFG_MASK 0x0200 /* GP1_OP_CFG */ +#define WM5100_GP1_OP_CFG_SHIFT 9 /* GP1_OP_CFG */ +#define WM5100_GP1_OP_CFG_WIDTH 1 /* GP1_OP_CFG */ +#define WM5100_GP1_DB 0x0100 /* GP1_DB */ +#define WM5100_GP1_DB_MASK 0x0100 /* GP1_DB */ +#define WM5100_GP1_DB_SHIFT 8 /* GP1_DB */ +#define WM5100_GP1_DB_WIDTH 1 /* GP1_DB */ +#define WM5100_GP1_LVL 0x0040 /* GP1_LVL */ +#define WM5100_GP1_LVL_MASK 0x0040 /* GP1_LVL */ +#define WM5100_GP1_LVL_SHIFT 6 /* GP1_LVL */ +#define WM5100_GP1_LVL_WIDTH 1 /* GP1_LVL */ +#define WM5100_GP1_FN_MASK 0x003F /* GP1_FN - [5:0] */ +#define WM5100_GP1_FN_SHIFT 0 /* GP1_FN - [5:0] */ +#define WM5100_GP1_FN_WIDTH 6 /* GP1_FN - [5:0] */ + +/* + * R3073 (0xC01) - GPIO CTRL 2 + */ +#define WM5100_GP2_DIR 0x8000 /* GP2_DIR */ +#define WM5100_GP2_DIR_MASK 0x8000 /* GP2_DIR */ +#define WM5100_GP2_DIR_SHIFT 15 /* GP2_DIR */ +#define WM5100_GP2_DIR_WIDTH 1 /* GP2_DIR */ +#define WM5100_GP2_PU 0x4000 /* GP2_PU */ +#define WM5100_GP2_PU_MASK 0x4000 /* GP2_PU */ +#define WM5100_GP2_PU_SHIFT 14 /* GP2_PU */ +#define WM5100_GP2_PU_WIDTH 1 /* GP2_PU */ +#define WM5100_GP2_PD 0x2000 /* GP2_PD */ +#define WM5100_GP2_PD_MASK 0x2000 /* GP2_PD */ +#define WM5100_GP2_PD_SHIFT 13 /* GP2_PD */ +#define WM5100_GP2_PD_WIDTH 1 /* GP2_PD */ +#define WM5100_GP2_POL 0x0400 /* GP2_POL */ +#define WM5100_GP2_POL_MASK 0x0400 /* GP2_POL */ +#define WM5100_GP2_POL_SHIFT 10 /* GP2_POL */ +#define WM5100_GP2_POL_WIDTH 1 /* GP2_POL */ +#define WM5100_GP2_OP_CFG 0x0200 /* GP2_OP_CFG */ +#define WM5100_GP2_OP_CFG_MASK 0x0200 /* GP2_OP_CFG */ +#define WM5100_GP2_OP_CFG_SHIFT 9 /* GP2_OP_CFG */ +#define WM5100_GP2_OP_CFG_WIDTH 1 /* GP2_OP_CFG */ +#define WM5100_GP2_DB 0x0100 /* GP2_DB */ +#define WM5100_GP2_DB_MASK 0x0100 /* GP2_DB */ +#define WM5100_GP2_DB_SHIFT 8 /* GP2_DB */ +#define WM5100_GP2_DB_WIDTH 1 /* GP2_DB */ +#define WM5100_GP2_LVL 0x0040 /* GP2_LVL */ +#define WM5100_GP2_LVL_MASK 0x0040 /* GP2_LVL */ +#define WM5100_GP2_LVL_SHIFT 6 /* GP2_LVL */ +#define WM5100_GP2_LVL_WIDTH 1 /* GP2_LVL */ +#define WM5100_GP2_FN_MASK 0x003F /* GP2_FN - [5:0] */ +#define WM5100_GP2_FN_SHIFT 0 /* GP2_FN - [5:0] */ +#define WM5100_GP2_FN_WIDTH 6 /* GP2_FN - [5:0] */ + +/* + * R3074 (0xC02) - GPIO CTRL 3 + */ +#define WM5100_GP3_DIR 0x8000 /* GP3_DIR */ +#define WM5100_GP3_DIR_MASK 0x8000 /* GP3_DIR */ +#define WM5100_GP3_DIR_SHIFT 15 /* GP3_DIR */ +#define WM5100_GP3_DIR_WIDTH 1 /* GP3_DIR */ +#define WM5100_GP3_PU 0x4000 /* GP3_PU */ +#define WM5100_GP3_PU_MASK 0x4000 /* GP3_PU */ +#define WM5100_GP3_PU_SHIFT 14 /* GP3_PU */ +#define WM5100_GP3_PU_WIDTH 1 /* GP3_PU */ +#define WM5100_GP3_PD 0x2000 /* GP3_PD */ +#define WM5100_GP3_PD_MASK 0x2000 /* GP3_PD */ +#define WM5100_GP3_PD_SHIFT 13 /* GP3_PD */ +#define WM5100_GP3_PD_WIDTH 1 /* GP3_PD */ +#define WM5100_GP3_POL 0x0400 /* GP3_POL */ +#define WM5100_GP3_POL_MASK 0x0400 /* GP3_POL */ +#define WM5100_GP3_POL_SHIFT 10 /* GP3_POL */ +#define WM5100_GP3_POL_WIDTH 1 /* GP3_POL */ +#define WM5100_GP3_OP_CFG 0x0200 /* GP3_OP_CFG */ +#define WM5100_GP3_OP_CFG_MASK 0x0200 /* GP3_OP_CFG */ +#define WM5100_GP3_OP_CFG_SHIFT 9 /* GP3_OP_CFG */ +#define WM5100_GP3_OP_CFG_WIDTH 1 /* GP3_OP_CFG */ +#define WM5100_GP3_DB 0x0100 /* GP3_DB */ +#define WM5100_GP3_DB_MASK 0x0100 /* GP3_DB */ +#define WM5100_GP3_DB_SHIFT 8 /* GP3_DB */ +#define WM5100_GP3_DB_WIDTH 1 /* GP3_DB */ +#define WM5100_GP3_LVL 0x0040 /* GP3_LVL */ +#define WM5100_GP3_LVL_MASK 0x0040 /* GP3_LVL */ +#define WM5100_GP3_LVL_SHIFT 6 /* GP3_LVL */ +#define WM5100_GP3_LVL_WIDTH 1 /* GP3_LVL */ +#define WM5100_GP3_FN_MASK 0x003F /* GP3_FN - [5:0] */ +#define WM5100_GP3_FN_SHIFT 0 /* GP3_FN - [5:0] */ +#define WM5100_GP3_FN_WIDTH 6 /* GP3_FN - [5:0] */ + +/* + * R3075 (0xC03) - GPIO CTRL 4 + */ +#define WM5100_GP4_DIR 0x8000 /* GP4_DIR */ +#define WM5100_GP4_DIR_MASK 0x8000 /* GP4_DIR */ +#define WM5100_GP4_DIR_SHIFT 15 /* GP4_DIR */ +#define WM5100_GP4_DIR_WIDTH 1 /* GP4_DIR */ +#define WM5100_GP4_PU 0x4000 /* GP4_PU */ +#define WM5100_GP4_PU_MASK 0x4000 /* GP4_PU */ +#define WM5100_GP4_PU_SHIFT 14 /* GP4_PU */ +#define WM5100_GP4_PU_WIDTH 1 /* GP4_PU */ +#define WM5100_GP4_PD 0x2000 /* GP4_PD */ +#define WM5100_GP4_PD_MASK 0x2000 /* GP4_PD */ +#define WM5100_GP4_PD_SHIFT 13 /* GP4_PD */ +#define WM5100_GP4_PD_WIDTH 1 /* GP4_PD */ +#define WM5100_GP4_POL 0x0400 /* GP4_POL */ +#define WM5100_GP4_POL_MASK 0x0400 /* GP4_POL */ +#define WM5100_GP4_POL_SHIFT 10 /* GP4_POL */ +#define WM5100_GP4_POL_WIDTH 1 /* GP4_POL */ +#define WM5100_GP4_OP_CFG 0x0200 /* GP4_OP_CFG */ +#define WM5100_GP4_OP_CFG_MASK 0x0200 /* GP4_OP_CFG */ +#define WM5100_GP4_OP_CFG_SHIFT 9 /* GP4_OP_CFG */ +#define WM5100_GP4_OP_CFG_WIDTH 1 /* GP4_OP_CFG */ +#define WM5100_GP4_DB 0x0100 /* GP4_DB */ +#define WM5100_GP4_DB_MASK 0x0100 /* GP4_DB */ +#define WM5100_GP4_DB_SHIFT 8 /* GP4_DB */ +#define WM5100_GP4_DB_WIDTH 1 /* GP4_DB */ +#define WM5100_GP4_LVL 0x0040 /* GP4_LVL */ +#define WM5100_GP4_LVL_MASK 0x0040 /* GP4_LVL */ +#define WM5100_GP4_LVL_SHIFT 6 /* GP4_LVL */ +#define WM5100_GP4_LVL_WIDTH 1 /* GP4_LVL */ +#define WM5100_GP4_FN_MASK 0x003F /* GP4_FN - [5:0] */ +#define WM5100_GP4_FN_SHIFT 0 /* GP4_FN - [5:0] */ +#define WM5100_GP4_FN_WIDTH 6 /* GP4_FN - [5:0] */ + +/* + * R3076 (0xC04) - GPIO CTRL 5 + */ +#define WM5100_GP5_DIR 0x8000 /* GP5_DIR */ +#define WM5100_GP5_DIR_MASK 0x8000 /* GP5_DIR */ +#define WM5100_GP5_DIR_SHIFT 15 /* GP5_DIR */ +#define WM5100_GP5_DIR_WIDTH 1 /* GP5_DIR */ +#define WM5100_GP5_PU 0x4000 /* GP5_PU */ +#define WM5100_GP5_PU_MASK 0x4000 /* GP5_PU */ +#define WM5100_GP5_PU_SHIFT 14 /* GP5_PU */ +#define WM5100_GP5_PU_WIDTH 1 /* GP5_PU */ +#define WM5100_GP5_PD 0x2000 /* GP5_PD */ +#define WM5100_GP5_PD_MASK 0x2000 /* GP5_PD */ +#define WM5100_GP5_PD_SHIFT 13 /* GP5_PD */ +#define WM5100_GP5_PD_WIDTH 1 /* GP5_PD */ +#define WM5100_GP5_POL 0x0400 /* GP5_POL */ +#define WM5100_GP5_POL_MASK 0x0400 /* GP5_POL */ +#define WM5100_GP5_POL_SHIFT 10 /* GP5_POL */ +#define WM5100_GP5_POL_WIDTH 1 /* GP5_POL */ +#define WM5100_GP5_OP_CFG 0x0200 /* GP5_OP_CFG */ +#define WM5100_GP5_OP_CFG_MASK 0x0200 /* GP5_OP_CFG */ +#define WM5100_GP5_OP_CFG_SHIFT 9 /* GP5_OP_CFG */ +#define WM5100_GP5_OP_CFG_WIDTH 1 /* GP5_OP_CFG */ +#define WM5100_GP5_DB 0x0100 /* GP5_DB */ +#define WM5100_GP5_DB_MASK 0x0100 /* GP5_DB */ +#define WM5100_GP5_DB_SHIFT 8 /* GP5_DB */ +#define WM5100_GP5_DB_WIDTH 1 /* GP5_DB */ +#define WM5100_GP5_LVL 0x0040 /* GP5_LVL */ +#define WM5100_GP5_LVL_MASK 0x0040 /* GP5_LVL */ +#define WM5100_GP5_LVL_SHIFT 6 /* GP5_LVL */ +#define WM5100_GP5_LVL_WIDTH 1 /* GP5_LVL */ +#define WM5100_GP5_FN_MASK 0x003F /* GP5_FN - [5:0] */ +#define WM5100_GP5_FN_SHIFT 0 /* GP5_FN - [5:0] */ +#define WM5100_GP5_FN_WIDTH 6 /* GP5_FN - [5:0] */ + +/* + * R3077 (0xC05) - GPIO CTRL 6 + */ +#define WM5100_GP6_DIR 0x8000 /* GP6_DIR */ +#define WM5100_GP6_DIR_MASK 0x8000 /* GP6_DIR */ +#define WM5100_GP6_DIR_SHIFT 15 /* GP6_DIR */ +#define WM5100_GP6_DIR_WIDTH 1 /* GP6_DIR */ +#define WM5100_GP6_PU 0x4000 /* GP6_PU */ +#define WM5100_GP6_PU_MASK 0x4000 /* GP6_PU */ +#define WM5100_GP6_PU_SHIFT 14 /* GP6_PU */ +#define WM5100_GP6_PU_WIDTH 1 /* GP6_PU */ +#define WM5100_GP6_PD 0x2000 /* GP6_PD */ +#define WM5100_GP6_PD_MASK 0x2000 /* GP6_PD */ +#define WM5100_GP6_PD_SHIFT 13 /* GP6_PD */ +#define WM5100_GP6_PD_WIDTH 1 /* GP6_PD */ +#define WM5100_GP6_POL 0x0400 /* GP6_POL */ +#define WM5100_GP6_POL_MASK 0x0400 /* GP6_POL */ +#define WM5100_GP6_POL_SHIFT 10 /* GP6_POL */ +#define WM5100_GP6_POL_WIDTH 1 /* GP6_POL */ +#define WM5100_GP6_OP_CFG 0x0200 /* GP6_OP_CFG */ +#define WM5100_GP6_OP_CFG_MASK 0x0200 /* GP6_OP_CFG */ +#define WM5100_GP6_OP_CFG_SHIFT 9 /* GP6_OP_CFG */ +#define WM5100_GP6_OP_CFG_WIDTH 1 /* GP6_OP_CFG */ +#define WM5100_GP6_DB 0x0100 /* GP6_DB */ +#define WM5100_GP6_DB_MASK 0x0100 /* GP6_DB */ +#define WM5100_GP6_DB_SHIFT 8 /* GP6_DB */ +#define WM5100_GP6_DB_WIDTH 1 /* GP6_DB */ +#define WM5100_GP6_LVL 0x0040 /* GP6_LVL */ +#define WM5100_GP6_LVL_MASK 0x0040 /* GP6_LVL */ +#define WM5100_GP6_LVL_SHIFT 6 /* GP6_LVL */ +#define WM5100_GP6_LVL_WIDTH 1 /* GP6_LVL */ +#define WM5100_GP6_FN_MASK 0x003F /* GP6_FN - [5:0] */ +#define WM5100_GP6_FN_SHIFT 0 /* GP6_FN - [5:0] */ +#define WM5100_GP6_FN_WIDTH 6 /* GP6_FN - [5:0] */ + +/* + * R3107 (0xC23) - Misc Pad Ctrl 1 + */ +#define WM5100_LDO1ENA_PD 0x8000 /* LDO1ENA_PD */ +#define WM5100_LDO1ENA_PD_MASK 0x8000 /* LDO1ENA_PD */ +#define WM5100_LDO1ENA_PD_SHIFT 15 /* LDO1ENA_PD */ +#define WM5100_LDO1ENA_PD_WIDTH 1 /* LDO1ENA_PD */ +#define WM5100_MCLK2_PD 0x2000 /* MCLK2_PD */ +#define WM5100_MCLK2_PD_MASK 0x2000 /* MCLK2_PD */ +#define WM5100_MCLK2_PD_SHIFT 13 /* MCLK2_PD */ +#define WM5100_MCLK2_PD_WIDTH 1 /* MCLK2_PD */ +#define WM5100_MCLK1_PD 0x1000 /* MCLK1_PD */ +#define WM5100_MCLK1_PD_MASK 0x1000 /* MCLK1_PD */ +#define WM5100_MCLK1_PD_SHIFT 12 /* MCLK1_PD */ +#define WM5100_MCLK1_PD_WIDTH 1 /* MCLK1_PD */ +#define WM5100_RESET_PU 0x0002 /* RESET_PU */ +#define WM5100_RESET_PU_MASK 0x0002 /* RESET_PU */ +#define WM5100_RESET_PU_SHIFT 1 /* RESET_PU */ +#define WM5100_RESET_PU_WIDTH 1 /* RESET_PU */ +#define WM5100_ADDR_PD 0x0001 /* ADDR_PD */ +#define WM5100_ADDR_PD_MASK 0x0001 /* ADDR_PD */ +#define WM5100_ADDR_PD_SHIFT 0 /* ADDR_PD */ +#define WM5100_ADDR_PD_WIDTH 1 /* ADDR_PD */ + +/* + * R3108 (0xC24) - Misc Pad Ctrl 2 + */ +#define WM5100_DMICDAT4_PD 0x0008 /* DMICDAT4_PD */ +#define WM5100_DMICDAT4_PD_MASK 0x0008 /* DMICDAT4_PD */ +#define WM5100_DMICDAT4_PD_SHIFT 3 /* DMICDAT4_PD */ +#define WM5100_DMICDAT4_PD_WIDTH 1 /* DMICDAT4_PD */ +#define WM5100_DMICDAT3_PD 0x0004 /* DMICDAT3_PD */ +#define WM5100_DMICDAT3_PD_MASK 0x0004 /* DMICDAT3_PD */ +#define WM5100_DMICDAT3_PD_SHIFT 2 /* DMICDAT3_PD */ +#define WM5100_DMICDAT3_PD_WIDTH 1 /* DMICDAT3_PD */ +#define WM5100_DMICDAT2_PD 0x0002 /* DMICDAT2_PD */ +#define WM5100_DMICDAT2_PD_MASK 0x0002 /* DMICDAT2_PD */ +#define WM5100_DMICDAT2_PD_SHIFT 1 /* DMICDAT2_PD */ +#define WM5100_DMICDAT2_PD_WIDTH 1 /* DMICDAT2_PD */ +#define WM5100_DMICDAT1_PD 0x0001 /* DMICDAT1_PD */ +#define WM5100_DMICDAT1_PD_MASK 0x0001 /* DMICDAT1_PD */ +#define WM5100_DMICDAT1_PD_SHIFT 0 /* DMICDAT1_PD */ +#define WM5100_DMICDAT1_PD_WIDTH 1 /* DMICDAT1_PD */ + +/* + * R3109 (0xC25) - Misc Pad Ctrl 3 + */ +#define WM5100_AIF1RXLRCLK_PU 0x0020 /* AIF1RXLRCLK_PU */ +#define WM5100_AIF1RXLRCLK_PU_MASK 0x0020 /* AIF1RXLRCLK_PU */ +#define WM5100_AIF1RXLRCLK_PU_SHIFT 5 /* AIF1RXLRCLK_PU */ +#define WM5100_AIF1RXLRCLK_PU_WIDTH 1 /* AIF1RXLRCLK_PU */ +#define WM5100_AIF1RXLRCLK_PD 0x0010 /* AIF1RXLRCLK_PD */ +#define WM5100_AIF1RXLRCLK_PD_MASK 0x0010 /* AIF1RXLRCLK_PD */ +#define WM5100_AIF1RXLRCLK_PD_SHIFT 4 /* AIF1RXLRCLK_PD */ +#define WM5100_AIF1RXLRCLK_PD_WIDTH 1 /* AIF1RXLRCLK_PD */ +#define WM5100_AIF1BCLK_PU 0x0008 /* AIF1BCLK_PU */ +#define WM5100_AIF1BCLK_PU_MASK 0x0008 /* AIF1BCLK_PU */ +#define WM5100_AIF1BCLK_PU_SHIFT 3 /* AIF1BCLK_PU */ +#define WM5100_AIF1BCLK_PU_WIDTH 1 /* AIF1BCLK_PU */ +#define WM5100_AIF1BCLK_PD 0x0004 /* AIF1BCLK_PD */ +#define WM5100_AIF1BCLK_PD_MASK 0x0004 /* AIF1BCLK_PD */ +#define WM5100_AIF1BCLK_PD_SHIFT 2 /* AIF1BCLK_PD */ +#define WM5100_AIF1BCLK_PD_WIDTH 1 /* AIF1BCLK_PD */ +#define WM5100_AIF1RXDAT_PU 0x0002 /* AIF1RXDAT_PU */ +#define WM5100_AIF1RXDAT_PU_MASK 0x0002 /* AIF1RXDAT_PU */ +#define WM5100_AIF1RXDAT_PU_SHIFT 1 /* AIF1RXDAT_PU */ +#define WM5100_AIF1RXDAT_PU_WIDTH 1 /* AIF1RXDAT_PU */ +#define WM5100_AIF1RXDAT_PD 0x0001 /* AIF1RXDAT_PD */ +#define WM5100_AIF1RXDAT_PD_MASK 0x0001 /* AIF1RXDAT_PD */ +#define WM5100_AIF1RXDAT_PD_SHIFT 0 /* AIF1RXDAT_PD */ +#define WM5100_AIF1RXDAT_PD_WIDTH 1 /* AIF1RXDAT_PD */ + +/* + * R3110 (0xC26) - Misc Pad Ctrl 4 + */ +#define WM5100_AIF2RXLRCLK_PU 0x0020 /* AIF2RXLRCLK_PU */ +#define WM5100_AIF2RXLRCLK_PU_MASK 0x0020 /* AIF2RXLRCLK_PU */ +#define WM5100_AIF2RXLRCLK_PU_SHIFT 5 /* AIF2RXLRCLK_PU */ +#define WM5100_AIF2RXLRCLK_PU_WIDTH 1 /* AIF2RXLRCLK_PU */ +#define WM5100_AIF2RXLRCLK_PD 0x0010 /* AIF2RXLRCLK_PD */ +#define WM5100_AIF2RXLRCLK_PD_MASK 0x0010 /* AIF2RXLRCLK_PD */ +#define WM5100_AIF2RXLRCLK_PD_SHIFT 4 /* AIF2RXLRCLK_PD */ +#define WM5100_AIF2RXLRCLK_PD_WIDTH 1 /* AIF2RXLRCLK_PD */ +#define WM5100_AIF2BCLK_PU 0x0008 /* AIF2BCLK_PU */ +#define WM5100_AIF2BCLK_PU_MASK 0x0008 /* AIF2BCLK_PU */ +#define WM5100_AIF2BCLK_PU_SHIFT 3 /* AIF2BCLK_PU */ +#define WM5100_AIF2BCLK_PU_WIDTH 1 /* AIF2BCLK_PU */ +#define WM5100_AIF2BCLK_PD 0x0004 /* AIF2BCLK_PD */ +#define WM5100_AIF2BCLK_PD_MASK 0x0004 /* AIF2BCLK_PD */ +#define WM5100_AIF2BCLK_PD_SHIFT 2 /* AIF2BCLK_PD */ +#define WM5100_AIF2BCLK_PD_WIDTH 1 /* AIF2BCLK_PD */ +#define WM5100_AIF2RXDAT_PU 0x0002 /* AIF2RXDAT_PU */ +#define WM5100_AIF2RXDAT_PU_MASK 0x0002 /* AIF2RXDAT_PU */ +#define WM5100_AIF2RXDAT_PU_SHIFT 1 /* AIF2RXDAT_PU */ +#define WM5100_AIF2RXDAT_PU_WIDTH 1 /* AIF2RXDAT_PU */ +#define WM5100_AIF2RXDAT_PD 0x0001 /* AIF2RXDAT_PD */ +#define WM5100_AIF2RXDAT_PD_MASK 0x0001 /* AIF2RXDAT_PD */ +#define WM5100_AIF2RXDAT_PD_SHIFT 0 /* AIF2RXDAT_PD */ +#define WM5100_AIF2RXDAT_PD_WIDTH 1 /* AIF2RXDAT_PD */ + +/* + * R3111 (0xC27) - Misc Pad Ctrl 5 + */ +#define WM5100_AIF3RXLRCLK_PU 0x0020 /* AIF3RXLRCLK_PU */ +#define WM5100_AIF3RXLRCLK_PU_MASK 0x0020 /* AIF3RXLRCLK_PU */ +#define WM5100_AIF3RXLRCLK_PU_SHIFT 5 /* AIF3RXLRCLK_PU */ +#define WM5100_AIF3RXLRCLK_PU_WIDTH 1 /* AIF3RXLRCLK_PU */ +#define WM5100_AIF3RXLRCLK_PD 0x0010 /* AIF3RXLRCLK_PD */ +#define WM5100_AIF3RXLRCLK_PD_MASK 0x0010 /* AIF3RXLRCLK_PD */ +#define WM5100_AIF3RXLRCLK_PD_SHIFT 4 /* AIF3RXLRCLK_PD */ +#define WM5100_AIF3RXLRCLK_PD_WIDTH 1 /* AIF3RXLRCLK_PD */ +#define WM5100_AIF3BCLK_PU 0x0008 /* AIF3BCLK_PU */ +#define WM5100_AIF3BCLK_PU_MASK 0x0008 /* AIF3BCLK_PU */ +#define WM5100_AIF3BCLK_PU_SHIFT 3 /* AIF3BCLK_PU */ +#define WM5100_AIF3BCLK_PU_WIDTH 1 /* AIF3BCLK_PU */ +#define WM5100_AIF3BCLK_PD 0x0004 /* AIF3BCLK_PD */ +#define WM5100_AIF3BCLK_PD_MASK 0x0004 /* AIF3BCLK_PD */ +#define WM5100_AIF3BCLK_PD_SHIFT 2 /* AIF3BCLK_PD */ +#define WM5100_AIF3BCLK_PD_WIDTH 1 /* AIF3BCLK_PD */ +#define WM5100_AIF3RXDAT_PU 0x0002 /* AIF3RXDAT_PU */ +#define WM5100_AIF3RXDAT_PU_MASK 0x0002 /* AIF3RXDAT_PU */ +#define WM5100_AIF3RXDAT_PU_SHIFT 1 /* AIF3RXDAT_PU */ +#define WM5100_AIF3RXDAT_PU_WIDTH 1 /* AIF3RXDAT_PU */ +#define WM5100_AIF3RXDAT_PD 0x0001 /* AIF3RXDAT_PD */ +#define WM5100_AIF3RXDAT_PD_MASK 0x0001 /* AIF3RXDAT_PD */ +#define WM5100_AIF3RXDAT_PD_SHIFT 0 /* AIF3RXDAT_PD */ +#define WM5100_AIF3RXDAT_PD_WIDTH 1 /* AIF3RXDAT_PD */ + +/* + * R3112 (0xC28) - Misc GPIO 1 + */ +#define WM5100_OPCLK_SEL_MASK 0x0003 /* OPCLK_SEL - [1:0] */ +#define WM5100_OPCLK_SEL_SHIFT 0 /* OPCLK_SEL - [1:0] */ +#define WM5100_OPCLK_SEL_WIDTH 2 /* OPCLK_SEL - [1:0] */ + +/* + * R3328 (0xD00) - Interrupt Status 1 + */ +#define WM5100_GP6_EINT 0x0020 /* GP6_EINT */ +#define WM5100_GP6_EINT_MASK 0x0020 /* GP6_EINT */ +#define WM5100_GP6_EINT_SHIFT 5 /* GP6_EINT */ +#define WM5100_GP6_EINT_WIDTH 1 /* GP6_EINT */ +#define WM5100_GP5_EINT 0x0010 /* GP5_EINT */ +#define WM5100_GP5_EINT_MASK 0x0010 /* GP5_EINT */ +#define WM5100_GP5_EINT_SHIFT 4 /* GP5_EINT */ +#define WM5100_GP5_EINT_WIDTH 1 /* GP5_EINT */ +#define WM5100_GP4_EINT 0x0008 /* GP4_EINT */ +#define WM5100_GP4_EINT_MASK 0x0008 /* GP4_EINT */ +#define WM5100_GP4_EINT_SHIFT 3 /* GP4_EINT */ +#define WM5100_GP4_EINT_WIDTH 1 /* GP4_EINT */ +#define WM5100_GP3_EINT 0x0004 /* GP3_EINT */ +#define WM5100_GP3_EINT_MASK 0x0004 /* GP3_EINT */ +#define WM5100_GP3_EINT_SHIFT 2 /* GP3_EINT */ +#define WM5100_GP3_EINT_WIDTH 1 /* GP3_EINT */ +#define WM5100_GP2_EINT 0x0002 /* GP2_EINT */ +#define WM5100_GP2_EINT_MASK 0x0002 /* GP2_EINT */ +#define WM5100_GP2_EINT_SHIFT 1 /* GP2_EINT */ +#define WM5100_GP2_EINT_WIDTH 1 /* GP2_EINT */ +#define WM5100_GP1_EINT 0x0001 /* GP1_EINT */ +#define WM5100_GP1_EINT_MASK 0x0001 /* GP1_EINT */ +#define WM5100_GP1_EINT_SHIFT 0 /* GP1_EINT */ +#define WM5100_GP1_EINT_WIDTH 1 /* GP1_EINT */ + +/* + * R3329 (0xD01) - Interrupt Status 2 + */ +#define WM5100_DSP_IRQ6_EINT 0x0020 /* DSP_IRQ6_EINT */ +#define WM5100_DSP_IRQ6_EINT_MASK 0x0020 /* DSP_IRQ6_EINT */ +#define WM5100_DSP_IRQ6_EINT_SHIFT 5 /* DSP_IRQ6_EINT */ +#define WM5100_DSP_IRQ6_EINT_WIDTH 1 /* DSP_IRQ6_EINT */ +#define WM5100_DSP_IRQ5_EINT 0x0010 /* DSP_IRQ5_EINT */ +#define WM5100_DSP_IRQ5_EINT_MASK 0x0010 /* DSP_IRQ5_EINT */ +#define WM5100_DSP_IRQ5_EINT_SHIFT 4 /* DSP_IRQ5_EINT */ +#define WM5100_DSP_IRQ5_EINT_WIDTH 1 /* DSP_IRQ5_EINT */ +#define WM5100_DSP_IRQ4_EINT 0x0008 /* DSP_IRQ4_EINT */ +#define WM5100_DSP_IRQ4_EINT_MASK 0x0008 /* DSP_IRQ4_EINT */ +#define WM5100_DSP_IRQ4_EINT_SHIFT 3 /* DSP_IRQ4_EINT */ +#define WM5100_DSP_IRQ4_EINT_WIDTH 1 /* DSP_IRQ4_EINT */ +#define WM5100_DSP_IRQ3_EINT 0x0004 /* DSP_IRQ3_EINT */ +#define WM5100_DSP_IRQ3_EINT_MASK 0x0004 /* DSP_IRQ3_EINT */ +#define WM5100_DSP_IRQ3_EINT_SHIFT 2 /* DSP_IRQ3_EINT */ +#define WM5100_DSP_IRQ3_EINT_WIDTH 1 /* DSP_IRQ3_EINT */ +#define WM5100_DSP_IRQ2_EINT 0x0002 /* DSP_IRQ2_EINT */ +#define WM5100_DSP_IRQ2_EINT_MASK 0x0002 /* DSP_IRQ2_EINT */ +#define WM5100_DSP_IRQ2_EINT_SHIFT 1 /* DSP_IRQ2_EINT */ +#define WM5100_DSP_IRQ2_EINT_WIDTH 1 /* DSP_IRQ2_EINT */ +#define WM5100_DSP_IRQ1_EINT 0x0001 /* DSP_IRQ1_EINT */ +#define WM5100_DSP_IRQ1_EINT_MASK 0x0001 /* DSP_IRQ1_EINT */ +#define WM5100_DSP_IRQ1_EINT_SHIFT 0 /* DSP_IRQ1_EINT */ +#define WM5100_DSP_IRQ1_EINT_WIDTH 1 /* DSP_IRQ1_EINT */ + +/* + * R3330 (0xD02) - Interrupt Status 3 + */ +#define WM5100_SPK_SHUTDOWN_WARN_EINT 0x8000 /* SPK_SHUTDOWN_WARN_EINT */ +#define WM5100_SPK_SHUTDOWN_WARN_EINT_MASK 0x8000 /* SPK_SHUTDOWN_WARN_EINT */ +#define WM5100_SPK_SHUTDOWN_WARN_EINT_SHIFT 15 /* SPK_SHUTDOWN_WARN_EINT */ +#define WM5100_SPK_SHUTDOWN_WARN_EINT_WIDTH 1 /* SPK_SHUTDOWN_WARN_EINT */ +#define WM5100_SPK_SHUTDOWN_EINT 0x4000 /* SPK_SHUTDOWN_EINT */ +#define WM5100_SPK_SHUTDOWN_EINT_MASK 0x4000 /* SPK_SHUTDOWN_EINT */ +#define WM5100_SPK_SHUTDOWN_EINT_SHIFT 14 /* SPK_SHUTDOWN_EINT */ +#define WM5100_SPK_SHUTDOWN_EINT_WIDTH 1 /* SPK_SHUTDOWN_EINT */ +#define WM5100_HPDET_EINT 0x2000 /* HPDET_EINT */ +#define WM5100_HPDET_EINT_MASK 0x2000 /* HPDET_EINT */ +#define WM5100_HPDET_EINT_SHIFT 13 /* HPDET_EINT */ +#define WM5100_HPDET_EINT_WIDTH 1 /* HPDET_EINT */ +#define WM5100_ACCDET_EINT 0x1000 /* ACCDET_EINT */ +#define WM5100_ACCDET_EINT_MASK 0x1000 /* ACCDET_EINT */ +#define WM5100_ACCDET_EINT_SHIFT 12 /* ACCDET_EINT */ +#define WM5100_ACCDET_EINT_WIDTH 1 /* ACCDET_EINT */ +#define WM5100_DRC_SIG_DET_EINT 0x0200 /* DRC_SIG_DET_EINT */ +#define WM5100_DRC_SIG_DET_EINT_MASK 0x0200 /* DRC_SIG_DET_EINT */ +#define WM5100_DRC_SIG_DET_EINT_SHIFT 9 /* DRC_SIG_DET_EINT */ +#define WM5100_DRC_SIG_DET_EINT_WIDTH 1 /* DRC_SIG_DET_EINT */ +#define WM5100_ASRC2_LOCK_EINT 0x0100 /* ASRC2_LOCK_EINT */ +#define WM5100_ASRC2_LOCK_EINT_MASK 0x0100 /* ASRC2_LOCK_EINT */ +#define WM5100_ASRC2_LOCK_EINT_SHIFT 8 /* ASRC2_LOCK_EINT */ +#define WM5100_ASRC2_LOCK_EINT_WIDTH 1 /* ASRC2_LOCK_EINT */ +#define WM5100_ASRC1_LOCK_EINT 0x0080 /* ASRC1_LOCK_EINT */ +#define WM5100_ASRC1_LOCK_EINT_MASK 0x0080 /* ASRC1_LOCK_EINT */ +#define WM5100_ASRC1_LOCK_EINT_SHIFT 7 /* ASRC1_LOCK_EINT */ +#define WM5100_ASRC1_LOCK_EINT_WIDTH 1 /* ASRC1_LOCK_EINT */ +#define WM5100_FLL2_LOCK_EINT 0x0008 /* FLL2_LOCK_EINT */ +#define WM5100_FLL2_LOCK_EINT_MASK 0x0008 /* FLL2_LOCK_EINT */ +#define WM5100_FLL2_LOCK_EINT_SHIFT 3 /* FLL2_LOCK_EINT */ +#define WM5100_FLL2_LOCK_EINT_WIDTH 1 /* FLL2_LOCK_EINT */ +#define WM5100_FLL1_LOCK_EINT 0x0004 /* FLL1_LOCK_EINT */ +#define WM5100_FLL1_LOCK_EINT_MASK 0x0004 /* FLL1_LOCK_EINT */ +#define WM5100_FLL1_LOCK_EINT_SHIFT 2 /* FLL1_LOCK_EINT */ +#define WM5100_FLL1_LOCK_EINT_WIDTH 1 /* FLL1_LOCK_EINT */ +#define WM5100_CLKGEN_ERR_EINT 0x0002 /* CLKGEN_ERR_EINT */ +#define WM5100_CLKGEN_ERR_EINT_MASK 0x0002 /* CLKGEN_ERR_EINT */ +#define WM5100_CLKGEN_ERR_EINT_SHIFT 1 /* CLKGEN_ERR_EINT */ +#define WM5100_CLKGEN_ERR_EINT_WIDTH 1 /* CLKGEN_ERR_EINT */ +#define WM5100_CLKGEN_ERR_ASYNC_EINT 0x0001 /* CLKGEN_ERR_ASYNC_EINT */ +#define WM5100_CLKGEN_ERR_ASYNC_EINT_MASK 0x0001 /* CLKGEN_ERR_ASYNC_EINT */ +#define WM5100_CLKGEN_ERR_ASYNC_EINT_SHIFT 0 /* CLKGEN_ERR_ASYNC_EINT */ +#define WM5100_CLKGEN_ERR_ASYNC_EINT_WIDTH 1 /* CLKGEN_ERR_ASYNC_EINT */ + +/* + * R3331 (0xD03) - Interrupt Status 4 + */ +#define WM5100_AIF3_ERR_EINT 0x2000 /* AIF3_ERR_EINT */ +#define WM5100_AIF3_ERR_EINT_MASK 0x2000 /* AIF3_ERR_EINT */ +#define WM5100_AIF3_ERR_EINT_SHIFT 13 /* AIF3_ERR_EINT */ +#define WM5100_AIF3_ERR_EINT_WIDTH 1 /* AIF3_ERR_EINT */ +#define WM5100_AIF2_ERR_EINT 0x1000 /* AIF2_ERR_EINT */ +#define WM5100_AIF2_ERR_EINT_MASK 0x1000 /* AIF2_ERR_EINT */ +#define WM5100_AIF2_ERR_EINT_SHIFT 12 /* AIF2_ERR_EINT */ +#define WM5100_AIF2_ERR_EINT_WIDTH 1 /* AIF2_ERR_EINT */ +#define WM5100_AIF1_ERR_EINT 0x0800 /* AIF1_ERR_EINT */ +#define WM5100_AIF1_ERR_EINT_MASK 0x0800 /* AIF1_ERR_EINT */ +#define WM5100_AIF1_ERR_EINT_SHIFT 11 /* AIF1_ERR_EINT */ +#define WM5100_AIF1_ERR_EINT_WIDTH 1 /* AIF1_ERR_EINT */ +#define WM5100_CTRLIF_ERR_EINT 0x0400 /* CTRLIF_ERR_EINT */ +#define WM5100_CTRLIF_ERR_EINT_MASK 0x0400 /* CTRLIF_ERR_EINT */ +#define WM5100_CTRLIF_ERR_EINT_SHIFT 10 /* CTRLIF_ERR_EINT */ +#define WM5100_CTRLIF_ERR_EINT_WIDTH 1 /* CTRLIF_ERR_EINT */ +#define WM5100_ISRC2_UNDERCLOCKED_EINT 0x0200 /* ISRC2_UNDERCLOCKED_EINT */ +#define WM5100_ISRC2_UNDERCLOCKED_EINT_MASK 0x0200 /* ISRC2_UNDERCLOCKED_EINT */ +#define WM5100_ISRC2_UNDERCLOCKED_EINT_SHIFT 9 /* ISRC2_UNDERCLOCKED_EINT */ +#define WM5100_ISRC2_UNDERCLOCKED_EINT_WIDTH 1 /* ISRC2_UNDERCLOCKED_EINT */ +#define WM5100_ISRC1_UNDERCLOCKED_EINT 0x0100 /* ISRC1_UNDERCLOCKED_EINT */ +#define WM5100_ISRC1_UNDERCLOCKED_EINT_MASK 0x0100 /* ISRC1_UNDERCLOCKED_EINT */ +#define WM5100_ISRC1_UNDERCLOCKED_EINT_SHIFT 8 /* ISRC1_UNDERCLOCKED_EINT */ +#define WM5100_ISRC1_UNDERCLOCKED_EINT_WIDTH 1 /* ISRC1_UNDERCLOCKED_EINT */ +#define WM5100_FX_UNDERCLOCKED_EINT 0x0080 /* FX_UNDERCLOCKED_EINT */ +#define WM5100_FX_UNDERCLOCKED_EINT_MASK 0x0080 /* FX_UNDERCLOCKED_EINT */ +#define WM5100_FX_UNDERCLOCKED_EINT_SHIFT 7 /* FX_UNDERCLOCKED_EINT */ +#define WM5100_FX_UNDERCLOCKED_EINT_WIDTH 1 /* FX_UNDERCLOCKED_EINT */ +#define WM5100_AIF3_UNDERCLOCKED_EINT 0x0040 /* AIF3_UNDERCLOCKED_EINT */ +#define WM5100_AIF3_UNDERCLOCKED_EINT_MASK 0x0040 /* AIF3_UNDERCLOCKED_EINT */ +#define WM5100_AIF3_UNDERCLOCKED_EINT_SHIFT 6 /* AIF3_UNDERCLOCKED_EINT */ +#define WM5100_AIF3_UNDERCLOCKED_EINT_WIDTH 1 /* AIF3_UNDERCLOCKED_EINT */ +#define WM5100_AIF2_UNDERCLOCKED_EINT 0x0020 /* AIF2_UNDERCLOCKED_EINT */ +#define WM5100_AIF2_UNDERCLOCKED_EINT_MASK 0x0020 /* AIF2_UNDERCLOCKED_EINT */ +#define WM5100_AIF2_UNDERCLOCKED_EINT_SHIFT 5 /* AIF2_UNDERCLOCKED_EINT */ +#define WM5100_AIF2_UNDERCLOCKED_EINT_WIDTH 1 /* AIF2_UNDERCLOCKED_EINT */ +#define WM5100_AIF1_UNDERCLOCKED_EINT 0x0010 /* AIF1_UNDERCLOCKED_EINT */ +#define WM5100_AIF1_UNDERCLOCKED_EINT_MASK 0x0010 /* AIF1_UNDERCLOCKED_EINT */ +#define WM5100_AIF1_UNDERCLOCKED_EINT_SHIFT 4 /* AIF1_UNDERCLOCKED_EINT */ +#define WM5100_AIF1_UNDERCLOCKED_EINT_WIDTH 1 /* AIF1_UNDERCLOCKED_EINT */ +#define WM5100_ASRC_UNDERCLOCKED_EINT 0x0008 /* ASRC_UNDERCLOCKED_EINT */ +#define WM5100_ASRC_UNDERCLOCKED_EINT_MASK 0x0008 /* ASRC_UNDERCLOCKED_EINT */ +#define WM5100_ASRC_UNDERCLOCKED_EINT_SHIFT 3 /* ASRC_UNDERCLOCKED_EINT */ +#define WM5100_ASRC_UNDERCLOCKED_EINT_WIDTH 1 /* ASRC_UNDERCLOCKED_EINT */ +#define WM5100_DAC_UNDERCLOCKED_EINT 0x0004 /* DAC_UNDERCLOCKED_EINT */ +#define WM5100_DAC_UNDERCLOCKED_EINT_MASK 0x0004 /* DAC_UNDERCLOCKED_EINT */ +#define WM5100_DAC_UNDERCLOCKED_EINT_SHIFT 2 /* DAC_UNDERCLOCKED_EINT */ +#define WM5100_DAC_UNDERCLOCKED_EINT_WIDTH 1 /* DAC_UNDERCLOCKED_EINT */ +#define WM5100_ADC_UNDERCLOCKED_EINT 0x0002 /* ADC_UNDERCLOCKED_EINT */ +#define WM5100_ADC_UNDERCLOCKED_EINT_MASK 0x0002 /* ADC_UNDERCLOCKED_EINT */ +#define WM5100_ADC_UNDERCLOCKED_EINT_SHIFT 1 /* ADC_UNDERCLOCKED_EINT */ +#define WM5100_ADC_UNDERCLOCKED_EINT_WIDTH 1 /* ADC_UNDERCLOCKED_EINT */ +#define WM5100_MIXER_UNDERCLOCKED_EINT 0x0001 /* MIXER_UNDERCLOCKED_EINT */ +#define WM5100_MIXER_UNDERCLOCKED_EINT_MASK 0x0001 /* MIXER_UNDERCLOCKED_EINT */ +#define WM5100_MIXER_UNDERCLOCKED_EINT_SHIFT 0 /* MIXER_UNDERCLOCKED_EINT */ +#define WM5100_MIXER_UNDERCLOCKED_EINT_WIDTH 1 /* MIXER_UNDERCLOCKED_EINT */ + +/* + * R3332 (0xD04) - Interrupt Raw Status 2 + */ +#define WM5100_DSP_IRQ6_STS 0x0020 /* DSP_IRQ6_STS */ +#define WM5100_DSP_IRQ6_STS_MASK 0x0020 /* DSP_IRQ6_STS */ +#define WM5100_DSP_IRQ6_STS_SHIFT 5 /* DSP_IRQ6_STS */ +#define WM5100_DSP_IRQ6_STS_WIDTH 1 /* DSP_IRQ6_STS */ +#define WM5100_DSP_IRQ5_STS 0x0010 /* DSP_IRQ5_STS */ +#define WM5100_DSP_IRQ5_STS_MASK 0x0010 /* DSP_IRQ5_STS */ +#define WM5100_DSP_IRQ5_STS_SHIFT 4 /* DSP_IRQ5_STS */ +#define WM5100_DSP_IRQ5_STS_WIDTH 1 /* DSP_IRQ5_STS */ +#define WM5100_DSP_IRQ4_STS 0x0008 /* DSP_IRQ4_STS */ +#define WM5100_DSP_IRQ4_STS_MASK 0x0008 /* DSP_IRQ4_STS */ +#define WM5100_DSP_IRQ4_STS_SHIFT 3 /* DSP_IRQ4_STS */ +#define WM5100_DSP_IRQ4_STS_WIDTH 1 /* DSP_IRQ4_STS */ +#define WM5100_DSP_IRQ3_STS 0x0004 /* DSP_IRQ3_STS */ +#define WM5100_DSP_IRQ3_STS_MASK 0x0004 /* DSP_IRQ3_STS */ +#define WM5100_DSP_IRQ3_STS_SHIFT 2 /* DSP_IRQ3_STS */ +#define WM5100_DSP_IRQ3_STS_WIDTH 1 /* DSP_IRQ3_STS */ +#define WM5100_DSP_IRQ2_STS 0x0002 /* DSP_IRQ2_STS */ +#define WM5100_DSP_IRQ2_STS_MASK 0x0002 /* DSP_IRQ2_STS */ +#define WM5100_DSP_IRQ2_STS_SHIFT 1 /* DSP_IRQ2_STS */ +#define WM5100_DSP_IRQ2_STS_WIDTH 1 /* DSP_IRQ2_STS */ +#define WM5100_DSP_IRQ1_STS 0x0001 /* DSP_IRQ1_STS */ +#define WM5100_DSP_IRQ1_STS_MASK 0x0001 /* DSP_IRQ1_STS */ +#define WM5100_DSP_IRQ1_STS_SHIFT 0 /* DSP_IRQ1_STS */ +#define WM5100_DSP_IRQ1_STS_WIDTH 1 /* DSP_IRQ1_STS */ + +/* + * R3333 (0xD05) - Interrupt Raw Status 3 + */ +#define WM5100_SPK_SHUTDOWN_WARN_STS 0x8000 /* SPK_SHUTDOWN_WARN_STS */ +#define WM5100_SPK_SHUTDOWN_WARN_STS_MASK 0x8000 /* SPK_SHUTDOWN_WARN_STS */ +#define WM5100_SPK_SHUTDOWN_WARN_STS_SHIFT 15 /* SPK_SHUTDOWN_WARN_STS */ +#define WM5100_SPK_SHUTDOWN_WARN_STS_WIDTH 1 /* SPK_SHUTDOWN_WARN_STS */ +#define WM5100_SPK_SHUTDOWN_STS 0x4000 /* SPK_SHUTDOWN_STS */ +#define WM5100_SPK_SHUTDOWN_STS_MASK 0x4000 /* SPK_SHUTDOWN_STS */ +#define WM5100_SPK_SHUTDOWN_STS_SHIFT 14 /* SPK_SHUTDOWN_STS */ +#define WM5100_SPK_SHUTDOWN_STS_WIDTH 1 /* SPK_SHUTDOWN_STS */ +#define WM5100_HPDET_STS 0x2000 /* HPDET_STS */ +#define WM5100_HPDET_STS_MASK 0x2000 /* HPDET_STS */ +#define WM5100_HPDET_STS_SHIFT 13 /* HPDET_STS */ +#define WM5100_HPDET_STS_WIDTH 1 /* HPDET_STS */ +#define WM5100_DRC_SID_DET_STS 0x0200 /* DRC_SID_DET_STS */ +#define WM5100_DRC_SID_DET_STS_MASK 0x0200 /* DRC_SID_DET_STS */ +#define WM5100_DRC_SID_DET_STS_SHIFT 9 /* DRC_SID_DET_STS */ +#define WM5100_DRC_SID_DET_STS_WIDTH 1 /* DRC_SID_DET_STS */ +#define WM5100_ASRC2_LOCK_STS 0x0100 /* ASRC2_LOCK_STS */ +#define WM5100_ASRC2_LOCK_STS_MASK 0x0100 /* ASRC2_LOCK_STS */ +#define WM5100_ASRC2_LOCK_STS_SHIFT 8 /* ASRC2_LOCK_STS */ +#define WM5100_ASRC2_LOCK_STS_WIDTH 1 /* ASRC2_LOCK_STS */ +#define WM5100_ASRC1_LOCK_STS 0x0080 /* ASRC1_LOCK_STS */ +#define WM5100_ASRC1_LOCK_STS_MASK 0x0080 /* ASRC1_LOCK_STS */ +#define WM5100_ASRC1_LOCK_STS_SHIFT 7 /* ASRC1_LOCK_STS */ +#define WM5100_ASRC1_LOCK_STS_WIDTH 1 /* ASRC1_LOCK_STS */ +#define WM5100_FLL2_LOCK_STS 0x0008 /* FLL2_LOCK_STS */ +#define WM5100_FLL2_LOCK_STS_MASK 0x0008 /* FLL2_LOCK_STS */ +#define WM5100_FLL2_LOCK_STS_SHIFT 3 /* FLL2_LOCK_STS */ +#define WM5100_FLL2_LOCK_STS_WIDTH 1 /* FLL2_LOCK_STS */ +#define WM5100_FLL1_LOCK_STS 0x0004 /* FLL1_LOCK_STS */ +#define WM5100_FLL1_LOCK_STS_MASK 0x0004 /* FLL1_LOCK_STS */ +#define WM5100_FLL1_LOCK_STS_SHIFT 2 /* FLL1_LOCK_STS */ +#define WM5100_FLL1_LOCK_STS_WIDTH 1 /* FLL1_LOCK_STS */ +#define WM5100_CLKGEN_ERR_STS 0x0002 /* CLKGEN_ERR_STS */ +#define WM5100_CLKGEN_ERR_STS_MASK 0x0002 /* CLKGEN_ERR_STS */ +#define WM5100_CLKGEN_ERR_STS_SHIFT 1 /* CLKGEN_ERR_STS */ +#define WM5100_CLKGEN_ERR_STS_WIDTH 1 /* CLKGEN_ERR_STS */ +#define WM5100_CLKGEN_ERR_ASYNC_STS 0x0001 /* CLKGEN_ERR_ASYNC_STS */ +#define WM5100_CLKGEN_ERR_ASYNC_STS_MASK 0x0001 /* CLKGEN_ERR_ASYNC_STS */ +#define WM5100_CLKGEN_ERR_ASYNC_STS_SHIFT 0 /* CLKGEN_ERR_ASYNC_STS */ +#define WM5100_CLKGEN_ERR_ASYNC_STS_WIDTH 1 /* CLKGEN_ERR_ASYNC_STS */ + +/* + * R3334 (0xD06) - Interrupt Raw Status 4 + */ +#define WM5100_AIF3_ERR_STS 0x2000 /* AIF3_ERR_STS */ +#define WM5100_AIF3_ERR_STS_MASK 0x2000 /* AIF3_ERR_STS */ +#define WM5100_AIF3_ERR_STS_SHIFT 13 /* AIF3_ERR_STS */ +#define WM5100_AIF3_ERR_STS_WIDTH 1 /* AIF3_ERR_STS */ +#define WM5100_AIF2_ERR_STS 0x1000 /* AIF2_ERR_STS */ +#define WM5100_AIF2_ERR_STS_MASK 0x1000 /* AIF2_ERR_STS */ +#define WM5100_AIF2_ERR_STS_SHIFT 12 /* AIF2_ERR_STS */ +#define WM5100_AIF2_ERR_STS_WIDTH 1 /* AIF2_ERR_STS */ +#define WM5100_AIF1_ERR_STS 0x0800 /* AIF1_ERR_STS */ +#define WM5100_AIF1_ERR_STS_MASK 0x0800 /* AIF1_ERR_STS */ +#define WM5100_AIF1_ERR_STS_SHIFT 11 /* AIF1_ERR_STS */ +#define WM5100_AIF1_ERR_STS_WIDTH 1 /* AIF1_ERR_STS */ +#define WM5100_CTRLIF_ERR_STS 0x0400 /* CTRLIF_ERR_STS */ +#define WM5100_CTRLIF_ERR_STS_MASK 0x0400 /* CTRLIF_ERR_STS */ +#define WM5100_CTRLIF_ERR_STS_SHIFT 10 /* CTRLIF_ERR_STS */ +#define WM5100_CTRLIF_ERR_STS_WIDTH 1 /* CTRLIF_ERR_STS */ +#define WM5100_ISRC2_UNDERCLOCKED_STS 0x0200 /* ISRC2_UNDERCLOCKED_STS */ +#define WM5100_ISRC2_UNDERCLOCKED_STS_MASK 0x0200 /* ISRC2_UNDERCLOCKED_STS */ +#define WM5100_ISRC2_UNDERCLOCKED_STS_SHIFT 9 /* ISRC2_UNDERCLOCKED_STS */ +#define WM5100_ISRC2_UNDERCLOCKED_STS_WIDTH 1 /* ISRC2_UNDERCLOCKED_STS */ +#define WM5100_ISRC1_UNDERCLOCKED_STS 0x0100 /* ISRC1_UNDERCLOCKED_STS */ +#define WM5100_ISRC1_UNDERCLOCKED_STS_MASK 0x0100 /* ISRC1_UNDERCLOCKED_STS */ +#define WM5100_ISRC1_UNDERCLOCKED_STS_SHIFT 8 /* ISRC1_UNDERCLOCKED_STS */ +#define WM5100_ISRC1_UNDERCLOCKED_STS_WIDTH 1 /* ISRC1_UNDERCLOCKED_STS */ +#define WM5100_FX_UNDERCLOCKED_STS 0x0080 /* FX_UNDERCLOCKED_STS */ +#define WM5100_FX_UNDERCLOCKED_STS_MASK 0x0080 /* FX_UNDERCLOCKED_STS */ +#define WM5100_FX_UNDERCLOCKED_STS_SHIFT 7 /* FX_UNDERCLOCKED_STS */ +#define WM5100_FX_UNDERCLOCKED_STS_WIDTH 1 /* FX_UNDERCLOCKED_STS */ +#define WM5100_AIF3_UNDERCLOCKED_STS 0x0040 /* AIF3_UNDERCLOCKED_STS */ +#define WM5100_AIF3_UNDERCLOCKED_STS_MASK 0x0040 /* AIF3_UNDERCLOCKED_STS */ +#define WM5100_AIF3_UNDERCLOCKED_STS_SHIFT 6 /* AIF3_UNDERCLOCKED_STS */ +#define WM5100_AIF3_UNDERCLOCKED_STS_WIDTH 1 /* AIF3_UNDERCLOCKED_STS */ +#define WM5100_AIF2_UNDERCLOCKED_STS 0x0020 /* AIF2_UNDERCLOCKED_STS */ +#define WM5100_AIF2_UNDERCLOCKED_STS_MASK 0x0020 /* AIF2_UNDERCLOCKED_STS */ +#define WM5100_AIF2_UNDERCLOCKED_STS_SHIFT 5 /* AIF2_UNDERCLOCKED_STS */ +#define WM5100_AIF2_UNDERCLOCKED_STS_WIDTH 1 /* AIF2_UNDERCLOCKED_STS */ +#define WM5100_AIF1_UNDERCLOCKED_STS 0x0010 /* AIF1_UNDERCLOCKED_STS */ +#define WM5100_AIF1_UNDERCLOCKED_STS_MASK 0x0010 /* AIF1_UNDERCLOCKED_STS */ +#define WM5100_AIF1_UNDERCLOCKED_STS_SHIFT 4 /* AIF1_UNDERCLOCKED_STS */ +#define WM5100_AIF1_UNDERCLOCKED_STS_WIDTH 1 /* AIF1_UNDERCLOCKED_STS */ +#define WM5100_ASRC_UNDERCLOCKED_STS 0x0008 /* ASRC_UNDERCLOCKED_STS */ +#define WM5100_ASRC_UNDERCLOCKED_STS_MASK 0x0008 /* ASRC_UNDERCLOCKED_STS */ +#define WM5100_ASRC_UNDERCLOCKED_STS_SHIFT 3 /* ASRC_UNDERCLOCKED_STS */ +#define WM5100_ASRC_UNDERCLOCKED_STS_WIDTH 1 /* ASRC_UNDERCLOCKED_STS */ +#define WM5100_DAC_UNDERCLOCKED_STS 0x0004 /* DAC_UNDERCLOCKED_STS */ +#define WM5100_DAC_UNDERCLOCKED_STS_MASK 0x0004 /* DAC_UNDERCLOCKED_STS */ +#define WM5100_DAC_UNDERCLOCKED_STS_SHIFT 2 /* DAC_UNDERCLOCKED_STS */ +#define WM5100_DAC_UNDERCLOCKED_STS_WIDTH 1 /* DAC_UNDERCLOCKED_STS */ +#define WM5100_ADC_UNDERCLOCKED_STS 0x0002 /* ADC_UNDERCLOCKED_STS */ +#define WM5100_ADC_UNDERCLOCKED_STS_MASK 0x0002 /* ADC_UNDERCLOCKED_STS */ +#define WM5100_ADC_UNDERCLOCKED_STS_SHIFT 1 /* ADC_UNDERCLOCKED_STS */ +#define WM5100_ADC_UNDERCLOCKED_STS_WIDTH 1 /* ADC_UNDERCLOCKED_STS */ +#define WM5100_MIXER_UNDERCLOCKED_STS 0x0001 /* MIXER_UNDERCLOCKED_STS */ +#define WM5100_MIXER_UNDERCLOCKED_STS_MASK 0x0001 /* MIXER_UNDERCLOCKED_STS */ +#define WM5100_MIXER_UNDERCLOCKED_STS_SHIFT 0 /* MIXER_UNDERCLOCKED_STS */ +#define WM5100_MIXER_UNDERCLOCKED_STS_WIDTH 1 /* MIXER_UNDERCLOCKED_STS */ + +/* + * R3335 (0xD07) - Interrupt Status 1 Mask + */ +#define WM5100_IM_GP6_EINT 0x0020 /* IM_GP6_EINT */ +#define WM5100_IM_GP6_EINT_MASK 0x0020 /* IM_GP6_EINT */ +#define WM5100_IM_GP6_EINT_SHIFT 5 /* IM_GP6_EINT */ +#define WM5100_IM_GP6_EINT_WIDTH 1 /* IM_GP6_EINT */ +#define WM5100_IM_GP5_EINT 0x0010 /* IM_GP5_EINT */ +#define WM5100_IM_GP5_EINT_MASK 0x0010 /* IM_GP5_EINT */ +#define WM5100_IM_GP5_EINT_SHIFT 4 /* IM_GP5_EINT */ +#define WM5100_IM_GP5_EINT_WIDTH 1 /* IM_GP5_EINT */ +#define WM5100_IM_GP4_EINT 0x0008 /* IM_GP4_EINT */ +#define WM5100_IM_GP4_EINT_MASK 0x0008 /* IM_GP4_EINT */ +#define WM5100_IM_GP4_EINT_SHIFT 3 /* IM_GP4_EINT */ +#define WM5100_IM_GP4_EINT_WIDTH 1 /* IM_GP4_EINT */ +#define WM5100_IM_GP3_EINT 0x0004 /* IM_GP3_EINT */ +#define WM5100_IM_GP3_EINT_MASK 0x0004 /* IM_GP3_EINT */ +#define WM5100_IM_GP3_EINT_SHIFT 2 /* IM_GP3_EINT */ +#define WM5100_IM_GP3_EINT_WIDTH 1 /* IM_GP3_EINT */ +#define WM5100_IM_GP2_EINT 0x0002 /* IM_GP2_EINT */ +#define WM5100_IM_GP2_EINT_MASK 0x0002 /* IM_GP2_EINT */ +#define WM5100_IM_GP2_EINT_SHIFT 1 /* IM_GP2_EINT */ +#define WM5100_IM_GP2_EINT_WIDTH 1 /* IM_GP2_EINT */ +#define WM5100_IM_GP1_EINT 0x0001 /* IM_GP1_EINT */ +#define WM5100_IM_GP1_EINT_MASK 0x0001 /* IM_GP1_EINT */ +#define WM5100_IM_GP1_EINT_SHIFT 0 /* IM_GP1_EINT */ +#define WM5100_IM_GP1_EINT_WIDTH 1 /* IM_GP1_EINT */ + +/* + * R3336 (0xD08) - Interrupt Status 2 Mask + */ +#define WM5100_IM_DSP_IRQ6_EINT 0x0020 /* IM_DSP_IRQ6_EINT */ +#define WM5100_IM_DSP_IRQ6_EINT_MASK 0x0020 /* IM_DSP_IRQ6_EINT */ +#define WM5100_IM_DSP_IRQ6_EINT_SHIFT 5 /* IM_DSP_IRQ6_EINT */ +#define WM5100_IM_DSP_IRQ6_EINT_WIDTH 1 /* IM_DSP_IRQ6_EINT */ +#define WM5100_IM_DSP_IRQ5_EINT 0x0010 /* IM_DSP_IRQ5_EINT */ +#define WM5100_IM_DSP_IRQ5_EINT_MASK 0x0010 /* IM_DSP_IRQ5_EINT */ +#define WM5100_IM_DSP_IRQ5_EINT_SHIFT 4 /* IM_DSP_IRQ5_EINT */ +#define WM5100_IM_DSP_IRQ5_EINT_WIDTH 1 /* IM_DSP_IRQ5_EINT */ +#define WM5100_IM_DSP_IRQ4_EINT 0x0008 /* IM_DSP_IRQ4_EINT */ +#define WM5100_IM_DSP_IRQ4_EINT_MASK 0x0008 /* IM_DSP_IRQ4_EINT */ +#define WM5100_IM_DSP_IRQ4_EINT_SHIFT 3 /* IM_DSP_IRQ4_EINT */ +#define WM5100_IM_DSP_IRQ4_EINT_WIDTH 1 /* IM_DSP_IRQ4_EINT */ +#define WM5100_IM_DSP_IRQ3_EINT 0x0004 /* IM_DSP_IRQ3_EINT */ +#define WM5100_IM_DSP_IRQ3_EINT_MASK 0x0004 /* IM_DSP_IRQ3_EINT */ +#define WM5100_IM_DSP_IRQ3_EINT_SHIFT 2 /* IM_DSP_IRQ3_EINT */ +#define WM5100_IM_DSP_IRQ3_EINT_WIDTH 1 /* IM_DSP_IRQ3_EINT */ +#define WM5100_IM_DSP_IRQ2_EINT 0x0002 /* IM_DSP_IRQ2_EINT */ +#define WM5100_IM_DSP_IRQ2_EINT_MASK 0x0002 /* IM_DSP_IRQ2_EINT */ +#define WM5100_IM_DSP_IRQ2_EINT_SHIFT 1 /* IM_DSP_IRQ2_EINT */ +#define WM5100_IM_DSP_IRQ2_EINT_WIDTH 1 /* IM_DSP_IRQ2_EINT */ +#define WM5100_IM_DSP_IRQ1_EINT 0x0001 /* IM_DSP_IRQ1_EINT */ +#define WM5100_IM_DSP_IRQ1_EINT_MASK 0x0001 /* IM_DSP_IRQ1_EINT */ +#define WM5100_IM_DSP_IRQ1_EINT_SHIFT 0 /* IM_DSP_IRQ1_EINT */ +#define WM5100_IM_DSP_IRQ1_EINT_WIDTH 1 /* IM_DSP_IRQ1_EINT */ + +/* + * R3337 (0xD09) - Interrupt Status 3 Mask + */ +#define WM5100_IM_SPK_SHUTDOWN_WARN_EINT 0x8000 /* IM_SPK_SHUTDOWN_WARN_EINT */ +#define WM5100_IM_SPK_SHUTDOWN_WARN_EINT_MASK 0x8000 /* IM_SPK_SHUTDOWN_WARN_EINT */ +#define WM5100_IM_SPK_SHUTDOWN_WARN_EINT_SHIFT 15 /* IM_SPK_SHUTDOWN_WARN_EINT */ +#define WM5100_IM_SPK_SHUTDOWN_WARN_EINT_WIDTH 1 /* IM_SPK_SHUTDOWN_WARN_EINT */ +#define WM5100_IM_SPK_SHUTDOWN_EINT 0x4000 /* IM_SPK_SHUTDOWN_EINT */ +#define WM5100_IM_SPK_SHUTDOWN_EINT_MASK 0x4000 /* IM_SPK_SHUTDOWN_EINT */ +#define WM5100_IM_SPK_SHUTDOWN_EINT_SHIFT 14 /* IM_SPK_SHUTDOWN_EINT */ +#define WM5100_IM_SPK_SHUTDOWN_EINT_WIDTH 1 /* IM_SPK_SHUTDOWN_EINT */ +#define WM5100_IM_HPDET_EINT 0x2000 /* IM_HPDET_EINT */ +#define WM5100_IM_HPDET_EINT_MASK 0x2000 /* IM_HPDET_EINT */ +#define WM5100_IM_HPDET_EINT_SHIFT 13 /* IM_HPDET_EINT */ +#define WM5100_IM_HPDET_EINT_WIDTH 1 /* IM_HPDET_EINT */ +#define WM5100_IM_ACCDET_EINT 0x1000 /* IM_ACCDET_EINT */ +#define WM5100_IM_ACCDET_EINT_MASK 0x1000 /* IM_ACCDET_EINT */ +#define WM5100_IM_ACCDET_EINT_SHIFT 12 /* IM_ACCDET_EINT */ +#define WM5100_IM_ACCDET_EINT_WIDTH 1 /* IM_ACCDET_EINT */ +#define WM5100_IM_DRC_SIG_DET_EINT 0x0200 /* IM_DRC_SIG_DET_EINT */ +#define WM5100_IM_DRC_SIG_DET_EINT_MASK 0x0200 /* IM_DRC_SIG_DET_EINT */ +#define WM5100_IM_DRC_SIG_DET_EINT_SHIFT 9 /* IM_DRC_SIG_DET_EINT */ +#define WM5100_IM_DRC_SIG_DET_EINT_WIDTH 1 /* IM_DRC_SIG_DET_EINT */ +#define WM5100_IM_ASRC2_LOCK_EINT 0x0100 /* IM_ASRC2_LOCK_EINT */ +#define WM5100_IM_ASRC2_LOCK_EINT_MASK 0x0100 /* IM_ASRC2_LOCK_EINT */ +#define WM5100_IM_ASRC2_LOCK_EINT_SHIFT 8 /* IM_ASRC2_LOCK_EINT */ +#define WM5100_IM_ASRC2_LOCK_EINT_WIDTH 1 /* IM_ASRC2_LOCK_EINT */ +#define WM5100_IM_ASRC1_LOCK_EINT 0x0080 /* IM_ASRC1_LOCK_EINT */ +#define WM5100_IM_ASRC1_LOCK_EINT_MASK 0x0080 /* IM_ASRC1_LOCK_EINT */ +#define WM5100_IM_ASRC1_LOCK_EINT_SHIFT 7 /* IM_ASRC1_LOCK_EINT */ +#define WM5100_IM_ASRC1_LOCK_EINT_WIDTH 1 /* IM_ASRC1_LOCK_EINT */ +#define WM5100_IM_FLL2_LOCK_EINT 0x0008 /* IM_FLL2_LOCK_EINT */ +#define WM5100_IM_FLL2_LOCK_EINT_MASK 0x0008 /* IM_FLL2_LOCK_EINT */ +#define WM5100_IM_FLL2_LOCK_EINT_SHIFT 3 /* IM_FLL2_LOCK_EINT */ +#define WM5100_IM_FLL2_LOCK_EINT_WIDTH 1 /* IM_FLL2_LOCK_EINT */ +#define WM5100_IM_FLL1_LOCK_EINT 0x0004 /* IM_FLL1_LOCK_EINT */ +#define WM5100_IM_FLL1_LOCK_EINT_MASK 0x0004 /* IM_FLL1_LOCK_EINT */ +#define WM5100_IM_FLL1_LOCK_EINT_SHIFT 2 /* IM_FLL1_LOCK_EINT */ +#define WM5100_IM_FLL1_LOCK_EINT_WIDTH 1 /* IM_FLL1_LOCK_EINT */ +#define WM5100_IM_CLKGEN_ERR_EINT 0x0002 /* IM_CLKGEN_ERR_EINT */ +#define WM5100_IM_CLKGEN_ERR_EINT_MASK 0x0002 /* IM_CLKGEN_ERR_EINT */ +#define WM5100_IM_CLKGEN_ERR_EINT_SHIFT 1 /* IM_CLKGEN_ERR_EINT */ +#define WM5100_IM_CLKGEN_ERR_EINT_WIDTH 1 /* IM_CLKGEN_ERR_EINT */ +#define WM5100_IM_CLKGEN_ERR_ASYNC_EINT 0x0001 /* IM_CLKGEN_ERR_ASYNC_EINT */ +#define WM5100_IM_CLKGEN_ERR_ASYNC_EINT_MASK 0x0001 /* IM_CLKGEN_ERR_ASYNC_EINT */ +#define WM5100_IM_CLKGEN_ERR_ASYNC_EINT_SHIFT 0 /* IM_CLKGEN_ERR_ASYNC_EINT */ +#define WM5100_IM_CLKGEN_ERR_ASYNC_EINT_WIDTH 1 /* IM_CLKGEN_ERR_ASYNC_EINT */ + +/* + * R3338 (0xD0A) - Interrupt Status 4 Mask + */ +#define WM5100_IM_AIF3_ERR_EINT 0x2000 /* IM_AIF3_ERR_EINT */ +#define WM5100_IM_AIF3_ERR_EINT_MASK 0x2000 /* IM_AIF3_ERR_EINT */ +#define WM5100_IM_AIF3_ERR_EINT_SHIFT 13 /* IM_AIF3_ERR_EINT */ +#define WM5100_IM_AIF3_ERR_EINT_WIDTH 1 /* IM_AIF3_ERR_EINT */ +#define WM5100_IM_AIF2_ERR_EINT 0x1000 /* IM_AIF2_ERR_EINT */ +#define WM5100_IM_AIF2_ERR_EINT_MASK 0x1000 /* IM_AIF2_ERR_EINT */ +#define WM5100_IM_AIF2_ERR_EINT_SHIFT 12 /* IM_AIF2_ERR_EINT */ +#define WM5100_IM_AIF2_ERR_EINT_WIDTH 1 /* IM_AIF2_ERR_EINT */ +#define WM5100_IM_AIF1_ERR_EINT 0x0800 /* IM_AIF1_ERR_EINT */ +#define WM5100_IM_AIF1_ERR_EINT_MASK 0x0800 /* IM_AIF1_ERR_EINT */ +#define WM5100_IM_AIF1_ERR_EINT_SHIFT 11 /* IM_AIF1_ERR_EINT */ +#define WM5100_IM_AIF1_ERR_EINT_WIDTH 1 /* IM_AIF1_ERR_EINT */ +#define WM5100_IM_CTRLIF_ERR_EINT 0x0400 /* IM_CTRLIF_ERR_EINT */ +#define WM5100_IM_CTRLIF_ERR_EINT_MASK 0x0400 /* IM_CTRLIF_ERR_EINT */ +#define WM5100_IM_CTRLIF_ERR_EINT_SHIFT 10 /* IM_CTRLIF_ERR_EINT */ +#define WM5100_IM_CTRLIF_ERR_EINT_WIDTH 1 /* IM_CTRLIF_ERR_EINT */ +#define WM5100_IM_ISRC2_UNDERCLOCKED_EINT 0x0200 /* IM_ISRC2_UNDERCLOCKED_EINT */ +#define WM5100_IM_ISRC2_UNDERCLOCKED_EINT_MASK 0x0200 /* IM_ISRC2_UNDERCLOCKED_EINT */ +#define WM5100_IM_ISRC2_UNDERCLOCKED_EINT_SHIFT 9 /* IM_ISRC2_UNDERCLOCKED_EINT */ +#define WM5100_IM_ISRC2_UNDERCLOCKED_EINT_WIDTH 1 /* IM_ISRC2_UNDERCLOCKED_EINT */ +#define WM5100_IM_ISRC1_UNDERCLOCKED_EINT 0x0100 /* IM_ISRC1_UNDERCLOCKED_EINT */ +#define WM5100_IM_ISRC1_UNDERCLOCKED_EINT_MASK 0x0100 /* IM_ISRC1_UNDERCLOCKED_EINT */ +#define WM5100_IM_ISRC1_UNDERCLOCKED_EINT_SHIFT 8 /* IM_ISRC1_UNDERCLOCKED_EINT */ +#define WM5100_IM_ISRC1_UNDERCLOCKED_EINT_WIDTH 1 /* IM_ISRC1_UNDERCLOCKED_EINT */ +#define WM5100_IM_FX_UNDERCLOCKED_EINT 0x0080 /* IM_FX_UNDERCLOCKED_EINT */ +#define WM5100_IM_FX_UNDERCLOCKED_EINT_MASK 0x0080 /* IM_FX_UNDERCLOCKED_EINT */ +#define WM5100_IM_FX_UNDERCLOCKED_EINT_SHIFT 7 /* IM_FX_UNDERCLOCKED_EINT */ +#define WM5100_IM_FX_UNDERCLOCKED_EINT_WIDTH 1 /* IM_FX_UNDERCLOCKED_EINT */ +#define WM5100_IM_AIF3_UNDERCLOCKED_EINT 0x0040 /* IM_AIF3_UNDERCLOCKED_EINT */ +#define WM5100_IM_AIF3_UNDERCLOCKED_EINT_MASK 0x0040 /* IM_AIF3_UNDERCLOCKED_EINT */ +#define WM5100_IM_AIF3_UNDERCLOCKED_EINT_SHIFT 6 /* IM_AIF3_UNDERCLOCKED_EINT */ +#define WM5100_IM_AIF3_UNDERCLOCKED_EINT_WIDTH 1 /* IM_AIF3_UNDERCLOCKED_EINT */ +#define WM5100_IM_AIF2_UNDERCLOCKED_EINT 0x0020 /* IM_AIF2_UNDERCLOCKED_EINT */ +#define WM5100_IM_AIF2_UNDERCLOCKED_EINT_MASK 0x0020 /* IM_AIF2_UNDERCLOCKED_EINT */ +#define WM5100_IM_AIF2_UNDERCLOCKED_EINT_SHIFT 5 /* IM_AIF2_UNDERCLOCKED_EINT */ +#define WM5100_IM_AIF2_UNDERCLOCKED_EINT_WIDTH 1 /* IM_AIF2_UNDERCLOCKED_EINT */ +#define WM5100_IM_AIF1_UNDERCLOCKED_EINT 0x0010 /* IM_AIF1_UNDERCLOCKED_EINT */ +#define WM5100_IM_AIF1_UNDERCLOCKED_EINT_MASK 0x0010 /* IM_AIF1_UNDERCLOCKED_EINT */ +#define WM5100_IM_AIF1_UNDERCLOCKED_EINT_SHIFT 4 /* IM_AIF1_UNDERCLOCKED_EINT */ +#define WM5100_IM_AIF1_UNDERCLOCKED_EINT_WIDTH 1 /* IM_AIF1_UNDERCLOCKED_EINT */ +#define WM5100_IM_ASRC_UNDERCLOCKED_EINT 0x0008 /* IM_ASRC_UNDERCLOCKED_EINT */ +#define WM5100_IM_ASRC_UNDERCLOCKED_EINT_MASK 0x0008 /* IM_ASRC_UNDERCLOCKED_EINT */ +#define WM5100_IM_ASRC_UNDERCLOCKED_EINT_SHIFT 3 /* IM_ASRC_UNDERCLOCKED_EINT */ +#define WM5100_IM_ASRC_UNDERCLOCKED_EINT_WIDTH 1 /* IM_ASRC_UNDERCLOCKED_EINT */ +#define WM5100_IM_DAC_UNDERCLOCKED_EINT 0x0004 /* IM_DAC_UNDERCLOCKED_EINT */ +#define WM5100_IM_DAC_UNDERCLOCKED_EINT_MASK 0x0004 /* IM_DAC_UNDERCLOCKED_EINT */ +#define WM5100_IM_DAC_UNDERCLOCKED_EINT_SHIFT 2 /* IM_DAC_UNDERCLOCKED_EINT */ +#define WM5100_IM_DAC_UNDERCLOCKED_EINT_WIDTH 1 /* IM_DAC_UNDERCLOCKED_EINT */ +#define WM5100_IM_ADC_UNDERCLOCKED_EINT 0x0002 /* IM_ADC_UNDERCLOCKED_EINT */ +#define WM5100_IM_ADC_UNDERCLOCKED_EINT_MASK 0x0002 /* IM_ADC_UNDERCLOCKED_EINT */ +#define WM5100_IM_ADC_UNDERCLOCKED_EINT_SHIFT 1 /* IM_ADC_UNDERCLOCKED_EINT */ +#define WM5100_IM_ADC_UNDERCLOCKED_EINT_WIDTH 1 /* IM_ADC_UNDERCLOCKED_EINT */ +#define WM5100_IM_MIXER_UNDERCLOCKED_EINT 0x0001 /* IM_MIXER_UNDERCLOCKED_EINT */ +#define WM5100_IM_MIXER_UNDERCLOCKED_EINT_MASK 0x0001 /* IM_MIXER_UNDERCLOCKED_EINT */ +#define WM5100_IM_MIXER_UNDERCLOCKED_EINT_SHIFT 0 /* IM_MIXER_UNDERCLOCKED_EINT */ +#define WM5100_IM_MIXER_UNDERCLOCKED_EINT_WIDTH 1 /* IM_MIXER_UNDERCLOCKED_EINT */ + +/* + * R3359 (0xD1F) - Interrupt Control + */ +#define WM5100_IM_IRQ 0x0001 /* IM_IRQ */ +#define WM5100_IM_IRQ_MASK 0x0001 /* IM_IRQ */ +#define WM5100_IM_IRQ_SHIFT 0 /* IM_IRQ */ +#define WM5100_IM_IRQ_WIDTH 1 /* IM_IRQ */ + +/* + * R3360 (0xD20) - IRQ Debounce 1 + */ +#define WM5100_SPK_SHUTDOWN_WARN_DB 0x0200 /* SPK_SHUTDOWN_WARN_DB */ +#define WM5100_SPK_SHUTDOWN_WARN_DB_MASK 0x0200 /* SPK_SHUTDOWN_WARN_DB */ +#define WM5100_SPK_SHUTDOWN_WARN_DB_SHIFT 9 /* SPK_SHUTDOWN_WARN_DB */ +#define WM5100_SPK_SHUTDOWN_WARN_DB_WIDTH 1 /* SPK_SHUTDOWN_WARN_DB */ +#define WM5100_SPK_SHUTDOWN_DB 0x0100 /* SPK_SHUTDOWN_DB */ +#define WM5100_SPK_SHUTDOWN_DB_MASK 0x0100 /* SPK_SHUTDOWN_DB */ +#define WM5100_SPK_SHUTDOWN_DB_SHIFT 8 /* SPK_SHUTDOWN_DB */ +#define WM5100_SPK_SHUTDOWN_DB_WIDTH 1 /* SPK_SHUTDOWN_DB */ +#define WM5100_FLL1_LOCK_IRQ_DB 0x0008 /* FLL1_LOCK_IRQ_DB */ +#define WM5100_FLL1_LOCK_IRQ_DB_MASK 0x0008 /* FLL1_LOCK_IRQ_DB */ +#define WM5100_FLL1_LOCK_IRQ_DB_SHIFT 3 /* FLL1_LOCK_IRQ_DB */ +#define WM5100_FLL1_LOCK_IRQ_DB_WIDTH 1 /* FLL1_LOCK_IRQ_DB */ +#define WM5100_FLL2_LOCK_IRQ_DB 0x0004 /* FLL2_LOCK_IRQ_DB */ +#define WM5100_FLL2_LOCK_IRQ_DB_MASK 0x0004 /* FLL2_LOCK_IRQ_DB */ +#define WM5100_FLL2_LOCK_IRQ_DB_SHIFT 2 /* FLL2_LOCK_IRQ_DB */ +#define WM5100_FLL2_LOCK_IRQ_DB_WIDTH 1 /* FLL2_LOCK_IRQ_DB */ +#define WM5100_CLKGEN_ERR_IRQ_DB 0x0002 /* CLKGEN_ERR_IRQ_DB */ +#define WM5100_CLKGEN_ERR_IRQ_DB_MASK 0x0002 /* CLKGEN_ERR_IRQ_DB */ +#define WM5100_CLKGEN_ERR_IRQ_DB_SHIFT 1 /* CLKGEN_ERR_IRQ_DB */ +#define WM5100_CLKGEN_ERR_IRQ_DB_WIDTH 1 /* CLKGEN_ERR_IRQ_DB */ +#define WM5100_CLKGEN_ERR_ASYNC_IRQ_DB 0x0001 /* CLKGEN_ERR_ASYNC_IRQ_DB */ +#define WM5100_CLKGEN_ERR_ASYNC_IRQ_DB_MASK 0x0001 /* CLKGEN_ERR_ASYNC_IRQ_DB */ +#define WM5100_CLKGEN_ERR_ASYNC_IRQ_DB_SHIFT 0 /* CLKGEN_ERR_ASYNC_IRQ_DB */ +#define WM5100_CLKGEN_ERR_ASYNC_IRQ_DB_WIDTH 1 /* CLKGEN_ERR_ASYNC_IRQ_DB */ + +/* + * R3361 (0xD21) - IRQ Debounce 2 + */ +#define WM5100_AIF_ERR_DB 0x0001 /* AIF_ERR_DB */ +#define WM5100_AIF_ERR_DB_MASK 0x0001 /* AIF_ERR_DB */ +#define WM5100_AIF_ERR_DB_SHIFT 0 /* AIF_ERR_DB */ +#define WM5100_AIF_ERR_DB_WIDTH 1 /* AIF_ERR_DB */ + +/* + * R3584 (0xE00) - FX_Ctrl + */ +#define WM5100_FX_STS_MASK 0xFFC0 /* FX_STS - [15:6] */ +#define WM5100_FX_STS_SHIFT 6 /* FX_STS - [15:6] */ +#define WM5100_FX_STS_WIDTH 10 /* FX_STS - [15:6] */ +#define WM5100_FX_RATE_MASK 0x0003 /* FX_RATE - [1:0] */ +#define WM5100_FX_RATE_SHIFT 0 /* FX_RATE - [1:0] */ +#define WM5100_FX_RATE_WIDTH 2 /* FX_RATE - [1:0] */ + +/* + * R3600 (0xE10) - EQ1_1 + */ +#define WM5100_EQ1_B1_GAIN_MASK 0xF800 /* EQ1_B1_GAIN - [15:11] */ +#define WM5100_EQ1_B1_GAIN_SHIFT 11 /* EQ1_B1_GAIN - [15:11] */ +#define WM5100_EQ1_B1_GAIN_WIDTH 5 /* EQ1_B1_GAIN - [15:11] */ +#define WM5100_EQ1_B2_GAIN_MASK 0x07C0 /* EQ1_B2_GAIN - [10:6] */ +#define WM5100_EQ1_B2_GAIN_SHIFT 6 /* EQ1_B2_GAIN - [10:6] */ +#define WM5100_EQ1_B2_GAIN_WIDTH 5 /* EQ1_B2_GAIN - [10:6] */ +#define WM5100_EQ1_B3_GAIN_MASK 0x003E /* EQ1_B3_GAIN - [5:1] */ +#define WM5100_EQ1_B3_GAIN_SHIFT 1 /* EQ1_B3_GAIN - [5:1] */ +#define WM5100_EQ1_B3_GAIN_WIDTH 5 /* EQ1_B3_GAIN - [5:1] */ +#define WM5100_EQ1_ENA 0x0001 /* EQ1_ENA */ +#define WM5100_EQ1_ENA_MASK 0x0001 /* EQ1_ENA */ +#define WM5100_EQ1_ENA_SHIFT 0 /* EQ1_ENA */ +#define WM5100_EQ1_ENA_WIDTH 1 /* EQ1_ENA */ + +/* + * R3601 (0xE11) - EQ1_2 + */ +#define WM5100_EQ1_B4_GAIN_MASK 0xF800 /* EQ1_B4_GAIN - [15:11] */ +#define WM5100_EQ1_B4_GAIN_SHIFT 11 /* EQ1_B4_GAIN - [15:11] */ +#define WM5100_EQ1_B4_GAIN_WIDTH 5 /* EQ1_B4_GAIN - [15:11] */ +#define WM5100_EQ1_B5_GAIN_MASK 0x07C0 /* EQ1_B5_GAIN - [10:6] */ +#define WM5100_EQ1_B5_GAIN_SHIFT 6 /* EQ1_B5_GAIN - [10:6] */ +#define WM5100_EQ1_B5_GAIN_WIDTH 5 /* EQ1_B5_GAIN - [10:6] */ + +/* + * R3602 (0xE12) - EQ1_3 + */ +#define WM5100_EQ1_B1_A_MASK 0xFFFF /* EQ1_B1_A - [15:0] */ +#define WM5100_EQ1_B1_A_SHIFT 0 /* EQ1_B1_A - [15:0] */ +#define WM5100_EQ1_B1_A_WIDTH 16 /* EQ1_B1_A - [15:0] */ + +/* + * R3603 (0xE13) - EQ1_4 + */ +#define WM5100_EQ1_B1_B_MASK 0xFFFF /* EQ1_B1_B - [15:0] */ +#define WM5100_EQ1_B1_B_SHIFT 0 /* EQ1_B1_B - [15:0] */ +#define WM5100_EQ1_B1_B_WIDTH 16 /* EQ1_B1_B - [15:0] */ + +/* + * R3604 (0xE14) - EQ1_5 + */ +#define WM5100_EQ1_B1_PG_MASK 0xFFFF /* EQ1_B1_PG - [15:0] */ +#define WM5100_EQ1_B1_PG_SHIFT 0 /* EQ1_B1_PG - [15:0] */ +#define WM5100_EQ1_B1_PG_WIDTH 16 /* EQ1_B1_PG - [15:0] */ + +/* + * R3605 (0xE15) - EQ1_6 + */ +#define WM5100_EQ1_B2_A_MASK 0xFFFF /* EQ1_B2_A - [15:0] */ +#define WM5100_EQ1_B2_A_SHIFT 0 /* EQ1_B2_A - [15:0] */ +#define WM5100_EQ1_B2_A_WIDTH 16 /* EQ1_B2_A - [15:0] */ + +/* + * R3606 (0xE16) - EQ1_7 + */ +#define WM5100_EQ1_B2_B_MASK 0xFFFF /* EQ1_B2_B - [15:0] */ +#define WM5100_EQ1_B2_B_SHIFT 0 /* EQ1_B2_B - [15:0] */ +#define WM5100_EQ1_B2_B_WIDTH 16 /* EQ1_B2_B - [15:0] */ + +/* + * R3607 (0xE17) - EQ1_8 + */ +#define WM5100_EQ1_B2_C_MASK 0xFFFF /* EQ1_B2_C - [15:0] */ +#define WM5100_EQ1_B2_C_SHIFT 0 /* EQ1_B2_C - [15:0] */ +#define WM5100_EQ1_B2_C_WIDTH 16 /* EQ1_B2_C - [15:0] */ + +/* + * R3608 (0xE18) - EQ1_9 + */ +#define WM5100_EQ1_B2_PG_MASK 0xFFFF /* EQ1_B2_PG - [15:0] */ +#define WM5100_EQ1_B2_PG_SHIFT 0 /* EQ1_B2_PG - [15:0] */ +#define WM5100_EQ1_B2_PG_WIDTH 16 /* EQ1_B2_PG - [15:0] */ + +/* + * R3609 (0xE19) - EQ1_10 + */ +#define WM5100_EQ1_B3_A_MASK 0xFFFF /* EQ1_B3_A - [15:0] */ +#define WM5100_EQ1_B3_A_SHIFT 0 /* EQ1_B3_A - [15:0] */ +#define WM5100_EQ1_B3_A_WIDTH 16 /* EQ1_B3_A - [15:0] */ + +/* + * R3610 (0xE1A) - EQ1_11 + */ +#define WM5100_EQ1_B3_B_MASK 0xFFFF /* EQ1_B3_B - [15:0] */ +#define WM5100_EQ1_B3_B_SHIFT 0 /* EQ1_B3_B - [15:0] */ +#define WM5100_EQ1_B3_B_WIDTH 16 /* EQ1_B3_B - [15:0] */ + +/* + * R3611 (0xE1B) - EQ1_12 + */ +#define WM5100_EQ1_B3_C_MASK 0xFFFF /* EQ1_B3_C - [15:0] */ +#define WM5100_EQ1_B3_C_SHIFT 0 /* EQ1_B3_C - [15:0] */ +#define WM5100_EQ1_B3_C_WIDTH 16 /* EQ1_B3_C - [15:0] */ + +/* + * R3612 (0xE1C) - EQ1_13 + */ +#define WM5100_EQ1_B3_PG_MASK 0xFFFF /* EQ1_B3_PG - [15:0] */ +#define WM5100_EQ1_B3_PG_SHIFT 0 /* EQ1_B3_PG - [15:0] */ +#define WM5100_EQ1_B3_PG_WIDTH 16 /* EQ1_B3_PG - [15:0] */ + +/* + * R3613 (0xE1D) - EQ1_14 + */ +#define WM5100_EQ1_B4_A_MASK 0xFFFF /* EQ1_B4_A - [15:0] */ +#define WM5100_EQ1_B4_A_SHIFT 0 /* EQ1_B4_A - [15:0] */ +#define WM5100_EQ1_B4_A_WIDTH 16 /* EQ1_B4_A - [15:0] */ + +/* + * R3614 (0xE1E) - EQ1_15 + */ +#define WM5100_EQ1_B4_B_MASK 0xFFFF /* EQ1_B4_B - [15:0] */ +#define WM5100_EQ1_B4_B_SHIFT 0 /* EQ1_B4_B - [15:0] */ +#define WM5100_EQ1_B4_B_WIDTH 16 /* EQ1_B4_B - [15:0] */ + +/* + * R3615 (0xE1F) - EQ1_16 + */ +#define WM5100_EQ1_B4_C_MASK 0xFFFF /* EQ1_B4_C - [15:0] */ +#define WM5100_EQ1_B4_C_SHIFT 0 /* EQ1_B4_C - [15:0] */ +#define WM5100_EQ1_B4_C_WIDTH 16 /* EQ1_B4_C - [15:0] */ + +/* + * R3616 (0xE20) - EQ1_17 + */ +#define WM5100_EQ1_B4_PG_MASK 0xFFFF /* EQ1_B4_PG - [15:0] */ +#define WM5100_EQ1_B4_PG_SHIFT 0 /* EQ1_B4_PG - [15:0] */ +#define WM5100_EQ1_B4_PG_WIDTH 16 /* EQ1_B4_PG - [15:0] */ + +/* + * R3617 (0xE21) - EQ1_18 + */ +#define WM5100_EQ1_B5_A_MASK 0xFFFF /* EQ1_B5_A - [15:0] */ +#define WM5100_EQ1_B5_A_SHIFT 0 /* EQ1_B5_A - [15:0] */ +#define WM5100_EQ1_B5_A_WIDTH 16 /* EQ1_B5_A - [15:0] */ + +/* + * R3618 (0xE22) - EQ1_19 + */ +#define WM5100_EQ1_B5_B_MASK 0xFFFF /* EQ1_B5_B - [15:0] */ +#define WM5100_EQ1_B5_B_SHIFT 0 /* EQ1_B5_B - [15:0] */ +#define WM5100_EQ1_B5_B_WIDTH 16 /* EQ1_B5_B - [15:0] */ + +/* + * R3619 (0xE23) - EQ1_20 + */ +#define WM5100_EQ1_B5_PG_MASK 0xFFFF /* EQ1_B5_PG - [15:0] */ +#define WM5100_EQ1_B5_PG_SHIFT 0 /* EQ1_B5_PG - [15:0] */ +#define WM5100_EQ1_B5_PG_WIDTH 16 /* EQ1_B5_PG - [15:0] */ + +/* + * R3622 (0xE26) - EQ2_1 + */ +#define WM5100_EQ2_B1_GAIN_MASK 0xF800 /* EQ2_B1_GAIN - [15:11] */ +#define WM5100_EQ2_B1_GAIN_SHIFT 11 /* EQ2_B1_GAIN - [15:11] */ +#define WM5100_EQ2_B1_GAIN_WIDTH 5 /* EQ2_B1_GAIN - [15:11] */ +#define WM5100_EQ2_B2_GAIN_MASK 0x07C0 /* EQ2_B2_GAIN - [10:6] */ +#define WM5100_EQ2_B2_GAIN_SHIFT 6 /* EQ2_B2_GAIN - [10:6] */ +#define WM5100_EQ2_B2_GAIN_WIDTH 5 /* EQ2_B2_GAIN - [10:6] */ +#define WM5100_EQ2_B3_GAIN_MASK 0x003E /* EQ2_B3_GAIN - [5:1] */ +#define WM5100_EQ2_B3_GAIN_SHIFT 1 /* EQ2_B3_GAIN - [5:1] */ +#define WM5100_EQ2_B3_GAIN_WIDTH 5 /* EQ2_B3_GAIN - [5:1] */ +#define WM5100_EQ2_ENA 0x0001 /* EQ2_ENA */ +#define WM5100_EQ2_ENA_MASK 0x0001 /* EQ2_ENA */ +#define WM5100_EQ2_ENA_SHIFT 0 /* EQ2_ENA */ +#define WM5100_EQ2_ENA_WIDTH 1 /* EQ2_ENA */ + +/* + * R3623 (0xE27) - EQ2_2 + */ +#define WM5100_EQ2_B4_GAIN_MASK 0xF800 /* EQ2_B4_GAIN - [15:11] */ +#define WM5100_EQ2_B4_GAIN_SHIFT 11 /* EQ2_B4_GAIN - [15:11] */ +#define WM5100_EQ2_B4_GAIN_WIDTH 5 /* EQ2_B4_GAIN - [15:11] */ +#define WM5100_EQ2_B5_GAIN_MASK 0x07C0 /* EQ2_B5_GAIN - [10:6] */ +#define WM5100_EQ2_B5_GAIN_SHIFT 6 /* EQ2_B5_GAIN - [10:6] */ +#define WM5100_EQ2_B5_GAIN_WIDTH 5 /* EQ2_B5_GAIN - [10:6] */ + +/* + * R3624 (0xE28) - EQ2_3 + */ +#define WM5100_EQ2_B1_A_MASK 0xFFFF /* EQ2_B1_A - [15:0] */ +#define WM5100_EQ2_B1_A_SHIFT 0 /* EQ2_B1_A - [15:0] */ +#define WM5100_EQ2_B1_A_WIDTH 16 /* EQ2_B1_A - [15:0] */ + +/* + * R3625 (0xE29) - EQ2_4 + */ +#define WM5100_EQ2_B1_B_MASK 0xFFFF /* EQ2_B1_B - [15:0] */ +#define WM5100_EQ2_B1_B_SHIFT 0 /* EQ2_B1_B - [15:0] */ +#define WM5100_EQ2_B1_B_WIDTH 16 /* EQ2_B1_B - [15:0] */ + +/* + * R3626 (0xE2A) - EQ2_5 + */ +#define WM5100_EQ2_B1_PG_MASK 0xFFFF /* EQ2_B1_PG - [15:0] */ +#define WM5100_EQ2_B1_PG_SHIFT 0 /* EQ2_B1_PG - [15:0] */ +#define WM5100_EQ2_B1_PG_WIDTH 16 /* EQ2_B1_PG - [15:0] */ + +/* + * R3627 (0xE2B) - EQ2_6 + */ +#define WM5100_EQ2_B2_A_MASK 0xFFFF /* EQ2_B2_A - [15:0] */ +#define WM5100_EQ2_B2_A_SHIFT 0 /* EQ2_B2_A - [15:0] */ +#define WM5100_EQ2_B2_A_WIDTH 16 /* EQ2_B2_A - [15:0] */ + +/* + * R3628 (0xE2C) - EQ2_7 + */ +#define WM5100_EQ2_B2_B_MASK 0xFFFF /* EQ2_B2_B - [15:0] */ +#define WM5100_EQ2_B2_B_SHIFT 0 /* EQ2_B2_B - [15:0] */ +#define WM5100_EQ2_B2_B_WIDTH 16 /* EQ2_B2_B - [15:0] */ + +/* + * R3629 (0xE2D) - EQ2_8 + */ +#define WM5100_EQ2_B2_C_MASK 0xFFFF /* EQ2_B2_C - [15:0] */ +#define WM5100_EQ2_B2_C_SHIFT 0 /* EQ2_B2_C - [15:0] */ +#define WM5100_EQ2_B2_C_WIDTH 16 /* EQ2_B2_C - [15:0] */ + +/* + * R3630 (0xE2E) - EQ2_9 + */ +#define WM5100_EQ2_B2_PG_MASK 0xFFFF /* EQ2_B2_PG - [15:0] */ +#define WM5100_EQ2_B2_PG_SHIFT 0 /* EQ2_B2_PG - [15:0] */ +#define WM5100_EQ2_B2_PG_WIDTH 16 /* EQ2_B2_PG - [15:0] */ + +/* + * R3631 (0xE2F) - EQ2_10 + */ +#define WM5100_EQ2_B3_A_MASK 0xFFFF /* EQ2_B3_A - [15:0] */ +#define WM5100_EQ2_B3_A_SHIFT 0 /* EQ2_B3_A - [15:0] */ +#define WM5100_EQ2_B3_A_WIDTH 16 /* EQ2_B3_A - [15:0] */ + +/* + * R3632 (0xE30) - EQ2_11 + */ +#define WM5100_EQ2_B3_B_MASK 0xFFFF /* EQ2_B3_B - [15:0] */ +#define WM5100_EQ2_B3_B_SHIFT 0 /* EQ2_B3_B - [15:0] */ +#define WM5100_EQ2_B3_B_WIDTH 16 /* EQ2_B3_B - [15:0] */ + +/* + * R3633 (0xE31) - EQ2_12 + */ +#define WM5100_EQ2_B3_C_MASK 0xFFFF /* EQ2_B3_C - [15:0] */ +#define WM5100_EQ2_B3_C_SHIFT 0 /* EQ2_B3_C - [15:0] */ +#define WM5100_EQ2_B3_C_WIDTH 16 /* EQ2_B3_C - [15:0] */ + +/* + * R3634 (0xE32) - EQ2_13 + */ +#define WM5100_EQ2_B3_PG_MASK 0xFFFF /* EQ2_B3_PG - [15:0] */ +#define WM5100_EQ2_B3_PG_SHIFT 0 /* EQ2_B3_PG - [15:0] */ +#define WM5100_EQ2_B3_PG_WIDTH 16 /* EQ2_B3_PG - [15:0] */ + +/* + * R3635 (0xE33) - EQ2_14 + */ +#define WM5100_EQ2_B4_A_MASK 0xFFFF /* EQ2_B4_A - [15:0] */ +#define WM5100_EQ2_B4_A_SHIFT 0 /* EQ2_B4_A - [15:0] */ +#define WM5100_EQ2_B4_A_WIDTH 16 /* EQ2_B4_A - [15:0] */ + +/* + * R3636 (0xE34) - EQ2_15 + */ +#define WM5100_EQ2_B4_B_MASK 0xFFFF /* EQ2_B4_B - [15:0] */ +#define WM5100_EQ2_B4_B_SHIFT 0 /* EQ2_B4_B - [15:0] */ +#define WM5100_EQ2_B4_B_WIDTH 16 /* EQ2_B4_B - [15:0] */ + +/* + * R3637 (0xE35) - EQ2_16 + */ +#define WM5100_EQ2_B4_C_MASK 0xFFFF /* EQ2_B4_C - [15:0] */ +#define WM5100_EQ2_B4_C_SHIFT 0 /* EQ2_B4_C - [15:0] */ +#define WM5100_EQ2_B4_C_WIDTH 16 /* EQ2_B4_C - [15:0] */ + +/* + * R3638 (0xE36) - EQ2_17 + */ +#define WM5100_EQ2_B4_PG_MASK 0xFFFF /* EQ2_B4_PG - [15:0] */ +#define WM5100_EQ2_B4_PG_SHIFT 0 /* EQ2_B4_PG - [15:0] */ +#define WM5100_EQ2_B4_PG_WIDTH 16 /* EQ2_B4_PG - [15:0] */ + +/* + * R3639 (0xE37) - EQ2_18 + */ +#define WM5100_EQ2_B5_A_MASK 0xFFFF /* EQ2_B5_A - [15:0] */ +#define WM5100_EQ2_B5_A_SHIFT 0 /* EQ2_B5_A - [15:0] */ +#define WM5100_EQ2_B5_A_WIDTH 16 /* EQ2_B5_A - [15:0] */ + +/* + * R3640 (0xE38) - EQ2_19 + */ +#define WM5100_EQ2_B5_B_MASK 0xFFFF /* EQ2_B5_B - [15:0] */ +#define WM5100_EQ2_B5_B_SHIFT 0 /* EQ2_B5_B - [15:0] */ +#define WM5100_EQ2_B5_B_WIDTH 16 /* EQ2_B5_B - [15:0] */ + +/* + * R3641 (0xE39) - EQ2_20 + */ +#define WM5100_EQ2_B5_PG_MASK 0xFFFF /* EQ2_B5_PG - [15:0] */ +#define WM5100_EQ2_B5_PG_SHIFT 0 /* EQ2_B5_PG - [15:0] */ +#define WM5100_EQ2_B5_PG_WIDTH 16 /* EQ2_B5_PG - [15:0] */ + +/* + * R3644 (0xE3C) - EQ3_1 + */ +#define WM5100_EQ3_B1_GAIN_MASK 0xF800 /* EQ3_B1_GAIN - [15:11] */ +#define WM5100_EQ3_B1_GAIN_SHIFT 11 /* EQ3_B1_GAIN - [15:11] */ +#define WM5100_EQ3_B1_GAIN_WIDTH 5 /* EQ3_B1_GAIN - [15:11] */ +#define WM5100_EQ3_B2_GAIN_MASK 0x07C0 /* EQ3_B2_GAIN - [10:6] */ +#define WM5100_EQ3_B2_GAIN_SHIFT 6 /* EQ3_B2_GAIN - [10:6] */ +#define WM5100_EQ3_B2_GAIN_WIDTH 5 /* EQ3_B2_GAIN - [10:6] */ +#define WM5100_EQ3_B3_GAIN_MASK 0x003E /* EQ3_B3_GAIN - [5:1] */ +#define WM5100_EQ3_B3_GAIN_SHIFT 1 /* EQ3_B3_GAIN - [5:1] */ +#define WM5100_EQ3_B3_GAIN_WIDTH 5 /* EQ3_B3_GAIN - [5:1] */ +#define WM5100_EQ3_ENA 0x0001 /* EQ3_ENA */ +#define WM5100_EQ3_ENA_MASK 0x0001 /* EQ3_ENA */ +#define WM5100_EQ3_ENA_SHIFT 0 /* EQ3_ENA */ +#define WM5100_EQ3_ENA_WIDTH 1 /* EQ3_ENA */ + +/* + * R3645 (0xE3D) - EQ3_2 + */ +#define WM5100_EQ3_B4_GAIN_MASK 0xF800 /* EQ3_B4_GAIN - [15:11] */ +#define WM5100_EQ3_B4_GAIN_SHIFT 11 /* EQ3_B4_GAIN - [15:11] */ +#define WM5100_EQ3_B4_GAIN_WIDTH 5 /* EQ3_B4_GAIN - [15:11] */ +#define WM5100_EQ3_B5_GAIN_MASK 0x07C0 /* EQ3_B5_GAIN - [10:6] */ +#define WM5100_EQ3_B5_GAIN_SHIFT 6 /* EQ3_B5_GAIN - [10:6] */ +#define WM5100_EQ3_B5_GAIN_WIDTH 5 /* EQ3_B5_GAIN - [10:6] */ + +/* + * R3646 (0xE3E) - EQ3_3 + */ +#define WM5100_EQ3_B1_A_MASK 0xFFFF /* EQ3_B1_A - [15:0] */ +#define WM5100_EQ3_B1_A_SHIFT 0 /* EQ3_B1_A - [15:0] */ +#define WM5100_EQ3_B1_A_WIDTH 16 /* EQ3_B1_A - [15:0] */ + +/* + * R3647 (0xE3F) - EQ3_4 + */ +#define WM5100_EQ3_B1_B_MASK 0xFFFF /* EQ3_B1_B - [15:0] */ +#define WM5100_EQ3_B1_B_SHIFT 0 /* EQ3_B1_B - [15:0] */ +#define WM5100_EQ3_B1_B_WIDTH 16 /* EQ3_B1_B - [15:0] */ + +/* + * R3648 (0xE40) - EQ3_5 + */ +#define WM5100_EQ3_B1_PG_MASK 0xFFFF /* EQ3_B1_PG - [15:0] */ +#define WM5100_EQ3_B1_PG_SHIFT 0 /* EQ3_B1_PG - [15:0] */ +#define WM5100_EQ3_B1_PG_WIDTH 16 /* EQ3_B1_PG - [15:0] */ + +/* + * R3649 (0xE41) - EQ3_6 + */ +#define WM5100_EQ3_B2_A_MASK 0xFFFF /* EQ3_B2_A - [15:0] */ +#define WM5100_EQ3_B2_A_SHIFT 0 /* EQ3_B2_A - [15:0] */ +#define WM5100_EQ3_B2_A_WIDTH 16 /* EQ3_B2_A - [15:0] */ + +/* + * R3650 (0xE42) - EQ3_7 + */ +#define WM5100_EQ3_B2_B_MASK 0xFFFF /* EQ3_B2_B - [15:0] */ +#define WM5100_EQ3_B2_B_SHIFT 0 /* EQ3_B2_B - [15:0] */ +#define WM5100_EQ3_B2_B_WIDTH 16 /* EQ3_B2_B - [15:0] */ + +/* + * R3651 (0xE43) - EQ3_8 + */ +#define WM5100_EQ3_B2_C_MASK 0xFFFF /* EQ3_B2_C - [15:0] */ +#define WM5100_EQ3_B2_C_SHIFT 0 /* EQ3_B2_C - [15:0] */ +#define WM5100_EQ3_B2_C_WIDTH 16 /* EQ3_B2_C - [15:0] */ + +/* + * R3652 (0xE44) - EQ3_9 + */ +#define WM5100_EQ3_B2_PG_MASK 0xFFFF /* EQ3_B2_PG - [15:0] */ +#define WM5100_EQ3_B2_PG_SHIFT 0 /* EQ3_B2_PG - [15:0] */ +#define WM5100_EQ3_B2_PG_WIDTH 16 /* EQ3_B2_PG - [15:0] */ + +/* + * R3653 (0xE45) - EQ3_10 + */ +#define WM5100_EQ3_B3_A_MASK 0xFFFF /* EQ3_B3_A - [15:0] */ +#define WM5100_EQ3_B3_A_SHIFT 0 /* EQ3_B3_A - [15:0] */ +#define WM5100_EQ3_B3_A_WIDTH 16 /* EQ3_B3_A - [15:0] */ + +/* + * R3654 (0xE46) - EQ3_11 + */ +#define WM5100_EQ3_B3_B_MASK 0xFFFF /* EQ3_B3_B - [15:0] */ +#define WM5100_EQ3_B3_B_SHIFT 0 /* EQ3_B3_B - [15:0] */ +#define WM5100_EQ3_B3_B_WIDTH 16 /* EQ3_B3_B - [15:0] */ + +/* + * R3655 (0xE47) - EQ3_12 + */ +#define WM5100_EQ3_B3_C_MASK 0xFFFF /* EQ3_B3_C - [15:0] */ +#define WM5100_EQ3_B3_C_SHIFT 0 /* EQ3_B3_C - [15:0] */ +#define WM5100_EQ3_B3_C_WIDTH 16 /* EQ3_B3_C - [15:0] */ + +/* + * R3656 (0xE48) - EQ3_13 + */ +#define WM5100_EQ3_B3_PG_MASK 0xFFFF /* EQ3_B3_PG - [15:0] */ +#define WM5100_EQ3_B3_PG_SHIFT 0 /* EQ3_B3_PG - [15:0] */ +#define WM5100_EQ3_B3_PG_WIDTH 16 /* EQ3_B3_PG - [15:0] */ + +/* + * R3657 (0xE49) - EQ3_14 + */ +#define WM5100_EQ3_B4_A_MASK 0xFFFF /* EQ3_B4_A - [15:0] */ +#define WM5100_EQ3_B4_A_SHIFT 0 /* EQ3_B4_A - [15:0] */ +#define WM5100_EQ3_B4_A_WIDTH 16 /* EQ3_B4_A - [15:0] */ + +/* + * R3658 (0xE4A) - EQ3_15 + */ +#define WM5100_EQ3_B4_B_MASK 0xFFFF /* EQ3_B4_B - [15:0] */ +#define WM5100_EQ3_B4_B_SHIFT 0 /* EQ3_B4_B - [15:0] */ +#define WM5100_EQ3_B4_B_WIDTH 16 /* EQ3_B4_B - [15:0] */ + +/* + * R3659 (0xE4B) - EQ3_16 + */ +#define WM5100_EQ3_B4_C_MASK 0xFFFF /* EQ3_B4_C - [15:0] */ +#define WM5100_EQ3_B4_C_SHIFT 0 /* EQ3_B4_C - [15:0] */ +#define WM5100_EQ3_B4_C_WIDTH 16 /* EQ3_B4_C - [15:0] */ + +/* + * R3660 (0xE4C) - EQ3_17 + */ +#define WM5100_EQ3_B4_PG_MASK 0xFFFF /* EQ3_B4_PG - [15:0] */ +#define WM5100_EQ3_B4_PG_SHIFT 0 /* EQ3_B4_PG - [15:0] */ +#define WM5100_EQ3_B4_PG_WIDTH 16 /* EQ3_B4_PG - [15:0] */ + +/* + * R3661 (0xE4D) - EQ3_18 + */ +#define WM5100_EQ3_B5_A_MASK 0xFFFF /* EQ3_B5_A - [15:0] */ +#define WM5100_EQ3_B5_A_SHIFT 0 /* EQ3_B5_A - [15:0] */ +#define WM5100_EQ3_B5_A_WIDTH 16 /* EQ3_B5_A - [15:0] */ + +/* + * R3662 (0xE4E) - EQ3_19 + */ +#define WM5100_EQ3_B5_B_MASK 0xFFFF /* EQ3_B5_B - [15:0] */ +#define WM5100_EQ3_B5_B_SHIFT 0 /* EQ3_B5_B - [15:0] */ +#define WM5100_EQ3_B5_B_WIDTH 16 /* EQ3_B5_B - [15:0] */ + +/* + * R3663 (0xE4F) - EQ3_20 + */ +#define WM5100_EQ3_B5_PG_MASK 0xFFFF /* EQ3_B5_PG - [15:0] */ +#define WM5100_EQ3_B5_PG_SHIFT 0 /* EQ3_B5_PG - [15:0] */ +#define WM5100_EQ3_B5_PG_WIDTH 16 /* EQ3_B5_PG - [15:0] */ + +/* + * R3666 (0xE52) - EQ4_1 + */ +#define WM5100_EQ4_B1_GAIN_MASK 0xF800 /* EQ4_B1_GAIN - [15:11] */ +#define WM5100_EQ4_B1_GAIN_SHIFT 11 /* EQ4_B1_GAIN - [15:11] */ +#define WM5100_EQ4_B1_GAIN_WIDTH 5 /* EQ4_B1_GAIN - [15:11] */ +#define WM5100_EQ4_B2_GAIN_MASK 0x07C0 /* EQ4_B2_GAIN - [10:6] */ +#define WM5100_EQ4_B2_GAIN_SHIFT 6 /* EQ4_B2_GAIN - [10:6] */ +#define WM5100_EQ4_B2_GAIN_WIDTH 5 /* EQ4_B2_GAIN - [10:6] */ +#define WM5100_EQ4_B3_GAIN_MASK 0x003E /* EQ4_B3_GAIN - [5:1] */ +#define WM5100_EQ4_B3_GAIN_SHIFT 1 /* EQ4_B3_GAIN - [5:1] */ +#define WM5100_EQ4_B3_GAIN_WIDTH 5 /* EQ4_B3_GAIN - [5:1] */ +#define WM5100_EQ4_ENA 0x0001 /* EQ4_ENA */ +#define WM5100_EQ4_ENA_MASK 0x0001 /* EQ4_ENA */ +#define WM5100_EQ4_ENA_SHIFT 0 /* EQ4_ENA */ +#define WM5100_EQ4_ENA_WIDTH 1 /* EQ4_ENA */ + +/* + * R3667 (0xE53) - EQ4_2 + */ +#define WM5100_EQ4_B4_GAIN_MASK 0xF800 /* EQ4_B4_GAIN - [15:11] */ +#define WM5100_EQ4_B4_GAIN_SHIFT 11 /* EQ4_B4_GAIN - [15:11] */ +#define WM5100_EQ4_B4_GAIN_WIDTH 5 /* EQ4_B4_GAIN - [15:11] */ +#define WM5100_EQ4_B5_GAIN_MASK 0x07C0 /* EQ4_B5_GAIN - [10:6] */ +#define WM5100_EQ4_B5_GAIN_SHIFT 6 /* EQ4_B5_GAIN - [10:6] */ +#define WM5100_EQ4_B5_GAIN_WIDTH 5 /* EQ4_B5_GAIN - [10:6] */ + +/* + * R3668 (0xE54) - EQ4_3 + */ +#define WM5100_EQ4_B1_A_MASK 0xFFFF /* EQ4_B1_A - [15:0] */ +#define WM5100_EQ4_B1_A_SHIFT 0 /* EQ4_B1_A - [15:0] */ +#define WM5100_EQ4_B1_A_WIDTH 16 /* EQ4_B1_A - [15:0] */ + +/* + * R3669 (0xE55) - EQ4_4 + */ +#define WM5100_EQ4_B1_B_MASK 0xFFFF /* EQ4_B1_B - [15:0] */ +#define WM5100_EQ4_B1_B_SHIFT 0 /* EQ4_B1_B - [15:0] */ +#define WM5100_EQ4_B1_B_WIDTH 16 /* EQ4_B1_B - [15:0] */ + +/* + * R3670 (0xE56) - EQ4_5 + */ +#define WM5100_EQ4_B1_PG_MASK 0xFFFF /* EQ4_B1_PG - [15:0] */ +#define WM5100_EQ4_B1_PG_SHIFT 0 /* EQ4_B1_PG - [15:0] */ +#define WM5100_EQ4_B1_PG_WIDTH 16 /* EQ4_B1_PG - [15:0] */ + +/* + * R3671 (0xE57) - EQ4_6 + */ +#define WM5100_EQ4_B2_A_MASK 0xFFFF /* EQ4_B2_A - [15:0] */ +#define WM5100_EQ4_B2_A_SHIFT 0 /* EQ4_B2_A - [15:0] */ +#define WM5100_EQ4_B2_A_WIDTH 16 /* EQ4_B2_A - [15:0] */ + +/* + * R3672 (0xE58) - EQ4_7 + */ +#define WM5100_EQ4_B2_B_MASK 0xFFFF /* EQ4_B2_B - [15:0] */ +#define WM5100_EQ4_B2_B_SHIFT 0 /* EQ4_B2_B - [15:0] */ +#define WM5100_EQ4_B2_B_WIDTH 16 /* EQ4_B2_B - [15:0] */ + +/* + * R3673 (0xE59) - EQ4_8 + */ +#define WM5100_EQ4_B2_C_MASK 0xFFFF /* EQ4_B2_C - [15:0] */ +#define WM5100_EQ4_B2_C_SHIFT 0 /* EQ4_B2_C - [15:0] */ +#define WM5100_EQ4_B2_C_WIDTH 16 /* EQ4_B2_C - [15:0] */ + +/* + * R3674 (0xE5A) - EQ4_9 + */ +#define WM5100_EQ4_B2_PG_MASK 0xFFFF /* EQ4_B2_PG - [15:0] */ +#define WM5100_EQ4_B2_PG_SHIFT 0 /* EQ4_B2_PG - [15:0] */ +#define WM5100_EQ4_B2_PG_WIDTH 16 /* EQ4_B2_PG - [15:0] */ + +/* + * R3675 (0xE5B) - EQ4_10 + */ +#define WM5100_EQ4_B3_A_MASK 0xFFFF /* EQ4_B3_A - [15:0] */ +#define WM5100_EQ4_B3_A_SHIFT 0 /* EQ4_B3_A - [15:0] */ +#define WM5100_EQ4_B3_A_WIDTH 16 /* EQ4_B3_A - [15:0] */ + +/* + * R3676 (0xE5C) - EQ4_11 + */ +#define WM5100_EQ4_B3_B_MASK 0xFFFF /* EQ4_B3_B - [15:0] */ +#define WM5100_EQ4_B3_B_SHIFT 0 /* EQ4_B3_B - [15:0] */ +#define WM5100_EQ4_B3_B_WIDTH 16 /* EQ4_B3_B - [15:0] */ + +/* + * R3677 (0xE5D) - EQ4_12 + */ +#define WM5100_EQ4_B3_C_MASK 0xFFFF /* EQ4_B3_C - [15:0] */ +#define WM5100_EQ4_B3_C_SHIFT 0 /* EQ4_B3_C - [15:0] */ +#define WM5100_EQ4_B3_C_WIDTH 16 /* EQ4_B3_C - [15:0] */ + +/* + * R3678 (0xE5E) - EQ4_13 + */ +#define WM5100_EQ4_B3_PG_MASK 0xFFFF /* EQ4_B3_PG - [15:0] */ +#define WM5100_EQ4_B3_PG_SHIFT 0 /* EQ4_B3_PG - [15:0] */ +#define WM5100_EQ4_B3_PG_WIDTH 16 /* EQ4_B3_PG - [15:0] */ + +/* + * R3679 (0xE5F) - EQ4_14 + */ +#define WM5100_EQ4_B4_A_MASK 0xFFFF /* EQ4_B4_A - [15:0] */ +#define WM5100_EQ4_B4_A_SHIFT 0 /* EQ4_B4_A - [15:0] */ +#define WM5100_EQ4_B4_A_WIDTH 16 /* EQ4_B4_A - [15:0] */ + +/* + * R3680 (0xE60) - EQ4_15 + */ +#define WM5100_EQ4_B4_B_MASK 0xFFFF /* EQ4_B4_B - [15:0] */ +#define WM5100_EQ4_B4_B_SHIFT 0 /* EQ4_B4_B - [15:0] */ +#define WM5100_EQ4_B4_B_WIDTH 16 /* EQ4_B4_B - [15:0] */ + +/* + * R3681 (0xE61) - EQ4_16 + */ +#define WM5100_EQ4_B4_C_MASK 0xFFFF /* EQ4_B4_C - [15:0] */ +#define WM5100_EQ4_B4_C_SHIFT 0 /* EQ4_B4_C - [15:0] */ +#define WM5100_EQ4_B4_C_WIDTH 16 /* EQ4_B4_C - [15:0] */ + +/* + * R3682 (0xE62) - EQ4_17 + */ +#define WM5100_EQ4_B4_PG_MASK 0xFFFF /* EQ4_B4_PG - [15:0] */ +#define WM5100_EQ4_B4_PG_SHIFT 0 /* EQ4_B4_PG - [15:0] */ +#define WM5100_EQ4_B4_PG_WIDTH 16 /* EQ4_B4_PG - [15:0] */ + +/* + * R3683 (0xE63) - EQ4_18 + */ +#define WM5100_EQ4_B5_A_MASK 0xFFFF /* EQ4_B5_A - [15:0] */ +#define WM5100_EQ4_B5_A_SHIFT 0 /* EQ4_B5_A - [15:0] */ +#define WM5100_EQ4_B5_A_WIDTH 16 /* EQ4_B5_A - [15:0] */ + +/* + * R3684 (0xE64) - EQ4_19 + */ +#define WM5100_EQ4_B5_B_MASK 0xFFFF /* EQ4_B5_B - [15:0] */ +#define WM5100_EQ4_B5_B_SHIFT 0 /* EQ4_B5_B - [15:0] */ +#define WM5100_EQ4_B5_B_WIDTH 16 /* EQ4_B5_B - [15:0] */ + +/* + * R3685 (0xE65) - EQ4_20 + */ +#define WM5100_EQ4_B5_PG_MASK 0xFFFF /* EQ4_B5_PG - [15:0] */ +#define WM5100_EQ4_B5_PG_SHIFT 0 /* EQ4_B5_PG - [15:0] */ +#define WM5100_EQ4_B5_PG_WIDTH 16 /* EQ4_B5_PG - [15:0] */ + +/* + * R3712 (0xE80) - DRC1 ctrl1 + */ +#define WM5100_DRC_SIG_DET_RMS_MASK 0xF800 /* DRC_SIG_DET_RMS - [15:11] */ +#define WM5100_DRC_SIG_DET_RMS_SHIFT 11 /* DRC_SIG_DET_RMS - [15:11] */ +#define WM5100_DRC_SIG_DET_RMS_WIDTH 5 /* DRC_SIG_DET_RMS - [15:11] */ +#define WM5100_DRC_SIG_DET_PK_MASK 0x0600 /* DRC_SIG_DET_PK - [10:9] */ +#define WM5100_DRC_SIG_DET_PK_SHIFT 9 /* DRC_SIG_DET_PK - [10:9] */ +#define WM5100_DRC_SIG_DET_PK_WIDTH 2 /* DRC_SIG_DET_PK - [10:9] */ +#define WM5100_DRC_NG_ENA 0x0100 /* DRC_NG_ENA */ +#define WM5100_DRC_NG_ENA_MASK 0x0100 /* DRC_NG_ENA */ +#define WM5100_DRC_NG_ENA_SHIFT 8 /* DRC_NG_ENA */ +#define WM5100_DRC_NG_ENA_WIDTH 1 /* DRC_NG_ENA */ +#define WM5100_DRC_SIG_DET_MODE 0x0080 /* DRC_SIG_DET_MODE */ +#define WM5100_DRC_SIG_DET_MODE_MASK 0x0080 /* DRC_SIG_DET_MODE */ +#define WM5100_DRC_SIG_DET_MODE_SHIFT 7 /* DRC_SIG_DET_MODE */ +#define WM5100_DRC_SIG_DET_MODE_WIDTH 1 /* DRC_SIG_DET_MODE */ +#define WM5100_DRC_SIG_DET 0x0040 /* DRC_SIG_DET */ +#define WM5100_DRC_SIG_DET_MASK 0x0040 /* DRC_SIG_DET */ +#define WM5100_DRC_SIG_DET_SHIFT 6 /* DRC_SIG_DET */ +#define WM5100_DRC_SIG_DET_WIDTH 1 /* DRC_SIG_DET */ +#define WM5100_DRC_KNEE2_OP_ENA 0x0020 /* DRC_KNEE2_OP_ENA */ +#define WM5100_DRC_KNEE2_OP_ENA_MASK 0x0020 /* DRC_KNEE2_OP_ENA */ +#define WM5100_DRC_KNEE2_OP_ENA_SHIFT 5 /* DRC_KNEE2_OP_ENA */ +#define WM5100_DRC_KNEE2_OP_ENA_WIDTH 1 /* DRC_KNEE2_OP_ENA */ +#define WM5100_DRC_QR 0x0010 /* DRC_QR */ +#define WM5100_DRC_QR_MASK 0x0010 /* DRC_QR */ +#define WM5100_DRC_QR_SHIFT 4 /* DRC_QR */ +#define WM5100_DRC_QR_WIDTH 1 /* DRC_QR */ +#define WM5100_DRC_ANTICLIP 0x0008 /* DRC_ANTICLIP */ +#define WM5100_DRC_ANTICLIP_MASK 0x0008 /* DRC_ANTICLIP */ +#define WM5100_DRC_ANTICLIP_SHIFT 3 /* DRC_ANTICLIP */ +#define WM5100_DRC_ANTICLIP_WIDTH 1 /* DRC_ANTICLIP */ +#define WM5100_DRCL_ENA 0x0002 /* DRCL_ENA */ +#define WM5100_DRCL_ENA_MASK 0x0002 /* DRCL_ENA */ +#define WM5100_DRCL_ENA_SHIFT 1 /* DRCL_ENA */ +#define WM5100_DRCL_ENA_WIDTH 1 /* DRCL_ENA */ +#define WM5100_DRCR_ENA 0x0001 /* DRCR_ENA */ +#define WM5100_DRCR_ENA_MASK 0x0001 /* DRCR_ENA */ +#define WM5100_DRCR_ENA_SHIFT 0 /* DRCR_ENA */ +#define WM5100_DRCR_ENA_WIDTH 1 /* DRCR_ENA */ + +/* + * R3713 (0xE81) - DRC1 ctrl2 + */ +#define WM5100_DRC_ATK_MASK 0x1E00 /* DRC_ATK - [12:9] */ +#define WM5100_DRC_ATK_SHIFT 9 /* DRC_ATK - [12:9] */ +#define WM5100_DRC_ATK_WIDTH 4 /* DRC_ATK - [12:9] */ +#define WM5100_DRC_DCY_MASK 0x01E0 /* DRC_DCY - [8:5] */ +#define WM5100_DRC_DCY_SHIFT 5 /* DRC_DCY - [8:5] */ +#define WM5100_DRC_DCY_WIDTH 4 /* DRC_DCY - [8:5] */ +#define WM5100_DRC_MINGAIN_MASK 0x001C /* DRC_MINGAIN - [4:2] */ +#define WM5100_DRC_MINGAIN_SHIFT 2 /* DRC_MINGAIN - [4:2] */ +#define WM5100_DRC_MINGAIN_WIDTH 3 /* DRC_MINGAIN - [4:2] */ +#define WM5100_DRC_MAXGAIN_MASK 0x0003 /* DRC_MAXGAIN - [1:0] */ +#define WM5100_DRC_MAXGAIN_SHIFT 0 /* DRC_MAXGAIN - [1:0] */ +#define WM5100_DRC_MAXGAIN_WIDTH 2 /* DRC_MAXGAIN - [1:0] */ + +/* + * R3714 (0xE82) - DRC1 ctrl3 + */ +#define WM5100_DRC_NG_MINGAIN_MASK 0xF000 /* DRC_NG_MINGAIN - [15:12] */ +#define WM5100_DRC_NG_MINGAIN_SHIFT 12 /* DRC_NG_MINGAIN - [15:12] */ +#define WM5100_DRC_NG_MINGAIN_WIDTH 4 /* DRC_NG_MINGAIN - [15:12] */ +#define WM5100_DRC_NG_EXP_MASK 0x0C00 /* DRC_NG_EXP - [11:10] */ +#define WM5100_DRC_NG_EXP_SHIFT 10 /* DRC_NG_EXP - [11:10] */ +#define WM5100_DRC_NG_EXP_WIDTH 2 /* DRC_NG_EXP - [11:10] */ +#define WM5100_DRC_QR_THR_MASK 0x0300 /* DRC_QR_THR - [9:8] */ +#define WM5100_DRC_QR_THR_SHIFT 8 /* DRC_QR_THR - [9:8] */ +#define WM5100_DRC_QR_THR_WIDTH 2 /* DRC_QR_THR - [9:8] */ +#define WM5100_DRC_QR_DCY_MASK 0x00C0 /* DRC_QR_DCY - [7:6] */ +#define WM5100_DRC_QR_DCY_SHIFT 6 /* DRC_QR_DCY - [7:6] */ +#define WM5100_DRC_QR_DCY_WIDTH 2 /* DRC_QR_DCY - [7:6] */ +#define WM5100_DRC_HI_COMP_MASK 0x0038 /* DRC_HI_COMP - [5:3] */ +#define WM5100_DRC_HI_COMP_SHIFT 3 /* DRC_HI_COMP - [5:3] */ +#define WM5100_DRC_HI_COMP_WIDTH 3 /* DRC_HI_COMP - [5:3] */ +#define WM5100_DRC_LO_COMP_MASK 0x0007 /* DRC_LO_COMP - [2:0] */ +#define WM5100_DRC_LO_COMP_SHIFT 0 /* DRC_LO_COMP - [2:0] */ +#define WM5100_DRC_LO_COMP_WIDTH 3 /* DRC_LO_COMP - [2:0] */ + +/* + * R3715 (0xE83) - DRC1 ctrl4 + */ +#define WM5100_DRC_KNEE_IP_MASK 0x07E0 /* DRC_KNEE_IP - [10:5] */ +#define WM5100_DRC_KNEE_IP_SHIFT 5 /* DRC_KNEE_IP - [10:5] */ +#define WM5100_DRC_KNEE_IP_WIDTH 6 /* DRC_KNEE_IP - [10:5] */ +#define WM5100_DRC_KNEE_OP_MASK 0x001F /* DRC_KNEE_OP - [4:0] */ +#define WM5100_DRC_KNEE_OP_SHIFT 0 /* DRC_KNEE_OP - [4:0] */ +#define WM5100_DRC_KNEE_OP_WIDTH 5 /* DRC_KNEE_OP - [4:0] */ + +/* + * R3716 (0xE84) - DRC1 ctrl5 + */ +#define WM5100_DRC_KNEE2_IP_MASK 0x03E0 /* DRC_KNEE2_IP - [9:5] */ +#define WM5100_DRC_KNEE2_IP_SHIFT 5 /* DRC_KNEE2_IP - [9:5] */ +#define WM5100_DRC_KNEE2_IP_WIDTH 5 /* DRC_KNEE2_IP - [9:5] */ +#define WM5100_DRC_KNEE2_OP_MASK 0x001F /* DRC_KNEE2_OP - [4:0] */ +#define WM5100_DRC_KNEE2_OP_SHIFT 0 /* DRC_KNEE2_OP - [4:0] */ +#define WM5100_DRC_KNEE2_OP_WIDTH 5 /* DRC_KNEE2_OP - [4:0] */ + +/* + * R3776 (0xEC0) - HPLPF1_1 + */ +#define WM5100_LHPF1_MODE 0x0002 /* LHPF1_MODE */ +#define WM5100_LHPF1_MODE_MASK 0x0002 /* LHPF1_MODE */ +#define WM5100_LHPF1_MODE_SHIFT 1 /* LHPF1_MODE */ +#define WM5100_LHPF1_MODE_WIDTH 1 /* LHPF1_MODE */ +#define WM5100_LHPF1_ENA 0x0001 /* LHPF1_ENA */ +#define WM5100_LHPF1_ENA_MASK 0x0001 /* LHPF1_ENA */ +#define WM5100_LHPF1_ENA_SHIFT 0 /* LHPF1_ENA */ +#define WM5100_LHPF1_ENA_WIDTH 1 /* LHPF1_ENA */ + +/* + * R3777 (0xEC1) - HPLPF1_2 + */ +#define WM5100_LHPF1_COEFF_MASK 0xFFFF /* LHPF1_COEFF - [15:0] */ +#define WM5100_LHPF1_COEFF_SHIFT 0 /* LHPF1_COEFF - [15:0] */ +#define WM5100_LHPF1_COEFF_WIDTH 16 /* LHPF1_COEFF - [15:0] */ + +/* + * R3780 (0xEC4) - HPLPF2_1 + */ +#define WM5100_LHPF2_MODE 0x0002 /* LHPF2_MODE */ +#define WM5100_LHPF2_MODE_MASK 0x0002 /* LHPF2_MODE */ +#define WM5100_LHPF2_MODE_SHIFT 1 /* LHPF2_MODE */ +#define WM5100_LHPF2_MODE_WIDTH 1 /* LHPF2_MODE */ +#define WM5100_LHPF2_ENA 0x0001 /* LHPF2_ENA */ +#define WM5100_LHPF2_ENA_MASK 0x0001 /* LHPF2_ENA */ +#define WM5100_LHPF2_ENA_SHIFT 0 /* LHPF2_ENA */ +#define WM5100_LHPF2_ENA_WIDTH 1 /* LHPF2_ENA */ + +/* + * R3781 (0xEC5) - HPLPF2_2 + */ +#define WM5100_LHPF2_COEFF_MASK 0xFFFF /* LHPF2_COEFF - [15:0] */ +#define WM5100_LHPF2_COEFF_SHIFT 0 /* LHPF2_COEFF - [15:0] */ +#define WM5100_LHPF2_COEFF_WIDTH 16 /* LHPF2_COEFF - [15:0] */ + +/* + * R3784 (0xEC8) - HPLPF3_1 + */ +#define WM5100_LHPF3_MODE 0x0002 /* LHPF3_MODE */ +#define WM5100_LHPF3_MODE_MASK 0x0002 /* LHPF3_MODE */ +#define WM5100_LHPF3_MODE_SHIFT 1 /* LHPF3_MODE */ +#define WM5100_LHPF3_MODE_WIDTH 1 /* LHPF3_MODE */ +#define WM5100_LHPF3_ENA 0x0001 /* LHPF3_ENA */ +#define WM5100_LHPF3_ENA_MASK 0x0001 /* LHPF3_ENA */ +#define WM5100_LHPF3_ENA_SHIFT 0 /* LHPF3_ENA */ +#define WM5100_LHPF3_ENA_WIDTH 1 /* LHPF3_ENA */ + +/* + * R3785 (0xEC9) - HPLPF3_2 + */ +#define WM5100_LHPF3_COEFF_MASK 0xFFFF /* LHPF3_COEFF - [15:0] */ +#define WM5100_LHPF3_COEFF_SHIFT 0 /* LHPF3_COEFF - [15:0] */ +#define WM5100_LHPF3_COEFF_WIDTH 16 /* LHPF3_COEFF - [15:0] */ + +/* + * R3788 (0xECC) - HPLPF4_1 + */ +#define WM5100_LHPF4_MODE 0x0002 /* LHPF4_MODE */ +#define WM5100_LHPF4_MODE_MASK 0x0002 /* LHPF4_MODE */ +#define WM5100_LHPF4_MODE_SHIFT 1 /* LHPF4_MODE */ +#define WM5100_LHPF4_MODE_WIDTH 1 /* LHPF4_MODE */ +#define WM5100_LHPF4_ENA 0x0001 /* LHPF4_ENA */ +#define WM5100_LHPF4_ENA_MASK 0x0001 /* LHPF4_ENA */ +#define WM5100_LHPF4_ENA_SHIFT 0 /* LHPF4_ENA */ +#define WM5100_LHPF4_ENA_WIDTH 1 /* LHPF4_ENA */ + +/* + * R3789 (0xECD) - HPLPF4_2 + */ +#define WM5100_LHPF4_COEFF_MASK 0xFFFF /* LHPF4_COEFF - [15:0] */ +#define WM5100_LHPF4_COEFF_SHIFT 0 /* LHPF4_COEFF - [15:0] */ +#define WM5100_LHPF4_COEFF_WIDTH 16 /* LHPF4_COEFF - [15:0] */ + +/* + * R16384 (0x4000) - DSP1 DM 0 + */ +#define WM5100_DSP1_DM_START_1_MASK 0x00FF /* DSP1_DM_START - [7:0] */ +#define WM5100_DSP1_DM_START_1_SHIFT 0 /* DSP1_DM_START - [7:0] */ +#define WM5100_DSP1_DM_START_1_WIDTH 8 /* DSP1_DM_START - [7:0] */ + +/* + * R16385 (0x4001) - DSP1 DM 1 + */ +#define WM5100_DSP1_DM_START_MASK 0xFFFF /* DSP1_DM_START - [15:0] */ +#define WM5100_DSP1_DM_START_SHIFT 0 /* DSP1_DM_START - [15:0] */ +#define WM5100_DSP1_DM_START_WIDTH 16 /* DSP1_DM_START - [15:0] */ + +/* + * R16386 (0x4002) - DSP1 DM 2 + */ +#define WM5100_DSP1_DM_1_1_MASK 0x00FF /* DSP1_DM_1 - [7:0] */ +#define WM5100_DSP1_DM_1_1_SHIFT 0 /* DSP1_DM_1 - [7:0] */ +#define WM5100_DSP1_DM_1_1_WIDTH 8 /* DSP1_DM_1 - [7:0] */ + +/* + * R16387 (0x4003) - DSP1 DM 3 + */ +#define WM5100_DSP1_DM_1_MASK 0xFFFF /* DSP1_DM_1 - [15:0] */ +#define WM5100_DSP1_DM_1_SHIFT 0 /* DSP1_DM_1 - [15:0] */ +#define WM5100_DSP1_DM_1_WIDTH 16 /* DSP1_DM_1 - [15:0] */ + +/* + * R16892 (0x41FC) - DSP1 DM 508 + */ +#define WM5100_DSP1_DM_254_1_MASK 0x00FF /* DSP1_DM_254 - [7:0] */ +#define WM5100_DSP1_DM_254_1_SHIFT 0 /* DSP1_DM_254 - [7:0] */ +#define WM5100_DSP1_DM_254_1_WIDTH 8 /* DSP1_DM_254 - [7:0] */ + +/* + * R16893 (0x41FD) - DSP1 DM 509 + */ +#define WM5100_DSP1_DM_254_MASK 0xFFFF /* DSP1_DM_254 - [15:0] */ +#define WM5100_DSP1_DM_254_SHIFT 0 /* DSP1_DM_254 - [15:0] */ +#define WM5100_DSP1_DM_254_WIDTH 16 /* DSP1_DM_254 - [15:0] */ + +/* + * R16894 (0x41FE) - DSP1 DM 510 + */ +#define WM5100_DSP1_DM_END_1_MASK 0x00FF /* DSP1_DM_END - [7:0] */ +#define WM5100_DSP1_DM_END_1_SHIFT 0 /* DSP1_DM_END - [7:0] */ +#define WM5100_DSP1_DM_END_1_WIDTH 8 /* DSP1_DM_END - [7:0] */ + +/* + * R16895 (0x41FF) - DSP1 DM 511 + */ +#define WM5100_DSP1_DM_END_MASK 0xFFFF /* DSP1_DM_END - [15:0] */ +#define WM5100_DSP1_DM_END_SHIFT 0 /* DSP1_DM_END - [15:0] */ +#define WM5100_DSP1_DM_END_WIDTH 16 /* DSP1_DM_END - [15:0] */ + +/* + * R18432 (0x4800) - DSP1 PM 0 + */ +#define WM5100_DSP1_PM_START_2_MASK 0x00FF /* DSP1_PM_START - [7:0] */ +#define WM5100_DSP1_PM_START_2_SHIFT 0 /* DSP1_PM_START - [7:0] */ +#define WM5100_DSP1_PM_START_2_WIDTH 8 /* DSP1_PM_START - [7:0] */ + +/* + * R18433 (0x4801) - DSP1 PM 1 + */ +#define WM5100_DSP1_PM_START_1_MASK 0xFFFF /* DSP1_PM_START - [15:0] */ +#define WM5100_DSP1_PM_START_1_SHIFT 0 /* DSP1_PM_START - [15:0] */ +#define WM5100_DSP1_PM_START_1_WIDTH 16 /* DSP1_PM_START - [15:0] */ + +/* + * R18434 (0x4802) - DSP1 PM 2 + */ +#define WM5100_DSP1_PM_START_MASK 0xFFFF /* DSP1_PM_START - [15:0] */ +#define WM5100_DSP1_PM_START_SHIFT 0 /* DSP1_PM_START - [15:0] */ +#define WM5100_DSP1_PM_START_WIDTH 16 /* DSP1_PM_START - [15:0] */ + +/* + * R18435 (0x4803) - DSP1 PM 3 + */ +#define WM5100_DSP1_PM_1_2_MASK 0x00FF /* DSP1_PM_1 - [7:0] */ +#define WM5100_DSP1_PM_1_2_SHIFT 0 /* DSP1_PM_1 - [7:0] */ +#define WM5100_DSP1_PM_1_2_WIDTH 8 /* DSP1_PM_1 - [7:0] */ + +/* + * R18436 (0x4804) - DSP1 PM 4 + */ +#define WM5100_DSP1_PM_1_1_MASK 0xFFFF /* DSP1_PM_1 - [15:0] */ +#define WM5100_DSP1_PM_1_1_SHIFT 0 /* DSP1_PM_1 - [15:0] */ +#define WM5100_DSP1_PM_1_1_WIDTH 16 /* DSP1_PM_1 - [15:0] */ + +/* + * R18437 (0x4805) - DSP1 PM 5 + */ +#define WM5100_DSP1_PM_1_MASK 0xFFFF /* DSP1_PM_1 - [15:0] */ +#define WM5100_DSP1_PM_1_SHIFT 0 /* DSP1_PM_1 - [15:0] */ +#define WM5100_DSP1_PM_1_WIDTH 16 /* DSP1_PM_1 - [15:0] */ + +/* + * R19962 (0x4DFA) - DSP1 PM 1530 + */ +#define WM5100_DSP1_PM_510_2_MASK 0x00FF /* DSP1_PM_510 - [7:0] */ +#define WM5100_DSP1_PM_510_2_SHIFT 0 /* DSP1_PM_510 - [7:0] */ +#define WM5100_DSP1_PM_510_2_WIDTH 8 /* DSP1_PM_510 - [7:0] */ + +/* + * R19963 (0x4DFB) - DSP1 PM 1531 + */ +#define WM5100_DSP1_PM_510_1_MASK 0xFFFF /* DSP1_PM_510 - [15:0] */ +#define WM5100_DSP1_PM_510_1_SHIFT 0 /* DSP1_PM_510 - [15:0] */ +#define WM5100_DSP1_PM_510_1_WIDTH 16 /* DSP1_PM_510 - [15:0] */ + +/* + * R19964 (0x4DFC) - DSP1 PM 1532 + */ +#define WM5100_DSP1_PM_510_MASK 0xFFFF /* DSP1_PM_510 - [15:0] */ +#define WM5100_DSP1_PM_510_SHIFT 0 /* DSP1_PM_510 - [15:0] */ +#define WM5100_DSP1_PM_510_WIDTH 16 /* DSP1_PM_510 - [15:0] */ + +/* + * R19965 (0x4DFD) - DSP1 PM 1533 + */ +#define WM5100_DSP1_PM_END_2_MASK 0x00FF /* DSP1_PM_END - [7:0] */ +#define WM5100_DSP1_PM_END_2_SHIFT 0 /* DSP1_PM_END - [7:0] */ +#define WM5100_DSP1_PM_END_2_WIDTH 8 /* DSP1_PM_END - [7:0] */ + +/* + * R19966 (0x4DFE) - DSP1 PM 1534 + */ +#define WM5100_DSP1_PM_END_1_MASK 0xFFFF /* DSP1_PM_END - [15:0] */ +#define WM5100_DSP1_PM_END_1_SHIFT 0 /* DSP1_PM_END - [15:0] */ +#define WM5100_DSP1_PM_END_1_WIDTH 16 /* DSP1_PM_END - [15:0] */ + +/* + * R19967 (0x4DFF) - DSP1 PM 1535 + */ +#define WM5100_DSP1_PM_END_MASK 0xFFFF /* DSP1_PM_END - [15:0] */ +#define WM5100_DSP1_PM_END_SHIFT 0 /* DSP1_PM_END - [15:0] */ +#define WM5100_DSP1_PM_END_WIDTH 16 /* DSP1_PM_END - [15:0] */ + +/* + * R20480 (0x5000) - DSP1 ZM 0 + */ +#define WM5100_DSP1_ZM_START_1_MASK 0x00FF /* DSP1_ZM_START - [7:0] */ +#define WM5100_DSP1_ZM_START_1_SHIFT 0 /* DSP1_ZM_START - [7:0] */ +#define WM5100_DSP1_ZM_START_1_WIDTH 8 /* DSP1_ZM_START - [7:0] */ + +/* + * R20481 (0x5001) - DSP1 ZM 1 + */ +#define WM5100_DSP1_ZM_START_MASK 0xFFFF /* DSP1_ZM_START - [15:0] */ +#define WM5100_DSP1_ZM_START_SHIFT 0 /* DSP1_ZM_START - [15:0] */ +#define WM5100_DSP1_ZM_START_WIDTH 16 /* DSP1_ZM_START - [15:0] */ + +/* + * R20482 (0x5002) - DSP1 ZM 2 + */ +#define WM5100_DSP1_ZM_1_1_MASK 0x00FF /* DSP1_ZM_1 - [7:0] */ +#define WM5100_DSP1_ZM_1_1_SHIFT 0 /* DSP1_ZM_1 - [7:0] */ +#define WM5100_DSP1_ZM_1_1_WIDTH 8 /* DSP1_ZM_1 - [7:0] */ + +/* + * R20483 (0x5003) - DSP1 ZM 3 + */ +#define WM5100_DSP1_ZM_1_MASK 0xFFFF /* DSP1_ZM_1 - [15:0] */ +#define WM5100_DSP1_ZM_1_SHIFT 0 /* DSP1_ZM_1 - [15:0] */ +#define WM5100_DSP1_ZM_1_WIDTH 16 /* DSP1_ZM_1 - [15:0] */ + +/* + * R22524 (0x57FC) - DSP1 ZM 2044 + */ +#define WM5100_DSP1_ZM_1022_1_MASK 0x00FF /* DSP1_ZM_1022 - [7:0] */ +#define WM5100_DSP1_ZM_1022_1_SHIFT 0 /* DSP1_ZM_1022 - [7:0] */ +#define WM5100_DSP1_ZM_1022_1_WIDTH 8 /* DSP1_ZM_1022 - [7:0] */ + +/* + * R22525 (0x57FD) - DSP1 ZM 2045 + */ +#define WM5100_DSP1_ZM_1022_MASK 0xFFFF /* DSP1_ZM_1022 - [15:0] */ +#define WM5100_DSP1_ZM_1022_SHIFT 0 /* DSP1_ZM_1022 - [15:0] */ +#define WM5100_DSP1_ZM_1022_WIDTH 16 /* DSP1_ZM_1022 - [15:0] */ + +/* + * R22526 (0x57FE) - DSP1 ZM 2046 + */ +#define WM5100_DSP1_ZM_END_1_MASK 0x00FF /* DSP1_ZM_END - [7:0] */ +#define WM5100_DSP1_ZM_END_1_SHIFT 0 /* DSP1_ZM_END - [7:0] */ +#define WM5100_DSP1_ZM_END_1_WIDTH 8 /* DSP1_ZM_END - [7:0] */ + +/* + * R22527 (0x57FF) - DSP1 ZM 2047 + */ +#define WM5100_DSP1_ZM_END_MASK 0xFFFF /* DSP1_ZM_END - [15:0] */ +#define WM5100_DSP1_ZM_END_SHIFT 0 /* DSP1_ZM_END - [15:0] */ +#define WM5100_DSP1_ZM_END_WIDTH 16 /* DSP1_ZM_END - [15:0] */ + +/* + * R24576 (0x6000) - DSP2 DM 0 + */ +#define WM5100_DSP2_DM_START_1_MASK 0x00FF /* DSP2_DM_START - [7:0] */ +#define WM5100_DSP2_DM_START_1_SHIFT 0 /* DSP2_DM_START - [7:0] */ +#define WM5100_DSP2_DM_START_1_WIDTH 8 /* DSP2_DM_START - [7:0] */ + +/* + * R24577 (0x6001) - DSP2 DM 1 + */ +#define WM5100_DSP2_DM_START_MASK 0xFFFF /* DSP2_DM_START - [15:0] */ +#define WM5100_DSP2_DM_START_SHIFT 0 /* DSP2_DM_START - [15:0] */ +#define WM5100_DSP2_DM_START_WIDTH 16 /* DSP2_DM_START - [15:0] */ + +/* + * R24578 (0x6002) - DSP2 DM 2 + */ +#define WM5100_DSP2_DM_1_1_MASK 0x00FF /* DSP2_DM_1 - [7:0] */ +#define WM5100_DSP2_DM_1_1_SHIFT 0 /* DSP2_DM_1 - [7:0] */ +#define WM5100_DSP2_DM_1_1_WIDTH 8 /* DSP2_DM_1 - [7:0] */ + +/* + * R24579 (0x6003) - DSP2 DM 3 + */ +#define WM5100_DSP2_DM_1_MASK 0xFFFF /* DSP2_DM_1 - [15:0] */ +#define WM5100_DSP2_DM_1_SHIFT 0 /* DSP2_DM_1 - [15:0] */ +#define WM5100_DSP2_DM_1_WIDTH 16 /* DSP2_DM_1 - [15:0] */ + +/* + * R25084 (0x61FC) - DSP2 DM 508 + */ +#define WM5100_DSP2_DM_254_1_MASK 0x00FF /* DSP2_DM_254 - [7:0] */ +#define WM5100_DSP2_DM_254_1_SHIFT 0 /* DSP2_DM_254 - [7:0] */ +#define WM5100_DSP2_DM_254_1_WIDTH 8 /* DSP2_DM_254 - [7:0] */ + +/* + * R25085 (0x61FD) - DSP2 DM 509 + */ +#define WM5100_DSP2_DM_254_MASK 0xFFFF /* DSP2_DM_254 - [15:0] */ +#define WM5100_DSP2_DM_254_SHIFT 0 /* DSP2_DM_254 - [15:0] */ +#define WM5100_DSP2_DM_254_WIDTH 16 /* DSP2_DM_254 - [15:0] */ + +/* + * R25086 (0x61FE) - DSP2 DM 510 + */ +#define WM5100_DSP2_DM_END_1_MASK 0x00FF /* DSP2_DM_END - [7:0] */ +#define WM5100_DSP2_DM_END_1_SHIFT 0 /* DSP2_DM_END - [7:0] */ +#define WM5100_DSP2_DM_END_1_WIDTH 8 /* DSP2_DM_END - [7:0] */ + +/* + * R25087 (0x61FF) - DSP2 DM 511 + */ +#define WM5100_DSP2_DM_END_MASK 0xFFFF /* DSP2_DM_END - [15:0] */ +#define WM5100_DSP2_DM_END_SHIFT 0 /* DSP2_DM_END - [15:0] */ +#define WM5100_DSP2_DM_END_WIDTH 16 /* DSP2_DM_END - [15:0] */ + +/* + * R26624 (0x6800) - DSP2 PM 0 + */ +#define WM5100_DSP2_PM_START_2_MASK 0x00FF /* DSP2_PM_START - [7:0] */ +#define WM5100_DSP2_PM_START_2_SHIFT 0 /* DSP2_PM_START - [7:0] */ +#define WM5100_DSP2_PM_START_2_WIDTH 8 /* DSP2_PM_START - [7:0] */ + +/* + * R26625 (0x6801) - DSP2 PM 1 + */ +#define WM5100_DSP2_PM_START_1_MASK 0xFFFF /* DSP2_PM_START - [15:0] */ +#define WM5100_DSP2_PM_START_1_SHIFT 0 /* DSP2_PM_START - [15:0] */ +#define WM5100_DSP2_PM_START_1_WIDTH 16 /* DSP2_PM_START - [15:0] */ + +/* + * R26626 (0x6802) - DSP2 PM 2 + */ +#define WM5100_DSP2_PM_START_MASK 0xFFFF /* DSP2_PM_START - [15:0] */ +#define WM5100_DSP2_PM_START_SHIFT 0 /* DSP2_PM_START - [15:0] */ +#define WM5100_DSP2_PM_START_WIDTH 16 /* DSP2_PM_START - [15:0] */ + +/* + * R26627 (0x6803) - DSP2 PM 3 + */ +#define WM5100_DSP2_PM_1_2_MASK 0x00FF /* DSP2_PM_1 - [7:0] */ +#define WM5100_DSP2_PM_1_2_SHIFT 0 /* DSP2_PM_1 - [7:0] */ +#define WM5100_DSP2_PM_1_2_WIDTH 8 /* DSP2_PM_1 - [7:0] */ + +/* + * R26628 (0x6804) - DSP2 PM 4 + */ +#define WM5100_DSP2_PM_1_1_MASK 0xFFFF /* DSP2_PM_1 - [15:0] */ +#define WM5100_DSP2_PM_1_1_SHIFT 0 /* DSP2_PM_1 - [15:0] */ +#define WM5100_DSP2_PM_1_1_WIDTH 16 /* DSP2_PM_1 - [15:0] */ + +/* + * R26629 (0x6805) - DSP2 PM 5 + */ +#define WM5100_DSP2_PM_1_MASK 0xFFFF /* DSP2_PM_1 - [15:0] */ +#define WM5100_DSP2_PM_1_SHIFT 0 /* DSP2_PM_1 - [15:0] */ +#define WM5100_DSP2_PM_1_WIDTH 16 /* DSP2_PM_1 - [15:0] */ + +/* + * R28154 (0x6DFA) - DSP2 PM 1530 + */ +#define WM5100_DSP2_PM_510_2_MASK 0x00FF /* DSP2_PM_510 - [7:0] */ +#define WM5100_DSP2_PM_510_2_SHIFT 0 /* DSP2_PM_510 - [7:0] */ +#define WM5100_DSP2_PM_510_2_WIDTH 8 /* DSP2_PM_510 - [7:0] */ + +/* + * R28155 (0x6DFB) - DSP2 PM 1531 + */ +#define WM5100_DSP2_PM_510_1_MASK 0xFFFF /* DSP2_PM_510 - [15:0] */ +#define WM5100_DSP2_PM_510_1_SHIFT 0 /* DSP2_PM_510 - [15:0] */ +#define WM5100_DSP2_PM_510_1_WIDTH 16 /* DSP2_PM_510 - [15:0] */ + +/* + * R28156 (0x6DFC) - DSP2 PM 1532 + */ +#define WM5100_DSP2_PM_510_MASK 0xFFFF /* DSP2_PM_510 - [15:0] */ +#define WM5100_DSP2_PM_510_SHIFT 0 /* DSP2_PM_510 - [15:0] */ +#define WM5100_DSP2_PM_510_WIDTH 16 /* DSP2_PM_510 - [15:0] */ + +/* + * R28157 (0x6DFD) - DSP2 PM 1533 + */ +#define WM5100_DSP2_PM_END_2_MASK 0x00FF /* DSP2_PM_END - [7:0] */ +#define WM5100_DSP2_PM_END_2_SHIFT 0 /* DSP2_PM_END - [7:0] */ +#define WM5100_DSP2_PM_END_2_WIDTH 8 /* DSP2_PM_END - [7:0] */ + +/* + * R28158 (0x6DFE) - DSP2 PM 1534 + */ +#define WM5100_DSP2_PM_END_1_MASK 0xFFFF /* DSP2_PM_END - [15:0] */ +#define WM5100_DSP2_PM_END_1_SHIFT 0 /* DSP2_PM_END - [15:0] */ +#define WM5100_DSP2_PM_END_1_WIDTH 16 /* DSP2_PM_END - [15:0] */ + +/* + * R28159 (0x6DFF) - DSP2 PM 1535 + */ +#define WM5100_DSP2_PM_END_MASK 0xFFFF /* DSP2_PM_END - [15:0] */ +#define WM5100_DSP2_PM_END_SHIFT 0 /* DSP2_PM_END - [15:0] */ +#define WM5100_DSP2_PM_END_WIDTH 16 /* DSP2_PM_END - [15:0] */ + +/* + * R28672 (0x7000) - DSP2 ZM 0 + */ +#define WM5100_DSP2_ZM_START_1_MASK 0x00FF /* DSP2_ZM_START - [7:0] */ +#define WM5100_DSP2_ZM_START_1_SHIFT 0 /* DSP2_ZM_START - [7:0] */ +#define WM5100_DSP2_ZM_START_1_WIDTH 8 /* DSP2_ZM_START - [7:0] */ + +/* + * R28673 (0x7001) - DSP2 ZM 1 + */ +#define WM5100_DSP2_ZM_START_MASK 0xFFFF /* DSP2_ZM_START - [15:0] */ +#define WM5100_DSP2_ZM_START_SHIFT 0 /* DSP2_ZM_START - [15:0] */ +#define WM5100_DSP2_ZM_START_WIDTH 16 /* DSP2_ZM_START - [15:0] */ + +/* + * R28674 (0x7002) - DSP2 ZM 2 + */ +#define WM5100_DSP2_ZM_1_1_MASK 0x00FF /* DSP2_ZM_1 - [7:0] */ +#define WM5100_DSP2_ZM_1_1_SHIFT 0 /* DSP2_ZM_1 - [7:0] */ +#define WM5100_DSP2_ZM_1_1_WIDTH 8 /* DSP2_ZM_1 - [7:0] */ + +/* + * R28675 (0x7003) - DSP2 ZM 3 + */ +#define WM5100_DSP2_ZM_1_MASK 0xFFFF /* DSP2_ZM_1 - [15:0] */ +#define WM5100_DSP2_ZM_1_SHIFT 0 /* DSP2_ZM_1 - [15:0] */ +#define WM5100_DSP2_ZM_1_WIDTH 16 /* DSP2_ZM_1 - [15:0] */ + +/* + * R30716 (0x77FC) - DSP2 ZM 2044 + */ +#define WM5100_DSP2_ZM_1022_1_MASK 0x00FF /* DSP2_ZM_1022 - [7:0] */ +#define WM5100_DSP2_ZM_1022_1_SHIFT 0 /* DSP2_ZM_1022 - [7:0] */ +#define WM5100_DSP2_ZM_1022_1_WIDTH 8 /* DSP2_ZM_1022 - [7:0] */ + +/* + * R30717 (0x77FD) - DSP2 ZM 2045 + */ +#define WM5100_DSP2_ZM_1022_MASK 0xFFFF /* DSP2_ZM_1022 - [15:0] */ +#define WM5100_DSP2_ZM_1022_SHIFT 0 /* DSP2_ZM_1022 - [15:0] */ +#define WM5100_DSP2_ZM_1022_WIDTH 16 /* DSP2_ZM_1022 - [15:0] */ + +/* + * R30718 (0x77FE) - DSP2 ZM 2046 + */ +#define WM5100_DSP2_ZM_END_1_MASK 0x00FF /* DSP2_ZM_END - [7:0] */ +#define WM5100_DSP2_ZM_END_1_SHIFT 0 /* DSP2_ZM_END - [7:0] */ +#define WM5100_DSP2_ZM_END_1_WIDTH 8 /* DSP2_ZM_END - [7:0] */ + +/* + * R30719 (0x77FF) - DSP2 ZM 2047 + */ +#define WM5100_DSP2_ZM_END_MASK 0xFFFF /* DSP2_ZM_END - [15:0] */ +#define WM5100_DSP2_ZM_END_SHIFT 0 /* DSP2_ZM_END - [15:0] */ +#define WM5100_DSP2_ZM_END_WIDTH 16 /* DSP2_ZM_END - [15:0] */ + +/* + * R32768 (0x8000) - DSP3 DM 0 + */ +#define WM5100_DSP3_DM_START_1_MASK 0x00FF /* DSP3_DM_START - [7:0] */ +#define WM5100_DSP3_DM_START_1_SHIFT 0 /* DSP3_DM_START - [7:0] */ +#define WM5100_DSP3_DM_START_1_WIDTH 8 /* DSP3_DM_START - [7:0] */ + +/* + * R32769 (0x8001) - DSP3 DM 1 + */ +#define WM5100_DSP3_DM_START_MASK 0xFFFF /* DSP3_DM_START - [15:0] */ +#define WM5100_DSP3_DM_START_SHIFT 0 /* DSP3_DM_START - [15:0] */ +#define WM5100_DSP3_DM_START_WIDTH 16 /* DSP3_DM_START - [15:0] */ + +/* + * R32770 (0x8002) - DSP3 DM 2 + */ +#define WM5100_DSP3_DM_1_1_MASK 0x00FF /* DSP3_DM_1 - [7:0] */ +#define WM5100_DSP3_DM_1_1_SHIFT 0 /* DSP3_DM_1 - [7:0] */ +#define WM5100_DSP3_DM_1_1_WIDTH 8 /* DSP3_DM_1 - [7:0] */ + +/* + * R32771 (0x8003) - DSP3 DM 3 + */ +#define WM5100_DSP3_DM_1_MASK 0xFFFF /* DSP3_DM_1 - [15:0] */ +#define WM5100_DSP3_DM_1_SHIFT 0 /* DSP3_DM_1 - [15:0] */ +#define WM5100_DSP3_DM_1_WIDTH 16 /* DSP3_DM_1 - [15:0] */ + +/* + * R33276 (0x81FC) - DSP3 DM 508 + */ +#define WM5100_DSP3_DM_254_1_MASK 0x00FF /* DSP3_DM_254 - [7:0] */ +#define WM5100_DSP3_DM_254_1_SHIFT 0 /* DSP3_DM_254 - [7:0] */ +#define WM5100_DSP3_DM_254_1_WIDTH 8 /* DSP3_DM_254 - [7:0] */ + +/* + * R33277 (0x81FD) - DSP3 DM 509 + */ +#define WM5100_DSP3_DM_254_MASK 0xFFFF /* DSP3_DM_254 - [15:0] */ +#define WM5100_DSP3_DM_254_SHIFT 0 /* DSP3_DM_254 - [15:0] */ +#define WM5100_DSP3_DM_254_WIDTH 16 /* DSP3_DM_254 - [15:0] */ + +/* + * R33278 (0x81FE) - DSP3 DM 510 + */ +#define WM5100_DSP3_DM_END_1_MASK 0x00FF /* DSP3_DM_END - [7:0] */ +#define WM5100_DSP3_DM_END_1_SHIFT 0 /* DSP3_DM_END - [7:0] */ +#define WM5100_DSP3_DM_END_1_WIDTH 8 /* DSP3_DM_END - [7:0] */ + +/* + * R33279 (0x81FF) - DSP3 DM 511 + */ +#define WM5100_DSP3_DM_END_MASK 0xFFFF /* DSP3_DM_END - [15:0] */ +#define WM5100_DSP3_DM_END_SHIFT 0 /* DSP3_DM_END - [15:0] */ +#define WM5100_DSP3_DM_END_WIDTH 16 /* DSP3_DM_END - [15:0] */ + +/* + * R34816 (0x8800) - DSP3 PM 0 + */ +#define WM5100_DSP3_PM_START_2_MASK 0x00FF /* DSP3_PM_START - [7:0] */ +#define WM5100_DSP3_PM_START_2_SHIFT 0 /* DSP3_PM_START - [7:0] */ +#define WM5100_DSP3_PM_START_2_WIDTH 8 /* DSP3_PM_START - [7:0] */ + +/* + * R34817 (0x8801) - DSP3 PM 1 + */ +#define WM5100_DSP3_PM_START_1_MASK 0xFFFF /* DSP3_PM_START - [15:0] */ +#define WM5100_DSP3_PM_START_1_SHIFT 0 /* DSP3_PM_START - [15:0] */ +#define WM5100_DSP3_PM_START_1_WIDTH 16 /* DSP3_PM_START - [15:0] */ + +/* + * R34818 (0x8802) - DSP3 PM 2 + */ +#define WM5100_DSP3_PM_START_MASK 0xFFFF /* DSP3_PM_START - [15:0] */ +#define WM5100_DSP3_PM_START_SHIFT 0 /* DSP3_PM_START - [15:0] */ +#define WM5100_DSP3_PM_START_WIDTH 16 /* DSP3_PM_START - [15:0] */ + +/* + * R34819 (0x8803) - DSP3 PM 3 + */ +#define WM5100_DSP3_PM_1_2_MASK 0x00FF /* DSP3_PM_1 - [7:0] */ +#define WM5100_DSP3_PM_1_2_SHIFT 0 /* DSP3_PM_1 - [7:0] */ +#define WM5100_DSP3_PM_1_2_WIDTH 8 /* DSP3_PM_1 - [7:0] */ + +/* + * R34820 (0x8804) - DSP3 PM 4 + */ +#define WM5100_DSP3_PM_1_1_MASK 0xFFFF /* DSP3_PM_1 - [15:0] */ +#define WM5100_DSP3_PM_1_1_SHIFT 0 /* DSP3_PM_1 - [15:0] */ +#define WM5100_DSP3_PM_1_1_WIDTH 16 /* DSP3_PM_1 - [15:0] */ + +/* + * R34821 (0x8805) - DSP3 PM 5 + */ +#define WM5100_DSP3_PM_1_MASK 0xFFFF /* DSP3_PM_1 - [15:0] */ +#define WM5100_DSP3_PM_1_SHIFT 0 /* DSP3_PM_1 - [15:0] */ +#define WM5100_DSP3_PM_1_WIDTH 16 /* DSP3_PM_1 - [15:0] */ + +/* + * R36346 (0x8DFA) - DSP3 PM 1530 + */ +#define WM5100_DSP3_PM_510_2_MASK 0x00FF /* DSP3_PM_510 - [7:0] */ +#define WM5100_DSP3_PM_510_2_SHIFT 0 /* DSP3_PM_510 - [7:0] */ +#define WM5100_DSP3_PM_510_2_WIDTH 8 /* DSP3_PM_510 - [7:0] */ + +/* + * R36347 (0x8DFB) - DSP3 PM 1531 + */ +#define WM5100_DSP3_PM_510_1_MASK 0xFFFF /* DSP3_PM_510 - [15:0] */ +#define WM5100_DSP3_PM_510_1_SHIFT 0 /* DSP3_PM_510 - [15:0] */ +#define WM5100_DSP3_PM_510_1_WIDTH 16 /* DSP3_PM_510 - [15:0] */ + +/* + * R36348 (0x8DFC) - DSP3 PM 1532 + */ +#define WM5100_DSP3_PM_510_MASK 0xFFFF /* DSP3_PM_510 - [15:0] */ +#define WM5100_DSP3_PM_510_SHIFT 0 /* DSP3_PM_510 - [15:0] */ +#define WM5100_DSP3_PM_510_WIDTH 16 /* DSP3_PM_510 - [15:0] */ + +/* + * R36349 (0x8DFD) - DSP3 PM 1533 + */ +#define WM5100_DSP3_PM_END_2_MASK 0x00FF /* DSP3_PM_END - [7:0] */ +#define WM5100_DSP3_PM_END_2_SHIFT 0 /* DSP3_PM_END - [7:0] */ +#define WM5100_DSP3_PM_END_2_WIDTH 8 /* DSP3_PM_END - [7:0] */ + +/* + * R36350 (0x8DFE) - DSP3 PM 1534 + */ +#define WM5100_DSP3_PM_END_1_MASK 0xFFFF /* DSP3_PM_END - [15:0] */ +#define WM5100_DSP3_PM_END_1_SHIFT 0 /* DSP3_PM_END - [15:0] */ +#define WM5100_DSP3_PM_END_1_WIDTH 16 /* DSP3_PM_END - [15:0] */ + +/* + * R36351 (0x8DFF) - DSP3 PM 1535 + */ +#define WM5100_DSP3_PM_END_MASK 0xFFFF /* DSP3_PM_END - [15:0] */ +#define WM5100_DSP3_PM_END_SHIFT 0 /* DSP3_PM_END - [15:0] */ +#define WM5100_DSP3_PM_END_WIDTH 16 /* DSP3_PM_END - [15:0] */ + +/* + * R36864 (0x9000) - DSP3 ZM 0 + */ +#define WM5100_DSP3_ZM_START_1_MASK 0x00FF /* DSP3_ZM_START - [7:0] */ +#define WM5100_DSP3_ZM_START_1_SHIFT 0 /* DSP3_ZM_START - [7:0] */ +#define WM5100_DSP3_ZM_START_1_WIDTH 8 /* DSP3_ZM_START - [7:0] */ + +/* + * R36865 (0x9001) - DSP3 ZM 1 + */ +#define WM5100_DSP3_ZM_START_MASK 0xFFFF /* DSP3_ZM_START - [15:0] */ +#define WM5100_DSP3_ZM_START_SHIFT 0 /* DSP3_ZM_START - [15:0] */ +#define WM5100_DSP3_ZM_START_WIDTH 16 /* DSP3_ZM_START - [15:0] */ + +/* + * R36866 (0x9002) - DSP3 ZM 2 + */ +#define WM5100_DSP3_ZM_1_1_MASK 0x00FF /* DSP3_ZM_1 - [7:0] */ +#define WM5100_DSP3_ZM_1_1_SHIFT 0 /* DSP3_ZM_1 - [7:0] */ +#define WM5100_DSP3_ZM_1_1_WIDTH 8 /* DSP3_ZM_1 - [7:0] */ + +/* + * R36867 (0x9003) - DSP3 ZM 3 + */ +#define WM5100_DSP3_ZM_1_MASK 0xFFFF /* DSP3_ZM_1 - [15:0] */ +#define WM5100_DSP3_ZM_1_SHIFT 0 /* DSP3_ZM_1 - [15:0] */ +#define WM5100_DSP3_ZM_1_WIDTH 16 /* DSP3_ZM_1 - [15:0] */ + +/* + * R38908 (0x97FC) - DSP3 ZM 2044 + */ +#define WM5100_DSP3_ZM_1022_1_MASK 0x00FF /* DSP3_ZM_1022 - [7:0] */ +#define WM5100_DSP3_ZM_1022_1_SHIFT 0 /* DSP3_ZM_1022 - [7:0] */ +#define WM5100_DSP3_ZM_1022_1_WIDTH 8 /* DSP3_ZM_1022 - [7:0] */ + +/* + * R38909 (0x97FD) - DSP3 ZM 2045 + */ +#define WM5100_DSP3_ZM_1022_MASK 0xFFFF /* DSP3_ZM_1022 - [15:0] */ +#define WM5100_DSP3_ZM_1022_SHIFT 0 /* DSP3_ZM_1022 - [15:0] */ +#define WM5100_DSP3_ZM_1022_WIDTH 16 /* DSP3_ZM_1022 - [15:0] */ + +/* + * R38910 (0x97FE) - DSP3 ZM 2046 + */ +#define WM5100_DSP3_ZM_END_1_MASK 0x00FF /* DSP3_ZM_END - [7:0] */ +#define WM5100_DSP3_ZM_END_1_SHIFT 0 /* DSP3_ZM_END - [7:0] */ +#define WM5100_DSP3_ZM_END_1_WIDTH 8 /* DSP3_ZM_END - [7:0] */ + +/* + * R38911 (0x97FF) - DSP3 ZM 2047 + */ +#define WM5100_DSP3_ZM_END_MASK 0xFFFF /* DSP3_ZM_END - [15:0] */ +#define WM5100_DSP3_ZM_END_SHIFT 0 /* DSP3_ZM_END - [15:0] */ +#define WM5100_DSP3_ZM_END_WIDTH 16 /* DSP3_ZM_END - [15:0] */ + +int wm5100_readable_register(struct snd_soc_codec *codec, unsigned int reg); +int wm5100_volatile_register(struct snd_soc_codec *codec, unsigned int reg); + +extern u16 wm5100_reg_defaults[WM5100_MAX_REGISTER + 1]; + +#endif diff --git a/sound/soc/codecs/wm8350.c b/sound/soc/codecs/wm8350.c index 6d6dc9efe91..35f3ad83dfb 100644 --- a/sound/soc/codecs/wm8350.c +++ b/sound/soc/codecs/wm8350.c @@ -355,7 +355,7 @@ static int wm8350_put_volsw_2r_vu(struct snd_kcontrol *kcontrol, return 1; } - ret = snd_soc_put_volsw_2r(kcontrol, ucontrol); + ret = snd_soc_put_volsw(kcontrol, ucontrol); if (ret < 0) return ret; @@ -392,23 +392,9 @@ static int wm8350_get_volsw_2r(struct snd_kcontrol *kcontrol, break; } - return snd_soc_get_volsw_2r(kcontrol, ucontrol); + return snd_soc_get_volsw(kcontrol, ucontrol); } -/* double control with volume update */ -#define SOC_WM8350_DOUBLE_R_TLV(xname, reg_left, reg_right, xshift, xmax, \ - xinvert, tlv_array) \ -{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = (xname), \ - .access = SNDRV_CTL_ELEM_ACCESS_TLV_READ | \ - SNDRV_CTL_ELEM_ACCESS_READWRITE | \ - SNDRV_CTL_ELEM_ACCESS_VOLATILE, \ - .tlv.p = (tlv_array), \ - .info = snd_soc_info_volsw_2r, \ - .get = wm8350_get_volsw_2r, .put = wm8350_put_volsw_2r_vu, \ - .private_value = (unsigned long)&(struct soc_mixer_control) \ - {.reg = reg_left, .rreg = reg_right, .shift = xshift, \ - .rshift = xshift, .max = xmax, .invert = xinvert}, } - static const char *wm8350_deemp[] = { "None", "32kHz", "44.1kHz", "48kHz" }; static const char *wm8350_pol[] = { "Normal", "Inv R", "Inv L", "Inv L & R" }; static const char *wm8350_dacmutem[] = { "Normal", "Soft" }; @@ -443,26 +429,29 @@ static const unsigned int capture_sd_tlv[] = { static const struct snd_kcontrol_new wm8350_snd_controls[] = { SOC_ENUM("Playback Deemphasis", wm8350_enum[0]), SOC_ENUM("Playback DAC Inversion", wm8350_enum[1]), - SOC_WM8350_DOUBLE_R_TLV("Playback PCM Volume", + SOC_DOUBLE_R_EXT_TLV("Playback PCM Volume", WM8350_DAC_DIGITAL_VOLUME_L, WM8350_DAC_DIGITAL_VOLUME_R, - 0, 255, 0, dac_pcm_tlv), + 0, 255, 0, wm8350_get_volsw_2r, + wm8350_put_volsw_2r_vu, dac_pcm_tlv), SOC_ENUM("Playback PCM Mute Function", wm8350_enum[2]), SOC_ENUM("Playback PCM Mute Speed", wm8350_enum[3]), SOC_ENUM("Capture PCM Filter", wm8350_enum[4]), SOC_ENUM("Capture PCM HP Filter", wm8350_enum[5]), SOC_ENUM("Capture ADC Inversion", wm8350_enum[6]), - SOC_WM8350_DOUBLE_R_TLV("Capture PCM Volume", + SOC_DOUBLE_R_EXT_TLV("Capture PCM Volume", WM8350_ADC_DIGITAL_VOLUME_L, WM8350_ADC_DIGITAL_VOLUME_R, - 0, 255, 0, adc_pcm_tlv), + 0, 255, 0, wm8350_get_volsw_2r, + wm8350_put_volsw_2r_vu, adc_pcm_tlv), SOC_DOUBLE_TLV("Capture Sidetone Volume", WM8350_ADC_DIVIDER, 8, 4, 15, 1, capture_sd_tlv), - SOC_WM8350_DOUBLE_R_TLV("Capture Volume", + SOC_DOUBLE_R_EXT_TLV("Capture Volume", WM8350_LEFT_INPUT_VOLUME, WM8350_RIGHT_INPUT_VOLUME, - 2, 63, 0, pre_amp_tlv), + 2, 63, 0, wm8350_get_volsw_2r, + wm8350_put_volsw_2r_vu, pre_amp_tlv), SOC_DOUBLE_R("Capture ZC Switch", WM8350_LEFT_INPUT_VOLUME, WM8350_RIGHT_INPUT_VOLUME, 13, 1, 0), @@ -490,17 +479,19 @@ static const struct snd_kcontrol_new wm8350_snd_controls[] = { SOC_SINGLE_TLV("Out4 Capture Volume", WM8350_INPUT_MIXER_VOLUME, 1, 7, 0, out_mix_tlv), - SOC_WM8350_DOUBLE_R_TLV("Out1 Playback Volume", + SOC_DOUBLE_R_EXT_TLV("Out1 Playback Volume", WM8350_LOUT1_VOLUME, WM8350_ROUT1_VOLUME, - 2, 63, 0, out_pga_tlv), + 2, 63, 0, wm8350_get_volsw_2r, + wm8350_put_volsw_2r_vu, out_pga_tlv), SOC_DOUBLE_R("Out1 Playback ZC Switch", WM8350_LOUT1_VOLUME, WM8350_ROUT1_VOLUME, 13, 1, 0), - SOC_WM8350_DOUBLE_R_TLV("Out2 Playback Volume", + SOC_DOUBLE_R_EXT_TLV("Out2 Playback Volume", WM8350_LOUT2_VOLUME, WM8350_ROUT2_VOLUME, - 2, 63, 0, out_pga_tlv), + 2, 63, 0, wm8350_get_volsw_2r, + wm8350_put_volsw_2r_vu, out_pga_tlv), SOC_DOUBLE_R("Out2 Playback ZC Switch", WM8350_LOUT2_VOLUME, WM8350_ROUT2_VOLUME, 13, 1, 0), SOC_SINGLE("Out2 Right Invert Switch", WM8350_ROUT2_VOLUME, 10, 1, 0), diff --git a/sound/soc/codecs/wm8400.c b/sound/soc/codecs/wm8400.c index fbee556cbf3..dc13be2a09c 100644 --- a/sound/soc/codecs/wm8400.c +++ b/sound/soc/codecs/wm8400.c @@ -383,7 +383,7 @@ static int inmixer_event (struct snd_soc_dapm_widget *w, (1 << WM8400_AINRMUX_PWR))) { reg |= WM8400_AINR_ENA; } else { - reg &= ~WM8400_AINL_ENA; + reg &= ~WM8400_AINR_ENA; } wm8400_write(w->codec, WM8400_POWER_MANAGEMENT_2, reg); diff --git a/sound/soc/codecs/wm8510.c b/sound/soc/codecs/wm8510.c index db0dced7484..07c9cc759e9 100644 --- a/sound/soc/codecs/wm8510.c +++ b/sound/soc/codecs/wm8510.c @@ -20,6 +20,7 @@ #include <linux/platform_device.h> #include <linux/spi/spi.h> #include <linux/slab.h> +#include <linux/of_device.h> #include <sound/core.h> #include <sound/pcm.h> #include <sound/pcm_params.h> @@ -479,6 +480,8 @@ static int wm8510_set_bias_level(struct snd_soc_codec *codec, power1 |= WM8510_POWER1_BIASEN | WM8510_POWER1_BUFIOEN; if (codec->dapm.bias_level == SND_SOC_BIAS_OFF) { + snd_soc_cache_sync(codec); + /* Initial cap charge at VMID 5k */ snd_soc_write(codec, WM8510_POWER1, power1 | 0x3); mdelay(100); @@ -540,18 +543,7 @@ static int wm8510_suspend(struct snd_soc_codec *codec, pm_message_t state) static int wm8510_resume(struct snd_soc_codec *codec) { - int i; - u8 data[2]; - u16 *cache = codec->reg_cache; - - /* Sync reg_cache with the hardware */ - for (i = 0; i < ARRAY_SIZE(wm8510_reg); i++) { - data[0] = (i << 1) | ((cache[i] >> 8) & 0x0001); - data[1] = cache[i] & 0x00ff; - codec->hw_write(codec->control_data, data, 2); - } wm8510_set_bias_level(codec, SND_SOC_BIAS_STANDBY); - return 0; } @@ -598,6 +590,11 @@ static struct snd_soc_codec_driver soc_codec_dev_wm8510 = { .reg_cache_default =wm8510_reg, }; +static const struct of_device_id wm8510_of_match[] = { + { .compatible = "wlf,wm8510" }, + { }, +}; + #if defined(CONFIG_SPI_MASTER) static int __devinit wm8510_spi_probe(struct spi_device *spi) { @@ -628,6 +625,7 @@ static struct spi_driver wm8510_spi_driver = { .driver = { .name = "wm8510", .owner = THIS_MODULE, + .of_match_table = wm8510_of_match, }, .probe = wm8510_spi_probe, .remove = __devexit_p(wm8510_spi_remove), @@ -671,6 +669,7 @@ static struct i2c_driver wm8510_i2c_driver = { .driver = { .name = "wm8510-codec", .owner = THIS_MODULE, + .of_match_table = wm8510_of_match, }, .probe = wm8510_i2c_probe, .remove = __devexit_p(wm8510_i2c_remove), diff --git a/sound/soc/codecs/wm8523.c b/sound/soc/codecs/wm8523.c index 4fd4d8dca0f..db7a6819499 100644 --- a/sound/soc/codecs/wm8523.c +++ b/sound/soc/codecs/wm8523.c @@ -20,6 +20,7 @@ #include <linux/platform_device.h> #include <linux/regulator/consumer.h> #include <linux/slab.h> +#include <linux/of_device.h> #include <sound/core.h> #include <sound/pcm.h> #include <sound/pcm_params.h> @@ -84,7 +85,7 @@ static const char *wm8523_zd_count_text[] = { static const struct soc_enum wm8523_zc_count = SOC_ENUM_SINGLE(WM8523_ZERO_DETECT, 0, 2, wm8523_zd_count_text); -static const struct snd_kcontrol_new wm8523_snd_controls[] = { +static const struct snd_kcontrol_new wm8523_controls[] = { SOC_DOUBLE_R_TLV("Playback Volume", WM8523_DAC_GAINL, WM8523_DAC_GAINR, 0, 448, 0, dac_tlv), SOC_SINGLE("ZC Switch", WM8523_DAC_CTRL3, 4, 1, 0), @@ -101,22 +102,11 @@ SND_SOC_DAPM_OUTPUT("LINEVOUTL"), SND_SOC_DAPM_OUTPUT("LINEVOUTR"), }; -static const struct snd_soc_dapm_route intercon[] = { +static const struct snd_soc_dapm_route wm8523_dapm_routes[] = { { "LINEVOUTL", NULL, "DAC" }, { "LINEVOUTR", NULL, "DAC" }, }; -static int wm8523_add_widgets(struct snd_soc_codec *codec) -{ - struct snd_soc_dapm_context *dapm = &codec->dapm; - - snd_soc_dapm_new_controls(dapm, wm8523_dapm_widgets, - ARRAY_SIZE(wm8523_dapm_widgets)); - snd_soc_dapm_add_routes(dapm, intercon, ARRAY_SIZE(intercon)); - - return 0; -} - static struct { int value; int ratio; @@ -416,7 +406,6 @@ static int wm8523_probe(struct snd_soc_codec *codec) struct wm8523_priv *wm8523 = snd_soc_codec_get_drvdata(codec); int ret, i; - codec->hw_write = (hw_write_t)i2c_master_send; wm8523->rate_constraint.list = &wm8523->rate_constraint_list[0]; wm8523->rate_constraint.count = ARRAY_SIZE(wm8523->rate_constraint_list); @@ -479,10 +468,6 @@ static int wm8523_probe(struct snd_soc_codec *codec) /* Bias level configuration will have done an extra enable */ regulator_bulk_disable(ARRAY_SIZE(wm8523->supplies), wm8523->supplies); - snd_soc_add_controls(codec, wm8523_snd_controls, - ARRAY_SIZE(wm8523_snd_controls)); - wm8523_add_widgets(codec); - return 0; err_enable: @@ -512,6 +497,18 @@ static struct snd_soc_codec_driver soc_codec_dev_wm8523 = { .reg_word_size = sizeof(u16), .reg_cache_default = wm8523_reg, .volatile_register = wm8523_volatile_register, + + .controls = wm8523_controls, + .num_controls = ARRAY_SIZE(wm8523_controls), + .dapm_widgets = wm8523_dapm_widgets, + .num_dapm_widgets = ARRAY_SIZE(wm8523_dapm_widgets), + .dapm_routes = wm8523_dapm_routes, + .num_dapm_routes = ARRAY_SIZE(wm8523_dapm_routes), +}; + +static const struct of_device_id wm8523_of_match[] = { + { .compatible = "wlf,wm8523" }, + { }, }; #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) @@ -551,8 +548,9 @@ MODULE_DEVICE_TABLE(i2c, wm8523_i2c_id); static struct i2c_driver wm8523_i2c_driver = { .driver = { - .name = "wm8523-codec", + .name = "wm8523", .owner = THIS_MODULE, + .of_match_table = wm8523_of_match, }, .probe = wm8523_i2c_probe, .remove = __devexit_p(wm8523_i2c_remove), diff --git a/sound/soc/codecs/wm8580.c b/sound/soc/codecs/wm8580.c index 4bbc0a79f01..8212b3c8bfd 100644 --- a/sound/soc/codecs/wm8580.c +++ b/sound/soc/codecs/wm8580.c @@ -26,6 +26,7 @@ #include <linux/platform_device.h> #include <linux/regulator/consumer.h> #include <linux/slab.h> +#include <linux/of_device.h> #include <sound/core.h> #include <sound/pcm.h> @@ -212,7 +213,7 @@ static int wm8580_out_vu(struct snd_kcontrol *kcontrol, reg_cache[reg] = 0; reg_cache[reg2] = 0; - ret = snd_soc_put_volsw_2r(kcontrol, ucontrol); + ret = snd_soc_put_volsw(kcontrol, ucontrol); if (ret < 0) return ret; @@ -223,31 +224,19 @@ static int wm8580_out_vu(struct snd_kcontrol *kcontrol, return 0; } -#define SOC_WM8580_OUT_DOUBLE_R_TLV(xname, reg_left, reg_right, xshift, xmax, \ - xinvert, tlv_array) \ -{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = (xname), \ - .access = SNDRV_CTL_ELEM_ACCESS_TLV_READ |\ - SNDRV_CTL_ELEM_ACCESS_READWRITE, \ - .tlv.p = (tlv_array), \ - .info = snd_soc_info_volsw_2r, \ - .get = snd_soc_get_volsw_2r, .put = wm8580_out_vu, \ - .private_value = (unsigned long)&(struct soc_mixer_control) \ - {.reg = reg_left, .rreg = reg_right, .shift = xshift, \ - .max = xmax, .invert = xinvert} } - static const struct snd_kcontrol_new wm8580_snd_controls[] = { -SOC_WM8580_OUT_DOUBLE_R_TLV("DAC1 Playback Volume", - WM8580_DIGITAL_ATTENUATION_DACL1, - WM8580_DIGITAL_ATTENUATION_DACR1, - 0, 0xff, 0, dac_tlv), -SOC_WM8580_OUT_DOUBLE_R_TLV("DAC2 Playback Volume", - WM8580_DIGITAL_ATTENUATION_DACL2, - WM8580_DIGITAL_ATTENUATION_DACR2, - 0, 0xff, 0, dac_tlv), -SOC_WM8580_OUT_DOUBLE_R_TLV("DAC3 Playback Volume", - WM8580_DIGITAL_ATTENUATION_DACL3, - WM8580_DIGITAL_ATTENUATION_DACR3, - 0, 0xff, 0, dac_tlv), +SOC_DOUBLE_R_EXT_TLV("DAC1 Playback Volume", + WM8580_DIGITAL_ATTENUATION_DACL1, + WM8580_DIGITAL_ATTENUATION_DACR1, + 0, 0xff, 0, snd_soc_get_volsw, wm8580_out_vu, dac_tlv), +SOC_DOUBLE_R_EXT_TLV("DAC2 Playback Volume", + WM8580_DIGITAL_ATTENUATION_DACL2, + WM8580_DIGITAL_ATTENUATION_DACR2, + 0, 0xff, 0, snd_soc_get_volsw, wm8580_out_vu, dac_tlv), +SOC_DOUBLE_R_EXT_TLV("DAC3 Playback Volume", + WM8580_DIGITAL_ATTENUATION_DACL3, + WM8580_DIGITAL_ATTENUATION_DACR3, + 0, 0xff, 0, snd_soc_get_volsw, wm8580_out_vu, dac_tlv), SOC_SINGLE("DAC1 Deemphasis Switch", WM8580_DAC_CONTROL3, 0, 1, 0), SOC_SINGLE("DAC2 Deemphasis Switch", WM8580_DAC_CONTROL3, 1, 1, 0), @@ -441,8 +430,7 @@ static int wm8580_set_dai_pll(struct snd_soc_dai *codec_dai, int pll_id, /* Always disable the PLL - it is not safe to leave it running * while reprogramming it. */ - reg = snd_soc_read(codec, WM8580_PWRDN2); - snd_soc_write(codec, WM8580_PWRDN2, reg | pwr_mask); + snd_soc_update_bits(codec, WM8580_PWRDN2, pwr_mask, pwr_mask); if (!freq_in || !freq_out) return 0; @@ -460,8 +448,7 @@ static int wm8580_set_dai_pll(struct snd_soc_dai *codec_dai, int pll_id, snd_soc_write(codec, WM8580_PLLA4 + offset, reg); /* All done, turn it on */ - reg = snd_soc_read(codec, WM8580_PWRDN2); - snd_soc_write(codec, WM8580_PWRDN2, reg & ~pwr_mask); + snd_soc_update_bits(codec, WM8580_PWRDN2, pwr_mask, 0); return 0; } @@ -759,7 +746,6 @@ static int wm8580_digital_mute(struct snd_soc_dai *codec_dai, int mute) static int wm8580_set_bias_level(struct snd_soc_codec *codec, enum snd_soc_bias_level level) { - u16 reg; switch (level) { case SND_SOC_BIAS_ON: case SND_SOC_BIAS_PREPARE: @@ -768,20 +754,19 @@ static int wm8580_set_bias_level(struct snd_soc_codec *codec, case SND_SOC_BIAS_STANDBY: if (codec->dapm.bias_level == SND_SOC_BIAS_OFF) { /* Power up and get individual control of the DACs */ - reg = snd_soc_read(codec, WM8580_PWRDN1); - reg &= ~(WM8580_PWRDN1_PWDN | WM8580_PWRDN1_ALLDACPD); - snd_soc_write(codec, WM8580_PWRDN1, reg); + snd_soc_update_bits(codec, WM8580_PWRDN1, + WM8580_PWRDN1_PWDN | + WM8580_PWRDN1_ALLDACPD, 0); /* Make VMID high impedance */ - reg = snd_soc_read(codec, WM8580_ADC_CONTROL1); - reg &= ~0x100; - snd_soc_write(codec, WM8580_ADC_CONTROL1, reg); + snd_soc_update_bits(codec, WM8580_ADC_CONTROL1, + 0x100, 0); } break; case SND_SOC_BIAS_OFF: - reg = snd_soc_read(codec, WM8580_PWRDN1); - snd_soc_write(codec, WM8580_PWRDN1, reg | WM8580_PWRDN1_PWDN); + snd_soc_update_bits(codec, WM8580_PWRDN1, + WM8580_PWRDN1_PWDN, WM8580_PWRDN1_PWDN); break; } codec->dapm.bias_level = level; @@ -907,6 +892,11 @@ static struct snd_soc_codec_driver soc_codec_dev_wm8580 = { .reg_cache_default = wm8580_reg, }; +static const struct of_device_id wm8580_of_match[] = { + { .compatible = "wlf,wm8580" }, + { }, +}; + #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) static int wm8580_i2c_probe(struct i2c_client *i2c, const struct i2c_device_id *id) @@ -943,8 +933,9 @@ MODULE_DEVICE_TABLE(i2c, wm8580_i2c_id); static struct i2c_driver wm8580_i2c_driver = { .driver = { - .name = "wm8580-codec", + .name = "wm8580", .owner = THIS_MODULE, + .of_match_table = wm8580_of_match, }, .probe = wm8580_i2c_probe, .remove = wm8580_i2c_remove, diff --git a/sound/soc/codecs/wm8711.c b/sound/soc/codecs/wm8711.c index a537e4af6ae..076bdb9930a 100644 --- a/sound/soc/codecs/wm8711.c +++ b/sound/soc/codecs/wm8711.c @@ -3,7 +3,7 @@ * * Copyright 2006 Wolfson Microelectronics * - * Author: Mike Arthur <linux@wolfsonmicro.com> + * Author: Mike Arthur <Mike.Arthur@wolfsonmicro.com> * * Based on wm8731.c by Richard Purdie * @@ -21,6 +21,7 @@ #include <linux/platform_device.h> #include <linux/spi/spi.h> #include <linux/slab.h> +#include <linux/of_device.h> #include <sound/core.h> #include <sound/pcm.h> #include <sound/pcm_params.h> @@ -150,7 +151,7 @@ static int wm8711_hw_params(struct snd_pcm_substream *substream, { struct snd_soc_codec *codec = dai->codec; struct wm8711_priv *wm8711 = snd_soc_codec_get_drvdata(codec); - u16 iface = snd_soc_read(codec, WM8711_IFACE) & 0xfffc; + u16 iface = snd_soc_read(codec, WM8711_IFACE) & 0xfff3; int i = get_coeff(wm8711->sysclk, params_rate(params)); u16 srate = (coeff_div[i].sr << 2) | (coeff_div[i].bosr << 1) | coeff_div[i].usb; @@ -231,7 +232,7 @@ static int wm8711_set_dai_fmt(struct snd_soc_dai *codec_dai, unsigned int fmt) { struct snd_soc_codec *codec = codec_dai->codec; - u16 iface = 0; + u16 iface = snd_soc_read(codec, WM8711_IFACE) & 0x000c; /* set master/slave audio interface */ switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { @@ -286,7 +287,6 @@ static int wm8711_set_dai_fmt(struct snd_soc_dai *codec_dai, return 0; } - static int wm8711_set_bias_level(struct snd_soc_codec *codec, enum snd_soc_bias_level level) { @@ -299,6 +299,9 @@ static int wm8711_set_bias_level(struct snd_soc_codec *codec, case SND_SOC_BIAS_PREPARE: break; case SND_SOC_BIAS_STANDBY: + if (codec->dapm.bias_level == SND_SOC_BIAS_OFF) + snd_soc_cache_sync(codec); + snd_soc_write(codec, WM8711_PWR, reg | 0x0040); break; case SND_SOC_BIAS_OFF: @@ -345,25 +348,14 @@ static int wm8711_suspend(struct snd_soc_codec *codec, pm_message_t state) static int wm8711_resume(struct snd_soc_codec *codec) { - int i; - u8 data[2]; - u16 *cache = codec->reg_cache; - - /* Sync reg_cache with the hardware */ - for (i = 0; i < ARRAY_SIZE(wm8711_reg); i++) { - data[0] = (i << 1) | ((cache[i] >> 8) & 0x0001); - data[1] = cache[i] & 0x00ff; - codec->hw_write(codec->control_data, data, 2); - } wm8711_set_bias_level(codec, SND_SOC_BIAS_STANDBY); - return 0; } static int wm8711_probe(struct snd_soc_codec *codec) { struct wm8711_priv *wm8711 = snd_soc_codec_get_drvdata(codec); - int ret, reg; + int ret; ret = snd_soc_codec_set_cache_io(codec, 7, 9, wm8711->bus_type); if (ret < 0) { @@ -380,10 +372,8 @@ static int wm8711_probe(struct snd_soc_codec *codec) wm8711_set_bias_level(codec, SND_SOC_BIAS_STANDBY); /* Latch the update bits */ - reg = snd_soc_read(codec, WM8711_LOUT1V); - snd_soc_write(codec, WM8711_LOUT1V, reg | 0x0100); - reg = snd_soc_read(codec, WM8711_ROUT1V); - snd_soc_write(codec, WM8711_ROUT1V, reg | 0x0100); + snd_soc_update_bits(codec, WM8711_LOUT1V, 0x0100, 0x0100); + snd_soc_update_bits(codec, WM8711_ROUT1V, 0x0100, 0x0100); snd_soc_add_controls(codec, wm8711_snd_controls, ARRAY_SIZE(wm8711_snd_controls)); @@ -414,6 +404,12 @@ static struct snd_soc_codec_driver soc_codec_dev_wm8711 = { .num_dapm_routes = ARRAY_SIZE(wm8711_intercon), }; +static const struct of_device_id wm8711_of_match[] = { + { .compatible = "wlf,wm8711", }, + { } +}; +MODULE_DEVICE_TABLE(of, wm8711_of_match); + #if defined(CONFIG_SPI_MASTER) static int __devinit wm8711_spi_probe(struct spi_device *spi) { @@ -443,8 +439,9 @@ static int __devexit wm8711_spi_remove(struct spi_device *spi) static struct spi_driver wm8711_spi_driver = { .driver = { - .name = "wm8711-codec", + .name = "wm8711", .owner = THIS_MODULE, + .of_match_table = wm8711_of_match, }, .probe = wm8711_spi_probe, .remove = __devexit_p(wm8711_spi_remove), @@ -487,8 +484,9 @@ MODULE_DEVICE_TABLE(i2c, wm8711_i2c_id); static struct i2c_driver wm8711_i2c_driver = { .driver = { - .name = "wm8711-codec", + .name = "wm8711", .owner = THIS_MODULE, + .of_match_table = wm8711_of_match, }, .probe = wm8711_i2c_probe, .remove = __devexit_p(wm8711_i2c_remove), diff --git a/sound/soc/codecs/wm8728.c b/sound/soc/codecs/wm8728.c index 86d4718d3a7..04b027efd5c 100644 --- a/sound/soc/codecs/wm8728.c +++ b/sound/soc/codecs/wm8728.c @@ -19,6 +19,7 @@ #include <linux/platform_device.h> #include <linux/spi/spi.h> #include <linux/slab.h> +#include <linux/of_device.h> #include <sound/core.h> #include <sound/pcm.h> #include <sound/pcm_params.h> @@ -269,6 +270,12 @@ static struct snd_soc_codec_driver soc_codec_dev_wm8728 = { .num_dapm_routes = ARRAY_SIZE(wm8728_intercon), }; +static const struct of_device_id wm8728_of_match[] = { + { .compatible = "wlf,wm8728", }, + { } +}; +MODULE_DEVICE_TABLE(of, wm8728_of_match); + #if defined(CONFIG_SPI_MASTER) static int __devinit wm8728_spi_probe(struct spi_device *spi) { @@ -298,8 +305,9 @@ static int __devexit wm8728_spi_remove(struct spi_device *spi) static struct spi_driver wm8728_spi_driver = { .driver = { - .name = "wm8728-codec", + .name = "wm8728", .owner = THIS_MODULE, + .of_match_table = wm8728_of_match, }, .probe = wm8728_spi_probe, .remove = __devexit_p(wm8728_spi_remove), @@ -342,8 +350,9 @@ MODULE_DEVICE_TABLE(i2c, wm8728_i2c_id); static struct i2c_driver wm8728_i2c_driver = { .driver = { - .name = "wm8728-codec", + .name = "wm8728", .owner = THIS_MODULE, + .of_match_table = wm8728_of_match, }, .probe = wm8728_i2c_probe, .remove = __devexit_p(wm8728_i2c_remove), diff --git a/sound/soc/codecs/wm8731.c b/sound/soc/codecs/wm8731.c index 76b4361e9b8..7e5ec03f6f8 100644 --- a/sound/soc/codecs/wm8731.c +++ b/sound/soc/codecs/wm8731.c @@ -22,6 +22,7 @@ #include <linux/platform_device.h> #include <linux/regulator/consumer.h> #include <linux/spi/spi.h> +#include <linux/of_device.h> #include <sound/core.h> #include <sound/pcm.h> #include <sound/pcm_params.h> @@ -426,9 +427,7 @@ static int wm8731_set_bias_level(struct snd_soc_codec *codec, enum snd_soc_bias_level level) { struct wm8731_priv *wm8731 = snd_soc_codec_get_drvdata(codec); - int i, ret; - u8 data[2]; - u16 *cache = codec->reg_cache; + int ret; u16 reg; switch (level) { @@ -443,16 +442,7 @@ static int wm8731_set_bias_level(struct snd_soc_codec *codec, if (ret != 0) return ret; - /* Sync reg_cache with the hardware */ - for (i = 0; i < ARRAY_SIZE(wm8731_reg); i++) { - if (cache[i] == wm8731_reg[i]) - continue; - - data[0] = (i << 1) | ((cache[i] >> 8) - & 0x0001); - data[1] = cache[i] & 0x00ff; - codec->hw_write(codec->control_data, data, 2); - } + snd_soc_cache_sync(codec); } /* Clear PWROFF, gate CLKOUT, everything else as-is */ @@ -607,6 +597,13 @@ static struct snd_soc_codec_driver soc_codec_dev_wm8731 = { .num_dapm_routes = ARRAY_SIZE(wm8731_intercon), }; +static const struct of_device_id wm8731_of_match[] = { + { .compatible = "wlf,wm8731", }, + { } +}; + +MODULE_DEVICE_TABLE(of, wm8731_of_match); + #if defined(CONFIG_SPI_MASTER) static int __devinit wm8731_spi_probe(struct spi_device *spi) { @@ -638,6 +635,7 @@ static struct spi_driver wm8731_spi_driver = { .driver = { .name = "wm8731", .owner = THIS_MODULE, + .of_match_table = wm8731_of_match, }, .probe = wm8731_spi_probe, .remove = __devexit_p(wm8731_spi_remove), @@ -682,6 +680,7 @@ static struct i2c_driver wm8731_i2c_driver = { .driver = { .name = "wm8731", .owner = THIS_MODULE, + .of_match_table = wm8731_of_match, }, .probe = wm8731_i2c_probe, .remove = __devexit_p(wm8731_i2c_remove), diff --git a/sound/soc/codecs/wm8737.c b/sound/soc/codecs/wm8737.c index 30c67d06a90..f6aef58845c 100644 --- a/sound/soc/codecs/wm8737.c +++ b/sound/soc/codecs/wm8737.c @@ -20,6 +20,7 @@ #include <linux/regulator/consumer.h> #include <linux/spi/spi.h> #include <linux/slab.h> +#include <linux/of_device.h> #include <sound/core.h> #include <sound/pcm.h> #include <sound/pcm_params.h> @@ -634,6 +635,13 @@ static struct snd_soc_codec_driver soc_codec_dev_wm8737 = { .reg_cache_default = wm8737_reg, }; +static const struct of_device_id wm8737_of_match[] = { + { .compatible = "wlf,wm8737", }, + { } +}; + +MODULE_DEVICE_TABLE(of, wm8737_of_match); + #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) static __devinit int wm8737_i2c_probe(struct i2c_client *i2c, const struct i2c_device_id *id) @@ -673,6 +681,7 @@ static struct i2c_driver wm8737_i2c_driver = { .driver = { .name = "wm8737", .owner = THIS_MODULE, + .of_match_table = wm8737_of_match, }, .probe = wm8737_i2c_probe, .remove = __devexit_p(wm8737_i2c_remove), @@ -711,6 +720,7 @@ static struct spi_driver wm8737_spi_driver = { .driver = { .name = "wm8737", .owner = THIS_MODULE, + .of_match_table = wm8737_of_match, }, .probe = wm8737_spi_probe, .remove = __devexit_p(wm8737_spi_remove), diff --git a/sound/soc/codecs/wm8741.c b/sound/soc/codecs/wm8741.c index 25af901fe81..57ad22aacc5 100644 --- a/sound/soc/codecs/wm8741.c +++ b/sound/soc/codecs/wm8741.c @@ -17,9 +17,11 @@ #include <linux/delay.h> #include <linux/pm.h> #include <linux/i2c.h> +#include <linux/spi/spi.h> #include <linux/platform_device.h> #include <linux/regulator/consumer.h> #include <linux/slab.h> +#include <linux/of_device.h> #include <sound/core.h> #include <sound/pcm.h> #include <sound/pcm_params.h> @@ -337,10 +339,10 @@ static int wm8741_set_dai_fmt(struct snd_soc_dai *codec_dai, iface |= 0x0004; break; case SND_SOC_DAIFMT_DSP_A: - iface |= 0x0003; + iface |= 0x000C; break; case SND_SOC_DAIFMT_DSP_B: - iface |= 0x0013; + iface |= 0x001C; break; default: return -EINVAL; @@ -402,15 +404,7 @@ static struct snd_soc_dai_driver wm8741_dai = { #ifdef CONFIG_PM static int wm8741_resume(struct snd_soc_codec *codec) { - u16 *cache = codec->reg_cache; - int i; - - /* RESTORE REG Cache */ - for (i = 0; i < WM8741_REGISTER_COUNT; i++) { - if (cache[i] == wm8741_reg_defaults[i] || WM8741_RESET == i) - continue; - snd_soc_write(codec, i, cache[i]); - } + snd_soc_cache_sync(codec); return 0; } #else @@ -422,17 +416,35 @@ static int wm8741_probe(struct snd_soc_codec *codec) { struct wm8741_priv *wm8741 = snd_soc_codec_get_drvdata(codec); int ret = 0; + int i; + + for (i = 0; i < ARRAY_SIZE(wm8741->supplies); i++) + wm8741->supplies[i].supply = wm8741_supply_names[i]; + + ret = regulator_bulk_get(codec->dev, ARRAY_SIZE(wm8741->supplies), + wm8741->supplies); + if (ret != 0) { + dev_err(codec->dev, "Failed to request supplies: %d\n", ret); + goto err; + } + + ret = regulator_bulk_enable(ARRAY_SIZE(wm8741->supplies), + wm8741->supplies); + if (ret != 0) { + dev_err(codec->dev, "Failed to enable supplies: %d\n", ret); + goto err_get; + } ret = snd_soc_codec_set_cache_io(codec, 7, 9, wm8741->control_type); if (ret != 0) { dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret); - return ret; + goto err_enable; } ret = wm8741_reset(codec); if (ret < 0) { dev_err(codec->dev, "Failed to issue reset\n"); - return ret; + goto err_enable; } /* Change some default settings - latch VU */ @@ -442,7 +454,7 @@ static int wm8741_probe(struct snd_soc_codec *codec) WM8741_UPDATELM, WM8741_UPDATELM); snd_soc_update_bits(codec, WM8741_DACRLSB_ATTENUATION, WM8741_UPDATERL, WM8741_UPDATERL); - snd_soc_update_bits(codec, WM8741_DACRLSB_ATTENUATION, + snd_soc_update_bits(codec, WM8741_DACRMSB_ATTENUATION, WM8741_UPDATERM, WM8741_UPDATERM); snd_soc_add_controls(codec, wm8741_snd_controls, @@ -451,58 +463,61 @@ static int wm8741_probe(struct snd_soc_codec *codec) dev_dbg(codec->dev, "Successful registration\n"); return ret; + +err_enable: + regulator_bulk_disable(ARRAY_SIZE(wm8741->supplies), wm8741->supplies); +err_get: + regulator_bulk_free(ARRAY_SIZE(wm8741->supplies), wm8741->supplies); +err: + return ret; +} + +static int wm8741_remove(struct snd_soc_codec *codec) +{ + struct wm8741_priv *wm8741 = snd_soc_codec_get_drvdata(codec); + + regulator_bulk_disable(ARRAY_SIZE(wm8741->supplies), wm8741->supplies); + regulator_bulk_free(ARRAY_SIZE(wm8741->supplies), wm8741->supplies); + + return 0; } static struct snd_soc_codec_driver soc_codec_dev_wm8741 = { .probe = wm8741_probe, + .remove = wm8741_remove, .resume = wm8741_resume, .reg_cache_size = ARRAY_SIZE(wm8741_reg_defaults), .reg_word_size = sizeof(u16), .reg_cache_default = wm8741_reg_defaults, }; +static const struct of_device_id wm8741_of_match[] = { + { .compatible = "wlf,wm8741", }, + { } +}; +MODULE_DEVICE_TABLE(of, wm8741_of_match); + #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) static int wm8741_i2c_probe(struct i2c_client *i2c, const struct i2c_device_id *id) { struct wm8741_priv *wm8741; - int ret, i; + int ret; wm8741 = kzalloc(sizeof(struct wm8741_priv), GFP_KERNEL); if (wm8741 == NULL) return -ENOMEM; - for (i = 0; i < ARRAY_SIZE(wm8741->supplies); i++) - wm8741->supplies[i].supply = wm8741_supply_names[i]; - - ret = regulator_bulk_get(&i2c->dev, ARRAY_SIZE(wm8741->supplies), - wm8741->supplies); - if (ret != 0) { - dev_err(&i2c->dev, "Failed to request supplies: %d\n", ret); - goto err; - } - - ret = regulator_bulk_enable(ARRAY_SIZE(wm8741->supplies), - wm8741->supplies); - if (ret != 0) { - dev_err(&i2c->dev, "Failed to enable supplies: %d\n", ret); - goto err_get; - } - i2c_set_clientdata(i2c, wm8741); wm8741->control_type = SND_SOC_I2C; - ret = snd_soc_register_codec(&i2c->dev, - &soc_codec_dev_wm8741, &wm8741_dai, 1); - if (ret < 0) - goto err_enable; - return ret; + ret = snd_soc_register_codec(&i2c->dev, + &soc_codec_dev_wm8741, &wm8741_dai, 1); + if (ret != 0) + goto err; -err_enable: - regulator_bulk_disable(ARRAY_SIZE(wm8741->supplies), wm8741->supplies); + return ret; -err_get: - regulator_bulk_free(ARRAY_SIZE(wm8741->supplies), wm8741->supplies); err: kfree(wm8741); return ret; @@ -510,10 +525,7 @@ err: static int wm8741_i2c_remove(struct i2c_client *client) { - struct wm8741_priv *wm8741 = i2c_get_clientdata(client); - snd_soc_unregister_codec(&client->dev); - regulator_bulk_free(ARRAY_SIZE(wm8741->supplies), wm8741->supplies); kfree(i2c_get_clientdata(client)); return 0; } @@ -526,8 +538,9 @@ MODULE_DEVICE_TABLE(i2c, wm8741_i2c_id); static struct i2c_driver wm8741_i2c_driver = { .driver = { - .name = "wm8741-codec", + .name = "wm8741", .owner = THIS_MODULE, + .of_match_table = wm8741_of_match, }, .probe = wm8741_i2c_probe, .remove = wm8741_i2c_remove, @@ -535,6 +548,44 @@ static struct i2c_driver wm8741_i2c_driver = { }; #endif +#if defined(CONFIG_SPI_MASTER) +static int __devinit wm8741_spi_probe(struct spi_device *spi) +{ + struct wm8741_priv *wm8741; + int ret; + + wm8741 = kzalloc(sizeof(struct wm8741_priv), GFP_KERNEL); + if (wm8741 == NULL) + return -ENOMEM; + + wm8741->control_type = SND_SOC_SPI; + spi_set_drvdata(spi, wm8741); + + ret = snd_soc_register_codec(&spi->dev, + &soc_codec_dev_wm8741, &wm8741_dai, 1); + if (ret < 0) + kfree(wm8741); + return ret; +} + +static int __devexit wm8741_spi_remove(struct spi_device *spi) +{ + snd_soc_unregister_codec(&spi->dev); + kfree(spi_get_drvdata(spi)); + return 0; +} + +static struct spi_driver wm8741_spi_driver = { + .driver = { + .name = "wm8741", + .owner = THIS_MODULE, + .of_match_table = wm8741_of_match, + }, + .probe = wm8741_spi_probe, + .remove = __devexit_p(wm8741_spi_remove), +}; +#endif /* CONFIG_SPI_MASTER */ + static int __init wm8741_modinit(void) { int ret = 0; @@ -544,6 +595,13 @@ static int __init wm8741_modinit(void) if (ret != 0) pr_err("Failed to register WM8741 I2C driver: %d\n", ret); #endif +#if defined(CONFIG_SPI_MASTER) + ret = spi_register_driver(&wm8741_spi_driver); + if (ret != 0) { + printk(KERN_ERR "Failed to register wm8741 SPI driver: %d\n", + ret); + } +#endif return ret; } @@ -551,6 +609,9 @@ module_init(wm8741_modinit); static void __exit wm8741_exit(void) { +#if defined(CONFIG_SPI_MASTER) + spi_unregister_driver(&wm8741_spi_driver); +#endif #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) i2c_del_driver(&wm8741_i2c_driver); #endif diff --git a/sound/soc/codecs/wm8750.c b/sound/soc/codecs/wm8750.c index d0003cc3bcd..ca75a818070 100644 --- a/sound/soc/codecs/wm8750.c +++ b/sound/soc/codecs/wm8750.c @@ -21,6 +21,7 @@ #include <linux/platform_device.h> #include <linux/spi/spi.h> #include <linux/slab.h> +#include <linux/of_device.h> #include <sound/core.h> #include <sound/pcm.h> #include <sound/pcm_params.h> @@ -615,6 +616,8 @@ static int wm8750_set_bias_level(struct snd_soc_codec *codec, break; case SND_SOC_BIAS_STANDBY: if (codec->dapm.bias_level == SND_SOC_BIAS_OFF) { + snd_soc_cache_sync(codec); + /* Set VMID to 5k */ snd_soc_write(codec, WM8750_PWR1, pwr_reg | 0x01c1); @@ -672,28 +675,14 @@ static int wm8750_suspend(struct snd_soc_codec *codec, pm_message_t state) static int wm8750_resume(struct snd_soc_codec *codec) { - int i; - u8 data[2]; - u16 *cache = codec->reg_cache; - - /* Sync reg_cache with the hardware */ - for (i = 0; i < ARRAY_SIZE(wm8750_reg); i++) { - if (i == WM8750_RESET) - continue; - data[0] = (i << 1) | ((cache[i] >> 8) & 0x0001); - data[1] = cache[i] & 0x00ff; - codec->hw_write(codec->control_data, data, 2); - } - wm8750_set_bias_level(codec, SND_SOC_BIAS_STANDBY); - return 0; } static int wm8750_probe(struct snd_soc_codec *codec) { struct wm8750_priv *wm8750 = snd_soc_codec_get_drvdata(codec); - int reg, ret; + int ret; ret = snd_soc_codec_set_cache_io(codec, 7, 9, wm8750->control_type); if (ret < 0) { @@ -711,22 +700,14 @@ static int wm8750_probe(struct snd_soc_codec *codec) wm8750_set_bias_level(codec, SND_SOC_BIAS_STANDBY); /* set the update bits */ - reg = snd_soc_read(codec, WM8750_LDAC); - snd_soc_write(codec, WM8750_LDAC, reg | 0x0100); - reg = snd_soc_read(codec, WM8750_RDAC); - snd_soc_write(codec, WM8750_RDAC, reg | 0x0100); - reg = snd_soc_read(codec, WM8750_LOUT1V); - snd_soc_write(codec, WM8750_LOUT1V, reg | 0x0100); - reg = snd_soc_read(codec, WM8750_ROUT1V); - snd_soc_write(codec, WM8750_ROUT1V, reg | 0x0100); - reg = snd_soc_read(codec, WM8750_LOUT2V); - snd_soc_write(codec, WM8750_LOUT2V, reg | 0x0100); - reg = snd_soc_read(codec, WM8750_ROUT2V); - snd_soc_write(codec, WM8750_ROUT2V, reg | 0x0100); - reg = snd_soc_read(codec, WM8750_LINVOL); - snd_soc_write(codec, WM8750_LINVOL, reg | 0x0100); - reg = snd_soc_read(codec, WM8750_RINVOL); - snd_soc_write(codec, WM8750_RINVOL, reg | 0x0100); + snd_soc_update_bits(codec, WM8750_LDAC, 0x0100, 0x0100); + snd_soc_update_bits(codec, WM8750_RDAC, 0x0100, 0x0100); + snd_soc_update_bits(codec, WM8750_LOUT1V, 0x0100, 0x0100); + snd_soc_update_bits(codec, WM8750_ROUT1V, 0x0100, 0x0100); + snd_soc_update_bits(codec, WM8750_LOUT2V, 0x0100, 0x0100); + snd_soc_update_bits(codec, WM8750_ROUT2V, 0x0100, 0x0100); + snd_soc_update_bits(codec, WM8750_LINVOL, 0x0100, 0x0100); + snd_soc_update_bits(codec, WM8750_RINVOL, 0x0100, 0x0100); snd_soc_add_controls(codec, wm8750_snd_controls, ARRAY_SIZE(wm8750_snd_controls)); @@ -751,6 +732,13 @@ static struct snd_soc_codec_driver soc_codec_dev_wm8750 = { .reg_cache_default = wm8750_reg, }; +static const struct of_device_id wm8750_of_match[] = { + { .compatible = "wlf,wm8750", }, + { .compatible = "wlf,wm8987", }, + { } +}; +MODULE_DEVICE_TABLE(of, wm8750_of_match); + #if defined(CONFIG_SPI_MASTER) static int __devinit wm8750_spi_probe(struct spi_device *spi) { @@ -787,8 +775,9 @@ MODULE_DEVICE_TABLE(spi, wm8750_spi_ids); static struct spi_driver wm8750_spi_driver = { .driver = { - .name = "wm8750-codec", + .name = "wm8750", .owner = THIS_MODULE, + .of_match_table = wm8750_of_match, }, .id_table = wm8750_spi_ids, .probe = wm8750_spi_probe, @@ -833,8 +822,9 @@ MODULE_DEVICE_TABLE(i2c, wm8750_i2c_id); static struct i2c_driver wm8750_i2c_driver = { .driver = { - .name = "wm8750-codec", + .name = "wm8750", .owner = THIS_MODULE, + .of_match_table = wm8750_of_match, }, .probe = wm8750_i2c_probe, .remove = __devexit_p(wm8750_i2c_remove), diff --git a/sound/soc/codecs/wm8753.c b/sound/soc/codecs/wm8753.c index aa091a0d818..a9504710bb6 100644 --- a/sound/soc/codecs/wm8753.c +++ b/sound/soc/codecs/wm8753.c @@ -38,6 +38,7 @@ #include <linux/delay.h> #include <linux/pm.h> #include <linux/i2c.h> +#include <linux/of_device.h> #include <linux/platform_device.h> #include <linux/spi/spi.h> #include <linux/slab.h> @@ -1490,6 +1491,12 @@ static struct snd_soc_codec_driver soc_codec_dev_wm8753 = { .reg_cache_default = wm8753_reg, }; +static const struct of_device_id wm8753_of_match[] = { + { .compatible = "wlf,wm8753", }, + { } +}; +MODULE_DEVICE_TABLE(of, wm8753_of_match); + #if defined(CONFIG_SPI_MASTER) static int __devinit wm8753_spi_probe(struct spi_device *spi) { @@ -1519,8 +1526,9 @@ static int __devexit wm8753_spi_remove(struct spi_device *spi) static struct spi_driver wm8753_spi_driver = { .driver = { - .name = "wm8753-codec", + .name = "wm8753", .owner = THIS_MODULE, + .of_match_table = wm8753_of_match, }, .probe = wm8753_spi_probe, .remove = __devexit_p(wm8753_spi_remove), @@ -1563,8 +1571,9 @@ MODULE_DEVICE_TABLE(i2c, wm8753_i2c_id); static struct i2c_driver wm8753_i2c_driver = { .driver = { - .name = "wm8753-codec", + .name = "wm8753", .owner = THIS_MODULE, + .of_match_table = wm8753_of_match, }, .probe = wm8753_i2c_probe, .remove = __devexit_p(wm8753_i2c_remove), diff --git a/sound/soc/codecs/wm8770.c b/sound/soc/codecs/wm8770.c index 19b92baa9e8..aa05e6507f8 100644 --- a/sound/soc/codecs/wm8770.c +++ b/sound/soc/codecs/wm8770.c @@ -14,6 +14,7 @@ #include <linux/moduleparam.h> #include <linux/init.h> #include <linux/delay.h> +#include <linux/of_device.h> #include <linux/pm.h> #include <linux/platform_device.h> #include <linux/spi/spi.h> @@ -684,6 +685,12 @@ static struct snd_soc_codec_driver soc_codec_dev_wm8770 = { .reg_cache_default = wm8770_reg_defs }; +static const struct of_device_id wm8770_of_match[] = { + { .compatible = "wlf,wm8770", }, + { } +}; +MODULE_DEVICE_TABLE(of, wm8770_of_match); + #if defined(CONFIG_SPI_MASTER) static int __devinit wm8770_spi_probe(struct spi_device *spi) { @@ -715,6 +722,7 @@ static struct spi_driver wm8770_spi_driver = { .driver = { .name = "wm8770", .owner = THIS_MODULE, + .of_match_table = wm8770_of_match, }, .probe = wm8770_spi_probe, .remove = __devexit_p(wm8770_spi_remove) diff --git a/sound/soc/codecs/wm8776.c b/sound/soc/codecs/wm8776.c index 8e7953b1b79..bfdc52370ad 100644 --- a/sound/soc/codecs/wm8776.c +++ b/sound/soc/codecs/wm8776.c @@ -18,6 +18,7 @@ #include <linux/delay.h> #include <linux/pm.h> #include <linux/i2c.h> +#include <linux/of_device.h> #include <linux/platform_device.h> #include <linux/spi/spi.h> #include <linux/slab.h> @@ -215,8 +216,6 @@ static int wm8776_hw_params(struct snd_pcm_substream *substream, int ratio_shift, master; int i; - iface = 0; - switch (dai->driver->id) { case WM8776_DAI_DAC: iface_reg = WM8776_DACIFCTRL; @@ -232,20 +231,23 @@ static int wm8776_hw_params(struct snd_pcm_substream *substream, return -EINVAL; } - /* Set word length */ - switch (params_format(params)) { - case SNDRV_PCM_FORMAT_S16_LE: - break; - case SNDRV_PCM_FORMAT_S20_3LE: - iface |= 0x10; + switch (snd_pcm_format_width(params_format(params))) { + case 16: + iface = 0; + case 20: + iface = 0x10; break; - case SNDRV_PCM_FORMAT_S24_LE: - iface |= 0x20; + case 24: + iface = 0x20; break; - case SNDRV_PCM_FORMAT_S32_LE: - iface |= 0x30; + case 32: + iface = 0x30; break; + default: + dev_err(codec->dev, "Unsupported sample size: %i\n", + snd_pcm_format_width(params_format(params))); + return -EINVAL; } /* Only need to set MCLK/LRCLK ratio if we're master */ @@ -306,6 +308,8 @@ static int wm8776_set_bias_level(struct snd_soc_codec *codec, break; case SND_SOC_BIAS_STANDBY: if (codec->dapm.bias_level == SND_SOC_BIAS_OFF) { + snd_soc_cache_sync(codec); + /* Disable the global powerdown; DAPM does the rest */ snd_soc_update_bits(codec, WM8776_PWRDOWN, 1, 0); } @@ -320,11 +324,6 @@ static int wm8776_set_bias_level(struct snd_soc_codec *codec, return 0; } -#define WM8776_RATES (SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_44100 |\ - SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_88200 |\ - SNDRV_PCM_RATE_96000) - - #define WM8776_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE |\ SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S32_LE) @@ -349,7 +348,9 @@ static struct snd_soc_dai_driver wm8776_dai[] = { .stream_name = "Playback", .channels_min = 2, .channels_max = 2, - .rates = WM8776_RATES, + .rates = SNDRV_PCM_RATE_CONTINUOUS, + .rate_min = 32000, + .rate_max = 192000, .formats = WM8776_FORMATS, }, .ops = &wm8776_dac_ops, @@ -361,7 +362,9 @@ static struct snd_soc_dai_driver wm8776_dai[] = { .stream_name = "Capture", .channels_min = 2, .channels_max = 2, - .rates = WM8776_RATES, + .rates = SNDRV_PCM_RATE_CONTINUOUS, + .rate_min = 32000, + .rate_max = 96000, .formats = WM8776_FORMATS, }, .ops = &wm8776_adc_ops, @@ -378,21 +381,7 @@ static int wm8776_suspend(struct snd_soc_codec *codec, pm_message_t state) static int wm8776_resume(struct snd_soc_codec *codec) { - int i; - u8 data[2]; - u16 *cache = codec->reg_cache; - - /* Sync reg_cache with the hardware */ - for (i = 0; i < ARRAY_SIZE(wm8776_reg); i++) { - if (cache[i] == wm8776_reg[i]) - continue; - data[0] = (i << 1) | ((cache[i] >> 8) & 0x0001); - data[1] = cache[i] & 0x00ff; - codec->hw_write(codec->control_data, data, 2); - } - wm8776_set_bias_level(codec, SND_SOC_BIAS_STANDBY); - return 0; } #else @@ -452,6 +441,12 @@ static struct snd_soc_codec_driver soc_codec_dev_wm8776 = { .reg_cache_default = wm8776_reg, }; +static const struct of_device_id wm8776_of_match[] = { + { .compatible = "wlf,wm8776", }, + { } +}; +MODULE_DEVICE_TABLE(of, wm8776_of_match); + #if defined(CONFIG_SPI_MASTER) static int __devinit wm8776_spi_probe(struct spi_device *spi) { @@ -481,8 +476,9 @@ static int __devexit wm8776_spi_remove(struct spi_device *spi) static struct spi_driver wm8776_spi_driver = { .driver = { - .name = "wm8776-codec", + .name = "wm8776", .owner = THIS_MODULE, + .of_match_table = wm8776_of_match, }, .probe = wm8776_spi_probe, .remove = __devexit_p(wm8776_spi_remove), @@ -525,8 +521,9 @@ MODULE_DEVICE_TABLE(i2c, wm8776_i2c_id); static struct i2c_driver wm8776_i2c_driver = { .driver = { - .name = "wm8776-codec", + .name = "wm8776", .owner = THIS_MODULE, + .of_match_table = wm8776_of_match, }, .probe = wm8776_i2c_probe, .remove = __devexit_p(wm8776_i2c_remove), diff --git a/sound/soc/codecs/wm8782.c b/sound/soc/codecs/wm8782.c index a2a09f85ea9..f2ced71328b 100644 --- a/sound/soc/codecs/wm8782.c +++ b/sound/soc/codecs/wm8782.c @@ -60,7 +60,7 @@ static struct platform_driver wm8782_codec_driver = { .owner = THIS_MODULE, }, .probe = wm8782_probe, - .remove = wm8782_remove, + .remove = __devexit_p(wm8782_remove), }; static int __init wm8782_init(void) diff --git a/sound/soc/codecs/wm8804.c b/sound/soc/codecs/wm8804.c index 9a5e67c5a6b..9ee072b8597 100644 --- a/sound/soc/codecs/wm8804.c +++ b/sound/soc/codecs/wm8804.c @@ -16,6 +16,7 @@ #include <linux/delay.h> #include <linux/pm.h> #include <linux/i2c.h> +#include <linux/of_device.h> #include <linux/spi/spi.h> #include <linux/regulator/consumer.h> #include <linux/slab.h> @@ -717,6 +718,12 @@ static struct snd_soc_codec_driver soc_codec_dev_wm8804 = { .volatile_register = wm8804_volatile }; +static const struct of_device_id wm8804_of_match[] = { + { .compatible = "wlf,wm8804", }, + { } +}; +MODULE_DEVICE_TABLE(of, wm8804_of_match); + #if defined(CONFIG_SPI_MASTER) static int __devinit wm8804_spi_probe(struct spi_device *spi) { @@ -748,6 +755,7 @@ static struct spi_driver wm8804_spi_driver = { .driver = { .name = "wm8804", .owner = THIS_MODULE, + .of_match_table = wm8804_of_match, }, .probe = wm8804_spi_probe, .remove = __devexit_p(wm8804_spi_remove) @@ -792,6 +800,7 @@ static struct i2c_driver wm8804_i2c_driver = { .driver = { .name = "wm8804", .owner = THIS_MODULE, + .of_match_table = wm8804_of_match, }, .probe = wm8804_i2c_probe, .remove = __devexit_p(wm8804_i2c_remove), diff --git a/sound/soc/codecs/wm8900.c b/sound/soc/codecs/wm8900.c index 082040eda8a..3d0dc1591ec 100644 --- a/sound/soc/codecs/wm8900.c +++ b/sound/soc/codecs/wm8900.c @@ -110,8 +110,8 @@ #define WM8900_REG_CLOCKING1_BCLK_DIR 0x1 #define WM8900_REG_CLOCKING1_MCLK_SRC 0x100 -#define WM8900_REG_CLOCKING1_BCLK_MASK (~0x01e) -#define WM8900_REG_CLOCKING1_OPCLK_MASK (~0x7000) +#define WM8900_REG_CLOCKING1_BCLK_MASK 0x01e +#define WM8900_REG_CLOCKING1_OPCLK_MASK 0x7000 #define WM8900_REG_CLOCKING2_ADC_CLKDIV 0xe0 #define WM8900_REG_CLOCKING2_DAC_CLKDIV 0x1c @@ -135,7 +135,7 @@ #define WM8900_REG_HPCTL1_HP_SHORT 0x08 #define WM8900_REG_HPCTL1_HP_SHORT2 0x04 -#define WM8900_LRC_MASK 0xfc00 +#define WM8900_LRC_MASK 0x03ff struct wm8900_priv { enum snd_soc_control_type control_type; @@ -742,26 +742,20 @@ static int wm8900_set_fll(struct snd_soc_codec *codec, { struct wm8900_priv *wm8900 = snd_soc_codec_get_drvdata(codec); struct _fll_div fll_div; - unsigned int reg; if (wm8900->fll_in == freq_in && wm8900->fll_out == freq_out) return 0; /* The digital side should be disabled during any change. */ - reg = snd_soc_read(codec, WM8900_REG_POWER1); - snd_soc_write(codec, WM8900_REG_POWER1, - reg & (~WM8900_REG_POWER1_FLL_ENA)); + snd_soc_update_bits(codec, WM8900_REG_POWER1, + WM8900_REG_POWER1_FLL_ENA, 0); /* Disable the FLL? */ if (!freq_in || !freq_out) { - reg = snd_soc_read(codec, WM8900_REG_CLOCKING1); - snd_soc_write(codec, WM8900_REG_CLOCKING1, - reg & (~WM8900_REG_CLOCKING1_MCLK_SRC)); - - reg = snd_soc_read(codec, WM8900_REG_FLLCTL1); - snd_soc_write(codec, WM8900_REG_FLLCTL1, - reg & (~WM8900_REG_FLLCTL1_OSC_ENA)); - + snd_soc_update_bits(codec, WM8900_REG_CLOCKING1, + WM8900_REG_CLOCKING1_MCLK_SRC, 0); + snd_soc_update_bits(codec, WM8900_REG_FLLCTL1, + WM8900_REG_FLLCTL1_OSC_ENA, 0); wm8900->fll_in = freq_in; wm8900->fll_out = freq_out; @@ -796,15 +790,14 @@ static int wm8900_set_fll(struct snd_soc_codec *codec, else snd_soc_write(codec, WM8900_REG_FLLCTL6, 0); - reg = snd_soc_read(codec, WM8900_REG_POWER1); - snd_soc_write(codec, WM8900_REG_POWER1, - reg | WM8900_REG_POWER1_FLL_ENA); + snd_soc_update_bits(codec, WM8900_REG_POWER1, + WM8900_REG_POWER1_FLL_ENA, + WM8900_REG_POWER1_FLL_ENA); reenable: - reg = snd_soc_read(codec, WM8900_REG_CLOCKING1); - snd_soc_write(codec, WM8900_REG_CLOCKING1, - reg | WM8900_REG_CLOCKING1_MCLK_SRC); - + snd_soc_update_bits(codec, WM8900_REG_CLOCKING1, + WM8900_REG_CLOCKING1_MCLK_SRC, + WM8900_REG_CLOCKING1_MCLK_SRC); return 0; } @@ -818,43 +811,35 @@ static int wm8900_set_dai_clkdiv(struct snd_soc_dai *codec_dai, int div_id, int div) { struct snd_soc_codec *codec = codec_dai->codec; - unsigned int reg; switch (div_id) { case WM8900_BCLK_DIV: - reg = snd_soc_read(codec, WM8900_REG_CLOCKING1); - snd_soc_write(codec, WM8900_REG_CLOCKING1, - div | (reg & WM8900_REG_CLOCKING1_BCLK_MASK)); + snd_soc_update_bits(codec, WM8900_REG_CLOCKING1, + WM8900_REG_CLOCKING1_BCLK_MASK, div); break; case WM8900_OPCLK_DIV: - reg = snd_soc_read(codec, WM8900_REG_CLOCKING1); - snd_soc_write(codec, WM8900_REG_CLOCKING1, - div | (reg & WM8900_REG_CLOCKING1_OPCLK_MASK)); + snd_soc_update_bits(codec, WM8900_REG_CLOCKING1, + WM8900_REG_CLOCKING1_OPCLK_MASK, div); break; case WM8900_DAC_LRCLK: - reg = snd_soc_read(codec, WM8900_REG_AUDIO4); - snd_soc_write(codec, WM8900_REG_AUDIO4, - div | (reg & WM8900_LRC_MASK)); + snd_soc_update_bits(codec, WM8900_REG_AUDIO4, + WM8900_LRC_MASK, div); break; case WM8900_ADC_LRCLK: - reg = snd_soc_read(codec, WM8900_REG_AUDIO3); - snd_soc_write(codec, WM8900_REG_AUDIO3, - div | (reg & WM8900_LRC_MASK)); + snd_soc_update_bits(codec, WM8900_REG_AUDIO3, + WM8900_LRC_MASK, div); break; case WM8900_DAC_CLKDIV: - reg = snd_soc_read(codec, WM8900_REG_CLOCKING2); - snd_soc_write(codec, WM8900_REG_CLOCKING2, - div | (reg & WM8900_REG_CLOCKING2_DAC_CLKDIV)); + snd_soc_update_bits(codec, WM8900_REG_CLOCKING2, + WM8900_REG_CLOCKING2_DAC_CLKDIV, div); break; case WM8900_ADC_CLKDIV: - reg = snd_soc_read(codec, WM8900_REG_CLOCKING2); - snd_soc_write(codec, WM8900_REG_CLOCKING2, - div | (reg & WM8900_REG_CLOCKING2_ADC_CLKDIV)); + snd_soc_update_bits(codec, WM8900_REG_CLOCKING2, + WM8900_REG_CLOCKING2_ADC_CLKDIV, div); break; case WM8900_LRCLK_MODE: - reg = snd_soc_read(codec, WM8900_REG_DACCTRL); - snd_soc_write(codec, WM8900_REG_DACCTRL, - div | (reg & WM8900_REG_DACCTRL_AIF_LRCLKRATE)); + snd_soc_update_bits(codec, WM8900_REG_DACCTRL, + WM8900_REG_DACCTRL_AIF_LRCLKRATE, div); break; default: return -EINVAL; @@ -1037,12 +1022,12 @@ static int wm8900_set_bias_level(struct snd_soc_codec *codec, switch (level) { case SND_SOC_BIAS_ON: /* Enable thermal shutdown */ - reg = snd_soc_read(codec, WM8900_REG_GPIO); - snd_soc_write(codec, WM8900_REG_GPIO, - reg | WM8900_REG_GPIO_TEMP_ENA); - reg = snd_soc_read(codec, WM8900_REG_ADDCTL); - snd_soc_write(codec, WM8900_REG_ADDCTL, - reg | WM8900_REG_ADDCTL_TEMP_SD); + snd_soc_update_bits(codec, WM8900_REG_GPIO, + WM8900_REG_GPIO_TEMP_ENA, + WM8900_REG_GPIO_TEMP_ENA); + snd_soc_update_bits(codec, WM8900_REG_ADDCTL, + WM8900_REG_ADDCTL_TEMP_SD, + WM8900_REG_ADDCTL_TEMP_SD); break; case SND_SOC_BIAS_PREPARE: @@ -1205,26 +1190,16 @@ static int wm8900_probe(struct snd_soc_codec *codec) wm8900_set_bias_level(codec, SND_SOC_BIAS_STANDBY); /* Latch the volume update bits */ - snd_soc_write(codec, WM8900_REG_LINVOL, - snd_soc_read(codec, WM8900_REG_LINVOL) | 0x100); - snd_soc_write(codec, WM8900_REG_RINVOL, - snd_soc_read(codec, WM8900_REG_RINVOL) | 0x100); - snd_soc_write(codec, WM8900_REG_LOUT1CTL, - snd_soc_read(codec, WM8900_REG_LOUT1CTL) | 0x100); - snd_soc_write(codec, WM8900_REG_ROUT1CTL, - snd_soc_read(codec, WM8900_REG_ROUT1CTL) | 0x100); - snd_soc_write(codec, WM8900_REG_LOUT2CTL, - snd_soc_read(codec, WM8900_REG_LOUT2CTL) | 0x100); - snd_soc_write(codec, WM8900_REG_ROUT2CTL, - snd_soc_read(codec, WM8900_REG_ROUT2CTL) | 0x100); - snd_soc_write(codec, WM8900_REG_LDAC_DV, - snd_soc_read(codec, WM8900_REG_LDAC_DV) | 0x100); - snd_soc_write(codec, WM8900_REG_RDAC_DV, - snd_soc_read(codec, WM8900_REG_RDAC_DV) | 0x100); - snd_soc_write(codec, WM8900_REG_LADC_DV, - snd_soc_read(codec, WM8900_REG_LADC_DV) | 0x100); - snd_soc_write(codec, WM8900_REG_RADC_DV, - snd_soc_read(codec, WM8900_REG_RADC_DV) | 0x100); + snd_soc_update_bits(codec, WM8900_REG_LINVOL, 0x100, 0x100); + snd_soc_update_bits(codec, WM8900_REG_RINVOL, 0x100, 0x100); + snd_soc_update_bits(codec, WM8900_REG_LOUT1CTL, 0x100, 0x100); + snd_soc_update_bits(codec, WM8900_REG_ROUT1CTL, 0x100, 0x100); + snd_soc_update_bits(codec, WM8900_REG_LOUT2CTL, 0x100, 0x100); + snd_soc_update_bits(codec, WM8900_REG_ROUT2CTL, 0x100, 0x100); + snd_soc_update_bits(codec, WM8900_REG_LDAC_DV, 0x100, 0x100); + snd_soc_update_bits(codec, WM8900_REG_RDAC_DV, 0x100, 0x100); + snd_soc_update_bits(codec, WM8900_REG_LADC_DV, 0x100, 0x100); + snd_soc_update_bits(codec, WM8900_REG_RADC_DV, 0x100, 0x100); /* Set the DAC and mixer output bias */ snd_soc_write(codec, WM8900_REG_OUTBIASCTL, 0x81); diff --git a/sound/soc/codecs/wm8904.c b/sound/soc/codecs/wm8904.c index b085575d4aa..285ef87e670 100644 --- a/sound/soc/codecs/wm8904.c +++ b/sound/soc/codecs/wm8904.c @@ -50,7 +50,6 @@ static const char *wm8904_supply_names[WM8904_NUM_SUPPLIES] = { struct wm8904_priv { enum wm8904_type devtype; - void *control_data; struct regulator_bulk_data supplies[WM8904_NUM_SUPPLIES]; @@ -868,7 +867,7 @@ SOC_ENUM("Right Capture Mode", rin_mode), SOC_DOUBLE_R("Capture Volume", WM8904_ANALOGUE_LEFT_INPUT_0, WM8904_ANALOGUE_RIGHT_INPUT_0, 0, 31, 0), SOC_DOUBLE_R("Capture Switch", WM8904_ANALOGUE_LEFT_INPUT_0, - WM8904_ANALOGUE_RIGHT_INPUT_0, 7, 1, 0), + WM8904_ANALOGUE_RIGHT_INPUT_0, 7, 1, 1), SOC_SINGLE("High Pass Filter Switch", WM8904_ADC_DIGITAL_0, 4, 1, 0), SOC_ENUM("High Pass Filter Mode", hpf_mode), @@ -2540,7 +2539,6 @@ static __devinit int wm8904_i2c_probe(struct i2c_client *i2c, wm8904->devtype = id->driver_data; i2c_set_clientdata(i2c, wm8904); - wm8904->control_data = i2c; wm8904->pdata = i2c->dev.platform_data; ret = snd_soc_register_codec(&i2c->dev, diff --git a/sound/soc/codecs/wm8940.c b/sound/soc/codecs/wm8940.c index 056daa0010f..de9ec9b8b7d 100644 --- a/sound/soc/codecs/wm8940.c +++ b/sound/soc/codecs/wm8940.c @@ -43,9 +43,19 @@ struct wm8940_priv { unsigned int sysclk; enum snd_soc_control_type control_type; - void *control_data; }; +static int wm8940_volatile_register(struct snd_soc_codec *codec, + unsigned int reg) +{ + switch (reg) { + case WM8940_SOFTRESET: + return 1; + default: + return 0; + } +} + static u16 wm8940_reg_defaults[] = { 0x8940, /* Soft Reset */ 0x0000, /* Power 1 */ @@ -460,6 +470,14 @@ static int wm8940_set_bias_level(struct snd_soc_codec *codec, ret = snd_soc_write(codec, WM8940_POWER1, pwr_reg | 0x1); break; case SND_SOC_BIAS_STANDBY: + if (codec->dapm.bias_level == SND_SOC_BIAS_OFF) { + ret = snd_soc_cache_sync(codec); + if (ret < 0) { + dev_err(codec->dev, "Failed to sync cache: %d\n", ret); + return ret; + } + } + /* ensure bufioen and biasen */ pwr_reg |= (1 << 2) | (1 << 3); /* set vmid to 300k for standby */ @@ -470,6 +488,8 @@ static int wm8940_set_bias_level(struct snd_soc_codec *codec, break; } + codec->dapm.bias_level = level; + return ret; } @@ -601,7 +621,7 @@ static int wm8940_set_dai_clkdiv(struct snd_soc_dai *codec_dai, switch (div_id) { case WM8940_BCLKDIV: - reg = snd_soc_read(codec, WM8940_CLOCK) & 0xFFEF3; + reg = snd_soc_read(codec, WM8940_CLOCK) & 0xFFE3; ret = snd_soc_write(codec, WM8940_CLOCK, reg | (div << 2)); break; case WM8940_MCLKDIV: @@ -660,30 +680,8 @@ static int wm8940_suspend(struct snd_soc_codec *codec, pm_message_t state) static int wm8940_resume(struct snd_soc_codec *codec) { - int i; - int ret; - u8 data[3]; - u16 *cache = codec->reg_cache; - - /* Sync reg_cache with the hardware - * Could use auto incremented writes to speed this up - */ - for (i = 0; i < ARRAY_SIZE(wm8940_reg_defaults); i++) { - data[0] = i; - data[1] = (cache[i] & 0xFF00) >> 8; - data[2] = cache[i] & 0x00FF; - ret = codec->hw_write(codec->control_data, data, 3); - if (ret < 0) - goto error_ret; - else if (ret != 3) { - ret = -EIO; - goto error_ret; - } - } - ret = wm8940_set_bias_level(codec, SND_SOC_BIAS_STANDBY); - -error_ret: - return ret; + wm8940_set_bias_level(codec, SND_SOC_BIAS_STANDBY); + return 0; } static int wm8940_probe(struct snd_soc_codec *codec) @@ -693,7 +691,6 @@ static int wm8940_probe(struct snd_soc_codec *codec) int ret; u16 reg; - codec->control_data = wm8940->control_data; ret = snd_soc_codec_set_cache_io(codec, 8, 16, wm8940->control_type); if (ret < 0) { dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret); @@ -744,6 +741,7 @@ static struct snd_soc_codec_driver soc_codec_dev_wm8940 = { .reg_cache_size = ARRAY_SIZE(wm8940_reg_defaults), .reg_word_size = sizeof(u16), .reg_cache_default = wm8940_reg_defaults, + .volatile_register = wm8940_volatile_register, }; #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) @@ -758,7 +756,6 @@ static __devinit int wm8940_i2c_probe(struct i2c_client *i2c, return -ENOMEM; i2c_set_clientdata(i2c, wm8940); - wm8940->control_data = i2c; wm8940->control_type = SND_SOC_I2C; ret = snd_soc_register_codec(&i2c->dev, diff --git a/sound/soc/codecs/wm8960.c b/sound/soc/codecs/wm8960.c index 4393394b7bc..2df253c1856 100644 --- a/sound/soc/codecs/wm8960.c +++ b/sound/soc/codecs/wm8960.c @@ -72,7 +72,6 @@ static const u16 wm8960_reg[WM8960_CACHEREGNUM] = { struct wm8960_priv { enum snd_soc_control_type control_type; - void *control_data; int (*set_bias_level)(struct snd_soc_codec *, enum snd_soc_bias_level level); struct snd_soc_dapm_widget *lout1; @@ -575,6 +574,8 @@ static int wm8960_set_bias_level_out3(struct snd_soc_codec *codec, case SND_SOC_BIAS_STANDBY: if (codec->dapm.bias_level == SND_SOC_BIAS_OFF) { + snd_soc_cache_sync(codec); + /* Enable anti-pop features */ snd_soc_write(codec, WM8960_APOP1, WM8960_POBCTRL | WM8960_SOFT_ST | @@ -677,6 +678,9 @@ static int wm8960_set_bias_level_capless(struct snd_soc_codec *codec, WM8960_VREF | WM8960_VMID_MASK, 0); break; + case SND_SOC_BIAS_OFF: + snd_soc_cache_sync(codec); + break; default: break; } @@ -902,16 +906,6 @@ static int wm8960_suspend(struct snd_soc_codec *codec, pm_message_t state) static int wm8960_resume(struct snd_soc_codec *codec) { struct wm8960_priv *wm8960 = snd_soc_codec_get_drvdata(codec); - int i; - u8 data[2]; - u16 *cache = codec->reg_cache; - - /* Sync reg_cache with the hardware */ - for (i = 0; i < ARRAY_SIZE(wm8960_reg); i++) { - data[0] = (i << 1) | ((cache[i] >> 8) & 0x0001); - data[1] = cache[i] & 0x00ff; - codec->hw_write(codec->control_data, data, 2); - } wm8960->set_bias_level(codec, SND_SOC_BIAS_STANDBY); return 0; @@ -925,7 +919,6 @@ static int wm8960_probe(struct snd_soc_codec *codec) u16 reg; wm8960->set_bias_level = wm8960_set_bias_level_out3; - codec->control_data = wm8960->control_data; if (!pdata) { dev_warn(codec->dev, "No platform data supplied\n"); @@ -1015,7 +1008,6 @@ static __devinit int wm8960_i2c_probe(struct i2c_client *i2c, i2c_set_clientdata(i2c, wm8960); wm8960->control_type = SND_SOC_I2C; - wm8960->control_data = i2c; ret = snd_soc_register_codec(&i2c->dev, &soc_codec_dev_wm8960, &wm8960_dai, 1); diff --git a/sound/soc/codecs/wm8961.c b/sound/soc/codecs/wm8961.c index cdee8103d09..9568c8a49f9 100644 --- a/sound/soc/codecs/wm8961.c +++ b/sound/soc/codecs/wm8961.c @@ -974,7 +974,9 @@ static int wm8961_probe(struct snd_soc_codec *codec) } /* This isn't volatile - readback doesn't correspond to write */ - reg = codec->hw_read(codec, WM8961_RIGHT_INPUT_VOLUME); + codec->cache_bypass = 1; + reg = snd_soc_read(codec, WM8961_RIGHT_INPUT_VOLUME); + codec->cache_bypass = 0; dev_info(codec->dev, "WM8961 family %d revision %c\n", (reg & WM8961_DEVICE_ID_MASK) >> WM8961_DEVICE_ID_SHIFT, ((reg & WM8961_CHIP_REV_MASK) >> WM8961_CHIP_REV_SHIFT) diff --git a/sound/soc/codecs/wm8962.c b/sound/soc/codecs/wm8962.c index d2c315fa1b9..91d3c6dbeba 100644 --- a/sound/soc/codecs/wm8962.c +++ b/sound/soc/codecs/wm8962.c @@ -63,6 +63,8 @@ struct wm8962_priv { int fll_fref; int fll_fout; + u16 dsp2_ena; + struct delayed_work mic_work; struct snd_soc_jack *jack; @@ -837,7 +839,7 @@ static const struct wm8962_reg_access { [40] = { 0x00FF, 0x01FF, 0x0000 }, /* R40 - SPKOUTL volume */ [41] = { 0x00FF, 0x01FF, 0x0000 }, /* R41 - SPKOUTR volume */ - [47] = { 0x000F, 0x0000, 0x0000 }, /* R47 - Thermal Shutdown Status */ + [47] = { 0x000F, 0x0000, 0xFFFF }, /* R47 - Thermal Shutdown Status */ [48] = { 0x7EC7, 0x7E07, 0xFFFF }, /* R48 - Additional Control (4) */ [49] = { 0x00D3, 0x00D7, 0xFFFF }, /* R49 - Class D Control 1 */ [51] = { 0x0047, 0x0047, 0x0000 }, /* R51 - Class D Control 2 */ @@ -965,7 +967,7 @@ static const struct wm8962_reg_access { [584] = { 0x002D, 0x002D, 0x0000 }, /* R584 - IRQ Debounce */ [586] = { 0xC000, 0xC000, 0x0000 }, /* R586 - MICINT Source Pol */ [768] = { 0x0001, 0x0001, 0x0000 }, /* R768 - DSP2 Power Management */ - [1037] = { 0x0000, 0x003F, 0x0000 }, /* R1037 - DSP2_ExecControl */ + [1037] = { 0x0000, 0x003F, 0xFFFF }, /* R1037 - DSP2_ExecControl */ [4096] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4096 - Write Sequencer 0 */ [4097] = { 0x00FF, 0x00FF, 0x0000 }, /* R4097 - Write Sequencer 1 */ [4098] = { 0x070F, 0x070F, 0x0000 }, /* R4098 - Write Sequencer 2 */ @@ -1959,7 +1961,13 @@ static int wm8962_readable_register(struct snd_soc_codec *codec, unsigned int re static int wm8962_reset(struct snd_soc_codec *codec) { - return snd_soc_write(codec, WM8962_SOFTWARE_RESET, 0x6243); + int ret; + + ret = snd_soc_write(codec, WM8962_SOFTWARE_RESET, 0x6243); + if (ret != 0) + return ret; + + return snd_soc_write(codec, WM8962_PLL_SOFTWARE_RESET, 0); } static const DECLARE_TLV_DB_SCALE(inpga_tlv, -2325, 75, 0); @@ -1986,6 +1994,122 @@ static const unsigned int classd_tlv[] = { }; static const DECLARE_TLV_DB_SCALE(eq_tlv, -1200, 100, 0); +static int wm8962_dsp2_write_config(struct snd_soc_codec *codec) +{ + return 0; +} + +static int wm8962_dsp2_set_enable(struct snd_soc_codec *codec, u16 val) +{ + u16 adcl = snd_soc_read(codec, WM8962_LEFT_ADC_VOLUME); + u16 adcr = snd_soc_read(codec, WM8962_RIGHT_ADC_VOLUME); + u16 dac = snd_soc_read(codec, WM8962_ADC_DAC_CONTROL_1); + + /* Mute the ADCs and DACs */ + snd_soc_write(codec, WM8962_LEFT_ADC_VOLUME, 0); + snd_soc_write(codec, WM8962_RIGHT_ADC_VOLUME, WM8962_ADC_VU); + snd_soc_update_bits(codec, WM8962_ADC_DAC_CONTROL_1, + WM8962_DAC_MUTE, WM8962_DAC_MUTE); + + snd_soc_write(codec, WM8962_SOUNDSTAGE_ENABLES_0, val); + + /* Restore the ADCs and DACs */ + snd_soc_write(codec, WM8962_LEFT_ADC_VOLUME, adcl); + snd_soc_write(codec, WM8962_RIGHT_ADC_VOLUME, adcr); + snd_soc_update_bits(codec, WM8962_ADC_DAC_CONTROL_1, + WM8962_DAC_MUTE, dac); + + return 0; +} + +static int wm8962_dsp2_start(struct snd_soc_codec *codec) +{ + struct wm8962_priv *wm8962 = snd_soc_codec_get_drvdata(codec); + + wm8962_dsp2_write_config(codec); + + snd_soc_write(codec, WM8962_DSP2_EXECCONTROL, WM8962_DSP2_RUNR); + + wm8962_dsp2_set_enable(codec, wm8962->dsp2_ena); + + return 0; +} + +static int wm8962_dsp2_stop(struct snd_soc_codec *codec) +{ + wm8962_dsp2_set_enable(codec, 0); + + snd_soc_write(codec, WM8962_DSP2_EXECCONTROL, WM8962_DSP2_STOP); + + return 0; +} + +#define WM8962_DSP2_ENABLE(xname, xshift) \ +{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \ + .info = wm8962_dsp2_ena_info, \ + .get = wm8962_dsp2_ena_get, .put = wm8962_dsp2_ena_put, \ + .private_value = xshift } + +static int wm8962_dsp2_ena_info(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_info *uinfo) +{ + uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN; + + uinfo->count = 1; + uinfo->value.integer.min = 0; + uinfo->value.integer.max = 1; + + return 0; +} + +static int wm8962_dsp2_ena_get(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + int shift = kcontrol->private_value; + struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); + struct wm8962_priv *wm8962 = snd_soc_codec_get_drvdata(codec); + + ucontrol->value.integer.value[0] = !!(wm8962->dsp2_ena & 1 << shift); + + return 0; +} + +static int wm8962_dsp2_ena_put(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + int shift = kcontrol->private_value; + struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); + struct wm8962_priv *wm8962 = snd_soc_codec_get_drvdata(codec); + int old = wm8962->dsp2_ena; + int ret = 0; + int dsp2_running = snd_soc_read(codec, WM8962_DSP2_POWER_MANAGEMENT) & + WM8962_DSP2_ENA; + + mutex_lock(&codec->mutex); + + if (ucontrol->value.integer.value[0]) + wm8962->dsp2_ena |= 1 << shift; + else + wm8962->dsp2_ena &= ~(1 << shift); + + if (wm8962->dsp2_ena == old) + goto out; + + ret = 1; + + if (dsp2_running) { + if (wm8962->dsp2_ena) + wm8962_dsp2_set_enable(codec, wm8962->dsp2_ena); + else + wm8962_dsp2_stop(codec); + } + +out: + mutex_unlock(&codec->mutex); + + return ret; +} + /* The VU bits for the headphones are in a different register to the mute * bits and only take effect on the PGA if it is actually powered. */ @@ -2021,7 +2145,6 @@ static int wm8962_put_spk_sw(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); - u16 *reg_cache = codec->reg_cache; int ret; /* Apply the update (if any) */ @@ -2030,16 +2153,19 @@ static int wm8962_put_spk_sw(struct snd_kcontrol *kcontrol, return 0; /* If the left PGA is enabled hit that VU bit... */ - if (reg_cache[WM8962_PWR_MGMT_2] & WM8962_SPKOUTL_PGA_ENA) - return snd_soc_write(codec, WM8962_SPKOUTL_VOLUME, - reg_cache[WM8962_SPKOUTL_VOLUME]); + ret = snd_soc_read(codec, WM8962_PWR_MGMT_2); + if (ret & WM8962_SPKOUTL_PGA_ENA) { + snd_soc_write(codec, WM8962_SPKOUTL_VOLUME, + snd_soc_read(codec, WM8962_SPKOUTL_VOLUME)); + return 1; + } /* ...otherwise the right. The VU is stereo. */ - if (reg_cache[WM8962_PWR_MGMT_2] & WM8962_SPKOUTR_PGA_ENA) - return snd_soc_write(codec, WM8962_SPKOUTR_VOLUME, - reg_cache[WM8962_SPKOUTR_VOLUME]); + if (ret & WM8962_SPKOUTR_PGA_ENA) + snd_soc_write(codec, WM8962_SPKOUTR_VOLUME, + snd_soc_read(codec, WM8962_SPKOUTR_VOLUME)); - return 0; + return 1; } static const char *cap_hpf_mode_text[] = { @@ -2049,6 +2175,14 @@ static const char *cap_hpf_mode_text[] = { static const struct soc_enum cap_hpf_mode = SOC_ENUM_SINGLE(WM8962_ADC_DAC_CONTROL_2, 10, 2, cap_hpf_mode_text); + +static const char *cap_lhpf_mode_text[] = { + "LPF", "HPF" +}; + +static const struct soc_enum cap_lhpf_mode = + SOC_ENUM_SINGLE(WM8962_LHPF1, 1, 2, cap_lhpf_mode_text); + static const struct snd_kcontrol_new wm8962_snd_controls[] = { SOC_DOUBLE("Input Mixer Switch", WM8962_INPUT_MIXER_CONTROL_1, 3, 2, 1, 1), @@ -2077,6 +2211,8 @@ SOC_DOUBLE_R("Capture ZC Switch", WM8962_LEFT_INPUT_VOLUME, SOC_SINGLE("Capture HPF Switch", WM8962_ADC_DAC_CONTROL_1, 0, 1, 1), SOC_ENUM("Capture HPF Mode", cap_hpf_mode), SOC_SINGLE("Capture HPF Cutoff", WM8962_ADC_DAC_CONTROL_2, 7, 7, 0), +SOC_SINGLE("Capture LHPF Switch", WM8962_LHPF1, 0, 1, 0), +SOC_ENUM("Capture LHPF Mode", cap_lhpf_mode), SOC_DOUBLE_R_TLV("Sidetone Volume", WM8962_DAC_DSP_MIXING_1, WM8962_DAC_DSP_MIXING_2, 4, 12, 0, st_tlv), @@ -2134,6 +2270,11 @@ SOC_DOUBLE_R_TLV("EQ4 Volume", WM8962_EQ3, WM8962_EQ23, WM8962_EQL_B4_GAIN_SHIFT, 31, 0, eq_tlv), SOC_DOUBLE_R_TLV("EQ5 Volume", WM8962_EQ3, WM8962_EQ23, WM8962_EQL_B5_GAIN_SHIFT, 31, 0, eq_tlv), + +WM8962_DSP2_ENABLE("VSS Switch", WM8962_VSS_ENA_SHIFT), +WM8962_DSP2_ENABLE("HPF1 Switch", WM8962_HPF1_ENA_SHIFT), +WM8962_DSP2_ENABLE("HPF2 Switch", WM8962_HPF2_ENA_SHIFT), +WM8962_DSP2_ENABLE("HD Bass Switch", WM8962_HDBASS_ENA_SHIFT), }; static const struct snd_kcontrol_new wm8962_spk_mono_controls[] = { @@ -2225,15 +2366,14 @@ static int sysclk_event(struct snd_soc_dapm_widget *w, snd_soc_update_bits(codec, WM8962_FLL_CONTROL_1, WM8962_FLL_ENA, WM8962_FLL_ENA); - if (wm8962->irq) { - timeout = msecs_to_jiffies(5); - timeout = wait_for_completion_timeout(&wm8962->fll_lock, - timeout); - - if (timeout == 0) - dev_err(codec->dev, - "Timed out starting FLL\n"); - } + + timeout = msecs_to_jiffies(5); + timeout = wait_for_completion_timeout(&wm8962->fll_lock, + timeout); + + if (wm8962->irq && timeout == 0) + dev_err(codec->dev, + "Timed out starting FLL\n"); } break; @@ -2365,7 +2505,6 @@ static int out_pga_event(struct snd_soc_dapm_widget *w, struct snd_kcontrol *kcontrol, int event) { struct snd_soc_codec *codec = w->codec; - u16 *reg_cache = codec->reg_cache; int reg; switch (w->shift) { @@ -2388,13 +2527,38 @@ static int out_pga_event(struct snd_soc_dapm_widget *w, switch (event) { case SND_SOC_DAPM_POST_PMU: - return snd_soc_write(codec, reg, reg_cache[reg]); + return snd_soc_write(codec, reg, snd_soc_read(codec, reg)); default: BUG(); return -EINVAL; } } +static int dsp2_event(struct snd_soc_dapm_widget *w, + struct snd_kcontrol *kcontrol, int event) +{ + struct snd_soc_codec *codec = w->codec; + struct wm8962_priv *wm8962 = snd_soc_codec_get_drvdata(codec); + + switch (event) { + case SND_SOC_DAPM_POST_PMU: + if (wm8962->dsp2_ena) + wm8962_dsp2_start(codec); + break; + + case SND_SOC_DAPM_PRE_PMD: + if (wm8962->dsp2_ena) + wm8962_dsp2_stop(codec); + break; + + default: + BUG(); + return -EINVAL; + } + + return 0; +} + static const char *st_text[] = { "None", "Right", "Left" }; static const struct soc_enum str_enum = @@ -2509,7 +2673,7 @@ SND_SOC_DAPM_INPUT("IN4R"), SND_SOC_DAPM_INPUT("Beep"), SND_SOC_DAPM_INPUT("DMICDAT"), -SND_SOC_DAPM_MICBIAS("MICBIAS", WM8962_PWR_MGMT_1, 1, 0), +SND_SOC_DAPM_SUPPLY("MICBIAS", WM8962_PWR_MGMT_1, 1, 0, NULL, 0), SND_SOC_DAPM_SUPPLY("Class G", WM8962_CHARGE_PUMP_B, 0, 1, NULL, 0), SND_SOC_DAPM_SUPPLY("SYSCLK", WM8962_CLOCKING2, 5, 0, sysclk_event, @@ -2517,6 +2681,9 @@ SND_SOC_DAPM_SUPPLY("SYSCLK", WM8962_CLOCKING2, 5, 0, sysclk_event, SND_SOC_DAPM_SUPPLY("Charge Pump", WM8962_CHARGE_PUMP_1, 0, 0, cp_event, SND_SOC_DAPM_POST_PMU), SND_SOC_DAPM_SUPPLY("TOCLK", WM8962_ADDITIONAL_CONTROL_1, 0, 0, NULL, 0), +SND_SOC_DAPM_SUPPLY_S("DSP2", 1, WM8962_DSP2_POWER_MANAGEMENT, + WM8962_DSP2_ENA_SHIFT, 0, dsp2_event, + SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD), SND_SOC_DAPM_MIXER("INPGAL", WM8962_LEFT_INPUT_PGA_CONTROL, 4, 0, inpgal, ARRAY_SIZE(inpgal)), @@ -2527,7 +2694,7 @@ SND_SOC_DAPM_MIXER("MIXINL", WM8962_PWR_MGMT_1, 5, 0, SND_SOC_DAPM_MIXER("MIXINR", WM8962_PWR_MGMT_1, 4, 0, mixinr, ARRAY_SIZE(mixinr)), -SND_SOC_DAPM_AIF_IN("DMIC", NULL, 0, WM8962_PWR_MGMT_1, 10, 0), +SND_SOC_DAPM_AIF_IN("DMIC_ENA", NULL, 0, WM8962_PWR_MGMT_1, 10, 0), SND_SOC_DAPM_ADC("ADCL", "Capture", WM8962_PWR_MGMT_1, 3, 0), SND_SOC_DAPM_ADC("ADCR", "Capture", WM8962_PWR_MGMT_1, 2, 0), @@ -2606,17 +2773,19 @@ static const struct snd_soc_dapm_route wm8962_intercon[] = { { "MICBIAS", NULL, "SYSCLK" }, - { "DMIC", NULL, "DMICDAT" }, + { "DMIC_ENA", NULL, "DMICDAT" }, { "ADCL", NULL, "SYSCLK" }, { "ADCL", NULL, "TOCLK" }, { "ADCL", NULL, "MIXINL" }, - { "ADCL", NULL, "DMIC" }, + { "ADCL", NULL, "DMIC_ENA" }, + { "ADCL", NULL, "DSP2" }, { "ADCR", NULL, "SYSCLK" }, { "ADCR", NULL, "TOCLK" }, { "ADCR", NULL, "MIXINR" }, - { "ADCR", NULL, "DMIC" }, + { "ADCR", NULL, "DMIC_ENA" }, + { "ADCR", NULL, "DSP2" }, { "STL", "Left", "ADCL" }, { "STL", "Right", "ADCR" }, @@ -2628,11 +2797,13 @@ static const struct snd_soc_dapm_route wm8962_intercon[] = { { "DACL", NULL, "TOCLK" }, { "DACL", NULL, "Beep" }, { "DACL", NULL, "STL" }, + { "DACL", NULL, "DSP2" }, { "DACR", NULL, "SYSCLK" }, { "DACR", NULL, "TOCLK" }, { "DACR", NULL, "Beep" }, { "DACR", NULL, "STR" }, + { "DACR", NULL, "DSP2" }, { "HPMIXL", "IN4L Switch", "IN4L" }, { "HPMIXL", "IN4R Switch", "IN4R" }, @@ -3058,9 +3229,9 @@ static int wm8962_set_dai_fmt(struct snd_soc_dai *dai, unsigned int fmt) int aif0 = 0; switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { - case SND_SOC_DAIFMT_DSP_A: - aif0 |= WM8962_LRCLK_INV; case SND_SOC_DAIFMT_DSP_B: + aif0 |= WM8962_LRCLK_INV | 3; + case SND_SOC_DAIFMT_DSP_A: aif0 |= 3; switch (fmt & SND_SOC_DAIFMT_INV_MASK) { @@ -3403,12 +3574,16 @@ static irqreturn_t wm8962_irq(int irq, void *data) struct wm8962_priv *wm8962 = snd_soc_codec_get_drvdata(codec); int mask; int active; + int reg; mask = snd_soc_read(codec, WM8962_INTERRUPT_STATUS_2_MASK); active = snd_soc_read(codec, WM8962_INTERRUPT_STATUS_2); active &= ~mask; + if (!active) + return IRQ_NONE; + /* Acknowledge the interrupts */ snd_soc_write(codec, WM8962_INTERRUPT_STATUS_2, active); @@ -3420,9 +3595,21 @@ static irqreturn_t wm8962_irq(int irq, void *data) if (active & WM8962_FIFOS_ERR_EINT) dev_err(codec->dev, "FIFO error\n"); - if (active & WM8962_TEMP_SHUT_EINT) + if (active & WM8962_TEMP_SHUT_EINT) { dev_crit(codec->dev, "Thermal shutdown\n"); + reg = snd_soc_read(codec, WM8962_THERMAL_SHUTDOWN_STATUS); + + if (reg & WM8962_TEMP_ERR_HP) + dev_crit(codec->dev, "Headphone thermal error\n"); + if (reg & WM8962_TEMP_WARN_HP) + dev_crit(codec->dev, "Headphone thermal warning\n"); + if (reg & WM8962_TEMP_ERR_SPK) + dev_crit(codec->dev, "Speaker thermal error\n"); + if (reg & WM8962_TEMP_WARN_SPK) + dev_crit(codec->dev, "Speaker thermal warning\n"); + } + if (active & (WM8962_MICSCD_EINT | WM8962_MICD_EINT)) { dev_dbg(codec->dev, "Microphone event detected\n"); @@ -3847,6 +4034,11 @@ static int wm8962_probe(struct snd_soc_codec *codec) snd_soc_update_bits(codec, WM8962_CLOCKING2, WM8962_CLKREG_OVD, WM8962_CLKREG_OVD); + /* Ensure that the oscillator and PLLs are disabled */ + snd_soc_update_bits(codec, WM8962_PLL2, + WM8962_OSC_ENA | WM8962_PLL2_ENA | WM8962_PLL3_ENA, + 0); + regulator_bulk_disable(ARRAY_SIZE(wm8962->supplies), wm8962->supplies); if (pdata) { diff --git a/sound/soc/codecs/wm8971.c b/sound/soc/codecs/wm8971.c index 572bb80627a..b444b297d0b 100644 --- a/sound/soc/codecs/wm8971.c +++ b/sound/soc/codecs/wm8971.c @@ -546,6 +546,9 @@ static int wm8971_set_bias_level(struct snd_soc_codec *codec, case SND_SOC_BIAS_PREPARE: break; case SND_SOC_BIAS_STANDBY: + if (codec->dapm.bias_level == SND_SOC_BIAS_OFF) + snd_soc_cache_sync(codec); + /* mute dac and set vmid to 500k, enable VREF */ snd_soc_write(codec, WM8971_PWR1, pwr_reg | 0x0140); break; @@ -605,20 +608,8 @@ static int wm8971_suspend(struct snd_soc_codec *codec, pm_message_t state) static int wm8971_resume(struct snd_soc_codec *codec) { - int i; - u8 data[2]; - u16 *cache = codec->reg_cache; u16 reg; - /* Sync reg_cache with the hardware */ - for (i = 0; i < ARRAY_SIZE(wm8971_reg); i++) { - if (i + 1 == WM8971_RESET) - continue; - data[0] = (i << 1) | ((cache[i] >> 8) & 0x0001); - data[1] = cache[i] & 0x00ff; - codec->hw_write(codec->control_data, data, 2); - } - wm8971_set_bias_level(codec, SND_SOC_BIAS_STANDBY); /* charge wm8971 caps */ @@ -660,25 +651,14 @@ static int wm8971_probe(struct snd_soc_codec *codec) msecs_to_jiffies(1000)); /* set the update bits */ - reg = snd_soc_read(codec, WM8971_LDAC); - snd_soc_write(codec, WM8971_LDAC, reg | 0x0100); - reg = snd_soc_read(codec, WM8971_RDAC); - snd_soc_write(codec, WM8971_RDAC, reg | 0x0100); - - reg = snd_soc_read(codec, WM8971_LOUT1V); - snd_soc_write(codec, WM8971_LOUT1V, reg | 0x0100); - reg = snd_soc_read(codec, WM8971_ROUT1V); - snd_soc_write(codec, WM8971_ROUT1V, reg | 0x0100); - - reg = snd_soc_read(codec, WM8971_LOUT2V); - snd_soc_write(codec, WM8971_LOUT2V, reg | 0x0100); - reg = snd_soc_read(codec, WM8971_ROUT2V); - snd_soc_write(codec, WM8971_ROUT2V, reg | 0x0100); - - reg = snd_soc_read(codec, WM8971_LINVOL); - snd_soc_write(codec, WM8971_LINVOL, reg | 0x0100); - reg = snd_soc_read(codec, WM8971_RINVOL); - snd_soc_write(codec, WM8971_RINVOL, reg | 0x0100); + snd_soc_update_bits(codec, WM8971_LDAC, 0x0100, 0x0100); + snd_soc_update_bits(codec, WM8971_RDAC, 0x0100, 0x0100); + snd_soc_update_bits(codec, WM8971_LOUT1V, 0x0100, 0x0100); + snd_soc_update_bits(codec, WM8971_ROUT1V, 0x0100, 0x0100); + snd_soc_update_bits(codec, WM8971_LOUT2V, 0x0100, 0x0100); + snd_soc_update_bits(codec, WM8971_ROUT2V, 0x0100, 0x0100); + snd_soc_update_bits(codec, WM8971_LINVOL, 0x0100, 0x0100); + snd_soc_update_bits(codec, WM8971_RINVOL, 0x0100, 0x0100); snd_soc_add_controls(codec, wm8971_snd_controls, ARRAY_SIZE(wm8971_snd_controls)); diff --git a/sound/soc/codecs/wm8974.c b/sound/soc/codecs/wm8974.c index ca646a82244..9352f1e088d 100644 --- a/sound/soc/codecs/wm8974.c +++ b/sound/soc/codecs/wm8974.c @@ -3,7 +3,7 @@ * * Copyright 2006-2009 Wolfson Microelectronics PLC. * - * Author: Liam Girdwood <linux@wolfsonmicro.com> + * Author: Liam Girdwood <Liam.Girdwood@wolfsonmicro.com> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as @@ -530,6 +530,8 @@ static int wm8974_set_bias_level(struct snd_soc_codec *codec, power1 |= WM8974_POWER1_BIASEN | WM8974_POWER1_BUFIOEN; if (codec->dapm.bias_level == SND_SOC_BIAS_OFF) { + snd_soc_cache_sync(codec); + /* Initial cap charge at VMID 5k */ snd_soc_write(codec, WM8974_POWER1, power1 | 0x3); mdelay(100); @@ -589,18 +591,7 @@ static int wm8974_suspend(struct snd_soc_codec *codec, pm_message_t state) static int wm8974_resume(struct snd_soc_codec *codec) { - int i; - u8 data[2]; - u16 *cache = codec->reg_cache; - - /* Sync reg_cache with the hardware */ - for (i = 0; i < ARRAY_SIZE(wm8974_reg); i++) { - data[0] = (i << 1) | ((cache[i] >> 8) & 0x0001); - data[1] = cache[i] & 0x00ff; - codec->hw_write(codec->control_data, data, 2); - } wm8974_set_bias_level(codec, SND_SOC_BIAS_STANDBY); - return 0; } diff --git a/sound/soc/codecs/wm8978.c b/sound/soc/codecs/wm8978.c index 85e3e630e76..41ca4d9ac20 100644 --- a/sound/soc/codecs/wm8978.c +++ b/sound/soc/codecs/wm8978.c @@ -52,7 +52,6 @@ static const u16 wm8978_reg[WM8978_CACHEREGNUM] = { /* codec private data */ struct wm8978_priv { enum snd_soc_control_type control_type; - void *control_data; unsigned int f_pllout; unsigned int f_mclk; unsigned int f_256fs; @@ -955,7 +954,6 @@ static int wm8978_probe(struct snd_soc_codec *codec) * default hardware setting */ wm8978->sysclk = WM8978_PLL; - codec->control_data = wm8978->control_data; ret = snd_soc_codec_set_cache_io(codec, 7, 9, SND_SOC_I2C); if (ret < 0) { dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret); @@ -1016,7 +1014,6 @@ static __devinit int wm8978_i2c_probe(struct i2c_client *i2c, return -ENOMEM; i2c_set_clientdata(i2c, wm8978); - wm8978->control_data = i2c; ret = snd_soc_register_codec(&i2c->dev, &soc_codec_dev_wm8978, &wm8978_dai, 1); diff --git a/sound/soc/codecs/wm8983.c b/sound/soc/codecs/wm8983.c index 17f04ec2b94..93ee28439be 100644 --- a/sound/soc/codecs/wm8983.c +++ b/sound/soc/codecs/wm8983.c @@ -1007,7 +1007,7 @@ static int wm8983_probe(struct snd_soc_codec *codec) return ret; } - ret = snd_soc_write(codec, WM8983_SOFTWARE_RESET, 0x8983); + ret = snd_soc_write(codec, WM8983_SOFTWARE_RESET, 0); if (ret < 0) { dev_err(codec->dev, "Failed to issue reset: %d\n", ret); return ret; diff --git a/sound/soc/codecs/wm8988.c b/sound/soc/codecs/wm8988.c index d7170f1381a..2e9eba717d1 100644 --- a/sound/soc/codecs/wm8988.c +++ b/sound/soc/codecs/wm8988.c @@ -55,7 +55,6 @@ struct wm8988_priv { struct snd_pcm_hw_constraint_list *sysclk_constraints; }; - #define wm8988_reset(c) snd_soc_write(c, WM8988_RESET, 0) /* @@ -676,6 +675,8 @@ static int wm8988_set_bias_level(struct snd_soc_codec *codec, case SND_SOC_BIAS_STANDBY: if (codec->dapm.bias_level == SND_SOC_BIAS_OFF) { + snd_soc_cache_sync(codec); + /* VREF, VMID=2x5k */ snd_soc_write(codec, WM8988_PWR1, pwr_reg | 0x1c1); @@ -736,21 +737,7 @@ static int wm8988_suspend(struct snd_soc_codec *codec, pm_message_t state) static int wm8988_resume(struct snd_soc_codec *codec) { - int i; - u8 data[2]; - u16 *cache = codec->reg_cache; - - /* Sync reg_cache with the hardware */ - for (i = 0; i < WM8988_NUM_REG; i++) { - if (i == WM8988_RESET) - continue; - data[0] = (i << 1) | ((cache[i] >> 8) & 0x0001); - data[1] = cache[i] & 0x00ff; - codec->hw_write(codec->control_data, data, 2); - } - wm8988_set_bias_level(codec, SND_SOC_BIAS_STANDBY); - return 0; } @@ -759,7 +746,6 @@ static int wm8988_probe(struct snd_soc_codec *codec) struct wm8988_priv *wm8988 = snd_soc_codec_get_drvdata(codec); struct snd_soc_dapm_context *dapm = &codec->dapm; int ret = 0; - u16 reg; ret = snd_soc_codec_set_cache_io(codec, 7, 9, wm8988->control_type); if (ret < 0) { @@ -774,16 +760,11 @@ static int wm8988_probe(struct snd_soc_codec *codec) } /* set the update bits (we always update left then right) */ - reg = snd_soc_read(codec, WM8988_RADC); - snd_soc_write(codec, WM8988_RADC, reg | 0x100); - reg = snd_soc_read(codec, WM8988_RDAC); - snd_soc_write(codec, WM8988_RDAC, reg | 0x0100); - reg = snd_soc_read(codec, WM8988_ROUT1V); - snd_soc_write(codec, WM8988_ROUT1V, reg | 0x0100); - reg = snd_soc_read(codec, WM8988_ROUT2V); - snd_soc_write(codec, WM8988_ROUT2V, reg | 0x0100); - reg = snd_soc_read(codec, WM8988_RINVOL); - snd_soc_write(codec, WM8988_RINVOL, reg | 0x0100); + snd_soc_update_bits(codec, WM8988_RADC, 0x0100, 0x0100); + snd_soc_update_bits(codec, WM8988_RDAC, 0x0100, 0x0100); + snd_soc_update_bits(codec, WM8988_ROUT1V, 0x0100, 0x0100); + snd_soc_update_bits(codec, WM8988_ROUT2V, 0x0100, 0x0100); + snd_soc_update_bits(codec, WM8988_RINVOL, 0x0100, 0x0100); wm8988_set_bias_level(codec, SND_SOC_BIAS_STANDBY); diff --git a/sound/soc/codecs/wm8990.c b/sound/soc/codecs/wm8990.c index 100aeee5ba9..d29a9622964 100644 --- a/sound/soc/codecs/wm8990.c +++ b/sound/soc/codecs/wm8990.c @@ -36,10 +36,17 @@ struct wm8990_priv { unsigned int pcmclk; }; -/* - * wm8990 register cache. Note that register 0 is not included in the - * cache. - */ +static int wm8990_volatile_register(struct snd_soc_codec *codec, + unsigned int reg) +{ + switch (reg) { + case WM8990_RESET: + return 1; + default: + return 0; + } +} + static const u16 wm8990_reg[] = { 0x8990, /* R0 - Reset */ 0x0000, /* R1 - Power Management (1) */ @@ -394,7 +401,7 @@ static int inmixer_event(struct snd_soc_dapm_widget *w, (1 << WM8990_AINRMUX_PWR_BIT))) { reg |= WM8990_AINR_ENA; } else { - reg &= ~WM8990_AINL_ENA; + reg &= ~WM8990_AINR_ENA; } snd_soc_write(w->codec, WM8990_POWER_MANAGEMENT_2, reg); @@ -974,7 +981,6 @@ static void pll_factors(struct _pll_div *pll_div, unsigned int target, static int wm8990_set_dai_pll(struct snd_soc_dai *codec_dai, int pll_id, int source, unsigned int freq_in, unsigned int freq_out) { - u16 reg; struct snd_soc_codec *codec = codec_dai->codec; struct _pll_div pll_div; @@ -982,13 +988,12 @@ static int wm8990_set_dai_pll(struct snd_soc_dai *codec_dai, int pll_id, pll_factors(&pll_div, freq_out * 4, freq_in); /* Turn on PLL */ - reg = snd_soc_read(codec, WM8990_POWER_MANAGEMENT_2); - reg |= WM8990_PLL_ENA; - snd_soc_write(codec, WM8990_POWER_MANAGEMENT_2, reg); + snd_soc_update_bits(codec, WM8990_POWER_MANAGEMENT_2, + WM8990_PLL_ENA, WM8990_PLL_ENA); /* sysclk comes from PLL */ - reg = snd_soc_read(codec, WM8990_CLOCKING_2); - snd_soc_write(codec, WM8990_CLOCKING_2, reg | WM8990_SYSCLK_SRC); + snd_soc_update_bits(codec, WM8990_CLOCKING_2, + WM8990_SYSCLK_SRC, WM8990_SYSCLK_SRC); /* set up N , fractional mode and pre-divisor if necessary */ snd_soc_write(codec, WM8990_PLL1, pll_div.n | WM8990_SDM | @@ -996,10 +1001,9 @@ static int wm8990_set_dai_pll(struct snd_soc_dai *codec_dai, int pll_id, snd_soc_write(codec, WM8990_PLL2, (u8)(pll_div.k>>8)); snd_soc_write(codec, WM8990_PLL3, (u8)(pll_div.k & 0xFF)); } else { - /* Turn on PLL */ - reg = snd_soc_read(codec, WM8990_POWER_MANAGEMENT_2); - reg &= ~WM8990_PLL_ENA; - snd_soc_write(codec, WM8990_POWER_MANAGEMENT_2, reg); + /* Turn off PLL */ + snd_soc_update_bits(codec, WM8990_POWER_MANAGEMENT_2, + WM8990_PLL_ENA, 0); } return 0; } @@ -1077,28 +1081,23 @@ static int wm8990_set_dai_clkdiv(struct snd_soc_dai *codec_dai, int div_id, int div) { struct snd_soc_codec *codec = codec_dai->codec; - u16 reg; switch (div_id) { case WM8990_MCLK_DIV: - reg = snd_soc_read(codec, WM8990_CLOCKING_2) & - ~WM8990_MCLK_DIV_MASK; - snd_soc_write(codec, WM8990_CLOCKING_2, reg | div); + snd_soc_update_bits(codec, WM8990_CLOCKING_2, + WM8990_MCLK_DIV_MASK, div); break; case WM8990_DACCLK_DIV: - reg = snd_soc_read(codec, WM8990_CLOCKING_2) & - ~WM8990_DAC_CLKDIV_MASK; - snd_soc_write(codec, WM8990_CLOCKING_2, reg | div); + snd_soc_update_bits(codec, WM8990_CLOCKING_2, + WM8990_DAC_CLKDIV_MASK, div); break; case WM8990_ADCCLK_DIV: - reg = snd_soc_read(codec, WM8990_CLOCKING_2) & - ~WM8990_ADC_CLKDIV_MASK; - snd_soc_write(codec, WM8990_CLOCKING_2, reg | div); + snd_soc_update_bits(codec, WM8990_CLOCKING_2, + WM8990_ADC_CLKDIV_MASK, div); break; case WM8990_BCLK_DIV: - reg = snd_soc_read(codec, WM8990_CLOCKING_1) & - ~WM8990_BCLK_DIV_MASK; - snd_soc_write(codec, WM8990_CLOCKING_1, reg | div); + snd_soc_update_bits(codec, WM8990_CLOCKING_1, + WM8990_BCLK_DIV_MASK, div); break; default: return -EINVAL; @@ -1156,7 +1155,7 @@ static int wm8990_mute(struct snd_soc_dai *dai, int mute) static int wm8990_set_bias_level(struct snd_soc_codec *codec, enum snd_soc_bias_level level) { - u16 val; + int ret; switch (level) { case SND_SOC_BIAS_ON: @@ -1164,13 +1163,18 @@ static int wm8990_set_bias_level(struct snd_soc_codec *codec, case SND_SOC_BIAS_PREPARE: /* VMID=2*50k */ - val = snd_soc_read(codec, WM8990_POWER_MANAGEMENT_1) & - ~WM8990_VMID_MODE_MASK; - snd_soc_write(codec, WM8990_POWER_MANAGEMENT_1, val | 0x2); + snd_soc_update_bits(codec, WM8990_POWER_MANAGEMENT_1, + WM8990_VMID_MODE_MASK, 0x2); break; case SND_SOC_BIAS_STANDBY: if (codec->dapm.bias_level == SND_SOC_BIAS_OFF) { + ret = snd_soc_cache_sync(codec); + if (ret < 0) { + dev_err(codec->dev, "Failed to sync cache: %d\n", ret); + return ret; + } + /* Enable all output discharge bits */ snd_soc_write(codec, WM8990_ANTIPOP1, WM8990_DIS_LLINE | WM8990_DIS_RLINE | WM8990_DIS_OUT3 | @@ -1225,9 +1229,8 @@ static int wm8990_set_bias_level(struct snd_soc_codec *codec, } /* VMID=2*250k */ - val = snd_soc_read(codec, WM8990_POWER_MANAGEMENT_1) & - ~WM8990_VMID_MODE_MASK; - snd_soc_write(codec, WM8990_POWER_MANAGEMENT_1, val | 0x4); + snd_soc_update_bits(codec, WM8990_POWER_MANAGEMENT_1, + WM8990_VMID_MODE_MASK, 0x4); break; case SND_SOC_BIAS_OFF: @@ -1241,8 +1244,8 @@ static int wm8990_set_bias_level(struct snd_soc_codec *codec, WM8990_BUFIOEN); /* mute DAC */ - val = snd_soc_read(codec, WM8990_DAC_CTRL); - snd_soc_write(codec, WM8990_DAC_CTRL, val | WM8990_DAC_MUTE); + snd_soc_update_bits(codec, WM8990_DAC_CTRL, + WM8990_DAC_MUTE, WM8990_DAC_MUTE); /* Enable any disabled outputs */ snd_soc_write(codec, WM8990_POWER_MANAGEMENT_1, 0x1f03); @@ -1319,19 +1322,6 @@ static int wm8990_suspend(struct snd_soc_codec *codec, pm_message_t state) static int wm8990_resume(struct snd_soc_codec *codec) { - int i; - u8 data[2]; - u16 *cache = codec->reg_cache; - - /* Sync reg_cache with the hardware */ - for (i = 0; i < ARRAY_SIZE(wm8990_reg); i++) { - if (i + 1 == WM8990_RESET) - continue; - data[0] = ((i + 1) << 1) | ((cache[i] >> 8) & 0x0001); - data[1] = cache[i] & 0x00ff; - codec->hw_write(codec->control_data, data, 2); - } - wm8990_set_bias_level(codec, SND_SOC_BIAS_STANDBY); return 0; } @@ -1343,7 +1333,6 @@ static int wm8990_resume(struct snd_soc_codec *codec) static int wm8990_probe(struct snd_soc_codec *codec) { int ret; - u16 reg; ret = snd_soc_codec_set_cache_io(codec, 8, 16, SND_SOC_I2C); if (ret < 0) { @@ -1356,15 +1345,14 @@ static int wm8990_probe(struct snd_soc_codec *codec) /* charge output caps */ wm8990_set_bias_level(codec, SND_SOC_BIAS_STANDBY); - reg = snd_soc_read(codec, WM8990_AUDIO_INTERFACE_4); - snd_soc_write(codec, WM8990_AUDIO_INTERFACE_4, reg | WM8990_ALRCGPIO1); + snd_soc_update_bits(codec, WM8990_AUDIO_INTERFACE_4, + WM8990_ALRCGPIO1, WM8990_ALRCGPIO1); - reg = snd_soc_read(codec, WM8990_GPIO1_GPIO2) & - ~WM8990_GPIO1_SEL_MASK; - snd_soc_write(codec, WM8990_GPIO1_GPIO2, reg | 1); + snd_soc_update_bits(codec, WM8990_GPIO1_GPIO2, + WM8990_GPIO1_SEL_MASK, 1); - reg = snd_soc_read(codec, WM8990_POWER_MANAGEMENT_2); - snd_soc_write(codec, WM8990_POWER_MANAGEMENT_2, reg | WM8990_OPCLK_ENA); + snd_soc_update_bits(codec, WM8990_POWER_MANAGEMENT_2, + WM8990_OPCLK_ENA, WM8990_OPCLK_ENA); snd_soc_write(codec, WM8990_LEFT_OUTPUT_VOLUME, 0x50 | (1<<8)); snd_soc_write(codec, WM8990_RIGHT_OUTPUT_VOLUME, 0x50 | (1<<8)); @@ -1392,6 +1380,7 @@ static struct snd_soc_codec_driver soc_codec_dev_wm8990 = { .reg_cache_size = ARRAY_SIZE(wm8990_reg), .reg_word_size = sizeof(u16), .reg_cache_default = wm8990_reg, + .volatile_register = wm8990_volatile_register, }; #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) diff --git a/sound/soc/codecs/wm8991.c b/sound/soc/codecs/wm8991.c index 6af23d06870..c9ab3ba9bce 100644 --- a/sound/soc/codecs/wm8991.c +++ b/sound/soc/codecs/wm8991.c @@ -3,7 +3,7 @@ * * Copyright 2007-2010 Wolfson Microelectronics PLC. * Author: Graeme Gregory - * linux@wolfsonmicro.com + * Graeme.Gregory@wolfsonmicro.com * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the @@ -393,7 +393,7 @@ static int inmixer_event(struct snd_soc_dapm_widget *w, (1 << WM8991_AINRMUX_PWR_BIT))) reg |= WM8991_AINR_ENA; else - reg &= ~WM8991_AINL_ENA; + reg &= ~WM8991_AINR_ENA; snd_soc_write(w->codec, WM8991_POWER_MANAGEMENT_2, reg); return 0; @@ -1264,7 +1264,6 @@ static int wm8991_probe(struct snd_soc_codec *codec) { struct wm8991_priv *wm8991; int ret; - unsigned int reg; wm8991 = snd_soc_codec_get_drvdata(codec); @@ -1282,19 +1281,18 @@ static int wm8991_probe(struct snd_soc_codec *codec) wm8991_set_bias_level(codec, SND_SOC_BIAS_STANDBY); - reg = snd_soc_read(codec, WM8991_AUDIO_INTERFACE_4); - snd_soc_write(codec, WM8991_AUDIO_INTERFACE_4, reg | WM8991_ALRCGPIO1); + snd_soc_update_bits(codec, WM8991_AUDIO_INTERFACE_4, + WM8991_ALRCGPIO1, WM8991_ALRCGPIO1); - reg = snd_soc_read(codec, WM8991_GPIO1_GPIO2) & - ~WM8991_GPIO1_SEL_MASK; - snd_soc_write(codec, WM8991_GPIO1_GPIO2, reg | 1); + snd_soc_update_bits(codec, WM8991_GPIO1_GPIO2, + WM8991_GPIO1_SEL_MASK, 1); - reg = snd_soc_read(codec, WM8991_POWER_MANAGEMENT_1); - snd_soc_write(codec, WM8991_POWER_MANAGEMENT_1, reg | WM8991_VREF_ENA| - WM8991_VMID_MODE_MASK); + snd_soc_update_bits(codec, WM8991_POWER_MANAGEMENT_1, + WM8991_VREF_ENA | WM8991_VMID_MODE_MASK, + WM8991_VREF_ENA | WM8991_VMID_MODE_MASK); - reg = snd_soc_read(codec, WM8991_POWER_MANAGEMENT_2); - snd_soc_write(codec, WM8991_POWER_MANAGEMENT_2, reg | WM8991_OPCLK_ENA); + snd_soc_update_bits(codec, WM8991_POWER_MANAGEMENT_2, + WM8991_OPCLK_ENA, WM8991_OPCLK_ENA); snd_soc_write(codec, WM8991_DAC_CTRL, 0); snd_soc_write(codec, WM8991_LEFT_OUTPUT_VOLUME, 0x50 | (1<<8)); diff --git a/sound/soc/codecs/wm8993.c b/sound/soc/codecs/wm8993.c index 6e85b8869af..eec8e143511 100644 --- a/sound/soc/codecs/wm8993.c +++ b/sound/soc/codecs/wm8993.c @@ -847,6 +847,7 @@ SND_SOC_DAPM_SUPPLY("CLK_SYS", WM8993_BUS_CONTROL_1, 1, 0, clk_sys_event, SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD), SND_SOC_DAPM_SUPPLY("TOCLK", WM8993_CLOCKING_1, 14, 0, NULL, 0), SND_SOC_DAPM_SUPPLY("CLK_DSP", WM8993_CLOCKING_3, 0, 0, NULL, 0), +SND_SOC_DAPM_SUPPLY("VMID", SND_SOC_NOPM, 0, 0, NULL, 0), SND_SOC_DAPM_ADC("ADCL", NULL, WM8993_POWER_MANAGEMENT_2, 1, 0), SND_SOC_DAPM_ADC("ADCR", NULL, WM8993_POWER_MANAGEMENT_2, 0, 0), @@ -880,6 +881,9 @@ SND_SOC_DAPM_PGA("Direct Voice", SND_SOC_NOPM, 0, 0, NULL, 0), }; static const struct snd_soc_dapm_route routes[] = { + { "MICBIAS1", NULL, "VMID" }, + { "MICBIAS2", NULL, "VMID" }, + { "ADCL", NULL, "CLK_SYS" }, { "ADCL", NULL, "CLK_DSP" }, { "ADCR", NULL, "CLK_SYS" }, @@ -1433,7 +1437,8 @@ static int wm8993_probe(struct snd_soc_codec *codec) int ret, i, val; wm8993->hubs_data.hp_startup_mode = 1; - wm8993->hubs_data.dcs_codes = -2; + wm8993->hubs_data.dcs_codes_l = -2; + wm8993->hubs_data.dcs_codes_r = -2; wm8993->hubs_data.series_startup = 1; ret = snd_soc_codec_set_cache_io(codec, 8, 16, SND_SOC_I2C); diff --git a/sound/soc/codecs/wm8994-tables.c b/sound/soc/codecs/wm8994-tables.c index a87adbd05ee..df5a8b9a250 100644 --- a/sound/soc/codecs/wm8994-tables.c +++ b/sound/soc/codecs/wm8994-tables.c @@ -1073,8 +1073,8 @@ const struct wm8994_access_mask wm8994_access_masks[WM8994_CACHE_SIZE] = { { 0x0000, 0x0000 }, /* R1069 */ { 0x0000, 0x0000 }, /* R1070 */ { 0x0000, 0x0000 }, /* R1071 */ - { 0x0000, 0x0000 }, /* R1072 */ - { 0x0000, 0x0000 }, /* R1073 */ + { 0x006F, 0x006F }, /* R1072 - AIF1 DAC1 Noise Gate */ + { 0x006F, 0x006F }, /* R1073 - AIF1 DAC2 Noise Gate */ { 0x0000, 0x0000 }, /* R1074 */ { 0x0000, 0x0000 }, /* R1075 */ { 0x0000, 0x0000 }, /* R1076 */ @@ -1329,7 +1329,7 @@ const struct wm8994_access_mask wm8994_access_masks[WM8994_CACHE_SIZE] = { { 0x0000, 0x0000 }, /* R1325 */ { 0x0000, 0x0000 }, /* R1326 */ { 0x0000, 0x0000 }, /* R1327 */ - { 0x0000, 0x0000 }, /* R1328 */ + { 0x006F, 0x006F }, /* R1328 - AIF2 DAC Noise Gate */ { 0x0000, 0x0000 }, /* R1329 */ { 0x0000, 0x0000 }, /* R1330 */ { 0x0000, 0x0000 }, /* R1331 */ @@ -1635,8 +1635,8 @@ const u16 wm8994_reg_defaults[WM8994_CACHE_SIZE] = { 0x0000, /* R58 - MICBIAS */ 0x000D, /* R59 - LDO 1 */ 0x0003, /* R60 - LDO 2 */ - 0x0000, /* R61 */ - 0x0000, /* R62 */ + 0x0039, /* R61 - MICBIAS1 */ + 0x0039, /* R62 - MICBIAS2 */ 0x0000, /* R63 */ 0x0000, /* R64 */ 0x0000, /* R65 */ @@ -2646,8 +2646,8 @@ const u16 wm8994_reg_defaults[WM8994_CACHE_SIZE] = { 0x0000, /* R1069 */ 0x0000, /* R1070 */ 0x0000, /* R1071 */ - 0x0000, /* R1072 */ - 0x0000, /* R1073 */ + 0x0068, /* R1072 - AIF1 DAC1 Noise Gate */ + 0x0068, /* R1073 - AIF1 DAC2 Noise Gate */ 0x0000, /* R1074 */ 0x0000, /* R1075 */ 0x0000, /* R1076 */ @@ -2902,7 +2902,7 @@ const u16 wm8994_reg_defaults[WM8994_CACHE_SIZE] = { 0x0000, /* R1325 */ 0x0000, /* R1326 */ 0x0000, /* R1327 */ - 0x0000, /* R1328 */ + 0x0068, /* R1328 - AIF2 DAC Noise Gate */ 0x0000, /* R1329 */ 0x0000, /* R1330 */ 0x0000, /* R1331 */ diff --git a/sound/soc/codecs/wm8994.c b/sound/soc/codecs/wm8994.c index b393f9fac97..9c982e47eb9 100644 --- a/sound/soc/codecs/wm8994.c +++ b/sound/soc/codecs/wm8994.c @@ -56,7 +56,7 @@ static int wm8994_retune_mobile_base[] = { static int wm8994_readable(struct snd_soc_codec *codec, unsigned int reg) { struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec); - struct wm8994 *control = wm8994->control_data; + struct wm8994 *control = codec->control_data; switch (reg) { case WM8994_GPIO_1: @@ -107,6 +107,7 @@ static int wm8994_volatile(struct snd_soc_codec *codec, unsigned int reg) case WM8994_LDO_2: case WM8958_DSP2_EXECCONTROL: case WM8958_MIC_DETECT_3: + case WM8994_DC_SERVO_4E: return 1; default: return 0; @@ -207,7 +208,7 @@ static int configure_aif_clock(struct snd_soc_codec *codec, int aif) static int configure_clock(struct snd_soc_codec *codec) { struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec); - int old, new; + int change, new; /* Bring up the AIF clocks first */ configure_aif_clock(codec, 0); @@ -228,14 +229,11 @@ static int configure_clock(struct snd_soc_codec *codec) else new = 0; - old = snd_soc_read(codec, WM8994_CLOCKING_1) & WM8994_SYSCLK_SRC; - - /* If there's no change then we're done. */ - if (old == new) + change = snd_soc_update_bits(codec, WM8994_CLOCKING_1, + WM8994_SYSCLK_SRC, new); + if (!change) return 0; - snd_soc_update_bits(codec, WM8994_CLOCKING_1, WM8994_SYSCLK_SRC, new); - snd_soc_dapm_sync(&codec->dapm); return 0; @@ -281,6 +279,8 @@ static const DECLARE_TLV_DB_SCALE(digital_tlv, -7200, 75, 1); static const DECLARE_TLV_DB_SCALE(st_tlv, -3600, 300, 0); static const DECLARE_TLV_DB_SCALE(wm8994_3d_tlv, -1600, 183, 0); static const DECLARE_TLV_DB_SCALE(eq_tlv, -1200, 100, 0); +static const DECLARE_TLV_DB_SCALE(ng_tlv, -10200, 600, 0); +static const DECLARE_TLV_DB_SCALE(mixin_boost_tlv, 0, 900, 0); #define WM8994_DRC_SWITCH(xname, reg, shift) \ { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \ @@ -660,8 +660,52 @@ SOC_SINGLE_TLV("AIF2 EQ5 Volume", WM8994_AIF2_EQ_GAINS_2, 6, 31, 0, eq_tlv), }; +static const char *wm8958_ng_text[] = { + "30ms", "125ms", "250ms", "500ms", +}; + +static const struct soc_enum wm8958_aif1dac1_ng_hold = + SOC_ENUM_SINGLE(WM8958_AIF1_DAC1_NOISE_GATE, + WM8958_AIF1DAC1_NG_THR_SHIFT, 4, wm8958_ng_text); + +static const struct soc_enum wm8958_aif1dac2_ng_hold = + SOC_ENUM_SINGLE(WM8958_AIF1_DAC2_NOISE_GATE, + WM8958_AIF1DAC2_NG_THR_SHIFT, 4, wm8958_ng_text); + +static const struct soc_enum wm8958_aif2dac_ng_hold = + SOC_ENUM_SINGLE(WM8958_AIF2_DAC_NOISE_GATE, + WM8958_AIF2DAC_NG_THR_SHIFT, 4, wm8958_ng_text); + static const struct snd_kcontrol_new wm8958_snd_controls[] = { SOC_SINGLE_TLV("AIF3 Boost Volume", WM8958_AIF3_CONTROL_2, 10, 3, 0, aif_tlv), + +SOC_SINGLE("AIF1DAC1 Noise Gate Switch", WM8958_AIF1_DAC1_NOISE_GATE, + WM8958_AIF1DAC1_NG_ENA_SHIFT, 1, 0), +SOC_ENUM("AIF1DAC1 Noise Gate Hold Time", wm8958_aif1dac1_ng_hold), +SOC_SINGLE_TLV("AIF1DAC1 Noise Gate Threshold Volume", + WM8958_AIF1_DAC1_NOISE_GATE, WM8958_AIF1DAC1_NG_THR_SHIFT, + 7, 1, ng_tlv), + +SOC_SINGLE("AIF1DAC2 Noise Gate Switch", WM8958_AIF1_DAC2_NOISE_GATE, + WM8958_AIF1DAC2_NG_ENA_SHIFT, 1, 0), +SOC_ENUM("AIF1DAC2 Noise Gate Hold Time", wm8958_aif1dac2_ng_hold), +SOC_SINGLE_TLV("AIF1DAC2 Noise Gate Threshold Volume", + WM8958_AIF1_DAC2_NOISE_GATE, WM8958_AIF1DAC2_NG_THR_SHIFT, + 7, 1, ng_tlv), + +SOC_SINGLE("AIF2DAC Noise Gate Switch", WM8958_AIF2_DAC_NOISE_GATE, + WM8958_AIF2DAC_NG_ENA_SHIFT, 1, 0), +SOC_ENUM("AIF2DAC Noise Gate Hold Time", wm8958_aif2dac_ng_hold), +SOC_SINGLE_TLV("AIF2DAC Noise Gate Threshold Volume", + WM8958_AIF2_DAC_NOISE_GATE, WM8958_AIF2DAC_NG_THR_SHIFT, + 7, 1, ng_tlv), +}; + +static const struct snd_kcontrol_new wm1811_snd_controls[] = { +SOC_SINGLE_TLV("MIXINL IN1LP Boost Volume", WM8994_INPUT_MIXER_1, 7, 1, 0, + mixin_boost_tlv), +SOC_SINGLE_TLV("MIXINL IN1RP Boost Volume", WM8994_INPUT_MIXER_1, 8, 1, 0, + mixin_boost_tlv), }; static int clk_sys_event(struct snd_soc_dapm_widget *w, @@ -681,6 +725,97 @@ static int clk_sys_event(struct snd_soc_dapm_widget *w, return 0; } +static void vmid_reference(struct snd_soc_codec *codec) +{ + struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec); + + wm8994->vmid_refcount++; + + dev_dbg(codec->dev, "Referencing VMID, refcount is now %d\n", + wm8994->vmid_refcount); + + if (wm8994->vmid_refcount == 1) { + /* Startup bias, VMID ramp & buffer */ + snd_soc_update_bits(codec, WM8994_ANTIPOP_2, + WM8994_STARTUP_BIAS_ENA | + WM8994_VMID_BUF_ENA | + WM8994_VMID_RAMP_MASK, + WM8994_STARTUP_BIAS_ENA | + WM8994_VMID_BUF_ENA | + (0x11 << WM8994_VMID_RAMP_SHIFT)); + + /* Main bias enable, VMID=2x40k */ + snd_soc_update_bits(codec, WM8994_POWER_MANAGEMENT_1, + WM8994_BIAS_ENA | + WM8994_VMID_SEL_MASK, + WM8994_BIAS_ENA | 0x2); + + msleep(20); + } +} + +static void vmid_dereference(struct snd_soc_codec *codec) +{ + struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec); + + wm8994->vmid_refcount--; + + dev_dbg(codec->dev, "Dereferencing VMID, refcount is now %d\n", + wm8994->vmid_refcount); + + if (wm8994->vmid_refcount == 0) { + /* Switch over to startup biases */ + snd_soc_update_bits(codec, WM8994_ANTIPOP_2, + WM8994_BIAS_SRC | + WM8994_STARTUP_BIAS_ENA | + WM8994_VMID_BUF_ENA | + WM8994_VMID_RAMP_MASK, + WM8994_BIAS_SRC | + WM8994_STARTUP_BIAS_ENA | + WM8994_VMID_BUF_ENA | + (1 << WM8994_VMID_RAMP_SHIFT)); + + /* Disable main biases */ + snd_soc_update_bits(codec, WM8994_POWER_MANAGEMENT_1, + WM8994_BIAS_ENA | + WM8994_VMID_SEL_MASK, 0); + + /* Discharge line */ + snd_soc_update_bits(codec, WM8994_ANTIPOP_1, + WM8994_LINEOUT1_DISCH | + WM8994_LINEOUT2_DISCH, + WM8994_LINEOUT1_DISCH | + WM8994_LINEOUT2_DISCH); + + msleep(5); + + /* Switch off startup biases */ + snd_soc_update_bits(codec, WM8994_ANTIPOP_2, + WM8994_BIAS_SRC | + WM8994_STARTUP_BIAS_ENA | + WM8994_VMID_BUF_ENA | + WM8994_VMID_RAMP_MASK, 0); + } +} + +static int vmid_event(struct snd_soc_dapm_widget *w, + struct snd_kcontrol *kcontrol, int event) +{ + struct snd_soc_codec *codec = w->codec; + + switch (event) { + case SND_SOC_DAPM_PRE_PMU: + vmid_reference(codec); + break; + + case SND_SOC_DAPM_POST_PMD: + vmid_dereference(codec); + break; + } + + return 0; +} + static void wm8994_update_class_w(struct snd_soc_codec *codec) { struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec); @@ -1208,6 +1343,8 @@ SND_SOC_DAPM_INPUT("Clock"), SND_SOC_DAPM_SUPPLY_S("MICBIAS Supply", 1, SND_SOC_NOPM, 0, 0, micbias_ev, SND_SOC_DAPM_PRE_PMU), +SND_SOC_DAPM_SUPPLY("VMID", SND_SOC_NOPM, 0, 0, vmid_event, + SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD), SND_SOC_DAPM_SUPPLY("CLK_SYS", SND_SOC_NOPM, 0, 0, clk_sys_event, SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD), @@ -1282,7 +1419,7 @@ SND_SOC_DAPM_MUX("AIF2DAC Mux", SND_SOC_NOPM, 0, 0, &aif2dac_mux), SND_SOC_DAPM_MUX("AIF2ADC Mux", SND_SOC_NOPM, 0, 0, &aif2adc_mux), SND_SOC_DAPM_AIF_IN("AIF3DACDAT", "AIF3 Playback", 0, SND_SOC_NOPM, 0, 0), -SND_SOC_DAPM_AIF_IN("AIF3ADCDAT", "AIF3 Capture", 0, SND_SOC_NOPM, 0, 0), +SND_SOC_DAPM_AIF_OUT("AIF3ADCDAT", "AIF3 Capture", 0, SND_SOC_NOPM, 0, 0), SND_SOC_DAPM_SUPPLY("TOCLK", WM8994_CLOCKING_1, 4, 0, NULL, 0), @@ -1525,6 +1662,8 @@ static const struct snd_soc_dapm_route wm8994_revd_intercon[] = { static const struct snd_soc_dapm_route wm8994_intercon[] = { { "AIF2DACL", NULL, "AIF2DAC Mux" }, { "AIF2DACR", NULL, "AIF2DAC Mux" }, + { "MICBIAS1", NULL, "VMID" }, + { "MICBIAS2", NULL, "VMID" }, }; static const struct snd_soc_dapm_route wm8958_intercon[] = { @@ -1629,10 +1768,12 @@ static int _wm8994_set_fll(struct snd_soc_codec *codec, int id, int src, unsigned int freq_in, unsigned int freq_out) { struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec); + struct wm8994 *control = codec->control_data; int reg_offset, ret; struct fll_div fll; u16 reg, aif1, aif2; unsigned long timeout; + bool was_enabled; aif1 = snd_soc_read(codec, WM8994_AIF1_CLOCKING_1) & WM8994_AIF1CLK_ENA; @@ -1653,6 +1794,9 @@ static int _wm8994_set_fll(struct snd_soc_codec *codec, int id, int src, return -EINVAL; } + reg = snd_soc_read(codec, WM8994_FLL1_CONTROL_1 + reg_offset); + was_enabled = reg & WM8994_FLL1_ENA; + switch (src) { case 0: /* Allow no source specification when stopping */ @@ -1719,6 +1863,21 @@ static int _wm8994_set_fll(struct snd_soc_codec *codec, int id, int src, /* Enable (with fractional mode if required) */ if (freq_out) { + /* Enable VMID if we need it */ + if (!was_enabled) { + switch (control->type) { + case WM8994: + vmid_reference(codec); + break; + case WM8958: + if (wm8994->revision < 1) + vmid_reference(codec); + break; + default: + break; + } + } + if (fll.k) reg = WM8994_FLL1_ENA | WM8994_FLL1_FRAC; else @@ -1736,6 +1895,20 @@ static int _wm8994_set_fll(struct snd_soc_codec *codec, int id, int src, } else { msleep(5); } + } else { + if (was_enabled) { + switch (control->type) { + case WM8994: + vmid_dereference(codec); + break; + case WM8958: + if (wm8994->revision < 1) + vmid_dereference(codec); + break; + default: + break; + } + } } wm8994->fll[id].in = freq_in; @@ -1852,9 +2025,6 @@ static int wm8994_set_bias_level(struct snd_soc_codec *codec, break; case SND_SOC_BIAS_PREPARE: - /* VMID=2x40k */ - snd_soc_update_bits(codec, WM8994_POWER_MANAGEMENT_1, - WM8994_VMID_SEL_MASK, 0x2); break; case SND_SOC_BIAS_STANDBY: @@ -1888,6 +2058,15 @@ static int wm8994_set_bias_level(struct snd_soc_codec *codec, WM8958_CP_DISCH); } break; + + case WM1811: + if (wm8994->revision < 2) { + snd_soc_write(codec, 0x102, 0x3); + snd_soc_write(codec, 0x5d, 0x7e); + snd_soc_write(codec, 0x5e, 0x0); + snd_soc_write(codec, 0x102, 0x0); + } + break; } /* Discharge LINEOUT1 & 2 */ @@ -1896,65 +2075,13 @@ static int wm8994_set_bias_level(struct snd_soc_codec *codec, WM8994_LINEOUT2_DISCH, WM8994_LINEOUT1_DISCH | WM8994_LINEOUT2_DISCH); - - /* Startup bias, VMID ramp & buffer */ - snd_soc_update_bits(codec, WM8994_ANTIPOP_2, - WM8994_STARTUP_BIAS_ENA | - WM8994_VMID_BUF_ENA | - WM8994_VMID_RAMP_MASK, - WM8994_STARTUP_BIAS_ENA | - WM8994_VMID_BUF_ENA | - (0x11 << WM8994_VMID_RAMP_SHIFT)); - - /* Main bias enable, VMID=2x40k */ - snd_soc_update_bits(codec, WM8994_POWER_MANAGEMENT_1, - WM8994_BIAS_ENA | - WM8994_VMID_SEL_MASK, - WM8994_BIAS_ENA | 0x2); - - msleep(20); } - /* VMID=2x500k */ - snd_soc_update_bits(codec, WM8994_POWER_MANAGEMENT_1, - WM8994_VMID_SEL_MASK, 0x4); break; case SND_SOC_BIAS_OFF: if (codec->dapm.bias_level == SND_SOC_BIAS_STANDBY) { - /* Switch over to startup biases */ - snd_soc_update_bits(codec, WM8994_ANTIPOP_2, - WM8994_BIAS_SRC | - WM8994_STARTUP_BIAS_ENA | - WM8994_VMID_BUF_ENA | - WM8994_VMID_RAMP_MASK, - WM8994_BIAS_SRC | - WM8994_STARTUP_BIAS_ENA | - WM8994_VMID_BUF_ENA | - (1 << WM8994_VMID_RAMP_SHIFT)); - - /* Disable main biases */ - snd_soc_update_bits(codec, WM8994_POWER_MANAGEMENT_1, - WM8994_BIAS_ENA | - WM8994_VMID_SEL_MASK, 0); - - /* Discharge line */ - snd_soc_update_bits(codec, WM8994_ANTIPOP_1, - WM8994_LINEOUT1_DISCH | - WM8994_LINEOUT2_DISCH, - WM8994_LINEOUT1_DISCH | - WM8994_LINEOUT2_DISCH); - - msleep(5); - - /* Switch off startup biases */ - snd_soc_update_bits(codec, WM8994_ANTIPOP_2, - WM8994_BIAS_SRC | - WM8994_STARTUP_BIAS_ENA | - WM8994_VMID_BUF_ENA | - WM8994_VMID_RAMP_MASK, 0); - wm8994->cur_fw = NULL; pm_runtime_put(codec->dev); @@ -2055,10 +2182,18 @@ static int wm8994_set_dai_fmt(struct snd_soc_dai *dai, unsigned int fmt) /* The AIF2 format configuration needs to be mirrored to AIF3 * on WM8958 if it's in use so just do it all the time. */ - if (control->type == WM8958 && dai->id == 2) - snd_soc_update_bits(codec, WM8958_AIF3_CONTROL_1, - WM8994_AIF1_LRCLK_INV | - WM8958_AIF3_FMT_MASK, aif1); + switch (control->type) { + case WM1811: + case WM8958: + if (dai->id == 2) + snd_soc_update_bits(codec, WM8958_AIF3_CONTROL_1, + WM8994_AIF1_LRCLK_INV | + WM8958_AIF3_FMT_MASK, aif1); + break; + + default: + break; + } snd_soc_update_bits(codec, aif1_reg, WM8994_AIF1_BCLK_INV | WM8994_AIF1_LRCLK_INV | @@ -2100,7 +2235,6 @@ static int wm8994_hw_params(struct snd_pcm_substream *substream, struct snd_soc_dai *dai) { struct snd_soc_codec *codec = dai->codec; - struct wm8994 *control = codec->control_data; struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec); int aif1_reg; int aif2_reg; @@ -2143,14 +2277,6 @@ static int wm8994_hw_params(struct snd_pcm_substream *substream, dev_dbg(codec->dev, "AIF2 using split LRCLK\n"); } break; - case 3: - switch (control->type) { - case WM8958: - aif1_reg = WM8958_AIF3_CONTROL_1; - break; - default: - return 0; - } default: return -EINVAL; } @@ -2271,6 +2397,7 @@ static int wm8994_aif3_hw_params(struct snd_pcm_substream *substream, switch (dai->id) { case 3: switch (control->type) { + case WM1811: case WM8958: aif1_reg = WM8958_AIF3_CONTROL_1; break; @@ -2311,7 +2438,7 @@ static void wm8994_aif_shutdown(struct snd_pcm_substream *substream, rate_reg = WM8994_AIF1_RATE; break; case 2: - rate_reg = WM8994_AIF1_RATE; + rate_reg = WM8994_AIF2_RATE; break; default: break; @@ -2384,6 +2511,21 @@ static int wm8994_set_tristate(struct snd_soc_dai *codec_dai, int tristate) return snd_soc_update_bits(codec, reg, mask, val); } +static int wm8994_aif2_probe(struct snd_soc_dai *dai) +{ + struct snd_soc_codec *codec = dai->codec; + + /* Disable the pulls on the AIF if we're using it to save power. */ + snd_soc_update_bits(codec, WM8994_GPIO_3, + WM8994_GPN_PU | WM8994_GPN_PD, 0); + snd_soc_update_bits(codec, WM8994_GPIO_4, + WM8994_GPN_PU | WM8994_GPN_PD, 0); + snd_soc_update_bits(codec, WM8994_GPIO_5, + WM8994_GPN_PU | WM8994_GPN_PD, 0); + + return 0; +} + #define WM8994_RATES SNDRV_PCM_RATE_8000_96000 #define WM8994_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE |\ @@ -2451,6 +2593,7 @@ static struct snd_soc_dai_driver wm8994_dai[] = { .rates = WM8994_RATES, .formats = WM8994_FORMATS, }, + .probe = wm8994_aif2_probe, .ops = &wm8994_aif2_dai_ops, }, { @@ -2485,6 +2628,7 @@ static int wm8994_suspend(struct snd_soc_codec *codec, pm_message_t state) case WM8994: snd_soc_update_bits(codec, WM8994_MICBIAS, WM8994_MICD_ENA, 0); break; + case WM1811: case WM8958: snd_soc_update_bits(codec, WM8958_MIC_DETECT_1, WM8958_MICD_ENA, 0); @@ -2553,6 +2697,7 @@ static int wm8994_resume(struct snd_soc_codec *codec) snd_soc_update_bits(codec, WM8994_MICBIAS, WM8994_MICD_ENA, WM8994_MICD_ENA); break; + case WM1811: case WM8958: if (wm8994->jack_cb) snd_soc_update_bits(codec, WM8958_MIC_DETECT_1, @@ -2851,8 +2996,13 @@ int wm8958_mic_detect(struct snd_soc_codec *codec, struct snd_soc_jack *jack, struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec); struct wm8994 *control = codec->control_data; - if (control->type != WM8958) + switch (control->type) { + case WM1811: + case WM8958: + break; + default: return -EINVAL; + } if (jack) { if (!cb) { @@ -2880,19 +3030,34 @@ static irqreturn_t wm8958_mic_irq(int irq, void *data) { struct wm8994_priv *wm8994 = data; struct snd_soc_codec *codec = wm8994->codec; - int reg; + int reg, count; - reg = snd_soc_read(codec, WM8958_MIC_DETECT_3); - if (reg < 0) { - dev_err(codec->dev, "Failed to read mic detect status: %d\n", - reg); - return IRQ_NONE; - } + /* We may occasionally read a detection without an impedence + * range being provided - if that happens loop again. + */ + count = 10; + do { + reg = snd_soc_read(codec, WM8958_MIC_DETECT_3); + if (reg < 0) { + dev_err(codec->dev, + "Failed to read mic detect status: %d\n", + reg); + return IRQ_NONE; + } - if (!(reg & WM8958_MICD_VALID)) { - dev_dbg(codec->dev, "Mic detect data not valid\n"); - goto out; - } + if (!(reg & WM8958_MICD_VALID)) { + dev_dbg(codec->dev, "Mic detect data not valid\n"); + goto out; + } + + if (!(reg & WM8958_MICD_STS) || (reg & WM8958_MICD_LVL_MASK)) + break; + + msleep(1); + } while (count--); + + if (count == 0) + dev_warn(codec->dev, "No impedence range reported for jack\n"); #ifndef CONFIG_SND_SOC_WM8994_MODULE trace_snd_soc_jack_irq(dev_name(codec->dev)); @@ -2916,6 +3081,24 @@ static irqreturn_t wm8994_fifo_error(int irq, void *data) return IRQ_HANDLED; } +static irqreturn_t wm8994_temp_warn(int irq, void *data) +{ + struct snd_soc_codec *codec = data; + + dev_err(codec->dev, "Thermal warning\n"); + + return IRQ_HANDLED; +} + +static irqreturn_t wm8994_temp_shut(int irq, void *data) +{ + struct snd_soc_codec *codec = data; + + dev_crit(codec->dev, "Thermal shutdown\n"); + + return IRQ_HANDLED; +} + static int wm8994_codec_probe(struct snd_soc_codec *codec) { struct wm8994 *control; @@ -2972,13 +3155,14 @@ static int wm8994_codec_probe(struct snd_soc_codec *codec) switch (wm8994->revision) { case 2: case 3: - wm8994->hubs.dcs_codes = -5; + wm8994->hubs.dcs_codes_l = -5; + wm8994->hubs.dcs_codes_r = -5; wm8994->hubs.hp_startup_mode = 1; wm8994->hubs.dcs_readback_mode = 1; wm8994->hubs.series_startup = 1; break; default: - wm8994->hubs.dcs_readback_mode = 1; + wm8994->hubs.dcs_readback_mode = 2; break; } break; @@ -2987,12 +3171,34 @@ static int wm8994_codec_probe(struct snd_soc_codec *codec) wm8994->hubs.dcs_readback_mode = 1; break; + case WM1811: + wm8994->hubs.dcs_readback_mode = 2; + wm8994->hubs.no_series_update = 1; + + switch (wm8994->revision) { + case 0: + case 1: + wm8994->hubs.dcs_codes_l = -9; + wm8994->hubs.dcs_codes_r = -5; + break; + default: + break; + } + + snd_soc_update_bits(codec, WM8994_ANALOGUE_HP_1, + WM1811_HPOUT1_ATTN, WM1811_HPOUT1_ATTN); + break; + default: break; } wm8994_request_irq(codec->control_data, WM8994_IRQ_FIFOS_ERR, wm8994_fifo_error, "FIFO error", codec); + wm8994_request_irq(codec->control_data, WM8994_IRQ_TEMP_WARN, + wm8994_temp_warn, "Thermal warning", codec); + wm8994_request_irq(codec->control_data, WM8994_IRQ_TEMP_SHUT, + wm8994_temp_shut, "Thermal shutdown", codec); ret = wm8994_request_irq(codec->control_data, WM8994_IRQ_DCS_DONE, wm_hubs_dcs_done, "DC servo done", @@ -3043,6 +3249,7 @@ static int wm8994_codec_probe(struct snd_soc_codec *codec) break; case WM8958: + case WM1811: if (wm8994->micdet_irq) { ret = request_threaded_irq(wm8994->micdet_irq, NULL, wm8958_mic_irq, @@ -3205,6 +3412,19 @@ static int wm8994_codec_probe(struct snd_soc_codec *codec) ARRAY_SIZE(wm8994_dac_widgets)); } break; + + case WM1811: + snd_soc_add_controls(codec, wm8958_snd_controls, + ARRAY_SIZE(wm8958_snd_controls)); + snd_soc_dapm_new_controls(dapm, wm8958_dapm_widgets, + ARRAY_SIZE(wm8958_dapm_widgets)); + snd_soc_dapm_new_controls(dapm, wm8994_lateclk_widgets, + ARRAY_SIZE(wm8994_lateclk_widgets)); + snd_soc_dapm_new_controls(dapm, wm8994_adc_widgets, + ARRAY_SIZE(wm8994_adc_widgets)); + snd_soc_dapm_new_controls(dapm, wm8994_dac_widgets, + ARRAY_SIZE(wm8994_dac_widgets)); + break; } @@ -3241,6 +3461,12 @@ static int wm8994_codec_probe(struct snd_soc_codec *codec) wm8958_dsp2_init(codec); break; + case WM1811: + snd_soc_dapm_add_routes(dapm, wm8994_lateclk_intercon, + ARRAY_SIZE(wm8994_lateclk_intercon)); + snd_soc_dapm_add_routes(dapm, wm8958_intercon, + ARRAY_SIZE(wm8958_intercon)); + break; } return 0; @@ -3257,6 +3483,8 @@ err_irq: wm8994_free_irq(codec->control_data, WM8994_IRQ_DCS_DONE, &wm8994->hubs); wm8994_free_irq(codec->control_data, WM8994_IRQ_FIFOS_ERR, codec); + wm8994_free_irq(codec->control_data, WM8994_IRQ_TEMP_SHUT, codec); + wm8994_free_irq(codec->control_data, WM8994_IRQ_TEMP_WARN, codec); err: kfree(wm8994); return ret; @@ -3279,6 +3507,8 @@ static int wm8994_codec_remove(struct snd_soc_codec *codec) wm8994_free_irq(codec->control_data, WM8994_IRQ_DCS_DONE, &wm8994->hubs); wm8994_free_irq(codec->control_data, WM8994_IRQ_FIFOS_ERR, codec); + wm8994_free_irq(codec->control_data, WM8994_IRQ_TEMP_SHUT, codec); + wm8994_free_irq(codec->control_data, WM8994_IRQ_TEMP_WARN, codec); switch (control->type) { case WM8994: @@ -3292,6 +3522,7 @@ static int wm8994_codec_remove(struct snd_soc_codec *codec) wm8994); break; + case WM1811: case WM8958: if (wm8994->micdet_irq) free_irq(wm8994->micdet_irq, wm8994); diff --git a/sound/soc/codecs/wm8994.h b/sound/soc/codecs/wm8994.h index 1ab2266039f..f4f1355efc8 100644 --- a/sound/soc/codecs/wm8994.h +++ b/sound/soc/codecs/wm8994.h @@ -83,6 +83,8 @@ struct wm8994_priv { struct completion fll_locked[2]; bool fll_locked_irq; + int vmid_refcount; + int dac_rates[2]; int lrclk_shared[2]; diff --git a/sound/soc/codecs/wm8995.c b/sound/soc/codecs/wm8995.c index 5ad873fda81..78eeb21e669 100644 --- a/sound/soc/codecs/wm8995.c +++ b/sound/soc/codecs/wm8995.c @@ -485,7 +485,7 @@ static int configure_aif_clock(struct snd_soc_codec *codec, int aif) static int configure_clock(struct snd_soc_codec *codec) { struct wm8995_priv *wm8995; - int old, new; + int change, new; wm8995 = snd_soc_codec_get_drvdata(codec); @@ -509,15 +509,11 @@ static int configure_clock(struct snd_soc_codec *codec) else new = 0; - old = snd_soc_read(codec, WM8995_CLOCKING_1) & WM8995_SYSCLK_SRC; - - /* If there's no change then we're done. */ - if (old == new) + change = snd_soc_update_bits(codec, WM8995_CLOCKING_1, + WM8995_SYSCLK_SRC_MASK, new); + if (!change) return 0; - snd_soc_update_bits(codec, WM8995_CLOCKING_1, - WM8995_SYSCLK_SRC_MASK, new); - snd_soc_dapm_sync(&codec->dapm); return 0; @@ -1573,11 +1569,16 @@ static int wm8995_resume(struct snd_soc_codec *codec) static int wm8995_remove(struct snd_soc_codec *codec) { struct wm8995_priv *wm8995; - struct i2c_client *i2c; + int i; - i2c = container_of(codec->dev, struct i2c_client, dev); wm8995 = snd_soc_codec_get_drvdata(codec); wm8995_set_bias_level(codec, SND_SOC_BIAS_OFF); + + for (i = 0; i < ARRAY_SIZE(wm8995->supplies); ++i) + regulator_unregister_notifier(wm8995->supplies[i].consumer, + &wm8995->disable_nb[i]); + + regulator_bulk_free(ARRAY_SIZE(wm8995->supplies), wm8995->supplies); return 0; } @@ -1642,6 +1643,7 @@ static int wm8995_probe(struct snd_soc_codec *codec) if (ret != 0x8995) { dev_err(codec->dev, "Invalid device ID: %#x\n", ret); + ret = -EINVAL; goto err_reg_enable; } diff --git a/sound/soc/codecs/wm8996.c b/sound/soc/codecs/wm8996.c index 0cdb9d10567..645c980d6b8 100644 --- a/sound/soc/codecs/wm8996.c +++ b/sound/soc/codecs/wm8996.c @@ -41,12 +41,11 @@ #define HPOUT2L 4 #define HPOUT2R 8 -#define WM8996_NUM_SUPPLIES 4 +#define WM8996_NUM_SUPPLIES 3 static const char *wm8996_supply_names[WM8996_NUM_SUPPLIES] = { "DBVDD", "AVDD1", "AVDD2", - "CPVDD", }; struct wm8996_priv { @@ -71,6 +70,8 @@ struct wm8996_priv { struct regulator_bulk_data supplies[WM8996_NUM_SUPPLIES]; struct notifier_block disable_nb[WM8996_NUM_SUPPLIES]; + struct regulator *cpvdd; + int bg_ena; struct wm8996_pdata pdata; @@ -112,7 +113,6 @@ static int wm8996_regulator_event_##n(struct notifier_block *nb, \ WM8996_REGULATOR_EVENT(0) WM8996_REGULATOR_EVENT(1) WM8996_REGULATOR_EVENT(2) -WM8996_REGULATOR_EVENT(3) static const u16 wm8996_reg[WM8996_MAX_REGISTER] = { [WM8996_SOFTWARE_RESET] = 0x8996, @@ -414,6 +414,7 @@ static const DECLARE_TLV_DB_SCALE(out_digital_tlv, -1200, 150, 0); static const DECLARE_TLV_DB_SCALE(out_tlv, -900, 75, 0); static const DECLARE_TLV_DB_SCALE(spk_tlv, -900, 150, 0); static const DECLARE_TLV_DB_SCALE(eq_tlv, -1200, 100, 0); +static const DECLARE_TLV_DB_SCALE(threedstereo_tlv, -1600, 183, 1); static const char *sidetone_hpf_text[] = { "2.9kHz", "1.5kHz", "735Hz", "403Hz", "196Hz", "98Hz", "49Hz" @@ -608,6 +609,14 @@ SOC_SINGLE("DAC High Performance Switch", WM8996_OVERSAMPLING, 0, 1, 0), SOC_SINGLE("DAC Soft Mute Switch", WM8996_DAC_SOFTMUTE, 1, 1, 0), SOC_SINGLE("DAC Slow Soft Mute Switch", WM8996_DAC_SOFTMUTE, 0, 1, 0), +SOC_SINGLE("DSP1 3D Stereo Switch", WM8996_DSP1_RX_FILTERS_2, 8, 1, 0), +SOC_SINGLE("DSP2 3D Stereo Switch", WM8996_DSP2_RX_FILTERS_2, 8, 1, 0), + +SOC_SINGLE_TLV("DSP1 3D Stereo Volume", WM8996_DSP1_RX_FILTERS_2, 10, 15, + 0, threedstereo_tlv), +SOC_SINGLE_TLV("DSP2 3D Stereo Volume", WM8996_DSP2_RX_FILTERS_2, 10, 15, + 0, threedstereo_tlv), + SOC_DOUBLE_TLV("Digital Output 1 Volume", WM8996_DAC1_HPOUT1_VOLUME, 0, 4, 8, 0, out_digital_tlv), SOC_DOUBLE_TLV("Digital Output 2 Volume", WM8996_DAC2_HPOUT2_VOLUME, 0, 4, @@ -632,6 +641,14 @@ SOC_DOUBLE_R("Speaker ZC Switch", WM8996_LEFT_PDM_SPEAKER, SOC_SINGLE("DSP1 EQ Switch", WM8996_DSP1_RX_EQ_GAINS_1, 0, 1, 0), SOC_SINGLE("DSP2 EQ Switch", WM8996_DSP2_RX_EQ_GAINS_1, 0, 1, 0), + +SOC_SINGLE("DSP1 DRC TXL Switch", WM8996_DSP1_DRC_1, 0, 1, 0), +SOC_SINGLE("DSP1 DRC TXR Switch", WM8996_DSP1_DRC_1, 1, 1, 0), +SOC_SINGLE("DSP1 DRC RX Switch", WM8996_DSP1_DRC_1, 2, 1, 0), + +SOC_SINGLE("DSP2 DRC TXL Switch", WM8996_DSP2_DRC_1, 0, 1, 0), +SOC_SINGLE("DSP2 DRC TXR Switch", WM8996_DSP2_DRC_1, 1, 1, 0), +SOC_SINGLE("DSP2 DRC RX Switch", WM8996_DSP2_DRC_1, 2, 1, 0), }; static const struct snd_kcontrol_new wm8996_eq_controls[] = { @@ -658,19 +675,75 @@ SOC_SINGLE_TLV("DSP2 EQ B5 Volume", WM8996_DSP2_RX_EQ_GAINS_2, 6, 31, 0, eq_tlv), }; +static void wm8996_bg_enable(struct snd_soc_codec *codec) +{ + struct wm8996_priv *wm8996 = snd_soc_codec_get_drvdata(codec); + + wm8996->bg_ena++; + if (wm8996->bg_ena == 1) { + snd_soc_update_bits(codec, WM8996_POWER_MANAGEMENT_1, + WM8996_BG_ENA, WM8996_BG_ENA); + msleep(2); + } +} + +static void wm8996_bg_disable(struct snd_soc_codec *codec) +{ + struct wm8996_priv *wm8996 = snd_soc_codec_get_drvdata(codec); + + wm8996->bg_ena--; + if (!wm8996->bg_ena) + snd_soc_update_bits(codec, WM8996_POWER_MANAGEMENT_1, + WM8996_BG_ENA, 0); +} + +static int bg_event(struct snd_soc_dapm_widget *w, + struct snd_kcontrol *kcontrol, int event) +{ + struct snd_soc_codec *codec = w->codec; + int ret = 0; + + switch (event) { + case SND_SOC_DAPM_PRE_PMU: + wm8996_bg_enable(codec); + break; + case SND_SOC_DAPM_POST_PMD: + wm8996_bg_disable(codec); + break; + default: + BUG(); + ret = -EINVAL; + } + + return ret; +} + static int cp_event(struct snd_soc_dapm_widget *w, struct snd_kcontrol *kcontrol, int event) { + struct snd_soc_codec *codec = w->codec; + struct wm8996_priv *wm8996 = snd_soc_codec_get_drvdata(codec); + int ret = 0; + switch (event) { + case SND_SOC_DAPM_PRE_PMU: + ret = regulator_enable(wm8996->cpvdd); + if (ret != 0) + dev_err(codec->dev, "Failed to enable CPVDD: %d\n", + ret); + break; case SND_SOC_DAPM_POST_PMU: msleep(5); break; + case SND_SOC_DAPM_POST_PMD: + regulator_disable_deferred(wm8996->cpvdd, 20); + break; default: BUG(); - return -EINVAL; + ret = -EINVAL; } - return 0; + return ret; } static int rmv_short_event(struct snd_soc_dapm_widget *w, @@ -698,7 +771,7 @@ static void wait_for_dc_servo(struct snd_soc_codec *codec, u16 mask) { struct i2c_client *i2c = to_i2c_client(codec->dev); struct wm8996_priv *wm8996 = snd_soc_codec_get_drvdata(codec); - int i, ret; + int ret; unsigned long timeout = 200; snd_soc_write(codec, WM8996_DC_SERVO_2, mask); @@ -713,15 +786,12 @@ static void wait_for_dc_servo(struct snd_soc_codec *codec, u16 mask) } else { msleep(1); - if (--i) { - timeout = 0; - break; - } + timeout--; } ret = snd_soc_read(codec, WM8996_DC_SERVO_2); dev_dbg(codec->dev, "DC servo state: %x\n", ret); - } while (ret & mask); + } while (timeout && ret & mask); if (timeout == 0) dev_err(codec->dev, "DC servo timed out for %x\n", mask); @@ -979,9 +1049,12 @@ SND_SOC_DAPM_SUPPLY_S("SYSCLK", 1, WM8996_AIF_CLOCKING_1, 0, 0, NULL, 0), SND_SOC_DAPM_SUPPLY_S("SYSDSPCLK", 2, WM8996_CLOCKING_1, 1, 0, NULL, 0), SND_SOC_DAPM_SUPPLY_S("AIFCLK", 2, WM8996_CLOCKING_1, 2, 0, NULL, 0), SND_SOC_DAPM_SUPPLY_S("Charge Pump", 2, WM8996_CHARGE_PUMP_1, 15, 0, cp_event, - SND_SOC_DAPM_POST_PMU), - + SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD), +SND_SOC_DAPM_SUPPLY("Bandgap", SND_SOC_NOPM, 0, 0, bg_event, + SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD), SND_SOC_DAPM_SUPPLY("LDO2", WM8996_POWER_MANAGEMENT_2, 1, 0, NULL, 0), +SND_SOC_DAPM_SUPPLY("MICB1 Audio", WM8996_MICBIAS_1, 4, 1, NULL, 0), +SND_SOC_DAPM_SUPPLY("MICB2 Audio", WM8996_MICBIAS_2, 4, 1, NULL, 0), SND_SOC_DAPM_MICBIAS("MICB2", WM8996_POWER_MANAGEMENT_1, 9, 0), SND_SOC_DAPM_MICBIAS("MICB1", WM8996_POWER_MANAGEMENT_1, 8, 0), @@ -1035,14 +1108,14 @@ SND_SOC_DAPM_DAC("DAC2R", NULL, WM8996_POWER_MANAGEMENT_5, 2, 0), SND_SOC_DAPM_DAC("DAC1L", NULL, WM8996_POWER_MANAGEMENT_5, 1, 0), SND_SOC_DAPM_DAC("DAC1R", NULL, WM8996_POWER_MANAGEMENT_5, 0, 0), -SND_SOC_DAPM_AIF_IN("AIF2RX1", "AIF2 Playback", 1, +SND_SOC_DAPM_AIF_IN("AIF2RX1", "AIF2 Playback", 0, WM8996_POWER_MANAGEMENT_4, 9, 0), -SND_SOC_DAPM_AIF_IN("AIF2RX0", "AIF2 Playback", 2, +SND_SOC_DAPM_AIF_IN("AIF2RX0", "AIF2 Playback", 1, WM8996_POWER_MANAGEMENT_4, 8, 0), -SND_SOC_DAPM_AIF_IN("AIF2TX1", "AIF2 Capture", 1, +SND_SOC_DAPM_AIF_OUT("AIF2TX1", "AIF2 Capture", 0, WM8996_POWER_MANAGEMENT_6, 9, 0), -SND_SOC_DAPM_AIF_IN("AIF2TX0", "AIF2 Capture", 2, +SND_SOC_DAPM_AIF_OUT("AIF2TX0", "AIF2 Capture", 1, WM8996_POWER_MANAGEMENT_6, 8, 0), SND_SOC_DAPM_AIF_IN("AIF1RX5", "AIF1 Playback", 5, @@ -1137,17 +1210,23 @@ static const struct snd_soc_dapm_route wm8996_dapm_routes[] = { { "Charge Pump", NULL, "SYSCLK" }, { "MICB1", NULL, "LDO2" }, + { "MICB1", NULL, "MICB1 Audio" }, + { "MICB1", NULL, "Bandgap" }, { "MICB2", NULL, "LDO2" }, + { "MICB2", NULL, "MICB2 Audio" }, + { "MICB2", NULL, "Bandgap" }, { "IN1L PGA", NULL, "IN2LN" }, { "IN1L PGA", NULL, "IN2LP" }, { "IN1L PGA", NULL, "IN1LN" }, { "IN1L PGA", NULL, "IN1LP" }, + { "IN1L PGA", NULL, "Bandgap" }, { "IN1R PGA", NULL, "IN2RN" }, { "IN1R PGA", NULL, "IN2RP" }, { "IN1R PGA", NULL, "IN1RN" }, { "IN1R PGA", NULL, "IN1RP" }, + { "IN1R PGA", NULL, "Bandgap" }, { "ADCL", NULL, "IN1L PGA" }, @@ -1281,6 +1360,7 @@ static const struct snd_soc_dapm_route wm8996_dapm_routes[] = { { "DAC2R", NULL, "DAC2R Mixer" }, { "HPOUT2L PGA", NULL, "Charge Pump" }, + { "HPOUT2L PGA", NULL, "Bandgap" }, { "HPOUT2L PGA", NULL, "DAC2L" }, { "HPOUT2L_DLY", NULL, "HPOUT2L PGA" }, { "HPOUT2L_DCS", NULL, "HPOUT2L_DLY" }, @@ -1288,6 +1368,7 @@ static const struct snd_soc_dapm_route wm8996_dapm_routes[] = { { "HPOUT2L_RMV_SHORT", NULL, "HPOUT2L_OUTP" }, { "HPOUT2R PGA", NULL, "Charge Pump" }, + { "HPOUT2R PGA", NULL, "Bandgap" }, { "HPOUT2R PGA", NULL, "DAC2R" }, { "HPOUT2R_DLY", NULL, "HPOUT2R PGA" }, { "HPOUT2R_DCS", NULL, "HPOUT2R_DLY" }, @@ -1295,6 +1376,7 @@ static const struct snd_soc_dapm_route wm8996_dapm_routes[] = { { "HPOUT2R_RMV_SHORT", NULL, "HPOUT2R_OUTP" }, { "HPOUT1L PGA", NULL, "Charge Pump" }, + { "HPOUT1L PGA", NULL, "Bandgap" }, { "HPOUT1L PGA", NULL, "DAC1L" }, { "HPOUT1L_DLY", NULL, "HPOUT1L PGA" }, { "HPOUT1L_DCS", NULL, "HPOUT1L_DLY" }, @@ -1302,6 +1384,7 @@ static const struct snd_soc_dapm_route wm8996_dapm_routes[] = { { "HPOUT1L_RMV_SHORT", NULL, "HPOUT1L_OUTP" }, { "HPOUT1R PGA", NULL, "Charge Pump" }, + { "HPOUT1R PGA", NULL, "Bandgap" }, { "HPOUT1R PGA", NULL, "DAC1R" }, { "HPOUT1R_DLY", NULL, "HPOUT1R PGA" }, { "HPOUT1R_DCS", NULL, "HPOUT1R_DLY" }, @@ -1620,14 +1703,7 @@ static int wm8996_set_bias_level(struct snd_soc_codec *codec, switch (level) { case SND_SOC_BIAS_ON: - break; - case SND_SOC_BIAS_PREPARE: - if (codec->dapm.bias_level == SND_SOC_BIAS_STANDBY) { - snd_soc_update_bits(codec, WM8996_POWER_MANAGEMENT_1, - WM8996_BG_ENA, WM8996_BG_ENA); - msleep(2); - } break; case SND_SOC_BIAS_STANDBY: @@ -1650,9 +1726,6 @@ static int wm8996_set_bias_level(struct snd_soc_codec *codec, codec->cache_only = false; snd_soc_cache_sync(codec); } - - snd_soc_update_bits(codec, WM8996_POWER_MANAGEMENT_1, - WM8996_BG_ENA, 0); break; case SND_SOC_BIAS_OFF: @@ -1847,7 +1920,7 @@ static int wm8996_hw_params(struct snd_pcm_substream *substream, snd_soc_update_bits(codec, lrclk_reg, WM8996_AIF1RX_RATE_MASK, lrclk); snd_soc_update_bits(codec, WM8996_AIF_CLOCKING_2, - WM8996_DSP1_DIV_SHIFT << dsp_shift, dsp); + WM8996_DSP1_DIV_MASK << dsp_shift, dsp); return 0; } @@ -2041,7 +2114,7 @@ static int wm8996_set_fll(struct snd_soc_codec *codec, int fll_id, int source, struct i2c_client *i2c = to_i2c_client(codec->dev); struct _fll_div fll_div; unsigned long timeout; - int ret, reg; + int ret, reg, retry; /* Any change? */ if (source == wm8996->fll_src && Fref == wm8996->fll_fref && @@ -2057,6 +2130,8 @@ static int wm8996_set_fll(struct snd_soc_codec *codec, int fll_id, int source, snd_soc_update_bits(codec, WM8996_FLL_CONTROL_1, WM8996_FLL_ENA, 0); + wm8996_bg_disable(codec); + return 0; } @@ -2111,6 +2186,11 @@ static int wm8996_set_fll(struct snd_soc_codec *codec, int fll_id, int source, snd_soc_write(codec, WM8996_FLL_EFS_1, fll_div.lambda); + /* Enable the bandgap if it's not already enabled */ + ret = snd_soc_read(codec, WM8996_FLL_CONTROL_1); + if (!(ret & WM8996_FLL_ENA)) + wm8996_bg_enable(codec); + /* Clear any pending completions (eg, from failed startups) */ try_wait_for_completion(&wm8996->fll_lock); @@ -2128,17 +2208,29 @@ static int wm8996_set_fll(struct snd_soc_codec *codec, int fll_id, int source, else timeout = msecs_to_jiffies(2); - /* Allow substantially longer if we've actually got the IRQ */ + /* Allow substantially longer if we've actually got the IRQ, poll + * at a slightly higher rate if we don't. + */ if (i2c->irq) - timeout *= 1000; + timeout *= 10; + else + timeout /= 2; - ret = wait_for_completion_timeout(&wm8996->fll_lock, timeout); + for (retry = 0; retry < 10; retry++) { + ret = wait_for_completion_timeout(&wm8996->fll_lock, + timeout); + if (ret != 0) { + WARN_ON(!i2c->irq); + break; + } - if (ret == 0 && i2c->irq) { + ret = snd_soc_read(codec, WM8996_INTERRUPT_RAW_STATUS_2); + if (ret & WM8996_FLL_LOCK_STS) + break; + } + if (retry == 10) { dev_err(codec->dev, "Timed out waiting for FLL\n"); ret = -ETIMEDOUT; - } else { - ret = 0; } dev_dbg(codec->dev, "FLL configured for %dHz->%dHz\n", Fref, Fout); @@ -2297,12 +2389,94 @@ int wm8996_detect(struct snd_soc_codec *codec, struct snd_soc_jack *jack, /* Enable interrupts and we're off */ snd_soc_update_bits(codec, WM8996_INTERRUPT_STATUS_2_MASK, - WM8996_IM_MICD_EINT, 0); + WM8996_IM_MICD_EINT | WM8996_HP_DONE_EINT, 0); return 0; } EXPORT_SYMBOL_GPL(wm8996_detect); +static void wm8996_hpdet_irq(struct snd_soc_codec *codec) +{ + struct wm8996_priv *wm8996 = snd_soc_codec_get_drvdata(codec); + int val, reg, report; + + /* Assume headphone in error conditions; we need to report + * something or we stall our state machine. + */ + report = SND_JACK_HEADPHONE; + + reg = snd_soc_read(codec, WM8996_HEADPHONE_DETECT_2); + if (reg < 0) { + dev_err(codec->dev, "Failed to read HPDET status\n"); + goto out; + } + + if (!(reg & WM8996_HP_DONE)) { + dev_err(codec->dev, "Got HPDET IRQ but HPDET is busy\n"); + goto out; + } + + val = reg & WM8996_HP_LVL_MASK; + + dev_dbg(codec->dev, "HPDET measured %d ohms\n", val); + + /* If we've got high enough impedence then report as line, + * otherwise assume headphone. + */ + if (val >= 126) + report = SND_JACK_LINEOUT; + else + report = SND_JACK_HEADPHONE; + +out: + if (wm8996->jack_mic) + report |= SND_JACK_MICROPHONE; + + snd_soc_jack_report(wm8996->jack, report, + SND_JACK_LINEOUT | SND_JACK_HEADSET); + + wm8996->detecting = false; + + /* If the output isn't running re-clamp it */ + if (!(snd_soc_read(codec, WM8996_POWER_MANAGEMENT_1) & + (WM8996_HPOUT1L_ENA | WM8996_HPOUT1R_RMV_SHORT))) + snd_soc_update_bits(codec, WM8996_ANALOGUE_HP_1, + WM8996_HPOUT1L_RMV_SHORT | + WM8996_HPOUT1R_RMV_SHORT, 0); + + /* Go back to looking at the microphone */ + snd_soc_update_bits(codec, WM8996_ACCESSORY_DETECT_MODE_1, + WM8996_JD_MODE_MASK, 0); + snd_soc_update_bits(codec, WM8996_MIC_DETECT_1, WM8996_MICD_ENA, + WM8996_MICD_ENA); + + snd_soc_dapm_disable_pin(&codec->dapm, "Bandgap"); + snd_soc_dapm_sync(&codec->dapm); +} + +static void wm8996_hpdet_start(struct snd_soc_codec *codec) +{ + /* Unclamp the output, we can't measure while we're shorting it */ + snd_soc_update_bits(codec, WM8996_ANALOGUE_HP_1, + WM8996_HPOUT1L_RMV_SHORT | + WM8996_HPOUT1R_RMV_SHORT, + WM8996_HPOUT1L_RMV_SHORT | + WM8996_HPOUT1R_RMV_SHORT); + + /* We need bandgap for HPDET */ + snd_soc_dapm_force_enable_pin(&codec->dapm, "Bandgap"); + snd_soc_dapm_sync(&codec->dapm); + + /* Go into headphone detect left mode */ + snd_soc_update_bits(codec, WM8996_MIC_DETECT_1, WM8996_MICD_ENA, 0); + snd_soc_update_bits(codec, WM8996_ACCESSORY_DETECT_MODE_1, + WM8996_JD_MODE_MASK, 1); + + /* Trigger a measurement */ + snd_soc_update_bits(codec, WM8996_HEADPHONE_DETECT_1, + WM8996_HP_POLL, WM8996_HP_POLL); +} + static void wm8996_micd(struct snd_soc_codec *codec) { struct wm8996_priv *wm8996 = snd_soc_codec_get_drvdata(codec); @@ -2323,28 +2497,36 @@ static void wm8996_micd(struct snd_soc_codec *codec) wm8996->jack_mic = false; wm8996->detecting = true; snd_soc_jack_report(wm8996->jack, 0, - SND_JACK_HEADSET | SND_JACK_BTN_0); + SND_JACK_LINEOUT | SND_JACK_HEADSET | + SND_JACK_BTN_0); + snd_soc_update_bits(codec, WM8996_MIC_DETECT_1, WM8996_MICD_RATE_MASK, WM8996_MICD_RATE_MASK); return; } - /* If the measurement is very high we've got a microphone but - * do a little debounce to account for mechanical issues. + /* If the measurement is very high we've got a microphone, + * either we just detected one or if we already reported then + * we've got a button release event. */ if (val & 0x400) { - dev_dbg(codec->dev, "Microphone detected\n"); - snd_soc_jack_report(wm8996->jack, SND_JACK_HEADSET, - SND_JACK_HEADSET | SND_JACK_BTN_0); - wm8996->jack_mic = true; - wm8996->detecting = false; - - /* Increase poll rate to give better responsiveness - * for buttons */ - snd_soc_update_bits(codec, WM8996_MIC_DETECT_1, - WM8996_MICD_RATE_MASK, - 5 << WM8996_MICD_RATE_SHIFT); + if (wm8996->detecting) { + dev_dbg(codec->dev, "Microphone detected\n"); + wm8996->jack_mic = true; + wm8996_hpdet_start(codec); + + /* Increase poll rate to give better responsiveness + * for buttons */ + snd_soc_update_bits(codec, WM8996_MIC_DETECT_1, + WM8996_MICD_RATE_MASK, + 5 << WM8996_MICD_RATE_SHIFT); + } else { + dev_dbg(codec->dev, "Mic button up\n"); + snd_soc_jack_report(wm8996->jack, 0, SND_JACK_BTN_0); + } + + return; } /* If we detected a lower impedence during initial startup @@ -2376,15 +2558,11 @@ static void wm8996_micd(struct snd_soc_codec *codec) if (val & 0x3fc) { if (wm8996->jack_mic) { dev_dbg(codec->dev, "Mic button detected\n"); - snd_soc_jack_report(wm8996->jack, - SND_JACK_HEADSET | SND_JACK_BTN_0, - SND_JACK_HEADSET | SND_JACK_BTN_0); - } else { - dev_dbg(codec->dev, "Headphone detected\n"); - snd_soc_jack_report(wm8996->jack, - SND_JACK_HEADPHONE, - SND_JACK_HEADSET | + snd_soc_jack_report(wm8996->jack, SND_JACK_BTN_0, SND_JACK_BTN_0); + } else if (wm8996->detecting) { + dev_dbg(codec->dev, "Headphone detected\n"); + wm8996_hpdet_start(codec); /* Increase the detection rate a bit for * responsiveness. @@ -2392,8 +2570,6 @@ static void wm8996_micd(struct snd_soc_codec *codec) snd_soc_update_bits(codec, WM8996_MIC_DETECT_1, WM8996_MICD_RATE_MASK, 7 << WM8996_MICD_RATE_SHIFT); - - wm8996->detecting = false; } } } @@ -2412,6 +2588,9 @@ static irqreturn_t wm8996_irq(int irq, void *data) } irq_val &= ~snd_soc_read(codec, WM8996_INTERRUPT_STATUS_2_MASK); + if (!irq_val) + return IRQ_NONE; + snd_soc_write(codec, WM8996_INTERRUPT_STATUS_2, irq_val); if (irq_val & (WM8996_DCS_DONE_01_EINT | WM8996_DCS_DONE_23_EINT)) { @@ -2430,10 +2609,10 @@ static irqreturn_t wm8996_irq(int irq, void *data) if (irq_val & WM8996_MICD_EINT) wm8996_micd(codec); - if (irq_val) - return IRQ_HANDLED; - else - return IRQ_NONE; + if (irq_val & WM8996_HP_DONE_EINT) + wm8996_hpdet_irq(codec); + + return IRQ_HANDLED; } static irqreturn_t wm8996_edge_irq(int irq, void *data) @@ -2527,7 +2706,6 @@ static int wm8996_probe(struct snd_soc_codec *codec) init_completion(&wm8996->fll_lock); dapm->idle_bias_off = true; - dapm->bias_level = SND_SOC_BIAS_OFF; ret = snd_soc_codec_set_cache_io(codec, 16, 16, SND_SOC_I2C); if (ret != 0) { @@ -2548,7 +2726,13 @@ static int wm8996_probe(struct snd_soc_codec *codec) wm8996->disable_nb[0].notifier_call = wm8996_regulator_event_0; wm8996->disable_nb[1].notifier_call = wm8996_regulator_event_1; wm8996->disable_nb[2].notifier_call = wm8996_regulator_event_2; - wm8996->disable_nb[3].notifier_call = wm8996_regulator_event_3; + + wm8996->cpvdd = regulator_get(&i2c->dev, "CPVDD"); + if (IS_ERR(wm8996->cpvdd)) { + ret = PTR_ERR(wm8996->cpvdd); + dev_err(&i2c->dev, "Failed to get CPVDD: %d\n", ret); + goto err_get; + } /* This should really be moved into the regulator core */ for (i = 0; i < ARRAY_SIZE(wm8996->supplies); i++) { @@ -2565,7 +2749,7 @@ static int wm8996_probe(struct snd_soc_codec *codec) wm8996->supplies); if (ret != 0) { dev_err(codec->dev, "Failed to enable supplies: %d\n", ret); - goto err_get; + goto err_cpvdd; } if (wm8996->pdata.ldo_ena >= 0) { @@ -2808,6 +2992,8 @@ err_enable: gpio_set_value_cansleep(wm8996->pdata.ldo_ena, 0); regulator_bulk_disable(ARRAY_SIZE(wm8996->supplies), wm8996->supplies); +err_cpvdd: + regulator_put(wm8996->cpvdd); err_get: regulator_bulk_free(ARRAY_SIZE(wm8996->supplies), wm8996->supplies); err: @@ -2831,6 +3017,7 @@ static int wm8996_remove(struct snd_soc_codec *codec) for (i = 0; i < ARRAY_SIZE(wm8996->supplies); i++) regulator_unregister_notifier(wm8996->supplies[i].consumer, &wm8996->disable_nb[i]); + regulator_put(wm8996->cpvdd); regulator_bulk_free(ARRAY_SIZE(wm8996->supplies), wm8996->supplies); return 0; diff --git a/sound/soc/codecs/wm9081.c b/sound/soc/codecs/wm9081.c index a4691321f9b..3cd35a02c28 100644 --- a/sound/soc/codecs/wm9081.c +++ b/sound/soc/codecs/wm9081.c @@ -157,7 +157,6 @@ static struct { struct wm9081_priv { enum snd_soc_control_type control_type; - void *control_data; int sysclk_source; int mclk_rate; int sysclk_rate; @@ -174,6 +173,7 @@ static int wm9081_volatile_register(struct snd_soc_codec *codec, unsigned int re { switch (reg) { case WM9081_SOFTWARE_RESET: + case WM9081_INTERRUPT_STATUS: return 1; default: return 0; @@ -820,7 +820,7 @@ static int wm9081_set_bias_level(struct snd_soc_codec *codec, /* VMID 2*240k */ reg = snd_soc_read(codec, WM9081_BIAS_CONTROL_1); reg &= ~WM9081_VMID_SEL_MASK; - reg |= 0x40; + reg |= 0x04; snd_soc_write(codec, WM9081_VMID_CONTROL, reg); /* Standby bias current on */ @@ -1120,8 +1120,8 @@ static int wm9081_digital_mute(struct snd_soc_dai *codec_dai, int mute) return 0; } -static int wm9081_set_sysclk(struct snd_soc_codec *codec, - int clk_id, unsigned int freq, int dir) +static int wm9081_set_sysclk(struct snd_soc_codec *codec, int clk_id, + int source, unsigned int freq, int dir) { struct wm9081_priv *wm9081 = snd_soc_codec_get_drvdata(codec); @@ -1213,7 +1213,6 @@ static int wm9081_probe(struct snd_soc_codec *codec) int ret; u16 reg; - codec->control_data = wm9081->control_data; ret = snd_soc_codec_set_cache_io(codec, 8, 16, wm9081->control_type); if (ret != 0) { dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret); @@ -1250,8 +1249,6 @@ static int wm9081_probe(struct snd_soc_codec *codec) snd_soc_write(codec, WM9081_ANALOGUE_SPEAKER_PGA, reg | WM9081_SPKPGAZC); - snd_soc_add_controls(codec, wm9081_snd_controls, - ARRAY_SIZE(wm9081_snd_controls)); if (!wm9081->pdata.num_retune_configs) { dev_dbg(codec->dev, "No ReTune Mobile data, using normal EQ\n"); @@ -1311,6 +1308,8 @@ static struct snd_soc_codec_driver soc_codec_dev_wm9081 = { .reg_cache_default = wm9081_reg_defaults, .volatile_register = wm9081_volatile_register, + .controls = wm9081_snd_controls, + .num_controls = ARRAY_SIZE(wm9081_snd_controls), .dapm_widgets = wm9081_dapm_widgets, .num_dapm_widgets = ARRAY_SIZE(wm9081_dapm_widgets), .dapm_routes = wm9081_audio_paths, @@ -1330,7 +1329,6 @@ static __devinit int wm9081_i2c_probe(struct i2c_client *i2c, i2c_set_clientdata(i2c, wm9081); wm9081->control_type = SND_SOC_I2C; - wm9081->control_data = i2c; if (dev_get_platdata(&i2c->dev)) memcpy(&wm9081->pdata, dev_get_platdata(&i2c->dev), diff --git a/sound/soc/codecs/wm9090.c b/sound/soc/codecs/wm9090.c index 4de12203e61..2b5252c9e37 100644 --- a/sound/soc/codecs/wm9090.c +++ b/sound/soc/codecs/wm9090.c @@ -139,9 +139,7 @@ static const u16 wm9090_reg_defaults[] = { /* This struct is used to save the context */ struct wm9090_priv { - struct mutex mutex; struct wm9090_platform_data pdata; - void *control_data; }; static int wm9090_volatile(struct snd_soc_codec *codec, unsigned int reg) @@ -550,10 +548,8 @@ static int wm9090_set_bias_level(struct snd_soc_codec *codec, static int wm9090_probe(struct snd_soc_codec *codec) { - struct wm9090_priv *wm9090 = snd_soc_codec_get_drvdata(codec); int ret; - codec->control_data = wm9090->control_data; ret = snd_soc_codec_set_cache_io(codec, 8, 16, SND_SOC_I2C); if (ret != 0) { dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret); @@ -662,8 +658,6 @@ static int wm9090_i2c_probe(struct i2c_client *i2c, sizeof(wm9090->pdata)); i2c_set_clientdata(i2c, wm9090); - wm9090->control_data = i2c; - mutex_init(&wm9090->mutex); ret = snd_soc_register_codec(&i2c->dev, &soc_codec_dev_wm9090, NULL, 0); @@ -684,6 +678,7 @@ static int __devexit wm9090_i2c_remove(struct i2c_client *i2c) static const struct i2c_device_id wm9090_id[] = { { "wm9090", 0 }, + { "wm9093", 0 }, { } }; MODULE_DEVICE_TABLE(i2c, wm9090_id); diff --git a/sound/soc/codecs/wm_hubs.c b/sound/soc/codecs/wm_hubs.c index e763c54c55d..84f33d4ea2c 100644 --- a/sound/soc/codecs/wm_hubs.c +++ b/sound/soc/codecs/wm_hubs.c @@ -18,6 +18,7 @@ #include <linux/pm.h> #include <linux/i2c.h> #include <linux/platform_device.h> +#include <linux/mfd/wm8994/registers.h> #include <sound/core.h> #include <sound/pcm.h> #include <sound/pcm_params.h> @@ -116,14 +117,23 @@ static void calibrate_dc_servo(struct snd_soc_codec *codec) { struct wm_hubs_data *hubs = snd_soc_codec_get_drvdata(codec); s8 offset; - u16 reg, reg_l, reg_r, dcs_cfg; + u16 reg, reg_l, reg_r, dcs_cfg, dcs_reg; + + switch (hubs->dcs_readback_mode) { + case 2: + dcs_reg = WM8994_DC_SERVO_4E; + break; + default: + dcs_reg = WM8993_DC_SERVO_3; + break; + } /* If we're using a digital only path and have a previously * callibrated DC servo offset stored then use that. */ if (hubs->class_w && hubs->class_w_dcs) { dev_dbg(codec->dev, "Using cached DC servo offset %x\n", hubs->class_w_dcs); - snd_soc_write(codec, WM8993_DC_SERVO_3, hubs->class_w_dcs); + snd_soc_write(codec, dcs_reg, hubs->class_w_dcs); wait_for_dc_servo(codec, WM8993_DCS_TRIG_DAC_WR_0 | WM8993_DCS_TRIG_DAC_WR_1); @@ -154,8 +164,9 @@ static void calibrate_dc_servo(struct snd_soc_codec *codec) reg_r = snd_soc_read(codec, WM8993_DC_SERVO_READBACK_2) & WM8993_DCS_INTEG_CHAN_1_MASK; break; + case 2: case 1: - reg = snd_soc_read(codec, WM8993_DC_SERVO_3); + reg = snd_soc_read(codec, dcs_reg); reg_r = (reg & WM8993_DCS_DAC_WR_VAL_1_MASK) >> WM8993_DCS_DAC_WR_VAL_1_SHIFT; reg_l = reg & WM8993_DCS_DAC_WR_VAL_0_MASK; @@ -168,24 +179,25 @@ static void calibrate_dc_servo(struct snd_soc_codec *codec) dev_dbg(codec->dev, "DCS input: %x %x\n", reg_l, reg_r); /* Apply correction to DC servo result */ - if (hubs->dcs_codes) { - dev_dbg(codec->dev, "Applying %d code DC servo correction\n", - hubs->dcs_codes); + if (hubs->dcs_codes_l || hubs->dcs_codes_r) { + dev_dbg(codec->dev, + "Applying %d/%d code DC servo correction\n", + hubs->dcs_codes_l, hubs->dcs_codes_r); /* HPOUT1R */ offset = reg_r; - offset += hubs->dcs_codes; + offset += hubs->dcs_codes_r; dcs_cfg = (u8)offset << WM8993_DCS_DAC_WR_VAL_1_SHIFT; /* HPOUT1L */ offset = reg_l; - offset += hubs->dcs_codes; + offset += hubs->dcs_codes_l; dcs_cfg |= (u8)offset; dev_dbg(codec->dev, "DCS result: %x\n", dcs_cfg); /* Do it */ - snd_soc_write(codec, WM8993_DC_SERVO_3, dcs_cfg); + snd_soc_write(codec, dcs_reg, dcs_cfg); wait_for_dc_servo(codec, WM8993_DCS_TRIG_DAC_WR_0 | WM8993_DCS_TRIG_DAC_WR_1); @@ -210,14 +222,14 @@ static int wm8993_put_dc_servo(struct snd_kcontrol *kcontrol, struct wm_hubs_data *hubs = snd_soc_codec_get_drvdata(codec); int ret; - ret = snd_soc_put_volsw_2r(kcontrol, ucontrol); + ret = snd_soc_put_volsw(kcontrol, ucontrol); /* Updating the analogue gains invalidates the DC servo cache */ hubs->class_w_dcs = 0; /* If we're applying an offset correction then updating the * callibration would be likely to introduce further offsets. */ - if (hubs->dcs_codes || hubs->no_series_update) + if (hubs->dcs_codes_l || hubs->dcs_codes_r || hubs->no_series_update) return ret; /* Only need to do this if the outputs are active */ @@ -350,19 +362,11 @@ SOC_DOUBLE_TLV("Speaker Boost Volume", WM8993_SPKOUT_BOOST, 3, 0, 7, 0, SOC_ENUM("Speaker Reference", speaker_ref), SOC_ENUM("Speaker Mode", speaker_mode), -{ - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = "Headphone Volume", - .access = SNDRV_CTL_ELEM_ACCESS_TLV_READ | - SNDRV_CTL_ELEM_ACCESS_READWRITE, - .tlv.p = outpga_tlv, - .info = snd_soc_info_volsw_2r, - .get = snd_soc_get_volsw_2r, .put = wm8993_put_dc_servo, - .private_value = (unsigned long)&(struct soc_mixer_control) { - .reg = WM8993_LEFT_OUTPUT_VOLUME, - .rreg = WM8993_RIGHT_OUTPUT_VOLUME, - .shift = 0, .max = 63 - }, -}, +SOC_DOUBLE_R_EXT_TLV("Headphone Volume", + WM8993_LEFT_OUTPUT_VOLUME, WM8993_RIGHT_OUTPUT_VOLUME, + 0, 63, 0, snd_soc_get_volsw, wm8993_put_dc_servo, + outpga_tlv), + SOC_DOUBLE_R("Headphone Switch", WM8993_LEFT_OUTPUT_VOLUME, WM8993_RIGHT_OUTPUT_VOLUME, 6, 1, 0), SOC_DOUBLE_R("Headphone ZC Switch", WM8993_LEFT_OUTPUT_VOLUME, @@ -699,6 +703,11 @@ static const struct snd_soc_dapm_route analogue_routes[] = { { "IN1L PGA", "IN1LP Switch", "IN1LP" }, { "IN1L PGA", "IN1LN Switch", "IN1LN" }, + { "IN1L PGA", NULL, "VMID" }, + { "IN1R PGA", NULL, "VMID" }, + { "IN2L PGA", NULL, "VMID" }, + { "IN2R PGA", NULL, "VMID" }, + { "IN1R PGA", "IN1RP Switch", "IN1RP" }, { "IN1R PGA", "IN1RN Switch", "IN1RN" }, @@ -716,12 +725,14 @@ static const struct snd_soc_dapm_route analogue_routes[] = { { "MIXINL", NULL, "Direct Voice" }, { "MIXINL", NULL, "IN1LP" }, { "MIXINL", NULL, "Left Output Mixer" }, + { "MIXINL", NULL, "VMID" }, { "MIXINR", "IN1R Switch", "IN1R PGA" }, { "MIXINR", "IN2R Switch", "IN2R PGA" }, { "MIXINR", NULL, "Direct Voice" }, { "MIXINR", NULL, "IN1RP" }, { "MIXINR", NULL, "Right Output Mixer" }, + { "MIXINR", NULL, "VMID" }, { "ADCL", NULL, "MIXINL" }, { "ADCR", NULL, "MIXINR" }, @@ -752,6 +763,7 @@ static const struct snd_soc_dapm_route analogue_routes[] = { { "Earpiece Mixer", "Left Output Switch", "Left Output PGA" }, { "Earpiece Mixer", "Right Output Switch", "Right Output PGA" }, + { "Earpiece Driver", NULL, "VMID" }, { "Earpiece Driver", NULL, "Earpiece Mixer" }, { "HPOUT2N", NULL, "Earpiece Driver" }, { "HPOUT2P", NULL, "Earpiece Driver" }, @@ -774,9 +786,11 @@ static const struct snd_soc_dapm_route analogue_routes[] = { { "SPKR Boost", "SPKR Switch", "SPKR" }, { "SPKR Boost", "SPKL Switch", "SPKL" }, + { "SPKL Driver", NULL, "VMID" }, { "SPKL Driver", NULL, "SPKL Boost" }, { "SPKL Driver", NULL, "CLK_SYS" }, + { "SPKR Driver", NULL, "VMID" }, { "SPKR Driver", NULL, "SPKR Boost" }, { "SPKR Driver", NULL, "CLK_SYS" }, @@ -790,12 +804,18 @@ static const struct snd_soc_dapm_route analogue_routes[] = { { "Headphone PGA", NULL, "Left Headphone Mux" }, { "Headphone PGA", NULL, "Right Headphone Mux" }, + { "Headphone PGA", NULL, "VMID" }, { "Headphone PGA", NULL, "CLK_SYS" }, { "Headphone PGA", NULL, "Headphone Supply" }, { "HPOUT1L", NULL, "Headphone PGA" }, { "HPOUT1R", NULL, "Headphone PGA" }, + { "LINEOUT1N Driver", NULL, "VMID" }, + { "LINEOUT1P Driver", NULL, "VMID" }, + { "LINEOUT2N Driver", NULL, "VMID" }, + { "LINEOUT2P Driver", NULL, "VMID" }, + { "LINEOUT1N", NULL, "LINEOUT1N Driver" }, { "LINEOUT1P", NULL, "LINEOUT1P Driver" }, { "LINEOUT2N", NULL, "LINEOUT2N Driver" }, diff --git a/sound/soc/codecs/wm_hubs.h b/sound/soc/codecs/wm_hubs.h index 676b1252ab9..c674c7a502a 100644 --- a/sound/soc/codecs/wm_hubs.h +++ b/sound/soc/codecs/wm_hubs.h @@ -23,7 +23,8 @@ extern const unsigned int wm_hubs_spkmix_tlv[]; /* This *must* be the first element of the codec->private_data struct */ struct wm_hubs_data { - int dcs_codes; + int dcs_codes_l; + int dcs_codes_r; int dcs_readback_mode; int hp_startup_mode; int series_startup; |