1 /* 2 * wm8770.c -- WM8770 ALSA SoC Audio driver 3 * 4 * Copyright 2010 Wolfson Microelectronics plc 5 * 6 * Author: Dimitris Papastamos <dp@opensource.wolfsonmicro.com> 7 * 8 * This program is free software; you can redistribute it and/or modify 9 * it under the terms of the GNU General Public License version 2 as 10 * published by the Free Software Foundation. 11 */ 12 13 #include <linux/module.h> 14 #include <linux/moduleparam.h> 15 #include <linux/init.h> 16 #include <linux/delay.h> 17 #include <linux/pm.h> 18 #include <linux/platform_device.h> 19 #include <linux/spi/spi.h> 20 #include <linux/regulator/consumer.h> 21 #include <linux/slab.h> 22 #include <sound/core.h> 23 #include <sound/pcm.h> 24 #include <sound/pcm_params.h> 25 #include <sound/soc.h> 26 #include <sound/initval.h> 27 #include <sound/tlv.h> 28 29 #include "wm8770.h" 30 31 #define WM8770_NUM_SUPPLIES 3 32 static const char *wm8770_supply_names[WM8770_NUM_SUPPLIES] = { 33 "AVDD1", 34 "AVDD2", 35 "DVDD" 36 }; 37 38 static const u16 wm8770_reg_defs[WM8770_CACHEREGNUM] = { 39 0x7f, 0x7f, 0x7f, 0x7f, 40 0x7f, 0x7f, 0x7f, 0x7f, 41 0x7f, 0xff, 0xff, 0xff, 42 0xff, 0xff, 0xff, 0xff, 43 0xff, 0xff, 0, 0x90, 0, 44 0, 0x22, 0x22, 0x3e, 45 0xc, 0xc, 0x100, 0x189, 46 0x189, 0x8770 47 }; 48 49 struct wm8770_priv { 50 enum snd_soc_control_type control_type; 51 struct regulator_bulk_data supplies[WM8770_NUM_SUPPLIES]; 52 struct notifier_block disable_nb[WM8770_NUM_SUPPLIES]; 53 struct snd_soc_codec *codec; 54 int sysclk; 55 }; 56 57 static int vout12supply_event(struct snd_soc_dapm_widget *w, 58 struct snd_kcontrol *kcontrol, int event); 59 static int vout34supply_event(struct snd_soc_dapm_widget *w, 60 struct snd_kcontrol *kcontrol, int event); 61 62 /* 63 * We can't use the same notifier block for more than one supply and 64 * there's no way I can see to get from a callback to the caller 65 * except container_of(). 66 */ 67 #define WM8770_REGULATOR_EVENT(n) \ 68 static int wm8770_regulator_event_##n(struct notifier_block *nb, \ 69 unsigned long event, void *data) \ 70 { \ 71 struct wm8770_priv *wm8770 = container_of(nb, struct wm8770_priv, \ 72 disable_nb[n]); \ 73 if (event & REGULATOR_EVENT_DISABLE) { \ 74 wm8770->codec->cache_sync = 1; \ 75 } \ 76 return 0; \ 77 } 78 79 WM8770_REGULATOR_EVENT(0) 80 WM8770_REGULATOR_EVENT(1) 81 WM8770_REGULATOR_EVENT(2) 82 83 static const DECLARE_TLV_DB_SCALE(adc_tlv, -1200, 100, 0); 84 static const DECLARE_TLV_DB_SCALE(dac_dig_tlv, -12750, 50, 1); 85 static const DECLARE_TLV_DB_SCALE(dac_alg_tlv, -12700, 100, 1); 86 87 static const char *dac_phase_text[][2] = { 88 { "DAC1 Normal", "DAC1 Inverted" }, 89 { "DAC2 Normal", "DAC2 Inverted" }, 90 { "DAC3 Normal", "DAC3 Inverted" }, 91 { "DAC4 Normal", "DAC4 Inverted" }, 92 }; 93 94 static const struct soc_enum dac_phase[] = { 95 SOC_ENUM_DOUBLE(WM8770_DACPHASE, 0, 1, 2, dac_phase_text[0]), 96 SOC_ENUM_DOUBLE(WM8770_DACPHASE, 2, 3, 2, dac_phase_text[1]), 97 SOC_ENUM_DOUBLE(WM8770_DACPHASE, 4, 5, 2, dac_phase_text[2]), 98 SOC_ENUM_DOUBLE(WM8770_DACPHASE, 6, 7, 2, dac_phase_text[3]), 99 }; 100 101 static const struct snd_kcontrol_new wm8770_snd_controls[] = { 102 /* global DAC playback controls */ 103 SOC_SINGLE_TLV("DAC Playback Volume", WM8770_MSDIGVOL, 0, 255, 0, 104 dac_dig_tlv), 105 SOC_SINGLE("DAC Playback Switch", WM8770_DACMUTE, 4, 1, 1), 106 SOC_SINGLE("DAC Playback ZC Switch", WM8770_DACCTRL1, 0, 1, 0), 107 108 /* global VOUT playback controls */ 109 SOC_SINGLE_TLV("VOUT Playback Volume", WM8770_MSALGVOL, 0, 127, 0, 110 dac_alg_tlv), 111 SOC_SINGLE("VOUT Playback ZC Switch", WM8770_MSALGVOL, 7, 1, 0), 112 113 /* VOUT1/2/3/4 specific controls */ 114 SOC_DOUBLE_R_TLV("VOUT1 Playback Volume", WM8770_VOUT1LVOL, 115 WM8770_VOUT1RVOL, 0, 127, 0, dac_alg_tlv), 116 SOC_DOUBLE_R("VOUT1 Playback ZC Switch", WM8770_VOUT1LVOL, 117 WM8770_VOUT1RVOL, 7, 1, 0), 118 SOC_DOUBLE_R_TLV("VOUT2 Playback Volume", WM8770_VOUT2LVOL, 119 WM8770_VOUT2RVOL, 0, 127, 0, dac_alg_tlv), 120 SOC_DOUBLE_R("VOUT2 Playback ZC Switch", WM8770_VOUT2LVOL, 121 WM8770_VOUT2RVOL, 7, 1, 0), 122 SOC_DOUBLE_R_TLV("VOUT3 Playback Volume", WM8770_VOUT3LVOL, 123 WM8770_VOUT3RVOL, 0, 127, 0, dac_alg_tlv), 124 SOC_DOUBLE_R("VOUT3 Playback ZC Switch", WM8770_VOUT3LVOL, 125 WM8770_VOUT3RVOL, 7, 1, 0), 126 SOC_DOUBLE_R_TLV("VOUT4 Playback Volume", WM8770_VOUT4LVOL, 127 WM8770_VOUT4RVOL, 0, 127, 0, dac_alg_tlv), 128 SOC_DOUBLE_R("VOUT4 Playback ZC Switch", WM8770_VOUT4LVOL, 129 WM8770_VOUT4RVOL, 7, 1, 0), 130 131 /* DAC1/2/3/4 specific controls */ 132 SOC_DOUBLE_R_TLV("DAC1 Playback Volume", WM8770_DAC1LVOL, 133 WM8770_DAC1RVOL, 0, 255, 0, dac_dig_tlv), 134 SOC_SINGLE("DAC1 Deemphasis Switch", WM8770_DACCTRL2, 0, 1, 0), 135 SOC_ENUM("DAC1 Phase", dac_phase[0]), 136 SOC_DOUBLE_R_TLV("DAC2 Playback Volume", WM8770_DAC2LVOL, 137 WM8770_DAC2RVOL, 0, 255, 0, dac_dig_tlv), 138 SOC_SINGLE("DAC2 Deemphasis Switch", WM8770_DACCTRL2, 1, 1, 0), 139 SOC_ENUM("DAC2 Phase", dac_phase[1]), 140 SOC_DOUBLE_R_TLV("DAC3 Playback Volume", WM8770_DAC3LVOL, 141 WM8770_DAC3RVOL, 0, 255, 0, dac_dig_tlv), 142 SOC_SINGLE("DAC3 Deemphasis Switch", WM8770_DACCTRL2, 2, 1, 0), 143 SOC_ENUM("DAC3 Phase", dac_phase[2]), 144 SOC_DOUBLE_R_TLV("DAC4 Playback Volume", WM8770_DAC4LVOL, 145 WM8770_DAC4RVOL, 0, 255, 0, dac_dig_tlv), 146 SOC_SINGLE("DAC4 Deemphasis Switch", WM8770_DACCTRL2, 3, 1, 0), 147 SOC_ENUM("DAC4 Phase", dac_phase[3]), 148 149 /* ADC specific controls */ 150 SOC_DOUBLE_R_TLV("Capture Volume", WM8770_ADCLCTRL, WM8770_ADCRCTRL, 151 0, 31, 0, adc_tlv), 152 SOC_DOUBLE_R("Capture Switch", WM8770_ADCLCTRL, WM8770_ADCRCTRL, 153 5, 1, 1), 154 155 /* other controls */ 156 SOC_SINGLE("ADC 128x Oversampling Switch", WM8770_MSTRCTRL, 3, 1, 0), 157 SOC_SINGLE("ADC Highpass Filter Switch", WM8770_IFACECTRL, 8, 1, 1) 158 }; 159 160 static const char *ain_text[] = { 161 "AIN1", "AIN2", "AIN3", "AIN4", 162 "AIN5", "AIN6", "AIN7", "AIN8" 163 }; 164 165 static const struct soc_enum ain_enum = 166 SOC_ENUM_DOUBLE(WM8770_ADCMUX, 0, 4, 8, ain_text); 167 168 static const struct snd_kcontrol_new ain_mux = 169 SOC_DAPM_ENUM("Capture Mux", ain_enum); 170 171 static const struct snd_kcontrol_new vout1_mix_controls[] = { 172 SOC_DAPM_SINGLE("DAC1 Switch", WM8770_OUTMUX1, 0, 1, 0), 173 SOC_DAPM_SINGLE("AUX1 Switch", WM8770_OUTMUX1, 1, 1, 0), 174 SOC_DAPM_SINGLE("Bypass Switch", WM8770_OUTMUX1, 2, 1, 0) 175 }; 176 177 static const struct snd_kcontrol_new vout2_mix_controls[] = { 178 SOC_DAPM_SINGLE("DAC2 Switch", WM8770_OUTMUX1, 3, 1, 0), 179 SOC_DAPM_SINGLE("AUX2 Switch", WM8770_OUTMUX1, 4, 1, 0), 180 SOC_DAPM_SINGLE("Bypass Switch", WM8770_OUTMUX1, 5, 1, 0) 181 }; 182 183 static const struct snd_kcontrol_new vout3_mix_controls[] = { 184 SOC_DAPM_SINGLE("DAC3 Switch", WM8770_OUTMUX2, 0, 1, 0), 185 SOC_DAPM_SINGLE("AUX3 Switch", WM8770_OUTMUX2, 1, 1, 0), 186 SOC_DAPM_SINGLE("Bypass Switch", WM8770_OUTMUX2, 2, 1, 0) 187 }; 188 189 static const struct snd_kcontrol_new vout4_mix_controls[] = { 190 SOC_DAPM_SINGLE("DAC4 Switch", WM8770_OUTMUX2, 3, 1, 0), 191 SOC_DAPM_SINGLE("Bypass Switch", WM8770_OUTMUX2, 4, 1, 0) 192 }; 193 194 static const struct snd_soc_dapm_widget wm8770_dapm_widgets[] = { 195 SND_SOC_DAPM_INPUT("AUX1"), 196 SND_SOC_DAPM_INPUT("AUX2"), 197 SND_SOC_DAPM_INPUT("AUX3"), 198 199 SND_SOC_DAPM_INPUT("AIN1"), 200 SND_SOC_DAPM_INPUT("AIN2"), 201 SND_SOC_DAPM_INPUT("AIN3"), 202 SND_SOC_DAPM_INPUT("AIN4"), 203 SND_SOC_DAPM_INPUT("AIN5"), 204 SND_SOC_DAPM_INPUT("AIN6"), 205 SND_SOC_DAPM_INPUT("AIN7"), 206 SND_SOC_DAPM_INPUT("AIN8"), 207 208 SND_SOC_DAPM_MUX("Capture Mux", WM8770_ADCMUX, 8, 1, &ain_mux), 209 210 SND_SOC_DAPM_ADC("ADC", "Capture", WM8770_PWDNCTRL, 1, 1), 211 212 SND_SOC_DAPM_DAC("DAC1", "Playback", WM8770_PWDNCTRL, 2, 1), 213 SND_SOC_DAPM_DAC("DAC2", "Playback", WM8770_PWDNCTRL, 3, 1), 214 SND_SOC_DAPM_DAC("DAC3", "Playback", WM8770_PWDNCTRL, 4, 1), 215 SND_SOC_DAPM_DAC("DAC4", "Playback", WM8770_PWDNCTRL, 5, 1), 216 217 SND_SOC_DAPM_SUPPLY("VOUT12 Supply", SND_SOC_NOPM, 0, 0, 218 vout12supply_event, SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD), 219 SND_SOC_DAPM_SUPPLY("VOUT34 Supply", SND_SOC_NOPM, 0, 0, 220 vout34supply_event, SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD), 221 222 SND_SOC_DAPM_MIXER("VOUT1 Mixer", SND_SOC_NOPM, 0, 0, 223 vout1_mix_controls, ARRAY_SIZE(vout1_mix_controls)), 224 SND_SOC_DAPM_MIXER("VOUT2 Mixer", SND_SOC_NOPM, 0, 0, 225 vout2_mix_controls, ARRAY_SIZE(vout2_mix_controls)), 226 SND_SOC_DAPM_MIXER("VOUT3 Mixer", SND_SOC_NOPM, 0, 0, 227 vout3_mix_controls, ARRAY_SIZE(vout3_mix_controls)), 228 SND_SOC_DAPM_MIXER("VOUT4 Mixer", SND_SOC_NOPM, 0, 0, 229 vout4_mix_controls, ARRAY_SIZE(vout4_mix_controls)), 230 231 SND_SOC_DAPM_OUTPUT("VOUT1"), 232 SND_SOC_DAPM_OUTPUT("VOUT2"), 233 SND_SOC_DAPM_OUTPUT("VOUT3"), 234 SND_SOC_DAPM_OUTPUT("VOUT4") 235 }; 236 237 static const struct snd_soc_dapm_route wm8770_intercon[] = { 238 { "Capture Mux", "AIN1", "AIN1" }, 239 { "Capture Mux", "AIN2", "AIN2" }, 240 { "Capture Mux", "AIN3", "AIN3" }, 241 { "Capture Mux", "AIN4", "AIN4" }, 242 { "Capture Mux", "AIN5", "AIN5" }, 243 { "Capture Mux", "AIN6", "AIN6" }, 244 { "Capture Mux", "AIN7", "AIN7" }, 245 { "Capture Mux", "AIN8", "AIN8" }, 246 247 { "ADC", NULL, "Capture Mux" }, 248 249 { "VOUT1 Mixer", NULL, "VOUT12 Supply" }, 250 { "VOUT1 Mixer", "DAC1 Switch", "DAC1" }, 251 { "VOUT1 Mixer", "AUX1 Switch", "AUX1" }, 252 { "VOUT1 Mixer", "Bypass Switch", "Capture Mux" }, 253 254 { "VOUT2 Mixer", NULL, "VOUT12 Supply" }, 255 { "VOUT2 Mixer", "DAC2 Switch", "DAC2" }, 256 { "VOUT2 Mixer", "AUX2 Switch", "AUX2" }, 257 { "VOUT2 Mixer", "Bypass Switch", "Capture Mux" }, 258 259 { "VOUT3 Mixer", NULL, "VOUT34 Supply" }, 260 { "VOUT3 Mixer", "DAC3 Switch", "DAC3" }, 261 { "VOUT3 Mixer", "AUX3 Switch", "AUX3" }, 262 { "VOUT3 Mixer", "Bypass Switch", "Capture Mux" }, 263 264 { "VOUT4 Mixer", NULL, "VOUT34 Supply" }, 265 { "VOUT4 Mixer", "DAC4 Switch", "DAC4" }, 266 { "VOUT4 Mixer", "Bypass Switch", "Capture Mux" }, 267 268 { "VOUT1", NULL, "VOUT1 Mixer" }, 269 { "VOUT2", NULL, "VOUT2 Mixer" }, 270 { "VOUT3", NULL, "VOUT3 Mixer" }, 271 { "VOUT4", NULL, "VOUT4 Mixer" } 272 }; 273 274 static int vout12supply_event(struct snd_soc_dapm_widget *w, 275 struct snd_kcontrol *kcontrol, int event) 276 { 277 struct snd_soc_codec *codec; 278 279 codec = w->codec; 280 281 switch (event) { 282 case SND_SOC_DAPM_PRE_PMU: 283 snd_soc_update_bits(codec, WM8770_OUTMUX1, 0x180, 0); 284 break; 285 case SND_SOC_DAPM_POST_PMD: 286 snd_soc_update_bits(codec, WM8770_OUTMUX1, 0x180, 0x180); 287 break; 288 } 289 290 return 0; 291 } 292 293 static int vout34supply_event(struct snd_soc_dapm_widget *w, 294 struct snd_kcontrol *kcontrol, int event) 295 { 296 struct snd_soc_codec *codec; 297 298 codec = w->codec; 299 300 switch (event) { 301 case SND_SOC_DAPM_PRE_PMU: 302 snd_soc_update_bits(codec, WM8770_OUTMUX2, 0x180, 0); 303 break; 304 case SND_SOC_DAPM_POST_PMD: 305 snd_soc_update_bits(codec, WM8770_OUTMUX2, 0x180, 0x180); 306 break; 307 } 308 309 return 0; 310 } 311 312 static int wm8770_reset(struct snd_soc_codec *codec) 313 { 314 return snd_soc_write(codec, WM8770_RESET, 0); 315 } 316 317 static int wm8770_set_fmt(struct snd_soc_dai *dai, unsigned int fmt) 318 { 319 struct snd_soc_codec *codec; 320 int iface, master; 321 322 codec = dai->codec; 323 324 switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { 325 case SND_SOC_DAIFMT_CBM_CFM: 326 master = 0x100; 327 break; 328 case SND_SOC_DAIFMT_CBS_CFS: 329 master = 0; 330 break; 331 default: 332 return -EINVAL; 333 } 334 335 iface = 0; 336 switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { 337 case SND_SOC_DAIFMT_I2S: 338 iface |= 0x2; 339 break; 340 case SND_SOC_DAIFMT_RIGHT_J: 341 break; 342 case SND_SOC_DAIFMT_LEFT_J: 343 iface |= 0x1; 344 break; 345 default: 346 return -EINVAL; 347 } 348 349 switch (fmt & SND_SOC_DAIFMT_INV_MASK) { 350 case SND_SOC_DAIFMT_NB_NF: 351 break; 352 case SND_SOC_DAIFMT_IB_IF: 353 iface |= 0xc; 354 break; 355 case SND_SOC_DAIFMT_IB_NF: 356 iface |= 0x8; 357 break; 358 case SND_SOC_DAIFMT_NB_IF: 359 iface |= 0x4; 360 break; 361 default: 362 return -EINVAL; 363 } 364 365 snd_soc_update_bits(codec, WM8770_IFACECTRL, 0xf, iface); 366 snd_soc_update_bits(codec, WM8770_MSTRCTRL, 0x100, master); 367 368 return 0; 369 } 370 371 static const int mclk_ratios[] = { 372 128, 373 192, 374 256, 375 384, 376 512, 377 768 378 }; 379 380 static int wm8770_hw_params(struct snd_pcm_substream *substream, 381 struct snd_pcm_hw_params *params, 382 struct snd_soc_dai *dai) 383 { 384 struct snd_soc_codec *codec; 385 struct wm8770_priv *wm8770; 386 int i; 387 int iface; 388 int shift; 389 int ratio; 390 391 codec = dai->codec; 392 wm8770 = snd_soc_codec_get_drvdata(codec); 393 394 iface = 0; 395 switch (params_format(params)) { 396 case SNDRV_PCM_FORMAT_S16_LE: 397 break; 398 case SNDRV_PCM_FORMAT_S20_3LE: 399 iface |= 0x10; 400 break; 401 case SNDRV_PCM_FORMAT_S24_LE: 402 iface |= 0x20; 403 break; 404 case SNDRV_PCM_FORMAT_S32_LE: 405 iface |= 0x30; 406 break; 407 } 408 409 switch (substream->stream) { 410 case SNDRV_PCM_STREAM_PLAYBACK: 411 i = 0; 412 shift = 4; 413 break; 414 case SNDRV_PCM_STREAM_CAPTURE: 415 i = 2; 416 shift = 0; 417 break; 418 default: 419 return -EINVAL; 420 } 421 422 /* Only need to set MCLK/LRCLK ratio if we're master */ 423 if (snd_soc_read(codec, WM8770_MSTRCTRL) & 0x100) { 424 for (; i < ARRAY_SIZE(mclk_ratios); ++i) { 425 ratio = wm8770->sysclk / params_rate(params); 426 if (ratio == mclk_ratios[i]) 427 break; 428 } 429 430 if (i == ARRAY_SIZE(mclk_ratios)) { 431 dev_err(codec->dev, 432 "Unable to configure MCLK ratio %d/%d\n", 433 wm8770->sysclk, params_rate(params)); 434 return -EINVAL; 435 } 436 437 dev_dbg(codec->dev, "MCLK is %dfs\n", mclk_ratios[i]); 438 439 snd_soc_update_bits(codec, WM8770_MSTRCTRL, 0x7 << shift, 440 i << shift); 441 } 442 443 snd_soc_update_bits(codec, WM8770_IFACECTRL, 0x30, iface); 444 445 return 0; 446 } 447 448 static int wm8770_mute(struct snd_soc_dai *dai, int mute) 449 { 450 struct snd_soc_codec *codec; 451 452 codec = dai->codec; 453 return snd_soc_update_bits(codec, WM8770_DACMUTE, 0x10, 454 !!mute << 4); 455 } 456 457 static int wm8770_set_sysclk(struct snd_soc_dai *dai, 458 int clk_id, unsigned int freq, int dir) 459 { 460 struct snd_soc_codec *codec; 461 struct wm8770_priv *wm8770; 462 463 codec = dai->codec; 464 wm8770 = snd_soc_codec_get_drvdata(codec); 465 wm8770->sysclk = freq; 466 return 0; 467 } 468 469 static void wm8770_sync_cache(struct snd_soc_codec *codec) 470 { 471 int i; 472 u16 *cache; 473 474 if (!codec->cache_sync) 475 return; 476 477 codec->cache_only = 0; 478 cache = codec->reg_cache; 479 for (i = 0; i < codec->driver->reg_cache_size; i++) { 480 if (i == WM8770_RESET || cache[i] == wm8770_reg_defs[i]) 481 continue; 482 snd_soc_write(codec, i, cache[i]); 483 } 484 codec->cache_sync = 0; 485 } 486 487 static int wm8770_set_bias_level(struct snd_soc_codec *codec, 488 enum snd_soc_bias_level level) 489 { 490 int ret; 491 struct wm8770_priv *wm8770; 492 493 wm8770 = snd_soc_codec_get_drvdata(codec); 494 495 switch (level) { 496 case SND_SOC_BIAS_ON: 497 break; 498 case SND_SOC_BIAS_PREPARE: 499 break; 500 case SND_SOC_BIAS_STANDBY: 501 if (codec->dapm.bias_level == SND_SOC_BIAS_OFF) { 502 ret = regulator_bulk_enable(ARRAY_SIZE(wm8770->supplies), 503 wm8770->supplies); 504 if (ret) { 505 dev_err(codec->dev, 506 "Failed to enable supplies: %d\n", 507 ret); 508 return ret; 509 } 510 wm8770_sync_cache(codec); 511 /* global powerup */ 512 snd_soc_write(codec, WM8770_PWDNCTRL, 0); 513 } 514 break; 515 case SND_SOC_BIAS_OFF: 516 /* global powerdown */ 517 snd_soc_write(codec, WM8770_PWDNCTRL, 1); 518 regulator_bulk_disable(ARRAY_SIZE(wm8770->supplies), 519 wm8770->supplies); 520 break; 521 } 522 523 codec->dapm.bias_level = level; 524 return 0; 525 } 526 527 #define WM8770_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE | \ 528 SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S32_LE) 529 530 static struct snd_soc_dai_ops wm8770_dai_ops = { 531 .digital_mute = wm8770_mute, 532 .hw_params = wm8770_hw_params, 533 .set_fmt = wm8770_set_fmt, 534 .set_sysclk = wm8770_set_sysclk, 535 }; 536 537 static struct snd_soc_dai_driver wm8770_dai = { 538 .name = "wm8770-hifi", 539 .playback = { 540 .stream_name = "Playback", 541 .channels_min = 2, 542 .channels_max = 2, 543 .rates = SNDRV_PCM_RATE_8000_192000, 544 .formats = WM8770_FORMATS 545 }, 546 .capture = { 547 .stream_name = "Capture", 548 .channels_min = 2, 549 .channels_max = 2, 550 .rates = SNDRV_PCM_RATE_8000_96000, 551 .formats = WM8770_FORMATS 552 }, 553 .ops = &wm8770_dai_ops, 554 .symmetric_rates = 1 555 }; 556 557 #ifdef CONFIG_PM 558 static int wm8770_suspend(struct snd_soc_codec *codec, pm_message_t state) 559 { 560 wm8770_set_bias_level(codec, SND_SOC_BIAS_OFF); 561 return 0; 562 } 563 564 static int wm8770_resume(struct snd_soc_codec *codec) 565 { 566 wm8770_set_bias_level(codec, SND_SOC_BIAS_STANDBY); 567 return 0; 568 } 569 #else 570 #define wm8770_suspend NULL 571 #define wm8770_resume NULL 572 #endif 573 574 static int wm8770_probe(struct snd_soc_codec *codec) 575 { 576 struct wm8770_priv *wm8770; 577 int ret; 578 int i; 579 580 wm8770 = snd_soc_codec_get_drvdata(codec); 581 wm8770->codec = codec; 582 583 codec->dapm.idle_bias_off = 1; 584 585 ret = snd_soc_codec_set_cache_io(codec, 7, 9, wm8770->control_type); 586 if (ret < 0) { 587 dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret); 588 return ret; 589 } 590 591 for (i = 0; i < ARRAY_SIZE(wm8770->supplies); i++) 592 wm8770->supplies[i].supply = wm8770_supply_names[i]; 593 594 ret = regulator_bulk_get(codec->dev, ARRAY_SIZE(wm8770->supplies), 595 wm8770->supplies); 596 if (ret) { 597 dev_err(codec->dev, "Failed to request supplies: %d\n", ret); 598 return ret; 599 } 600 601 wm8770->disable_nb[0].notifier_call = wm8770_regulator_event_0; 602 wm8770->disable_nb[1].notifier_call = wm8770_regulator_event_1; 603 wm8770->disable_nb[2].notifier_call = wm8770_regulator_event_2; 604 605 /* This should really be moved into the regulator core */ 606 for (i = 0; i < ARRAY_SIZE(wm8770->supplies); i++) { 607 ret = regulator_register_notifier(wm8770->supplies[i].consumer, 608 &wm8770->disable_nb[i]); 609 if (ret) { 610 dev_err(codec->dev, 611 "Failed to register regulator notifier: %d\n", 612 ret); 613 } 614 } 615 616 ret = regulator_bulk_enable(ARRAY_SIZE(wm8770->supplies), 617 wm8770->supplies); 618 if (ret) { 619 dev_err(codec->dev, "Failed to enable supplies: %d\n", ret); 620 goto err_reg_get; 621 } 622 623 ret = wm8770_reset(codec); 624 if (ret < 0) { 625 dev_err(codec->dev, "Failed to issue reset: %d\n", ret); 626 goto err_reg_enable; 627 } 628 629 wm8770_set_bias_level(codec, SND_SOC_BIAS_STANDBY); 630 631 /* latch the volume update bits */ 632 snd_soc_update_bits(codec, WM8770_MSDIGVOL, 0x100, 0x100); 633 snd_soc_update_bits(codec, WM8770_MSALGVOL, 0x100, 0x100); 634 snd_soc_update_bits(codec, WM8770_VOUT1RVOL, 0x100, 0x100); 635 snd_soc_update_bits(codec, WM8770_VOUT2RVOL, 0x100, 0x100); 636 snd_soc_update_bits(codec, WM8770_VOUT3RVOL, 0x100, 0x100); 637 snd_soc_update_bits(codec, WM8770_VOUT4RVOL, 0x100, 0x100); 638 snd_soc_update_bits(codec, WM8770_DAC1RVOL, 0x100, 0x100); 639 snd_soc_update_bits(codec, WM8770_DAC2RVOL, 0x100, 0x100); 640 snd_soc_update_bits(codec, WM8770_DAC3RVOL, 0x100, 0x100); 641 snd_soc_update_bits(codec, WM8770_DAC4RVOL, 0x100, 0x100); 642 643 /* mute all DACs */ 644 snd_soc_update_bits(codec, WM8770_DACMUTE, 0x10, 0x10); 645 646 snd_soc_add_controls(codec, wm8770_snd_controls, 647 ARRAY_SIZE(wm8770_snd_controls)); 648 snd_soc_dapm_new_controls(&codec->dapm, wm8770_dapm_widgets, 649 ARRAY_SIZE(wm8770_dapm_widgets)); 650 snd_soc_dapm_add_routes(&codec->dapm, wm8770_intercon, 651 ARRAY_SIZE(wm8770_intercon)); 652 return 0; 653 654 err_reg_enable: 655 regulator_bulk_disable(ARRAY_SIZE(wm8770->supplies), wm8770->supplies); 656 err_reg_get: 657 regulator_bulk_free(ARRAY_SIZE(wm8770->supplies), wm8770->supplies); 658 return ret; 659 } 660 661 static int wm8770_remove(struct snd_soc_codec *codec) 662 { 663 struct wm8770_priv *wm8770; 664 int i; 665 666 wm8770 = snd_soc_codec_get_drvdata(codec); 667 wm8770_set_bias_level(codec, SND_SOC_BIAS_OFF); 668 669 for (i = 0; i < ARRAY_SIZE(wm8770->supplies); ++i) 670 regulator_unregister_notifier(wm8770->supplies[i].consumer, 671 &wm8770->disable_nb[i]); 672 regulator_bulk_free(ARRAY_SIZE(wm8770->supplies), wm8770->supplies); 673 return 0; 674 } 675 676 static struct snd_soc_codec_driver soc_codec_dev_wm8770 = { 677 .probe = wm8770_probe, 678 .remove = wm8770_remove, 679 .suspend = wm8770_suspend, 680 .resume = wm8770_resume, 681 .set_bias_level = wm8770_set_bias_level, 682 .reg_cache_size = ARRAY_SIZE(wm8770_reg_defs), 683 .reg_word_size = sizeof (u16), 684 .reg_cache_default = wm8770_reg_defs 685 }; 686 687 #if defined(CONFIG_SPI_MASTER) 688 static int __devinit wm8770_spi_probe(struct spi_device *spi) 689 { 690 struct wm8770_priv *wm8770; 691 int ret; 692 693 wm8770 = kzalloc(sizeof(struct wm8770_priv), GFP_KERNEL); 694 if (!wm8770) 695 return -ENOMEM; 696 697 wm8770->control_type = SND_SOC_SPI; 698 spi_set_drvdata(spi, wm8770); 699 700 ret = snd_soc_register_codec(&spi->dev, 701 &soc_codec_dev_wm8770, &wm8770_dai, 1); 702 if (ret < 0) 703 kfree(wm8770); 704 return ret; 705 } 706 707 static int __devexit wm8770_spi_remove(struct spi_device *spi) 708 { 709 snd_soc_unregister_codec(&spi->dev); 710 kfree(spi_get_drvdata(spi)); 711 return 0; 712 } 713 714 static struct spi_driver wm8770_spi_driver = { 715 .driver = { 716 .name = "wm8770", 717 .owner = THIS_MODULE, 718 }, 719 .probe = wm8770_spi_probe, 720 .remove = __devexit_p(wm8770_spi_remove) 721 }; 722 #endif 723 724 static int __init wm8770_modinit(void) 725 { 726 int ret = 0; 727 728 #if defined(CONFIG_SPI_MASTER) 729 ret = spi_register_driver(&wm8770_spi_driver); 730 if (ret) { 731 printk(KERN_ERR "Failed to register wm8770 SPI driver: %d\n", 732 ret); 733 } 734 #endif 735 return ret; 736 } 737 module_init(wm8770_modinit); 738 739 static void __exit wm8770_exit(void) 740 { 741 #if defined(CONFIG_SPI_MASTER) 742 spi_unregister_driver(&wm8770_spi_driver); 743 #endif 744 } 745 module_exit(wm8770_exit); 746 747 MODULE_DESCRIPTION("ASoC WM8770 driver"); 748 MODULE_AUTHOR("Dimitris Papastamos <dp@opensource.wolfsonmicro.com>"); 749 MODULE_LICENSE("GPL"); 750