aboutsummaryrefslogtreecommitdiffstats
path: root/sound/soc/codecs/wm8731.c
diff options
context:
space:
mode:
authorMark Brown <broonie@opensource.wolfsonmicro.com>2010-05-07 14:14:45 -0400
committerMark Brown <broonie@opensource.wolfsonmicro.com>2010-05-10 06:04:22 -0400
commit06ae99888e599ea2e82386d618405c473c379185 (patch)
tree1ba1ec7f3147b845284b8e7ff61f97ee51e6a3da /sound/soc/codecs/wm8731.c
parent3efab7dcc0f4d0087f73ff975eaa2fddc02ffc69 (diff)
ASoC: Refactor WM8731 regulator management into bias management
This allows more flexible integration with subsystem features. Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com> Acked-by: Liam Girdwood <lrg@slimlogic.co.uk>
Diffstat (limited to 'sound/soc/codecs/wm8731.c')
-rw-r--r--sound/soc/codecs/wm8731.c51
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,
368static int wm8731_set_bias_level(struct snd_soc_codec *codec, 368static 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
608err_codec: 614err_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;