aboutsummaryrefslogtreecommitdiffstats
path: root/sound/soc/codecs/wm8940.c
diff options
context:
space:
mode:
Diffstat (limited to 'sound/soc/codecs/wm8940.c')
-rw-r--r--sound/soc/codecs/wm8940.c53
1 files changed, 25 insertions, 28 deletions
diff --git a/sound/soc/codecs/wm8940.c b/sound/soc/codecs/wm8940.c
index 056daa0010f..de9ec9b8b7d 100644
--- a/sound/soc/codecs/wm8940.c
+++ b/sound/soc/codecs/wm8940.c
@@ -43,9 +43,19 @@
43struct wm8940_priv { 43struct wm8940_priv {
44 unsigned int sysclk; 44 unsigned int sysclk;
45 enum snd_soc_control_type control_type; 45 enum snd_soc_control_type control_type;
46 void *control_data;
47}; 46};
48 47
48static int wm8940_volatile_register(struct snd_soc_codec *codec,
49 unsigned int reg)
50{
51 switch (reg) {
52 case WM8940_SOFTRESET:
53 return 1;
54 default:
55 return 0;
56 }
57}
58
49static u16 wm8940_reg_defaults[] = { 59static u16 wm8940_reg_defaults[] = {
50 0x8940, /* Soft Reset */ 60 0x8940, /* Soft Reset */
51 0x0000, /* Power 1 */ 61 0x0000, /* Power 1 */
@@ -460,6 +470,14 @@ static int wm8940_set_bias_level(struct snd_soc_codec *codec,
460 ret = snd_soc_write(codec, WM8940_POWER1, pwr_reg | 0x1); 470 ret = snd_soc_write(codec, WM8940_POWER1, pwr_reg | 0x1);
461 break; 471 break;
462 case SND_SOC_BIAS_STANDBY: 472 case SND_SOC_BIAS_STANDBY:
473 if (codec->dapm.bias_level == SND_SOC_BIAS_OFF) {
474 ret = snd_soc_cache_sync(codec);
475 if (ret < 0) {
476 dev_err(codec->dev, "Failed to sync cache: %d\n", ret);
477 return ret;
478 }
479 }
480
463 /* ensure bufioen and biasen */ 481 /* ensure bufioen and biasen */
464 pwr_reg |= (1 << 2) | (1 << 3); 482 pwr_reg |= (1 << 2) | (1 << 3);
465 /* set vmid to 300k for standby */ 483 /* set vmid to 300k for standby */
@@ -470,6 +488,8 @@ static int wm8940_set_bias_level(struct snd_soc_codec *codec,
470 break; 488 break;
471 } 489 }
472 490
491 codec->dapm.bias_level = level;
492
473 return ret; 493 return ret;
474} 494}
475 495
@@ -601,7 +621,7 @@ static int wm8940_set_dai_clkdiv(struct snd_soc_dai *codec_dai,
601 621
602 switch (div_id) { 622 switch (div_id) {
603 case WM8940_BCLKDIV: 623 case WM8940_BCLKDIV:
604 reg = snd_soc_read(codec, WM8940_CLOCK) & 0xFFEF3; 624 reg = snd_soc_read(codec, WM8940_CLOCK) & 0xFFE3;
605 ret = snd_soc_write(codec, WM8940_CLOCK, reg | (div << 2)); 625 ret = snd_soc_write(codec, WM8940_CLOCK, reg | (div << 2));
606 break; 626 break;
607 case WM8940_MCLKDIV: 627 case WM8940_MCLKDIV:
@@ -660,30 +680,8 @@ static int wm8940_suspend(struct snd_soc_codec *codec, pm_message_t state)
660 680
661static int wm8940_resume(struct snd_soc_codec *codec) 681static int wm8940_resume(struct snd_soc_codec *codec)
662{ 682{
663 int i; 683 wm8940_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
664 int ret; 684 return 0;
665 u8 data[3];
666 u16 *cache = codec->reg_cache;
667
668 /* Sync reg_cache with the hardware
669 * Could use auto incremented writes to speed this up
670 */
671 for (i = 0; i < ARRAY_SIZE(wm8940_reg_defaults); i++) {
672 data[0] = i;
673 data[1] = (cache[i] & 0xFF00) >> 8;
674 data[2] = cache[i] & 0x00FF;
675 ret = codec->hw_write(codec->control_data, data, 3);
676 if (ret < 0)
677 goto error_ret;
678 else if (ret != 3) {
679 ret = -EIO;
680 goto error_ret;
681 }
682 }
683 ret = wm8940_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
684
685error_ret:
686 return ret;
687} 685}
688 686
689static int wm8940_probe(struct snd_soc_codec *codec) 687static int wm8940_probe(struct snd_soc_codec *codec)
@@ -693,7 +691,6 @@ static int wm8940_probe(struct snd_soc_codec *codec)
693 int ret; 691 int ret;
694 u16 reg; 692 u16 reg;
695 693
696 codec->control_data = wm8940->control_data;
697 ret = snd_soc_codec_set_cache_io(codec, 8, 16, wm8940->control_type); 694 ret = snd_soc_codec_set_cache_io(codec, 8, 16, wm8940->control_type);
698 if (ret < 0) { 695 if (ret < 0) {
699 dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret); 696 dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret);
@@ -744,6 +741,7 @@ static struct snd_soc_codec_driver soc_codec_dev_wm8940 = {
744 .reg_cache_size = ARRAY_SIZE(wm8940_reg_defaults), 741 .reg_cache_size = ARRAY_SIZE(wm8940_reg_defaults),
745 .reg_word_size = sizeof(u16), 742 .reg_word_size = sizeof(u16),
746 .reg_cache_default = wm8940_reg_defaults, 743 .reg_cache_default = wm8940_reg_defaults,
744 .volatile_register = wm8940_volatile_register,
747}; 745};
748 746
749#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) 747#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
@@ -758,7 +756,6 @@ static __devinit int wm8940_i2c_probe(struct i2c_client *i2c,
758 return -ENOMEM; 756 return -ENOMEM;
759 757
760 i2c_set_clientdata(i2c, wm8940); 758 i2c_set_clientdata(i2c, wm8940);
761 wm8940->control_data = i2c;
762 wm8940->control_type = SND_SOC_I2C; 759 wm8940->control_type = SND_SOC_I2C;
763 760
764 ret = snd_soc_register_codec(&i2c->dev, 761 ret = snd_soc_register_codec(&i2c->dev,