1 /* 2 * wm8960.c -- WM8960 ALSA SoC Audio driver 3 * 4 * Author: Liam Girdwood 5 * 6 * This program is free software; you can redistribute it and/or modify 7 * it under the terms of the GNU General Public License version 2 as 8 * published by the Free Software Foundation. 9 */ 10 11 #include <linux/module.h> 12 #include <linux/moduleparam.h> 13 #include <linux/init.h> 14 #include <linux/delay.h> 15 #include <linux/pm.h> 16 #include <linux/i2c.h> 17 #include <linux/platform_device.h> 18 #include <sound/core.h> 19 #include <sound/pcm.h> 20 #include <sound/pcm_params.h> 21 #include <sound/soc.h> 22 #include <sound/soc-dapm.h> 23 #include <sound/initval.h> 24 #include <sound/tlv.h> 25 26 #include "wm8960.h" 27 28 #define AUDIO_NAME "wm8960" 29 30 struct snd_soc_codec_device soc_codec_dev_wm8960; 31 32 /* R25 - Power 1 */ 33 #define WM8960_VREF 0x40 34 35 /* R28 - Anti-pop 1 */ 36 #define WM8960_POBCTRL 0x80 37 #define WM8960_BUFDCOPEN 0x10 38 #define WM8960_BUFIOEN 0x08 39 #define WM8960_SOFT_ST 0x04 40 #define WM8960_HPSTBY 0x01 41 42 /* R29 - Anti-pop 2 */ 43 #define WM8960_DISOP 0x40 44 45 /* 46 * wm8960 register cache 47 * We can't read the WM8960 register space when we are 48 * using 2 wire for device control, so we cache them instead. 49 */ 50 static const u16 wm8960_reg[WM8960_CACHEREGNUM] = { 51 0x0097, 0x0097, 0x0000, 0x0000, 52 0x0000, 0x0008, 0x0000, 0x000a, 53 0x01c0, 0x0000, 0x00ff, 0x00ff, 54 0x0000, 0x0000, 0x0000, 0x0000, 55 0x0000, 0x007b, 0x0100, 0x0032, 56 0x0000, 0x00c3, 0x00c3, 0x01c0, 57 0x0000, 0x0000, 0x0000, 0x0000, 58 0x0000, 0x0000, 0x0000, 0x0000, 59 0x0100, 0x0100, 0x0050, 0x0050, 60 0x0050, 0x0050, 0x0000, 0x0000, 61 0x0000, 0x0000, 0x0040, 0x0000, 62 0x0000, 0x0050, 0x0050, 0x0000, 63 0x0002, 0x0037, 0x004d, 0x0080, 64 0x0008, 0x0031, 0x0026, 0x00e9, 65 }; 66 67 struct wm8960_priv { 68 u16 reg_cache[WM8960_CACHEREGNUM]; 69 struct snd_soc_codec codec; 70 }; 71 72 /* 73 * read wm8960 register cache 74 */ 75 static inline unsigned int wm8960_read_reg_cache(struct snd_soc_codec *codec, 76 unsigned int reg) 77 { 78 u16 *cache = codec->reg_cache; 79 if (reg == WM8960_RESET) 80 return 0; 81 if (reg >= WM8960_CACHEREGNUM) 82 return -1; 83 return cache[reg]; 84 } 85 86 /* 87 * write wm8960 register cache 88 */ 89 static inline void wm8960_write_reg_cache(struct snd_soc_codec *codec, 90 u16 reg, unsigned int value) 91 { 92 u16 *cache = codec->reg_cache; 93 if (reg >= WM8960_CACHEREGNUM) 94 return; 95 cache[reg] = value; 96 } 97 98 static inline unsigned int wm8960_read(struct snd_soc_codec *codec, 99 unsigned int reg) 100 { 101 return wm8960_read_reg_cache(codec, reg); 102 } 103 104 /* 105 * write to the WM8960 register space 106 */ 107 static int wm8960_write(struct snd_soc_codec *codec, unsigned int reg, 108 unsigned int value) 109 { 110 u8 data[2]; 111 112 /* data is 113 * D15..D9 WM8960 register offset 114 * D8...D0 register data 115 */ 116 data[0] = (reg << 1) | ((value >> 8) & 0x0001); 117 data[1] = value & 0x00ff; 118 119 wm8960_write_reg_cache(codec, reg, value); 120 if (codec->hw_write(codec->control_data, data, 2) == 2) 121 return 0; 122 else 123 return -EIO; 124 } 125 126 #define wm8960_reset(c) wm8960_write(c, WM8960_RESET, 0) 127 128 /* enumerated controls */ 129 static const char *wm8960_deemph[] = {"None", "32Khz", "44.1Khz", "48Khz"}; 130 static const char *wm8960_polarity[] = {"No Inversion", "Left Inverted", 131 "Right Inverted", "Stereo Inversion"}; 132 static const char *wm8960_3d_upper_cutoff[] = {"High", "Low"}; 133 static const char *wm8960_3d_lower_cutoff[] = {"Low", "High"}; 134 static const char *wm8960_alcfunc[] = {"Off", "Right", "Left", "Stereo"}; 135 static const char *wm8960_alcmode[] = {"ALC", "Limiter"}; 136 137 static const struct soc_enum wm8960_enum[] = { 138 SOC_ENUM_SINGLE(WM8960_DACCTL1, 1, 4, wm8960_deemph), 139 SOC_ENUM_SINGLE(WM8960_DACCTL1, 5, 4, wm8960_polarity), 140 SOC_ENUM_SINGLE(WM8960_DACCTL2, 5, 4, wm8960_polarity), 141 SOC_ENUM_SINGLE(WM8960_3D, 6, 2, wm8960_3d_upper_cutoff), 142 SOC_ENUM_SINGLE(WM8960_3D, 5, 2, wm8960_3d_lower_cutoff), 143 SOC_ENUM_SINGLE(WM8960_ALC1, 7, 4, wm8960_alcfunc), 144 SOC_ENUM_SINGLE(WM8960_ALC3, 8, 2, wm8960_alcmode), 145 }; 146 147 static const DECLARE_TLV_DB_SCALE(adc_tlv, -9700, 50, 0); 148 static const DECLARE_TLV_DB_SCALE(dac_tlv, -12700, 50, 1); 149 static const DECLARE_TLV_DB_SCALE(bypass_tlv, -2100, 300, 0); 150 static const DECLARE_TLV_DB_SCALE(out_tlv, -12100, 100, 1); 151 152 static const struct snd_kcontrol_new wm8960_snd_controls[] = { 153 SOC_DOUBLE_R_TLV("Capture Volume", WM8960_LINVOL, WM8960_RINVOL, 154 0, 63, 0, adc_tlv), 155 SOC_DOUBLE_R("Capture Volume ZC Switch", WM8960_LINVOL, WM8960_RINVOL, 156 6, 1, 0), 157 SOC_DOUBLE_R("Capture Switch", WM8960_LINVOL, WM8960_RINVOL, 158 7, 1, 0), 159 160 SOC_DOUBLE_R_TLV("Playback Volume", WM8960_LDAC, WM8960_RDAC, 161 0, 255, 0, dac_tlv), 162 163 SOC_DOUBLE_R_TLV("Headphone Playback Volume", WM8960_LOUT1, WM8960_ROUT1, 164 0, 127, 0, out_tlv), 165 SOC_DOUBLE_R("Headphone Playback ZC Switch", WM8960_LOUT1, WM8960_ROUT1, 166 7, 1, 0), 167 168 SOC_DOUBLE_R_TLV("Speaker Playback Volume", WM8960_LOUT2, WM8960_ROUT2, 169 0, 127, 0, out_tlv), 170 SOC_DOUBLE_R("Speaker Playback ZC Switch", WM8960_LOUT2, WM8960_ROUT2, 171 7, 1, 0), 172 SOC_SINGLE("Speaker DC Volume", WM8960_CLASSD3, 3, 5, 0), 173 SOC_SINGLE("Speaker AC Volume", WM8960_CLASSD3, 0, 5, 0), 174 175 SOC_SINGLE("PCM Playback -6dB Switch", WM8960_DACCTL1, 7, 1, 0), 176 SOC_ENUM("ADC Polarity", wm8960_enum[1]), 177 SOC_ENUM("Playback De-emphasis", wm8960_enum[0]), 178 SOC_SINGLE("ADC High Pass Filter Switch", WM8960_DACCTL1, 0, 1, 0), 179 180 SOC_ENUM("DAC Polarity", wm8960_enum[2]), 181 182 SOC_ENUM("3D Filter Upper Cut-Off", wm8960_enum[3]), 183 SOC_ENUM("3D Filter Lower Cut-Off", wm8960_enum[4]), 184 SOC_SINGLE("3D Volume", WM8960_3D, 1, 15, 0), 185 SOC_SINGLE("3D Switch", WM8960_3D, 0, 1, 0), 186 187 SOC_ENUM("ALC Function", wm8960_enum[5]), 188 SOC_SINGLE("ALC Max Gain", WM8960_ALC1, 4, 7, 0), 189 SOC_SINGLE("ALC Target", WM8960_ALC1, 0, 15, 1), 190 SOC_SINGLE("ALC Min Gain", WM8960_ALC2, 4, 7, 0), 191 SOC_SINGLE("ALC Hold Time", WM8960_ALC2, 0, 15, 0), 192 SOC_ENUM("ALC Mode", wm8960_enum[6]), 193 SOC_SINGLE("ALC Decay", WM8960_ALC3, 4, 15, 0), 194 SOC_SINGLE("ALC Attack", WM8960_ALC3, 0, 15, 0), 195 196 SOC_SINGLE("Noise Gate Threshold", WM8960_NOISEG, 3, 31, 0), 197 SOC_SINGLE("Noise Gate Switch", WM8960_NOISEG, 0, 1, 0), 198 199 SOC_DOUBLE_R("ADC PCM Capture Volume", WM8960_LINPATH, WM8960_RINPATH, 200 0, 127, 0), 201 202 SOC_SINGLE_TLV("Left Output Mixer Boost Bypass Volume", 203 WM8960_BYPASS1, 4, 7, 1, bypass_tlv), 204 SOC_SINGLE_TLV("Left Output Mixer LINPUT3 Volume", 205 WM8960_LOUTMIX, 4, 7, 1, bypass_tlv), 206 SOC_SINGLE_TLV("Right Output Mixer Boost Bypass Volume", 207 WM8960_BYPASS2, 4, 7, 1, bypass_tlv), 208 SOC_SINGLE_TLV("Right Output Mixer RINPUT3 Volume", 209 WM8960_ROUTMIX, 4, 7, 1, bypass_tlv), 210 }; 211 212 static const struct snd_kcontrol_new wm8960_lin_boost[] = { 213 SOC_DAPM_SINGLE("LINPUT2 Switch", WM8960_LINPATH, 6, 1, 0), 214 SOC_DAPM_SINGLE("LINPUT3 Switch", WM8960_LINPATH, 7, 1, 0), 215 SOC_DAPM_SINGLE("LINPUT1 Switch", WM8960_LINPATH, 8, 1, 0), 216 }; 217 218 static const struct snd_kcontrol_new wm8960_lin[] = { 219 SOC_DAPM_SINGLE("Boost Switch", WM8960_LINPATH, 3, 1, 0), 220 }; 221 222 static const struct snd_kcontrol_new wm8960_rin_boost[] = { 223 SOC_DAPM_SINGLE("RINPUT2 Switch", WM8960_RINPATH, 6, 1, 0), 224 SOC_DAPM_SINGLE("RINPUT3 Switch", WM8960_RINPATH, 7, 1, 0), 225 SOC_DAPM_SINGLE("RINPUT1 Switch", WM8960_RINPATH, 8, 1, 0), 226 }; 227 228 static const struct snd_kcontrol_new wm8960_rin[] = { 229 SOC_DAPM_SINGLE("Boost Switch", WM8960_RINPATH, 3, 1, 0), 230 }; 231 232 static const struct snd_kcontrol_new wm8960_loutput_mixer[] = { 233 SOC_DAPM_SINGLE("PCM Playback Switch", WM8960_LOUTMIX, 8, 1, 0), 234 SOC_DAPM_SINGLE("LINPUT3 Switch", WM8960_LOUTMIX, 7, 1, 0), 235 SOC_DAPM_SINGLE("Boost Bypass Switch", WM8960_BYPASS1, 7, 1, 0), 236 }; 237 238 static const struct snd_kcontrol_new wm8960_routput_mixer[] = { 239 SOC_DAPM_SINGLE("PCM Playback Switch", WM8960_ROUTMIX, 8, 1, 0), 240 SOC_DAPM_SINGLE("RINPUT3 Switch", WM8960_ROUTMIX, 7, 1, 0), 241 SOC_DAPM_SINGLE("Boost Bypass Switch", WM8960_BYPASS2, 7, 1, 0), 242 }; 243 244 static const struct snd_kcontrol_new wm8960_mono_out[] = { 245 SOC_DAPM_SINGLE("Left Switch", WM8960_MONOMIX1, 7, 1, 0), 246 SOC_DAPM_SINGLE("Right Switch", WM8960_MONOMIX2, 7, 1, 0), 247 }; 248 249 static const struct snd_soc_dapm_widget wm8960_dapm_widgets[] = { 250 SND_SOC_DAPM_INPUT("LINPUT1"), 251 SND_SOC_DAPM_INPUT("RINPUT1"), 252 SND_SOC_DAPM_INPUT("LINPUT2"), 253 SND_SOC_DAPM_INPUT("RINPUT2"), 254 SND_SOC_DAPM_INPUT("LINPUT3"), 255 SND_SOC_DAPM_INPUT("RINPUT3"), 256 257 SND_SOC_DAPM_MICBIAS("MICB", WM8960_POWER1, 1, 0), 258 259 SND_SOC_DAPM_MIXER("Left Boost Mixer", WM8960_POWER1, 5, 0, 260 wm8960_lin_boost, ARRAY_SIZE(wm8960_lin_boost)), 261 SND_SOC_DAPM_MIXER("Right Boost Mixer", WM8960_POWER1, 4, 0, 262 wm8960_rin_boost, ARRAY_SIZE(wm8960_rin_boost)), 263 264 SND_SOC_DAPM_MIXER("Left Input Mixer", WM8960_POWER3, 5, 0, 265 wm8960_lin, ARRAY_SIZE(wm8960_lin)), 266 SND_SOC_DAPM_MIXER("Right Input Mixer", WM8960_POWER3, 4, 0, 267 wm8960_rin, ARRAY_SIZE(wm8960_rin)), 268 269 SND_SOC_DAPM_ADC("Left ADC", "Capture", WM8960_POWER2, 3, 0), 270 SND_SOC_DAPM_ADC("Right ADC", "Capture", WM8960_POWER2, 2, 0), 271 272 SND_SOC_DAPM_DAC("Left DAC", "Playback", WM8960_POWER2, 8, 0), 273 SND_SOC_DAPM_DAC("Right DAC", "Playback", WM8960_POWER2, 7, 0), 274 275 SND_SOC_DAPM_MIXER("Left Output Mixer", WM8960_POWER3, 3, 0, 276 &wm8960_loutput_mixer[0], 277 ARRAY_SIZE(wm8960_loutput_mixer)), 278 SND_SOC_DAPM_MIXER("Right Output Mixer", WM8960_POWER3, 2, 0, 279 &wm8960_routput_mixer[0], 280 ARRAY_SIZE(wm8960_routput_mixer)), 281 282 SND_SOC_DAPM_MIXER("Mono Output Mixer", WM8960_POWER2, 1, 0, 283 &wm8960_mono_out[0], 284 ARRAY_SIZE(wm8960_mono_out)), 285 286 SND_SOC_DAPM_PGA("LOUT1 PGA", WM8960_POWER2, 6, 0, NULL, 0), 287 SND_SOC_DAPM_PGA("ROUT1 PGA", WM8960_POWER2, 5, 0, NULL, 0), 288 289 SND_SOC_DAPM_PGA("Left Speaker PGA", WM8960_POWER2, 4, 0, NULL, 0), 290 SND_SOC_DAPM_PGA("Right Speaker PGA", WM8960_POWER2, 3, 0, NULL, 0), 291 292 SND_SOC_DAPM_PGA("Right Speaker Output", WM8960_CLASSD1, 7, 0, NULL, 0), 293 SND_SOC_DAPM_PGA("Left Speaker Output", WM8960_CLASSD1, 6, 0, NULL, 0), 294 295 SND_SOC_DAPM_OUTPUT("SPK_LP"), 296 SND_SOC_DAPM_OUTPUT("SPK_LN"), 297 SND_SOC_DAPM_OUTPUT("HP_L"), 298 SND_SOC_DAPM_OUTPUT("HP_R"), 299 SND_SOC_DAPM_OUTPUT("SPK_RP"), 300 SND_SOC_DAPM_OUTPUT("SPK_RN"), 301 SND_SOC_DAPM_OUTPUT("OUT3"), 302 }; 303 304 static const struct snd_soc_dapm_route audio_paths[] = { 305 { "Left Boost Mixer", "LINPUT1 Switch", "LINPUT1" }, 306 { "Left Boost Mixer", "LINPUT2 Switch", "LINPUT2" }, 307 { "Left Boost Mixer", "LINPUT3 Switch", "LINPUT3" }, 308 309 { "Left Input Mixer", "Boost Switch", "Left Boost Mixer", }, 310 { "Left Input Mixer", NULL, "LINPUT1", }, /* Really Boost Switch */ 311 { "Left Input Mixer", NULL, "LINPUT2" }, 312 { "Left Input Mixer", NULL, "LINPUT3" }, 313 314 { "Right Boost Mixer", "RINPUT1 Switch", "RINPUT1" }, 315 { "Right Boost Mixer", "RINPUT2 Switch", "RINPUT2" }, 316 { "Right Boost Mixer", "RINPUT3 Switch", "RINPUT3" }, 317 318 { "Right Input Mixer", "Boost Switch", "Right Boost Mixer", }, 319 { "Right Input Mixer", NULL, "RINPUT1", }, /* Really Boost Switch */ 320 { "Right Input Mixer", NULL, "RINPUT2" }, 321 { "Right Input Mixer", NULL, "LINPUT3" }, 322 323 { "Left ADC", NULL, "Left Input Mixer" }, 324 { "Right ADC", NULL, "Right Input Mixer" }, 325 326 { "Left Output Mixer", "LINPUT3 Switch", "LINPUT3" }, 327 { "Left Output Mixer", "Boost Bypass Switch", "Left Boost Mixer"} , 328 { "Left Output Mixer", "PCM Playback Switch", "Left DAC" }, 329 330 { "Right Output Mixer", "RINPUT3 Switch", "RINPUT3" }, 331 { "Right Output Mixer", "Boost Bypass Switch", "Right Boost Mixer" } , 332 { "Right Output Mixer", "PCM Playback Switch", "Right DAC" }, 333 334 { "Mono Output Mixer", "Left Switch", "Left Output Mixer" }, 335 { "Mono Output Mixer", "Right Switch", "Right Output Mixer" }, 336 337 { "LOUT1 PGA", NULL, "Left Output Mixer" }, 338 { "ROUT1 PGA", NULL, "Right Output Mixer" }, 339 340 { "HP_L", NULL, "LOUT1 PGA" }, 341 { "HP_R", NULL, "ROUT1 PGA" }, 342 343 { "Left Speaker PGA", NULL, "Left Output Mixer" }, 344 { "Right Speaker PGA", NULL, "Right Output Mixer" }, 345 346 { "Left Speaker Output", NULL, "Left Speaker PGA" }, 347 { "Right Speaker Output", NULL, "Right Speaker PGA" }, 348 349 { "SPK_LN", NULL, "Left Speaker Output" }, 350 { "SPK_LP", NULL, "Left Speaker Output" }, 351 { "SPK_RN", NULL, "Right Speaker Output" }, 352 { "SPK_RP", NULL, "Right Speaker Output" }, 353 354 { "OUT3", NULL, "Mono Output Mixer", } 355 }; 356 357 static int wm8960_add_widgets(struct snd_soc_codec *codec) 358 { 359 snd_soc_dapm_new_controls(codec, wm8960_dapm_widgets, 360 ARRAY_SIZE(wm8960_dapm_widgets)); 361 362 snd_soc_dapm_add_routes(codec, audio_paths, ARRAY_SIZE(audio_paths)); 363 364 snd_soc_dapm_new_widgets(codec); 365 return 0; 366 } 367 368 static int wm8960_set_dai_fmt(struct snd_soc_dai *codec_dai, 369 unsigned int fmt) 370 { 371 struct snd_soc_codec *codec = codec_dai->codec; 372 u16 iface = 0; 373 374 /* set master/slave audio interface */ 375 switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { 376 case SND_SOC_DAIFMT_CBM_CFM: 377 iface |= 0x0040; 378 break; 379 case SND_SOC_DAIFMT_CBS_CFS: 380 break; 381 default: 382 return -EINVAL; 383 } 384 385 /* interface format */ 386 switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { 387 case SND_SOC_DAIFMT_I2S: 388 iface |= 0x0002; 389 break; 390 case SND_SOC_DAIFMT_RIGHT_J: 391 break; 392 case SND_SOC_DAIFMT_LEFT_J: 393 iface |= 0x0001; 394 break; 395 case SND_SOC_DAIFMT_DSP_A: 396 iface |= 0x0003; 397 break; 398 case SND_SOC_DAIFMT_DSP_B: 399 iface |= 0x0013; 400 break; 401 default: 402 return -EINVAL; 403 } 404 405 /* clock inversion */ 406 switch (fmt & SND_SOC_DAIFMT_INV_MASK) { 407 case SND_SOC_DAIFMT_NB_NF: 408 break; 409 case SND_SOC_DAIFMT_IB_IF: 410 iface |= 0x0090; 411 break; 412 case SND_SOC_DAIFMT_IB_NF: 413 iface |= 0x0080; 414 break; 415 case SND_SOC_DAIFMT_NB_IF: 416 iface |= 0x0010; 417 break; 418 default: 419 return -EINVAL; 420 } 421 422 /* set iface */ 423 wm8960_write(codec, WM8960_IFACE1, iface); 424 return 0; 425 } 426 427 static int wm8960_hw_params(struct snd_pcm_substream *substream, 428 struct snd_pcm_hw_params *params, 429 struct snd_soc_dai *dai) 430 { 431 struct snd_soc_pcm_runtime *rtd = substream->private_data; 432 struct snd_soc_device *socdev = rtd->socdev; 433 struct snd_soc_codec *codec = socdev->card->codec; 434 u16 iface = wm8960_read(codec, WM8960_IFACE1) & 0xfff3; 435 436 /* bit size */ 437 switch (params_format(params)) { 438 case SNDRV_PCM_FORMAT_S16_LE: 439 break; 440 case SNDRV_PCM_FORMAT_S20_3LE: 441 iface |= 0x0004; 442 break; 443 case SNDRV_PCM_FORMAT_S24_LE: 444 iface |= 0x0008; 445 break; 446 } 447 448 /* set iface */ 449 wm8960_write(codec, WM8960_IFACE1, iface); 450 return 0; 451 } 452 453 static int wm8960_mute(struct snd_soc_dai *dai, int mute) 454 { 455 struct snd_soc_codec *codec = dai->codec; 456 u16 mute_reg = wm8960_read(codec, WM8960_DACCTL1) & 0xfff7; 457 458 if (mute) 459 wm8960_write(codec, WM8960_DACCTL1, mute_reg | 0x8); 460 else 461 wm8960_write(codec, WM8960_DACCTL1, mute_reg); 462 return 0; 463 } 464 465 static int wm8960_set_bias_level(struct snd_soc_codec *codec, 466 enum snd_soc_bias_level level) 467 { 468 struct wm8960_data *pdata = codec->dev->platform_data; 469 u16 reg; 470 471 switch (level) { 472 case SND_SOC_BIAS_ON: 473 break; 474 475 case SND_SOC_BIAS_PREPARE: 476 /* Set VMID to 2x50k */ 477 reg = wm8960_read(codec, WM8960_POWER1); 478 reg &= ~0x180; 479 reg |= 0x80; 480 wm8960_write(codec, WM8960_POWER1, reg); 481 break; 482 483 case SND_SOC_BIAS_STANDBY: 484 if (codec->bias_level == SND_SOC_BIAS_OFF) { 485 /* Enable anti-pop features */ 486 wm8960_write(codec, WM8960_APOP1, 487 WM8960_POBCTRL | WM8960_SOFT_ST | 488 WM8960_BUFDCOPEN | WM8960_BUFIOEN); 489 490 /* Discharge HP output */ 491 reg = WM8960_DISOP; 492 if (pdata) 493 reg |= pdata->dres << 4; 494 wm8960_write(codec, WM8960_APOP2, reg); 495 496 msleep(400); 497 498 wm8960_write(codec, WM8960_APOP2, 0); 499 500 /* Enable & ramp VMID at 2x50k */ 501 reg = wm8960_read(codec, WM8960_POWER1); 502 reg |= 0x80; 503 wm8960_write(codec, WM8960_POWER1, reg); 504 msleep(100); 505 506 /* Enable VREF */ 507 wm8960_write(codec, WM8960_POWER1, reg | WM8960_VREF); 508 509 /* Disable anti-pop features */ 510 wm8960_write(codec, WM8960_APOP1, WM8960_BUFIOEN); 511 } 512 513 /* Set VMID to 2x250k */ 514 reg = wm8960_read(codec, WM8960_POWER1); 515 reg &= ~0x180; 516 reg |= 0x100; 517 wm8960_write(codec, WM8960_POWER1, reg); 518 break; 519 520 case SND_SOC_BIAS_OFF: 521 /* Enable anti-pop features */ 522 wm8960_write(codec, WM8960_APOP1, 523 WM8960_POBCTRL | WM8960_SOFT_ST | 524 WM8960_BUFDCOPEN | WM8960_BUFIOEN); 525 526 /* Disable VMID and VREF, let them discharge */ 527 wm8960_write(codec, WM8960_POWER1, 0); 528 msleep(600); 529 530 wm8960_write(codec, WM8960_APOP1, 0); 531 break; 532 } 533 534 codec->bias_level = level; 535 536 return 0; 537 } 538 539 /* PLL divisors */ 540 struct _pll_div { 541 u32 pre_div:1; 542 u32 n:4; 543 u32 k:24; 544 }; 545 546 /* The size in bits of the pll divide multiplied by 10 547 * to allow rounding later */ 548 #define FIXED_PLL_SIZE ((1 << 24) * 10) 549 550 static int pll_factors(unsigned int source, unsigned int target, 551 struct _pll_div *pll_div) 552 { 553 unsigned long long Kpart; 554 unsigned int K, Ndiv, Nmod; 555 556 pr_debug("WM8960 PLL: setting %dHz->%dHz\n", source, target); 557 558 /* Scale up target to PLL operating frequency */ 559 target *= 4; 560 561 Ndiv = target / source; 562 if (Ndiv < 6) { 563 source >>= 1; 564 pll_div->pre_div = 1; 565 Ndiv = target / source; 566 } else 567 pll_div->pre_div = 0; 568 569 if ((Ndiv < 6) || (Ndiv > 12)) { 570 pr_err("WM8960 PLL: Unsupported N=%d\n", Ndiv); 571 return -EINVAL; 572 } 573 574 pll_div->n = Ndiv; 575 Nmod = target % source; 576 Kpart = FIXED_PLL_SIZE * (long long)Nmod; 577 578 do_div(Kpart, source); 579 580 K = Kpart & 0xFFFFFFFF; 581 582 /* Check if we need to round */ 583 if ((K % 10) >= 5) 584 K += 5; 585 586 /* Move down to proper range now rounding is done */ 587 K /= 10; 588 589 pll_div->k = K; 590 591 pr_debug("WM8960 PLL: N=%x K=%x pre_div=%d\n", 592 pll_div->n, pll_div->k, pll_div->pre_div); 593 594 return 0; 595 } 596 597 static int wm8960_set_dai_pll(struct snd_soc_dai *codec_dai, 598 int pll_id, unsigned int freq_in, unsigned int freq_out) 599 { 600 struct snd_soc_codec *codec = codec_dai->codec; 601 u16 reg; 602 static struct _pll_div pll_div; 603 int ret; 604 605 if (freq_in && freq_out) { 606 ret = pll_factors(freq_in, freq_out, &pll_div); 607 if (ret != 0) 608 return ret; 609 } 610 611 /* Disable the PLL: even if we are changing the frequency the 612 * PLL needs to be disabled while we do so. */ 613 wm8960_write(codec, WM8960_CLOCK1, 614 wm8960_read(codec, WM8960_CLOCK1) & ~1); 615 wm8960_write(codec, WM8960_POWER2, 616 wm8960_read(codec, WM8960_POWER2) & ~1); 617 618 if (!freq_in || !freq_out) 619 return 0; 620 621 reg = wm8960_read(codec, WM8960_PLL1) & ~0x3f; 622 reg |= pll_div.pre_div << 4; 623 reg |= pll_div.n; 624 625 if (pll_div.k) { 626 reg |= 0x20; 627 628 wm8960_write(codec, WM8960_PLL2, (pll_div.k >> 18) & 0x3f); 629 wm8960_write(codec, WM8960_PLL3, (pll_div.k >> 9) & 0x1ff); 630 wm8960_write(codec, WM8960_PLL4, pll_div.k & 0x1ff); 631 } 632 wm8960_write(codec, WM8960_PLL1, reg); 633 634 /* Turn it on */ 635 wm8960_write(codec, WM8960_POWER2, 636 wm8960_read(codec, WM8960_POWER2) | 1); 637 msleep(250); 638 wm8960_write(codec, WM8960_CLOCK1, 639 wm8960_read(codec, WM8960_CLOCK1) | 1); 640 641 return 0; 642 } 643 644 static int wm8960_set_dai_clkdiv(struct snd_soc_dai *codec_dai, 645 int div_id, int div) 646 { 647 struct snd_soc_codec *codec = codec_dai->codec; 648 u16 reg; 649 650 switch (div_id) { 651 case WM8960_SYSCLKSEL: 652 reg = wm8960_read(codec, WM8960_CLOCK1) & 0x1fe; 653 wm8960_write(codec, WM8960_CLOCK1, reg | div); 654 break; 655 case WM8960_SYSCLKDIV: 656 reg = wm8960_read(codec, WM8960_CLOCK1) & 0x1f9; 657 wm8960_write(codec, WM8960_CLOCK1, reg | div); 658 break; 659 case WM8960_DACDIV: 660 reg = wm8960_read(codec, WM8960_CLOCK1) & 0x1c7; 661 wm8960_write(codec, WM8960_CLOCK1, reg | div); 662 break; 663 case WM8960_OPCLKDIV: 664 reg = wm8960_read(codec, WM8960_PLL1) & 0x03f; 665 wm8960_write(codec, WM8960_PLL1, reg | div); 666 break; 667 case WM8960_DCLKDIV: 668 reg = wm8960_read(codec, WM8960_CLOCK2) & 0x03f; 669 wm8960_write(codec, WM8960_CLOCK2, reg | div); 670 break; 671 case WM8960_TOCLKSEL: 672 reg = wm8960_read(codec, WM8960_ADDCTL1) & 0x1fd; 673 wm8960_write(codec, WM8960_ADDCTL1, reg | div); 674 break; 675 default: 676 return -EINVAL; 677 } 678 679 return 0; 680 } 681 682 #define WM8960_RATES SNDRV_PCM_RATE_8000_48000 683 684 #define WM8960_FORMATS \ 685 (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE | \ 686 SNDRV_PCM_FMTBIT_S24_LE) 687 688 static struct snd_soc_dai_ops wm8960_dai_ops = { 689 .hw_params = wm8960_hw_params, 690 .digital_mute = wm8960_mute, 691 .set_fmt = wm8960_set_dai_fmt, 692 .set_clkdiv = wm8960_set_dai_clkdiv, 693 .set_pll = wm8960_set_dai_pll, 694 }; 695 696 struct snd_soc_dai wm8960_dai = { 697 .name = "WM8960", 698 .playback = { 699 .stream_name = "Playback", 700 .channels_min = 1, 701 .channels_max = 2, 702 .rates = WM8960_RATES, 703 .formats = WM8960_FORMATS,}, 704 .capture = { 705 .stream_name = "Capture", 706 .channels_min = 1, 707 .channels_max = 2, 708 .rates = WM8960_RATES, 709 .formats = WM8960_FORMATS,}, 710 .ops = &wm8960_dai_ops, 711 .symmetric_rates = 1, 712 }; 713 EXPORT_SYMBOL_GPL(wm8960_dai); 714 715 static int wm8960_suspend(struct platform_device *pdev, pm_message_t state) 716 { 717 struct snd_soc_device *socdev = platform_get_drvdata(pdev); 718 struct snd_soc_codec *codec = socdev->card->codec; 719 720 wm8960_set_bias_level(codec, SND_SOC_BIAS_OFF); 721 return 0; 722 } 723 724 static int wm8960_resume(struct platform_device *pdev) 725 { 726 struct snd_soc_device *socdev = platform_get_drvdata(pdev); 727 struct snd_soc_codec *codec = socdev->card->codec; 728 int i; 729 u8 data[2]; 730 u16 *cache = codec->reg_cache; 731 732 /* Sync reg_cache with the hardware */ 733 for (i = 0; i < ARRAY_SIZE(wm8960_reg); i++) { 734 data[0] = (i << 1) | ((cache[i] >> 8) & 0x0001); 735 data[1] = cache[i] & 0x00ff; 736 codec->hw_write(codec->control_data, data, 2); 737 } 738 739 wm8960_set_bias_level(codec, SND_SOC_BIAS_STANDBY); 740 wm8960_set_bias_level(codec, codec->suspend_bias_level); 741 return 0; 742 } 743 744 static struct snd_soc_codec *wm8960_codec; 745 746 static int wm8960_probe(struct platform_device *pdev) 747 { 748 struct snd_soc_device *socdev = platform_get_drvdata(pdev); 749 struct snd_soc_codec *codec; 750 int ret = 0; 751 752 if (wm8960_codec == NULL) { 753 dev_err(&pdev->dev, "Codec device not registered\n"); 754 return -ENODEV; 755 } 756 757 socdev->card->codec = wm8960_codec; 758 codec = wm8960_codec; 759 760 /* register pcms */ 761 ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1); 762 if (ret < 0) { 763 dev_err(codec->dev, "failed to create pcms: %d\n", ret); 764 goto pcm_err; 765 } 766 767 snd_soc_add_controls(codec, wm8960_snd_controls, 768 ARRAY_SIZE(wm8960_snd_controls)); 769 wm8960_add_widgets(codec); 770 ret = snd_soc_init_card(socdev); 771 if (ret < 0) { 772 dev_err(codec->dev, "failed to register card: %d\n", ret); 773 goto card_err; 774 } 775 776 return ret; 777 778 card_err: 779 snd_soc_free_pcms(socdev); 780 snd_soc_dapm_free(socdev); 781 pcm_err: 782 return ret; 783 } 784 785 /* power down chip */ 786 static int wm8960_remove(struct platform_device *pdev) 787 { 788 struct snd_soc_device *socdev = platform_get_drvdata(pdev); 789 790 snd_soc_free_pcms(socdev); 791 snd_soc_dapm_free(socdev); 792 793 return 0; 794 } 795 796 struct snd_soc_codec_device soc_codec_dev_wm8960 = { 797 .probe = wm8960_probe, 798 .remove = wm8960_remove, 799 .suspend = wm8960_suspend, 800 .resume = wm8960_resume, 801 }; 802 EXPORT_SYMBOL_GPL(soc_codec_dev_wm8960); 803 804 static int wm8960_register(struct wm8960_priv *wm8960) 805 { 806 struct wm8960_data *pdata = wm8960->codec.dev->platform_data; 807 struct snd_soc_codec *codec = &wm8960->codec; 808 int ret; 809 u16 reg; 810 811 if (wm8960_codec) { 812 dev_err(codec->dev, "Another WM8960 is registered\n"); 813 return -EINVAL; 814 } 815 816 if (!pdata) { 817 dev_warn(codec->dev, "No platform data supplied\n"); 818 } else { 819 if (pdata->dres > WM8960_DRES_MAX) { 820 dev_err(codec->dev, "Invalid DRES: %d\n", pdata->dres); 821 pdata->dres = 0; 822 } 823 } 824 825 mutex_init(&codec->mutex); 826 INIT_LIST_HEAD(&codec->dapm_widgets); 827 INIT_LIST_HEAD(&codec->dapm_paths); 828 829 codec->private_data = wm8960; 830 codec->name = "WM8960"; 831 codec->owner = THIS_MODULE; 832 codec->read = wm8960_read_reg_cache; 833 codec->write = wm8960_write; 834 codec->bias_level = SND_SOC_BIAS_OFF; 835 codec->set_bias_level = wm8960_set_bias_level; 836 codec->dai = &wm8960_dai; 837 codec->num_dai = 1; 838 codec->reg_cache_size = WM8960_CACHEREGNUM; 839 codec->reg_cache = &wm8960->reg_cache; 840 841 memcpy(codec->reg_cache, wm8960_reg, sizeof(wm8960_reg)); 842 843 ret = wm8960_reset(codec); 844 if (ret < 0) { 845 dev_err(codec->dev, "Failed to issue reset\n"); 846 return ret; 847 } 848 849 wm8960_dai.dev = codec->dev; 850 851 wm8960_set_bias_level(codec, SND_SOC_BIAS_STANDBY); 852 853 /* Latch the update bits */ 854 reg = wm8960_read(codec, WM8960_LINVOL); 855 wm8960_write(codec, WM8960_LINVOL, reg | 0x100); 856 reg = wm8960_read(codec, WM8960_RINVOL); 857 wm8960_write(codec, WM8960_RINVOL, reg | 0x100); 858 reg = wm8960_read(codec, WM8960_LADC); 859 wm8960_write(codec, WM8960_LADC, reg | 0x100); 860 reg = wm8960_read(codec, WM8960_RADC); 861 wm8960_write(codec, WM8960_RADC, reg | 0x100); 862 reg = wm8960_read(codec, WM8960_LDAC); 863 wm8960_write(codec, WM8960_LDAC, reg | 0x100); 864 reg = wm8960_read(codec, WM8960_RDAC); 865 wm8960_write(codec, WM8960_RDAC, reg | 0x100); 866 reg = wm8960_read(codec, WM8960_LOUT1); 867 wm8960_write(codec, WM8960_LOUT1, reg | 0x100); 868 reg = wm8960_read(codec, WM8960_ROUT1); 869 wm8960_write(codec, WM8960_ROUT1, reg | 0x100); 870 reg = wm8960_read(codec, WM8960_LOUT2); 871 wm8960_write(codec, WM8960_LOUT2, reg | 0x100); 872 reg = wm8960_read(codec, WM8960_ROUT2); 873 wm8960_write(codec, WM8960_ROUT2, reg | 0x100); 874 875 wm8960_codec = codec; 876 877 ret = snd_soc_register_codec(codec); 878 if (ret != 0) { 879 dev_err(codec->dev, "Failed to register codec: %d\n", ret); 880 return ret; 881 } 882 883 ret = snd_soc_register_dai(&wm8960_dai); 884 if (ret != 0) { 885 dev_err(codec->dev, "Failed to register DAI: %d\n", ret); 886 snd_soc_unregister_codec(codec); 887 return ret; 888 } 889 890 return 0; 891 } 892 893 static void wm8960_unregister(struct wm8960_priv *wm8960) 894 { 895 wm8960_set_bias_level(&wm8960->codec, SND_SOC_BIAS_OFF); 896 snd_soc_unregister_dai(&wm8960_dai); 897 snd_soc_unregister_codec(&wm8960->codec); 898 kfree(wm8960); 899 wm8960_codec = NULL; 900 } 901 902 static __devinit int wm8960_i2c_probe(struct i2c_client *i2c, 903 const struct i2c_device_id *id) 904 { 905 struct wm8960_priv *wm8960; 906 struct snd_soc_codec *codec; 907 908 wm8960 = kzalloc(sizeof(struct wm8960_priv), GFP_KERNEL); 909 if (wm8960 == NULL) 910 return -ENOMEM; 911 912 codec = &wm8960->codec; 913 codec->hw_write = (hw_write_t)i2c_master_send; 914 915 i2c_set_clientdata(i2c, wm8960); 916 codec->control_data = i2c; 917 918 codec->dev = &i2c->dev; 919 920 return wm8960_register(wm8960); 921 } 922 923 static __devexit int wm8960_i2c_remove(struct i2c_client *client) 924 { 925 struct wm8960_priv *wm8960 = i2c_get_clientdata(client); 926 wm8960_unregister(wm8960); 927 return 0; 928 } 929 930 static const struct i2c_device_id wm8960_i2c_id[] = { 931 { "wm8960", 0 }, 932 { } 933 }; 934 MODULE_DEVICE_TABLE(i2c, wm8960_i2c_id); 935 936 static struct i2c_driver wm8960_i2c_driver = { 937 .driver = { 938 .name = "WM8960 I2C Codec", 939 .owner = THIS_MODULE, 940 }, 941 .probe = wm8960_i2c_probe, 942 .remove = __devexit_p(wm8960_i2c_remove), 943 .id_table = wm8960_i2c_id, 944 }; 945 946 static int __init wm8960_modinit(void) 947 { 948 int ret; 949 950 ret = i2c_add_driver(&wm8960_i2c_driver); 951 if (ret != 0) { 952 printk(KERN_ERR "Failed to register WM8960 I2C driver: %d\n", 953 ret); 954 } 955 956 return ret; 957 } 958 module_init(wm8960_modinit); 959 960 static void __exit wm8960_exit(void) 961 { 962 i2c_del_driver(&wm8960_i2c_driver); 963 } 964 module_exit(wm8960_exit); 965 966 967 MODULE_DESCRIPTION("ASoC WM8960 driver"); 968 MODULE_AUTHOR("Liam Girdwood"); 969 MODULE_LICENSE("GPL"); 970