aboutsummaryrefslogtreecommitdiffstats
path: root/sound/soc
diff options
context:
space:
mode:
Diffstat (limited to 'sound/soc')
-rw-r--r--sound/soc/Kconfig2
-rw-r--r--sound/soc/Makefile2
-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/snd-soc-afeb9260.c203
-rw-r--r--sound/soc/blackfin/bf5xx-ac97.c9
-rw-r--r--sound/soc/blackfin/bf5xx-sport.c4
-rw-r--r--sound/soc/codecs/Kconfig24
-rw-r--r--sound/soc/codecs/Makefile12
-rw-r--r--sound/soc/codecs/ac97.c4
-rw-r--r--sound/soc/codecs/ad1980.c4
-rw-r--r--sound/soc/codecs/cs4270.c105
-rw-r--r--sound/soc/codecs/spdif_transciever.c71
-rw-r--r--sound/soc/codecs/spdif_transciever.h17
-rw-r--r--sound/soc/codecs/ssm2602.c33
-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/twl4030.c1116
-rw-r--r--sound/soc/codecs/twl4030.h43
-rw-r--r--sound/soc/codecs/uda134x.c4
-rw-r--r--sound/soc/codecs/wm8350.c2
-rw-r--r--sound/soc/codecs/wm8350.h1
-rw-r--r--sound/soc/codecs/wm8400.c8
-rw-r--r--sound/soc/codecs/wm8510.c2
-rw-r--r--sound/soc/codecs/wm8580.c4
-rw-r--r--sound/soc/codecs/wm8731.c4
-rw-r--r--sound/soc/codecs/wm8753.c6
-rw-r--r--sound/soc/codecs/wm8900.c6
-rw-r--r--sound/soc/codecs/wm8903.c119
-rw-r--r--sound/soc/codecs/wm8940.c955
-rw-r--r--sound/soc/codecs/wm8940.h104
-rw-r--r--sound/soc/codecs/wm8960.c969
-rw-r--r--sound/soc/codecs/wm8960.h127
-rw-r--r--sound/soc/codecs/wm8988.c1097
-rw-r--r--sound/soc/codecs/wm8988.h60
-rw-r--r--sound/soc/codecs/wm8990.c2
-rw-r--r--sound/soc/codecs/wm9081.c1534
-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/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.c564
-rw-r--r--sound/soc/fsl/mpc5200_dma.h80
-rw-r--r--sound/soc/fsl/mpc5200_psc_ac97.c329
-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/Kconfig8
-rw-r--r--sound/soc/omap/Makefile2
-rw-r--r--sound/soc/omap/n810.c7
-rw-r--r--sound/soc/omap/omap-mcbsp.c43
-rw-r--r--sound/soc/omap/omap-pcm.c9
-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.c94
-rw-r--r--sound/soc/pxa/Kconfig13
-rw-r--r--sound/soc/pxa/Makefile2
-rw-r--r--sound/soc/pxa/em-x270.c9
-rw-r--r--sound/soc/pxa/imote2.c114
-rw-r--r--sound/soc/pxa/magician.c13
-rw-r--r--sound/soc/pxa/pxa-ssp.c218
-rw-r--r--sound/soc/pxa/pxa2xx-i2s.c39
-rw-r--r--sound/soc/s3c24xx/s3c-i2s-v2.c91
-rw-r--r--sound/soc/s3c24xx/s3c2412-i2s.c2
-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-core.c165
-rw-r--r--sound/soc/soc-dapm.c427
-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.c430
-rw-r--r--sound/soc/txx9/txx9aclc.h83
92 files changed, 12359 insertions, 1606 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 0237879fd412..6f1e28de23cf 100644
--- a/sound/soc/Makefile
+++ b/sound/soc/Makefile
@@ -10,4 +10,6 @@ obj-$(CONFIG_SND_SOC) += fsl/
10obj-$(CONFIG_SND_SOC) += omap/ 10obj-$(CONFIG_SND_SOC) += omap/
11obj-$(CONFIG_SND_SOC) += pxa/ 11obj-$(CONFIG_SND_SOC) += pxa/
12obj-$(CONFIG_SND_SOC) += s3c24xx/ 12obj-$(CONFIG_SND_SOC) += s3c24xx/
13obj-$(CONFIG_SND_SOC) += s6000/
13obj-$(CONFIG_SND_SOC) += sh/ 14obj-$(CONFIG_SND_SOC) += sh/
15obj-$(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/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/bf5xx-ac97.c b/sound/soc/blackfin/bf5xx-ac97.c
index 8a935f2d1767..b1ed423fabd5 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
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/codecs/Kconfig b/sound/soc/codecs/Kconfig
index b6c7f7a01cb0..bbc97fd76648 100644
--- a/sound/soc/codecs/Kconfig
+++ b/sound/soc/codecs/Kconfig
@@ -18,7 +18,9 @@ config SND_SOC_ALL_CODECS
18 select SND_SOC_AK4535 if I2C 18 select SND_SOC_AK4535 if I2C
19 select SND_SOC_CS4270 if I2C 19 select SND_SOC_CS4270 if I2C
20 select SND_SOC_PCM3008 20 select SND_SOC_PCM3008
21 select SND_SOC_SPDIF
21 select SND_SOC_SSM2602 if I2C 22 select SND_SOC_SSM2602 if I2C
23 select SND_SOC_STAC9766 if SND_SOC_AC97_BUS
22 select SND_SOC_TLV320AIC23 if I2C 24 select SND_SOC_TLV320AIC23 if I2C
23 select SND_SOC_TLV320AIC26 if SPI_MASTER 25 select SND_SOC_TLV320AIC26 if SPI_MASTER
24 select SND_SOC_TLV320AIC3X if I2C 26 select SND_SOC_TLV320AIC3X if I2C
@@ -35,8 +37,12 @@ config SND_SOC_ALL_CODECS
35 select SND_SOC_WM8753 if SND_SOC_I2C_AND_SPI 37 select SND_SOC_WM8753 if SND_SOC_I2C_AND_SPI
36 select SND_SOC_WM8900 if I2C 38 select SND_SOC_WM8900 if I2C
37 select SND_SOC_WM8903 if I2C 39 select SND_SOC_WM8903 if I2C
40 select SND_SOC_WM8940 if I2C
41 select SND_SOC_WM8960 if I2C
38 select SND_SOC_WM8971 if I2C 42 select SND_SOC_WM8971 if I2C
43 select SND_SOC_WM8988 if SND_SOC_I2C_AND_SPI
39 select SND_SOC_WM8990 if I2C 44 select SND_SOC_WM8990 if I2C
45 select SND_SOC_WM9081 if I2C
40 select SND_SOC_WM9705 if SND_SOC_AC97_BUS 46 select SND_SOC_WM9705 if SND_SOC_AC97_BUS
41 select SND_SOC_WM9712 if SND_SOC_AC97_BUS 47 select SND_SOC_WM9712 if SND_SOC_AC97_BUS
42 select SND_SOC_WM9713 if SND_SOC_AC97_BUS 48 select SND_SOC_WM9713 if SND_SOC_AC97_BUS
@@ -86,9 +92,15 @@ config SND_SOC_L3
86config SND_SOC_PCM3008 92config SND_SOC_PCM3008
87 tristate 93 tristate
88 94
95config SND_SOC_SPDIF
96 tristate
97
89config SND_SOC_SSM2602 98config SND_SOC_SSM2602
90 tristate 99 tristate
91 100
101config SND_SOC_STAC9766
102 tristate
103
92config SND_SOC_TLV320AIC23 104config SND_SOC_TLV320AIC23
93 tristate 105 tristate
94 106
@@ -138,12 +150,24 @@ config SND_SOC_WM8900
138config SND_SOC_WM8903 150config SND_SOC_WM8903
139 tristate 151 tristate
140 152
153config SND_SOC_WM8940
154 tristate
155
156config SND_SOC_WM8960
157 tristate
158
141config SND_SOC_WM8971 159config SND_SOC_WM8971
142 tristate 160 tristate
143 161
162config SND_SOC_WM8988
163 tristate
164
144config SND_SOC_WM8990 165config SND_SOC_WM8990
145 tristate 166 tristate
146 167
168config SND_SOC_WM9081
169 tristate
170
147config SND_SOC_WM9705 171config SND_SOC_WM9705
148 tristate 172 tristate
149 173
diff --git a/sound/soc/codecs/Makefile b/sound/soc/codecs/Makefile
index f2653803ede8..8b7530546f4d 100644
--- a/sound/soc/codecs/Makefile
+++ b/sound/soc/codecs/Makefile
@@ -6,7 +6,9 @@ snd-soc-ak4535-objs := ak4535.o
6snd-soc-cs4270-objs := cs4270.o 6snd-soc-cs4270-objs := cs4270.o
7snd-soc-l3-objs := l3.o 7snd-soc-l3-objs := l3.o
8snd-soc-pcm3008-objs := pcm3008.o 8snd-soc-pcm3008-objs := pcm3008.o
9snd-soc-spdif-objs := spdif_transciever.o
9snd-soc-ssm2602-objs := ssm2602.o 10snd-soc-ssm2602-objs := ssm2602.o
11snd-soc-stac9766-objs := stac9766.o
10snd-soc-tlv320aic23-objs := tlv320aic23.o 12snd-soc-tlv320aic23-objs := tlv320aic23.o
11snd-soc-tlv320aic26-objs := tlv320aic26.o 13snd-soc-tlv320aic26-objs := tlv320aic26.o
12snd-soc-tlv320aic3x-objs := tlv320aic3x.o 14snd-soc-tlv320aic3x-objs := tlv320aic3x.o
@@ -23,8 +25,12 @@ snd-soc-wm8750-objs := wm8750.o
23snd-soc-wm8753-objs := wm8753.o 25snd-soc-wm8753-objs := wm8753.o
24snd-soc-wm8900-objs := wm8900.o 26snd-soc-wm8900-objs := wm8900.o
25snd-soc-wm8903-objs := wm8903.o 27snd-soc-wm8903-objs := wm8903.o
28snd-soc-wm8940-objs := wm8940.o
29snd-soc-wm8960-objs := wm8960.o
26snd-soc-wm8971-objs := wm8971.o 30snd-soc-wm8971-objs := wm8971.o
31snd-soc-wm8988-objs := wm8988.o
27snd-soc-wm8990-objs := wm8990.o 32snd-soc-wm8990-objs := wm8990.o
33snd-soc-wm9081-objs := wm9081.o
28snd-soc-wm9705-objs := wm9705.o 34snd-soc-wm9705-objs := wm9705.o
29snd-soc-wm9712-objs := wm9712.o 35snd-soc-wm9712-objs := wm9712.o
30snd-soc-wm9713-objs := wm9713.o 36snd-soc-wm9713-objs := wm9713.o
@@ -37,7 +43,9 @@ obj-$(CONFIG_SND_SOC_AK4535) += snd-soc-ak4535.o
37obj-$(CONFIG_SND_SOC_CS4270) += snd-soc-cs4270.o 43obj-$(CONFIG_SND_SOC_CS4270) += snd-soc-cs4270.o
38obj-$(CONFIG_SND_SOC_L3) += snd-soc-l3.o 44obj-$(CONFIG_SND_SOC_L3) += snd-soc-l3.o
39obj-$(CONFIG_SND_SOC_PCM3008) += snd-soc-pcm3008.o 45obj-$(CONFIG_SND_SOC_PCM3008) += snd-soc-pcm3008.o
46obj-$(CONFIG_SND_SOC_SPDIF) += snd-soc-spdif.o
40obj-$(CONFIG_SND_SOC_SSM2602) += snd-soc-ssm2602.o 47obj-$(CONFIG_SND_SOC_SSM2602) += snd-soc-ssm2602.o
48obj-$(CONFIG_SND_SOC_STAC9766) += snd-soc-stac9766.o
41obj-$(CONFIG_SND_SOC_TLV320AIC23) += snd-soc-tlv320aic23.o 49obj-$(CONFIG_SND_SOC_TLV320AIC23) += snd-soc-tlv320aic23.o
42obj-$(CONFIG_SND_SOC_TLV320AIC26) += snd-soc-tlv320aic26.o 50obj-$(CONFIG_SND_SOC_TLV320AIC26) += snd-soc-tlv320aic26.o
43obj-$(CONFIG_SND_SOC_TLV320AIC3X) += snd-soc-tlv320aic3x.o 51obj-$(CONFIG_SND_SOC_TLV320AIC3X) += snd-soc-tlv320aic3x.o
@@ -55,7 +63,11 @@ obj-$(CONFIG_SND_SOC_WM8753) += snd-soc-wm8753.o
55obj-$(CONFIG_SND_SOC_WM8900) += snd-soc-wm8900.o 63obj-$(CONFIG_SND_SOC_WM8900) += snd-soc-wm8900.o
56obj-$(CONFIG_SND_SOC_WM8903) += snd-soc-wm8903.o 64obj-$(CONFIG_SND_SOC_WM8903) += snd-soc-wm8903.o
57obj-$(CONFIG_SND_SOC_WM8971) += snd-soc-wm8971.o 65obj-$(CONFIG_SND_SOC_WM8971) += snd-soc-wm8971.o
66obj-$(CONFIG_SND_SOC_WM8940) += snd-soc-wm8940.o
67obj-$(CONFIG_SND_SOC_WM8960) += snd-soc-wm8960.o
68obj-$(CONFIG_SND_SOC_WM8988) += snd-soc-wm8988.o
58obj-$(CONFIG_SND_SOC_WM8990) += snd-soc-wm8990.o 69obj-$(CONFIG_SND_SOC_WM8990) += snd-soc-wm8990.o
70obj-$(CONFIG_SND_SOC_WM9081) += snd-soc-wm9081.o
59obj-$(CONFIG_SND_SOC_WM9705) += snd-soc-wm9705.o 71obj-$(CONFIG_SND_SOC_WM9705) += snd-soc-wm9705.o
60obj-$(CONFIG_SND_SOC_WM9712) += snd-soc-wm9712.o 72obj-$(CONFIG_SND_SOC_WM9712) += snd-soc-wm9712.o
61obj-$(CONFIG_SND_SOC_WM9713) += snd-soc-wm9713.o 73obj-$(CONFIG_SND_SOC_WM9713) += snd-soc-wm9713.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/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/cs4270.c b/sound/soc/codecs/cs4270.c
index 7fa09a387622..a32b8226c8a4 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,57 @@ 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 int reg = snd_soc_read(codec, CS4270_PWRCTL) | CS4270_PWRCTL_PDN_ALL;
810
811 return snd_soc_write(codec, CS4270_PWRCTL, reg);
812}
813
814static int cs4270_i2c_resume(struct i2c_client *client)
815{
816 struct cs4270_private *cs4270 = i2c_get_clientdata(client);
817 struct snd_soc_codec *codec = &cs4270->codec;
818 int reg;
819
820 /* In case the device was put to hard reset during sleep, we need to
821 * wait 500ns here before any I2C communication. */
822 ndelay(500);
823
824 /* first restore the entire register cache ... */
825 for (reg = CS4270_FIRSTREG; reg <= CS4270_LASTREG; reg++) {
826 u8 val = snd_soc_read(codec, reg);
827
828 if (i2c_smbus_write_byte_data(client, reg, val)) {
829 dev_err(codec->dev, "i2c write failed\n");
830 return -EIO;
831 }
832 }
833
834 /* ... then disable the power-down bits */
835 reg = snd_soc_read(codec, CS4270_PWRCTL);
836 reg &= ~CS4270_PWRCTL_PDN_ALL;
837
838 return snd_soc_write(codec, CS4270_PWRCTL, reg);
839}
840#else
841#define cs4270_i2c_suspend NULL
842#define cs4270_i2c_resume NULL
843#endif /* CONFIG_PM */
844
756/* 845/*
757 * cs4270_i2c_driver - I2C device identification 846 * cs4270_i2c_driver - I2C device identification
758 * 847 *
@@ -767,6 +856,8 @@ static struct i2c_driver cs4270_i2c_driver = {
767 .id_table = cs4270_id, 856 .id_table = cs4270_id,
768 .probe = cs4270_i2c_probe, 857 .probe = cs4270_i2c_probe,
769 .remove = cs4270_i2c_remove, 858 .remove = cs4270_i2c_remove,
859 .suspend = cs4270_i2c_suspend,
860 .resume = cs4270_i2c_resume,
770}; 861};
771 862
772/* 863/*
diff --git a/sound/soc/codecs/spdif_transciever.c b/sound/soc/codecs/spdif_transciever.c
new file mode 100644
index 000000000000..218b33adad90
--- /dev/null
+++ b/sound/soc/codecs/spdif_transciever.c
@@ -0,0 +1,71 @@
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
24#define STUB_RATES SNDRV_PCM_RATE_8000_96000
25#define STUB_FORMATS SNDRV_PCM_FMTBIT_S16_LE
26
27struct snd_soc_dai dit_stub_dai = {
28 .name = "DIT",
29 .playback = {
30 .stream_name = "Playback",
31 .channels_min = 1,
32 .channels_max = 384,
33 .rates = STUB_RATES,
34 .formats = STUB_FORMATS,
35 },
36};
37
38static int spdif_dit_probe(struct platform_device *pdev)
39{
40 dit_stub_dai.dev = &pdev->dev;
41 return snd_soc_register_dai(&dit_stub_dai);
42}
43
44static int spdif_dit_remove(struct platform_device *pdev)
45{
46 snd_soc_unregister_dai(&dit_stub_dai);
47 return 0;
48}
49
50static struct platform_driver spdif_dit_driver = {
51 .probe = spdif_dit_probe,
52 .remove = spdif_dit_remove,
53 .driver = {
54 .name = "spdif-dit",
55 .owner = THIS_MODULE,
56 },
57};
58
59static int __init dit_modinit(void)
60{
61 return platform_driver_register(&spdif_dit_driver);
62}
63
64static void __exit dit_exit(void)
65{
66 platform_driver_unregister(&spdif_dit_driver);
67}
68
69module_init(dit_modinit);
70module_exit(dit_exit);
71
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..1fc4c8e0899c 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,11 @@ 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
378 if (ssm2602->master_substream == substream)
379 ssm2602->master_substream = ssm2602->slave_substream;
380
381 ssm2602->slave_substream = NULL;
375 /* deactivate */ 382 /* deactivate */
376 if (!codec->active) 383 if (!codec->active)
377 ssm2602_write(codec, SSM2602_ACTIVE, 0); 384 ssm2602_write(codec, SSM2602_ACTIVE, 0);
@@ -497,11 +504,9 @@ static int ssm2602_set_bias_level(struct snd_soc_codec *codec,
497 return 0; 504 return 0;
498} 505}
499 506
500#define SSM2602_RATES (SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_11025 |\ 507#define SSM2602_RATES (SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_32000 |\
501 SNDRV_PCM_RATE_16000 | SNDRV_PCM_RATE_22050 |\ 508 SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_48000 |\
502 SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_44100 |\ 509 SNDRV_PCM_RATE_88200 | SNDRV_PCM_RATE_96000)
503 SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_88200 |\
504 SNDRV_PCM_RATE_96000)
505 510
506#define SSM2602_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE |\ 511#define SSM2602_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE |\
507 SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S32_LE) 512 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..8ad4b7b3e3ba
--- /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/twl4030.c b/sound/soc/codecs/twl4030.c
index df7c8c281d2f..4dbb853eef5a 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
@@ -232,7 +249,7 @@ static void twl4030_codec_mute(struct snd_soc_codec *codec, int mute)
232 TWL4030_REG_PRECKL_CTL); 249 TWL4030_REG_PRECKL_CTL);
233 reg_val = twl4030_read_reg_cache(codec, TWL4030_REG_PRECKR_CTL); 250 reg_val = twl4030_read_reg_cache(codec, TWL4030_REG_PRECKR_CTL);
234 twl4030_i2c_write_u8(TWL4030_MODULE_AUDIO_VOICE, 251 twl4030_i2c_write_u8(TWL4030_MODULE_AUDIO_VOICE,
235 reg_val & (~TWL4030_PRECKL_GAIN), 252 reg_val & (~TWL4030_PRECKR_GAIN),
236 TWL4030_REG_PRECKR_CTL); 253 TWL4030_REG_PRECKR_CTL);
237 254
238 /* Disable PLL */ 255 /* Disable PLL */
@@ -316,104 +333,60 @@ static void twl4030_power_down(struct snd_soc_codec *codec)
316} 333}
317 334
318/* Earpiece */ 335/* Earpiece */
319static const char *twl4030_earpiece_texts[] = 336static const struct snd_kcontrol_new twl4030_dapm_earpiece_controls[] = {
320 {"Off", "DACL1", "DACL2", "DACR1"}; 337 SOC_DAPM_SINGLE("Voice", TWL4030_REG_EAR_CTL, 0, 1, 0),
321 338 SOC_DAPM_SINGLE("AudioL1", TWL4030_REG_EAR_CTL, 1, 1, 0),
322static const unsigned int twl4030_earpiece_values[] = 339 SOC_DAPM_SINGLE("AudioL2", TWL4030_REG_EAR_CTL, 2, 1, 0),
323 {0x0, 0x1, 0x2, 0x4}; 340 SOC_DAPM_SINGLE("AudioR1", TWL4030_REG_EAR_CTL, 3, 1, 0),
324 341};
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 342
334/* PreDrive Left */ 343/* PreDrive Left */
335static const char *twl4030_predrivel_texts[] = 344static const struct snd_kcontrol_new twl4030_dapm_predrivel_controls[] = {
336 {"Off", "DACL1", "DACL2", "DACR2"}; 345 SOC_DAPM_SINGLE("Voice", TWL4030_REG_PREDL_CTL, 0, 1, 0),
337 346 SOC_DAPM_SINGLE("AudioL1", TWL4030_REG_PREDL_CTL, 1, 1, 0),
338static const unsigned int twl4030_predrivel_values[] = 347 SOC_DAPM_SINGLE("AudioL2", TWL4030_REG_PREDL_CTL, 2, 1, 0),
339 {0x0, 0x1, 0x2, 0x4}; 348 SOC_DAPM_SINGLE("AudioR2", TWL4030_REG_PREDL_CTL, 3, 1, 0),
340 349};
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 350
350/* PreDrive Right */ 351/* PreDrive Right */
351static const char *twl4030_predriver_texts[] = 352static const struct snd_kcontrol_new twl4030_dapm_predriver_controls[] = {
352 {"Off", "DACR1", "DACR2", "DACL2"}; 353 SOC_DAPM_SINGLE("Voice", TWL4030_REG_PREDR_CTL, 0, 1, 0),
353 354 SOC_DAPM_SINGLE("AudioR1", TWL4030_REG_PREDR_CTL, 1, 1, 0),
354static const unsigned int twl4030_predriver_values[] = 355 SOC_DAPM_SINGLE("AudioR2", TWL4030_REG_PREDR_CTL, 2, 1, 0),
355 {0x0, 0x1, 0x2, 0x4}; 356 SOC_DAPM_SINGLE("AudioL2", TWL4030_REG_PREDR_CTL, 3, 1, 0),
356 357};
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 358
366/* Headset Left */ 359/* Headset Left */
367static const char *twl4030_hsol_texts[] = 360static const struct snd_kcontrol_new twl4030_dapm_hsol_controls[] = {
368 {"Off", "DACL1", "DACL2"}; 361 SOC_DAPM_SINGLE("Voice", TWL4030_REG_HS_SEL, 0, 1, 0),
369 362 SOC_DAPM_SINGLE("AudioL1", TWL4030_REG_HS_SEL, 1, 1, 0),
370static const struct soc_enum twl4030_hsol_enum = 363 SOC_DAPM_SINGLE("AudioL2", TWL4030_REG_HS_SEL, 2, 1, 0),
371 SOC_ENUM_SINGLE(TWL4030_REG_HS_SEL, 1, 364};
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 365
378/* Headset Right */ 366/* Headset Right */
379static const char *twl4030_hsor_texts[] = 367static const struct snd_kcontrol_new twl4030_dapm_hsor_controls[] = {
380 {"Off", "DACR1", "DACR2"}; 368 SOC_DAPM_SINGLE("Voice", TWL4030_REG_HS_SEL, 3, 1, 0),
381 369 SOC_DAPM_SINGLE("AudioR1", TWL4030_REG_HS_SEL, 4, 1, 0),
382static const struct soc_enum twl4030_hsor_enum = 370 SOC_DAPM_SINGLE("AudioR2", TWL4030_REG_HS_SEL, 5, 1, 0),
383 SOC_ENUM_SINGLE(TWL4030_REG_HS_SEL, 4, 371};
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 372
390/* Carkit Left */ 373/* Carkit Left */
391static const char *twl4030_carkitl_texts[] = 374static const struct snd_kcontrol_new twl4030_dapm_carkitl_controls[] = {
392 {"Off", "DACL1", "DACL2"}; 375 SOC_DAPM_SINGLE("Voice", TWL4030_REG_PRECKL_CTL, 0, 1, 0),
393 376 SOC_DAPM_SINGLE("AudioL1", TWL4030_REG_PRECKL_CTL, 1, 1, 0),
394static const struct soc_enum twl4030_carkitl_enum = 377 SOC_DAPM_SINGLE("AudioL2", TWL4030_REG_PRECKL_CTL, 2, 1, 0),
395 SOC_ENUM_SINGLE(TWL4030_REG_PRECKL_CTL, 1, 378};
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 379
402/* Carkit Right */ 380/* Carkit Right */
403static const char *twl4030_carkitr_texts[] = 381static const struct snd_kcontrol_new twl4030_dapm_carkitr_controls[] = {
404 {"Off", "DACR1", "DACR2"}; 382 SOC_DAPM_SINGLE("Voice", TWL4030_REG_PRECKR_CTL, 0, 1, 0),
405 383 SOC_DAPM_SINGLE("AudioR1", TWL4030_REG_PRECKR_CTL, 1, 1, 0),
406static const struct soc_enum twl4030_carkitr_enum = 384 SOC_DAPM_SINGLE("AudioR2", TWL4030_REG_PRECKR_CTL, 2, 1, 0),
407 SOC_ENUM_SINGLE(TWL4030_REG_PRECKR_CTL, 1, 385};
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 386
414/* Handsfree Left */ 387/* Handsfree Left */
415static const char *twl4030_handsfreel_texts[] = 388static const char *twl4030_handsfreel_texts[] =
416 {"Voice", "DACL1", "DACL2", "DACR2"}; 389 {"Voice", "AudioL1", "AudioL2", "AudioR2"};
417 390
418static const struct soc_enum twl4030_handsfreel_enum = 391static const struct soc_enum twl4030_handsfreel_enum =
419 SOC_ENUM_SINGLE(TWL4030_REG_HFL_CTL, 0, 392 SOC_ENUM_SINGLE(TWL4030_REG_HFL_CTL, 0,
@@ -423,9 +396,13 @@ static const struct soc_enum twl4030_handsfreel_enum =
423static const struct snd_kcontrol_new twl4030_dapm_handsfreel_control = 396static const struct snd_kcontrol_new twl4030_dapm_handsfreel_control =
424SOC_DAPM_ENUM("Route", twl4030_handsfreel_enum); 397SOC_DAPM_ENUM("Route", twl4030_handsfreel_enum);
425 398
399/* Handsfree Left virtual mute */
400static const struct snd_kcontrol_new twl4030_dapm_handsfreelmute_control =
401 SOC_DAPM_SINGLE("Switch", TWL4030_REG_SW_SHADOW, 0, 1, 0);
402
426/* Handsfree Right */ 403/* Handsfree Right */
427static const char *twl4030_handsfreer_texts[] = 404static const char *twl4030_handsfreer_texts[] =
428 {"Voice", "DACR1", "DACR2", "DACL2"}; 405 {"Voice", "AudioR1", "AudioR2", "AudioL2"};
429 406
430static const struct soc_enum twl4030_handsfreer_enum = 407static const struct soc_enum twl4030_handsfreer_enum =
431 SOC_ENUM_SINGLE(TWL4030_REG_HFR_CTL, 0, 408 SOC_ENUM_SINGLE(TWL4030_REG_HFR_CTL, 0,
@@ -435,37 +412,48 @@ static const struct soc_enum twl4030_handsfreer_enum =
435static const struct snd_kcontrol_new twl4030_dapm_handsfreer_control = 412static const struct snd_kcontrol_new twl4030_dapm_handsfreer_control =
436SOC_DAPM_ENUM("Route", twl4030_handsfreer_enum); 413SOC_DAPM_ENUM("Route", twl4030_handsfreer_enum);
437 414
438/* Left analog microphone selection */ 415/* Handsfree Right virtual mute */
439static const char *twl4030_analoglmic_texts[] = 416static const struct snd_kcontrol_new twl4030_dapm_handsfreermute_control =
440 {"Off", "Main mic", "Headset mic", "AUXL", "Carkit mic"}; 417 SOC_DAPM_SINGLE("Switch", TWL4030_REG_SW_SHADOW, 1, 1, 0);
441 418
442static const unsigned int twl4030_analoglmic_values[] = 419/* Vibra */
443 {0x0, 0x1, 0x2, 0x4, 0x8}; 420/* Vibra audio path selection */
421static const char *twl4030_vibra_texts[] =
422 {"AudioL1", "AudioR1", "AudioL2", "AudioR2"};
444 423
445static const struct soc_enum twl4030_analoglmic_enum = 424static const struct soc_enum twl4030_vibra_enum =
446 SOC_VALUE_ENUM_SINGLE(TWL4030_REG_ANAMICL, 0, 0xf, 425 SOC_ENUM_SINGLE(TWL4030_REG_VIBRA_CTL, 2,
447 ARRAY_SIZE(twl4030_analoglmic_texts), 426 ARRAY_SIZE(twl4030_vibra_texts),
448 twl4030_analoglmic_texts, 427 twl4030_vibra_texts);
449 twl4030_analoglmic_values);
450 428
451static const struct snd_kcontrol_new twl4030_dapm_analoglmic_control = 429static const struct snd_kcontrol_new twl4030_dapm_vibra_control =
452SOC_DAPM_VALUE_ENUM("Route", twl4030_analoglmic_enum); 430SOC_DAPM_ENUM("Route", twl4030_vibra_enum);
453 431
454/* Right analog microphone selection */ 432/* Vibra path selection: local vibrator (PWM) or audio driven */
455static const char *twl4030_analogrmic_texts[] = 433static const char *twl4030_vibrapath_texts[] =
456 {"Off", "Sub mic", "AUXR"}; 434 {"Local vibrator", "Audio"};
457 435
458static const unsigned int twl4030_analogrmic_values[] = 436static const struct soc_enum twl4030_vibrapath_enum =
459 {0x0, 0x1, 0x4}; 437 SOC_ENUM_SINGLE(TWL4030_REG_VIBRA_CTL, 4,
438 ARRAY_SIZE(twl4030_vibrapath_texts),
439 twl4030_vibrapath_texts);
460 440
461static const struct soc_enum twl4030_analogrmic_enum = 441static const struct snd_kcontrol_new twl4030_dapm_vibrapath_control =
462 SOC_VALUE_ENUM_SINGLE(TWL4030_REG_ANAMICR, 0, 0x5, 442SOC_DAPM_ENUM("Route", twl4030_vibrapath_enum);
463 ARRAY_SIZE(twl4030_analogrmic_texts),
464 twl4030_analogrmic_texts,
465 twl4030_analogrmic_values);
466 443
467static const struct snd_kcontrol_new twl4030_dapm_analogrmic_control = 444/* Left analog microphone selection */
468SOC_DAPM_VALUE_ENUM("Route", twl4030_analogrmic_enum); 445static const struct snd_kcontrol_new twl4030_dapm_analoglmic_controls[] = {
446 SOC_DAPM_SINGLE("Main mic", TWL4030_REG_ANAMICL, 0, 1, 0),
447 SOC_DAPM_SINGLE("Headset mic", TWL4030_REG_ANAMICL, 1, 1, 0),
448 SOC_DAPM_SINGLE("AUXL", TWL4030_REG_ANAMICL, 2, 1, 0),
449 SOC_DAPM_SINGLE("Carkit mic", TWL4030_REG_ANAMICL, 3, 1, 0),
450};
451
452/* Right analog microphone selection */
453static const struct snd_kcontrol_new twl4030_dapm_analogrmic_controls[] = {
454 SOC_DAPM_SINGLE("Sub mic", TWL4030_REG_ANAMICR, 0, 1, 0),
455 SOC_DAPM_SINGLE("AUXR", TWL4030_REG_ANAMICR, 2, 1, 0),
456};
469 457
470/* TX1 L/R Analog/Digital microphone selection */ 458/* TX1 L/R Analog/Digital microphone selection */
471static const char *twl4030_micpathtx1_texts[] = 459static const char *twl4030_micpathtx1_texts[] =
@@ -507,6 +495,10 @@ static const struct snd_kcontrol_new twl4030_dapm_abypassr2_control =
507static const struct snd_kcontrol_new twl4030_dapm_abypassl2_control = 495static const struct snd_kcontrol_new twl4030_dapm_abypassl2_control =
508 SOC_DAPM_SINGLE("Switch", TWL4030_REG_ARXL2_APGA_CTL, 2, 1, 0); 496 SOC_DAPM_SINGLE("Switch", TWL4030_REG_ARXL2_APGA_CTL, 2, 1, 0);
509 497
498/* Analog bypass for Voice */
499static const struct snd_kcontrol_new twl4030_dapm_abypassv_control =
500 SOC_DAPM_SINGLE("Switch", TWL4030_REG_VDL_APGA_CTL, 2, 1, 0);
501
510/* Digital bypass gain, 0 mutes the bypass */ 502/* Digital bypass gain, 0 mutes the bypass */
511static const unsigned int twl4030_dapm_dbypass_tlv[] = { 503static const unsigned int twl4030_dapm_dbypass_tlv[] = {
512 TLV_DB_RANGE_HEAD(2), 504 TLV_DB_RANGE_HEAD(2),
@@ -526,6 +518,18 @@ static const struct snd_kcontrol_new twl4030_dapm_dbypassr_control =
526 TWL4030_REG_ATX2ARXPGA, 0, 7, 0, 518 TWL4030_REG_ATX2ARXPGA, 0, 7, 0,
527 twl4030_dapm_dbypass_tlv); 519 twl4030_dapm_dbypass_tlv);
528 520
521/*
522 * Voice Sidetone GAIN volume control:
523 * from -51 to -10 dB in 1 dB steps (mute instead of -51 dB)
524 */
525static DECLARE_TLV_DB_SCALE(twl4030_dapm_dbypassv_tlv, -5100, 100, 1);
526
527/* Digital bypass voice: sidetone (VUL -> VDL)*/
528static const struct snd_kcontrol_new twl4030_dapm_dbypassv_control =
529 SOC_DAPM_SINGLE_TLV("Volume",
530 TWL4030_REG_VSTPGA, 0, 0x29, 0,
531 twl4030_dapm_dbypassv_tlv);
532
529static int micpath_event(struct snd_soc_dapm_widget *w, 533static int micpath_event(struct snd_soc_dapm_widget *w,
530 struct snd_kcontrol *kcontrol, int event) 534 struct snd_kcontrol *kcontrol, int event)
531{ 535{
@@ -556,63 +560,143 @@ static int micpath_event(struct snd_soc_dapm_widget *w,
556 return 0; 560 return 0;
557} 561}
558 562
559static int handsfree_event(struct snd_soc_dapm_widget *w, 563static void handsfree_ramp(struct snd_soc_codec *codec, int reg, int ramp)
560 struct snd_kcontrol *kcontrol, int event)
561{ 564{
562 struct soc_enum *e = (struct soc_enum *)w->kcontrols->private_value;
563 unsigned char hs_ctl; 565 unsigned char hs_ctl;
564 566
565 hs_ctl = twl4030_read_reg_cache(w->codec, e->reg); 567 hs_ctl = twl4030_read_reg_cache(codec, reg);
566 568
567 if (hs_ctl & TWL4030_HF_CTL_REF_EN) { 569 if (ramp) {
570 /* HF ramp-up */
571 hs_ctl |= TWL4030_HF_CTL_REF_EN;
572 twl4030_write(codec, reg, hs_ctl);
573 udelay(10);
568 hs_ctl |= TWL4030_HF_CTL_RAMP_EN; 574 hs_ctl |= TWL4030_HF_CTL_RAMP_EN;
569 twl4030_write(w->codec, e->reg, hs_ctl); 575 twl4030_write(codec, reg, hs_ctl);
576 udelay(40);
570 hs_ctl |= TWL4030_HF_CTL_LOOP_EN; 577 hs_ctl |= TWL4030_HF_CTL_LOOP_EN;
571 twl4030_write(w->codec, e->reg, hs_ctl);
572 hs_ctl |= TWL4030_HF_CTL_HB_EN; 578 hs_ctl |= TWL4030_HF_CTL_HB_EN;
573 twl4030_write(w->codec, e->reg, hs_ctl); 579 twl4030_write(codec, reg, hs_ctl);
574 } else { 580 } else {
575 hs_ctl &= ~(TWL4030_HF_CTL_RAMP_EN | TWL4030_HF_CTL_LOOP_EN 581 /* HF ramp-down */
576 | TWL4030_HF_CTL_HB_EN); 582 hs_ctl &= ~TWL4030_HF_CTL_LOOP_EN;
577 twl4030_write(w->codec, e->reg, hs_ctl); 583 hs_ctl &= ~TWL4030_HF_CTL_HB_EN;
584 twl4030_write(codec, reg, hs_ctl);
585 hs_ctl &= ~TWL4030_HF_CTL_RAMP_EN;
586 twl4030_write(codec, reg, hs_ctl);
587 udelay(40);
588 hs_ctl &= ~TWL4030_HF_CTL_REF_EN;
589 twl4030_write(codec, reg, hs_ctl);
578 } 590 }
591}
579 592
593static int handsfreelpga_event(struct snd_soc_dapm_widget *w,
594 struct snd_kcontrol *kcontrol, int event)
595{
596 switch (event) {
597 case SND_SOC_DAPM_POST_PMU:
598 handsfree_ramp(w->codec, TWL4030_REG_HFL_CTL, 1);
599 break;
600 case SND_SOC_DAPM_POST_PMD:
601 handsfree_ramp(w->codec, TWL4030_REG_HFL_CTL, 0);
602 break;
603 }
580 return 0; 604 return 0;
581} 605}
582 606
583static int headsetl_event(struct snd_soc_dapm_widget *w, 607static int handsfreerpga_event(struct snd_soc_dapm_widget *w,
584 struct snd_kcontrol *kcontrol, int event) 608 struct snd_kcontrol *kcontrol, int event)
585{ 609{
610 switch (event) {
611 case SND_SOC_DAPM_POST_PMU:
612 handsfree_ramp(w->codec, TWL4030_REG_HFR_CTL, 1);
613 break;
614 case SND_SOC_DAPM_POST_PMD:
615 handsfree_ramp(w->codec, TWL4030_REG_HFR_CTL, 0);
616 break;
617 }
618 return 0;
619}
620
621static void headset_ramp(struct snd_soc_codec *codec, int ramp)
622{
586 unsigned char hs_gain, hs_pop; 623 unsigned char hs_gain, hs_pop;
624 struct twl4030_priv *twl4030 = codec->private_data;
625 /* Base values for ramp delay calculation: 2^19 - 2^26 */
626 unsigned int ramp_base[] = {524288, 1048576, 2097152, 4194304,
627 8388608, 16777216, 33554432, 67108864};
587 628
588 /* Save the current volume */ 629 hs_gain = twl4030_read_reg_cache(codec, TWL4030_REG_HS_GAIN_SET);
589 hs_gain = twl4030_read_reg_cache(w->codec, TWL4030_REG_HS_GAIN_SET); 630 hs_pop = twl4030_read_reg_cache(codec, TWL4030_REG_HS_POPN_SET);
590 hs_pop = twl4030_read_reg_cache(w->codec, TWL4030_REG_HS_POPN_SET);
591 631
592 switch (event) { 632 if (ramp) {
593 case SND_SOC_DAPM_POST_PMU: 633 /* Headset ramp-up according to the TRM */
594 /* Do the anti-pop/bias ramp enable according to the TRM */
595 hs_pop |= TWL4030_VMID_EN; 634 hs_pop |= TWL4030_VMID_EN;
596 twl4030_write(w->codec, TWL4030_REG_HS_POPN_SET, hs_pop); 635 twl4030_write(codec, TWL4030_REG_HS_POPN_SET, hs_pop);
597 /* Is this needed? Can we just use whatever gain here? */ 636 twl4030_write(codec, TWL4030_REG_HS_GAIN_SET, hs_gain);
598 twl4030_write(w->codec, TWL4030_REG_HS_GAIN_SET,
599 (hs_gain & (~0x0f)) | 0x0a);
600 hs_pop |= TWL4030_RAMP_EN; 637 hs_pop |= TWL4030_RAMP_EN;
601 twl4030_write(w->codec, TWL4030_REG_HS_POPN_SET, hs_pop); 638 twl4030_write(codec, TWL4030_REG_HS_POPN_SET, hs_pop);
602 639 } else {
603 /* Restore the original volume */ 640 /* Headset ramp-down _not_ according to
604 twl4030_write(w->codec, TWL4030_REG_HS_GAIN_SET, hs_gain); 641 * the TRM, but in a way that it is working */
605 break;
606 case SND_SOC_DAPM_POST_PMD:
607 /* Do the anti-pop/bias ramp disable according to the TRM */
608 hs_pop &= ~TWL4030_RAMP_EN; 642 hs_pop &= ~TWL4030_RAMP_EN;
609 twl4030_write(w->codec, TWL4030_REG_HS_POPN_SET, hs_pop); 643 twl4030_write(codec, TWL4030_REG_HS_POPN_SET, hs_pop);
644 /* Wait ramp delay time + 1, so the VMID can settle */
645 mdelay((ramp_base[(hs_pop & TWL4030_RAMP_DELAY) >> 2] /
646 twl4030->sysclk) + 1);
610 /* Bypass the reg_cache to mute the headset */ 647 /* Bypass the reg_cache to mute the headset */
611 twl4030_i2c_write_u8(TWL4030_MODULE_AUDIO_VOICE, 648 twl4030_i2c_write_u8(TWL4030_MODULE_AUDIO_VOICE,
612 hs_gain & (~0x0f), 649 hs_gain & (~0x0f),
613 TWL4030_REG_HS_GAIN_SET); 650 TWL4030_REG_HS_GAIN_SET);
651
614 hs_pop &= ~TWL4030_VMID_EN; 652 hs_pop &= ~TWL4030_VMID_EN;
615 twl4030_write(w->codec, TWL4030_REG_HS_POPN_SET, hs_pop); 653 twl4030_write(codec, TWL4030_REG_HS_POPN_SET, hs_pop);
654 }
655}
656
657static int headsetlpga_event(struct snd_soc_dapm_widget *w,
658 struct snd_kcontrol *kcontrol, int event)
659{
660 struct twl4030_priv *twl4030 = w->codec->private_data;
661
662 switch (event) {
663 case SND_SOC_DAPM_POST_PMU:
664 /* Do the ramp-up only once */
665 if (!twl4030->hsr_enabled)
666 headset_ramp(w->codec, 1);
667
668 twl4030->hsl_enabled = 1;
669 break;
670 case SND_SOC_DAPM_POST_PMD:
671 /* Do the ramp-down only if both headsetL/R is disabled */
672 if (!twl4030->hsr_enabled)
673 headset_ramp(w->codec, 0);
674
675 twl4030->hsl_enabled = 0;
676 break;
677 }
678 return 0;
679}
680
681static int headsetrpga_event(struct snd_soc_dapm_widget *w,
682 struct snd_kcontrol *kcontrol, int event)
683{
684 struct twl4030_priv *twl4030 = w->codec->private_data;
685
686 switch (event) {
687 case SND_SOC_DAPM_POST_PMU:
688 /* Do the ramp-up only once */
689 if (!twl4030->hsl_enabled)
690 headset_ramp(w->codec, 1);
691
692 twl4030->hsr_enabled = 1;
693 break;
694 case SND_SOC_DAPM_POST_PMD:
695 /* Do the ramp-down only if both headsetL/R is disabled */
696 if (!twl4030->hsl_enabled)
697 headset_ramp(w->codec, 0);
698
699 twl4030->hsr_enabled = 0;
616 break; 700 break;
617 } 701 }
618 return 0; 702 return 0;
@@ -624,7 +708,7 @@ static int bypass_event(struct snd_soc_dapm_widget *w,
624 struct soc_mixer_control *m = 708 struct soc_mixer_control *m =
625 (struct soc_mixer_control *)w->kcontrols->private_value; 709 (struct soc_mixer_control *)w->kcontrols->private_value;
626 struct twl4030_priv *twl4030 = w->codec->private_data; 710 struct twl4030_priv *twl4030 = w->codec->private_data;
627 unsigned char reg; 711 unsigned char reg, misc;
628 712
629 reg = twl4030_read_reg_cache(w->codec, m->reg); 713 reg = twl4030_read_reg_cache(w->codec, m->reg);
630 714
@@ -636,14 +720,34 @@ static int bypass_event(struct snd_soc_dapm_widget *w,
636 else 720 else
637 twl4030->bypass_state &= 721 twl4030->bypass_state &=
638 ~(1 << (m->reg - TWL4030_REG_ARXL1_APGA_CTL)); 722 ~(1 << (m->reg - TWL4030_REG_ARXL1_APGA_CTL));
723 } else if (m->reg == TWL4030_REG_VDL_APGA_CTL) {
724 /* Analog voice bypass */
725 if (reg & (1 << m->shift))
726 twl4030->bypass_state |= (1 << 4);
727 else
728 twl4030->bypass_state &= ~(1 << 4);
729 } else if (m->reg == TWL4030_REG_VSTPGA) {
730 /* Voice digital bypass */
731 if (reg)
732 twl4030->bypass_state |= (1 << 5);
733 else
734 twl4030->bypass_state &= ~(1 << 5);
639 } else { 735 } else {
640 /* Digital bypass */ 736 /* Digital bypass */
641 if (reg & (0x7 << m->shift)) 737 if (reg & (0x7 << m->shift))
642 twl4030->bypass_state |= (1 << (m->shift ? 5 : 4)); 738 twl4030->bypass_state |= (1 << (m->shift ? 7 : 6));
643 else 739 else
644 twl4030->bypass_state &= ~(1 << (m->shift ? 5 : 4)); 740 twl4030->bypass_state &= ~(1 << (m->shift ? 7 : 6));
645 } 741 }
646 742
743 /* Enable master analog loopback mode if any analog switch is enabled*/
744 misc = twl4030_read_reg_cache(w->codec, TWL4030_REG_MISC_SET_1);
745 if (twl4030->bypass_state & 0x1F)
746 misc |= TWL4030_FMLOOP_EN;
747 else
748 misc &= ~TWL4030_FMLOOP_EN;
749 twl4030_write(w->codec, TWL4030_REG_MISC_SET_1, misc);
750
647 if (w->codec->bias_level == SND_SOC_BIAS_STANDBY) { 751 if (w->codec->bias_level == SND_SOC_BIAS_STANDBY) {
648 if (twl4030->bypass_state) 752 if (twl4030->bypass_state)
649 twl4030_codec_mute(w->codec, 0); 753 twl4030_codec_mute(w->codec, 0);
@@ -810,6 +914,48 @@ static int snd_soc_put_volsw_r2_twl4030(struct snd_kcontrol *kcontrol,
810 return err; 914 return err;
811} 915}
812 916
917/* Codec operation modes */
918static const char *twl4030_op_modes_texts[] = {
919 "Option 2 (voice/audio)", "Option 1 (audio)"
920};
921
922static const struct soc_enum twl4030_op_modes_enum =
923 SOC_ENUM_SINGLE(TWL4030_REG_CODEC_MODE, 0,
924 ARRAY_SIZE(twl4030_op_modes_texts),
925 twl4030_op_modes_texts);
926
927int snd_soc_put_twl4030_opmode_enum_double(struct snd_kcontrol *kcontrol,
928 struct snd_ctl_elem_value *ucontrol)
929{
930 struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
931 struct twl4030_priv *twl4030 = codec->private_data;
932 struct soc_enum *e = (struct soc_enum *)kcontrol->private_value;
933 unsigned short val;
934 unsigned short mask, bitmask;
935
936 if (twl4030->configured) {
937 printk(KERN_ERR "twl4030 operation mode cannot be "
938 "changed on-the-fly\n");
939 return -EBUSY;
940 }
941
942 for (bitmask = 1; bitmask < e->max; bitmask <<= 1)
943 ;
944 if (ucontrol->value.enumerated.item[0] > e->max - 1)
945 return -EINVAL;
946
947 val = ucontrol->value.enumerated.item[0] << e->shift_l;
948 mask = (bitmask - 1) << e->shift_l;
949 if (e->shift_l != e->shift_r) {
950 if (ucontrol->value.enumerated.item[1] > e->max - 1)
951 return -EINVAL;
952 val |= ucontrol->value.enumerated.item[1] << e->shift_r;
953 mask |= (bitmask - 1) << e->shift_r;
954 }
955
956 return snd_soc_update_bits(codec, e->reg, mask, val);
957}
958
813/* 959/*
814 * FGAIN volume control: 960 * FGAIN volume control:
815 * from -62 to 0 dB in 1 dB steps (mute instead of -63 dB) 961 * from -62 to 0 dB in 1 dB steps (mute instead of -63 dB)
@@ -824,6 +970,12 @@ static DECLARE_TLV_DB_SCALE(digital_fine_tlv, -6300, 100, 1);
824static DECLARE_TLV_DB_SCALE(digital_coarse_tlv, 0, 600, 0); 970static DECLARE_TLV_DB_SCALE(digital_coarse_tlv, 0, 600, 0);
825 971
826/* 972/*
973 * Voice Downlink GAIN volume control:
974 * from -37 to 12 dB in 1 dB steps (mute instead of -37 dB)
975 */
976static DECLARE_TLV_DB_SCALE(digital_voice_downlink_tlv, -3700, 100, 1);
977
978/*
827 * Analog playback gain 979 * Analog playback gain
828 * -24 dB to 12 dB in 2 dB steps 980 * -24 dB to 12 dB in 2 dB steps
829 */ 981 */
@@ -864,7 +1016,32 @@ static const struct soc_enum twl4030_rampdelay_enum =
864 ARRAY_SIZE(twl4030_rampdelay_texts), 1016 ARRAY_SIZE(twl4030_rampdelay_texts),
865 twl4030_rampdelay_texts); 1017 twl4030_rampdelay_texts);
866 1018
1019/* Vibra H-bridge direction mode */
1020static const char *twl4030_vibradirmode_texts[] = {
1021 "Vibra H-bridge direction", "Audio data MSB",
1022};
1023
1024static const struct soc_enum twl4030_vibradirmode_enum =
1025 SOC_ENUM_SINGLE(TWL4030_REG_VIBRA_CTL, 5,
1026 ARRAY_SIZE(twl4030_vibradirmode_texts),
1027 twl4030_vibradirmode_texts);
1028
1029/* Vibra H-bridge direction */
1030static const char *twl4030_vibradir_texts[] = {
1031 "Positive polarity", "Negative polarity",
1032};
1033
1034static const struct soc_enum twl4030_vibradir_enum =
1035 SOC_ENUM_SINGLE(TWL4030_REG_VIBRA_CTL, 1,
1036 ARRAY_SIZE(twl4030_vibradir_texts),
1037 twl4030_vibradir_texts);
1038
867static const struct snd_kcontrol_new twl4030_snd_controls[] = { 1039static const struct snd_kcontrol_new twl4030_snd_controls[] = {
1040 /* Codec operation mode control */
1041 SOC_ENUM_EXT("Codec Operation Mode", twl4030_op_modes_enum,
1042 snd_soc_get_enum_double,
1043 snd_soc_put_twl4030_opmode_enum_double),
1044
868 /* Common playback gain controls */ 1045 /* Common playback gain controls */
869 SOC_DOUBLE_R_TLV("DAC1 Digital Fine Playback Volume", 1046 SOC_DOUBLE_R_TLV("DAC1 Digital Fine Playback Volume",
870 TWL4030_REG_ARXL1PGA, TWL4030_REG_ARXR1PGA, 1047 TWL4030_REG_ARXL1PGA, TWL4030_REG_ARXR1PGA,
@@ -893,6 +1070,16 @@ static const struct snd_kcontrol_new twl4030_snd_controls[] = {
893 TWL4030_REG_ARXL2_APGA_CTL, TWL4030_REG_ARXR2_APGA_CTL, 1070 TWL4030_REG_ARXL2_APGA_CTL, TWL4030_REG_ARXR2_APGA_CTL,
894 1, 1, 0), 1071 1, 1, 0),
895 1072
1073 /* Common voice downlink gain controls */
1074 SOC_SINGLE_TLV("DAC Voice Digital Downlink Volume",
1075 TWL4030_REG_VRXPGA, 0, 0x31, 0, digital_voice_downlink_tlv),
1076
1077 SOC_SINGLE_TLV("DAC Voice Analog Downlink Volume",
1078 TWL4030_REG_VDL_APGA_CTL, 3, 0x12, 1, analog_tlv),
1079
1080 SOC_SINGLE("DAC Voice Analog Downlink Switch",
1081 TWL4030_REG_VDL_APGA_CTL, 1, 1, 0),
1082
896 /* Separate output gain controls */ 1083 /* Separate output gain controls */
897 SOC_DOUBLE_R_TLV_TWL4030("PreDriv Playback Volume", 1084 SOC_DOUBLE_R_TLV_TWL4030("PreDriv Playback Volume",
898 TWL4030_REG_PREDL_CTL, TWL4030_REG_PREDR_CTL, 1085 TWL4030_REG_PREDL_CTL, TWL4030_REG_PREDR_CTL,
@@ -920,6 +1107,9 @@ static const struct snd_kcontrol_new twl4030_snd_controls[] = {
920 0, 3, 5, 0, input_gain_tlv), 1107 0, 3, 5, 0, input_gain_tlv),
921 1108
922 SOC_ENUM("HS ramp delay", twl4030_rampdelay_enum), 1109 SOC_ENUM("HS ramp delay", twl4030_rampdelay_enum),
1110
1111 SOC_ENUM("Vibra H-bridge mode", twl4030_vibradirmode_enum),
1112 SOC_ENUM("Vibra H-bridge direction", twl4030_vibradir_enum),
923}; 1113};
924 1114
925static const struct snd_soc_dapm_widget twl4030_dapm_widgets[] = { 1115static const struct snd_soc_dapm_widget twl4030_dapm_widgets[] = {
@@ -947,26 +1137,19 @@ static const struct snd_soc_dapm_widget twl4030_dapm_widgets[] = {
947 SND_SOC_DAPM_OUTPUT("CARKITR"), 1137 SND_SOC_DAPM_OUTPUT("CARKITR"),
948 SND_SOC_DAPM_OUTPUT("HFL"), 1138 SND_SOC_DAPM_OUTPUT("HFL"),
949 SND_SOC_DAPM_OUTPUT("HFR"), 1139 SND_SOC_DAPM_OUTPUT("HFR"),
1140 SND_SOC_DAPM_OUTPUT("VIBRA"),
950 1141
951 /* DACs */ 1142 /* DACs */
952 SND_SOC_DAPM_DAC("DAC Right1", "Right Front Playback", 1143 SND_SOC_DAPM_DAC("DAC Right1", "Right Front HiFi Playback",
953 SND_SOC_NOPM, 0, 0), 1144 SND_SOC_NOPM, 0, 0),
954 SND_SOC_DAPM_DAC("DAC Left1", "Left Front Playback", 1145 SND_SOC_DAPM_DAC("DAC Left1", "Left Front HiFi Playback",
955 SND_SOC_NOPM, 0, 0), 1146 SND_SOC_NOPM, 0, 0),
956 SND_SOC_DAPM_DAC("DAC Right2", "Right Rear Playback", 1147 SND_SOC_DAPM_DAC("DAC Right2", "Right Rear HiFi Playback",
957 SND_SOC_NOPM, 0, 0), 1148 SND_SOC_NOPM, 0, 0),
958 SND_SOC_DAPM_DAC("DAC Left2", "Left Rear Playback", 1149 SND_SOC_DAPM_DAC("DAC Left2", "Left Rear HiFi Playback",
1150 SND_SOC_NOPM, 0, 0),
1151 SND_SOC_DAPM_DAC("DAC Voice", "Voice Playback",
959 SND_SOC_NOPM, 0, 0), 1152 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 1153
971 /* Analog bypasses */ 1154 /* Analog bypasses */
972 SND_SOC_DAPM_SWITCH_E("Right1 Analog Loopback", SND_SOC_NOPM, 0, 0, 1155 SND_SOC_DAPM_SWITCH_E("Right1 Analog Loopback", SND_SOC_NOPM, 0, 0,
@@ -981,6 +1164,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, 1164 SND_SOC_DAPM_SWITCH_E("Left2 Analog Loopback", SND_SOC_NOPM, 0, 0,
982 &twl4030_dapm_abypassl2_control, 1165 &twl4030_dapm_abypassl2_control,
983 bypass_event, SND_SOC_DAPM_POST_REG), 1166 bypass_event, SND_SOC_DAPM_POST_REG),
1167 SND_SOC_DAPM_SWITCH_E("Voice Analog Loopback", SND_SOC_NOPM, 0, 0,
1168 &twl4030_dapm_abypassv_control,
1169 bypass_event, SND_SOC_DAPM_POST_REG),
984 1170
985 /* Digital bypasses */ 1171 /* Digital bypasses */
986 SND_SOC_DAPM_SWITCH_E("Left Digital Loopback", SND_SOC_NOPM, 0, 0, 1172 SND_SOC_DAPM_SWITCH_E("Left Digital Loopback", SND_SOC_NOPM, 0, 0,
@@ -989,43 +1175,88 @@ static const struct snd_soc_dapm_widget twl4030_dapm_widgets[] = {
989 SND_SOC_DAPM_SWITCH_E("Right Digital Loopback", SND_SOC_NOPM, 0, 0, 1175 SND_SOC_DAPM_SWITCH_E("Right Digital Loopback", SND_SOC_NOPM, 0, 0,
990 &twl4030_dapm_dbypassr_control, bypass_event, 1176 &twl4030_dapm_dbypassr_control, bypass_event,
991 SND_SOC_DAPM_POST_REG), 1177 SND_SOC_DAPM_POST_REG),
1178 SND_SOC_DAPM_SWITCH_E("Voice Digital Loopback", SND_SOC_NOPM, 0, 0,
1179 &twl4030_dapm_dbypassv_control, bypass_event,
1180 SND_SOC_DAPM_POST_REG),
992 1181
993 SND_SOC_DAPM_MIXER("Analog R1 Playback Mixer", TWL4030_REG_AVDAC_CTL, 1182 /* Digital mixers, power control for the physical DACs */
994 0, 0, NULL, 0), 1183 SND_SOC_DAPM_MIXER("Digital R1 Playback Mixer",
995 SND_SOC_DAPM_MIXER("Analog L1 Playback Mixer", TWL4030_REG_AVDAC_CTL, 1184 TWL4030_REG_AVDAC_CTL, 0, 0, NULL, 0),
996 1, 0, NULL, 0), 1185 SND_SOC_DAPM_MIXER("Digital L1 Playback Mixer",
997 SND_SOC_DAPM_MIXER("Analog R2 Playback Mixer", TWL4030_REG_AVDAC_CTL, 1186 TWL4030_REG_AVDAC_CTL, 1, 0, NULL, 0),
998 2, 0, NULL, 0), 1187 SND_SOC_DAPM_MIXER("Digital R2 Playback Mixer",
999 SND_SOC_DAPM_MIXER("Analog L2 Playback Mixer", TWL4030_REG_AVDAC_CTL, 1188 TWL4030_REG_AVDAC_CTL, 2, 0, NULL, 0),
1000 3, 0, NULL, 0), 1189 SND_SOC_DAPM_MIXER("Digital L2 Playback Mixer",
1001 1190 TWL4030_REG_AVDAC_CTL, 3, 0, NULL, 0),
1002 /* Output MUX controls */ 1191 SND_SOC_DAPM_MIXER("Digital Voice Playback Mixer",
1192 TWL4030_REG_AVDAC_CTL, 4, 0, NULL, 0),
1193
1194 /* Analog mixers, power control for the physical PGAs */
1195 SND_SOC_DAPM_MIXER("Analog R1 Playback Mixer",
1196 TWL4030_REG_ARXR1_APGA_CTL, 0, 0, NULL, 0),
1197 SND_SOC_DAPM_MIXER("Analog L1 Playback Mixer",
1198 TWL4030_REG_ARXL1_APGA_CTL, 0, 0, NULL, 0),
1199 SND_SOC_DAPM_MIXER("Analog R2 Playback Mixer",
1200 TWL4030_REG_ARXR2_APGA_CTL, 0, 0, NULL, 0),
1201 SND_SOC_DAPM_MIXER("Analog L2 Playback Mixer",
1202 TWL4030_REG_ARXL2_APGA_CTL, 0, 0, NULL, 0),
1203 SND_SOC_DAPM_MIXER("Analog Voice Playback Mixer",
1204 TWL4030_REG_VDL_APGA_CTL, 0, 0, NULL, 0),
1205
1206 /* Output MIXER controls */
1003 /* Earpiece */ 1207 /* Earpiece */
1004 SND_SOC_DAPM_VALUE_MUX("Earpiece Mux", SND_SOC_NOPM, 0, 0, 1208 SND_SOC_DAPM_MIXER("Earpiece Mixer", SND_SOC_NOPM, 0, 0,
1005 &twl4030_dapm_earpiece_control), 1209 &twl4030_dapm_earpiece_controls[0],
1210 ARRAY_SIZE(twl4030_dapm_earpiece_controls)),
1006 /* PreDrivL/R */ 1211 /* PreDrivL/R */
1007 SND_SOC_DAPM_VALUE_MUX("PredriveL Mux", SND_SOC_NOPM, 0, 0, 1212 SND_SOC_DAPM_MIXER("PredriveL Mixer", SND_SOC_NOPM, 0, 0,
1008 &twl4030_dapm_predrivel_control), 1213 &twl4030_dapm_predrivel_controls[0],
1009 SND_SOC_DAPM_VALUE_MUX("PredriveR Mux", SND_SOC_NOPM, 0, 0, 1214 ARRAY_SIZE(twl4030_dapm_predrivel_controls)),
1010 &twl4030_dapm_predriver_control), 1215 SND_SOC_DAPM_MIXER("PredriveR Mixer", SND_SOC_NOPM, 0, 0,
1216 &twl4030_dapm_predriver_controls[0],
1217 ARRAY_SIZE(twl4030_dapm_predriver_controls)),
1011 /* HeadsetL/R */ 1218 /* HeadsetL/R */
1012 SND_SOC_DAPM_MUX_E("HeadsetL Mux", SND_SOC_NOPM, 0, 0, 1219 SND_SOC_DAPM_MIXER("HeadsetL Mixer", SND_SOC_NOPM, 0, 0,
1013 &twl4030_dapm_hsol_control, headsetl_event, 1220 &twl4030_dapm_hsol_controls[0],
1014 SND_SOC_DAPM_POST_PMU|SND_SOC_DAPM_POST_PMD), 1221 ARRAY_SIZE(twl4030_dapm_hsol_controls)),
1015 SND_SOC_DAPM_MUX("HeadsetR Mux", SND_SOC_NOPM, 0, 0, 1222 SND_SOC_DAPM_PGA_E("HeadsetL PGA", SND_SOC_NOPM,
1016 &twl4030_dapm_hsor_control), 1223 0, 0, NULL, 0, headsetlpga_event,
1224 SND_SOC_DAPM_POST_PMU|SND_SOC_DAPM_POST_PMD),
1225 SND_SOC_DAPM_MIXER("HeadsetR Mixer", SND_SOC_NOPM, 0, 0,
1226 &twl4030_dapm_hsor_controls[0],
1227 ARRAY_SIZE(twl4030_dapm_hsor_controls)),
1228 SND_SOC_DAPM_PGA_E("HeadsetR PGA", SND_SOC_NOPM,
1229 0, 0, NULL, 0, headsetrpga_event,
1230 SND_SOC_DAPM_POST_PMU|SND_SOC_DAPM_POST_PMD),
1017 /* CarkitL/R */ 1231 /* CarkitL/R */
1018 SND_SOC_DAPM_MUX("CarkitL Mux", SND_SOC_NOPM, 0, 0, 1232 SND_SOC_DAPM_MIXER("CarkitL Mixer", SND_SOC_NOPM, 0, 0,
1019 &twl4030_dapm_carkitl_control), 1233 &twl4030_dapm_carkitl_controls[0],
1020 SND_SOC_DAPM_MUX("CarkitR Mux", SND_SOC_NOPM, 0, 0, 1234 ARRAY_SIZE(twl4030_dapm_carkitl_controls)),
1021 &twl4030_dapm_carkitr_control), 1235 SND_SOC_DAPM_MIXER("CarkitR Mixer", SND_SOC_NOPM, 0, 0,
1236 &twl4030_dapm_carkitr_controls[0],
1237 ARRAY_SIZE(twl4030_dapm_carkitr_controls)),
1238
1239 /* Output MUX controls */
1022 /* HandsfreeL/R */ 1240 /* HandsfreeL/R */
1023 SND_SOC_DAPM_MUX_E("HandsfreeL Mux", TWL4030_REG_HFL_CTL, 5, 0, 1241 SND_SOC_DAPM_MUX("HandsfreeL Mux", SND_SOC_NOPM, 0, 0,
1024 &twl4030_dapm_handsfreel_control, handsfree_event, 1242 &twl4030_dapm_handsfreel_control),
1025 SND_SOC_DAPM_POST_PMU|SND_SOC_DAPM_POST_PMD), 1243 SND_SOC_DAPM_SWITCH("HandsfreeL Switch", SND_SOC_NOPM, 0, 0,
1026 SND_SOC_DAPM_MUX_E("HandsfreeR Mux", TWL4030_REG_HFR_CTL, 5, 0, 1244 &twl4030_dapm_handsfreelmute_control),
1027 &twl4030_dapm_handsfreer_control, handsfree_event, 1245 SND_SOC_DAPM_PGA_E("HandsfreeL PGA", SND_SOC_NOPM,
1028 SND_SOC_DAPM_POST_PMU|SND_SOC_DAPM_POST_PMD), 1246 0, 0, NULL, 0, handsfreelpga_event,
1247 SND_SOC_DAPM_POST_PMU|SND_SOC_DAPM_POST_PMD),
1248 SND_SOC_DAPM_MUX("HandsfreeR Mux", SND_SOC_NOPM, 5, 0,
1249 &twl4030_dapm_handsfreer_control),
1250 SND_SOC_DAPM_SWITCH("HandsfreeR Switch", SND_SOC_NOPM, 0, 0,
1251 &twl4030_dapm_handsfreermute_control),
1252 SND_SOC_DAPM_PGA_E("HandsfreeR PGA", SND_SOC_NOPM,
1253 0, 0, NULL, 0, handsfreerpga_event,
1254 SND_SOC_DAPM_POST_PMU|SND_SOC_DAPM_POST_PMD),
1255 /* Vibra */
1256 SND_SOC_DAPM_MUX("Vibra Mux", TWL4030_REG_VIBRA_CTL, 0, 0,
1257 &twl4030_dapm_vibra_control),
1258 SND_SOC_DAPM_MUX("Vibra Route", SND_SOC_NOPM, 0, 0,
1259 &twl4030_dapm_vibrapath_control),
1029 1260
1030 /* Introducing four virtual ADC, since TWL4030 have four channel for 1261 /* Introducing four virtual ADC, since TWL4030 have four channel for
1031 capture */ 1262 capture */
@@ -1050,11 +1281,15 @@ static const struct snd_soc_dapm_widget twl4030_dapm_widgets[] = {
1050 SND_SOC_DAPM_POST_PMU|SND_SOC_DAPM_POST_PMD| 1281 SND_SOC_DAPM_POST_PMU|SND_SOC_DAPM_POST_PMD|
1051 SND_SOC_DAPM_POST_REG), 1282 SND_SOC_DAPM_POST_REG),
1052 1283
1053 /* Analog input muxes with switch for the capture amplifiers */ 1284 /* Analog input mixers for the capture amplifiers */
1054 SND_SOC_DAPM_VALUE_MUX("Analog Left Capture Route", 1285 SND_SOC_DAPM_MIXER("Analog Left Capture Route",
1055 TWL4030_REG_ANAMICL, 4, 0, &twl4030_dapm_analoglmic_control), 1286 TWL4030_REG_ANAMICL, 4, 0,
1056 SND_SOC_DAPM_VALUE_MUX("Analog Right Capture Route", 1287 &twl4030_dapm_analoglmic_controls[0],
1057 TWL4030_REG_ANAMICR, 4, 0, &twl4030_dapm_analogrmic_control), 1288 ARRAY_SIZE(twl4030_dapm_analoglmic_controls)),
1289 SND_SOC_DAPM_MIXER("Analog Right Capture Route",
1290 TWL4030_REG_ANAMICR, 4, 0,
1291 &twl4030_dapm_analogrmic_controls[0],
1292 ARRAY_SIZE(twl4030_dapm_analogrmic_controls)),
1058 1293
1059 SND_SOC_DAPM_PGA("ADC Physical Left", 1294 SND_SOC_DAPM_PGA("ADC Physical Left",
1060 TWL4030_REG_AVADC_CTL, 3, 0, NULL, 0), 1295 TWL4030_REG_AVADC_CTL, 3, 0, NULL, 0),
@@ -1073,62 +1308,86 @@ static const struct snd_soc_dapm_widget twl4030_dapm_widgets[] = {
1073}; 1308};
1074 1309
1075static const struct snd_soc_dapm_route intercon[] = { 1310static const struct snd_soc_dapm_route intercon[] = {
1076 {"Analog L1 Playback Mixer", NULL, "DAC Left1"}, 1311 {"Digital L1 Playback Mixer", NULL, "DAC Left1"},
1077 {"Analog R1 Playback Mixer", NULL, "DAC Right1"}, 1312 {"Digital R1 Playback Mixer", NULL, "DAC Right1"},
1078 {"Analog L2 Playback Mixer", NULL, "DAC Left2"}, 1313 {"Digital L2 Playback Mixer", NULL, "DAC Left2"},
1079 {"Analog R2 Playback Mixer", NULL, "DAC Right2"}, 1314 {"Digital R2 Playback Mixer", NULL, "DAC Right2"},
1080 1315 {"Digital Voice Playback Mixer", NULL, "DAC Voice"},
1081 {"ARXL1_APGA", NULL, "Analog L1 Playback Mixer"}, 1316
1082 {"ARXR1_APGA", NULL, "Analog R1 Playback Mixer"}, 1317 {"Analog L1 Playback Mixer", NULL, "Digital L1 Playback Mixer"},
1083 {"ARXL2_APGA", NULL, "Analog L2 Playback Mixer"}, 1318 {"Analog R1 Playback Mixer", NULL, "Digital R1 Playback Mixer"},
1084 {"ARXR2_APGA", NULL, "Analog R2 Playback Mixer"}, 1319 {"Analog L2 Playback Mixer", NULL, "Digital L2 Playback Mixer"},
1320 {"Analog R2 Playback Mixer", NULL, "Digital R2 Playback Mixer"},
1321 {"Analog Voice Playback Mixer", NULL, "Digital Voice Playback Mixer"},
1085 1322
1086 /* Internal playback routings */ 1323 /* Internal playback routings */
1087 /* Earpiece */ 1324 /* Earpiece */
1088 {"Earpiece Mux", "DACL1", "ARXL1_APGA"}, 1325 {"Earpiece Mixer", "Voice", "Analog Voice Playback Mixer"},
1089 {"Earpiece Mux", "DACL2", "ARXL2_APGA"}, 1326 {"Earpiece Mixer", "AudioL1", "Analog L1 Playback Mixer"},
1090 {"Earpiece Mux", "DACR1", "ARXR1_APGA"}, 1327 {"Earpiece Mixer", "AudioL2", "Analog L2 Playback Mixer"},
1328 {"Earpiece Mixer", "AudioR1", "Analog R1 Playback Mixer"},
1091 /* PreDrivL */ 1329 /* PreDrivL */
1092 {"PredriveL Mux", "DACL1", "ARXL1_APGA"}, 1330 {"PredriveL Mixer", "Voice", "Analog Voice Playback Mixer"},
1093 {"PredriveL Mux", "DACL2", "ARXL2_APGA"}, 1331 {"PredriveL Mixer", "AudioL1", "Analog L1 Playback Mixer"},
1094 {"PredriveL Mux", "DACR2", "ARXR2_APGA"}, 1332 {"PredriveL Mixer", "AudioL2", "Analog L2 Playback Mixer"},
1333 {"PredriveL Mixer", "AudioR2", "Analog R2 Playback Mixer"},
1095 /* PreDrivR */ 1334 /* PreDrivR */
1096 {"PredriveR Mux", "DACR1", "ARXR1_APGA"}, 1335 {"PredriveR Mixer", "Voice", "Analog Voice Playback Mixer"},
1097 {"PredriveR Mux", "DACR2", "ARXR2_APGA"}, 1336 {"PredriveR Mixer", "AudioR1", "Analog R1 Playback Mixer"},
1098 {"PredriveR Mux", "DACL2", "ARXL2_APGA"}, 1337 {"PredriveR Mixer", "AudioR2", "Analog R2 Playback Mixer"},
1338 {"PredriveR Mixer", "AudioL2", "Analog L2 Playback Mixer"},
1099 /* HeadsetL */ 1339 /* HeadsetL */
1100 {"HeadsetL Mux", "DACL1", "ARXL1_APGA"}, 1340 {"HeadsetL Mixer", "Voice", "Analog Voice Playback Mixer"},
1101 {"HeadsetL Mux", "DACL2", "ARXL2_APGA"}, 1341 {"HeadsetL Mixer", "AudioL1", "Analog L1 Playback Mixer"},
1342 {"HeadsetL Mixer", "AudioL2", "Analog L2 Playback Mixer"},
1343 {"HeadsetL PGA", NULL, "HeadsetL Mixer"},
1102 /* HeadsetR */ 1344 /* HeadsetR */
1103 {"HeadsetR Mux", "DACR1", "ARXR1_APGA"}, 1345 {"HeadsetR Mixer", "Voice", "Analog Voice Playback Mixer"},
1104 {"HeadsetR Mux", "DACR2", "ARXR2_APGA"}, 1346 {"HeadsetR Mixer", "AudioR1", "Analog R1 Playback Mixer"},
1347 {"HeadsetR Mixer", "AudioR2", "Analog R2 Playback Mixer"},
1348 {"HeadsetR PGA", NULL, "HeadsetR Mixer"},
1105 /* CarkitL */ 1349 /* CarkitL */
1106 {"CarkitL Mux", "DACL1", "ARXL1_APGA"}, 1350 {"CarkitL Mixer", "Voice", "Analog Voice Playback Mixer"},
1107 {"CarkitL Mux", "DACL2", "ARXL2_APGA"}, 1351 {"CarkitL Mixer", "AudioL1", "Analog L1 Playback Mixer"},
1352 {"CarkitL Mixer", "AudioL2", "Analog L2 Playback Mixer"},
1108 /* CarkitR */ 1353 /* CarkitR */
1109 {"CarkitR Mux", "DACR1", "ARXR1_APGA"}, 1354 {"CarkitR Mixer", "Voice", "Analog Voice Playback Mixer"},
1110 {"CarkitR Mux", "DACR2", "ARXR2_APGA"}, 1355 {"CarkitR Mixer", "AudioR1", "Analog R1 Playback Mixer"},
1356 {"CarkitR Mixer", "AudioR2", "Analog R2 Playback Mixer"},
1111 /* HandsfreeL */ 1357 /* HandsfreeL */
1112 {"HandsfreeL Mux", "DACL1", "ARXL1_APGA"}, 1358 {"HandsfreeL Mux", "Voice", "Analog Voice Playback Mixer"},
1113 {"HandsfreeL Mux", "DACL2", "ARXL2_APGA"}, 1359 {"HandsfreeL Mux", "AudioL1", "Analog L1 Playback Mixer"},
1114 {"HandsfreeL Mux", "DACR2", "ARXR2_APGA"}, 1360 {"HandsfreeL Mux", "AudioL2", "Analog L2 Playback Mixer"},
1361 {"HandsfreeL Mux", "AudioR2", "Analog R2 Playback Mixer"},
1362 {"HandsfreeL Switch", "Switch", "HandsfreeL Mux"},
1363 {"HandsfreeL PGA", NULL, "HandsfreeL Switch"},
1115 /* HandsfreeR */ 1364 /* HandsfreeR */
1116 {"HandsfreeR Mux", "DACR1", "ARXR1_APGA"}, 1365 {"HandsfreeR Mux", "Voice", "Analog Voice Playback Mixer"},
1117 {"HandsfreeR Mux", "DACR2", "ARXR2_APGA"}, 1366 {"HandsfreeR Mux", "AudioR1", "Analog R1 Playback Mixer"},
1118 {"HandsfreeR Mux", "DACL2", "ARXL2_APGA"}, 1367 {"HandsfreeR Mux", "AudioR2", "Analog R2 Playback Mixer"},
1368 {"HandsfreeR Mux", "AudioL2", "Analog L2 Playback Mixer"},
1369 {"HandsfreeR Switch", "Switch", "HandsfreeR Mux"},
1370 {"HandsfreeR PGA", NULL, "HandsfreeR Switch"},
1371 /* Vibra */
1372 {"Vibra Mux", "AudioL1", "DAC Left1"},
1373 {"Vibra Mux", "AudioR1", "DAC Right1"},
1374 {"Vibra Mux", "AudioL2", "DAC Left2"},
1375 {"Vibra Mux", "AudioR2", "DAC Right2"},
1119 1376
1120 /* outputs */ 1377 /* outputs */
1121 {"OUTL", NULL, "ARXL2_APGA"}, 1378 {"OUTL", NULL, "Analog L2 Playback Mixer"},
1122 {"OUTR", NULL, "ARXR2_APGA"}, 1379 {"OUTR", NULL, "Analog R2 Playback Mixer"},
1123 {"EARPIECE", NULL, "Earpiece Mux"}, 1380 {"EARPIECE", NULL, "Earpiece Mixer"},
1124 {"PREDRIVEL", NULL, "PredriveL Mux"}, 1381 {"PREDRIVEL", NULL, "PredriveL Mixer"},
1125 {"PREDRIVER", NULL, "PredriveR Mux"}, 1382 {"PREDRIVER", NULL, "PredriveR Mixer"},
1126 {"HSOL", NULL, "HeadsetL Mux"}, 1383 {"HSOL", NULL, "HeadsetL PGA"},
1127 {"HSOR", NULL, "HeadsetR Mux"}, 1384 {"HSOR", NULL, "HeadsetR PGA"},
1128 {"CARKITL", NULL, "CarkitL Mux"}, 1385 {"CARKITL", NULL, "CarkitL Mixer"},
1129 {"CARKITR", NULL, "CarkitR Mux"}, 1386 {"CARKITR", NULL, "CarkitR Mixer"},
1130 {"HFL", NULL, "HandsfreeL Mux"}, 1387 {"HFL", NULL, "HandsfreeL PGA"},
1131 {"HFR", NULL, "HandsfreeR Mux"}, 1388 {"HFR", NULL, "HandsfreeR PGA"},
1389 {"Vibra Route", "Audio", "Vibra Mux"},
1390 {"VIBRA", NULL, "Vibra Route"},
1132 1391
1133 /* Capture path */ 1392 /* Capture path */
1134 {"Analog Left Capture Route", "Main mic", "MAINMIC"}, 1393 {"Analog Left Capture Route", "Main mic", "MAINMIC"},
@@ -1168,18 +1427,22 @@ static const struct snd_soc_dapm_route intercon[] = {
1168 {"Left1 Analog Loopback", "Switch", "Analog Left Capture Route"}, 1427 {"Left1 Analog Loopback", "Switch", "Analog Left Capture Route"},
1169 {"Right2 Analog Loopback", "Switch", "Analog Right Capture Route"}, 1428 {"Right2 Analog Loopback", "Switch", "Analog Right Capture Route"},
1170 {"Left2 Analog Loopback", "Switch", "Analog Left Capture Route"}, 1429 {"Left2 Analog Loopback", "Switch", "Analog Left Capture Route"},
1430 {"Voice Analog Loopback", "Switch", "Analog Left Capture Route"},
1171 1431
1172 {"Analog R1 Playback Mixer", NULL, "Right1 Analog Loopback"}, 1432 {"Analog R1 Playback Mixer", NULL, "Right1 Analog Loopback"},
1173 {"Analog L1 Playback Mixer", NULL, "Left1 Analog Loopback"}, 1433 {"Analog L1 Playback Mixer", NULL, "Left1 Analog Loopback"},
1174 {"Analog R2 Playback Mixer", NULL, "Right2 Analog Loopback"}, 1434 {"Analog R2 Playback Mixer", NULL, "Right2 Analog Loopback"},
1175 {"Analog L2 Playback Mixer", NULL, "Left2 Analog Loopback"}, 1435 {"Analog L2 Playback Mixer", NULL, "Left2 Analog Loopback"},
1436 {"Analog Voice Playback Mixer", NULL, "Voice Analog Loopback"},
1176 1437
1177 /* Digital bypass routes */ 1438 /* Digital bypass routes */
1178 {"Right Digital Loopback", "Volume", "TX1 Capture Route"}, 1439 {"Right Digital Loopback", "Volume", "TX1 Capture Route"},
1179 {"Left Digital Loopback", "Volume", "TX1 Capture Route"}, 1440 {"Left Digital Loopback", "Volume", "TX1 Capture Route"},
1441 {"Voice Digital Loopback", "Volume", "TX2 Capture Route"},
1180 1442
1181 {"Analog R2 Playback Mixer", NULL, "Right Digital Loopback"}, 1443 {"Digital R2 Playback Mixer", NULL, "Right Digital Loopback"},
1182 {"Analog L2 Playback Mixer", NULL, "Left Digital Loopback"}, 1444 {"Digital L2 Playback Mixer", NULL, "Left Digital Loopback"},
1445 {"Digital Voice Playback Mixer", NULL, "Voice Digital Loopback"},
1183 1446
1184}; 1447};
1185 1448
@@ -1226,6 +1489,58 @@ static int twl4030_set_bias_level(struct snd_soc_codec *codec,
1226 return 0; 1489 return 0;
1227} 1490}
1228 1491
1492static void twl4030_constraints(struct twl4030_priv *twl4030,
1493 struct snd_pcm_substream *mst_substream)
1494{
1495 struct snd_pcm_substream *slv_substream;
1496
1497 /* Pick the stream, which need to be constrained */
1498 if (mst_substream == twl4030->master_substream)
1499 slv_substream = twl4030->slave_substream;
1500 else if (mst_substream == twl4030->slave_substream)
1501 slv_substream = twl4030->master_substream;
1502 else /* This should not happen.. */
1503 return;
1504
1505 /* Set the constraints according to the already configured stream */
1506 snd_pcm_hw_constraint_minmax(slv_substream->runtime,
1507 SNDRV_PCM_HW_PARAM_RATE,
1508 twl4030->rate,
1509 twl4030->rate);
1510
1511 snd_pcm_hw_constraint_minmax(slv_substream->runtime,
1512 SNDRV_PCM_HW_PARAM_SAMPLE_BITS,
1513 twl4030->sample_bits,
1514 twl4030->sample_bits);
1515
1516 snd_pcm_hw_constraint_minmax(slv_substream->runtime,
1517 SNDRV_PCM_HW_PARAM_CHANNELS,
1518 twl4030->channels,
1519 twl4030->channels);
1520}
1521
1522/* In case of 4 channel mode, the RX1 L/R for playback and the TX2 L/R for
1523 * capture has to be enabled/disabled. */
1524static void twl4030_tdm_enable(struct snd_soc_codec *codec, int direction,
1525 int enable)
1526{
1527 u8 reg, mask;
1528
1529 reg = twl4030_read_reg_cache(codec, TWL4030_REG_OPTION);
1530
1531 if (direction == SNDRV_PCM_STREAM_PLAYBACK)
1532 mask = TWL4030_ARXL1_VRX_EN | TWL4030_ARXR1_EN;
1533 else
1534 mask = TWL4030_ATXL2_VTXL_EN | TWL4030_ATXR2_VTXR_EN;
1535
1536 if (enable)
1537 reg |= mask;
1538 else
1539 reg &= ~mask;
1540
1541 twl4030_write(codec, TWL4030_REG_OPTION, reg);
1542}
1543
1229static int twl4030_startup(struct snd_pcm_substream *substream, 1544static int twl4030_startup(struct snd_pcm_substream *substream,
1230 struct snd_soc_dai *dai) 1545 struct snd_soc_dai *dai)
1231{ 1546{
@@ -1234,26 +1549,25 @@ static int twl4030_startup(struct snd_pcm_substream *substream,
1234 struct snd_soc_codec *codec = socdev->card->codec; 1549 struct snd_soc_codec *codec = socdev->card->codec;
1235 struct twl4030_priv *twl4030 = codec->private_data; 1550 struct twl4030_priv *twl4030 = codec->private_data;
1236 1551
1237 /* If we already have a playback or capture going then constrain
1238 * this substream to match it.
1239 */
1240 if (twl4030->master_substream) { 1552 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; 1553 twl4030->slave_substream = substream;
1255 } else 1554 /* The DAI has one configuration for playback and capture, so
1555 * if the DAI has been already configured then constrain this
1556 * substream to match it. */
1557 if (twl4030->configured)
1558 twl4030_constraints(twl4030, twl4030->master_substream);
1559 } else {
1560 if (!(twl4030_read_reg_cache(codec, TWL4030_REG_CODEC_MODE) &
1561 TWL4030_OPTION_1)) {
1562 /* In option2 4 channel is not supported, set the
1563 * constraint for the first stream for channels, the
1564 * second stream will 'inherit' this cosntraint */
1565 snd_pcm_hw_constraint_minmax(substream->runtime,
1566 SNDRV_PCM_HW_PARAM_CHANNELS,
1567 2, 2);
1568 }
1256 twl4030->master_substream = substream; 1569 twl4030->master_substream = substream;
1570 }
1257 1571
1258 return 0; 1572 return 0;
1259} 1573}
@@ -1270,6 +1584,17 @@ static void twl4030_shutdown(struct snd_pcm_substream *substream,
1270 twl4030->master_substream = twl4030->slave_substream; 1584 twl4030->master_substream = twl4030->slave_substream;
1271 1585
1272 twl4030->slave_substream = NULL; 1586 twl4030->slave_substream = NULL;
1587
1588 /* If all streams are closed, or the remaining stream has not yet
1589 * been configured than set the DAI as not configured. */
1590 if (!twl4030->master_substream)
1591 twl4030->configured = 0;
1592 else if (!twl4030->master_substream->runtime->channels)
1593 twl4030->configured = 0;
1594
1595 /* If the closing substream had 4 channel, do the necessary cleanup */
1596 if (substream->runtime->channels == 4)
1597 twl4030_tdm_enable(codec, substream->stream, 0);
1273} 1598}
1274 1599
1275static int twl4030_hw_params(struct snd_pcm_substream *substream, 1600static int twl4030_hw_params(struct snd_pcm_substream *substream,
@@ -1282,8 +1607,24 @@ static int twl4030_hw_params(struct snd_pcm_substream *substream,
1282 struct twl4030_priv *twl4030 = codec->private_data; 1607 struct twl4030_priv *twl4030 = codec->private_data;
1283 u8 mode, old_mode, format, old_format; 1608 u8 mode, old_mode, format, old_format;
1284 1609
1285 if (substream == twl4030->slave_substream) 1610 /* If the substream has 4 channel, do the necessary setup */
1286 /* Ignoring hw_params for slave substream */ 1611 if (params_channels(params) == 4) {
1612 u8 format, mode;
1613
1614 format = twl4030_read_reg_cache(codec, TWL4030_REG_AUDIO_IF);
1615 mode = twl4030_read_reg_cache(codec, TWL4030_REG_CODEC_MODE);
1616
1617 /* Safety check: are we in the correct operating mode and
1618 * the interface is in TDM mode? */
1619 if ((mode & TWL4030_OPTION_1) &&
1620 ((format & TWL4030_AIF_FORMAT) == TWL4030_AIF_FORMAT_TDM))
1621 twl4030_tdm_enable(codec, substream->stream, 1);
1622 else
1623 return -EINVAL;
1624 }
1625
1626 if (twl4030->configured)
1627 /* Ignoring hw_params for already configured DAI */
1287 return 0; 1628 return 0;
1288 1629
1289 /* bit rate */ 1630 /* bit rate */
@@ -1363,6 +1704,21 @@ static int twl4030_hw_params(struct snd_pcm_substream *substream,
1363 /* set CODECPDZ afterwards */ 1704 /* set CODECPDZ afterwards */
1364 twl4030_codec_enable(codec, 1); 1705 twl4030_codec_enable(codec, 1);
1365 } 1706 }
1707
1708 /* Store the important parameters for the DAI configuration and set
1709 * the DAI as configured */
1710 twl4030->configured = 1;
1711 twl4030->rate = params_rate(params);
1712 twl4030->sample_bits = hw_param_interval(params,
1713 SNDRV_PCM_HW_PARAM_SAMPLE_BITS)->min;
1714 twl4030->channels = params_channels(params);
1715
1716 /* If both playback and capture streams are open, and one of them
1717 * is setting the hw parameters right now (since we are here), set
1718 * constraints to the other stream to match the current one. */
1719 if (twl4030->slave_substream)
1720 twl4030_constraints(twl4030, substream);
1721
1366 return 0; 1722 return 0;
1367} 1723}
1368 1724
@@ -1370,17 +1726,21 @@ static int twl4030_set_dai_sysclk(struct snd_soc_dai *codec_dai,
1370 int clk_id, unsigned int freq, int dir) 1726 int clk_id, unsigned int freq, int dir)
1371{ 1727{
1372 struct snd_soc_codec *codec = codec_dai->codec; 1728 struct snd_soc_codec *codec = codec_dai->codec;
1729 struct twl4030_priv *twl4030 = codec->private_data;
1373 u8 infreq; 1730 u8 infreq;
1374 1731
1375 switch (freq) { 1732 switch (freq) {
1376 case 19200000: 1733 case 19200000:
1377 infreq = TWL4030_APLL_INFREQ_19200KHZ; 1734 infreq = TWL4030_APLL_INFREQ_19200KHZ;
1735 twl4030->sysclk = 19200;
1378 break; 1736 break;
1379 case 26000000: 1737 case 26000000:
1380 infreq = TWL4030_APLL_INFREQ_26000KHZ; 1738 infreq = TWL4030_APLL_INFREQ_26000KHZ;
1739 twl4030->sysclk = 26000;
1381 break; 1740 break;
1382 case 38400000: 1741 case 38400000:
1383 infreq = TWL4030_APLL_INFREQ_38400KHZ; 1742 infreq = TWL4030_APLL_INFREQ_38400KHZ;
1743 twl4030->sysclk = 38400;
1384 break; 1744 break;
1385 default: 1745 default:
1386 printk(KERN_ERR "TWL4030 set sysclk: unknown rate %d\n", 1746 printk(KERN_ERR "TWL4030 set sysclk: unknown rate %d\n",
@@ -1424,6 +1784,9 @@ static int twl4030_set_dai_fmt(struct snd_soc_dai *codec_dai,
1424 case SND_SOC_DAIFMT_I2S: 1784 case SND_SOC_DAIFMT_I2S:
1425 format |= TWL4030_AIF_FORMAT_CODEC; 1785 format |= TWL4030_AIF_FORMAT_CODEC;
1426 break; 1786 break;
1787 case SND_SOC_DAIFMT_DSP_A:
1788 format |= TWL4030_AIF_FORMAT_TDM;
1789 break;
1427 default: 1790 default:
1428 return -EINVAL; 1791 return -EINVAL;
1429 } 1792 }
@@ -1443,6 +1806,180 @@ static int twl4030_set_dai_fmt(struct snd_soc_dai *codec_dai,
1443 return 0; 1806 return 0;
1444} 1807}
1445 1808
1809/* In case of voice mode, the RX1 L(VRX) for downlink and the TX2 L/R
1810 * (VTXL, VTXR) for uplink has to be enabled/disabled. */
1811static void twl4030_voice_enable(struct snd_soc_codec *codec, int direction,
1812 int enable)
1813{
1814 u8 reg, mask;
1815
1816 reg = twl4030_read_reg_cache(codec, TWL4030_REG_OPTION);
1817
1818 if (direction == SNDRV_PCM_STREAM_PLAYBACK)
1819 mask = TWL4030_ARXL1_VRX_EN;
1820 else
1821 mask = TWL4030_ATXL2_VTXL_EN | TWL4030_ATXR2_VTXR_EN;
1822
1823 if (enable)
1824 reg |= mask;
1825 else
1826 reg &= ~mask;
1827
1828 twl4030_write(codec, TWL4030_REG_OPTION, reg);
1829}
1830
1831static int twl4030_voice_startup(struct snd_pcm_substream *substream,
1832 struct snd_soc_dai *dai)
1833{
1834 struct snd_soc_pcm_runtime *rtd = substream->private_data;
1835 struct snd_soc_device *socdev = rtd->socdev;
1836 struct snd_soc_codec *codec = socdev->card->codec;
1837 u8 infreq;
1838 u8 mode;
1839
1840 /* If the system master clock is not 26MHz, the voice PCM interface is
1841 * not avilable.
1842 */
1843 infreq = twl4030_read_reg_cache(codec, TWL4030_REG_APLL_CTL)
1844 & TWL4030_APLL_INFREQ;
1845
1846 if (infreq != TWL4030_APLL_INFREQ_26000KHZ) {
1847 printk(KERN_ERR "TWL4030 voice startup: "
1848 "MCLK is not 26MHz, call set_sysclk() on init\n");
1849 return -EINVAL;
1850 }
1851
1852 /* If the codec mode is not option2, the voice PCM interface is not
1853 * avilable.
1854 */
1855 mode = twl4030_read_reg_cache(codec, TWL4030_REG_CODEC_MODE)
1856 & TWL4030_OPT_MODE;
1857
1858 if (mode != TWL4030_OPTION_2) {
1859 printk(KERN_ERR "TWL4030 voice startup: "
1860 "the codec mode is not option2\n");
1861 return -EINVAL;
1862 }
1863
1864 return 0;
1865}
1866
1867static void twl4030_voice_shutdown(struct snd_pcm_substream *substream,
1868 struct snd_soc_dai *dai)
1869{
1870 struct snd_soc_pcm_runtime *rtd = substream->private_data;
1871 struct snd_soc_device *socdev = rtd->socdev;
1872 struct snd_soc_codec *codec = socdev->card->codec;
1873
1874 /* Enable voice digital filters */
1875 twl4030_voice_enable(codec, substream->stream, 0);
1876}
1877
1878static int twl4030_voice_hw_params(struct snd_pcm_substream *substream,
1879 struct snd_pcm_hw_params *params, struct snd_soc_dai *dai)
1880{
1881 struct snd_soc_pcm_runtime *rtd = substream->private_data;
1882 struct snd_soc_device *socdev = rtd->socdev;
1883 struct snd_soc_codec *codec = socdev->card->codec;
1884 u8 old_mode, mode;
1885
1886 /* Enable voice digital filters */
1887 twl4030_voice_enable(codec, substream->stream, 1);
1888
1889 /* bit rate */
1890 old_mode = twl4030_read_reg_cache(codec, TWL4030_REG_CODEC_MODE)
1891 & ~(TWL4030_CODECPDZ);
1892 mode = old_mode;
1893
1894 switch (params_rate(params)) {
1895 case 8000:
1896 mode &= ~(TWL4030_SEL_16K);
1897 break;
1898 case 16000:
1899 mode |= TWL4030_SEL_16K;
1900 break;
1901 default:
1902 printk(KERN_ERR "TWL4030 voice hw params: unknown rate %d\n",
1903 params_rate(params));
1904 return -EINVAL;
1905 }
1906
1907 if (mode != old_mode) {
1908 /* change rate and set CODECPDZ */
1909 twl4030_codec_enable(codec, 0);
1910 twl4030_write(codec, TWL4030_REG_CODEC_MODE, mode);
1911 twl4030_codec_enable(codec, 1);
1912 }
1913
1914 return 0;
1915}
1916
1917static int twl4030_voice_set_dai_sysclk(struct snd_soc_dai *codec_dai,
1918 int clk_id, unsigned int freq, int dir)
1919{
1920 struct snd_soc_codec *codec = codec_dai->codec;
1921 u8 infreq;
1922
1923 switch (freq) {
1924 case 26000000:
1925 infreq = TWL4030_APLL_INFREQ_26000KHZ;
1926 break;
1927 default:
1928 printk(KERN_ERR "TWL4030 voice set sysclk: unknown rate %d\n",
1929 freq);
1930 return -EINVAL;
1931 }
1932
1933 infreq |= TWL4030_APLL_EN;
1934 twl4030_write(codec, TWL4030_REG_APLL_CTL, infreq);
1935
1936 return 0;
1937}
1938
1939static int twl4030_voice_set_dai_fmt(struct snd_soc_dai *codec_dai,
1940 unsigned int fmt)
1941{
1942 struct snd_soc_codec *codec = codec_dai->codec;
1943 u8 old_format, format;
1944
1945 /* get format */
1946 old_format = twl4030_read_reg_cache(codec, TWL4030_REG_VOICE_IF);
1947 format = old_format;
1948
1949 /* set master/slave audio interface */
1950 switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
1951 case SND_SOC_DAIFMT_CBS_CFM:
1952 format &= ~(TWL4030_VIF_SLAVE_EN);
1953 break;
1954 case SND_SOC_DAIFMT_CBS_CFS:
1955 format |= TWL4030_VIF_SLAVE_EN;
1956 break;
1957 default:
1958 return -EINVAL;
1959 }
1960
1961 /* clock inversion */
1962 switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
1963 case SND_SOC_DAIFMT_IB_NF:
1964 format &= ~(TWL4030_VIF_FORMAT);
1965 break;
1966 case SND_SOC_DAIFMT_NB_IF:
1967 format |= TWL4030_VIF_FORMAT;
1968 break;
1969 default:
1970 return -EINVAL;
1971 }
1972
1973 if (format != old_format) {
1974 /* change format and set CODECPDZ */
1975 twl4030_codec_enable(codec, 0);
1976 twl4030_write(codec, TWL4030_REG_VOICE_IF, format);
1977 twl4030_codec_enable(codec, 1);
1978 }
1979
1980 return 0;
1981}
1982
1446#define TWL4030_RATES (SNDRV_PCM_RATE_8000_48000) 1983#define TWL4030_RATES (SNDRV_PCM_RATE_8000_48000)
1447#define TWL4030_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FORMAT_S24_LE) 1984#define TWL4030_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FORMAT_S24_LE)
1448 1985
@@ -1454,21 +1991,47 @@ static struct snd_soc_dai_ops twl4030_dai_ops = {
1454 .set_fmt = twl4030_set_dai_fmt, 1991 .set_fmt = twl4030_set_dai_fmt,
1455}; 1992};
1456 1993
1457struct snd_soc_dai twl4030_dai = { 1994static struct snd_soc_dai_ops twl4030_dai_voice_ops = {
1995 .startup = twl4030_voice_startup,
1996 .shutdown = twl4030_voice_shutdown,
1997 .hw_params = twl4030_voice_hw_params,
1998 .set_sysclk = twl4030_voice_set_dai_sysclk,
1999 .set_fmt = twl4030_voice_set_dai_fmt,
2000};
2001
2002struct snd_soc_dai twl4030_dai[] = {
2003{
1458 .name = "twl4030", 2004 .name = "twl4030",
1459 .playback = { 2005 .playback = {
1460 .stream_name = "Playback", 2006 .stream_name = "HiFi Playback",
1461 .channels_min = 2, 2007 .channels_min = 2,
1462 .channels_max = 2, 2008 .channels_max = 4,
1463 .rates = TWL4030_RATES | SNDRV_PCM_RATE_96000, 2009 .rates = TWL4030_RATES | SNDRV_PCM_RATE_96000,
1464 .formats = TWL4030_FORMATS,}, 2010 .formats = TWL4030_FORMATS,},
1465 .capture = { 2011 .capture = {
1466 .stream_name = "Capture", 2012 .stream_name = "Capture",
1467 .channels_min = 2, 2013 .channels_min = 2,
1468 .channels_max = 2, 2014 .channels_max = 4,
1469 .rates = TWL4030_RATES, 2015 .rates = TWL4030_RATES,
1470 .formats = TWL4030_FORMATS,}, 2016 .formats = TWL4030_FORMATS,},
1471 .ops = &twl4030_dai_ops, 2017 .ops = &twl4030_dai_ops,
2018},
2019{
2020 .name = "twl4030 Voice",
2021 .playback = {
2022 .stream_name = "Voice Playback",
2023 .channels_min = 1,
2024 .channels_max = 1,
2025 .rates = SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_16000,
2026 .formats = SNDRV_PCM_FMTBIT_S16_LE,},
2027 .capture = {
2028 .stream_name = "Capture",
2029 .channels_min = 1,
2030 .channels_max = 2,
2031 .rates = SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_16000,
2032 .formats = SNDRV_PCM_FMTBIT_S16_LE,},
2033 .ops = &twl4030_dai_voice_ops,
2034},
1472}; 2035};
1473EXPORT_SYMBOL_GPL(twl4030_dai); 2036EXPORT_SYMBOL_GPL(twl4030_dai);
1474 2037
@@ -1500,6 +2063,8 @@ static int twl4030_resume(struct platform_device *pdev)
1500static int twl4030_init(struct snd_soc_device *socdev) 2063static int twl4030_init(struct snd_soc_device *socdev)
1501{ 2064{
1502 struct snd_soc_codec *codec = socdev->card->codec; 2065 struct snd_soc_codec *codec = socdev->card->codec;
2066 struct twl4030_setup_data *setup = socdev->codec_data;
2067 struct twl4030_priv *twl4030 = codec->private_data;
1503 int ret = 0; 2068 int ret = 0;
1504 2069
1505 printk(KERN_INFO "TWL4030 Audio Codec init \n"); 2070 printk(KERN_INFO "TWL4030 Audio Codec init \n");
@@ -1509,14 +2074,31 @@ static int twl4030_init(struct snd_soc_device *socdev)
1509 codec->read = twl4030_read_reg_cache; 2074 codec->read = twl4030_read_reg_cache;
1510 codec->write = twl4030_write; 2075 codec->write = twl4030_write;
1511 codec->set_bias_level = twl4030_set_bias_level; 2076 codec->set_bias_level = twl4030_set_bias_level;
1512 codec->dai = &twl4030_dai; 2077 codec->dai = twl4030_dai;
1513 codec->num_dai = 1; 2078 codec->num_dai = ARRAY_SIZE(twl4030_dai),
1514 codec->reg_cache_size = sizeof(twl4030_reg); 2079 codec->reg_cache_size = sizeof(twl4030_reg);
1515 codec->reg_cache = kmemdup(twl4030_reg, sizeof(twl4030_reg), 2080 codec->reg_cache = kmemdup(twl4030_reg, sizeof(twl4030_reg),
1516 GFP_KERNEL); 2081 GFP_KERNEL);
1517 if (codec->reg_cache == NULL) 2082 if (codec->reg_cache == NULL)
1518 return -ENOMEM; 2083 return -ENOMEM;
1519 2084
2085 /* Configuration for headset ramp delay from setup data */
2086 if (setup) {
2087 unsigned char hs_pop;
2088
2089 if (setup->sysclk)
2090 twl4030->sysclk = setup->sysclk;
2091 else
2092 twl4030->sysclk = 26000;
2093
2094 hs_pop = twl4030_read_reg_cache(codec, TWL4030_REG_HS_POPN_SET);
2095 hs_pop &= ~TWL4030_RAMP_DELAY;
2096 hs_pop |= (setup->ramp_delay_value << 2);
2097 twl4030_write_reg_cache(codec, TWL4030_REG_HS_POPN_SET, hs_pop);
2098 } else {
2099 twl4030->sysclk = 26000;
2100 }
2101
1520 /* register pcms */ 2102 /* register pcms */
1521 ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1); 2103 ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1);
1522 if (ret < 0) { 2104 if (ret < 0) {
@@ -1604,13 +2186,13 @@ EXPORT_SYMBOL_GPL(soc_codec_dev_twl4030);
1604 2186
1605static int __init twl4030_modinit(void) 2187static int __init twl4030_modinit(void)
1606{ 2188{
1607 return snd_soc_register_dai(&twl4030_dai); 2189 return snd_soc_register_dais(&twl4030_dai[0], ARRAY_SIZE(twl4030_dai));
1608} 2190}
1609module_init(twl4030_modinit); 2191module_init(twl4030_modinit);
1610 2192
1611static void __exit twl4030_exit(void) 2193static void __exit twl4030_exit(void)
1612{ 2194{
1613 snd_soc_unregister_dai(&twl4030_dai); 2195 snd_soc_unregister_dais(&twl4030_dai[0], ARRAY_SIZE(twl4030_dai));
1614} 2196}
1615module_exit(twl4030_exit); 2197module_exit(twl4030_exit);
1616 2198
diff --git a/sound/soc/codecs/twl4030.h b/sound/soc/codecs/twl4030.h
index cb63765db1df..fe5f395d9e4f 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,19 @@
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};
278
242#endif /* End of __TWL4030_AUDIO_H__ */ 279#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/wm8350.c b/sound/soc/codecs/wm8350.c
index 0275321ff8ab..e7348d341b76 100644
--- a/sound/soc/codecs/wm8350.c
+++ b/sound/soc/codecs/wm8350.c
@@ -1108,7 +1108,7 @@ static int wm8350_set_fll(struct snd_soc_dai *codec_dai,
1108 if (ret < 0) 1108 if (ret < 0)
1109 return ret; 1109 return ret;
1110 dev_dbg(wm8350->dev, 1110 dev_dbg(wm8350->dev,
1111 "FLL in %d FLL out %d N 0x%x K 0x%x div %d ratio %d", 1111 "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, 1112 freq_in, freq_out, fll_div.n, fll_div.k, fll_div.div,
1113 fll_div.ratio); 1113 fll_div.ratio);
1114 1114
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..502eefac1ecd 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
@@ -1473,8 +1473,8 @@ static int wm8400_codec_probe(struct platform_device *dev)
1473 1473
1474 codec = &priv->codec; 1474 codec = &priv->codec;
1475 codec->private_data = priv; 1475 codec->private_data = priv;
1476 codec->control_data = dev->dev.driver_data; 1476 codec->control_data = dev_get_drvdata(&dev->dev);
1477 priv->wm8400 = dev->dev.driver_data; 1477 priv->wm8400 = dev_get_drvdata(&dev->dev);
1478 1478
1479 ret = regulator_bulk_get(priv->wm8400->dev, 1479 ret = regulator_bulk_get(priv->wm8400->dev,
1480 ARRAY_SIZE(power), &power[0]); 1480 ARRAY_SIZE(power), &power[0]);
diff --git a/sound/soc/codecs/wm8510.c b/sound/soc/codecs/wm8510.c
index 6a4cea09c45d..c8b8dba85890 100644
--- a/sound/soc/codecs/wm8510.c
+++ b/sound/soc/codecs/wm8510.c
@@ -298,7 +298,7 @@ static void pll_factors(unsigned int target, unsigned int source)
298 298
299 if ((Ndiv < 6) || (Ndiv > 12)) 299 if ((Ndiv < 6) || (Ndiv > 12))
300 printk(KERN_WARNING 300 printk(KERN_WARNING
301 "WM8510 N value %d outwith recommended range!d\n", 301 "WM8510 N value %u outwith recommended range!d\n",
302 Ndiv); 302 Ndiv);
303 303
304 pll_div.n = Ndiv; 304 pll_div.n = Ndiv;
diff --git a/sound/soc/codecs/wm8580.c b/sound/soc/codecs/wm8580.c
index 9f6be3d31ac0..86c4b24db817 100644
--- a/sound/soc/codecs/wm8580.c
+++ b/sound/soc/codecs/wm8580.c
@@ -415,7 +415,7 @@ static int pll_factors(struct _pll_div *pll_div, unsigned int target,
415 unsigned int K, Ndiv, Nmod; 415 unsigned int K, Ndiv, Nmod;
416 int i; 416 int i;
417 417
418 pr_debug("wm8580: PLL %dHz->%dHz\n", source, target); 418 pr_debug("wm8580: PLL %uHz->%uHz\n", source, target);
419 419
420 /* Scale the output frequency up; the PLL should run in the 420 /* Scale the output frequency up; the PLL should run in the
421 * region of 90-100MHz. 421 * region of 90-100MHz.
@@ -447,7 +447,7 @@ static int pll_factors(struct _pll_div *pll_div, unsigned int target,
447 447
448 if ((Ndiv < 5) || (Ndiv > 13)) { 448 if ((Ndiv < 5) || (Ndiv > 13)) {
449 printk(KERN_ERR 449 printk(KERN_ERR
450 "WM8580 N=%d outside supported range\n", Ndiv); 450 "WM8580 N=%u outside supported range\n", Ndiv);
451 return -EINVAL; 451 return -EINVAL;
452 } 452 }
453 453
diff --git a/sound/soc/codecs/wm8731.c b/sound/soc/codecs/wm8731.c
index e043e3f60008..7a205876ef4f 100644
--- a/sound/soc/codecs/wm8731.c
+++ b/sound/soc/codecs/wm8731.c
@@ -666,14 +666,14 @@ static int __devinit wm8731_spi_probe(struct spi_device *spi)
666 codec->hw_write = (hw_write_t)wm8731_spi_write; 666 codec->hw_write = (hw_write_t)wm8731_spi_write;
667 codec->dev = &spi->dev; 667 codec->dev = &spi->dev;
668 668
669 spi->dev.driver_data = wm8731; 669 dev_set_drvdata(&spi->dev, wm8731);
670 670
671 return wm8731_register(wm8731); 671 return wm8731_register(wm8731);
672} 672}
673 673
674static int __devexit wm8731_spi_remove(struct spi_device *spi) 674static int __devexit wm8731_spi_remove(struct spi_device *spi)
675{ 675{
676 struct wm8731_priv *wm8731 = spi->dev.driver_data; 676 struct wm8731_priv *wm8731 = dev_get_drvdata(&spi->dev);
677 677
678 wm8731_unregister(wm8731); 678 wm8731_unregister(wm8731);
679 679
diff --git a/sound/soc/codecs/wm8753.c b/sound/soc/codecs/wm8753.c
index a6e8f3f7f052..d28eeaceb857 100644
--- a/sound/soc/codecs/wm8753.c
+++ b/sound/soc/codecs/wm8753.c
@@ -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;
@@ -1822,14 +1822,14 @@ static int __devinit wm8753_spi_probe(struct spi_device *spi)
1822 codec->hw_write = (hw_write_t)wm8753_spi_write; 1822 codec->hw_write = (hw_write_t)wm8753_spi_write;
1823 codec->dev = &spi->dev; 1823 codec->dev = &spi->dev;
1824 1824
1825 spi->dev.driver_data = wm8753; 1825 dev_set_drvdata(&spi->dev, wm8753);
1826 1826
1827 return wm8753_register(wm8753); 1827 return wm8753_register(wm8753);
1828} 1828}
1829 1829
1830static int __devexit wm8753_spi_remove(struct spi_device *spi) 1830static int __devexit wm8753_spi_remove(struct spi_device *spi)
1831{ 1831{
1832 struct wm8753_priv *wm8753 = spi->dev.driver_data; 1832 struct wm8753_priv *wm8753 = dev_get_drvdata(&spi->dev);
1833 wm8753_unregister(wm8753); 1833 wm8753_unregister(wm8753);
1834 return 0; 1834 return 0;
1835} 1835}
diff --git a/sound/soc/codecs/wm8900.c b/sound/soc/codecs/wm8900.c
index 46c5ea1ff921..3c78945244b8 100644
--- a/sound/soc/codecs/wm8900.c
+++ b/sound/soc/codecs/wm8900.c
@@ -778,11 +778,11 @@ static int fll_factors(struct _fll_div *fll_div, unsigned int Fref,
778 } 778 }
779 779
780 if (target > 100000000) 780 if (target > 100000000)
781 printk(KERN_WARNING "wm8900: FLL rate %d out of range, Fref=%d" 781 printk(KERN_WARNING "wm8900: FLL rate %u out of range, Fref=%u"
782 " Fout=%d\n", target, Fref, Fout); 782 " Fout=%u\n", target, Fref, Fout);
783 if (div > 32) { 783 if (div > 32) {
784 printk(KERN_ERR "wm8900: Invalid FLL division rate %u, " 784 printk(KERN_ERR "wm8900: Invalid FLL division rate %u, "
785 "Fref=%d, Fout=%d, target=%d\n", 785 "Fref=%u, Fout=%u, target=%u\n",
786 div, Fref, Fout, target); 786 div, Fref, Fout, target);
787 return -EINVAL; 787 return -EINVAL;
788 } 788 }
diff --git a/sound/soc/codecs/wm8903.c b/sound/soc/codecs/wm8903.c
index 8cf571f1a803..d8a9222fbf74 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;
@@ -373,6 +372,15 @@ static void wm8903_reset(struct snd_soc_codec *codec)
373#define WM8903_OUTPUT_INT 0x2 372#define WM8903_OUTPUT_INT 0x2
374#define WM8903_OUTPUT_IN 0x1 373#define WM8903_OUTPUT_IN 0x1
375 374
375static int wm8903_cp_event(struct snd_soc_dapm_widget *w,
376 struct snd_kcontrol *kcontrol, int event)
377{
378 WARN_ON(event != SND_SOC_DAPM_POST_PMU);
379 mdelay(4);
380
381 return 0;
382}
383
376/* 384/*
377 * Event for headphone and line out amplifier power changes. Special 385 * Event for headphone and line out amplifier power changes. Special
378 * power up/down sequences are required in order to maximise pop/click 386 * power up/down sequences are required in order to maximise pop/click
@@ -382,19 +390,20 @@ static int wm8903_output_event(struct snd_soc_dapm_widget *w,
382 struct snd_kcontrol *kcontrol, int event) 390 struct snd_kcontrol *kcontrol, int event)
383{ 391{
384 struct snd_soc_codec *codec = w->codec; 392 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; 393 u16 val;
388 u16 reg; 394 u16 reg;
395 u16 dcs_reg;
396 u16 dcs_bit;
389 int shift; 397 int shift;
390 u16 cp_reg = wm8903_read(codec, WM8903_CHARGE_PUMP_0);
391 398
392 switch (w->reg) { 399 switch (w->reg) {
393 case WM8903_POWER_MANAGEMENT_2: 400 case WM8903_POWER_MANAGEMENT_2:
394 reg = WM8903_ANALOGUE_HP_0; 401 reg = WM8903_ANALOGUE_HP_0;
402 dcs_bit = 0 + w->shift;
395 break; 403 break;
396 case WM8903_POWER_MANAGEMENT_3: 404 case WM8903_POWER_MANAGEMENT_3:
397 reg = WM8903_ANALOGUE_LINEOUT_0; 405 reg = WM8903_ANALOGUE_LINEOUT_0;
406 dcs_bit = 2 + w->shift;
398 break; 407 break;
399 default: 408 default:
400 BUG(); 409 BUG();
@@ -419,18 +428,6 @@ static int wm8903_output_event(struct snd_soc_dapm_widget *w,
419 /* Short the output */ 428 /* Short the output */
420 val &= ~(WM8903_OUTPUT_SHORT << shift); 429 val &= ~(WM8903_OUTPUT_SHORT << shift);
421 wm8903_write(codec, reg, val); 430 wm8903_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 } 431 }
435 432
436 if (event & SND_SOC_DAPM_POST_PMU) { 433 if (event & SND_SOC_DAPM_POST_PMU) {
@@ -446,6 +443,11 @@ static int wm8903_output_event(struct snd_soc_dapm_widget *w,
446 val |= (WM8903_OUTPUT_OUT << shift); 443 val |= (WM8903_OUTPUT_OUT << shift);
447 wm8903_write(codec, reg, val); 444 wm8903_write(codec, reg, val);
448 445
446 /* Enable the DC servo */
447 dcs_reg = wm8903_read(codec, WM8903_DC_SERVO_0);
448 dcs_reg |= dcs_bit;
449 wm8903_write(codec, WM8903_DC_SERVO_0, dcs_reg);
450
449 /* Remove the short */ 451 /* Remove the short */
450 val |= (WM8903_OUTPUT_SHORT << shift); 452 val |= (WM8903_OUTPUT_SHORT << shift);
451 wm8903_write(codec, reg, val); 453 wm8903_write(codec, reg, val);
@@ -458,25 +460,17 @@ static int wm8903_output_event(struct snd_soc_dapm_widget *w,
458 val &= ~(WM8903_OUTPUT_SHORT << shift); 460 val &= ~(WM8903_OUTPUT_SHORT << shift);
459 wm8903_write(codec, reg, val); 461 wm8903_write(codec, reg, val);
460 462
463 /* Disable the DC servo */
464 dcs_reg = wm8903_read(codec, WM8903_DC_SERVO_0);
465 dcs_reg &= ~dcs_bit;
466 wm8903_write(codec, WM8903_DC_SERVO_0, dcs_reg);
467
461 /* Then disable the intermediate and output stages */ 468 /* Then disable the intermediate and output stages */
462 val &= ~((WM8903_OUTPUT_OUT | WM8903_OUTPUT_INT | 469 val &= ~((WM8903_OUTPUT_OUT | WM8903_OUTPUT_INT |
463 WM8903_OUTPUT_IN) << shift); 470 WM8903_OUTPUT_IN) << shift);
464 wm8903_write(codec, reg, val); 471 wm8903_write(codec, reg, val);
465 } 472 }
466 473
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 }
479
480 return 0; 474 return 0;
481} 475}
482 476
@@ -539,6 +533,7 @@ static int wm8903_class_w_put(struct snd_kcontrol *kcontrol,
539/* ALSA can only do steps of .01dB */ 533/* ALSA can only do steps of .01dB */
540static const DECLARE_TLV_DB_SCALE(digital_tlv, -7200, 75, 1); 534static const DECLARE_TLV_DB_SCALE(digital_tlv, -7200, 75, 1);
541 535
536static const DECLARE_TLV_DB_SCALE(digital_sidetone_tlv, -3600, 300, 0);
542static const DECLARE_TLV_DB_SCALE(out_tlv, -5700, 100, 0); 537static const DECLARE_TLV_DB_SCALE(out_tlv, -5700, 100, 0);
543 538
544static const DECLARE_TLV_DB_SCALE(drc_tlv_thresh, 0, 75, 0); 539static const DECLARE_TLV_DB_SCALE(drc_tlv_thresh, 0, 75, 0);
@@ -657,6 +652,16 @@ static const struct soc_enum rinput_inv_enum =
657 SOC_ENUM_SINGLE(WM8903_ANALOGUE_RIGHT_INPUT_1, 4, 3, rinput_mux_text); 652 SOC_ENUM_SINGLE(WM8903_ANALOGUE_RIGHT_INPUT_1, 4, 3, rinput_mux_text);
658 653
659 654
655static const char *sidetone_text[] = {
656 "None", "Left", "Right"
657};
658
659static const struct soc_enum lsidetone_enum =
660 SOC_ENUM_SINGLE(WM8903_DAC_DIGITAL_0, 2, 3, sidetone_text);
661
662static const struct soc_enum rsidetone_enum =
663 SOC_ENUM_SINGLE(WM8903_DAC_DIGITAL_0, 0, 3, sidetone_text);
664
660static const struct snd_kcontrol_new wm8903_snd_controls[] = { 665static const struct snd_kcontrol_new wm8903_snd_controls[] = {
661 666
662/* Input PGAs - No TLV since the scale depends on PGA mode */ 667/* Input PGAs - No TLV since the scale depends on PGA mode */
@@ -700,6 +705,9 @@ SOC_DOUBLE_R_TLV("Digital Capture Volume", WM8903_ADC_DIGITAL_VOLUME_LEFT,
700SOC_ENUM("ADC Companding Mode", adc_companding), 705SOC_ENUM("ADC Companding Mode", adc_companding),
701SOC_SINGLE("ADC Companding Switch", WM8903_AUDIO_INTERFACE_0, 3, 1, 0), 706SOC_SINGLE("ADC Companding Switch", WM8903_AUDIO_INTERFACE_0, 3, 1, 0),
702 707
708SOC_DOUBLE_TLV("Digital Sidetone Volume", WM8903_DAC_DIGITAL_0, 4, 8,
709 12, 0, digital_sidetone_tlv),
710
703/* DAC */ 711/* DAC */
704SOC_DOUBLE_R_TLV("Digital Playback Volume", WM8903_DAC_DIGITAL_VOLUME_LEFT, 712SOC_DOUBLE_R_TLV("Digital Playback Volume", WM8903_DAC_DIGITAL_VOLUME_LEFT,
705 WM8903_DAC_DIGITAL_VOLUME_RIGHT, 1, 120, 0, digital_tlv), 713 WM8903_DAC_DIGITAL_VOLUME_RIGHT, 1, 120, 0, digital_tlv),
@@ -762,6 +770,12 @@ static const struct snd_kcontrol_new rinput_mux =
762static const struct snd_kcontrol_new rinput_inv_mux = 770static const struct snd_kcontrol_new rinput_inv_mux =
763 SOC_DAPM_ENUM("Right Inverting Input Mux", rinput_inv_enum); 771 SOC_DAPM_ENUM("Right Inverting Input Mux", rinput_inv_enum);
764 772
773static const struct snd_kcontrol_new lsidetone_mux =
774 SOC_DAPM_ENUM("DACL Sidetone Mux", lsidetone_enum);
775
776static const struct snd_kcontrol_new rsidetone_mux =
777 SOC_DAPM_ENUM("DACR Sidetone Mux", rsidetone_enum);
778
765static const struct snd_kcontrol_new left_output_mixer[] = { 779static const struct snd_kcontrol_new left_output_mixer[] = {
766SOC_DAPM_SINGLE("DACL Switch", WM8903_ANALOGUE_LEFT_MIX_0, 3, 1, 0), 780SOC_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), 781SOC_DAPM_SINGLE("DACR Switch", WM8903_ANALOGUE_LEFT_MIX_0, 2, 1, 0),
@@ -828,6 +842,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), 842SND_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), 843SND_SOC_DAPM_ADC("ADCR", "Right HiFi Capture", WM8903_POWER_MANAGEMENT_6, 0, 0),
830 844
845SND_SOC_DAPM_MUX("DACL Sidetone", SND_SOC_NOPM, 0, 0, &lsidetone_mux),
846SND_SOC_DAPM_MUX("DACR Sidetone", SND_SOC_NOPM, 0, 0, &rsidetone_mux),
847
831SND_SOC_DAPM_DAC("DACL", "Left Playback", WM8903_POWER_MANAGEMENT_6, 3, 0), 848SND_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), 849SND_SOC_DAPM_DAC("DACR", "Right Playback", WM8903_POWER_MANAGEMENT_6, 2, 0),
833 850
@@ -844,26 +861,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, 861SND_SOC_DAPM_PGA_E("Left Headphone Output PGA", WM8903_POWER_MANAGEMENT_2,
845 1, 0, NULL, 0, wm8903_output_event, 862 1, 0, NULL, 0, wm8903_output_event,
846 SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU | 863 SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
847 SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD), 864 SND_SOC_DAPM_PRE_PMD),
848SND_SOC_DAPM_PGA_E("Right Headphone Output PGA", WM8903_POWER_MANAGEMENT_2, 865SND_SOC_DAPM_PGA_E("Right Headphone Output PGA", WM8903_POWER_MANAGEMENT_2,
849 0, 0, NULL, 0, wm8903_output_event, 866 0, 0, NULL, 0, wm8903_output_event,
850 SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU | 867 SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
851 SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD), 868 SND_SOC_DAPM_PRE_PMD),
852 869
853SND_SOC_DAPM_PGA_E("Left Line Output PGA", WM8903_POWER_MANAGEMENT_3, 1, 0, 870SND_SOC_DAPM_PGA_E("Left Line Output PGA", WM8903_POWER_MANAGEMENT_3, 1, 0,
854 NULL, 0, wm8903_output_event, 871 NULL, 0, wm8903_output_event,
855 SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU | 872 SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
856 SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD), 873 SND_SOC_DAPM_PRE_PMD),
857SND_SOC_DAPM_PGA_E("Right Line Output PGA", WM8903_POWER_MANAGEMENT_3, 0, 0, 874SND_SOC_DAPM_PGA_E("Right Line Output PGA", WM8903_POWER_MANAGEMENT_3, 0, 0,
858 NULL, 0, wm8903_output_event, 875 NULL, 0, wm8903_output_event,
859 SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU | 876 SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
860 SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD), 877 SND_SOC_DAPM_PRE_PMD),
861 878
862SND_SOC_DAPM_PGA("Left Speaker PGA", WM8903_POWER_MANAGEMENT_5, 1, 0, 879SND_SOC_DAPM_PGA("Left Speaker PGA", WM8903_POWER_MANAGEMENT_5, 1, 0,
863 NULL, 0), 880 NULL, 0),
864SND_SOC_DAPM_PGA("Right Speaker PGA", WM8903_POWER_MANAGEMENT_5, 0, 0, 881SND_SOC_DAPM_PGA("Right Speaker PGA", WM8903_POWER_MANAGEMENT_5, 0, 0,
865 NULL, 0), 882 NULL, 0),
866 883
884SND_SOC_DAPM_SUPPLY("Charge Pump", WM8903_CHARGE_PUMP_0, 0, 0,
885 wm8903_cp_event, SND_SOC_DAPM_POST_PMU),
886SND_SOC_DAPM_SUPPLY("CLK_DSP", WM8903_CLOCK_RATES_2, 1, 0, NULL, 0),
867}; 887};
868 888
869static const struct snd_soc_dapm_route intercon[] = { 889static const struct snd_soc_dapm_route intercon[] = {
@@ -909,7 +929,19 @@ static const struct snd_soc_dapm_route intercon[] = {
909 { "Right Input PGA", NULL, "Right Input Mode Mux" }, 929 { "Right Input PGA", NULL, "Right Input Mode Mux" },
910 930
911 { "ADCL", NULL, "Left Input PGA" }, 931 { "ADCL", NULL, "Left Input PGA" },
932 { "ADCL", NULL, "CLK_DSP" },
912 { "ADCR", NULL, "Right Input PGA" }, 933 { "ADCR", NULL, "Right Input PGA" },
934 { "ADCR", NULL, "CLK_DSP" },
935
936 { "DACL Sidetone", "Left", "ADCL" },
937 { "DACL Sidetone", "Right", "ADCR" },
938 { "DACR Sidetone", "Left", "ADCL" },
939 { "DACR Sidetone", "Right", "ADCR" },
940
941 { "DACL", NULL, "DACL Sidetone" },
942 { "DACL", NULL, "CLK_DSP" },
943 { "DACR", NULL, "DACR Sidetone" },
944 { "DACR", NULL, "CLK_DSP" },
913 945
914 { "Left Output Mixer", "Left Bypass Switch", "Left Input PGA" }, 946 { "Left Output Mixer", "Left Bypass Switch", "Left Input PGA" },
915 { "Left Output Mixer", "Right Bypass Switch", "Right Input PGA" }, 947 { "Left Output Mixer", "Right Bypass Switch", "Right Input PGA" },
@@ -951,6 +983,11 @@ static const struct snd_soc_dapm_route intercon[] = {
951 983
952 { "ROP", NULL, "Right Speaker PGA" }, 984 { "ROP", NULL, "Right Speaker PGA" },
953 { "RON", NULL, "Right Speaker PGA" }, 985 { "RON", NULL, "Right Speaker PGA" },
986
987 { "Left Headphone Output PGA", NULL, "Charge Pump" },
988 { "Right Headphone Output PGA", NULL, "Charge Pump" },
989 { "Left Line Output PGA", NULL, "Charge Pump" },
990 { "Right Line Output PGA", NULL, "Charge Pump" },
954}; 991};
955 992
956static int wm8903_add_widgets(struct snd_soc_codec *codec) 993static int wm8903_add_widgets(struct snd_soc_codec *codec)
@@ -985,6 +1022,11 @@ static int wm8903_set_bias_level(struct snd_soc_codec *codec,
985 wm8903_write(codec, WM8903_CLOCK_RATES_2, 1022 wm8903_write(codec, WM8903_CLOCK_RATES_2,
986 WM8903_CLK_SYS_ENA); 1023 WM8903_CLK_SYS_ENA);
987 1024
1025 /* Change DC servo dither level in startup sequence */
1026 wm8903_write(codec, WM8903_WRITE_SEQUENCER_0, 0x11);
1027 wm8903_write(codec, WM8903_WRITE_SEQUENCER_1, 0x1257);
1028 wm8903_write(codec, WM8903_WRITE_SEQUENCER_2, 0x2);
1029
988 wm8903_run_sequence(codec, 0); 1030 wm8903_run_sequence(codec, 0);
989 wm8903_sync_reg_cache(codec, codec->reg_cache); 1031 wm8903_sync_reg_cache(codec, codec->reg_cache);
990 1032
@@ -1277,14 +1319,8 @@ static int wm8903_startup(struct snd_pcm_substream *substream,
1277 if (wm8903->master_substream) { 1319 if (wm8903->master_substream) {
1278 master_runtime = wm8903->master_substream->runtime; 1320 master_runtime = wm8903->master_substream->runtime;
1279 1321
1280 dev_dbg(&i2c->dev, "Constraining to %d bits at %dHz\n", 1322 dev_dbg(&i2c->dev, "Constraining to %d bits\n",
1281 master_runtime->sample_bits, 1323 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 1324
1289 snd_pcm_hw_constraint_minmax(substream->runtime, 1325 snd_pcm_hw_constraint_minmax(substream->runtime,
1290 SNDRV_PCM_HW_PARAM_SAMPLE_BITS, 1326 SNDRV_PCM_HW_PARAM_SAMPLE_BITS,
@@ -1523,6 +1559,7 @@ struct snd_soc_dai wm8903_dai = {
1523 .formats = WM8903_FORMATS, 1559 .formats = WM8903_FORMATS,
1524 }, 1560 },
1525 .ops = &wm8903_dai_ops, 1561 .ops = &wm8903_dai_ops,
1562 .symmetric_rates = 1,
1526}; 1563};
1527EXPORT_SYMBOL_GPL(wm8903_dai); 1564EXPORT_SYMBOL_GPL(wm8903_dai);
1528 1565
diff --git a/sound/soc/codecs/wm8940.c b/sound/soc/codecs/wm8940.c
new file mode 100644
index 000000000000..b8e17d6bc1f7
--- /dev/null
+++ b/sound/soc/codecs/wm8940.c
@@ -0,0 +1,955 @@
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 inline unsigned int wm8940_read_reg_cache(struct snd_soc_codec *codec,
110 unsigned int reg)
111{
112 u16 *cache = codec->reg_cache;
113
114 if (reg >= ARRAY_SIZE(wm8940_reg_defaults))
115 return -1;
116
117 return cache[reg];
118}
119
120static inline int wm8940_write_reg_cache(struct snd_soc_codec *codec,
121 u16 reg, unsigned int value)
122{
123 u16 *cache = codec->reg_cache;
124
125 if (reg >= ARRAY_SIZE(wm8940_reg_defaults))
126 return -1;
127
128 cache[reg] = value;
129
130 return 0;
131}
132
133static int wm8940_write(struct snd_soc_codec *codec, unsigned int reg,
134 unsigned int value)
135{
136 int ret;
137 u8 data[3] = { reg,
138 (value & 0xff00) >> 8,
139 (value & 0x00ff)
140 };
141
142 wm8940_write_reg_cache(codec, reg, value);
143
144 ret = codec->hw_write(codec->control_data, data, 3);
145
146 if (ret < 0)
147 return ret;
148 else if (ret != 3)
149 return -EIO;
150 return 0;
151}
152
153static const char *wm8940_companding[] = { "Off", "NC", "u-law", "A-law" };
154static const struct soc_enum wm8940_adc_companding_enum
155= SOC_ENUM_SINGLE(WM8940_COMPANDINGCTL, 1, 4, wm8940_companding);
156static const struct soc_enum wm8940_dac_companding_enum
157= SOC_ENUM_SINGLE(WM8940_COMPANDINGCTL, 3, 4, wm8940_companding);
158
159static const char *wm8940_alc_mode_text[] = {"ALC", "Limiter"};
160static const struct soc_enum wm8940_alc_mode_enum
161= SOC_ENUM_SINGLE(WM8940_ALC3, 8, 2, wm8940_alc_mode_text);
162
163static const char *wm8940_mic_bias_level_text[] = {"0.9", "0.65"};
164static const struct soc_enum wm8940_mic_bias_level_enum
165= SOC_ENUM_SINGLE(WM8940_INPUTCTL, 8, 2, wm8940_mic_bias_level_text);
166
167static const char *wm8940_filter_mode_text[] = {"Audio", "Application"};
168static const struct soc_enum wm8940_filter_mode_enum
169= SOC_ENUM_SINGLE(WM8940_ADC, 7, 2, wm8940_filter_mode_text);
170
171static DECLARE_TLV_DB_SCALE(wm8940_spk_vol_tlv, -5700, 100, 1);
172static DECLARE_TLV_DB_SCALE(wm8940_att_tlv, -1000, 1000, 0);
173static DECLARE_TLV_DB_SCALE(wm8940_pga_vol_tlv, -1200, 75, 0);
174static DECLARE_TLV_DB_SCALE(wm8940_alc_min_tlv, -1200, 600, 0);
175static DECLARE_TLV_DB_SCALE(wm8940_alc_max_tlv, 675, 600, 0);
176static DECLARE_TLV_DB_SCALE(wm8940_alc_tar_tlv, -2250, 50, 0);
177static DECLARE_TLV_DB_SCALE(wm8940_lim_boost_tlv, 0, 100, 0);
178static DECLARE_TLV_DB_SCALE(wm8940_lim_thresh_tlv, -600, 100, 0);
179static DECLARE_TLV_DB_SCALE(wm8940_adc_tlv, -12750, 50, 1);
180static DECLARE_TLV_DB_SCALE(wm8940_capture_boost_vol_tlv, 0, 2000, 0);
181
182static const struct snd_kcontrol_new wm8940_snd_controls[] = {
183 SOC_SINGLE("Digital Loopback Switch", WM8940_COMPANDINGCTL,
184 6, 1, 0),
185 SOC_ENUM("DAC Companding", wm8940_dac_companding_enum),
186 SOC_ENUM("ADC Companding", wm8940_adc_companding_enum),
187
188 SOC_ENUM("ALC Mode", wm8940_alc_mode_enum),
189 SOC_SINGLE("ALC Switch", WM8940_ALC1, 8, 1, 0),
190 SOC_SINGLE_TLV("ALC Capture Max Gain", WM8940_ALC1,
191 3, 7, 1, wm8940_alc_max_tlv),
192 SOC_SINGLE_TLV("ALC Capture Min Gain", WM8940_ALC1,
193 0, 7, 0, wm8940_alc_min_tlv),
194 SOC_SINGLE_TLV("ALC Capture Target", WM8940_ALC2,
195 0, 14, 0, wm8940_alc_tar_tlv),
196 SOC_SINGLE("ALC Capture Hold", WM8940_ALC2, 4, 10, 0),
197 SOC_SINGLE("ALC Capture Decay", WM8940_ALC3, 4, 10, 0),
198 SOC_SINGLE("ALC Capture Attach", WM8940_ALC3, 0, 10, 0),
199 SOC_SINGLE("ALC ZC Switch", WM8940_ALC4, 1, 1, 0),
200 SOC_SINGLE("ALC Capture Noise Gate Switch", WM8940_NOISEGATE,
201 3, 1, 0),
202 SOC_SINGLE("ALC Capture Noise Gate Threshold", WM8940_NOISEGATE,
203 0, 7, 0),
204
205 SOC_SINGLE("DAC Playback Limiter Switch", WM8940_DACLIM1, 8, 1, 0),
206 SOC_SINGLE("DAC Playback Limiter Attack", WM8940_DACLIM1, 0, 9, 0),
207 SOC_SINGLE("DAC Playback Limiter Decay", WM8940_DACLIM1, 4, 11, 0),
208 SOC_SINGLE_TLV("DAC Playback Limiter Threshold", WM8940_DACLIM2,
209 4, 9, 1, wm8940_lim_thresh_tlv),
210 SOC_SINGLE_TLV("DAC Playback Limiter Boost", WM8940_DACLIM2,
211 0, 12, 0, wm8940_lim_boost_tlv),
212
213 SOC_SINGLE("Capture PGA ZC Switch", WM8940_PGAGAIN, 7, 1, 0),
214 SOC_SINGLE_TLV("Capture PGA Volume", WM8940_PGAGAIN,
215 0, 63, 0, wm8940_pga_vol_tlv),
216 SOC_SINGLE_TLV("Digital Playback Volume", WM8940_DACVOL,
217 0, 255, 0, wm8940_adc_tlv),
218 SOC_SINGLE_TLV("Digital Capture Volume", WM8940_ADCVOL,
219 0, 255, 0, wm8940_adc_tlv),
220 SOC_ENUM("Mic Bias Level", wm8940_mic_bias_level_enum),
221 SOC_SINGLE_TLV("Capture Boost Volue", WM8940_ADCBOOST,
222 8, 1, 0, wm8940_capture_boost_vol_tlv),
223 SOC_SINGLE_TLV("Speaker Playback Volume", WM8940_SPKVOL,
224 0, 63, 0, wm8940_spk_vol_tlv),
225 SOC_SINGLE("Speaker Playback Switch", WM8940_SPKVOL, 6, 1, 1),
226
227 SOC_SINGLE_TLV("Speaker Mixer Line Bypass Volume", WM8940_SPKVOL,
228 8, 1, 1, wm8940_att_tlv),
229 SOC_SINGLE("Speaker Playback ZC Switch", WM8940_SPKVOL, 7, 1, 0),
230
231 SOC_SINGLE("Mono Out Switch", WM8940_MONOMIX, 6, 1, 1),
232 SOC_SINGLE_TLV("Mono Mixer Line Bypass Volume", WM8940_MONOMIX,
233 7, 1, 1, wm8940_att_tlv),
234
235 SOC_SINGLE("High Pass Filter Switch", WM8940_ADC, 8, 1, 0),
236 SOC_ENUM("High Pass Filter Mode", wm8940_filter_mode_enum),
237 SOC_SINGLE("High Pass Filter Cut Off", WM8940_ADC, 4, 7, 0),
238 SOC_SINGLE("ADC Inversion Switch", WM8940_ADC, 0, 1, 0),
239 SOC_SINGLE("DAC Inversion Switch", WM8940_DAC, 0, 1, 0),
240 SOC_SINGLE("DAC Auto Mute Switch", WM8940_DAC, 2, 1, 0),
241 SOC_SINGLE("ZC Timeout Clock Switch", WM8940_ADDCNTRL, 0, 1, 0),
242};
243
244static const struct snd_kcontrol_new wm8940_speaker_mixer_controls[] = {
245 SOC_DAPM_SINGLE("Line Bypass Switch", WM8940_SPKMIX, 1, 1, 0),
246 SOC_DAPM_SINGLE("Aux Playback Switch", WM8940_SPKMIX, 5, 1, 0),
247 SOC_DAPM_SINGLE("PCM Playback Switch", WM8940_SPKMIX, 0, 1, 0),
248};
249
250static const struct snd_kcontrol_new wm8940_mono_mixer_controls[] = {
251 SOC_DAPM_SINGLE("Line Bypass Switch", WM8940_MONOMIX, 1, 1, 0),
252 SOC_DAPM_SINGLE("Aux Playback Switch", WM8940_MONOMIX, 2, 1, 0),
253 SOC_DAPM_SINGLE("PCM Playback Switch", WM8940_MONOMIX, 0, 1, 0),
254};
255
256static DECLARE_TLV_DB_SCALE(wm8940_boost_vol_tlv, -1500, 300, 1);
257static const struct snd_kcontrol_new wm8940_input_boost_controls[] = {
258 SOC_DAPM_SINGLE("Mic PGA Switch", WM8940_PGAGAIN, 6, 1, 1),
259 SOC_DAPM_SINGLE_TLV("Aux Volume", WM8940_ADCBOOST,
260 0, 7, 0, wm8940_boost_vol_tlv),
261 SOC_DAPM_SINGLE_TLV("Mic Volume", WM8940_ADCBOOST,
262 4, 7, 0, wm8940_boost_vol_tlv),
263};
264
265static const struct snd_kcontrol_new wm8940_micpga_controls[] = {
266 SOC_DAPM_SINGLE("AUX Switch", WM8940_INPUTCTL, 2, 1, 0),
267 SOC_DAPM_SINGLE("MICP Switch", WM8940_INPUTCTL, 0, 1, 0),
268 SOC_DAPM_SINGLE("MICN Switch", WM8940_INPUTCTL, 1, 1, 0),
269};
270
271static const struct snd_soc_dapm_widget wm8940_dapm_widgets[] = {
272 SND_SOC_DAPM_MIXER("Speaker Mixer", WM8940_POWER3, 2, 0,
273 &wm8940_speaker_mixer_controls[0],
274 ARRAY_SIZE(wm8940_speaker_mixer_controls)),
275 SND_SOC_DAPM_MIXER("Mono Mixer", WM8940_POWER3, 3, 0,
276 &wm8940_mono_mixer_controls[0],
277 ARRAY_SIZE(wm8940_mono_mixer_controls)),
278 SND_SOC_DAPM_DAC("DAC", "HiFi Playback", WM8940_POWER3, 0, 0),
279
280 SND_SOC_DAPM_PGA("SpkN Out", WM8940_POWER3, 5, 0, NULL, 0),
281 SND_SOC_DAPM_PGA("SpkP Out", WM8940_POWER3, 6, 0, NULL, 0),
282 SND_SOC_DAPM_PGA("Mono Out", WM8940_POWER3, 7, 0, NULL, 0),
283 SND_SOC_DAPM_OUTPUT("MONOOUT"),
284 SND_SOC_DAPM_OUTPUT("SPKOUTP"),
285 SND_SOC_DAPM_OUTPUT("SPKOUTN"),
286
287 SND_SOC_DAPM_PGA("Aux Input", WM8940_POWER1, 6, 0, NULL, 0),
288 SND_SOC_DAPM_ADC("ADC", "HiFi Capture", WM8940_POWER2, 0, 0),
289 SND_SOC_DAPM_MIXER("Mic PGA", WM8940_POWER2, 2, 0,
290 &wm8940_micpga_controls[0],
291 ARRAY_SIZE(wm8940_micpga_controls)),
292 SND_SOC_DAPM_MIXER("Boost Mixer", WM8940_POWER2, 4, 0,
293 &wm8940_input_boost_controls[0],
294 ARRAY_SIZE(wm8940_input_boost_controls)),
295 SND_SOC_DAPM_MICBIAS("Mic Bias", WM8940_POWER1, 4, 0),
296
297 SND_SOC_DAPM_INPUT("MICN"),
298 SND_SOC_DAPM_INPUT("MICP"),
299 SND_SOC_DAPM_INPUT("AUX"),
300};
301
302static const struct snd_soc_dapm_route audio_map[] = {
303 /* Mono output mixer */
304 {"Mono Mixer", "PCM Playback Switch", "DAC"},
305 {"Mono Mixer", "Aux Playback Switch", "Aux Input"},
306 {"Mono Mixer", "Line Bypass Switch", "Boost Mixer"},
307
308 /* Speaker output mixer */
309 {"Speaker Mixer", "PCM Playback Switch", "DAC"},
310 {"Speaker Mixer", "Aux Playback Switch", "Aux Input"},
311 {"Speaker Mixer", "Line Bypass Switch", "Boost Mixer"},
312
313 /* Outputs */
314 {"Mono Out", NULL, "Mono Mixer"},
315 {"MONOOUT", NULL, "Mono Out"},
316 {"SpkN Out", NULL, "Speaker Mixer"},
317 {"SpkP Out", NULL, "Speaker Mixer"},
318 {"SPKOUTN", NULL, "SpkN Out"},
319 {"SPKOUTP", NULL, "SpkP Out"},
320
321 /* Microphone PGA */
322 {"Mic PGA", "MICN Switch", "MICN"},
323 {"Mic PGA", "MICP Switch", "MICP"},
324 {"Mic PGA", "AUX Switch", "AUX"},
325
326 /* Boost Mixer */
327 {"Boost Mixer", "Mic PGA Switch", "Mic PGA"},
328 {"Boost Mixer", "Mic Volume", "MICP"},
329 {"Boost Mixer", "Aux Volume", "Aux Input"},
330
331 {"ADC", NULL, "Boost Mixer"},
332};
333
334static int wm8940_add_widgets(struct snd_soc_codec *codec)
335{
336 int ret;
337
338 ret = snd_soc_dapm_new_controls(codec, wm8940_dapm_widgets,
339 ARRAY_SIZE(wm8940_dapm_widgets));
340 if (ret)
341 goto error_ret;
342 ret = snd_soc_dapm_add_routes(codec, audio_map, ARRAY_SIZE(audio_map));
343 if (ret)
344 goto error_ret;
345 ret = snd_soc_dapm_new_widgets(codec);
346
347error_ret:
348 return ret;
349}
350
351#define wm8940_reset(c) wm8940_write(c, WM8940_SOFTRESET, 0);
352
353static int wm8940_set_dai_fmt(struct snd_soc_dai *codec_dai,
354 unsigned int fmt)
355{
356 struct snd_soc_codec *codec = codec_dai->codec;
357 u16 iface = wm8940_read_reg_cache(codec, WM8940_IFACE) & 0xFE67;
358 u16 clk = wm8940_read_reg_cache(codec, WM8940_CLOCK) & 0x1fe;
359
360 switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
361 case SND_SOC_DAIFMT_CBM_CFM:
362 clk |= 1;
363 break;
364 case SND_SOC_DAIFMT_CBS_CFS:
365 break;
366 default:
367 return -EINVAL;
368 }
369 wm8940_write(codec, WM8940_CLOCK, clk);
370
371 switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
372 case SND_SOC_DAIFMT_I2S:
373 iface |= (2 << 3);
374 break;
375 case SND_SOC_DAIFMT_LEFT_J:
376 iface |= (1 << 3);
377 break;
378 case SND_SOC_DAIFMT_RIGHT_J:
379 break;
380 case SND_SOC_DAIFMT_DSP_A:
381 iface |= (3 << 3);
382 break;
383 case SND_SOC_DAIFMT_DSP_B:
384 iface |= (3 << 3) | (1 << 7);
385 break;
386 }
387
388 switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
389 case SND_SOC_DAIFMT_NB_NF:
390 break;
391 case SND_SOC_DAIFMT_NB_IF:
392 iface |= (1 << 7);
393 break;
394 case SND_SOC_DAIFMT_IB_NF:
395 iface |= (1 << 8);
396 break;
397 case SND_SOC_DAIFMT_IB_IF:
398 iface |= (1 << 8) | (1 << 7);
399 break;
400 }
401
402 wm8940_write(codec, WM8940_IFACE, iface);
403
404 return 0;
405}
406
407static int wm8940_i2s_hw_params(struct snd_pcm_substream *substream,
408 struct snd_pcm_hw_params *params,
409 struct snd_soc_dai *dai)
410{
411 struct snd_soc_pcm_runtime *rtd = substream->private_data;
412 struct snd_soc_device *socdev = rtd->socdev;
413 struct snd_soc_codec *codec = socdev->card->codec;
414 u16 iface = wm8940_read_reg_cache(codec, WM8940_IFACE) & 0xFD9F;
415 u16 addcntrl = wm8940_read_reg_cache(codec, WM8940_ADDCNTRL) & 0xFFF1;
416 u16 companding = wm8940_read_reg_cache(codec,
417 WM8940_COMPANDINGCTL) & 0xFFDF;
418 int ret;
419
420 /* LoutR control */
421 if (substream->stream == SNDRV_PCM_STREAM_CAPTURE
422 && params_channels(params) == 2)
423 iface |= (1 << 9);
424
425 switch (params_rate(params)) {
426 case SNDRV_PCM_RATE_8000:
427 addcntrl |= (0x5 << 1);
428 break;
429 case SNDRV_PCM_RATE_11025:
430 addcntrl |= (0x4 << 1);
431 break;
432 case SNDRV_PCM_RATE_16000:
433 addcntrl |= (0x3 << 1);
434 break;
435 case SNDRV_PCM_RATE_22050:
436 addcntrl |= (0x2 << 1);
437 break;
438 case SNDRV_PCM_RATE_32000:
439 addcntrl |= (0x1 << 1);
440 break;
441 case SNDRV_PCM_RATE_44100:
442 case SNDRV_PCM_RATE_48000:
443 break;
444 }
445 ret = wm8940_write(codec, WM8940_ADDCNTRL, addcntrl);
446 if (ret)
447 goto error_ret;
448
449 switch (params_format(params)) {
450 case SNDRV_PCM_FORMAT_S8:
451 companding = companding | (1 << 5);
452 break;
453 case SNDRV_PCM_FORMAT_S16_LE:
454 break;
455 case SNDRV_PCM_FORMAT_S20_3LE:
456 iface |= (1 << 5);
457 break;
458 case SNDRV_PCM_FORMAT_S24_LE:
459 iface |= (2 << 5);
460 break;
461 case SNDRV_PCM_FORMAT_S32_LE:
462 iface |= (3 << 5);
463 break;
464 }
465 ret = wm8940_write(codec, WM8940_COMPANDINGCTL, companding);
466 if (ret)
467 goto error_ret;
468 ret = wm8940_write(codec, WM8940_IFACE, iface);
469
470error_ret:
471 return ret;
472}
473
474static int wm8940_mute(struct snd_soc_dai *dai, int mute)
475{
476 struct snd_soc_codec *codec = dai->codec;
477 u16 mute_reg = wm8940_read_reg_cache(codec, WM8940_DAC) & 0xffbf;
478
479 if (mute)
480 mute_reg |= 0x40;
481
482 return wm8940_write(codec, WM8940_DAC, mute_reg);
483}
484
485static int wm8940_set_bias_level(struct snd_soc_codec *codec,
486 enum snd_soc_bias_level level)
487{
488 u16 val;
489 u16 pwr_reg = wm8940_read_reg_cache(codec, WM8940_POWER1) & 0x1F0;
490 int ret = 0;
491
492 switch (level) {
493 case SND_SOC_BIAS_ON:
494 /* ensure bufioen and biasen */
495 pwr_reg |= (1 << 2) | (1 << 3);
496 /* Enable thermal shutdown */
497 val = wm8940_read_reg_cache(codec, WM8940_OUTPUTCTL);
498 ret = wm8940_write(codec, WM8940_OUTPUTCTL, val | 0x2);
499 if (ret)
500 break;
501 /* set vmid to 75k */
502 ret = wm8940_write(codec, WM8940_POWER1, pwr_reg | 0x1);
503 break;
504 case SND_SOC_BIAS_PREPARE:
505 /* ensure bufioen and biasen */
506 pwr_reg |= (1 << 2) | (1 << 3);
507 ret = wm8940_write(codec, WM8940_POWER1, pwr_reg | 0x1);
508 break;
509 case SND_SOC_BIAS_STANDBY:
510 /* ensure bufioen and biasen */
511 pwr_reg |= (1 << 2) | (1 << 3);
512 /* set vmid to 300k for standby */
513 ret = wm8940_write(codec, WM8940_POWER1, pwr_reg | 0x2);
514 break;
515 case SND_SOC_BIAS_OFF:
516 ret = wm8940_write(codec, WM8940_POWER1, pwr_reg);
517 break;
518 }
519
520 return ret;
521}
522
523struct pll_ {
524 unsigned int pre_scale:2;
525 unsigned int n:4;
526 unsigned int k;
527};
528
529static struct pll_ pll_div;
530
531/* The size in bits of the pll divide multiplied by 10
532 * to allow rounding later */
533#define FIXED_PLL_SIZE ((1 << 24) * 10)
534static void pll_factors(unsigned int target, unsigned int source)
535{
536 unsigned long long Kpart;
537 unsigned int K, Ndiv, Nmod;
538 /* The left shift ist to avoid accuracy loss when right shifting */
539 Ndiv = target / source;
540
541 if (Ndiv > 12) {
542 source <<= 1;
543 /* Multiply by 2 */
544 pll_div.pre_scale = 0;
545 Ndiv = target / source;
546 } else if (Ndiv < 3) {
547 source >>= 2;
548 /* Divide by 4 */
549 pll_div.pre_scale = 3;
550 Ndiv = target / source;
551 } else if (Ndiv < 6) {
552 source >>= 1;
553 /* divide by 2 */
554 pll_div.pre_scale = 2;
555 Ndiv = target / source;
556 } else
557 pll_div.pre_scale = 1;
558
559 if ((Ndiv < 6) || (Ndiv > 12))
560 printk(KERN_WARNING
561 "WM8940 N value %d outwith recommended range!d\n",
562 Ndiv);
563
564 pll_div.n = Ndiv;
565 Nmod = target % source;
566 Kpart = FIXED_PLL_SIZE * (long long)Nmod;
567
568 do_div(Kpart, source);
569
570 K = Kpart & 0xFFFFFFFF;
571
572 /* Check if we need to round */
573 if ((K % 10) >= 5)
574 K += 5;
575
576 /* Move down to proper range now rounding is done */
577 K /= 10;
578
579 pll_div.k = K;
580}
581
582/* Untested at the moment */
583static int wm8940_set_dai_pll(struct snd_soc_dai *codec_dai,
584 int pll_id, unsigned int freq_in, unsigned int freq_out)
585{
586 struct snd_soc_codec *codec = codec_dai->codec;
587 u16 reg;
588
589 /* Turn off PLL */
590 reg = wm8940_read_reg_cache(codec, WM8940_POWER1);
591 wm8940_write(codec, WM8940_POWER1, reg & 0x1df);
592
593 if (freq_in == 0 || freq_out == 0) {
594 /* Clock CODEC directly from MCLK */
595 reg = wm8940_read_reg_cache(codec, WM8940_CLOCK);
596 wm8940_write(codec, WM8940_CLOCK, reg & 0x0ff);
597 /* Pll power down */
598 wm8940_write(codec, WM8940_PLLN, (1 << 7));
599 return 0;
600 }
601
602 /* Pll is followed by a frequency divide by 4 */
603 pll_factors(freq_out*4, freq_in);
604 if (pll_div.k)
605 wm8940_write(codec, WM8940_PLLN,
606 (pll_div.pre_scale << 4) | pll_div.n | (1 << 6));
607 else /* No factional component */
608 wm8940_write(codec, WM8940_PLLN,
609 (pll_div.pre_scale << 4) | pll_div.n);
610 wm8940_write(codec, WM8940_PLLK1, pll_div.k >> 18);
611 wm8940_write(codec, WM8940_PLLK2, (pll_div.k >> 9) & 0x1ff);
612 wm8940_write(codec, WM8940_PLLK3, pll_div.k & 0x1ff);
613 /* Enable the PLL */
614 reg = wm8940_read_reg_cache(codec, WM8940_POWER1);
615 wm8940_write(codec, WM8940_POWER1, reg | 0x020);
616
617 /* Run CODEC from PLL instead of MCLK */
618 reg = wm8940_read_reg_cache(codec, WM8940_CLOCK);
619 wm8940_write(codec, WM8940_CLOCK, reg | 0x100);
620
621 return 0;
622}
623
624static int wm8940_set_dai_sysclk(struct snd_soc_dai *codec_dai,
625 int clk_id, unsigned int freq, int dir)
626{
627 struct snd_soc_codec *codec = codec_dai->codec;
628 struct wm8940_priv *wm8940 = codec->private_data;
629
630 switch (freq) {
631 case 11289600:
632 case 12000000:
633 case 12288000:
634 case 16934400:
635 case 18432000:
636 wm8940->sysclk = freq;
637 return 0;
638 }
639 return -EINVAL;
640}
641
642static int wm8940_set_dai_clkdiv(struct snd_soc_dai *codec_dai,
643 int div_id, int div)
644{
645 struct snd_soc_codec *codec = codec_dai->codec;
646 u16 reg;
647 int ret = 0;
648
649 switch (div_id) {
650 case WM8940_BCLKDIV:
651 reg = wm8940_read_reg_cache(codec, WM8940_CLOCK) & 0xFFEF3;
652 ret = wm8940_write(codec, WM8940_CLOCK, reg | (div << 2));
653 break;
654 case WM8940_MCLKDIV:
655 reg = wm8940_read_reg_cache(codec, WM8940_CLOCK) & 0xFF1F;
656 ret = wm8940_write(codec, WM8940_CLOCK, reg | (div << 5));
657 break;
658 case WM8940_OPCLKDIV:
659 reg = wm8940_read_reg_cache(codec, WM8940_ADDCNTRL) & 0xFFCF;
660 ret = wm8940_write(codec, WM8940_ADDCNTRL, reg | (div << 4));
661 break;
662 }
663 return ret;
664}
665
666#define WM8940_RATES SNDRV_PCM_RATE_8000_48000
667
668#define WM8940_FORMATS (SNDRV_PCM_FMTBIT_S8 | \
669 SNDRV_PCM_FMTBIT_S16_LE | \
670 SNDRV_PCM_FMTBIT_S20_3LE | \
671 SNDRV_PCM_FMTBIT_S24_LE | \
672 SNDRV_PCM_FMTBIT_S32_LE)
673
674static struct snd_soc_dai_ops wm8940_dai_ops = {
675 .hw_params = wm8940_i2s_hw_params,
676 .set_sysclk = wm8940_set_dai_sysclk,
677 .digital_mute = wm8940_mute,
678 .set_fmt = wm8940_set_dai_fmt,
679 .set_clkdiv = wm8940_set_dai_clkdiv,
680 .set_pll = wm8940_set_dai_pll,
681};
682
683struct snd_soc_dai wm8940_dai = {
684 .name = "WM8940",
685 .playback = {
686 .stream_name = "Playback",
687 .channels_min = 1,
688 .channels_max = 2,
689 .rates = WM8940_RATES,
690 .formats = WM8940_FORMATS,
691 },
692 .capture = {
693 .stream_name = "Capture",
694 .channels_min = 1,
695 .channels_max = 2,
696 .rates = WM8940_RATES,
697 .formats = WM8940_FORMATS,
698 },
699 .ops = &wm8940_dai_ops,
700 .symmetric_rates = 1,
701};
702EXPORT_SYMBOL_GPL(wm8940_dai);
703
704static int wm8940_suspend(struct platform_device *pdev, pm_message_t state)
705{
706 struct snd_soc_device *socdev = platform_get_drvdata(pdev);
707 struct snd_soc_codec *codec = socdev->card->codec;
708
709 return wm8940_set_bias_level(codec, SND_SOC_BIAS_OFF);
710}
711
712static int wm8940_resume(struct platform_device *pdev)
713{
714 struct snd_soc_device *socdev = platform_get_drvdata(pdev);
715 struct snd_soc_codec *codec = socdev->card->codec;
716 int i;
717 int ret;
718 u8 data[3];
719 u16 *cache = codec->reg_cache;
720
721 /* Sync reg_cache with the hardware
722 * Could use auto incremented writes to speed this up
723 */
724 for (i = 0; i < ARRAY_SIZE(wm8940_reg_defaults); i++) {
725 data[0] = i;
726 data[1] = (cache[i] & 0xFF00) >> 8;
727 data[2] = cache[i] & 0x00FF;
728 ret = codec->hw_write(codec->control_data, data, 3);
729 if (ret < 0)
730 goto error_ret;
731 else if (ret != 3) {
732 ret = -EIO;
733 goto error_ret;
734 }
735 }
736 ret = wm8940_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
737 if (ret)
738 goto error_ret;
739 ret = wm8940_set_bias_level(codec, codec->suspend_bias_level);
740
741error_ret:
742 return ret;
743}
744
745static struct snd_soc_codec *wm8940_codec;
746
747static int wm8940_probe(struct platform_device *pdev)
748{
749 struct snd_soc_device *socdev = platform_get_drvdata(pdev);
750 struct snd_soc_codec *codec;
751
752 int ret = 0;
753
754 if (wm8940_codec == NULL) {
755 dev_err(&pdev->dev, "Codec device not registered\n");
756 return -ENODEV;
757 }
758
759 socdev->card->codec = wm8940_codec;
760 codec = wm8940_codec;
761
762 mutex_init(&codec->mutex);
763 /* register pcms */
764 ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1);
765 if (ret < 0) {
766 dev_err(codec->dev, "failed to create pcms: %d\n", ret);
767 goto pcm_err;
768 }
769
770 ret = snd_soc_add_controls(codec, wm8940_snd_controls,
771 ARRAY_SIZE(wm8940_snd_controls));
772 if (ret)
773 goto error_free_pcms;
774 ret = wm8940_add_widgets(codec);
775 if (ret)
776 goto error_free_pcms;
777
778 ret = snd_soc_init_card(socdev);
779 if (ret < 0) {
780 dev_err(codec->dev, "failed to register card: %d\n", ret);
781 goto error_free_pcms;
782 }
783
784 return ret;
785
786error_free_pcms:
787 snd_soc_free_pcms(socdev);
788 snd_soc_dapm_free(socdev);
789pcm_err:
790 return ret;
791}
792
793static int wm8940_remove(struct platform_device *pdev)
794{
795 struct snd_soc_device *socdev = platform_get_drvdata(pdev);
796
797 snd_soc_free_pcms(socdev);
798 snd_soc_dapm_free(socdev);
799
800 return 0;
801}
802
803struct snd_soc_codec_device soc_codec_dev_wm8940 = {
804 .probe = wm8940_probe,
805 .remove = wm8940_remove,
806 .suspend = wm8940_suspend,
807 .resume = wm8940_resume,
808};
809EXPORT_SYMBOL_GPL(soc_codec_dev_wm8940);
810
811static int wm8940_register(struct wm8940_priv *wm8940)
812{
813 struct wm8940_setup_data *pdata = wm8940->codec.dev->platform_data;
814 struct snd_soc_codec *codec = &wm8940->codec;
815 int ret;
816 u16 reg;
817 if (wm8940_codec) {
818 dev_err(codec->dev, "Another WM8940 is registered\n");
819 return -EINVAL;
820 }
821
822 INIT_LIST_HEAD(&codec->dapm_widgets);
823 INIT_LIST_HEAD(&codec->dapm_paths);
824
825 codec->private_data = wm8940;
826 codec->name = "WM8940";
827 codec->owner = THIS_MODULE;
828 codec->read = wm8940_read_reg_cache;
829 codec->write = wm8940_write;
830 codec->bias_level = SND_SOC_BIAS_OFF;
831 codec->set_bias_level = wm8940_set_bias_level;
832 codec->dai = &wm8940_dai;
833 codec->num_dai = 1;
834 codec->reg_cache_size = ARRAY_SIZE(wm8940_reg_defaults);
835 codec->reg_cache = &wm8940->reg_cache;
836
837 memcpy(codec->reg_cache, wm8940_reg_defaults,
838 sizeof(wm8940_reg_defaults));
839
840 ret = wm8940_reset(codec);
841 if (ret < 0) {
842 dev_err(codec->dev, "Failed to issue reset\n");
843 return ret;
844 }
845
846 wm8940_dai.dev = codec->dev;
847
848 wm8940_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
849
850 ret = wm8940_write(codec, WM8940_POWER1, 0x180);
851 if (ret < 0)
852 return ret;
853
854 if (!pdata)
855 dev_warn(codec->dev, "No platform data supplied\n");
856 else {
857 reg = wm8940_read_reg_cache(codec, WM8940_OUTPUTCTL);
858 ret = wm8940_write(codec, WM8940_OUTPUTCTL, reg | pdata->vroi);
859 if (ret < 0)
860 return ret;
861 }
862
863
864 wm8940_codec = codec;
865
866 ret = snd_soc_register_codec(codec);
867 if (ret) {
868 dev_err(codec->dev, "Failed to register codec: %d\n", ret);
869 return ret;
870 }
871
872 ret = snd_soc_register_dai(&wm8940_dai);
873 if (ret) {
874 dev_err(codec->dev, "Failed to register DAI: %d\n", ret);
875 snd_soc_unregister_codec(codec);
876 return ret;
877 }
878
879 return 0;
880}
881
882static void wm8940_unregister(struct wm8940_priv *wm8940)
883{
884 wm8940_set_bias_level(&wm8940->codec, SND_SOC_BIAS_OFF);
885 snd_soc_unregister_dai(&wm8940_dai);
886 snd_soc_unregister_codec(&wm8940->codec);
887 kfree(wm8940);
888 wm8940_codec = NULL;
889}
890
891static int wm8940_i2c_probe(struct i2c_client *i2c,
892 const struct i2c_device_id *id)
893{
894 struct wm8940_priv *wm8940;
895 struct snd_soc_codec *codec;
896
897 wm8940 = kzalloc(sizeof *wm8940, GFP_KERNEL);
898 if (wm8940 == NULL)
899 return -ENOMEM;
900
901 codec = &wm8940->codec;
902 codec->hw_write = (hw_write_t)i2c_master_send;
903 i2c_set_clientdata(i2c, wm8940);
904 codec->control_data = i2c;
905 codec->dev = &i2c->dev;
906
907 return wm8940_register(wm8940);
908}
909
910static int __devexit wm8940_i2c_remove(struct i2c_client *client)
911{
912 struct wm8940_priv *wm8940 = i2c_get_clientdata(client);
913
914 wm8940_unregister(wm8940);
915
916 return 0;
917}
918
919static const struct i2c_device_id wm8940_i2c_id[] = {
920 { "wm8940", 0 },
921 { }
922};
923MODULE_DEVICE_TABLE(i2c, wm8940_i2c_id);
924
925static struct i2c_driver wm8940_i2c_driver = {
926 .driver = {
927 .name = "WM8940 I2C Codec",
928 .owner = THIS_MODULE,
929 },
930 .probe = wm8940_i2c_probe,
931 .remove = __devexit_p(wm8940_i2c_remove),
932 .id_table = wm8940_i2c_id,
933};
934
935static int __init wm8940_modinit(void)
936{
937 int ret;
938
939 ret = i2c_add_driver(&wm8940_i2c_driver);
940 if (ret)
941 printk(KERN_ERR "Failed to register WM8940 I2C driver: %d\n",
942 ret);
943 return ret;
944}
945module_init(wm8940_modinit);
946
947static void __exit wm8940_exit(void)
948{
949 i2c_del_driver(&wm8940_i2c_driver);
950}
951module_exit(wm8940_exit);
952
953MODULE_DESCRIPTION("ASoC WM8940 driver");
954MODULE_AUTHOR("Jonathan Cameron");
955MODULE_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..e224d8add170
--- /dev/null
+++ b/sound/soc/codecs/wm8960.c
@@ -0,0 +1,969 @@
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/*
73 * read wm8960 register cache
74 */
75static inline unsigned int wm8960_read_reg_cache(struct snd_soc_codec *codec,
76 unsigned int reg)
77{
78 u16 *cache = codec->reg_cache;
79 if (reg == WM8960_RESET)
80 return 0;
81 if (reg >= WM8960_CACHEREGNUM)
82 return -1;
83 return cache[reg];
84}
85
86/*
87 * write wm8960 register cache
88 */
89static inline void wm8960_write_reg_cache(struct snd_soc_codec *codec,
90 u16 reg, unsigned int value)
91{
92 u16 *cache = codec->reg_cache;
93 if (reg >= WM8960_CACHEREGNUM)
94 return;
95 cache[reg] = value;
96}
97
98static inline unsigned int wm8960_read(struct snd_soc_codec *codec,
99 unsigned int reg)
100{
101 return wm8960_read_reg_cache(codec, reg);
102}
103
104/*
105 * write to the WM8960 register space
106 */
107static int wm8960_write(struct snd_soc_codec *codec, unsigned int reg,
108 unsigned int value)
109{
110 u8 data[2];
111
112 /* data is
113 * D15..D9 WM8960 register offset
114 * D8...D0 register data
115 */
116 data[0] = (reg << 1) | ((value >> 8) & 0x0001);
117 data[1] = value & 0x00ff;
118
119 wm8960_write_reg_cache(codec, reg, value);
120 if (codec->hw_write(codec->control_data, data, 2) == 2)
121 return 0;
122 else
123 return -EIO;
124}
125
126#define wm8960_reset(c) wm8960_write(c, WM8960_RESET, 0)
127
128/* enumerated controls */
129static const char *wm8960_deemph[] = {"None", "32Khz", "44.1Khz", "48Khz"};
130static const char *wm8960_polarity[] = {"No Inversion", "Left Inverted",
131 "Right Inverted", "Stereo Inversion"};
132static const char *wm8960_3d_upper_cutoff[] = {"High", "Low"};
133static const char *wm8960_3d_lower_cutoff[] = {"Low", "High"};
134static const char *wm8960_alcfunc[] = {"Off", "Right", "Left", "Stereo"};
135static const char *wm8960_alcmode[] = {"ALC", "Limiter"};
136
137static const struct soc_enum wm8960_enum[] = {
138 SOC_ENUM_SINGLE(WM8960_DACCTL1, 1, 4, wm8960_deemph),
139 SOC_ENUM_SINGLE(WM8960_DACCTL1, 5, 4, wm8960_polarity),
140 SOC_ENUM_SINGLE(WM8960_DACCTL2, 5, 4, wm8960_polarity),
141 SOC_ENUM_SINGLE(WM8960_3D, 6, 2, wm8960_3d_upper_cutoff),
142 SOC_ENUM_SINGLE(WM8960_3D, 5, 2, wm8960_3d_lower_cutoff),
143 SOC_ENUM_SINGLE(WM8960_ALC1, 7, 4, wm8960_alcfunc),
144 SOC_ENUM_SINGLE(WM8960_ALC3, 8, 2, wm8960_alcmode),
145};
146
147static const DECLARE_TLV_DB_SCALE(adc_tlv, -9700, 50, 0);
148static const DECLARE_TLV_DB_SCALE(dac_tlv, -12700, 50, 1);
149static const DECLARE_TLV_DB_SCALE(bypass_tlv, -2100, 300, 0);
150static const DECLARE_TLV_DB_SCALE(out_tlv, -12100, 100, 1);
151
152static const struct snd_kcontrol_new wm8960_snd_controls[] = {
153SOC_DOUBLE_R_TLV("Capture Volume", WM8960_LINVOL, WM8960_RINVOL,
154 0, 63, 0, adc_tlv),
155SOC_DOUBLE_R("Capture Volume ZC Switch", WM8960_LINVOL, WM8960_RINVOL,
156 6, 1, 0),
157SOC_DOUBLE_R("Capture Switch", WM8960_LINVOL, WM8960_RINVOL,
158 7, 1, 0),
159
160SOC_DOUBLE_R_TLV("Playback Volume", WM8960_LDAC, WM8960_RDAC,
161 0, 255, 0, dac_tlv),
162
163SOC_DOUBLE_R_TLV("Headphone Playback Volume", WM8960_LOUT1, WM8960_ROUT1,
164 0, 127, 0, out_tlv),
165SOC_DOUBLE_R("Headphone Playback ZC Switch", WM8960_LOUT1, WM8960_ROUT1,
166 7, 1, 0),
167
168SOC_DOUBLE_R_TLV("Speaker Playback Volume", WM8960_LOUT2, WM8960_ROUT2,
169 0, 127, 0, out_tlv),
170SOC_DOUBLE_R("Speaker Playback ZC Switch", WM8960_LOUT2, WM8960_ROUT2,
171 7, 1, 0),
172SOC_SINGLE("Speaker DC Volume", WM8960_CLASSD3, 3, 5, 0),
173SOC_SINGLE("Speaker AC Volume", WM8960_CLASSD3, 0, 5, 0),
174
175SOC_SINGLE("PCM Playback -6dB Switch", WM8960_DACCTL1, 7, 1, 0),
176SOC_ENUM("ADC Polarity", wm8960_enum[1]),
177SOC_ENUM("Playback De-emphasis", wm8960_enum[0]),
178SOC_SINGLE("ADC High Pass Filter Switch", WM8960_DACCTL1, 0, 1, 0),
179
180SOC_ENUM("DAC Polarity", wm8960_enum[2]),
181
182SOC_ENUM("3D Filter Upper Cut-Off", wm8960_enum[3]),
183SOC_ENUM("3D Filter Lower Cut-Off", wm8960_enum[4]),
184SOC_SINGLE("3D Volume", WM8960_3D, 1, 15, 0),
185SOC_SINGLE("3D Switch", WM8960_3D, 0, 1, 0),
186
187SOC_ENUM("ALC Function", wm8960_enum[5]),
188SOC_SINGLE("ALC Max Gain", WM8960_ALC1, 4, 7, 0),
189SOC_SINGLE("ALC Target", WM8960_ALC1, 0, 15, 1),
190SOC_SINGLE("ALC Min Gain", WM8960_ALC2, 4, 7, 0),
191SOC_SINGLE("ALC Hold Time", WM8960_ALC2, 0, 15, 0),
192SOC_ENUM("ALC Mode", wm8960_enum[6]),
193SOC_SINGLE("ALC Decay", WM8960_ALC3, 4, 15, 0),
194SOC_SINGLE("ALC Attack", WM8960_ALC3, 0, 15, 0),
195
196SOC_SINGLE("Noise Gate Threshold", WM8960_NOISEG, 3, 31, 0),
197SOC_SINGLE("Noise Gate Switch", WM8960_NOISEG, 0, 1, 0),
198
199SOC_DOUBLE_R("ADC PCM Capture Volume", WM8960_LINPATH, WM8960_RINPATH,
200 0, 127, 0),
201
202SOC_SINGLE_TLV("Left Output Mixer Boost Bypass Volume",
203 WM8960_BYPASS1, 4, 7, 1, bypass_tlv),
204SOC_SINGLE_TLV("Left Output Mixer LINPUT3 Volume",
205 WM8960_LOUTMIX, 4, 7, 1, bypass_tlv),
206SOC_SINGLE_TLV("Right Output Mixer Boost Bypass Volume",
207 WM8960_BYPASS2, 4, 7, 1, bypass_tlv),
208SOC_SINGLE_TLV("Right Output Mixer RINPUT3 Volume",
209 WM8960_ROUTMIX, 4, 7, 1, bypass_tlv),
210};
211
212static const struct snd_kcontrol_new wm8960_lin_boost[] = {
213SOC_DAPM_SINGLE("LINPUT2 Switch", WM8960_LINPATH, 6, 1, 0),
214SOC_DAPM_SINGLE("LINPUT3 Switch", WM8960_LINPATH, 7, 1, 0),
215SOC_DAPM_SINGLE("LINPUT1 Switch", WM8960_LINPATH, 8, 1, 0),
216};
217
218static const struct snd_kcontrol_new wm8960_lin[] = {
219SOC_DAPM_SINGLE("Boost Switch", WM8960_LINPATH, 3, 1, 0),
220};
221
222static const struct snd_kcontrol_new wm8960_rin_boost[] = {
223SOC_DAPM_SINGLE("RINPUT2 Switch", WM8960_RINPATH, 6, 1, 0),
224SOC_DAPM_SINGLE("RINPUT3 Switch", WM8960_RINPATH, 7, 1, 0),
225SOC_DAPM_SINGLE("RINPUT1 Switch", WM8960_RINPATH, 8, 1, 0),
226};
227
228static const struct snd_kcontrol_new wm8960_rin[] = {
229SOC_DAPM_SINGLE("Boost Switch", WM8960_RINPATH, 3, 1, 0),
230};
231
232static const struct snd_kcontrol_new wm8960_loutput_mixer[] = {
233SOC_DAPM_SINGLE("PCM Playback Switch", WM8960_LOUTMIX, 8, 1, 0),
234SOC_DAPM_SINGLE("LINPUT3 Switch", WM8960_LOUTMIX, 7, 1, 0),
235SOC_DAPM_SINGLE("Boost Bypass Switch", WM8960_BYPASS1, 7, 1, 0),
236};
237
238static const struct snd_kcontrol_new wm8960_routput_mixer[] = {
239SOC_DAPM_SINGLE("PCM Playback Switch", WM8960_ROUTMIX, 8, 1, 0),
240SOC_DAPM_SINGLE("RINPUT3 Switch", WM8960_ROUTMIX, 7, 1, 0),
241SOC_DAPM_SINGLE("Boost Bypass Switch", WM8960_BYPASS2, 7, 1, 0),
242};
243
244static const struct snd_kcontrol_new wm8960_mono_out[] = {
245SOC_DAPM_SINGLE("Left Switch", WM8960_MONOMIX1, 7, 1, 0),
246SOC_DAPM_SINGLE("Right Switch", WM8960_MONOMIX2, 7, 1, 0),
247};
248
249static const struct snd_soc_dapm_widget wm8960_dapm_widgets[] = {
250SND_SOC_DAPM_INPUT("LINPUT1"),
251SND_SOC_DAPM_INPUT("RINPUT1"),
252SND_SOC_DAPM_INPUT("LINPUT2"),
253SND_SOC_DAPM_INPUT("RINPUT2"),
254SND_SOC_DAPM_INPUT("LINPUT3"),
255SND_SOC_DAPM_INPUT("RINPUT3"),
256
257SND_SOC_DAPM_MICBIAS("MICB", WM8960_POWER1, 1, 0),
258
259SND_SOC_DAPM_MIXER("Left Boost Mixer", WM8960_POWER1, 5, 0,
260 wm8960_lin_boost, ARRAY_SIZE(wm8960_lin_boost)),
261SND_SOC_DAPM_MIXER("Right Boost Mixer", WM8960_POWER1, 4, 0,
262 wm8960_rin_boost, ARRAY_SIZE(wm8960_rin_boost)),
263
264SND_SOC_DAPM_MIXER("Left Input Mixer", WM8960_POWER3, 5, 0,
265 wm8960_lin, ARRAY_SIZE(wm8960_lin)),
266SND_SOC_DAPM_MIXER("Right Input Mixer", WM8960_POWER3, 4, 0,
267 wm8960_rin, ARRAY_SIZE(wm8960_rin)),
268
269SND_SOC_DAPM_ADC("Left ADC", "Capture", WM8960_POWER2, 3, 0),
270SND_SOC_DAPM_ADC("Right ADC", "Capture", WM8960_POWER2, 2, 0),
271
272SND_SOC_DAPM_DAC("Left DAC", "Playback", WM8960_POWER2, 8, 0),
273SND_SOC_DAPM_DAC("Right DAC", "Playback", WM8960_POWER2, 7, 0),
274
275SND_SOC_DAPM_MIXER("Left Output Mixer", WM8960_POWER3, 3, 0,
276 &wm8960_loutput_mixer[0],
277 ARRAY_SIZE(wm8960_loutput_mixer)),
278SND_SOC_DAPM_MIXER("Right Output Mixer", WM8960_POWER3, 2, 0,
279 &wm8960_routput_mixer[0],
280 ARRAY_SIZE(wm8960_routput_mixer)),
281
282SND_SOC_DAPM_MIXER("Mono Output Mixer", WM8960_POWER2, 1, 0,
283 &wm8960_mono_out[0],
284 ARRAY_SIZE(wm8960_mono_out)),
285
286SND_SOC_DAPM_PGA("LOUT1 PGA", WM8960_POWER2, 6, 0, NULL, 0),
287SND_SOC_DAPM_PGA("ROUT1 PGA", WM8960_POWER2, 5, 0, NULL, 0),
288
289SND_SOC_DAPM_PGA("Left Speaker PGA", WM8960_POWER2, 4, 0, NULL, 0),
290SND_SOC_DAPM_PGA("Right Speaker PGA", WM8960_POWER2, 3, 0, NULL, 0),
291
292SND_SOC_DAPM_PGA("Right Speaker Output", WM8960_CLASSD1, 7, 0, NULL, 0),
293SND_SOC_DAPM_PGA("Left Speaker Output", WM8960_CLASSD1, 6, 0, NULL, 0),
294
295SND_SOC_DAPM_OUTPUT("SPK_LP"),
296SND_SOC_DAPM_OUTPUT("SPK_LN"),
297SND_SOC_DAPM_OUTPUT("HP_L"),
298SND_SOC_DAPM_OUTPUT("HP_R"),
299SND_SOC_DAPM_OUTPUT("SPK_RP"),
300SND_SOC_DAPM_OUTPUT("SPK_RN"),
301SND_SOC_DAPM_OUTPUT("OUT3"),
302};
303
304static const struct snd_soc_dapm_route audio_paths[] = {
305 { "Left Boost Mixer", "LINPUT1 Switch", "LINPUT1" },
306 { "Left Boost Mixer", "LINPUT2 Switch", "LINPUT2" },
307 { "Left Boost Mixer", "LINPUT3 Switch", "LINPUT3" },
308
309 { "Left Input Mixer", "Boost Switch", "Left Boost Mixer", },
310 { "Left Input Mixer", NULL, "LINPUT1", }, /* Really Boost Switch */
311 { "Left Input Mixer", NULL, "LINPUT2" },
312 { "Left Input Mixer", NULL, "LINPUT3" },
313
314 { "Right Boost Mixer", "RINPUT1 Switch", "RINPUT1" },
315 { "Right Boost Mixer", "RINPUT2 Switch", "RINPUT2" },
316 { "Right Boost Mixer", "RINPUT3 Switch", "RINPUT3" },
317
318 { "Right Input Mixer", "Boost Switch", "Right Boost Mixer", },
319 { "Right Input Mixer", NULL, "RINPUT1", }, /* Really Boost Switch */
320 { "Right Input Mixer", NULL, "RINPUT2" },
321 { "Right Input Mixer", NULL, "LINPUT3" },
322
323 { "Left ADC", NULL, "Left Input Mixer" },
324 { "Right ADC", NULL, "Right Input Mixer" },
325
326 { "Left Output Mixer", "LINPUT3 Switch", "LINPUT3" },
327 { "Left Output Mixer", "Boost Bypass Switch", "Left Boost Mixer"} ,
328 { "Left Output Mixer", "PCM Playback Switch", "Left DAC" },
329
330 { "Right Output Mixer", "RINPUT3 Switch", "RINPUT3" },
331 { "Right Output Mixer", "Boost Bypass Switch", "Right Boost Mixer" } ,
332 { "Right Output Mixer", "PCM Playback Switch", "Right DAC" },
333
334 { "Mono Output Mixer", "Left Switch", "Left Output Mixer" },
335 { "Mono Output Mixer", "Right Switch", "Right Output Mixer" },
336
337 { "LOUT1 PGA", NULL, "Left Output Mixer" },
338 { "ROUT1 PGA", NULL, "Right Output Mixer" },
339
340 { "HP_L", NULL, "LOUT1 PGA" },
341 { "HP_R", NULL, "ROUT1 PGA" },
342
343 { "Left Speaker PGA", NULL, "Left Output Mixer" },
344 { "Right Speaker PGA", NULL, "Right Output Mixer" },
345
346 { "Left Speaker Output", NULL, "Left Speaker PGA" },
347 { "Right Speaker Output", NULL, "Right Speaker PGA" },
348
349 { "SPK_LN", NULL, "Left Speaker Output" },
350 { "SPK_LP", NULL, "Left Speaker Output" },
351 { "SPK_RN", NULL, "Right Speaker Output" },
352 { "SPK_RP", NULL, "Right Speaker Output" },
353
354 { "OUT3", NULL, "Mono Output Mixer", }
355};
356
357static int wm8960_add_widgets(struct snd_soc_codec *codec)
358{
359 snd_soc_dapm_new_controls(codec, wm8960_dapm_widgets,
360 ARRAY_SIZE(wm8960_dapm_widgets));
361
362 snd_soc_dapm_add_routes(codec, audio_paths, ARRAY_SIZE(audio_paths));
363
364 snd_soc_dapm_new_widgets(codec);
365 return 0;
366}
367
368static int wm8960_set_dai_fmt(struct snd_soc_dai *codec_dai,
369 unsigned int fmt)
370{
371 struct snd_soc_codec *codec = codec_dai->codec;
372 u16 iface = 0;
373
374 /* set master/slave audio interface */
375 switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
376 case SND_SOC_DAIFMT_CBM_CFM:
377 iface |= 0x0040;
378 break;
379 case SND_SOC_DAIFMT_CBS_CFS:
380 break;
381 default:
382 return -EINVAL;
383 }
384
385 /* interface format */
386 switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
387 case SND_SOC_DAIFMT_I2S:
388 iface |= 0x0002;
389 break;
390 case SND_SOC_DAIFMT_RIGHT_J:
391 break;
392 case SND_SOC_DAIFMT_LEFT_J:
393 iface |= 0x0001;
394 break;
395 case SND_SOC_DAIFMT_DSP_A:
396 iface |= 0x0003;
397 break;
398 case SND_SOC_DAIFMT_DSP_B:
399 iface |= 0x0013;
400 break;
401 default:
402 return -EINVAL;
403 }
404
405 /* clock inversion */
406 switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
407 case SND_SOC_DAIFMT_NB_NF:
408 break;
409 case SND_SOC_DAIFMT_IB_IF:
410 iface |= 0x0090;
411 break;
412 case SND_SOC_DAIFMT_IB_NF:
413 iface |= 0x0080;
414 break;
415 case SND_SOC_DAIFMT_NB_IF:
416 iface |= 0x0010;
417 break;
418 default:
419 return -EINVAL;
420 }
421
422 /* set iface */
423 wm8960_write(codec, WM8960_IFACE1, iface);
424 return 0;
425}
426
427static int wm8960_hw_params(struct snd_pcm_substream *substream,
428 struct snd_pcm_hw_params *params,
429 struct snd_soc_dai *dai)
430{
431 struct snd_soc_pcm_runtime *rtd = substream->private_data;
432 struct snd_soc_device *socdev = rtd->socdev;
433 struct snd_soc_codec *codec = socdev->card->codec;
434 u16 iface = wm8960_read(codec, WM8960_IFACE1) & 0xfff3;
435
436 /* bit size */
437 switch (params_format(params)) {
438 case SNDRV_PCM_FORMAT_S16_LE:
439 break;
440 case SNDRV_PCM_FORMAT_S20_3LE:
441 iface |= 0x0004;
442 break;
443 case SNDRV_PCM_FORMAT_S24_LE:
444 iface |= 0x0008;
445 break;
446 }
447
448 /* set iface */
449 wm8960_write(codec, WM8960_IFACE1, iface);
450 return 0;
451}
452
453static int wm8960_mute(struct snd_soc_dai *dai, int mute)
454{
455 struct snd_soc_codec *codec = dai->codec;
456 u16 mute_reg = wm8960_read(codec, WM8960_DACCTL1) & 0xfff7;
457
458 if (mute)
459 wm8960_write(codec, WM8960_DACCTL1, mute_reg | 0x8);
460 else
461 wm8960_write(codec, WM8960_DACCTL1, mute_reg);
462 return 0;
463}
464
465static int wm8960_set_bias_level(struct snd_soc_codec *codec,
466 enum snd_soc_bias_level level)
467{
468 struct wm8960_data *pdata = codec->dev->platform_data;
469 u16 reg;
470
471 switch (level) {
472 case SND_SOC_BIAS_ON:
473 break;
474
475 case SND_SOC_BIAS_PREPARE:
476 /* Set VMID to 2x50k */
477 reg = wm8960_read(codec, WM8960_POWER1);
478 reg &= ~0x180;
479 reg |= 0x80;
480 wm8960_write(codec, WM8960_POWER1, reg);
481 break;
482
483 case SND_SOC_BIAS_STANDBY:
484 if (codec->bias_level == SND_SOC_BIAS_OFF) {
485 /* Enable anti-pop features */
486 wm8960_write(codec, WM8960_APOP1,
487 WM8960_POBCTRL | WM8960_SOFT_ST |
488 WM8960_BUFDCOPEN | WM8960_BUFIOEN);
489
490 /* Discharge HP output */
491 reg = WM8960_DISOP;
492 if (pdata)
493 reg |= pdata->dres << 4;
494 wm8960_write(codec, WM8960_APOP2, reg);
495
496 msleep(400);
497
498 wm8960_write(codec, WM8960_APOP2, 0);
499
500 /* Enable & ramp VMID at 2x50k */
501 reg = wm8960_read(codec, WM8960_POWER1);
502 reg |= 0x80;
503 wm8960_write(codec, WM8960_POWER1, reg);
504 msleep(100);
505
506 /* Enable VREF */
507 wm8960_write(codec, WM8960_POWER1, reg | WM8960_VREF);
508
509 /* Disable anti-pop features */
510 wm8960_write(codec, WM8960_APOP1, WM8960_BUFIOEN);
511 }
512
513 /* Set VMID to 2x250k */
514 reg = wm8960_read(codec, WM8960_POWER1);
515 reg &= ~0x180;
516 reg |= 0x100;
517 wm8960_write(codec, WM8960_POWER1, reg);
518 break;
519
520 case SND_SOC_BIAS_OFF:
521 /* Enable anti-pop features */
522 wm8960_write(codec, WM8960_APOP1,
523 WM8960_POBCTRL | WM8960_SOFT_ST |
524 WM8960_BUFDCOPEN | WM8960_BUFIOEN);
525
526 /* Disable VMID and VREF, let them discharge */
527 wm8960_write(codec, WM8960_POWER1, 0);
528 msleep(600);
529
530 wm8960_write(codec, WM8960_APOP1, 0);
531 break;
532 }
533
534 codec->bias_level = level;
535
536 return 0;
537}
538
539/* PLL divisors */
540struct _pll_div {
541 u32 pre_div:1;
542 u32 n:4;
543 u32 k:24;
544};
545
546/* The size in bits of the pll divide multiplied by 10
547 * to allow rounding later */
548#define FIXED_PLL_SIZE ((1 << 24) * 10)
549
550static int pll_factors(unsigned int source, unsigned int target,
551 struct _pll_div *pll_div)
552{
553 unsigned long long Kpart;
554 unsigned int K, Ndiv, Nmod;
555
556 pr_debug("WM8960 PLL: setting %dHz->%dHz\n", source, target);
557
558 /* Scale up target to PLL operating frequency */
559 target *= 4;
560
561 Ndiv = target / source;
562 if (Ndiv < 6) {
563 source >>= 1;
564 pll_div->pre_div = 1;
565 Ndiv = target / source;
566 } else
567 pll_div->pre_div = 0;
568
569 if ((Ndiv < 6) || (Ndiv > 12)) {
570 pr_err("WM8960 PLL: Unsupported N=%d\n", Ndiv);
571 return -EINVAL;
572 }
573
574 pll_div->n = Ndiv;
575 Nmod = target % source;
576 Kpart = FIXED_PLL_SIZE * (long long)Nmod;
577
578 do_div(Kpart, source);
579
580 K = Kpart & 0xFFFFFFFF;
581
582 /* Check if we need to round */
583 if ((K % 10) >= 5)
584 K += 5;
585
586 /* Move down to proper range now rounding is done */
587 K /= 10;
588
589 pll_div->k = K;
590
591 pr_debug("WM8960 PLL: N=%x K=%x pre_div=%d\n",
592 pll_div->n, pll_div->k, pll_div->pre_div);
593
594 return 0;
595}
596
597static int wm8960_set_dai_pll(struct snd_soc_dai *codec_dai,
598 int pll_id, unsigned int freq_in, unsigned int freq_out)
599{
600 struct snd_soc_codec *codec = codec_dai->codec;
601 u16 reg;
602 static struct _pll_div pll_div;
603 int ret;
604
605 if (freq_in && freq_out) {
606 ret = pll_factors(freq_in, freq_out, &pll_div);
607 if (ret != 0)
608 return ret;
609 }
610
611 /* Disable the PLL: even if we are changing the frequency the
612 * PLL needs to be disabled while we do so. */
613 wm8960_write(codec, WM8960_CLOCK1,
614 wm8960_read(codec, WM8960_CLOCK1) & ~1);
615 wm8960_write(codec, WM8960_POWER2,
616 wm8960_read(codec, WM8960_POWER2) & ~1);
617
618 if (!freq_in || !freq_out)
619 return 0;
620
621 reg = wm8960_read(codec, WM8960_PLL1) & ~0x3f;
622 reg |= pll_div.pre_div << 4;
623 reg |= pll_div.n;
624
625 if (pll_div.k) {
626 reg |= 0x20;
627
628 wm8960_write(codec, WM8960_PLL2, (pll_div.k >> 18) & 0x3f);
629 wm8960_write(codec, WM8960_PLL3, (pll_div.k >> 9) & 0x1ff);
630 wm8960_write(codec, WM8960_PLL4, pll_div.k & 0x1ff);
631 }
632 wm8960_write(codec, WM8960_PLL1, reg);
633
634 /* Turn it on */
635 wm8960_write(codec, WM8960_POWER2,
636 wm8960_read(codec, WM8960_POWER2) | 1);
637 msleep(250);
638 wm8960_write(codec, WM8960_CLOCK1,
639 wm8960_read(codec, WM8960_CLOCK1) | 1);
640
641 return 0;
642}
643
644static int wm8960_set_dai_clkdiv(struct snd_soc_dai *codec_dai,
645 int div_id, int div)
646{
647 struct snd_soc_codec *codec = codec_dai->codec;
648 u16 reg;
649
650 switch (div_id) {
651 case WM8960_SYSCLKSEL:
652 reg = wm8960_read(codec, WM8960_CLOCK1) & 0x1fe;
653 wm8960_write(codec, WM8960_CLOCK1, reg | div);
654 break;
655 case WM8960_SYSCLKDIV:
656 reg = wm8960_read(codec, WM8960_CLOCK1) & 0x1f9;
657 wm8960_write(codec, WM8960_CLOCK1, reg | div);
658 break;
659 case WM8960_DACDIV:
660 reg = wm8960_read(codec, WM8960_CLOCK1) & 0x1c7;
661 wm8960_write(codec, WM8960_CLOCK1, reg | div);
662 break;
663 case WM8960_OPCLKDIV:
664 reg = wm8960_read(codec, WM8960_PLL1) & 0x03f;
665 wm8960_write(codec, WM8960_PLL1, reg | div);
666 break;
667 case WM8960_DCLKDIV:
668 reg = wm8960_read(codec, WM8960_CLOCK2) & 0x03f;
669 wm8960_write(codec, WM8960_CLOCK2, reg | div);
670 break;
671 case WM8960_TOCLKSEL:
672 reg = wm8960_read(codec, WM8960_ADDCTL1) & 0x1fd;
673 wm8960_write(codec, WM8960_ADDCTL1, reg | div);
674 break;
675 default:
676 return -EINVAL;
677 }
678
679 return 0;
680}
681
682#define WM8960_RATES SNDRV_PCM_RATE_8000_48000
683
684#define WM8960_FORMATS \
685 (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE | \
686 SNDRV_PCM_FMTBIT_S24_LE)
687
688static struct snd_soc_dai_ops wm8960_dai_ops = {
689 .hw_params = wm8960_hw_params,
690 .digital_mute = wm8960_mute,
691 .set_fmt = wm8960_set_dai_fmt,
692 .set_clkdiv = wm8960_set_dai_clkdiv,
693 .set_pll = wm8960_set_dai_pll,
694};
695
696struct snd_soc_dai wm8960_dai = {
697 .name = "WM8960",
698 .playback = {
699 .stream_name = "Playback",
700 .channels_min = 1,
701 .channels_max = 2,
702 .rates = WM8960_RATES,
703 .formats = WM8960_FORMATS,},
704 .capture = {
705 .stream_name = "Capture",
706 .channels_min = 1,
707 .channels_max = 2,
708 .rates = WM8960_RATES,
709 .formats = WM8960_FORMATS,},
710 .ops = &wm8960_dai_ops,
711 .symmetric_rates = 1,
712};
713EXPORT_SYMBOL_GPL(wm8960_dai);
714
715static int wm8960_suspend(struct platform_device *pdev, pm_message_t state)
716{
717 struct snd_soc_device *socdev = platform_get_drvdata(pdev);
718 struct snd_soc_codec *codec = socdev->card->codec;
719
720 wm8960_set_bias_level(codec, SND_SOC_BIAS_OFF);
721 return 0;
722}
723
724static int wm8960_resume(struct platform_device *pdev)
725{
726 struct snd_soc_device *socdev = platform_get_drvdata(pdev);
727 struct snd_soc_codec *codec = socdev->card->codec;
728 int i;
729 u8 data[2];
730 u16 *cache = codec->reg_cache;
731
732 /* Sync reg_cache with the hardware */
733 for (i = 0; i < ARRAY_SIZE(wm8960_reg); i++) {
734 data[0] = (i << 1) | ((cache[i] >> 8) & 0x0001);
735 data[1] = cache[i] & 0x00ff;
736 codec->hw_write(codec->control_data, data, 2);
737 }
738
739 wm8960_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
740 wm8960_set_bias_level(codec, codec->suspend_bias_level);
741 return 0;
742}
743
744static struct snd_soc_codec *wm8960_codec;
745
746static int wm8960_probe(struct platform_device *pdev)
747{
748 struct snd_soc_device *socdev = platform_get_drvdata(pdev);
749 struct snd_soc_codec *codec;
750 int ret = 0;
751
752 if (wm8960_codec == NULL) {
753 dev_err(&pdev->dev, "Codec device not registered\n");
754 return -ENODEV;
755 }
756
757 socdev->card->codec = wm8960_codec;
758 codec = wm8960_codec;
759
760 /* register pcms */
761 ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1);
762 if (ret < 0) {
763 dev_err(codec->dev, "failed to create pcms: %d\n", ret);
764 goto pcm_err;
765 }
766
767 snd_soc_add_controls(codec, wm8960_snd_controls,
768 ARRAY_SIZE(wm8960_snd_controls));
769 wm8960_add_widgets(codec);
770 ret = snd_soc_init_card(socdev);
771 if (ret < 0) {
772 dev_err(codec->dev, "failed to register card: %d\n", ret);
773 goto card_err;
774 }
775
776 return ret;
777
778card_err:
779 snd_soc_free_pcms(socdev);
780 snd_soc_dapm_free(socdev);
781pcm_err:
782 return ret;
783}
784
785/* power down chip */
786static int wm8960_remove(struct platform_device *pdev)
787{
788 struct snd_soc_device *socdev = platform_get_drvdata(pdev);
789
790 snd_soc_free_pcms(socdev);
791 snd_soc_dapm_free(socdev);
792
793 return 0;
794}
795
796struct snd_soc_codec_device soc_codec_dev_wm8960 = {
797 .probe = wm8960_probe,
798 .remove = wm8960_remove,
799 .suspend = wm8960_suspend,
800 .resume = wm8960_resume,
801};
802EXPORT_SYMBOL_GPL(soc_codec_dev_wm8960);
803
804static int wm8960_register(struct wm8960_priv *wm8960)
805{
806 struct wm8960_data *pdata = wm8960->codec.dev->platform_data;
807 struct snd_soc_codec *codec = &wm8960->codec;
808 int ret;
809 u16 reg;
810
811 if (wm8960_codec) {
812 dev_err(codec->dev, "Another WM8960 is registered\n");
813 return -EINVAL;
814 }
815
816 if (!pdata) {
817 dev_warn(codec->dev, "No platform data supplied\n");
818 } else {
819 if (pdata->dres > WM8960_DRES_MAX) {
820 dev_err(codec->dev, "Invalid DRES: %d\n", pdata->dres);
821 pdata->dres = 0;
822 }
823 }
824
825 mutex_init(&codec->mutex);
826 INIT_LIST_HEAD(&codec->dapm_widgets);
827 INIT_LIST_HEAD(&codec->dapm_paths);
828
829 codec->private_data = wm8960;
830 codec->name = "WM8960";
831 codec->owner = THIS_MODULE;
832 codec->read = wm8960_read_reg_cache;
833 codec->write = wm8960_write;
834 codec->bias_level = SND_SOC_BIAS_OFF;
835 codec->set_bias_level = wm8960_set_bias_level;
836 codec->dai = &wm8960_dai;
837 codec->num_dai = 1;
838 codec->reg_cache_size = WM8960_CACHEREGNUM;
839 codec->reg_cache = &wm8960->reg_cache;
840
841 memcpy(codec->reg_cache, wm8960_reg, sizeof(wm8960_reg));
842
843 ret = wm8960_reset(codec);
844 if (ret < 0) {
845 dev_err(codec->dev, "Failed to issue reset\n");
846 return ret;
847 }
848
849 wm8960_dai.dev = codec->dev;
850
851 wm8960_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
852
853 /* Latch the update bits */
854 reg = wm8960_read(codec, WM8960_LINVOL);
855 wm8960_write(codec, WM8960_LINVOL, reg | 0x100);
856 reg = wm8960_read(codec, WM8960_RINVOL);
857 wm8960_write(codec, WM8960_RINVOL, reg | 0x100);
858 reg = wm8960_read(codec, WM8960_LADC);
859 wm8960_write(codec, WM8960_LADC, reg | 0x100);
860 reg = wm8960_read(codec, WM8960_RADC);
861 wm8960_write(codec, WM8960_RADC, reg | 0x100);
862 reg = wm8960_read(codec, WM8960_LDAC);
863 wm8960_write(codec, WM8960_LDAC, reg | 0x100);
864 reg = wm8960_read(codec, WM8960_RDAC);
865 wm8960_write(codec, WM8960_RDAC, reg | 0x100);
866 reg = wm8960_read(codec, WM8960_LOUT1);
867 wm8960_write(codec, WM8960_LOUT1, reg | 0x100);
868 reg = wm8960_read(codec, WM8960_ROUT1);
869 wm8960_write(codec, WM8960_ROUT1, reg | 0x100);
870 reg = wm8960_read(codec, WM8960_LOUT2);
871 wm8960_write(codec, WM8960_LOUT2, reg | 0x100);
872 reg = wm8960_read(codec, WM8960_ROUT2);
873 wm8960_write(codec, WM8960_ROUT2, reg | 0x100);
874
875 wm8960_codec = codec;
876
877 ret = snd_soc_register_codec(codec);
878 if (ret != 0) {
879 dev_err(codec->dev, "Failed to register codec: %d\n", ret);
880 return ret;
881 }
882
883 ret = snd_soc_register_dai(&wm8960_dai);
884 if (ret != 0) {
885 dev_err(codec->dev, "Failed to register DAI: %d\n", ret);
886 snd_soc_unregister_codec(codec);
887 return ret;
888 }
889
890 return 0;
891}
892
893static void wm8960_unregister(struct wm8960_priv *wm8960)
894{
895 wm8960_set_bias_level(&wm8960->codec, SND_SOC_BIAS_OFF);
896 snd_soc_unregister_dai(&wm8960_dai);
897 snd_soc_unregister_codec(&wm8960->codec);
898 kfree(wm8960);
899 wm8960_codec = NULL;
900}
901
902static __devinit int wm8960_i2c_probe(struct i2c_client *i2c,
903 const struct i2c_device_id *id)
904{
905 struct wm8960_priv *wm8960;
906 struct snd_soc_codec *codec;
907
908 wm8960 = kzalloc(sizeof(struct wm8960_priv), GFP_KERNEL);
909 if (wm8960 == NULL)
910 return -ENOMEM;
911
912 codec = &wm8960->codec;
913 codec->hw_write = (hw_write_t)i2c_master_send;
914
915 i2c_set_clientdata(i2c, wm8960);
916 codec->control_data = i2c;
917
918 codec->dev = &i2c->dev;
919
920 return wm8960_register(wm8960);
921}
922
923static __devexit int wm8960_i2c_remove(struct i2c_client *client)
924{
925 struct wm8960_priv *wm8960 = i2c_get_clientdata(client);
926 wm8960_unregister(wm8960);
927 return 0;
928}
929
930static const struct i2c_device_id wm8960_i2c_id[] = {
931 { "wm8960", 0 },
932 { }
933};
934MODULE_DEVICE_TABLE(i2c, wm8960_i2c_id);
935
936static struct i2c_driver wm8960_i2c_driver = {
937 .driver = {
938 .name = "WM8960 I2C Codec",
939 .owner = THIS_MODULE,
940 },
941 .probe = wm8960_i2c_probe,
942 .remove = __devexit_p(wm8960_i2c_remove),
943 .id_table = wm8960_i2c_id,
944};
945
946static int __init wm8960_modinit(void)
947{
948 int ret;
949
950 ret = i2c_add_driver(&wm8960_i2c_driver);
951 if (ret != 0) {
952 printk(KERN_ERR "Failed to register WM8960 I2C driver: %d\n",
953 ret);
954 }
955
956 return ret;
957}
958module_init(wm8960_modinit);
959
960static void __exit wm8960_exit(void)
961{
962 i2c_del_driver(&wm8960_i2c_driver);
963}
964module_exit(wm8960_exit);
965
966
967MODULE_DESCRIPTION("ASoC WM8960 driver");
968MODULE_AUTHOR("Liam Girdwood");
969MODULE_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/wm8988.c b/sound/soc/codecs/wm8988.c
new file mode 100644
index 000000000000..c05f71803aa8
--- /dev/null
+++ b/sound/soc/codecs/wm8988.c
@@ -0,0 +1,1097 @@
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/*
61 * read wm8988 register cache
62 */
63static inline unsigned int wm8988_read_reg_cache(struct snd_soc_codec *codec,
64 unsigned int reg)
65{
66 u16 *cache = codec->reg_cache;
67 if (reg > WM8988_NUM_REG)
68 return -1;
69 return cache[reg];
70}
71
72/*
73 * write wm8988 register cache
74 */
75static inline void wm8988_write_reg_cache(struct snd_soc_codec *codec,
76 unsigned int reg, unsigned int value)
77{
78 u16 *cache = codec->reg_cache;
79 if (reg > WM8988_NUM_REG)
80 return;
81 cache[reg] = value;
82}
83
84static int wm8988_write(struct snd_soc_codec *codec, unsigned int reg,
85 unsigned int value)
86{
87 u8 data[2];
88
89 /* data is
90 * D15..D9 WM8753 register offset
91 * D8...D0 register data
92 */
93 data[0] = (reg << 1) | ((value >> 8) & 0x0001);
94 data[1] = value & 0x00ff;
95
96 wm8988_write_reg_cache(codec, reg, value);
97 if (codec->hw_write(codec->control_data, data, 2) == 2)
98 return 0;
99 else
100 return -EIO;
101}
102
103#define wm8988_reset(c) wm8988_write(c, WM8988_RESET, 0)
104
105/*
106 * WM8988 Controls
107 */
108
109static const char *bass_boost_txt[] = {"Linear Control", "Adaptive Boost"};
110static const struct soc_enum bass_boost =
111 SOC_ENUM_SINGLE(WM8988_BASS, 7, 2, bass_boost_txt);
112
113static const char *bass_filter_txt[] = { "130Hz @ 48kHz", "200Hz @ 48kHz" };
114static const struct soc_enum bass_filter =
115 SOC_ENUM_SINGLE(WM8988_BASS, 6, 2, bass_filter_txt);
116
117static const char *treble_txt[] = {"8kHz", "4kHz"};
118static const struct soc_enum treble =
119 SOC_ENUM_SINGLE(WM8988_TREBLE, 6, 2, treble_txt);
120
121static const char *stereo_3d_lc_txt[] = {"200Hz", "500Hz"};
122static const struct soc_enum stereo_3d_lc =
123 SOC_ENUM_SINGLE(WM8988_3D, 5, 2, stereo_3d_lc_txt);
124
125static const char *stereo_3d_uc_txt[] = {"2.2kHz", "1.5kHz"};
126static const struct soc_enum stereo_3d_uc =
127 SOC_ENUM_SINGLE(WM8988_3D, 6, 2, stereo_3d_uc_txt);
128
129static const char *stereo_3d_func_txt[] = {"Capture", "Playback"};
130static const struct soc_enum stereo_3d_func =
131 SOC_ENUM_SINGLE(WM8988_3D, 7, 2, stereo_3d_func_txt);
132
133static const char *alc_func_txt[] = {"Off", "Right", "Left", "Stereo"};
134static const struct soc_enum alc_func =
135 SOC_ENUM_SINGLE(WM8988_ALC1, 7, 4, alc_func_txt);
136
137static const char *ng_type_txt[] = {"Constant PGA Gain",
138 "Mute ADC Output"};
139static const struct soc_enum ng_type =
140 SOC_ENUM_SINGLE(WM8988_NGATE, 1, 2, ng_type_txt);
141
142static const char *deemph_txt[] = {"None", "32Khz", "44.1Khz", "48Khz"};
143static const struct soc_enum deemph =
144 SOC_ENUM_SINGLE(WM8988_ADCDAC, 1, 4, deemph_txt);
145
146static const char *adcpol_txt[] = {"Normal", "L Invert", "R Invert",
147 "L + R Invert"};
148static const struct soc_enum adcpol =
149 SOC_ENUM_SINGLE(WM8988_ADCDAC, 5, 4, adcpol_txt);
150
151static const DECLARE_TLV_DB_SCALE(pga_tlv, -1725, 75, 0);
152static const DECLARE_TLV_DB_SCALE(adc_tlv, -9750, 50, 1);
153static const DECLARE_TLV_DB_SCALE(dac_tlv, -12750, 50, 1);
154static const DECLARE_TLV_DB_SCALE(out_tlv, -12100, 100, 1);
155static const DECLARE_TLV_DB_SCALE(bypass_tlv, -1500, 300, 0);
156
157static const struct snd_kcontrol_new wm8988_snd_controls[] = {
158
159SOC_ENUM("Bass Boost", bass_boost),
160SOC_ENUM("Bass Filter", bass_filter),
161SOC_SINGLE("Bass Volume", WM8988_BASS, 0, 15, 1),
162
163SOC_SINGLE("Treble Volume", WM8988_TREBLE, 0, 15, 0),
164SOC_ENUM("Treble Cut-off", treble),
165
166SOC_SINGLE("3D Switch", WM8988_3D, 0, 1, 0),
167SOC_SINGLE("3D Volume", WM8988_3D, 1, 15, 0),
168SOC_ENUM("3D Lower Cut-off", stereo_3d_lc),
169SOC_ENUM("3D Upper Cut-off", stereo_3d_uc),
170SOC_ENUM("3D Mode", stereo_3d_func),
171
172SOC_SINGLE("ALC Capture Target Volume", WM8988_ALC1, 0, 7, 0),
173SOC_SINGLE("ALC Capture Max Volume", WM8988_ALC1, 4, 7, 0),
174SOC_ENUM("ALC Capture Function", alc_func),
175SOC_SINGLE("ALC Capture ZC Switch", WM8988_ALC2, 7, 1, 0),
176SOC_SINGLE("ALC Capture Hold Time", WM8988_ALC2, 0, 15, 0),
177SOC_SINGLE("ALC Capture Decay Time", WM8988_ALC3, 4, 15, 0),
178SOC_SINGLE("ALC Capture Attack Time", WM8988_ALC3, 0, 15, 0),
179SOC_SINGLE("ALC Capture NG Threshold", WM8988_NGATE, 3, 31, 0),
180SOC_ENUM("ALC Capture NG Type", ng_type),
181SOC_SINGLE("ALC Capture NG Switch", WM8988_NGATE, 0, 1, 0),
182
183SOC_SINGLE("ZC Timeout Switch", WM8988_ADCTL1, 0, 1, 0),
184
185SOC_DOUBLE_R_TLV("Capture Digital Volume", WM8988_LADC, WM8988_RADC,
186 0, 255, 0, adc_tlv),
187SOC_DOUBLE_R_TLV("Capture Volume", WM8988_LINVOL, WM8988_RINVOL,
188 0, 63, 0, pga_tlv),
189SOC_DOUBLE_R("Capture ZC Switch", WM8988_LINVOL, WM8988_RINVOL, 6, 1, 0),
190SOC_DOUBLE_R("Capture Switch", WM8988_LINVOL, WM8988_RINVOL, 7, 1, 1),
191
192SOC_ENUM("Playback De-emphasis", deemph),
193
194SOC_ENUM("Capture Polarity", adcpol),
195SOC_SINGLE("Playback 6dB Attenuate", WM8988_ADCDAC, 7, 1, 0),
196SOC_SINGLE("Capture 6dB Attenuate", WM8988_ADCDAC, 8, 1, 0),
197
198SOC_DOUBLE_R_TLV("PCM Volume", WM8988_LDAC, WM8988_RDAC, 0, 255, 0, dac_tlv),
199
200SOC_SINGLE_TLV("Left Mixer Left Bypass Volume", WM8988_LOUTM1, 4, 7, 1,
201 bypass_tlv),
202SOC_SINGLE_TLV("Left Mixer Right Bypass Volume", WM8988_LOUTM2, 4, 7, 1,
203 bypass_tlv),
204SOC_SINGLE_TLV("Right Mixer Left Bypass Volume", WM8988_ROUTM1, 4, 7, 1,
205 bypass_tlv),
206SOC_SINGLE_TLV("Right Mixer Right Bypass Volume", WM8988_ROUTM2, 4, 7, 1,
207 bypass_tlv),
208
209SOC_DOUBLE_R("Output 1 Playback ZC Switch", WM8988_LOUT1V,
210 WM8988_ROUT1V, 7, 1, 0),
211SOC_DOUBLE_R_TLV("Output 1 Playback Volume", WM8988_LOUT1V, WM8988_ROUT1V,
212 0, 127, 0, out_tlv),
213
214SOC_DOUBLE_R("Output 2 Playback ZC Switch", WM8988_LOUT2V,
215 WM8988_ROUT2V, 7, 1, 0),
216SOC_DOUBLE_R_TLV("Output 2 Playback Volume", WM8988_LOUT2V, WM8988_ROUT2V,
217 0, 127, 0, out_tlv),
218
219};
220
221/*
222 * DAPM Controls
223 */
224
225static int wm8988_lrc_control(struct snd_soc_dapm_widget *w,
226 struct snd_kcontrol *kcontrol, int event)
227{
228 struct snd_soc_codec *codec = w->codec;
229 u16 adctl2 = wm8988_read_reg_cache(codec, WM8988_ADCTL2);
230
231 /* Use the DAC to gate LRC if active, otherwise use ADC */
232 if (wm8988_read_reg_cache(codec, WM8988_PWR2) & 0x180)
233 adctl2 &= ~0x4;
234 else
235 adctl2 |= 0x4;
236
237 return wm8988_write(codec, WM8988_ADCTL2, adctl2);
238}
239
240static const char *wm8988_line_texts[] = {
241 "Line 1", "Line 2", "PGA", "Differential"};
242
243static const unsigned int wm8988_line_values[] = {
244 0, 1, 3, 4};
245
246static const struct soc_enum wm8988_lline_enum =
247 SOC_VALUE_ENUM_SINGLE(WM8988_LOUTM1, 0, 7,
248 ARRAY_SIZE(wm8988_line_texts),
249 wm8988_line_texts,
250 wm8988_line_values);
251static const struct snd_kcontrol_new wm8988_left_line_controls =
252 SOC_DAPM_VALUE_ENUM("Route", wm8988_lline_enum);
253
254static const struct soc_enum wm8988_rline_enum =
255 SOC_VALUE_ENUM_SINGLE(WM8988_ROUTM1, 0, 7,
256 ARRAY_SIZE(wm8988_line_texts),
257 wm8988_line_texts,
258 wm8988_line_values);
259static const struct snd_kcontrol_new wm8988_right_line_controls =
260 SOC_DAPM_VALUE_ENUM("Route", wm8988_lline_enum);
261
262/* Left Mixer */
263static const struct snd_kcontrol_new wm8988_left_mixer_controls[] = {
264 SOC_DAPM_SINGLE("Playback Switch", WM8988_LOUTM1, 8, 1, 0),
265 SOC_DAPM_SINGLE("Left Bypass Switch", WM8988_LOUTM1, 7, 1, 0),
266 SOC_DAPM_SINGLE("Right Playback Switch", WM8988_LOUTM2, 8, 1, 0),
267 SOC_DAPM_SINGLE("Right Bypass Switch", WM8988_LOUTM2, 7, 1, 0),
268};
269
270/* Right Mixer */
271static const struct snd_kcontrol_new wm8988_right_mixer_controls[] = {
272 SOC_DAPM_SINGLE("Left Playback Switch", WM8988_ROUTM1, 8, 1, 0),
273 SOC_DAPM_SINGLE("Left Bypass Switch", WM8988_ROUTM1, 7, 1, 0),
274 SOC_DAPM_SINGLE("Playback Switch", WM8988_ROUTM2, 8, 1, 0),
275 SOC_DAPM_SINGLE("Right Bypass Switch", WM8988_ROUTM2, 7, 1, 0),
276};
277
278static const char *wm8988_pga_sel[] = {"Line 1", "Line 2", "Differential"};
279static const unsigned int wm8988_pga_val[] = { 0, 1, 3 };
280
281/* Left PGA Mux */
282static const struct soc_enum wm8988_lpga_enum =
283 SOC_VALUE_ENUM_SINGLE(WM8988_LADCIN, 6, 3,
284 ARRAY_SIZE(wm8988_pga_sel),
285 wm8988_pga_sel,
286 wm8988_pga_val);
287static const struct snd_kcontrol_new wm8988_left_pga_controls =
288 SOC_DAPM_VALUE_ENUM("Route", wm8988_lpga_enum);
289
290/* Right PGA Mux */
291static const struct soc_enum wm8988_rpga_enum =
292 SOC_VALUE_ENUM_SINGLE(WM8988_RADCIN, 6, 3,
293 ARRAY_SIZE(wm8988_pga_sel),
294 wm8988_pga_sel,
295 wm8988_pga_val);
296static const struct snd_kcontrol_new wm8988_right_pga_controls =
297 SOC_DAPM_VALUE_ENUM("Route", wm8988_rpga_enum);
298
299/* Differential Mux */
300static const char *wm8988_diff_sel[] = {"Line 1", "Line 2"};
301static const struct soc_enum diffmux =
302 SOC_ENUM_SINGLE(WM8988_ADCIN, 8, 2, wm8988_diff_sel);
303static const struct snd_kcontrol_new wm8988_diffmux_controls =
304 SOC_DAPM_ENUM("Route", diffmux);
305
306/* Mono ADC Mux */
307static const char *wm8988_mono_mux[] = {"Stereo", "Mono (Left)",
308 "Mono (Right)", "Digital Mono"};
309static const struct soc_enum monomux =
310 SOC_ENUM_SINGLE(WM8988_ADCIN, 6, 4, wm8988_mono_mux);
311static const struct snd_kcontrol_new wm8988_monomux_controls =
312 SOC_DAPM_ENUM("Route", monomux);
313
314static const struct snd_soc_dapm_widget wm8988_dapm_widgets[] = {
315 SND_SOC_DAPM_MICBIAS("Mic Bias", WM8988_PWR1, 1, 0),
316
317 SND_SOC_DAPM_MUX("Differential Mux", SND_SOC_NOPM, 0, 0,
318 &wm8988_diffmux_controls),
319 SND_SOC_DAPM_MUX("Left ADC Mux", SND_SOC_NOPM, 0, 0,
320 &wm8988_monomux_controls),
321 SND_SOC_DAPM_MUX("Right ADC Mux", SND_SOC_NOPM, 0, 0,
322 &wm8988_monomux_controls),
323
324 SND_SOC_DAPM_MUX("Left PGA Mux", WM8988_PWR1, 5, 0,
325 &wm8988_left_pga_controls),
326 SND_SOC_DAPM_MUX("Right PGA Mux", WM8988_PWR1, 4, 0,
327 &wm8988_right_pga_controls),
328
329 SND_SOC_DAPM_MUX("Left Line Mux", SND_SOC_NOPM, 0, 0,
330 &wm8988_left_line_controls),
331 SND_SOC_DAPM_MUX("Right Line Mux", SND_SOC_NOPM, 0, 0,
332 &wm8988_right_line_controls),
333
334 SND_SOC_DAPM_ADC("Right ADC", "Right Capture", WM8988_PWR1, 2, 0),
335 SND_SOC_DAPM_ADC("Left ADC", "Left Capture", WM8988_PWR1, 3, 0),
336
337 SND_SOC_DAPM_DAC("Right DAC", "Right Playback", WM8988_PWR2, 7, 0),
338 SND_SOC_DAPM_DAC("Left DAC", "Left Playback", WM8988_PWR2, 8, 0),
339
340 SND_SOC_DAPM_MIXER("Left Mixer", SND_SOC_NOPM, 0, 0,
341 &wm8988_left_mixer_controls[0],
342 ARRAY_SIZE(wm8988_left_mixer_controls)),
343 SND_SOC_DAPM_MIXER("Right Mixer", SND_SOC_NOPM, 0, 0,
344 &wm8988_right_mixer_controls[0],
345 ARRAY_SIZE(wm8988_right_mixer_controls)),
346
347 SND_SOC_DAPM_PGA("Right Out 2", WM8988_PWR2, 3, 0, NULL, 0),
348 SND_SOC_DAPM_PGA("Left Out 2", WM8988_PWR2, 4, 0, NULL, 0),
349 SND_SOC_DAPM_PGA("Right Out 1", WM8988_PWR2, 5, 0, NULL, 0),
350 SND_SOC_DAPM_PGA("Left Out 1", WM8988_PWR2, 6, 0, NULL, 0),
351
352 SND_SOC_DAPM_POST("LRC control", wm8988_lrc_control),
353
354 SND_SOC_DAPM_OUTPUT("LOUT1"),
355 SND_SOC_DAPM_OUTPUT("ROUT1"),
356 SND_SOC_DAPM_OUTPUT("LOUT2"),
357 SND_SOC_DAPM_OUTPUT("ROUT2"),
358 SND_SOC_DAPM_OUTPUT("VREF"),
359
360 SND_SOC_DAPM_INPUT("LINPUT1"),
361 SND_SOC_DAPM_INPUT("LINPUT2"),
362 SND_SOC_DAPM_INPUT("RINPUT1"),
363 SND_SOC_DAPM_INPUT("RINPUT2"),
364};
365
366static const struct snd_soc_dapm_route audio_map[] = {
367
368 { "Left Line Mux", "Line 1", "LINPUT1" },
369 { "Left Line Mux", "Line 2", "LINPUT2" },
370 { "Left Line Mux", "PGA", "Left PGA Mux" },
371 { "Left Line Mux", "Differential", "Differential Mux" },
372
373 { "Right Line Mux", "Line 1", "RINPUT1" },
374 { "Right Line Mux", "Line 2", "RINPUT2" },
375 { "Right Line Mux", "PGA", "Right PGA Mux" },
376 { "Right Line Mux", "Differential", "Differential Mux" },
377
378 { "Left PGA Mux", "Line 1", "LINPUT1" },
379 { "Left PGA Mux", "Line 2", "LINPUT2" },
380 { "Left PGA Mux", "Differential", "Differential Mux" },
381
382 { "Right PGA Mux", "Line 1", "RINPUT1" },
383 { "Right PGA Mux", "Line 2", "RINPUT2" },
384 { "Right PGA Mux", "Differential", "Differential Mux" },
385
386 { "Differential Mux", "Line 1", "LINPUT1" },
387 { "Differential Mux", "Line 1", "RINPUT1" },
388 { "Differential Mux", "Line 2", "LINPUT2" },
389 { "Differential Mux", "Line 2", "RINPUT2" },
390
391 { "Left ADC Mux", "Stereo", "Left PGA Mux" },
392 { "Left ADC Mux", "Mono (Left)", "Left PGA Mux" },
393 { "Left ADC Mux", "Digital Mono", "Left PGA Mux" },
394
395 { "Right ADC Mux", "Stereo", "Right PGA Mux" },
396 { "Right ADC Mux", "Mono (Right)", "Right PGA Mux" },
397 { "Right ADC Mux", "Digital Mono", "Right PGA Mux" },
398
399 { "Left ADC", NULL, "Left ADC Mux" },
400 { "Right ADC", NULL, "Right ADC Mux" },
401
402 { "Left Line Mux", "Line 1", "LINPUT1" },
403 { "Left Line Mux", "Line 2", "LINPUT2" },
404 { "Left Line Mux", "PGA", "Left PGA Mux" },
405 { "Left Line Mux", "Differential", "Differential Mux" },
406
407 { "Right Line Mux", "Line 1", "RINPUT1" },
408 { "Right Line Mux", "Line 2", "RINPUT2" },
409 { "Right Line Mux", "PGA", "Right PGA Mux" },
410 { "Right Line Mux", "Differential", "Differential Mux" },
411
412 { "Left Mixer", "Playback Switch", "Left DAC" },
413 { "Left Mixer", "Left Bypass Switch", "Left Line Mux" },
414 { "Left Mixer", "Right Playback Switch", "Right DAC" },
415 { "Left Mixer", "Right Bypass Switch", "Right Line Mux" },
416
417 { "Right Mixer", "Left Playback Switch", "Left DAC" },
418 { "Right Mixer", "Left Bypass Switch", "Left Line Mux" },
419 { "Right Mixer", "Playback Switch", "Right DAC" },
420 { "Right Mixer", "Right Bypass Switch", "Right Line Mux" },
421
422 { "Left Out 1", NULL, "Left Mixer" },
423 { "LOUT1", NULL, "Left Out 1" },
424 { "Right Out 1", NULL, "Right Mixer" },
425 { "ROUT1", NULL, "Right Out 1" },
426
427 { "Left Out 2", NULL, "Left Mixer" },
428 { "LOUT2", NULL, "Left Out 2" },
429 { "Right Out 2", NULL, "Right Mixer" },
430 { "ROUT2", NULL, "Right Out 2" },
431};
432
433struct _coeff_div {
434 u32 mclk;
435 u32 rate;
436 u16 fs;
437 u8 sr:5;
438 u8 usb:1;
439};
440
441/* codec hifi mclk clock divider coefficients */
442static const struct _coeff_div coeff_div[] = {
443 /* 8k */
444 {12288000, 8000, 1536, 0x6, 0x0},
445 {11289600, 8000, 1408, 0x16, 0x0},
446 {18432000, 8000, 2304, 0x7, 0x0},
447 {16934400, 8000, 2112, 0x17, 0x0},
448 {12000000, 8000, 1500, 0x6, 0x1},
449
450 /* 11.025k */
451 {11289600, 11025, 1024, 0x18, 0x0},
452 {16934400, 11025, 1536, 0x19, 0x0},
453 {12000000, 11025, 1088, 0x19, 0x1},
454
455 /* 16k */
456 {12288000, 16000, 768, 0xa, 0x0},
457 {18432000, 16000, 1152, 0xb, 0x0},
458 {12000000, 16000, 750, 0xa, 0x1},
459
460 /* 22.05k */
461 {11289600, 22050, 512, 0x1a, 0x0},
462 {16934400, 22050, 768, 0x1b, 0x0},
463 {12000000, 22050, 544, 0x1b, 0x1},
464
465 /* 32k */
466 {12288000, 32000, 384, 0xc, 0x0},
467 {18432000, 32000, 576, 0xd, 0x0},
468 {12000000, 32000, 375, 0xa, 0x1},
469
470 /* 44.1k */
471 {11289600, 44100, 256, 0x10, 0x0},
472 {16934400, 44100, 384, 0x11, 0x0},
473 {12000000, 44100, 272, 0x11, 0x1},
474
475 /* 48k */
476 {12288000, 48000, 256, 0x0, 0x0},
477 {18432000, 48000, 384, 0x1, 0x0},
478 {12000000, 48000, 250, 0x0, 0x1},
479
480 /* 88.2k */
481 {11289600, 88200, 128, 0x1e, 0x0},
482 {16934400, 88200, 192, 0x1f, 0x0},
483 {12000000, 88200, 136, 0x1f, 0x1},
484
485 /* 96k */
486 {12288000, 96000, 128, 0xe, 0x0},
487 {18432000, 96000, 192, 0xf, 0x0},
488 {12000000, 96000, 125, 0xe, 0x1},
489};
490
491static inline int get_coeff(int mclk, int rate)
492{
493 int i;
494
495 for (i = 0; i < ARRAY_SIZE(coeff_div); i++) {
496 if (coeff_div[i].rate == rate && coeff_div[i].mclk == mclk)
497 return i;
498 }
499
500 return -EINVAL;
501}
502
503/* The set of rates we can generate from the above for each SYSCLK */
504
505static unsigned int rates_12288[] = {
506 8000, 12000, 16000, 24000, 24000, 32000, 48000, 96000,
507};
508
509static struct snd_pcm_hw_constraint_list constraints_12288 = {
510 .count = ARRAY_SIZE(rates_12288),
511 .list = rates_12288,
512};
513
514static unsigned int rates_112896[] = {
515 8000, 11025, 22050, 44100,
516};
517
518static struct snd_pcm_hw_constraint_list constraints_112896 = {
519 .count = ARRAY_SIZE(rates_112896),
520 .list = rates_112896,
521};
522
523static unsigned int rates_12[] = {
524 8000, 11025, 12000, 16000, 22050, 2400, 32000, 41100, 48000,
525 48000, 88235, 96000,
526};
527
528static struct snd_pcm_hw_constraint_list constraints_12 = {
529 .count = ARRAY_SIZE(rates_12),
530 .list = rates_12,
531};
532
533/*
534 * Note that this should be called from init rather than from hw_params.
535 */
536static int wm8988_set_dai_sysclk(struct snd_soc_dai *codec_dai,
537 int clk_id, unsigned int freq, int dir)
538{
539 struct snd_soc_codec *codec = codec_dai->codec;
540 struct wm8988_priv *wm8988 = codec->private_data;
541
542 switch (freq) {
543 case 11289600:
544 case 18432000:
545 case 22579200:
546 case 36864000:
547 wm8988->sysclk_constraints = &constraints_112896;
548 wm8988->sysclk = freq;
549 return 0;
550
551 case 12288000:
552 case 16934400:
553 case 24576000:
554 case 33868800:
555 wm8988->sysclk_constraints = &constraints_12288;
556 wm8988->sysclk = freq;
557 return 0;
558
559 case 12000000:
560 case 24000000:
561 wm8988->sysclk_constraints = &constraints_12;
562 wm8988->sysclk = freq;
563 return 0;
564 }
565 return -EINVAL;
566}
567
568static int wm8988_set_dai_fmt(struct snd_soc_dai *codec_dai,
569 unsigned int fmt)
570{
571 struct snd_soc_codec *codec = codec_dai->codec;
572 u16 iface = 0;
573
574 /* set master/slave audio interface */
575 switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
576 case SND_SOC_DAIFMT_CBM_CFM:
577 iface = 0x0040;
578 break;
579 case SND_SOC_DAIFMT_CBS_CFS:
580 break;
581 default:
582 return -EINVAL;
583 }
584
585 /* interface format */
586 switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
587 case SND_SOC_DAIFMT_I2S:
588 iface |= 0x0002;
589 break;
590 case SND_SOC_DAIFMT_RIGHT_J:
591 break;
592 case SND_SOC_DAIFMT_LEFT_J:
593 iface |= 0x0001;
594 break;
595 case SND_SOC_DAIFMT_DSP_A:
596 iface |= 0x0003;
597 break;
598 case SND_SOC_DAIFMT_DSP_B:
599 iface |= 0x0013;
600 break;
601 default:
602 return -EINVAL;
603 }
604
605 /* clock inversion */
606 switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
607 case SND_SOC_DAIFMT_NB_NF:
608 break;
609 case SND_SOC_DAIFMT_IB_IF:
610 iface |= 0x0090;
611 break;
612 case SND_SOC_DAIFMT_IB_NF:
613 iface |= 0x0080;
614 break;
615 case SND_SOC_DAIFMT_NB_IF:
616 iface |= 0x0010;
617 break;
618 default:
619 return -EINVAL;
620 }
621
622 wm8988_write(codec, WM8988_IFACE, iface);
623 return 0;
624}
625
626static int wm8988_pcm_startup(struct snd_pcm_substream *substream,
627 struct snd_soc_dai *dai)
628{
629 struct snd_soc_codec *codec = dai->codec;
630 struct wm8988_priv *wm8988 = codec->private_data;
631
632 /* The set of sample rates that can be supported depends on the
633 * MCLK supplied to the CODEC - enforce this.
634 */
635 if (!wm8988->sysclk) {
636 dev_err(codec->dev,
637 "No MCLK configured, call set_sysclk() on init\n");
638 return -EINVAL;
639 }
640
641 snd_pcm_hw_constraint_list(substream->runtime, 0,
642 SNDRV_PCM_HW_PARAM_RATE,
643 wm8988->sysclk_constraints);
644
645 return 0;
646}
647
648static int wm8988_pcm_hw_params(struct snd_pcm_substream *substream,
649 struct snd_pcm_hw_params *params,
650 struct snd_soc_dai *dai)
651{
652 struct snd_soc_pcm_runtime *rtd = substream->private_data;
653 struct snd_soc_device *socdev = rtd->socdev;
654 struct snd_soc_codec *codec = socdev->card->codec;
655 struct wm8988_priv *wm8988 = codec->private_data;
656 u16 iface = wm8988_read_reg_cache(codec, WM8988_IFACE) & 0x1f3;
657 u16 srate = wm8988_read_reg_cache(codec, WM8988_SRATE) & 0x180;
658 int coeff;
659
660 coeff = get_coeff(wm8988->sysclk, params_rate(params));
661 if (coeff < 0) {
662 coeff = get_coeff(wm8988->sysclk / 2, params_rate(params));
663 srate |= 0x40;
664 }
665 if (coeff < 0) {
666 dev_err(codec->dev,
667 "Unable to configure sample rate %dHz with %dHz MCLK\n",
668 params_rate(params), wm8988->sysclk);
669 return coeff;
670 }
671
672 /* bit size */
673 switch (params_format(params)) {
674 case SNDRV_PCM_FORMAT_S16_LE:
675 break;
676 case SNDRV_PCM_FORMAT_S20_3LE:
677 iface |= 0x0004;
678 break;
679 case SNDRV_PCM_FORMAT_S24_LE:
680 iface |= 0x0008;
681 break;
682 case SNDRV_PCM_FORMAT_S32_LE:
683 iface |= 0x000c;
684 break;
685 }
686
687 /* set iface & srate */
688 wm8988_write(codec, WM8988_IFACE, iface);
689 if (coeff >= 0)
690 wm8988_write(codec, WM8988_SRATE, srate |
691 (coeff_div[coeff].sr << 1) | coeff_div[coeff].usb);
692
693 return 0;
694}
695
696static int wm8988_mute(struct snd_soc_dai *dai, int mute)
697{
698 struct snd_soc_codec *codec = dai->codec;
699 u16 mute_reg = wm8988_read_reg_cache(codec, WM8988_ADCDAC) & 0xfff7;
700
701 if (mute)
702 wm8988_write(codec, WM8988_ADCDAC, mute_reg | 0x8);
703 else
704 wm8988_write(codec, WM8988_ADCDAC, mute_reg);
705 return 0;
706}
707
708static int wm8988_set_bias_level(struct snd_soc_codec *codec,
709 enum snd_soc_bias_level level)
710{
711 u16 pwr_reg = wm8988_read_reg_cache(codec, WM8988_PWR1) & ~0x1c1;
712
713 switch (level) {
714 case SND_SOC_BIAS_ON:
715 break;
716
717 case SND_SOC_BIAS_PREPARE:
718 /* VREF, VMID=2x50k, digital enabled */
719 wm8988_write(codec, WM8988_PWR1, pwr_reg | 0x00c0);
720 break;
721
722 case SND_SOC_BIAS_STANDBY:
723 if (codec->bias_level == SND_SOC_BIAS_OFF) {
724 /* VREF, VMID=2x5k */
725 wm8988_write(codec, WM8988_PWR1, pwr_reg | 0x1c1);
726
727 /* Charge caps */
728 msleep(100);
729 }
730
731 /* VREF, VMID=2*500k, digital stopped */
732 wm8988_write(codec, WM8988_PWR1, pwr_reg | 0x0141);
733 break;
734
735 case SND_SOC_BIAS_OFF:
736 wm8988_write(codec, WM8988_PWR1, 0x0000);
737 break;
738 }
739 codec->bias_level = level;
740 return 0;
741}
742
743#define WM8988_RATES SNDRV_PCM_RATE_8000_96000
744
745#define WM8988_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE |\
746 SNDRV_PCM_FMTBIT_S24_LE)
747
748static struct snd_soc_dai_ops wm8988_ops = {
749 .startup = wm8988_pcm_startup,
750 .hw_params = wm8988_pcm_hw_params,
751 .set_fmt = wm8988_set_dai_fmt,
752 .set_sysclk = wm8988_set_dai_sysclk,
753 .digital_mute = wm8988_mute,
754};
755
756struct snd_soc_dai wm8988_dai = {
757 .name = "WM8988",
758 .playback = {
759 .stream_name = "Playback",
760 .channels_min = 1,
761 .channels_max = 2,
762 .rates = WM8988_RATES,
763 .formats = WM8988_FORMATS,
764 },
765 .capture = {
766 .stream_name = "Capture",
767 .channels_min = 1,
768 .channels_max = 2,
769 .rates = WM8988_RATES,
770 .formats = WM8988_FORMATS,
771 },
772 .ops = &wm8988_ops,
773 .symmetric_rates = 1,
774};
775EXPORT_SYMBOL_GPL(wm8988_dai);
776
777static int wm8988_suspend(struct platform_device *pdev, pm_message_t state)
778{
779 struct snd_soc_device *socdev = platform_get_drvdata(pdev);
780 struct snd_soc_codec *codec = socdev->card->codec;
781
782 wm8988_set_bias_level(codec, SND_SOC_BIAS_OFF);
783 return 0;
784}
785
786static int wm8988_resume(struct platform_device *pdev)
787{
788 struct snd_soc_device *socdev = platform_get_drvdata(pdev);
789 struct snd_soc_codec *codec = socdev->card->codec;
790 int i;
791 u8 data[2];
792 u16 *cache = codec->reg_cache;
793
794 /* Sync reg_cache with the hardware */
795 for (i = 0; i < WM8988_NUM_REG; i++) {
796 if (i == WM8988_RESET)
797 continue;
798 data[0] = (i << 1) | ((cache[i] >> 8) & 0x0001);
799 data[1] = cache[i] & 0x00ff;
800 codec->hw_write(codec->control_data, data, 2);
801 }
802
803 wm8988_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
804
805 return 0;
806}
807
808static struct snd_soc_codec *wm8988_codec;
809
810static int wm8988_probe(struct platform_device *pdev)
811{
812 struct snd_soc_device *socdev = platform_get_drvdata(pdev);
813 struct snd_soc_codec *codec;
814 int ret = 0;
815
816 if (wm8988_codec == NULL) {
817 dev_err(&pdev->dev, "Codec device not registered\n");
818 return -ENODEV;
819 }
820
821 socdev->card->codec = wm8988_codec;
822 codec = wm8988_codec;
823
824 /* register pcms */
825 ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1);
826 if (ret < 0) {
827 dev_err(codec->dev, "failed to create pcms: %d\n", ret);
828 goto pcm_err;
829 }
830
831 snd_soc_add_controls(codec, wm8988_snd_controls,
832 ARRAY_SIZE(wm8988_snd_controls));
833 snd_soc_dapm_new_controls(codec, wm8988_dapm_widgets,
834 ARRAY_SIZE(wm8988_dapm_widgets));
835 snd_soc_dapm_add_routes(codec, audio_map, ARRAY_SIZE(audio_map));
836 snd_soc_dapm_new_widgets(codec);
837
838 ret = snd_soc_init_card(socdev);
839 if (ret < 0) {
840 dev_err(codec->dev, "failed to register card: %d\n", ret);
841 goto card_err;
842 }
843
844 return ret;
845
846card_err:
847 snd_soc_free_pcms(socdev);
848 snd_soc_dapm_free(socdev);
849pcm_err:
850 return ret;
851}
852
853static int wm8988_remove(struct platform_device *pdev)
854{
855 struct snd_soc_device *socdev = platform_get_drvdata(pdev);
856
857 snd_soc_free_pcms(socdev);
858 snd_soc_dapm_free(socdev);
859
860 return 0;
861}
862
863struct snd_soc_codec_device soc_codec_dev_wm8988 = {
864 .probe = wm8988_probe,
865 .remove = wm8988_remove,
866 .suspend = wm8988_suspend,
867 .resume = wm8988_resume,
868};
869EXPORT_SYMBOL_GPL(soc_codec_dev_wm8988);
870
871static int wm8988_register(struct wm8988_priv *wm8988)
872{
873 struct snd_soc_codec *codec = &wm8988->codec;
874 int ret;
875 u16 reg;
876
877 if (wm8988_codec) {
878 dev_err(codec->dev, "Another WM8988 is registered\n");
879 ret = -EINVAL;
880 goto err;
881 }
882
883 mutex_init(&codec->mutex);
884 INIT_LIST_HEAD(&codec->dapm_widgets);
885 INIT_LIST_HEAD(&codec->dapm_paths);
886
887 codec->private_data = wm8988;
888 codec->name = "WM8988";
889 codec->owner = THIS_MODULE;
890 codec->read = wm8988_read_reg_cache;
891 codec->write = wm8988_write;
892 codec->dai = &wm8988_dai;
893 codec->num_dai = 1;
894 codec->reg_cache_size = ARRAY_SIZE(wm8988->reg_cache);
895 codec->reg_cache = &wm8988->reg_cache;
896 codec->bias_level = SND_SOC_BIAS_OFF;
897 codec->set_bias_level = wm8988_set_bias_level;
898
899 memcpy(codec->reg_cache, wm8988_reg,
900 sizeof(wm8988_reg));
901
902 ret = wm8988_reset(codec);
903 if (ret < 0) {
904 dev_err(codec->dev, "Failed to issue reset\n");
905 return ret;
906 }
907
908 /* set the update bits (we always update left then right) */
909 reg = wm8988_read_reg_cache(codec, WM8988_RADC);
910 wm8988_write(codec, WM8988_RADC, reg | 0x100);
911 reg = wm8988_read_reg_cache(codec, WM8988_RDAC);
912 wm8988_write(codec, WM8988_RDAC, reg | 0x0100);
913 reg = wm8988_read_reg_cache(codec, WM8988_ROUT1V);
914 wm8988_write(codec, WM8988_ROUT1V, reg | 0x0100);
915 reg = wm8988_read_reg_cache(codec, WM8988_ROUT2V);
916 wm8988_write(codec, WM8988_ROUT2V, reg | 0x0100);
917 reg = wm8988_read_reg_cache(codec, WM8988_RINVOL);
918 wm8988_write(codec, WM8988_RINVOL, reg | 0x0100);
919
920 wm8988_set_bias_level(&wm8988->codec, SND_SOC_BIAS_STANDBY);
921
922 wm8988_dai.dev = codec->dev;
923
924 wm8988_codec = codec;
925
926 ret = snd_soc_register_codec(codec);
927 if (ret != 0) {
928 dev_err(codec->dev, "Failed to register codec: %d\n", ret);
929 return ret;
930 }
931
932 ret = snd_soc_register_dai(&wm8988_dai);
933 if (ret != 0) {
934 dev_err(codec->dev, "Failed to register DAI: %d\n", ret);
935 snd_soc_unregister_codec(codec);
936 return ret;
937 }
938
939 return 0;
940
941err:
942 kfree(wm8988);
943 return ret;
944}
945
946static void wm8988_unregister(struct wm8988_priv *wm8988)
947{
948 wm8988_set_bias_level(&wm8988->codec, SND_SOC_BIAS_OFF);
949 snd_soc_unregister_dai(&wm8988_dai);
950 snd_soc_unregister_codec(&wm8988->codec);
951 kfree(wm8988);
952 wm8988_codec = NULL;
953}
954
955#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
956static int wm8988_i2c_probe(struct i2c_client *i2c,
957 const struct i2c_device_id *id)
958{
959 struct wm8988_priv *wm8988;
960 struct snd_soc_codec *codec;
961
962 wm8988 = kzalloc(sizeof(struct wm8988_priv), GFP_KERNEL);
963 if (wm8988 == NULL)
964 return -ENOMEM;
965
966 codec = &wm8988->codec;
967 codec->hw_write = (hw_write_t)i2c_master_send;
968
969 i2c_set_clientdata(i2c, wm8988);
970 codec->control_data = i2c;
971
972 codec->dev = &i2c->dev;
973
974 return wm8988_register(wm8988);
975}
976
977static int wm8988_i2c_remove(struct i2c_client *client)
978{
979 struct wm8988_priv *wm8988 = i2c_get_clientdata(client);
980 wm8988_unregister(wm8988);
981 return 0;
982}
983
984static const struct i2c_device_id wm8988_i2c_id[] = {
985 { "wm8988", 0 },
986 { }
987};
988MODULE_DEVICE_TABLE(i2c, wm8988_i2c_id);
989
990static struct i2c_driver wm8988_i2c_driver = {
991 .driver = {
992 .name = "WM8988",
993 .owner = THIS_MODULE,
994 },
995 .probe = wm8988_i2c_probe,
996 .remove = wm8988_i2c_remove,
997 .id_table = wm8988_i2c_id,
998};
999#endif
1000
1001#if defined(CONFIG_SPI_MASTER)
1002static int wm8988_spi_write(struct spi_device *spi, const char *data, int len)
1003{
1004 struct spi_transfer t;
1005 struct spi_message m;
1006 u8 msg[2];
1007
1008 if (len <= 0)
1009 return 0;
1010
1011 msg[0] = data[0];
1012 msg[1] = data[1];
1013
1014 spi_message_init(&m);
1015 memset(&t, 0, (sizeof t));
1016
1017 t.tx_buf = &msg[0];
1018 t.len = len;
1019
1020 spi_message_add_tail(&t, &m);
1021 spi_sync(spi, &m);
1022
1023 return len;
1024}
1025
1026static int __devinit wm8988_spi_probe(struct spi_device *spi)
1027{
1028 struct wm8988_priv *wm8988;
1029 struct snd_soc_codec *codec;
1030
1031 wm8988 = kzalloc(sizeof(struct wm8988_priv), GFP_KERNEL);
1032 if (wm8988 == NULL)
1033 return -ENOMEM;
1034
1035 codec = &wm8988->codec;
1036 codec->hw_write = (hw_write_t)wm8988_spi_write;
1037 codec->control_data = spi;
1038 codec->dev = &spi->dev;
1039
1040 spi->dev.driver_data = wm8988;
1041
1042 return wm8988_register(wm8988);
1043}
1044
1045static int __devexit wm8988_spi_remove(struct spi_device *spi)
1046{
1047 struct wm8988_priv *wm8988 = spi->dev.driver_data;
1048
1049 wm8988_unregister(wm8988);
1050
1051 return 0;
1052}
1053
1054static struct spi_driver wm8988_spi_driver = {
1055 .driver = {
1056 .name = "wm8988",
1057 .bus = &spi_bus_type,
1058 .owner = THIS_MODULE,
1059 },
1060 .probe = wm8988_spi_probe,
1061 .remove = __devexit_p(wm8988_spi_remove),
1062};
1063#endif
1064
1065static int __init wm8988_modinit(void)
1066{
1067 int ret;
1068
1069#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
1070 ret = i2c_add_driver(&wm8988_i2c_driver);
1071 if (ret != 0)
1072 pr_err("WM8988: Unable to register I2C driver: %d\n", ret);
1073#endif
1074#if defined(CONFIG_SPI_MASTER)
1075 ret = spi_register_driver(&wm8988_spi_driver);
1076 if (ret != 0)
1077 pr_err("WM8988: Unable to register SPI driver: %d\n", ret);
1078#endif
1079 return ret;
1080}
1081module_init(wm8988_modinit);
1082
1083static void __exit wm8988_exit(void)
1084{
1085#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
1086 i2c_del_driver(&wm8988_i2c_driver);
1087#endif
1088#if defined(CONFIG_SPI_MASTER)
1089 spi_unregister_driver(&wm8988_spi_driver);
1090#endif
1091}
1092module_exit(wm8988_exit);
1093
1094
1095MODULE_DESCRIPTION("ASoC WM8988 driver");
1096MODULE_AUTHOR("Mark Brown <broonie@opensource.wolfsonmicro.com>");
1097MODULE_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..d029818350e9 100644
--- a/sound/soc/codecs/wm8990.c
+++ b/sound/soc/codecs/wm8990.c
@@ -998,7 +998,7 @@ static void pll_factors(struct _pll_div *pll_div, unsigned int target,
998 998
999 if ((Ndiv < 6) || (Ndiv > 12)) 999 if ((Ndiv < 6) || (Ndiv > 12))
1000 printk(KERN_WARNING 1000 printk(KERN_WARNING
1001 "WM8990 N value outwith recommended range! N = %d\n", Ndiv); 1001 "WM8990 N value outwith recommended range! N = %u\n", Ndiv);
1002 1002
1003 pll_div->n = Ndiv; 1003 pll_div->n = Ndiv;
1004 Nmod = target % source; 1004 Nmod = target % source;
diff --git a/sound/soc/codecs/wm9081.c b/sound/soc/codecs/wm9081.c
new file mode 100644
index 000000000000..86fc57e25f97
--- /dev/null
+++ b/sound/soc/codecs/wm9081.c
@@ -0,0 +1,1534 @@
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 struct wm9081_retune_mobile_config *retune;
169};
170
171static int wm9081_reg_is_volatile(int reg)
172{
173 switch (reg) {
174 default:
175 return 0;
176 }
177}
178
179static unsigned int wm9081_read_reg_cache(struct snd_soc_codec *codec,
180 unsigned int reg)
181{
182 u16 *cache = codec->reg_cache;
183 BUG_ON(reg > WM9081_MAX_REGISTER);
184 return cache[reg];
185}
186
187static unsigned int wm9081_read_hw(struct snd_soc_codec *codec, u8 reg)
188{
189 struct i2c_msg xfer[2];
190 u16 data;
191 int ret;
192 struct i2c_client *client = codec->control_data;
193
194 BUG_ON(reg > WM9081_MAX_REGISTER);
195
196 /* Write register */
197 xfer[0].addr = client->addr;
198 xfer[0].flags = 0;
199 xfer[0].len = 1;
200 xfer[0].buf = &reg;
201
202 /* Read data */
203 xfer[1].addr = client->addr;
204 xfer[1].flags = I2C_M_RD;
205 xfer[1].len = 2;
206 xfer[1].buf = (u8 *)&data;
207
208 ret = i2c_transfer(client->adapter, xfer, 2);
209 if (ret != 2) {
210 dev_err(&client->dev, "i2c_transfer() returned %d\n", ret);
211 return 0;
212 }
213
214 return (data >> 8) | ((data & 0xff) << 8);
215}
216
217static unsigned int wm9081_read(struct snd_soc_codec *codec, unsigned int reg)
218{
219 if (wm9081_reg_is_volatile(reg))
220 return wm9081_read_hw(codec, reg);
221 else
222 return wm9081_read_reg_cache(codec, reg);
223}
224
225static int wm9081_write(struct snd_soc_codec *codec, unsigned int reg,
226 unsigned int value)
227{
228 u16 *cache = codec->reg_cache;
229 u8 data[3];
230
231 BUG_ON(reg > WM9081_MAX_REGISTER);
232
233 if (!wm9081_reg_is_volatile(reg))
234 cache[reg] = value;
235
236 data[0] = reg;
237 data[1] = value >> 8;
238 data[2] = value & 0x00ff;
239
240 if (codec->hw_write(codec->control_data, data, 3) == 3)
241 return 0;
242 else
243 return -EIO;
244}
245
246static int wm9081_reset(struct snd_soc_codec *codec)
247{
248 return wm9081_write(codec, WM9081_SOFTWARE_RESET, 0);
249}
250
251static const DECLARE_TLV_DB_SCALE(drc_in_tlv, -4500, 75, 0);
252static const DECLARE_TLV_DB_SCALE(drc_out_tlv, -2250, 75, 0);
253static const DECLARE_TLV_DB_SCALE(drc_min_tlv, -1800, 600, 0);
254static unsigned int drc_max_tlv[] = {
255 TLV_DB_RANGE_HEAD(4),
256 0, 0, TLV_DB_SCALE_ITEM(1200, 0, 0),
257 1, 1, TLV_DB_SCALE_ITEM(1800, 0, 0),
258 2, 2, TLV_DB_SCALE_ITEM(2400, 0, 0),
259 3, 3, TLV_DB_SCALE_ITEM(3600, 0, 0),
260};
261static const DECLARE_TLV_DB_SCALE(drc_qr_tlv, 1200, 600, 0);
262static const DECLARE_TLV_DB_SCALE(drc_startup_tlv, -300, 50, 0);
263
264static const DECLARE_TLV_DB_SCALE(eq_tlv, -1200, 100, 0);
265
266static const DECLARE_TLV_DB_SCALE(in_tlv, -600, 600, 0);
267static const DECLARE_TLV_DB_SCALE(dac_tlv, -7200, 75, 1);
268static const DECLARE_TLV_DB_SCALE(out_tlv, -5700, 100, 0);
269
270static const char *drc_high_text[] = {
271 "1",
272 "1/2",
273 "1/4",
274 "1/8",
275 "1/16",
276 "0",
277};
278
279static const struct soc_enum drc_high =
280 SOC_ENUM_SINGLE(WM9081_DRC_3, 3, 6, drc_high_text);
281
282static const char *drc_low_text[] = {
283 "1",
284 "1/2",
285 "1/4",
286 "1/8",
287 "0",
288};
289
290static const struct soc_enum drc_low =
291 SOC_ENUM_SINGLE(WM9081_DRC_3, 0, 5, drc_low_text);
292
293static const char *drc_atk_text[] = {
294 "181us",
295 "181us",
296 "363us",
297 "726us",
298 "1.45ms",
299 "2.9ms",
300 "5.8ms",
301 "11.6ms",
302 "23.2ms",
303 "46.4ms",
304 "92.8ms",
305 "185.6ms",
306};
307
308static const struct soc_enum drc_atk =
309 SOC_ENUM_SINGLE(WM9081_DRC_2, 12, 12, drc_atk_text);
310
311static const char *drc_dcy_text[] = {
312 "186ms",
313 "372ms",
314 "743ms",
315 "1.49s",
316 "2.97s",
317 "5.94s",
318 "11.89s",
319 "23.78s",
320 "47.56s",
321};
322
323static const struct soc_enum drc_dcy =
324 SOC_ENUM_SINGLE(WM9081_DRC_2, 8, 9, drc_dcy_text);
325
326static const char *drc_qr_dcy_text[] = {
327 "0.725ms",
328 "1.45ms",
329 "5.8ms",
330};
331
332static const struct soc_enum drc_qr_dcy =
333 SOC_ENUM_SINGLE(WM9081_DRC_2, 4, 3, drc_qr_dcy_text);
334
335static const char *dac_deemph_text[] = {
336 "None",
337 "32kHz",
338 "44.1kHz",
339 "48kHz",
340};
341
342static const struct soc_enum dac_deemph =
343 SOC_ENUM_SINGLE(WM9081_DAC_DIGITAL_2, 1, 4, dac_deemph_text);
344
345static const char *speaker_mode_text[] = {
346 "Class D",
347 "Class AB",
348};
349
350static const struct soc_enum speaker_mode =
351 SOC_ENUM_SINGLE(WM9081_ANALOGUE_SPEAKER_2, 6, 2, speaker_mode_text);
352
353static int speaker_mode_get(struct snd_kcontrol *kcontrol,
354 struct snd_ctl_elem_value *ucontrol)
355{
356 struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
357 unsigned int reg;
358
359 reg = wm9081_read(codec, WM9081_ANALOGUE_SPEAKER_2);
360 if (reg & WM9081_SPK_MODE)
361 ucontrol->value.integer.value[0] = 1;
362 else
363 ucontrol->value.integer.value[0] = 0;
364
365 return 0;
366}
367
368/*
369 * Stop any attempts to change speaker mode while the speaker is enabled.
370 *
371 * We also have some special anti-pop controls dependant on speaker
372 * mode which must be changed along with the mode.
373 */
374static int speaker_mode_put(struct snd_kcontrol *kcontrol,
375 struct snd_ctl_elem_value *ucontrol)
376{
377 struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
378 unsigned int reg_pwr = wm9081_read(codec, WM9081_POWER_MANAGEMENT);
379 unsigned int reg2 = wm9081_read(codec, WM9081_ANALOGUE_SPEAKER_2);
380
381 /* Are we changing anything? */
382 if (ucontrol->value.integer.value[0] ==
383 ((reg2 & WM9081_SPK_MODE) != 0))
384 return 0;
385
386 /* Don't try to change modes while enabled */
387 if (reg_pwr & WM9081_SPK_ENA)
388 return -EINVAL;
389
390 if (ucontrol->value.integer.value[0]) {
391 /* Class AB */
392 reg2 &= ~(WM9081_SPK_INV_MUTE | WM9081_OUT_SPK_CTRL);
393 reg2 |= WM9081_SPK_MODE;
394 } else {
395 /* Class D */
396 reg2 |= WM9081_SPK_INV_MUTE | WM9081_OUT_SPK_CTRL;
397 reg2 &= ~WM9081_SPK_MODE;
398 }
399
400 wm9081_write(codec, WM9081_ANALOGUE_SPEAKER_2, reg2);
401
402 return 0;
403}
404
405static const struct snd_kcontrol_new wm9081_snd_controls[] = {
406SOC_SINGLE_TLV("IN1 Volume", WM9081_ANALOGUE_MIXER, 1, 1, 1, in_tlv),
407SOC_SINGLE_TLV("IN2 Volume", WM9081_ANALOGUE_MIXER, 3, 1, 1, in_tlv),
408
409SOC_SINGLE_TLV("Playback Volume", WM9081_DAC_DIGITAL_1, 1, 96, 0, dac_tlv),
410
411SOC_SINGLE("LINEOUT Switch", WM9081_ANALOGUE_LINEOUT, 7, 1, 1),
412SOC_SINGLE("LINEOUT ZC Switch", WM9081_ANALOGUE_LINEOUT, 6, 1, 0),
413SOC_SINGLE_TLV("LINEOUT Volume", WM9081_ANALOGUE_LINEOUT, 0, 63, 0, out_tlv),
414
415SOC_SINGLE("DRC Switch", WM9081_DRC_1, 15, 1, 0),
416SOC_ENUM("DRC High Slope", drc_high),
417SOC_ENUM("DRC Low Slope", drc_low),
418SOC_SINGLE_TLV("DRC Input Volume", WM9081_DRC_4, 5, 60, 1, drc_in_tlv),
419SOC_SINGLE_TLV("DRC Output Volume", WM9081_DRC_4, 0, 30, 1, drc_out_tlv),
420SOC_SINGLE_TLV("DRC Minimum Volume", WM9081_DRC_2, 2, 3, 1, drc_min_tlv),
421SOC_SINGLE_TLV("DRC Maximum Volume", WM9081_DRC_2, 0, 3, 0, drc_max_tlv),
422SOC_ENUM("DRC Attack", drc_atk),
423SOC_ENUM("DRC Decay", drc_dcy),
424SOC_SINGLE("DRC Quick Release Switch", WM9081_DRC_1, 2, 1, 0),
425SOC_SINGLE_TLV("DRC Quick Release Volume", WM9081_DRC_2, 6, 3, 0, drc_qr_tlv),
426SOC_ENUM("DRC Quick Release Decay", drc_qr_dcy),
427SOC_SINGLE_TLV("DRC Startup Volume", WM9081_DRC_1, 6, 18, 0, drc_startup_tlv),
428
429SOC_SINGLE("EQ Switch", WM9081_EQ_1, 0, 1, 0),
430
431SOC_SINGLE("Speaker DC Volume", WM9081_ANALOGUE_SPEAKER_1, 3, 5, 0),
432SOC_SINGLE("Speaker AC Volume", WM9081_ANALOGUE_SPEAKER_1, 0, 5, 0),
433SOC_SINGLE("Speaker Switch", WM9081_ANALOGUE_SPEAKER_PGA, 7, 1, 1),
434SOC_SINGLE("Speaker ZC Switch", WM9081_ANALOGUE_SPEAKER_PGA, 6, 1, 0),
435SOC_SINGLE_TLV("Speaker Volume", WM9081_ANALOGUE_SPEAKER_PGA, 0, 63, 0,
436 out_tlv),
437SOC_ENUM("DAC Deemphasis", dac_deemph),
438SOC_ENUM_EXT("Speaker Mode", speaker_mode, speaker_mode_get, speaker_mode_put),
439};
440
441static const struct snd_kcontrol_new wm9081_eq_controls[] = {
442SOC_SINGLE_TLV("EQ1 Volume", WM9081_EQ_1, 11, 24, 0, eq_tlv),
443SOC_SINGLE_TLV("EQ2 Volume", WM9081_EQ_1, 6, 24, 0, eq_tlv),
444SOC_SINGLE_TLV("EQ3 Volume", WM9081_EQ_1, 1, 24, 0, eq_tlv),
445SOC_SINGLE_TLV("EQ4 Volume", WM9081_EQ_2, 11, 24, 0, eq_tlv),
446SOC_SINGLE_TLV("EQ5 Volume", WM9081_EQ_2, 6, 24, 0, eq_tlv),
447};
448
449static const struct snd_kcontrol_new mixer[] = {
450SOC_DAPM_SINGLE("IN1 Switch", WM9081_ANALOGUE_MIXER, 0, 1, 0),
451SOC_DAPM_SINGLE("IN2 Switch", WM9081_ANALOGUE_MIXER, 2, 1, 0),
452SOC_DAPM_SINGLE("Playback Switch", WM9081_ANALOGUE_MIXER, 4, 1, 0),
453};
454
455static int speaker_event(struct snd_soc_dapm_widget *w,
456 struct snd_kcontrol *kcontrol, int event)
457{
458 struct snd_soc_codec *codec = w->codec;
459 unsigned int reg = wm9081_read(codec, WM9081_POWER_MANAGEMENT);
460
461 switch (event) {
462 case SND_SOC_DAPM_POST_PMU:
463 reg |= WM9081_SPK_ENA;
464 break;
465
466 case SND_SOC_DAPM_PRE_PMD:
467 reg &= ~WM9081_SPK_ENA;
468 break;
469 }
470
471 wm9081_write(codec, WM9081_POWER_MANAGEMENT, reg);
472
473 return 0;
474}
475
476struct _fll_div {
477 u16 fll_fratio;
478 u16 fll_outdiv;
479 u16 fll_clk_ref_div;
480 u16 n;
481 u16 k;
482};
483
484/* The size in bits of the FLL divide multiplied by 10
485 * to allow rounding later */
486#define FIXED_FLL_SIZE ((1 << 16) * 10)
487
488static struct {
489 unsigned int min;
490 unsigned int max;
491 u16 fll_fratio;
492 int ratio;
493} fll_fratios[] = {
494 { 0, 64000, 4, 16 },
495 { 64000, 128000, 3, 8 },
496 { 128000, 256000, 2, 4 },
497 { 256000, 1000000, 1, 2 },
498 { 1000000, 13500000, 0, 1 },
499};
500
501static int fll_factors(struct _fll_div *fll_div, unsigned int Fref,
502 unsigned int Fout)
503{
504 u64 Kpart;
505 unsigned int K, Ndiv, Nmod, target;
506 unsigned int div;
507 int i;
508
509 /* Fref must be <=13.5MHz */
510 div = 1;
511 while ((Fref / div) > 13500000) {
512 div *= 2;
513
514 if (div > 8) {
515 pr_err("Can't scale %dMHz input down to <=13.5MHz\n",
516 Fref);
517 return -EINVAL;
518 }
519 }
520 fll_div->fll_clk_ref_div = div / 2;
521
522 pr_debug("Fref=%u Fout=%u\n", Fref, Fout);
523
524 /* Apply the division for our remaining calculations */
525 Fref /= div;
526
527 /* Fvco should be 90-100MHz; don't check the upper bound */
528 div = 0;
529 target = Fout * 2;
530 while (target < 90000000) {
531 div++;
532 target *= 2;
533 if (div > 7) {
534 pr_err("Unable to find FLL_OUTDIV for Fout=%uHz\n",
535 Fout);
536 return -EINVAL;
537 }
538 }
539 fll_div->fll_outdiv = div;
540
541 pr_debug("Fvco=%dHz\n", target);
542
543 /* Find an appropraite FLL_FRATIO and factor it out of the target */
544 for (i = 0; i < ARRAY_SIZE(fll_fratios); i++) {
545 if (fll_fratios[i].min <= Fref && Fref <= fll_fratios[i].max) {
546 fll_div->fll_fratio = fll_fratios[i].fll_fratio;
547 target /= fll_fratios[i].ratio;
548 break;
549 }
550 }
551 if (i == ARRAY_SIZE(fll_fratios)) {
552 pr_err("Unable to find FLL_FRATIO for Fref=%uHz\n", Fref);
553 return -EINVAL;
554 }
555
556 /* Now, calculate N.K */
557 Ndiv = target / Fref;
558
559 fll_div->n = Ndiv;
560 Nmod = target % Fref;
561 pr_debug("Nmod=%d\n", Nmod);
562
563 /* Calculate fractional part - scale up so we can round. */
564 Kpart = FIXED_FLL_SIZE * (long long)Nmod;
565
566 do_div(Kpart, Fref);
567
568 K = Kpart & 0xFFFFFFFF;
569
570 if ((K % 10) >= 5)
571 K += 5;
572
573 /* Move down to proper range now rounding is done */
574 fll_div->k = K / 10;
575
576 pr_debug("N=%x K=%x FLL_FRATIO=%x FLL_OUTDIV=%x FLL_CLK_REF_DIV=%x\n",
577 fll_div->n, fll_div->k,
578 fll_div->fll_fratio, fll_div->fll_outdiv,
579 fll_div->fll_clk_ref_div);
580
581 return 0;
582}
583
584static int wm9081_set_fll(struct snd_soc_codec *codec, int fll_id,
585 unsigned int Fref, unsigned int Fout)
586{
587 struct wm9081_priv *wm9081 = codec->private_data;
588 u16 reg1, reg4, reg5;
589 struct _fll_div fll_div;
590 int ret;
591 int clk_sys_reg;
592
593 /* Any change? */
594 if (Fref == wm9081->fll_fref && Fout == wm9081->fll_fout)
595 return 0;
596
597 /* Disable the FLL */
598 if (Fout == 0) {
599 dev_dbg(codec->dev, "FLL disabled\n");
600 wm9081->fll_fref = 0;
601 wm9081->fll_fout = 0;
602
603 return 0;
604 }
605
606 ret = fll_factors(&fll_div, Fref, Fout);
607 if (ret != 0)
608 return ret;
609
610 reg5 = wm9081_read(codec, WM9081_FLL_CONTROL_5);
611 reg5 &= ~WM9081_FLL_CLK_SRC_MASK;
612
613 switch (fll_id) {
614 case WM9081_SYSCLK_FLL_MCLK:
615 reg5 |= 0x1;
616 break;
617
618 default:
619 dev_err(codec->dev, "Unknown FLL ID %d\n", fll_id);
620 return -EINVAL;
621 }
622
623 /* Disable CLK_SYS while we reconfigure */
624 clk_sys_reg = wm9081_read(codec, WM9081_CLOCK_CONTROL_3);
625 if (clk_sys_reg & WM9081_CLK_SYS_ENA)
626 wm9081_write(codec, WM9081_CLOCK_CONTROL_3,
627 clk_sys_reg & ~WM9081_CLK_SYS_ENA);
628
629 /* Any FLL configuration change requires that the FLL be
630 * disabled first. */
631 reg1 = wm9081_read(codec, WM9081_FLL_CONTROL_1);
632 reg1 &= ~WM9081_FLL_ENA;
633 wm9081_write(codec, WM9081_FLL_CONTROL_1, reg1);
634
635 /* Apply the configuration */
636 if (fll_div.k)
637 reg1 |= WM9081_FLL_FRAC_MASK;
638 else
639 reg1 &= ~WM9081_FLL_FRAC_MASK;
640 wm9081_write(codec, WM9081_FLL_CONTROL_1, reg1);
641
642 wm9081_write(codec, WM9081_FLL_CONTROL_2,
643 (fll_div.fll_outdiv << WM9081_FLL_OUTDIV_SHIFT) |
644 (fll_div.fll_fratio << WM9081_FLL_FRATIO_SHIFT));
645 wm9081_write(codec, WM9081_FLL_CONTROL_3, fll_div.k);
646
647 reg4 = wm9081_read(codec, WM9081_FLL_CONTROL_4);
648 reg4 &= ~WM9081_FLL_N_MASK;
649 reg4 |= fll_div.n << WM9081_FLL_N_SHIFT;
650 wm9081_write(codec, WM9081_FLL_CONTROL_4, reg4);
651
652 reg5 &= ~WM9081_FLL_CLK_REF_DIV_MASK;
653 reg5 |= fll_div.fll_clk_ref_div << WM9081_FLL_CLK_REF_DIV_SHIFT;
654 wm9081_write(codec, WM9081_FLL_CONTROL_5, reg5);
655
656 /* Enable the FLL */
657 wm9081_write(codec, WM9081_FLL_CONTROL_1, reg1 | WM9081_FLL_ENA);
658
659 /* Then bring CLK_SYS up again if it was disabled */
660 if (clk_sys_reg & WM9081_CLK_SYS_ENA)
661 wm9081_write(codec, WM9081_CLOCK_CONTROL_3, clk_sys_reg);
662
663 dev_dbg(codec->dev, "FLL enabled at %dHz->%dHz\n", Fref, Fout);
664
665 wm9081->fll_fref = Fref;
666 wm9081->fll_fout = Fout;
667
668 return 0;
669}
670
671static int configure_clock(struct snd_soc_codec *codec)
672{
673 struct wm9081_priv *wm9081 = codec->private_data;
674 int new_sysclk, i, target;
675 unsigned int reg;
676 int ret = 0;
677 int mclkdiv = 0;
678 int fll = 0;
679
680 switch (wm9081->sysclk_source) {
681 case WM9081_SYSCLK_MCLK:
682 if (wm9081->mclk_rate > 12225000) {
683 mclkdiv = 1;
684 wm9081->sysclk_rate = wm9081->mclk_rate / 2;
685 } else {
686 wm9081->sysclk_rate = wm9081->mclk_rate;
687 }
688 wm9081_set_fll(codec, WM9081_SYSCLK_FLL_MCLK, 0, 0);
689 break;
690
691 case WM9081_SYSCLK_FLL_MCLK:
692 /* If we have a sample rate calculate a CLK_SYS that
693 * gives us a suitable DAC configuration, plus BCLK.
694 * Ideally we would check to see if we can clock
695 * directly from MCLK and only use the FLL if this is
696 * not the case, though care must be taken with free
697 * running mode.
698 */
699 if (wm9081->master && wm9081->bclk) {
700 /* Make sure we can generate CLK_SYS and BCLK
701 * and that we've got 3MHz for optimal
702 * performance. */
703 for (i = 0; i < ARRAY_SIZE(clk_sys_rates); i++) {
704 target = wm9081->fs * clk_sys_rates[i].ratio;
705 new_sysclk = target;
706 if (target >= wm9081->bclk &&
707 target > 3000000)
708 break;
709 }
710 } else if (wm9081->fs) {
711 for (i = 0; i < ARRAY_SIZE(clk_sys_rates); i++) {
712 new_sysclk = clk_sys_rates[i].ratio
713 * wm9081->fs;
714 if (new_sysclk > 3000000)
715 break;
716 }
717 } else {
718 new_sysclk = 12288000;
719 }
720
721 ret = wm9081_set_fll(codec, WM9081_SYSCLK_FLL_MCLK,
722 wm9081->mclk_rate, new_sysclk);
723 if (ret == 0) {
724 wm9081->sysclk_rate = new_sysclk;
725
726 /* Switch SYSCLK over to FLL */
727 fll = 1;
728 } else {
729 wm9081->sysclk_rate = wm9081->mclk_rate;
730 }
731 break;
732
733 default:
734 return -EINVAL;
735 }
736
737 reg = wm9081_read(codec, WM9081_CLOCK_CONTROL_1);
738 if (mclkdiv)
739 reg |= WM9081_MCLKDIV2;
740 else
741 reg &= ~WM9081_MCLKDIV2;
742 wm9081_write(codec, WM9081_CLOCK_CONTROL_1, reg);
743
744 reg = wm9081_read(codec, WM9081_CLOCK_CONTROL_3);
745 if (fll)
746 reg |= WM9081_CLK_SRC_SEL;
747 else
748 reg &= ~WM9081_CLK_SRC_SEL;
749 wm9081_write(codec, WM9081_CLOCK_CONTROL_3, reg);
750
751 dev_dbg(codec->dev, "CLK_SYS is %dHz\n", wm9081->sysclk_rate);
752
753 return ret;
754}
755
756static int clk_sys_event(struct snd_soc_dapm_widget *w,
757 struct snd_kcontrol *kcontrol, int event)
758{
759 struct snd_soc_codec *codec = w->codec;
760 struct wm9081_priv *wm9081 = codec->private_data;
761
762 /* This should be done on init() for bypass paths */
763 switch (wm9081->sysclk_source) {
764 case WM9081_SYSCLK_MCLK:
765 dev_dbg(codec->dev, "Using %dHz MCLK\n", wm9081->mclk_rate);
766 break;
767 case WM9081_SYSCLK_FLL_MCLK:
768 dev_dbg(codec->dev, "Using %dHz MCLK with FLL\n",
769 wm9081->mclk_rate);
770 break;
771 default:
772 dev_err(codec->dev, "System clock not configured\n");
773 return -EINVAL;
774 }
775
776 switch (event) {
777 case SND_SOC_DAPM_PRE_PMU:
778 configure_clock(codec);
779 break;
780
781 case SND_SOC_DAPM_POST_PMD:
782 /* Disable the FLL if it's running */
783 wm9081_set_fll(codec, 0, 0, 0);
784 break;
785 }
786
787 return 0;
788}
789
790static const struct snd_soc_dapm_widget wm9081_dapm_widgets[] = {
791SND_SOC_DAPM_INPUT("IN1"),
792SND_SOC_DAPM_INPUT("IN2"),
793
794SND_SOC_DAPM_DAC("DAC", "HiFi Playback", WM9081_POWER_MANAGEMENT, 0, 0),
795
796SND_SOC_DAPM_MIXER_NAMED_CTL("Mixer", SND_SOC_NOPM, 0, 0,
797 mixer, ARRAY_SIZE(mixer)),
798
799SND_SOC_DAPM_PGA("LINEOUT PGA", WM9081_POWER_MANAGEMENT, 4, 0, NULL, 0),
800
801SND_SOC_DAPM_PGA_E("Speaker PGA", WM9081_POWER_MANAGEMENT, 2, 0, NULL, 0,
802 speaker_event,
803 SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD),
804
805SND_SOC_DAPM_OUTPUT("LINEOUT"),
806SND_SOC_DAPM_OUTPUT("SPKN"),
807SND_SOC_DAPM_OUTPUT("SPKP"),
808
809SND_SOC_DAPM_SUPPLY("CLK_SYS", WM9081_CLOCK_CONTROL_3, 0, 0, clk_sys_event,
810 SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
811SND_SOC_DAPM_SUPPLY("CLK_DSP", WM9081_CLOCK_CONTROL_3, 1, 0, NULL, 0),
812SND_SOC_DAPM_SUPPLY("TOCLK", WM9081_CLOCK_CONTROL_3, 2, 0, NULL, 0),
813};
814
815
816static const struct snd_soc_dapm_route audio_paths[] = {
817 { "DAC", NULL, "CLK_SYS" },
818 { "DAC", NULL, "CLK_DSP" },
819
820 { "Mixer", "IN1 Switch", "IN1" },
821 { "Mixer", "IN2 Switch", "IN2" },
822 { "Mixer", "Playback Switch", "DAC" },
823
824 { "LINEOUT PGA", NULL, "Mixer" },
825 { "LINEOUT PGA", NULL, "TOCLK" },
826 { "LINEOUT PGA", NULL, "CLK_SYS" },
827
828 { "LINEOUT", NULL, "LINEOUT PGA" },
829
830 { "Speaker PGA", NULL, "Mixer" },
831 { "Speaker PGA", NULL, "TOCLK" },
832 { "Speaker PGA", NULL, "CLK_SYS" },
833
834 { "SPKN", NULL, "Speaker PGA" },
835 { "SPKP", NULL, "Speaker PGA" },
836};
837
838static int wm9081_set_bias_level(struct snd_soc_codec *codec,
839 enum snd_soc_bias_level level)
840{
841 u16 reg;
842
843 switch (level) {
844 case SND_SOC_BIAS_ON:
845 break;
846
847 case SND_SOC_BIAS_PREPARE:
848 /* VMID=2*40k */
849 reg = wm9081_read(codec, WM9081_VMID_CONTROL);
850 reg &= ~WM9081_VMID_SEL_MASK;
851 reg |= 0x2;
852 wm9081_write(codec, WM9081_VMID_CONTROL, reg);
853
854 /* Normal bias current */
855 reg = wm9081_read(codec, WM9081_BIAS_CONTROL_1);
856 reg &= ~WM9081_STBY_BIAS_ENA;
857 wm9081_write(codec, WM9081_BIAS_CONTROL_1, reg);
858 break;
859
860 case SND_SOC_BIAS_STANDBY:
861 /* Initial cold start */
862 if (codec->bias_level == SND_SOC_BIAS_OFF) {
863 /* Disable LINEOUT discharge */
864 reg = wm9081_read(codec, WM9081_ANTI_POP_CONTROL);
865 reg &= ~WM9081_LINEOUT_DISCH;
866 wm9081_write(codec, WM9081_ANTI_POP_CONTROL, reg);
867
868 /* Select startup bias source */
869 reg = wm9081_read(codec, WM9081_BIAS_CONTROL_1);
870 reg |= WM9081_BIAS_SRC | WM9081_BIAS_ENA;
871 wm9081_write(codec, WM9081_BIAS_CONTROL_1, reg);
872
873 /* VMID 2*4k; Soft VMID ramp enable */
874 reg = wm9081_read(codec, WM9081_VMID_CONTROL);
875 reg |= WM9081_VMID_RAMP | 0x6;
876 wm9081_write(codec, WM9081_VMID_CONTROL, reg);
877
878 mdelay(100);
879
880 /* Normal bias enable & soft start off */
881 reg |= WM9081_BIAS_ENA;
882 reg &= ~WM9081_VMID_RAMP;
883 wm9081_write(codec, WM9081_VMID_CONTROL, reg);
884
885 /* Standard bias source */
886 reg = wm9081_read(codec, WM9081_BIAS_CONTROL_1);
887 reg &= ~WM9081_BIAS_SRC;
888 wm9081_write(codec, WM9081_BIAS_CONTROL_1, reg);
889 }
890
891 /* VMID 2*240k */
892 reg = wm9081_read(codec, WM9081_BIAS_CONTROL_1);
893 reg &= ~WM9081_VMID_SEL_MASK;
894 reg |= 0x40;
895 wm9081_write(codec, WM9081_VMID_CONTROL, reg);
896
897 /* Standby bias current on */
898 reg = wm9081_read(codec, WM9081_BIAS_CONTROL_1);
899 reg |= WM9081_STBY_BIAS_ENA;
900 wm9081_write(codec, WM9081_BIAS_CONTROL_1, reg);
901 break;
902
903 case SND_SOC_BIAS_OFF:
904 /* Startup bias source */
905 reg = wm9081_read(codec, WM9081_BIAS_CONTROL_1);
906 reg |= WM9081_BIAS_SRC;
907 wm9081_write(codec, WM9081_BIAS_CONTROL_1, reg);
908
909 /* Disable VMID and biases with soft ramping */
910 reg = wm9081_read(codec, WM9081_VMID_CONTROL);
911 reg &= ~(WM9081_VMID_SEL_MASK | WM9081_BIAS_ENA);
912 reg |= WM9081_VMID_RAMP;
913 wm9081_write(codec, WM9081_VMID_CONTROL, reg);
914
915 /* Actively discharge LINEOUT */
916 reg = wm9081_read(codec, WM9081_ANTI_POP_CONTROL);
917 reg |= WM9081_LINEOUT_DISCH;
918 wm9081_write(codec, WM9081_ANTI_POP_CONTROL, reg);
919 break;
920 }
921
922 codec->bias_level = level;
923
924 return 0;
925}
926
927static int wm9081_set_dai_fmt(struct snd_soc_dai *dai,
928 unsigned int fmt)
929{
930 struct snd_soc_codec *codec = dai->codec;
931 struct wm9081_priv *wm9081 = codec->private_data;
932 unsigned int aif2 = wm9081_read(codec, WM9081_AUDIO_INTERFACE_2);
933
934 aif2 &= ~(WM9081_AIF_BCLK_INV | WM9081_AIF_LRCLK_INV |
935 WM9081_BCLK_DIR | WM9081_LRCLK_DIR | WM9081_AIF_FMT_MASK);
936
937 switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
938 case SND_SOC_DAIFMT_CBS_CFS:
939 wm9081->master = 0;
940 break;
941 case SND_SOC_DAIFMT_CBS_CFM:
942 aif2 |= WM9081_LRCLK_DIR;
943 wm9081->master = 1;
944 break;
945 case SND_SOC_DAIFMT_CBM_CFS:
946 aif2 |= WM9081_BCLK_DIR;
947 wm9081->master = 1;
948 break;
949 case SND_SOC_DAIFMT_CBM_CFM:
950 aif2 |= WM9081_LRCLK_DIR | WM9081_BCLK_DIR;
951 wm9081->master = 1;
952 break;
953 default:
954 return -EINVAL;
955 }
956
957 switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
958 case SND_SOC_DAIFMT_DSP_B:
959 aif2 |= WM9081_AIF_LRCLK_INV;
960 case SND_SOC_DAIFMT_DSP_A:
961 aif2 |= 0x3;
962 break;
963 case SND_SOC_DAIFMT_I2S:
964 aif2 |= 0x2;
965 break;
966 case SND_SOC_DAIFMT_RIGHT_J:
967 break;
968 case SND_SOC_DAIFMT_LEFT_J:
969 aif2 |= 0x1;
970 break;
971 default:
972 return -EINVAL;
973 }
974
975 switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
976 case SND_SOC_DAIFMT_DSP_A:
977 case SND_SOC_DAIFMT_DSP_B:
978 /* frame inversion not valid for DSP modes */
979 switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
980 case SND_SOC_DAIFMT_NB_NF:
981 break;
982 case SND_SOC_DAIFMT_IB_NF:
983 aif2 |= WM9081_AIF_BCLK_INV;
984 break;
985 default:
986 return -EINVAL;
987 }
988 break;
989
990 case SND_SOC_DAIFMT_I2S:
991 case SND_SOC_DAIFMT_RIGHT_J:
992 case SND_SOC_DAIFMT_LEFT_J:
993 switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
994 case SND_SOC_DAIFMT_NB_NF:
995 break;
996 case SND_SOC_DAIFMT_IB_IF:
997 aif2 |= WM9081_AIF_BCLK_INV | WM9081_AIF_LRCLK_INV;
998 break;
999 case SND_SOC_DAIFMT_IB_NF:
1000 aif2 |= WM9081_AIF_BCLK_INV;
1001 break;
1002 case SND_SOC_DAIFMT_NB_IF:
1003 aif2 |= WM9081_AIF_LRCLK_INV;
1004 break;
1005 default:
1006 return -EINVAL;
1007 }
1008 break;
1009 default:
1010 return -EINVAL;
1011 }
1012
1013 wm9081_write(codec, WM9081_AUDIO_INTERFACE_2, aif2);
1014
1015 return 0;
1016}
1017
1018static int wm9081_hw_params(struct snd_pcm_substream *substream,
1019 struct snd_pcm_hw_params *params,
1020 struct snd_soc_dai *dai)
1021{
1022 struct snd_soc_codec *codec = dai->codec;
1023 struct wm9081_priv *wm9081 = codec->private_data;
1024 int ret, i, best, best_val, cur_val;
1025 unsigned int clk_ctrl2, aif1, aif2, aif3, aif4;
1026
1027 clk_ctrl2 = wm9081_read(codec, WM9081_CLOCK_CONTROL_2);
1028 clk_ctrl2 &= ~(WM9081_CLK_SYS_RATE_MASK | WM9081_SAMPLE_RATE_MASK);
1029
1030 aif1 = wm9081_read(codec, WM9081_AUDIO_INTERFACE_1);
1031
1032 aif2 = wm9081_read(codec, WM9081_AUDIO_INTERFACE_2);
1033 aif2 &= ~WM9081_AIF_WL_MASK;
1034
1035 aif3 = wm9081_read(codec, WM9081_AUDIO_INTERFACE_3);
1036 aif3 &= ~WM9081_BCLK_DIV_MASK;
1037
1038 aif4 = wm9081_read(codec, WM9081_AUDIO_INTERFACE_4);
1039 aif4 &= ~WM9081_LRCLK_RATE_MASK;
1040
1041 /* What BCLK do we need? */
1042 wm9081->fs = params_rate(params);
1043 wm9081->bclk = 2 * wm9081->fs;
1044 switch (params_format(params)) {
1045 case SNDRV_PCM_FORMAT_S16_LE:
1046 wm9081->bclk *= 16;
1047 break;
1048 case SNDRV_PCM_FORMAT_S20_3LE:
1049 wm9081->bclk *= 20;
1050 aif2 |= 0x4;
1051 break;
1052 case SNDRV_PCM_FORMAT_S24_LE:
1053 wm9081->bclk *= 24;
1054 aif2 |= 0x8;
1055 break;
1056 case SNDRV_PCM_FORMAT_S32_LE:
1057 wm9081->bclk *= 32;
1058 aif2 |= 0xc;
1059 break;
1060 default:
1061 return -EINVAL;
1062 }
1063
1064 if (aif1 & WM9081_AIFDAC_TDM_MODE_MASK) {
1065 int slots = ((aif1 & WM9081_AIFDAC_TDM_MODE_MASK) >>
1066 WM9081_AIFDAC_TDM_MODE_SHIFT) + 1;
1067 wm9081->bclk *= slots;
1068 }
1069
1070 dev_dbg(codec->dev, "Target BCLK is %dHz\n", wm9081->bclk);
1071
1072 ret = configure_clock(codec);
1073 if (ret != 0)
1074 return ret;
1075
1076 /* Select nearest CLK_SYS_RATE */
1077 best = 0;
1078 best_val = abs((wm9081->sysclk_rate / clk_sys_rates[0].ratio)
1079 - wm9081->fs);
1080 for (i = 1; i < ARRAY_SIZE(clk_sys_rates); i++) {
1081 cur_val = abs((wm9081->sysclk_rate /
1082 clk_sys_rates[i].ratio) - wm9081->fs);;
1083 if (cur_val < best_val) {
1084 best = i;
1085 best_val = cur_val;
1086 }
1087 }
1088 dev_dbg(codec->dev, "Selected CLK_SYS_RATIO of %d\n",
1089 clk_sys_rates[best].ratio);
1090 clk_ctrl2 |= (clk_sys_rates[best].clk_sys_rate
1091 << WM9081_CLK_SYS_RATE_SHIFT);
1092
1093 /* SAMPLE_RATE */
1094 best = 0;
1095 best_val = abs(wm9081->fs - sample_rates[0].rate);
1096 for (i = 1; i < ARRAY_SIZE(sample_rates); i++) {
1097 /* Closest match */
1098 cur_val = abs(wm9081->fs - sample_rates[i].rate);
1099 if (cur_val < best_val) {
1100 best = i;
1101 best_val = cur_val;
1102 }
1103 }
1104 dev_dbg(codec->dev, "Selected SAMPLE_RATE of %dHz\n",
1105 sample_rates[best].rate);
1106 clk_ctrl2 |= (sample_rates[best].sample_rate
1107 << WM9081_SAMPLE_RATE_SHIFT);
1108
1109 /* BCLK_DIV */
1110 best = 0;
1111 best_val = INT_MAX;
1112 for (i = 0; i < ARRAY_SIZE(bclk_divs); i++) {
1113 cur_val = ((wm9081->sysclk_rate * 10) / bclk_divs[i].div)
1114 - wm9081->bclk;
1115 if (cur_val < 0) /* Table is sorted */
1116 break;
1117 if (cur_val < best_val) {
1118 best = i;
1119 best_val = cur_val;
1120 }
1121 }
1122 wm9081->bclk = (wm9081->sysclk_rate * 10) / bclk_divs[best].div;
1123 dev_dbg(codec->dev, "Selected BCLK_DIV of %d for %dHz BCLK\n",
1124 bclk_divs[best].div, wm9081->bclk);
1125 aif3 |= bclk_divs[best].bclk_div;
1126
1127 /* LRCLK is a simple fraction of BCLK */
1128 dev_dbg(codec->dev, "LRCLK_RATE is %d\n", wm9081->bclk / wm9081->fs);
1129 aif4 |= wm9081->bclk / wm9081->fs;
1130
1131 /* Apply a ReTune Mobile configuration if it's in use */
1132 if (wm9081->retune) {
1133 struct wm9081_retune_mobile_config *retune = wm9081->retune;
1134 struct wm9081_retune_mobile_setting *s;
1135 int eq1;
1136
1137 best = 0;
1138 best_val = abs(retune->configs[0].rate - wm9081->fs);
1139 for (i = 0; i < retune->num_configs; i++) {
1140 cur_val = abs(retune->configs[i].rate - wm9081->fs);
1141 if (cur_val < best_val) {
1142 best_val = cur_val;
1143 best = i;
1144 }
1145 }
1146 s = &retune->configs[best];
1147
1148 dev_dbg(codec->dev, "ReTune Mobile %s tuned for %dHz\n",
1149 s->name, s->rate);
1150
1151 /* If the EQ is enabled then disable it while we write out */
1152 eq1 = wm9081_read(codec, WM9081_EQ_1) & WM9081_EQ_ENA;
1153 if (eq1 & WM9081_EQ_ENA)
1154 wm9081_write(codec, WM9081_EQ_1, 0);
1155
1156 /* Write out the other values */
1157 for (i = 1; i < ARRAY_SIZE(s->config); i++)
1158 wm9081_write(codec, WM9081_EQ_1 + i, s->config[i]);
1159
1160 eq1 |= (s->config[0] & ~WM9081_EQ_ENA);
1161 wm9081_write(codec, WM9081_EQ_1, eq1);
1162 }
1163
1164 wm9081_write(codec, WM9081_CLOCK_CONTROL_2, clk_ctrl2);
1165 wm9081_write(codec, WM9081_AUDIO_INTERFACE_2, aif2);
1166 wm9081_write(codec, WM9081_AUDIO_INTERFACE_3, aif3);
1167 wm9081_write(codec, WM9081_AUDIO_INTERFACE_4, aif4);
1168
1169 return 0;
1170}
1171
1172static int wm9081_digital_mute(struct snd_soc_dai *codec_dai, int mute)
1173{
1174 struct snd_soc_codec *codec = codec_dai->codec;
1175 unsigned int reg;
1176
1177 reg = wm9081_read(codec, WM9081_DAC_DIGITAL_2);
1178
1179 if (mute)
1180 reg |= WM9081_DAC_MUTE;
1181 else
1182 reg &= ~WM9081_DAC_MUTE;
1183
1184 wm9081_write(codec, WM9081_DAC_DIGITAL_2, reg);
1185
1186 return 0;
1187}
1188
1189static int wm9081_set_sysclk(struct snd_soc_dai *codec_dai,
1190 int clk_id, unsigned int freq, int dir)
1191{
1192 struct snd_soc_codec *codec = codec_dai->codec;
1193 struct wm9081_priv *wm9081 = codec->private_data;
1194
1195 switch (clk_id) {
1196 case WM9081_SYSCLK_MCLK:
1197 case WM9081_SYSCLK_FLL_MCLK:
1198 wm9081->sysclk_source = clk_id;
1199 wm9081->mclk_rate = freq;
1200 break;
1201
1202 default:
1203 return -EINVAL;
1204 }
1205
1206 return 0;
1207}
1208
1209static int wm9081_set_tdm_slot(struct snd_soc_dai *dai,
1210 unsigned int mask, int slots)
1211{
1212 struct snd_soc_codec *codec = dai->codec;
1213 unsigned int aif1 = wm9081_read(codec, WM9081_AUDIO_INTERFACE_1);
1214
1215 aif1 &= ~(WM9081_AIFDAC_TDM_SLOT_MASK | WM9081_AIFDAC_TDM_MODE_MASK);
1216
1217 if (slots < 1 || slots > 4)
1218 return -EINVAL;
1219
1220 aif1 |= (slots - 1) << WM9081_AIFDAC_TDM_MODE_SHIFT;
1221
1222 switch (mask) {
1223 case 1:
1224 break;
1225 case 2:
1226 aif1 |= 0x10;
1227 break;
1228 case 4:
1229 aif1 |= 0x20;
1230 break;
1231 case 8:
1232 aif1 |= 0x30;
1233 break;
1234 default:
1235 return -EINVAL;
1236 }
1237
1238 wm9081_write(codec, WM9081_AUDIO_INTERFACE_1, aif1);
1239
1240 return 0;
1241}
1242
1243#define WM9081_RATES SNDRV_PCM_RATE_8000_96000
1244
1245#define WM9081_FORMATS \
1246 (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE | \
1247 SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S32_LE)
1248
1249static struct snd_soc_dai_ops wm9081_dai_ops = {
1250 .hw_params = wm9081_hw_params,
1251 .set_sysclk = wm9081_set_sysclk,
1252 .set_fmt = wm9081_set_dai_fmt,
1253 .digital_mute = wm9081_digital_mute,
1254 .set_tdm_slot = wm9081_set_tdm_slot,
1255};
1256
1257/* We report two channels because the CODEC processes a stereo signal, even
1258 * though it is only capable of handling a mono output.
1259 */
1260struct snd_soc_dai wm9081_dai = {
1261 .name = "WM9081",
1262 .playback = {
1263 .stream_name = "HiFi Playback",
1264 .channels_min = 1,
1265 .channels_max = 2,
1266 .rates = WM9081_RATES,
1267 .formats = WM9081_FORMATS,
1268 },
1269 .ops = &wm9081_dai_ops,
1270};
1271EXPORT_SYMBOL_GPL(wm9081_dai);
1272
1273
1274static struct snd_soc_codec *wm9081_codec;
1275
1276static int wm9081_probe(struct platform_device *pdev)
1277{
1278 struct snd_soc_device *socdev = platform_get_drvdata(pdev);
1279 struct snd_soc_codec *codec;
1280 struct wm9081_priv *wm9081;
1281 int ret = 0;
1282
1283 if (wm9081_codec == NULL) {
1284 dev_err(&pdev->dev, "Codec device not registered\n");
1285 return -ENODEV;
1286 }
1287
1288 socdev->card->codec = wm9081_codec;
1289 codec = wm9081_codec;
1290 wm9081 = codec->private_data;
1291
1292 /* register pcms */
1293 ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1);
1294 if (ret < 0) {
1295 dev_err(codec->dev, "failed to create pcms: %d\n", ret);
1296 goto pcm_err;
1297 }
1298
1299 snd_soc_add_controls(codec, wm9081_snd_controls,
1300 ARRAY_SIZE(wm9081_snd_controls));
1301 if (!wm9081->retune) {
1302 dev_dbg(codec->dev,
1303 "No ReTune Mobile data, using normal EQ\n");
1304 snd_soc_add_controls(codec, wm9081_eq_controls,
1305 ARRAY_SIZE(wm9081_eq_controls));
1306 }
1307
1308 snd_soc_dapm_new_controls(codec, wm9081_dapm_widgets,
1309 ARRAY_SIZE(wm9081_dapm_widgets));
1310 snd_soc_dapm_add_routes(codec, audio_paths, ARRAY_SIZE(audio_paths));
1311 snd_soc_dapm_new_widgets(codec);
1312
1313 ret = snd_soc_init_card(socdev);
1314 if (ret < 0) {
1315 dev_err(codec->dev, "failed to register card: %d\n", ret);
1316 goto card_err;
1317 }
1318
1319 return ret;
1320
1321card_err:
1322 snd_soc_free_pcms(socdev);
1323 snd_soc_dapm_free(socdev);
1324pcm_err:
1325 return ret;
1326}
1327
1328static int wm9081_remove(struct platform_device *pdev)
1329{
1330 struct snd_soc_device *socdev = platform_get_drvdata(pdev);
1331
1332 snd_soc_free_pcms(socdev);
1333 snd_soc_dapm_free(socdev);
1334
1335 return 0;
1336}
1337
1338#ifdef CONFIG_PM
1339static int wm9081_suspend(struct platform_device *pdev, pm_message_t state)
1340{
1341 struct snd_soc_device *socdev = platform_get_drvdata(pdev);
1342 struct snd_soc_codec *codec = socdev->card->codec;
1343
1344 wm9081_set_bias_level(codec, SND_SOC_BIAS_OFF);
1345
1346 return 0;
1347}
1348
1349static int wm9081_resume(struct platform_device *pdev)
1350{
1351 struct snd_soc_device *socdev = platform_get_drvdata(pdev);
1352 struct snd_soc_codec *codec = socdev->card->codec;
1353 u16 *reg_cache = codec->reg_cache;
1354 int i;
1355
1356 for (i = 0; i < codec->reg_cache_size; i++) {
1357 if (i == WM9081_SOFTWARE_RESET)
1358 continue;
1359
1360 wm9081_write(codec, i, reg_cache[i]);
1361 }
1362
1363 wm9081_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
1364
1365 return 0;
1366}
1367#else
1368#define wm9081_suspend NULL
1369#define wm9081_resume NULL
1370#endif
1371
1372struct snd_soc_codec_device soc_codec_dev_wm9081 = {
1373 .probe = wm9081_probe,
1374 .remove = wm9081_remove,
1375 .suspend = wm9081_suspend,
1376 .resume = wm9081_resume,
1377};
1378EXPORT_SYMBOL_GPL(soc_codec_dev_wm9081);
1379
1380static int wm9081_register(struct wm9081_priv *wm9081)
1381{
1382 struct snd_soc_codec *codec = &wm9081->codec;
1383 int ret;
1384 u16 reg;
1385
1386 if (wm9081_codec) {
1387 dev_err(codec->dev, "Another WM9081 is registered\n");
1388 ret = -EINVAL;
1389 goto err;
1390 }
1391
1392 mutex_init(&codec->mutex);
1393 INIT_LIST_HEAD(&codec->dapm_widgets);
1394 INIT_LIST_HEAD(&codec->dapm_paths);
1395
1396 codec->private_data = wm9081;
1397 codec->name = "WM9081";
1398 codec->owner = THIS_MODULE;
1399 codec->read = wm9081_read;
1400 codec->write = wm9081_write;
1401 codec->dai = &wm9081_dai;
1402 codec->num_dai = 1;
1403 codec->reg_cache_size = ARRAY_SIZE(wm9081->reg_cache);
1404 codec->reg_cache = &wm9081->reg_cache;
1405 codec->bias_level = SND_SOC_BIAS_OFF;
1406 codec->set_bias_level = wm9081_set_bias_level;
1407
1408 memcpy(codec->reg_cache, wm9081_reg_defaults,
1409 sizeof(wm9081_reg_defaults));
1410
1411 reg = wm9081_read_hw(codec, WM9081_SOFTWARE_RESET);
1412 if (reg != 0x9081) {
1413 dev_err(codec->dev, "Device is not a WM9081: ID=0x%x\n", reg);
1414 ret = -EINVAL;
1415 goto err;
1416 }
1417
1418 ret = wm9081_reset(codec);
1419 if (ret < 0) {
1420 dev_err(codec->dev, "Failed to issue reset\n");
1421 return ret;
1422 }
1423
1424 wm9081_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
1425
1426 /* Enable zero cross by default */
1427 reg = wm9081_read(codec, WM9081_ANALOGUE_LINEOUT);
1428 wm9081_write(codec, WM9081_ANALOGUE_LINEOUT, reg | WM9081_LINEOUTZC);
1429 reg = wm9081_read(codec, WM9081_ANALOGUE_SPEAKER_PGA);
1430 wm9081_write(codec, WM9081_ANALOGUE_SPEAKER_PGA,
1431 reg | WM9081_SPKPGAZC);
1432
1433 wm9081_dai.dev = codec->dev;
1434
1435 wm9081_codec = codec;
1436
1437 ret = snd_soc_register_codec(codec);
1438 if (ret != 0) {
1439 dev_err(codec->dev, "Failed to register codec: %d\n", ret);
1440 return ret;
1441 }
1442
1443 ret = snd_soc_register_dai(&wm9081_dai);
1444 if (ret != 0) {
1445 dev_err(codec->dev, "Failed to register DAI: %d\n", ret);
1446 snd_soc_unregister_codec(codec);
1447 return ret;
1448 }
1449
1450 return 0;
1451
1452err:
1453 kfree(wm9081);
1454 return ret;
1455}
1456
1457static void wm9081_unregister(struct wm9081_priv *wm9081)
1458{
1459 wm9081_set_bias_level(&wm9081->codec, SND_SOC_BIAS_OFF);
1460 snd_soc_unregister_dai(&wm9081_dai);
1461 snd_soc_unregister_codec(&wm9081->codec);
1462 kfree(wm9081);
1463 wm9081_codec = NULL;
1464}
1465
1466static __devinit int wm9081_i2c_probe(struct i2c_client *i2c,
1467 const struct i2c_device_id *id)
1468{
1469 struct wm9081_priv *wm9081;
1470 struct snd_soc_codec *codec;
1471
1472 wm9081 = kzalloc(sizeof(struct wm9081_priv), GFP_KERNEL);
1473 if (wm9081 == NULL)
1474 return -ENOMEM;
1475
1476 codec = &wm9081->codec;
1477 codec->hw_write = (hw_write_t)i2c_master_send;
1478 wm9081->retune = i2c->dev.platform_data;
1479
1480 i2c_set_clientdata(i2c, wm9081);
1481 codec->control_data = i2c;
1482
1483 codec->dev = &i2c->dev;
1484
1485 return wm9081_register(wm9081);
1486}
1487
1488static __devexit int wm9081_i2c_remove(struct i2c_client *client)
1489{
1490 struct wm9081_priv *wm9081 = i2c_get_clientdata(client);
1491 wm9081_unregister(wm9081);
1492 return 0;
1493}
1494
1495static const struct i2c_device_id wm9081_i2c_id[] = {
1496 { "wm9081", 0 },
1497 { }
1498};
1499MODULE_DEVICE_TABLE(i2c, wm9081_i2c_id);
1500
1501static struct i2c_driver wm9081_i2c_driver = {
1502 .driver = {
1503 .name = "wm9081",
1504 .owner = THIS_MODULE,
1505 },
1506 .probe = wm9081_i2c_probe,
1507 .remove = __devexit_p(wm9081_i2c_remove),
1508 .id_table = wm9081_i2c_id,
1509};
1510
1511static int __init wm9081_modinit(void)
1512{
1513 int ret;
1514
1515 ret = i2c_add_driver(&wm9081_i2c_driver);
1516 if (ret != 0) {
1517 printk(KERN_ERR "Failed to register WM9081 I2C driver: %d\n",
1518 ret);
1519 }
1520
1521 return ret;
1522}
1523module_init(wm9081_modinit);
1524
1525static void __exit wm9081_exit(void)
1526{
1527 i2c_del_driver(&wm9081_i2c_driver);
1528}
1529module_exit(wm9081_exit);
1530
1531
1532MODULE_DESCRIPTION("ASoC WM9081 driver");
1533MODULE_AUTHOR("Mark Brown <broonie@opensource.wolfsonmicro.com>");
1534MODULE_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/fsl/Kconfig b/sound/soc/fsl/Kconfig
index 9fc908283371..5dbebf82249c 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 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 && BROKEN
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 && BROKEN
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..efec33a1c5bd
--- /dev/null
+++ b/sound/soc/fsl/mpc5200_dma.c
@@ -0,0 +1,564 @@
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 while (s->appl_ptr < s->runtime->control->appl_ptr) {
73
74 if (bcom_queue_full(s->bcom_task))
75 return;
76
77 s->appl_ptr += s->period_size;
78
79 psc_dma_bcom_enqueue_next_buffer(s);
80 }
81}
82
83/* Bestcomm DMA irq handler */
84static irqreturn_t psc_dma_bcom_irq_tx(int irq, void *_psc_dma_stream)
85{
86 struct psc_dma_stream *s = _psc_dma_stream;
87
88 spin_lock(&s->psc_dma->lock);
89 /* For each finished period, dequeue the completed period buffer
90 * and enqueue a new one in it's place. */
91 while (bcom_buffer_done(s->bcom_task)) {
92 bcom_retrieve_buffer(s->bcom_task, NULL, NULL);
93
94 s->period_current_pt += s->period_bytes;
95 if (s->period_current_pt >= s->period_end)
96 s->period_current_pt = s->period_start;
97 }
98 psc_dma_bcom_enqueue_tx(s);
99 spin_unlock(&s->psc_dma->lock);
100
101 /* If the stream is active, then also inform the PCM middle layer
102 * of the period finished event. */
103 if (s->active)
104 snd_pcm_period_elapsed(s->stream);
105
106 return IRQ_HANDLED;
107}
108
109static irqreturn_t psc_dma_bcom_irq_rx(int irq, void *_psc_dma_stream)
110{
111 struct psc_dma_stream *s = _psc_dma_stream;
112
113 spin_lock(&s->psc_dma->lock);
114 /* For each finished period, dequeue the completed period buffer
115 * and enqueue a new one in it's place. */
116 while (bcom_buffer_done(s->bcom_task)) {
117 bcom_retrieve_buffer(s->bcom_task, NULL, NULL);
118
119 s->period_current_pt += s->period_bytes;
120 if (s->period_current_pt >= s->period_end)
121 s->period_current_pt = s->period_start;
122
123 psc_dma_bcom_enqueue_next_buffer(s);
124 }
125 spin_unlock(&s->psc_dma->lock);
126
127 /* If the stream is active, then also inform the PCM middle layer
128 * of the period finished event. */
129 if (s->active)
130 snd_pcm_period_elapsed(s->stream);
131
132 return IRQ_HANDLED;
133}
134
135static int psc_dma_hw_free(struct snd_pcm_substream *substream)
136{
137 snd_pcm_set_runtime_buffer(substream, NULL);
138 return 0;
139}
140
141/**
142 * psc_dma_trigger: start and stop the DMA transfer.
143 *
144 * This function is called by ALSA to start, stop, pause, and resume the DMA
145 * transfer of data.
146 */
147static int psc_dma_trigger(struct snd_pcm_substream *substream, int cmd)
148{
149 struct snd_soc_pcm_runtime *rtd = substream->private_data;
150 struct psc_dma *psc_dma = rtd->dai->cpu_dai->private_data;
151 struct snd_pcm_runtime *runtime = substream->runtime;
152 struct psc_dma_stream *s;
153 struct mpc52xx_psc __iomem *regs = psc_dma->psc_regs;
154 u16 imr;
155 unsigned long flags;
156 int i;
157
158 if (substream->pstr->stream == SNDRV_PCM_STREAM_CAPTURE)
159 s = &psc_dma->capture;
160 else
161 s = &psc_dma->playback;
162
163 dev_dbg(psc_dma->dev, "psc_dma_trigger(substream=%p, cmd=%i)"
164 " stream_id=%i\n",
165 substream, cmd, substream->pstr->stream);
166
167 switch (cmd) {
168 case SNDRV_PCM_TRIGGER_START:
169 s->period_bytes = frames_to_bytes(runtime,
170 runtime->period_size);
171 s->period_start = virt_to_phys(runtime->dma_area);
172 s->period_end = s->period_start +
173 (s->period_bytes * runtime->periods);
174 s->period_next_pt = s->period_start;
175 s->period_current_pt = s->period_start;
176 s->period_size = runtime->period_size;
177 s->active = 1;
178
179 /* track appl_ptr so that we have a better chance of detecting
180 * end of stream and not over running it.
181 */
182 s->runtime = runtime;
183 s->appl_ptr = s->runtime->control->appl_ptr -
184 (runtime->period_size * runtime->periods);
185
186 /* Fill up the bestcomm bd queue and enable DMA.
187 * This will begin filling the PSC's fifo.
188 */
189 spin_lock_irqsave(&psc_dma->lock, flags);
190
191 if (substream->pstr->stream == SNDRV_PCM_STREAM_CAPTURE) {
192 bcom_gen_bd_rx_reset(s->bcom_task);
193 for (i = 0; i < runtime->periods; i++)
194 if (!bcom_queue_full(s->bcom_task))
195 psc_dma_bcom_enqueue_next_buffer(s);
196 } else {
197 bcom_gen_bd_tx_reset(s->bcom_task);
198 psc_dma_bcom_enqueue_tx(s);
199 }
200
201 bcom_enable(s->bcom_task);
202 spin_unlock_irqrestore(&psc_dma->lock, flags);
203
204 out_8(&regs->command, MPC52xx_PSC_RST_ERR_STAT);
205
206 break;
207
208 case SNDRV_PCM_TRIGGER_STOP:
209 s->active = 0;
210
211 spin_lock_irqsave(&psc_dma->lock, flags);
212 bcom_disable(s->bcom_task);
213 if (substream->pstr->stream == SNDRV_PCM_STREAM_CAPTURE)
214 bcom_gen_bd_rx_reset(s->bcom_task);
215 else
216 bcom_gen_bd_tx_reset(s->bcom_task);
217 spin_unlock_irqrestore(&psc_dma->lock, flags);
218
219 break;
220
221 default:
222 dev_dbg(psc_dma->dev, "invalid command\n");
223 return -EINVAL;
224 }
225
226 /* Update interrupt enable settings */
227 imr = 0;
228 if (psc_dma->playback.active)
229 imr |= MPC52xx_PSC_IMR_TXEMP;
230 if (psc_dma->capture.active)
231 imr |= MPC52xx_PSC_IMR_ORERR;
232 out_be16(&regs->isr_imr.imr, psc_dma->imr | imr);
233
234 return 0;
235}
236
237
238/* ---------------------------------------------------------------------
239 * The PSC DMA 'ASoC platform' driver
240 *
241 * Can be referenced by an 'ASoC machine' driver
242 * This driver only deals with the audio bus; it doesn't have any
243 * interaction with the attached codec
244 */
245
246static const struct snd_pcm_hardware psc_dma_hardware = {
247 .info = SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_MMAP_VALID |
248 SNDRV_PCM_INFO_INTERLEAVED | SNDRV_PCM_INFO_BLOCK_TRANSFER |
249 SNDRV_PCM_INFO_BATCH,
250 .formats = SNDRV_PCM_FMTBIT_S8 | SNDRV_PCM_FMTBIT_S16_BE |
251 SNDRV_PCM_FMTBIT_S24_BE | SNDRV_PCM_FMTBIT_S32_BE,
252 .rate_min = 8000,
253 .rate_max = 48000,
254 .channels_min = 1,
255 .channels_max = 2,
256 .period_bytes_max = 1024 * 1024,
257 .period_bytes_min = 32,
258 .periods_min = 2,
259 .periods_max = 256,
260 .buffer_bytes_max = 2 * 1024 * 1024,
261 .fifo_size = 512,
262};
263
264static int psc_dma_open(struct snd_pcm_substream *substream)
265{
266 struct snd_pcm_runtime *runtime = substream->runtime;
267 struct snd_soc_pcm_runtime *rtd = substream->private_data;
268 struct psc_dma *psc_dma = rtd->dai->cpu_dai->private_data;
269 struct psc_dma_stream *s;
270 int rc;
271
272 dev_dbg(psc_dma->dev, "psc_dma_open(substream=%p)\n", substream);
273
274 if (substream->pstr->stream == SNDRV_PCM_STREAM_CAPTURE)
275 s = &psc_dma->capture;
276 else
277 s = &psc_dma->playback;
278
279 snd_soc_set_runtime_hwparams(substream, &psc_dma_hardware);
280
281 rc = snd_pcm_hw_constraint_integer(runtime,
282 SNDRV_PCM_HW_PARAM_PERIODS);
283 if (rc < 0) {
284 dev_err(substream->pcm->card->dev, "invalid buffer size\n");
285 return rc;
286 }
287
288 s->stream = substream;
289 return 0;
290}
291
292static int psc_dma_close(struct snd_pcm_substream *substream)
293{
294 struct snd_soc_pcm_runtime *rtd = substream->private_data;
295 struct psc_dma *psc_dma = rtd->dai->cpu_dai->private_data;
296 struct psc_dma_stream *s;
297
298 dev_dbg(psc_dma->dev, "psc_dma_close(substream=%p)\n", substream);
299
300 if (substream->pstr->stream == SNDRV_PCM_STREAM_CAPTURE)
301 s = &psc_dma->capture;
302 else
303 s = &psc_dma->playback;
304
305 if (!psc_dma->playback.active &&
306 !psc_dma->capture.active) {
307
308 /* Disable all interrupts and reset the PSC */
309 out_be16(&psc_dma->psc_regs->isr_imr.imr, psc_dma->imr);
310 out_8(&psc_dma->psc_regs->command, 4 << 4); /* reset error */
311 }
312 s->stream = NULL;
313 return 0;
314}
315
316static snd_pcm_uframes_t
317psc_dma_pointer(struct snd_pcm_substream *substream)
318{
319 struct snd_soc_pcm_runtime *rtd = substream->private_data;
320 struct psc_dma *psc_dma = rtd->dai->cpu_dai->private_data;
321 struct psc_dma_stream *s;
322 dma_addr_t count;
323
324 if (substream->pstr->stream == SNDRV_PCM_STREAM_CAPTURE)
325 s = &psc_dma->capture;
326 else
327 s = &psc_dma->playback;
328
329 count = s->period_current_pt - s->period_start;
330
331 return bytes_to_frames(substream->runtime, count);
332}
333
334static int
335psc_dma_hw_params(struct snd_pcm_substream *substream,
336 struct snd_pcm_hw_params *params)
337{
338 snd_pcm_set_runtime_buffer(substream, &substream->dma_buffer);
339
340 return 0;
341}
342
343static struct snd_pcm_ops psc_dma_ops = {
344 .open = psc_dma_open,
345 .close = psc_dma_close,
346 .hw_free = psc_dma_hw_free,
347 .ioctl = snd_pcm_lib_ioctl,
348 .pointer = psc_dma_pointer,
349 .trigger = psc_dma_trigger,
350 .hw_params = psc_dma_hw_params,
351};
352
353static u64 psc_dma_dmamask = 0xffffffff;
354static int psc_dma_new(struct snd_card *card, struct snd_soc_dai *dai,
355 struct snd_pcm *pcm)
356{
357 struct snd_soc_pcm_runtime *rtd = pcm->private_data;
358 struct psc_dma *psc_dma = rtd->dai->cpu_dai->private_data;
359 size_t size = psc_dma_hardware.buffer_bytes_max;
360 int rc = 0;
361
362 dev_dbg(rtd->socdev->dev, "psc_dma_new(card=%p, dai=%p, pcm=%p)\n",
363 card, dai, pcm);
364
365 if (!card->dev->dma_mask)
366 card->dev->dma_mask = &psc_dma_dmamask;
367 if (!card->dev->coherent_dma_mask)
368 card->dev->coherent_dma_mask = 0xffffffff;
369
370 if (pcm->streams[0].substream) {
371 rc = snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, pcm->card->dev,
372 size, &pcm->streams[0].substream->dma_buffer);
373 if (rc)
374 goto playback_alloc_err;
375 }
376
377 if (pcm->streams[1].substream) {
378 rc = snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, pcm->card->dev,
379 size, &pcm->streams[1].substream->dma_buffer);
380 if (rc)
381 goto capture_alloc_err;
382 }
383
384 if (rtd->socdev->card->codec->ac97)
385 rtd->socdev->card->codec->ac97->private_data = psc_dma;
386
387 return 0;
388
389 capture_alloc_err:
390 if (pcm->streams[0].substream)
391 snd_dma_free_pages(&pcm->streams[0].substream->dma_buffer);
392
393 playback_alloc_err:
394 dev_err(card->dev, "Cannot allocate buffer(s)\n");
395
396 return -ENOMEM;
397}
398
399static void psc_dma_free(struct snd_pcm *pcm)
400{
401 struct snd_soc_pcm_runtime *rtd = pcm->private_data;
402 struct snd_pcm_substream *substream;
403 int stream;
404
405 dev_dbg(rtd->socdev->dev, "psc_dma_free(pcm=%p)\n", pcm);
406
407 for (stream = 0; stream < 2; stream++) {
408 substream = pcm->streams[stream].substream;
409 if (substream) {
410 snd_dma_free_pages(&substream->dma_buffer);
411 substream->dma_buffer.area = NULL;
412 substream->dma_buffer.addr = 0;
413 }
414 }
415}
416
417struct snd_soc_platform mpc5200_audio_dma_platform = {
418 .name = "mpc5200-psc-audio",
419 .pcm_ops = &psc_dma_ops,
420 .pcm_new = &psc_dma_new,
421 .pcm_free = &psc_dma_free,
422};
423EXPORT_SYMBOL_GPL(mpc5200_audio_dma_platform);
424
425int mpc5200_audio_dma_create(struct of_device *op)
426{
427 phys_addr_t fifo;
428 struct psc_dma *psc_dma;
429 struct resource res;
430 int size, irq, rc;
431 const __be32 *prop;
432 void __iomem *regs;
433
434 /* Fetch the registers and IRQ of the PSC */
435 irq = irq_of_parse_and_map(op->node, 0);
436 if (of_address_to_resource(op->node, 0, &res)) {
437 dev_err(&op->dev, "Missing reg property\n");
438 return -ENODEV;
439 }
440 regs = ioremap(res.start, 1 + res.end - res.start);
441 if (!regs) {
442 dev_err(&op->dev, "Could not map registers\n");
443 return -ENODEV;
444 }
445
446 /* Allocate and initialize the driver private data */
447 psc_dma = kzalloc(sizeof *psc_dma, GFP_KERNEL);
448 if (!psc_dma) {
449 iounmap(regs);
450 return -ENOMEM;
451 }
452
453 /* Get the PSC ID */
454 prop = of_get_property(op->node, "cell-index", &size);
455 if (!prop || size < sizeof *prop)
456 return -ENODEV;
457
458 spin_lock_init(&psc_dma->lock);
459 psc_dma->id = be32_to_cpu(*prop);
460 psc_dma->irq = irq;
461 psc_dma->psc_regs = regs;
462 psc_dma->fifo_regs = regs + sizeof *psc_dma->psc_regs;
463 psc_dma->dev = &op->dev;
464 psc_dma->playback.psc_dma = psc_dma;
465 psc_dma->capture.psc_dma = psc_dma;
466 snprintf(psc_dma->name, sizeof psc_dma->name, "PSC%u", psc_dma->id);
467
468 /* Find the address of the fifo data registers and setup the
469 * DMA tasks */
470 fifo = res.start + offsetof(struct mpc52xx_psc, buffer.buffer_32);
471 psc_dma->capture.bcom_task =
472 bcom_psc_gen_bd_rx_init(psc_dma->id, 10, fifo, 512);
473 psc_dma->playback.bcom_task =
474 bcom_psc_gen_bd_tx_init(psc_dma->id, 10, fifo);
475 if (!psc_dma->capture.bcom_task ||
476 !psc_dma->playback.bcom_task) {
477 dev_err(&op->dev, "Could not allocate bestcomm tasks\n");
478 iounmap(regs);
479 kfree(psc_dma);
480 return -ENODEV;
481 }
482
483 /* Disable all interrupts and reset the PSC */
484 out_be16(&psc_dma->psc_regs->isr_imr.imr, psc_dma->imr);
485 /* reset receiver */
486 out_8(&psc_dma->psc_regs->command, MPC52xx_PSC_RST_RX);
487 /* reset transmitter */
488 out_8(&psc_dma->psc_regs->command, MPC52xx_PSC_RST_TX);
489 /* reset error */
490 out_8(&psc_dma->psc_regs->command, MPC52xx_PSC_RST_ERR_STAT);
491 /* reset mode */
492 out_8(&psc_dma->psc_regs->command, MPC52xx_PSC_SEL_MODE_REG_1);
493
494 /* Set up mode register;
495 * First write: RxRdy (FIFO Alarm) generates rx FIFO irq
496 * Second write: register Normal mode for non loopback
497 */
498 out_8(&psc_dma->psc_regs->mode, 0);
499 out_8(&psc_dma->psc_regs->mode, 0);
500
501 /* Set the TX and RX fifo alarm thresholds */
502 out_be16(&psc_dma->fifo_regs->rfalarm, 0x100);
503 out_8(&psc_dma->fifo_regs->rfcntl, 0x4);
504 out_be16(&psc_dma->fifo_regs->tfalarm, 0x100);
505 out_8(&psc_dma->fifo_regs->tfcntl, 0x7);
506
507 /* Lookup the IRQ numbers */
508 psc_dma->playback.irq =
509 bcom_get_task_irq(psc_dma->playback.bcom_task);
510 psc_dma->capture.irq =
511 bcom_get_task_irq(psc_dma->capture.bcom_task);
512
513 rc = request_irq(psc_dma->irq, &psc_dma_status_irq, IRQF_SHARED,
514 "psc-dma-status", psc_dma);
515 rc |= request_irq(psc_dma->capture.irq,
516 &psc_dma_bcom_irq_rx, IRQF_SHARED,
517 "psc-dma-capture", &psc_dma->capture);
518 rc |= request_irq(psc_dma->playback.irq,
519 &psc_dma_bcom_irq_tx, IRQF_SHARED,
520 "psc-dma-playback", &psc_dma->playback);
521 if (rc) {
522 free_irq(psc_dma->irq, psc_dma);
523 free_irq(psc_dma->capture.irq,
524 &psc_dma->capture);
525 free_irq(psc_dma->playback.irq,
526 &psc_dma->playback);
527 return -ENODEV;
528 }
529
530 /* Save what we've done so it can be found again later */
531 dev_set_drvdata(&op->dev, psc_dma);
532
533 /* Tell the ASoC OF helpers about it */
534 return snd_soc_register_platform(&mpc5200_audio_dma_platform);
535}
536EXPORT_SYMBOL_GPL(mpc5200_audio_dma_create);
537
538int mpc5200_audio_dma_destroy(struct of_device *op)
539{
540 struct psc_dma *psc_dma = dev_get_drvdata(&op->dev);
541
542 dev_dbg(&op->dev, "mpc5200_audio_dma_destroy()\n");
543
544 snd_soc_unregister_platform(&mpc5200_audio_dma_platform);
545
546 bcom_gen_bd_rx_release(psc_dma->capture.bcom_task);
547 bcom_gen_bd_tx_release(psc_dma->playback.bcom_task);
548
549 /* Release irqs */
550 free_irq(psc_dma->irq, psc_dma);
551 free_irq(psc_dma->capture.irq, &psc_dma->capture);
552 free_irq(psc_dma->playback.irq, &psc_dma->playback);
553
554 iounmap(psc_dma->psc_regs);
555 kfree(psc_dma);
556 dev_set_drvdata(&op->dev, NULL);
557
558 return 0;
559}
560EXPORT_SYMBOL_GPL(mpc5200_audio_dma_destroy);
561
562MODULE_AUTHOR("Grant Likely <grant.likely@secretlab.ca>");
563MODULE_DESCRIPTION("Freescale MPC5200 PSC in DMA mode ASoC Driver");
564MODULE_LICENSE("GPL");
diff --git a/sound/soc/fsl/mpc5200_dma.h b/sound/soc/fsl/mpc5200_dma.h
new file mode 100644
index 000000000000..2000803f06a7
--- /dev/null
+++ b/sound/soc/fsl/mpc5200_dma.h
@@ -0,0 +1,80 @@
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 u32 sicr;
59 uint sysclk;
60 int imr;
61 int id;
62 unsigned int slots;
63
64 /* per-stream data */
65 struct psc_dma_stream playback;
66 struct psc_dma_stream capture;
67
68 /* Statistics */
69 struct {
70 unsigned long overrun_count;
71 unsigned long underrun_count;
72 } stats;
73};
74
75int mpc5200_audio_dma_create(struct of_device *op);
76int mpc5200_audio_dma_destroy(struct of_device *op);
77
78extern struct snd_soc_platform mpc5200_audio_dma_platform;
79
80#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..794a247b3eb5
--- /dev/null
+++ b/sound/soc/fsl/mpc5200_psc_ac97.c
@@ -0,0 +1,329 @@
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
16#include <sound/pcm.h>
17#include <sound/pcm_params.h>
18#include <sound/soc.h>
19
20#include <asm/time.h>
21#include <asm/delay.h>
22#include <asm/mpc52xx_psc.h>
23
24#include "mpc5200_dma.h"
25#include "mpc5200_psc_ac97.h"
26
27#define DRV_NAME "mpc5200-psc-ac97"
28
29/* ALSA only supports a single AC97 device so static is recommend here */
30static struct psc_dma *psc_dma;
31
32static unsigned short psc_ac97_read(struct snd_ac97 *ac97, unsigned short reg)
33{
34 int status;
35 unsigned int val;
36
37 /* Wait for command send status zero = ready */
38 status = spin_event_timeout(!(in_be16(&psc_dma->psc_regs->sr_csr.status) &
39 MPC52xx_PSC_SR_CMDSEND), 100, 0);
40 if (status == 0) {
41 pr_err("timeout on ac97 bus (rdy)\n");
42 return -ENODEV;
43 }
44 /* Send the read */
45 out_be32(&psc_dma->psc_regs->ac97_cmd, (1<<31) | ((reg & 0x7f) << 24));
46
47 /* Wait for the answer */
48 status = spin_event_timeout((in_be16(&psc_dma->psc_regs->sr_csr.status) &
49 MPC52xx_PSC_SR_DATA_VAL), 100, 0);
50 if (status == 0) {
51 pr_err("timeout on ac97 read (val) %x\n",
52 in_be16(&psc_dma->psc_regs->sr_csr.status));
53 return -ENODEV;
54 }
55 /* Get the data */
56 val = in_be32(&psc_dma->psc_regs->ac97_data);
57 if (((val >> 24) & 0x7f) != reg) {
58 pr_err("reg echo error on ac97 read\n");
59 return -ENODEV;
60 }
61 val = (val >> 8) & 0xffff;
62
63 return (unsigned short) val;
64}
65
66static void psc_ac97_write(struct snd_ac97 *ac97,
67 unsigned short reg, unsigned short val)
68{
69 int status;
70
71 /* Wait for command status zero = ready */
72 status = spin_event_timeout(!(in_be16(&psc_dma->psc_regs->sr_csr.status) &
73 MPC52xx_PSC_SR_CMDSEND), 100, 0);
74 if (status == 0) {
75 pr_err("timeout on ac97 bus (write)\n");
76 return;
77 }
78 /* Write data */
79 out_be32(&psc_dma->psc_regs->ac97_cmd,
80 ((reg & 0x7f) << 24) | (val << 8));
81}
82
83static void psc_ac97_warm_reset(struct snd_ac97 *ac97)
84{
85 struct mpc52xx_psc __iomem *regs = psc_dma->psc_regs;
86
87 out_be32(&regs->sicr, psc_dma->sicr | MPC52xx_PSC_SICR_AWR);
88 udelay(3);
89 out_be32(&regs->sicr, psc_dma->sicr);
90}
91
92static void psc_ac97_cold_reset(struct snd_ac97 *ac97)
93{
94 struct mpc52xx_psc __iomem *regs = psc_dma->psc_regs;
95
96 /* Do a cold reset */
97 out_8(&regs->op1, MPC52xx_PSC_OP_RES);
98 udelay(10);
99 out_8(&regs->op0, MPC52xx_PSC_OP_RES);
100 udelay(50);
101 psc_ac97_warm_reset(ac97);
102}
103
104struct snd_ac97_bus_ops soc_ac97_ops = {
105 .read = psc_ac97_read,
106 .write = psc_ac97_write,
107 .reset = psc_ac97_cold_reset,
108 .warm_reset = psc_ac97_warm_reset,
109};
110EXPORT_SYMBOL_GPL(soc_ac97_ops);
111
112static int psc_ac97_hw_analog_params(struct snd_pcm_substream *substream,
113 struct snd_pcm_hw_params *params,
114 struct snd_soc_dai *cpu_dai)
115{
116 struct psc_dma *psc_dma = cpu_dai->private_data;
117
118 dev_dbg(psc_dma->dev, "%s(substream=%p) p_size=%i p_bytes=%i"
119 " periods=%i buffer_size=%i buffer_bytes=%i channels=%i"
120 " rate=%i format=%i\n",
121 __func__, substream, params_period_size(params),
122 params_period_bytes(params), params_periods(params),
123 params_buffer_size(params), params_buffer_bytes(params),
124 params_channels(params), params_rate(params),
125 params_format(params));
126
127
128 if (substream->pstr->stream == SNDRV_PCM_STREAM_CAPTURE) {
129 if (params_channels(params) == 1)
130 psc_dma->slots |= 0x00000100;
131 else
132 psc_dma->slots |= 0x00000300;
133 } else {
134 if (params_channels(params) == 1)
135 psc_dma->slots |= 0x01000000;
136 else
137 psc_dma->slots |= 0x03000000;
138 }
139 out_be32(&psc_dma->psc_regs->ac97_slots, psc_dma->slots);
140
141 return 0;
142}
143
144static int psc_ac97_hw_digital_params(struct snd_pcm_substream *substream,
145 struct snd_pcm_hw_params *params,
146 struct snd_soc_dai *cpu_dai)
147{
148 struct psc_dma *psc_dma = cpu_dai->private_data;
149
150 if (params_channels(params) == 1)
151 out_be32(&psc_dma->psc_regs->ac97_slots, 0x01000000);
152 else
153 out_be32(&psc_dma->psc_regs->ac97_slots, 0x03000000);
154
155 return 0;
156}
157
158static int psc_ac97_trigger(struct snd_pcm_substream *substream, int cmd,
159 struct snd_soc_dai *dai)
160{
161 struct snd_soc_pcm_runtime *rtd = substream->private_data;
162 struct psc_dma *psc_dma = rtd->dai->cpu_dai->private_data;
163
164 switch (cmd) {
165 case SNDRV_PCM_TRIGGER_STOP:
166 if (substream->pstr->stream == SNDRV_PCM_STREAM_CAPTURE)
167 psc_dma->slots &= 0xFFFF0000;
168 else
169 psc_dma->slots &= 0x0000FFFF;
170
171 out_be32(&psc_dma->psc_regs->ac97_slots, psc_dma->slots);
172 break;
173 }
174 return 0;
175}
176
177static int psc_ac97_probe(struct platform_device *pdev,
178 struct snd_soc_dai *cpu_dai)
179{
180 struct psc_dma *psc_dma = cpu_dai->private_data;
181 struct mpc52xx_psc __iomem *regs = psc_dma->psc_regs;
182
183 /* Go */
184 out_8(&regs->command, MPC52xx_PSC_TX_ENABLE | MPC52xx_PSC_RX_ENABLE);
185 return 0;
186}
187
188/* ---------------------------------------------------------------------
189 * ALSA SoC Bindings
190 *
191 * - Digital Audio Interface (DAI) template
192 * - create/destroy dai hooks
193 */
194
195/**
196 * psc_ac97_dai_template: template CPU Digital Audio Interface
197 */
198static struct snd_soc_dai_ops psc_ac97_analog_ops = {
199 .hw_params = psc_ac97_hw_analog_params,
200 .trigger = psc_ac97_trigger,
201};
202
203static struct snd_soc_dai_ops psc_ac97_digital_ops = {
204 .hw_params = psc_ac97_hw_digital_params,
205};
206
207struct snd_soc_dai psc_ac97_dai[] = {
208{
209 .name = "AC97",
210 .ac97_control = 1,
211 .probe = psc_ac97_probe,
212 .playback = {
213 .channels_min = 1,
214 .channels_max = 6,
215 .rates = SNDRV_PCM_RATE_8000_48000,
216 .formats = SNDRV_PCM_FMTBIT_S32_BE,
217 },
218 .capture = {
219 .channels_min = 1,
220 .channels_max = 2,
221 .rates = SNDRV_PCM_RATE_8000_48000,
222 .formats = SNDRV_PCM_FMTBIT_S32_BE,
223 },
224 .ops = &psc_ac97_analog_ops,
225},
226{
227 .name = "SPDIF",
228 .ac97_control = 1,
229 .playback = {
230 .channels_min = 1,
231 .channels_max = 2,
232 .rates = SNDRV_PCM_RATE_32000 | \
233 SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_48000,
234 .formats = SNDRV_PCM_FMTBIT_IEC958_SUBFRAME_BE,
235 },
236 .ops = &psc_ac97_digital_ops,
237} };
238EXPORT_SYMBOL_GPL(psc_ac97_dai);
239
240
241
242/* ---------------------------------------------------------------------
243 * OF platform bus binding code:
244 * - Probe/remove operations
245 * - OF device match table
246 */
247static int __devinit psc_ac97_of_probe(struct of_device *op,
248 const struct of_device_id *match)
249{
250 int rc, i;
251 struct snd_ac97 ac97;
252 struct mpc52xx_psc __iomem *regs;
253
254 rc = mpc5200_audio_dma_create(op);
255 if (rc != 0)
256 return rc;
257
258 for (i = 0; i < ARRAY_SIZE(psc_ac97_dai); i++)
259 psc_ac97_dai[i].dev = &op->dev;
260
261 rc = snd_soc_register_dais(psc_ac97_dai, ARRAY_SIZE(psc_ac97_dai));
262 if (rc != 0) {
263 dev_err(&op->dev, "Failed to register DAI\n");
264 return rc;
265 }
266
267 psc_dma = dev_get_drvdata(&op->dev);
268 regs = psc_dma->psc_regs;
269 ac97.private_data = psc_dma;
270
271 for (i = 0; i < ARRAY_SIZE(psc_ac97_dai); i++)
272 psc_ac97_dai[i].private_data = psc_dma;
273
274 psc_dma->imr = 0;
275 out_be16(&psc_dma->psc_regs->isr_imr.imr, psc_dma->imr);
276
277 /* Configure the serial interface mode to AC97 */
278 psc_dma->sicr = MPC52xx_PSC_SICR_SIM_AC97 | MPC52xx_PSC_SICR_ENAC97;
279 out_be32(&regs->sicr, psc_dma->sicr);
280
281 /* No slots active */
282 out_be32(&regs->ac97_slots, 0x00000000);
283
284 return 0;
285}
286
287static int __devexit psc_ac97_of_remove(struct of_device *op)
288{
289 return mpc5200_audio_dma_destroy(op);
290}
291
292/* Match table for of_platform binding */
293static struct of_device_id psc_ac97_match[] __devinitdata = {
294 { .compatible = "fsl,mpc5200-psc-ac97", },
295 { .compatible = "fsl,mpc5200b-psc-ac97", },
296 {}
297};
298MODULE_DEVICE_TABLE(of, psc_ac97_match);
299
300static struct of_platform_driver psc_ac97_driver = {
301 .match_table = psc_ac97_match,
302 .probe = psc_ac97_of_probe,
303 .remove = __devexit_p(psc_ac97_of_remove),
304 .driver = {
305 .name = "mpc5200-psc-ac97",
306 .owner = THIS_MODULE,
307 },
308};
309
310/* ---------------------------------------------------------------------
311 * Module setup and teardown; simply register the of_platform driver
312 * for the PSC in AC97 mode.
313 */
314static int __init psc_ac97_init(void)
315{
316 return of_register_platform_driver(&psc_ac97_driver);
317}
318module_init(psc_ac97_init);
319
320static void __exit psc_ac97_exit(void)
321{
322 of_unregister_platform_driver(&psc_ac97_driver);
323}
324module_exit(psc_ac97_exit);
325
326MODULE_AUTHOR("Jon Smirl <jonsmirl@gmail.com>");
327MODULE_DESCRIPTION("mpc5200 AC97 module");
328MODULE_LICENSE("GPL");
329
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..b771238662b6 100644
--- a/sound/soc/omap/Kconfig
+++ b/sound/soc/omap/Kconfig
@@ -39,6 +39,14 @@ config SND_OMAP_SOC_OMAP2EVM
39 help 39 help
40 Say Y if you want to add support for SoC audio on the omap2evm board. 40 Say Y if you want to add support for SoC audio on the omap2evm board.
41 41
42config SND_OMAP_SOC_OMAP3EVM
43 tristate "SoC Audio support for OMAP3EVM board"
44 depends on TWL4030_CORE && SND_OMAP_SOC && MACH_OMAP3EVM
45 select SND_OMAP_SOC_MCBSP
46 select SND_SOC_TWL4030
47 help
48 Say Y if you want to add support for SoC audio on the omap3evm board.
49
42config SND_OMAP_SOC_SDP3430 50config SND_OMAP_SOC_SDP3430
43 tristate "SoC Audio support for Texas Instruments SDP3430" 51 tristate "SoC Audio support for Texas Instruments SDP3430"
44 depends on TWL4030_CORE && SND_OMAP_SOC && MACH_OMAP_3430SDP 52 depends on TWL4030_CORE && SND_OMAP_SOC && MACH_OMAP_3430SDP
diff --git a/sound/soc/omap/Makefile b/sound/soc/omap/Makefile
index 0c9e4ac37660..a37f49862389 100644
--- a/sound/soc/omap/Makefile
+++ b/sound/soc/omap/Makefile
@@ -10,6 +10,7 @@ snd-soc-n810-objs := n810.o
10snd-soc-osk5912-objs := osk5912.o 10snd-soc-osk5912-objs := osk5912.o
11snd-soc-overo-objs := overo.o 11snd-soc-overo-objs := overo.o
12snd-soc-omap2evm-objs := omap2evm.o 12snd-soc-omap2evm-objs := omap2evm.o
13snd-soc-omap3evm-objs := omap3evm.o
13snd-soc-sdp3430-objs := sdp3430.o 14snd-soc-sdp3430-objs := sdp3430.o
14snd-soc-omap3pandora-objs := omap3pandora.o 15snd-soc-omap3pandora-objs := omap3pandora.o
15snd-soc-omap3beagle-objs := omap3beagle.o 16snd-soc-omap3beagle-objs := omap3beagle.o
@@ -18,6 +19,7 @@ obj-$(CONFIG_SND_OMAP_SOC_N810) += snd-soc-n810.o
18obj-$(CONFIG_SND_OMAP_SOC_OSK5912) += snd-soc-osk5912.o 19obj-$(CONFIG_SND_OMAP_SOC_OSK5912) += snd-soc-osk5912.o
19obj-$(CONFIG_SND_OMAP_SOC_OVERO) += snd-soc-overo.o 20obj-$(CONFIG_SND_OMAP_SOC_OVERO) += snd-soc-overo.o
20obj-$(CONFIG_MACH_OMAP2EVM) += snd-soc-omap2evm.o 21obj-$(CONFIG_MACH_OMAP2EVM) += snd-soc-omap2evm.o
22obj-$(CONFIG_MACH_OMAP3EVM) += snd-soc-omap3evm.o
21obj-$(CONFIG_SND_OMAP_SOC_SDP3430) += snd-soc-sdp3430.o 23obj-$(CONFIG_SND_OMAP_SOC_SDP3430) += snd-soc-sdp3430.o
22obj-$(CONFIG_SND_OMAP_SOC_OMAP3_PANDORA) += snd-soc-omap3pandora.o 24obj-$(CONFIG_SND_OMAP_SOC_OMAP3_PANDORA) += snd-soc-omap3pandora.o
23obj-$(CONFIG_SND_OMAP_SOC_OMAP3_BEAGLE) += snd-soc-omap3beagle.o 25obj-$(CONFIG_SND_OMAP_SOC_OMAP3_BEAGLE) += snd-soc-omap3beagle.o
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..a5d46a7b196a 100644
--- a/sound/soc/omap/omap-mcbsp.c
+++ b/sound/soc/omap/omap-mcbsp.c
@@ -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..6454e15f7d28 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
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..b719e5db4f57 100644
--- a/sound/soc/omap/sdp3430.c
+++ b/sound/soc/omap/sdp3430.c
@@ -84,6 +84,49 @@ static struct snd_soc_ops sdp3430_ops = {
84 .hw_params = sdp3430_hw_params, 84 .hw_params = sdp3430_hw_params,
85}; 85};
86 86
87static int sdp3430_hw_voice_params(struct snd_pcm_substream *substream,
88 struct snd_pcm_hw_params *params)
89{
90 struct snd_soc_pcm_runtime *rtd = substream->private_data;
91 struct snd_soc_dai *codec_dai = rtd->dai->codec_dai;
92 struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai;
93 int ret;
94
95 /* Set codec DAI configuration */
96 ret = snd_soc_dai_set_fmt(codec_dai,
97 SND_SOC_DAIFMT_DSP_A |
98 SND_SOC_DAIFMT_IB_NF |
99 SND_SOC_DAIFMT_CBS_CFM);
100 if (ret) {
101 printk(KERN_ERR "can't set codec DAI configuration\n");
102 return ret;
103 }
104
105 /* Set cpu DAI configuration */
106 ret = snd_soc_dai_set_fmt(cpu_dai,
107 SND_SOC_DAIFMT_DSP_A |
108 SND_SOC_DAIFMT_IB_NF |
109 SND_SOC_DAIFMT_CBM_CFM);
110 if (ret < 0) {
111 printk(KERN_ERR "can't set cpu DAI configuration\n");
112 return ret;
113 }
114
115 /* Set the codec system clock for DAC and ADC */
116 ret = snd_soc_dai_set_sysclk(codec_dai, 0, 26000000,
117 SND_SOC_CLOCK_IN);
118 if (ret < 0) {
119 printk(KERN_ERR "can't set codec system clock\n");
120 return ret;
121 }
122
123 return 0;
124}
125
126static struct snd_soc_ops sdp3430_voice_ops = {
127 .hw_params = sdp3430_hw_voice_params,
128};
129
87/* Headset jack */ 130/* Headset jack */
88static struct snd_soc_jack hs_jack; 131static struct snd_soc_jack hs_jack;
89 132
@@ -192,28 +235,58 @@ static int sdp3430_twl4030_init(struct snd_soc_codec *codec)
192 return ret; 235 return ret;
193} 236}
194 237
238static int sdp3430_twl4030_voice_init(struct snd_soc_codec *codec)
239{
240 unsigned short reg;
241
242 /* Enable voice interface */
243 reg = codec->read(codec, TWL4030_REG_VOICE_IF);
244 reg |= TWL4030_VIF_DIN_EN | TWL4030_VIF_DOUT_EN | TWL4030_VIF_EN;
245 codec->write(codec, TWL4030_REG_VOICE_IF, reg);
246
247 return 0;
248}
249
250
195/* Digital audio interface glue - connects codec <--> CPU */ 251/* Digital audio interface glue - connects codec <--> CPU */
196static struct snd_soc_dai_link sdp3430_dai = { 252static struct snd_soc_dai_link sdp3430_dai[] = {
197 .name = "TWL4030", 253 {
198 .stream_name = "TWL4030", 254 .name = "TWL4030 I2S",
199 .cpu_dai = &omap_mcbsp_dai[0], 255 .stream_name = "TWL4030 Audio",
200 .codec_dai = &twl4030_dai, 256 .cpu_dai = &omap_mcbsp_dai[0],
201 .init = sdp3430_twl4030_init, 257 .codec_dai = &twl4030_dai[TWL4030_DAI_HIFI],
202 .ops = &sdp3430_ops, 258 .init = sdp3430_twl4030_init,
259 .ops = &sdp3430_ops,
260 },
261 {
262 .name = "TWL4030 PCM",
263 .stream_name = "TWL4030 Voice",
264 .cpu_dai = &omap_mcbsp_dai[1],
265 .codec_dai = &twl4030_dai[TWL4030_DAI_VOICE],
266 .init = sdp3430_twl4030_voice_init,
267 .ops = &sdp3430_voice_ops,
268 },
203}; 269};
204 270
205/* Audio machine driver */ 271/* Audio machine driver */
206static struct snd_soc_card snd_soc_sdp3430 = { 272static struct snd_soc_card snd_soc_sdp3430 = {
207 .name = "SDP3430", 273 .name = "SDP3430",
208 .platform = &omap_soc_platform, 274 .platform = &omap_soc_platform,
209 .dai_link = &sdp3430_dai, 275 .dai_link = sdp3430_dai,
210 .num_links = 1, 276 .num_links = ARRAY_SIZE(sdp3430_dai),
277};
278
279/* twl4030 setup */
280static struct twl4030_setup_data twl4030_setup = {
281 .ramp_delay_value = 3,
282 .sysclk = 26000,
211}; 283};
212 284
213/* Audio subsystem */ 285/* Audio subsystem */
214static struct snd_soc_device sdp3430_snd_devdata = { 286static struct snd_soc_device sdp3430_snd_devdata = {
215 .card = &snd_soc_sdp3430, 287 .card = &snd_soc_sdp3430,
216 .codec_dev = &soc_codec_dev_twl4030, 288 .codec_dev = &soc_codec_dev_twl4030,
289 .codec_data = &twl4030_setup,
217}; 290};
218 291
219static struct platform_device *sdp3430_snd_device; 292static struct platform_device *sdp3430_snd_device;
@@ -236,7 +309,8 @@ static int __init sdp3430_soc_init(void)
236 309
237 platform_set_drvdata(sdp3430_snd_device, &sdp3430_snd_devdata); 310 platform_set_drvdata(sdp3430_snd_device, &sdp3430_snd_devdata);
238 sdp3430_snd_devdata.dev = &sdp3430_snd_device->dev; 311 sdp3430_snd_devdata.dev = &sdp3430_snd_device->dev;
239 *(unsigned int *)sdp3430_dai.cpu_dai->private_data = 1; /* McBSP2 */ 312 *(unsigned int *)sdp3430_dai[0].cpu_dai->private_data = 1; /* McBSP2 */
313 *(unsigned int *)sdp3430_dai[1].cpu_dai->private_data = 2; /* McBSP3 */
240 314
241 ret = platform_device_add(sdp3430_snd_device); 315 ret = platform_device_add(sdp3430_snd_device);
242 if (ret) 316 if (ret)
diff --git a/sound/soc/pxa/Kconfig b/sound/soc/pxa/Kconfig
index ad8a10fe6298..dcd163a4ee9a 100644
--- a/sound/soc/pxa/Kconfig
+++ b/sound/soc/pxa/Kconfig
@@ -89,13 +89,13 @@ 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 and LifeDrive"
@@ -134,3 +134,12 @@ config SND_PXA2XX_SOC_MIOA701
134 help 134 help
135 Say Y if you want to add support for SoC audio on the 135 Say Y if you want to add support for SoC audio on the
136 MIO A701. 136 MIO A701.
137
138config SND_PXA2XX_SOC_IMOTE2
139 tristate "SoC Audio support for IMote 2"
140 depends on SND_PXA2XX_SOC && MACH_INTELMOTE2
141 select SND_PXA2XX_SOC_I2S
142 select SND_SOC_WM8940
143 help
144 Say Y if you want to add support for SoC audio on the
145 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/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..c89a3cdf31e4 100644
--- a/sound/soc/pxa/magician.c
+++ b/sound/soc/pxa/magician.c
@@ -106,7 +106,7 @@ static int magician_playback_hw_params(struct snd_pcm_substream *substream,
106 /* 513156 Hz ~= _2_ * 8000 Hz * 32 (+0.23%) */ 106 /* 513156 Hz ~= _2_ * 8000 Hz * 32 (+0.23%) */
107 acds = PXA_SSP_CLK_AUDIO_DIV_16; 107 acds = PXA_SSP_CLK_AUDIO_DIV_16;
108 break; 108 break;
109 case 32: 109 default: /* 32 */
110 /* 1026312 Hz ~= _2_ * 8000 Hz * 64 (+0.23%) */ 110 /* 1026312 Hz ~= _2_ * 8000 Hz * 64 (+0.23%) */
111 acds = PXA_SSP_CLK_AUDIO_DIV_8; 111 acds = PXA_SSP_CLK_AUDIO_DIV_8;
112 } 112 }
@@ -118,7 +118,7 @@ static int magician_playback_hw_params(struct snd_pcm_substream *substream,
118 /* 351375 Hz ~= 11025 Hz * 32 (-0.41%) */ 118 /* 351375 Hz ~= 11025 Hz * 32 (-0.41%) */
119 acds = PXA_SSP_CLK_AUDIO_DIV_4; 119 acds = PXA_SSP_CLK_AUDIO_DIV_4;
120 break; 120 break;
121 case 32: 121 default: /* 32 */
122 /* 702750 Hz ~= 11025 Hz * 64 (-0.41%) */ 122 /* 702750 Hz ~= 11025 Hz * 64 (-0.41%) */
123 acds = PXA_SSP_CLK_AUDIO_DIV_2; 123 acds = PXA_SSP_CLK_AUDIO_DIV_2;
124 } 124 }
@@ -130,7 +130,7 @@ static int magician_playback_hw_params(struct snd_pcm_substream *substream,
130 /* 702750 Hz ~= 22050 Hz * 32 (-0.41%) */ 130 /* 702750 Hz ~= 22050 Hz * 32 (-0.41%) */
131 acds = PXA_SSP_CLK_AUDIO_DIV_2; 131 acds = PXA_SSP_CLK_AUDIO_DIV_2;
132 break; 132 break;
133 case 32: 133 default: /* 32 */
134 /* 1405500 Hz ~= 22050 Hz * 64 (-0.41%) */ 134 /* 1405500 Hz ~= 22050 Hz * 64 (-0.41%) */
135 acds = PXA_SSP_CLK_AUDIO_DIV_1; 135 acds = PXA_SSP_CLK_AUDIO_DIV_1;
136 } 136 }
@@ -142,7 +142,7 @@ static int magician_playback_hw_params(struct snd_pcm_substream *substream,
142 /* 1405500 Hz ~= 44100 Hz * 32 (-0.41%) */ 142 /* 1405500 Hz ~= 44100 Hz * 32 (-0.41%) */
143 acds = PXA_SSP_CLK_AUDIO_DIV_2; 143 acds = PXA_SSP_CLK_AUDIO_DIV_2;
144 break; 144 break;
145 case 32: 145 default: /* 32 */
146 /* 2811000 Hz ~= 44100 Hz * 64 (-0.41%) */ 146 /* 2811000 Hz ~= 44100 Hz * 64 (-0.41%) */
147 acds = PXA_SSP_CLK_AUDIO_DIV_1; 147 acds = PXA_SSP_CLK_AUDIO_DIV_1;
148 } 148 }
@@ -154,19 +154,20 @@ static int magician_playback_hw_params(struct snd_pcm_substream *substream,
154 /* 1529375 Hz ~= 48000 Hz * 32 (-0.44%) */ 154 /* 1529375 Hz ~= 48000 Hz * 32 (-0.44%) */
155 acds = PXA_SSP_CLK_AUDIO_DIV_2; 155 acds = PXA_SSP_CLK_AUDIO_DIV_2;
156 break; 156 break;
157 case 32: 157 default: /* 32 */
158 /* 3058750 Hz ~= 48000 Hz * 64 (-0.44%) */ 158 /* 3058750 Hz ~= 48000 Hz * 64 (-0.44%) */
159 acds = PXA_SSP_CLK_AUDIO_DIV_1; 159 acds = PXA_SSP_CLK_AUDIO_DIV_1;
160 } 160 }
161 break; 161 break;
162 case 96000: 162 case 96000:
163 default:
163 acps = 12235000; 164 acps = 12235000;
164 switch (width) { 165 switch (width) {
165 case 16: 166 case 16:
166 /* 3058750 Hz ~= 96000 Hz * 32 (-0.44%) */ 167 /* 3058750 Hz ~= 96000 Hz * 32 (-0.44%) */
167 acds = PXA_SSP_CLK_AUDIO_DIV_1; 168 acds = PXA_SSP_CLK_AUDIO_DIV_1;
168 break; 169 break;
169 case 32: 170 default: /* 32 */
170 /* 6117500 Hz ~= 96000 Hz * 64 (-0.44%) */ 171 /* 6117500 Hz ~= 96000 Hz * 64 (-0.44%) */
171 acds = PXA_SSP_CLK_AUDIO_DIV_2; 172 acds = PXA_SSP_CLK_AUDIO_DIV_2;
172 div4 = PXA_SSP_CLK_SCDB_1; 173 div4 = PXA_SSP_CLK_SCDB_1;
diff --git a/sound/soc/pxa/pxa-ssp.c b/sound/soc/pxa/pxa-ssp.c
index 286be31545df..19c45409d94c 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 }
@@ -589,7 +474,10 @@ static int pxa_ssp_set_dai_fmt(struct snd_soc_dai *cpu_dai,
589 case SND_SOC_DAIFMT_NB_IF: 474 case SND_SOC_DAIFMT_NB_IF:
590 break; 475 break;
591 case SND_SOC_DAIFMT_IB_IF: 476 case SND_SOC_DAIFMT_IB_IF:
592 sspsp |= SSPSP_SCMODE(3); 477 sspsp |= SSPSP_SCMODE(2);
478 break;
479 case SND_SOC_DAIFMT_IB_NF:
480 sspsp |= SSPSP_SCMODE(2) | SSPSP_SFRMP;
593 break; 481 break;
594 default: 482 default:
595 return -EINVAL; 483 return -EINVAL;
@@ -606,7 +494,13 @@ static int pxa_ssp_set_dai_fmt(struct snd_soc_dai *cpu_dai,
606 case SND_SOC_DAIFMT_NB_NF: 494 case SND_SOC_DAIFMT_NB_NF:
607 sspsp |= SSPSP_SFRMP; 495 sspsp |= SSPSP_SFRMP;
608 break; 496 break;
497 case SND_SOC_DAIFMT_NB_IF:
498 break;
609 case SND_SOC_DAIFMT_IB_IF: 499 case SND_SOC_DAIFMT_IB_IF:
500 sspsp |= SSPSP_SCMODE(2);
501 break;
502 case SND_SOC_DAIFMT_IB_NF:
503 sspsp |= SSPSP_SCMODE(2) | SSPSP_SFRMP;
610 break; 504 break;
611 default: 505 default:
612 return -EINVAL; 506 return -EINVAL;
@@ -644,25 +538,23 @@ static int pxa_ssp_hw_params(struct snd_pcm_substream *substream,
644 struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai; 538 struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai;
645 struct ssp_priv *priv = cpu_dai->private_data; 539 struct ssp_priv *priv = cpu_dai->private_data;
646 struct ssp_device *ssp = priv->dev.ssp; 540 struct ssp_device *ssp = priv->dev.ssp;
647 int dma = 0, chn = params_channels(params); 541 int chn = params_channels(params);
648 u32 sscr0; 542 u32 sscr0;
649 u32 sspsp; 543 u32 sspsp;
650 int width = snd_pcm_format_physical_width(params_format(params)); 544 int width = snd_pcm_format_physical_width(params_format(params));
651 int ttsa = ssp_read_reg(ssp, SSTSA) & 0xf; 545 int ttsa = ssp_read_reg(ssp, SSTSA) & 0xf;
652 546
653 /* select correct DMA params */ 547 /* generate correct DMA params */
654 if (substream->stream != SNDRV_PCM_STREAM_PLAYBACK) 548 if (cpu_dai->dma_data)
655 dma = 1; /* capture DMA offset is 1,3 */ 549 kfree(cpu_dai->dma_data);
550
656 /* Network mode with one active slot (ttsa == 1) can be used 551 /* 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 552 * 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. 553 * with two channels. Use 16-bit DMA transfers for this case.
659 */ 554 */
660 if (((chn == 2) && (ttsa != 1)) || (width == 32)) 555 cpu_dai->dma_data = ssp_get_dma_params(ssp,
661 dma += 2; /* 32-bit DMA offset is 2, 16-bit is 0 */ 556 ((chn == 2) && (ttsa != 1)) || (width == 32),
662 557 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 558
667 /* we can only change the settings if the port is not in use */ 559 /* we can only change the settings if the port is not in use */
668 if (ssp_read_reg(ssp, SSCR0) & SSCR0_SSE) 560 if (ssp_read_reg(ssp, SSCR0) & SSCR0_SSE)
diff --git a/sound/soc/pxa/pxa2xx-i2s.c b/sound/soc/pxa/pxa2xx-i2s.c
index 2f4b6e489b78..4743e262895d 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}
@@ -178,9 +176,7 @@ static int pxa2xx_i2s_hw_params(struct snd_pcm_substream *substream,
178 176
179 /* is port used by another stream */ 177 /* is port used by another stream */
180 if (!(SACR0 & SACR0_ENB)) { 178 if (!(SACR0 & SACR0_ENB)) {
181
182 SACR0 = 0; 179 SACR0 = 0;
183 SACR1 = 0;
184 if (pxa_i2s.master) 180 if (pxa_i2s.master)
185 SACR0 |= SACR0_BCKD; 181 SACR0 |= SACR0_BCKD;
186 182
@@ -226,6 +222,10 @@ static int pxa2xx_i2s_trigger(struct snd_pcm_substream *substream, int cmd,
226 222
227 switch (cmd) { 223 switch (cmd) {
228 case SNDRV_PCM_TRIGGER_START: 224 case SNDRV_PCM_TRIGGER_START:
225 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
226 SACR1 &= ~SACR1_DRPL;
227 else
228 SACR1 &= ~SACR1_DREC;
229 SACR0 |= SACR0_ENB; 229 SACR0 |= SACR0_ENB;
230 break; 230 break;
231 case SNDRV_PCM_TRIGGER_RESUME: 231 case SNDRV_PCM_TRIGGER_RESUME:
@@ -252,21 +252,16 @@ static void pxa2xx_i2s_shutdown(struct snd_pcm_substream *substream,
252 SAIMR &= ~SAIMR_RFS; 252 SAIMR &= ~SAIMR_RFS;
253 } 253 }
254 254
255 if (SACR1 & (SACR1_DREC | SACR1_DRPL)) { 255 if ((SACR1 & (SACR1_DREC | SACR1_DRPL)) == (SACR1_DREC | SACR1_DRPL)) {
256 SACR0 &= ~SACR0_ENB; 256 SACR0 &= ~SACR0_ENB;
257 pxa_i2s_wait(); 257 pxa_i2s_wait();
258 clk_disable(clk_i2s); 258 clk_disable(clk_i2s);
259 } 259 }
260
261 clk_put(clk_i2s);
262} 260}
263 261
264#ifdef CONFIG_PM 262#ifdef CONFIG_PM
265static int pxa2xx_i2s_suspend(struct snd_soc_dai *dai) 263static int pxa2xx_i2s_suspend(struct snd_soc_dai *dai)
266{ 264{
267 if (!dai->active)
268 return 0;
269
270 /* store registers */ 265 /* store registers */
271 pxa_i2s.sacr0 = SACR0; 266 pxa_i2s.sacr0 = SACR0;
272 pxa_i2s.sacr1 = SACR1; 267 pxa_i2s.sacr1 = SACR1;
@@ -281,16 +276,14 @@ static int pxa2xx_i2s_suspend(struct snd_soc_dai *dai)
281 276
282static int pxa2xx_i2s_resume(struct snd_soc_dai *dai) 277static int pxa2xx_i2s_resume(struct snd_soc_dai *dai)
283{ 278{
284 if (!dai->active)
285 return 0;
286
287 pxa_i2s_wait(); 279 pxa_i2s_wait();
288 280
289 SACR0 = pxa_i2s.sacr0 &= ~SACR0_ENB; 281 SACR0 = pxa_i2s.sacr0 & ~SACR0_ENB;
290 SACR1 = pxa_i2s.sacr1; 282 SACR1 = pxa_i2s.sacr1;
291 SAIMR = pxa_i2s.saimr; 283 SAIMR = pxa_i2s.saimr;
292 SADIV = pxa_i2s.sadiv; 284 SADIV = pxa_i2s.sadiv;
293 SACR0 |= SACR0_ENB; 285
286 SACR0 = pxa_i2s.sacr0;
294 287
295 return 0; 288 return 0;
296} 289}
@@ -329,6 +322,7 @@ struct snd_soc_dai pxa_i2s_dai = {
329 .rates = PXA2XX_I2S_RATES, 322 .rates = PXA2XX_I2S_RATES,
330 .formats = SNDRV_PCM_FMTBIT_S16_LE,}, 323 .formats = SNDRV_PCM_FMTBIT_S16_LE,},
331 .ops = &pxa_i2s_dai_ops, 324 .ops = &pxa_i2s_dai_ops,
325 .symmetric_rates = 1,
332}; 326};
333 327
334EXPORT_SYMBOL_GPL(pxa_i2s_dai); 328EXPORT_SYMBOL_GPL(pxa_i2s_dai);
@@ -346,6 +340,19 @@ static int pxa2xx_i2s_probe(struct platform_device *dev)
346 if (ret != 0) 340 if (ret != 0)
347 clk_put(clk_i2s); 341 clk_put(clk_i2s);
348 342
343 /*
344 * PXA Developer's Manual:
345 * If SACR0[ENB] is toggled in the middle of a normal operation,
346 * the SACR0[RST] bit must also be set and cleared to reset all
347 * I2S controller registers.
348 */
349 SACR0 = SACR0_RST;
350 SACR0 = 0;
351 /* Make sure RPL and REC are disabled */
352 SACR1 = SACR1_DRPL | SACR1_DREC;
353 /* Along with FIFO servicing */
354 SAIMR &= ~(SAIMR_RFS | SAIMR_TFS);
355
349 return ret; 356 return ret;
350} 357}
351 358
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..168a088ba761 100644
--- a/sound/soc/s3c24xx/s3c2412-i2s.c
+++ b/sound/soc/s3c24xx/s3c2412-i2s.c
@@ -120,7 +120,7 @@ static int s3c2412_i2s_probe(struct platform_device *pdev,
120 120
121 s3c2412_i2s.iis_cclk = clk_get(&pdev->dev, "i2sclk"); 121 s3c2412_i2s.iis_cclk = clk_get(&pdev->dev, "i2sclk");
122 if (s3c2412_i2s.iis_cclk == NULL) { 122 if (s3c2412_i2s.iis_cclk == NULL) {
123 pr_debug("failed to get i2sclk clock\n"); 123 pr_err("failed to get i2sclk clock\n");
124 iounmap(s3c2412_i2s.regs); 124 iounmap(s3c2412_i2s.regs);
125 return -ENODEV; 125 return -ENODEV;
126 } 126 }
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-core.c b/sound/soc/soc-core.c
index 1cd149b9ce69..3f44150d8e30 100644
--- a/sound/soc/soc-core.c
+++ b/sound/soc/soc-core.c
@@ -113,6 +113,35 @@ static int soc_ac97_dev_register(struct snd_soc_codec *codec)
113} 113}
114#endif 114#endif
115 115
116static int soc_pcm_apply_symmetry(struct snd_pcm_substream *substream)
117{
118 struct snd_soc_pcm_runtime *rtd = substream->private_data;
119 struct snd_soc_device *socdev = rtd->socdev;
120 struct snd_soc_card *card = socdev->card;
121 struct snd_soc_dai_link *machine = rtd->dai;
122 struct snd_soc_dai *cpu_dai = machine->cpu_dai;
123 struct snd_soc_dai *codec_dai = machine->codec_dai;
124 int ret;
125
126 if (codec_dai->symmetric_rates || cpu_dai->symmetric_rates ||
127 machine->symmetric_rates) {
128 dev_dbg(card->dev, "Symmetry forces %dHz rate\n",
129 machine->rate);
130
131 ret = snd_pcm_hw_constraint_minmax(substream->runtime,
132 SNDRV_PCM_HW_PARAM_RATE,
133 machine->rate,
134 machine->rate);
135 if (ret < 0) {
136 dev_err(card->dev,
137 "Unable to apply rate symmetry constraint: %d\n", ret);
138 return ret;
139 }
140 }
141
142 return 0;
143}
144
116/* 145/*
117 * Called by ALSA when a PCM substream is opened, the runtime->hw record is 146 * 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 147 * then initialized and any private data can be allocated. This also calls
@@ -221,6 +250,13 @@ static int soc_pcm_open(struct snd_pcm_substream *substream)
221 goto machine_err; 250 goto machine_err;
222 } 251 }
223 252
253 /* Symmetry only applies if we've already got an active stream. */
254 if (cpu_dai->active || codec_dai->active) {
255 ret = soc_pcm_apply_symmetry(substream);
256 if (ret != 0)
257 goto machine_err;
258 }
259
224 pr_debug("asoc: %s <-> %s info:\n", codec_dai->name, cpu_dai->name); 260 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); 261 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, 262 pr_debug("asoc: min ch %d max ch %d\n", runtime->hw.channels_min,
@@ -263,7 +299,6 @@ static void close_delayed_work(struct work_struct *work)
263{ 299{
264 struct snd_soc_card *card = container_of(work, struct snd_soc_card, 300 struct snd_soc_card *card = container_of(work, struct snd_soc_card,
265 delayed_work.work); 301 delayed_work.work);
266 struct snd_soc_device *socdev = card->socdev;
267 struct snd_soc_codec *codec = card->codec; 302 struct snd_soc_codec *codec = card->codec;
268 struct snd_soc_dai *codec_dai; 303 struct snd_soc_dai *codec_dai;
269 int i; 304 int i;
@@ -279,27 +314,10 @@ static void close_delayed_work(struct work_struct *work)
279 314
280 /* are we waiting on this codec DAI stream */ 315 /* are we waiting on this codec DAI stream */
281 if (codec_dai->pop_wait == 1) { 316 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; 317 codec_dai->pop_wait = 0;
292 snd_soc_dapm_stream_event(codec, 318 snd_soc_dapm_stream_event(codec,
293 codec_dai->playback.stream_name, 319 codec_dai->playback.stream_name,
294 SND_SOC_DAPM_STREAM_STOP); 320 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 } 321 }
304 } 322 }
305 mutex_unlock(&pcm_mutex); 323 mutex_unlock(&pcm_mutex);
@@ -363,10 +381,6 @@ static int soc_codec_close(struct snd_pcm_substream *substream)
363 snd_soc_dapm_stream_event(codec, 381 snd_soc_dapm_stream_event(codec,
364 codec_dai->capture.stream_name, 382 codec_dai->capture.stream_name,
365 SND_SOC_DAPM_STREAM_STOP); 383 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 } 384 }
371 385
372 mutex_unlock(&pcm_mutex); 386 mutex_unlock(&pcm_mutex);
@@ -431,36 +445,16 @@ static int soc_pcm_prepare(struct snd_pcm_substream *substream)
431 cancel_delayed_work(&card->delayed_work); 445 cancel_delayed_work(&card->delayed_work);
432 } 446 }
433 447
434 /* do we need to power up codec */ 448 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
435 if (codec->bias_level != SND_SOC_BIAS_ON) { 449 snd_soc_dapm_stream_event(codec,
436 snd_soc_dapm_set_bias_level(socdev, 450 codec_dai->playback.stream_name,
437 SND_SOC_BIAS_PREPARE); 451 SND_SOC_DAPM_STREAM_START);
438 452 else
439 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) 453 snd_soc_dapm_stream_event(codec,
440 snd_soc_dapm_stream_event(codec, 454 codec_dai->capture.stream_name,
441 codec_dai->playback.stream_name, 455 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 456
462 snd_soc_dai_digital_mute(codec_dai, 0); 457 snd_soc_dai_digital_mute(codec_dai, 0);
463 }
464 458
465out: 459out:
466 mutex_unlock(&pcm_mutex); 460 mutex_unlock(&pcm_mutex);
@@ -521,6 +515,8 @@ static int soc_pcm_hw_params(struct snd_pcm_substream *substream,
521 } 515 }
522 } 516 }
523 517
518 machine->rate = params_rate(params);
519
524out: 520out:
525 mutex_unlock(&pcm_mutex); 521 mutex_unlock(&pcm_mutex);
526 return ret; 522 return ret;
@@ -632,6 +628,12 @@ static int soc_suspend(struct platform_device *pdev, pm_message_t state)
632 struct snd_soc_codec *codec = card->codec; 628 struct snd_soc_codec *codec = card->codec;
633 int i; 629 int i;
634 630
631 /* If the initialization of this soc device failed, there is no codec
632 * associated with it. Just bail out in this case.
633 */
634 if (!codec)
635 return 0;
636
635 /* Due to the resume being scheduled into a workqueue we could 637 /* Due to the resume being scheduled into a workqueue we could
636 * suspend before that's finished - wait for it to complete. 638 * suspend before that's finished - wait for it to complete.
637 */ 639 */
@@ -1334,6 +1336,7 @@ int snd_soc_new_pcms(struct snd_soc_device *socdev, int idx, const char *xid)
1334 return ret; 1336 return ret;
1335 } 1337 }
1336 1338
1339 codec->socdev = socdev;
1337 codec->card->dev = socdev->dev; 1340 codec->card->dev = socdev->dev;
1338 codec->card->private_data = codec; 1341 codec->card->private_data = codec;
1339 strncpy(codec->card->driver, codec->name, sizeof(codec->card->driver)); 1342 strncpy(codec->card->driver, codec->name, sizeof(codec->card->driver));
@@ -1744,7 +1747,7 @@ int snd_soc_info_volsw_ext(struct snd_kcontrol *kcontrol,
1744{ 1747{
1745 int max = kcontrol->private_value; 1748 int max = kcontrol->private_value;
1746 1749
1747 if (max == 1) 1750 if (max == 1 && !strstr(kcontrol->id.name, " Volume"))
1748 uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN; 1751 uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
1749 else 1752 else
1750 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; 1753 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
@@ -1774,7 +1777,7 @@ int snd_soc_info_volsw(struct snd_kcontrol *kcontrol,
1774 unsigned int shift = mc->shift; 1777 unsigned int shift = mc->shift;
1775 unsigned int rshift = mc->rshift; 1778 unsigned int rshift = mc->rshift;
1776 1779
1777 if (max == 1) 1780 if (max == 1 && !strstr(kcontrol->id.name, " Volume"))
1778 uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN; 1781 uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
1779 else 1782 else
1780 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; 1783 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
@@ -1881,7 +1884,7 @@ int snd_soc_info_volsw_2r(struct snd_kcontrol *kcontrol,
1881 (struct soc_mixer_control *)kcontrol->private_value; 1884 (struct soc_mixer_control *)kcontrol->private_value;
1882 int max = mc->max; 1885 int max = mc->max;
1883 1886
1884 if (max == 1) 1887 if (max == 1 && !strstr(kcontrol->id.name, " Volume"))
1885 uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN; 1888 uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
1886 else 1889 else
1887 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; 1890 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
@@ -2065,7 +2068,7 @@ EXPORT_SYMBOL_GPL(snd_soc_put_volsw_s8);
2065int snd_soc_dai_set_sysclk(struct snd_soc_dai *dai, int clk_id, 2068int snd_soc_dai_set_sysclk(struct snd_soc_dai *dai, int clk_id,
2066 unsigned int freq, int dir) 2069 unsigned int freq, int dir)
2067{ 2070{
2068 if (dai->ops->set_sysclk) 2071 if (dai->ops && dai->ops->set_sysclk)
2069 return dai->ops->set_sysclk(dai, clk_id, freq, dir); 2072 return dai->ops->set_sysclk(dai, clk_id, freq, dir);
2070 else 2073 else
2071 return -EINVAL; 2074 return -EINVAL;
@@ -2085,7 +2088,7 @@ EXPORT_SYMBOL_GPL(snd_soc_dai_set_sysclk);
2085int snd_soc_dai_set_clkdiv(struct snd_soc_dai *dai, 2088int snd_soc_dai_set_clkdiv(struct snd_soc_dai *dai,
2086 int div_id, int div) 2089 int div_id, int div)
2087{ 2090{
2088 if (dai->ops->set_clkdiv) 2091 if (dai->ops && dai->ops->set_clkdiv)
2089 return dai->ops->set_clkdiv(dai, div_id, div); 2092 return dai->ops->set_clkdiv(dai, div_id, div);
2090 else 2093 else
2091 return -EINVAL; 2094 return -EINVAL;
@@ -2104,7 +2107,7 @@ EXPORT_SYMBOL_GPL(snd_soc_dai_set_clkdiv);
2104int snd_soc_dai_set_pll(struct snd_soc_dai *dai, 2107int snd_soc_dai_set_pll(struct snd_soc_dai *dai,
2105 int pll_id, unsigned int freq_in, unsigned int freq_out) 2108 int pll_id, unsigned int freq_in, unsigned int freq_out)
2106{ 2109{
2107 if (dai->ops->set_pll) 2110 if (dai->ops && dai->ops->set_pll)
2108 return dai->ops->set_pll(dai, pll_id, freq_in, freq_out); 2111 return dai->ops->set_pll(dai, pll_id, freq_in, freq_out);
2109 else 2112 else
2110 return -EINVAL; 2113 return -EINVAL;
@@ -2120,7 +2123,7 @@ EXPORT_SYMBOL_GPL(snd_soc_dai_set_pll);
2120 */ 2123 */
2121int snd_soc_dai_set_fmt(struct snd_soc_dai *dai, unsigned int fmt) 2124int snd_soc_dai_set_fmt(struct snd_soc_dai *dai, unsigned int fmt)
2122{ 2125{
2123 if (dai->ops->set_fmt) 2126 if (dai->ops && dai->ops->set_fmt)
2124 return dai->ops->set_fmt(dai, fmt); 2127 return dai->ops->set_fmt(dai, fmt);
2125 else 2128 else
2126 return -EINVAL; 2129 return -EINVAL;
@@ -2139,7 +2142,7 @@ EXPORT_SYMBOL_GPL(snd_soc_dai_set_fmt);
2139int snd_soc_dai_set_tdm_slot(struct snd_soc_dai *dai, 2142int snd_soc_dai_set_tdm_slot(struct snd_soc_dai *dai,
2140 unsigned int mask, int slots) 2143 unsigned int mask, int slots)
2141{ 2144{
2142 if (dai->ops->set_sysclk) 2145 if (dai->ops && dai->ops->set_tdm_slot)
2143 return dai->ops->set_tdm_slot(dai, mask, slots); 2146 return dai->ops->set_tdm_slot(dai, mask, slots);
2144 else 2147 else
2145 return -EINVAL; 2148 return -EINVAL;
@@ -2155,7 +2158,7 @@ EXPORT_SYMBOL_GPL(snd_soc_dai_set_tdm_slot);
2155 */ 2158 */
2156int snd_soc_dai_set_tristate(struct snd_soc_dai *dai, int tristate) 2159int snd_soc_dai_set_tristate(struct snd_soc_dai *dai, int tristate)
2157{ 2160{
2158 if (dai->ops->set_sysclk) 2161 if (dai->ops && dai->ops->set_tristate)
2159 return dai->ops->set_tristate(dai, tristate); 2162 return dai->ops->set_tristate(dai, tristate);
2160 else 2163 else
2161 return -EINVAL; 2164 return -EINVAL;
@@ -2171,7 +2174,7 @@ EXPORT_SYMBOL_GPL(snd_soc_dai_set_tristate);
2171 */ 2174 */
2172int snd_soc_dai_digital_mute(struct snd_soc_dai *dai, int mute) 2175int snd_soc_dai_digital_mute(struct snd_soc_dai *dai, int mute)
2173{ 2176{
2174 if (dai->ops->digital_mute) 2177 if (dai->ops && dai->ops->digital_mute)
2175 return dai->ops->digital_mute(dai, mute); 2178 return dai->ops->digital_mute(dai, mute);
2176 else 2179 else
2177 return -EINVAL; 2180 return -EINVAL;
@@ -2352,6 +2355,39 @@ void snd_soc_unregister_platform(struct snd_soc_platform *platform)
2352} 2355}
2353EXPORT_SYMBOL_GPL(snd_soc_unregister_platform); 2356EXPORT_SYMBOL_GPL(snd_soc_unregister_platform);
2354 2357
2358static u64 codec_format_map[] = {
2359 SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S16_BE,
2360 SNDRV_PCM_FMTBIT_U16_LE | SNDRV_PCM_FMTBIT_U16_BE,
2361 SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S24_BE,
2362 SNDRV_PCM_FMTBIT_U24_LE | SNDRV_PCM_FMTBIT_U24_BE,
2363 SNDRV_PCM_FMTBIT_S32_LE | SNDRV_PCM_FMTBIT_S32_BE,
2364 SNDRV_PCM_FMTBIT_U32_LE | SNDRV_PCM_FMTBIT_U32_BE,
2365 SNDRV_PCM_FMTBIT_S24_3LE | SNDRV_PCM_FMTBIT_U24_3BE,
2366 SNDRV_PCM_FMTBIT_U24_3LE | SNDRV_PCM_FMTBIT_U24_3BE,
2367 SNDRV_PCM_FMTBIT_S20_3LE | SNDRV_PCM_FMTBIT_S20_3BE,
2368 SNDRV_PCM_FMTBIT_U20_3LE | SNDRV_PCM_FMTBIT_U20_3BE,
2369 SNDRV_PCM_FMTBIT_S18_3LE | SNDRV_PCM_FMTBIT_S18_3BE,
2370 SNDRV_PCM_FMTBIT_U18_3LE | SNDRV_PCM_FMTBIT_U18_3BE,
2371 SNDRV_PCM_FMTBIT_FLOAT_LE | SNDRV_PCM_FMTBIT_FLOAT_BE,
2372 SNDRV_PCM_FMTBIT_FLOAT64_LE | SNDRV_PCM_FMTBIT_FLOAT64_BE,
2373 SNDRV_PCM_FMTBIT_IEC958_SUBFRAME_LE
2374 | SNDRV_PCM_FMTBIT_IEC958_SUBFRAME_BE,
2375};
2376
2377/* Fix up the DAI formats for endianness: codecs don't actually see
2378 * the endianness of the data but we're using the CPU format
2379 * definitions which do need to include endianness so we ensure that
2380 * codec DAIs always have both big and little endian variants set.
2381 */
2382static void fixup_codec_formats(struct snd_soc_pcm_stream *stream)
2383{
2384 int i;
2385
2386 for (i = 0; i < ARRAY_SIZE(codec_format_map); i++)
2387 if (stream->formats & codec_format_map[i])
2388 stream->formats |= codec_format_map[i];
2389}
2390
2355/** 2391/**
2356 * snd_soc_register_codec - Register a codec with the ASoC core 2392 * snd_soc_register_codec - Register a codec with the ASoC core
2357 * 2393 *
@@ -2359,6 +2395,8 @@ EXPORT_SYMBOL_GPL(snd_soc_unregister_platform);
2359 */ 2395 */
2360int snd_soc_register_codec(struct snd_soc_codec *codec) 2396int snd_soc_register_codec(struct snd_soc_codec *codec)
2361{ 2397{
2398 int i;
2399
2362 if (!codec->name) 2400 if (!codec->name)
2363 return -EINVAL; 2401 return -EINVAL;
2364 2402
@@ -2368,6 +2406,11 @@ int snd_soc_register_codec(struct snd_soc_codec *codec)
2368 2406
2369 INIT_LIST_HEAD(&codec->list); 2407 INIT_LIST_HEAD(&codec->list);
2370 2408
2409 for (i = 0; i < codec->num_dai; i++) {
2410 fixup_codec_formats(&codec->dai[i].playback);
2411 fixup_codec_formats(&codec->dai[i].capture);
2412 }
2413
2371 mutex_lock(&client_mutex); 2414 mutex_lock(&client_mutex);
2372 list_add(&codec->list, &codec_list); 2415 list_add(&codec->list, &codec_list);
2373 snd_soc_instantiate_cards(); 2416 snd_soc_instantiate_cards();
diff --git a/sound/soc/soc-dapm.c b/sound/soc/soc-dapm.c
index 735903a74675..21c69074aa17 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,21 @@
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, snd_soc_dapm_supply, snd_soc_dapm_micbias,
56 snd_soc_dapm_mux, snd_soc_dapm_value_mux, snd_soc_dapm_dac, 56 snd_soc_dapm_mic, snd_soc_dapm_mux, snd_soc_dapm_value_mux,
57 snd_soc_dapm_mixer, snd_soc_dapm_mixer_named_ctl, snd_soc_dapm_pga, 57 snd_soc_dapm_dac, snd_soc_dapm_mixer, snd_soc_dapm_mixer_named_ctl,
58 snd_soc_dapm_adc, snd_soc_dapm_hp, snd_soc_dapm_spk, snd_soc_dapm_post 58 snd_soc_dapm_pga, snd_soc_dapm_adc, snd_soc_dapm_hp, snd_soc_dapm_spk,
59 snd_soc_dapm_post
59}; 60};
60 61
61static int dapm_down_seq[] = { 62static int dapm_down_seq[] = {
62 snd_soc_dapm_pre, snd_soc_dapm_adc, snd_soc_dapm_hp, snd_soc_dapm_spk, 63 snd_soc_dapm_pre, snd_soc_dapm_adc, snd_soc_dapm_hp, snd_soc_dapm_spk,
63 snd_soc_dapm_pga, snd_soc_dapm_mixer_named_ctl, snd_soc_dapm_mixer, 64 snd_soc_dapm_pga, snd_soc_dapm_mixer_named_ctl, snd_soc_dapm_mixer,
64 snd_soc_dapm_dac, snd_soc_dapm_mic, snd_soc_dapm_micbias, 65 snd_soc_dapm_dac, snd_soc_dapm_mic, snd_soc_dapm_micbias,
65 snd_soc_dapm_mux, snd_soc_dapm_value_mux, snd_soc_dapm_post 66 snd_soc_dapm_mux, snd_soc_dapm_value_mux, snd_soc_dapm_supply,
67 snd_soc_dapm_post
66}; 68};
67 69
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) 70static void pop_wait(u32 pop_time)
73{ 71{
74 if (pop_time) 72 if (pop_time)
@@ -96,6 +94,48 @@ static inline struct snd_soc_dapm_widget *dapm_cnew_widget(
96 return kmemdup(_widget, sizeof(*_widget), GFP_KERNEL); 94 return kmemdup(_widget, sizeof(*_widget), GFP_KERNEL);
97} 95}
98 96
97/**
98 * snd_soc_dapm_set_bias_level - set the bias level for the system
99 * @socdev: audio device
100 * @level: level to configure
101 *
102 * Configure the bias (power) levels for the SoC audio device.
103 *
104 * Returns 0 for success else error.
105 */
106static int snd_soc_dapm_set_bias_level(struct snd_soc_device *socdev,
107 enum snd_soc_bias_level level)
108{
109 struct snd_soc_card *card = socdev->card;
110 struct snd_soc_codec *codec = socdev->card->codec;
111 int ret = 0;
112
113 switch (level) {
114 case SND_SOC_BIAS_ON:
115 dev_dbg(socdev->dev, "Setting full bias\n");
116 break;
117 case SND_SOC_BIAS_PREPARE:
118 dev_dbg(socdev->dev, "Setting bias prepare\n");
119 break;
120 case SND_SOC_BIAS_STANDBY:
121 dev_dbg(socdev->dev, "Setting standby bias\n");
122 break;
123 case SND_SOC_BIAS_OFF:
124 dev_dbg(socdev->dev, "Setting bias off\n");
125 break;
126 default:
127 dev_err(socdev->dev, "Setting invalid bias %d\n", level);
128 return -EINVAL;
129 }
130
131 if (card->set_bias_level)
132 ret = card->set_bias_level(card, level);
133 if (ret == 0 && codec->set_bias_level)
134 ret = codec->set_bias_level(codec, level);
135
136 return ret;
137}
138
99/* set up initial codec paths */ 139/* set up initial codec paths */
100static void dapm_set_path_status(struct snd_soc_dapm_widget *w, 140static void dapm_set_path_status(struct snd_soc_dapm_widget *w,
101 struct snd_soc_dapm_path *p, int i) 141 struct snd_soc_dapm_path *p, int i)
@@ -165,6 +205,7 @@ static void dapm_set_path_status(struct snd_soc_dapm_widget *w,
165 case snd_soc_dapm_dac: 205 case snd_soc_dapm_dac:
166 case snd_soc_dapm_micbias: 206 case snd_soc_dapm_micbias:
167 case snd_soc_dapm_vmid: 207 case snd_soc_dapm_vmid:
208 case snd_soc_dapm_supply:
168 p->connect = 1; 209 p->connect = 1;
169 break; 210 break;
170 /* does effect routing - dynamically connected */ 211 /* does effect routing - dynamically connected */
@@ -179,7 +220,7 @@ static void dapm_set_path_status(struct snd_soc_dapm_widget *w,
179 } 220 }
180} 221}
181 222
182/* connect mux widget to it's interconnecting audio paths */ 223/* connect mux widget to its interconnecting audio paths */
183static int dapm_connect_mux(struct snd_soc_codec *codec, 224static int dapm_connect_mux(struct snd_soc_codec *codec,
184 struct snd_soc_dapm_widget *src, struct snd_soc_dapm_widget *dest, 225 struct snd_soc_dapm_widget *src, struct snd_soc_dapm_widget *dest,
185 struct snd_soc_dapm_path *path, const char *control_name, 226 struct snd_soc_dapm_path *path, const char *control_name,
@@ -202,7 +243,7 @@ static int dapm_connect_mux(struct snd_soc_codec *codec,
202 return -ENODEV; 243 return -ENODEV;
203} 244}
204 245
205/* connect mixer widget to it's interconnecting audio paths */ 246/* connect mixer widget to its interconnecting audio paths */
206static int dapm_connect_mixer(struct snd_soc_codec *codec, 247static int dapm_connect_mixer(struct snd_soc_codec *codec,
207 struct snd_soc_dapm_widget *src, struct snd_soc_dapm_widget *dest, 248 struct snd_soc_dapm_widget *src, struct snd_soc_dapm_widget *dest,
208 struct snd_soc_dapm_path *path, const char *control_name) 249 struct snd_soc_dapm_path *path, const char *control_name)
@@ -357,8 +398,9 @@ static int dapm_new_mixer(struct snd_soc_codec *codec,
357 path->long_name); 398 path->long_name);
358 ret = snd_ctl_add(codec->card, path->kcontrol); 399 ret = snd_ctl_add(codec->card, path->kcontrol);
359 if (ret < 0) { 400 if (ret < 0) {
360 printk(KERN_ERR "asoc: failed to add dapm kcontrol %s\n", 401 printk(KERN_ERR "asoc: failed to add dapm kcontrol %s: %d\n",
361 path->long_name); 402 path->long_name,
403 ret);
362 kfree(path->long_name); 404 kfree(path->long_name);
363 path->long_name = NULL; 405 path->long_name = NULL;
364 return ret; 406 return ret;
@@ -434,6 +476,9 @@ static int is_connected_output_ep(struct snd_soc_dapm_widget *widget)
434 struct snd_soc_dapm_path *path; 476 struct snd_soc_dapm_path *path;
435 int con = 0; 477 int con = 0;
436 478
479 if (widget->id == snd_soc_dapm_supply)
480 return 0;
481
437 if (widget->id == snd_soc_dapm_adc && widget->active) 482 if (widget->id == snd_soc_dapm_adc && widget->active)
438 return 1; 483 return 1;
439 484
@@ -470,6 +515,9 @@ static int is_connected_input_ep(struct snd_soc_dapm_widget *widget)
470 struct snd_soc_dapm_path *path; 515 struct snd_soc_dapm_path *path;
471 int con = 0; 516 int con = 0;
472 517
518 if (widget->id == snd_soc_dapm_supply)
519 return 0;
520
473 /* active stream ? */ 521 /* active stream ? */
474 if (widget->id == snd_soc_dapm_dac && widget->active) 522 if (widget->id == snd_soc_dapm_dac && widget->active)
475 return 1; 523 return 1;
@@ -521,84 +569,12 @@ int dapm_reg_event(struct snd_soc_dapm_widget *w,
521} 569}
522EXPORT_SYMBOL_GPL(dapm_reg_event); 570EXPORT_SYMBOL_GPL(dapm_reg_event);
523 571
524/* 572/* 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 573 * widgets.
526 * power status appropriately.
527 */ 574 */
528static int dapm_power_widget(struct snd_soc_codec *codec, int event, 575static int dapm_generic_apply_power(struct snd_soc_dapm_widget *w)
529 struct snd_soc_dapm_widget *w)
530{ 576{
531 int in, out, power_change, power, ret; 577 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 578
603 /* call any power change event handlers */ 579 /* call any power change event handlers */
604 if (w->event) 580 if (w->event)
@@ -607,7 +583,7 @@ static int dapm_power_widget(struct snd_soc_codec *codec, int event,
607 w->name, w->event_flags); 583 w->name, w->event_flags);
608 584
609 /* power up pre event */ 585 /* power up pre event */
610 if (power && w->event && 586 if (w->power && w->event &&
611 (w->event_flags & SND_SOC_DAPM_PRE_PMU)) { 587 (w->event_flags & SND_SOC_DAPM_PRE_PMU)) {
612 ret = w->event(w, NULL, SND_SOC_DAPM_PRE_PMU); 588 ret = w->event(w, NULL, SND_SOC_DAPM_PRE_PMU);
613 if (ret < 0) 589 if (ret < 0)
@@ -615,7 +591,7 @@ static int dapm_power_widget(struct snd_soc_codec *codec, int event,
615 } 591 }
616 592
617 /* power down pre event */ 593 /* power down pre event */
618 if (!power && w->event && 594 if (!w->power && w->event &&
619 (w->event_flags & SND_SOC_DAPM_PRE_PMD)) { 595 (w->event_flags & SND_SOC_DAPM_PRE_PMD)) {
620 ret = w->event(w, NULL, SND_SOC_DAPM_PRE_PMD); 596 ret = w->event(w, NULL, SND_SOC_DAPM_PRE_PMD);
621 if (ret < 0) 597 if (ret < 0)
@@ -623,17 +599,17 @@ static int dapm_power_widget(struct snd_soc_codec *codec, int event,
623 } 599 }
624 600
625 /* Lower PGA volume to reduce pops */ 601 /* Lower PGA volume to reduce pops */
626 if (w->id == snd_soc_dapm_pga && !power) 602 if (w->id == snd_soc_dapm_pga && !w->power)
627 dapm_set_pga(w, power); 603 dapm_set_pga(w, w->power);
628 604
629 dapm_update_bits(w); 605 dapm_update_bits(w);
630 606
631 /* Raise PGA volume to reduce pops */ 607 /* Raise PGA volume to reduce pops */
632 if (w->id == snd_soc_dapm_pga && power) 608 if (w->id == snd_soc_dapm_pga && w->power)
633 dapm_set_pga(w, power); 609 dapm_set_pga(w, w->power);
634 610
635 /* power up post event */ 611 /* power up post event */
636 if (power && w->event && 612 if (w->power && w->event &&
637 (w->event_flags & SND_SOC_DAPM_POST_PMU)) { 613 (w->event_flags & SND_SOC_DAPM_POST_PMU)) {
638 ret = w->event(w, 614 ret = w->event(w,
639 NULL, SND_SOC_DAPM_POST_PMU); 615 NULL, SND_SOC_DAPM_POST_PMU);
@@ -642,7 +618,7 @@ static int dapm_power_widget(struct snd_soc_codec *codec, int event,
642 } 618 }
643 619
644 /* power down post event */ 620 /* power down post event */
645 if (!power && w->event && 621 if (!w->power && w->event &&
646 (w->event_flags & SND_SOC_DAPM_POST_PMD)) { 622 (w->event_flags & SND_SOC_DAPM_POST_PMD)) {
647 ret = w->event(w, NULL, SND_SOC_DAPM_POST_PMD); 623 ret = w->event(w, NULL, SND_SOC_DAPM_POST_PMD);
648 if (ret < 0) 624 if (ret < 0)
@@ -652,6 +628,116 @@ static int dapm_power_widget(struct snd_soc_codec *codec, int event,
652 return 0; 628 return 0;
653} 629}
654 630
631/* Generic check to see if a widget should be powered.
632 */
633static int dapm_generic_check_power(struct snd_soc_dapm_widget *w)
634{
635 int in, out;
636
637 in = is_connected_input_ep(w);
638 dapm_clear_walk(w->codec);
639 out = is_connected_output_ep(w);
640 dapm_clear_walk(w->codec);
641 return out != 0 && in != 0;
642}
643
644/* Check to see if an ADC has power */
645static int dapm_adc_check_power(struct snd_soc_dapm_widget *w)
646{
647 int in;
648
649 if (w->active) {
650 in = is_connected_input_ep(w);
651 dapm_clear_walk(w->codec);
652 return in != 0;
653 } else {
654 return dapm_generic_check_power(w);
655 }
656}
657
658/* Check to see if a DAC has power */
659static int dapm_dac_check_power(struct snd_soc_dapm_widget *w)
660{
661 int out;
662
663 if (w->active) {
664 out = is_connected_output_ep(w);
665 dapm_clear_walk(w->codec);
666 return out != 0;
667 } else {
668 return dapm_generic_check_power(w);
669 }
670}
671
672/* Check to see if a power supply is needed */
673static int dapm_supply_check_power(struct snd_soc_dapm_widget *w)
674{
675 struct snd_soc_dapm_path *path;
676 int power = 0;
677
678 /* Check if one of our outputs is connected */
679 list_for_each_entry(path, &w->sinks, list_source) {
680 if (path->sink && path->sink->power_check &&
681 path->sink->power_check(path->sink)) {
682 power = 1;
683 break;
684 }
685 }
686
687 dapm_clear_walk(w->codec);
688
689 return power;
690}
691
692/*
693 * Scan a single DAPM widget for a complete audio path and update the
694 * power status appropriately.
695 */
696static int dapm_power_widget(struct snd_soc_codec *codec, int event,
697 struct snd_soc_dapm_widget *w)
698{
699 int ret;
700
701 switch (w->id) {
702 case snd_soc_dapm_pre:
703 if (!w->event)
704 return 0;
705
706 if (event == SND_SOC_DAPM_STREAM_START) {
707 ret = w->event(w,
708 NULL, SND_SOC_DAPM_PRE_PMU);
709 if (ret < 0)
710 return ret;
711 } else if (event == SND_SOC_DAPM_STREAM_STOP) {
712 ret = w->event(w,
713 NULL, SND_SOC_DAPM_PRE_PMD);
714 if (ret < 0)
715 return ret;
716 }
717 return 0;
718
719 case snd_soc_dapm_post:
720 if (!w->event)
721 return 0;
722
723 if (event == SND_SOC_DAPM_STREAM_START) {
724 ret = w->event(w,
725 NULL, SND_SOC_DAPM_POST_PMU);
726 if (ret < 0)
727 return ret;
728 } else if (event == SND_SOC_DAPM_STREAM_STOP) {
729 ret = w->event(w,
730 NULL, SND_SOC_DAPM_POST_PMD);
731 if (ret < 0)
732 return ret;
733 }
734 return 0;
735
736 default:
737 return dapm_generic_apply_power(w);
738 }
739}
740
655/* 741/*
656 * Scan each dapm widget for complete audio path. 742 * Scan each dapm widget for complete audio path.
657 * A complete path is a route that has valid endpoints i.e.:- 743 * A complete path is a route that has valid endpoints i.e.:-
@@ -663,31 +749,102 @@ static int dapm_power_widget(struct snd_soc_codec *codec, int event,
663 */ 749 */
664static int dapm_power_widgets(struct snd_soc_codec *codec, int event) 750static int dapm_power_widgets(struct snd_soc_codec *codec, int event)
665{ 751{
752 struct snd_soc_device *socdev = codec->socdev;
666 struct snd_soc_dapm_widget *w; 753 struct snd_soc_dapm_widget *w;
667 int i, c = 1, *seq = NULL, ret = 0; 754 int ret = 0;
668 755 int i, power;
669 /* do we have a sequenced stream event */ 756 int sys_power = 0;
670 if (event == SND_SOC_DAPM_STREAM_START) { 757
671 c = ARRAY_SIZE(dapm_up_seq); 758 INIT_LIST_HEAD(&codec->up_list);
672 seq = dapm_up_seq; 759 INIT_LIST_HEAD(&codec->down_list);
673 } else if (event == SND_SOC_DAPM_STREAM_STOP) { 760
674 c = ARRAY_SIZE(dapm_down_seq); 761 /* Check which widgets we need to power and store them in
675 seq = dapm_down_seq; 762 * lists indicating if they should be powered up or down.
763 */
764 list_for_each_entry(w, &codec->dapm_widgets, list) {
765 switch (w->id) {
766 case snd_soc_dapm_pre:
767 list_add_tail(&codec->down_list, &w->power_list);
768 break;
769 case snd_soc_dapm_post:
770 list_add_tail(&codec->up_list, &w->power_list);
771 break;
772
773 default:
774 if (!w->power_check)
775 continue;
776
777 power = w->power_check(w);
778 if (power)
779 sys_power = 1;
780
781 if (w->power == power)
782 continue;
783
784 if (power)
785 list_add_tail(&w->power_list, &codec->up_list);
786 else
787 list_add_tail(&w->power_list,
788 &codec->down_list);
789
790 w->power = power;
791 break;
792 }
676 } 793 }
677 794
678 for (i = 0; i < c; i++) { 795 /* If we're changing to all on or all off then prepare */
679 list_for_each_entry(w, &codec->dapm_widgets, list) { 796 if ((sys_power && codec->bias_level == SND_SOC_BIAS_STANDBY) ||
797 (!sys_power && codec->bias_level == SND_SOC_BIAS_ON)) {
798 ret = snd_soc_dapm_set_bias_level(socdev,
799 SND_SOC_BIAS_PREPARE);
800 if (ret != 0)
801 pr_err("Failed to prepare bias: %d\n", ret);
802 }
680 803
804 /* Power down widgets first; try to avoid amplifying pops. */
805 for (i = 0; i < ARRAY_SIZE(dapm_down_seq); i++) {
806 list_for_each_entry(w, &codec->down_list, power_list) {
681 /* is widget in stream order */ 807 /* is widget in stream order */
682 if (seq && seq[i] && w->id != seq[i]) 808 if (w->id != dapm_down_seq[i])
683 continue; 809 continue;
684 810
685 ret = dapm_power_widget(codec, event, w); 811 ret = dapm_power_widget(codec, event, w);
686 if (ret != 0) 812 if (ret != 0)
687 return ret; 813 pr_err("Failed to power down %s: %d\n",
814 w->name, ret);
688 } 815 }
689 } 816 }
690 817
818 /* Now power up. */
819 for (i = 0; i < ARRAY_SIZE(dapm_up_seq); i++) {
820 list_for_each_entry(w, &codec->up_list, power_list) {
821 /* is widget in stream order */
822 if (w->id != dapm_up_seq[i])
823 continue;
824
825 ret = dapm_power_widget(codec, event, w);
826 if (ret != 0)
827 pr_err("Failed to power up %s: %d\n",
828 w->name, ret);
829 }
830 }
831
832 /* If we just powered the last thing off drop to standby bias */
833 if (codec->bias_level == SND_SOC_BIAS_PREPARE && !sys_power) {
834 ret = snd_soc_dapm_set_bias_level(socdev,
835 SND_SOC_BIAS_STANDBY);
836 if (ret != 0)
837 pr_err("Failed to apply standby bias: %d\n", ret);
838 }
839
840 /* If we just powered up then move to active bias */
841 if (codec->bias_level == SND_SOC_BIAS_PREPARE && sys_power) {
842 ret = snd_soc_dapm_set_bias_level(socdev,
843 SND_SOC_BIAS_ON);
844 if (ret != 0)
845 pr_err("Failed to apply active bias: %d\n", ret);
846 }
847
691 return 0; 848 return 0;
692} 849}
693 850
@@ -723,6 +880,7 @@ static void dbg_dump_dapm(struct snd_soc_codec* codec, const char *action)
723 case snd_soc_dapm_pga: 880 case snd_soc_dapm_pga:
724 case snd_soc_dapm_mixer: 881 case snd_soc_dapm_mixer:
725 case snd_soc_dapm_mixer_named_ctl: 882 case snd_soc_dapm_mixer_named_ctl:
883 case snd_soc_dapm_supply:
726 if (w->name) { 884 if (w->name) {
727 in = is_connected_input_ep(w); 885 in = is_connected_input_ep(w);
728 dapm_clear_walk(w->codec); 886 dapm_clear_walk(w->codec);
@@ -851,6 +1009,7 @@ static ssize_t dapm_widget_show(struct device *dev,
851 case snd_soc_dapm_pga: 1009 case snd_soc_dapm_pga:
852 case snd_soc_dapm_mixer: 1010 case snd_soc_dapm_mixer:
853 case snd_soc_dapm_mixer_named_ctl: 1011 case snd_soc_dapm_mixer_named_ctl:
1012 case snd_soc_dapm_supply:
854 if (w->name) 1013 if (w->name)
855 count += sprintf(buf + count, "%s: %s\n", 1014 count += sprintf(buf + count, "%s: %s\n",
856 w->name, w->power ? "On":"Off"); 1015 w->name, w->power ? "On":"Off");
@@ -883,16 +1042,12 @@ static DEVICE_ATTR(dapm_widget, 0444, dapm_widget_show, NULL);
883 1042
884int snd_soc_dapm_sys_add(struct device *dev) 1043int snd_soc_dapm_sys_add(struct device *dev)
885{ 1044{
886 if (!dapm_status)
887 return 0;
888 return device_create_file(dev, &dev_attr_dapm_widget); 1045 return device_create_file(dev, &dev_attr_dapm_widget);
889} 1046}
890 1047
891static void snd_soc_dapm_sys_remove(struct device *dev) 1048static void snd_soc_dapm_sys_remove(struct device *dev)
892{ 1049{
893 if (dapm_status) { 1050 device_remove_file(dev, &dev_attr_dapm_widget);
894 device_remove_file(dev, &dev_attr_dapm_widget);
895 }
896} 1051}
897 1052
898/* free all dapm widgets and resources */ 1053/* free all dapm widgets and resources */
@@ -1015,6 +1170,7 @@ static int snd_soc_dapm_add_route(struct snd_soc_codec *codec,
1015 case snd_soc_dapm_vmid: 1170 case snd_soc_dapm_vmid:
1016 case snd_soc_dapm_pre: 1171 case snd_soc_dapm_pre:
1017 case snd_soc_dapm_post: 1172 case snd_soc_dapm_post:
1173 case snd_soc_dapm_supply:
1018 list_add(&path->list, &codec->dapm_paths); 1174 list_add(&path->list, &codec->dapm_paths);
1019 list_add(&path->list_sink, &wsink->sources); 1175 list_add(&path->list_sink, &wsink->sources);
1020 list_add(&path->list_source, &wsource->sinks); 1176 list_add(&path->list_source, &wsource->sinks);
@@ -1108,15 +1264,22 @@ int snd_soc_dapm_new_widgets(struct snd_soc_codec *codec)
1108 case snd_soc_dapm_switch: 1264 case snd_soc_dapm_switch:
1109 case snd_soc_dapm_mixer: 1265 case snd_soc_dapm_mixer:
1110 case snd_soc_dapm_mixer_named_ctl: 1266 case snd_soc_dapm_mixer_named_ctl:
1267 w->power_check = dapm_generic_check_power;
1111 dapm_new_mixer(codec, w); 1268 dapm_new_mixer(codec, w);
1112 break; 1269 break;
1113 case snd_soc_dapm_mux: 1270 case snd_soc_dapm_mux:
1114 case snd_soc_dapm_value_mux: 1271 case snd_soc_dapm_value_mux:
1272 w->power_check = dapm_generic_check_power;
1115 dapm_new_mux(codec, w); 1273 dapm_new_mux(codec, w);
1116 break; 1274 break;
1117 case snd_soc_dapm_adc: 1275 case snd_soc_dapm_adc:
1276 w->power_check = dapm_adc_check_power;
1277 break;
1118 case snd_soc_dapm_dac: 1278 case snd_soc_dapm_dac:
1279 w->power_check = dapm_dac_check_power;
1280 break;
1119 case snd_soc_dapm_pga: 1281 case snd_soc_dapm_pga:
1282 w->power_check = dapm_generic_check_power;
1120 dapm_new_pga(codec, w); 1283 dapm_new_pga(codec, w);
1121 break; 1284 break;
1122 case snd_soc_dapm_input: 1285 case snd_soc_dapm_input:
@@ -1126,6 +1289,10 @@ int snd_soc_dapm_new_widgets(struct snd_soc_codec *codec)
1126 case snd_soc_dapm_hp: 1289 case snd_soc_dapm_hp:
1127 case snd_soc_dapm_mic: 1290 case snd_soc_dapm_mic:
1128 case snd_soc_dapm_line: 1291 case snd_soc_dapm_line:
1292 w->power_check = dapm_generic_check_power;
1293 break;
1294 case snd_soc_dapm_supply:
1295 w->power_check = dapm_supply_check_power;
1129 case snd_soc_dapm_vmid: 1296 case snd_soc_dapm_vmid:
1130 case snd_soc_dapm_pre: 1297 case snd_soc_dapm_pre:
1131 case snd_soc_dapm_post: 1298 case snd_soc_dapm_post:
@@ -1626,35 +1793,11 @@ int snd_soc_dapm_stream_event(struct snd_soc_codec *codec,
1626EXPORT_SYMBOL_GPL(snd_soc_dapm_stream_event); 1793EXPORT_SYMBOL_GPL(snd_soc_dapm_stream_event);
1627 1794
1628/** 1795/**
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. 1796 * snd_soc_dapm_enable_pin - enable pin.
1654 * @codec: SoC codec 1797 * @codec: SoC codec
1655 * @pin: pin name 1798 * @pin: pin name
1656 * 1799 *
1657 * Enables input/output pin and it's parents or children widgets iff there is 1800 * Enables input/output pin and its parents or children widgets iff there is
1658 * a valid audio route and active audio stream. 1801 * a valid audio route and active audio stream.
1659 * NOTE: snd_soc_dapm_sync() needs to be called after this for DAPM to 1802 * NOTE: snd_soc_dapm_sync() needs to be called after this for DAPM to
1660 * do any widget power switching. 1803 * do any widget power switching.
@@ -1670,7 +1813,7 @@ EXPORT_SYMBOL_GPL(snd_soc_dapm_enable_pin);
1670 * @codec: SoC codec 1813 * @codec: SoC codec
1671 * @pin: pin name 1814 * @pin: pin name
1672 * 1815 *
1673 * Disables input/output pin and it's parents or children widgets. 1816 * 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 1817 * NOTE: snd_soc_dapm_sync() needs to be called after this for DAPM to
1675 * do any widget power switching. 1818 * do any widget power switching.
1676 */ 1819 */
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..fa336616152e
--- /dev/null
+++ b/sound/soc/txx9/txx9aclc.c
@@ -0,0 +1,430 @@
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[BUS_ID_SIZE + 2];
301
302 sprintf(devname, "%s.%d", dmadata->dma_res->name,
303 (int)dmadata->dma_res->start);
304 if (strcmp(dev_name(chan->device->dev), devname) == 0) {
305 chan->private = &dmadata->dma_slave;
306 return true;
307 }
308 return false;
309}
310
311static int txx9aclc_dma_init(struct txx9aclc_soc_device *dev,
312 struct txx9aclc_dmadata *dmadata)
313{
314 struct txx9aclc_plat_drvdata *drvdata = txx9aclc_get_plat_drvdata(dev);
315 struct txx9dmac_slave *ds = &dmadata->dma_slave;
316 dma_cap_mask_t mask;
317
318 spin_lock_init(&dmadata->dma_lock);
319
320 ds->reg_width = sizeof(u32);
321 if (dmadata->stream == SNDRV_PCM_STREAM_PLAYBACK) {
322 ds->tx_reg = drvdata->physbase + ACAUDODAT;
323 ds->rx_reg = 0;
324 } else {
325 ds->tx_reg = 0;
326 ds->rx_reg = drvdata->physbase + ACAUDIDAT;
327 }
328
329 /* Try to grab a DMA channel */
330 dma_cap_zero(mask);
331 dma_cap_set(DMA_SLAVE, mask);
332 dmadata->dma_chan = dma_request_channel(mask, filter, dmadata);
333 if (!dmadata->dma_chan) {
334 dev_err(dev->soc_dev.dev,
335 "DMA channel for %s is not available\n",
336 dmadata->stream == SNDRV_PCM_STREAM_PLAYBACK ?
337 "playback" : "capture");
338 return -EBUSY;
339 }
340 tasklet_init(&dmadata->tasklet, txx9aclc_dma_tasklet,
341 (unsigned long)dmadata);
342 return 0;
343}
344
345static int txx9aclc_pcm_probe(struct platform_device *pdev)
346{
347 struct snd_soc_device *socdev = platform_get_drvdata(pdev);
348 struct txx9aclc_soc_device *dev =
349 container_of(socdev, struct txx9aclc_soc_device, soc_dev);
350 struct resource *r;
351 int i;
352 int ret;
353
354 dev->dmadata[0].stream = SNDRV_PCM_STREAM_PLAYBACK;
355 dev->dmadata[1].stream = SNDRV_PCM_STREAM_CAPTURE;
356 for (i = 0; i < 2; i++) {
357 r = platform_get_resource(dev->aclc_pdev, IORESOURCE_DMA, i);
358 if (!r) {
359 ret = -EBUSY;
360 goto exit;
361 }
362 dev->dmadata[i].dma_res = r;
363 ret = txx9aclc_dma_init(dev, &dev->dmadata[i]);
364 if (ret)
365 goto exit;
366 }
367 return 0;
368
369exit:
370 for (i = 0; i < 2; i++) {
371 if (dev->dmadata[i].dma_chan)
372 dma_release_channel(dev->dmadata[i].dma_chan);
373 dev->dmadata[i].dma_chan = NULL;
374 }
375 return ret;
376}
377
378static int txx9aclc_pcm_remove(struct platform_device *pdev)
379{
380 struct snd_soc_device *socdev = platform_get_drvdata(pdev);
381 struct txx9aclc_soc_device *dev =
382 container_of(socdev, struct txx9aclc_soc_device, soc_dev);
383 struct txx9aclc_plat_drvdata *drvdata = txx9aclc_get_plat_drvdata(dev);
384 void __iomem *base = drvdata->base;
385 int i;
386
387 /* disable all FIFO DMAs */
388 __raw_writel(ACCTL_AUDODMA | ACCTL_AUDIDMA, base + ACCTLDIS);
389 /* dummy R/W to clear pending DMAREQ if any */
390 __raw_writel(__raw_readl(base + ACAUDIDAT), base + ACAUDODAT);
391
392 for (i = 0; i < 2; i++) {
393 struct txx9aclc_dmadata *dmadata = &dev->dmadata[i];
394 struct dma_chan *chan = dmadata->dma_chan;
395 if (chan) {
396 dmadata->frag_count = -1;
397 chan->device->device_terminate_all(chan);
398 dma_release_channel(chan);
399 }
400 dev->dmadata[i].dma_chan = NULL;
401 }
402 return 0;
403}
404
405struct snd_soc_platform txx9aclc_soc_platform = {
406 .name = "txx9aclc-audio",
407 .probe = txx9aclc_pcm_probe,
408 .remove = txx9aclc_pcm_remove,
409 .pcm_ops = &txx9aclc_pcm_ops,
410 .pcm_new = txx9aclc_pcm_new,
411 .pcm_free = txx9aclc_pcm_free_dma_buffers,
412};
413EXPORT_SYMBOL_GPL(txx9aclc_soc_platform);
414
415static int __init txx9aclc_soc_platform_init(void)
416{
417 return snd_soc_register_platform(&txx9aclc_soc_platform);
418}
419
420static void __exit txx9aclc_soc_platform_exit(void)
421{
422 snd_soc_unregister_platform(&txx9aclc_soc_platform);
423}
424
425module_init(txx9aclc_soc_platform_init);
426module_exit(txx9aclc_soc_platform_exit);
427
428MODULE_AUTHOR("Atsushi Nemoto <anemo@mba.ocn.ne.jp>");
429MODULE_DESCRIPTION("TXx9 ACLC Audio DMA driver");
430MODULE_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 */