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