aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--sound/soc/codecs/Kconfig1
-rw-r--r--sound/soc/codecs/wm9712.c143
2 files changed, 79 insertions, 65 deletions
diff --git a/sound/soc/codecs/Kconfig b/sound/soc/codecs/Kconfig
index c67667bb970f..f472254a575d 100644
--- a/sound/soc/codecs/Kconfig
+++ b/sound/soc/codecs/Kconfig
@@ -1057,6 +1057,7 @@ config SND_SOC_WM9705
1057 1057
1058config SND_SOC_WM9712 1058config SND_SOC_WM9712
1059 tristate 1059 tristate
1060 select REGMAP_AC97
1060 1061
1061config SND_SOC_WM9713 1062config SND_SOC_WM9713
1062 tristate 1063 tristate
diff --git a/sound/soc/codecs/wm9712.c b/sound/soc/codecs/wm9712.c
index 557709eac698..d2d0d2bb4412 100644
--- a/sound/soc/codecs/wm9712.c
+++ b/sound/soc/codecs/wm9712.c
@@ -15,6 +15,7 @@
15#include <linux/module.h> 15#include <linux/module.h>
16#include <linux/kernel.h> 16#include <linux/kernel.h>
17#include <linux/device.h> 17#include <linux/device.h>
18#include <linux/regmap.h>
18#include <sound/core.h> 19#include <sound/core.h>
19#include <sound/pcm.h> 20#include <sound/pcm.h>
20#include <sound/ac97_codec.h> 21#include <sound/ac97_codec.h>
@@ -32,31 +33,66 @@ struct wm9712_priv {
32 struct mutex lock; 33 struct mutex lock;
33}; 34};
34 35
35static unsigned int ac97_read(struct snd_soc_codec *codec, 36static const struct reg_default wm9712_reg_defaults[] = {
36 unsigned int reg); 37 { 0x02, 0x8000 },
37static int ac97_write(struct snd_soc_codec *codec, 38 { 0x04, 0x8000 },
38 unsigned int reg, unsigned int val); 39 { 0x06, 0x8000 },
40 { 0x08, 0x0f0f },
41 { 0x0a, 0xaaa0 },
42 { 0x0c, 0xc008 },
43 { 0x0e, 0x6808 },
44 { 0x10, 0xe808 },
45 { 0x12, 0xaaa0 },
46 { 0x14, 0xad00 },
47 { 0x16, 0x8000 },
48 { 0x18, 0xe808 },
49 { 0x1a, 0x3000 },
50 { 0x1c, 0x8000 },
51 { 0x20, 0x0000 },
52 { 0x22, 0x0000 },
53 { 0x26, 0x000f },
54 { 0x28, 0x0605 },
55 { 0x2a, 0x0410 },
56 { 0x2c, 0xbb80 },
57 { 0x2e, 0xbb80 },
58 { 0x32, 0xbb80 },
59 { 0x34, 0x2000 },
60 { 0x4c, 0xf83e },
61 { 0x4e, 0xffff },
62 { 0x50, 0x0000 },
63 { 0x52, 0x0000 },
64 { 0x56, 0xf83e },
65 { 0x58, 0x0008 },
66 { 0x5c, 0x0000 },
67 { 0x60, 0xb032 },
68 { 0x62, 0x3e00 },
69 { 0x64, 0x0000 },
70 { 0x76, 0x0006 },
71 { 0x78, 0x0001 },
72 { 0x7a, 0x0000 },
73};
39 74
40/* 75static bool wm9712_volatile_reg(struct device *dev, unsigned int reg)
41 * WM9712 register cache 76{
42 */ 77 switch (reg) {
43static const u16 wm9712_reg[] = { 78 case AC97_REC_GAIN:
44 0x6174, 0x8000, 0x8000, 0x8000, /* 6 */ 79 return true;
45 0x0f0f, 0xaaa0, 0xc008, 0x6808, /* e */ 80 default:
46 0xe808, 0xaaa0, 0xad00, 0x8000, /* 16 */ 81 return regmap_ac97_default_volatile(dev, reg);
47 0xe808, 0x3000, 0x8000, 0x0000, /* 1e */ 82 }
48 0x0000, 0x0000, 0x0000, 0x000f, /* 26 */ 83}
49 0x0405, 0x0410, 0xbb80, 0xbb80, /* 2e */ 84
50 0x0000, 0xbb80, 0x0000, 0x0000, /* 36 */ 85static const struct regmap_config wm9712_regmap_config = {
51 0x0000, 0x2000, 0x0000, 0x0000, /* 3e */ 86 .reg_bits = 16,
52 0x0000, 0x0000, 0x0000, 0x0000, /* 46 */ 87 .reg_stride = 2,
53 0x0000, 0x0000, 0xf83e, 0xffff, /* 4e */ 88 .val_bits = 16,
54 0x0000, 0x0000, 0x0000, 0xf83e, /* 56 */ 89 .max_register = 0x7e,
55 0x0008, 0x0000, 0x0000, 0x0000, /* 5e */ 90 .cache_type = REGCACHE_RBTREE,
56 0xb032, 0x3e00, 0x0000, 0x0000, /* 66 */ 91
57 0x0000, 0x0000, 0x0000, 0x0000, /* 6e */ 92 .volatile_reg = wm9712_volatile_reg,
58 0x0000, 0x0000, 0x0000, 0x0006, /* 76 */ 93
59 0x0001, 0x0000, 0x574d, 0x4c12, /* 7e */ 94 .reg_defaults = wm9712_reg_defaults,
95 .num_reg_defaults = ARRAY_SIZE(wm9712_reg_defaults),
60}; 96};
61 97
62#define HPL_MIXER 0x0 98#define HPL_MIXER 0x0
@@ -488,35 +524,13 @@ static const struct snd_soc_dapm_route wm9712_audio_map[] = {
488static unsigned int ac97_read(struct snd_soc_codec *codec, 524static unsigned int ac97_read(struct snd_soc_codec *codec,
489 unsigned int reg) 525 unsigned int reg)
490{ 526{
491 struct wm9712_priv *wm9712 = snd_soc_codec_get_drvdata(codec); 527 return snd_soc_read(codec, reg);
492 u16 *cache = codec->reg_cache;
493
494 if (reg == AC97_RESET || reg == AC97_GPIO_STATUS ||
495 reg == AC97_VENDOR_ID1 || reg == AC97_VENDOR_ID2 ||
496 reg == AC97_REC_GAIN)
497 return soc_ac97_ops->read(wm9712->ac97, reg);
498 else {
499 reg = reg >> 1;
500
501 if (reg >= (ARRAY_SIZE(wm9712_reg)))
502 return -EIO;
503
504 return cache[reg];
505 }
506} 528}
507 529
508static int ac97_write(struct snd_soc_codec *codec, unsigned int reg, 530static int ac97_write(struct snd_soc_codec *codec, unsigned int reg,
509 unsigned int val) 531 unsigned int val)
510{ 532{
511 struct wm9712_priv *wm9712 = snd_soc_codec_get_drvdata(codec); 533 return snd_soc_write(codec, reg, val);
512 u16 *cache = codec->reg_cache;
513
514 soc_ac97_ops->write(wm9712->ac97, reg, val);
515 reg = reg >> 1;
516 if (reg < (ARRAY_SIZE(wm9712_reg)))
517 cache[reg] = val;
518
519 return 0;
520} 534}
521 535
522static int ac97_prepare(struct snd_pcm_substream *substream, 536static int ac97_prepare(struct snd_pcm_substream *substream,
@@ -619,8 +633,7 @@ static int wm9712_set_bias_level(struct snd_soc_codec *codec,
619static int wm9712_soc_resume(struct snd_soc_codec *codec) 633static int wm9712_soc_resume(struct snd_soc_codec *codec)
620{ 634{
621 struct wm9712_priv *wm9712 = snd_soc_codec_get_drvdata(codec); 635 struct wm9712_priv *wm9712 = snd_soc_codec_get_drvdata(codec);
622 int i, ret; 636 int ret;
623 u16 *cache = codec->reg_cache;
624 637
625 ret = snd_ac97_reset(wm9712->ac97, true, WM9712_VENDOR_ID, 638 ret = snd_ac97_reset(wm9712->ac97, true, WM9712_VENDOR_ID,
626 WM9712_VENDOR_ID_MASK); 639 WM9712_VENDOR_ID_MASK);
@@ -629,15 +642,8 @@ static int wm9712_soc_resume(struct snd_soc_codec *codec)
629 642
630 snd_soc_codec_force_bias_level(codec, SND_SOC_BIAS_STANDBY); 643 snd_soc_codec_force_bias_level(codec, SND_SOC_BIAS_STANDBY);
631 644
632 if (ret == 0) { 645 if (ret == 0)
633 /* Sync reg_cache with the hardware after cold reset */ 646 regcache_sync(codec->component.regmap);
634 for (i = 2; i < ARRAY_SIZE(wm9712_reg) << 1; i += 2) {
635 if (i == AC97_INT_PAGING || i == AC97_POWERDOWN ||
636 (i > 0x58 && i != 0x5c))
637 continue;
638 soc_ac97_ops->write(wm9712->ac97, i, cache[i>>1]);
639 }
640 }
641 647
642 return ret; 648 return ret;
643} 649}
@@ -645,6 +651,7 @@ static int wm9712_soc_resume(struct snd_soc_codec *codec)
645static int wm9712_soc_probe(struct snd_soc_codec *codec) 651static int wm9712_soc_probe(struct snd_soc_codec *codec)
646{ 652{
647 struct wm9712_priv *wm9712 = snd_soc_codec_get_drvdata(codec); 653 struct wm9712_priv *wm9712 = snd_soc_codec_get_drvdata(codec);
654 struct regmap *regmap;
648 int ret; 655 int ret;
649 656
650 wm9712->ac97 = snd_soc_new_ac97_codec(codec, WM9712_VENDOR_ID, 657 wm9712->ac97 = snd_soc_new_ac97_codec(codec, WM9712_VENDOR_ID,
@@ -655,16 +662,28 @@ static int wm9712_soc_probe(struct snd_soc_codec *codec)
655 return ret; 662 return ret;
656 } 663 }
657 664
665 regmap = regmap_init_ac97(wm9712->ac97, &wm9712_regmap_config);
666 if (IS_ERR(regmap)) {
667 ret = PTR_ERR(regmap);
668 goto err_free_ac97_codec;
669 }
670
671 snd_soc_codec_init_regmap(codec, regmap);
672
658 /* set alc mux to none */ 673 /* set alc mux to none */
659 ac97_write(codec, AC97_VIDEO, ac97_read(codec, AC97_VIDEO) | 0x3000); 674 ac97_write(codec, AC97_VIDEO, ac97_read(codec, AC97_VIDEO) | 0x3000);
660 675
661 return 0; 676 return 0;
677err_free_ac97_codec:
678 snd_soc_free_ac97_codec(wm9712->ac97);
679 return ret;
662} 680}
663 681
664static int wm9712_soc_remove(struct snd_soc_codec *codec) 682static int wm9712_soc_remove(struct snd_soc_codec *codec)
665{ 683{
666 struct wm9712_priv *wm9712 = snd_soc_codec_get_drvdata(codec); 684 struct wm9712_priv *wm9712 = snd_soc_codec_get_drvdata(codec);
667 685
686 snd_soc_codec_exit_regmap(codec);
668 snd_soc_free_ac97_codec(wm9712->ac97); 687 snd_soc_free_ac97_codec(wm9712->ac97);
669 return 0; 688 return 0;
670} 689}
@@ -673,14 +692,8 @@ static const struct snd_soc_codec_driver soc_codec_dev_wm9712 = {
673 .probe = wm9712_soc_probe, 692 .probe = wm9712_soc_probe,
674 .remove = wm9712_soc_remove, 693 .remove = wm9712_soc_remove,
675 .resume = wm9712_soc_resume, 694 .resume = wm9712_soc_resume,
676 .read = ac97_read,
677 .write = ac97_write,
678 .set_bias_level = wm9712_set_bias_level, 695 .set_bias_level = wm9712_set_bias_level,
679 .suspend_bias_off = true, 696 .suspend_bias_off = true,
680 .reg_cache_size = ARRAY_SIZE(wm9712_reg),
681 .reg_word_size = sizeof(u16),
682 .reg_cache_step = 2,
683 .reg_cache_default = wm9712_reg,
684 697
685 .component_driver = { 698 .component_driver = {
686 .controls = wm9712_snd_ac97_controls, 699 .controls = wm9712_snd_ac97_controls,