diff options
| -rw-r--r-- | sound/soc/codecs/wm8731.c | 51 |
1 files changed, 28 insertions, 23 deletions
diff --git a/sound/soc/codecs/wm8731.c b/sound/soc/codecs/wm8731.c index c4b63538bb77..2650fac30ee4 100644 --- a/sound/soc/codecs/wm8731.c +++ b/sound/soc/codecs/wm8731.c | |||
| @@ -368,6 +368,10 @@ static int wm8731_set_dai_fmt(struct snd_soc_dai *codec_dai, | |||
| 368 | static int wm8731_set_bias_level(struct snd_soc_codec *codec, | 368 | static int wm8731_set_bias_level(struct snd_soc_codec *codec, |
| 369 | enum snd_soc_bias_level level) | 369 | enum snd_soc_bias_level level) |
| 370 | { | 370 | { |
| 371 | struct wm8731_priv *wm8731 = snd_soc_codec_get_drvdata(codec); | ||
| 372 | int i, ret; | ||
| 373 | u8 data[2]; | ||
| 374 | u16 *cache = codec->reg_cache; | ||
| 371 | u16 reg; | 375 | u16 reg; |
| 372 | 376 | ||
| 373 | switch (level) { | 377 | switch (level) { |
| @@ -376,6 +380,24 @@ static int wm8731_set_bias_level(struct snd_soc_codec *codec, | |||
| 376 | case SND_SOC_BIAS_PREPARE: | 380 | case SND_SOC_BIAS_PREPARE: |
| 377 | break; | 381 | break; |
| 378 | case SND_SOC_BIAS_STANDBY: | 382 | case SND_SOC_BIAS_STANDBY: |
| 383 | if (codec->bias_level == SND_SOC_BIAS_OFF) { | ||
| 384 | ret = regulator_bulk_enable(ARRAY_SIZE(wm8731->supplies), | ||
| 385 | wm8731->supplies); | ||
| 386 | if (ret != 0) | ||
| 387 | return ret; | ||
| 388 | |||
| 389 | /* Sync reg_cache with the hardware */ | ||
| 390 | for (i = 0; i < ARRAY_SIZE(wm8731_reg); i++) { | ||
| 391 | if (cache[i] == wm8731_reg[i]) | ||
| 392 | continue; | ||
| 393 | |||
| 394 | data[0] = (i << 1) | ((cache[i] >> 8) | ||
| 395 | & 0x0001); | ||
| 396 | data[1] = cache[i] & 0x00ff; | ||
| 397 | codec->hw_write(codec->control_data, data, 2); | ||
| 398 | } | ||
| 399 | } | ||
| 400 | |||
| 379 | /* Clear PWROFF, gate CLKOUT, everything else as-is */ | 401 | /* Clear PWROFF, gate CLKOUT, everything else as-is */ |
| 380 | reg = snd_soc_read(codec, WM8731_PWR) & 0xff7f; | 402 | reg = snd_soc_read(codec, WM8731_PWR) & 0xff7f; |
| 381 | snd_soc_write(codec, WM8731_PWR, reg | 0x0040); | 403 | snd_soc_write(codec, WM8731_PWR, reg | 0x0040); |
| @@ -383,6 +405,8 @@ static int wm8731_set_bias_level(struct snd_soc_codec *codec, | |||
| 383 | case SND_SOC_BIAS_OFF: | 405 | case SND_SOC_BIAS_OFF: |
| 384 | snd_soc_write(codec, WM8731_ACTIVE, 0x0); | 406 | snd_soc_write(codec, WM8731_ACTIVE, 0x0); |
| 385 | snd_soc_write(codec, WM8731_PWR, 0xffff); | 407 | snd_soc_write(codec, WM8731_PWR, 0xffff); |
| 408 | regulator_bulk_disable(ARRAY_SIZE(wm8731->supplies), | ||
| 409 | wm8731->supplies); | ||
| 386 | break; | 410 | break; |
| 387 | } | 411 | } |
| 388 | codec->bias_level = level; | 412 | codec->bias_level = level; |
| @@ -427,12 +451,9 @@ static int wm8731_suspend(struct platform_device *pdev, pm_message_t state) | |||
| 427 | { | 451 | { |
| 428 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | 452 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); |
| 429 | struct snd_soc_codec *codec = socdev->card->codec; | 453 | struct snd_soc_codec *codec = socdev->card->codec; |
| 430 | struct wm8731_priv *wm8731 = snd_soc_codec_get_drvdata(codec); | ||
| 431 | 454 | ||
| 432 | snd_soc_write(codec, WM8731_ACTIVE, 0x0); | ||
| 433 | wm8731_set_bias_level(codec, SND_SOC_BIAS_OFF); | 455 | wm8731_set_bias_level(codec, SND_SOC_BIAS_OFF); |
| 434 | regulator_bulk_disable(ARRAY_SIZE(wm8731->supplies), | 456 | |
| 435 | wm8731->supplies); | ||
| 436 | return 0; | 457 | return 0; |
| 437 | } | 458 | } |
| 438 | 459 | ||
| @@ -440,25 +461,7 @@ static int wm8731_resume(struct platform_device *pdev) | |||
| 440 | { | 461 | { |
| 441 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | 462 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); |
| 442 | struct snd_soc_codec *codec = socdev->card->codec; | 463 | struct snd_soc_codec *codec = socdev->card->codec; |
| 443 | struct wm8731_priv *wm8731 = snd_soc_codec_get_drvdata(codec); | ||
| 444 | int i, ret; | ||
| 445 | u8 data[2]; | ||
| 446 | u16 *cache = codec->reg_cache; | ||
| 447 | |||
| 448 | ret = regulator_bulk_enable(ARRAY_SIZE(wm8731->supplies), | ||
| 449 | wm8731->supplies); | ||
| 450 | if (ret != 0) | ||
| 451 | return ret; | ||
| 452 | |||
| 453 | /* Sync reg_cache with the hardware */ | ||
| 454 | for (i = 0; i < ARRAY_SIZE(wm8731_reg); i++) { | ||
| 455 | if (cache[i] == wm8731_reg[i]) | ||
| 456 | continue; | ||
| 457 | 464 | ||
| 458 | data[0] = (i << 1) | ((cache[i] >> 8) & 0x0001); | ||
| 459 | data[1] = cache[i] & 0x00ff; | ||
| 460 | codec->hw_write(codec->control_data, data, 2); | ||
| 461 | } | ||
| 462 | wm8731_set_bias_level(codec, SND_SOC_BIAS_STANDBY); | 465 | wm8731_set_bias_level(codec, SND_SOC_BIAS_STANDBY); |
| 463 | 466 | ||
| 464 | return 0; | 467 | return 0; |
| @@ -603,6 +606,9 @@ static int wm8731_register(struct wm8731_priv *wm8731, | |||
| 603 | goto err_codec; | 606 | goto err_codec; |
| 604 | } | 607 | } |
| 605 | 608 | ||
| 609 | /* Regulators will have been enabled by bias management */ | ||
| 610 | regulator_bulk_disable(ARRAY_SIZE(wm8731->supplies), wm8731->supplies); | ||
| 611 | |||
| 606 | return 0; | 612 | return 0; |
| 607 | 613 | ||
| 608 | err_codec: | 614 | err_codec: |
| @@ -621,7 +627,6 @@ static void wm8731_unregister(struct wm8731_priv *wm8731) | |||
| 621 | wm8731_set_bias_level(&wm8731->codec, SND_SOC_BIAS_OFF); | 627 | wm8731_set_bias_level(&wm8731->codec, SND_SOC_BIAS_OFF); |
| 622 | snd_soc_unregister_dai(&wm8731_dai); | 628 | snd_soc_unregister_dai(&wm8731_dai); |
| 623 | snd_soc_unregister_codec(&wm8731->codec); | 629 | snd_soc_unregister_codec(&wm8731->codec); |
| 624 | regulator_bulk_disable(ARRAY_SIZE(wm8731->supplies), wm8731->supplies); | ||
| 625 | regulator_bulk_free(ARRAY_SIZE(wm8731->supplies), wm8731->supplies); | 630 | regulator_bulk_free(ARRAY_SIZE(wm8731->supplies), wm8731->supplies); |
| 626 | kfree(wm8731); | 631 | kfree(wm8731); |
| 627 | wm8731_codec = NULL; | 632 | wm8731_codec = NULL; |
