aboutsummaryrefslogtreecommitdiffstats
path: root/sound/soc/codecs/wm9713.c
diff options
context:
space:
mode:
Diffstat (limited to 'sound/soc/codecs/wm9713.c')
-rw-r--r--sound/soc/codecs/wm9713.c296
1 files changed, 150 insertions, 146 deletions
diff --git a/sound/soc/codecs/wm9713.c b/sound/soc/codecs/wm9713.c
index 4083a5130cbd..79e143625ac3 100644
--- a/sound/soc/codecs/wm9713.c
+++ b/sound/soc/codecs/wm9713.c
@@ -19,6 +19,7 @@
19#include <linux/slab.h> 19#include <linux/slab.h>
20#include <linux/module.h> 20#include <linux/module.h>
21#include <linux/device.h> 21#include <linux/device.h>
22#include <linux/regmap.h>
22#include <sound/core.h> 23#include <sound/core.h>
23#include <sound/pcm.h> 24#include <sound/pcm.h>
24#include <sound/ac97_codec.h> 25#include <sound/ac97_codec.h>
@@ -39,34 +40,6 @@ struct wm9713_priv {
39 struct mutex lock; 40 struct mutex lock;
40}; 41};
41 42
42static unsigned int ac97_read(struct snd_soc_codec *codec,
43 unsigned int reg);
44static int ac97_write(struct snd_soc_codec *codec,
45 unsigned int reg, unsigned int val);
46
47/*
48 * WM9713 register cache
49 * Reg 0x3c bit 15 is used by touch driver.
50 */
51static const u16 wm9713_reg[] = {
52 0x6174, 0x8080, 0x8080, 0x8080,
53 0xc880, 0xe808, 0xe808, 0x0808,
54 0x00da, 0x8000, 0xd600, 0xaaa0,
55 0xaaa0, 0xaaa0, 0x0000, 0x0000,
56 0x0f0f, 0x0040, 0x0000, 0x7f00,
57 0x0405, 0x0410, 0xbb80, 0xbb80,
58 0x0000, 0xbb80, 0x0000, 0x4523,
59 0x0000, 0x2000, 0x7eff, 0xffff,
60 0x0000, 0x0000, 0x0080, 0x0000,
61 0x0000, 0x0000, 0xfffe, 0xffff,
62 0x0000, 0x0000, 0x0000, 0xfffe,
63 0x4000, 0x0000, 0x0000, 0x0000,
64 0xb032, 0x3e00, 0x0000, 0x0000,
65 0x0000, 0x0000, 0x0000, 0x0000,
66 0x0000, 0x0000, 0x0000, 0x0006,
67 0x0001, 0x0000, 0x574d, 0x4c13,
68};
69
70#define HPL_MIXER 0 43#define HPL_MIXER 0
71#define HPR_MIXER 1 44#define HPR_MIXER 1
72 45
@@ -220,18 +193,15 @@ static int wm9713_voice_shutdown(struct snd_soc_dapm_widget *w,
220 struct snd_kcontrol *kcontrol, int event) 193 struct snd_kcontrol *kcontrol, int event)
221{ 194{
222 struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm); 195 struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm);
223 u16 status, rate;
224 196
225 if (WARN_ON(event != SND_SOC_DAPM_PRE_PMD)) 197 if (WARN_ON(event != SND_SOC_DAPM_PRE_PMD))
226 return -EINVAL; 198 return -EINVAL;
227 199
228 /* Gracefully shut down the voice interface. */ 200 /* Gracefully shut down the voice interface. */
229 status = ac97_read(codec, AC97_EXTENDED_MID) | 0x1000; 201 snd_soc_update_bits(codec, AC97_HANDSET_RATE, 0x0f00, 0x0200);
230 rate = ac97_read(codec, AC97_HANDSET_RATE) & 0xF0FF;
231 ac97_write(codec, AC97_HANDSET_RATE, rate | 0x0200);
232 schedule_timeout_interruptible(msecs_to_jiffies(1)); 202 schedule_timeout_interruptible(msecs_to_jiffies(1));
233 ac97_write(codec, AC97_HANDSET_RATE, rate | 0x0F00); 203 snd_soc_update_bits(codec, AC97_HANDSET_RATE, 0x0f00, 0x0f00);
234 ac97_write(codec, AC97_EXTENDED_MID, status); 204 snd_soc_update_bits(codec, AC97_EXTENDED_MID, 0x1000, 0x1000);
235 205
236 return 0; 206 return 0;
237} 207}
@@ -674,39 +644,97 @@ static const struct snd_soc_dapm_route wm9713_audio_map[] = {
674 {"Capture Mono Mux", "Right", "Right Capture Source"}, 644 {"Capture Mono Mux", "Right", "Right Capture Source"},
675}; 645};
676 646
677static unsigned int ac97_read(struct snd_soc_codec *codec, 647static bool wm9713_readable_reg(struct device *dev, unsigned int reg)
678 unsigned int reg)
679{ 648{
680 struct wm9713_priv *wm9713 = snd_soc_codec_get_drvdata(codec); 649 switch (reg) {
681 u16 *cache = codec->reg_cache; 650 case AC97_RESET ... AC97_PCM_SURR_DAC_RATE:
682 651 case AC97_PCM_LR_ADC_RATE:
683 if (reg == AC97_RESET || reg == AC97_GPIO_STATUS || 652 case AC97_CENTER_LFE_MASTER:
684 reg == AC97_VENDOR_ID1 || reg == AC97_VENDOR_ID2 || 653 case AC97_SPDIF ... AC97_LINE1_LEVEL:
685 reg == AC97_CD) 654 case AC97_GPIO_CFG ... 0x5c:
686 return soc_ac97_ops->read(wm9713->ac97, reg); 655 case AC97_CODEC_CLASS_REV ... AC97_PCI_SID:
687 else { 656 case 0x74 ... AC97_VENDOR_ID2:
688 reg = reg >> 1; 657 return true;
689 658 default:
690 if (reg >= (ARRAY_SIZE(wm9713_reg))) 659 return false;
691 return -EIO;
692
693 return cache[reg];
694 } 660 }
695} 661}
696 662
697static int ac97_write(struct snd_soc_codec *codec, unsigned int reg, 663static bool wm9713_writeable_reg(struct device *dev, unsigned int reg)
698 unsigned int val)
699{ 664{
700 struct wm9713_priv *wm9713 = snd_soc_codec_get_drvdata(codec); 665 switch (reg) {
666 case AC97_VENDOR_ID1:
667 case AC97_VENDOR_ID2:
668 return false;
669 default:
670 return wm9713_readable_reg(dev, reg);
671 }
672}
701 673
702 u16 *cache = codec->reg_cache; 674static const struct reg_default wm9713_reg_defaults[] = {
703 soc_ac97_ops->write(wm9713->ac97, reg, val); 675 { 0x02, 0x8080 }, /* Speaker Output Volume */
704 reg = reg >> 1; 676 { 0x04, 0x8080 }, /* Headphone Output Volume */
705 if (reg < (ARRAY_SIZE(wm9713_reg))) 677 { 0x06, 0x8080 }, /* Out3/OUT4 Volume */
706 cache[reg] = val; 678 { 0x08, 0xc880 }, /* Mono Volume */
679 { 0x0a, 0xe808 }, /* LINEIN Volume */
680 { 0x0c, 0xe808 }, /* DAC PGA Volume */
681 { 0x0e, 0x0808 }, /* MIC PGA Volume */
682 { 0x10, 0x00da }, /* MIC Routing Control */
683 { 0x12, 0x8000 }, /* Record PGA Volume */
684 { 0x14, 0xd600 }, /* Record Routing */
685 { 0x16, 0xaaa0 }, /* PCBEEP Volume */
686 { 0x18, 0xaaa0 }, /* VxDAC Volume */
687 { 0x1a, 0xaaa0 }, /* AUXDAC Volume */
688 { 0x1c, 0x0000 }, /* Output PGA Mux */
689 { 0x1e, 0x0000 }, /* DAC 3D control */
690 { 0x20, 0x0f0f }, /* DAC Tone Control*/
691 { 0x22, 0x0040 }, /* MIC Input Select & Bias */
692 { 0x24, 0x0000 }, /* Output Volume Mapping & Jack */
693 { 0x26, 0x7f00 }, /* Powerdown Ctrl/Stat*/
694 { 0x28, 0x0405 }, /* Extended Audio ID */
695 { 0x2a, 0x0410 }, /* Extended Audio Start/Ctrl */
696 { 0x2c, 0xbb80 }, /* Audio DACs Sample Rate */
697 { 0x2e, 0xbb80 }, /* AUXDAC Sample Rate */
698 { 0x32, 0xbb80 }, /* Audio ADCs Sample Rate */
699 { 0x36, 0x4523 }, /* PCM codec control */
700 { 0x3a, 0x2000 }, /* SPDIF control */
701 { 0x3c, 0xfdff }, /* Powerdown 1 */
702 { 0x3e, 0xffff }, /* Powerdown 2 */
703 { 0x40, 0x0000 }, /* General Purpose */
704 { 0x42, 0x0000 }, /* Fast Power-Up Control */
705 { 0x44, 0x0080 }, /* MCLK/PLL Control */
706 { 0x46, 0x0000 }, /* MCLK/PLL Control */
707 { 0x4c, 0xfffe }, /* GPIO Pin Configuration */
708 { 0x4e, 0xffff }, /* GPIO Pin Polarity / Type */
709 { 0x50, 0x0000 }, /* GPIO Pin Sticky */
710 { 0x52, 0x0000 }, /* GPIO Pin Wake-Up */
711 /* GPIO Pin Status */
712 { 0x56, 0xfffe }, /* GPIO Pin Sharing */
713 { 0x58, 0x4000 }, /* GPIO PullUp/PullDown */
714 { 0x5a, 0x0000 }, /* Additional Functions 1 */
715 { 0x5c, 0x0000 }, /* Additional Functions 2 */
716 { 0x60, 0xb032 }, /* ALC Control */
717 { 0x62, 0x3e00 }, /* ALC / Noise Gate Control */
718 { 0x64, 0x0000 }, /* AUXDAC input control */
719 { 0x74, 0x0000 }, /* Digitiser Reg 1 */
720 { 0x76, 0x0006 }, /* Digitiser Reg 2 */
721 { 0x78, 0x0001 }, /* Digitiser Reg 3 */
722 { 0x7a, 0x0000 }, /* Digitiser Read Back */
723};
707 724
708 return 0; 725static const struct regmap_config wm9713_regmap_config = {
709} 726 .reg_bits = 16,
727 .reg_stride = 2,
728 .val_bits = 16,
729 .max_register = 0x7e,
730 .cache_type = REGCACHE_RBTREE,
731
732 .reg_defaults = wm9713_reg_defaults,
733 .num_reg_defaults = ARRAY_SIZE(wm9713_reg_defaults),
734 .volatile_reg = regmap_ac97_default_volatile,
735 .readable_reg = wm9713_readable_reg,
736 .writeable_reg = wm9713_writeable_reg,
737};
710 738
711/* PLL divisors */ 739/* PLL divisors */
712struct _pll_div { 740struct _pll_div {
@@ -793,10 +821,8 @@ static int wm9713_set_pll(struct snd_soc_codec *codec,
793 /* turn PLL off ? */ 821 /* turn PLL off ? */
794 if (freq_in == 0) { 822 if (freq_in == 0) {
795 /* disable PLL power and select ext source */ 823 /* disable PLL power and select ext source */
796 reg = ac97_read(codec, AC97_HANDSET_RATE); 824 snd_soc_update_bits(codec, AC97_HANDSET_RATE, 0x0080, 0x0080);
797 ac97_write(codec, AC97_HANDSET_RATE, reg | 0x0080); 825 snd_soc_update_bits(codec, AC97_EXTENDED_MID, 0x0200, 0x0200);
798 reg = ac97_read(codec, AC97_EXTENDED_MID);
799 ac97_write(codec, AC97_EXTENDED_MID, reg | 0x0200);
800 wm9713->pll_in = 0; 826 wm9713->pll_in = 0;
801 return 0; 827 return 0;
802 } 828 }
@@ -806,7 +832,7 @@ static int wm9713_set_pll(struct snd_soc_codec *codec,
806 if (pll_div.k == 0) { 832 if (pll_div.k == 0) {
807 reg = (pll_div.n << 12) | (pll_div.lf << 11) | 833 reg = (pll_div.n << 12) | (pll_div.lf << 11) |
808 (pll_div.divsel << 9) | (pll_div.divctl << 8); 834 (pll_div.divsel << 9) | (pll_div.divctl << 8);
809 ac97_write(codec, AC97_LINE1_LEVEL, reg); 835 snd_soc_write(codec, AC97_LINE1_LEVEL, reg);
810 } else { 836 } else {
811 /* write the fractional k to the reg 0x46 pages */ 837 /* write the fractional k to the reg 0x46 pages */
812 reg2 = (pll_div.n << 12) | (pll_div.lf << 11) | (1 << 10) | 838 reg2 = (pll_div.n << 12) | (pll_div.lf << 11) | (1 << 10) |
@@ -814,33 +840,31 @@ static int wm9713_set_pll(struct snd_soc_codec *codec,
814 840
815 /* K [21:20] */ 841 /* K [21:20] */
816 reg = reg2 | (0x5 << 4) | (pll_div.k >> 20); 842 reg = reg2 | (0x5 << 4) | (pll_div.k >> 20);
817 ac97_write(codec, AC97_LINE1_LEVEL, reg); 843 snd_soc_write(codec, AC97_LINE1_LEVEL, reg);
818 844
819 /* K [19:16] */ 845 /* K [19:16] */
820 reg = reg2 | (0x4 << 4) | ((pll_div.k >> 16) & 0xf); 846 reg = reg2 | (0x4 << 4) | ((pll_div.k >> 16) & 0xf);
821 ac97_write(codec, AC97_LINE1_LEVEL, reg); 847 snd_soc_write(codec, AC97_LINE1_LEVEL, reg);
822 848
823 /* K [15:12] */ 849 /* K [15:12] */
824 reg = reg2 | (0x3 << 4) | ((pll_div.k >> 12) & 0xf); 850 reg = reg2 | (0x3 << 4) | ((pll_div.k >> 12) & 0xf);
825 ac97_write(codec, AC97_LINE1_LEVEL, reg); 851 snd_soc_write(codec, AC97_LINE1_LEVEL, reg);
826 852
827 /* K [11:8] */ 853 /* K [11:8] */
828 reg = reg2 | (0x2 << 4) | ((pll_div.k >> 8) & 0xf); 854 reg = reg2 | (0x2 << 4) | ((pll_div.k >> 8) & 0xf);
829 ac97_write(codec, AC97_LINE1_LEVEL, reg); 855 snd_soc_write(codec, AC97_LINE1_LEVEL, reg);
830 856
831 /* K [7:4] */ 857 /* K [7:4] */
832 reg = reg2 | (0x1 << 4) | ((pll_div.k >> 4) & 0xf); 858 reg = reg2 | (0x1 << 4) | ((pll_div.k >> 4) & 0xf);
833 ac97_write(codec, AC97_LINE1_LEVEL, reg); 859 snd_soc_write(codec, AC97_LINE1_LEVEL, reg);
834 860
835 reg = reg2 | (0x0 << 4) | (pll_div.k & 0xf); /* K [3:0] */ 861 reg = reg2 | (0x0 << 4) | (pll_div.k & 0xf); /* K [3:0] */
836 ac97_write(codec, AC97_LINE1_LEVEL, reg); 862 snd_soc_write(codec, AC97_LINE1_LEVEL, reg);
837 } 863 }
838 864
839 /* turn PLL on and select as source */ 865 /* turn PLL on and select as source */
840 reg = ac97_read(codec, AC97_EXTENDED_MID); 866 snd_soc_update_bits(codec, AC97_EXTENDED_MID, 0x0200, 0x0000);
841 ac97_write(codec, AC97_EXTENDED_MID, reg & 0xfdff); 867 snd_soc_update_bits(codec, AC97_HANDSET_RATE, 0x0080, 0x0000);
842 reg = ac97_read(codec, AC97_HANDSET_RATE);
843 ac97_write(codec, AC97_HANDSET_RATE, reg & 0xff7f);
844 wm9713->pll_in = freq_in; 868 wm9713->pll_in = freq_in;
845 869
846 /* wait 10ms AC97 link frames for the link to stabilise */ 870 /* wait 10ms AC97 link frames for the link to stabilise */
@@ -863,10 +887,10 @@ static int wm9713_set_dai_tristate(struct snd_soc_dai *codec_dai,
863 int tristate) 887 int tristate)
864{ 888{
865 struct snd_soc_codec *codec = codec_dai->codec; 889 struct snd_soc_codec *codec = codec_dai->codec;
866 u16 reg = ac97_read(codec, AC97_CENTER_LFE_MASTER) & 0x9fff;
867 890
868 if (tristate) 891 if (tristate)
869 ac97_write(codec, AC97_CENTER_LFE_MASTER, reg); 892 snd_soc_update_bits(codec, AC97_CENTER_LFE_MASTER,
893 0x6000, 0x0000);
870 894
871 return 0; 895 return 0;
872} 896}
@@ -879,36 +903,30 @@ static int wm9713_set_dai_clkdiv(struct snd_soc_dai *codec_dai,
879 int div_id, int div) 903 int div_id, int div)
880{ 904{
881 struct snd_soc_codec *codec = codec_dai->codec; 905 struct snd_soc_codec *codec = codec_dai->codec;
882 u16 reg;
883 906
884 switch (div_id) { 907 switch (div_id) {
885 case WM9713_PCMCLK_DIV: 908 case WM9713_PCMCLK_DIV:
886 reg = ac97_read(codec, AC97_HANDSET_RATE) & 0xf0ff; 909 snd_soc_update_bits(codec, AC97_HANDSET_RATE, 0x0f00, div);
887 ac97_write(codec, AC97_HANDSET_RATE, reg | div);
888 break; 910 break;
889 case WM9713_CLKA_MULT: 911 case WM9713_CLKA_MULT:
890 reg = ac97_read(codec, AC97_HANDSET_RATE) & 0xfffd; 912 snd_soc_update_bits(codec, AC97_HANDSET_RATE, 0x0002, div);
891 ac97_write(codec, AC97_HANDSET_RATE, reg | div);
892 break; 913 break;
893 case WM9713_CLKB_MULT: 914 case WM9713_CLKB_MULT:
894 reg = ac97_read(codec, AC97_HANDSET_RATE) & 0xfffb; 915 snd_soc_update_bits(codec, AC97_HANDSET_RATE, 0x0004, div);
895 ac97_write(codec, AC97_HANDSET_RATE, reg | div);
896 break; 916 break;
897 case WM9713_HIFI_DIV: 917 case WM9713_HIFI_DIV:
898 reg = ac97_read(codec, AC97_HANDSET_RATE) & 0x8fff; 918 snd_soc_update_bits(codec, AC97_HANDSET_RATE, 0x7000, div);
899 ac97_write(codec, AC97_HANDSET_RATE, reg | div);
900 break; 919 break;
901 case WM9713_PCMBCLK_DIV: 920 case WM9713_PCMBCLK_DIV:
902 reg = ac97_read(codec, AC97_CENTER_LFE_MASTER) & 0xf1ff; 921 snd_soc_update_bits(codec, AC97_CENTER_LFE_MASTER, 0x0e00, div);
903 ac97_write(codec, AC97_CENTER_LFE_MASTER, reg | div);
904 break; 922 break;
905 case WM9713_PCMCLK_PLL_DIV: 923 case WM9713_PCMCLK_PLL_DIV:
906 reg = ac97_read(codec, AC97_LINE1_LEVEL) & 0xff80; 924 snd_soc_update_bits(codec, AC97_LINE1_LEVEL,
907 ac97_write(codec, AC97_LINE1_LEVEL, reg | 0x60 | div); 925 0x007f, div | 0x60);
908 break; 926 break;
909 case WM9713_HIFI_PLL_DIV: 927 case WM9713_HIFI_PLL_DIV:
910 reg = ac97_read(codec, AC97_LINE1_LEVEL) & 0xff80; 928 snd_soc_update_bits(codec, AC97_LINE1_LEVEL,
911 ac97_write(codec, AC97_LINE1_LEVEL, reg | 0x70 | div); 929 0x007f, div | 0x70);
912 break; 930 break;
913 default: 931 default:
914 return -EINVAL; 932 return -EINVAL;
@@ -921,7 +939,7 @@ static int wm9713_set_dai_fmt(struct snd_soc_dai *codec_dai,
921 unsigned int fmt) 939 unsigned int fmt)
922{ 940{
923 struct snd_soc_codec *codec = codec_dai->codec; 941 struct snd_soc_codec *codec = codec_dai->codec;
924 u16 gpio = ac97_read(codec, AC97_GPIO_CFG) & 0xffc5; 942 u16 gpio = snd_soc_read(codec, AC97_GPIO_CFG) & 0xffc5;
925 u16 reg = 0x8000; 943 u16 reg = 0x8000;
926 944
927 /* clock masters */ 945 /* clock masters */
@@ -974,8 +992,8 @@ static int wm9713_set_dai_fmt(struct snd_soc_dai *codec_dai,
974 break; 992 break;
975 } 993 }
976 994
977 ac97_write(codec, AC97_GPIO_CFG, gpio); 995 snd_soc_write(codec, AC97_GPIO_CFG, gpio);
978 ac97_write(codec, AC97_CENTER_LFE_MASTER, reg); 996 snd_soc_write(codec, AC97_CENTER_LFE_MASTER, reg);
979 return 0; 997 return 0;
980} 998}
981 999
@@ -984,24 +1002,24 @@ static int wm9713_pcm_hw_params(struct snd_pcm_substream *substream,
984 struct snd_soc_dai *dai) 1002 struct snd_soc_dai *dai)
985{ 1003{
986 struct snd_soc_codec *codec = dai->codec; 1004 struct snd_soc_codec *codec = dai->codec;
987 u16 reg = ac97_read(codec, AC97_CENTER_LFE_MASTER) & 0xfff3;
988 1005
1006 /* enable PCM interface in master mode */
989 switch (params_width(params)) { 1007 switch (params_width(params)) {
990 case 16: 1008 case 16:
991 break; 1009 break;
992 case 20: 1010 case 20:
993 reg |= 0x0004; 1011 snd_soc_update_bits(codec, AC97_CENTER_LFE_MASTER,
1012 0x000c, 0x0004);
994 break; 1013 break;
995 case 24: 1014 case 24:
996 reg |= 0x0008; 1015 snd_soc_update_bits(codec, AC97_CENTER_LFE_MASTER,
1016 0x000c, 0x0008);
997 break; 1017 break;
998 case 32: 1018 case 32:
999 reg |= 0x000c; 1019 snd_soc_update_bits(codec, AC97_CENTER_LFE_MASTER,
1020 0x000c, 0x000c);
1000 break; 1021 break;
1001 } 1022 }
1002
1003 /* enable PCM interface in master mode */
1004 ac97_write(codec, AC97_CENTER_LFE_MASTER, reg);
1005 return 0; 1023 return 0;
1006} 1024}
1007 1025
@@ -1011,17 +1029,15 @@ static int ac97_hifi_prepare(struct snd_pcm_substream *substream,
1011 struct snd_soc_codec *codec = dai->codec; 1029 struct snd_soc_codec *codec = dai->codec;
1012 struct snd_pcm_runtime *runtime = substream->runtime; 1030 struct snd_pcm_runtime *runtime = substream->runtime;
1013 int reg; 1031 int reg;
1014 u16 vra;
1015 1032
1016 vra = ac97_read(codec, AC97_EXTENDED_STATUS); 1033 snd_soc_update_bits(codec, AC97_EXTENDED_STATUS, 0x0001, 0x0001);
1017 ac97_write(codec, AC97_EXTENDED_STATUS, vra | 0x1);
1018 1034
1019 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) 1035 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
1020 reg = AC97_PCM_FRONT_DAC_RATE; 1036 reg = AC97_PCM_FRONT_DAC_RATE;
1021 else 1037 else
1022 reg = AC97_PCM_LR_ADC_RATE; 1038 reg = AC97_PCM_LR_ADC_RATE;
1023 1039
1024 return ac97_write(codec, reg, runtime->rate); 1040 return snd_soc_write(codec, reg, runtime->rate);
1025} 1041}
1026 1042
1027static int ac97_aux_prepare(struct snd_pcm_substream *substream, 1043static int ac97_aux_prepare(struct snd_pcm_substream *substream,
@@ -1029,17 +1045,14 @@ static int ac97_aux_prepare(struct snd_pcm_substream *substream,
1029{ 1045{
1030 struct snd_soc_codec *codec = dai->codec; 1046 struct snd_soc_codec *codec = dai->codec;
1031 struct snd_pcm_runtime *runtime = substream->runtime; 1047 struct snd_pcm_runtime *runtime = substream->runtime;
1032 u16 vra, xsle;
1033 1048
1034 vra = ac97_read(codec, AC97_EXTENDED_STATUS); 1049 snd_soc_update_bits(codec, AC97_EXTENDED_STATUS, 0x0001, 0x0001);
1035 ac97_write(codec, AC97_EXTENDED_STATUS, vra | 0x1); 1050 snd_soc_update_bits(codec, AC97_PCI_SID, 0x8000, 0x8000);
1036 xsle = ac97_read(codec, AC97_PCI_SID);
1037 ac97_write(codec, AC97_PCI_SID, xsle | 0x8000);
1038 1051
1039 if (substream->stream != SNDRV_PCM_STREAM_PLAYBACK) 1052 if (substream->stream != SNDRV_PCM_STREAM_PLAYBACK)
1040 return -ENODEV; 1053 return -ENODEV;
1041 1054
1042 return ac97_write(codec, AC97_PCM_SURR_DAC_RATE, runtime->rate); 1055 return snd_soc_write(codec, AC97_PCM_SURR_DAC_RATE, runtime->rate);
1043} 1056}
1044 1057
1045#define WM9713_RATES (SNDRV_PCM_RATE_8000 | \ 1058#define WM9713_RATES (SNDRV_PCM_RATE_8000 | \
@@ -1128,27 +1141,23 @@ static struct snd_soc_dai_driver wm9713_dai[] = {
1128static int wm9713_set_bias_level(struct snd_soc_codec *codec, 1141static int wm9713_set_bias_level(struct snd_soc_codec *codec,
1129 enum snd_soc_bias_level level) 1142 enum snd_soc_bias_level level)
1130{ 1143{
1131 u16 reg;
1132
1133 switch (level) { 1144 switch (level) {
1134 case SND_SOC_BIAS_ON: 1145 case SND_SOC_BIAS_ON:
1135 /* enable thermal shutdown */ 1146 /* enable thermal shutdown */
1136 reg = ac97_read(codec, AC97_EXTENDED_MID) & 0x1bff; 1147 snd_soc_update_bits(codec, AC97_EXTENDED_MID, 0xe400, 0x0000);
1137 ac97_write(codec, AC97_EXTENDED_MID, reg);
1138 break; 1148 break;
1139 case SND_SOC_BIAS_PREPARE: 1149 case SND_SOC_BIAS_PREPARE:
1140 break; 1150 break;
1141 case SND_SOC_BIAS_STANDBY: 1151 case SND_SOC_BIAS_STANDBY:
1142 /* enable master bias and vmid */ 1152 /* enable master bias and vmid */
1143 reg = ac97_read(codec, AC97_EXTENDED_MID) & 0x3bff; 1153 snd_soc_update_bits(codec, AC97_EXTENDED_MID, 0xc400, 0x0000);
1144 ac97_write(codec, AC97_EXTENDED_MID, reg); 1154 snd_soc_write(codec, AC97_POWERDOWN, 0x0000);
1145 ac97_write(codec, AC97_POWERDOWN, 0x0000);
1146 break; 1155 break;
1147 case SND_SOC_BIAS_OFF: 1156 case SND_SOC_BIAS_OFF:
1148 /* disable everything including AC link */ 1157 /* disable everything including AC link */
1149 ac97_write(codec, AC97_EXTENDED_MID, 0xffff); 1158 snd_soc_write(codec, AC97_EXTENDED_MID, 0xffff);
1150 ac97_write(codec, AC97_EXTENDED_MSTATUS, 0xffff); 1159 snd_soc_write(codec, AC97_EXTENDED_MSTATUS, 0xffff);
1151 ac97_write(codec, AC97_POWERDOWN, 0xffff); 1160 snd_soc_write(codec, AC97_POWERDOWN, 0xffff);
1152 break; 1161 break;
1153 } 1162 }
1154 return 0; 1163 return 0;
@@ -1156,16 +1165,14 @@ static int wm9713_set_bias_level(struct snd_soc_codec *codec,
1156 1165
1157static int wm9713_soc_suspend(struct snd_soc_codec *codec) 1166static int wm9713_soc_suspend(struct snd_soc_codec *codec)
1158{ 1167{
1159 u16 reg;
1160
1161 /* Disable everything except touchpanel - that will be handled 1168 /* Disable everything except touchpanel - that will be handled
1162 * by the touch driver and left disabled if touch is not in 1169 * by the touch driver and left disabled if touch is not in
1163 * use. */ 1170 * use. */
1164 reg = ac97_read(codec, AC97_EXTENDED_MID); 1171 snd_soc_update_bits(codec, AC97_EXTENDED_MID, 0x7fff,
1165 ac97_write(codec, AC97_EXTENDED_MID, reg | 0x7fff); 1172 0x7fff);
1166 ac97_write(codec, AC97_EXTENDED_MSTATUS, 0xffff); 1173 snd_soc_write(codec, AC97_EXTENDED_MSTATUS, 0xffff);
1167 ac97_write(codec, AC97_POWERDOWN, 0x6f00); 1174 snd_soc_write(codec, AC97_POWERDOWN, 0x6f00);
1168 ac97_write(codec, AC97_POWERDOWN, 0xffff); 1175 snd_soc_write(codec, AC97_POWERDOWN, 0xffff);
1169 1176
1170 return 0; 1177 return 0;
1171} 1178}
@@ -1173,8 +1180,7 @@ static int wm9713_soc_suspend(struct snd_soc_codec *codec)
1173static int wm9713_soc_resume(struct snd_soc_codec *codec) 1180static int wm9713_soc_resume(struct snd_soc_codec *codec)
1174{ 1181{
1175 struct wm9713_priv *wm9713 = snd_soc_codec_get_drvdata(codec); 1182 struct wm9713_priv *wm9713 = snd_soc_codec_get_drvdata(codec);
1176 int i, ret; 1183 int ret;
1177 u16 *cache = codec->reg_cache;
1178 1184
1179 ret = snd_ac97_reset(wm9713->ac97, true, WM9713_VENDOR_ID, 1185 ret = snd_ac97_reset(wm9713->ac97, true, WM9713_VENDOR_ID,
1180 WM9713_VENDOR_ID_MASK); 1186 WM9713_VENDOR_ID_MASK);
@@ -1189,12 +1195,8 @@ static int wm9713_soc_resume(struct snd_soc_codec *codec)
1189 1195
1190 /* only synchronise the codec if warm reset failed */ 1196 /* only synchronise the codec if warm reset failed */
1191 if (ret == 0) { 1197 if (ret == 0) {
1192 for (i = 2; i < ARRAY_SIZE(wm9713_reg) << 1; i += 2) { 1198 regcache_mark_dirty(codec->component.regmap);
1193 if (i == AC97_POWERDOWN || i == AC97_EXTENDED_MID || 1199 snd_soc_cache_sync(codec);
1194 i == AC97_EXTENDED_MSTATUS || i > 0x66)
1195 continue;
1196 soc_ac97_ops->write(wm9713->ac97, i, cache[i>>1]);
1197 }
1198 } 1200 }
1199 1201
1200 return ret; 1202 return ret;
@@ -1203,16 +1205,23 @@ static int wm9713_soc_resume(struct snd_soc_codec *codec)
1203static int wm9713_soc_probe(struct snd_soc_codec *codec) 1205static int wm9713_soc_probe(struct snd_soc_codec *codec)
1204{ 1206{
1205 struct wm9713_priv *wm9713 = snd_soc_codec_get_drvdata(codec); 1207 struct wm9713_priv *wm9713 = snd_soc_codec_get_drvdata(codec);
1206 int reg; 1208 struct regmap *regmap;
1207 1209
1208 wm9713->ac97 = snd_soc_new_ac97_codec(codec, WM9713_VENDOR_ID, 1210 wm9713->ac97 = snd_soc_new_ac97_codec(codec, WM9713_VENDOR_ID,
1209 WM9713_VENDOR_ID_MASK); 1211 WM9713_VENDOR_ID_MASK);
1210 if (IS_ERR(wm9713->ac97)) 1212 if (IS_ERR(wm9713->ac97))
1211 return PTR_ERR(wm9713->ac97); 1213 return PTR_ERR(wm9713->ac97);
1212 1214
1215 regmap = devm_regmap_init_ac97(wm9713->ac97, &wm9713_regmap_config);
1216 if (IS_ERR(regmap)) {
1217 snd_soc_free_ac97_codec(wm9713->ac97);
1218 return PTR_ERR(regmap);
1219 }
1220
1221 snd_soc_codec_init_regmap(codec, regmap);
1222
1213 /* unmute the adc - move to kcontrol */ 1223 /* unmute the adc - move to kcontrol */
1214 reg = ac97_read(codec, AC97_CD) & 0x7fff; 1224 snd_soc_update_bits(codec, AC97_CD, 0x7fff, 0x0000);
1215 ac97_write(codec, AC97_CD, reg);
1216 1225
1217 return 0; 1226 return 0;
1218} 1227}
@@ -1221,6 +1230,7 @@ static int wm9713_soc_remove(struct snd_soc_codec *codec)
1221{ 1230{
1222 struct wm9713_priv *wm9713 = snd_soc_codec_get_drvdata(codec); 1231 struct wm9713_priv *wm9713 = snd_soc_codec_get_drvdata(codec);
1223 1232
1233 snd_soc_codec_exit_regmap(codec);
1224 snd_soc_free_ac97_codec(wm9713->ac97); 1234 snd_soc_free_ac97_codec(wm9713->ac97);
1225 return 0; 1235 return 0;
1226} 1236}
@@ -1230,13 +1240,7 @@ static struct snd_soc_codec_driver soc_codec_dev_wm9713 = {
1230 .remove = wm9713_soc_remove, 1240 .remove = wm9713_soc_remove,
1231 .suspend = wm9713_soc_suspend, 1241 .suspend = wm9713_soc_suspend,
1232 .resume = wm9713_soc_resume, 1242 .resume = wm9713_soc_resume,
1233 .read = ac97_read,
1234 .write = ac97_write,
1235 .set_bias_level = wm9713_set_bias_level, 1243 .set_bias_level = wm9713_set_bias_level,
1236 .reg_cache_size = ARRAY_SIZE(wm9713_reg),
1237 .reg_word_size = sizeof(u16),
1238 .reg_cache_step = 2,
1239 .reg_cache_default = wm9713_reg,
1240 1244
1241 .controls = wm9713_snd_ac97_controls, 1245 .controls = wm9713_snd_ac97_controls,
1242 .num_controls = ARRAY_SIZE(wm9713_snd_ac97_controls), 1246 .num_controls = ARRAY_SIZE(wm9713_snd_ac97_controls),