Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-only
0002 /*
0003  * wm8737.c  --  WM8737 ALSA SoC Audio driver
0004  *
0005  * Copyright 2010 Wolfson Microelectronics plc
0006  *
0007  * Author: Mark Brown <broonie@opensource.wolfsonmicro.com>
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/pm.h>
0015 #include <linux/i2c.h>
0016 #include <linux/regmap.h>
0017 #include <linux/regulator/consumer.h>
0018 #include <linux/spi/spi.h>
0019 #include <linux/slab.h>
0020 #include <linux/of_device.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/soc-dapm.h>
0026 #include <sound/initval.h>
0027 #include <sound/tlv.h>
0028 
0029 #include "wm8737.h"
0030 
0031 #define WM8737_NUM_SUPPLIES 4
0032 static const char *wm8737_supply_names[WM8737_NUM_SUPPLIES] = {
0033     "DCVDD",
0034     "DBVDD",
0035     "AVDD",
0036     "MVDD",
0037 };
0038 
0039 /* codec private data */
0040 struct wm8737_priv {
0041     struct regmap *regmap;
0042     struct regulator_bulk_data supplies[WM8737_NUM_SUPPLIES];
0043     unsigned int mclk;
0044 };
0045 
0046 static const struct reg_default wm8737_reg_defaults[] = {
0047     {  0, 0x00C3 },     /* R0  - Left PGA volume */
0048     {  1, 0x00C3 },     /* R1  - Right PGA volume */
0049     {  2, 0x0007 },     /* R2  - AUDIO path L */
0050     {  3, 0x0007 },     /* R3  - AUDIO path R */
0051     {  4, 0x0000 },     /* R4  - 3D Enhance */
0052     {  5, 0x0000 },     /* R5  - ADC Control */
0053     {  6, 0x0000 },     /* R6  - Power Management */
0054     {  7, 0x000A },     /* R7  - Audio Format */
0055     {  8, 0x0000 },     /* R8  - Clocking */
0056     {  9, 0x000F },     /* R9  - MIC Preamp Control */
0057     { 10, 0x0003 },     /* R10 - Misc Bias Control */
0058     { 11, 0x0000 },     /* R11 - Noise Gate */
0059     { 12, 0x007C },     /* R12 - ALC1 */
0060     { 13, 0x0000 },     /* R13 - ALC2 */
0061     { 14, 0x0032 },     /* R14 - ALC3 */
0062 };
0063 
0064 static bool wm8737_volatile(struct device *dev, unsigned int reg)
0065 {
0066     switch (reg) {
0067     case WM8737_RESET:
0068         return true;
0069     default:
0070         return false;
0071     }
0072 }
0073 
0074 static int wm8737_reset(struct snd_soc_component *component)
0075 {
0076     return snd_soc_component_write(component, WM8737_RESET, 0);
0077 }
0078 
0079 static const DECLARE_TLV_DB_RANGE(micboost_tlv,
0080     0, 0, TLV_DB_SCALE_ITEM(1300, 0, 0),
0081     1, 1, TLV_DB_SCALE_ITEM(1800, 0, 0),
0082     2, 2, TLV_DB_SCALE_ITEM(2800, 0, 0),
0083     3, 3, TLV_DB_SCALE_ITEM(3300, 0, 0)
0084 );
0085 static const DECLARE_TLV_DB_SCALE(pga_tlv, -9750, 50, 1);
0086 static const DECLARE_TLV_DB_SCALE(adc_tlv, -600, 600, 0);
0087 static const DECLARE_TLV_DB_SCALE(ng_tlv, -7800, 600, 0);
0088 static const DECLARE_TLV_DB_SCALE(alc_max_tlv, -1200, 600, 0);
0089 static const DECLARE_TLV_DB_SCALE(alc_target_tlv, -1800, 100, 0);
0090 
0091 static const char *micbias_enum_text[] = {
0092     "25%",
0093     "50%",
0094     "75%",
0095     "100%",
0096 };
0097 
0098 static SOC_ENUM_SINGLE_DECL(micbias_enum,
0099                 WM8737_MIC_PREAMP_CONTROL, 0, micbias_enum_text);
0100 
0101 static const char *low_cutoff_text[] = {
0102     "Low", "High"
0103 };
0104 
0105 static SOC_ENUM_SINGLE_DECL(low_3d,
0106                 WM8737_3D_ENHANCE, 6, low_cutoff_text);
0107 
0108 static const char *high_cutoff_text[] = {
0109     "High", "Low"
0110 };
0111 
0112 static SOC_ENUM_SINGLE_DECL(high_3d,
0113                 WM8737_3D_ENHANCE, 5, high_cutoff_text);
0114 
0115 static const char *alc_fn_text[] = {
0116     "Disabled", "Right", "Left", "Stereo"
0117 };
0118 
0119 static SOC_ENUM_SINGLE_DECL(alc_fn,
0120                 WM8737_ALC1, 7, alc_fn_text);
0121 
0122 static const char *alc_hold_text[] = {
0123     "0", "2.67ms", "5.33ms", "10.66ms", "21.32ms", "42.64ms", "85.28ms",
0124     "170.56ms", "341.12ms", "682.24ms", "1.364s", "2.728s", "5.458s",
0125     "10.916s", "21.832s", "43.691s"
0126 };
0127 
0128 static SOC_ENUM_SINGLE_DECL(alc_hold,
0129                 WM8737_ALC2, 0, alc_hold_text);
0130 
0131 static const char *alc_atk_text[] = {
0132     "8.4ms", "16.8ms", "33.6ms", "67.2ms", "134.4ms", "268.8ms", "537.6ms",
0133     "1.075s", "2.15s", "4.3s", "8.6s"
0134 };
0135 
0136 static SOC_ENUM_SINGLE_DECL(alc_atk,
0137                 WM8737_ALC3, 0, alc_atk_text);
0138 
0139 static const char *alc_dcy_text[] = {
0140     "33.6ms", "67.2ms", "134.4ms", "268.8ms", "537.6ms", "1.075s", "2.15s",
0141     "4.3s", "8.6s", "17.2s", "34.41s"
0142 };
0143 
0144 static SOC_ENUM_SINGLE_DECL(alc_dcy,
0145                 WM8737_ALC3, 4, alc_dcy_text);
0146 
0147 static const struct snd_kcontrol_new wm8737_snd_controls[] = {
0148 SOC_DOUBLE_R_TLV("Mic Boost Volume", WM8737_AUDIO_PATH_L, WM8737_AUDIO_PATH_R,
0149          6, 3, 0, micboost_tlv),
0150 SOC_DOUBLE_R("Mic Boost Switch", WM8737_AUDIO_PATH_L, WM8737_AUDIO_PATH_R,
0151          4, 1, 0),
0152 SOC_DOUBLE("Mic ZC Switch", WM8737_AUDIO_PATH_L, WM8737_AUDIO_PATH_R,
0153        3, 1, 0),
0154 
0155 SOC_DOUBLE_R_TLV("Capture Volume", WM8737_LEFT_PGA_VOLUME,
0156          WM8737_RIGHT_PGA_VOLUME, 0, 255, 0, pga_tlv),
0157 SOC_DOUBLE("Capture ZC Switch", WM8737_AUDIO_PATH_L, WM8737_AUDIO_PATH_R,
0158        2, 1, 0),
0159 
0160 SOC_DOUBLE("INPUT1 DC Bias Switch", WM8737_MISC_BIAS_CONTROL, 0, 1, 1, 0),
0161 
0162 SOC_ENUM("Mic PGA Bias", micbias_enum),
0163 SOC_SINGLE("ADC Low Power Switch", WM8737_ADC_CONTROL, 2, 1, 0),
0164 SOC_SINGLE("High Pass Filter Switch", WM8737_ADC_CONTROL, 0, 1, 1),
0165 SOC_DOUBLE("Polarity Invert Switch", WM8737_ADC_CONTROL, 5, 6, 1, 0),
0166 
0167 SOC_SINGLE("3D Switch", WM8737_3D_ENHANCE, 0, 1, 0),
0168 SOC_SINGLE("3D Depth", WM8737_3D_ENHANCE, 1, 15, 0),
0169 SOC_ENUM("3D Low Cut-off", low_3d),
0170 SOC_ENUM("3D High Cut-off", high_3d),
0171 SOC_SINGLE_TLV("3D ADC Volume", WM8737_3D_ENHANCE, 7, 1, 1, adc_tlv),
0172 
0173 SOC_SINGLE("Noise Gate Switch", WM8737_NOISE_GATE, 0, 1, 0),
0174 SOC_SINGLE_TLV("Noise Gate Threshold Volume", WM8737_NOISE_GATE, 2, 7, 0,
0175            ng_tlv),
0176 
0177 SOC_ENUM("ALC", alc_fn),
0178 SOC_SINGLE_TLV("ALC Max Gain Volume", WM8737_ALC1, 4, 7, 0, alc_max_tlv),
0179 SOC_SINGLE_TLV("ALC Target Volume", WM8737_ALC1, 0, 15, 0, alc_target_tlv),
0180 SOC_ENUM("ALC Hold Time", alc_hold),
0181 SOC_SINGLE("ALC ZC Switch", WM8737_ALC2, 4, 1, 0),
0182 SOC_ENUM("ALC Attack Time", alc_atk),
0183 SOC_ENUM("ALC Decay Time", alc_dcy),
0184 };
0185 
0186 static const char *linsel_text[] = {
0187     "LINPUT1", "LINPUT2", "LINPUT3", "LINPUT1 DC",
0188 };
0189 
0190 static SOC_ENUM_SINGLE_DECL(linsel_enum,
0191                 WM8737_AUDIO_PATH_L, 7, linsel_text);
0192 
0193 static const struct snd_kcontrol_new linsel_mux =
0194     SOC_DAPM_ENUM("LINSEL", linsel_enum);
0195 
0196 
0197 static const char *rinsel_text[] = {
0198     "RINPUT1", "RINPUT2", "RINPUT3", "RINPUT1 DC",
0199 };
0200 
0201 static SOC_ENUM_SINGLE_DECL(rinsel_enum,
0202                 WM8737_AUDIO_PATH_R, 7, rinsel_text);
0203 
0204 static const struct snd_kcontrol_new rinsel_mux =
0205     SOC_DAPM_ENUM("RINSEL", rinsel_enum);
0206 
0207 static const char *bypass_text[] = {
0208     "Direct", "Preamp"
0209 };
0210 
0211 static SOC_ENUM_SINGLE_DECL(lbypass_enum,
0212                 WM8737_MIC_PREAMP_CONTROL, 2, bypass_text);
0213 
0214 static const struct snd_kcontrol_new lbypass_mux =
0215     SOC_DAPM_ENUM("Left Bypass", lbypass_enum);
0216 
0217 
0218 static SOC_ENUM_SINGLE_DECL(rbypass_enum,
0219                 WM8737_MIC_PREAMP_CONTROL, 3, bypass_text);
0220 
0221 static const struct snd_kcontrol_new rbypass_mux =
0222     SOC_DAPM_ENUM("Left Bypass", rbypass_enum);
0223 
0224 static const struct snd_soc_dapm_widget wm8737_dapm_widgets[] = {
0225 SND_SOC_DAPM_INPUT("LINPUT1"),
0226 SND_SOC_DAPM_INPUT("LINPUT2"),
0227 SND_SOC_DAPM_INPUT("LINPUT3"),
0228 SND_SOC_DAPM_INPUT("RINPUT1"),
0229 SND_SOC_DAPM_INPUT("RINPUT2"),
0230 SND_SOC_DAPM_INPUT("RINPUT3"),
0231 SND_SOC_DAPM_INPUT("LACIN"),
0232 SND_SOC_DAPM_INPUT("RACIN"),
0233 
0234 SND_SOC_DAPM_MUX("LINSEL", SND_SOC_NOPM, 0, 0, &linsel_mux),
0235 SND_SOC_DAPM_MUX("RINSEL", SND_SOC_NOPM, 0, 0, &rinsel_mux),
0236 
0237 SND_SOC_DAPM_MUX("Left Preamp Mux", SND_SOC_NOPM, 0, 0, &lbypass_mux),
0238 SND_SOC_DAPM_MUX("Right Preamp Mux", SND_SOC_NOPM, 0, 0, &rbypass_mux),
0239 
0240 SND_SOC_DAPM_PGA("PGAL", WM8737_POWER_MANAGEMENT, 5, 0, NULL, 0),
0241 SND_SOC_DAPM_PGA("PGAR", WM8737_POWER_MANAGEMENT, 4, 0, NULL, 0),
0242 
0243 SND_SOC_DAPM_DAC("ADCL", NULL, WM8737_POWER_MANAGEMENT, 3, 0),
0244 SND_SOC_DAPM_DAC("ADCR", NULL, WM8737_POWER_MANAGEMENT, 2, 0),
0245 
0246 SND_SOC_DAPM_AIF_OUT("AIF", "Capture", 0, WM8737_POWER_MANAGEMENT, 6, 0),
0247 };
0248 
0249 static const struct snd_soc_dapm_route intercon[] = {
0250     { "LINSEL", "LINPUT1", "LINPUT1" },
0251     { "LINSEL", "LINPUT2", "LINPUT2" },
0252     { "LINSEL", "LINPUT3", "LINPUT3" },
0253     { "LINSEL", "LINPUT1 DC", "LINPUT1" },
0254 
0255     { "RINSEL", "RINPUT1", "RINPUT1" },
0256     { "RINSEL", "RINPUT2", "RINPUT2" },
0257     { "RINSEL", "RINPUT3", "RINPUT3" },
0258     { "RINSEL", "RINPUT1 DC", "RINPUT1" },
0259 
0260     { "Left Preamp Mux", "Preamp", "LINSEL" },
0261     { "Left Preamp Mux", "Direct", "LACIN" },
0262 
0263     { "Right Preamp Mux", "Preamp", "RINSEL" },
0264     { "Right Preamp Mux", "Direct", "RACIN" },
0265 
0266     { "PGAL", NULL, "Left Preamp Mux" },
0267     { "PGAR", NULL, "Right Preamp Mux" },
0268 
0269     { "ADCL", NULL, "PGAL" },
0270     { "ADCR", NULL, "PGAR" },
0271 
0272     { "AIF", NULL, "ADCL" },
0273     { "AIF", NULL, "ADCR" },
0274 };
0275 
0276 /* codec mclk clock divider coefficients */
0277 static const struct {
0278     u32 mclk;
0279     u32 rate;
0280     u8 usb;
0281     u8 sr;
0282 } coeff_div[] = {
0283     { 12288000,  8000, 0,  0x4 },
0284     { 12288000, 12000, 0,  0x8 },
0285     { 12288000, 16000, 0,  0xa },
0286     { 12288000, 24000, 0, 0x1c },
0287     { 12288000, 32000, 0,  0xc },
0288     { 12288000, 48000, 0,    0 },
0289     { 12288000, 96000, 0,  0xe },
0290 
0291     { 11289600,  8000, 0, 0x14 },
0292     { 11289600, 11025, 0, 0x18 },
0293     { 11289600, 22050, 0, 0x1a },
0294     { 11289600, 44100, 0, 0x10 },
0295     { 11289600, 88200, 0, 0x1e },
0296 
0297     { 18432000,  8000, 0,  0x5 },
0298     { 18432000, 12000, 0,  0x9 },
0299     { 18432000, 16000, 0,  0xb },
0300     { 18432000, 24000, 0, 0x1b },
0301     { 18432000, 32000, 0,  0xd },
0302     { 18432000, 48000, 0,  0x1 },
0303     { 18432000, 96000, 0, 0x1f },
0304 
0305     { 16934400,  8000, 0, 0x15 },
0306     { 16934400, 11025, 0, 0x19 },
0307     { 16934400, 22050, 0, 0x1b },
0308     { 16934400, 44100, 0, 0x11 },
0309     { 16934400, 88200, 0, 0x1f },
0310 
0311     { 12000000,  8000, 1,  0x4 },
0312     { 12000000, 11025, 1, 0x19 },
0313     { 12000000, 12000, 1,  0x8 },
0314     { 12000000, 16000, 1,  0xa },
0315     { 12000000, 22050, 1, 0x1b },
0316     { 12000000, 24000, 1, 0x1c },
0317     { 12000000, 32000, 1,  0xc },
0318     { 12000000, 44100, 1, 0x11 },
0319     { 12000000, 48000, 1,  0x0 },
0320     { 12000000, 88200, 1, 0x1f },
0321     { 12000000, 96000, 1,  0xe },
0322 };
0323 
0324 static int wm8737_hw_params(struct snd_pcm_substream *substream,
0325                 struct snd_pcm_hw_params *params,
0326                 struct snd_soc_dai *dai)
0327 {
0328     struct snd_soc_component *component = dai->component;
0329     struct wm8737_priv *wm8737 = snd_soc_component_get_drvdata(component);
0330     int i;
0331     u16 clocking = 0;
0332     u16 af = 0;
0333 
0334     for (i = 0; i < ARRAY_SIZE(coeff_div); i++) {
0335         if (coeff_div[i].rate != params_rate(params))
0336             continue;
0337 
0338         if (coeff_div[i].mclk == wm8737->mclk)
0339             break;
0340 
0341         if (coeff_div[i].mclk == wm8737->mclk * 2) {
0342             clocking |= WM8737_CLKDIV2;
0343             break;
0344         }
0345     }
0346 
0347     if (i == ARRAY_SIZE(coeff_div)) {
0348         dev_err(component->dev, "%dHz MCLK can't support %dHz\n",
0349             wm8737->mclk, params_rate(params));
0350         return -EINVAL;
0351     }
0352 
0353     clocking |= coeff_div[i].usb | (coeff_div[i].sr << WM8737_SR_SHIFT);
0354 
0355     switch (params_width(params)) {
0356     case 16:
0357         break;
0358     case 20:
0359         af |= 0x8;
0360         break;
0361     case 24:
0362         af |= 0x10;
0363         break;
0364     case 32:
0365         af |= 0x18;
0366         break;
0367     default:
0368         return -EINVAL;
0369     }
0370 
0371     snd_soc_component_update_bits(component, WM8737_AUDIO_FORMAT, WM8737_WL_MASK, af);
0372     snd_soc_component_update_bits(component, WM8737_CLOCKING,
0373                 WM8737_USB_MODE | WM8737_CLKDIV2 | WM8737_SR_MASK,
0374                 clocking);
0375 
0376     return 0;
0377 }
0378 
0379 static int wm8737_set_dai_sysclk(struct snd_soc_dai *codec_dai,
0380                  int clk_id, unsigned int freq, int dir)
0381 {
0382     struct snd_soc_component *component = codec_dai->component;
0383     struct wm8737_priv *wm8737 = snd_soc_component_get_drvdata(component);
0384     int i;
0385 
0386     for (i = 0; i < ARRAY_SIZE(coeff_div); i++) {
0387         if (freq == coeff_div[i].mclk ||
0388             freq == coeff_div[i].mclk * 2) {
0389             wm8737->mclk = freq;
0390             return 0;
0391         }
0392     }
0393 
0394     dev_err(component->dev, "MCLK rate %dHz not supported\n", freq);
0395 
0396     return -EINVAL;
0397 }
0398 
0399 
0400 static int wm8737_set_dai_fmt(struct snd_soc_dai *codec_dai,
0401         unsigned int fmt)
0402 {
0403     struct snd_soc_component *component = codec_dai->component;
0404     u16 af = 0;
0405 
0406     switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
0407     case SND_SOC_DAIFMT_CBM_CFM:
0408         af |= WM8737_MS;
0409         break;
0410     case SND_SOC_DAIFMT_CBS_CFS:
0411         break;
0412     default:
0413         return -EINVAL;
0414     }
0415 
0416     switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
0417     case SND_SOC_DAIFMT_I2S:
0418         af |= 0x2;
0419         break;
0420     case SND_SOC_DAIFMT_RIGHT_J:
0421         break;
0422     case SND_SOC_DAIFMT_LEFT_J:
0423         af |= 0x1;
0424         break;
0425     case SND_SOC_DAIFMT_DSP_A:
0426         af |= 0x3;
0427         break;
0428     case SND_SOC_DAIFMT_DSP_B:
0429         af |= 0x13;
0430         break;
0431     default:
0432         return -EINVAL;
0433     }
0434 
0435     switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
0436     case SND_SOC_DAIFMT_NB_NF:
0437         break;
0438     case SND_SOC_DAIFMT_NB_IF:
0439         af |= WM8737_LRP;
0440         break;
0441     default:
0442         return -EINVAL;
0443     }
0444 
0445     snd_soc_component_update_bits(component, WM8737_AUDIO_FORMAT,
0446                 WM8737_FORMAT_MASK | WM8737_LRP | WM8737_MS, af);
0447 
0448     return 0;
0449 }
0450 
0451 static int wm8737_set_bias_level(struct snd_soc_component *component,
0452                  enum snd_soc_bias_level level)
0453 {
0454     struct wm8737_priv *wm8737 = snd_soc_component_get_drvdata(component);
0455     int ret;
0456 
0457     switch (level) {
0458     case SND_SOC_BIAS_ON:
0459         break;
0460 
0461     case SND_SOC_BIAS_PREPARE:
0462         /* VMID at 2*75k */
0463         snd_soc_component_update_bits(component, WM8737_MISC_BIAS_CONTROL,
0464                     WM8737_VMIDSEL_MASK, 0);
0465         break;
0466 
0467     case SND_SOC_BIAS_STANDBY:
0468         if (snd_soc_component_get_bias_level(component) == SND_SOC_BIAS_OFF) {
0469             ret = regulator_bulk_enable(ARRAY_SIZE(wm8737->supplies),
0470                             wm8737->supplies);
0471             if (ret != 0) {
0472                 dev_err(component->dev,
0473                     "Failed to enable supplies: %d\n",
0474                     ret);
0475                 return ret;
0476             }
0477 
0478             regcache_sync(wm8737->regmap);
0479 
0480             /* Fast VMID ramp at 2*2.5k */
0481             snd_soc_component_update_bits(component, WM8737_MISC_BIAS_CONTROL,
0482                         WM8737_VMIDSEL_MASK,
0483                         2 << WM8737_VMIDSEL_SHIFT);
0484 
0485             /* Bring VMID up */
0486             snd_soc_component_update_bits(component, WM8737_POWER_MANAGEMENT,
0487                         WM8737_VMID_MASK |
0488                         WM8737_VREF_MASK,
0489                         WM8737_VMID_MASK |
0490                         WM8737_VREF_MASK);
0491 
0492             msleep(500);
0493         }
0494 
0495         /* VMID at 2*300k */
0496         snd_soc_component_update_bits(component, WM8737_MISC_BIAS_CONTROL,
0497                     WM8737_VMIDSEL_MASK,
0498                     1 << WM8737_VMIDSEL_SHIFT);
0499 
0500         break;
0501 
0502     case SND_SOC_BIAS_OFF:
0503         snd_soc_component_update_bits(component, WM8737_POWER_MANAGEMENT,
0504                     WM8737_VMID_MASK | WM8737_VREF_MASK, 0);
0505 
0506         regulator_bulk_disable(ARRAY_SIZE(wm8737->supplies),
0507                        wm8737->supplies);
0508         break;
0509     }
0510 
0511     return 0;
0512 }
0513 
0514 #define WM8737_RATES SNDRV_PCM_RATE_8000_96000
0515 
0516 #define WM8737_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE |\
0517             SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S32_LE)
0518 
0519 static const struct snd_soc_dai_ops wm8737_dai_ops = {
0520     .hw_params  = wm8737_hw_params,
0521     .set_sysclk = wm8737_set_dai_sysclk,
0522     .set_fmt    = wm8737_set_dai_fmt,
0523 };
0524 
0525 static struct snd_soc_dai_driver wm8737_dai = {
0526     .name = "wm8737",
0527     .capture = {
0528         .stream_name = "Capture",
0529         .channels_min = 2,  /* Mono modes not yet supported */
0530         .channels_max = 2,
0531         .rates = WM8737_RATES,
0532         .formats = WM8737_FORMATS,
0533     },
0534     .ops = &wm8737_dai_ops,
0535 };
0536 
0537 static int wm8737_probe(struct snd_soc_component *component)
0538 {
0539     struct wm8737_priv *wm8737 = snd_soc_component_get_drvdata(component);
0540     int ret;
0541 
0542     ret = regulator_bulk_enable(ARRAY_SIZE(wm8737->supplies),
0543                     wm8737->supplies);
0544     if (ret != 0) {
0545         dev_err(component->dev, "Failed to enable supplies: %d\n", ret);
0546         goto err_get;
0547     }
0548 
0549     ret = wm8737_reset(component);
0550     if (ret < 0) {
0551         dev_err(component->dev, "Failed to issue reset\n");
0552         goto err_enable;
0553     }
0554 
0555     snd_soc_component_update_bits(component, WM8737_LEFT_PGA_VOLUME, WM8737_LVU,
0556                 WM8737_LVU);
0557     snd_soc_component_update_bits(component, WM8737_RIGHT_PGA_VOLUME, WM8737_RVU,
0558                 WM8737_RVU);
0559 
0560     snd_soc_component_force_bias_level(component, SND_SOC_BIAS_STANDBY);
0561 
0562     /* Bias level configuration will have done an extra enable */
0563     regulator_bulk_disable(ARRAY_SIZE(wm8737->supplies), wm8737->supplies);
0564 
0565     return 0;
0566 
0567 err_enable:
0568     regulator_bulk_disable(ARRAY_SIZE(wm8737->supplies), wm8737->supplies);
0569 err_get:
0570     return ret;
0571 }
0572 
0573 static const struct snd_soc_component_driver soc_component_dev_wm8737 = {
0574     .probe          = wm8737_probe,
0575     .set_bias_level     = wm8737_set_bias_level,
0576     .controls       = wm8737_snd_controls,
0577     .num_controls       = ARRAY_SIZE(wm8737_snd_controls),
0578     .dapm_widgets       = wm8737_dapm_widgets,
0579     .num_dapm_widgets   = ARRAY_SIZE(wm8737_dapm_widgets),
0580     .dapm_routes        = intercon,
0581     .num_dapm_routes    = ARRAY_SIZE(intercon),
0582     .suspend_bias_off   = 1,
0583     .idle_bias_on       = 1,
0584     .use_pmdown_time    = 1,
0585     .endianness     = 1,
0586 };
0587 
0588 static const struct of_device_id wm8737_of_match[] = {
0589     { .compatible = "wlf,wm8737", },
0590     { }
0591 };
0592 
0593 MODULE_DEVICE_TABLE(of, wm8737_of_match);
0594 
0595 static const struct regmap_config wm8737_regmap = {
0596     .reg_bits = 7,
0597     .val_bits = 9,
0598     .max_register = WM8737_MAX_REGISTER,
0599 
0600     .reg_defaults = wm8737_reg_defaults,
0601     .num_reg_defaults = ARRAY_SIZE(wm8737_reg_defaults),
0602     .cache_type = REGCACHE_RBTREE,
0603 
0604     .volatile_reg = wm8737_volatile,
0605 };
0606 
0607 #if IS_ENABLED(CONFIG_I2C)
0608 static int wm8737_i2c_probe(struct i2c_client *i2c)
0609 {
0610     struct wm8737_priv *wm8737;
0611     int ret, i;
0612 
0613     wm8737 = devm_kzalloc(&i2c->dev, sizeof(struct wm8737_priv),
0614                   GFP_KERNEL);
0615     if (wm8737 == NULL)
0616         return -ENOMEM;
0617 
0618     for (i = 0; i < ARRAY_SIZE(wm8737->supplies); i++)
0619         wm8737->supplies[i].supply = wm8737_supply_names[i];
0620 
0621     ret = devm_regulator_bulk_get(&i2c->dev, ARRAY_SIZE(wm8737->supplies),
0622                       wm8737->supplies);
0623     if (ret != 0) {
0624         dev_err(&i2c->dev, "Failed to request supplies: %d\n", ret);
0625         return ret;
0626     }
0627 
0628     wm8737->regmap = devm_regmap_init_i2c(i2c, &wm8737_regmap);
0629     if (IS_ERR(wm8737->regmap))
0630         return PTR_ERR(wm8737->regmap);
0631 
0632     i2c_set_clientdata(i2c, wm8737);
0633 
0634     ret = devm_snd_soc_register_component(&i2c->dev,
0635                 &soc_component_dev_wm8737, &wm8737_dai, 1);
0636 
0637     return ret;
0638 
0639 }
0640 
0641 static const struct i2c_device_id wm8737_i2c_id[] = {
0642     { "wm8737", 0 },
0643     { }
0644 };
0645 MODULE_DEVICE_TABLE(i2c, wm8737_i2c_id);
0646 
0647 static struct i2c_driver wm8737_i2c_driver = {
0648     .driver = {
0649         .name = "wm8737",
0650         .of_match_table = wm8737_of_match,
0651     },
0652     .probe_new = wm8737_i2c_probe,
0653     .id_table = wm8737_i2c_id,
0654 };
0655 #endif
0656 
0657 #if defined(CONFIG_SPI_MASTER)
0658 static int wm8737_spi_probe(struct spi_device *spi)
0659 {
0660     struct wm8737_priv *wm8737;
0661     int ret, i;
0662 
0663     wm8737 = devm_kzalloc(&spi->dev, sizeof(struct wm8737_priv),
0664                   GFP_KERNEL);
0665     if (wm8737 == NULL)
0666         return -ENOMEM;
0667 
0668     for (i = 0; i < ARRAY_SIZE(wm8737->supplies); i++)
0669         wm8737->supplies[i].supply = wm8737_supply_names[i];
0670 
0671     ret = devm_regulator_bulk_get(&spi->dev, ARRAY_SIZE(wm8737->supplies),
0672                       wm8737->supplies);
0673     if (ret != 0) {
0674         dev_err(&spi->dev, "Failed to request supplies: %d\n", ret);
0675         return ret;
0676     }
0677 
0678     wm8737->regmap = devm_regmap_init_spi(spi, &wm8737_regmap);
0679     if (IS_ERR(wm8737->regmap))
0680         return PTR_ERR(wm8737->regmap);
0681 
0682     spi_set_drvdata(spi, wm8737);
0683 
0684     ret = devm_snd_soc_register_component(&spi->dev,
0685                 &soc_component_dev_wm8737, &wm8737_dai, 1);
0686 
0687     return ret;
0688 }
0689 
0690 static struct spi_driver wm8737_spi_driver = {
0691     .driver = {
0692         .name   = "wm8737",
0693         .of_match_table = wm8737_of_match,
0694     },
0695     .probe      = wm8737_spi_probe,
0696 };
0697 #endif /* CONFIG_SPI_MASTER */
0698 
0699 static int __init wm8737_modinit(void)
0700 {
0701     int ret;
0702 #if IS_ENABLED(CONFIG_I2C)
0703     ret = i2c_add_driver(&wm8737_i2c_driver);
0704     if (ret != 0) {
0705         printk(KERN_ERR "Failed to register WM8737 I2C driver: %d\n",
0706                ret);
0707     }
0708 #endif
0709 #if defined(CONFIG_SPI_MASTER)
0710     ret = spi_register_driver(&wm8737_spi_driver);
0711     if (ret != 0) {
0712         printk(KERN_ERR "Failed to register WM8737 SPI driver: %d\n",
0713                ret);
0714     }
0715 #endif
0716     return 0;
0717 }
0718 module_init(wm8737_modinit);
0719 
0720 static void __exit wm8737_exit(void)
0721 {
0722 #if defined(CONFIG_SPI_MASTER)
0723     spi_unregister_driver(&wm8737_spi_driver);
0724 #endif
0725 #if IS_ENABLED(CONFIG_I2C)
0726     i2c_del_driver(&wm8737_i2c_driver);
0727 #endif
0728 }
0729 module_exit(wm8737_exit);
0730 
0731 MODULE_DESCRIPTION("ASoC WM8737 driver");
0732 MODULE_AUTHOR("Mark Brown <broonie@opensource.wolfsonmicro.com>");
0733 MODULE_LICENSE("GPL");