1 // SPDX-License-Identifier: GPL-2.0-only 2 /* 3 * wm8940.c -- WM8940 ALSA Soc Audio driver 4 * 5 * Author: Jonathan Cameron <jic23@cam.ac.uk> 6 * 7 * Based on wm8510.c 8 * Copyright 2006 Wolfson Microelectronics PLC. 9 * Author: Liam Girdwood <lrg@slimlogic.co.uk> 10 * 11 * Not currently handled: 12 * Notch filter control 13 * AUXMode (inverting vs mixer) 14 * No means to obtain current gain if alc enabled. 15 * No use made of gpio 16 * Fast VMID discharge for power down 17 * Soft Start 18 * DLR and ALR Swaps not enabled 19 * Digital Sidetone not supported 20 */ 21 #include <linux/module.h> 22 #include <linux/moduleparam.h> 23 #include <linux/kernel.h> 24 #include <linux/init.h> 25 #include <linux/delay.h> 26 #include <linux/pm.h> 27 #include <linux/i2c.h> 28 #include <linux/regmap.h> 29 #include <linux/slab.h> 30 #include <sound/core.h> 31 #include <sound/pcm.h> 32 #include <sound/pcm_params.h> 33 #include <sound/soc.h> 34 #include <sound/initval.h> 35 #include <sound/tlv.h> 36 37 #include "wm8940.h" 38 39 struct wm8940_priv { 40 unsigned int mclk; 41 unsigned int fs; 42 43 struct regmap *regmap; 44 }; 45 46 static bool wm8940_volatile_register(struct device *dev, unsigned int reg) 47 { 48 switch (reg) { 49 case WM8940_SOFTRESET: 50 return true; 51 default: 52 return false; 53 } 54 } 55 56 static bool wm8940_readable_register(struct device *dev, unsigned int reg) 57 { 58 switch (reg) { 59 case WM8940_SOFTRESET: 60 case WM8940_POWER1: 61 case WM8940_POWER2: 62 case WM8940_POWER3: 63 case WM8940_IFACE: 64 case WM8940_COMPANDINGCTL: 65 case WM8940_CLOCK: 66 case WM8940_ADDCNTRL: 67 case WM8940_GPIO: 68 case WM8940_CTLINT: 69 case WM8940_DAC: 70 case WM8940_DACVOL: 71 case WM8940_ADC: 72 case WM8940_ADCVOL: 73 case WM8940_NOTCH1: 74 case WM8940_NOTCH2: 75 case WM8940_NOTCH3: 76 case WM8940_NOTCH4: 77 case WM8940_NOTCH5: 78 case WM8940_NOTCH6: 79 case WM8940_NOTCH7: 80 case WM8940_NOTCH8: 81 case WM8940_DACLIM1: 82 case WM8940_DACLIM2: 83 case WM8940_ALC1: 84 case WM8940_ALC2: 85 case WM8940_ALC3: 86 case WM8940_NOISEGATE: 87 case WM8940_PLLN: 88 case WM8940_PLLK1: 89 case WM8940_PLLK2: 90 case WM8940_PLLK3: 91 case WM8940_ALC4: 92 case WM8940_INPUTCTL: 93 case WM8940_PGAGAIN: 94 case WM8940_ADCBOOST: 95 case WM8940_OUTPUTCTL: 96 case WM8940_SPKMIX: 97 case WM8940_SPKVOL: 98 case WM8940_MONOMIX: 99 return true; 100 default: 101 return false; 102 } 103 } 104 105 static const struct reg_default wm8940_reg_defaults[] = { 106 { 0x1, 0x0000 }, /* Power 1 */ 107 { 0x2, 0x0000 }, /* Power 2 */ 108 { 0x3, 0x0000 }, /* Power 3 */ 109 { 0x4, 0x0010 }, /* Interface Control */ 110 { 0x5, 0x0000 }, /* Companding Control */ 111 { 0x6, 0x0140 }, /* Clock Control */ 112 { 0x7, 0x0000 }, /* Additional Controls */ 113 { 0x8, 0x0000 }, /* GPIO Control */ 114 { 0x9, 0x0002 }, /* Auto Increment Control */ 115 { 0xa, 0x0000 }, /* DAC Control */ 116 { 0xb, 0x00FF }, /* DAC Volume */ 117 118 { 0xe, 0x0100 }, /* ADC Control */ 119 { 0xf, 0x00FF }, /* ADC Volume */ 120 { 0x10, 0x0000 }, /* Notch Filter 1 Control 1 */ 121 { 0x11, 0x0000 }, /* Notch Filter 1 Control 2 */ 122 { 0x12, 0x0000 }, /* Notch Filter 2 Control 1 */ 123 { 0x13, 0x0000 }, /* Notch Filter 2 Control 2 */ 124 { 0x14, 0x0000 }, /* Notch Filter 3 Control 1 */ 125 { 0x15, 0x0000 }, /* Notch Filter 3 Control 2 */ 126 { 0x16, 0x0000 }, /* Notch Filter 4 Control 1 */ 127 { 0x17, 0x0000 }, /* Notch Filter 4 Control 2 */ 128 { 0x18, 0x0032 }, /* DAC Limit Control 1 */ 129 { 0x19, 0x0000 }, /* DAC Limit Control 2 */ 130 131 { 0x20, 0x0038 }, /* ALC Control 1 */ 132 { 0x21, 0x000B }, /* ALC Control 2 */ 133 { 0x22, 0x0032 }, /* ALC Control 3 */ 134 { 0x23, 0x0000 }, /* Noise Gate */ 135 { 0x24, 0x0041 }, /* PLLN */ 136 { 0x25, 0x000C }, /* PLLK1 */ 137 { 0x26, 0x0093 }, /* PLLK2 */ 138 { 0x27, 0x00E9 }, /* PLLK3 */ 139 140 { 0x2a, 0x0030 }, /* ALC Control 4 */ 141 142 { 0x2c, 0x0002 }, /* Input Control */ 143 { 0x2d, 0x0050 }, /* PGA Gain */ 144 145 { 0x2f, 0x0002 }, /* ADC Boost Control */ 146 147 { 0x31, 0x0002 }, /* Output Control */ 148 { 0x32, 0x0000 }, /* Speaker Mixer Control */ 149 150 { 0x36, 0x0079 }, /* Speaker Volume */ 151 152 { 0x38, 0x0000 }, /* Mono Mixer Control */ 153 }; 154 155 static const char *wm8940_companding[] = { "Off", "NC", "u-law", "A-law" }; 156 static SOC_ENUM_SINGLE_DECL(wm8940_adc_companding_enum, 157 WM8940_COMPANDINGCTL, 1, wm8940_companding); 158 static SOC_ENUM_SINGLE_DECL(wm8940_dac_companding_enum, 159 WM8940_COMPANDINGCTL, 3, wm8940_companding); 160 161 static const char *wm8940_alc_mode_text[] = {"ALC", "Limiter"}; 162 static SOC_ENUM_SINGLE_DECL(wm8940_alc_mode_enum, 163 WM8940_ALC3, 8, wm8940_alc_mode_text); 164 165 static const char *wm8940_mic_bias_level_text[] = {"0.9", "0.65"}; 166 static SOC_ENUM_SINGLE_DECL(wm8940_mic_bias_level_enum, 167 WM8940_INPUTCTL, 8, wm8940_mic_bias_level_text); 168 169 static const char *wm8940_filter_mode_text[] = {"Audio", "Application"}; 170 static SOC_ENUM_SINGLE_DECL(wm8940_filter_mode_enum, 171 WM8940_ADC, 7, wm8940_filter_mode_text); 172 173 static DECLARE_TLV_DB_SCALE(wm8940_spk_vol_tlv, -5700, 100, 1); 174 static DECLARE_TLV_DB_SCALE(wm8940_att_tlv, -1000, 1000, 0); 175 static DECLARE_TLV_DB_SCALE(wm8940_pga_vol_tlv, -1200, 75, 0); 176 static DECLARE_TLV_DB_SCALE(wm8940_alc_min_tlv, -1200, 600, 0); 177 static DECLARE_TLV_DB_SCALE(wm8940_alc_max_tlv, 675, 600, 0); 178 static DECLARE_TLV_DB_SCALE(wm8940_alc_tar_tlv, -2250, 50, 0); 179 static DECLARE_TLV_DB_SCALE(wm8940_lim_boost_tlv, 0, 100, 0); 180 static DECLARE_TLV_DB_SCALE(wm8940_lim_thresh_tlv, -600, 100, 0); 181 static DECLARE_TLV_DB_SCALE(wm8940_adc_tlv, -12750, 50, 1); 182 static DECLARE_TLV_DB_SCALE(wm8940_capture_boost_vol_tlv, 0, 2000, 0); 183 184 static const struct snd_kcontrol_new wm8940_snd_controls[] = { 185 SOC_SINGLE("Digital Loopback Switch", WM8940_COMPANDINGCTL, 186 6, 1, 0), 187 SOC_ENUM("DAC Companding", wm8940_dac_companding_enum), 188 SOC_ENUM("ADC Companding", wm8940_adc_companding_enum), 189 190 SOC_ENUM("ALC Mode", wm8940_alc_mode_enum), 191 SOC_SINGLE("ALC Switch", WM8940_ALC1, 8, 1, 0), 192 SOC_SINGLE_TLV("ALC Capture Max Gain", WM8940_ALC1, 193 3, 7, 1, wm8940_alc_max_tlv), 194 SOC_SINGLE_TLV("ALC Capture Min Gain", WM8940_ALC1, 195 0, 7, 0, wm8940_alc_min_tlv), 196 SOC_SINGLE_TLV("ALC Capture Target", WM8940_ALC2, 197 0, 14, 0, wm8940_alc_tar_tlv), 198 SOC_SINGLE("ALC Capture Hold", WM8940_ALC2, 4, 10, 0), 199 SOC_SINGLE("ALC Capture Decay", WM8940_ALC3, 4, 10, 0), 200 SOC_SINGLE("ALC Capture Attach", WM8940_ALC3, 0, 10, 0), 201 SOC_SINGLE("ALC ZC Switch", WM8940_ALC4, 1, 1, 0), 202 SOC_SINGLE("ALC Capture Noise Gate Switch", WM8940_NOISEGATE, 203 3, 1, 0), 204 SOC_SINGLE("ALC Capture Noise Gate Threshold", WM8940_NOISEGATE, 205 0, 7, 0), 206 207 SOC_SINGLE("DAC Playback Limiter Switch", WM8940_DACLIM1, 8, 1, 0), 208 SOC_SINGLE("DAC Playback Limiter Attack", WM8940_DACLIM1, 0, 9, 0), 209 SOC_SINGLE("DAC Playback Limiter Decay", WM8940_DACLIM1, 4, 11, 0), 210 SOC_SINGLE_TLV("DAC Playback Limiter Threshold", WM8940_DACLIM2, 211 4, 9, 1, wm8940_lim_thresh_tlv), 212 SOC_SINGLE_TLV("DAC Playback Limiter Boost", WM8940_DACLIM2, 213 0, 12, 0, wm8940_lim_boost_tlv), 214 215 SOC_SINGLE("Capture PGA ZC Switch", WM8940_PGAGAIN, 7, 1, 0), 216 SOC_SINGLE_TLV("Capture PGA Volume", WM8940_PGAGAIN, 217 0, 63, 0, wm8940_pga_vol_tlv), 218 SOC_SINGLE_TLV("Digital Playback Volume", WM8940_DACVOL, 219 0, 255, 0, wm8940_adc_tlv), 220 SOC_SINGLE_TLV("Digital Capture Volume", WM8940_ADCVOL, 221 0, 255, 0, wm8940_adc_tlv), 222 SOC_ENUM("Mic Bias Level", wm8940_mic_bias_level_enum), 223 SOC_SINGLE_TLV("Capture Boost Volue", WM8940_ADCBOOST, 224 8, 1, 0, wm8940_capture_boost_vol_tlv), 225 SOC_SINGLE_TLV("Speaker Playback Volume", WM8940_SPKVOL, 226 0, 63, 0, wm8940_spk_vol_tlv), 227 SOC_SINGLE("Speaker Playback Switch", WM8940_SPKVOL, 6, 1, 1), 228 229 SOC_SINGLE_TLV("Speaker Mixer Line Bypass Volume", WM8940_SPKVOL, 230 8, 1, 1, wm8940_att_tlv), 231 SOC_SINGLE("Speaker Playback ZC Switch", WM8940_SPKVOL, 7, 1, 0), 232 233 SOC_SINGLE("Mono Out Switch", WM8940_MONOMIX, 6, 1, 1), 234 SOC_SINGLE_TLV("Mono Mixer Line Bypass Volume", WM8940_MONOMIX, 235 7, 1, 1, wm8940_att_tlv), 236 237 SOC_SINGLE("High Pass Filter Switch", WM8940_ADC, 8, 1, 0), 238 SOC_ENUM("High Pass Filter Mode", wm8940_filter_mode_enum), 239 SOC_SINGLE("High Pass Filter Cut Off", WM8940_ADC, 4, 7, 0), 240 SOC_SINGLE("ADC Inversion Switch", WM8940_ADC, 0, 1, 0), 241 SOC_SINGLE("DAC Inversion Switch", WM8940_DAC, 0, 1, 0), 242 SOC_SINGLE("DAC Auto Mute Switch", WM8940_DAC, 2, 1, 0), 243 SOC_SINGLE("ZC Timeout Clock Switch", WM8940_ADDCNTRL, 0, 1, 0), 244 }; 245 246 static const struct snd_kcontrol_new wm8940_speaker_mixer_controls[] = { 247 SOC_DAPM_SINGLE("Line Bypass Switch", WM8940_SPKMIX, 1, 1, 0), 248 SOC_DAPM_SINGLE("Aux Playback Switch", WM8940_SPKMIX, 5, 1, 0), 249 SOC_DAPM_SINGLE("PCM Playback Switch", WM8940_SPKMIX, 0, 1, 0), 250 }; 251 252 static const struct snd_kcontrol_new wm8940_mono_mixer_controls[] = { 253 SOC_DAPM_SINGLE("Line Bypass Switch", WM8940_MONOMIX, 1, 1, 0), 254 SOC_DAPM_SINGLE("Aux Playback Switch", WM8940_MONOMIX, 2, 1, 0), 255 SOC_DAPM_SINGLE("PCM Playback Switch", WM8940_MONOMIX, 0, 1, 0), 256 }; 257 258 static DECLARE_TLV_DB_SCALE(wm8940_boost_vol_tlv, -1500, 300, 1); 259 static const struct snd_kcontrol_new wm8940_input_boost_controls[] = { 260 SOC_DAPM_SINGLE("Mic PGA Switch", WM8940_PGAGAIN, 6, 1, 1), 261 SOC_DAPM_SINGLE_TLV("Aux Volume", WM8940_ADCBOOST, 262 0, 7, 0, wm8940_boost_vol_tlv), 263 SOC_DAPM_SINGLE_TLV("Mic Volume", WM8940_ADCBOOST, 264 4, 7, 0, wm8940_boost_vol_tlv), 265 }; 266 267 static const struct snd_kcontrol_new wm8940_micpga_controls[] = { 268 SOC_DAPM_SINGLE("AUX Switch", WM8940_INPUTCTL, 2, 1, 0), 269 SOC_DAPM_SINGLE("MICP Switch", WM8940_INPUTCTL, 0, 1, 0), 270 SOC_DAPM_SINGLE("MICN Switch", WM8940_INPUTCTL, 1, 1, 0), 271 }; 272 273 static const struct snd_soc_dapm_widget wm8940_dapm_widgets[] = { 274 SND_SOC_DAPM_MIXER("Speaker Mixer", WM8940_POWER3, 2, 0, 275 &wm8940_speaker_mixer_controls[0], 276 ARRAY_SIZE(wm8940_speaker_mixer_controls)), 277 SND_SOC_DAPM_MIXER("Mono Mixer", WM8940_POWER3, 3, 0, 278 &wm8940_mono_mixer_controls[0], 279 ARRAY_SIZE(wm8940_mono_mixer_controls)), 280 SND_SOC_DAPM_DAC("DAC", "HiFi Playback", WM8940_POWER3, 0, 0), 281 282 SND_SOC_DAPM_PGA("SpkN Out", WM8940_POWER3, 5, 0, NULL, 0), 283 SND_SOC_DAPM_PGA("SpkP Out", WM8940_POWER3, 6, 0, NULL, 0), 284 SND_SOC_DAPM_PGA("Mono Out", WM8940_POWER3, 7, 0, NULL, 0), 285 SND_SOC_DAPM_OUTPUT("MONOOUT"), 286 SND_SOC_DAPM_OUTPUT("SPKOUTP"), 287 SND_SOC_DAPM_OUTPUT("SPKOUTN"), 288 289 SND_SOC_DAPM_PGA("Aux Input", WM8940_POWER1, 6, 0, NULL, 0), 290 SND_SOC_DAPM_ADC("ADC", "HiFi Capture", WM8940_POWER2, 0, 0), 291 SND_SOC_DAPM_MIXER("Mic PGA", WM8940_POWER2, 2, 0, 292 &wm8940_micpga_controls[0], 293 ARRAY_SIZE(wm8940_micpga_controls)), 294 SND_SOC_DAPM_MIXER("Boost Mixer", WM8940_POWER2, 4, 0, 295 &wm8940_input_boost_controls[0], 296 ARRAY_SIZE(wm8940_input_boost_controls)), 297 SND_SOC_DAPM_MICBIAS("Mic Bias", WM8940_POWER1, 4, 0), 298 299 SND_SOC_DAPM_INPUT("MICN"), 300 SND_SOC_DAPM_INPUT("MICP"), 301 SND_SOC_DAPM_INPUT("AUX"), 302 }; 303 304 static const struct snd_soc_dapm_route wm8940_dapm_routes[] = { 305 /* Mono output mixer */ 306 {"Mono Mixer", "PCM Playback Switch", "DAC"}, 307 {"Mono Mixer", "Aux Playback Switch", "Aux Input"}, 308 {"Mono Mixer", "Line Bypass Switch", "Boost Mixer"}, 309 310 /* Speaker output mixer */ 311 {"Speaker Mixer", "PCM Playback Switch", "DAC"}, 312 {"Speaker Mixer", "Aux Playback Switch", "Aux Input"}, 313 {"Speaker Mixer", "Line Bypass Switch", "Boost Mixer"}, 314 315 /* Outputs */ 316 {"Mono Out", NULL, "Mono Mixer"}, 317 {"MONOOUT", NULL, "Mono Out"}, 318 {"SpkN Out", NULL, "Speaker Mixer"}, 319 {"SpkP Out", NULL, "Speaker Mixer"}, 320 {"SPKOUTN", NULL, "SpkN Out"}, 321 {"SPKOUTP", NULL, "SpkP Out"}, 322 323 /* Microphone PGA */ 324 {"Mic PGA", "MICN Switch", "MICN"}, 325 {"Mic PGA", "MICP Switch", "MICP"}, 326 {"Mic PGA", "AUX Switch", "AUX"}, 327 328 /* Boost Mixer */ 329 {"Boost Mixer", "Mic PGA Switch", "Mic PGA"}, 330 {"Boost Mixer", "Mic Volume", "MICP"}, 331 {"Boost Mixer", "Aux Volume", "Aux Input"}, 332 333 {"ADC", NULL, "Boost Mixer"}, 334 }; 335 336 #define wm8940_reset(c) snd_soc_component_write(c, WM8940_SOFTRESET, 0); 337 338 static int wm8940_set_dai_fmt(struct snd_soc_dai *codec_dai, 339 unsigned int fmt) 340 { 341 struct snd_soc_component *component = codec_dai->component; 342 u16 iface = snd_soc_component_read(component, WM8940_IFACE) & 0xFE67; 343 u16 clk = snd_soc_component_read(component, WM8940_CLOCK) & 0x1fe; 344 345 switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { 346 case SND_SOC_DAIFMT_CBM_CFM: 347 clk |= 1; 348 break; 349 case SND_SOC_DAIFMT_CBS_CFS: 350 break; 351 default: 352 return -EINVAL; 353 } 354 snd_soc_component_write(component, WM8940_CLOCK, clk); 355 356 switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { 357 case SND_SOC_DAIFMT_I2S: 358 iface |= (2 << 3); 359 break; 360 case SND_SOC_DAIFMT_LEFT_J: 361 iface |= (1 << 3); 362 break; 363 case SND_SOC_DAIFMT_RIGHT_J: 364 break; 365 case SND_SOC_DAIFMT_DSP_A: 366 iface |= (3 << 3); 367 break; 368 case SND_SOC_DAIFMT_DSP_B: 369 iface |= (3 << 3) | (1 << 7); 370 break; 371 } 372 373 switch (fmt & SND_SOC_DAIFMT_INV_MASK) { 374 case SND_SOC_DAIFMT_NB_NF: 375 break; 376 case SND_SOC_DAIFMT_NB_IF: 377 iface |= (1 << 7); 378 break; 379 case SND_SOC_DAIFMT_IB_NF: 380 iface |= (1 << 8); 381 break; 382 case SND_SOC_DAIFMT_IB_IF: 383 iface |= (1 << 8) | (1 << 7); 384 break; 385 } 386 387 snd_soc_component_write(component, WM8940_IFACE, iface); 388 389 return 0; 390 } 391 392 static int wm8940_update_clocks(struct snd_soc_dai *dai); 393 static int wm8940_i2s_hw_params(struct snd_pcm_substream *substream, 394 struct snd_pcm_hw_params *params, 395 struct snd_soc_dai *dai) 396 { 397 struct snd_soc_component *component = dai->component; 398 struct wm8940_priv *priv = snd_soc_component_get_drvdata(component); 399 u16 iface = snd_soc_component_read(component, WM8940_IFACE) & 0xFD9F; 400 u16 addcntrl = snd_soc_component_read(component, WM8940_ADDCNTRL) & 0xFFF1; 401 u16 companding = snd_soc_component_read(component, 402 WM8940_COMPANDINGCTL) & 0xFFDF; 403 int ret; 404 405 priv->fs = params_rate(params); 406 ret = wm8940_update_clocks(dai); 407 if (ret) 408 return ret; 409 410 /* LoutR control */ 411 if (substream->stream == SNDRV_PCM_STREAM_CAPTURE 412 && params_channels(params) == 2) 413 iface |= (1 << 9); 414 415 switch (params_rate(params)) { 416 case 8000: 417 addcntrl |= (0x5 << 1); 418 break; 419 case 11025: 420 addcntrl |= (0x4 << 1); 421 break; 422 case 16000: 423 addcntrl |= (0x3 << 1); 424 break; 425 case 22050: 426 addcntrl |= (0x2 << 1); 427 break; 428 case 32000: 429 addcntrl |= (0x1 << 1); 430 break; 431 case 44100: 432 case 48000: 433 break; 434 } 435 ret = snd_soc_component_write(component, WM8940_ADDCNTRL, addcntrl); 436 if (ret) 437 goto error_ret; 438 439 switch (params_width(params)) { 440 case 8: 441 companding = companding | (1 << 5); 442 break; 443 case 16: 444 break; 445 case 20: 446 iface |= (1 << 5); 447 break; 448 case 24: 449 iface |= (2 << 5); 450 break; 451 case 32: 452 iface |= (3 << 5); 453 break; 454 } 455 ret = snd_soc_component_write(component, WM8940_COMPANDINGCTL, companding); 456 if (ret) 457 goto error_ret; 458 ret = snd_soc_component_write(component, WM8940_IFACE, iface); 459 460 error_ret: 461 return ret; 462 } 463 464 static int wm8940_mute(struct snd_soc_dai *dai, int mute, int direction) 465 { 466 struct snd_soc_component *component = dai->component; 467 u16 mute_reg = snd_soc_component_read(component, WM8940_DAC) & 0xffbf; 468 469 if (mute) 470 mute_reg |= 0x40; 471 472 return snd_soc_component_write(component, WM8940_DAC, mute_reg); 473 } 474 475 static int wm8940_set_bias_level(struct snd_soc_component *component, 476 enum snd_soc_bias_level level) 477 { 478 struct wm8940_priv *wm8940 = snd_soc_component_get_drvdata(component); 479 u16 val; 480 u16 pwr_reg = snd_soc_component_read(component, WM8940_POWER1) & 0x1F0; 481 int ret = 0; 482 483 switch (level) { 484 case SND_SOC_BIAS_ON: 485 /* ensure bufioen and biasen */ 486 pwr_reg |= (1 << 2) | (1 << 3); 487 /* Enable thermal shutdown */ 488 val = snd_soc_component_read(component, WM8940_OUTPUTCTL); 489 ret = snd_soc_component_write(component, WM8940_OUTPUTCTL, val | 0x2); 490 if (ret) 491 break; 492 /* set vmid to 75k */ 493 ret = snd_soc_component_write(component, WM8940_POWER1, pwr_reg | 0x1); 494 break; 495 case SND_SOC_BIAS_PREPARE: 496 /* ensure bufioen and biasen */ 497 pwr_reg |= (1 << 2) | (1 << 3); 498 ret = snd_soc_component_write(component, WM8940_POWER1, pwr_reg | 0x1); 499 break; 500 case SND_SOC_BIAS_STANDBY: 501 if (snd_soc_component_get_bias_level(component) == SND_SOC_BIAS_OFF) { 502 ret = regcache_sync(wm8940->regmap); 503 if (ret < 0) { 504 dev_err(component->dev, "Failed to sync cache: %d\n", ret); 505 return ret; 506 } 507 } 508 509 /* ensure bufioen and biasen */ 510 pwr_reg |= (1 << 2) | (1 << 3); 511 /* set vmid to 300k for standby */ 512 ret = snd_soc_component_write(component, WM8940_POWER1, pwr_reg | 0x2); 513 break; 514 case SND_SOC_BIAS_OFF: 515 ret = snd_soc_component_write(component, WM8940_POWER1, pwr_reg); 516 break; 517 } 518 519 return ret; 520 } 521 522 struct pll_ { 523 unsigned int pre_scale:2; 524 unsigned int n:4; 525 unsigned int k; 526 }; 527 528 static struct pll_ pll_div; 529 530 /* The size in bits of the pll divide multiplied by 10 531 * to allow rounding later */ 532 #define FIXED_PLL_SIZE ((1 << 24) * 10) 533 static void pll_factors(unsigned int target, unsigned int source) 534 { 535 unsigned long long Kpart; 536 unsigned int K, Ndiv, Nmod; 537 /* The left shift ist to avoid accuracy loss when right shifting */ 538 Ndiv = target / source; 539 540 if (Ndiv > 12) { 541 source <<= 1; 542 /* Multiply by 2 */ 543 pll_div.pre_scale = 0; 544 Ndiv = target / source; 545 } else if (Ndiv < 3) { 546 source >>= 2; 547 /* Divide by 4 */ 548 pll_div.pre_scale = 3; 549 Ndiv = target / source; 550 } else if (Ndiv < 6) { 551 source >>= 1; 552 /* divide by 2 */ 553 pll_div.pre_scale = 2; 554 Ndiv = target / source; 555 } else 556 pll_div.pre_scale = 1; 557 558 if ((Ndiv < 6) || (Ndiv > 12)) 559 printk(KERN_WARNING 560 "WM8940 N value %d outwith recommended range!d\n", 561 Ndiv); 562 563 pll_div.n = Ndiv; 564 Nmod = target % source; 565 Kpart = FIXED_PLL_SIZE * (long long)Nmod; 566 567 do_div(Kpart, source); 568 569 K = Kpart & 0xFFFFFFFF; 570 571 /* Check if we need to round */ 572 if ((K % 10) >= 5) 573 K += 5; 574 575 /* Move down to proper range now rounding is done */ 576 K /= 10; 577 578 pll_div.k = K; 579 } 580 581 /* Untested at the moment */ 582 static int wm8940_set_dai_pll(struct snd_soc_dai *codec_dai, int pll_id, 583 int source, unsigned int freq_in, unsigned int freq_out) 584 { 585 struct snd_soc_component *component = codec_dai->component; 586 u16 reg; 587 588 /* Turn off PLL */ 589 reg = snd_soc_component_read(component, WM8940_POWER1); 590 snd_soc_component_write(component, WM8940_POWER1, reg & 0x1df); 591 592 if (freq_in == 0 || freq_out == 0) { 593 /* Clock CODEC directly from MCLK */ 594 reg = snd_soc_component_read(component, WM8940_CLOCK); 595 snd_soc_component_write(component, WM8940_CLOCK, reg & 0x0ff); 596 /* Pll power down */ 597 snd_soc_component_write(component, WM8940_PLLN, (1 << 7)); 598 return 0; 599 } 600 601 /* Pll is followed by a frequency divide by 4 */ 602 pll_factors(freq_out*4, freq_in); 603 if (pll_div.k) 604 snd_soc_component_write(component, WM8940_PLLN, 605 (pll_div.pre_scale << 4) | pll_div.n | (1 << 6)); 606 else /* No factional component */ 607 snd_soc_component_write(component, WM8940_PLLN, 608 (pll_div.pre_scale << 4) | pll_div.n); 609 snd_soc_component_write(component, WM8940_PLLK1, pll_div.k >> 18); 610 snd_soc_component_write(component, WM8940_PLLK2, (pll_div.k >> 9) & 0x1ff); 611 snd_soc_component_write(component, WM8940_PLLK3, pll_div.k & 0x1ff); 612 /* Enable the PLL */ 613 reg = snd_soc_component_read(component, WM8940_POWER1); 614 snd_soc_component_write(component, WM8940_POWER1, reg | 0x020); 615 616 /* Run CODEC from PLL instead of MCLK */ 617 reg = snd_soc_component_read(component, WM8940_CLOCK); 618 snd_soc_component_write(component, WM8940_CLOCK, reg | 0x100); 619 620 return 0; 621 } 622 623 static int wm8940_set_dai_clkdiv(struct snd_soc_dai *codec_dai, 624 int div_id, int div) 625 { 626 struct snd_soc_component *component = codec_dai->component; 627 u16 reg; 628 int ret = 0; 629 630 switch (div_id) { 631 case WM8940_BCLKDIV: 632 reg = snd_soc_component_read(component, WM8940_CLOCK) & 0xFFE3; 633 ret = snd_soc_component_write(component, WM8940_CLOCK, reg | (div << 2)); 634 break; 635 case WM8940_MCLKDIV: 636 reg = snd_soc_component_read(component, WM8940_CLOCK) & 0xFF1F; 637 ret = snd_soc_component_write(component, WM8940_CLOCK, reg | (div << 5)); 638 break; 639 case WM8940_OPCLKDIV: 640 reg = snd_soc_component_read(component, WM8940_GPIO) & 0xFFCF; 641 ret = snd_soc_component_write(component, WM8940_GPIO, reg | (div << 4)); 642 break; 643 } 644 return ret; 645 } 646 647 static unsigned int wm8940_get_mclkdiv(unsigned int f_in, unsigned int f_out, 648 int *mclkdiv) 649 { 650 unsigned int ratio = 2 * f_in / f_out; 651 652 if (ratio <= 2) { 653 *mclkdiv = WM8940_MCLKDIV_1; 654 ratio = 2; 655 } else if (ratio == 3) { 656 *mclkdiv = WM8940_MCLKDIV_1_5; 657 } else if (ratio == 4) { 658 *mclkdiv = WM8940_MCLKDIV_2; 659 } else if (ratio <= 6) { 660 *mclkdiv = WM8940_MCLKDIV_3; 661 ratio = 6; 662 } else if (ratio <= 8) { 663 *mclkdiv = WM8940_MCLKDIV_4; 664 ratio = 8; 665 } else if (ratio <= 12) { 666 *mclkdiv = WM8940_MCLKDIV_6; 667 ratio = 12; 668 } else if (ratio <= 16) { 669 *mclkdiv = WM8940_MCLKDIV_8; 670 ratio = 16; 671 } else { 672 *mclkdiv = WM8940_MCLKDIV_12; 673 ratio = 24; 674 } 675 676 return f_out * ratio / 2; 677 } 678 679 static int wm8940_update_clocks(struct snd_soc_dai *dai) 680 { 681 struct snd_soc_component *codec = dai->component; 682 struct wm8940_priv *priv = snd_soc_component_get_drvdata(codec); 683 unsigned int fs256; 684 unsigned int fpll = 0; 685 unsigned int f; 686 int mclkdiv; 687 688 if (!priv->mclk || !priv->fs) 689 return 0; 690 691 fs256 = 256 * priv->fs; 692 693 f = wm8940_get_mclkdiv(priv->mclk, fs256, &mclkdiv); 694 if (f != priv->mclk) { 695 /* The PLL performs best around 90MHz */ 696 fpll = wm8940_get_mclkdiv(22500000, fs256, &mclkdiv); 697 } 698 699 wm8940_set_dai_pll(dai, 0, 0, priv->mclk, fpll); 700 wm8940_set_dai_clkdiv(dai, WM8940_MCLKDIV, mclkdiv); 701 702 return 0; 703 } 704 705 static int wm8940_set_dai_sysclk(struct snd_soc_dai *dai, int clk_id, 706 unsigned int freq, int dir) 707 { 708 struct snd_soc_component *codec = dai->component; 709 struct wm8940_priv *priv = snd_soc_component_get_drvdata(codec); 710 711 if (dir != SND_SOC_CLOCK_IN) 712 return -EINVAL; 713 714 priv->mclk = freq; 715 716 return wm8940_update_clocks(dai); 717 } 718 719 #define WM8940_RATES SNDRV_PCM_RATE_8000_48000 720 721 #define WM8940_FORMATS (SNDRV_PCM_FMTBIT_S8 | \ 722 SNDRV_PCM_FMTBIT_S16_LE | \ 723 SNDRV_PCM_FMTBIT_S20_3LE | \ 724 SNDRV_PCM_FMTBIT_S24_LE | \ 725 SNDRV_PCM_FMTBIT_S32_LE) 726 727 static const struct snd_soc_dai_ops wm8940_dai_ops = { 728 .hw_params = wm8940_i2s_hw_params, 729 .set_sysclk = wm8940_set_dai_sysclk, 730 .mute_stream = wm8940_mute, 731 .set_fmt = wm8940_set_dai_fmt, 732 .set_clkdiv = wm8940_set_dai_clkdiv, 733 .set_pll = wm8940_set_dai_pll, 734 .no_capture_mute = 1, 735 }; 736 737 static struct snd_soc_dai_driver wm8940_dai = { 738 .name = "wm8940-hifi", 739 .playback = { 740 .stream_name = "Playback", 741 .channels_min = 1, 742 .channels_max = 2, 743 .rates = WM8940_RATES, 744 .formats = WM8940_FORMATS, 745 }, 746 .capture = { 747 .stream_name = "Capture", 748 .channels_min = 1, 749 .channels_max = 2, 750 .rates = WM8940_RATES, 751 .formats = WM8940_FORMATS, 752 }, 753 .ops = &wm8940_dai_ops, 754 .symmetric_rate = 1, 755 }; 756 757 static int wm8940_probe(struct snd_soc_component *component) 758 { 759 struct wm8940_setup_data *pdata = component->dev->platform_data; 760 int ret; 761 u16 reg; 762 763 /* 764 * Check chip ID for wm8940 - value of 0x00 offset 765 * SOFTWARE_RESET on write 766 * CHIP_ID on read 767 */ 768 reg = snd_soc_component_read(component, WM8940_SOFTRESET); 769 if (reg != WM8940_CHIP_ID) { 770 dev_err(component->dev, "Wrong wm8940 chip ID: 0x%x\n", reg); 771 return -ENODEV; 772 } 773 774 ret = wm8940_reset(component); 775 if (ret < 0) { 776 dev_err(component->dev, "Failed to issue reset\n"); 777 return ret; 778 } 779 780 snd_soc_component_force_bias_level(component, SND_SOC_BIAS_STANDBY); 781 782 ret = snd_soc_component_write(component, WM8940_POWER1, 0x180); 783 if (ret < 0) 784 return ret; 785 786 if (pdata) { 787 reg = snd_soc_component_read(component, WM8940_OUTPUTCTL); 788 ret = snd_soc_component_write(component, WM8940_OUTPUTCTL, reg | pdata->vroi); 789 if (ret < 0) 790 return ret; 791 } 792 793 return ret; 794 } 795 796 static const struct snd_soc_component_driver soc_component_dev_wm8940 = { 797 .probe = wm8940_probe, 798 .set_bias_level = wm8940_set_bias_level, 799 .controls = wm8940_snd_controls, 800 .num_controls = ARRAY_SIZE(wm8940_snd_controls), 801 .dapm_widgets = wm8940_dapm_widgets, 802 .num_dapm_widgets = ARRAY_SIZE(wm8940_dapm_widgets), 803 .dapm_routes = wm8940_dapm_routes, 804 .num_dapm_routes = ARRAY_SIZE(wm8940_dapm_routes), 805 .suspend_bias_off = 1, 806 .idle_bias_on = 1, 807 .use_pmdown_time = 1, 808 .endianness = 1, 809 }; 810 811 static const struct regmap_config wm8940_regmap = { 812 .reg_bits = 8, 813 .val_bits = 16, 814 815 .max_register = WM8940_MONOMIX, 816 .reg_defaults = wm8940_reg_defaults, 817 .num_reg_defaults = ARRAY_SIZE(wm8940_reg_defaults), 818 .cache_type = REGCACHE_MAPLE, 819 820 .readable_reg = wm8940_readable_register, 821 .volatile_reg = wm8940_volatile_register, 822 }; 823 824 static int wm8940_i2c_probe(struct i2c_client *i2c) 825 { 826 struct wm8940_priv *wm8940; 827 int ret; 828 829 wm8940 = devm_kzalloc(&i2c->dev, sizeof(struct wm8940_priv), 830 GFP_KERNEL); 831 if (wm8940 == NULL) 832 return -ENOMEM; 833 834 wm8940->regmap = devm_regmap_init_i2c(i2c, &wm8940_regmap); 835 if (IS_ERR(wm8940->regmap)) 836 return PTR_ERR(wm8940->regmap); 837 838 i2c_set_clientdata(i2c, wm8940); 839 840 ret = devm_snd_soc_register_component(&i2c->dev, 841 &soc_component_dev_wm8940, &wm8940_dai, 1); 842 843 return ret; 844 } 845 846 static const struct i2c_device_id wm8940_i2c_id[] = { 847 { "wm8940" }, 848 { } 849 }; 850 MODULE_DEVICE_TABLE(i2c, wm8940_i2c_id); 851 852 static const struct of_device_id wm8940_of_match[] = { 853 { .compatible = "wlf,wm8940", }, 854 { } 855 }; 856 MODULE_DEVICE_TABLE(of, wm8940_of_match); 857 858 static struct i2c_driver wm8940_i2c_driver = { 859 .driver = { 860 .name = "wm8940", 861 .of_match_table = wm8940_of_match, 862 }, 863 .probe = wm8940_i2c_probe, 864 .id_table = wm8940_i2c_id, 865 }; 866 867 module_i2c_driver(wm8940_i2c_driver); 868 869 MODULE_DESCRIPTION("ASoC WM8940 driver"); 870 MODULE_AUTHOR("Jonathan Cameron"); 871 MODULE_LICENSE("GPL"); 872
Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.