0001
0002
0003
0004
0005
0006
0007
0008
0009 #include <linux/module.h>
0010 #include <linux/moduleparam.h>
0011 #include <linux/kernel.h>
0012 #include <linux/slab.h>
0013 #include <linux/init.h>
0014 #include <linux/delay.h>
0015 #include <linux/pm.h>
0016 #include <linux/platform_device.h>
0017 #include <linux/regulator/consumer.h>
0018 #include <linux/mfd/wm8400-audio.h>
0019 #include <linux/mfd/wm8400-private.h>
0020 #include <linux/mfd/core.h>
0021 #include <sound/core.h>
0022 #include <sound/pcm.h>
0023 #include <sound/pcm_params.h>
0024 #include <sound/soc.h>
0025 #include <sound/initval.h>
0026 #include <sound/tlv.h>
0027
0028 #include "wm8400.h"
0029
0030 static struct regulator_bulk_data power[] = {
0031 {
0032 .supply = "I2S1VDD",
0033 },
0034 {
0035 .supply = "I2S2VDD",
0036 },
0037 {
0038 .supply = "DCVDD",
0039 },
0040 {
0041 .supply = "AVDD",
0042 },
0043 {
0044 .supply = "FLLVDD",
0045 },
0046 {
0047 .supply = "HPVDD",
0048 },
0049 {
0050 .supply = "SPKVDD",
0051 },
0052 };
0053
0054
0055 struct wm8400_priv {
0056 struct wm8400 *wm8400;
0057 u16 fake_register;
0058 unsigned int sysclk;
0059 unsigned int pcmclk;
0060 int fll_in, fll_out;
0061 };
0062
0063 static void wm8400_component_reset(struct snd_soc_component *component)
0064 {
0065 struct wm8400_priv *wm8400 = snd_soc_component_get_drvdata(component);
0066
0067 wm8400_reset_codec_reg_cache(wm8400->wm8400);
0068 }
0069
0070 static const DECLARE_TLV_DB_SCALE(in_pga_tlv, -1650, 3000, 0);
0071
0072 static const DECLARE_TLV_DB_SCALE(out_mix_tlv, -2100, 0, 0);
0073
0074 static const DECLARE_TLV_DB_SCALE(out_pga_tlv, -7300, 600, 0);
0075
0076 static const DECLARE_TLV_DB_SCALE(out_dac_tlv, -7163, 0, 0);
0077
0078 static const DECLARE_TLV_DB_SCALE(in_adc_tlv, -7163, 1763, 0);
0079
0080 static const DECLARE_TLV_DB_SCALE(out_sidetone_tlv, -3600, 0, 0);
0081
0082 static int wm8400_outpga_put_volsw_vu(struct snd_kcontrol *kcontrol,
0083 struct snd_ctl_elem_value *ucontrol)
0084 {
0085 struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol);
0086 struct soc_mixer_control *mc =
0087 (struct soc_mixer_control *)kcontrol->private_value;
0088 int reg = mc->reg;
0089 int ret;
0090 u16 val;
0091
0092 ret = snd_soc_put_volsw(kcontrol, ucontrol);
0093 if (ret < 0)
0094 return ret;
0095
0096
0097 val = snd_soc_component_read(component, reg);
0098 return snd_soc_component_write(component, reg, val | 0x0100);
0099 }
0100
0101 #define WM8400_OUTPGA_SINGLE_R_TLV(xname, reg, shift, max, invert, tlv_array) \
0102 SOC_SINGLE_EXT_TLV(xname, reg, shift, max, invert, \
0103 snd_soc_get_volsw, wm8400_outpga_put_volsw_vu, tlv_array)
0104
0105
0106 static const char *wm8400_digital_sidetone[] =
0107 {"None", "Left ADC", "Right ADC", "Reserved"};
0108
0109 static SOC_ENUM_SINGLE_DECL(wm8400_left_digital_sidetone_enum,
0110 WM8400_DIGITAL_SIDE_TONE,
0111 WM8400_ADC_TO_DACL_SHIFT,
0112 wm8400_digital_sidetone);
0113
0114 static SOC_ENUM_SINGLE_DECL(wm8400_right_digital_sidetone_enum,
0115 WM8400_DIGITAL_SIDE_TONE,
0116 WM8400_ADC_TO_DACR_SHIFT,
0117 wm8400_digital_sidetone);
0118
0119 static const char *wm8400_adcmode[] =
0120 {"Hi-fi mode", "Voice mode 1", "Voice mode 2", "Voice mode 3"};
0121
0122 static SOC_ENUM_SINGLE_DECL(wm8400_right_adcmode_enum,
0123 WM8400_ADC_CTRL,
0124 WM8400_ADC_HPF_CUT_SHIFT,
0125 wm8400_adcmode);
0126
0127 static const struct snd_kcontrol_new wm8400_snd_controls[] = {
0128
0129 SOC_SINGLE("LIN12 PGA Boost", WM8400_INPUT_MIXER3, WM8400_L12MNBST_SHIFT,
0130 1, 0),
0131 SOC_SINGLE("LIN34 PGA Boost", WM8400_INPUT_MIXER3, WM8400_L34MNBST_SHIFT,
0132 1, 0),
0133
0134 SOC_SINGLE("RIN12 PGA Boost", WM8400_INPUT_MIXER3, WM8400_R12MNBST_SHIFT,
0135 1, 0),
0136 SOC_SINGLE("RIN34 PGA Boost", WM8400_INPUT_MIXER3, WM8400_R34MNBST_SHIFT,
0137 1, 0),
0138
0139
0140 SOC_SINGLE_TLV("LOMIX LIN3 Bypass Volume", WM8400_OUTPUT_MIXER3,
0141 WM8400_LLI3LOVOL_SHIFT, 7, 0, out_mix_tlv),
0142 SOC_SINGLE_TLV("LOMIX RIN12 PGA Bypass Volume", WM8400_OUTPUT_MIXER3,
0143 WM8400_LR12LOVOL_SHIFT, 7, 0, out_mix_tlv),
0144 SOC_SINGLE_TLV("LOMIX LIN12 PGA Bypass Volume", WM8400_OUTPUT_MIXER3,
0145 WM8400_LL12LOVOL_SHIFT, 7, 0, out_mix_tlv),
0146 SOC_SINGLE_TLV("LOMIX RIN3 Bypass Volume", WM8400_OUTPUT_MIXER5,
0147 WM8400_LRI3LOVOL_SHIFT, 7, 0, out_mix_tlv),
0148 SOC_SINGLE_TLV("LOMIX AINRMUX Bypass Volume", WM8400_OUTPUT_MIXER5,
0149 WM8400_LRBLOVOL_SHIFT, 7, 0, out_mix_tlv),
0150 SOC_SINGLE_TLV("LOMIX AINLMUX Bypass Volume", WM8400_OUTPUT_MIXER5,
0151 WM8400_LRBLOVOL_SHIFT, 7, 0, out_mix_tlv),
0152
0153
0154 SOC_SINGLE_TLV("ROMIX RIN3 Bypass Volume", WM8400_OUTPUT_MIXER4,
0155 WM8400_RRI3ROVOL_SHIFT, 7, 0, out_mix_tlv),
0156 SOC_SINGLE_TLV("ROMIX LIN12 PGA Bypass Volume", WM8400_OUTPUT_MIXER4,
0157 WM8400_RL12ROVOL_SHIFT, 7, 0, out_mix_tlv),
0158 SOC_SINGLE_TLV("ROMIX RIN12 PGA Bypass Volume", WM8400_OUTPUT_MIXER4,
0159 WM8400_RR12ROVOL_SHIFT, 7, 0, out_mix_tlv),
0160 SOC_SINGLE_TLV("ROMIX LIN3 Bypass Volume", WM8400_OUTPUT_MIXER6,
0161 WM8400_RLI3ROVOL_SHIFT, 7, 0, out_mix_tlv),
0162 SOC_SINGLE_TLV("ROMIX AINLMUX Bypass Volume", WM8400_OUTPUT_MIXER6,
0163 WM8400_RLBROVOL_SHIFT, 7, 0, out_mix_tlv),
0164 SOC_SINGLE_TLV("ROMIX AINRMUX Bypass Volume", WM8400_OUTPUT_MIXER6,
0165 WM8400_RRBROVOL_SHIFT, 7, 0, out_mix_tlv),
0166
0167
0168 WM8400_OUTPGA_SINGLE_R_TLV("LOUT Volume", WM8400_LEFT_OUTPUT_VOLUME,
0169 WM8400_LOUTVOL_SHIFT, WM8400_LOUTVOL_MASK, 0, out_pga_tlv),
0170 SOC_SINGLE("LOUT ZC", WM8400_LEFT_OUTPUT_VOLUME, WM8400_LOZC_SHIFT, 1, 0),
0171
0172
0173 WM8400_OUTPGA_SINGLE_R_TLV("ROUT Volume", WM8400_RIGHT_OUTPUT_VOLUME,
0174 WM8400_ROUTVOL_SHIFT, WM8400_ROUTVOL_MASK, 0, out_pga_tlv),
0175 SOC_SINGLE("ROUT ZC", WM8400_RIGHT_OUTPUT_VOLUME, WM8400_ROZC_SHIFT, 1, 0),
0176
0177
0178 WM8400_OUTPGA_SINGLE_R_TLV("LOPGA Volume", WM8400_LEFT_OPGA_VOLUME,
0179 WM8400_LOPGAVOL_SHIFT, WM8400_LOPGAVOL_MASK, 0, out_pga_tlv),
0180 SOC_SINGLE("LOPGA ZC Switch", WM8400_LEFT_OPGA_VOLUME,
0181 WM8400_LOPGAZC_SHIFT, 1, 0),
0182
0183
0184 WM8400_OUTPGA_SINGLE_R_TLV("ROPGA Volume", WM8400_RIGHT_OPGA_VOLUME,
0185 WM8400_ROPGAVOL_SHIFT, WM8400_ROPGAVOL_MASK, 0, out_pga_tlv),
0186 SOC_SINGLE("ROPGA ZC Switch", WM8400_RIGHT_OPGA_VOLUME,
0187 WM8400_ROPGAZC_SHIFT, 1, 0),
0188
0189 SOC_SINGLE("LON Mute Switch", WM8400_LINE_OUTPUTS_VOLUME,
0190 WM8400_LONMUTE_SHIFT, 1, 0),
0191 SOC_SINGLE("LOP Mute Switch", WM8400_LINE_OUTPUTS_VOLUME,
0192 WM8400_LOPMUTE_SHIFT, 1, 0),
0193 SOC_SINGLE("LOP Attenuation Switch", WM8400_LINE_OUTPUTS_VOLUME,
0194 WM8400_LOATTN_SHIFT, 1, 0),
0195 SOC_SINGLE("RON Mute Switch", WM8400_LINE_OUTPUTS_VOLUME,
0196 WM8400_RONMUTE_SHIFT, 1, 0),
0197 SOC_SINGLE("ROP Mute Switch", WM8400_LINE_OUTPUTS_VOLUME,
0198 WM8400_ROPMUTE_SHIFT, 1, 0),
0199 SOC_SINGLE("ROP Attenuation Switch", WM8400_LINE_OUTPUTS_VOLUME,
0200 WM8400_ROATTN_SHIFT, 1, 0),
0201
0202 SOC_SINGLE("OUT3 Mute Switch", WM8400_OUT3_4_VOLUME,
0203 WM8400_OUT3MUTE_SHIFT, 1, 0),
0204 SOC_SINGLE("OUT3 Attenuation Switch", WM8400_OUT3_4_VOLUME,
0205 WM8400_OUT3ATTN_SHIFT, 1, 0),
0206
0207 SOC_SINGLE("OUT4 Mute Switch", WM8400_OUT3_4_VOLUME,
0208 WM8400_OUT4MUTE_SHIFT, 1, 0),
0209 SOC_SINGLE("OUT4 Attenuation Switch", WM8400_OUT3_4_VOLUME,
0210 WM8400_OUT4ATTN_SHIFT, 1, 0),
0211
0212 SOC_SINGLE("Speaker Mode Switch", WM8400_CLASSD1,
0213 WM8400_CDMODE_SHIFT, 1, 0),
0214
0215 SOC_SINGLE("Speaker Output Attenuation Volume", WM8400_SPEAKER_VOLUME,
0216 WM8400_SPKATTN_SHIFT, WM8400_SPKATTN_MASK, 0),
0217 SOC_SINGLE("Speaker DC Boost Volume", WM8400_CLASSD3,
0218 WM8400_DCGAIN_SHIFT, 6, 0),
0219 SOC_SINGLE("Speaker AC Boost Volume", WM8400_CLASSD3,
0220 WM8400_ACGAIN_SHIFT, 6, 0),
0221
0222 WM8400_OUTPGA_SINGLE_R_TLV("Left DAC Digital Volume",
0223 WM8400_LEFT_DAC_DIGITAL_VOLUME, WM8400_DACL_VOL_SHIFT,
0224 127, 0, out_dac_tlv),
0225
0226 WM8400_OUTPGA_SINGLE_R_TLV("Right DAC Digital Volume",
0227 WM8400_RIGHT_DAC_DIGITAL_VOLUME, WM8400_DACR_VOL_SHIFT,
0228 127, 0, out_dac_tlv),
0229
0230 SOC_ENUM("Left Digital Sidetone", wm8400_left_digital_sidetone_enum),
0231 SOC_ENUM("Right Digital Sidetone", wm8400_right_digital_sidetone_enum),
0232
0233 SOC_SINGLE_TLV("Left Digital Sidetone Volume", WM8400_DIGITAL_SIDE_TONE,
0234 WM8400_ADCL_DAC_SVOL_SHIFT, 15, 0, out_sidetone_tlv),
0235 SOC_SINGLE_TLV("Right Digital Sidetone Volume", WM8400_DIGITAL_SIDE_TONE,
0236 WM8400_ADCR_DAC_SVOL_SHIFT, 15, 0, out_sidetone_tlv),
0237
0238 SOC_SINGLE("ADC Digital High Pass Filter Switch", WM8400_ADC_CTRL,
0239 WM8400_ADC_HPF_ENA_SHIFT, 1, 0),
0240
0241 SOC_ENUM("ADC HPF Mode", wm8400_right_adcmode_enum),
0242
0243 WM8400_OUTPGA_SINGLE_R_TLV("Left ADC Digital Volume",
0244 WM8400_LEFT_ADC_DIGITAL_VOLUME,
0245 WM8400_ADCL_VOL_SHIFT,
0246 WM8400_ADCL_VOL_MASK,
0247 0,
0248 in_adc_tlv),
0249
0250 WM8400_OUTPGA_SINGLE_R_TLV("Right ADC Digital Volume",
0251 WM8400_RIGHT_ADC_DIGITAL_VOLUME,
0252 WM8400_ADCR_VOL_SHIFT,
0253 WM8400_ADCR_VOL_MASK,
0254 0,
0255 in_adc_tlv),
0256
0257 WM8400_OUTPGA_SINGLE_R_TLV("LIN12 Volume",
0258 WM8400_LEFT_LINE_INPUT_1_2_VOLUME,
0259 WM8400_LIN12VOL_SHIFT,
0260 WM8400_LIN12VOL_MASK,
0261 0,
0262 in_pga_tlv),
0263
0264 SOC_SINGLE("LIN12 ZC Switch", WM8400_LEFT_LINE_INPUT_1_2_VOLUME,
0265 WM8400_LI12ZC_SHIFT, 1, 0),
0266
0267 SOC_SINGLE("LIN12 Mute Switch", WM8400_LEFT_LINE_INPUT_1_2_VOLUME,
0268 WM8400_LI12MUTE_SHIFT, 1, 0),
0269
0270 WM8400_OUTPGA_SINGLE_R_TLV("LIN34 Volume",
0271 WM8400_LEFT_LINE_INPUT_3_4_VOLUME,
0272 WM8400_LIN34VOL_SHIFT,
0273 WM8400_LIN34VOL_MASK,
0274 0,
0275 in_pga_tlv),
0276
0277 SOC_SINGLE("LIN34 ZC Switch", WM8400_LEFT_LINE_INPUT_3_4_VOLUME,
0278 WM8400_LI34ZC_SHIFT, 1, 0),
0279
0280 SOC_SINGLE("LIN34 Mute Switch", WM8400_LEFT_LINE_INPUT_3_4_VOLUME,
0281 WM8400_LI34MUTE_SHIFT, 1, 0),
0282
0283 WM8400_OUTPGA_SINGLE_R_TLV("RIN12 Volume",
0284 WM8400_RIGHT_LINE_INPUT_1_2_VOLUME,
0285 WM8400_RIN12VOL_SHIFT,
0286 WM8400_RIN12VOL_MASK,
0287 0,
0288 in_pga_tlv),
0289
0290 SOC_SINGLE("RIN12 ZC Switch", WM8400_RIGHT_LINE_INPUT_1_2_VOLUME,
0291 WM8400_RI12ZC_SHIFT, 1, 0),
0292
0293 SOC_SINGLE("RIN12 Mute Switch", WM8400_RIGHT_LINE_INPUT_1_2_VOLUME,
0294 WM8400_RI12MUTE_SHIFT, 1, 0),
0295
0296 WM8400_OUTPGA_SINGLE_R_TLV("RIN34 Volume",
0297 WM8400_RIGHT_LINE_INPUT_3_4_VOLUME,
0298 WM8400_RIN34VOL_SHIFT,
0299 WM8400_RIN34VOL_MASK,
0300 0,
0301 in_pga_tlv),
0302
0303 SOC_SINGLE("RIN34 ZC Switch", WM8400_RIGHT_LINE_INPUT_3_4_VOLUME,
0304 WM8400_RI34ZC_SHIFT, 1, 0),
0305
0306 SOC_SINGLE("RIN34 Mute Switch", WM8400_RIGHT_LINE_INPUT_3_4_VOLUME,
0307 WM8400_RI34MUTE_SHIFT, 1, 0),
0308
0309 };
0310
0311
0312
0313
0314
0315 static int outmixer_event (struct snd_soc_dapm_widget *w,
0316 struct snd_kcontrol * kcontrol, int event)
0317 {
0318 struct snd_soc_component *component = snd_soc_dapm_to_component(w->dapm);
0319 struct soc_mixer_control *mc =
0320 (struct soc_mixer_control *)kcontrol->private_value;
0321 u32 reg_shift = mc->shift;
0322 int ret = 0;
0323 u16 reg;
0324
0325 switch (reg_shift) {
0326 case WM8400_SPEAKER_MIXER | (WM8400_LDSPK << 8) :
0327 reg = snd_soc_component_read(component, WM8400_OUTPUT_MIXER1);
0328 if (reg & WM8400_LDLO) {
0329 printk(KERN_WARNING
0330 "Cannot set as Output Mixer 1 LDLO Set\n");
0331 ret = -1;
0332 }
0333 break;
0334 case WM8400_SPEAKER_MIXER | (WM8400_RDSPK << 8):
0335 reg = snd_soc_component_read(component, WM8400_OUTPUT_MIXER2);
0336 if (reg & WM8400_RDRO) {
0337 printk(KERN_WARNING
0338 "Cannot set as Output Mixer 2 RDRO Set\n");
0339 ret = -1;
0340 }
0341 break;
0342 case WM8400_OUTPUT_MIXER1 | (WM8400_LDLO << 8):
0343 reg = snd_soc_component_read(component, WM8400_SPEAKER_MIXER);
0344 if (reg & WM8400_LDSPK) {
0345 printk(KERN_WARNING
0346 "Cannot set as Speaker Mixer LDSPK Set\n");
0347 ret = -1;
0348 }
0349 break;
0350 case WM8400_OUTPUT_MIXER2 | (WM8400_RDRO << 8):
0351 reg = snd_soc_component_read(component, WM8400_SPEAKER_MIXER);
0352 if (reg & WM8400_RDSPK) {
0353 printk(KERN_WARNING
0354 "Cannot set as Speaker Mixer RDSPK Set\n");
0355 ret = -1;
0356 }
0357 break;
0358 }
0359
0360 return ret;
0361 }
0362
0363
0364 static const DECLARE_TLV_DB_SCALE(in_mix_tlv, -1200, 600, 0);
0365
0366
0367 static const struct snd_kcontrol_new wm8400_dapm_lin12_pga_controls[] = {
0368 SOC_DAPM_SINGLE("LIN1 Switch", WM8400_INPUT_MIXER2, WM8400_LMN1_SHIFT, 1, 0),
0369 SOC_DAPM_SINGLE("LIN2 Switch", WM8400_INPUT_MIXER2, WM8400_LMP2_SHIFT, 1, 0),
0370 };
0371
0372 static const struct snd_kcontrol_new wm8400_dapm_lin34_pga_controls[] = {
0373 SOC_DAPM_SINGLE("LIN3 Switch", WM8400_INPUT_MIXER2, WM8400_LMN3_SHIFT, 1, 0),
0374 SOC_DAPM_SINGLE("LIN4 Switch", WM8400_INPUT_MIXER2, WM8400_LMP4_SHIFT, 1, 0),
0375 };
0376
0377
0378 static const struct snd_kcontrol_new wm8400_dapm_rin12_pga_controls[] = {
0379 SOC_DAPM_SINGLE("RIN1 Switch", WM8400_INPUT_MIXER2, WM8400_RMN1_SHIFT, 1, 0),
0380 SOC_DAPM_SINGLE("RIN2 Switch", WM8400_INPUT_MIXER2, WM8400_RMP2_SHIFT, 1, 0),
0381 };
0382
0383 static const struct snd_kcontrol_new wm8400_dapm_rin34_pga_controls[] = {
0384 SOC_DAPM_SINGLE("RIN3 Switch", WM8400_INPUT_MIXER2, WM8400_RMN3_SHIFT, 1, 0),
0385 SOC_DAPM_SINGLE("RIN4 Switch", WM8400_INPUT_MIXER2, WM8400_RMP4_SHIFT, 1, 0),
0386 };
0387
0388
0389 static const struct snd_kcontrol_new wm8400_dapm_inmixl_controls[] = {
0390 SOC_DAPM_SINGLE_TLV("Record Left Volume", WM8400_INPUT_MIXER3,
0391 WM8400_LDBVOL_SHIFT, WM8400_LDBVOL_MASK, 0, in_mix_tlv),
0392 SOC_DAPM_SINGLE_TLV("LIN2 Volume", WM8400_INPUT_MIXER5, WM8400_LI2BVOL_SHIFT,
0393 7, 0, in_mix_tlv),
0394 SOC_DAPM_SINGLE("LINPGA12 Switch", WM8400_INPUT_MIXER3, WM8400_L12MNB_SHIFT,
0395 1, 0),
0396 SOC_DAPM_SINGLE("LINPGA34 Switch", WM8400_INPUT_MIXER3, WM8400_L34MNB_SHIFT,
0397 1, 0),
0398 };
0399
0400
0401 static const struct snd_kcontrol_new wm8400_dapm_inmixr_controls[] = {
0402 SOC_DAPM_SINGLE_TLV("Record Right Volume", WM8400_INPUT_MIXER4,
0403 WM8400_RDBVOL_SHIFT, WM8400_RDBVOL_MASK, 0, in_mix_tlv),
0404 SOC_DAPM_SINGLE_TLV("RIN2 Volume", WM8400_INPUT_MIXER6, WM8400_RI2BVOL_SHIFT,
0405 7, 0, in_mix_tlv),
0406 SOC_DAPM_SINGLE("RINPGA12 Switch", WM8400_INPUT_MIXER3, WM8400_L12MNB_SHIFT,
0407 1, 0),
0408 SOC_DAPM_SINGLE("RINPGA34 Switch", WM8400_INPUT_MIXER3, WM8400_L34MNB_SHIFT,
0409 1, 0),
0410 };
0411
0412
0413 static const char *wm8400_ainlmux[] =
0414 {"INMIXL Mix", "RXVOICE Mix", "DIFFINL Mix"};
0415
0416 static SOC_ENUM_SINGLE_DECL(wm8400_ainlmux_enum,
0417 WM8400_INPUT_MIXER1,
0418 WM8400_AINLMODE_SHIFT,
0419 wm8400_ainlmux);
0420
0421 static const struct snd_kcontrol_new wm8400_dapm_ainlmux_controls =
0422 SOC_DAPM_ENUM("Route", wm8400_ainlmux_enum);
0423
0424
0425
0426
0427 static const char *wm8400_ainrmux[] =
0428 {"INMIXR Mix", "RXVOICE Mix", "DIFFINR Mix"};
0429
0430 static SOC_ENUM_SINGLE_DECL(wm8400_ainrmux_enum,
0431 WM8400_INPUT_MIXER1,
0432 WM8400_AINRMODE_SHIFT,
0433 wm8400_ainrmux);
0434
0435 static const struct snd_kcontrol_new wm8400_dapm_ainrmux_controls =
0436 SOC_DAPM_ENUM("Route", wm8400_ainrmux_enum);
0437
0438
0439 static const struct snd_kcontrol_new wm8400_dapm_lomix_controls[] = {
0440 SOC_DAPM_SINGLE("LOMIX Right ADC Bypass Switch", WM8400_OUTPUT_MIXER1,
0441 WM8400_LRBLO_SHIFT, 1, 0),
0442 SOC_DAPM_SINGLE("LOMIX Left ADC Bypass Switch", WM8400_OUTPUT_MIXER1,
0443 WM8400_LLBLO_SHIFT, 1, 0),
0444 SOC_DAPM_SINGLE("LOMIX RIN3 Bypass Switch", WM8400_OUTPUT_MIXER1,
0445 WM8400_LRI3LO_SHIFT, 1, 0),
0446 SOC_DAPM_SINGLE("LOMIX LIN3 Bypass Switch", WM8400_OUTPUT_MIXER1,
0447 WM8400_LLI3LO_SHIFT, 1, 0),
0448 SOC_DAPM_SINGLE("LOMIX RIN12 PGA Bypass Switch", WM8400_OUTPUT_MIXER1,
0449 WM8400_LR12LO_SHIFT, 1, 0),
0450 SOC_DAPM_SINGLE("LOMIX LIN12 PGA Bypass Switch", WM8400_OUTPUT_MIXER1,
0451 WM8400_LL12LO_SHIFT, 1, 0),
0452 SOC_DAPM_SINGLE("LOMIX Left DAC Switch", WM8400_OUTPUT_MIXER1,
0453 WM8400_LDLO_SHIFT, 1, 0),
0454 };
0455
0456
0457 static const struct snd_kcontrol_new wm8400_dapm_romix_controls[] = {
0458 SOC_DAPM_SINGLE("ROMIX Left ADC Bypass Switch", WM8400_OUTPUT_MIXER2,
0459 WM8400_RLBRO_SHIFT, 1, 0),
0460 SOC_DAPM_SINGLE("ROMIX Right ADC Bypass Switch", WM8400_OUTPUT_MIXER2,
0461 WM8400_RRBRO_SHIFT, 1, 0),
0462 SOC_DAPM_SINGLE("ROMIX LIN3 Bypass Switch", WM8400_OUTPUT_MIXER2,
0463 WM8400_RLI3RO_SHIFT, 1, 0),
0464 SOC_DAPM_SINGLE("ROMIX RIN3 Bypass Switch", WM8400_OUTPUT_MIXER2,
0465 WM8400_RRI3RO_SHIFT, 1, 0),
0466 SOC_DAPM_SINGLE("ROMIX LIN12 PGA Bypass Switch", WM8400_OUTPUT_MIXER2,
0467 WM8400_RL12RO_SHIFT, 1, 0),
0468 SOC_DAPM_SINGLE("ROMIX RIN12 PGA Bypass Switch", WM8400_OUTPUT_MIXER2,
0469 WM8400_RR12RO_SHIFT, 1, 0),
0470 SOC_DAPM_SINGLE("ROMIX Right DAC Switch", WM8400_OUTPUT_MIXER2,
0471 WM8400_RDRO_SHIFT, 1, 0),
0472 };
0473
0474
0475 static const struct snd_kcontrol_new wm8400_dapm_lonmix_controls[] = {
0476 SOC_DAPM_SINGLE("LONMIX Left Mixer PGA Switch", WM8400_LINE_MIXER1,
0477 WM8400_LLOPGALON_SHIFT, 1, 0),
0478 SOC_DAPM_SINGLE("LONMIX Right Mixer PGA Switch", WM8400_LINE_MIXER1,
0479 WM8400_LROPGALON_SHIFT, 1, 0),
0480 SOC_DAPM_SINGLE("LONMIX Inverted LOP Switch", WM8400_LINE_MIXER1,
0481 WM8400_LOPLON_SHIFT, 1, 0),
0482 };
0483
0484
0485 static const struct snd_kcontrol_new wm8400_dapm_lopmix_controls[] = {
0486 SOC_DAPM_SINGLE("LOPMIX Right Mic Bypass Switch", WM8400_LINE_MIXER1,
0487 WM8400_LR12LOP_SHIFT, 1, 0),
0488 SOC_DAPM_SINGLE("LOPMIX Left Mic Bypass Switch", WM8400_LINE_MIXER1,
0489 WM8400_LL12LOP_SHIFT, 1, 0),
0490 SOC_DAPM_SINGLE("LOPMIX Left Mixer PGA Switch", WM8400_LINE_MIXER1,
0491 WM8400_LLOPGALOP_SHIFT, 1, 0),
0492 };
0493
0494
0495 static const struct snd_kcontrol_new wm8400_dapm_ronmix_controls[] = {
0496 SOC_DAPM_SINGLE("RONMIX Right Mixer PGA Switch", WM8400_LINE_MIXER2,
0497 WM8400_RROPGARON_SHIFT, 1, 0),
0498 SOC_DAPM_SINGLE("RONMIX Left Mixer PGA Switch", WM8400_LINE_MIXER2,
0499 WM8400_RLOPGARON_SHIFT, 1, 0),
0500 SOC_DAPM_SINGLE("RONMIX Inverted ROP Switch", WM8400_LINE_MIXER2,
0501 WM8400_ROPRON_SHIFT, 1, 0),
0502 };
0503
0504
0505 static const struct snd_kcontrol_new wm8400_dapm_ropmix_controls[] = {
0506 SOC_DAPM_SINGLE("ROPMIX Left Mic Bypass Switch", WM8400_LINE_MIXER2,
0507 WM8400_RL12ROP_SHIFT, 1, 0),
0508 SOC_DAPM_SINGLE("ROPMIX Right Mic Bypass Switch", WM8400_LINE_MIXER2,
0509 WM8400_RR12ROP_SHIFT, 1, 0),
0510 SOC_DAPM_SINGLE("ROPMIX Right Mixer PGA Switch", WM8400_LINE_MIXER2,
0511 WM8400_RROPGAROP_SHIFT, 1, 0),
0512 };
0513
0514
0515 static const struct snd_kcontrol_new wm8400_dapm_out3mix_controls[] = {
0516 SOC_DAPM_SINGLE("OUT3MIX LIN4/RXP Bypass Switch", WM8400_OUT3_4_MIXER,
0517 WM8400_LI4O3_SHIFT, 1, 0),
0518 SOC_DAPM_SINGLE("OUT3MIX Left Out PGA Switch", WM8400_OUT3_4_MIXER,
0519 WM8400_LPGAO3_SHIFT, 1, 0),
0520 };
0521
0522
0523 static const struct snd_kcontrol_new wm8400_dapm_out4mix_controls[] = {
0524 SOC_DAPM_SINGLE("OUT4MIX Right Out PGA Switch", WM8400_OUT3_4_MIXER,
0525 WM8400_RPGAO4_SHIFT, 1, 0),
0526 SOC_DAPM_SINGLE("OUT4MIX RIN4/RXP Bypass Switch", WM8400_OUT3_4_MIXER,
0527 WM8400_RI4O4_SHIFT, 1, 0),
0528 };
0529
0530
0531 static const struct snd_kcontrol_new wm8400_dapm_spkmix_controls[] = {
0532 SOC_DAPM_SINGLE("SPKMIX LIN2 Bypass Switch", WM8400_SPEAKER_MIXER,
0533 WM8400_LI2SPK_SHIFT, 1, 0),
0534 SOC_DAPM_SINGLE("SPKMIX LADC Bypass Switch", WM8400_SPEAKER_MIXER,
0535 WM8400_LB2SPK_SHIFT, 1, 0),
0536 SOC_DAPM_SINGLE("SPKMIX Left Mixer PGA Switch", WM8400_SPEAKER_MIXER,
0537 WM8400_LOPGASPK_SHIFT, 1, 0),
0538 SOC_DAPM_SINGLE("SPKMIX Left DAC Switch", WM8400_SPEAKER_MIXER,
0539 WM8400_LDSPK_SHIFT, 1, 0),
0540 SOC_DAPM_SINGLE("SPKMIX Right DAC Switch", WM8400_SPEAKER_MIXER,
0541 WM8400_RDSPK_SHIFT, 1, 0),
0542 SOC_DAPM_SINGLE("SPKMIX Right Mixer PGA Switch", WM8400_SPEAKER_MIXER,
0543 WM8400_ROPGASPK_SHIFT, 1, 0),
0544 SOC_DAPM_SINGLE("SPKMIX RADC Bypass Switch", WM8400_SPEAKER_MIXER,
0545 WM8400_RL12ROP_SHIFT, 1, 0),
0546 SOC_DAPM_SINGLE("SPKMIX RIN2 Bypass Switch", WM8400_SPEAKER_MIXER,
0547 WM8400_RI2SPK_SHIFT, 1, 0),
0548 };
0549
0550 static const struct snd_soc_dapm_widget wm8400_dapm_widgets[] = {
0551
0552
0553 SND_SOC_DAPM_INPUT("LIN1"),
0554 SND_SOC_DAPM_INPUT("LIN2"),
0555 SND_SOC_DAPM_INPUT("LIN3"),
0556 SND_SOC_DAPM_INPUT("LIN4/RXN"),
0557 SND_SOC_DAPM_INPUT("RIN3"),
0558 SND_SOC_DAPM_INPUT("RIN4/RXP"),
0559 SND_SOC_DAPM_INPUT("RIN1"),
0560 SND_SOC_DAPM_INPUT("RIN2"),
0561 SND_SOC_DAPM_INPUT("Internal ADC Source"),
0562
0563
0564 SND_SOC_DAPM_ADC("Left ADC", "Left Capture", WM8400_POWER_MANAGEMENT_2,
0565 WM8400_ADCL_ENA_SHIFT, 0),
0566 SND_SOC_DAPM_ADC("Right ADC", "Right Capture", WM8400_POWER_MANAGEMENT_2,
0567 WM8400_ADCR_ENA_SHIFT, 0),
0568
0569
0570 SND_SOC_DAPM_MIXER("LIN12 PGA", WM8400_POWER_MANAGEMENT_2,
0571 WM8400_LIN12_ENA_SHIFT,
0572 0, &wm8400_dapm_lin12_pga_controls[0],
0573 ARRAY_SIZE(wm8400_dapm_lin12_pga_controls)),
0574 SND_SOC_DAPM_MIXER("LIN34 PGA", WM8400_POWER_MANAGEMENT_2,
0575 WM8400_LIN34_ENA_SHIFT,
0576 0, &wm8400_dapm_lin34_pga_controls[0],
0577 ARRAY_SIZE(wm8400_dapm_lin34_pga_controls)),
0578 SND_SOC_DAPM_MIXER("RIN12 PGA", WM8400_POWER_MANAGEMENT_2,
0579 WM8400_RIN12_ENA_SHIFT,
0580 0, &wm8400_dapm_rin12_pga_controls[0],
0581 ARRAY_SIZE(wm8400_dapm_rin12_pga_controls)),
0582 SND_SOC_DAPM_MIXER("RIN34 PGA", WM8400_POWER_MANAGEMENT_2,
0583 WM8400_RIN34_ENA_SHIFT,
0584 0, &wm8400_dapm_rin34_pga_controls[0],
0585 ARRAY_SIZE(wm8400_dapm_rin34_pga_controls)),
0586
0587 SND_SOC_DAPM_SUPPLY("INL", WM8400_POWER_MANAGEMENT_2, WM8400_AINL_ENA_SHIFT,
0588 0, NULL, 0),
0589 SND_SOC_DAPM_SUPPLY("INR", WM8400_POWER_MANAGEMENT_2, WM8400_AINR_ENA_SHIFT,
0590 0, NULL, 0),
0591
0592
0593 SND_SOC_DAPM_MIXER("INMIXL", SND_SOC_NOPM, 0, 0,
0594 &wm8400_dapm_inmixl_controls[0],
0595 ARRAY_SIZE(wm8400_dapm_inmixl_controls)),
0596
0597
0598 SND_SOC_DAPM_MUX("AILNMUX", SND_SOC_NOPM, 0, 0, &wm8400_dapm_ainlmux_controls),
0599
0600
0601 SND_SOC_DAPM_MIXER("INMIXR", SND_SOC_NOPM, 0, 0,
0602 &wm8400_dapm_inmixr_controls[0],
0603 ARRAY_SIZE(wm8400_dapm_inmixr_controls)),
0604
0605
0606 SND_SOC_DAPM_MUX("AIRNMUX", SND_SOC_NOPM, 0, 0, &wm8400_dapm_ainrmux_controls),
0607
0608
0609
0610 SND_SOC_DAPM_DAC("Left DAC", "Left Playback", WM8400_POWER_MANAGEMENT_3,
0611 WM8400_DACL_ENA_SHIFT, 0),
0612 SND_SOC_DAPM_DAC("Right DAC", "Right Playback", WM8400_POWER_MANAGEMENT_3,
0613 WM8400_DACR_ENA_SHIFT, 0),
0614
0615
0616 SND_SOC_DAPM_MIXER_E("LOMIX", WM8400_POWER_MANAGEMENT_3,
0617 WM8400_LOMIX_ENA_SHIFT,
0618 0, &wm8400_dapm_lomix_controls[0],
0619 ARRAY_SIZE(wm8400_dapm_lomix_controls),
0620 outmixer_event, SND_SOC_DAPM_PRE_REG),
0621
0622
0623 SND_SOC_DAPM_MIXER("LONMIX", WM8400_POWER_MANAGEMENT_3, WM8400_LON_ENA_SHIFT,
0624 0, &wm8400_dapm_lonmix_controls[0],
0625 ARRAY_SIZE(wm8400_dapm_lonmix_controls)),
0626
0627
0628 SND_SOC_DAPM_MIXER("LOPMIX", WM8400_POWER_MANAGEMENT_3, WM8400_LOP_ENA_SHIFT,
0629 0, &wm8400_dapm_lopmix_controls[0],
0630 ARRAY_SIZE(wm8400_dapm_lopmix_controls)),
0631
0632
0633 SND_SOC_DAPM_MIXER("OUT3MIX", WM8400_POWER_MANAGEMENT_1, WM8400_OUT3_ENA_SHIFT,
0634 0, &wm8400_dapm_out3mix_controls[0],
0635 ARRAY_SIZE(wm8400_dapm_out3mix_controls)),
0636
0637
0638 SND_SOC_DAPM_MIXER_E("SPKMIX", WM8400_POWER_MANAGEMENT_1, WM8400_SPK_ENA_SHIFT,
0639 0, &wm8400_dapm_spkmix_controls[0],
0640 ARRAY_SIZE(wm8400_dapm_spkmix_controls), outmixer_event,
0641 SND_SOC_DAPM_PRE_REG),
0642
0643
0644 SND_SOC_DAPM_MIXER("OUT4MIX", WM8400_POWER_MANAGEMENT_1, WM8400_OUT4_ENA_SHIFT,
0645 0, &wm8400_dapm_out4mix_controls[0],
0646 ARRAY_SIZE(wm8400_dapm_out4mix_controls)),
0647
0648
0649 SND_SOC_DAPM_MIXER("ROPMIX", WM8400_POWER_MANAGEMENT_3, WM8400_ROP_ENA_SHIFT,
0650 0, &wm8400_dapm_ropmix_controls[0],
0651 ARRAY_SIZE(wm8400_dapm_ropmix_controls)),
0652
0653
0654 SND_SOC_DAPM_MIXER("RONMIX", WM8400_POWER_MANAGEMENT_3, WM8400_RON_ENA_SHIFT,
0655 0, &wm8400_dapm_ronmix_controls[0],
0656 ARRAY_SIZE(wm8400_dapm_ronmix_controls)),
0657
0658
0659 SND_SOC_DAPM_MIXER_E("ROMIX", WM8400_POWER_MANAGEMENT_3,
0660 WM8400_ROMIX_ENA_SHIFT,
0661 0, &wm8400_dapm_romix_controls[0],
0662 ARRAY_SIZE(wm8400_dapm_romix_controls),
0663 outmixer_event, SND_SOC_DAPM_PRE_REG),
0664
0665
0666 SND_SOC_DAPM_PGA("LOUT PGA", WM8400_POWER_MANAGEMENT_1, WM8400_LOUT_ENA_SHIFT,
0667 0, NULL, 0),
0668
0669
0670 SND_SOC_DAPM_PGA("ROUT PGA", WM8400_POWER_MANAGEMENT_1, WM8400_ROUT_ENA_SHIFT,
0671 0, NULL, 0),
0672
0673
0674 SND_SOC_DAPM_PGA("LOPGA", WM8400_POWER_MANAGEMENT_3, WM8400_LOPGA_ENA_SHIFT, 0,
0675 NULL, 0),
0676
0677
0678 SND_SOC_DAPM_PGA("ROPGA", WM8400_POWER_MANAGEMENT_3, WM8400_ROPGA_ENA_SHIFT, 0,
0679 NULL, 0),
0680
0681
0682 SND_SOC_DAPM_SUPPLY("MICBIAS", WM8400_POWER_MANAGEMENT_1,
0683 WM8400_MIC1BIAS_ENA_SHIFT, 0, NULL, 0),
0684
0685 SND_SOC_DAPM_OUTPUT("LON"),
0686 SND_SOC_DAPM_OUTPUT("LOP"),
0687 SND_SOC_DAPM_OUTPUT("OUT3"),
0688 SND_SOC_DAPM_OUTPUT("LOUT"),
0689 SND_SOC_DAPM_OUTPUT("SPKN"),
0690 SND_SOC_DAPM_OUTPUT("SPKP"),
0691 SND_SOC_DAPM_OUTPUT("ROUT"),
0692 SND_SOC_DAPM_OUTPUT("OUT4"),
0693 SND_SOC_DAPM_OUTPUT("ROP"),
0694 SND_SOC_DAPM_OUTPUT("RON"),
0695
0696 SND_SOC_DAPM_OUTPUT("Internal DAC Sink"),
0697 };
0698
0699 static const struct snd_soc_dapm_route wm8400_dapm_routes[] = {
0700
0701 {"Internal DAC Sink", NULL, "Left DAC"},
0702 {"Internal DAC Sink", NULL, "Right DAC"},
0703
0704
0705
0706 {"Left ADC", NULL, "Internal ADC Source"},
0707 {"Right ADC", NULL, "Internal ADC Source"},
0708
0709
0710
0711 {"LIN12 PGA", "LIN1 Switch", "LIN1"},
0712 {"LIN12 PGA", "LIN2 Switch", "LIN2"},
0713
0714 {"LIN34 PGA", "LIN3 Switch", "LIN3"},
0715 {"LIN34 PGA", "LIN4 Switch", "LIN4/RXN"},
0716
0717 {"INMIXL", NULL, "INL"},
0718 {"INMIXL", "Record Left Volume", "LOMIX"},
0719 {"INMIXL", "LIN2 Volume", "LIN2"},
0720 {"INMIXL", "LINPGA12 Switch", "LIN12 PGA"},
0721 {"INMIXL", "LINPGA34 Switch", "LIN34 PGA"},
0722
0723 {"AILNMUX", NULL, "INL"},
0724 {"AILNMUX", "INMIXL Mix", "INMIXL"},
0725 {"AILNMUX", "DIFFINL Mix", "LIN12 PGA"},
0726 {"AILNMUX", "DIFFINL Mix", "LIN34 PGA"},
0727 {"AILNMUX", "RXVOICE Mix", "LIN4/RXN"},
0728 {"AILNMUX", "RXVOICE Mix", "RIN4/RXP"},
0729
0730 {"Left ADC", NULL, "AILNMUX"},
0731
0732
0733 {"RIN12 PGA", "RIN1 Switch", "RIN1"},
0734 {"RIN12 PGA", "RIN2 Switch", "RIN2"},
0735
0736 {"RIN34 PGA", "RIN3 Switch", "RIN3"},
0737 {"RIN34 PGA", "RIN4 Switch", "RIN4/RXP"},
0738
0739 {"INMIXR", NULL, "INR"},
0740 {"INMIXR", "Record Right Volume", "ROMIX"},
0741 {"INMIXR", "RIN2 Volume", "RIN2"},
0742 {"INMIXR", "RINPGA12 Switch", "RIN12 PGA"},
0743 {"INMIXR", "RINPGA34 Switch", "RIN34 PGA"},
0744
0745 {"AIRNMUX", NULL, "INR"},
0746 {"AIRNMUX", "INMIXR Mix", "INMIXR"},
0747 {"AIRNMUX", "DIFFINR Mix", "RIN12 PGA"},
0748 {"AIRNMUX", "DIFFINR Mix", "RIN34 PGA"},
0749 {"AIRNMUX", "RXVOICE Mix", "LIN4/RXN"},
0750 {"AIRNMUX", "RXVOICE Mix", "RIN4/RXP"},
0751
0752 {"Right ADC", NULL, "AIRNMUX"},
0753
0754
0755 {"LOMIX", "LOMIX RIN3 Bypass Switch", "RIN3"},
0756 {"LOMIX", "LOMIX LIN3 Bypass Switch", "LIN3"},
0757 {"LOMIX", "LOMIX LIN12 PGA Bypass Switch", "LIN12 PGA"},
0758 {"LOMIX", "LOMIX RIN12 PGA Bypass Switch", "RIN12 PGA"},
0759 {"LOMIX", "LOMIX Right ADC Bypass Switch", "AIRNMUX"},
0760 {"LOMIX", "LOMIX Left ADC Bypass Switch", "AILNMUX"},
0761 {"LOMIX", "LOMIX Left DAC Switch", "Left DAC"},
0762
0763
0764 {"ROMIX", "ROMIX RIN3 Bypass Switch", "RIN3"},
0765 {"ROMIX", "ROMIX LIN3 Bypass Switch", "LIN3"},
0766 {"ROMIX", "ROMIX LIN12 PGA Bypass Switch", "LIN12 PGA"},
0767 {"ROMIX", "ROMIX RIN12 PGA Bypass Switch", "RIN12 PGA"},
0768 {"ROMIX", "ROMIX Right ADC Bypass Switch", "AIRNMUX"},
0769 {"ROMIX", "ROMIX Left ADC Bypass Switch", "AILNMUX"},
0770 {"ROMIX", "ROMIX Right DAC Switch", "Right DAC"},
0771
0772
0773 {"SPKMIX", "SPKMIX LIN2 Bypass Switch", "LIN2"},
0774 {"SPKMIX", "SPKMIX RIN2 Bypass Switch", "RIN2"},
0775 {"SPKMIX", "SPKMIX LADC Bypass Switch", "AILNMUX"},
0776 {"SPKMIX", "SPKMIX RADC Bypass Switch", "AIRNMUX"},
0777 {"SPKMIX", "SPKMIX Left Mixer PGA Switch", "LOPGA"},
0778 {"SPKMIX", "SPKMIX Right Mixer PGA Switch", "ROPGA"},
0779 {"SPKMIX", "SPKMIX Right DAC Switch", "Right DAC"},
0780 {"SPKMIX", "SPKMIX Left DAC Switch", "Right DAC"},
0781
0782
0783 {"LONMIX", "LONMIX Left Mixer PGA Switch", "LOPGA"},
0784 {"LONMIX", "LONMIX Right Mixer PGA Switch", "ROPGA"},
0785 {"LONMIX", "LONMIX Inverted LOP Switch", "LOPMIX"},
0786
0787
0788 {"LOPMIX", "LOPMIX Right Mic Bypass Switch", "RIN12 PGA"},
0789 {"LOPMIX", "LOPMIX Left Mic Bypass Switch", "LIN12 PGA"},
0790 {"LOPMIX", "LOPMIX Left Mixer PGA Switch", "LOPGA"},
0791
0792
0793 {"OUT3MIX", "OUT3MIX LIN4/RXP Bypass Switch", "LIN4/RXN"},
0794 {"OUT3MIX", "OUT3MIX Left Out PGA Switch", "LOPGA"},
0795
0796
0797 {"OUT4MIX", "OUT4MIX Right Out PGA Switch", "ROPGA"},
0798 {"OUT4MIX", "OUT4MIX RIN4/RXP Bypass Switch", "RIN4/RXP"},
0799
0800
0801 {"RONMIX", "RONMIX Right Mixer PGA Switch", "ROPGA"},
0802 {"RONMIX", "RONMIX Left Mixer PGA Switch", "LOPGA"},
0803 {"RONMIX", "RONMIX Inverted ROP Switch", "ROPMIX"},
0804
0805
0806 {"ROPMIX", "ROPMIX Left Mic Bypass Switch", "LIN12 PGA"},
0807 {"ROPMIX", "ROPMIX Right Mic Bypass Switch", "RIN12 PGA"},
0808 {"ROPMIX", "ROPMIX Right Mixer PGA Switch", "ROPGA"},
0809
0810
0811 {"LOPGA", NULL, "LOMIX"},
0812 {"ROPGA", NULL, "ROMIX"},
0813
0814 {"LOUT PGA", NULL, "LOMIX"},
0815 {"ROUT PGA", NULL, "ROMIX"},
0816
0817
0818 {"LON", NULL, "LONMIX"},
0819 {"LOP", NULL, "LOPMIX"},
0820 {"OUT3", NULL, "OUT3MIX"},
0821 {"LOUT", NULL, "LOUT PGA"},
0822 {"SPKN", NULL, "SPKMIX"},
0823 {"ROUT", NULL, "ROUT PGA"},
0824 {"OUT4", NULL, "OUT4MIX"},
0825 {"ROP", NULL, "ROPMIX"},
0826 {"RON", NULL, "RONMIX"},
0827 };
0828
0829
0830
0831
0832 static int wm8400_set_dai_sysclk(struct snd_soc_dai *codec_dai,
0833 int clk_id, unsigned int freq, int dir)
0834 {
0835 struct snd_soc_component *component = codec_dai->component;
0836 struct wm8400_priv *wm8400 = snd_soc_component_get_drvdata(component);
0837
0838 wm8400->sysclk = freq;
0839 return 0;
0840 }
0841
0842 struct fll_factors {
0843 u16 n;
0844 u16 k;
0845 u16 outdiv;
0846 u16 fratio;
0847 u16 freq_ref;
0848 };
0849
0850 #define FIXED_FLL_SIZE ((1 << 16) * 10)
0851
0852 static int fll_factors(struct wm8400_priv *wm8400, struct fll_factors *factors,
0853 unsigned int Fref, unsigned int Fout)
0854 {
0855 u64 Kpart;
0856 unsigned int K, Nmod, target;
0857
0858 factors->outdiv = 2;
0859 while (Fout * factors->outdiv < 90000000 ||
0860 Fout * factors->outdiv > 100000000) {
0861 factors->outdiv *= 2;
0862 if (factors->outdiv > 32) {
0863 dev_err(wm8400->wm8400->dev,
0864 "Unsupported FLL output frequency %uHz\n",
0865 Fout);
0866 return -EINVAL;
0867 }
0868 }
0869 target = Fout * factors->outdiv;
0870 factors->outdiv = factors->outdiv >> 2;
0871
0872 if (Fref < 48000)
0873 factors->freq_ref = 1;
0874 else
0875 factors->freq_ref = 0;
0876
0877 if (Fref < 1000000)
0878 factors->fratio = 9;
0879 else
0880 factors->fratio = 0;
0881
0882
0883 do {
0884 if (Fref < 1000000)
0885 factors->fratio--;
0886 else
0887 factors->fratio++;
0888
0889 if (factors->fratio < 1 || factors->fratio > 8) {
0890 dev_err(wm8400->wm8400->dev,
0891 "Unable to calculate FRATIO\n");
0892 return -EINVAL;
0893 }
0894
0895 factors->n = target / (Fref * factors->fratio);
0896 Nmod = target % (Fref * factors->fratio);
0897 } while (Nmod == 0);
0898
0899
0900 Kpart = FIXED_FLL_SIZE * (long long)Nmod;
0901
0902 do_div(Kpart, (Fref * factors->fratio));
0903
0904 K = Kpart & 0xFFFFFFFF;
0905
0906 if ((K % 10) >= 5)
0907 K += 5;
0908
0909
0910 factors->k = K / 10;
0911
0912 dev_dbg(wm8400->wm8400->dev,
0913 "FLL: Fref=%u Fout=%u N=%x K=%x, FRATIO=%x OUTDIV=%x\n",
0914 Fref, Fout,
0915 factors->n, factors->k, factors->fratio, factors->outdiv);
0916
0917 return 0;
0918 }
0919
0920 static int wm8400_set_dai_pll(struct snd_soc_dai *codec_dai, int pll_id,
0921 int source, unsigned int freq_in,
0922 unsigned int freq_out)
0923 {
0924 struct snd_soc_component *component = codec_dai->component;
0925 struct wm8400_priv *wm8400 = snd_soc_component_get_drvdata(component);
0926 struct fll_factors factors;
0927 int ret;
0928 u16 reg;
0929
0930 if (freq_in == wm8400->fll_in && freq_out == wm8400->fll_out)
0931 return 0;
0932
0933 if (freq_out) {
0934 ret = fll_factors(wm8400, &factors, freq_in, freq_out);
0935 if (ret != 0)
0936 return ret;
0937 } else {
0938
0939
0940
0941 memset(&factors, 0, sizeof(factors));
0942 }
0943
0944 wm8400->fll_out = freq_out;
0945 wm8400->fll_in = freq_in;
0946
0947
0948 reg = snd_soc_component_read(component, WM8400_POWER_MANAGEMENT_2);
0949 reg &= ~WM8400_FLL_ENA;
0950 snd_soc_component_write(component, WM8400_POWER_MANAGEMENT_2, reg);
0951
0952 reg = snd_soc_component_read(component, WM8400_FLL_CONTROL_1);
0953 reg &= ~WM8400_FLL_OSC_ENA;
0954 snd_soc_component_write(component, WM8400_FLL_CONTROL_1, reg);
0955
0956 if (!freq_out)
0957 return 0;
0958
0959 reg &= ~(WM8400_FLL_REF_FREQ | WM8400_FLL_FRATIO_MASK);
0960 reg |= WM8400_FLL_FRAC | factors.fratio;
0961 reg |= factors.freq_ref << WM8400_FLL_REF_FREQ_SHIFT;
0962 snd_soc_component_write(component, WM8400_FLL_CONTROL_1, reg);
0963
0964 snd_soc_component_write(component, WM8400_FLL_CONTROL_2, factors.k);
0965 snd_soc_component_write(component, WM8400_FLL_CONTROL_3, factors.n);
0966
0967 reg = snd_soc_component_read(component, WM8400_FLL_CONTROL_4);
0968 reg &= ~WM8400_FLL_OUTDIV_MASK;
0969 reg |= factors.outdiv;
0970 snd_soc_component_write(component, WM8400_FLL_CONTROL_4, reg);
0971
0972 return 0;
0973 }
0974
0975
0976
0977
0978 static int wm8400_set_dai_fmt(struct snd_soc_dai *codec_dai,
0979 unsigned int fmt)
0980 {
0981 struct snd_soc_component *component = codec_dai->component;
0982 u16 audio1, audio3;
0983
0984 audio1 = snd_soc_component_read(component, WM8400_AUDIO_INTERFACE_1);
0985 audio3 = snd_soc_component_read(component, WM8400_AUDIO_INTERFACE_3);
0986
0987
0988 switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
0989 case SND_SOC_DAIFMT_CBS_CFS:
0990 audio3 &= ~WM8400_AIF_MSTR1;
0991 break;
0992 case SND_SOC_DAIFMT_CBM_CFM:
0993 audio3 |= WM8400_AIF_MSTR1;
0994 break;
0995 default:
0996 return -EINVAL;
0997 }
0998
0999 audio1 &= ~WM8400_AIF_FMT_MASK;
1000
1001
1002 switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
1003 case SND_SOC_DAIFMT_I2S:
1004 audio1 |= WM8400_AIF_FMT_I2S;
1005 audio1 &= ~WM8400_AIF_LRCLK_INV;
1006 break;
1007 case SND_SOC_DAIFMT_RIGHT_J:
1008 audio1 |= WM8400_AIF_FMT_RIGHTJ;
1009 audio1 &= ~WM8400_AIF_LRCLK_INV;
1010 break;
1011 case SND_SOC_DAIFMT_LEFT_J:
1012 audio1 |= WM8400_AIF_FMT_LEFTJ;
1013 audio1 &= ~WM8400_AIF_LRCLK_INV;
1014 break;
1015 case SND_SOC_DAIFMT_DSP_A:
1016 audio1 |= WM8400_AIF_FMT_DSP;
1017 audio1 &= ~WM8400_AIF_LRCLK_INV;
1018 break;
1019 case SND_SOC_DAIFMT_DSP_B:
1020 audio1 |= WM8400_AIF_FMT_DSP | WM8400_AIF_LRCLK_INV;
1021 break;
1022 default:
1023 return -EINVAL;
1024 }
1025
1026 snd_soc_component_write(component, WM8400_AUDIO_INTERFACE_1, audio1);
1027 snd_soc_component_write(component, WM8400_AUDIO_INTERFACE_3, audio3);
1028 return 0;
1029 }
1030
1031 static int wm8400_set_dai_clkdiv(struct snd_soc_dai *codec_dai,
1032 int div_id, int div)
1033 {
1034 struct snd_soc_component *component = codec_dai->component;
1035 u16 reg;
1036
1037 switch (div_id) {
1038 case WM8400_MCLK_DIV:
1039 reg = snd_soc_component_read(component, WM8400_CLOCKING_2) &
1040 ~WM8400_MCLK_DIV_MASK;
1041 snd_soc_component_write(component, WM8400_CLOCKING_2, reg | div);
1042 break;
1043 case WM8400_DACCLK_DIV:
1044 reg = snd_soc_component_read(component, WM8400_CLOCKING_2) &
1045 ~WM8400_DAC_CLKDIV_MASK;
1046 snd_soc_component_write(component, WM8400_CLOCKING_2, reg | div);
1047 break;
1048 case WM8400_ADCCLK_DIV:
1049 reg = snd_soc_component_read(component, WM8400_CLOCKING_2) &
1050 ~WM8400_ADC_CLKDIV_MASK;
1051 snd_soc_component_write(component, WM8400_CLOCKING_2, reg | div);
1052 break;
1053 case WM8400_BCLK_DIV:
1054 reg = snd_soc_component_read(component, WM8400_CLOCKING_1) &
1055 ~WM8400_BCLK_DIV_MASK;
1056 snd_soc_component_write(component, WM8400_CLOCKING_1, reg | div);
1057 break;
1058 default:
1059 return -EINVAL;
1060 }
1061
1062 return 0;
1063 }
1064
1065
1066
1067
1068 static int wm8400_hw_params(struct snd_pcm_substream *substream,
1069 struct snd_pcm_hw_params *params,
1070 struct snd_soc_dai *dai)
1071 {
1072 struct snd_soc_component *component = dai->component;
1073 u16 audio1 = snd_soc_component_read(component, WM8400_AUDIO_INTERFACE_1);
1074
1075 audio1 &= ~WM8400_AIF_WL_MASK;
1076
1077 switch (params_width(params)) {
1078 case 16:
1079 break;
1080 case 20:
1081 audio1 |= WM8400_AIF_WL_20BITS;
1082 break;
1083 case 24:
1084 audio1 |= WM8400_AIF_WL_24BITS;
1085 break;
1086 case 32:
1087 audio1 |= WM8400_AIF_WL_32BITS;
1088 break;
1089 }
1090
1091 snd_soc_component_write(component, WM8400_AUDIO_INTERFACE_1, audio1);
1092 return 0;
1093 }
1094
1095 static int wm8400_mute(struct snd_soc_dai *dai, int mute, int direction)
1096 {
1097 struct snd_soc_component *component = dai->component;
1098 u16 val = snd_soc_component_read(component, WM8400_DAC_CTRL) & ~WM8400_DAC_MUTE;
1099
1100 if (mute)
1101 snd_soc_component_write(component, WM8400_DAC_CTRL, val | WM8400_DAC_MUTE);
1102 else
1103 snd_soc_component_write(component, WM8400_DAC_CTRL, val);
1104
1105 return 0;
1106 }
1107
1108
1109 static int wm8400_set_bias_level(struct snd_soc_component *component,
1110 enum snd_soc_bias_level level)
1111 {
1112 struct wm8400_priv *wm8400 = snd_soc_component_get_drvdata(component);
1113 u16 val;
1114 int ret;
1115
1116 switch (level) {
1117 case SND_SOC_BIAS_ON:
1118 break;
1119
1120 case SND_SOC_BIAS_PREPARE:
1121
1122 val = snd_soc_component_read(component, WM8400_POWER_MANAGEMENT_1) &
1123 ~WM8400_VMID_MODE_MASK;
1124 snd_soc_component_write(component, WM8400_POWER_MANAGEMENT_1, val | 0x2);
1125 break;
1126
1127 case SND_SOC_BIAS_STANDBY:
1128 if (snd_soc_component_get_bias_level(component) == SND_SOC_BIAS_OFF) {
1129 ret = regulator_bulk_enable(ARRAY_SIZE(power),
1130 &power[0]);
1131 if (ret != 0) {
1132 dev_err(wm8400->wm8400->dev,
1133 "Failed to enable regulators: %d\n",
1134 ret);
1135 return ret;
1136 }
1137
1138 snd_soc_component_write(component, WM8400_POWER_MANAGEMENT_1,
1139 WM8400_CODEC_ENA | WM8400_SYSCLK_ENA);
1140
1141
1142 snd_soc_component_write(component, WM8400_ANTIPOP2, WM8400_SOFTST |
1143 WM8400_BUFDCOPEN | WM8400_POBCTRL);
1144
1145 msleep(50);
1146
1147
1148 val = snd_soc_component_read(component, WM8400_POWER_MANAGEMENT_1);
1149 val |= 0x2 | WM8400_VREF_ENA;
1150 snd_soc_component_write(component, WM8400_POWER_MANAGEMENT_1, val);
1151
1152
1153 snd_soc_component_write(component, WM8400_ANTIPOP2, WM8400_SOFTST |
1154 WM8400_BUFDCOPEN | WM8400_POBCTRL |
1155 WM8400_BUFIOEN);
1156
1157
1158 snd_soc_component_write(component, WM8400_ANTIPOP2, WM8400_BUFIOEN);
1159 }
1160
1161
1162 val = snd_soc_component_read(component, WM8400_POWER_MANAGEMENT_1) &
1163 ~WM8400_VMID_MODE_MASK;
1164 snd_soc_component_write(component, WM8400_POWER_MANAGEMENT_1, val | 0x4);
1165 break;
1166
1167 case SND_SOC_BIAS_OFF:
1168
1169 snd_soc_component_write(component, WM8400_ANTIPOP2, WM8400_SOFTST |
1170 WM8400_POBCTRL | WM8400_BUFIOEN);
1171
1172
1173 snd_soc_component_write(component, WM8400_ANTIPOP2, WM8400_SOFTST |
1174 WM8400_BUFDCOPEN | WM8400_POBCTRL |
1175 WM8400_BUFIOEN);
1176
1177
1178 val = snd_soc_component_read(component, WM8400_DAC_CTRL);
1179 snd_soc_component_write(component, WM8400_DAC_CTRL, val | WM8400_DAC_MUTE);
1180
1181
1182 val = snd_soc_component_read(component, WM8400_POWER_MANAGEMENT_1);
1183 val |= WM8400_SPK_ENA | WM8400_OUT3_ENA |
1184 WM8400_OUT4_ENA | WM8400_LOUT_ENA |
1185 WM8400_ROUT_ENA;
1186 snd_soc_component_write(component, WM8400_POWER_MANAGEMENT_1, val);
1187
1188
1189 val &= ~WM8400_VMID_MODE_MASK;
1190 snd_soc_component_write(component, WM8400_POWER_MANAGEMENT_1, val);
1191
1192 msleep(300);
1193
1194
1195 snd_soc_component_write(component, WM8400_ANTIPOP1, WM8400_DIS_LLINE |
1196 WM8400_DIS_RLINE | WM8400_DIS_OUT3 |
1197 WM8400_DIS_OUT4 | WM8400_DIS_LOUT |
1198 WM8400_DIS_ROUT);
1199
1200
1201 val &= ~WM8400_VREF_ENA;
1202 snd_soc_component_write(component, WM8400_POWER_MANAGEMENT_1, val);
1203
1204
1205 snd_soc_component_write(component, WM8400_ANTIPOP2, 0x0);
1206
1207 ret = regulator_bulk_disable(ARRAY_SIZE(power),
1208 &power[0]);
1209 if (ret != 0)
1210 return ret;
1211
1212 break;
1213 }
1214
1215 return 0;
1216 }
1217
1218 #define WM8400_RATES SNDRV_PCM_RATE_8000_96000
1219
1220 #define WM8400_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE |\
1221 SNDRV_PCM_FMTBIT_S24_LE)
1222
1223 static const struct snd_soc_dai_ops wm8400_dai_ops = {
1224 .hw_params = wm8400_hw_params,
1225 .mute_stream = wm8400_mute,
1226 .set_fmt = wm8400_set_dai_fmt,
1227 .set_clkdiv = wm8400_set_dai_clkdiv,
1228 .set_sysclk = wm8400_set_dai_sysclk,
1229 .set_pll = wm8400_set_dai_pll,
1230 .no_capture_mute = 1,
1231 };
1232
1233
1234
1235
1236
1237
1238
1239
1240 static struct snd_soc_dai_driver wm8400_dai = {
1241
1242 .name = "wm8400-hifi",
1243 .playback = {
1244 .stream_name = "Playback",
1245 .channels_min = 1,
1246 .channels_max = 2,
1247 .rates = WM8400_RATES,
1248 .formats = WM8400_FORMATS,
1249 },
1250 .capture = {
1251 .stream_name = "Capture",
1252 .channels_min = 1,
1253 .channels_max = 2,
1254 .rates = WM8400_RATES,
1255 .formats = WM8400_FORMATS,
1256 },
1257 .ops = &wm8400_dai_ops,
1258 };
1259
1260 static int wm8400_component_probe(struct snd_soc_component *component)
1261 {
1262 struct wm8400 *wm8400 = dev_get_platdata(component->dev);
1263 struct wm8400_priv *priv;
1264 int ret;
1265 u16 reg;
1266
1267 priv = devm_kzalloc(component->dev, sizeof(struct wm8400_priv),
1268 GFP_KERNEL);
1269 if (priv == NULL)
1270 return -ENOMEM;
1271
1272 snd_soc_component_init_regmap(component, wm8400->regmap);
1273 snd_soc_component_set_drvdata(component, priv);
1274 priv->wm8400 = wm8400;
1275
1276 ret = devm_regulator_bulk_get(wm8400->dev,
1277 ARRAY_SIZE(power), &power[0]);
1278 if (ret != 0) {
1279 dev_err(component->dev, "Failed to get regulators: %d\n", ret);
1280 return ret;
1281 }
1282
1283 wm8400_component_reset(component);
1284
1285 reg = snd_soc_component_read(component, WM8400_POWER_MANAGEMENT_1);
1286 snd_soc_component_write(component, WM8400_POWER_MANAGEMENT_1, reg | WM8400_CODEC_ENA);
1287
1288
1289 reg = snd_soc_component_read(component, WM8400_LEFT_LINE_INPUT_1_2_VOLUME);
1290 snd_soc_component_write(component, WM8400_LEFT_LINE_INPUT_1_2_VOLUME,
1291 reg & WM8400_IPVU);
1292 reg = snd_soc_component_read(component, WM8400_RIGHT_LINE_INPUT_1_2_VOLUME);
1293 snd_soc_component_write(component, WM8400_RIGHT_LINE_INPUT_1_2_VOLUME,
1294 reg & WM8400_IPVU);
1295
1296 snd_soc_component_write(component, WM8400_LEFT_OUTPUT_VOLUME, 0x50 | (1<<8));
1297 snd_soc_component_write(component, WM8400_RIGHT_OUTPUT_VOLUME, 0x50 | (1<<8));
1298
1299 return 0;
1300 }
1301
1302 static void wm8400_component_remove(struct snd_soc_component *component)
1303 {
1304 u16 reg;
1305
1306 reg = snd_soc_component_read(component, WM8400_POWER_MANAGEMENT_1);
1307 snd_soc_component_write(component, WM8400_POWER_MANAGEMENT_1,
1308 reg & (~WM8400_CODEC_ENA));
1309 }
1310
1311 static const struct snd_soc_component_driver soc_component_dev_wm8400 = {
1312 .probe = wm8400_component_probe,
1313 .remove = wm8400_component_remove,
1314 .set_bias_level = wm8400_set_bias_level,
1315 .controls = wm8400_snd_controls,
1316 .num_controls = ARRAY_SIZE(wm8400_snd_controls),
1317 .dapm_widgets = wm8400_dapm_widgets,
1318 .num_dapm_widgets = ARRAY_SIZE(wm8400_dapm_widgets),
1319 .dapm_routes = wm8400_dapm_routes,
1320 .num_dapm_routes = ARRAY_SIZE(wm8400_dapm_routes),
1321 .suspend_bias_off = 1,
1322 .idle_bias_on = 1,
1323 .use_pmdown_time = 1,
1324 .endianness = 1,
1325 };
1326
1327 static int wm8400_probe(struct platform_device *pdev)
1328 {
1329 return devm_snd_soc_register_component(&pdev->dev,
1330 &soc_component_dev_wm8400,
1331 &wm8400_dai, 1);
1332 }
1333
1334 static struct platform_driver wm8400_codec_driver = {
1335 .driver = {
1336 .name = "wm8400-codec",
1337 },
1338 .probe = wm8400_probe,
1339 };
1340
1341 module_platform_driver(wm8400_codec_driver);
1342
1343 MODULE_DESCRIPTION("ASoC WM8400 driver");
1344 MODULE_AUTHOR("Mark Brown");
1345 MODULE_LICENSE("GPL");
1346 MODULE_ALIAS("platform:wm8400-codec");