1 /* 2 * wm8804.c -- WM8804 S/PDIF transceiver driver 3 * 4 * Copyright 2010-11 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/gpio/consumer.h> 17 #include <linux/delay.h> 18 #include <linux/pm.h> 19 #include <linux/pm_runtime.h> 20 #include <linux/of_device.h> 21 #include <linux/regulator/consumer.h> 22 #include <linux/slab.h> 23 #include <sound/core.h> 24 #include <sound/pcm.h> 25 #include <sound/pcm_params.h> 26 #include <sound/soc.h> 27 #include <sound/initval.h> 28 #include <sound/tlv.h> 29 #include <sound/soc-dapm.h> 30 31 #include "wm8804.h" 32 33 #define WM8804_NUM_SUPPLIES 2 34 static const char *wm8804_supply_names[WM8804_NUM_SUPPLIES] = { 35 "PVDD", 36 "DVDD" 37 }; 38 39 static const struct reg_default wm8804_reg_defaults[] = { 40 { 3, 0x21 }, /* R3 - PLL1 */ 41 { 4, 0xFD }, /* R4 - PLL2 */ 42 { 5, 0x36 }, /* R5 - PLL3 */ 43 { 6, 0x07 }, /* R6 - PLL4 */ 44 { 7, 0x16 }, /* R7 - PLL5 */ 45 { 8, 0x18 }, /* R8 - PLL6 */ 46 { 9, 0xFF }, /* R9 - SPDMODE */ 47 { 10, 0x00 }, /* R10 - INTMASK */ 48 { 18, 0x00 }, /* R18 - SPDTX1 */ 49 { 19, 0x00 }, /* R19 - SPDTX2 */ 50 { 20, 0x00 }, /* R20 - SPDTX3 */ 51 { 21, 0x71 }, /* R21 - SPDTX4 */ 52 { 22, 0x0B }, /* R22 - SPDTX5 */ 53 { 23, 0x70 }, /* R23 - GPO0 */ 54 { 24, 0x57 }, /* R24 - GPO1 */ 55 { 26, 0x42 }, /* R26 - GPO2 */ 56 { 27, 0x06 }, /* R27 - AIFTX */ 57 { 28, 0x06 }, /* R28 - AIFRX */ 58 { 29, 0x80 }, /* R29 - SPDRX1 */ 59 { 30, 0x07 }, /* R30 - PWRDN */ 60 }; 61 62 struct wm8804_priv { 63 struct device *dev; 64 struct regmap *regmap; 65 struct regulator_bulk_data supplies[WM8804_NUM_SUPPLIES]; 66 struct notifier_block disable_nb[WM8804_NUM_SUPPLIES]; 67 int mclk_div; 68 69 struct gpio_desc *reset; 70 71 int aif_pwr; 72 }; 73 74 static int txsrc_put(struct snd_kcontrol *kcontrol, 75 struct snd_ctl_elem_value *ucontrol); 76 77 static int wm8804_aif_event(struct snd_soc_dapm_widget *w, 78 struct snd_kcontrol *kcontrol, int event); 79 80 /* 81 * We can't use the same notifier block for more than one supply and 82 * there's no way I can see to get from a callback to the caller 83 * except container_of(). 84 */ 85 #define WM8804_REGULATOR_EVENT(n) \ 86 static int wm8804_regulator_event_##n(struct notifier_block *nb, \ 87 unsigned long event, void *data) \ 88 { \ 89 struct wm8804_priv *wm8804 = container_of(nb, struct wm8804_priv, \ 90 disable_nb[n]); \ 91 if (event & REGULATOR_EVENT_DISABLE) { \ 92 regcache_mark_dirty(wm8804->regmap); \ 93 } \ 94 return 0; \ 95 } 96 97 WM8804_REGULATOR_EVENT(0) 98 WM8804_REGULATOR_EVENT(1) 99 100 static const char *txsrc_text[] = { "S/PDIF RX", "AIF" }; 101 static const SOC_ENUM_SINGLE_DECL(txsrc, WM8804_SPDTX4, 6, txsrc_text); 102 103 static const struct snd_kcontrol_new wm8804_tx_source_mux[] = { 104 SOC_DAPM_ENUM_EXT("Input Source", txsrc, 105 snd_soc_dapm_get_enum_double, txsrc_put), 106 }; 107 108 static const struct snd_soc_dapm_widget wm8804_dapm_widgets[] = { 109 SND_SOC_DAPM_OUTPUT("SPDIF Out"), 110 SND_SOC_DAPM_INPUT("SPDIF In"), 111 112 SND_SOC_DAPM_PGA("SPDIFTX", WM8804_PWRDN, 2, 1, NULL, 0), 113 SND_SOC_DAPM_PGA("SPDIFRX", WM8804_PWRDN, 1, 1, NULL, 0), 114 115 SND_SOC_DAPM_MUX("Tx Source", SND_SOC_NOPM, 6, 0, wm8804_tx_source_mux), 116 117 SND_SOC_DAPM_AIF_OUT_E("AIFTX", NULL, 0, SND_SOC_NOPM, 0, 0, wm8804_aif_event, 118 SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD), 119 SND_SOC_DAPM_AIF_IN_E("AIFRX", NULL, 0, SND_SOC_NOPM, 0, 0, wm8804_aif_event, 120 SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD), 121 }; 122 123 static const struct snd_soc_dapm_route wm8804_dapm_routes[] = { 124 { "AIFRX", NULL, "Playback" }, 125 { "Tx Source", "AIF", "AIFRX" }, 126 127 { "SPDIFRX", NULL, "SPDIF In" }, 128 { "Tx Source", "S/PDIF RX", "SPDIFRX" }, 129 130 { "SPDIFTX", NULL, "Tx Source" }, 131 { "SPDIF Out", NULL, "SPDIFTX" }, 132 133 { "AIFTX", NULL, "SPDIFRX" }, 134 { "Capture", NULL, "AIFTX" }, 135 }; 136 137 static int wm8804_aif_event(struct snd_soc_dapm_widget *w, 138 struct snd_kcontrol *kcontrol, int event) 139 { 140 struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm); 141 struct wm8804_priv *wm8804 = snd_soc_codec_get_drvdata(codec); 142 143 switch (event) { 144 case SND_SOC_DAPM_POST_PMU: 145 /* power up the aif */ 146 if (!wm8804->aif_pwr) 147 snd_soc_update_bits(codec, WM8804_PWRDN, 0x10, 0x0); 148 wm8804->aif_pwr++; 149 break; 150 case SND_SOC_DAPM_POST_PMD: 151 /* power down only both paths are disabled */ 152 wm8804->aif_pwr--; 153 if (!wm8804->aif_pwr) 154 snd_soc_update_bits(codec, WM8804_PWRDN, 0x10, 0x10); 155 break; 156 } 157 158 return 0; 159 } 160 161 static int txsrc_put(struct snd_kcontrol *kcontrol, 162 struct snd_ctl_elem_value *ucontrol) 163 { 164 struct snd_soc_codec *codec = snd_soc_dapm_kcontrol_codec(kcontrol); 165 struct snd_soc_dapm_context *dapm = snd_soc_codec_get_dapm(codec); 166 struct soc_enum *e = (struct soc_enum *)kcontrol->private_value; 167 unsigned int val = ucontrol->value.enumerated.item[0] << e->shift_l; 168 unsigned int mask = 1 << e->shift_l; 169 unsigned int txpwr; 170 171 if (val != 0 && val != mask) 172 return -EINVAL; 173 174 snd_soc_dapm_mutex_lock(dapm); 175 176 if (snd_soc_test_bits(codec, e->reg, mask, val)) { 177 /* save the current power state of the transmitter */ 178 txpwr = snd_soc_read(codec, WM8804_PWRDN) & 0x4; 179 180 /* power down the transmitter */ 181 snd_soc_update_bits(codec, WM8804_PWRDN, 0x4, 0x4); 182 183 /* set the tx source */ 184 snd_soc_update_bits(codec, e->reg, mask, val); 185 186 /* restore the transmitter's configuration */ 187 snd_soc_update_bits(codec, WM8804_PWRDN, 0x4, txpwr); 188 } 189 190 snd_soc_dapm_mutex_unlock(dapm); 191 192 return 0; 193 } 194 195 static bool wm8804_volatile(struct device *dev, unsigned int reg) 196 { 197 switch (reg) { 198 case WM8804_RST_DEVID1: 199 case WM8804_DEVID2: 200 case WM8804_DEVREV: 201 case WM8804_INTSTAT: 202 case WM8804_SPDSTAT: 203 case WM8804_RXCHAN1: 204 case WM8804_RXCHAN2: 205 case WM8804_RXCHAN3: 206 case WM8804_RXCHAN4: 207 case WM8804_RXCHAN5: 208 return true; 209 default: 210 return false; 211 } 212 } 213 214 static int wm8804_soft_reset(struct wm8804_priv *wm8804) 215 { 216 return regmap_write(wm8804->regmap, WM8804_RST_DEVID1, 0x0); 217 } 218 219 static int wm8804_set_fmt(struct snd_soc_dai *dai, unsigned int fmt) 220 { 221 struct snd_soc_codec *codec; 222 u16 format, master, bcp, lrp; 223 224 codec = dai->codec; 225 226 switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { 227 case SND_SOC_DAIFMT_I2S: 228 format = 0x2; 229 break; 230 case SND_SOC_DAIFMT_RIGHT_J: 231 format = 0x0; 232 break; 233 case SND_SOC_DAIFMT_LEFT_J: 234 format = 0x1; 235 break; 236 case SND_SOC_DAIFMT_DSP_A: 237 case SND_SOC_DAIFMT_DSP_B: 238 format = 0x3; 239 break; 240 default: 241 dev_err(dai->dev, "Unknown dai format\n"); 242 return -EINVAL; 243 } 244 245 /* set data format */ 246 snd_soc_update_bits(codec, WM8804_AIFTX, 0x3, format); 247 snd_soc_update_bits(codec, WM8804_AIFRX, 0x3, format); 248 249 switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { 250 case SND_SOC_DAIFMT_CBM_CFM: 251 master = 1; 252 break; 253 case SND_SOC_DAIFMT_CBS_CFS: 254 master = 0; 255 break; 256 default: 257 dev_err(dai->dev, "Unknown master/slave configuration\n"); 258 return -EINVAL; 259 } 260 261 /* set master/slave mode */ 262 snd_soc_update_bits(codec, WM8804_AIFRX, 0x40, master << 6); 263 264 bcp = lrp = 0; 265 switch (fmt & SND_SOC_DAIFMT_INV_MASK) { 266 case SND_SOC_DAIFMT_NB_NF: 267 break; 268 case SND_SOC_DAIFMT_IB_IF: 269 bcp = lrp = 1; 270 break; 271 case SND_SOC_DAIFMT_IB_NF: 272 bcp = 1; 273 break; 274 case SND_SOC_DAIFMT_NB_IF: 275 lrp = 1; 276 break; 277 default: 278 dev_err(dai->dev, "Unknown polarity configuration\n"); 279 return -EINVAL; 280 } 281 282 /* set frame inversion */ 283 snd_soc_update_bits(codec, WM8804_AIFTX, 0x10 | 0x20, 284 (bcp << 4) | (lrp << 5)); 285 snd_soc_update_bits(codec, WM8804_AIFRX, 0x10 | 0x20, 286 (bcp << 4) | (lrp << 5)); 287 return 0; 288 } 289 290 static int wm8804_hw_params(struct snd_pcm_substream *substream, 291 struct snd_pcm_hw_params *params, 292 struct snd_soc_dai *dai) 293 { 294 struct snd_soc_codec *codec; 295 u16 blen; 296 297 codec = dai->codec; 298 299 switch (params_width(params)) { 300 case 16: 301 blen = 0x0; 302 break; 303 case 20: 304 blen = 0x1; 305 break; 306 case 24: 307 blen = 0x2; 308 break; 309 default: 310 dev_err(dai->dev, "Unsupported word length: %u\n", 311 params_width(params)); 312 return -EINVAL; 313 } 314 315 /* set word length */ 316 snd_soc_update_bits(codec, WM8804_AIFTX, 0xc, blen << 2); 317 snd_soc_update_bits(codec, WM8804_AIFRX, 0xc, blen << 2); 318 319 return 0; 320 } 321 322 struct pll_div { 323 u32 prescale:1; 324 u32 mclkdiv:1; 325 u32 freqmode:2; 326 u32 n:4; 327 u32 k:22; 328 }; 329 330 /* PLL rate to output rate divisions */ 331 static struct { 332 unsigned int div; 333 unsigned int freqmode; 334 unsigned int mclkdiv; 335 } post_table[] = { 336 { 2, 0, 0 }, 337 { 4, 0, 1 }, 338 { 4, 1, 0 }, 339 { 8, 1, 1 }, 340 { 8, 2, 0 }, 341 { 16, 2, 1 }, 342 { 12, 3, 0 }, 343 { 24, 3, 1 } 344 }; 345 346 #define FIXED_PLL_SIZE ((1ULL << 22) * 10) 347 static int pll_factors(struct pll_div *pll_div, unsigned int target, 348 unsigned int source, unsigned int mclk_div) 349 { 350 u64 Kpart; 351 unsigned long int K, Ndiv, Nmod, tmp; 352 int i; 353 354 /* 355 * Scale the output frequency up; the PLL should run in the 356 * region of 90-100MHz. 357 */ 358 for (i = 0; i < ARRAY_SIZE(post_table); i++) { 359 tmp = target * post_table[i].div; 360 if ((tmp >= 90000000 && tmp <= 100000000) && 361 (mclk_div == post_table[i].mclkdiv)) { 362 pll_div->freqmode = post_table[i].freqmode; 363 pll_div->mclkdiv = post_table[i].mclkdiv; 364 target *= post_table[i].div; 365 break; 366 } 367 } 368 369 if (i == ARRAY_SIZE(post_table)) { 370 pr_err("%s: Unable to scale output frequency: %uHz\n", 371 __func__, target); 372 return -EINVAL; 373 } 374 375 pll_div->prescale = 0; 376 Ndiv = target / source; 377 if (Ndiv < 5) { 378 source >>= 1; 379 pll_div->prescale = 1; 380 Ndiv = target / source; 381 } 382 383 if (Ndiv < 5 || Ndiv > 13) { 384 pr_err("%s: WM8804 N value is not within the recommended range: %lu\n", 385 __func__, Ndiv); 386 return -EINVAL; 387 } 388 pll_div->n = Ndiv; 389 390 Nmod = target % source; 391 Kpart = FIXED_PLL_SIZE * (u64)Nmod; 392 393 do_div(Kpart, source); 394 395 K = Kpart & 0xffffffff; 396 if ((K % 10) >= 5) 397 K += 5; 398 K /= 10; 399 pll_div->k = K; 400 401 return 0; 402 } 403 404 static int wm8804_set_pll(struct snd_soc_dai *dai, int pll_id, 405 int source, unsigned int freq_in, 406 unsigned int freq_out) 407 { 408 struct snd_soc_codec *codec = dai->codec; 409 struct wm8804_priv *wm8804 = snd_soc_codec_get_drvdata(codec); 410 bool change; 411 412 if (!freq_in || !freq_out) { 413 /* disable the PLL */ 414 regmap_update_bits_check(wm8804->regmap, WM8804_PWRDN, 415 0x1, 0x1, &change); 416 if (change) 417 pm_runtime_put(wm8804->dev); 418 } else { 419 int ret; 420 struct pll_div pll_div; 421 422 ret = pll_factors(&pll_div, freq_out, freq_in, 423 wm8804->mclk_div); 424 if (ret) 425 return ret; 426 427 /* power down the PLL before reprogramming it */ 428 regmap_update_bits_check(wm8804->regmap, WM8804_PWRDN, 429 0x1, 0x1, &change); 430 if (!change) 431 pm_runtime_get_sync(wm8804->dev); 432 433 /* set PLLN and PRESCALE */ 434 snd_soc_update_bits(codec, WM8804_PLL4, 0xf | 0x10, 435 pll_div.n | (pll_div.prescale << 4)); 436 /* set mclkdiv and freqmode */ 437 snd_soc_update_bits(codec, WM8804_PLL5, 0x3 | 0x8, 438 pll_div.freqmode | (pll_div.mclkdiv << 3)); 439 /* set PLLK */ 440 snd_soc_write(codec, WM8804_PLL1, pll_div.k & 0xff); 441 snd_soc_write(codec, WM8804_PLL2, (pll_div.k >> 8) & 0xff); 442 snd_soc_write(codec, WM8804_PLL3, pll_div.k >> 16); 443 444 /* power up the PLL */ 445 snd_soc_update_bits(codec, WM8804_PWRDN, 0x1, 0); 446 } 447 448 return 0; 449 } 450 451 static int wm8804_set_sysclk(struct snd_soc_dai *dai, 452 int clk_id, unsigned int freq, int dir) 453 { 454 struct snd_soc_codec *codec; 455 456 codec = dai->codec; 457 458 switch (clk_id) { 459 case WM8804_TX_CLKSRC_MCLK: 460 if ((freq >= 10000000 && freq <= 14400000) 461 || (freq >= 16280000 && freq <= 27000000)) 462 snd_soc_update_bits(codec, WM8804_PLL6, 0x80, 0x80); 463 else { 464 dev_err(dai->dev, "OSCCLOCK is not within the " 465 "recommended range: %uHz\n", freq); 466 return -EINVAL; 467 } 468 break; 469 case WM8804_TX_CLKSRC_PLL: 470 snd_soc_update_bits(codec, WM8804_PLL6, 0x80, 0); 471 break; 472 case WM8804_CLKOUT_SRC_CLK1: 473 snd_soc_update_bits(codec, WM8804_PLL6, 0x8, 0); 474 break; 475 case WM8804_CLKOUT_SRC_OSCCLK: 476 snd_soc_update_bits(codec, WM8804_PLL6, 0x8, 0x8); 477 break; 478 default: 479 dev_err(dai->dev, "Unknown clock source: %d\n", clk_id); 480 return -EINVAL; 481 } 482 483 return 0; 484 } 485 486 static int wm8804_set_clkdiv(struct snd_soc_dai *dai, 487 int div_id, int div) 488 { 489 struct snd_soc_codec *codec; 490 struct wm8804_priv *wm8804; 491 492 codec = dai->codec; 493 switch (div_id) { 494 case WM8804_CLKOUT_DIV: 495 snd_soc_update_bits(codec, WM8804_PLL5, 0x30, 496 (div & 0x3) << 4); 497 break; 498 case WM8804_MCLK_DIV: 499 wm8804 = snd_soc_codec_get_drvdata(codec); 500 wm8804->mclk_div = div; 501 break; 502 default: 503 dev_err(dai->dev, "Unknown clock divider: %d\n", div_id); 504 return -EINVAL; 505 } 506 return 0; 507 } 508 509 static const struct snd_soc_dai_ops wm8804_dai_ops = { 510 .hw_params = wm8804_hw_params, 511 .set_fmt = wm8804_set_fmt, 512 .set_sysclk = wm8804_set_sysclk, 513 .set_clkdiv = wm8804_set_clkdiv, 514 .set_pll = wm8804_set_pll 515 }; 516 517 #define WM8804_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE | \ 518 SNDRV_PCM_FMTBIT_S24_LE) 519 520 #define WM8804_RATES (SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_44100 | \ 521 SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_64000 | \ 522 SNDRV_PCM_RATE_88200 | SNDRV_PCM_RATE_96000 | \ 523 SNDRV_PCM_RATE_176400 | SNDRV_PCM_RATE_192000) 524 525 static struct snd_soc_dai_driver wm8804_dai = { 526 .name = "wm8804-spdif", 527 .playback = { 528 .stream_name = "Playback", 529 .channels_min = 2, 530 .channels_max = 2, 531 .rates = WM8804_RATES, 532 .formats = WM8804_FORMATS, 533 }, 534 .capture = { 535 .stream_name = "Capture", 536 .channels_min = 2, 537 .channels_max = 2, 538 .rates = WM8804_RATES, 539 .formats = WM8804_FORMATS, 540 }, 541 .ops = &wm8804_dai_ops, 542 .symmetric_rates = 1 543 }; 544 545 static const struct snd_soc_codec_driver soc_codec_dev_wm8804 = { 546 .idle_bias_off = true, 547 548 .dapm_widgets = wm8804_dapm_widgets, 549 .num_dapm_widgets = ARRAY_SIZE(wm8804_dapm_widgets), 550 .dapm_routes = wm8804_dapm_routes, 551 .num_dapm_routes = ARRAY_SIZE(wm8804_dapm_routes), 552 }; 553 554 const struct regmap_config wm8804_regmap_config = { 555 .reg_bits = 8, 556 .val_bits = 8, 557 558 .max_register = WM8804_MAX_REGISTER, 559 .volatile_reg = wm8804_volatile, 560 561 .cache_type = REGCACHE_RBTREE, 562 .reg_defaults = wm8804_reg_defaults, 563 .num_reg_defaults = ARRAY_SIZE(wm8804_reg_defaults), 564 }; 565 EXPORT_SYMBOL_GPL(wm8804_regmap_config); 566 567 int wm8804_probe(struct device *dev, struct regmap *regmap) 568 { 569 struct wm8804_priv *wm8804; 570 unsigned int id1, id2; 571 int i, ret; 572 573 wm8804 = devm_kzalloc(dev, sizeof(*wm8804), GFP_KERNEL); 574 if (!wm8804) 575 return -ENOMEM; 576 577 dev_set_drvdata(dev, wm8804); 578 579 wm8804->dev = dev; 580 wm8804->regmap = regmap; 581 582 wm8804->reset = devm_gpiod_get_optional(dev, "wlf,reset", 583 GPIOD_OUT_LOW); 584 if (IS_ERR(wm8804->reset)) { 585 ret = PTR_ERR(wm8804->reset); 586 dev_err(dev, "Failed to get reset line: %d\n", ret); 587 return ret; 588 } 589 590 for (i = 0; i < ARRAY_SIZE(wm8804->supplies); i++) 591 wm8804->supplies[i].supply = wm8804_supply_names[i]; 592 593 ret = devm_regulator_bulk_get(dev, ARRAY_SIZE(wm8804->supplies), 594 wm8804->supplies); 595 if (ret) { 596 dev_err(dev, "Failed to request supplies: %d\n", ret); 597 return ret; 598 } 599 600 wm8804->disable_nb[0].notifier_call = wm8804_regulator_event_0; 601 wm8804->disable_nb[1].notifier_call = wm8804_regulator_event_1; 602 603 /* This should really be moved into the regulator core */ 604 for (i = 0; i < ARRAY_SIZE(wm8804->supplies); i++) { 605 struct regulator *regulator = wm8804->supplies[i].consumer; 606 607 ret = devm_regulator_register_notifier(regulator, 608 &wm8804->disable_nb[i]); 609 if (ret != 0) { 610 dev_err(dev, 611 "Failed to register regulator notifier: %d\n", 612 ret); 613 return ret; 614 } 615 } 616 617 ret = regulator_bulk_enable(ARRAY_SIZE(wm8804->supplies), 618 wm8804->supplies); 619 if (ret) { 620 dev_err(dev, "Failed to enable supplies: %d\n", ret); 621 return ret; 622 } 623 624 if (wm8804->reset) 625 gpiod_set_value_cansleep(wm8804->reset, 1); 626 627 ret = regmap_read(regmap, WM8804_RST_DEVID1, &id1); 628 if (ret < 0) { 629 dev_err(dev, "Failed to read device ID: %d\n", ret); 630 goto err_reg_enable; 631 } 632 633 ret = regmap_read(regmap, WM8804_DEVID2, &id2); 634 if (ret < 0) { 635 dev_err(dev, "Failed to read device ID: %d\n", ret); 636 goto err_reg_enable; 637 } 638 639 id2 = (id2 << 8) | id1; 640 641 if (id2 != 0x8805) { 642 dev_err(dev, "Invalid device ID: %#x\n", id2); 643 ret = -EINVAL; 644 goto err_reg_enable; 645 } 646 647 ret = regmap_read(regmap, WM8804_DEVREV, &id1); 648 if (ret < 0) { 649 dev_err(dev, "Failed to read device revision: %d\n", 650 ret); 651 goto err_reg_enable; 652 } 653 dev_info(dev, "revision %c\n", id1 + 'A'); 654 655 if (!wm8804->reset) { 656 ret = wm8804_soft_reset(wm8804); 657 if (ret < 0) { 658 dev_err(dev, "Failed to issue reset: %d\n", ret); 659 goto err_reg_enable; 660 } 661 } 662 663 ret = snd_soc_register_codec(dev, &soc_codec_dev_wm8804, 664 &wm8804_dai, 1); 665 if (ret < 0) { 666 dev_err(dev, "Failed to register CODEC: %d\n", ret); 667 goto err_reg_enable; 668 } 669 670 pm_runtime_set_active(dev); 671 pm_runtime_enable(dev); 672 pm_runtime_idle(dev); 673 674 return 0; 675 676 err_reg_enable: 677 regulator_bulk_disable(ARRAY_SIZE(wm8804->supplies), wm8804->supplies); 678 return ret; 679 } 680 EXPORT_SYMBOL_GPL(wm8804_probe); 681 682 void wm8804_remove(struct device *dev) 683 { 684 pm_runtime_disable(dev); 685 snd_soc_unregister_codec(dev); 686 } 687 EXPORT_SYMBOL_GPL(wm8804_remove); 688 689 #if IS_ENABLED(CONFIG_PM) 690 static int wm8804_runtime_resume(struct device *dev) 691 { 692 struct wm8804_priv *wm8804 = dev_get_drvdata(dev); 693 int ret; 694 695 ret = regulator_bulk_enable(ARRAY_SIZE(wm8804->supplies), 696 wm8804->supplies); 697 if (ret) { 698 dev_err(wm8804->dev, "Failed to enable supplies: %d\n", ret); 699 return ret; 700 } 701 702 regcache_sync(wm8804->regmap); 703 704 /* Power up OSCCLK */ 705 regmap_update_bits(wm8804->regmap, WM8804_PWRDN, 0x8, 0x0); 706 707 return 0; 708 } 709 710 static int wm8804_runtime_suspend(struct device *dev) 711 { 712 struct wm8804_priv *wm8804 = dev_get_drvdata(dev); 713 714 /* Power down OSCCLK */ 715 regmap_update_bits(wm8804->regmap, WM8804_PWRDN, 0x8, 0x8); 716 717 regulator_bulk_disable(ARRAY_SIZE(wm8804->supplies), 718 wm8804->supplies); 719 720 return 0; 721 } 722 #endif 723 724 const struct dev_pm_ops wm8804_pm = { 725 SET_RUNTIME_PM_OPS(wm8804_runtime_suspend, wm8804_runtime_resume, NULL) 726 }; 727 EXPORT_SYMBOL_GPL(wm8804_pm); 728 729 MODULE_DESCRIPTION("ASoC WM8804 driver"); 730 MODULE_AUTHOR("Dimitris Papastamos <dp@opensource.wolfsonmicro.com>"); 731 MODULE_LICENSE("GPL"); 732