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; |