13 #include <linux/module.h>
15 #include <linux/kernel.h>
19 #include <linux/i2c.h>
20 #include <linux/slab.h>
27 #include <asm/div64.h>
49 static const u16 wm8990_reg[] = {
116 #define wm8990_reset(c) snd_soc_write(c, WM8990_RESET, 0)
134 static int wm899x_outpga_put_volsw_vu(
struct snd_kcontrol *kcontrol,
153 #define SOC_WM899X_OUTPGA_SINGLE_R_TLV(xname, reg, shift, max, invert,\
155 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = (xname), \
156 .access = SNDRV_CTL_ELEM_ACCESS_TLV_READ |\
157 SNDRV_CTL_ELEM_ACCESS_READWRITE,\
158 .tlv.p = (tlv_array), \
159 .info = snd_soc_info_volsw, \
160 .get = snd_soc_get_volsw, .put = wm899x_outpga_put_volsw_vu, \
161 .private_value = SOC_SINGLE_VALUE(reg, shift, max, invert) }
164 static const char *wm8990_digital_sidetone[] =
165 {
"None",
"Left ADC",
"Right ADC",
"Reserved"};
167 static const struct soc_enum wm8990_left_digital_sidetone_enum =
171 wm8990_digital_sidetone);
173 static const struct soc_enum wm8990_right_digital_sidetone_enum =
177 wm8990_digital_sidetone);
179 static const char *wm8990_adcmode[] =
180 {
"Hi-fi mode",
"Voice mode 1",
"Voice mode 2",
"Voice mode 3"};
182 static const struct soc_enum wm8990_right_adcmode_enum =
297 SOC_ENUM(
"Left Digital Sidetone", wm8990_left_digital_sidetone_enum),
298 SOC_ENUM(
"Right Digital Sidetone", wm8990_right_digital_sidetone_enum),
310 SOC_ENUM(
"ADC HPF Mode", wm8990_right_adcmode_enum),
422 "Cannot set as Output Mixer 1 LDLO Set\n");
430 "Cannot set as Output Mixer 2 RDRO Set\n");
438 "Cannot set as Speaker Mixer LDSPK Set\n");
446 "Cannot set as Speaker Mixer RDSPK Set\n");
456 static const unsigned int in_mix_tlv[] = {
508 static const char *wm8990_ainlmux[] =
509 {
"INMIXL Mix",
"RXVOICE Mix",
"DIFFINL Mix"};
511 static const struct soc_enum wm8990_ainlmux_enum =
521 static const char *wm8990_ainrmux[] =
522 {
"INMIXR Mix",
"RXVOICE Mix",
"DIFFINR Mix"};
524 static const struct soc_enum wm8990_ainrmux_enum =
672 0, &wm8990_dapm_lin12_pga_controls[0],
675 0, &wm8990_dapm_lin34_pga_controls[0],
678 0, &wm8990_dapm_rin12_pga_controls[0],
681 0, &wm8990_dapm_rin34_pga_controls[0],
686 &wm8990_dapm_inmixl_controls[0],
692 &wm8990_dapm_ainlmux_controls, inmixer_event,
697 &wm8990_dapm_inmixr_controls[0],
703 &wm8990_dapm_ainrmux_controls, inmixer_event,
715 0, &wm8990_dapm_lomix_controls[0],
721 &wm8990_dapm_lonmix_controls[0],
726 &wm8990_dapm_lopmix_controls[0],
731 &wm8990_dapm_out3mix_controls[0],
736 &wm8990_dapm_spkmix_controls[0],
737 ARRAY_SIZE(wm8990_dapm_spkmix_controls), outmixer_event,
742 &wm8990_dapm_out4mix_controls[0],
747 &wm8990_dapm_ropmix_controls[0],
752 &wm8990_dapm_ronmix_controls[0],
757 0, &wm8990_dapm_romix_controls[0],
797 {
"Internal DAC Sink",
NULL,
"Left DAC"},
798 {
"Internal DAC Sink",
NULL,
"Right DAC"},
801 {
"Left ADC",
NULL,
"Internal ADC Source"},
802 {
"Right ADC",
NULL,
"Internal ADC Source"},
806 {
"LIN12 PGA",
"LIN1 Switch",
"LIN1"},
807 {
"LIN12 PGA",
"LIN2 Switch",
"LIN2"},
809 {
"LIN34 PGA",
"LIN3 Switch",
"LIN3"},
810 {
"LIN34 PGA",
"LIN4 Switch",
"LIN4/RXN"},
812 {
"INMIXL",
"Record Left Volume",
"LOMIX"},
813 {
"INMIXL",
"LIN2 Volume",
"LIN2"},
814 {
"INMIXL",
"LINPGA12 Switch",
"LIN12 PGA"},
815 {
"INMIXL",
"LINPGA34 Switch",
"LIN34 PGA"},
817 {
"AINLMUX",
"INMIXL Mix",
"INMIXL"},
818 {
"AINLMUX",
"DIFFINL Mix",
"LIN12 PGA"},
819 {
"AINLMUX",
"DIFFINL Mix",
"LIN34 PGA"},
820 {
"AINLMUX",
"RXVOICE Mix",
"LIN4/RXN"},
821 {
"AINLMUX",
"RXVOICE Mix",
"RIN4/RXP"},
823 {
"Left ADC",
NULL,
"AINLMUX"},
826 {
"RIN12 PGA",
"RIN1 Switch",
"RIN1"},
827 {
"RIN12 PGA",
"RIN2 Switch",
"RIN2"},
829 {
"RIN34 PGA",
"RIN3 Switch",
"RIN3"},
830 {
"RIN34 PGA",
"RIN4 Switch",
"RIN4/RXP"},
832 {
"INMIXR",
"Record Right Volume",
"ROMIX"},
833 {
"INMIXR",
"RIN2 Volume",
"RIN2"},
834 {
"INMIXR",
"RINPGA12 Switch",
"RIN12 PGA"},
835 {
"INMIXR",
"RINPGA34 Switch",
"RIN34 PGA"},
837 {
"AINRMUX",
"INMIXR Mix",
"INMIXR"},
838 {
"AINRMUX",
"DIFFINR Mix",
"RIN12 PGA"},
839 {
"AINRMUX",
"DIFFINR Mix",
"RIN34 PGA"},
840 {
"AINRMUX",
"RXVOICE Mix",
"LIN4/RXN"},
841 {
"AINRMUX",
"RXVOICE Mix",
"RIN4/RXP"},
843 {
"Right ADC",
NULL,
"AINRMUX"},
846 {
"LOMIX",
"LOMIX RIN3 Bypass Switch",
"RIN3"},
847 {
"LOMIX",
"LOMIX LIN3 Bypass Switch",
"LIN3"},
848 {
"LOMIX",
"LOMIX LIN12 PGA Bypass Switch",
"LIN12 PGA"},
849 {
"LOMIX",
"LOMIX RIN12 PGA Bypass Switch",
"RIN12 PGA"},
850 {
"LOMIX",
"LOMIX Right ADC Bypass Switch",
"AINRMUX"},
851 {
"LOMIX",
"LOMIX Left ADC Bypass Switch",
"AINLMUX"},
852 {
"LOMIX",
"LOMIX Left DAC Switch",
"Left DAC"},
855 {
"ROMIX",
"ROMIX RIN3 Bypass Switch",
"RIN3"},
856 {
"ROMIX",
"ROMIX LIN3 Bypass Switch",
"LIN3"},
857 {
"ROMIX",
"ROMIX LIN12 PGA Bypass Switch",
"LIN12 PGA"},
858 {
"ROMIX",
"ROMIX RIN12 PGA Bypass Switch",
"RIN12 PGA"},
859 {
"ROMIX",
"ROMIX Right ADC Bypass Switch",
"AINRMUX"},
860 {
"ROMIX",
"ROMIX Left ADC Bypass Switch",
"AINLMUX"},
861 {
"ROMIX",
"ROMIX Right DAC Switch",
"Right DAC"},
864 {
"SPKMIX",
"SPKMIX LIN2 Bypass Switch",
"LIN2"},
865 {
"SPKMIX",
"SPKMIX RIN2 Bypass Switch",
"RIN2"},
866 {
"SPKMIX",
"SPKMIX LADC Bypass Switch",
"AINLMUX"},
867 {
"SPKMIX",
"SPKMIX RADC Bypass Switch",
"AINRMUX"},
868 {
"SPKMIX",
"SPKMIX Left Mixer PGA Switch",
"LOPGA"},
869 {
"SPKMIX",
"SPKMIX Right Mixer PGA Switch",
"ROPGA"},
870 {
"SPKMIX",
"SPKMIX Right DAC Switch",
"Right DAC"},
871 {
"SPKMIX",
"SPKMIX Left DAC Switch",
"Left DAC"},
874 {
"LONMIX",
"LONMIX Left Mixer PGA Switch",
"LOPGA"},
875 {
"LONMIX",
"LONMIX Right Mixer PGA Switch",
"ROPGA"},
876 {
"LONMIX",
"LONMIX Inverted LOP Switch",
"LOPMIX"},
879 {
"LOPMIX",
"LOPMIX Right Mic Bypass Switch",
"RIN12 PGA"},
880 {
"LOPMIX",
"LOPMIX Left Mic Bypass Switch",
"LIN12 PGA"},
881 {
"LOPMIX",
"LOPMIX Left Mixer PGA Switch",
"LOPGA"},
884 {
"OUT3MIX",
"OUT3MIX LIN4/RXP Bypass Switch",
"LIN4/RXN"},
885 {
"OUT3MIX",
"OUT3MIX Left Out PGA Switch",
"LOPGA"},
888 {
"OUT4MIX",
"OUT4MIX Right Out PGA Switch",
"ROPGA"},
889 {
"OUT4MIX",
"OUT4MIX RIN4/RXP Bypass Switch",
"RIN4/RXP"},
892 {
"RONMIX",
"RONMIX Right Mixer PGA Switch",
"ROPGA"},
893 {
"RONMIX",
"RONMIX Left Mixer PGA Switch",
"LOPGA"},
894 {
"RONMIX",
"RONMIX Inverted ROP Switch",
"ROPMIX"},
897 {
"ROPMIX",
"ROPMIX Left Mic Bypass Switch",
"LIN12 PGA"},
898 {
"ROPMIX",
"ROPMIX Right Mic Bypass Switch",
"RIN12 PGA"},
899 {
"ROPMIX",
"ROPMIX Right Mixer PGA Switch",
"ROPGA"},
902 {
"LOPGA",
NULL,
"LOMIX"},
903 {
"ROPGA",
NULL,
"ROMIX"},
905 {
"LOUT PGA",
NULL,
"LOMIX"},
906 {
"ROUT PGA",
NULL,
"ROMIX"},
909 {
"LON",
NULL,
"LONMIX"},
910 {
"LOP",
NULL,
"LOPMIX"},
911 {
"OUT3",
NULL,
"OUT3MIX"},
912 {
"LOUT",
NULL,
"LOUT PGA"},
913 {
"SPKN",
NULL,
"SPKMIX"},
914 {
"ROUT",
NULL,
"ROUT PGA"},
915 {
"OUT4",
NULL,
"OUT4MIX"},
916 {
"ROP",
NULL,
"ROPMIX"},
917 {
"RON",
NULL,
"RONMIX"},
941 #define FIXED_PLL_SIZE ((1 << 16) * 10)
947 unsigned int K, Ndiv, Nmod;
958 if ((Ndiv < 6) || (Ndiv > 12))
960 "WM8990 N value outwith recommended range! N = %u\n", Ndiv);
968 K = Kpart & 0xFFFFFFFF;
980 static int wm8990_set_dai_pll(
struct snd_soc_dai *codec_dai,
int pll_id,
981 int source,
unsigned int freq_in,
unsigned int freq_out)
986 if (freq_in && freq_out) {
1013 static int wm8990_set_dai_sysclk(
struct snd_soc_dai *codec_dai,
1014 int clk_id,
unsigned int freq,
int dir)
1017 struct wm8990_priv *wm8990 = snd_soc_codec_get_drvdata(codec);
1026 static int wm8990_set_dai_fmt(
struct snd_soc_dai *codec_dai,
1079 static int wm8990_set_dai_clkdiv(
struct snd_soc_dai *codec_dai,
1080 int div_id,
int div)
1153 static int wm8990_set_bias_level(
struct snd_soc_codec *codec,
1172 dev_err(codec->
dev,
"Failed to sync cache: %d\n", ret);
1274 #define WM8990_RATES (SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_11025 |\
1275 SNDRV_PCM_RATE_16000 | SNDRV_PCM_RATE_22050 | SNDRV_PCM_RATE_44100 | \
1276 SNDRV_PCM_RATE_48000)
1278 #define WM8990_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE |\
1279 SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S32_LE)
1289 .hw_params = wm8990_hw_params,
1290 .digital_mute = wm8990_mute,
1291 .set_fmt = wm8990_set_dai_fmt,
1292 .set_clkdiv = wm8990_set_dai_clkdiv,
1293 .set_pll = wm8990_set_dai_pll,
1294 .set_sysclk = wm8990_set_dai_sysclk,
1299 .name =
"wm8990-hifi",
1301 .stream_name =
"Playback",
1307 .stream_name =
"Capture",
1312 .ops = &wm8990_dai_ops,
1360 wm8990_add_widgets(codec);
1373 .probe = wm8990_probe,
1374 .remove = wm8990_remove,
1375 .suspend = wm8990_suspend,
1376 .resume = wm8990_resume,
1377 .set_bias_level = wm8990_set_bias_level,
1379 .reg_word_size =
sizeof(
u16),
1384 #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
1396 i2c_set_clientdata(i2c, wm8990);
1399 &soc_codec_dev_wm8990, &wm8990_dai, 1);
1417 static struct i2c_driver wm8990_i2c_driver = {
1422 .probe = wm8990_i2c_probe,
1424 .id_table = wm8990_i2c_id,
1428 static int __init wm8990_modinit(
void)
1431 #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
1432 ret = i2c_add_driver(&wm8990_i2c_driver);
1442 static void __exit wm8990_exit(
void)
1444 #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)