aboutsummaryrefslogtreecommitdiffstats
path: root/sound/soc
diff options
context:
space:
mode:
authorMark Brown <broonie@opensource.wolfsonmicro.com>2009-08-15 06:20:44 -0400
committerMark Brown <broonie@opensource.wolfsonmicro.com>2009-08-15 06:20:44 -0400
commit08229de4b42816079ed5d15f0689fcd0af946d5e (patch)
tree7126dc7b220fbbce745cb5d9a8864e9690587da4 /sound/soc
parentfbb474dedab871c7382858c374acd287dad4ab38 (diff)
parent2a708137fd7d3e0928f27157aaed8aba404b11c9 (diff)
Merge branch 'for-2.6.32' into mxc
Conflicts: sound/soc/Makefile
Diffstat (limited to 'sound/soc')
-rw-r--r--sound/soc/Kconfig2
-rw-r--r--sound/soc/Makefile6
-rw-r--r--sound/soc/atmel/Kconfig8
-rw-r--r--sound/soc/atmel/Makefile1
-rw-r--r--sound/soc/atmel/playpaq_wm8510.c2
-rw-r--r--sound/soc/atmel/sam9g20_wm8731.c138
-rw-r--r--sound/soc/atmel/snd-soc-afeb9260.c203
-rw-r--r--sound/soc/blackfin/Kconfig23
-rw-r--r--sound/soc/blackfin/Makefile6
-rw-r--r--sound/soc/blackfin/bf5xx-ac97.c19
-rw-r--r--sound/soc/blackfin/bf5xx-ad1938.c142
-rw-r--r--sound/soc/blackfin/bf5xx-ad73311.c16
-rw-r--r--sound/soc/blackfin/bf5xx-i2s.c18
-rw-r--r--sound/soc/blackfin/bf5xx-sport.c4
-rw-r--r--sound/soc/blackfin/bf5xx-ssm2602.c16
-rw-r--r--sound/soc/blackfin/bf5xx-tdm-pcm.c330
-rw-r--r--sound/soc/blackfin/bf5xx-tdm-pcm.h21
-rw-r--r--sound/soc/blackfin/bf5xx-tdm.c343
-rw-r--r--sound/soc/blackfin/bf5xx-tdm.h14
-rw-r--r--sound/soc/codecs/Kconfig60
-rw-r--r--sound/soc/codecs/Makefile34
-rw-r--r--sound/soc/codecs/ac97.c4
-rw-r--r--sound/soc/codecs/ad1836.c446
-rw-r--r--sound/soc/codecs/ad1836.h64
-rw-r--r--sound/soc/codecs/ad1938.c682
-rw-r--r--sound/soc/codecs/ad1938.h100
-rw-r--r--sound/soc/codecs/ad1980.c4
-rw-r--r--sound/soc/codecs/ak4535.c16
-rw-r--r--sound/soc/codecs/cs4270.c126
-rw-r--r--sound/soc/codecs/cx20442.c501
-rw-r--r--sound/soc/codecs/cx20442.h20
-rw-r--r--sound/soc/codecs/max9877.c308
-rw-r--r--sound/soc/codecs/max9877.h37
-rw-r--r--sound/soc/codecs/spdif_transciever.c74
-rw-r--r--sound/soc/codecs/spdif_transciever.h17
-rw-r--r--sound/soc/codecs/ssm2602.c29
-rw-r--r--sound/soc/codecs/stac9766.c463
-rw-r--r--sound/soc/codecs/stac9766.h21
-rw-r--r--sound/soc/codecs/tlv320aic23.c16
-rw-r--r--sound/soc/codecs/tlv320aic3x.c22
-rw-r--r--sound/soc/codecs/twl4030.c1316
-rw-r--r--sound/soc/codecs/twl4030.h45
-rw-r--r--sound/soc/codecs/uda134x.c4
-rw-r--r--sound/soc/codecs/uda1380.c313
-rw-r--r--sound/soc/codecs/uda1380.h8
-rw-r--r--sound/soc/codecs/wm8350.c42
-rw-r--r--sound/soc/codecs/wm8350.h1
-rw-r--r--sound/soc/codecs/wm8400.c34
-rw-r--r--sound/soc/codecs/wm8510.c177
-rw-r--r--sound/soc/codecs/wm8523.c699
-rw-r--r--sound/soc/codecs/wm8523.h160
-rw-r--r--sound/soc/codecs/wm8580.c213
-rw-r--r--sound/soc/codecs/wm8728.c111
-rw-r--r--sound/soc/codecs/wm8731.c222
-rw-r--r--sound/soc/codecs/wm8750.c154
-rw-r--r--sound/soc/codecs/wm8753.c47
-rw-r--r--sound/soc/codecs/wm8776.c744
-rw-r--r--sound/soc/codecs/wm8776.h51
-rw-r--r--sound/soc/codecs/wm8900.c351
-rw-r--r--sound/soc/codecs/wm8903.c376
-rw-r--r--sound/soc/codecs/wm8940.c933
-rw-r--r--sound/soc/codecs/wm8940.h104
-rw-r--r--sound/soc/codecs/wm8960.c942
-rw-r--r--sound/soc/codecs/wm8960.h127
-rw-r--r--sound/soc/codecs/wm8961.c1265
-rw-r--r--sound/soc/codecs/wm8961.h866
-rw-r--r--sound/soc/codecs/wm8971.c127
-rw-r--r--sound/soc/codecs/wm8988.c1069
-rw-r--r--sound/soc/codecs/wm8988.h60
-rw-r--r--sound/soc/codecs/wm8990.c196
-rw-r--r--sound/soc/codecs/wm8993.c1534
-rw-r--r--sound/soc/codecs/wm8993.h2132
-rw-r--r--sound/soc/codecs/wm9081.c1511
-rw-r--r--sound/soc/codecs/wm9081.h787
-rw-r--r--sound/soc/codecs/wm9705.c4
-rw-r--r--sound/soc/codecs/wm9712.c8
-rw-r--r--sound/soc/codecs/wm9713.c48
-rw-r--r--sound/soc/codecs/wm_hubs.c758
-rw-r--r--sound/soc/codecs/wm_hubs.h24
-rw-r--r--sound/soc/davinci/Kconfig33
-rw-r--r--sound/soc/davinci/Makefile5
-rw-r--r--sound/soc/davinci/davinci-evm.c144
-rw-r--r--sound/soc/davinci/davinci-i2s.c340
-rw-r--r--sound/soc/davinci/davinci-mcasp.c973
-rw-r--r--sound/soc/davinci/davinci-mcasp.h60
-rw-r--r--sound/soc/davinci/davinci-pcm.c10
-rw-r--r--sound/soc/davinci/davinci-pcm.h19
-rw-r--r--sound/soc/fsl/Kconfig32
-rw-r--r--sound/soc/fsl/Makefile7
-rw-r--r--sound/soc/fsl/efika-audio-fabric.c90
-rw-r--r--sound/soc/fsl/fsl_ssi.c11
-rw-r--r--sound/soc/fsl/mpc5200_dma.c582
-rw-r--r--sound/soc/fsl/mpc5200_dma.h81
-rw-r--r--sound/soc/fsl/mpc5200_psc_ac97.c345
-rw-r--r--sound/soc/fsl/mpc5200_psc_ac97.h15
-rw-r--r--sound/soc/fsl/mpc5200_psc_i2s.c754
-rw-r--r--sound/soc/fsl/mpc5200_psc_i2s.h12
-rw-r--r--sound/soc/fsl/pcm030-audio-fabric.c90
-rw-r--r--sound/soc/omap/Kconfig23
-rw-r--r--sound/soc/omap/Makefile6
-rw-r--r--sound/soc/omap/ams-delta.c646
-rw-r--r--sound/soc/omap/n810.c7
-rw-r--r--sound/soc/omap/omap-mcbsp.c53
-rw-r--r--sound/soc/omap/omap-pcm.c22
-rw-r--r--sound/soc/omap/omap2evm.c2
-rw-r--r--sound/soc/omap/omap3beagle.c28
-rw-r--r--sound/soc/omap/omap3evm.c147
-rw-r--r--sound/soc/omap/omap3pandora.c4
-rw-r--r--sound/soc/omap/overo.c2
-rw-r--r--sound/soc/omap/sdp3430.c103
-rw-r--r--sound/soc/omap/zoom2.c314
-rw-r--r--sound/soc/pxa/Kconfig20
-rw-r--r--sound/soc/pxa/Makefile2
-rw-r--r--sound/soc/pxa/corgi.c36
-rw-r--r--sound/soc/pxa/em-x270.c9
-rw-r--r--sound/soc/pxa/imote2.c114
-rw-r--r--sound/soc/pxa/magician.c71
-rw-r--r--sound/soc/pxa/palm27x.c206
-rw-r--r--sound/soc/pxa/poodle.c36
-rw-r--r--sound/soc/pxa/pxa-ssp.c275
-rw-r--r--sound/soc/pxa/pxa2xx-ac97.c12
-rw-r--r--sound/soc/pxa/pxa2xx-i2s.c46
-rw-r--r--sound/soc/s3c24xx/Kconfig13
-rw-r--r--sound/soc/s3c24xx/Makefile2
-rw-r--r--sound/soc/s3c24xx/neo1973_gta02_wm8753.c498
-rw-r--r--sound/soc/s3c24xx/neo1973_wm8753.c16
-rw-r--r--sound/soc/s3c24xx/s3c-i2s-v2.c91
-rw-r--r--sound/soc/s3c24xx/s3c2412-i2s.c3
-rw-r--r--sound/soc/s3c24xx/s3c2443-ac97.c11
-rw-r--r--sound/soc/s3c24xx/s3c24xx-i2s.c2
-rw-r--r--sound/soc/s3c24xx/s3c24xx-pcm.c21
-rw-r--r--sound/soc/s3c24xx/s3c64xx-i2s.c157
-rw-r--r--sound/soc/s3c24xx/s3c64xx-i2s.h6
-rw-r--r--sound/soc/s6000/Kconfig19
-rw-r--r--sound/soc/s6000/Makefile11
-rw-r--r--sound/soc/s6000/s6000-i2s.c629
-rw-r--r--sound/soc/s6000/s6000-i2s.h25
-rw-r--r--sound/soc/s6000/s6000-pcm.c497
-rw-r--r--sound/soc/s6000/s6000-pcm.h35
-rw-r--r--sound/soc/s6000/s6105-ipcam.c244
-rw-r--r--sound/soc/sh/ssi.c2
-rw-r--r--sound/soc/soc-cache.c218
-rw-r--r--sound/soc/soc-core.c308
-rw-r--r--sound/soc/soc-dapm.c646
-rw-r--r--sound/soc/soc-jack.c24
-rw-r--r--sound/soc/txx9/Kconfig29
-rw-r--r--sound/soc/txx9/Makefile11
-rw-r--r--sound/soc/txx9/txx9aclc-ac97.c255
-rw-r--r--sound/soc/txx9/txx9aclc-generic.c98
-rw-r--r--sound/soc/txx9/txx9aclc.c432
-rw-r--r--sound/soc/txx9/txx9aclc.h83
151 files changed, 28435 insertions, 3657 deletions
diff --git a/sound/soc/Kconfig b/sound/soc/Kconfig
index 3d2bb6fc6dcc..d3e786a9a0a7 100644
--- a/sound/soc/Kconfig
+++ b/sound/soc/Kconfig
@@ -32,7 +32,9 @@ source "sound/soc/fsl/Kconfig"
32source "sound/soc/omap/Kconfig" 32source "sound/soc/omap/Kconfig"
33source "sound/soc/pxa/Kconfig" 33source "sound/soc/pxa/Kconfig"
34source "sound/soc/s3c24xx/Kconfig" 34source "sound/soc/s3c24xx/Kconfig"
35source "sound/soc/s6000/Kconfig"
35source "sound/soc/sh/Kconfig" 36source "sound/soc/sh/Kconfig"
37source "sound/soc/txx9/Kconfig"
36 38
37# Supported codecs 39# Supported codecs
38source "sound/soc/codecs/Kconfig" 40source "sound/soc/codecs/Kconfig"
diff --git a/sound/soc/Makefile b/sound/soc/Makefile
index 8120b52a4686..0c5eac01bf2e 100644
--- a/sound/soc/Makefile
+++ b/sound/soc/Makefile
@@ -1,4 +1,4 @@
1snd-soc-core-objs := soc-core.o soc-dapm.o soc-jack.o 1snd-soc-core-objs := soc-core.o soc-dapm.o soc-jack.o soc-cache.o
2 2
3obj-$(CONFIG_SND_SOC) += snd-soc-core.o 3obj-$(CONFIG_SND_SOC) += snd-soc-core.o
4obj-$(CONFIG_SND_SOC) += codecs/ 4obj-$(CONFIG_SND_SOC) += codecs/
@@ -7,8 +7,10 @@ obj-$(CONFIG_SND_SOC) += au1x/
7obj-$(CONFIG_SND_SOC) += blackfin/ 7obj-$(CONFIG_SND_SOC) += blackfin/
8obj-$(CONFIG_SND_SOC) += davinci/ 8obj-$(CONFIG_SND_SOC) += davinci/
9obj-$(CONFIG_SND_SOC) += fsl/ 9obj-$(CONFIG_SND_SOC) += fsl/
10obj-$(CONFIG_SND_SOC) += imx/
10obj-$(CONFIG_SND_SOC) += omap/ 11obj-$(CONFIG_SND_SOC) += omap/
11obj-$(CONFIG_SND_SOC) += pxa/ 12obj-$(CONFIG_SND_SOC) += pxa/
12obj-$(CONFIG_SND_SOC) += s3c24xx/ 13obj-$(CONFIG_SND_SOC) += s3c24xx/
14obj-$(CONFIG_SND_SOC) += s6000/
13obj-$(CONFIG_SND_SOC) += sh/ 15obj-$(CONFIG_SND_SOC) += sh/
14obj-$(CONFIG_SND_SOC) += imx/ 16obj-$(CONFIG_SND_SOC) += txx9/
diff --git a/sound/soc/atmel/Kconfig b/sound/soc/atmel/Kconfig
index a608d7009dbd..e720d5e6f04c 100644
--- a/sound/soc/atmel/Kconfig
+++ b/sound/soc/atmel/Kconfig
@@ -41,3 +41,11 @@ config SND_AT32_SOC_PLAYPAQ_SLAVE
41 and FRAME signals on the PlayPaq. Unless you want to play 41 and FRAME signals on the PlayPaq. Unless you want to play
42 with the AT32 as the SSC master, you probably want to say N here, 42 with the AT32 as the SSC master, you probably want to say N here,
43 as this will give you better sound quality. 43 as this will give you better sound quality.
44
45config SND_AT91_SOC_AFEB9260
46 tristate "SoC Audio support for AFEB9260 board"
47 depends on ARCH_AT91 && MACH_AFEB9260 && SND_ATMEL_SOC
48 select SND_ATMEL_SOC_SSC
49 select SND_SOC_TLV320AIC23
50 help
51 Say Y here to support sound on AFEB9260 board.
diff --git a/sound/soc/atmel/Makefile b/sound/soc/atmel/Makefile
index f54a7cc68e66..e7ea56bd5f82 100644
--- a/sound/soc/atmel/Makefile
+++ b/sound/soc/atmel/Makefile
@@ -13,3 +13,4 @@ snd-soc-playpaq-objs := playpaq_wm8510.o
13 13
14obj-$(CONFIG_SND_AT91_SOC_SAM9G20_WM8731) += snd-soc-sam9g20-wm8731.o 14obj-$(CONFIG_SND_AT91_SOC_SAM9G20_WM8731) += snd-soc-sam9g20-wm8731.o
15obj-$(CONFIG_SND_AT32_SOC_PLAYPAQ) += snd-soc-playpaq.o 15obj-$(CONFIG_SND_AT32_SOC_PLAYPAQ) += snd-soc-playpaq.o
16obj-$(CONFIG_SND_AT91_SOC_AFEB9260) += snd-soc-afeb9260.o
diff --git a/sound/soc/atmel/playpaq_wm8510.c b/sound/soc/atmel/playpaq_wm8510.c
index 70657534e6b1..9eb610c2ba91 100644
--- a/sound/soc/atmel/playpaq_wm8510.c
+++ b/sound/soc/atmel/playpaq_wm8510.c
@@ -117,7 +117,7 @@ static struct ssc_clock_data playpaq_wm8510_calc_ssc_clock(
117 * Find actual rate, compare to requested rate 117 * Find actual rate, compare to requested rate
118 */ 118 */
119 actual_rate = (cd.ssc_rate / (cd.cmr_div * 2)) / (2 * (cd.period + 1)); 119 actual_rate = (cd.ssc_rate / (cd.cmr_div * 2)) / (2 * (cd.period + 1));
120 pr_debug("playpaq_wm8510: Request rate = %d, actual rate = %d\n", 120 pr_debug("playpaq_wm8510: Request rate = %u, actual rate = %u\n",
121 rate, actual_rate); 121 rate, actual_rate);
122 122
123 123
diff --git a/sound/soc/atmel/sam9g20_wm8731.c b/sound/soc/atmel/sam9g20_wm8731.c
index 173a239a541c..130b12118d4f 100644
--- a/sound/soc/atmel/sam9g20_wm8731.c
+++ b/sound/soc/atmel/sam9g20_wm8731.c
@@ -56,30 +56,14 @@
56 56
57#define MCLK_RATE 12000000 57#define MCLK_RATE 12000000
58 58
59static struct clk *mclk; 59/*
60 60 * As shipped the board does not have inputs. However, it is relatively
61static int at91sam9g20ek_startup(struct snd_pcm_substream *substream) 61 * straightforward to modify the board to hook them up so support is left
62{ 62 * in the driver.
63 struct snd_soc_pcm_runtime *rtd = snd_pcm_substream_chip(substream); 63 */
64 struct snd_soc_dai *codec_dai = rtd->dai->codec_dai; 64#undef ENABLE_MIC_INPUT
65 int ret;
66
67 ret = snd_soc_dai_set_sysclk(codec_dai, WM8731_SYSCLK,
68 MCLK_RATE, SND_SOC_CLOCK_IN);
69 if (ret < 0) {
70 clk_disable(mclk);
71 return ret;
72 }
73
74 return 0;
75}
76
77static void at91sam9g20ek_shutdown(struct snd_pcm_substream *substream)
78{
79 struct snd_soc_pcm_runtime *rtd = snd_pcm_substream_chip(substream);
80 65
81 dev_dbg(rtd->socdev->dev, "shutdown"); 66static struct clk *mclk;
82}
83 67
84static int at91sam9g20ek_hw_params(struct snd_pcm_substream *substream, 68static int at91sam9g20ek_hw_params(struct snd_pcm_substream *substream,
85 struct snd_pcm_hw_params *params) 69 struct snd_pcm_hw_params *params)
@@ -87,102 +71,17 @@ static int at91sam9g20ek_hw_params(struct snd_pcm_substream *substream,
87 struct snd_soc_pcm_runtime *rtd = substream->private_data; 71 struct snd_soc_pcm_runtime *rtd = substream->private_data;
88 struct snd_soc_dai *codec_dai = rtd->dai->codec_dai; 72 struct snd_soc_dai *codec_dai = rtd->dai->codec_dai;
89 struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai; 73 struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai;
90 struct atmel_ssc_info *ssc_p = cpu_dai->private_data;
91 struct ssc_device *ssc = ssc_p->ssc;
92 int ret; 74 int ret;
93 75
94 unsigned int rate;
95 int cmr_div, period;
96
97 if (ssc == NULL) {
98 printk(KERN_INFO "at91sam9g20ek_hw_params: ssc is NULL!\n");
99 return -EINVAL;
100 }
101
102 /* set codec DAI configuration */ 76 /* set codec DAI configuration */
103 ret = snd_soc_dai_set_fmt(codec_dai, SND_SOC_DAIFMT_I2S | 77 ret = snd_soc_dai_set_fmt(codec_dai, SND_SOC_DAIFMT_I2S |
104 SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBS_CFS); 78 SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBM_CFM);
105 if (ret < 0) 79 if (ret < 0)
106 return ret; 80 return ret;
107 81
108 /* set cpu DAI configuration */ 82 /* set cpu DAI configuration */
109 ret = snd_soc_dai_set_fmt(cpu_dai, SND_SOC_DAIFMT_I2S | 83 ret = snd_soc_dai_set_fmt(cpu_dai, SND_SOC_DAIFMT_I2S |
110 SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBS_CFS); 84 SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBM_CFM);
111 if (ret < 0)
112 return ret;
113
114 /*
115 * The SSC clock dividers depend on the sample rate. The CMR.DIV
116 * field divides the system master clock MCK to drive the SSC TK
117 * signal which provides the codec BCLK. The TCMR.PERIOD and
118 * RCMR.PERIOD fields further divide the BCLK signal to drive
119 * the SSC TF and RF signals which provide the codec DACLRC and
120 * ADCLRC clocks.
121 *
122 * The dividers were determined through trial and error, where a
123 * CMR.DIV value is chosen such that the resulting BCLK value is
124 * divisible, or almost divisible, by (2 * sample rate), and then
125 * the TCMR.PERIOD or RCMR.PERIOD is BCLK / (2 * sample rate) - 1.
126 */
127 rate = params_rate(params);
128
129 switch (rate) {
130 case 8000:
131 cmr_div = 55; /* BCLK = 133MHz/(2*55) = 1.209MHz */
132 period = 74; /* LRC = BCLK/(2*(74+1)) ~= 8060,6Hz */
133 break;
134 case 11025:
135 cmr_div = 67; /* BCLK = 133MHz/(2*60) = 1.108MHz */
136 period = 45; /* LRC = BCLK/(2*(49+1)) = 11083,3Hz */
137 break;
138 case 16000:
139 cmr_div = 63; /* BCLK = 133MHz/(2*63) = 1.055MHz */
140 period = 32; /* LRC = BCLK/(2*(32+1)) = 15993,2Hz */
141 break;
142 case 22050:
143 cmr_div = 52; /* BCLK = 133MHz/(2*52) = 1.278MHz */
144 period = 28; /* LRC = BCLK/(2*(28+1)) = 22049Hz */
145 break;
146 case 32000:
147 cmr_div = 66; /* BCLK = 133MHz/(2*66) = 1.007MHz */
148 period = 15; /* LRC = BCLK/(2*(15+1)) = 31486,742Hz */
149 break;
150 case 44100:
151 cmr_div = 29; /* BCLK = 133MHz/(2*29) = 2.293MHz */
152 period = 25; /* LRC = BCLK/(2*(25+1)) = 44098Hz */
153 break;
154 case 48000:
155 cmr_div = 33; /* BCLK = 133MHz/(2*33) = 2.015MHz */
156 period = 20; /* LRC = BCLK/(2*(20+1)) = 47979,79Hz */
157 break;
158 case 88200:
159 cmr_div = 29; /* BCLK = 133MHz/(2*29) = 2.293MHz */
160 period = 12; /* LRC = BCLK/(2*(12+1)) = 88196Hz */
161 break;
162 case 96000:
163 cmr_div = 23; /* BCLK = 133MHz/(2*23) = 2.891MHz */
164 period = 14; /* LRC = BCLK/(2*(14+1)) = 96376Hz */
165 break;
166 default:
167 printk(KERN_WARNING "unsupported rate %d"
168 " on at91sam9g20ek board\n", rate);
169 return -EINVAL;
170 }
171
172 /* set the MCK divider for BCLK */
173 ret = snd_soc_dai_set_clkdiv(cpu_dai, ATMEL_SSC_CMR_DIV, cmr_div);
174 if (ret < 0)
175 return ret;
176
177 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
178 /* set the BCLK divider for DACLRC */
179 ret = snd_soc_dai_set_clkdiv(cpu_dai,
180 ATMEL_SSC_TCMR_PERIOD, period);
181 } else {
182 /* set the BCLK divider for ADCLRC */
183 ret = snd_soc_dai_set_clkdiv(cpu_dai,
184 ATMEL_SSC_RCMR_PERIOD, period);
185 }
186 if (ret < 0) 85 if (ret < 0)
187 return ret; 86 return ret;
188 87
@@ -190,9 +89,7 @@ static int at91sam9g20ek_hw_params(struct snd_pcm_substream *substream,
190} 89}
191 90
192static struct snd_soc_ops at91sam9g20ek_ops = { 91static struct snd_soc_ops at91sam9g20ek_ops = {
193 .startup = at91sam9g20ek_startup,
194 .hw_params = at91sam9g20ek_hw_params, 92 .hw_params = at91sam9g20ek_hw_params,
195 .shutdown = at91sam9g20ek_shutdown,
196}; 93};
197 94
198static int at91sam9g20ek_set_bias_level(struct snd_soc_card *card, 95static int at91sam9g20ek_set_bias_level(struct snd_soc_card *card,
@@ -241,10 +138,20 @@ static const struct snd_soc_dapm_route intercon[] = {
241 */ 138 */
242static int at91sam9g20ek_wm8731_init(struct snd_soc_codec *codec) 139static int at91sam9g20ek_wm8731_init(struct snd_soc_codec *codec)
243{ 140{
141 struct snd_soc_dai *codec_dai = &codec->dai[0];
142 int ret;
143
244 printk(KERN_DEBUG 144 printk(KERN_DEBUG
245 "at91sam9g20ek_wm8731 " 145 "at91sam9g20ek_wm8731 "
246 ": at91sam9g20ek_wm8731_init() called\n"); 146 ": at91sam9g20ek_wm8731_init() called\n");
247 147
148 ret = snd_soc_dai_set_sysclk(codec_dai, WM8731_SYSCLK,
149 MCLK_RATE, SND_SOC_CLOCK_IN);
150 if (ret < 0) {
151 printk(KERN_ERR "Failed to set WM8731 SYSCLK: %d\n", ret);
152 return ret;
153 }
154
248 /* Add specific widgets */ 155 /* Add specific widgets */
249 snd_soc_dapm_new_controls(codec, at91sam9g20ek_dapm_widgets, 156 snd_soc_dapm_new_controls(codec, at91sam9g20ek_dapm_widgets,
250 ARRAY_SIZE(at91sam9g20ek_dapm_widgets)); 157 ARRAY_SIZE(at91sam9g20ek_dapm_widgets));
@@ -255,8 +162,13 @@ static int at91sam9g20ek_wm8731_init(struct snd_soc_codec *codec)
255 snd_soc_dapm_nc_pin(codec, "RLINEIN"); 162 snd_soc_dapm_nc_pin(codec, "RLINEIN");
256 snd_soc_dapm_nc_pin(codec, "LLINEIN"); 163 snd_soc_dapm_nc_pin(codec, "LLINEIN");
257 164
258 /* always connected */ 165#ifdef ENABLE_MIC_INPUT
259 snd_soc_dapm_enable_pin(codec, "Int Mic"); 166 snd_soc_dapm_enable_pin(codec, "Int Mic");
167#else
168 snd_soc_dapm_nc_pin(codec, "Int Mic");
169#endif
170
171 /* always connected */
260 snd_soc_dapm_enable_pin(codec, "Ext Spk"); 172 snd_soc_dapm_enable_pin(codec, "Ext Spk");
261 173
262 snd_soc_dapm_sync(codec); 174 snd_soc_dapm_sync(codec);
diff --git a/sound/soc/atmel/snd-soc-afeb9260.c b/sound/soc/atmel/snd-soc-afeb9260.c
new file mode 100644
index 000000000000..23349de27313
--- /dev/null
+++ b/sound/soc/atmel/snd-soc-afeb9260.c
@@ -0,0 +1,203 @@
1/*
2 * afeb9260.c -- SoC audio for AFEB9260
3 *
4 * Copyright (C) 2009 Sergey Lapin <slapin@ossfans.org>
5 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License
8 * version 2 as published by the Free Software Foundation.
9 *
10 * This program is distributed in the hope that it will be useful, but
11 * WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
18 * 02110-1301 USA
19 *
20 */
21
22#include <linux/module.h>
23#include <linux/moduleparam.h>
24#include <linux/kernel.h>
25#include <linux/clk.h>
26#include <linux/platform_device.h>
27
28#include <linux/atmel-ssc.h>
29#include <sound/core.h>
30#include <sound/pcm.h>
31#include <sound/pcm_params.h>
32#include <sound/soc.h>
33#include <sound/soc-dapm.h>
34
35#include <asm/mach-types.h>
36#include <mach/hardware.h>
37#include <linux/gpio.h>
38
39#include "../codecs/tlv320aic23.h"
40#include "atmel-pcm.h"
41#include "atmel_ssc_dai.h"
42
43#define CODEC_CLOCK 12000000
44
45static int afeb9260_hw_params(struct snd_pcm_substream *substream,
46 struct snd_pcm_hw_params *params)
47{
48 struct snd_soc_pcm_runtime *rtd = substream->private_data;
49 struct snd_soc_dai *codec_dai = rtd->dai->codec_dai;
50 struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai;
51 int err;
52
53 /* Set codec DAI configuration */
54 err = snd_soc_dai_set_fmt(codec_dai,
55 SND_SOC_DAIFMT_I2S|
56 SND_SOC_DAIFMT_NB_IF |
57 SND_SOC_DAIFMT_CBM_CFM);
58 if (err < 0) {
59 printk(KERN_ERR "can't set codec DAI configuration\n");
60 return err;
61 }
62
63 /* Set cpu DAI configuration */
64 err = snd_soc_dai_set_fmt(cpu_dai,
65 SND_SOC_DAIFMT_I2S |
66 SND_SOC_DAIFMT_NB_IF |
67 SND_SOC_DAIFMT_CBM_CFM);
68 if (err < 0) {
69 printk(KERN_ERR "can't set cpu DAI configuration\n");
70 return err;
71 }
72
73 /* Set the codec system clock for DAC and ADC */
74 err =
75 snd_soc_dai_set_sysclk(codec_dai, 0, CODEC_CLOCK, SND_SOC_CLOCK_IN);
76
77 if (err < 0) {
78 printk(KERN_ERR "can't set codec system clock\n");
79 return err;
80 }
81
82 return err;
83}
84
85static struct snd_soc_ops afeb9260_ops = {
86 .hw_params = afeb9260_hw_params,
87};
88
89static const struct snd_soc_dapm_widget tlv320aic23_dapm_widgets[] = {
90 SND_SOC_DAPM_HP("Headphone Jack", NULL),
91 SND_SOC_DAPM_LINE("Line In", NULL),
92 SND_SOC_DAPM_MIC("Mic Jack", NULL),
93};
94
95static const struct snd_soc_dapm_route audio_map[] = {
96 {"Headphone Jack", NULL, "LHPOUT"},
97 {"Headphone Jack", NULL, "RHPOUT"},
98
99 {"LLINEIN", NULL, "Line In"},
100 {"RLINEIN", NULL, "Line In"},
101
102 {"MICIN", NULL, "Mic Jack"},
103};
104
105static int afeb9260_tlv320aic23_init(struct snd_soc_codec *codec)
106{
107
108 /* Add afeb9260 specific widgets */
109 snd_soc_dapm_new_controls(codec, tlv320aic23_dapm_widgets,
110 ARRAY_SIZE(tlv320aic23_dapm_widgets));
111
112 /* Set up afeb9260 specific audio path audio_map */
113 snd_soc_dapm_add_routes(codec, audio_map, ARRAY_SIZE(audio_map));
114
115 snd_soc_dapm_enable_pin(codec, "Headphone Jack");
116 snd_soc_dapm_enable_pin(codec, "Line In");
117 snd_soc_dapm_enable_pin(codec, "Mic Jack");
118
119 snd_soc_dapm_sync(codec);
120
121 return 0;
122}
123
124/* Digital audio interface glue - connects codec <--> CPU */
125static struct snd_soc_dai_link afeb9260_dai = {
126 .name = "TLV320AIC23",
127 .stream_name = "AIC23",
128 .cpu_dai = &atmel_ssc_dai[0],
129 .codec_dai = &tlv320aic23_dai,
130 .init = afeb9260_tlv320aic23_init,
131 .ops = &afeb9260_ops,
132};
133
134/* Audio machine driver */
135static struct snd_soc_card snd_soc_machine_afeb9260 = {
136 .name = "AFEB9260",
137 .platform = &atmel_soc_platform,
138 .dai_link = &afeb9260_dai,
139 .num_links = 1,
140};
141
142/* Audio subsystem */
143static struct snd_soc_device afeb9260_snd_devdata = {
144 .card = &snd_soc_machine_afeb9260,
145 .codec_dev = &soc_codec_dev_tlv320aic23,
146};
147
148static struct platform_device *afeb9260_snd_device;
149
150static int __init afeb9260_soc_init(void)
151{
152 int err;
153 struct device *dev;
154 struct atmel_ssc_info *ssc_p = afeb9260_dai.cpu_dai->private_data;
155 struct ssc_device *ssc = NULL;
156
157 if (!(machine_is_afeb9260()))
158 return -ENODEV;
159
160 ssc = ssc_request(0);
161 if (IS_ERR(ssc)) {
162 printk(KERN_ERR "ASoC: Failed to request SSC 0\n");
163 err = PTR_ERR(ssc);
164 ssc = NULL;
165 goto err_ssc;
166 }
167 ssc_p->ssc = ssc;
168
169 afeb9260_snd_device = platform_device_alloc("soc-audio", -1);
170 if (!afeb9260_snd_device) {
171 printk(KERN_ERR "ASoC: Platform device allocation failed\n");
172 return -ENOMEM;
173 }
174
175 platform_set_drvdata(afeb9260_snd_device, &afeb9260_snd_devdata);
176 afeb9260_snd_devdata.dev = &afeb9260_snd_device->dev;
177 err = platform_device_add(afeb9260_snd_device);
178 if (err)
179 goto err1;
180
181 dev = &afeb9260_snd_device->dev;
182
183 return 0;
184err1:
185 platform_device_del(afeb9260_snd_device);
186 platform_device_put(afeb9260_snd_device);
187err_ssc:
188 return err;
189
190}
191
192static void __exit afeb9260_soc_exit(void)
193{
194 platform_device_unregister(afeb9260_snd_device);
195}
196
197module_init(afeb9260_soc_init);
198module_exit(afeb9260_soc_exit);
199
200MODULE_AUTHOR("Sergey Lapin <slapin@ossfans.org>");
201MODULE_DESCRIPTION("ALSA SoC for AFEB9260");
202MODULE_LICENSE("GPL");
203
diff --git a/sound/soc/blackfin/Kconfig b/sound/soc/blackfin/Kconfig
index 811596f4c092..8a4de4de30f2 100644
--- a/sound/soc/blackfin/Kconfig
+++ b/sound/soc/blackfin/Kconfig
@@ -7,6 +7,15 @@ config SND_BF5XX_I2S
7 mode (supports single stereo In/Out). 7 mode (supports single stereo In/Out).
8 You will also need to select the audio interfaces to support below. 8 You will also need to select the audio interfaces to support below.
9 9
10config SND_BF5XX_TDM
11 tristate "SoC I2S(TDM mode) Audio for the ADI BF5xx chip"
12 depends on (BLACKFIN && SND_SOC)
13 help
14 Say Y or M if you want to add support for codecs attached to
15 the Blackfin SPORT (synchronous serial ports) interface in TDM
16 mode.
17 You will also need to select the audio interfaces to support below.
18
10config SND_BF5XX_SOC_SSM2602 19config SND_BF5XX_SOC_SSM2602
11 tristate "SoC SSM2602 Audio support for BF52x ezkit" 20 tristate "SoC SSM2602 Audio support for BF52x ezkit"
12 depends on SND_BF5XX_I2S 21 depends on SND_BF5XX_I2S
@@ -69,6 +78,10 @@ config SND_BF5XX_SOC_I2S
69 tristate 78 tristate
70 select SND_BF5XX_SOC_SPORT 79 select SND_BF5XX_SOC_SPORT
71 80
81config SND_BF5XX_SOC_TDM
82 tristate
83 select SND_BF5XX_SOC_SPORT
84
72config SND_BF5XX_SOC_AC97 85config SND_BF5XX_SOC_AC97
73 tristate 86 tristate
74 select AC97_BUS 87 select AC97_BUS
@@ -83,9 +96,17 @@ config SND_BF5XX_SOC_AD1980
83 help 96 help
84 Say Y if you want to add support for SoC audio on BF5xx STAMP/EZKIT. 97 Say Y if you want to add support for SoC audio on BF5xx STAMP/EZKIT.
85 98
99config SND_BF5XX_SOC_AD1938
100 tristate "SoC AD1938 Audio support for Blackfin"
101 depends on SND_BF5XX_TDM
102 select SND_BF5XX_SOC_TDM
103 select SND_SOC_AD1938
104 help
105 Say Y if you want to add support for AD1938 codec on Blackfin.
106
86config SND_BF5XX_SPORT_NUM 107config SND_BF5XX_SPORT_NUM
87 int "Set a SPORT for Sound chip" 108 int "Set a SPORT for Sound chip"
88 depends on (SND_BF5XX_I2S || SND_BF5XX_AC97) 109 depends on (SND_BF5XX_I2S || SND_BF5XX_AC97 || SND_BF5XX_TDM)
89 range 0 3 if BF54x 110 range 0 3 if BF54x
90 range 0 1 if !BF54x 111 range 0 1 if !BF54x
91 default 0 112 default 0
diff --git a/sound/soc/blackfin/Makefile b/sound/soc/blackfin/Makefile
index 97bb37a6359c..f4d760741fab 100644
--- a/sound/soc/blackfin/Makefile
+++ b/sound/soc/blackfin/Makefile
@@ -1,21 +1,27 @@
1# Blackfin Platform Support 1# Blackfin Platform Support
2snd-bf5xx-ac97-objs := bf5xx-ac97-pcm.o 2snd-bf5xx-ac97-objs := bf5xx-ac97-pcm.o
3snd-bf5xx-i2s-objs := bf5xx-i2s-pcm.o 3snd-bf5xx-i2s-objs := bf5xx-i2s-pcm.o
4snd-bf5xx-tdm-objs := bf5xx-tdm-pcm.o
4snd-soc-bf5xx-sport-objs := bf5xx-sport.o 5snd-soc-bf5xx-sport-objs := bf5xx-sport.o
5snd-soc-bf5xx-ac97-objs := bf5xx-ac97.o 6snd-soc-bf5xx-ac97-objs := bf5xx-ac97.o
6snd-soc-bf5xx-i2s-objs := bf5xx-i2s.o 7snd-soc-bf5xx-i2s-objs := bf5xx-i2s.o
8snd-soc-bf5xx-tdm-objs := bf5xx-tdm.o
7 9
8obj-$(CONFIG_SND_BF5XX_AC97) += snd-bf5xx-ac97.o 10obj-$(CONFIG_SND_BF5XX_AC97) += snd-bf5xx-ac97.o
9obj-$(CONFIG_SND_BF5XX_I2S) += snd-bf5xx-i2s.o 11obj-$(CONFIG_SND_BF5XX_I2S) += snd-bf5xx-i2s.o
12obj-$(CONFIG_SND_BF5XX_TDM) += snd-bf5xx-tdm.o
10obj-$(CONFIG_SND_BF5XX_SOC_SPORT) += snd-soc-bf5xx-sport.o 13obj-$(CONFIG_SND_BF5XX_SOC_SPORT) += snd-soc-bf5xx-sport.o
11obj-$(CONFIG_SND_BF5XX_SOC_AC97) += snd-soc-bf5xx-ac97.o 14obj-$(CONFIG_SND_BF5XX_SOC_AC97) += snd-soc-bf5xx-ac97.o
12obj-$(CONFIG_SND_BF5XX_SOC_I2S) += snd-soc-bf5xx-i2s.o 15obj-$(CONFIG_SND_BF5XX_SOC_I2S) += snd-soc-bf5xx-i2s.o
16obj-$(CONFIG_SND_BF5XX_SOC_TDM) += snd-soc-bf5xx-tdm.o
13 17
14# Blackfin Machine Support 18# Blackfin Machine Support
15snd-ad1980-objs := bf5xx-ad1980.o 19snd-ad1980-objs := bf5xx-ad1980.o
16snd-ssm2602-objs := bf5xx-ssm2602.o 20snd-ssm2602-objs := bf5xx-ssm2602.o
17snd-ad73311-objs := bf5xx-ad73311.o 21snd-ad73311-objs := bf5xx-ad73311.o
22snd-ad1938-objs := bf5xx-ad1938.o
18 23
19obj-$(CONFIG_SND_BF5XX_SOC_AD1980) += snd-ad1980.o 24obj-$(CONFIG_SND_BF5XX_SOC_AD1980) += snd-ad1980.o
20obj-$(CONFIG_SND_BF5XX_SOC_SSM2602) += snd-ssm2602.o 25obj-$(CONFIG_SND_BF5XX_SOC_SSM2602) += snd-ssm2602.o
21obj-$(CONFIG_SND_BF5XX_SOC_AD73311) += snd-ad73311.o 26obj-$(CONFIG_SND_BF5XX_SOC_AD73311) += snd-ad73311.o
27obj-$(CONFIG_SND_BF5XX_SOC_AD1938) += snd-ad1938.o
diff --git a/sound/soc/blackfin/bf5xx-ac97.c b/sound/soc/blackfin/bf5xx-ac97.c
index 8a935f2d1767..2758b9017a7f 100644
--- a/sound/soc/blackfin/bf5xx-ac97.c
+++ b/sound/soc/blackfin/bf5xx-ac97.c
@@ -31,6 +31,15 @@
31#include "bf5xx-sport.h" 31#include "bf5xx-sport.h"
32#include "bf5xx-ac97.h" 32#include "bf5xx-ac97.h"
33 33
34/* Anomaly notes:
35 * 05000250 - AD1980 is running in TDM mode and RFS/TFS are generated by SPORT
36 * contrtoller. But, RFSDIV and TFSDIV are always set to 16*16-1,
37 * while the max AC97 data size is 13*16. The DIV is always larger
38 * than data size. AD73311 and ad2602 are not running in TDM mode.
39 * AD1836 and AD73322 depend on external RFS/TFS only. So, this
40 * anomaly does not affect blackfin sound drivers.
41*/
42
34static int *cmd_count; 43static int *cmd_count;
35static int sport_num = CONFIG_SND_BF5XX_SPORT_NUM; 44static int sport_num = CONFIG_SND_BF5XX_SPORT_NUM;
36 45
@@ -268,28 +277,24 @@ static int bf5xx_ac97_resume(struct snd_soc_dai *dai)
268 if (!dai->active) 277 if (!dai->active)
269 return 0; 278 return 0;
270 279
271 ret = sport_set_multichannel(sport_handle, 16, 0x1F, 1); 280 ret = sport_set_multichannel(sport, 16, 0x1F, 1);
272 if (ret) { 281 if (ret) {
273 pr_err("SPORT is busy!\n"); 282 pr_err("SPORT is busy!\n");
274 return -EBUSY; 283 return -EBUSY;
275 } 284 }
276 285
277 ret = sport_config_rx(sport_handle, IRFS, 0xF, 0, (16*16-1)); 286 ret = sport_config_rx(sport, IRFS, 0xF, 0, (16*16-1));
278 if (ret) { 287 if (ret) {
279 pr_err("SPORT is busy!\n"); 288 pr_err("SPORT is busy!\n");
280 return -EBUSY; 289 return -EBUSY;
281 } 290 }
282 291
283 ret = sport_config_tx(sport_handle, ITFS, 0xF, 0, (16*16-1)); 292 ret = sport_config_tx(sport, ITFS, 0xF, 0, (16*16-1));
284 if (ret) { 293 if (ret) {
285 pr_err("SPORT is busy!\n"); 294 pr_err("SPORT is busy!\n");
286 return -EBUSY; 295 return -EBUSY;
287 } 296 }
288 297
289 if (dai->capture.active)
290 sport_rx_start(sport);
291 if (dai->playback.active)
292 sport_tx_start(sport);
293 return 0; 298 return 0;
294} 299}
295 300
diff --git a/sound/soc/blackfin/bf5xx-ad1938.c b/sound/soc/blackfin/bf5xx-ad1938.c
new file mode 100644
index 000000000000..08269e91810c
--- /dev/null
+++ b/sound/soc/blackfin/bf5xx-ad1938.c
@@ -0,0 +1,142 @@
1/*
2 * File: sound/soc/blackfin/bf5xx-ad1938.c
3 * Author: Barry Song <Barry.Song@analog.com>
4 *
5 * Created: Thur June 4 2009
6 * Description: Board driver for ad1938 sound chip
7 *
8 * Bugs: Enter bugs at http://blackfin.uclinux.org/
9 *
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License as published by
12 * the Free Software Foundation; either version 2 of the License, or
13 * (at your option) any later version.
14 *
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU General Public License for more details.
19 *
20 * You should have received a copy of the GNU General Public License
21 * along with this program; if not, see the file COPYING, or write
22 * to the Free Software Foundation, Inc.,
23 * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
24 */
25
26#include <linux/module.h>
27#include <linux/moduleparam.h>
28#include <linux/device.h>
29#include <sound/core.h>
30#include <sound/pcm.h>
31#include <sound/soc.h>
32#include <sound/soc-dapm.h>
33#include <sound/pcm_params.h>
34
35#include <asm/blackfin.h>
36#include <asm/cacheflush.h>
37#include <asm/irq.h>
38#include <asm/dma.h>
39#include <asm/portmux.h>
40
41#include "../codecs/ad1938.h"
42#include "bf5xx-sport.h"
43
44#include "bf5xx-tdm-pcm.h"
45#include "bf5xx-tdm.h"
46
47static struct snd_soc_card bf5xx_ad1938;
48
49static int bf5xx_ad1938_startup(struct snd_pcm_substream *substream)
50{
51 struct snd_soc_pcm_runtime *rtd = substream->private_data;
52 struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai;
53
54 cpu_dai->private_data = sport_handle;
55 return 0;
56}
57
58static int bf5xx_ad1938_hw_params(struct snd_pcm_substream *substream,
59 struct snd_pcm_hw_params *params)
60{
61 struct snd_soc_pcm_runtime *rtd = substream->private_data;
62 struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai;
63 struct snd_soc_dai *codec_dai = rtd->dai->codec_dai;
64 int ret = 0;
65 /* set cpu DAI configuration */
66 ret = snd_soc_dai_set_fmt(cpu_dai, SND_SOC_DAIFMT_DSP_A |
67 SND_SOC_DAIFMT_IB_IF | SND_SOC_DAIFMT_CBM_CFM);
68 if (ret < 0)
69 return ret;
70
71 /* set codec DAI configuration */
72 ret = snd_soc_dai_set_fmt(codec_dai, SND_SOC_DAIFMT_DSP_A |
73 SND_SOC_DAIFMT_IB_IF | SND_SOC_DAIFMT_CBM_CFM);
74 if (ret < 0)
75 return ret;
76
77 /* set codec DAI slots, 8 channels, all channels are enabled */
78 ret = snd_soc_dai_set_tdm_slot(codec_dai, 0xFF, 8);
79 if (ret < 0)
80 return ret;
81
82 return 0;
83}
84
85static struct snd_soc_ops bf5xx_ad1938_ops = {
86 .startup = bf5xx_ad1938_startup,
87 .hw_params = bf5xx_ad1938_hw_params,
88};
89
90static struct snd_soc_dai_link bf5xx_ad1938_dai = {
91 .name = "ad1938",
92 .stream_name = "AD1938",
93 .cpu_dai = &bf5xx_tdm_dai,
94 .codec_dai = &ad1938_dai,
95 .ops = &bf5xx_ad1938_ops,
96};
97
98static struct snd_soc_card bf5xx_ad1938 = {
99 .name = "bf5xx_ad1938",
100 .platform = &bf5xx_tdm_soc_platform,
101 .dai_link = &bf5xx_ad1938_dai,
102 .num_links = 1,
103};
104
105static struct snd_soc_device bf5xx_ad1938_snd_devdata = {
106 .card = &bf5xx_ad1938,
107 .codec_dev = &soc_codec_dev_ad1938,
108};
109
110static struct platform_device *bfxx_ad1938_snd_device;
111
112static int __init bf5xx_ad1938_init(void)
113{
114 int ret;
115
116 bfxx_ad1938_snd_device = platform_device_alloc("soc-audio", -1);
117 if (!bfxx_ad1938_snd_device)
118 return -ENOMEM;
119
120 platform_set_drvdata(bfxx_ad1938_snd_device, &bf5xx_ad1938_snd_devdata);
121 bf5xx_ad1938_snd_devdata.dev = &bfxx_ad1938_snd_device->dev;
122 ret = platform_device_add(bfxx_ad1938_snd_device);
123
124 if (ret)
125 platform_device_put(bfxx_ad1938_snd_device);
126
127 return ret;
128}
129
130static void __exit bf5xx_ad1938_exit(void)
131{
132 platform_device_unregister(bfxx_ad1938_snd_device);
133}
134
135module_init(bf5xx_ad1938_init);
136module_exit(bf5xx_ad1938_exit);
137
138/* Module information */
139MODULE_AUTHOR("Barry Song");
140MODULE_DESCRIPTION("ALSA SoC AD1938 board driver");
141MODULE_LICENSE("GPL");
142
diff --git a/sound/soc/blackfin/bf5xx-ad73311.c b/sound/soc/blackfin/bf5xx-ad73311.c
index edfbdc024e66..9825b71d0e28 100644
--- a/sound/soc/blackfin/bf5xx-ad73311.c
+++ b/sound/soc/blackfin/bf5xx-ad73311.c
@@ -203,23 +203,23 @@ static struct snd_soc_device bf5xx_ad73311_snd_devdata = {
203 .codec_dev = &soc_codec_dev_ad73311, 203 .codec_dev = &soc_codec_dev_ad73311,
204}; 204};
205 205
206static struct platform_device *bf52x_ad73311_snd_device; 206static struct platform_device *bf5xx_ad73311_snd_device;
207 207
208static int __init bf5xx_ad73311_init(void) 208static int __init bf5xx_ad73311_init(void)
209{ 209{
210 int ret; 210 int ret;
211 211
212 pr_debug("%s enter\n", __func__); 212 pr_debug("%s enter\n", __func__);
213 bf52x_ad73311_snd_device = platform_device_alloc("soc-audio", -1); 213 bf5xx_ad73311_snd_device = platform_device_alloc("soc-audio", -1);
214 if (!bf52x_ad73311_snd_device) 214 if (!bf5xx_ad73311_snd_device)
215 return -ENOMEM; 215 return -ENOMEM;
216 216
217 platform_set_drvdata(bf52x_ad73311_snd_device, &bf5xx_ad73311_snd_devdata); 217 platform_set_drvdata(bf5xx_ad73311_snd_device, &bf5xx_ad73311_snd_devdata);
218 bf5xx_ad73311_snd_devdata.dev = &bf52x_ad73311_snd_device->dev; 218 bf5xx_ad73311_snd_devdata.dev = &bf5xx_ad73311_snd_device->dev;
219 ret = platform_device_add(bf52x_ad73311_snd_device); 219 ret = platform_device_add(bf5xx_ad73311_snd_device);
220 220
221 if (ret) 221 if (ret)
222 platform_device_put(bf52x_ad73311_snd_device); 222 platform_device_put(bf5xx_ad73311_snd_device);
223 223
224 return ret; 224 return ret;
225} 225}
@@ -227,7 +227,7 @@ static int __init bf5xx_ad73311_init(void)
227static void __exit bf5xx_ad73311_exit(void) 227static void __exit bf5xx_ad73311_exit(void)
228{ 228{
229 pr_debug("%s enter\n", __func__); 229 pr_debug("%s enter\n", __func__);
230 platform_device_unregister(bf52x_ad73311_snd_device); 230 platform_device_unregister(bf5xx_ad73311_snd_device);
231} 231}
232 232
233module_init(bf5xx_ad73311_init); 233module_init(bf5xx_ad73311_init);
diff --git a/sound/soc/blackfin/bf5xx-i2s.c b/sound/soc/blackfin/bf5xx-i2s.c
index 964824419678..876abade27e1 100644
--- a/sound/soc/blackfin/bf5xx-i2s.c
+++ b/sound/soc/blackfin/bf5xx-i2s.c
@@ -50,6 +50,7 @@ struct bf5xx_i2s_port {
50 u16 tcr2; 50 u16 tcr2;
51 u16 rcr2; 51 u16 rcr2;
52 int counter; 52 int counter;
53 int configured;
53}; 54};
54 55
55static struct bf5xx_i2s_port bf5xx_i2s; 56static struct bf5xx_i2s_port bf5xx_i2s;
@@ -168,7 +169,7 @@ static int bf5xx_i2s_hw_params(struct snd_pcm_substream *substream,
168 break; 169 break;
169 } 170 }
170 171
171 if (bf5xx_i2s.counter == 1) { 172 if (!bf5xx_i2s.configured) {
172 /* 173 /*
173 * TX and RX are not independent,they are enabled at the 174 * TX and RX are not independent,they are enabled at the
174 * same time, even if only one side is running. So, we 175 * same time, even if only one side is running. So, we
@@ -177,6 +178,7 @@ static int bf5xx_i2s_hw_params(struct snd_pcm_substream *substream,
177 * 178 *
178 * CPU DAI:slave mode. 179 * CPU DAI:slave mode.
179 */ 180 */
181 bf5xx_i2s.configured = 1;
180 ret = sport_config_rx(sport_handle, bf5xx_i2s.rcr1, 182 ret = sport_config_rx(sport_handle, bf5xx_i2s.rcr1,
181 bf5xx_i2s.rcr2, 0, 0); 183 bf5xx_i2s.rcr2, 0, 0);
182 if (ret) { 184 if (ret) {
@@ -200,6 +202,9 @@ static void bf5xx_i2s_shutdown(struct snd_pcm_substream *substream,
200{ 202{
201 pr_debug("%s enter\n", __func__); 203 pr_debug("%s enter\n", __func__);
202 bf5xx_i2s.counter--; 204 bf5xx_i2s.counter--;
205 /* No active stream, SPORT is allowed to be configured again. */
206 if (!bf5xx_i2s.counter)
207 bf5xx_i2s.configured = 0;
203} 208}
204 209
205static int bf5xx_i2s_probe(struct platform_device *pdev, 210static int bf5xx_i2s_probe(struct platform_device *pdev,
@@ -244,8 +249,7 @@ static int bf5xx_i2s_suspend(struct snd_soc_dai *dai)
244 return 0; 249 return 0;
245} 250}
246 251
247static int bf5xx_i2s_resume(struct platform_device *pdev, 252static int bf5xx_i2s_resume(struct snd_soc_dai *dai)
248 struct snd_soc_dai *dai)
249{ 253{
250 int ret; 254 int ret;
251 struct sport_device *sport = 255 struct sport_device *sport =
@@ -255,22 +259,18 @@ static int bf5xx_i2s_resume(struct platform_device *pdev,
255 if (!dai->active) 259 if (!dai->active)
256 return 0; 260 return 0;
257 261
258 ret = sport_config_rx(sport_handle, RFSR | RCKFE, RSFSE|0x1f, 0, 0); 262 ret = sport_config_rx(sport, RFSR | RCKFE, RSFSE|0x1f, 0, 0);
259 if (ret) { 263 if (ret) {
260 pr_err("SPORT is busy!\n"); 264 pr_err("SPORT is busy!\n");
261 return -EBUSY; 265 return -EBUSY;
262 } 266 }
263 267
264 ret = sport_config_tx(sport_handle, TFSR | TCKFE, TSFSE|0x1f, 0, 0); 268 ret = sport_config_tx(sport, TFSR | TCKFE, TSFSE|0x1f, 0, 0);
265 if (ret) { 269 if (ret) {
266 pr_err("SPORT is busy!\n"); 270 pr_err("SPORT is busy!\n");
267 return -EBUSY; 271 return -EBUSY;
268 } 272 }
269 273
270 if (dai->capture.active)
271 sport_rx_start(sport);
272 if (dai->playback.active)
273 sport_tx_start(sport);
274 return 0; 274 return 0;
275} 275}
276 276
diff --git a/sound/soc/blackfin/bf5xx-sport.c b/sound/soc/blackfin/bf5xx-sport.c
index b7953c8cf838..469ce7fab20c 100644
--- a/sound/soc/blackfin/bf5xx-sport.c
+++ b/sound/soc/blackfin/bf5xx-sport.c
@@ -190,7 +190,7 @@ static inline int sport_hook_rx_dummy(struct sport_device *sport)
190 desc = get_dma_next_desc_ptr(sport->dma_rx_chan); 190 desc = get_dma_next_desc_ptr(sport->dma_rx_chan);
191 /* Copy the descriptor which will be damaged to backup */ 191 /* Copy the descriptor which will be damaged to backup */
192 temp_desc = *desc; 192 temp_desc = *desc;
193 desc->x_count = 0xa; 193 desc->x_count = sport->dummy_count / 2;
194 desc->y_count = 0; 194 desc->y_count = 0;
195 desc->next_desc_addr = sport->dummy_rx_desc; 195 desc->next_desc_addr = sport->dummy_rx_desc;
196 local_irq_restore(flags); 196 local_irq_restore(flags);
@@ -309,7 +309,7 @@ static inline int sport_hook_tx_dummy(struct sport_device *sport)
309 desc = get_dma_next_desc_ptr(sport->dma_tx_chan); 309 desc = get_dma_next_desc_ptr(sport->dma_tx_chan);
310 /* Store the descriptor which will be damaged */ 310 /* Store the descriptor which will be damaged */
311 temp_desc = *desc; 311 temp_desc = *desc;
312 desc->x_count = 0xa; 312 desc->x_count = sport->dummy_count / 2;
313 desc->y_count = 0; 313 desc->y_count = 0;
314 desc->next_desc_addr = sport->dummy_tx_desc; 314 desc->next_desc_addr = sport->dummy_tx_desc;
315 local_irq_restore(flags); 315 local_irq_restore(flags);
diff --git a/sound/soc/blackfin/bf5xx-ssm2602.c b/sound/soc/blackfin/bf5xx-ssm2602.c
index bc0cdded7116..3a00fa4dbe6d 100644
--- a/sound/soc/blackfin/bf5xx-ssm2602.c
+++ b/sound/soc/blackfin/bf5xx-ssm2602.c
@@ -148,24 +148,24 @@ static struct snd_soc_device bf5xx_ssm2602_snd_devdata = {
148 .codec_data = &bf5xx_ssm2602_setup, 148 .codec_data = &bf5xx_ssm2602_setup,
149}; 149};
150 150
151static struct platform_device *bf52x_ssm2602_snd_device; 151static struct platform_device *bf5xx_ssm2602_snd_device;
152 152
153static int __init bf5xx_ssm2602_init(void) 153static int __init bf5xx_ssm2602_init(void)
154{ 154{
155 int ret; 155 int ret;
156 156
157 pr_debug("%s enter\n", __func__); 157 pr_debug("%s enter\n", __func__);
158 bf52x_ssm2602_snd_device = platform_device_alloc("soc-audio", -1); 158 bf5xx_ssm2602_snd_device = platform_device_alloc("soc-audio", -1);
159 if (!bf52x_ssm2602_snd_device) 159 if (!bf5xx_ssm2602_snd_device)
160 return -ENOMEM; 160 return -ENOMEM;
161 161
162 platform_set_drvdata(bf52x_ssm2602_snd_device, 162 platform_set_drvdata(bf5xx_ssm2602_snd_device,
163 &bf5xx_ssm2602_snd_devdata); 163 &bf5xx_ssm2602_snd_devdata);
164 bf5xx_ssm2602_snd_devdata.dev = &bf52x_ssm2602_snd_device->dev; 164 bf5xx_ssm2602_snd_devdata.dev = &bf5xx_ssm2602_snd_device->dev;
165 ret = platform_device_add(bf52x_ssm2602_snd_device); 165 ret = platform_device_add(bf5xx_ssm2602_snd_device);
166 166
167 if (ret) 167 if (ret)
168 platform_device_put(bf52x_ssm2602_snd_device); 168 platform_device_put(bf5xx_ssm2602_snd_device);
169 169
170 return ret; 170 return ret;
171} 171}
@@ -173,7 +173,7 @@ static int __init bf5xx_ssm2602_init(void)
173static void __exit bf5xx_ssm2602_exit(void) 173static void __exit bf5xx_ssm2602_exit(void)
174{ 174{
175 pr_debug("%s enter\n", __func__); 175 pr_debug("%s enter\n", __func__);
176 platform_device_unregister(bf52x_ssm2602_snd_device); 176 platform_device_unregister(bf5xx_ssm2602_snd_device);
177} 177}
178 178
179module_init(bf5xx_ssm2602_init); 179module_init(bf5xx_ssm2602_init);
diff --git a/sound/soc/blackfin/bf5xx-tdm-pcm.c b/sound/soc/blackfin/bf5xx-tdm-pcm.c
new file mode 100644
index 000000000000..ccb5e823bd18
--- /dev/null
+++ b/sound/soc/blackfin/bf5xx-tdm-pcm.c
@@ -0,0 +1,330 @@
1/*
2 * File: sound/soc/blackfin/bf5xx-tdm-pcm.c
3 * Author: Barry Song <Barry.Song@analog.com>
4 *
5 * Created: Tue June 06 2009
6 * Description: DMA driver for tdm codec
7 *
8 * Modified:
9 * Copyright 2009 Analog Devices Inc.
10 *
11 * Bugs: Enter bugs at http://blackfin.uclinux.org/
12 *
13 * This program is free software; you can redistribute it and/or modify
14 * it under the terms of the GNU General Public License as published by
15 * the Free Software Foundation; either version 2 of the License, or
16 * (at your option) any later version.
17 *
18 * This program is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU General Public License for more details.
22 *
23 * You should have received a copy of the GNU General Public License
24 * along with this program; if not, see the file COPYING, or write
25 * to the Free Software Foundation, Inc.,
26 * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
27 */
28
29#include <linux/module.h>
30#include <linux/init.h>
31#include <linux/platform_device.h>
32#include <linux/slab.h>
33#include <linux/dma-mapping.h>
34
35#include <sound/core.h>
36#include <sound/pcm.h>
37#include <sound/pcm_params.h>
38#include <sound/soc.h>
39
40#include <asm/dma.h>
41
42#include "bf5xx-tdm-pcm.h"
43#include "bf5xx-tdm.h"
44#include "bf5xx-sport.h"
45
46#define PCM_BUFFER_MAX 0x10000
47#define FRAGMENT_SIZE_MIN (4*1024)
48#define FRAGMENTS_MIN 2
49#define FRAGMENTS_MAX 32
50
51static void bf5xx_dma_irq(void *data)
52{
53 struct snd_pcm_substream *pcm = data;
54 snd_pcm_period_elapsed(pcm);
55}
56
57static const struct snd_pcm_hardware bf5xx_pcm_hardware = {
58 .info = (SNDRV_PCM_INFO_INTERLEAVED | SNDRV_PCM_INFO_BLOCK_TRANSFER |
59 SNDRV_PCM_INFO_RESUME),
60 .formats = SNDRV_PCM_FMTBIT_S32_LE,
61 .rates = SNDRV_PCM_RATE_48000,
62 .channels_min = 2,
63 .channels_max = 8,
64 .buffer_bytes_max = PCM_BUFFER_MAX,
65 .period_bytes_min = FRAGMENT_SIZE_MIN,
66 .period_bytes_max = PCM_BUFFER_MAX/2,
67 .periods_min = FRAGMENTS_MIN,
68 .periods_max = FRAGMENTS_MAX,
69};
70
71static int bf5xx_pcm_hw_params(struct snd_pcm_substream *substream,
72 struct snd_pcm_hw_params *params)
73{
74 size_t size = bf5xx_pcm_hardware.buffer_bytes_max;
75 snd_pcm_lib_malloc_pages(substream, size * 4);
76
77 return 0;
78}
79
80static int bf5xx_pcm_hw_free(struct snd_pcm_substream *substream)
81{
82 snd_pcm_lib_free_pages(substream);
83
84 return 0;
85}
86
87static int bf5xx_pcm_prepare(struct snd_pcm_substream *substream)
88{
89 struct snd_pcm_runtime *runtime = substream->runtime;
90 struct sport_device *sport = runtime->private_data;
91 int fragsize_bytes = frames_to_bytes(runtime, runtime->period_size);
92
93 fragsize_bytes /= runtime->channels;
94 /* inflate the fragsize to match the dma width of SPORT */
95 fragsize_bytes *= 8;
96
97 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
98 sport_set_tx_callback(sport, bf5xx_dma_irq, substream);
99 sport_config_tx_dma(sport, runtime->dma_area,
100 runtime->periods, fragsize_bytes);
101 } else {
102 sport_set_rx_callback(sport, bf5xx_dma_irq, substream);
103 sport_config_rx_dma(sport, runtime->dma_area,
104 runtime->periods, fragsize_bytes);
105 }
106
107 return 0;
108}
109
110static int bf5xx_pcm_trigger(struct snd_pcm_substream *substream, int cmd)
111{
112 struct snd_pcm_runtime *runtime = substream->runtime;
113 struct sport_device *sport = runtime->private_data;
114 int ret = 0;
115
116 switch (cmd) {
117 case SNDRV_PCM_TRIGGER_START:
118 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
119 sport_tx_start(sport);
120 else
121 sport_rx_start(sport);
122 break;
123 case SNDRV_PCM_TRIGGER_STOP:
124 case SNDRV_PCM_TRIGGER_SUSPEND:
125 case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
126 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
127 sport_tx_stop(sport);
128 else
129 sport_rx_stop(sport);
130 break;
131 default:
132 ret = -EINVAL;
133 }
134
135 return ret;
136}
137
138static snd_pcm_uframes_t bf5xx_pcm_pointer(struct snd_pcm_substream *substream)
139{
140 struct snd_pcm_runtime *runtime = substream->runtime;
141 struct sport_device *sport = runtime->private_data;
142 unsigned int diff;
143 snd_pcm_uframes_t frames;
144
145 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
146 diff = sport_curr_offset_tx(sport);
147 frames = diff / (8*4); /* 32 bytes per frame */
148 } else {
149 diff = sport_curr_offset_rx(sport);
150 frames = diff / (8*4);
151 }
152 return frames;
153}
154
155static int bf5xx_pcm_open(struct snd_pcm_substream *substream)
156{
157 struct snd_pcm_runtime *runtime = substream->runtime;
158 int ret = 0;
159
160 snd_soc_set_runtime_hwparams(substream, &bf5xx_pcm_hardware);
161
162 ret = snd_pcm_hw_constraint_integer(runtime,
163 SNDRV_PCM_HW_PARAM_PERIODS);
164 if (ret < 0)
165 goto out;
166
167 if (sport_handle != NULL)
168 runtime->private_data = sport_handle;
169 else {
170 pr_err("sport_handle is NULL\n");
171 ret = -ENODEV;
172 }
173out:
174 return ret;
175}
176
177static int bf5xx_pcm_copy(struct snd_pcm_substream *substream, int channel,
178 snd_pcm_uframes_t pos, void *buf, snd_pcm_uframes_t count)
179{
180 unsigned int *src;
181 unsigned int *dst;
182 int i;
183
184 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
185 src = buf;
186 dst = (unsigned int *)substream->runtime->dma_area;
187
188 dst += pos * 8;
189 while (count--) {
190 for (i = 0; i < substream->runtime->channels; i++)
191 *(dst + i) = *src++;
192 dst += 8;
193 }
194 } else {
195 src = (unsigned int *)substream->runtime->dma_area;
196 dst = buf;
197
198 src += pos * 8;
199 while (count--) {
200 for (i = 0; i < substream->runtime->channels; i++)
201 *dst++ = *(src+i);
202 src += 8;
203 }
204 }
205
206 return 0;
207}
208
209static int bf5xx_pcm_silence(struct snd_pcm_substream *substream,
210 int channel, snd_pcm_uframes_t pos, snd_pcm_uframes_t count)
211{
212 unsigned char *buf = substream->runtime->dma_area;
213 buf += pos * 8 * 4;
214 memset(buf, '\0', count * 8 * 4);
215
216 return 0;
217}
218
219
220struct snd_pcm_ops bf5xx_pcm_tdm_ops = {
221 .open = bf5xx_pcm_open,
222 .ioctl = snd_pcm_lib_ioctl,
223 .hw_params = bf5xx_pcm_hw_params,
224 .hw_free = bf5xx_pcm_hw_free,
225 .prepare = bf5xx_pcm_prepare,
226 .trigger = bf5xx_pcm_trigger,
227 .pointer = bf5xx_pcm_pointer,
228 .copy = bf5xx_pcm_copy,
229 .silence = bf5xx_pcm_silence,
230};
231
232static int bf5xx_pcm_preallocate_dma_buffer(struct snd_pcm *pcm, int stream)
233{
234 struct snd_pcm_substream *substream = pcm->streams[stream].substream;
235 struct snd_dma_buffer *buf = &substream->dma_buffer;
236 size_t size = bf5xx_pcm_hardware.buffer_bytes_max;
237
238 buf->dev.type = SNDRV_DMA_TYPE_DEV;
239 buf->dev.dev = pcm->card->dev;
240 buf->private_data = NULL;
241 buf->area = dma_alloc_coherent(pcm->card->dev, size * 4,
242 &buf->addr, GFP_KERNEL);
243 if (!buf->area) {
244 pr_err("Failed to allocate dma memory \
245 Please increase uncached DMA memory region\n");
246 return -ENOMEM;
247 }
248 buf->bytes = size;
249
250 if (stream == SNDRV_PCM_STREAM_PLAYBACK)
251 sport_handle->tx_buf = buf->area;
252 else
253 sport_handle->rx_buf = buf->area;
254
255 return 0;
256}
257
258static void bf5xx_pcm_free_dma_buffers(struct snd_pcm *pcm)
259{
260 struct snd_pcm_substream *substream;
261 struct snd_dma_buffer *buf;
262 int stream;
263
264 for (stream = 0; stream < 2; stream++) {
265 substream = pcm->streams[stream].substream;
266 if (!substream)
267 continue;
268
269 buf = &substream->dma_buffer;
270 if (!buf->area)
271 continue;
272 dma_free_coherent(NULL, buf->bytes, buf->area, 0);
273 buf->area = NULL;
274 }
275 if (sport_handle)
276 sport_done(sport_handle);
277}
278
279static u64 bf5xx_pcm_dmamask = DMA_BIT_MASK(32);
280
281static int bf5xx_pcm_tdm_new(struct snd_card *card, struct snd_soc_dai *dai,
282 struct snd_pcm *pcm)
283{
284 int ret = 0;
285
286 if (!card->dev->dma_mask)
287 card->dev->dma_mask = &bf5xx_pcm_dmamask;
288 if (!card->dev->coherent_dma_mask)
289 card->dev->coherent_dma_mask = DMA_BIT_MASK(32);
290
291 if (dai->playback.channels_min) {
292 ret = bf5xx_pcm_preallocate_dma_buffer(pcm,
293 SNDRV_PCM_STREAM_PLAYBACK);
294 if (ret)
295 goto out;
296 }
297
298 if (dai->capture.channels_min) {
299 ret = bf5xx_pcm_preallocate_dma_buffer(pcm,
300 SNDRV_PCM_STREAM_CAPTURE);
301 if (ret)
302 goto out;
303 }
304out:
305 return ret;
306}
307
308struct snd_soc_platform bf5xx_tdm_soc_platform = {
309 .name = "bf5xx-audio",
310 .pcm_ops = &bf5xx_pcm_tdm_ops,
311 .pcm_new = bf5xx_pcm_tdm_new,
312 .pcm_free = bf5xx_pcm_free_dma_buffers,
313};
314EXPORT_SYMBOL_GPL(bf5xx_tdm_soc_platform);
315
316static int __init bfin_pcm_tdm_init(void)
317{
318 return snd_soc_register_platform(&bf5xx_tdm_soc_platform);
319}
320module_init(bfin_pcm_tdm_init);
321
322static void __exit bfin_pcm_tdm_exit(void)
323{
324 snd_soc_unregister_platform(&bf5xx_tdm_soc_platform);
325}
326module_exit(bfin_pcm_tdm_exit);
327
328MODULE_AUTHOR("Barry Song");
329MODULE_DESCRIPTION("ADI Blackfin TDM PCM DMA module");
330MODULE_LICENSE("GPL");
diff --git a/sound/soc/blackfin/bf5xx-tdm-pcm.h b/sound/soc/blackfin/bf5xx-tdm-pcm.h
new file mode 100644
index 000000000000..ddc5047df88c
--- /dev/null
+++ b/sound/soc/blackfin/bf5xx-tdm-pcm.h
@@ -0,0 +1,21 @@
1/*
2 * sound/soc/blackfin/bf5xx-tdm-pcm.h -- ALSA PCM interface for the Blackfin
3 *
4 * Copyright 2009 Analog Device Inc.
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License version 2 as
8 * published by the Free Software Foundation.
9 */
10
11#ifndef _BF5XX_TDM_PCM_H
12#define _BF5XX_TDM_PCM_H
13
14struct bf5xx_pcm_dma_params {
15 char *name; /* stream identifier */
16};
17
18/* platform data */
19extern struct snd_soc_platform bf5xx_tdm_soc_platform;
20
21#endif
diff --git a/sound/soc/blackfin/bf5xx-tdm.c b/sound/soc/blackfin/bf5xx-tdm.c
new file mode 100644
index 000000000000..3096badf09a5
--- /dev/null
+++ b/sound/soc/blackfin/bf5xx-tdm.c
@@ -0,0 +1,343 @@
1/*
2 * File: sound/soc/blackfin/bf5xx-tdm.c
3 * Author: Barry Song <Barry.Song@analog.com>
4 *
5 * Created: Thurs June 04 2009
6 * Description: Blackfin I2S(TDM) CPU DAI driver
7 * Even though TDM mode can be as part of I2S DAI, but there
8 * are so much difference in configuration and data flow,
9 * it's very ugly to integrate I2S and TDM into a module
10 *
11 * Modified:
12 * Copyright 2009 Analog Devices Inc.
13 *
14 * Bugs: Enter bugs at http://blackfin.uclinux.org/
15 *
16 * This program is free software; you can redistribute it and/or modify
17 * it under the terms of the GNU General Public License as published by
18 * the Free Software Foundation; either version 2 of the License, or
19 * (at your option) any later version.
20 *
21 * This program is distributed in the hope that it will be useful,
22 * but WITHOUT ANY WARRANTY; without even the implied warranty of
23 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
24 * GNU General Public License for more details.
25 *
26 * You should have received a copy of the GNU General Public License
27 * along with this program; if not, see the file COPYING, or write
28 * to the Free Software Foundation, Inc.,
29 * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
30 */
31
32#include <linux/init.h>
33#include <linux/module.h>
34#include <linux/device.h>
35#include <sound/core.h>
36#include <sound/pcm.h>
37#include <sound/pcm_params.h>
38#include <sound/initval.h>
39#include <sound/soc.h>
40
41#include <asm/irq.h>
42#include <asm/portmux.h>
43#include <linux/mutex.h>
44#include <linux/gpio.h>
45
46#include "bf5xx-sport.h"
47#include "bf5xx-tdm.h"
48
49struct bf5xx_tdm_port {
50 u16 tcr1;
51 u16 rcr1;
52 u16 tcr2;
53 u16 rcr2;
54 int configured;
55};
56
57static struct bf5xx_tdm_port bf5xx_tdm;
58static int sport_num = CONFIG_SND_BF5XX_SPORT_NUM;
59
60static struct sport_param sport_params[2] = {
61 {
62 .dma_rx_chan = CH_SPORT0_RX,
63 .dma_tx_chan = CH_SPORT0_TX,
64 .err_irq = IRQ_SPORT0_ERROR,
65 .regs = (struct sport_register *)SPORT0_TCR1,
66 },
67 {
68 .dma_rx_chan = CH_SPORT1_RX,
69 .dma_tx_chan = CH_SPORT1_TX,
70 .err_irq = IRQ_SPORT1_ERROR,
71 .regs = (struct sport_register *)SPORT1_TCR1,
72 }
73};
74
75/*
76 * Setting the TFS pin selector for SPORT 0 based on whether the selected
77 * port id F or G. If the port is F then no conflict should exist for the
78 * TFS. When Port G is selected and EMAC then there is a conflict between
79 * the PHY interrupt line and TFS. Current settings prevent the conflict
80 * by ignoring the TFS pin when Port G is selected. This allows both
81 * ssm2602 using Port G and EMAC concurrently.
82 */
83#ifdef CONFIG_BF527_SPORT0_PORTF
84#define LOCAL_SPORT0_TFS (P_SPORT0_TFS)
85#else
86#define LOCAL_SPORT0_TFS (0)
87#endif
88
89static u16 sport_req[][7] = { {P_SPORT0_DTPRI, P_SPORT0_TSCLK, P_SPORT0_RFS,
90 P_SPORT0_DRPRI, P_SPORT0_RSCLK, LOCAL_SPORT0_TFS, 0},
91 {P_SPORT1_DTPRI, P_SPORT1_TSCLK, P_SPORT1_RFS, P_SPORT1_DRPRI,
92 P_SPORT1_RSCLK, P_SPORT1_TFS, 0} };
93
94static int bf5xx_tdm_set_dai_fmt(struct snd_soc_dai *cpu_dai,
95 unsigned int fmt)
96{
97 int ret = 0;
98
99 /* interface format:support TDM,slave mode */
100 switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
101 case SND_SOC_DAIFMT_DSP_A:
102 break;
103 default:
104 printk(KERN_ERR "%s: Unknown DAI format type\n", __func__);
105 ret = -EINVAL;
106 break;
107 }
108
109 switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
110 case SND_SOC_DAIFMT_CBM_CFM:
111 break;
112 case SND_SOC_DAIFMT_CBS_CFS:
113 case SND_SOC_DAIFMT_CBM_CFS:
114 case SND_SOC_DAIFMT_CBS_CFM:
115 ret = -EINVAL;
116 break;
117 default:
118 printk(KERN_ERR "%s: Unknown DAI master type\n", __func__);
119 ret = -EINVAL;
120 break;
121 }
122
123 return ret;
124}
125
126static int bf5xx_tdm_hw_params(struct snd_pcm_substream *substream,
127 struct snd_pcm_hw_params *params,
128 struct snd_soc_dai *dai)
129{
130 int ret = 0;
131
132 bf5xx_tdm.tcr2 &= ~0x1f;
133 bf5xx_tdm.rcr2 &= ~0x1f;
134 switch (params_format(params)) {
135 case SNDRV_PCM_FORMAT_S32_LE:
136 bf5xx_tdm.tcr2 |= 31;
137 bf5xx_tdm.rcr2 |= 31;
138 sport_handle->wdsize = 4;
139 break;
140 /* at present, we only support 32bit transfer */
141 default:
142 pr_err("not supported PCM format yet\n");
143 return -EINVAL;
144 break;
145 }
146
147 if (!bf5xx_tdm.configured) {
148 /*
149 * TX and RX are not independent,they are enabled at the
150 * same time, even if only one side is running. So, we
151 * need to configure both of them at the time when the first
152 * stream is opened.
153 *
154 * CPU DAI:slave mode.
155 */
156 ret = sport_config_rx(sport_handle, bf5xx_tdm.rcr1,
157 bf5xx_tdm.rcr2, 0, 0);
158 if (ret) {
159 pr_err("SPORT is busy!\n");
160 return -EBUSY;
161 }
162
163 ret = sport_config_tx(sport_handle, bf5xx_tdm.tcr1,
164 bf5xx_tdm.tcr2, 0, 0);
165 if (ret) {
166 pr_err("SPORT is busy!\n");
167 return -EBUSY;
168 }
169
170 bf5xx_tdm.configured = 1;
171 }
172
173 return 0;
174}
175
176static void bf5xx_tdm_shutdown(struct snd_pcm_substream *substream,
177 struct snd_soc_dai *dai)
178{
179 /* No active stream, SPORT is allowed to be configured again. */
180 if (!dai->active)
181 bf5xx_tdm.configured = 0;
182}
183
184#ifdef CONFIG_PM
185static int bf5xx_tdm_suspend(struct snd_soc_dai *dai)
186{
187 struct sport_device *sport =
188 (struct sport_device *)dai->private_data;
189
190 if (!dai->active)
191 return 0;
192 if (dai->capture.active)
193 sport_rx_stop(sport);
194 if (dai->playback.active)
195 sport_tx_stop(sport);
196 return 0;
197}
198
199static int bf5xx_tdm_resume(struct snd_soc_dai *dai)
200{
201 int ret;
202 struct sport_device *sport =
203 (struct sport_device *)dai->private_data;
204
205 if (!dai->active)
206 return 0;
207
208 ret = sport_set_multichannel(sport, 8, 0xFF, 1);
209 if (ret) {
210 pr_err("SPORT is busy!\n");
211 ret = -EBUSY;
212 }
213
214 ret = sport_config_rx(sport, IRFS, 0x1F, 0, 0);
215 if (ret) {
216 pr_err("SPORT is busy!\n");
217 ret = -EBUSY;
218 }
219
220 ret = sport_config_tx(sport, ITFS, 0x1F, 0, 0);
221 if (ret) {
222 pr_err("SPORT is busy!\n");
223 ret = -EBUSY;
224 }
225
226 return 0;
227}
228
229#else
230#define bf5xx_tdm_suspend NULL
231#define bf5xx_tdm_resume NULL
232#endif
233
234static struct snd_soc_dai_ops bf5xx_tdm_dai_ops = {
235 .hw_params = bf5xx_tdm_hw_params,
236 .set_fmt = bf5xx_tdm_set_dai_fmt,
237 .shutdown = bf5xx_tdm_shutdown,
238};
239
240struct snd_soc_dai bf5xx_tdm_dai = {
241 .name = "bf5xx-tdm",
242 .id = 0,
243 .suspend = bf5xx_tdm_suspend,
244 .resume = bf5xx_tdm_resume,
245 .playback = {
246 .channels_min = 2,
247 .channels_max = 8,
248 .rates = SNDRV_PCM_RATE_48000,
249 .formats = SNDRV_PCM_FMTBIT_S32_LE,},
250 .capture = {
251 .channels_min = 2,
252 .channels_max = 8,
253 .rates = SNDRV_PCM_RATE_48000,
254 .formats = SNDRV_PCM_FMTBIT_S32_LE,},
255 .ops = &bf5xx_tdm_dai_ops,
256};
257EXPORT_SYMBOL_GPL(bf5xx_tdm_dai);
258
259static int __devinit bfin_tdm_probe(struct platform_device *pdev)
260{
261 int ret = 0;
262
263 if (peripheral_request_list(&sport_req[sport_num][0], "soc-audio")) {
264 pr_err("Requesting Peripherals failed\n");
265 return -EFAULT;
266 }
267
268 /* request DMA for SPORT */
269 sport_handle = sport_init(&sport_params[sport_num], 4, \
270 8 * sizeof(u32), NULL);
271 if (!sport_handle) {
272 peripheral_free_list(&sport_req[sport_num][0]);
273 return -ENODEV;
274 }
275
276 /* SPORT works in TDM mode */
277 ret = sport_set_multichannel(sport_handle, 8, 0xFF, 1);
278 if (ret) {
279 pr_err("SPORT is busy!\n");
280 ret = -EBUSY;
281 goto sport_config_err;
282 }
283
284 ret = sport_config_rx(sport_handle, IRFS, 0x1F, 0, 0);
285 if (ret) {
286 pr_err("SPORT is busy!\n");
287 ret = -EBUSY;
288 goto sport_config_err;
289 }
290
291 ret = sport_config_tx(sport_handle, ITFS, 0x1F, 0, 0);
292 if (ret) {
293 pr_err("SPORT is busy!\n");
294 ret = -EBUSY;
295 goto sport_config_err;
296 }
297
298 ret = snd_soc_register_dai(&bf5xx_tdm_dai);
299 if (ret) {
300 pr_err("Failed to register DAI: %d\n", ret);
301 goto sport_config_err;
302 }
303 return 0;
304
305sport_config_err:
306 peripheral_free_list(&sport_req[sport_num][0]);
307 return ret;
308}
309
310static int __devexit bfin_tdm_remove(struct platform_device *pdev)
311{
312 peripheral_free_list(&sport_req[sport_num][0]);
313 snd_soc_unregister_dai(&bf5xx_tdm_dai);
314
315 return 0;
316}
317
318static struct platform_driver bfin_tdm_driver = {
319 .probe = bfin_tdm_probe,
320 .remove = __devexit_p(bfin_tdm_remove),
321 .driver = {
322 .name = "bfin-tdm",
323 .owner = THIS_MODULE,
324 },
325};
326
327static int __init bfin_tdm_init(void)
328{
329 return platform_driver_register(&bfin_tdm_driver);
330}
331module_init(bfin_tdm_init);
332
333static void __exit bfin_tdm_exit(void)
334{
335 platform_driver_unregister(&bfin_tdm_driver);
336}
337module_exit(bfin_tdm_exit);
338
339/* Module information */
340MODULE_AUTHOR("Barry Song");
341MODULE_DESCRIPTION("TDM driver for ADI Blackfin");
342MODULE_LICENSE("GPL");
343
diff --git a/sound/soc/blackfin/bf5xx-tdm.h b/sound/soc/blackfin/bf5xx-tdm.h
new file mode 100644
index 000000000000..618ec3d90cd4
--- /dev/null
+++ b/sound/soc/blackfin/bf5xx-tdm.h
@@ -0,0 +1,14 @@
1/*
2 * sound/soc/blackfin/bf5xx-tdm.h
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License version 2 as
6 * published by the Free Software Foundation.
7 */
8
9#ifndef _BF5XX_TDM_H
10#define _BF5XX_TDM_H
11
12extern struct snd_soc_dai bf5xx_tdm_dai;
13
14#endif
diff --git a/sound/soc/codecs/Kconfig b/sound/soc/codecs/Kconfig
index b6c7f7a01cb0..910b9162cbbb 100644
--- a/sound/soc/codecs/Kconfig
+++ b/sound/soc/codecs/Kconfig
@@ -12,13 +12,18 @@ config SND_SOC_ALL_CODECS
12 tristate "Build all ASoC CODEC drivers" 12 tristate "Build all ASoC CODEC drivers"
13 select SND_SOC_L3 13 select SND_SOC_L3
14 select SND_SOC_AC97_CODEC if SND_SOC_AC97_BUS 14 select SND_SOC_AC97_CODEC if SND_SOC_AC97_BUS
15 select SND_SOC_AD1836 if SPI_MASTER
16 select SND_SOC_AD1938 if SPI_MASTER
15 select SND_SOC_AD1980 if SND_SOC_AC97_BUS 17 select SND_SOC_AD1980 if SND_SOC_AC97_BUS
16 select SND_SOC_AD73311 if I2C 18 select SND_SOC_AD73311 if I2C
17 select SND_SOC_AK4104 if SPI_MASTER 19 select SND_SOC_AK4104 if SPI_MASTER
18 select SND_SOC_AK4535 if I2C 20 select SND_SOC_AK4535 if I2C
19 select SND_SOC_CS4270 if I2C 21 select SND_SOC_CS4270 if I2C
22 select SND_SOC_MAX9877 if I2C
20 select SND_SOC_PCM3008 23 select SND_SOC_PCM3008
24 select SND_SOC_SPDIF
21 select SND_SOC_SSM2602 if I2C 25 select SND_SOC_SSM2602 if I2C
26 select SND_SOC_STAC9766 if SND_SOC_AC97_BUS
22 select SND_SOC_TLV320AIC23 if I2C 27 select SND_SOC_TLV320AIC23 if I2C
23 select SND_SOC_TLV320AIC26 if SPI_MASTER 28 select SND_SOC_TLV320AIC26 if SPI_MASTER
24 select SND_SOC_TLV320AIC3X if I2C 29 select SND_SOC_TLV320AIC3X if I2C
@@ -28,15 +33,23 @@ config SND_SOC_ALL_CODECS
28 select SND_SOC_WM8350 if MFD_WM8350 33 select SND_SOC_WM8350 if MFD_WM8350
29 select SND_SOC_WM8400 if MFD_WM8400 34 select SND_SOC_WM8400 if MFD_WM8400
30 select SND_SOC_WM8510 if SND_SOC_I2C_AND_SPI 35 select SND_SOC_WM8510 if SND_SOC_I2C_AND_SPI
36 select SND_SOC_WM8523 if I2C
31 select SND_SOC_WM8580 if I2C 37 select SND_SOC_WM8580 if I2C
32 select SND_SOC_WM8728 if SND_SOC_I2C_AND_SPI 38 select SND_SOC_WM8728 if SND_SOC_I2C_AND_SPI
33 select SND_SOC_WM8731 if SND_SOC_I2C_AND_SPI 39 select SND_SOC_WM8731 if SND_SOC_I2C_AND_SPI
34 select SND_SOC_WM8750 if SND_SOC_I2C_AND_SPI 40 select SND_SOC_WM8750 if SND_SOC_I2C_AND_SPI
35 select SND_SOC_WM8753 if SND_SOC_I2C_AND_SPI 41 select SND_SOC_WM8753 if SND_SOC_I2C_AND_SPI
42 select SND_SOC_WM8776 if SND_SOC_I2C_AND_SPI
36 select SND_SOC_WM8900 if I2C 43 select SND_SOC_WM8900 if I2C
37 select SND_SOC_WM8903 if I2C 44 select SND_SOC_WM8903 if I2C
45 select SND_SOC_WM8940 if I2C
46 select SND_SOC_WM8960 if I2C
47 select SND_SOC_WM8961 if I2C
38 select SND_SOC_WM8971 if I2C 48 select SND_SOC_WM8971 if I2C
49 select SND_SOC_WM8988 if SND_SOC_I2C_AND_SPI
39 select SND_SOC_WM8990 if I2C 50 select SND_SOC_WM8990 if I2C
51 select SND_SOC_WM8993 if I2C
52 select SND_SOC_WM9081 if I2C
40 select SND_SOC_WM9705 if SND_SOC_AC97_BUS 53 select SND_SOC_WM9705 if SND_SOC_AC97_BUS
41 select SND_SOC_WM9712 if SND_SOC_AC97_BUS 54 select SND_SOC_WM9712 if SND_SOC_AC97_BUS
42 select SND_SOC_WM9713 if SND_SOC_AC97_BUS 55 select SND_SOC_WM9713 if SND_SOC_AC97_BUS
@@ -51,11 +64,21 @@ config SND_SOC_ALL_CODECS
51 64
52 If unsure select "N". 65 If unsure select "N".
53 66
67config SND_SOC_WM_HUBS
68 tristate
69 default y if SND_SOC_WM8993=y
70 default m if SND_SOC_WM8993=m
54 71
55config SND_SOC_AC97_CODEC 72config SND_SOC_AC97_CODEC
56 tristate 73 tristate
57 select SND_AC97_CODEC 74 select SND_AC97_CODEC
58 75
76config SND_SOC_AD1836
77 tristate
78
79config SND_SOC_AD1938
80 tristate
81
59config SND_SOC_AD1980 82config SND_SOC_AD1980
60 tristate 83 tristate
61 84
@@ -80,15 +103,24 @@ config SND_SOC_CS4270_VD33_ERRATA
80 bool 103 bool
81 depends on SND_SOC_CS4270 104 depends on SND_SOC_CS4270
82 105
106config SND_SOC_CX20442
107 tristate
108
83config SND_SOC_L3 109config SND_SOC_L3
84 tristate 110 tristate
85 111
86config SND_SOC_PCM3008 112config SND_SOC_PCM3008
87 tristate 113 tristate
88 114
115config SND_SOC_SPDIF
116 tristate
117
89config SND_SOC_SSM2602 118config SND_SOC_SSM2602
90 tristate 119 tristate
91 120
121config SND_SOC_STAC9766
122 tristate
123
92config SND_SOC_TLV320AIC23 124config SND_SOC_TLV320AIC23
93 tristate 125 tristate
94 126
@@ -117,6 +149,9 @@ config SND_SOC_WM8400
117config SND_SOC_WM8510 149config SND_SOC_WM8510
118 tristate 150 tristate
119 151
152config SND_SOC_WM8523
153 tristate
154
120config SND_SOC_WM8580 155config SND_SOC_WM8580
121 tristate 156 tristate
122 157
@@ -132,18 +167,39 @@ config SND_SOC_WM8750
132config SND_SOC_WM8753 167config SND_SOC_WM8753
133 tristate 168 tristate
134 169
170config SND_SOC_WM8776
171 tristate
172
135config SND_SOC_WM8900 173config SND_SOC_WM8900
136 tristate 174 tristate
137 175
138config SND_SOC_WM8903 176config SND_SOC_WM8903
139 tristate 177 tristate
140 178
179config SND_SOC_WM8940
180 tristate
181
182config SND_SOC_WM8960
183 tristate
184
185config SND_SOC_WM8961
186 tristate
187
141config SND_SOC_WM8971 188config SND_SOC_WM8971
142 tristate 189 tristate
143 190
191config SND_SOC_WM8988
192 tristate
193
144config SND_SOC_WM8990 194config SND_SOC_WM8990
145 tristate 195 tristate
146 196
197config SND_SOC_WM8993
198 tristate
199
200config SND_SOC_WM9081
201 tristate
202
147config SND_SOC_WM9705 203config SND_SOC_WM9705
148 tristate 204 tristate
149 205
@@ -152,3 +208,7 @@ config SND_SOC_WM9712
152 208
153config SND_SOC_WM9713 209config SND_SOC_WM9713
154 tristate 210 tristate
211
212# Amp
213config SND_SOC_MAX9877
214 tristate
diff --git a/sound/soc/codecs/Makefile b/sound/soc/codecs/Makefile
index f2653803ede8..c7fd2297a06f 100644
--- a/sound/soc/codecs/Makefile
+++ b/sound/soc/codecs/Makefile
@@ -1,12 +1,17 @@
1snd-soc-ac97-objs := ac97.o 1snd-soc-ac97-objs := ac97.o
2snd-soc-ad1836-objs := ad1836.o
3snd-soc-ad1938-objs := ad1938.o
2snd-soc-ad1980-objs := ad1980.o 4snd-soc-ad1980-objs := ad1980.o
3snd-soc-ad73311-objs := ad73311.o 5snd-soc-ad73311-objs := ad73311.o
4snd-soc-ak4104-objs := ak4104.o 6snd-soc-ak4104-objs := ak4104.o
5snd-soc-ak4535-objs := ak4535.o 7snd-soc-ak4535-objs := ak4535.o
6snd-soc-cs4270-objs := cs4270.o 8snd-soc-cs4270-objs := cs4270.o
9snd-soc-cx20442-objs := cx20442.o
7snd-soc-l3-objs := l3.o 10snd-soc-l3-objs := l3.o
8snd-soc-pcm3008-objs := pcm3008.o 11snd-soc-pcm3008-objs := pcm3008.o
12snd-soc-spdif-objs := spdif_transciever.o
9snd-soc-ssm2602-objs := ssm2602.o 13snd-soc-ssm2602-objs := ssm2602.o
14snd-soc-stac9766-objs := stac9766.o
10snd-soc-tlv320aic23-objs := tlv320aic23.o 15snd-soc-tlv320aic23-objs := tlv320aic23.o
11snd-soc-tlv320aic26-objs := tlv320aic26.o 16snd-soc-tlv320aic26-objs := tlv320aic26.o
12snd-soc-tlv320aic3x-objs := tlv320aic3x.o 17snd-soc-tlv320aic3x-objs := tlv320aic3x.o
@@ -16,28 +21,45 @@ snd-soc-uda1380-objs := uda1380.o
16snd-soc-wm8350-objs := wm8350.o 21snd-soc-wm8350-objs := wm8350.o
17snd-soc-wm8400-objs := wm8400.o 22snd-soc-wm8400-objs := wm8400.o
18snd-soc-wm8510-objs := wm8510.o 23snd-soc-wm8510-objs := wm8510.o
24snd-soc-wm8523-objs := wm8523.o
19snd-soc-wm8580-objs := wm8580.o 25snd-soc-wm8580-objs := wm8580.o
20snd-soc-wm8728-objs := wm8728.o 26snd-soc-wm8728-objs := wm8728.o
21snd-soc-wm8731-objs := wm8731.o 27snd-soc-wm8731-objs := wm8731.o
22snd-soc-wm8750-objs := wm8750.o 28snd-soc-wm8750-objs := wm8750.o
23snd-soc-wm8753-objs := wm8753.o 29snd-soc-wm8753-objs := wm8753.o
30snd-soc-wm8776-objs := wm8776.o
24snd-soc-wm8900-objs := wm8900.o 31snd-soc-wm8900-objs := wm8900.o
25snd-soc-wm8903-objs := wm8903.o 32snd-soc-wm8903-objs := wm8903.o
33snd-soc-wm8940-objs := wm8940.o
34snd-soc-wm8960-objs := wm8960.o
35snd-soc-wm8961-objs := wm8961.o
26snd-soc-wm8971-objs := wm8971.o 36snd-soc-wm8971-objs := wm8971.o
37snd-soc-wm8988-objs := wm8988.o
27snd-soc-wm8990-objs := wm8990.o 38snd-soc-wm8990-objs := wm8990.o
39snd-soc-wm8993-objs := wm8993.o
40snd-soc-wm9081-objs := wm9081.o
28snd-soc-wm9705-objs := wm9705.o 41snd-soc-wm9705-objs := wm9705.o
29snd-soc-wm9712-objs := wm9712.o 42snd-soc-wm9712-objs := wm9712.o
30snd-soc-wm9713-objs := wm9713.o 43snd-soc-wm9713-objs := wm9713.o
44snd-soc-wm-hubs-objs := wm_hubs.o
45
46# Amp
47snd-soc-max9877-objs := max9877.o
31 48
32obj-$(CONFIG_SND_SOC_AC97_CODEC) += snd-soc-ac97.o 49obj-$(CONFIG_SND_SOC_AC97_CODEC) += snd-soc-ac97.o
50obj-$(CONFIG_SND_SOC_AD1836) += snd-soc-ad1836.o
51obj-$(CONFIG_SND_SOC_AD1938) += snd-soc-ad1938.o
33obj-$(CONFIG_SND_SOC_AD1980) += snd-soc-ad1980.o 52obj-$(CONFIG_SND_SOC_AD1980) += snd-soc-ad1980.o
34obj-$(CONFIG_SND_SOC_AD73311) += snd-soc-ad73311.o 53obj-$(CONFIG_SND_SOC_AD73311) += snd-soc-ad73311.o
35obj-$(CONFIG_SND_SOC_AK4104) += snd-soc-ak4104.o 54obj-$(CONFIG_SND_SOC_AK4104) += snd-soc-ak4104.o
36obj-$(CONFIG_SND_SOC_AK4535) += snd-soc-ak4535.o 55obj-$(CONFIG_SND_SOC_AK4535) += snd-soc-ak4535.o
37obj-$(CONFIG_SND_SOC_CS4270) += snd-soc-cs4270.o 56obj-$(CONFIG_SND_SOC_CS4270) += snd-soc-cs4270.o
57obj-$(CONFIG_SND_SOC_CX20442) += snd-soc-cx20442.o
38obj-$(CONFIG_SND_SOC_L3) += snd-soc-l3.o 58obj-$(CONFIG_SND_SOC_L3) += snd-soc-l3.o
39obj-$(CONFIG_SND_SOC_PCM3008) += snd-soc-pcm3008.o 59obj-$(CONFIG_SND_SOC_PCM3008) += snd-soc-pcm3008.o
60obj-$(CONFIG_SND_SOC_SPDIF) += snd-soc-spdif.o
40obj-$(CONFIG_SND_SOC_SSM2602) += snd-soc-ssm2602.o 61obj-$(CONFIG_SND_SOC_SSM2602) += snd-soc-ssm2602.o
62obj-$(CONFIG_SND_SOC_STAC9766) += snd-soc-stac9766.o
41obj-$(CONFIG_SND_SOC_TLV320AIC23) += snd-soc-tlv320aic23.o 63obj-$(CONFIG_SND_SOC_TLV320AIC23) += snd-soc-tlv320aic23.o
42obj-$(CONFIG_SND_SOC_TLV320AIC26) += snd-soc-tlv320aic26.o 64obj-$(CONFIG_SND_SOC_TLV320AIC26) += snd-soc-tlv320aic26.o
43obj-$(CONFIG_SND_SOC_TLV320AIC3X) += snd-soc-tlv320aic3x.o 65obj-$(CONFIG_SND_SOC_TLV320AIC3X) += snd-soc-tlv320aic3x.o
@@ -47,15 +69,27 @@ obj-$(CONFIG_SND_SOC_UDA1380) += snd-soc-uda1380.o
47obj-$(CONFIG_SND_SOC_WM8350) += snd-soc-wm8350.o 69obj-$(CONFIG_SND_SOC_WM8350) += snd-soc-wm8350.o
48obj-$(CONFIG_SND_SOC_WM8400) += snd-soc-wm8400.o 70obj-$(CONFIG_SND_SOC_WM8400) += snd-soc-wm8400.o
49obj-$(CONFIG_SND_SOC_WM8510) += snd-soc-wm8510.o 71obj-$(CONFIG_SND_SOC_WM8510) += snd-soc-wm8510.o
72obj-$(CONFIG_SND_SOC_WM8523) += snd-soc-wm8523.o
50obj-$(CONFIG_SND_SOC_WM8580) += snd-soc-wm8580.o 73obj-$(CONFIG_SND_SOC_WM8580) += snd-soc-wm8580.o
51obj-$(CONFIG_SND_SOC_WM8728) += snd-soc-wm8728.o 74obj-$(CONFIG_SND_SOC_WM8728) += snd-soc-wm8728.o
52obj-$(CONFIG_SND_SOC_WM8731) += snd-soc-wm8731.o 75obj-$(CONFIG_SND_SOC_WM8731) += snd-soc-wm8731.o
53obj-$(CONFIG_SND_SOC_WM8750) += snd-soc-wm8750.o 76obj-$(CONFIG_SND_SOC_WM8750) += snd-soc-wm8750.o
54obj-$(CONFIG_SND_SOC_WM8753) += snd-soc-wm8753.o 77obj-$(CONFIG_SND_SOC_WM8753) += snd-soc-wm8753.o
78obj-$(CONFIG_SND_SOC_WM8776) += snd-soc-wm8776.o
55obj-$(CONFIG_SND_SOC_WM8900) += snd-soc-wm8900.o 79obj-$(CONFIG_SND_SOC_WM8900) += snd-soc-wm8900.o
56obj-$(CONFIG_SND_SOC_WM8903) += snd-soc-wm8903.o 80obj-$(CONFIG_SND_SOC_WM8903) += snd-soc-wm8903.o
57obj-$(CONFIG_SND_SOC_WM8971) += snd-soc-wm8971.o 81obj-$(CONFIG_SND_SOC_WM8971) += snd-soc-wm8971.o
82obj-$(CONFIG_SND_SOC_WM8940) += snd-soc-wm8940.o
83obj-$(CONFIG_SND_SOC_WM8960) += snd-soc-wm8960.o
84obj-$(CONFIG_SND_SOC_WM8961) += snd-soc-wm8961.o
85obj-$(CONFIG_SND_SOC_WM8988) += snd-soc-wm8988.o
58obj-$(CONFIG_SND_SOC_WM8990) += snd-soc-wm8990.o 86obj-$(CONFIG_SND_SOC_WM8990) += snd-soc-wm8990.o
87obj-$(CONFIG_SND_SOC_WM8993) += snd-soc-wm8993.o
88obj-$(CONFIG_SND_SOC_WM9081) += snd-soc-wm9081.o
59obj-$(CONFIG_SND_SOC_WM9705) += snd-soc-wm9705.o 89obj-$(CONFIG_SND_SOC_WM9705) += snd-soc-wm9705.o
60obj-$(CONFIG_SND_SOC_WM9712) += snd-soc-wm9712.o 90obj-$(CONFIG_SND_SOC_WM9712) += snd-soc-wm9712.o
61obj-$(CONFIG_SND_SOC_WM9713) += snd-soc-wm9713.o 91obj-$(CONFIG_SND_SOC_WM9713) += snd-soc-wm9713.o
92obj-$(CONFIG_SND_SOC_WM_HUBS) += snd-soc-wm-hubs.o
93
94# Amp
95obj-$(CONFIG_SND_SOC_MAX9877) += snd-soc-max9877.o
diff --git a/sound/soc/codecs/ac97.c b/sound/soc/codecs/ac97.c
index b0d4af145b87..932299bb5d1e 100644
--- a/sound/soc/codecs/ac97.c
+++ b/sound/soc/codecs/ac97.c
@@ -53,13 +53,13 @@ struct snd_soc_dai ac97_dai = {
53 .channels_min = 1, 53 .channels_min = 1,
54 .channels_max = 2, 54 .channels_max = 2,
55 .rates = STD_AC97_RATES, 55 .rates = STD_AC97_RATES,
56 .formats = SNDRV_PCM_FMTBIT_S16_LE,}, 56 .formats = SND_SOC_STD_AC97_FMTS,},
57 .capture = { 57 .capture = {
58 .stream_name = "AC97 Capture", 58 .stream_name = "AC97 Capture",
59 .channels_min = 1, 59 .channels_min = 1,
60 .channels_max = 2, 60 .channels_max = 2,
61 .rates = STD_AC97_RATES, 61 .rates = STD_AC97_RATES,
62 .formats = SNDRV_PCM_FMTBIT_S16_LE,}, 62 .formats = SND_SOC_STD_AC97_FMTS,},
63 .ops = &ac97_dai_ops, 63 .ops = &ac97_dai_ops,
64}; 64};
65EXPORT_SYMBOL_GPL(ac97_dai); 65EXPORT_SYMBOL_GPL(ac97_dai);
diff --git a/sound/soc/codecs/ad1836.c b/sound/soc/codecs/ad1836.c
new file mode 100644
index 000000000000..3612bb92df90
--- /dev/null
+++ b/sound/soc/codecs/ad1836.c
@@ -0,0 +1,446 @@
1/*
2 * File: sound/soc/codecs/ad1836.c
3 * Author: Barry Song <Barry.Song@analog.com>
4 *
5 * Created: Aug 04 2009
6 * Description: Driver for AD1836 sound chip
7 *
8 * Modified:
9 * Copyright 2009 Analog Devices Inc.
10 *
11 * Bugs: Enter bugs at http://blackfin.uclinux.org/
12 *
13 * This program is free software; you can redistribute it and/or modify
14 * it under the terms of the GNU General Public License as published by
15 * the Free Software Foundation; either version 2 of the License, or
16 * (at your option) any later version.
17 */
18
19#include <linux/init.h>
20#include <linux/module.h>
21#include <linux/version.h>
22#include <linux/kernel.h>
23#include <linux/device.h>
24#include <sound/core.h>
25#include <sound/pcm.h>
26#include <sound/pcm_params.h>
27#include <sound/initval.h>
28#include <sound/soc.h>
29#include <sound/tlv.h>
30#include <sound/soc-dapm.h>
31#include <linux/spi/spi.h>
32#include "ad1836.h"
33
34/* codec private data */
35struct ad1836_priv {
36 struct snd_soc_codec codec;
37 u16 reg_cache[AD1836_NUM_REGS];
38};
39
40static struct snd_soc_codec *ad1836_codec;
41struct snd_soc_codec_device soc_codec_dev_ad1836;
42static int ad1836_register(struct ad1836_priv *ad1836);
43static void ad1836_unregister(struct ad1836_priv *ad1836);
44
45/*
46 * AD1836 volume/mute/de-emphasis etc. controls
47 */
48static const char *ad1836_deemp[] = {"None", "44.1kHz", "32kHz", "48kHz"};
49
50static const struct soc_enum ad1836_deemp_enum =
51 SOC_ENUM_SINGLE(AD1836_DAC_CTRL1, 8, 4, ad1836_deemp);
52
53static const struct snd_kcontrol_new ad1836_snd_controls[] = {
54 /* DAC volume control */
55 SOC_DOUBLE_R("DAC1 Volume", AD1836_DAC_L1_VOL,
56 AD1836_DAC_R1_VOL, 0, 0x3FF, 0),
57 SOC_DOUBLE_R("DAC2 Volume", AD1836_DAC_L2_VOL,
58 AD1836_DAC_R2_VOL, 0, 0x3FF, 0),
59 SOC_DOUBLE_R("DAC3 Volume", AD1836_DAC_L3_VOL,
60 AD1836_DAC_R3_VOL, 0, 0x3FF, 0),
61
62 /* ADC switch control */
63 SOC_DOUBLE("ADC1 Switch", AD1836_ADC_CTRL2, AD1836_ADCL1_MUTE,
64 AD1836_ADCR1_MUTE, 1, 1),
65 SOC_DOUBLE("ADC2 Switch", AD1836_ADC_CTRL2, AD1836_ADCL2_MUTE,
66 AD1836_ADCR2_MUTE, 1, 1),
67
68 /* DAC switch control */
69 SOC_DOUBLE("DAC1 Switch", AD1836_DAC_CTRL2, AD1836_DACL1_MUTE,
70 AD1836_DACR1_MUTE, 1, 1),
71 SOC_DOUBLE("DAC2 Switch", AD1836_DAC_CTRL2, AD1836_DACL2_MUTE,
72 AD1836_DACR2_MUTE, 1, 1),
73 SOC_DOUBLE("DAC3 Switch", AD1836_DAC_CTRL2, AD1836_DACL3_MUTE,
74 AD1836_DACR3_MUTE, 1, 1),
75
76 /* ADC high-pass filter */
77 SOC_SINGLE("ADC High Pass Filter Switch", AD1836_ADC_CTRL1,
78 AD1836_ADC_HIGHPASS_FILTER, 1, 0),
79
80 /* DAC de-emphasis */
81 SOC_ENUM("Playback Deemphasis", ad1836_deemp_enum),
82};
83
84static const struct snd_soc_dapm_widget ad1836_dapm_widgets[] = {
85 SND_SOC_DAPM_DAC("DAC", "Playback", AD1836_DAC_CTRL1,
86 AD1836_DAC_POWERDOWN, 1),
87 SND_SOC_DAPM_ADC("ADC", "Capture", SND_SOC_NOPM, 0, 0),
88 SND_SOC_DAPM_SUPPLY("ADC_PWR", AD1836_ADC_CTRL1,
89 AD1836_ADC_POWERDOWN, 1, NULL, 0),
90 SND_SOC_DAPM_OUTPUT("DAC1OUT"),
91 SND_SOC_DAPM_OUTPUT("DAC2OUT"),
92 SND_SOC_DAPM_OUTPUT("DAC3OUT"),
93 SND_SOC_DAPM_INPUT("ADC1IN"),
94 SND_SOC_DAPM_INPUT("ADC2IN"),
95};
96
97static const struct snd_soc_dapm_route audio_paths[] = {
98 { "DAC", NULL, "ADC_PWR" },
99 { "ADC", NULL, "ADC_PWR" },
100 { "DAC1OUT", "DAC1 Switch", "DAC" },
101 { "DAC2OUT", "DAC2 Switch", "DAC" },
102 { "DAC3OUT", "DAC3 Switch", "DAC" },
103 { "ADC", "ADC1 Switch", "ADC1IN" },
104 { "ADC", "ADC2 Switch", "ADC2IN" },
105};
106
107/*
108 * DAI ops entries
109 */
110
111static int ad1836_set_dai_fmt(struct snd_soc_dai *codec_dai,
112 unsigned int fmt)
113{
114 switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
115 /* at present, we support adc aux mode to interface with
116 * blackfin sport tdm mode
117 */
118 case SND_SOC_DAIFMT_DSP_A:
119 break;
120 default:
121 return -EINVAL;
122 }
123
124 switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
125 case SND_SOC_DAIFMT_IB_IF:
126 break;
127 default:
128 return -EINVAL;
129 }
130
131 switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
132 /* ALCLK,ABCLK are both output, AD1836 can only be master */
133 case SND_SOC_DAIFMT_CBM_CFM:
134 break;
135 default:
136 return -EINVAL;
137 }
138
139 return 0;
140}
141
142static int ad1836_hw_params(struct snd_pcm_substream *substream,
143 struct snd_pcm_hw_params *params,
144 struct snd_soc_dai *dai)
145{
146 int word_len = 0;
147
148 struct snd_soc_pcm_runtime *rtd = substream->private_data;
149 struct snd_soc_device *socdev = rtd->socdev;
150 struct snd_soc_codec *codec = socdev->card->codec;
151
152 /* bit size */
153 switch (params_format(params)) {
154 case SNDRV_PCM_FORMAT_S16_LE:
155 word_len = 3;
156 break;
157 case SNDRV_PCM_FORMAT_S20_3LE:
158 word_len = 1;
159 break;
160 case SNDRV_PCM_FORMAT_S24_LE:
161 case SNDRV_PCM_FORMAT_S32_LE:
162 word_len = 0;
163 break;
164 }
165
166 snd_soc_update_bits(codec, AD1836_DAC_CTRL1,
167 AD1836_DAC_WORD_LEN_MASK, word_len);
168
169 snd_soc_update_bits(codec, AD1836_ADC_CTRL2,
170 AD1836_ADC_WORD_LEN_MASK, word_len);
171
172 return 0;
173}
174
175
176/*
177 * interface to read/write ad1836 register
178 */
179#define AD1836_SPI_REG_SHFT 12
180#define AD1836_SPI_READ (1 << 11)
181#define AD1836_SPI_VAL_MSK 0x3FF
182
183/*
184 * write to the ad1836 register space
185 */
186
187static int ad1836_write_reg(struct snd_soc_codec *codec, unsigned int reg,
188 unsigned int value)
189{
190 u16 *reg_cache = codec->reg_cache;
191 int ret = 0;
192
193 if (value != reg_cache[reg]) {
194 unsigned short buf;
195 struct spi_transfer t = {
196 .tx_buf = &buf,
197 .len = 2,
198 };
199 struct spi_message m;
200
201 buf = (reg << AD1836_SPI_REG_SHFT) |
202 (value & AD1836_SPI_VAL_MSK);
203 spi_message_init(&m);
204 spi_message_add_tail(&t, &m);
205 ret = spi_sync(codec->control_data, &m);
206 if (ret == 0)
207 reg_cache[reg] = value;
208 }
209
210 return ret;
211}
212
213/*
214 * read from the ad1836 register space cache
215 */
216static unsigned int ad1836_read_reg_cache(struct snd_soc_codec *codec,
217 unsigned int reg)
218{
219 u16 *reg_cache = codec->reg_cache;
220
221 if (reg >= codec->reg_cache_size)
222 return -EINVAL;
223
224 return reg_cache[reg];
225}
226
227static int __devinit ad1836_spi_probe(struct spi_device *spi)
228{
229 struct snd_soc_codec *codec;
230 struct ad1836_priv *ad1836;
231
232 ad1836 = kzalloc(sizeof(struct ad1836_priv), GFP_KERNEL);
233 if (ad1836 == NULL)
234 return -ENOMEM;
235
236 codec = &ad1836->codec;
237 codec->control_data = spi;
238 codec->dev = &spi->dev;
239
240 dev_set_drvdata(&spi->dev, ad1836);
241
242 return ad1836_register(ad1836);
243}
244
245static int __devexit ad1836_spi_remove(struct spi_device *spi)
246{
247 struct ad1836_priv *ad1836 = dev_get_drvdata(&spi->dev);
248
249 ad1836_unregister(ad1836);
250 return 0;
251}
252
253static struct spi_driver ad1836_spi_driver = {
254 .driver = {
255 .name = "ad1836-spi",
256 .bus = &spi_bus_type,
257 .owner = THIS_MODULE,
258 },
259 .probe = ad1836_spi_probe,
260 .remove = __devexit_p(ad1836_spi_remove),
261};
262
263static struct snd_soc_dai_ops ad1836_dai_ops = {
264 .hw_params = ad1836_hw_params,
265 .set_fmt = ad1836_set_dai_fmt,
266};
267
268/* codec DAI instance */
269struct snd_soc_dai ad1836_dai = {
270 .name = "AD1836",
271 .playback = {
272 .stream_name = "Playback",
273 .channels_min = 2,
274 .channels_max = 6,
275 .rates = SNDRV_PCM_RATE_48000,
276 .formats = SNDRV_PCM_FMTBIT_S32_LE | SNDRV_PCM_FMTBIT_S16_LE |
277 SNDRV_PCM_FMTBIT_S20_3LE | SNDRV_PCM_FMTBIT_S24_LE,
278 },
279 .capture = {
280 .stream_name = "Capture",
281 .channels_min = 2,
282 .channels_max = 4,
283 .rates = SNDRV_PCM_RATE_48000,
284 .formats = SNDRV_PCM_FMTBIT_S32_LE | SNDRV_PCM_FMTBIT_S16_LE |
285 SNDRV_PCM_FMTBIT_S20_3LE | SNDRV_PCM_FMTBIT_S24_LE,
286 },
287 .ops = &ad1836_dai_ops,
288};
289EXPORT_SYMBOL_GPL(ad1836_dai);
290
291static int ad1836_register(struct ad1836_priv *ad1836)
292{
293 int ret;
294 struct snd_soc_codec *codec = &ad1836->codec;
295
296 if (ad1836_codec) {
297 dev_err(codec->dev, "Another ad1836 is registered\n");
298 return -EINVAL;
299 }
300
301 mutex_init(&codec->mutex);
302 INIT_LIST_HEAD(&codec->dapm_widgets);
303 INIT_LIST_HEAD(&codec->dapm_paths);
304 codec->private_data = ad1836;
305 codec->reg_cache = ad1836->reg_cache;
306 codec->reg_cache_size = AD1836_NUM_REGS;
307 codec->name = "AD1836";
308 codec->owner = THIS_MODULE;
309 codec->dai = &ad1836_dai;
310 codec->num_dai = 1;
311 codec->write = ad1836_write_reg;
312 codec->read = ad1836_read_reg_cache;
313 INIT_LIST_HEAD(&codec->dapm_widgets);
314 INIT_LIST_HEAD(&codec->dapm_paths);
315
316 ad1836_dai.dev = codec->dev;
317 ad1836_codec = codec;
318
319 /* default setting for ad1836 */
320 /* de-emphasis: 48kHz, power-on dac */
321 codec->write(codec, AD1836_DAC_CTRL1, 0x300);
322 /* unmute dac channels */
323 codec->write(codec, AD1836_DAC_CTRL2, 0x0);
324 /* high-pass filter enable, power-on adc */
325 codec->write(codec, AD1836_ADC_CTRL1, 0x100);
326 /* unmute adc channles, adc aux mode */
327 codec->write(codec, AD1836_ADC_CTRL2, 0x180);
328 /* left/right diff:PGA/MUX */
329 codec->write(codec, AD1836_ADC_CTRL3, 0x3A);
330 /* volume */
331 codec->write(codec, AD1836_DAC_L1_VOL, 0x3FF);
332 codec->write(codec, AD1836_DAC_R1_VOL, 0x3FF);
333 codec->write(codec, AD1836_DAC_L2_VOL, 0x3FF);
334 codec->write(codec, AD1836_DAC_R2_VOL, 0x3FF);
335 codec->write(codec, AD1836_DAC_L3_VOL, 0x3FF);
336 codec->write(codec, AD1836_DAC_R3_VOL, 0x3FF);
337
338 ret = snd_soc_register_codec(codec);
339 if (ret != 0) {
340 dev_err(codec->dev, "Failed to register codec: %d\n", ret);
341 kfree(ad1836);
342 return ret;
343 }
344
345 ret = snd_soc_register_dai(&ad1836_dai);
346 if (ret != 0) {
347 dev_err(codec->dev, "Failed to register DAI: %d\n", ret);
348 snd_soc_unregister_codec(codec);
349 kfree(ad1836);
350 return ret;
351 }
352
353 return 0;
354}
355
356static void ad1836_unregister(struct ad1836_priv *ad1836)
357{
358 snd_soc_unregister_dai(&ad1836_dai);
359 snd_soc_unregister_codec(&ad1836->codec);
360 kfree(ad1836);
361 ad1836_codec = NULL;
362}
363
364static int ad1836_probe(struct platform_device *pdev)
365{
366 struct snd_soc_device *socdev = platform_get_drvdata(pdev);
367 struct snd_soc_codec *codec;
368 int ret = 0;
369
370 if (ad1836_codec == NULL) {
371 dev_err(&pdev->dev, "Codec device not registered\n");
372 return -ENODEV;
373 }
374
375 socdev->card->codec = ad1836_codec;
376 codec = ad1836_codec;
377
378 /* register pcms */
379 ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1);
380 if (ret < 0) {
381 dev_err(codec->dev, "failed to create pcms: %d\n", ret);
382 goto pcm_err;
383 }
384
385 snd_soc_add_controls(codec, ad1836_snd_controls,
386 ARRAY_SIZE(ad1836_snd_controls));
387 snd_soc_dapm_new_controls(codec, ad1836_dapm_widgets,
388 ARRAY_SIZE(ad1836_dapm_widgets));
389 snd_soc_dapm_add_routes(codec, audio_paths, ARRAY_SIZE(audio_paths));
390 snd_soc_dapm_new_widgets(codec);
391
392 ret = snd_soc_init_card(socdev);
393 if (ret < 0) {
394 dev_err(codec->dev, "failed to register card: %d\n", ret);
395 goto card_err;
396 }
397
398 return ret;
399
400card_err:
401 snd_soc_free_pcms(socdev);
402 snd_soc_dapm_free(socdev);
403pcm_err:
404 return ret;
405}
406
407/* power down chip */
408static int ad1836_remove(struct platform_device *pdev)
409{
410 struct snd_soc_device *socdev = platform_get_drvdata(pdev);
411
412 snd_soc_free_pcms(socdev);
413 snd_soc_dapm_free(socdev);
414
415 return 0;
416}
417
418struct snd_soc_codec_device soc_codec_dev_ad1836 = {
419 .probe = ad1836_probe,
420 .remove = ad1836_remove,
421};
422EXPORT_SYMBOL_GPL(soc_codec_dev_ad1836);
423
424static int __init ad1836_init(void)
425{
426 int ret;
427
428 ret = spi_register_driver(&ad1836_spi_driver);
429 if (ret != 0) {
430 printk(KERN_ERR "Failed to register ad1836 SPI driver: %d\n",
431 ret);
432 }
433
434 return ret;
435}
436module_init(ad1836_init);
437
438static void __exit ad1836_exit(void)
439{
440 spi_unregister_driver(&ad1836_spi_driver);
441}
442module_exit(ad1836_exit);
443
444MODULE_DESCRIPTION("ASoC ad1836 driver");
445MODULE_AUTHOR("Barry Song <21cnbao@gmail.com>");
446MODULE_LICENSE("GPL");
diff --git a/sound/soc/codecs/ad1836.h b/sound/soc/codecs/ad1836.h
new file mode 100644
index 000000000000..7660ee6973c0
--- /dev/null
+++ b/sound/soc/codecs/ad1836.h
@@ -0,0 +1,64 @@
1/*
2 * File: sound/soc/codecs/ad1836.h
3 * Based on:
4 * Author: Barry Song <Barry.Song@analog.com>
5 *
6 * Created: Aug 04, 2009
7 * Description: definitions for AD1836 registers
8 *
9 * Modified:
10 *
11 * Bugs: Enter bugs at http://blackfin.uclinux.org/
12 *
13 * This program is free software; you can redistribute it and/or modify
14 * it under the terms of the GNU General Public License as published by
15 * the Free Software Foundation; either version 2 of the License, or
16 * (at your option) any later version.
17 */
18
19#ifndef __AD1836_H__
20#define __AD1836_H__
21
22#define AD1836_DAC_CTRL1 0
23#define AD1836_DAC_POWERDOWN 2
24#define AD1836_DAC_SERFMT_MASK 0xE0
25#define AD1836_DAC_SERFMT_PCK256 (0x4 << 5)
26#define AD1836_DAC_SERFMT_PCK128 (0x5 << 5)
27#define AD1836_DAC_WORD_LEN_MASK 0x18
28
29#define AD1836_DAC_CTRL2 1
30#define AD1836_DACL1_MUTE 0
31#define AD1836_DACR1_MUTE 1
32#define AD1836_DACL2_MUTE 2
33#define AD1836_DACR2_MUTE 3
34#define AD1836_DACL3_MUTE 4
35#define AD1836_DACR3_MUTE 5
36
37#define AD1836_DAC_L1_VOL 2
38#define AD1836_DAC_R1_VOL 3
39#define AD1836_DAC_L2_VOL 4
40#define AD1836_DAC_R2_VOL 5
41#define AD1836_DAC_L3_VOL 6
42#define AD1836_DAC_R3_VOL 7
43
44#define AD1836_ADC_CTRL1 12
45#define AD1836_ADC_POWERDOWN 7
46#define AD1836_ADC_HIGHPASS_FILTER 8
47
48#define AD1836_ADC_CTRL2 13
49#define AD1836_ADCL1_MUTE 0
50#define AD1836_ADCR1_MUTE 1
51#define AD1836_ADCL2_MUTE 2
52#define AD1836_ADCR2_MUTE 3
53#define AD1836_ADC_WORD_LEN_MASK 0x30
54#define AD1836_ADC_SERFMT_MASK (7 << 6)
55#define AD1836_ADC_SERFMT_PCK256 (0x4 << 6)
56#define AD1836_ADC_SERFMT_PCK128 (0x5 << 6)
57
58#define AD1836_ADC_CTRL3 14
59
60#define AD1836_NUM_REGS 16
61
62extern struct snd_soc_dai ad1836_dai;
63extern struct snd_soc_codec_device soc_codec_dev_ad1836;
64#endif
diff --git a/sound/soc/codecs/ad1938.c b/sound/soc/codecs/ad1938.c
new file mode 100644
index 000000000000..e62b27701a49
--- /dev/null
+++ b/sound/soc/codecs/ad1938.c
@@ -0,0 +1,682 @@
1/*
2 * File: sound/soc/codecs/ad1938.c
3 * Author: Barry Song <Barry.Song@analog.com>
4 *
5 * Created: June 04 2009
6 * Description: Driver for AD1938 sound chip
7 *
8 * Modified:
9 * Copyright 2009 Analog Devices Inc.
10 *
11 * Bugs: Enter bugs at http://blackfin.uclinux.org/
12 *
13 * This program is free software; you can redistribute it and/or modify
14 * it under the terms of the GNU General Public License as published by
15 * the Free Software Foundation; either version 2 of the License, or
16 * (at your option) any later version.
17 *
18 * This program is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU General Public License for more details.
22 *
23 * You should have received a copy of the GNU General Public License
24 * along with this program; if not, see the file COPYING, or write
25 * to the Free Software Foundation, Inc.,
26 * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
27 */
28
29#include <linux/init.h>
30#include <linux/module.h>
31#include <linux/version.h>
32#include <linux/kernel.h>
33#include <linux/device.h>
34#include <sound/core.h>
35#include <sound/pcm.h>
36#include <sound/pcm_params.h>
37#include <sound/initval.h>
38#include <sound/soc.h>
39#include <sound/tlv.h>
40#include <sound/soc-dapm.h>
41#include <linux/spi/spi.h>
42#include "ad1938.h"
43
44/* codec private data */
45struct ad1938_priv {
46 struct snd_soc_codec codec;
47 u8 reg_cache[AD1938_NUM_REGS];
48};
49
50static struct snd_soc_codec *ad1938_codec;
51struct snd_soc_codec_device soc_codec_dev_ad1938;
52static int ad1938_register(struct ad1938_priv *ad1938);
53static void ad1938_unregister(struct ad1938_priv *ad1938);
54
55/*
56 * AD1938 volume/mute/de-emphasis etc. controls
57 */
58static const char *ad1938_deemp[] = {"None", "48kHz", "44.1kHz", "32kHz"};
59
60static const struct soc_enum ad1938_deemp_enum =
61 SOC_ENUM_SINGLE(AD1938_DAC_CTRL2, 1, 4, ad1938_deemp);
62
63static const struct snd_kcontrol_new ad1938_snd_controls[] = {
64 /* DAC volume control */
65 SOC_DOUBLE_R("DAC1 Volume", AD1938_DAC_L1_VOL,
66 AD1938_DAC_R1_VOL, 0, 0xFF, 1),
67 SOC_DOUBLE_R("DAC2 Volume", AD1938_DAC_L2_VOL,
68 AD1938_DAC_R2_VOL, 0, 0xFF, 1),
69 SOC_DOUBLE_R("DAC3 Volume", AD1938_DAC_L3_VOL,
70 AD1938_DAC_R3_VOL, 0, 0xFF, 1),
71 SOC_DOUBLE_R("DAC4 Volume", AD1938_DAC_L4_VOL,
72 AD1938_DAC_R4_VOL, 0, 0xFF, 1),
73
74 /* ADC switch control */
75 SOC_DOUBLE("ADC1 Switch", AD1938_ADC_CTRL0, AD1938_ADCL1_MUTE,
76 AD1938_ADCR1_MUTE, 1, 1),
77 SOC_DOUBLE("ADC2 Switch", AD1938_ADC_CTRL0, AD1938_ADCL2_MUTE,
78 AD1938_ADCR2_MUTE, 1, 1),
79
80 /* DAC switch control */
81 SOC_DOUBLE("DAC1 Switch", AD1938_DAC_CHNL_MUTE, AD1938_DACL1_MUTE,
82 AD1938_DACR1_MUTE, 1, 1),
83 SOC_DOUBLE("DAC2 Switch", AD1938_DAC_CHNL_MUTE, AD1938_DACL2_MUTE,
84 AD1938_DACR2_MUTE, 1, 1),
85 SOC_DOUBLE("DAC3 Switch", AD1938_DAC_CHNL_MUTE, AD1938_DACL3_MUTE,
86 AD1938_DACR3_MUTE, 1, 1),
87 SOC_DOUBLE("DAC4 Switch", AD1938_DAC_CHNL_MUTE, AD1938_DACL4_MUTE,
88 AD1938_DACR4_MUTE, 1, 1),
89
90 /* ADC high-pass filter */
91 SOC_SINGLE("ADC High Pass Filter Switch", AD1938_ADC_CTRL0,
92 AD1938_ADC_HIGHPASS_FILTER, 1, 0),
93
94 /* DAC de-emphasis */
95 SOC_ENUM("Playback Deemphasis", ad1938_deemp_enum),
96};
97
98static const struct snd_soc_dapm_widget ad1938_dapm_widgets[] = {
99 SND_SOC_DAPM_DAC("DAC", "Playback", AD1938_DAC_CTRL0, 0, 1),
100 SND_SOC_DAPM_ADC("ADC", "Capture", SND_SOC_NOPM, 0, 0),
101 SND_SOC_DAPM_SUPPLY("ADC_PWR", AD1938_ADC_CTRL0, 0, 1, NULL, 0),
102 SND_SOC_DAPM_OUTPUT("DAC1OUT"),
103 SND_SOC_DAPM_OUTPUT("DAC2OUT"),
104 SND_SOC_DAPM_OUTPUT("DAC3OUT"),
105 SND_SOC_DAPM_OUTPUT("DAC4OUT"),
106 SND_SOC_DAPM_INPUT("ADC1IN"),
107 SND_SOC_DAPM_INPUT("ADC2IN"),
108};
109
110static const struct snd_soc_dapm_route audio_paths[] = {
111 { "DAC", NULL, "ADC_PWR" },
112 { "ADC", NULL, "ADC_PWR" },
113 { "DAC1OUT", "DAC1 Switch", "DAC" },
114 { "DAC2OUT", "DAC2 Switch", "DAC" },
115 { "DAC3OUT", "DAC3 Switch", "DAC" },
116 { "DAC4OUT", "DAC4 Switch", "DAC" },
117 { "ADC", "ADC1 Switch", "ADC1IN" },
118 { "ADC", "ADC2 Switch", "ADC2IN" },
119};
120
121/*
122 * DAI ops entries
123 */
124
125static int ad1938_mute(struct snd_soc_dai *dai, int mute)
126{
127 struct snd_soc_codec *codec = dai->codec;
128 int reg;
129
130 reg = codec->read(codec, AD1938_DAC_CTRL2);
131 reg = (mute > 0) ? reg | AD1938_DAC_MASTER_MUTE : reg &
132 (~AD1938_DAC_MASTER_MUTE);
133 codec->write(codec, AD1938_DAC_CTRL2, reg);
134
135 return 0;
136}
137
138static inline int ad1938_pll_powerctrl(struct snd_soc_codec *codec, int cmd)
139{
140 int reg = codec->read(codec, AD1938_PLL_CLK_CTRL0);
141 reg = (cmd > 0) ? reg & (~AD1938_PLL_POWERDOWN) : reg |
142 AD1938_PLL_POWERDOWN;
143 codec->write(codec, AD1938_PLL_CLK_CTRL0, reg);
144
145 return 0;
146}
147
148static int ad1938_set_tdm_slot(struct snd_soc_dai *dai, unsigned int tx_mask,
149 unsigned int mask, int slots, int width)
150{
151 struct snd_soc_codec *codec = dai->codec;
152 int dac_reg = codec->read(codec, AD1938_DAC_CTRL1);
153 int adc_reg = codec->read(codec, AD1938_ADC_CTRL2);
154
155 dac_reg &= ~AD1938_DAC_CHAN_MASK;
156 adc_reg &= ~AD1938_ADC_CHAN_MASK;
157
158 switch (slots) {
159 case 2:
160 dac_reg |= AD1938_DAC_2_CHANNELS << AD1938_DAC_CHAN_SHFT;
161 adc_reg |= AD1938_ADC_2_CHANNELS << AD1938_ADC_CHAN_SHFT;
162 break;
163 case 4:
164 dac_reg |= AD1938_DAC_4_CHANNELS << AD1938_DAC_CHAN_SHFT;
165 adc_reg |= AD1938_ADC_4_CHANNELS << AD1938_ADC_CHAN_SHFT;
166 break;
167 case 8:
168 dac_reg |= AD1938_DAC_8_CHANNELS << AD1938_DAC_CHAN_SHFT;
169 adc_reg |= AD1938_ADC_8_CHANNELS << AD1938_ADC_CHAN_SHFT;
170 break;
171 case 16:
172 dac_reg |= AD1938_DAC_16_CHANNELS << AD1938_DAC_CHAN_SHFT;
173 adc_reg |= AD1938_ADC_16_CHANNELS << AD1938_ADC_CHAN_SHFT;
174 break;
175 default:
176 return -EINVAL;
177 }
178
179 codec->write(codec, AD1938_DAC_CTRL1, dac_reg);
180 codec->write(codec, AD1938_ADC_CTRL2, adc_reg);
181
182 return 0;
183}
184
185static int ad1938_set_dai_fmt(struct snd_soc_dai *codec_dai,
186 unsigned int fmt)
187{
188 struct snd_soc_codec *codec = codec_dai->codec;
189 int adc_reg, dac_reg;
190
191 adc_reg = codec->read(codec, AD1938_ADC_CTRL2);
192 dac_reg = codec->read(codec, AD1938_DAC_CTRL1);
193
194 /* At present, the driver only support AUX ADC mode(SND_SOC_DAIFMT_I2S
195 * with TDM) and ADC&DAC TDM mode(SND_SOC_DAIFMT_DSP_A)
196 */
197 switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
198 case SND_SOC_DAIFMT_I2S:
199 adc_reg &= ~AD1938_ADC_SERFMT_MASK;
200 adc_reg |= AD1938_ADC_SERFMT_TDM;
201 break;
202 case SND_SOC_DAIFMT_DSP_A:
203 adc_reg &= ~AD1938_ADC_SERFMT_MASK;
204 adc_reg |= AD1938_ADC_SERFMT_AUX;
205 break;
206 default:
207 return -EINVAL;
208 }
209
210 switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
211 case SND_SOC_DAIFMT_NB_NF: /* normal bit clock + frame */
212 adc_reg &= ~AD1938_ADC_LEFT_HIGH;
213 adc_reg &= ~AD1938_ADC_BCLK_INV;
214 dac_reg &= ~AD1938_DAC_LEFT_HIGH;
215 dac_reg &= ~AD1938_DAC_BCLK_INV;
216 break;
217 case SND_SOC_DAIFMT_NB_IF: /* normal bclk + invert frm */
218 adc_reg |= AD1938_ADC_LEFT_HIGH;
219 adc_reg &= ~AD1938_ADC_BCLK_INV;
220 dac_reg |= AD1938_DAC_LEFT_HIGH;
221 dac_reg &= ~AD1938_DAC_BCLK_INV;
222 break;
223 case SND_SOC_DAIFMT_IB_NF: /* invert bclk + normal frm */
224 adc_reg &= ~AD1938_ADC_LEFT_HIGH;
225 adc_reg |= AD1938_ADC_BCLK_INV;
226 dac_reg &= ~AD1938_DAC_LEFT_HIGH;
227 dac_reg |= AD1938_DAC_BCLK_INV;
228 break;
229
230 case SND_SOC_DAIFMT_IB_IF: /* invert bclk + frm */
231 adc_reg |= AD1938_ADC_LEFT_HIGH;
232 adc_reg |= AD1938_ADC_BCLK_INV;
233 dac_reg |= AD1938_DAC_LEFT_HIGH;
234 dac_reg |= AD1938_DAC_BCLK_INV;
235 break;
236 default:
237 return -EINVAL;
238 }
239
240 switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
241 case SND_SOC_DAIFMT_CBM_CFM: /* codec clk & frm master */
242 adc_reg |= AD1938_ADC_LCR_MASTER;
243 adc_reg |= AD1938_ADC_BCLK_MASTER;
244 dac_reg |= AD1938_DAC_LCR_MASTER;
245 dac_reg |= AD1938_DAC_BCLK_MASTER;
246 break;
247 case SND_SOC_DAIFMT_CBS_CFM: /* codec clk slave & frm master */
248 adc_reg |= AD1938_ADC_LCR_MASTER;
249 adc_reg &= ~AD1938_ADC_BCLK_MASTER;
250 dac_reg |= AD1938_DAC_LCR_MASTER;
251 dac_reg &= ~AD1938_DAC_BCLK_MASTER;
252 break;
253 case SND_SOC_DAIFMT_CBM_CFS: /* codec clk master & frame slave */
254 adc_reg &= ~AD1938_ADC_LCR_MASTER;
255 adc_reg |= AD1938_ADC_BCLK_MASTER;
256 dac_reg &= ~AD1938_DAC_LCR_MASTER;
257 dac_reg |= AD1938_DAC_BCLK_MASTER;
258 break;
259 case SND_SOC_DAIFMT_CBS_CFS: /* codec clk & frm slave */
260 adc_reg &= ~AD1938_ADC_LCR_MASTER;
261 adc_reg &= ~AD1938_ADC_BCLK_MASTER;
262 dac_reg &= ~AD1938_DAC_LCR_MASTER;
263 dac_reg &= ~AD1938_DAC_BCLK_MASTER;
264 break;
265 default:
266 return -EINVAL;
267 }
268
269 codec->write(codec, AD1938_ADC_CTRL2, adc_reg);
270 codec->write(codec, AD1938_DAC_CTRL1, dac_reg);
271
272 return 0;
273}
274
275static int ad1938_hw_params(struct snd_pcm_substream *substream,
276 struct snd_pcm_hw_params *params,
277 struct snd_soc_dai *dai)
278{
279 int word_len = 0, reg = 0;
280
281 struct snd_soc_pcm_runtime *rtd = substream->private_data;
282 struct snd_soc_device *socdev = rtd->socdev;
283 struct snd_soc_codec *codec = socdev->card->codec;
284
285 /* bit size */
286 switch (params_format(params)) {
287 case SNDRV_PCM_FORMAT_S16_LE:
288 word_len = 3;
289 break;
290 case SNDRV_PCM_FORMAT_S20_3LE:
291 word_len = 1;
292 break;
293 case SNDRV_PCM_FORMAT_S24_LE:
294 case SNDRV_PCM_FORMAT_S32_LE:
295 word_len = 0;
296 break;
297 }
298
299 reg = codec->read(codec, AD1938_DAC_CTRL2);
300 reg = (reg & (~AD1938_DAC_WORD_LEN_MASK)) | word_len;
301 codec->write(codec, AD1938_DAC_CTRL2, reg);
302
303 reg = codec->read(codec, AD1938_ADC_CTRL1);
304 reg = (reg & (~AD1938_ADC_WORD_LEN_MASK)) | word_len;
305 codec->write(codec, AD1938_ADC_CTRL1, reg);
306
307 return 0;
308}
309
310static int ad1938_set_bias_level(struct snd_soc_codec *codec,
311 enum snd_soc_bias_level level)
312{
313 switch (level) {
314 case SND_SOC_BIAS_ON:
315 ad1938_pll_powerctrl(codec, 1);
316 break;
317 case SND_SOC_BIAS_PREPARE:
318 break;
319 case SND_SOC_BIAS_STANDBY:
320 case SND_SOC_BIAS_OFF:
321 ad1938_pll_powerctrl(codec, 0);
322 break;
323 }
324 codec->bias_level = level;
325 return 0;
326}
327
328/*
329 * interface to read/write ad1938 register
330 */
331
332#define AD1938_SPI_ADDR 0x4
333#define AD1938_SPI_READ 0x1
334#define AD1938_SPI_BUFLEN 3
335
336/*
337 * write to the ad1938 register space
338 */
339
340static int ad1938_write_reg(struct snd_soc_codec *codec, unsigned int reg,
341 unsigned int value)
342{
343 u8 *reg_cache = codec->reg_cache;
344 int ret = 0;
345
346 if (value != reg_cache[reg]) {
347 uint8_t buf[AD1938_SPI_BUFLEN];
348 struct spi_transfer t = {
349 .tx_buf = buf,
350 .len = AD1938_SPI_BUFLEN,
351 };
352 struct spi_message m;
353
354 buf[0] = AD1938_SPI_ADDR << 1;
355 buf[1] = reg;
356 buf[2] = value;
357 spi_message_init(&m);
358 spi_message_add_tail(&t, &m);
359 ret = spi_sync(codec->control_data, &m);
360 if (ret == 0)
361 reg_cache[reg] = value;
362 }
363
364 return ret;
365}
366
367/*
368 * read from the ad1938 register space cache
369 */
370
371static unsigned int ad1938_read_reg_cache(struct snd_soc_codec *codec,
372 unsigned int reg)
373{
374 u8 *reg_cache = codec->reg_cache;
375
376 if (reg >= codec->reg_cache_size)
377 return -EINVAL;
378
379 return reg_cache[reg];
380}
381
382/*
383 * read from the ad1938 register space
384 */
385
386static unsigned int ad1938_read_reg(struct snd_soc_codec *codec,
387 unsigned int reg)
388{
389 char w_buf[AD1938_SPI_BUFLEN];
390 char r_buf[AD1938_SPI_BUFLEN];
391 int ret;
392
393 struct spi_transfer t = {
394 .tx_buf = w_buf,
395 .rx_buf = r_buf,
396 .len = AD1938_SPI_BUFLEN,
397 };
398 struct spi_message m;
399
400 w_buf[0] = (AD1938_SPI_ADDR << 1) | AD1938_SPI_READ;
401 w_buf[1] = reg;
402 w_buf[2] = 0;
403
404 spi_message_init(&m);
405 spi_message_add_tail(&t, &m);
406 ret = spi_sync(codec->control_data, &m);
407 if (ret == 0)
408 return r_buf[2];
409 else
410 return -EIO;
411}
412
413static int ad1938_fill_cache(struct snd_soc_codec *codec)
414{
415 int i;
416 u8 *reg_cache = codec->reg_cache;
417 struct spi_device *spi = codec->control_data;
418
419 for (i = 0; i < codec->reg_cache_size; i++) {
420 int ret = ad1938_read_reg(codec, i);
421 if (ret == -EIO) {
422 dev_err(&spi->dev, "AD1938 SPI read failure\n");
423 return ret;
424 }
425 reg_cache[i] = ret;
426 }
427
428 return 0;
429}
430
431static int __devinit ad1938_spi_probe(struct spi_device *spi)
432{
433 struct snd_soc_codec *codec;
434 struct ad1938_priv *ad1938;
435
436 ad1938 = kzalloc(sizeof(struct ad1938_priv), GFP_KERNEL);
437 if (ad1938 == NULL)
438 return -ENOMEM;
439
440 codec = &ad1938->codec;
441 codec->control_data = spi;
442 codec->dev = &spi->dev;
443
444 dev_set_drvdata(&spi->dev, ad1938);
445
446 return ad1938_register(ad1938);
447}
448
449static int __devexit ad1938_spi_remove(struct spi_device *spi)
450{
451 struct ad1938_priv *ad1938 = dev_get_drvdata(&spi->dev);
452
453 ad1938_unregister(ad1938);
454 return 0;
455}
456
457static struct spi_driver ad1938_spi_driver = {
458 .driver = {
459 .name = "ad1938",
460 .bus = &spi_bus_type,
461 .owner = THIS_MODULE,
462 },
463 .probe = ad1938_spi_probe,
464 .remove = __devexit_p(ad1938_spi_remove),
465};
466
467static struct snd_soc_dai_ops ad1938_dai_ops = {
468 .hw_params = ad1938_hw_params,
469 .digital_mute = ad1938_mute,
470 .set_tdm_slot = ad1938_set_tdm_slot,
471 .set_fmt = ad1938_set_dai_fmt,
472};
473
474/* codec DAI instance */
475struct snd_soc_dai ad1938_dai = {
476 .name = "AD1938",
477 .playback = {
478 .stream_name = "Playback",
479 .channels_min = 2,
480 .channels_max = 8,
481 .rates = SNDRV_PCM_RATE_48000,
482 .formats = SNDRV_PCM_FMTBIT_S32_LE | SNDRV_PCM_FMTBIT_S16_LE |
483 SNDRV_PCM_FMTBIT_S20_3LE | SNDRV_PCM_FMTBIT_S24_LE,
484 },
485 .capture = {
486 .stream_name = "Capture",
487 .channels_min = 2,
488 .channels_max = 4,
489 .rates = SNDRV_PCM_RATE_48000,
490 .formats = SNDRV_PCM_FMTBIT_S32_LE | SNDRV_PCM_FMTBIT_S16_LE |
491 SNDRV_PCM_FMTBIT_S20_3LE | SNDRV_PCM_FMTBIT_S24_LE,
492 },
493 .ops = &ad1938_dai_ops,
494};
495EXPORT_SYMBOL_GPL(ad1938_dai);
496
497static int ad1938_register(struct ad1938_priv *ad1938)
498{
499 int ret;
500 struct snd_soc_codec *codec = &ad1938->codec;
501
502 if (ad1938_codec) {
503 dev_err(codec->dev, "Another ad1938 is registered\n");
504 return -EINVAL;
505 }
506
507 mutex_init(&codec->mutex);
508 INIT_LIST_HEAD(&codec->dapm_widgets);
509 INIT_LIST_HEAD(&codec->dapm_paths);
510 codec->private_data = ad1938;
511 codec->reg_cache = ad1938->reg_cache;
512 codec->reg_cache_size = AD1938_NUM_REGS;
513 codec->name = "AD1938";
514 codec->owner = THIS_MODULE;
515 codec->dai = &ad1938_dai;
516 codec->num_dai = 1;
517 codec->write = ad1938_write_reg;
518 codec->read = ad1938_read_reg_cache;
519 INIT_LIST_HEAD(&codec->dapm_widgets);
520 INIT_LIST_HEAD(&codec->dapm_paths);
521
522 ad1938_dai.dev = codec->dev;
523 ad1938_codec = codec;
524
525 /* default setting for ad1938 */
526
527 /* unmute dac channels */
528 codec->write(codec, AD1938_DAC_CHNL_MUTE, 0x0);
529 /* de-emphasis: 48kHz, powedown dac */
530 codec->write(codec, AD1938_DAC_CTRL2, 0x1A);
531 /* powerdown dac, dac in tdm mode */
532 codec->write(codec, AD1938_DAC_CTRL0, 0x41);
533 /* high-pass filter enable */
534 codec->write(codec, AD1938_ADC_CTRL0, 0x3);
535 /* sata delay=1, adc aux mode */
536 codec->write(codec, AD1938_ADC_CTRL1, 0x43);
537 /* pll input: mclki/xi */
538 codec->write(codec, AD1938_PLL_CLK_CTRL0, 0x9D);
539 codec->write(codec, AD1938_PLL_CLK_CTRL1, 0x04);
540
541 ad1938_fill_cache(codec);
542
543 ret = snd_soc_register_codec(codec);
544 if (ret != 0) {
545 dev_err(codec->dev, "Failed to register codec: %d\n", ret);
546 kfree(ad1938);
547 return ret;
548 }
549
550 ret = snd_soc_register_dai(&ad1938_dai);
551 if (ret != 0) {
552 dev_err(codec->dev, "Failed to register DAI: %d\n", ret);
553 snd_soc_unregister_codec(codec);
554 kfree(ad1938);
555 return ret;
556 }
557
558 return 0;
559}
560
561static void ad1938_unregister(struct ad1938_priv *ad1938)
562{
563 ad1938_set_bias_level(&ad1938->codec, SND_SOC_BIAS_OFF);
564 snd_soc_unregister_dai(&ad1938_dai);
565 snd_soc_unregister_codec(&ad1938->codec);
566 kfree(ad1938);
567 ad1938_codec = NULL;
568}
569
570static int ad1938_probe(struct platform_device *pdev)
571{
572 struct snd_soc_device *socdev = platform_get_drvdata(pdev);
573 struct snd_soc_codec *codec;
574 int ret = 0;
575
576 if (ad1938_codec == NULL) {
577 dev_err(&pdev->dev, "Codec device not registered\n");
578 return -ENODEV;
579 }
580
581 socdev->card->codec = ad1938_codec;
582 codec = ad1938_codec;
583
584 /* register pcms */
585 ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1);
586 if (ret < 0) {
587 dev_err(codec->dev, "failed to create pcms: %d\n", ret);
588 goto pcm_err;
589 }
590
591 snd_soc_add_controls(codec, ad1938_snd_controls,
592 ARRAY_SIZE(ad1938_snd_controls));
593 snd_soc_dapm_new_controls(codec, ad1938_dapm_widgets,
594 ARRAY_SIZE(ad1938_dapm_widgets));
595 snd_soc_dapm_add_routes(codec, audio_paths, ARRAY_SIZE(audio_paths));
596 snd_soc_dapm_new_widgets(codec);
597
598 ad1938_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
599
600 ret = snd_soc_init_card(socdev);
601 if (ret < 0) {
602 dev_err(codec->dev, "failed to register card: %d\n", ret);
603 goto card_err;
604 }
605
606 return ret;
607
608card_err:
609 snd_soc_free_pcms(socdev);
610 snd_soc_dapm_free(socdev);
611pcm_err:
612 return ret;
613}
614
615/* power down chip */
616static int ad1938_remove(struct platform_device *pdev)
617{
618 struct snd_soc_device *socdev = platform_get_drvdata(pdev);
619
620 snd_soc_free_pcms(socdev);
621 snd_soc_dapm_free(socdev);
622
623 return 0;
624}
625
626#ifdef CONFIG_PM
627static int ad1938_suspend(struct platform_device *pdev,
628 pm_message_t state)
629{
630 struct snd_soc_device *socdev = platform_get_drvdata(pdev);
631 struct snd_soc_codec *codec = socdev->card->codec;
632
633 ad1938_set_bias_level(codec, SND_SOC_BIAS_OFF);
634 return 0;
635}
636
637static int ad1938_resume(struct platform_device *pdev)
638{
639 struct snd_soc_device *socdev = platform_get_drvdata(pdev);
640 struct snd_soc_codec *codec = socdev->card->codec;
641
642 if (codec->suspend_bias_level == SND_SOC_BIAS_ON)
643 ad1938_set_bias_level(codec, SND_SOC_BIAS_ON);
644
645 return 0;
646}
647#else
648#define ad1938_suspend NULL
649#define ad1938_resume NULL
650#endif
651
652struct snd_soc_codec_device soc_codec_dev_ad1938 = {
653 .probe = ad1938_probe,
654 .remove = ad1938_remove,
655 .suspend = ad1938_suspend,
656 .resume = ad1938_resume,
657};
658EXPORT_SYMBOL_GPL(soc_codec_dev_ad1938);
659
660static int __init ad1938_init(void)
661{
662 int ret;
663
664 ret = spi_register_driver(&ad1938_spi_driver);
665 if (ret != 0) {
666 printk(KERN_ERR "Failed to register ad1938 SPI driver: %d\n",
667 ret);
668 }
669
670 return ret;
671}
672module_init(ad1938_init);
673
674static void __exit ad1938_exit(void)
675{
676 spi_unregister_driver(&ad1938_spi_driver);
677}
678module_exit(ad1938_exit);
679
680MODULE_DESCRIPTION("ASoC ad1938 driver");
681MODULE_AUTHOR("Barry Song ");
682MODULE_LICENSE("GPL");
diff --git a/sound/soc/codecs/ad1938.h b/sound/soc/codecs/ad1938.h
new file mode 100644
index 000000000000..fe3c48cd2d5b
--- /dev/null
+++ b/sound/soc/codecs/ad1938.h
@@ -0,0 +1,100 @@
1/*
2 * File: sound/soc/codecs/ad1836.h
3 * Based on:
4 * Author: Barry Song <Barry.Song@analog.com>
5 *
6 * Created: May 25, 2009
7 * Description: definitions for AD1938 registers
8 *
9 * Modified:
10 *
11 * Bugs: Enter bugs at http://blackfin.uclinux.org/
12 *
13 * This program is free software; you can redistribute it and/or modify
14 * it under the terms of the GNU General Public License as published by
15 * the Free Software Foundation; either version 2 of the License, or
16 * (at your option) any later version.
17 *
18 * This program is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU General Public License for more details.
22 *
23 * You should have received a copy of the GNU General Public License
24 * along with this program; if not, see the file COPYING, or write
25 * to the Free Software Foundation, Inc.,
26 * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
27 */
28
29#ifndef __AD1938_H__
30#define __AD1938_H__
31
32#define AD1938_PLL_CLK_CTRL0 0
33#define AD1938_PLL_POWERDOWN 0x01
34#define AD1938_PLL_CLK_CTRL1 1
35#define AD1938_DAC_CTRL0 2
36#define AD1938_DAC_POWERDOWN 0x01
37#define AD1938_DAC_SERFMT_MASK 0xC0
38#define AD1938_DAC_SERFMT_STEREO (0 << 6)
39#define AD1938_DAC_SERFMT_TDM (1 << 6)
40#define AD1938_DAC_CTRL1 3
41#define AD1938_DAC_2_CHANNELS 0
42#define AD1938_DAC_4_CHANNELS 1
43#define AD1938_DAC_8_CHANNELS 2
44#define AD1938_DAC_16_CHANNELS 3
45#define AD1938_DAC_CHAN_SHFT 1
46#define AD1938_DAC_CHAN_MASK (3 << AD1938_DAC_CHAN_SHFT)
47#define AD1938_DAC_LCR_MASTER (1 << 4)
48#define AD1938_DAC_BCLK_MASTER (1 << 5)
49#define AD1938_DAC_LEFT_HIGH (1 << 3)
50#define AD1938_DAC_BCLK_INV (1 << 7)
51#define AD1938_DAC_CTRL2 4
52#define AD1938_DAC_WORD_LEN_MASK 0xC
53#define AD1938_DAC_MASTER_MUTE 1
54#define AD1938_DAC_CHNL_MUTE 5
55#define AD1938_DACL1_MUTE 0
56#define AD1938_DACR1_MUTE 1
57#define AD1938_DACL2_MUTE 2
58#define AD1938_DACR2_MUTE 3
59#define AD1938_DACL3_MUTE 4
60#define AD1938_DACR3_MUTE 5
61#define AD1938_DACL4_MUTE 6
62#define AD1938_DACR4_MUTE 7
63#define AD1938_DAC_L1_VOL 6
64#define AD1938_DAC_R1_VOL 7
65#define AD1938_DAC_L2_VOL 8
66#define AD1938_DAC_R2_VOL 9
67#define AD1938_DAC_L3_VOL 10
68#define AD1938_DAC_R3_VOL 11
69#define AD1938_DAC_L4_VOL 12
70#define AD1938_DAC_R4_VOL 13
71#define AD1938_ADC_CTRL0 14
72#define AD1938_ADC_POWERDOWN 0x01
73#define AD1938_ADC_HIGHPASS_FILTER 1
74#define AD1938_ADCL1_MUTE 2
75#define AD1938_ADCR1_MUTE 3
76#define AD1938_ADCL2_MUTE 4
77#define AD1938_ADCR2_MUTE 5
78#define AD1938_ADC_CTRL1 15
79#define AD1938_ADC_SERFMT_MASK 0x60
80#define AD1938_ADC_SERFMT_STEREO (0 << 5)
81#define AD1938_ADC_SERFMT_TDM (1 << 2)
82#define AD1938_ADC_SERFMT_AUX (2 << 5)
83#define AD1938_ADC_WORD_LEN_MASK 0x3
84#define AD1938_ADC_CTRL2 16
85#define AD1938_ADC_2_CHANNELS 0
86#define AD1938_ADC_4_CHANNELS 1
87#define AD1938_ADC_8_CHANNELS 2
88#define AD1938_ADC_16_CHANNELS 3
89#define AD1938_ADC_CHAN_SHFT 4
90#define AD1938_ADC_CHAN_MASK (3 << AD1938_ADC_CHAN_SHFT)
91#define AD1938_ADC_LCR_MASTER (1 << 3)
92#define AD1938_ADC_BCLK_MASTER (1 << 6)
93#define AD1938_ADC_LEFT_HIGH (1 << 2)
94#define AD1938_ADC_BCLK_INV (1 << 1)
95
96#define AD1938_NUM_REGS 17
97
98extern struct snd_soc_dai ad1938_dai;
99extern struct snd_soc_codec_device soc_codec_dev_ad1938;
100#endif
diff --git a/sound/soc/codecs/ad1980.c b/sound/soc/codecs/ad1980.c
index ddb3b08ac23c..d7440a982d22 100644
--- a/sound/soc/codecs/ad1980.c
+++ b/sound/soc/codecs/ad1980.c
@@ -137,13 +137,13 @@ struct snd_soc_dai ad1980_dai = {
137 .channels_min = 2, 137 .channels_min = 2,
138 .channels_max = 6, 138 .channels_max = 6,
139 .rates = SNDRV_PCM_RATE_48000, 139 .rates = SNDRV_PCM_RATE_48000,
140 .formats = SNDRV_PCM_FMTBIT_S16_LE, }, 140 .formats = SND_SOC_STD_AC97_FMTS, },
141 .capture = { 141 .capture = {
142 .stream_name = "Capture", 142 .stream_name = "Capture",
143 .channels_min = 2, 143 .channels_min = 2,
144 .channels_max = 2, 144 .channels_max = 2,
145 .rates = SNDRV_PCM_RATE_48000, 145 .rates = SNDRV_PCM_RATE_48000,
146 .formats = SNDRV_PCM_FMTBIT_S16_LE, }, 146 .formats = SND_SOC_STD_AC97_FMTS, },
147}; 147};
148EXPORT_SYMBOL_GPL(ad1980_dai); 148EXPORT_SYMBOL_GPL(ad1980_dai);
149 149
diff --git a/sound/soc/codecs/ak4535.c b/sound/soc/codecs/ak4535.c
index dd3380202766..0abec0d29a96 100644
--- a/sound/soc/codecs/ak4535.c
+++ b/sound/soc/codecs/ak4535.c
@@ -59,21 +59,6 @@ static inline unsigned int ak4535_read_reg_cache(struct snd_soc_codec *codec,
59 return cache[reg]; 59 return cache[reg];
60} 60}
61 61
62static inline unsigned int ak4535_read(struct snd_soc_codec *codec,
63 unsigned int reg)
64{
65 u8 data;
66 data = reg;
67
68 if (codec->hw_write(codec->control_data, &data, 1) != 1)
69 return -EIO;
70
71 if (codec->hw_read(codec->control_data, &data, 1) != 1)
72 return -EIO;
73
74 return data;
75};
76
77/* 62/*
78 * write ak4535 register cache 63 * write ak4535 register cache
79 */ 64 */
@@ -635,7 +620,6 @@ static int ak4535_probe(struct platform_device *pdev)
635#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) 620#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
636 if (setup->i2c_address) { 621 if (setup->i2c_address) {
637 codec->hw_write = (hw_write_t)i2c_master_send; 622 codec->hw_write = (hw_write_t)i2c_master_send;
638 codec->hw_read = (hw_read_t)i2c_master_recv;
639 ret = ak4535_add_i2c_device(pdev, setup); 623 ret = ak4535_add_i2c_device(pdev, setup);
640 } 624 }
641#endif 625#endif
diff --git a/sound/soc/codecs/cs4270.c b/sound/soc/codecs/cs4270.c
index 7fa09a387622..ca1e24a8f12a 100644
--- a/sound/soc/codecs/cs4270.c
+++ b/sound/soc/codecs/cs4270.c
@@ -18,7 +18,7 @@
18 * - The machine driver's 'startup' function must call 18 * - The machine driver's 'startup' function must call
19 * cs4270_set_dai_sysclk() with the value of MCLK. 19 * cs4270_set_dai_sysclk() with the value of MCLK.
20 * - Only I2S and left-justified modes are supported 20 * - Only I2S and left-justified modes are supported
21 * - Power management is not supported 21 * - Power management is supported
22 */ 22 */
23 23
24#include <linux/module.h> 24#include <linux/module.h>
@@ -27,6 +27,7 @@
27#include <sound/soc.h> 27#include <sound/soc.h>
28#include <sound/initval.h> 28#include <sound/initval.h>
29#include <linux/i2c.h> 29#include <linux/i2c.h>
30#include <linux/delay.h>
30 31
31#include "cs4270.h" 32#include "cs4270.h"
32 33
@@ -56,6 +57,7 @@
56#define CS4270_FIRSTREG 0x01 57#define CS4270_FIRSTREG 0x01
57#define CS4270_LASTREG 0x08 58#define CS4270_LASTREG 0x08
58#define CS4270_NUMREGS (CS4270_LASTREG - CS4270_FIRSTREG + 1) 59#define CS4270_NUMREGS (CS4270_LASTREG - CS4270_FIRSTREG + 1)
60#define CS4270_I2C_INCR 0x80
59 61
60/* Bit masks for the CS4270 registers */ 62/* Bit masks for the CS4270 registers */
61#define CS4270_CHIPID_ID 0xF0 63#define CS4270_CHIPID_ID 0xF0
@@ -64,6 +66,8 @@
64#define CS4270_PWRCTL_PDN_ADC 0x20 66#define CS4270_PWRCTL_PDN_ADC 0x20
65#define CS4270_PWRCTL_PDN_DAC 0x02 67#define CS4270_PWRCTL_PDN_DAC 0x02
66#define CS4270_PWRCTL_PDN 0x01 68#define CS4270_PWRCTL_PDN 0x01
69#define CS4270_PWRCTL_PDN_ALL \
70 (CS4270_PWRCTL_PDN_ADC | CS4270_PWRCTL_PDN_DAC | CS4270_PWRCTL_PDN)
67#define CS4270_MODE_SPEED_MASK 0x30 71#define CS4270_MODE_SPEED_MASK 0x30
68#define CS4270_MODE_1X 0x00 72#define CS4270_MODE_1X 0x00
69#define CS4270_MODE_2X 0x10 73#define CS4270_MODE_2X 0x10
@@ -109,6 +113,7 @@ struct cs4270_private {
109 unsigned int mclk; /* Input frequency of the MCLK pin */ 113 unsigned int mclk; /* Input frequency of the MCLK pin */
110 unsigned int mode; /* The mode (I2S or left-justified) */ 114 unsigned int mode; /* The mode (I2S or left-justified) */
111 unsigned int slave_mode; 115 unsigned int slave_mode;
116 unsigned int manual_mute;
112}; 117};
113 118
114/** 119/**
@@ -295,7 +300,7 @@ static int cs4270_fill_cache(struct snd_soc_codec *codec)
295 s32 length; 300 s32 length;
296 301
297 length = i2c_smbus_read_i2c_block_data(i2c_client, 302 length = i2c_smbus_read_i2c_block_data(i2c_client,
298 CS4270_FIRSTREG | 0x80, CS4270_NUMREGS, cache); 303 CS4270_FIRSTREG | CS4270_I2C_INCR, CS4270_NUMREGS, cache);
299 304
300 if (length != CS4270_NUMREGS) { 305 if (length != CS4270_NUMREGS) {
301 dev_err(codec->dev, "i2c read failure, addr=0x%x\n", 306 dev_err(codec->dev, "i2c read failure, addr=0x%x\n",
@@ -453,7 +458,7 @@ static int cs4270_hw_params(struct snd_pcm_substream *substream,
453} 458}
454 459
455/** 460/**
456 * cs4270_mute - enable/disable the CS4270 external mute 461 * cs4270_dai_mute - enable/disable the CS4270 external mute
457 * @dai: the SOC DAI 462 * @dai: the SOC DAI
458 * @mute: 0 = disable mute, 1 = enable mute 463 * @mute: 0 = disable mute, 1 = enable mute
459 * 464 *
@@ -462,21 +467,52 @@ static int cs4270_hw_params(struct snd_pcm_substream *substream,
462 * board does not have the MUTEA or MUTEB pins connected to such circuitry, 467 * board does not have the MUTEA or MUTEB pins connected to such circuitry,
463 * then this function will do nothing. 468 * then this function will do nothing.
464 */ 469 */
465static int cs4270_mute(struct snd_soc_dai *dai, int mute) 470static int cs4270_dai_mute(struct snd_soc_dai *dai, int mute)
466{ 471{
467 struct snd_soc_codec *codec = dai->codec; 472 struct snd_soc_codec *codec = dai->codec;
473 struct cs4270_private *cs4270 = codec->private_data;
468 int reg6; 474 int reg6;
469 475
470 reg6 = snd_soc_read(codec, CS4270_MUTE); 476 reg6 = snd_soc_read(codec, CS4270_MUTE);
471 477
472 if (mute) 478 if (mute)
473 reg6 |= CS4270_MUTE_DAC_A | CS4270_MUTE_DAC_B; 479 reg6 |= CS4270_MUTE_DAC_A | CS4270_MUTE_DAC_B;
474 else 480 else {
475 reg6 &= ~(CS4270_MUTE_DAC_A | CS4270_MUTE_DAC_B); 481 reg6 &= ~(CS4270_MUTE_DAC_A | CS4270_MUTE_DAC_B);
482 reg6 |= cs4270->manual_mute;
483 }
476 484
477 return snd_soc_write(codec, CS4270_MUTE, reg6); 485 return snd_soc_write(codec, CS4270_MUTE, reg6);
478} 486}
479 487
488/**
489 * cs4270_soc_put_mute - put callback for the 'Master Playback switch'
490 * alsa control.
491 * @kcontrol: mixer control
492 * @ucontrol: control element information
493 *
494 * This function basically passes the arguments on to the generic
495 * snd_soc_put_volsw() function and saves the mute information in
496 * our private data structure. This is because we want to prevent
497 * cs4270_dai_mute() neglecting the user's decision to manually
498 * mute the codec's output.
499 *
500 * Returns 0 for success.
501 */
502static int cs4270_soc_put_mute(struct snd_kcontrol *kcontrol,
503 struct snd_ctl_elem_value *ucontrol)
504{
505 struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
506 struct cs4270_private *cs4270 = codec->private_data;
507 int left = !ucontrol->value.integer.value[0];
508 int right = !ucontrol->value.integer.value[1];
509
510 cs4270->manual_mute = (left ? CS4270_MUTE_DAC_A : 0) |
511 (right ? CS4270_MUTE_DAC_B : 0);
512
513 return snd_soc_put_volsw(kcontrol, ucontrol);
514}
515
480/* A list of non-DAPM controls that the CS4270 supports */ 516/* A list of non-DAPM controls that the CS4270 supports */
481static const struct snd_kcontrol_new cs4270_snd_controls[] = { 517static const struct snd_kcontrol_new cs4270_snd_controls[] = {
482 SOC_DOUBLE_R("Master Playback Volume", 518 SOC_DOUBLE_R("Master Playback Volume",
@@ -486,7 +522,9 @@ static const struct snd_kcontrol_new cs4270_snd_controls[] = {
486 SOC_SINGLE("Zero Cross Switch", CS4270_TRANS, 5, 1, 0), 522 SOC_SINGLE("Zero Cross Switch", CS4270_TRANS, 5, 1, 0),
487 SOC_SINGLE("Popguard Switch", CS4270_MODE, 0, 1, 1), 523 SOC_SINGLE("Popguard Switch", CS4270_MODE, 0, 1, 1),
488 SOC_SINGLE("Auto-Mute Switch", CS4270_MUTE, 5, 1, 0), 524 SOC_SINGLE("Auto-Mute Switch", CS4270_MUTE, 5, 1, 0),
489 SOC_DOUBLE("Master Capture Switch", CS4270_MUTE, 3, 4, 1, 0) 525 SOC_DOUBLE("Master Capture Switch", CS4270_MUTE, 3, 4, 1, 1),
526 SOC_DOUBLE_EXT("Master Playback Switch", CS4270_MUTE, 0, 1, 1, 1,
527 snd_soc_get_volsw, cs4270_soc_put_mute),
490}; 528};
491 529
492/* 530/*
@@ -506,7 +544,7 @@ static struct snd_soc_dai_ops cs4270_dai_ops = {
506 .hw_params = cs4270_hw_params, 544 .hw_params = cs4270_hw_params,
507 .set_sysclk = cs4270_set_dai_sysclk, 545 .set_sysclk = cs4270_set_dai_sysclk,
508 .set_fmt = cs4270_set_dai_fmt, 546 .set_fmt = cs4270_set_dai_fmt,
509 .digital_mute = cs4270_mute, 547 .digital_mute = cs4270_dai_mute,
510}; 548};
511 549
512struct snd_soc_dai cs4270_dai = { 550struct snd_soc_dai cs4270_dai = {
@@ -753,6 +791,74 @@ static struct i2c_device_id cs4270_id[] = {
753}; 791};
754MODULE_DEVICE_TABLE(i2c, cs4270_id); 792MODULE_DEVICE_TABLE(i2c, cs4270_id);
755 793
794#ifdef CONFIG_PM
795
796/* This suspend/resume implementation can handle both - a simple standby
797 * where the codec remains powered, and a full suspend, where the voltage
798 * domain the codec is connected to is teared down and/or any other hardware
799 * reset condition is asserted.
800 *
801 * The codec's own power saving features are enabled in the suspend callback,
802 * and all registers are written back to the hardware when resuming.
803 */
804
805static int cs4270_i2c_suspend(struct i2c_client *client, pm_message_t mesg)
806{
807 struct cs4270_private *cs4270 = i2c_get_clientdata(client);
808 struct snd_soc_codec *codec = &cs4270->codec;
809
810 return snd_soc_suspend_device(codec->dev);
811}
812
813static int cs4270_i2c_resume(struct i2c_client *client)
814{
815 struct cs4270_private *cs4270 = i2c_get_clientdata(client);
816 struct snd_soc_codec *codec = &cs4270->codec;
817
818 return snd_soc_resume_device(codec->dev);
819}
820
821static int cs4270_soc_suspend(struct platform_device *pdev, pm_message_t mesg)
822{
823 struct snd_soc_codec *codec = cs4270_codec;
824 int reg = snd_soc_read(codec, CS4270_PWRCTL) | CS4270_PWRCTL_PDN_ALL;
825
826 return snd_soc_write(codec, CS4270_PWRCTL, reg);
827}
828
829static int cs4270_soc_resume(struct platform_device *pdev)
830{
831 struct snd_soc_codec *codec = cs4270_codec;
832 struct i2c_client *i2c_client = codec->control_data;
833 int reg;
834
835 /* In case the device was put to hard reset during sleep, we need to
836 * wait 500ns here before any I2C communication. */
837 ndelay(500);
838
839 /* first restore the entire register cache ... */
840 for (reg = CS4270_FIRSTREG; reg <= CS4270_LASTREG; reg++) {
841 u8 val = snd_soc_read(codec, reg);
842
843 if (i2c_smbus_write_byte_data(i2c_client, reg, val)) {
844 dev_err(codec->dev, "i2c write failed\n");
845 return -EIO;
846 }
847 }
848
849 /* ... then disable the power-down bits */
850 reg = snd_soc_read(codec, CS4270_PWRCTL);
851 reg &= ~CS4270_PWRCTL_PDN_ALL;
852
853 return snd_soc_write(codec, CS4270_PWRCTL, reg);
854}
855#else
856#define cs4270_i2c_suspend NULL
857#define cs4270_i2c_resume NULL
858#define cs4270_soc_suspend NULL
859#define cs4270_soc_resume NULL
860#endif /* CONFIG_PM */
861
756/* 862/*
757 * cs4270_i2c_driver - I2C device identification 863 * cs4270_i2c_driver - I2C device identification
758 * 864 *
@@ -767,6 +873,8 @@ static struct i2c_driver cs4270_i2c_driver = {
767 .id_table = cs4270_id, 873 .id_table = cs4270_id,
768 .probe = cs4270_i2c_probe, 874 .probe = cs4270_i2c_probe,
769 .remove = cs4270_i2c_remove, 875 .remove = cs4270_i2c_remove,
876 .suspend = cs4270_i2c_suspend,
877 .resume = cs4270_i2c_resume,
770}; 878};
771 879
772/* 880/*
@@ -777,7 +885,9 @@ static struct i2c_driver cs4270_i2c_driver = {
777 */ 885 */
778struct snd_soc_codec_device soc_codec_device_cs4270 = { 886struct snd_soc_codec_device soc_codec_device_cs4270 = {
779 .probe = cs4270_probe, 887 .probe = cs4270_probe,
780 .remove = cs4270_remove 888 .remove = cs4270_remove,
889 .suspend = cs4270_soc_suspend,
890 .resume = cs4270_soc_resume,
781}; 891};
782EXPORT_SYMBOL_GPL(soc_codec_device_cs4270); 892EXPORT_SYMBOL_GPL(soc_codec_device_cs4270);
783 893
diff --git a/sound/soc/codecs/cx20442.c b/sound/soc/codecs/cx20442.c
new file mode 100644
index 000000000000..38eac9c866e1
--- /dev/null
+++ b/sound/soc/codecs/cx20442.c
@@ -0,0 +1,501 @@
1/*
2 * cx20442.c -- CX20442 ALSA Soc Audio driver
3 *
4 * Copyright 2009 Janusz Krzysztofik <jkrzyszt@tis.icnet.pl>
5 *
6 * Initially based on sound/soc/codecs/wm8400.c
7 * Copyright 2008, 2009 Wolfson Microelectronics PLC.
8 * Author: Mark Brown <broonie@opensource.wolfsonmicro.com>
9 *
10 * This program is free software; you can redistribute it and/or modify it
11 * under the terms of the GNU General Public License as published by the
12 * Free Software Foundation; either version 2 of the License, or (at your
13 * option) any later version.
14 */
15
16#include <linux/tty.h>
17
18#include <sound/core.h>
19#include <sound/initval.h>
20#include <sound/soc-dapm.h>
21
22#include "cx20442.h"
23
24
25struct cx20442_priv {
26 struct snd_soc_codec codec;
27 u8 reg_cache[1];
28};
29
30#define CX20442_PM 0x0
31
32#define CX20442_TELIN 0
33#define CX20442_TELOUT 1
34#define CX20442_MIC 2
35#define CX20442_SPKOUT 3
36#define CX20442_AGC 4
37
38static const struct snd_soc_dapm_widget cx20442_dapm_widgets[] = {
39 SND_SOC_DAPM_OUTPUT("TELOUT"),
40 SND_SOC_DAPM_OUTPUT("SPKOUT"),
41 SND_SOC_DAPM_OUTPUT("AGCOUT"),
42
43 SND_SOC_DAPM_MIXER("SPKOUT Mixer", SND_SOC_NOPM, 0, 0, NULL, 0),
44
45 SND_SOC_DAPM_PGA("TELOUT Amp", CX20442_PM, CX20442_TELOUT, 0, NULL, 0),
46 SND_SOC_DAPM_PGA("SPKOUT Amp", CX20442_PM, CX20442_SPKOUT, 0, NULL, 0),
47 SND_SOC_DAPM_PGA("SPKOUT AGC", CX20442_PM, CX20442_AGC, 0, NULL, 0),
48
49 SND_SOC_DAPM_DAC("DAC", "Playback", SND_SOC_NOPM, 0, 0),
50 SND_SOC_DAPM_ADC("ADC", "Capture", SND_SOC_NOPM, 0, 0),
51
52 SND_SOC_DAPM_MIXER("Input Mixer", SND_SOC_NOPM, 0, 0, NULL, 0),
53
54 SND_SOC_DAPM_MICBIAS("TELIN Bias", CX20442_PM, CX20442_TELIN, 0),
55 SND_SOC_DAPM_MICBIAS("MIC Bias", CX20442_PM, CX20442_MIC, 0),
56
57 SND_SOC_DAPM_PGA("MIC AGC", CX20442_PM, CX20442_AGC, 0, NULL, 0),
58
59 SND_SOC_DAPM_INPUT("TELIN"),
60 SND_SOC_DAPM_INPUT("MIC"),
61 SND_SOC_DAPM_INPUT("AGCIN"),
62};
63
64static const struct snd_soc_dapm_route cx20442_audio_map[] = {
65 {"TELOUT", NULL, "TELOUT Amp"},
66
67 {"SPKOUT", NULL, "SPKOUT Mixer"},
68 {"SPKOUT Mixer", NULL, "SPKOUT Amp"},
69
70 {"TELOUT Amp", NULL, "DAC"},
71 {"SPKOUT Amp", NULL, "DAC"},
72
73 {"SPKOUT Mixer", NULL, "SPKOUT AGC"},
74 {"SPKOUT AGC", NULL, "AGCIN"},
75
76 {"AGCOUT", NULL, "MIC AGC"},
77 {"MIC AGC", NULL, "MIC"},
78
79 {"MIC Bias", NULL, "MIC"},
80 {"Input Mixer", NULL, "MIC Bias"},
81
82 {"TELIN Bias", NULL, "TELIN"},
83 {"Input Mixer", NULL, "TELIN Bias"},
84
85 {"ADC", NULL, "Input Mixer"},
86};
87
88static int cx20442_add_widgets(struct snd_soc_codec *codec)
89{
90 snd_soc_dapm_new_controls(codec, cx20442_dapm_widgets,
91 ARRAY_SIZE(cx20442_dapm_widgets));
92
93 snd_soc_dapm_add_routes(codec, cx20442_audio_map,
94 ARRAY_SIZE(cx20442_audio_map));
95
96 snd_soc_dapm_new_widgets(codec);
97 return 0;
98}
99
100static unsigned int cx20442_read_reg_cache(struct snd_soc_codec *codec,
101 unsigned int reg)
102{
103 u8 *reg_cache = codec->reg_cache;
104
105 if (reg >= codec->reg_cache_size)
106 return -EINVAL;
107
108 return reg_cache[reg];
109}
110
111enum v253_vls {
112 V253_VLS_NONE = 0,
113 V253_VLS_T,
114 V253_VLS_L,
115 V253_VLS_LT,
116 V253_VLS_S,
117 V253_VLS_ST,
118 V253_VLS_M,
119 V253_VLS_MST,
120 V253_VLS_S1,
121 V253_VLS_S1T,
122 V253_VLS_MS1T,
123 V253_VLS_M1,
124 V253_VLS_M1ST,
125 V253_VLS_M1S1T,
126 V253_VLS_H,
127 V253_VLS_HT,
128 V253_VLS_MS,
129 V253_VLS_MS1,
130 V253_VLS_M1S,
131 V253_VLS_M1S1,
132 V253_VLS_TEST,
133};
134
135static int cx20442_pm_to_v253_vls(u8 value)
136{
137 switch (value & ~(1 << CX20442_AGC)) {
138 case 0:
139 return V253_VLS_T;
140 case (1 << CX20442_SPKOUT):
141 case (1 << CX20442_MIC):
142 case (1 << CX20442_SPKOUT) | (1 << CX20442_MIC):
143 return V253_VLS_M1S1;
144 case (1 << CX20442_TELOUT):
145 case (1 << CX20442_TELIN):
146 case (1 << CX20442_TELOUT) | (1 << CX20442_TELIN):
147 return V253_VLS_L;
148 case (1 << CX20442_TELOUT) | (1 << CX20442_MIC):
149 return V253_VLS_NONE;
150 }
151 return -EINVAL;
152}
153static int cx20442_pm_to_v253_vsp(u8 value)
154{
155 switch (value & ~(1 << CX20442_AGC)) {
156 case (1 << CX20442_SPKOUT):
157 case (1 << CX20442_MIC):
158 case (1 << CX20442_SPKOUT) | (1 << CX20442_MIC):
159 return (bool)(value & (1 << CX20442_AGC));
160 }
161 return (value & (1 << CX20442_AGC)) ? -EINVAL : 0;
162}
163
164static int cx20442_write(struct snd_soc_codec *codec, unsigned int reg,
165 unsigned int value)
166{
167 u8 *reg_cache = codec->reg_cache;
168 int vls, vsp, old, len;
169 char buf[18];
170
171 if (reg >= codec->reg_cache_size)
172 return -EINVAL;
173
174 /* hw_write and control_data pointers required for talking to the modem
175 * are expected to be set by the line discipline initialization code */
176 if (!codec->hw_write || !codec->control_data)
177 return -EIO;
178
179 old = reg_cache[reg];
180 reg_cache[reg] = value;
181
182 vls = cx20442_pm_to_v253_vls(value);
183 if (vls < 0)
184 return vls;
185
186 vsp = cx20442_pm_to_v253_vsp(value);
187 if (vsp < 0)
188 return vsp;
189
190 if ((vls == V253_VLS_T) ||
191 (vls == cx20442_pm_to_v253_vls(old))) {
192 if (vsp == cx20442_pm_to_v253_vsp(old))
193 return 0;
194 len = snprintf(buf, ARRAY_SIZE(buf), "at+vsp=%d\r", vsp);
195 } else if (vsp == cx20442_pm_to_v253_vsp(old))
196 len = snprintf(buf, ARRAY_SIZE(buf), "at+vls=%d\r", vls);
197 else
198 len = snprintf(buf, ARRAY_SIZE(buf),
199 "at+vls=%d;+vsp=%d\r", vls, vsp);
200
201 if (unlikely(len > (ARRAY_SIZE(buf) - 1)))
202 return -ENOMEM;
203
204 dev_dbg(codec->dev, "%s: %s\n", __func__, buf);
205 if (codec->hw_write(codec->control_data, buf, len) != len)
206 return -EIO;
207
208 return 0;
209}
210
211
212/* Moved up here as line discipline referres it during initialization */
213static struct snd_soc_codec *cx20442_codec;
214
215
216/*
217 * Line discpline related code
218 *
219 * Any of the callback functions below can be used in two ways:
220 * 1) registerd by a machine driver as one of line discipline operations,
221 * 2) called from a machine's provided line discipline callback function
222 * in case when extra machine specific code must be run as well.
223 */
224
225/* Modem init: echo off, digital speaker off, quiet off, voice mode */
226static const char *v253_init = "ate0m0q0+fclass=8\r";
227
228/* Line discipline .open() */
229static int v253_open(struct tty_struct *tty)
230{
231 struct snd_soc_codec *codec = cx20442_codec;
232 int ret, len = strlen(v253_init);
233
234 /* Doesn't make sense without write callback */
235 if (!tty->ops->write)
236 return -EINVAL;
237
238 /* Pass the codec structure address for use by other ldisc callbacks */
239 tty->disc_data = codec;
240
241 if (tty->ops->write(tty, v253_init, len) != len) {
242 ret = -EIO;
243 goto err;
244 }
245 /* Actual setup will be performed after the modem responds. */
246 return 0;
247err:
248 tty->disc_data = NULL;
249 return ret;
250}
251
252/* Line discipline .close() */
253static void v253_close(struct tty_struct *tty)
254{
255 struct snd_soc_codec *codec = tty->disc_data;
256
257 tty->disc_data = NULL;
258
259 if (!codec)
260 return;
261
262 /* Prevent the codec driver from further accessing the modem */
263 codec->hw_write = NULL;
264 codec->control_data = NULL;
265 codec->pop_time = 0;
266}
267
268/* Line discipline .hangup() */
269static int v253_hangup(struct tty_struct *tty)
270{
271 v253_close(tty);
272 return 0;
273}
274
275/* Line discipline .receive_buf() */
276static void v253_receive(struct tty_struct *tty,
277 const unsigned char *cp, char *fp, int count)
278{
279 struct snd_soc_codec *codec = tty->disc_data;
280
281 if (!codec)
282 return;
283
284 if (!codec->control_data) {
285 /* First modem response, complete setup procedure */
286
287 /* Set up codec driver access to modem controls */
288 codec->control_data = tty;
289 codec->hw_write = (hw_write_t)tty->ops->write;
290 codec->pop_time = 1;
291 }
292}
293
294/* Line discipline .write_wakeup() */
295static void v253_wakeup(struct tty_struct *tty)
296{
297}
298
299struct tty_ldisc_ops v253_ops = {
300 .magic = TTY_LDISC_MAGIC,
301 .name = "cx20442",
302 .owner = THIS_MODULE,
303 .open = v253_open,
304 .close = v253_close,
305 .hangup = v253_hangup,
306 .receive_buf = v253_receive,
307 .write_wakeup = v253_wakeup,
308};
309EXPORT_SYMBOL_GPL(v253_ops);
310
311
312/*
313 * Codec DAI
314 */
315
316struct snd_soc_dai cx20442_dai = {
317 .name = "CX20442",
318 .playback = {
319 .stream_name = "Playback",
320 .channels_min = 1,
321 .channels_max = 1,
322 .rates = SNDRV_PCM_RATE_8000,
323 .formats = SNDRV_PCM_FMTBIT_S16_LE,
324 },
325 .capture = {
326 .stream_name = "Capture",
327 .channels_min = 1,
328 .channels_max = 1,
329 .rates = SNDRV_PCM_RATE_8000,
330 .formats = SNDRV_PCM_FMTBIT_S16_LE,
331 },
332};
333EXPORT_SYMBOL_GPL(cx20442_dai);
334
335static int cx20442_codec_probe(struct platform_device *pdev)
336{
337 struct snd_soc_device *socdev = platform_get_drvdata(pdev);
338 struct snd_soc_codec *codec;
339 int ret;
340
341 if (!cx20442_codec) {
342 dev_err(&pdev->dev, "cx20442 not yet discovered\n");
343 return -ENODEV;
344 }
345 codec = cx20442_codec;
346
347 socdev->card->codec = codec;
348
349 /* register pcms */
350 ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1);
351 if (ret < 0) {
352 dev_err(&pdev->dev, "failed to create pcms\n");
353 goto pcm_err;
354 }
355
356 cx20442_add_widgets(codec);
357
358 ret = snd_soc_init_card(socdev);
359 if (ret < 0) {
360 dev_err(&pdev->dev, "failed to register card\n");
361 goto card_err;
362 }
363
364 return ret;
365
366card_err:
367 snd_soc_free_pcms(socdev);
368 snd_soc_dapm_free(socdev);
369pcm_err:
370 return ret;
371}
372
373/* power down chip */
374static int cx20442_codec_remove(struct platform_device *pdev)
375{
376 struct snd_soc_device *socdev = platform_get_drvdata(pdev);
377
378 snd_soc_free_pcms(socdev);
379 snd_soc_dapm_free(socdev);
380
381 return 0;
382}
383
384struct snd_soc_codec_device cx20442_codec_dev = {
385 .probe = cx20442_codec_probe,
386 .remove = cx20442_codec_remove,
387};
388EXPORT_SYMBOL_GPL(cx20442_codec_dev);
389
390static int cx20442_register(struct cx20442_priv *cx20442)
391{
392 struct snd_soc_codec *codec = &cx20442->codec;
393 int ret;
394
395 mutex_init(&codec->mutex);
396 INIT_LIST_HEAD(&codec->dapm_widgets);
397 INIT_LIST_HEAD(&codec->dapm_paths);
398
399 codec->name = "CX20442";
400 codec->owner = THIS_MODULE;
401 codec->private_data = cx20442;
402
403 codec->dai = &cx20442_dai;
404 codec->num_dai = 1;
405
406 codec->reg_cache = &cx20442->reg_cache;
407 codec->reg_cache_size = ARRAY_SIZE(cx20442->reg_cache);
408 codec->read = cx20442_read_reg_cache;
409 codec->write = cx20442_write;
410
411 codec->bias_level = SND_SOC_BIAS_OFF;
412
413 cx20442_dai.dev = codec->dev;
414
415 cx20442_codec = codec;
416
417 ret = snd_soc_register_codec(codec);
418 if (ret != 0) {
419 dev_err(codec->dev, "Failed to register codec: %d\n", ret);
420 goto err;
421 }
422
423 ret = snd_soc_register_dai(&cx20442_dai);
424 if (ret != 0) {
425 dev_err(codec->dev, "Failed to register DAI: %d\n", ret);
426 goto err_codec;
427 }
428
429 return 0;
430
431err_codec:
432 snd_soc_unregister_codec(codec);
433err:
434 cx20442_codec = NULL;
435 kfree(cx20442);
436 return ret;
437}
438
439static void cx20442_unregister(struct cx20442_priv *cx20442)
440{
441 snd_soc_unregister_dai(&cx20442_dai);
442 snd_soc_unregister_codec(&cx20442->codec);
443
444 cx20442_codec = NULL;
445 kfree(cx20442);
446}
447
448static int cx20442_platform_probe(struct platform_device *pdev)
449{
450 struct cx20442_priv *cx20442;
451 struct snd_soc_codec *codec;
452
453 cx20442 = kzalloc(sizeof(struct cx20442_priv), GFP_KERNEL);
454 if (cx20442 == NULL)
455 return -ENOMEM;
456
457 codec = &cx20442->codec;
458
459 codec->control_data = NULL;
460 codec->hw_write = NULL;
461 codec->pop_time = 0;
462
463 codec->dev = &pdev->dev;
464 platform_set_drvdata(pdev, cx20442);
465
466 return cx20442_register(cx20442);
467}
468
469static int __exit cx20442_platform_remove(struct platform_device *pdev)
470{
471 struct cx20442_priv *cx20442 = platform_get_drvdata(pdev);
472
473 cx20442_unregister(cx20442);
474 return 0;
475}
476
477static struct platform_driver cx20442_platform_driver = {
478 .driver = {
479 .name = "cx20442",
480 .owner = THIS_MODULE,
481 },
482 .probe = cx20442_platform_probe,
483 .remove = __exit_p(cx20442_platform_remove),
484};
485
486static int __init cx20442_init(void)
487{
488 return platform_driver_register(&cx20442_platform_driver);
489}
490module_init(cx20442_init);
491
492static void __exit cx20442_exit(void)
493{
494 platform_driver_unregister(&cx20442_platform_driver);
495}
496module_exit(cx20442_exit);
497
498MODULE_DESCRIPTION("ASoC CX20442-11 voice modem codec driver");
499MODULE_AUTHOR("Janusz Krzysztofik");
500MODULE_LICENSE("GPL");
501MODULE_ALIAS("platform:cx20442");
diff --git a/sound/soc/codecs/cx20442.h b/sound/soc/codecs/cx20442.h
new file mode 100644
index 000000000000..688a5eb62e17
--- /dev/null
+++ b/sound/soc/codecs/cx20442.h
@@ -0,0 +1,20 @@
1/*
2 * cx20442.h -- audio driver for CX20442
3 *
4 * Copyright 2009 Janusz Krzysztofik <jkrzyszt@tis.icnet.pl>
5 *
6 * This program is free software; you can redistribute it and/or modify it
7 * under the terms of the GNU General Public License as published by the
8 * Free Software Foundation; either version 2 of the License, or (at your
9 * option) any later version.
10 *
11 */
12
13#ifndef _CX20442_CODEC_H
14#define _CX20442_CODEC_H
15
16extern struct snd_soc_dai cx20442_dai;
17extern struct snd_soc_codec_device cx20442_codec_dev;
18extern struct tty_ldisc_ops v253_ops;
19
20#endif
diff --git a/sound/soc/codecs/max9877.c b/sound/soc/codecs/max9877.c
new file mode 100644
index 000000000000..9e7e964a5fa3
--- /dev/null
+++ b/sound/soc/codecs/max9877.c
@@ -0,0 +1,308 @@
1/*
2 * max9877.c -- amp driver for max9877
3 *
4 * Copyright (C) 2009 Samsung Electronics Co.Ltd
5 * Author: Joonyoung Shim <jy0922.shim@samsung.com>
6 *
7 * This program is free software; you can redistribute it and/or modify it
8 * under the terms of the GNU General Public License as published by the
9 * Free Software Foundation; either version 2 of the License, or (at your
10 * option) any later version.
11 *
12 */
13
14#include <linux/module.h>
15#include <linux/init.h>
16#include <linux/i2c.h>
17#include <sound/soc.h>
18#include <sound/tlv.h>
19
20#include "max9877.h"
21
22static struct i2c_client *i2c;
23
24static u8 max9877_regs[5] = { 0x40, 0x00, 0x00, 0x00, 0x49 };
25
26static void max9877_write_regs(void)
27{
28 unsigned int i;
29 u8 data[6];
30
31 data[0] = MAX9877_INPUT_MODE;
32 for (i = 0; i < ARRAY_SIZE(max9877_regs); i++)
33 data[i + 1] = max9877_regs[i];
34
35 if (i2c_master_send(i2c, data, 6) != 6)
36 dev_err(&i2c->dev, "i2c write failed\n");
37}
38
39static int max9877_get_reg(struct snd_kcontrol *kcontrol,
40 struct snd_ctl_elem_value *ucontrol)
41{
42 struct soc_mixer_control *mc =
43 (struct soc_mixer_control *)kcontrol->private_value;
44 unsigned int reg = mc->reg;
45 unsigned int shift = mc->shift;
46 unsigned int mask = mc->max;
47 unsigned int invert = mc->invert;
48
49 ucontrol->value.integer.value[0] = (max9877_regs[reg] >> shift) & mask;
50
51 if (invert)
52 ucontrol->value.integer.value[0] =
53 mask - ucontrol->value.integer.value[0];
54
55 return 0;
56}
57
58static int max9877_set_reg(struct snd_kcontrol *kcontrol,
59 struct snd_ctl_elem_value *ucontrol)
60{
61 struct soc_mixer_control *mc =
62 (struct soc_mixer_control *)kcontrol->private_value;
63 unsigned int reg = mc->reg;
64 unsigned int shift = mc->shift;
65 unsigned int mask = mc->max;
66 unsigned int invert = mc->invert;
67 unsigned int val = (ucontrol->value.integer.value[0] & mask);
68
69 if (invert)
70 val = mask - val;
71
72 if (((max9877_regs[reg] >> shift) & mask) == val)
73 return 0;
74
75 max9877_regs[reg] &= ~(mask << shift);
76 max9877_regs[reg] |= val << shift;
77 max9877_write_regs();
78
79 return 1;
80}
81
82static int max9877_get_2reg(struct snd_kcontrol *kcontrol,
83 struct snd_ctl_elem_value *ucontrol)
84{
85 struct soc_mixer_control *mc =
86 (struct soc_mixer_control *)kcontrol->private_value;
87 unsigned int reg = mc->reg;
88 unsigned int reg2 = mc->rreg;
89 unsigned int shift = mc->shift;
90 unsigned int mask = mc->max;
91
92 ucontrol->value.integer.value[0] = (max9877_regs[reg] >> shift) & mask;
93 ucontrol->value.integer.value[1] = (max9877_regs[reg2] >> shift) & mask;
94
95 return 0;
96}
97
98static int max9877_set_2reg(struct snd_kcontrol *kcontrol,
99 struct snd_ctl_elem_value *ucontrol)
100{
101 struct soc_mixer_control *mc =
102 (struct soc_mixer_control *)kcontrol->private_value;
103 unsigned int reg = mc->reg;
104 unsigned int reg2 = mc->rreg;
105 unsigned int shift = mc->shift;
106 unsigned int mask = mc->max;
107 unsigned int val = (ucontrol->value.integer.value[0] & mask);
108 unsigned int val2 = (ucontrol->value.integer.value[1] & mask);
109 unsigned int change = 1;
110
111 if (((max9877_regs[reg] >> shift) & mask) == val)
112 change = 0;
113
114 if (((max9877_regs[reg2] >> shift) & mask) == val2)
115 change = 0;
116
117 if (change) {
118 max9877_regs[reg] &= ~(mask << shift);
119 max9877_regs[reg] |= val << shift;
120 max9877_regs[reg2] &= ~(mask << shift);
121 max9877_regs[reg2] |= val2 << shift;
122 max9877_write_regs();
123 }
124
125 return change;
126}
127
128static int max9877_get_out_mode(struct snd_kcontrol *kcontrol,
129 struct snd_ctl_elem_value *ucontrol)
130{
131 u8 value = max9877_regs[MAX9877_OUTPUT_MODE] & MAX9877_OUTMODE_MASK;
132
133 if (value)
134 value -= 1;
135
136 ucontrol->value.integer.value[0] = value;
137 return 0;
138}
139
140static int max9877_set_out_mode(struct snd_kcontrol *kcontrol,
141 struct snd_ctl_elem_value *ucontrol)
142{
143 u8 value = ucontrol->value.integer.value[0];
144
145 value += 1;
146
147 if ((max9877_regs[MAX9877_OUTPUT_MODE] & MAX9877_OUTMODE_MASK) == value)
148 return 0;
149
150 max9877_regs[MAX9877_OUTPUT_MODE] &= ~MAX9877_OUTMODE_MASK;
151 max9877_regs[MAX9877_OUTPUT_MODE] |= value;
152 max9877_write_regs();
153 return 1;
154}
155
156static int max9877_get_osc_mode(struct snd_kcontrol *kcontrol,
157 struct snd_ctl_elem_value *ucontrol)
158{
159 u8 value = (max9877_regs[MAX9877_OUTPUT_MODE] & MAX9877_OSC_MASK);
160
161 value = value >> MAX9877_OSC_OFFSET;
162
163 ucontrol->value.integer.value[0] = value;
164 return 0;
165}
166
167static int max9877_set_osc_mode(struct snd_kcontrol *kcontrol,
168 struct snd_ctl_elem_value *ucontrol)
169{
170 u8 value = ucontrol->value.integer.value[0];
171
172 value = value << MAX9877_OSC_OFFSET;
173 if ((max9877_regs[MAX9877_OUTPUT_MODE] & MAX9877_OSC_MASK) == value)
174 return 0;
175
176 max9877_regs[MAX9877_OUTPUT_MODE] &= ~MAX9877_OSC_MASK;
177 max9877_regs[MAX9877_OUTPUT_MODE] |= value;
178 max9877_write_regs();
179 return 1;
180}
181
182static const unsigned int max9877_pgain_tlv[] = {
183 TLV_DB_RANGE_HEAD(2),
184 0, 1, TLV_DB_SCALE_ITEM(0, 900, 0),
185 2, 2, TLV_DB_SCALE_ITEM(2000, 0, 0),
186};
187
188static const unsigned int max9877_output_tlv[] = {
189 TLV_DB_RANGE_HEAD(4),
190 0, 7, TLV_DB_SCALE_ITEM(-7900, 400, 1),
191 8, 15, TLV_DB_SCALE_ITEM(-4700, 300, 0),
192 16, 23, TLV_DB_SCALE_ITEM(-2300, 200, 0),
193 24, 31, TLV_DB_SCALE_ITEM(-700, 100, 0),
194};
195
196static const char *max9877_out_mode[] = {
197 "INA -> SPK",
198 "INA -> HP",
199 "INA -> SPK and HP",
200 "INB -> SPK",
201 "INB -> HP",
202 "INB -> SPK and HP",
203 "INA + INB -> SPK",
204 "INA + INB -> HP",
205 "INA + INB -> SPK and HP",
206};
207
208static const char *max9877_osc_mode[] = {
209 "1176KHz",
210 "1100KHz",
211 "700KHz",
212};
213
214static const struct soc_enum max9877_enum[] = {
215 SOC_ENUM_SINGLE_EXT(ARRAY_SIZE(max9877_out_mode), max9877_out_mode),
216 SOC_ENUM_SINGLE_EXT(ARRAY_SIZE(max9877_osc_mode), max9877_osc_mode),
217};
218
219static const struct snd_kcontrol_new max9877_controls[] = {
220 SOC_SINGLE_EXT_TLV("MAX9877 PGAINA Playback Volume",
221 MAX9877_INPUT_MODE, 0, 2, 0,
222 max9877_get_reg, max9877_set_reg, max9877_pgain_tlv),
223 SOC_SINGLE_EXT_TLV("MAX9877 PGAINB Playback Volume",
224 MAX9877_INPUT_MODE, 2, 2, 0,
225 max9877_get_reg, max9877_set_reg, max9877_pgain_tlv),
226 SOC_SINGLE_EXT_TLV("MAX9877 Amp Speaker Playback Volume",
227 MAX9877_SPK_VOLUME, 0, 31, 0,
228 max9877_get_reg, max9877_set_reg, max9877_output_tlv),
229 SOC_DOUBLE_R_EXT_TLV("MAX9877 Amp HP Playback Volume",
230 MAX9877_HPL_VOLUME, MAX9877_HPR_VOLUME, 0, 31, 0,
231 max9877_get_2reg, max9877_set_2reg, max9877_output_tlv),
232 SOC_SINGLE_EXT("MAX9877 INB Stereo Switch",
233 MAX9877_INPUT_MODE, 4, 1, 1,
234 max9877_get_reg, max9877_set_reg),
235 SOC_SINGLE_EXT("MAX9877 INA Stereo Switch",
236 MAX9877_INPUT_MODE, 5, 1, 1,
237 max9877_get_reg, max9877_set_reg),
238 SOC_SINGLE_EXT("MAX9877 Zero-crossing detection Switch",
239 MAX9877_INPUT_MODE, 6, 1, 0,
240 max9877_get_reg, max9877_set_reg),
241 SOC_SINGLE_EXT("MAX9877 Bypass Mode Switch",
242 MAX9877_OUTPUT_MODE, 6, 1, 0,
243 max9877_get_reg, max9877_set_reg),
244 SOC_SINGLE_EXT("MAX9877 Shutdown Mode Switch",
245 MAX9877_OUTPUT_MODE, 7, 1, 1,
246 max9877_get_reg, max9877_set_reg),
247 SOC_ENUM_EXT("MAX9877 Output Mode", max9877_enum[0],
248 max9877_get_out_mode, max9877_set_out_mode),
249 SOC_ENUM_EXT("MAX9877 Oscillator Mode", max9877_enum[1],
250 max9877_get_osc_mode, max9877_set_osc_mode),
251};
252
253/* This function is called from ASoC machine driver */
254int max9877_add_controls(struct snd_soc_codec *codec)
255{
256 return snd_soc_add_controls(codec, max9877_controls,
257 ARRAY_SIZE(max9877_controls));
258}
259EXPORT_SYMBOL_GPL(max9877_add_controls);
260
261static int __devinit max9877_i2c_probe(struct i2c_client *client,
262 const struct i2c_device_id *id)
263{
264 i2c = client;
265
266 max9877_write_regs();
267
268 return 0;
269}
270
271static __devexit int max9877_i2c_remove(struct i2c_client *client)
272{
273 i2c = NULL;
274
275 return 0;
276}
277
278static const struct i2c_device_id max9877_i2c_id[] = {
279 { "max9877", 0 },
280 { }
281};
282MODULE_DEVICE_TABLE(i2c, max9877_i2c_id);
283
284static struct i2c_driver max9877_i2c_driver = {
285 .driver = {
286 .name = "max9877",
287 .owner = THIS_MODULE,
288 },
289 .probe = max9877_i2c_probe,
290 .remove = __devexit_p(max9877_i2c_remove),
291 .id_table = max9877_i2c_id,
292};
293
294static int __init max9877_init(void)
295{
296 return i2c_add_driver(&max9877_i2c_driver);
297}
298module_init(max9877_init);
299
300static void __exit max9877_exit(void)
301{
302 i2c_del_driver(&max9877_i2c_driver);
303}
304module_exit(max9877_exit);
305
306MODULE_DESCRIPTION("ASoC MAX9877 amp driver");
307MODULE_AUTHOR("Joonyoung Shim <jy0922.shim@samsung.com>");
308MODULE_LICENSE("GPL");
diff --git a/sound/soc/codecs/max9877.h b/sound/soc/codecs/max9877.h
new file mode 100644
index 000000000000..6da72290ac58
--- /dev/null
+++ b/sound/soc/codecs/max9877.h
@@ -0,0 +1,37 @@
1/*
2 * max9877.h -- amp driver for max9877
3 *
4 * Copyright (C) 2009 Samsung Electronics Co.Ltd
5 * Author: Joonyoung Shim <jy0922.shim@samsung.com>
6 *
7 * This program is free software; you can redistribute it and/or modify it
8 * under the terms of the GNU General Public License as published by the
9 * Free Software Foundation; either version 2 of the License, or (at your
10 * option) any later version.
11 *
12 */
13
14#ifndef _MAX9877_H
15#define _MAX9877_H
16
17#define MAX9877_INPUT_MODE 0x00
18#define MAX9877_SPK_VOLUME 0x01
19#define MAX9877_HPL_VOLUME 0x02
20#define MAX9877_HPR_VOLUME 0x03
21#define MAX9877_OUTPUT_MODE 0x04
22
23/* MAX9877_INPUT_MODE */
24#define MAX9877_INB (1 << 4)
25#define MAX9877_INA (1 << 5)
26#define MAX9877_ZCD (1 << 6)
27
28/* MAX9877_OUTPUT_MODE */
29#define MAX9877_OUTMODE_MASK (15 << 0)
30#define MAX9877_OSC_MASK (3 << 4)
31#define MAX9877_OSC_OFFSET 4
32#define MAX9877_BYPASS (1 << 6)
33#define MAX9877_SHDN (1 << 7)
34
35extern int max9877_add_controls(struct snd_soc_codec *codec);
36
37#endif
diff --git a/sound/soc/codecs/spdif_transciever.c b/sound/soc/codecs/spdif_transciever.c
new file mode 100644
index 000000000000..a63191141052
--- /dev/null
+++ b/sound/soc/codecs/spdif_transciever.c
@@ -0,0 +1,74 @@
1/*
2 * ALSA SoC SPDIF DIT driver
3 *
4 * This driver is used by controllers which can operate in DIT (SPDI/F) where
5 * no codec is needed. This file provides stub codec that can be used
6 * in these configurations. TI DaVinci Audio controller uses this driver.
7 *
8 * Author: Steve Chen, <schen@mvista.com>
9 * Copyright: (C) 2009 MontaVista Software, Inc., <source@mvista.com>
10 * Copyright: (C) 2009 Texas Instruments, India
11 *
12 * This program is free software; you can redistribute it and/or modify
13 * it under the terms of the GNU General Public License version 2 as
14 * published by the Free Software Foundation.
15 */
16
17#include <linux/module.h>
18#include <linux/moduleparam.h>
19#include <sound/soc.h>
20#include <sound/pcm.h>
21
22#include "spdif_transciever.h"
23
24MODULE_LICENSE("GPL");
25
26#define STUB_RATES SNDRV_PCM_RATE_8000_96000
27#define STUB_FORMATS SNDRV_PCM_FMTBIT_S16_LE
28
29struct snd_soc_dai dit_stub_dai = {
30 .name = "DIT",
31 .playback = {
32 .stream_name = "Playback",
33 .channels_min = 1,
34 .channels_max = 384,
35 .rates = STUB_RATES,
36 .formats = STUB_FORMATS,
37 },
38};
39EXPORT_SYMBOL_GPL(dit_stub_dai);
40
41static int spdif_dit_probe(struct platform_device *pdev)
42{
43 dit_stub_dai.dev = &pdev->dev;
44 return snd_soc_register_dai(&dit_stub_dai);
45}
46
47static int spdif_dit_remove(struct platform_device *pdev)
48{
49 snd_soc_unregister_dai(&dit_stub_dai);
50 return 0;
51}
52
53static struct platform_driver spdif_dit_driver = {
54 .probe = spdif_dit_probe,
55 .remove = spdif_dit_remove,
56 .driver = {
57 .name = "spdif-dit",
58 .owner = THIS_MODULE,
59 },
60};
61
62static int __init dit_modinit(void)
63{
64 return platform_driver_register(&spdif_dit_driver);
65}
66
67static void __exit dit_exit(void)
68{
69 platform_driver_unregister(&spdif_dit_driver);
70}
71
72module_init(dit_modinit);
73module_exit(dit_exit);
74
diff --git a/sound/soc/codecs/spdif_transciever.h b/sound/soc/codecs/spdif_transciever.h
new file mode 100644
index 000000000000..296f2eb6c4ef
--- /dev/null
+++ b/sound/soc/codecs/spdif_transciever.h
@@ -0,0 +1,17 @@
1/*
2 * ALSA SoC DIT/DIR driver header
3 *
4 * Author: Steve Chen, <schen@mvista.com>
5 * Copyright: (C) 2008 MontaVista Software, Inc., <source@mvista.com>
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License version 2 as
9 * published by the Free Software Foundation.
10 */
11
12#ifndef CODEC_STUBS_H
13#define CODEC_STUBS_H
14
15extern struct snd_soc_dai dit_stub_dai;
16
17#endif /* CODEC_STUBS_H */
diff --git a/sound/soc/codecs/ssm2602.c b/sound/soc/codecs/ssm2602.c
index 87f606c76822..c550750c79c0 100644
--- a/sound/soc/codecs/ssm2602.c
+++ b/sound/soc/codecs/ssm2602.c
@@ -336,15 +336,17 @@ static int ssm2602_startup(struct snd_pcm_substream *substream,
336 master_runtime->sample_bits, 336 master_runtime->sample_bits,
337 master_runtime->rate); 337 master_runtime->rate);
338 338
339 snd_pcm_hw_constraint_minmax(substream->runtime, 339 if (master_runtime->rate != 0)
340 SNDRV_PCM_HW_PARAM_RATE, 340 snd_pcm_hw_constraint_minmax(substream->runtime,
341 master_runtime->rate, 341 SNDRV_PCM_HW_PARAM_RATE,
342 master_runtime->rate); 342 master_runtime->rate,
343 343 master_runtime->rate);
344 snd_pcm_hw_constraint_minmax(substream->runtime, 344
345 SNDRV_PCM_HW_PARAM_SAMPLE_BITS, 345 if (master_runtime->sample_bits != 0)
346 master_runtime->sample_bits, 346 snd_pcm_hw_constraint_minmax(substream->runtime,
347 master_runtime->sample_bits); 347 SNDRV_PCM_HW_PARAM_SAMPLE_BITS,
348 master_runtime->sample_bits,
349 master_runtime->sample_bits);
348 350
349 ssm2602->slave_substream = substream; 351 ssm2602->slave_substream = substream;
350 } else 352 } else
@@ -372,6 +374,7 @@ static void ssm2602_shutdown(struct snd_pcm_substream *substream,
372 struct snd_soc_device *socdev = rtd->socdev; 374 struct snd_soc_device *socdev = rtd->socdev;
373 struct snd_soc_codec *codec = socdev->card->codec; 375 struct snd_soc_codec *codec = socdev->card->codec;
374 struct ssm2602_priv *ssm2602 = codec->private_data; 376 struct ssm2602_priv *ssm2602 = codec->private_data;
377
375 /* deactivate */ 378 /* deactivate */
376 if (!codec->active) 379 if (!codec->active)
377 ssm2602_write(codec, SSM2602_ACTIVE, 0); 380 ssm2602_write(codec, SSM2602_ACTIVE, 0);
@@ -497,11 +500,9 @@ static int ssm2602_set_bias_level(struct snd_soc_codec *codec,
497 return 0; 500 return 0;
498} 501}
499 502
500#define SSM2602_RATES (SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_11025 |\ 503#define SSM2602_RATES (SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_32000 |\
501 SNDRV_PCM_RATE_16000 | SNDRV_PCM_RATE_22050 |\ 504 SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_48000 |\
502 SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_44100 |\ 505 SNDRV_PCM_RATE_88200 | SNDRV_PCM_RATE_96000)
503 SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_88200 |\
504 SNDRV_PCM_RATE_96000)
505 506
506#define SSM2602_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE |\ 507#define SSM2602_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE |\
507 SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S32_LE) 508 SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S32_LE)
diff --git a/sound/soc/codecs/stac9766.c b/sound/soc/codecs/stac9766.c
new file mode 100644
index 000000000000..befc6488c39a
--- /dev/null
+++ b/sound/soc/codecs/stac9766.c
@@ -0,0 +1,463 @@
1/*
2 * stac9766.c -- ALSA SoC STAC9766 codec support
3 *
4 * Copyright 2009 Jon Smirl, Digispeaker
5 * Author: Jon Smirl <jonsmirl@gmail.com>
6 *
7 * This program is free software; you can redistribute it and/or modify it
8 * under the terms of the GNU General Public License as published by the
9 * Free Software Foundation; either version 2 of the License, or (at your
10 * option) any later version.
11 *
12 * Features:-
13 *
14 * o Support for AC97 Codec, S/PDIF
15 */
16
17#include <linux/init.h>
18#include <linux/module.h>
19#include <linux/device.h>
20#include <sound/core.h>
21#include <sound/pcm.h>
22#include <sound/ac97_codec.h>
23#include <sound/initval.h>
24#include <sound/pcm_params.h>
25#include <sound/soc.h>
26#include <sound/tlv.h>
27#include <sound/soc-of-simple.h>
28
29#include "stac9766.h"
30
31#define STAC9766_VERSION "0.10"
32
33/*
34 * STAC9766 register cache
35 */
36static const u16 stac9766_reg[] = {
37 0x6A90, 0x8000, 0x8000, 0x8000, /* 6 */
38 0x0000, 0x0000, 0x8008, 0x8008, /* e */
39 0x8808, 0x8808, 0x8808, 0x8808, /* 16 */
40 0x8808, 0x0000, 0x8000, 0x0000, /* 1e */
41 0x0000, 0x0000, 0x0000, 0x000f, /* 26 */
42 0x0a05, 0x0400, 0xbb80, 0x0000, /* 2e */
43 0x0000, 0xbb80, 0x0000, 0x0000, /* 36 */
44 0x0000, 0x2000, 0x0000, 0x0100, /* 3e */
45 0x0000, 0x0000, 0x0080, 0x0000, /* 46 */
46 0x0000, 0x0000, 0x0003, 0xffff, /* 4e */
47 0x0000, 0x0000, 0x0000, 0x0000, /* 56 */
48 0x4000, 0x0000, 0x0000, 0x0000, /* 5e */
49 0x1201, 0xFFFF, 0xFFFF, 0x0000, /* 66 */
50 0x0000, 0x0000, 0x0000, 0x0000, /* 6e */
51 0x0000, 0x0000, 0x0000, 0x0006, /* 76 */
52 0x0000, 0x0000, 0x0000, 0x0000, /* 7e */
53};
54
55static const char *stac9766_record_mux[] = {"Mic", "CD", "Video", "AUX",
56 "Line", "Stereo Mix", "Mono Mix", "Phone"};
57static const char *stac9766_mono_mux[] = {"Mix", "Mic"};
58static const char *stac9766_mic_mux[] = {"Mic1", "Mic2"};
59static const char *stac9766_SPDIF_mux[] = {"PCM", "ADC Record"};
60static const char *stac9766_popbypass_mux[] = {"Normal", "Bypass Mixer"};
61static const char *stac9766_record_all_mux[] = {"All analog",
62 "Analog plus DAC"};
63static const char *stac9766_boost1[] = {"0dB", "10dB"};
64static const char *stac9766_boost2[] = {"0dB", "20dB"};
65static const char *stac9766_stereo_mic[] = {"Off", "On"};
66
67static const struct soc_enum stac9766_record_enum =
68 SOC_ENUM_DOUBLE(AC97_REC_SEL, 8, 0, 8, stac9766_record_mux);
69static const struct soc_enum stac9766_mono_enum =
70 SOC_ENUM_SINGLE(AC97_GENERAL_PURPOSE, 9, 2, stac9766_mono_mux);
71static const struct soc_enum stac9766_mic_enum =
72 SOC_ENUM_SINGLE(AC97_GENERAL_PURPOSE, 8, 2, stac9766_mic_mux);
73static const struct soc_enum stac9766_SPDIF_enum =
74 SOC_ENUM_SINGLE(AC97_STAC_DA_CONTROL, 1, 2, stac9766_SPDIF_mux);
75static const struct soc_enum stac9766_popbypass_enum =
76 SOC_ENUM_SINGLE(AC97_GENERAL_PURPOSE, 15, 2, stac9766_popbypass_mux);
77static const struct soc_enum stac9766_record_all_enum =
78 SOC_ENUM_SINGLE(AC97_STAC_ANALOG_SPECIAL, 12, 2,
79 stac9766_record_all_mux);
80static const struct soc_enum stac9766_boost1_enum =
81 SOC_ENUM_SINGLE(AC97_MIC, 6, 2, stac9766_boost1); /* 0/10dB */
82static const struct soc_enum stac9766_boost2_enum =
83 SOC_ENUM_SINGLE(AC97_STAC_ANALOG_SPECIAL, 2, 2, stac9766_boost2); /* 0/20dB */
84static const struct soc_enum stac9766_stereo_mic_enum =
85 SOC_ENUM_SINGLE(AC97_STAC_STEREO_MIC, 2, 1, stac9766_stereo_mic);
86
87static const DECLARE_TLV_DB_LINEAR(master_tlv, -4600, 0);
88static const DECLARE_TLV_DB_LINEAR(record_tlv, 0, 2250);
89static const DECLARE_TLV_DB_LINEAR(beep_tlv, -4500, 0);
90static const DECLARE_TLV_DB_LINEAR(mix_tlv, -3450, 1200);
91
92static const struct snd_kcontrol_new stac9766_snd_ac97_controls[] = {
93 SOC_DOUBLE_TLV("Speaker Volume", AC97_MASTER, 8, 0, 31, 1, master_tlv),
94 SOC_SINGLE("Speaker Switch", AC97_MASTER, 15, 1, 1),
95 SOC_DOUBLE_TLV("Headphone Volume", AC97_HEADPHONE, 8, 0, 31, 1,
96 master_tlv),
97 SOC_SINGLE("Headphone Switch", AC97_HEADPHONE, 15, 1, 1),
98 SOC_SINGLE_TLV("Mono Out Volume", AC97_MASTER_MONO, 0, 31, 1,
99 master_tlv),
100 SOC_SINGLE("Mono Out Switch", AC97_MASTER_MONO, 15, 1, 1),
101
102 SOC_DOUBLE_TLV("Record Volume", AC97_REC_GAIN, 8, 0, 15, 0, record_tlv),
103 SOC_SINGLE("Record Switch", AC97_REC_GAIN, 15, 1, 1),
104
105
106 SOC_SINGLE_TLV("Beep Volume", AC97_PC_BEEP, 1, 15, 1, beep_tlv),
107 SOC_SINGLE("Beep Switch", AC97_PC_BEEP, 15, 1, 1),
108 SOC_SINGLE("Beep Frequency", AC97_PC_BEEP, 5, 127, 1),
109 SOC_SINGLE_TLV("Phone Volume", AC97_PHONE, 0, 31, 1, mix_tlv),
110 SOC_SINGLE("Phone Switch", AC97_PHONE, 15, 1, 1),
111
112 SOC_ENUM("Mic Boost1", stac9766_boost1_enum),
113 SOC_ENUM("Mic Boost2", stac9766_boost2_enum),
114 SOC_SINGLE_TLV("Mic Volume", AC97_MIC, 0, 31, 1, mix_tlv),
115 SOC_SINGLE("Mic Switch", AC97_MIC, 15, 1, 1),
116 SOC_ENUM("Stereo Mic", stac9766_stereo_mic_enum),
117
118 SOC_DOUBLE_TLV("Line Volume", AC97_LINE, 8, 0, 31, 1, mix_tlv),
119 SOC_SINGLE("Line Switch", AC97_LINE, 15, 1, 1),
120 SOC_DOUBLE_TLV("CD Volume", AC97_CD, 8, 0, 31, 1, mix_tlv),
121 SOC_SINGLE("CD Switch", AC97_CD, 15, 1, 1),
122 SOC_DOUBLE_TLV("AUX Volume", AC97_AUX, 8, 0, 31, 1, mix_tlv),
123 SOC_SINGLE("AUX Switch", AC97_AUX, 15, 1, 1),
124 SOC_DOUBLE_TLV("Video Volume", AC97_VIDEO, 8, 0, 31, 1, mix_tlv),
125 SOC_SINGLE("Video Switch", AC97_VIDEO, 15, 1, 1),
126
127 SOC_DOUBLE_TLV("DAC Volume", AC97_PCM, 8, 0, 31, 1, mix_tlv),
128 SOC_SINGLE("DAC Switch", AC97_PCM, 15, 1, 1),
129 SOC_SINGLE("Loopback Test Switch", AC97_GENERAL_PURPOSE, 7, 1, 0),
130 SOC_SINGLE("3D Volume", AC97_3D_CONTROL, 3, 2, 1),
131 SOC_SINGLE("3D Switch", AC97_GENERAL_PURPOSE, 13, 1, 0),
132
133 SOC_ENUM("SPDIF Mux", stac9766_SPDIF_enum),
134 SOC_ENUM("Mic1/2 Mux", stac9766_mic_enum),
135 SOC_ENUM("Record All Mux", stac9766_record_all_enum),
136 SOC_ENUM("Record Mux", stac9766_record_enum),
137 SOC_ENUM("Mono Mux", stac9766_mono_enum),
138 SOC_ENUM("Pop Bypass Mux", stac9766_popbypass_enum),
139};
140
141static int stac9766_ac97_write(struct snd_soc_codec *codec, unsigned int reg,
142 unsigned int val)
143{
144 u16 *cache = codec->reg_cache;
145
146 if (reg > AC97_STAC_PAGE0) {
147 stac9766_ac97_write(codec, AC97_INT_PAGING, 0);
148 soc_ac97_ops.write(codec->ac97, reg, val);
149 stac9766_ac97_write(codec, AC97_INT_PAGING, 1);
150 return 0;
151 }
152 if (reg / 2 >= ARRAY_SIZE(stac9766_reg))
153 return -EIO;
154
155 soc_ac97_ops.write(codec->ac97, reg, val);
156 cache[reg / 2] = val;
157 return 0;
158}
159
160static unsigned int stac9766_ac97_read(struct snd_soc_codec *codec,
161 unsigned int reg)
162{
163 u16 val = 0, *cache = codec->reg_cache;
164
165 if (reg > AC97_STAC_PAGE0) {
166 stac9766_ac97_write(codec, AC97_INT_PAGING, 0);
167 val = soc_ac97_ops.read(codec->ac97, reg - AC97_STAC_PAGE0);
168 stac9766_ac97_write(codec, AC97_INT_PAGING, 1);
169 return val;
170 }
171 if (reg / 2 >= ARRAY_SIZE(stac9766_reg))
172 return -EIO;
173
174 if (reg == AC97_RESET || reg == AC97_GPIO_STATUS ||
175 reg == AC97_INT_PAGING || reg == AC97_VENDOR_ID1 ||
176 reg == AC97_VENDOR_ID2) {
177
178 val = soc_ac97_ops.read(codec->ac97, reg);
179 return val;
180 }
181 return cache[reg / 2];
182}
183
184static int ac97_analog_prepare(struct snd_pcm_substream *substream,
185 struct snd_soc_dai *dai)
186{
187 struct snd_soc_codec *codec = dai->codec;
188 struct snd_pcm_runtime *runtime = substream->runtime;
189 unsigned short reg, vra;
190
191 vra = stac9766_ac97_read(codec, AC97_EXTENDED_STATUS);
192
193 vra |= 0x1; /* enable variable rate audio */
194
195 stac9766_ac97_write(codec, AC97_EXTENDED_STATUS, vra);
196
197 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
198 reg = AC97_PCM_FRONT_DAC_RATE;
199 else
200 reg = AC97_PCM_LR_ADC_RATE;
201
202 return stac9766_ac97_write(codec, reg, runtime->rate);
203}
204
205static int ac97_digital_prepare(struct snd_pcm_substream *substream,
206 struct snd_soc_dai *dai)
207{
208 struct snd_soc_codec *codec = dai->codec;
209 struct snd_pcm_runtime *runtime = substream->runtime;
210 unsigned short reg, vra;
211
212 stac9766_ac97_write(codec, AC97_SPDIF, 0x2002);
213
214 vra = stac9766_ac97_read(codec, AC97_EXTENDED_STATUS);
215 vra |= 0x5; /* Enable VRA and SPDIF out */
216
217 stac9766_ac97_write(codec, AC97_EXTENDED_STATUS, vra);
218
219 reg = AC97_PCM_FRONT_DAC_RATE;
220
221 return stac9766_ac97_write(codec, reg, runtime->rate);
222}
223
224static int ac97_digital_trigger(struct snd_pcm_substream *substream,
225 int cmd, struct snd_soc_dai *dai)
226{
227 struct snd_soc_codec *codec = dai->codec;
228 unsigned short vra;
229
230 switch (cmd) {
231 case SNDRV_PCM_TRIGGER_STOP:
232 vra = stac9766_ac97_read(codec, AC97_EXTENDED_STATUS);
233 vra &= !0x04;
234 stac9766_ac97_write(codec, AC97_EXTENDED_STATUS, vra);
235 break;
236 }
237 return 0;
238}
239
240static int stac9766_set_bias_level(struct snd_soc_codec *codec,
241 enum snd_soc_bias_level level)
242{
243 switch (level) {
244 case SND_SOC_BIAS_ON: /* full On */
245 case SND_SOC_BIAS_PREPARE: /* partial On */
246 case SND_SOC_BIAS_STANDBY: /* Off, with power */
247 stac9766_ac97_write(codec, AC97_POWERDOWN, 0x0000);
248 break;
249 case SND_SOC_BIAS_OFF: /* Off, without power */
250 /* disable everything including AC link */
251 stac9766_ac97_write(codec, AC97_POWERDOWN, 0xffff);
252 break;
253 }
254 codec->bias_level = level;
255 return 0;
256}
257
258static int stac9766_reset(struct snd_soc_codec *codec, int try_warm)
259{
260 if (try_warm && soc_ac97_ops.warm_reset) {
261 soc_ac97_ops.warm_reset(codec->ac97);
262 if (stac9766_ac97_read(codec, 0) == stac9766_reg[0])
263 return 1;
264 }
265
266 soc_ac97_ops.reset(codec->ac97);
267 if (soc_ac97_ops.warm_reset)
268 soc_ac97_ops.warm_reset(codec->ac97);
269 if (stac9766_ac97_read(codec, 0) != stac9766_reg[0])
270 return -EIO;
271 return 0;
272}
273
274static int stac9766_codec_suspend(struct platform_device *pdev,
275 pm_message_t state)
276{
277 struct snd_soc_device *socdev = platform_get_drvdata(pdev);
278 struct snd_soc_codec *codec = socdev->card->codec;
279
280 stac9766_set_bias_level(codec, SND_SOC_BIAS_OFF);
281 return 0;
282}
283
284static int stac9766_codec_resume(struct platform_device *pdev)
285{
286 struct snd_soc_device *socdev = platform_get_drvdata(pdev);
287 struct snd_soc_codec *codec = socdev->card->codec;
288 u16 id, reset;
289
290 reset = 0;
291 /* give the codec an AC97 warm reset to start the link */
292reset:
293 if (reset > 5) {
294 printk(KERN_ERR "stac9766 failed to resume");
295 return -EIO;
296 }
297 codec->ac97->bus->ops->warm_reset(codec->ac97);
298 id = soc_ac97_ops.read(codec->ac97, AC97_VENDOR_ID2);
299 if (id != 0x4c13) {
300 stac9766_reset(codec, 0);
301 reset++;
302 goto reset;
303 }
304 stac9766_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
305
306 if (codec->suspend_bias_level == SND_SOC_BIAS_ON)
307 stac9766_set_bias_level(codec, SND_SOC_BIAS_ON);
308
309 return 0;
310}
311
312static struct snd_soc_dai_ops stac9766_dai_ops_analog = {
313 .prepare = ac97_analog_prepare,
314};
315
316static struct snd_soc_dai_ops stac9766_dai_ops_digital = {
317 .prepare = ac97_digital_prepare,
318 .trigger = ac97_digital_trigger,
319};
320
321struct snd_soc_dai stac9766_dai[] = {
322{
323 .name = "stac9766 analog",
324 .id = 0,
325 .ac97_control = 1,
326
327 /* stream cababilities */
328 .playback = {
329 .stream_name = "stac9766 analog",
330 .channels_min = 1,
331 .channels_max = 2,
332 .rates = SNDRV_PCM_RATE_8000_48000,
333 .formats = SND_SOC_STD_AC97_FMTS,
334 },
335 .capture = {
336 .stream_name = "stac9766 analog",
337 .channels_min = 1,
338 .channels_max = 2,
339 .rates = SNDRV_PCM_RATE_8000_48000,
340 .formats = SND_SOC_STD_AC97_FMTS,
341 },
342 /* alsa ops */
343 .ops = &stac9766_dai_ops_analog,
344},
345{
346 .name = "stac9766 IEC958",
347 .id = 1,
348 .ac97_control = 1,
349
350 /* stream cababilities */
351 .playback = {
352 .stream_name = "stac9766 IEC958",
353 .channels_min = 1,
354 .channels_max = 2,
355 .rates = SNDRV_PCM_RATE_32000 | \
356 SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_48000,
357 .formats = SNDRV_PCM_FORMAT_IEC958_SUBFRAME_BE,
358 },
359 /* alsa ops */
360 .ops = &stac9766_dai_ops_digital,
361}
362};
363EXPORT_SYMBOL_GPL(stac9766_dai);
364
365static int stac9766_codec_probe(struct platform_device *pdev)
366{
367 struct snd_soc_device *socdev = platform_get_drvdata(pdev);
368 struct snd_soc_codec *codec;
369 int ret = 0;
370
371 printk(KERN_INFO "STAC9766 SoC Audio Codec %s\n", STAC9766_VERSION);
372
373 socdev->card->codec = kzalloc(sizeof(struct snd_soc_codec), GFP_KERNEL);
374 if (socdev->card->codec == NULL)
375 return -ENOMEM;
376 codec = socdev->card->codec;
377 mutex_init(&codec->mutex);
378
379 codec->reg_cache = kmemdup(stac9766_reg, sizeof(stac9766_reg),
380 GFP_KERNEL);
381 if (codec->reg_cache == NULL) {
382 ret = -ENOMEM;
383 goto cache_err;
384 }
385 codec->reg_cache_size = sizeof(stac9766_reg);
386 codec->reg_cache_step = 2;
387
388 codec->name = "STAC9766";
389 codec->owner = THIS_MODULE;
390 codec->dai = stac9766_dai;
391 codec->num_dai = ARRAY_SIZE(stac9766_dai);
392 codec->write = stac9766_ac97_write;
393 codec->read = stac9766_ac97_read;
394 codec->set_bias_level = stac9766_set_bias_level;
395 INIT_LIST_HEAD(&codec->dapm_widgets);
396 INIT_LIST_HEAD(&codec->dapm_paths);
397
398 ret = snd_soc_new_ac97_codec(codec, &soc_ac97_ops, 0);
399 if (ret < 0)
400 goto codec_err;
401
402 /* register pcms */
403 ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1);
404 if (ret < 0)
405 goto pcm_err;
406
407 /* do a cold reset for the controller and then try
408 * a warm reset followed by an optional cold reset for codec */
409 stac9766_reset(codec, 0);
410 ret = stac9766_reset(codec, 1);
411 if (ret < 0) {
412 printk(KERN_ERR "Failed to reset STAC9766: AC97 link error\n");
413 goto reset_err;
414 }
415
416 stac9766_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
417
418 snd_soc_add_controls(codec, stac9766_snd_ac97_controls,
419 ARRAY_SIZE(stac9766_snd_ac97_controls));
420
421 ret = snd_soc_init_card(socdev);
422 if (ret < 0)
423 goto reset_err;
424 return 0;
425
426reset_err:
427 snd_soc_free_pcms(socdev);
428pcm_err:
429 snd_soc_free_ac97_codec(codec);
430codec_err:
431 kfree(codec->private_data);
432cache_err:
433 kfree(socdev->card->codec);
434 socdev->card->codec = NULL;
435 return ret;
436}
437
438static int stac9766_codec_remove(struct platform_device *pdev)
439{
440 struct snd_soc_device *socdev = platform_get_drvdata(pdev);
441 struct snd_soc_codec *codec = socdev->card->codec;
442
443 if (codec == NULL)
444 return 0;
445
446 snd_soc_free_pcms(socdev);
447 snd_soc_free_ac97_codec(codec);
448 kfree(codec->reg_cache);
449 kfree(codec);
450 return 0;
451}
452
453struct snd_soc_codec_device soc_codec_dev_stac9766 = {
454 .probe = stac9766_codec_probe,
455 .remove = stac9766_codec_remove,
456 .suspend = stac9766_codec_suspend,
457 .resume = stac9766_codec_resume,
458};
459EXPORT_SYMBOL_GPL(soc_codec_dev_stac9766);
460
461MODULE_DESCRIPTION("ASoC stac9766 driver");
462MODULE_AUTHOR("Jon Smirl <jonsmirl@gmail.com>");
463MODULE_LICENSE("GPL");
diff --git a/sound/soc/codecs/stac9766.h b/sound/soc/codecs/stac9766.h
new file mode 100644
index 000000000000..65642eb8393e
--- /dev/null
+++ b/sound/soc/codecs/stac9766.h
@@ -0,0 +1,21 @@
1/*
2 * stac9766.h -- STAC9766 Soc Audio driver
3 */
4
5#ifndef _STAC9766_H
6#define _STAC9766_H
7
8#define AC97_STAC_PAGE0 0x1000
9#define AC97_STAC_DA_CONTROL (AC97_STAC_PAGE0 | 0x6A)
10#define AC97_STAC_ANALOG_SPECIAL (AC97_STAC_PAGE0 | 0x6E)
11#define AC97_STAC_STEREO_MIC 0x78
12
13/* STAC9766 DAI ID's */
14#define STAC9766_DAI_AC97_ANALOG 0
15#define STAC9766_DAI_AC97_DIGITAL 1
16
17extern struct snd_soc_dai stac9766_dai[];
18extern struct snd_soc_codec_device soc_codec_dev_stac9766;
19
20
21#endif
diff --git a/sound/soc/codecs/tlv320aic23.c b/sound/soc/codecs/tlv320aic23.c
index c3f4afb5d017..0b8dcb5cd729 100644
--- a/sound/soc/codecs/tlv320aic23.c
+++ b/sound/soc/codecs/tlv320aic23.c
@@ -86,7 +86,7 @@ static int tlv320aic23_write(struct snd_soc_codec *codec, unsigned int reg,
86 */ 86 */
87 87
88 if ((reg < 0 || reg > 9) && (reg != 15)) { 88 if ((reg < 0 || reg > 9) && (reg != 15)) {
89 printk(KERN_WARNING "%s Invalid register R%d\n", __func__, reg); 89 printk(KERN_WARNING "%s Invalid register R%u\n", __func__, reg);
90 return -1; 90 return -1;
91 } 91 }
92 92
@@ -98,7 +98,7 @@ static int tlv320aic23_write(struct snd_soc_codec *codec, unsigned int reg,
98 if (codec->hw_write(codec->control_data, data, 2) == 2) 98 if (codec->hw_write(codec->control_data, data, 2) == 2)
99 return 0; 99 return 0;
100 100
101 printk(KERN_ERR "%s cannot write %03x to register R%d\n", __func__, 101 printk(KERN_ERR "%s cannot write %03x to register R%u\n", __func__,
102 value, reg); 102 value, reg);
103 103
104 return -EIO; 104 return -EIO;
@@ -273,14 +273,14 @@ static const unsigned short sr_valid_mask[] = {
273 * Every divisor is a factor of 11*12 273 * Every divisor is a factor of 11*12
274 */ 274 */
275#define SR_MULT (11*12) 275#define SR_MULT (11*12)
276#define A(x) (x) ? (SR_MULT/x) : 0 276#define A(x) (SR_MULT/x)
277static const unsigned char sr_adc_mult_table[] = { 277static const unsigned char sr_adc_mult_table[] = {
278 A(2), A(2), A(12), A(12), A(0), A(0), A(3), A(1), 278 A(2), A(2), A(12), A(12), 0, 0, A(3), A(1),
279 A(2), A(2), A(11), A(11), A(0), A(0), A(0), A(1) 279 A(2), A(2), A(11), A(11), 0, 0, 0, A(1)
280}; 280};
281static const unsigned char sr_dac_mult_table[] = { 281static const unsigned char sr_dac_mult_table[] = {
282 A(2), A(12), A(2), A(12), A(0), A(0), A(3), A(1), 282 A(2), A(12), A(2), A(12), 0, 0, A(3), A(1),
283 A(2), A(11), A(2), A(11), A(0), A(0), A(0), A(1) 283 A(2), A(11), A(2), A(11), 0, 0, 0, A(1)
284}; 284};
285 285
286static unsigned get_score(int adc, int adc_l, int adc_h, int need_adc, 286static unsigned get_score(int adc, int adc_l, int adc_h, int need_adc,
@@ -523,6 +523,8 @@ static int tlv320aic23_set_dai_fmt(struct snd_soc_dai *codec_dai,
523 case SND_SOC_DAIFMT_I2S: 523 case SND_SOC_DAIFMT_I2S:
524 iface_reg |= TLV320AIC23_FOR_I2S; 524 iface_reg |= TLV320AIC23_FOR_I2S;
525 break; 525 break;
526 case SND_SOC_DAIFMT_DSP_A:
527 iface_reg |= TLV320AIC23_LRP_ON;
526 case SND_SOC_DAIFMT_DSP_B: 528 case SND_SOC_DAIFMT_DSP_B:
527 iface_reg |= TLV320AIC23_FOR_DSP; 529 iface_reg |= TLV320AIC23_FOR_DSP;
528 break; 530 break;
diff --git a/sound/soc/codecs/tlv320aic3x.c b/sound/soc/codecs/tlv320aic3x.c
index ab099f482487..126b15b18aeb 100644
--- a/sound/soc/codecs/tlv320aic3x.c
+++ b/sound/soc/codecs/tlv320aic3x.c
@@ -145,8 +145,8 @@ static int aic3x_read(struct snd_soc_codec *codec, unsigned int reg,
145 u8 *value) 145 u8 *value)
146{ 146{
147 *value = reg & 0xff; 147 *value = reg & 0xff;
148 if (codec->hw_read(codec->control_data, value, 1) != 1) 148
149 return -EIO; 149 value[0] = i2c_smbus_read_byte_data(codec->control_data, value[0]);
150 150
151 aic3x_write_reg_cache(codec, reg, *value); 151 aic3x_write_reg_cache(codec, reg, *value);
152 return 0; 152 return 0;
@@ -767,6 +767,7 @@ static int aic3x_hw_params(struct snd_pcm_substream *substream,
767 int codec_clk = 0, bypass_pll = 0, fsref, last_clk = 0; 767 int codec_clk = 0, bypass_pll = 0, fsref, last_clk = 0;
768 u8 data, r, p, pll_q, pll_p = 1, pll_r = 1, pll_j = 1; 768 u8 data, r, p, pll_q, pll_p = 1, pll_r = 1, pll_j = 1;
769 u16 pll_d = 1; 769 u16 pll_d = 1;
770 u8 reg;
770 771
771 /* select data word length */ 772 /* select data word length */
772 data = 773 data =
@@ -801,8 +802,16 @@ static int aic3x_hw_params(struct snd_pcm_substream *substream,
801 pll_q &= 0xf; 802 pll_q &= 0xf;
802 aic3x_write(codec, AIC3X_PLL_PROGA_REG, pll_q << PLLQ_SHIFT); 803 aic3x_write(codec, AIC3X_PLL_PROGA_REG, pll_q << PLLQ_SHIFT);
803 aic3x_write(codec, AIC3X_GPIOB_REG, CODEC_CLKIN_CLKDIV); 804 aic3x_write(codec, AIC3X_GPIOB_REG, CODEC_CLKIN_CLKDIV);
804 } else 805 /* disable PLL if it is bypassed */
806 reg = aic3x_read_reg_cache(codec, AIC3X_PLL_PROGA_REG);
807 aic3x_write(codec, AIC3X_PLL_PROGA_REG, reg & ~PLL_ENABLE);
808
809 } else {
805 aic3x_write(codec, AIC3X_GPIOB_REG, CODEC_CLKIN_PLLDIV); 810 aic3x_write(codec, AIC3X_GPIOB_REG, CODEC_CLKIN_PLLDIV);
811 /* enable PLL when it is used */
812 reg = aic3x_read_reg_cache(codec, AIC3X_PLL_PROGA_REG);
813 aic3x_write(codec, AIC3X_PLL_PROGA_REG, reg | PLL_ENABLE);
814 }
806 815
807 /* Route Left DAC to left channel input and 816 /* Route Left DAC to left channel input and
808 * right DAC to right channel input */ 817 * right DAC to right channel input */
@@ -1316,12 +1325,6 @@ static struct i2c_driver aic3x_i2c_driver = {
1316 .id_table = aic3x_i2c_id, 1325 .id_table = aic3x_i2c_id,
1317}; 1326};
1318 1327
1319static int aic3x_i2c_read(struct i2c_client *client, u8 *value, int len)
1320{
1321 value[0] = i2c_smbus_read_byte_data(client, value[0]);
1322 return (len == 1);
1323}
1324
1325static int aic3x_add_i2c_device(struct platform_device *pdev, 1328static int aic3x_add_i2c_device(struct platform_device *pdev,
1326 const struct aic3x_setup_data *setup) 1329 const struct aic3x_setup_data *setup)
1327{ 1330{
@@ -1394,7 +1397,6 @@ static int aic3x_probe(struct platform_device *pdev)
1394#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) 1397#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
1395 if (setup->i2c_address) { 1398 if (setup->i2c_address) {
1396 codec->hw_write = (hw_write_t) i2c_master_send; 1399 codec->hw_write = (hw_write_t) i2c_master_send;
1397 codec->hw_read = (hw_read_t) aic3x_i2c_read;
1398 ret = aic3x_add_i2c_device(pdev, setup); 1400 ret = aic3x_add_i2c_device(pdev, setup);
1399 } 1401 }
1400#else 1402#else
diff --git a/sound/soc/codecs/twl4030.c b/sound/soc/codecs/twl4030.c
index df7c8c281d2f..4df7c6c61c76 100644
--- a/sound/soc/codecs/twl4030.c
+++ b/sound/soc/codecs/twl4030.c
@@ -115,6 +115,7 @@ static const u8 twl4030_reg[TWL4030_CACHEREGNUM] = {
115 0x00, /* REG_VIBRA_PWM_SET (0x47) */ 115 0x00, /* REG_VIBRA_PWM_SET (0x47) */
116 0x00, /* REG_ANAMIC_GAIN (0x48) */ 116 0x00, /* REG_ANAMIC_GAIN (0x48) */
117 0x00, /* REG_MISC_SET_2 (0x49) */ 117 0x00, /* REG_MISC_SET_2 (0x49) */
118 0x00, /* REG_SW_SHADOW (0x4A) - Shadow, non HW register */
118}; 119};
119 120
120/* codec private data */ 121/* codec private data */
@@ -125,6 +126,17 @@ struct twl4030_priv {
125 126
126 struct snd_pcm_substream *master_substream; 127 struct snd_pcm_substream *master_substream;
127 struct snd_pcm_substream *slave_substream; 128 struct snd_pcm_substream *slave_substream;
129
130 unsigned int configured;
131 unsigned int rate;
132 unsigned int sample_bits;
133 unsigned int channels;
134
135 unsigned int sysclk;
136
137 /* Headset output state handling */
138 unsigned int hsl_enabled;
139 unsigned int hsr_enabled;
128}; 140};
129 141
130/* 142/*
@@ -161,7 +173,11 @@ static int twl4030_write(struct snd_soc_codec *codec,
161 unsigned int reg, unsigned int value) 173 unsigned int reg, unsigned int value)
162{ 174{
163 twl4030_write_reg_cache(codec, reg, value); 175 twl4030_write_reg_cache(codec, reg, value);
164 return twl4030_i2c_write_u8(TWL4030_MODULE_AUDIO_VOICE, value, reg); 176 if (likely(reg < TWL4030_REG_SW_SHADOW))
177 return twl4030_i2c_write_u8(TWL4030_MODULE_AUDIO_VOICE, value,
178 reg);
179 else
180 return 0;
165} 181}
166 182
167static void twl4030_codec_enable(struct snd_soc_codec *codec, int enable) 183static void twl4030_codec_enable(struct snd_soc_codec *codec, int enable)
@@ -188,6 +204,7 @@ static void twl4030_codec_enable(struct snd_soc_codec *codec, int enable)
188 204
189static void twl4030_init_chip(struct snd_soc_codec *codec) 205static void twl4030_init_chip(struct snd_soc_codec *codec)
190{ 206{
207 u8 *cache = codec->reg_cache;
191 int i; 208 int i;
192 209
193 /* clear CODECPDZ prior to setting register defaults */ 210 /* clear CODECPDZ prior to setting register defaults */
@@ -195,7 +212,7 @@ static void twl4030_init_chip(struct snd_soc_codec *codec)
195 212
196 /* set all audio section registers to reasonable defaults */ 213 /* set all audio section registers to reasonable defaults */
197 for (i = TWL4030_REG_OPTION; i <= TWL4030_REG_MISC_SET_2; i++) 214 for (i = TWL4030_REG_OPTION; i <= TWL4030_REG_MISC_SET_2; i++)
198 twl4030_write(codec, i, twl4030_reg[i]); 215 twl4030_write(codec, i, cache[i]);
199 216
200} 217}
201 218
@@ -208,55 +225,11 @@ static void twl4030_codec_mute(struct snd_soc_codec *codec, int mute)
208 return; 225 return;
209 226
210 if (mute) { 227 if (mute) {
211 /* Bypass the reg_cache and mute the volumes
212 * Headset mute is done in it's own event handler
213 * Things to mute: Earpiece, PreDrivL/R, CarkitL/R
214 */
215 reg_val = twl4030_read_reg_cache(codec, TWL4030_REG_EAR_CTL);
216 twl4030_i2c_write_u8(TWL4030_MODULE_AUDIO_VOICE,
217 reg_val & (~TWL4030_EAR_GAIN),
218 TWL4030_REG_EAR_CTL);
219
220 reg_val = twl4030_read_reg_cache(codec, TWL4030_REG_PREDL_CTL);
221 twl4030_i2c_write_u8(TWL4030_MODULE_AUDIO_VOICE,
222 reg_val & (~TWL4030_PREDL_GAIN),
223 TWL4030_REG_PREDL_CTL);
224 reg_val = twl4030_read_reg_cache(codec, TWL4030_REG_PREDR_CTL);
225 twl4030_i2c_write_u8(TWL4030_MODULE_AUDIO_VOICE,
226 reg_val & (~TWL4030_PREDR_GAIN),
227 TWL4030_REG_PREDL_CTL);
228
229 reg_val = twl4030_read_reg_cache(codec, TWL4030_REG_PRECKL_CTL);
230 twl4030_i2c_write_u8(TWL4030_MODULE_AUDIO_VOICE,
231 reg_val & (~TWL4030_PRECKL_GAIN),
232 TWL4030_REG_PRECKL_CTL);
233 reg_val = twl4030_read_reg_cache(codec, TWL4030_REG_PRECKR_CTL);
234 twl4030_i2c_write_u8(TWL4030_MODULE_AUDIO_VOICE,
235 reg_val & (~TWL4030_PRECKL_GAIN),
236 TWL4030_REG_PRECKR_CTL);
237
238 /* Disable PLL */ 228 /* Disable PLL */
239 reg_val = twl4030_read_reg_cache(codec, TWL4030_REG_APLL_CTL); 229 reg_val = twl4030_read_reg_cache(codec, TWL4030_REG_APLL_CTL);
240 reg_val &= ~TWL4030_APLL_EN; 230 reg_val &= ~TWL4030_APLL_EN;
241 twl4030_write(codec, TWL4030_REG_APLL_CTL, reg_val); 231 twl4030_write(codec, TWL4030_REG_APLL_CTL, reg_val);
242 } else { 232 } else {
243 /* Restore the volumes
244 * Headset mute is done in it's own event handler
245 * Things to restore: Earpiece, PreDrivL/R, CarkitL/R
246 */
247 twl4030_write(codec, TWL4030_REG_EAR_CTL,
248 twl4030_read_reg_cache(codec, TWL4030_REG_EAR_CTL));
249
250 twl4030_write(codec, TWL4030_REG_PREDL_CTL,
251 twl4030_read_reg_cache(codec, TWL4030_REG_PREDL_CTL));
252 twl4030_write(codec, TWL4030_REG_PREDR_CTL,
253 twl4030_read_reg_cache(codec, TWL4030_REG_PREDR_CTL));
254
255 twl4030_write(codec, TWL4030_REG_PRECKL_CTL,
256 twl4030_read_reg_cache(codec, TWL4030_REG_PRECKL_CTL));
257 twl4030_write(codec, TWL4030_REG_PRECKR_CTL,
258 twl4030_read_reg_cache(codec, TWL4030_REG_PRECKR_CTL));
259
260 /* Enable PLL */ 233 /* Enable PLL */
261 reg_val = twl4030_read_reg_cache(codec, TWL4030_REG_APLL_CTL); 234 reg_val = twl4030_read_reg_cache(codec, TWL4030_REG_APLL_CTL);
262 reg_val |= TWL4030_APLL_EN; 235 reg_val |= TWL4030_APLL_EN;
@@ -316,104 +289,60 @@ static void twl4030_power_down(struct snd_soc_codec *codec)
316} 289}
317 290
318/* Earpiece */ 291/* Earpiece */
319static const char *twl4030_earpiece_texts[] = 292static const struct snd_kcontrol_new twl4030_dapm_earpiece_controls[] = {
320 {"Off", "DACL1", "DACL2", "DACR1"}; 293 SOC_DAPM_SINGLE("Voice", TWL4030_REG_EAR_CTL, 0, 1, 0),
321 294 SOC_DAPM_SINGLE("AudioL1", TWL4030_REG_EAR_CTL, 1, 1, 0),
322static const unsigned int twl4030_earpiece_values[] = 295 SOC_DAPM_SINGLE("AudioL2", TWL4030_REG_EAR_CTL, 2, 1, 0),
323 {0x0, 0x1, 0x2, 0x4}; 296 SOC_DAPM_SINGLE("AudioR1", TWL4030_REG_EAR_CTL, 3, 1, 0),
324 297};
325static const struct soc_enum twl4030_earpiece_enum =
326 SOC_VALUE_ENUM_SINGLE(TWL4030_REG_EAR_CTL, 1, 0x7,
327 ARRAY_SIZE(twl4030_earpiece_texts),
328 twl4030_earpiece_texts,
329 twl4030_earpiece_values);
330
331static const struct snd_kcontrol_new twl4030_dapm_earpiece_control =
332SOC_DAPM_VALUE_ENUM("Route", twl4030_earpiece_enum);
333 298
334/* PreDrive Left */ 299/* PreDrive Left */
335static const char *twl4030_predrivel_texts[] = 300static const struct snd_kcontrol_new twl4030_dapm_predrivel_controls[] = {
336 {"Off", "DACL1", "DACL2", "DACR2"}; 301 SOC_DAPM_SINGLE("Voice", TWL4030_REG_PREDL_CTL, 0, 1, 0),
337 302 SOC_DAPM_SINGLE("AudioL1", TWL4030_REG_PREDL_CTL, 1, 1, 0),
338static const unsigned int twl4030_predrivel_values[] = 303 SOC_DAPM_SINGLE("AudioL2", TWL4030_REG_PREDL_CTL, 2, 1, 0),
339 {0x0, 0x1, 0x2, 0x4}; 304 SOC_DAPM_SINGLE("AudioR2", TWL4030_REG_PREDL_CTL, 3, 1, 0),
340 305};
341static const struct soc_enum twl4030_predrivel_enum =
342 SOC_VALUE_ENUM_SINGLE(TWL4030_REG_PREDL_CTL, 1, 0x7,
343 ARRAY_SIZE(twl4030_predrivel_texts),
344 twl4030_predrivel_texts,
345 twl4030_predrivel_values);
346
347static const struct snd_kcontrol_new twl4030_dapm_predrivel_control =
348SOC_DAPM_VALUE_ENUM("Route", twl4030_predrivel_enum);
349 306
350/* PreDrive Right */ 307/* PreDrive Right */
351static const char *twl4030_predriver_texts[] = 308static const struct snd_kcontrol_new twl4030_dapm_predriver_controls[] = {
352 {"Off", "DACR1", "DACR2", "DACL2"}; 309 SOC_DAPM_SINGLE("Voice", TWL4030_REG_PREDR_CTL, 0, 1, 0),
353 310 SOC_DAPM_SINGLE("AudioR1", TWL4030_REG_PREDR_CTL, 1, 1, 0),
354static const unsigned int twl4030_predriver_values[] = 311 SOC_DAPM_SINGLE("AudioR2", TWL4030_REG_PREDR_CTL, 2, 1, 0),
355 {0x0, 0x1, 0x2, 0x4}; 312 SOC_DAPM_SINGLE("AudioL2", TWL4030_REG_PREDR_CTL, 3, 1, 0),
356 313};
357static const struct soc_enum twl4030_predriver_enum =
358 SOC_VALUE_ENUM_SINGLE(TWL4030_REG_PREDR_CTL, 1, 0x7,
359 ARRAY_SIZE(twl4030_predriver_texts),
360 twl4030_predriver_texts,
361 twl4030_predriver_values);
362
363static const struct snd_kcontrol_new twl4030_dapm_predriver_control =
364SOC_DAPM_VALUE_ENUM("Route", twl4030_predriver_enum);
365 314
366/* Headset Left */ 315/* Headset Left */
367static const char *twl4030_hsol_texts[] = 316static const struct snd_kcontrol_new twl4030_dapm_hsol_controls[] = {
368 {"Off", "DACL1", "DACL2"}; 317 SOC_DAPM_SINGLE("Voice", TWL4030_REG_HS_SEL, 0, 1, 0),
369 318 SOC_DAPM_SINGLE("AudioL1", TWL4030_REG_HS_SEL, 1, 1, 0),
370static const struct soc_enum twl4030_hsol_enum = 319 SOC_DAPM_SINGLE("AudioL2", TWL4030_REG_HS_SEL, 2, 1, 0),
371 SOC_ENUM_SINGLE(TWL4030_REG_HS_SEL, 1, 320};
372 ARRAY_SIZE(twl4030_hsol_texts),
373 twl4030_hsol_texts);
374
375static const struct snd_kcontrol_new twl4030_dapm_hsol_control =
376SOC_DAPM_ENUM("Route", twl4030_hsol_enum);
377 321
378/* Headset Right */ 322/* Headset Right */
379static const char *twl4030_hsor_texts[] = 323static const struct snd_kcontrol_new twl4030_dapm_hsor_controls[] = {
380 {"Off", "DACR1", "DACR2"}; 324 SOC_DAPM_SINGLE("Voice", TWL4030_REG_HS_SEL, 3, 1, 0),
381 325 SOC_DAPM_SINGLE("AudioR1", TWL4030_REG_HS_SEL, 4, 1, 0),
382static const struct soc_enum twl4030_hsor_enum = 326 SOC_DAPM_SINGLE("AudioR2", TWL4030_REG_HS_SEL, 5, 1, 0),
383 SOC_ENUM_SINGLE(TWL4030_REG_HS_SEL, 4, 327};
384 ARRAY_SIZE(twl4030_hsor_texts),
385 twl4030_hsor_texts);
386
387static const struct snd_kcontrol_new twl4030_dapm_hsor_control =
388SOC_DAPM_ENUM("Route", twl4030_hsor_enum);
389 328
390/* Carkit Left */ 329/* Carkit Left */
391static const char *twl4030_carkitl_texts[] = 330static const struct snd_kcontrol_new twl4030_dapm_carkitl_controls[] = {
392 {"Off", "DACL1", "DACL2"}; 331 SOC_DAPM_SINGLE("Voice", TWL4030_REG_PRECKL_CTL, 0, 1, 0),
393 332 SOC_DAPM_SINGLE("AudioL1", TWL4030_REG_PRECKL_CTL, 1, 1, 0),
394static const struct soc_enum twl4030_carkitl_enum = 333 SOC_DAPM_SINGLE("AudioL2", TWL4030_REG_PRECKL_CTL, 2, 1, 0),
395 SOC_ENUM_SINGLE(TWL4030_REG_PRECKL_CTL, 1, 334};
396 ARRAY_SIZE(twl4030_carkitl_texts),
397 twl4030_carkitl_texts);
398
399static const struct snd_kcontrol_new twl4030_dapm_carkitl_control =
400SOC_DAPM_ENUM("Route", twl4030_carkitl_enum);
401 335
402/* Carkit Right */ 336/* Carkit Right */
403static const char *twl4030_carkitr_texts[] = 337static const struct snd_kcontrol_new twl4030_dapm_carkitr_controls[] = {
404 {"Off", "DACR1", "DACR2"}; 338 SOC_DAPM_SINGLE("Voice", TWL4030_REG_PRECKR_CTL, 0, 1, 0),
405 339 SOC_DAPM_SINGLE("AudioR1", TWL4030_REG_PRECKR_CTL, 1, 1, 0),
406static const struct soc_enum twl4030_carkitr_enum = 340 SOC_DAPM_SINGLE("AudioR2", TWL4030_REG_PRECKR_CTL, 2, 1, 0),
407 SOC_ENUM_SINGLE(TWL4030_REG_PRECKR_CTL, 1, 341};
408 ARRAY_SIZE(twl4030_carkitr_texts),
409 twl4030_carkitr_texts);
410
411static const struct snd_kcontrol_new twl4030_dapm_carkitr_control =
412SOC_DAPM_ENUM("Route", twl4030_carkitr_enum);
413 342
414/* Handsfree Left */ 343/* Handsfree Left */
415static const char *twl4030_handsfreel_texts[] = 344static const char *twl4030_handsfreel_texts[] =
416 {"Voice", "DACL1", "DACL2", "DACR2"}; 345 {"Voice", "AudioL1", "AudioL2", "AudioR2"};
417 346
418static const struct soc_enum twl4030_handsfreel_enum = 347static const struct soc_enum twl4030_handsfreel_enum =
419 SOC_ENUM_SINGLE(TWL4030_REG_HFL_CTL, 0, 348 SOC_ENUM_SINGLE(TWL4030_REG_HFL_CTL, 0,
@@ -423,9 +352,13 @@ static const struct soc_enum twl4030_handsfreel_enum =
423static const struct snd_kcontrol_new twl4030_dapm_handsfreel_control = 352static const struct snd_kcontrol_new twl4030_dapm_handsfreel_control =
424SOC_DAPM_ENUM("Route", twl4030_handsfreel_enum); 353SOC_DAPM_ENUM("Route", twl4030_handsfreel_enum);
425 354
355/* Handsfree Left virtual mute */
356static const struct snd_kcontrol_new twl4030_dapm_handsfreelmute_control =
357 SOC_DAPM_SINGLE("Switch", TWL4030_REG_SW_SHADOW, 0, 1, 0);
358
426/* Handsfree Right */ 359/* Handsfree Right */
427static const char *twl4030_handsfreer_texts[] = 360static const char *twl4030_handsfreer_texts[] =
428 {"Voice", "DACR1", "DACR2", "DACL2"}; 361 {"Voice", "AudioR1", "AudioR2", "AudioL2"};
429 362
430static const struct soc_enum twl4030_handsfreer_enum = 363static const struct soc_enum twl4030_handsfreer_enum =
431 SOC_ENUM_SINGLE(TWL4030_REG_HFR_CTL, 0, 364 SOC_ENUM_SINGLE(TWL4030_REG_HFR_CTL, 0,
@@ -435,37 +368,52 @@ static const struct soc_enum twl4030_handsfreer_enum =
435static const struct snd_kcontrol_new twl4030_dapm_handsfreer_control = 368static const struct snd_kcontrol_new twl4030_dapm_handsfreer_control =
436SOC_DAPM_ENUM("Route", twl4030_handsfreer_enum); 369SOC_DAPM_ENUM("Route", twl4030_handsfreer_enum);
437 370
438/* Left analog microphone selection */ 371/* Handsfree Right virtual mute */
439static const char *twl4030_analoglmic_texts[] = 372static const struct snd_kcontrol_new twl4030_dapm_handsfreermute_control =
440 {"Off", "Main mic", "Headset mic", "AUXL", "Carkit mic"}; 373 SOC_DAPM_SINGLE("Switch", TWL4030_REG_SW_SHADOW, 1, 1, 0);
441 374
442static const unsigned int twl4030_analoglmic_values[] = 375/* Vibra */
443 {0x0, 0x1, 0x2, 0x4, 0x8}; 376/* Vibra audio path selection */
377static const char *twl4030_vibra_texts[] =
378 {"AudioL1", "AudioR1", "AudioL2", "AudioR2"};
444 379
445static const struct soc_enum twl4030_analoglmic_enum = 380static const struct soc_enum twl4030_vibra_enum =
446 SOC_VALUE_ENUM_SINGLE(TWL4030_REG_ANAMICL, 0, 0xf, 381 SOC_ENUM_SINGLE(TWL4030_REG_VIBRA_CTL, 2,
447 ARRAY_SIZE(twl4030_analoglmic_texts), 382 ARRAY_SIZE(twl4030_vibra_texts),
448 twl4030_analoglmic_texts, 383 twl4030_vibra_texts);
449 twl4030_analoglmic_values);
450 384
451static const struct snd_kcontrol_new twl4030_dapm_analoglmic_control = 385static const struct snd_kcontrol_new twl4030_dapm_vibra_control =
452SOC_DAPM_VALUE_ENUM("Route", twl4030_analoglmic_enum); 386SOC_DAPM_ENUM("Route", twl4030_vibra_enum);
453 387
454/* Right analog microphone selection */ 388/* Vibra path selection: local vibrator (PWM) or audio driven */
455static const char *twl4030_analogrmic_texts[] = 389static const char *twl4030_vibrapath_texts[] =
456 {"Off", "Sub mic", "AUXR"}; 390 {"Local vibrator", "Audio"};
457 391
458static const unsigned int twl4030_analogrmic_values[] = 392static const struct soc_enum twl4030_vibrapath_enum =
459 {0x0, 0x1, 0x4}; 393 SOC_ENUM_SINGLE(TWL4030_REG_VIBRA_CTL, 4,
394 ARRAY_SIZE(twl4030_vibrapath_texts),
395 twl4030_vibrapath_texts);
460 396
461static const struct soc_enum twl4030_analogrmic_enum = 397static const struct snd_kcontrol_new twl4030_dapm_vibrapath_control =
462 SOC_VALUE_ENUM_SINGLE(TWL4030_REG_ANAMICR, 0, 0x5, 398SOC_DAPM_ENUM("Route", twl4030_vibrapath_enum);
463 ARRAY_SIZE(twl4030_analogrmic_texts),
464 twl4030_analogrmic_texts,
465 twl4030_analogrmic_values);
466 399
467static const struct snd_kcontrol_new twl4030_dapm_analogrmic_control = 400/* Left analog microphone selection */
468SOC_DAPM_VALUE_ENUM("Route", twl4030_analogrmic_enum); 401static const struct snd_kcontrol_new twl4030_dapm_analoglmic_controls[] = {
402 SOC_DAPM_SINGLE("Main Mic Capture Switch",
403 TWL4030_REG_ANAMICL, 0, 1, 0),
404 SOC_DAPM_SINGLE("Headset Mic Capture Switch",
405 TWL4030_REG_ANAMICL, 1, 1, 0),
406 SOC_DAPM_SINGLE("AUXL Capture Switch",
407 TWL4030_REG_ANAMICL, 2, 1, 0),
408 SOC_DAPM_SINGLE("Carkit Mic Capture Switch",
409 TWL4030_REG_ANAMICL, 3, 1, 0),
410};
411
412/* Right analog microphone selection */
413static const struct snd_kcontrol_new twl4030_dapm_analogrmic_controls[] = {
414 SOC_DAPM_SINGLE("Sub Mic Capture Switch", TWL4030_REG_ANAMICR, 0, 1, 0),
415 SOC_DAPM_SINGLE("AUXR Capture Switch", TWL4030_REG_ANAMICR, 2, 1, 0),
416};
469 417
470/* TX1 L/R Analog/Digital microphone selection */ 418/* TX1 L/R Analog/Digital microphone selection */
471static const char *twl4030_micpathtx1_texts[] = 419static const char *twl4030_micpathtx1_texts[] =
@@ -507,6 +455,10 @@ static const struct snd_kcontrol_new twl4030_dapm_abypassr2_control =
507static const struct snd_kcontrol_new twl4030_dapm_abypassl2_control = 455static const struct snd_kcontrol_new twl4030_dapm_abypassl2_control =
508 SOC_DAPM_SINGLE("Switch", TWL4030_REG_ARXL2_APGA_CTL, 2, 1, 0); 456 SOC_DAPM_SINGLE("Switch", TWL4030_REG_ARXL2_APGA_CTL, 2, 1, 0);
509 457
458/* Analog bypass for Voice */
459static const struct snd_kcontrol_new twl4030_dapm_abypassv_control =
460 SOC_DAPM_SINGLE("Switch", TWL4030_REG_VDL_APGA_CTL, 2, 1, 0);
461
510/* Digital bypass gain, 0 mutes the bypass */ 462/* Digital bypass gain, 0 mutes the bypass */
511static const unsigned int twl4030_dapm_dbypass_tlv[] = { 463static const unsigned int twl4030_dapm_dbypass_tlv[] = {
512 TLV_DB_RANGE_HEAD(2), 464 TLV_DB_RANGE_HEAD(2),
@@ -526,6 +478,18 @@ static const struct snd_kcontrol_new twl4030_dapm_dbypassr_control =
526 TWL4030_REG_ATX2ARXPGA, 0, 7, 0, 478 TWL4030_REG_ATX2ARXPGA, 0, 7, 0,
527 twl4030_dapm_dbypass_tlv); 479 twl4030_dapm_dbypass_tlv);
528 480
481/*
482 * Voice Sidetone GAIN volume control:
483 * from -51 to -10 dB in 1 dB steps (mute instead of -51 dB)
484 */
485static DECLARE_TLV_DB_SCALE(twl4030_dapm_dbypassv_tlv, -5100, 100, 1);
486
487/* Digital bypass voice: sidetone (VUL -> VDL)*/
488static const struct snd_kcontrol_new twl4030_dapm_dbypassv_control =
489 SOC_DAPM_SINGLE_TLV("Volume",
490 TWL4030_REG_VSTPGA, 0, 0x29, 0,
491 twl4030_dapm_dbypassv_tlv);
492
529static int micpath_event(struct snd_soc_dapm_widget *w, 493static int micpath_event(struct snd_soc_dapm_widget *w,
530 struct snd_kcontrol *kcontrol, int event) 494 struct snd_kcontrol *kcontrol, int event)
531{ 495{
@@ -556,63 +520,205 @@ static int micpath_event(struct snd_soc_dapm_widget *w,
556 return 0; 520 return 0;
557} 521}
558 522
559static int handsfree_event(struct snd_soc_dapm_widget *w, 523/*
560 struct snd_kcontrol *kcontrol, int event) 524 * Output PGA builder:
525 * Handle the muting and unmuting of the given output (turning off the
526 * amplifier associated with the output pin)
527 * On mute bypass the reg_cache and mute the volume
528 * On unmute: restore the register content
529 * Outputs handled in this way: Earpiece, PreDrivL/R, CarkitL/R
530 */
531#define TWL4030_OUTPUT_PGA(pin_name, reg, mask) \
532static int pin_name##pga_event(struct snd_soc_dapm_widget *w, \
533 struct snd_kcontrol *kcontrol, int event) \
534{ \
535 u8 reg_val; \
536 \
537 switch (event) { \
538 case SND_SOC_DAPM_POST_PMU: \
539 twl4030_write(w->codec, reg, \
540 twl4030_read_reg_cache(w->codec, reg)); \
541 break; \
542 case SND_SOC_DAPM_POST_PMD: \
543 reg_val = twl4030_read_reg_cache(w->codec, reg); \
544 twl4030_i2c_write_u8(TWL4030_MODULE_AUDIO_VOICE, \
545 reg_val & (~mask), \
546 reg); \
547 break; \
548 } \
549 return 0; \
550}
551
552TWL4030_OUTPUT_PGA(earpiece, TWL4030_REG_EAR_CTL, TWL4030_EAR_GAIN);
553TWL4030_OUTPUT_PGA(predrivel, TWL4030_REG_PREDL_CTL, TWL4030_PREDL_GAIN);
554TWL4030_OUTPUT_PGA(predriver, TWL4030_REG_PREDR_CTL, TWL4030_PREDR_GAIN);
555TWL4030_OUTPUT_PGA(carkitl, TWL4030_REG_PRECKL_CTL, TWL4030_PRECKL_GAIN);
556TWL4030_OUTPUT_PGA(carkitr, TWL4030_REG_PRECKR_CTL, TWL4030_PRECKR_GAIN);
557
558static void handsfree_ramp(struct snd_soc_codec *codec, int reg, int ramp)
561{ 559{
562 struct soc_enum *e = (struct soc_enum *)w->kcontrols->private_value;
563 unsigned char hs_ctl; 560 unsigned char hs_ctl;
564 561
565 hs_ctl = twl4030_read_reg_cache(w->codec, e->reg); 562 hs_ctl = twl4030_read_reg_cache(codec, reg);
566 563
567 if (hs_ctl & TWL4030_HF_CTL_REF_EN) { 564 if (ramp) {
565 /* HF ramp-up */
566 hs_ctl |= TWL4030_HF_CTL_REF_EN;
567 twl4030_write(codec, reg, hs_ctl);
568 udelay(10);
568 hs_ctl |= TWL4030_HF_CTL_RAMP_EN; 569 hs_ctl |= TWL4030_HF_CTL_RAMP_EN;
569 twl4030_write(w->codec, e->reg, hs_ctl); 570 twl4030_write(codec, reg, hs_ctl);
571 udelay(40);
570 hs_ctl |= TWL4030_HF_CTL_LOOP_EN; 572 hs_ctl |= TWL4030_HF_CTL_LOOP_EN;
571 twl4030_write(w->codec, e->reg, hs_ctl);
572 hs_ctl |= TWL4030_HF_CTL_HB_EN; 573 hs_ctl |= TWL4030_HF_CTL_HB_EN;
573 twl4030_write(w->codec, e->reg, hs_ctl); 574 twl4030_write(codec, reg, hs_ctl);
574 } else { 575 } else {
575 hs_ctl &= ~(TWL4030_HF_CTL_RAMP_EN | TWL4030_HF_CTL_LOOP_EN 576 /* HF ramp-down */
576 | TWL4030_HF_CTL_HB_EN); 577 hs_ctl &= ~TWL4030_HF_CTL_LOOP_EN;
577 twl4030_write(w->codec, e->reg, hs_ctl); 578 hs_ctl &= ~TWL4030_HF_CTL_HB_EN;
579 twl4030_write(codec, reg, hs_ctl);
580 hs_ctl &= ~TWL4030_HF_CTL_RAMP_EN;
581 twl4030_write(codec, reg, hs_ctl);
582 udelay(40);
583 hs_ctl &= ~TWL4030_HF_CTL_REF_EN;
584 twl4030_write(codec, reg, hs_ctl);
578 } 585 }
586}
579 587
588static int handsfreelpga_event(struct snd_soc_dapm_widget *w,
589 struct snd_kcontrol *kcontrol, int event)
590{
591 switch (event) {
592 case SND_SOC_DAPM_POST_PMU:
593 handsfree_ramp(w->codec, TWL4030_REG_HFL_CTL, 1);
594 break;
595 case SND_SOC_DAPM_POST_PMD:
596 handsfree_ramp(w->codec, TWL4030_REG_HFL_CTL, 0);
597 break;
598 }
580 return 0; 599 return 0;
581} 600}
582 601
583static int headsetl_event(struct snd_soc_dapm_widget *w, 602static int handsfreerpga_event(struct snd_soc_dapm_widget *w,
584 struct snd_kcontrol *kcontrol, int event) 603 struct snd_kcontrol *kcontrol, int event)
585{ 604{
586 unsigned char hs_gain, hs_pop;
587
588 /* Save the current volume */
589 hs_gain = twl4030_read_reg_cache(w->codec, TWL4030_REG_HS_GAIN_SET);
590 hs_pop = twl4030_read_reg_cache(w->codec, TWL4030_REG_HS_POPN_SET);
591
592 switch (event) { 605 switch (event) {
593 case SND_SOC_DAPM_POST_PMU: 606 case SND_SOC_DAPM_POST_PMU:
594 /* Do the anti-pop/bias ramp enable according to the TRM */ 607 handsfree_ramp(w->codec, TWL4030_REG_HFR_CTL, 1);
595 hs_pop |= TWL4030_VMID_EN;
596 twl4030_write(w->codec, TWL4030_REG_HS_POPN_SET, hs_pop);
597 /* Is this needed? Can we just use whatever gain here? */
598 twl4030_write(w->codec, TWL4030_REG_HS_GAIN_SET,
599 (hs_gain & (~0x0f)) | 0x0a);
600 hs_pop |= TWL4030_RAMP_EN;
601 twl4030_write(w->codec, TWL4030_REG_HS_POPN_SET, hs_pop);
602
603 /* Restore the original volume */
604 twl4030_write(w->codec, TWL4030_REG_HS_GAIN_SET, hs_gain);
605 break; 608 break;
606 case SND_SOC_DAPM_POST_PMD: 609 case SND_SOC_DAPM_POST_PMD:
607 /* Do the anti-pop/bias ramp disable according to the TRM */ 610 handsfree_ramp(w->codec, TWL4030_REG_HFR_CTL, 0);
611 break;
612 }
613 return 0;
614}
615
616static void headset_ramp(struct snd_soc_codec *codec, int ramp)
617{
618 struct snd_soc_device *socdev = codec->socdev;
619 struct twl4030_setup_data *setup = socdev->codec_data;
620
621 unsigned char hs_gain, hs_pop;
622 struct twl4030_priv *twl4030 = codec->private_data;
623 /* Base values for ramp delay calculation: 2^19 - 2^26 */
624 unsigned int ramp_base[] = {524288, 1048576, 2097152, 4194304,
625 8388608, 16777216, 33554432, 67108864};
626
627 hs_gain = twl4030_read_reg_cache(codec, TWL4030_REG_HS_GAIN_SET);
628 hs_pop = twl4030_read_reg_cache(codec, TWL4030_REG_HS_POPN_SET);
629
630 /* Enable external mute control, this dramatically reduces
631 * the pop-noise */
632 if (setup && setup->hs_extmute) {
633 if (setup->set_hs_extmute) {
634 setup->set_hs_extmute(1);
635 } else {
636 hs_pop |= TWL4030_EXTMUTE;
637 twl4030_write(codec, TWL4030_REG_HS_POPN_SET, hs_pop);
638 }
639 }
640
641 if (ramp) {
642 /* Headset ramp-up according to the TRM */
643 hs_pop |= TWL4030_VMID_EN;
644 twl4030_write(codec, TWL4030_REG_HS_POPN_SET, hs_pop);
645 twl4030_write(codec, TWL4030_REG_HS_GAIN_SET, hs_gain);
646 hs_pop |= TWL4030_RAMP_EN;
647 twl4030_write(codec, TWL4030_REG_HS_POPN_SET, hs_pop);
648 /* Wait ramp delay time + 1, so the VMID can settle */
649 mdelay((ramp_base[(hs_pop & TWL4030_RAMP_DELAY) >> 2] /
650 twl4030->sysclk) + 1);
651 } else {
652 /* Headset ramp-down _not_ according to
653 * the TRM, but in a way that it is working */
608 hs_pop &= ~TWL4030_RAMP_EN; 654 hs_pop &= ~TWL4030_RAMP_EN;
609 twl4030_write(w->codec, TWL4030_REG_HS_POPN_SET, hs_pop); 655 twl4030_write(codec, TWL4030_REG_HS_POPN_SET, hs_pop);
656 /* Wait ramp delay time + 1, so the VMID can settle */
657 mdelay((ramp_base[(hs_pop & TWL4030_RAMP_DELAY) >> 2] /
658 twl4030->sysclk) + 1);
610 /* Bypass the reg_cache to mute the headset */ 659 /* Bypass the reg_cache to mute the headset */
611 twl4030_i2c_write_u8(TWL4030_MODULE_AUDIO_VOICE, 660 twl4030_i2c_write_u8(TWL4030_MODULE_AUDIO_VOICE,
612 hs_gain & (~0x0f), 661 hs_gain & (~0x0f),
613 TWL4030_REG_HS_GAIN_SET); 662 TWL4030_REG_HS_GAIN_SET);
663
614 hs_pop &= ~TWL4030_VMID_EN; 664 hs_pop &= ~TWL4030_VMID_EN;
615 twl4030_write(w->codec, TWL4030_REG_HS_POPN_SET, hs_pop); 665 twl4030_write(codec, TWL4030_REG_HS_POPN_SET, hs_pop);
666 }
667
668 /* Disable external mute */
669 if (setup && setup->hs_extmute) {
670 if (setup->set_hs_extmute) {
671 setup->set_hs_extmute(0);
672 } else {
673 hs_pop &= ~TWL4030_EXTMUTE;
674 twl4030_write(codec, TWL4030_REG_HS_POPN_SET, hs_pop);
675 }
676 }
677}
678
679static int headsetlpga_event(struct snd_soc_dapm_widget *w,
680 struct snd_kcontrol *kcontrol, int event)
681{
682 struct twl4030_priv *twl4030 = w->codec->private_data;
683
684 switch (event) {
685 case SND_SOC_DAPM_POST_PMU:
686 /* Do the ramp-up only once */
687 if (!twl4030->hsr_enabled)
688 headset_ramp(w->codec, 1);
689
690 twl4030->hsl_enabled = 1;
691 break;
692 case SND_SOC_DAPM_POST_PMD:
693 /* Do the ramp-down only if both headsetL/R is disabled */
694 if (!twl4030->hsr_enabled)
695 headset_ramp(w->codec, 0);
696
697 twl4030->hsl_enabled = 0;
698 break;
699 }
700 return 0;
701}
702
703static int headsetrpga_event(struct snd_soc_dapm_widget *w,
704 struct snd_kcontrol *kcontrol, int event)
705{
706 struct twl4030_priv *twl4030 = w->codec->private_data;
707
708 switch (event) {
709 case SND_SOC_DAPM_POST_PMU:
710 /* Do the ramp-up only once */
711 if (!twl4030->hsl_enabled)
712 headset_ramp(w->codec, 1);
713
714 twl4030->hsr_enabled = 1;
715 break;
716 case SND_SOC_DAPM_POST_PMD:
717 /* Do the ramp-down only if both headsetL/R is disabled */
718 if (!twl4030->hsl_enabled)
719 headset_ramp(w->codec, 0);
720
721 twl4030->hsr_enabled = 0;
616 break; 722 break;
617 } 723 }
618 return 0; 724 return 0;
@@ -624,11 +730,23 @@ static int bypass_event(struct snd_soc_dapm_widget *w,
624 struct soc_mixer_control *m = 730 struct soc_mixer_control *m =
625 (struct soc_mixer_control *)w->kcontrols->private_value; 731 (struct soc_mixer_control *)w->kcontrols->private_value;
626 struct twl4030_priv *twl4030 = w->codec->private_data; 732 struct twl4030_priv *twl4030 = w->codec->private_data;
627 unsigned char reg; 733 unsigned char reg, misc;
628 734
629 reg = twl4030_read_reg_cache(w->codec, m->reg); 735 reg = twl4030_read_reg_cache(w->codec, m->reg);
630 736
631 if (m->reg <= TWL4030_REG_ARXR2_APGA_CTL) { 737 /*
738 * bypass_state[0:3] - analog HiFi bypass
739 * bypass_state[4] - analog voice bypass
740 * bypass_state[5] - digital voice bypass
741 * bypass_state[6:7] - digital HiFi bypass
742 */
743 if (m->reg == TWL4030_REG_VSTPGA) {
744 /* Voice digital bypass */
745 if (reg)
746 twl4030->bypass_state |= (1 << 5);
747 else
748 twl4030->bypass_state &= ~(1 << 5);
749 } else if (m->reg <= TWL4030_REG_ARXR2_APGA_CTL) {
632 /* Analog bypass */ 750 /* Analog bypass */
633 if (reg & (1 << m->shift)) 751 if (reg & (1 << m->shift))
634 twl4030->bypass_state |= 752 twl4030->bypass_state |=
@@ -636,14 +754,28 @@ static int bypass_event(struct snd_soc_dapm_widget *w,
636 else 754 else
637 twl4030->bypass_state &= 755 twl4030->bypass_state &=
638 ~(1 << (m->reg - TWL4030_REG_ARXL1_APGA_CTL)); 756 ~(1 << (m->reg - TWL4030_REG_ARXL1_APGA_CTL));
757 } else if (m->reg == TWL4030_REG_VDL_APGA_CTL) {
758 /* Analog voice bypass */
759 if (reg & (1 << m->shift))
760 twl4030->bypass_state |= (1 << 4);
761 else
762 twl4030->bypass_state &= ~(1 << 4);
639 } else { 763 } else {
640 /* Digital bypass */ 764 /* Digital bypass */
641 if (reg & (0x7 << m->shift)) 765 if (reg & (0x7 << m->shift))
642 twl4030->bypass_state |= (1 << (m->shift ? 5 : 4)); 766 twl4030->bypass_state |= (1 << (m->shift ? 7 : 6));
643 else 767 else
644 twl4030->bypass_state &= ~(1 << (m->shift ? 5 : 4)); 768 twl4030->bypass_state &= ~(1 << (m->shift ? 7 : 6));
645 } 769 }
646 770
771 /* Enable master analog loopback mode if any analog switch is enabled*/
772 misc = twl4030_read_reg_cache(w->codec, TWL4030_REG_MISC_SET_1);
773 if (twl4030->bypass_state & 0x1F)
774 misc |= TWL4030_FMLOOP_EN;
775 else
776 misc &= ~TWL4030_FMLOOP_EN;
777 twl4030_write(w->codec, TWL4030_REG_MISC_SET_1, misc);
778
647 if (w->codec->bias_level == SND_SOC_BIAS_STANDBY) { 779 if (w->codec->bias_level == SND_SOC_BIAS_STANDBY) {
648 if (twl4030->bypass_state) 780 if (twl4030->bypass_state)
649 twl4030_codec_mute(w->codec, 0); 781 twl4030_codec_mute(w->codec, 0);
@@ -810,6 +942,48 @@ static int snd_soc_put_volsw_r2_twl4030(struct snd_kcontrol *kcontrol,
810 return err; 942 return err;
811} 943}
812 944
945/* Codec operation modes */
946static const char *twl4030_op_modes_texts[] = {
947 "Option 2 (voice/audio)", "Option 1 (audio)"
948};
949
950static const struct soc_enum twl4030_op_modes_enum =
951 SOC_ENUM_SINGLE(TWL4030_REG_CODEC_MODE, 0,
952 ARRAY_SIZE(twl4030_op_modes_texts),
953 twl4030_op_modes_texts);
954
955static int snd_soc_put_twl4030_opmode_enum_double(struct snd_kcontrol *kcontrol,
956 struct snd_ctl_elem_value *ucontrol)
957{
958 struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
959 struct twl4030_priv *twl4030 = codec->private_data;
960 struct soc_enum *e = (struct soc_enum *)kcontrol->private_value;
961 unsigned short val;
962 unsigned short mask, bitmask;
963
964 if (twl4030->configured) {
965 printk(KERN_ERR "twl4030 operation mode cannot be "
966 "changed on-the-fly\n");
967 return -EBUSY;
968 }
969
970 for (bitmask = 1; bitmask < e->max; bitmask <<= 1)
971 ;
972 if (ucontrol->value.enumerated.item[0] > e->max - 1)
973 return -EINVAL;
974
975 val = ucontrol->value.enumerated.item[0] << e->shift_l;
976 mask = (bitmask - 1) << e->shift_l;
977 if (e->shift_l != e->shift_r) {
978 if (ucontrol->value.enumerated.item[1] > e->max - 1)
979 return -EINVAL;
980 val |= ucontrol->value.enumerated.item[1] << e->shift_r;
981 mask |= (bitmask - 1) << e->shift_r;
982 }
983
984 return snd_soc_update_bits(codec, e->reg, mask, val);
985}
986
813/* 987/*
814 * FGAIN volume control: 988 * FGAIN volume control:
815 * from -62 to 0 dB in 1 dB steps (mute instead of -63 dB) 989 * from -62 to 0 dB in 1 dB steps (mute instead of -63 dB)
@@ -824,6 +998,12 @@ static DECLARE_TLV_DB_SCALE(digital_fine_tlv, -6300, 100, 1);
824static DECLARE_TLV_DB_SCALE(digital_coarse_tlv, 0, 600, 0); 998static DECLARE_TLV_DB_SCALE(digital_coarse_tlv, 0, 600, 0);
825 999
826/* 1000/*
1001 * Voice Downlink GAIN volume control:
1002 * from -37 to 12 dB in 1 dB steps (mute instead of -37 dB)
1003 */
1004static DECLARE_TLV_DB_SCALE(digital_voice_downlink_tlv, -3700, 100, 1);
1005
1006/*
827 * Analog playback gain 1007 * Analog playback gain
828 * -24 dB to 12 dB in 2 dB steps 1008 * -24 dB to 12 dB in 2 dB steps
829 */ 1009 */
@@ -853,6 +1033,16 @@ static DECLARE_TLV_DB_SCALE(digital_capture_tlv, 0, 100, 0);
853 */ 1033 */
854static DECLARE_TLV_DB_SCALE(input_gain_tlv, 0, 600, 0); 1034static DECLARE_TLV_DB_SCALE(input_gain_tlv, 0, 600, 0);
855 1035
1036/* AVADC clock priority */
1037static const char *twl4030_avadc_clk_priority_texts[] = {
1038 "Voice high priority", "HiFi high priority"
1039};
1040
1041static const struct soc_enum twl4030_avadc_clk_priority_enum =
1042 SOC_ENUM_SINGLE(TWL4030_REG_AVADC_CTL, 2,
1043 ARRAY_SIZE(twl4030_avadc_clk_priority_texts),
1044 twl4030_avadc_clk_priority_texts);
1045
856static const char *twl4030_rampdelay_texts[] = { 1046static const char *twl4030_rampdelay_texts[] = {
857 "27/20/14 ms", "55/40/27 ms", "109/81/55 ms", "218/161/109 ms", 1047 "27/20/14 ms", "55/40/27 ms", "109/81/55 ms", "218/161/109 ms",
858 "437/323/218 ms", "874/645/437 ms", "1748/1291/874 ms", 1048 "437/323/218 ms", "874/645/437 ms", "1748/1291/874 ms",
@@ -864,7 +1054,32 @@ static const struct soc_enum twl4030_rampdelay_enum =
864 ARRAY_SIZE(twl4030_rampdelay_texts), 1054 ARRAY_SIZE(twl4030_rampdelay_texts),
865 twl4030_rampdelay_texts); 1055 twl4030_rampdelay_texts);
866 1056
1057/* Vibra H-bridge direction mode */
1058static const char *twl4030_vibradirmode_texts[] = {
1059 "Vibra H-bridge direction", "Audio data MSB",
1060};
1061
1062static const struct soc_enum twl4030_vibradirmode_enum =
1063 SOC_ENUM_SINGLE(TWL4030_REG_VIBRA_CTL, 5,
1064 ARRAY_SIZE(twl4030_vibradirmode_texts),
1065 twl4030_vibradirmode_texts);
1066
1067/* Vibra H-bridge direction */
1068static const char *twl4030_vibradir_texts[] = {
1069 "Positive polarity", "Negative polarity",
1070};
1071
1072static const struct soc_enum twl4030_vibradir_enum =
1073 SOC_ENUM_SINGLE(TWL4030_REG_VIBRA_CTL, 1,
1074 ARRAY_SIZE(twl4030_vibradir_texts),
1075 twl4030_vibradir_texts);
1076
867static const struct snd_kcontrol_new twl4030_snd_controls[] = { 1077static const struct snd_kcontrol_new twl4030_snd_controls[] = {
1078 /* Codec operation mode control */
1079 SOC_ENUM_EXT("Codec Operation Mode", twl4030_op_modes_enum,
1080 snd_soc_get_enum_double,
1081 snd_soc_put_twl4030_opmode_enum_double),
1082
868 /* Common playback gain controls */ 1083 /* Common playback gain controls */
869 SOC_DOUBLE_R_TLV("DAC1 Digital Fine Playback Volume", 1084 SOC_DOUBLE_R_TLV("DAC1 Digital Fine Playback Volume",
870 TWL4030_REG_ARXL1PGA, TWL4030_REG_ARXR1PGA, 1085 TWL4030_REG_ARXL1PGA, TWL4030_REG_ARXR1PGA,
@@ -893,6 +1108,16 @@ static const struct snd_kcontrol_new twl4030_snd_controls[] = {
893 TWL4030_REG_ARXL2_APGA_CTL, TWL4030_REG_ARXR2_APGA_CTL, 1108 TWL4030_REG_ARXL2_APGA_CTL, TWL4030_REG_ARXR2_APGA_CTL,
894 1, 1, 0), 1109 1, 1, 0),
895 1110
1111 /* Common voice downlink gain controls */
1112 SOC_SINGLE_TLV("DAC Voice Digital Downlink Volume",
1113 TWL4030_REG_VRXPGA, 0, 0x31, 0, digital_voice_downlink_tlv),
1114
1115 SOC_SINGLE_TLV("DAC Voice Analog Downlink Volume",
1116 TWL4030_REG_VDL_APGA_CTL, 3, 0x12, 1, analog_tlv),
1117
1118 SOC_SINGLE("DAC Voice Analog Downlink Switch",
1119 TWL4030_REG_VDL_APGA_CTL, 1, 1, 0),
1120
896 /* Separate output gain controls */ 1121 /* Separate output gain controls */
897 SOC_DOUBLE_R_TLV_TWL4030("PreDriv Playback Volume", 1122 SOC_DOUBLE_R_TLV_TWL4030("PreDriv Playback Volume",
898 TWL4030_REG_PREDL_CTL, TWL4030_REG_PREDR_CTL, 1123 TWL4030_REG_PREDL_CTL, TWL4030_REG_PREDR_CTL,
@@ -919,7 +1144,12 @@ static const struct snd_kcontrol_new twl4030_snd_controls[] = {
919 SOC_DOUBLE_TLV("Analog Capture Volume", TWL4030_REG_ANAMIC_GAIN, 1144 SOC_DOUBLE_TLV("Analog Capture Volume", TWL4030_REG_ANAMIC_GAIN,
920 0, 3, 5, 0, input_gain_tlv), 1145 0, 3, 5, 0, input_gain_tlv),
921 1146
1147 SOC_ENUM("AVADC Clock Priority", twl4030_avadc_clk_priority_enum),
1148
922 SOC_ENUM("HS ramp delay", twl4030_rampdelay_enum), 1149 SOC_ENUM("HS ramp delay", twl4030_rampdelay_enum),
1150
1151 SOC_ENUM("Vibra H-bridge mode", twl4030_vibradirmode_enum),
1152 SOC_ENUM("Vibra H-bridge direction", twl4030_vibradir_enum),
923}; 1153};
924 1154
925static const struct snd_soc_dapm_widget twl4030_dapm_widgets[] = { 1155static const struct snd_soc_dapm_widget twl4030_dapm_widgets[] = {
@@ -947,26 +1177,19 @@ static const struct snd_soc_dapm_widget twl4030_dapm_widgets[] = {
947 SND_SOC_DAPM_OUTPUT("CARKITR"), 1177 SND_SOC_DAPM_OUTPUT("CARKITR"),
948 SND_SOC_DAPM_OUTPUT("HFL"), 1178 SND_SOC_DAPM_OUTPUT("HFL"),
949 SND_SOC_DAPM_OUTPUT("HFR"), 1179 SND_SOC_DAPM_OUTPUT("HFR"),
1180 SND_SOC_DAPM_OUTPUT("VIBRA"),
950 1181
951 /* DACs */ 1182 /* DACs */
952 SND_SOC_DAPM_DAC("DAC Right1", "Right Front Playback", 1183 SND_SOC_DAPM_DAC("DAC Right1", "Right Front HiFi Playback",
953 SND_SOC_NOPM, 0, 0), 1184 SND_SOC_NOPM, 0, 0),
954 SND_SOC_DAPM_DAC("DAC Left1", "Left Front Playback", 1185 SND_SOC_DAPM_DAC("DAC Left1", "Left Front HiFi Playback",
955 SND_SOC_NOPM, 0, 0), 1186 SND_SOC_NOPM, 0, 0),
956 SND_SOC_DAPM_DAC("DAC Right2", "Right Rear Playback", 1187 SND_SOC_DAPM_DAC("DAC Right2", "Right Rear HiFi Playback",
957 SND_SOC_NOPM, 0, 0), 1188 SND_SOC_NOPM, 0, 0),
958 SND_SOC_DAPM_DAC("DAC Left2", "Left Rear Playback", 1189 SND_SOC_DAPM_DAC("DAC Left2", "Left Rear HiFi Playback",
1190 SND_SOC_NOPM, 0, 0),
1191 SND_SOC_DAPM_DAC("DAC Voice", "Voice Playback",
959 SND_SOC_NOPM, 0, 0), 1192 SND_SOC_NOPM, 0, 0),
960
961 /* Analog PGAs */
962 SND_SOC_DAPM_PGA("ARXR1_APGA", TWL4030_REG_ARXR1_APGA_CTL,
963 0, 0, NULL, 0),
964 SND_SOC_DAPM_PGA("ARXL1_APGA", TWL4030_REG_ARXL1_APGA_CTL,
965 0, 0, NULL, 0),
966 SND_SOC_DAPM_PGA("ARXR2_APGA", TWL4030_REG_ARXR2_APGA_CTL,
967 0, 0, NULL, 0),
968 SND_SOC_DAPM_PGA("ARXL2_APGA", TWL4030_REG_ARXL2_APGA_CTL,
969 0, 0, NULL, 0),
970 1193
971 /* Analog bypasses */ 1194 /* Analog bypasses */
972 SND_SOC_DAPM_SWITCH_E("Right1 Analog Loopback", SND_SOC_NOPM, 0, 0, 1195 SND_SOC_DAPM_SWITCH_E("Right1 Analog Loopback", SND_SOC_NOPM, 0, 0,
@@ -981,6 +1204,9 @@ static const struct snd_soc_dapm_widget twl4030_dapm_widgets[] = {
981 SND_SOC_DAPM_SWITCH_E("Left2 Analog Loopback", SND_SOC_NOPM, 0, 0, 1204 SND_SOC_DAPM_SWITCH_E("Left2 Analog Loopback", SND_SOC_NOPM, 0, 0,
982 &twl4030_dapm_abypassl2_control, 1205 &twl4030_dapm_abypassl2_control,
983 bypass_event, SND_SOC_DAPM_POST_REG), 1206 bypass_event, SND_SOC_DAPM_POST_REG),
1207 SND_SOC_DAPM_SWITCH_E("Voice Analog Loopback", SND_SOC_NOPM, 0, 0,
1208 &twl4030_dapm_abypassv_control,
1209 bypass_event, SND_SOC_DAPM_POST_REG),
984 1210
985 /* Digital bypasses */ 1211 /* Digital bypasses */
986 SND_SOC_DAPM_SWITCH_E("Left Digital Loopback", SND_SOC_NOPM, 0, 0, 1212 SND_SOC_DAPM_SWITCH_E("Left Digital Loopback", SND_SOC_NOPM, 0, 0,
@@ -989,43 +1215,103 @@ static const struct snd_soc_dapm_widget twl4030_dapm_widgets[] = {
989 SND_SOC_DAPM_SWITCH_E("Right Digital Loopback", SND_SOC_NOPM, 0, 0, 1215 SND_SOC_DAPM_SWITCH_E("Right Digital Loopback", SND_SOC_NOPM, 0, 0,
990 &twl4030_dapm_dbypassr_control, bypass_event, 1216 &twl4030_dapm_dbypassr_control, bypass_event,
991 SND_SOC_DAPM_POST_REG), 1217 SND_SOC_DAPM_POST_REG),
1218 SND_SOC_DAPM_SWITCH_E("Voice Digital Loopback", SND_SOC_NOPM, 0, 0,
1219 &twl4030_dapm_dbypassv_control, bypass_event,
1220 SND_SOC_DAPM_POST_REG),
992 1221
993 SND_SOC_DAPM_MIXER("Analog R1 Playback Mixer", TWL4030_REG_AVDAC_CTL, 1222 /* Digital mixers, power control for the physical DACs */
994 0, 0, NULL, 0), 1223 SND_SOC_DAPM_MIXER("Digital R1 Playback Mixer",
995 SND_SOC_DAPM_MIXER("Analog L1 Playback Mixer", TWL4030_REG_AVDAC_CTL, 1224 TWL4030_REG_AVDAC_CTL, 0, 0, NULL, 0),
996 1, 0, NULL, 0), 1225 SND_SOC_DAPM_MIXER("Digital L1 Playback Mixer",
997 SND_SOC_DAPM_MIXER("Analog R2 Playback Mixer", TWL4030_REG_AVDAC_CTL, 1226 TWL4030_REG_AVDAC_CTL, 1, 0, NULL, 0),
998 2, 0, NULL, 0), 1227 SND_SOC_DAPM_MIXER("Digital R2 Playback Mixer",
999 SND_SOC_DAPM_MIXER("Analog L2 Playback Mixer", TWL4030_REG_AVDAC_CTL, 1228 TWL4030_REG_AVDAC_CTL, 2, 0, NULL, 0),
1000 3, 0, NULL, 0), 1229 SND_SOC_DAPM_MIXER("Digital L2 Playback Mixer",
1001 1230 TWL4030_REG_AVDAC_CTL, 3, 0, NULL, 0),
1002 /* Output MUX controls */ 1231 SND_SOC_DAPM_MIXER("Digital Voice Playback Mixer",
1232 TWL4030_REG_AVDAC_CTL, 4, 0, NULL, 0),
1233
1234 /* Analog mixers, power control for the physical PGAs */
1235 SND_SOC_DAPM_MIXER("Analog R1 Playback Mixer",
1236 TWL4030_REG_ARXR1_APGA_CTL, 0, 0, NULL, 0),
1237 SND_SOC_DAPM_MIXER("Analog L1 Playback Mixer",
1238 TWL4030_REG_ARXL1_APGA_CTL, 0, 0, NULL, 0),
1239 SND_SOC_DAPM_MIXER("Analog R2 Playback Mixer",
1240 TWL4030_REG_ARXR2_APGA_CTL, 0, 0, NULL, 0),
1241 SND_SOC_DAPM_MIXER("Analog L2 Playback Mixer",
1242 TWL4030_REG_ARXL2_APGA_CTL, 0, 0, NULL, 0),
1243 SND_SOC_DAPM_MIXER("Analog Voice Playback Mixer",
1244 TWL4030_REG_VDL_APGA_CTL, 0, 0, NULL, 0),
1245
1246 /* Output MIXER controls */
1003 /* Earpiece */ 1247 /* Earpiece */
1004 SND_SOC_DAPM_VALUE_MUX("Earpiece Mux", SND_SOC_NOPM, 0, 0, 1248 SND_SOC_DAPM_MIXER("Earpiece Mixer", SND_SOC_NOPM, 0, 0,
1005 &twl4030_dapm_earpiece_control), 1249 &twl4030_dapm_earpiece_controls[0],
1250 ARRAY_SIZE(twl4030_dapm_earpiece_controls)),
1251 SND_SOC_DAPM_PGA_E("Earpiece PGA", SND_SOC_NOPM,
1252 0, 0, NULL, 0, earpiecepga_event,
1253 SND_SOC_DAPM_POST_PMU|SND_SOC_DAPM_POST_PMD),
1006 /* PreDrivL/R */ 1254 /* PreDrivL/R */
1007 SND_SOC_DAPM_VALUE_MUX("PredriveL Mux", SND_SOC_NOPM, 0, 0, 1255 SND_SOC_DAPM_MIXER("PredriveL Mixer", SND_SOC_NOPM, 0, 0,
1008 &twl4030_dapm_predrivel_control), 1256 &twl4030_dapm_predrivel_controls[0],
1009 SND_SOC_DAPM_VALUE_MUX("PredriveR Mux", SND_SOC_NOPM, 0, 0, 1257 ARRAY_SIZE(twl4030_dapm_predrivel_controls)),
1010 &twl4030_dapm_predriver_control), 1258 SND_SOC_DAPM_PGA_E("PredriveL PGA", SND_SOC_NOPM,
1259 0, 0, NULL, 0, predrivelpga_event,
1260 SND_SOC_DAPM_POST_PMU|SND_SOC_DAPM_POST_PMD),
1261 SND_SOC_DAPM_MIXER("PredriveR Mixer", SND_SOC_NOPM, 0, 0,
1262 &twl4030_dapm_predriver_controls[0],
1263 ARRAY_SIZE(twl4030_dapm_predriver_controls)),
1264 SND_SOC_DAPM_PGA_E("PredriveR PGA", SND_SOC_NOPM,
1265 0, 0, NULL, 0, predriverpga_event,
1266 SND_SOC_DAPM_POST_PMU|SND_SOC_DAPM_POST_PMD),
1011 /* HeadsetL/R */ 1267 /* HeadsetL/R */
1012 SND_SOC_DAPM_MUX_E("HeadsetL Mux", SND_SOC_NOPM, 0, 0, 1268 SND_SOC_DAPM_MIXER("HeadsetL Mixer", SND_SOC_NOPM, 0, 0,
1013 &twl4030_dapm_hsol_control, headsetl_event, 1269 &twl4030_dapm_hsol_controls[0],
1014 SND_SOC_DAPM_POST_PMU|SND_SOC_DAPM_POST_PMD), 1270 ARRAY_SIZE(twl4030_dapm_hsol_controls)),
1015 SND_SOC_DAPM_MUX("HeadsetR Mux", SND_SOC_NOPM, 0, 0, 1271 SND_SOC_DAPM_PGA_E("HeadsetL PGA", SND_SOC_NOPM,
1016 &twl4030_dapm_hsor_control), 1272 0, 0, NULL, 0, headsetlpga_event,
1273 SND_SOC_DAPM_POST_PMU|SND_SOC_DAPM_POST_PMD),
1274 SND_SOC_DAPM_MIXER("HeadsetR Mixer", SND_SOC_NOPM, 0, 0,
1275 &twl4030_dapm_hsor_controls[0],
1276 ARRAY_SIZE(twl4030_dapm_hsor_controls)),
1277 SND_SOC_DAPM_PGA_E("HeadsetR PGA", SND_SOC_NOPM,
1278 0, 0, NULL, 0, headsetrpga_event,
1279 SND_SOC_DAPM_POST_PMU|SND_SOC_DAPM_POST_PMD),
1017 /* CarkitL/R */ 1280 /* CarkitL/R */
1018 SND_SOC_DAPM_MUX("CarkitL Mux", SND_SOC_NOPM, 0, 0, 1281 SND_SOC_DAPM_MIXER("CarkitL Mixer", SND_SOC_NOPM, 0, 0,
1019 &twl4030_dapm_carkitl_control), 1282 &twl4030_dapm_carkitl_controls[0],
1020 SND_SOC_DAPM_MUX("CarkitR Mux", SND_SOC_NOPM, 0, 0, 1283 ARRAY_SIZE(twl4030_dapm_carkitl_controls)),
1021 &twl4030_dapm_carkitr_control), 1284 SND_SOC_DAPM_PGA_E("CarkitL PGA", SND_SOC_NOPM,
1285 0, 0, NULL, 0, carkitlpga_event,
1286 SND_SOC_DAPM_POST_PMU|SND_SOC_DAPM_POST_PMD),
1287 SND_SOC_DAPM_MIXER("CarkitR Mixer", SND_SOC_NOPM, 0, 0,
1288 &twl4030_dapm_carkitr_controls[0],
1289 ARRAY_SIZE(twl4030_dapm_carkitr_controls)),
1290 SND_SOC_DAPM_PGA_E("CarkitR PGA", SND_SOC_NOPM,
1291 0, 0, NULL, 0, carkitrpga_event,
1292 SND_SOC_DAPM_POST_PMU|SND_SOC_DAPM_POST_PMD),
1293
1294 /* Output MUX controls */
1022 /* HandsfreeL/R */ 1295 /* HandsfreeL/R */
1023 SND_SOC_DAPM_MUX_E("HandsfreeL Mux", TWL4030_REG_HFL_CTL, 5, 0, 1296 SND_SOC_DAPM_MUX("HandsfreeL Mux", SND_SOC_NOPM, 0, 0,
1024 &twl4030_dapm_handsfreel_control, handsfree_event, 1297 &twl4030_dapm_handsfreel_control),
1025 SND_SOC_DAPM_POST_PMU|SND_SOC_DAPM_POST_PMD), 1298 SND_SOC_DAPM_SWITCH("HandsfreeL", SND_SOC_NOPM, 0, 0,
1026 SND_SOC_DAPM_MUX_E("HandsfreeR Mux", TWL4030_REG_HFR_CTL, 5, 0, 1299 &twl4030_dapm_handsfreelmute_control),
1027 &twl4030_dapm_handsfreer_control, handsfree_event, 1300 SND_SOC_DAPM_PGA_E("HandsfreeL PGA", SND_SOC_NOPM,
1028 SND_SOC_DAPM_POST_PMU|SND_SOC_DAPM_POST_PMD), 1301 0, 0, NULL, 0, handsfreelpga_event,
1302 SND_SOC_DAPM_POST_PMU|SND_SOC_DAPM_POST_PMD),
1303 SND_SOC_DAPM_MUX("HandsfreeR Mux", SND_SOC_NOPM, 5, 0,
1304 &twl4030_dapm_handsfreer_control),
1305 SND_SOC_DAPM_SWITCH("HandsfreeR", SND_SOC_NOPM, 0, 0,
1306 &twl4030_dapm_handsfreermute_control),
1307 SND_SOC_DAPM_PGA_E("HandsfreeR PGA", SND_SOC_NOPM,
1308 0, 0, NULL, 0, handsfreerpga_event,
1309 SND_SOC_DAPM_POST_PMU|SND_SOC_DAPM_POST_PMD),
1310 /* Vibra */
1311 SND_SOC_DAPM_MUX("Vibra Mux", TWL4030_REG_VIBRA_CTL, 0, 0,
1312 &twl4030_dapm_vibra_control),
1313 SND_SOC_DAPM_MUX("Vibra Route", SND_SOC_NOPM, 0, 0,
1314 &twl4030_dapm_vibrapath_control),
1029 1315
1030 /* Introducing four virtual ADC, since TWL4030 have four channel for 1316 /* Introducing four virtual ADC, since TWL4030 have four channel for
1031 capture */ 1317 capture */
@@ -1050,11 +1336,15 @@ static const struct snd_soc_dapm_widget twl4030_dapm_widgets[] = {
1050 SND_SOC_DAPM_POST_PMU|SND_SOC_DAPM_POST_PMD| 1336 SND_SOC_DAPM_POST_PMU|SND_SOC_DAPM_POST_PMD|
1051 SND_SOC_DAPM_POST_REG), 1337 SND_SOC_DAPM_POST_REG),
1052 1338
1053 /* Analog input muxes with switch for the capture amplifiers */ 1339 /* Analog input mixers for the capture amplifiers */
1054 SND_SOC_DAPM_VALUE_MUX("Analog Left Capture Route", 1340 SND_SOC_DAPM_MIXER("Analog Left",
1055 TWL4030_REG_ANAMICL, 4, 0, &twl4030_dapm_analoglmic_control), 1341 TWL4030_REG_ANAMICL, 4, 0,
1056 SND_SOC_DAPM_VALUE_MUX("Analog Right Capture Route", 1342 &twl4030_dapm_analoglmic_controls[0],
1057 TWL4030_REG_ANAMICR, 4, 0, &twl4030_dapm_analogrmic_control), 1343 ARRAY_SIZE(twl4030_dapm_analoglmic_controls)),
1344 SND_SOC_DAPM_MIXER("Analog Right",
1345 TWL4030_REG_ANAMICR, 4, 0,
1346 &twl4030_dapm_analogrmic_controls[0],
1347 ARRAY_SIZE(twl4030_dapm_analogrmic_controls)),
1058 1348
1059 SND_SOC_DAPM_PGA("ADC Physical Left", 1349 SND_SOC_DAPM_PGA("ADC Physical Left",
1060 TWL4030_REG_AVADC_CTL, 3, 0, NULL, 0), 1350 TWL4030_REG_AVADC_CTL, 3, 0, NULL, 0),
@@ -1073,74 +1363,103 @@ static const struct snd_soc_dapm_widget twl4030_dapm_widgets[] = {
1073}; 1363};
1074 1364
1075static const struct snd_soc_dapm_route intercon[] = { 1365static const struct snd_soc_dapm_route intercon[] = {
1076 {"Analog L1 Playback Mixer", NULL, "DAC Left1"}, 1366 {"Digital L1 Playback Mixer", NULL, "DAC Left1"},
1077 {"Analog R1 Playback Mixer", NULL, "DAC Right1"}, 1367 {"Digital R1 Playback Mixer", NULL, "DAC Right1"},
1078 {"Analog L2 Playback Mixer", NULL, "DAC Left2"}, 1368 {"Digital L2 Playback Mixer", NULL, "DAC Left2"},
1079 {"Analog R2 Playback Mixer", NULL, "DAC Right2"}, 1369 {"Digital R2 Playback Mixer", NULL, "DAC Right2"},
1080 1370 {"Digital Voice Playback Mixer", NULL, "DAC Voice"},
1081 {"ARXL1_APGA", NULL, "Analog L1 Playback Mixer"}, 1371
1082 {"ARXR1_APGA", NULL, "Analog R1 Playback Mixer"}, 1372 {"Analog L1 Playback Mixer", NULL, "Digital L1 Playback Mixer"},
1083 {"ARXL2_APGA", NULL, "Analog L2 Playback Mixer"}, 1373 {"Analog R1 Playback Mixer", NULL, "Digital R1 Playback Mixer"},
1084 {"ARXR2_APGA", NULL, "Analog R2 Playback Mixer"}, 1374 {"Analog L2 Playback Mixer", NULL, "Digital L2 Playback Mixer"},
1375 {"Analog R2 Playback Mixer", NULL, "Digital R2 Playback Mixer"},
1376 {"Analog Voice Playback Mixer", NULL, "Digital Voice Playback Mixer"},
1085 1377
1086 /* Internal playback routings */ 1378 /* Internal playback routings */
1087 /* Earpiece */ 1379 /* Earpiece */
1088 {"Earpiece Mux", "DACL1", "ARXL1_APGA"}, 1380 {"Earpiece Mixer", "Voice", "Analog Voice Playback Mixer"},
1089 {"Earpiece Mux", "DACL2", "ARXL2_APGA"}, 1381 {"Earpiece Mixer", "AudioL1", "Analog L1 Playback Mixer"},
1090 {"Earpiece Mux", "DACR1", "ARXR1_APGA"}, 1382 {"Earpiece Mixer", "AudioL2", "Analog L2 Playback Mixer"},
1383 {"Earpiece Mixer", "AudioR1", "Analog R1 Playback Mixer"},
1384 {"Earpiece PGA", NULL, "Earpiece Mixer"},
1091 /* PreDrivL */ 1385 /* PreDrivL */
1092 {"PredriveL Mux", "DACL1", "ARXL1_APGA"}, 1386 {"PredriveL Mixer", "Voice", "Analog Voice Playback Mixer"},
1093 {"PredriveL Mux", "DACL2", "ARXL2_APGA"}, 1387 {"PredriveL Mixer", "AudioL1", "Analog L1 Playback Mixer"},
1094 {"PredriveL Mux", "DACR2", "ARXR2_APGA"}, 1388 {"PredriveL Mixer", "AudioL2", "Analog L2 Playback Mixer"},
1389 {"PredriveL Mixer", "AudioR2", "Analog R2 Playback Mixer"},
1390 {"PredriveL PGA", NULL, "PredriveL Mixer"},
1095 /* PreDrivR */ 1391 /* PreDrivR */
1096 {"PredriveR Mux", "DACR1", "ARXR1_APGA"}, 1392 {"PredriveR Mixer", "Voice", "Analog Voice Playback Mixer"},
1097 {"PredriveR Mux", "DACR2", "ARXR2_APGA"}, 1393 {"PredriveR Mixer", "AudioR1", "Analog R1 Playback Mixer"},
1098 {"PredriveR Mux", "DACL2", "ARXL2_APGA"}, 1394 {"PredriveR Mixer", "AudioR2", "Analog R2 Playback Mixer"},
1395 {"PredriveR Mixer", "AudioL2", "Analog L2 Playback Mixer"},
1396 {"PredriveR PGA", NULL, "PredriveR Mixer"},
1099 /* HeadsetL */ 1397 /* HeadsetL */
1100 {"HeadsetL Mux", "DACL1", "ARXL1_APGA"}, 1398 {"HeadsetL Mixer", "Voice", "Analog Voice Playback Mixer"},
1101 {"HeadsetL Mux", "DACL2", "ARXL2_APGA"}, 1399 {"HeadsetL Mixer", "AudioL1", "Analog L1 Playback Mixer"},
1400 {"HeadsetL Mixer", "AudioL2", "Analog L2 Playback Mixer"},
1401 {"HeadsetL PGA", NULL, "HeadsetL Mixer"},
1102 /* HeadsetR */ 1402 /* HeadsetR */
1103 {"HeadsetR Mux", "DACR1", "ARXR1_APGA"}, 1403 {"HeadsetR Mixer", "Voice", "Analog Voice Playback Mixer"},
1104 {"HeadsetR Mux", "DACR2", "ARXR2_APGA"}, 1404 {"HeadsetR Mixer", "AudioR1", "Analog R1 Playback Mixer"},
1405 {"HeadsetR Mixer", "AudioR2", "Analog R2 Playback Mixer"},
1406 {"HeadsetR PGA", NULL, "HeadsetR Mixer"},
1105 /* CarkitL */ 1407 /* CarkitL */
1106 {"CarkitL Mux", "DACL1", "ARXL1_APGA"}, 1408 {"CarkitL Mixer", "Voice", "Analog Voice Playback Mixer"},
1107 {"CarkitL Mux", "DACL2", "ARXL2_APGA"}, 1409 {"CarkitL Mixer", "AudioL1", "Analog L1 Playback Mixer"},
1410 {"CarkitL Mixer", "AudioL2", "Analog L2 Playback Mixer"},
1411 {"CarkitL PGA", NULL, "CarkitL Mixer"},
1108 /* CarkitR */ 1412 /* CarkitR */
1109 {"CarkitR Mux", "DACR1", "ARXR1_APGA"}, 1413 {"CarkitR Mixer", "Voice", "Analog Voice Playback Mixer"},
1110 {"CarkitR Mux", "DACR2", "ARXR2_APGA"}, 1414 {"CarkitR Mixer", "AudioR1", "Analog R1 Playback Mixer"},
1415 {"CarkitR Mixer", "AudioR2", "Analog R2 Playback Mixer"},
1416 {"CarkitR PGA", NULL, "CarkitR Mixer"},
1111 /* HandsfreeL */ 1417 /* HandsfreeL */
1112 {"HandsfreeL Mux", "DACL1", "ARXL1_APGA"}, 1418 {"HandsfreeL Mux", "Voice", "Analog Voice Playback Mixer"},
1113 {"HandsfreeL Mux", "DACL2", "ARXL2_APGA"}, 1419 {"HandsfreeL Mux", "AudioL1", "Analog L1 Playback Mixer"},
1114 {"HandsfreeL Mux", "DACR2", "ARXR2_APGA"}, 1420 {"HandsfreeL Mux", "AudioL2", "Analog L2 Playback Mixer"},
1421 {"HandsfreeL Mux", "AudioR2", "Analog R2 Playback Mixer"},
1422 {"HandsfreeL", "Switch", "HandsfreeL Mux"},
1423 {"HandsfreeL PGA", NULL, "HandsfreeL"},
1115 /* HandsfreeR */ 1424 /* HandsfreeR */
1116 {"HandsfreeR Mux", "DACR1", "ARXR1_APGA"}, 1425 {"HandsfreeR Mux", "Voice", "Analog Voice Playback Mixer"},
1117 {"HandsfreeR Mux", "DACR2", "ARXR2_APGA"}, 1426 {"HandsfreeR Mux", "AudioR1", "Analog R1 Playback Mixer"},
1118 {"HandsfreeR Mux", "DACL2", "ARXL2_APGA"}, 1427 {"HandsfreeR Mux", "AudioR2", "Analog R2 Playback Mixer"},
1428 {"HandsfreeR Mux", "AudioL2", "Analog L2 Playback Mixer"},
1429 {"HandsfreeR", "Switch", "HandsfreeR Mux"},
1430 {"HandsfreeR PGA", NULL, "HandsfreeR"},
1431 /* Vibra */
1432 {"Vibra Mux", "AudioL1", "DAC Left1"},
1433 {"Vibra Mux", "AudioR1", "DAC Right1"},
1434 {"Vibra Mux", "AudioL2", "DAC Left2"},
1435 {"Vibra Mux", "AudioR2", "DAC Right2"},
1119 1436
1120 /* outputs */ 1437 /* outputs */
1121 {"OUTL", NULL, "ARXL2_APGA"}, 1438 {"OUTL", NULL, "Analog L2 Playback Mixer"},
1122 {"OUTR", NULL, "ARXR2_APGA"}, 1439 {"OUTR", NULL, "Analog R2 Playback Mixer"},
1123 {"EARPIECE", NULL, "Earpiece Mux"}, 1440 {"EARPIECE", NULL, "Earpiece PGA"},
1124 {"PREDRIVEL", NULL, "PredriveL Mux"}, 1441 {"PREDRIVEL", NULL, "PredriveL PGA"},
1125 {"PREDRIVER", NULL, "PredriveR Mux"}, 1442 {"PREDRIVER", NULL, "PredriveR PGA"},
1126 {"HSOL", NULL, "HeadsetL Mux"}, 1443 {"HSOL", NULL, "HeadsetL PGA"},
1127 {"HSOR", NULL, "HeadsetR Mux"}, 1444 {"HSOR", NULL, "HeadsetR PGA"},
1128 {"CARKITL", NULL, "CarkitL Mux"}, 1445 {"CARKITL", NULL, "CarkitL PGA"},
1129 {"CARKITR", NULL, "CarkitR Mux"}, 1446 {"CARKITR", NULL, "CarkitR PGA"},
1130 {"HFL", NULL, "HandsfreeL Mux"}, 1447 {"HFL", NULL, "HandsfreeL PGA"},
1131 {"HFR", NULL, "HandsfreeR Mux"}, 1448 {"HFR", NULL, "HandsfreeR PGA"},
1449 {"Vibra Route", "Audio", "Vibra Mux"},
1450 {"VIBRA", NULL, "Vibra Route"},
1132 1451
1133 /* Capture path */ 1452 /* Capture path */
1134 {"Analog Left Capture Route", "Main mic", "MAINMIC"}, 1453 {"Analog Left", "Main Mic Capture Switch", "MAINMIC"},
1135 {"Analog Left Capture Route", "Headset mic", "HSMIC"}, 1454 {"Analog Left", "Headset Mic Capture Switch", "HSMIC"},
1136 {"Analog Left Capture Route", "AUXL", "AUXL"}, 1455 {"Analog Left", "AUXL Capture Switch", "AUXL"},
1137 {"Analog Left Capture Route", "Carkit mic", "CARKITMIC"}, 1456 {"Analog Left", "Carkit Mic Capture Switch", "CARKITMIC"},
1138 1457
1139 {"Analog Right Capture Route", "Sub mic", "SUBMIC"}, 1458 {"Analog Right", "Sub Mic Capture Switch", "SUBMIC"},
1140 {"Analog Right Capture Route", "AUXR", "AUXR"}, 1459 {"Analog Right", "AUXR Capture Switch", "AUXR"},
1141 1460
1142 {"ADC Physical Left", NULL, "Analog Left Capture Route"}, 1461 {"ADC Physical Left", NULL, "Analog Left"},
1143 {"ADC Physical Right", NULL, "Analog Right Capture Route"}, 1462 {"ADC Physical Right", NULL, "Analog Right"},
1144 1463
1145 {"Digimic0 Enable", NULL, "DIGIMIC0"}, 1464 {"Digimic0 Enable", NULL, "DIGIMIC0"},
1146 {"Digimic1 Enable", NULL, "DIGIMIC1"}, 1465 {"Digimic1 Enable", NULL, "DIGIMIC1"},
@@ -1164,22 +1483,26 @@ static const struct snd_soc_dapm_route intercon[] = {
1164 {"ADC Virtual Right2", NULL, "TX2 Capture Route"}, 1483 {"ADC Virtual Right2", NULL, "TX2 Capture Route"},
1165 1484
1166 /* Analog bypass routes */ 1485 /* Analog bypass routes */
1167 {"Right1 Analog Loopback", "Switch", "Analog Right Capture Route"}, 1486 {"Right1 Analog Loopback", "Switch", "Analog Right"},
1168 {"Left1 Analog Loopback", "Switch", "Analog Left Capture Route"}, 1487 {"Left1 Analog Loopback", "Switch", "Analog Left"},
1169 {"Right2 Analog Loopback", "Switch", "Analog Right Capture Route"}, 1488 {"Right2 Analog Loopback", "Switch", "Analog Right"},
1170 {"Left2 Analog Loopback", "Switch", "Analog Left Capture Route"}, 1489 {"Left2 Analog Loopback", "Switch", "Analog Left"},
1490 {"Voice Analog Loopback", "Switch", "Analog Left"},
1171 1491
1172 {"Analog R1 Playback Mixer", NULL, "Right1 Analog Loopback"}, 1492 {"Analog R1 Playback Mixer", NULL, "Right1 Analog Loopback"},
1173 {"Analog L1 Playback Mixer", NULL, "Left1 Analog Loopback"}, 1493 {"Analog L1 Playback Mixer", NULL, "Left1 Analog Loopback"},
1174 {"Analog R2 Playback Mixer", NULL, "Right2 Analog Loopback"}, 1494 {"Analog R2 Playback Mixer", NULL, "Right2 Analog Loopback"},
1175 {"Analog L2 Playback Mixer", NULL, "Left2 Analog Loopback"}, 1495 {"Analog L2 Playback Mixer", NULL, "Left2 Analog Loopback"},
1496 {"Analog Voice Playback Mixer", NULL, "Voice Analog Loopback"},
1176 1497
1177 /* Digital bypass routes */ 1498 /* Digital bypass routes */
1178 {"Right Digital Loopback", "Volume", "TX1 Capture Route"}, 1499 {"Right Digital Loopback", "Volume", "TX1 Capture Route"},
1179 {"Left Digital Loopback", "Volume", "TX1 Capture Route"}, 1500 {"Left Digital Loopback", "Volume", "TX1 Capture Route"},
1501 {"Voice Digital Loopback", "Volume", "TX2 Capture Route"},
1180 1502
1181 {"Analog R2 Playback Mixer", NULL, "Right Digital Loopback"}, 1503 {"Digital R2 Playback Mixer", NULL, "Right Digital Loopback"},
1182 {"Analog L2 Playback Mixer", NULL, "Left Digital Loopback"}, 1504 {"Digital L2 Playback Mixer", NULL, "Left Digital Loopback"},
1505 {"Digital Voice Playback Mixer", NULL, "Voice Digital Loopback"},
1183 1506
1184}; 1507};
1185 1508
@@ -1226,6 +1549,58 @@ static int twl4030_set_bias_level(struct snd_soc_codec *codec,
1226 return 0; 1549 return 0;
1227} 1550}
1228 1551
1552static void twl4030_constraints(struct twl4030_priv *twl4030,
1553 struct snd_pcm_substream *mst_substream)
1554{
1555 struct snd_pcm_substream *slv_substream;
1556
1557 /* Pick the stream, which need to be constrained */
1558 if (mst_substream == twl4030->master_substream)
1559 slv_substream = twl4030->slave_substream;
1560 else if (mst_substream == twl4030->slave_substream)
1561 slv_substream = twl4030->master_substream;
1562 else /* This should not happen.. */
1563 return;
1564
1565 /* Set the constraints according to the already configured stream */
1566 snd_pcm_hw_constraint_minmax(slv_substream->runtime,
1567 SNDRV_PCM_HW_PARAM_RATE,
1568 twl4030->rate,
1569 twl4030->rate);
1570
1571 snd_pcm_hw_constraint_minmax(slv_substream->runtime,
1572 SNDRV_PCM_HW_PARAM_SAMPLE_BITS,
1573 twl4030->sample_bits,
1574 twl4030->sample_bits);
1575
1576 snd_pcm_hw_constraint_minmax(slv_substream->runtime,
1577 SNDRV_PCM_HW_PARAM_CHANNELS,
1578 twl4030->channels,
1579 twl4030->channels);
1580}
1581
1582/* In case of 4 channel mode, the RX1 L/R for playback and the TX2 L/R for
1583 * capture has to be enabled/disabled. */
1584static void twl4030_tdm_enable(struct snd_soc_codec *codec, int direction,
1585 int enable)
1586{
1587 u8 reg, mask;
1588
1589 reg = twl4030_read_reg_cache(codec, TWL4030_REG_OPTION);
1590
1591 if (direction == SNDRV_PCM_STREAM_PLAYBACK)
1592 mask = TWL4030_ARXL1_VRX_EN | TWL4030_ARXR1_EN;
1593 else
1594 mask = TWL4030_ATXL2_VTXL_EN | TWL4030_ATXR2_VTXR_EN;
1595
1596 if (enable)
1597 reg |= mask;
1598 else
1599 reg &= ~mask;
1600
1601 twl4030_write(codec, TWL4030_REG_OPTION, reg);
1602}
1603
1229static int twl4030_startup(struct snd_pcm_substream *substream, 1604static int twl4030_startup(struct snd_pcm_substream *substream,
1230 struct snd_soc_dai *dai) 1605 struct snd_soc_dai *dai)
1231{ 1606{
@@ -1234,26 +1609,25 @@ static int twl4030_startup(struct snd_pcm_substream *substream,
1234 struct snd_soc_codec *codec = socdev->card->codec; 1609 struct snd_soc_codec *codec = socdev->card->codec;
1235 struct twl4030_priv *twl4030 = codec->private_data; 1610 struct twl4030_priv *twl4030 = codec->private_data;
1236 1611
1237 /* If we already have a playback or capture going then constrain
1238 * this substream to match it.
1239 */
1240 if (twl4030->master_substream) { 1612 if (twl4030->master_substream) {
1241 struct snd_pcm_runtime *master_runtime;
1242 master_runtime = twl4030->master_substream->runtime;
1243
1244 snd_pcm_hw_constraint_minmax(substream->runtime,
1245 SNDRV_PCM_HW_PARAM_RATE,
1246 master_runtime->rate,
1247 master_runtime->rate);
1248
1249 snd_pcm_hw_constraint_minmax(substream->runtime,
1250 SNDRV_PCM_HW_PARAM_SAMPLE_BITS,
1251 master_runtime->sample_bits,
1252 master_runtime->sample_bits);
1253
1254 twl4030->slave_substream = substream; 1613 twl4030->slave_substream = substream;
1255 } else 1614 /* The DAI has one configuration for playback and capture, so
1615 * if the DAI has been already configured then constrain this
1616 * substream to match it. */
1617 if (twl4030->configured)
1618 twl4030_constraints(twl4030, twl4030->master_substream);
1619 } else {
1620 if (!(twl4030_read_reg_cache(codec, TWL4030_REG_CODEC_MODE) &
1621 TWL4030_OPTION_1)) {
1622 /* In option2 4 channel is not supported, set the
1623 * constraint for the first stream for channels, the
1624 * second stream will 'inherit' this cosntraint */
1625 snd_pcm_hw_constraint_minmax(substream->runtime,
1626 SNDRV_PCM_HW_PARAM_CHANNELS,
1627 2, 2);
1628 }
1256 twl4030->master_substream = substream; 1629 twl4030->master_substream = substream;
1630 }
1257 1631
1258 return 0; 1632 return 0;
1259} 1633}
@@ -1270,6 +1644,17 @@ static void twl4030_shutdown(struct snd_pcm_substream *substream,
1270 twl4030->master_substream = twl4030->slave_substream; 1644 twl4030->master_substream = twl4030->slave_substream;
1271 1645
1272 twl4030->slave_substream = NULL; 1646 twl4030->slave_substream = NULL;
1647
1648 /* If all streams are closed, or the remaining stream has not yet
1649 * been configured than set the DAI as not configured. */
1650 if (!twl4030->master_substream)
1651 twl4030->configured = 0;
1652 else if (!twl4030->master_substream->runtime->channels)
1653 twl4030->configured = 0;
1654
1655 /* If the closing substream had 4 channel, do the necessary cleanup */
1656 if (substream->runtime->channels == 4)
1657 twl4030_tdm_enable(codec, substream->stream, 0);
1273} 1658}
1274 1659
1275static int twl4030_hw_params(struct snd_pcm_substream *substream, 1660static int twl4030_hw_params(struct snd_pcm_substream *substream,
@@ -1282,8 +1667,22 @@ static int twl4030_hw_params(struct snd_pcm_substream *substream,
1282 struct twl4030_priv *twl4030 = codec->private_data; 1667 struct twl4030_priv *twl4030 = codec->private_data;
1283 u8 mode, old_mode, format, old_format; 1668 u8 mode, old_mode, format, old_format;
1284 1669
1285 if (substream == twl4030->slave_substream) 1670 /* If the substream has 4 channel, do the necessary setup */
1286 /* Ignoring hw_params for slave substream */ 1671 if (params_channels(params) == 4) {
1672 format = twl4030_read_reg_cache(codec, TWL4030_REG_AUDIO_IF);
1673 mode = twl4030_read_reg_cache(codec, TWL4030_REG_CODEC_MODE);
1674
1675 /* Safety check: are we in the correct operating mode and
1676 * the interface is in TDM mode? */
1677 if ((mode & TWL4030_OPTION_1) &&
1678 ((format & TWL4030_AIF_FORMAT) == TWL4030_AIF_FORMAT_TDM))
1679 twl4030_tdm_enable(codec, substream->stream, 1);
1680 else
1681 return -EINVAL;
1682 }
1683
1684 if (twl4030->configured)
1685 /* Ignoring hw_params for already configured DAI */
1287 return 0; 1686 return 0;
1288 1687
1289 /* bit rate */ 1688 /* bit rate */
@@ -1363,6 +1762,21 @@ static int twl4030_hw_params(struct snd_pcm_substream *substream,
1363 /* set CODECPDZ afterwards */ 1762 /* set CODECPDZ afterwards */
1364 twl4030_codec_enable(codec, 1); 1763 twl4030_codec_enable(codec, 1);
1365 } 1764 }
1765
1766 /* Store the important parameters for the DAI configuration and set
1767 * the DAI as configured */
1768 twl4030->configured = 1;
1769 twl4030->rate = params_rate(params);
1770 twl4030->sample_bits = hw_param_interval(params,
1771 SNDRV_PCM_HW_PARAM_SAMPLE_BITS)->min;
1772 twl4030->channels = params_channels(params);
1773
1774 /* If both playback and capture streams are open, and one of them
1775 * is setting the hw parameters right now (since we are here), set
1776 * constraints to the other stream to match the current one. */
1777 if (twl4030->slave_substream)
1778 twl4030_constraints(twl4030, substream);
1779
1366 return 0; 1780 return 0;
1367} 1781}
1368 1782
@@ -1370,17 +1784,21 @@ static int twl4030_set_dai_sysclk(struct snd_soc_dai *codec_dai,
1370 int clk_id, unsigned int freq, int dir) 1784 int clk_id, unsigned int freq, int dir)
1371{ 1785{
1372 struct snd_soc_codec *codec = codec_dai->codec; 1786 struct snd_soc_codec *codec = codec_dai->codec;
1787 struct twl4030_priv *twl4030 = codec->private_data;
1373 u8 infreq; 1788 u8 infreq;
1374 1789
1375 switch (freq) { 1790 switch (freq) {
1376 case 19200000: 1791 case 19200000:
1377 infreq = TWL4030_APLL_INFREQ_19200KHZ; 1792 infreq = TWL4030_APLL_INFREQ_19200KHZ;
1793 twl4030->sysclk = 19200;
1378 break; 1794 break;
1379 case 26000000: 1795 case 26000000:
1380 infreq = TWL4030_APLL_INFREQ_26000KHZ; 1796 infreq = TWL4030_APLL_INFREQ_26000KHZ;
1797 twl4030->sysclk = 26000;
1381 break; 1798 break;
1382 case 38400000: 1799 case 38400000:
1383 infreq = TWL4030_APLL_INFREQ_38400KHZ; 1800 infreq = TWL4030_APLL_INFREQ_38400KHZ;
1801 twl4030->sysclk = 38400;
1384 break; 1802 break;
1385 default: 1803 default:
1386 printk(KERN_ERR "TWL4030 set sysclk: unknown rate %d\n", 1804 printk(KERN_ERR "TWL4030 set sysclk: unknown rate %d\n",
@@ -1424,6 +1842,9 @@ static int twl4030_set_dai_fmt(struct snd_soc_dai *codec_dai,
1424 case SND_SOC_DAIFMT_I2S: 1842 case SND_SOC_DAIFMT_I2S:
1425 format |= TWL4030_AIF_FORMAT_CODEC; 1843 format |= TWL4030_AIF_FORMAT_CODEC;
1426 break; 1844 break;
1845 case SND_SOC_DAIFMT_DSP_A:
1846 format |= TWL4030_AIF_FORMAT_TDM;
1847 break;
1427 default: 1848 default:
1428 return -EINVAL; 1849 return -EINVAL;
1429 } 1850 }
@@ -1443,6 +1864,206 @@ static int twl4030_set_dai_fmt(struct snd_soc_dai *codec_dai,
1443 return 0; 1864 return 0;
1444} 1865}
1445 1866
1867static int twl4030_set_tristate(struct snd_soc_dai *dai, int tristate)
1868{
1869 struct snd_soc_codec *codec = dai->codec;
1870 u8 reg = twl4030_read_reg_cache(codec, TWL4030_REG_AUDIO_IF);
1871
1872 if (tristate)
1873 reg |= TWL4030_AIF_TRI_EN;
1874 else
1875 reg &= ~TWL4030_AIF_TRI_EN;
1876
1877 return twl4030_write(codec, TWL4030_REG_AUDIO_IF, reg);
1878}
1879
1880/* In case of voice mode, the RX1 L(VRX) for downlink and the TX2 L/R
1881 * (VTXL, VTXR) for uplink has to be enabled/disabled. */
1882static void twl4030_voice_enable(struct snd_soc_codec *codec, int direction,
1883 int enable)
1884{
1885 u8 reg, mask;
1886
1887 reg = twl4030_read_reg_cache(codec, TWL4030_REG_OPTION);
1888
1889 if (direction == SNDRV_PCM_STREAM_PLAYBACK)
1890 mask = TWL4030_ARXL1_VRX_EN;
1891 else
1892 mask = TWL4030_ATXL2_VTXL_EN | TWL4030_ATXR2_VTXR_EN;
1893
1894 if (enable)
1895 reg |= mask;
1896 else
1897 reg &= ~mask;
1898
1899 twl4030_write(codec, TWL4030_REG_OPTION, reg);
1900}
1901
1902static int twl4030_voice_startup(struct snd_pcm_substream *substream,
1903 struct snd_soc_dai *dai)
1904{
1905 struct snd_soc_pcm_runtime *rtd = substream->private_data;
1906 struct snd_soc_device *socdev = rtd->socdev;
1907 struct snd_soc_codec *codec = socdev->card->codec;
1908 u8 infreq;
1909 u8 mode;
1910
1911 /* If the system master clock is not 26MHz, the voice PCM interface is
1912 * not avilable.
1913 */
1914 infreq = twl4030_read_reg_cache(codec, TWL4030_REG_APLL_CTL)
1915 & TWL4030_APLL_INFREQ;
1916
1917 if (infreq != TWL4030_APLL_INFREQ_26000KHZ) {
1918 printk(KERN_ERR "TWL4030 voice startup: "
1919 "MCLK is not 26MHz, call set_sysclk() on init\n");
1920 return -EINVAL;
1921 }
1922
1923 /* If the codec mode is not option2, the voice PCM interface is not
1924 * avilable.
1925 */
1926 mode = twl4030_read_reg_cache(codec, TWL4030_REG_CODEC_MODE)
1927 & TWL4030_OPT_MODE;
1928
1929 if (mode != TWL4030_OPTION_2) {
1930 printk(KERN_ERR "TWL4030 voice startup: "
1931 "the codec mode is not option2\n");
1932 return -EINVAL;
1933 }
1934
1935 return 0;
1936}
1937
1938static void twl4030_voice_shutdown(struct snd_pcm_substream *substream,
1939 struct snd_soc_dai *dai)
1940{
1941 struct snd_soc_pcm_runtime *rtd = substream->private_data;
1942 struct snd_soc_device *socdev = rtd->socdev;
1943 struct snd_soc_codec *codec = socdev->card->codec;
1944
1945 /* Enable voice digital filters */
1946 twl4030_voice_enable(codec, substream->stream, 0);
1947}
1948
1949static int twl4030_voice_hw_params(struct snd_pcm_substream *substream,
1950 struct snd_pcm_hw_params *params, struct snd_soc_dai *dai)
1951{
1952 struct snd_soc_pcm_runtime *rtd = substream->private_data;
1953 struct snd_soc_device *socdev = rtd->socdev;
1954 struct snd_soc_codec *codec = socdev->card->codec;
1955 u8 old_mode, mode;
1956
1957 /* Enable voice digital filters */
1958 twl4030_voice_enable(codec, substream->stream, 1);
1959
1960 /* bit rate */
1961 old_mode = twl4030_read_reg_cache(codec, TWL4030_REG_CODEC_MODE)
1962 & ~(TWL4030_CODECPDZ);
1963 mode = old_mode;
1964
1965 switch (params_rate(params)) {
1966 case 8000:
1967 mode &= ~(TWL4030_SEL_16K);
1968 break;
1969 case 16000:
1970 mode |= TWL4030_SEL_16K;
1971 break;
1972 default:
1973 printk(KERN_ERR "TWL4030 voice hw params: unknown rate %d\n",
1974 params_rate(params));
1975 return -EINVAL;
1976 }
1977
1978 if (mode != old_mode) {
1979 /* change rate and set CODECPDZ */
1980 twl4030_codec_enable(codec, 0);
1981 twl4030_write(codec, TWL4030_REG_CODEC_MODE, mode);
1982 twl4030_codec_enable(codec, 1);
1983 }
1984
1985 return 0;
1986}
1987
1988static int twl4030_voice_set_dai_sysclk(struct snd_soc_dai *codec_dai,
1989 int clk_id, unsigned int freq, int dir)
1990{
1991 struct snd_soc_codec *codec = codec_dai->codec;
1992 u8 infreq;
1993
1994 switch (freq) {
1995 case 26000000:
1996 infreq = TWL4030_APLL_INFREQ_26000KHZ;
1997 break;
1998 default:
1999 printk(KERN_ERR "TWL4030 voice set sysclk: unknown rate %d\n",
2000 freq);
2001 return -EINVAL;
2002 }
2003
2004 infreq |= TWL4030_APLL_EN;
2005 twl4030_write(codec, TWL4030_REG_APLL_CTL, infreq);
2006
2007 return 0;
2008}
2009
2010static int twl4030_voice_set_dai_fmt(struct snd_soc_dai *codec_dai,
2011 unsigned int fmt)
2012{
2013 struct snd_soc_codec *codec = codec_dai->codec;
2014 u8 old_format, format;
2015
2016 /* get format */
2017 old_format = twl4030_read_reg_cache(codec, TWL4030_REG_VOICE_IF);
2018 format = old_format;
2019
2020 /* set master/slave audio interface */
2021 switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
2022 case SND_SOC_DAIFMT_CBM_CFM:
2023 format &= ~(TWL4030_VIF_SLAVE_EN);
2024 break;
2025 case SND_SOC_DAIFMT_CBS_CFS:
2026 format |= TWL4030_VIF_SLAVE_EN;
2027 break;
2028 default:
2029 return -EINVAL;
2030 }
2031
2032 /* clock inversion */
2033 switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
2034 case SND_SOC_DAIFMT_IB_NF:
2035 format &= ~(TWL4030_VIF_FORMAT);
2036 break;
2037 case SND_SOC_DAIFMT_NB_IF:
2038 format |= TWL4030_VIF_FORMAT;
2039 break;
2040 default:
2041 return -EINVAL;
2042 }
2043
2044 if (format != old_format) {
2045 /* change format and set CODECPDZ */
2046 twl4030_codec_enable(codec, 0);
2047 twl4030_write(codec, TWL4030_REG_VOICE_IF, format);
2048 twl4030_codec_enable(codec, 1);
2049 }
2050
2051 return 0;
2052}
2053
2054static int twl4030_voice_set_tristate(struct snd_soc_dai *dai, int tristate)
2055{
2056 struct snd_soc_codec *codec = dai->codec;
2057 u8 reg = twl4030_read_reg_cache(codec, TWL4030_REG_VOICE_IF);
2058
2059 if (tristate)
2060 reg |= TWL4030_VIF_TRI_EN;
2061 else
2062 reg &= ~TWL4030_VIF_TRI_EN;
2063
2064 return twl4030_write(codec, TWL4030_REG_VOICE_IF, reg);
2065}
2066
1446#define TWL4030_RATES (SNDRV_PCM_RATE_8000_48000) 2067#define TWL4030_RATES (SNDRV_PCM_RATE_8000_48000)
1447#define TWL4030_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FORMAT_S24_LE) 2068#define TWL4030_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FORMAT_S24_LE)
1448 2069
@@ -1452,23 +2073,51 @@ static struct snd_soc_dai_ops twl4030_dai_ops = {
1452 .hw_params = twl4030_hw_params, 2073 .hw_params = twl4030_hw_params,
1453 .set_sysclk = twl4030_set_dai_sysclk, 2074 .set_sysclk = twl4030_set_dai_sysclk,
1454 .set_fmt = twl4030_set_dai_fmt, 2075 .set_fmt = twl4030_set_dai_fmt,
2076 .set_tristate = twl4030_set_tristate,
2077};
2078
2079static struct snd_soc_dai_ops twl4030_dai_voice_ops = {
2080 .startup = twl4030_voice_startup,
2081 .shutdown = twl4030_voice_shutdown,
2082 .hw_params = twl4030_voice_hw_params,
2083 .set_sysclk = twl4030_voice_set_dai_sysclk,
2084 .set_fmt = twl4030_voice_set_dai_fmt,
2085 .set_tristate = twl4030_voice_set_tristate,
1455}; 2086};
1456 2087
1457struct snd_soc_dai twl4030_dai = { 2088struct snd_soc_dai twl4030_dai[] = {
2089{
1458 .name = "twl4030", 2090 .name = "twl4030",
1459 .playback = { 2091 .playback = {
1460 .stream_name = "Playback", 2092 .stream_name = "HiFi Playback",
1461 .channels_min = 2, 2093 .channels_min = 2,
1462 .channels_max = 2, 2094 .channels_max = 4,
1463 .rates = TWL4030_RATES | SNDRV_PCM_RATE_96000, 2095 .rates = TWL4030_RATES | SNDRV_PCM_RATE_96000,
1464 .formats = TWL4030_FORMATS,}, 2096 .formats = TWL4030_FORMATS,},
1465 .capture = { 2097 .capture = {
1466 .stream_name = "Capture", 2098 .stream_name = "Capture",
1467 .channels_min = 2, 2099 .channels_min = 2,
1468 .channels_max = 2, 2100 .channels_max = 4,
1469 .rates = TWL4030_RATES, 2101 .rates = TWL4030_RATES,
1470 .formats = TWL4030_FORMATS,}, 2102 .formats = TWL4030_FORMATS,},
1471 .ops = &twl4030_dai_ops, 2103 .ops = &twl4030_dai_ops,
2104},
2105{
2106 .name = "twl4030 Voice",
2107 .playback = {
2108 .stream_name = "Voice Playback",
2109 .channels_min = 1,
2110 .channels_max = 1,
2111 .rates = SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_16000,
2112 .formats = SNDRV_PCM_FMTBIT_S16_LE,},
2113 .capture = {
2114 .stream_name = "Capture",
2115 .channels_min = 1,
2116 .channels_max = 2,
2117 .rates = SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_16000,
2118 .formats = SNDRV_PCM_FMTBIT_S16_LE,},
2119 .ops = &twl4030_dai_voice_ops,
2120},
1472}; 2121};
1473EXPORT_SYMBOL_GPL(twl4030_dai); 2122EXPORT_SYMBOL_GPL(twl4030_dai);
1474 2123
@@ -1500,6 +2149,8 @@ static int twl4030_resume(struct platform_device *pdev)
1500static int twl4030_init(struct snd_soc_device *socdev) 2149static int twl4030_init(struct snd_soc_device *socdev)
1501{ 2150{
1502 struct snd_soc_codec *codec = socdev->card->codec; 2151 struct snd_soc_codec *codec = socdev->card->codec;
2152 struct twl4030_setup_data *setup = socdev->codec_data;
2153 struct twl4030_priv *twl4030 = codec->private_data;
1503 int ret = 0; 2154 int ret = 0;
1504 2155
1505 printk(KERN_INFO "TWL4030 Audio Codec init \n"); 2156 printk(KERN_INFO "TWL4030 Audio Codec init \n");
@@ -1509,14 +2160,31 @@ static int twl4030_init(struct snd_soc_device *socdev)
1509 codec->read = twl4030_read_reg_cache; 2160 codec->read = twl4030_read_reg_cache;
1510 codec->write = twl4030_write; 2161 codec->write = twl4030_write;
1511 codec->set_bias_level = twl4030_set_bias_level; 2162 codec->set_bias_level = twl4030_set_bias_level;
1512 codec->dai = &twl4030_dai; 2163 codec->dai = twl4030_dai;
1513 codec->num_dai = 1; 2164 codec->num_dai = ARRAY_SIZE(twl4030_dai),
1514 codec->reg_cache_size = sizeof(twl4030_reg); 2165 codec->reg_cache_size = sizeof(twl4030_reg);
1515 codec->reg_cache = kmemdup(twl4030_reg, sizeof(twl4030_reg), 2166 codec->reg_cache = kmemdup(twl4030_reg, sizeof(twl4030_reg),
1516 GFP_KERNEL); 2167 GFP_KERNEL);
1517 if (codec->reg_cache == NULL) 2168 if (codec->reg_cache == NULL)
1518 return -ENOMEM; 2169 return -ENOMEM;
1519 2170
2171 /* Configuration for headset ramp delay from setup data */
2172 if (setup) {
2173 unsigned char hs_pop;
2174
2175 if (setup->sysclk)
2176 twl4030->sysclk = setup->sysclk;
2177 else
2178 twl4030->sysclk = 26000;
2179
2180 hs_pop = twl4030_read_reg_cache(codec, TWL4030_REG_HS_POPN_SET);
2181 hs_pop &= ~TWL4030_RAMP_DELAY;
2182 hs_pop |= (setup->ramp_delay_value << 2);
2183 twl4030_write_reg_cache(codec, TWL4030_REG_HS_POPN_SET, hs_pop);
2184 } else {
2185 twl4030->sysclk = 26000;
2186 }
2187
1520 /* register pcms */ 2188 /* register pcms */
1521 ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1); 2189 ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1);
1522 if (ret < 0) { 2190 if (ret < 0) {
@@ -1604,13 +2272,13 @@ EXPORT_SYMBOL_GPL(soc_codec_dev_twl4030);
1604 2272
1605static int __init twl4030_modinit(void) 2273static int __init twl4030_modinit(void)
1606{ 2274{
1607 return snd_soc_register_dai(&twl4030_dai); 2275 return snd_soc_register_dais(&twl4030_dai[0], ARRAY_SIZE(twl4030_dai));
1608} 2276}
1609module_init(twl4030_modinit); 2277module_init(twl4030_modinit);
1610 2278
1611static void __exit twl4030_exit(void) 2279static void __exit twl4030_exit(void)
1612{ 2280{
1613 snd_soc_unregister_dai(&twl4030_dai); 2281 snd_soc_unregister_dais(&twl4030_dai[0], ARRAY_SIZE(twl4030_dai));
1614} 2282}
1615module_exit(twl4030_exit); 2283module_exit(twl4030_exit);
1616 2284
diff --git a/sound/soc/codecs/twl4030.h b/sound/soc/codecs/twl4030.h
index cb63765db1df..2b4bfa23f985 100644
--- a/sound/soc/codecs/twl4030.h
+++ b/sound/soc/codecs/twl4030.h
@@ -92,8 +92,9 @@
92#define TWL4030_REG_VIBRA_PWM_SET 0x47 92#define TWL4030_REG_VIBRA_PWM_SET 0x47
93#define TWL4030_REG_ANAMIC_GAIN 0x48 93#define TWL4030_REG_ANAMIC_GAIN 0x48
94#define TWL4030_REG_MISC_SET_2 0x49 94#define TWL4030_REG_MISC_SET_2 0x49
95#define TWL4030_REG_SW_SHADOW 0x4A
95 96
96#define TWL4030_CACHEREGNUM (TWL4030_REG_MISC_SET_2 + 1) 97#define TWL4030_CACHEREGNUM (TWL4030_REG_SW_SHADOW + 1)
97 98
98/* Bitfield Definitions */ 99/* Bitfield Definitions */
99 100
@@ -110,9 +111,22 @@
110#define TWL4030_APLL_RATE_44100 0x90 111#define TWL4030_APLL_RATE_44100 0x90
111#define TWL4030_APLL_RATE_48000 0xA0 112#define TWL4030_APLL_RATE_48000 0xA0
112#define TWL4030_APLL_RATE_96000 0xE0 113#define TWL4030_APLL_RATE_96000 0xE0
113#define TWL4030_SEL_16K 0x04 114#define TWL4030_SEL_16K 0x08
114#define TWL4030_CODECPDZ 0x02 115#define TWL4030_CODECPDZ 0x02
115#define TWL4030_OPT_MODE 0x01 116#define TWL4030_OPT_MODE 0x01
117#define TWL4030_OPTION_1 (1 << 0)
118#define TWL4030_OPTION_2 (0 << 0)
119
120/* TWL4030_OPTION (0x02) Fields */
121
122#define TWL4030_ATXL1_EN (1 << 0)
123#define TWL4030_ATXR1_EN (1 << 1)
124#define TWL4030_ATXL2_VTXL_EN (1 << 2)
125#define TWL4030_ATXR2_VTXR_EN (1 << 3)
126#define TWL4030_ARXL1_VRX_EN (1 << 4)
127#define TWL4030_ARXR1_EN (1 << 5)
128#define TWL4030_ARXL2_EN (1 << 6)
129#define TWL4030_ARXR2_EN (1 << 7)
116 130
117/* TWL4030_REG_MICBIAS_CTL (0x04) Fields */ 131/* TWL4030_REG_MICBIAS_CTL (0x04) Fields */
118 132
@@ -171,6 +185,17 @@
171#define TWL4030_CLK256FS_EN 0x02 185#define TWL4030_CLK256FS_EN 0x02
172#define TWL4030_AIF_EN 0x01 186#define TWL4030_AIF_EN 0x01
173 187
188/* VOICE_IF (0x0F) Fields */
189
190#define TWL4030_VIF_SLAVE_EN 0x80
191#define TWL4030_VIF_DIN_EN 0x40
192#define TWL4030_VIF_DOUT_EN 0x20
193#define TWL4030_VIF_SWAP 0x10
194#define TWL4030_VIF_FORMAT 0x08
195#define TWL4030_VIF_TRI_EN 0x04
196#define TWL4030_VIF_SUB_EN 0x02
197#define TWL4030_VIF_EN 0x01
198
174/* EAR_CTL (0x21) */ 199/* EAR_CTL (0x21) */
175#define TWL4030_EAR_GAIN 0x30 200#define TWL4030_EAR_GAIN 0x30
176 201
@@ -236,7 +261,21 @@
236#define TWL4030_SMOOTH_ANAVOL_EN 0x02 261#define TWL4030_SMOOTH_ANAVOL_EN 0x02
237#define TWL4030_DIGMIC_LR_SWAP_EN 0x01 262#define TWL4030_DIGMIC_LR_SWAP_EN 0x01
238 263
239extern struct snd_soc_dai twl4030_dai; 264/* TWL4030_REG_SW_SHADOW (0x4A) Fields */
265#define TWL4030_HFL_EN 0x01
266#define TWL4030_HFR_EN 0x02
267
268#define TWL4030_DAI_HIFI 0
269#define TWL4030_DAI_VOICE 1
270
271extern struct snd_soc_dai twl4030_dai[2];
240extern struct snd_soc_codec_device soc_codec_dev_twl4030; 272extern struct snd_soc_codec_device soc_codec_dev_twl4030;
241 273
274struct twl4030_setup_data {
275 unsigned int ramp_delay_value;
276 unsigned int sysclk;
277 unsigned int hs_extmute:1;
278 void (*set_hs_extmute)(int mute);
279};
280
242#endif /* End of __TWL4030_AUDIO_H__ */ 281#endif /* End of __TWL4030_AUDIO_H__ */
diff --git a/sound/soc/codecs/uda134x.c b/sound/soc/codecs/uda134x.c
index ddefb8f80145..269b108e1de6 100644
--- a/sound/soc/codecs/uda134x.c
+++ b/sound/soc/codecs/uda134x.c
@@ -101,7 +101,7 @@ static int uda134x_write(struct snd_soc_codec *codec, unsigned int reg,
101 pr_debug("%s reg: %02X, value:%02X\n", __func__, reg, value); 101 pr_debug("%s reg: %02X, value:%02X\n", __func__, reg, value);
102 102
103 if (reg >= UDA134X_REGS_NUM) { 103 if (reg >= UDA134X_REGS_NUM) {
104 printk(KERN_ERR "%s unkown register: reg: %d", 104 printk(KERN_ERR "%s unkown register: reg: %u",
105 __func__, reg); 105 __func__, reg);
106 return -EINVAL; 106 return -EINVAL;
107 } 107 }
@@ -296,7 +296,7 @@ static int uda134x_set_dai_sysclk(struct snd_soc_dai *codec_dai,
296 struct snd_soc_codec *codec = codec_dai->codec; 296 struct snd_soc_codec *codec = codec_dai->codec;
297 struct uda134x_priv *uda134x = codec->private_data; 297 struct uda134x_priv *uda134x = codec->private_data;
298 298
299 pr_debug("%s clk_id: %d, freq: %d, dir: %d\n", __func__, 299 pr_debug("%s clk_id: %d, freq: %u, dir: %d\n", __func__,
300 clk_id, freq, dir); 300 clk_id, freq, dir);
301 301
302 /* Anything between 256fs*8Khz and 512fs*48Khz should be acceptable 302 /* Anything between 256fs*8Khz and 512fs*48Khz should be acceptable
diff --git a/sound/soc/codecs/uda1380.c b/sound/soc/codecs/uda1380.c
index 5b21594e0e58..92ec03442154 100644
--- a/sound/soc/codecs/uda1380.c
+++ b/sound/soc/codecs/uda1380.c
@@ -5,9 +5,7 @@
5 * it under the terms of the GNU General Public License version 2 as 5 * it under the terms of the GNU General Public License version 2 as
6 * published by the Free Software Foundation. 6 * published by the Free Software Foundation.
7 * 7 *
8 * Copyright (c) 2007 Philipp Zabel <philipp.zabel@gmail.com> 8 * Copyright (c) 2007-2009 Philipp Zabel <philipp.zabel@gmail.com>
9 * Improved support for DAPM and audio routing/mixing capabilities,
10 * added TLV support.
11 * 9 *
12 * Modified by Richard Purdie <richard@openedhand.com> to fit into SoC 10 * Modified by Richard Purdie <richard@openedhand.com> to fit into SoC
13 * codec model. 11 * codec model.
@@ -19,26 +17,32 @@
19#include <linux/module.h> 17#include <linux/module.h>
20#include <linux/init.h> 18#include <linux/init.h>
21#include <linux/types.h> 19#include <linux/types.h>
22#include <linux/string.h>
23#include <linux/slab.h> 20#include <linux/slab.h>
24#include <linux/errno.h> 21#include <linux/errno.h>
25#include <linux/ioctl.h> 22#include <linux/gpio.h>
26#include <linux/delay.h> 23#include <linux/delay.h>
27#include <linux/i2c.h> 24#include <linux/i2c.h>
28#include <linux/workqueue.h> 25#include <linux/workqueue.h>
29#include <sound/core.h> 26#include <sound/core.h>
30#include <sound/control.h> 27#include <sound/control.h>
31#include <sound/initval.h> 28#include <sound/initval.h>
32#include <sound/info.h>
33#include <sound/soc.h> 29#include <sound/soc.h>
34#include <sound/soc-dapm.h> 30#include <sound/soc-dapm.h>
35#include <sound/tlv.h> 31#include <sound/tlv.h>
32#include <sound/uda1380.h>
36 33
37#include "uda1380.h" 34#include "uda1380.h"
38 35
39static struct work_struct uda1380_work;
40static struct snd_soc_codec *uda1380_codec; 36static struct snd_soc_codec *uda1380_codec;
41 37
38/* codec private data */
39struct uda1380_priv {
40 struct snd_soc_codec codec;
41 u16 reg_cache[UDA1380_CACHEREGNUM];
42 unsigned int dac_clk;
43 struct work_struct work;
44};
45
42/* 46/*
43 * uda1380 register cache 47 * uda1380 register cache
44 */ 48 */
@@ -473,6 +477,7 @@ static int uda1380_trigger(struct snd_pcm_substream *substream, int cmd,
473 struct snd_soc_pcm_runtime *rtd = substream->private_data; 477 struct snd_soc_pcm_runtime *rtd = substream->private_data;
474 struct snd_soc_device *socdev = rtd->socdev; 478 struct snd_soc_device *socdev = rtd->socdev;
475 struct snd_soc_codec *codec = socdev->card->codec; 479 struct snd_soc_codec *codec = socdev->card->codec;
480 struct uda1380_priv *uda1380 = codec->private_data;
476 int mixer = uda1380_read_reg_cache(codec, UDA1380_MIXER); 481 int mixer = uda1380_read_reg_cache(codec, UDA1380_MIXER);
477 482
478 switch (cmd) { 483 switch (cmd) {
@@ -480,13 +485,13 @@ static int uda1380_trigger(struct snd_pcm_substream *substream, int cmd,
480 case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: 485 case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
481 uda1380_write_reg_cache(codec, UDA1380_MIXER, 486 uda1380_write_reg_cache(codec, UDA1380_MIXER,
482 mixer & ~R14_SILENCE); 487 mixer & ~R14_SILENCE);
483 schedule_work(&uda1380_work); 488 schedule_work(&uda1380->work);
484 break; 489 break;
485 case SNDRV_PCM_TRIGGER_STOP: 490 case SNDRV_PCM_TRIGGER_STOP:
486 case SNDRV_PCM_TRIGGER_PAUSE_PUSH: 491 case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
487 uda1380_write_reg_cache(codec, UDA1380_MIXER, 492 uda1380_write_reg_cache(codec, UDA1380_MIXER,
488 mixer | R14_SILENCE); 493 mixer | R14_SILENCE);
489 schedule_work(&uda1380_work); 494 schedule_work(&uda1380->work);
490 break; 495 break;
491 } 496 }
492 return 0; 497 return 0;
@@ -670,44 +675,33 @@ static int uda1380_resume(struct platform_device *pdev)
670 return 0; 675 return 0;
671} 676}
672 677
673/* 678static int uda1380_probe(struct platform_device *pdev)
674 * initialise the UDA1380 driver
675 * register mixer and dsp interfaces with the kernel
676 */
677static int uda1380_init(struct snd_soc_device *socdev, int dac_clk)
678{ 679{
679 struct snd_soc_codec *codec = socdev->card->codec; 680 struct snd_soc_device *socdev = platform_get_drvdata(pdev);
681 struct snd_soc_codec *codec;
682 struct uda1380_platform_data *pdata;
680 int ret = 0; 683 int ret = 0;
681 684
682 codec->name = "UDA1380"; 685 if (uda1380_codec == NULL) {
683 codec->owner = THIS_MODULE; 686 dev_err(&pdev->dev, "Codec device not registered\n");
684 codec->read = uda1380_read_reg_cache; 687 return -ENODEV;
685 codec->write = uda1380_write; 688 }
686 codec->set_bias_level = uda1380_set_bias_level;
687 codec->dai = uda1380_dai;
688 codec->num_dai = ARRAY_SIZE(uda1380_dai);
689 codec->reg_cache = kmemdup(uda1380_reg, sizeof(uda1380_reg),
690 GFP_KERNEL);
691 if (codec->reg_cache == NULL)
692 return -ENOMEM;
693 codec->reg_cache_size = ARRAY_SIZE(uda1380_reg);
694 codec->reg_cache_step = 1;
695 uda1380_reset(codec);
696 689
697 uda1380_codec = codec; 690 socdev->card->codec = uda1380_codec;
698 INIT_WORK(&uda1380_work, uda1380_flush_work); 691 codec = uda1380_codec;
692 pdata = codec->dev->platform_data;
699 693
700 /* register pcms */ 694 /* register pcms */
701 ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1); 695 ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1);
702 if (ret < 0) { 696 if (ret < 0) {
703 pr_err("uda1380: failed to create pcms\n"); 697 dev_err(codec->dev, "failed to create pcms: %d\n", ret);
704 goto pcm_err; 698 goto pcm_err;
705 } 699 }
706 700
707 /* power on device */ 701 /* power on device */
708 uda1380_set_bias_level(codec, SND_SOC_BIAS_STANDBY); 702 uda1380_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
709 /* set clock input */ 703 /* set clock input */
710 switch (dac_clk) { 704 switch (pdata->dac_clk) {
711 case UDA1380_DAC_CLK_SYSCLK: 705 case UDA1380_DAC_CLK_SYSCLK:
712 uda1380_write(codec, UDA1380_CLK, 0); 706 uda1380_write(codec, UDA1380_CLK, 0);
713 break; 707 break;
@@ -716,13 +710,12 @@ static int uda1380_init(struct snd_soc_device *socdev, int dac_clk)
716 break; 710 break;
717 } 711 }
718 712
719 /* uda1380 init */
720 snd_soc_add_controls(codec, uda1380_snd_controls, 713 snd_soc_add_controls(codec, uda1380_snd_controls,
721 ARRAY_SIZE(uda1380_snd_controls)); 714 ARRAY_SIZE(uda1380_snd_controls));
722 uda1380_add_widgets(codec); 715 uda1380_add_widgets(codec);
723 ret = snd_soc_init_card(socdev); 716 ret = snd_soc_init_card(socdev);
724 if (ret < 0) { 717 if (ret < 0) {
725 pr_err("uda1380: failed to register card\n"); 718 dev_err(codec->dev, "failed to register card: %d\n", ret);
726 goto card_err; 719 goto card_err;
727 } 720 }
728 721
@@ -732,165 +725,201 @@ card_err:
732 snd_soc_free_pcms(socdev); 725 snd_soc_free_pcms(socdev);
733 snd_soc_dapm_free(socdev); 726 snd_soc_dapm_free(socdev);
734pcm_err: 727pcm_err:
735 kfree(codec->reg_cache);
736 return ret; 728 return ret;
737} 729}
738 730
739static struct snd_soc_device *uda1380_socdev; 731/* power down chip */
740 732static int uda1380_remove(struct platform_device *pdev)
741#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
742
743static int uda1380_i2c_probe(struct i2c_client *i2c,
744 const struct i2c_device_id *id)
745{ 733{
746 struct snd_soc_device *socdev = uda1380_socdev; 734 struct snd_soc_device *socdev = platform_get_drvdata(pdev);
747 struct uda1380_setup_data *setup = socdev->codec_data;
748 struct snd_soc_codec *codec = socdev->card->codec; 735 struct snd_soc_codec *codec = socdev->card->codec;
749 int ret;
750
751 i2c_set_clientdata(i2c, codec);
752 codec->control_data = i2c;
753 736
754 ret = uda1380_init(socdev, setup->dac_clk); 737 if (codec->control_data)
755 if (ret < 0) 738 uda1380_set_bias_level(codec, SND_SOC_BIAS_OFF);
756 pr_err("uda1380: failed to initialise UDA1380\n");
757 739
758 return ret; 740 snd_soc_free_pcms(socdev);
759} 741 snd_soc_dapm_free(socdev);
760 742
761static int uda1380_i2c_remove(struct i2c_client *client)
762{
763 struct snd_soc_codec *codec = i2c_get_clientdata(client);
764 kfree(codec->reg_cache);
765 return 0; 743 return 0;
766} 744}
767 745
768static const struct i2c_device_id uda1380_i2c_id[] = { 746struct snd_soc_codec_device soc_codec_dev_uda1380 = {
769 { "uda1380", 0 }, 747 .probe = uda1380_probe,
770 { } 748 .remove = uda1380_remove,
771}; 749 .suspend = uda1380_suspend,
772MODULE_DEVICE_TABLE(i2c, uda1380_i2c_id); 750 .resume = uda1380_resume,
773
774static struct i2c_driver uda1380_i2c_driver = {
775 .driver = {
776 .name = "UDA1380 I2C Codec",
777 .owner = THIS_MODULE,
778 },
779 .probe = uda1380_i2c_probe,
780 .remove = uda1380_i2c_remove,
781 .id_table = uda1380_i2c_id,
782}; 751};
752EXPORT_SYMBOL_GPL(soc_codec_dev_uda1380);
783 753
784static int uda1380_add_i2c_device(struct platform_device *pdev, 754static int uda1380_register(struct uda1380_priv *uda1380)
785 const struct uda1380_setup_data *setup)
786{ 755{
787 struct i2c_board_info info; 756 int ret, i;
788 struct i2c_adapter *adapter; 757 struct snd_soc_codec *codec = &uda1380->codec;
789 struct i2c_client *client; 758 struct uda1380_platform_data *pdata = codec->dev->platform_data;
790 int ret;
791 759
792 ret = i2c_add_driver(&uda1380_i2c_driver); 760 if (uda1380_codec) {
793 if (ret != 0) { 761 dev_err(codec->dev, "Another UDA1380 is registered\n");
794 dev_err(&pdev->dev, "can't add i2c driver\n"); 762 return -EINVAL;
795 return ret; 763 }
764
765 if (!pdata || !pdata->gpio_power || !pdata->gpio_reset)
766 return -EINVAL;
767
768 ret = gpio_request(pdata->gpio_power, "uda1380 power");
769 if (ret)
770 goto err_out;
771 ret = gpio_request(pdata->gpio_reset, "uda1380 reset");
772 if (ret)
773 goto err_gpio;
774
775 gpio_direction_output(pdata->gpio_power, 1);
776
777 /* we may need to have the clock running here - pH5 */
778 gpio_direction_output(pdata->gpio_reset, 1);
779 udelay(5);
780 gpio_set_value(pdata->gpio_reset, 0);
781
782 mutex_init(&codec->mutex);
783 INIT_LIST_HEAD(&codec->dapm_widgets);
784 INIT_LIST_HEAD(&codec->dapm_paths);
785
786 codec->private_data = uda1380;
787 codec->name = "UDA1380";
788 codec->owner = THIS_MODULE;
789 codec->read = uda1380_read_reg_cache;
790 codec->write = uda1380_write;
791 codec->bias_level = SND_SOC_BIAS_OFF;
792 codec->set_bias_level = uda1380_set_bias_level;
793 codec->dai = uda1380_dai;
794 codec->num_dai = ARRAY_SIZE(uda1380_dai);
795 codec->reg_cache_size = ARRAY_SIZE(uda1380_reg);
796 codec->reg_cache = &uda1380->reg_cache;
797 codec->reg_cache_step = 1;
798
799 memcpy(codec->reg_cache, uda1380_reg, sizeof(uda1380_reg));
800
801 ret = uda1380_reset(codec);
802 if (ret < 0) {
803 dev_err(codec->dev, "Failed to issue reset\n");
804 goto err_reset;
796 } 805 }
797 806
798 memset(&info, 0, sizeof(struct i2c_board_info)); 807 INIT_WORK(&uda1380->work, uda1380_flush_work);
799 info.addr = setup->i2c_address; 808
800 strlcpy(info.type, "uda1380", I2C_NAME_SIZE); 809 for (i = 0; i < ARRAY_SIZE(uda1380_dai); i++)
810 uda1380_dai[i].dev = codec->dev;
801 811
802 adapter = i2c_get_adapter(setup->i2c_bus); 812 uda1380_codec = codec;
803 if (!adapter) { 813
804 dev_err(&pdev->dev, "can't get i2c adapter %d\n", 814 ret = snd_soc_register_codec(codec);
805 setup->i2c_bus); 815 if (ret != 0) {
806 goto err_driver; 816 dev_err(codec->dev, "Failed to register codec: %d\n", ret);
817 goto err_reset;
807 } 818 }
808 819
809 client = i2c_new_device(adapter, &info); 820 ret = snd_soc_register_dais(uda1380_dai, ARRAY_SIZE(uda1380_dai));
810 i2c_put_adapter(adapter); 821 if (ret != 0) {
811 if (!client) { 822 dev_err(codec->dev, "Failed to register DAIs: %d\n", ret);
812 dev_err(&pdev->dev, "can't add i2c device at 0x%x\n", 823 goto err_dai;
813 (unsigned int)info.addr);
814 goto err_driver;
815 } 824 }
816 825
817 return 0; 826 return 0;
818 827
819err_driver: 828err_dai:
820 i2c_del_driver(&uda1380_i2c_driver); 829 snd_soc_unregister_codec(codec);
821 return -ENODEV; 830err_reset:
831 gpio_set_value(pdata->gpio_power, 0);
832 gpio_free(pdata->gpio_reset);
833err_gpio:
834 gpio_free(pdata->gpio_power);
835err_out:
836 return ret;
822} 837}
823#endif
824 838
825static int uda1380_probe(struct platform_device *pdev) 839static void uda1380_unregister(struct uda1380_priv *uda1380)
826{ 840{
827 struct snd_soc_device *socdev = platform_get_drvdata(pdev); 841 struct snd_soc_codec *codec = &uda1380->codec;
828 struct uda1380_setup_data *setup; 842 struct uda1380_platform_data *pdata = codec->dev->platform_data;
843
844 snd_soc_unregister_dais(uda1380_dai, ARRAY_SIZE(uda1380_dai));
845 snd_soc_unregister_codec(&uda1380->codec);
846
847 gpio_set_value(pdata->gpio_power, 0);
848 gpio_free(pdata->gpio_reset);
849 gpio_free(pdata->gpio_power);
850
851 kfree(uda1380);
852 uda1380_codec = NULL;
853}
854
855#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
856static __devinit int uda1380_i2c_probe(struct i2c_client *i2c,
857 const struct i2c_device_id *id)
858{
859 struct uda1380_priv *uda1380;
829 struct snd_soc_codec *codec; 860 struct snd_soc_codec *codec;
830 int ret; 861 int ret;
831 862
832 setup = socdev->codec_data; 863 uda1380 = kzalloc(sizeof(struct uda1380_priv), GFP_KERNEL);
833 codec = kzalloc(sizeof(struct snd_soc_codec), GFP_KERNEL); 864 if (uda1380 == NULL)
834 if (codec == NULL)
835 return -ENOMEM; 865 return -ENOMEM;
836 866
837 socdev->card->codec = codec; 867 codec = &uda1380->codec;
838 mutex_init(&codec->mutex); 868 codec->hw_write = (hw_write_t)i2c_master_send;
839 INIT_LIST_HEAD(&codec->dapm_widgets);
840 INIT_LIST_HEAD(&codec->dapm_paths);
841 869
842 uda1380_socdev = socdev; 870 i2c_set_clientdata(i2c, uda1380);
843 ret = -ENODEV; 871 codec->control_data = i2c;
844 872
845#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) 873 codec->dev = &i2c->dev;
846 if (setup->i2c_address) {
847 codec->hw_write = (hw_write_t)i2c_master_send;
848 ret = uda1380_add_i2c_device(pdev, setup);
849 }
850#endif
851 874
875 ret = uda1380_register(uda1380);
852 if (ret != 0) 876 if (ret != 0)
853 kfree(codec); 877 kfree(uda1380);
878
854 return ret; 879 return ret;
855} 880}
856 881
857/* power down chip */ 882static int __devexit uda1380_i2c_remove(struct i2c_client *i2c)
858static int uda1380_remove(struct platform_device *pdev)
859{ 883{
860 struct snd_soc_device *socdev = platform_get_drvdata(pdev); 884 struct uda1380_priv *uda1380 = i2c_get_clientdata(i2c);
861 struct snd_soc_codec *codec = socdev->card->codec; 885 uda1380_unregister(uda1380);
862
863 if (codec->control_data)
864 uda1380_set_bias_level(codec, SND_SOC_BIAS_OFF);
865
866 snd_soc_free_pcms(socdev);
867 snd_soc_dapm_free(socdev);
868#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
869 i2c_unregister_device(codec->control_data);
870 i2c_del_driver(&uda1380_i2c_driver);
871#endif
872 kfree(codec);
873
874 return 0; 886 return 0;
875} 887}
876 888
877struct snd_soc_codec_device soc_codec_dev_uda1380 = { 889static const struct i2c_device_id uda1380_i2c_id[] = {
878 .probe = uda1380_probe, 890 { "uda1380", 0 },
879 .remove = uda1380_remove, 891 { }
880 .suspend = uda1380_suspend,
881 .resume = uda1380_resume,
882}; 892};
883EXPORT_SYMBOL_GPL(soc_codec_dev_uda1380); 893MODULE_DEVICE_TABLE(i2c, uda1380_i2c_id);
894
895static struct i2c_driver uda1380_i2c_driver = {
896 .driver = {
897 .name = "UDA1380 I2C Codec",
898 .owner = THIS_MODULE,
899 },
900 .probe = uda1380_i2c_probe,
901 .remove = __devexit_p(uda1380_i2c_remove),
902 .id_table = uda1380_i2c_id,
903};
904#endif
884 905
885static int __init uda1380_modinit(void) 906static int __init uda1380_modinit(void)
886{ 907{
887 return snd_soc_register_dais(uda1380_dai, ARRAY_SIZE(uda1380_dai)); 908 int ret;
909#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
910 ret = i2c_add_driver(&uda1380_i2c_driver);
911 if (ret != 0)
912 pr_err("Failed to register UDA1380 I2C driver: %d\n", ret);
913#endif
914 return 0;
888} 915}
889module_init(uda1380_modinit); 916module_init(uda1380_modinit);
890 917
891static void __exit uda1380_exit(void) 918static void __exit uda1380_exit(void)
892{ 919{
893 snd_soc_unregister_dais(uda1380_dai, ARRAY_SIZE(uda1380_dai)); 920#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
921 i2c_del_driver(&uda1380_i2c_driver);
922#endif
894} 923}
895module_exit(uda1380_exit); 924module_exit(uda1380_exit);
896 925
diff --git a/sound/soc/codecs/uda1380.h b/sound/soc/codecs/uda1380.h
index c55c17a52a12..9cefa8a54770 100644
--- a/sound/soc/codecs/uda1380.h
+++ b/sound/soc/codecs/uda1380.h
@@ -72,14 +72,6 @@
72#define R22_SKIP_DCFIL 0x0002 72#define R22_SKIP_DCFIL 0x0002
73#define R23_AGC_EN 0x0001 73#define R23_AGC_EN 0x0001
74 74
75struct uda1380_setup_data {
76 int i2c_bus;
77 unsigned short i2c_address;
78 int dac_clk;
79#define UDA1380_DAC_CLK_SYSCLK 0
80#define UDA1380_DAC_CLK_WSPLL 1
81};
82
83#define UDA1380_DAI_DUPLEX 0 /* playback and capture on single DAI */ 75#define UDA1380_DAI_DUPLEX 0 /* playback and capture on single DAI */
84#define UDA1380_DAI_PLAYBACK 1 /* playback DAI */ 76#define UDA1380_DAI_PLAYBACK 1 /* playback DAI */
85#define UDA1380_DAI_CAPTURE 2 /* capture DAI */ 77#define UDA1380_DAI_CAPTURE 2 /* capture DAI */
diff --git a/sound/soc/codecs/wm8350.c b/sound/soc/codecs/wm8350.c
index 0275321ff8ab..4ded0e3a35e0 100644
--- a/sound/soc/codecs/wm8350.c
+++ b/sound/soc/codecs/wm8350.c
@@ -406,7 +406,6 @@ static const char *wm8350_deemp[] = { "None", "32kHz", "44.1kHz", "48kHz" };
406static const char *wm8350_pol[] = { "Normal", "Inv R", "Inv L", "Inv L & R" }; 406static const char *wm8350_pol[] = { "Normal", "Inv R", "Inv L", "Inv L & R" };
407static const char *wm8350_dacmutem[] = { "Normal", "Soft" }; 407static const char *wm8350_dacmutem[] = { "Normal", "Soft" };
408static const char *wm8350_dacmutes[] = { "Fast", "Slow" }; 408static const char *wm8350_dacmutes[] = { "Fast", "Slow" };
409static const char *wm8350_dacfilter[] = { "Normal", "Sloping" };
410static const char *wm8350_adcfilter[] = { "None", "High Pass" }; 409static const char *wm8350_adcfilter[] = { "None", "High Pass" };
411static const char *wm8350_adchp[] = { "44.1kHz", "8kHz", "16kHz", "32kHz" }; 410static const char *wm8350_adchp[] = { "44.1kHz", "8kHz", "16kHz", "32kHz" };
412static const char *wm8350_lr[] = { "Left", "Right" }; 411static const char *wm8350_lr[] = { "Left", "Right" };
@@ -416,7 +415,6 @@ static const struct soc_enum wm8350_enum[] = {
416 SOC_ENUM_SINGLE(WM8350_DAC_CONTROL, 0, 4, wm8350_pol), 415 SOC_ENUM_SINGLE(WM8350_DAC_CONTROL, 0, 4, wm8350_pol),
417 SOC_ENUM_SINGLE(WM8350_DAC_MUTE_VOLUME, 14, 2, wm8350_dacmutem), 416 SOC_ENUM_SINGLE(WM8350_DAC_MUTE_VOLUME, 14, 2, wm8350_dacmutem),
418 SOC_ENUM_SINGLE(WM8350_DAC_MUTE_VOLUME, 13, 2, wm8350_dacmutes), 417 SOC_ENUM_SINGLE(WM8350_DAC_MUTE_VOLUME, 13, 2, wm8350_dacmutes),
419 SOC_ENUM_SINGLE(WM8350_DAC_MUTE_VOLUME, 12, 2, wm8350_dacfilter),
420 SOC_ENUM_SINGLE(WM8350_ADC_CONTROL, 15, 2, wm8350_adcfilter), 418 SOC_ENUM_SINGLE(WM8350_ADC_CONTROL, 15, 2, wm8350_adcfilter),
421 SOC_ENUM_SINGLE(WM8350_ADC_CONTROL, 8, 4, wm8350_adchp), 419 SOC_ENUM_SINGLE(WM8350_ADC_CONTROL, 8, 4, wm8350_adchp),
422 SOC_ENUM_SINGLE(WM8350_ADC_CONTROL, 0, 4, wm8350_pol), 420 SOC_ENUM_SINGLE(WM8350_ADC_CONTROL, 0, 4, wm8350_pol),
@@ -444,10 +442,9 @@ static const struct snd_kcontrol_new wm8350_snd_controls[] = {
444 0, 255, 0, dac_pcm_tlv), 442 0, 255, 0, dac_pcm_tlv),
445 SOC_ENUM("Playback PCM Mute Function", wm8350_enum[2]), 443 SOC_ENUM("Playback PCM Mute Function", wm8350_enum[2]),
446 SOC_ENUM("Playback PCM Mute Speed", wm8350_enum[3]), 444 SOC_ENUM("Playback PCM Mute Speed", wm8350_enum[3]),
447 SOC_ENUM("Playback PCM Filter", wm8350_enum[4]), 445 SOC_ENUM("Capture PCM Filter", wm8350_enum[4]),
448 SOC_ENUM("Capture PCM Filter", wm8350_enum[5]), 446 SOC_ENUM("Capture PCM HP Filter", wm8350_enum[5]),
449 SOC_ENUM("Capture PCM HP Filter", wm8350_enum[6]), 447 SOC_ENUM("Capture ADC Inversion", wm8350_enum[6]),
450 SOC_ENUM("Capture ADC Inversion", wm8350_enum[7]),
451 SOC_WM8350_DOUBLE_R_TLV("Capture PCM Volume", 448 SOC_WM8350_DOUBLE_R_TLV("Capture PCM Volume",
452 WM8350_ADC_DIGITAL_VOLUME_L, 449 WM8350_ADC_DIGITAL_VOLUME_L,
453 WM8350_ADC_DIGITAL_VOLUME_R, 450 WM8350_ADC_DIGITAL_VOLUME_R,
@@ -993,6 +990,7 @@ static int wm8350_pcm_hw_params(struct snd_pcm_substream *substream,
993 struct snd_soc_dai *codec_dai) 990 struct snd_soc_dai *codec_dai)
994{ 991{
995 struct snd_soc_codec *codec = codec_dai->codec; 992 struct snd_soc_codec *codec = codec_dai->codec;
993 struct wm8350 *wm8350 = codec->control_data;
996 u16 iface = wm8350_codec_read(codec, WM8350_AI_FORMATING) & 994 u16 iface = wm8350_codec_read(codec, WM8350_AI_FORMATING) &
997 ~WM8350_AIF_WL_MASK; 995 ~WM8350_AIF_WL_MASK;
998 996
@@ -1012,6 +1010,19 @@ static int wm8350_pcm_hw_params(struct snd_pcm_substream *substream,
1012 } 1010 }
1013 1011
1014 wm8350_codec_write(codec, WM8350_AI_FORMATING, iface); 1012 wm8350_codec_write(codec, WM8350_AI_FORMATING, iface);
1013
1014 /* The sloping stopband filter is recommended for use with
1015 * lower sample rates to improve performance.
1016 */
1017 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
1018 if (params_rate(params) < 24000)
1019 wm8350_set_bits(wm8350, WM8350_DAC_MUTE_VOLUME,
1020 WM8350_DAC_SB_FILT);
1021 else
1022 wm8350_clear_bits(wm8350, WM8350_DAC_MUTE_VOLUME,
1023 WM8350_DAC_SB_FILT);
1024 }
1025
1015 return 0; 1026 return 0;
1016} 1027}
1017 1028
@@ -1108,7 +1119,7 @@ static int wm8350_set_fll(struct snd_soc_dai *codec_dai,
1108 if (ret < 0) 1119 if (ret < 0)
1109 return ret; 1120 return ret;
1110 dev_dbg(wm8350->dev, 1121 dev_dbg(wm8350->dev,
1111 "FLL in %d FLL out %d N 0x%x K 0x%x div %d ratio %d", 1122 "FLL in %u FLL out %u N 0x%x K 0x%x div %d ratio %d",
1112 freq_in, freq_out, fll_div.n, fll_div.k, fll_div.div, 1123 freq_in, freq_out, fll_div.n, fll_div.k, fll_div.div,
1113 fll_div.ratio); 1124 fll_div.ratio);
1114 1125
@@ -1660,6 +1671,21 @@ static int __devexit wm8350_codec_remove(struct platform_device *pdev)
1660 return 0; 1671 return 0;
1661} 1672}
1662 1673
1674#ifdef CONFIG_PM
1675static int wm8350_codec_suspend(struct platform_device *pdev, pm_message_t m)
1676{
1677 return snd_soc_suspend_device(&pdev->dev);
1678}
1679
1680static int wm8350_codec_resume(struct platform_device *pdev)
1681{
1682 return snd_soc_resume_device(&pdev->dev);
1683}
1684#else
1685#define wm8350_codec_suspend NULL
1686#define wm8350_codec_resume NULL
1687#endif
1688
1663static struct platform_driver wm8350_codec_driver = { 1689static struct platform_driver wm8350_codec_driver = {
1664 .driver = { 1690 .driver = {
1665 .name = "wm8350-codec", 1691 .name = "wm8350-codec",
@@ -1667,6 +1693,8 @@ static struct platform_driver wm8350_codec_driver = {
1667 }, 1693 },
1668 .probe = wm8350_codec_probe, 1694 .probe = wm8350_codec_probe,
1669 .remove = __devexit_p(wm8350_codec_remove), 1695 .remove = __devexit_p(wm8350_codec_remove),
1696 .suspend = wm8350_codec_suspend,
1697 .resume = wm8350_codec_resume,
1670}; 1698};
1671 1699
1672static __init int wm8350_init(void) 1700static __init int wm8350_init(void)
diff --git a/sound/soc/codecs/wm8350.h b/sound/soc/codecs/wm8350.h
index d11bd9288cf9..d088eb4b88bb 100644
--- a/sound/soc/codecs/wm8350.h
+++ b/sound/soc/codecs/wm8350.h
@@ -13,6 +13,7 @@
13#define _WM8350_H 13#define _WM8350_H
14 14
15#include <sound/soc.h> 15#include <sound/soc.h>
16#include <linux/mfd/wm8350/audio.h>
16 17
17extern struct snd_soc_dai wm8350_dai; 18extern struct snd_soc_dai wm8350_dai;
18extern struct snd_soc_codec_device soc_codec_dev_wm8350; 19extern struct snd_soc_codec_device soc_codec_dev_wm8350;
diff --git a/sound/soc/codecs/wm8400.c b/sound/soc/codecs/wm8400.c
index 510efa604008..b9ef4d915221 100644
--- a/sound/soc/codecs/wm8400.c
+++ b/sound/soc/codecs/wm8400.c
@@ -954,7 +954,7 @@ static int fll_factors(struct wm8400_priv *wm8400, struct fll_factors *factors,
954 factors->outdiv *= 2; 954 factors->outdiv *= 2;
955 if (factors->outdiv > 32) { 955 if (factors->outdiv > 32) {
956 dev_err(wm8400->wm8400->dev, 956 dev_err(wm8400->wm8400->dev,
957 "Unsupported FLL output frequency %dHz\n", 957 "Unsupported FLL output frequency %uHz\n",
958 Fout); 958 Fout);
959 return -EINVAL; 959 return -EINVAL;
960 } 960 }
@@ -1003,7 +1003,7 @@ static int fll_factors(struct wm8400_priv *wm8400, struct fll_factors *factors,
1003 factors->k = K / 10; 1003 factors->k = K / 10;
1004 1004
1005 dev_dbg(wm8400->wm8400->dev, 1005 dev_dbg(wm8400->wm8400->dev,
1006 "FLL: Fref=%d Fout=%d N=%x K=%x, FRATIO=%x OUTDIV=%x\n", 1006 "FLL: Fref=%u Fout=%u N=%x K=%x, FRATIO=%x OUTDIV=%x\n",
1007 Fref, Fout, 1007 Fref, Fout,
1008 factors->n, factors->k, factors->fratio, factors->outdiv); 1008 factors->n, factors->k, factors->fratio, factors->outdiv);
1009 1009
@@ -1022,10 +1022,15 @@ static int wm8400_set_dai_pll(struct snd_soc_dai *codec_dai, int pll_id,
1022 if (freq_in == wm8400->fll_in && freq_out == wm8400->fll_out) 1022 if (freq_in == wm8400->fll_in && freq_out == wm8400->fll_out)
1023 return 0; 1023 return 0;
1024 1024
1025 if (freq_out != 0) { 1025 if (freq_out) {
1026 ret = fll_factors(wm8400, &factors, freq_in, freq_out); 1026 ret = fll_factors(wm8400, &factors, freq_in, freq_out);
1027 if (ret != 0) 1027 if (ret != 0)
1028 return ret; 1028 return ret;
1029 } else {
1030 /* Bodge GCC 4.4.0 uninitialised variable warning - it
1031 * doesn't seem capable of working out that we exit if
1032 * freq_out is 0 before any of the uses. */
1033 memset(&factors, 0, sizeof(factors));
1029 } 1034 }
1030 1035
1031 wm8400->fll_out = freq_out; 1036 wm8400->fll_out = freq_out;
@@ -1040,7 +1045,7 @@ static int wm8400_set_dai_pll(struct snd_soc_dai *codec_dai, int pll_id,
1040 reg &= ~WM8400_FLL_OSC_ENA; 1045 reg &= ~WM8400_FLL_OSC_ENA;
1041 wm8400_write(codec, WM8400_FLL_CONTROL_1, reg); 1046 wm8400_write(codec, WM8400_FLL_CONTROL_1, reg);
1042 1047
1043 if (freq_out == 0) 1048 if (!freq_out)
1044 return 0; 1049 return 0;
1045 1050
1046 reg &= ~(WM8400_FLL_REF_FREQ | WM8400_FLL_FRATIO_MASK); 1051 reg &= ~(WM8400_FLL_REF_FREQ | WM8400_FLL_FRATIO_MASK);
@@ -1473,8 +1478,8 @@ static int wm8400_codec_probe(struct platform_device *dev)
1473 1478
1474 codec = &priv->codec; 1479 codec = &priv->codec;
1475 codec->private_data = priv; 1480 codec->private_data = priv;
1476 codec->control_data = dev->dev.driver_data; 1481 codec->control_data = dev_get_drvdata(&dev->dev);
1477 priv->wm8400 = dev->dev.driver_data; 1482 priv->wm8400 = dev_get_drvdata(&dev->dev);
1478 1483
1479 ret = regulator_bulk_get(priv->wm8400->dev, 1484 ret = regulator_bulk_get(priv->wm8400->dev,
1480 ARRAY_SIZE(power), &power[0]); 1485 ARRAY_SIZE(power), &power[0]);
@@ -1553,6 +1558,21 @@ static int __exit wm8400_codec_remove(struct platform_device *dev)
1553 return 0; 1558 return 0;
1554} 1559}
1555 1560
1561#ifdef CONFIG_PM
1562static int wm8400_pdev_suspend(struct platform_device *pdev, pm_message_t msg)
1563{
1564 return snd_soc_suspend_device(&pdev->dev);
1565}
1566
1567static int wm8400_pdev_resume(struct platform_device *pdev)
1568{
1569 return snd_soc_resume_device(&pdev->dev);
1570}
1571#else
1572#define wm8400_pdev_suspend NULL
1573#define wm8400_pdev_resume NULL
1574#endif
1575
1556static struct platform_driver wm8400_codec_driver = { 1576static struct platform_driver wm8400_codec_driver = {
1557 .driver = { 1577 .driver = {
1558 .name = "wm8400-codec", 1578 .name = "wm8400-codec",
@@ -1560,6 +1580,8 @@ static struct platform_driver wm8400_codec_driver = {
1560 }, 1580 },
1561 .probe = wm8400_codec_probe, 1581 .probe = wm8400_codec_probe,
1562 .remove = __exit_p(wm8400_codec_remove), 1582 .remove = __exit_p(wm8400_codec_remove),
1583 .suspend = wm8400_pdev_suspend,
1584 .resume = wm8400_pdev_resume,
1563}; 1585};
1564 1586
1565static int __init wm8400_codec_init(void) 1587static int __init wm8400_codec_init(void)
diff --git a/sound/soc/codecs/wm8510.c b/sound/soc/codecs/wm8510.c
index 6a4cea09c45d..060d5d06ba95 100644
--- a/sound/soc/codecs/wm8510.c
+++ b/sound/soc/codecs/wm8510.c
@@ -58,55 +58,7 @@ static const u16 wm8510_reg[WM8510_CACHEREGNUM] = {
58#define WM8510_POWER1_BIASEN 0x08 58#define WM8510_POWER1_BIASEN 0x08
59#define WM8510_POWER1_BUFIOEN 0x10 59#define WM8510_POWER1_BUFIOEN 0x10
60 60
61/* 61#define wm8510_reset(c) snd_soc_write(c, WM8510_RESET, 0)
62 * read wm8510 register cache
63 */
64static inline unsigned int wm8510_read_reg_cache(struct snd_soc_codec *codec,
65 unsigned int reg)
66{
67 u16 *cache = codec->reg_cache;
68 if (reg == WM8510_RESET)
69 return 0;
70 if (reg >= WM8510_CACHEREGNUM)
71 return -1;
72 return cache[reg];
73}
74
75/*
76 * write wm8510 register cache
77 */
78static inline void wm8510_write_reg_cache(struct snd_soc_codec *codec,
79 u16 reg, unsigned int value)
80{
81 u16 *cache = codec->reg_cache;
82 if (reg >= WM8510_CACHEREGNUM)
83 return;
84 cache[reg] = value;
85}
86
87/*
88 * write to the WM8510 register space
89 */
90static int wm8510_write(struct snd_soc_codec *codec, unsigned int reg,
91 unsigned int value)
92{
93 u8 data[2];
94
95 /* data is
96 * D15..D9 WM8510 register offset
97 * D8...D0 register data
98 */
99 data[0] = (reg << 1) | ((value >> 8) & 0x0001);
100 data[1] = value & 0x00ff;
101
102 wm8510_write_reg_cache(codec, reg, value);
103 if (codec->hw_write(codec->control_data, data, 2) == 2)
104 return 0;
105 else
106 return -EIO;
107}
108
109#define wm8510_reset(c) wm8510_write(c, WM8510_RESET, 0)
110 62
111static const char *wm8510_companding[] = { "Off", "NC", "u-law", "A-law" }; 63static const char *wm8510_companding[] = { "Off", "NC", "u-law", "A-law" };
112static const char *wm8510_deemp[] = { "None", "32kHz", "44.1kHz", "48kHz" }; 64static const char *wm8510_deemp[] = { "None", "32kHz", "44.1kHz", "48kHz" };
@@ -298,7 +250,7 @@ static void pll_factors(unsigned int target, unsigned int source)
298 250
299 if ((Ndiv < 6) || (Ndiv > 12)) 251 if ((Ndiv < 6) || (Ndiv > 12))
300 printk(KERN_WARNING 252 printk(KERN_WARNING
301 "WM8510 N value %d outwith recommended range!d\n", 253 "WM8510 N value %u outwith recommended range!d\n",
302 Ndiv); 254 Ndiv);
303 255
304 pll_div.n = Ndiv; 256 pll_div.n = Ndiv;
@@ -327,27 +279,27 @@ static int wm8510_set_dai_pll(struct snd_soc_dai *codec_dai,
327 279
328 if (freq_in == 0 || freq_out == 0) { 280 if (freq_in == 0 || freq_out == 0) {
329 /* Clock CODEC directly from MCLK */ 281 /* Clock CODEC directly from MCLK */
330 reg = wm8510_read_reg_cache(codec, WM8510_CLOCK); 282 reg = snd_soc_read(codec, WM8510_CLOCK);
331 wm8510_write(codec, WM8510_CLOCK, reg & 0x0ff); 283 snd_soc_write(codec, WM8510_CLOCK, reg & 0x0ff);
332 284
333 /* Turn off PLL */ 285 /* Turn off PLL */
334 reg = wm8510_read_reg_cache(codec, WM8510_POWER1); 286 reg = snd_soc_read(codec, WM8510_POWER1);
335 wm8510_write(codec, WM8510_POWER1, reg & 0x1df); 287 snd_soc_write(codec, WM8510_POWER1, reg & 0x1df);
336 return 0; 288 return 0;
337 } 289 }
338 290
339 pll_factors(freq_out*4, freq_in); 291 pll_factors(freq_out*4, freq_in);
340 292
341 wm8510_write(codec, WM8510_PLLN, (pll_div.pre_div << 4) | pll_div.n); 293 snd_soc_write(codec, WM8510_PLLN, (pll_div.pre_div << 4) | pll_div.n);
342 wm8510_write(codec, WM8510_PLLK1, pll_div.k >> 18); 294 snd_soc_write(codec, WM8510_PLLK1, pll_div.k >> 18);
343 wm8510_write(codec, WM8510_PLLK2, (pll_div.k >> 9) & 0x1ff); 295 snd_soc_write(codec, WM8510_PLLK2, (pll_div.k >> 9) & 0x1ff);
344 wm8510_write(codec, WM8510_PLLK3, pll_div.k & 0x1ff); 296 snd_soc_write(codec, WM8510_PLLK3, pll_div.k & 0x1ff);
345 reg = wm8510_read_reg_cache(codec, WM8510_POWER1); 297 reg = snd_soc_read(codec, WM8510_POWER1);
346 wm8510_write(codec, WM8510_POWER1, reg | 0x020); 298 snd_soc_write(codec, WM8510_POWER1, reg | 0x020);
347 299
348 /* Run CODEC from PLL instead of MCLK */ 300 /* Run CODEC from PLL instead of MCLK */
349 reg = wm8510_read_reg_cache(codec, WM8510_CLOCK); 301 reg = snd_soc_read(codec, WM8510_CLOCK);
350 wm8510_write(codec, WM8510_CLOCK, reg | 0x100); 302 snd_soc_write(codec, WM8510_CLOCK, reg | 0x100);
351 303
352 return 0; 304 return 0;
353} 305}
@@ -363,24 +315,24 @@ static int wm8510_set_dai_clkdiv(struct snd_soc_dai *codec_dai,
363 315
364 switch (div_id) { 316 switch (div_id) {
365 case WM8510_OPCLKDIV: 317 case WM8510_OPCLKDIV:
366 reg = wm8510_read_reg_cache(codec, WM8510_GPIO) & 0x1cf; 318 reg = snd_soc_read(codec, WM8510_GPIO) & 0x1cf;
367 wm8510_write(codec, WM8510_GPIO, reg | div); 319 snd_soc_write(codec, WM8510_GPIO, reg | div);
368 break; 320 break;
369 case WM8510_MCLKDIV: 321 case WM8510_MCLKDIV:
370 reg = wm8510_read_reg_cache(codec, WM8510_CLOCK) & 0x11f; 322 reg = snd_soc_read(codec, WM8510_CLOCK) & 0x11f;
371 wm8510_write(codec, WM8510_CLOCK, reg | div); 323 snd_soc_write(codec, WM8510_CLOCK, reg | div);
372 break; 324 break;
373 case WM8510_ADCCLK: 325 case WM8510_ADCCLK:
374 reg = wm8510_read_reg_cache(codec, WM8510_ADC) & 0x1f7; 326 reg = snd_soc_read(codec, WM8510_ADC) & 0x1f7;
375 wm8510_write(codec, WM8510_ADC, reg | div); 327 snd_soc_write(codec, WM8510_ADC, reg | div);
376 break; 328 break;
377 case WM8510_DACCLK: 329 case WM8510_DACCLK:
378 reg = wm8510_read_reg_cache(codec, WM8510_DAC) & 0x1f7; 330 reg = snd_soc_read(codec, WM8510_DAC) & 0x1f7;
379 wm8510_write(codec, WM8510_DAC, reg | div); 331 snd_soc_write(codec, WM8510_DAC, reg | div);
380 break; 332 break;
381 case WM8510_BCLKDIV: 333 case WM8510_BCLKDIV:
382 reg = wm8510_read_reg_cache(codec, WM8510_CLOCK) & 0x1e3; 334 reg = snd_soc_read(codec, WM8510_CLOCK) & 0x1e3;
383 wm8510_write(codec, WM8510_CLOCK, reg | div); 335 snd_soc_write(codec, WM8510_CLOCK, reg | div);
384 break; 336 break;
385 default: 337 default:
386 return -EINVAL; 338 return -EINVAL;
@@ -394,7 +346,7 @@ static int wm8510_set_dai_fmt(struct snd_soc_dai *codec_dai,
394{ 346{
395 struct snd_soc_codec *codec = codec_dai->codec; 347 struct snd_soc_codec *codec = codec_dai->codec;
396 u16 iface = 0; 348 u16 iface = 0;
397 u16 clk = wm8510_read_reg_cache(codec, WM8510_CLOCK) & 0x1fe; 349 u16 clk = snd_soc_read(codec, WM8510_CLOCK) & 0x1fe;
398 350
399 /* set master/slave audio interface */ 351 /* set master/slave audio interface */
400 switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { 352 switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
@@ -441,8 +393,8 @@ static int wm8510_set_dai_fmt(struct snd_soc_dai *codec_dai,
441 return -EINVAL; 393 return -EINVAL;
442 } 394 }
443 395
444 wm8510_write(codec, WM8510_IFACE, iface); 396 snd_soc_write(codec, WM8510_IFACE, iface);
445 wm8510_write(codec, WM8510_CLOCK, clk); 397 snd_soc_write(codec, WM8510_CLOCK, clk);
446 return 0; 398 return 0;
447} 399}
448 400
@@ -453,8 +405,8 @@ static int wm8510_pcm_hw_params(struct snd_pcm_substream *substream,
453 struct snd_soc_pcm_runtime *rtd = substream->private_data; 405 struct snd_soc_pcm_runtime *rtd = substream->private_data;
454 struct snd_soc_device *socdev = rtd->socdev; 406 struct snd_soc_device *socdev = rtd->socdev;
455 struct snd_soc_codec *codec = socdev->card->codec; 407 struct snd_soc_codec *codec = socdev->card->codec;
456 u16 iface = wm8510_read_reg_cache(codec, WM8510_IFACE) & 0x19f; 408 u16 iface = snd_soc_read(codec, WM8510_IFACE) & 0x19f;
457 u16 adn = wm8510_read_reg_cache(codec, WM8510_ADD) & 0x1f1; 409 u16 adn = snd_soc_read(codec, WM8510_ADD) & 0x1f1;
458 410
459 /* bit size */ 411 /* bit size */
460 switch (params_format(params)) { 412 switch (params_format(params)) {
@@ -493,20 +445,20 @@ static int wm8510_pcm_hw_params(struct snd_pcm_substream *substream,
493 break; 445 break;
494 } 446 }
495 447
496 wm8510_write(codec, WM8510_IFACE, iface); 448 snd_soc_write(codec, WM8510_IFACE, iface);
497 wm8510_write(codec, WM8510_ADD, adn); 449 snd_soc_write(codec, WM8510_ADD, adn);
498 return 0; 450 return 0;
499} 451}
500 452
501static int wm8510_mute(struct snd_soc_dai *dai, int mute) 453static int wm8510_mute(struct snd_soc_dai *dai, int mute)
502{ 454{
503 struct snd_soc_codec *codec = dai->codec; 455 struct snd_soc_codec *codec = dai->codec;
504 u16 mute_reg = wm8510_read_reg_cache(codec, WM8510_DAC) & 0xffbf; 456 u16 mute_reg = snd_soc_read(codec, WM8510_DAC) & 0xffbf;
505 457
506 if (mute) 458 if (mute)
507 wm8510_write(codec, WM8510_DAC, mute_reg | 0x40); 459 snd_soc_write(codec, WM8510_DAC, mute_reg | 0x40);
508 else 460 else
509 wm8510_write(codec, WM8510_DAC, mute_reg); 461 snd_soc_write(codec, WM8510_DAC, mute_reg);
510 return 0; 462 return 0;
511} 463}
512 464
@@ -514,13 +466,13 @@ static int wm8510_mute(struct snd_soc_dai *dai, int mute)
514static int wm8510_set_bias_level(struct snd_soc_codec *codec, 466static int wm8510_set_bias_level(struct snd_soc_codec *codec,
515 enum snd_soc_bias_level level) 467 enum snd_soc_bias_level level)
516{ 468{
517 u16 power1 = wm8510_read_reg_cache(codec, WM8510_POWER1) & ~0x3; 469 u16 power1 = snd_soc_read(codec, WM8510_POWER1) & ~0x3;
518 470
519 switch (level) { 471 switch (level) {
520 case SND_SOC_BIAS_ON: 472 case SND_SOC_BIAS_ON:
521 case SND_SOC_BIAS_PREPARE: 473 case SND_SOC_BIAS_PREPARE:
522 power1 |= 0x1; /* VMID 50k */ 474 power1 |= 0x1; /* VMID 50k */
523 wm8510_write(codec, WM8510_POWER1, power1); 475 snd_soc_write(codec, WM8510_POWER1, power1);
524 break; 476 break;
525 477
526 case SND_SOC_BIAS_STANDBY: 478 case SND_SOC_BIAS_STANDBY:
@@ -528,18 +480,18 @@ static int wm8510_set_bias_level(struct snd_soc_codec *codec,
528 480
529 if (codec->bias_level == SND_SOC_BIAS_OFF) { 481 if (codec->bias_level == SND_SOC_BIAS_OFF) {
530 /* Initial cap charge at VMID 5k */ 482 /* Initial cap charge at VMID 5k */
531 wm8510_write(codec, WM8510_POWER1, power1 | 0x3); 483 snd_soc_write(codec, WM8510_POWER1, power1 | 0x3);
532 mdelay(100); 484 mdelay(100);
533 } 485 }
534 486
535 power1 |= 0x2; /* VMID 500k */ 487 power1 |= 0x2; /* VMID 500k */
536 wm8510_write(codec, WM8510_POWER1, power1); 488 snd_soc_write(codec, WM8510_POWER1, power1);
537 break; 489 break;
538 490
539 case SND_SOC_BIAS_OFF: 491 case SND_SOC_BIAS_OFF:
540 wm8510_write(codec, WM8510_POWER1, 0); 492 snd_soc_write(codec, WM8510_POWER1, 0);
541 wm8510_write(codec, WM8510_POWER2, 0); 493 snd_soc_write(codec, WM8510_POWER2, 0);
542 wm8510_write(codec, WM8510_POWER3, 0); 494 snd_soc_write(codec, WM8510_POWER3, 0);
543 break; 495 break;
544 } 496 }
545 497
@@ -577,6 +529,7 @@ struct snd_soc_dai wm8510_dai = {
577 .rates = WM8510_RATES, 529 .rates = WM8510_RATES,
578 .formats = WM8510_FORMATS,}, 530 .formats = WM8510_FORMATS,},
579 .ops = &wm8510_dai_ops, 531 .ops = &wm8510_dai_ops,
532 .symmetric_rates = 1,
580}; 533};
581EXPORT_SYMBOL_GPL(wm8510_dai); 534EXPORT_SYMBOL_GPL(wm8510_dai);
582 535
@@ -612,15 +565,14 @@ static int wm8510_resume(struct platform_device *pdev)
612 * initialise the WM8510 driver 565 * initialise the WM8510 driver
613 * register the mixer and dsp interfaces with the kernel 566 * register the mixer and dsp interfaces with the kernel
614 */ 567 */
615static int wm8510_init(struct snd_soc_device *socdev) 568static int wm8510_init(struct snd_soc_device *socdev,
569 enum snd_soc_control_type control)
616{ 570{
617 struct snd_soc_codec *codec = socdev->card->codec; 571 struct snd_soc_codec *codec = socdev->card->codec;
618 int ret = 0; 572 int ret = 0;
619 573
620 codec->name = "WM8510"; 574 codec->name = "WM8510";
621 codec->owner = THIS_MODULE; 575 codec->owner = THIS_MODULE;
622 codec->read = wm8510_read_reg_cache;
623 codec->write = wm8510_write;
624 codec->set_bias_level = wm8510_set_bias_level; 576 codec->set_bias_level = wm8510_set_bias_level;
625 codec->dai = &wm8510_dai; 577 codec->dai = &wm8510_dai;
626 codec->num_dai = 1; 578 codec->num_dai = 1;
@@ -630,13 +582,20 @@ static int wm8510_init(struct snd_soc_device *socdev)
630 if (codec->reg_cache == NULL) 582 if (codec->reg_cache == NULL)
631 return -ENOMEM; 583 return -ENOMEM;
632 584
585 ret = snd_soc_codec_set_cache_io(codec, 7, 9, control);
586 if (ret < 0) {
587 printk(KERN_ERR "wm8510: failed to set cache I/O: %d\n",
588 ret);
589 goto err;
590 }
591
633 wm8510_reset(codec); 592 wm8510_reset(codec);
634 593
635 /* register pcms */ 594 /* register pcms */
636 ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1); 595 ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1);
637 if (ret < 0) { 596 if (ret < 0) {
638 printk(KERN_ERR "wm8510: failed to create pcms\n"); 597 printk(KERN_ERR "wm8510: failed to create pcms\n");
639 goto pcm_err; 598 goto err;
640 } 599 }
641 600
642 /* power on device */ 601 /* power on device */
@@ -655,7 +614,7 @@ static int wm8510_init(struct snd_soc_device *socdev)
655card_err: 614card_err:
656 snd_soc_free_pcms(socdev); 615 snd_soc_free_pcms(socdev);
657 snd_soc_dapm_free(socdev); 616 snd_soc_dapm_free(socdev);
658pcm_err: 617err:
659 kfree(codec->reg_cache); 618 kfree(codec->reg_cache);
660 return ret; 619 return ret;
661} 620}
@@ -678,7 +637,7 @@ static int wm8510_i2c_probe(struct i2c_client *i2c,
678 i2c_set_clientdata(i2c, codec); 637 i2c_set_clientdata(i2c, codec);
679 codec->control_data = i2c; 638 codec->control_data = i2c;
680 639
681 ret = wm8510_init(socdev); 640 ret = wm8510_init(socdev, SND_SOC_I2C);
682 if (ret < 0) 641 if (ret < 0)
683 pr_err("failed to initialise WM8510\n"); 642 pr_err("failed to initialise WM8510\n");
684 643
@@ -758,7 +717,7 @@ static int __devinit wm8510_spi_probe(struct spi_device *spi)
758 717
759 codec->control_data = spi; 718 codec->control_data = spi;
760 719
761 ret = wm8510_init(socdev); 720 ret = wm8510_init(socdev, SND_SOC_SPI);
762 if (ret < 0) 721 if (ret < 0)
763 dev_err(&spi->dev, "failed to initialise WM8510\n"); 722 dev_err(&spi->dev, "failed to initialise WM8510\n");
764 723
@@ -779,30 +738,6 @@ static struct spi_driver wm8510_spi_driver = {
779 .probe = wm8510_spi_probe, 738 .probe = wm8510_spi_probe,
780 .remove = __devexit_p(wm8510_spi_remove), 739 .remove = __devexit_p(wm8510_spi_remove),
781}; 740};
782
783static int wm8510_spi_write(struct spi_device *spi, const char *data, int len)
784{
785 struct spi_transfer t;
786 struct spi_message m;
787 u8 msg[2];
788
789 if (len <= 0)
790 return 0;
791
792 msg[0] = data[0];
793 msg[1] = data[1];
794
795 spi_message_init(&m);
796 memset(&t, 0, (sizeof t));
797
798 t.tx_buf = &msg[0];
799 t.len = len;
800
801 spi_message_add_tail(&t, &m);
802 spi_sync(spi, &m);
803
804 return len;
805}
806#endif /* CONFIG_SPI_MASTER */ 741#endif /* CONFIG_SPI_MASTER */
807 742
808static int wm8510_probe(struct platform_device *pdev) 743static int wm8510_probe(struct platform_device *pdev)
@@ -827,13 +762,11 @@ static int wm8510_probe(struct platform_device *pdev)
827 wm8510_socdev = socdev; 762 wm8510_socdev = socdev;
828#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) 763#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
829 if (setup->i2c_address) { 764 if (setup->i2c_address) {
830 codec->hw_write = (hw_write_t)i2c_master_send;
831 ret = wm8510_add_i2c_device(pdev, setup); 765 ret = wm8510_add_i2c_device(pdev, setup);
832 } 766 }
833#endif 767#endif
834#if defined(CONFIG_SPI_MASTER) 768#if defined(CONFIG_SPI_MASTER)
835 if (setup->spi) { 769 if (setup->spi) {
836 codec->hw_write = (hw_write_t)wm8510_spi_write;
837 ret = spi_register_driver(&wm8510_spi_driver); 770 ret = spi_register_driver(&wm8510_spi_driver);
838 if (ret != 0) 771 if (ret != 0)
839 printk(KERN_ERR "can't add spi driver"); 772 printk(KERN_ERR "can't add spi driver");
diff --git a/sound/soc/codecs/wm8523.c b/sound/soc/codecs/wm8523.c
new file mode 100644
index 000000000000..25870a4652fb
--- /dev/null
+++ b/sound/soc/codecs/wm8523.c
@@ -0,0 +1,699 @@
1/*
2 * wm8523.c -- WM8523 ALSA SoC Audio driver
3 *
4 * Copyright 2009 Wolfson Microelectronics plc
5 *
6 * Author: Mark Brown <broonie@opensource.wolfsonmicro.com>
7 *
8 *
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License version 2 as
11 * published by the Free Software Foundation.
12 */
13
14#include <linux/module.h>
15#include <linux/moduleparam.h>
16#include <linux/init.h>
17#include <linux/delay.h>
18#include <linux/pm.h>
19#include <linux/i2c.h>
20#include <linux/platform_device.h>
21#include <linux/regulator/consumer.h>
22#include <sound/core.h>
23#include <sound/pcm.h>
24#include <sound/pcm_params.h>
25#include <sound/soc.h>
26#include <sound/soc-dapm.h>
27#include <sound/initval.h>
28#include <sound/tlv.h>
29
30#include "wm8523.h"
31
32static struct snd_soc_codec *wm8523_codec;
33struct snd_soc_codec_device soc_codec_dev_wm8523;
34
35#define WM8523_NUM_SUPPLIES 2
36static const char *wm8523_supply_names[WM8523_NUM_SUPPLIES] = {
37 "AVDD",
38 "LINEVDD",
39};
40
41#define WM8523_NUM_RATES 7
42
43/* codec private data */
44struct wm8523_priv {
45 struct snd_soc_codec codec;
46 u16 reg_cache[WM8523_REGISTER_COUNT];
47 struct regulator_bulk_data supplies[WM8523_NUM_SUPPLIES];
48 unsigned int sysclk;
49 unsigned int rate_constraint_list[WM8523_NUM_RATES];
50 struct snd_pcm_hw_constraint_list rate_constraint;
51};
52
53static const u16 wm8523_reg[WM8523_REGISTER_COUNT] = {
54 0x8523, /* R0 - DEVICE_ID */
55 0x0001, /* R1 - REVISION */
56 0x0000, /* R2 - PSCTRL1 */
57 0x1812, /* R3 - AIF_CTRL1 */
58 0x0000, /* R4 - AIF_CTRL2 */
59 0x0001, /* R5 - DAC_CTRL3 */
60 0x0190, /* R6 - DAC_GAINL */
61 0x0190, /* R7 - DAC_GAINR */
62 0x0000, /* R8 - ZERO_DETECT */
63};
64
65static int wm8523_volatile_register(unsigned int reg)
66{
67 switch (reg) {
68 case WM8523_DEVICE_ID:
69 case WM8523_REVISION:
70 return 1;
71 default:
72 return 0;
73 }
74}
75
76static int wm8523_reset(struct snd_soc_codec *codec)
77{
78 return snd_soc_write(codec, WM8523_DEVICE_ID, 0);
79}
80
81static const DECLARE_TLV_DB_SCALE(dac_tlv, -10000, 25, 0);
82
83static const char *wm8523_zd_count_text[] = {
84 "1024",
85 "2048",
86};
87
88static const struct soc_enum wm8523_zc_count =
89 SOC_ENUM_SINGLE(WM8523_ZERO_DETECT, 0, 2, wm8523_zd_count_text);
90
91static const struct snd_kcontrol_new wm8523_snd_controls[] = {
92SOC_DOUBLE_R_TLV("Playback Volume", WM8523_DAC_GAINL, WM8523_DAC_GAINR,
93 0, 448, 0, dac_tlv),
94SOC_SINGLE("ZC Switch", WM8523_DAC_CTRL3, 4, 1, 0),
95SOC_SINGLE("Playback Deemphasis Switch", WM8523_AIF_CTRL1, 8, 1, 0),
96SOC_DOUBLE("Playback Switch", WM8523_DAC_CTRL3, 2, 3, 1, 1),
97SOC_SINGLE("Volume Ramp Up Switch", WM8523_DAC_CTRL3, 1, 1, 0),
98SOC_SINGLE("Volume Ramp Down Switch", WM8523_DAC_CTRL3, 0, 1, 0),
99SOC_ENUM("Zero Detect Count", wm8523_zc_count),
100};
101
102static const struct snd_soc_dapm_widget wm8523_dapm_widgets[] = {
103SND_SOC_DAPM_DAC("DAC", "Playback", SND_SOC_NOPM, 0, 0),
104SND_SOC_DAPM_OUTPUT("LINEVOUTL"),
105SND_SOC_DAPM_OUTPUT("LINEVOUTR"),
106};
107
108static const struct snd_soc_dapm_route intercon[] = {
109 { "LINEVOUTL", NULL, "DAC" },
110 { "LINEVOUTR", NULL, "DAC" },
111};
112
113static int wm8523_add_widgets(struct snd_soc_codec *codec)
114{
115 snd_soc_dapm_new_controls(codec, wm8523_dapm_widgets,
116 ARRAY_SIZE(wm8523_dapm_widgets));
117
118 snd_soc_dapm_add_routes(codec, intercon, ARRAY_SIZE(intercon));
119
120 snd_soc_dapm_new_widgets(codec);
121 return 0;
122}
123
124static struct {
125 int value;
126 int ratio;
127} lrclk_ratios[WM8523_NUM_RATES] = {
128 { 1, 128 },
129 { 2, 192 },
130 { 3, 256 },
131 { 4, 384 },
132 { 5, 512 },
133 { 6, 768 },
134 { 7, 1152 },
135};
136
137static int wm8523_startup(struct snd_pcm_substream *substream,
138 struct snd_soc_dai *dai)
139{
140 struct snd_soc_codec *codec = dai->codec;
141 struct wm8523_priv *wm8523 = codec->private_data;
142
143 /* The set of sample rates that can be supported depends on the
144 * MCLK supplied to the CODEC - enforce this.
145 */
146 if (!wm8523->sysclk) {
147 dev_err(codec->dev,
148 "No MCLK configured, call set_sysclk() on init\n");
149 return -EINVAL;
150 }
151
152 return 0;
153 snd_pcm_hw_constraint_list(substream->runtime, 0,
154 SNDRV_PCM_HW_PARAM_RATE,
155 &wm8523->rate_constraint);
156
157 return 0;
158}
159
160static int wm8523_hw_params(struct snd_pcm_substream *substream,
161 struct snd_pcm_hw_params *params,
162 struct snd_soc_dai *dai)
163{
164 struct snd_soc_pcm_runtime *rtd = substream->private_data;
165 struct snd_soc_device *socdev = rtd->socdev;
166 struct snd_soc_codec *codec = socdev->card->codec;
167 struct wm8523_priv *wm8523 = codec->private_data;
168 int i;
169 u16 aifctrl1 = snd_soc_read(codec, WM8523_AIF_CTRL1);
170 u16 aifctrl2 = snd_soc_read(codec, WM8523_AIF_CTRL2);
171
172 /* Find a supported LRCLK ratio */
173 for (i = 0; i < ARRAY_SIZE(lrclk_ratios); i++) {
174 if (wm8523->sysclk / params_rate(params) ==
175 lrclk_ratios[i].ratio)
176 break;
177 }
178
179 /* Should never happen, should be handled by constraints */
180 if (i == ARRAY_SIZE(lrclk_ratios)) {
181 dev_err(codec->dev, "MCLK/fs ratio %d unsupported\n",
182 wm8523->sysclk / params_rate(params));
183 return -EINVAL;
184 }
185
186 aifctrl2 &= ~WM8523_SR_MASK;
187 aifctrl2 |= lrclk_ratios[i].value;
188
189 aifctrl1 &= ~WM8523_WL_MASK;
190 switch (params_format(params)) {
191 case SNDRV_PCM_FORMAT_S16_LE:
192 break;
193 case SNDRV_PCM_FORMAT_S20_3LE:
194 aifctrl1 |= 0x8;
195 break;
196 case SNDRV_PCM_FORMAT_S24_LE:
197 aifctrl1 |= 0x10;
198 break;
199 case SNDRV_PCM_FORMAT_S32_LE:
200 aifctrl1 |= 0x18;
201 break;
202 }
203
204 snd_soc_write(codec, WM8523_AIF_CTRL1, aifctrl1);
205 snd_soc_write(codec, WM8523_AIF_CTRL2, aifctrl2);
206
207 return 0;
208}
209
210static int wm8523_set_dai_sysclk(struct snd_soc_dai *codec_dai,
211 int clk_id, unsigned int freq, int dir)
212{
213 struct snd_soc_codec *codec = codec_dai->codec;
214 struct wm8523_priv *wm8523 = codec->private_data;
215 unsigned int val;
216 int i;
217
218 wm8523->sysclk = freq;
219
220 wm8523->rate_constraint.count = 0;
221 for (i = 0; i < ARRAY_SIZE(lrclk_ratios); i++) {
222 val = freq / lrclk_ratios[i].ratio;
223 /* Check that it's a standard rate since core can't
224 * cope with others and having the odd rates confuses
225 * constraint matching.
226 */
227 switch (val) {
228 case 8000:
229 case 11025:
230 case 16000:
231 case 22050:
232 case 32000:
233 case 44100:
234 case 48000:
235 case 64000:
236 case 88200:
237 case 96000:
238 case 176400:
239 case 192000:
240 dev_dbg(codec->dev, "Supported sample rate: %dHz\n",
241 val);
242 wm8523->rate_constraint_list[i] = val;
243 wm8523->rate_constraint.count++;
244 break;
245 default:
246 dev_dbg(codec->dev, "Skipping sample rate: %dHz\n",
247 val);
248 }
249 }
250
251 /* Need at least one supported rate... */
252 if (wm8523->rate_constraint.count == 0)
253 return -EINVAL;
254
255 return 0;
256}
257
258
259static int wm8523_set_dai_fmt(struct snd_soc_dai *codec_dai,
260 unsigned int fmt)
261{
262 struct snd_soc_codec *codec = codec_dai->codec;
263 u16 aifctrl1 = snd_soc_read(codec, WM8523_AIF_CTRL1);
264
265 aifctrl1 &= ~(WM8523_BCLK_INV_MASK | WM8523_LRCLK_INV_MASK |
266 WM8523_FMT_MASK | WM8523_AIF_MSTR_MASK);
267
268 switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
269 case SND_SOC_DAIFMT_CBM_CFM:
270 aifctrl1 |= WM8523_AIF_MSTR;
271 break;
272 case SND_SOC_DAIFMT_CBS_CFS:
273 break;
274 default:
275 return -EINVAL;
276 }
277
278 switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
279 case SND_SOC_DAIFMT_I2S:
280 aifctrl1 |= 0x0002;
281 break;
282 case SND_SOC_DAIFMT_RIGHT_J:
283 break;
284 case SND_SOC_DAIFMT_LEFT_J:
285 aifctrl1 |= 0x0001;
286 break;
287 case SND_SOC_DAIFMT_DSP_A:
288 aifctrl1 |= 0x0003;
289 break;
290 case SND_SOC_DAIFMT_DSP_B:
291 aifctrl1 |= 0x0023;
292 break;
293 default:
294 return -EINVAL;
295 }
296
297 switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
298 case SND_SOC_DAIFMT_NB_NF:
299 break;
300 case SND_SOC_DAIFMT_IB_IF:
301 aifctrl1 |= WM8523_BCLK_INV | WM8523_LRCLK_INV;
302 break;
303 case SND_SOC_DAIFMT_IB_NF:
304 aifctrl1 |= WM8523_BCLK_INV;
305 break;
306 case SND_SOC_DAIFMT_NB_IF:
307 aifctrl1 |= WM8523_LRCLK_INV;
308 break;
309 default:
310 return -EINVAL;
311 }
312
313 snd_soc_write(codec, WM8523_AIF_CTRL1, aifctrl1);
314
315 return 0;
316}
317
318static int wm8523_set_bias_level(struct snd_soc_codec *codec,
319 enum snd_soc_bias_level level)
320{
321 struct wm8523_priv *wm8523 = codec->private_data;
322 int ret, i;
323
324 switch (level) {
325 case SND_SOC_BIAS_ON:
326 break;
327
328 case SND_SOC_BIAS_PREPARE:
329 /* Full power on */
330 snd_soc_update_bits(codec, WM8523_PSCTRL1,
331 WM8523_SYS_ENA_MASK, 3);
332 break;
333
334 case SND_SOC_BIAS_STANDBY:
335 if (codec->bias_level == SND_SOC_BIAS_OFF) {
336 ret = regulator_bulk_enable(ARRAY_SIZE(wm8523->supplies),
337 wm8523->supplies);
338 if (ret != 0) {
339 dev_err(codec->dev,
340 "Failed to enable supplies: %d\n",
341 ret);
342 return ret;
343 }
344
345 /* Initial power up */
346 snd_soc_update_bits(codec, WM8523_PSCTRL1,
347 WM8523_SYS_ENA_MASK, 1);
348
349 /* Sync back default/cached values */
350 for (i = WM8523_AIF_CTRL1;
351 i < WM8523_MAX_REGISTER; i++)
352 snd_soc_write(codec, i, wm8523->reg_cache[i]);
353
354
355 msleep(100);
356 }
357
358 /* Power up to mute */
359 snd_soc_update_bits(codec, WM8523_PSCTRL1,
360 WM8523_SYS_ENA_MASK, 2);
361
362 break;
363
364 case SND_SOC_BIAS_OFF:
365 /* The chip runs through the power down sequence for us. */
366 snd_soc_update_bits(codec, WM8523_PSCTRL1,
367 WM8523_SYS_ENA_MASK, 0);
368 msleep(100);
369
370 regulator_bulk_disable(ARRAY_SIZE(wm8523->supplies),
371 wm8523->supplies);
372 break;
373 }
374 codec->bias_level = level;
375 return 0;
376}
377
378#define WM8523_RATES SNDRV_PCM_RATE_8000_192000
379
380#define WM8523_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE |\
381 SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S32_LE)
382
383static struct snd_soc_dai_ops wm8523_dai_ops = {
384 .startup = wm8523_startup,
385 .hw_params = wm8523_hw_params,
386 .set_sysclk = wm8523_set_dai_sysclk,
387 .set_fmt = wm8523_set_dai_fmt,
388};
389
390struct snd_soc_dai wm8523_dai = {
391 .name = "WM8523",
392 .playback = {
393 .stream_name = "Playback",
394 .channels_min = 2, /* Mono modes not yet supported */
395 .channels_max = 2,
396 .rates = WM8523_RATES,
397 .formats = WM8523_FORMATS,
398 },
399 .ops = &wm8523_dai_ops,
400};
401EXPORT_SYMBOL_GPL(wm8523_dai);
402
403#ifdef CONFIG_PM
404static int wm8523_suspend(struct platform_device *pdev, pm_message_t state)
405{
406 struct snd_soc_device *socdev = platform_get_drvdata(pdev);
407 struct snd_soc_codec *codec = socdev->card->codec;
408
409 wm8523_set_bias_level(codec, SND_SOC_BIAS_OFF);
410 return 0;
411}
412
413static int wm8523_resume(struct platform_device *pdev)
414{
415 struct snd_soc_device *socdev = platform_get_drvdata(pdev);
416 struct snd_soc_codec *codec = socdev->card->codec;
417
418 wm8523_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
419
420 return 0;
421}
422#else
423#define wm8523_suspend NULL
424#define wm8523_resume NULL
425#endif
426
427static int wm8523_probe(struct platform_device *pdev)
428{
429 struct snd_soc_device *socdev = platform_get_drvdata(pdev);
430 struct snd_soc_codec *codec;
431 int ret = 0;
432
433 if (wm8523_codec == NULL) {
434 dev_err(&pdev->dev, "Codec device not registered\n");
435 return -ENODEV;
436 }
437
438 socdev->card->codec = wm8523_codec;
439 codec = wm8523_codec;
440
441 /* register pcms */
442 ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1);
443 if (ret < 0) {
444 dev_err(codec->dev, "failed to create pcms: %d\n", ret);
445 goto pcm_err;
446 }
447
448 snd_soc_add_controls(codec, wm8523_snd_controls,
449 ARRAY_SIZE(wm8523_snd_controls));
450 wm8523_add_widgets(codec);
451 ret = snd_soc_init_card(socdev);
452 if (ret < 0) {
453 dev_err(codec->dev, "failed to register card: %d\n", ret);
454 goto card_err;
455 }
456
457 return ret;
458
459card_err:
460 snd_soc_free_pcms(socdev);
461 snd_soc_dapm_free(socdev);
462pcm_err:
463 return ret;
464}
465
466static int wm8523_remove(struct platform_device *pdev)
467{
468 struct snd_soc_device *socdev = platform_get_drvdata(pdev);
469
470 snd_soc_free_pcms(socdev);
471 snd_soc_dapm_free(socdev);
472
473 return 0;
474}
475
476struct snd_soc_codec_device soc_codec_dev_wm8523 = {
477 .probe = wm8523_probe,
478 .remove = wm8523_remove,
479 .suspend = wm8523_suspend,
480 .resume = wm8523_resume,
481};
482EXPORT_SYMBOL_GPL(soc_codec_dev_wm8523);
483
484static int wm8523_register(struct wm8523_priv *wm8523,
485 enum snd_soc_control_type control)
486{
487 int ret;
488 struct snd_soc_codec *codec = &wm8523->codec;
489 int i;
490
491 if (wm8523_codec) {
492 dev_err(codec->dev, "Another WM8523 is registered\n");
493 return -EINVAL;
494 }
495
496 mutex_init(&codec->mutex);
497 INIT_LIST_HEAD(&codec->dapm_widgets);
498 INIT_LIST_HEAD(&codec->dapm_paths);
499
500 codec->private_data = wm8523;
501 codec->name = "WM8523";
502 codec->owner = THIS_MODULE;
503 codec->bias_level = SND_SOC_BIAS_OFF;
504 codec->set_bias_level = wm8523_set_bias_level;
505 codec->dai = &wm8523_dai;
506 codec->num_dai = 1;
507 codec->reg_cache_size = WM8523_REGISTER_COUNT;
508 codec->reg_cache = &wm8523->reg_cache;
509 codec->volatile_register = wm8523_volatile_register;
510
511 wm8523->rate_constraint.list = &wm8523->rate_constraint_list[0];
512 wm8523->rate_constraint.count =
513 ARRAY_SIZE(wm8523->rate_constraint_list);
514
515 memcpy(codec->reg_cache, wm8523_reg, sizeof(wm8523_reg));
516
517 ret = snd_soc_codec_set_cache_io(codec, 8, 16, control);
518 if (ret != 0) {
519 dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret);
520 goto err;
521 }
522
523 for (i = 0; i < ARRAY_SIZE(wm8523->supplies); i++)
524 wm8523->supplies[i].supply = wm8523_supply_names[i];
525
526 ret = regulator_bulk_get(codec->dev, ARRAY_SIZE(wm8523->supplies),
527 wm8523->supplies);
528 if (ret != 0) {
529 dev_err(codec->dev, "Failed to request supplies: %d\n", ret);
530 goto err;
531 }
532
533 ret = regulator_bulk_enable(ARRAY_SIZE(wm8523->supplies),
534 wm8523->supplies);
535 if (ret != 0) {
536 dev_err(codec->dev, "Failed to enable supplies: %d\n", ret);
537 goto err_get;
538 }
539
540 ret = snd_soc_read(codec, WM8523_DEVICE_ID);
541 if (ret < 0) {
542 dev_err(codec->dev, "Failed to read ID register\n");
543 goto err_enable;
544 }
545 if (ret != wm8523_reg[WM8523_DEVICE_ID]) {
546 dev_err(codec->dev, "Device is not a WM8523, ID is %x\n", ret);
547 ret = -EINVAL;
548 goto err_enable;
549 }
550
551 ret = snd_soc_read(codec, WM8523_REVISION);
552 if (ret < 0) {
553 dev_err(codec->dev, "Failed to read revision register\n");
554 goto err_enable;
555 }
556 dev_info(codec->dev, "revision %c\n",
557 (ret & WM8523_CHIP_REV_MASK) + 'A');
558
559 ret = wm8523_reset(codec);
560 if (ret < 0) {
561 dev_err(codec->dev, "Failed to issue reset\n");
562 goto err_enable;
563 }
564
565 wm8523_dai.dev = codec->dev;
566
567 /* Change some default settings - latch VU and enable ZC */
568 wm8523->reg_cache[WM8523_DAC_GAINR] |= WM8523_DACR_VU;
569 wm8523->reg_cache[WM8523_DAC_CTRL3] |= WM8523_ZC;
570
571 wm8523_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
572
573 /* Bias level configuration will have done an extra enable */
574 regulator_bulk_disable(ARRAY_SIZE(wm8523->supplies), wm8523->supplies);
575
576 wm8523_codec = codec;
577
578 ret = snd_soc_register_codec(codec);
579 if (ret != 0) {
580 dev_err(codec->dev, "Failed to register codec: %d\n", ret);
581 return ret;
582 }
583
584 ret = snd_soc_register_dai(&wm8523_dai);
585 if (ret != 0) {
586 dev_err(codec->dev, "Failed to register DAI: %d\n", ret);
587 snd_soc_unregister_codec(codec);
588 return ret;
589 }
590
591 return 0;
592
593err_enable:
594 regulator_bulk_disable(ARRAY_SIZE(wm8523->supplies), wm8523->supplies);
595err_get:
596 regulator_bulk_free(ARRAY_SIZE(wm8523->supplies), wm8523->supplies);
597err:
598 kfree(wm8523);
599 return ret;
600}
601
602static void wm8523_unregister(struct wm8523_priv *wm8523)
603{
604 wm8523_set_bias_level(&wm8523->codec, SND_SOC_BIAS_OFF);
605 regulator_bulk_free(ARRAY_SIZE(wm8523->supplies), wm8523->supplies);
606 snd_soc_unregister_dai(&wm8523_dai);
607 snd_soc_unregister_codec(&wm8523->codec);
608 kfree(wm8523);
609 wm8523_codec = NULL;
610}
611
612#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
613static __devinit int wm8523_i2c_probe(struct i2c_client *i2c,
614 const struct i2c_device_id *id)
615{
616 struct wm8523_priv *wm8523;
617 struct snd_soc_codec *codec;
618
619 wm8523 = kzalloc(sizeof(struct wm8523_priv), GFP_KERNEL);
620 if (wm8523 == NULL)
621 return -ENOMEM;
622
623 codec = &wm8523->codec;
624 codec->hw_write = (hw_write_t)i2c_master_send;
625
626 i2c_set_clientdata(i2c, wm8523);
627 codec->control_data = i2c;
628
629 codec->dev = &i2c->dev;
630
631 return wm8523_register(wm8523, SND_SOC_I2C);
632}
633
634static __devexit int wm8523_i2c_remove(struct i2c_client *client)
635{
636 struct wm8523_priv *wm8523 = i2c_get_clientdata(client);
637 wm8523_unregister(wm8523);
638 return 0;
639}
640
641#ifdef CONFIG_PM
642static int wm8523_i2c_suspend(struct i2c_client *i2c, pm_message_t msg)
643{
644 return snd_soc_suspend_device(&i2c->dev);
645}
646
647static int wm8523_i2c_resume(struct i2c_client *i2c)
648{
649 return snd_soc_resume_device(&i2c->dev);
650}
651#else
652#define wm8523_i2c_suspend NULL
653#define wm8523_i2c_resume NULL
654#endif
655
656static const struct i2c_device_id wm8523_i2c_id[] = {
657 { "wm8523", 0 },
658 { }
659};
660MODULE_DEVICE_TABLE(i2c, wm8523_i2c_id);
661
662static struct i2c_driver wm8523_i2c_driver = {
663 .driver = {
664 .name = "WM8523",
665 .owner = THIS_MODULE,
666 },
667 .probe = wm8523_i2c_probe,
668 .remove = __devexit_p(wm8523_i2c_remove),
669 .suspend = wm8523_i2c_suspend,
670 .resume = wm8523_i2c_resume,
671 .id_table = wm8523_i2c_id,
672};
673#endif
674
675static int __init wm8523_modinit(void)
676{
677 int ret;
678#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
679 ret = i2c_add_driver(&wm8523_i2c_driver);
680 if (ret != 0) {
681 printk(KERN_ERR "Failed to register WM8523 I2C driver: %d\n",
682 ret);
683 }
684#endif
685 return 0;
686}
687module_init(wm8523_modinit);
688
689static void __exit wm8523_exit(void)
690{
691#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
692 i2c_del_driver(&wm8523_i2c_driver);
693#endif
694}
695module_exit(wm8523_exit);
696
697MODULE_DESCRIPTION("ASoC WM8523 driver");
698MODULE_AUTHOR("Mark Brown <broonie@opensource.wolfsonmicro.com>");
699MODULE_LICENSE("GPL");
diff --git a/sound/soc/codecs/wm8523.h b/sound/soc/codecs/wm8523.h
new file mode 100644
index 000000000000..1aa9ce3e1357
--- /dev/null
+++ b/sound/soc/codecs/wm8523.h
@@ -0,0 +1,160 @@
1/*
2 * wm8523.h -- WM8423 ASoC driver
3 *
4 * Copyright 2009 Wolfson Microelectronics, plc
5 *
6 * Author: Mark Brown <broonie@opensource.wolfsonmicro.com>
7 *
8 * Based on wm8753.h
9 *
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License version 2 as
12 * published by the Free Software Foundation.
13 */
14
15#ifndef _WM8523_H
16#define _WM8523_H
17
18/*
19 * Register values.
20 */
21#define WM8523_DEVICE_ID 0x00
22#define WM8523_REVISION 0x01
23#define WM8523_PSCTRL1 0x02
24#define WM8523_AIF_CTRL1 0x03
25#define WM8523_AIF_CTRL2 0x04
26#define WM8523_DAC_CTRL3 0x05
27#define WM8523_DAC_GAINL 0x06
28#define WM8523_DAC_GAINR 0x07
29#define WM8523_ZERO_DETECT 0x08
30
31#define WM8523_REGISTER_COUNT 9
32#define WM8523_MAX_REGISTER 0x08
33
34/*
35 * Field Definitions.
36 */
37
38/*
39 * R0 (0x00) - DEVICE_ID
40 */
41#define WM8523_CHIP_ID_MASK 0xFFFF /* CHIP_ID - [15:0] */
42#define WM8523_CHIP_ID_SHIFT 0 /* CHIP_ID - [15:0] */
43#define WM8523_CHIP_ID_WIDTH 16 /* CHIP_ID - [15:0] */
44
45/*
46 * R1 (0x01) - REVISION
47 */
48#define WM8523_CHIP_REV_MASK 0x0007 /* CHIP_REV - [2:0] */
49#define WM8523_CHIP_REV_SHIFT 0 /* CHIP_REV - [2:0] */
50#define WM8523_CHIP_REV_WIDTH 3 /* CHIP_REV - [2:0] */
51
52/*
53 * R2 (0x02) - PSCTRL1
54 */
55#define WM8523_SYS_ENA_MASK 0x0003 /* SYS_ENA - [1:0] */
56#define WM8523_SYS_ENA_SHIFT 0 /* SYS_ENA - [1:0] */
57#define WM8523_SYS_ENA_WIDTH 2 /* SYS_ENA - [1:0] */
58
59/*
60 * R3 (0x03) - AIF_CTRL1
61 */
62#define WM8523_TDM_MODE_MASK 0x1800 /* TDM_MODE - [12:11] */
63#define WM8523_TDM_MODE_SHIFT 11 /* TDM_MODE - [12:11] */
64#define WM8523_TDM_MODE_WIDTH 2 /* TDM_MODE - [12:11] */
65#define WM8523_TDM_SLOT_MASK 0x0600 /* TDM_SLOT - [10:9] */
66#define WM8523_TDM_SLOT_SHIFT 9 /* TDM_SLOT - [10:9] */
67#define WM8523_TDM_SLOT_WIDTH 2 /* TDM_SLOT - [10:9] */
68#define WM8523_DEEMPH 0x0100 /* DEEMPH */
69#define WM8523_DEEMPH_MASK 0x0100 /* DEEMPH */
70#define WM8523_DEEMPH_SHIFT 8 /* DEEMPH */
71#define WM8523_DEEMPH_WIDTH 1 /* DEEMPH */
72#define WM8523_AIF_MSTR 0x0080 /* AIF_MSTR */
73#define WM8523_AIF_MSTR_MASK 0x0080 /* AIF_MSTR */
74#define WM8523_AIF_MSTR_SHIFT 7 /* AIF_MSTR */
75#define WM8523_AIF_MSTR_WIDTH 1 /* AIF_MSTR */
76#define WM8523_LRCLK_INV 0x0040 /* LRCLK_INV */
77#define WM8523_LRCLK_INV_MASK 0x0040 /* LRCLK_INV */
78#define WM8523_LRCLK_INV_SHIFT 6 /* LRCLK_INV */
79#define WM8523_LRCLK_INV_WIDTH 1 /* LRCLK_INV */
80#define WM8523_BCLK_INV 0x0020 /* BCLK_INV */
81#define WM8523_BCLK_INV_MASK 0x0020 /* BCLK_INV */
82#define WM8523_BCLK_INV_SHIFT 5 /* BCLK_INV */
83#define WM8523_BCLK_INV_WIDTH 1 /* BCLK_INV */
84#define WM8523_WL_MASK 0x0018 /* WL - [4:3] */
85#define WM8523_WL_SHIFT 3 /* WL - [4:3] */
86#define WM8523_WL_WIDTH 2 /* WL - [4:3] */
87#define WM8523_FMT_MASK 0x0007 /* FMT - [2:0] */
88#define WM8523_FMT_SHIFT 0 /* FMT - [2:0] */
89#define WM8523_FMT_WIDTH 3 /* FMT - [2:0] */
90
91/*
92 * R4 (0x04) - AIF_CTRL2
93 */
94#define WM8523_DAC_OP_MUX_MASK 0x00C0 /* DAC_OP_MUX - [7:6] */
95#define WM8523_DAC_OP_MUX_SHIFT 6 /* DAC_OP_MUX - [7:6] */
96#define WM8523_DAC_OP_MUX_WIDTH 2 /* DAC_OP_MUX - [7:6] */
97#define WM8523_BCLKDIV_MASK 0x0038 /* BCLKDIV - [5:3] */
98#define WM8523_BCLKDIV_SHIFT 3 /* BCLKDIV - [5:3] */
99#define WM8523_BCLKDIV_WIDTH 3 /* BCLKDIV - [5:3] */
100#define WM8523_SR_MASK 0x0007 /* SR - [2:0] */
101#define WM8523_SR_SHIFT 0 /* SR - [2:0] */
102#define WM8523_SR_WIDTH 3 /* SR - [2:0] */
103
104/*
105 * R5 (0x05) - DAC_CTRL3
106 */
107#define WM8523_ZC 0x0010 /* ZC */
108#define WM8523_ZC_MASK 0x0010 /* ZC */
109#define WM8523_ZC_SHIFT 4 /* ZC */
110#define WM8523_ZC_WIDTH 1 /* ZC */
111#define WM8523_DACR 0x0008 /* DACR */
112#define WM8523_DACR_MASK 0x0008 /* DACR */
113#define WM8523_DACR_SHIFT 3 /* DACR */
114#define WM8523_DACR_WIDTH 1 /* DACR */
115#define WM8523_DACL 0x0004 /* DACL */
116#define WM8523_DACL_MASK 0x0004 /* DACL */
117#define WM8523_DACL_SHIFT 2 /* DACL */
118#define WM8523_DACL_WIDTH 1 /* DACL */
119#define WM8523_VOL_UP_RAMP 0x0002 /* VOL_UP_RAMP */
120#define WM8523_VOL_UP_RAMP_MASK 0x0002 /* VOL_UP_RAMP */
121#define WM8523_VOL_UP_RAMP_SHIFT 1 /* VOL_UP_RAMP */
122#define WM8523_VOL_UP_RAMP_WIDTH 1 /* VOL_UP_RAMP */
123#define WM8523_VOL_DOWN_RAMP 0x0001 /* VOL_DOWN_RAMP */
124#define WM8523_VOL_DOWN_RAMP_MASK 0x0001 /* VOL_DOWN_RAMP */
125#define WM8523_VOL_DOWN_RAMP_SHIFT 0 /* VOL_DOWN_RAMP */
126#define WM8523_VOL_DOWN_RAMP_WIDTH 1 /* VOL_DOWN_RAMP */
127
128/*
129 * R6 (0x06) - DAC_GAINL
130 */
131#define WM8523_DACL_VU 0x0200 /* DACL_VU */
132#define WM8523_DACL_VU_MASK 0x0200 /* DACL_VU */
133#define WM8523_DACL_VU_SHIFT 9 /* DACL_VU */
134#define WM8523_DACL_VU_WIDTH 1 /* DACL_VU */
135#define WM8523_DACL_VOL_MASK 0x01FF /* DACL_VOL - [8:0] */
136#define WM8523_DACL_VOL_SHIFT 0 /* DACL_VOL - [8:0] */
137#define WM8523_DACL_VOL_WIDTH 9 /* DACL_VOL - [8:0] */
138
139/*
140 * R7 (0x07) - DAC_GAINR
141 */
142#define WM8523_DACR_VU 0x0200 /* DACR_VU */
143#define WM8523_DACR_VU_MASK 0x0200 /* DACR_VU */
144#define WM8523_DACR_VU_SHIFT 9 /* DACR_VU */
145#define WM8523_DACR_VU_WIDTH 1 /* DACR_VU */
146#define WM8523_DACR_VOL_MASK 0x01FF /* DACR_VOL - [8:0] */
147#define WM8523_DACR_VOL_SHIFT 0 /* DACR_VOL - [8:0] */
148#define WM8523_DACR_VOL_WIDTH 9 /* DACR_VOL - [8:0] */
149
150/*
151 * R8 (0x08) - ZERO_DETECT
152 */
153#define WM8523_ZD_COUNT_MASK 0x0003 /* ZD_COUNT - [1:0] */
154#define WM8523_ZD_COUNT_SHIFT 0 /* ZD_COUNT - [1:0] */
155#define WM8523_ZD_COUNT_WIDTH 2 /* ZD_COUNT - [1:0] */
156
157extern struct snd_soc_dai wm8523_dai;
158extern struct snd_soc_codec_device soc_codec_dev_wm8523;
159
160#endif
diff --git a/sound/soc/codecs/wm8580.c b/sound/soc/codecs/wm8580.c
index 9f6be3d31ac0..d5473473a1e3 100644
--- a/sound/soc/codecs/wm8580.c
+++ b/sound/soc/codecs/wm8580.c
@@ -24,6 +24,8 @@
24#include <linux/pm.h> 24#include <linux/pm.h>
25#include <linux/i2c.h> 25#include <linux/i2c.h>
26#include <linux/platform_device.h> 26#include <linux/platform_device.h>
27#include <linux/regulator/consumer.h>
28
27#include <sound/core.h> 29#include <sound/core.h>
28#include <sound/pcm.h> 30#include <sound/pcm.h>
29#include <sound/pcm_params.h> 31#include <sound/pcm_params.h>
@@ -187,82 +189,22 @@ struct pll_state {
187 unsigned int out; 189 unsigned int out;
188}; 190};
189 191
192#define WM8580_NUM_SUPPLIES 3
193static const char *wm8580_supply_names[WM8580_NUM_SUPPLIES] = {
194 "AVDD",
195 "DVDD",
196 "PVDD",
197};
198
190/* codec private data */ 199/* codec private data */
191struct wm8580_priv { 200struct wm8580_priv {
192 struct snd_soc_codec codec; 201 struct snd_soc_codec codec;
202 struct regulator_bulk_data supplies[WM8580_NUM_SUPPLIES];
193 u16 reg_cache[WM8580_MAX_REGISTER + 1]; 203 u16 reg_cache[WM8580_MAX_REGISTER + 1];
194 struct pll_state a; 204 struct pll_state a;
195 struct pll_state b; 205 struct pll_state b;
196}; 206};
197 207
198
199/*
200 * read wm8580 register cache
201 */
202static inline unsigned int wm8580_read_reg_cache(struct snd_soc_codec *codec,
203 unsigned int reg)
204{
205 u16 *cache = codec->reg_cache;
206 BUG_ON(reg >= ARRAY_SIZE(wm8580_reg));
207 return cache[reg];
208}
209
210/*
211 * write wm8580 register cache
212 */
213static inline void wm8580_write_reg_cache(struct snd_soc_codec *codec,
214 unsigned int reg, unsigned int value)
215{
216 u16 *cache = codec->reg_cache;
217
218 cache[reg] = value;
219}
220
221/*
222 * write to the WM8580 register space
223 */
224static int wm8580_write(struct snd_soc_codec *codec, unsigned int reg,
225 unsigned int value)
226{
227 u8 data[2];
228
229 BUG_ON(reg >= ARRAY_SIZE(wm8580_reg));
230
231 /* Registers are 9 bits wide */
232 value &= 0x1ff;
233
234 switch (reg) {
235 case WM8580_RESET:
236 /* Uncached */
237 break;
238 default:
239 if (value == wm8580_read_reg_cache(codec, reg))
240 return 0;
241 }
242
243 /* data is
244 * D15..D9 WM8580 register offset
245 * D8...D0 register data
246 */
247 data[0] = (reg << 1) | ((value >> 8) & 0x0001);
248 data[1] = value & 0x00ff;
249
250 wm8580_write_reg_cache(codec, reg, value);
251 if (codec->hw_write(codec->control_data, data, 2) == 2)
252 return 0;
253 else
254 return -EIO;
255}
256
257static inline unsigned int wm8580_read(struct snd_soc_codec *codec,
258 unsigned int reg)
259{
260 switch (reg) {
261 default:
262 return wm8580_read_reg_cache(codec, reg);
263 }
264}
265
266static const DECLARE_TLV_DB_SCALE(dac_tlv, -12750, 50, 1); 208static const DECLARE_TLV_DB_SCALE(dac_tlv, -12750, 50, 1);
267 209
268static int wm8580_out_vu(struct snd_kcontrol *kcontrol, 210static int wm8580_out_vu(struct snd_kcontrol *kcontrol,
@@ -271,25 +213,22 @@ static int wm8580_out_vu(struct snd_kcontrol *kcontrol,
271 struct soc_mixer_control *mc = 213 struct soc_mixer_control *mc =
272 (struct soc_mixer_control *)kcontrol->private_value; 214 (struct soc_mixer_control *)kcontrol->private_value;
273 struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); 215 struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
216 u16 *reg_cache = codec->reg_cache;
274 unsigned int reg = mc->reg; 217 unsigned int reg = mc->reg;
275 unsigned int reg2 = mc->rreg; 218 unsigned int reg2 = mc->rreg;
276 int ret; 219 int ret;
277 u16 val;
278 220
279 /* Clear the register cache so we write without VU set */ 221 /* Clear the register cache so we write without VU set */
280 wm8580_write_reg_cache(codec, reg, 0); 222 reg_cache[reg] = 0;
281 wm8580_write_reg_cache(codec, reg2, 0); 223 reg_cache[reg2] = 0;
282 224
283 ret = snd_soc_put_volsw_2r(kcontrol, ucontrol); 225 ret = snd_soc_put_volsw_2r(kcontrol, ucontrol);
284 if (ret < 0) 226 if (ret < 0)
285 return ret; 227 return ret;
286 228
287 /* Now write again with the volume update bit set */ 229 /* Now write again with the volume update bit set */
288 val = wm8580_read_reg_cache(codec, reg); 230 snd_soc_update_bits(codec, reg, 0x100, 0x100);
289 wm8580_write(codec, reg, val | 0x0100); 231 snd_soc_update_bits(codec, reg2, 0x100, 0x100);
290
291 val = wm8580_read_reg_cache(codec, reg2);
292 wm8580_write(codec, reg2, val | 0x0100);
293 232
294 return 0; 233 return 0;
295} 234}
@@ -415,7 +354,7 @@ static int pll_factors(struct _pll_div *pll_div, unsigned int target,
415 unsigned int K, Ndiv, Nmod; 354 unsigned int K, Ndiv, Nmod;
416 int i; 355 int i;
417 356
418 pr_debug("wm8580: PLL %dHz->%dHz\n", source, target); 357 pr_debug("wm8580: PLL %uHz->%uHz\n", source, target);
419 358
420 /* Scale the output frequency up; the PLL should run in the 359 /* Scale the output frequency up; the PLL should run in the
421 * region of 90-100MHz. 360 * region of 90-100MHz.
@@ -447,7 +386,7 @@ static int pll_factors(struct _pll_div *pll_div, unsigned int target,
447 386
448 if ((Ndiv < 5) || (Ndiv > 13)) { 387 if ((Ndiv < 5) || (Ndiv > 13)) {
449 printk(KERN_ERR 388 printk(KERN_ERR
450 "WM8580 N=%d outside supported range\n", Ndiv); 389 "WM8580 N=%u outside supported range\n", Ndiv);
451 return -EINVAL; 390 return -EINVAL;
452 } 391 }
453 392
@@ -512,27 +451,27 @@ static int wm8580_set_dai_pll(struct snd_soc_dai *codec_dai,
512 /* Always disable the PLL - it is not safe to leave it running 451 /* Always disable the PLL - it is not safe to leave it running
513 * while reprogramming it. 452 * while reprogramming it.
514 */ 453 */
515 reg = wm8580_read(codec, WM8580_PWRDN2); 454 reg = snd_soc_read(codec, WM8580_PWRDN2);
516 wm8580_write(codec, WM8580_PWRDN2, reg | pwr_mask); 455 snd_soc_write(codec, WM8580_PWRDN2, reg | pwr_mask);
517 456
518 if (!freq_in || !freq_out) 457 if (!freq_in || !freq_out)
519 return 0; 458 return 0;
520 459
521 wm8580_write(codec, WM8580_PLLA1 + offset, pll_div.k & 0x1ff); 460 snd_soc_write(codec, WM8580_PLLA1 + offset, pll_div.k & 0x1ff);
522 wm8580_write(codec, WM8580_PLLA2 + offset, (pll_div.k >> 9) & 0xff); 461 snd_soc_write(codec, WM8580_PLLA2 + offset, (pll_div.k >> 9) & 0xff);
523 wm8580_write(codec, WM8580_PLLA3 + offset, 462 snd_soc_write(codec, WM8580_PLLA3 + offset,
524 (pll_div.k >> 18 & 0xf) | (pll_div.n << 4)); 463 (pll_div.k >> 18 & 0xf) | (pll_div.n << 4));
525 464
526 reg = wm8580_read(codec, WM8580_PLLA4 + offset); 465 reg = snd_soc_read(codec, WM8580_PLLA4 + offset);
527 reg &= ~0x3f; 466 reg &= ~0x3f;
528 reg |= pll_div.prescale | pll_div.postscale << 1 | 467 reg |= pll_div.prescale | pll_div.postscale << 1 |
529 pll_div.freqmode << 3; 468 pll_div.freqmode << 3;
530 469
531 wm8580_write(codec, WM8580_PLLA4 + offset, reg); 470 snd_soc_write(codec, WM8580_PLLA4 + offset, reg);
532 471
533 /* All done, turn it on */ 472 /* All done, turn it on */
534 reg = wm8580_read(codec, WM8580_PWRDN2); 473 reg = snd_soc_read(codec, WM8580_PWRDN2);
535 wm8580_write(codec, WM8580_PWRDN2, reg & ~pwr_mask); 474 snd_soc_write(codec, WM8580_PWRDN2, reg & ~pwr_mask);
536 475
537 return 0; 476 return 0;
538} 477}
@@ -547,7 +486,7 @@ static int wm8580_paif_hw_params(struct snd_pcm_substream *substream,
547 struct snd_soc_pcm_runtime *rtd = substream->private_data; 486 struct snd_soc_pcm_runtime *rtd = substream->private_data;
548 struct snd_soc_device *socdev = rtd->socdev; 487 struct snd_soc_device *socdev = rtd->socdev;
549 struct snd_soc_codec *codec = socdev->card->codec; 488 struct snd_soc_codec *codec = socdev->card->codec;
550 u16 paifb = wm8580_read(codec, WM8580_PAIF3 + dai->id); 489 u16 paifb = snd_soc_read(codec, WM8580_PAIF3 + dai->id);
551 490
552 paifb &= ~WM8580_AIF_LENGTH_MASK; 491 paifb &= ~WM8580_AIF_LENGTH_MASK;
553 /* bit size */ 492 /* bit size */
@@ -567,7 +506,7 @@ static int wm8580_paif_hw_params(struct snd_pcm_substream *substream,
567 return -EINVAL; 506 return -EINVAL;
568 } 507 }
569 508
570 wm8580_write(codec, WM8580_PAIF3 + dai->id, paifb); 509 snd_soc_write(codec, WM8580_PAIF3 + dai->id, paifb);
571 return 0; 510 return 0;
572} 511}
573 512
@@ -579,8 +518,8 @@ static int wm8580_set_paif_dai_fmt(struct snd_soc_dai *codec_dai,
579 unsigned int aifb; 518 unsigned int aifb;
580 int can_invert_lrclk; 519 int can_invert_lrclk;
581 520
582 aifa = wm8580_read(codec, WM8580_PAIF1 + codec_dai->id); 521 aifa = snd_soc_read(codec, WM8580_PAIF1 + codec_dai->id);
583 aifb = wm8580_read(codec, WM8580_PAIF3 + codec_dai->id); 522 aifb = snd_soc_read(codec, WM8580_PAIF3 + codec_dai->id);
584 523
585 aifb &= ~(WM8580_AIF_FMT_MASK | WM8580_AIF_LRP | WM8580_AIF_BCP); 524 aifb &= ~(WM8580_AIF_FMT_MASK | WM8580_AIF_LRP | WM8580_AIF_BCP);
586 525
@@ -646,8 +585,8 @@ static int wm8580_set_paif_dai_fmt(struct snd_soc_dai *codec_dai,
646 return -EINVAL; 585 return -EINVAL;
647 } 586 }
648 587
649 wm8580_write(codec, WM8580_PAIF1 + codec_dai->id, aifa); 588 snd_soc_write(codec, WM8580_PAIF1 + codec_dai->id, aifa);
650 wm8580_write(codec, WM8580_PAIF3 + codec_dai->id, aifb); 589 snd_soc_write(codec, WM8580_PAIF3 + codec_dai->id, aifb);
651 590
652 return 0; 591 return 0;
653} 592}
@@ -660,7 +599,7 @@ static int wm8580_set_dai_clkdiv(struct snd_soc_dai *codec_dai,
660 599
661 switch (div_id) { 600 switch (div_id) {
662 case WM8580_MCLK: 601 case WM8580_MCLK:
663 reg = wm8580_read(codec, WM8580_PLLB4); 602 reg = snd_soc_read(codec, WM8580_PLLB4);
664 reg &= ~WM8580_PLLB4_MCLKOUTSRC_MASK; 603 reg &= ~WM8580_PLLB4_MCLKOUTSRC_MASK;
665 604
666 switch (div) { 605 switch (div) {
@@ -682,11 +621,11 @@ static int wm8580_set_dai_clkdiv(struct snd_soc_dai *codec_dai,
682 default: 621 default:
683 return -EINVAL; 622 return -EINVAL;
684 } 623 }
685 wm8580_write(codec, WM8580_PLLB4, reg); 624 snd_soc_write(codec, WM8580_PLLB4, reg);
686 break; 625 break;
687 626
688 case WM8580_DAC_CLKSEL: 627 case WM8580_DAC_CLKSEL:
689 reg = wm8580_read(codec, WM8580_CLKSEL); 628 reg = snd_soc_read(codec, WM8580_CLKSEL);
690 reg &= ~WM8580_CLKSEL_DAC_CLKSEL_MASK; 629 reg &= ~WM8580_CLKSEL_DAC_CLKSEL_MASK;
691 630
692 switch (div) { 631 switch (div) {
@@ -704,11 +643,11 @@ static int wm8580_set_dai_clkdiv(struct snd_soc_dai *codec_dai,
704 default: 643 default:
705 return -EINVAL; 644 return -EINVAL;
706 } 645 }
707 wm8580_write(codec, WM8580_CLKSEL, reg); 646 snd_soc_write(codec, WM8580_CLKSEL, reg);
708 break; 647 break;
709 648
710 case WM8580_CLKOUTSRC: 649 case WM8580_CLKOUTSRC:
711 reg = wm8580_read(codec, WM8580_PLLB4); 650 reg = snd_soc_read(codec, WM8580_PLLB4);
712 reg &= ~WM8580_PLLB4_CLKOUTSRC_MASK; 651 reg &= ~WM8580_PLLB4_CLKOUTSRC_MASK;
713 652
714 switch (div) { 653 switch (div) {
@@ -730,7 +669,7 @@ static int wm8580_set_dai_clkdiv(struct snd_soc_dai *codec_dai,
730 default: 669 default:
731 return -EINVAL; 670 return -EINVAL;
732 } 671 }
733 wm8580_write(codec, WM8580_PLLB4, reg); 672 snd_soc_write(codec, WM8580_PLLB4, reg);
734 break; 673 break;
735 674
736 default: 675 default:
@@ -745,14 +684,14 @@ static int wm8580_digital_mute(struct snd_soc_dai *codec_dai, int mute)
745 struct snd_soc_codec *codec = codec_dai->codec; 684 struct snd_soc_codec *codec = codec_dai->codec;
746 unsigned int reg; 685 unsigned int reg;
747 686
748 reg = wm8580_read(codec, WM8580_DAC_CONTROL5); 687 reg = snd_soc_read(codec, WM8580_DAC_CONTROL5);
749 688
750 if (mute) 689 if (mute)
751 reg |= WM8580_DAC_CONTROL5_MUTEALL; 690 reg |= WM8580_DAC_CONTROL5_MUTEALL;
752 else 691 else
753 reg &= ~WM8580_DAC_CONTROL5_MUTEALL; 692 reg &= ~WM8580_DAC_CONTROL5_MUTEALL;
754 693
755 wm8580_write(codec, WM8580_DAC_CONTROL5, reg); 694 snd_soc_write(codec, WM8580_DAC_CONTROL5, reg);
756 695
757 return 0; 696 return 0;
758} 697}
@@ -769,20 +708,20 @@ static int wm8580_set_bias_level(struct snd_soc_codec *codec,
769 case SND_SOC_BIAS_STANDBY: 708 case SND_SOC_BIAS_STANDBY:
770 if (codec->bias_level == SND_SOC_BIAS_OFF) { 709 if (codec->bias_level == SND_SOC_BIAS_OFF) {
771 /* Power up and get individual control of the DACs */ 710 /* Power up and get individual control of the DACs */
772 reg = wm8580_read(codec, WM8580_PWRDN1); 711 reg = snd_soc_read(codec, WM8580_PWRDN1);
773 reg &= ~(WM8580_PWRDN1_PWDN | WM8580_PWRDN1_ALLDACPD); 712 reg &= ~(WM8580_PWRDN1_PWDN | WM8580_PWRDN1_ALLDACPD);
774 wm8580_write(codec, WM8580_PWRDN1, reg); 713 snd_soc_write(codec, WM8580_PWRDN1, reg);
775 714
776 /* Make VMID high impedence */ 715 /* Make VMID high impedence */
777 reg = wm8580_read(codec, WM8580_ADC_CONTROL1); 716 reg = snd_soc_read(codec, WM8580_ADC_CONTROL1);
778 reg &= ~0x100; 717 reg &= ~0x100;
779 wm8580_write(codec, WM8580_ADC_CONTROL1, reg); 718 snd_soc_write(codec, WM8580_ADC_CONTROL1, reg);
780 } 719 }
781 break; 720 break;
782 721
783 case SND_SOC_BIAS_OFF: 722 case SND_SOC_BIAS_OFF:
784 reg = wm8580_read(codec, WM8580_PWRDN1); 723 reg = snd_soc_read(codec, WM8580_PWRDN1);
785 wm8580_write(codec, WM8580_PWRDN1, reg | WM8580_PWRDN1_PWDN); 724 snd_soc_write(codec, WM8580_PWRDN1, reg | WM8580_PWRDN1_PWDN);
786 break; 725 break;
787 } 726 }
788 codec->bias_level = level; 727 codec->bias_level = level;
@@ -893,7 +832,8 @@ struct snd_soc_codec_device soc_codec_dev_wm8580 = {
893}; 832};
894EXPORT_SYMBOL_GPL(soc_codec_dev_wm8580); 833EXPORT_SYMBOL_GPL(soc_codec_dev_wm8580);
895 834
896static int wm8580_register(struct wm8580_priv *wm8580) 835static int wm8580_register(struct wm8580_priv *wm8580,
836 enum snd_soc_control_type control)
897{ 837{
898 int ret, i; 838 int ret, i;
899 struct snd_soc_codec *codec = &wm8580->codec; 839 struct snd_soc_codec *codec = &wm8580->codec;
@@ -911,8 +851,6 @@ static int wm8580_register(struct wm8580_priv *wm8580)
911 codec->private_data = wm8580; 851 codec->private_data = wm8580;
912 codec->name = "WM8580"; 852 codec->name = "WM8580";
913 codec->owner = THIS_MODULE; 853 codec->owner = THIS_MODULE;
914 codec->read = wm8580_read_reg_cache;
915 codec->write = wm8580_write;
916 codec->bias_level = SND_SOC_BIAS_OFF; 854 codec->bias_level = SND_SOC_BIAS_OFF;
917 codec->set_bias_level = wm8580_set_bias_level; 855 codec->set_bias_level = wm8580_set_bias_level;
918 codec->dai = wm8580_dai; 856 codec->dai = wm8580_dai;
@@ -922,11 +860,34 @@ static int wm8580_register(struct wm8580_priv *wm8580)
922 860
923 memcpy(codec->reg_cache, wm8580_reg, sizeof(wm8580_reg)); 861 memcpy(codec->reg_cache, wm8580_reg, sizeof(wm8580_reg));
924 862
863 ret = snd_soc_codec_set_cache_io(codec, 7, 9, control);
864 if (ret < 0) {
865 dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret);
866 goto err;
867 }
868
869 for (i = 0; i < ARRAY_SIZE(wm8580->supplies); i++)
870 wm8580->supplies[i].supply = wm8580_supply_names[i];
871
872 ret = regulator_bulk_get(codec->dev, ARRAY_SIZE(wm8580->supplies),
873 wm8580->supplies);
874 if (ret != 0) {
875 dev_err(codec->dev, "Failed to request supplies: %d\n", ret);
876 goto err;
877 }
878
879 ret = regulator_bulk_enable(ARRAY_SIZE(wm8580->supplies),
880 wm8580->supplies);
881 if (ret != 0) {
882 dev_err(codec->dev, "Failed to enable supplies: %d\n", ret);
883 goto err_regulator_get;
884 }
885
925 /* Get the codec into a known state */ 886 /* Get the codec into a known state */
926 ret = wm8580_write(codec, WM8580_RESET, 0); 887 ret = snd_soc_write(codec, WM8580_RESET, 0);
927 if (ret != 0) { 888 if (ret != 0) {
928 dev_err(codec->dev, "Failed to reset codec: %d\n", ret); 889 dev_err(codec->dev, "Failed to reset codec: %d\n", ret);
929 goto err; 890 goto err_regulator_enable;
930 } 891 }
931 892
932 for (i = 0; i < ARRAY_SIZE(wm8580_dai); i++) 893 for (i = 0; i < ARRAY_SIZE(wm8580_dai); i++)
@@ -939,7 +900,7 @@ static int wm8580_register(struct wm8580_priv *wm8580)
939 ret = snd_soc_register_codec(codec); 900 ret = snd_soc_register_codec(codec);
940 if (ret != 0) { 901 if (ret != 0) {
941 dev_err(codec->dev, "Failed to register codec: %d\n", ret); 902 dev_err(codec->dev, "Failed to register codec: %d\n", ret);
942 goto err; 903 goto err_regulator_enable;
943 } 904 }
944 905
945 ret = snd_soc_register_dais(wm8580_dai, ARRAY_SIZE(wm8580_dai)); 906 ret = snd_soc_register_dais(wm8580_dai, ARRAY_SIZE(wm8580_dai));
@@ -952,6 +913,10 @@ static int wm8580_register(struct wm8580_priv *wm8580)
952 913
953err_codec: 914err_codec:
954 snd_soc_unregister_codec(codec); 915 snd_soc_unregister_codec(codec);
916err_regulator_enable:
917 regulator_bulk_disable(ARRAY_SIZE(wm8580->supplies), wm8580->supplies);
918err_regulator_get:
919 regulator_bulk_free(ARRAY_SIZE(wm8580->supplies), wm8580->supplies);
955err: 920err:
956 kfree(wm8580); 921 kfree(wm8580);
957 return ret; 922 return ret;
@@ -962,6 +927,8 @@ static void wm8580_unregister(struct wm8580_priv *wm8580)
962 wm8580_set_bias_level(&wm8580->codec, SND_SOC_BIAS_OFF); 927 wm8580_set_bias_level(&wm8580->codec, SND_SOC_BIAS_OFF);
963 snd_soc_unregister_dais(wm8580_dai, ARRAY_SIZE(wm8580_dai)); 928 snd_soc_unregister_dais(wm8580_dai, ARRAY_SIZE(wm8580_dai));
964 snd_soc_unregister_codec(&wm8580->codec); 929 snd_soc_unregister_codec(&wm8580->codec);
930 regulator_bulk_disable(ARRAY_SIZE(wm8580->supplies), wm8580->supplies);
931 regulator_bulk_free(ARRAY_SIZE(wm8580->supplies), wm8580->supplies);
965 kfree(wm8580); 932 kfree(wm8580);
966 wm8580_codec = NULL; 933 wm8580_codec = NULL;
967} 934}
@@ -978,14 +945,13 @@ static int wm8580_i2c_probe(struct i2c_client *i2c,
978 return -ENOMEM; 945 return -ENOMEM;
979 946
980 codec = &wm8580->codec; 947 codec = &wm8580->codec;
981 codec->hw_write = (hw_write_t)i2c_master_send;
982 948
983 i2c_set_clientdata(i2c, wm8580); 949 i2c_set_clientdata(i2c, wm8580);
984 codec->control_data = i2c; 950 codec->control_data = i2c;
985 951
986 codec->dev = &i2c->dev; 952 codec->dev = &i2c->dev;
987 953
988 return wm8580_register(wm8580); 954 return wm8580_register(wm8580, SND_SOC_I2C);
989} 955}
990 956
991static int wm8580_i2c_remove(struct i2c_client *client) 957static int wm8580_i2c_remove(struct i2c_client *client)
@@ -995,6 +961,21 @@ static int wm8580_i2c_remove(struct i2c_client *client)
995 return 0; 961 return 0;
996} 962}
997 963
964#ifdef CONFIG_PM
965static int wm8580_i2c_suspend(struct i2c_client *client, pm_message_t msg)
966{
967 return snd_soc_suspend_device(&client->dev);
968}
969
970static int wm8580_i2c_resume(struct i2c_client *client)
971{
972 return snd_soc_resume_device(&client->dev);
973}
974#else
975#define wm8580_i2c_suspend NULL
976#define wm8580_i2c_resume NULL
977#endif
978
998static const struct i2c_device_id wm8580_i2c_id[] = { 979static const struct i2c_device_id wm8580_i2c_id[] = {
999 { "wm8580", 0 }, 980 { "wm8580", 0 },
1000 { } 981 { }
@@ -1008,6 +989,8 @@ static struct i2c_driver wm8580_i2c_driver = {
1008 }, 989 },
1009 .probe = wm8580_i2c_probe, 990 .probe = wm8580_i2c_probe,
1010 .remove = wm8580_i2c_remove, 991 .remove = wm8580_i2c_remove,
992 .suspend = wm8580_i2c_suspend,
993 .resume = wm8580_i2c_resume,
1011 .id_table = wm8580_i2c_id, 994 .id_table = wm8580_i2c_id,
1012}; 995};
1013#endif 996#endif
diff --git a/sound/soc/codecs/wm8728.c b/sound/soc/codecs/wm8728.c
index e7ff2121ede9..16e969a762c3 100644
--- a/sound/soc/codecs/wm8728.c
+++ b/sound/soc/codecs/wm8728.c
@@ -43,45 +43,6 @@ static const u16 wm8728_reg_defaults[] = {
43 0x100, 43 0x100,
44}; 44};
45 45
46static inline unsigned int wm8728_read_reg_cache(struct snd_soc_codec *codec,
47 unsigned int reg)
48{
49 u16 *cache = codec->reg_cache;
50 BUG_ON(reg >= ARRAY_SIZE(wm8728_reg_defaults));
51 return cache[reg];
52}
53
54static inline void wm8728_write_reg_cache(struct snd_soc_codec *codec,
55 u16 reg, unsigned int value)
56{
57 u16 *cache = codec->reg_cache;
58 BUG_ON(reg >= ARRAY_SIZE(wm8728_reg_defaults));
59 cache[reg] = value;
60}
61
62/*
63 * write to the WM8728 register space
64 */
65static int wm8728_write(struct snd_soc_codec *codec, unsigned int reg,
66 unsigned int value)
67{
68 u8 data[2];
69
70 /* data is
71 * D15..D9 WM8728 register offset
72 * D8...D0 register data
73 */
74 data[0] = (reg << 1) | ((value >> 8) & 0x0001);
75 data[1] = value & 0x00ff;
76
77 wm8728_write_reg_cache(codec, reg, value);
78
79 if (codec->hw_write(codec->control_data, data, 2) == 2)
80 return 0;
81 else
82 return -EIO;
83}
84
85static const DECLARE_TLV_DB_SCALE(wm8728_tlv, -12750, 50, 1); 46static const DECLARE_TLV_DB_SCALE(wm8728_tlv, -12750, 50, 1);
86 47
87static const struct snd_kcontrol_new wm8728_snd_controls[] = { 48static const struct snd_kcontrol_new wm8728_snd_controls[] = {
@@ -121,12 +82,12 @@ static int wm8728_add_widgets(struct snd_soc_codec *codec)
121static int wm8728_mute(struct snd_soc_dai *dai, int mute) 82static int wm8728_mute(struct snd_soc_dai *dai, int mute)
122{ 83{
123 struct snd_soc_codec *codec = dai->codec; 84 struct snd_soc_codec *codec = dai->codec;
124 u16 mute_reg = wm8728_read_reg_cache(codec, WM8728_DACCTL); 85 u16 mute_reg = snd_soc_read(codec, WM8728_DACCTL);
125 86
126 if (mute) 87 if (mute)
127 wm8728_write(codec, WM8728_DACCTL, mute_reg | 1); 88 snd_soc_write(codec, WM8728_DACCTL, mute_reg | 1);
128 else 89 else
129 wm8728_write(codec, WM8728_DACCTL, mute_reg & ~1); 90 snd_soc_write(codec, WM8728_DACCTL, mute_reg & ~1);
130 91
131 return 0; 92 return 0;
132} 93}
@@ -138,7 +99,7 @@ static int wm8728_hw_params(struct snd_pcm_substream *substream,
138 struct snd_soc_pcm_runtime *rtd = substream->private_data; 99 struct snd_soc_pcm_runtime *rtd = substream->private_data;
139 struct snd_soc_device *socdev = rtd->socdev; 100 struct snd_soc_device *socdev = rtd->socdev;
140 struct snd_soc_codec *codec = socdev->card->codec; 101 struct snd_soc_codec *codec = socdev->card->codec;
141 u16 dac = wm8728_read_reg_cache(codec, WM8728_DACCTL); 102 u16 dac = snd_soc_read(codec, WM8728_DACCTL);
142 103
143 dac &= ~0x18; 104 dac &= ~0x18;
144 105
@@ -155,7 +116,7 @@ static int wm8728_hw_params(struct snd_pcm_substream *substream,
155 return -EINVAL; 116 return -EINVAL;
156 } 117 }
157 118
158 wm8728_write(codec, WM8728_DACCTL, dac); 119 snd_soc_write(codec, WM8728_DACCTL, dac);
159 120
160 return 0; 121 return 0;
161} 122}
@@ -164,7 +125,7 @@ static int wm8728_set_dai_fmt(struct snd_soc_dai *codec_dai,
164 unsigned int fmt) 125 unsigned int fmt)
165{ 126{
166 struct snd_soc_codec *codec = codec_dai->codec; 127 struct snd_soc_codec *codec = codec_dai->codec;
167 u16 iface = wm8728_read_reg_cache(codec, WM8728_IFCTL); 128 u16 iface = snd_soc_read(codec, WM8728_IFCTL);
168 129
169 /* Currently only I2S is supported by the driver, though the 130 /* Currently only I2S is supported by the driver, though the
170 * hardware is more flexible. 131 * hardware is more flexible.
@@ -204,7 +165,7 @@ static int wm8728_set_dai_fmt(struct snd_soc_dai *codec_dai,
204 return -EINVAL; 165 return -EINVAL;
205 } 166 }
206 167
207 wm8728_write(codec, WM8728_IFCTL, iface); 168 snd_soc_write(codec, WM8728_IFCTL, iface);
208 return 0; 169 return 0;
209} 170}
210 171
@@ -220,19 +181,19 @@ static int wm8728_set_bias_level(struct snd_soc_codec *codec,
220 case SND_SOC_BIAS_STANDBY: 181 case SND_SOC_BIAS_STANDBY:
221 if (codec->bias_level == SND_SOC_BIAS_OFF) { 182 if (codec->bias_level == SND_SOC_BIAS_OFF) {
222 /* Power everything up... */ 183 /* Power everything up... */
223 reg = wm8728_read_reg_cache(codec, WM8728_DACCTL); 184 reg = snd_soc_read(codec, WM8728_DACCTL);
224 wm8728_write(codec, WM8728_DACCTL, reg & ~0x4); 185 snd_soc_write(codec, WM8728_DACCTL, reg & ~0x4);
225 186
226 /* ..then sync in the register cache. */ 187 /* ..then sync in the register cache. */
227 for (i = 0; i < ARRAY_SIZE(wm8728_reg_defaults); i++) 188 for (i = 0; i < ARRAY_SIZE(wm8728_reg_defaults); i++)
228 wm8728_write(codec, i, 189 snd_soc_write(codec, i,
229 wm8728_read_reg_cache(codec, i)); 190 snd_soc_read(codec, i));
230 } 191 }
231 break; 192 break;
232 193
233 case SND_SOC_BIAS_OFF: 194 case SND_SOC_BIAS_OFF:
234 reg = wm8728_read_reg_cache(codec, WM8728_DACCTL); 195 reg = snd_soc_read(codec, WM8728_DACCTL);
235 wm8728_write(codec, WM8728_DACCTL, reg | 0x4); 196 snd_soc_write(codec, WM8728_DACCTL, reg | 0x4);
236 break; 197 break;
237 } 198 }
238 codec->bias_level = level; 199 codec->bias_level = level;
@@ -287,15 +248,14 @@ static int wm8728_resume(struct platform_device *pdev)
287 * initialise the WM8728 driver 248 * initialise the WM8728 driver
288 * register the mixer and dsp interfaces with the kernel 249 * register the mixer and dsp interfaces with the kernel
289 */ 250 */
290static int wm8728_init(struct snd_soc_device *socdev) 251static int wm8728_init(struct snd_soc_device *socdev,
252 enum snd_soc_control_type control)
291{ 253{
292 struct snd_soc_codec *codec = socdev->card->codec; 254 struct snd_soc_codec *codec = socdev->card->codec;
293 int ret = 0; 255 int ret = 0;
294 256
295 codec->name = "WM8728"; 257 codec->name = "WM8728";
296 codec->owner = THIS_MODULE; 258 codec->owner = THIS_MODULE;
297 codec->read = wm8728_read_reg_cache;
298 codec->write = wm8728_write;
299 codec->set_bias_level = wm8728_set_bias_level; 259 codec->set_bias_level = wm8728_set_bias_level;
300 codec->dai = &wm8728_dai; 260 codec->dai = &wm8728_dai;
301 codec->num_dai = 1; 261 codec->num_dai = 1;
@@ -307,11 +267,18 @@ static int wm8728_init(struct snd_soc_device *socdev)
307 if (codec->reg_cache == NULL) 267 if (codec->reg_cache == NULL)
308 return -ENOMEM; 268 return -ENOMEM;
309 269
270 ret = snd_soc_codec_set_cache_io(codec, 7, 9, control);
271 if (ret < 0) {
272 printk(KERN_ERR "wm8728: failed to configure cache I/O: %d\n",
273 ret);
274 goto err;
275 }
276
310 /* register pcms */ 277 /* register pcms */
311 ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1); 278 ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1);
312 if (ret < 0) { 279 if (ret < 0) {
313 printk(KERN_ERR "wm8728: failed to create pcms\n"); 280 printk(KERN_ERR "wm8728: failed to create pcms\n");
314 goto pcm_err; 281 goto err;
315 } 282 }
316 283
317 /* power on device */ 284 /* power on device */
@@ -331,7 +298,7 @@ static int wm8728_init(struct snd_soc_device *socdev)
331card_err: 298card_err:
332 snd_soc_free_pcms(socdev); 299 snd_soc_free_pcms(socdev);
333 snd_soc_dapm_free(socdev); 300 snd_soc_dapm_free(socdev);
334pcm_err: 301err:
335 kfree(codec->reg_cache); 302 kfree(codec->reg_cache);
336 return ret; 303 return ret;
337} 304}
@@ -357,7 +324,7 @@ static int wm8728_i2c_probe(struct i2c_client *i2c,
357 i2c_set_clientdata(i2c, codec); 324 i2c_set_clientdata(i2c, codec);
358 codec->control_data = i2c; 325 codec->control_data = i2c;
359 326
360 ret = wm8728_init(socdev); 327 ret = wm8728_init(socdev, SND_SOC_I2C);
361 if (ret < 0) 328 if (ret < 0)
362 pr_err("failed to initialise WM8728\n"); 329 pr_err("failed to initialise WM8728\n");
363 330
@@ -437,7 +404,7 @@ static int __devinit wm8728_spi_probe(struct spi_device *spi)
437 404
438 codec->control_data = spi; 405 codec->control_data = spi;
439 406
440 ret = wm8728_init(socdev); 407 ret = wm8728_init(socdev, SND_SOC_SPI);
441 if (ret < 0) 408 if (ret < 0)
442 dev_err(&spi->dev, "failed to initialise WM8728\n"); 409 dev_err(&spi->dev, "failed to initialise WM8728\n");
443 410
@@ -458,30 +425,6 @@ static struct spi_driver wm8728_spi_driver = {
458 .probe = wm8728_spi_probe, 425 .probe = wm8728_spi_probe,
459 .remove = __devexit_p(wm8728_spi_remove), 426 .remove = __devexit_p(wm8728_spi_remove),
460}; 427};
461
462static int wm8728_spi_write(struct spi_device *spi, const char *data, int len)
463{
464 struct spi_transfer t;
465 struct spi_message m;
466 u8 msg[2];
467
468 if (len <= 0)
469 return 0;
470
471 msg[0] = data[0];
472 msg[1] = data[1];
473
474 spi_message_init(&m);
475 memset(&t, 0, (sizeof t));
476
477 t.tx_buf = &msg[0];
478 t.len = len;
479
480 spi_message_add_tail(&t, &m);
481 spi_sync(spi, &m);
482
483 return len;
484}
485#endif /* CONFIG_SPI_MASTER */ 428#endif /* CONFIG_SPI_MASTER */
486 429
487static int wm8728_probe(struct platform_device *pdev) 430static int wm8728_probe(struct platform_device *pdev)
@@ -506,13 +449,11 @@ static int wm8728_probe(struct platform_device *pdev)
506 449
507#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) 450#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
508 if (setup->i2c_address) { 451 if (setup->i2c_address) {
509 codec->hw_write = (hw_write_t)i2c_master_send;
510 ret = wm8728_add_i2c_device(pdev, setup); 452 ret = wm8728_add_i2c_device(pdev, setup);
511 } 453 }
512#endif 454#endif
513#if defined(CONFIG_SPI_MASTER) 455#if defined(CONFIG_SPI_MASTER)
514 if (setup->spi) { 456 if (setup->spi) {
515 codec->hw_write = (hw_write_t)wm8728_spi_write;
516 ret = spi_register_driver(&wm8728_spi_driver); 457 ret = spi_register_driver(&wm8728_spi_driver);
517 if (ret != 0) 458 if (ret != 0)
518 printk(KERN_ERR "can't add spi driver"); 459 printk(KERN_ERR "can't add spi driver");
diff --git a/sound/soc/codecs/wm8731.c b/sound/soc/codecs/wm8731.c
index e043e3f60008..d3fd4f28d96e 100644
--- a/sound/soc/codecs/wm8731.c
+++ b/sound/soc/codecs/wm8731.c
@@ -26,6 +26,7 @@
26#include <sound/soc.h> 26#include <sound/soc.h>
27#include <sound/soc-dapm.h> 27#include <sound/soc-dapm.h>
28#include <sound/initval.h> 28#include <sound/initval.h>
29#include <sound/tlv.h>
29 30
30#include "wm8731.h" 31#include "wm8731.h"
31 32
@@ -39,9 +40,6 @@ struct wm8731_priv {
39 unsigned int sysclk; 40 unsigned int sysclk;
40}; 41};
41 42
42#ifdef CONFIG_SPI_MASTER
43static int wm8731_spi_write(struct spi_device *spi, const char *data, int len);
44#endif
45 43
46/* 44/*
47 * wm8731 register cache 45 * wm8731 register cache
@@ -50,60 +48,12 @@ static int wm8731_spi_write(struct spi_device *spi, const char *data, int len);
50 * There is no point in caching the reset register 48 * There is no point in caching the reset register
51 */ 49 */
52static const u16 wm8731_reg[WM8731_CACHEREGNUM] = { 50static const u16 wm8731_reg[WM8731_CACHEREGNUM] = {
53 0x0097, 0x0097, 0x0079, 0x0079, 51 0x0097, 0x0097, 0x0079, 0x0079,
54 0x000a, 0x0008, 0x009f, 0x000a, 52 0x000a, 0x0008, 0x009f, 0x000a,
55 0x0000, 0x0000 53 0x0000, 0x0000
56}; 54};
57 55
58/* 56#define wm8731_reset(c) snd_soc_write(c, WM8731_RESET, 0)
59 * read wm8731 register cache
60 */
61static inline unsigned int wm8731_read_reg_cache(struct snd_soc_codec *codec,
62 unsigned int reg)
63{
64 u16 *cache = codec->reg_cache;
65 if (reg == WM8731_RESET)
66 return 0;
67 if (reg >= WM8731_CACHEREGNUM)
68 return -1;
69 return cache[reg];
70}
71
72/*
73 * write wm8731 register cache
74 */
75static inline void wm8731_write_reg_cache(struct snd_soc_codec *codec,
76 u16 reg, unsigned int value)
77{
78 u16 *cache = codec->reg_cache;
79 if (reg >= WM8731_CACHEREGNUM)
80 return;
81 cache[reg] = value;
82}
83
84/*
85 * write to the WM8731 register space
86 */
87static int wm8731_write(struct snd_soc_codec *codec, unsigned int reg,
88 unsigned int value)
89{
90 u8 data[2];
91
92 /* data is
93 * D15..D9 WM8731 register offset
94 * D8...D0 register data
95 */
96 data[0] = (reg << 1) | ((value >> 8) & 0x0001);
97 data[1] = value & 0x00ff;
98
99 wm8731_write_reg_cache(codec, reg, value);
100 if (codec->hw_write(codec->control_data, data, 2) == 2)
101 return 0;
102 else
103 return -EIO;
104}
105
106#define wm8731_reset(c) wm8731_write(c, WM8731_RESET, 0)
107 57
108static const char *wm8731_input_select[] = {"Line In", "Mic"}; 58static const char *wm8731_input_select[] = {"Line In", "Mic"};
109static const char *wm8731_deemph[] = {"None", "32Khz", "44.1Khz", "48Khz"}; 59static const char *wm8731_deemph[] = {"None", "32Khz", "44.1Khz", "48Khz"};
@@ -113,20 +63,26 @@ static const struct soc_enum wm8731_enum[] = {
113 SOC_ENUM_SINGLE(WM8731_APDIGI, 1, 4, wm8731_deemph), 63 SOC_ENUM_SINGLE(WM8731_APDIGI, 1, 4, wm8731_deemph),
114}; 64};
115 65
66static const DECLARE_TLV_DB_SCALE(in_tlv, -3450, 150, 0);
67static const DECLARE_TLV_DB_SCALE(sidetone_tlv, -1500, 300, 0);
68static const DECLARE_TLV_DB_SCALE(out_tlv, -12100, 100, 1);
69
116static const struct snd_kcontrol_new wm8731_snd_controls[] = { 70static const struct snd_kcontrol_new wm8731_snd_controls[] = {
117 71
118SOC_DOUBLE_R("Master Playback Volume", WM8731_LOUT1V, WM8731_ROUT1V, 72SOC_DOUBLE_R_TLV("Master Playback Volume", WM8731_LOUT1V, WM8731_ROUT1V,
119 0, 127, 0), 73 0, 127, 0, out_tlv),
120SOC_DOUBLE_R("Master Playback ZC Switch", WM8731_LOUT1V, WM8731_ROUT1V, 74SOC_DOUBLE_R("Master Playback ZC Switch", WM8731_LOUT1V, WM8731_ROUT1V,
121 7, 1, 0), 75 7, 1, 0),
122 76
123SOC_DOUBLE_R("Capture Volume", WM8731_LINVOL, WM8731_RINVOL, 0, 31, 0), 77SOC_DOUBLE_R_TLV("Capture Volume", WM8731_LINVOL, WM8731_RINVOL, 0, 31, 0,
78 in_tlv),
124SOC_DOUBLE_R("Line Capture Switch", WM8731_LINVOL, WM8731_RINVOL, 7, 1, 1), 79SOC_DOUBLE_R("Line Capture Switch", WM8731_LINVOL, WM8731_RINVOL, 7, 1, 1),
125 80
126SOC_SINGLE("Mic Boost (+20dB)", WM8731_APANA, 0, 1, 0), 81SOC_SINGLE("Mic Boost (+20dB)", WM8731_APANA, 0, 1, 0),
127SOC_SINGLE("Capture Mic Switch", WM8731_APANA, 1, 1, 1), 82SOC_SINGLE("Mic Capture Switch", WM8731_APANA, 1, 1, 1),
128 83
129SOC_SINGLE("Sidetone Playback Volume", WM8731_APANA, 6, 3, 1), 84SOC_SINGLE_TLV("Sidetone Playback Volume", WM8731_APANA, 6, 3, 1,
85 sidetone_tlv),
130 86
131SOC_SINGLE("ADC High Pass Filter Switch", WM8731_APDIGI, 0, 1, 1), 87SOC_SINGLE("ADC High Pass Filter Switch", WM8731_APDIGI, 0, 1, 1),
132SOC_SINGLE("Store DC Offset Switch", WM8731_APDIGI, 4, 1, 0), 88SOC_SINGLE("Store DC Offset Switch", WM8731_APDIGI, 4, 1, 0),
@@ -260,12 +216,12 @@ static int wm8731_hw_params(struct snd_pcm_substream *substream,
260 struct snd_soc_device *socdev = rtd->socdev; 216 struct snd_soc_device *socdev = rtd->socdev;
261 struct snd_soc_codec *codec = socdev->card->codec; 217 struct snd_soc_codec *codec = socdev->card->codec;
262 struct wm8731_priv *wm8731 = codec->private_data; 218 struct wm8731_priv *wm8731 = codec->private_data;
263 u16 iface = wm8731_read_reg_cache(codec, WM8731_IFACE) & 0xfff3; 219 u16 iface = snd_soc_read(codec, WM8731_IFACE) & 0xfff3;
264 int i = get_coeff(wm8731->sysclk, params_rate(params)); 220 int i = get_coeff(wm8731->sysclk, params_rate(params));
265 u16 srate = (coeff_div[i].sr << 2) | 221 u16 srate = (coeff_div[i].sr << 2) |
266 (coeff_div[i].bosr << 1) | coeff_div[i].usb; 222 (coeff_div[i].bosr << 1) | coeff_div[i].usb;
267 223
268 wm8731_write(codec, WM8731_SRATE, srate); 224 snd_soc_write(codec, WM8731_SRATE, srate);
269 225
270 /* bit size */ 226 /* bit size */
271 switch (params_format(params)) { 227 switch (params_format(params)) {
@@ -279,7 +235,7 @@ static int wm8731_hw_params(struct snd_pcm_substream *substream,
279 break; 235 break;
280 } 236 }
281 237
282 wm8731_write(codec, WM8731_IFACE, iface); 238 snd_soc_write(codec, WM8731_IFACE, iface);
283 return 0; 239 return 0;
284} 240}
285 241
@@ -291,7 +247,7 @@ static int wm8731_pcm_prepare(struct snd_pcm_substream *substream,
291 struct snd_soc_codec *codec = socdev->card->codec; 247 struct snd_soc_codec *codec = socdev->card->codec;
292 248
293 /* set active */ 249 /* set active */
294 wm8731_write(codec, WM8731_ACTIVE, 0x0001); 250 snd_soc_write(codec, WM8731_ACTIVE, 0x0001);
295 251
296 return 0; 252 return 0;
297} 253}
@@ -306,19 +262,19 @@ static void wm8731_shutdown(struct snd_pcm_substream *substream,
306 /* deactivate */ 262 /* deactivate */
307 if (!codec->active) { 263 if (!codec->active) {
308 udelay(50); 264 udelay(50);
309 wm8731_write(codec, WM8731_ACTIVE, 0x0); 265 snd_soc_write(codec, WM8731_ACTIVE, 0x0);
310 } 266 }
311} 267}
312 268
313static int wm8731_mute(struct snd_soc_dai *dai, int mute) 269static int wm8731_mute(struct snd_soc_dai *dai, int mute)
314{ 270{
315 struct snd_soc_codec *codec = dai->codec; 271 struct snd_soc_codec *codec = dai->codec;
316 u16 mute_reg = wm8731_read_reg_cache(codec, WM8731_APDIGI) & 0xfff7; 272 u16 mute_reg = snd_soc_read(codec, WM8731_APDIGI) & 0xfff7;
317 273
318 if (mute) 274 if (mute)
319 wm8731_write(codec, WM8731_APDIGI, mute_reg | 0x8); 275 snd_soc_write(codec, WM8731_APDIGI, mute_reg | 0x8);
320 else 276 else
321 wm8731_write(codec, WM8731_APDIGI, mute_reg); 277 snd_soc_write(codec, WM8731_APDIGI, mute_reg);
322 return 0; 278 return 0;
323} 279}
324 280
@@ -396,7 +352,7 @@ static int wm8731_set_dai_fmt(struct snd_soc_dai *codec_dai,
396 } 352 }
397 353
398 /* set iface */ 354 /* set iface */
399 wm8731_write(codec, WM8731_IFACE, iface); 355 snd_soc_write(codec, WM8731_IFACE, iface);
400 return 0; 356 return 0;
401} 357}
402 358
@@ -412,12 +368,12 @@ static int wm8731_set_bias_level(struct snd_soc_codec *codec,
412 break; 368 break;
413 case SND_SOC_BIAS_STANDBY: 369 case SND_SOC_BIAS_STANDBY:
414 /* Clear PWROFF, gate CLKOUT, everything else as-is */ 370 /* Clear PWROFF, gate CLKOUT, everything else as-is */
415 reg = wm8731_read_reg_cache(codec, WM8731_PWR) & 0xff7f; 371 reg = snd_soc_read(codec, WM8731_PWR) & 0xff7f;
416 wm8731_write(codec, WM8731_PWR, reg | 0x0040); 372 snd_soc_write(codec, WM8731_PWR, reg | 0x0040);
417 break; 373 break;
418 case SND_SOC_BIAS_OFF: 374 case SND_SOC_BIAS_OFF:
419 wm8731_write(codec, WM8731_ACTIVE, 0x0); 375 snd_soc_write(codec, WM8731_ACTIVE, 0x0);
420 wm8731_write(codec, WM8731_PWR, 0xffff); 376 snd_soc_write(codec, WM8731_PWR, 0xffff);
421 break; 377 break;
422 } 378 }
423 codec->bias_level = level; 379 codec->bias_level = level;
@@ -457,15 +413,17 @@ struct snd_soc_dai wm8731_dai = {
457 .rates = WM8731_RATES, 413 .rates = WM8731_RATES,
458 .formats = WM8731_FORMATS,}, 414 .formats = WM8731_FORMATS,},
459 .ops = &wm8731_dai_ops, 415 .ops = &wm8731_dai_ops,
416 .symmetric_rates = 1,
460}; 417};
461EXPORT_SYMBOL_GPL(wm8731_dai); 418EXPORT_SYMBOL_GPL(wm8731_dai);
462 419
420#ifdef CONFIG_PM
463static int wm8731_suspend(struct platform_device *pdev, pm_message_t state) 421static int wm8731_suspend(struct platform_device *pdev, pm_message_t state)
464{ 422{
465 struct snd_soc_device *socdev = platform_get_drvdata(pdev); 423 struct snd_soc_device *socdev = platform_get_drvdata(pdev);
466 struct snd_soc_codec *codec = socdev->card->codec; 424 struct snd_soc_codec *codec = socdev->card->codec;
467 425
468 wm8731_write(codec, WM8731_ACTIVE, 0x0); 426 snd_soc_write(codec, WM8731_ACTIVE, 0x0);
469 wm8731_set_bias_level(codec, SND_SOC_BIAS_OFF); 427 wm8731_set_bias_level(codec, SND_SOC_BIAS_OFF);
470 return 0; 428 return 0;
471} 429}
@@ -488,6 +446,10 @@ static int wm8731_resume(struct platform_device *pdev)
488 wm8731_set_bias_level(codec, codec->suspend_bias_level); 446 wm8731_set_bias_level(codec, codec->suspend_bias_level);
489 return 0; 447 return 0;
490} 448}
449#else
450#define wm8731_suspend NULL
451#define wm8731_resume NULL
452#endif
491 453
492static int wm8731_probe(struct platform_device *pdev) 454static int wm8731_probe(struct platform_device *pdev)
493{ 455{
@@ -547,15 +509,16 @@ struct snd_soc_codec_device soc_codec_dev_wm8731 = {
547}; 509};
548EXPORT_SYMBOL_GPL(soc_codec_dev_wm8731); 510EXPORT_SYMBOL_GPL(soc_codec_dev_wm8731);
549 511
550static int wm8731_register(struct wm8731_priv *wm8731) 512static int wm8731_register(struct wm8731_priv *wm8731,
513 enum snd_soc_control_type control)
551{ 514{
552 int ret; 515 int ret;
553 struct snd_soc_codec *codec = &wm8731->codec; 516 struct snd_soc_codec *codec = &wm8731->codec;
554 u16 reg;
555 517
556 if (wm8731_codec) { 518 if (wm8731_codec) {
557 dev_err(codec->dev, "Another WM8731 is registered\n"); 519 dev_err(codec->dev, "Another WM8731 is registered\n");
558 return -EINVAL; 520 ret = -EINVAL;
521 goto err;
559 } 522 }
560 523
561 mutex_init(&codec->mutex); 524 mutex_init(&codec->mutex);
@@ -565,8 +528,6 @@ static int wm8731_register(struct wm8731_priv *wm8731)
565 codec->private_data = wm8731; 528 codec->private_data = wm8731;
566 codec->name = "WM8731"; 529 codec->name = "WM8731";
567 codec->owner = THIS_MODULE; 530 codec->owner = THIS_MODULE;
568 codec->read = wm8731_read_reg_cache;
569 codec->write = wm8731_write;
570 codec->bias_level = SND_SOC_BIAS_OFF; 531 codec->bias_level = SND_SOC_BIAS_OFF;
571 codec->set_bias_level = wm8731_set_bias_level; 532 codec->set_bias_level = wm8731_set_bias_level;
572 codec->dai = &wm8731_dai; 533 codec->dai = &wm8731_dai;
@@ -576,10 +537,16 @@ static int wm8731_register(struct wm8731_priv *wm8731)
576 537
577 memcpy(codec->reg_cache, wm8731_reg, sizeof(wm8731_reg)); 538 memcpy(codec->reg_cache, wm8731_reg, sizeof(wm8731_reg));
578 539
540 ret = snd_soc_codec_set_cache_io(codec, 7, 9, control);
541 if (ret < 0) {
542 dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret);
543 goto err;
544 }
545
579 ret = wm8731_reset(codec); 546 ret = wm8731_reset(codec);
580 if (ret < 0) { 547 if (ret < 0) {
581 dev_err(codec->dev, "Failed to issue reset\n"); 548 dev_err(codec->dev, "Failed to issue reset: %d\n", ret);
582 return ret; 549 goto err;
583 } 550 }
584 551
585 wm8731_dai.dev = codec->dev; 552 wm8731_dai.dev = codec->dev;
@@ -587,35 +554,36 @@ static int wm8731_register(struct wm8731_priv *wm8731)
587 wm8731_set_bias_level(codec, SND_SOC_BIAS_STANDBY); 554 wm8731_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
588 555
589 /* Latch the update bits */ 556 /* Latch the update bits */
590 reg = wm8731_read_reg_cache(codec, WM8731_LOUT1V); 557 snd_soc_update_bits(codec, WM8731_LOUT1V, 0x100, 0);
591 wm8731_write(codec, WM8731_LOUT1V, reg & ~0x0100); 558 snd_soc_update_bits(codec, WM8731_ROUT1V, 0x100, 0);
592 reg = wm8731_read_reg_cache(codec, WM8731_ROUT1V); 559 snd_soc_update_bits(codec, WM8731_LINVOL, 0x100, 0);
593 wm8731_write(codec, WM8731_ROUT1V, reg & ~0x0100); 560 snd_soc_update_bits(codec, WM8731_RINVOL, 0x100, 0);
594 reg = wm8731_read_reg_cache(codec, WM8731_LINVOL);
595 wm8731_write(codec, WM8731_LINVOL, reg & ~0x0100);
596 reg = wm8731_read_reg_cache(codec, WM8731_RINVOL);
597 wm8731_write(codec, WM8731_RINVOL, reg & ~0x0100);
598 561
599 /* Disable bypass path by default */ 562 /* Disable bypass path by default */
600 reg = wm8731_read_reg_cache(codec, WM8731_APANA); 563 snd_soc_update_bits(codec, WM8731_APANA, 0x4, 0);
601 wm8731_write(codec, WM8731_APANA, reg & ~0x4);
602 564
603 wm8731_codec = codec; 565 wm8731_codec = codec;
604 566
605 ret = snd_soc_register_codec(codec); 567 ret = snd_soc_register_codec(codec);
606 if (ret != 0) { 568 if (ret != 0) {
607 dev_err(codec->dev, "Failed to register codec: %d\n", ret); 569 dev_err(codec->dev, "Failed to register codec: %d\n", ret);
608 return ret; 570 goto err;
609 } 571 }
610 572
611 ret = snd_soc_register_dai(&wm8731_dai); 573 ret = snd_soc_register_dai(&wm8731_dai);
612 if (ret != 0) { 574 if (ret != 0) {
613 dev_err(codec->dev, "Failed to register DAI: %d\n", ret); 575 dev_err(codec->dev, "Failed to register DAI: %d\n", ret);
614 snd_soc_unregister_codec(codec); 576 snd_soc_unregister_codec(codec);
615 return ret; 577 goto err_codec;
616 } 578 }
617 579
618 return 0; 580 return 0;
581
582err_codec:
583 snd_soc_unregister_codec(codec);
584err:
585 kfree(wm8731);
586 return ret;
619} 587}
620 588
621static void wm8731_unregister(struct wm8731_priv *wm8731) 589static void wm8731_unregister(struct wm8731_priv *wm8731)
@@ -628,30 +596,6 @@ static void wm8731_unregister(struct wm8731_priv *wm8731)
628} 596}
629 597
630#if defined(CONFIG_SPI_MASTER) 598#if defined(CONFIG_SPI_MASTER)
631static int wm8731_spi_write(struct spi_device *spi, const char *data, int len)
632{
633 struct spi_transfer t;
634 struct spi_message m;
635 u8 msg[2];
636
637 if (len <= 0)
638 return 0;
639
640 msg[0] = data[0];
641 msg[1] = data[1];
642
643 spi_message_init(&m);
644 memset(&t, 0, (sizeof t));
645
646 t.tx_buf = &msg[0];
647 t.len = len;
648
649 spi_message_add_tail(&t, &m);
650 spi_sync(spi, &m);
651
652 return len;
653}
654
655static int __devinit wm8731_spi_probe(struct spi_device *spi) 599static int __devinit wm8731_spi_probe(struct spi_device *spi)
656{ 600{
657 struct snd_soc_codec *codec; 601 struct snd_soc_codec *codec;
@@ -663,23 +607,37 @@ static int __devinit wm8731_spi_probe(struct spi_device *spi)
663 607
664 codec = &wm8731->codec; 608 codec = &wm8731->codec;
665 codec->control_data = spi; 609 codec->control_data = spi;
666 codec->hw_write = (hw_write_t)wm8731_spi_write;
667 codec->dev = &spi->dev; 610 codec->dev = &spi->dev;
668 611
669 spi->dev.driver_data = wm8731; 612 dev_set_drvdata(&spi->dev, wm8731);
670 613
671 return wm8731_register(wm8731); 614 return wm8731_register(wm8731, SND_SOC_SPI);
672} 615}
673 616
674static int __devexit wm8731_spi_remove(struct spi_device *spi) 617static int __devexit wm8731_spi_remove(struct spi_device *spi)
675{ 618{
676 struct wm8731_priv *wm8731 = spi->dev.driver_data; 619 struct wm8731_priv *wm8731 = dev_get_drvdata(&spi->dev);
677 620
678 wm8731_unregister(wm8731); 621 wm8731_unregister(wm8731);
679 622
680 return 0; 623 return 0;
681} 624}
682 625
626#ifdef CONFIG_PM
627static int wm8731_spi_suspend(struct spi_device *spi, pm_message_t msg)
628{
629 return snd_soc_suspend_device(&spi->dev);
630}
631
632static int wm8731_spi_resume(struct spi_device *spi)
633{
634 return snd_soc_resume_device(&spi->dev);
635}
636#else
637#define wm8731_spi_suspend NULL
638#define wm8731_spi_resume NULL
639#endif
640
683static struct spi_driver wm8731_spi_driver = { 641static struct spi_driver wm8731_spi_driver = {
684 .driver = { 642 .driver = {
685 .name = "wm8731", 643 .name = "wm8731",
@@ -687,6 +645,8 @@ static struct spi_driver wm8731_spi_driver = {
687 .owner = THIS_MODULE, 645 .owner = THIS_MODULE,
688 }, 646 },
689 .probe = wm8731_spi_probe, 647 .probe = wm8731_spi_probe,
648 .suspend = wm8731_spi_suspend,
649 .resume = wm8731_spi_resume,
690 .remove = __devexit_p(wm8731_spi_remove), 650 .remove = __devexit_p(wm8731_spi_remove),
691}; 651};
692#endif /* CONFIG_SPI_MASTER */ 652#endif /* CONFIG_SPI_MASTER */
@@ -703,14 +663,13 @@ static __devinit int wm8731_i2c_probe(struct i2c_client *i2c,
703 return -ENOMEM; 663 return -ENOMEM;
704 664
705 codec = &wm8731->codec; 665 codec = &wm8731->codec;
706 codec->hw_write = (hw_write_t)i2c_master_send;
707 666
708 i2c_set_clientdata(i2c, wm8731); 667 i2c_set_clientdata(i2c, wm8731);
709 codec->control_data = i2c; 668 codec->control_data = i2c;
710 669
711 codec->dev = &i2c->dev; 670 codec->dev = &i2c->dev;
712 671
713 return wm8731_register(wm8731); 672 return wm8731_register(wm8731, SND_SOC_I2C);
714} 673}
715 674
716static __devexit int wm8731_i2c_remove(struct i2c_client *client) 675static __devexit int wm8731_i2c_remove(struct i2c_client *client)
@@ -720,6 +679,21 @@ static __devexit int wm8731_i2c_remove(struct i2c_client *client)
720 return 0; 679 return 0;
721} 680}
722 681
682#ifdef CONFIG_PM
683static int wm8731_i2c_suspend(struct i2c_client *i2c, pm_message_t msg)
684{
685 return snd_soc_suspend_device(&i2c->dev);
686}
687
688static int wm8731_i2c_resume(struct i2c_client *i2c)
689{
690 return snd_soc_resume_device(&i2c->dev);
691}
692#else
693#define wm8731_i2c_suspend NULL
694#define wm8731_i2c_resume NULL
695#endif
696
723static const struct i2c_device_id wm8731_i2c_id[] = { 697static const struct i2c_device_id wm8731_i2c_id[] = {
724 { "wm8731", 0 }, 698 { "wm8731", 0 },
725 { } 699 { }
@@ -733,6 +707,8 @@ static struct i2c_driver wm8731_i2c_driver = {
733 }, 707 },
734 .probe = wm8731_i2c_probe, 708 .probe = wm8731_i2c_probe,
735 .remove = __devexit_p(wm8731_i2c_remove), 709 .remove = __devexit_p(wm8731_i2c_remove),
710 .suspend = wm8731_i2c_suspend,
711 .resume = wm8731_i2c_resume,
736 .id_table = wm8731_i2c_id, 712 .id_table = wm8731_i2c_id,
737}; 713};
738#endif 714#endif
diff --git a/sound/soc/codecs/wm8750.c b/sound/soc/codecs/wm8750.c
index b64509b01a49..4ba1e7e93fb4 100644
--- a/sound/soc/codecs/wm8750.c
+++ b/sound/soc/codecs/wm8750.c
@@ -55,50 +55,7 @@ static const u16 wm8750_reg[] = {
55 0x0079, 0x0079, 0x0079, /* 40 */ 55 0x0079, 0x0079, 0x0079, /* 40 */
56}; 56};
57 57
58/* 58#define wm8750_reset(c) snd_soc_write(c, WM8750_RESET, 0)
59 * read wm8750 register cache
60 */
61static inline unsigned int wm8750_read_reg_cache(struct snd_soc_codec *codec,
62 unsigned int reg)
63{
64 u16 *cache = codec->reg_cache;
65 if (reg > WM8750_CACHE_REGNUM)
66 return -1;
67 return cache[reg];
68}
69
70/*
71 * write wm8750 register cache
72 */
73static inline void wm8750_write_reg_cache(struct snd_soc_codec *codec,
74 unsigned int reg, unsigned int value)
75{
76 u16 *cache = codec->reg_cache;
77 if (reg > WM8750_CACHE_REGNUM)
78 return;
79 cache[reg] = value;
80}
81
82static int wm8750_write(struct snd_soc_codec *codec, unsigned int reg,
83 unsigned int value)
84{
85 u8 data[2];
86
87 /* data is
88 * D15..D9 WM8753 register offset
89 * D8...D0 register data
90 */
91 data[0] = (reg << 1) | ((value >> 8) & 0x0001);
92 data[1] = value & 0x00ff;
93
94 wm8750_write_reg_cache(codec, reg, value);
95 if (codec->hw_write(codec->control_data, data, 2) == 2)
96 return 0;
97 else
98 return -EIO;
99}
100
101#define wm8750_reset(c) wm8750_write(c, WM8750_RESET, 0)
102 59
103/* 60/*
104 * WM8750 Controls 61 * WM8750 Controls
@@ -594,7 +551,7 @@ static int wm8750_set_dai_fmt(struct snd_soc_dai *codec_dai,
594 return -EINVAL; 551 return -EINVAL;
595 } 552 }
596 553
597 wm8750_write(codec, WM8750_IFACE, iface); 554 snd_soc_write(codec, WM8750_IFACE, iface);
598 return 0; 555 return 0;
599} 556}
600 557
@@ -606,8 +563,8 @@ static int wm8750_pcm_hw_params(struct snd_pcm_substream *substream,
606 struct snd_soc_device *socdev = rtd->socdev; 563 struct snd_soc_device *socdev = rtd->socdev;
607 struct snd_soc_codec *codec = socdev->card->codec; 564 struct snd_soc_codec *codec = socdev->card->codec;
608 struct wm8750_priv *wm8750 = codec->private_data; 565 struct wm8750_priv *wm8750 = codec->private_data;
609 u16 iface = wm8750_read_reg_cache(codec, WM8750_IFACE) & 0x1f3; 566 u16 iface = snd_soc_read(codec, WM8750_IFACE) & 0x1f3;
610 u16 srate = wm8750_read_reg_cache(codec, WM8750_SRATE) & 0x1c0; 567 u16 srate = snd_soc_read(codec, WM8750_SRATE) & 0x1c0;
611 int coeff = get_coeff(wm8750->sysclk, params_rate(params)); 568 int coeff = get_coeff(wm8750->sysclk, params_rate(params));
612 569
613 /* bit size */ 570 /* bit size */
@@ -626,9 +583,9 @@ static int wm8750_pcm_hw_params(struct snd_pcm_substream *substream,
626 } 583 }
627 584
628 /* set iface & srate */ 585 /* set iface & srate */
629 wm8750_write(codec, WM8750_IFACE, iface); 586 snd_soc_write(codec, WM8750_IFACE, iface);
630 if (coeff >= 0) 587 if (coeff >= 0)
631 wm8750_write(codec, WM8750_SRATE, srate | 588 snd_soc_write(codec, WM8750_SRATE, srate |
632 (coeff_div[coeff].sr << 1) | coeff_div[coeff].usb); 589 (coeff_div[coeff].sr << 1) | coeff_div[coeff].usb);
633 590
634 return 0; 591 return 0;
@@ -637,35 +594,35 @@ static int wm8750_pcm_hw_params(struct snd_pcm_substream *substream,
637static int wm8750_mute(struct snd_soc_dai *dai, int mute) 594static int wm8750_mute(struct snd_soc_dai *dai, int mute)
638{ 595{
639 struct snd_soc_codec *codec = dai->codec; 596 struct snd_soc_codec *codec = dai->codec;
640 u16 mute_reg = wm8750_read_reg_cache(codec, WM8750_ADCDAC) & 0xfff7; 597 u16 mute_reg = snd_soc_read(codec, WM8750_ADCDAC) & 0xfff7;
641 598
642 if (mute) 599 if (mute)
643 wm8750_write(codec, WM8750_ADCDAC, mute_reg | 0x8); 600 snd_soc_write(codec, WM8750_ADCDAC, mute_reg | 0x8);
644 else 601 else
645 wm8750_write(codec, WM8750_ADCDAC, mute_reg); 602 snd_soc_write(codec, WM8750_ADCDAC, mute_reg);
646 return 0; 603 return 0;
647} 604}
648 605
649static int wm8750_set_bias_level(struct snd_soc_codec *codec, 606static int wm8750_set_bias_level(struct snd_soc_codec *codec,
650 enum snd_soc_bias_level level) 607 enum snd_soc_bias_level level)
651{ 608{
652 u16 pwr_reg = wm8750_read_reg_cache(codec, WM8750_PWR1) & 0xfe3e; 609 u16 pwr_reg = snd_soc_read(codec, WM8750_PWR1) & 0xfe3e;
653 610
654 switch (level) { 611 switch (level) {
655 case SND_SOC_BIAS_ON: 612 case SND_SOC_BIAS_ON:
656 /* set vmid to 50k and unmute dac */ 613 /* set vmid to 50k and unmute dac */
657 wm8750_write(codec, WM8750_PWR1, pwr_reg | 0x00c0); 614 snd_soc_write(codec, WM8750_PWR1, pwr_reg | 0x00c0);
658 break; 615 break;
659 case SND_SOC_BIAS_PREPARE: 616 case SND_SOC_BIAS_PREPARE:
660 /* set vmid to 5k for quick power up */ 617 /* set vmid to 5k for quick power up */
661 wm8750_write(codec, WM8750_PWR1, pwr_reg | 0x01c1); 618 snd_soc_write(codec, WM8750_PWR1, pwr_reg | 0x01c1);
662 break; 619 break;
663 case SND_SOC_BIAS_STANDBY: 620 case SND_SOC_BIAS_STANDBY:
664 /* mute dac and set vmid to 500k, enable VREF */ 621 /* mute dac and set vmid to 500k, enable VREF */
665 wm8750_write(codec, WM8750_PWR1, pwr_reg | 0x0141); 622 snd_soc_write(codec, WM8750_PWR1, pwr_reg | 0x0141);
666 break; 623 break;
667 case SND_SOC_BIAS_OFF: 624 case SND_SOC_BIAS_OFF:
668 wm8750_write(codec, WM8750_PWR1, 0x0001); 625 snd_soc_write(codec, WM8750_PWR1, 0x0001);
669 break; 626 break;
670 } 627 }
671 codec->bias_level = level; 628 codec->bias_level = level;
@@ -754,15 +711,14 @@ static int wm8750_resume(struct platform_device *pdev)
754 * initialise the WM8750 driver 711 * initialise the WM8750 driver
755 * register the mixer and dsp interfaces with the kernel 712 * register the mixer and dsp interfaces with the kernel
756 */ 713 */
757static int wm8750_init(struct snd_soc_device *socdev) 714static int wm8750_init(struct snd_soc_device *socdev,
715 enum snd_soc_control_type control)
758{ 716{
759 struct snd_soc_codec *codec = socdev->card->codec; 717 struct snd_soc_codec *codec = socdev->card->codec;
760 int reg, ret = 0; 718 int reg, ret = 0;
761 719
762 codec->name = "WM8750"; 720 codec->name = "WM8750";
763 codec->owner = THIS_MODULE; 721 codec->owner = THIS_MODULE;
764 codec->read = wm8750_read_reg_cache;
765 codec->write = wm8750_write;
766 codec->set_bias_level = wm8750_set_bias_level; 722 codec->set_bias_level = wm8750_set_bias_level;
767 codec->dai = &wm8750_dai; 723 codec->dai = &wm8750_dai;
768 codec->num_dai = 1; 724 codec->num_dai = 1;
@@ -771,13 +727,23 @@ static int wm8750_init(struct snd_soc_device *socdev)
771 if (codec->reg_cache == NULL) 727 if (codec->reg_cache == NULL)
772 return -ENOMEM; 728 return -ENOMEM;
773 729
774 wm8750_reset(codec); 730 ret = snd_soc_codec_set_cache_io(codec, 7, 9, control);
731 if (ret < 0) {
732 printk(KERN_ERR "wm8750: failed to set cache I/O: %d\n", ret);
733 goto err;
734 }
735
736 ret = wm8750_reset(codec);
737 if (ret < 0) {
738 printk(KERN_ERR "wm8750: failed to reset: %d\n", ret);
739 goto err;
740 }
775 741
776 /* register pcms */ 742 /* register pcms */
777 ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1); 743 ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1);
778 if (ret < 0) { 744 if (ret < 0) {
779 printk(KERN_ERR "wm8750: failed to create pcms\n"); 745 printk(KERN_ERR "wm8750: failed to create pcms\n");
780 goto pcm_err; 746 goto err;
781 } 747 }
782 748
783 /* charge output caps */ 749 /* charge output caps */
@@ -786,22 +752,22 @@ static int wm8750_init(struct snd_soc_device *socdev)
786 schedule_delayed_work(&codec->delayed_work, msecs_to_jiffies(1000)); 752 schedule_delayed_work(&codec->delayed_work, msecs_to_jiffies(1000));
787 753
788 /* set the update bits */ 754 /* set the update bits */
789 reg = wm8750_read_reg_cache(codec, WM8750_LDAC); 755 reg = snd_soc_read(codec, WM8750_LDAC);
790 wm8750_write(codec, WM8750_LDAC, reg | 0x0100); 756 snd_soc_write(codec, WM8750_LDAC, reg | 0x0100);
791 reg = wm8750_read_reg_cache(codec, WM8750_RDAC); 757 reg = snd_soc_read(codec, WM8750_RDAC);
792 wm8750_write(codec, WM8750_RDAC, reg | 0x0100); 758 snd_soc_write(codec, WM8750_RDAC, reg | 0x0100);
793 reg = wm8750_read_reg_cache(codec, WM8750_LOUT1V); 759 reg = snd_soc_read(codec, WM8750_LOUT1V);
794 wm8750_write(codec, WM8750_LOUT1V, reg | 0x0100); 760 snd_soc_write(codec, WM8750_LOUT1V, reg | 0x0100);
795 reg = wm8750_read_reg_cache(codec, WM8750_ROUT1V); 761 reg = snd_soc_read(codec, WM8750_ROUT1V);
796 wm8750_write(codec, WM8750_ROUT1V, reg | 0x0100); 762 snd_soc_write(codec, WM8750_ROUT1V, reg | 0x0100);
797 reg = wm8750_read_reg_cache(codec, WM8750_LOUT2V); 763 reg = snd_soc_read(codec, WM8750_LOUT2V);
798 wm8750_write(codec, WM8750_LOUT2V, reg | 0x0100); 764 snd_soc_write(codec, WM8750_LOUT2V, reg | 0x0100);
799 reg = wm8750_read_reg_cache(codec, WM8750_ROUT2V); 765 reg = snd_soc_read(codec, WM8750_ROUT2V);
800 wm8750_write(codec, WM8750_ROUT2V, reg | 0x0100); 766 snd_soc_write(codec, WM8750_ROUT2V, reg | 0x0100);
801 reg = wm8750_read_reg_cache(codec, WM8750_LINVOL); 767 reg = snd_soc_read(codec, WM8750_LINVOL);
802 wm8750_write(codec, WM8750_LINVOL, reg | 0x0100); 768 snd_soc_write(codec, WM8750_LINVOL, reg | 0x0100);
803 reg = wm8750_read_reg_cache(codec, WM8750_RINVOL); 769 reg = snd_soc_read(codec, WM8750_RINVOL);
804 wm8750_write(codec, WM8750_RINVOL, reg | 0x0100); 770 snd_soc_write(codec, WM8750_RINVOL, reg | 0x0100);
805 771
806 snd_soc_add_controls(codec, wm8750_snd_controls, 772 snd_soc_add_controls(codec, wm8750_snd_controls,
807 ARRAY_SIZE(wm8750_snd_controls)); 773 ARRAY_SIZE(wm8750_snd_controls));
@@ -816,7 +782,7 @@ static int wm8750_init(struct snd_soc_device *socdev)
816card_err: 782card_err:
817 snd_soc_free_pcms(socdev); 783 snd_soc_free_pcms(socdev);
818 snd_soc_dapm_free(socdev); 784 snd_soc_dapm_free(socdev);
819pcm_err: 785err:
820 kfree(codec->reg_cache); 786 kfree(codec->reg_cache);
821 return ret; 787 return ret;
822} 788}
@@ -844,7 +810,7 @@ static int wm8750_i2c_probe(struct i2c_client *i2c,
844 i2c_set_clientdata(i2c, codec); 810 i2c_set_clientdata(i2c, codec);
845 codec->control_data = i2c; 811 codec->control_data = i2c;
846 812
847 ret = wm8750_init(socdev); 813 ret = wm8750_init(socdev, SND_SOC_I2C);
848 if (ret < 0) 814 if (ret < 0)
849 pr_err("failed to initialise WM8750\n"); 815 pr_err("failed to initialise WM8750\n");
850 816
@@ -924,7 +890,7 @@ static int __devinit wm8750_spi_probe(struct spi_device *spi)
924 890
925 codec->control_data = spi; 891 codec->control_data = spi;
926 892
927 ret = wm8750_init(socdev); 893 ret = wm8750_init(socdev, SND_SOC_SPI);
928 if (ret < 0) 894 if (ret < 0)
929 dev_err(&spi->dev, "failed to initialise WM8750\n"); 895 dev_err(&spi->dev, "failed to initialise WM8750\n");
930 896
@@ -945,30 +911,6 @@ static struct spi_driver wm8750_spi_driver = {
945 .probe = wm8750_spi_probe, 911 .probe = wm8750_spi_probe,
946 .remove = __devexit_p(wm8750_spi_remove), 912 .remove = __devexit_p(wm8750_spi_remove),
947}; 913};
948
949static int wm8750_spi_write(struct spi_device *spi, const char *data, int len)
950{
951 struct spi_transfer t;
952 struct spi_message m;
953 u8 msg[2];
954
955 if (len <= 0)
956 return 0;
957
958 msg[0] = data[0];
959 msg[1] = data[1];
960
961 spi_message_init(&m);
962 memset(&t, 0, (sizeof t));
963
964 t.tx_buf = &msg[0];
965 t.len = len;
966
967 spi_message_add_tail(&t, &m);
968 spi_sync(spi, &m);
969
970 return len;
971}
972#endif 914#endif
973 915
974static int wm8750_probe(struct platform_device *pdev) 916static int wm8750_probe(struct platform_device *pdev)
@@ -1002,13 +944,11 @@ static int wm8750_probe(struct platform_device *pdev)
1002 944
1003#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) 945#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
1004 if (setup->i2c_address) { 946 if (setup->i2c_address) {
1005 codec->hw_write = (hw_write_t)i2c_master_send;
1006 ret = wm8750_add_i2c_device(pdev, setup); 947 ret = wm8750_add_i2c_device(pdev, setup);
1007 } 948 }
1008#endif 949#endif
1009#if defined(CONFIG_SPI_MASTER) 950#if defined(CONFIG_SPI_MASTER)
1010 if (setup->spi) { 951 if (setup->spi) {
1011 codec->hw_write = (hw_write_t)wm8750_spi_write;
1012 ret = spi_register_driver(&wm8750_spi_driver); 952 ret = spi_register_driver(&wm8750_spi_driver);
1013 if (ret != 0) 953 if (ret != 0)
1014 printk(KERN_ERR "can't add spi driver"); 954 printk(KERN_ERR "can't add spi driver");
diff --git a/sound/soc/codecs/wm8753.c b/sound/soc/codecs/wm8753.c
index a6e8f3f7f052..d80d414cfbbd 100644
--- a/sound/soc/codecs/wm8753.c
+++ b/sound/soc/codecs/wm8753.c
@@ -79,7 +79,7 @@ static const u16 wm8753_reg[] = {
79 0x0097, 0x0097, 0x0000, 0x0004, 79 0x0097, 0x0097, 0x0000, 0x0004,
80 0x0000, 0x0083, 0x0024, 0x01ba, 80 0x0000, 0x0083, 0x0024, 0x01ba,
81 0x0000, 0x0083, 0x0024, 0x01ba, 81 0x0000, 0x0083, 0x0024, 0x01ba,
82 0x0000, 0x0000 82 0x0000, 0x0000, 0x0000
83}; 83};
84 84
85/* codec private data */ 85/* codec private data */
@@ -703,7 +703,7 @@ static void pll_factors(struct _pll_div *pll_div, unsigned int target,
703 703
704 if ((Ndiv < 6) || (Ndiv > 12)) 704 if ((Ndiv < 6) || (Ndiv > 12))
705 printk(KERN_WARNING 705 printk(KERN_WARNING
706 "wm8753: unsupported N = %d\n", Ndiv); 706 "wm8753: unsupported N = %u\n", Ndiv);
707 707
708 pll_div->n = Ndiv; 708 pll_div->n = Ndiv;
709 Nmod = target % source; 709 Nmod = target % source;
@@ -1660,11 +1660,11 @@ static int wm8753_register(struct wm8753_priv *wm8753)
1660 codec->set_bias_level = wm8753_set_bias_level; 1660 codec->set_bias_level = wm8753_set_bias_level;
1661 codec->dai = wm8753_dai; 1661 codec->dai = wm8753_dai;
1662 codec->num_dai = 2; 1662 codec->num_dai = 2;
1663 codec->reg_cache_size = ARRAY_SIZE(wm8753->reg_cache); 1663 codec->reg_cache_size = ARRAY_SIZE(wm8753->reg_cache) + 1;
1664 codec->reg_cache = &wm8753->reg_cache; 1664 codec->reg_cache = &wm8753->reg_cache;
1665 codec->private_data = wm8753; 1665 codec->private_data = wm8753;
1666 1666
1667 memcpy(codec->reg_cache, wm8753_reg, sizeof(codec->reg_cache)); 1667 memcpy(codec->reg_cache, wm8753_reg, sizeof(wm8753->reg_cache));
1668 INIT_DELAYED_WORK(&codec->delayed_work, wm8753_work); 1668 INIT_DELAYED_WORK(&codec->delayed_work, wm8753_work);
1669 1669
1670 ret = wm8753_reset(codec); 1670 ret = wm8753_reset(codec);
@@ -1766,6 +1766,21 @@ static int wm8753_i2c_remove(struct i2c_client *client)
1766 return 0; 1766 return 0;
1767} 1767}
1768 1768
1769#ifdef CONFIG_PM
1770static int wm8753_i2c_suspend(struct i2c_client *client, pm_message_t msg)
1771{
1772 return snd_soc_suspend_device(&client->dev);
1773}
1774
1775static int wm8753_i2c_resume(struct i2c_client *client)
1776{
1777 return snd_soc_resume_device(&client->dev);
1778}
1779#else
1780#define wm8753_i2c_suspend NULL
1781#define wm8753_i2c_resume NULL
1782#endif
1783
1769static const struct i2c_device_id wm8753_i2c_id[] = { 1784static const struct i2c_device_id wm8753_i2c_id[] = {
1770 { "wm8753", 0 }, 1785 { "wm8753", 0 },
1771 { } 1786 { }
@@ -1779,6 +1794,8 @@ static struct i2c_driver wm8753_i2c_driver = {
1779 }, 1794 },
1780 .probe = wm8753_i2c_probe, 1795 .probe = wm8753_i2c_probe,
1781 .remove = wm8753_i2c_remove, 1796 .remove = wm8753_i2c_remove,
1797 .suspend = wm8753_i2c_suspend,
1798 .resume = wm8753_i2c_resume,
1782 .id_table = wm8753_i2c_id, 1799 .id_table = wm8753_i2c_id,
1783}; 1800};
1784#endif 1801#endif
@@ -1822,18 +1839,34 @@ static int __devinit wm8753_spi_probe(struct spi_device *spi)
1822 codec->hw_write = (hw_write_t)wm8753_spi_write; 1839 codec->hw_write = (hw_write_t)wm8753_spi_write;
1823 codec->dev = &spi->dev; 1840 codec->dev = &spi->dev;
1824 1841
1825 spi->dev.driver_data = wm8753; 1842 dev_set_drvdata(&spi->dev, wm8753);
1826 1843
1827 return wm8753_register(wm8753); 1844 return wm8753_register(wm8753);
1828} 1845}
1829 1846
1830static int __devexit wm8753_spi_remove(struct spi_device *spi) 1847static int __devexit wm8753_spi_remove(struct spi_device *spi)
1831{ 1848{
1832 struct wm8753_priv *wm8753 = spi->dev.driver_data; 1849 struct wm8753_priv *wm8753 = dev_get_drvdata(&spi->dev);
1833 wm8753_unregister(wm8753); 1850 wm8753_unregister(wm8753);
1834 return 0; 1851 return 0;
1835} 1852}
1836 1853
1854#ifdef CONFIG_PM
1855static int wm8753_spi_suspend(struct spi_device *spi, pm_message_t msg)
1856{
1857 return snd_soc_suspend_device(&spi->dev);
1858}
1859
1860static int wm8753_spi_resume(struct spi_device *spi)
1861{
1862 return snd_soc_resume_device(&spi->dev);
1863}
1864
1865#else
1866#define wm8753_spi_suspend NULL
1867#define wm8753_spi_resume NULL
1868#endif
1869
1837static struct spi_driver wm8753_spi_driver = { 1870static struct spi_driver wm8753_spi_driver = {
1838 .driver = { 1871 .driver = {
1839 .name = "wm8753", 1872 .name = "wm8753",
@@ -1842,6 +1875,8 @@ static struct spi_driver wm8753_spi_driver = {
1842 }, 1875 },
1843 .probe = wm8753_spi_probe, 1876 .probe = wm8753_spi_probe,
1844 .remove = __devexit_p(wm8753_spi_remove), 1877 .remove = __devexit_p(wm8753_spi_remove),
1878 .suspend = wm8753_spi_suspend,
1879 .resume = wm8753_spi_resume,
1845}; 1880};
1846#endif 1881#endif
1847 1882
diff --git a/sound/soc/codecs/wm8776.c b/sound/soc/codecs/wm8776.c
new file mode 100644
index 000000000000..a9829aa26e53
--- /dev/null
+++ b/sound/soc/codecs/wm8776.c
@@ -0,0 +1,744 @@
1/*
2 * wm8776.c -- WM8776 ALSA SoC Audio driver
3 *
4 * Copyright 2009 Wolfson Microelectronics plc
5 *
6 * Author: Mark Brown <broonie@opensource.wolfsonmicro.com>
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License version 2 as
10 * published by the Free Software Foundation.
11 *
12 * TODO: Input ALC/limiter support
13 */
14
15#include <linux/module.h>
16#include <linux/moduleparam.h>
17#include <linux/init.h>
18#include <linux/delay.h>
19#include <linux/pm.h>
20#include <linux/i2c.h>
21#include <linux/platform_device.h>
22#include <linux/spi/spi.h>
23#include <sound/core.h>
24#include <sound/pcm.h>
25#include <sound/pcm_params.h>
26#include <sound/soc.h>
27#include <sound/soc-dapm.h>
28#include <sound/initval.h>
29#include <sound/tlv.h>
30
31#include "wm8776.h"
32
33static struct snd_soc_codec *wm8776_codec;
34struct snd_soc_codec_device soc_codec_dev_wm8776;
35
36/* codec private data */
37struct wm8776_priv {
38 struct snd_soc_codec codec;
39 u16 reg_cache[WM8776_CACHEREGNUM];
40 int sysclk[2];
41};
42
43#ifdef CONFIG_SPI_MASTER
44static int wm8776_spi_write(struct spi_device *spi, const char *data, int len);
45#endif
46
47static const u16 wm8776_reg[WM8776_CACHEREGNUM] = {
48 0x79, 0x79, 0x79, 0xff, 0xff, /* 4 */
49 0xff, 0x00, 0x90, 0x00, 0x00, /* 9 */
50 0x22, 0x22, 0x22, 0x08, 0xcf, /* 14 */
51 0xcf, 0x7b, 0x00, 0x32, 0x00, /* 19 */
52 0xa6, 0x01, 0x01
53};
54
55static int wm8776_reset(struct snd_soc_codec *codec)
56{
57 return snd_soc_write(codec, WM8776_RESET, 0);
58}
59
60static const DECLARE_TLV_DB_SCALE(hp_tlv, -12100, 100, 1);
61static const DECLARE_TLV_DB_SCALE(dac_tlv, -12750, 50, 1);
62static const DECLARE_TLV_DB_SCALE(adc_tlv, -10350, 50, 1);
63
64static const struct snd_kcontrol_new wm8776_snd_controls[] = {
65SOC_DOUBLE_R_TLV("Headphone Playback Volume", WM8776_HPLVOL, WM8776_HPRVOL,
66 0, 127, 0, hp_tlv),
67SOC_DOUBLE_R_TLV("Digital Playback Volume", WM8776_DACLVOL, WM8776_DACRVOL,
68 0, 255, 0, dac_tlv),
69SOC_SINGLE("Digital Playback ZC Switch", WM8776_DACCTRL1, 0, 1, 0),
70
71SOC_SINGLE("Deemphasis Switch", WM8776_DACCTRL2, 0, 1, 0),
72
73SOC_DOUBLE_R_TLV("Capture Volume", WM8776_ADCLVOL, WM8776_ADCRVOL,
74 0, 255, 0, adc_tlv),
75SOC_DOUBLE("Capture Switch", WM8776_ADCMUX, 7, 6, 1, 1),
76SOC_DOUBLE_R("Capture ZC Switch", WM8776_ADCLVOL, WM8776_ADCRVOL, 8, 1, 0),
77SOC_SINGLE("Capture HPF Switch", WM8776_ADCIFCTRL, 8, 1, 1),
78};
79
80static const struct snd_kcontrol_new inmix_controls[] = {
81SOC_DAPM_SINGLE("AIN1 Switch", WM8776_ADCMUX, 0, 1, 0),
82SOC_DAPM_SINGLE("AIN2 Switch", WM8776_ADCMUX, 1, 1, 0),
83SOC_DAPM_SINGLE("AIN3 Switch", WM8776_ADCMUX, 2, 1, 0),
84SOC_DAPM_SINGLE("AIN4 Switch", WM8776_ADCMUX, 3, 1, 0),
85SOC_DAPM_SINGLE("AIN5 Switch", WM8776_ADCMUX, 4, 1, 0),
86};
87
88static const struct snd_kcontrol_new outmix_controls[] = {
89SOC_DAPM_SINGLE("DAC Switch", WM8776_OUTMUX, 0, 1, 0),
90SOC_DAPM_SINGLE("AUX Switch", WM8776_OUTMUX, 1, 1, 0),
91SOC_DAPM_SINGLE("Bypass Switch", WM8776_OUTMUX, 2, 1, 0),
92};
93
94static const struct snd_soc_dapm_widget wm8776_dapm_widgets[] = {
95SND_SOC_DAPM_INPUT("AUX"),
96SND_SOC_DAPM_INPUT("AUX"),
97
98SND_SOC_DAPM_INPUT("AIN1"),
99SND_SOC_DAPM_INPUT("AIN2"),
100SND_SOC_DAPM_INPUT("AIN3"),
101SND_SOC_DAPM_INPUT("AIN4"),
102SND_SOC_DAPM_INPUT("AIN5"),
103
104SND_SOC_DAPM_MIXER("Input Mixer", WM8776_PWRDOWN, 6, 1,
105 inmix_controls, ARRAY_SIZE(inmix_controls)),
106
107SND_SOC_DAPM_ADC("ADC", "Capture", WM8776_PWRDOWN, 1, 1),
108SND_SOC_DAPM_DAC("DAC", "Playback", WM8776_PWRDOWN, 2, 1),
109
110SND_SOC_DAPM_MIXER("Output Mixer", SND_SOC_NOPM, 0, 0,
111 outmix_controls, ARRAY_SIZE(outmix_controls)),
112
113SND_SOC_DAPM_PGA("Headphone PGA", WM8776_PWRDOWN, 3, 1, NULL, 0),
114
115SND_SOC_DAPM_OUTPUT("VOUT"),
116
117SND_SOC_DAPM_OUTPUT("HPOUTL"),
118SND_SOC_DAPM_OUTPUT("HPOUTR"),
119};
120
121static const struct snd_soc_dapm_route routes[] = {
122 { "Input Mixer", "AIN1 Switch", "AIN1" },
123 { "Input Mixer", "AIN2 Switch", "AIN2" },
124 { "Input Mixer", "AIN3 Switch", "AIN3" },
125 { "Input Mixer", "AIN4 Switch", "AIN4" },
126 { "Input Mixer", "AIN5 Switch", "AIN5" },
127
128 { "ADC", NULL, "Input Mixer" },
129
130 { "Output Mixer", "DAC Switch", "DAC" },
131 { "Output Mixer", "AUX Switch", "AUX" },
132 { "Output Mixer", "Bypass Switch", "Input Mixer" },
133
134 { "VOUT", NULL, "Output Mixer" },
135
136 { "Headphone PGA", NULL, "Output Mixer" },
137
138 { "HPOUTL", NULL, "Headphone PGA" },
139 { "HPOUTR", NULL, "Headphone PGA" },
140};
141
142static int wm8776_set_fmt(struct snd_soc_dai *dai, unsigned int fmt)
143{
144 struct snd_soc_codec *codec = dai->codec;
145 int reg, iface, master;
146
147 switch (dai->id) {
148 case WM8776_DAI_DAC:
149 reg = WM8776_DACIFCTRL;
150 master = 0x80;
151 break;
152 case WM8776_DAI_ADC:
153 reg = WM8776_ADCIFCTRL;
154 master = 0x100;
155 break;
156 default:
157 return -EINVAL;
158 }
159
160 iface = 0;
161
162 switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
163 case SND_SOC_DAIFMT_CBM_CFM:
164 break;
165 case SND_SOC_DAIFMT_CBS_CFS:
166 master = 0;
167 break;
168 default:
169 return -EINVAL;
170 }
171
172 switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
173 case SND_SOC_DAIFMT_I2S:
174 iface |= 0x0002;
175 break;
176 case SND_SOC_DAIFMT_RIGHT_J:
177 break;
178 case SND_SOC_DAIFMT_LEFT_J:
179 iface |= 0x0001;
180 break;
181 /* FIXME: CHECK A/B */
182 case SND_SOC_DAIFMT_DSP_A:
183 iface |= 0x0003;
184 break;
185 case SND_SOC_DAIFMT_DSP_B:
186 iface |= 0x0007;
187 break;
188 default:
189 return -EINVAL;
190 }
191
192 switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
193 case SND_SOC_DAIFMT_NB_NF:
194 break;
195 case SND_SOC_DAIFMT_IB_IF:
196 iface |= 0x00c;
197 break;
198 case SND_SOC_DAIFMT_IB_NF:
199 iface |= 0x008;
200 break;
201 case SND_SOC_DAIFMT_NB_IF:
202 iface |= 0x004;
203 break;
204 default:
205 return -EINVAL;
206 }
207
208 /* Finally, write out the values */
209 snd_soc_update_bits(codec, reg, 0xf, iface);
210 snd_soc_update_bits(codec, WM8776_MSTRCTRL, 0x180, master);
211
212 return 0;
213}
214
215static int mclk_ratios[] = {
216 128,
217 192,
218 256,
219 384,
220 512,
221 768,
222};
223
224static int wm8776_hw_params(struct snd_pcm_substream *substream,
225 struct snd_pcm_hw_params *params,
226 struct snd_soc_dai *dai)
227{
228 struct snd_soc_codec *codec = dai->codec;
229 struct wm8776_priv *wm8776 = codec->private_data;
230 int iface_reg, iface;
231 int ratio_shift, master;
232 int i;
233
234 iface = 0;
235
236 switch (dai->id) {
237 case WM8776_DAI_DAC:
238 iface_reg = WM8776_DACIFCTRL;
239 master = 0x80;
240 ratio_shift = 4;
241 break;
242 case WM8776_DAI_ADC:
243 iface_reg = WM8776_ADCIFCTRL;
244 master = 0x100;
245 ratio_shift = 0;
246 break;
247 default:
248 return -EINVAL;
249 }
250
251
252 /* Set word length */
253 switch (params_format(params)) {
254 case SNDRV_PCM_FORMAT_S16_LE:
255 break;
256 case SNDRV_PCM_FORMAT_S20_3LE:
257 iface |= 0x10;
258 break;
259 case SNDRV_PCM_FORMAT_S24_LE:
260 iface |= 0x20;
261 break;
262 case SNDRV_PCM_FORMAT_S32_LE:
263 iface |= 0x30;
264 break;
265 }
266
267 /* Only need to set MCLK/LRCLK ratio if we're master */
268 if (snd_soc_read(codec, WM8776_MSTRCTRL) & master) {
269 for (i = 0; i < ARRAY_SIZE(mclk_ratios); i++) {
270 if (wm8776->sysclk[dai->id] / params_rate(params)
271 == mclk_ratios[i])
272 break;
273 }
274
275 if (i == ARRAY_SIZE(mclk_ratios)) {
276 dev_err(codec->dev,
277 "Unable to configure MCLK ratio %d/%d\n",
278 wm8776->sysclk[dai->id], params_rate(params));
279 return -EINVAL;
280 }
281
282 dev_dbg(codec->dev, "MCLK is %dfs\n", mclk_ratios[i]);
283
284 snd_soc_update_bits(codec, WM8776_MSTRCTRL,
285 0x7 << ratio_shift, i << ratio_shift);
286 } else {
287 dev_dbg(codec->dev, "DAI in slave mode\n");
288 }
289
290 snd_soc_update_bits(codec, iface_reg, 0x30, iface);
291
292 return 0;
293}
294
295static int wm8776_mute(struct snd_soc_dai *dai, int mute)
296{
297 struct snd_soc_codec *codec = dai->codec;
298
299 return snd_soc_write(codec, WM8776_DACMUTE, !!mute);
300}
301
302static int wm8776_set_sysclk(struct snd_soc_dai *dai,
303 int clk_id, unsigned int freq, int dir)
304{
305 struct snd_soc_codec *codec = dai->codec;
306 struct wm8776_priv *wm8776 = codec->private_data;
307
308 BUG_ON(dai->id >= ARRAY_SIZE(wm8776->sysclk));
309
310 wm8776->sysclk[dai->id] = freq;
311
312 return 0;
313}
314
315static int wm8776_set_bias_level(struct snd_soc_codec *codec,
316 enum snd_soc_bias_level level)
317{
318 switch (level) {
319 case SND_SOC_BIAS_ON:
320 break;
321 case SND_SOC_BIAS_PREPARE:
322 break;
323 case SND_SOC_BIAS_STANDBY:
324 if (codec->bias_level == SND_SOC_BIAS_OFF) {
325 /* Disable the global powerdown; DAPM does the rest */
326 snd_soc_update_bits(codec, WM8776_PWRDOWN, 1, 0);
327 }
328
329 break;
330 case SND_SOC_BIAS_OFF:
331 snd_soc_update_bits(codec, WM8776_PWRDOWN, 1, 1);
332 break;
333 }
334
335 codec->bias_level = level;
336 return 0;
337}
338
339#define WM8776_RATES (SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_44100 |\
340 SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_88200 |\
341 SNDRV_PCM_RATE_96000)
342
343
344#define WM8776_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE |\
345 SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S32_LE)
346
347static struct snd_soc_dai_ops wm8776_dac_ops = {
348 .digital_mute = wm8776_mute,
349 .hw_params = wm8776_hw_params,
350 .set_fmt = wm8776_set_fmt,
351 .set_sysclk = wm8776_set_sysclk,
352};
353
354static struct snd_soc_dai_ops wm8776_adc_ops = {
355 .hw_params = wm8776_hw_params,
356 .set_fmt = wm8776_set_fmt,
357 .set_sysclk = wm8776_set_sysclk,
358};
359
360struct snd_soc_dai wm8776_dai[] = {
361 {
362 .name = "WM8776 Playback",
363 .id = WM8776_DAI_DAC,
364 .playback = {
365 .stream_name = "Playback",
366 .channels_min = 2,
367 .channels_max = 2,
368 .rates = WM8776_RATES,
369 .formats = WM8776_FORMATS,
370 },
371 .ops = &wm8776_dac_ops,
372 },
373 {
374 .name = "WM8776 Capture",
375 .id = WM8776_DAI_ADC,
376 .capture = {
377 .stream_name = "Capture",
378 .channels_min = 2,
379 .channels_max = 2,
380 .rates = WM8776_RATES,
381 .formats = WM8776_FORMATS,
382 },
383 .ops = &wm8776_adc_ops,
384 },
385};
386EXPORT_SYMBOL_GPL(wm8776_dai);
387
388#ifdef CONFIG_PM
389static int wm8776_suspend(struct platform_device *pdev, pm_message_t state)
390{
391 struct snd_soc_device *socdev = platform_get_drvdata(pdev);
392 struct snd_soc_codec *codec = socdev->card->codec;
393
394 wm8776_set_bias_level(codec, SND_SOC_BIAS_OFF);
395
396 return 0;
397}
398
399static int wm8776_resume(struct platform_device *pdev)
400{
401 struct snd_soc_device *socdev = platform_get_drvdata(pdev);
402 struct snd_soc_codec *codec = socdev->card->codec;
403 int i;
404 u8 data[2];
405 u16 *cache = codec->reg_cache;
406
407 /* Sync reg_cache with the hardware */
408 for (i = 0; i < ARRAY_SIZE(wm8776_reg); i++) {
409 data[0] = (i << 1) | ((cache[i] >> 8) & 0x0001);
410 data[1] = cache[i] & 0x00ff;
411 codec->hw_write(codec->control_data, data, 2);
412 }
413
414 wm8776_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
415
416 return 0;
417}
418#else
419#define wm8776_suspend NULL
420#define wm8776_resume NULL
421#endif
422
423static int wm8776_probe(struct platform_device *pdev)
424{
425 struct snd_soc_device *socdev = platform_get_drvdata(pdev);
426 struct snd_soc_codec *codec;
427 int ret = 0;
428
429 if (wm8776_codec == NULL) {
430 dev_err(&pdev->dev, "Codec device not registered\n");
431 return -ENODEV;
432 }
433
434 socdev->card->codec = wm8776_codec;
435 codec = wm8776_codec;
436
437 /* register pcms */
438 ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1);
439 if (ret < 0) {
440 dev_err(codec->dev, "failed to create pcms: %d\n", ret);
441 goto pcm_err;
442 }
443
444 snd_soc_add_controls(codec, wm8776_snd_controls,
445 ARRAY_SIZE(wm8776_snd_controls));
446 snd_soc_dapm_new_controls(codec, wm8776_dapm_widgets,
447 ARRAY_SIZE(wm8776_dapm_widgets));
448 snd_soc_dapm_add_routes(codec, routes, ARRAY_SIZE(routes));
449
450 ret = snd_soc_init_card(socdev);
451 if (ret < 0) {
452 dev_err(codec->dev, "failed to register card: %d\n", ret);
453 goto card_err;
454 }
455
456 return ret;
457
458card_err:
459 snd_soc_free_pcms(socdev);
460 snd_soc_dapm_free(socdev);
461pcm_err:
462 return ret;
463}
464
465/* power down chip */
466static int wm8776_remove(struct platform_device *pdev)
467{
468 struct snd_soc_device *socdev = platform_get_drvdata(pdev);
469
470 snd_soc_free_pcms(socdev);
471 snd_soc_dapm_free(socdev);
472
473 return 0;
474}
475
476struct snd_soc_codec_device soc_codec_dev_wm8776 = {
477 .probe = wm8776_probe,
478 .remove = wm8776_remove,
479 .suspend = wm8776_suspend,
480 .resume = wm8776_resume,
481};
482EXPORT_SYMBOL_GPL(soc_codec_dev_wm8776);
483
484static int wm8776_register(struct wm8776_priv *wm8776,
485 enum snd_soc_control_type control)
486{
487 int ret, i;
488 struct snd_soc_codec *codec = &wm8776->codec;
489
490 if (wm8776_codec) {
491 dev_err(codec->dev, "Another WM8776 is registered\n");
492 ret = -EINVAL;
493 goto err;
494 }
495
496 mutex_init(&codec->mutex);
497 INIT_LIST_HEAD(&codec->dapm_widgets);
498 INIT_LIST_HEAD(&codec->dapm_paths);
499
500 codec->private_data = wm8776;
501 codec->name = "WM8776";
502 codec->owner = THIS_MODULE;
503 codec->bias_level = SND_SOC_BIAS_OFF;
504 codec->set_bias_level = wm8776_set_bias_level;
505 codec->dai = wm8776_dai;
506 codec->num_dai = ARRAY_SIZE(wm8776_dai);
507 codec->reg_cache_size = WM8776_CACHEREGNUM;
508 codec->reg_cache = &wm8776->reg_cache;
509
510 memcpy(codec->reg_cache, wm8776_reg, sizeof(wm8776_reg));
511
512 ret = snd_soc_codec_set_cache_io(codec, 7, 9, control);
513 if (ret < 0) {
514 dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret);
515 goto err;
516 }
517
518 for (i = 0; i < ARRAY_SIZE(wm8776_dai); i++)
519 wm8776_dai[i].dev = codec->dev;
520
521 ret = wm8776_reset(codec);
522 if (ret < 0) {
523 dev_err(codec->dev, "Failed to issue reset: %d\n", ret);
524 goto err;
525 }
526
527 wm8776_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
528
529 /* Latch the update bits; right channel only since we always
530 * update both. */
531 snd_soc_update_bits(codec, WM8776_HPRVOL, 0x100, 0x100);
532 snd_soc_update_bits(codec, WM8776_DACRVOL, 0x100, 0x100);
533
534 wm8776_codec = codec;
535
536 ret = snd_soc_register_codec(codec);
537 if (ret != 0) {
538 dev_err(codec->dev, "Failed to register codec: %d\n", ret);
539 goto err;
540 }
541
542 ret = snd_soc_register_dais(wm8776_dai, ARRAY_SIZE(wm8776_dai));
543 if (ret != 0) {
544 dev_err(codec->dev, "Failed to register DAIs: %d\n", ret);
545 goto err_codec;
546 }
547
548 return 0;
549
550err_codec:
551 snd_soc_unregister_codec(codec);
552err:
553 kfree(wm8776);
554 return ret;
555}
556
557static void wm8776_unregister(struct wm8776_priv *wm8776)
558{
559 wm8776_set_bias_level(&wm8776->codec, SND_SOC_BIAS_OFF);
560 snd_soc_unregister_dais(wm8776_dai, ARRAY_SIZE(wm8776_dai));
561 snd_soc_unregister_codec(&wm8776->codec);
562 kfree(wm8776);
563 wm8776_codec = NULL;
564}
565
566#if defined(CONFIG_SPI_MASTER)
567static int wm8776_spi_write(struct spi_device *spi, const char *data, int len)
568{
569 struct spi_transfer t;
570 struct spi_message m;
571 u8 msg[2];
572
573 if (len <= 0)
574 return 0;
575
576 msg[0] = data[0];
577 msg[1] = data[1];
578
579 spi_message_init(&m);
580 memset(&t, 0, (sizeof t));
581
582 t.tx_buf = &msg[0];
583 t.len = len;
584
585 spi_message_add_tail(&t, &m);
586 spi_sync(spi, &m);
587
588 return len;
589}
590
591static int __devinit wm8776_spi_probe(struct spi_device *spi)
592{
593 struct snd_soc_codec *codec;
594 struct wm8776_priv *wm8776;
595
596 wm8776 = kzalloc(sizeof(struct wm8776_priv), GFP_KERNEL);
597 if (wm8776 == NULL)
598 return -ENOMEM;
599
600 codec = &wm8776->codec;
601 codec->control_data = spi;
602 codec->hw_write = (hw_write_t)wm8776_spi_write;
603 codec->dev = &spi->dev;
604
605 dev_set_drvdata(&spi->dev, wm8776);
606
607 return wm8776_register(wm8776, SND_SOC_SPI);
608}
609
610static int __devexit wm8776_spi_remove(struct spi_device *spi)
611{
612 struct wm8776_priv *wm8776 = dev_get_drvdata(&spi->dev);
613
614 wm8776_unregister(wm8776);
615
616 return 0;
617}
618
619#ifdef CONFIG_PM
620static int wm8776_spi_suspend(struct spi_device *spi, pm_message_t msg)
621{
622 return snd_soc_suspend_device(&spi->dev);
623}
624
625static int wm8776_spi_resume(struct spi_device *spi)
626{
627 return snd_soc_resume_device(&spi->dev);
628}
629#else
630#define wm8776_spi_suspend NULL
631#define wm8776_spi_resume NULL
632#endif
633
634static struct spi_driver wm8776_spi_driver = {
635 .driver = {
636 .name = "wm8776",
637 .bus = &spi_bus_type,
638 .owner = THIS_MODULE,
639 },
640 .probe = wm8776_spi_probe,
641 .suspend = wm8776_spi_suspend,
642 .resume = wm8776_spi_resume,
643 .remove = __devexit_p(wm8776_spi_remove),
644};
645#endif /* CONFIG_SPI_MASTER */
646
647#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
648static __devinit int wm8776_i2c_probe(struct i2c_client *i2c,
649 const struct i2c_device_id *id)
650{
651 struct wm8776_priv *wm8776;
652 struct snd_soc_codec *codec;
653
654 wm8776 = kzalloc(sizeof(struct wm8776_priv), GFP_KERNEL);
655 if (wm8776 == NULL)
656 return -ENOMEM;
657
658 codec = &wm8776->codec;
659 codec->hw_write = (hw_write_t)i2c_master_send;
660
661 i2c_set_clientdata(i2c, wm8776);
662 codec->control_data = i2c;
663
664 codec->dev = &i2c->dev;
665
666 return wm8776_register(wm8776, SND_SOC_I2C);
667}
668
669static __devexit int wm8776_i2c_remove(struct i2c_client *client)
670{
671 struct wm8776_priv *wm8776 = i2c_get_clientdata(client);
672 wm8776_unregister(wm8776);
673 return 0;
674}
675
676#ifdef CONFIG_PM
677static int wm8776_i2c_suspend(struct i2c_client *i2c, pm_message_t msg)
678{
679 return snd_soc_suspend_device(&i2c->dev);
680}
681
682static int wm8776_i2c_resume(struct i2c_client *i2c)
683{
684 return snd_soc_resume_device(&i2c->dev);
685}
686#else
687#define wm8776_i2c_suspend NULL
688#define wm8776_i2c_resume NULL
689#endif
690
691static const struct i2c_device_id wm8776_i2c_id[] = {
692 { "wm8776", 0 },
693 { }
694};
695MODULE_DEVICE_TABLE(i2c, wm8776_i2c_id);
696
697static struct i2c_driver wm8776_i2c_driver = {
698 .driver = {
699 .name = "wm8776",
700 .owner = THIS_MODULE,
701 },
702 .probe = wm8776_i2c_probe,
703 .remove = __devexit_p(wm8776_i2c_remove),
704 .suspend = wm8776_i2c_suspend,
705 .resume = wm8776_i2c_resume,
706 .id_table = wm8776_i2c_id,
707};
708#endif
709
710static int __init wm8776_modinit(void)
711{
712 int ret;
713#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
714 ret = i2c_add_driver(&wm8776_i2c_driver);
715 if (ret != 0) {
716 printk(KERN_ERR "Failed to register WM8776 I2C driver: %d\n",
717 ret);
718 }
719#endif
720#if defined(CONFIG_SPI_MASTER)
721 ret = spi_register_driver(&wm8776_spi_driver);
722 if (ret != 0) {
723 printk(KERN_ERR "Failed to register WM8776 SPI driver: %d\n",
724 ret);
725 }
726#endif
727 return 0;
728}
729module_init(wm8776_modinit);
730
731static void __exit wm8776_exit(void)
732{
733#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
734 i2c_del_driver(&wm8776_i2c_driver);
735#endif
736#if defined(CONFIG_SPI_MASTER)
737 spi_unregister_driver(&wm8776_spi_driver);
738#endif
739}
740module_exit(wm8776_exit);
741
742MODULE_DESCRIPTION("ASoC WM8776 driver");
743MODULE_AUTHOR("Mark Brown <broonie@opensource.wolfsonmicro.com>");
744MODULE_LICENSE("GPL");
diff --git a/sound/soc/codecs/wm8776.h b/sound/soc/codecs/wm8776.h
new file mode 100644
index 000000000000..6606d25d2d83
--- /dev/null
+++ b/sound/soc/codecs/wm8776.h
@@ -0,0 +1,51 @@
1/*
2 * wm8776.h -- WM8776 ASoC driver
3 *
4 * Copyright 2009 Wolfson Microelectronics plc
5 *
6 * Author: Mark Brown <broonie@opensource.wolfsonmicro.com>
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License version 2 as
10 * published by the Free Software Foundation.
11 */
12
13#ifndef _WM8776_H
14#define _WM8776_H
15
16/* Registers */
17
18#define WM8776_HPLVOL 0x00
19#define WM8776_HPRVOL 0x01
20#define WM8776_HPMASTER 0x02
21#define WM8776_DACLVOL 0x03
22#define WM8776_DACRVOL 0x04
23#define WM8776_DACMASTER 0x05
24#define WM8776_PHASESWAP 0x06
25#define WM8776_DACCTRL1 0x07
26#define WM8776_DACMUTE 0x08
27#define WM8776_DACCTRL2 0x09
28#define WM8776_DACIFCTRL 0x0a
29#define WM8776_ADCIFCTRL 0x0b
30#define WM8776_MSTRCTRL 0x0c
31#define WM8776_PWRDOWN 0x0d
32#define WM8776_ADCLVOL 0x0e
33#define WM8776_ADCRVOL 0x0f
34#define WM8776_ALCCTRL1 0x10
35#define WM8776_ALCCTRL2 0x11
36#define WM8776_ALCCTRL3 0x12
37#define WM8776_NOISEGATE 0x13
38#define WM8776_LIMITER 0x14
39#define WM8776_ADCMUX 0x15
40#define WM8776_OUTMUX 0x16
41#define WM8776_RESET 0x17
42
43#define WM8776_CACHEREGNUM 0x17
44
45#define WM8776_DAI_DAC 0
46#define WM8776_DAI_ADC 1
47
48extern struct snd_soc_dai wm8776_dai[];
49extern struct snd_soc_codec_device soc_codec_dev_wm8776;
50
51#endif
diff --git a/sound/soc/codecs/wm8900.c b/sound/soc/codecs/wm8900.c
index 46c5ea1ff921..5e9c855c0036 100644
--- a/sound/soc/codecs/wm8900.c
+++ b/sound/soc/codecs/wm8900.c
@@ -116,6 +116,7 @@
116#define WM8900_REG_CLOCKING2_DAC_CLKDIV 0x1c 116#define WM8900_REG_CLOCKING2_DAC_CLKDIV 0x1c
117 117
118#define WM8900_REG_DACCTRL_MUTE 0x004 118#define WM8900_REG_DACCTRL_MUTE 0x004
119#define WM8900_REG_DACCTRL_DAC_SB_FILT 0x100
119#define WM8900_REG_DACCTRL_AIF_LRCLKRATE 0x400 120#define WM8900_REG_DACCTRL_AIF_LRCLKRATE 0x400
120 121
121#define WM8900_REG_AUDIO3_ADCLRC_DIR 0x0800 122#define WM8900_REG_AUDIO3_ADCLRC_DIR 0x0800
@@ -182,111 +183,20 @@ static const u16 wm8900_reg_defaults[WM8900_MAXREG] = {
182 /* Remaining registers all zero */ 183 /* Remaining registers all zero */
183}; 184};
184 185
185/* 186static int wm8900_volatile_register(unsigned int reg)
186 * read wm8900 register cache
187 */
188static inline unsigned int wm8900_read_reg_cache(struct snd_soc_codec *codec,
189 unsigned int reg)
190{
191 u16 *cache = codec->reg_cache;
192
193 BUG_ON(reg >= WM8900_MAXREG);
194
195 if (reg == WM8900_REG_ID)
196 return 0;
197
198 return cache[reg];
199}
200
201/*
202 * write wm8900 register cache
203 */
204static inline void wm8900_write_reg_cache(struct snd_soc_codec *codec,
205 u16 reg, unsigned int value)
206{
207 u16 *cache = codec->reg_cache;
208
209 BUG_ON(reg >= WM8900_MAXREG);
210
211 cache[reg] = value;
212}
213
214/*
215 * write to the WM8900 register space
216 */
217static int wm8900_write(struct snd_soc_codec *codec, unsigned int reg,
218 unsigned int value)
219{
220 u8 data[3];
221
222 if (value == wm8900_read_reg_cache(codec, reg))
223 return 0;
224
225 /* data is
226 * D15..D9 WM8900 register offset
227 * D8...D0 register data
228 */
229 data[0] = reg;
230 data[1] = value >> 8;
231 data[2] = value & 0x00ff;
232
233 wm8900_write_reg_cache(codec, reg, value);
234 if (codec->hw_write(codec->control_data, data, 3) == 3)
235 return 0;
236 else
237 return -EIO;
238}
239
240/*
241 * Read from the wm8900.
242 */
243static unsigned int wm8900_chip_read(struct snd_soc_codec *codec, u8 reg)
244{
245 struct i2c_msg xfer[2];
246 u16 data;
247 int ret;
248 struct i2c_client *client = codec->control_data;
249
250 BUG_ON(reg != WM8900_REG_ID && reg != WM8900_REG_POWER1);
251
252 /* Write register */
253 xfer[0].addr = client->addr;
254 xfer[0].flags = 0;
255 xfer[0].len = 1;
256 xfer[0].buf = &reg;
257
258 /* Read data */
259 xfer[1].addr = client->addr;
260 xfer[1].flags = I2C_M_RD;
261 xfer[1].len = 2;
262 xfer[1].buf = (u8 *)&data;
263
264 ret = i2c_transfer(client->adapter, xfer, 2);
265 if (ret != 2) {
266 printk(KERN_CRIT "i2c_transfer returned %d\n", ret);
267 return 0;
268 }
269
270 return (data >> 8) | ((data & 0xff) << 8);
271}
272
273/*
274 * Read from the WM8900 register space. Most registers can't be read
275 * and are therefore supplied from cache.
276 */
277static unsigned int wm8900_read(struct snd_soc_codec *codec, unsigned int reg)
278{ 187{
279 switch (reg) { 188 switch (reg) {
280 case WM8900_REG_ID: 189 case WM8900_REG_ID:
281 return wm8900_chip_read(codec, reg); 190 case WM8900_REG_POWER1:
191 return 1;
282 default: 192 default:
283 return wm8900_read_reg_cache(codec, reg); 193 return 0;
284 } 194 }
285} 195}
286 196
287static void wm8900_reset(struct snd_soc_codec *codec) 197static void wm8900_reset(struct snd_soc_codec *codec)
288{ 198{
289 wm8900_write(codec, WM8900_REG_RESET, 0); 199 snd_soc_write(codec, WM8900_REG_RESET, 0);
290 200
291 memcpy(codec->reg_cache, wm8900_reg_defaults, 201 memcpy(codec->reg_cache, wm8900_reg_defaults,
292 sizeof(codec->reg_cache)); 202 sizeof(codec->reg_cache));
@@ -296,14 +206,14 @@ static int wm8900_hp_event(struct snd_soc_dapm_widget *w,
296 struct snd_kcontrol *kcontrol, int event) 206 struct snd_kcontrol *kcontrol, int event)
297{ 207{
298 struct snd_soc_codec *codec = w->codec; 208 struct snd_soc_codec *codec = w->codec;
299 u16 hpctl1 = wm8900_read(codec, WM8900_REG_HPCTL1); 209 u16 hpctl1 = snd_soc_read(codec, WM8900_REG_HPCTL1);
300 210
301 switch (event) { 211 switch (event) {
302 case SND_SOC_DAPM_PRE_PMU: 212 case SND_SOC_DAPM_PRE_PMU:
303 /* Clamp headphone outputs */ 213 /* Clamp headphone outputs */
304 hpctl1 = WM8900_REG_HPCTL1_HP_CLAMP_IP | 214 hpctl1 = WM8900_REG_HPCTL1_HP_CLAMP_IP |
305 WM8900_REG_HPCTL1_HP_CLAMP_OP; 215 WM8900_REG_HPCTL1_HP_CLAMP_OP;
306 wm8900_write(codec, WM8900_REG_HPCTL1, hpctl1); 216 snd_soc_write(codec, WM8900_REG_HPCTL1, hpctl1);
307 break; 217 break;
308 218
309 case SND_SOC_DAPM_POST_PMU: 219 case SND_SOC_DAPM_POST_PMU:
@@ -312,41 +222,41 @@ static int wm8900_hp_event(struct snd_soc_dapm_widget *w,
312 hpctl1 |= WM8900_REG_HPCTL1_HP_SHORT | 222 hpctl1 |= WM8900_REG_HPCTL1_HP_SHORT |
313 WM8900_REG_HPCTL1_HP_SHORT2 | 223 WM8900_REG_HPCTL1_HP_SHORT2 |
314 WM8900_REG_HPCTL1_HP_IPSTAGE_ENA; 224 WM8900_REG_HPCTL1_HP_IPSTAGE_ENA;
315 wm8900_write(codec, WM8900_REG_HPCTL1, hpctl1); 225 snd_soc_write(codec, WM8900_REG_HPCTL1, hpctl1);
316 226
317 msleep(400); 227 msleep(400);
318 228
319 /* Enable the output stage */ 229 /* Enable the output stage */
320 hpctl1 &= ~WM8900_REG_HPCTL1_HP_CLAMP_OP; 230 hpctl1 &= ~WM8900_REG_HPCTL1_HP_CLAMP_OP;
321 hpctl1 |= WM8900_REG_HPCTL1_HP_OPSTAGE_ENA; 231 hpctl1 |= WM8900_REG_HPCTL1_HP_OPSTAGE_ENA;
322 wm8900_write(codec, WM8900_REG_HPCTL1, hpctl1); 232 snd_soc_write(codec, WM8900_REG_HPCTL1, hpctl1);
323 233
324 /* Remove the shorts */ 234 /* Remove the shorts */
325 hpctl1 &= ~WM8900_REG_HPCTL1_HP_SHORT2; 235 hpctl1 &= ~WM8900_REG_HPCTL1_HP_SHORT2;
326 wm8900_write(codec, WM8900_REG_HPCTL1, hpctl1); 236 snd_soc_write(codec, WM8900_REG_HPCTL1, hpctl1);
327 hpctl1 &= ~WM8900_REG_HPCTL1_HP_SHORT; 237 hpctl1 &= ~WM8900_REG_HPCTL1_HP_SHORT;
328 wm8900_write(codec, WM8900_REG_HPCTL1, hpctl1); 238 snd_soc_write(codec, WM8900_REG_HPCTL1, hpctl1);
329 break; 239 break;
330 240
331 case SND_SOC_DAPM_PRE_PMD: 241 case SND_SOC_DAPM_PRE_PMD:
332 /* Short the output */ 242 /* Short the output */
333 hpctl1 |= WM8900_REG_HPCTL1_HP_SHORT; 243 hpctl1 |= WM8900_REG_HPCTL1_HP_SHORT;
334 wm8900_write(codec, WM8900_REG_HPCTL1, hpctl1); 244 snd_soc_write(codec, WM8900_REG_HPCTL1, hpctl1);
335 245
336 /* Disable the output stage */ 246 /* Disable the output stage */
337 hpctl1 &= ~WM8900_REG_HPCTL1_HP_OPSTAGE_ENA; 247 hpctl1 &= ~WM8900_REG_HPCTL1_HP_OPSTAGE_ENA;
338 wm8900_write(codec, WM8900_REG_HPCTL1, hpctl1); 248 snd_soc_write(codec, WM8900_REG_HPCTL1, hpctl1);
339 249
340 /* Clamp the outputs and power down input */ 250 /* Clamp the outputs and power down input */
341 hpctl1 |= WM8900_REG_HPCTL1_HP_CLAMP_IP | 251 hpctl1 |= WM8900_REG_HPCTL1_HP_CLAMP_IP |
342 WM8900_REG_HPCTL1_HP_CLAMP_OP; 252 WM8900_REG_HPCTL1_HP_CLAMP_OP;
343 hpctl1 &= ~WM8900_REG_HPCTL1_HP_IPSTAGE_ENA; 253 hpctl1 &= ~WM8900_REG_HPCTL1_HP_IPSTAGE_ENA;
344 wm8900_write(codec, WM8900_REG_HPCTL1, hpctl1); 254 snd_soc_write(codec, WM8900_REG_HPCTL1, hpctl1);
345 break; 255 break;
346 256
347 case SND_SOC_DAPM_POST_PMD: 257 case SND_SOC_DAPM_POST_PMD:
348 /* Disable everything */ 258 /* Disable everything */
349 wm8900_write(codec, WM8900_REG_HPCTL1, 0); 259 snd_soc_write(codec, WM8900_REG_HPCTL1, 0);
350 break; 260 break;
351 261
352 default: 262 default:
@@ -439,7 +349,6 @@ SOC_SINGLE("DAC Soft Mute Switch", WM8900_REG_DACCTRL, 6, 1, 1),
439SOC_ENUM("DAC Mute Rate", dac_mute_rate), 349SOC_ENUM("DAC Mute Rate", dac_mute_rate),
440SOC_SINGLE("DAC Mono Switch", WM8900_REG_DACCTRL, 9, 1, 0), 350SOC_SINGLE("DAC Mono Switch", WM8900_REG_DACCTRL, 9, 1, 0),
441SOC_ENUM("DAC Deemphasis", dac_deemphasis), 351SOC_ENUM("DAC Deemphasis", dac_deemphasis),
442SOC_SINGLE("DAC Sloping Stopband Filter Switch", WM8900_REG_DACCTRL, 8, 1, 0),
443SOC_SINGLE("DAC Sigma-Delta Modulator Clock Switch", WM8900_REG_DACCTRL, 352SOC_SINGLE("DAC Sigma-Delta Modulator Clock Switch", WM8900_REG_DACCTRL,
444 12, 1, 0), 353 12, 1, 0),
445 354
@@ -723,7 +632,7 @@ static int wm8900_hw_params(struct snd_pcm_substream *substream,
723 struct snd_soc_codec *codec = socdev->card->codec; 632 struct snd_soc_codec *codec = socdev->card->codec;
724 u16 reg; 633 u16 reg;
725 634
726 reg = wm8900_read(codec, WM8900_REG_AUDIO1) & ~0x60; 635 reg = snd_soc_read(codec, WM8900_REG_AUDIO1) & ~0x60;
727 636
728 switch (params_format(params)) { 637 switch (params_format(params)) {
729 case SNDRV_PCM_FORMAT_S16_LE: 638 case SNDRV_PCM_FORMAT_S16_LE:
@@ -741,7 +650,18 @@ static int wm8900_hw_params(struct snd_pcm_substream *substream,
741 return -EINVAL; 650 return -EINVAL;
742 } 651 }
743 652
744 wm8900_write(codec, WM8900_REG_AUDIO1, reg); 653 snd_soc_write(codec, WM8900_REG_AUDIO1, reg);
654
655 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
656 reg = snd_soc_read(codec, WM8900_REG_DACCTRL);
657
658 if (params_rate(params) <= 24000)
659 reg |= WM8900_REG_DACCTRL_DAC_SB_FILT;
660 else
661 reg &= ~WM8900_REG_DACCTRL_DAC_SB_FILT;
662
663 snd_soc_write(codec, WM8900_REG_DACCTRL, reg);
664 }
745 665
746 return 0; 666 return 0;
747} 667}
@@ -778,11 +698,11 @@ static int fll_factors(struct _fll_div *fll_div, unsigned int Fref,
778 } 698 }
779 699
780 if (target > 100000000) 700 if (target > 100000000)
781 printk(KERN_WARNING "wm8900: FLL rate %d out of range, Fref=%d" 701 printk(KERN_WARNING "wm8900: FLL rate %u out of range, Fref=%u"
782 " Fout=%d\n", target, Fref, Fout); 702 " Fout=%u\n", target, Fref, Fout);
783 if (div > 32) { 703 if (div > 32) {
784 printk(KERN_ERR "wm8900: Invalid FLL division rate %u, " 704 printk(KERN_ERR "wm8900: Invalid FLL division rate %u, "
785 "Fref=%d, Fout=%d, target=%d\n", 705 "Fref=%u, Fout=%u, target=%u\n",
786 div, Fref, Fout, target); 706 div, Fref, Fout, target);
787 return -EINVAL; 707 return -EINVAL;
788 } 708 }
@@ -834,18 +754,18 @@ static int wm8900_set_fll(struct snd_soc_codec *codec,
834 return 0; 754 return 0;
835 755
836 /* The digital side should be disabled during any change. */ 756 /* The digital side should be disabled during any change. */
837 reg = wm8900_read(codec, WM8900_REG_POWER1); 757 reg = snd_soc_read(codec, WM8900_REG_POWER1);
838 wm8900_write(codec, WM8900_REG_POWER1, 758 snd_soc_write(codec, WM8900_REG_POWER1,
839 reg & (~WM8900_REG_POWER1_FLL_ENA)); 759 reg & (~WM8900_REG_POWER1_FLL_ENA));
840 760
841 /* Disable the FLL? */ 761 /* Disable the FLL? */
842 if (!freq_in || !freq_out) { 762 if (!freq_in || !freq_out) {
843 reg = wm8900_read(codec, WM8900_REG_CLOCKING1); 763 reg = snd_soc_read(codec, WM8900_REG_CLOCKING1);
844 wm8900_write(codec, WM8900_REG_CLOCKING1, 764 snd_soc_write(codec, WM8900_REG_CLOCKING1,
845 reg & (~WM8900_REG_CLOCKING1_MCLK_SRC)); 765 reg & (~WM8900_REG_CLOCKING1_MCLK_SRC));
846 766
847 reg = wm8900_read(codec, WM8900_REG_FLLCTL1); 767 reg = snd_soc_read(codec, WM8900_REG_FLLCTL1);
848 wm8900_write(codec, WM8900_REG_FLLCTL1, 768 snd_soc_write(codec, WM8900_REG_FLLCTL1,
849 reg & (~WM8900_REG_FLLCTL1_OSC_ENA)); 769 reg & (~WM8900_REG_FLLCTL1_OSC_ENA));
850 770
851 wm8900->fll_in = freq_in; 771 wm8900->fll_in = freq_in;
@@ -862,33 +782,33 @@ static int wm8900_set_fll(struct snd_soc_codec *codec,
862 782
863 /* The osclilator *MUST* be enabled before we enable the 783 /* The osclilator *MUST* be enabled before we enable the
864 * digital circuit. */ 784 * digital circuit. */
865 wm8900_write(codec, WM8900_REG_FLLCTL1, 785 snd_soc_write(codec, WM8900_REG_FLLCTL1,
866 fll_div.fll_ratio | WM8900_REG_FLLCTL1_OSC_ENA); 786 fll_div.fll_ratio | WM8900_REG_FLLCTL1_OSC_ENA);
867 787
868 wm8900_write(codec, WM8900_REG_FLLCTL4, fll_div.n >> 5); 788 snd_soc_write(codec, WM8900_REG_FLLCTL4, fll_div.n >> 5);
869 wm8900_write(codec, WM8900_REG_FLLCTL5, 789 snd_soc_write(codec, WM8900_REG_FLLCTL5,
870 (fll_div.fllclk_div << 6) | (fll_div.n & 0x1f)); 790 (fll_div.fllclk_div << 6) | (fll_div.n & 0x1f));
871 791
872 if (fll_div.k) { 792 if (fll_div.k) {
873 wm8900_write(codec, WM8900_REG_FLLCTL2, 793 snd_soc_write(codec, WM8900_REG_FLLCTL2,
874 (fll_div.k >> 8) | 0x100); 794 (fll_div.k >> 8) | 0x100);
875 wm8900_write(codec, WM8900_REG_FLLCTL3, fll_div.k & 0xff); 795 snd_soc_write(codec, WM8900_REG_FLLCTL3, fll_div.k & 0xff);
876 } else 796 } else
877 wm8900_write(codec, WM8900_REG_FLLCTL2, 0); 797 snd_soc_write(codec, WM8900_REG_FLLCTL2, 0);
878 798
879 if (fll_div.fll_slow_lock_ref) 799 if (fll_div.fll_slow_lock_ref)
880 wm8900_write(codec, WM8900_REG_FLLCTL6, 800 snd_soc_write(codec, WM8900_REG_FLLCTL6,
881 WM8900_REG_FLLCTL6_FLL_SLOW_LOCK_REF); 801 WM8900_REG_FLLCTL6_FLL_SLOW_LOCK_REF);
882 else 802 else
883 wm8900_write(codec, WM8900_REG_FLLCTL6, 0); 803 snd_soc_write(codec, WM8900_REG_FLLCTL6, 0);
884 804
885 reg = wm8900_read(codec, WM8900_REG_POWER1); 805 reg = snd_soc_read(codec, WM8900_REG_POWER1);
886 wm8900_write(codec, WM8900_REG_POWER1, 806 snd_soc_write(codec, WM8900_REG_POWER1,
887 reg | WM8900_REG_POWER1_FLL_ENA); 807 reg | WM8900_REG_POWER1_FLL_ENA);
888 808
889reenable: 809reenable:
890 reg = wm8900_read(codec, WM8900_REG_CLOCKING1); 810 reg = snd_soc_read(codec, WM8900_REG_CLOCKING1);
891 wm8900_write(codec, WM8900_REG_CLOCKING1, 811 snd_soc_write(codec, WM8900_REG_CLOCKING1,
892 reg | WM8900_REG_CLOCKING1_MCLK_SRC); 812 reg | WM8900_REG_CLOCKING1_MCLK_SRC);
893 813
894 return 0; 814 return 0;
@@ -908,38 +828,38 @@ static int wm8900_set_dai_clkdiv(struct snd_soc_dai *codec_dai,
908 828
909 switch (div_id) { 829 switch (div_id) {
910 case WM8900_BCLK_DIV: 830 case WM8900_BCLK_DIV:
911 reg = wm8900_read(codec, WM8900_REG_CLOCKING1); 831 reg = snd_soc_read(codec, WM8900_REG_CLOCKING1);
912 wm8900_write(codec, WM8900_REG_CLOCKING1, 832 snd_soc_write(codec, WM8900_REG_CLOCKING1,
913 div | (reg & WM8900_REG_CLOCKING1_BCLK_MASK)); 833 div | (reg & WM8900_REG_CLOCKING1_BCLK_MASK));
914 break; 834 break;
915 case WM8900_OPCLK_DIV: 835 case WM8900_OPCLK_DIV:
916 reg = wm8900_read(codec, WM8900_REG_CLOCKING1); 836 reg = snd_soc_read(codec, WM8900_REG_CLOCKING1);
917 wm8900_write(codec, WM8900_REG_CLOCKING1, 837 snd_soc_write(codec, WM8900_REG_CLOCKING1,
918 div | (reg & WM8900_REG_CLOCKING1_OPCLK_MASK)); 838 div | (reg & WM8900_REG_CLOCKING1_OPCLK_MASK));
919 break; 839 break;
920 case WM8900_DAC_LRCLK: 840 case WM8900_DAC_LRCLK:
921 reg = wm8900_read(codec, WM8900_REG_AUDIO4); 841 reg = snd_soc_read(codec, WM8900_REG_AUDIO4);
922 wm8900_write(codec, WM8900_REG_AUDIO4, 842 snd_soc_write(codec, WM8900_REG_AUDIO4,
923 div | (reg & WM8900_LRC_MASK)); 843 div | (reg & WM8900_LRC_MASK));
924 break; 844 break;
925 case WM8900_ADC_LRCLK: 845 case WM8900_ADC_LRCLK:
926 reg = wm8900_read(codec, WM8900_REG_AUDIO3); 846 reg = snd_soc_read(codec, WM8900_REG_AUDIO3);
927 wm8900_write(codec, WM8900_REG_AUDIO3, 847 snd_soc_write(codec, WM8900_REG_AUDIO3,
928 div | (reg & WM8900_LRC_MASK)); 848 div | (reg & WM8900_LRC_MASK));
929 break; 849 break;
930 case WM8900_DAC_CLKDIV: 850 case WM8900_DAC_CLKDIV:
931 reg = wm8900_read(codec, WM8900_REG_CLOCKING2); 851 reg = snd_soc_read(codec, WM8900_REG_CLOCKING2);
932 wm8900_write(codec, WM8900_REG_CLOCKING2, 852 snd_soc_write(codec, WM8900_REG_CLOCKING2,
933 div | (reg & WM8900_REG_CLOCKING2_DAC_CLKDIV)); 853 div | (reg & WM8900_REG_CLOCKING2_DAC_CLKDIV));
934 break; 854 break;
935 case WM8900_ADC_CLKDIV: 855 case WM8900_ADC_CLKDIV:
936 reg = wm8900_read(codec, WM8900_REG_CLOCKING2); 856 reg = snd_soc_read(codec, WM8900_REG_CLOCKING2);
937 wm8900_write(codec, WM8900_REG_CLOCKING2, 857 snd_soc_write(codec, WM8900_REG_CLOCKING2,
938 div | (reg & WM8900_REG_CLOCKING2_ADC_CLKDIV)); 858 div | (reg & WM8900_REG_CLOCKING2_ADC_CLKDIV));
939 break; 859 break;
940 case WM8900_LRCLK_MODE: 860 case WM8900_LRCLK_MODE:
941 reg = wm8900_read(codec, WM8900_REG_DACCTRL); 861 reg = snd_soc_read(codec, WM8900_REG_DACCTRL);
942 wm8900_write(codec, WM8900_REG_DACCTRL, 862 snd_soc_write(codec, WM8900_REG_DACCTRL,
943 div | (reg & WM8900_REG_DACCTRL_AIF_LRCLKRATE)); 863 div | (reg & WM8900_REG_DACCTRL_AIF_LRCLKRATE));
944 break; 864 break;
945 default: 865 default:
@@ -956,10 +876,10 @@ static int wm8900_set_dai_fmt(struct snd_soc_dai *codec_dai,
956 struct snd_soc_codec *codec = codec_dai->codec; 876 struct snd_soc_codec *codec = codec_dai->codec;
957 unsigned int clocking1, aif1, aif3, aif4; 877 unsigned int clocking1, aif1, aif3, aif4;
958 878
959 clocking1 = wm8900_read(codec, WM8900_REG_CLOCKING1); 879 clocking1 = snd_soc_read(codec, WM8900_REG_CLOCKING1);
960 aif1 = wm8900_read(codec, WM8900_REG_AUDIO1); 880 aif1 = snd_soc_read(codec, WM8900_REG_AUDIO1);
961 aif3 = wm8900_read(codec, WM8900_REG_AUDIO3); 881 aif3 = snd_soc_read(codec, WM8900_REG_AUDIO3);
962 aif4 = wm8900_read(codec, WM8900_REG_AUDIO4); 882 aif4 = snd_soc_read(codec, WM8900_REG_AUDIO4);
963 883
964 /* set master/slave audio interface */ 884 /* set master/slave audio interface */
965 switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { 885 switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
@@ -1055,10 +975,10 @@ static int wm8900_set_dai_fmt(struct snd_soc_dai *codec_dai,
1055 return -EINVAL; 975 return -EINVAL;
1056 } 976 }
1057 977
1058 wm8900_write(codec, WM8900_REG_CLOCKING1, clocking1); 978 snd_soc_write(codec, WM8900_REG_CLOCKING1, clocking1);
1059 wm8900_write(codec, WM8900_REG_AUDIO1, aif1); 979 snd_soc_write(codec, WM8900_REG_AUDIO1, aif1);
1060 wm8900_write(codec, WM8900_REG_AUDIO3, aif3); 980 snd_soc_write(codec, WM8900_REG_AUDIO3, aif3);
1061 wm8900_write(codec, WM8900_REG_AUDIO4, aif4); 981 snd_soc_write(codec, WM8900_REG_AUDIO4, aif4);
1062 982
1063 return 0; 983 return 0;
1064} 984}
@@ -1068,14 +988,14 @@ static int wm8900_digital_mute(struct snd_soc_dai *codec_dai, int mute)
1068 struct snd_soc_codec *codec = codec_dai->codec; 988 struct snd_soc_codec *codec = codec_dai->codec;
1069 u16 reg; 989 u16 reg;
1070 990
1071 reg = wm8900_read(codec, WM8900_REG_DACCTRL); 991 reg = snd_soc_read(codec, WM8900_REG_DACCTRL);
1072 992
1073 if (mute) 993 if (mute)
1074 reg |= WM8900_REG_DACCTRL_MUTE; 994 reg |= WM8900_REG_DACCTRL_MUTE;
1075 else 995 else
1076 reg &= ~WM8900_REG_DACCTRL_MUTE; 996 reg &= ~WM8900_REG_DACCTRL_MUTE;
1077 997
1078 wm8900_write(codec, WM8900_REG_DACCTRL, reg); 998 snd_soc_write(codec, WM8900_REG_DACCTRL, reg);
1079 999
1080 return 0; 1000 return 0;
1081} 1001}
@@ -1124,11 +1044,11 @@ static int wm8900_set_bias_level(struct snd_soc_codec *codec,
1124 switch (level) { 1044 switch (level) {
1125 case SND_SOC_BIAS_ON: 1045 case SND_SOC_BIAS_ON:
1126 /* Enable thermal shutdown */ 1046 /* Enable thermal shutdown */
1127 reg = wm8900_read(codec, WM8900_REG_GPIO); 1047 reg = snd_soc_read(codec, WM8900_REG_GPIO);
1128 wm8900_write(codec, WM8900_REG_GPIO, 1048 snd_soc_write(codec, WM8900_REG_GPIO,
1129 reg | WM8900_REG_GPIO_TEMP_ENA); 1049 reg | WM8900_REG_GPIO_TEMP_ENA);
1130 reg = wm8900_read(codec, WM8900_REG_ADDCTL); 1050 reg = snd_soc_read(codec, WM8900_REG_ADDCTL);
1131 wm8900_write(codec, WM8900_REG_ADDCTL, 1051 snd_soc_write(codec, WM8900_REG_ADDCTL,
1132 reg | WM8900_REG_ADDCTL_TEMP_SD); 1052 reg | WM8900_REG_ADDCTL_TEMP_SD);
1133 break; 1053 break;
1134 1054
@@ -1139,69 +1059,69 @@ static int wm8900_set_bias_level(struct snd_soc_codec *codec,
1139 /* Charge capacitors if initial power up */ 1059 /* Charge capacitors if initial power up */
1140 if (codec->bias_level == SND_SOC_BIAS_OFF) { 1060 if (codec->bias_level == SND_SOC_BIAS_OFF) {
1141 /* STARTUP_BIAS_ENA on */ 1061 /* STARTUP_BIAS_ENA on */
1142 wm8900_write(codec, WM8900_REG_POWER1, 1062 snd_soc_write(codec, WM8900_REG_POWER1,
1143 WM8900_REG_POWER1_STARTUP_BIAS_ENA); 1063 WM8900_REG_POWER1_STARTUP_BIAS_ENA);
1144 1064
1145 /* Startup bias mode */ 1065 /* Startup bias mode */
1146 wm8900_write(codec, WM8900_REG_ADDCTL, 1066 snd_soc_write(codec, WM8900_REG_ADDCTL,
1147 WM8900_REG_ADDCTL_BIAS_SRC | 1067 WM8900_REG_ADDCTL_BIAS_SRC |
1148 WM8900_REG_ADDCTL_VMID_SOFTST); 1068 WM8900_REG_ADDCTL_VMID_SOFTST);
1149 1069
1150 /* VMID 2x50k */ 1070 /* VMID 2x50k */
1151 wm8900_write(codec, WM8900_REG_POWER1, 1071 snd_soc_write(codec, WM8900_REG_POWER1,
1152 WM8900_REG_POWER1_STARTUP_BIAS_ENA | 0x1); 1072 WM8900_REG_POWER1_STARTUP_BIAS_ENA | 0x1);
1153 1073
1154 /* Allow capacitors to charge */ 1074 /* Allow capacitors to charge */
1155 schedule_timeout_interruptible(msecs_to_jiffies(400)); 1075 schedule_timeout_interruptible(msecs_to_jiffies(400));
1156 1076
1157 /* Enable bias */ 1077 /* Enable bias */
1158 wm8900_write(codec, WM8900_REG_POWER1, 1078 snd_soc_write(codec, WM8900_REG_POWER1,
1159 WM8900_REG_POWER1_STARTUP_BIAS_ENA | 1079 WM8900_REG_POWER1_STARTUP_BIAS_ENA |
1160 WM8900_REG_POWER1_BIAS_ENA | 0x1); 1080 WM8900_REG_POWER1_BIAS_ENA | 0x1);
1161 1081
1162 wm8900_write(codec, WM8900_REG_ADDCTL, 0); 1082 snd_soc_write(codec, WM8900_REG_ADDCTL, 0);
1163 1083
1164 wm8900_write(codec, WM8900_REG_POWER1, 1084 snd_soc_write(codec, WM8900_REG_POWER1,
1165 WM8900_REG_POWER1_BIAS_ENA | 0x1); 1085 WM8900_REG_POWER1_BIAS_ENA | 0x1);
1166 } 1086 }
1167 1087
1168 reg = wm8900_read(codec, WM8900_REG_POWER1); 1088 reg = snd_soc_read(codec, WM8900_REG_POWER1);
1169 wm8900_write(codec, WM8900_REG_POWER1, 1089 snd_soc_write(codec, WM8900_REG_POWER1,
1170 (reg & WM8900_REG_POWER1_FLL_ENA) | 1090 (reg & WM8900_REG_POWER1_FLL_ENA) |
1171 WM8900_REG_POWER1_BIAS_ENA | 0x1); 1091 WM8900_REG_POWER1_BIAS_ENA | 0x1);
1172 wm8900_write(codec, WM8900_REG_POWER2, 1092 snd_soc_write(codec, WM8900_REG_POWER2,
1173 WM8900_REG_POWER2_SYSCLK_ENA); 1093 WM8900_REG_POWER2_SYSCLK_ENA);
1174 wm8900_write(codec, WM8900_REG_POWER3, 0); 1094 snd_soc_write(codec, WM8900_REG_POWER3, 0);
1175 break; 1095 break;
1176 1096
1177 case SND_SOC_BIAS_OFF: 1097 case SND_SOC_BIAS_OFF:
1178 /* Startup bias enable */ 1098 /* Startup bias enable */
1179 reg = wm8900_read(codec, WM8900_REG_POWER1); 1099 reg = snd_soc_read(codec, WM8900_REG_POWER1);
1180 wm8900_write(codec, WM8900_REG_POWER1, 1100 snd_soc_write(codec, WM8900_REG_POWER1,
1181 reg & WM8900_REG_POWER1_STARTUP_BIAS_ENA); 1101 reg & WM8900_REG_POWER1_STARTUP_BIAS_ENA);
1182 wm8900_write(codec, WM8900_REG_ADDCTL, 1102 snd_soc_write(codec, WM8900_REG_ADDCTL,
1183 WM8900_REG_ADDCTL_BIAS_SRC | 1103 WM8900_REG_ADDCTL_BIAS_SRC |
1184 WM8900_REG_ADDCTL_VMID_SOFTST); 1104 WM8900_REG_ADDCTL_VMID_SOFTST);
1185 1105
1186 /* Discharge caps */ 1106 /* Discharge caps */
1187 wm8900_write(codec, WM8900_REG_POWER1, 1107 snd_soc_write(codec, WM8900_REG_POWER1,
1188 WM8900_REG_POWER1_STARTUP_BIAS_ENA); 1108 WM8900_REG_POWER1_STARTUP_BIAS_ENA);
1189 schedule_timeout_interruptible(msecs_to_jiffies(500)); 1109 schedule_timeout_interruptible(msecs_to_jiffies(500));
1190 1110
1191 /* Remove clamp */ 1111 /* Remove clamp */
1192 wm8900_write(codec, WM8900_REG_HPCTL1, 0); 1112 snd_soc_write(codec, WM8900_REG_HPCTL1, 0);
1193 1113
1194 /* Power down */ 1114 /* Power down */
1195 wm8900_write(codec, WM8900_REG_ADDCTL, 0); 1115 snd_soc_write(codec, WM8900_REG_ADDCTL, 0);
1196 wm8900_write(codec, WM8900_REG_POWER1, 0); 1116 snd_soc_write(codec, WM8900_REG_POWER1, 0);
1197 wm8900_write(codec, WM8900_REG_POWER2, 0); 1117 snd_soc_write(codec, WM8900_REG_POWER2, 0);
1198 wm8900_write(codec, WM8900_REG_POWER3, 0); 1118 snd_soc_write(codec, WM8900_REG_POWER3, 0);
1199 1119
1200 /* Need to let things settle before stopping the clock 1120 /* Need to let things settle before stopping the clock
1201 * to ensure that restart works, see "Stopping the 1121 * to ensure that restart works, see "Stopping the
1202 * master clock" in the datasheet. */ 1122 * master clock" in the datasheet. */
1203 schedule_timeout_interruptible(msecs_to_jiffies(1)); 1123 schedule_timeout_interruptible(msecs_to_jiffies(1));
1204 wm8900_write(codec, WM8900_REG_POWER2, 1124 snd_soc_write(codec, WM8900_REG_POWER2,
1205 WM8900_REG_POWER2_SYSCLK_ENA); 1125 WM8900_REG_POWER2_SYSCLK_ENA);
1206 break; 1126 break;
1207 } 1127 }
@@ -1264,7 +1184,7 @@ static int wm8900_resume(struct platform_device *pdev)
1264 1184
1265 if (cache) { 1185 if (cache) {
1266 for (i = 0; i < WM8900_MAXREG; i++) 1186 for (i = 0; i < WM8900_MAXREG; i++)
1267 wm8900_write(codec, i, cache[i]); 1187 snd_soc_write(codec, i, cache[i]);
1268 kfree(cache); 1188 kfree(cache);
1269 } else 1189 } else
1270 dev_err(&pdev->dev, "Unable to allocate register cache\n"); 1190 dev_err(&pdev->dev, "Unable to allocate register cache\n");
@@ -1297,16 +1217,20 @@ static __devinit int wm8900_i2c_probe(struct i2c_client *i2c,
1297 1217
1298 codec->name = "WM8900"; 1218 codec->name = "WM8900";
1299 codec->owner = THIS_MODULE; 1219 codec->owner = THIS_MODULE;
1300 codec->read = wm8900_read;
1301 codec->write = wm8900_write;
1302 codec->dai = &wm8900_dai; 1220 codec->dai = &wm8900_dai;
1303 codec->num_dai = 1; 1221 codec->num_dai = 1;
1304 codec->hw_write = (hw_write_t)i2c_master_send;
1305 codec->control_data = i2c; 1222 codec->control_data = i2c;
1306 codec->set_bias_level = wm8900_set_bias_level; 1223 codec->set_bias_level = wm8900_set_bias_level;
1224 codec->volatile_register = wm8900_volatile_register;
1307 codec->dev = &i2c->dev; 1225 codec->dev = &i2c->dev;
1308 1226
1309 reg = wm8900_read(codec, WM8900_REG_ID); 1227 ret = snd_soc_codec_set_cache_io(codec, 8, 16, SND_SOC_I2C);
1228 if (ret != 0) {
1229 dev_err(&i2c->dev, "Failed to set cache I/O: %d\n", ret);
1230 goto err;
1231 }
1232
1233 reg = snd_soc_read(codec, WM8900_REG_ID);
1310 if (reg != 0x8900) { 1234 if (reg != 0x8900) {
1311 dev_err(&i2c->dev, "Device is not a WM8900 - ID %x\n", reg); 1235 dev_err(&i2c->dev, "Device is not a WM8900 - ID %x\n", reg);
1312 ret = -ENODEV; 1236 ret = -ENODEV;
@@ -1314,7 +1238,7 @@ static __devinit int wm8900_i2c_probe(struct i2c_client *i2c,
1314 } 1238 }
1315 1239
1316 /* Read back from the chip */ 1240 /* Read back from the chip */
1317 reg = wm8900_chip_read(codec, WM8900_REG_POWER1); 1241 reg = snd_soc_read(codec, WM8900_REG_POWER1);
1318 reg = (reg >> 12) & 0xf; 1242 reg = (reg >> 12) & 0xf;
1319 dev_info(&i2c->dev, "WM8900 revision %d\n", reg); 1243 dev_info(&i2c->dev, "WM8900 revision %d\n", reg);
1320 1244
@@ -1324,29 +1248,29 @@ static __devinit int wm8900_i2c_probe(struct i2c_client *i2c,
1324 wm8900_set_bias_level(codec, SND_SOC_BIAS_STANDBY); 1248 wm8900_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
1325 1249
1326 /* Latch the volume update bits */ 1250 /* Latch the volume update bits */
1327 wm8900_write(codec, WM8900_REG_LINVOL, 1251 snd_soc_write(codec, WM8900_REG_LINVOL,
1328 wm8900_read(codec, WM8900_REG_LINVOL) | 0x100); 1252 snd_soc_read(codec, WM8900_REG_LINVOL) | 0x100);
1329 wm8900_write(codec, WM8900_REG_RINVOL, 1253 snd_soc_write(codec, WM8900_REG_RINVOL,
1330 wm8900_read(codec, WM8900_REG_RINVOL) | 0x100); 1254 snd_soc_read(codec, WM8900_REG_RINVOL) | 0x100);
1331 wm8900_write(codec, WM8900_REG_LOUT1CTL, 1255 snd_soc_write(codec, WM8900_REG_LOUT1CTL,
1332 wm8900_read(codec, WM8900_REG_LOUT1CTL) | 0x100); 1256 snd_soc_read(codec, WM8900_REG_LOUT1CTL) | 0x100);
1333 wm8900_write(codec, WM8900_REG_ROUT1CTL, 1257 snd_soc_write(codec, WM8900_REG_ROUT1CTL,
1334 wm8900_read(codec, WM8900_REG_ROUT1CTL) | 0x100); 1258 snd_soc_read(codec, WM8900_REG_ROUT1CTL) | 0x100);
1335 wm8900_write(codec, WM8900_REG_LOUT2CTL, 1259 snd_soc_write(codec, WM8900_REG_LOUT2CTL,
1336 wm8900_read(codec, WM8900_REG_LOUT2CTL) | 0x100); 1260 snd_soc_read(codec, WM8900_REG_LOUT2CTL) | 0x100);
1337 wm8900_write(codec, WM8900_REG_ROUT2CTL, 1261 snd_soc_write(codec, WM8900_REG_ROUT2CTL,
1338 wm8900_read(codec, WM8900_REG_ROUT2CTL) | 0x100); 1262 snd_soc_read(codec, WM8900_REG_ROUT2CTL) | 0x100);
1339 wm8900_write(codec, WM8900_REG_LDAC_DV, 1263 snd_soc_write(codec, WM8900_REG_LDAC_DV,
1340 wm8900_read(codec, WM8900_REG_LDAC_DV) | 0x100); 1264 snd_soc_read(codec, WM8900_REG_LDAC_DV) | 0x100);
1341 wm8900_write(codec, WM8900_REG_RDAC_DV, 1265 snd_soc_write(codec, WM8900_REG_RDAC_DV,
1342 wm8900_read(codec, WM8900_REG_RDAC_DV) | 0x100); 1266 snd_soc_read(codec, WM8900_REG_RDAC_DV) | 0x100);
1343 wm8900_write(codec, WM8900_REG_LADC_DV, 1267 snd_soc_write(codec, WM8900_REG_LADC_DV,
1344 wm8900_read(codec, WM8900_REG_LADC_DV) | 0x100); 1268 snd_soc_read(codec, WM8900_REG_LADC_DV) | 0x100);
1345 wm8900_write(codec, WM8900_REG_RADC_DV, 1269 snd_soc_write(codec, WM8900_REG_RADC_DV,
1346 wm8900_read(codec, WM8900_REG_RADC_DV) | 0x100); 1270 snd_soc_read(codec, WM8900_REG_RADC_DV) | 0x100);
1347 1271
1348 /* Set the DAC and mixer output bias */ 1272 /* Set the DAC and mixer output bias */
1349 wm8900_write(codec, WM8900_REG_OUTBIASCTL, 0x81); 1273 snd_soc_write(codec, WM8900_REG_OUTBIASCTL, 0x81);
1350 1274
1351 wm8900_dai.dev = &i2c->dev; 1275 wm8900_dai.dev = &i2c->dev;
1352 1276
@@ -1388,6 +1312,21 @@ static __devexit int wm8900_i2c_remove(struct i2c_client *client)
1388 return 0; 1312 return 0;
1389} 1313}
1390 1314
1315#ifdef CONFIG_PM
1316static int wm8900_i2c_suspend(struct i2c_client *client, pm_message_t msg)
1317{
1318 return snd_soc_suspend_device(&client->dev);
1319}
1320
1321static int wm8900_i2c_resume(struct i2c_client *client)
1322{
1323 return snd_soc_resume_device(&client->dev);
1324}
1325#else
1326#define wm8900_i2c_suspend NULL
1327#define wm8900_i2c_resume NULL
1328#endif
1329
1391static const struct i2c_device_id wm8900_i2c_id[] = { 1330static const struct i2c_device_id wm8900_i2c_id[] = {
1392 { "wm8900", 0 }, 1331 { "wm8900", 0 },
1393 { } 1332 { }
@@ -1401,6 +1340,8 @@ static struct i2c_driver wm8900_i2c_driver = {
1401 }, 1340 },
1402 .probe = wm8900_i2c_probe, 1341 .probe = wm8900_i2c_probe,
1403 .remove = __devexit_p(wm8900_i2c_remove), 1342 .remove = __devexit_p(wm8900_i2c_remove),
1343 .suspend = wm8900_i2c_suspend,
1344 .resume = wm8900_i2c_resume,
1404 .id_table = wm8900_i2c_id, 1345 .id_table = wm8900_i2c_id,
1405}; 1346};
1406 1347
diff --git a/sound/soc/codecs/wm8903.c b/sound/soc/codecs/wm8903.c
index 8cf571f1a803..fe1307b500cf 100644
--- a/sound/soc/codecs/wm8903.c
+++ b/sound/soc/codecs/wm8903.c
@@ -217,7 +217,6 @@ struct wm8903_priv {
217 int sysclk; 217 int sysclk;
218 218
219 /* Reference counts */ 219 /* Reference counts */
220 int charge_pump_users;
221 int class_w_users; 220 int class_w_users;
222 int playback_active; 221 int playback_active;
223 int capture_active; 222 int capture_active;
@@ -226,94 +225,18 @@ struct wm8903_priv {
226 struct snd_pcm_substream *slave_substream; 225 struct snd_pcm_substream *slave_substream;
227}; 226};
228 227
229 228static int wm8903_volatile_register(unsigned int reg)
230static unsigned int wm8903_read_reg_cache(struct snd_soc_codec *codec,
231 unsigned int reg)
232{
233 u16 *cache = codec->reg_cache;
234
235 BUG_ON(reg >= ARRAY_SIZE(wm8903_reg_defaults));
236
237 return cache[reg];
238}
239
240static unsigned int wm8903_hw_read(struct snd_soc_codec *codec, u8 reg)
241{
242 struct i2c_msg xfer[2];
243 u16 data;
244 int ret;
245 struct i2c_client *client = codec->control_data;
246
247 /* Write register */
248 xfer[0].addr = client->addr;
249 xfer[0].flags = 0;
250 xfer[0].len = 1;
251 xfer[0].buf = &reg;
252
253 /* Read data */
254 xfer[1].addr = client->addr;
255 xfer[1].flags = I2C_M_RD;
256 xfer[1].len = 2;
257 xfer[1].buf = (u8 *)&data;
258
259 ret = i2c_transfer(client->adapter, xfer, 2);
260 if (ret != 2) {
261 pr_err("i2c_transfer returned %d\n", ret);
262 return 0;
263 }
264
265 return (data >> 8) | ((data & 0xff) << 8);
266}
267
268static unsigned int wm8903_read(struct snd_soc_codec *codec,
269 unsigned int reg)
270{ 229{
271 switch (reg) { 230 switch (reg) {
272 case WM8903_SW_RESET_AND_ID: 231 case WM8903_SW_RESET_AND_ID:
273 case WM8903_REVISION_NUMBER: 232 case WM8903_REVISION_NUMBER:
274 case WM8903_INTERRUPT_STATUS_1: 233 case WM8903_INTERRUPT_STATUS_1:
275 case WM8903_WRITE_SEQUENCER_4: 234 case WM8903_WRITE_SEQUENCER_4:
276 return wm8903_hw_read(codec, reg); 235 return 1;
277
278 default:
279 return wm8903_read_reg_cache(codec, reg);
280 }
281}
282
283static void wm8903_write_reg_cache(struct snd_soc_codec *codec,
284 u16 reg, unsigned int value)
285{
286 u16 *cache = codec->reg_cache;
287
288 BUG_ON(reg >= ARRAY_SIZE(wm8903_reg_defaults));
289
290 switch (reg) {
291 case WM8903_SW_RESET_AND_ID:
292 case WM8903_REVISION_NUMBER:
293 break;
294 236
295 default: 237 default:
296 cache[reg] = value;
297 break;
298 }
299}
300
301static int wm8903_write(struct snd_soc_codec *codec, unsigned int reg,
302 unsigned int value)
303{
304 u8 data[3];
305
306 wm8903_write_reg_cache(codec, reg, value);
307
308 /* Data format is 1 byte of address followed by 2 bytes of data */
309 data[0] = reg;
310 data[1] = (value >> 8) & 0xff;
311 data[2] = value & 0xff;
312
313 if (codec->hw_write(codec->control_data, data, 3) == 2)
314 return 0; 238 return 0;
315 else 239 }
316 return -EIO;
317} 240}
318 241
319static int wm8903_run_sequence(struct snd_soc_codec *codec, unsigned int start) 242static int wm8903_run_sequence(struct snd_soc_codec *codec, unsigned int start)
@@ -324,13 +247,13 @@ static int wm8903_run_sequence(struct snd_soc_codec *codec, unsigned int start)
324 BUG_ON(start > 48); 247 BUG_ON(start > 48);
325 248
326 /* Enable the sequencer */ 249 /* Enable the sequencer */
327 reg[0] = wm8903_read(codec, WM8903_WRITE_SEQUENCER_0); 250 reg[0] = snd_soc_read(codec, WM8903_WRITE_SEQUENCER_0);
328 reg[0] |= WM8903_WSEQ_ENA; 251 reg[0] |= WM8903_WSEQ_ENA;
329 wm8903_write(codec, WM8903_WRITE_SEQUENCER_0, reg[0]); 252 snd_soc_write(codec, WM8903_WRITE_SEQUENCER_0, reg[0]);
330 253
331 dev_dbg(&i2c->dev, "Starting sequence at %d\n", start); 254 dev_dbg(&i2c->dev, "Starting sequence at %d\n", start);
332 255
333 wm8903_write(codec, WM8903_WRITE_SEQUENCER_3, 256 snd_soc_write(codec, WM8903_WRITE_SEQUENCER_3,
334 start | WM8903_WSEQ_START); 257 start | WM8903_WSEQ_START);
335 258
336 /* Wait for it to complete. If we have the interrupt wired up then 259 /* Wait for it to complete. If we have the interrupt wired up then
@@ -340,13 +263,13 @@ static int wm8903_run_sequence(struct snd_soc_codec *codec, unsigned int start)
340 do { 263 do {
341 msleep(10); 264 msleep(10);
342 265
343 reg[4] = wm8903_read(codec, WM8903_WRITE_SEQUENCER_4); 266 reg[4] = snd_soc_read(codec, WM8903_WRITE_SEQUENCER_4);
344 } while (reg[4] & WM8903_WSEQ_BUSY); 267 } while (reg[4] & WM8903_WSEQ_BUSY);
345 268
346 dev_dbg(&i2c->dev, "Sequence complete\n"); 269 dev_dbg(&i2c->dev, "Sequence complete\n");
347 270
348 /* Disable the sequencer again */ 271 /* Disable the sequencer again */
349 wm8903_write(codec, WM8903_WRITE_SEQUENCER_0, 272 snd_soc_write(codec, WM8903_WRITE_SEQUENCER_0,
350 reg[0] & ~WM8903_WSEQ_ENA); 273 reg[0] & ~WM8903_WSEQ_ENA);
351 274
352 return 0; 275 return 0;
@@ -358,12 +281,12 @@ static void wm8903_sync_reg_cache(struct snd_soc_codec *codec, u16 *cache)
358 281
359 /* There really ought to be something better we can do here :/ */ 282 /* There really ought to be something better we can do here :/ */
360 for (i = 0; i < ARRAY_SIZE(wm8903_reg_defaults); i++) 283 for (i = 0; i < ARRAY_SIZE(wm8903_reg_defaults); i++)
361 cache[i] = wm8903_hw_read(codec, i); 284 cache[i] = codec->hw_read(codec, i);
362} 285}
363 286
364static void wm8903_reset(struct snd_soc_codec *codec) 287static void wm8903_reset(struct snd_soc_codec *codec)
365{ 288{
366 wm8903_write(codec, WM8903_SW_RESET_AND_ID, 0); 289 snd_soc_write(codec, WM8903_SW_RESET_AND_ID, 0);
367 memcpy(codec->reg_cache, wm8903_reg_defaults, 290 memcpy(codec->reg_cache, wm8903_reg_defaults,
368 sizeof(wm8903_reg_defaults)); 291 sizeof(wm8903_reg_defaults));
369} 292}
@@ -373,6 +296,15 @@ static void wm8903_reset(struct snd_soc_codec *codec)
373#define WM8903_OUTPUT_INT 0x2 296#define WM8903_OUTPUT_INT 0x2
374#define WM8903_OUTPUT_IN 0x1 297#define WM8903_OUTPUT_IN 0x1
375 298
299static int wm8903_cp_event(struct snd_soc_dapm_widget *w,
300 struct snd_kcontrol *kcontrol, int event)
301{
302 WARN_ON(event != SND_SOC_DAPM_POST_PMU);
303 mdelay(4);
304
305 return 0;
306}
307
376/* 308/*
377 * Event for headphone and line out amplifier power changes. Special 309 * Event for headphone and line out amplifier power changes. Special
378 * power up/down sequences are required in order to maximise pop/click 310 * power up/down sequences are required in order to maximise pop/click
@@ -382,19 +314,20 @@ static int wm8903_output_event(struct snd_soc_dapm_widget *w,
382 struct snd_kcontrol *kcontrol, int event) 314 struct snd_kcontrol *kcontrol, int event)
383{ 315{
384 struct snd_soc_codec *codec = w->codec; 316 struct snd_soc_codec *codec = w->codec;
385 struct wm8903_priv *wm8903 = codec->private_data;
386 struct i2c_client *i2c = codec->control_data;
387 u16 val; 317 u16 val;
388 u16 reg; 318 u16 reg;
319 u16 dcs_reg;
320 u16 dcs_bit;
389 int shift; 321 int shift;
390 u16 cp_reg = wm8903_read(codec, WM8903_CHARGE_PUMP_0);
391 322
392 switch (w->reg) { 323 switch (w->reg) {
393 case WM8903_POWER_MANAGEMENT_2: 324 case WM8903_POWER_MANAGEMENT_2:
394 reg = WM8903_ANALOGUE_HP_0; 325 reg = WM8903_ANALOGUE_HP_0;
326 dcs_bit = 0 + w->shift;
395 break; 327 break;
396 case WM8903_POWER_MANAGEMENT_3: 328 case WM8903_POWER_MANAGEMENT_3:
397 reg = WM8903_ANALOGUE_LINEOUT_0; 329 reg = WM8903_ANALOGUE_LINEOUT_0;
330 dcs_bit = 2 + w->shift;
398 break; 331 break;
399 default: 332 default:
400 BUG(); 333 BUG();
@@ -414,67 +347,52 @@ static int wm8903_output_event(struct snd_soc_dapm_widget *w,
414 } 347 }
415 348
416 if (event & SND_SOC_DAPM_PRE_PMU) { 349 if (event & SND_SOC_DAPM_PRE_PMU) {
417 val = wm8903_read(codec, reg); 350 val = snd_soc_read(codec, reg);
418 351
419 /* Short the output */ 352 /* Short the output */
420 val &= ~(WM8903_OUTPUT_SHORT << shift); 353 val &= ~(WM8903_OUTPUT_SHORT << shift);
421 wm8903_write(codec, reg, val); 354 snd_soc_write(codec, reg, val);
422
423 wm8903->charge_pump_users++;
424
425 dev_dbg(&i2c->dev, "Charge pump use count now %d\n",
426 wm8903->charge_pump_users);
427
428 if (wm8903->charge_pump_users == 1) {
429 dev_dbg(&i2c->dev, "Enabling charge pump\n");
430 wm8903_write(codec, WM8903_CHARGE_PUMP_0,
431 cp_reg | WM8903_CP_ENA);
432 mdelay(4);
433 }
434 } 355 }
435 356
436 if (event & SND_SOC_DAPM_POST_PMU) { 357 if (event & SND_SOC_DAPM_POST_PMU) {
437 val = wm8903_read(codec, reg); 358 val = snd_soc_read(codec, reg);
438 359
439 val |= (WM8903_OUTPUT_IN << shift); 360 val |= (WM8903_OUTPUT_IN << shift);
440 wm8903_write(codec, reg, val); 361 snd_soc_write(codec, reg, val);
441 362
442 val |= (WM8903_OUTPUT_INT << shift); 363 val |= (WM8903_OUTPUT_INT << shift);
443 wm8903_write(codec, reg, val); 364 snd_soc_write(codec, reg, val);
444 365
445 /* Turn on the output ENA_OUTP */ 366 /* Turn on the output ENA_OUTP */
446 val |= (WM8903_OUTPUT_OUT << shift); 367 val |= (WM8903_OUTPUT_OUT << shift);
447 wm8903_write(codec, reg, val); 368 snd_soc_write(codec, reg, val);
369
370 /* Enable the DC servo */
371 dcs_reg = snd_soc_read(codec, WM8903_DC_SERVO_0);
372 dcs_reg |= dcs_bit;
373 snd_soc_write(codec, WM8903_DC_SERVO_0, dcs_reg);
448 374
449 /* Remove the short */ 375 /* Remove the short */
450 val |= (WM8903_OUTPUT_SHORT << shift); 376 val |= (WM8903_OUTPUT_SHORT << shift);
451 wm8903_write(codec, reg, val); 377 snd_soc_write(codec, reg, val);
452 } 378 }
453 379
454 if (event & SND_SOC_DAPM_PRE_PMD) { 380 if (event & SND_SOC_DAPM_PRE_PMD) {
455 val = wm8903_read(codec, reg); 381 val = snd_soc_read(codec, reg);
456 382
457 /* Short the output */ 383 /* Short the output */
458 val &= ~(WM8903_OUTPUT_SHORT << shift); 384 val &= ~(WM8903_OUTPUT_SHORT << shift);
459 wm8903_write(codec, reg, val); 385 snd_soc_write(codec, reg, val);
386
387 /* Disable the DC servo */
388 dcs_reg = snd_soc_read(codec, WM8903_DC_SERVO_0);
389 dcs_reg &= ~dcs_bit;
390 snd_soc_write(codec, WM8903_DC_SERVO_0, dcs_reg);
460 391
461 /* Then disable the intermediate and output stages */ 392 /* Then disable the intermediate and output stages */
462 val &= ~((WM8903_OUTPUT_OUT | WM8903_OUTPUT_INT | 393 val &= ~((WM8903_OUTPUT_OUT | WM8903_OUTPUT_INT |
463 WM8903_OUTPUT_IN) << shift); 394 WM8903_OUTPUT_IN) << shift);
464 wm8903_write(codec, reg, val); 395 snd_soc_write(codec, reg, val);
465 }
466
467 if (event & SND_SOC_DAPM_POST_PMD) {
468 wm8903->charge_pump_users--;
469
470 dev_dbg(&i2c->dev, "Charge pump use count now %d\n",
471 wm8903->charge_pump_users);
472
473 if (wm8903->charge_pump_users == 0) {
474 dev_dbg(&i2c->dev, "Disabling charge pump\n");
475 wm8903_write(codec, WM8903_CHARGE_PUMP_0,
476 cp_reg & ~WM8903_CP_ENA);
477 }
478 } 396 }
479 397
480 return 0; 398 return 0;
@@ -498,13 +416,13 @@ static int wm8903_class_w_put(struct snd_kcontrol *kcontrol,
498 u16 reg; 416 u16 reg;
499 int ret; 417 int ret;
500 418
501 reg = wm8903_read(codec, WM8903_CLASS_W_0); 419 reg = snd_soc_read(codec, WM8903_CLASS_W_0);
502 420
503 /* Turn it off if we're about to enable bypass */ 421 /* Turn it off if we're about to enable bypass */
504 if (ucontrol->value.integer.value[0]) { 422 if (ucontrol->value.integer.value[0]) {
505 if (wm8903->class_w_users == 0) { 423 if (wm8903->class_w_users == 0) {
506 dev_dbg(&i2c->dev, "Disabling Class W\n"); 424 dev_dbg(&i2c->dev, "Disabling Class W\n");
507 wm8903_write(codec, WM8903_CLASS_W_0, reg & 425 snd_soc_write(codec, WM8903_CLASS_W_0, reg &
508 ~(WM8903_CP_DYN_FREQ | WM8903_CP_DYN_V)); 426 ~(WM8903_CP_DYN_FREQ | WM8903_CP_DYN_V));
509 } 427 }
510 wm8903->class_w_users++; 428 wm8903->class_w_users++;
@@ -517,7 +435,7 @@ static int wm8903_class_w_put(struct snd_kcontrol *kcontrol,
517 if (!ucontrol->value.integer.value[0]) { 435 if (!ucontrol->value.integer.value[0]) {
518 if (wm8903->class_w_users == 1) { 436 if (wm8903->class_w_users == 1) {
519 dev_dbg(&i2c->dev, "Enabling Class W\n"); 437 dev_dbg(&i2c->dev, "Enabling Class W\n");
520 wm8903_write(codec, WM8903_CLASS_W_0, reg | 438 snd_soc_write(codec, WM8903_CLASS_W_0, reg |
521 WM8903_CP_DYN_FREQ | WM8903_CP_DYN_V); 439 WM8903_CP_DYN_FREQ | WM8903_CP_DYN_V);
522 } 440 }
523 wm8903->class_w_users--; 441 wm8903->class_w_users--;
@@ -539,6 +457,7 @@ static int wm8903_class_w_put(struct snd_kcontrol *kcontrol,
539/* ALSA can only do steps of .01dB */ 457/* ALSA can only do steps of .01dB */
540static const DECLARE_TLV_DB_SCALE(digital_tlv, -7200, 75, 1); 458static const DECLARE_TLV_DB_SCALE(digital_tlv, -7200, 75, 1);
541 459
460static const DECLARE_TLV_DB_SCALE(digital_sidetone_tlv, -3600, 300, 0);
542static const DECLARE_TLV_DB_SCALE(out_tlv, -5700, 100, 0); 461static const DECLARE_TLV_DB_SCALE(out_tlv, -5700, 100, 0);
543 462
544static const DECLARE_TLV_DB_SCALE(drc_tlv_thresh, 0, 75, 0); 463static const DECLARE_TLV_DB_SCALE(drc_tlv_thresh, 0, 75, 0);
@@ -657,6 +576,16 @@ static const struct soc_enum rinput_inv_enum =
657 SOC_ENUM_SINGLE(WM8903_ANALOGUE_RIGHT_INPUT_1, 4, 3, rinput_mux_text); 576 SOC_ENUM_SINGLE(WM8903_ANALOGUE_RIGHT_INPUT_1, 4, 3, rinput_mux_text);
658 577
659 578
579static const char *sidetone_text[] = {
580 "None", "Left", "Right"
581};
582
583static const struct soc_enum lsidetone_enum =
584 SOC_ENUM_SINGLE(WM8903_DAC_DIGITAL_0, 2, 3, sidetone_text);
585
586static const struct soc_enum rsidetone_enum =
587 SOC_ENUM_SINGLE(WM8903_DAC_DIGITAL_0, 0, 3, sidetone_text);
588
660static const struct snd_kcontrol_new wm8903_snd_controls[] = { 589static const struct snd_kcontrol_new wm8903_snd_controls[] = {
661 590
662/* Input PGAs - No TLV since the scale depends on PGA mode */ 591/* Input PGAs - No TLV since the scale depends on PGA mode */
@@ -700,6 +629,9 @@ SOC_DOUBLE_R_TLV("Digital Capture Volume", WM8903_ADC_DIGITAL_VOLUME_LEFT,
700SOC_ENUM("ADC Companding Mode", adc_companding), 629SOC_ENUM("ADC Companding Mode", adc_companding),
701SOC_SINGLE("ADC Companding Switch", WM8903_AUDIO_INTERFACE_0, 3, 1, 0), 630SOC_SINGLE("ADC Companding Switch", WM8903_AUDIO_INTERFACE_0, 3, 1, 0),
702 631
632SOC_DOUBLE_TLV("Digital Sidetone Volume", WM8903_DAC_DIGITAL_0, 4, 8,
633 12, 0, digital_sidetone_tlv),
634
703/* DAC */ 635/* DAC */
704SOC_DOUBLE_R_TLV("Digital Playback Volume", WM8903_DAC_DIGITAL_VOLUME_LEFT, 636SOC_DOUBLE_R_TLV("Digital Playback Volume", WM8903_DAC_DIGITAL_VOLUME_LEFT,
705 WM8903_DAC_DIGITAL_VOLUME_RIGHT, 1, 120, 0, digital_tlv), 637 WM8903_DAC_DIGITAL_VOLUME_RIGHT, 1, 120, 0, digital_tlv),
@@ -707,8 +639,6 @@ SOC_ENUM("DAC Soft Mute Rate", soft_mute),
707SOC_ENUM("DAC Mute Mode", mute_mode), 639SOC_ENUM("DAC Mute Mode", mute_mode),
708SOC_SINGLE("DAC Mono Switch", WM8903_DAC_DIGITAL_1, 12, 1, 0), 640SOC_SINGLE("DAC Mono Switch", WM8903_DAC_DIGITAL_1, 12, 1, 0),
709SOC_ENUM("DAC De-emphasis", dac_deemphasis), 641SOC_ENUM("DAC De-emphasis", dac_deemphasis),
710SOC_SINGLE("DAC Sloping Stopband Filter Switch",
711 WM8903_DAC_DIGITAL_1, 11, 1, 0),
712SOC_ENUM("DAC Companding Mode", dac_companding), 642SOC_ENUM("DAC Companding Mode", dac_companding),
713SOC_SINGLE("DAC Companding Switch", WM8903_AUDIO_INTERFACE_0, 1, 1, 0), 643SOC_SINGLE("DAC Companding Switch", WM8903_AUDIO_INTERFACE_0, 1, 1, 0),
714 644
@@ -762,6 +692,12 @@ static const struct snd_kcontrol_new rinput_mux =
762static const struct snd_kcontrol_new rinput_inv_mux = 692static const struct snd_kcontrol_new rinput_inv_mux =
763 SOC_DAPM_ENUM("Right Inverting Input Mux", rinput_inv_enum); 693 SOC_DAPM_ENUM("Right Inverting Input Mux", rinput_inv_enum);
764 694
695static const struct snd_kcontrol_new lsidetone_mux =
696 SOC_DAPM_ENUM("DACL Sidetone Mux", lsidetone_enum);
697
698static const struct snd_kcontrol_new rsidetone_mux =
699 SOC_DAPM_ENUM("DACR Sidetone Mux", rsidetone_enum);
700
765static const struct snd_kcontrol_new left_output_mixer[] = { 701static const struct snd_kcontrol_new left_output_mixer[] = {
766SOC_DAPM_SINGLE("DACL Switch", WM8903_ANALOGUE_LEFT_MIX_0, 3, 1, 0), 702SOC_DAPM_SINGLE("DACL Switch", WM8903_ANALOGUE_LEFT_MIX_0, 3, 1, 0),
767SOC_DAPM_SINGLE("DACR Switch", WM8903_ANALOGUE_LEFT_MIX_0, 2, 1, 0), 703SOC_DAPM_SINGLE("DACR Switch", WM8903_ANALOGUE_LEFT_MIX_0, 2, 1, 0),
@@ -828,6 +764,9 @@ SND_SOC_DAPM_PGA("Right Input PGA", WM8903_POWER_MANAGEMENT_0, 0, 0, NULL, 0),
828SND_SOC_DAPM_ADC("ADCL", "Left HiFi Capture", WM8903_POWER_MANAGEMENT_6, 1, 0), 764SND_SOC_DAPM_ADC("ADCL", "Left HiFi Capture", WM8903_POWER_MANAGEMENT_6, 1, 0),
829SND_SOC_DAPM_ADC("ADCR", "Right HiFi Capture", WM8903_POWER_MANAGEMENT_6, 0, 0), 765SND_SOC_DAPM_ADC("ADCR", "Right HiFi Capture", WM8903_POWER_MANAGEMENT_6, 0, 0),
830 766
767SND_SOC_DAPM_MUX("DACL Sidetone", SND_SOC_NOPM, 0, 0, &lsidetone_mux),
768SND_SOC_DAPM_MUX("DACR Sidetone", SND_SOC_NOPM, 0, 0, &rsidetone_mux),
769
831SND_SOC_DAPM_DAC("DACL", "Left Playback", WM8903_POWER_MANAGEMENT_6, 3, 0), 770SND_SOC_DAPM_DAC("DACL", "Left Playback", WM8903_POWER_MANAGEMENT_6, 3, 0),
832SND_SOC_DAPM_DAC("DACR", "Right Playback", WM8903_POWER_MANAGEMENT_6, 2, 0), 771SND_SOC_DAPM_DAC("DACR", "Right Playback", WM8903_POWER_MANAGEMENT_6, 2, 0),
833 772
@@ -844,26 +783,29 @@ SND_SOC_DAPM_MIXER("Right Speaker Mixer", WM8903_POWER_MANAGEMENT_4, 0, 0,
844SND_SOC_DAPM_PGA_E("Left Headphone Output PGA", WM8903_POWER_MANAGEMENT_2, 783SND_SOC_DAPM_PGA_E("Left Headphone Output PGA", WM8903_POWER_MANAGEMENT_2,
845 1, 0, NULL, 0, wm8903_output_event, 784 1, 0, NULL, 0, wm8903_output_event,
846 SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU | 785 SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
847 SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD), 786 SND_SOC_DAPM_PRE_PMD),
848SND_SOC_DAPM_PGA_E("Right Headphone Output PGA", WM8903_POWER_MANAGEMENT_2, 787SND_SOC_DAPM_PGA_E("Right Headphone Output PGA", WM8903_POWER_MANAGEMENT_2,
849 0, 0, NULL, 0, wm8903_output_event, 788 0, 0, NULL, 0, wm8903_output_event,
850 SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU | 789 SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
851 SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD), 790 SND_SOC_DAPM_PRE_PMD),
852 791
853SND_SOC_DAPM_PGA_E("Left Line Output PGA", WM8903_POWER_MANAGEMENT_3, 1, 0, 792SND_SOC_DAPM_PGA_E("Left Line Output PGA", WM8903_POWER_MANAGEMENT_3, 1, 0,
854 NULL, 0, wm8903_output_event, 793 NULL, 0, wm8903_output_event,
855 SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU | 794 SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
856 SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD), 795 SND_SOC_DAPM_PRE_PMD),
857SND_SOC_DAPM_PGA_E("Right Line Output PGA", WM8903_POWER_MANAGEMENT_3, 0, 0, 796SND_SOC_DAPM_PGA_E("Right Line Output PGA", WM8903_POWER_MANAGEMENT_3, 0, 0,
858 NULL, 0, wm8903_output_event, 797 NULL, 0, wm8903_output_event,
859 SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU | 798 SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
860 SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD), 799 SND_SOC_DAPM_PRE_PMD),
861 800
862SND_SOC_DAPM_PGA("Left Speaker PGA", WM8903_POWER_MANAGEMENT_5, 1, 0, 801SND_SOC_DAPM_PGA("Left Speaker PGA", WM8903_POWER_MANAGEMENT_5, 1, 0,
863 NULL, 0), 802 NULL, 0),
864SND_SOC_DAPM_PGA("Right Speaker PGA", WM8903_POWER_MANAGEMENT_5, 0, 0, 803SND_SOC_DAPM_PGA("Right Speaker PGA", WM8903_POWER_MANAGEMENT_5, 0, 0,
865 NULL, 0), 804 NULL, 0),
866 805
806SND_SOC_DAPM_SUPPLY("Charge Pump", WM8903_CHARGE_PUMP_0, 0, 0,
807 wm8903_cp_event, SND_SOC_DAPM_POST_PMU),
808SND_SOC_DAPM_SUPPLY("CLK_DSP", WM8903_CLOCK_RATES_2, 1, 0, NULL, 0),
867}; 809};
868 810
869static const struct snd_soc_dapm_route intercon[] = { 811static const struct snd_soc_dapm_route intercon[] = {
@@ -909,7 +851,19 @@ static const struct snd_soc_dapm_route intercon[] = {
909 { "Right Input PGA", NULL, "Right Input Mode Mux" }, 851 { "Right Input PGA", NULL, "Right Input Mode Mux" },
910 852
911 { "ADCL", NULL, "Left Input PGA" }, 853 { "ADCL", NULL, "Left Input PGA" },
854 { "ADCL", NULL, "CLK_DSP" },
912 { "ADCR", NULL, "Right Input PGA" }, 855 { "ADCR", NULL, "Right Input PGA" },
856 { "ADCR", NULL, "CLK_DSP" },
857
858 { "DACL Sidetone", "Left", "ADCL" },
859 { "DACL Sidetone", "Right", "ADCR" },
860 { "DACR Sidetone", "Left", "ADCL" },
861 { "DACR Sidetone", "Right", "ADCR" },
862
863 { "DACL", NULL, "DACL Sidetone" },
864 { "DACL", NULL, "CLK_DSP" },
865 { "DACR", NULL, "DACR Sidetone" },
866 { "DACR", NULL, "CLK_DSP" },
913 867
914 { "Left Output Mixer", "Left Bypass Switch", "Left Input PGA" }, 868 { "Left Output Mixer", "Left Bypass Switch", "Left Input PGA" },
915 { "Left Output Mixer", "Right Bypass Switch", "Right Input PGA" }, 869 { "Left Output Mixer", "Right Bypass Switch", "Right Input PGA" },
@@ -951,6 +905,11 @@ static const struct snd_soc_dapm_route intercon[] = {
951 905
952 { "ROP", NULL, "Right Speaker PGA" }, 906 { "ROP", NULL, "Right Speaker PGA" },
953 { "RON", NULL, "Right Speaker PGA" }, 907 { "RON", NULL, "Right Speaker PGA" },
908
909 { "Left Headphone Output PGA", NULL, "Charge Pump" },
910 { "Right Headphone Output PGA", NULL, "Charge Pump" },
911 { "Left Line Output PGA", NULL, "Charge Pump" },
912 { "Right Line Output PGA", NULL, "Charge Pump" },
954}; 913};
955 914
956static int wm8903_add_widgets(struct snd_soc_codec *codec) 915static int wm8903_add_widgets(struct snd_soc_codec *codec)
@@ -974,50 +933,55 @@ static int wm8903_set_bias_level(struct snd_soc_codec *codec,
974 switch (level) { 933 switch (level) {
975 case SND_SOC_BIAS_ON: 934 case SND_SOC_BIAS_ON:
976 case SND_SOC_BIAS_PREPARE: 935 case SND_SOC_BIAS_PREPARE:
977 reg = wm8903_read(codec, WM8903_VMID_CONTROL_0); 936 reg = snd_soc_read(codec, WM8903_VMID_CONTROL_0);
978 reg &= ~(WM8903_VMID_RES_MASK); 937 reg &= ~(WM8903_VMID_RES_MASK);
979 reg |= WM8903_VMID_RES_50K; 938 reg |= WM8903_VMID_RES_50K;
980 wm8903_write(codec, WM8903_VMID_CONTROL_0, reg); 939 snd_soc_write(codec, WM8903_VMID_CONTROL_0, reg);
981 break; 940 break;
982 941
983 case SND_SOC_BIAS_STANDBY: 942 case SND_SOC_BIAS_STANDBY:
984 if (codec->bias_level == SND_SOC_BIAS_OFF) { 943 if (codec->bias_level == SND_SOC_BIAS_OFF) {
985 wm8903_write(codec, WM8903_CLOCK_RATES_2, 944 snd_soc_write(codec, WM8903_CLOCK_RATES_2,
986 WM8903_CLK_SYS_ENA); 945 WM8903_CLK_SYS_ENA);
987 946
947 /* Change DC servo dither level in startup sequence */
948 snd_soc_write(codec, WM8903_WRITE_SEQUENCER_0, 0x11);
949 snd_soc_write(codec, WM8903_WRITE_SEQUENCER_1, 0x1257);
950 snd_soc_write(codec, WM8903_WRITE_SEQUENCER_2, 0x2);
951
988 wm8903_run_sequence(codec, 0); 952 wm8903_run_sequence(codec, 0);
989 wm8903_sync_reg_cache(codec, codec->reg_cache); 953 wm8903_sync_reg_cache(codec, codec->reg_cache);
990 954
991 /* Enable low impedence charge pump output */ 955 /* Enable low impedence charge pump output */
992 reg = wm8903_read(codec, 956 reg = snd_soc_read(codec,
993 WM8903_CONTROL_INTERFACE_TEST_1); 957 WM8903_CONTROL_INTERFACE_TEST_1);
994 wm8903_write(codec, WM8903_CONTROL_INTERFACE_TEST_1, 958 snd_soc_write(codec, WM8903_CONTROL_INTERFACE_TEST_1,
995 reg | WM8903_TEST_KEY); 959 reg | WM8903_TEST_KEY);
996 reg2 = wm8903_read(codec, WM8903_CHARGE_PUMP_TEST_1); 960 reg2 = snd_soc_read(codec, WM8903_CHARGE_PUMP_TEST_1);
997 wm8903_write(codec, WM8903_CHARGE_PUMP_TEST_1, 961 snd_soc_write(codec, WM8903_CHARGE_PUMP_TEST_1,
998 reg2 | WM8903_CP_SW_KELVIN_MODE_MASK); 962 reg2 | WM8903_CP_SW_KELVIN_MODE_MASK);
999 wm8903_write(codec, WM8903_CONTROL_INTERFACE_TEST_1, 963 snd_soc_write(codec, WM8903_CONTROL_INTERFACE_TEST_1,
1000 reg); 964 reg);
1001 965
1002 /* By default no bypass paths are enabled so 966 /* By default no bypass paths are enabled so
1003 * enable Class W support. 967 * enable Class W support.
1004 */ 968 */
1005 dev_dbg(&i2c->dev, "Enabling Class W\n"); 969 dev_dbg(&i2c->dev, "Enabling Class W\n");
1006 wm8903_write(codec, WM8903_CLASS_W_0, reg | 970 snd_soc_write(codec, WM8903_CLASS_W_0, reg |
1007 WM8903_CP_DYN_FREQ | WM8903_CP_DYN_V); 971 WM8903_CP_DYN_FREQ | WM8903_CP_DYN_V);
1008 } 972 }
1009 973
1010 reg = wm8903_read(codec, WM8903_VMID_CONTROL_0); 974 reg = snd_soc_read(codec, WM8903_VMID_CONTROL_0);
1011 reg &= ~(WM8903_VMID_RES_MASK); 975 reg &= ~(WM8903_VMID_RES_MASK);
1012 reg |= WM8903_VMID_RES_250K; 976 reg |= WM8903_VMID_RES_250K;
1013 wm8903_write(codec, WM8903_VMID_CONTROL_0, reg); 977 snd_soc_write(codec, WM8903_VMID_CONTROL_0, reg);
1014 break; 978 break;
1015 979
1016 case SND_SOC_BIAS_OFF: 980 case SND_SOC_BIAS_OFF:
1017 wm8903_run_sequence(codec, 32); 981 wm8903_run_sequence(codec, 32);
1018 reg = wm8903_read(codec, WM8903_CLOCK_RATES_2); 982 reg = snd_soc_read(codec, WM8903_CLOCK_RATES_2);
1019 reg &= ~WM8903_CLK_SYS_ENA; 983 reg &= ~WM8903_CLK_SYS_ENA;
1020 wm8903_write(codec, WM8903_CLOCK_RATES_2, reg); 984 snd_soc_write(codec, WM8903_CLOCK_RATES_2, reg);
1021 break; 985 break;
1022 } 986 }
1023 987
@@ -1041,7 +1005,7 @@ static int wm8903_set_dai_fmt(struct snd_soc_dai *codec_dai,
1041 unsigned int fmt) 1005 unsigned int fmt)
1042{ 1006{
1043 struct snd_soc_codec *codec = codec_dai->codec; 1007 struct snd_soc_codec *codec = codec_dai->codec;
1044 u16 aif1 = wm8903_read(codec, WM8903_AUDIO_INTERFACE_1); 1008 u16 aif1 = snd_soc_read(codec, WM8903_AUDIO_INTERFACE_1);
1045 1009
1046 aif1 &= ~(WM8903_LRCLK_DIR | WM8903_BCLK_DIR | WM8903_AIF_FMT_MASK | 1010 aif1 &= ~(WM8903_LRCLK_DIR | WM8903_BCLK_DIR | WM8903_AIF_FMT_MASK |
1047 WM8903_AIF_LRCLK_INV | WM8903_AIF_BCLK_INV); 1011 WM8903_AIF_LRCLK_INV | WM8903_AIF_BCLK_INV);
@@ -1119,7 +1083,7 @@ static int wm8903_set_dai_fmt(struct snd_soc_dai *codec_dai,
1119 return -EINVAL; 1083 return -EINVAL;
1120 } 1084 }
1121 1085
1122 wm8903_write(codec, WM8903_AUDIO_INTERFACE_1, aif1); 1086 snd_soc_write(codec, WM8903_AUDIO_INTERFACE_1, aif1);
1123 1087
1124 return 0; 1088 return 0;
1125} 1089}
@@ -1129,14 +1093,14 @@ static int wm8903_digital_mute(struct snd_soc_dai *codec_dai, int mute)
1129 struct snd_soc_codec *codec = codec_dai->codec; 1093 struct snd_soc_codec *codec = codec_dai->codec;
1130 u16 reg; 1094 u16 reg;
1131 1095
1132 reg = wm8903_read(codec, WM8903_DAC_DIGITAL_1); 1096 reg = snd_soc_read(codec, WM8903_DAC_DIGITAL_1);
1133 1097
1134 if (mute) 1098 if (mute)
1135 reg |= WM8903_DAC_MUTE; 1099 reg |= WM8903_DAC_MUTE;
1136 else 1100 else
1137 reg &= ~WM8903_DAC_MUTE; 1101 reg &= ~WM8903_DAC_MUTE;
1138 1102
1139 wm8903_write(codec, WM8903_DAC_DIGITAL_1, reg); 1103 snd_soc_write(codec, WM8903_DAC_DIGITAL_1, reg);
1140 1104
1141 return 0; 1105 return 0;
1142} 1106}
@@ -1215,22 +1179,18 @@ static struct {
1215 int div; 1179 int div;
1216} bclk_divs[] = { 1180} bclk_divs[] = {
1217 { 10, 0 }, 1181 { 10, 0 },
1218 { 15, 1 },
1219 { 20, 2 }, 1182 { 20, 2 },
1220 { 30, 3 }, 1183 { 30, 3 },
1221 { 40, 4 }, 1184 { 40, 4 },
1222 { 50, 5 }, 1185 { 50, 5 },
1223 { 55, 6 },
1224 { 60, 7 }, 1186 { 60, 7 },
1225 { 80, 8 }, 1187 { 80, 8 },
1226 { 100, 9 }, 1188 { 100, 9 },
1227 { 110, 10 },
1228 { 120, 11 }, 1189 { 120, 11 },
1229 { 160, 12 }, 1190 { 160, 12 },
1230 { 200, 13 }, 1191 { 200, 13 },
1231 { 220, 14 }, 1192 { 220, 14 },
1232 { 240, 15 }, 1193 { 240, 15 },
1233 { 250, 16 },
1234 { 300, 17 }, 1194 { 300, 17 },
1235 { 320, 18 }, 1195 { 320, 18 },
1236 { 440, 19 }, 1196 { 440, 19 },
@@ -1277,14 +1237,8 @@ static int wm8903_startup(struct snd_pcm_substream *substream,
1277 if (wm8903->master_substream) { 1237 if (wm8903->master_substream) {
1278 master_runtime = wm8903->master_substream->runtime; 1238 master_runtime = wm8903->master_substream->runtime;
1279 1239
1280 dev_dbg(&i2c->dev, "Constraining to %d bits at %dHz\n", 1240 dev_dbg(&i2c->dev, "Constraining to %d bits\n",
1281 master_runtime->sample_bits, 1241 master_runtime->sample_bits);
1282 master_runtime->rate);
1283
1284 snd_pcm_hw_constraint_minmax(substream->runtime,
1285 SNDRV_PCM_HW_PARAM_RATE,
1286 master_runtime->rate,
1287 master_runtime->rate);
1288 1242
1289 snd_pcm_hw_constraint_minmax(substream->runtime, 1243 snd_pcm_hw_constraint_minmax(substream->runtime,
1290 SNDRV_PCM_HW_PARAM_SAMPLE_BITS, 1244 SNDRV_PCM_HW_PARAM_SAMPLE_BITS,
@@ -1336,17 +1290,24 @@ static int wm8903_hw_params(struct snd_pcm_substream *substream,
1336 int cur_val; 1290 int cur_val;
1337 int clk_sys; 1291 int clk_sys;
1338 1292
1339 u16 aif1 = wm8903_read(codec, WM8903_AUDIO_INTERFACE_1); 1293 u16 aif1 = snd_soc_read(codec, WM8903_AUDIO_INTERFACE_1);
1340 u16 aif2 = wm8903_read(codec, WM8903_AUDIO_INTERFACE_2); 1294 u16 aif2 = snd_soc_read(codec, WM8903_AUDIO_INTERFACE_2);
1341 u16 aif3 = wm8903_read(codec, WM8903_AUDIO_INTERFACE_3); 1295 u16 aif3 = snd_soc_read(codec, WM8903_AUDIO_INTERFACE_3);
1342 u16 clock0 = wm8903_read(codec, WM8903_CLOCK_RATES_0); 1296 u16 clock0 = snd_soc_read(codec, WM8903_CLOCK_RATES_0);
1343 u16 clock1 = wm8903_read(codec, WM8903_CLOCK_RATES_1); 1297 u16 clock1 = snd_soc_read(codec, WM8903_CLOCK_RATES_1);
1298 u16 dac_digital1 = snd_soc_read(codec, WM8903_DAC_DIGITAL_1);
1344 1299
1345 if (substream == wm8903->slave_substream) { 1300 if (substream == wm8903->slave_substream) {
1346 dev_dbg(&i2c->dev, "Ignoring hw_params for slave substream\n"); 1301 dev_dbg(&i2c->dev, "Ignoring hw_params for slave substream\n");
1347 return 0; 1302 return 0;
1348 } 1303 }
1349 1304
1305 /* Enable sloping stopband filter for low sample rates */
1306 if (fs <= 24000)
1307 dac_digital1 |= WM8903_DAC_SB_FILT;
1308 else
1309 dac_digital1 &= ~WM8903_DAC_SB_FILT;
1310
1350 /* Configure sample rate logic for DSP - choose nearest rate */ 1311 /* Configure sample rate logic for DSP - choose nearest rate */
1351 dsp_config = 0; 1312 dsp_config = 0;
1352 best_val = abs(sample_rates[dsp_config].rate - fs); 1313 best_val = abs(sample_rates[dsp_config].rate - fs);
@@ -1466,11 +1427,12 @@ static int wm8903_hw_params(struct snd_pcm_substream *substream,
1466 aif2 |= bclk_divs[bclk_div].div; 1427 aif2 |= bclk_divs[bclk_div].div;
1467 aif3 |= bclk / fs; 1428 aif3 |= bclk / fs;
1468 1429
1469 wm8903_write(codec, WM8903_CLOCK_RATES_0, clock0); 1430 snd_soc_write(codec, WM8903_CLOCK_RATES_0, clock0);
1470 wm8903_write(codec, WM8903_CLOCK_RATES_1, clock1); 1431 snd_soc_write(codec, WM8903_CLOCK_RATES_1, clock1);
1471 wm8903_write(codec, WM8903_AUDIO_INTERFACE_1, aif1); 1432 snd_soc_write(codec, WM8903_AUDIO_INTERFACE_1, aif1);
1472 wm8903_write(codec, WM8903_AUDIO_INTERFACE_2, aif2); 1433 snd_soc_write(codec, WM8903_AUDIO_INTERFACE_2, aif2);
1473 wm8903_write(codec, WM8903_AUDIO_INTERFACE_3, aif3); 1434 snd_soc_write(codec, WM8903_AUDIO_INTERFACE_3, aif3);
1435 snd_soc_write(codec, WM8903_DAC_DIGITAL_1, dac_digital1);
1474 1436
1475 return 0; 1437 return 0;
1476} 1438}
@@ -1523,6 +1485,7 @@ struct snd_soc_dai wm8903_dai = {
1523 .formats = WM8903_FORMATS, 1485 .formats = WM8903_FORMATS,
1524 }, 1486 },
1525 .ops = &wm8903_dai_ops, 1487 .ops = &wm8903_dai_ops,
1488 .symmetric_rates = 1,
1526}; 1489};
1527EXPORT_SYMBOL_GPL(wm8903_dai); 1490EXPORT_SYMBOL_GPL(wm8903_dai);
1528 1491
@@ -1554,7 +1517,7 @@ static int wm8903_resume(struct platform_device *pdev)
1554 if (tmp_cache) { 1517 if (tmp_cache) {
1555 for (i = 2; i < ARRAY_SIZE(wm8903_reg_defaults); i++) 1518 for (i = 2; i < ARRAY_SIZE(wm8903_reg_defaults); i++)
1556 if (tmp_cache[i] != reg_cache[i]) 1519 if (tmp_cache[i] != reg_cache[i])
1557 wm8903_write(codec, i, tmp_cache[i]); 1520 snd_soc_write(codec, i, tmp_cache[i]);
1558 } else { 1521 } else {
1559 dev_err(&i2c->dev, "Failed to allocate temporary cache\n"); 1522 dev_err(&i2c->dev, "Failed to allocate temporary cache\n");
1560 } 1523 }
@@ -1585,9 +1548,6 @@ static __devinit int wm8903_i2c_probe(struct i2c_client *i2c,
1585 codec->dev = &i2c->dev; 1548 codec->dev = &i2c->dev;
1586 codec->name = "WM8903"; 1549 codec->name = "WM8903";
1587 codec->owner = THIS_MODULE; 1550 codec->owner = THIS_MODULE;
1588 codec->read = wm8903_read;
1589 codec->write = wm8903_write;
1590 codec->hw_write = (hw_write_t)i2c_master_send;
1591 codec->bias_level = SND_SOC_BIAS_OFF; 1551 codec->bias_level = SND_SOC_BIAS_OFF;
1592 codec->set_bias_level = wm8903_set_bias_level; 1552 codec->set_bias_level = wm8903_set_bias_level;
1593 codec->dai = &wm8903_dai; 1553 codec->dai = &wm8903_dai;
@@ -1595,18 +1555,25 @@ static __devinit int wm8903_i2c_probe(struct i2c_client *i2c,
1595 codec->reg_cache_size = ARRAY_SIZE(wm8903->reg_cache); 1555 codec->reg_cache_size = ARRAY_SIZE(wm8903->reg_cache);
1596 codec->reg_cache = &wm8903->reg_cache[0]; 1556 codec->reg_cache = &wm8903->reg_cache[0];
1597 codec->private_data = wm8903; 1557 codec->private_data = wm8903;
1558 codec->volatile_register = wm8903_volatile_register;
1598 1559
1599 i2c_set_clientdata(i2c, codec); 1560 i2c_set_clientdata(i2c, codec);
1600 codec->control_data = i2c; 1561 codec->control_data = i2c;
1601 1562
1602 val = wm8903_hw_read(codec, WM8903_SW_RESET_AND_ID); 1563 ret = snd_soc_codec_set_cache_io(codec, 8, 16, SND_SOC_I2C);
1564 if (ret != 0) {
1565 dev_err(&i2c->dev, "Failed to set cache I/O: %d\n", ret);
1566 goto err;
1567 }
1568
1569 val = snd_soc_read(codec, WM8903_SW_RESET_AND_ID);
1603 if (val != wm8903_reg_defaults[WM8903_SW_RESET_AND_ID]) { 1570 if (val != wm8903_reg_defaults[WM8903_SW_RESET_AND_ID]) {
1604 dev_err(&i2c->dev, 1571 dev_err(&i2c->dev,
1605 "Device with ID register %x is not a WM8903\n", val); 1572 "Device with ID register %x is not a WM8903\n", val);
1606 return -ENODEV; 1573 return -ENODEV;
1607 } 1574 }
1608 1575
1609 val = wm8903_read(codec, WM8903_REVISION_NUMBER); 1576 val = snd_soc_read(codec, WM8903_REVISION_NUMBER);
1610 dev_info(&i2c->dev, "WM8903 revision %d\n", 1577 dev_info(&i2c->dev, "WM8903 revision %d\n",
1611 val & WM8903_CHIP_REV_MASK); 1578 val & WM8903_CHIP_REV_MASK);
1612 1579
@@ -1616,35 +1583,35 @@ static __devinit int wm8903_i2c_probe(struct i2c_client *i2c,
1616 wm8903_set_bias_level(codec, SND_SOC_BIAS_STANDBY); 1583 wm8903_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
1617 1584
1618 /* Latch volume update bits */ 1585 /* Latch volume update bits */
1619 val = wm8903_read(codec, WM8903_ADC_DIGITAL_VOLUME_LEFT); 1586 val = snd_soc_read(codec, WM8903_ADC_DIGITAL_VOLUME_LEFT);
1620 val |= WM8903_ADCVU; 1587 val |= WM8903_ADCVU;
1621 wm8903_write(codec, WM8903_ADC_DIGITAL_VOLUME_LEFT, val); 1588 snd_soc_write(codec, WM8903_ADC_DIGITAL_VOLUME_LEFT, val);
1622 wm8903_write(codec, WM8903_ADC_DIGITAL_VOLUME_RIGHT, val); 1589 snd_soc_write(codec, WM8903_ADC_DIGITAL_VOLUME_RIGHT, val);
1623 1590
1624 val = wm8903_read(codec, WM8903_DAC_DIGITAL_VOLUME_LEFT); 1591 val = snd_soc_read(codec, WM8903_DAC_DIGITAL_VOLUME_LEFT);
1625 val |= WM8903_DACVU; 1592 val |= WM8903_DACVU;
1626 wm8903_write(codec, WM8903_DAC_DIGITAL_VOLUME_LEFT, val); 1593 snd_soc_write(codec, WM8903_DAC_DIGITAL_VOLUME_LEFT, val);
1627 wm8903_write(codec, WM8903_DAC_DIGITAL_VOLUME_RIGHT, val); 1594 snd_soc_write(codec, WM8903_DAC_DIGITAL_VOLUME_RIGHT, val);
1628 1595
1629 val = wm8903_read(codec, WM8903_ANALOGUE_OUT1_LEFT); 1596 val = snd_soc_read(codec, WM8903_ANALOGUE_OUT1_LEFT);
1630 val |= WM8903_HPOUTVU; 1597 val |= WM8903_HPOUTVU;
1631 wm8903_write(codec, WM8903_ANALOGUE_OUT1_LEFT, val); 1598 snd_soc_write(codec, WM8903_ANALOGUE_OUT1_LEFT, val);
1632 wm8903_write(codec, WM8903_ANALOGUE_OUT1_RIGHT, val); 1599 snd_soc_write(codec, WM8903_ANALOGUE_OUT1_RIGHT, val);
1633 1600
1634 val = wm8903_read(codec, WM8903_ANALOGUE_OUT2_LEFT); 1601 val = snd_soc_read(codec, WM8903_ANALOGUE_OUT2_LEFT);
1635 val |= WM8903_LINEOUTVU; 1602 val |= WM8903_LINEOUTVU;
1636 wm8903_write(codec, WM8903_ANALOGUE_OUT2_LEFT, val); 1603 snd_soc_write(codec, WM8903_ANALOGUE_OUT2_LEFT, val);
1637 wm8903_write(codec, WM8903_ANALOGUE_OUT2_RIGHT, val); 1604 snd_soc_write(codec, WM8903_ANALOGUE_OUT2_RIGHT, val);
1638 1605
1639 val = wm8903_read(codec, WM8903_ANALOGUE_OUT3_LEFT); 1606 val = snd_soc_read(codec, WM8903_ANALOGUE_OUT3_LEFT);
1640 val |= WM8903_SPKVU; 1607 val |= WM8903_SPKVU;
1641 wm8903_write(codec, WM8903_ANALOGUE_OUT3_LEFT, val); 1608 snd_soc_write(codec, WM8903_ANALOGUE_OUT3_LEFT, val);
1642 wm8903_write(codec, WM8903_ANALOGUE_OUT3_RIGHT, val); 1609 snd_soc_write(codec, WM8903_ANALOGUE_OUT3_RIGHT, val);
1643 1610
1644 /* Enable DAC soft mute by default */ 1611 /* Enable DAC soft mute by default */
1645 val = wm8903_read(codec, WM8903_DAC_DIGITAL_1); 1612 val = snd_soc_read(codec, WM8903_DAC_DIGITAL_1);
1646 val |= WM8903_DAC_MUTEMODE; 1613 val |= WM8903_DAC_MUTEMODE;
1647 wm8903_write(codec, WM8903_DAC_DIGITAL_1, val); 1614 snd_soc_write(codec, WM8903_DAC_DIGITAL_1, val);
1648 1615
1649 wm8903_dai.dev = &i2c->dev; 1616 wm8903_dai.dev = &i2c->dev;
1650 wm8903_codec = codec; 1617 wm8903_codec = codec;
@@ -1688,6 +1655,21 @@ static __devexit int wm8903_i2c_remove(struct i2c_client *client)
1688 return 0; 1655 return 0;
1689} 1656}
1690 1657
1658#ifdef CONFIG_PM
1659static int wm8903_i2c_suspend(struct i2c_client *client, pm_message_t msg)
1660{
1661 return snd_soc_suspend_device(&client->dev);
1662}
1663
1664static int wm8903_i2c_resume(struct i2c_client *client)
1665{
1666 return snd_soc_resume_device(&client->dev);
1667}
1668#else
1669#define wm8903_i2c_suspend NULL
1670#define wm8903_i2c_resume NULL
1671#endif
1672
1691/* i2c codec control layer */ 1673/* i2c codec control layer */
1692static const struct i2c_device_id wm8903_i2c_id[] = { 1674static const struct i2c_device_id wm8903_i2c_id[] = {
1693 { "wm8903", 0 }, 1675 { "wm8903", 0 },
@@ -1702,6 +1684,8 @@ static struct i2c_driver wm8903_i2c_driver = {
1702 }, 1684 },
1703 .probe = wm8903_i2c_probe, 1685 .probe = wm8903_i2c_probe,
1704 .remove = __devexit_p(wm8903_i2c_remove), 1686 .remove = __devexit_p(wm8903_i2c_remove),
1687 .suspend = wm8903_i2c_suspend,
1688 .resume = wm8903_i2c_resume,
1705 .id_table = wm8903_i2c_id, 1689 .id_table = wm8903_i2c_id,
1706}; 1690};
1707 1691
diff --git a/sound/soc/codecs/wm8940.c b/sound/soc/codecs/wm8940.c
new file mode 100644
index 000000000000..da97aae475a2
--- /dev/null
+++ b/sound/soc/codecs/wm8940.c
@@ -0,0 +1,933 @@
1/*
2 * wm8940.c -- WM8940 ALSA Soc Audio driver
3 *
4 * Author: Jonathan Cameron <jic23@cam.ac.uk>
5 *
6 * Based on wm8510.c
7 * Copyright 2006 Wolfson Microelectronics PLC.
8 * Author: Liam Girdwood <lrg@slimlogic.co.uk>
9 *
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License version 2 as
12 * published by the Free Software Foundation.
13 *
14 * Not currently handled:
15 * Notch filter control
16 * AUXMode (inverting vs mixer)
17 * No means to obtain current gain if alc enabled.
18 * No use made of gpio
19 * Fast VMID discharge for power down
20 * Soft Start
21 * DLR and ALR Swaps not enabled
22 * Digital Sidetone not supported
23 */
24#include <linux/module.h>
25#include <linux/moduleparam.h>
26#include <linux/kernel.h>
27#include <linux/init.h>
28#include <linux/delay.h>
29#include <linux/pm.h>
30#include <linux/i2c.h>
31#include <linux/platform_device.h>
32#include <linux/spi/spi.h>
33#include <sound/core.h>
34#include <sound/pcm.h>
35#include <sound/pcm_params.h>
36#include <sound/soc.h>
37#include <sound/soc-dapm.h>
38#include <sound/initval.h>
39#include <sound/tlv.h>
40
41#include "wm8940.h"
42
43struct wm8940_priv {
44 unsigned int sysclk;
45 u16 reg_cache[WM8940_CACHEREGNUM];
46 struct snd_soc_codec codec;
47};
48
49static u16 wm8940_reg_defaults[] = {
50 0x8940, /* Soft Reset */
51 0x0000, /* Power 1 */
52 0x0000, /* Power 2 */
53 0x0000, /* Power 3 */
54 0x0010, /* Interface Control */
55 0x0000, /* Companding Control */
56 0x0140, /* Clock Control */
57 0x0000, /* Additional Controls */
58 0x0000, /* GPIO Control */
59 0x0002, /* Auto Increment Control */
60 0x0000, /* DAC Control */
61 0x00FF, /* DAC Volume */
62 0,
63 0,
64 0x0100, /* ADC Control */
65 0x00FF, /* ADC Volume */
66 0x0000, /* Notch Filter 1 Control 1 */
67 0x0000, /* Notch Filter 1 Control 2 */
68 0x0000, /* Notch Filter 2 Control 1 */
69 0x0000, /* Notch Filter 2 Control 2 */
70 0x0000, /* Notch Filter 3 Control 1 */
71 0x0000, /* Notch Filter 3 Control 2 */
72 0x0000, /* Notch Filter 4 Control 1 */
73 0x0000, /* Notch Filter 4 Control 2 */
74 0x0032, /* DAC Limit Control 1 */
75 0x0000, /* DAC Limit Control 2 */
76 0,
77 0,
78 0,
79 0,
80 0,
81 0,
82 0x0038, /* ALC Control 1 */
83 0x000B, /* ALC Control 2 */
84 0x0032, /* ALC Control 3 */
85 0x0000, /* Noise Gate */
86 0x0041, /* PLLN */
87 0x000C, /* PLLK1 */
88 0x0093, /* PLLK2 */
89 0x00E9, /* PLLK3 */
90 0,
91 0,
92 0x0030, /* ALC Control 4 */
93 0,
94 0x0002, /* Input Control */
95 0x0050, /* PGA Gain */
96 0,
97 0x0002, /* ADC Boost Control */
98 0,
99 0x0002, /* Output Control */
100 0x0000, /* Speaker Mixer Control */
101 0,
102 0,
103 0,
104 0x0079, /* Speaker Volume */
105 0,
106 0x0000, /* Mono Mixer Control */
107};
108
109static const char *wm8940_companding[] = { "Off", "NC", "u-law", "A-law" };
110static const struct soc_enum wm8940_adc_companding_enum
111= SOC_ENUM_SINGLE(WM8940_COMPANDINGCTL, 1, 4, wm8940_companding);
112static const struct soc_enum wm8940_dac_companding_enum
113= SOC_ENUM_SINGLE(WM8940_COMPANDINGCTL, 3, 4, wm8940_companding);
114
115static const char *wm8940_alc_mode_text[] = {"ALC", "Limiter"};
116static const struct soc_enum wm8940_alc_mode_enum
117= SOC_ENUM_SINGLE(WM8940_ALC3, 8, 2, wm8940_alc_mode_text);
118
119static const char *wm8940_mic_bias_level_text[] = {"0.9", "0.65"};
120static const struct soc_enum wm8940_mic_bias_level_enum
121= SOC_ENUM_SINGLE(WM8940_INPUTCTL, 8, 2, wm8940_mic_bias_level_text);
122
123static const char *wm8940_filter_mode_text[] = {"Audio", "Application"};
124static const struct soc_enum wm8940_filter_mode_enum
125= SOC_ENUM_SINGLE(WM8940_ADC, 7, 2, wm8940_filter_mode_text);
126
127static DECLARE_TLV_DB_SCALE(wm8940_spk_vol_tlv, -5700, 100, 1);
128static DECLARE_TLV_DB_SCALE(wm8940_att_tlv, -1000, 1000, 0);
129static DECLARE_TLV_DB_SCALE(wm8940_pga_vol_tlv, -1200, 75, 0);
130static DECLARE_TLV_DB_SCALE(wm8940_alc_min_tlv, -1200, 600, 0);
131static DECLARE_TLV_DB_SCALE(wm8940_alc_max_tlv, 675, 600, 0);
132static DECLARE_TLV_DB_SCALE(wm8940_alc_tar_tlv, -2250, 50, 0);
133static DECLARE_TLV_DB_SCALE(wm8940_lim_boost_tlv, 0, 100, 0);
134static DECLARE_TLV_DB_SCALE(wm8940_lim_thresh_tlv, -600, 100, 0);
135static DECLARE_TLV_DB_SCALE(wm8940_adc_tlv, -12750, 50, 1);
136static DECLARE_TLV_DB_SCALE(wm8940_capture_boost_vol_tlv, 0, 2000, 0);
137
138static const struct snd_kcontrol_new wm8940_snd_controls[] = {
139 SOC_SINGLE("Digital Loopback Switch", WM8940_COMPANDINGCTL,
140 6, 1, 0),
141 SOC_ENUM("DAC Companding", wm8940_dac_companding_enum),
142 SOC_ENUM("ADC Companding", wm8940_adc_companding_enum),
143
144 SOC_ENUM("ALC Mode", wm8940_alc_mode_enum),
145 SOC_SINGLE("ALC Switch", WM8940_ALC1, 8, 1, 0),
146 SOC_SINGLE_TLV("ALC Capture Max Gain", WM8940_ALC1,
147 3, 7, 1, wm8940_alc_max_tlv),
148 SOC_SINGLE_TLV("ALC Capture Min Gain", WM8940_ALC1,
149 0, 7, 0, wm8940_alc_min_tlv),
150 SOC_SINGLE_TLV("ALC Capture Target", WM8940_ALC2,
151 0, 14, 0, wm8940_alc_tar_tlv),
152 SOC_SINGLE("ALC Capture Hold", WM8940_ALC2, 4, 10, 0),
153 SOC_SINGLE("ALC Capture Decay", WM8940_ALC3, 4, 10, 0),
154 SOC_SINGLE("ALC Capture Attach", WM8940_ALC3, 0, 10, 0),
155 SOC_SINGLE("ALC ZC Switch", WM8940_ALC4, 1, 1, 0),
156 SOC_SINGLE("ALC Capture Noise Gate Switch", WM8940_NOISEGATE,
157 3, 1, 0),
158 SOC_SINGLE("ALC Capture Noise Gate Threshold", WM8940_NOISEGATE,
159 0, 7, 0),
160
161 SOC_SINGLE("DAC Playback Limiter Switch", WM8940_DACLIM1, 8, 1, 0),
162 SOC_SINGLE("DAC Playback Limiter Attack", WM8940_DACLIM1, 0, 9, 0),
163 SOC_SINGLE("DAC Playback Limiter Decay", WM8940_DACLIM1, 4, 11, 0),
164 SOC_SINGLE_TLV("DAC Playback Limiter Threshold", WM8940_DACLIM2,
165 4, 9, 1, wm8940_lim_thresh_tlv),
166 SOC_SINGLE_TLV("DAC Playback Limiter Boost", WM8940_DACLIM2,
167 0, 12, 0, wm8940_lim_boost_tlv),
168
169 SOC_SINGLE("Capture PGA ZC Switch", WM8940_PGAGAIN, 7, 1, 0),
170 SOC_SINGLE_TLV("Capture PGA Volume", WM8940_PGAGAIN,
171 0, 63, 0, wm8940_pga_vol_tlv),
172 SOC_SINGLE_TLV("Digital Playback Volume", WM8940_DACVOL,
173 0, 255, 0, wm8940_adc_tlv),
174 SOC_SINGLE_TLV("Digital Capture Volume", WM8940_ADCVOL,
175 0, 255, 0, wm8940_adc_tlv),
176 SOC_ENUM("Mic Bias Level", wm8940_mic_bias_level_enum),
177 SOC_SINGLE_TLV("Capture Boost Volue", WM8940_ADCBOOST,
178 8, 1, 0, wm8940_capture_boost_vol_tlv),
179 SOC_SINGLE_TLV("Speaker Playback Volume", WM8940_SPKVOL,
180 0, 63, 0, wm8940_spk_vol_tlv),
181 SOC_SINGLE("Speaker Playback Switch", WM8940_SPKVOL, 6, 1, 1),
182
183 SOC_SINGLE_TLV("Speaker Mixer Line Bypass Volume", WM8940_SPKVOL,
184 8, 1, 1, wm8940_att_tlv),
185 SOC_SINGLE("Speaker Playback ZC Switch", WM8940_SPKVOL, 7, 1, 0),
186
187 SOC_SINGLE("Mono Out Switch", WM8940_MONOMIX, 6, 1, 1),
188 SOC_SINGLE_TLV("Mono Mixer Line Bypass Volume", WM8940_MONOMIX,
189 7, 1, 1, wm8940_att_tlv),
190
191 SOC_SINGLE("High Pass Filter Switch", WM8940_ADC, 8, 1, 0),
192 SOC_ENUM("High Pass Filter Mode", wm8940_filter_mode_enum),
193 SOC_SINGLE("High Pass Filter Cut Off", WM8940_ADC, 4, 7, 0),
194 SOC_SINGLE("ADC Inversion Switch", WM8940_ADC, 0, 1, 0),
195 SOC_SINGLE("DAC Inversion Switch", WM8940_DAC, 0, 1, 0),
196 SOC_SINGLE("DAC Auto Mute Switch", WM8940_DAC, 2, 1, 0),
197 SOC_SINGLE("ZC Timeout Clock Switch", WM8940_ADDCNTRL, 0, 1, 0),
198};
199
200static const struct snd_kcontrol_new wm8940_speaker_mixer_controls[] = {
201 SOC_DAPM_SINGLE("Line Bypass Switch", WM8940_SPKMIX, 1, 1, 0),
202 SOC_DAPM_SINGLE("Aux Playback Switch", WM8940_SPKMIX, 5, 1, 0),
203 SOC_DAPM_SINGLE("PCM Playback Switch", WM8940_SPKMIX, 0, 1, 0),
204};
205
206static const struct snd_kcontrol_new wm8940_mono_mixer_controls[] = {
207 SOC_DAPM_SINGLE("Line Bypass Switch", WM8940_MONOMIX, 1, 1, 0),
208 SOC_DAPM_SINGLE("Aux Playback Switch", WM8940_MONOMIX, 2, 1, 0),
209 SOC_DAPM_SINGLE("PCM Playback Switch", WM8940_MONOMIX, 0, 1, 0),
210};
211
212static DECLARE_TLV_DB_SCALE(wm8940_boost_vol_tlv, -1500, 300, 1);
213static const struct snd_kcontrol_new wm8940_input_boost_controls[] = {
214 SOC_DAPM_SINGLE("Mic PGA Switch", WM8940_PGAGAIN, 6, 1, 1),
215 SOC_DAPM_SINGLE_TLV("Aux Volume", WM8940_ADCBOOST,
216 0, 7, 0, wm8940_boost_vol_tlv),
217 SOC_DAPM_SINGLE_TLV("Mic Volume", WM8940_ADCBOOST,
218 4, 7, 0, wm8940_boost_vol_tlv),
219};
220
221static const struct snd_kcontrol_new wm8940_micpga_controls[] = {
222 SOC_DAPM_SINGLE("AUX Switch", WM8940_INPUTCTL, 2, 1, 0),
223 SOC_DAPM_SINGLE("MICP Switch", WM8940_INPUTCTL, 0, 1, 0),
224 SOC_DAPM_SINGLE("MICN Switch", WM8940_INPUTCTL, 1, 1, 0),
225};
226
227static const struct snd_soc_dapm_widget wm8940_dapm_widgets[] = {
228 SND_SOC_DAPM_MIXER("Speaker Mixer", WM8940_POWER3, 2, 0,
229 &wm8940_speaker_mixer_controls[0],
230 ARRAY_SIZE(wm8940_speaker_mixer_controls)),
231 SND_SOC_DAPM_MIXER("Mono Mixer", WM8940_POWER3, 3, 0,
232 &wm8940_mono_mixer_controls[0],
233 ARRAY_SIZE(wm8940_mono_mixer_controls)),
234 SND_SOC_DAPM_DAC("DAC", "HiFi Playback", WM8940_POWER3, 0, 0),
235
236 SND_SOC_DAPM_PGA("SpkN Out", WM8940_POWER3, 5, 0, NULL, 0),
237 SND_SOC_DAPM_PGA("SpkP Out", WM8940_POWER3, 6, 0, NULL, 0),
238 SND_SOC_DAPM_PGA("Mono Out", WM8940_POWER3, 7, 0, NULL, 0),
239 SND_SOC_DAPM_OUTPUT("MONOOUT"),
240 SND_SOC_DAPM_OUTPUT("SPKOUTP"),
241 SND_SOC_DAPM_OUTPUT("SPKOUTN"),
242
243 SND_SOC_DAPM_PGA("Aux Input", WM8940_POWER1, 6, 0, NULL, 0),
244 SND_SOC_DAPM_ADC("ADC", "HiFi Capture", WM8940_POWER2, 0, 0),
245 SND_SOC_DAPM_MIXER("Mic PGA", WM8940_POWER2, 2, 0,
246 &wm8940_micpga_controls[0],
247 ARRAY_SIZE(wm8940_micpga_controls)),
248 SND_SOC_DAPM_MIXER("Boost Mixer", WM8940_POWER2, 4, 0,
249 &wm8940_input_boost_controls[0],
250 ARRAY_SIZE(wm8940_input_boost_controls)),
251 SND_SOC_DAPM_MICBIAS("Mic Bias", WM8940_POWER1, 4, 0),
252
253 SND_SOC_DAPM_INPUT("MICN"),
254 SND_SOC_DAPM_INPUT("MICP"),
255 SND_SOC_DAPM_INPUT("AUX"),
256};
257
258static const struct snd_soc_dapm_route audio_map[] = {
259 /* Mono output mixer */
260 {"Mono Mixer", "PCM Playback Switch", "DAC"},
261 {"Mono Mixer", "Aux Playback Switch", "Aux Input"},
262 {"Mono Mixer", "Line Bypass Switch", "Boost Mixer"},
263
264 /* Speaker output mixer */
265 {"Speaker Mixer", "PCM Playback Switch", "DAC"},
266 {"Speaker Mixer", "Aux Playback Switch", "Aux Input"},
267 {"Speaker Mixer", "Line Bypass Switch", "Boost Mixer"},
268
269 /* Outputs */
270 {"Mono Out", NULL, "Mono Mixer"},
271 {"MONOOUT", NULL, "Mono Out"},
272 {"SpkN Out", NULL, "Speaker Mixer"},
273 {"SpkP Out", NULL, "Speaker Mixer"},
274 {"SPKOUTN", NULL, "SpkN Out"},
275 {"SPKOUTP", NULL, "SpkP Out"},
276
277 /* Microphone PGA */
278 {"Mic PGA", "MICN Switch", "MICN"},
279 {"Mic PGA", "MICP Switch", "MICP"},
280 {"Mic PGA", "AUX Switch", "AUX"},
281
282 /* Boost Mixer */
283 {"Boost Mixer", "Mic PGA Switch", "Mic PGA"},
284 {"Boost Mixer", "Mic Volume", "MICP"},
285 {"Boost Mixer", "Aux Volume", "Aux Input"},
286
287 {"ADC", NULL, "Boost Mixer"},
288};
289
290static int wm8940_add_widgets(struct snd_soc_codec *codec)
291{
292 int ret;
293
294 ret = snd_soc_dapm_new_controls(codec, wm8940_dapm_widgets,
295 ARRAY_SIZE(wm8940_dapm_widgets));
296 if (ret)
297 goto error_ret;
298 ret = snd_soc_dapm_add_routes(codec, audio_map, ARRAY_SIZE(audio_map));
299 if (ret)
300 goto error_ret;
301 ret = snd_soc_dapm_new_widgets(codec);
302
303error_ret:
304 return ret;
305}
306
307#define wm8940_reset(c) snd_soc_write(c, WM8940_SOFTRESET, 0);
308
309static int wm8940_set_dai_fmt(struct snd_soc_dai *codec_dai,
310 unsigned int fmt)
311{
312 struct snd_soc_codec *codec = codec_dai->codec;
313 u16 iface = snd_soc_read(codec, WM8940_IFACE) & 0xFE67;
314 u16 clk = snd_soc_read(codec, WM8940_CLOCK) & 0x1fe;
315
316 switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
317 case SND_SOC_DAIFMT_CBM_CFM:
318 clk |= 1;
319 break;
320 case SND_SOC_DAIFMT_CBS_CFS:
321 break;
322 default:
323 return -EINVAL;
324 }
325 snd_soc_write(codec, WM8940_CLOCK, clk);
326
327 switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
328 case SND_SOC_DAIFMT_I2S:
329 iface |= (2 << 3);
330 break;
331 case SND_SOC_DAIFMT_LEFT_J:
332 iface |= (1 << 3);
333 break;
334 case SND_SOC_DAIFMT_RIGHT_J:
335 break;
336 case SND_SOC_DAIFMT_DSP_A:
337 iface |= (3 << 3);
338 break;
339 case SND_SOC_DAIFMT_DSP_B:
340 iface |= (3 << 3) | (1 << 7);
341 break;
342 }
343
344 switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
345 case SND_SOC_DAIFMT_NB_NF:
346 break;
347 case SND_SOC_DAIFMT_NB_IF:
348 iface |= (1 << 7);
349 break;
350 case SND_SOC_DAIFMT_IB_NF:
351 iface |= (1 << 8);
352 break;
353 case SND_SOC_DAIFMT_IB_IF:
354 iface |= (1 << 8) | (1 << 7);
355 break;
356 }
357
358 snd_soc_write(codec, WM8940_IFACE, iface);
359
360 return 0;
361}
362
363static int wm8940_i2s_hw_params(struct snd_pcm_substream *substream,
364 struct snd_pcm_hw_params *params,
365 struct snd_soc_dai *dai)
366{
367 struct snd_soc_pcm_runtime *rtd = substream->private_data;
368 struct snd_soc_device *socdev = rtd->socdev;
369 struct snd_soc_codec *codec = socdev->card->codec;
370 u16 iface = snd_soc_read(codec, WM8940_IFACE) & 0xFD9F;
371 u16 addcntrl = snd_soc_read(codec, WM8940_ADDCNTRL) & 0xFFF1;
372 u16 companding = snd_soc_read(codec,
373 WM8940_COMPANDINGCTL) & 0xFFDF;
374 int ret;
375
376 /* LoutR control */
377 if (substream->stream == SNDRV_PCM_STREAM_CAPTURE
378 && params_channels(params) == 2)
379 iface |= (1 << 9);
380
381 switch (params_rate(params)) {
382 case SNDRV_PCM_RATE_8000:
383 addcntrl |= (0x5 << 1);
384 break;
385 case SNDRV_PCM_RATE_11025:
386 addcntrl |= (0x4 << 1);
387 break;
388 case SNDRV_PCM_RATE_16000:
389 addcntrl |= (0x3 << 1);
390 break;
391 case SNDRV_PCM_RATE_22050:
392 addcntrl |= (0x2 << 1);
393 break;
394 case SNDRV_PCM_RATE_32000:
395 addcntrl |= (0x1 << 1);
396 break;
397 case SNDRV_PCM_RATE_44100:
398 case SNDRV_PCM_RATE_48000:
399 break;
400 }
401 ret = snd_soc_write(codec, WM8940_ADDCNTRL, addcntrl);
402 if (ret)
403 goto error_ret;
404
405 switch (params_format(params)) {
406 case SNDRV_PCM_FORMAT_S8:
407 companding = companding | (1 << 5);
408 break;
409 case SNDRV_PCM_FORMAT_S16_LE:
410 break;
411 case SNDRV_PCM_FORMAT_S20_3LE:
412 iface |= (1 << 5);
413 break;
414 case SNDRV_PCM_FORMAT_S24_LE:
415 iface |= (2 << 5);
416 break;
417 case SNDRV_PCM_FORMAT_S32_LE:
418 iface |= (3 << 5);
419 break;
420 }
421 ret = snd_soc_write(codec, WM8940_COMPANDINGCTL, companding);
422 if (ret)
423 goto error_ret;
424 ret = snd_soc_write(codec, WM8940_IFACE, iface);
425
426error_ret:
427 return ret;
428}
429
430static int wm8940_mute(struct snd_soc_dai *dai, int mute)
431{
432 struct snd_soc_codec *codec = dai->codec;
433 u16 mute_reg = snd_soc_read(codec, WM8940_DAC) & 0xffbf;
434
435 if (mute)
436 mute_reg |= 0x40;
437
438 return snd_soc_write(codec, WM8940_DAC, mute_reg);
439}
440
441static int wm8940_set_bias_level(struct snd_soc_codec *codec,
442 enum snd_soc_bias_level level)
443{
444 u16 val;
445 u16 pwr_reg = snd_soc_read(codec, WM8940_POWER1) & 0x1F0;
446 int ret = 0;
447
448 switch (level) {
449 case SND_SOC_BIAS_ON:
450 /* ensure bufioen and biasen */
451 pwr_reg |= (1 << 2) | (1 << 3);
452 /* Enable thermal shutdown */
453 val = snd_soc_read(codec, WM8940_OUTPUTCTL);
454 ret = snd_soc_write(codec, WM8940_OUTPUTCTL, val | 0x2);
455 if (ret)
456 break;
457 /* set vmid to 75k */
458 ret = snd_soc_write(codec, WM8940_POWER1, pwr_reg | 0x1);
459 break;
460 case SND_SOC_BIAS_PREPARE:
461 /* ensure bufioen and biasen */
462 pwr_reg |= (1 << 2) | (1 << 3);
463 ret = snd_soc_write(codec, WM8940_POWER1, pwr_reg | 0x1);
464 break;
465 case SND_SOC_BIAS_STANDBY:
466 /* ensure bufioen and biasen */
467 pwr_reg |= (1 << 2) | (1 << 3);
468 /* set vmid to 300k for standby */
469 ret = snd_soc_write(codec, WM8940_POWER1, pwr_reg | 0x2);
470 break;
471 case SND_SOC_BIAS_OFF:
472 ret = snd_soc_write(codec, WM8940_POWER1, pwr_reg);
473 break;
474 }
475
476 return ret;
477}
478
479struct pll_ {
480 unsigned int pre_scale:2;
481 unsigned int n:4;
482 unsigned int k;
483};
484
485static struct pll_ pll_div;
486
487/* The size in bits of the pll divide multiplied by 10
488 * to allow rounding later */
489#define FIXED_PLL_SIZE ((1 << 24) * 10)
490static void pll_factors(unsigned int target, unsigned int source)
491{
492 unsigned long long Kpart;
493 unsigned int K, Ndiv, Nmod;
494 /* The left shift ist to avoid accuracy loss when right shifting */
495 Ndiv = target / source;
496
497 if (Ndiv > 12) {
498 source <<= 1;
499 /* Multiply by 2 */
500 pll_div.pre_scale = 0;
501 Ndiv = target / source;
502 } else if (Ndiv < 3) {
503 source >>= 2;
504 /* Divide by 4 */
505 pll_div.pre_scale = 3;
506 Ndiv = target / source;
507 } else if (Ndiv < 6) {
508 source >>= 1;
509 /* divide by 2 */
510 pll_div.pre_scale = 2;
511 Ndiv = target / source;
512 } else
513 pll_div.pre_scale = 1;
514
515 if ((Ndiv < 6) || (Ndiv > 12))
516 printk(KERN_WARNING
517 "WM8940 N value %d outwith recommended range!d\n",
518 Ndiv);
519
520 pll_div.n = Ndiv;
521 Nmod = target % source;
522 Kpart = FIXED_PLL_SIZE * (long long)Nmod;
523
524 do_div(Kpart, source);
525
526 K = Kpart & 0xFFFFFFFF;
527
528 /* Check if we need to round */
529 if ((K % 10) >= 5)
530 K += 5;
531
532 /* Move down to proper range now rounding is done */
533 K /= 10;
534
535 pll_div.k = K;
536}
537
538/* Untested at the moment */
539static int wm8940_set_dai_pll(struct snd_soc_dai *codec_dai,
540 int pll_id, unsigned int freq_in, unsigned int freq_out)
541{
542 struct snd_soc_codec *codec = codec_dai->codec;
543 u16 reg;
544
545 /* Turn off PLL */
546 reg = snd_soc_read(codec, WM8940_POWER1);
547 snd_soc_write(codec, WM8940_POWER1, reg & 0x1df);
548
549 if (freq_in == 0 || freq_out == 0) {
550 /* Clock CODEC directly from MCLK */
551 reg = snd_soc_read(codec, WM8940_CLOCK);
552 snd_soc_write(codec, WM8940_CLOCK, reg & 0x0ff);
553 /* Pll power down */
554 snd_soc_write(codec, WM8940_PLLN, (1 << 7));
555 return 0;
556 }
557
558 /* Pll is followed by a frequency divide by 4 */
559 pll_factors(freq_out*4, freq_in);
560 if (pll_div.k)
561 snd_soc_write(codec, WM8940_PLLN,
562 (pll_div.pre_scale << 4) | pll_div.n | (1 << 6));
563 else /* No factional component */
564 snd_soc_write(codec, WM8940_PLLN,
565 (pll_div.pre_scale << 4) | pll_div.n);
566 snd_soc_write(codec, WM8940_PLLK1, pll_div.k >> 18);
567 snd_soc_write(codec, WM8940_PLLK2, (pll_div.k >> 9) & 0x1ff);
568 snd_soc_write(codec, WM8940_PLLK3, pll_div.k & 0x1ff);
569 /* Enable the PLL */
570 reg = snd_soc_read(codec, WM8940_POWER1);
571 snd_soc_write(codec, WM8940_POWER1, reg | 0x020);
572
573 /* Run CODEC from PLL instead of MCLK */
574 reg = snd_soc_read(codec, WM8940_CLOCK);
575 snd_soc_write(codec, WM8940_CLOCK, reg | 0x100);
576
577 return 0;
578}
579
580static int wm8940_set_dai_sysclk(struct snd_soc_dai *codec_dai,
581 int clk_id, unsigned int freq, int dir)
582{
583 struct snd_soc_codec *codec = codec_dai->codec;
584 struct wm8940_priv *wm8940 = codec->private_data;
585
586 switch (freq) {
587 case 11289600:
588 case 12000000:
589 case 12288000:
590 case 16934400:
591 case 18432000:
592 wm8940->sysclk = freq;
593 return 0;
594 }
595 return -EINVAL;
596}
597
598static int wm8940_set_dai_clkdiv(struct snd_soc_dai *codec_dai,
599 int div_id, int div)
600{
601 struct snd_soc_codec *codec = codec_dai->codec;
602 u16 reg;
603 int ret = 0;
604
605 switch (div_id) {
606 case WM8940_BCLKDIV:
607 reg = snd_soc_read(codec, WM8940_CLOCK) & 0xFFEF3;
608 ret = snd_soc_write(codec, WM8940_CLOCK, reg | (div << 2));
609 break;
610 case WM8940_MCLKDIV:
611 reg = snd_soc_read(codec, WM8940_CLOCK) & 0xFF1F;
612 ret = snd_soc_write(codec, WM8940_CLOCK, reg | (div << 5));
613 break;
614 case WM8940_OPCLKDIV:
615 reg = snd_soc_read(codec, WM8940_ADDCNTRL) & 0xFFCF;
616 ret = snd_soc_write(codec, WM8940_ADDCNTRL, reg | (div << 4));
617 break;
618 }
619 return ret;
620}
621
622#define WM8940_RATES SNDRV_PCM_RATE_8000_48000
623
624#define WM8940_FORMATS (SNDRV_PCM_FMTBIT_S8 | \
625 SNDRV_PCM_FMTBIT_S16_LE | \
626 SNDRV_PCM_FMTBIT_S20_3LE | \
627 SNDRV_PCM_FMTBIT_S24_LE | \
628 SNDRV_PCM_FMTBIT_S32_LE)
629
630static struct snd_soc_dai_ops wm8940_dai_ops = {
631 .hw_params = wm8940_i2s_hw_params,
632 .set_sysclk = wm8940_set_dai_sysclk,
633 .digital_mute = wm8940_mute,
634 .set_fmt = wm8940_set_dai_fmt,
635 .set_clkdiv = wm8940_set_dai_clkdiv,
636 .set_pll = wm8940_set_dai_pll,
637};
638
639struct snd_soc_dai wm8940_dai = {
640 .name = "WM8940",
641 .playback = {
642 .stream_name = "Playback",
643 .channels_min = 1,
644 .channels_max = 2,
645 .rates = WM8940_RATES,
646 .formats = WM8940_FORMATS,
647 },
648 .capture = {
649 .stream_name = "Capture",
650 .channels_min = 1,
651 .channels_max = 2,
652 .rates = WM8940_RATES,
653 .formats = WM8940_FORMATS,
654 },
655 .ops = &wm8940_dai_ops,
656 .symmetric_rates = 1,
657};
658EXPORT_SYMBOL_GPL(wm8940_dai);
659
660static int wm8940_suspend(struct platform_device *pdev, pm_message_t state)
661{
662 struct snd_soc_device *socdev = platform_get_drvdata(pdev);
663 struct snd_soc_codec *codec = socdev->card->codec;
664
665 return wm8940_set_bias_level(codec, SND_SOC_BIAS_OFF);
666}
667
668static int wm8940_resume(struct platform_device *pdev)
669{
670 struct snd_soc_device *socdev = platform_get_drvdata(pdev);
671 struct snd_soc_codec *codec = socdev->card->codec;
672 int i;
673 int ret;
674 u8 data[3];
675 u16 *cache = codec->reg_cache;
676
677 /* Sync reg_cache with the hardware
678 * Could use auto incremented writes to speed this up
679 */
680 for (i = 0; i < ARRAY_SIZE(wm8940_reg_defaults); i++) {
681 data[0] = i;
682 data[1] = (cache[i] & 0xFF00) >> 8;
683 data[2] = cache[i] & 0x00FF;
684 ret = codec->hw_write(codec->control_data, data, 3);
685 if (ret < 0)
686 goto error_ret;
687 else if (ret != 3) {
688 ret = -EIO;
689 goto error_ret;
690 }
691 }
692 ret = wm8940_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
693 if (ret)
694 goto error_ret;
695 ret = wm8940_set_bias_level(codec, codec->suspend_bias_level);
696
697error_ret:
698 return ret;
699}
700
701static struct snd_soc_codec *wm8940_codec;
702
703static int wm8940_probe(struct platform_device *pdev)
704{
705 struct snd_soc_device *socdev = platform_get_drvdata(pdev);
706 struct snd_soc_codec *codec;
707
708 int ret = 0;
709
710 if (wm8940_codec == NULL) {
711 dev_err(&pdev->dev, "Codec device not registered\n");
712 return -ENODEV;
713 }
714
715 socdev->card->codec = wm8940_codec;
716 codec = wm8940_codec;
717
718 mutex_init(&codec->mutex);
719 /* register pcms */
720 ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1);
721 if (ret < 0) {
722 dev_err(codec->dev, "failed to create pcms: %d\n", ret);
723 goto pcm_err;
724 }
725
726 ret = snd_soc_add_controls(codec, wm8940_snd_controls,
727 ARRAY_SIZE(wm8940_snd_controls));
728 if (ret)
729 goto error_free_pcms;
730 ret = wm8940_add_widgets(codec);
731 if (ret)
732 goto error_free_pcms;
733
734 ret = snd_soc_init_card(socdev);
735 if (ret < 0) {
736 dev_err(codec->dev, "failed to register card: %d\n", ret);
737 goto error_free_pcms;
738 }
739
740 return ret;
741
742error_free_pcms:
743 snd_soc_free_pcms(socdev);
744 snd_soc_dapm_free(socdev);
745pcm_err:
746 return ret;
747}
748
749static int wm8940_remove(struct platform_device *pdev)
750{
751 struct snd_soc_device *socdev = platform_get_drvdata(pdev);
752
753 snd_soc_free_pcms(socdev);
754 snd_soc_dapm_free(socdev);
755
756 return 0;
757}
758
759struct snd_soc_codec_device soc_codec_dev_wm8940 = {
760 .probe = wm8940_probe,
761 .remove = wm8940_remove,
762 .suspend = wm8940_suspend,
763 .resume = wm8940_resume,
764};
765EXPORT_SYMBOL_GPL(soc_codec_dev_wm8940);
766
767static int wm8940_register(struct wm8940_priv *wm8940,
768 enum snd_soc_control_type control)
769{
770 struct wm8940_setup_data *pdata = wm8940->codec.dev->platform_data;
771 struct snd_soc_codec *codec = &wm8940->codec;
772 int ret;
773 u16 reg;
774 if (wm8940_codec) {
775 dev_err(codec->dev, "Another WM8940 is registered\n");
776 return -EINVAL;
777 }
778
779 INIT_LIST_HEAD(&codec->dapm_widgets);
780 INIT_LIST_HEAD(&codec->dapm_paths);
781
782 codec->private_data = wm8940;
783 codec->name = "WM8940";
784 codec->owner = THIS_MODULE;
785 codec->bias_level = SND_SOC_BIAS_OFF;
786 codec->set_bias_level = wm8940_set_bias_level;
787 codec->dai = &wm8940_dai;
788 codec->num_dai = 1;
789 codec->reg_cache_size = ARRAY_SIZE(wm8940_reg_defaults);
790 codec->reg_cache = &wm8940->reg_cache;
791
792 ret = snd_soc_codec_set_cache_io(codec, 8, 16, control);
793 if (ret == 0) {
794 dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret);
795 return ret;
796 }
797
798 memcpy(codec->reg_cache, wm8940_reg_defaults,
799 sizeof(wm8940_reg_defaults));
800
801 ret = wm8940_reset(codec);
802 if (ret < 0) {
803 dev_err(codec->dev, "Failed to issue reset\n");
804 return ret;
805 }
806
807 wm8940_dai.dev = codec->dev;
808
809 wm8940_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
810
811 ret = snd_soc_write(codec, WM8940_POWER1, 0x180);
812 if (ret < 0)
813 return ret;
814
815 if (!pdata)
816 dev_warn(codec->dev, "No platform data supplied\n");
817 else {
818 reg = snd_soc_read(codec, WM8940_OUTPUTCTL);
819 ret = snd_soc_write(codec, WM8940_OUTPUTCTL, reg | pdata->vroi);
820 if (ret < 0)
821 return ret;
822 }
823
824
825 wm8940_codec = codec;
826
827 ret = snd_soc_register_codec(codec);
828 if (ret) {
829 dev_err(codec->dev, "Failed to register codec: %d\n", ret);
830 return ret;
831 }
832
833 ret = snd_soc_register_dai(&wm8940_dai);
834 if (ret) {
835 dev_err(codec->dev, "Failed to register DAI: %d\n", ret);
836 snd_soc_unregister_codec(codec);
837 return ret;
838 }
839
840 return 0;
841}
842
843static void wm8940_unregister(struct wm8940_priv *wm8940)
844{
845 wm8940_set_bias_level(&wm8940->codec, SND_SOC_BIAS_OFF);
846 snd_soc_unregister_dai(&wm8940_dai);
847 snd_soc_unregister_codec(&wm8940->codec);
848 kfree(wm8940);
849 wm8940_codec = NULL;
850}
851
852static int wm8940_i2c_probe(struct i2c_client *i2c,
853 const struct i2c_device_id *id)
854{
855 struct wm8940_priv *wm8940;
856 struct snd_soc_codec *codec;
857
858 wm8940 = kzalloc(sizeof *wm8940, GFP_KERNEL);
859 if (wm8940 == NULL)
860 return -ENOMEM;
861
862 codec = &wm8940->codec;
863 codec->hw_write = (hw_write_t)i2c_master_send;
864 i2c_set_clientdata(i2c, wm8940);
865 codec->control_data = i2c;
866 codec->dev = &i2c->dev;
867
868 return wm8940_register(wm8940, SND_SOC_I2C);
869}
870
871static int __devexit wm8940_i2c_remove(struct i2c_client *client)
872{
873 struct wm8940_priv *wm8940 = i2c_get_clientdata(client);
874
875 wm8940_unregister(wm8940);
876
877 return 0;
878}
879
880#ifdef CONFIG_PM
881static int wm8940_i2c_suspend(struct i2c_client *client, pm_message_t msg)
882{
883 return snd_soc_suspend_device(&client->dev);
884}
885
886static int wm8940_i2c_resume(struct i2c_client *client)
887{
888 return snd_soc_resume_device(&client->dev);
889}
890#else
891#define wm8940_i2c_suspend NULL
892#define wm8940_i2c_resume NULL
893#endif
894
895static const struct i2c_device_id wm8940_i2c_id[] = {
896 { "wm8940", 0 },
897 { }
898};
899MODULE_DEVICE_TABLE(i2c, wm8940_i2c_id);
900
901static struct i2c_driver wm8940_i2c_driver = {
902 .driver = {
903 .name = "WM8940 I2C Codec",
904 .owner = THIS_MODULE,
905 },
906 .probe = wm8940_i2c_probe,
907 .remove = __devexit_p(wm8940_i2c_remove),
908 .suspend = wm8940_i2c_suspend,
909 .resume = wm8940_i2c_resume,
910 .id_table = wm8940_i2c_id,
911};
912
913static int __init wm8940_modinit(void)
914{
915 int ret;
916
917 ret = i2c_add_driver(&wm8940_i2c_driver);
918 if (ret)
919 printk(KERN_ERR "Failed to register WM8940 I2C driver: %d\n",
920 ret);
921 return ret;
922}
923module_init(wm8940_modinit);
924
925static void __exit wm8940_exit(void)
926{
927 i2c_del_driver(&wm8940_i2c_driver);
928}
929module_exit(wm8940_exit);
930
931MODULE_DESCRIPTION("ASoC WM8940 driver");
932MODULE_AUTHOR("Jonathan Cameron");
933MODULE_LICENSE("GPL");
diff --git a/sound/soc/codecs/wm8940.h b/sound/soc/codecs/wm8940.h
new file mode 100644
index 000000000000..8410eed3ef84
--- /dev/null
+++ b/sound/soc/codecs/wm8940.h
@@ -0,0 +1,104 @@
1/*
2 * wm8940.h -- WM8940 Soc Audio driver
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License version 2 as
6 * published by the Free Software Foundation.
7 */
8
9#ifndef _WM8940_H
10#define _WM8940_H
11
12struct wm8940_setup_data {
13 /* Vref to analogue output resistance */
14#define WM8940_VROI_1K 0
15#define WM8940_VROI_30K 1
16 unsigned int vroi:1;
17};
18extern struct snd_soc_dai wm8940_dai;
19extern struct snd_soc_codec_device soc_codec_dev_wm8940;
20
21/* WM8940 register space */
22#define WM8940_SOFTRESET 0x00
23#define WM8940_POWER1 0x01
24#define WM8940_POWER2 0x02
25#define WM8940_POWER3 0x03
26#define WM8940_IFACE 0x04
27#define WM8940_COMPANDINGCTL 0x05
28#define WM8940_CLOCK 0x06
29#define WM8940_ADDCNTRL 0x07
30#define WM8940_GPIO 0x08
31#define WM8940_CTLINT 0x09
32#define WM8940_DAC 0x0A
33#define WM8940_DACVOL 0x0B
34
35#define WM8940_ADC 0x0E
36#define WM8940_ADCVOL 0x0F
37#define WM8940_NOTCH1 0x10
38#define WM8940_NOTCH2 0x11
39#define WM8940_NOTCH3 0x12
40#define WM8940_NOTCH4 0x13
41#define WM8940_NOTCH5 0x14
42#define WM8940_NOTCH6 0x15
43#define WM8940_NOTCH7 0x16
44#define WM8940_NOTCH8 0x17
45#define WM8940_DACLIM1 0x18
46#define WM8940_DACLIM2 0x19
47
48#define WM8940_ALC1 0x20
49#define WM8940_ALC2 0x21
50#define WM8940_ALC3 0x22
51#define WM8940_NOISEGATE 0x23
52#define WM8940_PLLN 0x24
53#define WM8940_PLLK1 0x25
54#define WM8940_PLLK2 0x26
55#define WM8940_PLLK3 0x27
56
57#define WM8940_ALC4 0x2A
58
59#define WM8940_INPUTCTL 0x2C
60#define WM8940_PGAGAIN 0x2D
61
62#define WM8940_ADCBOOST 0x2F
63
64#define WM8940_OUTPUTCTL 0x31
65#define WM8940_SPKMIX 0x32
66
67#define WM8940_SPKVOL 0x36
68
69#define WM8940_MONOMIX 0x38
70
71#define WM8940_CACHEREGNUM 0x57
72
73
74/* Clock divider Id's */
75#define WM8940_BCLKDIV 0
76#define WM8940_MCLKDIV 1
77#define WM8940_OPCLKDIV 2
78
79/* MCLK clock dividers */
80#define WM8940_MCLKDIV_1 0
81#define WM8940_MCLKDIV_1_5 1
82#define WM8940_MCLKDIV_2 2
83#define WM8940_MCLKDIV_3 3
84#define WM8940_MCLKDIV_4 4
85#define WM8940_MCLKDIV_6 5
86#define WM8940_MCLKDIV_8 6
87#define WM8940_MCLKDIV_12 7
88
89/* BCLK clock dividers */
90#define WM8940_BCLKDIV_1 0
91#define WM8940_BCLKDIV_2 1
92#define WM8940_BCLKDIV_4 2
93#define WM8940_BCLKDIV_8 3
94#define WM8940_BCLKDIV_16 4
95#define WM8940_BCLKDIV_32 5
96
97/* PLL Out Dividers */
98#define WM8940_OPCLKDIV_1 0
99#define WM8940_OPCLKDIV_2 1
100#define WM8940_OPCLKDIV_3 2
101#define WM8940_OPCLKDIV_4 3
102
103#endif /* _WM8940_H */
104
diff --git a/sound/soc/codecs/wm8960.c b/sound/soc/codecs/wm8960.c
new file mode 100644
index 000000000000..f59703be61c8
--- /dev/null
+++ b/sound/soc/codecs/wm8960.c
@@ -0,0 +1,942 @@
1/*
2 * wm8960.c -- WM8960 ALSA SoC Audio driver
3 *
4 * Author: Liam Girdwood
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License version 2 as
8 * published by the Free Software Foundation.
9 */
10
11#include <linux/module.h>
12#include <linux/moduleparam.h>
13#include <linux/init.h>
14#include <linux/delay.h>
15#include <linux/pm.h>
16#include <linux/i2c.h>
17#include <linux/platform_device.h>
18#include <sound/core.h>
19#include <sound/pcm.h>
20#include <sound/pcm_params.h>
21#include <sound/soc.h>
22#include <sound/soc-dapm.h>
23#include <sound/initval.h>
24#include <sound/tlv.h>
25
26#include "wm8960.h"
27
28#define AUDIO_NAME "wm8960"
29
30struct snd_soc_codec_device soc_codec_dev_wm8960;
31
32/* R25 - Power 1 */
33#define WM8960_VREF 0x40
34
35/* R28 - Anti-pop 1 */
36#define WM8960_POBCTRL 0x80
37#define WM8960_BUFDCOPEN 0x10
38#define WM8960_BUFIOEN 0x08
39#define WM8960_SOFT_ST 0x04
40#define WM8960_HPSTBY 0x01
41
42/* R29 - Anti-pop 2 */
43#define WM8960_DISOP 0x40
44
45/*
46 * wm8960 register cache
47 * We can't read the WM8960 register space when we are
48 * using 2 wire for device control, so we cache them instead.
49 */
50static const u16 wm8960_reg[WM8960_CACHEREGNUM] = {
51 0x0097, 0x0097, 0x0000, 0x0000,
52 0x0000, 0x0008, 0x0000, 0x000a,
53 0x01c0, 0x0000, 0x00ff, 0x00ff,
54 0x0000, 0x0000, 0x0000, 0x0000,
55 0x0000, 0x007b, 0x0100, 0x0032,
56 0x0000, 0x00c3, 0x00c3, 0x01c0,
57 0x0000, 0x0000, 0x0000, 0x0000,
58 0x0000, 0x0000, 0x0000, 0x0000,
59 0x0100, 0x0100, 0x0050, 0x0050,
60 0x0050, 0x0050, 0x0000, 0x0000,
61 0x0000, 0x0000, 0x0040, 0x0000,
62 0x0000, 0x0050, 0x0050, 0x0000,
63 0x0002, 0x0037, 0x004d, 0x0080,
64 0x0008, 0x0031, 0x0026, 0x00e9,
65};
66
67struct wm8960_priv {
68 u16 reg_cache[WM8960_CACHEREGNUM];
69 struct snd_soc_codec codec;
70};
71
72#define wm8960_reset(c) snd_soc_write(c, WM8960_RESET, 0)
73
74/* enumerated controls */
75static const char *wm8960_deemph[] = {"None", "32Khz", "44.1Khz", "48Khz"};
76static const char *wm8960_polarity[] = {"No Inversion", "Left Inverted",
77 "Right Inverted", "Stereo Inversion"};
78static const char *wm8960_3d_upper_cutoff[] = {"High", "Low"};
79static const char *wm8960_3d_lower_cutoff[] = {"Low", "High"};
80static const char *wm8960_alcfunc[] = {"Off", "Right", "Left", "Stereo"};
81static const char *wm8960_alcmode[] = {"ALC", "Limiter"};
82
83static const struct soc_enum wm8960_enum[] = {
84 SOC_ENUM_SINGLE(WM8960_DACCTL1, 1, 4, wm8960_deemph),
85 SOC_ENUM_SINGLE(WM8960_DACCTL1, 5, 4, wm8960_polarity),
86 SOC_ENUM_SINGLE(WM8960_DACCTL2, 5, 4, wm8960_polarity),
87 SOC_ENUM_SINGLE(WM8960_3D, 6, 2, wm8960_3d_upper_cutoff),
88 SOC_ENUM_SINGLE(WM8960_3D, 5, 2, wm8960_3d_lower_cutoff),
89 SOC_ENUM_SINGLE(WM8960_ALC1, 7, 4, wm8960_alcfunc),
90 SOC_ENUM_SINGLE(WM8960_ALC3, 8, 2, wm8960_alcmode),
91};
92
93static const DECLARE_TLV_DB_SCALE(adc_tlv, -9700, 50, 0);
94static const DECLARE_TLV_DB_SCALE(dac_tlv, -12700, 50, 1);
95static const DECLARE_TLV_DB_SCALE(bypass_tlv, -2100, 300, 0);
96static const DECLARE_TLV_DB_SCALE(out_tlv, -12100, 100, 1);
97
98static const struct snd_kcontrol_new wm8960_snd_controls[] = {
99SOC_DOUBLE_R_TLV("Capture Volume", WM8960_LINVOL, WM8960_RINVOL,
100 0, 63, 0, adc_tlv),
101SOC_DOUBLE_R("Capture Volume ZC Switch", WM8960_LINVOL, WM8960_RINVOL,
102 6, 1, 0),
103SOC_DOUBLE_R("Capture Switch", WM8960_LINVOL, WM8960_RINVOL,
104 7, 1, 0),
105
106SOC_DOUBLE_R_TLV("Playback Volume", WM8960_LDAC, WM8960_RDAC,
107 0, 255, 0, dac_tlv),
108
109SOC_DOUBLE_R_TLV("Headphone Playback Volume", WM8960_LOUT1, WM8960_ROUT1,
110 0, 127, 0, out_tlv),
111SOC_DOUBLE_R("Headphone Playback ZC Switch", WM8960_LOUT1, WM8960_ROUT1,
112 7, 1, 0),
113
114SOC_DOUBLE_R_TLV("Speaker Playback Volume", WM8960_LOUT2, WM8960_ROUT2,
115 0, 127, 0, out_tlv),
116SOC_DOUBLE_R("Speaker Playback ZC Switch", WM8960_LOUT2, WM8960_ROUT2,
117 7, 1, 0),
118SOC_SINGLE("Speaker DC Volume", WM8960_CLASSD3, 3, 5, 0),
119SOC_SINGLE("Speaker AC Volume", WM8960_CLASSD3, 0, 5, 0),
120
121SOC_SINGLE("PCM Playback -6dB Switch", WM8960_DACCTL1, 7, 1, 0),
122SOC_ENUM("ADC Polarity", wm8960_enum[1]),
123SOC_ENUM("Playback De-emphasis", wm8960_enum[0]),
124SOC_SINGLE("ADC High Pass Filter Switch", WM8960_DACCTL1, 0, 1, 0),
125
126SOC_ENUM("DAC Polarity", wm8960_enum[2]),
127
128SOC_ENUM("3D Filter Upper Cut-Off", wm8960_enum[3]),
129SOC_ENUM("3D Filter Lower Cut-Off", wm8960_enum[4]),
130SOC_SINGLE("3D Volume", WM8960_3D, 1, 15, 0),
131SOC_SINGLE("3D Switch", WM8960_3D, 0, 1, 0),
132
133SOC_ENUM("ALC Function", wm8960_enum[5]),
134SOC_SINGLE("ALC Max Gain", WM8960_ALC1, 4, 7, 0),
135SOC_SINGLE("ALC Target", WM8960_ALC1, 0, 15, 1),
136SOC_SINGLE("ALC Min Gain", WM8960_ALC2, 4, 7, 0),
137SOC_SINGLE("ALC Hold Time", WM8960_ALC2, 0, 15, 0),
138SOC_ENUM("ALC Mode", wm8960_enum[6]),
139SOC_SINGLE("ALC Decay", WM8960_ALC3, 4, 15, 0),
140SOC_SINGLE("ALC Attack", WM8960_ALC3, 0, 15, 0),
141
142SOC_SINGLE("Noise Gate Threshold", WM8960_NOISEG, 3, 31, 0),
143SOC_SINGLE("Noise Gate Switch", WM8960_NOISEG, 0, 1, 0),
144
145SOC_DOUBLE_R("ADC PCM Capture Volume", WM8960_LINPATH, WM8960_RINPATH,
146 0, 127, 0),
147
148SOC_SINGLE_TLV("Left Output Mixer Boost Bypass Volume",
149 WM8960_BYPASS1, 4, 7, 1, bypass_tlv),
150SOC_SINGLE_TLV("Left Output Mixer LINPUT3 Volume",
151 WM8960_LOUTMIX, 4, 7, 1, bypass_tlv),
152SOC_SINGLE_TLV("Right Output Mixer Boost Bypass Volume",
153 WM8960_BYPASS2, 4, 7, 1, bypass_tlv),
154SOC_SINGLE_TLV("Right Output Mixer RINPUT3 Volume",
155 WM8960_ROUTMIX, 4, 7, 1, bypass_tlv),
156};
157
158static const struct snd_kcontrol_new wm8960_lin_boost[] = {
159SOC_DAPM_SINGLE("LINPUT2 Switch", WM8960_LINPATH, 6, 1, 0),
160SOC_DAPM_SINGLE("LINPUT3 Switch", WM8960_LINPATH, 7, 1, 0),
161SOC_DAPM_SINGLE("LINPUT1 Switch", WM8960_LINPATH, 8, 1, 0),
162};
163
164static const struct snd_kcontrol_new wm8960_lin[] = {
165SOC_DAPM_SINGLE("Boost Switch", WM8960_LINPATH, 3, 1, 0),
166};
167
168static const struct snd_kcontrol_new wm8960_rin_boost[] = {
169SOC_DAPM_SINGLE("RINPUT2 Switch", WM8960_RINPATH, 6, 1, 0),
170SOC_DAPM_SINGLE("RINPUT3 Switch", WM8960_RINPATH, 7, 1, 0),
171SOC_DAPM_SINGLE("RINPUT1 Switch", WM8960_RINPATH, 8, 1, 0),
172};
173
174static const struct snd_kcontrol_new wm8960_rin[] = {
175SOC_DAPM_SINGLE("Boost Switch", WM8960_RINPATH, 3, 1, 0),
176};
177
178static const struct snd_kcontrol_new wm8960_loutput_mixer[] = {
179SOC_DAPM_SINGLE("PCM Playback Switch", WM8960_LOUTMIX, 8, 1, 0),
180SOC_DAPM_SINGLE("LINPUT3 Switch", WM8960_LOUTMIX, 7, 1, 0),
181SOC_DAPM_SINGLE("Boost Bypass Switch", WM8960_BYPASS1, 7, 1, 0),
182};
183
184static const struct snd_kcontrol_new wm8960_routput_mixer[] = {
185SOC_DAPM_SINGLE("PCM Playback Switch", WM8960_ROUTMIX, 8, 1, 0),
186SOC_DAPM_SINGLE("RINPUT3 Switch", WM8960_ROUTMIX, 7, 1, 0),
187SOC_DAPM_SINGLE("Boost Bypass Switch", WM8960_BYPASS2, 7, 1, 0),
188};
189
190static const struct snd_kcontrol_new wm8960_mono_out[] = {
191SOC_DAPM_SINGLE("Left Switch", WM8960_MONOMIX1, 7, 1, 0),
192SOC_DAPM_SINGLE("Right Switch", WM8960_MONOMIX2, 7, 1, 0),
193};
194
195static const struct snd_soc_dapm_widget wm8960_dapm_widgets[] = {
196SND_SOC_DAPM_INPUT("LINPUT1"),
197SND_SOC_DAPM_INPUT("RINPUT1"),
198SND_SOC_DAPM_INPUT("LINPUT2"),
199SND_SOC_DAPM_INPUT("RINPUT2"),
200SND_SOC_DAPM_INPUT("LINPUT3"),
201SND_SOC_DAPM_INPUT("RINPUT3"),
202
203SND_SOC_DAPM_MICBIAS("MICB", WM8960_POWER1, 1, 0),
204
205SND_SOC_DAPM_MIXER("Left Boost Mixer", WM8960_POWER1, 5, 0,
206 wm8960_lin_boost, ARRAY_SIZE(wm8960_lin_boost)),
207SND_SOC_DAPM_MIXER("Right Boost Mixer", WM8960_POWER1, 4, 0,
208 wm8960_rin_boost, ARRAY_SIZE(wm8960_rin_boost)),
209
210SND_SOC_DAPM_MIXER("Left Input Mixer", WM8960_POWER3, 5, 0,
211 wm8960_lin, ARRAY_SIZE(wm8960_lin)),
212SND_SOC_DAPM_MIXER("Right Input Mixer", WM8960_POWER3, 4, 0,
213 wm8960_rin, ARRAY_SIZE(wm8960_rin)),
214
215SND_SOC_DAPM_ADC("Left ADC", "Capture", WM8960_POWER2, 3, 0),
216SND_SOC_DAPM_ADC("Right ADC", "Capture", WM8960_POWER2, 2, 0),
217
218SND_SOC_DAPM_DAC("Left DAC", "Playback", WM8960_POWER2, 8, 0),
219SND_SOC_DAPM_DAC("Right DAC", "Playback", WM8960_POWER2, 7, 0),
220
221SND_SOC_DAPM_MIXER("Left Output Mixer", WM8960_POWER3, 3, 0,
222 &wm8960_loutput_mixer[0],
223 ARRAY_SIZE(wm8960_loutput_mixer)),
224SND_SOC_DAPM_MIXER("Right Output Mixer", WM8960_POWER3, 2, 0,
225 &wm8960_routput_mixer[0],
226 ARRAY_SIZE(wm8960_routput_mixer)),
227
228SND_SOC_DAPM_MIXER("Mono Output Mixer", WM8960_POWER2, 1, 0,
229 &wm8960_mono_out[0],
230 ARRAY_SIZE(wm8960_mono_out)),
231
232SND_SOC_DAPM_PGA("LOUT1 PGA", WM8960_POWER2, 6, 0, NULL, 0),
233SND_SOC_DAPM_PGA("ROUT1 PGA", WM8960_POWER2, 5, 0, NULL, 0),
234
235SND_SOC_DAPM_PGA("Left Speaker PGA", WM8960_POWER2, 4, 0, NULL, 0),
236SND_SOC_DAPM_PGA("Right Speaker PGA", WM8960_POWER2, 3, 0, NULL, 0),
237
238SND_SOC_DAPM_PGA("Right Speaker Output", WM8960_CLASSD1, 7, 0, NULL, 0),
239SND_SOC_DAPM_PGA("Left Speaker Output", WM8960_CLASSD1, 6, 0, NULL, 0),
240
241SND_SOC_DAPM_OUTPUT("SPK_LP"),
242SND_SOC_DAPM_OUTPUT("SPK_LN"),
243SND_SOC_DAPM_OUTPUT("HP_L"),
244SND_SOC_DAPM_OUTPUT("HP_R"),
245SND_SOC_DAPM_OUTPUT("SPK_RP"),
246SND_SOC_DAPM_OUTPUT("SPK_RN"),
247SND_SOC_DAPM_OUTPUT("OUT3"),
248};
249
250static const struct snd_soc_dapm_route audio_paths[] = {
251 { "Left Boost Mixer", "LINPUT1 Switch", "LINPUT1" },
252 { "Left Boost Mixer", "LINPUT2 Switch", "LINPUT2" },
253 { "Left Boost Mixer", "LINPUT3 Switch", "LINPUT3" },
254
255 { "Left Input Mixer", "Boost Switch", "Left Boost Mixer", },
256 { "Left Input Mixer", NULL, "LINPUT1", }, /* Really Boost Switch */
257 { "Left Input Mixer", NULL, "LINPUT2" },
258 { "Left Input Mixer", NULL, "LINPUT3" },
259
260 { "Right Boost Mixer", "RINPUT1 Switch", "RINPUT1" },
261 { "Right Boost Mixer", "RINPUT2 Switch", "RINPUT2" },
262 { "Right Boost Mixer", "RINPUT3 Switch", "RINPUT3" },
263
264 { "Right Input Mixer", "Boost Switch", "Right Boost Mixer", },
265 { "Right Input Mixer", NULL, "RINPUT1", }, /* Really Boost Switch */
266 { "Right Input Mixer", NULL, "RINPUT2" },
267 { "Right Input Mixer", NULL, "LINPUT3" },
268
269 { "Left ADC", NULL, "Left Input Mixer" },
270 { "Right ADC", NULL, "Right Input Mixer" },
271
272 { "Left Output Mixer", "LINPUT3 Switch", "LINPUT3" },
273 { "Left Output Mixer", "Boost Bypass Switch", "Left Boost Mixer"} ,
274 { "Left Output Mixer", "PCM Playback Switch", "Left DAC" },
275
276 { "Right Output Mixer", "RINPUT3 Switch", "RINPUT3" },
277 { "Right Output Mixer", "Boost Bypass Switch", "Right Boost Mixer" } ,
278 { "Right Output Mixer", "PCM Playback Switch", "Right DAC" },
279
280 { "Mono Output Mixer", "Left Switch", "Left Output Mixer" },
281 { "Mono Output Mixer", "Right Switch", "Right Output Mixer" },
282
283 { "LOUT1 PGA", NULL, "Left Output Mixer" },
284 { "ROUT1 PGA", NULL, "Right Output Mixer" },
285
286 { "HP_L", NULL, "LOUT1 PGA" },
287 { "HP_R", NULL, "ROUT1 PGA" },
288
289 { "Left Speaker PGA", NULL, "Left Output Mixer" },
290 { "Right Speaker PGA", NULL, "Right Output Mixer" },
291
292 { "Left Speaker Output", NULL, "Left Speaker PGA" },
293 { "Right Speaker Output", NULL, "Right Speaker PGA" },
294
295 { "SPK_LN", NULL, "Left Speaker Output" },
296 { "SPK_LP", NULL, "Left Speaker Output" },
297 { "SPK_RN", NULL, "Right Speaker Output" },
298 { "SPK_RP", NULL, "Right Speaker Output" },
299
300 { "OUT3", NULL, "Mono Output Mixer", }
301};
302
303static int wm8960_add_widgets(struct snd_soc_codec *codec)
304{
305 snd_soc_dapm_new_controls(codec, wm8960_dapm_widgets,
306 ARRAY_SIZE(wm8960_dapm_widgets));
307
308 snd_soc_dapm_add_routes(codec, audio_paths, ARRAY_SIZE(audio_paths));
309
310 snd_soc_dapm_new_widgets(codec);
311 return 0;
312}
313
314static int wm8960_set_dai_fmt(struct snd_soc_dai *codec_dai,
315 unsigned int fmt)
316{
317 struct snd_soc_codec *codec = codec_dai->codec;
318 u16 iface = 0;
319
320 /* set master/slave audio interface */
321 switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
322 case SND_SOC_DAIFMT_CBM_CFM:
323 iface |= 0x0040;
324 break;
325 case SND_SOC_DAIFMT_CBS_CFS:
326 break;
327 default:
328 return -EINVAL;
329 }
330
331 /* interface format */
332 switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
333 case SND_SOC_DAIFMT_I2S:
334 iface |= 0x0002;
335 break;
336 case SND_SOC_DAIFMT_RIGHT_J:
337 break;
338 case SND_SOC_DAIFMT_LEFT_J:
339 iface |= 0x0001;
340 break;
341 case SND_SOC_DAIFMT_DSP_A:
342 iface |= 0x0003;
343 break;
344 case SND_SOC_DAIFMT_DSP_B:
345 iface |= 0x0013;
346 break;
347 default:
348 return -EINVAL;
349 }
350
351 /* clock inversion */
352 switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
353 case SND_SOC_DAIFMT_NB_NF:
354 break;
355 case SND_SOC_DAIFMT_IB_IF:
356 iface |= 0x0090;
357 break;
358 case SND_SOC_DAIFMT_IB_NF:
359 iface |= 0x0080;
360 break;
361 case SND_SOC_DAIFMT_NB_IF:
362 iface |= 0x0010;
363 break;
364 default:
365 return -EINVAL;
366 }
367
368 /* set iface */
369 snd_soc_write(codec, WM8960_IFACE1, iface);
370 return 0;
371}
372
373static int wm8960_hw_params(struct snd_pcm_substream *substream,
374 struct snd_pcm_hw_params *params,
375 struct snd_soc_dai *dai)
376{
377 struct snd_soc_pcm_runtime *rtd = substream->private_data;
378 struct snd_soc_device *socdev = rtd->socdev;
379 struct snd_soc_codec *codec = socdev->card->codec;
380 u16 iface = snd_soc_read(codec, WM8960_IFACE1) & 0xfff3;
381
382 /* bit size */
383 switch (params_format(params)) {
384 case SNDRV_PCM_FORMAT_S16_LE:
385 break;
386 case SNDRV_PCM_FORMAT_S20_3LE:
387 iface |= 0x0004;
388 break;
389 case SNDRV_PCM_FORMAT_S24_LE:
390 iface |= 0x0008;
391 break;
392 }
393
394 /* set iface */
395 snd_soc_write(codec, WM8960_IFACE1, iface);
396 return 0;
397}
398
399static int wm8960_mute(struct snd_soc_dai *dai, int mute)
400{
401 struct snd_soc_codec *codec = dai->codec;
402 u16 mute_reg = snd_soc_read(codec, WM8960_DACCTL1) & 0xfff7;
403
404 if (mute)
405 snd_soc_write(codec, WM8960_DACCTL1, mute_reg | 0x8);
406 else
407 snd_soc_write(codec, WM8960_DACCTL1, mute_reg);
408 return 0;
409}
410
411static int wm8960_set_bias_level(struct snd_soc_codec *codec,
412 enum snd_soc_bias_level level)
413{
414 struct wm8960_data *pdata = codec->dev->platform_data;
415 u16 reg;
416
417 switch (level) {
418 case SND_SOC_BIAS_ON:
419 break;
420
421 case SND_SOC_BIAS_PREPARE:
422 /* Set VMID to 2x50k */
423 reg = snd_soc_read(codec, WM8960_POWER1);
424 reg &= ~0x180;
425 reg |= 0x80;
426 snd_soc_write(codec, WM8960_POWER1, reg);
427 break;
428
429 case SND_SOC_BIAS_STANDBY:
430 if (codec->bias_level == SND_SOC_BIAS_OFF) {
431 /* Enable anti-pop features */
432 snd_soc_write(codec, WM8960_APOP1,
433 WM8960_POBCTRL | WM8960_SOFT_ST |
434 WM8960_BUFDCOPEN | WM8960_BUFIOEN);
435
436 /* Discharge HP output */
437 reg = WM8960_DISOP;
438 if (pdata)
439 reg |= pdata->dres << 4;
440 snd_soc_write(codec, WM8960_APOP2, reg);
441
442 msleep(400);
443
444 snd_soc_write(codec, WM8960_APOP2, 0);
445
446 /* Enable & ramp VMID at 2x50k */
447 reg = snd_soc_read(codec, WM8960_POWER1);
448 reg |= 0x80;
449 snd_soc_write(codec, WM8960_POWER1, reg);
450 msleep(100);
451
452 /* Enable VREF */
453 snd_soc_write(codec, WM8960_POWER1, reg | WM8960_VREF);
454
455 /* Disable anti-pop features */
456 snd_soc_write(codec, WM8960_APOP1, WM8960_BUFIOEN);
457 }
458
459 /* Set VMID to 2x250k */
460 reg = snd_soc_read(codec, WM8960_POWER1);
461 reg &= ~0x180;
462 reg |= 0x100;
463 snd_soc_write(codec, WM8960_POWER1, reg);
464 break;
465
466 case SND_SOC_BIAS_OFF:
467 /* Enable anti-pop features */
468 snd_soc_write(codec, WM8960_APOP1,
469 WM8960_POBCTRL | WM8960_SOFT_ST |
470 WM8960_BUFDCOPEN | WM8960_BUFIOEN);
471
472 /* Disable VMID and VREF, let them discharge */
473 snd_soc_write(codec, WM8960_POWER1, 0);
474 msleep(600);
475
476 snd_soc_write(codec, WM8960_APOP1, 0);
477 break;
478 }
479
480 codec->bias_level = level;
481
482 return 0;
483}
484
485/* PLL divisors */
486struct _pll_div {
487 u32 pre_div:1;
488 u32 n:4;
489 u32 k:24;
490};
491
492/* The size in bits of the pll divide multiplied by 10
493 * to allow rounding later */
494#define FIXED_PLL_SIZE ((1 << 24) * 10)
495
496static int pll_factors(unsigned int source, unsigned int target,
497 struct _pll_div *pll_div)
498{
499 unsigned long long Kpart;
500 unsigned int K, Ndiv, Nmod;
501
502 pr_debug("WM8960 PLL: setting %dHz->%dHz\n", source, target);
503
504 /* Scale up target to PLL operating frequency */
505 target *= 4;
506
507 Ndiv = target / source;
508 if (Ndiv < 6) {
509 source >>= 1;
510 pll_div->pre_div = 1;
511 Ndiv = target / source;
512 } else
513 pll_div->pre_div = 0;
514
515 if ((Ndiv < 6) || (Ndiv > 12)) {
516 pr_err("WM8960 PLL: Unsupported N=%d\n", Ndiv);
517 return -EINVAL;
518 }
519
520 pll_div->n = Ndiv;
521 Nmod = target % source;
522 Kpart = FIXED_PLL_SIZE * (long long)Nmod;
523
524 do_div(Kpart, source);
525
526 K = Kpart & 0xFFFFFFFF;
527
528 /* Check if we need to round */
529 if ((K % 10) >= 5)
530 K += 5;
531
532 /* Move down to proper range now rounding is done */
533 K /= 10;
534
535 pll_div->k = K;
536
537 pr_debug("WM8960 PLL: N=%x K=%x pre_div=%d\n",
538 pll_div->n, pll_div->k, pll_div->pre_div);
539
540 return 0;
541}
542
543static int wm8960_set_dai_pll(struct snd_soc_dai *codec_dai,
544 int pll_id, unsigned int freq_in, unsigned int freq_out)
545{
546 struct snd_soc_codec *codec = codec_dai->codec;
547 u16 reg;
548 static struct _pll_div pll_div;
549 int ret;
550
551 if (freq_in && freq_out) {
552 ret = pll_factors(freq_in, freq_out, &pll_div);
553 if (ret != 0)
554 return ret;
555 }
556
557 /* Disable the PLL: even if we are changing the frequency the
558 * PLL needs to be disabled while we do so. */
559 snd_soc_write(codec, WM8960_CLOCK1,
560 snd_soc_read(codec, WM8960_CLOCK1) & ~1);
561 snd_soc_write(codec, WM8960_POWER2,
562 snd_soc_read(codec, WM8960_POWER2) & ~1);
563
564 if (!freq_in || !freq_out)
565 return 0;
566
567 reg = snd_soc_read(codec, WM8960_PLL1) & ~0x3f;
568 reg |= pll_div.pre_div << 4;
569 reg |= pll_div.n;
570
571 if (pll_div.k) {
572 reg |= 0x20;
573
574 snd_soc_write(codec, WM8960_PLL2, (pll_div.k >> 18) & 0x3f);
575 snd_soc_write(codec, WM8960_PLL3, (pll_div.k >> 9) & 0x1ff);
576 snd_soc_write(codec, WM8960_PLL4, pll_div.k & 0x1ff);
577 }
578 snd_soc_write(codec, WM8960_PLL1, reg);
579
580 /* Turn it on */
581 snd_soc_write(codec, WM8960_POWER2,
582 snd_soc_read(codec, WM8960_POWER2) | 1);
583 msleep(250);
584 snd_soc_write(codec, WM8960_CLOCK1,
585 snd_soc_read(codec, WM8960_CLOCK1) | 1);
586
587 return 0;
588}
589
590static int wm8960_set_dai_clkdiv(struct snd_soc_dai *codec_dai,
591 int div_id, int div)
592{
593 struct snd_soc_codec *codec = codec_dai->codec;
594 u16 reg;
595
596 switch (div_id) {
597 case WM8960_SYSCLKSEL:
598 reg = snd_soc_read(codec, WM8960_CLOCK1) & 0x1fe;
599 snd_soc_write(codec, WM8960_CLOCK1, reg | div);
600 break;
601 case WM8960_SYSCLKDIV:
602 reg = snd_soc_read(codec, WM8960_CLOCK1) & 0x1f9;
603 snd_soc_write(codec, WM8960_CLOCK1, reg | div);
604 break;
605 case WM8960_DACDIV:
606 reg = snd_soc_read(codec, WM8960_CLOCK1) & 0x1c7;
607 snd_soc_write(codec, WM8960_CLOCK1, reg | div);
608 break;
609 case WM8960_OPCLKDIV:
610 reg = snd_soc_read(codec, WM8960_PLL1) & 0x03f;
611 snd_soc_write(codec, WM8960_PLL1, reg | div);
612 break;
613 case WM8960_DCLKDIV:
614 reg = snd_soc_read(codec, WM8960_CLOCK2) & 0x03f;
615 snd_soc_write(codec, WM8960_CLOCK2, reg | div);
616 break;
617 case WM8960_TOCLKSEL:
618 reg = snd_soc_read(codec, WM8960_ADDCTL1) & 0x1fd;
619 snd_soc_write(codec, WM8960_ADDCTL1, reg | div);
620 break;
621 default:
622 return -EINVAL;
623 }
624
625 return 0;
626}
627
628#define WM8960_RATES SNDRV_PCM_RATE_8000_48000
629
630#define WM8960_FORMATS \
631 (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE | \
632 SNDRV_PCM_FMTBIT_S24_LE)
633
634static struct snd_soc_dai_ops wm8960_dai_ops = {
635 .hw_params = wm8960_hw_params,
636 .digital_mute = wm8960_mute,
637 .set_fmt = wm8960_set_dai_fmt,
638 .set_clkdiv = wm8960_set_dai_clkdiv,
639 .set_pll = wm8960_set_dai_pll,
640};
641
642struct snd_soc_dai wm8960_dai = {
643 .name = "WM8960",
644 .playback = {
645 .stream_name = "Playback",
646 .channels_min = 1,
647 .channels_max = 2,
648 .rates = WM8960_RATES,
649 .formats = WM8960_FORMATS,},
650 .capture = {
651 .stream_name = "Capture",
652 .channels_min = 1,
653 .channels_max = 2,
654 .rates = WM8960_RATES,
655 .formats = WM8960_FORMATS,},
656 .ops = &wm8960_dai_ops,
657 .symmetric_rates = 1,
658};
659EXPORT_SYMBOL_GPL(wm8960_dai);
660
661static int wm8960_suspend(struct platform_device *pdev, pm_message_t state)
662{
663 struct snd_soc_device *socdev = platform_get_drvdata(pdev);
664 struct snd_soc_codec *codec = socdev->card->codec;
665
666 wm8960_set_bias_level(codec, SND_SOC_BIAS_OFF);
667 return 0;
668}
669
670static int wm8960_resume(struct platform_device *pdev)
671{
672 struct snd_soc_device *socdev = platform_get_drvdata(pdev);
673 struct snd_soc_codec *codec = socdev->card->codec;
674 int i;
675 u8 data[2];
676 u16 *cache = codec->reg_cache;
677
678 /* Sync reg_cache with the hardware */
679 for (i = 0; i < ARRAY_SIZE(wm8960_reg); i++) {
680 data[0] = (i << 1) | ((cache[i] >> 8) & 0x0001);
681 data[1] = cache[i] & 0x00ff;
682 codec->hw_write(codec->control_data, data, 2);
683 }
684
685 wm8960_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
686 wm8960_set_bias_level(codec, codec->suspend_bias_level);
687 return 0;
688}
689
690static struct snd_soc_codec *wm8960_codec;
691
692static int wm8960_probe(struct platform_device *pdev)
693{
694 struct snd_soc_device *socdev = platform_get_drvdata(pdev);
695 struct snd_soc_codec *codec;
696 int ret = 0;
697
698 if (wm8960_codec == NULL) {
699 dev_err(&pdev->dev, "Codec device not registered\n");
700 return -ENODEV;
701 }
702
703 socdev->card->codec = wm8960_codec;
704 codec = wm8960_codec;
705
706 /* register pcms */
707 ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1);
708 if (ret < 0) {
709 dev_err(codec->dev, "failed to create pcms: %d\n", ret);
710 goto pcm_err;
711 }
712
713 snd_soc_add_controls(codec, wm8960_snd_controls,
714 ARRAY_SIZE(wm8960_snd_controls));
715 wm8960_add_widgets(codec);
716 ret = snd_soc_init_card(socdev);
717 if (ret < 0) {
718 dev_err(codec->dev, "failed to register card: %d\n", ret);
719 goto card_err;
720 }
721
722 return ret;
723
724card_err:
725 snd_soc_free_pcms(socdev);
726 snd_soc_dapm_free(socdev);
727pcm_err:
728 return ret;
729}
730
731/* power down chip */
732static int wm8960_remove(struct platform_device *pdev)
733{
734 struct snd_soc_device *socdev = platform_get_drvdata(pdev);
735
736 snd_soc_free_pcms(socdev);
737 snd_soc_dapm_free(socdev);
738
739 return 0;
740}
741
742struct snd_soc_codec_device soc_codec_dev_wm8960 = {
743 .probe = wm8960_probe,
744 .remove = wm8960_remove,
745 .suspend = wm8960_suspend,
746 .resume = wm8960_resume,
747};
748EXPORT_SYMBOL_GPL(soc_codec_dev_wm8960);
749
750static int wm8960_register(struct wm8960_priv *wm8960,
751 enum snd_soc_control_type control)
752{
753 struct wm8960_data *pdata = wm8960->codec.dev->platform_data;
754 struct snd_soc_codec *codec = &wm8960->codec;
755 int ret;
756 u16 reg;
757
758 if (wm8960_codec) {
759 dev_err(codec->dev, "Another WM8960 is registered\n");
760 ret = -EINVAL;
761 goto err;
762 }
763
764 if (!pdata) {
765 dev_warn(codec->dev, "No platform data supplied\n");
766 } else {
767 if (pdata->dres > WM8960_DRES_MAX) {
768 dev_err(codec->dev, "Invalid DRES: %d\n", pdata->dres);
769 pdata->dres = 0;
770 }
771 }
772
773 mutex_init(&codec->mutex);
774 INIT_LIST_HEAD(&codec->dapm_widgets);
775 INIT_LIST_HEAD(&codec->dapm_paths);
776
777 codec->private_data = wm8960;
778 codec->name = "WM8960";
779 codec->owner = THIS_MODULE;
780 codec->bias_level = SND_SOC_BIAS_OFF;
781 codec->set_bias_level = wm8960_set_bias_level;
782 codec->dai = &wm8960_dai;
783 codec->num_dai = 1;
784 codec->reg_cache_size = WM8960_CACHEREGNUM;
785 codec->reg_cache = &wm8960->reg_cache;
786
787 memcpy(codec->reg_cache, wm8960_reg, sizeof(wm8960_reg));
788
789 ret = snd_soc_codec_set_cache_io(codec, 7, 9, control);
790 if (ret < 0) {
791 dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret);
792 goto err;
793 }
794
795 ret = wm8960_reset(codec);
796 if (ret < 0) {
797 dev_err(codec->dev, "Failed to issue reset\n");
798 goto err;
799 }
800
801 wm8960_dai.dev = codec->dev;
802
803 wm8960_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
804
805 /* Latch the update bits */
806 reg = snd_soc_read(codec, WM8960_LINVOL);
807 snd_soc_write(codec, WM8960_LINVOL, reg | 0x100);
808 reg = snd_soc_read(codec, WM8960_RINVOL);
809 snd_soc_write(codec, WM8960_RINVOL, reg | 0x100);
810 reg = snd_soc_read(codec, WM8960_LADC);
811 snd_soc_write(codec, WM8960_LADC, reg | 0x100);
812 reg = snd_soc_read(codec, WM8960_RADC);
813 snd_soc_write(codec, WM8960_RADC, reg | 0x100);
814 reg = snd_soc_read(codec, WM8960_LDAC);
815 snd_soc_write(codec, WM8960_LDAC, reg | 0x100);
816 reg = snd_soc_read(codec, WM8960_RDAC);
817 snd_soc_write(codec, WM8960_RDAC, reg | 0x100);
818 reg = snd_soc_read(codec, WM8960_LOUT1);
819 snd_soc_write(codec, WM8960_LOUT1, reg | 0x100);
820 reg = snd_soc_read(codec, WM8960_ROUT1);
821 snd_soc_write(codec, WM8960_ROUT1, reg | 0x100);
822 reg = snd_soc_read(codec, WM8960_LOUT2);
823 snd_soc_write(codec, WM8960_LOUT2, reg | 0x100);
824 reg = snd_soc_read(codec, WM8960_ROUT2);
825 snd_soc_write(codec, WM8960_ROUT2, reg | 0x100);
826
827 wm8960_codec = codec;
828
829 ret = snd_soc_register_codec(codec);
830 if (ret != 0) {
831 dev_err(codec->dev, "Failed to register codec: %d\n", ret);
832 goto err;
833 }
834
835 ret = snd_soc_register_dai(&wm8960_dai);
836 if (ret != 0) {
837 dev_err(codec->dev, "Failed to register DAI: %d\n", ret);
838 goto err_codec;
839 }
840
841 return 0;
842
843err_codec:
844 snd_soc_unregister_codec(codec);
845err:
846 kfree(wm8960);
847 return ret;
848}
849
850static void wm8960_unregister(struct wm8960_priv *wm8960)
851{
852 wm8960_set_bias_level(&wm8960->codec, SND_SOC_BIAS_OFF);
853 snd_soc_unregister_dai(&wm8960_dai);
854 snd_soc_unregister_codec(&wm8960->codec);
855 kfree(wm8960);
856 wm8960_codec = NULL;
857}
858
859static __devinit int wm8960_i2c_probe(struct i2c_client *i2c,
860 const struct i2c_device_id *id)
861{
862 struct wm8960_priv *wm8960;
863 struct snd_soc_codec *codec;
864
865 wm8960 = kzalloc(sizeof(struct wm8960_priv), GFP_KERNEL);
866 if (wm8960 == NULL)
867 return -ENOMEM;
868
869 codec = &wm8960->codec;
870
871 i2c_set_clientdata(i2c, wm8960);
872 codec->control_data = i2c;
873
874 codec->dev = &i2c->dev;
875
876 return wm8960_register(wm8960, SND_SOC_I2C);
877}
878
879static __devexit int wm8960_i2c_remove(struct i2c_client *client)
880{
881 struct wm8960_priv *wm8960 = i2c_get_clientdata(client);
882 wm8960_unregister(wm8960);
883 return 0;
884}
885
886#ifdef CONFIG_PM
887static int wm8960_i2c_suspend(struct i2c_client *client, pm_message_t msg)
888{
889 return snd_soc_suspend_device(&client->dev);
890}
891
892static int wm8960_i2c_resume(struct i2c_client *client)
893{
894 return snd_soc_resume_device(&client->dev);
895}
896#else
897#define wm8960_i2c_suspend NULL
898#define wm8960_i2c_resume NULL
899#endif
900
901static const struct i2c_device_id wm8960_i2c_id[] = {
902 { "wm8960", 0 },
903 { }
904};
905MODULE_DEVICE_TABLE(i2c, wm8960_i2c_id);
906
907static struct i2c_driver wm8960_i2c_driver = {
908 .driver = {
909 .name = "WM8960 I2C Codec",
910 .owner = THIS_MODULE,
911 },
912 .probe = wm8960_i2c_probe,
913 .remove = __devexit_p(wm8960_i2c_remove),
914 .suspend = wm8960_i2c_suspend,
915 .resume = wm8960_i2c_resume,
916 .id_table = wm8960_i2c_id,
917};
918
919static int __init wm8960_modinit(void)
920{
921 int ret;
922
923 ret = i2c_add_driver(&wm8960_i2c_driver);
924 if (ret != 0) {
925 printk(KERN_ERR "Failed to register WM8960 I2C driver: %d\n",
926 ret);
927 }
928
929 return ret;
930}
931module_init(wm8960_modinit);
932
933static void __exit wm8960_exit(void)
934{
935 i2c_del_driver(&wm8960_i2c_driver);
936}
937module_exit(wm8960_exit);
938
939
940MODULE_DESCRIPTION("ASoC WM8960 driver");
941MODULE_AUTHOR("Liam Girdwood");
942MODULE_LICENSE("GPL");
diff --git a/sound/soc/codecs/wm8960.h b/sound/soc/codecs/wm8960.h
new file mode 100644
index 000000000000..c9af56c9d9d4
--- /dev/null
+++ b/sound/soc/codecs/wm8960.h
@@ -0,0 +1,127 @@
1/*
2 * wm8960.h -- WM8960 Soc Audio driver
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License version 2 as
6 * published by the Free Software Foundation.
7 */
8
9#ifndef _WM8960_H
10#define _WM8960_H
11
12/* WM8960 register space */
13
14
15#define WM8960_CACHEREGNUM 56
16
17#define WM8960_LINVOL 0x0
18#define WM8960_RINVOL 0x1
19#define WM8960_LOUT1 0x2
20#define WM8960_ROUT1 0x3
21#define WM8960_CLOCK1 0x4
22#define WM8960_DACCTL1 0x5
23#define WM8960_DACCTL2 0x6
24#define WM8960_IFACE1 0x7
25#define WM8960_CLOCK2 0x8
26#define WM8960_IFACE2 0x9
27#define WM8960_LDAC 0xa
28#define WM8960_RDAC 0xb
29
30#define WM8960_RESET 0xf
31#define WM8960_3D 0x10
32#define WM8960_ALC1 0x11
33#define WM8960_ALC2 0x12
34#define WM8960_ALC3 0x13
35#define WM8960_NOISEG 0x14
36#define WM8960_LADC 0x15
37#define WM8960_RADC 0x16
38#define WM8960_ADDCTL1 0x17
39#define WM8960_ADDCTL2 0x18
40#define WM8960_POWER1 0x19
41#define WM8960_POWER2 0x1a
42#define WM8960_ADDCTL3 0x1b
43#define WM8960_APOP1 0x1c
44#define WM8960_APOP2 0x1d
45
46#define WM8960_LINPATH 0x20
47#define WM8960_RINPATH 0x21
48#define WM8960_LOUTMIX 0x22
49
50#define WM8960_ROUTMIX 0x25
51#define WM8960_MONOMIX1 0x26
52#define WM8960_MONOMIX2 0x27
53#define WM8960_LOUT2 0x28
54#define WM8960_ROUT2 0x29
55#define WM8960_MONO 0x2a
56#define WM8960_INBMIX1 0x2b
57#define WM8960_INBMIX2 0x2c
58#define WM8960_BYPASS1 0x2d
59#define WM8960_BYPASS2 0x2e
60#define WM8960_POWER3 0x2f
61#define WM8960_ADDCTL4 0x30
62#define WM8960_CLASSD1 0x31
63
64#define WM8960_CLASSD3 0x33
65#define WM8960_PLL1 0x34
66#define WM8960_PLL2 0x35
67#define WM8960_PLL3 0x36
68#define WM8960_PLL4 0x37
69
70
71/*
72 * WM8960 Clock dividers
73 */
74#define WM8960_SYSCLKDIV 0
75#define WM8960_DACDIV 1
76#define WM8960_OPCLKDIV 2
77#define WM8960_DCLKDIV 3
78#define WM8960_TOCLKSEL 4
79#define WM8960_SYSCLKSEL 5
80
81#define WM8960_SYSCLK_DIV_1 (0 << 1)
82#define WM8960_SYSCLK_DIV_2 (2 << 1)
83
84#define WM8960_SYSCLK_MCLK (0 << 0)
85#define WM8960_SYSCLK_PLL (1 << 0)
86
87#define WM8960_DAC_DIV_1 (0 << 3)
88#define WM8960_DAC_DIV_1_5 (1 << 3)
89#define WM8960_DAC_DIV_2 (2 << 3)
90#define WM8960_DAC_DIV_3 (3 << 3)
91#define WM8960_DAC_DIV_4 (4 << 3)
92#define WM8960_DAC_DIV_5_5 (5 << 3)
93#define WM8960_DAC_DIV_6 (6 << 3)
94
95#define WM8960_DCLK_DIV_1_5 (0 << 6)
96#define WM8960_DCLK_DIV_2 (1 << 6)
97#define WM8960_DCLK_DIV_3 (2 << 6)
98#define WM8960_DCLK_DIV_4 (3 << 6)
99#define WM8960_DCLK_DIV_6 (4 << 6)
100#define WM8960_DCLK_DIV_8 (5 << 6)
101#define WM8960_DCLK_DIV_12 (6 << 6)
102#define WM8960_DCLK_DIV_16 (7 << 6)
103
104#define WM8960_TOCLK_F19 (0 << 1)
105#define WM8960_TOCLK_F21 (1 << 1)
106
107#define WM8960_OPCLK_DIV_1 (0 << 0)
108#define WM8960_OPCLK_DIV_2 (1 << 0)
109#define WM8960_OPCLK_DIV_3 (2 << 0)
110#define WM8960_OPCLK_DIV_4 (3 << 0)
111#define WM8960_OPCLK_DIV_5_5 (4 << 0)
112#define WM8960_OPCLK_DIV_6 (5 << 0)
113
114extern struct snd_soc_dai wm8960_dai;
115extern struct snd_soc_codec_device soc_codec_dev_wm8960;
116
117#define WM8960_DRES_400R 0
118#define WM8960_DRES_200R 1
119#define WM8960_DRES_600R 2
120#define WM8960_DRES_150R 3
121#define WM8960_DRES_MAX 3
122
123struct wm8960_data {
124 int dres;
125};
126
127#endif
diff --git a/sound/soc/codecs/wm8961.c b/sound/soc/codecs/wm8961.c
new file mode 100644
index 000000000000..503032085899
--- /dev/null
+++ b/sound/soc/codecs/wm8961.c
@@ -0,0 +1,1265 @@
1/*
2 * wm8961.c -- WM8961 ALSA SoC Audio driver
3 *
4 * Author: Mark Brown
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License version 2 as
8 * published by the Free Software Foundation.
9 *
10 * Currently unimplemented features:
11 * - ALC
12 */
13
14#include <linux/module.h>
15#include <linux/moduleparam.h>
16#include <linux/init.h>
17#include <linux/delay.h>
18#include <linux/pm.h>
19#include <linux/i2c.h>
20#include <linux/platform_device.h>
21#include <sound/core.h>
22#include <sound/pcm.h>
23#include <sound/pcm_params.h>
24#include <sound/soc.h>
25#include <sound/soc-dapm.h>
26#include <sound/initval.h>
27#include <sound/tlv.h>
28
29#include "wm8961.h"
30
31#define WM8961_MAX_REGISTER 0xFC
32
33static u16 wm8961_reg_defaults[] = {
34 0x009F, /* R0 - Left Input volume */
35 0x009F, /* R1 - Right Input volume */
36 0x0000, /* R2 - LOUT1 volume */
37 0x0000, /* R3 - ROUT1 volume */
38 0x0020, /* R4 - Clocking1 */
39 0x0008, /* R5 - ADC & DAC Control 1 */
40 0x0000, /* R6 - ADC & DAC Control 2 */
41 0x000A, /* R7 - Audio Interface 0 */
42 0x01F4, /* R8 - Clocking2 */
43 0x0000, /* R9 - Audio Interface 1 */
44 0x00FF, /* R10 - Left DAC volume */
45 0x00FF, /* R11 - Right DAC volume */
46 0x0000, /* R12 */
47 0x0000, /* R13 */
48 0x0040, /* R14 - Audio Interface 2 */
49 0x0000, /* R15 - Software Reset */
50 0x0000, /* R16 */
51 0x007B, /* R17 - ALC1 */
52 0x0000, /* R18 - ALC2 */
53 0x0032, /* R19 - ALC3 */
54 0x0000, /* R20 - Noise Gate */
55 0x00C0, /* R21 - Left ADC volume */
56 0x00C0, /* R22 - Right ADC volume */
57 0x0120, /* R23 - Additional control(1) */
58 0x0000, /* R24 - Additional control(2) */
59 0x0000, /* R25 - Pwr Mgmt (1) */
60 0x0000, /* R26 - Pwr Mgmt (2) */
61 0x0000, /* R27 - Additional Control (3) */
62 0x0000, /* R28 - Anti-pop */
63 0x0000, /* R29 */
64 0x005F, /* R30 - Clocking 3 */
65 0x0000, /* R31 */
66 0x0000, /* R32 - ADCL signal path */
67 0x0000, /* R33 - ADCR signal path */
68 0x0000, /* R34 */
69 0x0000, /* R35 */
70 0x0000, /* R36 */
71 0x0000, /* R37 */
72 0x0000, /* R38 */
73 0x0000, /* R39 */
74 0x0000, /* R40 - LOUT2 volume */
75 0x0000, /* R41 - ROUT2 volume */
76 0x0000, /* R42 */
77 0x0000, /* R43 */
78 0x0000, /* R44 */
79 0x0000, /* R45 */
80 0x0000, /* R46 */
81 0x0000, /* R47 - Pwr Mgmt (3) */
82 0x0023, /* R48 - Additional Control (4) */
83 0x0000, /* R49 - Class D Control 1 */
84 0x0000, /* R50 */
85 0x0003, /* R51 - Class D Control 2 */
86 0x0000, /* R52 */
87 0x0000, /* R53 */
88 0x0000, /* R54 */
89 0x0000, /* R55 */
90 0x0106, /* R56 - Clocking 4 */
91 0x0000, /* R57 - DSP Sidetone 0 */
92 0x0000, /* R58 - DSP Sidetone 1 */
93 0x0000, /* R59 */
94 0x0000, /* R60 - DC Servo 0 */
95 0x0000, /* R61 - DC Servo 1 */
96 0x0000, /* R62 */
97 0x015E, /* R63 - DC Servo 3 */
98 0x0010, /* R64 */
99 0x0010, /* R65 - DC Servo 5 */
100 0x0000, /* R66 */
101 0x0001, /* R67 */
102 0x0003, /* R68 - Analogue PGA Bias */
103 0x0000, /* R69 - Analogue HP 0 */
104 0x0060, /* R70 */
105 0x01FB, /* R71 - Analogue HP 2 */
106 0x0000, /* R72 - Charge Pump 1 */
107 0x0065, /* R73 */
108 0x005F, /* R74 */
109 0x0059, /* R75 */
110 0x006B, /* R76 */
111 0x0038, /* R77 */
112 0x000C, /* R78 */
113 0x000A, /* R79 */
114 0x006B, /* R80 */
115 0x0000, /* R81 */
116 0x0000, /* R82 - Charge Pump B */
117 0x0087, /* R83 */
118 0x0000, /* R84 */
119 0x005C, /* R85 */
120 0x0000, /* R86 */
121 0x0000, /* R87 - Write Sequencer 1 */
122 0x0000, /* R88 - Write Sequencer 2 */
123 0x0000, /* R89 - Write Sequencer 3 */
124 0x0000, /* R90 - Write Sequencer 4 */
125 0x0000, /* R91 - Write Sequencer 5 */
126 0x0000, /* R92 - Write Sequencer 6 */
127 0x0000, /* R93 - Write Sequencer 7 */
128 0x0000, /* R94 */
129 0x0000, /* R95 */
130 0x0000, /* R96 */
131 0x0000, /* R97 */
132 0x0000, /* R98 */
133 0x0000, /* R99 */
134 0x0000, /* R100 */
135 0x0000, /* R101 */
136 0x0000, /* R102 */
137 0x0000, /* R103 */
138 0x0000, /* R104 */
139 0x0000, /* R105 */
140 0x0000, /* R106 */
141 0x0000, /* R107 */
142 0x0000, /* R108 */
143 0x0000, /* R109 */
144 0x0000, /* R110 */
145 0x0000, /* R111 */
146 0x0000, /* R112 */
147 0x0000, /* R113 */
148 0x0000, /* R114 */
149 0x0000, /* R115 */
150 0x0000, /* R116 */
151 0x0000, /* R117 */
152 0x0000, /* R118 */
153 0x0000, /* R119 */
154 0x0000, /* R120 */
155 0x0000, /* R121 */
156 0x0000, /* R122 */
157 0x0000, /* R123 */
158 0x0000, /* R124 */
159 0x0000, /* R125 */
160 0x0000, /* R126 */
161 0x0000, /* R127 */
162 0x0000, /* R128 */
163 0x0000, /* R129 */
164 0x0000, /* R130 */
165 0x0000, /* R131 */
166 0x0000, /* R132 */
167 0x0000, /* R133 */
168 0x0000, /* R134 */
169 0x0000, /* R135 */
170 0x0000, /* R136 */
171 0x0000, /* R137 */
172 0x0000, /* R138 */
173 0x0000, /* R139 */
174 0x0000, /* R140 */
175 0x0000, /* R141 */
176 0x0000, /* R142 */
177 0x0000, /* R143 */
178 0x0000, /* R144 */
179 0x0000, /* R145 */
180 0x0000, /* R146 */
181 0x0000, /* R147 */
182 0x0000, /* R148 */
183 0x0000, /* R149 */
184 0x0000, /* R150 */
185 0x0000, /* R151 */
186 0x0000, /* R152 */
187 0x0000, /* R153 */
188 0x0000, /* R154 */
189 0x0000, /* R155 */
190 0x0000, /* R156 */
191 0x0000, /* R157 */
192 0x0000, /* R158 */
193 0x0000, /* R159 */
194 0x0000, /* R160 */
195 0x0000, /* R161 */
196 0x0000, /* R162 */
197 0x0000, /* R163 */
198 0x0000, /* R164 */
199 0x0000, /* R165 */
200 0x0000, /* R166 */
201 0x0000, /* R167 */
202 0x0000, /* R168 */
203 0x0000, /* R169 */
204 0x0000, /* R170 */
205 0x0000, /* R171 */
206 0x0000, /* R172 */
207 0x0000, /* R173 */
208 0x0000, /* R174 */
209 0x0000, /* R175 */
210 0x0000, /* R176 */
211 0x0000, /* R177 */
212 0x0000, /* R178 */
213 0x0000, /* R179 */
214 0x0000, /* R180 */
215 0x0000, /* R181 */
216 0x0000, /* R182 */
217 0x0000, /* R183 */
218 0x0000, /* R184 */
219 0x0000, /* R185 */
220 0x0000, /* R186 */
221 0x0000, /* R187 */
222 0x0000, /* R188 */
223 0x0000, /* R189 */
224 0x0000, /* R190 */
225 0x0000, /* R191 */
226 0x0000, /* R192 */
227 0x0000, /* R193 */
228 0x0000, /* R194 */
229 0x0000, /* R195 */
230 0x0030, /* R196 */
231 0x0006, /* R197 */
232 0x0000, /* R198 */
233 0x0060, /* R199 */
234 0x0000, /* R200 */
235 0x003F, /* R201 */
236 0x0000, /* R202 */
237 0x0000, /* R203 */
238 0x0000, /* R204 */
239 0x0001, /* R205 */
240 0x0000, /* R206 */
241 0x0181, /* R207 */
242 0x0005, /* R208 */
243 0x0008, /* R209 */
244 0x0008, /* R210 */
245 0x0000, /* R211 */
246 0x013B, /* R212 */
247 0x0000, /* R213 */
248 0x0000, /* R214 */
249 0x0000, /* R215 */
250 0x0000, /* R216 */
251 0x0070, /* R217 */
252 0x0000, /* R218 */
253 0x0000, /* R219 */
254 0x0000, /* R220 */
255 0x0000, /* R221 */
256 0x0000, /* R222 */
257 0x0003, /* R223 */
258 0x0000, /* R224 */
259 0x0000, /* R225 */
260 0x0001, /* R226 */
261 0x0008, /* R227 */
262 0x0000, /* R228 */
263 0x0000, /* R229 */
264 0x0000, /* R230 */
265 0x0000, /* R231 */
266 0x0004, /* R232 */
267 0x0000, /* R233 */
268 0x0000, /* R234 */
269 0x0000, /* R235 */
270 0x0000, /* R236 */
271 0x0000, /* R237 */
272 0x0080, /* R238 */
273 0x0000, /* R239 */
274 0x0000, /* R240 */
275 0x0000, /* R241 */
276 0x0000, /* R242 */
277 0x0000, /* R243 */
278 0x0000, /* R244 */
279 0x0052, /* R245 */
280 0x0110, /* R246 */
281 0x0040, /* R247 */
282 0x0000, /* R248 */
283 0x0030, /* R249 */
284 0x0000, /* R250 */
285 0x0000, /* R251 */
286 0x0001, /* R252 - General test 1 */
287};
288
289struct wm8961_priv {
290 struct snd_soc_codec codec;
291 int sysclk;
292 u16 reg_cache[WM8961_MAX_REGISTER];
293};
294
295static int wm8961_volatile_register(unsigned int reg)
296{
297 switch (reg) {
298 case WM8961_SOFTWARE_RESET:
299 case WM8961_WRITE_SEQUENCER_7:
300 case WM8961_DC_SERVO_1:
301 return 1;
302
303 default:
304 return 0;
305 }
306}
307
308static int wm8961_reset(struct snd_soc_codec *codec)
309{
310 return snd_soc_write(codec, WM8961_SOFTWARE_RESET, 0);
311}
312
313/*
314 * The headphone output supports special anti-pop sequences giving
315 * silent power up and power down.
316 */
317static int wm8961_hp_event(struct snd_soc_dapm_widget *w,
318 struct snd_kcontrol *kcontrol, int event)
319{
320 struct snd_soc_codec *codec = w->codec;
321 u16 hp_reg = snd_soc_read(codec, WM8961_ANALOGUE_HP_0);
322 u16 cp_reg = snd_soc_read(codec, WM8961_CHARGE_PUMP_1);
323 u16 pwr_reg = snd_soc_read(codec, WM8961_PWR_MGMT_2);
324 u16 dcs_reg = snd_soc_read(codec, WM8961_DC_SERVO_1);
325 int timeout = 500;
326
327 if (event & SND_SOC_DAPM_POST_PMU) {
328 /* Make sure the output is shorted */
329 hp_reg &= ~(WM8961_HPR_RMV_SHORT | WM8961_HPL_RMV_SHORT);
330 snd_soc_write(codec, WM8961_ANALOGUE_HP_0, hp_reg);
331
332 /* Enable the charge pump */
333 cp_reg |= WM8961_CP_ENA;
334 snd_soc_write(codec, WM8961_CHARGE_PUMP_1, cp_reg);
335 mdelay(5);
336
337 /* Enable the PGA */
338 pwr_reg |= WM8961_LOUT1_PGA | WM8961_ROUT1_PGA;
339 snd_soc_write(codec, WM8961_PWR_MGMT_2, pwr_reg);
340
341 /* Enable the amplifier */
342 hp_reg |= WM8961_HPR_ENA | WM8961_HPL_ENA;
343 snd_soc_write(codec, WM8961_ANALOGUE_HP_0, hp_reg);
344
345 /* Second stage enable */
346 hp_reg |= WM8961_HPR_ENA_DLY | WM8961_HPL_ENA_DLY;
347 snd_soc_write(codec, WM8961_ANALOGUE_HP_0, hp_reg);
348
349 /* Enable the DC servo & trigger startup */
350 dcs_reg |=
351 WM8961_DCS_ENA_CHAN_HPR | WM8961_DCS_TRIG_STARTUP_HPR |
352 WM8961_DCS_ENA_CHAN_HPL | WM8961_DCS_TRIG_STARTUP_HPL;
353 dev_dbg(codec->dev, "Enabling DC servo\n");
354
355 snd_soc_write(codec, WM8961_DC_SERVO_1, dcs_reg);
356 do {
357 msleep(1);
358 dcs_reg = snd_soc_read(codec, WM8961_DC_SERVO_1);
359 } while (--timeout &&
360 dcs_reg & (WM8961_DCS_TRIG_STARTUP_HPR |
361 WM8961_DCS_TRIG_STARTUP_HPL));
362 if (dcs_reg & (WM8961_DCS_TRIG_STARTUP_HPR |
363 WM8961_DCS_TRIG_STARTUP_HPL))
364 dev_err(codec->dev, "DC servo timed out\n");
365 else
366 dev_dbg(codec->dev, "DC servo startup complete\n");
367
368 /* Enable the output stage */
369 hp_reg |= WM8961_HPR_ENA_OUTP | WM8961_HPL_ENA_OUTP;
370 snd_soc_write(codec, WM8961_ANALOGUE_HP_0, hp_reg);
371
372 /* Remove the short on the output stage */
373 hp_reg |= WM8961_HPR_RMV_SHORT | WM8961_HPL_RMV_SHORT;
374 snd_soc_write(codec, WM8961_ANALOGUE_HP_0, hp_reg);
375 }
376
377 if (event & SND_SOC_DAPM_PRE_PMD) {
378 /* Short the output */
379 hp_reg &= ~(WM8961_HPR_RMV_SHORT | WM8961_HPL_RMV_SHORT);
380 snd_soc_write(codec, WM8961_ANALOGUE_HP_0, hp_reg);
381
382 /* Disable the output stage */
383 hp_reg &= ~(WM8961_HPR_ENA_OUTP | WM8961_HPL_ENA_OUTP);
384 snd_soc_write(codec, WM8961_ANALOGUE_HP_0, hp_reg);
385
386 /* Disable DC offset cancellation */
387 dcs_reg &= ~(WM8961_DCS_ENA_CHAN_HPR |
388 WM8961_DCS_ENA_CHAN_HPL);
389 snd_soc_write(codec, WM8961_DC_SERVO_1, dcs_reg);
390
391 /* Finish up */
392 hp_reg &= ~(WM8961_HPR_ENA_DLY | WM8961_HPR_ENA |
393 WM8961_HPL_ENA_DLY | WM8961_HPL_ENA);
394 snd_soc_write(codec, WM8961_ANALOGUE_HP_0, hp_reg);
395
396 /* Disable the PGA */
397 pwr_reg &= ~(WM8961_LOUT1_PGA | WM8961_ROUT1_PGA);
398 snd_soc_write(codec, WM8961_PWR_MGMT_2, pwr_reg);
399
400 /* Disable the charge pump */
401 dev_dbg(codec->dev, "Disabling charge pump\n");
402 snd_soc_write(codec, WM8961_CHARGE_PUMP_1,
403 cp_reg & ~WM8961_CP_ENA);
404 }
405
406 return 0;
407}
408
409static int wm8961_spk_event(struct snd_soc_dapm_widget *w,
410 struct snd_kcontrol *kcontrol, int event)
411{
412 struct snd_soc_codec *codec = w->codec;
413 u16 pwr_reg = snd_soc_read(codec, WM8961_PWR_MGMT_2);
414 u16 spk_reg = snd_soc_read(codec, WM8961_CLASS_D_CONTROL_1);
415
416 if (event & SND_SOC_DAPM_POST_PMU) {
417 /* Enable the PGA */
418 pwr_reg |= WM8961_SPKL_PGA | WM8961_SPKR_PGA;
419 snd_soc_write(codec, WM8961_PWR_MGMT_2, pwr_reg);
420
421 /* Enable the amplifier */
422 spk_reg |= WM8961_SPKL_ENA | WM8961_SPKR_ENA;
423 snd_soc_write(codec, WM8961_CLASS_D_CONTROL_1, spk_reg);
424 }
425
426 if (event & SND_SOC_DAPM_PRE_PMD) {
427 /* Enable the amplifier */
428 spk_reg &= ~(WM8961_SPKL_ENA | WM8961_SPKR_ENA);
429 snd_soc_write(codec, WM8961_CLASS_D_CONTROL_1, spk_reg);
430
431 /* Enable the PGA */
432 pwr_reg &= ~(WM8961_SPKL_PGA | WM8961_SPKR_PGA);
433 snd_soc_write(codec, WM8961_PWR_MGMT_2, pwr_reg);
434 }
435
436 return 0;
437}
438
439static const char *adc_hpf_text[] = {
440 "Hi-fi", "Voice 1", "Voice 2", "Voice 3",
441};
442
443static const struct soc_enum adc_hpf =
444 SOC_ENUM_SINGLE(WM8961_ADC_DAC_CONTROL_2, 7, 4, adc_hpf_text);
445
446static const char *dac_deemph_text[] = {
447 "None", "32kHz", "44.1kHz", "48kHz",
448};
449
450static const struct soc_enum dac_deemph =
451 SOC_ENUM_SINGLE(WM8961_ADC_DAC_CONTROL_1, 1, 4, dac_deemph_text);
452
453static const DECLARE_TLV_DB_SCALE(out_tlv, -12100, 100, 1);
454static const DECLARE_TLV_DB_SCALE(hp_sec_tlv, -700, 100, 0);
455static const DECLARE_TLV_DB_SCALE(adc_tlv, -7200, 75, 1);
456static const DECLARE_TLV_DB_SCALE(sidetone_tlv, -3600, 300, 0);
457static unsigned int boost_tlv[] = {
458 TLV_DB_RANGE_HEAD(4),
459 0, 0, TLV_DB_SCALE_ITEM(0, 0, 0),
460 1, 1, TLV_DB_SCALE_ITEM(13, 0, 0),
461 2, 2, TLV_DB_SCALE_ITEM(20, 0, 0),
462 3, 3, TLV_DB_SCALE_ITEM(29, 0, 0),
463};
464static const DECLARE_TLV_DB_SCALE(pga_tlv, -2325, 75, 0);
465
466static const struct snd_kcontrol_new wm8961_snd_controls[] = {
467SOC_DOUBLE_R_TLV("Headphone Volume", WM8961_LOUT1_VOLUME, WM8961_ROUT1_VOLUME,
468 0, 127, 0, out_tlv),
469SOC_DOUBLE_TLV("Headphone Secondary Volume", WM8961_ANALOGUE_HP_2,
470 6, 3, 7, 0, hp_sec_tlv),
471SOC_DOUBLE_R("Headphone ZC Switch", WM8961_LOUT1_VOLUME, WM8961_ROUT1_VOLUME,
472 7, 1, 0),
473
474SOC_DOUBLE_R_TLV("Speaker Volume", WM8961_LOUT2_VOLUME, WM8961_ROUT2_VOLUME,
475 0, 127, 0, out_tlv),
476SOC_DOUBLE_R("Speaker ZC Switch", WM8961_LOUT2_VOLUME, WM8961_ROUT2_VOLUME,
477 7, 1, 0),
478SOC_SINGLE("Speaker AC Gain", WM8961_CLASS_D_CONTROL_2, 0, 7, 0),
479
480SOC_SINGLE("DAC x128 OSR Switch", WM8961_ADC_DAC_CONTROL_2, 0, 1, 0),
481SOC_ENUM("DAC Deemphasis", dac_deemph),
482SOC_SINGLE("DAC Soft Mute Switch", WM8961_ADC_DAC_CONTROL_2, 3, 1, 0),
483
484SOC_DOUBLE_R_TLV("Sidetone Volume", WM8961_DSP_SIDETONE_0,
485 WM8961_DSP_SIDETONE_1, 4, 12, 0, sidetone_tlv),
486
487SOC_SINGLE("ADC High Pass Filter Switch", WM8961_ADC_DAC_CONTROL_1, 0, 1, 0),
488SOC_ENUM("ADC High Pass Filter Mode", adc_hpf),
489
490SOC_DOUBLE_R_TLV("Capture Volume",
491 WM8961_LEFT_ADC_VOLUME, WM8961_RIGHT_ADC_VOLUME,
492 1, 119, 0, adc_tlv),
493SOC_DOUBLE_R_TLV("Capture Boost Volume",
494 WM8961_ADCL_SIGNAL_PATH, WM8961_ADCR_SIGNAL_PATH,
495 4, 3, 0, boost_tlv),
496SOC_DOUBLE_R_TLV("Capture PGA Volume",
497 WM8961_LEFT_INPUT_VOLUME, WM8961_RIGHT_INPUT_VOLUME,
498 0, 62, 0, pga_tlv),
499SOC_DOUBLE_R("Capture PGA ZC Switch",
500 WM8961_LEFT_INPUT_VOLUME, WM8961_RIGHT_INPUT_VOLUME,
501 6, 1, 1),
502SOC_DOUBLE_R("Capture PGA Switch",
503 WM8961_LEFT_INPUT_VOLUME, WM8961_RIGHT_INPUT_VOLUME,
504 7, 1, 1),
505};
506
507static const char *sidetone_text[] = {
508 "None", "Left", "Right"
509};
510
511static const struct soc_enum dacl_sidetone =
512 SOC_ENUM_SINGLE(WM8961_DSP_SIDETONE_0, 2, 3, sidetone_text);
513
514static const struct soc_enum dacr_sidetone =
515 SOC_ENUM_SINGLE(WM8961_DSP_SIDETONE_1, 2, 3, sidetone_text);
516
517static const struct snd_kcontrol_new dacl_mux =
518 SOC_DAPM_ENUM("DACL Sidetone", dacl_sidetone);
519
520static const struct snd_kcontrol_new dacr_mux =
521 SOC_DAPM_ENUM("DACR Sidetone", dacr_sidetone);
522
523static const struct snd_soc_dapm_widget wm8961_dapm_widgets[] = {
524SND_SOC_DAPM_INPUT("LINPUT"),
525SND_SOC_DAPM_INPUT("RINPUT"),
526
527SND_SOC_DAPM_SUPPLY("CLK_DSP", WM8961_CLOCKING2, 4, 0, NULL, 0),
528
529SND_SOC_DAPM_PGA("Left Input", WM8961_PWR_MGMT_1, 5, 0, NULL, 0),
530SND_SOC_DAPM_PGA("Right Input", WM8961_PWR_MGMT_1, 4, 0, NULL, 0),
531
532SND_SOC_DAPM_ADC("ADCL", "HiFi Capture", WM8961_PWR_MGMT_1, 3, 0),
533SND_SOC_DAPM_ADC("ADCR", "HiFi Capture", WM8961_PWR_MGMT_1, 2, 0),
534
535SND_SOC_DAPM_MICBIAS("MICBIAS", WM8961_PWR_MGMT_1, 1, 0),
536
537SND_SOC_DAPM_MUX("DACL Sidetone", SND_SOC_NOPM, 0, 0, &dacl_mux),
538SND_SOC_DAPM_MUX("DACR Sidetone", SND_SOC_NOPM, 0, 0, &dacr_mux),
539
540SND_SOC_DAPM_DAC("DACL", "HiFi Playback", WM8961_PWR_MGMT_2, 8, 0),
541SND_SOC_DAPM_DAC("DACR", "HiFi Playback", WM8961_PWR_MGMT_2, 7, 0),
542
543/* Handle as a mono path for DCS */
544SND_SOC_DAPM_PGA_E("Headphone Output", SND_SOC_NOPM,
545 4, 0, NULL, 0, wm8961_hp_event,
546 SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD),
547SND_SOC_DAPM_PGA_E("Speaker Output", SND_SOC_NOPM,
548 4, 0, NULL, 0, wm8961_spk_event,
549 SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD),
550
551SND_SOC_DAPM_OUTPUT("HP_L"),
552SND_SOC_DAPM_OUTPUT("HP_R"),
553SND_SOC_DAPM_OUTPUT("SPK_LN"),
554SND_SOC_DAPM_OUTPUT("SPK_LP"),
555SND_SOC_DAPM_OUTPUT("SPK_RN"),
556SND_SOC_DAPM_OUTPUT("SPK_RP"),
557};
558
559
560static const struct snd_soc_dapm_route audio_paths[] = {
561 { "DACL", NULL, "CLK_DSP" },
562 { "DACL", NULL, "DACL Sidetone" },
563 { "DACR", NULL, "CLK_DSP" },
564 { "DACR", NULL, "DACR Sidetone" },
565
566 { "DACL Sidetone", "Left", "ADCL" },
567 { "DACL Sidetone", "Right", "ADCR" },
568
569 { "DACR Sidetone", "Left", "ADCL" },
570 { "DACR Sidetone", "Right", "ADCR" },
571
572 { "HP_L", NULL, "Headphone Output" },
573 { "HP_R", NULL, "Headphone Output" },
574 { "Headphone Output", NULL, "DACL" },
575 { "Headphone Output", NULL, "DACR" },
576
577 { "SPK_LN", NULL, "Speaker Output" },
578 { "SPK_LP", NULL, "Speaker Output" },
579 { "SPK_RN", NULL, "Speaker Output" },
580 { "SPK_RP", NULL, "Speaker Output" },
581
582 { "Speaker Output", NULL, "DACL" },
583 { "Speaker Output", NULL, "DACR" },
584
585 { "ADCL", NULL, "Left Input" },
586 { "ADCL", NULL, "CLK_DSP" },
587 { "ADCR", NULL, "Right Input" },
588 { "ADCR", NULL, "CLK_DSP" },
589
590 { "Left Input", NULL, "LINPUT" },
591 { "Right Input", NULL, "RINPUT" },
592
593};
594
595/* Values for CLK_SYS_RATE */
596static struct {
597 int ratio;
598 u16 val;
599} wm8961_clk_sys_ratio[] = {
600 { 64, 0 },
601 { 128, 1 },
602 { 192, 2 },
603 { 256, 3 },
604 { 384, 4 },
605 { 512, 5 },
606 { 768, 6 },
607 { 1024, 7 },
608 { 1408, 8 },
609 { 1536, 9 },
610};
611
612/* Values for SAMPLE_RATE */
613static struct {
614 int rate;
615 u16 val;
616} wm8961_srate[] = {
617 { 48000, 0 },
618 { 44100, 0 },
619 { 32000, 1 },
620 { 22050, 2 },
621 { 24000, 2 },
622 { 16000, 3 },
623 { 11250, 4 },
624 { 12000, 4 },
625 { 8000, 5 },
626};
627
628static int wm8961_hw_params(struct snd_pcm_substream *substream,
629 struct snd_pcm_hw_params *params,
630 struct snd_soc_dai *dai)
631{
632 struct snd_soc_codec *codec = dai->codec;
633 struct wm8961_priv *wm8961 = codec->private_data;
634 int i, best, target, fs;
635 u16 reg;
636
637 fs = params_rate(params);
638
639 if (!wm8961->sysclk) {
640 dev_err(codec->dev, "MCLK has not been specified\n");
641 return -EINVAL;
642 }
643
644 /* Find the closest sample rate for the filters */
645 best = 0;
646 for (i = 0; i < ARRAY_SIZE(wm8961_srate); i++) {
647 if (abs(wm8961_srate[i].rate - fs) <
648 abs(wm8961_srate[best].rate - fs))
649 best = i;
650 }
651 reg = snd_soc_read(codec, WM8961_ADDITIONAL_CONTROL_3);
652 reg &= ~WM8961_SAMPLE_RATE_MASK;
653 reg |= wm8961_srate[best].val;
654 snd_soc_write(codec, WM8961_ADDITIONAL_CONTROL_3, reg);
655 dev_dbg(codec->dev, "Selected SRATE %dHz for %dHz\n",
656 wm8961_srate[best].rate, fs);
657
658 /* Select a CLK_SYS/fs ratio equal to or higher than required */
659 target = wm8961->sysclk / fs;
660
661 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK && target < 64) {
662 dev_err(codec->dev,
663 "SYSCLK must be at least 64*fs for DAC\n");
664 return -EINVAL;
665 }
666 if (substream->stream == SNDRV_PCM_STREAM_CAPTURE && target < 256) {
667 dev_err(codec->dev,
668 "SYSCLK must be at least 256*fs for ADC\n");
669 return -EINVAL;
670 }
671
672 for (i = 0; i < ARRAY_SIZE(wm8961_clk_sys_ratio); i++) {
673 if (wm8961_clk_sys_ratio[i].ratio >= target)
674 break;
675 }
676 if (i == ARRAY_SIZE(wm8961_clk_sys_ratio)) {
677 dev_err(codec->dev, "Unable to generate CLK_SYS_RATE\n");
678 return -EINVAL;
679 }
680 dev_dbg(codec->dev, "Selected CLK_SYS_RATE of %d for %d/%d=%d\n",
681 wm8961_clk_sys_ratio[i].ratio, wm8961->sysclk, fs,
682 wm8961->sysclk / fs);
683
684 reg = snd_soc_read(codec, WM8961_CLOCKING_4);
685 reg &= ~WM8961_CLK_SYS_RATE_MASK;
686 reg |= wm8961_clk_sys_ratio[i].val << WM8961_CLK_SYS_RATE_SHIFT;
687 snd_soc_write(codec, WM8961_CLOCKING_4, reg);
688
689 reg = snd_soc_read(codec, WM8961_AUDIO_INTERFACE_0);
690 reg &= ~WM8961_WL_MASK;
691 switch (params_format(params)) {
692 case SNDRV_PCM_FORMAT_S16_LE:
693 break;
694 case SNDRV_PCM_FORMAT_S20_3LE:
695 reg |= 1 << WM8961_WL_SHIFT;
696 break;
697 case SNDRV_PCM_FORMAT_S24_LE:
698 reg |= 2 << WM8961_WL_SHIFT;
699 break;
700 case SNDRV_PCM_FORMAT_S32_LE:
701 reg |= 3 << WM8961_WL_SHIFT;
702 break;
703 default:
704 return -EINVAL;
705 }
706 snd_soc_write(codec, WM8961_AUDIO_INTERFACE_0, reg);
707
708 /* Sloping stop-band filter is recommended for <= 24kHz */
709 reg = snd_soc_read(codec, WM8961_ADC_DAC_CONTROL_2);
710 if (fs <= 24000)
711 reg |= WM8961_DACSLOPE;
712 else
713 reg &= WM8961_DACSLOPE;
714 snd_soc_write(codec, WM8961_ADC_DAC_CONTROL_2, reg);
715
716 return 0;
717}
718
719static int wm8961_set_sysclk(struct snd_soc_dai *dai, int clk_id,
720 unsigned int freq,
721 int dir)
722{
723 struct snd_soc_codec *codec = dai->codec;
724 struct wm8961_priv *wm8961 = codec->private_data;
725 u16 reg = snd_soc_read(codec, WM8961_CLOCKING1);
726
727 if (freq > 33000000) {
728 dev_err(codec->dev, "MCLK must be <33MHz\n");
729 return -EINVAL;
730 }
731
732 if (freq > 16500000) {
733 dev_dbg(codec->dev, "Using MCLK/2 for %dHz MCLK\n", freq);
734 reg |= WM8961_MCLKDIV;
735 freq /= 2;
736 } else {
737 dev_dbg(codec->dev, "Using MCLK/1 for %dHz MCLK\n", freq);
738 reg &= WM8961_MCLKDIV;
739 }
740
741 snd_soc_write(codec, WM8961_CLOCKING1, reg);
742
743 wm8961->sysclk = freq;
744
745 return 0;
746}
747
748static int wm8961_set_fmt(struct snd_soc_dai *dai, unsigned int fmt)
749{
750 struct snd_soc_codec *codec = dai->codec;
751 u16 aif = snd_soc_read(codec, WM8961_AUDIO_INTERFACE_0);
752
753 aif &= ~(WM8961_BCLKINV | WM8961_LRP |
754 WM8961_MS | WM8961_FORMAT_MASK);
755
756 switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
757 case SND_SOC_DAIFMT_CBM_CFM:
758 aif |= WM8961_MS;
759 break;
760 case SND_SOC_DAIFMT_CBS_CFS:
761 break;
762 default:
763 return -EINVAL;
764 }
765
766 switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
767 case SND_SOC_DAIFMT_RIGHT_J:
768 break;
769
770 case SND_SOC_DAIFMT_LEFT_J:
771 aif |= 1;
772 break;
773
774 case SND_SOC_DAIFMT_I2S:
775 aif |= 2;
776 break;
777
778 case SND_SOC_DAIFMT_DSP_B:
779 aif |= WM8961_LRP;
780 case SND_SOC_DAIFMT_DSP_A:
781 aif |= 3;
782 switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
783 case SND_SOC_DAIFMT_NB_NF:
784 case SND_SOC_DAIFMT_IB_NF:
785 break;
786 default:
787 return -EINVAL;
788 }
789 break;
790
791 default:
792 return -EINVAL;
793 }
794
795 switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
796 case SND_SOC_DAIFMT_NB_NF:
797 break;
798 case SND_SOC_DAIFMT_NB_IF:
799 aif |= WM8961_LRP;
800 break;
801 case SND_SOC_DAIFMT_IB_NF:
802 aif |= WM8961_BCLKINV;
803 break;
804 case SND_SOC_DAIFMT_IB_IF:
805 aif |= WM8961_BCLKINV | WM8961_LRP;
806 break;
807 default:
808 return -EINVAL;
809 }
810
811 return snd_soc_write(codec, WM8961_AUDIO_INTERFACE_0, aif);
812}
813
814static int wm8961_set_tristate(struct snd_soc_dai *dai, int tristate)
815{
816 struct snd_soc_codec *codec = dai->codec;
817 u16 reg = snd_soc_read(codec, WM8961_ADDITIONAL_CONTROL_2);
818
819 if (tristate)
820 reg |= WM8961_TRIS;
821 else
822 reg &= ~WM8961_TRIS;
823
824 return snd_soc_write(codec, WM8961_ADDITIONAL_CONTROL_2, reg);
825}
826
827static int wm8961_digital_mute(struct snd_soc_dai *dai, int mute)
828{
829 struct snd_soc_codec *codec = dai->codec;
830 u16 reg = snd_soc_read(codec, WM8961_ADC_DAC_CONTROL_1);
831
832 if (mute)
833 reg |= WM8961_DACMU;
834 else
835 reg &= ~WM8961_DACMU;
836
837 msleep(17);
838
839 return snd_soc_write(codec, WM8961_ADC_DAC_CONTROL_1, reg);
840}
841
842static int wm8961_set_clkdiv(struct snd_soc_dai *dai, int div_id, int div)
843{
844 struct snd_soc_codec *codec = dai->codec;
845 u16 reg;
846
847 switch (div_id) {
848 case WM8961_BCLK:
849 reg = snd_soc_read(codec, WM8961_CLOCKING2);
850 reg &= ~WM8961_BCLKDIV_MASK;
851 reg |= div;
852 snd_soc_write(codec, WM8961_CLOCKING2, reg);
853 break;
854
855 case WM8961_LRCLK:
856 reg = snd_soc_read(codec, WM8961_AUDIO_INTERFACE_2);
857 reg &= ~WM8961_LRCLK_RATE_MASK;
858 reg |= div;
859 snd_soc_write(codec, WM8961_AUDIO_INTERFACE_2, reg);
860 break;
861
862 default:
863 return -EINVAL;
864 }
865
866 return 0;
867}
868
869static int wm8961_set_bias_level(struct snd_soc_codec *codec,
870 enum snd_soc_bias_level level)
871{
872 u16 reg;
873
874 /* This is all slightly unusual since we have no bypass paths
875 * and the output amplifier structure means we can just slam
876 * the biases straight up rather than having to ramp them
877 * slowly.
878 */
879 switch (level) {
880 case SND_SOC_BIAS_ON:
881 break;
882
883 case SND_SOC_BIAS_PREPARE:
884 if (codec->bias_level == SND_SOC_BIAS_STANDBY) {
885 /* Enable bias generation */
886 reg = snd_soc_read(codec, WM8961_ANTI_POP);
887 reg |= WM8961_BUFIOEN | WM8961_BUFDCOPEN;
888 snd_soc_write(codec, WM8961_ANTI_POP, reg);
889
890 /* VMID=2*50k, VREF */
891 reg = snd_soc_read(codec, WM8961_PWR_MGMT_1);
892 reg &= ~WM8961_VMIDSEL_MASK;
893 reg |= (1 << WM8961_VMIDSEL_SHIFT) | WM8961_VREF;
894 snd_soc_write(codec, WM8961_PWR_MGMT_1, reg);
895 }
896 break;
897
898 case SND_SOC_BIAS_STANDBY:
899 if (codec->bias_level == SND_SOC_BIAS_PREPARE) {
900 /* VREF off */
901 reg = snd_soc_read(codec, WM8961_PWR_MGMT_1);
902 reg &= ~WM8961_VREF;
903 snd_soc_write(codec, WM8961_PWR_MGMT_1, reg);
904
905 /* Bias generation off */
906 reg = snd_soc_read(codec, WM8961_ANTI_POP);
907 reg &= ~(WM8961_BUFIOEN | WM8961_BUFDCOPEN);
908 snd_soc_write(codec, WM8961_ANTI_POP, reg);
909
910 /* VMID off */
911 reg = snd_soc_read(codec, WM8961_PWR_MGMT_1);
912 reg &= ~WM8961_VMIDSEL_MASK;
913 snd_soc_write(codec, WM8961_PWR_MGMT_1, reg);
914 }
915 break;
916
917 case SND_SOC_BIAS_OFF:
918 break;
919 }
920
921 codec->bias_level = level;
922
923 return 0;
924}
925
926
927#define WM8961_RATES SNDRV_PCM_RATE_8000_48000
928
929#define WM8961_FORMATS \
930 (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE | \
931 SNDRV_PCM_FMTBIT_S24_LE)
932
933static struct snd_soc_dai_ops wm8961_dai_ops = {
934 .hw_params = wm8961_hw_params,
935 .set_sysclk = wm8961_set_sysclk,
936 .set_fmt = wm8961_set_fmt,
937 .digital_mute = wm8961_digital_mute,
938 .set_tristate = wm8961_set_tristate,
939 .set_clkdiv = wm8961_set_clkdiv,
940};
941
942struct snd_soc_dai wm8961_dai = {
943 .name = "WM8961",
944 .playback = {
945 .stream_name = "HiFi Playback",
946 .channels_min = 1,
947 .channels_max = 2,
948 .rates = WM8961_RATES,
949 .formats = WM8961_FORMATS,},
950 .capture = {
951 .stream_name = "HiFi Capture",
952 .channels_min = 1,
953 .channels_max = 2,
954 .rates = WM8961_RATES,
955 .formats = WM8961_FORMATS,},
956 .ops = &wm8961_dai_ops,
957};
958EXPORT_SYMBOL_GPL(wm8961_dai);
959
960
961static struct snd_soc_codec *wm8961_codec;
962
963static int wm8961_probe(struct platform_device *pdev)
964{
965 struct snd_soc_device *socdev = platform_get_drvdata(pdev);
966 struct snd_soc_codec *codec;
967 int ret = 0;
968
969 if (wm8961_codec == NULL) {
970 dev_err(&pdev->dev, "Codec device not registered\n");
971 return -ENODEV;
972 }
973
974 socdev->card->codec = wm8961_codec;
975 codec = wm8961_codec;
976
977 /* register pcms */
978 ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1);
979 if (ret < 0) {
980 dev_err(codec->dev, "failed to create pcms: %d\n", ret);
981 goto pcm_err;
982 }
983
984 snd_soc_add_controls(codec, wm8961_snd_controls,
985 ARRAY_SIZE(wm8961_snd_controls));
986 snd_soc_dapm_new_controls(codec, wm8961_dapm_widgets,
987 ARRAY_SIZE(wm8961_dapm_widgets));
988 snd_soc_dapm_add_routes(codec, audio_paths, ARRAY_SIZE(audio_paths));
989 snd_soc_dapm_new_widgets(codec);
990
991 ret = snd_soc_init_card(socdev);
992 if (ret < 0) {
993 dev_err(codec->dev, "failed to register card: %d\n", ret);
994 goto card_err;
995 }
996
997 return ret;
998
999card_err:
1000 snd_soc_free_pcms(socdev);
1001 snd_soc_dapm_free(socdev);
1002pcm_err:
1003 return ret;
1004}
1005
1006static int wm8961_remove(struct platform_device *pdev)
1007{
1008 struct snd_soc_device *socdev = platform_get_drvdata(pdev);
1009
1010 snd_soc_free_pcms(socdev);
1011 snd_soc_dapm_free(socdev);
1012
1013 return 0;
1014}
1015
1016#ifdef CONFIG_PM
1017static int wm8961_suspend(struct platform_device *pdev, pm_message_t state)
1018{
1019 struct snd_soc_device *socdev = platform_get_drvdata(pdev);
1020 struct snd_soc_codec *codec = socdev->card->codec;
1021
1022 wm8961_set_bias_level(codec, SND_SOC_BIAS_OFF);
1023
1024 return 0;
1025}
1026
1027static int wm8961_resume(struct platform_device *pdev)
1028{
1029 struct snd_soc_device *socdev = platform_get_drvdata(pdev);
1030 struct snd_soc_codec *codec = socdev->card->codec;
1031 u16 *reg_cache = codec->reg_cache;
1032 int i;
1033
1034 for (i = 0; i < codec->reg_cache_size; i++) {
1035 if (i == WM8961_SOFTWARE_RESET)
1036 continue;
1037
1038 snd_soc_write(codec, i, reg_cache[i]);
1039 }
1040
1041 wm8961_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
1042
1043 return 0;
1044}
1045#else
1046#define wm8961_suspend NULL
1047#define wm8961_resume NULL
1048#endif
1049
1050struct snd_soc_codec_device soc_codec_dev_wm8961 = {
1051 .probe = wm8961_probe,
1052 .remove = wm8961_remove,
1053 .suspend = wm8961_suspend,
1054 .resume = wm8961_resume,
1055};
1056EXPORT_SYMBOL_GPL(soc_codec_dev_wm8961);
1057
1058static int wm8961_register(struct wm8961_priv *wm8961)
1059{
1060 struct snd_soc_codec *codec = &wm8961->codec;
1061 int ret;
1062 u16 reg;
1063
1064 if (wm8961_codec) {
1065 dev_err(codec->dev, "Another WM8961 is registered\n");
1066 ret = -EINVAL;
1067 goto err;
1068 }
1069
1070 mutex_init(&codec->mutex);
1071 INIT_LIST_HEAD(&codec->dapm_widgets);
1072 INIT_LIST_HEAD(&codec->dapm_paths);
1073
1074 codec->private_data = wm8961;
1075 codec->name = "WM8961";
1076 codec->owner = THIS_MODULE;
1077 codec->dai = &wm8961_dai;
1078 codec->num_dai = 1;
1079 codec->reg_cache_size = ARRAY_SIZE(wm8961->reg_cache);
1080 codec->reg_cache = &wm8961->reg_cache;
1081 codec->bias_level = SND_SOC_BIAS_OFF;
1082 codec->set_bias_level = wm8961_set_bias_level;
1083 codec->volatile_register = wm8961_volatile_register;
1084
1085 memcpy(codec->reg_cache, wm8961_reg_defaults,
1086 sizeof(wm8961_reg_defaults));
1087
1088 ret = snd_soc_codec_set_cache_io(codec, 8, 16, SND_SOC_I2C);
1089 if (ret != 0) {
1090 dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret);
1091 goto err;
1092 }
1093
1094 reg = snd_soc_read(codec, WM8961_SOFTWARE_RESET);
1095 if (reg != 0x1801) {
1096 dev_err(codec->dev, "Device is not a WM8961: ID=0x%x\n", reg);
1097 ret = -EINVAL;
1098 goto err;
1099 }
1100
1101 /* This isn't volatile - readback doesn't correspond to write */
1102 reg = codec->hw_read(codec, WM8961_RIGHT_INPUT_VOLUME);
1103 dev_info(codec->dev, "WM8961 family %d revision %c\n",
1104 (reg & WM8961_DEVICE_ID_MASK) >> WM8961_DEVICE_ID_SHIFT,
1105 ((reg & WM8961_CHIP_REV_MASK) >> WM8961_CHIP_REV_SHIFT)
1106 + 'A');
1107
1108 ret = wm8961_reset(codec);
1109 if (ret < 0) {
1110 dev_err(codec->dev, "Failed to issue reset\n");
1111 return ret;
1112 }
1113
1114 /* Enable class W */
1115 reg = snd_soc_read(codec, WM8961_CHARGE_PUMP_B);
1116 reg |= WM8961_CP_DYN_PWR_MASK;
1117 snd_soc_write(codec, WM8961_CHARGE_PUMP_B, reg);
1118
1119 /* Latch volume update bits (right channel only, we always
1120 * write both out) and default ZC on. */
1121 reg = snd_soc_read(codec, WM8961_ROUT1_VOLUME);
1122 snd_soc_write(codec, WM8961_ROUT1_VOLUME,
1123 reg | WM8961_LO1ZC | WM8961_OUT1VU);
1124 snd_soc_write(codec, WM8961_LOUT1_VOLUME, reg | WM8961_LO1ZC);
1125 reg = snd_soc_read(codec, WM8961_ROUT2_VOLUME);
1126 snd_soc_write(codec, WM8961_ROUT2_VOLUME,
1127 reg | WM8961_SPKRZC | WM8961_SPKVU);
1128 snd_soc_write(codec, WM8961_LOUT2_VOLUME, reg | WM8961_SPKLZC);
1129
1130 reg = snd_soc_read(codec, WM8961_RIGHT_ADC_VOLUME);
1131 snd_soc_write(codec, WM8961_RIGHT_ADC_VOLUME, reg | WM8961_ADCVU);
1132 reg = snd_soc_read(codec, WM8961_RIGHT_INPUT_VOLUME);
1133 snd_soc_write(codec, WM8961_RIGHT_INPUT_VOLUME, reg | WM8961_IPVU);
1134
1135 /* Use soft mute by default */
1136 reg = snd_soc_read(codec, WM8961_ADC_DAC_CONTROL_2);
1137 reg |= WM8961_DACSMM;
1138 snd_soc_write(codec, WM8961_ADC_DAC_CONTROL_2, reg);
1139
1140 /* Use automatic clocking mode by default; for now this is all
1141 * we support.
1142 */
1143 reg = snd_soc_read(codec, WM8961_CLOCKING_3);
1144 reg &= ~WM8961_MANUAL_MODE;
1145 snd_soc_write(codec, WM8961_CLOCKING_3, reg);
1146
1147 wm8961_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
1148
1149 wm8961_dai.dev = codec->dev;
1150
1151 wm8961_codec = codec;
1152
1153 ret = snd_soc_register_codec(codec);
1154 if (ret != 0) {
1155 dev_err(codec->dev, "Failed to register codec: %d\n", ret);
1156 return ret;
1157 }
1158
1159 ret = snd_soc_register_dai(&wm8961_dai);
1160 if (ret != 0) {
1161 dev_err(codec->dev, "Failed to register DAI: %d\n", ret);
1162 snd_soc_unregister_codec(codec);
1163 return ret;
1164 }
1165
1166 return 0;
1167
1168err:
1169 kfree(wm8961);
1170 return ret;
1171}
1172
1173static void wm8961_unregister(struct wm8961_priv *wm8961)
1174{
1175 wm8961_set_bias_level(&wm8961->codec, SND_SOC_BIAS_OFF);
1176 snd_soc_unregister_dai(&wm8961_dai);
1177 snd_soc_unregister_codec(&wm8961->codec);
1178 kfree(wm8961);
1179 wm8961_codec = NULL;
1180}
1181
1182static __devinit int wm8961_i2c_probe(struct i2c_client *i2c,
1183 const struct i2c_device_id *id)
1184{
1185 struct wm8961_priv *wm8961;
1186 struct snd_soc_codec *codec;
1187
1188 wm8961 = kzalloc(sizeof(struct wm8961_priv), GFP_KERNEL);
1189 if (wm8961 == NULL)
1190 return -ENOMEM;
1191
1192 codec = &wm8961->codec;
1193
1194 i2c_set_clientdata(i2c, wm8961);
1195 codec->control_data = i2c;
1196
1197 codec->dev = &i2c->dev;
1198
1199 return wm8961_register(wm8961);
1200}
1201
1202static __devexit int wm8961_i2c_remove(struct i2c_client *client)
1203{
1204 struct wm8961_priv *wm8961 = i2c_get_clientdata(client);
1205 wm8961_unregister(wm8961);
1206 return 0;
1207}
1208
1209#ifdef CONFIG_PM
1210static int wm8961_i2c_suspend(struct i2c_client *client, pm_message_t state)
1211{
1212 return snd_soc_suspend_device(&client->dev);
1213}
1214
1215static int wm8961_i2c_resume(struct i2c_client *client)
1216{
1217 return snd_soc_resume_device(&client->dev);
1218}
1219#else
1220#define wm8961_i2c_suspend NULL
1221#define wm8961_i2c_resume NULL
1222#endif
1223
1224static const struct i2c_device_id wm8961_i2c_id[] = {
1225 { "wm8961", 0 },
1226 { }
1227};
1228MODULE_DEVICE_TABLE(i2c, wm8961_i2c_id);
1229
1230static struct i2c_driver wm8961_i2c_driver = {
1231 .driver = {
1232 .name = "wm8961",
1233 .owner = THIS_MODULE,
1234 },
1235 .probe = wm8961_i2c_probe,
1236 .remove = __devexit_p(wm8961_i2c_remove),
1237 .suspend = wm8961_i2c_suspend,
1238 .resume = wm8961_i2c_resume,
1239 .id_table = wm8961_i2c_id,
1240};
1241
1242static int __init wm8961_modinit(void)
1243{
1244 int ret;
1245
1246 ret = i2c_add_driver(&wm8961_i2c_driver);
1247 if (ret != 0) {
1248 printk(KERN_ERR "Failed to register WM8961 I2C driver: %d\n",
1249 ret);
1250 }
1251
1252 return ret;
1253}
1254module_init(wm8961_modinit);
1255
1256static void __exit wm8961_exit(void)
1257{
1258 i2c_del_driver(&wm8961_i2c_driver);
1259}
1260module_exit(wm8961_exit);
1261
1262
1263MODULE_DESCRIPTION("ASoC WM8961 driver");
1264MODULE_AUTHOR("Mark Brown <broonie@opensource.wolfsonmicro.com>");
1265MODULE_LICENSE("GPL");
diff --git a/sound/soc/codecs/wm8961.h b/sound/soc/codecs/wm8961.h
new file mode 100644
index 000000000000..5513bfd720d6
--- /dev/null
+++ b/sound/soc/codecs/wm8961.h
@@ -0,0 +1,866 @@
1/*
2 * wm8961.h -- WM8961 Soc Audio driver
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License version 2 as
6 * published by the Free Software Foundation.
7 */
8
9#ifndef _WM8961_H
10#define _WM8961_H
11
12#include <sound/soc.h>
13
14extern struct snd_soc_codec_device soc_codec_dev_wm8961;
15extern struct snd_soc_dai wm8961_dai;
16
17#define WM8961_BCLK 1
18#define WM8961_LRCLK 2
19
20#define WM8961_BCLK_DIV_1 0
21#define WM8961_BCLK_DIV_1_5 1
22#define WM8961_BCLK_DIV_2 2
23#define WM8961_BCLK_DIV_3 3
24#define WM8961_BCLK_DIV_4 4
25#define WM8961_BCLK_DIV_5_5 5
26#define WM8961_BCLK_DIV_6 6
27#define WM8961_BCLK_DIV_8 7
28#define WM8961_BCLK_DIV_11 8
29#define WM8961_BCLK_DIV_12 9
30#define WM8961_BCLK_DIV_16 10
31#define WM8961_BCLK_DIV_24 11
32#define WM8961_BCLK_DIV_32 13
33
34
35/*
36 * Register values.
37 */
38#define WM8961_LEFT_INPUT_VOLUME 0x00
39#define WM8961_RIGHT_INPUT_VOLUME 0x01
40#define WM8961_LOUT1_VOLUME 0x02
41#define WM8961_ROUT1_VOLUME 0x03
42#define WM8961_CLOCKING1 0x04
43#define WM8961_ADC_DAC_CONTROL_1 0x05
44#define WM8961_ADC_DAC_CONTROL_2 0x06
45#define WM8961_AUDIO_INTERFACE_0 0x07
46#define WM8961_CLOCKING2 0x08
47#define WM8961_AUDIO_INTERFACE_1 0x09
48#define WM8961_LEFT_DAC_VOLUME 0x0A
49#define WM8961_RIGHT_DAC_VOLUME 0x0B
50#define WM8961_AUDIO_INTERFACE_2 0x0E
51#define WM8961_SOFTWARE_RESET 0x0F
52#define WM8961_ALC1 0x11
53#define WM8961_ALC2 0x12
54#define WM8961_ALC3 0x13
55#define WM8961_NOISE_GATE 0x14
56#define WM8961_LEFT_ADC_VOLUME 0x15
57#define WM8961_RIGHT_ADC_VOLUME 0x16
58#define WM8961_ADDITIONAL_CONTROL_1 0x17
59#define WM8961_ADDITIONAL_CONTROL_2 0x18
60#define WM8961_PWR_MGMT_1 0x19
61#define WM8961_PWR_MGMT_2 0x1A
62#define WM8961_ADDITIONAL_CONTROL_3 0x1B
63#define WM8961_ANTI_POP 0x1C
64#define WM8961_CLOCKING_3 0x1E
65#define WM8961_ADCL_SIGNAL_PATH 0x20
66#define WM8961_ADCR_SIGNAL_PATH 0x21
67#define WM8961_LOUT2_VOLUME 0x28
68#define WM8961_ROUT2_VOLUME 0x29
69#define WM8961_PWR_MGMT_3 0x2F
70#define WM8961_ADDITIONAL_CONTROL_4 0x30
71#define WM8961_CLASS_D_CONTROL_1 0x31
72#define WM8961_CLASS_D_CONTROL_2 0x33
73#define WM8961_CLOCKING_4 0x38
74#define WM8961_DSP_SIDETONE_0 0x39
75#define WM8961_DSP_SIDETONE_1 0x3A
76#define WM8961_DC_SERVO_0 0x3C
77#define WM8961_DC_SERVO_1 0x3D
78#define WM8961_DC_SERVO_3 0x3F
79#define WM8961_DC_SERVO_5 0x41
80#define WM8961_ANALOGUE_PGA_BIAS 0x44
81#define WM8961_ANALOGUE_HP_0 0x45
82#define WM8961_ANALOGUE_HP_2 0x47
83#define WM8961_CHARGE_PUMP_1 0x48
84#define WM8961_CHARGE_PUMP_B 0x52
85#define WM8961_WRITE_SEQUENCER_1 0x57
86#define WM8961_WRITE_SEQUENCER_2 0x58
87#define WM8961_WRITE_SEQUENCER_3 0x59
88#define WM8961_WRITE_SEQUENCER_4 0x5A
89#define WM8961_WRITE_SEQUENCER_5 0x5B
90#define WM8961_WRITE_SEQUENCER_6 0x5C
91#define WM8961_WRITE_SEQUENCER_7 0x5D
92#define WM8961_GENERAL_TEST_1 0xFC
93
94
95/*
96 * Field Definitions.
97 */
98
99/*
100 * R0 (0x00) - Left Input volume
101 */
102#define WM8961_IPVU 0x0100 /* IPVU */
103#define WM8961_IPVU_MASK 0x0100 /* IPVU */
104#define WM8961_IPVU_SHIFT 8 /* IPVU */
105#define WM8961_IPVU_WIDTH 1 /* IPVU */
106#define WM8961_LINMUTE 0x0080 /* LINMUTE */
107#define WM8961_LINMUTE_MASK 0x0080 /* LINMUTE */
108#define WM8961_LINMUTE_SHIFT 7 /* LINMUTE */
109#define WM8961_LINMUTE_WIDTH 1 /* LINMUTE */
110#define WM8961_LIZC 0x0040 /* LIZC */
111#define WM8961_LIZC_MASK 0x0040 /* LIZC */
112#define WM8961_LIZC_SHIFT 6 /* LIZC */
113#define WM8961_LIZC_WIDTH 1 /* LIZC */
114#define WM8961_LINVOL_MASK 0x003F /* LINVOL - [5:0] */
115#define WM8961_LINVOL_SHIFT 0 /* LINVOL - [5:0] */
116#define WM8961_LINVOL_WIDTH 6 /* LINVOL - [5:0] */
117
118/*
119 * R1 (0x01) - Right Input volume
120 */
121#define WM8961_DEVICE_ID_MASK 0xF000 /* DEVICE_ID - [15:12] */
122#define WM8961_DEVICE_ID_SHIFT 12 /* DEVICE_ID - [15:12] */
123#define WM8961_DEVICE_ID_WIDTH 4 /* DEVICE_ID - [15:12] */
124#define WM8961_CHIP_REV_MASK 0x0E00 /* CHIP_REV - [11:9] */
125#define WM8961_CHIP_REV_SHIFT 9 /* CHIP_REV - [11:9] */
126#define WM8961_CHIP_REV_WIDTH 3 /* CHIP_REV - [11:9] */
127#define WM8961_IPVU 0x0100 /* IPVU */
128#define WM8961_IPVU_MASK 0x0100 /* IPVU */
129#define WM8961_IPVU_SHIFT 8 /* IPVU */
130#define WM8961_IPVU_WIDTH 1 /* IPVU */
131#define WM8961_RINMUTE 0x0080 /* RINMUTE */
132#define WM8961_RINMUTE_MASK 0x0080 /* RINMUTE */
133#define WM8961_RINMUTE_SHIFT 7 /* RINMUTE */
134#define WM8961_RINMUTE_WIDTH 1 /* RINMUTE */
135#define WM8961_RIZC 0x0040 /* RIZC */
136#define WM8961_RIZC_MASK 0x0040 /* RIZC */
137#define WM8961_RIZC_SHIFT 6 /* RIZC */
138#define WM8961_RIZC_WIDTH 1 /* RIZC */
139#define WM8961_RINVOL_MASK 0x003F /* RINVOL - [5:0] */
140#define WM8961_RINVOL_SHIFT 0 /* RINVOL - [5:0] */
141#define WM8961_RINVOL_WIDTH 6 /* RINVOL - [5:0] */
142
143/*
144 * R2 (0x02) - LOUT1 volume
145 */
146#define WM8961_OUT1VU 0x0100 /* OUT1VU */
147#define WM8961_OUT1VU_MASK 0x0100 /* OUT1VU */
148#define WM8961_OUT1VU_SHIFT 8 /* OUT1VU */
149#define WM8961_OUT1VU_WIDTH 1 /* OUT1VU */
150#define WM8961_LO1ZC 0x0080 /* LO1ZC */
151#define WM8961_LO1ZC_MASK 0x0080 /* LO1ZC */
152#define WM8961_LO1ZC_SHIFT 7 /* LO1ZC */
153#define WM8961_LO1ZC_WIDTH 1 /* LO1ZC */
154#define WM8961_LOUT1VOL_MASK 0x007F /* LOUT1VOL - [6:0] */
155#define WM8961_LOUT1VOL_SHIFT 0 /* LOUT1VOL - [6:0] */
156#define WM8961_LOUT1VOL_WIDTH 7 /* LOUT1VOL - [6:0] */
157
158/*
159 * R3 (0x03) - ROUT1 volume
160 */
161#define WM8961_OUT1VU 0x0100 /* OUT1VU */
162#define WM8961_OUT1VU_MASK 0x0100 /* OUT1VU */
163#define WM8961_OUT1VU_SHIFT 8 /* OUT1VU */
164#define WM8961_OUT1VU_WIDTH 1 /* OUT1VU */
165#define WM8961_RO1ZC 0x0080 /* RO1ZC */
166#define WM8961_RO1ZC_MASK 0x0080 /* RO1ZC */
167#define WM8961_RO1ZC_SHIFT 7 /* RO1ZC */
168#define WM8961_RO1ZC_WIDTH 1 /* RO1ZC */
169#define WM8961_ROUT1VOL_MASK 0x007F /* ROUT1VOL - [6:0] */
170#define WM8961_ROUT1VOL_SHIFT 0 /* ROUT1VOL - [6:0] */
171#define WM8961_ROUT1VOL_WIDTH 7 /* ROUT1VOL - [6:0] */
172
173/*
174 * R4 (0x04) - Clocking1
175 */
176#define WM8961_ADCDIV_MASK 0x01C0 /* ADCDIV - [8:6] */
177#define WM8961_ADCDIV_SHIFT 6 /* ADCDIV - [8:6] */
178#define WM8961_ADCDIV_WIDTH 3 /* ADCDIV - [8:6] */
179#define WM8961_DACDIV_MASK 0x0038 /* DACDIV - [5:3] */
180#define WM8961_DACDIV_SHIFT 3 /* DACDIV - [5:3] */
181#define WM8961_DACDIV_WIDTH 3 /* DACDIV - [5:3] */
182#define WM8961_MCLKDIV 0x0004 /* MCLKDIV */
183#define WM8961_MCLKDIV_MASK 0x0004 /* MCLKDIV */
184#define WM8961_MCLKDIV_SHIFT 2 /* MCLKDIV */
185#define WM8961_MCLKDIV_WIDTH 1 /* MCLKDIV */
186
187/*
188 * R5 (0x05) - ADC & DAC Control 1
189 */
190#define WM8961_ADCPOL_MASK 0x0060 /* ADCPOL - [6:5] */
191#define WM8961_ADCPOL_SHIFT 5 /* ADCPOL - [6:5] */
192#define WM8961_ADCPOL_WIDTH 2 /* ADCPOL - [6:5] */
193#define WM8961_DACMU 0x0008 /* DACMU */
194#define WM8961_DACMU_MASK 0x0008 /* DACMU */
195#define WM8961_DACMU_SHIFT 3 /* DACMU */
196#define WM8961_DACMU_WIDTH 1 /* DACMU */
197#define WM8961_DEEMPH_MASK 0x0006 /* DEEMPH - [2:1] */
198#define WM8961_DEEMPH_SHIFT 1 /* DEEMPH - [2:1] */
199#define WM8961_DEEMPH_WIDTH 2 /* DEEMPH - [2:1] */
200#define WM8961_ADCHPD 0x0001 /* ADCHPD */
201#define WM8961_ADCHPD_MASK 0x0001 /* ADCHPD */
202#define WM8961_ADCHPD_SHIFT 0 /* ADCHPD */
203#define WM8961_ADCHPD_WIDTH 1 /* ADCHPD */
204
205/*
206 * R6 (0x06) - ADC & DAC Control 2
207 */
208#define WM8961_ADC_HPF_CUT_MASK 0x0180 /* ADC_HPF_CUT - [8:7] */
209#define WM8961_ADC_HPF_CUT_SHIFT 7 /* ADC_HPF_CUT - [8:7] */
210#define WM8961_ADC_HPF_CUT_WIDTH 2 /* ADC_HPF_CUT - [8:7] */
211#define WM8961_DACPOL_MASK 0x0060 /* DACPOL - [6:5] */
212#define WM8961_DACPOL_SHIFT 5 /* DACPOL - [6:5] */
213#define WM8961_DACPOL_WIDTH 2 /* DACPOL - [6:5] */
214#define WM8961_DACSMM 0x0008 /* DACSMM */
215#define WM8961_DACSMM_MASK 0x0008 /* DACSMM */
216#define WM8961_DACSMM_SHIFT 3 /* DACSMM */
217#define WM8961_DACSMM_WIDTH 1 /* DACSMM */
218#define WM8961_DACMR 0x0004 /* DACMR */
219#define WM8961_DACMR_MASK 0x0004 /* DACMR */
220#define WM8961_DACMR_SHIFT 2 /* DACMR */
221#define WM8961_DACMR_WIDTH 1 /* DACMR */
222#define WM8961_DACSLOPE 0x0002 /* DACSLOPE */
223#define WM8961_DACSLOPE_MASK 0x0002 /* DACSLOPE */
224#define WM8961_DACSLOPE_SHIFT 1 /* DACSLOPE */
225#define WM8961_DACSLOPE_WIDTH 1 /* DACSLOPE */
226#define WM8961_DAC_OSR128 0x0001 /* DAC_OSR128 */
227#define WM8961_DAC_OSR128_MASK 0x0001 /* DAC_OSR128 */
228#define WM8961_DAC_OSR128_SHIFT 0 /* DAC_OSR128 */
229#define WM8961_DAC_OSR128_WIDTH 1 /* DAC_OSR128 */
230
231/*
232 * R7 (0x07) - Audio Interface 0
233 */
234#define WM8961_ALRSWAP 0x0100 /* ALRSWAP */
235#define WM8961_ALRSWAP_MASK 0x0100 /* ALRSWAP */
236#define WM8961_ALRSWAP_SHIFT 8 /* ALRSWAP */
237#define WM8961_ALRSWAP_WIDTH 1 /* ALRSWAP */
238#define WM8961_BCLKINV 0x0080 /* BCLKINV */
239#define WM8961_BCLKINV_MASK 0x0080 /* BCLKINV */
240#define WM8961_BCLKINV_SHIFT 7 /* BCLKINV */
241#define WM8961_BCLKINV_WIDTH 1 /* BCLKINV */
242#define WM8961_MS 0x0040 /* MS */
243#define WM8961_MS_MASK 0x0040 /* MS */
244#define WM8961_MS_SHIFT 6 /* MS */
245#define WM8961_MS_WIDTH 1 /* MS */
246#define WM8961_DLRSWAP 0x0020 /* DLRSWAP */
247#define WM8961_DLRSWAP_MASK 0x0020 /* DLRSWAP */
248#define WM8961_DLRSWAP_SHIFT 5 /* DLRSWAP */
249#define WM8961_DLRSWAP_WIDTH 1 /* DLRSWAP */
250#define WM8961_LRP 0x0010 /* LRP */
251#define WM8961_LRP_MASK 0x0010 /* LRP */
252#define WM8961_LRP_SHIFT 4 /* LRP */
253#define WM8961_LRP_WIDTH 1 /* LRP */
254#define WM8961_WL_MASK 0x000C /* WL - [3:2] */
255#define WM8961_WL_SHIFT 2 /* WL - [3:2] */
256#define WM8961_WL_WIDTH 2 /* WL - [3:2] */
257#define WM8961_FORMAT_MASK 0x0003 /* FORMAT - [1:0] */
258#define WM8961_FORMAT_SHIFT 0 /* FORMAT - [1:0] */
259#define WM8961_FORMAT_WIDTH 2 /* FORMAT - [1:0] */
260
261/*
262 * R8 (0x08) - Clocking2
263 */
264#define WM8961_DCLKDIV_MASK 0x01C0 /* DCLKDIV - [8:6] */
265#define WM8961_DCLKDIV_SHIFT 6 /* DCLKDIV - [8:6] */
266#define WM8961_DCLKDIV_WIDTH 3 /* DCLKDIV - [8:6] */
267#define WM8961_CLK_SYS_ENA 0x0020 /* CLK_SYS_ENA */
268#define WM8961_CLK_SYS_ENA_MASK 0x0020 /* CLK_SYS_ENA */
269#define WM8961_CLK_SYS_ENA_SHIFT 5 /* CLK_SYS_ENA */
270#define WM8961_CLK_SYS_ENA_WIDTH 1 /* CLK_SYS_ENA */
271#define WM8961_CLK_DSP_ENA 0x0010 /* CLK_DSP_ENA */
272#define WM8961_CLK_DSP_ENA_MASK 0x0010 /* CLK_DSP_ENA */
273#define WM8961_CLK_DSP_ENA_SHIFT 4 /* CLK_DSP_ENA */
274#define WM8961_CLK_DSP_ENA_WIDTH 1 /* CLK_DSP_ENA */
275#define WM8961_BCLKDIV_MASK 0x000F /* BCLKDIV - [3:0] */
276#define WM8961_BCLKDIV_SHIFT 0 /* BCLKDIV - [3:0] */
277#define WM8961_BCLKDIV_WIDTH 4 /* BCLKDIV - [3:0] */
278
279/*
280 * R9 (0x09) - Audio Interface 1
281 */
282#define WM8961_DACCOMP_MASK 0x0018 /* DACCOMP - [4:3] */
283#define WM8961_DACCOMP_SHIFT 3 /* DACCOMP - [4:3] */
284#define WM8961_DACCOMP_WIDTH 2 /* DACCOMP - [4:3] */
285#define WM8961_ADCCOMP_MASK 0x0006 /* ADCCOMP - [2:1] */
286#define WM8961_ADCCOMP_SHIFT 1 /* ADCCOMP - [2:1] */
287#define WM8961_ADCCOMP_WIDTH 2 /* ADCCOMP - [2:1] */
288#define WM8961_LOOPBACK 0x0001 /* LOOPBACK */
289#define WM8961_LOOPBACK_MASK 0x0001 /* LOOPBACK */
290#define WM8961_LOOPBACK_SHIFT 0 /* LOOPBACK */
291#define WM8961_LOOPBACK_WIDTH 1 /* LOOPBACK */
292
293/*
294 * R10 (0x0A) - Left DAC volume
295 */
296#define WM8961_DACVU 0x0100 /* DACVU */
297#define WM8961_DACVU_MASK 0x0100 /* DACVU */
298#define WM8961_DACVU_SHIFT 8 /* DACVU */
299#define WM8961_DACVU_WIDTH 1 /* DACVU */
300#define WM8961_LDACVOL_MASK 0x00FF /* LDACVOL - [7:0] */
301#define WM8961_LDACVOL_SHIFT 0 /* LDACVOL - [7:0] */
302#define WM8961_LDACVOL_WIDTH 8 /* LDACVOL - [7:0] */
303
304/*
305 * R11 (0x0B) - Right DAC volume
306 */
307#define WM8961_DACVU 0x0100 /* DACVU */
308#define WM8961_DACVU_MASK 0x0100 /* DACVU */
309#define WM8961_DACVU_SHIFT 8 /* DACVU */
310#define WM8961_DACVU_WIDTH 1 /* DACVU */
311#define WM8961_RDACVOL_MASK 0x00FF /* RDACVOL - [7:0] */
312#define WM8961_RDACVOL_SHIFT 0 /* RDACVOL - [7:0] */
313#define WM8961_RDACVOL_WIDTH 8 /* RDACVOL - [7:0] */
314
315/*
316 * R14 (0x0E) - Audio Interface 2
317 */
318#define WM8961_LRCLK_RATE_MASK 0x01FF /* LRCLK_RATE - [8:0] */
319#define WM8961_LRCLK_RATE_SHIFT 0 /* LRCLK_RATE - [8:0] */
320#define WM8961_LRCLK_RATE_WIDTH 9 /* LRCLK_RATE - [8:0] */
321
322/*
323 * R15 (0x0F) - Software Reset
324 */
325#define WM8961_SW_RST_DEV_ID1_MASK 0xFFFF /* SW_RST_DEV_ID1 - [15:0] */
326#define WM8961_SW_RST_DEV_ID1_SHIFT 0 /* SW_RST_DEV_ID1 - [15:0] */
327#define WM8961_SW_RST_DEV_ID1_WIDTH 16 /* SW_RST_DEV_ID1 - [15:0] */
328
329/*
330 * R17 (0x11) - ALC1
331 */
332#define WM8961_ALCSEL_MASK 0x0180 /* ALCSEL - [8:7] */
333#define WM8961_ALCSEL_SHIFT 7 /* ALCSEL - [8:7] */
334#define WM8961_ALCSEL_WIDTH 2 /* ALCSEL - [8:7] */
335#define WM8961_MAXGAIN_MASK 0x0070 /* MAXGAIN - [6:4] */
336#define WM8961_MAXGAIN_SHIFT 4 /* MAXGAIN - [6:4] */
337#define WM8961_MAXGAIN_WIDTH 3 /* MAXGAIN - [6:4] */
338#define WM8961_ALCL_MASK 0x000F /* ALCL - [3:0] */
339#define WM8961_ALCL_SHIFT 0 /* ALCL - [3:0] */
340#define WM8961_ALCL_WIDTH 4 /* ALCL - [3:0] */
341
342/*
343 * R18 (0x12) - ALC2
344 */
345#define WM8961_ALCZC 0x0080 /* ALCZC */
346#define WM8961_ALCZC_MASK 0x0080 /* ALCZC */
347#define WM8961_ALCZC_SHIFT 7 /* ALCZC */
348#define WM8961_ALCZC_WIDTH 1 /* ALCZC */
349#define WM8961_MINGAIN_MASK 0x0070 /* MINGAIN - [6:4] */
350#define WM8961_MINGAIN_SHIFT 4 /* MINGAIN - [6:4] */
351#define WM8961_MINGAIN_WIDTH 3 /* MINGAIN - [6:4] */
352#define WM8961_HLD_MASK 0x000F /* HLD - [3:0] */
353#define WM8961_HLD_SHIFT 0 /* HLD - [3:0] */
354#define WM8961_HLD_WIDTH 4 /* HLD - [3:0] */
355
356/*
357 * R19 (0x13) - ALC3
358 */
359#define WM8961_ALCMODE 0x0100 /* ALCMODE */
360#define WM8961_ALCMODE_MASK 0x0100 /* ALCMODE */
361#define WM8961_ALCMODE_SHIFT 8 /* ALCMODE */
362#define WM8961_ALCMODE_WIDTH 1 /* ALCMODE */
363#define WM8961_DCY_MASK 0x00F0 /* DCY - [7:4] */
364#define WM8961_DCY_SHIFT 4 /* DCY - [7:4] */
365#define WM8961_DCY_WIDTH 4 /* DCY - [7:4] */
366#define WM8961_ATK_MASK 0x000F /* ATK - [3:0] */
367#define WM8961_ATK_SHIFT 0 /* ATK - [3:0] */
368#define WM8961_ATK_WIDTH 4 /* ATK - [3:0] */
369
370/*
371 * R20 (0x14) - Noise Gate
372 */
373#define WM8961_NGTH_MASK 0x00F8 /* NGTH - [7:3] */
374#define WM8961_NGTH_SHIFT 3 /* NGTH - [7:3] */
375#define WM8961_NGTH_WIDTH 5 /* NGTH - [7:3] */
376#define WM8961_NGG 0x0002 /* NGG */
377#define WM8961_NGG_MASK 0x0002 /* NGG */
378#define WM8961_NGG_SHIFT 1 /* NGG */
379#define WM8961_NGG_WIDTH 1 /* NGG */
380#define WM8961_NGAT 0x0001 /* NGAT */
381#define WM8961_NGAT_MASK 0x0001 /* NGAT */
382#define WM8961_NGAT_SHIFT 0 /* NGAT */
383#define WM8961_NGAT_WIDTH 1 /* NGAT */
384
385/*
386 * R21 (0x15) - Left ADC volume
387 */
388#define WM8961_ADCVU 0x0100 /* ADCVU */
389#define WM8961_ADCVU_MASK 0x0100 /* ADCVU */
390#define WM8961_ADCVU_SHIFT 8 /* ADCVU */
391#define WM8961_ADCVU_WIDTH 1 /* ADCVU */
392#define WM8961_LADCVOL_MASK 0x00FF /* LADCVOL - [7:0] */
393#define WM8961_LADCVOL_SHIFT 0 /* LADCVOL - [7:0] */
394#define WM8961_LADCVOL_WIDTH 8 /* LADCVOL - [7:0] */
395
396/*
397 * R22 (0x16) - Right ADC volume
398 */
399#define WM8961_ADCVU 0x0100 /* ADCVU */
400#define WM8961_ADCVU_MASK 0x0100 /* ADCVU */
401#define WM8961_ADCVU_SHIFT 8 /* ADCVU */
402#define WM8961_ADCVU_WIDTH 1 /* ADCVU */
403#define WM8961_RADCVOL_MASK 0x00FF /* RADCVOL - [7:0] */
404#define WM8961_RADCVOL_SHIFT 0 /* RADCVOL - [7:0] */
405#define WM8961_RADCVOL_WIDTH 8 /* RADCVOL - [7:0] */
406
407/*
408 * R23 (0x17) - Additional control(1)
409 */
410#define WM8961_TSDEN 0x0100 /* TSDEN */
411#define WM8961_TSDEN_MASK 0x0100 /* TSDEN */
412#define WM8961_TSDEN_SHIFT 8 /* TSDEN */
413#define WM8961_TSDEN_WIDTH 1 /* TSDEN */
414#define WM8961_DMONOMIX 0x0010 /* DMONOMIX */
415#define WM8961_DMONOMIX_MASK 0x0010 /* DMONOMIX */
416#define WM8961_DMONOMIX_SHIFT 4 /* DMONOMIX */
417#define WM8961_DMONOMIX_WIDTH 1 /* DMONOMIX */
418#define WM8961_TOEN 0x0001 /* TOEN */
419#define WM8961_TOEN_MASK 0x0001 /* TOEN */
420#define WM8961_TOEN_SHIFT 0 /* TOEN */
421#define WM8961_TOEN_WIDTH 1 /* TOEN */
422
423/*
424 * R24 (0x18) - Additional control(2)
425 */
426#define WM8961_TRIS 0x0008 /* TRIS */
427#define WM8961_TRIS_MASK 0x0008 /* TRIS */
428#define WM8961_TRIS_SHIFT 3 /* TRIS */
429#define WM8961_TRIS_WIDTH 1 /* TRIS */
430
431/*
432 * R25 (0x19) - Pwr Mgmt (1)
433 */
434#define WM8961_VMIDSEL_MASK 0x0180 /* VMIDSEL - [8:7] */
435#define WM8961_VMIDSEL_SHIFT 7 /* VMIDSEL - [8:7] */
436#define WM8961_VMIDSEL_WIDTH 2 /* VMIDSEL - [8:7] */
437#define WM8961_VREF 0x0040 /* VREF */
438#define WM8961_VREF_MASK 0x0040 /* VREF */
439#define WM8961_VREF_SHIFT 6 /* VREF */
440#define WM8961_VREF_WIDTH 1 /* VREF */
441#define WM8961_AINL 0x0020 /* AINL */
442#define WM8961_AINL_MASK 0x0020 /* AINL */
443#define WM8961_AINL_SHIFT 5 /* AINL */
444#define WM8961_AINL_WIDTH 1 /* AINL */
445#define WM8961_AINR 0x0010 /* AINR */
446#define WM8961_AINR_MASK 0x0010 /* AINR */
447#define WM8961_AINR_SHIFT 4 /* AINR */
448#define WM8961_AINR_WIDTH 1 /* AINR */
449#define WM8961_ADCL 0x0008 /* ADCL */
450#define WM8961_ADCL_MASK 0x0008 /* ADCL */
451#define WM8961_ADCL_SHIFT 3 /* ADCL */
452#define WM8961_ADCL_WIDTH 1 /* ADCL */
453#define WM8961_ADCR 0x0004 /* ADCR */
454#define WM8961_ADCR_MASK 0x0004 /* ADCR */
455#define WM8961_ADCR_SHIFT 2 /* ADCR */
456#define WM8961_ADCR_WIDTH 1 /* ADCR */
457#define WM8961_MICB 0x0002 /* MICB */
458#define WM8961_MICB_MASK 0x0002 /* MICB */
459#define WM8961_MICB_SHIFT 1 /* MICB */
460#define WM8961_MICB_WIDTH 1 /* MICB */
461
462/*
463 * R26 (0x1A) - Pwr Mgmt (2)
464 */
465#define WM8961_DACL 0x0100 /* DACL */
466#define WM8961_DACL_MASK 0x0100 /* DACL */
467#define WM8961_DACL_SHIFT 8 /* DACL */
468#define WM8961_DACL_WIDTH 1 /* DACL */
469#define WM8961_DACR 0x0080 /* DACR */
470#define WM8961_DACR_MASK 0x0080 /* DACR */
471#define WM8961_DACR_SHIFT 7 /* DACR */
472#define WM8961_DACR_WIDTH 1 /* DACR */
473#define WM8961_LOUT1_PGA 0x0040 /* LOUT1_PGA */
474#define WM8961_LOUT1_PGA_MASK 0x0040 /* LOUT1_PGA */
475#define WM8961_LOUT1_PGA_SHIFT 6 /* LOUT1_PGA */
476#define WM8961_LOUT1_PGA_WIDTH 1 /* LOUT1_PGA */
477#define WM8961_ROUT1_PGA 0x0020 /* ROUT1_PGA */
478#define WM8961_ROUT1_PGA_MASK 0x0020 /* ROUT1_PGA */
479#define WM8961_ROUT1_PGA_SHIFT 5 /* ROUT1_PGA */
480#define WM8961_ROUT1_PGA_WIDTH 1 /* ROUT1_PGA */
481#define WM8961_SPKL_PGA 0x0010 /* SPKL_PGA */
482#define WM8961_SPKL_PGA_MASK 0x0010 /* SPKL_PGA */
483#define WM8961_SPKL_PGA_SHIFT 4 /* SPKL_PGA */
484#define WM8961_SPKL_PGA_WIDTH 1 /* SPKL_PGA */
485#define WM8961_SPKR_PGA 0x0008 /* SPKR_PGA */
486#define WM8961_SPKR_PGA_MASK 0x0008 /* SPKR_PGA */
487#define WM8961_SPKR_PGA_SHIFT 3 /* SPKR_PGA */
488#define WM8961_SPKR_PGA_WIDTH 1 /* SPKR_PGA */
489
490/*
491 * R27 (0x1B) - Additional Control (3)
492 */
493#define WM8961_SAMPLE_RATE_MASK 0x0007 /* SAMPLE_RATE - [2:0] */
494#define WM8961_SAMPLE_RATE_SHIFT 0 /* SAMPLE_RATE - [2:0] */
495#define WM8961_SAMPLE_RATE_WIDTH 3 /* SAMPLE_RATE - [2:0] */
496
497/*
498 * R28 (0x1C) - Anti-pop
499 */
500#define WM8961_BUFDCOPEN 0x0010 /* BUFDCOPEN */
501#define WM8961_BUFDCOPEN_MASK 0x0010 /* BUFDCOPEN */
502#define WM8961_BUFDCOPEN_SHIFT 4 /* BUFDCOPEN */
503#define WM8961_BUFDCOPEN_WIDTH 1 /* BUFDCOPEN */
504#define WM8961_BUFIOEN 0x0008 /* BUFIOEN */
505#define WM8961_BUFIOEN_MASK 0x0008 /* BUFIOEN */
506#define WM8961_BUFIOEN_SHIFT 3 /* BUFIOEN */
507#define WM8961_BUFIOEN_WIDTH 1 /* BUFIOEN */
508#define WM8961_SOFT_ST 0x0004 /* SOFT_ST */
509#define WM8961_SOFT_ST_MASK 0x0004 /* SOFT_ST */
510#define WM8961_SOFT_ST_SHIFT 2 /* SOFT_ST */
511#define WM8961_SOFT_ST_WIDTH 1 /* SOFT_ST */
512
513/*
514 * R30 (0x1E) - Clocking 3
515 */
516#define WM8961_CLK_TO_DIV_MASK 0x0180 /* CLK_TO_DIV - [8:7] */
517#define WM8961_CLK_TO_DIV_SHIFT 7 /* CLK_TO_DIV - [8:7] */
518#define WM8961_CLK_TO_DIV_WIDTH 2 /* CLK_TO_DIV - [8:7] */
519#define WM8961_CLK_256K_DIV_MASK 0x007E /* CLK_256K_DIV - [6:1] */
520#define WM8961_CLK_256K_DIV_SHIFT 1 /* CLK_256K_DIV - [6:1] */
521#define WM8961_CLK_256K_DIV_WIDTH 6 /* CLK_256K_DIV - [6:1] */
522#define WM8961_MANUAL_MODE 0x0001 /* MANUAL_MODE */
523#define WM8961_MANUAL_MODE_MASK 0x0001 /* MANUAL_MODE */
524#define WM8961_MANUAL_MODE_SHIFT 0 /* MANUAL_MODE */
525#define WM8961_MANUAL_MODE_WIDTH 1 /* MANUAL_MODE */
526
527/*
528 * R32 (0x20) - ADCL signal path
529 */
530#define WM8961_LMICBOOST_MASK 0x0030 /* LMICBOOST - [5:4] */
531#define WM8961_LMICBOOST_SHIFT 4 /* LMICBOOST - [5:4] */
532#define WM8961_LMICBOOST_WIDTH 2 /* LMICBOOST - [5:4] */
533
534/*
535 * R33 (0x21) - ADCR signal path
536 */
537#define WM8961_RMICBOOST_MASK 0x0030 /* RMICBOOST - [5:4] */
538#define WM8961_RMICBOOST_SHIFT 4 /* RMICBOOST - [5:4] */
539#define WM8961_RMICBOOST_WIDTH 2 /* RMICBOOST - [5:4] */
540
541/*
542 * R40 (0x28) - LOUT2 volume
543 */
544#define WM8961_SPKVU 0x0100 /* SPKVU */
545#define WM8961_SPKVU_MASK 0x0100 /* SPKVU */
546#define WM8961_SPKVU_SHIFT 8 /* SPKVU */
547#define WM8961_SPKVU_WIDTH 1 /* SPKVU */
548#define WM8961_SPKLZC 0x0080 /* SPKLZC */
549#define WM8961_SPKLZC_MASK 0x0080 /* SPKLZC */
550#define WM8961_SPKLZC_SHIFT 7 /* SPKLZC */
551#define WM8961_SPKLZC_WIDTH 1 /* SPKLZC */
552#define WM8961_SPKLVOL_MASK 0x007F /* SPKLVOL - [6:0] */
553#define WM8961_SPKLVOL_SHIFT 0 /* SPKLVOL - [6:0] */
554#define WM8961_SPKLVOL_WIDTH 7 /* SPKLVOL - [6:0] */
555
556/*
557 * R41 (0x29) - ROUT2 volume
558 */
559#define WM8961_SPKVU 0x0100 /* SPKVU */
560#define WM8961_SPKVU_MASK 0x0100 /* SPKVU */
561#define WM8961_SPKVU_SHIFT 8 /* SPKVU */
562#define WM8961_SPKVU_WIDTH 1 /* SPKVU */
563#define WM8961_SPKRZC 0x0080 /* SPKRZC */
564#define WM8961_SPKRZC_MASK 0x0080 /* SPKRZC */
565#define WM8961_SPKRZC_SHIFT 7 /* SPKRZC */
566#define WM8961_SPKRZC_WIDTH 1 /* SPKRZC */
567#define WM8961_SPKRVOL_MASK 0x007F /* SPKRVOL - [6:0] */
568#define WM8961_SPKRVOL_SHIFT 0 /* SPKRVOL - [6:0] */
569#define WM8961_SPKRVOL_WIDTH 7 /* SPKRVOL - [6:0] */
570
571/*
572 * R47 (0x2F) - Pwr Mgmt (3)
573 */
574#define WM8961_TEMP_SHUT 0x0002 /* TEMP_SHUT */
575#define WM8961_TEMP_SHUT_MASK 0x0002 /* TEMP_SHUT */
576#define WM8961_TEMP_SHUT_SHIFT 1 /* TEMP_SHUT */
577#define WM8961_TEMP_SHUT_WIDTH 1 /* TEMP_SHUT */
578#define WM8961_TEMP_WARN 0x0001 /* TEMP_WARN */
579#define WM8961_TEMP_WARN_MASK 0x0001 /* TEMP_WARN */
580#define WM8961_TEMP_WARN_SHIFT 0 /* TEMP_WARN */
581#define WM8961_TEMP_WARN_WIDTH 1 /* TEMP_WARN */
582
583/*
584 * R48 (0x30) - Additional Control (4)
585 */
586#define WM8961_TSENSEN 0x0002 /* TSENSEN */
587#define WM8961_TSENSEN_MASK 0x0002 /* TSENSEN */
588#define WM8961_TSENSEN_SHIFT 1 /* TSENSEN */
589#define WM8961_TSENSEN_WIDTH 1 /* TSENSEN */
590#define WM8961_MBSEL 0x0001 /* MBSEL */
591#define WM8961_MBSEL_MASK 0x0001 /* MBSEL */
592#define WM8961_MBSEL_SHIFT 0 /* MBSEL */
593#define WM8961_MBSEL_WIDTH 1 /* MBSEL */
594
595/*
596 * R49 (0x31) - Class D Control 1
597 */
598#define WM8961_SPKR_ENA 0x0080 /* SPKR_ENA */
599#define WM8961_SPKR_ENA_MASK 0x0080 /* SPKR_ENA */
600#define WM8961_SPKR_ENA_SHIFT 7 /* SPKR_ENA */
601#define WM8961_SPKR_ENA_WIDTH 1 /* SPKR_ENA */
602#define WM8961_SPKL_ENA 0x0040 /* SPKL_ENA */
603#define WM8961_SPKL_ENA_MASK 0x0040 /* SPKL_ENA */
604#define WM8961_SPKL_ENA_SHIFT 6 /* SPKL_ENA */
605#define WM8961_SPKL_ENA_WIDTH 1 /* SPKL_ENA */
606
607/*
608 * R51 (0x33) - Class D Control 2
609 */
610#define WM8961_CLASSD_ACGAIN_MASK 0x0007 /* CLASSD_ACGAIN - [2:0] */
611#define WM8961_CLASSD_ACGAIN_SHIFT 0 /* CLASSD_ACGAIN - [2:0] */
612#define WM8961_CLASSD_ACGAIN_WIDTH 3 /* CLASSD_ACGAIN - [2:0] */
613
614/*
615 * R56 (0x38) - Clocking 4
616 */
617#define WM8961_CLK_DCS_DIV_MASK 0x01E0 /* CLK_DCS_DIV - [8:5] */
618#define WM8961_CLK_DCS_DIV_SHIFT 5 /* CLK_DCS_DIV - [8:5] */
619#define WM8961_CLK_DCS_DIV_WIDTH 4 /* CLK_DCS_DIV - [8:5] */
620#define WM8961_CLK_SYS_RATE_MASK 0x001E /* CLK_SYS_RATE - [4:1] */
621#define WM8961_CLK_SYS_RATE_SHIFT 1 /* CLK_SYS_RATE - [4:1] */
622#define WM8961_CLK_SYS_RATE_WIDTH 4 /* CLK_SYS_RATE - [4:1] */
623
624/*
625 * R57 (0x39) - DSP Sidetone 0
626 */
627#define WM8961_ADCR_DAC_SVOL_MASK 0x00F0 /* ADCR_DAC_SVOL - [7:4] */
628#define WM8961_ADCR_DAC_SVOL_SHIFT 4 /* ADCR_DAC_SVOL - [7:4] */
629#define WM8961_ADCR_DAC_SVOL_WIDTH 4 /* ADCR_DAC_SVOL - [7:4] */
630#define WM8961_ADC_TO_DACR_MASK 0x000C /* ADC_TO_DACR - [3:2] */
631#define WM8961_ADC_TO_DACR_SHIFT 2 /* ADC_TO_DACR - [3:2] */
632#define WM8961_ADC_TO_DACR_WIDTH 2 /* ADC_TO_DACR - [3:2] */
633
634/*
635 * R58 (0x3A) - DSP Sidetone 1
636 */
637#define WM8961_ADCL_DAC_SVOL_MASK 0x00F0 /* ADCL_DAC_SVOL - [7:4] */
638#define WM8961_ADCL_DAC_SVOL_SHIFT 4 /* ADCL_DAC_SVOL - [7:4] */
639#define WM8961_ADCL_DAC_SVOL_WIDTH 4 /* ADCL_DAC_SVOL - [7:4] */
640#define WM8961_ADC_TO_DACL_MASK 0x000C /* ADC_TO_DACL - [3:2] */
641#define WM8961_ADC_TO_DACL_SHIFT 2 /* ADC_TO_DACL - [3:2] */
642#define WM8961_ADC_TO_DACL_WIDTH 2 /* ADC_TO_DACL - [3:2] */
643
644/*
645 * R60 (0x3C) - DC Servo 0
646 */
647#define WM8961_DCS_ENA_CHAN_INL 0x0080 /* DCS_ENA_CHAN_INL */
648#define WM8961_DCS_ENA_CHAN_INL_MASK 0x0080 /* DCS_ENA_CHAN_INL */
649#define WM8961_DCS_ENA_CHAN_INL_SHIFT 7 /* DCS_ENA_CHAN_INL */
650#define WM8961_DCS_ENA_CHAN_INL_WIDTH 1 /* DCS_ENA_CHAN_INL */
651#define WM8961_DCS_TRIG_STARTUP_INL 0x0040 /* DCS_TRIG_STARTUP_INL */
652#define WM8961_DCS_TRIG_STARTUP_INL_MASK 0x0040 /* DCS_TRIG_STARTUP_INL */
653#define WM8961_DCS_TRIG_STARTUP_INL_SHIFT 6 /* DCS_TRIG_STARTUP_INL */
654#define WM8961_DCS_TRIG_STARTUP_INL_WIDTH 1 /* DCS_TRIG_STARTUP_INL */
655#define WM8961_DCS_TRIG_SERIES_INL 0x0010 /* DCS_TRIG_SERIES_INL */
656#define WM8961_DCS_TRIG_SERIES_INL_MASK 0x0010 /* DCS_TRIG_SERIES_INL */
657#define WM8961_DCS_TRIG_SERIES_INL_SHIFT 4 /* DCS_TRIG_SERIES_INL */
658#define WM8961_DCS_TRIG_SERIES_INL_WIDTH 1 /* DCS_TRIG_SERIES_INL */
659#define WM8961_DCS_ENA_CHAN_INR 0x0008 /* DCS_ENA_CHAN_INR */
660#define WM8961_DCS_ENA_CHAN_INR_MASK 0x0008 /* DCS_ENA_CHAN_INR */
661#define WM8961_DCS_ENA_CHAN_INR_SHIFT 3 /* DCS_ENA_CHAN_INR */
662#define WM8961_DCS_ENA_CHAN_INR_WIDTH 1 /* DCS_ENA_CHAN_INR */
663#define WM8961_DCS_TRIG_STARTUP_INR 0x0004 /* DCS_TRIG_STARTUP_INR */
664#define WM8961_DCS_TRIG_STARTUP_INR_MASK 0x0004 /* DCS_TRIG_STARTUP_INR */
665#define WM8961_DCS_TRIG_STARTUP_INR_SHIFT 2 /* DCS_TRIG_STARTUP_INR */
666#define WM8961_DCS_TRIG_STARTUP_INR_WIDTH 1 /* DCS_TRIG_STARTUP_INR */
667#define WM8961_DCS_TRIG_SERIES_INR 0x0001 /* DCS_TRIG_SERIES_INR */
668#define WM8961_DCS_TRIG_SERIES_INR_MASK 0x0001 /* DCS_TRIG_SERIES_INR */
669#define WM8961_DCS_TRIG_SERIES_INR_SHIFT 0 /* DCS_TRIG_SERIES_INR */
670#define WM8961_DCS_TRIG_SERIES_INR_WIDTH 1 /* DCS_TRIG_SERIES_INR */
671
672/*
673 * R61 (0x3D) - DC Servo 1
674 */
675#define WM8961_DCS_ENA_CHAN_HPL 0x0080 /* DCS_ENA_CHAN_HPL */
676#define WM8961_DCS_ENA_CHAN_HPL_MASK 0x0080 /* DCS_ENA_CHAN_HPL */
677#define WM8961_DCS_ENA_CHAN_HPL_SHIFT 7 /* DCS_ENA_CHAN_HPL */
678#define WM8961_DCS_ENA_CHAN_HPL_WIDTH 1 /* DCS_ENA_CHAN_HPL */
679#define WM8961_DCS_TRIG_STARTUP_HPL 0x0040 /* DCS_TRIG_STARTUP_HPL */
680#define WM8961_DCS_TRIG_STARTUP_HPL_MASK 0x0040 /* DCS_TRIG_STARTUP_HPL */
681#define WM8961_DCS_TRIG_STARTUP_HPL_SHIFT 6 /* DCS_TRIG_STARTUP_HPL */
682#define WM8961_DCS_TRIG_STARTUP_HPL_WIDTH 1 /* DCS_TRIG_STARTUP_HPL */
683#define WM8961_DCS_TRIG_SERIES_HPL 0x0010 /* DCS_TRIG_SERIES_HPL */
684#define WM8961_DCS_TRIG_SERIES_HPL_MASK 0x0010 /* DCS_TRIG_SERIES_HPL */
685#define WM8961_DCS_TRIG_SERIES_HPL_SHIFT 4 /* DCS_TRIG_SERIES_HPL */
686#define WM8961_DCS_TRIG_SERIES_HPL_WIDTH 1 /* DCS_TRIG_SERIES_HPL */
687#define WM8961_DCS_ENA_CHAN_HPR 0x0008 /* DCS_ENA_CHAN_HPR */
688#define WM8961_DCS_ENA_CHAN_HPR_MASK 0x0008 /* DCS_ENA_CHAN_HPR */
689#define WM8961_DCS_ENA_CHAN_HPR_SHIFT 3 /* DCS_ENA_CHAN_HPR */
690#define WM8961_DCS_ENA_CHAN_HPR_WIDTH 1 /* DCS_ENA_CHAN_HPR */
691#define WM8961_DCS_TRIG_STARTUP_HPR 0x0004 /* DCS_TRIG_STARTUP_HPR */
692#define WM8961_DCS_TRIG_STARTUP_HPR_MASK 0x0004 /* DCS_TRIG_STARTUP_HPR */
693#define WM8961_DCS_TRIG_STARTUP_HPR_SHIFT 2 /* DCS_TRIG_STARTUP_HPR */
694#define WM8961_DCS_TRIG_STARTUP_HPR_WIDTH 1 /* DCS_TRIG_STARTUP_HPR */
695#define WM8961_DCS_TRIG_SERIES_HPR 0x0001 /* DCS_TRIG_SERIES_HPR */
696#define WM8961_DCS_TRIG_SERIES_HPR_MASK 0x0001 /* DCS_TRIG_SERIES_HPR */
697#define WM8961_DCS_TRIG_SERIES_HPR_SHIFT 0 /* DCS_TRIG_SERIES_HPR */
698#define WM8961_DCS_TRIG_SERIES_HPR_WIDTH 1 /* DCS_TRIG_SERIES_HPR */
699
700/*
701 * R63 (0x3F) - DC Servo 3
702 */
703#define WM8961_DCS_FILT_BW_SERIES_MASK 0x0030 /* DCS_FILT_BW_SERIES - [5:4] */
704#define WM8961_DCS_FILT_BW_SERIES_SHIFT 4 /* DCS_FILT_BW_SERIES - [5:4] */
705#define WM8961_DCS_FILT_BW_SERIES_WIDTH 2 /* DCS_FILT_BW_SERIES - [5:4] */
706
707/*
708 * R65 (0x41) - DC Servo 5
709 */
710#define WM8961_DCS_SERIES_NO_HP_MASK 0x007F /* DCS_SERIES_NO_HP - [6:0] */
711#define WM8961_DCS_SERIES_NO_HP_SHIFT 0 /* DCS_SERIES_NO_HP - [6:0] */
712#define WM8961_DCS_SERIES_NO_HP_WIDTH 7 /* DCS_SERIES_NO_HP - [6:0] */
713
714/*
715 * R68 (0x44) - Analogue PGA Bias
716 */
717#define WM8961_HP_PGAS_BIAS_MASK 0x0007 /* HP_PGAS_BIAS - [2:0] */
718#define WM8961_HP_PGAS_BIAS_SHIFT 0 /* HP_PGAS_BIAS - [2:0] */
719#define WM8961_HP_PGAS_BIAS_WIDTH 3 /* HP_PGAS_BIAS - [2:0] */
720
721/*
722 * R69 (0x45) - Analogue HP 0
723 */
724#define WM8961_HPL_RMV_SHORT 0x0080 /* HPL_RMV_SHORT */
725#define WM8961_HPL_RMV_SHORT_MASK 0x0080 /* HPL_RMV_SHORT */
726#define WM8961_HPL_RMV_SHORT_SHIFT 7 /* HPL_RMV_SHORT */
727#define WM8961_HPL_RMV_SHORT_WIDTH 1 /* HPL_RMV_SHORT */
728#define WM8961_HPL_ENA_OUTP 0x0040 /* HPL_ENA_OUTP */
729#define WM8961_HPL_ENA_OUTP_MASK 0x0040 /* HPL_ENA_OUTP */
730#define WM8961_HPL_ENA_OUTP_SHIFT 6 /* HPL_ENA_OUTP */
731#define WM8961_HPL_ENA_OUTP_WIDTH 1 /* HPL_ENA_OUTP */
732#define WM8961_HPL_ENA_DLY 0x0020 /* HPL_ENA_DLY */
733#define WM8961_HPL_ENA_DLY_MASK 0x0020 /* HPL_ENA_DLY */
734#define WM8961_HPL_ENA_DLY_SHIFT 5 /* HPL_ENA_DLY */
735#define WM8961_HPL_ENA_DLY_WIDTH 1 /* HPL_ENA_DLY */
736#define WM8961_HPL_ENA 0x0010 /* HPL_ENA */
737#define WM8961_HPL_ENA_MASK 0x0010 /* HPL_ENA */
738#define WM8961_HPL_ENA_SHIFT 4 /* HPL_ENA */
739#define WM8961_HPL_ENA_WIDTH 1 /* HPL_ENA */
740#define WM8961_HPR_RMV_SHORT 0x0008 /* HPR_RMV_SHORT */
741#define WM8961_HPR_RMV_SHORT_MASK 0x0008 /* HPR_RMV_SHORT */
742#define WM8961_HPR_RMV_SHORT_SHIFT 3 /* HPR_RMV_SHORT */
743#define WM8961_HPR_RMV_SHORT_WIDTH 1 /* HPR_RMV_SHORT */
744#define WM8961_HPR_ENA_OUTP 0x0004 /* HPR_ENA_OUTP */
745#define WM8961_HPR_ENA_OUTP_MASK 0x0004 /* HPR_ENA_OUTP */
746#define WM8961_HPR_ENA_OUTP_SHIFT 2 /* HPR_ENA_OUTP */
747#define WM8961_HPR_ENA_OUTP_WIDTH 1 /* HPR_ENA_OUTP */
748#define WM8961_HPR_ENA_DLY 0x0002 /* HPR_ENA_DLY */
749#define WM8961_HPR_ENA_DLY_MASK 0x0002 /* HPR_ENA_DLY */
750#define WM8961_HPR_ENA_DLY_SHIFT 1 /* HPR_ENA_DLY */
751#define WM8961_HPR_ENA_DLY_WIDTH 1 /* HPR_ENA_DLY */
752#define WM8961_HPR_ENA 0x0001 /* HPR_ENA */
753#define WM8961_HPR_ENA_MASK 0x0001 /* HPR_ENA */
754#define WM8961_HPR_ENA_SHIFT 0 /* HPR_ENA */
755#define WM8961_HPR_ENA_WIDTH 1 /* HPR_ENA */
756
757/*
758 * R71 (0x47) - Analogue HP 2
759 */
760#define WM8961_HPL_VOL_MASK 0x01C0 /* HPL_VOL - [8:6] */
761#define WM8961_HPL_VOL_SHIFT 6 /* HPL_VOL - [8:6] */
762#define WM8961_HPL_VOL_WIDTH 3 /* HPL_VOL - [8:6] */
763#define WM8961_HPR_VOL_MASK 0x0038 /* HPR_VOL - [5:3] */
764#define WM8961_HPR_VOL_SHIFT 3 /* HPR_VOL - [5:3] */
765#define WM8961_HPR_VOL_WIDTH 3 /* HPR_VOL - [5:3] */
766#define WM8961_HP_BIAS_BOOST_MASK 0x0007 /* HP_BIAS_BOOST - [2:0] */
767#define WM8961_HP_BIAS_BOOST_SHIFT 0 /* HP_BIAS_BOOST - [2:0] */
768#define WM8961_HP_BIAS_BOOST_WIDTH 3 /* HP_BIAS_BOOST - [2:0] */
769
770/*
771 * R72 (0x48) - Charge Pump 1
772 */
773#define WM8961_CP_ENA 0x0001 /* CP_ENA */
774#define WM8961_CP_ENA_MASK 0x0001 /* CP_ENA */
775#define WM8961_CP_ENA_SHIFT 0 /* CP_ENA */
776#define WM8961_CP_ENA_WIDTH 1 /* CP_ENA */
777
778/*
779 * R82 (0x52) - Charge Pump B
780 */
781#define WM8961_CP_DYN_PWR_MASK 0x0003 /* CP_DYN_PWR - [1:0] */
782#define WM8961_CP_DYN_PWR_SHIFT 0 /* CP_DYN_PWR - [1:0] */
783#define WM8961_CP_DYN_PWR_WIDTH 2 /* CP_DYN_PWR - [1:0] */
784
785/*
786 * R87 (0x57) - Write Sequencer 1
787 */
788#define WM8961_WSEQ_ENA 0x0020 /* WSEQ_ENA */
789#define WM8961_WSEQ_ENA_MASK 0x0020 /* WSEQ_ENA */
790#define WM8961_WSEQ_ENA_SHIFT 5 /* WSEQ_ENA */
791#define WM8961_WSEQ_ENA_WIDTH 1 /* WSEQ_ENA */
792#define WM8961_WSEQ_WRITE_INDEX_MASK 0x001F /* WSEQ_WRITE_INDEX - [4:0] */
793#define WM8961_WSEQ_WRITE_INDEX_SHIFT 0 /* WSEQ_WRITE_INDEX - [4:0] */
794#define WM8961_WSEQ_WRITE_INDEX_WIDTH 5 /* WSEQ_WRITE_INDEX - [4:0] */
795
796/*
797 * R88 (0x58) - Write Sequencer 2
798 */
799#define WM8961_WSEQ_EOS 0x0100 /* WSEQ_EOS */
800#define WM8961_WSEQ_EOS_MASK 0x0100 /* WSEQ_EOS */
801#define WM8961_WSEQ_EOS_SHIFT 8 /* WSEQ_EOS */
802#define WM8961_WSEQ_EOS_WIDTH 1 /* WSEQ_EOS */
803#define WM8961_WSEQ_ADDR_MASK 0x00FF /* WSEQ_ADDR - [7:0] */
804#define WM8961_WSEQ_ADDR_SHIFT 0 /* WSEQ_ADDR - [7:0] */
805#define WM8961_WSEQ_ADDR_WIDTH 8 /* WSEQ_ADDR - [7:0] */
806
807/*
808 * R89 (0x59) - Write Sequencer 3
809 */
810#define WM8961_WSEQ_DATA_MASK 0x00FF /* WSEQ_DATA - [7:0] */
811#define WM8961_WSEQ_DATA_SHIFT 0 /* WSEQ_DATA - [7:0] */
812#define WM8961_WSEQ_DATA_WIDTH 8 /* WSEQ_DATA - [7:0] */
813
814/*
815 * R90 (0x5A) - Write Sequencer 4
816 */
817#define WM8961_WSEQ_ABORT 0x0100 /* WSEQ_ABORT */
818#define WM8961_WSEQ_ABORT_MASK 0x0100 /* WSEQ_ABORT */
819#define WM8961_WSEQ_ABORT_SHIFT 8 /* WSEQ_ABORT */
820#define WM8961_WSEQ_ABORT_WIDTH 1 /* WSEQ_ABORT */
821#define WM8961_WSEQ_START 0x0080 /* WSEQ_START */
822#define WM8961_WSEQ_START_MASK 0x0080 /* WSEQ_START */
823#define WM8961_WSEQ_START_SHIFT 7 /* WSEQ_START */
824#define WM8961_WSEQ_START_WIDTH 1 /* WSEQ_START */
825#define WM8961_WSEQ_START_INDEX_MASK 0x003F /* WSEQ_START_INDEX - [5:0] */
826#define WM8961_WSEQ_START_INDEX_SHIFT 0 /* WSEQ_START_INDEX - [5:0] */
827#define WM8961_WSEQ_START_INDEX_WIDTH 6 /* WSEQ_START_INDEX - [5:0] */
828
829/*
830 * R91 (0x5B) - Write Sequencer 5
831 */
832#define WM8961_WSEQ_DATA_WIDTH_MASK 0x0070 /* WSEQ_DATA_WIDTH - [6:4] */
833#define WM8961_WSEQ_DATA_WIDTH_SHIFT 4 /* WSEQ_DATA_WIDTH - [6:4] */
834#define WM8961_WSEQ_DATA_WIDTH_WIDTH 3 /* WSEQ_DATA_WIDTH - [6:4] */
835#define WM8961_WSEQ_DATA_START_MASK 0x000F /* WSEQ_DATA_START - [3:0] */
836#define WM8961_WSEQ_DATA_START_SHIFT 0 /* WSEQ_DATA_START - [3:0] */
837#define WM8961_WSEQ_DATA_START_WIDTH 4 /* WSEQ_DATA_START - [3:0] */
838
839/*
840 * R92 (0x5C) - Write Sequencer 6
841 */
842#define WM8961_WSEQ_DELAY_MASK 0x000F /* WSEQ_DELAY - [3:0] */
843#define WM8961_WSEQ_DELAY_SHIFT 0 /* WSEQ_DELAY - [3:0] */
844#define WM8961_WSEQ_DELAY_WIDTH 4 /* WSEQ_DELAY - [3:0] */
845
846/*
847 * R93 (0x5D) - Write Sequencer 7
848 */
849#define WM8961_WSEQ_BUSY 0x0001 /* WSEQ_BUSY */
850#define WM8961_WSEQ_BUSY_MASK 0x0001 /* WSEQ_BUSY */
851#define WM8961_WSEQ_BUSY_SHIFT 0 /* WSEQ_BUSY */
852#define WM8961_WSEQ_BUSY_WIDTH 1 /* WSEQ_BUSY */
853
854/*
855 * R252 (0xFC) - General test 1
856 */
857#define WM8961_ARA_ENA 0x0002 /* ARA_ENA */
858#define WM8961_ARA_ENA_MASK 0x0002 /* ARA_ENA */
859#define WM8961_ARA_ENA_SHIFT 1 /* ARA_ENA */
860#define WM8961_ARA_ENA_WIDTH 1 /* ARA_ENA */
861#define WM8961_AUTO_INC 0x0001 /* AUTO_INC */
862#define WM8961_AUTO_INC_MASK 0x0001 /* AUTO_INC */
863#define WM8961_AUTO_INC_SHIFT 0 /* AUTO_INC */
864#define WM8961_AUTO_INC_WIDTH 1 /* AUTO_INC */
865
866#endif
diff --git a/sound/soc/codecs/wm8971.c b/sound/soc/codecs/wm8971.c
index 032dca22dbd3..d66efb0546ea 100644
--- a/sound/soc/codecs/wm8971.c
+++ b/sound/soc/codecs/wm8971.c
@@ -59,44 +59,7 @@ static const u16 wm8971_reg[] = {
59 0x0079, 0x0079, 0x0079, /* 40 */ 59 0x0079, 0x0079, 0x0079, /* 40 */
60}; 60};
61 61
62static inline unsigned int wm8971_read_reg_cache(struct snd_soc_codec *codec, 62#define wm8971_reset(c) snd_soc_write(c, WM8971_RESET, 0)
63 unsigned int reg)
64{
65 u16 *cache = codec->reg_cache;
66 if (reg < WM8971_REG_COUNT)
67 return cache[reg];
68
69 return -1;
70}
71
72static inline void wm8971_write_reg_cache(struct snd_soc_codec *codec,
73 unsigned int reg, unsigned int value)
74{
75 u16 *cache = codec->reg_cache;
76 if (reg < WM8971_REG_COUNT)
77 cache[reg] = value;
78}
79
80static int wm8971_write(struct snd_soc_codec *codec, unsigned int reg,
81 unsigned int value)
82{
83 u8 data[2];
84
85 /* data is
86 * D15..D9 WM8753 register offset
87 * D8...D0 register data
88 */
89 data[0] = (reg << 1) | ((value >> 8) & 0x0001);
90 data[1] = value & 0x00ff;
91
92 wm8971_write_reg_cache (codec, reg, value);
93 if (codec->hw_write(codec->control_data, data, 2) == 2)
94 return 0;
95 else
96 return -EIO;
97}
98
99#define wm8971_reset(c) wm8971_write(c, WM8971_RESET, 0)
100 63
101/* WM8971 Controls */ 64/* WM8971 Controls */
102static const char *wm8971_bass[] = { "Linear Control", "Adaptive Boost" }; 65static const char *wm8971_bass[] = { "Linear Control", "Adaptive Boost" };
@@ -521,7 +484,7 @@ static int wm8971_set_dai_fmt(struct snd_soc_dai *codec_dai,
521 return -EINVAL; 484 return -EINVAL;
522 } 485 }
523 486
524 wm8971_write(codec, WM8971_IFACE, iface); 487 snd_soc_write(codec, WM8971_IFACE, iface);
525 return 0; 488 return 0;
526} 489}
527 490
@@ -533,8 +496,8 @@ static int wm8971_pcm_hw_params(struct snd_pcm_substream *substream,
533 struct snd_soc_device *socdev = rtd->socdev; 496 struct snd_soc_device *socdev = rtd->socdev;
534 struct snd_soc_codec *codec = socdev->card->codec; 497 struct snd_soc_codec *codec = socdev->card->codec;
535 struct wm8971_priv *wm8971 = codec->private_data; 498 struct wm8971_priv *wm8971 = codec->private_data;
536 u16 iface = wm8971_read_reg_cache(codec, WM8971_IFACE) & 0x1f3; 499 u16 iface = snd_soc_read(codec, WM8971_IFACE) & 0x1f3;
537 u16 srate = wm8971_read_reg_cache(codec, WM8971_SRATE) & 0x1c0; 500 u16 srate = snd_soc_read(codec, WM8971_SRATE) & 0x1c0;
538 int coeff = get_coeff(wm8971->sysclk, params_rate(params)); 501 int coeff = get_coeff(wm8971->sysclk, params_rate(params));
539 502
540 /* bit size */ 503 /* bit size */
@@ -553,9 +516,9 @@ static int wm8971_pcm_hw_params(struct snd_pcm_substream *substream,
553 } 516 }
554 517
555 /* set iface & srate */ 518 /* set iface & srate */
556 wm8971_write(codec, WM8971_IFACE, iface); 519 snd_soc_write(codec, WM8971_IFACE, iface);
557 if (coeff >= 0) 520 if (coeff >= 0)
558 wm8971_write(codec, WM8971_SRATE, srate | 521 snd_soc_write(codec, WM8971_SRATE, srate |
559 (coeff_div[coeff].sr << 1) | coeff_div[coeff].usb); 522 (coeff_div[coeff].sr << 1) | coeff_div[coeff].usb);
560 523
561 return 0; 524 return 0;
@@ -564,33 +527,33 @@ static int wm8971_pcm_hw_params(struct snd_pcm_substream *substream,
564static int wm8971_mute(struct snd_soc_dai *dai, int mute) 527static int wm8971_mute(struct snd_soc_dai *dai, int mute)
565{ 528{
566 struct snd_soc_codec *codec = dai->codec; 529 struct snd_soc_codec *codec = dai->codec;
567 u16 mute_reg = wm8971_read_reg_cache(codec, WM8971_ADCDAC) & 0xfff7; 530 u16 mute_reg = snd_soc_read(codec, WM8971_ADCDAC) & 0xfff7;
568 531
569 if (mute) 532 if (mute)
570 wm8971_write(codec, WM8971_ADCDAC, mute_reg | 0x8); 533 snd_soc_write(codec, WM8971_ADCDAC, mute_reg | 0x8);
571 else 534 else
572 wm8971_write(codec, WM8971_ADCDAC, mute_reg); 535 snd_soc_write(codec, WM8971_ADCDAC, mute_reg);
573 return 0; 536 return 0;
574} 537}
575 538
576static int wm8971_set_bias_level(struct snd_soc_codec *codec, 539static int wm8971_set_bias_level(struct snd_soc_codec *codec,
577 enum snd_soc_bias_level level) 540 enum snd_soc_bias_level level)
578{ 541{
579 u16 pwr_reg = wm8971_read_reg_cache(codec, WM8971_PWR1) & 0xfe3e; 542 u16 pwr_reg = snd_soc_read(codec, WM8971_PWR1) & 0xfe3e;
580 543
581 switch (level) { 544 switch (level) {
582 case SND_SOC_BIAS_ON: 545 case SND_SOC_BIAS_ON:
583 /* set vmid to 50k and unmute dac */ 546 /* set vmid to 50k and unmute dac */
584 wm8971_write(codec, WM8971_PWR1, pwr_reg | 0x00c1); 547 snd_soc_write(codec, WM8971_PWR1, pwr_reg | 0x00c1);
585 break; 548 break;
586 case SND_SOC_BIAS_PREPARE: 549 case SND_SOC_BIAS_PREPARE:
587 break; 550 break;
588 case SND_SOC_BIAS_STANDBY: 551 case SND_SOC_BIAS_STANDBY:
589 /* mute dac and set vmid to 500k, enable VREF */ 552 /* mute dac and set vmid to 500k, enable VREF */
590 wm8971_write(codec, WM8971_PWR1, pwr_reg | 0x0140); 553 snd_soc_write(codec, WM8971_PWR1, pwr_reg | 0x0140);
591 break; 554 break;
592 case SND_SOC_BIAS_OFF: 555 case SND_SOC_BIAS_OFF:
593 wm8971_write(codec, WM8971_PWR1, 0x0001); 556 snd_soc_write(codec, WM8971_PWR1, 0x0001);
594 break; 557 break;
595 } 558 }
596 codec->bias_level = level; 559 codec->bias_level = level;
@@ -667,8 +630,8 @@ static int wm8971_resume(struct platform_device *pdev)
667 630
668 /* charge wm8971 caps */ 631 /* charge wm8971 caps */
669 if (codec->suspend_bias_level == SND_SOC_BIAS_ON) { 632 if (codec->suspend_bias_level == SND_SOC_BIAS_ON) {
670 reg = wm8971_read_reg_cache(codec, WM8971_PWR1) & 0xfe3e; 633 reg = snd_soc_read(codec, WM8971_PWR1) & 0xfe3e;
671 wm8971_write(codec, WM8971_PWR1, reg | 0x01c0); 634 snd_soc_write(codec, WM8971_PWR1, reg | 0x01c0);
672 codec->bias_level = SND_SOC_BIAS_ON; 635 codec->bias_level = SND_SOC_BIAS_ON;
673 queue_delayed_work(wm8971_workq, &codec->delayed_work, 636 queue_delayed_work(wm8971_workq, &codec->delayed_work,
674 msecs_to_jiffies(1000)); 637 msecs_to_jiffies(1000));
@@ -677,15 +640,14 @@ static int wm8971_resume(struct platform_device *pdev)
677 return 0; 640 return 0;
678} 641}
679 642
680static int wm8971_init(struct snd_soc_device *socdev) 643static int wm8971_init(struct snd_soc_device *socdev,
644 enum snd_soc_control_type control)
681{ 645{
682 struct snd_soc_codec *codec = socdev->card->codec; 646 struct snd_soc_codec *codec = socdev->card->codec;
683 int reg, ret = 0; 647 int reg, ret = 0;
684 648
685 codec->name = "WM8971"; 649 codec->name = "WM8971";
686 codec->owner = THIS_MODULE; 650 codec->owner = THIS_MODULE;
687 codec->read = wm8971_read_reg_cache;
688 codec->write = wm8971_write;
689 codec->set_bias_level = wm8971_set_bias_level; 651 codec->set_bias_level = wm8971_set_bias_level;
690 codec->dai = &wm8971_dai; 652 codec->dai = &wm8971_dai;
691 codec->reg_cache_size = ARRAY_SIZE(wm8971_reg); 653 codec->reg_cache_size = ARRAY_SIZE(wm8971_reg);
@@ -695,42 +657,48 @@ static int wm8971_init(struct snd_soc_device *socdev)
695 if (codec->reg_cache == NULL) 657 if (codec->reg_cache == NULL)
696 return -ENOMEM; 658 return -ENOMEM;
697 659
660 ret = snd_soc_codec_set_cache_io(codec, 7, 9, control);
661 if (ret < 0) {
662 printk(KERN_ERR "wm8971: failed to set cache I/O: %d\n", ret);
663 goto err;
664 }
665
698 wm8971_reset(codec); 666 wm8971_reset(codec);
699 667
700 /* register pcms */ 668 /* register pcms */
701 ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1); 669 ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1);
702 if (ret < 0) { 670 if (ret < 0) {
703 printk(KERN_ERR "wm8971: failed to create pcms\n"); 671 printk(KERN_ERR "wm8971: failed to create pcms\n");
704 goto pcm_err; 672 goto err;
705 } 673 }
706 674
707 /* charge output caps - set vmid to 5k for quick power up */ 675 /* charge output caps - set vmid to 5k for quick power up */
708 reg = wm8971_read_reg_cache(codec, WM8971_PWR1) & 0xfe3e; 676 reg = snd_soc_read(codec, WM8971_PWR1) & 0xfe3e;
709 wm8971_write(codec, WM8971_PWR1, reg | 0x01c0); 677 snd_soc_write(codec, WM8971_PWR1, reg | 0x01c0);
710 codec->bias_level = SND_SOC_BIAS_STANDBY; 678 codec->bias_level = SND_SOC_BIAS_STANDBY;
711 queue_delayed_work(wm8971_workq, &codec->delayed_work, 679 queue_delayed_work(wm8971_workq, &codec->delayed_work,
712 msecs_to_jiffies(1000)); 680 msecs_to_jiffies(1000));
713 681
714 /* set the update bits */ 682 /* set the update bits */
715 reg = wm8971_read_reg_cache(codec, WM8971_LDAC); 683 reg = snd_soc_read(codec, WM8971_LDAC);
716 wm8971_write(codec, WM8971_LDAC, reg | 0x0100); 684 snd_soc_write(codec, WM8971_LDAC, reg | 0x0100);
717 reg = wm8971_read_reg_cache(codec, WM8971_RDAC); 685 reg = snd_soc_read(codec, WM8971_RDAC);
718 wm8971_write(codec, WM8971_RDAC, reg | 0x0100); 686 snd_soc_write(codec, WM8971_RDAC, reg | 0x0100);
719 687
720 reg = wm8971_read_reg_cache(codec, WM8971_LOUT1V); 688 reg = snd_soc_read(codec, WM8971_LOUT1V);
721 wm8971_write(codec, WM8971_LOUT1V, reg | 0x0100); 689 snd_soc_write(codec, WM8971_LOUT1V, reg | 0x0100);
722 reg = wm8971_read_reg_cache(codec, WM8971_ROUT1V); 690 reg = snd_soc_read(codec, WM8971_ROUT1V);
723 wm8971_write(codec, WM8971_ROUT1V, reg | 0x0100); 691 snd_soc_write(codec, WM8971_ROUT1V, reg | 0x0100);
724 692
725 reg = wm8971_read_reg_cache(codec, WM8971_LOUT2V); 693 reg = snd_soc_read(codec, WM8971_LOUT2V);
726 wm8971_write(codec, WM8971_LOUT2V, reg | 0x0100); 694 snd_soc_write(codec, WM8971_LOUT2V, reg | 0x0100);
727 reg = wm8971_read_reg_cache(codec, WM8971_ROUT2V); 695 reg = snd_soc_read(codec, WM8971_ROUT2V);
728 wm8971_write(codec, WM8971_ROUT2V, reg | 0x0100); 696 snd_soc_write(codec, WM8971_ROUT2V, reg | 0x0100);
729 697
730 reg = wm8971_read_reg_cache(codec, WM8971_LINVOL); 698 reg = snd_soc_read(codec, WM8971_LINVOL);
731 wm8971_write(codec, WM8971_LINVOL, reg | 0x0100); 699 snd_soc_write(codec, WM8971_LINVOL, reg | 0x0100);
732 reg = wm8971_read_reg_cache(codec, WM8971_RINVOL); 700 reg = snd_soc_read(codec, WM8971_RINVOL);
733 wm8971_write(codec, WM8971_RINVOL, reg | 0x0100); 701 snd_soc_write(codec, WM8971_RINVOL, reg | 0x0100);
734 702
735 snd_soc_add_controls(codec, wm8971_snd_controls, 703 snd_soc_add_controls(codec, wm8971_snd_controls,
736 ARRAY_SIZE(wm8971_snd_controls)); 704 ARRAY_SIZE(wm8971_snd_controls));
@@ -745,7 +713,7 @@ static int wm8971_init(struct snd_soc_device *socdev)
745card_err: 713card_err:
746 snd_soc_free_pcms(socdev); 714 snd_soc_free_pcms(socdev);
747 snd_soc_dapm_free(socdev); 715 snd_soc_dapm_free(socdev);
748pcm_err: 716err:
749 kfree(codec->reg_cache); 717 kfree(codec->reg_cache);
750 return ret; 718 return ret;
751} 719}
@@ -767,7 +735,7 @@ static int wm8971_i2c_probe(struct i2c_client *i2c,
767 735
768 codec->control_data = i2c; 736 codec->control_data = i2c;
769 737
770 ret = wm8971_init(socdev); 738 ret = wm8971_init(socdev, SND_SOC_I2C);
771 if (ret < 0) 739 if (ret < 0)
772 pr_err("failed to initialise WM8971\n"); 740 pr_err("failed to initialise WM8971\n");
773 741
@@ -877,7 +845,6 @@ static int wm8971_probe(struct platform_device *pdev)
877 845
878#if defined (CONFIG_I2C) || defined (CONFIG_I2C_MODULE) 846#if defined (CONFIG_I2C) || defined (CONFIG_I2C_MODULE)
879 if (setup->i2c_address) { 847 if (setup->i2c_address) {
880 codec->hw_write = (hw_write_t)i2c_master_send;
881 ret = wm8971_add_i2c_device(pdev, setup); 848 ret = wm8971_add_i2c_device(pdev, setup);
882 } 849 }
883#endif 850#endif
diff --git a/sound/soc/codecs/wm8988.c b/sound/soc/codecs/wm8988.c
new file mode 100644
index 000000000000..1c8653523c8c
--- /dev/null
+++ b/sound/soc/codecs/wm8988.c
@@ -0,0 +1,1069 @@
1/*
2 * wm8988.c -- WM8988 ALSA SoC audio driver
3 *
4 * Copyright 2009 Wolfson Microelectronics plc
5 * Copyright 2005 Openedhand Ltd.
6 *
7 * Author: Mark Brown <broonie@opensource.wolfsonmicro.com>
8 *
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License version 2 as
11 * published by the Free Software Foundation.
12 */
13
14#include <linux/module.h>
15#include <linux/moduleparam.h>
16#include <linux/init.h>
17#include <linux/delay.h>
18#include <linux/pm.h>
19#include <linux/i2c.h>
20#include <linux/spi/spi.h>
21#include <linux/platform_device.h>
22#include <sound/core.h>
23#include <sound/pcm.h>
24#include <sound/pcm_params.h>
25#include <sound/tlv.h>
26#include <sound/soc.h>
27#include <sound/soc-dapm.h>
28#include <sound/initval.h>
29
30#include "wm8988.h"
31
32/*
33 * wm8988 register cache
34 * We can't read the WM8988 register space when we
35 * are using 2 wire for device control, so we cache them instead.
36 */
37static const u16 wm8988_reg[] = {
38 0x0097, 0x0097, 0x0079, 0x0079, /* 0 */
39 0x0000, 0x0008, 0x0000, 0x000a, /* 4 */
40 0x0000, 0x0000, 0x00ff, 0x00ff, /* 8 */
41 0x000f, 0x000f, 0x0000, 0x0000, /* 12 */
42 0x0000, 0x007b, 0x0000, 0x0032, /* 16 */
43 0x0000, 0x00c3, 0x00c3, 0x00c0, /* 20 */
44 0x0000, 0x0000, 0x0000, 0x0000, /* 24 */
45 0x0000, 0x0000, 0x0000, 0x0000, /* 28 */
46 0x0000, 0x0000, 0x0050, 0x0050, /* 32 */
47 0x0050, 0x0050, 0x0050, 0x0050, /* 36 */
48 0x0079, 0x0079, 0x0079, /* 40 */
49};
50
51/* codec private data */
52struct wm8988_priv {
53 unsigned int sysclk;
54 struct snd_soc_codec codec;
55 struct snd_pcm_hw_constraint_list *sysclk_constraints;
56 u16 reg_cache[WM8988_NUM_REG];
57};
58
59
60#define wm8988_reset(c) snd_soc_write(c, WM8988_RESET, 0)
61
62/*
63 * WM8988 Controls
64 */
65
66static const char *bass_boost_txt[] = {"Linear Control", "Adaptive Boost"};
67static const struct soc_enum bass_boost =
68 SOC_ENUM_SINGLE(WM8988_BASS, 7, 2, bass_boost_txt);
69
70static const char *bass_filter_txt[] = { "130Hz @ 48kHz", "200Hz @ 48kHz" };
71static const struct soc_enum bass_filter =
72 SOC_ENUM_SINGLE(WM8988_BASS, 6, 2, bass_filter_txt);
73
74static const char *treble_txt[] = {"8kHz", "4kHz"};
75static const struct soc_enum treble =
76 SOC_ENUM_SINGLE(WM8988_TREBLE, 6, 2, treble_txt);
77
78static const char *stereo_3d_lc_txt[] = {"200Hz", "500Hz"};
79static const struct soc_enum stereo_3d_lc =
80 SOC_ENUM_SINGLE(WM8988_3D, 5, 2, stereo_3d_lc_txt);
81
82static const char *stereo_3d_uc_txt[] = {"2.2kHz", "1.5kHz"};
83static const struct soc_enum stereo_3d_uc =
84 SOC_ENUM_SINGLE(WM8988_3D, 6, 2, stereo_3d_uc_txt);
85
86static const char *stereo_3d_func_txt[] = {"Capture", "Playback"};
87static const struct soc_enum stereo_3d_func =
88 SOC_ENUM_SINGLE(WM8988_3D, 7, 2, stereo_3d_func_txt);
89
90static const char *alc_func_txt[] = {"Off", "Right", "Left", "Stereo"};
91static const struct soc_enum alc_func =
92 SOC_ENUM_SINGLE(WM8988_ALC1, 7, 4, alc_func_txt);
93
94static const char *ng_type_txt[] = {"Constant PGA Gain",
95 "Mute ADC Output"};
96static const struct soc_enum ng_type =
97 SOC_ENUM_SINGLE(WM8988_NGATE, 1, 2, ng_type_txt);
98
99static const char *deemph_txt[] = {"None", "32Khz", "44.1Khz", "48Khz"};
100static const struct soc_enum deemph =
101 SOC_ENUM_SINGLE(WM8988_ADCDAC, 1, 4, deemph_txt);
102
103static const char *adcpol_txt[] = {"Normal", "L Invert", "R Invert",
104 "L + R Invert"};
105static const struct soc_enum adcpol =
106 SOC_ENUM_SINGLE(WM8988_ADCDAC, 5, 4, adcpol_txt);
107
108static const DECLARE_TLV_DB_SCALE(pga_tlv, -1725, 75, 0);
109static const DECLARE_TLV_DB_SCALE(adc_tlv, -9750, 50, 1);
110static const DECLARE_TLV_DB_SCALE(dac_tlv, -12750, 50, 1);
111static const DECLARE_TLV_DB_SCALE(out_tlv, -12100, 100, 1);
112static const DECLARE_TLV_DB_SCALE(bypass_tlv, -1500, 300, 0);
113
114static const struct snd_kcontrol_new wm8988_snd_controls[] = {
115
116SOC_ENUM("Bass Boost", bass_boost),
117SOC_ENUM("Bass Filter", bass_filter),
118SOC_SINGLE("Bass Volume", WM8988_BASS, 0, 15, 1),
119
120SOC_SINGLE("Treble Volume", WM8988_TREBLE, 0, 15, 0),
121SOC_ENUM("Treble Cut-off", treble),
122
123SOC_SINGLE("3D Switch", WM8988_3D, 0, 1, 0),
124SOC_SINGLE("3D Volume", WM8988_3D, 1, 15, 0),
125SOC_ENUM("3D Lower Cut-off", stereo_3d_lc),
126SOC_ENUM("3D Upper Cut-off", stereo_3d_uc),
127SOC_ENUM("3D Mode", stereo_3d_func),
128
129SOC_SINGLE("ALC Capture Target Volume", WM8988_ALC1, 0, 7, 0),
130SOC_SINGLE("ALC Capture Max Volume", WM8988_ALC1, 4, 7, 0),
131SOC_ENUM("ALC Capture Function", alc_func),
132SOC_SINGLE("ALC Capture ZC Switch", WM8988_ALC2, 7, 1, 0),
133SOC_SINGLE("ALC Capture Hold Time", WM8988_ALC2, 0, 15, 0),
134SOC_SINGLE("ALC Capture Decay Time", WM8988_ALC3, 4, 15, 0),
135SOC_SINGLE("ALC Capture Attack Time", WM8988_ALC3, 0, 15, 0),
136SOC_SINGLE("ALC Capture NG Threshold", WM8988_NGATE, 3, 31, 0),
137SOC_ENUM("ALC Capture NG Type", ng_type),
138SOC_SINGLE("ALC Capture NG Switch", WM8988_NGATE, 0, 1, 0),
139
140SOC_SINGLE("ZC Timeout Switch", WM8988_ADCTL1, 0, 1, 0),
141
142SOC_DOUBLE_R_TLV("Capture Digital Volume", WM8988_LADC, WM8988_RADC,
143 0, 255, 0, adc_tlv),
144SOC_DOUBLE_R_TLV("Capture Volume", WM8988_LINVOL, WM8988_RINVOL,
145 0, 63, 0, pga_tlv),
146SOC_DOUBLE_R("Capture ZC Switch", WM8988_LINVOL, WM8988_RINVOL, 6, 1, 0),
147SOC_DOUBLE_R("Capture Switch", WM8988_LINVOL, WM8988_RINVOL, 7, 1, 1),
148
149SOC_ENUM("Playback De-emphasis", deemph),
150
151SOC_ENUM("Capture Polarity", adcpol),
152SOC_SINGLE("Playback 6dB Attenuate", WM8988_ADCDAC, 7, 1, 0),
153SOC_SINGLE("Capture 6dB Attenuate", WM8988_ADCDAC, 8, 1, 0),
154
155SOC_DOUBLE_R_TLV("PCM Volume", WM8988_LDAC, WM8988_RDAC, 0, 255, 0, dac_tlv),
156
157SOC_SINGLE_TLV("Left Mixer Left Bypass Volume", WM8988_LOUTM1, 4, 7, 1,
158 bypass_tlv),
159SOC_SINGLE_TLV("Left Mixer Right Bypass Volume", WM8988_LOUTM2, 4, 7, 1,
160 bypass_tlv),
161SOC_SINGLE_TLV("Right Mixer Left Bypass Volume", WM8988_ROUTM1, 4, 7, 1,
162 bypass_tlv),
163SOC_SINGLE_TLV("Right Mixer Right Bypass Volume", WM8988_ROUTM2, 4, 7, 1,
164 bypass_tlv),
165
166SOC_DOUBLE_R("Output 1 Playback ZC Switch", WM8988_LOUT1V,
167 WM8988_ROUT1V, 7, 1, 0),
168SOC_DOUBLE_R_TLV("Output 1 Playback Volume", WM8988_LOUT1V, WM8988_ROUT1V,
169 0, 127, 0, out_tlv),
170
171SOC_DOUBLE_R("Output 2 Playback ZC Switch", WM8988_LOUT2V,
172 WM8988_ROUT2V, 7, 1, 0),
173SOC_DOUBLE_R_TLV("Output 2 Playback Volume", WM8988_LOUT2V, WM8988_ROUT2V,
174 0, 127, 0, out_tlv),
175
176};
177
178/*
179 * DAPM Controls
180 */
181
182static int wm8988_lrc_control(struct snd_soc_dapm_widget *w,
183 struct snd_kcontrol *kcontrol, int event)
184{
185 struct snd_soc_codec *codec = w->codec;
186 u16 adctl2 = snd_soc_read(codec, WM8988_ADCTL2);
187
188 /* Use the DAC to gate LRC if active, otherwise use ADC */
189 if (snd_soc_read(codec, WM8988_PWR2) & 0x180)
190 adctl2 &= ~0x4;
191 else
192 adctl2 |= 0x4;
193
194 return snd_soc_write(codec, WM8988_ADCTL2, adctl2);
195}
196
197static const char *wm8988_line_texts[] = {
198 "Line 1", "Line 2", "PGA", "Differential"};
199
200static const unsigned int wm8988_line_values[] = {
201 0, 1, 3, 4};
202
203static const struct soc_enum wm8988_lline_enum =
204 SOC_VALUE_ENUM_SINGLE(WM8988_LOUTM1, 0, 7,
205 ARRAY_SIZE(wm8988_line_texts),
206 wm8988_line_texts,
207 wm8988_line_values);
208static const struct snd_kcontrol_new wm8988_left_line_controls =
209 SOC_DAPM_VALUE_ENUM("Route", wm8988_lline_enum);
210
211static const struct soc_enum wm8988_rline_enum =
212 SOC_VALUE_ENUM_SINGLE(WM8988_ROUTM1, 0, 7,
213 ARRAY_SIZE(wm8988_line_texts),
214 wm8988_line_texts,
215 wm8988_line_values);
216static const struct snd_kcontrol_new wm8988_right_line_controls =
217 SOC_DAPM_VALUE_ENUM("Route", wm8988_lline_enum);
218
219/* Left Mixer */
220static const struct snd_kcontrol_new wm8988_left_mixer_controls[] = {
221 SOC_DAPM_SINGLE("Playback Switch", WM8988_LOUTM1, 8, 1, 0),
222 SOC_DAPM_SINGLE("Left Bypass Switch", WM8988_LOUTM1, 7, 1, 0),
223 SOC_DAPM_SINGLE("Right Playback Switch", WM8988_LOUTM2, 8, 1, 0),
224 SOC_DAPM_SINGLE("Right Bypass Switch", WM8988_LOUTM2, 7, 1, 0),
225};
226
227/* Right Mixer */
228static const struct snd_kcontrol_new wm8988_right_mixer_controls[] = {
229 SOC_DAPM_SINGLE("Left Playback Switch", WM8988_ROUTM1, 8, 1, 0),
230 SOC_DAPM_SINGLE("Left Bypass Switch", WM8988_ROUTM1, 7, 1, 0),
231 SOC_DAPM_SINGLE("Playback Switch", WM8988_ROUTM2, 8, 1, 0),
232 SOC_DAPM_SINGLE("Right Bypass Switch", WM8988_ROUTM2, 7, 1, 0),
233};
234
235static const char *wm8988_pga_sel[] = {"Line 1", "Line 2", "Differential"};
236static const unsigned int wm8988_pga_val[] = { 0, 1, 3 };
237
238/* Left PGA Mux */
239static const struct soc_enum wm8988_lpga_enum =
240 SOC_VALUE_ENUM_SINGLE(WM8988_LADCIN, 6, 3,
241 ARRAY_SIZE(wm8988_pga_sel),
242 wm8988_pga_sel,
243 wm8988_pga_val);
244static const struct snd_kcontrol_new wm8988_left_pga_controls =
245 SOC_DAPM_VALUE_ENUM("Route", wm8988_lpga_enum);
246
247/* Right PGA Mux */
248static const struct soc_enum wm8988_rpga_enum =
249 SOC_VALUE_ENUM_SINGLE(WM8988_RADCIN, 6, 3,
250 ARRAY_SIZE(wm8988_pga_sel),
251 wm8988_pga_sel,
252 wm8988_pga_val);
253static const struct snd_kcontrol_new wm8988_right_pga_controls =
254 SOC_DAPM_VALUE_ENUM("Route", wm8988_rpga_enum);
255
256/* Differential Mux */
257static const char *wm8988_diff_sel[] = {"Line 1", "Line 2"};
258static const struct soc_enum diffmux =
259 SOC_ENUM_SINGLE(WM8988_ADCIN, 8, 2, wm8988_diff_sel);
260static const struct snd_kcontrol_new wm8988_diffmux_controls =
261 SOC_DAPM_ENUM("Route", diffmux);
262
263/* Mono ADC Mux */
264static const char *wm8988_mono_mux[] = {"Stereo", "Mono (Left)",
265 "Mono (Right)", "Digital Mono"};
266static const struct soc_enum monomux =
267 SOC_ENUM_SINGLE(WM8988_ADCIN, 6, 4, wm8988_mono_mux);
268static const struct snd_kcontrol_new wm8988_monomux_controls =
269 SOC_DAPM_ENUM("Route", monomux);
270
271static const struct snd_soc_dapm_widget wm8988_dapm_widgets[] = {
272 SND_SOC_DAPM_MICBIAS("Mic Bias", WM8988_PWR1, 1, 0),
273
274 SND_SOC_DAPM_MUX("Differential Mux", SND_SOC_NOPM, 0, 0,
275 &wm8988_diffmux_controls),
276 SND_SOC_DAPM_MUX("Left ADC Mux", SND_SOC_NOPM, 0, 0,
277 &wm8988_monomux_controls),
278 SND_SOC_DAPM_MUX("Right ADC Mux", SND_SOC_NOPM, 0, 0,
279 &wm8988_monomux_controls),
280
281 SND_SOC_DAPM_MUX("Left PGA Mux", WM8988_PWR1, 5, 0,
282 &wm8988_left_pga_controls),
283 SND_SOC_DAPM_MUX("Right PGA Mux", WM8988_PWR1, 4, 0,
284 &wm8988_right_pga_controls),
285
286 SND_SOC_DAPM_MUX("Left Line Mux", SND_SOC_NOPM, 0, 0,
287 &wm8988_left_line_controls),
288 SND_SOC_DAPM_MUX("Right Line Mux", SND_SOC_NOPM, 0, 0,
289 &wm8988_right_line_controls),
290
291 SND_SOC_DAPM_ADC("Right ADC", "Right Capture", WM8988_PWR1, 2, 0),
292 SND_SOC_DAPM_ADC("Left ADC", "Left Capture", WM8988_PWR1, 3, 0),
293
294 SND_SOC_DAPM_DAC("Right DAC", "Right Playback", WM8988_PWR2, 7, 0),
295 SND_SOC_DAPM_DAC("Left DAC", "Left Playback", WM8988_PWR2, 8, 0),
296
297 SND_SOC_DAPM_MIXER("Left Mixer", SND_SOC_NOPM, 0, 0,
298 &wm8988_left_mixer_controls[0],
299 ARRAY_SIZE(wm8988_left_mixer_controls)),
300 SND_SOC_DAPM_MIXER("Right Mixer", SND_SOC_NOPM, 0, 0,
301 &wm8988_right_mixer_controls[0],
302 ARRAY_SIZE(wm8988_right_mixer_controls)),
303
304 SND_SOC_DAPM_PGA("Right Out 2", WM8988_PWR2, 3, 0, NULL, 0),
305 SND_SOC_DAPM_PGA("Left Out 2", WM8988_PWR2, 4, 0, NULL, 0),
306 SND_SOC_DAPM_PGA("Right Out 1", WM8988_PWR2, 5, 0, NULL, 0),
307 SND_SOC_DAPM_PGA("Left Out 1", WM8988_PWR2, 6, 0, NULL, 0),
308
309 SND_SOC_DAPM_POST("LRC control", wm8988_lrc_control),
310
311 SND_SOC_DAPM_OUTPUT("LOUT1"),
312 SND_SOC_DAPM_OUTPUT("ROUT1"),
313 SND_SOC_DAPM_OUTPUT("LOUT2"),
314 SND_SOC_DAPM_OUTPUT("ROUT2"),
315 SND_SOC_DAPM_OUTPUT("VREF"),
316
317 SND_SOC_DAPM_INPUT("LINPUT1"),
318 SND_SOC_DAPM_INPUT("LINPUT2"),
319 SND_SOC_DAPM_INPUT("RINPUT1"),
320 SND_SOC_DAPM_INPUT("RINPUT2"),
321};
322
323static const struct snd_soc_dapm_route audio_map[] = {
324
325 { "Left Line Mux", "Line 1", "LINPUT1" },
326 { "Left Line Mux", "Line 2", "LINPUT2" },
327 { "Left Line Mux", "PGA", "Left PGA Mux" },
328 { "Left Line Mux", "Differential", "Differential Mux" },
329
330 { "Right Line Mux", "Line 1", "RINPUT1" },
331 { "Right Line Mux", "Line 2", "RINPUT2" },
332 { "Right Line Mux", "PGA", "Right PGA Mux" },
333 { "Right Line Mux", "Differential", "Differential Mux" },
334
335 { "Left PGA Mux", "Line 1", "LINPUT1" },
336 { "Left PGA Mux", "Line 2", "LINPUT2" },
337 { "Left PGA Mux", "Differential", "Differential Mux" },
338
339 { "Right PGA Mux", "Line 1", "RINPUT1" },
340 { "Right PGA Mux", "Line 2", "RINPUT2" },
341 { "Right PGA Mux", "Differential", "Differential Mux" },
342
343 { "Differential Mux", "Line 1", "LINPUT1" },
344 { "Differential Mux", "Line 1", "RINPUT1" },
345 { "Differential Mux", "Line 2", "LINPUT2" },
346 { "Differential Mux", "Line 2", "RINPUT2" },
347
348 { "Left ADC Mux", "Stereo", "Left PGA Mux" },
349 { "Left ADC Mux", "Mono (Left)", "Left PGA Mux" },
350 { "Left ADC Mux", "Digital Mono", "Left PGA Mux" },
351
352 { "Right ADC Mux", "Stereo", "Right PGA Mux" },
353 { "Right ADC Mux", "Mono (Right)", "Right PGA Mux" },
354 { "Right ADC Mux", "Digital Mono", "Right PGA Mux" },
355
356 { "Left ADC", NULL, "Left ADC Mux" },
357 { "Right ADC", NULL, "Right ADC Mux" },
358
359 { "Left Line Mux", "Line 1", "LINPUT1" },
360 { "Left Line Mux", "Line 2", "LINPUT2" },
361 { "Left Line Mux", "PGA", "Left PGA Mux" },
362 { "Left Line Mux", "Differential", "Differential Mux" },
363
364 { "Right Line Mux", "Line 1", "RINPUT1" },
365 { "Right Line Mux", "Line 2", "RINPUT2" },
366 { "Right Line Mux", "PGA", "Right PGA Mux" },
367 { "Right Line Mux", "Differential", "Differential Mux" },
368
369 { "Left Mixer", "Playback Switch", "Left DAC" },
370 { "Left Mixer", "Left Bypass Switch", "Left Line Mux" },
371 { "Left Mixer", "Right Playback Switch", "Right DAC" },
372 { "Left Mixer", "Right Bypass Switch", "Right Line Mux" },
373
374 { "Right Mixer", "Left Playback Switch", "Left DAC" },
375 { "Right Mixer", "Left Bypass Switch", "Left Line Mux" },
376 { "Right Mixer", "Playback Switch", "Right DAC" },
377 { "Right Mixer", "Right Bypass Switch", "Right Line Mux" },
378
379 { "Left Out 1", NULL, "Left Mixer" },
380 { "LOUT1", NULL, "Left Out 1" },
381 { "Right Out 1", NULL, "Right Mixer" },
382 { "ROUT1", NULL, "Right Out 1" },
383
384 { "Left Out 2", NULL, "Left Mixer" },
385 { "LOUT2", NULL, "Left Out 2" },
386 { "Right Out 2", NULL, "Right Mixer" },
387 { "ROUT2", NULL, "Right Out 2" },
388};
389
390struct _coeff_div {
391 u32 mclk;
392 u32 rate;
393 u16 fs;
394 u8 sr:5;
395 u8 usb:1;
396};
397
398/* codec hifi mclk clock divider coefficients */
399static const struct _coeff_div coeff_div[] = {
400 /* 8k */
401 {12288000, 8000, 1536, 0x6, 0x0},
402 {11289600, 8000, 1408, 0x16, 0x0},
403 {18432000, 8000, 2304, 0x7, 0x0},
404 {16934400, 8000, 2112, 0x17, 0x0},
405 {12000000, 8000, 1500, 0x6, 0x1},
406
407 /* 11.025k */
408 {11289600, 11025, 1024, 0x18, 0x0},
409 {16934400, 11025, 1536, 0x19, 0x0},
410 {12000000, 11025, 1088, 0x19, 0x1},
411
412 /* 16k */
413 {12288000, 16000, 768, 0xa, 0x0},
414 {18432000, 16000, 1152, 0xb, 0x0},
415 {12000000, 16000, 750, 0xa, 0x1},
416
417 /* 22.05k */
418 {11289600, 22050, 512, 0x1a, 0x0},
419 {16934400, 22050, 768, 0x1b, 0x0},
420 {12000000, 22050, 544, 0x1b, 0x1},
421
422 /* 32k */
423 {12288000, 32000, 384, 0xc, 0x0},
424 {18432000, 32000, 576, 0xd, 0x0},
425 {12000000, 32000, 375, 0xa, 0x1},
426
427 /* 44.1k */
428 {11289600, 44100, 256, 0x10, 0x0},
429 {16934400, 44100, 384, 0x11, 0x0},
430 {12000000, 44100, 272, 0x11, 0x1},
431
432 /* 48k */
433 {12288000, 48000, 256, 0x0, 0x0},
434 {18432000, 48000, 384, 0x1, 0x0},
435 {12000000, 48000, 250, 0x0, 0x1},
436
437 /* 88.2k */
438 {11289600, 88200, 128, 0x1e, 0x0},
439 {16934400, 88200, 192, 0x1f, 0x0},
440 {12000000, 88200, 136, 0x1f, 0x1},
441
442 /* 96k */
443 {12288000, 96000, 128, 0xe, 0x0},
444 {18432000, 96000, 192, 0xf, 0x0},
445 {12000000, 96000, 125, 0xe, 0x1},
446};
447
448static inline int get_coeff(int mclk, int rate)
449{
450 int i;
451
452 for (i = 0; i < ARRAY_SIZE(coeff_div); i++) {
453 if (coeff_div[i].rate == rate && coeff_div[i].mclk == mclk)
454 return i;
455 }
456
457 return -EINVAL;
458}
459
460/* The set of rates we can generate from the above for each SYSCLK */
461
462static unsigned int rates_12288[] = {
463 8000, 12000, 16000, 24000, 24000, 32000, 48000, 96000,
464};
465
466static struct snd_pcm_hw_constraint_list constraints_12288 = {
467 .count = ARRAY_SIZE(rates_12288),
468 .list = rates_12288,
469};
470
471static unsigned int rates_112896[] = {
472 8000, 11025, 22050, 44100,
473};
474
475static struct snd_pcm_hw_constraint_list constraints_112896 = {
476 .count = ARRAY_SIZE(rates_112896),
477 .list = rates_112896,
478};
479
480static unsigned int rates_12[] = {
481 8000, 11025, 12000, 16000, 22050, 2400, 32000, 41100, 48000,
482 48000, 88235, 96000,
483};
484
485static struct snd_pcm_hw_constraint_list constraints_12 = {
486 .count = ARRAY_SIZE(rates_12),
487 .list = rates_12,
488};
489
490/*
491 * Note that this should be called from init rather than from hw_params.
492 */
493static int wm8988_set_dai_sysclk(struct snd_soc_dai *codec_dai,
494 int clk_id, unsigned int freq, int dir)
495{
496 struct snd_soc_codec *codec = codec_dai->codec;
497 struct wm8988_priv *wm8988 = codec->private_data;
498
499 switch (freq) {
500 case 11289600:
501 case 18432000:
502 case 22579200:
503 case 36864000:
504 wm8988->sysclk_constraints = &constraints_112896;
505 wm8988->sysclk = freq;
506 return 0;
507
508 case 12288000:
509 case 16934400:
510 case 24576000:
511 case 33868800:
512 wm8988->sysclk_constraints = &constraints_12288;
513 wm8988->sysclk = freq;
514 return 0;
515
516 case 12000000:
517 case 24000000:
518 wm8988->sysclk_constraints = &constraints_12;
519 wm8988->sysclk = freq;
520 return 0;
521 }
522 return -EINVAL;
523}
524
525static int wm8988_set_dai_fmt(struct snd_soc_dai *codec_dai,
526 unsigned int fmt)
527{
528 struct snd_soc_codec *codec = codec_dai->codec;
529 u16 iface = 0;
530
531 /* set master/slave audio interface */
532 switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
533 case SND_SOC_DAIFMT_CBM_CFM:
534 iface = 0x0040;
535 break;
536 case SND_SOC_DAIFMT_CBS_CFS:
537 break;
538 default:
539 return -EINVAL;
540 }
541
542 /* interface format */
543 switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
544 case SND_SOC_DAIFMT_I2S:
545 iface |= 0x0002;
546 break;
547 case SND_SOC_DAIFMT_RIGHT_J:
548 break;
549 case SND_SOC_DAIFMT_LEFT_J:
550 iface |= 0x0001;
551 break;
552 case SND_SOC_DAIFMT_DSP_A:
553 iface |= 0x0003;
554 break;
555 case SND_SOC_DAIFMT_DSP_B:
556 iface |= 0x0013;
557 break;
558 default:
559 return -EINVAL;
560 }
561
562 /* clock inversion */
563 switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
564 case SND_SOC_DAIFMT_NB_NF:
565 break;
566 case SND_SOC_DAIFMT_IB_IF:
567 iface |= 0x0090;
568 break;
569 case SND_SOC_DAIFMT_IB_NF:
570 iface |= 0x0080;
571 break;
572 case SND_SOC_DAIFMT_NB_IF:
573 iface |= 0x0010;
574 break;
575 default:
576 return -EINVAL;
577 }
578
579 snd_soc_write(codec, WM8988_IFACE, iface);
580 return 0;
581}
582
583static int wm8988_pcm_startup(struct snd_pcm_substream *substream,
584 struct snd_soc_dai *dai)
585{
586 struct snd_soc_codec *codec = dai->codec;
587 struct wm8988_priv *wm8988 = codec->private_data;
588
589 /* The set of sample rates that can be supported depends on the
590 * MCLK supplied to the CODEC - enforce this.
591 */
592 if (!wm8988->sysclk) {
593 dev_err(codec->dev,
594 "No MCLK configured, call set_sysclk() on init\n");
595 return -EINVAL;
596 }
597
598 snd_pcm_hw_constraint_list(substream->runtime, 0,
599 SNDRV_PCM_HW_PARAM_RATE,
600 wm8988->sysclk_constraints);
601
602 return 0;
603}
604
605static int wm8988_pcm_hw_params(struct snd_pcm_substream *substream,
606 struct snd_pcm_hw_params *params,
607 struct snd_soc_dai *dai)
608{
609 struct snd_soc_pcm_runtime *rtd = substream->private_data;
610 struct snd_soc_device *socdev = rtd->socdev;
611 struct snd_soc_codec *codec = socdev->card->codec;
612 struct wm8988_priv *wm8988 = codec->private_data;
613 u16 iface = snd_soc_read(codec, WM8988_IFACE) & 0x1f3;
614 u16 srate = snd_soc_read(codec, WM8988_SRATE) & 0x180;
615 int coeff;
616
617 coeff = get_coeff(wm8988->sysclk, params_rate(params));
618 if (coeff < 0) {
619 coeff = get_coeff(wm8988->sysclk / 2, params_rate(params));
620 srate |= 0x40;
621 }
622 if (coeff < 0) {
623 dev_err(codec->dev,
624 "Unable to configure sample rate %dHz with %dHz MCLK\n",
625 params_rate(params), wm8988->sysclk);
626 return coeff;
627 }
628
629 /* bit size */
630 switch (params_format(params)) {
631 case SNDRV_PCM_FORMAT_S16_LE:
632 break;
633 case SNDRV_PCM_FORMAT_S20_3LE:
634 iface |= 0x0004;
635 break;
636 case SNDRV_PCM_FORMAT_S24_LE:
637 iface |= 0x0008;
638 break;
639 case SNDRV_PCM_FORMAT_S32_LE:
640 iface |= 0x000c;
641 break;
642 }
643
644 /* set iface & srate */
645 snd_soc_write(codec, WM8988_IFACE, iface);
646 if (coeff >= 0)
647 snd_soc_write(codec, WM8988_SRATE, srate |
648 (coeff_div[coeff].sr << 1) | coeff_div[coeff].usb);
649
650 return 0;
651}
652
653static int wm8988_mute(struct snd_soc_dai *dai, int mute)
654{
655 struct snd_soc_codec *codec = dai->codec;
656 u16 mute_reg = snd_soc_read(codec, WM8988_ADCDAC) & 0xfff7;
657
658 if (mute)
659 snd_soc_write(codec, WM8988_ADCDAC, mute_reg | 0x8);
660 else
661 snd_soc_write(codec, WM8988_ADCDAC, mute_reg);
662 return 0;
663}
664
665static int wm8988_set_bias_level(struct snd_soc_codec *codec,
666 enum snd_soc_bias_level level)
667{
668 u16 pwr_reg = snd_soc_read(codec, WM8988_PWR1) & ~0x1c1;
669
670 switch (level) {
671 case SND_SOC_BIAS_ON:
672 break;
673
674 case SND_SOC_BIAS_PREPARE:
675 /* VREF, VMID=2x50k, digital enabled */
676 snd_soc_write(codec, WM8988_PWR1, pwr_reg | 0x00c0);
677 break;
678
679 case SND_SOC_BIAS_STANDBY:
680 if (codec->bias_level == SND_SOC_BIAS_OFF) {
681 /* VREF, VMID=2x5k */
682 snd_soc_write(codec, WM8988_PWR1, pwr_reg | 0x1c1);
683
684 /* Charge caps */
685 msleep(100);
686 }
687
688 /* VREF, VMID=2*500k, digital stopped */
689 snd_soc_write(codec, WM8988_PWR1, pwr_reg | 0x0141);
690 break;
691
692 case SND_SOC_BIAS_OFF:
693 snd_soc_write(codec, WM8988_PWR1, 0x0000);
694 break;
695 }
696 codec->bias_level = level;
697 return 0;
698}
699
700#define WM8988_RATES SNDRV_PCM_RATE_8000_96000
701
702#define WM8988_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE |\
703 SNDRV_PCM_FMTBIT_S24_LE)
704
705static struct snd_soc_dai_ops wm8988_ops = {
706 .startup = wm8988_pcm_startup,
707 .hw_params = wm8988_pcm_hw_params,
708 .set_fmt = wm8988_set_dai_fmt,
709 .set_sysclk = wm8988_set_dai_sysclk,
710 .digital_mute = wm8988_mute,
711};
712
713struct snd_soc_dai wm8988_dai = {
714 .name = "WM8988",
715 .playback = {
716 .stream_name = "Playback",
717 .channels_min = 1,
718 .channels_max = 2,
719 .rates = WM8988_RATES,
720 .formats = WM8988_FORMATS,
721 },
722 .capture = {
723 .stream_name = "Capture",
724 .channels_min = 1,
725 .channels_max = 2,
726 .rates = WM8988_RATES,
727 .formats = WM8988_FORMATS,
728 },
729 .ops = &wm8988_ops,
730 .symmetric_rates = 1,
731};
732EXPORT_SYMBOL_GPL(wm8988_dai);
733
734static int wm8988_suspend(struct platform_device *pdev, pm_message_t state)
735{
736 struct snd_soc_device *socdev = platform_get_drvdata(pdev);
737 struct snd_soc_codec *codec = socdev->card->codec;
738
739 wm8988_set_bias_level(codec, SND_SOC_BIAS_OFF);
740 return 0;
741}
742
743static int wm8988_resume(struct platform_device *pdev)
744{
745 struct snd_soc_device *socdev = platform_get_drvdata(pdev);
746 struct snd_soc_codec *codec = socdev->card->codec;
747 int i;
748 u8 data[2];
749 u16 *cache = codec->reg_cache;
750
751 /* Sync reg_cache with the hardware */
752 for (i = 0; i < WM8988_NUM_REG; i++) {
753 if (i == WM8988_RESET)
754 continue;
755 data[0] = (i << 1) | ((cache[i] >> 8) & 0x0001);
756 data[1] = cache[i] & 0x00ff;
757 codec->hw_write(codec->control_data, data, 2);
758 }
759
760 wm8988_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
761
762 return 0;
763}
764
765static struct snd_soc_codec *wm8988_codec;
766
767static int wm8988_probe(struct platform_device *pdev)
768{
769 struct snd_soc_device *socdev = platform_get_drvdata(pdev);
770 struct snd_soc_codec *codec;
771 int ret = 0;
772
773 if (wm8988_codec == NULL) {
774 dev_err(&pdev->dev, "Codec device not registered\n");
775 return -ENODEV;
776 }
777
778 socdev->card->codec = wm8988_codec;
779 codec = wm8988_codec;
780
781 /* register pcms */
782 ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1);
783 if (ret < 0) {
784 dev_err(codec->dev, "failed to create pcms: %d\n", ret);
785 goto pcm_err;
786 }
787
788 snd_soc_add_controls(codec, wm8988_snd_controls,
789 ARRAY_SIZE(wm8988_snd_controls));
790 snd_soc_dapm_new_controls(codec, wm8988_dapm_widgets,
791 ARRAY_SIZE(wm8988_dapm_widgets));
792 snd_soc_dapm_add_routes(codec, audio_map, ARRAY_SIZE(audio_map));
793 snd_soc_dapm_new_widgets(codec);
794
795 ret = snd_soc_init_card(socdev);
796 if (ret < 0) {
797 dev_err(codec->dev, "failed to register card: %d\n", ret);
798 goto card_err;
799 }
800
801 return ret;
802
803card_err:
804 snd_soc_free_pcms(socdev);
805 snd_soc_dapm_free(socdev);
806pcm_err:
807 return ret;
808}
809
810static int wm8988_remove(struct platform_device *pdev)
811{
812 struct snd_soc_device *socdev = platform_get_drvdata(pdev);
813
814 snd_soc_free_pcms(socdev);
815 snd_soc_dapm_free(socdev);
816
817 return 0;
818}
819
820struct snd_soc_codec_device soc_codec_dev_wm8988 = {
821 .probe = wm8988_probe,
822 .remove = wm8988_remove,
823 .suspend = wm8988_suspend,
824 .resume = wm8988_resume,
825};
826EXPORT_SYMBOL_GPL(soc_codec_dev_wm8988);
827
828static int wm8988_register(struct wm8988_priv *wm8988,
829 enum snd_soc_control_type control)
830{
831 struct snd_soc_codec *codec = &wm8988->codec;
832 int ret;
833 u16 reg;
834
835 if (wm8988_codec) {
836 dev_err(codec->dev, "Another WM8988 is registered\n");
837 ret = -EINVAL;
838 goto err;
839 }
840
841 mutex_init(&codec->mutex);
842 INIT_LIST_HEAD(&codec->dapm_widgets);
843 INIT_LIST_HEAD(&codec->dapm_paths);
844
845 codec->private_data = wm8988;
846 codec->name = "WM8988";
847 codec->owner = THIS_MODULE;
848 codec->dai = &wm8988_dai;
849 codec->num_dai = 1;
850 codec->reg_cache_size = ARRAY_SIZE(wm8988->reg_cache);
851 codec->reg_cache = &wm8988->reg_cache;
852 codec->bias_level = SND_SOC_BIAS_OFF;
853 codec->set_bias_level = wm8988_set_bias_level;
854
855 memcpy(codec->reg_cache, wm8988_reg,
856 sizeof(wm8988_reg));
857
858 ret = snd_soc_codec_set_cache_io(codec, 7, 9, control);
859 if (ret < 0) {
860 dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret);
861 goto err;
862 }
863
864 ret = wm8988_reset(codec);
865 if (ret < 0) {
866 dev_err(codec->dev, "Failed to issue reset\n");
867 goto err;
868 }
869
870 /* set the update bits (we always update left then right) */
871 reg = snd_soc_read(codec, WM8988_RADC);
872 snd_soc_write(codec, WM8988_RADC, reg | 0x100);
873 reg = snd_soc_read(codec, WM8988_RDAC);
874 snd_soc_write(codec, WM8988_RDAC, reg | 0x0100);
875 reg = snd_soc_read(codec, WM8988_ROUT1V);
876 snd_soc_write(codec, WM8988_ROUT1V, reg | 0x0100);
877 reg = snd_soc_read(codec, WM8988_ROUT2V);
878 snd_soc_write(codec, WM8988_ROUT2V, reg | 0x0100);
879 reg = snd_soc_read(codec, WM8988_RINVOL);
880 snd_soc_write(codec, WM8988_RINVOL, reg | 0x0100);
881
882 wm8988_set_bias_level(&wm8988->codec, SND_SOC_BIAS_STANDBY);
883
884 wm8988_dai.dev = codec->dev;
885
886 wm8988_codec = codec;
887
888 ret = snd_soc_register_codec(codec);
889 if (ret != 0) {
890 dev_err(codec->dev, "Failed to register codec: %d\n", ret);
891 goto err;
892 }
893
894 ret = snd_soc_register_dai(&wm8988_dai);
895 if (ret != 0) {
896 dev_err(codec->dev, "Failed to register DAI: %d\n", ret);
897 snd_soc_unregister_codec(codec);
898 goto err_codec;
899 }
900
901 return 0;
902
903err_codec:
904 snd_soc_unregister_codec(codec);
905err:
906 kfree(wm8988);
907 return ret;
908}
909
910static void wm8988_unregister(struct wm8988_priv *wm8988)
911{
912 wm8988_set_bias_level(&wm8988->codec, SND_SOC_BIAS_OFF);
913 snd_soc_unregister_dai(&wm8988_dai);
914 snd_soc_unregister_codec(&wm8988->codec);
915 kfree(wm8988);
916 wm8988_codec = NULL;
917}
918
919#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
920static int wm8988_i2c_probe(struct i2c_client *i2c,
921 const struct i2c_device_id *id)
922{
923 struct wm8988_priv *wm8988;
924 struct snd_soc_codec *codec;
925
926 wm8988 = kzalloc(sizeof(struct wm8988_priv), GFP_KERNEL);
927 if (wm8988 == NULL)
928 return -ENOMEM;
929
930 codec = &wm8988->codec;
931
932 i2c_set_clientdata(i2c, wm8988);
933 codec->control_data = i2c;
934
935 codec->dev = &i2c->dev;
936
937 return wm8988_register(wm8988, SND_SOC_I2C);
938}
939
940static int wm8988_i2c_remove(struct i2c_client *client)
941{
942 struct wm8988_priv *wm8988 = i2c_get_clientdata(client);
943 wm8988_unregister(wm8988);
944 return 0;
945}
946
947#ifdef CONFIG_PM
948static int wm8988_i2c_suspend(struct i2c_client *client, pm_message_t msg)
949{
950 return snd_soc_suspend_device(&client->dev);
951}
952
953static int wm8988_i2c_resume(struct i2c_client *client)
954{
955 return snd_soc_resume_device(&client->dev);
956}
957#else
958#define wm8988_i2c_suspend NULL
959#define wm8988_i2c_resume NULL
960#endif
961
962static const struct i2c_device_id wm8988_i2c_id[] = {
963 { "wm8988", 0 },
964 { }
965};
966MODULE_DEVICE_TABLE(i2c, wm8988_i2c_id);
967
968static struct i2c_driver wm8988_i2c_driver = {
969 .driver = {
970 .name = "WM8988",
971 .owner = THIS_MODULE,
972 },
973 .probe = wm8988_i2c_probe,
974 .remove = wm8988_i2c_remove,
975 .suspend = wm8988_i2c_suspend,
976 .resume = wm8988_i2c_resume,
977 .id_table = wm8988_i2c_id,
978};
979#endif
980
981#if defined(CONFIG_SPI_MASTER)
982static int __devinit wm8988_spi_probe(struct spi_device *spi)
983{
984 struct wm8988_priv *wm8988;
985 struct snd_soc_codec *codec;
986
987 wm8988 = kzalloc(sizeof(struct wm8988_priv), GFP_KERNEL);
988 if (wm8988 == NULL)
989 return -ENOMEM;
990
991 codec = &wm8988->codec;
992 codec->control_data = spi;
993 codec->dev = &spi->dev;
994
995 spi->dev.driver_data = wm8988;
996
997 return wm8988_register(wm8988, SND_SOC_SPI);
998}
999
1000static int __devexit wm8988_spi_remove(struct spi_device *spi)
1001{
1002 struct wm8988_priv *wm8988 = spi->dev.driver_data;
1003
1004 wm8988_unregister(wm8988);
1005
1006 return 0;
1007}
1008
1009#ifdef CONFIG_PM
1010static int wm8988_spi_suspend(struct spi_device *spi, pm_message_t msg)
1011{
1012 return snd_soc_suspend_device(&spi->dev);
1013}
1014
1015static int wm8988_spi_resume(struct spi_device *spi)
1016{
1017 return snd_soc_resume_device(&spi->dev);
1018}
1019#else
1020#define wm8988_spi_suspend NULL
1021#define wm8988_spi_resume NULL
1022#endif
1023
1024static struct spi_driver wm8988_spi_driver = {
1025 .driver = {
1026 .name = "wm8988",
1027 .bus = &spi_bus_type,
1028 .owner = THIS_MODULE,
1029 },
1030 .probe = wm8988_spi_probe,
1031 .remove = __devexit_p(wm8988_spi_remove),
1032 .suspend = wm8988_spi_suspend,
1033 .resume = wm8988_spi_resume,
1034};
1035#endif
1036
1037static int __init wm8988_modinit(void)
1038{
1039 int ret;
1040
1041#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
1042 ret = i2c_add_driver(&wm8988_i2c_driver);
1043 if (ret != 0)
1044 pr_err("WM8988: Unable to register I2C driver: %d\n", ret);
1045#endif
1046#if defined(CONFIG_SPI_MASTER)
1047 ret = spi_register_driver(&wm8988_spi_driver);
1048 if (ret != 0)
1049 pr_err("WM8988: Unable to register SPI driver: %d\n", ret);
1050#endif
1051 return ret;
1052}
1053module_init(wm8988_modinit);
1054
1055static void __exit wm8988_exit(void)
1056{
1057#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
1058 i2c_del_driver(&wm8988_i2c_driver);
1059#endif
1060#if defined(CONFIG_SPI_MASTER)
1061 spi_unregister_driver(&wm8988_spi_driver);
1062#endif
1063}
1064module_exit(wm8988_exit);
1065
1066
1067MODULE_DESCRIPTION("ASoC WM8988 driver");
1068MODULE_AUTHOR("Mark Brown <broonie@opensource.wolfsonmicro.com>");
1069MODULE_LICENSE("GPL");
diff --git a/sound/soc/codecs/wm8988.h b/sound/soc/codecs/wm8988.h
new file mode 100644
index 000000000000..4552d37fdd41
--- /dev/null
+++ b/sound/soc/codecs/wm8988.h
@@ -0,0 +1,60 @@
1/*
2 * Copyright 2005 Openedhand Ltd.
3 *
4 * Author: Richard Purdie <richard@openedhand.com>
5 *
6 * Based on WM8753.h
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License version 2 as
10 * published by the Free Software Foundation.
11 *
12 */
13
14#ifndef _WM8988_H
15#define _WM8988_H
16
17/* WM8988 register space */
18
19#define WM8988_LINVOL 0x00
20#define WM8988_RINVOL 0x01
21#define WM8988_LOUT1V 0x02
22#define WM8988_ROUT1V 0x03
23#define WM8988_ADCDAC 0x05
24#define WM8988_IFACE 0x07
25#define WM8988_SRATE 0x08
26#define WM8988_LDAC 0x0a
27#define WM8988_RDAC 0x0b
28#define WM8988_BASS 0x0c
29#define WM8988_TREBLE 0x0d
30#define WM8988_RESET 0x0f
31#define WM8988_3D 0x10
32#define WM8988_ALC1 0x11
33#define WM8988_ALC2 0x12
34#define WM8988_ALC3 0x13
35#define WM8988_NGATE 0x14
36#define WM8988_LADC 0x15
37#define WM8988_RADC 0x16
38#define WM8988_ADCTL1 0x17
39#define WM8988_ADCTL2 0x18
40#define WM8988_PWR1 0x19
41#define WM8988_PWR2 0x1a
42#define WM8988_ADCTL3 0x1b
43#define WM8988_ADCIN 0x1f
44#define WM8988_LADCIN 0x20
45#define WM8988_RADCIN 0x21
46#define WM8988_LOUTM1 0x22
47#define WM8988_LOUTM2 0x23
48#define WM8988_ROUTM1 0x24
49#define WM8988_ROUTM2 0x25
50#define WM8988_LOUT2V 0x28
51#define WM8988_ROUT2V 0x29
52#define WM8988_LPPB 0x43
53#define WM8988_NUM_REG 0x44
54
55#define WM8988_SYSCLK 0
56
57extern struct snd_soc_dai wm8988_dai;
58extern struct snd_soc_codec_device soc_codec_dev_wm8988;
59
60#endif
diff --git a/sound/soc/codecs/wm8990.c b/sound/soc/codecs/wm8990.c
index 40cd274eb1ef..2d702db4131d 100644
--- a/sound/soc/codecs/wm8990.c
+++ b/sound/soc/codecs/wm8990.c
@@ -108,53 +108,7 @@ static const u16 wm8990_reg[] = {
108 0x0000, /* R63 - Driver internal */ 108 0x0000, /* R63 - Driver internal */
109}; 109};
110 110
111/* 111#define wm8990_reset(c) snd_soc_write(c, WM8990_RESET, 0)
112 * read wm8990 register cache
113 */
114static inline unsigned int wm8990_read_reg_cache(struct snd_soc_codec *codec,
115 unsigned int reg)
116{
117 u16 *cache = codec->reg_cache;
118 BUG_ON(reg >= ARRAY_SIZE(wm8990_reg));
119 return cache[reg];
120}
121
122/*
123 * write wm8990 register cache
124 */
125static inline void wm8990_write_reg_cache(struct snd_soc_codec *codec,
126 unsigned int reg, unsigned int value)
127{
128 u16 *cache = codec->reg_cache;
129
130 /* Reset register and reserved registers are uncached */
131 if (reg == 0 || reg >= ARRAY_SIZE(wm8990_reg))
132 return;
133
134 cache[reg] = value;
135}
136
137/*
138 * write to the wm8990 register space
139 */
140static int wm8990_write(struct snd_soc_codec *codec, unsigned int reg,
141 unsigned int value)
142{
143 u8 data[3];
144
145 data[0] = reg & 0xFF;
146 data[1] = (value >> 8) & 0xFF;
147 data[2] = value & 0xFF;
148
149 wm8990_write_reg_cache(codec, reg, value);
150
151 if (codec->hw_write(codec->control_data, data, 3) == 2)
152 return 0;
153 else
154 return -EIO;
155}
156
157#define wm8990_reset(c) wm8990_write(c, WM8990_RESET, 0)
158 112
159static const DECLARE_TLV_DB_LINEAR(rec_mix_tlv, -1500, 600); 113static const DECLARE_TLV_DB_LINEAR(rec_mix_tlv, -1500, 600);
160 114
@@ -187,8 +141,8 @@ static int wm899x_outpga_put_volsw_vu(struct snd_kcontrol *kcontrol,
187 return ret; 141 return ret;
188 142
189 /* now hit the volume update bits (always bit 8) */ 143 /* now hit the volume update bits (always bit 8) */
190 val = wm8990_read_reg_cache(codec, reg); 144 val = snd_soc_read(codec, reg);
191 return wm8990_write(codec, reg, val | 0x0100); 145 return snd_soc_write(codec, reg, val | 0x0100);
192} 146}
193 147
194#define SOC_WM899X_OUTPGA_SINGLE_R_TLV(xname, reg, shift, max, invert,\ 148#define SOC_WM899X_OUTPGA_SINGLE_R_TLV(xname, reg, shift, max, invert,\
@@ -427,8 +381,8 @@ static int inmixer_event(struct snd_soc_dapm_widget *w,
427{ 381{
428 u16 reg, fakepower; 382 u16 reg, fakepower;
429 383
430 reg = wm8990_read_reg_cache(w->codec, WM8990_POWER_MANAGEMENT_2); 384 reg = snd_soc_read(w->codec, WM8990_POWER_MANAGEMENT_2);
431 fakepower = wm8990_read_reg_cache(w->codec, WM8990_INTDRIVBITS); 385 fakepower = snd_soc_read(w->codec, WM8990_INTDRIVBITS);
432 386
433 if (fakepower & ((1 << WM8990_INMIXL_PWR_BIT) | 387 if (fakepower & ((1 << WM8990_INMIXL_PWR_BIT) |
434 (1 << WM8990_AINLMUX_PWR_BIT))) { 388 (1 << WM8990_AINLMUX_PWR_BIT))) {
@@ -443,7 +397,7 @@ static int inmixer_event(struct snd_soc_dapm_widget *w,
443 } else { 397 } else {
444 reg &= ~WM8990_AINL_ENA; 398 reg &= ~WM8990_AINL_ENA;
445 } 399 }
446 wm8990_write(w->codec, WM8990_POWER_MANAGEMENT_2, reg); 400 snd_soc_write(w->codec, WM8990_POWER_MANAGEMENT_2, reg);
447 401
448 return 0; 402 return 0;
449} 403}
@@ -457,7 +411,7 @@ static int outmixer_event(struct snd_soc_dapm_widget *w,
457 411
458 switch (reg_shift) { 412 switch (reg_shift) {
459 case WM8990_SPEAKER_MIXER | (WM8990_LDSPK_BIT << 8) : 413 case WM8990_SPEAKER_MIXER | (WM8990_LDSPK_BIT << 8) :
460 reg = wm8990_read_reg_cache(w->codec, WM8990_OUTPUT_MIXER1); 414 reg = snd_soc_read(w->codec, WM8990_OUTPUT_MIXER1);
461 if (reg & WM8990_LDLO) { 415 if (reg & WM8990_LDLO) {
462 printk(KERN_WARNING 416 printk(KERN_WARNING
463 "Cannot set as Output Mixer 1 LDLO Set\n"); 417 "Cannot set as Output Mixer 1 LDLO Set\n");
@@ -465,7 +419,7 @@ static int outmixer_event(struct snd_soc_dapm_widget *w,
465 } 419 }
466 break; 420 break;
467 case WM8990_SPEAKER_MIXER | (WM8990_RDSPK_BIT << 8): 421 case WM8990_SPEAKER_MIXER | (WM8990_RDSPK_BIT << 8):
468 reg = wm8990_read_reg_cache(w->codec, WM8990_OUTPUT_MIXER2); 422 reg = snd_soc_read(w->codec, WM8990_OUTPUT_MIXER2);
469 if (reg & WM8990_RDRO) { 423 if (reg & WM8990_RDRO) {
470 printk(KERN_WARNING 424 printk(KERN_WARNING
471 "Cannot set as Output Mixer 2 RDRO Set\n"); 425 "Cannot set as Output Mixer 2 RDRO Set\n");
@@ -473,7 +427,7 @@ static int outmixer_event(struct snd_soc_dapm_widget *w,
473 } 427 }
474 break; 428 break;
475 case WM8990_OUTPUT_MIXER1 | (WM8990_LDLO_BIT << 8): 429 case WM8990_OUTPUT_MIXER1 | (WM8990_LDLO_BIT << 8):
476 reg = wm8990_read_reg_cache(w->codec, WM8990_SPEAKER_MIXER); 430 reg = snd_soc_read(w->codec, WM8990_SPEAKER_MIXER);
477 if (reg & WM8990_LDSPK) { 431 if (reg & WM8990_LDSPK) {
478 printk(KERN_WARNING 432 printk(KERN_WARNING
479 "Cannot set as Speaker Mixer LDSPK Set\n"); 433 "Cannot set as Speaker Mixer LDSPK Set\n");
@@ -481,7 +435,7 @@ static int outmixer_event(struct snd_soc_dapm_widget *w,
481 } 435 }
482 break; 436 break;
483 case WM8990_OUTPUT_MIXER2 | (WM8990_RDRO_BIT << 8): 437 case WM8990_OUTPUT_MIXER2 | (WM8990_RDRO_BIT << 8):
484 reg = wm8990_read_reg_cache(w->codec, WM8990_SPEAKER_MIXER); 438 reg = snd_soc_read(w->codec, WM8990_SPEAKER_MIXER);
485 if (reg & WM8990_RDSPK) { 439 if (reg & WM8990_RDSPK) {
486 printk(KERN_WARNING 440 printk(KERN_WARNING
487 "Cannot set as Speaker Mixer RDSPK Set\n"); 441 "Cannot set as Speaker Mixer RDSPK Set\n");
@@ -998,7 +952,7 @@ static void pll_factors(struct _pll_div *pll_div, unsigned int target,
998 952
999 if ((Ndiv < 6) || (Ndiv > 12)) 953 if ((Ndiv < 6) || (Ndiv > 12))
1000 printk(KERN_WARNING 954 printk(KERN_WARNING
1001 "WM8990 N value outwith recommended range! N = %d\n", Ndiv); 955 "WM8990 N value outwith recommended range! N = %u\n", Ndiv);
1002 956
1003 pll_div->n = Ndiv; 957 pll_div->n = Ndiv;
1004 Nmod = target % source; 958 Nmod = target % source;
@@ -1029,24 +983,24 @@ static int wm8990_set_dai_pll(struct snd_soc_dai *codec_dai,
1029 pll_factors(&pll_div, freq_out * 4, freq_in); 983 pll_factors(&pll_div, freq_out * 4, freq_in);
1030 984
1031 /* Turn on PLL */ 985 /* Turn on PLL */
1032 reg = wm8990_read_reg_cache(codec, WM8990_POWER_MANAGEMENT_2); 986 reg = snd_soc_read(codec, WM8990_POWER_MANAGEMENT_2);
1033 reg |= WM8990_PLL_ENA; 987 reg |= WM8990_PLL_ENA;
1034 wm8990_write(codec, WM8990_POWER_MANAGEMENT_2, reg); 988 snd_soc_write(codec, WM8990_POWER_MANAGEMENT_2, reg);
1035 989
1036 /* sysclk comes from PLL */ 990 /* sysclk comes from PLL */
1037 reg = wm8990_read_reg_cache(codec, WM8990_CLOCKING_2); 991 reg = snd_soc_read(codec, WM8990_CLOCKING_2);
1038 wm8990_write(codec, WM8990_CLOCKING_2, reg | WM8990_SYSCLK_SRC); 992 snd_soc_write(codec, WM8990_CLOCKING_2, reg | WM8990_SYSCLK_SRC);
1039 993
1040 /* set up N , fractional mode and pre-divisor if neccessary */ 994 /* set up N , fractional mode and pre-divisor if neccessary */
1041 wm8990_write(codec, WM8990_PLL1, pll_div.n | WM8990_SDM | 995 snd_soc_write(codec, WM8990_PLL1, pll_div.n | WM8990_SDM |
1042 (pll_div.div2?WM8990_PRESCALE:0)); 996 (pll_div.div2?WM8990_PRESCALE:0));
1043 wm8990_write(codec, WM8990_PLL2, (u8)(pll_div.k>>8)); 997 snd_soc_write(codec, WM8990_PLL2, (u8)(pll_div.k>>8));
1044 wm8990_write(codec, WM8990_PLL3, (u8)(pll_div.k & 0xFF)); 998 snd_soc_write(codec, WM8990_PLL3, (u8)(pll_div.k & 0xFF));
1045 } else { 999 } else {
1046 /* Turn on PLL */ 1000 /* Turn on PLL */
1047 reg = wm8990_read_reg_cache(codec, WM8990_POWER_MANAGEMENT_2); 1001 reg = snd_soc_read(codec, WM8990_POWER_MANAGEMENT_2);
1048 reg &= ~WM8990_PLL_ENA; 1002 reg &= ~WM8990_PLL_ENA;
1049 wm8990_write(codec, WM8990_POWER_MANAGEMENT_2, reg); 1003 snd_soc_write(codec, WM8990_POWER_MANAGEMENT_2, reg);
1050 } 1004 }
1051 return 0; 1005 return 0;
1052} 1006}
@@ -1073,8 +1027,8 @@ static int wm8990_set_dai_fmt(struct snd_soc_dai *codec_dai,
1073 struct snd_soc_codec *codec = codec_dai->codec; 1027 struct snd_soc_codec *codec = codec_dai->codec;
1074 u16 audio1, audio3; 1028 u16 audio1, audio3;
1075 1029
1076 audio1 = wm8990_read_reg_cache(codec, WM8990_AUDIO_INTERFACE_1); 1030 audio1 = snd_soc_read(codec, WM8990_AUDIO_INTERFACE_1);
1077 audio3 = wm8990_read_reg_cache(codec, WM8990_AUDIO_INTERFACE_3); 1031 audio3 = snd_soc_read(codec, WM8990_AUDIO_INTERFACE_3);
1078 1032
1079 /* set master/slave audio interface */ 1033 /* set master/slave audio interface */
1080 switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { 1034 switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
@@ -1115,8 +1069,8 @@ static int wm8990_set_dai_fmt(struct snd_soc_dai *codec_dai,
1115 return -EINVAL; 1069 return -EINVAL;
1116 } 1070 }
1117 1071
1118 wm8990_write(codec, WM8990_AUDIO_INTERFACE_1, audio1); 1072 snd_soc_write(codec, WM8990_AUDIO_INTERFACE_1, audio1);
1119 wm8990_write(codec, WM8990_AUDIO_INTERFACE_3, audio3); 1073 snd_soc_write(codec, WM8990_AUDIO_INTERFACE_3, audio3);
1120 return 0; 1074 return 0;
1121} 1075}
1122 1076
@@ -1128,24 +1082,24 @@ static int wm8990_set_dai_clkdiv(struct snd_soc_dai *codec_dai,
1128 1082
1129 switch (div_id) { 1083 switch (div_id) {
1130 case WM8990_MCLK_DIV: 1084 case WM8990_MCLK_DIV:
1131 reg = wm8990_read_reg_cache(codec, WM8990_CLOCKING_2) & 1085 reg = snd_soc_read(codec, WM8990_CLOCKING_2) &
1132 ~WM8990_MCLK_DIV_MASK; 1086 ~WM8990_MCLK_DIV_MASK;
1133 wm8990_write(codec, WM8990_CLOCKING_2, reg | div); 1087 snd_soc_write(codec, WM8990_CLOCKING_2, reg | div);
1134 break; 1088 break;
1135 case WM8990_DACCLK_DIV: 1089 case WM8990_DACCLK_DIV:
1136 reg = wm8990_read_reg_cache(codec, WM8990_CLOCKING_2) & 1090 reg = snd_soc_read(codec, WM8990_CLOCKING_2) &
1137 ~WM8990_DAC_CLKDIV_MASK; 1091 ~WM8990_DAC_CLKDIV_MASK;
1138 wm8990_write(codec, WM8990_CLOCKING_2, reg | div); 1092 snd_soc_write(codec, WM8990_CLOCKING_2, reg | div);
1139 break; 1093 break;
1140 case WM8990_ADCCLK_DIV: 1094 case WM8990_ADCCLK_DIV:
1141 reg = wm8990_read_reg_cache(codec, WM8990_CLOCKING_2) & 1095 reg = snd_soc_read(codec, WM8990_CLOCKING_2) &
1142 ~WM8990_ADC_CLKDIV_MASK; 1096 ~WM8990_ADC_CLKDIV_MASK;
1143 wm8990_write(codec, WM8990_CLOCKING_2, reg | div); 1097 snd_soc_write(codec, WM8990_CLOCKING_2, reg | div);
1144 break; 1098 break;
1145 case WM8990_BCLK_DIV: 1099 case WM8990_BCLK_DIV:
1146 reg = wm8990_read_reg_cache(codec, WM8990_CLOCKING_1) & 1100 reg = snd_soc_read(codec, WM8990_CLOCKING_1) &
1147 ~WM8990_BCLK_DIV_MASK; 1101 ~WM8990_BCLK_DIV_MASK;
1148 wm8990_write(codec, WM8990_CLOCKING_1, reg | div); 1102 snd_soc_write(codec, WM8990_CLOCKING_1, reg | div);
1149 break; 1103 break;
1150 default: 1104 default:
1151 return -EINVAL; 1105 return -EINVAL;
@@ -1164,7 +1118,7 @@ static int wm8990_hw_params(struct snd_pcm_substream *substream,
1164 struct snd_soc_pcm_runtime *rtd = substream->private_data; 1118 struct snd_soc_pcm_runtime *rtd = substream->private_data;
1165 struct snd_soc_device *socdev = rtd->socdev; 1119 struct snd_soc_device *socdev = rtd->socdev;
1166 struct snd_soc_codec *codec = socdev->card->codec; 1120 struct snd_soc_codec *codec = socdev->card->codec;
1167 u16 audio1 = wm8990_read_reg_cache(codec, WM8990_AUDIO_INTERFACE_1); 1121 u16 audio1 = snd_soc_read(codec, WM8990_AUDIO_INTERFACE_1);
1168 1122
1169 audio1 &= ~WM8990_AIF_WL_MASK; 1123 audio1 &= ~WM8990_AIF_WL_MASK;
1170 /* bit size */ 1124 /* bit size */
@@ -1182,7 +1136,7 @@ static int wm8990_hw_params(struct snd_pcm_substream *substream,
1182 break; 1136 break;
1183 } 1137 }
1184 1138
1185 wm8990_write(codec, WM8990_AUDIO_INTERFACE_1, audio1); 1139 snd_soc_write(codec, WM8990_AUDIO_INTERFACE_1, audio1);
1186 return 0; 1140 return 0;
1187} 1141}
1188 1142
@@ -1191,12 +1145,12 @@ static int wm8990_mute(struct snd_soc_dai *dai, int mute)
1191 struct snd_soc_codec *codec = dai->codec; 1145 struct snd_soc_codec *codec = dai->codec;
1192 u16 val; 1146 u16 val;
1193 1147
1194 val = wm8990_read_reg_cache(codec, WM8990_DAC_CTRL) & ~WM8990_DAC_MUTE; 1148 val = snd_soc_read(codec, WM8990_DAC_CTRL) & ~WM8990_DAC_MUTE;
1195 1149
1196 if (mute) 1150 if (mute)
1197 wm8990_write(codec, WM8990_DAC_CTRL, val | WM8990_DAC_MUTE); 1151 snd_soc_write(codec, WM8990_DAC_CTRL, val | WM8990_DAC_MUTE);
1198 else 1152 else
1199 wm8990_write(codec, WM8990_DAC_CTRL, val); 1153 snd_soc_write(codec, WM8990_DAC_CTRL, val);
1200 1154
1201 return 0; 1155 return 0;
1202} 1156}
@@ -1212,21 +1166,21 @@ static int wm8990_set_bias_level(struct snd_soc_codec *codec,
1212 1166
1213 case SND_SOC_BIAS_PREPARE: 1167 case SND_SOC_BIAS_PREPARE:
1214 /* VMID=2*50k */ 1168 /* VMID=2*50k */
1215 val = wm8990_read_reg_cache(codec, WM8990_POWER_MANAGEMENT_1) & 1169 val = snd_soc_read(codec, WM8990_POWER_MANAGEMENT_1) &
1216 ~WM8990_VMID_MODE_MASK; 1170 ~WM8990_VMID_MODE_MASK;
1217 wm8990_write(codec, WM8990_POWER_MANAGEMENT_1, val | 0x2); 1171 snd_soc_write(codec, WM8990_POWER_MANAGEMENT_1, val | 0x2);
1218 break; 1172 break;
1219 1173
1220 case SND_SOC_BIAS_STANDBY: 1174 case SND_SOC_BIAS_STANDBY:
1221 if (codec->bias_level == SND_SOC_BIAS_OFF) { 1175 if (codec->bias_level == SND_SOC_BIAS_OFF) {
1222 /* Enable all output discharge bits */ 1176 /* Enable all output discharge bits */
1223 wm8990_write(codec, WM8990_ANTIPOP1, WM8990_DIS_LLINE | 1177 snd_soc_write(codec, WM8990_ANTIPOP1, WM8990_DIS_LLINE |
1224 WM8990_DIS_RLINE | WM8990_DIS_OUT3 | 1178 WM8990_DIS_RLINE | WM8990_DIS_OUT3 |
1225 WM8990_DIS_OUT4 | WM8990_DIS_LOUT | 1179 WM8990_DIS_OUT4 | WM8990_DIS_LOUT |
1226 WM8990_DIS_ROUT); 1180 WM8990_DIS_ROUT);
1227 1181
1228 /* Enable POBCTRL, SOFT_ST, VMIDTOG and BUFDCOPEN */ 1182 /* Enable POBCTRL, SOFT_ST, VMIDTOG and BUFDCOPEN */
1229 wm8990_write(codec, WM8990_ANTIPOP2, WM8990_SOFTST | 1183 snd_soc_write(codec, WM8990_ANTIPOP2, WM8990_SOFTST |
1230 WM8990_BUFDCOPEN | WM8990_POBCTRL | 1184 WM8990_BUFDCOPEN | WM8990_POBCTRL |
1231 WM8990_VMIDTOG); 1185 WM8990_VMIDTOG);
1232 1186
@@ -1234,83 +1188,83 @@ static int wm8990_set_bias_level(struct snd_soc_codec *codec,
1234 msleep(msecs_to_jiffies(300)); 1188 msleep(msecs_to_jiffies(300));
1235 1189
1236 /* Disable VMIDTOG */ 1190 /* Disable VMIDTOG */
1237 wm8990_write(codec, WM8990_ANTIPOP2, WM8990_SOFTST | 1191 snd_soc_write(codec, WM8990_ANTIPOP2, WM8990_SOFTST |
1238 WM8990_BUFDCOPEN | WM8990_POBCTRL); 1192 WM8990_BUFDCOPEN | WM8990_POBCTRL);
1239 1193
1240 /* disable all output discharge bits */ 1194 /* disable all output discharge bits */
1241 wm8990_write(codec, WM8990_ANTIPOP1, 0); 1195 snd_soc_write(codec, WM8990_ANTIPOP1, 0);
1242 1196
1243 /* Enable outputs */ 1197 /* Enable outputs */
1244 wm8990_write(codec, WM8990_POWER_MANAGEMENT_1, 0x1b00); 1198 snd_soc_write(codec, WM8990_POWER_MANAGEMENT_1, 0x1b00);
1245 1199
1246 msleep(msecs_to_jiffies(50)); 1200 msleep(msecs_to_jiffies(50));
1247 1201
1248 /* Enable VMID at 2x50k */ 1202 /* Enable VMID at 2x50k */
1249 wm8990_write(codec, WM8990_POWER_MANAGEMENT_1, 0x1f02); 1203 snd_soc_write(codec, WM8990_POWER_MANAGEMENT_1, 0x1f02);
1250 1204
1251 msleep(msecs_to_jiffies(100)); 1205 msleep(msecs_to_jiffies(100));
1252 1206
1253 /* Enable VREF */ 1207 /* Enable VREF */
1254 wm8990_write(codec, WM8990_POWER_MANAGEMENT_1, 0x1f03); 1208 snd_soc_write(codec, WM8990_POWER_MANAGEMENT_1, 0x1f03);
1255 1209
1256 msleep(msecs_to_jiffies(600)); 1210 msleep(msecs_to_jiffies(600));
1257 1211
1258 /* Enable BUFIOEN */ 1212 /* Enable BUFIOEN */
1259 wm8990_write(codec, WM8990_ANTIPOP2, WM8990_SOFTST | 1213 snd_soc_write(codec, WM8990_ANTIPOP2, WM8990_SOFTST |
1260 WM8990_BUFDCOPEN | WM8990_POBCTRL | 1214 WM8990_BUFDCOPEN | WM8990_POBCTRL |
1261 WM8990_BUFIOEN); 1215 WM8990_BUFIOEN);
1262 1216
1263 /* Disable outputs */ 1217 /* Disable outputs */
1264 wm8990_write(codec, WM8990_POWER_MANAGEMENT_1, 0x3); 1218 snd_soc_write(codec, WM8990_POWER_MANAGEMENT_1, 0x3);
1265 1219
1266 /* disable POBCTRL, SOFT_ST and BUFDCOPEN */ 1220 /* disable POBCTRL, SOFT_ST and BUFDCOPEN */
1267 wm8990_write(codec, WM8990_ANTIPOP2, WM8990_BUFIOEN); 1221 snd_soc_write(codec, WM8990_ANTIPOP2, WM8990_BUFIOEN);
1268 1222
1269 /* Enable workaround for ADC clocking issue. */ 1223 /* Enable workaround for ADC clocking issue. */
1270 wm8990_write(codec, WM8990_EXT_ACCESS_ENA, 0x2); 1224 snd_soc_write(codec, WM8990_EXT_ACCESS_ENA, 0x2);
1271 wm8990_write(codec, WM8990_EXT_CTL1, 0xa003); 1225 snd_soc_write(codec, WM8990_EXT_CTL1, 0xa003);
1272 wm8990_write(codec, WM8990_EXT_ACCESS_ENA, 0); 1226 snd_soc_write(codec, WM8990_EXT_ACCESS_ENA, 0);
1273 } 1227 }
1274 1228
1275 /* VMID=2*250k */ 1229 /* VMID=2*250k */
1276 val = wm8990_read_reg_cache(codec, WM8990_POWER_MANAGEMENT_1) & 1230 val = snd_soc_read(codec, WM8990_POWER_MANAGEMENT_1) &
1277 ~WM8990_VMID_MODE_MASK; 1231 ~WM8990_VMID_MODE_MASK;
1278 wm8990_write(codec, WM8990_POWER_MANAGEMENT_1, val | 0x4); 1232 snd_soc_write(codec, WM8990_POWER_MANAGEMENT_1, val | 0x4);
1279 break; 1233 break;
1280 1234
1281 case SND_SOC_BIAS_OFF: 1235 case SND_SOC_BIAS_OFF:
1282 /* Enable POBCTRL and SOFT_ST */ 1236 /* Enable POBCTRL and SOFT_ST */
1283 wm8990_write(codec, WM8990_ANTIPOP2, WM8990_SOFTST | 1237 snd_soc_write(codec, WM8990_ANTIPOP2, WM8990_SOFTST |
1284 WM8990_POBCTRL | WM8990_BUFIOEN); 1238 WM8990_POBCTRL | WM8990_BUFIOEN);
1285 1239
1286 /* Enable POBCTRL, SOFT_ST and BUFDCOPEN */ 1240 /* Enable POBCTRL, SOFT_ST and BUFDCOPEN */
1287 wm8990_write(codec, WM8990_ANTIPOP2, WM8990_SOFTST | 1241 snd_soc_write(codec, WM8990_ANTIPOP2, WM8990_SOFTST |
1288 WM8990_BUFDCOPEN | WM8990_POBCTRL | 1242 WM8990_BUFDCOPEN | WM8990_POBCTRL |
1289 WM8990_BUFIOEN); 1243 WM8990_BUFIOEN);
1290 1244
1291 /* mute DAC */ 1245 /* mute DAC */
1292 val = wm8990_read_reg_cache(codec, WM8990_DAC_CTRL); 1246 val = snd_soc_read(codec, WM8990_DAC_CTRL);
1293 wm8990_write(codec, WM8990_DAC_CTRL, val | WM8990_DAC_MUTE); 1247 snd_soc_write(codec, WM8990_DAC_CTRL, val | WM8990_DAC_MUTE);
1294 1248
1295 /* Enable any disabled outputs */ 1249 /* Enable any disabled outputs */
1296 wm8990_write(codec, WM8990_POWER_MANAGEMENT_1, 0x1f03); 1250 snd_soc_write(codec, WM8990_POWER_MANAGEMENT_1, 0x1f03);
1297 1251
1298 /* Disable VMID */ 1252 /* Disable VMID */
1299 wm8990_write(codec, WM8990_POWER_MANAGEMENT_1, 0x1f01); 1253 snd_soc_write(codec, WM8990_POWER_MANAGEMENT_1, 0x1f01);
1300 1254
1301 msleep(msecs_to_jiffies(300)); 1255 msleep(msecs_to_jiffies(300));
1302 1256
1303 /* Enable all output discharge bits */ 1257 /* Enable all output discharge bits */
1304 wm8990_write(codec, WM8990_ANTIPOP1, WM8990_DIS_LLINE | 1258 snd_soc_write(codec, WM8990_ANTIPOP1, WM8990_DIS_LLINE |
1305 WM8990_DIS_RLINE | WM8990_DIS_OUT3 | 1259 WM8990_DIS_RLINE | WM8990_DIS_OUT3 |
1306 WM8990_DIS_OUT4 | WM8990_DIS_LOUT | 1260 WM8990_DIS_OUT4 | WM8990_DIS_LOUT |
1307 WM8990_DIS_ROUT); 1261 WM8990_DIS_ROUT);
1308 1262
1309 /* Disable VREF */ 1263 /* Disable VREF */
1310 wm8990_write(codec, WM8990_POWER_MANAGEMENT_1, 0x0); 1264 snd_soc_write(codec, WM8990_POWER_MANAGEMENT_1, 0x0);
1311 1265
1312 /* disable POBCTRL, SOFT_ST and BUFDCOPEN */ 1266 /* disable POBCTRL, SOFT_ST and BUFDCOPEN */
1313 wm8990_write(codec, WM8990_ANTIPOP2, 0x0); 1267 snd_soc_write(codec, WM8990_ANTIPOP2, 0x0);
1314 break; 1268 break;
1315 } 1269 }
1316 1270
@@ -1411,8 +1365,6 @@ static int wm8990_init(struct snd_soc_device *socdev)
1411 1365
1412 codec->name = "WM8990"; 1366 codec->name = "WM8990";
1413 codec->owner = THIS_MODULE; 1367 codec->owner = THIS_MODULE;
1414 codec->read = wm8990_read_reg_cache;
1415 codec->write = wm8990_write;
1416 codec->set_bias_level = wm8990_set_bias_level; 1368 codec->set_bias_level = wm8990_set_bias_level;
1417 codec->dai = &wm8990_dai; 1369 codec->dai = &wm8990_dai;
1418 codec->num_dai = 2; 1370 codec->num_dai = 2;
@@ -1422,6 +1374,12 @@ static int wm8990_init(struct snd_soc_device *socdev)
1422 if (codec->reg_cache == NULL) 1374 if (codec->reg_cache == NULL)
1423 return -ENOMEM; 1375 return -ENOMEM;
1424 1376
1377 ret = snd_soc_codec_set_cache_io(codec, 8, 16, SND_SOC_I2C);
1378 if (ret < 0) {
1379 printk(KERN_ERR "wm8990: failed to set cache I/O: %d\n", ret);
1380 goto pcm_err;
1381 }
1382
1425 wm8990_reset(codec); 1383 wm8990_reset(codec);
1426 1384
1427 /* register pcms */ 1385 /* register pcms */
@@ -1435,18 +1393,18 @@ static int wm8990_init(struct snd_soc_device *socdev)
1435 codec->bias_level = SND_SOC_BIAS_OFF; 1393 codec->bias_level = SND_SOC_BIAS_OFF;
1436 wm8990_set_bias_level(codec, SND_SOC_BIAS_STANDBY); 1394 wm8990_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
1437 1395
1438 reg = wm8990_read_reg_cache(codec, WM8990_AUDIO_INTERFACE_4); 1396 reg = snd_soc_read(codec, WM8990_AUDIO_INTERFACE_4);
1439 wm8990_write(codec, WM8990_AUDIO_INTERFACE_4, reg | WM8990_ALRCGPIO1); 1397 snd_soc_write(codec, WM8990_AUDIO_INTERFACE_4, reg | WM8990_ALRCGPIO1);
1440 1398
1441 reg = wm8990_read_reg_cache(codec, WM8990_GPIO1_GPIO2) & 1399 reg = snd_soc_read(codec, WM8990_GPIO1_GPIO2) &
1442 ~WM8990_GPIO1_SEL_MASK; 1400 ~WM8990_GPIO1_SEL_MASK;
1443 wm8990_write(codec, WM8990_GPIO1_GPIO2, reg | 1); 1401 snd_soc_write(codec, WM8990_GPIO1_GPIO2, reg | 1);
1444 1402
1445 reg = wm8990_read_reg_cache(codec, WM8990_POWER_MANAGEMENT_2); 1403 reg = snd_soc_read(codec, WM8990_POWER_MANAGEMENT_2);
1446 wm8990_write(codec, WM8990_POWER_MANAGEMENT_2, reg | WM8990_OPCLK_ENA); 1404 snd_soc_write(codec, WM8990_POWER_MANAGEMENT_2, reg | WM8990_OPCLK_ENA);
1447 1405
1448 wm8990_write(codec, WM8990_LEFT_OUTPUT_VOLUME, 0x50 | (1<<8)); 1406 snd_soc_write(codec, WM8990_LEFT_OUTPUT_VOLUME, 0x50 | (1<<8));
1449 wm8990_write(codec, WM8990_RIGHT_OUTPUT_VOLUME, 0x50 | (1<<8)); 1407 snd_soc_write(codec, WM8990_RIGHT_OUTPUT_VOLUME, 0x50 | (1<<8));
1450 1408
1451 snd_soc_add_controls(codec, wm8990_snd_controls, 1409 snd_soc_add_controls(codec, wm8990_snd_controls,
1452 ARRAY_SIZE(wm8990_snd_controls)); 1410 ARRAY_SIZE(wm8990_snd_controls));
diff --git a/sound/soc/codecs/wm8993.c b/sound/soc/codecs/wm8993.c
new file mode 100644
index 000000000000..cd1566931135
--- /dev/null
+++ b/sound/soc/codecs/wm8993.c
@@ -0,0 +1,1534 @@
1/*
2 * wm8993.c -- WM8993 ALSA SoC audio driver
3 *
4 * Copyright 2009 Wolfson Microelectronics plc
5 *
6 * Author: Mark Brown <broonie@opensource.wolfsonmicro.com>
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License version 2 as
10 * published by the Free Software Foundation.
11 */
12
13#include <linux/module.h>
14#include <linux/moduleparam.h>
15#include <linux/init.h>
16#include <linux/delay.h>
17#include <linux/pm.h>
18#include <linux/i2c.h>
19#include <linux/spi/spi.h>
20#include <sound/core.h>
21#include <sound/pcm.h>
22#include <sound/pcm_params.h>
23#include <sound/tlv.h>
24#include <sound/soc.h>
25#include <sound/soc-dapm.h>
26#include <sound/initval.h>
27#include <sound/wm8993.h>
28
29#include "wm8993.h"
30#include "wm_hubs.h"
31
32static u16 wm8993_reg_defaults[WM8993_REGISTER_COUNT] = {
33 0x8993, /* R0 - Software Reset */
34 0x0000, /* R1 - Power Management (1) */
35 0x6000, /* R2 - Power Management (2) */
36 0x0000, /* R3 - Power Management (3) */
37 0x4050, /* R4 - Audio Interface (1) */
38 0x4000, /* R5 - Audio Interface (2) */
39 0x01C8, /* R6 - Clocking 1 */
40 0x0000, /* R7 - Clocking 2 */
41 0x0000, /* R8 - Audio Interface (3) */
42 0x0040, /* R9 - Audio Interface (4) */
43 0x0004, /* R10 - DAC CTRL */
44 0x00C0, /* R11 - Left DAC Digital Volume */
45 0x00C0, /* R12 - Right DAC Digital Volume */
46 0x0000, /* R13 - Digital Side Tone */
47 0x0300, /* R14 - ADC CTRL */
48 0x00C0, /* R15 - Left ADC Digital Volume */
49 0x00C0, /* R16 - Right ADC Digital Volume */
50 0x0000, /* R17 */
51 0x0000, /* R18 - GPIO CTRL 1 */
52 0x0010, /* R19 - GPIO1 */
53 0x0000, /* R20 - IRQ_DEBOUNCE */
54 0x0000, /* R21 */
55 0x8000, /* R22 - GPIOCTRL 2 */
56 0x0800, /* R23 - GPIO_POL */
57 0x008B, /* R24 - Left Line Input 1&2 Volume */
58 0x008B, /* R25 - Left Line Input 3&4 Volume */
59 0x008B, /* R26 - Right Line Input 1&2 Volume */
60 0x008B, /* R27 - Right Line Input 3&4 Volume */
61 0x006D, /* R28 - Left Output Volume */
62 0x006D, /* R29 - Right Output Volume */
63 0x0066, /* R30 - Line Outputs Volume */
64 0x0020, /* R31 - HPOUT2 Volume */
65 0x0079, /* R32 - Left OPGA Volume */
66 0x0079, /* R33 - Right OPGA Volume */
67 0x0003, /* R34 - SPKMIXL Attenuation */
68 0x0003, /* R35 - SPKMIXR Attenuation */
69 0x0011, /* R36 - SPKOUT Mixers */
70 0x0100, /* R37 - SPKOUT Boost */
71 0x0079, /* R38 - Speaker Volume Left */
72 0x0079, /* R39 - Speaker Volume Right */
73 0x0000, /* R40 - Input Mixer2 */
74 0x0000, /* R41 - Input Mixer3 */
75 0x0000, /* R42 - Input Mixer4 */
76 0x0000, /* R43 - Input Mixer5 */
77 0x0000, /* R44 - Input Mixer6 */
78 0x0000, /* R45 - Output Mixer1 */
79 0x0000, /* R46 - Output Mixer2 */
80 0x0000, /* R47 - Output Mixer3 */
81 0x0000, /* R48 - Output Mixer4 */
82 0x0000, /* R49 - Output Mixer5 */
83 0x0000, /* R50 - Output Mixer6 */
84 0x0000, /* R51 - HPOUT2 Mixer */
85 0x0000, /* R52 - Line Mixer1 */
86 0x0000, /* R53 - Line Mixer2 */
87 0x0000, /* R54 - Speaker Mixer */
88 0x0000, /* R55 - Additional Control */
89 0x0000, /* R56 - AntiPOP1 */
90 0x0000, /* R57 - AntiPOP2 */
91 0x0000, /* R58 - MICBIAS */
92 0x0000, /* R59 */
93 0x0000, /* R60 - FLL Control 1 */
94 0x0000, /* R61 - FLL Control 2 */
95 0x0000, /* R62 - FLL Control 3 */
96 0x2EE0, /* R63 - FLL Control 4 */
97 0x0002, /* R64 - FLL Control 5 */
98 0x2287, /* R65 - Clocking 3 */
99 0x025F, /* R66 - Clocking 4 */
100 0x0000, /* R67 - MW Slave Control */
101 0x0000, /* R68 */
102 0x0002, /* R69 - Bus Control 1 */
103 0x0000, /* R70 - Write Sequencer 0 */
104 0x0000, /* R71 - Write Sequencer 1 */
105 0x0000, /* R72 - Write Sequencer 2 */
106 0x0000, /* R73 - Write Sequencer 3 */
107 0x0000, /* R74 - Write Sequencer 4 */
108 0x0000, /* R75 - Write Sequencer 5 */
109 0x1F25, /* R76 - Charge Pump 1 */
110 0x0000, /* R77 */
111 0x0000, /* R78 */
112 0x0000, /* R79 */
113 0x0000, /* R80 */
114 0x0000, /* R81 - Class W 0 */
115 0x0000, /* R82 */
116 0x0000, /* R83 */
117 0x0000, /* R84 - DC Servo 0 */
118 0x054A, /* R85 - DC Servo 1 */
119 0x0000, /* R86 */
120 0x0000, /* R87 - DC Servo 3 */
121 0x0000, /* R88 - DC Servo Readback 0 */
122 0x0000, /* R89 - DC Servo Readback 1 */
123 0x0000, /* R90 - DC Servo Readback 2 */
124 0x0000, /* R91 */
125 0x0000, /* R92 */
126 0x0000, /* R93 */
127 0x0000, /* R94 */
128 0x0000, /* R95 */
129 0x0100, /* R96 - Analogue HP 0 */
130 0x0000, /* R97 */
131 0x0000, /* R98 - EQ1 */
132 0x000C, /* R99 - EQ2 */
133 0x000C, /* R100 - EQ3 */
134 0x000C, /* R101 - EQ4 */
135 0x000C, /* R102 - EQ5 */
136 0x000C, /* R103 - EQ6 */
137 0x0FCA, /* R104 - EQ7 */
138 0x0400, /* R105 - EQ8 */
139 0x00D8, /* R106 - EQ9 */
140 0x1EB5, /* R107 - EQ10 */
141 0xF145, /* R108 - EQ11 */
142 0x0B75, /* R109 - EQ12 */
143 0x01C5, /* R110 - EQ13 */
144 0x1C58, /* R111 - EQ14 */
145 0xF373, /* R112 - EQ15 */
146 0x0A54, /* R113 - EQ16 */
147 0x0558, /* R114 - EQ17 */
148 0x168E, /* R115 - EQ18 */
149 0xF829, /* R116 - EQ19 */
150 0x07AD, /* R117 - EQ20 */
151 0x1103, /* R118 - EQ21 */
152 0x0564, /* R119 - EQ22 */
153 0x0559, /* R120 - EQ23 */
154 0x4000, /* R121 - EQ24 */
155 0x0000, /* R122 - Digital Pulls */
156 0x0F08, /* R123 - DRC Control 1 */
157 0x0000, /* R124 - DRC Control 2 */
158 0x0080, /* R125 - DRC Control 3 */
159 0x0000, /* R126 - DRC Control 4 */
160};
161
162static struct {
163 int ratio;
164 int clk_sys_rate;
165} clk_sys_rates[] = {
166 { 64, 0 },
167 { 128, 1 },
168 { 192, 2 },
169 { 256, 3 },
170 { 384, 4 },
171 { 512, 5 },
172 { 768, 6 },
173 { 1024, 7 },
174 { 1408, 8 },
175 { 1536, 9 },
176};
177
178static struct {
179 int rate;
180 int sample_rate;
181} sample_rates[] = {
182 { 8000, 0 },
183 { 11025, 1 },
184 { 12000, 1 },
185 { 16000, 2 },
186 { 22050, 3 },
187 { 24000, 3 },
188 { 32000, 4 },
189 { 44100, 5 },
190 { 48000, 5 },
191};
192
193static struct {
194 int div; /* *10 due to .5s */
195 int bclk_div;
196} bclk_divs[] = {
197 { 10, 0 },
198 { 15, 1 },
199 { 20, 2 },
200 { 30, 3 },
201 { 40, 4 },
202 { 55, 5 },
203 { 60, 6 },
204 { 80, 7 },
205 { 110, 8 },
206 { 120, 9 },
207 { 160, 10 },
208 { 220, 11 },
209 { 240, 12 },
210 { 320, 13 },
211 { 440, 14 },
212 { 480, 15 },
213};
214
215struct wm8993_priv {
216 u16 reg_cache[WM8993_REGISTER_COUNT];
217 struct wm8993_platform_data pdata;
218 struct snd_soc_codec codec;
219 int master;
220 int sysclk_source;
221 unsigned int mclk_rate;
222 unsigned int sysclk_rate;
223 unsigned int fs;
224 unsigned int bclk;
225 int class_w_users;
226 unsigned int fll_fref;
227 unsigned int fll_fout;
228};
229
230static unsigned int wm8993_read_hw(struct snd_soc_codec *codec, u8 reg)
231{
232 struct i2c_msg xfer[2];
233 u16 data;
234 int ret;
235 struct i2c_client *i2c = codec->control_data;
236
237 /* Write register */
238 xfer[0].addr = i2c->addr;
239 xfer[0].flags = 0;
240 xfer[0].len = 1;
241 xfer[0].buf = &reg;
242
243 /* Read data */
244 xfer[1].addr = i2c->addr;
245 xfer[1].flags = I2C_M_RD;
246 xfer[1].len = 2;
247 xfer[1].buf = (u8 *)&data;
248
249 ret = i2c_transfer(i2c->adapter, xfer, 2);
250 if (ret != 2) {
251 dev_err(codec->dev, "Failed to read 0x%x: %d\n", reg, ret);
252 return 0;
253 }
254
255 return (data >> 8) | ((data & 0xff) << 8);
256}
257
258static int wm8993_volatile(unsigned int reg)
259{
260 switch (reg) {
261 case WM8993_SOFTWARE_RESET:
262 case WM8993_DC_SERVO_0:
263 case WM8993_DC_SERVO_READBACK_0:
264 case WM8993_DC_SERVO_READBACK_1:
265 case WM8993_DC_SERVO_READBACK_2:
266 return 1;
267 default:
268 return 0;
269 }
270}
271
272static unsigned int wm8993_read(struct snd_soc_codec *codec,
273 unsigned int reg)
274{
275 u16 *reg_cache = codec->reg_cache;
276
277 BUG_ON(reg > WM8993_MAX_REGISTER);
278
279 if (wm8993_volatile(reg))
280 return wm8993_read_hw(codec, reg);
281 else
282 return reg_cache[reg];
283}
284
285static int wm8993_write(struct snd_soc_codec *codec, unsigned int reg,
286 unsigned int value)
287{
288 u16 *reg_cache = codec->reg_cache;
289 u8 data[3];
290 int ret;
291
292 BUG_ON(reg > WM8993_MAX_REGISTER);
293
294 /* data is
295 * D15..D9 WM8993 register offset
296 * D8...D0 register data
297 */
298 data[0] = reg;
299 data[1] = value >> 8;
300 data[2] = value & 0x00ff;
301
302 if (!wm8993_volatile(reg))
303 reg_cache[reg] = value;
304
305 ret = codec->hw_write(codec->control_data, data, 3);
306
307 if (ret == 3)
308 return 0;
309 if (ret < 0)
310 return ret;
311 return -EIO;
312}
313
314struct _fll_div {
315 u16 fll_fratio;
316 u16 fll_outdiv;
317 u16 fll_clk_ref_div;
318 u16 n;
319 u16 k;
320};
321
322/* The size in bits of the FLL divide multiplied by 10
323 * to allow rounding later */
324#define FIXED_FLL_SIZE ((1 << 16) * 10)
325
326static struct {
327 unsigned int min;
328 unsigned int max;
329 u16 fll_fratio;
330 int ratio;
331} fll_fratios[] = {
332 { 0, 64000, 4, 16 },
333 { 64000, 128000, 3, 8 },
334 { 128000, 256000, 2, 4 },
335 { 256000, 1000000, 1, 2 },
336 { 1000000, 13500000, 0, 1 },
337};
338
339static int fll_factors(struct _fll_div *fll_div, unsigned int Fref,
340 unsigned int Fout)
341{
342 u64 Kpart;
343 unsigned int K, Ndiv, Nmod, target;
344 unsigned int div;
345 int i;
346
347 /* Fref must be <=13.5MHz */
348 div = 1;
349 fll_div->fll_clk_ref_div = 0;
350 while ((Fref / div) > 13500000) {
351 div *= 2;
352 fll_div->fll_clk_ref_div++;
353
354 if (div > 8) {
355 pr_err("Can't scale %dMHz input down to <=13.5MHz\n",
356 Fref);
357 return -EINVAL;
358 }
359 }
360
361 pr_debug("Fref=%u Fout=%u\n", Fref, Fout);
362
363 /* Apply the division for our remaining calculations */
364 Fref /= div;
365
366 /* Fvco should be 90-100MHz; don't check the upper bound */
367 div = 0;
368 target = Fout * 2;
369 while (target < 90000000) {
370 div++;
371 target *= 2;
372 if (div > 7) {
373 pr_err("Unable to find FLL_OUTDIV for Fout=%uHz\n",
374 Fout);
375 return -EINVAL;
376 }
377 }
378 fll_div->fll_outdiv = div;
379
380 pr_debug("Fvco=%dHz\n", target);
381
382 /* Find an appropraite FLL_FRATIO and factor it out of the target */
383 for (i = 0; i < ARRAY_SIZE(fll_fratios); i++) {
384 if (fll_fratios[i].min <= Fref && Fref <= fll_fratios[i].max) {
385 fll_div->fll_fratio = fll_fratios[i].fll_fratio;
386 target /= fll_fratios[i].ratio;
387 break;
388 }
389 }
390 if (i == ARRAY_SIZE(fll_fratios)) {
391 pr_err("Unable to find FLL_FRATIO for Fref=%uHz\n", Fref);
392 return -EINVAL;
393 }
394
395 /* Now, calculate N.K */
396 Ndiv = target / Fref;
397
398 fll_div->n = Ndiv;
399 Nmod = target % Fref;
400 pr_debug("Nmod=%d\n", Nmod);
401
402 /* Calculate fractional part - scale up so we can round. */
403 Kpart = FIXED_FLL_SIZE * (long long)Nmod;
404
405 do_div(Kpart, Fref);
406
407 K = Kpart & 0xFFFFFFFF;
408
409 if ((K % 10) >= 5)
410 K += 5;
411
412 /* Move down to proper range now rounding is done */
413 fll_div->k = K / 10;
414
415 pr_debug("N=%x K=%x FLL_FRATIO=%x FLL_OUTDIV=%x FLL_CLK_REF_DIV=%x\n",
416 fll_div->n, fll_div->k,
417 fll_div->fll_fratio, fll_div->fll_outdiv,
418 fll_div->fll_clk_ref_div);
419
420 return 0;
421}
422
423static int wm8993_set_fll(struct snd_soc_dai *dai, int fll_id,
424 unsigned int Fref, unsigned int Fout)
425{
426 struct snd_soc_codec *codec = dai->codec;
427 struct wm8993_priv *wm8993 = codec->private_data;
428 u16 reg1, reg4, reg5;
429 struct _fll_div fll_div;
430 int ret;
431
432 /* Any change? */
433 if (Fref == wm8993->fll_fref && Fout == wm8993->fll_fout)
434 return 0;
435
436 /* Disable the FLL */
437 if (Fout == 0) {
438 dev_dbg(codec->dev, "FLL disabled\n");
439 wm8993->fll_fref = 0;
440 wm8993->fll_fout = 0;
441
442 reg1 = wm8993_read(codec, WM8993_FLL_CONTROL_1);
443 reg1 &= ~WM8993_FLL_ENA;
444 wm8993_write(codec, WM8993_FLL_CONTROL_1, reg1);
445
446 return 0;
447 }
448
449 ret = fll_factors(&fll_div, Fref, Fout);
450 if (ret != 0)
451 return ret;
452
453 reg5 = wm8993_read(codec, WM8993_FLL_CONTROL_5);
454 reg5 &= ~WM8993_FLL_CLK_SRC_MASK;
455
456 switch (fll_id) {
457 case WM8993_FLL_MCLK:
458 break;
459
460 case WM8993_FLL_LRCLK:
461 reg5 |= 1;
462 break;
463
464 case WM8993_FLL_BCLK:
465 reg5 |= 2;
466 break;
467
468 default:
469 dev_err(codec->dev, "Unknown FLL ID %d\n", fll_id);
470 return -EINVAL;
471 }
472
473 /* Any FLL configuration change requires that the FLL be
474 * disabled first. */
475 reg1 = wm8993_read(codec, WM8993_FLL_CONTROL_1);
476 reg1 &= ~WM8993_FLL_ENA;
477 wm8993_write(codec, WM8993_FLL_CONTROL_1, reg1);
478
479 /* Apply the configuration */
480 if (fll_div.k)
481 reg1 |= WM8993_FLL_FRAC_MASK;
482 else
483 reg1 &= ~WM8993_FLL_FRAC_MASK;
484 wm8993_write(codec, WM8993_FLL_CONTROL_1, reg1);
485
486 wm8993_write(codec, WM8993_FLL_CONTROL_2,
487 (fll_div.fll_outdiv << WM8993_FLL_OUTDIV_SHIFT) |
488 (fll_div.fll_fratio << WM8993_FLL_FRATIO_SHIFT));
489 wm8993_write(codec, WM8993_FLL_CONTROL_3, fll_div.k);
490
491 reg4 = wm8993_read(codec, WM8993_FLL_CONTROL_4);
492 reg4 &= ~WM8993_FLL_N_MASK;
493 reg4 |= fll_div.n << WM8993_FLL_N_SHIFT;
494 wm8993_write(codec, WM8993_FLL_CONTROL_4, reg4);
495
496 reg5 &= ~WM8993_FLL_CLK_REF_DIV_MASK;
497 reg5 |= fll_div.fll_clk_ref_div << WM8993_FLL_CLK_REF_DIV_SHIFT;
498 wm8993_write(codec, WM8993_FLL_CONTROL_5, reg5);
499
500 /* Enable the FLL */
501 wm8993_write(codec, WM8993_FLL_CONTROL_1, reg1 | WM8993_FLL_ENA);
502
503 dev_dbg(codec->dev, "FLL enabled at %dHz->%dHz\n", Fref, Fout);
504
505 wm8993->fll_fref = Fref;
506 wm8993->fll_fout = Fout;
507
508 return 0;
509}
510
511static int configure_clock(struct snd_soc_codec *codec)
512{
513 struct wm8993_priv *wm8993 = codec->private_data;
514 unsigned int reg;
515
516 /* This should be done on init() for bypass paths */
517 switch (wm8993->sysclk_source) {
518 case WM8993_SYSCLK_MCLK:
519 dev_dbg(codec->dev, "Using %dHz MCLK\n", wm8993->mclk_rate);
520
521 reg = wm8993_read(codec, WM8993_CLOCKING_2);
522 reg &= ~WM8993_SYSCLK_SRC;
523 if (wm8993->mclk_rate > 13500000) {
524 reg |= WM8993_MCLK_DIV;
525 wm8993->sysclk_rate = wm8993->mclk_rate / 2;
526 } else {
527 reg &= ~WM8993_MCLK_DIV;
528 wm8993->sysclk_rate = wm8993->mclk_rate;
529 }
530 reg &= ~WM8993_MCLK_DIV;
531 reg &= ~(WM8993_MCLK_DIV | WM8993_SYSCLK_SRC);
532 wm8993_write(codec, WM8993_CLOCKING_2, reg);
533 break;
534
535 case WM8993_SYSCLK_FLL:
536 dev_dbg(codec->dev, "Using %dHz FLL clock\n",
537 wm8993->fll_fout);
538
539 reg = wm8993_read(codec, WM8993_CLOCKING_2);
540 reg |= WM8993_SYSCLK_SRC;
541 if (wm8993->fll_fout > 13500000) {
542 reg |= WM8993_MCLK_DIV;
543 wm8993->sysclk_rate = wm8993->fll_fout / 2;
544 } else {
545 reg &= ~WM8993_MCLK_DIV;
546 wm8993->sysclk_rate = wm8993->fll_fout;
547 }
548 wm8993_write(codec, WM8993_CLOCKING_2, reg);
549 break;
550
551 default:
552 dev_err(codec->dev, "System clock not configured\n");
553 return -EINVAL;
554 }
555
556 dev_dbg(codec->dev, "CLK_SYS is %dHz\n", wm8993->sysclk_rate);
557
558 return 0;
559}
560
561static const DECLARE_TLV_DB_SCALE(sidetone_tlv, -3600, 300, 0);
562static const DECLARE_TLV_DB_SCALE(drc_comp_threash, -4500, 75, 0);
563static const DECLARE_TLV_DB_SCALE(drc_comp_amp, -2250, 75, 0);
564static const DECLARE_TLV_DB_SCALE(drc_min_tlv, -1800, 600, 0);
565static const unsigned int drc_max_tlv[] = {
566 TLV_DB_RANGE_HEAD(4),
567 0, 2, TLV_DB_SCALE_ITEM(1200, 600, 0),
568 3, 3, TLV_DB_SCALE_ITEM(3600, 0, 0),
569};
570static const DECLARE_TLV_DB_SCALE(drc_qr_tlv, 1200, 600, 0);
571static const DECLARE_TLV_DB_SCALE(drc_startup_tlv, -1800, 300, 0);
572static const DECLARE_TLV_DB_SCALE(eq_tlv, -1200, 100, 0);
573static const DECLARE_TLV_DB_SCALE(digital_tlv, -7200, 75, 1);
574static const DECLARE_TLV_DB_SCALE(dac_boost_tlv, 0, 600, 0);
575
576static const char *dac_deemph_text[] = {
577 "None",
578 "32kHz",
579 "44.1kHz",
580 "48kHz",
581};
582
583static const struct soc_enum dac_deemph =
584 SOC_ENUM_SINGLE(WM8993_DAC_CTRL, 4, 4, dac_deemph_text);
585
586static const char *adc_hpf_text[] = {
587 "Hi-Fi",
588 "Voice 1",
589 "Voice 2",
590 "Voice 3",
591};
592
593static const struct soc_enum adc_hpf =
594 SOC_ENUM_SINGLE(WM8993_ADC_CTRL, 5, 4, adc_hpf_text);
595
596static const char *drc_path_text[] = {
597 "ADC",
598 "DAC"
599};
600
601static const struct soc_enum drc_path =
602 SOC_ENUM_SINGLE(WM8993_DRC_CONTROL_1, 14, 2, drc_path_text);
603
604static const char *drc_r0_text[] = {
605 "1",
606 "1/2",
607 "1/4",
608 "1/8",
609 "1/16",
610 "0",
611};
612
613static const struct soc_enum drc_r0 =
614 SOC_ENUM_SINGLE(WM8993_DRC_CONTROL_3, 8, 6, drc_r0_text);
615
616static const char *drc_r1_text[] = {
617 "1",
618 "1/2",
619 "1/4",
620 "1/8",
621 "0",
622};
623
624static const struct soc_enum drc_r1 =
625 SOC_ENUM_SINGLE(WM8993_DRC_CONTROL_4, 13, 5, drc_r1_text);
626
627static const char *drc_attack_text[] = {
628 "Reserved",
629 "181us",
630 "363us",
631 "726us",
632 "1.45ms",
633 "2.9ms",
634 "5.8ms",
635 "11.6ms",
636 "23.2ms",
637 "46.4ms",
638 "92.8ms",
639 "185.6ms",
640};
641
642static const struct soc_enum drc_attack =
643 SOC_ENUM_SINGLE(WM8993_DRC_CONTROL_2, 12, 12, drc_attack_text);
644
645static const char *drc_decay_text[] = {
646 "186ms",
647 "372ms",
648 "743ms",
649 "1.49s",
650 "2.97ms",
651 "5.94ms",
652 "11.89ms",
653 "23.78ms",
654 "47.56ms",
655};
656
657static const struct soc_enum drc_decay =
658 SOC_ENUM_SINGLE(WM8993_DRC_CONTROL_2, 8, 9, drc_decay_text);
659
660static const char *drc_ff_text[] = {
661 "5 samples",
662 "9 samples",
663};
664
665static const struct soc_enum drc_ff =
666 SOC_ENUM_SINGLE(WM8993_DRC_CONTROL_3, 7, 2, drc_ff_text);
667
668static const char *drc_qr_rate_text[] = {
669 "0.725ms",
670 "1.45ms",
671 "5.8ms",
672};
673
674static const struct soc_enum drc_qr_rate =
675 SOC_ENUM_SINGLE(WM8993_DRC_CONTROL_3, 0, 3, drc_qr_rate_text);
676
677static const char *drc_smooth_text[] = {
678 "Low",
679 "Medium",
680 "High",
681};
682
683static const struct soc_enum drc_smooth =
684 SOC_ENUM_SINGLE(WM8993_DRC_CONTROL_1, 4, 3, drc_smooth_text);
685
686static const struct snd_kcontrol_new wm8993_snd_controls[] = {
687SOC_DOUBLE_TLV("Digital Sidetone Volume", WM8993_DIGITAL_SIDE_TONE,
688 5, 9, 12, 0, sidetone_tlv),
689
690SOC_SINGLE("DRC Switch", WM8993_DRC_CONTROL_1, 15, 1, 0),
691SOC_ENUM("DRC Path", drc_path),
692SOC_SINGLE_TLV("DRC Compressor Threashold Volume", WM8993_DRC_CONTROL_2,
693 2, 60, 1, drc_comp_threash),
694SOC_SINGLE_TLV("DRC Compressor Amplitude Volume", WM8993_DRC_CONTROL_3,
695 11, 30, 1, drc_comp_amp),
696SOC_ENUM("DRC R0", drc_r0),
697SOC_ENUM("DRC R1", drc_r1),
698SOC_SINGLE_TLV("DRC Minimum Volume", WM8993_DRC_CONTROL_1, 2, 3, 1,
699 drc_min_tlv),
700SOC_SINGLE_TLV("DRC Maximum Volume", WM8993_DRC_CONTROL_1, 0, 3, 0,
701 drc_max_tlv),
702SOC_ENUM("DRC Attack Rate", drc_attack),
703SOC_ENUM("DRC Decay Rate", drc_decay),
704SOC_ENUM("DRC FF Delay", drc_ff),
705SOC_SINGLE("DRC Anti-clip Switch", WM8993_DRC_CONTROL_1, 9, 1, 0),
706SOC_SINGLE("DRC Quick Release Switch", WM8993_DRC_CONTROL_1, 10, 1, 0),
707SOC_SINGLE_TLV("DRC Quick Release Volume", WM8993_DRC_CONTROL_3, 2, 3, 0,
708 drc_qr_tlv),
709SOC_ENUM("DRC Quick Release Rate", drc_qr_rate),
710SOC_SINGLE("DRC Smoothing Switch", WM8993_DRC_CONTROL_1, 11, 1, 0),
711SOC_SINGLE("DRC Smoothing Hysteresis Switch", WM8993_DRC_CONTROL_1, 8, 1, 0),
712SOC_ENUM("DRC Smoothing Hysteresis Threashold", drc_smooth),
713SOC_SINGLE_TLV("DRC Startup Volume", WM8993_DRC_CONTROL_4, 8, 18, 0,
714 drc_startup_tlv),
715
716SOC_SINGLE("EQ Switch", WM8993_EQ1, 0, 1, 0),
717
718SOC_DOUBLE_R_TLV("Capture Volume", WM8993_LEFT_ADC_DIGITAL_VOLUME,
719 WM8993_RIGHT_ADC_DIGITAL_VOLUME, 1, 96, 0, digital_tlv),
720SOC_SINGLE("ADC High Pass Filter Switch", WM8993_ADC_CTRL, 8, 1, 0),
721SOC_ENUM("ADC High Pass Filter Mode", adc_hpf),
722
723SOC_DOUBLE_R_TLV("Playback Volume", WM8993_LEFT_DAC_DIGITAL_VOLUME,
724 WM8993_RIGHT_DAC_DIGITAL_VOLUME, 1, 96, 0, digital_tlv),
725SOC_SINGLE_TLV("Playback Boost Volume", WM8993_AUDIO_INTERFACE_2, 10, 3, 0,
726 dac_boost_tlv),
727SOC_ENUM("DAC Deemphasis", dac_deemph),
728
729SOC_SINGLE_TLV("SPKL DAC Volume", WM8993_SPKMIXL_ATTENUATION,
730 2, 1, 1, wm_hubs_spkmix_tlv),
731
732SOC_SINGLE_TLV("SPKR DAC Volume", WM8993_SPKMIXR_ATTENUATION,
733 2, 1, 1, wm_hubs_spkmix_tlv),
734};
735
736static const struct snd_kcontrol_new wm8993_eq_controls[] = {
737SOC_SINGLE_TLV("EQ1 Volume", WM8993_EQ2, 0, 24, 0, eq_tlv),
738SOC_SINGLE_TLV("EQ2 Volume", WM8993_EQ3, 0, 24, 0, eq_tlv),
739SOC_SINGLE_TLV("EQ3 Volume", WM8993_EQ4, 0, 24, 0, eq_tlv),
740SOC_SINGLE_TLV("EQ4 Volume", WM8993_EQ5, 0, 24, 0, eq_tlv),
741SOC_SINGLE_TLV("EQ5 Volume", WM8993_EQ6, 0, 24, 0, eq_tlv),
742};
743
744static int clk_sys_event(struct snd_soc_dapm_widget *w,
745 struct snd_kcontrol *kcontrol, int event)
746{
747 struct snd_soc_codec *codec = w->codec;
748
749 switch (event) {
750 case SND_SOC_DAPM_PRE_PMU:
751 return configure_clock(codec);
752
753 case SND_SOC_DAPM_POST_PMD:
754 break;
755 }
756
757 return 0;
758}
759
760/*
761 * When used with DAC outputs only the WM8993 charge pump supports
762 * operation in class W mode, providing very low power consumption
763 * when used with digital sources. Enable and disable this mode
764 * automatically depending on the mixer configuration.
765 *
766 * Currently the only supported paths are the direct DAC->headphone
767 * paths (which provide minimum power consumption anyway).
768 */
769static int class_w_put(struct snd_kcontrol *kcontrol,
770 struct snd_ctl_elem_value *ucontrol)
771{
772 struct snd_soc_dapm_widget *widget = snd_kcontrol_chip(kcontrol);
773 struct snd_soc_codec *codec = widget->codec;
774 struct wm8993_priv *wm8993 = codec->private_data;
775 int ret;
776
777 /* Turn it off if we're using the main output mixer */
778 if (ucontrol->value.integer.value[0] == 0) {
779 if (wm8993->class_w_users == 0) {
780 dev_dbg(codec->dev, "Disabling Class W\n");
781 snd_soc_update_bits(codec, WM8993_CLASS_W_0,
782 WM8993_CP_DYN_FREQ |
783 WM8993_CP_DYN_V,
784 0);
785 }
786 wm8993->class_w_users++;
787 }
788
789 /* Implement the change */
790 ret = snd_soc_dapm_put_enum_double(kcontrol, ucontrol);
791
792 /* Enable it if we're using the direct DAC path */
793 if (ucontrol->value.integer.value[0] == 1) {
794 if (wm8993->class_w_users == 1) {
795 dev_dbg(codec->dev, "Enabling Class W\n");
796 snd_soc_update_bits(codec, WM8993_CLASS_W_0,
797 WM8993_CP_DYN_FREQ |
798 WM8993_CP_DYN_V,
799 WM8993_CP_DYN_FREQ |
800 WM8993_CP_DYN_V);
801 }
802 wm8993->class_w_users--;
803 }
804
805 dev_dbg(codec->dev, "Indirect DAC use count now %d\n",
806 wm8993->class_w_users);
807
808 return ret;
809}
810
811#define SOC_DAPM_ENUM_W(xname, xenum) \
812{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \
813 .info = snd_soc_info_enum_double, \
814 .get = snd_soc_dapm_get_enum_double, \
815 .put = class_w_put, \
816 .private_value = (unsigned long)&xenum }
817
818static const char *hp_mux_text[] = {
819 "Mixer",
820 "DAC",
821};
822
823static const struct soc_enum hpl_enum =
824 SOC_ENUM_SINGLE(WM8993_OUTPUT_MIXER1, 8, 2, hp_mux_text);
825
826static const struct snd_kcontrol_new hpl_mux =
827 SOC_DAPM_ENUM_W("Left Headphone Mux", hpl_enum);
828
829static const struct soc_enum hpr_enum =
830 SOC_ENUM_SINGLE(WM8993_OUTPUT_MIXER2, 8, 2, hp_mux_text);
831
832static const struct snd_kcontrol_new hpr_mux =
833 SOC_DAPM_ENUM_W("Right Headphone Mux", hpr_enum);
834
835static const struct snd_kcontrol_new left_speaker_mixer[] = {
836SOC_DAPM_SINGLE("Input Switch", WM8993_SPEAKER_MIXER, 7, 1, 0),
837SOC_DAPM_SINGLE("IN1LP Switch", WM8993_SPEAKER_MIXER, 5, 1, 0),
838SOC_DAPM_SINGLE("Output Switch", WM8993_SPEAKER_MIXER, 3, 1, 0),
839SOC_DAPM_SINGLE("DAC Switch", WM8993_SPEAKER_MIXER, 6, 1, 0),
840};
841
842static const struct snd_kcontrol_new right_speaker_mixer[] = {
843SOC_DAPM_SINGLE("Input Switch", WM8993_SPEAKER_MIXER, 6, 1, 0),
844SOC_DAPM_SINGLE("IN1RP Switch", WM8993_SPEAKER_MIXER, 4, 1, 0),
845SOC_DAPM_SINGLE("Output Switch", WM8993_SPEAKER_MIXER, 2, 1, 0),
846SOC_DAPM_SINGLE("DAC Switch", WM8993_SPEAKER_MIXER, 0, 1, 0),
847};
848
849static const struct snd_soc_dapm_widget wm8993_dapm_widgets[] = {
850SND_SOC_DAPM_SUPPLY("CLK_SYS", WM8993_BUS_CONTROL_1, 1, 0, clk_sys_event,
851 SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
852SND_SOC_DAPM_SUPPLY("TOCLK", WM8993_CLOCKING_1, 14, 0, NULL, 0),
853SND_SOC_DAPM_SUPPLY("CLK_DSP", WM8993_CLOCKING_3, 0, 0, NULL, 0),
854
855
856SND_SOC_DAPM_ADC("ADCL", "Capture", WM8993_POWER_MANAGEMENT_2, 1, 0),
857SND_SOC_DAPM_ADC("ADCR", "Capture", WM8993_POWER_MANAGEMENT_2, 0, 0),
858
859SND_SOC_DAPM_DAC("DACL", "Playback", WM8993_POWER_MANAGEMENT_3, 1, 0),
860SND_SOC_DAPM_DAC("DACR", "Playback", WM8993_POWER_MANAGEMENT_3, 0, 0),
861
862SND_SOC_DAPM_MUX("Left Headphone Mux", SND_SOC_NOPM, 0, 0, &hpl_mux),
863SND_SOC_DAPM_MUX("Right Headphone Mux", SND_SOC_NOPM, 0, 0, &hpr_mux),
864
865SND_SOC_DAPM_MIXER("SPKL", WM8993_POWER_MANAGEMENT_3, 8, 0,
866 left_speaker_mixer, ARRAY_SIZE(left_speaker_mixer)),
867SND_SOC_DAPM_MIXER("SPKR", WM8993_POWER_MANAGEMENT_3, 9, 0,
868 right_speaker_mixer, ARRAY_SIZE(right_speaker_mixer)),
869
870};
871
872static const struct snd_soc_dapm_route routes[] = {
873 { "ADCL", NULL, "CLK_SYS" },
874 { "ADCL", NULL, "CLK_DSP" },
875 { "ADCR", NULL, "CLK_SYS" },
876 { "ADCR", NULL, "CLK_DSP" },
877
878 { "DACL", NULL, "CLK_SYS" },
879 { "DACL", NULL, "CLK_DSP" },
880 { "DACR", NULL, "CLK_SYS" },
881 { "DACR", NULL, "CLK_DSP" },
882
883 { "Left Output Mixer", "DAC Switch", "DACL" },
884
885 { "Right Output Mixer", "DAC Switch", "DACR" },
886
887 { "Left Output PGA", NULL, "CLK_SYS" },
888
889 { "Right Output PGA", NULL, "CLK_SYS" },
890
891 { "SPKL", "DAC Switch", "DACL" },
892 { "SPKL", NULL, "CLK_SYS" },
893
894 { "SPKR", "DAC Switch", "DACR" },
895 { "SPKR", NULL, "CLK_SYS" },
896
897 { "Left Headphone Mux", "DAC", "DACL" },
898 { "Right Headphone Mux", "DAC", "DACR" },
899};
900
901static int wm8993_set_bias_level(struct snd_soc_codec *codec,
902 enum snd_soc_bias_level level)
903{
904 struct wm8993_priv *wm8993 = codec->private_data;
905
906 switch (level) {
907 case SND_SOC_BIAS_ON:
908 case SND_SOC_BIAS_PREPARE:
909 /* VMID=2*40k */
910 snd_soc_update_bits(codec, WM8993_POWER_MANAGEMENT_1,
911 WM8993_VMID_SEL_MASK, 0x2);
912 snd_soc_update_bits(codec, WM8993_POWER_MANAGEMENT_2,
913 WM8993_TSHUT_ENA, WM8993_TSHUT_ENA);
914 break;
915
916 case SND_SOC_BIAS_STANDBY:
917 if (codec->bias_level == SND_SOC_BIAS_OFF) {
918 /* Bring up VMID with fast soft start */
919 snd_soc_update_bits(codec, WM8993_ANTIPOP2,
920 WM8993_STARTUP_BIAS_ENA |
921 WM8993_VMID_BUF_ENA |
922 WM8993_VMID_RAMP_MASK |
923 WM8993_BIAS_SRC,
924 WM8993_STARTUP_BIAS_ENA |
925 WM8993_VMID_BUF_ENA |
926 WM8993_VMID_RAMP_MASK |
927 WM8993_BIAS_SRC);
928
929 /* If either line output is single ended we
930 * need the VMID buffer */
931 if (!wm8993->pdata.lineout1_diff ||
932 !wm8993->pdata.lineout2_diff)
933 snd_soc_update_bits(codec, WM8993_ANTIPOP1,
934 WM8993_LINEOUT_VMID_BUF_ENA,
935 WM8993_LINEOUT_VMID_BUF_ENA);
936
937 /* VMID=2*40k */
938 snd_soc_update_bits(codec, WM8993_POWER_MANAGEMENT_1,
939 WM8993_VMID_SEL_MASK |
940 WM8993_BIAS_ENA,
941 WM8993_BIAS_ENA | 0x2);
942 msleep(32);
943
944 /* Switch to normal bias */
945 snd_soc_update_bits(codec, WM8993_ANTIPOP2,
946 WM8993_BIAS_SRC |
947 WM8993_STARTUP_BIAS_ENA, 0);
948 }
949
950 /* VMID=2*240k */
951 snd_soc_update_bits(codec, WM8993_POWER_MANAGEMENT_1,
952 WM8993_VMID_SEL_MASK, 0x4);
953
954 snd_soc_update_bits(codec, WM8993_POWER_MANAGEMENT_2,
955 WM8993_TSHUT_ENA, 0);
956 break;
957
958 case SND_SOC_BIAS_OFF:
959 snd_soc_update_bits(codec, WM8993_ANTIPOP1,
960 WM8993_LINEOUT_VMID_BUF_ENA, 0);
961
962 snd_soc_update_bits(codec, WM8993_POWER_MANAGEMENT_1,
963 WM8993_VMID_SEL_MASK | WM8993_BIAS_ENA,
964 0);
965 break;
966 }
967
968 codec->bias_level = level;
969
970 return 0;
971}
972
973static int wm8993_set_sysclk(struct snd_soc_dai *codec_dai,
974 int clk_id, unsigned int freq, int dir)
975{
976 struct snd_soc_codec *codec = codec_dai->codec;
977 struct wm8993_priv *wm8993 = codec->private_data;
978
979 switch (clk_id) {
980 case WM8993_SYSCLK_MCLK:
981 wm8993->mclk_rate = freq;
982 case WM8993_SYSCLK_FLL:
983 wm8993->sysclk_source = clk_id;
984 break;
985
986 default:
987 return -EINVAL;
988 }
989
990 return 0;
991}
992
993static int wm8993_set_dai_fmt(struct snd_soc_dai *dai,
994 unsigned int fmt)
995{
996 struct snd_soc_codec *codec = dai->codec;
997 struct wm8993_priv *wm8993 = codec->private_data;
998 unsigned int aif1 = wm8993_read(codec, WM8993_AUDIO_INTERFACE_1);
999 unsigned int aif4 = wm8993_read(codec, WM8993_AUDIO_INTERFACE_4);
1000
1001 aif1 &= ~(WM8993_BCLK_DIR | WM8993_AIF_BCLK_INV |
1002 WM8993_AIF_LRCLK_INV | WM8993_AIF_FMT_MASK);
1003 aif4 &= ~WM8993_LRCLK_DIR;
1004
1005 switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
1006 case SND_SOC_DAIFMT_CBS_CFS:
1007 wm8993->master = 0;
1008 break;
1009 case SND_SOC_DAIFMT_CBS_CFM:
1010 aif4 |= WM8993_LRCLK_DIR;
1011 wm8993->master = 1;
1012 break;
1013 case SND_SOC_DAIFMT_CBM_CFS:
1014 aif1 |= WM8993_BCLK_DIR;
1015 wm8993->master = 1;
1016 break;
1017 case SND_SOC_DAIFMT_CBM_CFM:
1018 aif1 |= WM8993_BCLK_DIR;
1019 aif4 |= WM8993_LRCLK_DIR;
1020 wm8993->master = 1;
1021 break;
1022 default:
1023 return -EINVAL;
1024 }
1025
1026 switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
1027 case SND_SOC_DAIFMT_DSP_B:
1028 aif1 |= WM8993_AIF_LRCLK_INV;
1029 case SND_SOC_DAIFMT_DSP_A:
1030 aif1 |= 0x18;
1031 break;
1032 case SND_SOC_DAIFMT_I2S:
1033 aif1 |= 0x10;
1034 break;
1035 case SND_SOC_DAIFMT_RIGHT_J:
1036 break;
1037 case SND_SOC_DAIFMT_LEFT_J:
1038 aif1 |= 0x8;
1039 break;
1040 default:
1041 return -EINVAL;
1042 }
1043
1044 switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
1045 case SND_SOC_DAIFMT_DSP_A:
1046 case SND_SOC_DAIFMT_DSP_B:
1047 /* frame inversion not valid for DSP modes */
1048 switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
1049 case SND_SOC_DAIFMT_NB_NF:
1050 break;
1051 case SND_SOC_DAIFMT_IB_NF:
1052 aif1 |= WM8993_AIF_BCLK_INV;
1053 break;
1054 default:
1055 return -EINVAL;
1056 }
1057 break;
1058
1059 case SND_SOC_DAIFMT_I2S:
1060 case SND_SOC_DAIFMT_RIGHT_J:
1061 case SND_SOC_DAIFMT_LEFT_J:
1062 switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
1063 case SND_SOC_DAIFMT_NB_NF:
1064 break;
1065 case SND_SOC_DAIFMT_IB_IF:
1066 aif1 |= WM8993_AIF_BCLK_INV | WM8993_AIF_LRCLK_INV;
1067 break;
1068 case SND_SOC_DAIFMT_IB_NF:
1069 aif1 |= WM8993_AIF_BCLK_INV;
1070 break;
1071 case SND_SOC_DAIFMT_NB_IF:
1072 aif1 |= WM8993_AIF_LRCLK_INV;
1073 break;
1074 default:
1075 return -EINVAL;
1076 }
1077 break;
1078 default:
1079 return -EINVAL;
1080 }
1081
1082 wm8993_write(codec, WM8993_AUDIO_INTERFACE_1, aif1);
1083 wm8993_write(codec, WM8993_AUDIO_INTERFACE_4, aif4);
1084
1085 return 0;
1086}
1087
1088static int wm8993_hw_params(struct snd_pcm_substream *substream,
1089 struct snd_pcm_hw_params *params,
1090 struct snd_soc_dai *dai)
1091{
1092 struct snd_soc_codec *codec = dai->codec;
1093 struct wm8993_priv *wm8993 = codec->private_data;
1094 int ret, i, best, best_val, cur_val;
1095 unsigned int clocking1, clocking3, aif1, aif4;
1096
1097 clocking1 = wm8993_read(codec, WM8993_CLOCKING_1);
1098 clocking1 &= ~WM8993_BCLK_DIV_MASK;
1099
1100 clocking3 = wm8993_read(codec, WM8993_CLOCKING_3);
1101 clocking3 &= ~(WM8993_CLK_SYS_RATE_MASK | WM8993_SAMPLE_RATE_MASK);
1102
1103 aif1 = wm8993_read(codec, WM8993_AUDIO_INTERFACE_1);
1104 aif1 &= ~WM8993_AIF_WL_MASK;
1105
1106 aif4 = wm8993_read(codec, WM8993_AUDIO_INTERFACE_4);
1107 aif4 &= ~WM8993_LRCLK_RATE_MASK;
1108
1109 /* What BCLK do we need? */
1110 wm8993->fs = params_rate(params);
1111 wm8993->bclk = 2 * wm8993->fs;
1112 switch (params_format(params)) {
1113 case SNDRV_PCM_FORMAT_S16_LE:
1114 wm8993->bclk *= 16;
1115 break;
1116 case SNDRV_PCM_FORMAT_S20_3LE:
1117 wm8993->bclk *= 20;
1118 aif1 |= 0x8;
1119 break;
1120 case SNDRV_PCM_FORMAT_S24_LE:
1121 wm8993->bclk *= 24;
1122 aif1 |= 0x10;
1123 break;
1124 case SNDRV_PCM_FORMAT_S32_LE:
1125 wm8993->bclk *= 32;
1126 aif1 |= 0x18;
1127 break;
1128 default:
1129 return -EINVAL;
1130 }
1131
1132 dev_dbg(codec->dev, "Target BCLK is %dHz\n", wm8993->bclk);
1133
1134 ret = configure_clock(codec);
1135 if (ret != 0)
1136 return ret;
1137
1138 /* Select nearest CLK_SYS_RATE */
1139 best = 0;
1140 best_val = abs((wm8993->sysclk_rate / clk_sys_rates[0].ratio)
1141 - wm8993->fs);
1142 for (i = 1; i < ARRAY_SIZE(clk_sys_rates); i++) {
1143 cur_val = abs((wm8993->sysclk_rate /
1144 clk_sys_rates[i].ratio) - wm8993->fs);;
1145 if (cur_val < best_val) {
1146 best = i;
1147 best_val = cur_val;
1148 }
1149 }
1150 dev_dbg(codec->dev, "Selected CLK_SYS_RATIO of %d\n",
1151 clk_sys_rates[best].ratio);
1152 clocking3 |= (clk_sys_rates[best].clk_sys_rate
1153 << WM8993_CLK_SYS_RATE_SHIFT);
1154
1155 /* SAMPLE_RATE */
1156 best = 0;
1157 best_val = abs(wm8993->fs - sample_rates[0].rate);
1158 for (i = 1; i < ARRAY_SIZE(sample_rates); i++) {
1159 /* Closest match */
1160 cur_val = abs(wm8993->fs - sample_rates[i].rate);
1161 if (cur_val < best_val) {
1162 best = i;
1163 best_val = cur_val;
1164 }
1165 }
1166 dev_dbg(codec->dev, "Selected SAMPLE_RATE of %dHz\n",
1167 sample_rates[best].rate);
1168 clocking3 |= (sample_rates[best].sample_rate
1169 << WM8993_SAMPLE_RATE_SHIFT);
1170
1171 /* BCLK_DIV */
1172 best = 0;
1173 best_val = INT_MAX;
1174 for (i = 0; i < ARRAY_SIZE(bclk_divs); i++) {
1175 cur_val = ((wm8993->sysclk_rate * 10) / bclk_divs[i].div)
1176 - wm8993->bclk;
1177 if (cur_val < 0) /* Table is sorted */
1178 break;
1179 if (cur_val < best_val) {
1180 best = i;
1181 best_val = cur_val;
1182 }
1183 }
1184 wm8993->bclk = (wm8993->sysclk_rate * 10) / bclk_divs[best].div;
1185 dev_dbg(codec->dev, "Selected BCLK_DIV of %d for %dHz BCLK\n",
1186 bclk_divs[best].div, wm8993->bclk);
1187 clocking1 |= bclk_divs[best].bclk_div << WM8993_BCLK_DIV_SHIFT;
1188
1189 /* LRCLK is a simple fraction of BCLK */
1190 dev_dbg(codec->dev, "LRCLK_RATE is %d\n", wm8993->bclk / wm8993->fs);
1191 aif4 |= wm8993->bclk / wm8993->fs;
1192
1193 wm8993_write(codec, WM8993_CLOCKING_1, clocking1);
1194 wm8993_write(codec, WM8993_CLOCKING_3, clocking3);
1195 wm8993_write(codec, WM8993_AUDIO_INTERFACE_1, aif1);
1196 wm8993_write(codec, WM8993_AUDIO_INTERFACE_4, aif4);
1197
1198 /* ReTune Mobile? */
1199 if (wm8993->pdata.num_retune_configs) {
1200 u16 eq1 = wm8993_read(codec, WM8993_EQ1);
1201 struct wm8993_retune_mobile_setting *s;
1202
1203 best = 0;
1204 best_val = abs(wm8993->pdata.retune_configs[0].rate
1205 - wm8993->fs);
1206 for (i = 0; i < wm8993->pdata.num_retune_configs; i++) {
1207 cur_val = abs(wm8993->pdata.retune_configs[i].rate
1208 - wm8993->fs);
1209 if (cur_val < best_val) {
1210 best_val = cur_val;
1211 best = i;
1212 }
1213 }
1214 s = &wm8993->pdata.retune_configs[best];
1215
1216 dev_dbg(codec->dev, "ReTune Mobile %s tuned for %dHz\n",
1217 s->name, s->rate);
1218
1219 /* Disable EQ while we reconfigure */
1220 snd_soc_update_bits(codec, WM8993_EQ1, WM8993_EQ_ENA, 0);
1221
1222 for (i = 1; i < ARRAY_SIZE(s->config); i++)
1223 wm8993_write(codec, WM8993_EQ1 + i, s->config[i]);
1224
1225 snd_soc_update_bits(codec, WM8993_EQ1, WM8993_EQ_ENA, eq1);
1226 }
1227
1228 return 0;
1229}
1230
1231static int wm8993_digital_mute(struct snd_soc_dai *codec_dai, int mute)
1232{
1233 struct snd_soc_codec *codec = codec_dai->codec;
1234 unsigned int reg;
1235
1236 reg = wm8993_read(codec, WM8993_DAC_CTRL);
1237
1238 if (mute)
1239 reg |= WM8993_DAC_MUTE;
1240 else
1241 reg &= ~WM8993_DAC_MUTE;
1242
1243 wm8993_write(codec, WM8993_DAC_CTRL, reg);
1244
1245 return 0;
1246}
1247
1248static struct snd_soc_dai_ops wm8993_ops = {
1249 .set_sysclk = wm8993_set_sysclk,
1250 .set_fmt = wm8993_set_dai_fmt,
1251 .hw_params = wm8993_hw_params,
1252 .digital_mute = wm8993_digital_mute,
1253 .set_pll = wm8993_set_fll,
1254};
1255
1256#define WM8993_RATES SNDRV_PCM_RATE_8000_48000
1257
1258#define WM8993_FORMATS (SNDRV_PCM_FMTBIT_S16_LE |\
1259 SNDRV_PCM_FMTBIT_S20_3LE |\
1260 SNDRV_PCM_FMTBIT_S24_LE |\
1261 SNDRV_PCM_FMTBIT_S32_LE)
1262
1263struct snd_soc_dai wm8993_dai = {
1264 .name = "WM8993",
1265 .playback = {
1266 .stream_name = "Playback",
1267 .channels_min = 1,
1268 .channels_max = 2,
1269 .rates = WM8993_RATES,
1270 .formats = WM8993_FORMATS,
1271 },
1272 .capture = {
1273 .stream_name = "Capture",
1274 .channels_min = 1,
1275 .channels_max = 2,
1276 .rates = WM8993_RATES,
1277 .formats = WM8993_FORMATS,
1278 },
1279 .ops = &wm8993_ops,
1280 .symmetric_rates = 1,
1281};
1282EXPORT_SYMBOL_GPL(wm8993_dai);
1283
1284static struct snd_soc_codec *wm8993_codec;
1285
1286static int wm8993_probe(struct platform_device *pdev)
1287{
1288 struct snd_soc_device *socdev = platform_get_drvdata(pdev);
1289 struct snd_soc_codec *codec;
1290 struct wm8993_priv *wm8993;
1291 int ret = 0;
1292
1293 if (!wm8993_codec) {
1294 dev_err(&pdev->dev, "I2C device not yet probed\n");
1295 goto err;
1296 }
1297
1298 socdev->card->codec = wm8993_codec;
1299 codec = wm8993_codec;
1300 wm8993 = codec->private_data;
1301
1302 ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1);
1303 if (ret < 0) {
1304 dev_err(codec->dev, "failed to create pcms\n");
1305 goto err;
1306 }
1307
1308 snd_soc_add_controls(codec, wm8993_snd_controls,
1309 ARRAY_SIZE(wm8993_snd_controls));
1310 if (wm8993->pdata.num_retune_configs != 0) {
1311 dev_dbg(codec->dev, "Using ReTune Mobile\n");
1312 } else {
1313 dev_dbg(codec->dev, "No ReTune Mobile, using normal EQ\n");
1314 snd_soc_add_controls(codec, wm8993_eq_controls,
1315 ARRAY_SIZE(wm8993_eq_controls));
1316 }
1317
1318 snd_soc_dapm_new_controls(codec, wm8993_dapm_widgets,
1319 ARRAY_SIZE(wm8993_dapm_widgets));
1320 wm_hubs_add_analogue_controls(codec);
1321
1322 snd_soc_dapm_add_routes(codec, routes, ARRAY_SIZE(routes));
1323 wm_hubs_add_analogue_routes(codec, wm8993->pdata.lineout1_diff,
1324 wm8993->pdata.lineout2_diff);
1325
1326 snd_soc_dapm_new_widgets(codec);
1327
1328 ret = snd_soc_init_card(socdev);
1329 if (ret < 0) {
1330 dev_err(codec->dev, "failed to register card\n");
1331 goto card_err;
1332 }
1333
1334 return ret;
1335
1336card_err:
1337 snd_soc_free_pcms(socdev);
1338 snd_soc_dapm_free(socdev);
1339err:
1340 return ret;
1341}
1342
1343static int wm8993_remove(struct platform_device *pdev)
1344{
1345 struct snd_soc_device *socdev = platform_get_drvdata(pdev);
1346
1347 snd_soc_free_pcms(socdev);
1348 snd_soc_dapm_free(socdev);
1349
1350 return 0;
1351}
1352
1353struct snd_soc_codec_device soc_codec_dev_wm8993 = {
1354 .probe = wm8993_probe,
1355 .remove = wm8993_remove,
1356};
1357EXPORT_SYMBOL_GPL(soc_codec_dev_wm8993);
1358
1359static int wm8993_i2c_probe(struct i2c_client *i2c,
1360 const struct i2c_device_id *id)
1361{
1362 struct wm8993_priv *wm8993;
1363 struct snd_soc_codec *codec;
1364 unsigned int val;
1365 int ret;
1366
1367 if (wm8993_codec) {
1368 dev_err(&i2c->dev, "A WM8993 is already registered\n");
1369 return -EINVAL;
1370 }
1371
1372 wm8993 = kzalloc(sizeof(struct wm8993_priv), GFP_KERNEL);
1373 if (wm8993 == NULL)
1374 return -ENOMEM;
1375
1376 codec = &wm8993->codec;
1377 if (i2c->dev.platform_data)
1378 memcpy(&wm8993->pdata, i2c->dev.platform_data,
1379 sizeof(wm8993->pdata));
1380
1381 mutex_init(&codec->mutex);
1382 INIT_LIST_HEAD(&codec->dapm_widgets);
1383 INIT_LIST_HEAD(&codec->dapm_paths);
1384
1385 codec->name = "WM8993";
1386 codec->read = wm8993_read;
1387 codec->write = wm8993_write;
1388 codec->hw_write = (hw_write_t)i2c_master_send;
1389 codec->reg_cache = wm8993->reg_cache;
1390 codec->reg_cache_size = ARRAY_SIZE(wm8993->reg_cache);
1391 codec->bias_level = SND_SOC_BIAS_OFF;
1392 codec->set_bias_level = wm8993_set_bias_level;
1393 codec->dai = &wm8993_dai;
1394 codec->num_dai = 1;
1395 codec->private_data = wm8993;
1396
1397 memcpy(wm8993->reg_cache, wm8993_reg_defaults,
1398 sizeof(wm8993->reg_cache));
1399
1400 i2c_set_clientdata(i2c, wm8993);
1401 codec->control_data = i2c;
1402 wm8993_codec = codec;
1403
1404 codec->dev = &i2c->dev;
1405
1406 val = wm8993_read_hw(codec, WM8993_SOFTWARE_RESET);
1407 if (val != wm8993_reg_defaults[WM8993_SOFTWARE_RESET]) {
1408 dev_err(codec->dev, "Invalid ID register value %x\n", val);
1409 ret = -EINVAL;
1410 goto err;
1411 }
1412
1413 ret = wm8993_write(codec, WM8993_SOFTWARE_RESET, 0xffff);
1414 if (ret != 0)
1415 goto err;
1416
1417 /* By default we're using the output mixers */
1418 wm8993->class_w_users = 2;
1419
1420 /* Latch volume update bits and default ZC on */
1421 snd_soc_update_bits(codec, WM8993_RIGHT_DAC_DIGITAL_VOLUME,
1422 WM8993_DAC_VU, WM8993_DAC_VU);
1423 snd_soc_update_bits(codec, WM8993_RIGHT_ADC_DIGITAL_VOLUME,
1424 WM8993_ADC_VU, WM8993_ADC_VU);
1425
1426 /* Manualy manage the HPOUT sequencing for independent stereo
1427 * control. */
1428 snd_soc_update_bits(codec, WM8993_ANALOGUE_HP_0,
1429 WM8993_HPOUT1_AUTO_PU, 0);
1430
1431 /* Use automatic clock configuration */
1432 snd_soc_update_bits(codec, WM8993_CLOCKING_4, WM8993_SR_MODE, 0);
1433
1434 if (!wm8993->pdata.lineout1_diff)
1435 snd_soc_update_bits(codec, WM8993_LINE_MIXER1,
1436 WM8993_LINEOUT1_MODE,
1437 WM8993_LINEOUT1_MODE);
1438 if (!wm8993->pdata.lineout2_diff)
1439 snd_soc_update_bits(codec, WM8993_LINE_MIXER2,
1440 WM8993_LINEOUT2_MODE,
1441 WM8993_LINEOUT2_MODE);
1442
1443 if (wm8993->pdata.lineout1fb)
1444 snd_soc_update_bits(codec, WM8993_ADDITIONAL_CONTROL,
1445 WM8993_LINEOUT1_FB, WM8993_LINEOUT1_FB);
1446
1447 if (wm8993->pdata.lineout2fb)
1448 snd_soc_update_bits(codec, WM8993_ADDITIONAL_CONTROL,
1449 WM8993_LINEOUT2_FB, WM8993_LINEOUT2_FB);
1450
1451 /* Apply the microphone bias/detection configuration - the
1452 * platform data is directly applicable to the register. */
1453 snd_soc_update_bits(codec, WM8993_MICBIAS,
1454 WM8993_JD_SCTHR_MASK | WM8993_JD_THR_MASK |
1455 WM8993_MICB1_LVL | WM8993_MICB2_LVL,
1456 wm8993->pdata.jd_scthr << WM8993_JD_SCTHR_SHIFT |
1457 wm8993->pdata.jd_thr << WM8993_JD_THR_SHIFT |
1458 wm8993->pdata.micbias1_lvl |
1459 wm8993->pdata.micbias1_lvl << 1);
1460
1461 ret = wm8993_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
1462 if (ret != 0)
1463 goto err;
1464
1465 wm8993_dai.dev = codec->dev;
1466
1467 ret = snd_soc_register_dai(&wm8993_dai);
1468 if (ret != 0)
1469 goto err_bias;
1470
1471 ret = snd_soc_register_codec(codec);
1472
1473 return 0;
1474
1475err_bias:
1476 wm8993_set_bias_level(codec, SND_SOC_BIAS_OFF);
1477err:
1478 wm8993_codec = NULL;
1479 kfree(wm8993);
1480 return ret;
1481}
1482
1483static int wm8993_i2c_remove(struct i2c_client *client)
1484{
1485 struct wm8993_priv *wm8993 = i2c_get_clientdata(client);
1486
1487 snd_soc_unregister_codec(&wm8993->codec);
1488 snd_soc_unregister_dai(&wm8993_dai);
1489
1490 wm8993_set_bias_level(&wm8993->codec, SND_SOC_BIAS_OFF);
1491 kfree(wm8993);
1492
1493 return 0;
1494}
1495
1496static const struct i2c_device_id wm8993_i2c_id[] = {
1497 { "wm8993", 0 },
1498 { }
1499};
1500MODULE_DEVICE_TABLE(i2c, wm8993_i2c_id);
1501
1502static struct i2c_driver wm8993_i2c_driver = {
1503 .driver = {
1504 .name = "WM8993",
1505 .owner = THIS_MODULE,
1506 },
1507 .probe = wm8993_i2c_probe,
1508 .remove = wm8993_i2c_remove,
1509 .id_table = wm8993_i2c_id,
1510};
1511
1512
1513static int __init wm8993_modinit(void)
1514{
1515 int ret;
1516
1517 ret = i2c_add_driver(&wm8993_i2c_driver);
1518 if (ret != 0)
1519 pr_err("WM8993: Unable to register I2C driver: %d\n", ret);
1520
1521 return ret;
1522}
1523module_init(wm8993_modinit);
1524
1525static void __exit wm8993_exit(void)
1526{
1527 i2c_del_driver(&wm8993_i2c_driver);
1528}
1529module_exit(wm8993_exit);
1530
1531
1532MODULE_DESCRIPTION("ASoC WM8993 driver");
1533MODULE_AUTHOR("Mark Brown <broonie@opensource.wolfsonmicro.com>");
1534MODULE_LICENSE("GPL");
diff --git a/sound/soc/codecs/wm8993.h b/sound/soc/codecs/wm8993.h
new file mode 100644
index 000000000000..30e71ca88dad
--- /dev/null
+++ b/sound/soc/codecs/wm8993.h
@@ -0,0 +1,2132 @@
1#ifndef WM8993_H
2#define WM8993_H
3
4extern struct snd_soc_dai wm8993_dai;
5extern struct snd_soc_codec_device soc_codec_dev_wm8993;
6
7#define WM8993_SYSCLK_MCLK 1
8#define WM8993_SYSCLK_FLL 2
9
10#define WM8993_FLL_MCLK 1
11#define WM8993_FLL_BCLK 2
12#define WM8993_FLL_LRCLK 3
13
14/*
15 * Register values.
16 */
17#define WM8993_SOFTWARE_RESET 0x00
18#define WM8993_POWER_MANAGEMENT_1 0x01
19#define WM8993_POWER_MANAGEMENT_2 0x02
20#define WM8993_POWER_MANAGEMENT_3 0x03
21#define WM8993_AUDIO_INTERFACE_1 0x04
22#define WM8993_AUDIO_INTERFACE_2 0x05
23#define WM8993_CLOCKING_1 0x06
24#define WM8993_CLOCKING_2 0x07
25#define WM8993_AUDIO_INTERFACE_3 0x08
26#define WM8993_AUDIO_INTERFACE_4 0x09
27#define WM8993_DAC_CTRL 0x0A
28#define WM8993_LEFT_DAC_DIGITAL_VOLUME 0x0B
29#define WM8993_RIGHT_DAC_DIGITAL_VOLUME 0x0C
30#define WM8993_DIGITAL_SIDE_TONE 0x0D
31#define WM8993_ADC_CTRL 0x0E
32#define WM8993_LEFT_ADC_DIGITAL_VOLUME 0x0F
33#define WM8993_RIGHT_ADC_DIGITAL_VOLUME 0x10
34#define WM8993_GPIO_CTRL_1 0x12
35#define WM8993_GPIO1 0x13
36#define WM8993_IRQ_DEBOUNCE 0x14
37#define WM8993_GPIOCTRL_2 0x16
38#define WM8993_GPIO_POL 0x17
39#define WM8993_LEFT_LINE_INPUT_1_2_VOLUME 0x18
40#define WM8993_LEFT_LINE_INPUT_3_4_VOLUME 0x19
41#define WM8993_RIGHT_LINE_INPUT_1_2_VOLUME 0x1A
42#define WM8993_RIGHT_LINE_INPUT_3_4_VOLUME 0x1B
43#define WM8993_LEFT_OUTPUT_VOLUME 0x1C
44#define WM8993_RIGHT_OUTPUT_VOLUME 0x1D
45#define WM8993_LINE_OUTPUTS_VOLUME 0x1E
46#define WM8993_HPOUT2_VOLUME 0x1F
47#define WM8993_LEFT_OPGA_VOLUME 0x20
48#define WM8993_RIGHT_OPGA_VOLUME 0x21
49#define WM8993_SPKMIXL_ATTENUATION 0x22
50#define WM8993_SPKMIXR_ATTENUATION 0x23
51#define WM8993_SPKOUT_MIXERS 0x24
52#define WM8993_SPKOUT_BOOST 0x25
53#define WM8993_SPEAKER_VOLUME_LEFT 0x26
54#define WM8993_SPEAKER_VOLUME_RIGHT 0x27
55#define WM8993_INPUT_MIXER2 0x28
56#define WM8993_INPUT_MIXER3 0x29
57#define WM8993_INPUT_MIXER4 0x2A
58#define WM8993_INPUT_MIXER5 0x2B
59#define WM8993_INPUT_MIXER6 0x2C
60#define WM8993_OUTPUT_MIXER1 0x2D
61#define WM8993_OUTPUT_MIXER2 0x2E
62#define WM8993_OUTPUT_MIXER3 0x2F
63#define WM8993_OUTPUT_MIXER4 0x30
64#define WM8993_OUTPUT_MIXER5 0x31
65#define WM8993_OUTPUT_MIXER6 0x32
66#define WM8993_HPOUT2_MIXER 0x33
67#define WM8993_LINE_MIXER1 0x34
68#define WM8993_LINE_MIXER2 0x35
69#define WM8993_SPEAKER_MIXER 0x36
70#define WM8993_ADDITIONAL_CONTROL 0x37
71#define WM8993_ANTIPOP1 0x38
72#define WM8993_ANTIPOP2 0x39
73#define WM8993_MICBIAS 0x3A
74#define WM8993_FLL_CONTROL_1 0x3C
75#define WM8993_FLL_CONTROL_2 0x3D
76#define WM8993_FLL_CONTROL_3 0x3E
77#define WM8993_FLL_CONTROL_4 0x3F
78#define WM8993_FLL_CONTROL_5 0x40
79#define WM8993_CLOCKING_3 0x41
80#define WM8993_CLOCKING_4 0x42
81#define WM8993_MW_SLAVE_CONTROL 0x43
82#define WM8993_BUS_CONTROL_1 0x45
83#define WM8993_WRITE_SEQUENCER_0 0x46
84#define WM8993_WRITE_SEQUENCER_1 0x47
85#define WM8993_WRITE_SEQUENCER_2 0x48
86#define WM8993_WRITE_SEQUENCER_3 0x49
87#define WM8993_WRITE_SEQUENCER_4 0x4A
88#define WM8993_WRITE_SEQUENCER_5 0x4B
89#define WM8993_CHARGE_PUMP_1 0x4C
90#define WM8993_CLASS_W_0 0x51
91#define WM8993_DC_SERVO_0 0x54
92#define WM8993_DC_SERVO_1 0x55
93#define WM8993_DC_SERVO_3 0x57
94#define WM8993_DC_SERVO_READBACK_0 0x58
95#define WM8993_DC_SERVO_READBACK_1 0x59
96#define WM8993_DC_SERVO_READBACK_2 0x5A
97#define WM8993_ANALOGUE_HP_0 0x60
98#define WM8993_EQ1 0x62
99#define WM8993_EQ2 0x63
100#define WM8993_EQ3 0x64
101#define WM8993_EQ4 0x65
102#define WM8993_EQ5 0x66
103#define WM8993_EQ6 0x67
104#define WM8993_EQ7 0x68
105#define WM8993_EQ8 0x69
106#define WM8993_EQ9 0x6A
107#define WM8993_EQ10 0x6B
108#define WM8993_EQ11 0x6C
109#define WM8993_EQ12 0x6D
110#define WM8993_EQ13 0x6E
111#define WM8993_EQ14 0x6F
112#define WM8993_EQ15 0x70
113#define WM8993_EQ16 0x71
114#define WM8993_EQ17 0x72
115#define WM8993_EQ18 0x73
116#define WM8993_EQ19 0x74
117#define WM8993_EQ20 0x75
118#define WM8993_EQ21 0x76
119#define WM8993_EQ22 0x77
120#define WM8993_EQ23 0x78
121#define WM8993_EQ24 0x79
122#define WM8993_DIGITAL_PULLS 0x7A
123#define WM8993_DRC_CONTROL_1 0x7B
124#define WM8993_DRC_CONTROL_2 0x7C
125#define WM8993_DRC_CONTROL_3 0x7D
126#define WM8993_DRC_CONTROL_4 0x7E
127
128#define WM8993_REGISTER_COUNT 0x7F
129#define WM8993_MAX_REGISTER 0x7E
130
131/*
132 * Field Definitions.
133 */
134
135/*
136 * R0 (0x00) - Software Reset
137 */
138#define WM8993_SW_RESET_MASK 0xFFFF /* SW_RESET - [15:0] */
139#define WM8993_SW_RESET_SHIFT 0 /* SW_RESET - [15:0] */
140#define WM8993_SW_RESET_WIDTH 16 /* SW_RESET - [15:0] */
141
142/*
143 * R1 (0x01) - Power Management (1)
144 */
145#define WM8993_SPKOUTR_ENA 0x2000 /* SPKOUTR_ENA */
146#define WM8993_SPKOUTR_ENA_MASK 0x2000 /* SPKOUTR_ENA */
147#define WM8993_SPKOUTR_ENA_SHIFT 13 /* SPKOUTR_ENA */
148#define WM8993_SPKOUTR_ENA_WIDTH 1 /* SPKOUTR_ENA */
149#define WM8993_SPKOUTL_ENA 0x1000 /* SPKOUTL_ENA */
150#define WM8993_SPKOUTL_ENA_MASK 0x1000 /* SPKOUTL_ENA */
151#define WM8993_SPKOUTL_ENA_SHIFT 12 /* SPKOUTL_ENA */
152#define WM8993_SPKOUTL_ENA_WIDTH 1 /* SPKOUTL_ENA */
153#define WM8993_HPOUT2_ENA 0x0800 /* HPOUT2_ENA */
154#define WM8993_HPOUT2_ENA_MASK 0x0800 /* HPOUT2_ENA */
155#define WM8993_HPOUT2_ENA_SHIFT 11 /* HPOUT2_ENA */
156#define WM8993_HPOUT2_ENA_WIDTH 1 /* HPOUT2_ENA */
157#define WM8993_HPOUT1L_ENA 0x0200 /* HPOUT1L_ENA */
158#define WM8993_HPOUT1L_ENA_MASK 0x0200 /* HPOUT1L_ENA */
159#define WM8993_HPOUT1L_ENA_SHIFT 9 /* HPOUT1L_ENA */
160#define WM8993_HPOUT1L_ENA_WIDTH 1 /* HPOUT1L_ENA */
161#define WM8993_HPOUT1R_ENA 0x0100 /* HPOUT1R_ENA */
162#define WM8993_HPOUT1R_ENA_MASK 0x0100 /* HPOUT1R_ENA */
163#define WM8993_HPOUT1R_ENA_SHIFT 8 /* HPOUT1R_ENA */
164#define WM8993_HPOUT1R_ENA_WIDTH 1 /* HPOUT1R_ENA */
165#define WM8993_MICB2_ENA 0x0020 /* MICB2_ENA */
166#define WM8993_MICB2_ENA_MASK 0x0020 /* MICB2_ENA */
167#define WM8993_MICB2_ENA_SHIFT 5 /* MICB2_ENA */
168#define WM8993_MICB2_ENA_WIDTH 1 /* MICB2_ENA */
169#define WM8993_MICB1_ENA 0x0010 /* MICB1_ENA */
170#define WM8993_MICB1_ENA_MASK 0x0010 /* MICB1_ENA */
171#define WM8993_MICB1_ENA_SHIFT 4 /* MICB1_ENA */
172#define WM8993_MICB1_ENA_WIDTH 1 /* MICB1_ENA */
173#define WM8993_VMID_SEL_MASK 0x0006 /* VMID_SEL - [2:1] */
174#define WM8993_VMID_SEL_SHIFT 1 /* VMID_SEL - [2:1] */
175#define WM8993_VMID_SEL_WIDTH 2 /* VMID_SEL - [2:1] */
176#define WM8993_BIAS_ENA 0x0001 /* BIAS_ENA */
177#define WM8993_BIAS_ENA_MASK 0x0001 /* BIAS_ENA */
178#define WM8993_BIAS_ENA_SHIFT 0 /* BIAS_ENA */
179#define WM8993_BIAS_ENA_WIDTH 1 /* BIAS_ENA */
180
181/*
182 * R2 (0x02) - Power Management (2)
183 */
184#define WM8993_TSHUT_ENA 0x4000 /* TSHUT_ENA */
185#define WM8993_TSHUT_ENA_MASK 0x4000 /* TSHUT_ENA */
186#define WM8993_TSHUT_ENA_SHIFT 14 /* TSHUT_ENA */
187#define WM8993_TSHUT_ENA_WIDTH 1 /* TSHUT_ENA */
188#define WM8993_TSHUT_OPDIS 0x2000 /* TSHUT_OPDIS */
189#define WM8993_TSHUT_OPDIS_MASK 0x2000 /* TSHUT_OPDIS */
190#define WM8993_TSHUT_OPDIS_SHIFT 13 /* TSHUT_OPDIS */
191#define WM8993_TSHUT_OPDIS_WIDTH 1 /* TSHUT_OPDIS */
192#define WM8993_OPCLK_ENA 0x0800 /* OPCLK_ENA */
193#define WM8993_OPCLK_ENA_MASK 0x0800 /* OPCLK_ENA */
194#define WM8993_OPCLK_ENA_SHIFT 11 /* OPCLK_ENA */
195#define WM8993_OPCLK_ENA_WIDTH 1 /* OPCLK_ENA */
196#define WM8993_MIXINL_ENA 0x0200 /* MIXINL_ENA */
197#define WM8993_MIXINL_ENA_MASK 0x0200 /* MIXINL_ENA */
198#define WM8993_MIXINL_ENA_SHIFT 9 /* MIXINL_ENA */
199#define WM8993_MIXINL_ENA_WIDTH 1 /* MIXINL_ENA */
200#define WM8993_MIXINR_ENA 0x0100 /* MIXINR_ENA */
201#define WM8993_MIXINR_ENA_MASK 0x0100 /* MIXINR_ENA */
202#define WM8993_MIXINR_ENA_SHIFT 8 /* MIXINR_ENA */
203#define WM8993_MIXINR_ENA_WIDTH 1 /* MIXINR_ENA */
204#define WM8993_IN2L_ENA 0x0080 /* IN2L_ENA */
205#define WM8993_IN2L_ENA_MASK 0x0080 /* IN2L_ENA */
206#define WM8993_IN2L_ENA_SHIFT 7 /* IN2L_ENA */
207#define WM8993_IN2L_ENA_WIDTH 1 /* IN2L_ENA */
208#define WM8993_IN1L_ENA 0x0040 /* IN1L_ENA */
209#define WM8993_IN1L_ENA_MASK 0x0040 /* IN1L_ENA */
210#define WM8993_IN1L_ENA_SHIFT 6 /* IN1L_ENA */
211#define WM8993_IN1L_ENA_WIDTH 1 /* IN1L_ENA */
212#define WM8993_IN2R_ENA 0x0020 /* IN2R_ENA */
213#define WM8993_IN2R_ENA_MASK 0x0020 /* IN2R_ENA */
214#define WM8993_IN2R_ENA_SHIFT 5 /* IN2R_ENA */
215#define WM8993_IN2R_ENA_WIDTH 1 /* IN2R_ENA */
216#define WM8993_IN1R_ENA 0x0010 /* IN1R_ENA */
217#define WM8993_IN1R_ENA_MASK 0x0010 /* IN1R_ENA */
218#define WM8993_IN1R_ENA_SHIFT 4 /* IN1R_ENA */
219#define WM8993_IN1R_ENA_WIDTH 1 /* IN1R_ENA */
220#define WM8993_ADCL_ENA 0x0002 /* ADCL_ENA */
221#define WM8993_ADCL_ENA_MASK 0x0002 /* ADCL_ENA */
222#define WM8993_ADCL_ENA_SHIFT 1 /* ADCL_ENA */
223#define WM8993_ADCL_ENA_WIDTH 1 /* ADCL_ENA */
224#define WM8993_ADCR_ENA 0x0001 /* ADCR_ENA */
225#define WM8993_ADCR_ENA_MASK 0x0001 /* ADCR_ENA */
226#define WM8993_ADCR_ENA_SHIFT 0 /* ADCR_ENA */
227#define WM8993_ADCR_ENA_WIDTH 1 /* ADCR_ENA */
228
229/*
230 * R3 (0x03) - Power Management (3)
231 */
232#define WM8993_LINEOUT1N_ENA 0x2000 /* LINEOUT1N_ENA */
233#define WM8993_LINEOUT1N_ENA_MASK 0x2000 /* LINEOUT1N_ENA */
234#define WM8993_LINEOUT1N_ENA_SHIFT 13 /* LINEOUT1N_ENA */
235#define WM8993_LINEOUT1N_ENA_WIDTH 1 /* LINEOUT1N_ENA */
236#define WM8993_LINEOUT1P_ENA 0x1000 /* LINEOUT1P_ENA */
237#define WM8993_LINEOUT1P_ENA_MASK 0x1000 /* LINEOUT1P_ENA */
238#define WM8993_LINEOUT1P_ENA_SHIFT 12 /* LINEOUT1P_ENA */
239#define WM8993_LINEOUT1P_ENA_WIDTH 1 /* LINEOUT1P_ENA */
240#define WM8993_LINEOUT2N_ENA 0x0800 /* LINEOUT2N_ENA */
241#define WM8993_LINEOUT2N_ENA_MASK 0x0800 /* LINEOUT2N_ENA */
242#define WM8993_LINEOUT2N_ENA_SHIFT 11 /* LINEOUT2N_ENA */
243#define WM8993_LINEOUT2N_ENA_WIDTH 1 /* LINEOUT2N_ENA */
244#define WM8993_LINEOUT2P_ENA 0x0400 /* LINEOUT2P_ENA */
245#define WM8993_LINEOUT2P_ENA_MASK 0x0400 /* LINEOUT2P_ENA */
246#define WM8993_LINEOUT2P_ENA_SHIFT 10 /* LINEOUT2P_ENA */
247#define WM8993_LINEOUT2P_ENA_WIDTH 1 /* LINEOUT2P_ENA */
248#define WM8993_SPKRVOL_ENA 0x0200 /* SPKRVOL_ENA */
249#define WM8993_SPKRVOL_ENA_MASK 0x0200 /* SPKRVOL_ENA */
250#define WM8993_SPKRVOL_ENA_SHIFT 9 /* SPKRVOL_ENA */
251#define WM8993_SPKRVOL_ENA_WIDTH 1 /* SPKRVOL_ENA */
252#define WM8993_SPKLVOL_ENA 0x0100 /* SPKLVOL_ENA */
253#define WM8993_SPKLVOL_ENA_MASK 0x0100 /* SPKLVOL_ENA */
254#define WM8993_SPKLVOL_ENA_SHIFT 8 /* SPKLVOL_ENA */
255#define WM8993_SPKLVOL_ENA_WIDTH 1 /* SPKLVOL_ENA */
256#define WM8993_MIXOUTLVOL_ENA 0x0080 /* MIXOUTLVOL_ENA */
257#define WM8993_MIXOUTLVOL_ENA_MASK 0x0080 /* MIXOUTLVOL_ENA */
258#define WM8993_MIXOUTLVOL_ENA_SHIFT 7 /* MIXOUTLVOL_ENA */
259#define WM8993_MIXOUTLVOL_ENA_WIDTH 1 /* MIXOUTLVOL_ENA */
260#define WM8993_MIXOUTRVOL_ENA 0x0040 /* MIXOUTRVOL_ENA */
261#define WM8993_MIXOUTRVOL_ENA_MASK 0x0040 /* MIXOUTRVOL_ENA */
262#define WM8993_MIXOUTRVOL_ENA_SHIFT 6 /* MIXOUTRVOL_ENA */
263#define WM8993_MIXOUTRVOL_ENA_WIDTH 1 /* MIXOUTRVOL_ENA */
264#define WM8993_MIXOUTL_ENA 0x0020 /* MIXOUTL_ENA */
265#define WM8993_MIXOUTL_ENA_MASK 0x0020 /* MIXOUTL_ENA */
266#define WM8993_MIXOUTL_ENA_SHIFT 5 /* MIXOUTL_ENA */
267#define WM8993_MIXOUTL_ENA_WIDTH 1 /* MIXOUTL_ENA */
268#define WM8993_MIXOUTR_ENA 0x0010 /* MIXOUTR_ENA */
269#define WM8993_MIXOUTR_ENA_MASK 0x0010 /* MIXOUTR_ENA */
270#define WM8993_MIXOUTR_ENA_SHIFT 4 /* MIXOUTR_ENA */
271#define WM8993_MIXOUTR_ENA_WIDTH 1 /* MIXOUTR_ENA */
272#define WM8993_DACL_ENA 0x0002 /* DACL_ENA */
273#define WM8993_DACL_ENA_MASK 0x0002 /* DACL_ENA */
274#define WM8993_DACL_ENA_SHIFT 1 /* DACL_ENA */
275#define WM8993_DACL_ENA_WIDTH 1 /* DACL_ENA */
276#define WM8993_DACR_ENA 0x0001 /* DACR_ENA */
277#define WM8993_DACR_ENA_MASK 0x0001 /* DACR_ENA */
278#define WM8993_DACR_ENA_SHIFT 0 /* DACR_ENA */
279#define WM8993_DACR_ENA_WIDTH 1 /* DACR_ENA */
280
281/*
282 * R4 (0x04) - Audio Interface (1)
283 */
284#define WM8993_AIFADCL_SRC 0x8000 /* AIFADCL_SRC */
285#define WM8993_AIFADCL_SRC_MASK 0x8000 /* AIFADCL_SRC */
286#define WM8993_AIFADCL_SRC_SHIFT 15 /* AIFADCL_SRC */
287#define WM8993_AIFADCL_SRC_WIDTH 1 /* AIFADCL_SRC */
288#define WM8993_AIFADCR_SRC 0x4000 /* AIFADCR_SRC */
289#define WM8993_AIFADCR_SRC_MASK 0x4000 /* AIFADCR_SRC */
290#define WM8993_AIFADCR_SRC_SHIFT 14 /* AIFADCR_SRC */
291#define WM8993_AIFADCR_SRC_WIDTH 1 /* AIFADCR_SRC */
292#define WM8993_AIFADC_TDM 0x2000 /* AIFADC_TDM */
293#define WM8993_AIFADC_TDM_MASK 0x2000 /* AIFADC_TDM */
294#define WM8993_AIFADC_TDM_SHIFT 13 /* AIFADC_TDM */
295#define WM8993_AIFADC_TDM_WIDTH 1 /* AIFADC_TDM */
296#define WM8993_AIFADC_TDM_CHAN 0x1000 /* AIFADC_TDM_CHAN */
297#define WM8993_AIFADC_TDM_CHAN_MASK 0x1000 /* AIFADC_TDM_CHAN */
298#define WM8993_AIFADC_TDM_CHAN_SHIFT 12 /* AIFADC_TDM_CHAN */
299#define WM8993_AIFADC_TDM_CHAN_WIDTH 1 /* AIFADC_TDM_CHAN */
300#define WM8993_BCLK_DIR 0x0200 /* BCLK_DIR */
301#define WM8993_BCLK_DIR_MASK 0x0200 /* BCLK_DIR */
302#define WM8993_BCLK_DIR_SHIFT 9 /* BCLK_DIR */
303#define WM8993_BCLK_DIR_WIDTH 1 /* BCLK_DIR */
304#define WM8993_AIF_BCLK_INV 0x0100 /* AIF_BCLK_INV */
305#define WM8993_AIF_BCLK_INV_MASK 0x0100 /* AIF_BCLK_INV */
306#define WM8993_AIF_BCLK_INV_SHIFT 8 /* AIF_BCLK_INV */
307#define WM8993_AIF_BCLK_INV_WIDTH 1 /* AIF_BCLK_INV */
308#define WM8993_AIF_LRCLK_INV 0x0080 /* AIF_LRCLK_INV */
309#define WM8993_AIF_LRCLK_INV_MASK 0x0080 /* AIF_LRCLK_INV */
310#define WM8993_AIF_LRCLK_INV_SHIFT 7 /* AIF_LRCLK_INV */
311#define WM8993_AIF_LRCLK_INV_WIDTH 1 /* AIF_LRCLK_INV */
312#define WM8993_AIF_WL_MASK 0x0060 /* AIF_WL - [6:5] */
313#define WM8993_AIF_WL_SHIFT 5 /* AIF_WL - [6:5] */
314#define WM8993_AIF_WL_WIDTH 2 /* AIF_WL - [6:5] */
315#define WM8993_AIF_FMT_MASK 0x0018 /* AIF_FMT - [4:3] */
316#define WM8993_AIF_FMT_SHIFT 3 /* AIF_FMT - [4:3] */
317#define WM8993_AIF_FMT_WIDTH 2 /* AIF_FMT - [4:3] */
318
319/*
320 * R5 (0x05) - Audio Interface (2)
321 */
322#define WM8993_AIFDACL_SRC 0x8000 /* AIFDACL_SRC */
323#define WM8993_AIFDACL_SRC_MASK 0x8000 /* AIFDACL_SRC */
324#define WM8993_AIFDACL_SRC_SHIFT 15 /* AIFDACL_SRC */
325#define WM8993_AIFDACL_SRC_WIDTH 1 /* AIFDACL_SRC */
326#define WM8993_AIFDACR_SRC 0x4000 /* AIFDACR_SRC */
327#define WM8993_AIFDACR_SRC_MASK 0x4000 /* AIFDACR_SRC */
328#define WM8993_AIFDACR_SRC_SHIFT 14 /* AIFDACR_SRC */
329#define WM8993_AIFDACR_SRC_WIDTH 1 /* AIFDACR_SRC */
330#define WM8993_AIFDAC_TDM 0x2000 /* AIFDAC_TDM */
331#define WM8993_AIFDAC_TDM_MASK 0x2000 /* AIFDAC_TDM */
332#define WM8993_AIFDAC_TDM_SHIFT 13 /* AIFDAC_TDM */
333#define WM8993_AIFDAC_TDM_WIDTH 1 /* AIFDAC_TDM */
334#define WM8993_AIFDAC_TDM_CHAN 0x1000 /* AIFDAC_TDM_CHAN */
335#define WM8993_AIFDAC_TDM_CHAN_MASK 0x1000 /* AIFDAC_TDM_CHAN */
336#define WM8993_AIFDAC_TDM_CHAN_SHIFT 12 /* AIFDAC_TDM_CHAN */
337#define WM8993_AIFDAC_TDM_CHAN_WIDTH 1 /* AIFDAC_TDM_CHAN */
338#define WM8993_DAC_BOOST_MASK 0x0C00 /* DAC_BOOST - [11:10] */
339#define WM8993_DAC_BOOST_SHIFT 10 /* DAC_BOOST - [11:10] */
340#define WM8993_DAC_BOOST_WIDTH 2 /* DAC_BOOST - [11:10] */
341#define WM8993_DAC_COMP 0x0010 /* DAC_COMP */
342#define WM8993_DAC_COMP_MASK 0x0010 /* DAC_COMP */
343#define WM8993_DAC_COMP_SHIFT 4 /* DAC_COMP */
344#define WM8993_DAC_COMP_WIDTH 1 /* DAC_COMP */
345#define WM8993_DAC_COMPMODE 0x0008 /* DAC_COMPMODE */
346#define WM8993_DAC_COMPMODE_MASK 0x0008 /* DAC_COMPMODE */
347#define WM8993_DAC_COMPMODE_SHIFT 3 /* DAC_COMPMODE */
348#define WM8993_DAC_COMPMODE_WIDTH 1 /* DAC_COMPMODE */
349#define WM8993_ADC_COMP 0x0004 /* ADC_COMP */
350#define WM8993_ADC_COMP_MASK 0x0004 /* ADC_COMP */
351#define WM8993_ADC_COMP_SHIFT 2 /* ADC_COMP */
352#define WM8993_ADC_COMP_WIDTH 1 /* ADC_COMP */
353#define WM8993_ADC_COMPMODE 0x0002 /* ADC_COMPMODE */
354#define WM8993_ADC_COMPMODE_MASK 0x0002 /* ADC_COMPMODE */
355#define WM8993_ADC_COMPMODE_SHIFT 1 /* ADC_COMPMODE */
356#define WM8993_ADC_COMPMODE_WIDTH 1 /* ADC_COMPMODE */
357#define WM8993_LOOPBACK 0x0001 /* LOOPBACK */
358#define WM8993_LOOPBACK_MASK 0x0001 /* LOOPBACK */
359#define WM8993_LOOPBACK_SHIFT 0 /* LOOPBACK */
360#define WM8993_LOOPBACK_WIDTH 1 /* LOOPBACK */
361
362/*
363 * R6 (0x06) - Clocking 1
364 */
365#define WM8993_TOCLK_RATE 0x8000 /* TOCLK_RATE */
366#define WM8993_TOCLK_RATE_MASK 0x8000 /* TOCLK_RATE */
367#define WM8993_TOCLK_RATE_SHIFT 15 /* TOCLK_RATE */
368#define WM8993_TOCLK_RATE_WIDTH 1 /* TOCLK_RATE */
369#define WM8993_TOCLK_ENA 0x4000 /* TOCLK_ENA */
370#define WM8993_TOCLK_ENA_MASK 0x4000 /* TOCLK_ENA */
371#define WM8993_TOCLK_ENA_SHIFT 14 /* TOCLK_ENA */
372#define WM8993_TOCLK_ENA_WIDTH 1 /* TOCLK_ENA */
373#define WM8993_OPCLK_DIV_MASK 0x1E00 /* OPCLK_DIV - [12:9] */
374#define WM8993_OPCLK_DIV_SHIFT 9 /* OPCLK_DIV - [12:9] */
375#define WM8993_OPCLK_DIV_WIDTH 4 /* OPCLK_DIV - [12:9] */
376#define WM8993_DCLK_DIV_MASK 0x01C0 /* DCLK_DIV - [8:6] */
377#define WM8993_DCLK_DIV_SHIFT 6 /* DCLK_DIV - [8:6] */
378#define WM8993_DCLK_DIV_WIDTH 3 /* DCLK_DIV - [8:6] */
379#define WM8993_BCLK_DIV_MASK 0x001E /* BCLK_DIV - [4:1] */
380#define WM8993_BCLK_DIV_SHIFT 1 /* BCLK_DIV - [4:1] */
381#define WM8993_BCLK_DIV_WIDTH 4 /* BCLK_DIV - [4:1] */
382
383/*
384 * R7 (0x07) - Clocking 2
385 */
386#define WM8993_MCLK_SRC 0x8000 /* MCLK_SRC */
387#define WM8993_MCLK_SRC_MASK 0x8000 /* MCLK_SRC */
388#define WM8993_MCLK_SRC_SHIFT 15 /* MCLK_SRC */
389#define WM8993_MCLK_SRC_WIDTH 1 /* MCLK_SRC */
390#define WM8993_SYSCLK_SRC 0x4000 /* SYSCLK_SRC */
391#define WM8993_SYSCLK_SRC_MASK 0x4000 /* SYSCLK_SRC */
392#define WM8993_SYSCLK_SRC_SHIFT 14 /* SYSCLK_SRC */
393#define WM8993_SYSCLK_SRC_WIDTH 1 /* SYSCLK_SRC */
394#define WM8993_MCLK_DIV 0x1000 /* MCLK_DIV */
395#define WM8993_MCLK_DIV_MASK 0x1000 /* MCLK_DIV */
396#define WM8993_MCLK_DIV_SHIFT 12 /* MCLK_DIV */
397#define WM8993_MCLK_DIV_WIDTH 1 /* MCLK_DIV */
398#define WM8993_MCLK_INV 0x0400 /* MCLK_INV */
399#define WM8993_MCLK_INV_MASK 0x0400 /* MCLK_INV */
400#define WM8993_MCLK_INV_SHIFT 10 /* MCLK_INV */
401#define WM8993_MCLK_INV_WIDTH 1 /* MCLK_INV */
402#define WM8993_ADC_DIV_MASK 0x00E0 /* ADC_DIV - [7:5] */
403#define WM8993_ADC_DIV_SHIFT 5 /* ADC_DIV - [7:5] */
404#define WM8993_ADC_DIV_WIDTH 3 /* ADC_DIV - [7:5] */
405#define WM8993_DAC_DIV_MASK 0x001C /* DAC_DIV - [4:2] */
406#define WM8993_DAC_DIV_SHIFT 2 /* DAC_DIV - [4:2] */
407#define WM8993_DAC_DIV_WIDTH 3 /* DAC_DIV - [4:2] */
408
409/*
410 * R8 (0x08) - Audio Interface (3)
411 */
412#define WM8993_AIF_MSTR1 0x8000 /* AIF_MSTR1 */
413#define WM8993_AIF_MSTR1_MASK 0x8000 /* AIF_MSTR1 */
414#define WM8993_AIF_MSTR1_SHIFT 15 /* AIF_MSTR1 */
415#define WM8993_AIF_MSTR1_WIDTH 1 /* AIF_MSTR1 */
416
417/*
418 * R9 (0x09) - Audio Interface (4)
419 */
420#define WM8993_AIF_TRIS 0x2000 /* AIF_TRIS */
421#define WM8993_AIF_TRIS_MASK 0x2000 /* AIF_TRIS */
422#define WM8993_AIF_TRIS_SHIFT 13 /* AIF_TRIS */
423#define WM8993_AIF_TRIS_WIDTH 1 /* AIF_TRIS */
424#define WM8993_LRCLK_DIR 0x0800 /* LRCLK_DIR */
425#define WM8993_LRCLK_DIR_MASK 0x0800 /* LRCLK_DIR */
426#define WM8993_LRCLK_DIR_SHIFT 11 /* LRCLK_DIR */
427#define WM8993_LRCLK_DIR_WIDTH 1 /* LRCLK_DIR */
428#define WM8993_LRCLK_RATE_MASK 0x07FF /* LRCLK_RATE - [10:0] */
429#define WM8993_LRCLK_RATE_SHIFT 0 /* LRCLK_RATE - [10:0] */
430#define WM8993_LRCLK_RATE_WIDTH 11 /* LRCLK_RATE - [10:0] */
431
432/*
433 * R10 (0x0A) - DAC CTRL
434 */
435#define WM8993_DAC_OSR128 0x2000 /* DAC_OSR128 */
436#define WM8993_DAC_OSR128_MASK 0x2000 /* DAC_OSR128 */
437#define WM8993_DAC_OSR128_SHIFT 13 /* DAC_OSR128 */
438#define WM8993_DAC_OSR128_WIDTH 1 /* DAC_OSR128 */
439#define WM8993_DAC_MONO 0x0200 /* DAC_MONO */
440#define WM8993_DAC_MONO_MASK 0x0200 /* DAC_MONO */
441#define WM8993_DAC_MONO_SHIFT 9 /* DAC_MONO */
442#define WM8993_DAC_MONO_WIDTH 1 /* DAC_MONO */
443#define WM8993_DAC_SB_FILT 0x0100 /* DAC_SB_FILT */
444#define WM8993_DAC_SB_FILT_MASK 0x0100 /* DAC_SB_FILT */
445#define WM8993_DAC_SB_FILT_SHIFT 8 /* DAC_SB_FILT */
446#define WM8993_DAC_SB_FILT_WIDTH 1 /* DAC_SB_FILT */
447#define WM8993_DAC_MUTERATE 0x0080 /* DAC_MUTERATE */
448#define WM8993_DAC_MUTERATE_MASK 0x0080 /* DAC_MUTERATE */
449#define WM8993_DAC_MUTERATE_SHIFT 7 /* DAC_MUTERATE */
450#define WM8993_DAC_MUTERATE_WIDTH 1 /* DAC_MUTERATE */
451#define WM8993_DAC_UNMUTE_RAMP 0x0040 /* DAC_UNMUTE_RAMP */
452#define WM8993_DAC_UNMUTE_RAMP_MASK 0x0040 /* DAC_UNMUTE_RAMP */
453#define WM8993_DAC_UNMUTE_RAMP_SHIFT 6 /* DAC_UNMUTE_RAMP */
454#define WM8993_DAC_UNMUTE_RAMP_WIDTH 1 /* DAC_UNMUTE_RAMP */
455#define WM8993_DEEMPH_MASK 0x0030 /* DEEMPH - [5:4] */
456#define WM8993_DEEMPH_SHIFT 4 /* DEEMPH - [5:4] */
457#define WM8993_DEEMPH_WIDTH 2 /* DEEMPH - [5:4] */
458#define WM8993_DAC_MUTE 0x0004 /* DAC_MUTE */
459#define WM8993_DAC_MUTE_MASK 0x0004 /* DAC_MUTE */
460#define WM8993_DAC_MUTE_SHIFT 2 /* DAC_MUTE */
461#define WM8993_DAC_MUTE_WIDTH 1 /* DAC_MUTE */
462#define WM8993_DACL_DATINV 0x0002 /* DACL_DATINV */
463#define WM8993_DACL_DATINV_MASK 0x0002 /* DACL_DATINV */
464#define WM8993_DACL_DATINV_SHIFT 1 /* DACL_DATINV */
465#define WM8993_DACL_DATINV_WIDTH 1 /* DACL_DATINV */
466#define WM8993_DACR_DATINV 0x0001 /* DACR_DATINV */
467#define WM8993_DACR_DATINV_MASK 0x0001 /* DACR_DATINV */
468#define WM8993_DACR_DATINV_SHIFT 0 /* DACR_DATINV */
469#define WM8993_DACR_DATINV_WIDTH 1 /* DACR_DATINV */
470
471/*
472 * R11 (0x0B) - Left DAC Digital Volume
473 */
474#define WM8993_DAC_VU 0x0100 /* DAC_VU */
475#define WM8993_DAC_VU_MASK 0x0100 /* DAC_VU */
476#define WM8993_DAC_VU_SHIFT 8 /* DAC_VU */
477#define WM8993_DAC_VU_WIDTH 1 /* DAC_VU */
478#define WM8993_DACL_VOL_MASK 0x00FF /* DACL_VOL - [7:0] */
479#define WM8993_DACL_VOL_SHIFT 0 /* DACL_VOL - [7:0] */
480#define WM8993_DACL_VOL_WIDTH 8 /* DACL_VOL - [7:0] */
481
482/*
483 * R12 (0x0C) - Right DAC Digital Volume
484 */
485#define WM8993_DAC_VU 0x0100 /* DAC_VU */
486#define WM8993_DAC_VU_MASK 0x0100 /* DAC_VU */
487#define WM8993_DAC_VU_SHIFT 8 /* DAC_VU */
488#define WM8993_DAC_VU_WIDTH 1 /* DAC_VU */
489#define WM8993_DACR_VOL_MASK 0x00FF /* DACR_VOL - [7:0] */
490#define WM8993_DACR_VOL_SHIFT 0 /* DACR_VOL - [7:0] */
491#define WM8993_DACR_VOL_WIDTH 8 /* DACR_VOL - [7:0] */
492
493/*
494 * R13 (0x0D) - Digital Side Tone
495 */
496#define WM8993_ADCL_DAC_SVOL_MASK 0x1E00 /* ADCL_DAC_SVOL - [12:9] */
497#define WM8993_ADCL_DAC_SVOL_SHIFT 9 /* ADCL_DAC_SVOL - [12:9] */
498#define WM8993_ADCL_DAC_SVOL_WIDTH 4 /* ADCL_DAC_SVOL - [12:9] */
499#define WM8993_ADCR_DAC_SVOL_MASK 0x01E0 /* ADCR_DAC_SVOL - [8:5] */
500#define WM8993_ADCR_DAC_SVOL_SHIFT 5 /* ADCR_DAC_SVOL - [8:5] */
501#define WM8993_ADCR_DAC_SVOL_WIDTH 4 /* ADCR_DAC_SVOL - [8:5] */
502#define WM8993_ADC_TO_DACL_MASK 0x000C /* ADC_TO_DACL - [3:2] */
503#define WM8993_ADC_TO_DACL_SHIFT 2 /* ADC_TO_DACL - [3:2] */
504#define WM8993_ADC_TO_DACL_WIDTH 2 /* ADC_TO_DACL - [3:2] */
505#define WM8993_ADC_TO_DACR_MASK 0x0003 /* ADC_TO_DACR - [1:0] */
506#define WM8993_ADC_TO_DACR_SHIFT 0 /* ADC_TO_DACR - [1:0] */
507#define WM8993_ADC_TO_DACR_WIDTH 2 /* ADC_TO_DACR - [1:0] */
508
509/*
510 * R14 (0x0E) - ADC CTRL
511 */
512#define WM8993_ADC_OSR128 0x0200 /* ADC_OSR128 */
513#define WM8993_ADC_OSR128_MASK 0x0200 /* ADC_OSR128 */
514#define WM8993_ADC_OSR128_SHIFT 9 /* ADC_OSR128 */
515#define WM8993_ADC_OSR128_WIDTH 1 /* ADC_OSR128 */
516#define WM8993_ADC_HPF 0x0100 /* ADC_HPF */
517#define WM8993_ADC_HPF_MASK 0x0100 /* ADC_HPF */
518#define WM8993_ADC_HPF_SHIFT 8 /* ADC_HPF */
519#define WM8993_ADC_HPF_WIDTH 1 /* ADC_HPF */
520#define WM8993_ADC_HPF_CUT_MASK 0x0060 /* ADC_HPF_CUT - [6:5] */
521#define WM8993_ADC_HPF_CUT_SHIFT 5 /* ADC_HPF_CUT - [6:5] */
522#define WM8993_ADC_HPF_CUT_WIDTH 2 /* ADC_HPF_CUT - [6:5] */
523#define WM8993_ADCL_DATINV 0x0002 /* ADCL_DATINV */
524#define WM8993_ADCL_DATINV_MASK 0x0002 /* ADCL_DATINV */
525#define WM8993_ADCL_DATINV_SHIFT 1 /* ADCL_DATINV */
526#define WM8993_ADCL_DATINV_WIDTH 1 /* ADCL_DATINV */
527#define WM8993_ADCR_DATINV 0x0001 /* ADCR_DATINV */
528#define WM8993_ADCR_DATINV_MASK 0x0001 /* ADCR_DATINV */
529#define WM8993_ADCR_DATINV_SHIFT 0 /* ADCR_DATINV */
530#define WM8993_ADCR_DATINV_WIDTH 1 /* ADCR_DATINV */
531
532/*
533 * R15 (0x0F) - Left ADC Digital Volume
534 */
535#define WM8993_ADC_VU 0x0100 /* ADC_VU */
536#define WM8993_ADC_VU_MASK 0x0100 /* ADC_VU */
537#define WM8993_ADC_VU_SHIFT 8 /* ADC_VU */
538#define WM8993_ADC_VU_WIDTH 1 /* ADC_VU */
539#define WM8993_ADCL_VOL_MASK 0x00FF /* ADCL_VOL - [7:0] */
540#define WM8993_ADCL_VOL_SHIFT 0 /* ADCL_VOL - [7:0] */
541#define WM8993_ADCL_VOL_WIDTH 8 /* ADCL_VOL - [7:0] */
542
543/*
544 * R16 (0x10) - Right ADC Digital Volume
545 */
546#define WM8993_ADC_VU 0x0100 /* ADC_VU */
547#define WM8993_ADC_VU_MASK 0x0100 /* ADC_VU */
548#define WM8993_ADC_VU_SHIFT 8 /* ADC_VU */
549#define WM8993_ADC_VU_WIDTH 1 /* ADC_VU */
550#define WM8993_ADCR_VOL_MASK 0x00FF /* ADCR_VOL - [7:0] */
551#define WM8993_ADCR_VOL_SHIFT 0 /* ADCR_VOL - [7:0] */
552#define WM8993_ADCR_VOL_WIDTH 8 /* ADCR_VOL - [7:0] */
553
554/*
555 * R18 (0x12) - GPIO CTRL 1
556 */
557#define WM8993_JD2_SC_EINT 0x8000 /* JD2_SC_EINT */
558#define WM8993_JD2_SC_EINT_MASK 0x8000 /* JD2_SC_EINT */
559#define WM8993_JD2_SC_EINT_SHIFT 15 /* JD2_SC_EINT */
560#define WM8993_JD2_SC_EINT_WIDTH 1 /* JD2_SC_EINT */
561#define WM8993_JD2_EINT 0x4000 /* JD2_EINT */
562#define WM8993_JD2_EINT_MASK 0x4000 /* JD2_EINT */
563#define WM8993_JD2_EINT_SHIFT 14 /* JD2_EINT */
564#define WM8993_JD2_EINT_WIDTH 1 /* JD2_EINT */
565#define WM8993_WSEQ_EINT 0x2000 /* WSEQ_EINT */
566#define WM8993_WSEQ_EINT_MASK 0x2000 /* WSEQ_EINT */
567#define WM8993_WSEQ_EINT_SHIFT 13 /* WSEQ_EINT */
568#define WM8993_WSEQ_EINT_WIDTH 1 /* WSEQ_EINT */
569#define WM8993_IRQ 0x1000 /* IRQ */
570#define WM8993_IRQ_MASK 0x1000 /* IRQ */
571#define WM8993_IRQ_SHIFT 12 /* IRQ */
572#define WM8993_IRQ_WIDTH 1 /* IRQ */
573#define WM8993_TEMPOK_EINT 0x0800 /* TEMPOK_EINT */
574#define WM8993_TEMPOK_EINT_MASK 0x0800 /* TEMPOK_EINT */
575#define WM8993_TEMPOK_EINT_SHIFT 11 /* TEMPOK_EINT */
576#define WM8993_TEMPOK_EINT_WIDTH 1 /* TEMPOK_EINT */
577#define WM8993_JD1_SC_EINT 0x0400 /* JD1_SC_EINT */
578#define WM8993_JD1_SC_EINT_MASK 0x0400 /* JD1_SC_EINT */
579#define WM8993_JD1_SC_EINT_SHIFT 10 /* JD1_SC_EINT */
580#define WM8993_JD1_SC_EINT_WIDTH 1 /* JD1_SC_EINT */
581#define WM8993_JD1_EINT 0x0200 /* JD1_EINT */
582#define WM8993_JD1_EINT_MASK 0x0200 /* JD1_EINT */
583#define WM8993_JD1_EINT_SHIFT 9 /* JD1_EINT */
584#define WM8993_JD1_EINT_WIDTH 1 /* JD1_EINT */
585#define WM8993_FLL_LOCK_EINT 0x0100 /* FLL_LOCK_EINT */
586#define WM8993_FLL_LOCK_EINT_MASK 0x0100 /* FLL_LOCK_EINT */
587#define WM8993_FLL_LOCK_EINT_SHIFT 8 /* FLL_LOCK_EINT */
588#define WM8993_FLL_LOCK_EINT_WIDTH 1 /* FLL_LOCK_EINT */
589#define WM8993_GPI8_EINT 0x0080 /* GPI8_EINT */
590#define WM8993_GPI8_EINT_MASK 0x0080 /* GPI8_EINT */
591#define WM8993_GPI8_EINT_SHIFT 7 /* GPI8_EINT */
592#define WM8993_GPI8_EINT_WIDTH 1 /* GPI8_EINT */
593#define WM8993_GPI7_EINT 0x0040 /* GPI7_EINT */
594#define WM8993_GPI7_EINT_MASK 0x0040 /* GPI7_EINT */
595#define WM8993_GPI7_EINT_SHIFT 6 /* GPI7_EINT */
596#define WM8993_GPI7_EINT_WIDTH 1 /* GPI7_EINT */
597#define WM8993_GPIO1_EINT 0x0001 /* GPIO1_EINT */
598#define WM8993_GPIO1_EINT_MASK 0x0001 /* GPIO1_EINT */
599#define WM8993_GPIO1_EINT_SHIFT 0 /* GPIO1_EINT */
600#define WM8993_GPIO1_EINT_WIDTH 1 /* GPIO1_EINT */
601
602/*
603 * R19 (0x13) - GPIO1
604 */
605#define WM8993_GPIO1_PU 0x0020 /* GPIO1_PU */
606#define WM8993_GPIO1_PU_MASK 0x0020 /* GPIO1_PU */
607#define WM8993_GPIO1_PU_SHIFT 5 /* GPIO1_PU */
608#define WM8993_GPIO1_PU_WIDTH 1 /* GPIO1_PU */
609#define WM8993_GPIO1_PD 0x0010 /* GPIO1_PD */
610#define WM8993_GPIO1_PD_MASK 0x0010 /* GPIO1_PD */
611#define WM8993_GPIO1_PD_SHIFT 4 /* GPIO1_PD */
612#define WM8993_GPIO1_PD_WIDTH 1 /* GPIO1_PD */
613#define WM8993_GPIO1_SEL_MASK 0x000F /* GPIO1_SEL - [3:0] */
614#define WM8993_GPIO1_SEL_SHIFT 0 /* GPIO1_SEL - [3:0] */
615#define WM8993_GPIO1_SEL_WIDTH 4 /* GPIO1_SEL - [3:0] */
616
617/*
618 * R20 (0x14) - IRQ_DEBOUNCE
619 */
620#define WM8993_JD2_SC_DB 0x8000 /* JD2_SC_DB */
621#define WM8993_JD2_SC_DB_MASK 0x8000 /* JD2_SC_DB */
622#define WM8993_JD2_SC_DB_SHIFT 15 /* JD2_SC_DB */
623#define WM8993_JD2_SC_DB_WIDTH 1 /* JD2_SC_DB */
624#define WM8993_JD2_DB 0x4000 /* JD2_DB */
625#define WM8993_JD2_DB_MASK 0x4000 /* JD2_DB */
626#define WM8993_JD2_DB_SHIFT 14 /* JD2_DB */
627#define WM8993_JD2_DB_WIDTH 1 /* JD2_DB */
628#define WM8993_WSEQ_DB 0x2000 /* WSEQ_DB */
629#define WM8993_WSEQ_DB_MASK 0x2000 /* WSEQ_DB */
630#define WM8993_WSEQ_DB_SHIFT 13 /* WSEQ_DB */
631#define WM8993_WSEQ_DB_WIDTH 1 /* WSEQ_DB */
632#define WM8993_TEMPOK_DB 0x0800 /* TEMPOK_DB */
633#define WM8993_TEMPOK_DB_MASK 0x0800 /* TEMPOK_DB */
634#define WM8993_TEMPOK_DB_SHIFT 11 /* TEMPOK_DB */
635#define WM8993_TEMPOK_DB_WIDTH 1 /* TEMPOK_DB */
636#define WM8993_JD1_SC_DB 0x0400 /* JD1_SC_DB */
637#define WM8993_JD1_SC_DB_MASK 0x0400 /* JD1_SC_DB */
638#define WM8993_JD1_SC_DB_SHIFT 10 /* JD1_SC_DB */
639#define WM8993_JD1_SC_DB_WIDTH 1 /* JD1_SC_DB */
640#define WM8993_JD1_DB 0x0200 /* JD1_DB */
641#define WM8993_JD1_DB_MASK 0x0200 /* JD1_DB */
642#define WM8993_JD1_DB_SHIFT 9 /* JD1_DB */
643#define WM8993_JD1_DB_WIDTH 1 /* JD1_DB */
644#define WM8993_FLL_LOCK_DB 0x0100 /* FLL_LOCK_DB */
645#define WM8993_FLL_LOCK_DB_MASK 0x0100 /* FLL_LOCK_DB */
646#define WM8993_FLL_LOCK_DB_SHIFT 8 /* FLL_LOCK_DB */
647#define WM8993_FLL_LOCK_DB_WIDTH 1 /* FLL_LOCK_DB */
648#define WM8993_GPI8_DB 0x0080 /* GPI8_DB */
649#define WM8993_GPI8_DB_MASK 0x0080 /* GPI8_DB */
650#define WM8993_GPI8_DB_SHIFT 7 /* GPI8_DB */
651#define WM8993_GPI8_DB_WIDTH 1 /* GPI8_DB */
652#define WM8993_GPI7_DB 0x0008 /* GPI7_DB */
653#define WM8993_GPI7_DB_MASK 0x0008 /* GPI7_DB */
654#define WM8993_GPI7_DB_SHIFT 3 /* GPI7_DB */
655#define WM8993_GPI7_DB_WIDTH 1 /* GPI7_DB */
656#define WM8993_GPIO1_DB 0x0001 /* GPIO1_DB */
657#define WM8993_GPIO1_DB_MASK 0x0001 /* GPIO1_DB */
658#define WM8993_GPIO1_DB_SHIFT 0 /* GPIO1_DB */
659#define WM8993_GPIO1_DB_WIDTH 1 /* GPIO1_DB */
660
661/*
662 * R22 (0x16) - GPIOCTRL 2
663 */
664#define WM8993_IM_JD2_EINT 0x2000 /* IM_JD2_EINT */
665#define WM8993_IM_JD2_EINT_MASK 0x2000 /* IM_JD2_EINT */
666#define WM8993_IM_JD2_EINT_SHIFT 13 /* IM_JD2_EINT */
667#define WM8993_IM_JD2_EINT_WIDTH 1 /* IM_JD2_EINT */
668#define WM8993_IM_JD2_SC_EINT 0x1000 /* IM_JD2_SC_EINT */
669#define WM8993_IM_JD2_SC_EINT_MASK 0x1000 /* IM_JD2_SC_EINT */
670#define WM8993_IM_JD2_SC_EINT_SHIFT 12 /* IM_JD2_SC_EINT */
671#define WM8993_IM_JD2_SC_EINT_WIDTH 1 /* IM_JD2_SC_EINT */
672#define WM8993_IM_TEMPOK_EINT 0x0800 /* IM_TEMPOK_EINT */
673#define WM8993_IM_TEMPOK_EINT_MASK 0x0800 /* IM_TEMPOK_EINT */
674#define WM8993_IM_TEMPOK_EINT_SHIFT 11 /* IM_TEMPOK_EINT */
675#define WM8993_IM_TEMPOK_EINT_WIDTH 1 /* IM_TEMPOK_EINT */
676#define WM8993_IM_JD1_SC_EINT 0x0400 /* IM_JD1_SC_EINT */
677#define WM8993_IM_JD1_SC_EINT_MASK 0x0400 /* IM_JD1_SC_EINT */
678#define WM8993_IM_JD1_SC_EINT_SHIFT 10 /* IM_JD1_SC_EINT */
679#define WM8993_IM_JD1_SC_EINT_WIDTH 1 /* IM_JD1_SC_EINT */
680#define WM8993_IM_JD1_EINT 0x0200 /* IM_JD1_EINT */
681#define WM8993_IM_JD1_EINT_MASK 0x0200 /* IM_JD1_EINT */
682#define WM8993_IM_JD1_EINT_SHIFT 9 /* IM_JD1_EINT */
683#define WM8993_IM_JD1_EINT_WIDTH 1 /* IM_JD1_EINT */
684#define WM8993_IM_FLL_LOCK_EINT 0x0100 /* IM_FLL_LOCK_EINT */
685#define WM8993_IM_FLL_LOCK_EINT_MASK 0x0100 /* IM_FLL_LOCK_EINT */
686#define WM8993_IM_FLL_LOCK_EINT_SHIFT 8 /* IM_FLL_LOCK_EINT */
687#define WM8993_IM_FLL_LOCK_EINT_WIDTH 1 /* IM_FLL_LOCK_EINT */
688#define WM8993_IM_GPI8_EINT 0x0040 /* IM_GPI8_EINT */
689#define WM8993_IM_GPI8_EINT_MASK 0x0040 /* IM_GPI8_EINT */
690#define WM8993_IM_GPI8_EINT_SHIFT 6 /* IM_GPI8_EINT */
691#define WM8993_IM_GPI8_EINT_WIDTH 1 /* IM_GPI8_EINT */
692#define WM8993_IM_GPIO1_EINT 0x0020 /* IM_GPIO1_EINT */
693#define WM8993_IM_GPIO1_EINT_MASK 0x0020 /* IM_GPIO1_EINT */
694#define WM8993_IM_GPIO1_EINT_SHIFT 5 /* IM_GPIO1_EINT */
695#define WM8993_IM_GPIO1_EINT_WIDTH 1 /* IM_GPIO1_EINT */
696#define WM8993_GPI8_ENA 0x0010 /* GPI8_ENA */
697#define WM8993_GPI8_ENA_MASK 0x0010 /* GPI8_ENA */
698#define WM8993_GPI8_ENA_SHIFT 4 /* GPI8_ENA */
699#define WM8993_GPI8_ENA_WIDTH 1 /* GPI8_ENA */
700#define WM8993_IM_GPI7_EINT 0x0004 /* IM_GPI7_EINT */
701#define WM8993_IM_GPI7_EINT_MASK 0x0004 /* IM_GPI7_EINT */
702#define WM8993_IM_GPI7_EINT_SHIFT 2 /* IM_GPI7_EINT */
703#define WM8993_IM_GPI7_EINT_WIDTH 1 /* IM_GPI7_EINT */
704#define WM8993_IM_WSEQ_EINT 0x0002 /* IM_WSEQ_EINT */
705#define WM8993_IM_WSEQ_EINT_MASK 0x0002 /* IM_WSEQ_EINT */
706#define WM8993_IM_WSEQ_EINT_SHIFT 1 /* IM_WSEQ_EINT */
707#define WM8993_IM_WSEQ_EINT_WIDTH 1 /* IM_WSEQ_EINT */
708#define WM8993_GPI7_ENA 0x0001 /* GPI7_ENA */
709#define WM8993_GPI7_ENA_MASK 0x0001 /* GPI7_ENA */
710#define WM8993_GPI7_ENA_SHIFT 0 /* GPI7_ENA */
711#define WM8993_GPI7_ENA_WIDTH 1 /* GPI7_ENA */
712
713/*
714 * R23 (0x17) - GPIO_POL
715 */
716#define WM8993_JD2_SC_POL 0x8000 /* JD2_SC_POL */
717#define WM8993_JD2_SC_POL_MASK 0x8000 /* JD2_SC_POL */
718#define WM8993_JD2_SC_POL_SHIFT 15 /* JD2_SC_POL */
719#define WM8993_JD2_SC_POL_WIDTH 1 /* JD2_SC_POL */
720#define WM8993_JD2_POL 0x4000 /* JD2_POL */
721#define WM8993_JD2_POL_MASK 0x4000 /* JD2_POL */
722#define WM8993_JD2_POL_SHIFT 14 /* JD2_POL */
723#define WM8993_JD2_POL_WIDTH 1 /* JD2_POL */
724#define WM8993_WSEQ_POL 0x2000 /* WSEQ_POL */
725#define WM8993_WSEQ_POL_MASK 0x2000 /* WSEQ_POL */
726#define WM8993_WSEQ_POL_SHIFT 13 /* WSEQ_POL */
727#define WM8993_WSEQ_POL_WIDTH 1 /* WSEQ_POL */
728#define WM8993_IRQ_POL 0x1000 /* IRQ_POL */
729#define WM8993_IRQ_POL_MASK 0x1000 /* IRQ_POL */
730#define WM8993_IRQ_POL_SHIFT 12 /* IRQ_POL */
731#define WM8993_IRQ_POL_WIDTH 1 /* IRQ_POL */
732#define WM8993_TEMPOK_POL 0x0800 /* TEMPOK_POL */
733#define WM8993_TEMPOK_POL_MASK 0x0800 /* TEMPOK_POL */
734#define WM8993_TEMPOK_POL_SHIFT 11 /* TEMPOK_POL */
735#define WM8993_TEMPOK_POL_WIDTH 1 /* TEMPOK_POL */
736#define WM8993_JD1_SC_POL 0x0400 /* JD1_SC_POL */
737#define WM8993_JD1_SC_POL_MASK 0x0400 /* JD1_SC_POL */
738#define WM8993_JD1_SC_POL_SHIFT 10 /* JD1_SC_POL */
739#define WM8993_JD1_SC_POL_WIDTH 1 /* JD1_SC_POL */
740#define WM8993_JD1_POL 0x0200 /* JD1_POL */
741#define WM8993_JD1_POL_MASK 0x0200 /* JD1_POL */
742#define WM8993_JD1_POL_SHIFT 9 /* JD1_POL */
743#define WM8993_JD1_POL_WIDTH 1 /* JD1_POL */
744#define WM8993_FLL_LOCK_POL 0x0100 /* FLL_LOCK_POL */
745#define WM8993_FLL_LOCK_POL_MASK 0x0100 /* FLL_LOCK_POL */
746#define WM8993_FLL_LOCK_POL_SHIFT 8 /* FLL_LOCK_POL */
747#define WM8993_FLL_LOCK_POL_WIDTH 1 /* FLL_LOCK_POL */
748#define WM8993_GPI8_POL 0x0080 /* GPI8_POL */
749#define WM8993_GPI8_POL_MASK 0x0080 /* GPI8_POL */
750#define WM8993_GPI8_POL_SHIFT 7 /* GPI8_POL */
751#define WM8993_GPI8_POL_WIDTH 1 /* GPI8_POL */
752#define WM8993_GPI7_POL 0x0040 /* GPI7_POL */
753#define WM8993_GPI7_POL_MASK 0x0040 /* GPI7_POL */
754#define WM8993_GPI7_POL_SHIFT 6 /* GPI7_POL */
755#define WM8993_GPI7_POL_WIDTH 1 /* GPI7_POL */
756#define WM8993_GPIO1_POL 0x0001 /* GPIO1_POL */
757#define WM8993_GPIO1_POL_MASK 0x0001 /* GPIO1_POL */
758#define WM8993_GPIO1_POL_SHIFT 0 /* GPIO1_POL */
759#define WM8993_GPIO1_POL_WIDTH 1 /* GPIO1_POL */
760
761/*
762 * R24 (0x18) - Left Line Input 1&2 Volume
763 */
764#define WM8993_IN1_VU 0x0100 /* IN1_VU */
765#define WM8993_IN1_VU_MASK 0x0100 /* IN1_VU */
766#define WM8993_IN1_VU_SHIFT 8 /* IN1_VU */
767#define WM8993_IN1_VU_WIDTH 1 /* IN1_VU */
768#define WM8993_IN1L_MUTE 0x0080 /* IN1L_MUTE */
769#define WM8993_IN1L_MUTE_MASK 0x0080 /* IN1L_MUTE */
770#define WM8993_IN1L_MUTE_SHIFT 7 /* IN1L_MUTE */
771#define WM8993_IN1L_MUTE_WIDTH 1 /* IN1L_MUTE */
772#define WM8993_IN1L_ZC 0x0040 /* IN1L_ZC */
773#define WM8993_IN1L_ZC_MASK 0x0040 /* IN1L_ZC */
774#define WM8993_IN1L_ZC_SHIFT 6 /* IN1L_ZC */
775#define WM8993_IN1L_ZC_WIDTH 1 /* IN1L_ZC */
776#define WM8993_IN1L_VOL_MASK 0x001F /* IN1L_VOL - [4:0] */
777#define WM8993_IN1L_VOL_SHIFT 0 /* IN1L_VOL - [4:0] */
778#define WM8993_IN1L_VOL_WIDTH 5 /* IN1L_VOL - [4:0] */
779
780/*
781 * R25 (0x19) - Left Line Input 3&4 Volume
782 */
783#define WM8993_IN2_VU 0x0100 /* IN2_VU */
784#define WM8993_IN2_VU_MASK 0x0100 /* IN2_VU */
785#define WM8993_IN2_VU_SHIFT 8 /* IN2_VU */
786#define WM8993_IN2_VU_WIDTH 1 /* IN2_VU */
787#define WM8993_IN2L_MUTE 0x0080 /* IN2L_MUTE */
788#define WM8993_IN2L_MUTE_MASK 0x0080 /* IN2L_MUTE */
789#define WM8993_IN2L_MUTE_SHIFT 7 /* IN2L_MUTE */
790#define WM8993_IN2L_MUTE_WIDTH 1 /* IN2L_MUTE */
791#define WM8993_IN2L_ZC 0x0040 /* IN2L_ZC */
792#define WM8993_IN2L_ZC_MASK 0x0040 /* IN2L_ZC */
793#define WM8993_IN2L_ZC_SHIFT 6 /* IN2L_ZC */
794#define WM8993_IN2L_ZC_WIDTH 1 /* IN2L_ZC */
795#define WM8993_IN2L_VOL_MASK 0x001F /* IN2L_VOL - [4:0] */
796#define WM8993_IN2L_VOL_SHIFT 0 /* IN2L_VOL - [4:0] */
797#define WM8993_IN2L_VOL_WIDTH 5 /* IN2L_VOL - [4:0] */
798
799/*
800 * R26 (0x1A) - Right Line Input 1&2 Volume
801 */
802#define WM8993_IN1_VU 0x0100 /* IN1_VU */
803#define WM8993_IN1_VU_MASK 0x0100 /* IN1_VU */
804#define WM8993_IN1_VU_SHIFT 8 /* IN1_VU */
805#define WM8993_IN1_VU_WIDTH 1 /* IN1_VU */
806#define WM8993_IN1R_MUTE 0x0080 /* IN1R_MUTE */
807#define WM8993_IN1R_MUTE_MASK 0x0080 /* IN1R_MUTE */
808#define WM8993_IN1R_MUTE_SHIFT 7 /* IN1R_MUTE */
809#define WM8993_IN1R_MUTE_WIDTH 1 /* IN1R_MUTE */
810#define WM8993_IN1R_ZC 0x0040 /* IN1R_ZC */
811#define WM8993_IN1R_ZC_MASK 0x0040 /* IN1R_ZC */
812#define WM8993_IN1R_ZC_SHIFT 6 /* IN1R_ZC */
813#define WM8993_IN1R_ZC_WIDTH 1 /* IN1R_ZC */
814#define WM8993_IN1R_VOL_MASK 0x001F /* IN1R_VOL - [4:0] */
815#define WM8993_IN1R_VOL_SHIFT 0 /* IN1R_VOL - [4:0] */
816#define WM8993_IN1R_VOL_WIDTH 5 /* IN1R_VOL - [4:0] */
817
818/*
819 * R27 (0x1B) - Right Line Input 3&4 Volume
820 */
821#define WM8993_IN2_VU 0x0100 /* IN2_VU */
822#define WM8993_IN2_VU_MASK 0x0100 /* IN2_VU */
823#define WM8993_IN2_VU_SHIFT 8 /* IN2_VU */
824#define WM8993_IN2_VU_WIDTH 1 /* IN2_VU */
825#define WM8993_IN2R_MUTE 0x0080 /* IN2R_MUTE */
826#define WM8993_IN2R_MUTE_MASK 0x0080 /* IN2R_MUTE */
827#define WM8993_IN2R_MUTE_SHIFT 7 /* IN2R_MUTE */
828#define WM8993_IN2R_MUTE_WIDTH 1 /* IN2R_MUTE */
829#define WM8993_IN2R_ZC 0x0040 /* IN2R_ZC */
830#define WM8993_IN2R_ZC_MASK 0x0040 /* IN2R_ZC */
831#define WM8993_IN2R_ZC_SHIFT 6 /* IN2R_ZC */
832#define WM8993_IN2R_ZC_WIDTH 1 /* IN2R_ZC */
833#define WM8993_IN2R_VOL_MASK 0x001F /* IN2R_VOL - [4:0] */
834#define WM8993_IN2R_VOL_SHIFT 0 /* IN2R_VOL - [4:0] */
835#define WM8993_IN2R_VOL_WIDTH 5 /* IN2R_VOL - [4:0] */
836
837/*
838 * R28 (0x1C) - Left Output Volume
839 */
840#define WM8993_HPOUT1_VU 0x0100 /* HPOUT1_VU */
841#define WM8993_HPOUT1_VU_MASK 0x0100 /* HPOUT1_VU */
842#define WM8993_HPOUT1_VU_SHIFT 8 /* HPOUT1_VU */
843#define WM8993_HPOUT1_VU_WIDTH 1 /* HPOUT1_VU */
844#define WM8993_HPOUT1L_ZC 0x0080 /* HPOUT1L_ZC */
845#define WM8993_HPOUT1L_ZC_MASK 0x0080 /* HPOUT1L_ZC */
846#define WM8993_HPOUT1L_ZC_SHIFT 7 /* HPOUT1L_ZC */
847#define WM8993_HPOUT1L_ZC_WIDTH 1 /* HPOUT1L_ZC */
848#define WM8993_HPOUT1L_MUTE_N 0x0040 /* HPOUT1L_MUTE_N */
849#define WM8993_HPOUT1L_MUTE_N_MASK 0x0040 /* HPOUT1L_MUTE_N */
850#define WM8993_HPOUT1L_MUTE_N_SHIFT 6 /* HPOUT1L_MUTE_N */
851#define WM8993_HPOUT1L_MUTE_N_WIDTH 1 /* HPOUT1L_MUTE_N */
852#define WM8993_HPOUT1L_VOL_MASK 0x003F /* HPOUT1L_VOL - [5:0] */
853#define WM8993_HPOUT1L_VOL_SHIFT 0 /* HPOUT1L_VOL - [5:0] */
854#define WM8993_HPOUT1L_VOL_WIDTH 6 /* HPOUT1L_VOL - [5:0] */
855
856/*
857 * R29 (0x1D) - Right Output Volume
858 */
859#define WM8993_HPOUT1_VU 0x0100 /* HPOUT1_VU */
860#define WM8993_HPOUT1_VU_MASK 0x0100 /* HPOUT1_VU */
861#define WM8993_HPOUT1_VU_SHIFT 8 /* HPOUT1_VU */
862#define WM8993_HPOUT1_VU_WIDTH 1 /* HPOUT1_VU */
863#define WM8993_HPOUT1R_ZC 0x0080 /* HPOUT1R_ZC */
864#define WM8993_HPOUT1R_ZC_MASK 0x0080 /* HPOUT1R_ZC */
865#define WM8993_HPOUT1R_ZC_SHIFT 7 /* HPOUT1R_ZC */
866#define WM8993_HPOUT1R_ZC_WIDTH 1 /* HPOUT1R_ZC */
867#define WM8993_HPOUT1R_MUTE_N 0x0040 /* HPOUT1R_MUTE_N */
868#define WM8993_HPOUT1R_MUTE_N_MASK 0x0040 /* HPOUT1R_MUTE_N */
869#define WM8993_HPOUT1R_MUTE_N_SHIFT 6 /* HPOUT1R_MUTE_N */
870#define WM8993_HPOUT1R_MUTE_N_WIDTH 1 /* HPOUT1R_MUTE_N */
871#define WM8993_HPOUT1R_VOL_MASK 0x003F /* HPOUT1R_VOL - [5:0] */
872#define WM8993_HPOUT1R_VOL_SHIFT 0 /* HPOUT1R_VOL - [5:0] */
873#define WM8993_HPOUT1R_VOL_WIDTH 6 /* HPOUT1R_VOL - [5:0] */
874
875/*
876 * R30 (0x1E) - Line Outputs Volume
877 */
878#define WM8993_LINEOUT1N_MUTE 0x0040 /* LINEOUT1N_MUTE */
879#define WM8993_LINEOUT1N_MUTE_MASK 0x0040 /* LINEOUT1N_MUTE */
880#define WM8993_LINEOUT1N_MUTE_SHIFT 6 /* LINEOUT1N_MUTE */
881#define WM8993_LINEOUT1N_MUTE_WIDTH 1 /* LINEOUT1N_MUTE */
882#define WM8993_LINEOUT1P_MUTE 0x0020 /* LINEOUT1P_MUTE */
883#define WM8993_LINEOUT1P_MUTE_MASK 0x0020 /* LINEOUT1P_MUTE */
884#define WM8993_LINEOUT1P_MUTE_SHIFT 5 /* LINEOUT1P_MUTE */
885#define WM8993_LINEOUT1P_MUTE_WIDTH 1 /* LINEOUT1P_MUTE */
886#define WM8993_LINEOUT1_VOL 0x0010 /* LINEOUT1_VOL */
887#define WM8993_LINEOUT1_VOL_MASK 0x0010 /* LINEOUT1_VOL */
888#define WM8993_LINEOUT1_VOL_SHIFT 4 /* LINEOUT1_VOL */
889#define WM8993_LINEOUT1_VOL_WIDTH 1 /* LINEOUT1_VOL */
890#define WM8993_LINEOUT2N_MUTE 0x0004 /* LINEOUT2N_MUTE */
891#define WM8993_LINEOUT2N_MUTE_MASK 0x0004 /* LINEOUT2N_MUTE */
892#define WM8993_LINEOUT2N_MUTE_SHIFT 2 /* LINEOUT2N_MUTE */
893#define WM8993_LINEOUT2N_MUTE_WIDTH 1 /* LINEOUT2N_MUTE */
894#define WM8993_LINEOUT2P_MUTE 0x0002 /* LINEOUT2P_MUTE */
895#define WM8993_LINEOUT2P_MUTE_MASK 0x0002 /* LINEOUT2P_MUTE */
896#define WM8993_LINEOUT2P_MUTE_SHIFT 1 /* LINEOUT2P_MUTE */
897#define WM8993_LINEOUT2P_MUTE_WIDTH 1 /* LINEOUT2P_MUTE */
898#define WM8993_LINEOUT2_VOL 0x0001 /* LINEOUT2_VOL */
899#define WM8993_LINEOUT2_VOL_MASK 0x0001 /* LINEOUT2_VOL */
900#define WM8993_LINEOUT2_VOL_SHIFT 0 /* LINEOUT2_VOL */
901#define WM8993_LINEOUT2_VOL_WIDTH 1 /* LINEOUT2_VOL */
902
903/*
904 * R31 (0x1F) - HPOUT2 Volume
905 */
906#define WM8993_HPOUT2_MUTE 0x0020 /* HPOUT2_MUTE */
907#define WM8993_HPOUT2_MUTE_MASK 0x0020 /* HPOUT2_MUTE */
908#define WM8993_HPOUT2_MUTE_SHIFT 5 /* HPOUT2_MUTE */
909#define WM8993_HPOUT2_MUTE_WIDTH 1 /* HPOUT2_MUTE */
910#define WM8993_HPOUT2_VOL 0x0010 /* HPOUT2_VOL */
911#define WM8993_HPOUT2_VOL_MASK 0x0010 /* HPOUT2_VOL */
912#define WM8993_HPOUT2_VOL_SHIFT 4 /* HPOUT2_VOL */
913#define WM8993_HPOUT2_VOL_WIDTH 1 /* HPOUT2_VOL */
914
915/*
916 * R32 (0x20) - Left OPGA Volume
917 */
918#define WM8993_MIXOUT_VU 0x0100 /* MIXOUT_VU */
919#define WM8993_MIXOUT_VU_MASK 0x0100 /* MIXOUT_VU */
920#define WM8993_MIXOUT_VU_SHIFT 8 /* MIXOUT_VU */
921#define WM8993_MIXOUT_VU_WIDTH 1 /* MIXOUT_VU */
922#define WM8993_MIXOUTL_ZC 0x0080 /* MIXOUTL_ZC */
923#define WM8993_MIXOUTL_ZC_MASK 0x0080 /* MIXOUTL_ZC */
924#define WM8993_MIXOUTL_ZC_SHIFT 7 /* MIXOUTL_ZC */
925#define WM8993_MIXOUTL_ZC_WIDTH 1 /* MIXOUTL_ZC */
926#define WM8993_MIXOUTL_MUTE_N 0x0040 /* MIXOUTL_MUTE_N */
927#define WM8993_MIXOUTL_MUTE_N_MASK 0x0040 /* MIXOUTL_MUTE_N */
928#define WM8993_MIXOUTL_MUTE_N_SHIFT 6 /* MIXOUTL_MUTE_N */
929#define WM8993_MIXOUTL_MUTE_N_WIDTH 1 /* MIXOUTL_MUTE_N */
930#define WM8993_MIXOUTL_VOL_MASK 0x003F /* MIXOUTL_VOL - [5:0] */
931#define WM8993_MIXOUTL_VOL_SHIFT 0 /* MIXOUTL_VOL - [5:0] */
932#define WM8993_MIXOUTL_VOL_WIDTH 6 /* MIXOUTL_VOL - [5:0] */
933
934/*
935 * R33 (0x21) - Right OPGA Volume
936 */
937#define WM8993_MIXOUT_VU 0x0100 /* MIXOUT_VU */
938#define WM8993_MIXOUT_VU_MASK 0x0100 /* MIXOUT_VU */
939#define WM8993_MIXOUT_VU_SHIFT 8 /* MIXOUT_VU */
940#define WM8993_MIXOUT_VU_WIDTH 1 /* MIXOUT_VU */
941#define WM8993_MIXOUTR_ZC 0x0080 /* MIXOUTR_ZC */
942#define WM8993_MIXOUTR_ZC_MASK 0x0080 /* MIXOUTR_ZC */
943#define WM8993_MIXOUTR_ZC_SHIFT 7 /* MIXOUTR_ZC */
944#define WM8993_MIXOUTR_ZC_WIDTH 1 /* MIXOUTR_ZC */
945#define WM8993_MIXOUTR_MUTE_N 0x0040 /* MIXOUTR_MUTE_N */
946#define WM8993_MIXOUTR_MUTE_N_MASK 0x0040 /* MIXOUTR_MUTE_N */
947#define WM8993_MIXOUTR_MUTE_N_SHIFT 6 /* MIXOUTR_MUTE_N */
948#define WM8993_MIXOUTR_MUTE_N_WIDTH 1 /* MIXOUTR_MUTE_N */
949#define WM8993_MIXOUTR_VOL_MASK 0x003F /* MIXOUTR_VOL - [5:0] */
950#define WM8993_MIXOUTR_VOL_SHIFT 0 /* MIXOUTR_VOL - [5:0] */
951#define WM8993_MIXOUTR_VOL_WIDTH 6 /* MIXOUTR_VOL - [5:0] */
952
953/*
954 * R34 (0x22) - SPKMIXL Attenuation
955 */
956#define WM8993_MIXINL_SPKMIXL_VOL 0x0020 /* MIXINL_SPKMIXL_VOL */
957#define WM8993_MIXINL_SPKMIXL_VOL_MASK 0x0020 /* MIXINL_SPKMIXL_VOL */
958#define WM8993_MIXINL_SPKMIXL_VOL_SHIFT 5 /* MIXINL_SPKMIXL_VOL */
959#define WM8993_MIXINL_SPKMIXL_VOL_WIDTH 1 /* MIXINL_SPKMIXL_VOL */
960#define WM8993_IN1LP_SPKMIXL_VOL 0x0010 /* IN1LP_SPKMIXL_VOL */
961#define WM8993_IN1LP_SPKMIXL_VOL_MASK 0x0010 /* IN1LP_SPKMIXL_VOL */
962#define WM8993_IN1LP_SPKMIXL_VOL_SHIFT 4 /* IN1LP_SPKMIXL_VOL */
963#define WM8993_IN1LP_SPKMIXL_VOL_WIDTH 1 /* IN1LP_SPKMIXL_VOL */
964#define WM8993_MIXOUTL_SPKMIXL_VOL 0x0008 /* MIXOUTL_SPKMIXL_VOL */
965#define WM8993_MIXOUTL_SPKMIXL_VOL_MASK 0x0008 /* MIXOUTL_SPKMIXL_VOL */
966#define WM8993_MIXOUTL_SPKMIXL_VOL_SHIFT 3 /* MIXOUTL_SPKMIXL_VOL */
967#define WM8993_MIXOUTL_SPKMIXL_VOL_WIDTH 1 /* MIXOUTL_SPKMIXL_VOL */
968#define WM8993_DACL_SPKMIXL_VOL 0x0004 /* DACL_SPKMIXL_VOL */
969#define WM8993_DACL_SPKMIXL_VOL_MASK 0x0004 /* DACL_SPKMIXL_VOL */
970#define WM8993_DACL_SPKMIXL_VOL_SHIFT 2 /* DACL_SPKMIXL_VOL */
971#define WM8993_DACL_SPKMIXL_VOL_WIDTH 1 /* DACL_SPKMIXL_VOL */
972#define WM8993_SPKMIXL_VOL_MASK 0x0003 /* SPKMIXL_VOL - [1:0] */
973#define WM8993_SPKMIXL_VOL_SHIFT 0 /* SPKMIXL_VOL - [1:0] */
974#define WM8993_SPKMIXL_VOL_WIDTH 2 /* SPKMIXL_VOL - [1:0] */
975
976/*
977 * R35 (0x23) - SPKMIXR Attenuation
978 */
979#define WM8993_SPKOUT_CLASSAB_MODE 0x0100 /* SPKOUT_CLASSAB_MODE */
980#define WM8993_SPKOUT_CLASSAB_MODE_MASK 0x0100 /* SPKOUT_CLASSAB_MODE */
981#define WM8993_SPKOUT_CLASSAB_MODE_SHIFT 8 /* SPKOUT_CLASSAB_MODE */
982#define WM8993_SPKOUT_CLASSAB_MODE_WIDTH 1 /* SPKOUT_CLASSAB_MODE */
983#define WM8993_MIXINR_SPKMIXR_VOL 0x0020 /* MIXINR_SPKMIXR_VOL */
984#define WM8993_MIXINR_SPKMIXR_VOL_MASK 0x0020 /* MIXINR_SPKMIXR_VOL */
985#define WM8993_MIXINR_SPKMIXR_VOL_SHIFT 5 /* MIXINR_SPKMIXR_VOL */
986#define WM8993_MIXINR_SPKMIXR_VOL_WIDTH 1 /* MIXINR_SPKMIXR_VOL */
987#define WM8993_IN1RP_SPKMIXR_VOL 0x0010 /* IN1RP_SPKMIXR_VOL */
988#define WM8993_IN1RP_SPKMIXR_VOL_MASK 0x0010 /* IN1RP_SPKMIXR_VOL */
989#define WM8993_IN1RP_SPKMIXR_VOL_SHIFT 4 /* IN1RP_SPKMIXR_VOL */
990#define WM8993_IN1RP_SPKMIXR_VOL_WIDTH 1 /* IN1RP_SPKMIXR_VOL */
991#define WM8993_MIXOUTR_SPKMIXR_VOL 0x0008 /* MIXOUTR_SPKMIXR_VOL */
992#define WM8993_MIXOUTR_SPKMIXR_VOL_MASK 0x0008 /* MIXOUTR_SPKMIXR_VOL */
993#define WM8993_MIXOUTR_SPKMIXR_VOL_SHIFT 3 /* MIXOUTR_SPKMIXR_VOL */
994#define WM8993_MIXOUTR_SPKMIXR_VOL_WIDTH 1 /* MIXOUTR_SPKMIXR_VOL */
995#define WM8993_DACR_SPKMIXR_VOL 0x0004 /* DACR_SPKMIXR_VOL */
996#define WM8993_DACR_SPKMIXR_VOL_MASK 0x0004 /* DACR_SPKMIXR_VOL */
997#define WM8993_DACR_SPKMIXR_VOL_SHIFT 2 /* DACR_SPKMIXR_VOL */
998#define WM8993_DACR_SPKMIXR_VOL_WIDTH 1 /* DACR_SPKMIXR_VOL */
999#define WM8993_SPKMIXR_VOL_MASK 0x0003 /* SPKMIXR_VOL - [1:0] */
1000#define WM8993_SPKMIXR_VOL_SHIFT 0 /* SPKMIXR_VOL - [1:0] */
1001#define WM8993_SPKMIXR_VOL_WIDTH 2 /* SPKMIXR_VOL - [1:0] */
1002
1003/*
1004 * R36 (0x24) - SPKOUT Mixers
1005 */
1006#define WM8993_VRX_TO_SPKOUTL 0x0020 /* VRX_TO_SPKOUTL */
1007#define WM8993_VRX_TO_SPKOUTL_MASK 0x0020 /* VRX_TO_SPKOUTL */
1008#define WM8993_VRX_TO_SPKOUTL_SHIFT 5 /* VRX_TO_SPKOUTL */
1009#define WM8993_VRX_TO_SPKOUTL_WIDTH 1 /* VRX_TO_SPKOUTL */
1010#define WM8993_SPKMIXL_TO_SPKOUTL 0x0010 /* SPKMIXL_TO_SPKOUTL */
1011#define WM8993_SPKMIXL_TO_SPKOUTL_MASK 0x0010 /* SPKMIXL_TO_SPKOUTL */
1012#define WM8993_SPKMIXL_TO_SPKOUTL_SHIFT 4 /* SPKMIXL_TO_SPKOUTL */
1013#define WM8993_SPKMIXL_TO_SPKOUTL_WIDTH 1 /* SPKMIXL_TO_SPKOUTL */
1014#define WM8993_SPKMIXR_TO_SPKOUTL 0x0008 /* SPKMIXR_TO_SPKOUTL */
1015#define WM8993_SPKMIXR_TO_SPKOUTL_MASK 0x0008 /* SPKMIXR_TO_SPKOUTL */
1016#define WM8993_SPKMIXR_TO_SPKOUTL_SHIFT 3 /* SPKMIXR_TO_SPKOUTL */
1017#define WM8993_SPKMIXR_TO_SPKOUTL_WIDTH 1 /* SPKMIXR_TO_SPKOUTL */
1018#define WM8993_VRX_TO_SPKOUTR 0x0004 /* VRX_TO_SPKOUTR */
1019#define WM8993_VRX_TO_SPKOUTR_MASK 0x0004 /* VRX_TO_SPKOUTR */
1020#define WM8993_VRX_TO_SPKOUTR_SHIFT 2 /* VRX_TO_SPKOUTR */
1021#define WM8993_VRX_TO_SPKOUTR_WIDTH 1 /* VRX_TO_SPKOUTR */
1022#define WM8993_SPKMIXL_TO_SPKOUTR 0x0002 /* SPKMIXL_TO_SPKOUTR */
1023#define WM8993_SPKMIXL_TO_SPKOUTR_MASK 0x0002 /* SPKMIXL_TO_SPKOUTR */
1024#define WM8993_SPKMIXL_TO_SPKOUTR_SHIFT 1 /* SPKMIXL_TO_SPKOUTR */
1025#define WM8993_SPKMIXL_TO_SPKOUTR_WIDTH 1 /* SPKMIXL_TO_SPKOUTR */
1026#define WM8993_SPKMIXR_TO_SPKOUTR 0x0001 /* SPKMIXR_TO_SPKOUTR */
1027#define WM8993_SPKMIXR_TO_SPKOUTR_MASK 0x0001 /* SPKMIXR_TO_SPKOUTR */
1028#define WM8993_SPKMIXR_TO_SPKOUTR_SHIFT 0 /* SPKMIXR_TO_SPKOUTR */
1029#define WM8993_SPKMIXR_TO_SPKOUTR_WIDTH 1 /* SPKMIXR_TO_SPKOUTR */
1030
1031/*
1032 * R37 (0x25) - SPKOUT Boost
1033 */
1034#define WM8993_SPKOUTL_BOOST_MASK 0x0038 /* SPKOUTL_BOOST - [5:3] */
1035#define WM8993_SPKOUTL_BOOST_SHIFT 3 /* SPKOUTL_BOOST - [5:3] */
1036#define WM8993_SPKOUTL_BOOST_WIDTH 3 /* SPKOUTL_BOOST - [5:3] */
1037#define WM8993_SPKOUTR_BOOST_MASK 0x0007 /* SPKOUTR_BOOST - [2:0] */
1038#define WM8993_SPKOUTR_BOOST_SHIFT 0 /* SPKOUTR_BOOST - [2:0] */
1039#define WM8993_SPKOUTR_BOOST_WIDTH 3 /* SPKOUTR_BOOST - [2:0] */
1040
1041/*
1042 * R38 (0x26) - Speaker Volume Left
1043 */
1044#define WM8993_SPKOUT_VU 0x0100 /* SPKOUT_VU */
1045#define WM8993_SPKOUT_VU_MASK 0x0100 /* SPKOUT_VU */
1046#define WM8993_SPKOUT_VU_SHIFT 8 /* SPKOUT_VU */
1047#define WM8993_SPKOUT_VU_WIDTH 1 /* SPKOUT_VU */
1048#define WM8993_SPKOUTL_ZC 0x0080 /* SPKOUTL_ZC */
1049#define WM8993_SPKOUTL_ZC_MASK 0x0080 /* SPKOUTL_ZC */
1050#define WM8993_SPKOUTL_ZC_SHIFT 7 /* SPKOUTL_ZC */
1051#define WM8993_SPKOUTL_ZC_WIDTH 1 /* SPKOUTL_ZC */
1052#define WM8993_SPKOUTL_MUTE_N 0x0040 /* SPKOUTL_MUTE_N */
1053#define WM8993_SPKOUTL_MUTE_N_MASK 0x0040 /* SPKOUTL_MUTE_N */
1054#define WM8993_SPKOUTL_MUTE_N_SHIFT 6 /* SPKOUTL_MUTE_N */
1055#define WM8993_SPKOUTL_MUTE_N_WIDTH 1 /* SPKOUTL_MUTE_N */
1056#define WM8993_SPKOUTL_VOL_MASK 0x003F /* SPKOUTL_VOL - [5:0] */
1057#define WM8993_SPKOUTL_VOL_SHIFT 0 /* SPKOUTL_VOL - [5:0] */
1058#define WM8993_SPKOUTL_VOL_WIDTH 6 /* SPKOUTL_VOL - [5:0] */
1059
1060/*
1061 * R39 (0x27) - Speaker Volume Right
1062 */
1063#define WM8993_SPKOUT_VU 0x0100 /* SPKOUT_VU */
1064#define WM8993_SPKOUT_VU_MASK 0x0100 /* SPKOUT_VU */
1065#define WM8993_SPKOUT_VU_SHIFT 8 /* SPKOUT_VU */
1066#define WM8993_SPKOUT_VU_WIDTH 1 /* SPKOUT_VU */
1067#define WM8993_SPKOUTR_ZC 0x0080 /* SPKOUTR_ZC */
1068#define WM8993_SPKOUTR_ZC_MASK 0x0080 /* SPKOUTR_ZC */
1069#define WM8993_SPKOUTR_ZC_SHIFT 7 /* SPKOUTR_ZC */
1070#define WM8993_SPKOUTR_ZC_WIDTH 1 /* SPKOUTR_ZC */
1071#define WM8993_SPKOUTR_MUTE_N 0x0040 /* SPKOUTR_MUTE_N */
1072#define WM8993_SPKOUTR_MUTE_N_MASK 0x0040 /* SPKOUTR_MUTE_N */
1073#define WM8993_SPKOUTR_MUTE_N_SHIFT 6 /* SPKOUTR_MUTE_N */
1074#define WM8993_SPKOUTR_MUTE_N_WIDTH 1 /* SPKOUTR_MUTE_N */
1075#define WM8993_SPKOUTR_VOL_MASK 0x003F /* SPKOUTR_VOL - [5:0] */
1076#define WM8993_SPKOUTR_VOL_SHIFT 0 /* SPKOUTR_VOL - [5:0] */
1077#define WM8993_SPKOUTR_VOL_WIDTH 6 /* SPKOUTR_VOL - [5:0] */
1078
1079/*
1080 * R40 (0x28) - Input Mixer2
1081 */
1082#define WM8993_IN2LP_TO_IN2L 0x0080 /* IN2LP_TO_IN2L */
1083#define WM8993_IN2LP_TO_IN2L_MASK 0x0080 /* IN2LP_TO_IN2L */
1084#define WM8993_IN2LP_TO_IN2L_SHIFT 7 /* IN2LP_TO_IN2L */
1085#define WM8993_IN2LP_TO_IN2L_WIDTH 1 /* IN2LP_TO_IN2L */
1086#define WM8993_IN2LN_TO_IN2L 0x0040 /* IN2LN_TO_IN2L */
1087#define WM8993_IN2LN_TO_IN2L_MASK 0x0040 /* IN2LN_TO_IN2L */
1088#define WM8993_IN2LN_TO_IN2L_SHIFT 6 /* IN2LN_TO_IN2L */
1089#define WM8993_IN2LN_TO_IN2L_WIDTH 1 /* IN2LN_TO_IN2L */
1090#define WM8993_IN1LP_TO_IN1L 0x0020 /* IN1LP_TO_IN1L */
1091#define WM8993_IN1LP_TO_IN1L_MASK 0x0020 /* IN1LP_TO_IN1L */
1092#define WM8993_IN1LP_TO_IN1L_SHIFT 5 /* IN1LP_TO_IN1L */
1093#define WM8993_IN1LP_TO_IN1L_WIDTH 1 /* IN1LP_TO_IN1L */
1094#define WM8993_IN1LN_TO_IN1L 0x0010 /* IN1LN_TO_IN1L */
1095#define WM8993_IN1LN_TO_IN1L_MASK 0x0010 /* IN1LN_TO_IN1L */
1096#define WM8993_IN1LN_TO_IN1L_SHIFT 4 /* IN1LN_TO_IN1L */
1097#define WM8993_IN1LN_TO_IN1L_WIDTH 1 /* IN1LN_TO_IN1L */
1098#define WM8993_IN2RP_TO_IN2R 0x0008 /* IN2RP_TO_IN2R */
1099#define WM8993_IN2RP_TO_IN2R_MASK 0x0008 /* IN2RP_TO_IN2R */
1100#define WM8993_IN2RP_TO_IN2R_SHIFT 3 /* IN2RP_TO_IN2R */
1101#define WM8993_IN2RP_TO_IN2R_WIDTH 1 /* IN2RP_TO_IN2R */
1102#define WM8993_IN2RN_TO_IN2R 0x0004 /* IN2RN_TO_IN2R */
1103#define WM8993_IN2RN_TO_IN2R_MASK 0x0004 /* IN2RN_TO_IN2R */
1104#define WM8993_IN2RN_TO_IN2R_SHIFT 2 /* IN2RN_TO_IN2R */
1105#define WM8993_IN2RN_TO_IN2R_WIDTH 1 /* IN2RN_TO_IN2R */
1106#define WM8993_IN1RP_TO_IN1R 0x0002 /* IN1RP_TO_IN1R */
1107#define WM8993_IN1RP_TO_IN1R_MASK 0x0002 /* IN1RP_TO_IN1R */
1108#define WM8993_IN1RP_TO_IN1R_SHIFT 1 /* IN1RP_TO_IN1R */
1109#define WM8993_IN1RP_TO_IN1R_WIDTH 1 /* IN1RP_TO_IN1R */
1110#define WM8993_IN1RN_TO_IN1R 0x0001 /* IN1RN_TO_IN1R */
1111#define WM8993_IN1RN_TO_IN1R_MASK 0x0001 /* IN1RN_TO_IN1R */
1112#define WM8993_IN1RN_TO_IN1R_SHIFT 0 /* IN1RN_TO_IN1R */
1113#define WM8993_IN1RN_TO_IN1R_WIDTH 1 /* IN1RN_TO_IN1R */
1114
1115/*
1116 * R41 (0x29) - Input Mixer3
1117 */
1118#define WM8993_IN2L_TO_MIXINL 0x0100 /* IN2L_TO_MIXINL */
1119#define WM8993_IN2L_TO_MIXINL_MASK 0x0100 /* IN2L_TO_MIXINL */
1120#define WM8993_IN2L_TO_MIXINL_SHIFT 8 /* IN2L_TO_MIXINL */
1121#define WM8993_IN2L_TO_MIXINL_WIDTH 1 /* IN2L_TO_MIXINL */
1122#define WM8993_IN2L_MIXINL_VOL 0x0080 /* IN2L_MIXINL_VOL */
1123#define WM8993_IN2L_MIXINL_VOL_MASK 0x0080 /* IN2L_MIXINL_VOL */
1124#define WM8993_IN2L_MIXINL_VOL_SHIFT 7 /* IN2L_MIXINL_VOL */
1125#define WM8993_IN2L_MIXINL_VOL_WIDTH 1 /* IN2L_MIXINL_VOL */
1126#define WM8993_IN1L_TO_MIXINL 0x0020 /* IN1L_TO_MIXINL */
1127#define WM8993_IN1L_TO_MIXINL_MASK 0x0020 /* IN1L_TO_MIXINL */
1128#define WM8993_IN1L_TO_MIXINL_SHIFT 5 /* IN1L_TO_MIXINL */
1129#define WM8993_IN1L_TO_MIXINL_WIDTH 1 /* IN1L_TO_MIXINL */
1130#define WM8993_IN1L_MIXINL_VOL 0x0010 /* IN1L_MIXINL_VOL */
1131#define WM8993_IN1L_MIXINL_VOL_MASK 0x0010 /* IN1L_MIXINL_VOL */
1132#define WM8993_IN1L_MIXINL_VOL_SHIFT 4 /* IN1L_MIXINL_VOL */
1133#define WM8993_IN1L_MIXINL_VOL_WIDTH 1 /* IN1L_MIXINL_VOL */
1134#define WM8993_MIXOUTL_MIXINL_VOL_MASK 0x0007 /* MIXOUTL_MIXINL_VOL - [2:0] */
1135#define WM8993_MIXOUTL_MIXINL_VOL_SHIFT 0 /* MIXOUTL_MIXINL_VOL - [2:0] */
1136#define WM8993_MIXOUTL_MIXINL_VOL_WIDTH 3 /* MIXOUTL_MIXINL_VOL - [2:0] */
1137
1138/*
1139 * R42 (0x2A) - Input Mixer4
1140 */
1141#define WM8993_IN2R_TO_MIXINR 0x0100 /* IN2R_TO_MIXINR */
1142#define WM8993_IN2R_TO_MIXINR_MASK 0x0100 /* IN2R_TO_MIXINR */
1143#define WM8993_IN2R_TO_MIXINR_SHIFT 8 /* IN2R_TO_MIXINR */
1144#define WM8993_IN2R_TO_MIXINR_WIDTH 1 /* IN2R_TO_MIXINR */
1145#define WM8993_IN2R_MIXINR_VOL 0x0080 /* IN2R_MIXINR_VOL */
1146#define WM8993_IN2R_MIXINR_VOL_MASK 0x0080 /* IN2R_MIXINR_VOL */
1147#define WM8993_IN2R_MIXINR_VOL_SHIFT 7 /* IN2R_MIXINR_VOL */
1148#define WM8993_IN2R_MIXINR_VOL_WIDTH 1 /* IN2R_MIXINR_VOL */
1149#define WM8993_IN1R_TO_MIXINR 0x0020 /* IN1R_TO_MIXINR */
1150#define WM8993_IN1R_TO_MIXINR_MASK 0x0020 /* IN1R_TO_MIXINR */
1151#define WM8993_IN1R_TO_MIXINR_SHIFT 5 /* IN1R_TO_MIXINR */
1152#define WM8993_IN1R_TO_MIXINR_WIDTH 1 /* IN1R_TO_MIXINR */
1153#define WM8993_IN1R_MIXINR_VOL 0x0010 /* IN1R_MIXINR_VOL */
1154#define WM8993_IN1R_MIXINR_VOL_MASK 0x0010 /* IN1R_MIXINR_VOL */
1155#define WM8993_IN1R_MIXINR_VOL_SHIFT 4 /* IN1R_MIXINR_VOL */
1156#define WM8993_IN1R_MIXINR_VOL_WIDTH 1 /* IN1R_MIXINR_VOL */
1157#define WM8993_MIXOUTR_MIXINR_VOL_MASK 0x0007 /* MIXOUTR_MIXINR_VOL - [2:0] */
1158#define WM8993_MIXOUTR_MIXINR_VOL_SHIFT 0 /* MIXOUTR_MIXINR_VOL - [2:0] */
1159#define WM8993_MIXOUTR_MIXINR_VOL_WIDTH 3 /* MIXOUTR_MIXINR_VOL - [2:0] */
1160
1161/*
1162 * R43 (0x2B) - Input Mixer5
1163 */
1164#define WM8993_IN1LP_MIXINL_VOL_MASK 0x01C0 /* IN1LP_MIXINL_VOL - [8:6] */
1165#define WM8993_IN1LP_MIXINL_VOL_SHIFT 6 /* IN1LP_MIXINL_VOL - [8:6] */
1166#define WM8993_IN1LP_MIXINL_VOL_WIDTH 3 /* IN1LP_MIXINL_VOL - [8:6] */
1167#define WM8993_VRX_MIXINL_VOL_MASK 0x0007 /* VRX_MIXINL_VOL - [2:0] */
1168#define WM8993_VRX_MIXINL_VOL_SHIFT 0 /* VRX_MIXINL_VOL - [2:0] */
1169#define WM8993_VRX_MIXINL_VOL_WIDTH 3 /* VRX_MIXINL_VOL - [2:0] */
1170
1171/*
1172 * R44 (0x2C) - Input Mixer6
1173 */
1174#define WM8993_IN1RP_MIXINR_VOL_MASK 0x01C0 /* IN1RP_MIXINR_VOL - [8:6] */
1175#define WM8993_IN1RP_MIXINR_VOL_SHIFT 6 /* IN1RP_MIXINR_VOL - [8:6] */
1176#define WM8993_IN1RP_MIXINR_VOL_WIDTH 3 /* IN1RP_MIXINR_VOL - [8:6] */
1177#define WM8993_VRX_MIXINR_VOL_MASK 0x0007 /* VRX_MIXINR_VOL - [2:0] */
1178#define WM8993_VRX_MIXINR_VOL_SHIFT 0 /* VRX_MIXINR_VOL - [2:0] */
1179#define WM8993_VRX_MIXINR_VOL_WIDTH 3 /* VRX_MIXINR_VOL - [2:0] */
1180
1181/*
1182 * R45 (0x2D) - Output Mixer1
1183 */
1184#define WM8993_DACL_TO_HPOUT1L 0x0100 /* DACL_TO_HPOUT1L */
1185#define WM8993_DACL_TO_HPOUT1L_MASK 0x0100 /* DACL_TO_HPOUT1L */
1186#define WM8993_DACL_TO_HPOUT1L_SHIFT 8 /* DACL_TO_HPOUT1L */
1187#define WM8993_DACL_TO_HPOUT1L_WIDTH 1 /* DACL_TO_HPOUT1L */
1188#define WM8993_MIXINR_TO_MIXOUTL 0x0080 /* MIXINR_TO_MIXOUTL */
1189#define WM8993_MIXINR_TO_MIXOUTL_MASK 0x0080 /* MIXINR_TO_MIXOUTL */
1190#define WM8993_MIXINR_TO_MIXOUTL_SHIFT 7 /* MIXINR_TO_MIXOUTL */
1191#define WM8993_MIXINR_TO_MIXOUTL_WIDTH 1 /* MIXINR_TO_MIXOUTL */
1192#define WM8993_MIXINL_TO_MIXOUTL 0x0040 /* MIXINL_TO_MIXOUTL */
1193#define WM8993_MIXINL_TO_MIXOUTL_MASK 0x0040 /* MIXINL_TO_MIXOUTL */
1194#define WM8993_MIXINL_TO_MIXOUTL_SHIFT 6 /* MIXINL_TO_MIXOUTL */
1195#define WM8993_MIXINL_TO_MIXOUTL_WIDTH 1 /* MIXINL_TO_MIXOUTL */
1196#define WM8993_IN2RN_TO_MIXOUTL 0x0020 /* IN2RN_TO_MIXOUTL */
1197#define WM8993_IN2RN_TO_MIXOUTL_MASK 0x0020 /* IN2RN_TO_MIXOUTL */
1198#define WM8993_IN2RN_TO_MIXOUTL_SHIFT 5 /* IN2RN_TO_MIXOUTL */
1199#define WM8993_IN2RN_TO_MIXOUTL_WIDTH 1 /* IN2RN_TO_MIXOUTL */
1200#define WM8993_IN2LN_TO_MIXOUTL 0x0010 /* IN2LN_TO_MIXOUTL */
1201#define WM8993_IN2LN_TO_MIXOUTL_MASK 0x0010 /* IN2LN_TO_MIXOUTL */
1202#define WM8993_IN2LN_TO_MIXOUTL_SHIFT 4 /* IN2LN_TO_MIXOUTL */
1203#define WM8993_IN2LN_TO_MIXOUTL_WIDTH 1 /* IN2LN_TO_MIXOUTL */
1204#define WM8993_IN1R_TO_MIXOUTL 0x0008 /* IN1R_TO_MIXOUTL */
1205#define WM8993_IN1R_TO_MIXOUTL_MASK 0x0008 /* IN1R_TO_MIXOUTL */
1206#define WM8993_IN1R_TO_MIXOUTL_SHIFT 3 /* IN1R_TO_MIXOUTL */
1207#define WM8993_IN1R_TO_MIXOUTL_WIDTH 1 /* IN1R_TO_MIXOUTL */
1208#define WM8993_IN1L_TO_MIXOUTL 0x0004 /* IN1L_TO_MIXOUTL */
1209#define WM8993_IN1L_TO_MIXOUTL_MASK 0x0004 /* IN1L_TO_MIXOUTL */
1210#define WM8993_IN1L_TO_MIXOUTL_SHIFT 2 /* IN1L_TO_MIXOUTL */
1211#define WM8993_IN1L_TO_MIXOUTL_WIDTH 1 /* IN1L_TO_MIXOUTL */
1212#define WM8993_IN2LP_TO_MIXOUTL 0x0002 /* IN2LP_TO_MIXOUTL */
1213#define WM8993_IN2LP_TO_MIXOUTL_MASK 0x0002 /* IN2LP_TO_MIXOUTL */
1214#define WM8993_IN2LP_TO_MIXOUTL_SHIFT 1 /* IN2LP_TO_MIXOUTL */
1215#define WM8993_IN2LP_TO_MIXOUTL_WIDTH 1 /* IN2LP_TO_MIXOUTL */
1216#define WM8993_DACL_TO_MIXOUTL 0x0001 /* DACL_TO_MIXOUTL */
1217#define WM8993_DACL_TO_MIXOUTL_MASK 0x0001 /* DACL_TO_MIXOUTL */
1218#define WM8993_DACL_TO_MIXOUTL_SHIFT 0 /* DACL_TO_MIXOUTL */
1219#define WM8993_DACL_TO_MIXOUTL_WIDTH 1 /* DACL_TO_MIXOUTL */
1220
1221/*
1222 * R46 (0x2E) - Output Mixer2
1223 */
1224#define WM8993_DACR_TO_HPOUT1R 0x0100 /* DACR_TO_HPOUT1R */
1225#define WM8993_DACR_TO_HPOUT1R_MASK 0x0100 /* DACR_TO_HPOUT1R */
1226#define WM8993_DACR_TO_HPOUT1R_SHIFT 8 /* DACR_TO_HPOUT1R */
1227#define WM8993_DACR_TO_HPOUT1R_WIDTH 1 /* DACR_TO_HPOUT1R */
1228#define WM8993_MIXINL_TO_MIXOUTR 0x0080 /* MIXINL_TO_MIXOUTR */
1229#define WM8993_MIXINL_TO_MIXOUTR_MASK 0x0080 /* MIXINL_TO_MIXOUTR */
1230#define WM8993_MIXINL_TO_MIXOUTR_SHIFT 7 /* MIXINL_TO_MIXOUTR */
1231#define WM8993_MIXINL_TO_MIXOUTR_WIDTH 1 /* MIXINL_TO_MIXOUTR */
1232#define WM8993_MIXINR_TO_MIXOUTR 0x0040 /* MIXINR_TO_MIXOUTR */
1233#define WM8993_MIXINR_TO_MIXOUTR_MASK 0x0040 /* MIXINR_TO_MIXOUTR */
1234#define WM8993_MIXINR_TO_MIXOUTR_SHIFT 6 /* MIXINR_TO_MIXOUTR */
1235#define WM8993_MIXINR_TO_MIXOUTR_WIDTH 1 /* MIXINR_TO_MIXOUTR */
1236#define WM8993_IN2LN_TO_MIXOUTR 0x0020 /* IN2LN_TO_MIXOUTR */
1237#define WM8993_IN2LN_TO_MIXOUTR_MASK 0x0020 /* IN2LN_TO_MIXOUTR */
1238#define WM8993_IN2LN_TO_MIXOUTR_SHIFT 5 /* IN2LN_TO_MIXOUTR */
1239#define WM8993_IN2LN_TO_MIXOUTR_WIDTH 1 /* IN2LN_TO_MIXOUTR */
1240#define WM8993_IN2RN_TO_MIXOUTR 0x0010 /* IN2RN_TO_MIXOUTR */
1241#define WM8993_IN2RN_TO_MIXOUTR_MASK 0x0010 /* IN2RN_TO_MIXOUTR */
1242#define WM8993_IN2RN_TO_MIXOUTR_SHIFT 4 /* IN2RN_TO_MIXOUTR */
1243#define WM8993_IN2RN_TO_MIXOUTR_WIDTH 1 /* IN2RN_TO_MIXOUTR */
1244#define WM8993_IN1L_TO_MIXOUTR 0x0008 /* IN1L_TO_MIXOUTR */
1245#define WM8993_IN1L_TO_MIXOUTR_MASK 0x0008 /* IN1L_TO_MIXOUTR */
1246#define WM8993_IN1L_TO_MIXOUTR_SHIFT 3 /* IN1L_TO_MIXOUTR */
1247#define WM8993_IN1L_TO_MIXOUTR_WIDTH 1 /* IN1L_TO_MIXOUTR */
1248#define WM8993_IN1R_TO_MIXOUTR 0x0004 /* IN1R_TO_MIXOUTR */
1249#define WM8993_IN1R_TO_MIXOUTR_MASK 0x0004 /* IN1R_TO_MIXOUTR */
1250#define WM8993_IN1R_TO_MIXOUTR_SHIFT 2 /* IN1R_TO_MIXOUTR */
1251#define WM8993_IN1R_TO_MIXOUTR_WIDTH 1 /* IN1R_TO_MIXOUTR */
1252#define WM8993_IN2RP_TO_MIXOUTR 0x0002 /* IN2RP_TO_MIXOUTR */
1253#define WM8993_IN2RP_TO_MIXOUTR_MASK 0x0002 /* IN2RP_TO_MIXOUTR */
1254#define WM8993_IN2RP_TO_MIXOUTR_SHIFT 1 /* IN2RP_TO_MIXOUTR */
1255#define WM8993_IN2RP_TO_MIXOUTR_WIDTH 1 /* IN2RP_TO_MIXOUTR */
1256#define WM8993_DACR_TO_MIXOUTR 0x0001 /* DACR_TO_MIXOUTR */
1257#define WM8993_DACR_TO_MIXOUTR_MASK 0x0001 /* DACR_TO_MIXOUTR */
1258#define WM8993_DACR_TO_MIXOUTR_SHIFT 0 /* DACR_TO_MIXOUTR */
1259#define WM8993_DACR_TO_MIXOUTR_WIDTH 1 /* DACR_TO_MIXOUTR */
1260
1261/*
1262 * R47 (0x2F) - Output Mixer3
1263 */
1264#define WM8993_IN2LP_MIXOUTL_VOL_MASK 0x0E00 /* IN2LP_MIXOUTL_VOL - [11:9] */
1265#define WM8993_IN2LP_MIXOUTL_VOL_SHIFT 9 /* IN2LP_MIXOUTL_VOL - [11:9] */
1266#define WM8993_IN2LP_MIXOUTL_VOL_WIDTH 3 /* IN2LP_MIXOUTL_VOL - [11:9] */
1267#define WM8993_IN2LN_MIXOUTL_VOL_MASK 0x01C0 /* IN2LN_MIXOUTL_VOL - [8:6] */
1268#define WM8993_IN2LN_MIXOUTL_VOL_SHIFT 6 /* IN2LN_MIXOUTL_VOL - [8:6] */
1269#define WM8993_IN2LN_MIXOUTL_VOL_WIDTH 3 /* IN2LN_MIXOUTL_VOL - [8:6] */
1270#define WM8993_IN1R_MIXOUTL_VOL_MASK 0x0038 /* IN1R_MIXOUTL_VOL - [5:3] */
1271#define WM8993_IN1R_MIXOUTL_VOL_SHIFT 3 /* IN1R_MIXOUTL_VOL - [5:3] */
1272#define WM8993_IN1R_MIXOUTL_VOL_WIDTH 3 /* IN1R_MIXOUTL_VOL - [5:3] */
1273#define WM8993_IN1L_MIXOUTL_VOL_MASK 0x0007 /* IN1L_MIXOUTL_VOL - [2:0] */
1274#define WM8993_IN1L_MIXOUTL_VOL_SHIFT 0 /* IN1L_MIXOUTL_VOL - [2:0] */
1275#define WM8993_IN1L_MIXOUTL_VOL_WIDTH 3 /* IN1L_MIXOUTL_VOL - [2:0] */
1276
1277/*
1278 * R48 (0x30) - Output Mixer4
1279 */
1280#define WM8993_IN2RP_MIXOUTR_VOL_MASK 0x0E00 /* IN2RP_MIXOUTR_VOL - [11:9] */
1281#define WM8993_IN2RP_MIXOUTR_VOL_SHIFT 9 /* IN2RP_MIXOUTR_VOL - [11:9] */
1282#define WM8993_IN2RP_MIXOUTR_VOL_WIDTH 3 /* IN2RP_MIXOUTR_VOL - [11:9] */
1283#define WM8993_IN2RN_MIXOUTR_VOL_MASK 0x01C0 /* IN2RN_MIXOUTR_VOL - [8:6] */
1284#define WM8993_IN2RN_MIXOUTR_VOL_SHIFT 6 /* IN2RN_MIXOUTR_VOL - [8:6] */
1285#define WM8993_IN2RN_MIXOUTR_VOL_WIDTH 3 /* IN2RN_MIXOUTR_VOL - [8:6] */
1286#define WM8993_IN1L_MIXOUTR_VOL_MASK 0x0038 /* IN1L_MIXOUTR_VOL - [5:3] */
1287#define WM8993_IN1L_MIXOUTR_VOL_SHIFT 3 /* IN1L_MIXOUTR_VOL - [5:3] */
1288#define WM8993_IN1L_MIXOUTR_VOL_WIDTH 3 /* IN1L_MIXOUTR_VOL - [5:3] */
1289#define WM8993_IN1R_MIXOUTR_VOL_MASK 0x0007 /* IN1R_MIXOUTR_VOL - [2:0] */
1290#define WM8993_IN1R_MIXOUTR_VOL_SHIFT 0 /* IN1R_MIXOUTR_VOL - [2:0] */
1291#define WM8993_IN1R_MIXOUTR_VOL_WIDTH 3 /* IN1R_MIXOUTR_VOL - [2:0] */
1292
1293/*
1294 * R49 (0x31) - Output Mixer5
1295 */
1296#define WM8993_DACL_MIXOUTL_VOL_MASK 0x0E00 /* DACL_MIXOUTL_VOL - [11:9] */
1297#define WM8993_DACL_MIXOUTL_VOL_SHIFT 9 /* DACL_MIXOUTL_VOL - [11:9] */
1298#define WM8993_DACL_MIXOUTL_VOL_WIDTH 3 /* DACL_MIXOUTL_VOL - [11:9] */
1299#define WM8993_IN2RN_MIXOUTL_VOL_MASK 0x01C0 /* IN2RN_MIXOUTL_VOL - [8:6] */
1300#define WM8993_IN2RN_MIXOUTL_VOL_SHIFT 6 /* IN2RN_MIXOUTL_VOL - [8:6] */
1301#define WM8993_IN2RN_MIXOUTL_VOL_WIDTH 3 /* IN2RN_MIXOUTL_VOL - [8:6] */
1302#define WM8993_MIXINR_MIXOUTL_VOL_MASK 0x0038 /* MIXINR_MIXOUTL_VOL - [5:3] */
1303#define WM8993_MIXINR_MIXOUTL_VOL_SHIFT 3 /* MIXINR_MIXOUTL_VOL - [5:3] */
1304#define WM8993_MIXINR_MIXOUTL_VOL_WIDTH 3 /* MIXINR_MIXOUTL_VOL - [5:3] */
1305#define WM8993_MIXINL_MIXOUTL_VOL_MASK 0x0007 /* MIXINL_MIXOUTL_VOL - [2:0] */
1306#define WM8993_MIXINL_MIXOUTL_VOL_SHIFT 0 /* MIXINL_MIXOUTL_VOL - [2:0] */
1307#define WM8993_MIXINL_MIXOUTL_VOL_WIDTH 3 /* MIXINL_MIXOUTL_VOL - [2:0] */
1308
1309/*
1310 * R50 (0x32) - Output Mixer6
1311 */
1312#define WM8993_DACR_MIXOUTR_VOL_MASK 0x0E00 /* DACR_MIXOUTR_VOL - [11:9] */
1313#define WM8993_DACR_MIXOUTR_VOL_SHIFT 9 /* DACR_MIXOUTR_VOL - [11:9] */
1314#define WM8993_DACR_MIXOUTR_VOL_WIDTH 3 /* DACR_MIXOUTR_VOL - [11:9] */
1315#define WM8993_IN2LN_MIXOUTR_VOL_MASK 0x01C0 /* IN2LN_MIXOUTR_VOL - [8:6] */
1316#define WM8993_IN2LN_MIXOUTR_VOL_SHIFT 6 /* IN2LN_MIXOUTR_VOL - [8:6] */
1317#define WM8993_IN2LN_MIXOUTR_VOL_WIDTH 3 /* IN2LN_MIXOUTR_VOL - [8:6] */
1318#define WM8993_MIXINL_MIXOUTR_VOL_MASK 0x0038 /* MIXINL_MIXOUTR_VOL - [5:3] */
1319#define WM8993_MIXINL_MIXOUTR_VOL_SHIFT 3 /* MIXINL_MIXOUTR_VOL - [5:3] */
1320#define WM8993_MIXINL_MIXOUTR_VOL_WIDTH 3 /* MIXINL_MIXOUTR_VOL - [5:3] */
1321#define WM8993_MIXINR_MIXOUTR_VOL_MASK 0x0007 /* MIXINR_MIXOUTR_VOL - [2:0] */
1322#define WM8993_MIXINR_MIXOUTR_VOL_SHIFT 0 /* MIXINR_MIXOUTR_VOL - [2:0] */
1323#define WM8993_MIXINR_MIXOUTR_VOL_WIDTH 3 /* MIXINR_MIXOUTR_VOL - [2:0] */
1324
1325/*
1326 * R51 (0x33) - HPOUT2 Mixer
1327 */
1328#define WM8993_VRX_TO_HPOUT2 0x0020 /* VRX_TO_HPOUT2 */
1329#define WM8993_VRX_TO_HPOUT2_MASK 0x0020 /* VRX_TO_HPOUT2 */
1330#define WM8993_VRX_TO_HPOUT2_SHIFT 5 /* VRX_TO_HPOUT2 */
1331#define WM8993_VRX_TO_HPOUT2_WIDTH 1 /* VRX_TO_HPOUT2 */
1332#define WM8993_MIXOUTLVOL_TO_HPOUT2 0x0010 /* MIXOUTLVOL_TO_HPOUT2 */
1333#define WM8993_MIXOUTLVOL_TO_HPOUT2_MASK 0x0010 /* MIXOUTLVOL_TO_HPOUT2 */
1334#define WM8993_MIXOUTLVOL_TO_HPOUT2_SHIFT 4 /* MIXOUTLVOL_TO_HPOUT2 */
1335#define WM8993_MIXOUTLVOL_TO_HPOUT2_WIDTH 1 /* MIXOUTLVOL_TO_HPOUT2 */
1336#define WM8993_MIXOUTRVOL_TO_HPOUT2 0x0008 /* MIXOUTRVOL_TO_HPOUT2 */
1337#define WM8993_MIXOUTRVOL_TO_HPOUT2_MASK 0x0008 /* MIXOUTRVOL_TO_HPOUT2 */
1338#define WM8993_MIXOUTRVOL_TO_HPOUT2_SHIFT 3 /* MIXOUTRVOL_TO_HPOUT2 */
1339#define WM8993_MIXOUTRVOL_TO_HPOUT2_WIDTH 1 /* MIXOUTRVOL_TO_HPOUT2 */
1340
1341/*
1342 * R52 (0x34) - Line Mixer1
1343 */
1344#define WM8993_MIXOUTL_TO_LINEOUT1N 0x0040 /* MIXOUTL_TO_LINEOUT1N */
1345#define WM8993_MIXOUTL_TO_LINEOUT1N_MASK 0x0040 /* MIXOUTL_TO_LINEOUT1N */
1346#define WM8993_MIXOUTL_TO_LINEOUT1N_SHIFT 6 /* MIXOUTL_TO_LINEOUT1N */
1347#define WM8993_MIXOUTL_TO_LINEOUT1N_WIDTH 1 /* MIXOUTL_TO_LINEOUT1N */
1348#define WM8993_MIXOUTR_TO_LINEOUT1N 0x0020 /* MIXOUTR_TO_LINEOUT1N */
1349#define WM8993_MIXOUTR_TO_LINEOUT1N_MASK 0x0020 /* MIXOUTR_TO_LINEOUT1N */
1350#define WM8993_MIXOUTR_TO_LINEOUT1N_SHIFT 5 /* MIXOUTR_TO_LINEOUT1N */
1351#define WM8993_MIXOUTR_TO_LINEOUT1N_WIDTH 1 /* MIXOUTR_TO_LINEOUT1N */
1352#define WM8993_LINEOUT1_MODE 0x0010 /* LINEOUT1_MODE */
1353#define WM8993_LINEOUT1_MODE_MASK 0x0010 /* LINEOUT1_MODE */
1354#define WM8993_LINEOUT1_MODE_SHIFT 4 /* LINEOUT1_MODE */
1355#define WM8993_LINEOUT1_MODE_WIDTH 1 /* LINEOUT1_MODE */
1356#define WM8993_IN1R_TO_LINEOUT1P 0x0004 /* IN1R_TO_LINEOUT1P */
1357#define WM8993_IN1R_TO_LINEOUT1P_MASK 0x0004 /* IN1R_TO_LINEOUT1P */
1358#define WM8993_IN1R_TO_LINEOUT1P_SHIFT 2 /* IN1R_TO_LINEOUT1P */
1359#define WM8993_IN1R_TO_LINEOUT1P_WIDTH 1 /* IN1R_TO_LINEOUT1P */
1360#define WM8993_IN1L_TO_LINEOUT1P 0x0002 /* IN1L_TO_LINEOUT1P */
1361#define WM8993_IN1L_TO_LINEOUT1P_MASK 0x0002 /* IN1L_TO_LINEOUT1P */
1362#define WM8993_IN1L_TO_LINEOUT1P_SHIFT 1 /* IN1L_TO_LINEOUT1P */
1363#define WM8993_IN1L_TO_LINEOUT1P_WIDTH 1 /* IN1L_TO_LINEOUT1P */
1364#define WM8993_MIXOUTL_TO_LINEOUT1P 0x0001 /* MIXOUTL_TO_LINEOUT1P */
1365#define WM8993_MIXOUTL_TO_LINEOUT1P_MASK 0x0001 /* MIXOUTL_TO_LINEOUT1P */
1366#define WM8993_MIXOUTL_TO_LINEOUT1P_SHIFT 0 /* MIXOUTL_TO_LINEOUT1P */
1367#define WM8993_MIXOUTL_TO_LINEOUT1P_WIDTH 1 /* MIXOUTL_TO_LINEOUT1P */
1368
1369/*
1370 * R53 (0x35) - Line Mixer2
1371 */
1372#define WM8993_MIXOUTR_TO_LINEOUT2N 0x0040 /* MIXOUTR_TO_LINEOUT2N */
1373#define WM8993_MIXOUTR_TO_LINEOUT2N_MASK 0x0040 /* MIXOUTR_TO_LINEOUT2N */
1374#define WM8993_MIXOUTR_TO_LINEOUT2N_SHIFT 6 /* MIXOUTR_TO_LINEOUT2N */
1375#define WM8993_MIXOUTR_TO_LINEOUT2N_WIDTH 1 /* MIXOUTR_TO_LINEOUT2N */
1376#define WM8993_MIXOUTL_TO_LINEOUT2N 0x0020 /* MIXOUTL_TO_LINEOUT2N */
1377#define WM8993_MIXOUTL_TO_LINEOUT2N_MASK 0x0020 /* MIXOUTL_TO_LINEOUT2N */
1378#define WM8993_MIXOUTL_TO_LINEOUT2N_SHIFT 5 /* MIXOUTL_TO_LINEOUT2N */
1379#define WM8993_MIXOUTL_TO_LINEOUT2N_WIDTH 1 /* MIXOUTL_TO_LINEOUT2N */
1380#define WM8993_LINEOUT2_MODE 0x0010 /* LINEOUT2_MODE */
1381#define WM8993_LINEOUT2_MODE_MASK 0x0010 /* LINEOUT2_MODE */
1382#define WM8993_LINEOUT2_MODE_SHIFT 4 /* LINEOUT2_MODE */
1383#define WM8993_LINEOUT2_MODE_WIDTH 1 /* LINEOUT2_MODE */
1384#define WM8993_IN1L_TO_LINEOUT2P 0x0004 /* IN1L_TO_LINEOUT2P */
1385#define WM8993_IN1L_TO_LINEOUT2P_MASK 0x0004 /* IN1L_TO_LINEOUT2P */
1386#define WM8993_IN1L_TO_LINEOUT2P_SHIFT 2 /* IN1L_TO_LINEOUT2P */
1387#define WM8993_IN1L_TO_LINEOUT2P_WIDTH 1 /* IN1L_TO_LINEOUT2P */
1388#define WM8993_IN1R_TO_LINEOUT2P 0x0002 /* IN1R_TO_LINEOUT2P */
1389#define WM8993_IN1R_TO_LINEOUT2P_MASK 0x0002 /* IN1R_TO_LINEOUT2P */
1390#define WM8993_IN1R_TO_LINEOUT2P_SHIFT 1 /* IN1R_TO_LINEOUT2P */
1391#define WM8993_IN1R_TO_LINEOUT2P_WIDTH 1 /* IN1R_TO_LINEOUT2P */
1392#define WM8993_MIXOUTR_TO_LINEOUT2P 0x0001 /* MIXOUTR_TO_LINEOUT2P */
1393#define WM8993_MIXOUTR_TO_LINEOUT2P_MASK 0x0001 /* MIXOUTR_TO_LINEOUT2P */
1394#define WM8993_MIXOUTR_TO_LINEOUT2P_SHIFT 0 /* MIXOUTR_TO_LINEOUT2P */
1395#define WM8993_MIXOUTR_TO_LINEOUT2P_WIDTH 1 /* MIXOUTR_TO_LINEOUT2P */
1396
1397/*
1398 * R54 (0x36) - Speaker Mixer
1399 */
1400#define WM8993_SPKAB_REF_SEL 0x0100 /* SPKAB_REF_SEL */
1401#define WM8993_SPKAB_REF_SEL_MASK 0x0100 /* SPKAB_REF_SEL */
1402#define WM8993_SPKAB_REF_SEL_SHIFT 8 /* SPKAB_REF_SEL */
1403#define WM8993_SPKAB_REF_SEL_WIDTH 1 /* SPKAB_REF_SEL */
1404#define WM8993_MIXINL_TO_SPKMIXL 0x0080 /* MIXINL_TO_SPKMIXL */
1405#define WM8993_MIXINL_TO_SPKMIXL_MASK 0x0080 /* MIXINL_TO_SPKMIXL */
1406#define WM8993_MIXINL_TO_SPKMIXL_SHIFT 7 /* MIXINL_TO_SPKMIXL */
1407#define WM8993_MIXINL_TO_SPKMIXL_WIDTH 1 /* MIXINL_TO_SPKMIXL */
1408#define WM8993_MIXINR_TO_SPKMIXR 0x0040 /* MIXINR_TO_SPKMIXR */
1409#define WM8993_MIXINR_TO_SPKMIXR_MASK 0x0040 /* MIXINR_TO_SPKMIXR */
1410#define WM8993_MIXINR_TO_SPKMIXR_SHIFT 6 /* MIXINR_TO_SPKMIXR */
1411#define WM8993_MIXINR_TO_SPKMIXR_WIDTH 1 /* MIXINR_TO_SPKMIXR */
1412#define WM8993_IN1LP_TO_SPKMIXL 0x0020 /* IN1LP_TO_SPKMIXL */
1413#define WM8993_IN1LP_TO_SPKMIXL_MASK 0x0020 /* IN1LP_TO_SPKMIXL */
1414#define WM8993_IN1LP_TO_SPKMIXL_SHIFT 5 /* IN1LP_TO_SPKMIXL */
1415#define WM8993_IN1LP_TO_SPKMIXL_WIDTH 1 /* IN1LP_TO_SPKMIXL */
1416#define WM8993_IN1RP_TO_SPKMIXR 0x0010 /* IN1RP_TO_SPKMIXR */
1417#define WM8993_IN1RP_TO_SPKMIXR_MASK 0x0010 /* IN1RP_TO_SPKMIXR */
1418#define WM8993_IN1RP_TO_SPKMIXR_SHIFT 4 /* IN1RP_TO_SPKMIXR */
1419#define WM8993_IN1RP_TO_SPKMIXR_WIDTH 1 /* IN1RP_TO_SPKMIXR */
1420#define WM8993_MIXOUTL_TO_SPKMIXL 0x0008 /* MIXOUTL_TO_SPKMIXL */
1421#define WM8993_MIXOUTL_TO_SPKMIXL_MASK 0x0008 /* MIXOUTL_TO_SPKMIXL */
1422#define WM8993_MIXOUTL_TO_SPKMIXL_SHIFT 3 /* MIXOUTL_TO_SPKMIXL */
1423#define WM8993_MIXOUTL_TO_SPKMIXL_WIDTH 1 /* MIXOUTL_TO_SPKMIXL */
1424#define WM8993_MIXOUTR_TO_SPKMIXR 0x0004 /* MIXOUTR_TO_SPKMIXR */
1425#define WM8993_MIXOUTR_TO_SPKMIXR_MASK 0x0004 /* MIXOUTR_TO_SPKMIXR */
1426#define WM8993_MIXOUTR_TO_SPKMIXR_SHIFT 2 /* MIXOUTR_TO_SPKMIXR */
1427#define WM8993_MIXOUTR_TO_SPKMIXR_WIDTH 1 /* MIXOUTR_TO_SPKMIXR */
1428#define WM8993_DACL_TO_SPKMIXL 0x0002 /* DACL_TO_SPKMIXL */
1429#define WM8993_DACL_TO_SPKMIXL_MASK 0x0002 /* DACL_TO_SPKMIXL */
1430#define WM8993_DACL_TO_SPKMIXL_SHIFT 1 /* DACL_TO_SPKMIXL */
1431#define WM8993_DACL_TO_SPKMIXL_WIDTH 1 /* DACL_TO_SPKMIXL */
1432#define WM8993_DACR_TO_SPKMIXR 0x0001 /* DACR_TO_SPKMIXR */
1433#define WM8993_DACR_TO_SPKMIXR_MASK 0x0001 /* DACR_TO_SPKMIXR */
1434#define WM8993_DACR_TO_SPKMIXR_SHIFT 0 /* DACR_TO_SPKMIXR */
1435#define WM8993_DACR_TO_SPKMIXR_WIDTH 1 /* DACR_TO_SPKMIXR */
1436
1437/*
1438 * R55 (0x37) - Additional Control
1439 */
1440#define WM8993_LINEOUT1_FB 0x0080 /* LINEOUT1_FB */
1441#define WM8993_LINEOUT1_FB_MASK 0x0080 /* LINEOUT1_FB */
1442#define WM8993_LINEOUT1_FB_SHIFT 7 /* LINEOUT1_FB */
1443#define WM8993_LINEOUT1_FB_WIDTH 1 /* LINEOUT1_FB */
1444#define WM8993_LINEOUT2_FB 0x0040 /* LINEOUT2_FB */
1445#define WM8993_LINEOUT2_FB_MASK 0x0040 /* LINEOUT2_FB */
1446#define WM8993_LINEOUT2_FB_SHIFT 6 /* LINEOUT2_FB */
1447#define WM8993_LINEOUT2_FB_WIDTH 1 /* LINEOUT2_FB */
1448#define WM8993_VROI 0x0001 /* VROI */
1449#define WM8993_VROI_MASK 0x0001 /* VROI */
1450#define WM8993_VROI_SHIFT 0 /* VROI */
1451#define WM8993_VROI_WIDTH 1 /* VROI */
1452
1453/*
1454 * R56 (0x38) - AntiPOP1
1455 */
1456#define WM8993_LINEOUT_VMID_BUF_ENA 0x0080 /* LINEOUT_VMID_BUF_ENA */
1457#define WM8993_LINEOUT_VMID_BUF_ENA_MASK 0x0080 /* LINEOUT_VMID_BUF_ENA */
1458#define WM8993_LINEOUT_VMID_BUF_ENA_SHIFT 7 /* LINEOUT_VMID_BUF_ENA */
1459#define WM8993_LINEOUT_VMID_BUF_ENA_WIDTH 1 /* LINEOUT_VMID_BUF_ENA */
1460#define WM8993_HPOUT2_IN_ENA 0x0040 /* HPOUT2_IN_ENA */
1461#define WM8993_HPOUT2_IN_ENA_MASK 0x0040 /* HPOUT2_IN_ENA */
1462#define WM8993_HPOUT2_IN_ENA_SHIFT 6 /* HPOUT2_IN_ENA */
1463#define WM8993_HPOUT2_IN_ENA_WIDTH 1 /* HPOUT2_IN_ENA */
1464#define WM8993_LINEOUT1_DISCH 0x0020 /* LINEOUT1_DISCH */
1465#define WM8993_LINEOUT1_DISCH_MASK 0x0020 /* LINEOUT1_DISCH */
1466#define WM8993_LINEOUT1_DISCH_SHIFT 5 /* LINEOUT1_DISCH */
1467#define WM8993_LINEOUT1_DISCH_WIDTH 1 /* LINEOUT1_DISCH */
1468#define WM8993_LINEOUT2_DISCH 0x0010 /* LINEOUT2_DISCH */
1469#define WM8993_LINEOUT2_DISCH_MASK 0x0010 /* LINEOUT2_DISCH */
1470#define WM8993_LINEOUT2_DISCH_SHIFT 4 /* LINEOUT2_DISCH */
1471#define WM8993_LINEOUT2_DISCH_WIDTH 1 /* LINEOUT2_DISCH */
1472
1473/*
1474 * R57 (0x39) - AntiPOP2
1475 */
1476#define WM8993_VMID_RAMP_MASK 0x0060 /* VMID_RAMP - [6:5] */
1477#define WM8993_VMID_RAMP_SHIFT 5 /* VMID_RAMP - [6:5] */
1478#define WM8993_VMID_RAMP_WIDTH 2 /* VMID_RAMP - [6:5] */
1479#define WM8993_VMID_BUF_ENA 0x0008 /* VMID_BUF_ENA */
1480#define WM8993_VMID_BUF_ENA_MASK 0x0008 /* VMID_BUF_ENA */
1481#define WM8993_VMID_BUF_ENA_SHIFT 3 /* VMID_BUF_ENA */
1482#define WM8993_VMID_BUF_ENA_WIDTH 1 /* VMID_BUF_ENA */
1483#define WM8993_STARTUP_BIAS_ENA 0x0004 /* STARTUP_BIAS_ENA */
1484#define WM8993_STARTUP_BIAS_ENA_MASK 0x0004 /* STARTUP_BIAS_ENA */
1485#define WM8993_STARTUP_BIAS_ENA_SHIFT 2 /* STARTUP_BIAS_ENA */
1486#define WM8993_STARTUP_BIAS_ENA_WIDTH 1 /* STARTUP_BIAS_ENA */
1487#define WM8993_BIAS_SRC 0x0002 /* BIAS_SRC */
1488#define WM8993_BIAS_SRC_MASK 0x0002 /* BIAS_SRC */
1489#define WM8993_BIAS_SRC_SHIFT 1 /* BIAS_SRC */
1490#define WM8993_BIAS_SRC_WIDTH 1 /* BIAS_SRC */
1491#define WM8993_VMID_DISCH 0x0001 /* VMID_DISCH */
1492#define WM8993_VMID_DISCH_MASK 0x0001 /* VMID_DISCH */
1493#define WM8993_VMID_DISCH_SHIFT 0 /* VMID_DISCH */
1494#define WM8993_VMID_DISCH_WIDTH 1 /* VMID_DISCH */
1495
1496/*
1497 * R58 (0x3A) - MICBIAS
1498 */
1499#define WM8993_JD_SCTHR_MASK 0x00C0 /* JD_SCTHR - [7:6] */
1500#define WM8993_JD_SCTHR_SHIFT 6 /* JD_SCTHR - [7:6] */
1501#define WM8993_JD_SCTHR_WIDTH 2 /* JD_SCTHR - [7:6] */
1502#define WM8993_JD_THR_MASK 0x0030 /* JD_THR - [5:4] */
1503#define WM8993_JD_THR_SHIFT 4 /* JD_THR - [5:4] */
1504#define WM8993_JD_THR_WIDTH 2 /* JD_THR - [5:4] */
1505#define WM8993_JD_ENA 0x0004 /* JD_ENA */
1506#define WM8993_JD_ENA_MASK 0x0004 /* JD_ENA */
1507#define WM8993_JD_ENA_SHIFT 2 /* JD_ENA */
1508#define WM8993_JD_ENA_WIDTH 1 /* JD_ENA */
1509#define WM8993_MICB2_LVL 0x0002 /* MICB2_LVL */
1510#define WM8993_MICB2_LVL_MASK 0x0002 /* MICB2_LVL */
1511#define WM8993_MICB2_LVL_SHIFT 1 /* MICB2_LVL */
1512#define WM8993_MICB2_LVL_WIDTH 1 /* MICB2_LVL */
1513#define WM8993_MICB1_LVL 0x0001 /* MICB1_LVL */
1514#define WM8993_MICB1_LVL_MASK 0x0001 /* MICB1_LVL */
1515#define WM8993_MICB1_LVL_SHIFT 0 /* MICB1_LVL */
1516#define WM8993_MICB1_LVL_WIDTH 1 /* MICB1_LVL */
1517
1518/*
1519 * R60 (0x3C) - FLL Control 1
1520 */
1521#define WM8993_FLL_FRAC 0x0004 /* FLL_FRAC */
1522#define WM8993_FLL_FRAC_MASK 0x0004 /* FLL_FRAC */
1523#define WM8993_FLL_FRAC_SHIFT 2 /* FLL_FRAC */
1524#define WM8993_FLL_FRAC_WIDTH 1 /* FLL_FRAC */
1525#define WM8993_FLL_OSC_ENA 0x0002 /* FLL_OSC_ENA */
1526#define WM8993_FLL_OSC_ENA_MASK 0x0002 /* FLL_OSC_ENA */
1527#define WM8993_FLL_OSC_ENA_SHIFT 1 /* FLL_OSC_ENA */
1528#define WM8993_FLL_OSC_ENA_WIDTH 1 /* FLL_OSC_ENA */
1529#define WM8993_FLL_ENA 0x0001 /* FLL_ENA */
1530#define WM8993_FLL_ENA_MASK 0x0001 /* FLL_ENA */
1531#define WM8993_FLL_ENA_SHIFT 0 /* FLL_ENA */
1532#define WM8993_FLL_ENA_WIDTH 1 /* FLL_ENA */
1533
1534/*
1535 * R61 (0x3D) - FLL Control 2
1536 */
1537#define WM8993_FLL_OUTDIV_MASK 0x0700 /* FLL_OUTDIV - [10:8] */
1538#define WM8993_FLL_OUTDIV_SHIFT 8 /* FLL_OUTDIV - [10:8] */
1539#define WM8993_FLL_OUTDIV_WIDTH 3 /* FLL_OUTDIV - [10:8] */
1540#define WM8993_FLL_CTRL_RATE_MASK 0x0070 /* FLL_CTRL_RATE - [6:4] */
1541#define WM8993_FLL_CTRL_RATE_SHIFT 4 /* FLL_CTRL_RATE - [6:4] */
1542#define WM8993_FLL_CTRL_RATE_WIDTH 3 /* FLL_CTRL_RATE - [6:4] */
1543#define WM8993_FLL_FRATIO_MASK 0x0007 /* FLL_FRATIO - [2:0] */
1544#define WM8993_FLL_FRATIO_SHIFT 0 /* FLL_FRATIO - [2:0] */
1545#define WM8993_FLL_FRATIO_WIDTH 3 /* FLL_FRATIO - [2:0] */
1546
1547/*
1548 * R62 (0x3E) - FLL Control 3
1549 */
1550#define WM8993_FLL_K_MASK 0xFFFF /* FLL_K - [15:0] */
1551#define WM8993_FLL_K_SHIFT 0 /* FLL_K - [15:0] */
1552#define WM8993_FLL_K_WIDTH 16 /* FLL_K - [15:0] */
1553
1554/*
1555 * R63 (0x3F) - FLL Control 4
1556 */
1557#define WM8993_FLL_N_MASK 0x7FE0 /* FLL_N - [14:5] */
1558#define WM8993_FLL_N_SHIFT 5 /* FLL_N - [14:5] */
1559#define WM8993_FLL_N_WIDTH 10 /* FLL_N - [14:5] */
1560#define WM8993_FLL_GAIN_MASK 0x000F /* FLL_GAIN - [3:0] */
1561#define WM8993_FLL_GAIN_SHIFT 0 /* FLL_GAIN - [3:0] */
1562#define WM8993_FLL_GAIN_WIDTH 4 /* FLL_GAIN - [3:0] */
1563
1564/*
1565 * R64 (0x40) - FLL Control 5
1566 */
1567#define WM8993_FLL_FRC_NCO_VAL_MASK 0x1F80 /* FLL_FRC_NCO_VAL - [12:7] */
1568#define WM8993_FLL_FRC_NCO_VAL_SHIFT 7 /* FLL_FRC_NCO_VAL - [12:7] */
1569#define WM8993_FLL_FRC_NCO_VAL_WIDTH 6 /* FLL_FRC_NCO_VAL - [12:7] */
1570#define WM8993_FLL_FRC_NCO 0x0040 /* FLL_FRC_NCO */
1571#define WM8993_FLL_FRC_NCO_MASK 0x0040 /* FLL_FRC_NCO */
1572#define WM8993_FLL_FRC_NCO_SHIFT 6 /* FLL_FRC_NCO */
1573#define WM8993_FLL_FRC_NCO_WIDTH 1 /* FLL_FRC_NCO */
1574#define WM8993_FLL_CLK_REF_DIV_MASK 0x0018 /* FLL_CLK_REF_DIV - [4:3] */
1575#define WM8993_FLL_CLK_REF_DIV_SHIFT 3 /* FLL_CLK_REF_DIV - [4:3] */
1576#define WM8993_FLL_CLK_REF_DIV_WIDTH 2 /* FLL_CLK_REF_DIV - [4:3] */
1577#define WM8993_FLL_CLK_SRC_MASK 0x0003 /* FLL_CLK_SRC - [1:0] */
1578#define WM8993_FLL_CLK_SRC_SHIFT 0 /* FLL_CLK_SRC - [1:0] */
1579#define WM8993_FLL_CLK_SRC_WIDTH 2 /* FLL_CLK_SRC - [1:0] */
1580
1581/*
1582 * R65 (0x41) - Clocking 3
1583 */
1584#define WM8993_CLK_DCS_DIV_MASK 0x3C00 /* CLK_DCS_DIV - [13:10] */
1585#define WM8993_CLK_DCS_DIV_SHIFT 10 /* CLK_DCS_DIV - [13:10] */
1586#define WM8993_CLK_DCS_DIV_WIDTH 4 /* CLK_DCS_DIV - [13:10] */
1587#define WM8993_SAMPLE_RATE_MASK 0x0380 /* SAMPLE_RATE - [9:7] */
1588#define WM8993_SAMPLE_RATE_SHIFT 7 /* SAMPLE_RATE - [9:7] */
1589#define WM8993_SAMPLE_RATE_WIDTH 3 /* SAMPLE_RATE - [9:7] */
1590#define WM8993_CLK_SYS_RATE_MASK 0x001E /* CLK_SYS_RATE - [4:1] */
1591#define WM8993_CLK_SYS_RATE_SHIFT 1 /* CLK_SYS_RATE - [4:1] */
1592#define WM8993_CLK_SYS_RATE_WIDTH 4 /* CLK_SYS_RATE - [4:1] */
1593#define WM8993_CLK_DSP_ENA 0x0001 /* CLK_DSP_ENA */
1594#define WM8993_CLK_DSP_ENA_MASK 0x0001 /* CLK_DSP_ENA */
1595#define WM8993_CLK_DSP_ENA_SHIFT 0 /* CLK_DSP_ENA */
1596#define WM8993_CLK_DSP_ENA_WIDTH 1 /* CLK_DSP_ENA */
1597
1598/*
1599 * R66 (0x42) - Clocking 4
1600 */
1601#define WM8993_DAC_DIV4 0x0200 /* DAC_DIV4 */
1602#define WM8993_DAC_DIV4_MASK 0x0200 /* DAC_DIV4 */
1603#define WM8993_DAC_DIV4_SHIFT 9 /* DAC_DIV4 */
1604#define WM8993_DAC_DIV4_WIDTH 1 /* DAC_DIV4 */
1605#define WM8993_CLK_256K_DIV_MASK 0x007E /* CLK_256K_DIV - [6:1] */
1606#define WM8993_CLK_256K_DIV_SHIFT 1 /* CLK_256K_DIV - [6:1] */
1607#define WM8993_CLK_256K_DIV_WIDTH 6 /* CLK_256K_DIV - [6:1] */
1608#define WM8993_SR_MODE 0x0001 /* SR_MODE */
1609#define WM8993_SR_MODE_MASK 0x0001 /* SR_MODE */
1610#define WM8993_SR_MODE_SHIFT 0 /* SR_MODE */
1611#define WM8993_SR_MODE_WIDTH 1 /* SR_MODE */
1612
1613/*
1614 * R67 (0x43) - MW Slave Control
1615 */
1616#define WM8993_MASK_WRITE_ENA 0x0001 /* MASK_WRITE_ENA */
1617#define WM8993_MASK_WRITE_ENA_MASK 0x0001 /* MASK_WRITE_ENA */
1618#define WM8993_MASK_WRITE_ENA_SHIFT 0 /* MASK_WRITE_ENA */
1619#define WM8993_MASK_WRITE_ENA_WIDTH 1 /* MASK_WRITE_ENA */
1620
1621/*
1622 * R69 (0x45) - Bus Control 1
1623 */
1624#define WM8993_CLK_SYS_ENA 0x0002 /* CLK_SYS_ENA */
1625#define WM8993_CLK_SYS_ENA_MASK 0x0002 /* CLK_SYS_ENA */
1626#define WM8993_CLK_SYS_ENA_SHIFT 1 /* CLK_SYS_ENA */
1627#define WM8993_CLK_SYS_ENA_WIDTH 1 /* CLK_SYS_ENA */
1628
1629/*
1630 * R70 (0x46) - Write Sequencer 0
1631 */
1632#define WM8993_WSEQ_ENA 0x0100 /* WSEQ_ENA */
1633#define WM8993_WSEQ_ENA_MASK 0x0100 /* WSEQ_ENA */
1634#define WM8993_WSEQ_ENA_SHIFT 8 /* WSEQ_ENA */
1635#define WM8993_WSEQ_ENA_WIDTH 1 /* WSEQ_ENA */
1636#define WM8993_WSEQ_WRITE_INDEX_MASK 0x001F /* WSEQ_WRITE_INDEX - [4:0] */
1637#define WM8993_WSEQ_WRITE_INDEX_SHIFT 0 /* WSEQ_WRITE_INDEX - [4:0] */
1638#define WM8993_WSEQ_WRITE_INDEX_WIDTH 5 /* WSEQ_WRITE_INDEX - [4:0] */
1639
1640/*
1641 * R71 (0x47) - Write Sequencer 1
1642 */
1643#define WM8993_WSEQ_DATA_WIDTH_MASK 0x7000 /* WSEQ_DATA_WIDTH - [14:12] */
1644#define WM8993_WSEQ_DATA_WIDTH_SHIFT 12 /* WSEQ_DATA_WIDTH - [14:12] */
1645#define WM8993_WSEQ_DATA_WIDTH_WIDTH 3 /* WSEQ_DATA_WIDTH - [14:12] */
1646#define WM8993_WSEQ_DATA_START_MASK 0x0F00 /* WSEQ_DATA_START - [11:8] */
1647#define WM8993_WSEQ_DATA_START_SHIFT 8 /* WSEQ_DATA_START - [11:8] */
1648#define WM8993_WSEQ_DATA_START_WIDTH 4 /* WSEQ_DATA_START - [11:8] */
1649#define WM8993_WSEQ_ADDR_MASK 0x00FF /* WSEQ_ADDR - [7:0] */
1650#define WM8993_WSEQ_ADDR_SHIFT 0 /* WSEQ_ADDR - [7:0] */
1651#define WM8993_WSEQ_ADDR_WIDTH 8 /* WSEQ_ADDR - [7:0] */
1652
1653/*
1654 * R72 (0x48) - Write Sequencer 2
1655 */
1656#define WM8993_WSEQ_EOS 0x4000 /* WSEQ_EOS */
1657#define WM8993_WSEQ_EOS_MASK 0x4000 /* WSEQ_EOS */
1658#define WM8993_WSEQ_EOS_SHIFT 14 /* WSEQ_EOS */
1659#define WM8993_WSEQ_EOS_WIDTH 1 /* WSEQ_EOS */
1660#define WM8993_WSEQ_DELAY_MASK 0x0F00 /* WSEQ_DELAY - [11:8] */
1661#define WM8993_WSEQ_DELAY_SHIFT 8 /* WSEQ_DELAY - [11:8] */
1662#define WM8993_WSEQ_DELAY_WIDTH 4 /* WSEQ_DELAY - [11:8] */
1663#define WM8993_WSEQ_DATA_MASK 0x00FF /* WSEQ_DATA - [7:0] */
1664#define WM8993_WSEQ_DATA_SHIFT 0 /* WSEQ_DATA - [7:0] */
1665#define WM8993_WSEQ_DATA_WIDTH 8 /* WSEQ_DATA - [7:0] */
1666
1667/*
1668 * R73 (0x49) - Write Sequencer 3
1669 */
1670#define WM8993_WSEQ_ABORT 0x0200 /* WSEQ_ABORT */
1671#define WM8993_WSEQ_ABORT_MASK 0x0200 /* WSEQ_ABORT */
1672#define WM8993_WSEQ_ABORT_SHIFT 9 /* WSEQ_ABORT */
1673#define WM8993_WSEQ_ABORT_WIDTH 1 /* WSEQ_ABORT */
1674#define WM8993_WSEQ_START 0x0100 /* WSEQ_START */
1675#define WM8993_WSEQ_START_MASK 0x0100 /* WSEQ_START */
1676#define WM8993_WSEQ_START_SHIFT 8 /* WSEQ_START */
1677#define WM8993_WSEQ_START_WIDTH 1 /* WSEQ_START */
1678#define WM8993_WSEQ_START_INDEX_MASK 0x003F /* WSEQ_START_INDEX - [5:0] */
1679#define WM8993_WSEQ_START_INDEX_SHIFT 0 /* WSEQ_START_INDEX - [5:0] */
1680#define WM8993_WSEQ_START_INDEX_WIDTH 6 /* WSEQ_START_INDEX - [5:0] */
1681
1682/*
1683 * R74 (0x4A) - Write Sequencer 4
1684 */
1685#define WM8993_WSEQ_BUSY 0x0001 /* WSEQ_BUSY */
1686#define WM8993_WSEQ_BUSY_MASK 0x0001 /* WSEQ_BUSY */
1687#define WM8993_WSEQ_BUSY_SHIFT 0 /* WSEQ_BUSY */
1688#define WM8993_WSEQ_BUSY_WIDTH 1 /* WSEQ_BUSY */
1689
1690/*
1691 * R75 (0x4B) - Write Sequencer 5
1692 */
1693#define WM8993_WSEQ_CURRENT_INDEX_MASK 0x003F /* WSEQ_CURRENT_INDEX - [5:0] */
1694#define WM8993_WSEQ_CURRENT_INDEX_SHIFT 0 /* WSEQ_CURRENT_INDEX - [5:0] */
1695#define WM8993_WSEQ_CURRENT_INDEX_WIDTH 6 /* WSEQ_CURRENT_INDEX - [5:0] */
1696
1697/*
1698 * R76 (0x4C) - Charge Pump 1
1699 */
1700#define WM8993_CP_ENA 0x8000 /* CP_ENA */
1701#define WM8993_CP_ENA_MASK 0x8000 /* CP_ENA */
1702#define WM8993_CP_ENA_SHIFT 15 /* CP_ENA */
1703#define WM8993_CP_ENA_WIDTH 1 /* CP_ENA */
1704
1705/*
1706 * R81 (0x51) - Class W 0
1707 */
1708#define WM8993_CP_DYN_FREQ 0x0002 /* CP_DYN_FREQ */
1709#define WM8993_CP_DYN_FREQ_MASK 0x0002 /* CP_DYN_FREQ */
1710#define WM8993_CP_DYN_FREQ_SHIFT 1 /* CP_DYN_FREQ */
1711#define WM8993_CP_DYN_FREQ_WIDTH 1 /* CP_DYN_FREQ */
1712#define WM8993_CP_DYN_V 0x0001 /* CP_DYN_V */
1713#define WM8993_CP_DYN_V_MASK 0x0001 /* CP_DYN_V */
1714#define WM8993_CP_DYN_V_SHIFT 0 /* CP_DYN_V */
1715#define WM8993_CP_DYN_V_WIDTH 1 /* CP_DYN_V */
1716
1717/*
1718 * R84 (0x54) - DC Servo 0
1719 */
1720#define WM8993_DCS_TRIG_SINGLE_1 0x2000 /* DCS_TRIG_SINGLE_1 */
1721#define WM8993_DCS_TRIG_SINGLE_1_MASK 0x2000 /* DCS_TRIG_SINGLE_1 */
1722#define WM8993_DCS_TRIG_SINGLE_1_SHIFT 13 /* DCS_TRIG_SINGLE_1 */
1723#define WM8993_DCS_TRIG_SINGLE_1_WIDTH 1 /* DCS_TRIG_SINGLE_1 */
1724#define WM8993_DCS_TRIG_SINGLE_0 0x1000 /* DCS_TRIG_SINGLE_0 */
1725#define WM8993_DCS_TRIG_SINGLE_0_MASK 0x1000 /* DCS_TRIG_SINGLE_0 */
1726#define WM8993_DCS_TRIG_SINGLE_0_SHIFT 12 /* DCS_TRIG_SINGLE_0 */
1727#define WM8993_DCS_TRIG_SINGLE_0_WIDTH 1 /* DCS_TRIG_SINGLE_0 */
1728#define WM8993_DCS_TRIG_SERIES_1 0x0200 /* DCS_TRIG_SERIES_1 */
1729#define WM8993_DCS_TRIG_SERIES_1_MASK 0x0200 /* DCS_TRIG_SERIES_1 */
1730#define WM8993_DCS_TRIG_SERIES_1_SHIFT 9 /* DCS_TRIG_SERIES_1 */
1731#define WM8993_DCS_TRIG_SERIES_1_WIDTH 1 /* DCS_TRIG_SERIES_1 */
1732#define WM8993_DCS_TRIG_SERIES_0 0x0100 /* DCS_TRIG_SERIES_0 */
1733#define WM8993_DCS_TRIG_SERIES_0_MASK 0x0100 /* DCS_TRIG_SERIES_0 */
1734#define WM8993_DCS_TRIG_SERIES_0_SHIFT 8 /* DCS_TRIG_SERIES_0 */
1735#define WM8993_DCS_TRIG_SERIES_0_WIDTH 1 /* DCS_TRIG_SERIES_0 */
1736#define WM8993_DCS_TRIG_STARTUP_1 0x0020 /* DCS_TRIG_STARTUP_1 */
1737#define WM8993_DCS_TRIG_STARTUP_1_MASK 0x0020 /* DCS_TRIG_STARTUP_1 */
1738#define WM8993_DCS_TRIG_STARTUP_1_SHIFT 5 /* DCS_TRIG_STARTUP_1 */
1739#define WM8993_DCS_TRIG_STARTUP_1_WIDTH 1 /* DCS_TRIG_STARTUP_1 */
1740#define WM8993_DCS_TRIG_STARTUP_0 0x0010 /* DCS_TRIG_STARTUP_0 */
1741#define WM8993_DCS_TRIG_STARTUP_0_MASK 0x0010 /* DCS_TRIG_STARTUP_0 */
1742#define WM8993_DCS_TRIG_STARTUP_0_SHIFT 4 /* DCS_TRIG_STARTUP_0 */
1743#define WM8993_DCS_TRIG_STARTUP_0_WIDTH 1 /* DCS_TRIG_STARTUP_0 */
1744#define WM8993_DCS_TRIG_DAC_WR_1 0x0008 /* DCS_TRIG_DAC_WR_1 */
1745#define WM8993_DCS_TRIG_DAC_WR_1_MASK 0x0008 /* DCS_TRIG_DAC_WR_1 */
1746#define WM8993_DCS_TRIG_DAC_WR_1_SHIFT 3 /* DCS_TRIG_DAC_WR_1 */
1747#define WM8993_DCS_TRIG_DAC_WR_1_WIDTH 1 /* DCS_TRIG_DAC_WR_1 */
1748#define WM8993_DCS_TRIG_DAC_WR_0 0x0004 /* DCS_TRIG_DAC_WR_0 */
1749#define WM8993_DCS_TRIG_DAC_WR_0_MASK 0x0004 /* DCS_TRIG_DAC_WR_0 */
1750#define WM8993_DCS_TRIG_DAC_WR_0_SHIFT 2 /* DCS_TRIG_DAC_WR_0 */
1751#define WM8993_DCS_TRIG_DAC_WR_0_WIDTH 1 /* DCS_TRIG_DAC_WR_0 */
1752#define WM8993_DCS_ENA_CHAN_1 0x0002 /* DCS_ENA_CHAN_1 */
1753#define WM8993_DCS_ENA_CHAN_1_MASK 0x0002 /* DCS_ENA_CHAN_1 */
1754#define WM8993_DCS_ENA_CHAN_1_SHIFT 1 /* DCS_ENA_CHAN_1 */
1755#define WM8993_DCS_ENA_CHAN_1_WIDTH 1 /* DCS_ENA_CHAN_1 */
1756#define WM8993_DCS_ENA_CHAN_0 0x0001 /* DCS_ENA_CHAN_0 */
1757#define WM8993_DCS_ENA_CHAN_0_MASK 0x0001 /* DCS_ENA_CHAN_0 */
1758#define WM8993_DCS_ENA_CHAN_0_SHIFT 0 /* DCS_ENA_CHAN_0 */
1759#define WM8993_DCS_ENA_CHAN_0_WIDTH 1 /* DCS_ENA_CHAN_0 */
1760
1761/*
1762 * R85 (0x55) - DC Servo 1
1763 */
1764#define WM8993_DCS_SERIES_NO_01_MASK 0x0FE0 /* DCS_SERIES_NO_01 - [11:5] */
1765#define WM8993_DCS_SERIES_NO_01_SHIFT 5 /* DCS_SERIES_NO_01 - [11:5] */
1766#define WM8993_DCS_SERIES_NO_01_WIDTH 7 /* DCS_SERIES_NO_01 - [11:5] */
1767#define WM8993_DCS_TIMER_PERIOD_01_MASK 0x000F /* DCS_TIMER_PERIOD_01 - [3:0] */
1768#define WM8993_DCS_TIMER_PERIOD_01_SHIFT 0 /* DCS_TIMER_PERIOD_01 - [3:0] */
1769#define WM8993_DCS_TIMER_PERIOD_01_WIDTH 4 /* DCS_TIMER_PERIOD_01 - [3:0] */
1770
1771/*
1772 * R87 (0x57) - DC Servo 3
1773 */
1774#define WM8993_DCS_DAC_WR_VAL_1_MASK 0xFF00 /* DCS_DAC_WR_VAL_1 - [15:8] */
1775#define WM8993_DCS_DAC_WR_VAL_1_SHIFT 8 /* DCS_DAC_WR_VAL_1 - [15:8] */
1776#define WM8993_DCS_DAC_WR_VAL_1_WIDTH 8 /* DCS_DAC_WR_VAL_1 - [15:8] */
1777#define WM8993_DCS_DAC_WR_VAL_0_MASK 0x00FF /* DCS_DAC_WR_VAL_0 - [7:0] */
1778#define WM8993_DCS_DAC_WR_VAL_0_SHIFT 0 /* DCS_DAC_WR_VAL_0 - [7:0] */
1779#define WM8993_DCS_DAC_WR_VAL_0_WIDTH 8 /* DCS_DAC_WR_VAL_0 - [7:0] */
1780
1781/*
1782 * R88 (0x58) - DC Servo Readback 0
1783 */
1784#define WM8993_DCS_DATAPATH_BUSY 0x4000 /* DCS_DATAPATH_BUSY */
1785#define WM8993_DCS_DATAPATH_BUSY_MASK 0x4000 /* DCS_DATAPATH_BUSY */
1786#define WM8993_DCS_DATAPATH_BUSY_SHIFT 14 /* DCS_DATAPATH_BUSY */
1787#define WM8993_DCS_DATAPATH_BUSY_WIDTH 1 /* DCS_DATAPATH_BUSY */
1788#define WM8993_DCS_CHANNEL_MASK 0x3000 /* DCS_CHANNEL - [13:12] */
1789#define WM8993_DCS_CHANNEL_SHIFT 12 /* DCS_CHANNEL - [13:12] */
1790#define WM8993_DCS_CHANNEL_WIDTH 2 /* DCS_CHANNEL - [13:12] */
1791#define WM8993_DCS_CAL_COMPLETE_MASK 0x0300 /* DCS_CAL_COMPLETE - [9:8] */
1792#define WM8993_DCS_CAL_COMPLETE_SHIFT 8 /* DCS_CAL_COMPLETE - [9:8] */
1793#define WM8993_DCS_CAL_COMPLETE_WIDTH 2 /* DCS_CAL_COMPLETE - [9:8] */
1794#define WM8993_DCS_DAC_WR_COMPLETE_MASK 0x0030 /* DCS_DAC_WR_COMPLETE - [5:4] */
1795#define WM8993_DCS_DAC_WR_COMPLETE_SHIFT 4 /* DCS_DAC_WR_COMPLETE - [5:4] */
1796#define WM8993_DCS_DAC_WR_COMPLETE_WIDTH 2 /* DCS_DAC_WR_COMPLETE - [5:4] */
1797#define WM8993_DCS_STARTUP_COMPLETE_MASK 0x0003 /* DCS_STARTUP_COMPLETE - [1:0] */
1798#define WM8993_DCS_STARTUP_COMPLETE_SHIFT 0 /* DCS_STARTUP_COMPLETE - [1:0] */
1799#define WM8993_DCS_STARTUP_COMPLETE_WIDTH 2 /* DCS_STARTUP_COMPLETE - [1:0] */
1800
1801/*
1802 * R89 (0x59) - DC Servo Readback 1
1803 */
1804#define WM8993_DCS_INTEG_CHAN_1_MASK 0x00FF /* DCS_INTEG_CHAN_1 - [7:0] */
1805#define WM8993_DCS_INTEG_CHAN_1_SHIFT 0 /* DCS_INTEG_CHAN_1 - [7:0] */
1806#define WM8993_DCS_INTEG_CHAN_1_WIDTH 8 /* DCS_INTEG_CHAN_1 - [7:0] */
1807
1808/*
1809 * R90 (0x5A) - DC Servo Readback 2
1810 */
1811#define WM8993_DCS_INTEG_CHAN_0_MASK 0x00FF /* DCS_INTEG_CHAN_0 - [7:0] */
1812#define WM8993_DCS_INTEG_CHAN_0_SHIFT 0 /* DCS_INTEG_CHAN_0 - [7:0] */
1813#define WM8993_DCS_INTEG_CHAN_0_WIDTH 8 /* DCS_INTEG_CHAN_0 - [7:0] */
1814
1815/*
1816 * R96 (0x60) - Analogue HP 0
1817 */
1818#define WM8993_HPOUT1_AUTO_PU 0x0100 /* HPOUT1_AUTO_PU */
1819#define WM8993_HPOUT1_AUTO_PU_MASK 0x0100 /* HPOUT1_AUTO_PU */
1820#define WM8993_HPOUT1_AUTO_PU_SHIFT 8 /* HPOUT1_AUTO_PU */
1821#define WM8993_HPOUT1_AUTO_PU_WIDTH 1 /* HPOUT1_AUTO_PU */
1822#define WM8993_HPOUT1L_RMV_SHORT 0x0080 /* HPOUT1L_RMV_SHORT */
1823#define WM8993_HPOUT1L_RMV_SHORT_MASK 0x0080 /* HPOUT1L_RMV_SHORT */
1824#define WM8993_HPOUT1L_RMV_SHORT_SHIFT 7 /* HPOUT1L_RMV_SHORT */
1825#define WM8993_HPOUT1L_RMV_SHORT_WIDTH 1 /* HPOUT1L_RMV_SHORT */
1826#define WM8993_HPOUT1L_OUTP 0x0040 /* HPOUT1L_OUTP */
1827#define WM8993_HPOUT1L_OUTP_MASK 0x0040 /* HPOUT1L_OUTP */
1828#define WM8993_HPOUT1L_OUTP_SHIFT 6 /* HPOUT1L_OUTP */
1829#define WM8993_HPOUT1L_OUTP_WIDTH 1 /* HPOUT1L_OUTP */
1830#define WM8993_HPOUT1L_DLY 0x0020 /* HPOUT1L_DLY */
1831#define WM8993_HPOUT1L_DLY_MASK 0x0020 /* HPOUT1L_DLY */
1832#define WM8993_HPOUT1L_DLY_SHIFT 5 /* HPOUT1L_DLY */
1833#define WM8993_HPOUT1L_DLY_WIDTH 1 /* HPOUT1L_DLY */
1834#define WM8993_HPOUT1R_RMV_SHORT 0x0008 /* HPOUT1R_RMV_SHORT */
1835#define WM8993_HPOUT1R_RMV_SHORT_MASK 0x0008 /* HPOUT1R_RMV_SHORT */
1836#define WM8993_HPOUT1R_RMV_SHORT_SHIFT 3 /* HPOUT1R_RMV_SHORT */
1837#define WM8993_HPOUT1R_RMV_SHORT_WIDTH 1 /* HPOUT1R_RMV_SHORT */
1838#define WM8993_HPOUT1R_OUTP 0x0004 /* HPOUT1R_OUTP */
1839#define WM8993_HPOUT1R_OUTP_MASK 0x0004 /* HPOUT1R_OUTP */
1840#define WM8993_HPOUT1R_OUTP_SHIFT 2 /* HPOUT1R_OUTP */
1841#define WM8993_HPOUT1R_OUTP_WIDTH 1 /* HPOUT1R_OUTP */
1842#define WM8993_HPOUT1R_DLY 0x0002 /* HPOUT1R_DLY */
1843#define WM8993_HPOUT1R_DLY_MASK 0x0002 /* HPOUT1R_DLY */
1844#define WM8993_HPOUT1R_DLY_SHIFT 1 /* HPOUT1R_DLY */
1845#define WM8993_HPOUT1R_DLY_WIDTH 1 /* HPOUT1R_DLY */
1846
1847/*
1848 * R98 (0x62) - EQ1
1849 */
1850#define WM8993_EQ_ENA 0x0001 /* EQ_ENA */
1851#define WM8993_EQ_ENA_MASK 0x0001 /* EQ_ENA */
1852#define WM8993_EQ_ENA_SHIFT 0 /* EQ_ENA */
1853#define WM8993_EQ_ENA_WIDTH 1 /* EQ_ENA */
1854
1855/*
1856 * R99 (0x63) - EQ2
1857 */
1858#define WM8993_EQ_B1_GAIN_MASK 0x001F /* EQ_B1_GAIN - [4:0] */
1859#define WM8993_EQ_B1_GAIN_SHIFT 0 /* EQ_B1_GAIN - [4:0] */
1860#define WM8993_EQ_B1_GAIN_WIDTH 5 /* EQ_B1_GAIN - [4:0] */
1861
1862/*
1863 * R100 (0x64) - EQ3
1864 */
1865#define WM8993_EQ_B2_GAIN_MASK 0x001F /* EQ_B2_GAIN - [4:0] */
1866#define WM8993_EQ_B2_GAIN_SHIFT 0 /* EQ_B2_GAIN - [4:0] */
1867#define WM8993_EQ_B2_GAIN_WIDTH 5 /* EQ_B2_GAIN - [4:0] */
1868
1869/*
1870 * R101 (0x65) - EQ4
1871 */
1872#define WM8993_EQ_B3_GAIN_MASK 0x001F /* EQ_B3_GAIN - [4:0] */
1873#define WM8993_EQ_B3_GAIN_SHIFT 0 /* EQ_B3_GAIN - [4:0] */
1874#define WM8993_EQ_B3_GAIN_WIDTH 5 /* EQ_B3_GAIN - [4:0] */
1875
1876/*
1877 * R102 (0x66) - EQ5
1878 */
1879#define WM8993_EQ_B4_GAIN_MASK 0x001F /* EQ_B4_GAIN - [4:0] */
1880#define WM8993_EQ_B4_GAIN_SHIFT 0 /* EQ_B4_GAIN - [4:0] */
1881#define WM8993_EQ_B4_GAIN_WIDTH 5 /* EQ_B4_GAIN - [4:0] */
1882
1883/*
1884 * R103 (0x67) - EQ6
1885 */
1886#define WM8993_EQ_B5_GAIN_MASK 0x001F /* EQ_B5_GAIN - [4:0] */
1887#define WM8993_EQ_B5_GAIN_SHIFT 0 /* EQ_B5_GAIN - [4:0] */
1888#define WM8993_EQ_B5_GAIN_WIDTH 5 /* EQ_B5_GAIN - [4:0] */
1889
1890/*
1891 * R104 (0x68) - EQ7
1892 */
1893#define WM8993_EQ_B1_A_MASK 0xFFFF /* EQ_B1_A - [15:0] */
1894#define WM8993_EQ_B1_A_SHIFT 0 /* EQ_B1_A - [15:0] */
1895#define WM8993_EQ_B1_A_WIDTH 16 /* EQ_B1_A - [15:0] */
1896
1897/*
1898 * R105 (0x69) - EQ8
1899 */
1900#define WM8993_EQ_B1_B_MASK 0xFFFF /* EQ_B1_B - [15:0] */
1901#define WM8993_EQ_B1_B_SHIFT 0 /* EQ_B1_B - [15:0] */
1902#define WM8993_EQ_B1_B_WIDTH 16 /* EQ_B1_B - [15:0] */
1903
1904/*
1905 * R106 (0x6A) - EQ9
1906 */
1907#define WM8993_EQ_B1_PG_MASK 0xFFFF /* EQ_B1_PG - [15:0] */
1908#define WM8993_EQ_B1_PG_SHIFT 0 /* EQ_B1_PG - [15:0] */
1909#define WM8993_EQ_B1_PG_WIDTH 16 /* EQ_B1_PG - [15:0] */
1910
1911/*
1912 * R107 (0x6B) - EQ10
1913 */
1914#define WM8993_EQ_B2_A_MASK 0xFFFF /* EQ_B2_A - [15:0] */
1915#define WM8993_EQ_B2_A_SHIFT 0 /* EQ_B2_A - [15:0] */
1916#define WM8993_EQ_B2_A_WIDTH 16 /* EQ_B2_A - [15:0] */
1917
1918/*
1919 * R108 (0x6C) - EQ11
1920 */
1921#define WM8993_EQ_B2_B_MASK 0xFFFF /* EQ_B2_B - [15:0] */
1922#define WM8993_EQ_B2_B_SHIFT 0 /* EQ_B2_B - [15:0] */
1923#define WM8993_EQ_B2_B_WIDTH 16 /* EQ_B2_B - [15:0] */
1924
1925/*
1926 * R109 (0x6D) - EQ12
1927 */
1928#define WM8993_EQ_B2_C_MASK 0xFFFF /* EQ_B2_C - [15:0] */
1929#define WM8993_EQ_B2_C_SHIFT 0 /* EQ_B2_C - [15:0] */
1930#define WM8993_EQ_B2_C_WIDTH 16 /* EQ_B2_C - [15:0] */
1931
1932/*
1933 * R110 (0x6E) - EQ13
1934 */
1935#define WM8993_EQ_B2_PG_MASK 0xFFFF /* EQ_B2_PG - [15:0] */
1936#define WM8993_EQ_B2_PG_SHIFT 0 /* EQ_B2_PG - [15:0] */
1937#define WM8993_EQ_B2_PG_WIDTH 16 /* EQ_B2_PG - [15:0] */
1938
1939/*
1940 * R111 (0x6F) - EQ14
1941 */
1942#define WM8993_EQ_B3_A_MASK 0xFFFF /* EQ_B3_A - [15:0] */
1943#define WM8993_EQ_B3_A_SHIFT 0 /* EQ_B3_A - [15:0] */
1944#define WM8993_EQ_B3_A_WIDTH 16 /* EQ_B3_A - [15:0] */
1945
1946/*
1947 * R112 (0x70) - EQ15
1948 */
1949#define WM8993_EQ_B3_B_MASK 0xFFFF /* EQ_B3_B - [15:0] */
1950#define WM8993_EQ_B3_B_SHIFT 0 /* EQ_B3_B - [15:0] */
1951#define WM8993_EQ_B3_B_WIDTH 16 /* EQ_B3_B - [15:0] */
1952
1953/*
1954 * R113 (0x71) - EQ16
1955 */
1956#define WM8993_EQ_B3_C_MASK 0xFFFF /* EQ_B3_C - [15:0] */
1957#define WM8993_EQ_B3_C_SHIFT 0 /* EQ_B3_C - [15:0] */
1958#define WM8993_EQ_B3_C_WIDTH 16 /* EQ_B3_C - [15:0] */
1959
1960/*
1961 * R114 (0x72) - EQ17
1962 */
1963#define WM8993_EQ_B3_PG_MASK 0xFFFF /* EQ_B3_PG - [15:0] */
1964#define WM8993_EQ_B3_PG_SHIFT 0 /* EQ_B3_PG - [15:0] */
1965#define WM8993_EQ_B3_PG_WIDTH 16 /* EQ_B3_PG - [15:0] */
1966
1967/*
1968 * R115 (0x73) - EQ18
1969 */
1970#define WM8993_EQ_B4_A_MASK 0xFFFF /* EQ_B4_A - [15:0] */
1971#define WM8993_EQ_B4_A_SHIFT 0 /* EQ_B4_A - [15:0] */
1972#define WM8993_EQ_B4_A_WIDTH 16 /* EQ_B4_A - [15:0] */
1973
1974/*
1975 * R116 (0x74) - EQ19
1976 */
1977#define WM8993_EQ_B4_B_MASK 0xFFFF /* EQ_B4_B - [15:0] */
1978#define WM8993_EQ_B4_B_SHIFT 0 /* EQ_B4_B - [15:0] */
1979#define WM8993_EQ_B4_B_WIDTH 16 /* EQ_B4_B - [15:0] */
1980
1981/*
1982 * R117 (0x75) - EQ20
1983 */
1984#define WM8993_EQ_B4_C_MASK 0xFFFF /* EQ_B4_C - [15:0] */
1985#define WM8993_EQ_B4_C_SHIFT 0 /* EQ_B4_C - [15:0] */
1986#define WM8993_EQ_B4_C_WIDTH 16 /* EQ_B4_C - [15:0] */
1987
1988/*
1989 * R118 (0x76) - EQ21
1990 */
1991#define WM8993_EQ_B4_PG_MASK 0xFFFF /* EQ_B4_PG - [15:0] */
1992#define WM8993_EQ_B4_PG_SHIFT 0 /* EQ_B4_PG - [15:0] */
1993#define WM8993_EQ_B4_PG_WIDTH 16 /* EQ_B4_PG - [15:0] */
1994
1995/*
1996 * R119 (0x77) - EQ22
1997 */
1998#define WM8993_EQ_B5_A_MASK 0xFFFF /* EQ_B5_A - [15:0] */
1999#define WM8993_EQ_B5_A_SHIFT 0 /* EQ_B5_A - [15:0] */
2000#define WM8993_EQ_B5_A_WIDTH 16 /* EQ_B5_A - [15:0] */
2001
2002/*
2003 * R120 (0x78) - EQ23
2004 */
2005#define WM8993_EQ_B5_B_MASK 0xFFFF /* EQ_B5_B - [15:0] */
2006#define WM8993_EQ_B5_B_SHIFT 0 /* EQ_B5_B - [15:0] */
2007#define WM8993_EQ_B5_B_WIDTH 16 /* EQ_B5_B - [15:0] */
2008
2009/*
2010 * R121 (0x79) - EQ24
2011 */
2012#define WM8993_EQ_B5_PG_MASK 0xFFFF /* EQ_B5_PG - [15:0] */
2013#define WM8993_EQ_B5_PG_SHIFT 0 /* EQ_B5_PG - [15:0] */
2014#define WM8993_EQ_B5_PG_WIDTH 16 /* EQ_B5_PG - [15:0] */
2015
2016/*
2017 * R122 (0x7A) - Digital Pulls
2018 */
2019#define WM8993_MCLK_PU 0x0080 /* MCLK_PU */
2020#define WM8993_MCLK_PU_MASK 0x0080 /* MCLK_PU */
2021#define WM8993_MCLK_PU_SHIFT 7 /* MCLK_PU */
2022#define WM8993_MCLK_PU_WIDTH 1 /* MCLK_PU */
2023#define WM8993_MCLK_PD 0x0040 /* MCLK_PD */
2024#define WM8993_MCLK_PD_MASK 0x0040 /* MCLK_PD */
2025#define WM8993_MCLK_PD_SHIFT 6 /* MCLK_PD */
2026#define WM8993_MCLK_PD_WIDTH 1 /* MCLK_PD */
2027#define WM8993_DACDAT_PU 0x0020 /* DACDAT_PU */
2028#define WM8993_DACDAT_PU_MASK 0x0020 /* DACDAT_PU */
2029#define WM8993_DACDAT_PU_SHIFT 5 /* DACDAT_PU */
2030#define WM8993_DACDAT_PU_WIDTH 1 /* DACDAT_PU */
2031#define WM8993_DACDAT_PD 0x0010 /* DACDAT_PD */
2032#define WM8993_DACDAT_PD_MASK 0x0010 /* DACDAT_PD */
2033#define WM8993_DACDAT_PD_SHIFT 4 /* DACDAT_PD */
2034#define WM8993_DACDAT_PD_WIDTH 1 /* DACDAT_PD */
2035#define WM8993_LRCLK_PU 0x0008 /* LRCLK_PU */
2036#define WM8993_LRCLK_PU_MASK 0x0008 /* LRCLK_PU */
2037#define WM8993_LRCLK_PU_SHIFT 3 /* LRCLK_PU */
2038#define WM8993_LRCLK_PU_WIDTH 1 /* LRCLK_PU */
2039#define WM8993_LRCLK_PD 0x0004 /* LRCLK_PD */
2040#define WM8993_LRCLK_PD_MASK 0x0004 /* LRCLK_PD */
2041#define WM8993_LRCLK_PD_SHIFT 2 /* LRCLK_PD */
2042#define WM8993_LRCLK_PD_WIDTH 1 /* LRCLK_PD */
2043#define WM8993_BCLK_PU 0x0002 /* BCLK_PU */
2044#define WM8993_BCLK_PU_MASK 0x0002 /* BCLK_PU */
2045#define WM8993_BCLK_PU_SHIFT 1 /* BCLK_PU */
2046#define WM8993_BCLK_PU_WIDTH 1 /* BCLK_PU */
2047#define WM8993_BCLK_PD 0x0001 /* BCLK_PD */
2048#define WM8993_BCLK_PD_MASK 0x0001 /* BCLK_PD */
2049#define WM8993_BCLK_PD_SHIFT 0 /* BCLK_PD */
2050#define WM8993_BCLK_PD_WIDTH 1 /* BCLK_PD */
2051
2052/*
2053 * R123 (0x7B) - DRC Control 1
2054 */
2055#define WM8993_DRC_ENA 0x8000 /* DRC_ENA */
2056#define WM8993_DRC_ENA_MASK 0x8000 /* DRC_ENA */
2057#define WM8993_DRC_ENA_SHIFT 15 /* DRC_ENA */
2058#define WM8993_DRC_ENA_WIDTH 1 /* DRC_ENA */
2059#define WM8993_DRC_DAC_PATH 0x4000 /* DRC_DAC_PATH */
2060#define WM8993_DRC_DAC_PATH_MASK 0x4000 /* DRC_DAC_PATH */
2061#define WM8993_DRC_DAC_PATH_SHIFT 14 /* DRC_DAC_PATH */
2062#define WM8993_DRC_DAC_PATH_WIDTH 1 /* DRC_DAC_PATH */
2063#define WM8993_DRC_SMOOTH_ENA 0x0800 /* DRC_SMOOTH_ENA */
2064#define WM8993_DRC_SMOOTH_ENA_MASK 0x0800 /* DRC_SMOOTH_ENA */
2065#define WM8993_DRC_SMOOTH_ENA_SHIFT 11 /* DRC_SMOOTH_ENA */
2066#define WM8993_DRC_SMOOTH_ENA_WIDTH 1 /* DRC_SMOOTH_ENA */
2067#define WM8993_DRC_QR_ENA 0x0400 /* DRC_QR_ENA */
2068#define WM8993_DRC_QR_ENA_MASK 0x0400 /* DRC_QR_ENA */
2069#define WM8993_DRC_QR_ENA_SHIFT 10 /* DRC_QR_ENA */
2070#define WM8993_DRC_QR_ENA_WIDTH 1 /* DRC_QR_ENA */
2071#define WM8993_DRC_ANTICLIP_ENA 0x0200 /* DRC_ANTICLIP_ENA */
2072#define WM8993_DRC_ANTICLIP_ENA_MASK 0x0200 /* DRC_ANTICLIP_ENA */
2073#define WM8993_DRC_ANTICLIP_ENA_SHIFT 9 /* DRC_ANTICLIP_ENA */
2074#define WM8993_DRC_ANTICLIP_ENA_WIDTH 1 /* DRC_ANTICLIP_ENA */
2075#define WM8993_DRC_HYST_ENA 0x0100 /* DRC_HYST_ENA */
2076#define WM8993_DRC_HYST_ENA_MASK 0x0100 /* DRC_HYST_ENA */
2077#define WM8993_DRC_HYST_ENA_SHIFT 8 /* DRC_HYST_ENA */
2078#define WM8993_DRC_HYST_ENA_WIDTH 1 /* DRC_HYST_ENA */
2079#define WM8993_DRC_THRESH_HYST_MASK 0x0030 /* DRC_THRESH_HYST - [5:4] */
2080#define WM8993_DRC_THRESH_HYST_SHIFT 4 /* DRC_THRESH_HYST - [5:4] */
2081#define WM8993_DRC_THRESH_HYST_WIDTH 2 /* DRC_THRESH_HYST - [5:4] */
2082#define WM8993_DRC_MINGAIN_MASK 0x000C /* DRC_MINGAIN - [3:2] */
2083#define WM8993_DRC_MINGAIN_SHIFT 2 /* DRC_MINGAIN - [3:2] */
2084#define WM8993_DRC_MINGAIN_WIDTH 2 /* DRC_MINGAIN - [3:2] */
2085#define WM8993_DRC_MAXGAIN_MASK 0x0003 /* DRC_MAXGAIN - [1:0] */
2086#define WM8993_DRC_MAXGAIN_SHIFT 0 /* DRC_MAXGAIN - [1:0] */
2087#define WM8993_DRC_MAXGAIN_WIDTH 2 /* DRC_MAXGAIN - [1:0] */
2088
2089/*
2090 * R124 (0x7C) - DRC Control 2
2091 */
2092#define WM8993_DRC_ATTACK_RATE_MASK 0xF000 /* DRC_ATTACK_RATE - [15:12] */
2093#define WM8993_DRC_ATTACK_RATE_SHIFT 12 /* DRC_ATTACK_RATE - [15:12] */
2094#define WM8993_DRC_ATTACK_RATE_WIDTH 4 /* DRC_ATTACK_RATE - [15:12] */
2095#define WM8993_DRC_DECAY_RATE_MASK 0x0F00 /* DRC_DECAY_RATE - [11:8] */
2096#define WM8993_DRC_DECAY_RATE_SHIFT 8 /* DRC_DECAY_RATE - [11:8] */
2097#define WM8993_DRC_DECAY_RATE_WIDTH 4 /* DRC_DECAY_RATE - [11:8] */
2098#define WM8993_DRC_THRESH_COMP_MASK 0x00FC /* DRC_THRESH_COMP - [7:2] */
2099#define WM8993_DRC_THRESH_COMP_SHIFT 2 /* DRC_THRESH_COMP - [7:2] */
2100#define WM8993_DRC_THRESH_COMP_WIDTH 6 /* DRC_THRESH_COMP - [7:2] */
2101
2102/*
2103 * R125 (0x7D) - DRC Control 3
2104 */
2105#define WM8993_DRC_AMP_COMP_MASK 0xF800 /* DRC_AMP_COMP - [15:11] */
2106#define WM8993_DRC_AMP_COMP_SHIFT 11 /* DRC_AMP_COMP - [15:11] */
2107#define WM8993_DRC_AMP_COMP_WIDTH 5 /* DRC_AMP_COMP - [15:11] */
2108#define WM8993_DRC_R0_SLOPE_COMP_MASK 0x0700 /* DRC_R0_SLOPE_COMP - [10:8] */
2109#define WM8993_DRC_R0_SLOPE_COMP_SHIFT 8 /* DRC_R0_SLOPE_COMP - [10:8] */
2110#define WM8993_DRC_R0_SLOPE_COMP_WIDTH 3 /* DRC_R0_SLOPE_COMP - [10:8] */
2111#define WM8993_DRC_FF_DELAY 0x0080 /* DRC_FF_DELAY */
2112#define WM8993_DRC_FF_DELAY_MASK 0x0080 /* DRC_FF_DELAY */
2113#define WM8993_DRC_FF_DELAY_SHIFT 7 /* DRC_FF_DELAY */
2114#define WM8993_DRC_FF_DELAY_WIDTH 1 /* DRC_FF_DELAY */
2115#define WM8993_DRC_THRESH_QR_MASK 0x000C /* DRC_THRESH_QR - [3:2] */
2116#define WM8993_DRC_THRESH_QR_SHIFT 2 /* DRC_THRESH_QR - [3:2] */
2117#define WM8993_DRC_THRESH_QR_WIDTH 2 /* DRC_THRESH_QR - [3:2] */
2118#define WM8993_DRC_RATE_QR_MASK 0x0003 /* DRC_RATE_QR - [1:0] */
2119#define WM8993_DRC_RATE_QR_SHIFT 0 /* DRC_RATE_QR - [1:0] */
2120#define WM8993_DRC_RATE_QR_WIDTH 2 /* DRC_RATE_QR - [1:0] */
2121
2122/*
2123 * R126 (0x7E) - DRC Control 4
2124 */
2125#define WM8993_DRC_R1_SLOPE_COMP_MASK 0xE000 /* DRC_R1_SLOPE_COMP - [15:13] */
2126#define WM8993_DRC_R1_SLOPE_COMP_SHIFT 13 /* DRC_R1_SLOPE_COMP - [15:13] */
2127#define WM8993_DRC_R1_SLOPE_COMP_WIDTH 3 /* DRC_R1_SLOPE_COMP - [15:13] */
2128#define WM8993_DRC_STARTUP_GAIN_MASK 0x1F00 /* DRC_STARTUP_GAIN - [12:8] */
2129#define WM8993_DRC_STARTUP_GAIN_SHIFT 8 /* DRC_STARTUP_GAIN - [12:8] */
2130#define WM8993_DRC_STARTUP_GAIN_WIDTH 5 /* DRC_STARTUP_GAIN - [12:8] */
2131
2132#endif
diff --git a/sound/soc/codecs/wm9081.c b/sound/soc/codecs/wm9081.c
new file mode 100644
index 000000000000..c64e55aa63b6
--- /dev/null
+++ b/sound/soc/codecs/wm9081.c
@@ -0,0 +1,1511 @@
1/*
2 * wm9081.c -- WM9081 ALSA SoC Audio driver
3 *
4 * Author: Mark Brown
5 *
6 * Copyright 2009 Wolfson Microelectronics plc
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License version 2 as
10 * published by the Free Software Foundation.
11 *
12 */
13
14#include <linux/module.h>
15#include <linux/moduleparam.h>
16#include <linux/init.h>
17#include <linux/delay.h>
18#include <linux/pm.h>
19#include <linux/i2c.h>
20#include <linux/platform_device.h>
21#include <sound/core.h>
22#include <sound/pcm.h>
23#include <sound/pcm_params.h>
24#include <sound/soc.h>
25#include <sound/soc-dapm.h>
26#include <sound/initval.h>
27#include <sound/tlv.h>
28
29#include <sound/wm9081.h>
30#include "wm9081.h"
31
32static u16 wm9081_reg_defaults[] = {
33 0x0000, /* R0 - Software Reset */
34 0x0000, /* R1 */
35 0x00B9, /* R2 - Analogue Lineout */
36 0x00B9, /* R3 - Analogue Speaker PGA */
37 0x0001, /* R4 - VMID Control */
38 0x0068, /* R5 - Bias Control 1 */
39 0x0000, /* R6 */
40 0x0000, /* R7 - Analogue Mixer */
41 0x0000, /* R8 - Anti Pop Control */
42 0x01DB, /* R9 - Analogue Speaker 1 */
43 0x0018, /* R10 - Analogue Speaker 2 */
44 0x0180, /* R11 - Power Management */
45 0x0000, /* R12 - Clock Control 1 */
46 0x0038, /* R13 - Clock Control 2 */
47 0x4000, /* R14 - Clock Control 3 */
48 0x0000, /* R15 */
49 0x0000, /* R16 - FLL Control 1 */
50 0x0200, /* R17 - FLL Control 2 */
51 0x0000, /* R18 - FLL Control 3 */
52 0x0204, /* R19 - FLL Control 4 */
53 0x0000, /* R20 - FLL Control 5 */
54 0x0000, /* R21 */
55 0x0000, /* R22 - Audio Interface 1 */
56 0x0002, /* R23 - Audio Interface 2 */
57 0x0008, /* R24 - Audio Interface 3 */
58 0x0022, /* R25 - Audio Interface 4 */
59 0x0000, /* R26 - Interrupt Status */
60 0x0006, /* R27 - Interrupt Status Mask */
61 0x0000, /* R28 - Interrupt Polarity */
62 0x0000, /* R29 - Interrupt Control */
63 0x00C0, /* R30 - DAC Digital 1 */
64 0x0008, /* R31 - DAC Digital 2 */
65 0x09AF, /* R32 - DRC 1 */
66 0x4201, /* R33 - DRC 2 */
67 0x0000, /* R34 - DRC 3 */
68 0x0000, /* R35 - DRC 4 */
69 0x0000, /* R36 */
70 0x0000, /* R37 */
71 0x0000, /* R38 - Write Sequencer 1 */
72 0x0000, /* R39 - Write Sequencer 2 */
73 0x0002, /* R40 - MW Slave 1 */
74 0x0000, /* R41 */
75 0x0000, /* R42 - EQ 1 */
76 0x0000, /* R43 - EQ 2 */
77 0x0FCA, /* R44 - EQ 3 */
78 0x0400, /* R45 - EQ 4 */
79 0x00B8, /* R46 - EQ 5 */
80 0x1EB5, /* R47 - EQ 6 */
81 0xF145, /* R48 - EQ 7 */
82 0x0B75, /* R49 - EQ 8 */
83 0x01C5, /* R50 - EQ 9 */
84 0x169E, /* R51 - EQ 10 */
85 0xF829, /* R52 - EQ 11 */
86 0x07AD, /* R53 - EQ 12 */
87 0x1103, /* R54 - EQ 13 */
88 0x1C58, /* R55 - EQ 14 */
89 0xF373, /* R56 - EQ 15 */
90 0x0A54, /* R57 - EQ 16 */
91 0x0558, /* R58 - EQ 17 */
92 0x0564, /* R59 - EQ 18 */
93 0x0559, /* R60 - EQ 19 */
94 0x4000, /* R61 - EQ 20 */
95};
96
97static struct {
98 int ratio;
99 int clk_sys_rate;
100} clk_sys_rates[] = {
101 { 64, 0 },
102 { 128, 1 },
103 { 192, 2 },
104 { 256, 3 },
105 { 384, 4 },
106 { 512, 5 },
107 { 768, 6 },
108 { 1024, 7 },
109 { 1408, 8 },
110 { 1536, 9 },
111};
112
113static struct {
114 int rate;
115 int sample_rate;
116} sample_rates[] = {
117 { 8000, 0 },
118 { 11025, 1 },
119 { 12000, 2 },
120 { 16000, 3 },
121 { 22050, 4 },
122 { 24000, 5 },
123 { 32000, 6 },
124 { 44100, 7 },
125 { 48000, 8 },
126 { 88200, 9 },
127 { 96000, 10 },
128};
129
130static struct {
131 int div; /* *10 due to .5s */
132 int bclk_div;
133} bclk_divs[] = {
134 { 10, 0 },
135 { 15, 1 },
136 { 20, 2 },
137 { 30, 3 },
138 { 40, 4 },
139 { 50, 5 },
140 { 55, 6 },
141 { 60, 7 },
142 { 80, 8 },
143 { 100, 9 },
144 { 110, 10 },
145 { 120, 11 },
146 { 160, 12 },
147 { 200, 13 },
148 { 220, 14 },
149 { 240, 15 },
150 { 250, 16 },
151 { 300, 17 },
152 { 320, 18 },
153 { 440, 19 },
154 { 480, 20 },
155};
156
157struct wm9081_priv {
158 struct snd_soc_codec codec;
159 u16 reg_cache[WM9081_MAX_REGISTER + 1];
160 int sysclk_source;
161 int mclk_rate;
162 int sysclk_rate;
163 int fs;
164 int bclk;
165 int master;
166 int fll_fref;
167 int fll_fout;
168 int tdm_width;
169 struct wm9081_retune_mobile_config *retune;
170};
171
172static int wm9081_volatile_register(unsigned int reg)
173{
174 switch (reg) {
175 case WM9081_SOFTWARE_RESET:
176 return 1;
177 default:
178 return 0;
179 }
180}
181
182static int wm9081_reset(struct snd_soc_codec *codec)
183{
184 return snd_soc_write(codec, WM9081_SOFTWARE_RESET, 0);
185}
186
187static const DECLARE_TLV_DB_SCALE(drc_in_tlv, -4500, 75, 0);
188static const DECLARE_TLV_DB_SCALE(drc_out_tlv, -2250, 75, 0);
189static const DECLARE_TLV_DB_SCALE(drc_min_tlv, -1800, 600, 0);
190static unsigned int drc_max_tlv[] = {
191 TLV_DB_RANGE_HEAD(4),
192 0, 0, TLV_DB_SCALE_ITEM(1200, 0, 0),
193 1, 1, TLV_DB_SCALE_ITEM(1800, 0, 0),
194 2, 2, TLV_DB_SCALE_ITEM(2400, 0, 0),
195 3, 3, TLV_DB_SCALE_ITEM(3600, 0, 0),
196};
197static const DECLARE_TLV_DB_SCALE(drc_qr_tlv, 1200, 600, 0);
198static const DECLARE_TLV_DB_SCALE(drc_startup_tlv, -300, 50, 0);
199
200static const DECLARE_TLV_DB_SCALE(eq_tlv, -1200, 100, 0);
201
202static const DECLARE_TLV_DB_SCALE(in_tlv, -600, 600, 0);
203static const DECLARE_TLV_DB_SCALE(dac_tlv, -7200, 75, 1);
204static const DECLARE_TLV_DB_SCALE(out_tlv, -5700, 100, 0);
205
206static const char *drc_high_text[] = {
207 "1",
208 "1/2",
209 "1/4",
210 "1/8",
211 "1/16",
212 "0",
213};
214
215static const struct soc_enum drc_high =
216 SOC_ENUM_SINGLE(WM9081_DRC_3, 3, 6, drc_high_text);
217
218static const char *drc_low_text[] = {
219 "1",
220 "1/2",
221 "1/4",
222 "1/8",
223 "0",
224};
225
226static const struct soc_enum drc_low =
227 SOC_ENUM_SINGLE(WM9081_DRC_3, 0, 5, drc_low_text);
228
229static const char *drc_atk_text[] = {
230 "181us",
231 "181us",
232 "363us",
233 "726us",
234 "1.45ms",
235 "2.9ms",
236 "5.8ms",
237 "11.6ms",
238 "23.2ms",
239 "46.4ms",
240 "92.8ms",
241 "185.6ms",
242};
243
244static const struct soc_enum drc_atk =
245 SOC_ENUM_SINGLE(WM9081_DRC_2, 12, 12, drc_atk_text);
246
247static const char *drc_dcy_text[] = {
248 "186ms",
249 "372ms",
250 "743ms",
251 "1.49s",
252 "2.97s",
253 "5.94s",
254 "11.89s",
255 "23.78s",
256 "47.56s",
257};
258
259static const struct soc_enum drc_dcy =
260 SOC_ENUM_SINGLE(WM9081_DRC_2, 8, 9, drc_dcy_text);
261
262static const char *drc_qr_dcy_text[] = {
263 "0.725ms",
264 "1.45ms",
265 "5.8ms",
266};
267
268static const struct soc_enum drc_qr_dcy =
269 SOC_ENUM_SINGLE(WM9081_DRC_2, 4, 3, drc_qr_dcy_text);
270
271static const char *dac_deemph_text[] = {
272 "None",
273 "32kHz",
274 "44.1kHz",
275 "48kHz",
276};
277
278static const struct soc_enum dac_deemph =
279 SOC_ENUM_SINGLE(WM9081_DAC_DIGITAL_2, 1, 4, dac_deemph_text);
280
281static const char *speaker_mode_text[] = {
282 "Class D",
283 "Class AB",
284};
285
286static const struct soc_enum speaker_mode =
287 SOC_ENUM_SINGLE(WM9081_ANALOGUE_SPEAKER_2, 6, 2, speaker_mode_text);
288
289static int speaker_mode_get(struct snd_kcontrol *kcontrol,
290 struct snd_ctl_elem_value *ucontrol)
291{
292 struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
293 unsigned int reg;
294
295 reg = snd_soc_read(codec, WM9081_ANALOGUE_SPEAKER_2);
296 if (reg & WM9081_SPK_MODE)
297 ucontrol->value.integer.value[0] = 1;
298 else
299 ucontrol->value.integer.value[0] = 0;
300
301 return 0;
302}
303
304/*
305 * Stop any attempts to change speaker mode while the speaker is enabled.
306 *
307 * We also have some special anti-pop controls dependant on speaker
308 * mode which must be changed along with the mode.
309 */
310static int speaker_mode_put(struct snd_kcontrol *kcontrol,
311 struct snd_ctl_elem_value *ucontrol)
312{
313 struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
314 unsigned int reg_pwr = snd_soc_read(codec, WM9081_POWER_MANAGEMENT);
315 unsigned int reg2 = snd_soc_read(codec, WM9081_ANALOGUE_SPEAKER_2);
316
317 /* Are we changing anything? */
318 if (ucontrol->value.integer.value[0] ==
319 ((reg2 & WM9081_SPK_MODE) != 0))
320 return 0;
321
322 /* Don't try to change modes while enabled */
323 if (reg_pwr & WM9081_SPK_ENA)
324 return -EINVAL;
325
326 if (ucontrol->value.integer.value[0]) {
327 /* Class AB */
328 reg2 &= ~(WM9081_SPK_INV_MUTE | WM9081_OUT_SPK_CTRL);
329 reg2 |= WM9081_SPK_MODE;
330 } else {
331 /* Class D */
332 reg2 |= WM9081_SPK_INV_MUTE | WM9081_OUT_SPK_CTRL;
333 reg2 &= ~WM9081_SPK_MODE;
334 }
335
336 snd_soc_write(codec, WM9081_ANALOGUE_SPEAKER_2, reg2);
337
338 return 0;
339}
340
341static const struct snd_kcontrol_new wm9081_snd_controls[] = {
342SOC_SINGLE_TLV("IN1 Volume", WM9081_ANALOGUE_MIXER, 1, 1, 1, in_tlv),
343SOC_SINGLE_TLV("IN2 Volume", WM9081_ANALOGUE_MIXER, 3, 1, 1, in_tlv),
344
345SOC_SINGLE_TLV("Playback Volume", WM9081_DAC_DIGITAL_1, 1, 96, 0, dac_tlv),
346
347SOC_SINGLE("LINEOUT Switch", WM9081_ANALOGUE_LINEOUT, 7, 1, 1),
348SOC_SINGLE("LINEOUT ZC Switch", WM9081_ANALOGUE_LINEOUT, 6, 1, 0),
349SOC_SINGLE_TLV("LINEOUT Volume", WM9081_ANALOGUE_LINEOUT, 0, 63, 0, out_tlv),
350
351SOC_SINGLE("DRC Switch", WM9081_DRC_1, 15, 1, 0),
352SOC_ENUM("DRC High Slope", drc_high),
353SOC_ENUM("DRC Low Slope", drc_low),
354SOC_SINGLE_TLV("DRC Input Volume", WM9081_DRC_4, 5, 60, 1, drc_in_tlv),
355SOC_SINGLE_TLV("DRC Output Volume", WM9081_DRC_4, 0, 30, 1, drc_out_tlv),
356SOC_SINGLE_TLV("DRC Minimum Volume", WM9081_DRC_2, 2, 3, 1, drc_min_tlv),
357SOC_SINGLE_TLV("DRC Maximum Volume", WM9081_DRC_2, 0, 3, 0, drc_max_tlv),
358SOC_ENUM("DRC Attack", drc_atk),
359SOC_ENUM("DRC Decay", drc_dcy),
360SOC_SINGLE("DRC Quick Release Switch", WM9081_DRC_1, 2, 1, 0),
361SOC_SINGLE_TLV("DRC Quick Release Volume", WM9081_DRC_2, 6, 3, 0, drc_qr_tlv),
362SOC_ENUM("DRC Quick Release Decay", drc_qr_dcy),
363SOC_SINGLE_TLV("DRC Startup Volume", WM9081_DRC_1, 6, 18, 0, drc_startup_tlv),
364
365SOC_SINGLE("EQ Switch", WM9081_EQ_1, 0, 1, 0),
366
367SOC_SINGLE("Speaker DC Volume", WM9081_ANALOGUE_SPEAKER_1, 3, 5, 0),
368SOC_SINGLE("Speaker AC Volume", WM9081_ANALOGUE_SPEAKER_1, 0, 5, 0),
369SOC_SINGLE("Speaker Switch", WM9081_ANALOGUE_SPEAKER_PGA, 7, 1, 1),
370SOC_SINGLE("Speaker ZC Switch", WM9081_ANALOGUE_SPEAKER_PGA, 6, 1, 0),
371SOC_SINGLE_TLV("Speaker Volume", WM9081_ANALOGUE_SPEAKER_PGA, 0, 63, 0,
372 out_tlv),
373SOC_ENUM("DAC Deemphasis", dac_deemph),
374SOC_ENUM_EXT("Speaker Mode", speaker_mode, speaker_mode_get, speaker_mode_put),
375};
376
377static const struct snd_kcontrol_new wm9081_eq_controls[] = {
378SOC_SINGLE_TLV("EQ1 Volume", WM9081_EQ_1, 11, 24, 0, eq_tlv),
379SOC_SINGLE_TLV("EQ2 Volume", WM9081_EQ_1, 6, 24, 0, eq_tlv),
380SOC_SINGLE_TLV("EQ3 Volume", WM9081_EQ_1, 1, 24, 0, eq_tlv),
381SOC_SINGLE_TLV("EQ4 Volume", WM9081_EQ_2, 11, 24, 0, eq_tlv),
382SOC_SINGLE_TLV("EQ5 Volume", WM9081_EQ_2, 6, 24, 0, eq_tlv),
383};
384
385static const struct snd_kcontrol_new mixer[] = {
386SOC_DAPM_SINGLE("IN1 Switch", WM9081_ANALOGUE_MIXER, 0, 1, 0),
387SOC_DAPM_SINGLE("IN2 Switch", WM9081_ANALOGUE_MIXER, 2, 1, 0),
388SOC_DAPM_SINGLE("Playback Switch", WM9081_ANALOGUE_MIXER, 4, 1, 0),
389};
390
391static int speaker_event(struct snd_soc_dapm_widget *w,
392 struct snd_kcontrol *kcontrol, int event)
393{
394 struct snd_soc_codec *codec = w->codec;
395 unsigned int reg = snd_soc_read(codec, WM9081_POWER_MANAGEMENT);
396
397 switch (event) {
398 case SND_SOC_DAPM_POST_PMU:
399 reg |= WM9081_SPK_ENA;
400 break;
401
402 case SND_SOC_DAPM_PRE_PMD:
403 reg &= ~WM9081_SPK_ENA;
404 break;
405 }
406
407 snd_soc_write(codec, WM9081_POWER_MANAGEMENT, reg);
408
409 return 0;
410}
411
412struct _fll_div {
413 u16 fll_fratio;
414 u16 fll_outdiv;
415 u16 fll_clk_ref_div;
416 u16 n;
417 u16 k;
418};
419
420/* The size in bits of the FLL divide multiplied by 10
421 * to allow rounding later */
422#define FIXED_FLL_SIZE ((1 << 16) * 10)
423
424static struct {
425 unsigned int min;
426 unsigned int max;
427 u16 fll_fratio;
428 int ratio;
429} fll_fratios[] = {
430 { 0, 64000, 4, 16 },
431 { 64000, 128000, 3, 8 },
432 { 128000, 256000, 2, 4 },
433 { 256000, 1000000, 1, 2 },
434 { 1000000, 13500000, 0, 1 },
435};
436
437static int fll_factors(struct _fll_div *fll_div, unsigned int Fref,
438 unsigned int Fout)
439{
440 u64 Kpart;
441 unsigned int K, Ndiv, Nmod, target;
442 unsigned int div;
443 int i;
444
445 /* Fref must be <=13.5MHz */
446 div = 1;
447 while ((Fref / div) > 13500000) {
448 div *= 2;
449
450 if (div > 8) {
451 pr_err("Can't scale %dMHz input down to <=13.5MHz\n",
452 Fref);
453 return -EINVAL;
454 }
455 }
456 fll_div->fll_clk_ref_div = div / 2;
457
458 pr_debug("Fref=%u Fout=%u\n", Fref, Fout);
459
460 /* Apply the division for our remaining calculations */
461 Fref /= div;
462
463 /* Fvco should be 90-100MHz; don't check the upper bound */
464 div = 0;
465 target = Fout * 2;
466 while (target < 90000000) {
467 div++;
468 target *= 2;
469 if (div > 7) {
470 pr_err("Unable to find FLL_OUTDIV for Fout=%uHz\n",
471 Fout);
472 return -EINVAL;
473 }
474 }
475 fll_div->fll_outdiv = div;
476
477 pr_debug("Fvco=%dHz\n", target);
478
479 /* Find an appropraite FLL_FRATIO and factor it out of the target */
480 for (i = 0; i < ARRAY_SIZE(fll_fratios); i++) {
481 if (fll_fratios[i].min <= Fref && Fref <= fll_fratios[i].max) {
482 fll_div->fll_fratio = fll_fratios[i].fll_fratio;
483 target /= fll_fratios[i].ratio;
484 break;
485 }
486 }
487 if (i == ARRAY_SIZE(fll_fratios)) {
488 pr_err("Unable to find FLL_FRATIO for Fref=%uHz\n", Fref);
489 return -EINVAL;
490 }
491
492 /* Now, calculate N.K */
493 Ndiv = target / Fref;
494
495 fll_div->n = Ndiv;
496 Nmod = target % Fref;
497 pr_debug("Nmod=%d\n", Nmod);
498
499 /* Calculate fractional part - scale up so we can round. */
500 Kpart = FIXED_FLL_SIZE * (long long)Nmod;
501
502 do_div(Kpart, Fref);
503
504 K = Kpart & 0xFFFFFFFF;
505
506 if ((K % 10) >= 5)
507 K += 5;
508
509 /* Move down to proper range now rounding is done */
510 fll_div->k = K / 10;
511
512 pr_debug("N=%x K=%x FLL_FRATIO=%x FLL_OUTDIV=%x FLL_CLK_REF_DIV=%x\n",
513 fll_div->n, fll_div->k,
514 fll_div->fll_fratio, fll_div->fll_outdiv,
515 fll_div->fll_clk_ref_div);
516
517 return 0;
518}
519
520static int wm9081_set_fll(struct snd_soc_codec *codec, int fll_id,
521 unsigned int Fref, unsigned int Fout)
522{
523 struct wm9081_priv *wm9081 = codec->private_data;
524 u16 reg1, reg4, reg5;
525 struct _fll_div fll_div;
526 int ret;
527 int clk_sys_reg;
528
529 /* Any change? */
530 if (Fref == wm9081->fll_fref && Fout == wm9081->fll_fout)
531 return 0;
532
533 /* Disable the FLL */
534 if (Fout == 0) {
535 dev_dbg(codec->dev, "FLL disabled\n");
536 wm9081->fll_fref = 0;
537 wm9081->fll_fout = 0;
538
539 return 0;
540 }
541
542 ret = fll_factors(&fll_div, Fref, Fout);
543 if (ret != 0)
544 return ret;
545
546 reg5 = snd_soc_read(codec, WM9081_FLL_CONTROL_5);
547 reg5 &= ~WM9081_FLL_CLK_SRC_MASK;
548
549 switch (fll_id) {
550 case WM9081_SYSCLK_FLL_MCLK:
551 reg5 |= 0x1;
552 break;
553
554 default:
555 dev_err(codec->dev, "Unknown FLL ID %d\n", fll_id);
556 return -EINVAL;
557 }
558
559 /* Disable CLK_SYS while we reconfigure */
560 clk_sys_reg = snd_soc_read(codec, WM9081_CLOCK_CONTROL_3);
561 if (clk_sys_reg & WM9081_CLK_SYS_ENA)
562 snd_soc_write(codec, WM9081_CLOCK_CONTROL_3,
563 clk_sys_reg & ~WM9081_CLK_SYS_ENA);
564
565 /* Any FLL configuration change requires that the FLL be
566 * disabled first. */
567 reg1 = snd_soc_read(codec, WM9081_FLL_CONTROL_1);
568 reg1 &= ~WM9081_FLL_ENA;
569 snd_soc_write(codec, WM9081_FLL_CONTROL_1, reg1);
570
571 /* Apply the configuration */
572 if (fll_div.k)
573 reg1 |= WM9081_FLL_FRAC_MASK;
574 else
575 reg1 &= ~WM9081_FLL_FRAC_MASK;
576 snd_soc_write(codec, WM9081_FLL_CONTROL_1, reg1);
577
578 snd_soc_write(codec, WM9081_FLL_CONTROL_2,
579 (fll_div.fll_outdiv << WM9081_FLL_OUTDIV_SHIFT) |
580 (fll_div.fll_fratio << WM9081_FLL_FRATIO_SHIFT));
581 snd_soc_write(codec, WM9081_FLL_CONTROL_3, fll_div.k);
582
583 reg4 = snd_soc_read(codec, WM9081_FLL_CONTROL_4);
584 reg4 &= ~WM9081_FLL_N_MASK;
585 reg4 |= fll_div.n << WM9081_FLL_N_SHIFT;
586 snd_soc_write(codec, WM9081_FLL_CONTROL_4, reg4);
587
588 reg5 &= ~WM9081_FLL_CLK_REF_DIV_MASK;
589 reg5 |= fll_div.fll_clk_ref_div << WM9081_FLL_CLK_REF_DIV_SHIFT;
590 snd_soc_write(codec, WM9081_FLL_CONTROL_5, reg5);
591
592 /* Enable the FLL */
593 snd_soc_write(codec, WM9081_FLL_CONTROL_1, reg1 | WM9081_FLL_ENA);
594
595 /* Then bring CLK_SYS up again if it was disabled */
596 if (clk_sys_reg & WM9081_CLK_SYS_ENA)
597 snd_soc_write(codec, WM9081_CLOCK_CONTROL_3, clk_sys_reg);
598
599 dev_dbg(codec->dev, "FLL enabled at %dHz->%dHz\n", Fref, Fout);
600
601 wm9081->fll_fref = Fref;
602 wm9081->fll_fout = Fout;
603
604 return 0;
605}
606
607static int configure_clock(struct snd_soc_codec *codec)
608{
609 struct wm9081_priv *wm9081 = codec->private_data;
610 int new_sysclk, i, target;
611 unsigned int reg;
612 int ret = 0;
613 int mclkdiv = 0;
614 int fll = 0;
615
616 switch (wm9081->sysclk_source) {
617 case WM9081_SYSCLK_MCLK:
618 if (wm9081->mclk_rate > 12225000) {
619 mclkdiv = 1;
620 wm9081->sysclk_rate = wm9081->mclk_rate / 2;
621 } else {
622 wm9081->sysclk_rate = wm9081->mclk_rate;
623 }
624 wm9081_set_fll(codec, WM9081_SYSCLK_FLL_MCLK, 0, 0);
625 break;
626
627 case WM9081_SYSCLK_FLL_MCLK:
628 /* If we have a sample rate calculate a CLK_SYS that
629 * gives us a suitable DAC configuration, plus BCLK.
630 * Ideally we would check to see if we can clock
631 * directly from MCLK and only use the FLL if this is
632 * not the case, though care must be taken with free
633 * running mode.
634 */
635 if (wm9081->master && wm9081->bclk) {
636 /* Make sure we can generate CLK_SYS and BCLK
637 * and that we've got 3MHz for optimal
638 * performance. */
639 for (i = 0; i < ARRAY_SIZE(clk_sys_rates); i++) {
640 target = wm9081->fs * clk_sys_rates[i].ratio;
641 new_sysclk = target;
642 if (target >= wm9081->bclk &&
643 target > 3000000)
644 break;
645 }
646
647 if (i == ARRAY_SIZE(clk_sys_rates))
648 return -EINVAL;
649
650 } else if (wm9081->fs) {
651 for (i = 0; i < ARRAY_SIZE(clk_sys_rates); i++) {
652 new_sysclk = clk_sys_rates[i].ratio
653 * wm9081->fs;
654 if (new_sysclk > 3000000)
655 break;
656 }
657
658 if (i == ARRAY_SIZE(clk_sys_rates))
659 return -EINVAL;
660
661 } else {
662 new_sysclk = 12288000;
663 }
664
665 ret = wm9081_set_fll(codec, WM9081_SYSCLK_FLL_MCLK,
666 wm9081->mclk_rate, new_sysclk);
667 if (ret == 0) {
668 wm9081->sysclk_rate = new_sysclk;
669
670 /* Switch SYSCLK over to FLL */
671 fll = 1;
672 } else {
673 wm9081->sysclk_rate = wm9081->mclk_rate;
674 }
675 break;
676
677 default:
678 return -EINVAL;
679 }
680
681 reg = snd_soc_read(codec, WM9081_CLOCK_CONTROL_1);
682 if (mclkdiv)
683 reg |= WM9081_MCLKDIV2;
684 else
685 reg &= ~WM9081_MCLKDIV2;
686 snd_soc_write(codec, WM9081_CLOCK_CONTROL_1, reg);
687
688 reg = snd_soc_read(codec, WM9081_CLOCK_CONTROL_3);
689 if (fll)
690 reg |= WM9081_CLK_SRC_SEL;
691 else
692 reg &= ~WM9081_CLK_SRC_SEL;
693 snd_soc_write(codec, WM9081_CLOCK_CONTROL_3, reg);
694
695 dev_dbg(codec->dev, "CLK_SYS is %dHz\n", wm9081->sysclk_rate);
696
697 return ret;
698}
699
700static int clk_sys_event(struct snd_soc_dapm_widget *w,
701 struct snd_kcontrol *kcontrol, int event)
702{
703 struct snd_soc_codec *codec = w->codec;
704 struct wm9081_priv *wm9081 = codec->private_data;
705
706 /* This should be done on init() for bypass paths */
707 switch (wm9081->sysclk_source) {
708 case WM9081_SYSCLK_MCLK:
709 dev_dbg(codec->dev, "Using %dHz MCLK\n", wm9081->mclk_rate);
710 break;
711 case WM9081_SYSCLK_FLL_MCLK:
712 dev_dbg(codec->dev, "Using %dHz MCLK with FLL\n",
713 wm9081->mclk_rate);
714 break;
715 default:
716 dev_err(codec->dev, "System clock not configured\n");
717 return -EINVAL;
718 }
719
720 switch (event) {
721 case SND_SOC_DAPM_PRE_PMU:
722 configure_clock(codec);
723 break;
724
725 case SND_SOC_DAPM_POST_PMD:
726 /* Disable the FLL if it's running */
727 wm9081_set_fll(codec, 0, 0, 0);
728 break;
729 }
730
731 return 0;
732}
733
734static const struct snd_soc_dapm_widget wm9081_dapm_widgets[] = {
735SND_SOC_DAPM_INPUT("IN1"),
736SND_SOC_DAPM_INPUT("IN2"),
737
738SND_SOC_DAPM_DAC("DAC", "HiFi Playback", WM9081_POWER_MANAGEMENT, 0, 0),
739
740SND_SOC_DAPM_MIXER_NAMED_CTL("Mixer", SND_SOC_NOPM, 0, 0,
741 mixer, ARRAY_SIZE(mixer)),
742
743SND_SOC_DAPM_PGA("LINEOUT PGA", WM9081_POWER_MANAGEMENT, 4, 0, NULL, 0),
744
745SND_SOC_DAPM_PGA_E("Speaker PGA", WM9081_POWER_MANAGEMENT, 2, 0, NULL, 0,
746 speaker_event,
747 SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD),
748
749SND_SOC_DAPM_OUTPUT("LINEOUT"),
750SND_SOC_DAPM_OUTPUT("SPKN"),
751SND_SOC_DAPM_OUTPUT("SPKP"),
752
753SND_SOC_DAPM_SUPPLY("CLK_SYS", WM9081_CLOCK_CONTROL_3, 0, 0, clk_sys_event,
754 SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
755SND_SOC_DAPM_SUPPLY("CLK_DSP", WM9081_CLOCK_CONTROL_3, 1, 0, NULL, 0),
756SND_SOC_DAPM_SUPPLY("TOCLK", WM9081_CLOCK_CONTROL_3, 2, 0, NULL, 0),
757};
758
759
760static const struct snd_soc_dapm_route audio_paths[] = {
761 { "DAC", NULL, "CLK_SYS" },
762 { "DAC", NULL, "CLK_DSP" },
763
764 { "Mixer", "IN1 Switch", "IN1" },
765 { "Mixer", "IN2 Switch", "IN2" },
766 { "Mixer", "Playback Switch", "DAC" },
767
768 { "LINEOUT PGA", NULL, "Mixer" },
769 { "LINEOUT PGA", NULL, "TOCLK" },
770 { "LINEOUT PGA", NULL, "CLK_SYS" },
771
772 { "LINEOUT", NULL, "LINEOUT PGA" },
773
774 { "Speaker PGA", NULL, "Mixer" },
775 { "Speaker PGA", NULL, "TOCLK" },
776 { "Speaker PGA", NULL, "CLK_SYS" },
777
778 { "SPKN", NULL, "Speaker PGA" },
779 { "SPKP", NULL, "Speaker PGA" },
780};
781
782static int wm9081_set_bias_level(struct snd_soc_codec *codec,
783 enum snd_soc_bias_level level)
784{
785 u16 reg;
786
787 switch (level) {
788 case SND_SOC_BIAS_ON:
789 break;
790
791 case SND_SOC_BIAS_PREPARE:
792 /* VMID=2*40k */
793 reg = snd_soc_read(codec, WM9081_VMID_CONTROL);
794 reg &= ~WM9081_VMID_SEL_MASK;
795 reg |= 0x2;
796 snd_soc_write(codec, WM9081_VMID_CONTROL, reg);
797
798 /* Normal bias current */
799 reg = snd_soc_read(codec, WM9081_BIAS_CONTROL_1);
800 reg &= ~WM9081_STBY_BIAS_ENA;
801 snd_soc_write(codec, WM9081_BIAS_CONTROL_1, reg);
802 break;
803
804 case SND_SOC_BIAS_STANDBY:
805 /* Initial cold start */
806 if (codec->bias_level == SND_SOC_BIAS_OFF) {
807 /* Disable LINEOUT discharge */
808 reg = snd_soc_read(codec, WM9081_ANTI_POP_CONTROL);
809 reg &= ~WM9081_LINEOUT_DISCH;
810 snd_soc_write(codec, WM9081_ANTI_POP_CONTROL, reg);
811
812 /* Select startup bias source */
813 reg = snd_soc_read(codec, WM9081_BIAS_CONTROL_1);
814 reg |= WM9081_BIAS_SRC | WM9081_BIAS_ENA;
815 snd_soc_write(codec, WM9081_BIAS_CONTROL_1, reg);
816
817 /* VMID 2*4k; Soft VMID ramp enable */
818 reg = snd_soc_read(codec, WM9081_VMID_CONTROL);
819 reg |= WM9081_VMID_RAMP | 0x6;
820 snd_soc_write(codec, WM9081_VMID_CONTROL, reg);
821
822 mdelay(100);
823
824 /* Normal bias enable & soft start off */
825 reg |= WM9081_BIAS_ENA;
826 reg &= ~WM9081_VMID_RAMP;
827 snd_soc_write(codec, WM9081_VMID_CONTROL, reg);
828
829 /* Standard bias source */
830 reg = snd_soc_read(codec, WM9081_BIAS_CONTROL_1);
831 reg &= ~WM9081_BIAS_SRC;
832 snd_soc_write(codec, WM9081_BIAS_CONTROL_1, reg);
833 }
834
835 /* VMID 2*240k */
836 reg = snd_soc_read(codec, WM9081_BIAS_CONTROL_1);
837 reg &= ~WM9081_VMID_SEL_MASK;
838 reg |= 0x40;
839 snd_soc_write(codec, WM9081_VMID_CONTROL, reg);
840
841 /* Standby bias current on */
842 reg = snd_soc_read(codec, WM9081_BIAS_CONTROL_1);
843 reg |= WM9081_STBY_BIAS_ENA;
844 snd_soc_write(codec, WM9081_BIAS_CONTROL_1, reg);
845 break;
846
847 case SND_SOC_BIAS_OFF:
848 /* Startup bias source */
849 reg = snd_soc_read(codec, WM9081_BIAS_CONTROL_1);
850 reg |= WM9081_BIAS_SRC;
851 snd_soc_write(codec, WM9081_BIAS_CONTROL_1, reg);
852
853 /* Disable VMID and biases with soft ramping */
854 reg = snd_soc_read(codec, WM9081_VMID_CONTROL);
855 reg &= ~(WM9081_VMID_SEL_MASK | WM9081_BIAS_ENA);
856 reg |= WM9081_VMID_RAMP;
857 snd_soc_write(codec, WM9081_VMID_CONTROL, reg);
858
859 /* Actively discharge LINEOUT */
860 reg = snd_soc_read(codec, WM9081_ANTI_POP_CONTROL);
861 reg |= WM9081_LINEOUT_DISCH;
862 snd_soc_write(codec, WM9081_ANTI_POP_CONTROL, reg);
863 break;
864 }
865
866 codec->bias_level = level;
867
868 return 0;
869}
870
871static int wm9081_set_dai_fmt(struct snd_soc_dai *dai,
872 unsigned int fmt)
873{
874 struct snd_soc_codec *codec = dai->codec;
875 struct wm9081_priv *wm9081 = codec->private_data;
876 unsigned int aif2 = snd_soc_read(codec, WM9081_AUDIO_INTERFACE_2);
877
878 aif2 &= ~(WM9081_AIF_BCLK_INV | WM9081_AIF_LRCLK_INV |
879 WM9081_BCLK_DIR | WM9081_LRCLK_DIR | WM9081_AIF_FMT_MASK);
880
881 switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
882 case SND_SOC_DAIFMT_CBS_CFS:
883 wm9081->master = 0;
884 break;
885 case SND_SOC_DAIFMT_CBS_CFM:
886 aif2 |= WM9081_LRCLK_DIR;
887 wm9081->master = 1;
888 break;
889 case SND_SOC_DAIFMT_CBM_CFS:
890 aif2 |= WM9081_BCLK_DIR;
891 wm9081->master = 1;
892 break;
893 case SND_SOC_DAIFMT_CBM_CFM:
894 aif2 |= WM9081_LRCLK_DIR | WM9081_BCLK_DIR;
895 wm9081->master = 1;
896 break;
897 default:
898 return -EINVAL;
899 }
900
901 switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
902 case SND_SOC_DAIFMT_DSP_B:
903 aif2 |= WM9081_AIF_LRCLK_INV;
904 case SND_SOC_DAIFMT_DSP_A:
905 aif2 |= 0x3;
906 break;
907 case SND_SOC_DAIFMT_I2S:
908 aif2 |= 0x2;
909 break;
910 case SND_SOC_DAIFMT_RIGHT_J:
911 break;
912 case SND_SOC_DAIFMT_LEFT_J:
913 aif2 |= 0x1;
914 break;
915 default:
916 return -EINVAL;
917 }
918
919 switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
920 case SND_SOC_DAIFMT_DSP_A:
921 case SND_SOC_DAIFMT_DSP_B:
922 /* frame inversion not valid for DSP modes */
923 switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
924 case SND_SOC_DAIFMT_NB_NF:
925 break;
926 case SND_SOC_DAIFMT_IB_NF:
927 aif2 |= WM9081_AIF_BCLK_INV;
928 break;
929 default:
930 return -EINVAL;
931 }
932 break;
933
934 case SND_SOC_DAIFMT_I2S:
935 case SND_SOC_DAIFMT_RIGHT_J:
936 case SND_SOC_DAIFMT_LEFT_J:
937 switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
938 case SND_SOC_DAIFMT_NB_NF:
939 break;
940 case SND_SOC_DAIFMT_IB_IF:
941 aif2 |= WM9081_AIF_BCLK_INV | WM9081_AIF_LRCLK_INV;
942 break;
943 case SND_SOC_DAIFMT_IB_NF:
944 aif2 |= WM9081_AIF_BCLK_INV;
945 break;
946 case SND_SOC_DAIFMT_NB_IF:
947 aif2 |= WM9081_AIF_LRCLK_INV;
948 break;
949 default:
950 return -EINVAL;
951 }
952 break;
953 default:
954 return -EINVAL;
955 }
956
957 snd_soc_write(codec, WM9081_AUDIO_INTERFACE_2, aif2);
958
959 return 0;
960}
961
962static int wm9081_hw_params(struct snd_pcm_substream *substream,
963 struct snd_pcm_hw_params *params,
964 struct snd_soc_dai *dai)
965{
966 struct snd_soc_codec *codec = dai->codec;
967 struct wm9081_priv *wm9081 = codec->private_data;
968 int ret, i, best, best_val, cur_val;
969 unsigned int clk_ctrl2, aif1, aif2, aif3, aif4;
970
971 clk_ctrl2 = snd_soc_read(codec, WM9081_CLOCK_CONTROL_2);
972 clk_ctrl2 &= ~(WM9081_CLK_SYS_RATE_MASK | WM9081_SAMPLE_RATE_MASK);
973
974 aif1 = snd_soc_read(codec, WM9081_AUDIO_INTERFACE_1);
975
976 aif2 = snd_soc_read(codec, WM9081_AUDIO_INTERFACE_2);
977 aif2 &= ~WM9081_AIF_WL_MASK;
978
979 aif3 = snd_soc_read(codec, WM9081_AUDIO_INTERFACE_3);
980 aif3 &= ~WM9081_BCLK_DIV_MASK;
981
982 aif4 = snd_soc_read(codec, WM9081_AUDIO_INTERFACE_4);
983 aif4 &= ~WM9081_LRCLK_RATE_MASK;
984
985 wm9081->fs = params_rate(params);
986
987 if (wm9081->tdm_width) {
988 /* If TDM is set up then that fixes our BCLK. */
989 int slots = ((aif1 & WM9081_AIFDAC_TDM_MODE_MASK) >>
990 WM9081_AIFDAC_TDM_MODE_SHIFT) + 1;
991
992 wm9081->bclk = wm9081->fs * wm9081->tdm_width * slots;
993 } else {
994 /* Otherwise work out a BCLK from the sample size */
995 wm9081->bclk = 2 * wm9081->fs;
996
997 switch (params_format(params)) {
998 case SNDRV_PCM_FORMAT_S16_LE:
999 wm9081->bclk *= 16;
1000 break;
1001 case SNDRV_PCM_FORMAT_S20_3LE:
1002 wm9081->bclk *= 20;
1003 aif2 |= 0x4;
1004 break;
1005 case SNDRV_PCM_FORMAT_S24_LE:
1006 wm9081->bclk *= 24;
1007 aif2 |= 0x8;
1008 break;
1009 case SNDRV_PCM_FORMAT_S32_LE:
1010 wm9081->bclk *= 32;
1011 aif2 |= 0xc;
1012 break;
1013 default:
1014 return -EINVAL;
1015 }
1016 }
1017
1018 dev_dbg(codec->dev, "Target BCLK is %dHz\n", wm9081->bclk);
1019
1020 ret = configure_clock(codec);
1021 if (ret != 0)
1022 return ret;
1023
1024 /* Select nearest CLK_SYS_RATE */
1025 best = 0;
1026 best_val = abs((wm9081->sysclk_rate / clk_sys_rates[0].ratio)
1027 - wm9081->fs);
1028 for (i = 1; i < ARRAY_SIZE(clk_sys_rates); i++) {
1029 cur_val = abs((wm9081->sysclk_rate /
1030 clk_sys_rates[i].ratio) - wm9081->fs);;
1031 if (cur_val < best_val) {
1032 best = i;
1033 best_val = cur_val;
1034 }
1035 }
1036 dev_dbg(codec->dev, "Selected CLK_SYS_RATIO of %d\n",
1037 clk_sys_rates[best].ratio);
1038 clk_ctrl2 |= (clk_sys_rates[best].clk_sys_rate
1039 << WM9081_CLK_SYS_RATE_SHIFT);
1040
1041 /* SAMPLE_RATE */
1042 best = 0;
1043 best_val = abs(wm9081->fs - sample_rates[0].rate);
1044 for (i = 1; i < ARRAY_SIZE(sample_rates); i++) {
1045 /* Closest match */
1046 cur_val = abs(wm9081->fs - sample_rates[i].rate);
1047 if (cur_val < best_val) {
1048 best = i;
1049 best_val = cur_val;
1050 }
1051 }
1052 dev_dbg(codec->dev, "Selected SAMPLE_RATE of %dHz\n",
1053 sample_rates[best].rate);
1054 clk_ctrl2 |= (sample_rates[best].sample_rate
1055 << WM9081_SAMPLE_RATE_SHIFT);
1056
1057 /* BCLK_DIV */
1058 best = 0;
1059 best_val = INT_MAX;
1060 for (i = 0; i < ARRAY_SIZE(bclk_divs); i++) {
1061 cur_val = ((wm9081->sysclk_rate * 10) / bclk_divs[i].div)
1062 - wm9081->bclk;
1063 if (cur_val < 0) /* Table is sorted */
1064 break;
1065 if (cur_val < best_val) {
1066 best = i;
1067 best_val = cur_val;
1068 }
1069 }
1070 wm9081->bclk = (wm9081->sysclk_rate * 10) / bclk_divs[best].div;
1071 dev_dbg(codec->dev, "Selected BCLK_DIV of %d for %dHz BCLK\n",
1072 bclk_divs[best].div, wm9081->bclk);
1073 aif3 |= bclk_divs[best].bclk_div;
1074
1075 /* LRCLK is a simple fraction of BCLK */
1076 dev_dbg(codec->dev, "LRCLK_RATE is %d\n", wm9081->bclk / wm9081->fs);
1077 aif4 |= wm9081->bclk / wm9081->fs;
1078
1079 /* Apply a ReTune Mobile configuration if it's in use */
1080 if (wm9081->retune) {
1081 struct wm9081_retune_mobile_config *retune = wm9081->retune;
1082 struct wm9081_retune_mobile_setting *s;
1083 int eq1;
1084
1085 best = 0;
1086 best_val = abs(retune->configs[0].rate - wm9081->fs);
1087 for (i = 0; i < retune->num_configs; i++) {
1088 cur_val = abs(retune->configs[i].rate - wm9081->fs);
1089 if (cur_val < best_val) {
1090 best_val = cur_val;
1091 best = i;
1092 }
1093 }
1094 s = &retune->configs[best];
1095
1096 dev_dbg(codec->dev, "ReTune Mobile %s tuned for %dHz\n",
1097 s->name, s->rate);
1098
1099 /* If the EQ is enabled then disable it while we write out */
1100 eq1 = snd_soc_read(codec, WM9081_EQ_1) & WM9081_EQ_ENA;
1101 if (eq1 & WM9081_EQ_ENA)
1102 snd_soc_write(codec, WM9081_EQ_1, 0);
1103
1104 /* Write out the other values */
1105 for (i = 1; i < ARRAY_SIZE(s->config); i++)
1106 snd_soc_write(codec, WM9081_EQ_1 + i, s->config[i]);
1107
1108 eq1 |= (s->config[0] & ~WM9081_EQ_ENA);
1109 snd_soc_write(codec, WM9081_EQ_1, eq1);
1110 }
1111
1112 snd_soc_write(codec, WM9081_CLOCK_CONTROL_2, clk_ctrl2);
1113 snd_soc_write(codec, WM9081_AUDIO_INTERFACE_2, aif2);
1114 snd_soc_write(codec, WM9081_AUDIO_INTERFACE_3, aif3);
1115 snd_soc_write(codec, WM9081_AUDIO_INTERFACE_4, aif4);
1116
1117 return 0;
1118}
1119
1120static int wm9081_digital_mute(struct snd_soc_dai *codec_dai, int mute)
1121{
1122 struct snd_soc_codec *codec = codec_dai->codec;
1123 unsigned int reg;
1124
1125 reg = snd_soc_read(codec, WM9081_DAC_DIGITAL_2);
1126
1127 if (mute)
1128 reg |= WM9081_DAC_MUTE;
1129 else
1130 reg &= ~WM9081_DAC_MUTE;
1131
1132 snd_soc_write(codec, WM9081_DAC_DIGITAL_2, reg);
1133
1134 return 0;
1135}
1136
1137static int wm9081_set_sysclk(struct snd_soc_dai *codec_dai,
1138 int clk_id, unsigned int freq, int dir)
1139{
1140 struct snd_soc_codec *codec = codec_dai->codec;
1141 struct wm9081_priv *wm9081 = codec->private_data;
1142
1143 switch (clk_id) {
1144 case WM9081_SYSCLK_MCLK:
1145 case WM9081_SYSCLK_FLL_MCLK:
1146 wm9081->sysclk_source = clk_id;
1147 wm9081->mclk_rate = freq;
1148 break;
1149
1150 default:
1151 return -EINVAL;
1152 }
1153
1154 return 0;
1155}
1156
1157static int wm9081_set_tdm_slot(struct snd_soc_dai *dai,
1158 unsigned int tx_mask, unsigned int rx_mask, int slots, int slot_width)
1159{
1160 struct snd_soc_codec *codec = dai->codec;
1161 struct wm9081_priv *wm9081 = codec->private_data;
1162 unsigned int aif1 = snd_soc_read(codec, WM9081_AUDIO_INTERFACE_1);
1163
1164 aif1 &= ~(WM9081_AIFDAC_TDM_SLOT_MASK | WM9081_AIFDAC_TDM_MODE_MASK);
1165
1166 if (slots < 0 || slots > 4)
1167 return -EINVAL;
1168
1169 wm9081->tdm_width = slot_width;
1170
1171 if (slots == 0)
1172 slots = 1;
1173
1174 aif1 |= (slots - 1) << WM9081_AIFDAC_TDM_MODE_SHIFT;
1175
1176 switch (rx_mask) {
1177 case 1:
1178 break;
1179 case 2:
1180 aif1 |= 0x10;
1181 break;
1182 case 4:
1183 aif1 |= 0x20;
1184 break;
1185 case 8:
1186 aif1 |= 0x30;
1187 break;
1188 default:
1189 return -EINVAL;
1190 }
1191
1192 snd_soc_write(codec, WM9081_AUDIO_INTERFACE_1, aif1);
1193
1194 return 0;
1195}
1196
1197#define WM9081_RATES SNDRV_PCM_RATE_8000_96000
1198
1199#define WM9081_FORMATS \
1200 (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE | \
1201 SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S32_LE)
1202
1203static struct snd_soc_dai_ops wm9081_dai_ops = {
1204 .hw_params = wm9081_hw_params,
1205 .set_sysclk = wm9081_set_sysclk,
1206 .set_fmt = wm9081_set_dai_fmt,
1207 .digital_mute = wm9081_digital_mute,
1208 .set_tdm_slot = wm9081_set_tdm_slot,
1209};
1210
1211/* We report two channels because the CODEC processes a stereo signal, even
1212 * though it is only capable of handling a mono output.
1213 */
1214struct snd_soc_dai wm9081_dai = {
1215 .name = "WM9081",
1216 .playback = {
1217 .stream_name = "HiFi Playback",
1218 .channels_min = 1,
1219 .channels_max = 2,
1220 .rates = WM9081_RATES,
1221 .formats = WM9081_FORMATS,
1222 },
1223 .ops = &wm9081_dai_ops,
1224};
1225EXPORT_SYMBOL_GPL(wm9081_dai);
1226
1227
1228static struct snd_soc_codec *wm9081_codec;
1229
1230static int wm9081_probe(struct platform_device *pdev)
1231{
1232 struct snd_soc_device *socdev = platform_get_drvdata(pdev);
1233 struct snd_soc_codec *codec;
1234 struct wm9081_priv *wm9081;
1235 int ret = 0;
1236
1237 if (wm9081_codec == NULL) {
1238 dev_err(&pdev->dev, "Codec device not registered\n");
1239 return -ENODEV;
1240 }
1241
1242 socdev->card->codec = wm9081_codec;
1243 codec = wm9081_codec;
1244 wm9081 = codec->private_data;
1245
1246 /* register pcms */
1247 ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1);
1248 if (ret < 0) {
1249 dev_err(codec->dev, "failed to create pcms: %d\n", ret);
1250 goto pcm_err;
1251 }
1252
1253 snd_soc_add_controls(codec, wm9081_snd_controls,
1254 ARRAY_SIZE(wm9081_snd_controls));
1255 if (!wm9081->retune) {
1256 dev_dbg(codec->dev,
1257 "No ReTune Mobile data, using normal EQ\n");
1258 snd_soc_add_controls(codec, wm9081_eq_controls,
1259 ARRAY_SIZE(wm9081_eq_controls));
1260 }
1261
1262 snd_soc_dapm_new_controls(codec, wm9081_dapm_widgets,
1263 ARRAY_SIZE(wm9081_dapm_widgets));
1264 snd_soc_dapm_add_routes(codec, audio_paths, ARRAY_SIZE(audio_paths));
1265 snd_soc_dapm_new_widgets(codec);
1266
1267 ret = snd_soc_init_card(socdev);
1268 if (ret < 0) {
1269 dev_err(codec->dev, "failed to register card: %d\n", ret);
1270 goto card_err;
1271 }
1272
1273 return ret;
1274
1275card_err:
1276 snd_soc_free_pcms(socdev);
1277 snd_soc_dapm_free(socdev);
1278pcm_err:
1279 return ret;
1280}
1281
1282static int wm9081_remove(struct platform_device *pdev)
1283{
1284 struct snd_soc_device *socdev = platform_get_drvdata(pdev);
1285
1286 snd_soc_free_pcms(socdev);
1287 snd_soc_dapm_free(socdev);
1288
1289 return 0;
1290}
1291
1292#ifdef CONFIG_PM
1293static int wm9081_suspend(struct platform_device *pdev, pm_message_t state)
1294{
1295 struct snd_soc_device *socdev = platform_get_drvdata(pdev);
1296 struct snd_soc_codec *codec = socdev->card->codec;
1297
1298 wm9081_set_bias_level(codec, SND_SOC_BIAS_OFF);
1299
1300 return 0;
1301}
1302
1303static int wm9081_resume(struct platform_device *pdev)
1304{
1305 struct snd_soc_device *socdev = platform_get_drvdata(pdev);
1306 struct snd_soc_codec *codec = socdev->card->codec;
1307 u16 *reg_cache = codec->reg_cache;
1308 int i;
1309
1310 for (i = 0; i < codec->reg_cache_size; i++) {
1311 if (i == WM9081_SOFTWARE_RESET)
1312 continue;
1313
1314 snd_soc_write(codec, i, reg_cache[i]);
1315 }
1316
1317 wm9081_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
1318
1319 return 0;
1320}
1321#else
1322#define wm9081_suspend NULL
1323#define wm9081_resume NULL
1324#endif
1325
1326struct snd_soc_codec_device soc_codec_dev_wm9081 = {
1327 .probe = wm9081_probe,
1328 .remove = wm9081_remove,
1329 .suspend = wm9081_suspend,
1330 .resume = wm9081_resume,
1331};
1332EXPORT_SYMBOL_GPL(soc_codec_dev_wm9081);
1333
1334static int wm9081_register(struct wm9081_priv *wm9081,
1335 enum snd_soc_control_type control)
1336{
1337 struct snd_soc_codec *codec = &wm9081->codec;
1338 int ret;
1339 u16 reg;
1340
1341 if (wm9081_codec) {
1342 dev_err(codec->dev, "Another WM9081 is registered\n");
1343 ret = -EINVAL;
1344 goto err;
1345 }
1346
1347 mutex_init(&codec->mutex);
1348 INIT_LIST_HEAD(&codec->dapm_widgets);
1349 INIT_LIST_HEAD(&codec->dapm_paths);
1350
1351 codec->private_data = wm9081;
1352 codec->name = "WM9081";
1353 codec->owner = THIS_MODULE;
1354 codec->dai = &wm9081_dai;
1355 codec->num_dai = 1;
1356 codec->reg_cache_size = ARRAY_SIZE(wm9081->reg_cache);
1357 codec->reg_cache = &wm9081->reg_cache;
1358 codec->bias_level = SND_SOC_BIAS_OFF;
1359 codec->set_bias_level = wm9081_set_bias_level;
1360 codec->volatile_register = wm9081_volatile_register;
1361
1362 memcpy(codec->reg_cache, wm9081_reg_defaults,
1363 sizeof(wm9081_reg_defaults));
1364
1365 ret = snd_soc_codec_set_cache_io(codec, 8, 16, control);
1366 if (ret != 0) {
1367 dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret);
1368 return ret;
1369 }
1370
1371 reg = snd_soc_read(codec, WM9081_SOFTWARE_RESET);
1372 if (reg != 0x9081) {
1373 dev_err(codec->dev, "Device is not a WM9081: ID=0x%x\n", reg);
1374 ret = -EINVAL;
1375 goto err;
1376 }
1377
1378 ret = wm9081_reset(codec);
1379 if (ret < 0) {
1380 dev_err(codec->dev, "Failed to issue reset\n");
1381 return ret;
1382 }
1383
1384 wm9081_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
1385
1386 /* Enable zero cross by default */
1387 reg = snd_soc_read(codec, WM9081_ANALOGUE_LINEOUT);
1388 snd_soc_write(codec, WM9081_ANALOGUE_LINEOUT, reg | WM9081_LINEOUTZC);
1389 reg = snd_soc_read(codec, WM9081_ANALOGUE_SPEAKER_PGA);
1390 snd_soc_write(codec, WM9081_ANALOGUE_SPEAKER_PGA,
1391 reg | WM9081_SPKPGAZC);
1392
1393 wm9081_dai.dev = codec->dev;
1394
1395 wm9081_codec = codec;
1396
1397 ret = snd_soc_register_codec(codec);
1398 if (ret != 0) {
1399 dev_err(codec->dev, "Failed to register codec: %d\n", ret);
1400 return ret;
1401 }
1402
1403 ret = snd_soc_register_dai(&wm9081_dai);
1404 if (ret != 0) {
1405 dev_err(codec->dev, "Failed to register DAI: %d\n", ret);
1406 snd_soc_unregister_codec(codec);
1407 return ret;
1408 }
1409
1410 return 0;
1411
1412err:
1413 kfree(wm9081);
1414 return ret;
1415}
1416
1417static void wm9081_unregister(struct wm9081_priv *wm9081)
1418{
1419 wm9081_set_bias_level(&wm9081->codec, SND_SOC_BIAS_OFF);
1420 snd_soc_unregister_dai(&wm9081_dai);
1421 snd_soc_unregister_codec(&wm9081->codec);
1422 kfree(wm9081);
1423 wm9081_codec = NULL;
1424}
1425
1426static __devinit int wm9081_i2c_probe(struct i2c_client *i2c,
1427 const struct i2c_device_id *id)
1428{
1429 struct wm9081_priv *wm9081;
1430 struct snd_soc_codec *codec;
1431
1432 wm9081 = kzalloc(sizeof(struct wm9081_priv), GFP_KERNEL);
1433 if (wm9081 == NULL)
1434 return -ENOMEM;
1435
1436 codec = &wm9081->codec;
1437 codec->hw_write = (hw_write_t)i2c_master_send;
1438 wm9081->retune = i2c->dev.platform_data;
1439
1440 i2c_set_clientdata(i2c, wm9081);
1441 codec->control_data = i2c;
1442
1443 codec->dev = &i2c->dev;
1444
1445 return wm9081_register(wm9081, SND_SOC_I2C);
1446}
1447
1448static __devexit int wm9081_i2c_remove(struct i2c_client *client)
1449{
1450 struct wm9081_priv *wm9081 = i2c_get_clientdata(client);
1451 wm9081_unregister(wm9081);
1452 return 0;
1453}
1454
1455#ifdef CONFIG_PM
1456static int wm9081_i2c_suspend(struct i2c_client *client, pm_message_t msg)
1457{
1458 return snd_soc_suspend_device(&client->dev);
1459}
1460
1461static int wm9081_i2c_resume(struct i2c_client *client)
1462{
1463 return snd_soc_resume_device(&client->dev);
1464}
1465#else
1466#define wm9081_i2c_suspend NULL
1467#define wm9081_i2c_resume NULL
1468#endif
1469
1470static const struct i2c_device_id wm9081_i2c_id[] = {
1471 { "wm9081", 0 },
1472 { }
1473};
1474MODULE_DEVICE_TABLE(i2c, wm9081_i2c_id);
1475
1476static struct i2c_driver wm9081_i2c_driver = {
1477 .driver = {
1478 .name = "wm9081",
1479 .owner = THIS_MODULE,
1480 },
1481 .probe = wm9081_i2c_probe,
1482 .remove = __devexit_p(wm9081_i2c_remove),
1483 .suspend = wm9081_i2c_suspend,
1484 .resume = wm9081_i2c_resume,
1485 .id_table = wm9081_i2c_id,
1486};
1487
1488static int __init wm9081_modinit(void)
1489{
1490 int ret;
1491
1492 ret = i2c_add_driver(&wm9081_i2c_driver);
1493 if (ret != 0) {
1494 printk(KERN_ERR "Failed to register WM9081 I2C driver: %d\n",
1495 ret);
1496 }
1497
1498 return ret;
1499}
1500module_init(wm9081_modinit);
1501
1502static void __exit wm9081_exit(void)
1503{
1504 i2c_del_driver(&wm9081_i2c_driver);
1505}
1506module_exit(wm9081_exit);
1507
1508
1509MODULE_DESCRIPTION("ASoC WM9081 driver");
1510MODULE_AUTHOR("Mark Brown <broonie@opensource.wolfsonmicro.com>");
1511MODULE_LICENSE("GPL");
diff --git a/sound/soc/codecs/wm9081.h b/sound/soc/codecs/wm9081.h
new file mode 100644
index 000000000000..42d3bc757021
--- /dev/null
+++ b/sound/soc/codecs/wm9081.h
@@ -0,0 +1,787 @@
1#ifndef WM9081_H
2#define WM9081_H
3
4/*
5 * wm9081.c -- WM9081 ALSA SoC Audio driver
6 *
7 * Author: Mark Brown
8 *
9 * Copyright 2009 Wolfson Microelectronics plc
10 *
11 * This program is free software; you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License version 2 as
13 * published by the Free Software Foundation.
14 */
15
16#include <sound/soc.h>
17
18extern struct snd_soc_dai wm9081_dai;
19extern struct snd_soc_codec_device soc_codec_dev_wm9081;
20
21/*
22 * SYSCLK sources
23 */
24#define WM9081_SYSCLK_MCLK 1 /* Use MCLK without FLL */
25#define WM9081_SYSCLK_FLL_MCLK 2 /* Use MCLK, enabling FLL if required */
26
27/*
28 * Register values.
29 */
30#define WM9081_SOFTWARE_RESET 0x00
31#define WM9081_ANALOGUE_LINEOUT 0x02
32#define WM9081_ANALOGUE_SPEAKER_PGA 0x03
33#define WM9081_VMID_CONTROL 0x04
34#define WM9081_BIAS_CONTROL_1 0x05
35#define WM9081_ANALOGUE_MIXER 0x07
36#define WM9081_ANTI_POP_CONTROL 0x08
37#define WM9081_ANALOGUE_SPEAKER_1 0x09
38#define WM9081_ANALOGUE_SPEAKER_2 0x0A
39#define WM9081_POWER_MANAGEMENT 0x0B
40#define WM9081_CLOCK_CONTROL_1 0x0C
41#define WM9081_CLOCK_CONTROL_2 0x0D
42#define WM9081_CLOCK_CONTROL_3 0x0E
43#define WM9081_FLL_CONTROL_1 0x10
44#define WM9081_FLL_CONTROL_2 0x11
45#define WM9081_FLL_CONTROL_3 0x12
46#define WM9081_FLL_CONTROL_4 0x13
47#define WM9081_FLL_CONTROL_5 0x14
48#define WM9081_AUDIO_INTERFACE_1 0x16
49#define WM9081_AUDIO_INTERFACE_2 0x17
50#define WM9081_AUDIO_INTERFACE_3 0x18
51#define WM9081_AUDIO_INTERFACE_4 0x19
52#define WM9081_INTERRUPT_STATUS 0x1A
53#define WM9081_INTERRUPT_STATUS_MASK 0x1B
54#define WM9081_INTERRUPT_POLARITY 0x1C
55#define WM9081_INTERRUPT_CONTROL 0x1D
56#define WM9081_DAC_DIGITAL_1 0x1E
57#define WM9081_DAC_DIGITAL_2 0x1F
58#define WM9081_DRC_1 0x20
59#define WM9081_DRC_2 0x21
60#define WM9081_DRC_3 0x22
61#define WM9081_DRC_4 0x23
62#define WM9081_WRITE_SEQUENCER_1 0x26
63#define WM9081_WRITE_SEQUENCER_2 0x27
64#define WM9081_MW_SLAVE_1 0x28
65#define WM9081_EQ_1 0x2A
66#define WM9081_EQ_2 0x2B
67#define WM9081_EQ_3 0x2C
68#define WM9081_EQ_4 0x2D
69#define WM9081_EQ_5 0x2E
70#define WM9081_EQ_6 0x2F
71#define WM9081_EQ_7 0x30
72#define WM9081_EQ_8 0x31
73#define WM9081_EQ_9 0x32
74#define WM9081_EQ_10 0x33
75#define WM9081_EQ_11 0x34
76#define WM9081_EQ_12 0x35
77#define WM9081_EQ_13 0x36
78#define WM9081_EQ_14 0x37
79#define WM9081_EQ_15 0x38
80#define WM9081_EQ_16 0x39
81#define WM9081_EQ_17 0x3A
82#define WM9081_EQ_18 0x3B
83#define WM9081_EQ_19 0x3C
84#define WM9081_EQ_20 0x3D
85
86#define WM9081_REGISTER_COUNT 55
87#define WM9081_MAX_REGISTER 0x3D
88
89/*
90 * Field Definitions.
91 */
92
93/*
94 * R0 (0x00) - Software Reset
95 */
96#define WM9081_SW_RST_DEV_ID1_MASK 0xFFFF /* SW_RST_DEV_ID1 - [15:0] */
97#define WM9081_SW_RST_DEV_ID1_SHIFT 0 /* SW_RST_DEV_ID1 - [15:0] */
98#define WM9081_SW_RST_DEV_ID1_WIDTH 16 /* SW_RST_DEV_ID1 - [15:0] */
99
100/*
101 * R2 (0x02) - Analogue Lineout
102 */
103#define WM9081_LINEOUT_MUTE 0x0080 /* LINEOUT_MUTE */
104#define WM9081_LINEOUT_MUTE_MASK 0x0080 /* LINEOUT_MUTE */
105#define WM9081_LINEOUT_MUTE_SHIFT 7 /* LINEOUT_MUTE */
106#define WM9081_LINEOUT_MUTE_WIDTH 1 /* LINEOUT_MUTE */
107#define WM9081_LINEOUTZC 0x0040 /* LINEOUTZC */
108#define WM9081_LINEOUTZC_MASK 0x0040 /* LINEOUTZC */
109#define WM9081_LINEOUTZC_SHIFT 6 /* LINEOUTZC */
110#define WM9081_LINEOUTZC_WIDTH 1 /* LINEOUTZC */
111#define WM9081_LINEOUT_VOL_MASK 0x003F /* LINEOUT_VOL - [5:0] */
112#define WM9081_LINEOUT_VOL_SHIFT 0 /* LINEOUT_VOL - [5:0] */
113#define WM9081_LINEOUT_VOL_WIDTH 6 /* LINEOUT_VOL - [5:0] */
114
115/*
116 * R3 (0x03) - Analogue Speaker PGA
117 */
118#define WM9081_SPKPGA_MUTE 0x0080 /* SPKPGA_MUTE */
119#define WM9081_SPKPGA_MUTE_MASK 0x0080 /* SPKPGA_MUTE */
120#define WM9081_SPKPGA_MUTE_SHIFT 7 /* SPKPGA_MUTE */
121#define WM9081_SPKPGA_MUTE_WIDTH 1 /* SPKPGA_MUTE */
122#define WM9081_SPKPGAZC 0x0040 /* SPKPGAZC */
123#define WM9081_SPKPGAZC_MASK 0x0040 /* SPKPGAZC */
124#define WM9081_SPKPGAZC_SHIFT 6 /* SPKPGAZC */
125#define WM9081_SPKPGAZC_WIDTH 1 /* SPKPGAZC */
126#define WM9081_SPKPGA_VOL_MASK 0x003F /* SPKPGA_VOL - [5:0] */
127#define WM9081_SPKPGA_VOL_SHIFT 0 /* SPKPGA_VOL - [5:0] */
128#define WM9081_SPKPGA_VOL_WIDTH 6 /* SPKPGA_VOL - [5:0] */
129
130/*
131 * R4 (0x04) - VMID Control
132 */
133#define WM9081_VMID_BUF_ENA 0x0020 /* VMID_BUF_ENA */
134#define WM9081_VMID_BUF_ENA_MASK 0x0020 /* VMID_BUF_ENA */
135#define WM9081_VMID_BUF_ENA_SHIFT 5 /* VMID_BUF_ENA */
136#define WM9081_VMID_BUF_ENA_WIDTH 1 /* VMID_BUF_ENA */
137#define WM9081_VMID_RAMP 0x0008 /* VMID_RAMP */
138#define WM9081_VMID_RAMP_MASK 0x0008 /* VMID_RAMP */
139#define WM9081_VMID_RAMP_SHIFT 3 /* VMID_RAMP */
140#define WM9081_VMID_RAMP_WIDTH 1 /* VMID_RAMP */
141#define WM9081_VMID_SEL_MASK 0x0006 /* VMID_SEL - [2:1] */
142#define WM9081_VMID_SEL_SHIFT 1 /* VMID_SEL - [2:1] */
143#define WM9081_VMID_SEL_WIDTH 2 /* VMID_SEL - [2:1] */
144#define WM9081_VMID_FAST_ST 0x0001 /* VMID_FAST_ST */
145#define WM9081_VMID_FAST_ST_MASK 0x0001 /* VMID_FAST_ST */
146#define WM9081_VMID_FAST_ST_SHIFT 0 /* VMID_FAST_ST */
147#define WM9081_VMID_FAST_ST_WIDTH 1 /* VMID_FAST_ST */
148
149/*
150 * R5 (0x05) - Bias Control 1
151 */
152#define WM9081_BIAS_SRC 0x0040 /* BIAS_SRC */
153#define WM9081_BIAS_SRC_MASK 0x0040 /* BIAS_SRC */
154#define WM9081_BIAS_SRC_SHIFT 6 /* BIAS_SRC */
155#define WM9081_BIAS_SRC_WIDTH 1 /* BIAS_SRC */
156#define WM9081_STBY_BIAS_LVL 0x0020 /* STBY_BIAS_LVL */
157#define WM9081_STBY_BIAS_LVL_MASK 0x0020 /* STBY_BIAS_LVL */
158#define WM9081_STBY_BIAS_LVL_SHIFT 5 /* STBY_BIAS_LVL */
159#define WM9081_STBY_BIAS_LVL_WIDTH 1 /* STBY_BIAS_LVL */
160#define WM9081_STBY_BIAS_ENA 0x0010 /* STBY_BIAS_ENA */
161#define WM9081_STBY_BIAS_ENA_MASK 0x0010 /* STBY_BIAS_ENA */
162#define WM9081_STBY_BIAS_ENA_SHIFT 4 /* STBY_BIAS_ENA */
163#define WM9081_STBY_BIAS_ENA_WIDTH 1 /* STBY_BIAS_ENA */
164#define WM9081_BIAS_LVL_MASK 0x000C /* BIAS_LVL - [3:2] */
165#define WM9081_BIAS_LVL_SHIFT 2 /* BIAS_LVL - [3:2] */
166#define WM9081_BIAS_LVL_WIDTH 2 /* BIAS_LVL - [3:2] */
167#define WM9081_BIAS_ENA 0x0002 /* BIAS_ENA */
168#define WM9081_BIAS_ENA_MASK 0x0002 /* BIAS_ENA */
169#define WM9081_BIAS_ENA_SHIFT 1 /* BIAS_ENA */
170#define WM9081_BIAS_ENA_WIDTH 1 /* BIAS_ENA */
171#define WM9081_STARTUP_BIAS_ENA 0x0001 /* STARTUP_BIAS_ENA */
172#define WM9081_STARTUP_BIAS_ENA_MASK 0x0001 /* STARTUP_BIAS_ENA */
173#define WM9081_STARTUP_BIAS_ENA_SHIFT 0 /* STARTUP_BIAS_ENA */
174#define WM9081_STARTUP_BIAS_ENA_WIDTH 1 /* STARTUP_BIAS_ENA */
175
176/*
177 * R7 (0x07) - Analogue Mixer
178 */
179#define WM9081_DAC_SEL 0x0010 /* DAC_SEL */
180#define WM9081_DAC_SEL_MASK 0x0010 /* DAC_SEL */
181#define WM9081_DAC_SEL_SHIFT 4 /* DAC_SEL */
182#define WM9081_DAC_SEL_WIDTH 1 /* DAC_SEL */
183#define WM9081_IN2_VOL 0x0008 /* IN2_VOL */
184#define WM9081_IN2_VOL_MASK 0x0008 /* IN2_VOL */
185#define WM9081_IN2_VOL_SHIFT 3 /* IN2_VOL */
186#define WM9081_IN2_VOL_WIDTH 1 /* IN2_VOL */
187#define WM9081_IN2_ENA 0x0004 /* IN2_ENA */
188#define WM9081_IN2_ENA_MASK 0x0004 /* IN2_ENA */
189#define WM9081_IN2_ENA_SHIFT 2 /* IN2_ENA */
190#define WM9081_IN2_ENA_WIDTH 1 /* IN2_ENA */
191#define WM9081_IN1_VOL 0x0002 /* IN1_VOL */
192#define WM9081_IN1_VOL_MASK 0x0002 /* IN1_VOL */
193#define WM9081_IN1_VOL_SHIFT 1 /* IN1_VOL */
194#define WM9081_IN1_VOL_WIDTH 1 /* IN1_VOL */
195#define WM9081_IN1_ENA 0x0001 /* IN1_ENA */
196#define WM9081_IN1_ENA_MASK 0x0001 /* IN1_ENA */
197#define WM9081_IN1_ENA_SHIFT 0 /* IN1_ENA */
198#define WM9081_IN1_ENA_WIDTH 1 /* IN1_ENA */
199
200/*
201 * R8 (0x08) - Anti Pop Control
202 */
203#define WM9081_LINEOUT_DISCH 0x0004 /* LINEOUT_DISCH */
204#define WM9081_LINEOUT_DISCH_MASK 0x0004 /* LINEOUT_DISCH */
205#define WM9081_LINEOUT_DISCH_SHIFT 2 /* LINEOUT_DISCH */
206#define WM9081_LINEOUT_DISCH_WIDTH 1 /* LINEOUT_DISCH */
207#define WM9081_LINEOUT_VROI 0x0002 /* LINEOUT_VROI */
208#define WM9081_LINEOUT_VROI_MASK 0x0002 /* LINEOUT_VROI */
209#define WM9081_LINEOUT_VROI_SHIFT 1 /* LINEOUT_VROI */
210#define WM9081_LINEOUT_VROI_WIDTH 1 /* LINEOUT_VROI */
211#define WM9081_LINEOUT_CLAMP 0x0001 /* LINEOUT_CLAMP */
212#define WM9081_LINEOUT_CLAMP_MASK 0x0001 /* LINEOUT_CLAMP */
213#define WM9081_LINEOUT_CLAMP_SHIFT 0 /* LINEOUT_CLAMP */
214#define WM9081_LINEOUT_CLAMP_WIDTH 1 /* LINEOUT_CLAMP */
215
216/*
217 * R9 (0x09) - Analogue Speaker 1
218 */
219#define WM9081_SPK_DCGAIN_MASK 0x0038 /* SPK_DCGAIN - [5:3] */
220#define WM9081_SPK_DCGAIN_SHIFT 3 /* SPK_DCGAIN - [5:3] */
221#define WM9081_SPK_DCGAIN_WIDTH 3 /* SPK_DCGAIN - [5:3] */
222#define WM9081_SPK_ACGAIN_MASK 0x0007 /* SPK_ACGAIN - [2:0] */
223#define WM9081_SPK_ACGAIN_SHIFT 0 /* SPK_ACGAIN - [2:0] */
224#define WM9081_SPK_ACGAIN_WIDTH 3 /* SPK_ACGAIN - [2:0] */
225
226/*
227 * R10 (0x0A) - Analogue Speaker 2
228 */
229#define WM9081_SPK_MODE 0x0040 /* SPK_MODE */
230#define WM9081_SPK_MODE_MASK 0x0040 /* SPK_MODE */
231#define WM9081_SPK_MODE_SHIFT 6 /* SPK_MODE */
232#define WM9081_SPK_MODE_WIDTH 1 /* SPK_MODE */
233#define WM9081_SPK_INV_MUTE 0x0010 /* SPK_INV_MUTE */
234#define WM9081_SPK_INV_MUTE_MASK 0x0010 /* SPK_INV_MUTE */
235#define WM9081_SPK_INV_MUTE_SHIFT 4 /* SPK_INV_MUTE */
236#define WM9081_SPK_INV_MUTE_WIDTH 1 /* SPK_INV_MUTE */
237#define WM9081_OUT_SPK_CTRL 0x0008 /* OUT_SPK_CTRL */
238#define WM9081_OUT_SPK_CTRL_MASK 0x0008 /* OUT_SPK_CTRL */
239#define WM9081_OUT_SPK_CTRL_SHIFT 3 /* OUT_SPK_CTRL */
240#define WM9081_OUT_SPK_CTRL_WIDTH 1 /* OUT_SPK_CTRL */
241
242/*
243 * R11 (0x0B) - Power Management
244 */
245#define WM9081_TSHUT_ENA 0x0100 /* TSHUT_ENA */
246#define WM9081_TSHUT_ENA_MASK 0x0100 /* TSHUT_ENA */
247#define WM9081_TSHUT_ENA_SHIFT 8 /* TSHUT_ENA */
248#define WM9081_TSHUT_ENA_WIDTH 1 /* TSHUT_ENA */
249#define WM9081_TSENSE_ENA 0x0080 /* TSENSE_ENA */
250#define WM9081_TSENSE_ENA_MASK 0x0080 /* TSENSE_ENA */
251#define WM9081_TSENSE_ENA_SHIFT 7 /* TSENSE_ENA */
252#define WM9081_TSENSE_ENA_WIDTH 1 /* TSENSE_ENA */
253#define WM9081_TEMP_SHUT 0x0040 /* TEMP_SHUT */
254#define WM9081_TEMP_SHUT_MASK 0x0040 /* TEMP_SHUT */
255#define WM9081_TEMP_SHUT_SHIFT 6 /* TEMP_SHUT */
256#define WM9081_TEMP_SHUT_WIDTH 1 /* TEMP_SHUT */
257#define WM9081_LINEOUT_ENA 0x0010 /* LINEOUT_ENA */
258#define WM9081_LINEOUT_ENA_MASK 0x0010 /* LINEOUT_ENA */
259#define WM9081_LINEOUT_ENA_SHIFT 4 /* LINEOUT_ENA */
260#define WM9081_LINEOUT_ENA_WIDTH 1 /* LINEOUT_ENA */
261#define WM9081_SPKPGA_ENA 0x0004 /* SPKPGA_ENA */
262#define WM9081_SPKPGA_ENA_MASK 0x0004 /* SPKPGA_ENA */
263#define WM9081_SPKPGA_ENA_SHIFT 2 /* SPKPGA_ENA */
264#define WM9081_SPKPGA_ENA_WIDTH 1 /* SPKPGA_ENA */
265#define WM9081_SPK_ENA 0x0002 /* SPK_ENA */
266#define WM9081_SPK_ENA_MASK 0x0002 /* SPK_ENA */
267#define WM9081_SPK_ENA_SHIFT 1 /* SPK_ENA */
268#define WM9081_SPK_ENA_WIDTH 1 /* SPK_ENA */
269#define WM9081_DAC_ENA 0x0001 /* DAC_ENA */
270#define WM9081_DAC_ENA_MASK 0x0001 /* DAC_ENA */
271#define WM9081_DAC_ENA_SHIFT 0 /* DAC_ENA */
272#define WM9081_DAC_ENA_WIDTH 1 /* DAC_ENA */
273
274/*
275 * R12 (0x0C) - Clock Control 1
276 */
277#define WM9081_CLK_OP_DIV_MASK 0x1C00 /* CLK_OP_DIV - [12:10] */
278#define WM9081_CLK_OP_DIV_SHIFT 10 /* CLK_OP_DIV - [12:10] */
279#define WM9081_CLK_OP_DIV_WIDTH 3 /* CLK_OP_DIV - [12:10] */
280#define WM9081_CLK_TO_DIV_MASK 0x0300 /* CLK_TO_DIV - [9:8] */
281#define WM9081_CLK_TO_DIV_SHIFT 8 /* CLK_TO_DIV - [9:8] */
282#define WM9081_CLK_TO_DIV_WIDTH 2 /* CLK_TO_DIV - [9:8] */
283#define WM9081_MCLKDIV2 0x0080 /* MCLKDIV2 */
284#define WM9081_MCLKDIV2_MASK 0x0080 /* MCLKDIV2 */
285#define WM9081_MCLKDIV2_SHIFT 7 /* MCLKDIV2 */
286#define WM9081_MCLKDIV2_WIDTH 1 /* MCLKDIV2 */
287
288/*
289 * R13 (0x0D) - Clock Control 2
290 */
291#define WM9081_CLK_SYS_RATE_MASK 0x00F0 /* CLK_SYS_RATE - [7:4] */
292#define WM9081_CLK_SYS_RATE_SHIFT 4 /* CLK_SYS_RATE - [7:4] */
293#define WM9081_CLK_SYS_RATE_WIDTH 4 /* CLK_SYS_RATE - [7:4] */
294#define WM9081_SAMPLE_RATE_MASK 0x000F /* SAMPLE_RATE - [3:0] */
295#define WM9081_SAMPLE_RATE_SHIFT 0 /* SAMPLE_RATE - [3:0] */
296#define WM9081_SAMPLE_RATE_WIDTH 4 /* SAMPLE_RATE - [3:0] */
297
298/*
299 * R14 (0x0E) - Clock Control 3
300 */
301#define WM9081_CLK_SRC_SEL 0x2000 /* CLK_SRC_SEL */
302#define WM9081_CLK_SRC_SEL_MASK 0x2000 /* CLK_SRC_SEL */
303#define WM9081_CLK_SRC_SEL_SHIFT 13 /* CLK_SRC_SEL */
304#define WM9081_CLK_SRC_SEL_WIDTH 1 /* CLK_SRC_SEL */
305#define WM9081_CLK_OP_ENA 0x0020 /* CLK_OP_ENA */
306#define WM9081_CLK_OP_ENA_MASK 0x0020 /* CLK_OP_ENA */
307#define WM9081_CLK_OP_ENA_SHIFT 5 /* CLK_OP_ENA */
308#define WM9081_CLK_OP_ENA_WIDTH 1 /* CLK_OP_ENA */
309#define WM9081_CLK_TO_ENA 0x0004 /* CLK_TO_ENA */
310#define WM9081_CLK_TO_ENA_MASK 0x0004 /* CLK_TO_ENA */
311#define WM9081_CLK_TO_ENA_SHIFT 2 /* CLK_TO_ENA */
312#define WM9081_CLK_TO_ENA_WIDTH 1 /* CLK_TO_ENA */
313#define WM9081_CLK_DSP_ENA 0x0002 /* CLK_DSP_ENA */
314#define WM9081_CLK_DSP_ENA_MASK 0x0002 /* CLK_DSP_ENA */
315#define WM9081_CLK_DSP_ENA_SHIFT 1 /* CLK_DSP_ENA */
316#define WM9081_CLK_DSP_ENA_WIDTH 1 /* CLK_DSP_ENA */
317#define WM9081_CLK_SYS_ENA 0x0001 /* CLK_SYS_ENA */
318#define WM9081_CLK_SYS_ENA_MASK 0x0001 /* CLK_SYS_ENA */
319#define WM9081_CLK_SYS_ENA_SHIFT 0 /* CLK_SYS_ENA */
320#define WM9081_CLK_SYS_ENA_WIDTH 1 /* CLK_SYS_ENA */
321
322/*
323 * R16 (0x10) - FLL Control 1
324 */
325#define WM9081_FLL_HOLD 0x0008 /* FLL_HOLD */
326#define WM9081_FLL_HOLD_MASK 0x0008 /* FLL_HOLD */
327#define WM9081_FLL_HOLD_SHIFT 3 /* FLL_HOLD */
328#define WM9081_FLL_HOLD_WIDTH 1 /* FLL_HOLD */
329#define WM9081_FLL_FRAC 0x0004 /* FLL_FRAC */
330#define WM9081_FLL_FRAC_MASK 0x0004 /* FLL_FRAC */
331#define WM9081_FLL_FRAC_SHIFT 2 /* FLL_FRAC */
332#define WM9081_FLL_FRAC_WIDTH 1 /* FLL_FRAC */
333#define WM9081_FLL_ENA 0x0001 /* FLL_ENA */
334#define WM9081_FLL_ENA_MASK 0x0001 /* FLL_ENA */
335#define WM9081_FLL_ENA_SHIFT 0 /* FLL_ENA */
336#define WM9081_FLL_ENA_WIDTH 1 /* FLL_ENA */
337
338/*
339 * R17 (0x11) - FLL Control 2
340 */
341#define WM9081_FLL_OUTDIV_MASK 0x0700 /* FLL_OUTDIV - [10:8] */
342#define WM9081_FLL_OUTDIV_SHIFT 8 /* FLL_OUTDIV - [10:8] */
343#define WM9081_FLL_OUTDIV_WIDTH 3 /* FLL_OUTDIV - [10:8] */
344#define WM9081_FLL_CTRL_RATE_MASK 0x0070 /* FLL_CTRL_RATE - [6:4] */
345#define WM9081_FLL_CTRL_RATE_SHIFT 4 /* FLL_CTRL_RATE - [6:4] */
346#define WM9081_FLL_CTRL_RATE_WIDTH 3 /* FLL_CTRL_RATE - [6:4] */
347#define WM9081_FLL_FRATIO_MASK 0x0007 /* FLL_FRATIO - [2:0] */
348#define WM9081_FLL_FRATIO_SHIFT 0 /* FLL_FRATIO - [2:0] */
349#define WM9081_FLL_FRATIO_WIDTH 3 /* FLL_FRATIO - [2:0] */
350
351/*
352 * R18 (0x12) - FLL Control 3
353 */
354#define WM9081_FLL_K_MASK 0xFFFF /* FLL_K - [15:0] */
355#define WM9081_FLL_K_SHIFT 0 /* FLL_K - [15:0] */
356#define WM9081_FLL_K_WIDTH 16 /* FLL_K - [15:0] */
357
358/*
359 * R19 (0x13) - FLL Control 4
360 */
361#define WM9081_FLL_N_MASK 0x7FE0 /* FLL_N - [14:5] */
362#define WM9081_FLL_N_SHIFT 5 /* FLL_N - [14:5] */
363#define WM9081_FLL_N_WIDTH 10 /* FLL_N - [14:5] */
364#define WM9081_FLL_GAIN_MASK 0x000F /* FLL_GAIN - [3:0] */
365#define WM9081_FLL_GAIN_SHIFT 0 /* FLL_GAIN - [3:0] */
366#define WM9081_FLL_GAIN_WIDTH 4 /* FLL_GAIN - [3:0] */
367
368/*
369 * R20 (0x14) - FLL Control 5
370 */
371#define WM9081_FLL_CLK_REF_DIV_MASK 0x0018 /* FLL_CLK_REF_DIV - [4:3] */
372#define WM9081_FLL_CLK_REF_DIV_SHIFT 3 /* FLL_CLK_REF_DIV - [4:3] */
373#define WM9081_FLL_CLK_REF_DIV_WIDTH 2 /* FLL_CLK_REF_DIV - [4:3] */
374#define WM9081_FLL_CLK_SRC_MASK 0x0003 /* FLL_CLK_SRC - [1:0] */
375#define WM9081_FLL_CLK_SRC_SHIFT 0 /* FLL_CLK_SRC - [1:0] */
376#define WM9081_FLL_CLK_SRC_WIDTH 2 /* FLL_CLK_SRC - [1:0] */
377
378/*
379 * R22 (0x16) - Audio Interface 1
380 */
381#define WM9081_AIFDAC_CHAN 0x0040 /* AIFDAC_CHAN */
382#define WM9081_AIFDAC_CHAN_MASK 0x0040 /* AIFDAC_CHAN */
383#define WM9081_AIFDAC_CHAN_SHIFT 6 /* AIFDAC_CHAN */
384#define WM9081_AIFDAC_CHAN_WIDTH 1 /* AIFDAC_CHAN */
385#define WM9081_AIFDAC_TDM_SLOT_MASK 0x0030 /* AIFDAC_TDM_SLOT - [5:4] */
386#define WM9081_AIFDAC_TDM_SLOT_SHIFT 4 /* AIFDAC_TDM_SLOT - [5:4] */
387#define WM9081_AIFDAC_TDM_SLOT_WIDTH 2 /* AIFDAC_TDM_SLOT - [5:4] */
388#define WM9081_AIFDAC_TDM_MODE_MASK 0x000C /* AIFDAC_TDM_MODE - [3:2] */
389#define WM9081_AIFDAC_TDM_MODE_SHIFT 2 /* AIFDAC_TDM_MODE - [3:2] */
390#define WM9081_AIFDAC_TDM_MODE_WIDTH 2 /* AIFDAC_TDM_MODE - [3:2] */
391#define WM9081_DAC_COMP 0x0002 /* DAC_COMP */
392#define WM9081_DAC_COMP_MASK 0x0002 /* DAC_COMP */
393#define WM9081_DAC_COMP_SHIFT 1 /* DAC_COMP */
394#define WM9081_DAC_COMP_WIDTH 1 /* DAC_COMP */
395#define WM9081_DAC_COMPMODE 0x0001 /* DAC_COMPMODE */
396#define WM9081_DAC_COMPMODE_MASK 0x0001 /* DAC_COMPMODE */
397#define WM9081_DAC_COMPMODE_SHIFT 0 /* DAC_COMPMODE */
398#define WM9081_DAC_COMPMODE_WIDTH 1 /* DAC_COMPMODE */
399
400/*
401 * R23 (0x17) - Audio Interface 2
402 */
403#define WM9081_AIF_TRIS 0x0200 /* AIF_TRIS */
404#define WM9081_AIF_TRIS_MASK 0x0200 /* AIF_TRIS */
405#define WM9081_AIF_TRIS_SHIFT 9 /* AIF_TRIS */
406#define WM9081_AIF_TRIS_WIDTH 1 /* AIF_TRIS */
407#define WM9081_DAC_DAT_INV 0x0100 /* DAC_DAT_INV */
408#define WM9081_DAC_DAT_INV_MASK 0x0100 /* DAC_DAT_INV */
409#define WM9081_DAC_DAT_INV_SHIFT 8 /* DAC_DAT_INV */
410#define WM9081_DAC_DAT_INV_WIDTH 1 /* DAC_DAT_INV */
411#define WM9081_AIF_BCLK_INV 0x0080 /* AIF_BCLK_INV */
412#define WM9081_AIF_BCLK_INV_MASK 0x0080 /* AIF_BCLK_INV */
413#define WM9081_AIF_BCLK_INV_SHIFT 7 /* AIF_BCLK_INV */
414#define WM9081_AIF_BCLK_INV_WIDTH 1 /* AIF_BCLK_INV */
415#define WM9081_BCLK_DIR 0x0040 /* BCLK_DIR */
416#define WM9081_BCLK_DIR_MASK 0x0040 /* BCLK_DIR */
417#define WM9081_BCLK_DIR_SHIFT 6 /* BCLK_DIR */
418#define WM9081_BCLK_DIR_WIDTH 1 /* BCLK_DIR */
419#define WM9081_LRCLK_DIR 0x0020 /* LRCLK_DIR */
420#define WM9081_LRCLK_DIR_MASK 0x0020 /* LRCLK_DIR */
421#define WM9081_LRCLK_DIR_SHIFT 5 /* LRCLK_DIR */
422#define WM9081_LRCLK_DIR_WIDTH 1 /* LRCLK_DIR */
423#define WM9081_AIF_LRCLK_INV 0x0010 /* AIF_LRCLK_INV */
424#define WM9081_AIF_LRCLK_INV_MASK 0x0010 /* AIF_LRCLK_INV */
425#define WM9081_AIF_LRCLK_INV_SHIFT 4 /* AIF_LRCLK_INV */
426#define WM9081_AIF_LRCLK_INV_WIDTH 1 /* AIF_LRCLK_INV */
427#define WM9081_AIF_WL_MASK 0x000C /* AIF_WL - [3:2] */
428#define WM9081_AIF_WL_SHIFT 2 /* AIF_WL - [3:2] */
429#define WM9081_AIF_WL_WIDTH 2 /* AIF_WL - [3:2] */
430#define WM9081_AIF_FMT_MASK 0x0003 /* AIF_FMT - [1:0] */
431#define WM9081_AIF_FMT_SHIFT 0 /* AIF_FMT - [1:0] */
432#define WM9081_AIF_FMT_WIDTH 2 /* AIF_FMT - [1:0] */
433
434/*
435 * R24 (0x18) - Audio Interface 3
436 */
437#define WM9081_BCLK_DIV_MASK 0x001F /* BCLK_DIV - [4:0] */
438#define WM9081_BCLK_DIV_SHIFT 0 /* BCLK_DIV - [4:0] */
439#define WM9081_BCLK_DIV_WIDTH 5 /* BCLK_DIV - [4:0] */
440
441/*
442 * R25 (0x19) - Audio Interface 4
443 */
444#define WM9081_LRCLK_RATE_MASK 0x07FF /* LRCLK_RATE - [10:0] */
445#define WM9081_LRCLK_RATE_SHIFT 0 /* LRCLK_RATE - [10:0] */
446#define WM9081_LRCLK_RATE_WIDTH 11 /* LRCLK_RATE - [10:0] */
447
448/*
449 * R26 (0x1A) - Interrupt Status
450 */
451#define WM9081_WSEQ_BUSY_EINT 0x0004 /* WSEQ_BUSY_EINT */
452#define WM9081_WSEQ_BUSY_EINT_MASK 0x0004 /* WSEQ_BUSY_EINT */
453#define WM9081_WSEQ_BUSY_EINT_SHIFT 2 /* WSEQ_BUSY_EINT */
454#define WM9081_WSEQ_BUSY_EINT_WIDTH 1 /* WSEQ_BUSY_EINT */
455#define WM9081_TSHUT_EINT 0x0001 /* TSHUT_EINT */
456#define WM9081_TSHUT_EINT_MASK 0x0001 /* TSHUT_EINT */
457#define WM9081_TSHUT_EINT_SHIFT 0 /* TSHUT_EINT */
458#define WM9081_TSHUT_EINT_WIDTH 1 /* TSHUT_EINT */
459
460/*
461 * R27 (0x1B) - Interrupt Status Mask
462 */
463#define WM9081_IM_WSEQ_BUSY_EINT 0x0004 /* IM_WSEQ_BUSY_EINT */
464#define WM9081_IM_WSEQ_BUSY_EINT_MASK 0x0004 /* IM_WSEQ_BUSY_EINT */
465#define WM9081_IM_WSEQ_BUSY_EINT_SHIFT 2 /* IM_WSEQ_BUSY_EINT */
466#define WM9081_IM_WSEQ_BUSY_EINT_WIDTH 1 /* IM_WSEQ_BUSY_EINT */
467#define WM9081_IM_TSHUT_EINT 0x0001 /* IM_TSHUT_EINT */
468#define WM9081_IM_TSHUT_EINT_MASK 0x0001 /* IM_TSHUT_EINT */
469#define WM9081_IM_TSHUT_EINT_SHIFT 0 /* IM_TSHUT_EINT */
470#define WM9081_IM_TSHUT_EINT_WIDTH 1 /* IM_TSHUT_EINT */
471
472/*
473 * R28 (0x1C) - Interrupt Polarity
474 */
475#define WM9081_TSHUT_INV 0x0001 /* TSHUT_INV */
476#define WM9081_TSHUT_INV_MASK 0x0001 /* TSHUT_INV */
477#define WM9081_TSHUT_INV_SHIFT 0 /* TSHUT_INV */
478#define WM9081_TSHUT_INV_WIDTH 1 /* TSHUT_INV */
479
480/*
481 * R29 (0x1D) - Interrupt Control
482 */
483#define WM9081_IRQ_POL 0x8000 /* IRQ_POL */
484#define WM9081_IRQ_POL_MASK 0x8000 /* IRQ_POL */
485#define WM9081_IRQ_POL_SHIFT 15 /* IRQ_POL */
486#define WM9081_IRQ_POL_WIDTH 1 /* IRQ_POL */
487#define WM9081_IRQ_OP_CTRL 0x0001 /* IRQ_OP_CTRL */
488#define WM9081_IRQ_OP_CTRL_MASK 0x0001 /* IRQ_OP_CTRL */
489#define WM9081_IRQ_OP_CTRL_SHIFT 0 /* IRQ_OP_CTRL */
490#define WM9081_IRQ_OP_CTRL_WIDTH 1 /* IRQ_OP_CTRL */
491
492/*
493 * R30 (0x1E) - DAC Digital 1
494 */
495#define WM9081_DAC_VOL_MASK 0x00FF /* DAC_VOL - [7:0] */
496#define WM9081_DAC_VOL_SHIFT 0 /* DAC_VOL - [7:0] */
497#define WM9081_DAC_VOL_WIDTH 8 /* DAC_VOL - [7:0] */
498
499/*
500 * R31 (0x1F) - DAC Digital 2
501 */
502#define WM9081_DAC_MUTERATE 0x0400 /* DAC_MUTERATE */
503#define WM9081_DAC_MUTERATE_MASK 0x0400 /* DAC_MUTERATE */
504#define WM9081_DAC_MUTERATE_SHIFT 10 /* DAC_MUTERATE */
505#define WM9081_DAC_MUTERATE_WIDTH 1 /* DAC_MUTERATE */
506#define WM9081_DAC_MUTEMODE 0x0200 /* DAC_MUTEMODE */
507#define WM9081_DAC_MUTEMODE_MASK 0x0200 /* DAC_MUTEMODE */
508#define WM9081_DAC_MUTEMODE_SHIFT 9 /* DAC_MUTEMODE */
509#define WM9081_DAC_MUTEMODE_WIDTH 1 /* DAC_MUTEMODE */
510#define WM9081_DAC_MUTE 0x0008 /* DAC_MUTE */
511#define WM9081_DAC_MUTE_MASK 0x0008 /* DAC_MUTE */
512#define WM9081_DAC_MUTE_SHIFT 3 /* DAC_MUTE */
513#define WM9081_DAC_MUTE_WIDTH 1 /* DAC_MUTE */
514#define WM9081_DEEMPH_MASK 0x0006 /* DEEMPH - [2:1] */
515#define WM9081_DEEMPH_SHIFT 1 /* DEEMPH - [2:1] */
516#define WM9081_DEEMPH_WIDTH 2 /* DEEMPH - [2:1] */
517
518/*
519 * R32 (0x20) - DRC 1
520 */
521#define WM9081_DRC_ENA 0x8000 /* DRC_ENA */
522#define WM9081_DRC_ENA_MASK 0x8000 /* DRC_ENA */
523#define WM9081_DRC_ENA_SHIFT 15 /* DRC_ENA */
524#define WM9081_DRC_ENA_WIDTH 1 /* DRC_ENA */
525#define WM9081_DRC_STARTUP_GAIN_MASK 0x07C0 /* DRC_STARTUP_GAIN - [10:6] */
526#define WM9081_DRC_STARTUP_GAIN_SHIFT 6 /* DRC_STARTUP_GAIN - [10:6] */
527#define WM9081_DRC_STARTUP_GAIN_WIDTH 5 /* DRC_STARTUP_GAIN - [10:6] */
528#define WM9081_DRC_FF_DLY 0x0020 /* DRC_FF_DLY */
529#define WM9081_DRC_FF_DLY_MASK 0x0020 /* DRC_FF_DLY */
530#define WM9081_DRC_FF_DLY_SHIFT 5 /* DRC_FF_DLY */
531#define WM9081_DRC_FF_DLY_WIDTH 1 /* DRC_FF_DLY */
532#define WM9081_DRC_QR 0x0004 /* DRC_QR */
533#define WM9081_DRC_QR_MASK 0x0004 /* DRC_QR */
534#define WM9081_DRC_QR_SHIFT 2 /* DRC_QR */
535#define WM9081_DRC_QR_WIDTH 1 /* DRC_QR */
536#define WM9081_DRC_ANTICLIP 0x0002 /* DRC_ANTICLIP */
537#define WM9081_DRC_ANTICLIP_MASK 0x0002 /* DRC_ANTICLIP */
538#define WM9081_DRC_ANTICLIP_SHIFT 1 /* DRC_ANTICLIP */
539#define WM9081_DRC_ANTICLIP_WIDTH 1 /* DRC_ANTICLIP */
540
541/*
542 * R33 (0x21) - DRC 2
543 */
544#define WM9081_DRC_ATK_MASK 0xF000 /* DRC_ATK - [15:12] */
545#define WM9081_DRC_ATK_SHIFT 12 /* DRC_ATK - [15:12] */
546#define WM9081_DRC_ATK_WIDTH 4 /* DRC_ATK - [15:12] */
547#define WM9081_DRC_DCY_MASK 0x0F00 /* DRC_DCY - [11:8] */
548#define WM9081_DRC_DCY_SHIFT 8 /* DRC_DCY - [11:8] */
549#define WM9081_DRC_DCY_WIDTH 4 /* DRC_DCY - [11:8] */
550#define WM9081_DRC_QR_THR_MASK 0x00C0 /* DRC_QR_THR - [7:6] */
551#define WM9081_DRC_QR_THR_SHIFT 6 /* DRC_QR_THR - [7:6] */
552#define WM9081_DRC_QR_THR_WIDTH 2 /* DRC_QR_THR - [7:6] */
553#define WM9081_DRC_QR_DCY_MASK 0x0030 /* DRC_QR_DCY - [5:4] */
554#define WM9081_DRC_QR_DCY_SHIFT 4 /* DRC_QR_DCY - [5:4] */
555#define WM9081_DRC_QR_DCY_WIDTH 2 /* DRC_QR_DCY - [5:4] */
556#define WM9081_DRC_MINGAIN_MASK 0x000C /* DRC_MINGAIN - [3:2] */
557#define WM9081_DRC_MINGAIN_SHIFT 2 /* DRC_MINGAIN - [3:2] */
558#define WM9081_DRC_MINGAIN_WIDTH 2 /* DRC_MINGAIN - [3:2] */
559#define WM9081_DRC_MAXGAIN_MASK 0x0003 /* DRC_MAXGAIN - [1:0] */
560#define WM9081_DRC_MAXGAIN_SHIFT 0 /* DRC_MAXGAIN - [1:0] */
561#define WM9081_DRC_MAXGAIN_WIDTH 2 /* DRC_MAXGAIN - [1:0] */
562
563/*
564 * R34 (0x22) - DRC 3
565 */
566#define WM9081_DRC_HI_COMP_MASK 0x0038 /* DRC_HI_COMP - [5:3] */
567#define WM9081_DRC_HI_COMP_SHIFT 3 /* DRC_HI_COMP - [5:3] */
568#define WM9081_DRC_HI_COMP_WIDTH 3 /* DRC_HI_COMP - [5:3] */
569#define WM9081_DRC_LO_COMP_MASK 0x0007 /* DRC_LO_COMP - [2:0] */
570#define WM9081_DRC_LO_COMP_SHIFT 0 /* DRC_LO_COMP - [2:0] */
571#define WM9081_DRC_LO_COMP_WIDTH 3 /* DRC_LO_COMP - [2:0] */
572
573/*
574 * R35 (0x23) - DRC 4
575 */
576#define WM9081_DRC_KNEE_IP_MASK 0x07E0 /* DRC_KNEE_IP - [10:5] */
577#define WM9081_DRC_KNEE_IP_SHIFT 5 /* DRC_KNEE_IP - [10:5] */
578#define WM9081_DRC_KNEE_IP_WIDTH 6 /* DRC_KNEE_IP - [10:5] */
579#define WM9081_DRC_KNEE_OP_MASK 0x001F /* DRC_KNEE_OP - [4:0] */
580#define WM9081_DRC_KNEE_OP_SHIFT 0 /* DRC_KNEE_OP - [4:0] */
581#define WM9081_DRC_KNEE_OP_WIDTH 5 /* DRC_KNEE_OP - [4:0] */
582
583/*
584 * R38 (0x26) - Write Sequencer 1
585 */
586#define WM9081_WSEQ_ENA 0x8000 /* WSEQ_ENA */
587#define WM9081_WSEQ_ENA_MASK 0x8000 /* WSEQ_ENA */
588#define WM9081_WSEQ_ENA_SHIFT 15 /* WSEQ_ENA */
589#define WM9081_WSEQ_ENA_WIDTH 1 /* WSEQ_ENA */
590#define WM9081_WSEQ_ABORT 0x0200 /* WSEQ_ABORT */
591#define WM9081_WSEQ_ABORT_MASK 0x0200 /* WSEQ_ABORT */
592#define WM9081_WSEQ_ABORT_SHIFT 9 /* WSEQ_ABORT */
593#define WM9081_WSEQ_ABORT_WIDTH 1 /* WSEQ_ABORT */
594#define WM9081_WSEQ_START 0x0100 /* WSEQ_START */
595#define WM9081_WSEQ_START_MASK 0x0100 /* WSEQ_START */
596#define WM9081_WSEQ_START_SHIFT 8 /* WSEQ_START */
597#define WM9081_WSEQ_START_WIDTH 1 /* WSEQ_START */
598#define WM9081_WSEQ_START_INDEX_MASK 0x007F /* WSEQ_START_INDEX - [6:0] */
599#define WM9081_WSEQ_START_INDEX_SHIFT 0 /* WSEQ_START_INDEX - [6:0] */
600#define WM9081_WSEQ_START_INDEX_WIDTH 7 /* WSEQ_START_INDEX - [6:0] */
601
602/*
603 * R39 (0x27) - Write Sequencer 2
604 */
605#define WM9081_WSEQ_CURRENT_INDEX_MASK 0x07F0 /* WSEQ_CURRENT_INDEX - [10:4] */
606#define WM9081_WSEQ_CURRENT_INDEX_SHIFT 4 /* WSEQ_CURRENT_INDEX - [10:4] */
607#define WM9081_WSEQ_CURRENT_INDEX_WIDTH 7 /* WSEQ_CURRENT_INDEX - [10:4] */
608#define WM9081_WSEQ_BUSY 0x0001 /* WSEQ_BUSY */
609#define WM9081_WSEQ_BUSY_MASK 0x0001 /* WSEQ_BUSY */
610#define WM9081_WSEQ_BUSY_SHIFT 0 /* WSEQ_BUSY */
611#define WM9081_WSEQ_BUSY_WIDTH 1 /* WSEQ_BUSY */
612
613/*
614 * R40 (0x28) - MW Slave 1
615 */
616#define WM9081_SPI_CFG 0x0020 /* SPI_CFG */
617#define WM9081_SPI_CFG_MASK 0x0020 /* SPI_CFG */
618#define WM9081_SPI_CFG_SHIFT 5 /* SPI_CFG */
619#define WM9081_SPI_CFG_WIDTH 1 /* SPI_CFG */
620#define WM9081_SPI_4WIRE 0x0010 /* SPI_4WIRE */
621#define WM9081_SPI_4WIRE_MASK 0x0010 /* SPI_4WIRE */
622#define WM9081_SPI_4WIRE_SHIFT 4 /* SPI_4WIRE */
623#define WM9081_SPI_4WIRE_WIDTH 1 /* SPI_4WIRE */
624#define WM9081_ARA_ENA 0x0008 /* ARA_ENA */
625#define WM9081_ARA_ENA_MASK 0x0008 /* ARA_ENA */
626#define WM9081_ARA_ENA_SHIFT 3 /* ARA_ENA */
627#define WM9081_ARA_ENA_WIDTH 1 /* ARA_ENA */
628#define WM9081_AUTO_INC 0x0002 /* AUTO_INC */
629#define WM9081_AUTO_INC_MASK 0x0002 /* AUTO_INC */
630#define WM9081_AUTO_INC_SHIFT 1 /* AUTO_INC */
631#define WM9081_AUTO_INC_WIDTH 1 /* AUTO_INC */
632
633/*
634 * R42 (0x2A) - EQ 1
635 */
636#define WM9081_EQ_B1_GAIN_MASK 0xF800 /* EQ_B1_GAIN - [15:11] */
637#define WM9081_EQ_B1_GAIN_SHIFT 11 /* EQ_B1_GAIN - [15:11] */
638#define WM9081_EQ_B1_GAIN_WIDTH 5 /* EQ_B1_GAIN - [15:11] */
639#define WM9081_EQ_B2_GAIN_MASK 0x07C0 /* EQ_B2_GAIN - [10:6] */
640#define WM9081_EQ_B2_GAIN_SHIFT 6 /* EQ_B2_GAIN - [10:6] */
641#define WM9081_EQ_B2_GAIN_WIDTH 5 /* EQ_B2_GAIN - [10:6] */
642#define WM9081_EQ_B4_GAIN_MASK 0x003E /* EQ_B4_GAIN - [5:1] */
643#define WM9081_EQ_B4_GAIN_SHIFT 1 /* EQ_B4_GAIN - [5:1] */
644#define WM9081_EQ_B4_GAIN_WIDTH 5 /* EQ_B4_GAIN - [5:1] */
645#define WM9081_EQ_ENA 0x0001 /* EQ_ENA */
646#define WM9081_EQ_ENA_MASK 0x0001 /* EQ_ENA */
647#define WM9081_EQ_ENA_SHIFT 0 /* EQ_ENA */
648#define WM9081_EQ_ENA_WIDTH 1 /* EQ_ENA */
649
650/*
651 * R43 (0x2B) - EQ 2
652 */
653#define WM9081_EQ_B3_GAIN_MASK 0xF800 /* EQ_B3_GAIN - [15:11] */
654#define WM9081_EQ_B3_GAIN_SHIFT 11 /* EQ_B3_GAIN - [15:11] */
655#define WM9081_EQ_B3_GAIN_WIDTH 5 /* EQ_B3_GAIN - [15:11] */
656#define WM9081_EQ_B5_GAIN_MASK 0x07C0 /* EQ_B5_GAIN - [10:6] */
657#define WM9081_EQ_B5_GAIN_SHIFT 6 /* EQ_B5_GAIN - [10:6] */
658#define WM9081_EQ_B5_GAIN_WIDTH 5 /* EQ_B5_GAIN - [10:6] */
659
660/*
661 * R44 (0x2C) - EQ 3
662 */
663#define WM9081_EQ_B1_A_MASK 0xFFFF /* EQ_B1_A - [15:0] */
664#define WM9081_EQ_B1_A_SHIFT 0 /* EQ_B1_A - [15:0] */
665#define WM9081_EQ_B1_A_WIDTH 16 /* EQ_B1_A - [15:0] */
666
667/*
668 * R45 (0x2D) - EQ 4
669 */
670#define WM9081_EQ_B1_B_MASK 0xFFFF /* EQ_B1_B - [15:0] */
671#define WM9081_EQ_B1_B_SHIFT 0 /* EQ_B1_B - [15:0] */
672#define WM9081_EQ_B1_B_WIDTH 16 /* EQ_B1_B - [15:0] */
673
674/*
675 * R46 (0x2E) - EQ 5
676 */
677#define WM9081_EQ_B1_PG_MASK 0xFFFF /* EQ_B1_PG - [15:0] */
678#define WM9081_EQ_B1_PG_SHIFT 0 /* EQ_B1_PG - [15:0] */
679#define WM9081_EQ_B1_PG_WIDTH 16 /* EQ_B1_PG - [15:0] */
680
681/*
682 * R47 (0x2F) - EQ 6
683 */
684#define WM9081_EQ_B2_A_MASK 0xFFFF /* EQ_B2_A - [15:0] */
685#define WM9081_EQ_B2_A_SHIFT 0 /* EQ_B2_A - [15:0] */
686#define WM9081_EQ_B2_A_WIDTH 16 /* EQ_B2_A - [15:0] */
687
688/*
689 * R48 (0x30) - EQ 7
690 */
691#define WM9081_EQ_B2_B_MASK 0xFFFF /* EQ_B2_B - [15:0] */
692#define WM9081_EQ_B2_B_SHIFT 0 /* EQ_B2_B - [15:0] */
693#define WM9081_EQ_B2_B_WIDTH 16 /* EQ_B2_B - [15:0] */
694
695/*
696 * R49 (0x31) - EQ 8
697 */
698#define WM9081_EQ_B2_C_MASK 0xFFFF /* EQ_B2_C - [15:0] */
699#define WM9081_EQ_B2_C_SHIFT 0 /* EQ_B2_C - [15:0] */
700#define WM9081_EQ_B2_C_WIDTH 16 /* EQ_B2_C - [15:0] */
701
702/*
703 * R50 (0x32) - EQ 9
704 */
705#define WM9081_EQ_B2_PG_MASK 0xFFFF /* EQ_B2_PG - [15:0] */
706#define WM9081_EQ_B2_PG_SHIFT 0 /* EQ_B2_PG - [15:0] */
707#define WM9081_EQ_B2_PG_WIDTH 16 /* EQ_B2_PG - [15:0] */
708
709/*
710 * R51 (0x33) - EQ 10
711 */
712#define WM9081_EQ_B4_A_MASK 0xFFFF /* EQ_B4_A - [15:0] */
713#define WM9081_EQ_B4_A_SHIFT 0 /* EQ_B4_A - [15:0] */
714#define WM9081_EQ_B4_A_WIDTH 16 /* EQ_B4_A - [15:0] */
715
716/*
717 * R52 (0x34) - EQ 11
718 */
719#define WM9081_EQ_B4_B_MASK 0xFFFF /* EQ_B4_B - [15:0] */
720#define WM9081_EQ_B4_B_SHIFT 0 /* EQ_B4_B - [15:0] */
721#define WM9081_EQ_B4_B_WIDTH 16 /* EQ_B4_B - [15:0] */
722
723/*
724 * R53 (0x35) - EQ 12
725 */
726#define WM9081_EQ_B4_C_MASK 0xFFFF /* EQ_B4_C - [15:0] */
727#define WM9081_EQ_B4_C_SHIFT 0 /* EQ_B4_C - [15:0] */
728#define WM9081_EQ_B4_C_WIDTH 16 /* EQ_B4_C - [15:0] */
729
730/*
731 * R54 (0x36) - EQ 13
732 */
733#define WM9081_EQ_B4_PG_MASK 0xFFFF /* EQ_B4_PG - [15:0] */
734#define WM9081_EQ_B4_PG_SHIFT 0 /* EQ_B4_PG - [15:0] */
735#define WM9081_EQ_B4_PG_WIDTH 16 /* EQ_B4_PG - [15:0] */
736
737/*
738 * R55 (0x37) - EQ 14
739 */
740#define WM9081_EQ_B3_A_MASK 0xFFFF /* EQ_B3_A - [15:0] */
741#define WM9081_EQ_B3_A_SHIFT 0 /* EQ_B3_A - [15:0] */
742#define WM9081_EQ_B3_A_WIDTH 16 /* EQ_B3_A - [15:0] */
743
744/*
745 * R56 (0x38) - EQ 15
746 */
747#define WM9081_EQ_B3_B_MASK 0xFFFF /* EQ_B3_B - [15:0] */
748#define WM9081_EQ_B3_B_SHIFT 0 /* EQ_B3_B - [15:0] */
749#define WM9081_EQ_B3_B_WIDTH 16 /* EQ_B3_B - [15:0] */
750
751/*
752 * R57 (0x39) - EQ 16
753 */
754#define WM9081_EQ_B3_C_MASK 0xFFFF /* EQ_B3_C - [15:0] */
755#define WM9081_EQ_B3_C_SHIFT 0 /* EQ_B3_C - [15:0] */
756#define WM9081_EQ_B3_C_WIDTH 16 /* EQ_B3_C - [15:0] */
757
758/*
759 * R58 (0x3A) - EQ 17
760 */
761#define WM9081_EQ_B3_PG_MASK 0xFFFF /* EQ_B3_PG - [15:0] */
762#define WM9081_EQ_B3_PG_SHIFT 0 /* EQ_B3_PG - [15:0] */
763#define WM9081_EQ_B3_PG_WIDTH 16 /* EQ_B3_PG - [15:0] */
764
765/*
766 * R59 (0x3B) - EQ 18
767 */
768#define WM9081_EQ_B5_A_MASK 0xFFFF /* EQ_B5_A - [15:0] */
769#define WM9081_EQ_B5_A_SHIFT 0 /* EQ_B5_A - [15:0] */
770#define WM9081_EQ_B5_A_WIDTH 16 /* EQ_B5_A - [15:0] */
771
772/*
773 * R60 (0x3C) - EQ 19
774 */
775#define WM9081_EQ_B5_B_MASK 0xFFFF /* EQ_B5_B - [15:0] */
776#define WM9081_EQ_B5_B_SHIFT 0 /* EQ_B5_B - [15:0] */
777#define WM9081_EQ_B5_B_WIDTH 16 /* EQ_B5_B - [15:0] */
778
779/*
780 * R61 (0x3D) - EQ 20
781 */
782#define WM9081_EQ_B5_PG_MASK 0xFFFF /* EQ_B5_PG - [15:0] */
783#define WM9081_EQ_B5_PG_SHIFT 0 /* EQ_B5_PG - [15:0] */
784#define WM9081_EQ_B5_PG_WIDTH 16 /* EQ_B5_PG - [15:0] */
785
786
787#endif
diff --git a/sound/soc/codecs/wm9705.c b/sound/soc/codecs/wm9705.c
index c2d1a7a18fa3..fa88b463e71f 100644
--- a/sound/soc/codecs/wm9705.c
+++ b/sound/soc/codecs/wm9705.c
@@ -282,14 +282,14 @@ struct snd_soc_dai wm9705_dai[] = {
282 .channels_min = 1, 282 .channels_min = 1,
283 .channels_max = 2, 283 .channels_max = 2,
284 .rates = WM9705_AC97_RATES, 284 .rates = WM9705_AC97_RATES,
285 .formats = SNDRV_PCM_FMTBIT_S16_LE, 285 .formats = SND_SOC_STD_AC97_FMTS,
286 }, 286 },
287 .capture = { 287 .capture = {
288 .stream_name = "HiFi Capture", 288 .stream_name = "HiFi Capture",
289 .channels_min = 1, 289 .channels_min = 1,
290 .channels_max = 2, 290 .channels_max = 2,
291 .rates = WM9705_AC97_RATES, 291 .rates = WM9705_AC97_RATES,
292 .formats = SNDRV_PCM_FMTBIT_S16_LE, 292 .formats = SND_SOC_STD_AC97_FMTS,
293 }, 293 },
294 .ops = &wm9705_dai_ops, 294 .ops = &wm9705_dai_ops,
295 }, 295 },
diff --git a/sound/soc/codecs/wm9712.c b/sound/soc/codecs/wm9712.c
index 765cf1e7369e..1fd4e88f50cf 100644
--- a/sound/soc/codecs/wm9712.c
+++ b/sound/soc/codecs/wm9712.c
@@ -534,13 +534,13 @@ struct snd_soc_dai wm9712_dai[] = {
534 .channels_min = 1, 534 .channels_min = 1,
535 .channels_max = 2, 535 .channels_max = 2,
536 .rates = WM9712_AC97_RATES, 536 .rates = WM9712_AC97_RATES,
537 .formats = SNDRV_PCM_FMTBIT_S16_LE,}, 537 .formats = SND_SOC_STD_AC97_FMTS,},
538 .capture = { 538 .capture = {
539 .stream_name = "HiFi Capture", 539 .stream_name = "HiFi Capture",
540 .channels_min = 1, 540 .channels_min = 1,
541 .channels_max = 2, 541 .channels_max = 2,
542 .rates = WM9712_AC97_RATES, 542 .rates = WM9712_AC97_RATES,
543 .formats = SNDRV_PCM_FMTBIT_S16_LE,}, 543 .formats = SND_SOC_STD_AC97_FMTS,},
544 .ops = &wm9712_dai_ops_hifi, 544 .ops = &wm9712_dai_ops_hifi,
545}, 545},
546{ 546{
@@ -550,7 +550,7 @@ struct snd_soc_dai wm9712_dai[] = {
550 .channels_min = 1, 550 .channels_min = 1,
551 .channels_max = 1, 551 .channels_max = 1,
552 .rates = WM9712_AC97_RATES, 552 .rates = WM9712_AC97_RATES,
553 .formats = SNDRV_PCM_FMTBIT_S16_LE,}, 553 .formats = SND_SOC_STD_AC97_FMTS,},
554 .ops = &wm9712_dai_ops_aux, 554 .ops = &wm9712_dai_ops_aux,
555} 555}
556}; 556};
@@ -585,6 +585,8 @@ static int wm9712_reset(struct snd_soc_codec *codec, int try_warm)
585 } 585 }
586 586
587 soc_ac97_ops.reset(codec->ac97); 587 soc_ac97_ops.reset(codec->ac97);
588 if (soc_ac97_ops.warm_reset)
589 soc_ac97_ops.warm_reset(codec->ac97);
588 if (ac97_read(codec, 0) != wm9712_reg[0]) 590 if (ac97_read(codec, 0) != wm9712_reg[0])
589 goto err; 591 goto err;
590 return 0; 592 return 0;
diff --git a/sound/soc/codecs/wm9713.c b/sound/soc/codecs/wm9713.c
index 523bad077fa0..abed37acf787 100644
--- a/sound/soc/codecs/wm9713.c
+++ b/sound/soc/codecs/wm9713.c
@@ -189,6 +189,26 @@ SOC_SINGLE("3D Lower Cut-off Switch", AC97_REC_GAIN_MIC, 4, 1, 0),
189SOC_SINGLE("3D Depth", AC97_REC_GAIN_MIC, 0, 15, 1), 189SOC_SINGLE("3D Depth", AC97_REC_GAIN_MIC, 0, 15, 1),
190}; 190};
191 191
192static int wm9713_voice_shutdown(struct snd_soc_dapm_widget *w,
193 struct snd_kcontrol *kcontrol, int event)
194{
195 struct snd_soc_codec *codec = w->codec;
196 u16 status, rate;
197
198 BUG_ON(event != SND_SOC_DAPM_PRE_PMD);
199
200 /* Gracefully shut down the voice interface. */
201 status = ac97_read(codec, AC97_EXTENDED_MID) | 0x1000;
202 rate = ac97_read(codec, AC97_HANDSET_RATE) & 0xF0FF;
203 ac97_write(codec, AC97_HANDSET_RATE, rate | 0x0200);
204 schedule_timeout_interruptible(msecs_to_jiffies(1));
205 ac97_write(codec, AC97_HANDSET_RATE, rate | 0x0F00);
206 ac97_write(codec, AC97_EXTENDED_MID, status);
207
208 return 0;
209}
210
211
192/* We have to create a fake left and right HP mixers because 212/* We have to create a fake left and right HP mixers because
193 * the codec only has a single control that is shared by both channels. 213 * the codec only has a single control that is shared by both channels.
194 * This makes it impossible to determine the audio path using the current 214 * This makes it impossible to determine the audio path using the current
@@ -400,7 +420,8 @@ SND_SOC_DAPM_MIXER("AC97 Mixer", SND_SOC_NOPM, 0, 0, NULL, 0),
400SND_SOC_DAPM_MIXER("HP Mixer", SND_SOC_NOPM, 0, 0, NULL, 0), 420SND_SOC_DAPM_MIXER("HP Mixer", SND_SOC_NOPM, 0, 0, NULL, 0),
401SND_SOC_DAPM_MIXER("Line Mixer", SND_SOC_NOPM, 0, 0, NULL, 0), 421SND_SOC_DAPM_MIXER("Line Mixer", SND_SOC_NOPM, 0, 0, NULL, 0),
402SND_SOC_DAPM_MIXER("Capture Mixer", SND_SOC_NOPM, 0, 0, NULL, 0), 422SND_SOC_DAPM_MIXER("Capture Mixer", SND_SOC_NOPM, 0, 0, NULL, 0),
403SND_SOC_DAPM_DAC("Voice DAC", "Voice Playback", AC97_EXTENDED_MID, 12, 1), 423SND_SOC_DAPM_DAC_E("Voice DAC", "Voice Playback", AC97_EXTENDED_MID, 12, 1,
424 wm9713_voice_shutdown, SND_SOC_DAPM_PRE_PMD),
404SND_SOC_DAPM_DAC("Aux DAC", "Aux Playback", AC97_EXTENDED_MID, 11, 1), 425SND_SOC_DAPM_DAC("Aux DAC", "Aux Playback", AC97_EXTENDED_MID, 11, 1),
405SND_SOC_DAPM_PGA("Left ADC", AC97_EXTENDED_MID, 5, 1, NULL, 0), 426SND_SOC_DAPM_PGA("Left ADC", AC97_EXTENDED_MID, 5, 1, NULL, 0),
406SND_SOC_DAPM_PGA("Right ADC", AC97_EXTENDED_MID, 4, 1, NULL, 0), 427SND_SOC_DAPM_PGA("Right ADC", AC97_EXTENDED_MID, 4, 1, NULL, 0),
@@ -689,7 +710,7 @@ static void pll_factors(struct _pll_div *pll_div, unsigned int source)
689 Ndiv = target / source; 710 Ndiv = target / source;
690 if ((Ndiv < 5) || (Ndiv > 12)) 711 if ((Ndiv < 5) || (Ndiv > 12))
691 printk(KERN_WARNING 712 printk(KERN_WARNING
692 "WM9713 PLL N value %d out of recommended range!\n", 713 "WM9713 PLL N value %u out of recommended range!\n",
693 Ndiv); 714 Ndiv);
694 715
695 pll_div->n = Ndiv; 716 pll_div->n = Ndiv;
@@ -936,21 +957,6 @@ static int wm9713_pcm_hw_params(struct snd_pcm_substream *substream,
936 return 0; 957 return 0;
937} 958}
938 959
939static void wm9713_voiceshutdown(struct snd_pcm_substream *substream,
940 struct snd_soc_dai *dai)
941{
942 struct snd_soc_codec *codec = dai->codec;
943 u16 status, rate;
944
945 /* Gracefully shut down the voice interface. */
946 status = ac97_read(codec, AC97_EXTENDED_STATUS) | 0x1000;
947 rate = ac97_read(codec, AC97_HANDSET_RATE) & 0xF0FF;
948 ac97_write(codec, AC97_HANDSET_RATE, rate | 0x0200);
949 schedule_timeout_interruptible(msecs_to_jiffies(1));
950 ac97_write(codec, AC97_HANDSET_RATE, rate | 0x0F00);
951 ac97_write(codec, AC97_EXTENDED_MID, status);
952}
953
954static int ac97_hifi_prepare(struct snd_pcm_substream *substream, 960static int ac97_hifi_prepare(struct snd_pcm_substream *substream,
955 struct snd_soc_dai *dai) 961 struct snd_soc_dai *dai)
956{ 962{
@@ -1019,7 +1025,6 @@ static struct snd_soc_dai_ops wm9713_dai_ops_aux = {
1019 1025
1020static struct snd_soc_dai_ops wm9713_dai_ops_voice = { 1026static struct snd_soc_dai_ops wm9713_dai_ops_voice = {
1021 .hw_params = wm9713_pcm_hw_params, 1027 .hw_params = wm9713_pcm_hw_params,
1022 .shutdown = wm9713_voiceshutdown,
1023 .set_clkdiv = wm9713_set_dai_clkdiv, 1028 .set_clkdiv = wm9713_set_dai_clkdiv,
1024 .set_pll = wm9713_set_dai_pll, 1029 .set_pll = wm9713_set_dai_pll,
1025 .set_fmt = wm9713_set_dai_fmt, 1030 .set_fmt = wm9713_set_dai_fmt,
@@ -1035,13 +1040,13 @@ struct snd_soc_dai wm9713_dai[] = {
1035 .channels_min = 1, 1040 .channels_min = 1,
1036 .channels_max = 2, 1041 .channels_max = 2,
1037 .rates = WM9713_RATES, 1042 .rates = WM9713_RATES,
1038 .formats = SNDRV_PCM_FMTBIT_S16_LE,}, 1043 .formats = SND_SOC_STD_AC97_FMTS,},
1039 .capture = { 1044 .capture = {
1040 .stream_name = "HiFi Capture", 1045 .stream_name = "HiFi Capture",
1041 .channels_min = 1, 1046 .channels_min = 1,
1042 .channels_max = 2, 1047 .channels_max = 2,
1043 .rates = WM9713_RATES, 1048 .rates = WM9713_RATES,
1044 .formats = SNDRV_PCM_FMTBIT_S16_LE,}, 1049 .formats = SND_SOC_STD_AC97_FMTS,},
1045 .ops = &wm9713_dai_ops_hifi, 1050 .ops = &wm9713_dai_ops_hifi,
1046 }, 1051 },
1047 { 1052 {
@@ -1051,7 +1056,7 @@ struct snd_soc_dai wm9713_dai[] = {
1051 .channels_min = 1, 1056 .channels_min = 1,
1052 .channels_max = 1, 1057 .channels_max = 1,
1053 .rates = WM9713_RATES, 1058 .rates = WM9713_RATES,
1054 .formats = SNDRV_PCM_FMTBIT_S16_LE,}, 1059 .formats = SND_SOC_STD_AC97_FMTS,},
1055 .ops = &wm9713_dai_ops_aux, 1060 .ops = &wm9713_dai_ops_aux,
1056 }, 1061 },
1057 { 1062 {
@@ -1069,6 +1074,7 @@ struct snd_soc_dai wm9713_dai[] = {
1069 .rates = WM9713_PCM_RATES, 1074 .rates = WM9713_PCM_RATES,
1070 .formats = WM9713_PCM_FORMATS,}, 1075 .formats = WM9713_PCM_FORMATS,},
1071 .ops = &wm9713_dai_ops_voice, 1076 .ops = &wm9713_dai_ops_voice,
1077 .symmetric_rates = 1,
1072 }, 1078 },
1073}; 1079};
1074EXPORT_SYMBOL_GPL(wm9713_dai); 1080EXPORT_SYMBOL_GPL(wm9713_dai);
diff --git a/sound/soc/codecs/wm_hubs.c b/sound/soc/codecs/wm_hubs.c
new file mode 100644
index 000000000000..e8fc474ba5cf
--- /dev/null
+++ b/sound/soc/codecs/wm_hubs.c
@@ -0,0 +1,758 @@
1/*
2 * wm_hubs.c -- WM8993/4 common code
3 *
4 * Copyright 2009 Wolfson Microelectronics plc
5 *
6 * Author: Mark Brown <broonie@opensource.wolfsonmicro.com>
7 *
8 *
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License version 2 as
11 * published by the Free Software Foundation.
12 */
13
14#include <linux/module.h>
15#include <linux/moduleparam.h>
16#include <linux/init.h>
17#include <linux/delay.h>
18#include <linux/pm.h>
19#include <linux/i2c.h>
20#include <linux/platform_device.h>
21#include <linux/regulator/consumer.h>
22#include <sound/core.h>
23#include <sound/pcm.h>
24#include <sound/pcm_params.h>
25#include <sound/soc.h>
26#include <sound/soc-dapm.h>
27#include <sound/initval.h>
28#include <sound/tlv.h>
29
30#include "wm8993.h"
31#include "wm_hubs.h"
32
33const DECLARE_TLV_DB_SCALE(wm_hubs_spkmix_tlv, -300, 300, 0);
34EXPORT_SYMBOL_GPL(wm_hubs_spkmix_tlv);
35
36static const DECLARE_TLV_DB_SCALE(inpga_tlv, -1650, 150, 0);
37static const DECLARE_TLV_DB_SCALE(inmix_sw_tlv, 0, 3000, 0);
38static const DECLARE_TLV_DB_SCALE(inmix_tlv, -1500, 300, 1);
39static const DECLARE_TLV_DB_SCALE(earpiece_tlv, -600, 600, 0);
40static const DECLARE_TLV_DB_SCALE(outmix_tlv, -2100, 300, 0);
41static const DECLARE_TLV_DB_SCALE(spkmixout_tlv, -1800, 600, 1);
42static const DECLARE_TLV_DB_SCALE(outpga_tlv, -5700, 100, 0);
43static const unsigned int spkboost_tlv[] = {
44 TLV_DB_RANGE_HEAD(7),
45 0, 6, TLV_DB_SCALE_ITEM(0, 150, 0),
46 7, 7, TLV_DB_SCALE_ITEM(1200, 0, 0),
47};
48static const DECLARE_TLV_DB_SCALE(line_tlv, -600, 600, 0);
49
50static const char *speaker_ref_text[] = {
51 "SPKVDD/2",
52 "VMID",
53};
54
55static const struct soc_enum speaker_ref =
56 SOC_ENUM_SINGLE(WM8993_SPEAKER_MIXER, 8, 2, speaker_ref_text);
57
58static const char *speaker_mode_text[] = {
59 "Class D",
60 "Class AB",
61};
62
63static const struct soc_enum speaker_mode =
64 SOC_ENUM_SINGLE(WM8993_SPKMIXR_ATTENUATION, 8, 2, speaker_mode_text);
65
66static void wait_for_dc_servo(struct snd_soc_codec *codec)
67{
68 unsigned int reg;
69 int count = 0;
70
71 dev_dbg(codec->dev, "Waiting for DC servo...\n");
72 do {
73 count++;
74 msleep(1);
75 reg = snd_soc_read(codec, WM8993_DC_SERVO_READBACK_0);
76 dev_dbg(codec->dev, "DC servo status: %x\n", reg);
77 } while ((reg & WM8993_DCS_CAL_COMPLETE_MASK)
78 != WM8993_DCS_CAL_COMPLETE_MASK && count < 1000);
79
80 if ((reg & WM8993_DCS_CAL_COMPLETE_MASK)
81 != WM8993_DCS_CAL_COMPLETE_MASK)
82 dev_err(codec->dev, "Timed out waiting for DC Servo\n");
83}
84
85/*
86 * Update the DC servo calibration on gain changes
87 */
88static int wm8993_put_dc_servo(struct snd_kcontrol *kcontrol,
89 struct snd_ctl_elem_value *ucontrol)
90{
91 struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
92 int ret;
93
94 ret = snd_soc_put_volsw_2r(kcontrol, ucontrol);
95
96 /* Only need to do this if the outputs are active */
97 if (snd_soc_read(codec, WM8993_POWER_MANAGEMENT_1)
98 & (WM8993_HPOUT1L_ENA | WM8993_HPOUT1R_ENA))
99 snd_soc_update_bits(codec,
100 WM8993_DC_SERVO_0,
101 WM8993_DCS_TRIG_SINGLE_0 |
102 WM8993_DCS_TRIG_SINGLE_1,
103 WM8993_DCS_TRIG_SINGLE_0 |
104 WM8993_DCS_TRIG_SINGLE_1);
105
106 return ret;
107}
108
109static const struct snd_kcontrol_new analogue_snd_controls[] = {
110SOC_SINGLE_TLV("IN1L Volume", WM8993_LEFT_LINE_INPUT_1_2_VOLUME, 0, 31, 0,
111 inpga_tlv),
112SOC_SINGLE("IN1L Switch", WM8993_LEFT_LINE_INPUT_1_2_VOLUME, 7, 1, 1),
113SOC_SINGLE("IN1L ZC Switch", WM8993_LEFT_LINE_INPUT_1_2_VOLUME, 7, 1, 0),
114
115SOC_SINGLE_TLV("IN1R Volume", WM8993_RIGHT_LINE_INPUT_1_2_VOLUME, 0, 31, 0,
116 inpga_tlv),
117SOC_SINGLE("IN1R Switch", WM8993_RIGHT_LINE_INPUT_1_2_VOLUME, 7, 1, 1),
118SOC_SINGLE("IN1R ZC Switch", WM8993_RIGHT_LINE_INPUT_1_2_VOLUME, 7, 1, 0),
119
120
121SOC_SINGLE_TLV("IN2L Volume", WM8993_LEFT_LINE_INPUT_3_4_VOLUME, 0, 31, 0,
122 inpga_tlv),
123SOC_SINGLE("IN2L Switch", WM8993_LEFT_LINE_INPUT_3_4_VOLUME, 7, 1, 1),
124SOC_SINGLE("IN2L ZC Switch", WM8993_LEFT_LINE_INPUT_3_4_VOLUME, 7, 1, 0),
125
126SOC_SINGLE_TLV("IN2R Volume", WM8993_RIGHT_LINE_INPUT_3_4_VOLUME, 0, 31, 0,
127 inpga_tlv),
128SOC_SINGLE("IN2R Switch", WM8993_RIGHT_LINE_INPUT_3_4_VOLUME, 7, 1, 1),
129SOC_SINGLE("IN2R ZC Switch", WM8993_RIGHT_LINE_INPUT_3_4_VOLUME, 7, 1, 0),
130
131SOC_SINGLE_TLV("MIXINL IN2L Volume", WM8993_INPUT_MIXER3, 7, 1, 0,
132 inmix_sw_tlv),
133SOC_SINGLE_TLV("MIXINL IN1L Volume", WM8993_INPUT_MIXER3, 4, 1, 0,
134 inmix_sw_tlv),
135SOC_SINGLE_TLV("MIXINL Output Record Volume", WM8993_INPUT_MIXER3, 0, 7, 0,
136 inmix_tlv),
137SOC_SINGLE_TLV("MIXINL IN1LP Volume", WM8993_INPUT_MIXER5, 6, 7, 0, inmix_tlv),
138SOC_SINGLE_TLV("MIXINL Direct Voice Volume", WM8993_INPUT_MIXER5, 0, 6, 0,
139 inmix_tlv),
140
141SOC_SINGLE_TLV("MIXINR IN2R Volume", WM8993_INPUT_MIXER4, 7, 1, 0,
142 inmix_sw_tlv),
143SOC_SINGLE_TLV("MIXINR IN1R Volume", WM8993_INPUT_MIXER4, 4, 1, 0,
144 inmix_sw_tlv),
145SOC_SINGLE_TLV("MIXINR Output Record Volume", WM8993_INPUT_MIXER4, 0, 7, 0,
146 inmix_tlv),
147SOC_SINGLE_TLV("MIXINR IN1RP Volume", WM8993_INPUT_MIXER6, 6, 7, 0, inmix_tlv),
148SOC_SINGLE_TLV("MIXINR Direct Voice Volume", WM8993_INPUT_MIXER6, 0, 6, 0,
149 inmix_tlv),
150
151SOC_SINGLE_TLV("Left Output Mixer IN2RN Volume", WM8993_OUTPUT_MIXER5, 6, 7, 1,
152 outmix_tlv),
153SOC_SINGLE_TLV("Left Output Mixer IN2LN Volume", WM8993_OUTPUT_MIXER3, 6, 7, 1,
154 outmix_tlv),
155SOC_SINGLE_TLV("Left Output Mixer IN2LP Volume", WM8993_OUTPUT_MIXER3, 9, 7, 1,
156 outmix_tlv),
157SOC_SINGLE_TLV("Left Output Mixer IN1L Volume", WM8993_OUTPUT_MIXER3, 0, 7, 1,
158 outmix_tlv),
159SOC_SINGLE_TLV("Left Output Mixer IN1R Volume", WM8993_OUTPUT_MIXER3, 3, 7, 1,
160 outmix_tlv),
161SOC_SINGLE_TLV("Left Output Mixer Right Input Volume",
162 WM8993_OUTPUT_MIXER5, 3, 7, 1, outmix_tlv),
163SOC_SINGLE_TLV("Left Output Mixer Left Input Volume",
164 WM8993_OUTPUT_MIXER5, 0, 7, 1, outmix_tlv),
165SOC_SINGLE_TLV("Left Output Mixer DAC Volume", WM8993_OUTPUT_MIXER5, 9, 7, 1,
166 outmix_tlv),
167
168SOC_SINGLE_TLV("Right Output Mixer IN2LN Volume",
169 WM8993_OUTPUT_MIXER6, 6, 7, 1, outmix_tlv),
170SOC_SINGLE_TLV("Right Output Mixer IN2RN Volume",
171 WM8993_OUTPUT_MIXER4, 6, 7, 1, outmix_tlv),
172SOC_SINGLE_TLV("Right Output Mixer IN1L Volume",
173 WM8993_OUTPUT_MIXER4, 3, 7, 1, outmix_tlv),
174SOC_SINGLE_TLV("Right Output Mixer IN1R Volume",
175 WM8993_OUTPUT_MIXER4, 0, 7, 1, outmix_tlv),
176SOC_SINGLE_TLV("Right Output Mixer IN2RP Volume",
177 WM8993_OUTPUT_MIXER4, 9, 7, 1, outmix_tlv),
178SOC_SINGLE_TLV("Right Output Mixer Left Input Volume",
179 WM8993_OUTPUT_MIXER6, 3, 7, 1, outmix_tlv),
180SOC_SINGLE_TLV("Right Output Mixer Right Input Volume",
181 WM8993_OUTPUT_MIXER6, 6, 7, 1, outmix_tlv),
182SOC_SINGLE_TLV("Right Output Mixer DAC Volume",
183 WM8993_OUTPUT_MIXER6, 9, 7, 1, outmix_tlv),
184
185SOC_DOUBLE_R_TLV("Output Volume", WM8993_LEFT_OPGA_VOLUME,
186 WM8993_RIGHT_OPGA_VOLUME, 0, 63, 0, outpga_tlv),
187SOC_DOUBLE_R("Output Switch", WM8993_LEFT_OPGA_VOLUME,
188 WM8993_RIGHT_OPGA_VOLUME, 6, 1, 0),
189SOC_DOUBLE_R("Output ZC Switch", WM8993_LEFT_OPGA_VOLUME,
190 WM8993_RIGHT_OPGA_VOLUME, 7, 1, 0),
191
192SOC_SINGLE("Earpiece Switch", WM8993_HPOUT2_VOLUME, 5, 1, 1),
193SOC_SINGLE_TLV("Earpiece Volume", WM8993_HPOUT2_VOLUME, 4, 1, 1, earpiece_tlv),
194
195SOC_SINGLE_TLV("SPKL Input Volume", WM8993_SPKMIXL_ATTENUATION,
196 5, 1, 1, wm_hubs_spkmix_tlv),
197SOC_SINGLE_TLV("SPKL IN1LP Volume", WM8993_SPKMIXL_ATTENUATION,
198 4, 1, 1, wm_hubs_spkmix_tlv),
199SOC_SINGLE_TLV("SPKL Output Volume", WM8993_SPKMIXL_ATTENUATION,
200 3, 1, 1, wm_hubs_spkmix_tlv),
201
202SOC_SINGLE_TLV("SPKR Input Volume", WM8993_SPKMIXR_ATTENUATION,
203 5, 1, 1, wm_hubs_spkmix_tlv),
204SOC_SINGLE_TLV("SPKR IN1RP Volume", WM8993_SPKMIXR_ATTENUATION,
205 4, 1, 1, wm_hubs_spkmix_tlv),
206SOC_SINGLE_TLV("SPKR Output Volume", WM8993_SPKMIXR_ATTENUATION,
207 3, 1, 1, wm_hubs_spkmix_tlv),
208
209SOC_DOUBLE_R_TLV("Speaker Mixer Volume",
210 WM8993_SPKMIXL_ATTENUATION, WM8993_SPKMIXR_ATTENUATION,
211 0, 3, 1, spkmixout_tlv),
212SOC_DOUBLE_R_TLV("Speaker Volume",
213 WM8993_SPEAKER_VOLUME_LEFT, WM8993_SPEAKER_VOLUME_RIGHT,
214 0, 63, 0, outpga_tlv),
215SOC_DOUBLE_R("Speaker Switch",
216 WM8993_SPEAKER_VOLUME_LEFT, WM8993_SPEAKER_VOLUME_RIGHT,
217 6, 1, 0),
218SOC_DOUBLE_R("Speaker ZC Switch",
219 WM8993_SPEAKER_VOLUME_LEFT, WM8993_SPEAKER_VOLUME_RIGHT,
220 7, 1, 0),
221SOC_DOUBLE_TLV("Speaker Boost Volume", WM8993_SPKOUT_BOOST, 0, 3, 7, 0,
222 spkboost_tlv),
223SOC_ENUM("Speaker Reference", speaker_ref),
224SOC_ENUM("Speaker Mode", speaker_mode),
225
226{
227 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = "Headphone Volume",
228 .access = SNDRV_CTL_ELEM_ACCESS_TLV_READ |
229 SNDRV_CTL_ELEM_ACCESS_READWRITE,
230 .tlv.p = outpga_tlv,
231 .info = snd_soc_info_volsw_2r,
232 .get = snd_soc_get_volsw_2r, .put = wm8993_put_dc_servo,
233 .private_value = (unsigned long)&(struct soc_mixer_control) {
234 .reg = WM8993_LEFT_OUTPUT_VOLUME,
235 .rreg = WM8993_RIGHT_OUTPUT_VOLUME,
236 .shift = 0, .max = 63
237 },
238},
239SOC_DOUBLE_R("Headphone Switch", WM8993_LEFT_OUTPUT_VOLUME,
240 WM8993_RIGHT_OUTPUT_VOLUME, 6, 1, 0),
241SOC_DOUBLE_R("Headphone ZC Switch", WM8993_LEFT_OUTPUT_VOLUME,
242 WM8993_RIGHT_OUTPUT_VOLUME, 7, 1, 0),
243
244SOC_SINGLE("LINEOUT1N Switch", WM8993_LINE_OUTPUTS_VOLUME, 6, 1, 1),
245SOC_SINGLE("LINEOUT1P Switch", WM8993_LINE_OUTPUTS_VOLUME, 5, 1, 1),
246SOC_SINGLE_TLV("LINEOUT1 Volume", WM8993_LINE_OUTPUTS_VOLUME, 4, 1, 1,
247 line_tlv),
248
249SOC_SINGLE("LINEOUT2N Switch", WM8993_LINE_OUTPUTS_VOLUME, 2, 1, 1),
250SOC_SINGLE("LINEOUT2P Switch", WM8993_LINE_OUTPUTS_VOLUME, 1, 1, 1),
251SOC_SINGLE_TLV("LINEOUT2 Volume", WM8993_LINE_OUTPUTS_VOLUME, 0, 1, 1,
252 line_tlv),
253};
254
255static int hp_event(struct snd_soc_dapm_widget *w,
256 struct snd_kcontrol *kcontrol, int event)
257{
258 struct snd_soc_codec *codec = w->codec;
259 unsigned int reg = snd_soc_read(codec, WM8993_ANALOGUE_HP_0);
260
261 switch (event) {
262 case SND_SOC_DAPM_POST_PMU:
263 snd_soc_update_bits(codec, WM8993_CHARGE_PUMP_1,
264 WM8993_CP_ENA, WM8993_CP_ENA);
265
266 msleep(5);
267
268 snd_soc_update_bits(codec, WM8993_POWER_MANAGEMENT_1,
269 WM8993_HPOUT1L_ENA | WM8993_HPOUT1R_ENA,
270 WM8993_HPOUT1L_ENA | WM8993_HPOUT1R_ENA);
271
272 reg |= WM8993_HPOUT1L_DLY | WM8993_HPOUT1R_DLY;
273 snd_soc_write(codec, WM8993_ANALOGUE_HP_0, reg);
274
275 /* Start the DC servo */
276 snd_soc_update_bits(codec, WM8993_DC_SERVO_0,
277 WM8993_DCS_ENA_CHAN_0 |
278 WM8993_DCS_ENA_CHAN_1 |
279 WM8993_DCS_TRIG_STARTUP_1 |
280 WM8993_DCS_TRIG_STARTUP_0,
281 WM8993_DCS_ENA_CHAN_0 |
282 WM8993_DCS_ENA_CHAN_1 |
283 WM8993_DCS_TRIG_STARTUP_1 |
284 WM8993_DCS_TRIG_STARTUP_0);
285 wait_for_dc_servo(codec);
286 snd_soc_update_bits(codec, WM8993_DC_SERVO_1,
287 WM8993_DCS_TIMER_PERIOD_01_MASK, 0xa);
288
289 reg |= WM8993_HPOUT1R_OUTP | WM8993_HPOUT1R_RMV_SHORT |
290 WM8993_HPOUT1L_OUTP | WM8993_HPOUT1L_RMV_SHORT;
291 snd_soc_write(codec, WM8993_ANALOGUE_HP_0, reg);
292 break;
293
294 case SND_SOC_DAPM_PRE_PMD:
295 reg &= ~(WM8993_HPOUT1L_RMV_SHORT |
296 WM8993_HPOUT1L_DLY |
297 WM8993_HPOUT1L_OUTP |
298 WM8993_HPOUT1R_RMV_SHORT |
299 WM8993_HPOUT1R_DLY |
300 WM8993_HPOUT1R_OUTP);
301
302 snd_soc_update_bits(codec, WM8993_DC_SERVO_1,
303 WM8993_DCS_TIMER_PERIOD_01_MASK, 0);
304 snd_soc_update_bits(codec, WM8993_DC_SERVO_0,
305 WM8993_DCS_ENA_CHAN_0 |
306 WM8993_DCS_ENA_CHAN_1, 0);
307
308 snd_soc_write(codec, WM8993_ANALOGUE_HP_0, reg);
309 snd_soc_update_bits(codec, WM8993_POWER_MANAGEMENT_1,
310 WM8993_HPOUT1L_ENA | WM8993_HPOUT1R_ENA,
311 0);
312
313 snd_soc_update_bits(codec, WM8993_CHARGE_PUMP_1,
314 WM8993_CP_ENA, 0);
315 break;
316 }
317
318 return 0;
319}
320
321static int earpiece_event(struct snd_soc_dapm_widget *w,
322 struct snd_kcontrol *control, int event)
323{
324 struct snd_soc_codec *codec = w->codec;
325 u16 reg = snd_soc_read(codec, WM8993_ANTIPOP1) & ~WM8993_HPOUT2_IN_ENA;
326
327 switch (event) {
328 case SND_SOC_DAPM_PRE_PMU:
329 reg |= WM8993_HPOUT2_IN_ENA;
330 snd_soc_write(codec, WM8993_ANTIPOP1, reg);
331 udelay(50);
332 break;
333
334 case SND_SOC_DAPM_POST_PMD:
335 snd_soc_write(codec, WM8993_ANTIPOP1, reg);
336 break;
337
338 default:
339 BUG();
340 break;
341 }
342
343 return 0;
344}
345
346static const struct snd_kcontrol_new in1l_pga[] = {
347SOC_DAPM_SINGLE("IN1LP Switch", WM8993_INPUT_MIXER2, 5, 1, 0),
348SOC_DAPM_SINGLE("IN1LN Switch", WM8993_INPUT_MIXER2, 4, 1, 0),
349};
350
351static const struct snd_kcontrol_new in1r_pga[] = {
352SOC_DAPM_SINGLE("IN1RP Switch", WM8993_INPUT_MIXER2, 1, 1, 0),
353SOC_DAPM_SINGLE("IN1RN Switch", WM8993_INPUT_MIXER2, 0, 1, 0),
354};
355
356static const struct snd_kcontrol_new in2l_pga[] = {
357SOC_DAPM_SINGLE("IN2LP Switch", WM8993_INPUT_MIXER2, 7, 1, 0),
358SOC_DAPM_SINGLE("IN2LN Switch", WM8993_INPUT_MIXER2, 6, 1, 0),
359};
360
361static const struct snd_kcontrol_new in2r_pga[] = {
362SOC_DAPM_SINGLE("IN2RP Switch", WM8993_INPUT_MIXER2, 3, 1, 0),
363SOC_DAPM_SINGLE("IN2RN Switch", WM8993_INPUT_MIXER2, 2, 1, 0),
364};
365
366static const struct snd_kcontrol_new mixinl[] = {
367SOC_DAPM_SINGLE("IN2L Switch", WM8993_INPUT_MIXER3, 8, 1, 0),
368SOC_DAPM_SINGLE("IN1L Switch", WM8993_INPUT_MIXER3, 5, 1, 0),
369};
370
371static const struct snd_kcontrol_new mixinr[] = {
372SOC_DAPM_SINGLE("IN2R Switch", WM8993_INPUT_MIXER4, 8, 1, 0),
373SOC_DAPM_SINGLE("IN1R Switch", WM8993_INPUT_MIXER4, 5, 1, 0),
374};
375
376static const struct snd_kcontrol_new left_output_mixer[] = {
377SOC_DAPM_SINGLE("Right Input Switch", WM8993_OUTPUT_MIXER1, 7, 1, 0),
378SOC_DAPM_SINGLE("Left Input Switch", WM8993_OUTPUT_MIXER1, 6, 1, 0),
379SOC_DAPM_SINGLE("IN2RN Switch", WM8993_OUTPUT_MIXER1, 5, 1, 0),
380SOC_DAPM_SINGLE("IN2LN Switch", WM8993_OUTPUT_MIXER1, 4, 1, 0),
381SOC_DAPM_SINGLE("IN2LP Switch", WM8993_OUTPUT_MIXER1, 1, 1, 0),
382SOC_DAPM_SINGLE("IN1R Switch", WM8993_OUTPUT_MIXER1, 3, 1, 0),
383SOC_DAPM_SINGLE("IN1L Switch", WM8993_OUTPUT_MIXER1, 2, 1, 0),
384SOC_DAPM_SINGLE("DAC Switch", WM8993_OUTPUT_MIXER1, 0, 1, 0),
385};
386
387static const struct snd_kcontrol_new right_output_mixer[] = {
388SOC_DAPM_SINGLE("Left Input Switch", WM8993_OUTPUT_MIXER2, 7, 1, 0),
389SOC_DAPM_SINGLE("Right Input Switch", WM8993_OUTPUT_MIXER2, 6, 1, 0),
390SOC_DAPM_SINGLE("IN2LN Switch", WM8993_OUTPUT_MIXER2, 5, 1, 0),
391SOC_DAPM_SINGLE("IN2RN Switch", WM8993_OUTPUT_MIXER2, 4, 1, 0),
392SOC_DAPM_SINGLE("IN1L Switch", WM8993_OUTPUT_MIXER2, 3, 1, 0),
393SOC_DAPM_SINGLE("IN1R Switch", WM8993_OUTPUT_MIXER2, 2, 1, 0),
394SOC_DAPM_SINGLE("IN2RP Switch", WM8993_OUTPUT_MIXER2, 1, 1, 0),
395SOC_DAPM_SINGLE("DAC Switch", WM8993_OUTPUT_MIXER2, 0, 1, 0),
396};
397
398static const struct snd_kcontrol_new earpiece_mixer[] = {
399SOC_DAPM_SINGLE("Direct Voice Switch", WM8993_HPOUT2_MIXER, 5, 1, 0),
400SOC_DAPM_SINGLE("Left Output Switch", WM8993_HPOUT2_MIXER, 4, 1, 0),
401SOC_DAPM_SINGLE("Right Output Switch", WM8993_HPOUT2_MIXER, 3, 1, 0),
402};
403
404static const struct snd_kcontrol_new left_speaker_boost[] = {
405SOC_DAPM_SINGLE("Direct Voice Switch", WM8993_SPKOUT_MIXERS, 5, 1, 0),
406SOC_DAPM_SINGLE("SPKL Switch", WM8993_SPKOUT_MIXERS, 4, 1, 0),
407SOC_DAPM_SINGLE("SPKR Switch", WM8993_SPKOUT_MIXERS, 3, 1, 0),
408};
409
410static const struct snd_kcontrol_new right_speaker_boost[] = {
411SOC_DAPM_SINGLE("Direct Voice Switch", WM8993_SPKOUT_MIXERS, 2, 1, 0),
412SOC_DAPM_SINGLE("SPKL Switch", WM8993_SPKOUT_MIXERS, 1, 1, 0),
413SOC_DAPM_SINGLE("SPKR Switch", WM8993_SPKOUT_MIXERS, 0, 1, 0),
414};
415
416static const struct snd_kcontrol_new line1_mix[] = {
417SOC_DAPM_SINGLE("IN1R Switch", WM8993_LINE_MIXER1, 2, 1, 0),
418SOC_DAPM_SINGLE("IN1L Switch", WM8993_LINE_MIXER1, 1, 1, 0),
419SOC_DAPM_SINGLE("Output Switch", WM8993_LINE_MIXER1, 0, 1, 0),
420};
421
422static const struct snd_kcontrol_new line1n_mix[] = {
423SOC_DAPM_SINGLE("Left Output Switch", WM8993_LINE_MIXER1, 6, 1, 0),
424SOC_DAPM_SINGLE("Right Output Switch", WM8993_LINE_MIXER1, 5, 1, 0),
425};
426
427static const struct snd_kcontrol_new line1p_mix[] = {
428SOC_DAPM_SINGLE("Left Output Switch", WM8993_LINE_MIXER1, 0, 1, 0),
429};
430
431static const struct snd_kcontrol_new line2_mix[] = {
432SOC_DAPM_SINGLE("IN2R Switch", WM8993_LINE_MIXER2, 2, 1, 0),
433SOC_DAPM_SINGLE("IN2L Switch", WM8993_LINE_MIXER2, 1, 1, 0),
434SOC_DAPM_SINGLE("Output Switch", WM8993_LINE_MIXER2, 0, 1, 0),
435};
436
437static const struct snd_kcontrol_new line2n_mix[] = {
438SOC_DAPM_SINGLE("Left Output Switch", WM8993_LINE_MIXER2, 6, 1, 0),
439SOC_DAPM_SINGLE("Right Output Switch", WM8993_LINE_MIXER2, 5, 1, 0),
440};
441
442static const struct snd_kcontrol_new line2p_mix[] = {
443SOC_DAPM_SINGLE("Right Output Switch", WM8993_LINE_MIXER2, 0, 1, 0),
444};
445
446static const struct snd_soc_dapm_widget analogue_dapm_widgets[] = {
447SND_SOC_DAPM_INPUT("IN1LN"),
448SND_SOC_DAPM_INPUT("IN1LP"),
449SND_SOC_DAPM_INPUT("IN2LN"),
450SND_SOC_DAPM_INPUT("IN2LP/VXRN"),
451SND_SOC_DAPM_INPUT("IN1RN"),
452SND_SOC_DAPM_INPUT("IN1RP"),
453SND_SOC_DAPM_INPUT("IN2RN"),
454SND_SOC_DAPM_INPUT("IN2RP/VXRP"),
455
456SND_SOC_DAPM_MICBIAS("MICBIAS2", WM8993_POWER_MANAGEMENT_1, 5, 0),
457SND_SOC_DAPM_MICBIAS("MICBIAS1", WM8993_POWER_MANAGEMENT_1, 4, 0),
458
459SND_SOC_DAPM_MIXER("IN1L PGA", WM8993_POWER_MANAGEMENT_2, 6, 0,
460 in1l_pga, ARRAY_SIZE(in1l_pga)),
461SND_SOC_DAPM_MIXER("IN1R PGA", WM8993_POWER_MANAGEMENT_2, 4, 0,
462 in1r_pga, ARRAY_SIZE(in1r_pga)),
463
464SND_SOC_DAPM_MIXER("IN2L PGA", WM8993_POWER_MANAGEMENT_2, 7, 0,
465 in2l_pga, ARRAY_SIZE(in2l_pga)),
466SND_SOC_DAPM_MIXER("IN2R PGA", WM8993_POWER_MANAGEMENT_2, 5, 0,
467 in2r_pga, ARRAY_SIZE(in2r_pga)),
468
469/* Dummy widgets to represent differential paths */
470SND_SOC_DAPM_PGA("Direct Voice", SND_SOC_NOPM, 0, 0, NULL, 0),
471
472SND_SOC_DAPM_MIXER("MIXINL", WM8993_POWER_MANAGEMENT_2, 9, 0,
473 mixinl, ARRAY_SIZE(mixinl)),
474SND_SOC_DAPM_MIXER("MIXINR", WM8993_POWER_MANAGEMENT_2, 8, 0,
475 mixinr, ARRAY_SIZE(mixinr)),
476
477SND_SOC_DAPM_ADC("ADCL", "Capture", WM8993_POWER_MANAGEMENT_2, 1, 0),
478SND_SOC_DAPM_ADC("ADCR", "Capture", WM8993_POWER_MANAGEMENT_2, 0, 0),
479
480SND_SOC_DAPM_DAC("DACL", "Playback", WM8993_POWER_MANAGEMENT_3, 1, 0),
481SND_SOC_DAPM_DAC("DACR", "Playback", WM8993_POWER_MANAGEMENT_3, 0, 0),
482
483SND_SOC_DAPM_MIXER("Left Output Mixer", WM8993_POWER_MANAGEMENT_3, 5, 0,
484 left_output_mixer, ARRAY_SIZE(left_output_mixer)),
485SND_SOC_DAPM_MIXER("Right Output Mixer", WM8993_POWER_MANAGEMENT_3, 4, 0,
486 right_output_mixer, ARRAY_SIZE(right_output_mixer)),
487
488SND_SOC_DAPM_PGA("Left Output PGA", WM8993_POWER_MANAGEMENT_3, 7, 0, NULL, 0),
489SND_SOC_DAPM_PGA("Right Output PGA", WM8993_POWER_MANAGEMENT_3, 6, 0, NULL, 0),
490
491SND_SOC_DAPM_PGA_E("Headphone PGA", SND_SOC_NOPM, 0, 0,
492 NULL, 0,
493 hp_event, SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD),
494
495SND_SOC_DAPM_MIXER("Earpiece Mixer", SND_SOC_NOPM, 0, 0,
496 earpiece_mixer, ARRAY_SIZE(earpiece_mixer)),
497SND_SOC_DAPM_PGA_E("Earpiece Driver", WM8993_POWER_MANAGEMENT_1, 11, 0,
498 NULL, 0, earpiece_event,
499 SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
500
501SND_SOC_DAPM_MIXER("SPKL Boost", SND_SOC_NOPM, 0, 0,
502 left_speaker_boost, ARRAY_SIZE(left_speaker_boost)),
503SND_SOC_DAPM_MIXER("SPKR Boost", SND_SOC_NOPM, 0, 0,
504 right_speaker_boost, ARRAY_SIZE(right_speaker_boost)),
505
506SND_SOC_DAPM_PGA("SPKL Driver", WM8993_POWER_MANAGEMENT_1, 12, 0,
507 NULL, 0),
508SND_SOC_DAPM_PGA("SPKR Driver", WM8993_POWER_MANAGEMENT_1, 13, 0,
509 NULL, 0),
510
511SND_SOC_DAPM_MIXER("LINEOUT1 Mixer", SND_SOC_NOPM, 0, 0,
512 line1_mix, ARRAY_SIZE(line1_mix)),
513SND_SOC_DAPM_MIXER("LINEOUT2 Mixer", SND_SOC_NOPM, 0, 0,
514 line2_mix, ARRAY_SIZE(line2_mix)),
515
516SND_SOC_DAPM_MIXER("LINEOUT1N Mixer", SND_SOC_NOPM, 0, 0,
517 line1n_mix, ARRAY_SIZE(line1n_mix)),
518SND_SOC_DAPM_MIXER("LINEOUT1P Mixer", SND_SOC_NOPM, 0, 0,
519 line1p_mix, ARRAY_SIZE(line1p_mix)),
520SND_SOC_DAPM_MIXER("LINEOUT2N Mixer", SND_SOC_NOPM, 0, 0,
521 line2n_mix, ARRAY_SIZE(line2n_mix)),
522SND_SOC_DAPM_MIXER("LINEOUT2P Mixer", SND_SOC_NOPM, 0, 0,
523 line2p_mix, ARRAY_SIZE(line2p_mix)),
524
525SND_SOC_DAPM_PGA("LINEOUT1N Driver", WM8993_POWER_MANAGEMENT_3, 13, 0,
526 NULL, 0),
527SND_SOC_DAPM_PGA("LINEOUT1P Driver", WM8993_POWER_MANAGEMENT_3, 12, 0,
528 NULL, 0),
529SND_SOC_DAPM_PGA("LINEOUT2N Driver", WM8993_POWER_MANAGEMENT_3, 11, 0,
530 NULL, 0),
531SND_SOC_DAPM_PGA("LINEOUT2P Driver", WM8993_POWER_MANAGEMENT_3, 10, 0,
532 NULL, 0),
533
534SND_SOC_DAPM_OUTPUT("SPKOUTLP"),
535SND_SOC_DAPM_OUTPUT("SPKOUTLN"),
536SND_SOC_DAPM_OUTPUT("SPKOUTRP"),
537SND_SOC_DAPM_OUTPUT("SPKOUTRN"),
538SND_SOC_DAPM_OUTPUT("HPOUT1L"),
539SND_SOC_DAPM_OUTPUT("HPOUT1R"),
540SND_SOC_DAPM_OUTPUT("HPOUT2P"),
541SND_SOC_DAPM_OUTPUT("HPOUT2N"),
542SND_SOC_DAPM_OUTPUT("LINEOUT1P"),
543SND_SOC_DAPM_OUTPUT("LINEOUT1N"),
544SND_SOC_DAPM_OUTPUT("LINEOUT2P"),
545SND_SOC_DAPM_OUTPUT("LINEOUT2N"),
546};
547
548static const struct snd_soc_dapm_route analogue_routes[] = {
549 { "IN1L PGA", "IN1LP Switch", "IN1LP" },
550 { "IN1L PGA", "IN1LN Switch", "IN1LN" },
551
552 { "IN1R PGA", "IN1RP Switch", "IN1RP" },
553 { "IN1R PGA", "IN1RN Switch", "IN1RN" },
554
555 { "IN2L PGA", "IN2LP Switch", "IN2LP/VXRN" },
556 { "IN2L PGA", "IN2LN Switch", "IN2LN" },
557
558 { "IN2R PGA", "IN2RP Switch", "IN2RP/VXRP" },
559 { "IN2R PGA", "IN2RN Switch", "IN2RN" },
560
561 { "Direct Voice", NULL, "IN2LP/VXRN" },
562 { "Direct Voice", NULL, "IN2RP/VXRP" },
563
564 { "MIXINL", "IN1L Switch", "IN1L PGA" },
565 { "MIXINL", "IN2L Switch", "IN2L PGA" },
566 { "MIXINL", NULL, "Direct Voice" },
567 { "MIXINL", NULL, "IN1LP" },
568 { "MIXINL", NULL, "Left Output Mixer" },
569
570 { "MIXINR", "IN1R Switch", "IN1R PGA" },
571 { "MIXINR", "IN2R Switch", "IN2R PGA" },
572 { "MIXINR", NULL, "Direct Voice" },
573 { "MIXINR", NULL, "IN1RP" },
574 { "MIXINR", NULL, "Right Output Mixer" },
575
576 { "ADCL", NULL, "MIXINL" },
577 { "ADCR", NULL, "MIXINR" },
578
579 { "Left Output Mixer", "Left Input Switch", "MIXINL" },
580 { "Left Output Mixer", "Right Input Switch", "MIXINR" },
581 { "Left Output Mixer", "IN2RN Switch", "IN2RN" },
582 { "Left Output Mixer", "IN2LN Switch", "IN2LN" },
583 { "Left Output Mixer", "IN2LP Switch", "IN2LP/VXRN" },
584 { "Left Output Mixer", "IN1L Switch", "IN1L PGA" },
585 { "Left Output Mixer", "IN1R Switch", "IN1R PGA" },
586
587 { "Right Output Mixer", "Left Input Switch", "MIXINL" },
588 { "Right Output Mixer", "Right Input Switch", "MIXINR" },
589 { "Right Output Mixer", "IN2LN Switch", "IN2LN" },
590 { "Right Output Mixer", "IN2RN Switch", "IN2RN" },
591 { "Right Output Mixer", "IN2RP Switch", "IN2RP/VXRP" },
592 { "Right Output Mixer", "IN1L Switch", "IN1L PGA" },
593 { "Right Output Mixer", "IN1R Switch", "IN1R PGA" },
594
595 { "Left Output PGA", NULL, "Left Output Mixer" },
596 { "Left Output PGA", NULL, "TOCLK" },
597
598 { "Right Output PGA", NULL, "Right Output Mixer" },
599 { "Right Output PGA", NULL, "TOCLK" },
600
601 { "Earpiece Mixer", "Direct Voice Switch", "Direct Voice" },
602 { "Earpiece Mixer", "Left Output Switch", "Left Output PGA" },
603 { "Earpiece Mixer", "Right Output Switch", "Right Output PGA" },
604
605 { "Earpiece Driver", NULL, "Earpiece Mixer" },
606 { "HPOUT2N", NULL, "Earpiece Driver" },
607 { "HPOUT2P", NULL, "Earpiece Driver" },
608
609 { "SPKL", "Input Switch", "MIXINL" },
610 { "SPKL", "IN1LP Switch", "IN1LP" },
611 { "SPKL", "Output Switch", "Left Output Mixer" },
612 { "SPKL", NULL, "TOCLK" },
613
614 { "SPKR", "Input Switch", "MIXINR" },
615 { "SPKR", "IN1RP Switch", "IN1RP" },
616 { "SPKR", "Output Switch", "Right Output Mixer" },
617 { "SPKR", NULL, "TOCLK" },
618
619 { "SPKL Boost", "Direct Voice Switch", "Direct Voice" },
620 { "SPKL Boost", "SPKL Switch", "SPKL" },
621 { "SPKL Boost", "SPKR Switch", "SPKR" },
622
623 { "SPKR Boost", "Direct Voice Switch", "Direct Voice" },
624 { "SPKR Boost", "SPKR Switch", "SPKR" },
625 { "SPKR Boost", "SPKL Switch", "SPKL" },
626
627 { "SPKL Driver", NULL, "SPKL Boost" },
628 { "SPKL Driver", NULL, "CLK_SYS" },
629
630 { "SPKR Driver", NULL, "SPKR Boost" },
631 { "SPKR Driver", NULL, "CLK_SYS" },
632
633 { "SPKOUTLP", NULL, "SPKL Driver" },
634 { "SPKOUTLN", NULL, "SPKL Driver" },
635 { "SPKOUTRP", NULL, "SPKR Driver" },
636 { "SPKOUTRN", NULL, "SPKR Driver" },
637
638 { "Left Headphone Mux", "Mixer", "Left Output Mixer" },
639 { "Right Headphone Mux", "Mixer", "Right Output Mixer" },
640
641 { "Headphone PGA", NULL, "Left Headphone Mux" },
642 { "Headphone PGA", NULL, "Right Headphone Mux" },
643 { "Headphone PGA", NULL, "CLK_SYS" },
644
645 { "HPOUT1L", NULL, "Headphone PGA" },
646 { "HPOUT1R", NULL, "Headphone PGA" },
647
648 { "LINEOUT1N", NULL, "LINEOUT1N Driver" },
649 { "LINEOUT1P", NULL, "LINEOUT1P Driver" },
650 { "LINEOUT2N", NULL, "LINEOUT2N Driver" },
651 { "LINEOUT2P", NULL, "LINEOUT2P Driver" },
652};
653
654static const struct snd_soc_dapm_route lineout1_diff_routes[] = {
655 { "LINEOUT1 Mixer", "IN1L Switch", "IN1L PGA" },
656 { "LINEOUT1 Mixer", "IN1R Switch", "IN1R PGA" },
657 { "LINEOUT1 Mixer", "Output Switch", "Left Output Mixer" },
658
659 { "LINEOUT1N Driver", NULL, "LINEOUT1 Mixer" },
660 { "LINEOUT1P Driver", NULL, "LINEOUT1 Mixer" },
661};
662
663static const struct snd_soc_dapm_route lineout1_se_routes[] = {
664 { "LINEOUT1N Mixer", "Left Output Switch", "Left Output Mixer" },
665 { "LINEOUT1N Mixer", "Right Output Switch", "Left Output Mixer" },
666
667 { "LINEOUT1P Mixer", "Left Output Switch", "Left Output Mixer" },
668
669 { "LINEOUT1N Driver", NULL, "LINEOUT1N Mixer" },
670 { "LINEOUT1P Driver", NULL, "LINEOUT1P Mixer" },
671};
672
673static const struct snd_soc_dapm_route lineout2_diff_routes[] = {
674 { "LINEOUT2 Mixer", "IN2L Switch", "IN2L PGA" },
675 { "LINEOUT2 Mixer", "IN2R Switch", "IN2R PGA" },
676 { "LINEOUT2 Mixer", "Output Switch", "Right Output Mixer" },
677
678 { "LINEOUT2N Driver", NULL, "LINEOUT2 Mixer" },
679 { "LINEOUT2P Driver", NULL, "LINEOUT2 Mixer" },
680};
681
682static const struct snd_soc_dapm_route lineout2_se_routes[] = {
683 { "LINEOUT2N Mixer", "Left Output Switch", "Left Output Mixer" },
684 { "LINEOUT2N Mixer", "Right Output Switch", "Left Output Mixer" },
685
686 { "LINEOUT2P Mixer", "Right Output Switch", "Right Output Mixer" },
687
688 { "LINEOUT2N Driver", NULL, "LINEOUT2N Mixer" },
689 { "LINEOUT2P Driver", NULL, "LINEOUT2P Mixer" },
690};
691
692int wm_hubs_add_analogue_controls(struct snd_soc_codec *codec)
693{
694 /* Latch volume update bits & default ZC on */
695 snd_soc_update_bits(codec, WM8993_LEFT_LINE_INPUT_1_2_VOLUME,
696 WM8993_IN1_VU, WM8993_IN1_VU);
697 snd_soc_update_bits(codec, WM8993_RIGHT_LINE_INPUT_1_2_VOLUME,
698 WM8993_IN1_VU, WM8993_IN1_VU);
699 snd_soc_update_bits(codec, WM8993_LEFT_LINE_INPUT_3_4_VOLUME,
700 WM8993_IN2_VU, WM8993_IN2_VU);
701 snd_soc_update_bits(codec, WM8993_RIGHT_LINE_INPUT_3_4_VOLUME,
702 WM8993_IN2_VU, WM8993_IN2_VU);
703
704 snd_soc_update_bits(codec, WM8993_SPEAKER_VOLUME_RIGHT,
705 WM8993_SPKOUT_VU, WM8993_SPKOUT_VU);
706
707 snd_soc_update_bits(codec, WM8993_LEFT_OUTPUT_VOLUME,
708 WM8993_HPOUT1L_ZC, WM8993_HPOUT1L_ZC);
709 snd_soc_update_bits(codec, WM8993_RIGHT_OUTPUT_VOLUME,
710 WM8993_HPOUT1_VU | WM8993_HPOUT1R_ZC,
711 WM8993_HPOUT1_VU | WM8993_HPOUT1R_ZC);
712
713 snd_soc_update_bits(codec, WM8993_LEFT_OPGA_VOLUME,
714 WM8993_MIXOUTL_ZC, WM8993_MIXOUTL_ZC);
715 snd_soc_update_bits(codec, WM8993_RIGHT_OPGA_VOLUME,
716 WM8993_MIXOUTR_ZC | WM8993_MIXOUT_VU,
717 WM8993_MIXOUTR_ZC | WM8993_MIXOUT_VU);
718
719 snd_soc_add_controls(codec, analogue_snd_controls,
720 ARRAY_SIZE(analogue_snd_controls));
721
722 snd_soc_dapm_new_controls(codec, analogue_dapm_widgets,
723 ARRAY_SIZE(analogue_dapm_widgets));
724 return 0;
725}
726EXPORT_SYMBOL_GPL(wm_hubs_add_analogue_controls);
727
728int wm_hubs_add_analogue_routes(struct snd_soc_codec *codec,
729 int lineout1_diff, int lineout2_diff)
730{
731 snd_soc_dapm_add_routes(codec, analogue_routes,
732 ARRAY_SIZE(analogue_routes));
733
734 if (lineout1_diff)
735 snd_soc_dapm_add_routes(codec,
736 lineout1_diff_routes,
737 ARRAY_SIZE(lineout1_diff_routes));
738 else
739 snd_soc_dapm_add_routes(codec,
740 lineout1_se_routes,
741 ARRAY_SIZE(lineout1_se_routes));
742
743 if (lineout2_diff)
744 snd_soc_dapm_add_routes(codec,
745 lineout2_diff_routes,
746 ARRAY_SIZE(lineout2_diff_routes));
747 else
748 snd_soc_dapm_add_routes(codec,
749 lineout2_se_routes,
750 ARRAY_SIZE(lineout2_se_routes));
751
752 return 0;
753}
754EXPORT_SYMBOL_GPL(wm_hubs_add_analogue_routes);
755
756MODULE_DESCRIPTION("Shared support for Wolfson hubs products");
757MODULE_AUTHOR("Mark Brown <broonie@opensource.wolfsonmicro.com>");
758MODULE_LICENSE("GPL");
diff --git a/sound/soc/codecs/wm_hubs.h b/sound/soc/codecs/wm_hubs.h
new file mode 100644
index 000000000000..ec09cb6a2939
--- /dev/null
+++ b/sound/soc/codecs/wm_hubs.h
@@ -0,0 +1,24 @@
1/*
2 * wm_hubs.h -- WM899x common code
3 *
4 * Copyright 2009 Wolfson Microelectronics plc
5 *
6 * Author: Mark Brown <broonie@opensource.wolfsonmicro.com>
7 *
8 *
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License version 2 as
11 * published by the Free Software Foundation.
12 */
13
14#ifndef _WM_HUBS_H
15#define _WM_HUBS_H
16
17struct snd_soc_codec;
18
19extern const unsigned int wm_hubs_spkmix_tlv[];
20
21extern int wm_hubs_add_analogue_controls(struct snd_soc_codec *);
22extern int wm_hubs_add_analogue_routes(struct snd_soc_codec *, int, int);
23
24#endif
diff --git a/sound/soc/davinci/Kconfig b/sound/soc/davinci/Kconfig
index 411a710be660..4dfd4ad9d90e 100644
--- a/sound/soc/davinci/Kconfig
+++ b/sound/soc/davinci/Kconfig
@@ -9,6 +9,9 @@ config SND_DAVINCI_SOC
9config SND_DAVINCI_SOC_I2S 9config SND_DAVINCI_SOC_I2S
10 tristate 10 tristate
11 11
12config SND_DAVINCI_SOC_MCASP
13 tristate
14
12config SND_DAVINCI_SOC_EVM 15config SND_DAVINCI_SOC_EVM
13 tristate "SoC Audio support for DaVinci DM6446 or DM355 EVM" 16 tristate "SoC Audio support for DaVinci DM6446 or DM355 EVM"
14 depends on SND_DAVINCI_SOC 17 depends on SND_DAVINCI_SOC
@@ -19,6 +22,16 @@ config SND_DAVINCI_SOC_EVM
19 Say Y if you want to add support for SoC audio on TI 22 Say Y if you want to add support for SoC audio on TI
20 DaVinci DM6446 or DM355 EVM platforms. 23 DaVinci DM6446 or DM355 EVM platforms.
21 24
25config SND_DM6467_SOC_EVM
26 tristate "SoC Audio support for DaVinci DM6467 EVM"
27 depends on SND_DAVINCI_SOC && MACH_DAVINCI_DM6467_EVM
28 select SND_DAVINCI_SOC_MCASP
29 select SND_SOC_TLV320AIC3X
30 select SND_SOC_SPDIF
31
32 help
33 Say Y if you want to add support for SoC audio on TI
34
22config SND_DAVINCI_SOC_SFFSDR 35config SND_DAVINCI_SOC_SFFSDR
23 tristate "SoC Audio support for SFFSDR" 36 tristate "SoC Audio support for SFFSDR"
24 depends on SND_DAVINCI_SOC && MACH_SFFSDR 37 depends on SND_DAVINCI_SOC && MACH_SFFSDR
@@ -28,3 +41,23 @@ config SND_DAVINCI_SOC_SFFSDR
28 help 41 help
29 Say Y if you want to add support for SoC audio on 42 Say Y if you want to add support for SoC audio on
30 Lyrtech SFFSDR board. 43 Lyrtech SFFSDR board.
44
45config SND_DA830_SOC_EVM
46 tristate "SoC Audio support for DA830/OMAP-L137 EVM"
47 depends on SND_DAVINCI_SOC && MACH_DAVINCI_DA830_EVM
48 select SND_DAVINCI_SOC_MCASP
49 select SND_SOC_TLV320AIC3X
50
51 help
52 Say Y if you want to add support for SoC audio on TI
53 DA830/OMAP-L137 EVM
54
55config SND_DA850_SOC_EVM
56 tristate "SoC Audio support for DA850/OMAP-L138 EVM"
57 depends on SND_DAVINCI_SOC && MACH_DAVINCI_DA850_EVM
58 select SND_DAVINCI_SOC_MCASP
59 select SND_SOC_TLV320AIC3X
60 help
61 Say Y if you want to add support for SoC audio on TI
62 DA850/OMAP-L138 EVM
63
diff --git a/sound/soc/davinci/Makefile b/sound/soc/davinci/Makefile
index ca8bae1fc3f6..a6939d71b988 100644
--- a/sound/soc/davinci/Makefile
+++ b/sound/soc/davinci/Makefile
@@ -1,13 +1,18 @@
1# DAVINCI Platform Support 1# DAVINCI Platform Support
2snd-soc-davinci-objs := davinci-pcm.o 2snd-soc-davinci-objs := davinci-pcm.o
3snd-soc-davinci-i2s-objs := davinci-i2s.o 3snd-soc-davinci-i2s-objs := davinci-i2s.o
4snd-soc-davinci-mcasp-objs:= davinci-mcasp.o
4 5
5obj-$(CONFIG_SND_DAVINCI_SOC) += snd-soc-davinci.o 6obj-$(CONFIG_SND_DAVINCI_SOC) += snd-soc-davinci.o
6obj-$(CONFIG_SND_DAVINCI_SOC_I2S) += snd-soc-davinci-i2s.o 7obj-$(CONFIG_SND_DAVINCI_SOC_I2S) += snd-soc-davinci-i2s.o
8obj-$(CONFIG_SND_DAVINCI_SOC_MCASP) += snd-soc-davinci-mcasp.o
7 9
8# DAVINCI Machine Support 10# DAVINCI Machine Support
9snd-soc-evm-objs := davinci-evm.o 11snd-soc-evm-objs := davinci-evm.o
10snd-soc-sffsdr-objs := davinci-sffsdr.o 12snd-soc-sffsdr-objs := davinci-sffsdr.o
11 13
12obj-$(CONFIG_SND_DAVINCI_SOC_EVM) += snd-soc-evm.o 14obj-$(CONFIG_SND_DAVINCI_SOC_EVM) += snd-soc-evm.o
15obj-$(CONFIG_SND_DM6467_SOC_EVM) += snd-soc-evm.o
16obj-$(CONFIG_SND_DA830_SOC_EVM) += snd-soc-evm.o
17obj-$(CONFIG_SND_DA850_SOC_EVM) += snd-soc-evm.o
13obj-$(CONFIG_SND_DAVINCI_SOC_SFFSDR) += snd-soc-sffsdr.o 18obj-$(CONFIG_SND_DAVINCI_SOC_SFFSDR) += snd-soc-sffsdr.o
diff --git a/sound/soc/davinci/davinci-evm.c b/sound/soc/davinci/davinci-evm.c
index 58fd1cbedd88..46c1b0cb1d1b 100644
--- a/sound/soc/davinci/davinci-evm.c
+++ b/sound/soc/davinci/davinci-evm.c
@@ -27,9 +27,10 @@
27#include <mach/mux.h> 27#include <mach/mux.h>
28 28
29#include "../codecs/tlv320aic3x.h" 29#include "../codecs/tlv320aic3x.h"
30#include "../codecs/spdif_transciever.h"
30#include "davinci-pcm.h" 31#include "davinci-pcm.h"
31#include "davinci-i2s.h" 32#include "davinci-i2s.h"
32 33#include "davinci-mcasp.h"
33 34
34#define AUDIO_FORMAT (SND_SOC_DAIFMT_DSP_B | \ 35#define AUDIO_FORMAT (SND_SOC_DAIFMT_DSP_B | \
35 SND_SOC_DAIFMT_CBM_CFM | SND_SOC_DAIFMT_IB_NF) 36 SND_SOC_DAIFMT_CBM_CFM | SND_SOC_DAIFMT_IB_NF)
@@ -43,7 +44,7 @@ static int evm_hw_params(struct snd_pcm_substream *substream,
43 unsigned sysclk; 44 unsigned sysclk;
44 45
45 /* ASP1 on DM355 EVM is clocked by an external oscillator */ 46 /* ASP1 on DM355 EVM is clocked by an external oscillator */
46 if (machine_is_davinci_dm355_evm()) 47 if (machine_is_davinci_dm355_evm() || machine_is_davinci_dm6467_evm())
47 sysclk = 27000000; 48 sysclk = 27000000;
48 49
49 /* ASP0 in DM6446 EVM is clocked by U55, as configured by 50 /* ASP0 in DM6446 EVM is clocked by U55, as configured by
@@ -53,6 +54,10 @@ static int evm_hw_params(struct snd_pcm_substream *substream,
53 else if (machine_is_davinci_evm()) 54 else if (machine_is_davinci_evm())
54 sysclk = 12288000; 55 sysclk = 12288000;
55 56
57 else if (machine_is_davinci_da830_evm() ||
58 machine_is_davinci_da850_evm())
59 sysclk = 24576000;
60
56 else 61 else
57 return -EINVAL; 62 return -EINVAL;
58 63
@@ -144,6 +149,32 @@ static struct snd_soc_dai_link evm_dai = {
144 .ops = &evm_ops, 149 .ops = &evm_ops,
145}; 150};
146 151
152static struct snd_soc_dai_link dm6467_evm_dai[] = {
153 {
154 .name = "TLV320AIC3X",
155 .stream_name = "AIC3X",
156 .cpu_dai = &davinci_mcasp_dai[DAVINCI_MCASP_I2S_DAI],
157 .codec_dai = &aic3x_dai,
158 .init = evm_aic3x_init,
159 .ops = &evm_ops,
160 },
161 {
162 .name = "McASP",
163 .stream_name = "spdif",
164 .cpu_dai = &davinci_mcasp_dai[DAVINCI_MCASP_DIT_DAI],
165 .codec_dai = &dit_stub_dai,
166 .ops = &evm_ops,
167 },
168};
169static struct snd_soc_dai_link da8xx_evm_dai = {
170 .name = "TLV320AIC3X",
171 .stream_name = "AIC3X",
172 .cpu_dai = &davinci_mcasp_dai[DAVINCI_MCASP_I2S_DAI],
173 .codec_dai = &aic3x_dai,
174 .init = evm_aic3x_init,
175 .ops = &evm_ops,
176};
177
147/* davinci-evm audio machine driver */ 178/* davinci-evm audio machine driver */
148static struct snd_soc_card snd_soc_card_evm = { 179static struct snd_soc_card snd_soc_card_evm = {
149 .name = "DaVinci EVM", 180 .name = "DaVinci EVM",
@@ -152,12 +183,45 @@ static struct snd_soc_card snd_soc_card_evm = {
152 .num_links = 1, 183 .num_links = 1,
153}; 184};
154 185
186/* davinci dm6467 evm audio machine driver */
187static struct snd_soc_card dm6467_snd_soc_card_evm = {
188 .name = "DaVinci DM6467 EVM",
189 .platform = &davinci_soc_platform,
190 .dai_link = dm6467_evm_dai,
191 .num_links = ARRAY_SIZE(dm6467_evm_dai),
192};
193
194static struct snd_soc_card da830_snd_soc_card = {
195 .name = "DA830/OMAP-L137 EVM",
196 .dai_link = &da8xx_evm_dai,
197 .platform = &davinci_soc_platform,
198 .num_links = 1,
199};
200
201static struct snd_soc_card da850_snd_soc_card = {
202 .name = "DA850/OMAP-L138 EVM",
203 .dai_link = &da8xx_evm_dai,
204 .platform = &davinci_soc_platform,
205 .num_links = 1,
206};
207
155/* evm audio private data */ 208/* evm audio private data */
156static struct aic3x_setup_data evm_aic3x_setup = { 209static struct aic3x_setup_data evm_aic3x_setup = {
157 .i2c_bus = 1, 210 .i2c_bus = 1,
158 .i2c_address = 0x1b, 211 .i2c_address = 0x1b,
159}; 212};
160 213
214/* dm6467 evm audio private data */
215static struct aic3x_setup_data dm6467_evm_aic3x_setup = {
216 .i2c_bus = 1,
217 .i2c_address = 0x18,
218};
219
220static struct aic3x_setup_data da8xx_evm_aic3x_setup = {
221 .i2c_bus = 1,
222 .i2c_address = 0x18,
223};
224
161/* evm audio subsystem */ 225/* evm audio subsystem */
162static struct snd_soc_device evm_snd_devdata = { 226static struct snd_soc_device evm_snd_devdata = {
163 .card = &snd_soc_card_evm, 227 .card = &snd_soc_card_evm,
@@ -165,60 +229,49 @@ static struct snd_soc_device evm_snd_devdata = {
165 .codec_data = &evm_aic3x_setup, 229 .codec_data = &evm_aic3x_setup,
166}; 230};
167 231
168/* DM6446 EVM uses ASP0; line-out is a pair of RCA jacks */ 232/* evm audio subsystem */
169static struct resource evm_snd_resources[] = { 233static struct snd_soc_device dm6467_evm_snd_devdata = {
170 { 234 .card = &dm6467_snd_soc_card_evm,
171 .start = DAVINCI_ASP0_BASE, 235 .codec_dev = &soc_codec_dev_aic3x,
172 .end = DAVINCI_ASP0_BASE + SZ_8K - 1, 236 .codec_data = &dm6467_evm_aic3x_setup,
173 .flags = IORESOURCE_MEM,
174 },
175};
176
177static struct evm_snd_platform_data evm_snd_data = {
178 .tx_dma_ch = DAVINCI_DMA_ASP0_TX,
179 .rx_dma_ch = DAVINCI_DMA_ASP0_RX,
180}; 237};
181 238
182/* DM335 EVM uses ASP1; line-out is a stereo mini-jack */ 239/* evm audio subsystem */
183static struct resource dm335evm_snd_resources[] = { 240static struct snd_soc_device da830_evm_snd_devdata = {
184 { 241 .card = &da830_snd_soc_card,
185 .start = DAVINCI_ASP1_BASE, 242 .codec_dev = &soc_codec_dev_aic3x,
186 .end = DAVINCI_ASP1_BASE + SZ_8K - 1, 243 .codec_data = &da8xx_evm_aic3x_setup,
187 .flags = IORESOURCE_MEM,
188 },
189}; 244};
190 245
191static struct evm_snd_platform_data dm335evm_snd_data = { 246static struct snd_soc_device da850_evm_snd_devdata = {
192 .tx_dma_ch = DAVINCI_DMA_ASP1_TX, 247 .card = &da850_snd_soc_card,
193 .rx_dma_ch = DAVINCI_DMA_ASP1_RX, 248 .codec_dev = &soc_codec_dev_aic3x,
249 .codec_data = &da8xx_evm_aic3x_setup,
194}; 250};
195 251
196static struct platform_device *evm_snd_device; 252static struct platform_device *evm_snd_device;
197 253
198static int __init evm_init(void) 254static int __init evm_init(void)
199{ 255{
200 struct resource *resources; 256 struct snd_soc_device *evm_snd_dev_data;
201 unsigned num_resources;
202 struct evm_snd_platform_data *data;
203 int index; 257 int index;
204 int ret; 258 int ret;
205 259
206 if (machine_is_davinci_evm()) { 260 if (machine_is_davinci_evm()) {
207 davinci_cfg_reg(DM644X_MCBSP); 261 evm_snd_dev_data = &evm_snd_devdata;
208
209 resources = evm_snd_resources;
210 num_resources = ARRAY_SIZE(evm_snd_resources);
211 data = &evm_snd_data;
212 index = 0; 262 index = 0;
213 } else if (machine_is_davinci_dm355_evm()) { 263 } else if (machine_is_davinci_dm355_evm()) {
214 /* we don't use ASP1 IRQs, or we'd need to mux them ... */ 264 evm_snd_dev_data = &evm_snd_devdata;
215 davinci_cfg_reg(DM355_EVT8_ASP1_TX); 265 index = 1;
216 davinci_cfg_reg(DM355_EVT9_ASP1_RX); 266 } else if (machine_is_davinci_dm6467_evm()) {
217 267 evm_snd_dev_data = &dm6467_evm_snd_devdata;
218 resources = dm335evm_snd_resources; 268 index = 0;
219 num_resources = ARRAY_SIZE(dm335evm_snd_resources); 269 } else if (machine_is_davinci_da830_evm()) {
220 data = &dm335evm_snd_data; 270 evm_snd_dev_data = &da830_evm_snd_devdata;
221 index = 1; 271 index = 1;
272 } else if (machine_is_davinci_da850_evm()) {
273 evm_snd_dev_data = &da850_evm_snd_devdata;
274 index = 0;
222 } else 275 } else
223 return -EINVAL; 276 return -EINVAL;
224 277
@@ -226,17 +279,8 @@ static int __init evm_init(void)
226 if (!evm_snd_device) 279 if (!evm_snd_device)
227 return -ENOMEM; 280 return -ENOMEM;
228 281
229 platform_set_drvdata(evm_snd_device, &evm_snd_devdata); 282 platform_set_drvdata(evm_snd_device, evm_snd_dev_data);
230 evm_snd_devdata.dev = &evm_snd_device->dev; 283 evm_snd_dev_data->dev = &evm_snd_device->dev;
231 platform_device_add_data(evm_snd_device, data, sizeof(*data));
232
233 ret = platform_device_add_resources(evm_snd_device, resources,
234 num_resources);
235 if (ret) {
236 platform_device_put(evm_snd_device);
237 return ret;
238 }
239
240 ret = platform_device_add(evm_snd_device); 284 ret = platform_device_add(evm_snd_device);
241 if (ret) 285 if (ret)
242 platform_device_put(evm_snd_device); 286 platform_device_put(evm_snd_device);
diff --git a/sound/soc/davinci/davinci-i2s.c b/sound/soc/davinci/davinci-i2s.c
index b1ea52fc83c7..12a6c549ee6e 100644
--- a/sound/soc/davinci/davinci-i2s.c
+++ b/sound/soc/davinci/davinci-i2s.c
@@ -22,6 +22,8 @@
22#include <sound/initval.h> 22#include <sound/initval.h>
23#include <sound/soc.h> 23#include <sound/soc.h>
24 24
25#include <mach/asp.h>
26
25#include "davinci-pcm.h" 27#include "davinci-pcm.h"
26 28
27 29
@@ -63,6 +65,7 @@
63#define DAVINCI_MCBSP_RCR_RWDLEN1(v) ((v) << 5) 65#define DAVINCI_MCBSP_RCR_RWDLEN1(v) ((v) << 5)
64#define DAVINCI_MCBSP_RCR_RFRLEN1(v) ((v) << 8) 66#define DAVINCI_MCBSP_RCR_RFRLEN1(v) ((v) << 8)
65#define DAVINCI_MCBSP_RCR_RDATDLY(v) ((v) << 16) 67#define DAVINCI_MCBSP_RCR_RDATDLY(v) ((v) << 16)
68#define DAVINCI_MCBSP_RCR_RFIG (1 << 18)
66#define DAVINCI_MCBSP_RCR_RWDLEN2(v) ((v) << 21) 69#define DAVINCI_MCBSP_RCR_RWDLEN2(v) ((v) << 21)
67 70
68#define DAVINCI_MCBSP_XCR_XWDLEN1(v) ((v) << 5) 71#define DAVINCI_MCBSP_XCR_XWDLEN1(v) ((v) << 5)
@@ -85,14 +88,6 @@
85#define DAVINCI_MCBSP_PCR_FSRM (1 << 10) 88#define DAVINCI_MCBSP_PCR_FSRM (1 << 10)
86#define DAVINCI_MCBSP_PCR_FSXM (1 << 11) 89#define DAVINCI_MCBSP_PCR_FSXM (1 << 11)
87 90
88#define MOD_REG_BIT(val, mask, set) do { \
89 if (set) { \
90 val |= mask; \
91 } else { \
92 val &= ~mask; \
93 } \
94} while (0)
95
96enum { 91enum {
97 DAVINCI_MCBSP_WORD_8 = 0, 92 DAVINCI_MCBSP_WORD_8 = 0,
98 DAVINCI_MCBSP_WORD_12, 93 DAVINCI_MCBSP_WORD_12,
@@ -112,6 +107,10 @@ static struct davinci_pcm_dma_params davinci_i2s_pcm_in = {
112 107
113struct davinci_mcbsp_dev { 108struct davinci_mcbsp_dev {
114 void __iomem *base; 109 void __iomem *base;
110#define MOD_DSP_A 0
111#define MOD_DSP_B 1
112 int mode;
113 u32 pcr;
115 struct clk *clk; 114 struct clk *clk;
116 struct davinci_pcm_dma_params *dma_params[2]; 115 struct davinci_pcm_dma_params *dma_params[2];
117}; 116};
@@ -127,96 +126,100 @@ static inline u32 davinci_mcbsp_read_reg(struct davinci_mcbsp_dev *dev, int reg)
127 return __raw_readl(dev->base + reg); 126 return __raw_readl(dev->base + reg);
128} 127}
129 128
130static void davinci_mcbsp_start(struct snd_pcm_substream *substream) 129static void toggle_clock(struct davinci_mcbsp_dev *dev, int playback)
130{
131 u32 m = playback ? DAVINCI_MCBSP_PCR_CLKXP : DAVINCI_MCBSP_PCR_CLKRP;
132 /* The clock needs to toggle to complete reset.
133 * So, fake it by toggling the clk polarity.
134 */
135 davinci_mcbsp_write_reg(dev, DAVINCI_MCBSP_PCR_REG, dev->pcr ^ m);
136 davinci_mcbsp_write_reg(dev, DAVINCI_MCBSP_PCR_REG, dev->pcr);
137}
138
139static void davinci_mcbsp_start(struct davinci_mcbsp_dev *dev,
140 struct snd_pcm_substream *substream)
131{ 141{
132 struct snd_soc_pcm_runtime *rtd = substream->private_data; 142 struct snd_soc_pcm_runtime *rtd = substream->private_data;
133 struct davinci_mcbsp_dev *dev = rtd->dai->cpu_dai->private_data;
134 struct snd_soc_device *socdev = rtd->socdev; 143 struct snd_soc_device *socdev = rtd->socdev;
135 struct snd_soc_platform *platform = socdev->card->platform; 144 struct snd_soc_platform *platform = socdev->card->platform;
136 u32 w; 145 int playback = (substream->stream == SNDRV_PCM_STREAM_PLAYBACK);
137 int ret; 146 u32 spcr;
138 147 u32 mask = playback ? DAVINCI_MCBSP_SPCR_XRST : DAVINCI_MCBSP_SPCR_RRST;
139 /* Start the sample generator and enable transmitter/receiver */ 148 spcr = davinci_mcbsp_read_reg(dev, DAVINCI_MCBSP_SPCR_REG);
140 w = davinci_mcbsp_read_reg(dev, DAVINCI_MCBSP_SPCR_REG); 149 if (spcr & mask) {
141 MOD_REG_BIT(w, DAVINCI_MCBSP_SPCR_GRST, 1); 150 /* start off disabled */
142 davinci_mcbsp_write_reg(dev, DAVINCI_MCBSP_SPCR_REG, w); 151 davinci_mcbsp_write_reg(dev, DAVINCI_MCBSP_SPCR_REG,
152 spcr & ~mask);
153 toggle_clock(dev, playback);
154 }
155 if (dev->pcr & (DAVINCI_MCBSP_PCR_FSXM | DAVINCI_MCBSP_PCR_FSRM |
156 DAVINCI_MCBSP_PCR_CLKXM | DAVINCI_MCBSP_PCR_CLKRM)) {
157 /* Start the sample generator */
158 spcr |= DAVINCI_MCBSP_SPCR_GRST;
159 davinci_mcbsp_write_reg(dev, DAVINCI_MCBSP_SPCR_REG, spcr);
160 }
143 161
144 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { 162 if (playback) {
145 /* Stop the DMA to avoid data loss */ 163 /* Stop the DMA to avoid data loss */
146 /* while the transmitter is out of reset to handle XSYNCERR */ 164 /* while the transmitter is out of reset to handle XSYNCERR */
147 if (platform->pcm_ops->trigger) { 165 if (platform->pcm_ops->trigger) {
148 ret = platform->pcm_ops->trigger(substream, 166 int ret = platform->pcm_ops->trigger(substream,
149 SNDRV_PCM_TRIGGER_STOP); 167 SNDRV_PCM_TRIGGER_STOP);
150 if (ret < 0) 168 if (ret < 0)
151 printk(KERN_DEBUG "Playback DMA stop failed\n"); 169 printk(KERN_DEBUG "Playback DMA stop failed\n");
152 } 170 }
153 171
154 /* Enable the transmitter */ 172 /* Enable the transmitter */
155 w = davinci_mcbsp_read_reg(dev, DAVINCI_MCBSP_SPCR_REG); 173 spcr = davinci_mcbsp_read_reg(dev, DAVINCI_MCBSP_SPCR_REG);
156 MOD_REG_BIT(w, DAVINCI_MCBSP_SPCR_XRST, 1); 174 spcr |= DAVINCI_MCBSP_SPCR_XRST;
157 davinci_mcbsp_write_reg(dev, DAVINCI_MCBSP_SPCR_REG, w); 175 davinci_mcbsp_write_reg(dev, DAVINCI_MCBSP_SPCR_REG, spcr);
158 176
159 /* wait for any unexpected frame sync error to occur */ 177 /* wait for any unexpected frame sync error to occur */
160 udelay(100); 178 udelay(100);
161 179
162 /* Disable the transmitter to clear any outstanding XSYNCERR */ 180 /* Disable the transmitter to clear any outstanding XSYNCERR */
163 w = davinci_mcbsp_read_reg(dev, DAVINCI_MCBSP_SPCR_REG); 181 spcr = davinci_mcbsp_read_reg(dev, DAVINCI_MCBSP_SPCR_REG);
164 MOD_REG_BIT(w, DAVINCI_MCBSP_SPCR_XRST, 0); 182 spcr &= ~DAVINCI_MCBSP_SPCR_XRST;
165 davinci_mcbsp_write_reg(dev, DAVINCI_MCBSP_SPCR_REG, w); 183 davinci_mcbsp_write_reg(dev, DAVINCI_MCBSP_SPCR_REG, spcr);
184 toggle_clock(dev, playback);
166 185
167 /* Restart the DMA */ 186 /* Restart the DMA */
168 if (platform->pcm_ops->trigger) { 187 if (platform->pcm_ops->trigger) {
169 ret = platform->pcm_ops->trigger(substream, 188 int ret = platform->pcm_ops->trigger(substream,
170 SNDRV_PCM_TRIGGER_START); 189 SNDRV_PCM_TRIGGER_START);
171 if (ret < 0) 190 if (ret < 0)
172 printk(KERN_DEBUG "Playback DMA start failed\n"); 191 printk(KERN_DEBUG "Playback DMA start failed\n");
173 } 192 }
174 /* Enable the transmitter */
175 w = davinci_mcbsp_read_reg(dev, DAVINCI_MCBSP_SPCR_REG);
176 MOD_REG_BIT(w, DAVINCI_MCBSP_SPCR_XRST, 1);
177 davinci_mcbsp_write_reg(dev, DAVINCI_MCBSP_SPCR_REG, w);
178
179 } else {
180
181 /* Enable the reciever */
182 w = davinci_mcbsp_read_reg(dev, DAVINCI_MCBSP_SPCR_REG);
183 MOD_REG_BIT(w, DAVINCI_MCBSP_SPCR_RRST, 1);
184 davinci_mcbsp_write_reg(dev, DAVINCI_MCBSP_SPCR_REG, w);
185 } 193 }
186 194
195 /* Enable transmitter or receiver */
196 spcr = davinci_mcbsp_read_reg(dev, DAVINCI_MCBSP_SPCR_REG);
197 spcr |= mask;
187 198
188 /* Start frame sync */ 199 if (dev->pcr & (DAVINCI_MCBSP_PCR_FSXM | DAVINCI_MCBSP_PCR_FSRM)) {
189 w = davinci_mcbsp_read_reg(dev, DAVINCI_MCBSP_SPCR_REG); 200 /* Start frame sync */
190 MOD_REG_BIT(w, DAVINCI_MCBSP_SPCR_FRST, 1); 201 spcr |= DAVINCI_MCBSP_SPCR_FRST;
191 davinci_mcbsp_write_reg(dev, DAVINCI_MCBSP_SPCR_REG, w); 202 }
203 davinci_mcbsp_write_reg(dev, DAVINCI_MCBSP_SPCR_REG, spcr);
192} 204}
193 205
194static void davinci_mcbsp_stop(struct snd_pcm_substream *substream) 206static void davinci_mcbsp_stop(struct davinci_mcbsp_dev *dev, int playback)
195{ 207{
196 struct snd_soc_pcm_runtime *rtd = substream->private_data; 208 u32 spcr;
197 struct davinci_mcbsp_dev *dev = rtd->dai->cpu_dai->private_data;
198 u32 w;
199 209
200 /* Reset transmitter/receiver and sample rate/frame sync generators */ 210 /* Reset transmitter/receiver and sample rate/frame sync generators */
201 w = davinci_mcbsp_read_reg(dev, DAVINCI_MCBSP_SPCR_REG); 211 spcr = davinci_mcbsp_read_reg(dev, DAVINCI_MCBSP_SPCR_REG);
202 MOD_REG_BIT(w, DAVINCI_MCBSP_SPCR_GRST | 212 spcr &= ~(DAVINCI_MCBSP_SPCR_GRST | DAVINCI_MCBSP_SPCR_FRST);
203 DAVINCI_MCBSP_SPCR_FRST, 0); 213 spcr &= playback ? ~DAVINCI_MCBSP_SPCR_XRST : ~DAVINCI_MCBSP_SPCR_RRST;
204 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) 214 davinci_mcbsp_write_reg(dev, DAVINCI_MCBSP_SPCR_REG, spcr);
205 MOD_REG_BIT(w, DAVINCI_MCBSP_SPCR_XRST, 0); 215 toggle_clock(dev, playback);
206 else
207 MOD_REG_BIT(w, DAVINCI_MCBSP_SPCR_RRST, 0);
208 davinci_mcbsp_write_reg(dev, DAVINCI_MCBSP_SPCR_REG, w);
209} 216}
210 217
211static int davinci_i2s_startup(struct snd_pcm_substream *substream, 218static int davinci_i2s_startup(struct snd_pcm_substream *substream,
212 struct snd_soc_dai *dai) 219 struct snd_soc_dai *cpu_dai)
213{ 220{
214 struct snd_soc_pcm_runtime *rtd = substream->private_data; 221 struct davinci_mcbsp_dev *dev = cpu_dai->private_data;
215 struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai;
216 struct davinci_mcbsp_dev *dev = rtd->dai->cpu_dai->private_data;
217
218 cpu_dai->dma_data = dev->dma_params[substream->stream]; 222 cpu_dai->dma_data = dev->dma_params[substream->stream];
219
220 return 0; 223 return 0;
221} 224}
222 225
@@ -228,12 +231,11 @@ static int davinci_i2s_set_dai_fmt(struct snd_soc_dai *cpu_dai,
228 struct davinci_mcbsp_dev *dev = cpu_dai->private_data; 231 struct davinci_mcbsp_dev *dev = cpu_dai->private_data;
229 unsigned int pcr; 232 unsigned int pcr;
230 unsigned int srgr; 233 unsigned int srgr;
231 unsigned int rcr;
232 unsigned int xcr;
233 srgr = DAVINCI_MCBSP_SRGR_FSGM | 234 srgr = DAVINCI_MCBSP_SRGR_FSGM |
234 DAVINCI_MCBSP_SRGR_FPER(DEFAULT_BITPERSAMPLE * 2 - 1) | 235 DAVINCI_MCBSP_SRGR_FPER(DEFAULT_BITPERSAMPLE * 2 - 1) |
235 DAVINCI_MCBSP_SRGR_FWID(DEFAULT_BITPERSAMPLE - 1); 236 DAVINCI_MCBSP_SRGR_FWID(DEFAULT_BITPERSAMPLE - 1);
236 237
238 /* set master/slave audio interface */
237 switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { 239 switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
238 case SND_SOC_DAIFMT_CBS_CFS: 240 case SND_SOC_DAIFMT_CBS_CFS:
239 /* cpu is master */ 241 /* cpu is master */
@@ -258,11 +260,8 @@ static int davinci_i2s_set_dai_fmt(struct snd_soc_dai *cpu_dai,
258 return -EINVAL; 260 return -EINVAL;
259 } 261 }
260 262
261 rcr = DAVINCI_MCBSP_RCR_RFRLEN1(1); 263 /* interface format */
262 xcr = DAVINCI_MCBSP_XCR_XFIG | DAVINCI_MCBSP_XCR_XFRLEN1(1);
263 switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { 264 switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
264 case SND_SOC_DAIFMT_DSP_B:
265 break;
266 case SND_SOC_DAIFMT_I2S: 265 case SND_SOC_DAIFMT_I2S:
267 /* Davinci doesn't support TRUE I2S, but some codecs will have 266 /* Davinci doesn't support TRUE I2S, but some codecs will have
268 * the left and right channels contiguous. This allows 267 * the left and right channels contiguous. This allows
@@ -282,8 +281,10 @@ static int davinci_i2s_set_dai_fmt(struct snd_soc_dai *cpu_dai,
282 */ 281 */
283 fmt ^= SND_SOC_DAIFMT_NB_IF; 282 fmt ^= SND_SOC_DAIFMT_NB_IF;
284 case SND_SOC_DAIFMT_DSP_A: 283 case SND_SOC_DAIFMT_DSP_A:
285 rcr |= DAVINCI_MCBSP_RCR_RDATDLY(1); 284 dev->mode = MOD_DSP_A;
286 xcr |= DAVINCI_MCBSP_XCR_XDATDLY(1); 285 break;
286 case SND_SOC_DAIFMT_DSP_B:
287 dev->mode = MOD_DSP_B;
287 break; 288 break;
288 default: 289 default:
289 printk(KERN_ERR "%s:bad format\n", __func__); 290 printk(KERN_ERR "%s:bad format\n", __func__);
@@ -343,9 +344,8 @@ static int davinci_i2s_set_dai_fmt(struct snd_soc_dai *cpu_dai,
343 return -EINVAL; 344 return -EINVAL;
344 } 345 }
345 davinci_mcbsp_write_reg(dev, DAVINCI_MCBSP_SRGR_REG, srgr); 346 davinci_mcbsp_write_reg(dev, DAVINCI_MCBSP_SRGR_REG, srgr);
347 dev->pcr = pcr;
346 davinci_mcbsp_write_reg(dev, DAVINCI_MCBSP_PCR_REG, pcr); 348 davinci_mcbsp_write_reg(dev, DAVINCI_MCBSP_PCR_REG, pcr);
347 davinci_mcbsp_write_reg(dev, DAVINCI_MCBSP_RCR_REG, rcr);
348 davinci_mcbsp_write_reg(dev, DAVINCI_MCBSP_XCR_REG, xcr);
349 return 0; 349 return 0;
350} 350}
351 351
@@ -353,31 +353,40 @@ static int davinci_i2s_hw_params(struct snd_pcm_substream *substream,
353 struct snd_pcm_hw_params *params, 353 struct snd_pcm_hw_params *params,
354 struct snd_soc_dai *dai) 354 struct snd_soc_dai *dai)
355{ 355{
356 struct snd_soc_pcm_runtime *rtd = substream->private_data; 356 struct davinci_pcm_dma_params *dma_params = dai->dma_data;
357 struct davinci_pcm_dma_params *dma_params = rtd->dai->cpu_dai->dma_data; 357 struct davinci_mcbsp_dev *dev = dai->private_data;
358 struct davinci_mcbsp_dev *dev = rtd->dai->cpu_dai->private_data;
359 struct snd_interval *i = NULL; 358 struct snd_interval *i = NULL;
360 int mcbsp_word_length; 359 int mcbsp_word_length;
361 u32 w; 360 unsigned int rcr, xcr, srgr;
361 u32 spcr;
362 362
363 /* general line settings */ 363 /* general line settings */
364 w = davinci_mcbsp_read_reg(dev, DAVINCI_MCBSP_SPCR_REG); 364 spcr = davinci_mcbsp_read_reg(dev, DAVINCI_MCBSP_SPCR_REG);
365 if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) { 365 if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) {
366 w |= DAVINCI_MCBSP_SPCR_RINTM(3) | DAVINCI_MCBSP_SPCR_FREE; 366 spcr |= DAVINCI_MCBSP_SPCR_RINTM(3) | DAVINCI_MCBSP_SPCR_FREE;
367 davinci_mcbsp_write_reg(dev, DAVINCI_MCBSP_SPCR_REG, w); 367 davinci_mcbsp_write_reg(dev, DAVINCI_MCBSP_SPCR_REG, spcr);
368 } else { 368 } else {
369 w |= DAVINCI_MCBSP_SPCR_XINTM(3) | DAVINCI_MCBSP_SPCR_FREE; 369 spcr |= DAVINCI_MCBSP_SPCR_XINTM(3) | DAVINCI_MCBSP_SPCR_FREE;
370 davinci_mcbsp_write_reg(dev, DAVINCI_MCBSP_SPCR_REG, w); 370 davinci_mcbsp_write_reg(dev, DAVINCI_MCBSP_SPCR_REG, spcr);
371 } 371 }
372 372
373 i = hw_param_interval(params, SNDRV_PCM_HW_PARAM_SAMPLE_BITS); 373 i = hw_param_interval(params, SNDRV_PCM_HW_PARAM_SAMPLE_BITS);
374 w = DAVINCI_MCBSP_SRGR_FSGM; 374 srgr = DAVINCI_MCBSP_SRGR_FSGM;
375 MOD_REG_BIT(w, DAVINCI_MCBSP_SRGR_FWID(snd_interval_value(i) - 1), 1); 375 srgr |= DAVINCI_MCBSP_SRGR_FWID(snd_interval_value(i) - 1);
376 376
377 i = hw_param_interval(params, SNDRV_PCM_HW_PARAM_FRAME_BITS); 377 i = hw_param_interval(params, SNDRV_PCM_HW_PARAM_FRAME_BITS);
378 MOD_REG_BIT(w, DAVINCI_MCBSP_SRGR_FPER(snd_interval_value(i) - 1), 1); 378 srgr |= DAVINCI_MCBSP_SRGR_FPER(snd_interval_value(i) - 1);
379 davinci_mcbsp_write_reg(dev, DAVINCI_MCBSP_SRGR_REG, w); 379 davinci_mcbsp_write_reg(dev, DAVINCI_MCBSP_SRGR_REG, srgr);
380 380
381 rcr = DAVINCI_MCBSP_RCR_RFIG;
382 xcr = DAVINCI_MCBSP_XCR_XFIG;
383 if (dev->mode == MOD_DSP_B) {
384 rcr |= DAVINCI_MCBSP_RCR_RDATDLY(0);
385 xcr |= DAVINCI_MCBSP_XCR_XDATDLY(0);
386 } else {
387 rcr |= DAVINCI_MCBSP_RCR_RDATDLY(1);
388 xcr |= DAVINCI_MCBSP_XCR_XDATDLY(1);
389 }
381 /* Determine xfer data type */ 390 /* Determine xfer data type */
382 switch (params_format(params)) { 391 switch (params_format(params)) {
383 case SNDRV_PCM_FORMAT_S8: 392 case SNDRV_PCM_FORMAT_S8:
@@ -397,18 +406,31 @@ static int davinci_i2s_hw_params(struct snd_pcm_substream *substream,
397 return -EINVAL; 406 return -EINVAL;
398 } 407 }
399 408
400 if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) { 409 dma_params->acnt = dma_params->data_type;
401 w = davinci_mcbsp_read_reg(dev, DAVINCI_MCBSP_RCR_REG); 410 rcr |= DAVINCI_MCBSP_RCR_RFRLEN1(1);
402 MOD_REG_BIT(w, DAVINCI_MCBSP_RCR_RWDLEN1(mcbsp_word_length) | 411 xcr |= DAVINCI_MCBSP_XCR_XFRLEN1(1);
403 DAVINCI_MCBSP_RCR_RWDLEN2(mcbsp_word_length), 1);
404 davinci_mcbsp_write_reg(dev, DAVINCI_MCBSP_RCR_REG, w);
405 412
406 } else { 413 rcr |= DAVINCI_MCBSP_RCR_RWDLEN1(mcbsp_word_length) |
407 w = davinci_mcbsp_read_reg(dev, DAVINCI_MCBSP_XCR_REG); 414 DAVINCI_MCBSP_RCR_RWDLEN2(mcbsp_word_length);
408 MOD_REG_BIT(w, DAVINCI_MCBSP_XCR_XWDLEN1(mcbsp_word_length) | 415 xcr |= DAVINCI_MCBSP_XCR_XWDLEN1(mcbsp_word_length) |
409 DAVINCI_MCBSP_XCR_XWDLEN2(mcbsp_word_length), 1); 416 DAVINCI_MCBSP_XCR_XWDLEN2(mcbsp_word_length);
410 davinci_mcbsp_write_reg(dev, DAVINCI_MCBSP_XCR_REG, w);
411 417
418 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
419 davinci_mcbsp_write_reg(dev, DAVINCI_MCBSP_XCR_REG, xcr);
420 else
421 davinci_mcbsp_write_reg(dev, DAVINCI_MCBSP_RCR_REG, rcr);
422 return 0;
423}
424
425static int davinci_i2s_prepare(struct snd_pcm_substream *substream,
426 struct snd_soc_dai *dai)
427{
428 struct davinci_mcbsp_dev *dev = dai->private_data;
429 int playback = (substream->stream == SNDRV_PCM_STREAM_PLAYBACK);
430 davinci_mcbsp_stop(dev, playback);
431 if ((dev->pcr & DAVINCI_MCBSP_PCR_FSXM) == 0) {
432 /* codec is master */
433 davinci_mcbsp_start(dev, substream);
412 } 434 }
413 return 0; 435 return 0;
414} 436}
@@ -416,35 +438,72 @@ static int davinci_i2s_hw_params(struct snd_pcm_substream *substream,
416static int davinci_i2s_trigger(struct snd_pcm_substream *substream, int cmd, 438static int davinci_i2s_trigger(struct snd_pcm_substream *substream, int cmd,
417 struct snd_soc_dai *dai) 439 struct snd_soc_dai *dai)
418{ 440{
441 struct davinci_mcbsp_dev *dev = dai->private_data;
419 int ret = 0; 442 int ret = 0;
443 int playback = (substream->stream == SNDRV_PCM_STREAM_PLAYBACK);
444 if ((dev->pcr & DAVINCI_MCBSP_PCR_FSXM) == 0)
445 return 0; /* return if codec is master */
420 446
421 switch (cmd) { 447 switch (cmd) {
422 case SNDRV_PCM_TRIGGER_START: 448 case SNDRV_PCM_TRIGGER_START:
423 case SNDRV_PCM_TRIGGER_RESUME: 449 case SNDRV_PCM_TRIGGER_RESUME:
424 case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: 450 case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
425 davinci_mcbsp_start(substream); 451 davinci_mcbsp_start(dev, substream);
426 break; 452 break;
427 case SNDRV_PCM_TRIGGER_STOP: 453 case SNDRV_PCM_TRIGGER_STOP:
428 case SNDRV_PCM_TRIGGER_SUSPEND: 454 case SNDRV_PCM_TRIGGER_SUSPEND:
429 case SNDRV_PCM_TRIGGER_PAUSE_PUSH: 455 case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
430 davinci_mcbsp_stop(substream); 456 davinci_mcbsp_stop(dev, playback);
431 break; 457 break;
432 default: 458 default:
433 ret = -EINVAL; 459 ret = -EINVAL;
434 } 460 }
435
436 return ret; 461 return ret;
437} 462}
438 463
439static int davinci_i2s_probe(struct platform_device *pdev, 464static void davinci_i2s_shutdown(struct snd_pcm_substream *substream,
440 struct snd_soc_dai *dai) 465 struct snd_soc_dai *dai)
466{
467 struct davinci_mcbsp_dev *dev = dai->private_data;
468 int playback = (substream->stream == SNDRV_PCM_STREAM_PLAYBACK);
469 davinci_mcbsp_stop(dev, playback);
470}
471
472#define DAVINCI_I2S_RATES SNDRV_PCM_RATE_8000_96000
473
474static struct snd_soc_dai_ops davinci_i2s_dai_ops = {
475 .startup = davinci_i2s_startup,
476 .shutdown = davinci_i2s_shutdown,
477 .prepare = davinci_i2s_prepare,
478 .trigger = davinci_i2s_trigger,
479 .hw_params = davinci_i2s_hw_params,
480 .set_fmt = davinci_i2s_set_dai_fmt,
481
482};
483
484struct snd_soc_dai davinci_i2s_dai = {
485 .name = "davinci-i2s",
486 .id = 0,
487 .playback = {
488 .channels_min = 2,
489 .channels_max = 2,
490 .rates = DAVINCI_I2S_RATES,
491 .formats = SNDRV_PCM_FMTBIT_S16_LE,},
492 .capture = {
493 .channels_min = 2,
494 .channels_max = 2,
495 .rates = DAVINCI_I2S_RATES,
496 .formats = SNDRV_PCM_FMTBIT_S16_LE,},
497 .ops = &davinci_i2s_dai_ops,
498
499};
500EXPORT_SYMBOL_GPL(davinci_i2s_dai);
501
502static int davinci_i2s_probe(struct platform_device *pdev)
441{ 503{
442 struct snd_soc_device *socdev = platform_get_drvdata(pdev); 504 struct snd_platform_data *pdata = pdev->dev.platform_data;
443 struct snd_soc_card *card = socdev->card;
444 struct snd_soc_dai *cpu_dai = card->dai_link->cpu_dai;
445 struct davinci_mcbsp_dev *dev; 505 struct davinci_mcbsp_dev *dev;
446 struct resource *mem, *ioarea; 506 struct resource *mem, *ioarea, *res;
447 struct evm_snd_platform_data *pdata;
448 int ret; 507 int ret;
449 508
450 mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); 509 mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
@@ -466,8 +525,6 @@ static int davinci_i2s_probe(struct platform_device *pdev,
466 goto err_release_region; 525 goto err_release_region;
467 } 526 }
468 527
469 cpu_dai->private_data = dev;
470
471 dev->clk = clk_get(&pdev->dev, NULL); 528 dev->clk = clk_get(&pdev->dev, NULL);
472 if (IS_ERR(dev->clk)) { 529 if (IS_ERR(dev->clk)) {
473 ret = -ENODEV; 530 ret = -ENODEV;
@@ -476,18 +533,37 @@ static int davinci_i2s_probe(struct platform_device *pdev,
476 clk_enable(dev->clk); 533 clk_enable(dev->clk);
477 534
478 dev->base = (void __iomem *)IO_ADDRESS(mem->start); 535 dev->base = (void __iomem *)IO_ADDRESS(mem->start);
479 pdata = pdev->dev.platform_data;
480 536
481 dev->dma_params[SNDRV_PCM_STREAM_PLAYBACK] = &davinci_i2s_pcm_out; 537 dev->dma_params[SNDRV_PCM_STREAM_PLAYBACK] = &davinci_i2s_pcm_out;
482 dev->dma_params[SNDRV_PCM_STREAM_PLAYBACK]->channel = pdata->tx_dma_ch;
483 dev->dma_params[SNDRV_PCM_STREAM_PLAYBACK]->dma_addr = 538 dev->dma_params[SNDRV_PCM_STREAM_PLAYBACK]->dma_addr =
484 (dma_addr_t)(io_v2p(dev->base) + DAVINCI_MCBSP_DXR_REG); 539 (dma_addr_t)(io_v2p(dev->base) + DAVINCI_MCBSP_DXR_REG);
485 540
486 dev->dma_params[SNDRV_PCM_STREAM_CAPTURE] = &davinci_i2s_pcm_in; 541 dev->dma_params[SNDRV_PCM_STREAM_CAPTURE] = &davinci_i2s_pcm_in;
487 dev->dma_params[SNDRV_PCM_STREAM_CAPTURE]->channel = pdata->rx_dma_ch;
488 dev->dma_params[SNDRV_PCM_STREAM_CAPTURE]->dma_addr = 542 dev->dma_params[SNDRV_PCM_STREAM_CAPTURE]->dma_addr =
489 (dma_addr_t)(io_v2p(dev->base) + DAVINCI_MCBSP_DRR_REG); 543 (dma_addr_t)(io_v2p(dev->base) + DAVINCI_MCBSP_DRR_REG);
490 544
545 /* first TX, then RX */
546 res = platform_get_resource(pdev, IORESOURCE_DMA, 0);
547 if (!res) {
548 dev_err(&pdev->dev, "no DMA resource\n");
549 ret = -ENXIO;
550 goto err_free_mem;
551 }
552 dev->dma_params[SNDRV_PCM_STREAM_PLAYBACK]->channel = res->start;
553
554 res = platform_get_resource(pdev, IORESOURCE_DMA, 1);
555 if (!res) {
556 dev_err(&pdev->dev, "no DMA resource\n");
557 ret = -ENXIO;
558 goto err_free_mem;
559 }
560 dev->dma_params[SNDRV_PCM_STREAM_CAPTURE]->channel = res->start;
561
562 davinci_i2s_dai.private_data = dev;
563 ret = snd_soc_register_dai(&davinci_i2s_dai);
564 if (ret != 0)
565 goto err_free_mem;
566
491 return 0; 567 return 0;
492 568
493err_free_mem: 569err_free_mem:
@@ -498,62 +574,40 @@ err_release_region:
498 return ret; 574 return ret;
499} 575}
500 576
501static void davinci_i2s_remove(struct platform_device *pdev, 577static int davinci_i2s_remove(struct platform_device *pdev)
502 struct snd_soc_dai *dai)
503{ 578{
504 struct snd_soc_device *socdev = platform_get_drvdata(pdev); 579 struct davinci_mcbsp_dev *dev = davinci_i2s_dai.private_data;
505 struct snd_soc_card *card = socdev->card;
506 struct snd_soc_dai *cpu_dai = card->dai_link->cpu_dai;
507 struct davinci_mcbsp_dev *dev = cpu_dai->private_data;
508 struct resource *mem; 580 struct resource *mem;
509 581
582 snd_soc_unregister_dai(&davinci_i2s_dai);
510 clk_disable(dev->clk); 583 clk_disable(dev->clk);
511 clk_put(dev->clk); 584 clk_put(dev->clk);
512 dev->clk = NULL; 585 dev->clk = NULL;
513
514 kfree(dev); 586 kfree(dev);
515
516 mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); 587 mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
517 release_mem_region(mem->start, (mem->end - mem->start) + 1); 588 release_mem_region(mem->start, (mem->end - mem->start) + 1);
518}
519 589
520#define DAVINCI_I2S_RATES SNDRV_PCM_RATE_8000_96000 590 return 0;
521 591}
522static struct snd_soc_dai_ops davinci_i2s_dai_ops = {
523 .startup = davinci_i2s_startup,
524 .trigger = davinci_i2s_trigger,
525 .hw_params = davinci_i2s_hw_params,
526 .set_fmt = davinci_i2s_set_dai_fmt,
527};
528 592
529struct snd_soc_dai davinci_i2s_dai = { 593static struct platform_driver davinci_mcbsp_driver = {
530 .name = "davinci-i2s", 594 .probe = davinci_i2s_probe,
531 .id = 0, 595 .remove = davinci_i2s_remove,
532 .probe = davinci_i2s_probe, 596 .driver = {
533 .remove = davinci_i2s_remove, 597 .name = "davinci-asp",
534 .playback = { 598 .owner = THIS_MODULE,
535 .channels_min = 2, 599 },
536 .channels_max = 2,
537 .rates = DAVINCI_I2S_RATES,
538 .formats = SNDRV_PCM_FMTBIT_S16_LE,},
539 .capture = {
540 .channels_min = 2,
541 .channels_max = 2,
542 .rates = DAVINCI_I2S_RATES,
543 .formats = SNDRV_PCM_FMTBIT_S16_LE,},
544 .ops = &davinci_i2s_dai_ops,
545}; 600};
546EXPORT_SYMBOL_GPL(davinci_i2s_dai);
547 601
548static int __init davinci_i2s_init(void) 602static int __init davinci_i2s_init(void)
549{ 603{
550 return snd_soc_register_dai(&davinci_i2s_dai); 604 return platform_driver_register(&davinci_mcbsp_driver);
551} 605}
552module_init(davinci_i2s_init); 606module_init(davinci_i2s_init);
553 607
554static void __exit davinci_i2s_exit(void) 608static void __exit davinci_i2s_exit(void)
555{ 609{
556 snd_soc_unregister_dai(&davinci_i2s_dai); 610 platform_driver_unregister(&davinci_mcbsp_driver);
557} 611}
558module_exit(davinci_i2s_exit); 612module_exit(davinci_i2s_exit);
559 613
diff --git a/sound/soc/davinci/davinci-mcasp.c b/sound/soc/davinci/davinci-mcasp.c
new file mode 100644
index 000000000000..eca22d7829d2
--- /dev/null
+++ b/sound/soc/davinci/davinci-mcasp.c
@@ -0,0 +1,973 @@
1/*
2 * ALSA SoC McASP Audio Layer for TI DAVINCI processor
3 *
4 * Multi-channel Audio Serial Port Driver
5 *
6 * Author: Nirmal Pandey <n-pandey@ti.com>,
7 * Suresh Rajashekara <suresh.r@ti.com>
8 * Steve Chen <schen@.mvista.com>
9 *
10 * Copyright: (C) 2009 MontaVista Software, Inc., <source@mvista.com>
11 * Copyright: (C) 2009 Texas Instruments, India
12 *
13 * This program is free software; you can redistribute it and/or modify
14 * it under the terms of the GNU General Public License version 2 as
15 * published by the Free Software Foundation.
16 */
17
18#include <linux/init.h>
19#include <linux/module.h>
20#include <linux/device.h>
21#include <linux/delay.h>
22#include <linux/io.h>
23#include <linux/clk.h>
24
25#include <sound/core.h>
26#include <sound/pcm.h>
27#include <sound/pcm_params.h>
28#include <sound/initval.h>
29#include <sound/soc.h>
30
31#include "davinci-pcm.h"
32#include "davinci-mcasp.h"
33
34/*
35 * McASP register definitions
36 */
37#define DAVINCI_MCASP_PID_REG 0x00
38#define DAVINCI_MCASP_PWREMUMGT_REG 0x04
39
40#define DAVINCI_MCASP_PFUNC_REG 0x10
41#define DAVINCI_MCASP_PDIR_REG 0x14
42#define DAVINCI_MCASP_PDOUT_REG 0x18
43#define DAVINCI_MCASP_PDSET_REG 0x1c
44
45#define DAVINCI_MCASP_PDCLR_REG 0x20
46
47#define DAVINCI_MCASP_TLGC_REG 0x30
48#define DAVINCI_MCASP_TLMR_REG 0x34
49
50#define DAVINCI_MCASP_GBLCTL_REG 0x44
51#define DAVINCI_MCASP_AMUTE_REG 0x48
52#define DAVINCI_MCASP_LBCTL_REG 0x4c
53
54#define DAVINCI_MCASP_TXDITCTL_REG 0x50
55
56#define DAVINCI_MCASP_GBLCTLR_REG 0x60
57#define DAVINCI_MCASP_RXMASK_REG 0x64
58#define DAVINCI_MCASP_RXFMT_REG 0x68
59#define DAVINCI_MCASP_RXFMCTL_REG 0x6c
60
61#define DAVINCI_MCASP_ACLKRCTL_REG 0x70
62#define DAVINCI_MCASP_AHCLKRCTL_REG 0x74
63#define DAVINCI_MCASP_RXTDM_REG 0x78
64#define DAVINCI_MCASP_EVTCTLR_REG 0x7c
65
66#define DAVINCI_MCASP_RXSTAT_REG 0x80
67#define DAVINCI_MCASP_RXTDMSLOT_REG 0x84
68#define DAVINCI_MCASP_RXCLKCHK_REG 0x88
69#define DAVINCI_MCASP_REVTCTL_REG 0x8c
70
71#define DAVINCI_MCASP_GBLCTLX_REG 0xa0
72#define DAVINCI_MCASP_TXMASK_REG 0xa4
73#define DAVINCI_MCASP_TXFMT_REG 0xa8
74#define DAVINCI_MCASP_TXFMCTL_REG 0xac
75
76#define DAVINCI_MCASP_ACLKXCTL_REG 0xb0
77#define DAVINCI_MCASP_AHCLKXCTL_REG 0xb4
78#define DAVINCI_MCASP_TXTDM_REG 0xb8
79#define DAVINCI_MCASP_EVTCTLX_REG 0xbc
80
81#define DAVINCI_MCASP_TXSTAT_REG 0xc0
82#define DAVINCI_MCASP_TXTDMSLOT_REG 0xc4
83#define DAVINCI_MCASP_TXCLKCHK_REG 0xc8
84#define DAVINCI_MCASP_XEVTCTL_REG 0xcc
85
86/* Left(even TDM Slot) Channel Status Register File */
87#define DAVINCI_MCASP_DITCSRA_REG 0x100
88/* Right(odd TDM slot) Channel Status Register File */
89#define DAVINCI_MCASP_DITCSRB_REG 0x118
90/* Left(even TDM slot) User Data Register File */
91#define DAVINCI_MCASP_DITUDRA_REG 0x130
92/* Right(odd TDM Slot) User Data Register File */
93#define DAVINCI_MCASP_DITUDRB_REG 0x148
94
95/* Serializer n Control Register */
96#define DAVINCI_MCASP_XRSRCTL_BASE_REG 0x180
97#define DAVINCI_MCASP_XRSRCTL_REG(n) (DAVINCI_MCASP_XRSRCTL_BASE_REG + \
98 (n << 2))
99
100/* Transmit Buffer for Serializer n */
101#define DAVINCI_MCASP_TXBUF_REG 0x200
102/* Receive Buffer for Serializer n */
103#define DAVINCI_MCASP_RXBUF_REG 0x280
104
105/* McASP FIFO Registers */
106#define DAVINCI_MCASP_WFIFOCTL (0x1010)
107#define DAVINCI_MCASP_WFIFOSTS (0x1014)
108#define DAVINCI_MCASP_RFIFOCTL (0x1018)
109#define DAVINCI_MCASP_RFIFOSTS (0x101C)
110
111/*
112 * DAVINCI_MCASP_PWREMUMGT_REG - Power Down and Emulation Management
113 * Register Bits
114 */
115#define MCASP_FREE BIT(0)
116#define MCASP_SOFT BIT(1)
117
118/*
119 * DAVINCI_MCASP_PFUNC_REG - Pin Function / GPIO Enable Register Bits
120 */
121#define AXR(n) (1<<n)
122#define PFUNC_AMUTE BIT(25)
123#define ACLKX BIT(26)
124#define AHCLKX BIT(27)
125#define AFSX BIT(28)
126#define ACLKR BIT(29)
127#define AHCLKR BIT(30)
128#define AFSR BIT(31)
129
130/*
131 * DAVINCI_MCASP_PDIR_REG - Pin Direction Register Bits
132 */
133#define AXR(n) (1<<n)
134#define PDIR_AMUTE BIT(25)
135#define ACLKX BIT(26)
136#define AHCLKX BIT(27)
137#define AFSX BIT(28)
138#define ACLKR BIT(29)
139#define AHCLKR BIT(30)
140#define AFSR BIT(31)
141
142/*
143 * DAVINCI_MCASP_TXDITCTL_REG - Transmit DIT Control Register Bits
144 */
145#define DITEN BIT(0) /* Transmit DIT mode enable/disable */
146#define VA BIT(2)
147#define VB BIT(3)
148
149/*
150 * DAVINCI_MCASP_TXFMT_REG - Transmit Bitstream Format Register Bits
151 */
152#define TXROT(val) (val)
153#define TXSEL BIT(3)
154#define TXSSZ(val) (val<<4)
155#define TXPBIT(val) (val<<8)
156#define TXPAD(val) (val<<13)
157#define TXORD BIT(15)
158#define FSXDLY(val) (val<<16)
159
160/*
161 * DAVINCI_MCASP_RXFMT_REG - Receive Bitstream Format Register Bits
162 */
163#define RXROT(val) (val)
164#define RXSEL BIT(3)
165#define RXSSZ(val) (val<<4)
166#define RXPBIT(val) (val<<8)
167#define RXPAD(val) (val<<13)
168#define RXORD BIT(15)
169#define FSRDLY(val) (val<<16)
170
171/*
172 * DAVINCI_MCASP_TXFMCTL_REG - Transmit Frame Control Register Bits
173 */
174#define FSXPOL BIT(0)
175#define AFSXE BIT(1)
176#define FSXDUR BIT(4)
177#define FSXMOD(val) (val<<7)
178
179/*
180 * DAVINCI_MCASP_RXFMCTL_REG - Receive Frame Control Register Bits
181 */
182#define FSRPOL BIT(0)
183#define AFSRE BIT(1)
184#define FSRDUR BIT(4)
185#define FSRMOD(val) (val<<7)
186
187/*
188 * DAVINCI_MCASP_ACLKXCTL_REG - Transmit Clock Control Register Bits
189 */
190#define ACLKXDIV(val) (val)
191#define ACLKXE BIT(5)
192#define TX_ASYNC BIT(6)
193#define ACLKXPOL BIT(7)
194
195/*
196 * DAVINCI_MCASP_ACLKRCTL_REG Receive Clock Control Register Bits
197 */
198#define ACLKRDIV(val) (val)
199#define ACLKRE BIT(5)
200#define RX_ASYNC BIT(6)
201#define ACLKRPOL BIT(7)
202
203/*
204 * DAVINCI_MCASP_AHCLKXCTL_REG - High Frequency Transmit Clock Control
205 * Register Bits
206 */
207#define AHCLKXDIV(val) (val)
208#define AHCLKXPOL BIT(14)
209#define AHCLKXE BIT(15)
210
211/*
212 * DAVINCI_MCASP_AHCLKRCTL_REG - High Frequency Receive Clock Control
213 * Register Bits
214 */
215#define AHCLKRDIV(val) (val)
216#define AHCLKRPOL BIT(14)
217#define AHCLKRE BIT(15)
218
219/*
220 * DAVINCI_MCASP_XRSRCTL_BASE_REG - Serializer Control Register Bits
221 */
222#define MODE(val) (val)
223#define DISMOD (val)(val<<2)
224#define TXSTATE BIT(4)
225#define RXSTATE BIT(5)
226
227/*
228 * DAVINCI_MCASP_LBCTL_REG - Loop Back Control Register Bits
229 */
230#define LBEN BIT(0)
231#define LBORD BIT(1)
232#define LBGENMODE(val) (val<<2)
233
234/*
235 * DAVINCI_MCASP_TXTDMSLOT_REG - Transmit TDM Slot Register configuration
236 */
237#define TXTDMS(n) (1<<n)
238
239/*
240 * DAVINCI_MCASP_RXTDMSLOT_REG - Receive TDM Slot Register configuration
241 */
242#define RXTDMS(n) (1<<n)
243
244/*
245 * DAVINCI_MCASP_GBLCTL_REG - Global Control Register Bits
246 */
247#define RXCLKRST BIT(0) /* Receiver Clock Divider Reset */
248#define RXHCLKRST BIT(1) /* Receiver High Frequency Clock Divider */
249#define RXSERCLR BIT(2) /* Receiver Serializer Clear */
250#define RXSMRST BIT(3) /* Receiver State Machine Reset */
251#define RXFSRST BIT(4) /* Frame Sync Generator Reset */
252#define TXCLKRST BIT(8) /* Transmitter Clock Divider Reset */
253#define TXHCLKRST BIT(9) /* Transmitter High Frequency Clock Divider*/
254#define TXSERCLR BIT(10) /* Transmit Serializer Clear */
255#define TXSMRST BIT(11) /* Transmitter State Machine Reset */
256#define TXFSRST BIT(12) /* Frame Sync Generator Reset */
257
258/*
259 * DAVINCI_MCASP_AMUTE_REG - Mute Control Register Bits
260 */
261#define MUTENA(val) (val)
262#define MUTEINPOL BIT(2)
263#define MUTEINENA BIT(3)
264#define MUTEIN BIT(4)
265#define MUTER BIT(5)
266#define MUTEX BIT(6)
267#define MUTEFSR BIT(7)
268#define MUTEFSX BIT(8)
269#define MUTEBADCLKR BIT(9)
270#define MUTEBADCLKX BIT(10)
271#define MUTERXDMAERR BIT(11)
272#define MUTETXDMAERR BIT(12)
273
274/*
275 * DAVINCI_MCASP_REVTCTL_REG - Receiver DMA Event Control Register bits
276 */
277#define RXDATADMADIS BIT(0)
278
279/*
280 * DAVINCI_MCASP_XEVTCTL_REG - Transmitter DMA Event Control Register bits
281 */
282#define TXDATADMADIS BIT(0)
283
284/*
285 * DAVINCI_MCASP_W[R]FIFOCTL - Write/Read FIFO Control Register bits
286 */
287#define FIFO_ENABLE BIT(16)
288#define NUMEVT_MASK (0xFF << 8)
289#define NUMDMA_MASK (0xFF)
290
291#define DAVINCI_MCASP_NUM_SERIALIZER 16
292
293static inline void mcasp_set_bits(void __iomem *reg, u32 val)
294{
295 __raw_writel(__raw_readl(reg) | val, reg);
296}
297
298static inline void mcasp_clr_bits(void __iomem *reg, u32 val)
299{
300 __raw_writel((__raw_readl(reg) & ~(val)), reg);
301}
302
303static inline void mcasp_mod_bits(void __iomem *reg, u32 val, u32 mask)
304{
305 __raw_writel((__raw_readl(reg) & ~mask) | val, reg);
306}
307
308static inline void mcasp_set_reg(void __iomem *reg, u32 val)
309{
310 __raw_writel(val, reg);
311}
312
313static inline u32 mcasp_get_reg(void __iomem *reg)
314{
315 return (unsigned int)__raw_readl(reg);
316}
317
318static inline void mcasp_set_ctl_reg(void __iomem *regs, u32 val)
319{
320 int i = 0;
321
322 mcasp_set_bits(regs, val);
323
324 /* programming GBLCTL needs to read back from GBLCTL and verfiy */
325 /* loop count is to avoid the lock-up */
326 for (i = 0; i < 1000; i++) {
327 if ((mcasp_get_reg(regs) & val) == val)
328 break;
329 }
330
331 if (i == 1000 && ((mcasp_get_reg(regs) & val) != val))
332 printk(KERN_ERR "GBLCTL write error\n");
333}
334
335static int davinci_mcasp_startup(struct snd_pcm_substream *substream,
336 struct snd_soc_dai *cpu_dai)
337{
338 struct davinci_audio_dev *dev = cpu_dai->private_data;
339 cpu_dai->dma_data = dev->dma_params[substream->stream];
340 return 0;
341}
342
343static void mcasp_start_rx(struct davinci_audio_dev *dev)
344{
345 mcasp_set_ctl_reg(dev->base + DAVINCI_MCASP_GBLCTLR_REG, RXHCLKRST);
346 mcasp_set_ctl_reg(dev->base + DAVINCI_MCASP_GBLCTLR_REG, RXCLKRST);
347 mcasp_set_ctl_reg(dev->base + DAVINCI_MCASP_GBLCTLR_REG, RXSERCLR);
348 mcasp_set_reg(dev->base + DAVINCI_MCASP_RXBUF_REG, 0);
349
350 mcasp_set_ctl_reg(dev->base + DAVINCI_MCASP_GBLCTLR_REG, RXSMRST);
351 mcasp_set_ctl_reg(dev->base + DAVINCI_MCASP_GBLCTLR_REG, RXFSRST);
352 mcasp_set_reg(dev->base + DAVINCI_MCASP_RXBUF_REG, 0);
353
354 mcasp_set_ctl_reg(dev->base + DAVINCI_MCASP_GBLCTLR_REG, RXSMRST);
355 mcasp_set_ctl_reg(dev->base + DAVINCI_MCASP_GBLCTLR_REG, RXFSRST);
356}
357
358static void mcasp_start_tx(struct davinci_audio_dev *dev)
359{
360 u8 offset = 0, i;
361 u32 cnt;
362
363 mcasp_set_ctl_reg(dev->base + DAVINCI_MCASP_GBLCTLX_REG, TXHCLKRST);
364 mcasp_set_ctl_reg(dev->base + DAVINCI_MCASP_GBLCTLX_REG, TXCLKRST);
365 mcasp_set_ctl_reg(dev->base + DAVINCI_MCASP_GBLCTLX_REG, TXSERCLR);
366 mcasp_set_reg(dev->base + DAVINCI_MCASP_TXBUF_REG, 0);
367
368 mcasp_set_ctl_reg(dev->base + DAVINCI_MCASP_GBLCTLX_REG, TXSMRST);
369 mcasp_set_ctl_reg(dev->base + DAVINCI_MCASP_GBLCTLX_REG, TXFSRST);
370 mcasp_set_reg(dev->base + DAVINCI_MCASP_TXBUF_REG, 0);
371 for (i = 0; i < dev->num_serializer; i++) {
372 if (dev->serial_dir[i] == TX_MODE) {
373 offset = i;
374 break;
375 }
376 }
377
378 /* wait for TX ready */
379 cnt = 0;
380 while (!(mcasp_get_reg(dev->base + DAVINCI_MCASP_XRSRCTL_REG(offset)) &
381 TXSTATE) && (cnt < 100000))
382 cnt++;
383
384 mcasp_set_reg(dev->base + DAVINCI_MCASP_TXBUF_REG, 0);
385}
386
387static void davinci_mcasp_start(struct davinci_audio_dev *dev, int stream)
388{
389 if (stream == SNDRV_PCM_STREAM_PLAYBACK)
390 mcasp_start_tx(dev);
391 else
392 mcasp_start_rx(dev);
393
394 /* enable FIFO */
395 if (dev->txnumevt)
396 mcasp_set_bits(dev->base + DAVINCI_MCASP_WFIFOCTL, FIFO_ENABLE);
397
398 if (dev->rxnumevt)
399 mcasp_set_bits(dev->base + DAVINCI_MCASP_RFIFOCTL, FIFO_ENABLE);
400}
401
402static void mcasp_stop_rx(struct davinci_audio_dev *dev)
403{
404 mcasp_set_reg(dev->base + DAVINCI_MCASP_GBLCTLR_REG, 0);
405 mcasp_set_reg(dev->base + DAVINCI_MCASP_RXSTAT_REG, 0xFFFFFFFF);
406}
407
408static void mcasp_stop_tx(struct davinci_audio_dev *dev)
409{
410 mcasp_set_reg(dev->base + DAVINCI_MCASP_GBLCTLX_REG, 0);
411 mcasp_set_reg(dev->base + DAVINCI_MCASP_TXSTAT_REG, 0xFFFFFFFF);
412}
413
414static void davinci_mcasp_stop(struct davinci_audio_dev *dev, int stream)
415{
416 if (stream == SNDRV_PCM_STREAM_PLAYBACK)
417 mcasp_stop_tx(dev);
418 else
419 mcasp_stop_rx(dev);
420
421 /* disable FIFO */
422 if (dev->txnumevt)
423 mcasp_clr_bits(dev->base + DAVINCI_MCASP_WFIFOCTL, FIFO_ENABLE);
424
425 if (dev->rxnumevt)
426 mcasp_clr_bits(dev->base + DAVINCI_MCASP_RFIFOCTL, FIFO_ENABLE);
427}
428
429static int davinci_mcasp_set_dai_fmt(struct snd_soc_dai *cpu_dai,
430 unsigned int fmt)
431{
432 struct davinci_audio_dev *dev = cpu_dai->private_data;
433 void __iomem *base = dev->base;
434
435 switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
436 case SND_SOC_DAIFMT_CBS_CFS:
437 /* codec is clock and frame slave */
438 mcasp_set_bits(base + DAVINCI_MCASP_ACLKXCTL_REG, ACLKXE);
439 mcasp_set_bits(base + DAVINCI_MCASP_TXFMCTL_REG, AFSXE);
440
441 mcasp_set_bits(base + DAVINCI_MCASP_ACLKRCTL_REG, ACLKRE);
442 mcasp_set_bits(base + DAVINCI_MCASP_RXFMCTL_REG, AFSRE);
443
444 mcasp_set_bits(base + DAVINCI_MCASP_PDIR_REG, (0x7 << 26));
445 break;
446 case SND_SOC_DAIFMT_CBM_CFS:
447 /* codec is clock master and frame slave */
448 mcasp_set_bits(base + DAVINCI_MCASP_ACLKXCTL_REG, ACLKXE);
449 mcasp_set_bits(base + DAVINCI_MCASP_TXFMCTL_REG, AFSXE);
450
451 mcasp_set_bits(base + DAVINCI_MCASP_ACLKRCTL_REG, ACLKRE);
452 mcasp_set_bits(base + DAVINCI_MCASP_RXFMCTL_REG, AFSRE);
453
454 mcasp_set_bits(base + DAVINCI_MCASP_PDIR_REG, (0x2d << 26));
455 break;
456 case SND_SOC_DAIFMT_CBM_CFM:
457 /* codec is clock and frame master */
458 mcasp_clr_bits(base + DAVINCI_MCASP_ACLKXCTL_REG, ACLKXE);
459 mcasp_clr_bits(base + DAVINCI_MCASP_TXFMCTL_REG, AFSXE);
460
461 mcasp_clr_bits(base + DAVINCI_MCASP_ACLKRCTL_REG, ACLKRE);
462 mcasp_clr_bits(base + DAVINCI_MCASP_RXFMCTL_REG, AFSRE);
463
464 mcasp_clr_bits(base + DAVINCI_MCASP_PDIR_REG, (0x3f << 26));
465 break;
466
467 default:
468 return -EINVAL;
469 }
470
471 switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
472 case SND_SOC_DAIFMT_IB_NF:
473 mcasp_clr_bits(base + DAVINCI_MCASP_ACLKXCTL_REG, ACLKXPOL);
474 mcasp_clr_bits(base + DAVINCI_MCASP_TXFMCTL_REG, FSXPOL);
475
476 mcasp_set_bits(base + DAVINCI_MCASP_ACLKRCTL_REG, ACLKRPOL);
477 mcasp_clr_bits(base + DAVINCI_MCASP_RXFMCTL_REG, FSRPOL);
478 break;
479
480 case SND_SOC_DAIFMT_NB_IF:
481 mcasp_set_bits(base + DAVINCI_MCASP_ACLKXCTL_REG, ACLKXPOL);
482 mcasp_set_bits(base + DAVINCI_MCASP_TXFMCTL_REG, FSXPOL);
483
484 mcasp_clr_bits(base + DAVINCI_MCASP_ACLKRCTL_REG, ACLKRPOL);
485 mcasp_set_bits(base + DAVINCI_MCASP_RXFMCTL_REG, FSRPOL);
486 break;
487
488 case SND_SOC_DAIFMT_IB_IF:
489 mcasp_clr_bits(base + DAVINCI_MCASP_ACLKXCTL_REG, ACLKXPOL);
490 mcasp_set_bits(base + DAVINCI_MCASP_TXFMCTL_REG, FSXPOL);
491
492 mcasp_set_bits(base + DAVINCI_MCASP_ACLKRCTL_REG, ACLKRPOL);
493 mcasp_set_bits(base + DAVINCI_MCASP_RXFMCTL_REG, FSRPOL);
494 break;
495
496 case SND_SOC_DAIFMT_NB_NF:
497 mcasp_set_bits(base + DAVINCI_MCASP_ACLKXCTL_REG, ACLKXPOL);
498 mcasp_clr_bits(base + DAVINCI_MCASP_TXFMCTL_REG, FSXPOL);
499
500 mcasp_clr_bits(base + DAVINCI_MCASP_ACLKRCTL_REG, ACLKRPOL);
501 mcasp_clr_bits(base + DAVINCI_MCASP_RXFMCTL_REG, FSRPOL);
502 break;
503
504 default:
505 return -EINVAL;
506 }
507
508 return 0;
509}
510
511static int davinci_config_channel_size(struct davinci_audio_dev *dev,
512 int channel_size)
513{
514 u32 fmt = 0;
515
516 switch (channel_size) {
517 case DAVINCI_AUDIO_WORD_8:
518 fmt = 0x03;
519 break;
520
521 case DAVINCI_AUDIO_WORD_12:
522 fmt = 0x05;
523 break;
524
525 case DAVINCI_AUDIO_WORD_16:
526 fmt = 0x07;
527 break;
528
529 case DAVINCI_AUDIO_WORD_20:
530 fmt = 0x09;
531 break;
532
533 case DAVINCI_AUDIO_WORD_24:
534 fmt = 0x0B;
535 break;
536
537 case DAVINCI_AUDIO_WORD_28:
538 fmt = 0x0D;
539 break;
540
541 case DAVINCI_AUDIO_WORD_32:
542 fmt = 0x0F;
543 break;
544
545 default:
546 return -EINVAL;
547 }
548
549 mcasp_mod_bits(dev->base + DAVINCI_MCASP_RXFMT_REG,
550 RXSSZ(fmt), RXSSZ(0x0F));
551 mcasp_mod_bits(dev->base + DAVINCI_MCASP_TXFMT_REG,
552 TXSSZ(fmt), TXSSZ(0x0F));
553 return 0;
554}
555
556static void davinci_hw_common_param(struct davinci_audio_dev *dev, int stream)
557{
558 int i;
559 u8 tx_ser = 0;
560 u8 rx_ser = 0;
561
562 /* Default configuration */
563 mcasp_set_bits(dev->base + DAVINCI_MCASP_PWREMUMGT_REG, MCASP_SOFT);
564
565 /* All PINS as McASP */
566 mcasp_set_reg(dev->base + DAVINCI_MCASP_PFUNC_REG, 0x00000000);
567
568 if (stream == SNDRV_PCM_STREAM_PLAYBACK) {
569 mcasp_set_reg(dev->base + DAVINCI_MCASP_TXSTAT_REG, 0xFFFFFFFF);
570 mcasp_clr_bits(dev->base + DAVINCI_MCASP_XEVTCTL_REG,
571 TXDATADMADIS);
572 } else {
573 mcasp_set_reg(dev->base + DAVINCI_MCASP_RXSTAT_REG, 0xFFFFFFFF);
574 mcasp_clr_bits(dev->base + DAVINCI_MCASP_REVTCTL_REG,
575 RXDATADMADIS);
576 }
577
578 for (i = 0; i < dev->num_serializer; i++) {
579 mcasp_set_bits(dev->base + DAVINCI_MCASP_XRSRCTL_REG(i),
580 dev->serial_dir[i]);
581 if (dev->serial_dir[i] == TX_MODE) {
582 mcasp_set_bits(dev->base + DAVINCI_MCASP_PDIR_REG,
583 AXR(i));
584 tx_ser++;
585 } else if (dev->serial_dir[i] == RX_MODE) {
586 mcasp_clr_bits(dev->base + DAVINCI_MCASP_PDIR_REG,
587 AXR(i));
588 rx_ser++;
589 }
590 }
591
592 if (dev->txnumevt && stream == SNDRV_PCM_STREAM_PLAYBACK) {
593 if (dev->txnumevt * tx_ser > 64)
594 dev->txnumevt = 1;
595
596 mcasp_mod_bits(dev->base + DAVINCI_MCASP_WFIFOCTL, tx_ser,
597 NUMDMA_MASK);
598 mcasp_mod_bits(dev->base + DAVINCI_MCASP_WFIFOCTL,
599 ((dev->txnumevt * tx_ser) << 8), NUMEVT_MASK);
600 mcasp_set_bits(dev->base + DAVINCI_MCASP_WFIFOCTL, FIFO_ENABLE);
601 }
602
603 if (dev->rxnumevt && stream == SNDRV_PCM_STREAM_CAPTURE) {
604 if (dev->rxnumevt * rx_ser > 64)
605 dev->rxnumevt = 1;
606
607 mcasp_mod_bits(dev->base + DAVINCI_MCASP_RFIFOCTL, rx_ser,
608 NUMDMA_MASK);
609 mcasp_mod_bits(dev->base + DAVINCI_MCASP_RFIFOCTL,
610 ((dev->rxnumevt * rx_ser) << 8), NUMEVT_MASK);
611 mcasp_set_bits(dev->base + DAVINCI_MCASP_RFIFOCTL, FIFO_ENABLE);
612 }
613}
614
615static void davinci_hw_param(struct davinci_audio_dev *dev, int stream)
616{
617 int i, active_slots;
618 u32 mask = 0;
619
620 active_slots = (dev->tdm_slots > 31) ? 32 : dev->tdm_slots;
621 for (i = 0; i < active_slots; i++)
622 mask |= (1 << i);
623
624 mcasp_clr_bits(dev->base + DAVINCI_MCASP_ACLKXCTL_REG, TX_ASYNC);
625
626 if (stream == SNDRV_PCM_STREAM_PLAYBACK) {
627 /* bit stream is MSB first with no delay */
628 /* DSP_B mode */
629 mcasp_set_bits(dev->base + DAVINCI_MCASP_AHCLKXCTL_REG,
630 AHCLKXE);
631 mcasp_set_reg(dev->base + DAVINCI_MCASP_TXTDM_REG, mask);
632 mcasp_set_bits(dev->base + DAVINCI_MCASP_TXFMT_REG, TXORD);
633
634 if ((dev->tdm_slots >= 2) || (dev->tdm_slots <= 32))
635 mcasp_mod_bits(dev->base + DAVINCI_MCASP_TXFMCTL_REG,
636 FSXMOD(dev->tdm_slots), FSXMOD(0x1FF));
637 else
638 printk(KERN_ERR "playback tdm slot %d not supported\n",
639 dev->tdm_slots);
640
641 mcasp_set_reg(dev->base + DAVINCI_MCASP_TXMASK_REG, 0xFFFFFFFF);
642 mcasp_clr_bits(dev->base + DAVINCI_MCASP_TXFMCTL_REG, FSXDUR);
643 } else {
644 /* bit stream is MSB first with no delay */
645 /* DSP_B mode */
646 mcasp_set_bits(dev->base + DAVINCI_MCASP_RXFMT_REG, RXORD);
647 mcasp_set_bits(dev->base + DAVINCI_MCASP_AHCLKRCTL_REG,
648 AHCLKRE);
649 mcasp_set_reg(dev->base + DAVINCI_MCASP_RXTDM_REG, mask);
650
651 if ((dev->tdm_slots >= 2) || (dev->tdm_slots <= 32))
652 mcasp_mod_bits(dev->base + DAVINCI_MCASP_RXFMCTL_REG,
653 FSRMOD(dev->tdm_slots), FSRMOD(0x1FF));
654 else
655 printk(KERN_ERR "capture tdm slot %d not supported\n",
656 dev->tdm_slots);
657
658 mcasp_set_reg(dev->base + DAVINCI_MCASP_RXMASK_REG, 0xFFFFFFFF);
659 mcasp_clr_bits(dev->base + DAVINCI_MCASP_RXFMCTL_REG, FSRDUR);
660 }
661}
662
663/* S/PDIF */
664static void davinci_hw_dit_param(struct davinci_audio_dev *dev)
665{
666 /* Set the PDIR for Serialiser as output */
667 mcasp_set_bits(dev->base + DAVINCI_MCASP_PDIR_REG, AFSX);
668
669 /* TXMASK for 24 bits */
670 mcasp_set_reg(dev->base + DAVINCI_MCASP_TXMASK_REG, 0x00FFFFFF);
671
672 /* Set the TX format : 24 bit right rotation, 32 bit slot, Pad 0
673 and LSB first */
674 mcasp_set_bits(dev->base + DAVINCI_MCASP_TXFMT_REG,
675 TXROT(6) | TXSSZ(15));
676
677 /* Set TX frame synch : DIT Mode, 1 bit width, internal, rising edge */
678 mcasp_set_reg(dev->base + DAVINCI_MCASP_TXFMCTL_REG,
679 AFSXE | FSXMOD(0x180));
680
681 /* Set the TX tdm : for all the slots */
682 mcasp_set_reg(dev->base + DAVINCI_MCASP_TXTDM_REG, 0xFFFFFFFF);
683
684 /* Set the TX clock controls : div = 1 and internal */
685 mcasp_set_bits(dev->base + DAVINCI_MCASP_ACLKXCTL_REG,
686 ACLKXE | TX_ASYNC);
687
688 mcasp_clr_bits(dev->base + DAVINCI_MCASP_XEVTCTL_REG, TXDATADMADIS);
689
690 /* Only 44100 and 48000 are valid, both have the same setting */
691 mcasp_set_bits(dev->base + DAVINCI_MCASP_AHCLKXCTL_REG, AHCLKXDIV(3));
692
693 /* Enable the DIT */
694 mcasp_set_bits(dev->base + DAVINCI_MCASP_TXDITCTL_REG, DITEN);
695}
696
697static int davinci_mcasp_hw_params(struct snd_pcm_substream *substream,
698 struct snd_pcm_hw_params *params,
699 struct snd_soc_dai *cpu_dai)
700{
701 struct davinci_audio_dev *dev = cpu_dai->private_data;
702 struct davinci_pcm_dma_params *dma_params =
703 dev->dma_params[substream->stream];
704 int word_length;
705 u8 numevt;
706
707 davinci_hw_common_param(dev, substream->stream);
708 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
709 numevt = dev->txnumevt;
710 else
711 numevt = dev->rxnumevt;
712
713 if (!numevt)
714 numevt = 1;
715
716 if (dev->op_mode == DAVINCI_MCASP_DIT_MODE)
717 davinci_hw_dit_param(dev);
718 else
719 davinci_hw_param(dev, substream->stream);
720
721 switch (params_format(params)) {
722 case SNDRV_PCM_FORMAT_S8:
723 dma_params->data_type = 1;
724 word_length = DAVINCI_AUDIO_WORD_8;
725 break;
726
727 case SNDRV_PCM_FORMAT_S16_LE:
728 dma_params->data_type = 2;
729 word_length = DAVINCI_AUDIO_WORD_16;
730 break;
731
732 case SNDRV_PCM_FORMAT_S32_LE:
733 dma_params->data_type = 4;
734 word_length = DAVINCI_AUDIO_WORD_32;
735 break;
736
737 default:
738 printk(KERN_WARNING "davinci-mcasp: unsupported PCM format");
739 return -EINVAL;
740 }
741
742 if (dev->version == MCASP_VERSION_2) {
743 dma_params->data_type *= numevt;
744 dma_params->acnt = 4 * numevt;
745 } else
746 dma_params->acnt = dma_params->data_type;
747
748 davinci_config_channel_size(dev, word_length);
749
750 return 0;
751}
752
753static int davinci_mcasp_trigger(struct snd_pcm_substream *substream,
754 int cmd, struct snd_soc_dai *cpu_dai)
755{
756 struct snd_soc_pcm_runtime *rtd = substream->private_data;
757 struct davinci_audio_dev *dev = rtd->dai->cpu_dai->private_data;
758 int ret = 0;
759
760 switch (cmd) {
761 case SNDRV_PCM_TRIGGER_START:
762 case SNDRV_PCM_TRIGGER_RESUME:
763 case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
764 davinci_mcasp_start(dev, substream->stream);
765 break;
766
767 case SNDRV_PCM_TRIGGER_STOP:
768 case SNDRV_PCM_TRIGGER_SUSPEND:
769 case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
770 davinci_mcasp_stop(dev, substream->stream);
771 break;
772
773 default:
774 ret = -EINVAL;
775 }
776
777 return ret;
778}
779
780static struct snd_soc_dai_ops davinci_mcasp_dai_ops = {
781 .startup = davinci_mcasp_startup,
782 .trigger = davinci_mcasp_trigger,
783 .hw_params = davinci_mcasp_hw_params,
784 .set_fmt = davinci_mcasp_set_dai_fmt,
785
786};
787
788struct snd_soc_dai davinci_mcasp_dai[] = {
789 {
790 .name = "davinci-i2s",
791 .id = 0,
792 .playback = {
793 .channels_min = 2,
794 .channels_max = 2,
795 .rates = DAVINCI_MCASP_RATES,
796 .formats = SNDRV_PCM_FMTBIT_S8 |
797 SNDRV_PCM_FMTBIT_S16_LE |
798 SNDRV_PCM_FMTBIT_S32_LE,
799 },
800 .capture = {
801 .channels_min = 2,
802 .channels_max = 2,
803 .rates = DAVINCI_MCASP_RATES,
804 .formats = SNDRV_PCM_FMTBIT_S8 |
805 SNDRV_PCM_FMTBIT_S16_LE |
806 SNDRV_PCM_FMTBIT_S32_LE,
807 },
808 .ops = &davinci_mcasp_dai_ops,
809
810 },
811 {
812 .name = "davinci-dit",
813 .id = 1,
814 .playback = {
815 .channels_min = 1,
816 .channels_max = 384,
817 .rates = DAVINCI_MCASP_RATES,
818 .formats = SNDRV_PCM_FMTBIT_S16_LE,
819 },
820 .ops = &davinci_mcasp_dai_ops,
821 },
822
823};
824EXPORT_SYMBOL_GPL(davinci_mcasp_dai);
825
826static int davinci_mcasp_probe(struct platform_device *pdev)
827{
828 struct davinci_pcm_dma_params *dma_data;
829 struct resource *mem, *ioarea, *res;
830 struct snd_platform_data *pdata;
831 struct davinci_audio_dev *dev;
832 int count = 0;
833 int ret = 0;
834
835 dev = kzalloc(sizeof(struct davinci_audio_dev), GFP_KERNEL);
836 if (!dev)
837 return -ENOMEM;
838
839 dma_data = kzalloc(sizeof(struct davinci_pcm_dma_params) * 2,
840 GFP_KERNEL);
841 if (!dma_data) {
842 ret = -ENOMEM;
843 goto err_release_dev;
844 }
845
846 mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
847 if (!mem) {
848 dev_err(&pdev->dev, "no mem resource?\n");
849 ret = -ENODEV;
850 goto err_release_data;
851 }
852
853 ioarea = request_mem_region(mem->start,
854 (mem->end - mem->start) + 1, pdev->name);
855 if (!ioarea) {
856 dev_err(&pdev->dev, "Audio region already claimed\n");
857 ret = -EBUSY;
858 goto err_release_data;
859 }
860
861 pdata = pdev->dev.platform_data;
862 dev->clk = clk_get(&pdev->dev, NULL);
863 if (IS_ERR(dev->clk)) {
864 ret = -ENODEV;
865 goto err_release_region;
866 }
867
868 clk_enable(dev->clk);
869
870 dev->base = (void __iomem *)IO_ADDRESS(mem->start);
871 dev->op_mode = pdata->op_mode;
872 dev->tdm_slots = pdata->tdm_slots;
873 dev->num_serializer = pdata->num_serializer;
874 dev->serial_dir = pdata->serial_dir;
875 dev->codec_fmt = pdata->codec_fmt;
876 dev->version = pdata->version;
877 dev->txnumevt = pdata->txnumevt;
878 dev->rxnumevt = pdata->rxnumevt;
879
880 dma_data[count].name = "I2S PCM Stereo out";
881 dma_data[count].eventq_no = pdata->eventq_no;
882 dma_data[count].dma_addr = (dma_addr_t) (pdata->tx_dma_offset +
883 io_v2p(dev->base));
884 dev->dma_params[SNDRV_PCM_STREAM_PLAYBACK] = &dma_data[count];
885
886 /* first TX, then RX */
887 res = platform_get_resource(pdev, IORESOURCE_DMA, 0);
888 if (!res) {
889 dev_err(&pdev->dev, "no DMA resource\n");
890 goto err_release_region;
891 }
892
893 dma_data[count].channel = res->start;
894 count++;
895 dma_data[count].name = "I2S PCM Stereo in";
896 dma_data[count].eventq_no = pdata->eventq_no;
897 dma_data[count].dma_addr = (dma_addr_t)(pdata->rx_dma_offset +
898 io_v2p(dev->base));
899 dev->dma_params[SNDRV_PCM_STREAM_CAPTURE] = &dma_data[count];
900
901 res = platform_get_resource(pdev, IORESOURCE_DMA, 1);
902 if (!res) {
903 dev_err(&pdev->dev, "no DMA resource\n");
904 goto err_release_region;
905 }
906
907 dma_data[count].channel = res->start;
908 davinci_mcasp_dai[pdata->op_mode].private_data = dev;
909 davinci_mcasp_dai[pdata->op_mode].dev = &pdev->dev;
910 ret = snd_soc_register_dai(&davinci_mcasp_dai[pdata->op_mode]);
911
912 if (ret != 0)
913 goto err_release_region;
914 return 0;
915
916err_release_region:
917 release_mem_region(mem->start, (mem->end - mem->start) + 1);
918err_release_data:
919 kfree(dma_data);
920err_release_dev:
921 kfree(dev);
922
923 return ret;
924}
925
926static int davinci_mcasp_remove(struct platform_device *pdev)
927{
928 struct snd_platform_data *pdata = pdev->dev.platform_data;
929 struct davinci_pcm_dma_params *dma_data;
930 struct davinci_audio_dev *dev;
931 struct resource *mem;
932
933 snd_soc_unregister_dai(&davinci_mcasp_dai[pdata->op_mode]);
934 dev = davinci_mcasp_dai[pdata->op_mode].private_data;
935 clk_disable(dev->clk);
936 clk_put(dev->clk);
937 dev->clk = NULL;
938
939 mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
940 release_mem_region(mem->start, (mem->end - mem->start) + 1);
941
942 dma_data = dev->dma_params[SNDRV_PCM_STREAM_PLAYBACK];
943 kfree(dma_data);
944 kfree(dev);
945
946 return 0;
947}
948
949static struct platform_driver davinci_mcasp_driver = {
950 .probe = davinci_mcasp_probe,
951 .remove = davinci_mcasp_remove,
952 .driver = {
953 .name = "davinci-mcasp",
954 .owner = THIS_MODULE,
955 },
956};
957
958static int __init davinci_mcasp_init(void)
959{
960 return platform_driver_register(&davinci_mcasp_driver);
961}
962module_init(davinci_mcasp_init);
963
964static void __exit davinci_mcasp_exit(void)
965{
966 platform_driver_unregister(&davinci_mcasp_driver);
967}
968module_exit(davinci_mcasp_exit);
969
970MODULE_AUTHOR("Steve Chen");
971MODULE_DESCRIPTION("TI DAVINCI McASP SoC Interface");
972MODULE_LICENSE("GPL");
973
diff --git a/sound/soc/davinci/davinci-mcasp.h b/sound/soc/davinci/davinci-mcasp.h
new file mode 100644
index 000000000000..554354c1cc2f
--- /dev/null
+++ b/sound/soc/davinci/davinci-mcasp.h
@@ -0,0 +1,60 @@
1/*
2 * ALSA SoC McASP Audio Layer for TI DAVINCI processor
3 *
4 * MCASP related definitions
5 *
6 * Author: Nirmal Pandey <n-pandey@ti.com>,
7 * Suresh Rajashekara <suresh.r@ti.com>
8 * Steve Chen <schen@.mvista.com>
9 *
10 * Copyright: (C) 2009 MontaVista Software, Inc., <source@mvista.com>
11 * Copyright: (C) 2009 Texas Instruments, India
12 *
13 * This program is free software; you can redistribute it and/or modify
14 * it under the terms of the GNU General Public License version 2 as
15 * published by the Free Software Foundation.
16 */
17
18#ifndef DAVINCI_MCASP_H
19#define DAVINCI_MCASP_H
20
21#include <linux/io.h>
22#include <mach/asp.h>
23#include "davinci-pcm.h"
24
25extern struct snd_soc_dai davinci_mcasp_dai[];
26
27#define DAVINCI_MCASP_RATES SNDRV_PCM_RATE_8000_96000
28#define DAVINCI_MCASP_I2S_DAI 0
29#define DAVINCI_MCASP_DIT_DAI 1
30
31enum {
32 DAVINCI_AUDIO_WORD_8 = 0,
33 DAVINCI_AUDIO_WORD_12,
34 DAVINCI_AUDIO_WORD_16,
35 DAVINCI_AUDIO_WORD_20,
36 DAVINCI_AUDIO_WORD_24,
37 DAVINCI_AUDIO_WORD_32,
38 DAVINCI_AUDIO_WORD_28, /* This is only valid for McASP */
39};
40
41struct davinci_audio_dev {
42 void __iomem *base;
43 int sample_rate;
44 struct clk *clk;
45 struct davinci_pcm_dma_params *dma_params[2];
46 unsigned int codec_fmt;
47
48 /* McASP specific data */
49 int tdm_slots;
50 u8 op_mode;
51 u8 num_serializer;
52 u8 *serial_dir;
53 u8 version;
54
55 /* McASP FIFO related */
56 u8 txnumevt;
57 u8 rxnumevt;
58};
59
60#endif /* DAVINCI_MCASP_H */
diff --git a/sound/soc/davinci/davinci-pcm.c b/sound/soc/davinci/davinci-pcm.c
index a05996588489..091dacb78b4d 100644
--- a/sound/soc/davinci/davinci-pcm.c
+++ b/sound/soc/davinci/davinci-pcm.c
@@ -67,6 +67,7 @@ static void davinci_pcm_enqueue_dma(struct snd_pcm_substream *substream)
67 dma_addr_t src, dst; 67 dma_addr_t src, dst;
68 unsigned short src_bidx, dst_bidx; 68 unsigned short src_bidx, dst_bidx;
69 unsigned int data_type; 69 unsigned int data_type;
70 unsigned short acnt;
70 unsigned int count; 71 unsigned int count;
71 72
72 period_size = snd_pcm_lib_period_bytes(substream); 73 period_size = snd_pcm_lib_period_bytes(substream);
@@ -91,11 +92,12 @@ static void davinci_pcm_enqueue_dma(struct snd_pcm_substream *substream)
91 dst_bidx = data_type; 92 dst_bidx = data_type;
92 } 93 }
93 94
95 acnt = prtd->params->acnt;
94 edma_set_src(lch, src, INCR, W8BIT); 96 edma_set_src(lch, src, INCR, W8BIT);
95 edma_set_dest(lch, dst, INCR, W8BIT); 97 edma_set_dest(lch, dst, INCR, W8BIT);
96 edma_set_src_index(lch, src_bidx, 0); 98 edma_set_src_index(lch, src_bidx, 0);
97 edma_set_dest_index(lch, dst_bidx, 0); 99 edma_set_dest_index(lch, dst_bidx, 0);
98 edma_set_transfer_params(lch, data_type, count, 1, 0, ASYNC); 100 edma_set_transfer_params(lch, acnt, count, 1, 0, ASYNC);
99 101
100 prtd->period++; 102 prtd->period++;
101 if (unlikely(prtd->period >= runtime->periods)) 103 if (unlikely(prtd->period >= runtime->periods))
@@ -206,6 +208,7 @@ static int davinci_pcm_prepare(struct snd_pcm_substream *substream)
206 /* Copy self-linked parameter RAM entry into master channel */ 208 /* Copy self-linked parameter RAM entry into master channel */
207 edma_read_slot(prtd->slave_lch, &temp); 209 edma_read_slot(prtd->slave_lch, &temp);
208 edma_write_slot(prtd->master_lch, &temp); 210 edma_write_slot(prtd->master_lch, &temp);
211 davinci_pcm_enqueue_dma(substream);
209 212
210 return 0; 213 return 0;
211} 214}
@@ -243,6 +246,11 @@ static int davinci_pcm_open(struct snd_pcm_substream *substream)
243 int ret = 0; 246 int ret = 0;
244 247
245 snd_soc_set_runtime_hwparams(substream, &davinci_pcm_hardware); 248 snd_soc_set_runtime_hwparams(substream, &davinci_pcm_hardware);
249 /* ensure that buffer size is a multiple of period size */
250 ret = snd_pcm_hw_constraint_integer(runtime,
251 SNDRV_PCM_HW_PARAM_PERIODS);
252 if (ret < 0)
253 return ret;
246 254
247 prtd = kzalloc(sizeof(struct davinci_runtime_data), GFP_KERNEL); 255 prtd = kzalloc(sizeof(struct davinci_runtime_data), GFP_KERNEL);
248 if (prtd == NULL) 256 if (prtd == NULL)
diff --git a/sound/soc/davinci/davinci-pcm.h b/sound/soc/davinci/davinci-pcm.h
index 62cb4eb07e34..63d96253c73a 100644
--- a/sound/soc/davinci/davinci-pcm.h
+++ b/sound/soc/davinci/davinci-pcm.h
@@ -12,17 +12,20 @@
12#ifndef _DAVINCI_PCM_H 12#ifndef _DAVINCI_PCM_H
13#define _DAVINCI_PCM_H 13#define _DAVINCI_PCM_H
14 14
15#include <mach/edma.h>
16#include <mach/asp.h>
17
18
15struct davinci_pcm_dma_params { 19struct davinci_pcm_dma_params {
16 char *name; /* stream identifier */ 20 char *name; /* stream identifier */
17 int channel; /* sync dma channel ID */ 21 int channel; /* sync dma channel ID */
18 dma_addr_t dma_addr; /* device physical address for DMA */ 22 unsigned short acnt;
19 unsigned int data_type; /* xfer data type */ 23 dma_addr_t dma_addr; /* device physical address for DMA */
24 enum dma_event_q eventq_no; /* event queue number */
25 unsigned char data_type; /* xfer data type */
26 unsigned char convert_mono_stereo;
20}; 27};
21 28
22struct evm_snd_platform_data {
23 int tx_dma_ch;
24 int rx_dma_ch;
25};
26 29
27extern struct snd_soc_platform davinci_soc_platform; 30extern struct snd_soc_platform davinci_soc_platform;
28 31
diff --git a/sound/soc/fsl/Kconfig b/sound/soc/fsl/Kconfig
index 9fc908283371..8cb65ccad35f 100644
--- a/sound/soc/fsl/Kconfig
+++ b/sound/soc/fsl/Kconfig
@@ -1,5 +1,8 @@
1config SND_SOC_OF_SIMPLE 1config SND_SOC_OF_SIMPLE
2 tristate 2 tristate
3
4config SND_MPC52xx_DMA
5 tristate
3 6
4# ASoC platform support for the Freescale MPC8610 SOC. This compiles drivers 7# ASoC platform support for the Freescale MPC8610 SOC. This compiles drivers
5# for the SSI and the Elo DMA controller. You will still need to select 8# for the SSI and the Elo DMA controller. You will still need to select
@@ -22,7 +25,34 @@ config SND_SOC_MPC8610_HPCD
22config SND_SOC_MPC5200_I2S 25config SND_SOC_MPC5200_I2S
23 tristate "Freescale MPC5200 PSC in I2S mode driver" 26 tristate "Freescale MPC5200 PSC in I2S mode driver"
24 depends on PPC_MPC52xx && PPC_BESTCOMM 27 depends on PPC_MPC52xx && PPC_BESTCOMM
25 select SND_SOC_OF_SIMPLE 28 select SND_MPC52xx_DMA
26 select PPC_BESTCOMM_GEN_BD 29 select PPC_BESTCOMM_GEN_BD
27 help 30 help
28 Say Y here to support the MPC5200 PSCs in I2S mode. 31 Say Y here to support the MPC5200 PSCs in I2S mode.
32
33config SND_SOC_MPC5200_AC97
34 tristate "Freescale MPC5200 PSC in AC97 mode driver"
35 depends on PPC_MPC52xx && PPC_BESTCOMM
36 select SND_SOC_AC97_BUS
37 select SND_MPC52xx_DMA
38 select PPC_BESTCOMM_GEN_BD
39 help
40 Say Y here to support the MPC5200 PSCs in AC97 mode.
41
42config SND_MPC52xx_SOC_PCM030
43 tristate "SoC AC97 Audio support for Phytec pcm030 and WM9712"
44 depends on PPC_MPC5200_SIMPLE
45 select SND_SOC_MPC5200_AC97
46 select SND_SOC_WM9712
47 help
48 Say Y if you want to add support for sound on the Phytec pcm030
49 baseboard.
50
51config SND_MPC52xx_SOC_EFIKA
52 tristate "SoC AC97 Audio support for bbplan Efika and STAC9766"
53 depends on PPC_EFIKA
54 select SND_SOC_MPC5200_AC97
55 select SND_SOC_STAC9766
56 help
57 Say Y if you want to add support for sound on the Efika.
58
diff --git a/sound/soc/fsl/Makefile b/sound/soc/fsl/Makefile
index f85134c86387..a83a73967ec6 100644
--- a/sound/soc/fsl/Makefile
+++ b/sound/soc/fsl/Makefile
@@ -10,5 +10,12 @@ snd-soc-fsl-ssi-objs := fsl_ssi.o
10snd-soc-fsl-dma-objs := fsl_dma.o 10snd-soc-fsl-dma-objs := fsl_dma.o
11obj-$(CONFIG_SND_SOC_MPC8610) += snd-soc-fsl-ssi.o snd-soc-fsl-dma.o 11obj-$(CONFIG_SND_SOC_MPC8610) += snd-soc-fsl-ssi.o snd-soc-fsl-dma.o
12 12
13# MPC5200 Platform Support
14obj-$(CONFIG_SND_MPC52xx_DMA) += mpc5200_dma.o
13obj-$(CONFIG_SND_SOC_MPC5200_I2S) += mpc5200_psc_i2s.o 15obj-$(CONFIG_SND_SOC_MPC5200_I2S) += mpc5200_psc_i2s.o
16obj-$(CONFIG_SND_SOC_MPC5200_AC97) += mpc5200_psc_ac97.o
17
18# MPC5200 Machine Support
19obj-$(CONFIG_SND_MPC52xx_SOC_PCM030) += pcm030-audio-fabric.o
20obj-$(CONFIG_SND_MPC52xx_SOC_EFIKA) += efika-audio-fabric.o
14 21
diff --git a/sound/soc/fsl/efika-audio-fabric.c b/sound/soc/fsl/efika-audio-fabric.c
new file mode 100644
index 000000000000..85b0e7569504
--- /dev/null
+++ b/sound/soc/fsl/efika-audio-fabric.c
@@ -0,0 +1,90 @@
1/*
2 * Efika driver for the PSC of the Freescale MPC52xx
3 * configured as AC97 interface
4 *
5 * Copyright 2008 Jon Smirl, Digispeaker
6 * Author: Jon Smirl <jonsmirl@gmail.com>
7 *
8 * This file is licensed under the terms of the GNU General Public License
9 * version 2. This program is licensed "as is" without any warranty of any
10 * kind, whether express or implied.
11 */
12
13#include <linux/init.h>
14#include <linux/module.h>
15#include <linux/interrupt.h>
16#include <linux/device.h>
17#include <linux/delay.h>
18#include <linux/of_device.h>
19#include <linux/of_platform.h>
20#include <linux/dma-mapping.h>
21
22#include <sound/core.h>
23#include <sound/pcm.h>
24#include <sound/pcm_params.h>
25#include <sound/initval.h>
26#include <sound/soc.h>
27#include <sound/soc-of-simple.h>
28
29#include "mpc5200_dma.h"
30#include "mpc5200_psc_ac97.h"
31#include "../codecs/stac9766.h"
32
33static struct snd_soc_device device;
34static struct snd_soc_card card;
35
36static struct snd_soc_dai_link efika_fabric_dai[] = {
37{
38 .name = "AC97",
39 .stream_name = "AC97 Analog",
40 .codec_dai = &stac9766_dai[STAC9766_DAI_AC97_ANALOG],
41 .cpu_dai = &psc_ac97_dai[MPC5200_AC97_NORMAL],
42},
43{
44 .name = "AC97",
45 .stream_name = "AC97 IEC958",
46 .codec_dai = &stac9766_dai[STAC9766_DAI_AC97_DIGITAL],
47 .cpu_dai = &psc_ac97_dai[MPC5200_AC97_SPDIF],
48},
49};
50
51static __init int efika_fabric_init(void)
52{
53 struct platform_device *pdev;
54 int rc;
55
56 if (!machine_is_compatible("bplan,efika"))
57 return -ENODEV;
58
59 card.platform = &mpc5200_audio_dma_platform;
60 card.name = "Efika";
61 card.dai_link = efika_fabric_dai;
62 card.num_links = ARRAY_SIZE(efika_fabric_dai);
63
64 device.card = &card;
65 device.codec_dev = &soc_codec_dev_stac9766;
66
67 pdev = platform_device_alloc("soc-audio", 1);
68 if (!pdev) {
69 pr_err("efika_fabric_init: platform_device_alloc() failed\n");
70 return -ENODEV;
71 }
72
73 platform_set_drvdata(pdev, &device);
74 device.dev = &pdev->dev;
75
76 rc = platform_device_add(pdev);
77 if (rc) {
78 pr_err("efika_fabric_init: platform_device_add() failed\n");
79 return -ENODEV;
80 }
81 return 0;
82}
83
84module_init(efika_fabric_init);
85
86
87MODULE_AUTHOR("Jon Smirl <jonsmirl@gmail.com>");
88MODULE_DESCRIPTION(DRV_NAME ": mpc5200 Efika fabric driver");
89MODULE_LICENSE("GPL");
90
diff --git a/sound/soc/fsl/fsl_ssi.c b/sound/soc/fsl/fsl_ssi.c
index 3711d8454d96..93f0f38a32c9 100644
--- a/sound/soc/fsl/fsl_ssi.c
+++ b/sound/soc/fsl/fsl_ssi.c
@@ -375,18 +375,14 @@ static int fsl_ssi_startup(struct snd_pcm_substream *substream,
375 struct snd_pcm_runtime *first_runtime = 375 struct snd_pcm_runtime *first_runtime =
376 ssi_private->first_stream->runtime; 376 ssi_private->first_stream->runtime;
377 377
378 if (!first_runtime->rate || !first_runtime->sample_bits) { 378 if (!first_runtime->sample_bits) {
379 dev_err(substream->pcm->card->dev, 379 dev_err(substream->pcm->card->dev,
380 "set sample rate and size in %s stream first\n", 380 "set sample size in %s stream first\n",
381 substream->stream == SNDRV_PCM_STREAM_PLAYBACK 381 substream->stream == SNDRV_PCM_STREAM_PLAYBACK
382 ? "capture" : "playback"); 382 ? "capture" : "playback");
383 return -EAGAIN; 383 return -EAGAIN;
384 } 384 }
385 385
386 snd_pcm_hw_constraint_minmax(substream->runtime,
387 SNDRV_PCM_HW_PARAM_RATE,
388 first_runtime->rate, first_runtime->rate);
389
390 /* If we're in synchronous mode, then we need to constrain 386 /* If we're in synchronous mode, then we need to constrain
391 * the sample size as well. We don't support independent sample 387 * the sample size as well. We don't support independent sample
392 * rates in asynchronous mode. 388 * rates in asynchronous mode.
@@ -674,7 +670,7 @@ struct snd_soc_dai *fsl_ssi_create_dai(struct fsl_ssi_info *ssi_info)
674 ssi_private->dev = ssi_info->dev; 670 ssi_private->dev = ssi_info->dev;
675 ssi_private->asynchronous = ssi_info->asynchronous; 671 ssi_private->asynchronous = ssi_info->asynchronous;
676 672
677 ssi_private->dev->driver_data = fsl_ssi_dai; 673 dev_set_drvdata(ssi_private->dev, fsl_ssi_dai);
678 674
679 /* Initialize the the device_attribute structure */ 675 /* Initialize the the device_attribute structure */
680 dev_attr->attr.name = "ssi-stats"; 676 dev_attr->attr.name = "ssi-stats";
@@ -693,6 +689,7 @@ struct snd_soc_dai *fsl_ssi_create_dai(struct fsl_ssi_info *ssi_info)
693 fsl_ssi_dai->name = ssi_private->name; 689 fsl_ssi_dai->name = ssi_private->name;
694 fsl_ssi_dai->id = ssi_info->id; 690 fsl_ssi_dai->id = ssi_info->id;
695 fsl_ssi_dai->dev = ssi_info->dev; 691 fsl_ssi_dai->dev = ssi_info->dev;
692 fsl_ssi_dai->symmetric_rates = 1;
696 693
697 ret = snd_soc_register_dai(fsl_ssi_dai); 694 ret = snd_soc_register_dai(fsl_ssi_dai);
698 if (ret != 0) { 695 if (ret != 0) {
diff --git a/sound/soc/fsl/mpc5200_dma.c b/sound/soc/fsl/mpc5200_dma.c
new file mode 100644
index 000000000000..9ff62e3a9b1d
--- /dev/null
+++ b/sound/soc/fsl/mpc5200_dma.c
@@ -0,0 +1,582 @@
1/*
2 * Freescale MPC5200 PSC DMA
3 * ALSA SoC Platform driver
4 *
5 * Copyright (C) 2008 Secret Lab Technologies Ltd.
6 * Copyright (C) 2009 Jon Smirl, Digispeaker
7 */
8
9#include <linux/module.h>
10#include <linux/of_device.h>
11
12#include <sound/soc.h>
13
14#include <sysdev/bestcomm/bestcomm.h>
15#include <sysdev/bestcomm/gen_bd.h>
16#include <asm/mpc52xx_psc.h>
17
18#include "mpc5200_dma.h"
19
20/*
21 * Interrupt handlers
22 */
23static irqreturn_t psc_dma_status_irq(int irq, void *_psc_dma)
24{
25 struct psc_dma *psc_dma = _psc_dma;
26 struct mpc52xx_psc __iomem *regs = psc_dma->psc_regs;
27 u16 isr;
28
29 isr = in_be16(&regs->mpc52xx_psc_isr);
30
31 /* Playback underrun error */
32 if (psc_dma->playback.active && (isr & MPC52xx_PSC_IMR_TXEMP))
33 psc_dma->stats.underrun_count++;
34
35 /* Capture overrun error */
36 if (psc_dma->capture.active && (isr & MPC52xx_PSC_IMR_ORERR))
37 psc_dma->stats.overrun_count++;
38
39 out_8(&regs->command, MPC52xx_PSC_RST_ERR_STAT);
40
41 return IRQ_HANDLED;
42}
43
44/**
45 * psc_dma_bcom_enqueue_next_buffer - Enqueue another audio buffer
46 * @s: pointer to stream private data structure
47 *
48 * Enqueues another audio period buffer into the bestcomm queue.
49 *
50 * Note: The routine must only be called when there is space available in
51 * the queue. Otherwise the enqueue will fail and the audio ring buffer
52 * will get out of sync
53 */
54static void psc_dma_bcom_enqueue_next_buffer(struct psc_dma_stream *s)
55{
56 struct bcom_bd *bd;
57
58 /* Prepare and enqueue the next buffer descriptor */
59 bd = bcom_prepare_next_buffer(s->bcom_task);
60 bd->status = s->period_bytes;
61 bd->data[0] = s->period_next_pt;
62 bcom_submit_next_buffer(s->bcom_task, NULL);
63
64 /* Update for next period */
65 s->period_next_pt += s->period_bytes;
66 if (s->period_next_pt >= s->period_end)
67 s->period_next_pt = s->period_start;
68}
69
70static void psc_dma_bcom_enqueue_tx(struct psc_dma_stream *s)
71{
72 if (s->appl_ptr > s->runtime->control->appl_ptr) {
73 /*
74 * In this case s->runtime->control->appl_ptr has wrapped around.
75 * Play the data to the end of the boundary, then wrap our own
76 * appl_ptr back around.
77 */
78 while (s->appl_ptr < s->runtime->boundary) {
79 if (bcom_queue_full(s->bcom_task))
80 return;
81
82 s->appl_ptr += s->period_size;
83
84 psc_dma_bcom_enqueue_next_buffer(s);
85 }
86 s->appl_ptr -= s->runtime->boundary;
87 }
88
89 while (s->appl_ptr < s->runtime->control->appl_ptr) {
90
91 if (bcom_queue_full(s->bcom_task))
92 return;
93
94 s->appl_ptr += s->period_size;
95
96 psc_dma_bcom_enqueue_next_buffer(s);
97 }
98}
99
100/* Bestcomm DMA irq handler */
101static irqreturn_t psc_dma_bcom_irq_tx(int irq, void *_psc_dma_stream)
102{
103 struct psc_dma_stream *s = _psc_dma_stream;
104
105 spin_lock(&s->psc_dma->lock);
106 /* For each finished period, dequeue the completed period buffer
107 * and enqueue a new one in it's place. */
108 while (bcom_buffer_done(s->bcom_task)) {
109 bcom_retrieve_buffer(s->bcom_task, NULL, NULL);
110
111 s->period_current_pt += s->period_bytes;
112 if (s->period_current_pt >= s->period_end)
113 s->period_current_pt = s->period_start;
114 }
115 psc_dma_bcom_enqueue_tx(s);
116 spin_unlock(&s->psc_dma->lock);
117
118 /* If the stream is active, then also inform the PCM middle layer
119 * of the period finished event. */
120 if (s->active)
121 snd_pcm_period_elapsed(s->stream);
122
123 return IRQ_HANDLED;
124}
125
126static irqreturn_t psc_dma_bcom_irq_rx(int irq, void *_psc_dma_stream)
127{
128 struct psc_dma_stream *s = _psc_dma_stream;
129
130 spin_lock(&s->psc_dma->lock);
131 /* For each finished period, dequeue the completed period buffer
132 * and enqueue a new one in it's place. */
133 while (bcom_buffer_done(s->bcom_task)) {
134 bcom_retrieve_buffer(s->bcom_task, NULL, NULL);
135
136 s->period_current_pt += s->period_bytes;
137 if (s->period_current_pt >= s->period_end)
138 s->period_current_pt = s->period_start;
139
140 psc_dma_bcom_enqueue_next_buffer(s);
141 }
142 spin_unlock(&s->psc_dma->lock);
143
144 /* If the stream is active, then also inform the PCM middle layer
145 * of the period finished event. */
146 if (s->active)
147 snd_pcm_period_elapsed(s->stream);
148
149 return IRQ_HANDLED;
150}
151
152static int psc_dma_hw_free(struct snd_pcm_substream *substream)
153{
154 snd_pcm_set_runtime_buffer(substream, NULL);
155 return 0;
156}
157
158/**
159 * psc_dma_trigger: start and stop the DMA transfer.
160 *
161 * This function is called by ALSA to start, stop, pause, and resume the DMA
162 * transfer of data.
163 */
164static int psc_dma_trigger(struct snd_pcm_substream *substream, int cmd)
165{
166 struct snd_soc_pcm_runtime *rtd = substream->private_data;
167 struct psc_dma *psc_dma = rtd->dai->cpu_dai->private_data;
168 struct snd_pcm_runtime *runtime = substream->runtime;
169 struct psc_dma_stream *s;
170 struct mpc52xx_psc __iomem *regs = psc_dma->psc_regs;
171 u16 imr;
172 unsigned long flags;
173 int i;
174
175 if (substream->pstr->stream == SNDRV_PCM_STREAM_CAPTURE)
176 s = &psc_dma->capture;
177 else
178 s = &psc_dma->playback;
179
180 dev_dbg(psc_dma->dev, "psc_dma_trigger(substream=%p, cmd=%i)"
181 " stream_id=%i\n",
182 substream, cmd, substream->pstr->stream);
183
184 switch (cmd) {
185 case SNDRV_PCM_TRIGGER_START:
186 s->period_bytes = frames_to_bytes(runtime,
187 runtime->period_size);
188 s->period_start = virt_to_phys(runtime->dma_area);
189 s->period_end = s->period_start +
190 (s->period_bytes * runtime->periods);
191 s->period_next_pt = s->period_start;
192 s->period_current_pt = s->period_start;
193 s->period_size = runtime->period_size;
194 s->active = 1;
195
196 /* track appl_ptr so that we have a better chance of detecting
197 * end of stream and not over running it.
198 */
199 s->runtime = runtime;
200 s->appl_ptr = s->runtime->control->appl_ptr -
201 (runtime->period_size * runtime->periods);
202
203 /* Fill up the bestcomm bd queue and enable DMA.
204 * This will begin filling the PSC's fifo.
205 */
206 spin_lock_irqsave(&psc_dma->lock, flags);
207
208 if (substream->pstr->stream == SNDRV_PCM_STREAM_CAPTURE) {
209 bcom_gen_bd_rx_reset(s->bcom_task);
210 for (i = 0; i < runtime->periods; i++)
211 if (!bcom_queue_full(s->bcom_task))
212 psc_dma_bcom_enqueue_next_buffer(s);
213 } else {
214 bcom_gen_bd_tx_reset(s->bcom_task);
215 psc_dma_bcom_enqueue_tx(s);
216 }
217
218 bcom_enable(s->bcom_task);
219 spin_unlock_irqrestore(&psc_dma->lock, flags);
220
221 out_8(&regs->command, MPC52xx_PSC_RST_ERR_STAT);
222
223 break;
224
225 case SNDRV_PCM_TRIGGER_STOP:
226 s->active = 0;
227
228 spin_lock_irqsave(&psc_dma->lock, flags);
229 bcom_disable(s->bcom_task);
230 if (substream->pstr->stream == SNDRV_PCM_STREAM_CAPTURE)
231 bcom_gen_bd_rx_reset(s->bcom_task);
232 else
233 bcom_gen_bd_tx_reset(s->bcom_task);
234 spin_unlock_irqrestore(&psc_dma->lock, flags);
235
236 break;
237
238 default:
239 dev_dbg(psc_dma->dev, "invalid command\n");
240 return -EINVAL;
241 }
242
243 /* Update interrupt enable settings */
244 imr = 0;
245 if (psc_dma->playback.active)
246 imr |= MPC52xx_PSC_IMR_TXEMP;
247 if (psc_dma->capture.active)
248 imr |= MPC52xx_PSC_IMR_ORERR;
249 out_be16(&regs->isr_imr.imr, psc_dma->imr | imr);
250
251 return 0;
252}
253
254
255/* ---------------------------------------------------------------------
256 * The PSC DMA 'ASoC platform' driver
257 *
258 * Can be referenced by an 'ASoC machine' driver
259 * This driver only deals with the audio bus; it doesn't have any
260 * interaction with the attached codec
261 */
262
263static const struct snd_pcm_hardware psc_dma_hardware = {
264 .info = SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_MMAP_VALID |
265 SNDRV_PCM_INFO_INTERLEAVED | SNDRV_PCM_INFO_BLOCK_TRANSFER |
266 SNDRV_PCM_INFO_BATCH,
267 .formats = SNDRV_PCM_FMTBIT_S8 | SNDRV_PCM_FMTBIT_S16_BE |
268 SNDRV_PCM_FMTBIT_S24_BE | SNDRV_PCM_FMTBIT_S32_BE,
269 .rate_min = 8000,
270 .rate_max = 48000,
271 .channels_min = 1,
272 .channels_max = 2,
273 .period_bytes_max = 1024 * 1024,
274 .period_bytes_min = 32,
275 .periods_min = 2,
276 .periods_max = 256,
277 .buffer_bytes_max = 2 * 1024 * 1024,
278 .fifo_size = 512,
279};
280
281static int psc_dma_open(struct snd_pcm_substream *substream)
282{
283 struct snd_pcm_runtime *runtime = substream->runtime;
284 struct snd_soc_pcm_runtime *rtd = substream->private_data;
285 struct psc_dma *psc_dma = rtd->dai->cpu_dai->private_data;
286 struct psc_dma_stream *s;
287 int rc;
288
289 dev_dbg(psc_dma->dev, "psc_dma_open(substream=%p)\n", substream);
290
291 if (substream->pstr->stream == SNDRV_PCM_STREAM_CAPTURE)
292 s = &psc_dma->capture;
293 else
294 s = &psc_dma->playback;
295
296 snd_soc_set_runtime_hwparams(substream, &psc_dma_hardware);
297
298 rc = snd_pcm_hw_constraint_integer(runtime,
299 SNDRV_PCM_HW_PARAM_PERIODS);
300 if (rc < 0) {
301 dev_err(substream->pcm->card->dev, "invalid buffer size\n");
302 return rc;
303 }
304
305 s->stream = substream;
306 return 0;
307}
308
309static int psc_dma_close(struct snd_pcm_substream *substream)
310{
311 struct snd_soc_pcm_runtime *rtd = substream->private_data;
312 struct psc_dma *psc_dma = rtd->dai->cpu_dai->private_data;
313 struct psc_dma_stream *s;
314
315 dev_dbg(psc_dma->dev, "psc_dma_close(substream=%p)\n", substream);
316
317 if (substream->pstr->stream == SNDRV_PCM_STREAM_CAPTURE)
318 s = &psc_dma->capture;
319 else
320 s = &psc_dma->playback;
321
322 if (!psc_dma->playback.active &&
323 !psc_dma->capture.active) {
324
325 /* Disable all interrupts and reset the PSC */
326 out_be16(&psc_dma->psc_regs->isr_imr.imr, psc_dma->imr);
327 out_8(&psc_dma->psc_regs->command, 4 << 4); /* reset error */
328 }
329 s->stream = NULL;
330 return 0;
331}
332
333static snd_pcm_uframes_t
334psc_dma_pointer(struct snd_pcm_substream *substream)
335{
336 struct snd_soc_pcm_runtime *rtd = substream->private_data;
337 struct psc_dma *psc_dma = rtd->dai->cpu_dai->private_data;
338 struct psc_dma_stream *s;
339 dma_addr_t count;
340
341 if (substream->pstr->stream == SNDRV_PCM_STREAM_CAPTURE)
342 s = &psc_dma->capture;
343 else
344 s = &psc_dma->playback;
345
346 count = s->period_current_pt - s->period_start;
347
348 return bytes_to_frames(substream->runtime, count);
349}
350
351static int
352psc_dma_hw_params(struct snd_pcm_substream *substream,
353 struct snd_pcm_hw_params *params)
354{
355 snd_pcm_set_runtime_buffer(substream, &substream->dma_buffer);
356
357 return 0;
358}
359
360static struct snd_pcm_ops psc_dma_ops = {
361 .open = psc_dma_open,
362 .close = psc_dma_close,
363 .hw_free = psc_dma_hw_free,
364 .ioctl = snd_pcm_lib_ioctl,
365 .pointer = psc_dma_pointer,
366 .trigger = psc_dma_trigger,
367 .hw_params = psc_dma_hw_params,
368};
369
370static u64 psc_dma_dmamask = 0xffffffff;
371static int psc_dma_new(struct snd_card *card, struct snd_soc_dai *dai,
372 struct snd_pcm *pcm)
373{
374 struct snd_soc_pcm_runtime *rtd = pcm->private_data;
375 struct psc_dma *psc_dma = rtd->dai->cpu_dai->private_data;
376 size_t size = psc_dma_hardware.buffer_bytes_max;
377 int rc = 0;
378
379 dev_dbg(rtd->socdev->dev, "psc_dma_new(card=%p, dai=%p, pcm=%p)\n",
380 card, dai, pcm);
381
382 if (!card->dev->dma_mask)
383 card->dev->dma_mask = &psc_dma_dmamask;
384 if (!card->dev->coherent_dma_mask)
385 card->dev->coherent_dma_mask = 0xffffffff;
386
387 if (pcm->streams[0].substream) {
388 rc = snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, pcm->card->dev,
389 size, &pcm->streams[0].substream->dma_buffer);
390 if (rc)
391 goto playback_alloc_err;
392 }
393
394 if (pcm->streams[1].substream) {
395 rc = snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, pcm->card->dev,
396 size, &pcm->streams[1].substream->dma_buffer);
397 if (rc)
398 goto capture_alloc_err;
399 }
400
401 if (rtd->socdev->card->codec->ac97)
402 rtd->socdev->card->codec->ac97->private_data = psc_dma;
403
404 return 0;
405
406 capture_alloc_err:
407 if (pcm->streams[0].substream)
408 snd_dma_free_pages(&pcm->streams[0].substream->dma_buffer);
409
410 playback_alloc_err:
411 dev_err(card->dev, "Cannot allocate buffer(s)\n");
412
413 return -ENOMEM;
414}
415
416static void psc_dma_free(struct snd_pcm *pcm)
417{
418 struct snd_soc_pcm_runtime *rtd = pcm->private_data;
419 struct snd_pcm_substream *substream;
420 int stream;
421
422 dev_dbg(rtd->socdev->dev, "psc_dma_free(pcm=%p)\n", pcm);
423
424 for (stream = 0; stream < 2; stream++) {
425 substream = pcm->streams[stream].substream;
426 if (substream) {
427 snd_dma_free_pages(&substream->dma_buffer);
428 substream->dma_buffer.area = NULL;
429 substream->dma_buffer.addr = 0;
430 }
431 }
432}
433
434struct snd_soc_platform mpc5200_audio_dma_platform = {
435 .name = "mpc5200-psc-audio",
436 .pcm_ops = &psc_dma_ops,
437 .pcm_new = &psc_dma_new,
438 .pcm_free = &psc_dma_free,
439};
440EXPORT_SYMBOL_GPL(mpc5200_audio_dma_platform);
441
442int mpc5200_audio_dma_create(struct of_device *op)
443{
444 phys_addr_t fifo;
445 struct psc_dma *psc_dma;
446 struct resource res;
447 int size, irq, rc;
448 const __be32 *prop;
449 void __iomem *regs;
450
451 /* Fetch the registers and IRQ of the PSC */
452 irq = irq_of_parse_and_map(op->node, 0);
453 if (of_address_to_resource(op->node, 0, &res)) {
454 dev_err(&op->dev, "Missing reg property\n");
455 return -ENODEV;
456 }
457 regs = ioremap(res.start, 1 + res.end - res.start);
458 if (!regs) {
459 dev_err(&op->dev, "Could not map registers\n");
460 return -ENODEV;
461 }
462
463 /* Allocate and initialize the driver private data */
464 psc_dma = kzalloc(sizeof *psc_dma, GFP_KERNEL);
465 if (!psc_dma) {
466 iounmap(regs);
467 return -ENOMEM;
468 }
469
470 /* Get the PSC ID */
471 prop = of_get_property(op->node, "cell-index", &size);
472 if (!prop || size < sizeof *prop)
473 return -ENODEV;
474
475 spin_lock_init(&psc_dma->lock);
476 mutex_init(&psc_dma->mutex);
477 psc_dma->id = be32_to_cpu(*prop);
478 psc_dma->irq = irq;
479 psc_dma->psc_regs = regs;
480 psc_dma->fifo_regs = regs + sizeof *psc_dma->psc_regs;
481 psc_dma->dev = &op->dev;
482 psc_dma->playback.psc_dma = psc_dma;
483 psc_dma->capture.psc_dma = psc_dma;
484 snprintf(psc_dma->name, sizeof psc_dma->name, "PSC%u", psc_dma->id);
485
486 /* Find the address of the fifo data registers and setup the
487 * DMA tasks */
488 fifo = res.start + offsetof(struct mpc52xx_psc, buffer.buffer_32);
489 psc_dma->capture.bcom_task =
490 bcom_psc_gen_bd_rx_init(psc_dma->id, 10, fifo, 512);
491 psc_dma->playback.bcom_task =
492 bcom_psc_gen_bd_tx_init(psc_dma->id, 10, fifo);
493 if (!psc_dma->capture.bcom_task ||
494 !psc_dma->playback.bcom_task) {
495 dev_err(&op->dev, "Could not allocate bestcomm tasks\n");
496 iounmap(regs);
497 kfree(psc_dma);
498 return -ENODEV;
499 }
500
501 /* Disable all interrupts and reset the PSC */
502 out_be16(&psc_dma->psc_regs->isr_imr.imr, psc_dma->imr);
503 /* reset receiver */
504 out_8(&psc_dma->psc_regs->command, MPC52xx_PSC_RST_RX);
505 /* reset transmitter */
506 out_8(&psc_dma->psc_regs->command, MPC52xx_PSC_RST_TX);
507 /* reset error */
508 out_8(&psc_dma->psc_regs->command, MPC52xx_PSC_RST_ERR_STAT);
509 /* reset mode */
510 out_8(&psc_dma->psc_regs->command, MPC52xx_PSC_SEL_MODE_REG_1);
511
512 /* Set up mode register;
513 * First write: RxRdy (FIFO Alarm) generates rx FIFO irq
514 * Second write: register Normal mode for non loopback
515 */
516 out_8(&psc_dma->psc_regs->mode, 0);
517 out_8(&psc_dma->psc_regs->mode, 0);
518
519 /* Set the TX and RX fifo alarm thresholds */
520 out_be16(&psc_dma->fifo_regs->rfalarm, 0x100);
521 out_8(&psc_dma->fifo_regs->rfcntl, 0x4);
522 out_be16(&psc_dma->fifo_regs->tfalarm, 0x100);
523 out_8(&psc_dma->fifo_regs->tfcntl, 0x7);
524
525 /* Lookup the IRQ numbers */
526 psc_dma->playback.irq =
527 bcom_get_task_irq(psc_dma->playback.bcom_task);
528 psc_dma->capture.irq =
529 bcom_get_task_irq(psc_dma->capture.bcom_task);
530
531 rc = request_irq(psc_dma->irq, &psc_dma_status_irq, IRQF_SHARED,
532 "psc-dma-status", psc_dma);
533 rc |= request_irq(psc_dma->capture.irq,
534 &psc_dma_bcom_irq_rx, IRQF_SHARED,
535 "psc-dma-capture", &psc_dma->capture);
536 rc |= request_irq(psc_dma->playback.irq,
537 &psc_dma_bcom_irq_tx, IRQF_SHARED,
538 "psc-dma-playback", &psc_dma->playback);
539 if (rc) {
540 free_irq(psc_dma->irq, psc_dma);
541 free_irq(psc_dma->capture.irq,
542 &psc_dma->capture);
543 free_irq(psc_dma->playback.irq,
544 &psc_dma->playback);
545 return -ENODEV;
546 }
547
548 /* Save what we've done so it can be found again later */
549 dev_set_drvdata(&op->dev, psc_dma);
550
551 /* Tell the ASoC OF helpers about it */
552 return snd_soc_register_platform(&mpc5200_audio_dma_platform);
553}
554EXPORT_SYMBOL_GPL(mpc5200_audio_dma_create);
555
556int mpc5200_audio_dma_destroy(struct of_device *op)
557{
558 struct psc_dma *psc_dma = dev_get_drvdata(&op->dev);
559
560 dev_dbg(&op->dev, "mpc5200_audio_dma_destroy()\n");
561
562 snd_soc_unregister_platform(&mpc5200_audio_dma_platform);
563
564 bcom_gen_bd_rx_release(psc_dma->capture.bcom_task);
565 bcom_gen_bd_tx_release(psc_dma->playback.bcom_task);
566
567 /* Release irqs */
568 free_irq(psc_dma->irq, psc_dma);
569 free_irq(psc_dma->capture.irq, &psc_dma->capture);
570 free_irq(psc_dma->playback.irq, &psc_dma->playback);
571
572 iounmap(psc_dma->psc_regs);
573 kfree(psc_dma);
574 dev_set_drvdata(&op->dev, NULL);
575
576 return 0;
577}
578EXPORT_SYMBOL_GPL(mpc5200_audio_dma_destroy);
579
580MODULE_AUTHOR("Grant Likely <grant.likely@secretlab.ca>");
581MODULE_DESCRIPTION("Freescale MPC5200 PSC in DMA mode ASoC Driver");
582MODULE_LICENSE("GPL");
diff --git a/sound/soc/fsl/mpc5200_dma.h b/sound/soc/fsl/mpc5200_dma.h
new file mode 100644
index 000000000000..8d396bb9d9fe
--- /dev/null
+++ b/sound/soc/fsl/mpc5200_dma.h
@@ -0,0 +1,81 @@
1/*
2 * Freescale MPC5200 Audio DMA driver
3 */
4
5#ifndef __SOUND_SOC_FSL_MPC5200_DMA_H__
6#define __SOUND_SOC_FSL_MPC5200_DMA_H__
7
8#define PSC_STREAM_NAME_LEN 32
9
10/**
11 * psc_ac97_stream - Data specific to a single stream (playback or capture)
12 * @active: flag indicating if the stream is active
13 * @psc_dma: pointer back to parent psc_dma data structure
14 * @bcom_task: bestcomm task structure
15 * @irq: irq number for bestcomm task
16 * @period_start: physical address of start of DMA region
17 * @period_end: physical address of end of DMA region
18 * @period_next_pt: physical address of next DMA buffer to enqueue
19 * @period_bytes: size of DMA period in bytes
20 */
21struct psc_dma_stream {
22 struct snd_pcm_runtime *runtime;
23 snd_pcm_uframes_t appl_ptr;
24
25 int active;
26 struct psc_dma *psc_dma;
27 struct bcom_task *bcom_task;
28 int irq;
29 struct snd_pcm_substream *stream;
30 dma_addr_t period_start;
31 dma_addr_t period_end;
32 dma_addr_t period_next_pt;
33 dma_addr_t period_current_pt;
34 int period_bytes;
35 int period_size;
36};
37
38/**
39 * psc_dma - Private driver data
40 * @name: short name for this device ("PSC0", "PSC1", etc)
41 * @psc_regs: pointer to the PSC's registers
42 * @fifo_regs: pointer to the PSC's FIFO registers
43 * @irq: IRQ of this PSC
44 * @dev: struct device pointer
45 * @dai: the CPU DAI for this device
46 * @sicr: Base value used in serial interface control register; mode is ORed
47 * with this value.
48 * @playback: Playback stream context data
49 * @capture: Capture stream context data
50 */
51struct psc_dma {
52 char name[32];
53 struct mpc52xx_psc __iomem *psc_regs;
54 struct mpc52xx_psc_fifo __iomem *fifo_regs;
55 unsigned int irq;
56 struct device *dev;
57 spinlock_t lock;
58 struct mutex mutex;
59 u32 sicr;
60 uint sysclk;
61 int imr;
62 int id;
63 unsigned int slots;
64
65 /* per-stream data */
66 struct psc_dma_stream playback;
67 struct psc_dma_stream capture;
68
69 /* Statistics */
70 struct {
71 unsigned long overrun_count;
72 unsigned long underrun_count;
73 } stats;
74};
75
76int mpc5200_audio_dma_create(struct of_device *op);
77int mpc5200_audio_dma_destroy(struct of_device *op);
78
79extern struct snd_soc_platform mpc5200_audio_dma_platform;
80
81#endif /* __SOUND_SOC_FSL_MPC5200_DMA_H__ */
diff --git a/sound/soc/fsl/mpc5200_psc_ac97.c b/sound/soc/fsl/mpc5200_psc_ac97.c
new file mode 100644
index 000000000000..c4ae3e096bb9
--- /dev/null
+++ b/sound/soc/fsl/mpc5200_psc_ac97.c
@@ -0,0 +1,345 @@
1/*
2 * linux/sound/mpc5200-ac97.c -- AC97 support for the Freescale MPC52xx chip.
3 *
4 * Copyright (C) 2009 Jon Smirl, Digispeaker
5 * Author: Jon Smirl <jonsmirl@gmail.com>
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License version 2 as
9 * published by the Free Software Foundation.
10 */
11
12#include <linux/module.h>
13#include <linux/of_device.h>
14#include <linux/of_platform.h>
15#include <linux/delay.h>
16
17#include <sound/pcm.h>
18#include <sound/pcm_params.h>
19#include <sound/soc.h>
20
21#include <asm/time.h>
22#include <asm/delay.h>
23#include <asm/mpc52xx_psc.h>
24
25#include "mpc5200_dma.h"
26#include "mpc5200_psc_ac97.h"
27
28#define DRV_NAME "mpc5200-psc-ac97"
29
30/* ALSA only supports a single AC97 device so static is recommend here */
31static struct psc_dma *psc_dma;
32
33static unsigned short psc_ac97_read(struct snd_ac97 *ac97, unsigned short reg)
34{
35 int status;
36 unsigned int val;
37
38 mutex_lock(&psc_dma->mutex);
39
40 /* Wait for command send status zero = ready */
41 status = spin_event_timeout(!(in_be16(&psc_dma->psc_regs->sr_csr.status) &
42 MPC52xx_PSC_SR_CMDSEND), 100, 0);
43 if (status == 0) {
44 pr_err("timeout on ac97 bus (rdy)\n");
45 mutex_unlock(&psc_dma->mutex);
46 return -ENODEV;
47 }
48
49 /* Force clear the data valid bit */
50 in_be32(&psc_dma->psc_regs->ac97_data);
51
52 /* Send the read */
53 out_be32(&psc_dma->psc_regs->ac97_cmd, (1<<31) | ((reg & 0x7f) << 24));
54
55 /* Wait for the answer */
56 status = spin_event_timeout((in_be16(&psc_dma->psc_regs->sr_csr.status) &
57 MPC52xx_PSC_SR_DATA_VAL), 100, 0);
58 if (status == 0) {
59 pr_err("timeout on ac97 read (val) %x\n",
60 in_be16(&psc_dma->psc_regs->sr_csr.status));
61 mutex_unlock(&psc_dma->mutex);
62 return -ENODEV;
63 }
64 /* Get the data */
65 val = in_be32(&psc_dma->psc_regs->ac97_data);
66 if (((val >> 24) & 0x7f) != reg) {
67 pr_err("reg echo error on ac97 read\n");
68 mutex_unlock(&psc_dma->mutex);
69 return -ENODEV;
70 }
71 val = (val >> 8) & 0xffff;
72
73 mutex_unlock(&psc_dma->mutex);
74 return (unsigned short) val;
75}
76
77static void psc_ac97_write(struct snd_ac97 *ac97,
78 unsigned short reg, unsigned short val)
79{
80 int status;
81
82 mutex_lock(&psc_dma->mutex);
83
84 /* Wait for command status zero = ready */
85 status = spin_event_timeout(!(in_be16(&psc_dma->psc_regs->sr_csr.status) &
86 MPC52xx_PSC_SR_CMDSEND), 100, 0);
87 if (status == 0) {
88 pr_err("timeout on ac97 bus (write)\n");
89 goto out;
90 }
91 /* Write data */
92 out_be32(&psc_dma->psc_regs->ac97_cmd,
93 ((reg & 0x7f) << 24) | (val << 8));
94
95 out:
96 mutex_unlock(&psc_dma->mutex);
97}
98
99static void psc_ac97_warm_reset(struct snd_ac97 *ac97)
100{
101 struct mpc52xx_psc __iomem *regs = psc_dma->psc_regs;
102
103 out_be32(&regs->sicr, psc_dma->sicr | MPC52xx_PSC_SICR_AWR);
104 udelay(3);
105 out_be32(&regs->sicr, psc_dma->sicr);
106}
107
108static void psc_ac97_cold_reset(struct snd_ac97 *ac97)
109{
110 struct mpc52xx_psc __iomem *regs = psc_dma->psc_regs;
111
112 /* Do a cold reset */
113 out_8(&regs->op1, MPC52xx_PSC_OP_RES);
114 udelay(10);
115 out_8(&regs->op0, MPC52xx_PSC_OP_RES);
116 msleep(1);
117 psc_ac97_warm_reset(ac97);
118}
119
120struct snd_ac97_bus_ops soc_ac97_ops = {
121 .read = psc_ac97_read,
122 .write = psc_ac97_write,
123 .reset = psc_ac97_cold_reset,
124 .warm_reset = psc_ac97_warm_reset,
125};
126EXPORT_SYMBOL_GPL(soc_ac97_ops);
127
128static int psc_ac97_hw_analog_params(struct snd_pcm_substream *substream,
129 struct snd_pcm_hw_params *params,
130 struct snd_soc_dai *cpu_dai)
131{
132 struct psc_dma *psc_dma = cpu_dai->private_data;
133
134 dev_dbg(psc_dma->dev, "%s(substream=%p) p_size=%i p_bytes=%i"
135 " periods=%i buffer_size=%i buffer_bytes=%i channels=%i"
136 " rate=%i format=%i\n",
137 __func__, substream, params_period_size(params),
138 params_period_bytes(params), params_periods(params),
139 params_buffer_size(params), params_buffer_bytes(params),
140 params_channels(params), params_rate(params),
141 params_format(params));
142
143
144 if (substream->pstr->stream == SNDRV_PCM_STREAM_CAPTURE) {
145 if (params_channels(params) == 1)
146 psc_dma->slots |= 0x00000100;
147 else
148 psc_dma->slots |= 0x00000300;
149 } else {
150 if (params_channels(params) == 1)
151 psc_dma->slots |= 0x01000000;
152 else
153 psc_dma->slots |= 0x03000000;
154 }
155 out_be32(&psc_dma->psc_regs->ac97_slots, psc_dma->slots);
156
157 return 0;
158}
159
160static int psc_ac97_hw_digital_params(struct snd_pcm_substream *substream,
161 struct snd_pcm_hw_params *params,
162 struct snd_soc_dai *cpu_dai)
163{
164 struct psc_dma *psc_dma = cpu_dai->private_data;
165
166 if (params_channels(params) == 1)
167 out_be32(&psc_dma->psc_regs->ac97_slots, 0x01000000);
168 else
169 out_be32(&psc_dma->psc_regs->ac97_slots, 0x03000000);
170
171 return 0;
172}
173
174static int psc_ac97_trigger(struct snd_pcm_substream *substream, int cmd,
175 struct snd_soc_dai *dai)
176{
177 struct snd_soc_pcm_runtime *rtd = substream->private_data;
178 struct psc_dma *psc_dma = rtd->dai->cpu_dai->private_data;
179
180 switch (cmd) {
181 case SNDRV_PCM_TRIGGER_STOP:
182 if (substream->pstr->stream == SNDRV_PCM_STREAM_CAPTURE)
183 psc_dma->slots &= 0xFFFF0000;
184 else
185 psc_dma->slots &= 0x0000FFFF;
186
187 out_be32(&psc_dma->psc_regs->ac97_slots, psc_dma->slots);
188 break;
189 }
190 return 0;
191}
192
193static int psc_ac97_probe(struct platform_device *pdev,
194 struct snd_soc_dai *cpu_dai)
195{
196 struct psc_dma *psc_dma = cpu_dai->private_data;
197 struct mpc52xx_psc __iomem *regs = psc_dma->psc_regs;
198
199 /* Go */
200 out_8(&regs->command, MPC52xx_PSC_TX_ENABLE | MPC52xx_PSC_RX_ENABLE);
201 return 0;
202}
203
204/* ---------------------------------------------------------------------
205 * ALSA SoC Bindings
206 *
207 * - Digital Audio Interface (DAI) template
208 * - create/destroy dai hooks
209 */
210
211/**
212 * psc_ac97_dai_template: template CPU Digital Audio Interface
213 */
214static struct snd_soc_dai_ops psc_ac97_analog_ops = {
215 .hw_params = psc_ac97_hw_analog_params,
216 .trigger = psc_ac97_trigger,
217};
218
219static struct snd_soc_dai_ops psc_ac97_digital_ops = {
220 .hw_params = psc_ac97_hw_digital_params,
221};
222
223struct snd_soc_dai psc_ac97_dai[] = {
224{
225 .name = "AC97",
226 .ac97_control = 1,
227 .probe = psc_ac97_probe,
228 .playback = {
229 .channels_min = 1,
230 .channels_max = 6,
231 .rates = SNDRV_PCM_RATE_8000_48000,
232 .formats = SNDRV_PCM_FMTBIT_S32_BE,
233 },
234 .capture = {
235 .channels_min = 1,
236 .channels_max = 2,
237 .rates = SNDRV_PCM_RATE_8000_48000,
238 .formats = SNDRV_PCM_FMTBIT_S32_BE,
239 },
240 .ops = &psc_ac97_analog_ops,
241},
242{
243 .name = "SPDIF",
244 .ac97_control = 1,
245 .playback = {
246 .channels_min = 1,
247 .channels_max = 2,
248 .rates = SNDRV_PCM_RATE_32000 | \
249 SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_48000,
250 .formats = SNDRV_PCM_FMTBIT_IEC958_SUBFRAME_BE,
251 },
252 .ops = &psc_ac97_digital_ops,
253} };
254EXPORT_SYMBOL_GPL(psc_ac97_dai);
255
256
257
258/* ---------------------------------------------------------------------
259 * OF platform bus binding code:
260 * - Probe/remove operations
261 * - OF device match table
262 */
263static int __devinit psc_ac97_of_probe(struct of_device *op,
264 const struct of_device_id *match)
265{
266 int rc, i;
267 struct snd_ac97 ac97;
268 struct mpc52xx_psc __iomem *regs;
269
270 rc = mpc5200_audio_dma_create(op);
271 if (rc != 0)
272 return rc;
273
274 for (i = 0; i < ARRAY_SIZE(psc_ac97_dai); i++)
275 psc_ac97_dai[i].dev = &op->dev;
276
277 rc = snd_soc_register_dais(psc_ac97_dai, ARRAY_SIZE(psc_ac97_dai));
278 if (rc != 0) {
279 dev_err(&op->dev, "Failed to register DAI\n");
280 return rc;
281 }
282
283 psc_dma = dev_get_drvdata(&op->dev);
284 regs = psc_dma->psc_regs;
285 ac97.private_data = psc_dma;
286
287 for (i = 0; i < ARRAY_SIZE(psc_ac97_dai); i++)
288 psc_ac97_dai[i].private_data = psc_dma;
289
290 psc_dma->imr = 0;
291 out_be16(&psc_dma->psc_regs->isr_imr.imr, psc_dma->imr);
292
293 /* Configure the serial interface mode to AC97 */
294 psc_dma->sicr = MPC52xx_PSC_SICR_SIM_AC97 | MPC52xx_PSC_SICR_ENAC97;
295 out_be32(&regs->sicr, psc_dma->sicr);
296
297 /* No slots active */
298 out_be32(&regs->ac97_slots, 0x00000000);
299
300 return 0;
301}
302
303static int __devexit psc_ac97_of_remove(struct of_device *op)
304{
305 return mpc5200_audio_dma_destroy(op);
306}
307
308/* Match table for of_platform binding */
309static struct of_device_id psc_ac97_match[] __devinitdata = {
310 { .compatible = "fsl,mpc5200-psc-ac97", },
311 { .compatible = "fsl,mpc5200b-psc-ac97", },
312 {}
313};
314MODULE_DEVICE_TABLE(of, psc_ac97_match);
315
316static struct of_platform_driver psc_ac97_driver = {
317 .match_table = psc_ac97_match,
318 .probe = psc_ac97_of_probe,
319 .remove = __devexit_p(psc_ac97_of_remove),
320 .driver = {
321 .name = "mpc5200-psc-ac97",
322 .owner = THIS_MODULE,
323 },
324};
325
326/* ---------------------------------------------------------------------
327 * Module setup and teardown; simply register the of_platform driver
328 * for the PSC in AC97 mode.
329 */
330static int __init psc_ac97_init(void)
331{
332 return of_register_platform_driver(&psc_ac97_driver);
333}
334module_init(psc_ac97_init);
335
336static void __exit psc_ac97_exit(void)
337{
338 of_unregister_platform_driver(&psc_ac97_driver);
339}
340module_exit(psc_ac97_exit);
341
342MODULE_AUTHOR("Jon Smirl <jonsmirl@gmail.com>");
343MODULE_DESCRIPTION("mpc5200 AC97 module");
344MODULE_LICENSE("GPL");
345
diff --git a/sound/soc/fsl/mpc5200_psc_ac97.h b/sound/soc/fsl/mpc5200_psc_ac97.h
new file mode 100644
index 000000000000..4bc18c35c369
--- /dev/null
+++ b/sound/soc/fsl/mpc5200_psc_ac97.h
@@ -0,0 +1,15 @@
1/*
2 * Freescale MPC5200 PSC in AC97 mode
3 * ALSA SoC Digital Audio Interface (DAI) driver
4 *
5 */
6
7#ifndef __SOUND_SOC_FSL_MPC52xx_PSC_AC97_H__
8#define __SOUND_SOC_FSL_MPC52xx_PSC_AC97_H__
9
10extern struct snd_soc_dai psc_ac97_dai[];
11
12#define MPC5200_AC97_NORMAL 0
13#define MPC5200_AC97_SPDIF 1
14
15#endif /* __SOUND_SOC_FSL_MPC52xx_PSC_AC97_H__ */
diff --git a/sound/soc/fsl/mpc5200_psc_i2s.c b/sound/soc/fsl/mpc5200_psc_i2s.c
index 1111c710118a..ce8de90fb94a 100644
--- a/sound/soc/fsl/mpc5200_psc_i2s.c
+++ b/sound/soc/fsl/mpc5200_psc_i2s.c
@@ -3,31 +3,21 @@
3 * ALSA SoC Digital Audio Interface (DAI) driver 3 * ALSA SoC Digital Audio Interface (DAI) driver
4 * 4 *
5 * Copyright (C) 2008 Secret Lab Technologies Ltd. 5 * Copyright (C) 2008 Secret Lab Technologies Ltd.
6 * Copyright (C) 2009 Jon Smirl, Digispeaker
6 */ 7 */
7 8
8#include <linux/init.h>
9#include <linux/module.h> 9#include <linux/module.h>
10#include <linux/interrupt.h>
11#include <linux/device.h>
12#include <linux/delay.h>
13#include <linux/of_device.h> 10#include <linux/of_device.h>
14#include <linux/of_platform.h> 11#include <linux/of_platform.h>
15#include <linux/dma-mapping.h>
16 12
17#include <sound/core.h>
18#include <sound/pcm.h> 13#include <sound/pcm.h>
19#include <sound/pcm_params.h> 14#include <sound/pcm_params.h>
20#include <sound/initval.h>
21#include <sound/soc.h> 15#include <sound/soc.h>
22#include <sound/soc-of-simple.h>
23 16
24#include <sysdev/bestcomm/bestcomm.h>
25#include <sysdev/bestcomm/gen_bd.h>
26#include <asm/mpc52xx_psc.h> 17#include <asm/mpc52xx_psc.h>
27 18
28MODULE_AUTHOR("Grant Likely <grant.likely@secretlab.ca>"); 19#include "mpc5200_psc_i2s.h"
29MODULE_DESCRIPTION("Freescale MPC5200 PSC in I2S mode ASoC Driver"); 20#include "mpc5200_dma.h"
30MODULE_LICENSE("GPL");
31 21
32/** 22/**
33 * PSC_I2S_RATES: sample rates supported by the I2S 23 * PSC_I2S_RATES: sample rates supported by the I2S
@@ -44,191 +34,17 @@ MODULE_LICENSE("GPL");
44 * PSC_I2S_FORMATS: audio formats supported by the PSC I2S mode 34 * PSC_I2S_FORMATS: audio formats supported by the PSC I2S mode
45 */ 35 */
46#define PSC_I2S_FORMATS (SNDRV_PCM_FMTBIT_S8 | SNDRV_PCM_FMTBIT_S16_BE | \ 36#define PSC_I2S_FORMATS (SNDRV_PCM_FMTBIT_S8 | SNDRV_PCM_FMTBIT_S16_BE | \
47 SNDRV_PCM_FMTBIT_S24_BE | SNDRV_PCM_FMTBIT_S24_BE | \ 37 SNDRV_PCM_FMTBIT_S24_BE | SNDRV_PCM_FMTBIT_S32_BE)
48 SNDRV_PCM_FMTBIT_S32_BE)
49
50/**
51 * psc_i2s_stream - Data specific to a single stream (playback or capture)
52 * @active: flag indicating if the stream is active
53 * @psc_i2s: pointer back to parent psc_i2s data structure
54 * @bcom_task: bestcomm task structure
55 * @irq: irq number for bestcomm task
56 * @period_start: physical address of start of DMA region
57 * @period_end: physical address of end of DMA region
58 * @period_next_pt: physical address of next DMA buffer to enqueue
59 * @period_bytes: size of DMA period in bytes
60 */
61struct psc_i2s_stream {
62 int active;
63 struct psc_i2s *psc_i2s;
64 struct bcom_task *bcom_task;
65 int irq;
66 struct snd_pcm_substream *stream;
67 dma_addr_t period_start;
68 dma_addr_t period_end;
69 dma_addr_t period_next_pt;
70 dma_addr_t period_current_pt;
71 int period_bytes;
72};
73
74/**
75 * psc_i2s - Private driver data
76 * @name: short name for this device ("PSC0", "PSC1", etc)
77 * @psc_regs: pointer to the PSC's registers
78 * @fifo_regs: pointer to the PSC's FIFO registers
79 * @irq: IRQ of this PSC
80 * @dev: struct device pointer
81 * @dai: the CPU DAI for this device
82 * @sicr: Base value used in serial interface control register; mode is ORed
83 * with this value.
84 * @playback: Playback stream context data
85 * @capture: Capture stream context data
86 */
87struct psc_i2s {
88 char name[32];
89 struct mpc52xx_psc __iomem *psc_regs;
90 struct mpc52xx_psc_fifo __iomem *fifo_regs;
91 unsigned int irq;
92 struct device *dev;
93 struct snd_soc_dai dai;
94 spinlock_t lock;
95 u32 sicr;
96
97 /* per-stream data */
98 struct psc_i2s_stream playback;
99 struct psc_i2s_stream capture;
100
101 /* Statistics */
102 struct {
103 int overrun_count;
104 int underrun_count;
105 } stats;
106};
107
108/*
109 * Interrupt handlers
110 */
111static irqreturn_t psc_i2s_status_irq(int irq, void *_psc_i2s)
112{
113 struct psc_i2s *psc_i2s = _psc_i2s;
114 struct mpc52xx_psc __iomem *regs = psc_i2s->psc_regs;
115 u16 isr;
116
117 isr = in_be16(&regs->mpc52xx_psc_isr);
118
119 /* Playback underrun error */
120 if (psc_i2s->playback.active && (isr & MPC52xx_PSC_IMR_TXEMP))
121 psc_i2s->stats.underrun_count++;
122
123 /* Capture overrun error */
124 if (psc_i2s->capture.active && (isr & MPC52xx_PSC_IMR_ORERR))
125 psc_i2s->stats.overrun_count++;
126
127 out_8(&regs->command, 4 << 4); /* reset the error status */
128
129 return IRQ_HANDLED;
130}
131
132/**
133 * psc_i2s_bcom_enqueue_next_buffer - Enqueue another audio buffer
134 * @s: pointer to stream private data structure
135 *
136 * Enqueues another audio period buffer into the bestcomm queue.
137 *
138 * Note: The routine must only be called when there is space available in
139 * the queue. Otherwise the enqueue will fail and the audio ring buffer
140 * will get out of sync
141 */
142static void psc_i2s_bcom_enqueue_next_buffer(struct psc_i2s_stream *s)
143{
144 struct bcom_bd *bd;
145
146 /* Prepare and enqueue the next buffer descriptor */
147 bd = bcom_prepare_next_buffer(s->bcom_task);
148 bd->status = s->period_bytes;
149 bd->data[0] = s->period_next_pt;
150 bcom_submit_next_buffer(s->bcom_task, NULL);
151
152 /* Update for next period */
153 s->period_next_pt += s->period_bytes;
154 if (s->period_next_pt >= s->period_end)
155 s->period_next_pt = s->period_start;
156}
157
158/* Bestcomm DMA irq handler */
159static irqreturn_t psc_i2s_bcom_irq(int irq, void *_psc_i2s_stream)
160{
161 struct psc_i2s_stream *s = _psc_i2s_stream;
162
163 /* For each finished period, dequeue the completed period buffer
164 * and enqueue a new one in it's place. */
165 while (bcom_buffer_done(s->bcom_task)) {
166 bcom_retrieve_buffer(s->bcom_task, NULL, NULL);
167 s->period_current_pt += s->period_bytes;
168 if (s->period_current_pt >= s->period_end)
169 s->period_current_pt = s->period_start;
170 psc_i2s_bcom_enqueue_next_buffer(s);
171 bcom_enable(s->bcom_task);
172 }
173
174 /* If the stream is active, then also inform the PCM middle layer
175 * of the period finished event. */
176 if (s->active)
177 snd_pcm_period_elapsed(s->stream);
178
179 return IRQ_HANDLED;
180}
181
182/**
183 * psc_i2s_startup: create a new substream
184 *
185 * This is the first function called when a stream is opened.
186 *
187 * If this is the first stream open, then grab the IRQ and program most of
188 * the PSC registers.
189 */
190static int psc_i2s_startup(struct snd_pcm_substream *substream,
191 struct snd_soc_dai *dai)
192{
193 struct snd_soc_pcm_runtime *rtd = substream->private_data;
194 struct psc_i2s *psc_i2s = rtd->dai->cpu_dai->private_data;
195 int rc;
196
197 dev_dbg(psc_i2s->dev, "psc_i2s_startup(substream=%p)\n", substream);
198
199 if (!psc_i2s->playback.active &&
200 !psc_i2s->capture.active) {
201 /* Setup the IRQs */
202 rc = request_irq(psc_i2s->irq, &psc_i2s_status_irq, IRQF_SHARED,
203 "psc-i2s-status", psc_i2s);
204 rc |= request_irq(psc_i2s->capture.irq,
205 &psc_i2s_bcom_irq, IRQF_SHARED,
206 "psc-i2s-capture", &psc_i2s->capture);
207 rc |= request_irq(psc_i2s->playback.irq,
208 &psc_i2s_bcom_irq, IRQF_SHARED,
209 "psc-i2s-playback", &psc_i2s->playback);
210 if (rc) {
211 free_irq(psc_i2s->irq, psc_i2s);
212 free_irq(psc_i2s->capture.irq,
213 &psc_i2s->capture);
214 free_irq(psc_i2s->playback.irq,
215 &psc_i2s->playback);
216 return -ENODEV;
217 }
218 }
219
220 return 0;
221}
222 38
223static int psc_i2s_hw_params(struct snd_pcm_substream *substream, 39static int psc_i2s_hw_params(struct snd_pcm_substream *substream,
224 struct snd_pcm_hw_params *params, 40 struct snd_pcm_hw_params *params,
225 struct snd_soc_dai *dai) 41 struct snd_soc_dai *dai)
226{ 42{
227 struct snd_soc_pcm_runtime *rtd = substream->private_data; 43 struct snd_soc_pcm_runtime *rtd = substream->private_data;
228 struct psc_i2s *psc_i2s = rtd->dai->cpu_dai->private_data; 44 struct psc_dma *psc_dma = rtd->dai->cpu_dai->private_data;
229 u32 mode; 45 u32 mode;
230 46
231 dev_dbg(psc_i2s->dev, "%s(substream=%p) p_size=%i p_bytes=%i" 47 dev_dbg(psc_dma->dev, "%s(substream=%p) p_size=%i p_bytes=%i"
232 " periods=%i buffer_size=%i buffer_bytes=%i\n", 48 " periods=%i buffer_size=%i buffer_bytes=%i\n",
233 __func__, substream, params_period_size(params), 49 __func__, substream, params_period_size(params),
234 params_period_bytes(params), params_periods(params), 50 params_period_bytes(params), params_periods(params),
@@ -248,175 +64,15 @@ static int psc_i2s_hw_params(struct snd_pcm_substream *substream,
248 mode = MPC52xx_PSC_SICR_SIM_CODEC_32; 64 mode = MPC52xx_PSC_SICR_SIM_CODEC_32;
249 break; 65 break;
250 default: 66 default:
251 dev_dbg(psc_i2s->dev, "invalid format\n"); 67 dev_dbg(psc_dma->dev, "invalid format\n");
252 return -EINVAL;
253 }
254 out_be32(&psc_i2s->psc_regs->sicr, psc_i2s->sicr | mode);
255
256 snd_pcm_set_runtime_buffer(substream, &substream->dma_buffer);
257
258 return 0;
259}
260
261static int psc_i2s_hw_free(struct snd_pcm_substream *substream,
262 struct snd_soc_dai *dai)
263{
264 snd_pcm_set_runtime_buffer(substream, NULL);
265 return 0;
266}
267
268/**
269 * psc_i2s_trigger: start and stop the DMA transfer.
270 *
271 * This function is called by ALSA to start, stop, pause, and resume the DMA
272 * transfer of data.
273 */
274static int psc_i2s_trigger(struct snd_pcm_substream *substream, int cmd,
275 struct snd_soc_dai *dai)
276{
277 struct snd_soc_pcm_runtime *rtd = substream->private_data;
278 struct psc_i2s *psc_i2s = rtd->dai->cpu_dai->private_data;
279 struct snd_pcm_runtime *runtime = substream->runtime;
280 struct psc_i2s_stream *s;
281 struct mpc52xx_psc __iomem *regs = psc_i2s->psc_regs;
282 u16 imr;
283 u8 psc_cmd;
284 unsigned long flags;
285
286 if (substream->pstr->stream == SNDRV_PCM_STREAM_CAPTURE)
287 s = &psc_i2s->capture;
288 else
289 s = &psc_i2s->playback;
290
291 dev_dbg(psc_i2s->dev, "psc_i2s_trigger(substream=%p, cmd=%i)"
292 " stream_id=%i\n",
293 substream, cmd, substream->pstr->stream);
294
295 switch (cmd) {
296 case SNDRV_PCM_TRIGGER_START:
297 s->period_bytes = frames_to_bytes(runtime,
298 runtime->period_size);
299 s->period_start = virt_to_phys(runtime->dma_area);
300 s->period_end = s->period_start +
301 (s->period_bytes * runtime->periods);
302 s->period_next_pt = s->period_start;
303 s->period_current_pt = s->period_start;
304 s->active = 1;
305
306 /* First; reset everything */
307 if (substream->pstr->stream == SNDRV_PCM_STREAM_CAPTURE) {
308 out_8(&regs->command, MPC52xx_PSC_RST_RX);
309 out_8(&regs->command, MPC52xx_PSC_RST_ERR_STAT);
310 } else {
311 out_8(&regs->command, MPC52xx_PSC_RST_TX);
312 out_8(&regs->command, MPC52xx_PSC_RST_ERR_STAT);
313 }
314
315 /* Next, fill up the bestcomm bd queue and enable DMA.
316 * This will begin filling the PSC's fifo. */
317 if (substream->pstr->stream == SNDRV_PCM_STREAM_CAPTURE)
318 bcom_gen_bd_rx_reset(s->bcom_task);
319 else
320 bcom_gen_bd_tx_reset(s->bcom_task);
321 while (!bcom_queue_full(s->bcom_task))
322 psc_i2s_bcom_enqueue_next_buffer(s);
323 bcom_enable(s->bcom_task);
324
325 /* Due to errata in the i2s mode; need to line up enabling
326 * the transmitter with a transition on the frame sync
327 * line */
328
329 spin_lock_irqsave(&psc_i2s->lock, flags);
330 /* first make sure it is low */
331 while ((in_8(&regs->ipcr_acr.ipcr) & 0x80) != 0)
332 ;
333 /* then wait for the transition to high */
334 while ((in_8(&regs->ipcr_acr.ipcr) & 0x80) == 0)
335 ;
336 /* Finally, enable the PSC.
337 * Receiver must always be enabled; even when we only want
338 * transmit. (see 15.3.2.3 of MPC5200B User's Guide) */
339 psc_cmd = MPC52xx_PSC_RX_ENABLE;
340 if (substream->pstr->stream == SNDRV_PCM_STREAM_PLAYBACK)
341 psc_cmd |= MPC52xx_PSC_TX_ENABLE;
342 out_8(&regs->command, psc_cmd);
343 spin_unlock_irqrestore(&psc_i2s->lock, flags);
344
345 break;
346
347 case SNDRV_PCM_TRIGGER_STOP:
348 /* Turn off the PSC */
349 s->active = 0;
350 if (substream->pstr->stream == SNDRV_PCM_STREAM_CAPTURE) {
351 if (!psc_i2s->playback.active) {
352 out_8(&regs->command, 2 << 4); /* reset rx */
353 out_8(&regs->command, 3 << 4); /* reset tx */
354 out_8(&regs->command, 4 << 4); /* reset err */
355 }
356 } else {
357 out_8(&regs->command, 3 << 4); /* reset tx */
358 out_8(&regs->command, 4 << 4); /* reset err */
359 if (!psc_i2s->capture.active)
360 out_8(&regs->command, 2 << 4); /* reset rx */
361 }
362
363 bcom_disable(s->bcom_task);
364 while (!bcom_queue_empty(s->bcom_task))
365 bcom_retrieve_buffer(s->bcom_task, NULL, NULL);
366
367 break;
368
369 default:
370 dev_dbg(psc_i2s->dev, "invalid command\n");
371 return -EINVAL; 68 return -EINVAL;
372 } 69 }
373 70 out_be32(&psc_dma->psc_regs->sicr, psc_dma->sicr | mode);
374 /* Update interrupt enable settings */
375 imr = 0;
376 if (psc_i2s->playback.active)
377 imr |= MPC52xx_PSC_IMR_TXEMP;
378 if (psc_i2s->capture.active)
379 imr |= MPC52xx_PSC_IMR_ORERR;
380 out_be16(&regs->isr_imr.imr, imr);
381 71
382 return 0; 72 return 0;
383} 73}
384 74
385/** 75/**
386 * psc_i2s_shutdown: shutdown the data transfer on a stream
387 *
388 * Shutdown the PSC if there are no other substreams open.
389 */
390static void psc_i2s_shutdown(struct snd_pcm_substream *substream,
391 struct snd_soc_dai *dai)
392{
393 struct snd_soc_pcm_runtime *rtd = substream->private_data;
394 struct psc_i2s *psc_i2s = rtd->dai->cpu_dai->private_data;
395
396 dev_dbg(psc_i2s->dev, "psc_i2s_shutdown(substream=%p)\n", substream);
397
398 /*
399 * If this is the last active substream, disable the PSC and release
400 * the IRQ.
401 */
402 if (!psc_i2s->playback.active &&
403 !psc_i2s->capture.active) {
404
405 /* Disable all interrupts and reset the PSC */
406 out_be16(&psc_i2s->psc_regs->isr_imr.imr, 0);
407 out_8(&psc_i2s->psc_regs->command, 3 << 4); /* reset tx */
408 out_8(&psc_i2s->psc_regs->command, 2 << 4); /* reset rx */
409 out_8(&psc_i2s->psc_regs->command, 1 << 4); /* reset mode */
410 out_8(&psc_i2s->psc_regs->command, 4 << 4); /* reset error */
411
412 /* Release irqs */
413 free_irq(psc_i2s->irq, psc_i2s);
414 free_irq(psc_i2s->capture.irq, &psc_i2s->capture);
415 free_irq(psc_i2s->playback.irq, &psc_i2s->playback);
416 }
417}
418
419/**
420 * psc_i2s_set_sysclk: set the clock frequency and direction 76 * psc_i2s_set_sysclk: set the clock frequency and direction
421 * 77 *
422 * This function is called by the machine driver to tell us what the clock 78 * This function is called by the machine driver to tell us what the clock
@@ -433,8 +89,8 @@ static void psc_i2s_shutdown(struct snd_pcm_substream *substream,
433static int psc_i2s_set_sysclk(struct snd_soc_dai *cpu_dai, 89static int psc_i2s_set_sysclk(struct snd_soc_dai *cpu_dai,
434 int clk_id, unsigned int freq, int dir) 90 int clk_id, unsigned int freq, int dir)
435{ 91{
436 struct psc_i2s *psc_i2s = cpu_dai->private_data; 92 struct psc_dma *psc_dma = cpu_dai->private_data;
437 dev_dbg(psc_i2s->dev, "psc_i2s_set_sysclk(cpu_dai=%p, dir=%i)\n", 93 dev_dbg(psc_dma->dev, "psc_i2s_set_sysclk(cpu_dai=%p, dir=%i)\n",
438 cpu_dai, dir); 94 cpu_dai, dir);
439 return (dir == SND_SOC_CLOCK_IN) ? 0 : -EINVAL; 95 return (dir == SND_SOC_CLOCK_IN) ? 0 : -EINVAL;
440} 96}
@@ -452,8 +108,8 @@ static int psc_i2s_set_sysclk(struct snd_soc_dai *cpu_dai,
452 */ 108 */
453static int psc_i2s_set_fmt(struct snd_soc_dai *cpu_dai, unsigned int format) 109static int psc_i2s_set_fmt(struct snd_soc_dai *cpu_dai, unsigned int format)
454{ 110{
455 struct psc_i2s *psc_i2s = cpu_dai->private_data; 111 struct psc_dma *psc_dma = cpu_dai->private_data;
456 dev_dbg(psc_i2s->dev, "psc_i2s_set_fmt(cpu_dai=%p, format=%i)\n", 112 dev_dbg(psc_dma->dev, "psc_i2s_set_fmt(cpu_dai=%p, format=%i)\n",
457 cpu_dai, format); 113 cpu_dai, format);
458 return (format == SND_SOC_DAIFMT_I2S) ? 0 : -EINVAL; 114 return (format == SND_SOC_DAIFMT_I2S) ? 0 : -EINVAL;
459} 115}
@@ -469,16 +125,13 @@ static int psc_i2s_set_fmt(struct snd_soc_dai *cpu_dai, unsigned int format)
469 * psc_i2s_dai_template: template CPU Digital Audio Interface 125 * psc_i2s_dai_template: template CPU Digital Audio Interface
470 */ 126 */
471static struct snd_soc_dai_ops psc_i2s_dai_ops = { 127static struct snd_soc_dai_ops psc_i2s_dai_ops = {
472 .startup = psc_i2s_startup,
473 .hw_params = psc_i2s_hw_params, 128 .hw_params = psc_i2s_hw_params,
474 .hw_free = psc_i2s_hw_free,
475 .shutdown = psc_i2s_shutdown,
476 .trigger = psc_i2s_trigger,
477 .set_sysclk = psc_i2s_set_sysclk, 129 .set_sysclk = psc_i2s_set_sysclk,
478 .set_fmt = psc_i2s_set_fmt, 130 .set_fmt = psc_i2s_set_fmt,
479}; 131};
480 132
481static struct snd_soc_dai psc_i2s_dai_template = { 133struct snd_soc_dai psc_i2s_dai[] = {{
134 .name = "I2S",
482 .playback = { 135 .playback = {
483 .channels_min = 2, 136 .channels_min = 2,
484 .channels_max = 2, 137 .channels_max = 2,
@@ -492,223 +145,8 @@ static struct snd_soc_dai psc_i2s_dai_template = {
492 .formats = PSC_I2S_FORMATS, 145 .formats = PSC_I2S_FORMATS,
493 }, 146 },
494 .ops = &psc_i2s_dai_ops, 147 .ops = &psc_i2s_dai_ops,
495}; 148} };
496 149EXPORT_SYMBOL_GPL(psc_i2s_dai);
497/* ---------------------------------------------------------------------
498 * The PSC I2S 'ASoC platform' driver
499 *
500 * Can be referenced by an 'ASoC machine' driver
501 * This driver only deals with the audio bus; it doesn't have any
502 * interaction with the attached codec
503 */
504
505static const struct snd_pcm_hardware psc_i2s_pcm_hardware = {
506 .info = SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_MMAP_VALID |
507 SNDRV_PCM_INFO_INTERLEAVED | SNDRV_PCM_INFO_BLOCK_TRANSFER |
508 SNDRV_PCM_INFO_BATCH,
509 .formats = SNDRV_PCM_FMTBIT_S8 | SNDRV_PCM_FMTBIT_S16_BE |
510 SNDRV_PCM_FMTBIT_S24_BE | SNDRV_PCM_FMTBIT_S32_BE,
511 .rate_min = 8000,
512 .rate_max = 48000,
513 .channels_min = 2,
514 .channels_max = 2,
515 .period_bytes_max = 1024 * 1024,
516 .period_bytes_min = 32,
517 .periods_min = 2,
518 .periods_max = 256,
519 .buffer_bytes_max = 2 * 1024 * 1024,
520 .fifo_size = 0,
521};
522
523static int psc_i2s_pcm_open(struct snd_pcm_substream *substream)
524{
525 struct snd_soc_pcm_runtime *rtd = substream->private_data;
526 struct psc_i2s *psc_i2s = rtd->dai->cpu_dai->private_data;
527 struct psc_i2s_stream *s;
528
529 dev_dbg(psc_i2s->dev, "psc_i2s_pcm_open(substream=%p)\n", substream);
530
531 if (substream->pstr->stream == SNDRV_PCM_STREAM_CAPTURE)
532 s = &psc_i2s->capture;
533 else
534 s = &psc_i2s->playback;
535
536 snd_soc_set_runtime_hwparams(substream, &psc_i2s_pcm_hardware);
537
538 s->stream = substream;
539 return 0;
540}
541
542static int psc_i2s_pcm_close(struct snd_pcm_substream *substream)
543{
544 struct snd_soc_pcm_runtime *rtd = substream->private_data;
545 struct psc_i2s *psc_i2s = rtd->dai->cpu_dai->private_data;
546 struct psc_i2s_stream *s;
547
548 dev_dbg(psc_i2s->dev, "psc_i2s_pcm_close(substream=%p)\n", substream);
549
550 if (substream->pstr->stream == SNDRV_PCM_STREAM_CAPTURE)
551 s = &psc_i2s->capture;
552 else
553 s = &psc_i2s->playback;
554
555 s->stream = NULL;
556 return 0;
557}
558
559static snd_pcm_uframes_t
560psc_i2s_pcm_pointer(struct snd_pcm_substream *substream)
561{
562 struct snd_soc_pcm_runtime *rtd = substream->private_data;
563 struct psc_i2s *psc_i2s = rtd->dai->cpu_dai->private_data;
564 struct psc_i2s_stream *s;
565 dma_addr_t count;
566
567 if (substream->pstr->stream == SNDRV_PCM_STREAM_CAPTURE)
568 s = &psc_i2s->capture;
569 else
570 s = &psc_i2s->playback;
571
572 count = s->period_current_pt - s->period_start;
573
574 return bytes_to_frames(substream->runtime, count);
575}
576
577static struct snd_pcm_ops psc_i2s_pcm_ops = {
578 .open = psc_i2s_pcm_open,
579 .close = psc_i2s_pcm_close,
580 .ioctl = snd_pcm_lib_ioctl,
581 .pointer = psc_i2s_pcm_pointer,
582};
583
584static u64 psc_i2s_pcm_dmamask = 0xffffffff;
585static int psc_i2s_pcm_new(struct snd_card *card, struct snd_soc_dai *dai,
586 struct snd_pcm *pcm)
587{
588 struct snd_soc_pcm_runtime *rtd = pcm->private_data;
589 size_t size = psc_i2s_pcm_hardware.buffer_bytes_max;
590 int rc = 0;
591
592 dev_dbg(rtd->socdev->dev, "psc_i2s_pcm_new(card=%p, dai=%p, pcm=%p)\n",
593 card, dai, pcm);
594
595 if (!card->dev->dma_mask)
596 card->dev->dma_mask = &psc_i2s_pcm_dmamask;
597 if (!card->dev->coherent_dma_mask)
598 card->dev->coherent_dma_mask = 0xffffffff;
599
600 if (pcm->streams[0].substream) {
601 rc = snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, pcm->dev, size,
602 &pcm->streams[0].substream->dma_buffer);
603 if (rc)
604 goto playback_alloc_err;
605 }
606
607 if (pcm->streams[1].substream) {
608 rc = snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, pcm->dev, size,
609 &pcm->streams[1].substream->dma_buffer);
610 if (rc)
611 goto capture_alloc_err;
612 }
613
614 return 0;
615
616 capture_alloc_err:
617 if (pcm->streams[0].substream)
618 snd_dma_free_pages(&pcm->streams[0].substream->dma_buffer);
619 playback_alloc_err:
620 dev_err(card->dev, "Cannot allocate buffer(s)\n");
621 return -ENOMEM;
622}
623
624static void psc_i2s_pcm_free(struct snd_pcm *pcm)
625{
626 struct snd_soc_pcm_runtime *rtd = pcm->private_data;
627 struct snd_pcm_substream *substream;
628 int stream;
629
630 dev_dbg(rtd->socdev->dev, "psc_i2s_pcm_free(pcm=%p)\n", pcm);
631
632 for (stream = 0; stream < 2; stream++) {
633 substream = pcm->streams[stream].substream;
634 if (substream) {
635 snd_dma_free_pages(&substream->dma_buffer);
636 substream->dma_buffer.area = NULL;
637 substream->dma_buffer.addr = 0;
638 }
639 }
640}
641
642struct snd_soc_platform psc_i2s_pcm_soc_platform = {
643 .name = "mpc5200-psc-audio",
644 .pcm_ops = &psc_i2s_pcm_ops,
645 .pcm_new = &psc_i2s_pcm_new,
646 .pcm_free = &psc_i2s_pcm_free,
647};
648
649/* ---------------------------------------------------------------------
650 * Sysfs attributes for debugging
651 */
652
653static ssize_t psc_i2s_status_show(struct device *dev,
654 struct device_attribute *attr, char *buf)
655{
656 struct psc_i2s *psc_i2s = dev_get_drvdata(dev);
657
658 return sprintf(buf, "status=%.4x sicr=%.8x rfnum=%i rfstat=0x%.4x "
659 "tfnum=%i tfstat=0x%.4x\n",
660 in_be16(&psc_i2s->psc_regs->sr_csr.status),
661 in_be32(&psc_i2s->psc_regs->sicr),
662 in_be16(&psc_i2s->fifo_regs->rfnum) & 0x1ff,
663 in_be16(&psc_i2s->fifo_regs->rfstat),
664 in_be16(&psc_i2s->fifo_regs->tfnum) & 0x1ff,
665 in_be16(&psc_i2s->fifo_regs->tfstat));
666}
667
668static int *psc_i2s_get_stat_attr(struct psc_i2s *psc_i2s, const char *name)
669{
670 if (strcmp(name, "playback_underrun") == 0)
671 return &psc_i2s->stats.underrun_count;
672 if (strcmp(name, "capture_overrun") == 0)
673 return &psc_i2s->stats.overrun_count;
674
675 return NULL;
676}
677
678static ssize_t psc_i2s_stat_show(struct device *dev,
679 struct device_attribute *attr, char *buf)
680{
681 struct psc_i2s *psc_i2s = dev_get_drvdata(dev);
682 int *attrib;
683
684 attrib = psc_i2s_get_stat_attr(psc_i2s, attr->attr.name);
685 if (!attrib)
686 return 0;
687
688 return sprintf(buf, "%i\n", *attrib);
689}
690
691static ssize_t psc_i2s_stat_store(struct device *dev,
692 struct device_attribute *attr,
693 const char *buf,
694 size_t count)
695{
696 struct psc_i2s *psc_i2s = dev_get_drvdata(dev);
697 int *attrib;
698
699 attrib = psc_i2s_get_stat_attr(psc_i2s, attr->attr.name);
700 if (!attrib)
701 return 0;
702
703 *attrib = simple_strtoul(buf, NULL, 0);
704 return count;
705}
706
707static DEVICE_ATTR(status, 0644, psc_i2s_status_show, NULL);
708static DEVICE_ATTR(playback_underrun, 0644, psc_i2s_stat_show,
709 psc_i2s_stat_store);
710static DEVICE_ATTR(capture_overrun, 0644, psc_i2s_stat_show,
711 psc_i2s_stat_store);
712 150
713/* --------------------------------------------------------------------- 151/* ---------------------------------------------------------------------
714 * OF platform bus binding code: 152 * OF platform bus binding code:
@@ -718,150 +156,65 @@ static DEVICE_ATTR(capture_overrun, 0644, psc_i2s_stat_show,
718static int __devinit psc_i2s_of_probe(struct of_device *op, 156static int __devinit psc_i2s_of_probe(struct of_device *op,
719 const struct of_device_id *match) 157 const struct of_device_id *match)
720{ 158{
721 phys_addr_t fifo; 159 int rc;
722 struct psc_i2s *psc_i2s; 160 struct psc_dma *psc_dma;
723 struct resource res; 161 struct mpc52xx_psc __iomem *regs;
724 int size, psc_id, irq, rc;
725 const __be32 *prop;
726 void __iomem *regs;
727
728 dev_dbg(&op->dev, "probing psc i2s device\n");
729
730 /* Get the PSC ID */
731 prop = of_get_property(op->node, "cell-index", &size);
732 if (!prop || size < sizeof *prop)
733 return -ENODEV;
734 psc_id = be32_to_cpu(*prop);
735
736 /* Fetch the registers and IRQ of the PSC */
737 irq = irq_of_parse_and_map(op->node, 0);
738 if (of_address_to_resource(op->node, 0, &res)) {
739 dev_err(&op->dev, "Missing reg property\n");
740 return -ENODEV;
741 }
742 regs = ioremap(res.start, 1 + res.end - res.start);
743 if (!regs) {
744 dev_err(&op->dev, "Could not map registers\n");
745 return -ENODEV;
746 }
747 162
748 /* Allocate and initialize the driver private data */ 163 rc = mpc5200_audio_dma_create(op);
749 psc_i2s = kzalloc(sizeof *psc_i2s, GFP_KERNEL); 164 if (rc != 0)
750 if (!psc_i2s) { 165 return rc;
751 iounmap(regs); 166
752 return -ENOMEM; 167 rc = snd_soc_register_dais(psc_i2s_dai, ARRAY_SIZE(psc_i2s_dai));
753 } 168 if (rc != 0) {
754 spin_lock_init(&psc_i2s->lock); 169 pr_err("Failed to register DAI\n");
755 psc_i2s->irq = irq; 170 return 0;
756 psc_i2s->psc_regs = regs;
757 psc_i2s->fifo_regs = regs + sizeof *psc_i2s->psc_regs;
758 psc_i2s->dev = &op->dev;
759 psc_i2s->playback.psc_i2s = psc_i2s;
760 psc_i2s->capture.psc_i2s = psc_i2s;
761 snprintf(psc_i2s->name, sizeof psc_i2s->name, "PSC%u", psc_id+1);
762
763 /* Fill out the CPU DAI structure */
764 memcpy(&psc_i2s->dai, &psc_i2s_dai_template, sizeof psc_i2s->dai);
765 psc_i2s->dai.private_data = psc_i2s;
766 psc_i2s->dai.name = psc_i2s->name;
767 psc_i2s->dai.id = psc_id;
768
769 /* Find the address of the fifo data registers and setup the
770 * DMA tasks */
771 fifo = res.start + offsetof(struct mpc52xx_psc, buffer.buffer_32);
772 psc_i2s->capture.bcom_task =
773 bcom_psc_gen_bd_rx_init(psc_id, 10, fifo, 512);
774 psc_i2s->playback.bcom_task =
775 bcom_psc_gen_bd_tx_init(psc_id, 10, fifo);
776 if (!psc_i2s->capture.bcom_task ||
777 !psc_i2s->playback.bcom_task) {
778 dev_err(&op->dev, "Could not allocate bestcomm tasks\n");
779 iounmap(regs);
780 kfree(psc_i2s);
781 return -ENODEV;
782 } 171 }
783 172
784 /* Disable all interrupts and reset the PSC */ 173 psc_dma = dev_get_drvdata(&op->dev);
785 out_be16(&psc_i2s->psc_regs->isr_imr.imr, 0); 174 regs = psc_dma->psc_regs;
786 out_8(&psc_i2s->psc_regs->command, 3 << 4); /* reset transmitter */
787 out_8(&psc_i2s->psc_regs->command, 2 << 4); /* reset receiver */
788 out_8(&psc_i2s->psc_regs->command, 1 << 4); /* reset mode */
789 out_8(&psc_i2s->psc_regs->command, 4 << 4); /* reset error */
790 175
791 /* Configure the serial interface mode; defaulting to CODEC8 mode */ 176 /* Configure the serial interface mode; defaulting to CODEC8 mode */
792 psc_i2s->sicr = MPC52xx_PSC_SICR_DTS1 | MPC52xx_PSC_SICR_I2S | 177 psc_dma->sicr = MPC52xx_PSC_SICR_DTS1 | MPC52xx_PSC_SICR_I2S |
793 MPC52xx_PSC_SICR_CLKPOL; 178 MPC52xx_PSC_SICR_CLKPOL;
794 if (of_get_property(op->node, "fsl,cellslave", NULL)) 179 out_be32(&psc_dma->psc_regs->sicr,
795 psc_i2s->sicr |= MPC52xx_PSC_SICR_CELLSLAVE | 180 psc_dma->sicr | MPC52xx_PSC_SICR_SIM_CODEC_8);
796 MPC52xx_PSC_SICR_GENCLK;
797 out_be32(&psc_i2s->psc_regs->sicr,
798 psc_i2s->sicr | MPC52xx_PSC_SICR_SIM_CODEC_8);
799 181
800 /* Check for the codec handle. If it is not present then we 182 /* Check for the codec handle. If it is not present then we
801 * are done */ 183 * are done */
802 if (!of_get_property(op->node, "codec-handle", NULL)) 184 if (!of_get_property(op->node, "codec-handle", NULL))
803 return 0; 185 return 0;
804 186
805 /* Set up mode register; 187 /* Due to errata in the dma mode; need to line up enabling
806 * First write: RxRdy (FIFO Alarm) generates rx FIFO irq 188 * the transmitter with a transition on the frame sync
807 * Second write: register Normal mode for non loopback 189 * line */
808 */ 190
809 out_8(&psc_i2s->psc_regs->mode, 0); 191 /* first make sure it is low */
810 out_8(&psc_i2s->psc_regs->mode, 0); 192 while ((in_8(&regs->ipcr_acr.ipcr) & 0x80) != 0)
811 193 ;
812 /* Set the TX and RX fifo alarm thresholds */ 194 /* then wait for the transition to high */
813 out_be16(&psc_i2s->fifo_regs->rfalarm, 0x100); 195 while ((in_8(&regs->ipcr_acr.ipcr) & 0x80) == 0)
814 out_8(&psc_i2s->fifo_regs->rfcntl, 0x4); 196 ;
815 out_be16(&psc_i2s->fifo_regs->tfalarm, 0x100); 197 /* Finally, enable the PSC.
816 out_8(&psc_i2s->fifo_regs->tfcntl, 0x7); 198 * Receiver must always be enabled; even when we only want
817 199 * transmit. (see 15.3.2.3 of MPC5200B User's Guide) */
818 /* Lookup the IRQ numbers */ 200
819 psc_i2s->playback.irq = 201 /* Go */
820 bcom_get_task_irq(psc_i2s->playback.bcom_task); 202 out_8(&psc_dma->psc_regs->command,
821 psc_i2s->capture.irq = 203 MPC52xx_PSC_TX_ENABLE | MPC52xx_PSC_RX_ENABLE);
822 bcom_get_task_irq(psc_i2s->capture.bcom_task);
823
824 /* Save what we've done so it can be found again later */
825 dev_set_drvdata(&op->dev, psc_i2s);
826
827 /* Register the SYSFS files */
828 rc = device_create_file(psc_i2s->dev, &dev_attr_status);
829 rc |= device_create_file(psc_i2s->dev, &dev_attr_capture_overrun);
830 rc |= device_create_file(psc_i2s->dev, &dev_attr_playback_underrun);
831 if (rc)
832 dev_info(psc_i2s->dev, "error creating sysfs files\n");
833
834 snd_soc_register_platform(&psc_i2s_pcm_soc_platform);
835
836 /* Tell the ASoC OF helpers about it */
837 of_snd_soc_register_platform(&psc_i2s_pcm_soc_platform, op->node,
838 &psc_i2s->dai);
839 204
840 return 0; 205 return 0;
206
841} 207}
842 208
843static int __devexit psc_i2s_of_remove(struct of_device *op) 209static int __devexit psc_i2s_of_remove(struct of_device *op)
844{ 210{
845 struct psc_i2s *psc_i2s = dev_get_drvdata(&op->dev); 211 return mpc5200_audio_dma_destroy(op);
846
847 dev_dbg(&op->dev, "psc_i2s_remove()\n");
848
849 snd_soc_unregister_platform(&psc_i2s_pcm_soc_platform);
850
851 bcom_gen_bd_rx_release(psc_i2s->capture.bcom_task);
852 bcom_gen_bd_tx_release(psc_i2s->playback.bcom_task);
853
854 iounmap(psc_i2s->psc_regs);
855 iounmap(psc_i2s->fifo_regs);
856 kfree(psc_i2s);
857 dev_set_drvdata(&op->dev, NULL);
858
859 return 0;
860} 212}
861 213
862/* Match table for of_platform binding */ 214/* Match table for of_platform binding */
863static struct of_device_id psc_i2s_match[] __devinitdata = { 215static struct of_device_id psc_i2s_match[] __devinitdata = {
864 { .compatible = "fsl,mpc5200-psc-i2s", }, 216 { .compatible = "fsl,mpc5200-psc-i2s", },
217 { .compatible = "fsl,mpc5200b-psc-i2s", },
865 {} 218 {}
866}; 219};
867MODULE_DEVICE_TABLE(of, psc_i2s_match); 220MODULE_DEVICE_TABLE(of, psc_i2s_match);
@@ -892,4 +245,7 @@ static void __exit psc_i2s_exit(void)
892} 245}
893module_exit(psc_i2s_exit); 246module_exit(psc_i2s_exit);
894 247
248MODULE_AUTHOR("Grant Likely <grant.likely@secretlab.ca>");
249MODULE_DESCRIPTION("Freescale MPC5200 PSC in I2S mode ASoC Driver");
250MODULE_LICENSE("GPL");
895 251
diff --git a/sound/soc/fsl/mpc5200_psc_i2s.h b/sound/soc/fsl/mpc5200_psc_i2s.h
new file mode 100644
index 000000000000..ce55e070fdf3
--- /dev/null
+++ b/sound/soc/fsl/mpc5200_psc_i2s.h
@@ -0,0 +1,12 @@
1/*
2 * Freescale MPC5200 PSC in I2S mode
3 * ALSA SoC Digital Audio Interface (DAI) driver
4 *
5 */
6
7#ifndef __SOUND_SOC_FSL_MPC52xx_PSC_I2S_H__
8#define __SOUND_SOC_FSL_MPC52xx_PSC_I2S_H__
9
10extern struct snd_soc_dai psc_i2s_dai[];
11
12#endif /* __SOUND_SOC_FSL_MPC52xx_PSC_I2S_H__ */
diff --git a/sound/soc/fsl/pcm030-audio-fabric.c b/sound/soc/fsl/pcm030-audio-fabric.c
new file mode 100644
index 000000000000..8766f7a3893d
--- /dev/null
+++ b/sound/soc/fsl/pcm030-audio-fabric.c
@@ -0,0 +1,90 @@
1/*
2 * Phytec pcm030 driver for the PSC of the Freescale MPC52xx
3 * configured as AC97 interface
4 *
5 * Copyright 2008 Jon Smirl, Digispeaker
6 * Author: Jon Smirl <jonsmirl@gmail.com>
7 *
8 * This file is licensed under the terms of the GNU General Public License
9 * version 2. This program is licensed "as is" without any warranty of any
10 * kind, whether express or implied.
11 */
12
13#include <linux/init.h>
14#include <linux/module.h>
15#include <linux/interrupt.h>
16#include <linux/device.h>
17#include <linux/delay.h>
18#include <linux/of_device.h>
19#include <linux/of_platform.h>
20#include <linux/dma-mapping.h>
21
22#include <sound/core.h>
23#include <sound/pcm.h>
24#include <sound/pcm_params.h>
25#include <sound/initval.h>
26#include <sound/soc.h>
27#include <sound/soc-of-simple.h>
28
29#include "mpc5200_dma.h"
30#include "mpc5200_psc_ac97.h"
31#include "../codecs/wm9712.h"
32
33static struct snd_soc_device device;
34static struct snd_soc_card card;
35
36static struct snd_soc_dai_link pcm030_fabric_dai[] = {
37{
38 .name = "AC97",
39 .stream_name = "AC97 Analog",
40 .codec_dai = &wm9712_dai[WM9712_DAI_AC97_HIFI],
41 .cpu_dai = &psc_ac97_dai[MPC5200_AC97_NORMAL],
42},
43{
44 .name = "AC97",
45 .stream_name = "AC97 IEC958",
46 .codec_dai = &wm9712_dai[WM9712_DAI_AC97_AUX],
47 .cpu_dai = &psc_ac97_dai[MPC5200_AC97_SPDIF],
48},
49};
50
51static __init int pcm030_fabric_init(void)
52{
53 struct platform_device *pdev;
54 int rc;
55
56 if (!machine_is_compatible("phytec,pcm030"))
57 return -ENODEV;
58
59 card.platform = &mpc5200_audio_dma_platform;
60 card.name = "pcm030";
61 card.dai_link = pcm030_fabric_dai;
62 card.num_links = ARRAY_SIZE(pcm030_fabric_dai);
63
64 device.card = &card;
65 device.codec_dev = &soc_codec_dev_wm9712;
66
67 pdev = platform_device_alloc("soc-audio", 1);
68 if (!pdev) {
69 pr_err("pcm030_fabric_init: platform_device_alloc() failed\n");
70 return -ENODEV;
71 }
72
73 platform_set_drvdata(pdev, &device);
74 device.dev = &pdev->dev;
75
76 rc = platform_device_add(pdev);
77 if (rc) {
78 pr_err("pcm030_fabric_init: platform_device_add() failed\n");
79 return -ENODEV;
80 }
81 return 0;
82}
83
84module_init(pcm030_fabric_init);
85
86
87MODULE_AUTHOR("Jon Smirl <jonsmirl@gmail.com>");
88MODULE_DESCRIPTION(DRV_NAME ": mpc5200 pcm030 fabric driver");
89MODULE_LICENSE("GPL");
90
diff --git a/sound/soc/omap/Kconfig b/sound/soc/omap/Kconfig
index 675732e724d5..2dee9839be86 100644
--- a/sound/soc/omap/Kconfig
+++ b/sound/soc/omap/Kconfig
@@ -15,6 +15,14 @@ config SND_OMAP_SOC_N810
15 help 15 help
16 Say Y if you want to add support for SoC audio on Nokia N810. 16 Say Y if you want to add support for SoC audio on Nokia N810.
17 17
18config SND_OMAP_SOC_AMS_DELTA
19 tristate "SoC Audio support for Amstrad E3 (Delta) videophone"
20 depends on SND_OMAP_SOC && MACH_AMS_DELTA
21 select SND_OMAP_SOC_MCBSP
22 select SND_SOC_CX20442
23 help
24 Say Y if you want to add support for SoC audio on Amstrad Delta.
25
18config SND_OMAP_SOC_OSK5912 26config SND_OMAP_SOC_OSK5912
19 tristate "SoC Audio support for omap osk5912" 27 tristate "SoC Audio support for omap osk5912"
20 depends on SND_OMAP_SOC && MACH_OMAP_OSK && I2C 28 depends on SND_OMAP_SOC && MACH_OMAP_OSK && I2C
@@ -39,6 +47,14 @@ config SND_OMAP_SOC_OMAP2EVM
39 help 47 help
40 Say Y if you want to add support for SoC audio on the omap2evm board. 48 Say Y if you want to add support for SoC audio on the omap2evm board.
41 49
50config SND_OMAP_SOC_OMAP3EVM
51 tristate "SoC Audio support for OMAP3EVM board"
52 depends on TWL4030_CORE && SND_OMAP_SOC && MACH_OMAP3EVM
53 select SND_OMAP_SOC_MCBSP
54 select SND_SOC_TWL4030
55 help
56 Say Y if you want to add support for SoC audio on the omap3evm board.
57
42config SND_OMAP_SOC_SDP3430 58config SND_OMAP_SOC_SDP3430
43 tristate "SoC Audio support for Texas Instruments SDP3430" 59 tristate "SoC Audio support for Texas Instruments SDP3430"
44 depends on TWL4030_CORE && SND_OMAP_SOC && MACH_OMAP_3430SDP 60 depends on TWL4030_CORE && SND_OMAP_SOC && MACH_OMAP_3430SDP
@@ -64,4 +80,11 @@ config SND_OMAP_SOC_OMAP3_BEAGLE
64 help 80 help
65 Say Y if you want to add support for SoC audio on the Beagleboard. 81 Say Y if you want to add support for SoC audio on the Beagleboard.
66 82
83config SND_OMAP_SOC_ZOOM2
84 tristate "SoC Audio support for Zoom2"
85 depends on TWL4030_CORE && SND_OMAP_SOC && MACH_OMAP_ZOOM2
86 select SND_OMAP_SOC_MCBSP
87 select SND_SOC_TWL4030
88 help
89 Say Y if you want to add support for Soc audio on Zoom2 board.
67 90
diff --git a/sound/soc/omap/Makefile b/sound/soc/omap/Makefile
index 0c9e4ac37660..02d69471dcb5 100644
--- a/sound/soc/omap/Makefile
+++ b/sound/soc/omap/Makefile
@@ -7,17 +7,23 @@ obj-$(CONFIG_SND_OMAP_SOC_MCBSP) += snd-soc-omap-mcbsp.o
7 7
8# OMAP Machine Support 8# OMAP Machine Support
9snd-soc-n810-objs := n810.o 9snd-soc-n810-objs := n810.o
10snd-soc-ams-delta-objs := ams-delta.o
10snd-soc-osk5912-objs := osk5912.o 11snd-soc-osk5912-objs := osk5912.o
11snd-soc-overo-objs := overo.o 12snd-soc-overo-objs := overo.o
12snd-soc-omap2evm-objs := omap2evm.o 13snd-soc-omap2evm-objs := omap2evm.o
14snd-soc-omap3evm-objs := omap3evm.o
13snd-soc-sdp3430-objs := sdp3430.o 15snd-soc-sdp3430-objs := sdp3430.o
14snd-soc-omap3pandora-objs := omap3pandora.o 16snd-soc-omap3pandora-objs := omap3pandora.o
15snd-soc-omap3beagle-objs := omap3beagle.o 17snd-soc-omap3beagle-objs := omap3beagle.o
18snd-soc-zoom2-objs := zoom2.o
16 19
17obj-$(CONFIG_SND_OMAP_SOC_N810) += snd-soc-n810.o 20obj-$(CONFIG_SND_OMAP_SOC_N810) += snd-soc-n810.o
21obj-$(CONFIG_SND_OMAP_SOC_AMS_DELTA) += snd-soc-ams-delta.o
18obj-$(CONFIG_SND_OMAP_SOC_OSK5912) += snd-soc-osk5912.o 22obj-$(CONFIG_SND_OMAP_SOC_OSK5912) += snd-soc-osk5912.o
19obj-$(CONFIG_SND_OMAP_SOC_OVERO) += snd-soc-overo.o 23obj-$(CONFIG_SND_OMAP_SOC_OVERO) += snd-soc-overo.o
20obj-$(CONFIG_MACH_OMAP2EVM) += snd-soc-omap2evm.o 24obj-$(CONFIG_MACH_OMAP2EVM) += snd-soc-omap2evm.o
25obj-$(CONFIG_MACH_OMAP3EVM) += snd-soc-omap3evm.o
21obj-$(CONFIG_SND_OMAP_SOC_SDP3430) += snd-soc-sdp3430.o 26obj-$(CONFIG_SND_OMAP_SOC_SDP3430) += snd-soc-sdp3430.o
22obj-$(CONFIG_SND_OMAP_SOC_OMAP3_PANDORA) += snd-soc-omap3pandora.o 27obj-$(CONFIG_SND_OMAP_SOC_OMAP3_PANDORA) += snd-soc-omap3pandora.o
23obj-$(CONFIG_SND_OMAP_SOC_OMAP3_BEAGLE) += snd-soc-omap3beagle.o 28obj-$(CONFIG_SND_OMAP_SOC_OMAP3_BEAGLE) += snd-soc-omap3beagle.o
29obj-$(CONFIG_SND_OMAP_SOC_ZOOM2) += snd-soc-zoom2.o
diff --git a/sound/soc/omap/ams-delta.c b/sound/soc/omap/ams-delta.c
new file mode 100644
index 000000000000..5a5166ac7279
--- /dev/null
+++ b/sound/soc/omap/ams-delta.c
@@ -0,0 +1,646 @@
1/*
2 * ams-delta.c -- SoC audio for Amstrad E3 (Delta) videophone
3 *
4 * Copyright (C) 2009 Janusz Krzysztofik <jkrzyszt@tis.icnet.pl>
5 *
6 * Initially based on sound/soc/omap/osk5912.x
7 * Copyright (C) 2008 Mistral Solutions
8 *
9 * This program is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU General Public License
11 * version 2 as published by the Free Software Foundation.
12 *
13 * This program is distributed in the hope that it will be useful, but
14 * WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
21 * 02110-1301 USA
22 *
23 */
24
25#include <linux/gpio.h>
26#include <linux/spinlock.h>
27#include <linux/tty.h>
28
29#include <sound/soc-dapm.h>
30#include <sound/jack.h>
31
32#include <asm/mach-types.h>
33
34#include <mach/board-ams-delta.h>
35#include <mach/mcbsp.h>
36
37#include "omap-mcbsp.h"
38#include "omap-pcm.h"
39#include "../codecs/cx20442.h"
40
41
42/* Board specific DAPM widgets */
43 const struct snd_soc_dapm_widget ams_delta_dapm_widgets[] = {
44 /* Handset */
45 SND_SOC_DAPM_MIC("Mouthpiece", NULL),
46 SND_SOC_DAPM_HP("Earpiece", NULL),
47 /* Handsfree/Speakerphone */
48 SND_SOC_DAPM_MIC("Microphone", NULL),
49 SND_SOC_DAPM_SPK("Speaker", NULL),
50};
51
52/* How they are connected to codec pins */
53static const struct snd_soc_dapm_route ams_delta_audio_map[] = {
54 {"TELIN", NULL, "Mouthpiece"},
55 {"Earpiece", NULL, "TELOUT"},
56
57 {"MIC", NULL, "Microphone"},
58 {"Speaker", NULL, "SPKOUT"},
59};
60
61/*
62 * Controls, functional after the modem line discipline is activated.
63 */
64
65/* Virtual switch: audio input/output constellations */
66static const char *ams_delta_audio_mode[] =
67 {"Mixed", "Handset", "Handsfree", "Speakerphone"};
68
69/* Selection <-> pin translation */
70#define AMS_DELTA_MOUTHPIECE 0
71#define AMS_DELTA_EARPIECE 1
72#define AMS_DELTA_MICROPHONE 2
73#define AMS_DELTA_SPEAKER 3
74#define AMS_DELTA_AGC 4
75
76#define AMS_DELTA_MIXED ((1 << AMS_DELTA_EARPIECE) | \
77 (1 << AMS_DELTA_MICROPHONE))
78#define AMS_DELTA_HANDSET ((1 << AMS_DELTA_MOUTHPIECE) | \
79 (1 << AMS_DELTA_EARPIECE))
80#define AMS_DELTA_HANDSFREE ((1 << AMS_DELTA_MICROPHONE) | \
81 (1 << AMS_DELTA_SPEAKER))
82#define AMS_DELTA_SPEAKERPHONE (AMS_DELTA_HANDSFREE | (1 << AMS_DELTA_AGC))
83
84unsigned short ams_delta_audio_mode_pins[] = {
85 AMS_DELTA_MIXED,
86 AMS_DELTA_HANDSET,
87 AMS_DELTA_HANDSFREE,
88 AMS_DELTA_SPEAKERPHONE,
89};
90
91static unsigned short ams_delta_audio_agc;
92
93static int ams_delta_set_audio_mode(struct snd_kcontrol *kcontrol,
94 struct snd_ctl_elem_value *ucontrol)
95{
96 struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
97 struct soc_enum *control = (struct soc_enum *)kcontrol->private_value;
98 unsigned short pins;
99 int pin, changed = 0;
100
101 /* Refuse any mode changes if we are not able to control the codec. */
102 if (!codec->control_data)
103 return -EUNATCH;
104
105 if (ucontrol->value.enumerated.item[0] >= control->max)
106 return -EINVAL;
107
108 mutex_lock(&codec->mutex);
109
110 /* Translate selection to bitmap */
111 pins = ams_delta_audio_mode_pins[ucontrol->value.enumerated.item[0]];
112
113 /* Setup pins after corresponding bits if changed */
114 pin = !!(pins & (1 << AMS_DELTA_MOUTHPIECE));
115 if (pin != snd_soc_dapm_get_pin_status(codec, "Mouthpiece")) {
116 changed = 1;
117 if (pin)
118 snd_soc_dapm_enable_pin(codec, "Mouthpiece");
119 else
120 snd_soc_dapm_disable_pin(codec, "Mouthpiece");
121 }
122 pin = !!(pins & (1 << AMS_DELTA_EARPIECE));
123 if (pin != snd_soc_dapm_get_pin_status(codec, "Earpiece")) {
124 changed = 1;
125 if (pin)
126 snd_soc_dapm_enable_pin(codec, "Earpiece");
127 else
128 snd_soc_dapm_disable_pin(codec, "Earpiece");
129 }
130 pin = !!(pins & (1 << AMS_DELTA_MICROPHONE));
131 if (pin != snd_soc_dapm_get_pin_status(codec, "Microphone")) {
132 changed = 1;
133 if (pin)
134 snd_soc_dapm_enable_pin(codec, "Microphone");
135 else
136 snd_soc_dapm_disable_pin(codec, "Microphone");
137 }
138 pin = !!(pins & (1 << AMS_DELTA_SPEAKER));
139 if (pin != snd_soc_dapm_get_pin_status(codec, "Speaker")) {
140 changed = 1;
141 if (pin)
142 snd_soc_dapm_enable_pin(codec, "Speaker");
143 else
144 snd_soc_dapm_disable_pin(codec, "Speaker");
145 }
146 pin = !!(pins & (1 << AMS_DELTA_AGC));
147 if (pin != ams_delta_audio_agc) {
148 ams_delta_audio_agc = pin;
149 changed = 1;
150 if (pin)
151 snd_soc_dapm_enable_pin(codec, "AGCIN");
152 else
153 snd_soc_dapm_disable_pin(codec, "AGCIN");
154 }
155 if (changed)
156 snd_soc_dapm_sync(codec);
157
158 mutex_unlock(&codec->mutex);
159
160 return changed;
161}
162
163static int ams_delta_get_audio_mode(struct snd_kcontrol *kcontrol,
164 struct snd_ctl_elem_value *ucontrol)
165{
166 struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
167 unsigned short pins, mode;
168
169 pins = ((snd_soc_dapm_get_pin_status(codec, "Mouthpiece") <<
170 AMS_DELTA_MOUTHPIECE) |
171 (snd_soc_dapm_get_pin_status(codec, "Earpiece") <<
172 AMS_DELTA_EARPIECE));
173 if (pins)
174 pins |= (snd_soc_dapm_get_pin_status(codec, "Microphone") <<
175 AMS_DELTA_MICROPHONE);
176 else
177 pins = ((snd_soc_dapm_get_pin_status(codec, "Microphone") <<
178 AMS_DELTA_MICROPHONE) |
179 (snd_soc_dapm_get_pin_status(codec, "Speaker") <<
180 AMS_DELTA_SPEAKER) |
181 (ams_delta_audio_agc << AMS_DELTA_AGC));
182
183 for (mode = 0; mode < ARRAY_SIZE(ams_delta_audio_mode); mode++)
184 if (pins == ams_delta_audio_mode_pins[mode])
185 break;
186
187 if (mode >= ARRAY_SIZE(ams_delta_audio_mode))
188 return -EINVAL;
189
190 ucontrol->value.enumerated.item[0] = mode;
191
192 return 0;
193}
194
195static const struct soc_enum ams_delta_audio_enum[] = {
196 SOC_ENUM_SINGLE_EXT(ARRAY_SIZE(ams_delta_audio_mode),
197 ams_delta_audio_mode),
198};
199
200static const struct snd_kcontrol_new ams_delta_audio_controls[] = {
201 SOC_ENUM_EXT("Audio Mode", ams_delta_audio_enum[0],
202 ams_delta_get_audio_mode, ams_delta_set_audio_mode),
203};
204
205/* Hook switch */
206static struct snd_soc_jack ams_delta_hook_switch;
207static struct snd_soc_jack_gpio ams_delta_hook_switch_gpios[] = {
208 {
209 .gpio = 4,
210 .name = "hook_switch",
211 .report = SND_JACK_HEADSET,
212 .invert = 1,
213 .debounce_time = 150,
214 }
215};
216
217/* After we are able to control the codec over the modem,
218 * the hook switch can be used for dynamic DAPM reconfiguration. */
219static struct snd_soc_jack_pin ams_delta_hook_switch_pins[] = {
220 /* Handset */
221 {
222 .pin = "Mouthpiece",
223 .mask = SND_JACK_MICROPHONE,
224 },
225 {
226 .pin = "Earpiece",
227 .mask = SND_JACK_HEADPHONE,
228 },
229 /* Handsfree */
230 {
231 .pin = "Microphone",
232 .mask = SND_JACK_MICROPHONE,
233 .invert = 1,
234 },
235 {
236 .pin = "Speaker",
237 .mask = SND_JACK_HEADPHONE,
238 .invert = 1,
239 },
240};
241
242
243/*
244 * Modem line discipline, required for making above controls functional.
245 * Activated from userspace with ldattach, possibly invoked from udev rule.
246 */
247
248/* To actually apply any modem controlled configuration changes to the codec,
249 * we must connect codec DAI pins to the modem for a moment. Be carefull not
250 * to interfere with our digital mute function that shares the same hardware. */
251static struct timer_list cx81801_timer;
252static bool cx81801_cmd_pending;
253static bool ams_delta_muted;
254static DEFINE_SPINLOCK(ams_delta_lock);
255
256static void cx81801_timeout(unsigned long data)
257{
258 int muted;
259
260 spin_lock(&ams_delta_lock);
261 cx81801_cmd_pending = 0;
262 muted = ams_delta_muted;
263 spin_unlock(&ams_delta_lock);
264
265 /* Reconnect the codec DAI back from the modem to the CPU DAI
266 * only if digital mute still off */
267 if (!muted)
268 ams_delta_latch2_write(AMS_DELTA_LATCH2_MODEM_CODEC, 0);
269}
270
271/* Line discipline .open() */
272static int cx81801_open(struct tty_struct *tty)
273{
274 return v253_ops.open(tty);
275}
276
277/* Line discipline .close() */
278static void cx81801_close(struct tty_struct *tty)
279{
280 struct snd_soc_codec *codec = tty->disc_data;
281
282 del_timer_sync(&cx81801_timer);
283
284 v253_ops.close(tty);
285
286 /* Prevent the hook switch from further changing the DAPM pins */
287 INIT_LIST_HEAD(&ams_delta_hook_switch.pins);
288
289 /* Revert back to default audio input/output constellation */
290 snd_soc_dapm_disable_pin(codec, "Mouthpiece");
291 snd_soc_dapm_enable_pin(codec, "Earpiece");
292 snd_soc_dapm_enable_pin(codec, "Microphone");
293 snd_soc_dapm_disable_pin(codec, "Speaker");
294 snd_soc_dapm_disable_pin(codec, "AGCIN");
295 snd_soc_dapm_sync(codec);
296}
297
298/* Line discipline .hangup() */
299static int cx81801_hangup(struct tty_struct *tty)
300{
301 cx81801_close(tty);
302 return 0;
303}
304
305/* Line discipline .recieve_buf() */
306static void cx81801_receive(struct tty_struct *tty,
307 const unsigned char *cp, char *fp, int count)
308{
309 struct snd_soc_codec *codec = tty->disc_data;
310 const unsigned char *c;
311 int apply, ret;
312
313 if (!codec->control_data) {
314 /* First modem response, complete setup procedure */
315
316 /* Initialize timer used for config pulse generation */
317 setup_timer(&cx81801_timer, cx81801_timeout, 0);
318
319 v253_ops.receive_buf(tty, cp, fp, count);
320
321 /* Link hook switch to DAPM pins */
322 ret = snd_soc_jack_add_pins(&ams_delta_hook_switch,
323 ARRAY_SIZE(ams_delta_hook_switch_pins),
324 ams_delta_hook_switch_pins);
325 if (ret)
326 dev_warn(codec->socdev->card->dev,
327 "Failed to link hook switch to DAPM pins, "
328 "will continue with hook switch unlinked.\n");
329
330 return;
331 }
332
333 v253_ops.receive_buf(tty, cp, fp, count);
334
335 for (c = &cp[count - 1]; c >= cp; c--) {
336 if (*c != '\r')
337 continue;
338 /* Complete modem response received, apply config to codec */
339
340 spin_lock_bh(&ams_delta_lock);
341 mod_timer(&cx81801_timer, jiffies + msecs_to_jiffies(150));
342 apply = !ams_delta_muted && !cx81801_cmd_pending;
343 cx81801_cmd_pending = 1;
344 spin_unlock_bh(&ams_delta_lock);
345
346 /* Apply config pulse by connecting the codec to the modem
347 * if not already done */
348 if (apply)
349 ams_delta_latch2_write(AMS_DELTA_LATCH2_MODEM_CODEC,
350 AMS_DELTA_LATCH2_MODEM_CODEC);
351 break;
352 }
353}
354
355/* Line discipline .write_wakeup() */
356static void cx81801_wakeup(struct tty_struct *tty)
357{
358 v253_ops.write_wakeup(tty);
359}
360
361static struct tty_ldisc_ops cx81801_ops = {
362 .magic = TTY_LDISC_MAGIC,
363 .name = "cx81801",
364 .owner = THIS_MODULE,
365 .open = cx81801_open,
366 .close = cx81801_close,
367 .hangup = cx81801_hangup,
368 .receive_buf = cx81801_receive,
369 .write_wakeup = cx81801_wakeup,
370};
371
372
373/*
374 * Even if not very usefull, the sound card can still work without any of the
375 * above functonality activated. You can still control its audio input/output
376 * constellation and speakerphone gain from userspace by issueing AT commands
377 * over the modem port.
378 */
379
380static int ams_delta_hw_params(struct snd_pcm_substream *substream,
381 struct snd_pcm_hw_params *params)
382{
383 struct snd_soc_pcm_runtime *rtd = substream->private_data;
384
385 /* Set cpu DAI configuration */
386 return snd_soc_dai_set_fmt(rtd->dai->cpu_dai,
387 SND_SOC_DAIFMT_DSP_A |
388 SND_SOC_DAIFMT_NB_NF |
389 SND_SOC_DAIFMT_CBM_CFM);
390}
391
392static struct snd_soc_ops ams_delta_ops = {
393 .hw_params = ams_delta_hw_params,
394};
395
396
397/* Board specific codec bias level control */
398static int ams_delta_set_bias_level(struct snd_soc_card *card,
399 enum snd_soc_bias_level level)
400{
401 struct snd_soc_codec *codec = card->codec;
402
403 switch (level) {
404 case SND_SOC_BIAS_ON:
405 case SND_SOC_BIAS_PREPARE:
406 case SND_SOC_BIAS_STANDBY:
407 if (codec->bias_level == SND_SOC_BIAS_OFF)
408 ams_delta_latch2_write(AMS_DELTA_LATCH2_MODEM_NRESET,
409 AMS_DELTA_LATCH2_MODEM_NRESET);
410 break;
411 case SND_SOC_BIAS_OFF:
412 if (codec->bias_level != SND_SOC_BIAS_OFF)
413 ams_delta_latch2_write(AMS_DELTA_LATCH2_MODEM_NRESET,
414 0);
415 }
416 codec->bias_level = level;
417
418 return 0;
419}
420
421/* Digital mute implemented using modem/CPU multiplexer.
422 * Shares hardware with codec config pulse generation */
423static bool ams_delta_muted = 1;
424
425static int ams_delta_digital_mute(struct snd_soc_dai *dai, int mute)
426{
427 int apply;
428
429 if (ams_delta_muted == mute)
430 return 0;
431
432 spin_lock_bh(&ams_delta_lock);
433 ams_delta_muted = mute;
434 apply = !cx81801_cmd_pending;
435 spin_unlock_bh(&ams_delta_lock);
436
437 if (apply)
438 ams_delta_latch2_write(AMS_DELTA_LATCH2_MODEM_CODEC,
439 mute ? AMS_DELTA_LATCH2_MODEM_CODEC : 0);
440 return 0;
441}
442
443/* Our codec DAI probably doesn't have its own .ops structure */
444static struct snd_soc_dai_ops ams_delta_dai_ops = {
445 .digital_mute = ams_delta_digital_mute,
446};
447
448/* Will be used if the codec ever has its own digital_mute function */
449static int ams_delta_startup(struct snd_pcm_substream *substream)
450{
451 return ams_delta_digital_mute(NULL, 0);
452}
453
454static void ams_delta_shutdown(struct snd_pcm_substream *substream)
455{
456 ams_delta_digital_mute(NULL, 1);
457}
458
459
460/*
461 * Card initialization
462 */
463
464static int ams_delta_cx20442_init(struct snd_soc_codec *codec)
465{
466 struct snd_soc_dai *codec_dai = codec->dai;
467 struct snd_soc_card *card = codec->socdev->card;
468 int ret;
469 /* Codec is ready, now add/activate board specific controls */
470
471 /* Set up digital mute if not provided by the codec */
472 if (!codec_dai->ops) {
473 codec_dai->ops = &ams_delta_dai_ops;
474 } else if (!codec_dai->ops->digital_mute) {
475 codec_dai->ops->digital_mute = ams_delta_digital_mute;
476 } else {
477 ams_delta_ops.startup = ams_delta_startup;
478 ams_delta_ops.shutdown = ams_delta_shutdown;
479 }
480
481 /* Set codec bias level */
482 ams_delta_set_bias_level(card, SND_SOC_BIAS_STANDBY);
483
484 /* Add hook switch - can be used to control the codec from userspace
485 * even if line discipline fails */
486 ret = snd_soc_jack_new(card, "hook_switch",
487 SND_JACK_HEADSET, &ams_delta_hook_switch);
488 if (ret)
489 dev_warn(card->dev,
490 "Failed to allocate resources for hook switch, "
491 "will continue without one.\n");
492 else {
493 ret = snd_soc_jack_add_gpios(&ams_delta_hook_switch,
494 ARRAY_SIZE(ams_delta_hook_switch_gpios),
495 ams_delta_hook_switch_gpios);
496 if (ret)
497 dev_warn(card->dev,
498 "Failed to set up hook switch GPIO line, "
499 "will continue with hook switch inactive.\n");
500 }
501
502 /* Register optional line discipline for over the modem control */
503 ret = tty_register_ldisc(N_V253, &cx81801_ops);
504 if (ret) {
505 dev_warn(card->dev,
506 "Failed to register line discipline, "
507 "will continue without any controls.\n");
508 return 0;
509 }
510
511 /* Add board specific DAPM widgets and routes */
512 ret = snd_soc_dapm_new_controls(codec, ams_delta_dapm_widgets,
513 ARRAY_SIZE(ams_delta_dapm_widgets));
514 if (ret) {
515 dev_warn(card->dev,
516 "Failed to register DAPM controls, "
517 "will continue without any.\n");
518 return 0;
519 }
520
521 ret = snd_soc_dapm_add_routes(codec, ams_delta_audio_map,
522 ARRAY_SIZE(ams_delta_audio_map));
523 if (ret) {
524 dev_warn(card->dev,
525 "Failed to set up DAPM routes, "
526 "will continue with codec default map.\n");
527 return 0;
528 }
529
530 /* Set up initial pin constellation */
531 snd_soc_dapm_disable_pin(codec, "Mouthpiece");
532 snd_soc_dapm_enable_pin(codec, "Earpiece");
533 snd_soc_dapm_enable_pin(codec, "Microphone");
534 snd_soc_dapm_disable_pin(codec, "Speaker");
535 snd_soc_dapm_disable_pin(codec, "AGCIN");
536 snd_soc_dapm_disable_pin(codec, "AGCOUT");
537 snd_soc_dapm_sync(codec);
538
539 /* Add virtual switch */
540 ret = snd_soc_add_controls(codec, ams_delta_audio_controls,
541 ARRAY_SIZE(ams_delta_audio_controls));
542 if (ret)
543 dev_warn(card->dev,
544 "Failed to register audio mode control, "
545 "will continue without it.\n");
546
547 return 0;
548}
549
550/* DAI glue - connects codec <--> CPU */
551static struct snd_soc_dai_link ams_delta_dai_link = {
552 .name = "CX20442",
553 .stream_name = "CX20442",
554 .cpu_dai = &omap_mcbsp_dai[0],
555 .codec_dai = &cx20442_dai,
556 .init = ams_delta_cx20442_init,
557 .ops = &ams_delta_ops,
558};
559
560/* Audio card driver */
561static struct snd_soc_card ams_delta_audio_card = {
562 .name = "AMS_DELTA",
563 .platform = &omap_soc_platform,
564 .dai_link = &ams_delta_dai_link,
565 .num_links = 1,
566 .set_bias_level = ams_delta_set_bias_level,
567};
568
569/* Audio subsystem */
570static struct snd_soc_device ams_delta_snd_soc_device = {
571 .card = &ams_delta_audio_card,
572 .codec_dev = &cx20442_codec_dev,
573};
574
575/* Module init/exit */
576static struct platform_device *ams_delta_audio_platform_device;
577static struct platform_device *cx20442_platform_device;
578
579static int __init ams_delta_module_init(void)
580{
581 int ret;
582
583 if (!(machine_is_ams_delta()))
584 return -ENODEV;
585
586 ams_delta_audio_platform_device =
587 platform_device_alloc("soc-audio", -1);
588 if (!ams_delta_audio_platform_device)
589 return -ENOMEM;
590
591 platform_set_drvdata(ams_delta_audio_platform_device,
592 &ams_delta_snd_soc_device);
593 ams_delta_snd_soc_device.dev = &ams_delta_audio_platform_device->dev;
594 *(unsigned int *)ams_delta_dai_link.cpu_dai->private_data = OMAP_MCBSP1;
595
596 ret = platform_device_add(ams_delta_audio_platform_device);
597 if (ret)
598 goto err;
599
600 /*
601 * Codec platform device could be registered from elsewhere (board?),
602 * but I do it here as it makes sense only if used with the card.
603 */
604 cx20442_platform_device = platform_device_register_simple("cx20442",
605 -1, NULL, 0);
606 return 0;
607err:
608 platform_device_put(ams_delta_audio_platform_device);
609 return ret;
610}
611module_init(ams_delta_module_init);
612
613static void __exit ams_delta_module_exit(void)
614{
615 struct snd_soc_codec *codec;
616 struct tty_struct *tty;
617
618 if (ams_delta_audio_card.codec) {
619 codec = ams_delta_audio_card.codec;
620
621 if (codec->control_data) {
622 tty = codec->control_data;
623
624 tty_hangup(tty);
625 }
626 }
627
628 if (tty_unregister_ldisc(N_V253) != 0)
629 dev_warn(&ams_delta_audio_platform_device->dev,
630 "failed to unregister V253 line discipline\n");
631
632 snd_soc_jack_free_gpios(&ams_delta_hook_switch,
633 ARRAY_SIZE(ams_delta_hook_switch_gpios),
634 ams_delta_hook_switch_gpios);
635
636 /* Keep modem power on */
637 ams_delta_set_bias_level(&ams_delta_audio_card, SND_SOC_BIAS_STANDBY);
638
639 platform_device_unregister(cx20442_platform_device);
640 platform_device_unregister(ams_delta_audio_platform_device);
641}
642module_exit(ams_delta_module_exit);
643
644MODULE_AUTHOR("Janusz Krzysztofik <jkrzyszt@tis.icnet.pl>");
645MODULE_DESCRIPTION("ALSA SoC driver for Amstrad E3 (Delta) videophone");
646MODULE_LICENSE("GPL");
diff --git a/sound/soc/omap/n810.c b/sound/soc/omap/n810.c
index 91ef17992de5..b60b1dfbc435 100644
--- a/sound/soc/omap/n810.c
+++ b/sound/soc/omap/n810.c
@@ -383,10 +383,9 @@ static int __init n810_soc_init(void)
383 clk_set_parent(sys_clkout2_src, func96m_clk); 383 clk_set_parent(sys_clkout2_src, func96m_clk);
384 clk_set_rate(sys_clkout2, 12000000); 384 clk_set_rate(sys_clkout2, 12000000);
385 385
386 if (gpio_request(N810_HEADSET_AMP_GPIO, "hs_amp") < 0) 386 BUG_ON((gpio_request(N810_HEADSET_AMP_GPIO, "hs_amp") < 0) ||
387 BUG(); 387 (gpio_request(N810_SPEAKER_AMP_GPIO, "spk_amp") < 0));
388 if (gpio_request(N810_SPEAKER_AMP_GPIO, "spk_amp") < 0) 388
389 BUG();
390 gpio_direction_output(N810_HEADSET_AMP_GPIO, 0); 389 gpio_direction_output(N810_HEADSET_AMP_GPIO, 0);
391 gpio_direction_output(N810_SPEAKER_AMP_GPIO, 0); 390 gpio_direction_output(N810_SPEAKER_AMP_GPIO, 0);
392 391
diff --git a/sound/soc/omap/omap-mcbsp.c b/sound/soc/omap/omap-mcbsp.c
index 912614283848..6a837ffd5d0b 100644
--- a/sound/soc/omap/omap-mcbsp.c
+++ b/sound/soc/omap/omap-mcbsp.c
@@ -183,21 +183,21 @@ static int omap_mcbsp_dai_trigger(struct snd_pcm_substream *substream, int cmd,
183 struct snd_soc_pcm_runtime *rtd = substream->private_data; 183 struct snd_soc_pcm_runtime *rtd = substream->private_data;
184 struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai; 184 struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai;
185 struct omap_mcbsp_data *mcbsp_data = to_mcbsp(cpu_dai->private_data); 185 struct omap_mcbsp_data *mcbsp_data = to_mcbsp(cpu_dai->private_data);
186 int err = 0; 186 int err = 0, play = (substream->stream == SNDRV_PCM_STREAM_PLAYBACK);
187 187
188 switch (cmd) { 188 switch (cmd) {
189 case SNDRV_PCM_TRIGGER_START: 189 case SNDRV_PCM_TRIGGER_START:
190 case SNDRV_PCM_TRIGGER_RESUME: 190 case SNDRV_PCM_TRIGGER_RESUME:
191 case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: 191 case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
192 if (!mcbsp_data->active++) 192 mcbsp_data->active++;
193 omap_mcbsp_start(mcbsp_data->bus_id); 193 omap_mcbsp_start(mcbsp_data->bus_id, play, !play);
194 break; 194 break;
195 195
196 case SNDRV_PCM_TRIGGER_STOP: 196 case SNDRV_PCM_TRIGGER_STOP:
197 case SNDRV_PCM_TRIGGER_SUSPEND: 197 case SNDRV_PCM_TRIGGER_SUSPEND:
198 case SNDRV_PCM_TRIGGER_PAUSE_PUSH: 198 case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
199 if (!--mcbsp_data->active) 199 omap_mcbsp_stop(mcbsp_data->bus_id, play, !play);
200 omap_mcbsp_stop(mcbsp_data->bus_id); 200 mcbsp_data->active--;
201 break; 201 break;
202 default: 202 default:
203 err = -EINVAL; 203 err = -EINVAL;
@@ -215,8 +215,9 @@ static int omap_mcbsp_dai_hw_params(struct snd_pcm_substream *substream,
215 struct omap_mcbsp_data *mcbsp_data = to_mcbsp(cpu_dai->private_data); 215 struct omap_mcbsp_data *mcbsp_data = to_mcbsp(cpu_dai->private_data);
216 struct omap_mcbsp_reg_cfg *regs = &mcbsp_data->regs; 216 struct omap_mcbsp_reg_cfg *regs = &mcbsp_data->regs;
217 int dma, bus_id = mcbsp_data->bus_id, id = cpu_dai->id; 217 int dma, bus_id = mcbsp_data->bus_id, id = cpu_dai->id;
218 int wlen, channels; 218 int wlen, channels, wpf;
219 unsigned long port; 219 unsigned long port;
220 unsigned int format;
220 221
221 if (cpu_class_is_omap1()) { 222 if (cpu_class_is_omap1()) {
222 dma = omap1_dma_reqs[bus_id][substream->stream]; 223 dma = omap1_dma_reqs[bus_id][substream->stream];
@@ -244,18 +245,24 @@ static int omap_mcbsp_dai_hw_params(struct snd_pcm_substream *substream,
244 return 0; 245 return 0;
245 } 246 }
246 247
247 channels = params_channels(params); 248 format = mcbsp_data->fmt & SND_SOC_DAIFMT_FORMAT_MASK;
249 wpf = channels = params_channels(params);
248 switch (channels) { 250 switch (channels) {
249 case 2: 251 case 2:
250 /* Use dual-phase frames */ 252 if (format == SND_SOC_DAIFMT_I2S) {
251 regs->rcr2 |= RPHASE; 253 /* Use dual-phase frames */
252 regs->xcr2 |= XPHASE; 254 regs->rcr2 |= RPHASE;
255 regs->xcr2 |= XPHASE;
256 /* Set 1 word per (McBSP) frame for phase1 and phase2 */
257 wpf--;
258 regs->rcr2 |= RFRLEN2(wpf - 1);
259 regs->xcr2 |= XFRLEN2(wpf - 1);
260 }
253 case 1: 261 case 1:
254 /* Set 1 word per (McBSP) frame */ 262 case 4:
255 regs->rcr2 |= RFRLEN2(1 - 1); 263 /* Set word per (McBSP) frame for phase1 */
256 regs->rcr1 |= RFRLEN1(1 - 1); 264 regs->rcr1 |= RFRLEN1(wpf - 1);
257 regs->xcr2 |= XFRLEN2(1 - 1); 265 regs->xcr1 |= XFRLEN1(wpf - 1);
258 regs->xcr1 |= XFRLEN1(1 - 1);
259 break; 266 break;
260 default: 267 default:
261 /* Unsupported number of channels */ 268 /* Unsupported number of channels */
@@ -277,11 +284,12 @@ static int omap_mcbsp_dai_hw_params(struct snd_pcm_substream *substream,
277 } 284 }
278 285
279 /* Set FS period and length in terms of bit clock periods */ 286 /* Set FS period and length in terms of bit clock periods */
280 switch (mcbsp_data->fmt & SND_SOC_DAIFMT_FORMAT_MASK) { 287 switch (format) {
281 case SND_SOC_DAIFMT_I2S: 288 case SND_SOC_DAIFMT_I2S:
282 regs->srgr2 |= FPER(wlen * 2 - 1); 289 regs->srgr2 |= FPER(wlen * channels - 1);
283 regs->srgr1 |= FWID(wlen - 1); 290 regs->srgr1 |= FWID(wlen - 1);
284 break; 291 break;
292 case SND_SOC_DAIFMT_DSP_A:
285 case SND_SOC_DAIFMT_DSP_B: 293 case SND_SOC_DAIFMT_DSP_B:
286 regs->srgr2 |= FPER(wlen * channels - 1); 294 regs->srgr2 |= FPER(wlen * channels - 1);
287 regs->srgr1 |= FWID(0); 295 regs->srgr1 |= FWID(0);
@@ -326,6 +334,13 @@ static int omap_mcbsp_dai_set_dai_fmt(struct snd_soc_dai *cpu_dai,
326 regs->rcr2 |= RDATDLY(1); 334 regs->rcr2 |= RDATDLY(1);
327 regs->xcr2 |= XDATDLY(1); 335 regs->xcr2 |= XDATDLY(1);
328 break; 336 break;
337 case SND_SOC_DAIFMT_DSP_A:
338 /* 1-bit data delay */
339 regs->rcr2 |= RDATDLY(1);
340 regs->xcr2 |= XDATDLY(1);
341 /* Invert FS polarity configuration */
342 temp_fmt ^= SND_SOC_DAIFMT_NB_IF;
343 break;
329 case SND_SOC_DAIFMT_DSP_B: 344 case SND_SOC_DAIFMT_DSP_B:
330 /* 0-bit data delay */ 345 /* 0-bit data delay */
331 regs->rcr2 |= RDATDLY(0); 346 regs->rcr2 |= RDATDLY(0);
@@ -492,13 +507,13 @@ static struct snd_soc_dai_ops omap_mcbsp_dai_ops = {
492 .id = (link_id), \ 507 .id = (link_id), \
493 .playback = { \ 508 .playback = { \
494 .channels_min = 1, \ 509 .channels_min = 1, \
495 .channels_max = 2, \ 510 .channels_max = 4, \
496 .rates = OMAP_MCBSP_RATES, \ 511 .rates = OMAP_MCBSP_RATES, \
497 .formats = SNDRV_PCM_FMTBIT_S16_LE, \ 512 .formats = SNDRV_PCM_FMTBIT_S16_LE, \
498 }, \ 513 }, \
499 .capture = { \ 514 .capture = { \
500 .channels_min = 1, \ 515 .channels_min = 1, \
501 .channels_max = 2, \ 516 .channels_max = 4, \
502 .rates = OMAP_MCBSP_RATES, \ 517 .rates = OMAP_MCBSP_RATES, \
503 .formats = SNDRV_PCM_FMTBIT_S16_LE, \ 518 .formats = SNDRV_PCM_FMTBIT_S16_LE, \
504 }, \ 519 }, \
diff --git a/sound/soc/omap/omap-pcm.c b/sound/soc/omap/omap-pcm.c
index 07cf7f46b584..c3c931d4537a 100644
--- a/sound/soc/omap/omap-pcm.c
+++ b/sound/soc/omap/omap-pcm.c
@@ -87,8 +87,10 @@ static int omap_pcm_hw_params(struct snd_pcm_substream *substream,
87 struct omap_pcm_dma_data *dma_data = rtd->dai->cpu_dai->dma_data; 87 struct omap_pcm_dma_data *dma_data = rtd->dai->cpu_dai->dma_data;
88 int err = 0; 88 int err = 0;
89 89
90 /* return if this is a bufferless transfer e.g.
91 * codec <--> BT codec or GSM modem -- lg FIXME */
90 if (!dma_data) 92 if (!dma_data)
91 return -ENODEV; 93 return 0;
92 94
93 snd_pcm_set_runtime_buffer(substream, &substream->dma_buffer); 95 snd_pcm_set_runtime_buffer(substream, &substream->dma_buffer);
94 runtime->dma_bytes = params_buffer_bytes(params); 96 runtime->dma_bytes = params_buffer_bytes(params);
@@ -134,6 +136,11 @@ static int omap_pcm_prepare(struct snd_pcm_substream *substream)
134 struct omap_pcm_dma_data *dma_data = prtd->dma_data; 136 struct omap_pcm_dma_data *dma_data = prtd->dma_data;
135 struct omap_dma_channel_params dma_params; 137 struct omap_dma_channel_params dma_params;
136 138
139 /* return if this is a bufferless transfer e.g.
140 * codec <--> BT codec or GSM modem -- lg FIXME */
141 if (!prtd->dma_data)
142 return 0;
143
137 memset(&dma_params, 0, sizeof(dma_params)); 144 memset(&dma_params, 0, sizeof(dma_params));
138 /* 145 /*
139 * Note: Regardless of interface data formats supported by OMAP McBSP 146 * Note: Regardless of interface data formats supported by OMAP McBSP
@@ -209,12 +216,15 @@ static snd_pcm_uframes_t omap_pcm_pointer(struct snd_pcm_substream *substream)
209 dma_addr_t ptr; 216 dma_addr_t ptr;
210 snd_pcm_uframes_t offset; 217 snd_pcm_uframes_t offset;
211 218
212 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) 219 if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) {
213 ptr = omap_get_dma_src_pos(prtd->dma_ch);
214 else
215 ptr = omap_get_dma_dst_pos(prtd->dma_ch); 220 ptr = omap_get_dma_dst_pos(prtd->dma_ch);
221 offset = bytes_to_frames(runtime, ptr - runtime->dma_addr);
222 } else if (!(cpu_is_omap1510())) {
223 ptr = omap_get_dma_src_pos(prtd->dma_ch);
224 offset = bytes_to_frames(runtime, ptr - runtime->dma_addr);
225 } else
226 offset = prtd->period_index * runtime->period_size;
216 227
217 offset = bytes_to_frames(runtime, ptr - runtime->dma_addr);
218 if (offset >= runtime->buffer_size) 228 if (offset >= runtime->buffer_size)
219 offset = 0; 229 offset = 0;
220 230
@@ -320,7 +330,7 @@ static void omap_pcm_free_dma_buffers(struct snd_pcm *pcm)
320 } 330 }
321} 331}
322 332
323int omap_pcm_new(struct snd_card *card, struct snd_soc_dai *dai, 333static int omap_pcm_new(struct snd_card *card, struct snd_soc_dai *dai,
324 struct snd_pcm *pcm) 334 struct snd_pcm *pcm)
325{ 335{
326 int ret = 0; 336 int ret = 0;
diff --git a/sound/soc/omap/omap2evm.c b/sound/soc/omap/omap2evm.c
index 0c2322dcf02a..027e1a40f8a1 100644
--- a/sound/soc/omap/omap2evm.c
+++ b/sound/soc/omap/omap2evm.c
@@ -86,7 +86,7 @@ static struct snd_soc_dai_link omap2evm_dai = {
86 .name = "TWL4030", 86 .name = "TWL4030",
87 .stream_name = "TWL4030", 87 .stream_name = "TWL4030",
88 .cpu_dai = &omap_mcbsp_dai[0], 88 .cpu_dai = &omap_mcbsp_dai[0],
89 .codec_dai = &twl4030_dai, 89 .codec_dai = &twl4030_dai[TWL4030_DAI_HIFI],
90 .ops = &omap2evm_ops, 90 .ops = &omap2evm_ops,
91}; 91};
92 92
diff --git a/sound/soc/omap/omap3beagle.c b/sound/soc/omap/omap3beagle.c
index fd24a4acd2f5..b0cff9f33b7e 100644
--- a/sound/soc/omap/omap3beagle.c
+++ b/sound/soc/omap/omap3beagle.c
@@ -41,23 +41,33 @@ static int omap3beagle_hw_params(struct snd_pcm_substream *substream,
41 struct snd_soc_pcm_runtime *rtd = substream->private_data; 41 struct snd_soc_pcm_runtime *rtd = substream->private_data;
42 struct snd_soc_dai *codec_dai = rtd->dai->codec_dai; 42 struct snd_soc_dai *codec_dai = rtd->dai->codec_dai;
43 struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai; 43 struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai;
44 unsigned int fmt;
44 int ret; 45 int ret;
45 46
47 switch (params_channels(params)) {
48 case 2: /* Stereo I2S mode */
49 fmt = SND_SOC_DAIFMT_I2S |
50 SND_SOC_DAIFMT_NB_NF |
51 SND_SOC_DAIFMT_CBM_CFM;
52 break;
53 case 4: /* Four channel TDM mode */
54 fmt = SND_SOC_DAIFMT_DSP_A |
55 SND_SOC_DAIFMT_IB_NF |
56 SND_SOC_DAIFMT_CBM_CFM;
57 break;
58 default:
59 return -EINVAL;
60 }
61
46 /* Set codec DAI configuration */ 62 /* Set codec DAI configuration */
47 ret = snd_soc_dai_set_fmt(codec_dai, 63 ret = snd_soc_dai_set_fmt(codec_dai, fmt);
48 SND_SOC_DAIFMT_I2S |
49 SND_SOC_DAIFMT_NB_NF |
50 SND_SOC_DAIFMT_CBM_CFM);
51 if (ret < 0) { 64 if (ret < 0) {
52 printk(KERN_ERR "can't set codec DAI configuration\n"); 65 printk(KERN_ERR "can't set codec DAI configuration\n");
53 return ret; 66 return ret;
54 } 67 }
55 68
56 /* Set cpu DAI configuration */ 69 /* Set cpu DAI configuration */
57 ret = snd_soc_dai_set_fmt(cpu_dai, 70 ret = snd_soc_dai_set_fmt(cpu_dai, fmt);
58 SND_SOC_DAIFMT_I2S |
59 SND_SOC_DAIFMT_NB_NF |
60 SND_SOC_DAIFMT_CBM_CFM);
61 if (ret < 0) { 71 if (ret < 0) {
62 printk(KERN_ERR "can't set cpu DAI configuration\n"); 72 printk(KERN_ERR "can't set cpu DAI configuration\n");
63 return ret; 73 return ret;
@@ -83,7 +93,7 @@ static struct snd_soc_dai_link omap3beagle_dai = {
83 .name = "TWL4030", 93 .name = "TWL4030",
84 .stream_name = "TWL4030", 94 .stream_name = "TWL4030",
85 .cpu_dai = &omap_mcbsp_dai[0], 95 .cpu_dai = &omap_mcbsp_dai[0],
86 .codec_dai = &twl4030_dai, 96 .codec_dai = &twl4030_dai[TWL4030_DAI_HIFI],
87 .ops = &omap3beagle_ops, 97 .ops = &omap3beagle_ops,
88}; 98};
89 99
diff --git a/sound/soc/omap/omap3evm.c b/sound/soc/omap/omap3evm.c
new file mode 100644
index 000000000000..9114c263077b
--- /dev/null
+++ b/sound/soc/omap/omap3evm.c
@@ -0,0 +1,147 @@
1/*
2 * omap3evm.c -- ALSA SoC support for OMAP3 EVM
3 *
4 * Author: Anuj Aggarwal <anuj.aggarwal@ti.com>
5 *
6 * Based on sound/soc/omap/beagle.c by Steve Sakoman
7 *
8 * Copyright (C) 2008 Texas Instruments, Incorporated
9 *
10 * This program is free software; you can redistribute it and/or modify it
11 * under the terms of the GNU General Public License as published by the
12 * Free Software Foundation version 2.
13 *
14 * This program is distributed "as is" WITHOUT ANY WARRANTY of any kind,
15 * whether express or implied; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 * General Public License for more details.
18 */
19
20#include <linux/clk.h>
21#include <linux/platform_device.h>
22#include <sound/core.h>
23#include <sound/pcm.h>
24#include <sound/soc.h>
25#include <sound/soc-dapm.h>
26
27#include <asm/mach-types.h>
28#include <mach/hardware.h>
29#include <mach/gpio.h>
30#include <mach/mcbsp.h>
31
32#include "omap-mcbsp.h"
33#include "omap-pcm.h"
34#include "../codecs/twl4030.h"
35
36static int omap3evm_hw_params(struct snd_pcm_substream *substream,
37 struct snd_pcm_hw_params *params)
38{
39 struct snd_soc_pcm_runtime *rtd = substream->private_data;
40 struct snd_soc_dai *codec_dai = rtd->dai->codec_dai;
41 struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai;
42 int ret;
43
44 /* Set codec DAI configuration */
45 ret = snd_soc_dai_set_fmt(codec_dai,
46 SND_SOC_DAIFMT_I2S |
47 SND_SOC_DAIFMT_NB_NF |
48 SND_SOC_DAIFMT_CBM_CFM);
49 if (ret < 0) {
50 printk(KERN_ERR "Can't set codec DAI configuration\n");
51 return ret;
52 }
53
54 /* Set cpu DAI configuration */
55 ret = snd_soc_dai_set_fmt(cpu_dai,
56 SND_SOC_DAIFMT_I2S |
57 SND_SOC_DAIFMT_NB_NF |
58 SND_SOC_DAIFMT_CBM_CFM);
59 if (ret < 0) {
60 printk(KERN_ERR "Can't set cpu DAI configuration\n");
61 return ret;
62 }
63
64 /* Set the codec system clock for DAC and ADC */
65 ret = snd_soc_dai_set_sysclk(codec_dai, 0, 26000000,
66 SND_SOC_CLOCK_IN);
67 if (ret < 0) {
68 printk(KERN_ERR "Can't set codec system clock\n");
69 return ret;
70 }
71
72 return 0;
73}
74
75static struct snd_soc_ops omap3evm_ops = {
76 .hw_params = omap3evm_hw_params,
77};
78
79/* Digital audio interface glue - connects codec <--> CPU */
80static struct snd_soc_dai_link omap3evm_dai = {
81 .name = "TWL4030",
82 .stream_name = "TWL4030",
83 .cpu_dai = &omap_mcbsp_dai[0],
84 .codec_dai = &twl4030_dai[TWL4030_DAI_HIFI],
85 .ops = &omap3evm_ops,
86};
87
88/* Audio machine driver */
89static struct snd_soc_card snd_soc_omap3evm = {
90 .name = "omap3evm",
91 .platform = &omap_soc_platform,
92 .dai_link = &omap3evm_dai,
93 .num_links = 1,
94};
95
96/* Audio subsystem */
97static struct snd_soc_device omap3evm_snd_devdata = {
98 .card = &snd_soc_omap3evm,
99 .codec_dev = &soc_codec_dev_twl4030,
100};
101
102static struct platform_device *omap3evm_snd_device;
103
104static int __init omap3evm_soc_init(void)
105{
106 int ret;
107
108 if (!machine_is_omap3evm()) {
109 pr_err("Not OMAP3 EVM!\n");
110 return -ENODEV;
111 }
112 pr_info("OMAP3 EVM SoC init\n");
113
114 omap3evm_snd_device = platform_device_alloc("soc-audio", -1);
115 if (!omap3evm_snd_device) {
116 printk(KERN_ERR "Platform device allocation failed\n");
117 return -ENOMEM;
118 }
119
120 platform_set_drvdata(omap3evm_snd_device, &omap3evm_snd_devdata);
121 omap3evm_snd_devdata.dev = &omap3evm_snd_device->dev;
122 *(unsigned int *)omap3evm_dai.cpu_dai->private_data = 1;
123
124 ret = platform_device_add(omap3evm_snd_device);
125 if (ret)
126 goto err1;
127
128 return 0;
129
130err1:
131 printk(KERN_ERR "Unable to add platform device\n");
132 platform_device_put(omap3evm_snd_device);
133
134 return ret;
135}
136
137static void __exit omap3evm_soc_exit(void)
138{
139 platform_device_unregister(omap3evm_snd_device);
140}
141
142module_init(omap3evm_soc_init);
143module_exit(omap3evm_soc_exit);
144
145MODULE_AUTHOR("Anuj Aggarwal <anuj.aggarwal@ti.com>");
146MODULE_DESCRIPTION("ALSA SoC OMAP3 EVM");
147MODULE_LICENSE("GPLv2");
diff --git a/sound/soc/omap/omap3pandora.c b/sound/soc/omap/omap3pandora.c
index fe282d4ef422..ad219aaf7cb8 100644
--- a/sound/soc/omap/omap3pandora.c
+++ b/sound/soc/omap/omap3pandora.c
@@ -228,14 +228,14 @@ static struct snd_soc_dai_link omap3pandora_dai[] = {
228 .name = "PCM1773", 228 .name = "PCM1773",
229 .stream_name = "HiFi Out", 229 .stream_name = "HiFi Out",
230 .cpu_dai = &omap_mcbsp_dai[0], 230 .cpu_dai = &omap_mcbsp_dai[0],
231 .codec_dai = &twl4030_dai, 231 .codec_dai = &twl4030_dai[TWL4030_DAI_HIFI],
232 .ops = &omap3pandora_out_ops, 232 .ops = &omap3pandora_out_ops,
233 .init = omap3pandora_out_init, 233 .init = omap3pandora_out_init,
234 }, { 234 }, {
235 .name = "TWL4030", 235 .name = "TWL4030",
236 .stream_name = "Line/Mic In", 236 .stream_name = "Line/Mic In",
237 .cpu_dai = &omap_mcbsp_dai[1], 237 .cpu_dai = &omap_mcbsp_dai[1],
238 .codec_dai = &twl4030_dai, 238 .codec_dai = &twl4030_dai[TWL4030_DAI_HIFI],
239 .ops = &omap3pandora_in_ops, 239 .ops = &omap3pandora_in_ops,
240 .init = omap3pandora_in_init, 240 .init = omap3pandora_in_init,
241 } 241 }
diff --git a/sound/soc/omap/overo.c b/sound/soc/omap/overo.c
index a72dc4e159e5..ec4f8fd8b3a2 100644
--- a/sound/soc/omap/overo.c
+++ b/sound/soc/omap/overo.c
@@ -83,7 +83,7 @@ static struct snd_soc_dai_link overo_dai = {
83 .name = "TWL4030", 83 .name = "TWL4030",
84 .stream_name = "TWL4030", 84 .stream_name = "TWL4030",
85 .cpu_dai = &omap_mcbsp_dai[0], 85 .cpu_dai = &omap_mcbsp_dai[0],
86 .codec_dai = &twl4030_dai, 86 .codec_dai = &twl4030_dai[TWL4030_DAI_HIFI],
87 .ops = &overo_ops, 87 .ops = &overo_ops,
88}; 88};
89 89
diff --git a/sound/soc/omap/sdp3430.c b/sound/soc/omap/sdp3430.c
index 10f1c867f11d..f7e5b7488c35 100644
--- a/sound/soc/omap/sdp3430.c
+++ b/sound/soc/omap/sdp3430.c
@@ -24,6 +24,7 @@
24 24
25#include <linux/clk.h> 25#include <linux/clk.h>
26#include <linux/platform_device.h> 26#include <linux/platform_device.h>
27#include <linux/i2c/twl4030.h>
27#include <sound/core.h> 28#include <sound/core.h>
28#include <sound/pcm.h> 29#include <sound/pcm.h>
29#include <sound/soc.h> 30#include <sound/soc.h>
@@ -39,6 +40,9 @@
39#include "omap-pcm.h" 40#include "omap-pcm.h"
40#include "../codecs/twl4030.h" 41#include "../codecs/twl4030.h"
41 42
43#define TWL4030_INTBR_PMBR1 0x0D
44#define EXTMUTE(value) (value << 2)
45
42static struct snd_soc_card snd_soc_sdp3430; 46static struct snd_soc_card snd_soc_sdp3430;
43 47
44static int sdp3430_hw_params(struct snd_pcm_substream *substream, 48static int sdp3430_hw_params(struct snd_pcm_substream *substream,
@@ -84,6 +88,49 @@ static struct snd_soc_ops sdp3430_ops = {
84 .hw_params = sdp3430_hw_params, 88 .hw_params = sdp3430_hw_params,
85}; 89};
86 90
91static int sdp3430_hw_voice_params(struct snd_pcm_substream *substream,
92 struct snd_pcm_hw_params *params)
93{
94 struct snd_soc_pcm_runtime *rtd = substream->private_data;
95 struct snd_soc_dai *codec_dai = rtd->dai->codec_dai;
96 struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai;
97 int ret;
98
99 /* Set codec DAI configuration */
100 ret = snd_soc_dai_set_fmt(codec_dai,
101 SND_SOC_DAIFMT_DSP_A |
102 SND_SOC_DAIFMT_IB_NF |
103 SND_SOC_DAIFMT_CBM_CFM);
104 if (ret) {
105 printk(KERN_ERR "can't set codec DAI configuration\n");
106 return ret;
107 }
108
109 /* Set cpu DAI configuration */
110 ret = snd_soc_dai_set_fmt(cpu_dai,
111 SND_SOC_DAIFMT_DSP_A |
112 SND_SOC_DAIFMT_IB_NF |
113 SND_SOC_DAIFMT_CBM_CFM);
114 if (ret < 0) {
115 printk(KERN_ERR "can't set cpu DAI configuration\n");
116 return ret;
117 }
118
119 /* Set the codec system clock for DAC and ADC */
120 ret = snd_soc_dai_set_sysclk(codec_dai, 0, 26000000,
121 SND_SOC_CLOCK_IN);
122 if (ret < 0) {
123 printk(KERN_ERR "can't set codec system clock\n");
124 return ret;
125 }
126
127 return 0;
128}
129
130static struct snd_soc_ops sdp3430_voice_ops = {
131 .hw_params = sdp3430_hw_voice_params,
132};
133
87/* Headset jack */ 134/* Headset jack */
88static struct snd_soc_jack hs_jack; 135static struct snd_soc_jack hs_jack;
89 136
@@ -192,28 +239,59 @@ static int sdp3430_twl4030_init(struct snd_soc_codec *codec)
192 return ret; 239 return ret;
193} 240}
194 241
242static int sdp3430_twl4030_voice_init(struct snd_soc_codec *codec)
243{
244 unsigned short reg;
245
246 /* Enable voice interface */
247 reg = codec->read(codec, TWL4030_REG_VOICE_IF);
248 reg |= TWL4030_VIF_DIN_EN | TWL4030_VIF_DOUT_EN | TWL4030_VIF_EN;
249 codec->write(codec, TWL4030_REG_VOICE_IF, reg);
250
251 return 0;
252}
253
254
195/* Digital audio interface glue - connects codec <--> CPU */ 255/* Digital audio interface glue - connects codec <--> CPU */
196static struct snd_soc_dai_link sdp3430_dai = { 256static struct snd_soc_dai_link sdp3430_dai[] = {
197 .name = "TWL4030", 257 {
198 .stream_name = "TWL4030", 258 .name = "TWL4030 I2S",
199 .cpu_dai = &omap_mcbsp_dai[0], 259 .stream_name = "TWL4030 Audio",
200 .codec_dai = &twl4030_dai, 260 .cpu_dai = &omap_mcbsp_dai[0],
201 .init = sdp3430_twl4030_init, 261 .codec_dai = &twl4030_dai[TWL4030_DAI_HIFI],
202 .ops = &sdp3430_ops, 262 .init = sdp3430_twl4030_init,
263 .ops = &sdp3430_ops,
264 },
265 {
266 .name = "TWL4030 PCM",
267 .stream_name = "TWL4030 Voice",
268 .cpu_dai = &omap_mcbsp_dai[1],
269 .codec_dai = &twl4030_dai[TWL4030_DAI_VOICE],
270 .init = sdp3430_twl4030_voice_init,
271 .ops = &sdp3430_voice_ops,
272 },
203}; 273};
204 274
205/* Audio machine driver */ 275/* Audio machine driver */
206static struct snd_soc_card snd_soc_sdp3430 = { 276static struct snd_soc_card snd_soc_sdp3430 = {
207 .name = "SDP3430", 277 .name = "SDP3430",
208 .platform = &omap_soc_platform, 278 .platform = &omap_soc_platform,
209 .dai_link = &sdp3430_dai, 279 .dai_link = sdp3430_dai,
210 .num_links = 1, 280 .num_links = ARRAY_SIZE(sdp3430_dai),
281};
282
283/* twl4030 setup */
284static struct twl4030_setup_data twl4030_setup = {
285 .ramp_delay_value = 3,
286 .sysclk = 26000,
287 .hs_extmute = 1,
211}; 288};
212 289
213/* Audio subsystem */ 290/* Audio subsystem */
214static struct snd_soc_device sdp3430_snd_devdata = { 291static struct snd_soc_device sdp3430_snd_devdata = {
215 .card = &snd_soc_sdp3430, 292 .card = &snd_soc_sdp3430,
216 .codec_dev = &soc_codec_dev_twl4030, 293 .codec_dev = &soc_codec_dev_twl4030,
294 .codec_data = &twl4030_setup,
217}; 295};
218 296
219static struct platform_device *sdp3430_snd_device; 297static struct platform_device *sdp3430_snd_device;
@@ -236,7 +314,12 @@ static int __init sdp3430_soc_init(void)
236 314
237 platform_set_drvdata(sdp3430_snd_device, &sdp3430_snd_devdata); 315 platform_set_drvdata(sdp3430_snd_device, &sdp3430_snd_devdata);
238 sdp3430_snd_devdata.dev = &sdp3430_snd_device->dev; 316 sdp3430_snd_devdata.dev = &sdp3430_snd_device->dev;
239 *(unsigned int *)sdp3430_dai.cpu_dai->private_data = 1; /* McBSP2 */ 317 *(unsigned int *)sdp3430_dai[0].cpu_dai->private_data = 1; /* McBSP2 */
318 *(unsigned int *)sdp3430_dai[1].cpu_dai->private_data = 2; /* McBSP3 */
319
320 /* Set TWL4030 GPIO6 as EXTMUTE signal */
321 twl4030_i2c_write_u8(TWL4030_MODULE_INTBR, EXTMUTE(0x02),
322 TWL4030_MODULE_INTBR);
240 323
241 ret = platform_device_add(sdp3430_snd_device); 324 ret = platform_device_add(sdp3430_snd_device);
242 if (ret) 325 if (ret)
diff --git a/sound/soc/omap/zoom2.c b/sound/soc/omap/zoom2.c
new file mode 100644
index 000000000000..f90b45f56220
--- /dev/null
+++ b/sound/soc/omap/zoom2.c
@@ -0,0 +1,314 @@
1/*
2 * zoom2.c -- SoC audio for Zoom2
3 *
4 * Author: Misael Lopez Cruz <x0052729@ti.com>
5 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License
8 * version 2 as published by the Free Software Foundation.
9 *
10 * This program is distributed in the hope that it will be useful, but
11 * WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
18 * 02110-1301 USA
19 *
20 */
21
22#include <linux/clk.h>
23#include <linux/platform_device.h>
24#include <sound/core.h>
25#include <sound/pcm.h>
26#include <sound/soc.h>
27#include <sound/soc-dapm.h>
28
29#include <asm/mach-types.h>
30#include <mach/hardware.h>
31#include <mach/gpio.h>
32#include <mach/mcbsp.h>
33
34#include "omap-mcbsp.h"
35#include "omap-pcm.h"
36#include "../codecs/twl4030.h"
37
38#define ZOOM2_HEADSET_MUX_GPIO (OMAP_MAX_GPIO_LINES + 15)
39#define ZOOM2_HEADSET_EXTMUTE_GPIO 153
40
41static int zoom2_hw_params(struct snd_pcm_substream *substream,
42 struct snd_pcm_hw_params *params)
43{
44 struct snd_soc_pcm_runtime *rtd = substream->private_data;
45 struct snd_soc_dai *codec_dai = rtd->dai->codec_dai;
46 struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai;
47 int ret;
48
49 /* Set codec DAI configuration */
50 ret = snd_soc_dai_set_fmt(codec_dai,
51 SND_SOC_DAIFMT_I2S |
52 SND_SOC_DAIFMT_NB_NF |
53 SND_SOC_DAIFMT_CBM_CFM);
54 if (ret < 0) {
55 printk(KERN_ERR "can't set codec DAI configuration\n");
56 return ret;
57 }
58
59 /* Set cpu DAI configuration */
60 ret = snd_soc_dai_set_fmt(cpu_dai,
61 SND_SOC_DAIFMT_I2S |
62 SND_SOC_DAIFMT_NB_NF |
63 SND_SOC_DAIFMT_CBM_CFM);
64 if (ret < 0) {
65 printk(KERN_ERR "can't set cpu DAI configuration\n");
66 return ret;
67 }
68
69 /* Set the codec system clock for DAC and ADC */
70 ret = snd_soc_dai_set_sysclk(codec_dai, 0, 26000000,
71 SND_SOC_CLOCK_IN);
72 if (ret < 0) {
73 printk(KERN_ERR "can't set codec system clock\n");
74 return ret;
75 }
76
77 return 0;
78}
79
80static struct snd_soc_ops zoom2_ops = {
81 .hw_params = zoom2_hw_params,
82};
83
84static int zoom2_hw_voice_params(struct snd_pcm_substream *substream,
85 struct snd_pcm_hw_params *params)
86{
87 struct snd_soc_pcm_runtime *rtd = substream->private_data;
88 struct snd_soc_dai *codec_dai = rtd->dai->codec_dai;
89 struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai;
90 int ret;
91
92 /* Set codec DAI configuration */
93 ret = snd_soc_dai_set_fmt(codec_dai,
94 SND_SOC_DAIFMT_DSP_A |
95 SND_SOC_DAIFMT_IB_NF |
96 SND_SOC_DAIFMT_CBM_CFM);
97 if (ret) {
98 printk(KERN_ERR "can't set codec DAI configuration\n");
99 return ret;
100 }
101
102 /* Set cpu DAI configuration */
103 ret = snd_soc_dai_set_fmt(cpu_dai,
104 SND_SOC_DAIFMT_DSP_A |
105 SND_SOC_DAIFMT_IB_NF |
106 SND_SOC_DAIFMT_CBM_CFM);
107 if (ret < 0) {
108 printk(KERN_ERR "can't set cpu DAI configuration\n");
109 return ret;
110 }
111
112 /* Set the codec system clock for DAC and ADC */
113 ret = snd_soc_dai_set_sysclk(codec_dai, 0, 26000000,
114 SND_SOC_CLOCK_IN);
115 if (ret < 0) {
116 printk(KERN_ERR "can't set codec system clock\n");
117 return ret;
118 }
119
120 return 0;
121}
122
123static struct snd_soc_ops zoom2_voice_ops = {
124 .hw_params = zoom2_hw_voice_params,
125};
126
127/* Zoom2 machine DAPM */
128static const struct snd_soc_dapm_widget zoom2_twl4030_dapm_widgets[] = {
129 SND_SOC_DAPM_MIC("Ext Mic", NULL),
130 SND_SOC_DAPM_SPK("Ext Spk", NULL),
131 SND_SOC_DAPM_MIC("Headset Mic", NULL),
132 SND_SOC_DAPM_HP("Headset Stereophone", NULL),
133 SND_SOC_DAPM_LINE("Aux In", NULL),
134};
135
136static const struct snd_soc_dapm_route audio_map[] = {
137 /* External Mics: MAINMIC, SUBMIC with bias*/
138 {"MAINMIC", NULL, "Mic Bias 1"},
139 {"SUBMIC", NULL, "Mic Bias 2"},
140 {"Mic Bias 1", NULL, "Ext Mic"},
141 {"Mic Bias 2", NULL, "Ext Mic"},
142
143 /* External Speakers: HFL, HFR */
144 {"Ext Spk", NULL, "HFL"},
145 {"Ext Spk", NULL, "HFR"},
146
147 /* Headset Stereophone: HSOL, HSOR */
148 {"Headset Stereophone", NULL, "HSOL"},
149 {"Headset Stereophone", NULL, "HSOR"},
150
151 /* Headset Mic: HSMIC with bias */
152 {"HSMIC", NULL, "Headset Mic Bias"},
153 {"Headset Mic Bias", NULL, "Headset Mic"},
154
155 /* Aux In: AUXL, AUXR */
156 {"Aux In", NULL, "AUXL"},
157 {"Aux In", NULL, "AUXR"},
158};
159
160static int zoom2_twl4030_init(struct snd_soc_codec *codec)
161{
162 int ret;
163
164 /* Add Zoom2 specific widgets */
165 ret = snd_soc_dapm_new_controls(codec, zoom2_twl4030_dapm_widgets,
166 ARRAY_SIZE(zoom2_twl4030_dapm_widgets));
167 if (ret)
168 return ret;
169
170 /* Set up Zoom2 specific audio path audio_map */
171 snd_soc_dapm_add_routes(codec, audio_map, ARRAY_SIZE(audio_map));
172
173 /* Zoom2 connected pins */
174 snd_soc_dapm_enable_pin(codec, "Ext Mic");
175 snd_soc_dapm_enable_pin(codec, "Ext Spk");
176 snd_soc_dapm_enable_pin(codec, "Headset Mic");
177 snd_soc_dapm_enable_pin(codec, "Headset Stereophone");
178 snd_soc_dapm_enable_pin(codec, "Aux In");
179
180 /* TWL4030 not connected pins */
181 snd_soc_dapm_nc_pin(codec, "CARKITMIC");
182 snd_soc_dapm_nc_pin(codec, "DIGIMIC0");
183 snd_soc_dapm_nc_pin(codec, "DIGIMIC1");
184
185 snd_soc_dapm_nc_pin(codec, "OUTL");
186 snd_soc_dapm_nc_pin(codec, "OUTR");
187 snd_soc_dapm_nc_pin(codec, "EARPIECE");
188 snd_soc_dapm_nc_pin(codec, "PREDRIVEL");
189 snd_soc_dapm_nc_pin(codec, "PREDRIVER");
190 snd_soc_dapm_nc_pin(codec, "CARKITL");
191 snd_soc_dapm_nc_pin(codec, "CARKITR");
192
193 ret = snd_soc_dapm_sync(codec);
194
195 return ret;
196}
197
198static int zoom2_twl4030_voice_init(struct snd_soc_codec *codec)
199{
200 unsigned short reg;
201
202 /* Enable voice interface */
203 reg = codec->read(codec, TWL4030_REG_VOICE_IF);
204 reg |= TWL4030_VIF_DIN_EN | TWL4030_VIF_DOUT_EN | TWL4030_VIF_EN;
205 codec->write(codec, TWL4030_REG_VOICE_IF, reg);
206
207 return 0;
208}
209
210/* Digital audio interface glue - connects codec <--> CPU */
211static struct snd_soc_dai_link zoom2_dai[] = {
212 {
213 .name = "TWL4030 I2S",
214 .stream_name = "TWL4030 Audio",
215 .cpu_dai = &omap_mcbsp_dai[0],
216 .codec_dai = &twl4030_dai[TWL4030_DAI_HIFI],
217 .init = zoom2_twl4030_init,
218 .ops = &zoom2_ops,
219 },
220 {
221 .name = "TWL4030 PCM",
222 .stream_name = "TWL4030 Voice",
223 .cpu_dai = &omap_mcbsp_dai[1],
224 .codec_dai = &twl4030_dai[TWL4030_DAI_VOICE],
225 .init = zoom2_twl4030_voice_init,
226 .ops = &zoom2_voice_ops,
227 },
228};
229
230/* Audio machine driver */
231static struct snd_soc_card snd_soc_zoom2 = {
232 .name = "Zoom2",
233 .platform = &omap_soc_platform,
234 .dai_link = zoom2_dai,
235 .num_links = ARRAY_SIZE(zoom2_dai),
236};
237
238/* EXTMUTE callback function */
239void zoom2_set_hs_extmute(int mute)
240{
241 gpio_set_value(ZOOM2_HEADSET_EXTMUTE_GPIO, mute);
242}
243
244/* twl4030 setup */
245static struct twl4030_setup_data twl4030_setup = {
246 .ramp_delay_value = 3, /* 161 ms */
247 .sysclk = 26000,
248 .hs_extmute = 1,
249 .set_hs_extmute = zoom2_set_hs_extmute,
250};
251
252/* Audio subsystem */
253static struct snd_soc_device zoom2_snd_devdata = {
254 .card = &snd_soc_zoom2,
255 .codec_dev = &soc_codec_dev_twl4030,
256 .codec_data = &twl4030_setup,
257};
258
259static struct platform_device *zoom2_snd_device;
260
261static int __init zoom2_soc_init(void)
262{
263 int ret;
264
265 if (!machine_is_omap_zoom2()) {
266 pr_debug("Not Zoom2!\n");
267 return -ENODEV;
268 }
269 printk(KERN_INFO "Zoom2 SoC init\n");
270
271 zoom2_snd_device = platform_device_alloc("soc-audio", -1);
272 if (!zoom2_snd_device) {
273 printk(KERN_ERR "Platform device allocation failed\n");
274 return -ENOMEM;
275 }
276
277 platform_set_drvdata(zoom2_snd_device, &zoom2_snd_devdata);
278 zoom2_snd_devdata.dev = &zoom2_snd_device->dev;
279 *(unsigned int *)zoom2_dai[0].cpu_dai->private_data = 1; /* McBSP2 */
280 *(unsigned int *)zoom2_dai[1].cpu_dai->private_data = 2; /* McBSP3 */
281
282 ret = platform_device_add(zoom2_snd_device);
283 if (ret)
284 goto err1;
285
286 BUG_ON(gpio_request(ZOOM2_HEADSET_MUX_GPIO, "hs_mux") < 0);
287 gpio_direction_output(ZOOM2_HEADSET_MUX_GPIO, 0);
288
289 BUG_ON(gpio_request(ZOOM2_HEADSET_EXTMUTE_GPIO, "ext_mute") < 0);
290 gpio_direction_output(ZOOM2_HEADSET_EXTMUTE_GPIO, 0);
291
292 return 0;
293
294err1:
295 printk(KERN_ERR "Unable to add platform device\n");
296 platform_device_put(zoom2_snd_device);
297
298 return ret;
299}
300module_init(zoom2_soc_init);
301
302static void __exit zoom2_soc_exit(void)
303{
304 gpio_free(ZOOM2_HEADSET_MUX_GPIO);
305 gpio_free(ZOOM2_HEADSET_EXTMUTE_GPIO);
306
307 platform_device_unregister(zoom2_snd_device);
308}
309module_exit(zoom2_soc_exit);
310
311MODULE_AUTHOR("Misael Lopez Cruz <x0052729@ti.com>");
312MODULE_DESCRIPTION("ALSA SoC Zoom2");
313MODULE_LICENSE("GPL");
314
diff --git a/sound/soc/pxa/Kconfig b/sound/soc/pxa/Kconfig
index ad8a10fe6298..6375b4ea525d 100644
--- a/sound/soc/pxa/Kconfig
+++ b/sound/soc/pxa/Kconfig
@@ -89,22 +89,23 @@ config SND_PXA2XX_SOC_E800
89 Toshiba e800 PDA 89 Toshiba e800 PDA
90 90
91config SND_PXA2XX_SOC_EM_X270 91config SND_PXA2XX_SOC_EM_X270
92 tristate "SoC Audio support for CompuLab EM-x270" 92 tristate "SoC Audio support for CompuLab EM-x270, eXeda and CM-X300"
93 depends on SND_PXA2XX_SOC && MACH_EM_X270 93 depends on SND_PXA2XX_SOC && MACH_EM_X270
94 select SND_PXA2XX_SOC_AC97 94 select SND_PXA2XX_SOC_AC97
95 select SND_SOC_WM9712 95 select SND_SOC_WM9712
96 help 96 help
97 Say Y if you want to add support for SoC audio on 97 Say Y if you want to add support for SoC audio on
98 CompuLab EM-x270. 98 CompuLab EM-x270, eXeda and CM-X300 machines.
99 99
100config SND_PXA2XX_SOC_PALM27X 100config SND_PXA2XX_SOC_PALM27X
101 bool "SoC Audio support for Palm T|X, T5 and LifeDrive" 101 bool "SoC Audio support for Palm T|X, T5, E2 and LifeDrive"
102 depends on SND_PXA2XX_SOC && (MACH_PALMLD || MACH_PALMTX || MACH_PALMT5) 102 depends on SND_PXA2XX_SOC && (MACH_PALMLD || MACH_PALMTX || \
103 MACH_PALMT5 || MACH_PALMTE2)
103 select SND_PXA2XX_SOC_AC97 104 select SND_PXA2XX_SOC_AC97
104 select SND_SOC_WM9712 105 select SND_SOC_WM9712
105 help 106 help
106 Say Y if you want to add support for SoC audio on 107 Say Y if you want to add support for SoC audio on
107 Palm T|X, T5 or LifeDrive handheld computer. 108 Palm T|X, T5, E2 or LifeDrive handheld computer.
108 109
109config SND_SOC_ZYLONITE 110config SND_SOC_ZYLONITE
110 tristate "SoC Audio support for Marvell Zylonite" 111 tristate "SoC Audio support for Marvell Zylonite"
@@ -134,3 +135,12 @@ config SND_PXA2XX_SOC_MIOA701
134 help 135 help
135 Say Y if you want to add support for SoC audio on the 136 Say Y if you want to add support for SoC audio on the
136 MIO A701. 137 MIO A701.
138
139config SND_PXA2XX_SOC_IMOTE2
140 tristate "SoC Audio support for IMote 2"
141 depends on SND_PXA2XX_SOC && MACH_INTELMOTE2
142 select SND_PXA2XX_SOC_I2S
143 select SND_SOC_WM8940
144 help
145 Say Y if you want to add support for SoC audio on the
146 IMote 2.
diff --git a/sound/soc/pxa/Makefile b/sound/soc/pxa/Makefile
index 4b90c3ccae45..6e096b480335 100644
--- a/sound/soc/pxa/Makefile
+++ b/sound/soc/pxa/Makefile
@@ -22,6 +22,7 @@ snd-soc-palm27x-objs := palm27x.o
22snd-soc-zylonite-objs := zylonite.o 22snd-soc-zylonite-objs := zylonite.o
23snd-soc-magician-objs := magician.o 23snd-soc-magician-objs := magician.o
24snd-soc-mioa701-objs := mioa701_wm9713.o 24snd-soc-mioa701-objs := mioa701_wm9713.o
25snd-soc-imote2-objs := imote2.o
25 26
26obj-$(CONFIG_SND_PXA2XX_SOC_CORGI) += snd-soc-corgi.o 27obj-$(CONFIG_SND_PXA2XX_SOC_CORGI) += snd-soc-corgi.o
27obj-$(CONFIG_SND_PXA2XX_SOC_POODLE) += snd-soc-poodle.o 28obj-$(CONFIG_SND_PXA2XX_SOC_POODLE) += snd-soc-poodle.o
@@ -35,3 +36,4 @@ obj-$(CONFIG_SND_PXA2XX_SOC_PALM27X) += snd-soc-palm27x.o
35obj-$(CONFIG_SND_PXA2XX_SOC_MAGICIAN) += snd-soc-magician.o 36obj-$(CONFIG_SND_PXA2XX_SOC_MAGICIAN) += snd-soc-magician.o
36obj-$(CONFIG_SND_PXA2XX_SOC_MIOA701) += snd-soc-mioa701.o 37obj-$(CONFIG_SND_PXA2XX_SOC_MIOA701) += snd-soc-mioa701.o
37obj-$(CONFIG_SND_SOC_ZYLONITE) += snd-soc-zylonite.o 38obj-$(CONFIG_SND_SOC_ZYLONITE) += snd-soc-zylonite.o
39obj-$(CONFIG_SND_PXA2XX_SOC_IMOTE2) += snd-soc-imote2.o
diff --git a/sound/soc/pxa/corgi.c b/sound/soc/pxa/corgi.c
index d5be2b30cda5..fefe1a57f31a 100644
--- a/sound/soc/pxa/corgi.c
+++ b/sound/soc/pxa/corgi.c
@@ -320,38 +320,6 @@ static struct snd_soc_device corgi_snd_devdata = {
320 .codec_dev = &soc_codec_dev_wm8731, 320 .codec_dev = &soc_codec_dev_wm8731,
321}; 321};
322 322
323/*
324 * FIXME: This is a temporary bodge to avoid cross-tree merge issues.
325 * New drivers should register the wm8731 I2C device in the machine
326 * setup code (under arch/arm for ARM systems).
327 */
328static int wm8731_i2c_register(void)
329{
330 struct i2c_board_info info;
331 struct i2c_adapter *adapter;
332 struct i2c_client *client;
333
334 memset(&info, 0, sizeof(struct i2c_board_info));
335 info.addr = 0x1b;
336 strlcpy(info.type, "wm8731", I2C_NAME_SIZE);
337
338 adapter = i2c_get_adapter(0);
339 if (!adapter) {
340 printk(KERN_ERR "can't get i2c adapter 0\n");
341 return -ENODEV;
342 }
343
344 client = i2c_new_device(adapter, &info);
345 i2c_put_adapter(adapter);
346 if (!client) {
347 printk(KERN_ERR "can't add i2c device at 0x%x\n",
348 (unsigned int)info.addr);
349 return -ENODEV;
350 }
351
352 return 0;
353}
354
355static struct platform_device *corgi_snd_device; 323static struct platform_device *corgi_snd_device;
356 324
357static int __init corgi_init(void) 325static int __init corgi_init(void)
@@ -362,10 +330,6 @@ static int __init corgi_init(void)
362 machine_is_husky())) 330 machine_is_husky()))
363 return -ENODEV; 331 return -ENODEV;
364 332
365 ret = wm8731_i2c_register();
366 if (ret != 0)
367 return ret;
368
369 corgi_snd_device = platform_device_alloc("soc-audio", -1); 333 corgi_snd_device = platform_device_alloc("soc-audio", -1);
370 if (!corgi_snd_device) 334 if (!corgi_snd_device)
371 return -ENOMEM; 335 return -ENOMEM;
diff --git a/sound/soc/pxa/em-x270.c b/sound/soc/pxa/em-x270.c
index 949be9c2a01b..f4756e4025fd 100644
--- a/sound/soc/pxa/em-x270.c
+++ b/sound/soc/pxa/em-x270.c
@@ -1,7 +1,7 @@
1/* 1/*
2 * em-x270.c -- SoC audio for EM-X270 2 * SoC audio driver for EM-X270, eXeda and CM-X300
3 * 3 *
4 * Copyright 2007 CompuLab, Ltd. 4 * Copyright 2007, 2009 CompuLab, Ltd.
5 * 5 *
6 * Author: Mike Rapoport <mike@compulab.co.il> 6 * Author: Mike Rapoport <mike@compulab.co.il>
7 * 7 *
@@ -68,7 +68,8 @@ static int __init em_x270_init(void)
68{ 68{
69 int ret; 69 int ret;
70 70
71 if (!machine_is_em_x270()) 71 if (!(machine_is_em_x270() || machine_is_exeda()
72 || machine_is_cm_x300()))
72 return -ENODEV; 73 return -ENODEV;
73 74
74 em_x270_snd_device = platform_device_alloc("soc-audio", -1); 75 em_x270_snd_device = platform_device_alloc("soc-audio", -1);
@@ -95,5 +96,5 @@ module_exit(em_x270_exit);
95 96
96/* Module information */ 97/* Module information */
97MODULE_AUTHOR("Mike Rapoport"); 98MODULE_AUTHOR("Mike Rapoport");
98MODULE_DESCRIPTION("ALSA SoC EM-X270"); 99MODULE_DESCRIPTION("ALSA SoC EM-X270, eXeda and CM-X300");
99MODULE_LICENSE("GPL"); 100MODULE_LICENSE("GPL");
diff --git a/sound/soc/pxa/imote2.c b/sound/soc/pxa/imote2.c
new file mode 100644
index 000000000000..405587a01160
--- /dev/null
+++ b/sound/soc/pxa/imote2.c
@@ -0,0 +1,114 @@
1
2#include <linux/module.h>
3#include <sound/soc.h>
4
5#include <asm/mach-types.h>
6
7#include "../codecs/wm8940.h"
8#include "pxa2xx-i2s.h"
9#include "pxa2xx-pcm.h"
10
11static int imote2_asoc_hw_params(struct snd_pcm_substream *substream,
12 struct snd_pcm_hw_params *params)
13{
14 struct snd_soc_pcm_runtime *rtd = substream->private_data;
15 struct snd_soc_dai *codec_dai = rtd->dai->codec_dai;
16 struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai;
17 unsigned int clk = 0;
18 int ret;
19
20 switch (params_rate(params)) {
21 case 8000:
22 case 16000:
23 case 48000:
24 case 96000:
25 clk = 12288000;
26 break;
27 case 11025:
28 case 22050:
29 case 44100:
30 clk = 11289600;
31 break;
32 }
33
34 /* set codec DAI configuration */
35 ret = snd_soc_dai_set_fmt(codec_dai, SND_SOC_DAIFMT_I2S
36 | SND_SOC_DAIFMT_NB_NF
37 | SND_SOC_DAIFMT_CBS_CFS);
38 if (ret < 0)
39 return ret;
40
41 /* CPU should be clock master */
42 ret = snd_soc_dai_set_fmt(cpu_dai, SND_SOC_DAIFMT_I2S
43 | SND_SOC_DAIFMT_NB_NF
44 | SND_SOC_DAIFMT_CBS_CFS);
45 if (ret < 0)
46 return ret;
47
48 ret = snd_soc_dai_set_sysclk(codec_dai, 0, clk,
49 SND_SOC_CLOCK_IN);
50 if (ret < 0)
51 return ret;
52
53 /* set the I2S system clock as input (unused) */
54 ret = snd_soc_dai_set_sysclk(cpu_dai, PXA2XX_I2S_SYSCLK, clk,
55 SND_SOC_CLOCK_OUT);
56
57 return ret;
58}
59
60static struct snd_soc_ops imote2_asoc_ops = {
61 .hw_params = imote2_asoc_hw_params,
62};
63
64static struct snd_soc_dai_link imote2_dai = {
65 .name = "WM8940",
66 .stream_name = "WM8940",
67 .cpu_dai = &pxa_i2s_dai,
68 .codec_dai = &wm8940_dai,
69 .ops = &imote2_asoc_ops,
70};
71
72static struct snd_soc_card snd_soc_imote2 = {
73 .name = "Imote2",
74 .platform = &pxa2xx_soc_platform,
75 .dai_link = &imote2_dai,
76 .num_links = 1,
77};
78
79static struct snd_soc_device imote2_snd_devdata = {
80 .card = &snd_soc_imote2,
81 .codec_dev = &soc_codec_dev_wm8940,
82};
83
84static struct platform_device *imote2_snd_device;
85
86static int __init imote2_asoc_init(void)
87{
88 int ret;
89
90 if (!machine_is_intelmote2())
91 return -ENODEV;
92 imote2_snd_device = platform_device_alloc("soc-audio", -1);
93 if (!imote2_snd_device)
94 return -ENOMEM;
95
96 platform_set_drvdata(imote2_snd_device, &imote2_snd_devdata);
97 imote2_snd_devdata.dev = &imote2_snd_device->dev;
98 ret = platform_device_add(imote2_snd_device);
99 if (ret)
100 platform_device_put(imote2_snd_device);
101
102 return ret;
103}
104module_init(imote2_asoc_init);
105
106static void __exit imote2_asoc_exit(void)
107{
108 platform_device_unregister(imote2_snd_device);
109}
110module_exit(imote2_asoc_exit);
111
112MODULE_AUTHOR("Jonathan Cameron");
113MODULE_DESCRIPTION("ALSA SoC Imote 2");
114MODULE_LICENSE("GPL");
diff --git a/sound/soc/pxa/magician.c b/sound/soc/pxa/magician.c
index 0625c342a1c9..9f7c61e23daf 100644
--- a/sound/soc/pxa/magician.c
+++ b/sound/soc/pxa/magician.c
@@ -20,12 +20,14 @@
20#include <linux/platform_device.h> 20#include <linux/platform_device.h>
21#include <linux/delay.h> 21#include <linux/delay.h>
22#include <linux/gpio.h> 22#include <linux/gpio.h>
23#include <linux/i2c.h>
23 24
24#include <sound/core.h> 25#include <sound/core.h>
25#include <sound/pcm.h> 26#include <sound/pcm.h>
26#include <sound/pcm_params.h> 27#include <sound/pcm_params.h>
27#include <sound/soc.h> 28#include <sound/soc.h>
28#include <sound/soc-dapm.h> 29#include <sound/soc-dapm.h>
30#include <sound/uda1380.h>
29 31
30#include <mach/magician.h> 32#include <mach/magician.h>
31#include <asm/mach-types.h> 33#include <asm/mach-types.h>
@@ -106,7 +108,7 @@ static int magician_playback_hw_params(struct snd_pcm_substream *substream,
106 /* 513156 Hz ~= _2_ * 8000 Hz * 32 (+0.23%) */ 108 /* 513156 Hz ~= _2_ * 8000 Hz * 32 (+0.23%) */
107 acds = PXA_SSP_CLK_AUDIO_DIV_16; 109 acds = PXA_SSP_CLK_AUDIO_DIV_16;
108 break; 110 break;
109 case 32: 111 default: /* 32 */
110 /* 1026312 Hz ~= _2_ * 8000 Hz * 64 (+0.23%) */ 112 /* 1026312 Hz ~= _2_ * 8000 Hz * 64 (+0.23%) */
111 acds = PXA_SSP_CLK_AUDIO_DIV_8; 113 acds = PXA_SSP_CLK_AUDIO_DIV_8;
112 } 114 }
@@ -118,7 +120,7 @@ static int magician_playback_hw_params(struct snd_pcm_substream *substream,
118 /* 351375 Hz ~= 11025 Hz * 32 (-0.41%) */ 120 /* 351375 Hz ~= 11025 Hz * 32 (-0.41%) */
119 acds = PXA_SSP_CLK_AUDIO_DIV_4; 121 acds = PXA_SSP_CLK_AUDIO_DIV_4;
120 break; 122 break;
121 case 32: 123 default: /* 32 */
122 /* 702750 Hz ~= 11025 Hz * 64 (-0.41%) */ 124 /* 702750 Hz ~= 11025 Hz * 64 (-0.41%) */
123 acds = PXA_SSP_CLK_AUDIO_DIV_2; 125 acds = PXA_SSP_CLK_AUDIO_DIV_2;
124 } 126 }
@@ -130,7 +132,7 @@ static int magician_playback_hw_params(struct snd_pcm_substream *substream,
130 /* 702750 Hz ~= 22050 Hz * 32 (-0.41%) */ 132 /* 702750 Hz ~= 22050 Hz * 32 (-0.41%) */
131 acds = PXA_SSP_CLK_AUDIO_DIV_2; 133 acds = PXA_SSP_CLK_AUDIO_DIV_2;
132 break; 134 break;
133 case 32: 135 default: /* 32 */
134 /* 1405500 Hz ~= 22050 Hz * 64 (-0.41%) */ 136 /* 1405500 Hz ~= 22050 Hz * 64 (-0.41%) */
135 acds = PXA_SSP_CLK_AUDIO_DIV_1; 137 acds = PXA_SSP_CLK_AUDIO_DIV_1;
136 } 138 }
@@ -142,7 +144,7 @@ static int magician_playback_hw_params(struct snd_pcm_substream *substream,
142 /* 1405500 Hz ~= 44100 Hz * 32 (-0.41%) */ 144 /* 1405500 Hz ~= 44100 Hz * 32 (-0.41%) */
143 acds = PXA_SSP_CLK_AUDIO_DIV_2; 145 acds = PXA_SSP_CLK_AUDIO_DIV_2;
144 break; 146 break;
145 case 32: 147 default: /* 32 */
146 /* 2811000 Hz ~= 44100 Hz * 64 (-0.41%) */ 148 /* 2811000 Hz ~= 44100 Hz * 64 (-0.41%) */
147 acds = PXA_SSP_CLK_AUDIO_DIV_1; 149 acds = PXA_SSP_CLK_AUDIO_DIV_1;
148 } 150 }
@@ -154,19 +156,20 @@ static int magician_playback_hw_params(struct snd_pcm_substream *substream,
154 /* 1529375 Hz ~= 48000 Hz * 32 (-0.44%) */ 156 /* 1529375 Hz ~= 48000 Hz * 32 (-0.44%) */
155 acds = PXA_SSP_CLK_AUDIO_DIV_2; 157 acds = PXA_SSP_CLK_AUDIO_DIV_2;
156 break; 158 break;
157 case 32: 159 default: /* 32 */
158 /* 3058750 Hz ~= 48000 Hz * 64 (-0.44%) */ 160 /* 3058750 Hz ~= 48000 Hz * 64 (-0.44%) */
159 acds = PXA_SSP_CLK_AUDIO_DIV_1; 161 acds = PXA_SSP_CLK_AUDIO_DIV_1;
160 } 162 }
161 break; 163 break;
162 case 96000: 164 case 96000:
165 default:
163 acps = 12235000; 166 acps = 12235000;
164 switch (width) { 167 switch (width) {
165 case 16: 168 case 16:
166 /* 3058750 Hz ~= 96000 Hz * 32 (-0.44%) */ 169 /* 3058750 Hz ~= 96000 Hz * 32 (-0.44%) */
167 acds = PXA_SSP_CLK_AUDIO_DIV_1; 170 acds = PXA_SSP_CLK_AUDIO_DIV_1;
168 break; 171 break;
169 case 32: 172 default: /* 32 */
170 /* 6117500 Hz ~= 96000 Hz * 64 (-0.44%) */ 173 /* 6117500 Hz ~= 96000 Hz * 64 (-0.44%) */
171 acds = PXA_SSP_CLK_AUDIO_DIV_2; 174 acds = PXA_SSP_CLK_AUDIO_DIV_2;
172 div4 = PXA_SSP_CLK_SCDB_1; 175 div4 = PXA_SSP_CLK_SCDB_1;
@@ -183,11 +186,11 @@ static int magician_playback_hw_params(struct snd_pcm_substream *substream,
183 186
184 /* set cpu DAI configuration */ 187 /* set cpu DAI configuration */
185 ret = snd_soc_dai_set_fmt(cpu_dai, SND_SOC_DAIFMT_DSP_A | 188 ret = snd_soc_dai_set_fmt(cpu_dai, SND_SOC_DAIFMT_DSP_A |
186 SND_SOC_DAIFMT_IB_IF | SND_SOC_DAIFMT_CBS_CFS); 189 SND_SOC_DAIFMT_NB_IF | SND_SOC_DAIFMT_CBS_CFS);
187 if (ret < 0) 190 if (ret < 0)
188 return ret; 191 return ret;
189 192
190 ret = snd_soc_dai_set_tdm_slot(cpu_dai, 1, 1); 193 ret = snd_soc_dai_set_tdm_slot(cpu_dai, 1, 0, 1, width);
191 if (ret < 0) 194 if (ret < 0)
192 return ret; 195 return ret;
193 196
@@ -446,34 +449,47 @@ static struct snd_soc_card snd_soc_card_magician = {
446 .platform = &pxa2xx_soc_platform, 449 .platform = &pxa2xx_soc_platform,
447}; 450};
448 451
449/* magician audio private data */
450static struct uda1380_setup_data magician_uda1380_setup = {
451 .i2c_address = 0x18,
452 .dac_clk = UDA1380_DAC_CLK_WSPLL,
453};
454
455/* magician audio subsystem */ 452/* magician audio subsystem */
456static struct snd_soc_device magician_snd_devdata = { 453static struct snd_soc_device magician_snd_devdata = {
457 .card = &snd_soc_card_magician, 454 .card = &snd_soc_card_magician,
458 .codec_dev = &soc_codec_dev_uda1380, 455 .codec_dev = &soc_codec_dev_uda1380,
459 .codec_data = &magician_uda1380_setup,
460}; 456};
461 457
462static struct platform_device *magician_snd_device; 458static struct platform_device *magician_snd_device;
463 459
460/*
461 * FIXME: move into magician board file once merged into the pxa tree
462 */
463static struct uda1380_platform_data uda1380_info = {
464 .gpio_power = EGPIO_MAGICIAN_CODEC_POWER,
465 .gpio_reset = EGPIO_MAGICIAN_CODEC_RESET,
466 .dac_clk = UDA1380_DAC_CLK_WSPLL,
467};
468
469static struct i2c_board_info i2c_board_info[] = {
470 {
471 I2C_BOARD_INFO("uda1380", 0x18),
472 .platform_data = &uda1380_info,
473 },
474};
475
464static int __init magician_init(void) 476static int __init magician_init(void)
465{ 477{
466 int ret; 478 int ret;
479 struct i2c_adapter *adapter;
480 struct i2c_client *client;
467 481
468 if (!machine_is_magician()) 482 if (!machine_is_magician())
469 return -ENODEV; 483 return -ENODEV;
470 484
471 ret = gpio_request(EGPIO_MAGICIAN_CODEC_POWER, "CODEC_POWER"); 485 adapter = i2c_get_adapter(0);
472 if (ret) 486 if (!adapter)
473 goto err_request_power; 487 return -ENODEV;
474 ret = gpio_request(EGPIO_MAGICIAN_CODEC_RESET, "CODEC_RESET"); 488 client = i2c_new_device(adapter, i2c_board_info);
475 if (ret) 489 i2c_put_adapter(adapter);
476 goto err_request_reset; 490 if (!client)
491 return -ENODEV;
492
477 ret = gpio_request(EGPIO_MAGICIAN_SPK_POWER, "SPK_POWER"); 493 ret = gpio_request(EGPIO_MAGICIAN_SPK_POWER, "SPK_POWER");
478 if (ret) 494 if (ret)
479 goto err_request_spk; 495 goto err_request_spk;
@@ -490,14 +506,8 @@ static int __init magician_init(void)
490 if (ret) 506 if (ret)
491 goto err_request_in_sel1; 507 goto err_request_in_sel1;
492 508
493 gpio_set_value(EGPIO_MAGICIAN_CODEC_POWER, 1);
494 gpio_set_value(EGPIO_MAGICIAN_IN_SEL0, 0); 509 gpio_set_value(EGPIO_MAGICIAN_IN_SEL0, 0);
495 510
496 /* we may need to have the clock running here - pH5 */
497 gpio_set_value(EGPIO_MAGICIAN_CODEC_RESET, 1);
498 udelay(5);
499 gpio_set_value(EGPIO_MAGICIAN_CODEC_RESET, 0);
500
501 magician_snd_device = platform_device_alloc("soc-audio", -1); 511 magician_snd_device = platform_device_alloc("soc-audio", -1);
502 if (!magician_snd_device) { 512 if (!magician_snd_device) {
503 ret = -ENOMEM; 513 ret = -ENOMEM;
@@ -525,10 +535,6 @@ err_request_mic:
525err_request_ep: 535err_request_ep:
526 gpio_free(EGPIO_MAGICIAN_SPK_POWER); 536 gpio_free(EGPIO_MAGICIAN_SPK_POWER);
527err_request_spk: 537err_request_spk:
528 gpio_free(EGPIO_MAGICIAN_CODEC_RESET);
529err_request_reset:
530 gpio_free(EGPIO_MAGICIAN_CODEC_POWER);
531err_request_power:
532 return ret; 538 return ret;
533} 539}
534 540
@@ -539,15 +545,12 @@ static void __exit magician_exit(void)
539 gpio_set_value(EGPIO_MAGICIAN_SPK_POWER, 0); 545 gpio_set_value(EGPIO_MAGICIAN_SPK_POWER, 0);
540 gpio_set_value(EGPIO_MAGICIAN_EP_POWER, 0); 546 gpio_set_value(EGPIO_MAGICIAN_EP_POWER, 0);
541 gpio_set_value(EGPIO_MAGICIAN_MIC_POWER, 0); 547 gpio_set_value(EGPIO_MAGICIAN_MIC_POWER, 0);
542 gpio_set_value(EGPIO_MAGICIAN_CODEC_POWER, 0);
543 548
544 gpio_free(EGPIO_MAGICIAN_IN_SEL1); 549 gpio_free(EGPIO_MAGICIAN_IN_SEL1);
545 gpio_free(EGPIO_MAGICIAN_IN_SEL0); 550 gpio_free(EGPIO_MAGICIAN_IN_SEL0);
546 gpio_free(EGPIO_MAGICIAN_MIC_POWER); 551 gpio_free(EGPIO_MAGICIAN_MIC_POWER);
547 gpio_free(EGPIO_MAGICIAN_EP_POWER); 552 gpio_free(EGPIO_MAGICIAN_EP_POWER);
548 gpio_free(EGPIO_MAGICIAN_SPK_POWER); 553 gpio_free(EGPIO_MAGICIAN_SPK_POWER);
549 gpio_free(EGPIO_MAGICIAN_CODEC_RESET);
550 gpio_free(EGPIO_MAGICIAN_CODEC_POWER);
551} 554}
552 555
553module_init(magician_init); 556module_init(magician_init);
diff --git a/sound/soc/pxa/palm27x.c b/sound/soc/pxa/palm27x.c
index 44fcc4e01e08..1f96e3227be5 100644
--- a/sound/soc/pxa/palm27x.c
+++ b/sound/soc/pxa/palm27x.c
@@ -17,13 +17,12 @@
17#include <linux/moduleparam.h> 17#include <linux/moduleparam.h>
18#include <linux/device.h> 18#include <linux/device.h>
19#include <linux/gpio.h> 19#include <linux/gpio.h>
20#include <linux/interrupt.h>
21#include <linux/irq.h>
22 20
23#include <sound/core.h> 21#include <sound/core.h>
24#include <sound/pcm.h> 22#include <sound/pcm.h>
25#include <sound/soc.h> 23#include <sound/soc.h>
26#include <sound/soc-dapm.h> 24#include <sound/soc-dapm.h>
25#include <sound/jack.h>
27 26
28#include <asm/mach-types.h> 27#include <asm/mach-types.h>
29#include <mach/audio.h> 28#include <mach/audio.h>
@@ -33,90 +32,31 @@
33#include "pxa2xx-pcm.h" 32#include "pxa2xx-pcm.h"
34#include "pxa2xx-ac97.h" 33#include "pxa2xx-ac97.h"
35 34
36static int palm27x_jack_func = 1; 35static struct snd_soc_jack hs_jack;
37static int palm27x_spk_func = 1;
38static int palm27x_ep_gpio = -1;
39 36
40static void palm27x_ext_control(struct snd_soc_codec *codec) 37/* Headphones jack detection DAPM pins */
41{ 38static struct snd_soc_jack_pin hs_jack_pins[] = {
42 if (!palm27x_spk_func) 39 {
43 snd_soc_dapm_enable_pin(codec, "Speaker"); 40 .pin = "Headphone Jack",
44 else 41 .mask = SND_JACK_HEADPHONE,
45 snd_soc_dapm_disable_pin(codec, "Speaker"); 42 },
46
47 if (!palm27x_jack_func)
48 snd_soc_dapm_enable_pin(codec, "Headphone Jack");
49 else
50 snd_soc_dapm_disable_pin(codec, "Headphone Jack");
51
52 snd_soc_dapm_sync(codec);
53}
54
55static int palm27x_startup(struct snd_pcm_substream *substream)
56{
57 struct snd_soc_pcm_runtime *rtd = substream->private_data;
58 struct snd_soc_codec *codec = rtd->socdev->card->codec;
59
60 /* check the jack status at stream startup */
61 palm27x_ext_control(codec);
62 return 0;
63}
64
65static struct snd_soc_ops palm27x_ops = {
66 .startup = palm27x_startup,
67}; 43};
68 44
69static irqreturn_t palm27x_interrupt(int irq, void *v) 45/* Headphones jack detection gpios */
70{ 46static struct snd_soc_jack_gpio hs_jack_gpios[] = {
71 palm27x_spk_func = gpio_get_value(palm27x_ep_gpio); 47 [0] = {
72 palm27x_jack_func = !palm27x_spk_func; 48 /* gpio is set on per-platform basis */
73 return IRQ_HANDLED; 49 .name = "hp-gpio",
74} 50 .report = SND_JACK_HEADPHONE,
75 51 .debounce_time = 200,
76static int palm27x_get_jack(struct snd_kcontrol *kcontrol, 52 },
77 struct snd_ctl_elem_value *ucontrol) 53};
78{
79 ucontrol->value.integer.value[0] = palm27x_jack_func;
80 return 0;
81}
82
83static int palm27x_set_jack(struct snd_kcontrol *kcontrol,
84 struct snd_ctl_elem_value *ucontrol)
85{
86 struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
87
88 if (palm27x_jack_func == ucontrol->value.integer.value[0])
89 return 0;
90
91 palm27x_jack_func = ucontrol->value.integer.value[0];
92 palm27x_ext_control(codec);
93 return 1;
94}
95
96static int palm27x_get_spk(struct snd_kcontrol *kcontrol,
97 struct snd_ctl_elem_value *ucontrol)
98{
99 ucontrol->value.integer.value[0] = palm27x_spk_func;
100 return 0;
101}
102
103static int palm27x_set_spk(struct snd_kcontrol *kcontrol,
104 struct snd_ctl_elem_value *ucontrol)
105{
106 struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
107
108 if (palm27x_spk_func == ucontrol->value.integer.value[0])
109 return 0;
110
111 palm27x_spk_func = ucontrol->value.integer.value[0];
112 palm27x_ext_control(codec);
113 return 1;
114}
115 54
116/* PalmTX machine dapm widgets */ 55/* Palm27x machine dapm widgets */
117static const struct snd_soc_dapm_widget palm27x_dapm_widgets[] = { 56static const struct snd_soc_dapm_widget palm27x_dapm_widgets[] = {
118 SND_SOC_DAPM_HP("Headphone Jack", NULL), 57 SND_SOC_DAPM_HP("Headphone Jack", NULL),
119 SND_SOC_DAPM_SPK("Speaker", NULL), 58 SND_SOC_DAPM_SPK("Ext. Speaker", NULL),
59 SND_SOC_DAPM_MIC("Ext. Microphone", NULL),
120}; 60};
121 61
122/* PalmTX audio map */ 62/* PalmTX audio map */
@@ -126,46 +66,66 @@ static const struct snd_soc_dapm_route audio_map[] = {
126 {"Headphone Jack", NULL, "HPOUTR"}, 66 {"Headphone Jack", NULL, "HPOUTR"},
127 67
128 /* ext speaker connected to ROUT2, LOUT2 */ 68 /* ext speaker connected to ROUT2, LOUT2 */
129 {"Speaker", NULL, "LOUT2"}, 69 {"Ext. Speaker", NULL, "LOUT2"},
130 {"Speaker", NULL, "ROUT2"}, 70 {"Ext. Speaker", NULL, "ROUT2"},
131};
132 71
133static const char *jack_function[] = {"Headphone", "Off"}; 72 /* mic connected to MIC1 */
134static const char *spk_function[] = {"On", "Off"}; 73 {"Ext. Microphone", NULL, "MIC1"},
135static const struct soc_enum palm27x_enum[] = {
136 SOC_ENUM_SINGLE_EXT(2, jack_function),
137 SOC_ENUM_SINGLE_EXT(2, spk_function),
138}; 74};
139 75
140static const struct snd_kcontrol_new palm27x_controls[] = { 76static struct snd_soc_card palm27x_asoc;
141 SOC_ENUM_EXT("Jack Function", palm27x_enum[0], palm27x_get_jack,
142 palm27x_set_jack),
143 SOC_ENUM_EXT("Speaker Function", palm27x_enum[1], palm27x_get_spk,
144 palm27x_set_spk),
145};
146 77
147static int palm27x_ac97_init(struct snd_soc_codec *codec) 78static int palm27x_ac97_init(struct snd_soc_codec *codec)
148{ 79{
149 int err; 80 int err;
150 81
82 /* add palm27x specific widgets */
83 err = snd_soc_dapm_new_controls(codec, palm27x_dapm_widgets,
84 ARRAY_SIZE(palm27x_dapm_widgets));
85 if (err)
86 return err;
87
88 /* set up palm27x specific audio path audio_map */
89 err = snd_soc_dapm_add_routes(codec, audio_map, ARRAY_SIZE(audio_map));
90 if (err)
91 return err;
92
93 /* connected pins */
94 if (machine_is_palmld())
95 snd_soc_dapm_enable_pin(codec, "MIC1");
96 snd_soc_dapm_enable_pin(codec, "HPOUTL");
97 snd_soc_dapm_enable_pin(codec, "HPOUTR");
98 snd_soc_dapm_enable_pin(codec, "LOUT2");
99 snd_soc_dapm_enable_pin(codec, "ROUT2");
100
101 /* not connected pins */
151 snd_soc_dapm_nc_pin(codec, "OUT3"); 102 snd_soc_dapm_nc_pin(codec, "OUT3");
152 snd_soc_dapm_nc_pin(codec, "MONOOUT"); 103 snd_soc_dapm_nc_pin(codec, "MONOOUT");
104 snd_soc_dapm_nc_pin(codec, "LINEINL");
105 snd_soc_dapm_nc_pin(codec, "LINEINR");
106 snd_soc_dapm_nc_pin(codec, "PCBEEP");
107 snd_soc_dapm_nc_pin(codec, "PHONE");
108 snd_soc_dapm_nc_pin(codec, "MIC2");
109
110 err = snd_soc_dapm_sync(codec);
111 if (err)
112 return err;
153 113
154 /* add palm27x specific controls */ 114 /* Jack detection API stuff */
155 err = snd_soc_add_controls(codec, palm27x_controls, 115 err = snd_soc_jack_new(&palm27x_asoc, "Headphone Jack",
156 ARRAY_SIZE(palm27x_controls)); 116 SND_JACK_HEADPHONE, &hs_jack);
157 if (err < 0) 117 if (err)
158 return err; 118 return err;
159 119
160 /* add palm27x specific widgets */ 120 err = snd_soc_jack_add_pins(&hs_jack, ARRAY_SIZE(hs_jack_pins),
161 snd_soc_dapm_new_controls(codec, palm27x_dapm_widgets, 121 hs_jack_pins);
162 ARRAY_SIZE(palm27x_dapm_widgets)); 122 if (err)
123 return err;
163 124
164 /* set up palm27x specific audio path audio_map */ 125 err = snd_soc_jack_add_gpios(&hs_jack, ARRAY_SIZE(hs_jack_gpios),
165 snd_soc_dapm_add_routes(codec, audio_map, ARRAY_SIZE(audio_map)); 126 hs_jack_gpios);
166 127
167 snd_soc_dapm_sync(codec); 128 return err;
168 return 0;
169} 129}
170 130
171static struct snd_soc_dai_link palm27x_dai[] = { 131static struct snd_soc_dai_link palm27x_dai[] = {
@@ -175,14 +135,12 @@ static struct snd_soc_dai_link palm27x_dai[] = {
175 .cpu_dai = &pxa_ac97_dai[PXA2XX_DAI_AC97_HIFI], 135 .cpu_dai = &pxa_ac97_dai[PXA2XX_DAI_AC97_HIFI],
176 .codec_dai = &wm9712_dai[WM9712_DAI_AC97_HIFI], 136 .codec_dai = &wm9712_dai[WM9712_DAI_AC97_HIFI],
177 .init = palm27x_ac97_init, 137 .init = palm27x_ac97_init,
178 .ops = &palm27x_ops,
179}, 138},
180{ 139{
181 .name = "AC97 Aux", 140 .name = "AC97 Aux",
182 .stream_name = "AC97 Aux", 141 .stream_name = "AC97 Aux",
183 .cpu_dai = &pxa_ac97_dai[PXA2XX_DAI_AC97_AUX], 142 .cpu_dai = &pxa_ac97_dai[PXA2XX_DAI_AC97_AUX],
184 .codec_dai = &wm9712_dai[WM9712_DAI_AC97_AUX], 143 .codec_dai = &wm9712_dai[WM9712_DAI_AC97_AUX],
185 .ops = &palm27x_ops,
186}, 144},
187}; 145};
188 146
@@ -205,30 +163,20 @@ static int palm27x_asoc_probe(struct platform_device *pdev)
205 int ret; 163 int ret;
206 164
207 if (!(machine_is_palmtx() || machine_is_palmt5() || 165 if (!(machine_is_palmtx() || machine_is_palmt5() ||
208 machine_is_palmld())) 166 machine_is_palmld() || machine_is_palmte2()))
209 return -ENODEV; 167 return -ENODEV;
210 168
211 if (pdev->dev.platform_data) 169 if (!pdev->dev.platform_data) {
212 palm27x_ep_gpio = ((struct palm27x_asoc_info *) 170 dev_err(&pdev->dev, "please supply platform_data\n");
213 (pdev->dev.platform_data))->jack_gpio; 171 return -ENODEV;
214 172 }
215 ret = gpio_request(palm27x_ep_gpio, "Headphone Jack");
216 if (ret)
217 return ret;
218 ret = gpio_direction_input(palm27x_ep_gpio);
219 if (ret)
220 goto err_alloc;
221 173
222 if (request_irq(gpio_to_irq(palm27x_ep_gpio), palm27x_interrupt, 174 hs_jack_gpios[0].gpio = ((struct palm27x_asoc_info *)
223 IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING, 175 (pdev->dev.platform_data))->jack_gpio;
224 "Headphone jack", NULL))
225 goto err_alloc;
226 176
227 palm27x_snd_device = platform_device_alloc("soc-audio", -1); 177 palm27x_snd_device = platform_device_alloc("soc-audio", -1);
228 if (!palm27x_snd_device) { 178 if (!palm27x_snd_device)
229 ret = -ENOMEM; 179 return -ENOMEM;
230 goto err_dev;
231 }
232 180
233 platform_set_drvdata(palm27x_snd_device, &palm27x_snd_devdata); 181 platform_set_drvdata(palm27x_snd_device, &palm27x_snd_devdata);
234 palm27x_snd_devdata.dev = &palm27x_snd_device->dev; 182 palm27x_snd_devdata.dev = &palm27x_snd_device->dev;
@@ -241,18 +189,12 @@ static int palm27x_asoc_probe(struct platform_device *pdev)
241 189
242put_device: 190put_device:
243 platform_device_put(palm27x_snd_device); 191 platform_device_put(palm27x_snd_device);
244err_dev:
245 free_irq(gpio_to_irq(palm27x_ep_gpio), NULL);
246err_alloc:
247 gpio_free(palm27x_ep_gpio);
248 192
249 return ret; 193 return ret;
250} 194}
251 195
252static int __devexit palm27x_asoc_remove(struct platform_device *pdev) 196static int __devexit palm27x_asoc_remove(struct platform_device *pdev)
253{ 197{
254 free_irq(gpio_to_irq(palm27x_ep_gpio), NULL);
255 gpio_free(palm27x_ep_gpio);
256 platform_device_unregister(palm27x_snd_device); 198 platform_device_unregister(palm27x_snd_device);
257 return 0; 199 return 0;
258} 200}
diff --git a/sound/soc/pxa/poodle.c b/sound/soc/pxa/poodle.c
index a51058f66747..c5f36e0eab58 100644
--- a/sound/soc/pxa/poodle.c
+++ b/sound/soc/pxa/poodle.c
@@ -280,38 +280,6 @@ static struct snd_soc_card snd_soc_poodle = {
280 .num_links = 1, 280 .num_links = 1,
281}; 281};
282 282
283/*
284 * FIXME: This is a temporary bodge to avoid cross-tree merge issues.
285 * New drivers should register the wm8731 I2C device in the machine
286 * setup code (under arch/arm for ARM systems).
287 */
288static int wm8731_i2c_register(void)
289{
290 struct i2c_board_info info;
291 struct i2c_adapter *adapter;
292 struct i2c_client *client;
293
294 memset(&info, 0, sizeof(struct i2c_board_info));
295 info.addr = 0x1b;
296 strlcpy(info.type, "wm8731", I2C_NAME_SIZE);
297
298 adapter = i2c_get_adapter(0);
299 if (!adapter) {
300 printk(KERN_ERR "can't get i2c adapter 0\n");
301 return -ENODEV;
302 }
303
304 client = i2c_new_device(adapter, &info);
305 i2c_put_adapter(adapter);
306 if (!client) {
307 printk(KERN_ERR "can't add i2c device at 0x%x\n",
308 (unsigned int)info.addr);
309 return -ENODEV;
310 }
311
312 return 0;
313}
314
315/* poodle audio subsystem */ 283/* poodle audio subsystem */
316static struct snd_soc_device poodle_snd_devdata = { 284static struct snd_soc_device poodle_snd_devdata = {
317 .card = &snd_soc_poodle, 285 .card = &snd_soc_poodle,
@@ -327,10 +295,6 @@ static int __init poodle_init(void)
327 if (!machine_is_poodle()) 295 if (!machine_is_poodle())
328 return -ENODEV; 296 return -ENODEV;
329 297
330 ret = wm8731_i2c_register();
331 if (ret != 0)
332 return ret;
333
334 locomo_gpio_set_dir(&poodle_locomo_device.dev, 298 locomo_gpio_set_dir(&poodle_locomo_device.dev,
335 POODLE_LOCOMO_GPIO_AMP_ON, 0); 299 POODLE_LOCOMO_GPIO_AMP_ON, 0);
336 /* should we mute HP at startup - burning power ?*/ 300 /* should we mute HP at startup - burning power ?*/
diff --git a/sound/soc/pxa/pxa-ssp.c b/sound/soc/pxa/pxa-ssp.c
index 286be31545df..5b9ed6464789 100644
--- a/sound/soc/pxa/pxa-ssp.c
+++ b/sound/soc/pxa/pxa-ssp.c
@@ -50,139 +50,6 @@ struct ssp_priv {
50#endif 50#endif
51}; 51};
52 52
53#define PXA2xx_SSP1_BASE 0x41000000
54#define PXA27x_SSP2_BASE 0x41700000
55#define PXA27x_SSP3_BASE 0x41900000
56#define PXA3xx_SSP4_BASE 0x41a00000
57
58static struct pxa2xx_pcm_dma_params pxa_ssp1_pcm_mono_out = {
59 .name = "SSP1 PCM Mono out",
60 .dev_addr = PXA2xx_SSP1_BASE + SSDR,
61 .drcmr = &DRCMR(14),
62 .dcmd = DCMD_INCSRCADDR | DCMD_FLOWTRG |
63 DCMD_BURST16 | DCMD_WIDTH2,
64};
65
66static struct pxa2xx_pcm_dma_params pxa_ssp1_pcm_mono_in = {
67 .name = "SSP1 PCM Mono in",
68 .dev_addr = PXA2xx_SSP1_BASE + SSDR,
69 .drcmr = &DRCMR(13),
70 .dcmd = DCMD_INCTRGADDR | DCMD_FLOWSRC |
71 DCMD_BURST16 | DCMD_WIDTH2,
72};
73
74static struct pxa2xx_pcm_dma_params pxa_ssp1_pcm_stereo_out = {
75 .name = "SSP1 PCM Stereo out",
76 .dev_addr = PXA2xx_SSP1_BASE + SSDR,
77 .drcmr = &DRCMR(14),
78 .dcmd = DCMD_INCSRCADDR | DCMD_FLOWTRG |
79 DCMD_BURST16 | DCMD_WIDTH4,
80};
81
82static struct pxa2xx_pcm_dma_params pxa_ssp1_pcm_stereo_in = {
83 .name = "SSP1 PCM Stereo in",
84 .dev_addr = PXA2xx_SSP1_BASE + SSDR,
85 .drcmr = &DRCMR(13),
86 .dcmd = DCMD_INCTRGADDR | DCMD_FLOWSRC |
87 DCMD_BURST16 | DCMD_WIDTH4,
88};
89
90static struct pxa2xx_pcm_dma_params pxa_ssp2_pcm_mono_out = {
91 .name = "SSP2 PCM Mono out",
92 .dev_addr = PXA27x_SSP2_BASE + SSDR,
93 .drcmr = &DRCMR(16),
94 .dcmd = DCMD_INCSRCADDR | DCMD_FLOWTRG |
95 DCMD_BURST16 | DCMD_WIDTH2,
96};
97
98static struct pxa2xx_pcm_dma_params pxa_ssp2_pcm_mono_in = {
99 .name = "SSP2 PCM Mono in",
100 .dev_addr = PXA27x_SSP2_BASE + SSDR,
101 .drcmr = &DRCMR(15),
102 .dcmd = DCMD_INCTRGADDR | DCMD_FLOWSRC |
103 DCMD_BURST16 | DCMD_WIDTH2,
104};
105
106static struct pxa2xx_pcm_dma_params pxa_ssp2_pcm_stereo_out = {
107 .name = "SSP2 PCM Stereo out",
108 .dev_addr = PXA27x_SSP2_BASE + SSDR,
109 .drcmr = &DRCMR(16),
110 .dcmd = DCMD_INCSRCADDR | DCMD_FLOWTRG |
111 DCMD_BURST16 | DCMD_WIDTH4,
112};
113
114static struct pxa2xx_pcm_dma_params pxa_ssp2_pcm_stereo_in = {
115 .name = "SSP2 PCM Stereo in",
116 .dev_addr = PXA27x_SSP2_BASE + SSDR,
117 .drcmr = &DRCMR(15),
118 .dcmd = DCMD_INCTRGADDR | DCMD_FLOWSRC |
119 DCMD_BURST16 | DCMD_WIDTH4,
120};
121
122static struct pxa2xx_pcm_dma_params pxa_ssp3_pcm_mono_out = {
123 .name = "SSP3 PCM Mono out",
124 .dev_addr = PXA27x_SSP3_BASE + SSDR,
125 .drcmr = &DRCMR(67),
126 .dcmd = DCMD_INCSRCADDR | DCMD_FLOWTRG |
127 DCMD_BURST16 | DCMD_WIDTH2,
128};
129
130static struct pxa2xx_pcm_dma_params pxa_ssp3_pcm_mono_in = {
131 .name = "SSP3 PCM Mono in",
132 .dev_addr = PXA27x_SSP3_BASE + SSDR,
133 .drcmr = &DRCMR(66),
134 .dcmd = DCMD_INCTRGADDR | DCMD_FLOWSRC |
135 DCMD_BURST16 | DCMD_WIDTH2,
136};
137
138static struct pxa2xx_pcm_dma_params pxa_ssp3_pcm_stereo_out = {
139 .name = "SSP3 PCM Stereo out",
140 .dev_addr = PXA27x_SSP3_BASE + SSDR,
141 .drcmr = &DRCMR(67),
142 .dcmd = DCMD_INCSRCADDR | DCMD_FLOWTRG |
143 DCMD_BURST16 | DCMD_WIDTH4,
144};
145
146static struct pxa2xx_pcm_dma_params pxa_ssp3_pcm_stereo_in = {
147 .name = "SSP3 PCM Stereo in",
148 .dev_addr = PXA27x_SSP3_BASE + SSDR,
149 .drcmr = &DRCMR(66),
150 .dcmd = DCMD_INCTRGADDR | DCMD_FLOWSRC |
151 DCMD_BURST16 | DCMD_WIDTH4,
152};
153
154static struct pxa2xx_pcm_dma_params pxa_ssp4_pcm_mono_out = {
155 .name = "SSP4 PCM Mono out",
156 .dev_addr = PXA3xx_SSP4_BASE + SSDR,
157 .drcmr = &DRCMR(67),
158 .dcmd = DCMD_INCSRCADDR | DCMD_FLOWTRG |
159 DCMD_BURST16 | DCMD_WIDTH2,
160};
161
162static struct pxa2xx_pcm_dma_params pxa_ssp4_pcm_mono_in = {
163 .name = "SSP4 PCM Mono in",
164 .dev_addr = PXA3xx_SSP4_BASE + SSDR,
165 .drcmr = &DRCMR(66),
166 .dcmd = DCMD_INCTRGADDR | DCMD_FLOWSRC |
167 DCMD_BURST16 | DCMD_WIDTH2,
168};
169
170static struct pxa2xx_pcm_dma_params pxa_ssp4_pcm_stereo_out = {
171 .name = "SSP4 PCM Stereo out",
172 .dev_addr = PXA3xx_SSP4_BASE + SSDR,
173 .drcmr = &DRCMR(67),
174 .dcmd = DCMD_INCSRCADDR | DCMD_FLOWTRG |
175 DCMD_BURST16 | DCMD_WIDTH4,
176};
177
178static struct pxa2xx_pcm_dma_params pxa_ssp4_pcm_stereo_in = {
179 .name = "SSP4 PCM Stereo in",
180 .dev_addr = PXA3xx_SSP4_BASE + SSDR,
181 .drcmr = &DRCMR(66),
182 .dcmd = DCMD_INCTRGADDR | DCMD_FLOWSRC |
183 DCMD_BURST16 | DCMD_WIDTH4,
184};
185
186static void dump_registers(struct ssp_device *ssp) 53static void dump_registers(struct ssp_device *ssp)
187{ 54{
188 dev_dbg(&ssp->pdev->dev, "SSCR0 0x%08x SSCR1 0x%08x SSTO 0x%08x\n", 55 dev_dbg(&ssp->pdev->dev, "SSCR0 0x%08x SSCR1 0x%08x SSTO 0x%08x\n",
@@ -194,25 +61,33 @@ static void dump_registers(struct ssp_device *ssp)
194 ssp_read_reg(ssp, SSACD)); 61 ssp_read_reg(ssp, SSACD));
195} 62}
196 63
197static struct pxa2xx_pcm_dma_params *ssp_dma_params[4][4] = { 64struct pxa2xx_pcm_dma_data {
198 { 65 struct pxa2xx_pcm_dma_params params;
199 &pxa_ssp1_pcm_mono_out, &pxa_ssp1_pcm_mono_in, 66 char name[20];
200 &pxa_ssp1_pcm_stereo_out, &pxa_ssp1_pcm_stereo_in,
201 },
202 {
203 &pxa_ssp2_pcm_mono_out, &pxa_ssp2_pcm_mono_in,
204 &pxa_ssp2_pcm_stereo_out, &pxa_ssp2_pcm_stereo_in,
205 },
206 {
207 &pxa_ssp3_pcm_mono_out, &pxa_ssp3_pcm_mono_in,
208 &pxa_ssp3_pcm_stereo_out, &pxa_ssp3_pcm_stereo_in,
209 },
210 {
211 &pxa_ssp4_pcm_mono_out, &pxa_ssp4_pcm_mono_in,
212 &pxa_ssp4_pcm_stereo_out, &pxa_ssp4_pcm_stereo_in,
213 },
214}; 67};
215 68
69static struct pxa2xx_pcm_dma_params *
70ssp_get_dma_params(struct ssp_device *ssp, int width4, int out)
71{
72 struct pxa2xx_pcm_dma_data *dma;
73
74 dma = kzalloc(sizeof(struct pxa2xx_pcm_dma_data), GFP_KERNEL);
75 if (dma == NULL)
76 return NULL;
77
78 snprintf(dma->name, 20, "SSP%d PCM %s %s", ssp->port_id,
79 width4 ? "32-bit" : "16-bit", out ? "out" : "in");
80
81 dma->params.name = dma->name;
82 dma->params.drcmr = &DRCMR(out ? ssp->drcmr_tx : ssp->drcmr_rx);
83 dma->params.dcmd = (out ? (DCMD_INCSRCADDR | DCMD_FLOWTRG) :
84 (DCMD_INCTRGADDR | DCMD_FLOWSRC)) |
85 (width4 ? DCMD_WIDTH4 : DCMD_WIDTH2) | DCMD_BURST16;
86 dma->params.dev_addr = ssp->phys_base + SSDR;
87
88 return &dma->params;
89}
90
216static int pxa_ssp_startup(struct snd_pcm_substream *substream, 91static int pxa_ssp_startup(struct snd_pcm_substream *substream,
217 struct snd_soc_dai *dai) 92 struct snd_soc_dai *dai)
218{ 93{
@@ -227,6 +102,11 @@ static int pxa_ssp_startup(struct snd_pcm_substream *substream,
227 clk_enable(priv->dev.ssp->clk); 102 clk_enable(priv->dev.ssp->clk);
228 ssp_disable(&priv->dev); 103 ssp_disable(&priv->dev);
229 } 104 }
105
106 if (cpu_dai->dma_data) {
107 kfree(cpu_dai->dma_data);
108 cpu_dai->dma_data = NULL;
109 }
230 return ret; 110 return ret;
231} 111}
232 112
@@ -241,6 +121,11 @@ static void pxa_ssp_shutdown(struct snd_pcm_substream *substream,
241 ssp_disable(&priv->dev); 121 ssp_disable(&priv->dev);
242 clk_disable(priv->dev.ssp->clk); 122 clk_disable(priv->dev.ssp->clk);
243 } 123 }
124
125 if (cpu_dai->dma_data) {
126 kfree(cpu_dai->dma_data);
127 cpu_dai->dma_data = NULL;
128 }
244} 129}
245 130
246#ifdef CONFIG_PM 131#ifdef CONFIG_PM
@@ -323,7 +208,7 @@ static int pxa_ssp_set_dai_sysclk(struct snd_soc_dai *cpu_dai,
323 ~(SSCR0_ECS | SSCR0_NCS | SSCR0_MOD | SSCR0_ACS); 208 ~(SSCR0_ECS | SSCR0_NCS | SSCR0_MOD | SSCR0_ACS);
324 209
325 dev_dbg(&ssp->pdev->dev, 210 dev_dbg(&ssp->pdev->dev,
326 "pxa_ssp_set_dai_sysclk id: %d, clk_id %d, freq %d\n", 211 "pxa_ssp_set_dai_sysclk id: %d, clk_id %d, freq %u\n",
327 cpu_dai->id, clk_id, freq); 212 cpu_dai->id, clk_id, freq);
328 213
329 switch (clk_id) { 214 switch (clk_id) {
@@ -472,7 +357,7 @@ static int pxa_ssp_set_dai_pll(struct snd_soc_dai *cpu_dai,
472 ssacd |= (0x6 << 4); 357 ssacd |= (0x6 << 4);
473 358
474 dev_dbg(&ssp->pdev->dev, 359 dev_dbg(&ssp->pdev->dev,
475 "Using SSACDD %x to supply %dHz\n", 360 "Using SSACDD %x to supply %uHz\n",
476 val, freq_out); 361 val, freq_out);
477 break; 362 break;
478 } 363 }
@@ -490,21 +375,34 @@ static int pxa_ssp_set_dai_pll(struct snd_soc_dai *cpu_dai,
490 * Set the active slots in TDM/Network mode 375 * Set the active slots in TDM/Network mode
491 */ 376 */
492static int pxa_ssp_set_dai_tdm_slot(struct snd_soc_dai *cpu_dai, 377static int pxa_ssp_set_dai_tdm_slot(struct snd_soc_dai *cpu_dai,
493 unsigned int mask, int slots) 378 unsigned int tx_mask, unsigned int rx_mask, int slots, int slot_width)
494{ 379{
495 struct ssp_priv *priv = cpu_dai->private_data; 380 struct ssp_priv *priv = cpu_dai->private_data;
496 struct ssp_device *ssp = priv->dev.ssp; 381 struct ssp_device *ssp = priv->dev.ssp;
497 u32 sscr0; 382 u32 sscr0;
498 383
499 sscr0 = ssp_read_reg(ssp, SSCR0) & ~SSCR0_SlotsPerFrm(7); 384 sscr0 = ssp_read_reg(ssp, SSCR0);
385 sscr0 &= ~(SSCR0_MOD | SSCR0_SlotsPerFrm(8) | SSCR0_EDSS | SSCR0_DSS);
500 386
501 /* set number of active slots */ 387 /* set slot width */
502 sscr0 |= SSCR0_SlotsPerFrm(slots); 388 if (slot_width > 16)
389 sscr0 |= SSCR0_EDSS | SSCR0_DataSize(slot_width - 16);
390 else
391 sscr0 |= SSCR0_DataSize(slot_width);
392
393 if (slots > 1) {
394 /* enable network mode */
395 sscr0 |= SSCR0_MOD;
396
397 /* set number of active slots */
398 sscr0 |= SSCR0_SlotsPerFrm(slots);
399
400 /* set active slot mask */
401 ssp_write_reg(ssp, SSTSA, tx_mask);
402 ssp_write_reg(ssp, SSRSA, rx_mask);
403 }
503 ssp_write_reg(ssp, SSCR0, sscr0); 404 ssp_write_reg(ssp, SSCR0, sscr0);
504 405
505 /* set active slot mask */
506 ssp_write_reg(ssp, SSTSA, mask);
507 ssp_write_reg(ssp, SSRSA, mask);
508 return 0; 406 return 0;
509} 407}
510 408
@@ -572,28 +470,27 @@ static int pxa_ssp_set_dai_fmt(struct snd_soc_dai *cpu_dai,
572 return -EINVAL; 470 return -EINVAL;
573 } 471 }
574 472
575 ssp_write_reg(ssp, SSCR0, sscr0); 473 switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
576 ssp_write_reg(ssp, SSCR1, sscr1); 474 case SND_SOC_DAIFMT_NB_NF:
577 ssp_write_reg(ssp, SSPSP, sspsp); 475 sspsp |= SSPSP_SFRMP;
476 break;
477 case SND_SOC_DAIFMT_NB_IF:
478 break;
479 case SND_SOC_DAIFMT_IB_IF:
480 sspsp |= SSPSP_SCMODE(2);
481 break;
482 case SND_SOC_DAIFMT_IB_NF:
483 sspsp |= SSPSP_SCMODE(2) | SSPSP_SFRMP;
484 break;
485 default:
486 return -EINVAL;
487 }
578 488
579 switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { 489 switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
580 case SND_SOC_DAIFMT_I2S: 490 case SND_SOC_DAIFMT_I2S:
581 sscr0 |= SSCR0_PSP; 491 sscr0 |= SSCR0_PSP;
582 sscr1 |= SSCR1_RWOT | SSCR1_TRAIL; 492 sscr1 |= SSCR1_RWOT | SSCR1_TRAIL;
583
584 /* See hw_params() */ 493 /* See hw_params() */
585 switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
586 case SND_SOC_DAIFMT_NB_NF:
587 sspsp |= SSPSP_SFRMP;
588 break;
589 case SND_SOC_DAIFMT_NB_IF:
590 break;
591 case SND_SOC_DAIFMT_IB_IF:
592 sspsp |= SSPSP_SCMODE(3);
593 break;
594 default:
595 return -EINVAL;
596 }
597 break; 494 break;
598 495
599 case SND_SOC_DAIFMT_DSP_A: 496 case SND_SOC_DAIFMT_DSP_A:
@@ -601,16 +498,6 @@ static int pxa_ssp_set_dai_fmt(struct snd_soc_dai *cpu_dai,
601 case SND_SOC_DAIFMT_DSP_B: 498 case SND_SOC_DAIFMT_DSP_B:
602 sscr0 |= SSCR0_MOD | SSCR0_PSP; 499 sscr0 |= SSCR0_MOD | SSCR0_PSP;
603 sscr1 |= SSCR1_TRAIL | SSCR1_RWOT; 500 sscr1 |= SSCR1_TRAIL | SSCR1_RWOT;
604
605 switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
606 case SND_SOC_DAIFMT_NB_NF:
607 sspsp |= SSPSP_SFRMP;
608 break;
609 case SND_SOC_DAIFMT_IB_IF:
610 break;
611 default:
612 return -EINVAL;
613 }
614 break; 501 break;
615 502
616 default: 503 default:
@@ -644,25 +531,23 @@ static int pxa_ssp_hw_params(struct snd_pcm_substream *substream,
644 struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai; 531 struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai;
645 struct ssp_priv *priv = cpu_dai->private_data; 532 struct ssp_priv *priv = cpu_dai->private_data;
646 struct ssp_device *ssp = priv->dev.ssp; 533 struct ssp_device *ssp = priv->dev.ssp;
647 int dma = 0, chn = params_channels(params); 534 int chn = params_channels(params);
648 u32 sscr0; 535 u32 sscr0;
649 u32 sspsp; 536 u32 sspsp;
650 int width = snd_pcm_format_physical_width(params_format(params)); 537 int width = snd_pcm_format_physical_width(params_format(params));
651 int ttsa = ssp_read_reg(ssp, SSTSA) & 0xf; 538 int ttsa = ssp_read_reg(ssp, SSTSA) & 0xf;
652 539
653 /* select correct DMA params */ 540 /* generate correct DMA params */
654 if (substream->stream != SNDRV_PCM_STREAM_PLAYBACK) 541 if (cpu_dai->dma_data)
655 dma = 1; /* capture DMA offset is 1,3 */ 542 kfree(cpu_dai->dma_data);
543
656 /* Network mode with one active slot (ttsa == 1) can be used 544 /* Network mode with one active slot (ttsa == 1) can be used
657 * to force 16-bit frame width on the wire (for S16_LE), even 545 * to force 16-bit frame width on the wire (for S16_LE), even
658 * with two channels. Use 16-bit DMA transfers for this case. 546 * with two channels. Use 16-bit DMA transfers for this case.
659 */ 547 */
660 if (((chn == 2) && (ttsa != 1)) || (width == 32)) 548 cpu_dai->dma_data = ssp_get_dma_params(ssp,
661 dma += 2; /* 32-bit DMA offset is 2, 16-bit is 0 */ 549 ((chn == 2) && (ttsa != 1)) || (width == 32),
662 550 substream->stream == SNDRV_PCM_STREAM_PLAYBACK);
663 cpu_dai->dma_data = ssp_dma_params[cpu_dai->id][dma];
664
665 dev_dbg(&ssp->pdev->dev, "pxa_ssp_hw_params: dma %d\n", dma);
666 551
667 /* we can only change the settings if the port is not in use */ 552 /* we can only change the settings if the port is not in use */
668 if (ssp_read_reg(ssp, SSCR0) & SSCR0_SSE) 553 if (ssp_read_reg(ssp, SSCR0) & SSCR0_SSE)
diff --git a/sound/soc/pxa/pxa2xx-ac97.c b/sound/soc/pxa/pxa2xx-ac97.c
index d9c94d71fa61..7330e5c5b9df 100644
--- a/sound/soc/pxa/pxa2xx-ac97.c
+++ b/sound/soc/pxa/pxa2xx-ac97.c
@@ -22,6 +22,7 @@
22#include <mach/hardware.h> 22#include <mach/hardware.h>
23#include <mach/regs-ac97.h> 23#include <mach/regs-ac97.h>
24#include <mach/dma.h> 24#include <mach/dma.h>
25#include <mach/audio.h>
25 26
26#include "pxa2xx-pcm.h" 27#include "pxa2xx-pcm.h"
27#include "pxa2xx-ac97.h" 28#include "pxa2xx-ac97.h"
@@ -241,9 +242,18 @@ EXPORT_SYMBOL_GPL(soc_ac97_ops);
241static int __devinit pxa2xx_ac97_dev_probe(struct platform_device *pdev) 242static int __devinit pxa2xx_ac97_dev_probe(struct platform_device *pdev)
242{ 243{
243 int i; 244 int i;
245 pxa2xx_audio_ops_t *pdata = pdev->dev.platform_data;
244 246
245 for (i = 0; i < ARRAY_SIZE(pxa_ac97_dai); i++) 247 if (pdev->id >= 0) {
248 dev_err(&pdev->dev, "PXA2xx has only one AC97 port.\n");
249 return -ENXIO;
250 }
251
252 for (i = 0; i < ARRAY_SIZE(pxa_ac97_dai); i++) {
246 pxa_ac97_dai[i].dev = &pdev->dev; 253 pxa_ac97_dai[i].dev = &pdev->dev;
254 if (pdata && pdata->codec_pdata)
255 pxa_ac97_dai[i].ac97_pdata = pdata->codec_pdata;
256 }
247 257
248 /* Punt most of the init to the SoC probe; we may need the machine 258 /* Punt most of the init to the SoC probe; we may need the machine
249 * driver to do interesting things with the clocking to get us up 259 * driver to do interesting things with the clocking to get us up
diff --git a/sound/soc/pxa/pxa2xx-i2s.c b/sound/soc/pxa/pxa2xx-i2s.c
index 2f4b6e489b78..6b8f655d1ad8 100644
--- a/sound/soc/pxa/pxa2xx-i2s.c
+++ b/sound/soc/pxa/pxa2xx-i2s.c
@@ -106,10 +106,8 @@ static int pxa2xx_i2s_startup(struct snd_pcm_substream *substream,
106 if (IS_ERR(clk_i2s)) 106 if (IS_ERR(clk_i2s))
107 return PTR_ERR(clk_i2s); 107 return PTR_ERR(clk_i2s);
108 108
109 if (!cpu_dai->active) { 109 if (!cpu_dai->active)
110 SACR0 |= SACR0_RST;
111 SACR0 = 0; 110 SACR0 = 0;
112 }
113 111
114 return 0; 112 return 0;
115} 113}
@@ -169,6 +167,7 @@ static int pxa2xx_i2s_hw_params(struct snd_pcm_substream *substream,
169 167
170 BUG_ON(IS_ERR(clk_i2s)); 168 BUG_ON(IS_ERR(clk_i2s));
171 clk_enable(clk_i2s); 169 clk_enable(clk_i2s);
170 dai->private_data = dai;
172 pxa_i2s_wait(); 171 pxa_i2s_wait();
173 172
174 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) 173 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
@@ -178,9 +177,7 @@ static int pxa2xx_i2s_hw_params(struct snd_pcm_substream *substream,
178 177
179 /* is port used by another stream */ 178 /* is port used by another stream */
180 if (!(SACR0 & SACR0_ENB)) { 179 if (!(SACR0 & SACR0_ENB)) {
181
182 SACR0 = 0; 180 SACR0 = 0;
183 SACR1 = 0;
184 if (pxa_i2s.master) 181 if (pxa_i2s.master)
185 SACR0 |= SACR0_BCKD; 182 SACR0 |= SACR0_BCKD;
186 183
@@ -226,6 +223,10 @@ static int pxa2xx_i2s_trigger(struct snd_pcm_substream *substream, int cmd,
226 223
227 switch (cmd) { 224 switch (cmd) {
228 case SNDRV_PCM_TRIGGER_START: 225 case SNDRV_PCM_TRIGGER_START:
226 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
227 SACR1 &= ~SACR1_DRPL;
228 else
229 SACR1 &= ~SACR1_DREC;
229 SACR0 |= SACR0_ENB; 230 SACR0 |= SACR0_ENB;
230 break; 231 break;
231 case SNDRV_PCM_TRIGGER_RESUME: 232 case SNDRV_PCM_TRIGGER_RESUME:
@@ -252,21 +253,19 @@ static void pxa2xx_i2s_shutdown(struct snd_pcm_substream *substream,
252 SAIMR &= ~SAIMR_RFS; 253 SAIMR &= ~SAIMR_RFS;
253 } 254 }
254 255
255 if (SACR1 & (SACR1_DREC | SACR1_DRPL)) { 256 if ((SACR1 & (SACR1_DREC | SACR1_DRPL)) == (SACR1_DREC | SACR1_DRPL)) {
256 SACR0 &= ~SACR0_ENB; 257 SACR0 &= ~SACR0_ENB;
257 pxa_i2s_wait(); 258 pxa_i2s_wait();
258 clk_disable(clk_i2s); 259 if (dai->private_data != NULL) {
260 clk_disable(clk_i2s);
261 dai->private_data = NULL;
262 }
259 } 263 }
260
261 clk_put(clk_i2s);
262} 264}
263 265
264#ifdef CONFIG_PM 266#ifdef CONFIG_PM
265static int pxa2xx_i2s_suspend(struct snd_soc_dai *dai) 267static int pxa2xx_i2s_suspend(struct snd_soc_dai *dai)
266{ 268{
267 if (!dai->active)
268 return 0;
269
270 /* store registers */ 269 /* store registers */
271 pxa_i2s.sacr0 = SACR0; 270 pxa_i2s.sacr0 = SACR0;
272 pxa_i2s.sacr1 = SACR1; 271 pxa_i2s.sacr1 = SACR1;
@@ -281,16 +280,14 @@ static int pxa2xx_i2s_suspend(struct snd_soc_dai *dai)
281 280
282static int pxa2xx_i2s_resume(struct snd_soc_dai *dai) 281static int pxa2xx_i2s_resume(struct snd_soc_dai *dai)
283{ 282{
284 if (!dai->active)
285 return 0;
286
287 pxa_i2s_wait(); 283 pxa_i2s_wait();
288 284
289 SACR0 = pxa_i2s.sacr0 &= ~SACR0_ENB; 285 SACR0 = pxa_i2s.sacr0 & ~SACR0_ENB;
290 SACR1 = pxa_i2s.sacr1; 286 SACR1 = pxa_i2s.sacr1;
291 SAIMR = pxa_i2s.saimr; 287 SAIMR = pxa_i2s.saimr;
292 SADIV = pxa_i2s.sadiv; 288 SADIV = pxa_i2s.sadiv;
293 SACR0 |= SACR0_ENB; 289
290 SACR0 = pxa_i2s.sacr0;
294 291
295 return 0; 292 return 0;
296} 293}
@@ -329,6 +326,7 @@ struct snd_soc_dai pxa_i2s_dai = {
329 .rates = PXA2XX_I2S_RATES, 326 .rates = PXA2XX_I2S_RATES,
330 .formats = SNDRV_PCM_FMTBIT_S16_LE,}, 327 .formats = SNDRV_PCM_FMTBIT_S16_LE,},
331 .ops = &pxa_i2s_dai_ops, 328 .ops = &pxa_i2s_dai_ops,
329 .symmetric_rates = 1,
332}; 330};
333 331
334EXPORT_SYMBOL_GPL(pxa_i2s_dai); 332EXPORT_SYMBOL_GPL(pxa_i2s_dai);
@@ -342,10 +340,24 @@ static int pxa2xx_i2s_probe(struct platform_device *dev)
342 return PTR_ERR(clk_i2s); 340 return PTR_ERR(clk_i2s);
343 341
344 pxa_i2s_dai.dev = &dev->dev; 342 pxa_i2s_dai.dev = &dev->dev;
343 pxa_i2s_dai.private_data = NULL;
345 ret = snd_soc_register_dai(&pxa_i2s_dai); 344 ret = snd_soc_register_dai(&pxa_i2s_dai);
346 if (ret != 0) 345 if (ret != 0)
347 clk_put(clk_i2s); 346 clk_put(clk_i2s);
348 347
348 /*
349 * PXA Developer's Manual:
350 * If SACR0[ENB] is toggled in the middle of a normal operation,
351 * the SACR0[RST] bit must also be set and cleared to reset all
352 * I2S controller registers.
353 */
354 SACR0 = SACR0_RST;
355 SACR0 = 0;
356 /* Make sure RPL and REC are disabled */
357 SACR1 = SACR1_DRPL | SACR1_DREC;
358 /* Along with FIFO servicing */
359 SAIMR &= ~(SAIMR_RFS | SAIMR_TFS);
360
349 return ret; 361 return ret;
350} 362}
351 363
diff --git a/sound/soc/s3c24xx/Kconfig b/sound/soc/s3c24xx/Kconfig
index df494d1e346f..808de5c5caa7 100644
--- a/sound/soc/s3c24xx/Kconfig
+++ b/sound/soc/s3c24xx/Kconfig
@@ -38,6 +38,15 @@ config SND_S3C24XX_SOC_NEO1973_WM8753
38 Say Y if you want to add support for SoC audio on smdk2440 38 Say Y if you want to add support for SoC audio on smdk2440
39 with the WM8753. 39 with the WM8753.
40 40
41config SND_S3C24XX_SOC_NEO1973_GTA02_WM8753
42 tristate "Audio support for the Openmoko Neo FreeRunner (GTA02)"
43 depends on SND_S3C24XX_SOC && MACH_NEO1973_GTA02
44 select SND_S3C24XX_SOC_I2S
45 select SND_SOC_WM8753
46 help
47 This driver provides audio support for the Openmoko Neo FreeRunner
48 smartphone.
49
41config SND_S3C24XX_SOC_JIVE_WM8750 50config SND_S3C24XX_SOC_JIVE_WM8750
42 tristate "SoC I2S Audio support for Jive" 51 tristate "SoC I2S Audio support for Jive"
43 depends on SND_S3C24XX_SOC && MACH_JIVE 52 depends on SND_S3C24XX_SOC && MACH_JIVE
@@ -57,7 +66,7 @@ config SND_S3C24XX_SOC_SMDK2443_WM9710
57 66
58config SND_S3C24XX_SOC_LN2440SBC_ALC650 67config SND_S3C24XX_SOC_LN2440SBC_ALC650
59 tristate "SoC AC97 Audio support for LN2440SBC - ALC650" 68 tristate "SoC AC97 Audio support for LN2440SBC - ALC650"
60 depends on SND_S3C24XX_SOC 69 depends on SND_S3C24XX_SOC && ARCH_S3C2410
61 select SND_S3C2443_SOC_AC97 70 select SND_S3C2443_SOC_AC97
62 select SND_SOC_AC97_CODEC 71 select SND_SOC_AC97_CODEC
63 help 72 help
@@ -66,7 +75,7 @@ config SND_S3C24XX_SOC_LN2440SBC_ALC650
66 75
67config SND_S3C24XX_SOC_S3C24XX_UDA134X 76config SND_S3C24XX_SOC_S3C24XX_UDA134X
68 tristate "SoC I2S Audio support UDA134X wired to a S3C24XX" 77 tristate "SoC I2S Audio support UDA134X wired to a S3C24XX"
69 depends on SND_S3C24XX_SOC 78 depends on SND_S3C24XX_SOC && ARCH_S3C2410
70 select SND_S3C24XX_SOC_I2S 79 select SND_S3C24XX_SOC_I2S
71 select SND_SOC_L3 80 select SND_SOC_L3
72 select SND_SOC_UDA134X 81 select SND_SOC_UDA134X
diff --git a/sound/soc/s3c24xx/Makefile b/sound/soc/s3c24xx/Makefile
index 07a93a2ebe5f..eb219b016499 100644
--- a/sound/soc/s3c24xx/Makefile
+++ b/sound/soc/s3c24xx/Makefile
@@ -16,12 +16,14 @@ obj-$(CONFIG_SND_S3C_I2SV2_SOC) += snd-soc-s3c-i2s-v2.o
16# S3C24XX Machine Support 16# S3C24XX Machine Support
17snd-soc-jive-wm8750-objs := jive_wm8750.o 17snd-soc-jive-wm8750-objs := jive_wm8750.o
18snd-soc-neo1973-wm8753-objs := neo1973_wm8753.o 18snd-soc-neo1973-wm8753-objs := neo1973_wm8753.o
19snd-soc-neo1973-gta02-wm8753-objs := neo1973_gta02_wm8753.o
19snd-soc-smdk2443-wm9710-objs := smdk2443_wm9710.o 20snd-soc-smdk2443-wm9710-objs := smdk2443_wm9710.o
20snd-soc-ln2440sbc-alc650-objs := ln2440sbc_alc650.o 21snd-soc-ln2440sbc-alc650-objs := ln2440sbc_alc650.o
21snd-soc-s3c24xx-uda134x-objs := s3c24xx_uda134x.o 22snd-soc-s3c24xx-uda134x-objs := s3c24xx_uda134x.o
22 23
23obj-$(CONFIG_SND_S3C24XX_SOC_JIVE_WM8750) += snd-soc-jive-wm8750.o 24obj-$(CONFIG_SND_S3C24XX_SOC_JIVE_WM8750) += snd-soc-jive-wm8750.o
24obj-$(CONFIG_SND_S3C24XX_SOC_NEO1973_WM8753) += snd-soc-neo1973-wm8753.o 25obj-$(CONFIG_SND_S3C24XX_SOC_NEO1973_WM8753) += snd-soc-neo1973-wm8753.o
26obj-$(CONFIG_SND_S3C24XX_SOC_NEO1973_GTA02_WM8753) += snd-soc-neo1973-gta02-wm8753.o
25obj-$(CONFIG_SND_S3C24XX_SOC_SMDK2443_WM9710) += snd-soc-smdk2443-wm9710.o 27obj-$(CONFIG_SND_S3C24XX_SOC_SMDK2443_WM9710) += snd-soc-smdk2443-wm9710.o
26obj-$(CONFIG_SND_S3C24XX_SOC_LN2440SBC_ALC650) += snd-soc-ln2440sbc-alc650.o 28obj-$(CONFIG_SND_S3C24XX_SOC_LN2440SBC_ALC650) += snd-soc-ln2440sbc-alc650.o
27obj-$(CONFIG_SND_S3C24XX_SOC_S3C24XX_UDA134X) += snd-soc-s3c24xx-uda134x.o 29obj-$(CONFIG_SND_S3C24XX_SOC_S3C24XX_UDA134X) += snd-soc-s3c24xx-uda134x.o
diff --git a/sound/soc/s3c24xx/neo1973_gta02_wm8753.c b/sound/soc/s3c24xx/neo1973_gta02_wm8753.c
new file mode 100644
index 000000000000..0c52e36ddd87
--- /dev/null
+++ b/sound/soc/s3c24xx/neo1973_gta02_wm8753.c
@@ -0,0 +1,498 @@
1/*
2 * neo1973_gta02_wm8753.c -- SoC audio for Openmoko Freerunner(GTA02)
3 *
4 * Copyright 2007 Openmoko Inc
5 * Author: Graeme Gregory <graeme@openmoko.org>
6 * Copyright 2007 Wolfson Microelectronics PLC.
7 * Author: Graeme Gregory <linux@wolfsonmicro.com>
8 * Copyright 2009 Wolfson Microelectronics
9 *
10 * This program is free software; you can redistribute it and/or modify it
11 * under the terms of the GNU General Public License as published by the
12 * Free Software Foundation; either version 2 of the License, or (at your
13 * option) any later version.
14 */
15
16#include <linux/module.h>
17#include <linux/moduleparam.h>
18#include <linux/timer.h>
19#include <linux/interrupt.h>
20#include <linux/platform_device.h>
21#include <linux/gpio.h>
22#include <sound/core.h>
23#include <sound/pcm.h>
24#include <sound/soc.h>
25#include <sound/soc-dapm.h>
26
27#include <asm/mach-types.h>
28
29#include <plat/regs-iis.h>
30
31#include <mach/regs-clock.h>
32#include <asm/io.h>
33#include <mach/gta02.h>
34#include "../codecs/wm8753.h"
35#include "s3c24xx-pcm.h"
36#include "s3c24xx-i2s.h"
37
38static struct snd_soc_card neo1973_gta02;
39
40static int neo1973_gta02_hifi_hw_params(struct snd_pcm_substream *substream,
41 struct snd_pcm_hw_params *params)
42{
43 struct snd_soc_pcm_runtime *rtd = substream->private_data;
44 struct snd_soc_dai *codec_dai = rtd->dai->codec_dai;
45 struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai;
46 unsigned int pll_out = 0, bclk = 0;
47 int ret = 0;
48 unsigned long iis_clkrate;
49
50 iis_clkrate = s3c24xx_i2s_get_clockrate();
51
52 switch (params_rate(params)) {
53 case 8000:
54 case 16000:
55 pll_out = 12288000;
56 break;
57 case 48000:
58 bclk = WM8753_BCLK_DIV_4;
59 pll_out = 12288000;
60 break;
61 case 96000:
62 bclk = WM8753_BCLK_DIV_2;
63 pll_out = 12288000;
64 break;
65 case 11025:
66 bclk = WM8753_BCLK_DIV_16;
67 pll_out = 11289600;
68 break;
69 case 22050:
70 bclk = WM8753_BCLK_DIV_8;
71 pll_out = 11289600;
72 break;
73 case 44100:
74 bclk = WM8753_BCLK_DIV_4;
75 pll_out = 11289600;
76 break;
77 case 88200:
78 bclk = WM8753_BCLK_DIV_2;
79 pll_out = 11289600;
80 break;
81 }
82
83 /* set codec DAI configuration */
84 ret = snd_soc_dai_set_fmt(codec_dai,
85 SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF |
86 SND_SOC_DAIFMT_CBM_CFM);
87 if (ret < 0)
88 return ret;
89
90 /* set cpu DAI configuration */
91 ret = snd_soc_dai_set_fmt(cpu_dai,
92 SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF |
93 SND_SOC_DAIFMT_CBM_CFM);
94 if (ret < 0)
95 return ret;
96
97 /* set the codec system clock for DAC and ADC */
98 ret = snd_soc_dai_set_sysclk(codec_dai, WM8753_MCLK, pll_out,
99 SND_SOC_CLOCK_IN);
100 if (ret < 0)
101 return ret;
102
103 /* set MCLK division for sample rate */
104 ret = snd_soc_dai_set_clkdiv(cpu_dai, S3C24XX_DIV_MCLK,
105 S3C2410_IISMOD_32FS);
106 if (ret < 0)
107 return ret;
108
109 /* set codec BCLK division for sample rate */
110 ret = snd_soc_dai_set_clkdiv(codec_dai,
111 WM8753_BCLKDIV, bclk);
112 if (ret < 0)
113 return ret;
114
115 /* set prescaler division for sample rate */
116 ret = snd_soc_dai_set_clkdiv(cpu_dai, S3C24XX_DIV_PRESCALER,
117 S3C24XX_PRESCALE(4, 4));
118 if (ret < 0)
119 return ret;
120
121 /* codec PLL input is PCLK/4 */
122 ret = snd_soc_dai_set_pll(codec_dai, WM8753_PLL1,
123 iis_clkrate / 4, pll_out);
124 if (ret < 0)
125 return ret;
126
127 return 0;
128}
129
130static int neo1973_gta02_hifi_hw_free(struct snd_pcm_substream *substream)
131{
132 struct snd_soc_pcm_runtime *rtd = substream->private_data;
133 struct snd_soc_dai *codec_dai = rtd->dai->codec_dai;
134
135 /* disable the PLL */
136 return snd_soc_dai_set_pll(codec_dai, WM8753_PLL1, 0, 0);
137}
138
139/*
140 * Neo1973 WM8753 HiFi DAI opserations.
141 */
142static struct snd_soc_ops neo1973_gta02_hifi_ops = {
143 .hw_params = neo1973_gta02_hifi_hw_params,
144 .hw_free = neo1973_gta02_hifi_hw_free,
145};
146
147static int neo1973_gta02_voice_hw_params(
148 struct snd_pcm_substream *substream,
149 struct snd_pcm_hw_params *params)
150{
151 struct snd_soc_pcm_runtime *rtd = substream->private_data;
152 struct snd_soc_dai *codec_dai = rtd->dai->codec_dai;
153 unsigned int pcmdiv = 0;
154 int ret = 0;
155 unsigned long iis_clkrate;
156
157 iis_clkrate = s3c24xx_i2s_get_clockrate();
158
159 if (params_rate(params) != 8000)
160 return -EINVAL;
161 if (params_channels(params) != 1)
162 return -EINVAL;
163
164 pcmdiv = WM8753_PCM_DIV_6; /* 2.048 MHz */
165
166 /* todo: gg check mode (DSP_B) against CSR datasheet */
167 /* set codec DAI configuration */
168 ret = snd_soc_dai_set_fmt(codec_dai, SND_SOC_DAIFMT_DSP_B |
169 SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBS_CFS);
170 if (ret < 0)
171 return ret;
172
173 /* set the codec system clock for DAC and ADC */
174 ret = snd_soc_dai_set_sysclk(codec_dai, WM8753_PCMCLK,
175 12288000, SND_SOC_CLOCK_IN);
176 if (ret < 0)
177 return ret;
178
179 /* set codec PCM division for sample rate */
180 ret = snd_soc_dai_set_clkdiv(codec_dai, WM8753_PCMDIV,
181 pcmdiv);
182 if (ret < 0)
183 return ret;
184
185 /* configue and enable PLL for 12.288MHz output */
186 ret = snd_soc_dai_set_pll(codec_dai, WM8753_PLL2,
187 iis_clkrate / 4, 12288000);
188 if (ret < 0)
189 return ret;
190
191 return 0;
192}
193
194static int neo1973_gta02_voice_hw_free(struct snd_pcm_substream *substream)
195{
196 struct snd_soc_pcm_runtime *rtd = substream->private_data;
197 struct snd_soc_dai *codec_dai = rtd->dai->codec_dai;
198
199 /* disable the PLL */
200 return snd_soc_dai_set_pll(codec_dai, WM8753_PLL2, 0, 0);
201}
202
203static struct snd_soc_ops neo1973_gta02_voice_ops = {
204 .hw_params = neo1973_gta02_voice_hw_params,
205 .hw_free = neo1973_gta02_voice_hw_free,
206};
207
208#define LM4853_AMP 1
209#define LM4853_SPK 2
210
211static u8 lm4853_state;
212
213/* This has no effect, it exists only to maintain compatibility with
214 * existing ALSA state files.
215 */
216static int lm4853_set_state(struct snd_kcontrol *kcontrol,
217 struct snd_ctl_elem_value *ucontrol)
218{
219 int val = ucontrol->value.integer.value[0];
220
221 if (val)
222 lm4853_state |= LM4853_AMP;
223 else
224 lm4853_state &= ~LM4853_AMP;
225
226 return 0;
227}
228
229static int lm4853_get_state(struct snd_kcontrol *kcontrol,
230 struct snd_ctl_elem_value *ucontrol)
231{
232 ucontrol->value.integer.value[0] = lm4853_state & LM4853_AMP;
233
234 return 0;
235}
236
237static int lm4853_set_spk(struct snd_kcontrol *kcontrol,
238 struct snd_ctl_elem_value *ucontrol)
239{
240 int val = ucontrol->value.integer.value[0];
241
242 if (val) {
243 lm4853_state |= LM4853_SPK;
244 gpio_set_value(GTA02_GPIO_HP_IN, 0);
245 } else {
246 lm4853_state &= ~LM4853_SPK;
247 gpio_set_value(GTA02_GPIO_HP_IN, 1);
248 }
249
250 return 0;
251}
252
253static int lm4853_get_spk(struct snd_kcontrol *kcontrol,
254 struct snd_ctl_elem_value *ucontrol)
255{
256 ucontrol->value.integer.value[0] = (lm4853_state & LM4853_SPK) >> 1;
257
258 return 0;
259}
260
261static int lm4853_event(struct snd_soc_dapm_widget *w,
262 struct snd_kcontrol *k,
263 int event)
264{
265 gpio_set_value(GTA02_GPIO_AMP_SHUT, SND_SOC_DAPM_EVENT_OFF(value));
266
267 return 0;
268}
269
270static const struct snd_soc_dapm_widget wm8753_dapm_widgets[] = {
271 SND_SOC_DAPM_SPK("Stereo Out", lm4853_event),
272 SND_SOC_DAPM_LINE("GSM Line Out", NULL),
273 SND_SOC_DAPM_LINE("GSM Line In", NULL),
274 SND_SOC_DAPM_MIC("Headset Mic", NULL),
275 SND_SOC_DAPM_MIC("Handset Mic", NULL),
276 SND_SOC_DAPM_SPK("Handset Spk", NULL),
277};
278
279
280/* example machine audio_mapnections */
281static const struct snd_soc_dapm_route audio_map[] = {
282
283 /* Connections to the lm4853 amp */
284 {"Stereo Out", NULL, "LOUT1"},
285 {"Stereo Out", NULL, "ROUT1"},
286
287 /* Connections to the GSM Module */
288 {"GSM Line Out", NULL, "MONO1"},
289 {"GSM Line Out", NULL, "MONO2"},
290 {"RXP", NULL, "GSM Line In"},
291 {"RXN", NULL, "GSM Line In"},
292
293 /* Connections to Headset */
294 {"MIC1", NULL, "Mic Bias"},
295 {"Mic Bias", NULL, "Headset Mic"},
296
297 /* Call Mic */
298 {"MIC2", NULL, "Mic Bias"},
299 {"MIC2N", NULL, "Mic Bias"},
300 {"Mic Bias", NULL, "Handset Mic"},
301
302 /* Call Speaker */
303 {"Handset Spk", NULL, "LOUT2"},
304 {"Handset Spk", NULL, "ROUT2"},
305
306 /* Connect the ALC pins */
307 {"ACIN", NULL, "ACOP"},
308};
309
310static const struct snd_kcontrol_new wm8753_neo1973_gta02_controls[] = {
311 SOC_DAPM_PIN_SWITCH("Stereo Out"),
312 SOC_DAPM_PIN_SWITCH("GSM Line Out"),
313 SOC_DAPM_PIN_SWITCH("GSM Line In"),
314 SOC_DAPM_PIN_SWITCH("Headset Mic"),
315 SOC_DAPM_PIN_SWITCH("Handset Mic"),
316 SOC_DAPM_PIN_SWITCH("Handset Spk"),
317
318 /* This has no effect, it exists only to maintain compatibility with
319 * existing ALSA state files.
320 */
321 SOC_SINGLE_EXT("Amp State Switch", 6, 0, 1, 0,
322 lm4853_get_state,
323 lm4853_set_state),
324 SOC_SINGLE_EXT("Amp Spk Switch", 7, 0, 1, 0,
325 lm4853_get_spk,
326 lm4853_set_spk),
327};
328
329/*
330 * This is an example machine initialisation for a wm8753 connected to a
331 * neo1973 GTA02.
332 */
333static int neo1973_gta02_wm8753_init(struct snd_soc_codec *codec)
334{
335 int err;
336
337 /* set up NC codec pins */
338 snd_soc_dapm_nc_pin(codec, "OUT3");
339 snd_soc_dapm_nc_pin(codec, "OUT4");
340 snd_soc_dapm_nc_pin(codec, "LINE1");
341 snd_soc_dapm_nc_pin(codec, "LINE2");
342
343 /* Add neo1973 gta02 specific widgets */
344 snd_soc_dapm_new_controls(codec, wm8753_dapm_widgets,
345 ARRAY_SIZE(wm8753_dapm_widgets));
346
347 /* add neo1973 gta02 specific controls */
348 err = snd_soc_add_controls(codec, wm8753_neo1973_gta02_controls,
349 ARRAY_SIZE(wm8753_neo1973_gta02_controls));
350
351 if (err < 0)
352 return err;
353
354 /* set up neo1973 gta02 specific audio path audio_map */
355 snd_soc_dapm_add_routes(codec, audio_map, ARRAY_SIZE(audio_map));
356
357 /* set endpoints to default off mode */
358 snd_soc_dapm_disable_pin(codec, "Stereo Out");
359 snd_soc_dapm_disable_pin(codec, "GSM Line Out");
360 snd_soc_dapm_disable_pin(codec, "GSM Line In");
361 snd_soc_dapm_disable_pin(codec, "Headset Mic");
362 snd_soc_dapm_disable_pin(codec, "Handset Mic");
363 snd_soc_dapm_disable_pin(codec, "Handset Spk");
364
365 snd_soc_dapm_sync(codec);
366
367 return 0;
368}
369
370/*
371 * BT Codec DAI
372 */
373static struct snd_soc_dai bt_dai = {
374 .name = "Bluetooth",
375 .id = 0,
376 .playback = {
377 .channels_min = 1,
378 .channels_max = 1,
379 .rates = SNDRV_PCM_RATE_8000,
380 .formats = SNDRV_PCM_FMTBIT_S16_LE,},
381 .capture = {
382 .channels_min = 1,
383 .channels_max = 1,
384 .rates = SNDRV_PCM_RATE_8000,
385 .formats = SNDRV_PCM_FMTBIT_S16_LE,},
386};
387
388static struct snd_soc_dai_link neo1973_gta02_dai[] = {
389{ /* Hifi Playback - for similatious use with voice below */
390 .name = "WM8753",
391 .stream_name = "WM8753 HiFi",
392 .cpu_dai = &s3c24xx_i2s_dai,
393 .codec_dai = &wm8753_dai[WM8753_DAI_HIFI],
394 .init = neo1973_gta02_wm8753_init,
395 .ops = &neo1973_gta02_hifi_ops,
396},
397{ /* Voice via BT */
398 .name = "Bluetooth",
399 .stream_name = "Voice",
400 .cpu_dai = &bt_dai,
401 .codec_dai = &wm8753_dai[WM8753_DAI_VOICE],
402 .ops = &neo1973_gta02_voice_ops,
403},
404};
405
406static struct snd_soc_card neo1973_gta02 = {
407 .name = "neo1973-gta02",
408 .platform = &s3c24xx_soc_platform,
409 .dai_link = neo1973_gta02_dai,
410 .num_links = ARRAY_SIZE(neo1973_gta02_dai),
411};
412
413static struct snd_soc_device neo1973_gta02_snd_devdata = {
414 .card = &neo1973_gta02,
415 .codec_dev = &soc_codec_dev_wm8753,
416};
417
418static struct platform_device *neo1973_gta02_snd_device;
419
420static int __init neo1973_gta02_init(void)
421{
422 int ret;
423
424 if (!machine_is_neo1973_gta02()) {
425 printk(KERN_INFO
426 "Only GTA02 is supported by this ASoC driver\n");
427 return -ENODEV;
428 }
429
430 /* register bluetooth DAI here */
431 ret = snd_soc_register_dai(&bt_dai);
432 if (ret)
433 return ret;
434
435 neo1973_gta02_snd_device = platform_device_alloc("soc-audio", -1);
436 if (!neo1973_gta02_snd_device)
437 return -ENOMEM;
438
439 platform_set_drvdata(neo1973_gta02_snd_device,
440 &neo1973_gta02_snd_devdata);
441 neo1973_gta02_snd_devdata.dev = &neo1973_gta02_snd_device->dev;
442 ret = platform_device_add(neo1973_gta02_snd_device);
443
444 if (ret) {
445 platform_device_put(neo1973_gta02_snd_device);
446 return ret;
447 }
448
449 /* Initialise GPIOs used by amp */
450 ret = gpio_request(GTA02_GPIO_HP_IN, "GTA02_HP_IN");
451 if (ret) {
452 pr_err("gta02_wm8753: Failed to register GPIO %d\n", GTA02_GPIO_HP_IN);
453 goto err_unregister_device;
454 }
455
456 ret = gpio_direction_output(GTA02_GPIO_AMP_HP_IN, 1);
457 if (ret) {
458 pr_err("gta02_wm8753: Failed to configure GPIO %d\n", GTA02_GPIO_HP_IN);
459 goto err_free_gpio_hp_in;
460 }
461
462 ret = gpio_request(GTA02_GPIO_AMP_SHUT, "GTA02_AMP_SHUT");
463 if (ret) {
464 pr_err("gta02_wm8753: Failed to register GPIO %d\n", GTA02_GPIO_AMP_SHUT);
465 goto err_free_gpio_hp_in;
466 }
467
468 ret = gpio_direction_output(GTA02_GPIO_AMP_SHUT, 1);
469 if (ret) {
470 pr_err("gta02_wm8753: Failed to configure GPIO %d\n", GTA02_GPIO_AMP_SHUT);
471 goto err_free_gpio_amp_shut;
472 }
473
474 return 0;
475
476err_free_gpio_amp_shut:
477 gpio_free(GTA02_GPIO_AMP_SHUT);
478err_free_gpio_hp_in:
479 gpio_free(GTA02_GPIO_HP_IN);
480err_unregister_device:
481 platform_device_unregister(neo1973_gta02_snd_device);
482 return ret;
483}
484module_init(neo1973_gta02_init);
485
486static void __exit neo1973_gta02_exit(void)
487{
488 snd_soc_unregister_dai(&bt_dai);
489 platform_device_unregister(neo1973_gta02_snd_device);
490 gpio_free(GTA02_GPIO_HP_IN);
491 gpio_free(GTA02_GPIO_AMP_SHUT);
492}
493module_exit(neo1973_gta02_exit);
494
495/* Module information */
496MODULE_AUTHOR("Graeme Gregory, graeme@openmoko.org");
497MODULE_DESCRIPTION("ALSA SoC WM8753 Neo1973 GTA02");
498MODULE_LICENSE("GPL");
diff --git a/sound/soc/s3c24xx/neo1973_wm8753.c b/sound/soc/s3c24xx/neo1973_wm8753.c
index 289fadf60b10..906709e6dd5f 100644
--- a/sound/soc/s3c24xx/neo1973_wm8753.c
+++ b/sound/soc/s3c24xx/neo1973_wm8753.c
@@ -345,9 +345,11 @@ static void lm4857_write_regs(void)
345static int lm4857_get_reg(struct snd_kcontrol *kcontrol, 345static int lm4857_get_reg(struct snd_kcontrol *kcontrol,
346 struct snd_ctl_elem_value *ucontrol) 346 struct snd_ctl_elem_value *ucontrol)
347{ 347{
348 int reg = kcontrol->private_value & 0xFF; 348 struct soc_mixer_control *mc =
349 int shift = (kcontrol->private_value >> 8) & 0x0F; 349 (struct soc_mixer_control *)kcontrol->private_value;
350 int mask = (kcontrol->private_value >> 16) & 0xFF; 350 int reg = mc->reg;
351 int shift = mc->shift;
352 int mask = mc->max;
351 353
352 pr_debug("Entered %s\n", __func__); 354 pr_debug("Entered %s\n", __func__);
353 355
@@ -358,9 +360,11 @@ static int lm4857_get_reg(struct snd_kcontrol *kcontrol,
358static int lm4857_set_reg(struct snd_kcontrol *kcontrol, 360static int lm4857_set_reg(struct snd_kcontrol *kcontrol,
359 struct snd_ctl_elem_value *ucontrol) 361 struct snd_ctl_elem_value *ucontrol)
360{ 362{
361 int reg = kcontrol->private_value & 0xFF; 363 struct soc_mixer_control *mc =
362 int shift = (kcontrol->private_value >> 8) & 0x0F; 364 (struct soc_mixer_control *)kcontrol->private_value;
363 int mask = (kcontrol->private_value >> 16) & 0xFF; 365 int reg = mc->reg;
366 int shift = mc->shift;
367 int mask = mc->max;
364 368
365 if (((lm4857_regs[reg] >> shift) & mask) == 369 if (((lm4857_regs[reg] >> shift) & mask) ==
366 ucontrol->value.integer.value[0]) 370 ucontrol->value.integer.value[0])
diff --git a/sound/soc/s3c24xx/s3c-i2s-v2.c b/sound/soc/s3c24xx/s3c-i2s-v2.c
index ab680aac3fcb..1a283170ca92 100644
--- a/sound/soc/s3c24xx/s3c-i2s-v2.c
+++ b/sound/soc/s3c24xx/s3c-i2s-v2.c
@@ -37,6 +37,20 @@
37 37
38#include "s3c-i2s-v2.h" 38#include "s3c-i2s-v2.h"
39 39
40#undef S3C_IIS_V2_SUPPORTED
41
42#if defined(CONFIG_CPU_S3C2412) || defined(CONFIG_CPU_S3C2413)
43#define S3C_IIS_V2_SUPPORTED
44#endif
45
46#ifdef CONFIG_PLAT_S3C64XX
47#define S3C_IIS_V2_SUPPORTED
48#endif
49
50#ifndef S3C_IIS_V2_SUPPORTED
51#error Unsupported CPU model
52#endif
53
40#define S3C2412_I2S_DEBUG_CON 0 54#define S3C2412_I2S_DEBUG_CON 0
41 55
42static inline struct s3c_i2sv2_info *to_info(struct snd_soc_dai *cpu_dai) 56static inline struct s3c_i2sv2_info *to_info(struct snd_soc_dai *cpu_dai)
@@ -75,7 +89,7 @@ static inline void dbg_showcon(const char *fn, u32 con)
75 89
76 90
77/* Turn on or off the transmission path. */ 91/* Turn on or off the transmission path. */
78void s3c2412_snd_txctrl(struct s3c_i2sv2_info *i2s, int on) 92static void s3c2412_snd_txctrl(struct s3c_i2sv2_info *i2s, int on)
79{ 93{
80 void __iomem *regs = i2s->regs; 94 void __iomem *regs = i2s->regs;
81 u32 fic, con, mod; 95 u32 fic, con, mod;
@@ -105,7 +119,9 @@ void s3c2412_snd_txctrl(struct s3c_i2sv2_info *i2s, int on)
105 break; 119 break;
106 120
107 default: 121 default:
108 dev_err(i2s->dev, "TXEN: Invalid MODE in IISMOD\n"); 122 dev_err(i2s->dev, "TXEN: Invalid MODE %x in IISMOD\n",
123 mod & S3C2412_IISMOD_MODE_MASK);
124 break;
109 } 125 }
110 126
111 writel(con, regs + S3C2412_IISCON); 127 writel(con, regs + S3C2412_IISCON);
@@ -132,7 +148,9 @@ void s3c2412_snd_txctrl(struct s3c_i2sv2_info *i2s, int on)
132 break; 148 break;
133 149
134 default: 150 default:
135 dev_err(i2s->dev, "TXDIS: Invalid MODE in IISMOD\n"); 151 dev_err(i2s->dev, "TXDIS: Invalid MODE %x in IISMOD\n",
152 mod & S3C2412_IISMOD_MODE_MASK);
153 break;
136 } 154 }
137 155
138 writel(mod, regs + S3C2412_IISMOD); 156 writel(mod, regs + S3C2412_IISMOD);
@@ -143,9 +161,8 @@ void s3c2412_snd_txctrl(struct s3c_i2sv2_info *i2s, int on)
143 dbg_showcon(__func__, con); 161 dbg_showcon(__func__, con);
144 pr_debug("%s: IIS: CON=%x MOD=%x FIC=%x\n", __func__, con, mod, fic); 162 pr_debug("%s: IIS: CON=%x MOD=%x FIC=%x\n", __func__, con, mod, fic);
145} 163}
146EXPORT_SYMBOL_GPL(s3c2412_snd_txctrl);
147 164
148void s3c2412_snd_rxctrl(struct s3c_i2sv2_info *i2s, int on) 165static void s3c2412_snd_rxctrl(struct s3c_i2sv2_info *i2s, int on)
149{ 166{
150 void __iomem *regs = i2s->regs; 167 void __iomem *regs = i2s->regs;
151 u32 fic, con, mod; 168 u32 fic, con, mod;
@@ -175,7 +192,8 @@ void s3c2412_snd_rxctrl(struct s3c_i2sv2_info *i2s, int on)
175 break; 192 break;
176 193
177 default: 194 default:
178 dev_err(i2s->dev, "RXEN: Invalid MODE in IISMOD\n"); 195 dev_err(i2s->dev, "RXEN: Invalid MODE %x in IISMOD\n",
196 mod & S3C2412_IISMOD_MODE_MASK);
179 } 197 }
180 198
181 writel(mod, regs + S3C2412_IISMOD); 199 writel(mod, regs + S3C2412_IISMOD);
@@ -199,7 +217,8 @@ void s3c2412_snd_rxctrl(struct s3c_i2sv2_info *i2s, int on)
199 break; 217 break;
200 218
201 default: 219 default:
202 dev_err(i2s->dev, "RXEN: Invalid MODE in IISMOD\n"); 220 dev_err(i2s->dev, "RXDIS: Invalid MODE %x in IISMOD\n",
221 mod & S3C2412_IISMOD_MODE_MASK);
203 } 222 }
204 223
205 writel(con, regs + S3C2412_IISCON); 224 writel(con, regs + S3C2412_IISCON);
@@ -209,7 +228,6 @@ void s3c2412_snd_rxctrl(struct s3c_i2sv2_info *i2s, int on)
209 fic = readl(regs + S3C2412_IISFIC); 228 fic = readl(regs + S3C2412_IISFIC);
210 pr_debug("%s: IIS: CON=%x MOD=%x FIC=%x\n", __func__, con, mod, fic); 229 pr_debug("%s: IIS: CON=%x MOD=%x FIC=%x\n", __func__, con, mod, fic);
211} 230}
212EXPORT_SYMBOL_GPL(s3c2412_snd_rxctrl);
213 231
214/* 232/*
215 * Wait for the LR signal to allow synchronisation to the L/R clock 233 * Wait for the LR signal to allow synchronisation to the L/R clock
@@ -266,7 +284,7 @@ static int s3c2412_i2s_set_fmt(struct snd_soc_dai *cpu_dai,
266 */ 284 */
267#define IISMOD_MASTER_MASK (1 << 11) 285#define IISMOD_MASTER_MASK (1 << 11)
268#define IISMOD_SLAVE (1 << 11) 286#define IISMOD_SLAVE (1 << 11)
269#define IISMOD_MASTER (0x0) 287#define IISMOD_MASTER (0 << 11)
270#endif 288#endif
271 289
272 switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { 290 switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
@@ -281,7 +299,7 @@ static int s3c2412_i2s_set_fmt(struct snd_soc_dai *cpu_dai,
281 iismod |= IISMOD_MASTER; 299 iismod |= IISMOD_MASTER;
282 break; 300 break;
283 default: 301 default:
284 pr_debug("unknwon master/slave format\n"); 302 pr_err("unknwon master/slave format\n");
285 return -EINVAL; 303 return -EINVAL;
286 } 304 }
287 305
@@ -298,7 +316,7 @@ static int s3c2412_i2s_set_fmt(struct snd_soc_dai *cpu_dai,
298 iismod |= S3C2412_IISMOD_SDF_IIS; 316 iismod |= S3C2412_IISMOD_SDF_IIS;
299 break; 317 break;
300 default: 318 default:
301 pr_debug("Unknown data format\n"); 319 pr_err("Unknown data format\n");
302 return -EINVAL; 320 return -EINVAL;
303 } 321 }
304 322
@@ -327,6 +345,7 @@ static int s3c2412_i2s_hw_params(struct snd_pcm_substream *substream,
327 iismod = readl(i2s->regs + S3C2412_IISMOD); 345 iismod = readl(i2s->regs + S3C2412_IISMOD);
328 pr_debug("%s: r: IISMOD: %x\n", __func__, iismod); 346 pr_debug("%s: r: IISMOD: %x\n", __func__, iismod);
329 347
348#if defined(CONFIG_CPU_S3C2412) || defined(CONFIG_CPU_S3C2413)
330 switch (params_format(params)) { 349 switch (params_format(params)) {
331 case SNDRV_PCM_FORMAT_S8: 350 case SNDRV_PCM_FORMAT_S8:
332 iismod |= S3C2412_IISMOD_8BIT; 351 iismod |= S3C2412_IISMOD_8BIT;
@@ -335,6 +354,25 @@ static int s3c2412_i2s_hw_params(struct snd_pcm_substream *substream,
335 iismod &= ~S3C2412_IISMOD_8BIT; 354 iismod &= ~S3C2412_IISMOD_8BIT;
336 break; 355 break;
337 } 356 }
357#endif
358
359#ifdef CONFIG_PLAT_S3C64XX
360 iismod &= ~0x606;
361 /* Sample size */
362 switch (params_format(params)) {
363 case SNDRV_PCM_FORMAT_S8:
364 /* 8 bit sample, 16fs BCLK */
365 iismod |= 0x2004;
366 break;
367 case SNDRV_PCM_FORMAT_S16_LE:
368 /* 16 bit sample, 32fs BCLK */
369 break;
370 case SNDRV_PCM_FORMAT_S24_LE:
371 /* 24 bit sample, 48fs BCLK */
372 iismod |= 0x4002;
373 break;
374 }
375#endif
338 376
339 writel(iismod, i2s->regs + S3C2412_IISMOD); 377 writel(iismod, i2s->regs + S3C2412_IISMOD);
340 pr_debug("%s: w: IISMOD: %x\n", __func__, iismod); 378 pr_debug("%s: w: IISMOD: %x\n", __func__, iismod);
@@ -489,6 +527,8 @@ int s3c_i2sv2_iis_calc_rate(struct s3c_i2sv2_rate_calc *info,
489 unsigned int best_rate = 0; 527 unsigned int best_rate = 0;
490 unsigned int best_deviation = INT_MAX; 528 unsigned int best_deviation = INT_MAX;
491 529
530 pr_debug("Input clock rate %ldHz\n", clkrate);
531
492 if (fstab == NULL) 532 if (fstab == NULL)
493 fstab = iis_fs_tab; 533 fstab = iis_fs_tab;
494 534
@@ -507,7 +547,7 @@ int s3c_i2sv2_iis_calc_rate(struct s3c_i2sv2_rate_calc *info,
507 actual = clkrate / (fsdiv * div); 547 actual = clkrate / (fsdiv * div);
508 deviation = actual - rate; 548 deviation = actual - rate;
509 549
510 printk(KERN_DEBUG "%dfs: div %d => result %d, deviation %d\n", 550 printk(KERN_DEBUG "%ufs: div %u => result %u, deviation %d\n",
511 fsdiv, div, actual, deviation); 551 fsdiv, div, actual, deviation);
512 552
513 deviation = abs(deviation); 553 deviation = abs(deviation);
@@ -523,7 +563,7 @@ int s3c_i2sv2_iis_calc_rate(struct s3c_i2sv2_rate_calc *info,
523 break; 563 break;
524 } 564 }
525 565
526 printk(KERN_DEBUG "best: fs=%d, div=%d, rate=%d\n", 566 printk(KERN_DEBUG "best: fs=%u, div=%u, rate=%u\n",
527 best_fs, best_div, best_rate); 567 best_fs, best_div, best_rate);
528 568
529 info->fs_div = best_fs; 569 info->fs_div = best_fs;
@@ -539,12 +579,31 @@ int s3c_i2sv2_probe(struct platform_device *pdev,
539 unsigned long base) 579 unsigned long base)
540{ 580{
541 struct device *dev = &pdev->dev; 581 struct device *dev = &pdev->dev;
582 unsigned int iismod;
542 583
543 i2s->dev = dev; 584 i2s->dev = dev;
544 585
545 /* record our i2s structure for later use in the callbacks */ 586 /* record our i2s structure for later use in the callbacks */
546 dai->private_data = i2s; 587 dai->private_data = i2s;
547 588
589 if (!base) {
590 struct resource *res = platform_get_resource(pdev,
591 IORESOURCE_MEM,
592 0);
593 if (!res) {
594 dev_err(dev, "Unable to get register resource\n");
595 return -ENXIO;
596 }
597
598 if (!request_mem_region(res->start, resource_size(res),
599 "s3c64xx-i2s-v4")) {
600 dev_err(dev, "Unable to request register region\n");
601 return -EBUSY;
602 }
603
604 base = res->start;
605 }
606
548 i2s->regs = ioremap(base, 0x100); 607 i2s->regs = ioremap(base, 0x100);
549 if (i2s->regs == NULL) { 608 if (i2s->regs == NULL) {
550 dev_err(dev, "cannot ioremap registers\n"); 609 dev_err(dev, "cannot ioremap registers\n");
@@ -560,12 +619,16 @@ int s3c_i2sv2_probe(struct platform_device *pdev,
560 619
561 clk_enable(i2s->iis_pclk); 620 clk_enable(i2s->iis_pclk);
562 621
622 /* Mark ourselves as in TXRX mode so we can run through our cleanup
623 * process without warnings. */
624 iismod = readl(i2s->regs + S3C2412_IISMOD);
625 iismod |= S3C2412_IISMOD_MODE_TXRX;
626 writel(iismod, i2s->regs + S3C2412_IISMOD);
563 s3c2412_snd_txctrl(i2s, 0); 627 s3c2412_snd_txctrl(i2s, 0);
564 s3c2412_snd_rxctrl(i2s, 0); 628 s3c2412_snd_rxctrl(i2s, 0);
565 629
566 return 0; 630 return 0;
567} 631}
568
569EXPORT_SYMBOL_GPL(s3c_i2sv2_probe); 632EXPORT_SYMBOL_GPL(s3c_i2sv2_probe);
570 633
571#ifdef CONFIG_PM 634#ifdef CONFIG_PM
diff --git a/sound/soc/s3c24xx/s3c2412-i2s.c b/sound/soc/s3c24xx/s3c2412-i2s.c
index b7e0b3f0bfc8..a587ec40b449 100644
--- a/sound/soc/s3c24xx/s3c2412-i2s.c
+++ b/sound/soc/s3c24xx/s3c2412-i2s.c
@@ -20,6 +20,7 @@
20#include <linux/module.h> 20#include <linux/module.h>
21#include <linux/device.h> 21#include <linux/device.h>
22#include <linux/delay.h> 22#include <linux/delay.h>
23#include <linux/gpio.h>
23#include <linux/clk.h> 24#include <linux/clk.h>
24#include <linux/kernel.h> 25#include <linux/kernel.h>
25#include <linux/io.h> 26#include <linux/io.h>
@@ -120,7 +121,7 @@ static int s3c2412_i2s_probe(struct platform_device *pdev,
120 121
121 s3c2412_i2s.iis_cclk = clk_get(&pdev->dev, "i2sclk"); 122 s3c2412_i2s.iis_cclk = clk_get(&pdev->dev, "i2sclk");
122 if (s3c2412_i2s.iis_cclk == NULL) { 123 if (s3c2412_i2s.iis_cclk == NULL) {
123 pr_debug("failed to get i2sclk clock\n"); 124 pr_err("failed to get i2sclk clock\n");
124 iounmap(s3c2412_i2s.regs); 125 iounmap(s3c2412_i2s.regs);
125 return -ENODEV; 126 return -ENODEV;
126 } 127 }
diff --git a/sound/soc/s3c24xx/s3c2443-ac97.c b/sound/soc/s3c24xx/s3c2443-ac97.c
index 3698f707c44d..bf16f20fcbb3 100644
--- a/sound/soc/s3c24xx/s3c2443-ac97.c
+++ b/sound/soc/s3c24xx/s3c2443-ac97.c
@@ -19,6 +19,7 @@
19#include <linux/io.h> 19#include <linux/io.h>
20#include <linux/wait.h> 20#include <linux/wait.h>
21#include <linux/delay.h> 21#include <linux/delay.h>
22#include <linux/gpio.h>
22#include <linux/clk.h> 23#include <linux/clk.h>
23 24
24#include <sound/core.h> 25#include <sound/core.h>
@@ -46,7 +47,7 @@ static struct s3c24xx_ac97_info s3c24xx_ac97;
46 47
47static DECLARE_COMPLETION(ac97_completion); 48static DECLARE_COMPLETION(ac97_completion);
48static u32 codec_ready; 49static u32 codec_ready;
49static DECLARE_MUTEX(ac97_mutex); 50static DEFINE_MUTEX(ac97_mutex);
50 51
51static unsigned short s3c2443_ac97_read(struct snd_ac97 *ac97, 52static unsigned short s3c2443_ac97_read(struct snd_ac97 *ac97,
52 unsigned short reg) 53 unsigned short reg)
@@ -55,7 +56,7 @@ static unsigned short s3c2443_ac97_read(struct snd_ac97 *ac97,
55 u32 ac_codec_cmd; 56 u32 ac_codec_cmd;
56 u32 stat, addr, data; 57 u32 stat, addr, data;
57 58
58 down(&ac97_mutex); 59 mutex_lock(&ac97_mutex);
59 60
60 codec_ready = S3C_AC97_GLBSTAT_CODECREADY; 61 codec_ready = S3C_AC97_GLBSTAT_CODECREADY;
61 ac_codec_cmd = readl(s3c24xx_ac97.regs + S3C_AC97_CODEC_CMD); 62 ac_codec_cmd = readl(s3c24xx_ac97.regs + S3C_AC97_CODEC_CMD);
@@ -78,7 +79,7 @@ static unsigned short s3c2443_ac97_read(struct snd_ac97 *ac97,
78 printk(KERN_ERR "s3c24xx-ac97: req addr = %02x," 79 printk(KERN_ERR "s3c24xx-ac97: req addr = %02x,"
79 " rep addr = %02x\n", reg, addr); 80 " rep addr = %02x\n", reg, addr);
80 81
81 up(&ac97_mutex); 82 mutex_unlock(&ac97_mutex);
82 83
83 return (unsigned short)data; 84 return (unsigned short)data;
84} 85}
@@ -89,7 +90,7 @@ static void s3c2443_ac97_write(struct snd_ac97 *ac97, unsigned short reg,
89 u32 ac_glbctrl; 90 u32 ac_glbctrl;
90 u32 ac_codec_cmd; 91 u32 ac_codec_cmd;
91 92
92 down(&ac97_mutex); 93 mutex_lock(&ac97_mutex);
93 94
94 codec_ready = S3C_AC97_GLBSTAT_CODECREADY; 95 codec_ready = S3C_AC97_GLBSTAT_CODECREADY;
95 ac_codec_cmd = readl(s3c24xx_ac97.regs + S3C_AC97_CODEC_CMD); 96 ac_codec_cmd = readl(s3c24xx_ac97.regs + S3C_AC97_CODEC_CMD);
@@ -108,7 +109,7 @@ static void s3c2443_ac97_write(struct snd_ac97 *ac97, unsigned short reg,
108 ac_codec_cmd |= S3C_AC97_CODEC_CMD_READ; 109 ac_codec_cmd |= S3C_AC97_CODEC_CMD_READ;
109 writel(ac_codec_cmd, s3c24xx_ac97.regs + S3C_AC97_CODEC_CMD); 110 writel(ac_codec_cmd, s3c24xx_ac97.regs + S3C_AC97_CODEC_CMD);
110 111
111 up(&ac97_mutex); 112 mutex_unlock(&ac97_mutex);
112 113
113} 114}
114 115
diff --git a/sound/soc/s3c24xx/s3c24xx-i2s.c b/sound/soc/s3c24xx/s3c24xx-i2s.c
index cc066964dad6..556e35f0ab73 100644
--- a/sound/soc/s3c24xx/s3c24xx-i2s.c
+++ b/sound/soc/s3c24xx/s3c24xx-i2s.c
@@ -21,6 +21,8 @@
21#include <linux/clk.h> 21#include <linux/clk.h>
22#include <linux/jiffies.h> 22#include <linux/jiffies.h>
23#include <linux/io.h> 23#include <linux/io.h>
24#include <linux/gpio.h>
25
24#include <sound/core.h> 26#include <sound/core.h>
25#include <sound/pcm.h> 27#include <sound/pcm.h>
26#include <sound/pcm_params.h> 28#include <sound/pcm_params.h>
diff --git a/sound/soc/s3c24xx/s3c24xx-pcm.c b/sound/soc/s3c24xx/s3c24xx-pcm.c
index 169ddad31575..eecfa5eba06b 100644
--- a/sound/soc/s3c24xx/s3c24xx-pcm.c
+++ b/sound/soc/s3c24xx/s3c24xx-pcm.c
@@ -218,24 +218,17 @@ static int s3c24xx_pcm_prepare(struct snd_pcm_substream *substream)
218 * sync to pclk, half-word transfers to the IIS-FIFO. */ 218 * sync to pclk, half-word transfers to the IIS-FIFO. */
219 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { 219 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
220 s3c2410_dma_devconfig(prtd->params->channel, 220 s3c2410_dma_devconfig(prtd->params->channel,
221 S3C2410_DMASRC_MEM, S3C2410_DISRCC_INC | 221 S3C2410_DMASRC_MEM,
222 S3C2410_DISRCC_APB, prtd->params->dma_addr); 222 prtd->params->dma_addr);
223
224 s3c2410_dma_config(prtd->params->channel,
225 prtd->params->dma_size,
226 S3C2410_DCON_SYNC_PCLK |
227 S3C2410_DCON_HANDSHAKE);
228 } else { 223 } else {
229 s3c2410_dma_config(prtd->params->channel,
230 prtd->params->dma_size,
231 S3C2410_DCON_HANDSHAKE |
232 S3C2410_DCON_SYNC_PCLK);
233
234 s3c2410_dma_devconfig(prtd->params->channel, 224 s3c2410_dma_devconfig(prtd->params->channel,
235 S3C2410_DMASRC_HW, 0x3, 225 S3C2410_DMASRC_HW,
236 prtd->params->dma_addr); 226 prtd->params->dma_addr);
237 } 227 }
238 228
229 s3c2410_dma_config(prtd->params->channel,
230 prtd->params->dma_size);
231
239 /* flush the DMA channel */ 232 /* flush the DMA channel */
240 s3c2410_dma_ctrl(prtd->params->channel, S3C2410_DMAOP_FLUSH); 233 s3c2410_dma_ctrl(prtd->params->channel, S3C2410_DMAOP_FLUSH);
241 prtd->dma_loaded = 0; 234 prtd->dma_loaded = 0;
diff --git a/sound/soc/s3c24xx/s3c64xx-i2s.c b/sound/soc/s3c24xx/s3c64xx-i2s.c
index 33c5de7e255f..3c06c401d0fb 100644
--- a/sound/soc/s3c24xx/s3c64xx-i2s.c
+++ b/sound/soc/s3c24xx/s3c64xx-i2s.c
@@ -108,48 +108,19 @@ static int s3c64xx_i2s_set_sysclk(struct snd_soc_dai *cpu_dai,
108 return 0; 108 return 0;
109} 109}
110 110
111 111struct clk *s3c64xx_i2s_get_clock(struct snd_soc_dai *dai)
112unsigned long s3c64xx_i2s_get_clockrate(struct snd_soc_dai *dai)
113{ 112{
114 struct s3c_i2sv2_info *i2s = to_info(dai); 113 struct s3c_i2sv2_info *i2s = to_info(dai);
115 114
116 return clk_get_rate(i2s->iis_cclk); 115 return i2s->iis_cclk;
117} 116}
118EXPORT_SYMBOL_GPL(s3c64xx_i2s_get_clockrate); 117EXPORT_SYMBOL_GPL(s3c64xx_i2s_get_clock);
119 118
120static int s3c64xx_i2s_probe(struct platform_device *pdev, 119static int s3c64xx_i2s_probe(struct platform_device *pdev,
121 struct snd_soc_dai *dai) 120 struct snd_soc_dai *dai)
122{ 121{
123 struct device *dev = &pdev->dev;
124 struct s3c_i2sv2_info *i2s;
125 int ret;
126
127 dev_dbg(dev, "%s: probing dai %d\n", __func__, pdev->id);
128
129 if (pdev->id < 0 || pdev->id > ARRAY_SIZE(s3c64xx_i2s)) {
130 dev_err(dev, "id %d out of range\n", pdev->id);
131 return -EINVAL;
132 }
133
134 i2s = &s3c64xx_i2s[pdev->id];
135
136 ret = s3c_i2sv2_probe(pdev, dai, i2s,
137 pdev->id ? S3C64XX_PA_IIS1 : S3C64XX_PA_IIS0);
138 if (ret)
139 return ret;
140
141 i2s->dma_capture = &s3c64xx_i2s_pcm_stereo_in[pdev->id];
142 i2s->dma_playback = &s3c64xx_i2s_pcm_stereo_out[pdev->id];
143
144 i2s->iis_cclk = clk_get(dev, "audio-bus");
145 if (IS_ERR(i2s->iis_cclk)) {
146 dev_err(dev, "failed to get audio-bus");
147 iounmap(i2s->regs);
148 return -ENODEV;
149 }
150
151 /* configure GPIO for i2s port */ 122 /* configure GPIO for i2s port */
152 switch (pdev->id) { 123 switch (dai->id) {
153 case 0: 124 case 0:
154 s3c_gpio_cfgpin(S3C64XX_GPD(0), S3C64XX_GPD0_I2S0_CLK); 125 s3c_gpio_cfgpin(S3C64XX_GPD(0), S3C64XX_GPD0_I2S0_CLK);
155 s3c_gpio_cfgpin(S3C64XX_GPD(1), S3C64XX_GPD1_I2S0_CDCLK); 126 s3c_gpio_cfgpin(S3C64XX_GPD(1), S3C64XX_GPD1_I2S0_CDCLK);
@@ -175,41 +146,122 @@ static int s3c64xx_i2s_probe(struct platform_device *pdev,
175 SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_88200 | SNDRV_PCM_RATE_96000) 146 SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_88200 | SNDRV_PCM_RATE_96000)
176 147
177#define S3C64XX_I2S_FMTS \ 148#define S3C64XX_I2S_FMTS \
178 (SNDRV_PCM_FMTBIT_S8 | SNDRV_PCM_FMTBIT_S16_LE) 149 (SNDRV_PCM_FMTBIT_S8 | SNDRV_PCM_FMTBIT_S16_LE |\
150 SNDRV_PCM_FMTBIT_S24_LE)
179 151
180static struct snd_soc_dai_ops s3c64xx_i2s_dai_ops = { 152static struct snd_soc_dai_ops s3c64xx_i2s_dai_ops = {
181 .set_sysclk = s3c64xx_i2s_set_sysclk, 153 .set_sysclk = s3c64xx_i2s_set_sysclk,
182}; 154};
183 155
184struct snd_soc_dai s3c64xx_i2s_dai = { 156struct snd_soc_dai s3c64xx_i2s_dai[] = {
185 .name = "s3c64xx-i2s", 157 {
186 .id = 0, 158 .name = "s3c64xx-i2s",
187 .probe = s3c64xx_i2s_probe, 159 .id = 0,
188 .playback = { 160 .probe = s3c64xx_i2s_probe,
189 .channels_min = 2, 161 .playback = {
190 .channels_max = 2, 162 .channels_min = 2,
191 .rates = S3C64XX_I2S_RATES, 163 .channels_max = 2,
192 .formats = S3C64XX_I2S_FMTS, 164 .rates = S3C64XX_I2S_RATES,
165 .formats = S3C64XX_I2S_FMTS,
166 },
167 .capture = {
168 .channels_min = 2,
169 .channels_max = 2,
170 .rates = S3C64XX_I2S_RATES,
171 .formats = S3C64XX_I2S_FMTS,
172 },
173 .ops = &s3c64xx_i2s_dai_ops,
174 .symmetric_rates = 1,
193 }, 175 },
194 .capture = { 176 {
195 .channels_min = 2, 177 .name = "s3c64xx-i2s",
196 .channels_max = 2, 178 .id = 1,
197 .rates = S3C64XX_I2S_RATES, 179 .probe = s3c64xx_i2s_probe,
198 .formats = S3C64XX_I2S_FMTS, 180 .playback = {
181 .channels_min = 2,
182 .channels_max = 2,
183 .rates = S3C64XX_I2S_RATES,
184 .formats = S3C64XX_I2S_FMTS,
185 },
186 .capture = {
187 .channels_min = 2,
188 .channels_max = 2,
189 .rates = S3C64XX_I2S_RATES,
190 .formats = S3C64XX_I2S_FMTS,
191 },
192 .ops = &s3c64xx_i2s_dai_ops,
193 .symmetric_rates = 1,
199 }, 194 },
200 .ops = &s3c64xx_i2s_dai_ops,
201}; 195};
202EXPORT_SYMBOL_GPL(s3c64xx_i2s_dai); 196EXPORT_SYMBOL_GPL(s3c64xx_i2s_dai);
203 197
198static __devinit int s3c64xx_iis_dev_probe(struct platform_device *pdev)
199{
200 struct s3c_i2sv2_info *i2s;
201 struct snd_soc_dai *dai;
202 int ret;
203
204 if (pdev->id >= ARRAY_SIZE(s3c64xx_i2s)) {
205 dev_err(&pdev->dev, "id %d out of range\n", pdev->id);
206 return -EINVAL;
207 }
208
209 i2s = &s3c64xx_i2s[pdev->id];
210 dai = &s3c64xx_i2s_dai[pdev->id];
211 dai->dev = &pdev->dev;
212
213 i2s->dma_capture = &s3c64xx_i2s_pcm_stereo_in[pdev->id];
214 i2s->dma_playback = &s3c64xx_i2s_pcm_stereo_out[pdev->id];
215
216 i2s->iis_cclk = clk_get(&pdev->dev, "audio-bus");
217 if (IS_ERR(i2s->iis_cclk)) {
218 dev_err(&pdev->dev, "failed to get audio-bus\n");
219 ret = PTR_ERR(i2s->iis_cclk);
220 goto err;
221 }
222
223 ret = s3c_i2sv2_probe(pdev, dai, i2s, 0);
224 if (ret)
225 goto err_clk;
226
227 ret = s3c_i2sv2_register_dai(dai);
228 if (ret != 0)
229 goto err_i2sv2;
230
231 return 0;
232
233err_i2sv2:
234 /* Not implemented for I2Sv2 core yet */
235err_clk:
236 clk_put(i2s->iis_cclk);
237err:
238 return ret;
239}
240
241static __devexit int s3c64xx_iis_dev_remove(struct platform_device *pdev)
242{
243 dev_err(&pdev->dev, "Device removal not yet supported\n");
244 return 0;
245}
246
247static struct platform_driver s3c64xx_iis_driver = {
248 .probe = s3c64xx_iis_dev_probe,
249 .remove = s3c64xx_iis_dev_remove,
250 .driver = {
251 .name = "s3c64xx-iis",
252 .owner = THIS_MODULE,
253 },
254};
255
204static int __init s3c64xx_i2s_init(void) 256static int __init s3c64xx_i2s_init(void)
205{ 257{
206 return s3c_i2sv2_register_dai(&s3c64xx_i2s_dai); 258 return platform_driver_register(&s3c64xx_iis_driver);
207} 259}
208module_init(s3c64xx_i2s_init); 260module_init(s3c64xx_i2s_init);
209 261
210static void __exit s3c64xx_i2s_exit(void) 262static void __exit s3c64xx_i2s_exit(void)
211{ 263{
212 snd_soc_unregister_dai(&s3c64xx_i2s_dai); 264 platform_driver_unregister(&s3c64xx_iis_driver);
213} 265}
214module_exit(s3c64xx_i2s_exit); 266module_exit(s3c64xx_i2s_exit);
215 267
@@ -217,6 +269,3 @@ module_exit(s3c64xx_i2s_exit);
217MODULE_AUTHOR("Ben Dooks, <ben@simtec.co.uk>"); 269MODULE_AUTHOR("Ben Dooks, <ben@simtec.co.uk>");
218MODULE_DESCRIPTION("S3C64XX I2S SoC Interface"); 270MODULE_DESCRIPTION("S3C64XX I2S SoC Interface");
219MODULE_LICENSE("GPL"); 271MODULE_LICENSE("GPL");
220
221
222
diff --git a/sound/soc/s3c24xx/s3c64xx-i2s.h b/sound/soc/s3c24xx/s3c64xx-i2s.h
index b7ffe3c38b66..02148cee2613 100644
--- a/sound/soc/s3c24xx/s3c64xx-i2s.h
+++ b/sound/soc/s3c24xx/s3c64xx-i2s.h
@@ -15,6 +15,8 @@
15#ifndef __SND_SOC_S3C24XX_S3C64XX_I2S_H 15#ifndef __SND_SOC_S3C24XX_S3C64XX_I2S_H
16#define __SND_SOC_S3C24XX_S3C64XX_I2S_H __FILE__ 16#define __SND_SOC_S3C24XX_S3C64XX_I2S_H __FILE__
17 17
18struct clk;
19
18#include "s3c-i2s-v2.h" 20#include "s3c-i2s-v2.h"
19 21
20#define S3C64XX_DIV_BCLK S3C_I2SV2_DIV_BCLK 22#define S3C64XX_DIV_BCLK S3C_I2SV2_DIV_BCLK
@@ -24,8 +26,8 @@
24#define S3C64XX_CLKSRC_PCLK (0) 26#define S3C64XX_CLKSRC_PCLK (0)
25#define S3C64XX_CLKSRC_MUX (1) 27#define S3C64XX_CLKSRC_MUX (1)
26 28
27extern struct snd_soc_dai s3c64xx_i2s_dai; 29extern struct snd_soc_dai s3c64xx_i2s_dai[];
28 30
29extern unsigned long s3c64xx_i2s_get_clockrate(struct snd_soc_dai *cpu_dai); 31extern struct clk *s3c64xx_i2s_get_clock(struct snd_soc_dai *dai);
30 32
31#endif /* __SND_SOC_S3C24XX_S3C64XX_I2S_H */ 33#endif /* __SND_SOC_S3C24XX_S3C64XX_I2S_H */
diff --git a/sound/soc/s6000/Kconfig b/sound/soc/s6000/Kconfig
new file mode 100644
index 000000000000..c74eb3d4a47c
--- /dev/null
+++ b/sound/soc/s6000/Kconfig
@@ -0,0 +1,19 @@
1config SND_S6000_SOC
2 tristate "SoC Audio for the Stretch s6000 family"
3 depends on XTENSA_VARIANT_S6000
4 help
5 Say Y or M if you want to add support for codecs attached to
6 s6000 family chips. You will also need to select the platform
7 to support below.
8
9config SND_S6000_SOC_I2S
10 tristate
11
12config SND_S6000_SOC_S6IPCAM
13 tristate "SoC Audio support for Stretch 6105 IP Camera"
14 depends on SND_S6000_SOC && XTENSA_PLATFORM_S6105
15 select SND_S6000_SOC_I2S
16 select SND_SOC_TLV320AIC3X
17 help
18 Say Y if you want to add support for SoC audio on the
19 Stretch s6105 IP Camera Reference Design.
diff --git a/sound/soc/s6000/Makefile b/sound/soc/s6000/Makefile
new file mode 100644
index 000000000000..7a613612e010
--- /dev/null
+++ b/sound/soc/s6000/Makefile
@@ -0,0 +1,11 @@
1# s6000 Platform Support
2snd-soc-s6000-objs := s6000-pcm.o
3snd-soc-s6000-i2s-objs := s6000-i2s.o
4
5obj-$(CONFIG_SND_S6000_SOC) += snd-soc-s6000.o
6obj-$(CONFIG_SND_S6000_SOC_I2S) += snd-soc-s6000-i2s.o
7
8# s6105 Machine Support
9snd-soc-s6ipcam-objs := s6105-ipcam.o
10
11obj-$(CONFIG_SND_S6000_SOC_S6IPCAM) += snd-soc-s6ipcam.o
diff --git a/sound/soc/s6000/s6000-i2s.c b/sound/soc/s6000/s6000-i2s.c
new file mode 100644
index 000000000000..c5cda187ecab
--- /dev/null
+++ b/sound/soc/s6000/s6000-i2s.c
@@ -0,0 +1,629 @@
1/*
2 * ALSA SoC I2S Audio Layer for the Stretch S6000 family
3 *
4 * Author: Daniel Gloeckner, <dg@emlix.com>
5 * Copyright: (C) 2009 emlix GmbH <info@emlix.com>
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License version 2 as
9 * published by the Free Software Foundation.
10 */
11
12#include <linux/init.h>
13#include <linux/module.h>
14#include <linux/device.h>
15#include <linux/delay.h>
16#include <linux/clk.h>
17#include <linux/interrupt.h>
18#include <linux/io.h>
19
20#include <sound/core.h>
21#include <sound/pcm.h>
22#include <sound/pcm_params.h>
23#include <sound/initval.h>
24#include <sound/soc.h>
25
26#include "s6000-i2s.h"
27#include "s6000-pcm.h"
28
29struct s6000_i2s_dev {
30 dma_addr_t sifbase;
31 u8 __iomem *scbbase;
32 unsigned int wide;
33 unsigned int channel_in;
34 unsigned int channel_out;
35 unsigned int lines_in;
36 unsigned int lines_out;
37 struct s6000_pcm_dma_params dma_params;
38};
39
40#define S6_I2S_INTERRUPT_STATUS 0x00
41#define S6_I2S_INT_OVERRUN 1
42#define S6_I2S_INT_UNDERRUN 2
43#define S6_I2S_INT_ALIGNMENT 4
44#define S6_I2S_INTERRUPT_ENABLE 0x04
45#define S6_I2S_INTERRUPT_RAW 0x08
46#define S6_I2S_INTERRUPT_CLEAR 0x0C
47#define S6_I2S_INTERRUPT_SET 0x10
48#define S6_I2S_MODE 0x20
49#define S6_I2S_DUAL 0
50#define S6_I2S_WIDE 1
51#define S6_I2S_TX_DEFAULT 0x24
52#define S6_I2S_DATA_CFG(c) (0x40 + 0x10 * (c))
53#define S6_I2S_IN 0
54#define S6_I2S_OUT 1
55#define S6_I2S_UNUSED 2
56#define S6_I2S_INTERFACE_CFG(c) (0x44 + 0x10 * (c))
57#define S6_I2S_DIV_MASK 0x001fff
58#define S6_I2S_16BIT 0x000000
59#define S6_I2S_20BIT 0x002000
60#define S6_I2S_24BIT 0x004000
61#define S6_I2S_32BIT 0x006000
62#define S6_I2S_BITS_MASK 0x006000
63#define S6_I2S_MEM_16BIT 0x000000
64#define S6_I2S_MEM_32BIT 0x008000
65#define S6_I2S_MEM_MASK 0x008000
66#define S6_I2S_CHANNELS_SHIFT 16
67#define S6_I2S_CHANNELS_MASK 0x030000
68#define S6_I2S_SCK_IN 0x000000
69#define S6_I2S_SCK_OUT 0x040000
70#define S6_I2S_SCK_DIR 0x040000
71#define S6_I2S_WS_IN 0x000000
72#define S6_I2S_WS_OUT 0x080000
73#define S6_I2S_WS_DIR 0x080000
74#define S6_I2S_LEFT_FIRST 0x000000
75#define S6_I2S_RIGHT_FIRST 0x100000
76#define S6_I2S_FIRST 0x100000
77#define S6_I2S_CUR_SCK 0x200000
78#define S6_I2S_CUR_WS 0x400000
79#define S6_I2S_ENABLE(c) (0x48 + 0x10 * (c))
80#define S6_I2S_DISABLE_IF 0x02
81#define S6_I2S_ENABLE_IF 0x03
82#define S6_I2S_IS_BUSY 0x04
83#define S6_I2S_DMA_ACTIVE 0x08
84#define S6_I2S_IS_ENABLED 0x10
85
86#define S6_I2S_NUM_LINES 4
87
88#define S6_I2S_SIF_PORT0 0x0000000
89#define S6_I2S_SIF_PORT1 0x0000080 /* docs say 0x0000010 */
90
91static inline void s6_i2s_write_reg(struct s6000_i2s_dev *dev, int reg, u32 val)
92{
93 writel(val, dev->scbbase + reg);
94}
95
96static inline u32 s6_i2s_read_reg(struct s6000_i2s_dev *dev, int reg)
97{
98 return readl(dev->scbbase + reg);
99}
100
101static inline void s6_i2s_mod_reg(struct s6000_i2s_dev *dev, int reg,
102 u32 mask, u32 val)
103{
104 val ^= s6_i2s_read_reg(dev, reg) & ~mask;
105 s6_i2s_write_reg(dev, reg, val);
106}
107
108static void s6000_i2s_start_channel(struct s6000_i2s_dev *dev, int channel)
109{
110 int i, j, cur, prev;
111
112 /*
113 * Wait for WCLK to toggle 5 times before enabling the channel
114 * s6000 Family Datasheet 3.6.4:
115 * "At least two cycles of WS must occur between commands
116 * to disable or enable the interface"
117 */
118 j = 0;
119 prev = ~S6_I2S_CUR_WS;
120 for (i = 1000000; --i && j < 6; ) {
121 cur = s6_i2s_read_reg(dev, S6_I2S_INTERFACE_CFG(channel))
122 & S6_I2S_CUR_WS;
123 if (prev != cur) {
124 prev = cur;
125 j++;
126 }
127 }
128 if (j < 6)
129 printk(KERN_WARNING "s6000-i2s: timeout waiting for WCLK\n");
130
131 s6_i2s_write_reg(dev, S6_I2S_ENABLE(channel), S6_I2S_ENABLE_IF);
132}
133
134static void s6000_i2s_stop_channel(struct s6000_i2s_dev *dev, int channel)
135{
136 s6_i2s_write_reg(dev, S6_I2S_ENABLE(channel), S6_I2S_DISABLE_IF);
137}
138
139static void s6000_i2s_start(struct snd_pcm_substream *substream)
140{
141 struct snd_soc_pcm_runtime *rtd = substream->private_data;
142 struct s6000_i2s_dev *dev = rtd->dai->cpu_dai->private_data;
143 int channel;
144
145 channel = (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) ?
146 dev->channel_out : dev->channel_in;
147
148 s6000_i2s_start_channel(dev, channel);
149}
150
151static void s6000_i2s_stop(struct snd_pcm_substream *substream)
152{
153 struct snd_soc_pcm_runtime *rtd = substream->private_data;
154 struct s6000_i2s_dev *dev = rtd->dai->cpu_dai->private_data;
155 int channel;
156
157 channel = (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) ?
158 dev->channel_out : dev->channel_in;
159
160 s6000_i2s_stop_channel(dev, channel);
161}
162
163static int s6000_i2s_trigger(struct snd_pcm_substream *substream, int cmd,
164 int after)
165{
166 switch (cmd) {
167 case SNDRV_PCM_TRIGGER_START:
168 case SNDRV_PCM_TRIGGER_RESUME:
169 case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
170 if ((substream->stream == SNDRV_PCM_STREAM_CAPTURE) ^ !after)
171 s6000_i2s_start(substream);
172 break;
173 case SNDRV_PCM_TRIGGER_STOP:
174 case SNDRV_PCM_TRIGGER_SUSPEND:
175 case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
176 if (!after)
177 s6000_i2s_stop(substream);
178 }
179 return 0;
180}
181
182static unsigned int s6000_i2s_int_sources(struct s6000_i2s_dev *dev)
183{
184 unsigned int pending;
185 pending = s6_i2s_read_reg(dev, S6_I2S_INTERRUPT_RAW);
186 pending &= S6_I2S_INT_ALIGNMENT |
187 S6_I2S_INT_UNDERRUN |
188 S6_I2S_INT_OVERRUN;
189 s6_i2s_write_reg(dev, S6_I2S_INTERRUPT_CLEAR, pending);
190
191 return pending;
192}
193
194static unsigned int s6000_i2s_check_xrun(struct snd_soc_dai *cpu_dai)
195{
196 struct s6000_i2s_dev *dev = cpu_dai->private_data;
197 unsigned int errors;
198 unsigned int ret;
199
200 errors = s6000_i2s_int_sources(dev);
201 if (likely(!errors))
202 return 0;
203
204 ret = 0;
205 if (errors & S6_I2S_INT_ALIGNMENT)
206 printk(KERN_ERR "s6000-i2s: WCLK misaligned\n");
207 if (errors & S6_I2S_INT_UNDERRUN)
208 ret |= 1 << SNDRV_PCM_STREAM_PLAYBACK;
209 if (errors & S6_I2S_INT_OVERRUN)
210 ret |= 1 << SNDRV_PCM_STREAM_CAPTURE;
211 return ret;
212}
213
214static void s6000_i2s_wait_disabled(struct s6000_i2s_dev *dev)
215{
216 int channel;
217 int n = 50;
218 for (channel = 0; channel < 2; channel++) {
219 while (--n >= 0) {
220 int v = s6_i2s_read_reg(dev, S6_I2S_ENABLE(channel));
221 if ((v & S6_I2S_IS_ENABLED)
222 || !(v & (S6_I2S_DMA_ACTIVE | S6_I2S_IS_BUSY)))
223 break;
224 udelay(20);
225 }
226 }
227 if (n < 0)
228 printk(KERN_WARNING "s6000-i2s: timeout disabling interfaces");
229}
230
231static int s6000_i2s_set_dai_fmt(struct snd_soc_dai *cpu_dai,
232 unsigned int fmt)
233{
234 struct s6000_i2s_dev *dev = cpu_dai->private_data;
235 u32 w;
236
237 switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
238 case SND_SOC_DAIFMT_CBM_CFM:
239 w = S6_I2S_SCK_IN | S6_I2S_WS_IN;
240 break;
241 case SND_SOC_DAIFMT_CBS_CFM:
242 w = S6_I2S_SCK_OUT | S6_I2S_WS_IN;
243 break;
244 case SND_SOC_DAIFMT_CBM_CFS:
245 w = S6_I2S_SCK_IN | S6_I2S_WS_OUT;
246 break;
247 case SND_SOC_DAIFMT_CBS_CFS:
248 w = S6_I2S_SCK_OUT | S6_I2S_WS_OUT;
249 break;
250 default:
251 return -EINVAL;
252 }
253
254 switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
255 case SND_SOC_DAIFMT_NB_NF:
256 w |= S6_I2S_LEFT_FIRST;
257 break;
258 case SND_SOC_DAIFMT_NB_IF:
259 w |= S6_I2S_RIGHT_FIRST;
260 break;
261 default:
262 return -EINVAL;
263 }
264
265 s6_i2s_mod_reg(dev, S6_I2S_INTERFACE_CFG(0),
266 S6_I2S_FIRST | S6_I2S_WS_DIR | S6_I2S_SCK_DIR, w);
267 s6_i2s_mod_reg(dev, S6_I2S_INTERFACE_CFG(1),
268 S6_I2S_FIRST | S6_I2S_WS_DIR | S6_I2S_SCK_DIR, w);
269
270 return 0;
271}
272
273static int s6000_i2s_set_clkdiv(struct snd_soc_dai *dai, int div_id, int div)
274{
275 struct s6000_i2s_dev *dev = dai->private_data;
276
277 if (!div || (div & 1) || div > (S6_I2S_DIV_MASK + 1) * 2)
278 return -EINVAL;
279
280 s6_i2s_mod_reg(dev, S6_I2S_INTERFACE_CFG(div_id),
281 S6_I2S_DIV_MASK, div / 2 - 1);
282 return 0;
283}
284
285static int s6000_i2s_hw_params(struct snd_pcm_substream *substream,
286 struct snd_pcm_hw_params *params,
287 struct snd_soc_dai *dai)
288{
289 struct s6000_i2s_dev *dev = dai->private_data;
290 int interf;
291 u32 w = 0;
292
293 if (dev->wide)
294 interf = 0;
295 else {
296 w |= (((params_channels(params) - 2) / 2)
297 << S6_I2S_CHANNELS_SHIFT) & S6_I2S_CHANNELS_MASK;
298 interf = (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
299 ? dev->channel_out : dev->channel_in;
300 }
301
302 switch (params_format(params)) {
303 case SNDRV_PCM_FORMAT_S16_LE:
304 w |= S6_I2S_16BIT | S6_I2S_MEM_16BIT;
305 break;
306 case SNDRV_PCM_FORMAT_S32_LE:
307 w |= S6_I2S_32BIT | S6_I2S_MEM_32BIT;
308 break;
309 default:
310 printk(KERN_WARNING "s6000-i2s: unsupported PCM format %x\n",
311 params_format(params));
312 return -EINVAL;
313 }
314
315 if (s6_i2s_read_reg(dev, S6_I2S_INTERFACE_CFG(interf))
316 & S6_I2S_IS_ENABLED) {
317 printk(KERN_ERR "s6000-i2s: interface already enabled\n");
318 return -EBUSY;
319 }
320
321 s6_i2s_mod_reg(dev, S6_I2S_INTERFACE_CFG(interf),
322 S6_I2S_CHANNELS_MASK|S6_I2S_MEM_MASK|S6_I2S_BITS_MASK,
323 w);
324
325 return 0;
326}
327
328static int s6000_i2s_dai_probe(struct platform_device *pdev,
329 struct snd_soc_dai *dai)
330{
331 struct s6000_i2s_dev *dev = dai->private_data;
332 struct s6000_snd_platform_data *pdata = pdev->dev.platform_data;
333
334 if (!pdata)
335 return -EINVAL;
336
337 dev->wide = pdata->wide;
338 dev->channel_in = pdata->channel_in;
339 dev->channel_out = pdata->channel_out;
340 dev->lines_in = pdata->lines_in;
341 dev->lines_out = pdata->lines_out;
342
343 s6_i2s_write_reg(dev, S6_I2S_MODE,
344 dev->wide ? S6_I2S_WIDE : S6_I2S_DUAL);
345
346 if (dev->wide) {
347 int i;
348
349 if (dev->lines_in + dev->lines_out > S6_I2S_NUM_LINES)
350 return -EINVAL;
351
352 dev->channel_in = 0;
353 dev->channel_out = 1;
354 dai->capture.channels_min = 2 * dev->lines_in;
355 dai->capture.channels_max = dai->capture.channels_min;
356 dai->playback.channels_min = 2 * dev->lines_out;
357 dai->playback.channels_max = dai->playback.channels_min;
358
359 for (i = 0; i < dev->lines_out; i++)
360 s6_i2s_write_reg(dev, S6_I2S_DATA_CFG(i), S6_I2S_OUT);
361
362 for (; i < S6_I2S_NUM_LINES - dev->lines_in; i++)
363 s6_i2s_write_reg(dev, S6_I2S_DATA_CFG(i),
364 S6_I2S_UNUSED);
365
366 for (; i < S6_I2S_NUM_LINES; i++)
367 s6_i2s_write_reg(dev, S6_I2S_DATA_CFG(i), S6_I2S_IN);
368 } else {
369 unsigned int cfg[2] = {S6_I2S_UNUSED, S6_I2S_UNUSED};
370
371 if (dev->lines_in > 1 || dev->lines_out > 1)
372 return -EINVAL;
373
374 dai->capture.channels_min = 2 * dev->lines_in;
375 dai->capture.channels_max = 8 * dev->lines_in;
376 dai->playback.channels_min = 2 * dev->lines_out;
377 dai->playback.channels_max = 8 * dev->lines_out;
378
379 if (dev->lines_in)
380 cfg[dev->channel_in] = S6_I2S_IN;
381 if (dev->lines_out)
382 cfg[dev->channel_out] = S6_I2S_OUT;
383
384 s6_i2s_write_reg(dev, S6_I2S_DATA_CFG(0), cfg[0]);
385 s6_i2s_write_reg(dev, S6_I2S_DATA_CFG(1), cfg[1]);
386 }
387
388 if (dev->lines_out) {
389 if (dev->lines_in) {
390 if (!dev->dma_params.dma_out)
391 return -ENODEV;
392 } else {
393 dev->dma_params.dma_out = dev->dma_params.dma_in;
394 dev->dma_params.dma_in = 0;
395 }
396 }
397 dev->dma_params.sif_in = dev->sifbase + (dev->channel_in ?
398 S6_I2S_SIF_PORT1 : S6_I2S_SIF_PORT0);
399 dev->dma_params.sif_out = dev->sifbase + (dev->channel_out ?
400 S6_I2S_SIF_PORT1 : S6_I2S_SIF_PORT0);
401 dev->dma_params.same_rate = pdata->same_rate | pdata->wide;
402 return 0;
403}
404
405#define S6000_I2S_RATES (SNDRV_PCM_RATE_CONTINUOUS | SNDRV_PCM_RATE_5512 | \
406 SNDRV_PCM_RATE_8000_192000)
407#define S6000_I2S_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S32_LE)
408
409static struct snd_soc_dai_ops s6000_i2s_dai_ops = {
410 .set_fmt = s6000_i2s_set_dai_fmt,
411 .set_clkdiv = s6000_i2s_set_clkdiv,
412 .hw_params = s6000_i2s_hw_params,
413};
414
415struct snd_soc_dai s6000_i2s_dai = {
416 .name = "s6000-i2s",
417 .id = 0,
418 .probe = s6000_i2s_dai_probe,
419 .playback = {
420 .channels_min = 2,
421 .channels_max = 8,
422 .formats = S6000_I2S_FORMATS,
423 .rates = S6000_I2S_RATES,
424 .rate_min = 0,
425 .rate_max = 1562500,
426 },
427 .capture = {
428 .channels_min = 2,
429 .channels_max = 8,
430 .formats = S6000_I2S_FORMATS,
431 .rates = S6000_I2S_RATES,
432 .rate_min = 0,
433 .rate_max = 1562500,
434 },
435 .ops = &s6000_i2s_dai_ops,
436}
437EXPORT_SYMBOL_GPL(s6000_i2s_dai);
438
439static int __devinit s6000_i2s_probe(struct platform_device *pdev)
440{
441 struct s6000_i2s_dev *dev;
442 struct resource *scbmem, *sifmem, *region, *dma1, *dma2;
443 u8 __iomem *mmio;
444 int ret;
445
446 scbmem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
447 if (!scbmem) {
448 dev_err(&pdev->dev, "no mem resource?\n");
449 ret = -ENODEV;
450 goto err_release_none;
451 }
452
453 region = request_mem_region(scbmem->start,
454 scbmem->end - scbmem->start + 1,
455 pdev->name);
456 if (!region) {
457 dev_err(&pdev->dev, "I2S SCB region already claimed\n");
458 ret = -EBUSY;
459 goto err_release_none;
460 }
461
462 mmio = ioremap(scbmem->start, scbmem->end - scbmem->start + 1);
463 if (!mmio) {
464 dev_err(&pdev->dev, "can't ioremap SCB region\n");
465 ret = -ENOMEM;
466 goto err_release_scb;
467 }
468
469 sifmem = platform_get_resource(pdev, IORESOURCE_MEM, 1);
470 if (!sifmem) {
471 dev_err(&pdev->dev, "no second mem resource?\n");
472 ret = -ENODEV;
473 goto err_release_map;
474 }
475
476 region = request_mem_region(sifmem->start,
477 sifmem->end - sifmem->start + 1,
478 pdev->name);
479 if (!region) {
480 dev_err(&pdev->dev, "I2S SIF region already claimed\n");
481 ret = -EBUSY;
482 goto err_release_map;
483 }
484
485 dma1 = platform_get_resource(pdev, IORESOURCE_DMA, 0);
486 if (!dma1) {
487 dev_err(&pdev->dev, "no dma resource?\n");
488 ret = -ENODEV;
489 goto err_release_sif;
490 }
491
492 region = request_mem_region(dma1->start, dma1->end - dma1->start + 1,
493 pdev->name);
494 if (!region) {
495 dev_err(&pdev->dev, "I2S DMA region already claimed\n");
496 ret = -EBUSY;
497 goto err_release_sif;
498 }
499
500 dma2 = platform_get_resource(pdev, IORESOURCE_DMA, 1);
501 if (dma2) {
502 region = request_mem_region(dma2->start,
503 dma2->end - dma2->start + 1,
504 pdev->name);
505 if (!region) {
506 dev_err(&pdev->dev,
507 "I2S DMA region already claimed\n");
508 ret = -EBUSY;
509 goto err_release_dma1;
510 }
511 }
512
513 dev = kzalloc(sizeof(struct s6000_i2s_dev), GFP_KERNEL);
514 if (!dev) {
515 ret = -ENOMEM;
516 goto err_release_dma2;
517 }
518
519 s6000_i2s_dai.dev = &pdev->dev;
520 s6000_i2s_dai.private_data = dev;
521 s6000_i2s_dai.dma_data = &dev->dma_params;
522
523 dev->sifbase = sifmem->start;
524 dev->scbbase = mmio;
525
526 s6_i2s_write_reg(dev, S6_I2S_INTERRUPT_ENABLE, 0);
527 s6_i2s_write_reg(dev, S6_I2S_INTERRUPT_CLEAR,
528 S6_I2S_INT_ALIGNMENT |
529 S6_I2S_INT_UNDERRUN |
530 S6_I2S_INT_OVERRUN);
531
532 s6000_i2s_stop_channel(dev, 0);
533 s6000_i2s_stop_channel(dev, 1);
534 s6000_i2s_wait_disabled(dev);
535
536 dev->dma_params.check_xrun = s6000_i2s_check_xrun;
537 dev->dma_params.trigger = s6000_i2s_trigger;
538 dev->dma_params.dma_in = dma1->start;
539 dev->dma_params.dma_out = dma2 ? dma2->start : 0;
540 dev->dma_params.irq = platform_get_irq(pdev, 0);
541 if (dev->dma_params.irq < 0) {
542 dev_err(&pdev->dev, "no irq resource?\n");
543 ret = -ENODEV;
544 goto err_release_dev;
545 }
546
547 s6_i2s_write_reg(dev, S6_I2S_INTERRUPT_ENABLE,
548 S6_I2S_INT_ALIGNMENT |
549 S6_I2S_INT_UNDERRUN |
550 S6_I2S_INT_OVERRUN);
551
552 ret = snd_soc_register_dai(&s6000_i2s_dai);
553 if (ret)
554 goto err_release_dev;
555
556 return 0;
557
558err_release_dev:
559 kfree(dev);
560err_release_dma2:
561 if (dma2)
562 release_mem_region(dma2->start, dma2->end - dma2->start + 1);
563err_release_dma1:
564 release_mem_region(dma1->start, dma1->end - dma1->start + 1);
565err_release_sif:
566 release_mem_region(sifmem->start, (sifmem->end - sifmem->start) + 1);
567err_release_map:
568 iounmap(mmio);
569err_release_scb:
570 release_mem_region(scbmem->start, (scbmem->end - scbmem->start) + 1);
571err_release_none:
572 return ret;
573}
574
575static void __devexit s6000_i2s_remove(struct platform_device *pdev)
576{
577 struct s6000_i2s_dev *dev = s6000_i2s_dai.private_data;
578 struct resource *region;
579 void __iomem *mmio = dev->scbbase;
580
581 snd_soc_unregister_dai(&s6000_i2s_dai);
582
583 s6000_i2s_stop_channel(dev, 0);
584 s6000_i2s_stop_channel(dev, 1);
585
586 s6_i2s_write_reg(dev, S6_I2S_INTERRUPT_ENABLE, 0);
587 s6000_i2s_dai.private_data = 0;
588 kfree(dev);
589
590 region = platform_get_resource(pdev, IORESOURCE_DMA, 0);
591 release_mem_region(region->start, region->end - region->start + 1);
592
593 region = platform_get_resource(pdev, IORESOURCE_DMA, 1);
594 if (region)
595 release_mem_region(region->start,
596 region->end - region->start + 1);
597
598 region = platform_get_resource(pdev, IORESOURCE_MEM, 0);
599 release_mem_region(region->start, (region->end - region->start) + 1);
600
601 iounmap(mmio);
602 region = platform_get_resource(pdev, IORESOURCE_IO, 0);
603 release_mem_region(region->start, (region->end - region->start) + 1);
604}
605
606static struct platform_driver s6000_i2s_driver = {
607 .probe = s6000_i2s_probe,
608 .remove = __devexit_p(s6000_i2s_remove),
609 .driver = {
610 .name = "s6000-i2s",
611 .owner = THIS_MODULE,
612 },
613};
614
615static int __init s6000_i2s_init(void)
616{
617 return platform_driver_register(&s6000_i2s_driver);
618}
619module_init(s6000_i2s_init);
620
621static void __exit s6000_i2s_exit(void)
622{
623 platform_driver_unregister(&s6000_i2s_driver);
624}
625module_exit(s6000_i2s_exit);
626
627MODULE_AUTHOR("Daniel Gloeckner");
628MODULE_DESCRIPTION("Stretch s6000 family I2S SoC Interface");
629MODULE_LICENSE("GPL");
diff --git a/sound/soc/s6000/s6000-i2s.h b/sound/soc/s6000/s6000-i2s.h
new file mode 100644
index 000000000000..2375fdfe6dba
--- /dev/null
+++ b/sound/soc/s6000/s6000-i2s.h
@@ -0,0 +1,25 @@
1/*
2 * ALSA SoC I2S Audio Layer for the Stretch s6000 family
3 *
4 * Author: Daniel Gloeckner, <dg@emlix.com>
5 * Copyright: (C) 2009 emlix GmbH <info@emlix.com>
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License version 2 as
9 * published by the Free Software Foundation.
10 */
11
12#ifndef _S6000_I2S_H
13#define _S6000_I2S_H
14
15extern struct snd_soc_dai s6000_i2s_dai;
16
17struct s6000_snd_platform_data {
18 int lines_in;
19 int lines_out;
20 int channel_in;
21 int channel_out;
22 int wide;
23 int same_rate;
24};
25#endif
diff --git a/sound/soc/s6000/s6000-pcm.c b/sound/soc/s6000/s6000-pcm.c
new file mode 100644
index 000000000000..83b8028e209d
--- /dev/null
+++ b/sound/soc/s6000/s6000-pcm.c
@@ -0,0 +1,497 @@
1/*
2 * ALSA PCM interface for the Stetch s6000 family
3 *
4 * Author: Daniel Gloeckner, <dg@emlix.com>
5 * Copyright: (C) 2009 emlix GmbH <info@emlix.com>
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License version 2 as
9 * published by the Free Software Foundation.
10 */
11
12#include <linux/module.h>
13#include <linux/init.h>
14#include <linux/platform_device.h>
15#include <linux/slab.h>
16#include <linux/dma-mapping.h>
17#include <linux/interrupt.h>
18
19#include <sound/core.h>
20#include <sound/pcm.h>
21#include <sound/pcm_params.h>
22#include <sound/soc.h>
23
24#include <asm/dma.h>
25#include <variant/dmac.h>
26
27#include "s6000-pcm.h"
28
29#define S6_PCM_PREALLOCATE_SIZE (96 * 1024)
30#define S6_PCM_PREALLOCATE_MAX (2048 * 1024)
31
32static struct snd_pcm_hardware s6000_pcm_hardware = {
33 .info = (SNDRV_PCM_INFO_INTERLEAVED | SNDRV_PCM_INFO_BLOCK_TRANSFER |
34 SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_MMAP_VALID |
35 SNDRV_PCM_INFO_PAUSE | SNDRV_PCM_INFO_JOINT_DUPLEX),
36 .formats = (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S32_LE),
37 .rates = (SNDRV_PCM_RATE_CONTINUOUS | SNDRV_PCM_RATE_5512 | \
38 SNDRV_PCM_RATE_8000_192000),
39 .rate_min = 0,
40 .rate_max = 1562500,
41 .channels_min = 2,
42 .channels_max = 8,
43 .buffer_bytes_max = 0x7ffffff0,
44 .period_bytes_min = 16,
45 .period_bytes_max = 0xfffff0,
46 .periods_min = 2,
47 .periods_max = 1024, /* no limit */
48 .fifo_size = 0,
49};
50
51struct s6000_runtime_data {
52 spinlock_t lock;
53 int period; /* current DMA period */
54};
55
56static void s6000_pcm_enqueue_dma(struct snd_pcm_substream *substream)
57{
58 struct snd_pcm_runtime *runtime = substream->runtime;
59 struct s6000_runtime_data *prtd = runtime->private_data;
60 struct snd_soc_pcm_runtime *soc_runtime = substream->private_data;
61 struct s6000_pcm_dma_params *par = soc_runtime->dai->cpu_dai->dma_data;
62 int channel;
63 unsigned int period_size;
64 unsigned int dma_offset;
65 dma_addr_t dma_pos;
66 dma_addr_t src, dst;
67
68 period_size = snd_pcm_lib_period_bytes(substream);
69 dma_offset = prtd->period * period_size;
70 dma_pos = runtime->dma_addr + dma_offset;
71
72 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
73 src = dma_pos;
74 dst = par->sif_out;
75 channel = par->dma_out;
76 } else {
77 src = par->sif_in;
78 dst = dma_pos;
79 channel = par->dma_in;
80 }
81
82 if (!s6dmac_channel_enabled(DMA_MASK_DMAC(channel),
83 DMA_INDEX_CHNL(channel)))
84 return;
85
86 if (s6dmac_fifo_full(DMA_MASK_DMAC(channel), DMA_INDEX_CHNL(channel))) {
87 printk(KERN_ERR "s6000-pcm: fifo full\n");
88 return;
89 }
90
91 BUG_ON(period_size & 15);
92 s6dmac_put_fifo(DMA_MASK_DMAC(channel), DMA_INDEX_CHNL(channel),
93 src, dst, period_size);
94
95 prtd->period++;
96 if (unlikely(prtd->period >= runtime->periods))
97 prtd->period = 0;
98}
99
100static irqreturn_t s6000_pcm_irq(int irq, void *data)
101{
102 struct snd_pcm *pcm = data;
103 struct snd_soc_pcm_runtime *runtime = pcm->private_data;
104 struct s6000_pcm_dma_params *params = runtime->dai->cpu_dai->dma_data;
105 struct s6000_runtime_data *prtd;
106 unsigned int has_xrun;
107 int i, ret = IRQ_NONE;
108 u32 channel[2] = {
109 [SNDRV_PCM_STREAM_PLAYBACK] = params->dma_out,
110 [SNDRV_PCM_STREAM_CAPTURE] = params->dma_in
111 };
112
113 has_xrun = params->check_xrun(runtime->dai->cpu_dai);
114
115 for (i = 0; i < ARRAY_SIZE(channel); ++i) {
116 struct snd_pcm_substream *substream = pcm->streams[i].substream;
117 unsigned int pending;
118
119 if (!channel[i])
120 continue;
121
122 if (unlikely(has_xrun & (1 << i)) &&
123 substream->runtime &&
124 snd_pcm_running(substream)) {
125 dev_dbg(pcm->dev, "xrun\n");
126 snd_pcm_stop(substream, SNDRV_PCM_STATE_XRUN);
127 ret = IRQ_HANDLED;
128 }
129
130 pending = s6dmac_int_sources(DMA_MASK_DMAC(channel[i]),
131 DMA_INDEX_CHNL(channel[i]));
132
133 if (pending & 1) {
134 ret = IRQ_HANDLED;
135 if (likely(substream->runtime &&
136 snd_pcm_running(substream))) {
137 snd_pcm_period_elapsed(substream);
138 dev_dbg(pcm->dev, "period elapsed %x %x\n",
139 s6dmac_cur_src(DMA_MASK_DMAC(channel[i]),
140 DMA_INDEX_CHNL(channel[i])),
141 s6dmac_cur_dst(DMA_MASK_DMAC(channel[i]),
142 DMA_INDEX_CHNL(channel[i])));
143 prtd = substream->runtime->private_data;
144 spin_lock(&prtd->lock);
145 s6000_pcm_enqueue_dma(substream);
146 spin_unlock(&prtd->lock);
147 }
148 }
149
150 if (unlikely(pending & ~7)) {
151 if (pending & (1 << 3))
152 printk(KERN_WARNING
153 "s6000-pcm: DMA %x Underflow\n",
154 channel[i]);
155 if (pending & (1 << 4))
156 printk(KERN_WARNING
157 "s6000-pcm: DMA %x Overflow\n",
158 channel[i]);
159 if (pending & 0x1e0)
160 printk(KERN_WARNING
161 "s6000-pcm: DMA %x Master Error "
162 "(mask %x)\n",
163 channel[i], pending >> 5);
164
165 }
166 }
167
168 return ret;
169}
170
171static int s6000_pcm_start(struct snd_pcm_substream *substream)
172{
173 struct s6000_runtime_data *prtd = substream->runtime->private_data;
174 struct snd_soc_pcm_runtime *soc_runtime = substream->private_data;
175 struct s6000_pcm_dma_params *par = soc_runtime->dai->cpu_dai->dma_data;
176 unsigned long flags;
177 int srcinc;
178 u32 dma;
179
180 spin_lock_irqsave(&prtd->lock, flags);
181
182 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
183 srcinc = 1;
184 dma = par->dma_out;
185 } else {
186 srcinc = 0;
187 dma = par->dma_in;
188 }
189 s6dmac_enable_chan(DMA_MASK_DMAC(dma), DMA_INDEX_CHNL(dma),
190 1 /* priority 1 (0 is max) */,
191 0 /* peripheral requests w/o xfer length mode */,
192 srcinc /* source address increment */,
193 srcinc^1 /* destination address increment */,
194 0 /* chunksize 0 (skip impossible on this dma) */,
195 0 /* source skip after chunk (impossible) */,
196 0 /* destination skip after chunk (impossible) */,
197 4 /* 16 byte burst size */,
198 -1 /* don't conserve bandwidth */,
199 0 /* low watermark irq descriptor theshold */,
200 0 /* disable hardware timestamps */,
201 1 /* enable channel */);
202
203 s6000_pcm_enqueue_dma(substream);
204 s6000_pcm_enqueue_dma(substream);
205
206 spin_unlock_irqrestore(&prtd->lock, flags);
207
208 return 0;
209}
210
211static int s6000_pcm_stop(struct snd_pcm_substream *substream)
212{
213 struct s6000_runtime_data *prtd = substream->runtime->private_data;
214 struct snd_soc_pcm_runtime *soc_runtime = substream->private_data;
215 struct s6000_pcm_dma_params *par = soc_runtime->dai->cpu_dai->dma_data;
216 unsigned long flags;
217 u32 channel;
218
219 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
220 channel = par->dma_out;
221 else
222 channel = par->dma_in;
223
224 s6dmac_set_terminal_count(DMA_MASK_DMAC(channel),
225 DMA_INDEX_CHNL(channel), 0);
226
227 spin_lock_irqsave(&prtd->lock, flags);
228
229 s6dmac_disable_chan(DMA_MASK_DMAC(channel), DMA_INDEX_CHNL(channel));
230
231 spin_unlock_irqrestore(&prtd->lock, flags);
232
233 return 0;
234}
235
236static int s6000_pcm_trigger(struct snd_pcm_substream *substream, int cmd)
237{
238 struct snd_soc_pcm_runtime *soc_runtime = substream->private_data;
239 struct s6000_pcm_dma_params *par = soc_runtime->dai->cpu_dai->dma_data;
240 int ret;
241
242 ret = par->trigger(substream, cmd, 0);
243 if (ret < 0)
244 return ret;
245
246 switch (cmd) {
247 case SNDRV_PCM_TRIGGER_START:
248 case SNDRV_PCM_TRIGGER_RESUME:
249 case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
250 ret = s6000_pcm_start(substream);
251 break;
252 case SNDRV_PCM_TRIGGER_STOP:
253 case SNDRV_PCM_TRIGGER_SUSPEND:
254 case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
255 ret = s6000_pcm_stop(substream);
256 break;
257 default:
258 ret = -EINVAL;
259 }
260 if (ret < 0)
261 return ret;
262
263 return par->trigger(substream, cmd, 1);
264}
265
266static int s6000_pcm_prepare(struct snd_pcm_substream *substream)
267{
268 struct s6000_runtime_data *prtd = substream->runtime->private_data;
269
270 prtd->period = 0;
271
272 return 0;
273}
274
275static snd_pcm_uframes_t s6000_pcm_pointer(struct snd_pcm_substream *substream)
276{
277 struct snd_soc_pcm_runtime *soc_runtime = substream->private_data;
278 struct s6000_pcm_dma_params *par = soc_runtime->dai->cpu_dai->dma_data;
279 struct snd_pcm_runtime *runtime = substream->runtime;
280 struct s6000_runtime_data *prtd = runtime->private_data;
281 unsigned long flags;
282 unsigned int offset;
283 dma_addr_t count;
284
285 spin_lock_irqsave(&prtd->lock, flags);
286
287 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
288 count = s6dmac_cur_src(DMA_MASK_DMAC(par->dma_out),
289 DMA_INDEX_CHNL(par->dma_out));
290 else
291 count = s6dmac_cur_dst(DMA_MASK_DMAC(par->dma_in),
292 DMA_INDEX_CHNL(par->dma_in));
293
294 count -= runtime->dma_addr;
295
296 spin_unlock_irqrestore(&prtd->lock, flags);
297
298 offset = bytes_to_frames(runtime, count);
299 if (unlikely(offset >= runtime->buffer_size))
300 offset = 0;
301
302 return offset;
303}
304
305static int s6000_pcm_open(struct snd_pcm_substream *substream)
306{
307 struct snd_soc_pcm_runtime *soc_runtime = substream->private_data;
308 struct s6000_pcm_dma_params *par = soc_runtime->dai->cpu_dai->dma_data;
309 struct snd_pcm_runtime *runtime = substream->runtime;
310 struct s6000_runtime_data *prtd;
311 int ret;
312
313 snd_soc_set_runtime_hwparams(substream, &s6000_pcm_hardware);
314
315 ret = snd_pcm_hw_constraint_step(runtime, 0,
316 SNDRV_PCM_HW_PARAM_PERIOD_BYTES, 16);
317 if (ret < 0)
318 return ret;
319 ret = snd_pcm_hw_constraint_step(runtime, 0,
320 SNDRV_PCM_HW_PARAM_BUFFER_BYTES, 16);
321 if (ret < 0)
322 return ret;
323 ret = snd_pcm_hw_constraint_integer(runtime,
324 SNDRV_PCM_HW_PARAM_PERIODS);
325 if (ret < 0)
326 return ret;
327
328 if (par->same_rate) {
329 int rate;
330 spin_lock(&par->lock); /* needed? */
331 rate = par->rate;
332 spin_unlock(&par->lock);
333 if (rate != -1) {
334 ret = snd_pcm_hw_constraint_minmax(runtime,
335 SNDRV_PCM_HW_PARAM_RATE,
336 rate, rate);
337 if (ret < 0)
338 return ret;
339 }
340 }
341
342 prtd = kzalloc(sizeof(struct s6000_runtime_data), GFP_KERNEL);
343 if (prtd == NULL)
344 return -ENOMEM;
345
346 spin_lock_init(&prtd->lock);
347
348 runtime->private_data = prtd;
349
350 return 0;
351}
352
353static int s6000_pcm_close(struct snd_pcm_substream *substream)
354{
355 struct snd_pcm_runtime *runtime = substream->runtime;
356 struct s6000_runtime_data *prtd = runtime->private_data;
357
358 kfree(prtd);
359
360 return 0;
361}
362
363static int s6000_pcm_hw_params(struct snd_pcm_substream *substream,
364 struct snd_pcm_hw_params *hw_params)
365{
366 struct snd_soc_pcm_runtime *soc_runtime = substream->private_data;
367 struct s6000_pcm_dma_params *par = soc_runtime->dai->cpu_dai->dma_data;
368 int ret;
369 ret = snd_pcm_lib_malloc_pages(substream,
370 params_buffer_bytes(hw_params));
371 if (ret < 0) {
372 printk(KERN_WARNING "s6000-pcm: allocation of memory failed\n");
373 return ret;
374 }
375
376 if (par->same_rate) {
377 spin_lock(&par->lock);
378 if (par->rate == -1 ||
379 !(par->in_use & ~(1 << substream->stream))) {
380 par->rate = params_rate(hw_params);
381 par->in_use |= 1 << substream->stream;
382 } else if (params_rate(hw_params) != par->rate) {
383 snd_pcm_lib_free_pages(substream);
384 par->in_use &= ~(1 << substream->stream);
385 ret = -EBUSY;
386 }
387 spin_unlock(&par->lock);
388 }
389 return ret;
390}
391
392static int s6000_pcm_hw_free(struct snd_pcm_substream *substream)
393{
394 struct snd_soc_pcm_runtime *soc_runtime = substream->private_data;
395 struct s6000_pcm_dma_params *par = soc_runtime->dai->cpu_dai->dma_data;
396
397 spin_lock(&par->lock);
398 par->in_use &= ~(1 << substream->stream);
399 if (!par->in_use)
400 par->rate = -1;
401 spin_unlock(&par->lock);
402
403 return snd_pcm_lib_free_pages(substream);
404}
405
406static struct snd_pcm_ops s6000_pcm_ops = {
407 .open = s6000_pcm_open,
408 .close = s6000_pcm_close,
409 .ioctl = snd_pcm_lib_ioctl,
410 .hw_params = s6000_pcm_hw_params,
411 .hw_free = s6000_pcm_hw_free,
412 .trigger = s6000_pcm_trigger,
413 .prepare = s6000_pcm_prepare,
414 .pointer = s6000_pcm_pointer,
415};
416
417static void s6000_pcm_free(struct snd_pcm *pcm)
418{
419 struct snd_soc_pcm_runtime *runtime = pcm->private_data;
420 struct s6000_pcm_dma_params *params = runtime->dai->cpu_dai->dma_data;
421
422 free_irq(params->irq, pcm);
423 snd_pcm_lib_preallocate_free_for_all(pcm);
424}
425
426static u64 s6000_pcm_dmamask = DMA_32BIT_MASK;
427
428static int s6000_pcm_new(struct snd_card *card,
429 struct snd_soc_dai *dai, struct snd_pcm *pcm)
430{
431 struct snd_soc_pcm_runtime *runtime = pcm->private_data;
432 struct s6000_pcm_dma_params *params = runtime->dai->cpu_dai->dma_data;
433 int res;
434
435 if (!card->dev->dma_mask)
436 card->dev->dma_mask = &s6000_pcm_dmamask;
437 if (!card->dev->coherent_dma_mask)
438 card->dev->coherent_dma_mask = DMA_32BIT_MASK;
439
440 if (params->dma_in) {
441 s6dmac_disable_chan(DMA_MASK_DMAC(params->dma_in),
442 DMA_INDEX_CHNL(params->dma_in));
443 s6dmac_int_sources(DMA_MASK_DMAC(params->dma_in),
444 DMA_INDEX_CHNL(params->dma_in));
445 }
446
447 if (params->dma_out) {
448 s6dmac_disable_chan(DMA_MASK_DMAC(params->dma_out),
449 DMA_INDEX_CHNL(params->dma_out));
450 s6dmac_int_sources(DMA_MASK_DMAC(params->dma_out),
451 DMA_INDEX_CHNL(params->dma_out));
452 }
453
454 res = request_irq(params->irq, s6000_pcm_irq, IRQF_SHARED,
455 s6000_soc_platform.name, pcm);
456 if (res) {
457 printk(KERN_ERR "s6000-pcm couldn't get IRQ\n");
458 return res;
459 }
460
461 res = snd_pcm_lib_preallocate_pages_for_all(pcm,
462 SNDRV_DMA_TYPE_DEV,
463 card->dev,
464 S6_PCM_PREALLOCATE_SIZE,
465 S6_PCM_PREALLOCATE_MAX);
466 if (res)
467 printk(KERN_WARNING "s6000-pcm: preallocation failed\n");
468
469 spin_lock_init(&params->lock);
470 params->in_use = 0;
471 params->rate = -1;
472 return 0;
473}
474
475struct snd_soc_platform s6000_soc_platform = {
476 .name = "s6000-audio",
477 .pcm_ops = &s6000_pcm_ops,
478 .pcm_new = s6000_pcm_new,
479 .pcm_free = s6000_pcm_free,
480};
481EXPORT_SYMBOL_GPL(s6000_soc_platform);
482
483static int __init s6000_pcm_init(void)
484{
485 return snd_soc_register_platform(&s6000_soc_platform);
486}
487module_init(s6000_pcm_init);
488
489static void __exit s6000_pcm_exit(void)
490{
491 snd_soc_unregister_platform(&s6000_soc_platform);
492}
493module_exit(s6000_pcm_exit);
494
495MODULE_AUTHOR("Daniel Gloeckner");
496MODULE_DESCRIPTION("Stretch s6000 family PCM DMA module");
497MODULE_LICENSE("GPL");
diff --git a/sound/soc/s6000/s6000-pcm.h b/sound/soc/s6000/s6000-pcm.h
new file mode 100644
index 000000000000..96f23f6f52bf
--- /dev/null
+++ b/sound/soc/s6000/s6000-pcm.h
@@ -0,0 +1,35 @@
1/*
2 * ALSA PCM interface for the Stretch s6000 family
3 *
4 * Author: Daniel Gloeckner, <dg@emlix.com>
5 * Copyright: (C) 2009 emlix GmbH <info@emlix.com>
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License version 2 as
9 * published by the Free Software Foundation.
10 */
11
12#ifndef _S6000_PCM_H
13#define _S6000_PCM_H
14
15struct snd_soc_dai;
16struct snd_pcm_substream;
17
18struct s6000_pcm_dma_params {
19 unsigned int (*check_xrun)(struct snd_soc_dai *cpu_dai);
20 int (*trigger)(struct snd_pcm_substream *substream, int cmd, int after);
21 dma_addr_t sif_in;
22 dma_addr_t sif_out;
23 u32 dma_in;
24 u32 dma_out;
25 int irq;
26 int same_rate;
27
28 spinlock_t lock;
29 int in_use;
30 int rate;
31};
32
33extern struct snd_soc_platform s6000_soc_platform;
34
35#endif
diff --git a/sound/soc/s6000/s6105-ipcam.c b/sound/soc/s6000/s6105-ipcam.c
new file mode 100644
index 000000000000..b5f95f9781c1
--- /dev/null
+++ b/sound/soc/s6000/s6105-ipcam.c
@@ -0,0 +1,244 @@
1/*
2 * ASoC driver for Stretch s6105 IP camera platform
3 *
4 * Author: Daniel Gloeckner, <dg@emlix.com>
5 * Copyright: (C) 2009 emlix GmbH <info@emlix.com>
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License version 2 as
9 * published by the Free Software Foundation.
10 */
11
12#include <linux/module.h>
13#include <linux/moduleparam.h>
14#include <linux/timer.h>
15#include <linux/interrupt.h>
16#include <linux/platform_device.h>
17#include <sound/core.h>
18#include <sound/pcm.h>
19#include <sound/soc.h>
20#include <sound/soc-dapm.h>
21
22#include <variant/dmac.h>
23
24#include "../codecs/tlv320aic3x.h"
25#include "s6000-pcm.h"
26#include "s6000-i2s.h"
27
28#define S6105_CAM_CODEC_CLOCK 12288000
29
30static int s6105_hw_params(struct snd_pcm_substream *substream,
31 struct snd_pcm_hw_params *params)
32{
33 struct snd_soc_pcm_runtime *rtd = substream->private_data;
34 struct snd_soc_dai *codec_dai = rtd->dai->codec_dai;
35 struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai;
36 int ret = 0;
37
38 /* set codec DAI configuration */
39 ret = snd_soc_dai_set_fmt(codec_dai, SND_SOC_DAIFMT_I2S |
40 SND_SOC_DAIFMT_CBM_CFM);
41 if (ret < 0)
42 return ret;
43
44 /* set cpu DAI configuration */
45 ret = snd_soc_dai_set_fmt(cpu_dai, SND_SOC_DAIFMT_CBM_CFM |
46 SND_SOC_DAIFMT_NB_NF);
47 if (ret < 0)
48 return ret;
49
50 /* set the codec system clock */
51 ret = snd_soc_dai_set_sysclk(codec_dai, 0, S6105_CAM_CODEC_CLOCK,
52 SND_SOC_CLOCK_OUT);
53 if (ret < 0)
54 return ret;
55
56 return 0;
57}
58
59static struct snd_soc_ops s6105_ops = {
60 .hw_params = s6105_hw_params,
61};
62
63/* s6105 machine dapm widgets */
64static const struct snd_soc_dapm_widget aic3x_dapm_widgets[] = {
65 SND_SOC_DAPM_LINE("Audio Out Differential", NULL),
66 SND_SOC_DAPM_LINE("Audio Out Stereo", NULL),
67 SND_SOC_DAPM_LINE("Audio In", NULL),
68};
69
70/* s6105 machine audio_mapnections to the codec pins */
71static const struct snd_soc_dapm_route audio_map[] = {
72 /* Audio Out connected to HPLOUT, HPLCOM, HPROUT */
73 {"Audio Out Differential", NULL, "HPLOUT"},
74 {"Audio Out Differential", NULL, "HPLCOM"},
75 {"Audio Out Stereo", NULL, "HPLOUT"},
76 {"Audio Out Stereo", NULL, "HPROUT"},
77
78 /* Audio In connected to LINE1L, LINE1R */
79 {"LINE1L", NULL, "Audio In"},
80 {"LINE1R", NULL, "Audio In"},
81};
82
83static int output_type_info(struct snd_kcontrol *kcontrol,
84 struct snd_ctl_elem_info *uinfo)
85{
86 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
87 uinfo->count = 1;
88 uinfo->value.enumerated.items = 2;
89 if (uinfo->value.enumerated.item) {
90 uinfo->value.enumerated.item = 1;
91 strcpy(uinfo->value.enumerated.name, "HPLOUT/HPROUT");
92 } else {
93 strcpy(uinfo->value.enumerated.name, "HPLOUT/HPLCOM");
94 }
95 return 0;
96}
97
98static int output_type_get(struct snd_kcontrol *kcontrol,
99 struct snd_ctl_elem_value *ucontrol)
100{
101 ucontrol->value.enumerated.item[0] = kcontrol->private_value;
102 return 0;
103}
104
105static int output_type_put(struct snd_kcontrol *kcontrol,
106 struct snd_ctl_elem_value *ucontrol)
107{
108 struct snd_soc_codec *codec = kcontrol->private_data;
109 unsigned int val = (ucontrol->value.enumerated.item[0] != 0);
110 char *differential = "Audio Out Differential";
111 char *stereo = "Audio Out Stereo";
112
113 if (kcontrol->private_value == val)
114 return 0;
115 kcontrol->private_value = val;
116 snd_soc_dapm_disable_pin(codec, val ? differential : stereo);
117 snd_soc_dapm_sync(codec);
118 snd_soc_dapm_enable_pin(codec, val ? stereo : differential);
119 snd_soc_dapm_sync(codec);
120
121 return 1;
122}
123
124static const struct snd_kcontrol_new audio_out_mux = {
125 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
126 .name = "Master Output Mux",
127 .index = 0,
128 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
129 .info = output_type_info,
130 .get = output_type_get,
131 .put = output_type_put,
132 .private_value = 1 /* default to stereo */
133};
134
135/* Logic for a aic3x as connected on the s6105 ip camera ref design */
136static int s6105_aic3x_init(struct snd_soc_codec *codec)
137{
138 /* Add s6105 specific widgets */
139 snd_soc_dapm_new_controls(codec, aic3x_dapm_widgets,
140 ARRAY_SIZE(aic3x_dapm_widgets));
141
142 /* Set up s6105 specific audio path audio_map */
143 snd_soc_dapm_add_routes(codec, audio_map, ARRAY_SIZE(audio_map));
144
145 /* not present */
146 snd_soc_dapm_nc_pin(codec, "MONO_LOUT");
147 snd_soc_dapm_nc_pin(codec, "LINE2L");
148 snd_soc_dapm_nc_pin(codec, "LINE2R");
149
150 /* not connected */
151 snd_soc_dapm_nc_pin(codec, "MIC3L"); /* LINE2L on this chip */
152 snd_soc_dapm_nc_pin(codec, "MIC3R"); /* LINE2R on this chip */
153 snd_soc_dapm_nc_pin(codec, "LLOUT");
154 snd_soc_dapm_nc_pin(codec, "RLOUT");
155 snd_soc_dapm_nc_pin(codec, "HPRCOM");
156
157 /* always connected */
158 snd_soc_dapm_enable_pin(codec, "Audio In");
159
160 /* must correspond to audio_out_mux.private_value initializer */
161 snd_soc_dapm_disable_pin(codec, "Audio Out Differential");
162 snd_soc_dapm_sync(codec);
163 snd_soc_dapm_enable_pin(codec, "Audio Out Stereo");
164
165 snd_soc_dapm_sync(codec);
166
167 snd_ctl_add(codec->card, snd_ctl_new1(&audio_out_mux, codec));
168
169 return 0;
170}
171
172/* s6105 digital audio interface glue - connects codec <--> CPU */
173static struct snd_soc_dai_link s6105_dai = {
174 .name = "TLV320AIC31",
175 .stream_name = "AIC31",
176 .cpu_dai = &s6000_i2s_dai,
177 .codec_dai = &aic3x_dai,
178 .init = s6105_aic3x_init,
179 .ops = &s6105_ops,
180};
181
182/* s6105 audio machine driver */
183static struct snd_soc_card snd_soc_card_s6105 = {
184 .name = "Stretch IP Camera",
185 .platform = &s6000_soc_platform,
186 .dai_link = &s6105_dai,
187 .num_links = 1,
188};
189
190/* s6105 audio private data */
191static struct aic3x_setup_data s6105_aic3x_setup = {
192 .i2c_bus = 0,
193 .i2c_address = 0x18,
194};
195
196/* s6105 audio subsystem */
197static struct snd_soc_device s6105_snd_devdata = {
198 .card = &snd_soc_card_s6105,
199 .codec_dev = &soc_codec_dev_aic3x,
200 .codec_data = &s6105_aic3x_setup,
201};
202
203static struct s6000_snd_platform_data __initdata s6105_snd_data = {
204 .wide = 0,
205 .channel_in = 0,
206 .channel_out = 1,
207 .lines_in = 1,
208 .lines_out = 1,
209 .same_rate = 1,
210};
211
212static struct platform_device *s6105_snd_device;
213
214static int __init s6105_init(void)
215{
216 int ret;
217
218 s6105_snd_device = platform_device_alloc("soc-audio", -1);
219 if (!s6105_snd_device)
220 return -ENOMEM;
221
222 platform_set_drvdata(s6105_snd_device, &s6105_snd_devdata);
223 s6105_snd_devdata.dev = &s6105_snd_device->dev;
224 platform_device_add_data(s6105_snd_device, &s6105_snd_data,
225 sizeof(s6105_snd_data));
226
227 ret = platform_device_add(s6105_snd_device);
228 if (ret)
229 platform_device_put(s6105_snd_device);
230
231 return ret;
232}
233
234static void __exit s6105_exit(void)
235{
236 platform_device_unregister(s6105_snd_device);
237}
238
239module_init(s6105_init);
240module_exit(s6105_exit);
241
242MODULE_AUTHOR("Daniel Gloeckner");
243MODULE_DESCRIPTION("Stretch s6105 IP camera ASoC driver");
244MODULE_LICENSE("GPL");
diff --git a/sound/soc/sh/ssi.c b/sound/soc/sh/ssi.c
index 56fa0872abbb..b378096cadb1 100644
--- a/sound/soc/sh/ssi.c
+++ b/sound/soc/sh/ssi.c
@@ -145,7 +145,7 @@ static int ssi_hw_params(struct snd_pcm_substream *substream,
145 recv = (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) ? 0 : 1; 145 recv = (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) ? 0 : 1;
146 146
147 pr_debug("ssi_hw_params() enter\nssicr was %08lx\n", ssicr); 147 pr_debug("ssi_hw_params() enter\nssicr was %08lx\n", ssicr);
148 pr_debug("bits: %d channels: %d\n", bits, channels); 148 pr_debug("bits: %u channels: %u\n", bits, channels);
149 149
150 ssicr &= ~(CR_TRMD | CR_CHNL_MASK | CR_DWL_MASK | CR_PDTA | 150 ssicr &= ~(CR_TRMD | CR_CHNL_MASK | CR_DWL_MASK | CR_PDTA |
151 CR_SWL_MASK); 151 CR_SWL_MASK);
diff --git a/sound/soc/soc-cache.c b/sound/soc/soc-cache.c
new file mode 100644
index 000000000000..c8ceddc2a26c
--- /dev/null
+++ b/sound/soc/soc-cache.c
@@ -0,0 +1,218 @@
1/*
2 * soc-cache.c -- ASoC register cache helpers
3 *
4 * Copyright 2009 Wolfson Microelectronics PLC.
5 *
6 * Author: Mark Brown <broonie@opensource.wolfsonmicro.com>
7 *
8 * This program is free software; you can redistribute it and/or modify it
9 * under the terms of the GNU General Public License as published by the
10 * Free Software Foundation; either version 2 of the License, or (at your
11 * option) any later version.
12 */
13
14#include <linux/i2c.h>
15#include <linux/spi/spi.h>
16#include <sound/soc.h>
17
18static unsigned int snd_soc_7_9_read(struct snd_soc_codec *codec,
19 unsigned int reg)
20{
21 u16 *cache = codec->reg_cache;
22 if (reg >= codec->reg_cache_size)
23 return -1;
24 return cache[reg];
25}
26
27static int snd_soc_7_9_write(struct snd_soc_codec *codec, unsigned int reg,
28 unsigned int value)
29{
30 u16 *cache = codec->reg_cache;
31 u8 data[2];
32 int ret;
33
34 BUG_ON(codec->volatile_register);
35
36 data[0] = (reg << 1) | ((value >> 8) & 0x0001);
37 data[1] = value & 0x00ff;
38
39 if (reg < codec->reg_cache_size)
40 cache[reg] = value;
41 ret = codec->hw_write(codec->control_data, data, 2);
42 if (ret == 2)
43 return 0;
44 if (ret < 0)
45 return ret;
46 else
47 return -EIO;
48}
49
50#if defined(CONFIG_SPI_MASTER)
51static int snd_soc_7_9_spi_write(void *control_data, const char *data,
52 int len)
53{
54 struct spi_device *spi = control_data;
55 struct spi_transfer t;
56 struct spi_message m;
57 u8 msg[2];
58
59 if (len <= 0)
60 return 0;
61
62 msg[0] = data[0];
63 msg[1] = data[1];
64
65 spi_message_init(&m);
66 memset(&t, 0, (sizeof t));
67
68 t.tx_buf = &msg[0];
69 t.len = len;
70
71 spi_message_add_tail(&t, &m);
72 spi_sync(spi, &m);
73
74 return len;
75}
76#else
77#define snd_soc_7_9_spi_write NULL
78#endif
79
80static int snd_soc_8_16_write(struct snd_soc_codec *codec, unsigned int reg,
81 unsigned int value)
82{
83 u16 *reg_cache = codec->reg_cache;
84 u8 data[3];
85
86 data[0] = reg;
87 data[1] = (value >> 8) & 0xff;
88 data[2] = value & 0xff;
89
90 if (!snd_soc_codec_volatile_register(codec, reg))
91 reg_cache[reg] = value;
92
93 if (codec->hw_write(codec->control_data, data, 3) == 3)
94 return 0;
95 else
96 return -EIO;
97}
98
99static unsigned int snd_soc_8_16_read(struct snd_soc_codec *codec,
100 unsigned int reg)
101{
102 u16 *cache = codec->reg_cache;
103
104 if (reg >= codec->reg_cache_size ||
105 snd_soc_codec_volatile_register(codec, reg))
106 return codec->hw_read(codec, reg);
107 else
108 return cache[reg];
109}
110
111#if defined(CONFIG_I2C) || (defined(CONFIG_I2C_MODULE) && defined(MODULE))
112static unsigned int snd_soc_8_16_read_i2c(struct snd_soc_codec *codec,
113 unsigned int r)
114{
115 struct i2c_msg xfer[2];
116 u8 reg = r;
117 u16 data;
118 int ret;
119 struct i2c_client *client = codec->control_data;
120
121 /* Write register */
122 xfer[0].addr = client->addr;
123 xfer[0].flags = 0;
124 xfer[0].len = 1;
125 xfer[0].buf = &reg;
126
127 /* Read data */
128 xfer[1].addr = client->addr;
129 xfer[1].flags = I2C_M_RD;
130 xfer[1].len = 2;
131 xfer[1].buf = (u8 *)&data;
132
133 ret = i2c_transfer(client->adapter, xfer, 2);
134 if (ret != 2) {
135 dev_err(&client->dev, "i2c_transfer() returned %d\n", ret);
136 return 0;
137 }
138
139 return (data >> 8) | ((data & 0xff) << 8);
140}
141#else
142#define snd_soc_8_16_read_i2c NULL
143#endif
144
145static struct {
146 int addr_bits;
147 int data_bits;
148 int (*write)(struct snd_soc_codec *codec, unsigned int, unsigned int);
149 int (*spi_write)(void *, const char *, int);
150 unsigned int (*read)(struct snd_soc_codec *, unsigned int);
151 unsigned int (*i2c_read)(struct snd_soc_codec *, unsigned int);
152} io_types[] = {
153 { 7, 9, snd_soc_7_9_write, snd_soc_7_9_spi_write, snd_soc_7_9_read },
154 { 8, 16, snd_soc_8_16_write, NULL, snd_soc_8_16_read,
155 snd_soc_8_16_read_i2c },
156};
157
158/**
159 * snd_soc_codec_set_cache_io: Set up standard I/O functions.
160 *
161 * @codec: CODEC to configure.
162 * @type: Type of cache.
163 * @addr_bits: Number of bits of register address data.
164 * @data_bits: Number of bits of data per register.
165 * @control: Control bus used.
166 *
167 * Register formats are frequently shared between many I2C and SPI
168 * devices. In order to promote code reuse the ASoC core provides
169 * some standard implementations of CODEC read and write operations
170 * which can be set up using this function.
171 *
172 * The caller is responsible for allocating and initialising the
173 * actual cache.
174 *
175 * Note that at present this code cannot be used by CODECs with
176 * volatile registers.
177 */
178int snd_soc_codec_set_cache_io(struct snd_soc_codec *codec,
179 int addr_bits, int data_bits,
180 enum snd_soc_control_type control)
181{
182 int i;
183
184 for (i = 0; i < ARRAY_SIZE(io_types); i++)
185 if (io_types[i].addr_bits == addr_bits &&
186 io_types[i].data_bits == data_bits)
187 break;
188 if (i == ARRAY_SIZE(io_types)) {
189 printk(KERN_ERR
190 "No I/O functions for %d bit address %d bit data\n",
191 addr_bits, data_bits);
192 return -EINVAL;
193 }
194
195 codec->write = io_types[i].write;
196 codec->read = io_types[i].read;
197
198 switch (control) {
199 case SND_SOC_CUSTOM:
200 break;
201
202 case SND_SOC_I2C:
203#if defined(CONFIG_I2C) || (defined(CONFIG_I2C_MODULE) && defined(MODULE))
204 codec->hw_write = (hw_write_t)i2c_master_send;
205#endif
206 if (io_types[i].i2c_read)
207 codec->hw_read = io_types[i].i2c_read;
208 break;
209
210 case SND_SOC_SPI:
211 if (io_types[i].spi_write)
212 codec->hw_write = io_types[i].spi_write;
213 break;
214 }
215
216 return 0;
217}
218EXPORT_SYMBOL_GPL(snd_soc_codec_set_cache_io);
diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c
index 1cd149b9ce69..e984a17cd656 100644
--- a/sound/soc/soc-core.c
+++ b/sound/soc/soc-core.c
@@ -28,6 +28,7 @@
28#include <linux/bitops.h> 28#include <linux/bitops.h>
29#include <linux/debugfs.h> 29#include <linux/debugfs.h>
30#include <linux/platform_device.h> 30#include <linux/platform_device.h>
31#include <sound/ac97_codec.h>
31#include <sound/core.h> 32#include <sound/core.h>
32#include <sound/pcm.h> 33#include <sound/pcm.h>
33#include <sound/pcm_params.h> 34#include <sound/pcm_params.h>
@@ -113,6 +114,35 @@ static int soc_ac97_dev_register(struct snd_soc_codec *codec)
113} 114}
114#endif 115#endif
115 116
117static int soc_pcm_apply_symmetry(struct snd_pcm_substream *substream)
118{
119 struct snd_soc_pcm_runtime *rtd = substream->private_data;
120 struct snd_soc_device *socdev = rtd->socdev;
121 struct snd_soc_card *card = socdev->card;
122 struct snd_soc_dai_link *machine = rtd->dai;
123 struct snd_soc_dai *cpu_dai = machine->cpu_dai;
124 struct snd_soc_dai *codec_dai = machine->codec_dai;
125 int ret;
126
127 if (codec_dai->symmetric_rates || cpu_dai->symmetric_rates ||
128 machine->symmetric_rates) {
129 dev_dbg(card->dev, "Symmetry forces %dHz rate\n",
130 machine->rate);
131
132 ret = snd_pcm_hw_constraint_minmax(substream->runtime,
133 SNDRV_PCM_HW_PARAM_RATE,
134 machine->rate,
135 machine->rate);
136 if (ret < 0) {
137 dev_err(card->dev,
138 "Unable to apply rate symmetry constraint: %d\n", ret);
139 return ret;
140 }
141 }
142
143 return 0;
144}
145
116/* 146/*
117 * Called by ALSA when a PCM substream is opened, the runtime->hw record is 147 * Called by ALSA when a PCM substream is opened, the runtime->hw record is
118 * then initialized and any private data can be allocated. This also calls 148 * then initialized and any private data can be allocated. This also calls
@@ -221,6 +251,13 @@ static int soc_pcm_open(struct snd_pcm_substream *substream)
221 goto machine_err; 251 goto machine_err;
222 } 252 }
223 253
254 /* Symmetry only applies if we've already got an active stream. */
255 if (cpu_dai->active || codec_dai->active) {
256 ret = soc_pcm_apply_symmetry(substream);
257 if (ret != 0)
258 goto machine_err;
259 }
260
224 pr_debug("asoc: %s <-> %s info:\n", codec_dai->name, cpu_dai->name); 261 pr_debug("asoc: %s <-> %s info:\n", codec_dai->name, cpu_dai->name);
225 pr_debug("asoc: rate mask 0x%x\n", runtime->hw.rates); 262 pr_debug("asoc: rate mask 0x%x\n", runtime->hw.rates);
226 pr_debug("asoc: min ch %d max ch %d\n", runtime->hw.channels_min, 263 pr_debug("asoc: min ch %d max ch %d\n", runtime->hw.channels_min,
@@ -263,7 +300,6 @@ static void close_delayed_work(struct work_struct *work)
263{ 300{
264 struct snd_soc_card *card = container_of(work, struct snd_soc_card, 301 struct snd_soc_card *card = container_of(work, struct snd_soc_card,
265 delayed_work.work); 302 delayed_work.work);
266 struct snd_soc_device *socdev = card->socdev;
267 struct snd_soc_codec *codec = card->codec; 303 struct snd_soc_codec *codec = card->codec;
268 struct snd_soc_dai *codec_dai; 304 struct snd_soc_dai *codec_dai;
269 int i; 305 int i;
@@ -279,27 +315,10 @@ static void close_delayed_work(struct work_struct *work)
279 315
280 /* are we waiting on this codec DAI stream */ 316 /* are we waiting on this codec DAI stream */
281 if (codec_dai->pop_wait == 1) { 317 if (codec_dai->pop_wait == 1) {
282
283 /* Reduce power if no longer active */
284 if (codec->active == 0) {
285 pr_debug("pop wq D1 %s %s\n", codec->name,
286 codec_dai->playback.stream_name);
287 snd_soc_dapm_set_bias_level(socdev,
288 SND_SOC_BIAS_PREPARE);
289 }
290
291 codec_dai->pop_wait = 0; 318 codec_dai->pop_wait = 0;
292 snd_soc_dapm_stream_event(codec, 319 snd_soc_dapm_stream_event(codec,
293 codec_dai->playback.stream_name, 320 codec_dai->playback.stream_name,
294 SND_SOC_DAPM_STREAM_STOP); 321 SND_SOC_DAPM_STREAM_STOP);
295
296 /* Fall into standby if no longer active */
297 if (codec->active == 0) {
298 pr_debug("pop wq D3 %s %s\n", codec->name,
299 codec_dai->playback.stream_name);
300 snd_soc_dapm_set_bias_level(socdev,
301 SND_SOC_BIAS_STANDBY);
302 }
303 } 322 }
304 } 323 }
305 mutex_unlock(&pcm_mutex); 324 mutex_unlock(&pcm_mutex);
@@ -363,10 +382,6 @@ static int soc_codec_close(struct snd_pcm_substream *substream)
363 snd_soc_dapm_stream_event(codec, 382 snd_soc_dapm_stream_event(codec,
364 codec_dai->capture.stream_name, 383 codec_dai->capture.stream_name,
365 SND_SOC_DAPM_STREAM_STOP); 384 SND_SOC_DAPM_STREAM_STOP);
366
367 if (codec->active == 0 && codec_dai->pop_wait == 0)
368 snd_soc_dapm_set_bias_level(socdev,
369 SND_SOC_BIAS_STANDBY);
370 } 385 }
371 386
372 mutex_unlock(&pcm_mutex); 387 mutex_unlock(&pcm_mutex);
@@ -431,36 +446,16 @@ static int soc_pcm_prepare(struct snd_pcm_substream *substream)
431 cancel_delayed_work(&card->delayed_work); 446 cancel_delayed_work(&card->delayed_work);
432 } 447 }
433 448
434 /* do we need to power up codec */ 449 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
435 if (codec->bias_level != SND_SOC_BIAS_ON) { 450 snd_soc_dapm_stream_event(codec,
436 snd_soc_dapm_set_bias_level(socdev, 451 codec_dai->playback.stream_name,
437 SND_SOC_BIAS_PREPARE); 452 SND_SOC_DAPM_STREAM_START);
438 453 else
439 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) 454 snd_soc_dapm_stream_event(codec,
440 snd_soc_dapm_stream_event(codec, 455 codec_dai->capture.stream_name,
441 codec_dai->playback.stream_name, 456 SND_SOC_DAPM_STREAM_START);
442 SND_SOC_DAPM_STREAM_START);
443 else
444 snd_soc_dapm_stream_event(codec,
445 codec_dai->capture.stream_name,
446 SND_SOC_DAPM_STREAM_START);
447
448 snd_soc_dapm_set_bias_level(socdev, SND_SOC_BIAS_ON);
449 snd_soc_dai_digital_mute(codec_dai, 0);
450
451 } else {
452 /* codec already powered - power on widgets */
453 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
454 snd_soc_dapm_stream_event(codec,
455 codec_dai->playback.stream_name,
456 SND_SOC_DAPM_STREAM_START);
457 else
458 snd_soc_dapm_stream_event(codec,
459 codec_dai->capture.stream_name,
460 SND_SOC_DAPM_STREAM_START);
461 457
462 snd_soc_dai_digital_mute(codec_dai, 0); 458 snd_soc_dai_digital_mute(codec_dai, 0);
463 }
464 459
465out: 460out:
466 mutex_unlock(&pcm_mutex); 461 mutex_unlock(&pcm_mutex);
@@ -521,6 +516,8 @@ static int soc_pcm_hw_params(struct snd_pcm_substream *substream,
521 } 516 }
522 } 517 }
523 518
519 machine->rate = params_rate(params);
520
524out: 521out:
525 mutex_unlock(&pcm_mutex); 522 mutex_unlock(&pcm_mutex);
526 return ret; 523 return ret;
@@ -623,8 +620,9 @@ static struct snd_pcm_ops soc_pcm_ops = {
623 620
624#ifdef CONFIG_PM 621#ifdef CONFIG_PM
625/* powers down audio subsystem for suspend */ 622/* powers down audio subsystem for suspend */
626static int soc_suspend(struct platform_device *pdev, pm_message_t state) 623static int soc_suspend(struct device *dev)
627{ 624{
625 struct platform_device *pdev = to_platform_device(dev);
628 struct snd_soc_device *socdev = platform_get_drvdata(pdev); 626 struct snd_soc_device *socdev = platform_get_drvdata(pdev);
629 struct snd_soc_card *card = socdev->card; 627 struct snd_soc_card *card = socdev->card;
630 struct snd_soc_platform *platform = card->platform; 628 struct snd_soc_platform *platform = card->platform;
@@ -632,6 +630,12 @@ static int soc_suspend(struct platform_device *pdev, pm_message_t state)
632 struct snd_soc_codec *codec = card->codec; 630 struct snd_soc_codec *codec = card->codec;
633 int i; 631 int i;
634 632
633 /* If the initialization of this soc device failed, there is no codec
634 * associated with it. Just bail out in this case.
635 */
636 if (!codec)
637 return 0;
638
635 /* Due to the resume being scheduled into a workqueue we could 639 /* Due to the resume being scheduled into a workqueue we could
636 * suspend before that's finished - wait for it to complete. 640 * suspend before that's finished - wait for it to complete.
637 */ 641 */
@@ -654,7 +658,7 @@ static int soc_suspend(struct platform_device *pdev, pm_message_t state)
654 snd_pcm_suspend_all(card->dai_link[i].pcm); 658 snd_pcm_suspend_all(card->dai_link[i].pcm);
655 659
656 if (card->suspend_pre) 660 if (card->suspend_pre)
657 card->suspend_pre(pdev, state); 661 card->suspend_pre(pdev, PMSG_SUSPEND);
658 662
659 for (i = 0; i < card->num_links; i++) { 663 for (i = 0; i < card->num_links; i++) {
660 struct snd_soc_dai *cpu_dai = card->dai_link[i].cpu_dai; 664 struct snd_soc_dai *cpu_dai = card->dai_link[i].cpu_dai;
@@ -680,7 +684,7 @@ static int soc_suspend(struct platform_device *pdev, pm_message_t state)
680 } 684 }
681 685
682 if (codec_dev->suspend) 686 if (codec_dev->suspend)
683 codec_dev->suspend(pdev, state); 687 codec_dev->suspend(pdev, PMSG_SUSPEND);
684 688
685 for (i = 0; i < card->num_links; i++) { 689 for (i = 0; i < card->num_links; i++) {
686 struct snd_soc_dai *cpu_dai = card->dai_link[i].cpu_dai; 690 struct snd_soc_dai *cpu_dai = card->dai_link[i].cpu_dai;
@@ -689,7 +693,7 @@ static int soc_suspend(struct platform_device *pdev, pm_message_t state)
689 } 693 }
690 694
691 if (card->suspend_post) 695 if (card->suspend_post)
692 card->suspend_post(pdev, state); 696 card->suspend_post(pdev, PMSG_SUSPEND);
693 697
694 return 0; 698 return 0;
695} 699}
@@ -763,8 +767,9 @@ static void soc_resume_deferred(struct work_struct *work)
763} 767}
764 768
765/* powers up audio subsystem after a suspend */ 769/* powers up audio subsystem after a suspend */
766static int soc_resume(struct platform_device *pdev) 770static int soc_resume(struct device *dev)
767{ 771{
772 struct platform_device *pdev = to_platform_device(dev);
768 struct snd_soc_device *socdev = platform_get_drvdata(pdev); 773 struct snd_soc_device *socdev = platform_get_drvdata(pdev);
769 struct snd_soc_card *card = socdev->card; 774 struct snd_soc_card *card = socdev->card;
770 struct snd_soc_dai *cpu_dai = card->dai_link[0].cpu_dai; 775 struct snd_soc_dai *cpu_dai = card->dai_link[0].cpu_dai;
@@ -786,6 +791,44 @@ static int soc_resume(struct platform_device *pdev)
786 return 0; 791 return 0;
787} 792}
788 793
794/**
795 * snd_soc_suspend_device: Notify core of device suspend
796 *
797 * @dev: Device being suspended.
798 *
799 * In order to ensure that the entire audio subsystem is suspended in a
800 * coordinated fashion ASoC devices should suspend themselves when
801 * called by ASoC. When the standard kernel suspend process asks the
802 * device to suspend it should call this function to initiate a suspend
803 * of the entire ASoC card.
804 *
805 * \note Currently this function is stubbed out.
806 */
807int snd_soc_suspend_device(struct device *dev)
808{
809 return 0;
810}
811EXPORT_SYMBOL_GPL(snd_soc_suspend_device);
812
813/**
814 * snd_soc_resume_device: Notify core of device resume
815 *
816 * @dev: Device being resumed.
817 *
818 * In order to ensure that the entire audio subsystem is resumed in a
819 * coordinated fashion ASoC devices should resume themselves when called
820 * by ASoC. When the standard kernel resume process asks the device
821 * to resume it should call this function. Once all the components of
822 * the card have notified that they are ready to be resumed the card
823 * will be resumed.
824 *
825 * \note Currently this function is stubbed out.
826 */
827int snd_soc_resume_device(struct device *dev)
828{
829 return 0;
830}
831EXPORT_SYMBOL_GPL(snd_soc_resume_device);
789#else 832#else
790#define soc_suspend NULL 833#define soc_suspend NULL
791#define soc_resume NULL 834#define soc_resume NULL
@@ -979,16 +1022,39 @@ static int soc_remove(struct platform_device *pdev)
979 return 0; 1022 return 0;
980} 1023}
981 1024
1025static int soc_poweroff(struct device *dev)
1026{
1027 struct platform_device *pdev = to_platform_device(dev);
1028 struct snd_soc_device *socdev = platform_get_drvdata(pdev);
1029 struct snd_soc_card *card = socdev->card;
1030
1031 if (!card->instantiated)
1032 return 0;
1033
1034 /* Flush out pmdown_time work - we actually do want to run it
1035 * now, we're shutting down so no imminent restart. */
1036 run_delayed_work(&card->delayed_work);
1037
1038 snd_soc_dapm_shutdown(socdev);
1039
1040 return 0;
1041}
1042
1043static struct dev_pm_ops soc_pm_ops = {
1044 .suspend = soc_suspend,
1045 .resume = soc_resume,
1046 .poweroff = soc_poweroff,
1047};
1048
982/* ASoC platform driver */ 1049/* ASoC platform driver */
983static struct platform_driver soc_driver = { 1050static struct platform_driver soc_driver = {
984 .driver = { 1051 .driver = {
985 .name = "soc-audio", 1052 .name = "soc-audio",
986 .owner = THIS_MODULE, 1053 .owner = THIS_MODULE,
1054 .pm = &soc_pm_ops,
987 }, 1055 },
988 .probe = soc_probe, 1056 .probe = soc_probe,
989 .remove = soc_remove, 1057 .remove = soc_remove,
990 .suspend = soc_suspend,
991 .resume = soc_resume,
992}; 1058};
993 1059
994/* create a new pcm */ 1060/* create a new pcm */
@@ -1060,6 +1126,23 @@ static int soc_new_pcm(struct snd_soc_device *socdev,
1060 return ret; 1126 return ret;
1061} 1127}
1062 1128
1129/**
1130 * snd_soc_codec_volatile_register: Report if a register is volatile.
1131 *
1132 * @codec: CODEC to query.
1133 * @reg: Register to query.
1134 *
1135 * Boolean function indiciating if a CODEC register is volatile.
1136 */
1137int snd_soc_codec_volatile_register(struct snd_soc_codec *codec, int reg)
1138{
1139 if (codec->volatile_register)
1140 return codec->volatile_register(reg);
1141 else
1142 return 0;
1143}
1144EXPORT_SYMBOL_GPL(snd_soc_codec_volatile_register);
1145
1063/* codec register dump */ 1146/* codec register dump */
1064static ssize_t soc_codec_reg_show(struct snd_soc_codec *codec, char *buf) 1147static ssize_t soc_codec_reg_show(struct snd_soc_codec *codec, char *buf)
1065{ 1148{
@@ -1073,6 +1156,9 @@ static ssize_t soc_codec_reg_show(struct snd_soc_codec *codec, char *buf)
1073 1156
1074 count += sprintf(buf, "%s registers\n", codec->name); 1157 count += sprintf(buf, "%s registers\n", codec->name);
1075 for (i = 0; i < codec->reg_cache_size; i += step) { 1158 for (i = 0; i < codec->reg_cache_size; i += step) {
1159 if (codec->readable_register && !codec->readable_register(i))
1160 continue;
1161
1076 count += sprintf(buf + count, "%2x: ", i); 1162 count += sprintf(buf + count, "%2x: ", i);
1077 if (count >= PAGE_SIZE - 1) 1163 if (count >= PAGE_SIZE - 1)
1078 break; 1164 break;
@@ -1262,10 +1348,10 @@ EXPORT_SYMBOL_GPL(snd_soc_free_ac97_codec);
1262 * Returns 1 for change else 0. 1348 * Returns 1 for change else 0.
1263 */ 1349 */
1264int snd_soc_update_bits(struct snd_soc_codec *codec, unsigned short reg, 1350int snd_soc_update_bits(struct snd_soc_codec *codec, unsigned short reg,
1265 unsigned short mask, unsigned short value) 1351 unsigned int mask, unsigned int value)
1266{ 1352{
1267 int change; 1353 int change;
1268 unsigned short old, new; 1354 unsigned int old, new;
1269 1355
1270 mutex_lock(&io_mutex); 1356 mutex_lock(&io_mutex);
1271 old = snd_soc_read(codec, reg); 1357 old = snd_soc_read(codec, reg);
@@ -1292,10 +1378,10 @@ EXPORT_SYMBOL_GPL(snd_soc_update_bits);
1292 * Returns 1 for change else 0. 1378 * Returns 1 for change else 0.
1293 */ 1379 */
1294int snd_soc_test_bits(struct snd_soc_codec *codec, unsigned short reg, 1380int snd_soc_test_bits(struct snd_soc_codec *codec, unsigned short reg,
1295 unsigned short mask, unsigned short value) 1381 unsigned int mask, unsigned int value)
1296{ 1382{
1297 int change; 1383 int change;
1298 unsigned short old, new; 1384 unsigned int old, new;
1299 1385
1300 mutex_lock(&io_mutex); 1386 mutex_lock(&io_mutex);
1301 old = snd_soc_read(codec, reg); 1387 old = snd_soc_read(codec, reg);
@@ -1334,6 +1420,7 @@ int snd_soc_new_pcms(struct snd_soc_device *socdev, int idx, const char *xid)
1334 return ret; 1420 return ret;
1335 } 1421 }
1336 1422
1423 codec->socdev = socdev;
1337 codec->card->dev = socdev->dev; 1424 codec->card->dev = socdev->dev;
1338 codec->card->private_data = codec; 1425 codec->card->private_data = codec;
1339 strncpy(codec->card->driver, codec->name, sizeof(codec->card->driver)); 1426 strncpy(codec->card->driver, codec->name, sizeof(codec->card->driver));
@@ -1378,14 +1465,20 @@ int snd_soc_init_card(struct snd_soc_device *socdev)
1378 continue; 1465 continue;
1379 } 1466 }
1380 } 1467 }
1381 if (card->dai_link[i].codec_dai->ac97_control) 1468 if (card->dai_link[i].codec_dai->ac97_control) {
1382 ac97 = 1; 1469 ac97 = 1;
1470 snd_ac97_dev_add_pdata(codec->ac97,
1471 card->dai_link[i].cpu_dai->ac97_pdata);
1472 }
1383 } 1473 }
1384 snprintf(codec->card->shortname, sizeof(codec->card->shortname), 1474 snprintf(codec->card->shortname, sizeof(codec->card->shortname),
1385 "%s", card->name); 1475 "%s", card->name);
1386 snprintf(codec->card->longname, sizeof(codec->card->longname), 1476 snprintf(codec->card->longname, sizeof(codec->card->longname),
1387 "%s (%s)", card->name, codec->name); 1477 "%s (%s)", card->name, codec->name);
1388 1478
1479 /* Make sure all DAPM widgets are instantiated */
1480 snd_soc_dapm_new_widgets(codec);
1481
1389 ret = snd_card_register(codec->card); 1482 ret = snd_card_register(codec->card);
1390 if (ret < 0) { 1483 if (ret < 0) {
1391 printk(KERN_ERR "asoc: failed to register soundcard for %s\n", 1484 printk(KERN_ERR "asoc: failed to register soundcard for %s\n",
@@ -1580,7 +1673,7 @@ int snd_soc_get_enum_double(struct snd_kcontrol *kcontrol,
1580{ 1673{
1581 struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); 1674 struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
1582 struct soc_enum *e = (struct soc_enum *)kcontrol->private_value; 1675 struct soc_enum *e = (struct soc_enum *)kcontrol->private_value;
1583 unsigned short val, bitmask; 1676 unsigned int val, bitmask;
1584 1677
1585 for (bitmask = 1; bitmask < e->max; bitmask <<= 1) 1678 for (bitmask = 1; bitmask < e->max; bitmask <<= 1)
1586 ; 1679 ;
@@ -1609,8 +1702,8 @@ int snd_soc_put_enum_double(struct snd_kcontrol *kcontrol,
1609{ 1702{
1610 struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); 1703 struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
1611 struct soc_enum *e = (struct soc_enum *)kcontrol->private_value; 1704 struct soc_enum *e = (struct soc_enum *)kcontrol->private_value;
1612 unsigned short val; 1705 unsigned int val;
1613 unsigned short mask, bitmask; 1706 unsigned int mask, bitmask;
1614 1707
1615 for (bitmask = 1; bitmask < e->max; bitmask <<= 1) 1708 for (bitmask = 1; bitmask < e->max; bitmask <<= 1)
1616 ; 1709 ;
@@ -1646,7 +1739,7 @@ int snd_soc_get_value_enum_double(struct snd_kcontrol *kcontrol,
1646{ 1739{
1647 struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); 1740 struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
1648 struct soc_enum *e = (struct soc_enum *)kcontrol->private_value; 1741 struct soc_enum *e = (struct soc_enum *)kcontrol->private_value;
1649 unsigned short reg_val, val, mux; 1742 unsigned int reg_val, val, mux;
1650 1743
1651 reg_val = snd_soc_read(codec, e->reg); 1744 reg_val = snd_soc_read(codec, e->reg);
1652 val = (reg_val >> e->shift_l) & e->mask; 1745 val = (reg_val >> e->shift_l) & e->mask;
@@ -1685,8 +1778,8 @@ int snd_soc_put_value_enum_double(struct snd_kcontrol *kcontrol,
1685{ 1778{
1686 struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); 1779 struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
1687 struct soc_enum *e = (struct soc_enum *)kcontrol->private_value; 1780 struct soc_enum *e = (struct soc_enum *)kcontrol->private_value;
1688 unsigned short val; 1781 unsigned int val;
1689 unsigned short mask; 1782 unsigned int mask;
1690 1783
1691 if (ucontrol->value.enumerated.item[0] > e->max - 1) 1784 if (ucontrol->value.enumerated.item[0] > e->max - 1)
1692 return -EINVAL; 1785 return -EINVAL;
@@ -1744,7 +1837,7 @@ int snd_soc_info_volsw_ext(struct snd_kcontrol *kcontrol,
1744{ 1837{
1745 int max = kcontrol->private_value; 1838 int max = kcontrol->private_value;
1746 1839
1747 if (max == 1) 1840 if (max == 1 && !strstr(kcontrol->id.name, " Volume"))
1748 uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN; 1841 uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
1749 else 1842 else
1750 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; 1843 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
@@ -1774,7 +1867,7 @@ int snd_soc_info_volsw(struct snd_kcontrol *kcontrol,
1774 unsigned int shift = mc->shift; 1867 unsigned int shift = mc->shift;
1775 unsigned int rshift = mc->rshift; 1868 unsigned int rshift = mc->rshift;
1776 1869
1777 if (max == 1) 1870 if (max == 1 && !strstr(kcontrol->id.name, " Volume"))
1778 uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN; 1871 uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
1779 else 1872 else
1780 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; 1873 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
@@ -1846,7 +1939,7 @@ int snd_soc_put_volsw(struct snd_kcontrol *kcontrol,
1846 int max = mc->max; 1939 int max = mc->max;
1847 unsigned int mask = (1 << fls(max)) - 1; 1940 unsigned int mask = (1 << fls(max)) - 1;
1848 unsigned int invert = mc->invert; 1941 unsigned int invert = mc->invert;
1849 unsigned short val, val2, val_mask; 1942 unsigned int val, val2, val_mask;
1850 1943
1851 val = (ucontrol->value.integer.value[0] & mask); 1944 val = (ucontrol->value.integer.value[0] & mask);
1852 if (invert) 1945 if (invert)
@@ -1881,7 +1974,7 @@ int snd_soc_info_volsw_2r(struct snd_kcontrol *kcontrol,
1881 (struct soc_mixer_control *)kcontrol->private_value; 1974 (struct soc_mixer_control *)kcontrol->private_value;
1882 int max = mc->max; 1975 int max = mc->max;
1883 1976
1884 if (max == 1) 1977 if (max == 1 && !strstr(kcontrol->id.name, " Volume"))
1885 uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN; 1978 uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
1886 else 1979 else
1887 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; 1980 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
@@ -1912,7 +2005,7 @@ int snd_soc_get_volsw_2r(struct snd_kcontrol *kcontrol,
1912 unsigned int reg2 = mc->rreg; 2005 unsigned int reg2 = mc->rreg;
1913 unsigned int shift = mc->shift; 2006 unsigned int shift = mc->shift;
1914 int max = mc->max; 2007 int max = mc->max;
1915 unsigned int mask = (1<<fls(max))-1; 2008 unsigned int mask = (1 << fls(max)) - 1;
1916 unsigned int invert = mc->invert; 2009 unsigned int invert = mc->invert;
1917 2010
1918 ucontrol->value.integer.value[0] = 2011 ucontrol->value.integer.value[0] =
@@ -1952,7 +2045,7 @@ int snd_soc_put_volsw_2r(struct snd_kcontrol *kcontrol,
1952 unsigned int mask = (1 << fls(max)) - 1; 2045 unsigned int mask = (1 << fls(max)) - 1;
1953 unsigned int invert = mc->invert; 2046 unsigned int invert = mc->invert;
1954 int err; 2047 int err;
1955 unsigned short val, val2, val_mask; 2048 unsigned int val, val2, val_mask;
1956 2049
1957 val_mask = mask << shift; 2050 val_mask = mask << shift;
1958 val = (ucontrol->value.integer.value[0] & mask); 2051 val = (ucontrol->value.integer.value[0] & mask);
@@ -2044,7 +2137,7 @@ int snd_soc_put_volsw_s8(struct snd_kcontrol *kcontrol,
2044 struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); 2137 struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
2045 unsigned int reg = mc->reg; 2138 unsigned int reg = mc->reg;
2046 int min = mc->min; 2139 int min = mc->min;
2047 unsigned short val; 2140 unsigned int val;
2048 2141
2049 val = (ucontrol->value.integer.value[0]+min) & 0xff; 2142 val = (ucontrol->value.integer.value[0]+min) & 0xff;
2050 val |= ((ucontrol->value.integer.value[1]+min) & 0xff) << 8; 2143 val |= ((ucontrol->value.integer.value[1]+min) & 0xff) << 8;
@@ -2065,7 +2158,7 @@ EXPORT_SYMBOL_GPL(snd_soc_put_volsw_s8);
2065int snd_soc_dai_set_sysclk(struct snd_soc_dai *dai, int clk_id, 2158int snd_soc_dai_set_sysclk(struct snd_soc_dai *dai, int clk_id,
2066 unsigned int freq, int dir) 2159 unsigned int freq, int dir)
2067{ 2160{
2068 if (dai->ops->set_sysclk) 2161 if (dai->ops && dai->ops->set_sysclk)
2069 return dai->ops->set_sysclk(dai, clk_id, freq, dir); 2162 return dai->ops->set_sysclk(dai, clk_id, freq, dir);
2070 else 2163 else
2071 return -EINVAL; 2164 return -EINVAL;
@@ -2085,7 +2178,7 @@ EXPORT_SYMBOL_GPL(snd_soc_dai_set_sysclk);
2085int snd_soc_dai_set_clkdiv(struct snd_soc_dai *dai, 2178int snd_soc_dai_set_clkdiv(struct snd_soc_dai *dai,
2086 int div_id, int div) 2179 int div_id, int div)
2087{ 2180{
2088 if (dai->ops->set_clkdiv) 2181 if (dai->ops && dai->ops->set_clkdiv)
2089 return dai->ops->set_clkdiv(dai, div_id, div); 2182 return dai->ops->set_clkdiv(dai, div_id, div);
2090 else 2183 else
2091 return -EINVAL; 2184 return -EINVAL;
@@ -2104,7 +2197,7 @@ EXPORT_SYMBOL_GPL(snd_soc_dai_set_clkdiv);
2104int snd_soc_dai_set_pll(struct snd_soc_dai *dai, 2197int snd_soc_dai_set_pll(struct snd_soc_dai *dai,
2105 int pll_id, unsigned int freq_in, unsigned int freq_out) 2198 int pll_id, unsigned int freq_in, unsigned int freq_out)
2106{ 2199{
2107 if (dai->ops->set_pll) 2200 if (dai->ops && dai->ops->set_pll)
2108 return dai->ops->set_pll(dai, pll_id, freq_in, freq_out); 2201 return dai->ops->set_pll(dai, pll_id, freq_in, freq_out);
2109 else 2202 else
2110 return -EINVAL; 2203 return -EINVAL;
@@ -2120,7 +2213,7 @@ EXPORT_SYMBOL_GPL(snd_soc_dai_set_pll);
2120 */ 2213 */
2121int snd_soc_dai_set_fmt(struct snd_soc_dai *dai, unsigned int fmt) 2214int snd_soc_dai_set_fmt(struct snd_soc_dai *dai, unsigned int fmt)
2122{ 2215{
2123 if (dai->ops->set_fmt) 2216 if (dai->ops && dai->ops->set_fmt)
2124 return dai->ops->set_fmt(dai, fmt); 2217 return dai->ops->set_fmt(dai, fmt);
2125 else 2218 else
2126 return -EINVAL; 2219 return -EINVAL;
@@ -2130,17 +2223,20 @@ EXPORT_SYMBOL_GPL(snd_soc_dai_set_fmt);
2130/** 2223/**
2131 * snd_soc_dai_set_tdm_slot - configure DAI TDM. 2224 * snd_soc_dai_set_tdm_slot - configure DAI TDM.
2132 * @dai: DAI 2225 * @dai: DAI
2133 * @mask: DAI specific mask representing used slots. 2226 * @tx_mask: bitmask representing active TX slots.
2227 * @rx_mask: bitmask representing active RX slots.
2134 * @slots: Number of slots in use. 2228 * @slots: Number of slots in use.
2229 * @slot_width: Width in bits for each slot.
2135 * 2230 *
2136 * Configures a DAI for TDM operation. Both mask and slots are codec and DAI 2231 * Configures a DAI for TDM operation. Both mask and slots are codec and DAI
2137 * specific. 2232 * specific.
2138 */ 2233 */
2139int snd_soc_dai_set_tdm_slot(struct snd_soc_dai *dai, 2234int snd_soc_dai_set_tdm_slot(struct snd_soc_dai *dai,
2140 unsigned int mask, int slots) 2235 unsigned int tx_mask, unsigned int rx_mask, int slots, int slot_width)
2141{ 2236{
2142 if (dai->ops->set_sysclk) 2237 if (dai->ops && dai->ops->set_tdm_slot)
2143 return dai->ops->set_tdm_slot(dai, mask, slots); 2238 return dai->ops->set_tdm_slot(dai, tx_mask, rx_mask,
2239 slots, slot_width);
2144 else 2240 else
2145 return -EINVAL; 2241 return -EINVAL;
2146} 2242}
@@ -2155,7 +2251,7 @@ EXPORT_SYMBOL_GPL(snd_soc_dai_set_tdm_slot);
2155 */ 2251 */
2156int snd_soc_dai_set_tristate(struct snd_soc_dai *dai, int tristate) 2252int snd_soc_dai_set_tristate(struct snd_soc_dai *dai, int tristate)
2157{ 2253{
2158 if (dai->ops->set_sysclk) 2254 if (dai->ops && dai->ops->set_tristate)
2159 return dai->ops->set_tristate(dai, tristate); 2255 return dai->ops->set_tristate(dai, tristate);
2160 else 2256 else
2161 return -EINVAL; 2257 return -EINVAL;
@@ -2171,7 +2267,7 @@ EXPORT_SYMBOL_GPL(snd_soc_dai_set_tristate);
2171 */ 2267 */
2172int snd_soc_dai_digital_mute(struct snd_soc_dai *dai, int mute) 2268int snd_soc_dai_digital_mute(struct snd_soc_dai *dai, int mute)
2173{ 2269{
2174 if (dai->ops->digital_mute) 2270 if (dai->ops && dai->ops->digital_mute)
2175 return dai->ops->digital_mute(dai, mute); 2271 return dai->ops->digital_mute(dai, mute);
2176 else 2272 else
2177 return -EINVAL; 2273 return -EINVAL;
@@ -2352,6 +2448,39 @@ void snd_soc_unregister_platform(struct snd_soc_platform *platform)
2352} 2448}
2353EXPORT_SYMBOL_GPL(snd_soc_unregister_platform); 2449EXPORT_SYMBOL_GPL(snd_soc_unregister_platform);
2354 2450
2451static u64 codec_format_map[] = {
2452 SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S16_BE,
2453 SNDRV_PCM_FMTBIT_U16_LE | SNDRV_PCM_FMTBIT_U16_BE,
2454 SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S24_BE,
2455 SNDRV_PCM_FMTBIT_U24_LE | SNDRV_PCM_FMTBIT_U24_BE,
2456 SNDRV_PCM_FMTBIT_S32_LE | SNDRV_PCM_FMTBIT_S32_BE,
2457 SNDRV_PCM_FMTBIT_U32_LE | SNDRV_PCM_FMTBIT_U32_BE,
2458 SNDRV_PCM_FMTBIT_S24_3LE | SNDRV_PCM_FMTBIT_U24_3BE,
2459 SNDRV_PCM_FMTBIT_U24_3LE | SNDRV_PCM_FMTBIT_U24_3BE,
2460 SNDRV_PCM_FMTBIT_S20_3LE | SNDRV_PCM_FMTBIT_S20_3BE,
2461 SNDRV_PCM_FMTBIT_U20_3LE | SNDRV_PCM_FMTBIT_U20_3BE,
2462 SNDRV_PCM_FMTBIT_S18_3LE | SNDRV_PCM_FMTBIT_S18_3BE,
2463 SNDRV_PCM_FMTBIT_U18_3LE | SNDRV_PCM_FMTBIT_U18_3BE,
2464 SNDRV_PCM_FMTBIT_FLOAT_LE | SNDRV_PCM_FMTBIT_FLOAT_BE,
2465 SNDRV_PCM_FMTBIT_FLOAT64_LE | SNDRV_PCM_FMTBIT_FLOAT64_BE,
2466 SNDRV_PCM_FMTBIT_IEC958_SUBFRAME_LE
2467 | SNDRV_PCM_FMTBIT_IEC958_SUBFRAME_BE,
2468};
2469
2470/* Fix up the DAI formats for endianness: codecs don't actually see
2471 * the endianness of the data but we're using the CPU format
2472 * definitions which do need to include endianness so we ensure that
2473 * codec DAIs always have both big and little endian variants set.
2474 */
2475static void fixup_codec_formats(struct snd_soc_pcm_stream *stream)
2476{
2477 int i;
2478
2479 for (i = 0; i < ARRAY_SIZE(codec_format_map); i++)
2480 if (stream->formats & codec_format_map[i])
2481 stream->formats |= codec_format_map[i];
2482}
2483
2355/** 2484/**
2356 * snd_soc_register_codec - Register a codec with the ASoC core 2485 * snd_soc_register_codec - Register a codec with the ASoC core
2357 * 2486 *
@@ -2359,6 +2488,8 @@ EXPORT_SYMBOL_GPL(snd_soc_unregister_platform);
2359 */ 2488 */
2360int snd_soc_register_codec(struct snd_soc_codec *codec) 2489int snd_soc_register_codec(struct snd_soc_codec *codec)
2361{ 2490{
2491 int i;
2492
2362 if (!codec->name) 2493 if (!codec->name)
2363 return -EINVAL; 2494 return -EINVAL;
2364 2495
@@ -2368,6 +2499,11 @@ int snd_soc_register_codec(struct snd_soc_codec *codec)
2368 2499
2369 INIT_LIST_HEAD(&codec->list); 2500 INIT_LIST_HEAD(&codec->list);
2370 2501
2502 for (i = 0; i < codec->num_dai; i++) {
2503 fixup_codec_formats(&codec->dai[i].playback);
2504 fixup_codec_formats(&codec->dai[i].capture);
2505 }
2506
2371 mutex_lock(&client_mutex); 2507 mutex_lock(&client_mutex);
2372 list_add(&codec->list, &codec_list); 2508 list_add(&codec->list, &codec_list);
2373 snd_soc_instantiate_cards(); 2509 snd_soc_instantiate_cards();
diff --git a/sound/soc/soc-dapm.c b/sound/soc/soc-dapm.c
index 735903a74675..c68c204a48ad 100644
--- a/sound/soc/soc-dapm.c
+++ b/sound/soc/soc-dapm.c
@@ -12,7 +12,7 @@
12 * Features: 12 * Features:
13 * o Changes power status of internal codec blocks depending on the 13 * o Changes power status of internal codec blocks depending on the
14 * dynamic configuration of codec internal audio paths and active 14 * dynamic configuration of codec internal audio paths and active
15 * DAC's/ADC's. 15 * DACs/ADCs.
16 * o Platform power domain - can support external components i.e. amps and 16 * o Platform power domain - can support external components i.e. amps and
17 * mic/meadphone insertion events. 17 * mic/meadphone insertion events.
18 * o Automatic Mic Bias support 18 * o Automatic Mic Bias support
@@ -52,23 +52,39 @@
52 52
53/* dapm power sequences - make this per codec in the future */ 53/* dapm power sequences - make this per codec in the future */
54static int dapm_up_seq[] = { 54static int dapm_up_seq[] = {
55 snd_soc_dapm_pre, snd_soc_dapm_micbias, snd_soc_dapm_mic, 55 [snd_soc_dapm_pre] = 0,
56 snd_soc_dapm_mux, snd_soc_dapm_value_mux, snd_soc_dapm_dac, 56 [snd_soc_dapm_supply] = 1,
57 snd_soc_dapm_mixer, snd_soc_dapm_mixer_named_ctl, snd_soc_dapm_pga, 57 [snd_soc_dapm_micbias] = 2,
58 snd_soc_dapm_adc, snd_soc_dapm_hp, snd_soc_dapm_spk, snd_soc_dapm_post 58 [snd_soc_dapm_mic] = 3,
59 [snd_soc_dapm_mux] = 4,
60 [snd_soc_dapm_value_mux] = 4,
61 [snd_soc_dapm_dac] = 5,
62 [snd_soc_dapm_mixer] = 6,
63 [snd_soc_dapm_mixer_named_ctl] = 6,
64 [snd_soc_dapm_pga] = 7,
65 [snd_soc_dapm_adc] = 8,
66 [snd_soc_dapm_hp] = 9,
67 [snd_soc_dapm_spk] = 10,
68 [snd_soc_dapm_post] = 11,
59}; 69};
60 70
61static int dapm_down_seq[] = { 71static int dapm_down_seq[] = {
62 snd_soc_dapm_pre, snd_soc_dapm_adc, snd_soc_dapm_hp, snd_soc_dapm_spk, 72 [snd_soc_dapm_pre] = 0,
63 snd_soc_dapm_pga, snd_soc_dapm_mixer_named_ctl, snd_soc_dapm_mixer, 73 [snd_soc_dapm_adc] = 1,
64 snd_soc_dapm_dac, snd_soc_dapm_mic, snd_soc_dapm_micbias, 74 [snd_soc_dapm_hp] = 2,
65 snd_soc_dapm_mux, snd_soc_dapm_value_mux, snd_soc_dapm_post 75 [snd_soc_dapm_spk] = 3,
76 [snd_soc_dapm_pga] = 4,
77 [snd_soc_dapm_mixer_named_ctl] = 5,
78 [snd_soc_dapm_mixer] = 5,
79 [snd_soc_dapm_dac] = 6,
80 [snd_soc_dapm_mic] = 7,
81 [snd_soc_dapm_micbias] = 8,
82 [snd_soc_dapm_mux] = 9,
83 [snd_soc_dapm_value_mux] = 9,
84 [snd_soc_dapm_supply] = 10,
85 [snd_soc_dapm_post] = 11,
66}; 86};
67 87
68static int dapm_status = 1;
69module_param(dapm_status, int, 0);
70MODULE_PARM_DESC(dapm_status, "enable DPM sysfs entries");
71
72static void pop_wait(u32 pop_time) 88static void pop_wait(u32 pop_time)
73{ 89{
74 if (pop_time) 90 if (pop_time)
@@ -96,6 +112,48 @@ static inline struct snd_soc_dapm_widget *dapm_cnew_widget(
96 return kmemdup(_widget, sizeof(*_widget), GFP_KERNEL); 112 return kmemdup(_widget, sizeof(*_widget), GFP_KERNEL);
97} 113}
98 114
115/**
116 * snd_soc_dapm_set_bias_level - set the bias level for the system
117 * @socdev: audio device
118 * @level: level to configure
119 *
120 * Configure the bias (power) levels for the SoC audio device.
121 *
122 * Returns 0 for success else error.
123 */
124static int snd_soc_dapm_set_bias_level(struct snd_soc_device *socdev,
125 enum snd_soc_bias_level level)
126{
127 struct snd_soc_card *card = socdev->card;
128 struct snd_soc_codec *codec = socdev->card->codec;
129 int ret = 0;
130
131 switch (level) {
132 case SND_SOC_BIAS_ON:
133 dev_dbg(socdev->dev, "Setting full bias\n");
134 break;
135 case SND_SOC_BIAS_PREPARE:
136 dev_dbg(socdev->dev, "Setting bias prepare\n");
137 break;
138 case SND_SOC_BIAS_STANDBY:
139 dev_dbg(socdev->dev, "Setting standby bias\n");
140 break;
141 case SND_SOC_BIAS_OFF:
142 dev_dbg(socdev->dev, "Setting bias off\n");
143 break;
144 default:
145 dev_err(socdev->dev, "Setting invalid bias %d\n", level);
146 return -EINVAL;
147 }
148
149 if (card->set_bias_level)
150 ret = card->set_bias_level(card, level);
151 if (ret == 0 && codec->set_bias_level)
152 ret = codec->set_bias_level(codec, level);
153
154 return ret;
155}
156
99/* set up initial codec paths */ 157/* set up initial codec paths */
100static void dapm_set_path_status(struct snd_soc_dapm_widget *w, 158static void dapm_set_path_status(struct snd_soc_dapm_widget *w,
101 struct snd_soc_dapm_path *p, int i) 159 struct snd_soc_dapm_path *p, int i)
@@ -165,6 +223,7 @@ static void dapm_set_path_status(struct snd_soc_dapm_widget *w,
165 case snd_soc_dapm_dac: 223 case snd_soc_dapm_dac:
166 case snd_soc_dapm_micbias: 224 case snd_soc_dapm_micbias:
167 case snd_soc_dapm_vmid: 225 case snd_soc_dapm_vmid:
226 case snd_soc_dapm_supply:
168 p->connect = 1; 227 p->connect = 1;
169 break; 228 break;
170 /* does effect routing - dynamically connected */ 229 /* does effect routing - dynamically connected */
@@ -179,7 +238,7 @@ static void dapm_set_path_status(struct snd_soc_dapm_widget *w,
179 } 238 }
180} 239}
181 240
182/* connect mux widget to it's interconnecting audio paths */ 241/* connect mux widget to its interconnecting audio paths */
183static int dapm_connect_mux(struct snd_soc_codec *codec, 242static int dapm_connect_mux(struct snd_soc_codec *codec,
184 struct snd_soc_dapm_widget *src, struct snd_soc_dapm_widget *dest, 243 struct snd_soc_dapm_widget *src, struct snd_soc_dapm_widget *dest,
185 struct snd_soc_dapm_path *path, const char *control_name, 244 struct snd_soc_dapm_path *path, const char *control_name,
@@ -202,7 +261,7 @@ static int dapm_connect_mux(struct snd_soc_codec *codec,
202 return -ENODEV; 261 return -ENODEV;
203} 262}
204 263
205/* connect mixer widget to it's interconnecting audio paths */ 264/* connect mixer widget to its interconnecting audio paths */
206static int dapm_connect_mixer(struct snd_soc_codec *codec, 265static int dapm_connect_mixer(struct snd_soc_codec *codec,
207 struct snd_soc_dapm_widget *src, struct snd_soc_dapm_widget *dest, 266 struct snd_soc_dapm_widget *src, struct snd_soc_dapm_widget *dest,
208 struct snd_soc_dapm_path *path, const char *control_name) 267 struct snd_soc_dapm_path *path, const char *control_name)
@@ -227,7 +286,7 @@ static int dapm_connect_mixer(struct snd_soc_codec *codec,
227static int dapm_update_bits(struct snd_soc_dapm_widget *widget) 286static int dapm_update_bits(struct snd_soc_dapm_widget *widget)
228{ 287{
229 int change, power; 288 int change, power;
230 unsigned short old, new; 289 unsigned int old, new;
231 struct snd_soc_codec *codec = widget->codec; 290 struct snd_soc_codec *codec = widget->codec;
232 291
233 /* check for valid widgets */ 292 /* check for valid widgets */
@@ -357,8 +416,9 @@ static int dapm_new_mixer(struct snd_soc_codec *codec,
357 path->long_name); 416 path->long_name);
358 ret = snd_ctl_add(codec->card, path->kcontrol); 417 ret = snd_ctl_add(codec->card, path->kcontrol);
359 if (ret < 0) { 418 if (ret < 0) {
360 printk(KERN_ERR "asoc: failed to add dapm kcontrol %s\n", 419 printk(KERN_ERR "asoc: failed to add dapm kcontrol %s: %d\n",
361 path->long_name); 420 path->long_name,
421 ret);
362 kfree(path->long_name); 422 kfree(path->long_name);
363 path->long_name = NULL; 423 path->long_name = NULL;
364 return ret; 424 return ret;
@@ -434,6 +494,9 @@ static int is_connected_output_ep(struct snd_soc_dapm_widget *widget)
434 struct snd_soc_dapm_path *path; 494 struct snd_soc_dapm_path *path;
435 int con = 0; 495 int con = 0;
436 496
497 if (widget->id == snd_soc_dapm_supply)
498 return 0;
499
437 if (widget->id == snd_soc_dapm_adc && widget->active) 500 if (widget->id == snd_soc_dapm_adc && widget->active)
438 return 1; 501 return 1;
439 502
@@ -470,6 +533,9 @@ static int is_connected_input_ep(struct snd_soc_dapm_widget *widget)
470 struct snd_soc_dapm_path *path; 533 struct snd_soc_dapm_path *path;
471 int con = 0; 534 int con = 0;
472 535
536 if (widget->id == snd_soc_dapm_supply)
537 return 0;
538
473 /* active stream ? */ 539 /* active stream ? */
474 if (widget->id == snd_soc_dapm_dac && widget->active) 540 if (widget->id == snd_soc_dapm_dac && widget->active)
475 return 1; 541 return 1;
@@ -521,84 +587,12 @@ int dapm_reg_event(struct snd_soc_dapm_widget *w,
521} 587}
522EXPORT_SYMBOL_GPL(dapm_reg_event); 588EXPORT_SYMBOL_GPL(dapm_reg_event);
523 589
524/* 590/* Standard power change method, used to apply power changes to most
525 * Scan a single DAPM widget for a complete audio path and update the 591 * widgets.
526 * power status appropriately.
527 */ 592 */
528static int dapm_power_widget(struct snd_soc_codec *codec, int event, 593static int dapm_generic_apply_power(struct snd_soc_dapm_widget *w)
529 struct snd_soc_dapm_widget *w)
530{ 594{
531 int in, out, power_change, power, ret; 595 int ret;
532
533 /* vmid - no action */
534 if (w->id == snd_soc_dapm_vmid)
535 return 0;
536
537 /* active ADC */
538 if (w->id == snd_soc_dapm_adc && w->active) {
539 in = is_connected_input_ep(w);
540 dapm_clear_walk(w->codec);
541 w->power = (in != 0) ? 1 : 0;
542 dapm_update_bits(w);
543 return 0;
544 }
545
546 /* active DAC */
547 if (w->id == snd_soc_dapm_dac && w->active) {
548 out = is_connected_output_ep(w);
549 dapm_clear_walk(w->codec);
550 w->power = (out != 0) ? 1 : 0;
551 dapm_update_bits(w);
552 return 0;
553 }
554
555 /* pre and post event widgets */
556 if (w->id == snd_soc_dapm_pre) {
557 if (!w->event)
558 return 0;
559
560 if (event == SND_SOC_DAPM_STREAM_START) {
561 ret = w->event(w,
562 NULL, SND_SOC_DAPM_PRE_PMU);
563 if (ret < 0)
564 return ret;
565 } else if (event == SND_SOC_DAPM_STREAM_STOP) {
566 ret = w->event(w,
567 NULL, SND_SOC_DAPM_PRE_PMD);
568 if (ret < 0)
569 return ret;
570 }
571 return 0;
572 }
573 if (w->id == snd_soc_dapm_post) {
574 if (!w->event)
575 return 0;
576
577 if (event == SND_SOC_DAPM_STREAM_START) {
578 ret = w->event(w,
579 NULL, SND_SOC_DAPM_POST_PMU);
580 if (ret < 0)
581 return ret;
582 } else if (event == SND_SOC_DAPM_STREAM_STOP) {
583 ret = w->event(w,
584 NULL, SND_SOC_DAPM_POST_PMD);
585 if (ret < 0)
586 return ret;
587 }
588 return 0;
589 }
590
591 /* all other widgets */
592 in = is_connected_input_ep(w);
593 dapm_clear_walk(w->codec);
594 out = is_connected_output_ep(w);
595 dapm_clear_walk(w->codec);
596 power = (out != 0 && in != 0) ? 1 : 0;
597 power_change = (w->power == power) ? 0 : 1;
598 w->power = power;
599
600 if (!power_change)
601 return 0;
602 596
603 /* call any power change event handlers */ 597 /* call any power change event handlers */
604 if (w->event) 598 if (w->event)
@@ -607,7 +601,7 @@ static int dapm_power_widget(struct snd_soc_codec *codec, int event,
607 w->name, w->event_flags); 601 w->name, w->event_flags);
608 602
609 /* power up pre event */ 603 /* power up pre event */
610 if (power && w->event && 604 if (w->power && w->event &&
611 (w->event_flags & SND_SOC_DAPM_PRE_PMU)) { 605 (w->event_flags & SND_SOC_DAPM_PRE_PMU)) {
612 ret = w->event(w, NULL, SND_SOC_DAPM_PRE_PMU); 606 ret = w->event(w, NULL, SND_SOC_DAPM_PRE_PMU);
613 if (ret < 0) 607 if (ret < 0)
@@ -615,7 +609,7 @@ static int dapm_power_widget(struct snd_soc_codec *codec, int event,
615 } 609 }
616 610
617 /* power down pre event */ 611 /* power down pre event */
618 if (!power && w->event && 612 if (!w->power && w->event &&
619 (w->event_flags & SND_SOC_DAPM_PRE_PMD)) { 613 (w->event_flags & SND_SOC_DAPM_PRE_PMD)) {
620 ret = w->event(w, NULL, SND_SOC_DAPM_PRE_PMD); 614 ret = w->event(w, NULL, SND_SOC_DAPM_PRE_PMD);
621 if (ret < 0) 615 if (ret < 0)
@@ -623,17 +617,17 @@ static int dapm_power_widget(struct snd_soc_codec *codec, int event,
623 } 617 }
624 618
625 /* Lower PGA volume to reduce pops */ 619 /* Lower PGA volume to reduce pops */
626 if (w->id == snd_soc_dapm_pga && !power) 620 if (w->id == snd_soc_dapm_pga && !w->power)
627 dapm_set_pga(w, power); 621 dapm_set_pga(w, w->power);
628 622
629 dapm_update_bits(w); 623 dapm_update_bits(w);
630 624
631 /* Raise PGA volume to reduce pops */ 625 /* Raise PGA volume to reduce pops */
632 if (w->id == snd_soc_dapm_pga && power) 626 if (w->id == snd_soc_dapm_pga && w->power)
633 dapm_set_pga(w, power); 627 dapm_set_pga(w, w->power);
634 628
635 /* power up post event */ 629 /* power up post event */
636 if (power && w->event && 630 if (w->power && w->event &&
637 (w->event_flags & SND_SOC_DAPM_POST_PMU)) { 631 (w->event_flags & SND_SOC_DAPM_POST_PMU)) {
638 ret = w->event(w, 632 ret = w->event(w,
639 NULL, SND_SOC_DAPM_POST_PMU); 633 NULL, SND_SOC_DAPM_POST_PMU);
@@ -642,7 +636,7 @@ static int dapm_power_widget(struct snd_soc_codec *codec, int event,
642 } 636 }
643 637
644 /* power down post event */ 638 /* power down post event */
645 if (!power && w->event && 639 if (!w->power && w->event &&
646 (w->event_flags & SND_SOC_DAPM_POST_PMD)) { 640 (w->event_flags & SND_SOC_DAPM_POST_PMD)) {
647 ret = w->event(w, NULL, SND_SOC_DAPM_POST_PMD); 641 ret = w->event(w, NULL, SND_SOC_DAPM_POST_PMD);
648 if (ret < 0) 642 if (ret < 0)
@@ -652,6 +646,274 @@ static int dapm_power_widget(struct snd_soc_codec *codec, int event,
652 return 0; 646 return 0;
653} 647}
654 648
649/* Generic check to see if a widget should be powered.
650 */
651static int dapm_generic_check_power(struct snd_soc_dapm_widget *w)
652{
653 int in, out;
654
655 in = is_connected_input_ep(w);
656 dapm_clear_walk(w->codec);
657 out = is_connected_output_ep(w);
658 dapm_clear_walk(w->codec);
659 return out != 0 && in != 0;
660}
661
662/* Check to see if an ADC has power */
663static int dapm_adc_check_power(struct snd_soc_dapm_widget *w)
664{
665 int in;
666
667 if (w->active) {
668 in = is_connected_input_ep(w);
669 dapm_clear_walk(w->codec);
670 return in != 0;
671 } else {
672 return dapm_generic_check_power(w);
673 }
674}
675
676/* Check to see if a DAC has power */
677static int dapm_dac_check_power(struct snd_soc_dapm_widget *w)
678{
679 int out;
680
681 if (w->active) {
682 out = is_connected_output_ep(w);
683 dapm_clear_walk(w->codec);
684 return out != 0;
685 } else {
686 return dapm_generic_check_power(w);
687 }
688}
689
690/* Check to see if a power supply is needed */
691static int dapm_supply_check_power(struct snd_soc_dapm_widget *w)
692{
693 struct snd_soc_dapm_path *path;
694 int power = 0;
695
696 /* Check if one of our outputs is connected */
697 list_for_each_entry(path, &w->sinks, list_source) {
698 if (path->sink && path->sink->power_check &&
699 path->sink->power_check(path->sink)) {
700 power = 1;
701 break;
702 }
703 }
704
705 dapm_clear_walk(w->codec);
706
707 return power;
708}
709
710static int dapm_seq_compare(struct snd_soc_dapm_widget *a,
711 struct snd_soc_dapm_widget *b,
712 int sort[])
713{
714 if (sort[a->id] != sort[b->id])
715 return sort[a->id] - sort[b->id];
716 if (a->reg != b->reg)
717 return a->reg - b->reg;
718
719 return 0;
720}
721
722/* Insert a widget in order into a DAPM power sequence. */
723static void dapm_seq_insert(struct snd_soc_dapm_widget *new_widget,
724 struct list_head *list,
725 int sort[])
726{
727 struct snd_soc_dapm_widget *w;
728
729 list_for_each_entry(w, list, power_list)
730 if (dapm_seq_compare(new_widget, w, sort) < 0) {
731 list_add_tail(&new_widget->power_list, &w->power_list);
732 return;
733 }
734
735 list_add_tail(&new_widget->power_list, list);
736}
737
738/* Apply the coalesced changes from a DAPM sequence */
739static void dapm_seq_run_coalesced(struct snd_soc_codec *codec,
740 struct list_head *pending)
741{
742 struct snd_soc_dapm_widget *w;
743 int reg, power, ret;
744 unsigned int value = 0;
745 unsigned int mask = 0;
746 unsigned int cur_mask;
747
748 reg = list_first_entry(pending, struct snd_soc_dapm_widget,
749 power_list)->reg;
750
751 list_for_each_entry(w, pending, power_list) {
752 cur_mask = 1 << w->shift;
753 BUG_ON(reg != w->reg);
754
755 if (w->invert)
756 power = !w->power;
757 else
758 power = w->power;
759
760 mask |= cur_mask;
761 if (power)
762 value |= cur_mask;
763
764 pop_dbg(codec->pop_time,
765 "pop test : Queue %s: reg=0x%x, 0x%x/0x%x\n",
766 w->name, reg, value, mask);
767
768 /* power up pre event */
769 if (w->power && w->event &&
770 (w->event_flags & SND_SOC_DAPM_PRE_PMU)) {
771 pop_dbg(codec->pop_time, "pop test : %s PRE_PMU\n",
772 w->name);
773 ret = w->event(w, NULL, SND_SOC_DAPM_PRE_PMU);
774 if (ret < 0)
775 pr_err("%s: pre event failed: %d\n",
776 w->name, ret);
777 }
778
779 /* power down pre event */
780 if (!w->power && w->event &&
781 (w->event_flags & SND_SOC_DAPM_PRE_PMD)) {
782 pop_dbg(codec->pop_time, "pop test : %s PRE_PMD\n",
783 w->name);
784 ret = w->event(w, NULL, SND_SOC_DAPM_PRE_PMD);
785 if (ret < 0)
786 pr_err("%s: pre event failed: %d\n",
787 w->name, ret);
788 }
789
790 /* Lower PGA volume to reduce pops */
791 if (w->id == snd_soc_dapm_pga && !w->power)
792 dapm_set_pga(w, w->power);
793 }
794
795 if (reg >= 0) {
796 pop_dbg(codec->pop_time,
797 "pop test : Applying 0x%x/0x%x to %x in %dms\n",
798 value, mask, reg, codec->pop_time);
799 pop_wait(codec->pop_time);
800 snd_soc_update_bits(codec, reg, mask, value);
801 }
802
803 list_for_each_entry(w, pending, power_list) {
804 /* Raise PGA volume to reduce pops */
805 if (w->id == snd_soc_dapm_pga && w->power)
806 dapm_set_pga(w, w->power);
807
808 /* power up post event */
809 if (w->power && w->event &&
810 (w->event_flags & SND_SOC_DAPM_POST_PMU)) {
811 pop_dbg(codec->pop_time, "pop test : %s POST_PMU\n",
812 w->name);
813 ret = w->event(w,
814 NULL, SND_SOC_DAPM_POST_PMU);
815 if (ret < 0)
816 pr_err("%s: post event failed: %d\n",
817 w->name, ret);
818 }
819
820 /* power down post event */
821 if (!w->power && w->event &&
822 (w->event_flags & SND_SOC_DAPM_POST_PMD)) {
823 pop_dbg(codec->pop_time, "pop test : %s POST_PMD\n",
824 w->name);
825 ret = w->event(w, NULL, SND_SOC_DAPM_POST_PMD);
826 if (ret < 0)
827 pr_err("%s: post event failed: %d\n",
828 w->name, ret);
829 }
830 }
831}
832
833/* Apply a DAPM power sequence.
834 *
835 * We walk over a pre-sorted list of widgets to apply power to. In
836 * order to minimise the number of writes to the device required
837 * multiple widgets will be updated in a single write where possible.
838 * Currently anything that requires more than a single write is not
839 * handled.
840 */
841static void dapm_seq_run(struct snd_soc_codec *codec, struct list_head *list,
842 int event, int sort[])
843{
844 struct snd_soc_dapm_widget *w, *n;
845 LIST_HEAD(pending);
846 int cur_sort = -1;
847 int cur_reg = SND_SOC_NOPM;
848 int ret;
849
850 list_for_each_entry_safe(w, n, list, power_list) {
851 ret = 0;
852
853 /* Do we need to apply any queued changes? */
854 if (sort[w->id] != cur_sort || w->reg != cur_reg) {
855 if (!list_empty(&pending))
856 dapm_seq_run_coalesced(codec, &pending);
857
858 INIT_LIST_HEAD(&pending);
859 cur_sort = -1;
860 cur_reg = SND_SOC_NOPM;
861 }
862
863 switch (w->id) {
864 case snd_soc_dapm_pre:
865 if (!w->event)
866 list_for_each_entry_safe_continue(w, n, list,
867 power_list);
868
869 if (event == SND_SOC_DAPM_STREAM_START)
870 ret = w->event(w,
871 NULL, SND_SOC_DAPM_PRE_PMU);
872 else if (event == SND_SOC_DAPM_STREAM_STOP)
873 ret = w->event(w,
874 NULL, SND_SOC_DAPM_PRE_PMD);
875 break;
876
877 case snd_soc_dapm_post:
878 if (!w->event)
879 list_for_each_entry_safe_continue(w, n, list,
880 power_list);
881
882 if (event == SND_SOC_DAPM_STREAM_START)
883 ret = w->event(w,
884 NULL, SND_SOC_DAPM_POST_PMU);
885 else if (event == SND_SOC_DAPM_STREAM_STOP)
886 ret = w->event(w,
887 NULL, SND_SOC_DAPM_POST_PMD);
888 break;
889
890 case snd_soc_dapm_input:
891 case snd_soc_dapm_output:
892 case snd_soc_dapm_hp:
893 case snd_soc_dapm_mic:
894 case snd_soc_dapm_line:
895 case snd_soc_dapm_spk:
896 /* No register support currently */
897 ret = dapm_generic_apply_power(w);
898 break;
899
900 default:
901 /* Queue it up for application */
902 cur_sort = sort[w->id];
903 cur_reg = w->reg;
904 list_move(&w->power_list, &pending);
905 break;
906 }
907
908 if (ret < 0)
909 pr_err("Failed to apply widget power: %d\n",
910 ret);
911 }
912
913 if (!list_empty(&pending))
914 dapm_seq_run_coalesced(codec, &pending);
915}
916
655/* 917/*
656 * Scan each dapm widget for complete audio path. 918 * Scan each dapm widget for complete audio path.
657 * A complete path is a route that has valid endpoints i.e.:- 919 * A complete path is a route that has valid endpoints i.e.:-
@@ -663,31 +925,81 @@ static int dapm_power_widget(struct snd_soc_codec *codec, int event,
663 */ 925 */
664static int dapm_power_widgets(struct snd_soc_codec *codec, int event) 926static int dapm_power_widgets(struct snd_soc_codec *codec, int event)
665{ 927{
928 struct snd_soc_device *socdev = codec->socdev;
666 struct snd_soc_dapm_widget *w; 929 struct snd_soc_dapm_widget *w;
667 int i, c = 1, *seq = NULL, ret = 0; 930 LIST_HEAD(up_list);
668 931 LIST_HEAD(down_list);
669 /* do we have a sequenced stream event */ 932 int ret = 0;
670 if (event == SND_SOC_DAPM_STREAM_START) { 933 int power;
671 c = ARRAY_SIZE(dapm_up_seq); 934 int sys_power = 0;
672 seq = dapm_up_seq; 935
673 } else if (event == SND_SOC_DAPM_STREAM_STOP) { 936 /* Check which widgets we need to power and store them in
674 c = ARRAY_SIZE(dapm_down_seq); 937 * lists indicating if they should be powered up or down.
675 seq = dapm_down_seq; 938 */
676 } 939 list_for_each_entry(w, &codec->dapm_widgets, list) {
940 switch (w->id) {
941 case snd_soc_dapm_pre:
942 dapm_seq_insert(w, &down_list, dapm_down_seq);
943 break;
944 case snd_soc_dapm_post:
945 dapm_seq_insert(w, &up_list, dapm_up_seq);
946 break;
677 947
678 for (i = 0; i < c; i++) { 948 default:
679 list_for_each_entry(w, &codec->dapm_widgets, list) { 949 if (!w->power_check)
950 continue;
680 951
681 /* is widget in stream order */ 952 power = w->power_check(w);
682 if (seq && seq[i] && w->id != seq[i]) 953 if (power)
954 sys_power = 1;
955
956 if (w->power == power)
683 continue; 957 continue;
684 958
685 ret = dapm_power_widget(codec, event, w); 959 if (power)
686 if (ret != 0) 960 dapm_seq_insert(w, &up_list, dapm_up_seq);
687 return ret; 961 else
962 dapm_seq_insert(w, &down_list, dapm_down_seq);
963
964 w->power = power;
965 break;
688 } 966 }
689 } 967 }
690 968
969 /* If we're changing to all on or all off then prepare */
970 if ((sys_power && codec->bias_level == SND_SOC_BIAS_STANDBY) ||
971 (!sys_power && codec->bias_level == SND_SOC_BIAS_ON)) {
972 ret = snd_soc_dapm_set_bias_level(socdev,
973 SND_SOC_BIAS_PREPARE);
974 if (ret != 0)
975 pr_err("Failed to prepare bias: %d\n", ret);
976 }
977
978 /* Power down widgets first; try to avoid amplifying pops. */
979 dapm_seq_run(codec, &down_list, event, dapm_down_seq);
980
981 /* Now power up. */
982 dapm_seq_run(codec, &up_list, event, dapm_up_seq);
983
984 /* If we just powered the last thing off drop to standby bias */
985 if (codec->bias_level == SND_SOC_BIAS_PREPARE && !sys_power) {
986 ret = snd_soc_dapm_set_bias_level(socdev,
987 SND_SOC_BIAS_STANDBY);
988 if (ret != 0)
989 pr_err("Failed to apply standby bias: %d\n", ret);
990 }
991
992 /* If we just powered up then move to active bias */
993 if (codec->bias_level == SND_SOC_BIAS_PREPARE && sys_power) {
994 ret = snd_soc_dapm_set_bias_level(socdev,
995 SND_SOC_BIAS_ON);
996 if (ret != 0)
997 pr_err("Failed to apply active bias: %d\n", ret);
998 }
999
1000 pop_dbg(codec->pop_time, "DAPM sequencing finished, waiting %dms\n",
1001 codec->pop_time);
1002
691 return 0; 1003 return 0;
692} 1004}
693 1005
@@ -723,6 +1035,7 @@ static void dbg_dump_dapm(struct snd_soc_codec* codec, const char *action)
723 case snd_soc_dapm_pga: 1035 case snd_soc_dapm_pga:
724 case snd_soc_dapm_mixer: 1036 case snd_soc_dapm_mixer:
725 case snd_soc_dapm_mixer_named_ctl: 1037 case snd_soc_dapm_mixer_named_ctl:
1038 case snd_soc_dapm_supply:
726 if (w->name) { 1039 if (w->name) {
727 in = is_connected_input_ep(w); 1040 in = is_connected_input_ep(w);
728 dapm_clear_walk(w->codec); 1041 dapm_clear_walk(w->codec);
@@ -851,6 +1164,7 @@ static ssize_t dapm_widget_show(struct device *dev,
851 case snd_soc_dapm_pga: 1164 case snd_soc_dapm_pga:
852 case snd_soc_dapm_mixer: 1165 case snd_soc_dapm_mixer:
853 case snd_soc_dapm_mixer_named_ctl: 1166 case snd_soc_dapm_mixer_named_ctl:
1167 case snd_soc_dapm_supply:
854 if (w->name) 1168 if (w->name)
855 count += sprintf(buf + count, "%s: %s\n", 1169 count += sprintf(buf + count, "%s: %s\n",
856 w->name, w->power ? "On":"Off"); 1170 w->name, w->power ? "On":"Off");
@@ -883,16 +1197,12 @@ static DEVICE_ATTR(dapm_widget, 0444, dapm_widget_show, NULL);
883 1197
884int snd_soc_dapm_sys_add(struct device *dev) 1198int snd_soc_dapm_sys_add(struct device *dev)
885{ 1199{
886 if (!dapm_status)
887 return 0;
888 return device_create_file(dev, &dev_attr_dapm_widget); 1200 return device_create_file(dev, &dev_attr_dapm_widget);
889} 1201}
890 1202
891static void snd_soc_dapm_sys_remove(struct device *dev) 1203static void snd_soc_dapm_sys_remove(struct device *dev)
892{ 1204{
893 if (dapm_status) { 1205 device_remove_file(dev, &dev_attr_dapm_widget);
894 device_remove_file(dev, &dev_attr_dapm_widget);
895 }
896} 1206}
897 1207
898/* free all dapm widgets and resources */ 1208/* free all dapm widgets and resources */
@@ -983,8 +1293,8 @@ static int snd_soc_dapm_add_route(struct snd_soc_codec *codec,
983 if (wsink->id == snd_soc_dapm_input) { 1293 if (wsink->id == snd_soc_dapm_input) {
984 if (wsource->id == snd_soc_dapm_micbias || 1294 if (wsource->id == snd_soc_dapm_micbias ||
985 wsource->id == snd_soc_dapm_mic || 1295 wsource->id == snd_soc_dapm_mic ||
986 wsink->id == snd_soc_dapm_line || 1296 wsource->id == snd_soc_dapm_line ||
987 wsink->id == snd_soc_dapm_output) 1297 wsource->id == snd_soc_dapm_output)
988 wsink->ext = 1; 1298 wsink->ext = 1;
989 } 1299 }
990 if (wsource->id == snd_soc_dapm_output) { 1300 if (wsource->id == snd_soc_dapm_output) {
@@ -1015,6 +1325,7 @@ static int snd_soc_dapm_add_route(struct snd_soc_codec *codec,
1015 case snd_soc_dapm_vmid: 1325 case snd_soc_dapm_vmid:
1016 case snd_soc_dapm_pre: 1326 case snd_soc_dapm_pre:
1017 case snd_soc_dapm_post: 1327 case snd_soc_dapm_post:
1328 case snd_soc_dapm_supply:
1018 list_add(&path->list, &codec->dapm_paths); 1329 list_add(&path->list, &codec->dapm_paths);
1019 list_add(&path->list_sink, &wsink->sources); 1330 list_add(&path->list_sink, &wsink->sources);
1020 list_add(&path->list_source, &wsource->sinks); 1331 list_add(&path->list_source, &wsource->sinks);
@@ -1108,15 +1419,22 @@ int snd_soc_dapm_new_widgets(struct snd_soc_codec *codec)
1108 case snd_soc_dapm_switch: 1419 case snd_soc_dapm_switch:
1109 case snd_soc_dapm_mixer: 1420 case snd_soc_dapm_mixer:
1110 case snd_soc_dapm_mixer_named_ctl: 1421 case snd_soc_dapm_mixer_named_ctl:
1422 w->power_check = dapm_generic_check_power;
1111 dapm_new_mixer(codec, w); 1423 dapm_new_mixer(codec, w);
1112 break; 1424 break;
1113 case snd_soc_dapm_mux: 1425 case snd_soc_dapm_mux:
1114 case snd_soc_dapm_value_mux: 1426 case snd_soc_dapm_value_mux:
1427 w->power_check = dapm_generic_check_power;
1115 dapm_new_mux(codec, w); 1428 dapm_new_mux(codec, w);
1116 break; 1429 break;
1117 case snd_soc_dapm_adc: 1430 case snd_soc_dapm_adc:
1431 w->power_check = dapm_adc_check_power;
1432 break;
1118 case snd_soc_dapm_dac: 1433 case snd_soc_dapm_dac:
1434 w->power_check = dapm_dac_check_power;
1435 break;
1119 case snd_soc_dapm_pga: 1436 case snd_soc_dapm_pga:
1437 w->power_check = dapm_generic_check_power;
1120 dapm_new_pga(codec, w); 1438 dapm_new_pga(codec, w);
1121 break; 1439 break;
1122 case snd_soc_dapm_input: 1440 case snd_soc_dapm_input:
@@ -1126,6 +1444,10 @@ int snd_soc_dapm_new_widgets(struct snd_soc_codec *codec)
1126 case snd_soc_dapm_hp: 1444 case snd_soc_dapm_hp:
1127 case snd_soc_dapm_mic: 1445 case snd_soc_dapm_mic:
1128 case snd_soc_dapm_line: 1446 case snd_soc_dapm_line:
1447 w->power_check = dapm_generic_check_power;
1448 break;
1449 case snd_soc_dapm_supply:
1450 w->power_check = dapm_supply_check_power;
1129 case snd_soc_dapm_vmid: 1451 case snd_soc_dapm_vmid:
1130 case snd_soc_dapm_pre: 1452 case snd_soc_dapm_pre:
1131 case snd_soc_dapm_post: 1453 case snd_soc_dapm_post:
@@ -1205,7 +1527,7 @@ int snd_soc_dapm_put_volsw(struct snd_kcontrol *kcontrol,
1205 int max = mc->max; 1527 int max = mc->max;
1206 unsigned int mask = (1 << fls(max)) - 1; 1528 unsigned int mask = (1 << fls(max)) - 1;
1207 unsigned int invert = mc->invert; 1529 unsigned int invert = mc->invert;
1208 unsigned short val, val2, val_mask; 1530 unsigned int val, val2, val_mask;
1209 int ret; 1531 int ret;
1210 1532
1211 val = (ucontrol->value.integer.value[0] & mask); 1533 val = (ucontrol->value.integer.value[0] & mask);
@@ -1269,7 +1591,7 @@ int snd_soc_dapm_get_enum_double(struct snd_kcontrol *kcontrol,
1269{ 1591{
1270 struct snd_soc_dapm_widget *widget = snd_kcontrol_chip(kcontrol); 1592 struct snd_soc_dapm_widget *widget = snd_kcontrol_chip(kcontrol);
1271 struct soc_enum *e = (struct soc_enum *)kcontrol->private_value; 1593 struct soc_enum *e = (struct soc_enum *)kcontrol->private_value;
1272 unsigned short val, bitmask; 1594 unsigned int val, bitmask;
1273 1595
1274 for (bitmask = 1; bitmask < e->max; bitmask <<= 1) 1596 for (bitmask = 1; bitmask < e->max; bitmask <<= 1)
1275 ; 1597 ;
@@ -1297,8 +1619,8 @@ int snd_soc_dapm_put_enum_double(struct snd_kcontrol *kcontrol,
1297{ 1619{
1298 struct snd_soc_dapm_widget *widget = snd_kcontrol_chip(kcontrol); 1620 struct snd_soc_dapm_widget *widget = snd_kcontrol_chip(kcontrol);
1299 struct soc_enum *e = (struct soc_enum *)kcontrol->private_value; 1621 struct soc_enum *e = (struct soc_enum *)kcontrol->private_value;
1300 unsigned short val, mux; 1622 unsigned int val, mux;
1301 unsigned short mask, bitmask; 1623 unsigned int mask, bitmask;
1302 int ret = 0; 1624 int ret = 0;
1303 1625
1304 for (bitmask = 1; bitmask < e->max; bitmask <<= 1) 1626 for (bitmask = 1; bitmask < e->max; bitmask <<= 1)
@@ -1356,7 +1678,7 @@ int snd_soc_dapm_get_value_enum_double(struct snd_kcontrol *kcontrol,
1356{ 1678{
1357 struct snd_soc_dapm_widget *widget = snd_kcontrol_chip(kcontrol); 1679 struct snd_soc_dapm_widget *widget = snd_kcontrol_chip(kcontrol);
1358 struct soc_enum *e = (struct soc_enum *)kcontrol->private_value; 1680 struct soc_enum *e = (struct soc_enum *)kcontrol->private_value;
1359 unsigned short reg_val, val, mux; 1681 unsigned int reg_val, val, mux;
1360 1682
1361 reg_val = snd_soc_read(widget->codec, e->reg); 1683 reg_val = snd_soc_read(widget->codec, e->reg);
1362 val = (reg_val >> e->shift_l) & e->mask; 1684 val = (reg_val >> e->shift_l) & e->mask;
@@ -1396,8 +1718,8 @@ int snd_soc_dapm_put_value_enum_double(struct snd_kcontrol *kcontrol,
1396{ 1718{
1397 struct snd_soc_dapm_widget *widget = snd_kcontrol_chip(kcontrol); 1719 struct snd_soc_dapm_widget *widget = snd_kcontrol_chip(kcontrol);
1398 struct soc_enum *e = (struct soc_enum *)kcontrol->private_value; 1720 struct soc_enum *e = (struct soc_enum *)kcontrol->private_value;
1399 unsigned short val, mux; 1721 unsigned int val, mux;
1400 unsigned short mask; 1722 unsigned int mask;
1401 int ret = 0; 1723 int ret = 0;
1402 1724
1403 if (ucontrol->value.enumerated.item[0] > e->max - 1) 1725 if (ucontrol->value.enumerated.item[0] > e->max - 1)
@@ -1626,35 +1948,11 @@ int snd_soc_dapm_stream_event(struct snd_soc_codec *codec,
1626EXPORT_SYMBOL_GPL(snd_soc_dapm_stream_event); 1948EXPORT_SYMBOL_GPL(snd_soc_dapm_stream_event);
1627 1949
1628/** 1950/**
1629 * snd_soc_dapm_set_bias_level - set the bias level for the system
1630 * @socdev: audio device
1631 * @level: level to configure
1632 *
1633 * Configure the bias (power) levels for the SoC audio device.
1634 *
1635 * Returns 0 for success else error.
1636 */
1637int snd_soc_dapm_set_bias_level(struct snd_soc_device *socdev,
1638 enum snd_soc_bias_level level)
1639{
1640 struct snd_soc_card *card = socdev->card;
1641 struct snd_soc_codec *codec = socdev->card->codec;
1642 int ret = 0;
1643
1644 if (card->set_bias_level)
1645 ret = card->set_bias_level(card, level);
1646 if (ret == 0 && codec->set_bias_level)
1647 ret = codec->set_bias_level(codec, level);
1648
1649 return ret;
1650}
1651
1652/**
1653 * snd_soc_dapm_enable_pin - enable pin. 1951 * snd_soc_dapm_enable_pin - enable pin.
1654 * @codec: SoC codec 1952 * @codec: SoC codec
1655 * @pin: pin name 1953 * @pin: pin name
1656 * 1954 *
1657 * Enables input/output pin and it's parents or children widgets iff there is 1955 * Enables input/output pin and its parents or children widgets iff there is
1658 * a valid audio route and active audio stream. 1956 * a valid audio route and active audio stream.
1659 * NOTE: snd_soc_dapm_sync() needs to be called after this for DAPM to 1957 * NOTE: snd_soc_dapm_sync() needs to be called after this for DAPM to
1660 * do any widget power switching. 1958 * do any widget power switching.
@@ -1670,7 +1968,7 @@ EXPORT_SYMBOL_GPL(snd_soc_dapm_enable_pin);
1670 * @codec: SoC codec 1968 * @codec: SoC codec
1671 * @pin: pin name 1969 * @pin: pin name
1672 * 1970 *
1673 * Disables input/output pin and it's parents or children widgets. 1971 * Disables input/output pin and its parents or children widgets.
1674 * NOTE: snd_soc_dapm_sync() needs to be called after this for DAPM to 1972 * NOTE: snd_soc_dapm_sync() needs to be called after this for DAPM to
1675 * do any widget power switching. 1973 * do any widget power switching.
1676 */ 1974 */
@@ -1737,6 +2035,36 @@ void snd_soc_dapm_free(struct snd_soc_device *socdev)
1737} 2035}
1738EXPORT_SYMBOL_GPL(snd_soc_dapm_free); 2036EXPORT_SYMBOL_GPL(snd_soc_dapm_free);
1739 2037
2038/*
2039 * snd_soc_dapm_shutdown - callback for system shutdown
2040 */
2041void snd_soc_dapm_shutdown(struct snd_soc_device *socdev)
2042{
2043 struct snd_soc_codec *codec = socdev->card->codec;
2044 struct snd_soc_dapm_widget *w;
2045 LIST_HEAD(down_list);
2046 int powerdown = 0;
2047
2048 list_for_each_entry(w, &codec->dapm_widgets, list) {
2049 if (w->power) {
2050 dapm_seq_insert(w, &down_list, dapm_down_seq);
2051 w->power = 0;
2052 powerdown = 1;
2053 }
2054 }
2055
2056 /* If there were no widgets to power down we're already in
2057 * standby.
2058 */
2059 if (powerdown) {
2060 snd_soc_dapm_set_bias_level(socdev, SND_SOC_BIAS_PREPARE);
2061 dapm_seq_run(codec, &down_list, 0, dapm_down_seq);
2062 snd_soc_dapm_set_bias_level(socdev, SND_SOC_BIAS_STANDBY);
2063 }
2064
2065 snd_soc_dapm_set_bias_level(socdev, SND_SOC_BIAS_OFF);
2066}
2067
1740/* Module information */ 2068/* Module information */
1741MODULE_AUTHOR("Liam Girdwood, lrg@slimlogic.co.uk"); 2069MODULE_AUTHOR("Liam Girdwood, lrg@slimlogic.co.uk");
1742MODULE_DESCRIPTION("Dynamic Audio Power Management core for ALSA SoC"); 2070MODULE_DESCRIPTION("Dynamic Audio Power Management core for ALSA SoC");
diff --git a/sound/soc/soc-jack.c b/sound/soc/soc-jack.c
index 28346fb2e70c..1d455ab79490 100644
--- a/sound/soc/soc-jack.c
+++ b/sound/soc/soc-jack.c
@@ -73,14 +73,15 @@ void snd_soc_jack_report(struct snd_soc_jack *jack, int status, int mask)
73 oldstatus = jack->status; 73 oldstatus = jack->status;
74 74
75 jack->status &= ~mask; 75 jack->status &= ~mask;
76 jack->status |= status; 76 jack->status |= status & mask;
77 77
78 /* The DAPM sync is expensive enough to be worth skipping */ 78 /* The DAPM sync is expensive enough to be worth skipping.
79 if (jack->status == oldstatus) 79 * However, empty mask means pin synchronization is desired. */
80 if (mask && (jack->status == oldstatus))
80 goto out; 81 goto out;
81 82
82 list_for_each_entry(pin, &jack->pins, list) { 83 list_for_each_entry(pin, &jack->pins, list) {
83 enable = pin->mask & status; 84 enable = pin->mask & jack->status;
84 85
85 if (pin->invert) 86 if (pin->invert)
86 enable = !enable; 87 enable = !enable;
@@ -220,6 +221,9 @@ int snd_soc_jack_add_gpios(struct snd_soc_jack *jack, int count,
220 if (ret) 221 if (ret)
221 goto err; 222 goto err;
222 223
224 INIT_WORK(&gpios[i].work, gpio_work);
225 gpios[i].jack = jack;
226
223 ret = request_irq(gpio_to_irq(gpios[i].gpio), 227 ret = request_irq(gpio_to_irq(gpios[i].gpio),
224 gpio_handler, 228 gpio_handler,
225 IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING, 229 IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING,
@@ -228,8 +232,13 @@ int snd_soc_jack_add_gpios(struct snd_soc_jack *jack, int count,
228 if (ret) 232 if (ret)
229 goto err; 233 goto err;
230 234
231 INIT_WORK(&gpios[i].work, gpio_work); 235#ifdef CONFIG_GPIO_SYSFS
232 gpios[i].jack = jack; 236 /* Expose GPIO value over sysfs for diagnostic purposes */
237 gpio_export(gpios[i].gpio, false);
238#endif
239
240 /* Update initial jack status */
241 snd_soc_jack_gpio_detect(&gpios[i]);
233 } 242 }
234 243
235 return 0; 244 return 0;
@@ -258,6 +267,9 @@ void snd_soc_jack_free_gpios(struct snd_soc_jack *jack, int count,
258 int i; 267 int i;
259 268
260 for (i = 0; i < count; i++) { 269 for (i = 0; i < count; i++) {
270#ifdef CONFIG_GPIO_SYSFS
271 gpio_unexport(gpios[i].gpio);
272#endif
261 free_irq(gpio_to_irq(gpios[i].gpio), &gpios[i]); 273 free_irq(gpio_to_irq(gpios[i].gpio), &gpios[i]);
262 gpio_free(gpios[i].gpio); 274 gpio_free(gpios[i].gpio);
263 gpios[i].jack = NULL; 275 gpios[i].jack = NULL;
diff --git a/sound/soc/txx9/Kconfig b/sound/soc/txx9/Kconfig
new file mode 100644
index 000000000000..ebc9327eae71
--- /dev/null
+++ b/sound/soc/txx9/Kconfig
@@ -0,0 +1,29 @@
1##
2## TXx9 ACLC
3##
4config SND_SOC_TXX9ACLC
5 tristate "SoC Audio for TXx9"
6 depends on HAS_TXX9_ACLC && TXX9_DMAC
7 help
8 This option enables support for the AC Link Controllers in TXx9 SoC.
9
10config HAS_TXX9_ACLC
11 bool
12
13config SND_SOC_TXX9ACLC_AC97
14 tristate
15 select AC97_BUS
16 select SND_AC97_CODEC
17 select SND_SOC_AC97_BUS
18
19
20##
21## Boards
22##
23config SND_SOC_TXX9ACLC_GENERIC
24 tristate "Generic TXx9 ACLC sound machine"
25 depends on SND_SOC_TXX9ACLC
26 select SND_SOC_TXX9ACLC_AC97
27 select SND_SOC_AC97_CODEC
28 help
29 This is a generic AC97 sound machine for use in TXx9 based systems.
diff --git a/sound/soc/txx9/Makefile b/sound/soc/txx9/Makefile
new file mode 100644
index 000000000000..551f16c0c4f9
--- /dev/null
+++ b/sound/soc/txx9/Makefile
@@ -0,0 +1,11 @@
1# Platform
2snd-soc-txx9aclc-objs := txx9aclc.o
3snd-soc-txx9aclc-ac97-objs := txx9aclc-ac97.o
4
5obj-$(CONFIG_SND_SOC_TXX9ACLC) += snd-soc-txx9aclc.o
6obj-$(CONFIG_SND_SOC_TXX9ACLC_AC97) += snd-soc-txx9aclc-ac97.o
7
8# Machine
9snd-soc-txx9aclc-generic-objs := txx9aclc-generic.o
10
11obj-$(CONFIG_SND_SOC_TXX9ACLC_GENERIC) += snd-soc-txx9aclc-generic.o
diff --git a/sound/soc/txx9/txx9aclc-ac97.c b/sound/soc/txx9/txx9aclc-ac97.c
new file mode 100644
index 000000000000..0f83bdb9b16f
--- /dev/null
+++ b/sound/soc/txx9/txx9aclc-ac97.c
@@ -0,0 +1,255 @@
1/*
2 * TXx9 ACLC AC97 driver
3 *
4 * Copyright (C) 2009 Atsushi Nemoto
5 *
6 * Based on RBTX49xx patch from CELF patch archive.
7 * (C) Copyright TOSHIBA CORPORATION 2004-2006
8 *
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License version 2 as
11 * published by the Free Software Foundation.
12 */
13
14#include <linux/init.h>
15#include <linux/module.h>
16#include <linux/delay.h>
17#include <linux/interrupt.h>
18#include <linux/io.h>
19#include <sound/core.h>
20#include <sound/pcm.h>
21#include <sound/soc.h>
22#include "txx9aclc.h"
23
24#define AC97_DIR \
25 (SND_SOC_DAIDIR_PLAYBACK | SND_SOC_DAIDIR_CAPTURE)
26
27#define AC97_RATES \
28 SNDRV_PCM_RATE_8000_48000
29
30#ifdef __BIG_ENDIAN
31#define AC97_FMTS SNDRV_PCM_FMTBIT_S16_BE
32#else
33#define AC97_FMTS SNDRV_PCM_FMTBIT_S16_LE
34#endif
35
36static DECLARE_WAIT_QUEUE_HEAD(ac97_waitq);
37
38/* REVISIT: How to find txx9aclc_soc_device from snd_ac97? */
39static struct txx9aclc_soc_device *txx9aclc_soc_dev;
40
41static int txx9aclc_regready(struct txx9aclc_soc_device *dev)
42{
43 struct txx9aclc_plat_drvdata *drvdata = txx9aclc_get_plat_drvdata(dev);
44
45 return __raw_readl(drvdata->base + ACINTSTS) & ACINT_REGACCRDY;
46}
47
48/* AC97 controller reads codec register */
49static unsigned short txx9aclc_ac97_read(struct snd_ac97 *ac97,
50 unsigned short reg)
51{
52 struct txx9aclc_soc_device *dev = txx9aclc_soc_dev;
53 struct txx9aclc_plat_drvdata *drvdata = txx9aclc_get_plat_drvdata(dev);
54 void __iomem *base = drvdata->base;
55 u32 dat;
56
57 if (!(__raw_readl(base + ACINTSTS) & ACINT_CODECRDY(ac97->num)))
58 return 0xffff;
59 reg |= ac97->num << 7;
60 dat = (reg << ACREGACC_REG_SHIFT) | ACREGACC_READ;
61 __raw_writel(dat, base + ACREGACC);
62 __raw_writel(ACINT_REGACCRDY, base + ACINTEN);
63 if (!wait_event_timeout(ac97_waitq, txx9aclc_regready(dev), HZ)) {
64 __raw_writel(ACINT_REGACCRDY, base + ACINTDIS);
65 dev_err(dev->soc_dev.dev, "ac97 read timeout (reg %#x)\n", reg);
66 dat = 0xffff;
67 goto done;
68 }
69 dat = __raw_readl(base + ACREGACC);
70 if (((dat >> ACREGACC_REG_SHIFT) & 0xff) != reg) {
71 dev_err(dev->soc_dev.dev, "reg mismatch %x with %x\n",
72 dat, reg);
73 dat = 0xffff;
74 goto done;
75 }
76 dat = (dat >> ACREGACC_DAT_SHIFT) & 0xffff;
77done:
78 __raw_writel(ACINT_REGACCRDY, base + ACINTDIS);
79 return dat;
80}
81
82/* AC97 controller writes to codec register */
83static void txx9aclc_ac97_write(struct snd_ac97 *ac97, unsigned short reg,
84 unsigned short val)
85{
86 struct txx9aclc_soc_device *dev = txx9aclc_soc_dev;
87 struct txx9aclc_plat_drvdata *drvdata = txx9aclc_get_plat_drvdata(dev);
88 void __iomem *base = drvdata->base;
89
90 __raw_writel(((reg | (ac97->num << 7)) << ACREGACC_REG_SHIFT) |
91 (val << ACREGACC_DAT_SHIFT),
92 base + ACREGACC);
93 __raw_writel(ACINT_REGACCRDY, base + ACINTEN);
94 if (!wait_event_timeout(ac97_waitq, txx9aclc_regready(dev), HZ)) {
95 dev_err(dev->soc_dev.dev,
96 "ac97 write timeout (reg %#x)\n", reg);
97 }
98 __raw_writel(ACINT_REGACCRDY, base + ACINTDIS);
99}
100
101static void txx9aclc_ac97_cold_reset(struct snd_ac97 *ac97)
102{
103 struct txx9aclc_soc_device *dev = txx9aclc_soc_dev;
104 struct txx9aclc_plat_drvdata *drvdata = txx9aclc_get_plat_drvdata(dev);
105 void __iomem *base = drvdata->base;
106 u32 ready = ACINT_CODECRDY(ac97->num) | ACINT_REGACCRDY;
107
108 __raw_writel(ACCTL_ENLINK, base + ACCTLDIS);
109 mmiowb();
110 udelay(1);
111 __raw_writel(ACCTL_ENLINK, base + ACCTLEN);
112 /* wait for primary codec ready status */
113 __raw_writel(ready, base + ACINTEN);
114 if (!wait_event_timeout(ac97_waitq,
115 (__raw_readl(base + ACINTSTS) & ready) == ready,
116 HZ)) {
117 dev_err(&ac97->dev, "primary codec is not ready "
118 "(status %#x)\n",
119 __raw_readl(base + ACINTSTS));
120 }
121 __raw_writel(ACINT_REGACCRDY, base + ACINTSTS);
122 __raw_writel(ready, base + ACINTDIS);
123}
124
125/* AC97 controller operations */
126struct snd_ac97_bus_ops soc_ac97_ops = {
127 .read = txx9aclc_ac97_read,
128 .write = txx9aclc_ac97_write,
129 .reset = txx9aclc_ac97_cold_reset,
130};
131EXPORT_SYMBOL_GPL(soc_ac97_ops);
132
133static irqreturn_t txx9aclc_ac97_irq(int irq, void *dev_id)
134{
135 struct txx9aclc_plat_drvdata *drvdata = dev_id;
136 void __iomem *base = drvdata->base;
137
138 __raw_writel(__raw_readl(base + ACINTMSTS), base + ACINTDIS);
139 wake_up(&ac97_waitq);
140 return IRQ_HANDLED;
141}
142
143static int txx9aclc_ac97_probe(struct platform_device *pdev,
144 struct snd_soc_dai *dai)
145{
146 struct snd_soc_device *socdev = platform_get_drvdata(pdev);
147 struct txx9aclc_soc_device *dev =
148 container_of(socdev, struct txx9aclc_soc_device, soc_dev);
149
150 dev->aclc_pdev = to_platform_device(dai->dev);
151 txx9aclc_soc_dev = dev;
152 return 0;
153}
154
155static void txx9aclc_ac97_remove(struct platform_device *pdev,
156 struct snd_soc_dai *dai)
157{
158 struct platform_device *aclc_pdev = to_platform_device(dai->dev);
159 struct txx9aclc_plat_drvdata *drvdata = platform_get_drvdata(aclc_pdev);
160
161 /* disable AC-link */
162 __raw_writel(ACCTL_ENLINK, drvdata->base + ACCTLDIS);
163 txx9aclc_soc_dev = NULL;
164}
165
166struct snd_soc_dai txx9aclc_ac97_dai = {
167 .name = "txx9aclc_ac97",
168 .ac97_control = 1,
169 .probe = txx9aclc_ac97_probe,
170 .remove = txx9aclc_ac97_remove,
171 .playback = {
172 .rates = AC97_RATES,
173 .formats = AC97_FMTS,
174 .channels_min = 2,
175 .channels_max = 2,
176 },
177 .capture = {
178 .rates = AC97_RATES,
179 .formats = AC97_FMTS,
180 .channels_min = 2,
181 .channels_max = 2,
182 },
183};
184EXPORT_SYMBOL_GPL(txx9aclc_ac97_dai);
185
186static int __devinit txx9aclc_ac97_dev_probe(struct platform_device *pdev)
187{
188 struct txx9aclc_plat_drvdata *drvdata;
189 struct resource *r;
190 int err;
191 int irq;
192
193 irq = platform_get_irq(pdev, 0);
194 if (irq < 0)
195 return irq;
196 r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
197 if (!r)
198 return -EBUSY;
199
200 if (!devm_request_mem_region(&pdev->dev, r->start, resource_size(r),
201 dev_name(&pdev->dev)))
202 return -EBUSY;
203
204 drvdata = devm_kzalloc(&pdev->dev, sizeof(*drvdata), GFP_KERNEL);
205 if (!drvdata)
206 return -ENOMEM;
207 platform_set_drvdata(pdev, drvdata);
208 drvdata->physbase = r->start;
209 if (sizeof(drvdata->physbase) > sizeof(r->start) &&
210 r->start >= TXX9_DIRECTMAP_BASE &&
211 r->start < TXX9_DIRECTMAP_BASE + 0x400000)
212 drvdata->physbase |= 0xf00000000ull;
213 drvdata->base = devm_ioremap(&pdev->dev, r->start, resource_size(r));
214 if (!drvdata->base)
215 return -EBUSY;
216 err = devm_request_irq(&pdev->dev, irq, txx9aclc_ac97_irq,
217 IRQF_DISABLED, dev_name(&pdev->dev), drvdata);
218 if (err < 0)
219 return err;
220
221 txx9aclc_ac97_dai.dev = &pdev->dev;
222 return snd_soc_register_dai(&txx9aclc_ac97_dai);
223}
224
225static int __devexit txx9aclc_ac97_dev_remove(struct platform_device *pdev)
226{
227 snd_soc_unregister_dai(&txx9aclc_ac97_dai);
228 return 0;
229}
230
231static struct platform_driver txx9aclc_ac97_driver = {
232 .probe = txx9aclc_ac97_dev_probe,
233 .remove = __devexit_p(txx9aclc_ac97_dev_remove),
234 .driver = {
235 .name = "txx9aclc-ac97",
236 .owner = THIS_MODULE,
237 },
238};
239
240static int __init txx9aclc_ac97_init(void)
241{
242 return platform_driver_register(&txx9aclc_ac97_driver);
243}
244
245static void __exit txx9aclc_ac97_exit(void)
246{
247 platform_driver_unregister(&txx9aclc_ac97_driver);
248}
249
250module_init(txx9aclc_ac97_init);
251module_exit(txx9aclc_ac97_exit);
252
253MODULE_AUTHOR("Atsushi Nemoto <anemo@mba.ocn.ne.jp>");
254MODULE_DESCRIPTION("TXx9 ACLC AC97 driver");
255MODULE_LICENSE("GPL");
diff --git a/sound/soc/txx9/txx9aclc-generic.c b/sound/soc/txx9/txx9aclc-generic.c
new file mode 100644
index 000000000000..3175de9a92cb
--- /dev/null
+++ b/sound/soc/txx9/txx9aclc-generic.c
@@ -0,0 +1,98 @@
1/*
2 * Generic TXx9 ACLC machine driver
3 *
4 * Copyright (C) 2009 Atsushi Nemoto
5 *
6 * Based on RBTX49xx patch from CELF patch archive.
7 * (C) Copyright TOSHIBA CORPORATION 2004-2006
8 *
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License version 2 as
11 * published by the Free Software Foundation.
12 *
13 * This is a very generic AC97 sound machine driver for boards which
14 * have (AC97) audio at ACLC (e.g. RBTX49XX boards).
15 */
16
17#include <linux/module.h>
18#include <linux/platform_device.h>
19#include <sound/core.h>
20#include <sound/pcm.h>
21#include <sound/soc.h>
22#include "../codecs/ac97.h"
23#include "txx9aclc.h"
24
25static struct snd_soc_dai_link txx9aclc_generic_dai = {
26 .name = "AC97",
27 .stream_name = "AC97 HiFi",
28 .cpu_dai = &txx9aclc_ac97_dai,
29 .codec_dai = &ac97_dai,
30};
31
32static struct snd_soc_card txx9aclc_generic_card = {
33 .name = "Generic TXx9 ACLC Audio",
34 .platform = &txx9aclc_soc_platform,
35 .dai_link = &txx9aclc_generic_dai,
36 .num_links = 1,
37};
38
39static struct txx9aclc_soc_device txx9aclc_generic_soc_device = {
40 .soc_dev = {
41 .card = &txx9aclc_generic_card,
42 .codec_dev = &soc_codec_dev_ac97,
43 },
44};
45
46static int __init txx9aclc_generic_probe(struct platform_device *pdev)
47{
48 struct txx9aclc_soc_device *dev = &txx9aclc_generic_soc_device;
49 struct platform_device *soc_pdev;
50 int ret;
51
52 soc_pdev = platform_device_alloc("soc-audio", -1);
53 if (!soc_pdev)
54 return -ENOMEM;
55 platform_set_drvdata(soc_pdev, &dev->soc_dev);
56 dev->soc_dev.dev = &soc_pdev->dev;
57 ret = platform_device_add(soc_pdev);
58 if (ret) {
59 platform_device_put(soc_pdev);
60 return ret;
61 }
62 platform_set_drvdata(pdev, soc_pdev);
63 return 0;
64}
65
66static int __exit txx9aclc_generic_remove(struct platform_device *pdev)
67{
68 struct platform_device *soc_pdev = platform_get_drvdata(pdev);
69
70 platform_device_unregister(soc_pdev);
71 return 0;
72}
73
74static struct platform_driver txx9aclc_generic_driver = {
75 .remove = txx9aclc_generic_remove,
76 .driver = {
77 .name = "txx9aclc-generic",
78 .owner = THIS_MODULE,
79 },
80};
81
82static int __init txx9aclc_generic_init(void)
83{
84 return platform_driver_probe(&txx9aclc_generic_driver,
85 txx9aclc_generic_probe);
86}
87
88static void __exit txx9aclc_generic_exit(void)
89{
90 platform_driver_unregister(&txx9aclc_generic_driver);
91}
92
93module_init(txx9aclc_generic_init);
94module_exit(txx9aclc_generic_exit);
95
96MODULE_AUTHOR("Atsushi Nemoto <anemo@mba.ocn.ne.jp>");
97MODULE_DESCRIPTION("Generic TXx9 ACLC ALSA SoC audio driver");
98MODULE_LICENSE("GPL");
diff --git a/sound/soc/txx9/txx9aclc.c b/sound/soc/txx9/txx9aclc.c
new file mode 100644
index 000000000000..efed64b8b026
--- /dev/null
+++ b/sound/soc/txx9/txx9aclc.c
@@ -0,0 +1,432 @@
1/*
2 * Generic TXx9 ACLC platform driver
3 *
4 * Copyright (C) 2009 Atsushi Nemoto
5 *
6 * Based on RBTX49xx patch from CELF patch archive.
7 * (C) Copyright TOSHIBA CORPORATION 2004-2006
8 *
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License version 2 as
11 * published by the Free Software Foundation.
12 */
13
14#include <linux/module.h>
15#include <linux/init.h>
16#include <linux/platform_device.h>
17#include <linux/scatterlist.h>
18#include <sound/core.h>
19#include <sound/pcm.h>
20#include <sound/pcm_params.h>
21#include <sound/soc.h>
22#include "txx9aclc.h"
23
24static const struct snd_pcm_hardware txx9aclc_pcm_hardware = {
25 /*
26 * REVISIT: SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_MMAP_VALID
27 * needs more works for noncoherent MIPS.
28 */
29 .info = SNDRV_PCM_INFO_INTERLEAVED |
30 SNDRV_PCM_INFO_BATCH |
31 SNDRV_PCM_INFO_PAUSE,
32#ifdef __BIG_ENDIAN
33 .formats = SNDRV_PCM_FMTBIT_S16_BE,
34#else
35 .formats = SNDRV_PCM_FMTBIT_S16_LE,
36#endif
37 .period_bytes_min = 1024,
38 .period_bytes_max = 8 * 1024,
39 .periods_min = 2,
40 .periods_max = 4096,
41 .buffer_bytes_max = 32 * 1024,
42};
43
44static int txx9aclc_pcm_hw_params(struct snd_pcm_substream *substream,
45 struct snd_pcm_hw_params *params)
46{
47 struct snd_soc_pcm_runtime *rtd = snd_pcm_substream_chip(substream);
48 struct snd_soc_device *socdev = rtd->socdev;
49 struct snd_pcm_runtime *runtime = substream->runtime;
50 struct txx9aclc_dmadata *dmadata = runtime->private_data;
51 int ret;
52
53 ret = snd_pcm_lib_malloc_pages(substream, params_buffer_bytes(params));
54 if (ret < 0)
55 return ret;
56
57 dev_dbg(socdev->dev,
58 "runtime->dma_area = %#lx dma_addr = %#lx dma_bytes = %zd "
59 "runtime->min_align %ld\n",
60 (unsigned long)runtime->dma_area,
61 (unsigned long)runtime->dma_addr, runtime->dma_bytes,
62 runtime->min_align);
63 dev_dbg(socdev->dev,
64 "periods %d period_bytes %d stream %d\n",
65 params_periods(params), params_period_bytes(params),
66 substream->stream);
67
68 dmadata->substream = substream;
69 dmadata->pos = 0;
70 return 0;
71}
72
73static int txx9aclc_pcm_hw_free(struct snd_pcm_substream *substream)
74{
75 return snd_pcm_lib_free_pages(substream);
76}
77
78static int txx9aclc_pcm_prepare(struct snd_pcm_substream *substream)
79{
80 struct snd_pcm_runtime *runtime = substream->runtime;
81 struct txx9aclc_dmadata *dmadata = runtime->private_data;
82
83 dmadata->dma_addr = runtime->dma_addr;
84 dmadata->buffer_bytes = snd_pcm_lib_buffer_bytes(substream);
85 dmadata->period_bytes = snd_pcm_lib_period_bytes(substream);
86
87 if (dmadata->buffer_bytes == dmadata->period_bytes) {
88 dmadata->frag_bytes = dmadata->period_bytes >> 1;
89 dmadata->frags = 2;
90 } else {
91 dmadata->frag_bytes = dmadata->period_bytes;
92 dmadata->frags = dmadata->buffer_bytes / dmadata->period_bytes;
93 }
94 dmadata->frag_count = 0;
95 dmadata->pos = 0;
96 return 0;
97}
98
99static void txx9aclc_dma_complete(void *arg)
100{
101 struct txx9aclc_dmadata *dmadata = arg;
102 unsigned long flags;
103
104 /* dma completion handler cannot submit new operations */
105 spin_lock_irqsave(&dmadata->dma_lock, flags);
106 if (dmadata->frag_count >= 0) {
107 dmadata->dmacount--;
108 BUG_ON(dmadata->dmacount < 0);
109 tasklet_schedule(&dmadata->tasklet);
110 }
111 spin_unlock_irqrestore(&dmadata->dma_lock, flags);
112}
113
114static struct dma_async_tx_descriptor *
115txx9aclc_dma_submit(struct txx9aclc_dmadata *dmadata, dma_addr_t buf_dma_addr)
116{
117 struct dma_chan *chan = dmadata->dma_chan;
118 struct dma_async_tx_descriptor *desc;
119 struct scatterlist sg;
120
121 sg_init_table(&sg, 1);
122 sg_set_page(&sg, pfn_to_page(PFN_DOWN(buf_dma_addr)),
123 dmadata->frag_bytes, buf_dma_addr & (PAGE_SIZE - 1));
124 sg_dma_address(&sg) = buf_dma_addr;
125 desc = chan->device->device_prep_slave_sg(chan, &sg, 1,
126 dmadata->substream->stream == SNDRV_PCM_STREAM_PLAYBACK ?
127 DMA_TO_DEVICE : DMA_FROM_DEVICE,
128 DMA_PREP_INTERRUPT | DMA_CTRL_ACK);
129 if (!desc) {
130 dev_err(&chan->dev->device, "cannot prepare slave dma\n");
131 return NULL;
132 }
133 desc->callback = txx9aclc_dma_complete;
134 desc->callback_param = dmadata;
135 desc->tx_submit(desc);
136 return desc;
137}
138
139#define NR_DMA_CHAIN 2
140
141static void txx9aclc_dma_tasklet(unsigned long data)
142{
143 struct txx9aclc_dmadata *dmadata = (struct txx9aclc_dmadata *)data;
144 struct dma_chan *chan = dmadata->dma_chan;
145 struct dma_async_tx_descriptor *desc;
146 struct snd_pcm_substream *substream = dmadata->substream;
147 u32 ctlbit = substream->stream == SNDRV_PCM_STREAM_PLAYBACK ?
148 ACCTL_AUDODMA : ACCTL_AUDIDMA;
149 int i;
150 unsigned long flags;
151
152 spin_lock_irqsave(&dmadata->dma_lock, flags);
153 if (dmadata->frag_count < 0) {
154 struct txx9aclc_soc_device *dev =
155 container_of(dmadata, struct txx9aclc_soc_device,
156 dmadata[substream->stream]);
157 struct txx9aclc_plat_drvdata *drvdata =
158 txx9aclc_get_plat_drvdata(dev);
159 void __iomem *base = drvdata->base;
160
161 spin_unlock_irqrestore(&dmadata->dma_lock, flags);
162 chan->device->device_terminate_all(chan);
163 /* first time */
164 for (i = 0; i < NR_DMA_CHAIN; i++) {
165 desc = txx9aclc_dma_submit(dmadata,
166 dmadata->dma_addr + i * dmadata->frag_bytes);
167 if (!desc)
168 return;
169 }
170 dmadata->dmacount = NR_DMA_CHAIN;
171 chan->device->device_issue_pending(chan);
172 spin_lock_irqsave(&dmadata->dma_lock, flags);
173 __raw_writel(ctlbit, base + ACCTLEN);
174 dmadata->frag_count = NR_DMA_CHAIN % dmadata->frags;
175 spin_unlock_irqrestore(&dmadata->dma_lock, flags);
176 return;
177 }
178 BUG_ON(dmadata->dmacount >= NR_DMA_CHAIN);
179 while (dmadata->dmacount < NR_DMA_CHAIN) {
180 dmadata->dmacount++;
181 spin_unlock_irqrestore(&dmadata->dma_lock, flags);
182 desc = txx9aclc_dma_submit(dmadata,
183 dmadata->dma_addr +
184 dmadata->frag_count * dmadata->frag_bytes);
185 if (!desc)
186 return;
187 chan->device->device_issue_pending(chan);
188
189 spin_lock_irqsave(&dmadata->dma_lock, flags);
190 dmadata->frag_count++;
191 dmadata->frag_count %= dmadata->frags;
192 dmadata->pos += dmadata->frag_bytes;
193 dmadata->pos %= dmadata->buffer_bytes;
194 if ((dmadata->frag_count * dmadata->frag_bytes) %
195 dmadata->period_bytes == 0)
196 snd_pcm_period_elapsed(substream);
197 }
198 spin_unlock_irqrestore(&dmadata->dma_lock, flags);
199}
200
201static int txx9aclc_pcm_trigger(struct snd_pcm_substream *substream, int cmd)
202{
203 struct txx9aclc_dmadata *dmadata = substream->runtime->private_data;
204 struct snd_soc_pcm_runtime *rtd = substream->private_data;
205 struct txx9aclc_soc_device *dev =
206 container_of(rtd->socdev, struct txx9aclc_soc_device, soc_dev);
207 struct txx9aclc_plat_drvdata *drvdata = txx9aclc_get_plat_drvdata(dev);
208 void __iomem *base = drvdata->base;
209 unsigned long flags;
210 int ret = 0;
211 u32 ctlbit = substream->stream == SNDRV_PCM_STREAM_PLAYBACK ?
212 ACCTL_AUDODMA : ACCTL_AUDIDMA;
213
214 spin_lock_irqsave(&dmadata->dma_lock, flags);
215 switch (cmd) {
216 case SNDRV_PCM_TRIGGER_START:
217 dmadata->frag_count = -1;
218 tasklet_schedule(&dmadata->tasklet);
219 break;
220 case SNDRV_PCM_TRIGGER_STOP:
221 case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
222 case SNDRV_PCM_TRIGGER_SUSPEND:
223 __raw_writel(ctlbit, base + ACCTLDIS);
224 break;
225 case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
226 case SNDRV_PCM_TRIGGER_RESUME:
227 __raw_writel(ctlbit, base + ACCTLEN);
228 break;
229 default:
230 ret = -EINVAL;
231 }
232 spin_unlock_irqrestore(&dmadata->dma_lock, flags);
233 return ret;
234}
235
236static snd_pcm_uframes_t
237txx9aclc_pcm_pointer(struct snd_pcm_substream *substream)
238{
239 struct txx9aclc_dmadata *dmadata = substream->runtime->private_data;
240
241 return bytes_to_frames(substream->runtime, dmadata->pos);
242}
243
244static int txx9aclc_pcm_open(struct snd_pcm_substream *substream)
245{
246 struct snd_soc_pcm_runtime *rtd = substream->private_data;
247 struct txx9aclc_soc_device *dev =
248 container_of(rtd->socdev, struct txx9aclc_soc_device, soc_dev);
249 struct txx9aclc_dmadata *dmadata = &dev->dmadata[substream->stream];
250 int ret;
251
252 ret = snd_soc_set_runtime_hwparams(substream, &txx9aclc_pcm_hardware);
253 if (ret)
254 return ret;
255 /* ensure that buffer size is a multiple of period size */
256 ret = snd_pcm_hw_constraint_integer(substream->runtime,
257 SNDRV_PCM_HW_PARAM_PERIODS);
258 if (ret < 0)
259 return ret;
260 substream->runtime->private_data = dmadata;
261 return 0;
262}
263
264static int txx9aclc_pcm_close(struct snd_pcm_substream *substream)
265{
266 struct txx9aclc_dmadata *dmadata = substream->runtime->private_data;
267 struct dma_chan *chan = dmadata->dma_chan;
268
269 dmadata->frag_count = -1;
270 chan->device->device_terminate_all(chan);
271 return 0;
272}
273
274static struct snd_pcm_ops txx9aclc_pcm_ops = {
275 .open = txx9aclc_pcm_open,
276 .close = txx9aclc_pcm_close,
277 .ioctl = snd_pcm_lib_ioctl,
278 .hw_params = txx9aclc_pcm_hw_params,
279 .hw_free = txx9aclc_pcm_hw_free,
280 .prepare = txx9aclc_pcm_prepare,
281 .trigger = txx9aclc_pcm_trigger,
282 .pointer = txx9aclc_pcm_pointer,
283};
284
285static void txx9aclc_pcm_free_dma_buffers(struct snd_pcm *pcm)
286{
287 snd_pcm_lib_preallocate_free_for_all(pcm);
288}
289
290static int txx9aclc_pcm_new(struct snd_card *card, struct snd_soc_dai *dai,
291 struct snd_pcm *pcm)
292{
293 return snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV,
294 card->dev, 64 * 1024, 4 * 1024 * 1024);
295}
296
297static bool filter(struct dma_chan *chan, void *param)
298{
299 struct txx9aclc_dmadata *dmadata = param;
300 char *devname;
301 bool found = false;
302
303 devname = kasprintf(GFP_KERNEL, "%s.%d", dmadata->dma_res->name,
304 (int)dmadata->dma_res->start);
305 if (strcmp(dev_name(chan->device->dev), devname) == 0) {
306 chan->private = &dmadata->dma_slave;
307 found = true;
308 }
309 kfree(devname);
310 return found;
311}
312
313static int txx9aclc_dma_init(struct txx9aclc_soc_device *dev,
314 struct txx9aclc_dmadata *dmadata)
315{
316 struct txx9aclc_plat_drvdata *drvdata = txx9aclc_get_plat_drvdata(dev);
317 struct txx9dmac_slave *ds = &dmadata->dma_slave;
318 dma_cap_mask_t mask;
319
320 spin_lock_init(&dmadata->dma_lock);
321
322 ds->reg_width = sizeof(u32);
323 if (dmadata->stream == SNDRV_PCM_STREAM_PLAYBACK) {
324 ds->tx_reg = drvdata->physbase + ACAUDODAT;
325 ds->rx_reg = 0;
326 } else {
327 ds->tx_reg = 0;
328 ds->rx_reg = drvdata->physbase + ACAUDIDAT;
329 }
330
331 /* Try to grab a DMA channel */
332 dma_cap_zero(mask);
333 dma_cap_set(DMA_SLAVE, mask);
334 dmadata->dma_chan = dma_request_channel(mask, filter, dmadata);
335 if (!dmadata->dma_chan) {
336 dev_err(dev->soc_dev.dev,
337 "DMA channel for %s is not available\n",
338 dmadata->stream == SNDRV_PCM_STREAM_PLAYBACK ?
339 "playback" : "capture");
340 return -EBUSY;
341 }
342 tasklet_init(&dmadata->tasklet, txx9aclc_dma_tasklet,
343 (unsigned long)dmadata);
344 return 0;
345}
346
347static int txx9aclc_pcm_probe(struct platform_device *pdev)
348{
349 struct snd_soc_device *socdev = platform_get_drvdata(pdev);
350 struct txx9aclc_soc_device *dev =
351 container_of(socdev, struct txx9aclc_soc_device, soc_dev);
352 struct resource *r;
353 int i;
354 int ret;
355
356 dev->dmadata[0].stream = SNDRV_PCM_STREAM_PLAYBACK;
357 dev->dmadata[1].stream = SNDRV_PCM_STREAM_CAPTURE;
358 for (i = 0; i < 2; i++) {
359 r = platform_get_resource(dev->aclc_pdev, IORESOURCE_DMA, i);
360 if (!r) {
361 ret = -EBUSY;
362 goto exit;
363 }
364 dev->dmadata[i].dma_res = r;
365 ret = txx9aclc_dma_init(dev, &dev->dmadata[i]);
366 if (ret)
367 goto exit;
368 }
369 return 0;
370
371exit:
372 for (i = 0; i < 2; i++) {
373 if (dev->dmadata[i].dma_chan)
374 dma_release_channel(dev->dmadata[i].dma_chan);
375 dev->dmadata[i].dma_chan = NULL;
376 }
377 return ret;
378}
379
380static int txx9aclc_pcm_remove(struct platform_device *pdev)
381{
382 struct snd_soc_device *socdev = platform_get_drvdata(pdev);
383 struct txx9aclc_soc_device *dev =
384 container_of(socdev, struct txx9aclc_soc_device, soc_dev);
385 struct txx9aclc_plat_drvdata *drvdata = txx9aclc_get_plat_drvdata(dev);
386 void __iomem *base = drvdata->base;
387 int i;
388
389 /* disable all FIFO DMAs */
390 __raw_writel(ACCTL_AUDODMA | ACCTL_AUDIDMA, base + ACCTLDIS);
391 /* dummy R/W to clear pending DMAREQ if any */
392 __raw_writel(__raw_readl(base + ACAUDIDAT), base + ACAUDODAT);
393
394 for (i = 0; i < 2; i++) {
395 struct txx9aclc_dmadata *dmadata = &dev->dmadata[i];
396 struct dma_chan *chan = dmadata->dma_chan;
397 if (chan) {
398 dmadata->frag_count = -1;
399 chan->device->device_terminate_all(chan);
400 dma_release_channel(chan);
401 }
402 dev->dmadata[i].dma_chan = NULL;
403 }
404 return 0;
405}
406
407struct snd_soc_platform txx9aclc_soc_platform = {
408 .name = "txx9aclc-audio",
409 .probe = txx9aclc_pcm_probe,
410 .remove = txx9aclc_pcm_remove,
411 .pcm_ops = &txx9aclc_pcm_ops,
412 .pcm_new = txx9aclc_pcm_new,
413 .pcm_free = txx9aclc_pcm_free_dma_buffers,
414};
415EXPORT_SYMBOL_GPL(txx9aclc_soc_platform);
416
417static int __init txx9aclc_soc_platform_init(void)
418{
419 return snd_soc_register_platform(&txx9aclc_soc_platform);
420}
421
422static void __exit txx9aclc_soc_platform_exit(void)
423{
424 snd_soc_unregister_platform(&txx9aclc_soc_platform);
425}
426
427module_init(txx9aclc_soc_platform_init);
428module_exit(txx9aclc_soc_platform_exit);
429
430MODULE_AUTHOR("Atsushi Nemoto <anemo@mba.ocn.ne.jp>");
431MODULE_DESCRIPTION("TXx9 ACLC Audio DMA driver");
432MODULE_LICENSE("GPL");
diff --git a/sound/soc/txx9/txx9aclc.h b/sound/soc/txx9/txx9aclc.h
new file mode 100644
index 000000000000..6769aab41b33
--- /dev/null
+++ b/sound/soc/txx9/txx9aclc.h
@@ -0,0 +1,83 @@
1/*
2 * TXx9 SoC AC Link Controller
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License version 2 as
6 * published by the Free Software Foundation.
7 */
8
9#ifndef __TXX9ACLC_H
10#define __TXX9ACLC_H
11
12#include <linux/interrupt.h>
13#include <asm/txx9/dmac.h>
14
15#define ACCTLEN 0x00 /* control enable */
16#define ACCTLDIS 0x04 /* control disable */
17#define ACCTL_ENLINK 0x00000001 /* enable/disable AC-link */
18#define ACCTL_AUDODMA 0x00000100 /* AUDODMA enable/disable */
19#define ACCTL_AUDIDMA 0x00001000 /* AUDIDMA enable/disable */
20#define ACCTL_AUDOEHLT 0x00010000 /* AUDO error halt
21 enable/disable */
22#define ACCTL_AUDIEHLT 0x00100000 /* AUDI error halt
23 enable/disable */
24#define ACREGACC 0x08 /* codec register access */
25#define ACREGACC_DAT_SHIFT 0 /* data field */
26#define ACREGACC_REG_SHIFT 16 /* address field */
27#define ACREGACC_CODECID_SHIFT 24 /* CODEC ID field */
28#define ACREGACC_READ 0x80000000 /* CODEC read */
29#define ACREGACC_WRITE 0x00000000 /* CODEC write */
30#define ACINTSTS 0x10 /* interrupt status */
31#define ACINTMSTS 0x14 /* interrupt masked status */
32#define ACINTEN 0x18 /* interrupt enable */
33#define ACINTDIS 0x1c /* interrupt disable */
34#define ACINT_CODECRDY(n) (0x00000001 << (n)) /* CODECn ready */
35#define ACINT_REGACCRDY 0x00000010 /* ACREGACC ready */
36#define ACINT_AUDOERR 0x00000100 /* AUDO underrun error */
37#define ACINT_AUDIERR 0x00001000 /* AUDI overrun error */
38#define ACDMASTS 0x80 /* DMA request status */
39#define ACDMA_AUDO 0x00000001 /* AUDODMA pending */
40#define ACDMA_AUDI 0x00000010 /* AUDIDMA pending */
41#define ACAUDODAT 0xa0 /* audio out data */
42#define ACAUDIDAT 0xb0 /* audio in data */
43#define ACREVID 0xfc /* revision ID */
44
45struct txx9aclc_dmadata {
46 struct resource *dma_res;
47 struct txx9dmac_slave dma_slave;
48 struct dma_chan *dma_chan;
49 struct tasklet_struct tasklet;
50 spinlock_t dma_lock;
51 int stream; /* SNDRV_PCM_STREAM_PLAYBACK or SNDRV_PCM_STREAM_CAPTURE */
52 struct snd_pcm_substream *substream;
53 unsigned long pos;
54 dma_addr_t dma_addr;
55 unsigned long buffer_bytes;
56 unsigned long period_bytes;
57 unsigned long frag_bytes;
58 int frags;
59 int frag_count;
60 int dmacount;
61};
62
63struct txx9aclc_plat_drvdata {
64 void __iomem *base;
65 u64 physbase;
66};
67
68struct txx9aclc_soc_device {
69 struct snd_soc_device soc_dev;
70 struct platform_device *aclc_pdev; /* for ioresources, drvdata */
71 struct txx9aclc_dmadata dmadata[2];
72};
73
74static inline struct txx9aclc_plat_drvdata *txx9aclc_get_plat_drvdata(
75 struct txx9aclc_soc_device *sdev)
76{
77 return platform_get_drvdata(sdev->aclc_pdev);
78}
79
80extern struct snd_soc_platform txx9aclc_soc_platform;
81extern struct snd_soc_dai txx9aclc_ac97_dai;
82
83#endif /* __TXX9ACLC_H */