0001
0002
0003
0004
0005
0006
0007
0008
0009
0010 #include <linux/module.h>
0011 #include <linux/moduleparam.h>
0012 #include <linux/init.h>
0013 #include <linux/delay.h>
0014 #include <linux/of_device.h>
0015 #include <linux/pm.h>
0016 #include <linux/spi/spi.h>
0017 #include <linux/regmap.h>
0018 #include <linux/regulator/consumer.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
0027 #include "wm8770.h"
0028
0029 #define WM8770_NUM_SUPPLIES 3
0030 static const char *wm8770_supply_names[WM8770_NUM_SUPPLIES] = {
0031 "AVDD1",
0032 "AVDD2",
0033 "DVDD"
0034 };
0035
0036 static const struct reg_default wm8770_reg_defaults[] = {
0037 { 0, 0x7f },
0038 { 1, 0x7f },
0039 { 2, 0x7f },
0040 { 3, 0x7f },
0041 { 4, 0x7f },
0042 { 5, 0x7f },
0043 { 6, 0x7f },
0044 { 7, 0x7f },
0045 { 8, 0x7f },
0046 { 9, 0xff },
0047 { 10, 0xff },
0048 { 11, 0xff },
0049 { 12, 0xff },
0050 { 13, 0xff },
0051 { 14, 0xff },
0052 { 15, 0xff },
0053 { 16, 0xff },
0054 { 17, 0xff },
0055 { 18, 0 },
0056 { 19, 0x90 },
0057 { 20, 0 },
0058 { 21, 0 },
0059 { 22, 0x22 },
0060 { 23, 0x22 },
0061 { 24, 0x3e },
0062 { 25, 0xc },
0063 { 26, 0xc },
0064 { 27, 0x100 },
0065 { 28, 0x189 },
0066 { 29, 0x189 },
0067 { 30, 0x8770 },
0068 };
0069
0070 static bool wm8770_volatile_reg(struct device *dev, unsigned int reg)
0071 {
0072 switch (reg) {
0073 case WM8770_RESET:
0074 return true;
0075 default:
0076 return false;
0077 }
0078 }
0079
0080 struct wm8770_priv {
0081 struct regmap *regmap;
0082 struct regulator_bulk_data supplies[WM8770_NUM_SUPPLIES];
0083 struct notifier_block disable_nb[WM8770_NUM_SUPPLIES];
0084 struct snd_soc_component *component;
0085 int sysclk;
0086 };
0087
0088 static int vout12supply_event(struct snd_soc_dapm_widget *w,
0089 struct snd_kcontrol *kcontrol, int event);
0090 static int vout34supply_event(struct snd_soc_dapm_widget *w,
0091 struct snd_kcontrol *kcontrol, int event);
0092
0093
0094
0095
0096
0097
0098 #define WM8770_REGULATOR_EVENT(n) \
0099 static int wm8770_regulator_event_##n(struct notifier_block *nb, \
0100 unsigned long event, void *data) \
0101 { \
0102 struct wm8770_priv *wm8770 = container_of(nb, struct wm8770_priv, \
0103 disable_nb[n]); \
0104 if (event & REGULATOR_EVENT_DISABLE) { \
0105 regcache_mark_dirty(wm8770->regmap); \
0106 } \
0107 return 0; \
0108 }
0109
0110 WM8770_REGULATOR_EVENT(0)
0111 WM8770_REGULATOR_EVENT(1)
0112 WM8770_REGULATOR_EVENT(2)
0113
0114 static const DECLARE_TLV_DB_SCALE(adc_tlv, -1200, 100, 0);
0115 static const DECLARE_TLV_DB_SCALE(dac_dig_tlv, -12750, 50, 1);
0116 static const DECLARE_TLV_DB_SCALE(dac_alg_tlv, -12700, 100, 1);
0117
0118 static const char *dac_phase_text[][2] = {
0119 { "DAC1 Normal", "DAC1 Inverted" },
0120 { "DAC2 Normal", "DAC2 Inverted" },
0121 { "DAC3 Normal", "DAC3 Inverted" },
0122 { "DAC4 Normal", "DAC4 Inverted" },
0123 };
0124
0125 static const struct soc_enum dac_phase[] = {
0126 SOC_ENUM_DOUBLE(WM8770_DACPHASE, 0, 1, 2, dac_phase_text[0]),
0127 SOC_ENUM_DOUBLE(WM8770_DACPHASE, 2, 3, 2, dac_phase_text[1]),
0128 SOC_ENUM_DOUBLE(WM8770_DACPHASE, 4, 5, 2, dac_phase_text[2]),
0129 SOC_ENUM_DOUBLE(WM8770_DACPHASE, 6, 7, 2, dac_phase_text[3]),
0130 };
0131
0132 static const struct snd_kcontrol_new wm8770_snd_controls[] = {
0133
0134 SOC_SINGLE_TLV("DAC Playback Volume", WM8770_MSDIGVOL, 0, 255, 0,
0135 dac_dig_tlv),
0136 SOC_SINGLE("DAC Playback Switch", WM8770_DACMUTE, 4, 1, 1),
0137 SOC_SINGLE("DAC Playback ZC Switch", WM8770_DACCTRL1, 0, 1, 0),
0138
0139
0140 SOC_SINGLE_TLV("VOUT Playback Volume", WM8770_MSALGVOL, 0, 127, 0,
0141 dac_alg_tlv),
0142 SOC_SINGLE("VOUT Playback ZC Switch", WM8770_MSALGVOL, 7, 1, 0),
0143
0144
0145 SOC_DOUBLE_R_TLV("VOUT1 Playback Volume", WM8770_VOUT1LVOL,
0146 WM8770_VOUT1RVOL, 0, 127, 0, dac_alg_tlv),
0147 SOC_DOUBLE_R("VOUT1 Playback ZC Switch", WM8770_VOUT1LVOL,
0148 WM8770_VOUT1RVOL, 7, 1, 0),
0149 SOC_DOUBLE_R_TLV("VOUT2 Playback Volume", WM8770_VOUT2LVOL,
0150 WM8770_VOUT2RVOL, 0, 127, 0, dac_alg_tlv),
0151 SOC_DOUBLE_R("VOUT2 Playback ZC Switch", WM8770_VOUT2LVOL,
0152 WM8770_VOUT2RVOL, 7, 1, 0),
0153 SOC_DOUBLE_R_TLV("VOUT3 Playback Volume", WM8770_VOUT3LVOL,
0154 WM8770_VOUT3RVOL, 0, 127, 0, dac_alg_tlv),
0155 SOC_DOUBLE_R("VOUT3 Playback ZC Switch", WM8770_VOUT3LVOL,
0156 WM8770_VOUT3RVOL, 7, 1, 0),
0157 SOC_DOUBLE_R_TLV("VOUT4 Playback Volume", WM8770_VOUT4LVOL,
0158 WM8770_VOUT4RVOL, 0, 127, 0, dac_alg_tlv),
0159 SOC_DOUBLE_R("VOUT4 Playback ZC Switch", WM8770_VOUT4LVOL,
0160 WM8770_VOUT4RVOL, 7, 1, 0),
0161
0162
0163 SOC_DOUBLE_R_TLV("DAC1 Playback Volume", WM8770_DAC1LVOL,
0164 WM8770_DAC1RVOL, 0, 255, 0, dac_dig_tlv),
0165 SOC_SINGLE("DAC1 Deemphasis Switch", WM8770_DACCTRL2, 0, 1, 0),
0166 SOC_ENUM("DAC1 Phase", dac_phase[0]),
0167 SOC_DOUBLE_R_TLV("DAC2 Playback Volume", WM8770_DAC2LVOL,
0168 WM8770_DAC2RVOL, 0, 255, 0, dac_dig_tlv),
0169 SOC_SINGLE("DAC2 Deemphasis Switch", WM8770_DACCTRL2, 1, 1, 0),
0170 SOC_ENUM("DAC2 Phase", dac_phase[1]),
0171 SOC_DOUBLE_R_TLV("DAC3 Playback Volume", WM8770_DAC3LVOL,
0172 WM8770_DAC3RVOL, 0, 255, 0, dac_dig_tlv),
0173 SOC_SINGLE("DAC3 Deemphasis Switch", WM8770_DACCTRL2, 2, 1, 0),
0174 SOC_ENUM("DAC3 Phase", dac_phase[2]),
0175 SOC_DOUBLE_R_TLV("DAC4 Playback Volume", WM8770_DAC4LVOL,
0176 WM8770_DAC4RVOL, 0, 255, 0, dac_dig_tlv),
0177 SOC_SINGLE("DAC4 Deemphasis Switch", WM8770_DACCTRL2, 3, 1, 0),
0178 SOC_ENUM("DAC4 Phase", dac_phase[3]),
0179
0180
0181 SOC_DOUBLE_R_TLV("Capture Volume", WM8770_ADCLCTRL, WM8770_ADCRCTRL,
0182 0, 31, 0, adc_tlv),
0183 SOC_DOUBLE_R("Capture Switch", WM8770_ADCLCTRL, WM8770_ADCRCTRL,
0184 5, 1, 1),
0185
0186
0187 SOC_SINGLE("ADC 128x Oversampling Switch", WM8770_MSTRCTRL, 3, 1, 0),
0188 SOC_SINGLE("ADC Highpass Filter Switch", WM8770_IFACECTRL, 8, 1, 1)
0189 };
0190
0191 static const char *ain_text[] = {
0192 "AIN1", "AIN2", "AIN3", "AIN4",
0193 "AIN5", "AIN6", "AIN7", "AIN8"
0194 };
0195
0196 static SOC_ENUM_DOUBLE_DECL(ain_enum,
0197 WM8770_ADCMUX, 0, 4, ain_text);
0198
0199 static const struct snd_kcontrol_new ain_mux =
0200 SOC_DAPM_ENUM("Capture Mux", ain_enum);
0201
0202 static const struct snd_kcontrol_new vout1_mix_controls[] = {
0203 SOC_DAPM_SINGLE("DAC1 Switch", WM8770_OUTMUX1, 0, 1, 0),
0204 SOC_DAPM_SINGLE("AUX1 Switch", WM8770_OUTMUX1, 1, 1, 0),
0205 SOC_DAPM_SINGLE("Bypass Switch", WM8770_OUTMUX1, 2, 1, 0)
0206 };
0207
0208 static const struct snd_kcontrol_new vout2_mix_controls[] = {
0209 SOC_DAPM_SINGLE("DAC2 Switch", WM8770_OUTMUX1, 3, 1, 0),
0210 SOC_DAPM_SINGLE("AUX2 Switch", WM8770_OUTMUX1, 4, 1, 0),
0211 SOC_DAPM_SINGLE("Bypass Switch", WM8770_OUTMUX1, 5, 1, 0)
0212 };
0213
0214 static const struct snd_kcontrol_new vout3_mix_controls[] = {
0215 SOC_DAPM_SINGLE("DAC3 Switch", WM8770_OUTMUX2, 0, 1, 0),
0216 SOC_DAPM_SINGLE("AUX3 Switch", WM8770_OUTMUX2, 1, 1, 0),
0217 SOC_DAPM_SINGLE("Bypass Switch", WM8770_OUTMUX2, 2, 1, 0)
0218 };
0219
0220 static const struct snd_kcontrol_new vout4_mix_controls[] = {
0221 SOC_DAPM_SINGLE("DAC4 Switch", WM8770_OUTMUX2, 3, 1, 0),
0222 SOC_DAPM_SINGLE("Bypass Switch", WM8770_OUTMUX2, 4, 1, 0)
0223 };
0224
0225 static const struct snd_soc_dapm_widget wm8770_dapm_widgets[] = {
0226 SND_SOC_DAPM_INPUT("AUX1"),
0227 SND_SOC_DAPM_INPUT("AUX2"),
0228 SND_SOC_DAPM_INPUT("AUX3"),
0229
0230 SND_SOC_DAPM_INPUT("AIN1"),
0231 SND_SOC_DAPM_INPUT("AIN2"),
0232 SND_SOC_DAPM_INPUT("AIN3"),
0233 SND_SOC_DAPM_INPUT("AIN4"),
0234 SND_SOC_DAPM_INPUT("AIN5"),
0235 SND_SOC_DAPM_INPUT("AIN6"),
0236 SND_SOC_DAPM_INPUT("AIN7"),
0237 SND_SOC_DAPM_INPUT("AIN8"),
0238
0239 SND_SOC_DAPM_MUX("Capture Mux", WM8770_ADCMUX, 8, 1, &ain_mux),
0240
0241 SND_SOC_DAPM_ADC("ADC", "Capture", WM8770_PWDNCTRL, 1, 1),
0242
0243 SND_SOC_DAPM_DAC("DAC1", "Playback", WM8770_PWDNCTRL, 2, 1),
0244 SND_SOC_DAPM_DAC("DAC2", "Playback", WM8770_PWDNCTRL, 3, 1),
0245 SND_SOC_DAPM_DAC("DAC3", "Playback", WM8770_PWDNCTRL, 4, 1),
0246 SND_SOC_DAPM_DAC("DAC4", "Playback", WM8770_PWDNCTRL, 5, 1),
0247
0248 SND_SOC_DAPM_SUPPLY("VOUT12 Supply", SND_SOC_NOPM, 0, 0,
0249 vout12supply_event, SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
0250 SND_SOC_DAPM_SUPPLY("VOUT34 Supply", SND_SOC_NOPM, 0, 0,
0251 vout34supply_event, SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
0252
0253 SND_SOC_DAPM_MIXER("VOUT1 Mixer", SND_SOC_NOPM, 0, 0,
0254 vout1_mix_controls, ARRAY_SIZE(vout1_mix_controls)),
0255 SND_SOC_DAPM_MIXER("VOUT2 Mixer", SND_SOC_NOPM, 0, 0,
0256 vout2_mix_controls, ARRAY_SIZE(vout2_mix_controls)),
0257 SND_SOC_DAPM_MIXER("VOUT3 Mixer", SND_SOC_NOPM, 0, 0,
0258 vout3_mix_controls, ARRAY_SIZE(vout3_mix_controls)),
0259 SND_SOC_DAPM_MIXER("VOUT4 Mixer", SND_SOC_NOPM, 0, 0,
0260 vout4_mix_controls, ARRAY_SIZE(vout4_mix_controls)),
0261
0262 SND_SOC_DAPM_OUTPUT("VOUT1"),
0263 SND_SOC_DAPM_OUTPUT("VOUT2"),
0264 SND_SOC_DAPM_OUTPUT("VOUT3"),
0265 SND_SOC_DAPM_OUTPUT("VOUT4")
0266 };
0267
0268 static const struct snd_soc_dapm_route wm8770_intercon[] = {
0269 { "Capture Mux", "AIN1", "AIN1" },
0270 { "Capture Mux", "AIN2", "AIN2" },
0271 { "Capture Mux", "AIN3", "AIN3" },
0272 { "Capture Mux", "AIN4", "AIN4" },
0273 { "Capture Mux", "AIN5", "AIN5" },
0274 { "Capture Mux", "AIN6", "AIN6" },
0275 { "Capture Mux", "AIN7", "AIN7" },
0276 { "Capture Mux", "AIN8", "AIN8" },
0277
0278 { "ADC", NULL, "Capture Mux" },
0279
0280 { "VOUT1 Mixer", NULL, "VOUT12 Supply" },
0281 { "VOUT1 Mixer", "DAC1 Switch", "DAC1" },
0282 { "VOUT1 Mixer", "AUX1 Switch", "AUX1" },
0283 { "VOUT1 Mixer", "Bypass Switch", "Capture Mux" },
0284
0285 { "VOUT2 Mixer", NULL, "VOUT12 Supply" },
0286 { "VOUT2 Mixer", "DAC2 Switch", "DAC2" },
0287 { "VOUT2 Mixer", "AUX2 Switch", "AUX2" },
0288 { "VOUT2 Mixer", "Bypass Switch", "Capture Mux" },
0289
0290 { "VOUT3 Mixer", NULL, "VOUT34 Supply" },
0291 { "VOUT3 Mixer", "DAC3 Switch", "DAC3" },
0292 { "VOUT3 Mixer", "AUX3 Switch", "AUX3" },
0293 { "VOUT3 Mixer", "Bypass Switch", "Capture Mux" },
0294
0295 { "VOUT4 Mixer", NULL, "VOUT34 Supply" },
0296 { "VOUT4 Mixer", "DAC4 Switch", "DAC4" },
0297 { "VOUT4 Mixer", "Bypass Switch", "Capture Mux" },
0298
0299 { "VOUT1", NULL, "VOUT1 Mixer" },
0300 { "VOUT2", NULL, "VOUT2 Mixer" },
0301 { "VOUT3", NULL, "VOUT3 Mixer" },
0302 { "VOUT4", NULL, "VOUT4 Mixer" }
0303 };
0304
0305 static int vout12supply_event(struct snd_soc_dapm_widget *w,
0306 struct snd_kcontrol *kcontrol, int event)
0307 {
0308 struct snd_soc_component *component = snd_soc_dapm_to_component(w->dapm);
0309
0310 switch (event) {
0311 case SND_SOC_DAPM_PRE_PMU:
0312 snd_soc_component_update_bits(component, WM8770_OUTMUX1, 0x180, 0);
0313 break;
0314 case SND_SOC_DAPM_POST_PMD:
0315 snd_soc_component_update_bits(component, WM8770_OUTMUX1, 0x180, 0x180);
0316 break;
0317 }
0318
0319 return 0;
0320 }
0321
0322 static int vout34supply_event(struct snd_soc_dapm_widget *w,
0323 struct snd_kcontrol *kcontrol, int event)
0324 {
0325 struct snd_soc_component *component = snd_soc_dapm_to_component(w->dapm);
0326
0327 switch (event) {
0328 case SND_SOC_DAPM_PRE_PMU:
0329 snd_soc_component_update_bits(component, WM8770_OUTMUX2, 0x180, 0);
0330 break;
0331 case SND_SOC_DAPM_POST_PMD:
0332 snd_soc_component_update_bits(component, WM8770_OUTMUX2, 0x180, 0x180);
0333 break;
0334 }
0335
0336 return 0;
0337 }
0338
0339 static int wm8770_reset(struct snd_soc_component *component)
0340 {
0341 return snd_soc_component_write(component, WM8770_RESET, 0);
0342 }
0343
0344 static int wm8770_set_fmt(struct snd_soc_dai *dai, unsigned int fmt)
0345 {
0346 struct snd_soc_component *component;
0347 int iface, master;
0348
0349 component = dai->component;
0350
0351 switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
0352 case SND_SOC_DAIFMT_CBM_CFM:
0353 master = 0x100;
0354 break;
0355 case SND_SOC_DAIFMT_CBS_CFS:
0356 master = 0;
0357 break;
0358 default:
0359 return -EINVAL;
0360 }
0361
0362 iface = 0;
0363 switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
0364 case SND_SOC_DAIFMT_I2S:
0365 iface |= 0x2;
0366 break;
0367 case SND_SOC_DAIFMT_RIGHT_J:
0368 break;
0369 case SND_SOC_DAIFMT_LEFT_J:
0370 iface |= 0x1;
0371 break;
0372 default:
0373 return -EINVAL;
0374 }
0375
0376 switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
0377 case SND_SOC_DAIFMT_NB_NF:
0378 break;
0379 case SND_SOC_DAIFMT_IB_IF:
0380 iface |= 0xc;
0381 break;
0382 case SND_SOC_DAIFMT_IB_NF:
0383 iface |= 0x8;
0384 break;
0385 case SND_SOC_DAIFMT_NB_IF:
0386 iface |= 0x4;
0387 break;
0388 default:
0389 return -EINVAL;
0390 }
0391
0392 snd_soc_component_update_bits(component, WM8770_IFACECTRL, 0xf, iface);
0393 snd_soc_component_update_bits(component, WM8770_MSTRCTRL, 0x100, master);
0394
0395 return 0;
0396 }
0397
0398 static const int mclk_ratios[] = {
0399 128,
0400 192,
0401 256,
0402 384,
0403 512,
0404 768
0405 };
0406
0407 static int wm8770_hw_params(struct snd_pcm_substream *substream,
0408 struct snd_pcm_hw_params *params,
0409 struct snd_soc_dai *dai)
0410 {
0411 struct snd_soc_component *component;
0412 struct wm8770_priv *wm8770;
0413 int i;
0414 int iface;
0415 int shift;
0416 int ratio;
0417
0418 component = dai->component;
0419 wm8770 = snd_soc_component_get_drvdata(component);
0420
0421 iface = 0;
0422 switch (params_width(params)) {
0423 case 16:
0424 break;
0425 case 20:
0426 iface |= 0x10;
0427 break;
0428 case 24:
0429 iface |= 0x20;
0430 break;
0431 case 32:
0432 iface |= 0x30;
0433 break;
0434 }
0435
0436 switch (substream->stream) {
0437 case SNDRV_PCM_STREAM_PLAYBACK:
0438 i = 0;
0439 shift = 4;
0440 break;
0441 case SNDRV_PCM_STREAM_CAPTURE:
0442 i = 2;
0443 shift = 0;
0444 break;
0445 default:
0446 return -EINVAL;
0447 }
0448
0449
0450 if (snd_soc_component_read(component, WM8770_MSTRCTRL) & 0x100) {
0451 for (; i < ARRAY_SIZE(mclk_ratios); ++i) {
0452 ratio = wm8770->sysclk / params_rate(params);
0453 if (ratio == mclk_ratios[i])
0454 break;
0455 }
0456
0457 if (i == ARRAY_SIZE(mclk_ratios)) {
0458 dev_err(component->dev,
0459 "Unable to configure MCLK ratio %d/%d\n",
0460 wm8770->sysclk, params_rate(params));
0461 return -EINVAL;
0462 }
0463
0464 dev_dbg(component->dev, "MCLK is %dfs\n", mclk_ratios[i]);
0465
0466 snd_soc_component_update_bits(component, WM8770_MSTRCTRL, 0x7 << shift,
0467 i << shift);
0468 }
0469
0470 snd_soc_component_update_bits(component, WM8770_IFACECTRL, 0x30, iface);
0471
0472 return 0;
0473 }
0474
0475 static int wm8770_mute(struct snd_soc_dai *dai, int mute, int direction)
0476 {
0477 struct snd_soc_component *component;
0478
0479 component = dai->component;
0480 return snd_soc_component_update_bits(component, WM8770_DACMUTE, 0x10,
0481 !!mute << 4);
0482 }
0483
0484 static int wm8770_set_sysclk(struct snd_soc_dai *dai,
0485 int clk_id, unsigned int freq, int dir)
0486 {
0487 struct snd_soc_component *component;
0488 struct wm8770_priv *wm8770;
0489
0490 component = dai->component;
0491 wm8770 = snd_soc_component_get_drvdata(component);
0492 wm8770->sysclk = freq;
0493 return 0;
0494 }
0495
0496 static int wm8770_set_bias_level(struct snd_soc_component *component,
0497 enum snd_soc_bias_level level)
0498 {
0499 int ret;
0500 struct wm8770_priv *wm8770;
0501
0502 wm8770 = snd_soc_component_get_drvdata(component);
0503
0504 switch (level) {
0505 case SND_SOC_BIAS_ON:
0506 break;
0507 case SND_SOC_BIAS_PREPARE:
0508 break;
0509 case SND_SOC_BIAS_STANDBY:
0510 if (snd_soc_component_get_bias_level(component) == SND_SOC_BIAS_OFF) {
0511 ret = regulator_bulk_enable(ARRAY_SIZE(wm8770->supplies),
0512 wm8770->supplies);
0513 if (ret) {
0514 dev_err(component->dev,
0515 "Failed to enable supplies: %d\n",
0516 ret);
0517 return ret;
0518 }
0519
0520 regcache_sync(wm8770->regmap);
0521
0522
0523 snd_soc_component_write(component, WM8770_PWDNCTRL, 0);
0524 }
0525 break;
0526 case SND_SOC_BIAS_OFF:
0527
0528 snd_soc_component_write(component, WM8770_PWDNCTRL, 1);
0529 regulator_bulk_disable(ARRAY_SIZE(wm8770->supplies),
0530 wm8770->supplies);
0531 break;
0532 }
0533
0534 return 0;
0535 }
0536
0537 #define WM8770_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE | \
0538 SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S32_LE)
0539
0540 static const struct snd_soc_dai_ops wm8770_dai_ops = {
0541 .mute_stream = wm8770_mute,
0542 .hw_params = wm8770_hw_params,
0543 .set_fmt = wm8770_set_fmt,
0544 .set_sysclk = wm8770_set_sysclk,
0545 .no_capture_mute = 1,
0546 };
0547
0548 static struct snd_soc_dai_driver wm8770_dai = {
0549 .name = "wm8770-hifi",
0550 .playback = {
0551 .stream_name = "Playback",
0552 .channels_min = 2,
0553 .channels_max = 2,
0554 .rates = SNDRV_PCM_RATE_8000_192000,
0555 .formats = WM8770_FORMATS
0556 },
0557 .capture = {
0558 .stream_name = "Capture",
0559 .channels_min = 2,
0560 .channels_max = 2,
0561 .rates = SNDRV_PCM_RATE_8000_96000,
0562 .formats = WM8770_FORMATS
0563 },
0564 .ops = &wm8770_dai_ops,
0565 .symmetric_rate = 1
0566 };
0567
0568 static int wm8770_probe(struct snd_soc_component *component)
0569 {
0570 struct wm8770_priv *wm8770;
0571 int ret;
0572
0573 wm8770 = snd_soc_component_get_drvdata(component);
0574 wm8770->component = component;
0575
0576 ret = regulator_bulk_enable(ARRAY_SIZE(wm8770->supplies),
0577 wm8770->supplies);
0578 if (ret) {
0579 dev_err(component->dev, "Failed to enable supplies: %d\n", ret);
0580 return ret;
0581 }
0582
0583 ret = wm8770_reset(component);
0584 if (ret < 0) {
0585 dev_err(component->dev, "Failed to issue reset: %d\n", ret);
0586 goto err_reg_enable;
0587 }
0588
0589
0590 snd_soc_component_update_bits(component, WM8770_MSDIGVOL, 0x100, 0x100);
0591 snd_soc_component_update_bits(component, WM8770_MSALGVOL, 0x100, 0x100);
0592 snd_soc_component_update_bits(component, WM8770_VOUT1RVOL, 0x100, 0x100);
0593 snd_soc_component_update_bits(component, WM8770_VOUT2RVOL, 0x100, 0x100);
0594 snd_soc_component_update_bits(component, WM8770_VOUT3RVOL, 0x100, 0x100);
0595 snd_soc_component_update_bits(component, WM8770_VOUT4RVOL, 0x100, 0x100);
0596 snd_soc_component_update_bits(component, WM8770_DAC1RVOL, 0x100, 0x100);
0597 snd_soc_component_update_bits(component, WM8770_DAC2RVOL, 0x100, 0x100);
0598 snd_soc_component_update_bits(component, WM8770_DAC3RVOL, 0x100, 0x100);
0599 snd_soc_component_update_bits(component, WM8770_DAC4RVOL, 0x100, 0x100);
0600
0601
0602 snd_soc_component_update_bits(component, WM8770_DACMUTE, 0x10, 0x10);
0603
0604 err_reg_enable:
0605 regulator_bulk_disable(ARRAY_SIZE(wm8770->supplies), wm8770->supplies);
0606 return ret;
0607 }
0608
0609 static const struct snd_soc_component_driver soc_component_dev_wm8770 = {
0610 .probe = wm8770_probe,
0611 .set_bias_level = wm8770_set_bias_level,
0612 .controls = wm8770_snd_controls,
0613 .num_controls = ARRAY_SIZE(wm8770_snd_controls),
0614 .dapm_widgets = wm8770_dapm_widgets,
0615 .num_dapm_widgets = ARRAY_SIZE(wm8770_dapm_widgets),
0616 .dapm_routes = wm8770_intercon,
0617 .num_dapm_routes = ARRAY_SIZE(wm8770_intercon),
0618 .use_pmdown_time = 1,
0619 .endianness = 1,
0620 };
0621
0622 static const struct of_device_id wm8770_of_match[] = {
0623 { .compatible = "wlf,wm8770", },
0624 { }
0625 };
0626 MODULE_DEVICE_TABLE(of, wm8770_of_match);
0627
0628 static const struct regmap_config wm8770_regmap = {
0629 .reg_bits = 7,
0630 .val_bits = 9,
0631 .max_register = WM8770_RESET,
0632
0633 .reg_defaults = wm8770_reg_defaults,
0634 .num_reg_defaults = ARRAY_SIZE(wm8770_reg_defaults),
0635 .cache_type = REGCACHE_RBTREE,
0636
0637 .volatile_reg = wm8770_volatile_reg,
0638 };
0639
0640 static int wm8770_spi_probe(struct spi_device *spi)
0641 {
0642 struct wm8770_priv *wm8770;
0643 int ret, i;
0644
0645 wm8770 = devm_kzalloc(&spi->dev, sizeof(struct wm8770_priv),
0646 GFP_KERNEL);
0647 if (!wm8770)
0648 return -ENOMEM;
0649
0650 for (i = 0; i < ARRAY_SIZE(wm8770->supplies); i++)
0651 wm8770->supplies[i].supply = wm8770_supply_names[i];
0652
0653 ret = devm_regulator_bulk_get(&spi->dev, ARRAY_SIZE(wm8770->supplies),
0654 wm8770->supplies);
0655 if (ret) {
0656 dev_err(&spi->dev, "Failed to request supplies: %d\n", ret);
0657 return ret;
0658 }
0659
0660 wm8770->disable_nb[0].notifier_call = wm8770_regulator_event_0;
0661 wm8770->disable_nb[1].notifier_call = wm8770_regulator_event_1;
0662 wm8770->disable_nb[2].notifier_call = wm8770_regulator_event_2;
0663
0664
0665 for (i = 0; i < ARRAY_SIZE(wm8770->supplies); i++) {
0666 ret = devm_regulator_register_notifier(
0667 wm8770->supplies[i].consumer,
0668 &wm8770->disable_nb[i]);
0669 if (ret) {
0670 dev_err(&spi->dev,
0671 "Failed to register regulator notifier: %d\n",
0672 ret);
0673 }
0674 }
0675
0676 wm8770->regmap = devm_regmap_init_spi(spi, &wm8770_regmap);
0677 if (IS_ERR(wm8770->regmap))
0678 return PTR_ERR(wm8770->regmap);
0679
0680 spi_set_drvdata(spi, wm8770);
0681
0682 ret = devm_snd_soc_register_component(&spi->dev,
0683 &soc_component_dev_wm8770, &wm8770_dai, 1);
0684
0685 return ret;
0686 }
0687
0688 static struct spi_driver wm8770_spi_driver = {
0689 .driver = {
0690 .name = "wm8770",
0691 .of_match_table = wm8770_of_match,
0692 },
0693 .probe = wm8770_spi_probe,
0694 };
0695
0696 module_spi_driver(wm8770_spi_driver);
0697
0698 MODULE_DESCRIPTION("ASoC WM8770 driver");
0699 MODULE_AUTHOR("Dimitris Papastamos <dp@opensource.wolfsonmicro.com>");
0700 MODULE_LICENSE("GPL");