0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011 #include <linux/module.h>
0012 #include <linux/moduleparam.h>
0013 #include <linux/kernel.h>
0014 #include <linux/init.h>
0015 #include <linux/delay.h>
0016 #include <linux/pm.h>
0017 #include <linux/i2c.h>
0018 #include <linux/regmap.h>
0019 #include <linux/slab.h>
0020 #include <sound/core.h>
0021 #include <sound/pcm.h>
0022 #include <sound/pcm_params.h>
0023 #include <sound/soc.h>
0024 #include <sound/initval.h>
0025 #include <sound/tlv.h>
0026 #include <asm/div64.h>
0027
0028 #include "wm8978.h"
0029
0030 static const struct reg_default wm8978_reg_defaults[] = {
0031 { 1, 0x0000 },
0032 { 2, 0x0000 },
0033 { 3, 0x0000 },
0034 { 4, 0x0050 },
0035 { 5, 0x0000 },
0036 { 6, 0x0140 },
0037 { 7, 0x0000 },
0038 { 8, 0x0000 },
0039 { 9, 0x0000 },
0040 { 10, 0x0000 },
0041 { 11, 0x00ff },
0042 { 12, 0x00ff },
0043 { 13, 0x0000 },
0044 { 14, 0x0100 },
0045 { 15, 0x00ff },
0046 { 16, 0x00ff },
0047 { 17, 0x0000 },
0048 { 18, 0x012c },
0049 { 19, 0x002c },
0050 { 20, 0x002c },
0051 { 21, 0x002c },
0052 { 22, 0x002c },
0053 { 23, 0x0000 },
0054 { 24, 0x0032 },
0055 { 25, 0x0000 },
0056 { 26, 0x0000 },
0057 { 27, 0x0000 },
0058 { 28, 0x0000 },
0059 { 29, 0x0000 },
0060 { 30, 0x0000 },
0061 { 31, 0x0000 },
0062 { 32, 0x0038 },
0063 { 33, 0x000b },
0064 { 34, 0x0032 },
0065 { 35, 0x0000 },
0066 { 36, 0x0008 },
0067 { 37, 0x000c },
0068 { 38, 0x0093 },
0069 { 39, 0x00e9 },
0070 { 40, 0x0000 },
0071 { 41, 0x0000 },
0072 { 42, 0x0000 },
0073 { 43, 0x0000 },
0074 { 44, 0x0033 },
0075 { 45, 0x0010 },
0076 { 46, 0x0010 },
0077 { 47, 0x0100 },
0078 { 48, 0x0100 },
0079 { 49, 0x0002 },
0080 { 50, 0x0001 },
0081 { 51, 0x0001 },
0082 { 52, 0x0039 },
0083 { 53, 0x0039 },
0084 { 54, 0x0039 },
0085 { 55, 0x0039 },
0086 { 56, 0x0001 },
0087 { 57, 0x0001 },
0088 };
0089
0090 static bool wm8978_volatile(struct device *dev, unsigned int reg)
0091 {
0092 return reg == WM8978_RESET;
0093 }
0094
0095
0096 struct wm8978_priv {
0097 struct regmap *regmap;
0098 unsigned int f_pllout;
0099 unsigned int f_mclk;
0100 unsigned int f_256fs;
0101 unsigned int f_opclk;
0102 int mclk_idx;
0103 enum wm8978_sysclk_src sysclk;
0104 };
0105
0106 static const char *wm8978_companding[] = {"Off", "NC", "u-law", "A-law"};
0107 static const char *wm8978_eqmode[] = {"Capture", "Playback"};
0108 static const char *wm8978_bw[] = {"Narrow", "Wide"};
0109 static const char *wm8978_eq1[] = {"80Hz", "105Hz", "135Hz", "175Hz"};
0110 static const char *wm8978_eq2[] = {"230Hz", "300Hz", "385Hz", "500Hz"};
0111 static const char *wm8978_eq3[] = {"650Hz", "850Hz", "1.1kHz", "1.4kHz"};
0112 static const char *wm8978_eq4[] = {"1.8kHz", "2.4kHz", "3.2kHz", "4.1kHz"};
0113 static const char *wm8978_eq5[] = {"5.3kHz", "6.9kHz", "9kHz", "11.7kHz"};
0114 static const char *wm8978_alc3[] = {"ALC", "Limiter"};
0115 static const char *wm8978_alc1[] = {"Off", "Right", "Left", "Both"};
0116
0117 static SOC_ENUM_SINGLE_DECL(adc_compand, WM8978_COMPANDING_CONTROL, 1,
0118 wm8978_companding);
0119 static SOC_ENUM_SINGLE_DECL(dac_compand, WM8978_COMPANDING_CONTROL, 3,
0120 wm8978_companding);
0121 static SOC_ENUM_SINGLE_DECL(eqmode, WM8978_EQ1, 8, wm8978_eqmode);
0122 static SOC_ENUM_SINGLE_DECL(eq1, WM8978_EQ1, 5, wm8978_eq1);
0123 static SOC_ENUM_SINGLE_DECL(eq2bw, WM8978_EQ2, 8, wm8978_bw);
0124 static SOC_ENUM_SINGLE_DECL(eq2, WM8978_EQ2, 5, wm8978_eq2);
0125 static SOC_ENUM_SINGLE_DECL(eq3bw, WM8978_EQ3, 8, wm8978_bw);
0126 static SOC_ENUM_SINGLE_DECL(eq3, WM8978_EQ3, 5, wm8978_eq3);
0127 static SOC_ENUM_SINGLE_DECL(eq4bw, WM8978_EQ4, 8, wm8978_bw);
0128 static SOC_ENUM_SINGLE_DECL(eq4, WM8978_EQ4, 5, wm8978_eq4);
0129 static SOC_ENUM_SINGLE_DECL(eq5, WM8978_EQ5, 5, wm8978_eq5);
0130 static SOC_ENUM_SINGLE_DECL(alc3, WM8978_ALC_CONTROL_3, 8, wm8978_alc3);
0131 static SOC_ENUM_SINGLE_DECL(alc1, WM8978_ALC_CONTROL_1, 7, wm8978_alc1);
0132
0133 static const DECLARE_TLV_DB_SCALE(digital_tlv, -12750, 50, 1);
0134 static const DECLARE_TLV_DB_SCALE(eq_tlv, -1200, 100, 0);
0135 static const DECLARE_TLV_DB_SCALE(inpga_tlv, -1200, 75, 0);
0136 static const DECLARE_TLV_DB_SCALE(spk_tlv, -5700, 100, 0);
0137 static const DECLARE_TLV_DB_SCALE(boost_tlv, -1500, 300, 1);
0138 static const DECLARE_TLV_DB_SCALE(limiter_tlv, 0, 100, 0);
0139
0140 static const struct snd_kcontrol_new wm8978_snd_controls[] = {
0141
0142 SOC_SINGLE("Digital Loopback Switch",
0143 WM8978_COMPANDING_CONTROL, 0, 1, 0),
0144
0145 SOC_ENUM("ADC Companding", adc_compand),
0146 SOC_ENUM("DAC Companding", dac_compand),
0147
0148 SOC_DOUBLE("DAC Inversion Switch", WM8978_DAC_CONTROL, 0, 1, 1, 0),
0149
0150 SOC_DOUBLE_R_TLV("PCM Volume",
0151 WM8978_LEFT_DAC_DIGITAL_VOLUME, WM8978_RIGHT_DAC_DIGITAL_VOLUME,
0152 0, 255, 0, digital_tlv),
0153
0154 SOC_SINGLE("High Pass Filter Switch", WM8978_ADC_CONTROL, 8, 1, 0),
0155 SOC_SINGLE("High Pass Cut Off", WM8978_ADC_CONTROL, 4, 7, 0),
0156 SOC_DOUBLE("ADC Inversion Switch", WM8978_ADC_CONTROL, 0, 1, 1, 0),
0157
0158 SOC_DOUBLE_R_TLV("ADC Volume",
0159 WM8978_LEFT_ADC_DIGITAL_VOLUME, WM8978_RIGHT_ADC_DIGITAL_VOLUME,
0160 0, 255, 0, digital_tlv),
0161
0162 SOC_ENUM("Equaliser Function", eqmode),
0163 SOC_ENUM("EQ1 Cut Off", eq1),
0164 SOC_SINGLE_TLV("EQ1 Volume", WM8978_EQ1, 0, 24, 1, eq_tlv),
0165
0166 SOC_ENUM("Equaliser EQ2 Bandwidth", eq2bw),
0167 SOC_ENUM("EQ2 Cut Off", eq2),
0168 SOC_SINGLE_TLV("EQ2 Volume", WM8978_EQ2, 0, 24, 1, eq_tlv),
0169
0170 SOC_ENUM("Equaliser EQ3 Bandwidth", eq3bw),
0171 SOC_ENUM("EQ3 Cut Off", eq3),
0172 SOC_SINGLE_TLV("EQ3 Volume", WM8978_EQ3, 0, 24, 1, eq_tlv),
0173
0174 SOC_ENUM("Equaliser EQ4 Bandwidth", eq4bw),
0175 SOC_ENUM("EQ4 Cut Off", eq4),
0176 SOC_SINGLE_TLV("EQ4 Volume", WM8978_EQ4, 0, 24, 1, eq_tlv),
0177
0178 SOC_ENUM("EQ5 Cut Off", eq5),
0179 SOC_SINGLE_TLV("EQ5 Volume", WM8978_EQ5, 0, 24, 1, eq_tlv),
0180
0181 SOC_SINGLE("DAC Playback Limiter Switch",
0182 WM8978_DAC_LIMITER_1, 8, 1, 0),
0183 SOC_SINGLE("DAC Playback Limiter Decay",
0184 WM8978_DAC_LIMITER_1, 4, 15, 0),
0185 SOC_SINGLE("DAC Playback Limiter Attack",
0186 WM8978_DAC_LIMITER_1, 0, 15, 0),
0187
0188 SOC_SINGLE("DAC Playback Limiter Threshold",
0189 WM8978_DAC_LIMITER_2, 4, 7, 0),
0190 SOC_SINGLE_TLV("DAC Playback Limiter Volume",
0191 WM8978_DAC_LIMITER_2, 0, 12, 0, limiter_tlv),
0192
0193 SOC_ENUM("ALC Enable Switch", alc1),
0194 SOC_SINGLE("ALC Capture Min Gain", WM8978_ALC_CONTROL_1, 0, 7, 0),
0195 SOC_SINGLE("ALC Capture Max Gain", WM8978_ALC_CONTROL_1, 3, 7, 0),
0196
0197 SOC_SINGLE("ALC Capture Hold", WM8978_ALC_CONTROL_2, 4, 10, 0),
0198 SOC_SINGLE("ALC Capture Target", WM8978_ALC_CONTROL_2, 0, 15, 0),
0199
0200 SOC_ENUM("ALC Capture Mode", alc3),
0201 SOC_SINGLE("ALC Capture Decay", WM8978_ALC_CONTROL_3, 4, 10, 0),
0202 SOC_SINGLE("ALC Capture Attack", WM8978_ALC_CONTROL_3, 0, 10, 0),
0203
0204 SOC_SINGLE("ALC Capture Noise Gate Switch", WM8978_NOISE_GATE, 3, 1, 0),
0205 SOC_SINGLE("ALC Capture Noise Gate Threshold",
0206 WM8978_NOISE_GATE, 0, 7, 0),
0207
0208 SOC_DOUBLE_R("Capture PGA ZC Switch",
0209 WM8978_LEFT_INP_PGA_CONTROL, WM8978_RIGHT_INP_PGA_CONTROL,
0210 7, 1, 0),
0211
0212
0213 SOC_DOUBLE_R("Headphone Playback ZC Switch",
0214 WM8978_LOUT1_HP_CONTROL, WM8978_ROUT1_HP_CONTROL, 7, 1, 0),
0215
0216 SOC_DOUBLE_R_TLV("Headphone Playback Volume",
0217 WM8978_LOUT1_HP_CONTROL, WM8978_ROUT1_HP_CONTROL,
0218 0, 63, 0, spk_tlv),
0219
0220
0221 SOC_DOUBLE_R("Speaker Playback ZC Switch",
0222 WM8978_LOUT2_SPK_CONTROL, WM8978_ROUT2_SPK_CONTROL, 7, 1, 0),
0223
0224 SOC_DOUBLE_R_TLV("Speaker Playback Volume",
0225 WM8978_LOUT2_SPK_CONTROL, WM8978_ROUT2_SPK_CONTROL,
0226 0, 63, 0, spk_tlv),
0227
0228
0229 SOC_DOUBLE_R("Line Playback Switch",
0230 WM8978_OUT3_MIXER_CONTROL, WM8978_OUT4_MIXER_CONTROL, 6, 1, 1),
0231
0232
0233 SOC_DOUBLE_R("PGA Boost (+20dB)",
0234 WM8978_LEFT_ADC_BOOST_CONTROL, WM8978_RIGHT_ADC_BOOST_CONTROL,
0235 8, 1, 0),
0236 SOC_DOUBLE_R_TLV("L2/R2 Boost Volume",
0237 WM8978_LEFT_ADC_BOOST_CONTROL, WM8978_RIGHT_ADC_BOOST_CONTROL,
0238 4, 7, 0, boost_tlv),
0239 SOC_DOUBLE_R_TLV("Aux Boost Volume",
0240 WM8978_LEFT_ADC_BOOST_CONTROL, WM8978_RIGHT_ADC_BOOST_CONTROL,
0241 0, 7, 0, boost_tlv),
0242
0243
0244 SOC_DOUBLE_R_TLV("Input PGA Volume",
0245 WM8978_LEFT_INP_PGA_CONTROL, WM8978_RIGHT_INP_PGA_CONTROL,
0246 0, 63, 0, inpga_tlv),
0247
0248
0249 SOC_DOUBLE_R("Headphone Switch",
0250 WM8978_LOUT1_HP_CONTROL, WM8978_ROUT1_HP_CONTROL, 6, 1, 1),
0251
0252
0253 SOC_DOUBLE_R("Speaker Switch",
0254 WM8978_LOUT2_SPK_CONTROL, WM8978_ROUT2_SPK_CONTROL, 6, 1, 1),
0255
0256
0257 SOC_SINGLE("DAC 128x Oversampling Switch", WM8978_DAC_CONTROL,
0258 5, 1, 0),
0259 SOC_SINGLE("ADC 128x Oversampling Switch", WM8978_ADC_CONTROL,
0260 5, 1, 0),
0261 };
0262
0263
0264 static const struct snd_kcontrol_new wm8978_left_out_mixer[] = {
0265 SOC_DAPM_SINGLE("Line Bypass Switch", WM8978_LEFT_MIXER_CONTROL, 1, 1, 0),
0266 SOC_DAPM_SINGLE("Aux Playback Switch", WM8978_LEFT_MIXER_CONTROL, 5, 1, 0),
0267 SOC_DAPM_SINGLE("PCM Playback Switch", WM8978_LEFT_MIXER_CONTROL, 0, 1, 0),
0268 };
0269
0270 static const struct snd_kcontrol_new wm8978_right_out_mixer[] = {
0271 SOC_DAPM_SINGLE("Line Bypass Switch", WM8978_RIGHT_MIXER_CONTROL, 1, 1, 0),
0272 SOC_DAPM_SINGLE("Aux Playback Switch", WM8978_RIGHT_MIXER_CONTROL, 5, 1, 0),
0273 SOC_DAPM_SINGLE("PCM Playback Switch", WM8978_RIGHT_MIXER_CONTROL, 0, 1, 0),
0274 };
0275
0276
0277
0278
0279 static const struct snd_kcontrol_new wm8978_left_input_mixer[] = {
0280 SOC_DAPM_SINGLE("L2 Switch", WM8978_INPUT_CONTROL, 2, 1, 0),
0281 SOC_DAPM_SINGLE("MicN Switch", WM8978_INPUT_CONTROL, 1, 1, 0),
0282 SOC_DAPM_SINGLE("MicP Switch", WM8978_INPUT_CONTROL, 0, 1, 0),
0283 };
0284 static const struct snd_kcontrol_new wm8978_right_input_mixer[] = {
0285 SOC_DAPM_SINGLE("R2 Switch", WM8978_INPUT_CONTROL, 6, 1, 0),
0286 SOC_DAPM_SINGLE("MicN Switch", WM8978_INPUT_CONTROL, 5, 1, 0),
0287 SOC_DAPM_SINGLE("MicP Switch", WM8978_INPUT_CONTROL, 4, 1, 0),
0288 };
0289
0290 static const struct snd_soc_dapm_widget wm8978_dapm_widgets[] = {
0291 SND_SOC_DAPM_DAC("Left DAC", "Left HiFi Playback",
0292 WM8978_POWER_MANAGEMENT_3, 0, 0),
0293 SND_SOC_DAPM_DAC("Right DAC", "Right HiFi Playback",
0294 WM8978_POWER_MANAGEMENT_3, 1, 0),
0295 SND_SOC_DAPM_ADC("Left ADC", "Left HiFi Capture",
0296 WM8978_POWER_MANAGEMENT_2, 0, 0),
0297 SND_SOC_DAPM_ADC("Right ADC", "Right HiFi Capture",
0298 WM8978_POWER_MANAGEMENT_2, 1, 0),
0299
0300
0301 SOC_MIXER_ARRAY("Left Output Mixer", WM8978_POWER_MANAGEMENT_3,
0302 2, 0, wm8978_left_out_mixer),
0303 SOC_MIXER_ARRAY("Right Output Mixer", WM8978_POWER_MANAGEMENT_3,
0304 3, 0, wm8978_right_out_mixer),
0305
0306 SOC_MIXER_ARRAY("Left Input Mixer", WM8978_POWER_MANAGEMENT_2,
0307 2, 0, wm8978_left_input_mixer),
0308 SOC_MIXER_ARRAY("Right Input Mixer", WM8978_POWER_MANAGEMENT_2,
0309 3, 0, wm8978_right_input_mixer),
0310
0311 SND_SOC_DAPM_PGA("Left Boost Mixer", WM8978_POWER_MANAGEMENT_2,
0312 4, 0, NULL, 0),
0313 SND_SOC_DAPM_PGA("Right Boost Mixer", WM8978_POWER_MANAGEMENT_2,
0314 5, 0, NULL, 0),
0315
0316 SND_SOC_DAPM_PGA("Left Capture PGA", WM8978_LEFT_INP_PGA_CONTROL,
0317 6, 1, NULL, 0),
0318 SND_SOC_DAPM_PGA("Right Capture PGA", WM8978_RIGHT_INP_PGA_CONTROL,
0319 6, 1, NULL, 0),
0320
0321 SND_SOC_DAPM_PGA("Left Headphone Out", WM8978_POWER_MANAGEMENT_2,
0322 7, 0, NULL, 0),
0323 SND_SOC_DAPM_PGA("Right Headphone Out", WM8978_POWER_MANAGEMENT_2,
0324 8, 0, NULL, 0),
0325
0326 SND_SOC_DAPM_PGA("Left Speaker Out", WM8978_POWER_MANAGEMENT_3,
0327 6, 0, NULL, 0),
0328 SND_SOC_DAPM_PGA("Right Speaker Out", WM8978_POWER_MANAGEMENT_3,
0329 5, 0, NULL, 0),
0330
0331 SND_SOC_DAPM_MIXER("OUT4 VMID", WM8978_POWER_MANAGEMENT_3,
0332 8, 0, NULL, 0),
0333
0334 SND_SOC_DAPM_MICBIAS("Mic Bias", WM8978_POWER_MANAGEMENT_1, 4, 0),
0335
0336 SND_SOC_DAPM_INPUT("LMICN"),
0337 SND_SOC_DAPM_INPUT("LMICP"),
0338 SND_SOC_DAPM_INPUT("RMICN"),
0339 SND_SOC_DAPM_INPUT("RMICP"),
0340 SND_SOC_DAPM_INPUT("LAUX"),
0341 SND_SOC_DAPM_INPUT("RAUX"),
0342 SND_SOC_DAPM_INPUT("L2"),
0343 SND_SOC_DAPM_INPUT("R2"),
0344 SND_SOC_DAPM_OUTPUT("LHP"),
0345 SND_SOC_DAPM_OUTPUT("RHP"),
0346 SND_SOC_DAPM_OUTPUT("LSPK"),
0347 SND_SOC_DAPM_OUTPUT("RSPK"),
0348 };
0349
0350 static const struct snd_soc_dapm_route wm8978_dapm_routes[] = {
0351
0352 {"Right Output Mixer", "PCM Playback Switch", "Right DAC"},
0353 {"Right Output Mixer", "Aux Playback Switch", "RAUX"},
0354 {"Right Output Mixer", "Line Bypass Switch", "Right Boost Mixer"},
0355
0356 {"Left Output Mixer", "PCM Playback Switch", "Left DAC"},
0357 {"Left Output Mixer", "Aux Playback Switch", "LAUX"},
0358 {"Left Output Mixer", "Line Bypass Switch", "Left Boost Mixer"},
0359
0360
0361 {"Right Headphone Out", NULL, "Right Output Mixer"},
0362 {"RHP", NULL, "Right Headphone Out"},
0363
0364 {"Left Headphone Out", NULL, "Left Output Mixer"},
0365 {"LHP", NULL, "Left Headphone Out"},
0366
0367 {"Right Speaker Out", NULL, "Right Output Mixer"},
0368 {"RSPK", NULL, "Right Speaker Out"},
0369
0370 {"Left Speaker Out", NULL, "Left Output Mixer"},
0371 {"LSPK", NULL, "Left Speaker Out"},
0372
0373
0374 {"Right ADC", NULL, "Right Boost Mixer"},
0375
0376 {"Right Boost Mixer", NULL, "RAUX"},
0377 {"Right Boost Mixer", NULL, "Right Capture PGA"},
0378 {"Right Boost Mixer", NULL, "R2"},
0379
0380 {"Left ADC", NULL, "Left Boost Mixer"},
0381
0382 {"Left Boost Mixer", NULL, "LAUX"},
0383 {"Left Boost Mixer", NULL, "Left Capture PGA"},
0384 {"Left Boost Mixer", NULL, "L2"},
0385
0386
0387 {"Right Capture PGA", NULL, "Right Input Mixer"},
0388 {"Left Capture PGA", NULL, "Left Input Mixer"},
0389
0390 {"Right Input Mixer", "R2 Switch", "R2"},
0391 {"Right Input Mixer", "MicN Switch", "RMICN"},
0392 {"Right Input Mixer", "MicP Switch", "RMICP"},
0393
0394 {"Left Input Mixer", "L2 Switch", "L2"},
0395 {"Left Input Mixer", "MicN Switch", "LMICN"},
0396 {"Left Input Mixer", "MicP Switch", "LMICP"},
0397 };
0398
0399
0400 struct wm8978_pll_div {
0401 u32 k;
0402 u8 n;
0403 u8 div2;
0404 };
0405
0406 #define FIXED_PLL_SIZE (1 << 24)
0407
0408 static void pll_factors(struct snd_soc_component *component,
0409 struct wm8978_pll_div *pll_div, unsigned int target, unsigned int source)
0410 {
0411 u64 k_part;
0412 unsigned int k, n_div, n_mod;
0413
0414 n_div = target / source;
0415 if (n_div < 6) {
0416 source >>= 1;
0417 pll_div->div2 = 1;
0418 n_div = target / source;
0419 } else {
0420 pll_div->div2 = 0;
0421 }
0422
0423 if (n_div < 6 || n_div > 12)
0424 dev_warn(component->dev,
0425 "WM8978 N value exceeds recommended range! N = %u\n",
0426 n_div);
0427
0428 pll_div->n = n_div;
0429 n_mod = target - source * n_div;
0430 k_part = FIXED_PLL_SIZE * (long long)n_mod + source / 2;
0431
0432 do_div(k_part, source);
0433
0434 k = k_part & 0xFFFFFFFF;
0435
0436 pll_div->k = k;
0437 }
0438
0439
0440 static const int mclk_numerator[] = {1, 3, 2, 3, 4, 6, 8, 12};
0441 static const int mclk_denominator[] = {1, 2, 1, 1, 1, 1, 1, 1};
0442
0443
0444
0445
0446
0447
0448
0449
0450 static int wm8978_enum_mclk(unsigned int f_out, unsigned int f_mclk,
0451 unsigned int *f_pllout)
0452 {
0453 int i;
0454
0455 for (i = 0; i < ARRAY_SIZE(mclk_numerator); i++) {
0456 unsigned int f_pllout_x4 = 4 * f_out * mclk_numerator[i] /
0457 mclk_denominator[i];
0458 if (3 * f_mclk <= f_pllout_x4 && f_pllout_x4 < 13 * f_mclk) {
0459 *f_pllout = f_pllout_x4 / 4;
0460 return i;
0461 }
0462 }
0463
0464 return -EINVAL;
0465 }
0466
0467
0468
0469
0470
0471 static int wm8978_configure_pll(struct snd_soc_component *component)
0472 {
0473 struct wm8978_priv *wm8978 = snd_soc_component_get_drvdata(component);
0474 struct wm8978_pll_div pll_div;
0475 unsigned int f_opclk = wm8978->f_opclk, f_mclk = wm8978->f_mclk,
0476 f_256fs = wm8978->f_256fs;
0477 unsigned int f2;
0478
0479 if (!f_mclk)
0480 return -EINVAL;
0481
0482 if (f_opclk) {
0483 unsigned int opclk_div;
0484
0485 wm8978->mclk_idx = -1;
0486
0487
0488
0489
0490
0491
0492
0493
0494
0495
0496 if (16 * f_opclk < 3 * f_mclk || 4 * f_opclk >= 13 * f_mclk)
0497 return -EINVAL;
0498
0499 if (4 * f_opclk < 3 * f_mclk)
0500
0501 opclk_div = (3 * f_mclk / 4 + f_opclk - 1) / f_opclk;
0502 else
0503 opclk_div = 1;
0504
0505 dev_dbg(component->dev, "%s: OPCLKDIV=%d\n", __func__, opclk_div);
0506
0507 snd_soc_component_update_bits(component, WM8978_GPIO_CONTROL, 0x30,
0508 (opclk_div - 1) << 4);
0509
0510 wm8978->f_pllout = f_opclk * opclk_div;
0511 } else if (f_256fs) {
0512
0513
0514
0515
0516
0517
0518
0519
0520
0521
0522 int idx = wm8978_enum_mclk(f_256fs, f_mclk, &wm8978->f_pllout);
0523 if (idx < 0)
0524 return idx;
0525
0526 wm8978->mclk_idx = idx;
0527 } else {
0528 return -EINVAL;
0529 }
0530
0531 f2 = wm8978->f_pllout * 4;
0532
0533 dev_dbg(component->dev, "%s: f_MCLK=%uHz, f_PLLOUT=%uHz\n", __func__,
0534 wm8978->f_mclk, wm8978->f_pllout);
0535
0536 pll_factors(component, &pll_div, f2, wm8978->f_mclk);
0537
0538 dev_dbg(component->dev, "%s: calculated PLL N=0x%x, K=0x%x, div2=%d\n",
0539 __func__, pll_div.n, pll_div.k, pll_div.div2);
0540
0541
0542 snd_soc_component_update_bits(component, WM8978_POWER_MANAGEMENT_1, 0x20, 0);
0543
0544 snd_soc_component_write(component, WM8978_PLL_N, (pll_div.div2 << 4) | pll_div.n);
0545 snd_soc_component_write(component, WM8978_PLL_K1, pll_div.k >> 18);
0546 snd_soc_component_write(component, WM8978_PLL_K2, (pll_div.k >> 9) & 0x1ff);
0547 snd_soc_component_write(component, WM8978_PLL_K3, pll_div.k & 0x1ff);
0548
0549
0550 snd_soc_component_update_bits(component, WM8978_POWER_MANAGEMENT_1, 0x20, 0x20);
0551
0552 if (f_opclk)
0553
0554 snd_soc_component_update_bits(component, WM8978_GPIO_CONTROL, 7, 4);
0555
0556 return 0;
0557 }
0558
0559
0560
0561
0562 static int wm8978_set_dai_clkdiv(struct snd_soc_dai *codec_dai,
0563 int div_id, int div)
0564 {
0565 struct snd_soc_component *component = codec_dai->component;
0566 struct wm8978_priv *wm8978 = snd_soc_component_get_drvdata(component);
0567 int ret = 0;
0568
0569 switch (div_id) {
0570 case WM8978_OPCLKRATE:
0571 wm8978->f_opclk = div;
0572
0573 if (wm8978->f_mclk)
0574
0575
0576
0577
0578
0579
0580
0581
0582
0583
0584
0585
0586
0587
0588 ret = wm8978_configure_pll(component);
0589 break;
0590 case WM8978_BCLKDIV:
0591 if (div & ~0x1c)
0592 return -EINVAL;
0593 snd_soc_component_update_bits(component, WM8978_CLOCKING, 0x1c, div);
0594 break;
0595 default:
0596 return -EINVAL;
0597 }
0598
0599 dev_dbg(component->dev, "%s: ID %d, value %u\n", __func__, div_id, div);
0600
0601 return ret;
0602 }
0603
0604
0605
0606
0607 static int wm8978_set_dai_sysclk(struct snd_soc_dai *codec_dai, int clk_id,
0608 unsigned int freq, int dir)
0609 {
0610 struct snd_soc_component *component = codec_dai->component;
0611 struct wm8978_priv *wm8978 = snd_soc_component_get_drvdata(component);
0612 int ret = 0;
0613
0614 dev_dbg(component->dev, "%s: ID %d, freq %u\n", __func__, clk_id, freq);
0615
0616 if (freq) {
0617 wm8978->f_mclk = freq;
0618
0619
0620 if (wm8978->f_opclk)
0621 ret = wm8978_configure_pll(component);
0622
0623
0624
0625 if (!ret)
0626 wm8978->sysclk = clk_id;
0627 }
0628
0629 if (wm8978->sysclk == WM8978_PLL && (!freq || clk_id == WM8978_MCLK)) {
0630
0631 snd_soc_component_update_bits(component, WM8978_CLOCKING, 0x100, 0);
0632
0633
0634 snd_soc_component_update_bits(component, WM8978_GPIO_CONTROL, 7, 0);
0635
0636
0637 snd_soc_component_update_bits(component, WM8978_POWER_MANAGEMENT_1, 0x20, 0);
0638 wm8978->sysclk = WM8978_MCLK;
0639 wm8978->f_pllout = 0;
0640 wm8978->f_opclk = 0;
0641 }
0642
0643 return ret;
0644 }
0645
0646
0647
0648
0649 static int wm8978_set_dai_fmt(struct snd_soc_dai *codec_dai, unsigned int fmt)
0650 {
0651 struct snd_soc_component *component = codec_dai->component;
0652
0653
0654
0655
0656 u16 iface = snd_soc_component_read(component, WM8978_AUDIO_INTERFACE) & ~0x198;
0657 u16 clk = snd_soc_component_read(component, WM8978_CLOCKING);
0658
0659 dev_dbg(component->dev, "%s\n", __func__);
0660
0661
0662 switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
0663 case SND_SOC_DAIFMT_CBM_CFM:
0664 clk |= 1;
0665 break;
0666 case SND_SOC_DAIFMT_CBS_CFS:
0667 clk &= ~1;
0668 break;
0669 default:
0670 return -EINVAL;
0671 }
0672
0673
0674 switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
0675 case SND_SOC_DAIFMT_I2S:
0676 iface |= 0x10;
0677 break;
0678 case SND_SOC_DAIFMT_RIGHT_J:
0679 break;
0680 case SND_SOC_DAIFMT_LEFT_J:
0681 iface |= 0x8;
0682 break;
0683 case SND_SOC_DAIFMT_DSP_A:
0684 iface |= 0x18;
0685 break;
0686 default:
0687 return -EINVAL;
0688 }
0689
0690
0691 switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
0692 case SND_SOC_DAIFMT_NB_NF:
0693 break;
0694 case SND_SOC_DAIFMT_IB_IF:
0695 iface |= 0x180;
0696 break;
0697 case SND_SOC_DAIFMT_IB_NF:
0698 iface |= 0x100;
0699 break;
0700 case SND_SOC_DAIFMT_NB_IF:
0701 iface |= 0x80;
0702 break;
0703 default:
0704 return -EINVAL;
0705 }
0706
0707 snd_soc_component_write(component, WM8978_AUDIO_INTERFACE, iface);
0708 snd_soc_component_write(component, WM8978_CLOCKING, clk);
0709
0710 return 0;
0711 }
0712
0713
0714
0715
0716 static int wm8978_hw_params(struct snd_pcm_substream *substream,
0717 struct snd_pcm_hw_params *params,
0718 struct snd_soc_dai *dai)
0719 {
0720 struct snd_soc_component *component = dai->component;
0721 struct wm8978_priv *wm8978 = snd_soc_component_get_drvdata(component);
0722
0723 u16 iface_ctl = snd_soc_component_read(component, WM8978_AUDIO_INTERFACE) & ~0x60;
0724
0725 u16 add_ctl = snd_soc_component_read(component, WM8978_ADDITIONAL_CONTROL) & ~0xe;
0726 u16 clking = snd_soc_component_read(component, WM8978_CLOCKING);
0727 enum wm8978_sysclk_src current_clk_id = (clking & 0x100) ?
0728 WM8978_PLL : WM8978_MCLK;
0729 unsigned int f_sel, diff, diff_best = INT_MAX;
0730 int i, best = 0;
0731
0732 if (!wm8978->f_mclk)
0733 return -EINVAL;
0734
0735
0736 switch (params_width(params)) {
0737 case 16:
0738 break;
0739 case 20:
0740 iface_ctl |= 0x20;
0741 break;
0742 case 24:
0743 iface_ctl |= 0x40;
0744 break;
0745 case 32:
0746 iface_ctl |= 0x60;
0747 break;
0748 }
0749
0750
0751 switch (params_rate(params)) {
0752 case 8000:
0753 add_ctl |= 0x5 << 1;
0754 break;
0755 case 11025:
0756 add_ctl |= 0x4 << 1;
0757 break;
0758 case 16000:
0759 add_ctl |= 0x3 << 1;
0760 break;
0761 case 22050:
0762 add_ctl |= 0x2 << 1;
0763 break;
0764 case 32000:
0765 add_ctl |= 0x1 << 1;
0766 break;
0767 case 44100:
0768 case 48000:
0769 break;
0770 }
0771
0772
0773 wm8978->f_256fs = params_rate(params) * 256;
0774
0775 if (wm8978->sysclk == WM8978_MCLK) {
0776 wm8978->mclk_idx = -1;
0777 f_sel = wm8978->f_mclk;
0778 } else {
0779 if (!wm8978->f_opclk) {
0780
0781 int ret = wm8978_configure_pll(component);
0782 if (ret < 0)
0783 return ret;
0784 }
0785 f_sel = wm8978->f_pllout;
0786 }
0787
0788 if (wm8978->mclk_idx < 0) {
0789
0790 if (f_sel < wm8978->f_256fs || f_sel > 12 * wm8978->f_256fs)
0791 return -EINVAL;
0792
0793 for (i = 0; i < ARRAY_SIZE(mclk_numerator); i++) {
0794 diff = abs(wm8978->f_256fs * 3 -
0795 f_sel * 3 * mclk_denominator[i] / mclk_numerator[i]);
0796
0797 if (diff < diff_best) {
0798 diff_best = diff;
0799 best = i;
0800 }
0801
0802 if (!diff)
0803 break;
0804 }
0805 } else {
0806
0807 best = wm8978->mclk_idx;
0808 diff = 0;
0809 }
0810
0811 if (diff)
0812 dev_warn(component->dev, "Imprecise sampling rate: %uHz%s\n",
0813 f_sel * mclk_denominator[best] / mclk_numerator[best] / 256,
0814 wm8978->sysclk == WM8978_MCLK ?
0815 ", consider using PLL" : "");
0816
0817 dev_dbg(component->dev, "%s: width %d, rate %u, MCLK divisor #%d\n", __func__,
0818 params_width(params), params_rate(params), best);
0819
0820
0821 snd_soc_component_update_bits(component, WM8978_CLOCKING, 0xe0, best << 5);
0822
0823 snd_soc_component_write(component, WM8978_AUDIO_INTERFACE, iface_ctl);
0824 snd_soc_component_write(component, WM8978_ADDITIONAL_CONTROL, add_ctl);
0825
0826 if (wm8978->sysclk != current_clk_id) {
0827 if (wm8978->sysclk == WM8978_PLL)
0828
0829 snd_soc_component_update_bits(component, WM8978_CLOCKING,
0830 0x100, 0x100);
0831 else
0832
0833 snd_soc_component_update_bits(component, WM8978_CLOCKING, 0x100, 0);
0834 }
0835
0836 return 0;
0837 }
0838
0839 static int wm8978_mute(struct snd_soc_dai *dai, int mute, int direction)
0840 {
0841 struct snd_soc_component *component = dai->component;
0842
0843 dev_dbg(component->dev, "%s: %d\n", __func__, mute);
0844
0845 if (mute)
0846 snd_soc_component_update_bits(component, WM8978_DAC_CONTROL, 0x40, 0x40);
0847 else
0848 snd_soc_component_update_bits(component, WM8978_DAC_CONTROL, 0x40, 0);
0849
0850 return 0;
0851 }
0852
0853 static int wm8978_set_bias_level(struct snd_soc_component *component,
0854 enum snd_soc_bias_level level)
0855 {
0856 u16 power1 = snd_soc_component_read(component, WM8978_POWER_MANAGEMENT_1) & ~3;
0857
0858 switch (level) {
0859 case SND_SOC_BIAS_ON:
0860 case SND_SOC_BIAS_PREPARE:
0861 power1 |= 1;
0862 snd_soc_component_write(component, WM8978_POWER_MANAGEMENT_1, power1);
0863 break;
0864 case SND_SOC_BIAS_STANDBY:
0865
0866 power1 |= 0xc;
0867
0868 if (snd_soc_component_get_bias_level(component) == SND_SOC_BIAS_OFF) {
0869
0870 snd_soc_component_write(component, WM8978_POWER_MANAGEMENT_1,
0871 power1 | 0x3);
0872 mdelay(100);
0873 }
0874
0875 power1 |= 0x2;
0876 snd_soc_component_write(component, WM8978_POWER_MANAGEMENT_1, power1);
0877 break;
0878 case SND_SOC_BIAS_OFF:
0879
0880 snd_soc_component_update_bits(component, WM8978_POWER_MANAGEMENT_1, ~0x20, 0);
0881 snd_soc_component_write(component, WM8978_POWER_MANAGEMENT_2, 0);
0882 snd_soc_component_write(component, WM8978_POWER_MANAGEMENT_3, 0);
0883 break;
0884 }
0885
0886 dev_dbg(component->dev, "%s: %d, %x\n", __func__, level, power1);
0887
0888 return 0;
0889 }
0890
0891 #define WM8978_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE | \
0892 SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S32_LE)
0893
0894 static const struct snd_soc_dai_ops wm8978_dai_ops = {
0895 .hw_params = wm8978_hw_params,
0896 .mute_stream = wm8978_mute,
0897 .set_fmt = wm8978_set_dai_fmt,
0898 .set_clkdiv = wm8978_set_dai_clkdiv,
0899 .set_sysclk = wm8978_set_dai_sysclk,
0900 .no_capture_mute = 1,
0901 };
0902
0903
0904 static struct snd_soc_dai_driver wm8978_dai = {
0905 .name = "wm8978-hifi",
0906 .playback = {
0907 .stream_name = "Playback",
0908 .channels_min = 1,
0909 .channels_max = 2,
0910 .rates = SNDRV_PCM_RATE_8000_48000,
0911 .formats = WM8978_FORMATS,
0912 },
0913 .capture = {
0914 .stream_name = "Capture",
0915 .channels_min = 1,
0916 .channels_max = 2,
0917 .rates = SNDRV_PCM_RATE_8000_48000,
0918 .formats = WM8978_FORMATS,
0919 },
0920 .ops = &wm8978_dai_ops,
0921 .symmetric_rate = 1,
0922 };
0923
0924 static int wm8978_suspend(struct snd_soc_component *component)
0925 {
0926 struct wm8978_priv *wm8978 = snd_soc_component_get_drvdata(component);
0927
0928 snd_soc_component_force_bias_level(component, SND_SOC_BIAS_OFF);
0929
0930 snd_soc_component_write(component, WM8978_POWER_MANAGEMENT_1, 0);
0931
0932 regcache_mark_dirty(wm8978->regmap);
0933
0934 return 0;
0935 }
0936
0937 static int wm8978_resume(struct snd_soc_component *component)
0938 {
0939 struct wm8978_priv *wm8978 = snd_soc_component_get_drvdata(component);
0940
0941
0942 regcache_sync(wm8978->regmap);
0943
0944 snd_soc_component_force_bias_level(component, SND_SOC_BIAS_STANDBY);
0945
0946 if (wm8978->f_pllout)
0947
0948 snd_soc_component_update_bits(component, WM8978_POWER_MANAGEMENT_1, 0x20, 0x20);
0949
0950 return 0;
0951 }
0952
0953
0954
0955
0956
0957
0958
0959 static const int update_reg[] = {
0960 WM8978_LEFT_DAC_DIGITAL_VOLUME,
0961 WM8978_RIGHT_DAC_DIGITAL_VOLUME,
0962 WM8978_LEFT_ADC_DIGITAL_VOLUME,
0963 WM8978_RIGHT_ADC_DIGITAL_VOLUME,
0964 WM8978_LEFT_INP_PGA_CONTROL,
0965 WM8978_RIGHT_INP_PGA_CONTROL,
0966 WM8978_LOUT1_HP_CONTROL,
0967 WM8978_ROUT1_HP_CONTROL,
0968 WM8978_LOUT2_SPK_CONTROL,
0969 WM8978_ROUT2_SPK_CONTROL,
0970 };
0971
0972 static int wm8978_probe(struct snd_soc_component *component)
0973 {
0974 struct wm8978_priv *wm8978 = snd_soc_component_get_drvdata(component);
0975 int i;
0976
0977
0978
0979
0980
0981 wm8978->sysclk = WM8978_PLL;
0982
0983
0984
0985
0986
0987
0988 for (i = 0; i < ARRAY_SIZE(update_reg); i++)
0989 snd_soc_component_update_bits(component, update_reg[i], 0x100, 0x100);
0990
0991 return 0;
0992 }
0993
0994 static const struct snd_soc_component_driver soc_component_dev_wm8978 = {
0995 .probe = wm8978_probe,
0996 .suspend = wm8978_suspend,
0997 .resume = wm8978_resume,
0998 .set_bias_level = wm8978_set_bias_level,
0999 .controls = wm8978_snd_controls,
1000 .num_controls = ARRAY_SIZE(wm8978_snd_controls),
1001 .dapm_widgets = wm8978_dapm_widgets,
1002 .num_dapm_widgets = ARRAY_SIZE(wm8978_dapm_widgets),
1003 .dapm_routes = wm8978_dapm_routes,
1004 .num_dapm_routes = ARRAY_SIZE(wm8978_dapm_routes),
1005 .idle_bias_on = 1,
1006 .use_pmdown_time = 1,
1007 .endianness = 1,
1008 };
1009
1010 static const struct regmap_config wm8978_regmap_config = {
1011 .reg_bits = 7,
1012 .val_bits = 9,
1013
1014 .max_register = WM8978_MAX_REGISTER,
1015 .volatile_reg = wm8978_volatile,
1016
1017 .cache_type = REGCACHE_RBTREE,
1018 .reg_defaults = wm8978_reg_defaults,
1019 .num_reg_defaults = ARRAY_SIZE(wm8978_reg_defaults),
1020 };
1021
1022 static int wm8978_i2c_probe(struct i2c_client *i2c)
1023 {
1024 struct wm8978_priv *wm8978;
1025 int ret;
1026
1027 wm8978 = devm_kzalloc(&i2c->dev, sizeof(struct wm8978_priv),
1028 GFP_KERNEL);
1029 if (wm8978 == NULL)
1030 return -ENOMEM;
1031
1032 wm8978->regmap = devm_regmap_init_i2c(i2c, &wm8978_regmap_config);
1033 if (IS_ERR(wm8978->regmap)) {
1034 ret = PTR_ERR(wm8978->regmap);
1035 dev_err(&i2c->dev, "Failed to allocate regmap: %d\n", ret);
1036 return ret;
1037 }
1038
1039 i2c_set_clientdata(i2c, wm8978);
1040
1041
1042 ret = regmap_write(wm8978->regmap, WM8978_RESET, 0);
1043 if (ret != 0) {
1044 dev_err(&i2c->dev, "Failed to issue reset: %d\n", ret);
1045 return ret;
1046 }
1047
1048 ret = devm_snd_soc_register_component(&i2c->dev,
1049 &soc_component_dev_wm8978, &wm8978_dai, 1);
1050 if (ret != 0) {
1051 dev_err(&i2c->dev, "Failed to register CODEC: %d\n", ret);
1052 return ret;
1053 }
1054
1055 return 0;
1056 }
1057
1058 static const struct i2c_device_id wm8978_i2c_id[] = {
1059 { "wm8978", 0 },
1060 { }
1061 };
1062 MODULE_DEVICE_TABLE(i2c, wm8978_i2c_id);
1063
1064 static const struct of_device_id wm8978_of_match[] = {
1065 { .compatible = "wlf,wm8978", },
1066 { }
1067 };
1068 MODULE_DEVICE_TABLE(of, wm8978_of_match);
1069
1070 static struct i2c_driver wm8978_i2c_driver = {
1071 .driver = {
1072 .name = "wm8978",
1073 .of_match_table = wm8978_of_match,
1074 },
1075 .probe_new = wm8978_i2c_probe,
1076 .id_table = wm8978_i2c_id,
1077 };
1078
1079 module_i2c_driver(wm8978_i2c_driver);
1080
1081 MODULE_DESCRIPTION("ASoC WM8978 codec driver");
1082 MODULE_AUTHOR("Guennadi Liakhovetski <g.liakhovetski@gmx.de>");
1083 MODULE_LICENSE("GPL");