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